unit rOrders;

interface

uses
  System.SysUtils, System.Classes, frxClass, frxExportBaseDialog, frxExportPDF,
  Data.DB, DBAccess, Uni, UniProvider, MySQLUniProvider, System.IniFiles, Vcl.Forms,
  MemDS, frxDBSet, frxTableObject, frCoreClasses, Common.Logging, System.IOUtils, JSON;

type
  TrptOrders = class(TDataModule)
    frxOrders: TfrxReport;
    frxPDFExport1: TfrxPDFExport;
    ucKG: TUniConnection;
    uqOrders: TUniQuery;
    frxDBOrders: TfrxDBDataset;
    uqOrdersORDER_ID: TLongWordField;
    uqOrdersLoc: TStringField;
    uqOrdersCOMPANY_NAME: TStringField;
    uqOrdersJOB_NAME: TStringField;
    uqOrdersORDER_DATE: TDateTimeField;
    uqOrdersORDER_TYPE: TStringField;
    uqOrdersPROOF_DUE: TDateField;
    uqOrdersPROOF_DONE: TDateTimeField;
    uqOrdersART_DUE: TDateField;
    uqOrdersART_DONE: TDateTimeField;
    uqOrdersPLATE_DUE: TDateField;
    uqOrdersPLATE_DONE: TDateTimeField;
    uqOrdersMOUNT_DUE: TDateField;
    uqOrdersMOUNT_DONE: TDateTimeField;
    uqOrdersSHIP_DUE: TDateField;
    uqOrdersSHIP_DONE: TDateTimeField;
    uqOrdersPRICE: TFloatField;
    uqOrdersQB_REF_NUM: TStringField;
    uqOrdersCOLORS: TStringField;
    uqColors: TUniQuery;
    procedure DataModuleCreate(Sender: TObject);
    procedure uqOrdersCalcFields(DataSet: TDataSet);

  private
    function BuildOrderQuery(searchOptions: string): string;
    function generateSubQuery(filterType, statusType,
      currStatus: string): string;
    function getColorCount(colors: string): string;

  public
    procedure PrepareReport(searchOptions: string);
    procedure GeneratePDF;
  end;

var
  rptOrders: TrptOrders;

implementation

uses
  uLibrary;

{%CLASSGROUP 'Vcl.Controls.TControl'}

{$R *.dfm}

procedure TrptOrders.DataModuleCreate(Sender: TObject);
begin
  Logger.Log( 3, 'TAuthDatabase.DataModuleCreate' );
  LoadDatabaseSettings( ucKG, 'kgOrdersServer.ini' );
  try
    ucKG.Connect;
  except
    on E: Exception do
    begin
      Logger.Log(3, '--TrptOrders.DataModuleCreate -Error connecting to database: ' + E.Message);
    end;
  end;
end;


procedure TrptOrders.PrepareReport(searchOptions: string);
var
  SQL: string;
begin
  SQL := BuildOrderQuery(searchOptions);
  Logger.Log(5, 'Generated SQL for Prepare Report: ' + SQL);

  uqOrders.Close;
  uqOrders.SQL.Text := SQL;
  uqOrders.Open;


  GeneratePDF;

  Logger.Log(5, 'Report preparation complete.');
end;



procedure TrptOrders.uqOrdersCalcFields(DataSet: TDataSet);
var
  ColorType: string;
  SQL: string;
  OrderID: LongWord;
  jsonStr: string;
begin
  OrderID := uqOrdersORDER_ID.AsInteger;
  if uqOrdersORDER_TYPE.AsString = 'web_plate' then
  begin
    ColorType := 'quantity_and_colors_qty_colors';
    SQL := 'SELECT ' + ColorType + ' FROM web_plate_orders WHERE order_id = ' + IntToStr(OrderID);
  end
  else
  begin
    ColorType := 'colors_colors';
    SQL := 'SELECT ' + ColorType + ' FROM corrugated_plate_orders WHERE order_id = ' + IntToStr(OrderID);
  end;

  uqColors.Close;
  uqColors.SQL.Text := SQL;
  try
    uqColors.Open;
    jsonStr := uqColors.FieldByName(ColorType).AsString;
    DataSet.FieldByName('COLORS').AsString := getColorCount(jsonStr);
  finally
    uqColors.Close; // Ensure it is closed
  end;
end;



function TrptOrders.getColorCount(colors: string): string;
var
  colorObject: TJSONObject;
  colorList: TJSONArray;
begin
  if colors = '' then
    result := '0'
  else
  begin
    colorObject := TJSONObject.ParseJSONValue(colors) as TJSONObject;
    try
      colorList := TJSONArray(colorObject.GetValue('items'));
      result := IntToStr(colorList.Count);
    finally
      colorObject.Free; // Free TJSONObject to avoid leaks
    end;
  end;
end;



// Builds a dynamic SQL query based on the search options
function TrptOrders.BuildOrderQuery(searchOptions: string): string;
var
  params: TStringList;
  PageNum, PageSize: Integer;
  startDate, endDate, filterType, statusType, statusSuffix: string;
  statusTableShort, statusTableLong, whereSQL, SQL: string;
