Commit fb763e28 by Mac Stephens

added fast report, fixed memory issues

parent f1a2333b
......@@ -1276,7 +1276,7 @@ object FData: TFData
PrintFont.Style = []
Width = 64
end>
DataSource = dsRecordings
DataSource = dsGrid2
InvalidPicture.Data = {
055449636F6E0000010001002020200000000000A81000001600000028000000
2000000040000000010020000000000000100000000000000000000000000000
......@@ -1509,7 +1509,8 @@ object FData: TFData
Left = 482
Top = 459
end
object dsRecordings: TDataSource
object dsGrid2: TDataSource
DataSet = rptOrders.uqOrders
Left = 348
Top = 472
end
......
// Uses Twilio.Data.Module for the rest api calls. Simply for testing querys.
// For testing querys.
// Visual aspect is for testing purposes only and has no affect on the client.
// Authors:
// Cameron Hayes
......@@ -23,7 +23,7 @@ type
Memo1: TMemo;
DBAdvGrid1: TDBAdvGrid;
DBAdvGrid2: TDBAdvGrid;
dsRecordings: TDataSource;
dsGrid2: TDataSource;
edtUsername: TEdit;
edtPassword: TEdit;
lblHash: TLabel;
......@@ -43,7 +43,7 @@ type
accountSID: string;
authHeader: string;
public
function GetReportPDF(OrderID: string): string;
procedure RunOrdersReport(searchOptions: string);
end;
var
......@@ -57,7 +57,7 @@ uses uLibrary, rOrders;
procedure TFData.btnPDFClick(Sender: TObject);
begin
GetReportPDF('');
RunOrdersReport('&pagenumber=1&pagesize=50&orderby=');
end;
......@@ -84,27 +84,16 @@ begin
end;
function TFData.GetReportPDF(OrderID: string): string;
procedure TFData.RunOrdersReport(searchOptions: string);
var
rptOrders: TrptOrders; // Local instance
OrderIDList: TStringList;
rptOrders: TrptOrders;
begin
rptOrders := TrptOrders.Create(nil); // Always create locally
rptOrders := TrptOrders.Create(nil);
try
// Create a list of hardcoded OrderIDs for testing
OrderIDList := TStringList.Create;
try
OrderIDList.Add('18995');
OrderIDList.Add('18994');
OrderIDList.Add('18993'); // Add more OrderIDs as needed
// Generate the PDF Report with the list of OrderIDs
rptOrders.GenerateSimpleReport(350);
finally
OrderIDList.Free; // Free the TStringList
end;
rptOrders.PrepareReport(searchOptions);
dsGrid2.DataSet := rptOrders.uqOrders;
finally
rptOrders.Free; // Ensure rptOrders is freed
rptOrders.Free;
end;
end;
......
......@@ -36,7 +36,6 @@ type
function EditUser(const editOptions: string): string;
function Search(phoneNum: string): TOrderList;
procedure GenerateReportPDF(searchOptions: string);
function BuildOrderQuery(searchOptions: string): string;
function AddUser(userInfo: string): string;
function AddItem(itemInfo: string): string;
function DelUser(username: string): string;
......@@ -172,100 +171,10 @@ begin
// Create instance of rptOrders
rptOrders := TrptOrders.Create(nil);
try
// Generate SQL dynamically using the existing GetOrders logic
SQL := BuildOrderQuery(searchOptions);
// Prepare the report dataset
rptOrders.PrepareReport(SQL);
// Generate the PDF report
rptOrders.GeneratePDF;
// Optionally, log success
rptOrders.PrepareReport(searchOptions);
Logger.log(5, 'PDF Report successfully generated for searchOptions: ' + searchOptions);
finally
rptOrders.Free; // Ensure proper cleanup
end;
end;
function TLookupService.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 status table
if statusSuffix = 'DUE' then
begin
statusTableShort := 'oss';
statusTableLong := 'orders_status_schedule';
end
else
begin
statusTableShort := 'os';
statusTableLong := 'orders_status';
end;
// Build the SELECT query with dynamically generated subqueries
SQL := 'SELECT o.ORDER_ID, c.NAME AS COMPANY_NAME, o.JOB_NAME, o.ORDER_DATE, o.ORDER_TYPE, ';
// Add dynamically generated subqueries
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');
// Include additional static fields
SQL := SQL + 'o.PRICE, qb.QB_REF_NUM ';
// FROM clause
SQL := SQL + 'FROM orders o ' +
'JOIN customers c ON o.COMPANY_ID = c.CUSTOMER_ID ' +
'LEFT JOIN qb_sales_orders qb ON qb.ORDER_ID = o.ORDER_ID ';
// WHERE clause
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);
// Add WHERE and ORDER clauses
SQL := SQL + whereSQL +
' ORDER BY o.ORDER_DATE DESC ' +
' LIMIT ' + IntToStr(PageSize) +
' OFFSET ' + IntToStr((PageNum - 1) * PageSize);
Result := SQL;
Logger.log(5, 'Generated SQL in Build order Query: ' + SQL);
finally
params.Free;
rptOrders.Free;
end;
end;
......@@ -328,6 +237,7 @@ var
statusTableShort: string;
statusTableLong: string;
begin
logger.log(4, 'Get Orders SearchOptions Str: ' + searchOptions);
params := TStringList.Create;
params.StrictDelimiter := true;
// parse the searchOptions
......@@ -398,7 +308,7 @@ begin
'ORDER BY o.ORDER_DATE DESC';
SQL := SQL + 'o.PRICE, qb.QB_REF_NUM ' + whereSQL + ' LIMIT ' + limit + ' OFFSET ' + offset;
end;
logger.log(4, 'Get Orders SQL: ' + SQL);
doQuery(ordersDB.UniQuery1, SQL);
Result:= TOrderList.Create;
......
......@@ -5,7 +5,7 @@ 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;
MemDS, frxDBSet, frxTableObject, frCoreClasses, Common.Logging, System.IOUtils, JSON;
type
TrptOrders = class(TDataModule)
......@@ -13,15 +13,38 @@ type
frxPDFExport1: TfrxPDFExport;
ucKG: TUniConnection;
uqOrders: TUniQuery;
frxReportTableObject1: TfrxReportTableObject;
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 GenerateSimpleReport(OrderID: Integer);
procedure PrepareReport(const SQL: string);
procedure PrepareReport(searchOptions: string);
procedure GeneratePDF;
end;
......@@ -51,61 +74,239 @@ begin
end;
end;
procedure TrptOrders.GenerateSimpleReport(OrderID: Integer);
procedure TrptOrders.PrepareReport(searchOptions: string);
var
SQL: string;
begin
try
Logger.Log(5, 'Generating Report for Order ID: ' + OrderID.ToString);
SQL := BuildOrderQuery(searchOptions);
Logger.Log(5, 'Generated SQL for Prepare Report: ' + SQL);
uqOrders.Close;
uqOrders.SQL.Text := 'SELECT ORDER_ID FROM corrugated_plate_orders WHERE ORDER_ID = :OrderID';
uqOrders.ParamByName('OrderID').AsInteger := OrderID;
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
uqOrders.Open;
except
on E: Exception do
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
Logger.Log(1, 'Error executing query: ' + E.Message);
Exit;
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;
frxOrders.PrepareReport;
frxOrders.ShowReport;
// 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
uqOrders.Close;
frxOrders.Clear;
Logger.Log(5, 'Report generation complete for Order ID: ' + OrderID.ToString);
params.Free;
end;
end;
procedure TrptOrders.PrepareReport(const SQL: string);
function TrptOrders.generateSubQuery(filterType, statusType, currStatus: string): string;
var
statusSuffix: string;
begin
// Prepare and load data into the query
uqOrders.Close;
uqOrders.SQL.Text := SQL;
uqOrders.Open;
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';
// Define output file
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');
// Prepare and export the report
frxOrders.PrepareReport;
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.
......@@ -1164,6 +1164,7 @@
<Platform value="Win32">True</Platform>
<Platform value="Win64">True</Platform>
</Platforms>
<ModelSupport>False</ModelSupport>
</BorlandProject>
<ProjectFileVersion>12</ProjectFileVersion>
</ProjectExtensions>
......
[Settings]
MemoLogLevel=5
FileLogLevel=5
LogFileNum=30
LogFileNum=81
webClientVersion=1.0.0
[Database]
--Server=192.168.159.132
Server=192.168.60.129
--Server=192.168.75.133
--Server=192.168.60.129
Server=192.168.102.130
--Database=
--Username=
Password=emsys!012
--Password=emsys!012
Password=emsys01
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment