unit Api.ServiceImpl;

interface

uses
  XData.Server.Module,
  XData.Service.Common,
  System.Variants,
  System.DateUtils,
  Api.Service,
  Api.Database,
  Common.Logging,
  System.SysUtils;

type
  [ServiceImplementation]
  TApiService = class(TInterfacedObject, IApiService)
  strict private
    apiDB: TApiDatabase;
  private
    procedure EnsureBlankWebTaskRow(const taskId: string);
    function SaveTaskRow(const Item: TTaskRowSave): Boolean;
  public
    procedure AfterConstruction; override;
    procedure BeforeDestruction; override;
    function GetTaskItems(taskId: string): TTasksList;
  end;

implementation

procedure TApiService.AfterConstruction;
begin
  inherited;
  apiDB := TApiDatabase.Create(nil);
  Logger.Log(4, 'ApiService.AfterConstruction - apiDB created');
end;

procedure TApiService.BeforeDestruction;
begin
  Logger.Log(4, 'ApiService.BeforeDestruction - freeing apiDB');
  apiDB.Free;
  inherited;
end;

function TApiService.GetTaskItems(taskId: string): TTasksList;
var
  task: TTask;
  item: TTaskItem;
begin
  Logger.Log(4, Format('ApiService.GetTaskItems - TASK_ID="%s"', [taskId]));

  Result := TTasksList.Create;
  TXDataOperationContext.Current.Handler.ManagedObjects.Add(Result);

  try
    apiDB.uqTaskItems.Close;
    apiDB.uqTaskItems.ParamByName('TASK_ID').AsString := taskId;
    apiDB.uqTaskItems.Open;

    if apiDB.uqTaskItems.IsEmpty then
    begin
      Logger.Log(4, Format('ApiService.GetTaskItems - no rows for TASK_ID="%s", ensuring blank row', [taskId]));
      EnsureBlankWebTaskRow(taskId);

      apiDB.uqTaskItems.Close;
      apiDB.uqTaskItems.ParamByName('TASK_ID').AsString := taskId;
      apiDB.uqTaskItems.Open;
    end;

    if apiDB.uqTaskItems.IsEmpty then
    begin
      Logger.Log(2, Format('ApiService.GetTaskItems - still no rows after ensure blank for TASK_ID="%s"', [taskId]));
      Result.count := 0;
      Exit;
    end;

    task := TTask.Create;
    TXDataOperationContext.Current.Handler.ManagedObjects.Add(task);

    task.taskId := taskId;

    Result.data.Add(task);

    while not apiDB.uqTaskItems.Eof do
    begin
      item := TTaskItem.Create;
      TXDataOperationContext.Current.Handler.ManagedObjects.Add(item);

      item.taskItemId := apiDB.uqTaskItemsTASK_ITEM_ID.AsString;
      item.taskId := apiDB.uqTaskItemsTASK_ID.AsString;
      item.itemNum := apiDB.uqTaskItemsITEM_NUM.AsInteger;

      item.application := apiDB.uqTaskItemsAPPLICATION.AsString;
      item.version := apiDB.uqTaskItemsAPP_VERSION.AsString;

      if apiDB.uqTaskItemsTASK_DATE.IsNull then
        item.taskDate := 0
      else
        item.taskDate := apiDB.uqTaskItemsTASK_DATE.AsDateTime;

      item.reportedBy := apiDB.uqTaskItemsREPORTED_BY.AsString;
      item.assignedTo := apiDB.uqTaskItemsASSIGNED_TO.AsString;

      item.status := apiDB.uqTaskItemsSTATUS.AsString;

      if apiDB.uqTaskItemsSTATUS_DATE.IsNull then
        item.statusDate := Null
      else
        item.statusDate := apiDB.uqTaskItemsSTATUS_DATE.AsDateTime;

      item.fixedVersion := apiDB.uqTaskItemsFIXED_VERSION.AsString;
      item.formSection := apiDB.uqTaskItemsFORM_SECTION.AsString;
      item.issue := apiDB.uqTaskItemsISSUE.AsString;
      item.notes := apiDB.uqTaskItemsNOTES.AsString;

      task.items.Add(item);

      apiDB.uqTaskItems.Next;
    end;

    Result.count := Result.data.Count;
    Logger.Log(4, Format('ApiService.GetTaskItems - returned %d task(s)', [Result.count]));
  except
    on E: Exception do
    begin
      Logger.Log(2, 'ApiService.GetTaskItems - ERROR: ' + E.Message);
      raise;
    end;
  end;