begin
  params := TStringList.Create;
  try
    params.StrictDelimiter := True;
    params.Delimiter := '&';
    params.DelimitedText := searchOptions;

    // Parse parameters
    PageNum := StrToIntDef(params.Values['pagenumber'], 1);
    PageSize := StrToIntDef(params.Values['pagesize'], 50);
    startDate := params.Values['startDate'];
    endDate := params.Values['endDate'];
    filterType := params.Values['filterType'];
    statusType := '';
    statusSuffix := '';

    if filterType <> '' then
    begin
      statusType := filterType.Split(['_'])[0];
      statusSuffix := filterType.Split(['_'])[1];
      filterType := statusType + '_' + statusSuffix;
    end;

    // Determine which status table to use
    if statusSuffix = 'DUE' then
    begin
      statusTableShort := 'oss';
      statusTableLong := 'orders_status_schedule';
    end
    else
    begin
      statusTableShort := 'os';
      statusTableLong := 'orders_status';
    end;


    SQL := 'SELECT o.ORDER_ID, ';
    if filterType <> '' then
      SQL := SQL + statusTableShort + '.STATUS_DATE AS ' + filterType.ToUpper + ', ';
    SQL := SQL +
      'o.LOCATION AS Loc, c.NAME AS COMPANY_NAME, o.JOB_NAME, o.ORDER_DATE, o.ORDER_TYPE, ';


    SQL := SQL + generateSubQuery(filterType, statusType, 'PROOF');
    SQL := SQL + generateSubQuery(filterType, statusType, 'ART');
    SQL := SQL + generateSubQuery(filterType, statusType, 'PLATE');
    SQL := SQL + generateSubQuery(filterType, statusType, 'MOUNT');
    SQL := SQL + generateSubQuery(filterType, statusType, 'SHIP');


    SQL := SQL + 'o.PRICE, qb.QB_REF_NUM ' +
      'FROM orders o ' +
      'JOIN ' + statusTableLong + ' ' + statusTableShort +
      ' ON ' + statusTableShort + '.ORDER_ID = o.ORDER_ID ' +
      'JOIN customers c ON c.CUSTOMER_ID = o.COMPANY_ID ' +
      'LEFT JOIN qb_sales_orders qb ON qb.ORDER_ID = o.ORDER_ID ';


    whereSQL := 'WHERE 1=1 ';
    if startDate <> '' then
      whereSQL := whereSQL + ' AND o.ORDER_DATE >= ' + QuotedStr(startDate);
    if endDate <> '' then
      whereSQL := whereSQL + ' AND o.ORDER_DATE <= ' + QuotedStr(endDate);
    if statusType <> '' then
      whereSQL := whereSQL + ' AND ' + statusTableShort + '.ORDER_STATUS = ' + QuotedStr(statusType);

    SQL := SQL + whereSQL;


    SQL := SQL + ' ORDER BY o.ORDER_DATE DESC ' +
      'LIMIT ' + IntToStr(PageSize) + ' OFFSET ' + IntToStr((PageNum - 1) * PageSize);

    Result := SQL;
  finally
    params.Free;
  end;
end;


function TrptOrders.generateSubQuery(filterType, statusType, currStatus: string): string;
var
  statusSuffix: string;
begin
  Result := '';
  statusSuffix := '';
  if filterType <> '' then
    statusSuffix := filterType.Split(['_'])[1];

  if statusType <> currStatus then
  begin
    if (statusSuffix = 'DUE') or (statusSuffix = '') then
    begin
      Result := Result +
        '(SELECT oss.STATUS_DATE FROM orders_status_schedule oss ' +
        'WHERE oss.ORDER_ID = o.ORDER_ID AND oss.ORDER_STATUS = ' + QuotedStr(currStatus) + ') AS ' + currStatus + '_DUE, ';
    end
    else
    begin
      Result := Result +
        '(SELECT os.STATUS_TIMESTAMP FROM orders_status os ' +
        'WHERE os.ORDER_ID = o.ORDER_ID AND os.ORDER_STATUS = ' + QuotedStr(currStatus) +
        ' ORDER BY os.STATUS_TIMESTAMP DESC LIMIT 1) AS ' + currStatus + '_DONE, ';
    end;
  end;

  if (statusSuffix = 'DUE') or (statusSuffix = '') then
  begin
    Result := Result +
      '(SELECT os.STATUS_TIMESTAMP FROM orders_status os ' +
      'WHERE os.ORDER_ID = o.ORDER_ID AND os.ORDER_STATUS = ' + QuotedStr(currStatus) +
      ' ORDER BY os.STATUS_TIMESTAMP DESC LIMIT 1) AS ' + currStatus + '_DONE, ';
  end
  else
  begin
    Result := Result +
      '(SELECT oss.STATUS_DATE FROM orders_status_schedule oss ' +
      'WHERE oss.ORDER_ID = o.ORDER_ID AND oss.ORDER_STATUS = ' + QuotedStr(currStatus) + ') AS ' + currStatus + '_DUE, ';
  end;
end;

//create new field called color count


procedure TrptOrders.GeneratePDF;
var
  ReportDir, ReportFileName: string;
begin
  ReportDir := 'C:\Projects\KGOrders\Reports';

  if not DirectoryExists(ReportDir) then
  begin
    ForceDirectories(ReportDir);
    Logger.Log(5, 'Reports directory created: ' + ReportDir);
  end;

  ReportFileName := TPath.Combine(ReportDir, 'OrderReport_' + FormatDateTime('yyyymmdd_hhnnss', Now) + '.pdf');

  frxPDFExport1.FileName := ReportFileName;
  frxPDFExport1.ShowDialog := False;
  try
    frxOrders.PrepareReport;
    frxOrders.Export(frxPDFExport1);
    frxOrders.ShowPreparedReport;
  finally
    frxOrders.Clear; // Clear the report to avoid memory bloat
  end;

  Logger.Log(5, 'PDF saved to: ' + ReportFileName);
end;





end.