end;

procedure TApiService.EnsureBlankWebTaskRow(const taskId: string);
begin
  Logger.Log(4, Format('ApiService.EnsureBlankWebTaskRow - TASK_ID="%s"', [taskId]));
  try
    apiDB.uqEnsureBlankRow.Close;
    apiDB.uqEnsureBlankRow.ParamByName('TASK_ID').AsString := taskId;
    apiDB.uqEnsureBlankRow.ExecSQL;
  except
    on E: Exception do
    begin
      Logger.Log(2, 'ApiService.EnsureBlankWebTaskRow - ERROR: ' + E.Message);
      raise;
    end;
  end;
end;

function TApiService.SaveTaskRow(const Item: TTaskRowSave): Boolean;

  function ParseDateOrZero(const S: string; out D: TDateTime): Boolean;
  begin
    Result := Trim(S) <> '';
    if Result then
      D := ISO8601ToDate(S, False);
  end;

var
  d: TDateTime;
begin
  Logger.Log(4, Format('ApiService.SaveTaskRow - TASK_ITEM_ID="%s"', [Item.taskItemId]));

  try
    apiDB.uqSaveTaskRow.Close;

    apiDB.uqSaveTaskRow.ParamByName('TASK_ITEM_ID').AsString := Item.taskItemId;

    apiDB.uqSaveTaskRow.ParamByName('APPLICATION').AsString := Item.application;
    apiDB.uqSaveTaskRow.ParamByName('APP_VERSION').AsString := Item.version;

    if ParseDateOrZero(Item.taskDate, d) then
      apiDB.uqSaveTaskRow.ParamByName('TASK_DATE').AsDateTime := d
    else
      apiDB.uqSaveTaskRow.ParamByName('TASK_DATE').Clear;

    apiDB.uqSaveTaskRow.ParamByName('REPORTED_BY').AsString := Item.reportedBy;
    apiDB.uqSaveTaskRow.ParamByName('ASSIGNED_TO').AsString := Item.assignedTo;

    apiDB.uqSaveTaskRow.ParamByName('STATUS').AsString := Item.status;

    if ParseDateOrZero(Item.statusDate, d) then
      apiDB.uqSaveTaskRow.ParamByName('STATUS_DATE').AsDateTime := d
    else
      apiDB.uqSaveTaskRow.ParamByName('STATUS_DATE').AsDateTime := Date;

    apiDB.uqSaveTaskRow.ParamByName('FIXED_VERSION').AsString := Item.fixedVersion;
    apiDB.uqSaveTaskRow.ParamByName('FORM_SECTION').AsString := Item.formSection;
    apiDB.uqSaveTaskRow.ParamByName('ISSUE').AsString := Item.issue;
    apiDB.uqSaveTaskRow.ParamByName('NOTES').AsString := Item.notes;

    apiDB.uqSaveTaskRow.ExecSQL;

    Result := True;
    Logger.Log(4, 'ApiService.SaveTaskRow - OK');
  except
    on E: Exception do
    begin
      Logger.Log(2, 'ApiService.SaveTaskRow - ERROR: ' + E.Message);
      raise;
    end;
  end;
end;

initialization
  RegisterServiceType(TypeInfo(IApiService));
  RegisterServiceType(TApiService);

end.

