Commit 35c58bb8 by Mac Stephens

Merge branch 'mac3'

Version 0.9.7 deployed to server, database updated on dbserver
parents 1a5d0980 6d54266c
object FViewAddCustomer: TFViewAddCustomer
Width = 842
Height = 607
OnShow = WebFormShow
CSSLibrary = cssBootstrap
ElementFont = efCSS
object lblFormState: TWebLabel
Left = 18
Top = 16
Width = 3
Height = 15
ElementID = 'lbl_form_state'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object dtpStartDate: TWebDateTimePicker
Left = 19
Top = 216
......@@ -200,44 +210,6 @@ object FViewAddCustomer: TFViewAddCustomer
WidthPercent = 100.000000000000000000
OnClick = btnEditClick
end
object pnlMessage: TWebPanel
Left = 324
Top = 19
Width = 121
Height = 33
ElementID = 'view.login.message'
ChildOrder = 5
ElementPosition = epRelative
Role = 'null'
TabOrder = 16
object lblMessage: TWebLabel
Left = 28
Top = 9
Width = 46
Height = 15
Caption = 'Message'
ElementID = 'view.login.message.label'
ElementPosition = epRelative
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object btnCloseNotification: TWebButton
Left = 96
Top = 3
Width = 22
Height = 25
ChildOrder = 1
ElementID = 'view.login.message.button'
ElementFont = efCSS
ElementPosition = epRelative
HeightStyle = ssAuto
HeightPercent = 100.000000000000000000
Role = 'null'
WidthStyle = ssAuto
WidthPercent = 100.000000000000000000
OnClick = btnCloseNotificationClick
end
end
object edtCustomerID: TWebDBEdit
Left = 151
Top = 12
......@@ -274,7 +246,7 @@ object FViewAddCustomer: TFViewAddCustomer
BorderColor = clSilver
ChildOrder = 11
ElementFont = efCSS
ElementHeaderClassName = 'thead-light sticky-top bg-light'
ElementHeaderClassName = 'thead-light sticky-top bg-light border-light'
ElementPosition = epRelative
ElementTableClassName = 'table table-striped table-hover table-bordered text-sm'
Footer.ButtonActiveElementClassName = 'btn btn-primary'
......@@ -296,6 +268,7 @@ object FViewAddCustomer: TFViewAddCustomer
Header.ListItemElementClassName = 'page-item'
Header.ListLinkElementClassName = 'page-link'
WordWrap = True
OnClickCell = wdbtcAddressesDblClickCell
OnDblClickCell = wdbtcAddressesDblClickCell
Columns = <
item
......@@ -350,6 +323,7 @@ object FViewAddCustomer: TFViewAddCustomer
Width = 121
Height = 22
ChildOrder = 22
EditType = weNumeric
ElementID = 'edtshippingzip'
Enabled = False
HeightPercent = 100.000000000000000000
......@@ -392,7 +366,6 @@ object FViewAddCustomer: TFViewAddCustomer
SelLength = 0
SelStart = 0
WidthPercent = 100.000000000000000000
OnChange = memoAddressBlockChange
end
object btnAdd: TWebButton
Left = 19
......@@ -470,18 +443,6 @@ object FViewAddCustomer: TFViewAddCustomer
WidthPercent = 100.000000000000000000
OnClick = btnShipAddClick
end
object btn_confirm_delete: TWebButton
Left = 725
Top = 433
Width = 96
Height = 25
Caption = 'Delete'
ChildOrder = 82
ElementID = 'btn_confirm_delete'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnClick = btn_confirm_deleteClick
end
object edtFirstLine: TWebEdit
Left = 190
Top = 430
......@@ -513,12 +474,12 @@ object FViewAddCustomer: TFViewAddCustomer
Top = 72
end
object WebDataSource1: TWebDataSource
AutoEdit = False
DataSet = XDataWebDataSet1
Left = 532
Top = 126
end
object XDataWebDataSet1: TXDataWebDataSet
AfterEdit = XDataWebDataSet1AfterEdit
Connection = DMConnection.ApiConnection
Left = 426
Top = 132
......@@ -566,12 +527,12 @@ object FViewAddCustomer: TFViewAddCustomer
end
end
object wdsShipTo: TWebDataSource
AutoEdit = False
DataSet = xdwdsShipTo
Left = 698
Top = 128
end
object xdwdsShipTo: TXDataWebDataSet
AfterEdit = xdwdsShipToAfterEdit
Left = 698
Top = 44
object xdwdsShipToADDRESS: TStringField
......@@ -603,6 +564,7 @@ object FViewAddCustomer: TFViewAddCustomer
Top = 42
end
object wdsUsers: TWebDataSource
AutoEdit = False
DataSet = xdwdsUsers
Left = 776
Top = 144
......
<nav class="navbar navbar-expand navbar-light bg-light sticky-top" style="z-index: 100;">
<div class="container-fluid ps-0">
<div id="view.login.message" class="alert alert-danger"
style="padding: 0.25rem 0.5rem; font-size: 0.875rem; line-height: 1.5; display: flex; align-items: center; margin: 0 0 0 60px; height: 32px; width: 400px;">
<button id="view.login.message.button" type="button" class="btn-close" aria-label="Close"></button>
<span id="view.login.message.label"></span>
</div>
<ul class="navbar-nav me-auto ps-2">
<nav class="navbar navbar-expand navbar-light bg-light sticky-top border-light" style="z-index: 100;">
<div class="container-fluid d-flex align-items-center ps-0 pe-0">
<!-- Left-aligned form state label -->
<div class="me-auto ps-3">
<label id="lbl_form_state" class="form-label mb-0 fw-bold text-uppercase text-nowrap text-danger" style="font-size: 16px;">View Mode</label>
</div>
<!-- Right-aligned buttons -->
<ul class="navbar-nav ms-auto pe-2 mb-0">
<li class="nav-item pe-2">
<button id="btnadd" class="btn btn-primary btn-sm">Add</button>
</li>
......@@ -25,9 +28,10 @@
<button id="btnclose" class="btn btn-primary btn-sm">Close</button>
</li>
</ul>
</div>
</nav>
<div class="row mx-5">
<div class="row mx-5">
<h4 class="custom-h4 mt-3">Customer Information</h4>
<hr class="custom-hr">
<div class="row">
......@@ -125,17 +129,20 @@
<h4 class="custom-h4 mt-3">Shipping Addresses</h4>
<hr class="custom-hr">
<div class="row">
<div class="overflow-auto mt-2"
style="max-height: calc(100vh - 250px); padding-bottom: 0; width: 100%;">
<table id="tblPhoneGrid" class="table table-striped table-bordered" style="width: 100%;">
<thead class="sticky-top thead-light">
<tr style="font-size: 0.875rem;">
<!-- Table headers are dynamically generated -->
<!-- headers -->
</tr>
</thead>
<tbody id="orderTableBody" class="align-middle">
<!-- Table rows are dynamically generated -->
<!-- rows -->
</tbody>
</table>
</div>
</div>
<div class="row mt-1">
<div class="col-auto">
<button id="btnshipadd" class="btn btn-primary btn-sm">Add</button>
......@@ -206,29 +213,6 @@
</div>
</div>
</div>
</div>
</div>
<div class="modal fade" id="confirmation_modal" tabindex="-1" aria-labelledby="confirmation_modal_label" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="confirmation_modal_label">Confirm</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body" id="modal_body">
Are you sure you want to delete this order?
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" id= 'btn_confirm_cancel'>Cancel</button>
<button type="button" class="btn btn-primary" data-bs-dismiss="modal" id="btn_confirm_delete">Delete</button>
</div>
</div>
</div>
</div>
<style>
.modal-backdrop {
opacity: 0 !important;
}
</style>
......@@ -9,7 +9,7 @@ uses
WEBLib.Forms, WEBLib.Dialogs, WEBLib.Menus, WEBLib.ExtCtrls, WEBLib.StdCtrls,
WEBLib.JSON, Auth.Service, XData.Web.Client, WebLib.Storage,
ConnectionModule, App.Types, Vcl.StdCtrls, Vcl.Controls, WEBLib.DBCtrls,
Data.DB, XData.Web.JsonDataset, XData.Web.Dataset, WEBLib.DB, WEBLib.Grids;
Data.DB, XData.Web.JsonDataset, XData.Web.Dataset, WEBLib.DB, WEBLib.Grids, VCL.Forms;
type
TFViewAddCustomer = class(TWebForm)
......@@ -29,9 +29,6 @@ type
btnDelete: TWebButton;
btnClose: TWebButton;
btnEdit: TWebButton;
pnlMessage: TWebPanel;
lblMessage: TWebLabel;
btnCloseNotification: TWebButton;
XDataWebClient1: TXDataWebClient;
WebDataSource1: TWebDataSource;
XDataWebDataSet1: TXDataWebDataSet;
......@@ -73,7 +70,6 @@ type
btnShipDelete: TWebButton;
btnShipEdit: TWebButton;
btnShipAdd: TWebButton;
btn_confirm_delete: TWebButton;
tmrReturn: TWebTimer;
edtFirstLine: TWebEdit;
wdsUsers: TWebDataSource;
......@@ -82,32 +78,25 @@ type
xdwdsUsersuserID: TStringField;
XDataWebDataSet1REP_USER_ID: TStringField;
xdwdsUsersfull_name: TStringField;
procedure WebFormShow(Sender: TObject);
procedure btnCloseNotificationClick(Sender: TObject);
lblFormState: TWebLabel;
procedure btnSaveClick(Sender: TObject);
procedure btnCancelClick(Sender: TObject);
procedure xdwdsShipToAfterEdit(DataSet: TDataSet);
procedure XDataWebDataSet1AfterEdit(DataSet: TDataSet);
procedure btnCloseClick(Sender: TObject);
procedure btnEditClick(Sender: TObject);
procedure wdbtcAddressesDblClickCell(Sender: TObject; ACol, ARow: Integer);
procedure btnClearClick(Sender: TObject);
procedure memoAddressBlockChange(Sender: TObject);
procedure AddressEditMode();
procedure edtShippingAddressChange(Sender: TObject);
procedure btnAddClick(Sender: TObject);
procedure btn_confirm_deleteClick(Sender: TObject);
procedure tmrReturnTimer(Sender: TObject);
procedure btnDeleteClick(Sender: TObject);
procedure btnShipAddClick(Sender: TObject);
procedure btnShipEditClick(Sender: TObject);
procedure btnShipSaveClick(Sender: TObject);
[async] procedure btnShipSaveClick(Sender: TObject);
procedure btnShipDeleteClick(Sender: TObject);
procedure btnShipCancelClick(Sender: TObject);
private
{ Private declarations }
procedure HideNotification();
procedure ShowNotification(Notification: string);
procedure ViewMode();
procedure EditMode();
[async] procedure GetCustomer();
......@@ -118,6 +107,7 @@ type
function VerifyAddress(): boolean;
procedure Clear();
procedure ShowSelectCustomerForm();
[async] procedure InitializeForm;
var
customerID: string;
notification: string;
......@@ -137,6 +127,45 @@ implementation
uses View.Main, View.Customers, View.SelectCustomer, Utils;
class function TFViewAddCustomer.CreateForm(AElementID, customerInfo, info: string): TWebForm;
begin
Application.CreateForm(TFViewAddCustomer, AElementID, Result,
procedure(AForm: TObject)
begin
with TFViewAddCustomer(AForm) do
begin
customerID := customerInfo;
notification := info;
InitializeForm;
end;
end
);
end;
[async] procedure TFViewAddCustomer.InitializeForm;
begin
if customerID = '' then
mode := 'ADD'
else
mode := 'EDIT';
if notification <> '' then
ShowToast(notification);
if mode = 'ADD' then
EditMode()
else
ViewMode();
await(GetCustomer);
dtpStartDate.Date := 0;
dtpEndDate.Date := 0;
end;
procedure TFViewAddCustomer.Clear();
// Clears the shipping address fields.
begin
......@@ -159,6 +188,7 @@ begin
newform.Caption := 'Select Customer and Order Type';
newForm.Popup := True;
newForm.Border := fbDialog;
newForm.Position := poScreenCenter;
// used to manage Back button handling to close subform
window.location.hash := 'subform';
......@@ -180,7 +210,7 @@ begin
Response := await(XDataWebClient1.RawInvokeAsync('ILookupService.DelShippingAddress',
[xdwdsShipTo.FieldByName('ship_id').AsString, customerID]));
notification := TJSObject(Response.Result);
ShowNotification(string(notification['status']));
ShowToast(string(notification['status']));
xdwdsShipTo.Close;
xdwdsShipTo.SetJSONData(notification['ADDRESS']);
xdwdsShipTo.Open;
......@@ -222,7 +252,7 @@ begin
[AddressJSON.ToString]));
notification := TJSObject(Response.Result);
ShowNotification(string(notification['status']));
ShowToast(string(notification['status']));
xdwdsShipTo.Close;
xdwdsShipTo.SetJSONData(notification['ADDRESS']);
xdwdsShipTo.Open;
......@@ -234,19 +264,28 @@ begin
ShowSelectCustomerForm();
end;
procedure TFViewAddCustomer.btnCancelClick(Sender: TObject);
// Shows a pop-up to confirm the user would like to cancel their changes.
begin
document.getElementById('modal_body').innerHTML := 'Are you sure you want to cancel all changes to the customer?';
document.getElementById('btn_confirm_cancel').innerText := 'No';
document.getElementById('btn_confirm_delete').innerText := 'Yes';
asm
var confirmationModal = new bootstrap.Modal(document.getElementById('confirmation_modal'), {
keyboard: false });
confirmationModal.show();
ShowConfirmationModal(
'Are you sure you want to cancel all changes to the customer?',
'Yes',
'No',
procedure(confirmed: Boolean)
begin
if confirmed then
begin
FViewMain.change := false;
if CustomerID <> '' then
FViewMain.ViewAddCustomer(CustomerID, 'Failure: Changes Discarded')
else
FViewMain.ShowForm(TFViewCustomers);
end;
end);
end;
procedure TFViewAddCustomer.btnClearClick(Sender: TObject);
// Clears the shipping address fields.
begin
......@@ -259,17 +298,13 @@ begin
FViewMain.ShowForm(TFViewCustomers)
end;
procedure TFViewAddCustomer.btnCloseNotificationClick(Sender: TObject);
// Closes a Notification.
begin
HideNotification();
end;
procedure TFViewAddCustomer.btnDeleteClick(Sender: TObject);
// Eventually will delete customers after a confirmation
// TODO implement deleting customers
begin
ShowMessage('Deleting Customers Is Not Yet Available');
ShowToast('Deleting Customers Is Not Yet Available', 'danger');
Exit;
end;
procedure TFViewAddCustomer.btnEditClick(Sender: TObject);
......@@ -284,119 +319,29 @@ begin
AddressEditMode();
end;
procedure TFViewAddCustomer.EditMode;
// Enables Customer Fields while disabling shipping address fields.
begin
FViewMain.change := true;
btnAdd.Enabled := false;
btnDelete.Enabled := false;
btnClose.Enabled := false;
btnSave.Enabled := true;
btnCancel.Enabled := True;
btnEdit.Enabled := false;
// Disable Shipping Address Editting
edtShippingAddress.Enabled := false;
edtShippingCity.Enabled := false;
edtShippingState.Enabled := false;
edtShippingZip.Enabled := false;
edtShippingContact.Enabled := false;
edtFirstLine.Enabled := false;
btnShipDelete.Enabled := false;
btnShipSave.Enabled := false;
btnShipCancel.Enabled := false;
btnShipEdit.Enabled := false;
btnShipAdd.Enabled := false;
end;
procedure TFViewAddCustomer.AddressEditMode;
// Enables Shipping Address fields while disabling customer fields.
begin
FViewMain.change := true;
btnDelete.Enabled := false;
btnClose.Enabled := false;
btnSave.Enabled := false;
btnCancel.Enabled := false;
btnEdit.Enabled := false;
btnAdd.Enabled := false;
btnShipDelete.Enabled := false;
btnShipSave.Enabled := true;
btnShipCancel.Enabled := true;
btnShipEdit.Enabled := false;
btnShipAdd.Enabled := false;
edtShippingAddress.Enabled := true;
edtShippingCity.Enabled := true;
edtShippingState.Enabled := true;
edtShippingZip.Enabled := true;
edtShippingContact.Enabled := true;
edtFirstLine.Enabled := true;
edtName.Enabled := false;
edtShortName.Enabled := false;
edtBillAddress.Enabled := false;
edtBillCity.Enabled := false;
edtBillState.Enabled := false;
edtBillZip.Enabled := false;
edtBillContact.Enabled := false;
dtpStartDate.Enabled := false;
dtpEndDate.Enabled := false;
edtFax.Enabled := false;
edtPhone.enabled := false;
wdblcbRep.Enabled := false;
end;
procedure TFViewAddCustomer.ViewMode;
// Enables Customer Fields while disabling shipping address fields.
begin
btnAdd.Enabled := true;
btnDelete.Enabled := true;
btnClose.Enabled := true;
btnSave.Enabled := false;
btnCancel.Enabled := false;
btnEdit.Enabled := true;
FViewMain.change := false;
btnShipAdd.Enabled := true;
if ( not xdwdsShipTo.IsEmpty ) then
btnShipDelete.Enabled := true;
btnShipSave.Enabled := false;
btnShipCancel.Enabled := false;
btnShipEdit.Enabled := true;
FViewMain.change := false;
edtName.Enabled := true;
edtShortName.Enabled := true;
edtBillAddress.Enabled := true;
edtBillCity.Enabled := true;
edtBillState.Enabled := true;
edtBillZip.Enabled := true;
edtBillContact.Enabled := true;
dtpStartDate.Enabled := true;
dtpEndDate.Enabled := true;
edtFax.Enabled := true;
edtPhone.enabled := true;
wdblcbRep.Enabled := true;
end;
procedure TFViewAddCustomer.wdbtcAddressesDblClickCell(Sender: TObject; ACol,
ARow: Integer);
// Retrieves the shipping address allowing it to be edited.
begin
xdwdsShipTo.Locate('ship_id', wdbtcAddresses.Cells[0, ARow], []);
edtShippingAddress.Text := xdwdsShipTo.FieldByName('shipping_address').AsString;
edtShippingCity.Text := xdwdsShipTo.FieldByName('city').AsString;
edtShippingState.Text := xdwdsShipTo.FieldByName('state').AsString;
edtShippingZip.Text := xdwdsShipTo.FieldByName('zip').AsString;
edtShippingContact.Text := xdwdsShipTo.FieldByName('contact').AsString;
memoShipBlock.Text := xdwdsShipTo.FieldByName('ADDRESS').AsString;
edtFirstLine.Text := memoShipBlock.Lines[0];
if memoShipBlock.Lines.Count > 0 then
edtFirstLine.Text := memoShipBlock.Lines[0]
else
edtFirstLine.Text := '';
btnShipEdit.Enabled := true;
end;
procedure TFViewAddCustomer.SendCustomerToServer();
// Creates the customer JSON and then sends it to the server.
var
......@@ -460,7 +405,7 @@ begin
edtCustomerID.Text := CustomerID;
ShowNotification(msg);
ShowToast(msg);
//TODO update the BILL_ADDRESS_BLOCK memo after saving.
......@@ -480,6 +425,7 @@ begin
if VerifyCustomer() then
begin
sendCustomerToServer();
GetCustomer();
ViewMode();
end;
end;
......@@ -492,112 +438,79 @@ begin
AddressEditMode();
end;
procedure TFViewAddCustomer.btnShipDeleteClick(Sender: TObject);
// Allows the user to delete a Shipping Address.
begin
document.getElementById('modal_body').innerHTML := 'Are you sure you want to delete this address?';
document.getElementById('btn_confirm_cancel').innerText := 'Cancel';
document.getElementById('btn_confirm_delete').innerText := 'Delete';
asm
var confirmationModal = new bootstrap.Modal(document.getElementById('confirmation_modal'), {
keyboard: false });
confirmationModal.show();
end;
end;
procedure TFViewAddCustomer.btnShipEditClick(Sender: TObject);
// Sets the form into AddressEdit mode.
begin
shipmode := 'EDIT';
AddressEditMode();
end;
procedure TFViewAddCustomer.btnShipSaveClick(Sender: TObject);
// After Verifying the Address it sends the address down to the server.
procedure TFViewAddCustomer.btnShipCancelClick(Sender: TObject);
begin
if VerifyAddress() then
ShowConfirmationModal(
'Are you sure you want to cancel address editing?',
'Yes',
'No',
procedure(confirmed: Boolean)
begin
SendAddressToServer();
if confirmed then
begin
shipmode := '';
Clear();
ViewMode();
end;
end);
end;
procedure TFViewAddCustomer.btn_confirm_deleteClick(Sender: TObject);
// Modal Confirmation button. Checks if the user is cancelling changes, or
// Deleting a shipping address/ customer
procedure TFViewAddCustomer.btnShipDeleteClick(Sender: TObject);
begin
FViewMain.change := false;
if document.getElementById('btn_confirm_delete').innerText = 'Yes' then
// checks if the user is canceling or deleting
begin
if CustomerID <> '' then
begin
FViewMain.ViewAddCustomer(CustomerID, 'Failure:Changes Discarded');
end
else
FViewMain.ShowForm(TFViewCustomers);
end
else if document.getElementById('modal_body').innerHTML.Contains('customer') then
// checks if the user is deleting a customer or a shipping address
ShowConfirmationModal(
'Are you sure you want to delete this address?',
'Delete',
'Cancel',
procedure(confirmed: Boolean)
begin
asm
var confirmationModal = new bootstrap.Modal(document.getElementById('confirmation_modal'), {
keyboard: false });
confirmationModal.hide();
end;
Utils.ShowSpinner('spinner');
//delCustomer();
tmrReturn.Enabled := true;
end
else
if confirmed then
begin
asm
var confirmationModal = new bootstrap.Modal(document.getElementById('confirmation_modal'), {
keyboard: false });
confirmationModal.hide();
end;
Utils.ShowSpinner('spinner');
delAddress();
DelAddress();
end;
end);
end;
class function TFViewAddCustomer.CreateForm(AElementID: string; customerInfo: string; info: string): TWebForm;
// Creates the Add Customer form. Setting the customer id so the customer can be
// Retrieved and the notification to be shown.
procedure TFViewAddCustomer.btnShipEditClick(Sender: TObject);
// Sets the form into AddressEdit mode.
begin
Application.CreateForm(TFViewAddCustomer, AElementID, Result,
procedure(AForm: TObject)
begin
with TFViewAddCustomer(AForm) do
shipmode := 'EDIT';
AddressEditMode();
end;
[async] procedure TFViewAddCustomer.btnShipSaveClick(Sender: TObject);
begin
if (customerID = '') then
begin
TFViewAddCustomer(AForm).customerID := customerInfo;
TFViewAddCustomer(AForm).notification := info;
ShowErrorModal('Cannot save address: Customer ID is not set.');
Exit;
end;
end
);
console.log('Saving address. CustomerID = ' + customerID);
if VerifyAddress() then
begin
await(SendAddressToServer);
Clear();
await(GetCustomer); // Ensures xdwdsShipTo is refreshed with server data
ViewMode();
end;
end;
procedure TFViewAddCustomer.GetCustomer;
// Retrieves a customer for a given CustomerID.
var
xdcResponse: TXDataClientResponse;
customer : TJSObject;
address: string;
items: TJSObject;
ship_block: TStringList;
begin
if CustomerID = '' then
begin
mode := 'ADD';
end
else
mode := 'EDIT';
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GetCustomer',
[customerID]));
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GetCustomer', [customerID]));
customer := TJSObject(xdcResponse.Result);
console.log(customer);
xdwdsUsers.Close;
xdwdsUsers.SetJSONData(customer['USERS']);
......@@ -632,81 +545,6 @@ begin
edtFirstLine.Text := memoShipBlock.Lines[0]
else
edtFirstLine.Text := '';
end;
procedure TFViewAddCustomer.WebFormShow(Sender: TObject);
// Sets the form up whenever it is shown.
var
SQL: string;
begin
if customerID = '' then
mode := 'ADD'
else
mode := 'EDIT';
if notification = '' then
hideNotification()
else
showNotification(notification);
if mode = 'ADD' then
EditMode()
else
ViewMode();
getCustomer();
dtpStartDate.Date := 0;
dtpEndDate.Date := 0;
end;
procedure TFViewAddCustomer.XDataWebDataSet1AfterEdit(DataSet: TDataSet);
begin
EditMode();
end;
procedure TFViewAddCustomer.xdwdsShipToAfterEdit(DataSet: TDataSet);
begin
EditMode();
end;
procedure TFViewAddCustomer.HideNotification;
begin
pnlMessage.ElementHandle.hidden := True;
end;
procedure TFViewAddCustomer.memoAddressBlockChange(Sender: TObject);
begin
EditMode();
end;
procedure TFViewAddCustomer.ShowNotification(Notification: string);
var
splitNotification: TArray<string>;
begin
if Notification <> '' then
begin
splitNotification := Notification.Split([':']);
if(splitNotification[0] = 'Success') then
begin
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-danger');
messageDiv.classList.add('alert-success');
end;
end
else
begin
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-success');
messageDiv.classList.add('alert-danger');
end;
end;
lblMessage.Caption := splitNotification[1];
pnlMessage.ElementHandle.hidden := False;
end;
end;
procedure TFViewAddCustomer.tmrReturnTimer(Sender: TObject);
......@@ -854,4 +692,124 @@ begin
end;
procedure TFViewAddCustomer.EditMode;
// Enables Customer Fields while disabling shipping address fields.
begin
XDataWebDataSet1.Edit;
FViewMain.change := true;
btnAdd.Enabled := false;
btnDelete.Enabled := false;
btnClose.Enabled := false;
btnSave.Enabled := true;
btnCancel.Enabled := True;
btnEdit.Enabled := false;
// Disable Shipping Address Editting
edtShippingAddress.Enabled := false;
edtShippingCity.Enabled := false;
edtShippingState.Enabled := false;
edtShippingZip.Enabled := false;
edtShippingContact.Enabled := false;
edtFirstLine.Enabled := false;
btnShipDelete.Enabled := false;
btnShipSave.Enabled := false;
btnShipCancel.Enabled := false;
btnShipEdit.Enabled := false;
btnShipAdd.Enabled := false;
lblFormState.Caption := 'Edit Mode';
lblFormState.ElementHandle.classList.remove('text-danger');
lblFormState.ElementHandle.classList.add('text-success');
end;
procedure TFViewAddCustomer.AddressEditMode;
// Enables Shipping Address fields while disabling customer fields.
begin
xdwdsShipTo.Edit;
FViewMain.change := true;
btnDelete.Enabled := false;
btnClose.Enabled := false;
btnSave.Enabled := false;
btnCancel.Enabled := false;
btnEdit.Enabled := false;
btnAdd.Enabled := false;
btnShipDelete.Enabled := false;
btnShipSave.Enabled := true;
btnShipCancel.Enabled := true;
btnShipEdit.Enabled := false;
btnShipAdd.Enabled := false;
edtShippingAddress.Enabled := true;
edtShippingCity.Enabled := true;
edtShippingState.Enabled := true;
edtShippingZip.Enabled := true;
edtShippingContact.Enabled := true;
edtFirstLine.Enabled := true;
edtName.Enabled := false;
edtShortName.Enabled := false;
edtBillAddress.Enabled := false;
edtBillCity.Enabled := false;
edtBillState.Enabled := false;
edtBillZip.Enabled := false;
edtBillContact.Enabled := false;
dtpStartDate.Enabled := false;
dtpEndDate.Enabled := false;
edtFax.Enabled := false;
edtPhone.enabled := false;
wdblcbRep.Enabled := false;
lblFormState.Caption := 'Edit Address';
lblFormState.ElementHandle.classList.remove('text-danger');
lblFormState.ElementHandle.classList.add('text-success');
end;
procedure TFViewAddCustomer.ViewMode;
// Enables Customer Fields while disabling shipping address fields.
begin
btnAdd.Enabled := true;
btnDelete.Enabled := true;
btnClose.Enabled := true;
btnSave.Enabled := false;
btnCancel.Enabled := false;
btnEdit.Enabled := true;
FViewMain.change := false;
btnShipAdd.Enabled := true;
if not xdwdsShipTo.IsEmpty then
begin
btnShipDelete.Enabled := true;
btnShipEdit.Enabled := true;
end
else
begin
btnShipDelete.Enabled := false;
btnShipEdit.Enabled := false;
end;
btnShipSave.Enabled := false;
btnShipCancel.Enabled := false;
edtName.Enabled := true;
edtShortName.Enabled := true;
edtBillAddress.Enabled := true;
edtBillCity.Enabled := true;
edtBillState.Enabled := true;
edtBillZip.Enabled := true;
edtBillContact.Enabled := true;
dtpStartDate.Enabled := true;
dtpEndDate.Enabled := true;
edtFax.Enabled := true;
edtPhone.Enabled := true;
wdblcbRep.Enabled := true;
lblFormState.Caption := 'View Mode';
lblFormState.ElementHandle.classList.remove('text-success');
lblFormState.ElementHandle.classList.add('text-danger');
end;
end.
\ No newline at end of file
......@@ -175,10 +175,10 @@ begin
Exit('');
Result := '';
asm
var Token = AToken.split('.');
if (Token.length = 3) {
Result = Token[1];
Result = atob(Result);
const parts = AToken.split('.');
if (parts.length === 3) { // <- strict compare
// JWTs use url-safe base64; convert before atob
Result = atob(parts[1].replace(/-/g,'+').replace(/_/g,'/'));
}
end;
end;
......
......@@ -19,7 +19,7 @@ type
FUnauthorizedAccessProc: TUnauthorizedAccessProc;
public
const clientVersion = '0.9.4';
const clientVersion = '0.9.7';
procedure InitApp(SuccessProc: TSuccessProc;
UnauthorizedAccessProc: TUnauthorizedAccessProc);
procedure SetClientConfig(Callback: TVersionCheckCallback);
......
......@@ -3,15 +3,18 @@ unit Utils;
interface
uses
System.Classes, SysUtils, JS, Web, WEBLib.Forms, WEBLib.Toast, DateUtils;
System.Classes, SysUtils, JS, Web, WEBLib.Forms, WEBLib.Toast, DateUtils, WebLib.Dialogs;
procedure ShowStatusMessage(const AMessage, AClass: string; const AElementId: string);
procedure HideStatusMessage(const AElementId: string);
procedure ShowSpinner(SpinnerID: string);
procedure HideSpinner(SpinnerID: string);
procedure ShowErrorModal(msg: string);
function CalculateAge(DateOfBirth: TDateTime): Integer;
function FormatPhoneNumber(PhoneNumber: string): string;
procedure ApplyReportTitle(CurrentReportType: string);
procedure ShowToast(const MessageText: string; const ToastType: string = 'success');
procedure ShowConfirmationModal(msg, leftLabel, rightLabel: string; ConfirmProc: TProc<Boolean>);
// function FormatDollarValue(ValueStr: string): string;
......@@ -65,6 +68,13 @@ begin
SpinnerElement := TJSHTMLElement(document.getElementById(SpinnerID));
if Assigned(SpinnerElement) then
begin
// Move spinner to the <body> if it's not already there
asm
if (SpinnerElement.parentNode !== document.body) {
document.body.appendChild(SpinnerElement);
}
end;
SpinnerElement.classList.remove('d-none');
SpinnerElement.classList.add('d-block');
end;
......@@ -83,6 +93,85 @@ begin
end;
procedure ShowErrorModal(msg: string);
begin
asm
var modal = document.getElementById('main_errormodal');
var label = document.getElementById('main_lblmodal_body');
var reloadBtn = document.getElementById('btn_modal_restart');
if (label) label.innerText = msg;
// Ensure modal is a direct child of <body>
if (modal && modal.parentNode !== document.body) {
document.body.appendChild(modal);
}
// Bind hard reload to button
if (reloadBtn) {
reloadBtn.onclick = function () {
window.location.reload(true); // hard reload, bypass cache
};
}
// Show the Bootstrap modal
var bsModal = new bootstrap.Modal(modal, { keyboard: false });
bsModal.show();
end;
end;
// ShowConfirmationModal displays a two-button modal with custom labels.
// Params:
// - messageText: text shown in the modal body
// - leftButtonText: label for the left button (e.g., "Cancel")
// - rightButtonText: label for the right button (e.g., "Delete")
// - callback: procedure(confirmed: Boolean); confirmed = True if right button clicked
//
// Example:
// ShowConfirmationModal('Delete this?', 'Cancel', 'Delete',
// procedure(confirmed: Boolean)
// begin
// if confirmed then DeleteOrder();
// end);
procedure ShowConfirmationModal(msg, leftLabel, rightLabel: string; ConfirmProc: TProc<Boolean>);
begin
asm
var modal = document.getElementById('main_confirmation_modal');
var body = document.getElementById('main_modal_body');
var btnLeft = document.getElementById('btn_confirm_left');
var btnRight = document.getElementById('btn_confirm_right');
var bsModal;
if (body) body.innerText = msg;
if (btnLeft) btnLeft.innerText = leftLabel;
if (btnRight) btnRight.innerText = rightLabel;
if (modal && modal.parentNode !== document.body) {
document.body.appendChild(modal);
}
btnLeft.onclick = null;
btnRight.onclick = null;
btnLeft.onclick = function () {
bsModal.hide();
ConfirmProc(true); // user confirmed
};
btnRight.onclick = function () {
bsModal.hide();
ConfirmProc(false); // user canceled
};
bsModal = new bootstrap.Modal(modal, { keyboard: false });
bsModal.show();
end;
end;
function CalculateAge(DateOfBirth: TDateTime): Integer;
var
Today, BirthDate: TJSDate;
......@@ -126,6 +215,71 @@ begin
end;
procedure ShowToast(const MessageText: string; const ToastType: string = 'success');
var
ParsedText, ToastKind, MsgPrefix: string;
Parts: TArray<string>;
begin
ParsedText := MessageText.Trim;
ToastKind := ToastType.ToLower;
// Check for "Success:" or "Failure:" at the start of message
if ParsedText.Contains(':') then
begin
Parts := ParsedText.Split([':'], 2);
MsgPrefix := Parts[0].Trim.ToLower;
if (MsgPrefix = 'success') or (MsgPrefix = 'failure') then
begin
ParsedText := Parts[1].Trim;
if MsgPrefix = 'success' then
ToastKind := 'success'
else
ToastKind := 'danger';
end;
end;
asm
var toastEl = document.getElementById('bootstrapToast');
var toastBody = document.getElementById('bootstrapToastBody');
if (!toastEl || !toastBody) return;
toastBody.innerText = ParsedText;
toastEl.classList.remove('bg-success', 'bg-danger', 'bg-warning', 'bg-info');
toastEl.classList.remove('slide-in');
switch (ToastKind) {
case 'danger':
toastEl.classList.add('bg-danger');
break;
case 'warning':
toastEl.classList.add('bg-warning');
break;
case 'info':
toastEl.classList.add('bg-info');
break;
default:
toastEl.classList.add('bg-success');
}
// Add slide-in animation
toastEl.classList.add('slide-in');
var toast = new bootstrap.Toast(toastEl, { delay: 2500 });
toast.show();
// Remove animation class after it's done (so it can be reapplied)
setTimeout(function() {
toastEl.classList.remove('slide-in');
}, 500);
end;
end;
procedure ApplyReportTitle(CurrentReportType: string);
var
CrimeTitleElement: TJSHTMLElement;
......
object fViewAddItem: TfViewAddItem
Width = 640
Height = 480
OnCreate = WebFormCreate
OnShow = WebFormShow
object WebLabel1: TWebLabel
Left = 8
Top = 81
Width = 95
Height = 15
Caption = 'Search Customers'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object WebLabel3: TWebLabel
Left = 131
Top = 81
Width = 137
Height = 15
Caption = 'Selected Quickbooks Item'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object edtSearch: TWebEdit
Left = 4
Top = 102
Width = 121
Height = 22
ChildOrder = 2
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object TMSFNCGrid1: TTMSFNCGrid
Left = 0
Top = 163
Width = 640
Height = 317
Align = alBottom
ParentDoubleBuffered = False
DoubleBuffered = True
TabOrder = 1
DefaultRowHeight = 40.000000000000000000
FixedColumns = 0
ColumnCount = 4
Options.Bands.Enabled = True
Options.ColumnSize.Stretch = True
Options.Editing.CalcFormat = '%g'
Options.Grouping.CalcFormat = '%g'
Options.Grouping.GroupCountFormat = '(%d)'
Options.IO.XMLEncoding = 'ISO-8859-1'
Options.Mouse.ClickMargin = 0
Options.Mouse.ColumnSizeMargin = 6
Options.Mouse.RowSizeMargin = 6
Columns = <
item
BorderWidth = 1
FixedFont.Charset = DEFAULT_CHARSET
FixedFont.Color = 4539717
FixedFont.Height = -11
FixedFont.Name = 'Segoe UI'
FixedFont.Style = [fsBold]
Font.Charset = DEFAULT_CHARSET
Font.Color = 8026746
Font.Height = -11
Font.Name = 'Segoe UI'
Font.Style = []
ID = ''
Width = 90.000000000000000000
end
item
BorderWidth = 1
FixedFont.Charset = DEFAULT_CHARSET
FixedFont.Color = 4539717
FixedFont.Height = -11
FixedFont.Name = 'Segoe UI'
FixedFont.Style = [fsBold]
Font.Charset = DEFAULT_CHARSET
Font.Color = 8026746
Font.Height = -11
Font.Name = 'Segoe UI'
Font.Style = []
ID = ''
Width = 150.000000000000000000
end
item
BorderWidth = 1
FixedFont.Charset = DEFAULT_CHARSET
FixedFont.Color = 4539717
FixedFont.Height = -11
FixedFont.Name = 'Segoe UI'
FixedFont.Style = [fsBold]
Font.Charset = DEFAULT_CHARSET
Font.Color = 8026746
Font.Height = -11
Font.Name = 'Segoe UI'
Font.Style = []
ID = ''
Width = 200.000000000000000000
end
item
BorderWidth = 1
FixedFont.Charset = DEFAULT_CHARSET
FixedFont.Color = 4539717
FixedFont.Height = -11
FixedFont.Name = 'Segoe UI'
FixedFont.Style = [fsBold]
Font.Charset = DEFAULT_CHARSET
Font.Color = 8026746
Font.Height = -11
Font.Name = 'Segoe UI'
Font.Style = []
ID = ''
Width = 181.000000000000000000
end
item
BorderWidth = 1
FixedFont.Charset = DEFAULT_CHARSET
FixedFont.Color = 4539717
FixedFont.Height = -11
FixedFont.Name = 'Segoe UI'
FixedFont.Style = [fsBold]
Font.Charset = DEFAULT_CHARSET
Font.Color = 8026746
Font.Height = -11
Font.Name = 'Segoe UI'
Font.Style = []
ID = ''
Width = 90.000000000000000000
end>
DefaultFont.Charset = DEFAULT_CHARSET
DefaultFont.Color = clWindowText
DefaultFont.Height = -11
DefaultFont.Name = 'Segoe UI'
DefaultFont.Style = []
TopRow = 1
Appearance.FixedLayout.Fill.Color = 16380654
Appearance.FixedLayout.Font.Charset = DEFAULT_CHARSET
Appearance.FixedLayout.Font.Color = 4539717
Appearance.FixedLayout.Font.Height = -13
Appearance.FixedLayout.Font.Name = 'Segoe UI'
Appearance.FixedLayout.Font.Style = [fsBold]
Appearance.NormalLayout.Fill.Color = 16578806
Appearance.NormalLayout.Font.Charset = DEFAULT_CHARSET
Appearance.NormalLayout.Font.Color = 8026746
Appearance.NormalLayout.Font.Height = -11
Appearance.NormalLayout.Font.Name = 'Segoe UI'
Appearance.NormalLayout.Font.Style = []
Appearance.GroupLayout.Fill.Color = 12817262
Appearance.GroupLayout.Font.Charset = DEFAULT_CHARSET
Appearance.GroupLayout.Font.Color = clBlack
Appearance.GroupLayout.Font.Height = -11
Appearance.GroupLayout.Font.Name = 'Segoe UI'
Appearance.GroupLayout.Font.Style = []
Appearance.SummaryLayout.Fill.Color = 14009785
Appearance.SummaryLayout.Font.Charset = DEFAULT_CHARSET
Appearance.SummaryLayout.Font.Color = clBlack
Appearance.SummaryLayout.Font.Height = -11
Appearance.SummaryLayout.Font.Name = 'Segoe UI'
Appearance.SummaryLayout.Font.Style = []
Appearance.SelectedLayout.Fill.Color = 16441019
Appearance.SelectedLayout.Font.Charset = DEFAULT_CHARSET
Appearance.SelectedLayout.Font.Color = 4539717
Appearance.SelectedLayout.Font.Height = -11
Appearance.SelectedLayout.Font.Name = 'Segoe UI'
Appearance.SelectedLayout.Font.Style = []
Appearance.FocusedLayout.Fill.Color = 16039284
Appearance.FocusedLayout.Font.Charset = DEFAULT_CHARSET
Appearance.FocusedLayout.Font.Color = 4539717
Appearance.FocusedLayout.Font.Height = -11
Appearance.FocusedLayout.Font.Name = 'Segoe UI'
Appearance.FocusedLayout.Font.Style = []
Appearance.FixedSelectedLayout.Fill.Color = clLightsteelblue
Appearance.FixedSelectedLayout.Font.Charset = DEFAULT_CHARSET
Appearance.FixedSelectedLayout.Font.Color = clBlack
Appearance.FixedSelectedLayout.Font.Height = -11
Appearance.FixedSelectedLayout.Font.Name = 'Segoe UI'
Appearance.FixedSelectedLayout.Font.Style = []
Appearance.BandLayout.Fill.Color = 16711679
Appearance.BandLayout.Font.Charset = DEFAULT_CHARSET
Appearance.BandLayout.Font.Color = 8026746
Appearance.BandLayout.Font.Height = -11
Appearance.BandLayout.Font.Name = 'Segoe UI'
Appearance.BandLayout.Font.Style = []
Appearance.ProgressLayout.Format = '%.0f%%'
LeftCol = 0
ScrollMode = scmItemScrolling
DesignTimeSampleData = True
OnCellClick = TMSFNCGrid1CellClick
end
object btnCancel: TWebButton
Left = 544
Top = 101
Width = 96
Height = 25
Caption = 'Cancel'
ChildOrder = 5
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnClick = btnCancelClick
end
object btnConfirm: TWebButton
Left = 446
Top = 101
Width = 96
Height = 25
Caption = 'Select'
ChildOrder = 5
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnClick = btnConfirmClick
end
object edtNotification: TWebEdit
Left = 4
Top = 16
Width = 510
Height = 22
HelpType = htKeyword
TabStop = False
ChildOrder = 8
ElementFont = efCSS
Enabled = False
Font.Charset = ANSI_CHARSET
Font.Color = clRed
Font.Height = -13
Font.Name = 'Arial'
Font.Style = []
HeightPercent = 100.000000000000000000
HideSelection = False
ParentFont = False
TabOrder = 1
WidthPercent = 100.000000000000000000
end
object edtName: TWebEdit
Left = 131
Top = 102
Width = 142
Height = 22
ChildOrder = 1
Enabled = False
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object XDataWebClient1: TXDataWebClient
Connection = DMConnection.ApiConnection
Left = 612
Top = 47
end
object xdwdsCustomers: TXDataWebDataSet
Connection = DMConnection.ApiConnection
Left = 166
Top = 129
object xdwdsCustomersqb_items_id: TStringField
FieldName = 'qb_items_id'
end
object xdwdsCustomersqb_item_name: TStringField
FieldName = 'qb_item_name'
end
object xdwdsCustomersitem_desc: TStringField
FieldName = 'item_desc'
end
object xdwdsCustomersstatus: TStringField
FieldName = 'status'
end
object xdwdsCustomersqb_items_qb_id: TStringField
FieldName = 'qb_items_qb_id'
end
end
object wdsCustomers: TWebDataSource
DataSet = xdwdsCustomers
Left = 104
Top = 135
end
end
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<title>TMS Web Project</title>
<style>
</style>
</head>
<body>
</body>
</html>
\ No newline at end of file
unit View.AddItem;
interface
uses
System.SysUtils, System.Generics.Collections, System.Classes, JS, Web, WEBLib.Graphics, WEBLib.Controls,
WEBLib.Forms, WEBLib.Dialogs, WEBLib.Menus, WEBLib.ExtCtrls, WEBLib.StdCtrls,
WEBLib.JSON, Auth.Service, XData.Web.Client, WebLib.Storage,
ConnectionModule, App.Types, Vcl.StdCtrls, Vcl.Controls, WEBLib.DBCtrls,
Data.DB, XData.Web.JsonDataset, XData.Web.Dataset, WEBLib.DB, VCL.TMSFNCTypes, VCL.TMSFNCUtils,
VCL.TMSFNCGraphics, VCL.TMSFNCGraphicsTypes, VCL.TMSFNCGridCell,
VCL.TMSFNCGridOptions, VCL.TMSFNCCustomControl, VCL.TMSFNCCustomScrollControl,
VCL.TMSFNCGridData, VCL.TMSFNCCustomGrid, VCL.TMSFNCGrid, Utils;
type
TfViewAddItem = class(TWebForm)
WebLabel1: TWebLabel;
WebLabel3: TWebLabel;
edtSearch: TWebEdit;
TMSFNCGrid1: TTMSFNCGrid;
btnCancel: TWebButton;
btnConfirm: TWebButton;
edtNotification: TWebEdit;
edtName: TWebEdit;
XDataWebClient1: TXDataWebClient;
xdwdsCustomers: TXDataWebDataSet;
wdsCustomers: TWebDataSource;
xdwdsCustomersqb_items_id: TStringField;
xdwdsCustomersqb_item_name: TStringField;
xdwdsCustomersitem_desc: TStringField;
xdwdsCustomersstatus: TStringField;
xdwdsCustomersqb_items_qb_id: TStringField;
procedure WebFormCreate(Sender: TObject);
procedure WebFormShow(Sender: TObject);
procedure TMSFNCGrid1CellClick(Sender: TObject; ACol, ARow: Integer);
procedure btnConfirmClick(Sender: TObject);
procedure btnCancelClick(Sender: TObject);
private
{ Private declarations }
[async] procedure getItems();
procedure PopulateGridManually();
[async] procedure SendItemToServer();
public
{ Public declarations }
notification: string;
end;
var
fViewAddItem: TfViewAddItem;
implementation
{$R *.dfm}
procedure TfViewAddItem.WebFormCreate(Sender: TObject);
begin
if not DMConnection.ApiConnection.Connected then
begin
DMConnection.ApiConnection.OpenAsync;
console.log('report requirements connection open')
end;
end;
procedure TfViewAddItem.WebFormShow(Sender: TObject);
begin
//Utils.ShowSpinner('spinner');
getItems();
end;
procedure TfViewAddItem.btnCancelClick(Sender: TObject);
begin
close();
end;
procedure TfViewAddItem.btnConfirmClick(Sender: TObject);
begin
xdwdsCustomers.Locate('qb_item_name', edtName.Text, []);
if edtName.Text = '' then
edtNotification.Text := 'Please Select an Item'
else if xdwdsCustomers.FieldByName('qb_items_id').AsString <> '' then
edtNotification.Text := 'Item Already In Database'
else
SendItemToServer();
end;
procedure TfViewAddItem.getItems;
var
xdcResponse: TXDataClientResponse;
customerList: TJSObject;
i: integer;
begin
// Fetch data from XData service
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.getQBItems', []));
customerList := TJSObject(xdcResponse.Result);
// Load data into TXDataWebDataset
xdwdsCustomers.Close;
xdwdsCustomers.SetJsonData(customerList);
xdwdsCustomers.Open;
// Manually populate the grid
PopulateGridManually;
//Utils.HideSpinner('spinner');
end;
procedure TFViewAddItem.PopulateGridManually;
// populates the grid with customers manually.
var
RowIndex: Integer;
begin
TMSFNCGrid1.BeginUpdate;
try
TMSFNCGrid1.Clear; // Clear any existing data
// Set up column headers
TMSFNCGrid1.ColumnCount := 4;
TMSFNCGrid1.RowCount := 1;
TMSFNCGrid1.Cells[0, 0] := 'KGOrders ID';
TMSFNCGrid1.Cells[1, 0] := 'Item Name';
TMSFNCGrid1.Cells[2, 0] := 'Item Description';
TMSFNCGrid1.Cells[3, 0] := 'Status';
// Populate the grid with data from the dataset
xdwdsCustomers.First;
RowIndex := 1;
while not xdwdsCustomers.EOF do
begin
TMSFNCGrid1.RowCount := RowIndex + 1;
TMSFNCGrid1.Cells[0, RowIndex] := xdwdsCustomers.FieldByName('qb_items_id').AsString;
TMSFNCGrid1.Cells[1, RowIndex] := xdwdsCustomers.FieldByName('qb_item_name').AsString;
TMSFNCGrid1.Cells[2, RowIndex] := xdwdsCustomers.FieldByName('item_desc').AsString;
TMSFNCGrid1.Cells[3, RowIndex] := xdwdsCustomers.FieldByName('status').AsString;
Inc(RowIndex);
xdwdsCustomers.Next;
end;
finally
TMSFNCGrid1.EndUpdate;
end;
Utils.HideSpinner('spinner');
end;
procedure TfViewAddItem.TMSFNCGrid1CellClick(Sender: TObject; ACol,
ARow: Integer);
begin
edtName.Text := TMSFNCGrid1.Cells[1, ARow];
end;
procedure TFViewAddItem.SendItemToServer;
var
ItemJSON: TJSONObject;
Response: TXDataClientResponse;
jsObj: TJSObject;
begin
ItemJSON := TJSONObject.Create;
ItemJSON.AddPair('qb_item_name', xdwdsCustomers.FieldByName('qb_item_name').AsString);
ItemJSON.AddPair('item_desc', xdwdsCustomers.FieldByName('item_desc').AsString);
ItemJSON.AddPair('status', xdwdsCustomers.FieldByName('status').AsString);
ItemJSON.AddPair('qb_items_qb_id', xdwdsCustomers.FieldByName('qb_items_qb_id').AsString);
ItemJSON.AddPair('mode', 'ADD');
// Utils.ShowSpinner('spinner');
Response := await(XDataWebClient1.RawInvokeAsync('ILookupService.AddItem',
[ItemJSON.ToString]));
jsObj := TJSObject(Response.Result);
notification := string(jsObj['msg']);
// Utils.HideSpinner('spinner');
Close();
end;
end.
\ No newline at end of file
object FAddOrder: TFAddOrder
Width = 871
Height = 477
Height = 428
OnShow = WebFormShow
object WebLabel1: TWebLabel
Left = 4
Top = 81
Top = 49
Width = 95
Height = 15
Caption = 'Search Customers'
......@@ -13,7 +13,7 @@ object FAddOrder: TFAddOrder
end
object WebLabel2: TWebLabel
Left = 135
Top = 81
Top = 49
Width = 113
Height = 15
Caption = 'Selected Customer ID'
......@@ -22,7 +22,7 @@ object FAddOrder: TFAddOrder
end
object WebLabel3: TWebLabel
Left = 283
Top = 81
Top = 49
Width = 134
Height = 15
Caption = 'Selected Customer Name'
......@@ -31,7 +31,7 @@ object FAddOrder: TFAddOrder
end
object edtSearch: TWebEdit
Left = 4
Top = 102
Top = 70
Width = 121
Height = 22
HeightPercent = 100.000000000000000000
......@@ -40,7 +40,7 @@ object FAddOrder: TFAddOrder
end
object edtID: TWebEdit
Left = 135
Top = 102
Top = 70
Width = 142
Height = 22
ChildOrder = 1
......@@ -50,7 +50,7 @@ object FAddOrder: TFAddOrder
end
object TMSFNCGrid1: TTMSFNCGrid
Left = 0
Top = 160
Top = 111
Width = 871
Height = 317
Align = alBottom
......@@ -204,10 +204,11 @@ object FAddOrder: TFAddOrder
ScrollMode = scmItemScrolling
DesignTimeSampleData = True
OnCellClick = TMSFNCGrid1CellClick
ExplicitTop = 112
end
object cbCorrugatedPlate: TWebCheckBox
Left = 4
Top = 49
Top = 17
Width = 113
Height = 22
Caption = 'Corrugated Plate'
......@@ -219,7 +220,7 @@ object FAddOrder: TFAddOrder
end
object cbWebPlate: TWebCheckBox
Left = 134
Top = 49
Top = 17
Width = 83
Height = 22
Caption = 'Web Plate'
......@@ -230,7 +231,7 @@ object FAddOrder: TFAddOrder
end
object btnCancel: TWebButton
Left = 542
Top = 101
Top = 69
Width = 96
Height = 25
Caption = 'Cancel'
......@@ -241,7 +242,7 @@ object FAddOrder: TFAddOrder
end
object btnConfirm: TWebButton
Left = 436
Top = 101
Top = 69
Width = 96
Height = 25
Caption = 'Select'
......@@ -252,7 +253,7 @@ object FAddOrder: TFAddOrder
end
object cbCuttingDie: TWebCheckBox
Left = 239
Top = 49
Top = 17
Width = 83
Height = 22
Caption = 'Cutting Die'
......@@ -261,30 +262,9 @@ object FAddOrder: TFAddOrder
WidthPercent = 100.000000000000000000
OnClick = cbCuttingDieClick
end
object edtNotification: TWebEdit
Left = 4
Top = 16
Width = 510
Height = 22
HelpType = htKeyword
TabStop = False
ChildOrder = 8
ElementFont = efCSS
Enabled = False
Font.Charset = ANSI_CHARSET
Font.Color = clRed
Font.Height = -13
Font.Name = 'Arial'
Font.Style = []
HeightPercent = 100.000000000000000000
HideSelection = False
ParentFont = False
TabOrder = 1
WidthPercent = 100.000000000000000000
end
object edtName: TWebEdit
Left = 283
Top = 102
Top = 70
Width = 142
Height = 22
ChildOrder = 1
......
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<title>TMS Web Project</title>
<style>
</style>
</head>
<body>
</body>
</html>
\ No newline at end of file
<div id="spinner" class="position-absolute top-50 start-50 translate-middle d-none">
<div class="lds-roller">
<div></div><div></div><div></div><div></div>
<div></div><div></div><div></div><div></div>
</div>
</div>
......@@ -11,7 +11,7 @@ uses
VCL.TMSFNCGridOptions, Vcl.Controls, VCL.TMSFNCCustomControl,
VCL.TMSFNCCustomScrollControl, VCL.TMSFNCGridData, VCL.TMSFNCCustomGrid,
VCL.TMSFNCGrid, Vcl.StdCtrls, WEBLib.StdCtrls, XData.Web.Client, Data.DB,
XData.Web.JsonDataset, XData.Web.Dataset, WEBLib.DB, ConnectionModule;
XData.Web.JsonDataset, XData.Web.Dataset, WEBLib.DB, ConnectionModule, Utils;
type
TFAddOrder = class(TWebForm)
......@@ -30,7 +30,6 @@ type
xdwdsCustomersSHORT_NAME: TStringField;
wdsCustomers: TWebDataSource;
cbCuttingDie: TWebCheckBox;
edtNotification: TWebEdit;
xdwdsCustomersstaff_fields_invoice_to: TStringField;
xdwdsCustomersCUSTOMER_ID: TIntegerField;
WebLabel3: TWebLabel;
......@@ -67,25 +66,25 @@ begin
Close;
end;
procedure TFAddOrder.btnConfirmClick(Sender: TObject);
begin
confirm := true;
edtNotification.ElementHandle.style.setProperty('color', '#8B0000', 'important');
if ( ( not cbCorrugatedPlate.Checked ) and ( not cbWebPlate.Checked ) and ( not cbCuttingDie.Checked ) ) then
begin
edtNotification.Text := 'Please Select an Order Type';
ShowToast('Please Select an Order Type', 'danger');
confirm := false;
end;
if edtID.Text = '' then
begin
edtNotification.Text := 'Please Select a Customer';
ShowToast('Please Select a Customer', 'danger');
confirm := false;
end;
if ( ( not cbCorrugatedPlate.Checked ) and ( not cbWebPlate.Checked ) and ( not cbCuttingDie.Checked ) and (edtID.Text = '' )) then
begin
edtNotification.Text := 'Please Select an Order Type and a Customer';
ShowToast('Please Select an Order Type and a Customer', 'danger');
confirm := false;
end;
......@@ -95,6 +94,7 @@ begin
end;
end;
procedure TFAddOrder.WebFormShow(Sender: TObject);
begin
confirm := false;
......@@ -108,23 +108,27 @@ begin
cbCuttingDie.Checked := False;
end;
procedure TFAddOrder.cbCuttingDieClick(Sender: TObject);
begin
cbCorrugatedPlate.Checked := False;
cbWebPlate.Checked := False;
end;
procedure TFAddOrder.cbWebPlateClick(Sender: TObject);
begin
cbCorrugatedPlate.Checked := False;
cbCuttingDie.Checked := False;
end;
procedure TFAddOrder.edtSearchChange(Sender: TObject);
begin
ApplyFilter;
end;
[async] procedure TFAddOrder.getCustomers();
// retrieves customer list from server
var
......@@ -144,6 +148,7 @@ begin
PopulateGridManually;
end;
procedure TFAddOrder.PopulateGridManually;
// populates the grid with customers manually.
var
......@@ -191,6 +196,7 @@ begin
DBID := TMSFNCGrid1.Cells[0, ARow];
end;
procedure TFAddOrder.ApplyFilter;
// filters the grid based on search textbox contents.
var
......
object FViewCustomers: TFViewCustomers
Width = 640
Height = 480
CSSLibrary = cssBootstrap
ElementFont = efCSS
OnCreate = WebFormCreate
object lblEntries: TWebLabel
Left = 12
......@@ -42,6 +44,7 @@ object FViewCustomers: TFViewCustomers
HeightPercent = 100.000000000000000000
Text = '500'
WidthPercent = 100.000000000000000000
OnChange = wcbPageSizeChange
ItemIndex = -1
Items.Strings = (
'100'
......
<div class="container h-100 d-flex flex-column mt-0" style="max-width: 100%; padding-bottom: 0;">
<!-- Alert Section -->
<div class="row">
<div class=col-sm>
<div id="view.login.message" class="alert alert-danger">
<button id="view.login.message.button" type="button" class="btn-close" aria-label="Close"></button>
<span id="view.login.message.label"></span>
</div>
</div>
</div>
<!-- Actions Row -->
<div class="row mt-3 justify-content-center align-items-end">
<div class="col-auto">
......
......@@ -13,7 +13,7 @@ uses
WEBLib.Grids, VCL.TMSFNCTypes, VCL.TMSFNCUtils, VCL.TMSFNCGraphics,
VCL.TMSFNCGraphicsTypes, VCL.TMSFNCGridCell, VCL.TMSFNCGridOptions,
VCL.TMSFNCCustomControl, VCL.TMSFNCCustomScrollControl, VCL.TMSFNCGridData,
VCL.TMSFNCCustomGrid, VCL.TMSFNCGrid;
VCL.TMSFNCCustomGrid, VCL.TMSFNCGrid, VCL.Forms;
type
TFViewCustomers = class(TWebForm)
......@@ -36,13 +36,13 @@ type
procedure btnAddCustomerClick(Sender: TObject);
procedure wdbtcCustomersDblClickCell(Sender: TObject; ACol, ARow: Integer);
procedure edtFilterChange(Sender: TObject);
procedure wcbPageSizeChange(Sender: TObject);
private
{ Private declarations }
procedure GeneratePagination(TotalPages: Integer);
[async] procedure GetCustomers(searchOptions: string);
function GenerateSearchOptions(): string;
procedure HideNotification();
procedure ShowNotification(Notification: string);
procedure ShowSelectCustomerForm();
var
......@@ -75,6 +75,7 @@ begin
newform.Caption := 'Select Customer and Order Type';
newForm.Popup := True;
newForm.Border := fbDialog;
newForm.Position := poScreenCenter;
// used to manage Back button handling to close subform
window.location.hash := 'subform';
......@@ -125,39 +126,32 @@ begin
if PageNumber > 0 then
begin
Utils.ShowSpinner('spinner');
try
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GetCustomers', [searchOptions]));
customerList := TJSObject(xdcResponse.Result);
// Load data into the dataset
xdwdsCustomers.Close;
xdwdsCustomers.SetJsonData(customerList['data']);
xdwdsCustomers.Open;
Utils.HideSpinner('spinner');
customerListLength := integer(customerList['count']);
TotalPages := ( (customerListLength + PageSize - 1) div PageSize);
if customerListLength = 0 then
begin
lblEntries.Caption := 'No entries found';
end
lblEntries.Caption := 'No entries found'
else if (PageNumber * PageSize) < customerListLength then
// Currently these do the same thing. If you want to limit the number of entries
// You will need to edit the server side, and then change this if statement so the label
// Correctly displayes. I believe it is IntToStr(PageSize * PageNum)
begin
lblEntries.Caption := 'Showing entries ' + IntToStr((PageNumber - 1) * PageSize + 1) +
' - ' + IntToStr(customerListLength) +
' of ' + IntToStr(customerListLength);
end
else if (PageNumber * PageSize) >= customerListLength then
begin
' of ' + IntToStr(customerListLength)
else
lblEntries.Caption := 'Showing entries ' + IntToStr((PageNumber - 1) * PageSize + 1) +
' - ' + IntToStr(customerListLength) +
' of ' + IntToStr(customerListLength);
except
on E: EXDataClientRequestException do
Utils.ShowErrorModal('Could not retrieve customers: ' + E.ErrorResult.ErrorMessage);
end;
Utils.HideSpinner('spinner');
end;
end;
......@@ -180,34 +174,13 @@ begin
end;
procedure TFViewCustomers.ShowNotification(Notification: string);
var
splitNotification: TArray<string>;
procedure TFViewCustomers.wcbPageSizeChange(Sender: TObject);
begin
if Notification <> '' then
begin
splitNotification := Notification.Split([':']);
if(splitNotification[0] = 'Success') then
begin
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-danger');
messageDiv.classList.add('alert-success');
end;
end
else
begin
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-success');
messageDiv.classList.add('alert-danger');
end;
end;
lblMessage.Caption := splitNotification[1];
pnlMessage.ElementHandle.hidden := False;
end;
PageSize := StrToInt(wcbPageSize.Text);
getCustomers(GenerateSearchOptions());
end;
procedure TFViewCustomers.wdbtcCustomersDblClickCell(Sender: TObject; ACol,
ARow: Integer);
begin
......
......@@ -108,6 +108,7 @@ object FViewEditUser: TFViewEditUser
ElementID = 'edtconfirmpassword'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnChange = edtConfirmPasswordChange
end
object edtEmail: TWebEdit
Left = 96
......@@ -128,6 +129,7 @@ object FViewEditUser: TFViewEditUser
ElementID = 'edtpassword'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnChange = edtPasswordChange
end
object btnConfirm: TWebButton
Left = 96
......@@ -187,48 +189,6 @@ object FViewEditUser: TFViewEditUser
WidthPercent = 100.000000000000000000
OnClick = btnCancelClick
end
object btnConfirmChanges: TWebButton
Left = 100
Top = 330
Width = 96
Height = 25
Caption = 'Confirm'
ChildOrder = 16
ElementID = 'btn_confirm_changes'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnClick = btnConfirmChangesClick
end
object pnlMessage: TWebPanel
Left = 482
Top = 4
Width = 121
Height = 33
ElementID = 'view.login.message'
ChildOrder = 17
TabOrder = 8
object lblMessage: TWebLabel
Left = 16
Top = 11
Width = 46
Height = 15
Caption = 'Message'
ElementID = 'view.login.message.label'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object btnCloseNotification: TWebButton
Left = 96
Top = 3
Width = 22
Height = 25
ChildOrder = 1
ElementID = 'view.login.message.button'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnClick = btnCloseNotificationClick
end
end
object cbStatus: TWebCheckBox
Left = 96
Top = 162
......
<div class="row">
<div class="col-12">
<div class="container mt-4">
<div class="row justify-content-center">
<div class="col-12 col-md-8">
<div class="container">
<!-- Edit-User form -->
<div class="row">
<div class=col-sm>
<div id="view.login.message" class="alert alert-danger">
<button id="view.login.message.button" type="button" class="btn-close" aria-label="Close"></button>
<span id="view.login.message.label"></span>
</div>
</div>
</div>
<form class="form-inline">
<div class="row">
<div class="col-sm">
<label class= 'pe-2' style="font-weight: 700;font-size: 15px;"id="lblfullname">Full Name:</label>
<input id="edtfullname" class= "form-control input-sm" width='50%'/>
</div>
<div class="col-sm">
<label class= 'pe-2' style="font-weight: 700;font-size: 15px"id="lblusername">Username:</label>
<input id="edtusername" class="form-control input-sm" width='50%'>
</div>
</div>
</form>
<form class="form-inline">
<div class="row">
<div class="col-sm">
<label class='pe-2' style="font-weight: 700;font-size: 15px;"id="lblpassword">Password:</label>
<input id="edtpassword" class= "form-control input-sm" width='50%'/>
</div>
<div class="col-sm">
<label class= 'pe-2' style="font-weight: 700;font-size: 15px"id="lblconfirm">Confirm Password:</label>
<input class="form-control input-sm" id="edtconfirmpassword">
</div>
</div>
<div class="col-lg-10 col-xl-8 mx-auto">
<form id="edituserform" class="row g-3 needs-validation" novalidate>
<div class="col-md-6">
<label id="lblfullname" for="edtfullname" class="form-label">Full&nbsp;Name</label>
<input id="edtfullname" class="form-control" required>
<div class="invalid-feedback">Full Name is required.</div>
</div>
<div class="col-md-6">
<label id="lblusername" for="edtusername" class="form-label">Username</label>
<input id="edtusername" class="form-control" required>
<div class="invalid-feedback">Username is required.</div>
</div>
<div class="col-md-6">
<label id="lblpassword" for="edtpassword" class="form-label">Password</label>
<input id="edtpassword" type="password" class="form-control" required>
<div class="invalid-feedback">Passwords must match.</div>
</div>
<div class="col-md-6">
<label id="lblconfirm" for="edtconfirmpassword" class="form-label">Confirm&nbsp;Password</label>
<input id="edtconfirmpassword" type="password" class="form-control" required disabled>
<div class="invalid-feedback">Passwords must match.</div>
</div>
<div class="col-md-6">
<label id="lblemail" for="edtemail" class="form-label">Email&nbsp;Address</label>
<input id="edtemail" type="email" class="form-control" required>
<div class="invalid-feedback">Valid email is required.</div>
</div>
<div class="col-md-6">
<label id="lblQB" for="edtQB" class="form-label">QuickBooks&nbsp;ID</label>
<input id="edtQB" class="form-control">
</div>
<div class="col-md-6">
<label id="lblrights" for="edtrights" class="form-label">System&nbsp;Rights</label>
<input id="edtrights" class="form-control">
</div>
<div class="col-md-6">
<label id="lblaccess" for="cbaccess" class="form-label">Access&nbsp;Type</label>
<select id="cbaccess" class="form-select" required>
<option selected disabled value="">Choose...</option>
<option value="ALL">All</option>
<option value="LIMITED">Limited</option>
</select>
<div class="invalid-feedback">Please select an access type.</div>
</div>
<div class="col-md-6">
<div class="form-check pt-2">
<input id="cbstatus" class="form-check-input" type="checkbox">
<label id="lblactive" for="cbstatus" class="form-check-label">Active</label>
</div>
</div>
<div class="d-flex gap-2 mt-4">
<button id="btnconfirm" type="button" class="btn btn-primary flex-grow-1">
Confirm
</button>
<button id="btncancel" type="button" class="btn btn-outline-secondary flex-grow-1">
Cancel
</button>
</div>
</form>
<form class="form-inline">
<div class="row">
<div class="col-sm">
<label class='pe-2' style="font-weight: 700;font-size: 15px;" id="lblemail">Email Address:</label>
<input id="edtemail" class= "form-control input-sm" width='50%'/>
</div>
<div class="col-sm">
<label class= 'pe-2' style="font-weight: 700;font-size: 15px"id="lblQB">Quickbook ID:</label>
<input class="form-control input-sm" id="edtQB">
</div>
</div>
</form>
<div class="row">
<div class="col-6">
<label class='pe-2' style="font-weight: 700;font-size: 15px;" id="lblrights">System Rights:</label>
<input id="edtrights" class= "form-control input-sm" width='50%'/>
</div>
</div>
<div class="row">
<div class="col-sm py-3">
<label class= 'pe-2' style="font-weight: 700;font-size: 15px"id="lblaccess">Access Type:</label>
<select class="custom-select-large" id="cbaccess" style="font-size: 1.00rem;"></select>
</div>
</div>
<div class="row">
<div class="col-sm">
<form class='form-inline'>
<div class="col-sm">
<div class="form-cells"><input type="checkbox" id="cbstatus"></div>
<div class="form-cells ps-1 py-2"><label style="font-weight: 700;font-size: 15px" id="lblactive">Active></label></div>
</div>
</form>
</div>
<div class="col-sm-12 py-2">
<button class="py-2" id="btnconfirm" style="font-weight: 700;font-size: 15px";>Confirm</button>
<button class="py-2" id="btncancel" style="font-weight: 700;font-size: 15px";>Cancel</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Confirmation modal -->
<div class="modal fade" id="confirmation_modal" tabindex="-1" aria-labelledby="confirmation_modal_label" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
......@@ -95,3 +94,4 @@
</div>
</div>
</div>
......@@ -26,10 +26,6 @@ type
XDataWebClient1: TXDataWebClient;
btnCancel: TWebButton;
WebTimer1: TWebTimer;
btnConfirmChanges: TWebButton;
pnlMessage: TWebPanel;
lblMessage: TWebLabel;
btnCloseNotification: TWebButton;
lblactive: TWebLabel;
cbStatus: TWebCheckBox;
lblRights: TWebLabel;
......@@ -42,8 +38,8 @@ type
procedure btnConfirmClick(Sender: TObject);
procedure btnCancelClick(Sender: TObject);
procedure WebTimer1Timer(Sender: TObject);
procedure btnConfirmChangesClick(Sender: TObject);
procedure btnCloseNotificationClick(Sender: TObject);
procedure edtPasswordChange(Sender: TObject);
procedure edtConfirmPasswordChange(Sender: TObject);
private
{ Private declarations }
FMessage: string;
......@@ -59,8 +55,7 @@ type
QB: string;
[async] procedure EditUser();
[async] function AddUser(): string;
procedure HideNotification();
procedure ShowNotification(notification: string);
procedure ValidatePasswords;
public
{ Public declarations }
Info: string;
......@@ -84,26 +79,12 @@ Utils;
procedure TFViewEditUser.btnCancelClick(Sender: TObject);
// Cancels the edit or addition
begin
Info := 'Failure:Changes discarded!';
Info := 'Failure: Changes discarded!';
FViewMain.ShowUserForm(Info);
end;
procedure TFViewEditUser.btnCloseNotificationClick(Sender: TObject);
begin
HideNotification;
end;
procedure TFViewEditUSer.btnConfirmChangesClick(Sender: TObject);
begin
if Mode = 'Edit' then
EditUser()
else
AddUser();
WebTimer1.Enabled := true;
Utils.ShowSpinner('spinner');
end;
function TFViewEditUser.AddUser(): string;
function TFViewEditUser.AddUser: string;
// Sends UserInfo over to the server so it can be added to the database
var
userInfo: string;
......@@ -120,26 +101,17 @@ begin
'&rights=' + edtRights.Text +
'&QB=' + edtQB.Text;
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.AddUser',
[userInfo]));
try
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.AddUser', [userInfo]));
responseString := TJSObject(xdcResponse.Result);
Info := string(responseString['value']);
end;
procedure TFViewEditUser.HideNotification;
begin
pnlMessage.ElementHandle.hidden := True;
end;
procedure TFViewEditUser.ShowNotification(Notification: string);
begin
if Notification <> '' then
begin
lblMessage.Caption := Notification;
pnlMessage.ElementHandle.hidden := False;
except
on E: EXDataClientRequestException do
Utils.ShowErrorModal('Could not add user: ' + E.ErrorResult.ErrorMessage);
end;
end;
procedure TFViewEditUser.EditUser();
// Sends EditOptions over to the server so the given user can be editted
var
......@@ -167,6 +139,16 @@ begin
end;
procedure TFViewEditUser.edtConfirmPasswordChange(Sender: TObject);
begin
ValidatePasswords;
end;
procedure TFViewEditUser.edtPasswordChange(Sender: TObject);
begin
ValidatePasswords;
end;
class function TFViewEditUser.CreateForm(AElementID, Mode, Username, Password, Name, Status, Email,
Access, Rights, Perspective, QB: string): TWebForm;
// Autofills known information about a user on create
......@@ -194,9 +176,7 @@ procedure TFViewEditUser.WebFormCreate(Sender: TObject);
// Autofills known information about a user on create
begin
if FMessage <> '' then
ShowNotification(FMessage)
else
HideNotification;
ShowToast(FMessage);
edtUsername.Text := Username;
edtFullName.Text := FullName;
if Mode = 'Edit' then
......@@ -221,132 +201,79 @@ begin
FViewMain.ShowUserForm(Info);
end
else
showNotification(Info);
showToast(Info);
console.log('Info at Timer:' + Info);
end;
procedure TFViewEditUser.btnConfirmClick(Sender: TObject);
// Confirms the edit or addition
var
checkString: string;
charIndex: integer;
phoneNum: string;
FormEl: TJSHTMLFormElement;
begin
{ checkString := edtFullName.Text + edtUsername.Text + edtPassword.Text
+ edtConfirmPassword.Text + edtPhoneNumber.Text + edtEmail.Text;
if string(edtFullName.Text).IsEmpty then
begin
ShowNotification('Full Name field is blank!');
exit;
end;
FormEl := TJSHTMLFormElement(document.getElementById('edituserform'));
if string(edtUsername.Text).IsEmpty then
if not FormEl.checkValidity then
begin
ShowNotification('Username field is blank!');
exit;
FormEl.classList.add('was-validated');
Exit;
end;
if string(edtPassword.Text).IsEmpty then
begin
ShowNotification('Password field is blank!');
exit;
end;
if string(edtConfirmPassword.Text).IsEmpty then
begin
ShowNotification('Please confirm your password!');
exit;
end;
if string(edtPhoneNumber.Text).IsEmpty then
begin
ShowNotification('Phone Number field is blank!');
exit;
end;
if string(edtEmail.Text).IsEmpty then
begin
ShowNotification('Email field is blank!');
exit;
end;
Utils.ShowSpinner('spinner');
if checkString.Contains('&') then
begin
ShowNotification('No fields may contain "&&"!');
exit;
end;
if Mode = 'Edit' then
EditUser
else
AddUser;
if string(edtEmail.Text).Contains('@') = false then
begin
ShowNotification('Please enter a valid email address');
exit;
end;
WebTimer1.Enabled := True;
end;
if (length(string(edtEmail.Text).Split(['@'])) <> 2) or (string(edtEmail.text).CountChar('@') > 1) then
begin
ShowNotification('Please enter a valid email address');
exit;
end;
phoneNum := edtPhoneNumber.Text;
procedure TFViewEditUser.ValidatePasswords;
var
Pwd, Confirm: string;
PwdInput, ConfirmInput: TJSHTMLInputElement;
begin
PwdInput := TJSHTMLInputElement(edtPassword.ElementHandle);
ConfirmInput := TJSHTMLInputElement(edtConfirmPassword.ElementHandle);
if (not phoneNum.Contains('(')) or (not phoneNum.Contains(')')) or (not phoneNum.Contains('-')) then
begin
ShowNotification('Please enter a valid phone number');
exit;
end;
Pwd := PwdInput.value.Trim;
Confirm := ConfirmInput.value.Trim;
if (phoneNum.CountChar('(') <> 1) or (phoneNum.CountChar(')') <> 1) or (phoneNum.CountChar('-') <> 1) or (phoneNum.CountChar(' ') > 1) then
// Disable confirm until password exists
if Pwd = '' then
begin
ShowNotification('Please enter a valid phone number');
exit;
end;
phoneNum := phoneNum.Replace('(', '');
phoneNum := phoneNum.Replace(')', '');
phoneNum := phoneNum.Replace('-', '');
phoneNum := phoneNum.Replace(' ', '');
if(length(phoneNum) <> 10) then
ConfirmInput.disabled := True;
ConfirmInput.value := '';
ConfirmInput.setCustomValidity('');
ConfirmInput.classList.remove('is-invalid');
ConfirmInput.classList.remove('is-valid');
end
else
begin
ShowNotification('Please enter a valid phone number');
exit;
end;
ConfirmInput.disabled := False;
for CharIndex := 1 to Length(phoneNum) do
// Live match check
if Confirm = '' then
begin
if not (phoneNum[CharIndex] in ['0' .. '9']) then
begin
console.log('here');
ShowNotification('Please enter a valid phone number');
exit;
end;
end;
if edtPassword.Text <> edtConfirmPassword.Text then
ConfirmInput.setCustomValidity('');
ConfirmInput.classList.remove('is-invalid');
ConfirmInput.classList.remove('is-valid');
end
else if Confirm = Pwd then
begin
ShowNotification('Passwords must match!');
exit;
end;
if (length(edtPassword.Text) > 20) or (length(edtPassword.Text) < 6) then
ConfirmInput.setCustomValidity('');
ConfirmInput.classList.add('is-valid');
ConfirmInput.classList.remove('is-invalid');
end
else
begin
ShowNotification('Passwords must be between 6-20 characters!');
exit;
ConfirmInput.setCustomValidity('Passwords must match');
ConfirmInput.classList.add('is-invalid');
ConfirmInput.classList.remove('is-valid');
end;
}
asm
var modal = document.getElementById('confirmation_modal');
// ensure the modal is directly under <body>
if (modal && modal.parentNode !== document.body) {
document.body.appendChild(modal);
}
var bsModal = new bootstrap.Modal(modal, {
keyboard: false
});
bsModal.show();
end;
end;
end.
......@@ -41,20 +41,19 @@ object FViewItems: TFViewItems
'25'
'50')
end
object btnApply: TWebButton
Left = 478
Top = 128
object btnAdd: TWebButton
Left = 565
Top = 318
Width = 96
Height = 25
Caption = 'Apply'
Caption = 'Add'
ChildOrder = 7
ElementClassName = 'btn btn-light'
ElementID = 'btnapply'
ElementID = 'btnadd'
ElementFont = efCSS
HeightStyle = ssAuto
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnClick = btnApplyClick
OnClick = btnAddClick
end
object edtName: TWebEdit
Left = 342
......@@ -97,6 +96,70 @@ object FViewItems: TFViewItems
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object btnSave: TWebButton
Left = 565
Top = 228
Width = 96
Height = 25
Caption = 'Save'
ChildOrder = 79
ElementID = 'btnconfirm'
ElementFont = efCSS
ElementPosition = epRelative
Enabled = False
HeightStyle = ssAuto
HeightPercent = 100.000000000000000000
Role = 'null'
WidthPercent = 100.000000000000000000
OnClick = btnSaveClick
end
object btnCancel: TWebButton
Left = 565
Top = 256
Width = 96
Height = 25
Caption = 'Cancel'
ChildOrder = 79
ElementID = 'btncancel'
ElementFont = efCSS
ElementPosition = epRelative
Enabled = False
HeightStyle = ssAuto
HeightPercent = 100.000000000000000000
Role = 'null'
WidthPercent = 100.000000000000000000
OnClick = btnCancelClick
end
object btnDelete: TWebButton
Left = 565
Top = 197
Width = 96
Height = 25
Caption = 'Delete'
ChildOrder = 79
ElementID = 'btndelete'
ElementFont = efCSS
Enabled = False
HeightStyle = ssAuto
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnClick = btnDeleteClick
end
object btnEdit: TWebButton
Left = 565
Top = 287
Width = 96
Height = 25
Caption = 'Edit'
ChildOrder = 83
ElementID = 'btnedit'
ElementFont = efCSS
Enabled = False
HeightStyle = ssAuto
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnClick = btnEditClick
end
object XDataWebClient1: TXDataWebClient
Connection = DMConnection.ApiConnection
Left = 426
......
<nav class="navbar navbar-expand navbar-light bg-light sticky-top" style="z-index: 100;">
<div class="container-fluid ps-0">
<ul class="navbar-nav me-auto ps-2">
<li class="nav-item pe-2">
<button id="btnadd" class="btn btn-primary btn-sm">Add</button>
</li>
<li class="nav-item pe-2">
<button id="btnedit" class="btn btn-primary btn-sm">Edit</button>
</li>
<li class="nav-item pe-2">
<button id="btndelete" class="btn btn-danger btn-sm">Delete</button>
</li>
<li class="nav-item pe-2">
<button id="btnconfirm" class="btn btn-success btn-sm">Save</button>
</li>
<li class="nav-item pe-2">
<button id="btncancel" class="btn btn-danger btn-sm">Cancel</button>
</li>
</ul>
</div>
</nav>
<div class="row">
<div class="col-12">
<div class="container mt-4">
......@@ -30,13 +51,10 @@
<div class="col-sm-5">
<label class="py-2" style="font-weight: 700;">Show <select class="custom-select" id="wcbpagesize" style="font-size: 1.00rem;"></select> entries</label>
</div>
<div class="col-sm-5">
<button class= "ps-3" id="btnapply"></button>
</div>
</div>
</form>
<table class="table table-responsive table-striped table-bordered" id="tblPhoneGrid">
<table class="table table-responsive table-striped table-hover table-bordered" id="tblPhoneGrid">
<thead class="thead-dark">
<tr>
<th scope="col">ID</th>
......
......@@ -2,7 +2,7 @@
// to sort the entries, filter their search, and search for a specific person.
// Authors:
// Cameron Hayes
// Mac ...
// Mac Stephens
unit View.Items;
......@@ -12,7 +12,7 @@ uses
System.SysUtils, System.Classes, Web, WEBLib.Graphics, WEBLib.Forms, WEBLib.Dialogs,
Vcl.Controls, Vcl.StdCtrls, WEBLib.StdCtrls, WEBLib.Controls, WEBLib.Grids, WebLib.Lists,
XData.Web.Client, WEBLib.ExtCtrls, DB, XData.Web.JsonDataset,
XData.Web.Dataset, XData.Web.Connection, Vcl.Forms, DateUtils, WebAudio;
XData.Web.Dataset, XData.Web.Connection, Vcl.Forms, DateUtils;
type
TFViewItems = class(TWebForm)
......@@ -20,21 +20,30 @@ type
XDataWebDataSet1: TXDataWebDataSet;
lblEntries: TWebLabel;
wcbPageSize: TWebComboBox;
btnApply: TWebButton;
btnAdd: TWebButton;
edtName: TWebEdit;
edtDescription: TWebEdit;
cbStatus: TWebCheckBox;
btnSave: TWebButton;
btnCancel: TWebButton;
btnDelete: TWebButton;
btnEdit: TWebButton;
procedure WebFormCreate(Sender: TObject);
procedure btnApplyClick(Sender: TObject);
procedure btnAddClick(Sender: TObject);
procedure wcbPageSizeChange(Sender: TObject);
procedure btnEditClick(Sender: TObject);
procedure btnSaveClick(Sender: TObject);
procedure btnDeleteClick(Sender: TObject);
procedure btnCancelClick(Sender: TObject);
private
FChildForm: TWebForm;
procedure AddRowToTable(ID, Name, Description, Status: string);
procedure ClearTable();
procedure GeneratePagination(TotalPages: Integer);
function GenerateSearchOptions(): string;
procedure ViewMode();
procedure EditMode();
[async] procedure GetItems(searchOptions: string);
[async] procedure getUser();
[async] procedure AddItem(itemOptions: string);
var
PageNumber: integer;
......@@ -55,7 +64,7 @@ implementation
uses
JS, XData.Model.Classes,
ConnectionModule, Auth.Service, Utils;
ConnectionModule, Auth.Service, Utils, View.AddItem, View.Main;
{$R *.dfm}
......@@ -72,56 +81,102 @@ begin
getItems(GenerateSearchOptions());
end;
procedure TFViewItems.getUser();
var
xdcResponse: TXDataClientResponse;
userList, user: TJSObject;
data: TJSArray;
procedure TFViewItems.ViewMode();
begin
btnAdd.Enabled := true;
btnDelete.Enabled := true;
btnSave.Enabled := false;
btnCancel.Enabled := false;
btnEdit.Enabled := true;
FViewMain.change := false;
edtName.Enabled := false;
edtDescription.enabled := false;
cbStatus.Checked := false;
end;
procedure TFViewItems.EditMode();
begin
FViewMain.change := true;
btnAdd.Enabled := false;
btnDelete.Enabled := false;
btnSave.Enabled := true;
btnCancel.Enabled := True;
btnEdit.Enabled := false;
edtName.Enabled := true;
edtDescription.Enabled := true;
cbStatus.enabled := true;
end;
procedure TFViewItems.AddRowToTable(ID, Name, Description, Status: string);
// Adds rows to the table
// ID: item ID
// Name: item name
// Description: item description
// Status: inactive or active
// Adds one row to #tblPhoneGrid and lets Bootstrap 5.3 highlight the row
// with its built-in `table-active` class when the user clicks it.
var
NewRow, Cell, P, Button, Audio: TJSHTMLElement;
NewRow, Cell: TJSHTMLElement;
begin
NewRow := TJSHTMLElement(document.createElement('tr'));
// Item ID Cell
// Row-select click handler
NewRow.addEventListener('click',
procedure(Event: TJSMouseEvent)
var
TBody : TJSHTMLElement;
Rows : TJSHTMLCollection;
I : Integer;
RowElem : TJSHTMLElement;
begin
// Grab the <tbody> once and cast it
TBody := TJSHTMLElement(
(document.getElementById('tblPhoneGrid') as TJSHTMLElement)
.getElementsByTagName('tbody')[0]
);
// Remove 'table-active' from every existing row
Rows := TBody.children;
for I := 0 to Rows.length - 1 do
begin
RowElem := TJSHTMLElement(Rows.item(I)); // cast Node HTMLElement
RowElem.classList.remove('table-primary');
end;
// Add highlight to the clicked row
TJSHTMLElement(Event.currentTarget).classList.add('table-primary');
end
);
Cell := TJSHTMLElement(document.createElement('td'));
Cell.setAttribute('data-label', 'Item ID');
Cell.innerText := ID;
NewRow.appendChild(Cell);
// Name Cell
Cell := TJSHTMLElement(document.createElement('td'));
Cell.setAttribute('data-label', 'Name');
Cell.innerText := Name;
NewRow.appendChild(Cell);
// Description Cell
Cell := TJSHTMLElement(document.createElement('td'));
Cell.setAttribute('data-label', 'Description');
Cell.innerText := Description;
NewRow.appendChild(Cell);
// Status Cell
Cell := TJSHTMLElement(document.createElement('td'));
Cell.setAttribute('data-label', 'Status');
Cell.innerText := Status;
NewRow.appendChild(Cell);
// Appends new rows to the table body
TJSHTMLElement(document.getElementById('tblPhoneGrid').getElementsByTagName('tbody')[0]).appendChild(NewRow);
TJSHTMLElement(
(document.getElementById('tblPhoneGrid') as TJSHTMLElement)
.getElementsByTagName('tbody')[0]
).appendChild(NewRow);
Utils.HideSpinner('spinner');
end;
procedure TFViewItems.GeneratePagination(TotalPages: Integer);
// Generates pagination for the table.
// TotalPages: Total amount of pages generated by the search
......@@ -306,13 +361,13 @@ begin
if PageNumber > 0 then
begin
Utils.ShowSpinner('spinner');
try
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GetItems',
[searchOptions]));
itemList := TJSObject(xdcResponse.Result);
data := TJSArray(itemList['data']);
itemListLength := integer(itemList['count']);
ClearTable();
Utils.HideSpinner('Spinner');
for i := 0 to data.Length - 1 do
begin
item := TJSObject(data[i]);
......@@ -333,34 +388,78 @@ begin
' of ' + IntToStr(itemListLength);
end;
GeneratePagination(TotalPages);
except
on E: EXDataClientRequestException do
Utils.ShowErrorModal('Could not retrieve items: ' + E.ErrorResult.ErrorMessage);
end;
Utils.HideSpinner('spinner');
end;
end;
procedure TFViewItems.btnApplyClick(Sender: TObject);
procedure TFViewItems.btnAddClick(Sender: TObject);
// Button that effectively functions as a GetItems() button
var
itemOptions: string;
newform: TFViewAddItem;
begin
PageNumber := 1;
PageSize := StrToInt(wcbPageSize.Text);
itemOptions := '&name=' + edtName.Text +
'&description=' + edtDescription.Text +
'&status=' + BoolToStr(cbStatus.Checked);
newform := TFViewAddItem.CreateNew;
console.log('GetItems');
AddItem(itemOptions);
newform.Caption := 'Select Item to Add';
newForm.Popup := True;
newForm.position:= poScreenCenter;
newForm.Border := fbDialog;
// used to manage Back button handling to close subform
window.location.hash := 'subform';
newform.ShowModal(
procedure(AValue: TModalResult)
begin
getItems(generateSearchOptions());
end
);
end;
procedure TFViewItems.btnCancelClick(Sender: TObject);
begin
ShowToast('Editing items is not yet implemented.', 'info');
end;
procedure TFViewItems.btnDeleteClick(Sender: TObject);
begin
ShowToast('Deleting items is no yet implemented.', 'info');
end;
procedure TFViewItems.btnEditClick(Sender: TObject);
begin
ShowToast('Editing items is not yet implemented.', 'info');
//EditMode();
end;
procedure TFViewItems.btnSaveClick(Sender: TObject);
//TODO implement editting items
begin
ShowToast('Editing items is not yet implemented.', 'info');
//ViewMode();
end;
procedure TFViewItems.AddItem(itemOptions: string);
// adds an item to the database.
var
xdcResponse: TXDataClientResponse;
begin
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.AddItem',
[itemOptions]));
try
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.AddItem', [itemOptions]));
getItems(GenerateSearchOptions());
except
on E: EXDataClientRequestException do
Utils.ShowErrorModal('Could not add item: ' + E.ErrorResult.ErrorMessage);
end;
end;
procedure TFViewItems.wcbPageSizeChange(Sender: TObject);
// gets a new amount of items based when the page size is changed
begin
......
......@@ -57,7 +57,7 @@ object FViewMain: TFViewMain
end
object lblAppTitle: TWebLabel
Left = 57
Top = 31
Top = 33
Width = 75
Height = 14
Caption = 'Koehler-Gibson'
......@@ -157,6 +157,12 @@ object FViewMain: TFViewMain
ChildOrder = 3
ElementFont = efCSS
ElementPosition = epIgnore
Font.Charset = ANSI_CHARSET
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Style = []
ParentFont = False
Role = 'null'
TabOrder = 0
end
......@@ -167,12 +173,14 @@ object FViewMain: TFViewMain
Height = 83
ElementID = 'main.debugmemo'
ElementPosition = epRelative
Enabled = False
HeightPercent = 100.000000000000000000
Lines.Strings = (
'WebMemo1')
Role = 'null'
SelLength = 0
SelStart = 0
ShowFocus = False
Visible = False
WidthPercent = 100.000000000000000000
end
......
......@@ -47,7 +47,22 @@
</div>
</div>
</nav>
<!-- Toast wrapper directly under navbar -->
<div id="toast-wrapper"
class="position-fixed top-0 start-0 mt-5 ms-4"
style="z-index: 1080; min-width: 300px; max-width: 500px;">
<div id="bootstrapToast"
class="toast align-items-center text-white bg-success border-0 shadow"
role="alert" aria-live="assertive" aria-atomic="true">
<div class="d-flex">
<div class="toast-body" id="bootstrapToastBody">
Success message
</div>
<button type="button" class="btn-close btn-close-white me-2 m-auto"
data-bs-dismiss="toast" aria-label="Close"></button>
</div>
</div>
</div>
<div class="container-fluid">
<div class="row">
<div id="main.webpanel" class="col-12"></div>
......@@ -69,6 +84,47 @@
</div>
</div>
<div class="modal fade" id="main_errormodal" tabindex="-1" aria-labelledby="main_lblmodal" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content shadow-lg">
<div class="modal-header">
<h5 class="modal-title" id="main_lblmodal">Error</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body fs-6 fw-bold" id="main_lblmodal_body">
Please contact EMSystems to solve the issue.
</div>
<div class="modal-footer justify-content-center">
<button type="button" id="btn_modal_restart" class="btn btn-primary">Back to Orders</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="main_confirmation_modal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content shadow-lg">
<div class="modal-header">
<h5 class="modal-title">Confirm</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body fw-bold" id="main_modal_body">
Placeholder text
</div>
<div class="modal-footer justify-content-center">
<button type="button" class="btn btn-primary me-3" id="btn_confirm_left">Cancel</button>
<button type="button" class="btn btn-secondary" id="btn_confirm_right">Confirm</button>
</div>
</div>
</div>
</div>
......@@ -6,7 +6,7 @@ uses
System.SysUtils, System.Classes, JS, Web, WEBLib.Graphics, WEBLib.Controls,
WEBLib.Forms, WEBLib.Dialogs, WEBLib.ExtCtrls, Vcl.Controls, Vcl.StdCtrls,
WEBLib.StdCtrls, Data.DB, XData.Web.JsonDataset, XData.Web.Dataset,
App.Types, ConnectionModule, XData.Web.Client, WEBLib.Menus;
App.Types, ConnectionModule, XData.Web.Client, WEBLib.Menus, Utils;
type
TFViewMain = class(TWebForm)
......@@ -46,6 +46,7 @@ type
//procedure EditUser( AParam, BParam, CParam, DParam, EParam: string);
function GetUserInfo: string;
procedure setActive(page: string);
procedure ConfirmLogout;
public
{ Public declarations }
class procedure Display(LogoutProc: TLogoutProc);
......@@ -101,7 +102,6 @@ begin
ShowForm(TFViewOrders);
lblAppTitle.Caption := 'Koehler-Gibson Orders';
lblVersion.Caption := 'v' + DMConnection.clientVersion;
setActive('Orders');
end;
......@@ -117,7 +117,7 @@ begin
setActive('Customers');
end
else
ShowMessage('Please Save or Cancel your changes');
ShowToast('Please Save or Cancel your changes', 'danger');
end;
procedure TFViewMain.lblHomeClick(Sender: TObject);
......@@ -129,12 +129,11 @@ begin
//setActive('Home');
end
else
ShowMessage('Please Save or Cancel your changes');
ShowToast('Please Save or Cancel your changes', 'danger');
end;
procedure TFViewMain.lblordersClick(Sender: TObject);
begin
console.log(change);
if ( not ( change ) ) then
begin
ShowForm(TFViewOrders);
......@@ -142,7 +141,7 @@ begin
setActive('Orders');
end
else
ShowMessage('Please Save or Cancel your changes');
ShowToast('Please Save or Cancel your changes', 'danger');
end;
procedure TFViewMain.lblQuickbooksClick(Sender: TObject);
......@@ -154,7 +153,7 @@ begin
setActive('QuickBooks');
end
else
ShowMessage('Please Save or Cancel your changes');
ShowToast('Please Save or Cancel your changes', 'danger');
end;
procedure TFViewMain.lblUsersClick(Sender: TObject);
......@@ -165,7 +164,7 @@ begin
lblAppTitle.Caption := 'Koehler-Gibson Users';
end
else
ShowMessage('Please Save or Cancel your changes');
ShowToast('Please Save or Cancel your changes', 'danger');
end;
procedure TFViewMain.lblItemsListClick(Sender: TObject);
......@@ -177,7 +176,7 @@ begin
setActive('Items');
end
else
ShowMessage('Please Save or Cancel your changes');
ShowToast('Please Save or Cancel your changes', 'danger');
end;
procedure TFViewMain.setActive(page: string);
......@@ -200,13 +199,28 @@ end;
procedure TFViewMain.mnuLogoutClick(Sender: TObject);
begin
FLogoutProc;
ConfirmLogout;
end;
procedure TFViewMain.wllblLogoutClick(Sender: TObject);
begin
FLogoutProc;
ConfirmLogout;
end;
procedure TFViewMain.ConfirmLogout;
begin
ShowConfirmationModal(
'Are you sure you want to log out?',
'Yes',
'No',
procedure(confirmed: Boolean)
begin
if confirmed and Assigned(FLogoutProc) then
FLogoutProc('');
end
);
end;
......@@ -315,4 +329,5 @@ begin
FChildForm := TFViewUsers.CreateForm(WebPanel1.ElementID, Info);
end;
end.
......@@ -8,7 +8,6 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
Font.Style = []
ParentFont = False
OnCreate = WebFormCreate
OnShow = WebFormShow
object WebLabel1: TWebLabel
Left = 34
Top = 188
......@@ -99,40 +98,14 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
Visible = False
WidthPercent = 100.000000000000000000
end
object pnlMessage: TWebPanel
Left = 324
Top = 19
Width = 121
Height = 33
ElementID = 'view.login.message'
ChildOrder = 5
ElementPosition = epRelative
Role = 'null'
TabOrder = 0
object lblMessage: TWebLabel
Left = 28
Top = 9
Width = 44
object lblFormState: TWebLabel
Left = 18
Top = 16
Width = 3
Height = 14
Caption = 'Message'
ElementID = 'view.login.message.label'
ElementPosition = epRelative
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object btnCloseNotification: TWebButton
Left = 96
Top = 3
Width = 22
Height = 25
ChildOrder = 1
ElementID = 'view.login.message.button'
ElementPosition = epRelative
ElementID = 'lbl_form_state'
HeightPercent = 100.000000000000000000
Role = 'null'
WidthPercent = 100.000000000000000000
OnClick = btnCloseNotificationClick
end
end
object dtpOrderDate: TWebDateTimePicker
Left = 22
......@@ -147,7 +120,6 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
ElementPosition = epRelative
Role = 'null'
Text = ''
OnChange = dtpOrderDateChange
end
object dtpProofDate: TWebDateTimePicker
Left = 22
......@@ -162,7 +134,6 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
ElementPosition = epRelative
Role = 'null'
Text = ''
OnChange = dtpProofDateChange
end
object dtpShipDate: TWebDateTimePicker
Left = 22
......@@ -177,7 +148,6 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
ElementPosition = epRelative
Role = 'null'
Text = ''
OnChange = dtpShipDateChange
end
object dtpArtDue: TWebDateTimePicker
Left = 24
......@@ -206,7 +176,6 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
ElementPosition = epRelative
Role = 'null'
Text = ''
OnChange = dtpPlateDueChange
end
object dtpMountDue: TWebDateTimePicker
Left = 24
......@@ -221,7 +190,6 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
ElementPosition = epRelative
Role = 'null'
Text = ''
OnChange = dtpMountDueChange
end
object btnAddColor: TWebButton
Left = 658
......@@ -234,6 +202,7 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
ElementPosition = epRelative
HeightPercent = 100.000000000000000000
Role = 'null'
TabStop = False
WidthPercent = 100.000000000000000000
OnClick = btnAddColorClick
end
......@@ -249,8 +218,9 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
Date = 45748.499176770830000000
ElementPosition = epRelative
Role = 'null'
ShowFocus = False
TabStop = False
Text = ''
OnChange = dtpApprovedDateChange
end
object edtCompanyName: TWebDBEdit
Left = 18
......@@ -315,7 +285,7 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
DataSource = WebDataSource1
end
object edtQuantity: TWebDBEdit
Left = 24
Left = 26
Top = 346
Width = 121
Height = 22
......@@ -519,6 +489,7 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
ElementPosition = epRelative
HeightPercent = 100.000000000000000000
HideSelection = False
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'mounting_custom_adhesive'
DataSource = WebDataSource1
......@@ -599,16 +570,18 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
DataSource = WebDataSource1
end
object edtProofOther: TWebDBEdit
Left = 666
Left = 658
Top = 458
Width = 121
Height = 22
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtproofother'
ElementPosition = epRelative
HeightPercent = 100.000000000000000000
HideSelection = False
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'proofing_other'
DataSource = WebDataSource1
......@@ -618,12 +591,14 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
Top = 328
Width = 121
Height = 22
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtproofshipto'
ElementPosition = epRelative
HeightPercent = 100.000000000000000000
HideSelection = False
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'proofing_ship_to'
DataSource = WebDataSource1
......@@ -633,12 +608,14 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
Top = 300
Width = 121
Height = 22
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtemailattn'
ElementPosition = epRelative
HeightPercent = 100.000000000000000000
HideSelection = False
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'proofing_e_mail_attn'
DataSource = WebDataSource1
......@@ -648,12 +625,14 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
Top = 272
Width = 121
Height = 22
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtproofemail'
ElementPosition = epRelative
HeightPercent = 100.000000000000000000
HideSelection = False
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'proofing_e_mail'
DataSource = WebDataSource1
......@@ -663,12 +642,14 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
Top = 244
Width = 121
Height = 22
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtfaxattn'
ElementPosition = epRelative
HeightPercent = 100.000000000000000000
HideSelection = False
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'proofing_fax_attn'
DataSource = WebDataSource1
......@@ -678,12 +659,14 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
Top = 219
Width = 121
Height = 22
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtfax'
ElementPosition = epRelative
HeightPercent = 100.000000000000000000
HideSelection = False
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'proofing_fax'
DataSource = WebDataSource1
......@@ -699,6 +682,7 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
ElementPosition = epRelative
HeightPercent = 100.000000000000000000
HideSelection = False
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'colors_clemson'
DataSource = WebDataSource1
......@@ -714,6 +698,7 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
ElementPosition = epRelative
HeightPercent = 100.000000000000000000
HideSelection = False
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'colors_cross_hairs'
DataSource = WebDataSource1
......@@ -729,6 +714,7 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
ElementPosition = epRelative
HeightPercent = 100.000000000000000000
HideSelection = False
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'colors_machine_ident'
DataSource = WebDataSource1
......@@ -744,6 +730,7 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
ElementPosition = epRelative
HeightPercent = 100.000000000000000000
HideSelection = False
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'colors_cylinder_size'
DataSource = WebDataSource1
......@@ -753,12 +740,14 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
Top = 105
Width = 121
Height = 22
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtjobnumber'
ElementPosition = epRelative
HeightPercent = 100.000000000000000000
HideSelection = False
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'plates_job_number'
DataSource = WebDataSource1
......@@ -768,12 +757,15 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
Top = 480
Width = 113
Height = 22
TabStop = False
Caption = 'Art Approved As Is'
ChildOrder = 79
ElementID = 'cbartapprovedasis'
ElementPosition = epRelative
Enabled = False
HeightPercent = 100.000000000000000000
Role = 'null'
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'proofing_art_approved_as_is'
DataSource = WebDataSource1
......@@ -785,12 +777,15 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
Top = 430
Width = 113
Height = 22
TabStop = False
Caption = 'PDF File'
ChildOrder = 79
ElementID = 'cbpdffile'
ElementPosition = epRelative
Enabled = False
HeightPercent = 100.000000000000000000
Role = 'null'
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'proofing_pdf_file'
DataSource = WebDataSource1
......@@ -802,12 +797,15 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
Top = 406
Width = 113
Height = 22
TabStop = False
Caption = 'Wide Format'
ChildOrder = 79
ElementID = 'cbwideformat'
ElementPosition = epRelative
Enabled = False
HeightPercent = 100.000000000000000000
Role = 'null'
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'proofing_wide_format'
DataSource = WebDataSource1
......@@ -819,12 +817,15 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
Top = 382
Width = 113
Height = 22
TabStop = False
Caption = 'Print Card'
ChildOrder = 79
ElementID = 'cbprintcard'
ElementPosition = epRelative
Enabled = False
HeightPercent = 100.000000000000000000
Role = 'null'
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'proofing_print_card'
DataSource = WebDataSource1
......@@ -836,12 +837,15 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
Top = 356
Width = 113
Height = 22
TabStop = False
Caption = 'Full Size Panel'
ChildOrder = 79
ElementID = 'cbfullsizepanel'
ElementPosition = epRelative
Enabled = False
HeightPercent = 100.000000000000000000
Role = 'null'
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'proofing_full_size_panel'
DataSource = WebDataSource1
......@@ -853,12 +857,14 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
Top = 185
Width = 121
Height = 22
TabStop = False
AutoSize = True
ChildOrder = 78
ElementID = 'edtspecialinstructions'
ElementPosition = epRelative
HeightPercent = 100.000000000000000000
HideSelection = False
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'general_special_instructions'
DataSource = WebDataSource1
......@@ -886,8 +892,10 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
ChildOrder = 76
ElementID = 'edtrefartapdf'
ElementPosition = epRelative
Enabled = False
HeightPercent = 100.000000000000000000
Role = 'null'
ShowFocus = False
WidthPercent = 100.000000000000000000
end
object cbRefArtPrintCard: TWebCheckBox
......@@ -899,8 +907,10 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
ChildOrder = 76
ElementID = 'edtrefartprintcard'
ElementPosition = epRelative
Enabled = False
HeightPercent = 100.000000000000000000
Role = 'null'
ShowFocus = False
WidthPercent = 100.000000000000000000
end
object cbExistingCuttingDie: TWebCheckBox
......@@ -912,8 +922,10 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
ChildOrder = 76
ElementID = 'edtexistingcuttingdie'
ElementPosition = epRelative
Enabled = False
HeightPercent = 100.000000000000000000
Role = 'null'
ShowFocus = False
WidthPercent = 100.000000000000000000
end
object cbFTP: TWebCheckBox
......@@ -925,8 +937,10 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
ChildOrder = 76
ElementID = 'cbftp'
ElementPosition = epRelative
Enabled = False
HeightPercent = 100.000000000000000000
Role = 'null'
ShowFocus = False
WidthPercent = 100.000000000000000000
end
object cbSampleCarton: TWebCheckBox
......@@ -938,8 +952,10 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
ChildOrder = 76
ElementID = 'cbsampleCarton'
ElementPosition = epRelative
Enabled = False
HeightPercent = 100.000000000000000000
Role = 'null'
ShowFocus = False
WidthPercent = 100.000000000000000000
end
object cbPlates: TWebCheckBox
......@@ -951,8 +967,10 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
ChildOrder = 76
ElementID = 'cbplates'
ElementPosition = epRelative
Enabled = False
HeightPercent = 100.000000000000000000
Role = 'null'
ShowFocus = False
WidthPercent = 100.000000000000000000
end
object cbColorCopy: TWebCheckBox
......@@ -964,8 +982,10 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
ChildOrder = 76
ElementID = 'cbcolorcopy'
ElementPosition = epRelative
Enabled = False
HeightPercent = 100.000000000000000000
Role = 'null'
ShowFocus = False
WidthPercent = 100.000000000000000000
end
object cbStripMount: TWebCheckBox
......@@ -977,8 +997,10 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
ChildOrder = 76
ElementID = 'cbstripmount'
ElementPosition = epRelative
Enabled = False
HeightPercent = 100.000000000000000000
Role = 'null'
ShowFocus = False
WidthPercent = 100.000000000000000000
end
object cbFullMount: TWebCheckBox
......@@ -990,8 +1012,10 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
ChildOrder = 76
ElementID = 'cbfullmount'
ElementPosition = epRelative
Enabled = False
HeightPercent = 100.000000000000000000
Role = 'null'
ShowFocus = False
WidthPercent = 100.000000000000000000
end
object cbStickyBak: TWebCheckBox
......@@ -1003,8 +1027,10 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
ChildOrder = 76
ElementID = 'cbstickybak'
ElementPosition = epRelative
Enabled = False
HeightPercent = 100.000000000000000000
Role = 'null'
ShowFocus = False
WidthPercent = 100.000000000000000000
end
object cbLoose: TWebCheckBox
......@@ -1016,8 +1042,10 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
ChildOrder = 76
ElementID = 'cbloose'
ElementPosition = epRelative
Enabled = False
HeightPercent = 100.000000000000000000
Role = 'null'
ShowFocus = False
WidthPercent = 100.000000000000000000
end
object cbExcaliburDie: TWebCheckBox
......@@ -1029,8 +1057,10 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
ChildOrder = 76
ElementID = 'cbexcaliburdie'
ElementPosition = epRelative
Enabled = False
HeightPercent = 100.000000000000000000
Role = 'null'
ShowFocus = False
WidthPercent = 100.000000000000000000
end
object WebDBComboBox1: TWebDBComboBox
......@@ -1058,8 +1088,10 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
ChildOrder = 75
ElementID = 'edtemail'
ElementPosition = epRelative
Enabled = False
HeightPercent = 100.000000000000000000
Role = 'null'
ShowFocus = False
WidthPercent = 100.000000000000000000
end
object btnCancel: TWebButton
......@@ -1101,6 +1133,8 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
ElementPosition = epRelative
HeightPercent = 100.000000000000000000
Role = 'null'
ShowFocus = False
TabStop = False
WidthPercent = 100.000000000000000000
ItemIndex = -1
Items.Strings = (
......@@ -1111,13 +1145,15 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
end
object WebDBComboBox4: TWebDBComboBox
Left = 833
Top = 48
Top = 49
Width = 145
Height = 22
ElementID = 'wcbthickness'
ElementPosition = epRelative
HeightPercent = 100.000000000000000000
Role = 'null'
ShowFocus = False
TabStop = False
WidthPercent = 100.000000000000000000
ItemIndex = -1
Items.Strings = (
......@@ -1190,18 +1226,6 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object btn_confirm_delete: TWebButton
Left = 1094
Top = 414
Width = 96
Height = 25
Caption = 'Delete'
ChildOrder = 82
ElementID = 'btn_confirm_delete'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnClick = btn_confirm_deleteClick
end
object btnEdit: TWebButton
Left = 1202
Top = 560
......@@ -1235,6 +1259,7 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
ChildOrder = 85
ElementID = 'btnaddaddress'
HeightPercent = 100.000000000000000000
TabStop = False
WidthPercent = 100.000000000000000000
OnClick = WebButton2Click
end
......@@ -1243,14 +1268,7 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
Left = 1014
Top = 44
end
object tmrScrollTop: TWebTimer
Interval = 100
OnTimer = tmrScrollTopTimer
Left = 1176
Top = 256
end
object XDataWebDataSet1: TXDataWebDataSet
AfterEdit = XDataWebDataSet1AfterEdit
Connection = DMConnection.ApiConnection
Left = 1060
Top = 182
......@@ -1542,17 +1560,18 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
end
end
object WebDataSource1: TWebDataSource
AutoEdit = False
DataSet = XDataWebDataSet1
Left = 1176
Top = 182
end
object wdsShipTo: TWebDataSource
AutoEdit = False
DataSet = xdwdsShipTo
Left = 1090
Top = 124
end
object xdwdsShipTo: TXDataWebDataSet
AfterEdit = xdwdsShipToAfterEdit
Left = 1096
Top = 40
object xdwdsShipToADDRESS: TStringField
......@@ -1560,12 +1579,12 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
end
end
object wdsQBItem: TWebDataSource
AutoEdit = False
DataSet = xdwdsQBItem
Left = 1172
Top = 128
end
object xdwdsQBItem: TXDataWebDataSet
AfterEdit = xdwdsQBItemAfterEdit
Left = 1174
Top = 38
object xdwdsQBItemname: TStringField
......
<nav class="navbar navbar-expand navbar-light bg-light border-light sticky-top" style="z-index: 100;">
<div class="container-fluid ps-0">
<div id="view.login.message" class="alert alert-danger"
style="padding: 0.25rem 0.5rem; font-size: 0.875rem; line-height: 1.5; display: flex; align-items: center; margin: 0 0 0 60px; height: 32px; width: 400px;">
<button id="view.login.message.button" type="button" class="btn-close" aria-label="Close"></button>
<span id="view.login.message.label"></span>
<div class="container-fluid d-flex align-items-center ps-0 pe-0">
<!-- Left-aligned label -->
<div class="me-auto ps-3">
<label id="lbl_form_state" class="form-label mb-0 fw-bold text-uppercase text-nowrap text-danger" style="font-size: 16px;">Test</label>
</div>
<ul class="navbar-nav me-auto ps-2">
<!-- Right-aligned buttons -->
<ul class="navbar-nav ms-auto pe-2 mb-0">
<li class="nav-item pe-2">
<button id="btnadd" class="btn btn-primary btn-sm">Add</button>
</li>
......@@ -32,6 +33,7 @@
<button id="btnclose" class="btn btn-primary btn-sm">Close</button>
</li>
</ul>
</div>
</nav>
<div class="row mx-5">
......@@ -220,7 +222,7 @@
<hr class="custom-hr">
<div class="row">
<div class="col-auto">
<label for="wdbe_first_name" class="form-label mt-2">Loose:</label>
<label for="wdbe_first_name" style="font-weight: 700; font-size: 15px;" class="form-label mt-2">Loose:</label>
<input type="checkbox" id="cbloose">
<input id="edtloose" class="form-control input-sm" style="width: 150px"/>
</div>
......@@ -362,28 +364,4 @@
<textarea id="edtspecialinstructions" class="form-control" style=" width: 500px; height: 150px;"></textarea>
</div>
</div>
</div>
<div class="modal fade" id="confirmation_modal" tabindex="-1" aria-labelledby="confirmation_modal_label" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="confirmation_modal_label">Confirm</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body" id="modal_body">
Are you sure you want to delete this order?
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" id= 'btn_confirm_cancel'>Cancel</button>
<button type="button" class="btn btn-primary" data-bs-dismiss="modal" id="btn_confirm_delete">Delete</button>
</div>
</div>
</div>
</div>
<style>
.modal-backdrop {
opacity: 0 !important;
}
</style>
......@@ -9,13 +9,10 @@ uses
WEBLib.Forms, WEBLib.Dialogs, WEBLib.Menus, WEBLib.ExtCtrls, WEBLib.StdCtrls,
WEBLib.JSON, Auth.Service, XData.Web.Client, WebLib.Storage,
ConnectionModule, App.Types, Vcl.StdCtrls, Vcl.Controls, WEBLib.DBCtrls,
Data.DB, XData.Web.JsonDataset, XData.Web.Dataset, WEBLib.DB;
Data.DB, XData.Web.JsonDataset, XData.Web.Dataset, WEBLib.DB, VCL.Forms;
type
TFOrderEntryCorrugated = class(TWebForm)
pnlMessage: TWebPanel;
lblMessage: TWebLabel;
btnCloseNotification: TWebButton;
dtpOrderDate: TWebDateTimePicker;
dtpProofDate: TWebDateTimePicker;
dtpShipDate: TWebDateTimePicker;
......@@ -74,7 +71,6 @@ type
cbFullSizePanel: TWebDBCheckBox;
XDataWebClient1: TXDataWebClient;
edtSpecialInstructions: TWebDBEdit;
tmrScrollTop: TWebTimer;
XDataWebDataSet1: TXDataWebDataSet;
WebDataSource1: TWebDataSource;
btnSave: TWebButton;
......@@ -198,18 +194,14 @@ type
btnDelete: TWebButton;
btnClose: TWebButton;
edtOrderNum: TWebEdit;
btn_confirm_delete: TWebButton;
tmrReturn: TWebTimer;
btnEdit: TWebButton;
btnAdd: TWebButton;
WebButton2: TWebButton;
lblFormState: TWebLabel;
procedure WebFormCreate(Sender: TObject);
procedure HideNotification();
procedure ShowNotification(Notification: string);
procedure WebFormShow(Sender: TObject);
[async] procedure getOrder(Order_ID: string);
[async] procedure getCustomer(customerID: string);
procedure tmrScrollTopTimer(Sender: TObject);
procedure btnAddColorClick(Sender: TObject);
procedure addColorRow(num, Color, LPI, Size: string);
procedure btnSaveClick(Sender: TObject);
......@@ -221,23 +213,12 @@ type
procedure btnCopyClick(Sender: TObject);
procedure sendOrderToServer();
procedure btnCloseClick(Sender: TObject);
procedure btnCloseNotificationClick(Sender: TObject);
procedure btnDeleteClick(Sender: TObject);
procedure btn_confirm_deleteClick(Sender: TObject);
procedure tmrReturnTimer(Sender: TObject);
function VerifyOrder(): boolean;
procedure XDataWebDataSet1AfterEdit(DataSet: TDataSet);
procedure xdwdsShipToAfterEdit(DataSet: TDataSet);
procedure dtpApprovedDateChange(Sender: TObject);
procedure dtpMountDueChange(Sender: TObject);
procedure dtpPlateDueChange(Sender: TObject);
procedure dtpShipDateChange(Sender: TObject);
procedure dtpProofDateChange(Sender: TObject);
procedure dtpOrderDateChange(Sender: TObject);
procedure EditMode();
procedure btnEditClick(Sender: TObject);
procedure btnAddClick(Sender: TObject);
procedure xdwdsQBItemAfterEdit(DataSet: TDataSet);
procedure ViewMode();
procedure WebButton2Click(Sender: TObject);
procedure ShowAddAddressForm();
......@@ -246,14 +227,16 @@ type
FAgencyCode: string;
FCurrentReportType: string;
FSelectProc: TSelectProc;
mode: string;
orderID: string;
customerID: string;
mode: string;
changed: boolean;
notification: string;
procedure RemoveColorRow(Sender: TObject);
[async] procedure InitializeForm;
//FJSONProc1: TJSONProc1;
public
class function CreateForm(AElementID, orderInfo, customerInfo, mode, info: string): TWebForm;
class function CreateForm(AElementID, orderInfo, customerInfo, modeparam, info: string): TWebForm;
end;
var
......@@ -266,6 +249,45 @@ implementation
uses
View.Home, View.Main, View.AddOrder, View.AddAddress, Utils;
class function TFOrderEntryCorrugated.CreateForm(AElementID, orderInfo, customerInfo, modeParam, info: string): TWebForm;
begin
Application.CreateForm(TFOrderEntryCorrugated, AElementID, Result,
procedure(AForm: TObject)
begin
with TFOrderEntryCorrugated(AForm) do
begin
customerID := customerInfo;
orderID := orderInfo;
mode := modeParam;
notification := info;
console.log('Mode in createform: ' + modeParam);
InitializeForm;
end;
end
);
end;
[async] procedure TFOrderEntryCorrugated.InitializeForm;
begin
if mode = 'ADD' then
begin
await(getCustomer(customerID));
EditMode;
end
else
begin
await(getOrder(orderID));
ViewMode;
end;
edtOrderNum.Text := orderID;
if notification <> '' then
ShowToast(notification);
end;
procedure TFOrderEntryCorrugated.sendOrderToServer();
// This can be improved. I was struggling to get the checkboxes to work with
// The dataset at first, but if you just change the fields in the database to be
......@@ -383,7 +405,11 @@ begin
if Field is TStringField then
begin
if Field.AsString = '' then
orderJSON.AddPair(Field.FieldName, '')
begin
orderJSON.AddPair(Field.FieldName, '');
console.log(Field.FieldName);
console.log(Field.AsString);
end
else
orderJSON.AddPair(Field.FieldName, Field.AsString); // Add all other fields
end
......@@ -403,14 +429,10 @@ begin
if mode = 'EDIT' then
orderJSON.AddPair('ORDER_ID', orderID);
if mode = 'ADD' then
ShowNotification('Success:Order Added Successfully!')
else
ShowNotification('Success:Order Edited Successfully');
AddCorrugatedOrder(orderJSON);
end;
procedure TFOrderEntryCorrugated.btnSaveClick(Sender: TObject);
// Converts all the information on the page into a JSON to then send to the server
begin
......@@ -436,7 +458,6 @@ begin
else
input.classList.remove('is-invalid');
input := TJSHTMLInputElement(document.getElementById('edtaccountcompanyname'));
if edtCompanyAccountName.Text = '' then
begin
......@@ -476,6 +497,7 @@ begin
input.classList.remove('is-invalid');
end;
procedure TFOrderEntryCorrugated.btnCopyClick(Sender: TObject);
begin
mode := 'ADD';
......@@ -489,73 +511,44 @@ begin
dtpApprovedDate.Date := 0;
edtOrderNum.Text := '';
EditMode();
ShowNotification('Success:Order Successfully Copied');
ShowToast('Success: Order Successfully Copied');
window.scrollTo(0, 0);
end;
procedure TFOrderEntryCorrugated.btnDeleteClick(Sender: TObject);
begin
document.getElementById('modal_body').innerHTML := 'Are you sure you want to delete this order?';
document.getElementById('btn_confirm_cancel').innerText := 'Cancel';
document.getElementById('btn_confirm_delete').innerText := 'Delete';
asm
var modal = document.getElementById('confirmation_modal');
// ensure the modal lives directly under <body>
if (modal && modal.parentNode !== document.body) {
document.body.appendChild(modal);
}
var bsModal = new bootstrap.Modal(modal, {
keyboard: false
});
bsModal.show();
ShowConfirmationModal(
'Are you sure you want to delete this order?',
'Delete',
'Cancel',
procedure(confirmed: Boolean)
begin
if confirmed then
begin
Utils.ShowSpinner('spinner');
DelOrder();
tmrReturn.Enabled := true;
end;
end
);
end;
procedure TFOrderEntryCorrugated.btnEditClick(Sender: TObject);
begin
EditMode();
end;
procedure TFOrderEntryCorrugated.btnPDFClick(Sender: TObject);
begin
if mode = 'EDIT' then
GenerateReportPDF
else
showNotification('Failure:Cannot Generate PDF when Adding an Order');
ShowToast('Failure: Cannot Generate PDF when Adding an Order');
end;
procedure TFOrderEntryCorrugated.btn_confirm_deleteClick(Sender: TObject);
begin
if document.getElementById('btn_confirm_delete').innerText = 'Yes' then
begin
FViewMain.change := false;
if OrderID <> '' then
begin
FViewMain.ViewOrderEntryCorrugated(OrderID, '', 'EDIT', 'Failure:Changes Discarded');
end
else
FViewMain.ViewOrders('');
end
else
begin
Utils.ShowSpinner('spinner');
asm
var modal = document.getElementById('confirmation_modal');
// ensure the modal lives directly under <body>
if (modal && modal.parentNode !== document.body) {
document.body.appendChild(modal);
}
var bsModal = new bootstrap.Modal(modal, {
keyboard: false
});
bsModal.hide();
end;
delOrder();
tmrReturn.Enabled := true;
end;
end;
[async] procedure TFOrderEntryCorrugated.GenerateReportPDF;
// sends the search to the server which then sends back a pdf of the results
......@@ -564,7 +557,7 @@ var
searchOptions, pdfURL: string;
jsObject: TJSObject;
begin
try
// Call the server method to generate the PDF
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GenerateOrderCorrugatedPDF', [orderID]));
jsObject := JS.TJSObject(xdcResponse.Result);
......@@ -573,113 +566,132 @@ begin
// Open the PDF in a new browser tab without needing a different form
// This method is much faster too, even for large datasets
window.open(pdfURL, '_blank');
except
on E: EXDataClientRequestException do
Utils.ShowErrorModal('Could not generate corrugated PDF: ' + E.ErrorResult.ErrorMessage);
end;
end;
procedure TFOrderEntryCorrugated.AddCorrugatedOrder(orderJSON: TJSONObject);
// sends the order JSON object to the server
var
Response: TXDataClientResponse;
jsObj: TJSObject;
begin
console.log(orderJSON);
Response := await(XDataWebClient1.RawInvokeAsync('ILookupService.AddCorrugatedOrder',
[orderJSON.ToString]));
jsObj := JS.TJSObject(Response.Result);
if mode = 'ADD' then
OrderID := String(jsObj.Properties['OrderID']);
edtOrderNum.Text := OrderID;
mode := 'EDIT';
ShowToast(string(jsObj.Properties['status']));
end;
procedure TFOrderEntryCorrugated.DelOrder();
var
Response: TXDataClientResponse;
begin
try
Response := await(XDataWebClient1.RawInvokeAsync('ILookupService.DelOrder',
[OrderID, 'corrugated', JS.toString(AuthService.TokenPayload.Properties['user_id'])]));
except
on E: EXDataClientRequestException do
Utils.ShowErrorModal('Could not delete order: ' + E.ErrorResult.ErrorMessage);
end;
end;
class function TFOrderEntryCorrugated.CreateForm(AElementID, orderInfo, customerInfo, mode, info: string): TWebForm;
procedure TFOrderEntryCorrugated.addColorRow(num, color, LPI, size: string);
var
localMode: string;
container, newRow, col, labelEl, inputEl, removeCol: TJSHTMLElement;
removeBtn: TWebButton;
values: array[0..3] of string;
labels: array[0..3] of string;
i: Integer;
begin
localMode := mode;
Application.CreateForm(TFOrderEntryCorrugated, AElementID, Result,
procedure(AForm: TObject)
begin
with TFOrderEntryCorrugated(AForm) do
begin
TFOrderEntryCorrugated(AForm).customerID := customerInfo;
TFOrderEntryCorrugated(AForm).orderID := orderInfo;
TFOrderEntryCorrugated(AForm).mode := localMode;
TFOrderEntryCorrugated(AForm).notification := info;
end;
end
);
container := TJSHTMLElement(document.getElementById('additionalFields'));
end;
// Create the new row container
newRow := TJSHTMLElement(document.createElement('div'));
newRow.className := 'row mb-2';
procedure TFOrderEntryCorrugated.addColorRow(num: string; Color: string; LPI: string; Size: string);
// Java script code to add a row of colors when a button is clicked
// all variables are information to be placed in the boxes when loading an order.
// TODO: convert to Delphi
begin
asm
const container = document.getElementById('additionalFields');
// Create a new row for the new fields
const newRow = document.createElement('div');
newRow.className = 'row mb-2';
const labels = ['#', 'Color', 'LPI', 'Size'];
const values = [num, Color, LPI, Size];
labels.forEach((label, index) => {
const col = document.createElement('div');
col.className = 'col-sm';
const labelElement = document.createElement('label');
labelElement.className = 'pe-2';
labelElement.style.fontWeight = '700';
labelElement.style.fontSize = '15px';
labelElement.textContent = label + ':';
const inputElement = document.createElement('input');
inputElement.className = 'form-control input-sm';
inputElement.style.width = '100%';
inputElement.id = 'input-' + container.childElementCount + '-' + index; // Unique ID based on count
inputElement.value = values[index]; // Set the value based on the parameter
col.appendChild(labelElement);
col.appendChild(inputElement);
labels[0] := '#'; values[0] := num;
labels[1] := 'Color'; values[1] := color;
labels[2] := 'LPI'; values[2] := LPI;
labels[3] := 'Size'; values[3] := size;
for i := 0 to 3 do
begin
col := TJSHTMLElement(document.createElement('div'));
col.className := 'col-sm';
labelEl := TJSHTMLElement(document.createElement('label'));
labelEl.className := 'pe-2';
labelEl.style.setProperty('font-weight', '700');
labelEl.style.setProperty('font-size', '15px');
labelEl.textContent := labels[i] + ':';
inputEl := TJSHTMLElement(document.createElement('input'));
inputEl.className := 'form-control input-sm';
inputEl.setAttribute('style', 'width: 100%');
inputEl.setAttribute('value', values[i]);
inputEl.setAttribute('id', 'input-' + IntToStr(container.childElementCount) + '-' + IntToStr(i));
col.appendChild(labelEl);
col.appendChild(inputEl);
newRow.appendChild(col);
});
const removeButtonCol = document.createElement('div');
removeButtonCol.className = 'col-auto d-flex align-items-center mt-3';
end;
const removeButton = document.createElement('button');
removeButton.className = 'btn btn-danger btn-sm mt-1';
removeButton.textContent = 'Remove';
removeButton.addEventListener('click', function() {
container.removeChild(newRow);
});
// Add remove button
removeCol := TJSHTMLElement(document.createElement('div'));
removeCol.className := 'col-auto d-flex align-items-end pb-1';
removeButtonCol.appendChild(removeButton);
newRow.appendChild(removeButtonCol);
removeBtn := TWebButton.Create(Self);
removeBtn.Caption := 'Remove';
removeBtn.ElementClassName := 'btn btn-danger btn-sm mt-1';
removeBtn.ParentElement := removeCol;
removeBtn.ElementHandle.style.setProperty('height', '30px');
removeBtn.OnClick := RemoveColorRow;
newRow.appendChild(removeCol);
container.appendChild(newRow);
end;
procedure TFOrderEntryCorrugated.RemoveColorRow(Sender: TObject);
var
btn: TWebButton;
rowElement: TJSHTMLElement;
begin
EditMode();
btn := TWebButton(Sender);
if Assigned(btn.ElementHandle) and Assigned(btn.ElementHandle.parentElement) then
begin
// Assuming button is inside a <div> inside the row
rowElement := TJSHTMLElement(btn.ElementHandle.parentElement.parentElement);
if Assigned(rowElement) then
rowElement.remove;
end;
end;
procedure TFOrderEntryCorrugated.btnAddColorClick(Sender: TObject);
begin
EditMode();
addColorRow('','','','');
end;
procedure TFOrderEntryCorrugated.WebButton2Click(Sender: TObject);
begin
ShowAddAddressForm();
end;
procedure TFOrderEntryCorrugated.SendAddressToServer(AddressJSON: TJSONObject);
var
Response: TXDataClientResponse;
......@@ -689,12 +701,13 @@ begin
[AddressJSON.ToString]));
notification := TJSObject(Response.Result);
ShowNotification(string(notification['status']));
ShowToast(string(notification['status']));
xdwdsShipTo.Close;
xdwdsShipTo.SetJSONData(notification['ADDRESS']);
xdwdsShipTo.Open;
end;
procedure TFOrderEntryCorrugated.ShowAddAddressForm;
// displays the search pop-up that allows the user to filter the order list
var
......@@ -706,6 +719,7 @@ begin
newform.Caption := 'Input Shipping Information';
newForm.Popup := True;
newForm.Position := poScreenCenter;
newForm.Border := fbDialog;
// used to manage Back button handling to close subform
......@@ -751,6 +765,7 @@ begin
newform.Caption := 'Select Customer and Order Type';
newForm.Popup := True;
newForm.Position := poScreenCenter;
newForm.Border := fbDialog;
// used to manage Back button handling to close subform
......@@ -779,34 +794,33 @@ begin
);
end;
procedure TFOrderEntryCorrugated.btnCancelClick(Sender: TObject);
begin
document.getElementById('modal_body').innerHTML := 'Are you sure you want to cancel all changes?';
document.getElementById('btn_confirm_cancel').innerText := 'No';
document.getElementById('btn_confirm_delete').innerText := 'Yes';
asm
var modal = document.getElementById('confirmation_modal');
// ensure the modal is directly under <body>
if (modal && modal.parentNode !== document.body) {
document.body.appendChild(modal);
}
var bsModal = new bootstrap.Modal(modal, {
keyboard: false
});
bsModal.show();
ShowConfirmationModal(
'Are you sure you want to cancel all changes?',
'Yes',
'No',
procedure(confirmed: Boolean)
begin
if confirmed then
begin
FViewMain.change := false;
if OrderID <> '' then
FViewMain.ViewOrderEntryCorrugated(OrderID, '', 'EDIT', 'Failure: Changes Discarded')
else
FViewMain.ViewOrders('');
end;
end
);
end;
procedure TFOrderEntryCorrugated.btnCloseClick(Sender: TObject);
begin
FViewMain.ViewOrders('');
end;
procedure TFOrderEntryCorrugated.btnCloseNotificationClick(Sender: TObject);
begin
hideNotification();
end;
procedure TFOrderEntryCorrugated.WebFormCreate(Sender: TObject);
begin
......@@ -817,6 +831,7 @@ begin
end;
end;
procedure TFOrderEntryCorrugated.getOrder(Order_ID: string);
// retrieves an order from the server then loads the info into the page
var
......@@ -835,13 +850,15 @@ var
colorListJSON: TJSONArray;
items: TJSObject;
begin
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GetOrder',
[Order_ID]));
try
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GetOrder', [Order_ID]));
order := TJSObject(xdcResponse.Result);
data := TJSArray(order['data']);
XDataWebDataSet1.Close;
XDataWebDataSet1.SetJsonData(order);
XDataWebDataSet1.Open;
XDataWebDataSet1.Edit;
if XDataWebDataSet1colors_colors.Value <> '' then
begin
colorObject := TJSObject(TJSJSON.parse(XDataWebDataSet1colors_colors.Value));
......@@ -967,9 +984,13 @@ begin
items := TJSObject(order['ITEMS']);
xdwdsQBItem.SetJsonData(items['data']);
xdwdsQBITEM.Open;
except
on E: EXDataClientRequestException do
Utils.ShowErrorModal('Could not retrieve order: ' + E.ErrorResult.ErrorMessage);
end;
end;
procedure TFOrderEntryCorrugated.getCustomer(customerID: string);
// gets a customer from the database then loads the appropiate fields
var
......@@ -978,14 +999,13 @@ var
address: string;
items: TJSObject;
begin
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GetCustomer',
[customerID]));
try
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GetCustomer', [customerID]));
customer := TJSObject(xdcResponse.Result);
XDataWebDataSet1.Close;
XDataWebDataSet1.SetJsonData(customer);
XDataWebDataSet1.Open;
XDataWebDataSet1.Edit;
xdwdsShipTo.Close;
xdwdsShipTo.SetJSONData(customer['ADDRESS_LIST']);
......@@ -1003,80 +1023,13 @@ begin
dtpMountDue.Date := 0;
dtpShipDate.Date := 0;
dtpApprovedDate.Date := 0;
end;
procedure TFOrderEntryCorrugated.WebFormShow(Sender: TObject);
begin
if mode <> 'ADD' then
begin
getOrder(orderID);
ViewMode();
end
else
begin
getCustomer(customerID);
EditMode();
end;
edtOrderNum.Text := OrderID;
if notification = '' then
begin
HideNotification;
end
else
begin
ShowNotification(notification);
except
on E: EXDataClientRequestException do
Utils.ShowErrorModal('Could not retrieve customer: ' + E.ErrorResult.ErrorMessage);
end;
end;
procedure TFOrderEntryCorrugated.XDataWebDataSet1AfterEdit(DataSet: TDataSet);
begin
EditMode();
end;
procedure TFOrderEntryCorrugated.xdwdsQBItemAfterEdit(DataSet: TDataSet);
begin
EditMode();
end;
procedure TFOrderEntryCorrugated.xdwdsShipToAfterEdit(DataSet: TDataSet);
begin
EditMode();
end;
procedure TFOrderEntryCorrugated.HideNotification;
begin
pnlMessage.ElementHandle.hidden := True;
end;
procedure TFOrderEntryCorrugated.ShowNotification(Notification: string);
var
splitNotification: TArray<string>;
begin
console.log(notification);
if Notification <> '' then
begin
splitNotification := Notification.Split([':']);
if(splitNotification[0] = 'Success') then
begin
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-danger');
messageDiv.classList.add('alert-success');
end;
end
else
begin
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-success');
messageDiv.classList.add('alert-danger');
end;
end;
console.log(splitNotification[1]) ;
lblMessage.Caption := splitNotification[1];
pnlMessage.ElementHandle.hidden := False;
end;
end;
procedure TFOrderEntryCorrugated.tmrReturnTimer(Sender: TObject);
......@@ -1086,14 +1039,10 @@ begin
FViewMain.ViewOrders('Success: Order Successfully Deleted');
end;
procedure TFOrderEntryCorrugated.tmrScrollTopTimer(Sender: TObject);
begin
tmrScrollTop.Enabled := False;
window.scrollTo(0, 0);
end;
procedure TFOrderEntryCorrugated.EditMode();
begin
XDataWebDataSet1.Edit;
FViewMain.change := true;
btnCopy.Enabled := false;
btnPDF.Enabled := false;
......@@ -1103,37 +1052,32 @@ begin
btnCancel.Enabled := True;
btnEdit.Enabled := false;
btnAdd.Enabled := false;
end;
procedure TFOrderEntryCorrugated.dtpApprovedDateChange(Sender: TObject);
begin
EditMode();
// Enable all non-DB checkboxes manually
cbRefArtAPDF.Enabled := True;
cbRefArtPrintCard.Enabled := True;
cbExistingCuttingDie.Enabled := True;
cbFTP.Enabled := True;
cbSampleCarton.Enabled := True;
cbPlates.Enabled := True;
cbColorCopy.Enabled := True;
cbStripMount.Enabled := True;
cbFullMount.Enabled := True;
cbStickyBak.Enabled := True;
cbLoose.Enabled := True;
cbExcaliburDie.Enabled := True;
cbEmail.Enabled := True;
cbArtApprovedAsIs.Enabled := True;
cbPDFFile.Enabled := True;
cbWideFormat.Enabled := True;
cbPrintCard.Enabled := True;
cbFullSizePanel.Enabled := True;
lblFormState.Caption := 'Edit Mode';
lblFormState.ElementHandle.classList.remove('text-danger');
lblFormState.ElementHandle.classList.add('text-success');
end;
procedure TFOrderEntryCorrugated.dtpMountDueChange(Sender: TObject);
begin
EditMode();
end;
procedure TFOrderEntryCorrugated.dtpOrderDateChange(Sender: TObject);
begin
EditMode();
end;
procedure TFOrderEntryCorrugated.dtpPlateDueChange(Sender: TObject);
begin
EditMode();
end;
procedure TFOrderEntryCorrugated.dtpProofDateChange(Sender: TObject);
begin
EditMode();
end;
procedure TFOrderEntryCorrugated.dtpShipDateChange(Sender: TObject);
begin
EditMode();
end;
procedure TFOrderEntryCorrugated.ViewMode;
begin
......@@ -1146,10 +1090,36 @@ begin
btnEdit.Enabled := true;
btnAdd.Enabled := true;
FViewMain.change := false;
// Explicitly disable all non-DB checkboxes
cbRefArtAPDF.Enabled := False;
cbRefArtPrintCard.Enabled := False;
cbExistingCuttingDie.Enabled := False;
cbFTP.Enabled := False;
cbSampleCarton.Enabled := False;
cbPlates.Enabled := False;
cbColorCopy.Enabled := False;
cbStripMount.Enabled := False;
cbFullMount.Enabled := False;
cbStickyBak.Enabled := False;
cbLoose.Enabled := False;
cbExcaliburDie.Enabled := False;
cbEmail.Enabled := False;
cbArtApprovedAsIs.Enabled := False;
cbPDFFile.Enabled := False;
cbWideFormat.Enabled := False;
cbPrintCard.Enabled := False;
cbFullSizePanel.Enabled := False;
lblFormState.Caption := 'View Mode';
lblFormState.ElementHandle.classList.remove('text-success');
lblFormState.ElementHandle.classList.add('text-danger');
end;
initialization
RegisterClass(TFOrderEntryCorrugated);
end.
object FOrderEntryCuttingDie: TFOrderEntryCuttingDie
Width = 956
Height = 728
OnShow = WebFormShow
object WebLabel2: TWebLabel
Left = 26
Top = 72
......@@ -32,6 +31,15 @@ object FOrderEntryCuttingDie: TFOrderEntryCuttingDie
Visible = False
WidthPercent = 100.000000000000000000
end
object lblFormState: TWebLabel
Left = 34
Top = 8
Width = 3
Height = 15
ElementID = 'lbl_form_state'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object edtCompanyAccountName: TWebDBEdit
Left = 24
Top = 120
......@@ -46,10 +54,11 @@ object FOrderEntryCuttingDie: TFOrderEntryCuttingDie
DataSource = WebDataSource1
end
object edtInQuickBooks: TWebDBEdit
Left = 26
Top = 148
Left = 24
Top = 152
Width = 121
Height = 23
AutoCompletion = acNope
AutoSize = True
ChildOrder = 79
ElementID = 'edtinquickbooks'
......@@ -70,7 +79,6 @@ object FOrderEntryCuttingDie: TFOrderEntryCuttingDie
Date = 45638.529943136570000000
Role = ''
Text = ''
OnChange = dtpOrderDateChange
end
object dtpProofDate: TWebDateTimePicker
Left = 22
......@@ -84,7 +92,6 @@ object FOrderEntryCuttingDie: TFOrderEntryCuttingDie
Date = 45638.529943136570000000
Role = ''
Text = ''
OnChange = dtpOrderDateChange
end
object dtpShipDate: TWebDateTimePicker
Left = 22
......@@ -98,7 +105,6 @@ object FOrderEntryCuttingDie: TFOrderEntryCuttingDie
Date = 45638.529943136570000000
Role = ''
Text = ''
OnChange = dtpOrderDateChange
end
object edtShipVia: TWebDBEdit
Left = 24
......@@ -120,6 +126,7 @@ object FOrderEntryCuttingDie: TFOrderEntryCuttingDie
Height = 23
AutoSize = True
ChildOrder = 79
EditType = weNumeric
ElementID = 'edtquantity'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
......@@ -228,43 +235,6 @@ object FOrderEntryCuttingDie: TFOrderEntryCuttingDie
WidthPercent = 100.000000000000000000
OnClick = btnCancelClick
end
object pnlMessage: TWebPanel
Left = 324
Top = 19
Width = 121
Height = 33
ElementID = 'view.login.message'
ChildOrder = 5
ElementPosition = epRelative
Role = 'alert'
TabOrder = 15
object lblMessage: TWebLabel
Left = 28
Top = 9
Width = 46
Height = 15
Caption = 'Message'
ElementID = 'view.login.message.label'
ElementPosition = epRelative
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object btnCloseNotification: TWebButton
Left = 96
Top = 3
Width = 22
Height = 25
ChildOrder = 1
ElementID = 'view.login.message.button'
ElementFont = efCSS
ElementPosition = epRelative
HeightStyle = ssAuto
HeightPercent = 100.000000000000000000
Role = 'button'
WidthStyle = ssAuto
WidthPercent = 100.000000000000000000
end
end
object edtCompanyName: TWebDBEdit
Left = 26
Top = 92
......@@ -338,18 +308,6 @@ object FOrderEntryCuttingDie: TFOrderEntryCuttingDie
WidthPercent = 100.000000000000000000
OnClick = btnCloseClick
end
object btn_confirm_delete: TWebButton
Left = 776
Top = 279
Width = 96
Height = 25
Caption = 'Delete'
ChildOrder = 82
ElementID = 'btn_confirm_delete'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnClick = btn_confirm_deleteClick
end
object btnCopy: TWebButton
Left = 746
Top = 453
......@@ -399,15 +357,15 @@ object FOrderEntryCuttingDie: TFOrderEntryCuttingDie
OnClick = WebButton2Click
end
object WebDataSource1: TWebDataSource
AutoEdit = False
DataSet = XDataWebDataSet1
Left = 22
Top = 10
Left = 418
Top = 86
end
object XDataWebDataSet1: TXDataWebDataSet
AfterEdit = XDataWebDataSet1AfterEdit
Connection = DMConnection.ApiConnection
Left = 90
Top = 20
Left = 422
Top = 28
object XDataWebDataSet1COMPANY_ID: TIntegerField
FieldName = 'COMPANY_ID'
end
......@@ -468,40 +426,35 @@ object FOrderEntryCuttingDie: TFOrderEntryCuttingDie
object XDataWebDataSet1staff_fields_quantity: TStringField
FieldName = 'staff_fields_quantity'
end
object XDataWebDataSet1inQuickBooks: TStringField
FieldName = 'inQuickBooks'
end
end
object XDataWebClient1: TXDataWebClient
Connection = DMConnection.ApiConnection
Left = 192
Top = 92
end
object tmrScrollTop: TWebTimer
Interval = 100
OnTimer = tmrScrollTopTimer
Left = 240
Top = 8
Left = 200
Top = 50
end
object wdsShipTo: TWebDataSource
DataSet = xdwdsShipTo
Left = 302
Top = 418
Left = 526
Top = 86
end
object xdwdsShipTo: TXDataWebDataSet
AfterEdit = xdwdsShipToAfterEdit
Left = 288
Top = 370
Left = 528
Top = 26
object xdwdsShipToADDRESS: TStringField
FieldName = 'ADDRESS'
end
end
object wdsQBItem: TWebDataSource
DataSet = xdwdsQBItem
Left = 230
Top = 554
Left = 606
Top = 86
end
object xdwdsQBItem: TXDataWebDataSet
AfterEdit = xdwdsQBItemAfterEdit
Left = 190
Top = 548
Left = 608
Top = 30
object xdwdsQBItemname: TStringField
FieldName = 'name'
end
......
<nav class="navbar navbar-expand navbar-light bg-light sticky-top" style="z-index: 100;">
<div class="container-fluid ps-0">
<div id="view.login.message" class="alert alert-danger"
style="padding: 0.25rem 0.5rem; font-size: 0.875rem; line-height: 1.5; display: flex; align-items: center; margin: 0 0 0 60px; height: 32px; width: 400px;">
<button id="view.login.message.button" type="button" class="btn-close" aria-label="Close"></button>
<span id="view.login.message.label"></span>
</div>
<ul class="navbar-nav me-auto ps-2">
<nav class="navbar navbar-expand navbar-light bg-light border-light sticky-top" style="z-index: 100;">
<div class="container-fluid d-flex align-items-center ps-0 pe-0">
<!-- Left-aligned label -->
<div class="me-auto ps-3">
<label id="lbl_form_state" class="form-label mb-0 fw-bold text-uppercase text-nowrap text-danger" style="font-size: 16px;">View Mode</label>
</div>
<!-- Right-aligned buttons -->
<ul class="navbar-nav ms-auto pe-2 mb-0">
<li class="nav-item pe-2">
<button id="btnadd" class="btn btn-primary btn-sm">Add</button>
</li>
......@@ -28,9 +30,10 @@
<button id="btncancel" class="btn btn-danger btn-sm">Cancel</button>
</li>
<li class="nav-item">
<button id="btnclose" class="btn btn-secondary btn-sm">Close</button>
<button id="btnclose" class="btn btn-primary btn-sm">Close</button>
</li>
</ul>
</div>
</nav>
<div class="row mx-5">
......@@ -129,26 +132,4 @@
</div>
</div>
</div>
<div class="modal fade" id="confirmation_modal" tabindex="-1" aria-labelledby="confirmation_modal_label" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="confirmation_modal_label">Confirm</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body" id="modal_body">
Are you sure you want to delete this order?
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" id=btn_confirm_cancel>Cancel</button>
<button type="button" class="btn btn-primary" data-bs-dismiss="modal" id="btn_confirm_delete">Delete</button>
</div>
</div>
</div>
</div>
</div>
<style>
.modal-backdrop {
opacity: 0 !important;
}
</style>
unit View.OrderEntryCuttingDie;
unit View.OrderEntryCuttingDie;
interface
......@@ -7,7 +7,7 @@ uses
WEBLib.Forms, WEBLib.Dialogs, WEBLib.Menus, WEBLib.ExtCtrls, WEBLib.StdCtrls,
WEBLib.JSON, Auth.Service, XData.Web.Client, WebLib.Storage,
ConnectionModule, App.Types, Vcl.StdCtrls, Vcl.Controls, WEBLib.DBCtrls,
Data.DB, XData.Web.JsonDataset, XData.Web.Dataset, WEBLib.DB;
Data.DB, XData.Web.JsonDataset, XData.Web.Dataset, WEBLib.DB, VCL.Forms;
type
TFOrderEntryCuttingDie = class(TWebForm)
......@@ -30,7 +30,6 @@ type
XDataWebDataSet1staff_fields_proof_date: TStringField;
XDataWebDataSet1staff_fields_ship_date: TStringField;
XDataWebClient1: TXDataWebClient;
tmrScrollTop: TWebTimer;
WebLabel2: TWebLabel;
edtCompanyAccountName: TWebDBEdit;
edtInQuickBooks: TWebDBEdit;
......@@ -52,9 +51,6 @@ type
edtSpecialInstructions: TWebDBEdit;
btnSave: TWebButton;
btnCancel: TWebButton;
pnlMessage: TWebPanel;
lblMessage: TWebLabel;
btnCloseNotification: TWebButton;
edtCompanyName: TWebDBEdit;
XDataWebDataSet1NAME: TStringField;
XDataWebDataSet1staff_fields_quickbooks_item: TStringField;
......@@ -68,21 +64,18 @@ type
edtOrderNum: TWebEdit;
btnDelete: TWebButton;
btnClose: TWebButton;
btn_confirm_delete: TWebButton;
btnCopy: TWebButton;
tmrReturn: TWebTimer;
btnEdit: TWebButton;
btnAdd: TWebButton;
WebButton2: TWebButton;
XDataWebDataSet1inQuickBooks: TStringField;
lblFormState: TWebLabel;
procedure btnSaveClick(Sender: TObject);
procedure btnCancelClick(Sender: TObject);
procedure WebFormCreate(Sender: TObject);
procedure HideNotification();
procedure ShowNotification(Notification: string);
procedure WebFormShow(Sender: TObject);
[async] procedure GetCuttingDieOrder(Order_ID: string);
[async] procedure GetCustomer(customerID: string);
procedure tmrScrollTopTimer(Sender: TObject);
[async] procedure AddCuttingDieOrder(orderJSON: TJSONObject);
procedure btnPDFClick(Sender: TObject);
[async] procedure GenerateReportPDF;
......@@ -92,14 +85,8 @@ type
[async] procedure delOrder();
procedure btnCloseClick(Sender: TObject);
procedure btnCopyClick(Sender: TObject);
procedure btn_confirm_deleteClick(Sender: TObject);
procedure tmrReturnTimer(Sender: TObject);
procedure btnAddClick(Sender: TObject);
procedure xdwdsShipToAfterEdit(DataSet: TDataSet);
procedure EditMode();
procedure xdwdsQBItemAfterEdit(DataSet: TDataSet);
procedure XDataWebDataSet1AfterEdit(DataSet: TDataSet);
procedure dtpOrderDateChange(Sender: TObject);
procedure btnEditClick(Sender: TObject);
procedure ViewMode();
procedure WebButton2Click(Sender: TObject);
......@@ -113,8 +100,10 @@ type
customerID: string;
mode: string;
notification: string;
procedure EditMode;
[async] procedure InitializeForm;
public
class function CreateForm(AElementID, orderInfo, customerInfo, mode, info: string): TWebForm;
class function CreateForm(AElementID, orderInfo, customerInfo, modeParam, info: string): TWebForm;
end;
var
......@@ -127,11 +116,52 @@ implementation
uses
View.Home, View.Main, View.AddOrder, View.AddAddress, Utils;
class function TFOrderEntryCuttingDie.CreateForm(AElementID, orderInfo, customerInfo, modeParam, info: string): TWebForm;
begin
Application.CreateForm(TFOrderEntryCuttingDie, AElementID, Result,
procedure(AForm: TObject)
begin
with TFOrderEntryCuttingDie(AForm) do
begin
customerID := customerInfo;
orderID := orderInfo;
mode := modeParam;
notification := info;
console.log('Mode in createform: ' + modeParam);
InitializeForm;
end;
end
);
end;
[async] procedure TFOrderEntryCuttingDie.InitializeForm;
begin
console.log('The mode in initialize form is: ' + mode);
if mode = 'ADD' then
begin
await(getCustomer(customerID));
EditMode;
end
else
begin
await(getCuttingDieOrder(orderID));
ViewMode;
end;
edtOrderNum.Text := orderID;
if notification <> '' then
ShowToast(notification);
end;
procedure TFOrderEntryCuttingDie.WebButton2Click(Sender: TObject);
begin
ShowAddAddressForm();
end;
procedure TFOrderEntryCuttingDie.SendAddressToServer(AddressJSON: TJSONObject);
var
Response: TXDataClientResponse;
......@@ -141,12 +171,13 @@ begin
[AddressJSON.ToString]));
notification := TJSObject(Response.Result);
ShowNotification(string(notification['status']));
ShowToast(string(notification['status']));
xdwdsShipTo.Close;
xdwdsShipTo.SetJSONData(notification['ADDRESS']);
xdwdsShipTo.Open;
end;
procedure TFOrderEntryCuttingDie.ShowAddAddressForm;
// displays the search pop-up that allows the user to filter the order list
var
......@@ -159,6 +190,7 @@ begin
newform.Caption := 'Shipping Information';
newForm.Popup := True;
newForm.Border := fbDialog;
newForm.Position := poScreenCenter;
// used to manage Back button handling to close subform
window.location.hash := 'subform';
......@@ -193,6 +225,7 @@ begin
);
end;
function TFOrderEntryCuttingDie.VerifyOrder: Boolean;
var
input: TJSHTMLInputElement;
......@@ -249,6 +282,7 @@ begin
input.classList.remove('is-invalid');
end;
procedure TFOrderEntryCuttingDie.SendOrderToServer;
var
orderJSON: TJSONObject;
......@@ -296,14 +330,14 @@ begin
orderJSON.AddPair('ORDER_ID', orderID);
if mode = 'ADD' then
ShowNotification('Success:Order Added Successfully!')
ShowToast('Success: Order Added Successfully!')
else
ShowNotification('Success:Order Edited Successfully');
ShowToast('Success: Order Edited Successfully');
AddCuttingDieOrder(orderJSON);
end;
procedure TFOrderEntryCuttingDie.btnSaveClick(Sender: TObject);
// Converts all the information on the page into a JSON to then send to the server
begin
......@@ -315,81 +349,57 @@ begin
window.scrollTo(0, 0);
end;
procedure TFOrderEntryCuttingDie.btnCopyClick(Sender: TObject);
begin
mode := 'ADD';
dtpOrderDate.Date := 0;
dtpProofDate.Date := 0;
edtOrderNum.Text := '';
ShowNotification('Success:Order Successfully Copied');
ShowToast('Success: Order Successfully Copied');
EditMode();
window.scrollTo(0, 0);
end;
procedure TFOrderEntryCuttingDie.btnDeleteClick(Sender: TObject);
begin
asm
var modal = document.getElementById('confirmation_modal');
// ensure the modal is directly under <body>
if (modal && modal.parentNode !== document.body) {
document.body.appendChild(modal);
}
var bsModal = new bootstrap.Modal(modal, {
keyboard: false
});
bsModal.show();
ShowConfirmationModal(
'Are you sure you want to delete this order?',
'Delete',
'Cancel',
procedure(confirmed: Boolean)
begin
if confirmed then
begin
Utils.ShowSpinner('spinner');
DelOrder();
tmrReturn.Enabled := true;
end;
end
);
end;
procedure TFOrderEntryCuttingDie.btnEditClick(Sender: TObject);
begin
EditMode();
EditMode;
end;
procedure TFOrderEntryCuttingDie.DelOrder();
var
Response: TXDataClientResponse;
begin
Response := await(XDataWebClient1.RawInvokeAsync('ILookupService.DelOrder',
[OrderID, 'corrugated', JS.toString(AuthService.TokenPayload.Properties['user_id'])]));
Response := await(XDataWebClient1.RawInvokeAsync('ILookupService.DelOrder', [OrderID, 'cutting', JS.toString(AuthService.TokenPayload.Properties['user_id'])]));
end;
procedure TFOrderEntryCuttingDie.btnPDFClick(Sender: TObject);
begin
GenerateReportPDF;
end;
procedure TFOrderEntryCuttingDie.btn_confirm_deleteClick(Sender: TObject);
begin
if document.getElementById('btn_confirm_delete').innerText = 'Yes' then
begin
FViewMain.change := false;
if OrderID <> '' then
begin
FViewMain.ViewOrderEntryCuttingDie(OrderID, '', 'EDIT', 'Failure:Changes Discarded');
end
else
FViewMain.ViewOrders('');
end
else
begin
Utils.ShowSpinner('spinner');
asm
var modal = document.getElementById('confirmation_modal');
// ensure the modal lives directly under <body>
if (modal && modal.parentNode !== document.body) {
document.body.appendChild(modal);
}
var bsModal = new bootstrap.Modal(modal, {
keyboard: false
});
bsModal.hide();
end;
delOrder();
tmrReturn.Enabled := true;
end;
end;
[async] procedure TFOrderEntryCuttingDie.GenerateReportPDF;
// sends the search to the server which then sends back a pdf of the results
......@@ -398,7 +408,7 @@ var
searchOptions, pdfURL: string;
jsObject: TJSObject;
begin
try
// Call the server method to generate the PDF
console.log(orderID);
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GenerateOrderCuttingPDF', [orderID]));
......@@ -408,43 +418,34 @@ begin
// Open the PDF in a new browser tab without needing a different form
// This method is much faster too, even for large datasets
window.open(pdfURL, '_blank');
except
on E: EXDataClientRequestException do
Utils.ShowErrorModal('Could not generate cutting die PDF: ' + E.ErrorResult.ErrorMessage);
end;
end;
procedure TFOrderEntryCuttingDie.AddCuttingDieOrder(orderJSON: TJSONObject);
// sends the order JSON object to the server
var
Response: TXDataClientResponse;
jsObj: TJSObject;
begin
try
Response := await(XDataWebClient1.RawInvokeAsync('ILookupService.AddCuttingDieOrder',
[orderJSON.ToString]));
jsObj := JS.TJSObject(Response.Result);
if mode = 'ADD' then
OrderID := String(jsObj.Properties['OrderID']);
edtOrderNum.Text := OrderID;
mode := 'EDIT';
end;
class function TFOrderEntryCuttingDie.CreateForm(AElementID, orderInfo, customerInfo, mode, info: string): TWebForm;
var
localMode: string;
begin
localMode := mode;
Application.CreateForm(TFOrderEntryCuttingDie, AElementID, Result,
procedure(AForm: TObject)
begin
with TFOrderEntryCuttingDie(AForm) do
begin
HideNotification;
TFOrderEntryCuttingDie(AForm).customerID := customerInfo;
TFOrderEntryCuttingDie(AForm).orderID := orderInfo;
TFOrderEntryCuttingDie(AForm).mode := localMode;
TFOrderEntryCuttingDie(AForm).notification := info;
except
on E: EXDataClientRequestException do
Utils.ShowErrorModal('Could not save cutting die order: ' + E.ErrorResult.ErrorMessage);
end;
end
);
end;
procedure TFOrderEntryCuttingDie.btnAddClick(Sender: TObject);
var
newform: TFAddOrder;
......@@ -455,6 +456,7 @@ begin
newform.Caption := 'Select Customer and Order Type';
newForm.Popup := True;
newForm.Border := fbDialog;
newForm.Position := poScreenCenter;
// used to manage Back button handling to close subform
window.location.hash := 'subform';
......@@ -482,25 +484,28 @@ begin
);
end;
procedure TFOrderEntryCuttingDie.btnCancelClick(Sender: TObject);
begin
document.getElementById('modal_body').innerHTML := 'Are you sure you want to cancel all changes?';
document.getElementById('btn_confirm_cancel').innerText := 'No';
document.getElementById('btn_confirm_delete').innerText := 'Yes';
asm
var modal = document.getElementById('confirmation_modal');
// ensure the modal is directly under <body>
if (modal && modal.parentNode !== document.body) {
document.body.appendChild(modal);
}
var bsModal = new bootstrap.Modal(modal, {
keyboard: false
});
bsModal.show();
ShowConfirmationModal(
'Are you sure you want to cancel all changes?',
'Yes',
'No',
procedure(confirmed: Boolean)
begin
if confirmed then
begin
FViewMain.change := false;
if OrderID <> '' then
FViewMain.ViewOrderEntryCuttingDie(OrderID, '', 'EDIT', 'Failure: Changes Discarded')
else
FViewMain.ViewOrders('');
end;
end
);
end;
procedure TFOrderEntryCuttingDie.btnCloseClick(Sender: TObject);
begin
FViewMain.ViewOrders('');
......@@ -509,12 +514,10 @@ end;
procedure TFOrderEntryCuttingDie.WebFormCreate(Sender: TObject);
begin
if not DMConnection.ApiConnection.Connected then
begin
DMConnection.ApiConnection.OpenAsync;
console.log('report requirements connection open')
end;
end;
procedure TFOrderEntryCuttingDie.getCuttingDieOrder(Order_ID: string);
// retrieves an order from the server then loads the info into the page
var
......@@ -524,6 +527,8 @@ var
data: TJSArray;
order, items: TJSObject;
begin
Utils.ShowSpinner('spinner');
try
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GetCuttingDieOrder',
[Order_ID]));
order := TJSObject(xdcResponse.Result);
......@@ -533,7 +538,6 @@ begin
XDataWebDataSet1.Open;
// Check boxes and dates need to be manually set
if not (XDataWebDataSet1staff_fields_order_date.AsString = '') then
dtpOrderDate.Date := StrToDateTime(XDataWebDataSet1staff_fields_order_date.Value)
else
......@@ -566,8 +570,14 @@ begin
xdwdsQBItem.SetJsonData(items['data']);
xdwdsQBITEM.Open;
except
on E: EXDataClientRequestException do
Utils.ShowErrorModal('Could not retrieve order: ' + E.ErrorResult.ErrorMessage);
end;
Utils.HideSpinner('spinner');
end;
procedure TFOrderEntryCuttingDie.getCustomer(customerID: string);
// gets a customer from the database then loads the appropiate fields
var
......@@ -598,63 +608,6 @@ begin
items := TJSObject(customer['ITEMS']);
xdwdsQBItem.SetJsonData(items['data']);
xdwdsQBITEM.Open;
end;
procedure TFOrderEntryCuttingDie.WebFormShow(Sender: TObject);
begin
if mode <> 'ADD' then
begin
getCuttingDieOrder(orderID);
ViewMode();
end
else
begin
getCustomer(customerID);
EditMode();
end;
edtOrderNum.Text := OrderID;
if notification = '' then
begin
HideNotification;
end
else
begin
ShowNotification(notification);
end;
end;
procedure TFOrderEntryCuttingDie.HideNotification;
begin
pnlMessage.ElementHandle.hidden := True;
end;
procedure TFOrderEntryCuttingDie.ShowNotification(Notification: string);
var
splitNotification: TArray<string>;
begin
if Notification <> '' then
begin
splitNotification := Notification.Split([':']);
if(splitNotification[0] = 'Success') then
begin
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-danger');
messageDiv.classList.add('alert-success');
end;
end
else
begin
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-success');
messageDiv.classList.add('alert-danger');
end;
end;
lblMessage.Caption := splitNotification[1];
pnlMessage.ElementHandle.hidden := False;
end;
end;
......@@ -665,14 +618,10 @@ begin
FViewMain.ViewOrders('Success: Order Successfully Deleted');
end;
procedure TFOrderEntryCuttingDie.tmrScrollTopTimer(Sender: TObject);
begin
tmrScrollTop.Enabled := False;
window.scrollTo(0, 0);
end;
procedure TFOrderEntryCuttingDie.EditMode;
begin
XDataWebDataSet1.Edit;
FViewMain.change := true;
btnCopy.Enabled := false;
btnPDF.Enabled := false;
......@@ -682,27 +631,12 @@ begin
btnCancel.Enabled := True;
btnEdit.Enabled := false;
btnAdd.Enabled := false;
end;
procedure TFOrderEntryCuttingDie.xdwdsQBItemAfterEdit(DataSet: TDataSet);
begin
EditMode();
end;
procedure TFOrderEntryCuttingDie.xdwdsShipToAfterEdit(DataSet: TDataSet);
begin
EditMode();
end;
procedure TFOrderEntryCuttingDie.XDataWebDataSet1AfterEdit(DataSet: TDataSet);
begin
EditMode();
lblFormState.Caption := 'Edit Mode';
lblFormState.ElementHandle.classList.remove('text-danger');
lblFormState.ElementHandle.classList.add('text-success');
end;
procedure TFOrderEntryCuttingDie.dtpOrderDateChange(Sender: TObject);
begin
EditMode();
end;
procedure TFOrderEntryCuttingDie.ViewMode;
begin
......@@ -715,8 +649,13 @@ begin
btnEdit.Enabled := true;
btnAdd.Enabled := true;
FViewMain.change := false;
lblFormState.Caption := 'View Mode';
lblFormState.ElementHandle.classList.remove('text-success');
lblFormState.ElementHandle.classList.add('text-danger');
end;
initialization
RegisterClass(TFOrderEntryCuttingDie);
......
object FOrderEntryWeb: TFOrderEntryWeb
Width = 1261
Height = 628
OnShow = WebFormShow
OnCreate = WebFormCreate
object WebLabel2: TWebLabel
Left = 26
Top = 72
......@@ -112,54 +112,27 @@ object FOrderEntryWeb: TFOrderEntryWeb
Visible = False
WidthPercent = 100.000000000000000000
end
object pnlMessage: TWebPanel
Left = 324
Top = 19
Width = 121
Height = 33
ElementID = 'view.login.message'
ChildOrder = 5
ElementPosition = epRelative
Role = 'alert'
TabOrder = 0
object lblMessage: TWebLabel
Left = 28
Top = 9
Width = 46
object lblFormState: TWebLabel
Left = 18
Top = 16
Width = 3
Height = 15
Caption = 'Message'
ElementID = 'view.login.message.label'
ElementPosition = epRelative
ElementID = 'lbl_form_state'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object btnCloseNotification: TWebButton
Left = 96
Top = 3
Width = 22
Height = 25
ChildOrder = 1
ElementID = 'view.login.message.button'
ElementFont = efCSS
ElementPosition = epRelative
HeightStyle = ssAuto
HeightPercent = 100.000000000000000000
Role = 'button'
WidthStyle = ssAuto
WidthPercent = 100.000000000000000000
OnClick = btnCloseNotificationClick
end
end
object edtCompanyName: TWebDBEdit
Left = 24
Top = 92
Width = 260
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtcompanyname'
HeightPercent = 100.000000000000000000
MaxLength = 90
ShowFocus = False
WidthStyle = ssAuto
WidthPercent = 100.000000000000000000
DataField = 'NAME'
......@@ -170,10 +143,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 120
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtaccountcompanyname'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'SHORT_NAME'
DataSource = WebDataSource1
......@@ -183,17 +158,19 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 148
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtinquickbooks'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'inQuickBooks'
DataSource = WebDataSource1
end
object dtpOrderDate: TWebDateTimePicker
Left = 22
Top = 218
Left = 24
Top = 215
Width = 170
Height = 22
ElementID = 'dtporderdate'
......@@ -202,8 +179,9 @@ object FOrderEntryWeb: TFOrderEntryWeb
Color = clWhite
Date = 45638.529943136570000000
Role = ''
ShowFocus = False
TabStop = False
Text = ''
OnChange = dtpOrderDateChange
end
object dtpProofDate: TWebDateTimePicker
Left = 22
......@@ -216,8 +194,9 @@ object FOrderEntryWeb: TFOrderEntryWeb
Color = clWhite
Date = 45638.529943136570000000
Role = ''
ShowFocus = False
TabStop = False
Text = ''
OnChange = dtpOrderDateChange
end
object dtpShipDate: TWebDateTimePicker
Left = 22
......@@ -230,8 +209,9 @@ object FOrderEntryWeb: TFOrderEntryWeb
Color = clWhite
Date = 45638.529943136570000000
Role = ''
ShowFocus = False
TabStop = False
Text = ''
OnChange = dtpOrderDateChange
end
object dtpArtDue: TWebDateTimePicker
Left = 24
......@@ -244,8 +224,9 @@ object FOrderEntryWeb: TFOrderEntryWeb
Color = clWhite
Date = 45638.529943136570000000
Role = ''
ShowFocus = False
TabStop = False
Text = ''
OnChange = dtpOrderDateChange
end
object dtpPlateDue: TWebDateTimePicker
Left = 24
......@@ -258,43 +239,50 @@ object FOrderEntryWeb: TFOrderEntryWeb
Color = clWhite
Date = 45638.529943136570000000
Role = ''
ShowFocus = False
TabStop = False
Text = ''
OnChange = dtpOrderDateChange
end
object edtShipVia: TWebDBEdit
Left = 24
Top = 314
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtshipvia'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'staff_fields_ship_via'
DataSource = WebDataSource1
end
object edtQuantity: TWebDBEdit
Left = 24
Top = 346
Top = 345
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtquantity'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'staff_fields_quantity'
DataSource = WebDataSource1
end
object edtPrice: TWebDBEdit
Left = 24
Left = 26
Top = 374
Width = 121
Height = 22
TabStop = False
ChildOrder = 79
ElementID = 'edtprice'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'staff_fields_price'
DataSource = WebDataSource1
......@@ -304,10 +292,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 402
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtinvoiceto'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'staff_fields_invoice_to'
DataSource = WebDataSource1
......@@ -317,34 +307,40 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 458
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtponumber'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'staff_fields_po_number'
DataSource = WebDataSource1
end
object edtJobName: TWebDBEdit
Left = 26
Top = 486
Left = 30
Top = 487
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtjobname'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'staff_fields_job_name'
DataSource = WebDataSource1
end
object WebDBComboBox1: TWebDBComboBox
Left = 26
Top = 430
Top = 429
Width = 145
Height = 23
ElementID = 'wcbshipto'
HeightPercent = 100.000000000000000000
ShowFocus = False
TabStop = False
WidthPercent = 100.000000000000000000
ItemIndex = -1
DataField = 'staff_fields_ship_to'
......@@ -357,10 +353,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 214
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtbworcolorcopy'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'supplied_by_customer_b_w_or_co'
DataSource = WebDataSource1
......@@ -370,23 +368,27 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 243
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtplates'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'supplied_by_customer_plates'
DataSource = WebDataSource1
end
object edtDimensionalLayout: TWebDBEdit
Left = 276
Top = 314
Top = 311
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtdimensionallayout'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'supplied_by_customer_dimension'
DataSource = WebDataSource1
......@@ -396,10 +398,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 281
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtsample'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'supplied_by_customer_sample'
DataSource = WebDataSource1
......@@ -409,10 +413,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 346
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtother'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'supplied_by_customer_other'
DataSource = WebDataSource1
......@@ -422,10 +428,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 379
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtemail'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'supplied_by_customer_e_mail'
DataSource = WebDataSource1
......@@ -435,10 +443,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 442
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edttotalinchesused'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'supplied_by_customer_total_inc'
DataSource = WebDataSource1
......@@ -448,10 +458,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 408
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtftp'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'supplied_by_customer_ftp'
DataSource = WebDataSource1
......@@ -461,10 +473,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 471
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtsheetsused'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'supplied_by_customer_sheets_us'
DataSource = WebDataSource1
......@@ -474,10 +488,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 504
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtinitials'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'supplied_by_customer_initials'
DataSource = WebDataSource1
......@@ -487,10 +503,13 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 96
Width = 113
Height = 22
TabStop = False
Caption = 'PDF'
ChildOrder = 79
ElementID = 'cbpdf'
Enabled = False
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'proofing_pdf'
DataSource = WebDataSource1
......@@ -500,10 +519,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 128
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtpdfto'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'proofing_pdf_to'
DataSource = WebDataSource1
......@@ -519,8 +540,9 @@ object FOrderEntryWeb: TFOrderEntryWeb
Color = clWhite
Date = 45638.529943136570000000
Role = ''
ShowFocus = False
TabStop = False
Text = ''
OnChange = dtpOrderDateChange
end
object dtpPDFDate3: TWebDateTimePicker
Left = 444
......@@ -533,8 +555,9 @@ object FOrderEntryWeb: TFOrderEntryWeb
Color = clWhite
Date = 45638.529943136570000000
Role = ''
ShowFocus = False
TabStop = False
Text = ''
OnChange = dtpOrderDateChange
end
object dtpPDFDate2: TWebDateTimePicker
Left = 444
......@@ -547,18 +570,22 @@ object FOrderEntryWeb: TFOrderEntryWeb
Color = clWhite
Date = 45638.529943136570000000
Role = ''
ShowFocus = False
TabStop = False
Text = ''
OnChange = dtpOrderDateChange
end
object cbInkJet: TWebDBCheckBox
Left = 444
Top = 238
Width = 113
Height = 22
TabStop = False
Caption = 'Full Size Ink Jet For Layout Content Only'
ChildOrder = 79
ElementID = 'cbfullsizeinkjet'
Enabled = False
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'proofing_full_size_ink_jet_for'
DataSource = WebDataSource1
......@@ -568,10 +595,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 295
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtinkjetto2'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'proofing_ink_jet_to_2'
DataSource = WebDataSource1
......@@ -581,10 +610,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 266
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtinkjetto'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'proofing_ink_jet_to'
DataSource = WebDataSource1
......@@ -600,8 +631,9 @@ object FOrderEntryWeb: TFOrderEntryWeb
Color = clWhite
Date = 45638.529943136570000000
Role = ''
ShowFocus = False
TabStop = False
Text = ''
OnChange = dtpOrderDateChange
end
object dtpInkJetDate3: TWebDateTimePicker
Left = 444
......@@ -614,8 +646,9 @@ object FOrderEntryWeb: TFOrderEntryWeb
Color = clWhite
Date = 45638.529943136570000000
Role = ''
ShowFocus = False
TabStop = False
Text = ''
OnChange = dtpOrderDateChange
end
object dtpInkJetDate2: TWebDateTimePicker
Left = 444
......@@ -628,18 +661,21 @@ object FOrderEntryWeb: TFOrderEntryWeb
Color = clWhite
Date = 45638.529943136570000000
Role = ''
ShowFocus = False
TabStop = False
Text = ''
OnChange = dtpOrderDateChange
end
object edtColorContrastTo: TWebDBEdit
Left = 444
Top = 435
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtcolorcontrastto'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'proofing_color_contrac_to'
DataSource = WebDataSource1
......@@ -655,8 +691,9 @@ object FOrderEntryWeb: TFOrderEntryWeb
Color = clWhite
Date = 45638.529943136570000000
Role = ''
ShowFocus = False
TabStop = False
Text = ''
OnChange = dtpOrderDateChange
end
object dtpColorContractDate2: TWebDateTimePicker
Left = 444
......@@ -669,18 +706,21 @@ object FOrderEntryWeb: TFOrderEntryWeb
Color = clWhite
Date = 45638.529943136570000000
Role = ''
ShowFocus = False
TabStop = False
Text = ''
OnChange = dtpOrderDateChange
end
object edtDigitalColorTo: TWebDBEdit
Left = 444
Top = 545
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtdigitalcolorto'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'proofing_digital_color_to'
DataSource = WebDataSource1
......@@ -690,10 +730,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 516
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtdigitalcolorkey'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'proofing_digital_color_key'
DataSource = WebDataSource1
......@@ -709,18 +751,21 @@ object FOrderEntryWeb: TFOrderEntryWeb
Color = clWhite
Date = 45638.529943136570000000
Role = ''
ShowFocus = False
TabStop = False
Text = ''
OnChange = dtpOrderDateChange
end
object edtAniloxInfo: TWebDBEdit
Left = 634
Top = 58
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtanilaxinfo'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'quantity_and_colors_anilox_info'
DataSource = WebDataSource1
......@@ -730,10 +775,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 29
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtpressname'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'quantity_and_colors_press_name'
DataSource = WebDataSource1
......@@ -743,10 +790,11 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 87
Width = 96
Height = 25
Caption = '+'
Caption = 'Add Color'
ChildOrder = 59
ElementID = 'btnaddcolor'
HeightPercent = 100.000000000000000000
TabStop = False
WidthPercent = 100.000000000000000000
OnClick = WebButton1Click
end
......@@ -755,10 +803,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 139
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtmicrodots'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'plate_marks_microdots'
DataSource = WebDataSource1
......@@ -768,10 +818,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 168
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtmicrodotscomments'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'plate_marks_microdots_comments'
DataSource = WebDataSource1
......@@ -781,10 +833,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 239
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtcrosshairscomments'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'plate_marks_crosshairs_comments'
DataSource = WebDataSource1
......@@ -794,10 +848,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 206
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtcrosshairs'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'plate_marks_crosshairs'
DataSource = WebDataSource1
......@@ -807,10 +863,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 300
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtcolorbarscomments'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'plate_marks_color_bars_comments'
DataSource = WebDataSource1
......@@ -820,10 +878,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 271
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtcolorbars'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'plate_marks_color_bars'
DataSource = WebDataSource1
......@@ -833,10 +893,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 329
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtplateother'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'plate_marks_other'
DataSource = WebDataSource1
......@@ -846,10 +908,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 358
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtplateothercomments'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'plate_marks_other_comments'
DataSource = WebDataSource1
......@@ -859,10 +923,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 29
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtaround'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'layout_around'
DataSource = WebDataSource1
......@@ -872,10 +938,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 58
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtaccross'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'layout_accross'
DataSource = WebDataSource1
......@@ -885,10 +953,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 129
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtreverseprint'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'layout_reverse_print'
DataSource = WebDataSource1
......@@ -898,10 +968,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 96
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtsurfaceprint'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'layout_surface_print'
DataSource = WebDataSource1
......@@ -911,10 +983,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 190
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtcutoffdimension'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'layout_cutoff_dimension'
DataSource = WebDataSource1
......@@ -924,10 +998,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 161
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtcylinderrepeat'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'layout_cylinder_repeat'
DataSource = WebDataSource1
......@@ -937,10 +1013,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 219
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtpitch'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'layout_pitch'
DataSource = WebDataSource1
......@@ -950,10 +1028,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 282
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtbleed'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'layout_bleed'
DataSource = WebDataSource1
......@@ -963,10 +1043,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 248
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtteeth'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'layout_teeth'
DataSource = WebDataSource1
......@@ -976,10 +1058,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 311
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtcutback'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'layout_cutback'
DataSource = WebDataSource1
......@@ -989,10 +1073,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 344
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtminimumtrapdimension'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'layout_minimum_trap_dim'
DataSource = WebDataSource1
......@@ -1002,10 +1088,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 373
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtmaximumtrapdimension'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'layout_maximum_trap_dim'
DataSource = WebDataSource1
......@@ -1015,10 +1103,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 423
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtsize'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'upc_size'
DataSource = WebDataSource1
......@@ -1028,10 +1118,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 452
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtbarwidthreduction'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'upc_bar_width_reduction'
DataSource = WebDataSource1
......@@ -1041,10 +1133,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 523
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtdistortionamount'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'upc_distortion_amount'
DataSource = WebDataSource1
......@@ -1054,10 +1148,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 490
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtdistortionpercent'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'upc_distortion_percent'
DataSource = WebDataSource1
......@@ -1067,10 +1163,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 516
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtjobnumber'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'plates_job_number'
DataSource = WebDataSource1
......@@ -1080,10 +1178,12 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 160
Width = 121
Height = 23
TabStop = False
AutoSize = True
ChildOrder = 79
ElementID = 'edtcomments'
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
DataField = 'general_comments'
DataSource = WebDataSource1
......@@ -1097,6 +1197,7 @@ object FOrderEntryWeb: TFOrderEntryWeb
ChildOrder = 79
ElementID = 'btnconfirm'
HeightPercent = 100.000000000000000000
TabStop = False
WidthPercent = 100.000000000000000000
OnClick = btnSaveClick
end
......@@ -1109,6 +1210,7 @@ object FOrderEntryWeb: TFOrderEntryWeb
ChildOrder = 79
ElementID = 'btnpdf'
HeightPercent = 100.000000000000000000
TabStop = False
WidthPercent = 100.000000000000000000
OnClick = btnPDFClick
end
......@@ -1121,6 +1223,7 @@ object FOrderEntryWeb: TFOrderEntryWeb
ChildOrder = 79
ElementID = 'btncancel'
HeightPercent = 100.000000000000000000
TabStop = False
WidthPercent = 100.000000000000000000
OnClick = btnCancelClick
end
......@@ -1131,6 +1234,8 @@ object FOrderEntryWeb: TFOrderEntryWeb
Height = 23
ElementID = 'wcbqbitem'
HeightPercent = 100.000000000000000000
ShowFocus = False
TabStop = False
WidthPercent = 100.000000000000000000
ItemIndex = -1
DataField = 'staff_fields_quickbooks_item'
......@@ -1145,6 +1250,8 @@ object FOrderEntryWeb: TFOrderEntryWeb
Height = 23
ElementID = 'wcbmaterial'
HeightPercent = 100.000000000000000000
ShowFocus = False
TabStop = False
WidthPercent = 100.000000000000000000
ItemIndex = -1
Items.Strings = (
......@@ -1160,6 +1267,8 @@ object FOrderEntryWeb: TFOrderEntryWeb
Height = 23
ElementID = 'wcbthickness'
HeightPercent = 100.000000000000000000
ShowFocus = False
TabStop = False
WidthPercent = 100.000000000000000000
ItemIndex = -1
Items.Strings = (
......@@ -1178,6 +1287,8 @@ object FOrderEntryWeb: TFOrderEntryWeb
Height = 23
ElementID = 'wcbprint'
HeightPercent = 100.000000000000000000
ShowFocus = False
TabStop = False
WidthPercent = 100.000000000000000000
ItemIndex = -1
Items.Strings = (
......@@ -1193,6 +1304,8 @@ object FOrderEntryWeb: TFOrderEntryWeb
Height = 23
ElementID = 'wcbcolorcontract'
HeightPercent = 100.000000000000000000
ShowFocus = False
TabStop = False
WidthPercent = 100.000000000000000000
ItemIndex = -1
Items.Strings = (
......@@ -1210,6 +1323,7 @@ object FOrderEntryWeb: TFOrderEntryWeb
ChildOrder = 91
ElementID = 'btncopy'
HeightPercent = 100.000000000000000000
TabStop = False
WidthPercent = 100.000000000000000000
OnClick = btnCopyClick
end
......@@ -1222,6 +1336,7 @@ object FOrderEntryWeb: TFOrderEntryWeb
ChildOrder = 79
ElementID = 'btndelete'
HeightPercent = 100.000000000000000000
TabStop = False
WidthPercent = 100.000000000000000000
OnClick = btnDeleteClick
end
......@@ -1234,6 +1349,7 @@ object FOrderEntryWeb: TFOrderEntryWeb
ChildOrder = 80
ElementID = 'btnclose'
HeightPercent = 100.000000000000000000
TabStop = False
WidthPercent = 100.000000000000000000
OnClick = btnCloseClick
end
......@@ -1242,24 +1358,14 @@ object FOrderEntryWeb: TFOrderEntryWeb
Top = 194
Width = 121
Height = 22
TabStop = False
ChildOrder = 81
ElementID = 'edtordernum'
Enabled = False
HeightPercent = 100.000000000000000000
ShowFocus = False
WidthPercent = 100.000000000000000000
end
object btn_confirm_delete: TWebButton
Left = 1094
Top = 414
Width = 96
Height = 25
Caption = 'Delete'
ChildOrder = 82
ElementID = 'btn_confirm_delete'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnClick = btn_confirm_deleteClick
end
object btnEdit: TWebButton
Left = 1165
Top = 560
......@@ -1269,6 +1375,7 @@ object FOrderEntryWeb: TFOrderEntryWeb
ChildOrder = 83
ElementID = 'btnedit'
HeightPercent = 100.000000000000000000
TabStop = False
WidthPercent = 100.000000000000000000
OnClick = btnEditClick
end
......@@ -1281,6 +1388,7 @@ object FOrderEntryWeb: TFOrderEntryWeb
ChildOrder = 84
ElementID = 'btnadd'
HeightPercent = 100.000000000000000000
TabStop = False
WidthPercent = 100.000000000000000000
OnClick = btnAddClick
end
......@@ -1293,6 +1401,7 @@ object FOrderEntryWeb: TFOrderEntryWeb
ChildOrder = 85
ElementID = 'btnaddaddress'
HeightPercent = 100.000000000000000000
TabStop = False
WidthPercent = 100.000000000000000000
OnClick = WebButton2Click
end
......@@ -1301,17 +1410,10 @@ object FOrderEntryWeb: TFOrderEntryWeb
Left = 160
Top = 18
end
object tmrScrollTop: TWebTimer
Interval = 100
OnTimer = tmrScrollTopTimer
Left = 240
Top = 8
end
object XDataWebDataSet1: TXDataWebDataSet
AfterEdit = XDataWebDataSet1AfterEdit
Connection = DMConnection.ApiConnection
Left = 90
Top = 20
Left = 408
Top = 4
object XDataWebDataSet1ORDER_ID: TIntegerField
FieldName = 'ORDER_ID'
end
......@@ -1568,32 +1670,33 @@ object FOrderEntryWeb: TFOrderEntryWeb
end
end
object WebDataSource1: TWebDataSource
AutoEdit = False
DataSet = XDataWebDataSet1
Left = 22
Top = 10
Left = 406
Top = 38
end
object wdsShipTo: TWebDataSource
AutoEdit = False
DataSet = xdwdsShipTo
Left = 212
Top = 436
Left = 320
Top = 38
end
object xdwdsShipTo: TXDataWebDataSet
AfterEdit = XDataWebDataSet1AfterEdit
Left = 208
Top = 398
Left = 322
Top = 6
object xdwdsShipToADDRESS: TStringField
FieldName = 'ADDRESS'
end
end
object wdsQBItem: TWebDataSource
AutoEdit = False
DataSet = xdwdsQBItem
Left = 240
Top = 518
Left = 244
Top = 34
end
object xdwdsQBItem: TXDataWebDataSet
AfterEdit = XDataWebDataSet1AfterEdit
Left = 200
Top = 512
Left = 246
Top = 2
object xdwdsQBItemname: TStringField
FieldName = 'name'
end
......@@ -1601,7 +1704,7 @@ object FOrderEntryWeb: TFOrderEntryWeb
object tmrReturn: TWebTimer
Enabled = False
OnTimer = tmrReturnTimer
Left = 306
Top = 62
Left = 216
Top = 258
end
end
<nav class="navbar navbar-expand navbar-light bg-light sticky-top" style="z-index: 100;">
<div class="container-fluid ps-0">
<div id="view.login.message" class="alert alert-danger"
style="padding: 0.25rem 0.5rem; font-size: 0.875rem; line-height: 1.5; display: flex; align-items: center; margin: 0 0 0 60px; height: 32px; width: 400px;">
<button id="view.login.message.button" type="button" class="btn-close" aria-label="Close"></button>
<span id="view.login.message.label"></span>
</div>
<ul class="navbar-nav me-auto ps-2">
<nav class="navbar navbar-expand navbar-light bg-light border-light sticky-top" style="z-index: 100;">
<div class="container-fluid d-flex align-items-center ps-0 pe-0">
<!-- Left-aligned label -->
<div class="me-auto ps-3">
<label id="lbl_form_state" class="form-label mb-0 fw-bold text-uppercase text-nowrap text-danger" style="font-size: 16px;">Test</label>
</div>
<!-- Right-aligned buttons -->
<ul class="navbar-nav ms-auto pe-2 mb-0">
<li class="nav-item pe-2">
<button id="btnadd" class="btn btn-primary btn-sm">Add</button>
</li>
......@@ -28,9 +30,10 @@
<button id="btncancel" class="btn btn-danger btn-sm">Cancel</button>
</li>
<li class="nav-item">
<button id="btnclose" class="btn btn-secondary btn-sm">Close</button>
<button id="btnclose" class="btn btn-primary btn-sm">Close</button>
</li>
</ul>
</div>
</nav>
<div class="row mx-5">
......@@ -248,25 +251,43 @@
<input class="form-control input-sm" id="dtpdigitalcolordate" type="date">
</div>
</div>
<h4 class="custom-h4 mt-3">Quantity and Colors</h4>
<h4 class="custom-h4 mt-3">Quantity</h4>
<hr class="custom-hr">
<div class="row">
<div class="col-auto">
<label style="font-weight: 700; font-size: 15px;" class="form-label mt-2">Press Name:</label>
<input id="edtpressname" class="form-control input-sm" width='50%'/>
<input id="edtpressname" class="form-control input-sm" width="50%" />
</div>
<div class="col-auto">
<label style="font-weight: 700; font-size: 15px;" class="form-label mt-2">Anilax Info:</label>
<input id="edtanilaxinfo" class="form-control input-sm" width='50%'/>
</div>
<div class="col-auto">
<label for="wdbe_first_name" style="font-weight: 700; font-size: 15px;" class="form-label mt-2">Colors:</label>
<button id="btnaddcolor" class="btn btn-primary btn-sm float-end">+</button>
<div id="additionalFields" class="row mt-3"></div>
<input id="edtanilaxinfo" class="form-control input-sm" width="50%" />
</div>
</div>
<h4 class="custom-h4 mt-3">Colors</h4>
<hr class="custom-hr">
<div class="row align-items-center">
<!-- placeholders for the 4 dynamic input columns to center the Add Color button -->
<div class="col-sm"></div>
<div class="col-sm"></div>
<div class="col-sm"></div>
<div class="col-sm"></div>
<div class="col-auto d-flex justify-content-center">
<!-- Delphi-generated TWebButton stays here -->
<button id="btnaddcolor" class="btn btn-primary btn-sm me-3">
Add Color
</button>
</div>
</div>
<!-- Dynamically injected color rows go here -->
<div id="additionalFields" class="row mt-3"></div>
<h4 class="custom-h4 mt-3">Plate Marks</h4>
<hr class="custom-hr">
<div class="row">
<div class="col-auto">
<label label style="font-weight: 700; font-size: 15px;" class="form-label mt-2">Microdots:</label>
......@@ -404,53 +425,5 @@
<textarea id="edtcomments" class="form-control" style=" width: 500px; height: 150px;"></textarea>
</div>
</div>
<div class="row">
<div class="col-auto">
<button id="btnconfirm" class="btn btn-primary btn-sm float-end my-2">Save</button>
</div>
<div class="col-auto">
<button id="btncancel" class="btn btn-primary btn-sm float-end my-2">Cancel</button>
</div>
<div class="col-auto">
<button id="btncopy" class="btn btn-primary btn-sm float-end my-2">Copy</button>
</div>
<div class="col-auto">
<button id="btnpdf" class="btn btn-primary btn-sm float-end my-2">PDF</button>
</div>
<div class="col-auto">
<button id="btndelete" class="btn btn-primary btn-sm float-end my-2">Delete</button>
</div>
<div class="col-auto">
<button id="btnclose" class="btn btn-primary btn-sm float-end my-2">Close</button>
</div>
<div class="col-auto">
<button id="btnedit" class="btn btn-primary btn-sm float-end my-2">Edit</button>
</div>
<div class="col-auto">
<button id="btnadd" class="btn btn-primary btn-sm float-end my-2">Add</button>
</div>
</div>
</div>
<div class="modal fade" id="confirmation_modal" tabindex="-1" aria-labelledby="confirmation_modal_label" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="confirmation_modal_label">Confirm</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body" id="modal_body">
Are you sure you want to delete this order?
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" id=btn_confirm_cancel>Cancel</button>
<button type="button" class="btn btn-primary" data-bs-dismiss="modal" id="btn_confirm_delete">Delete</button>
</div>
</div>
</div>
</div>
</div>
<style>
.modal-backdrop {
opacity: 0 !important;
}
</style>
......@@ -7,19 +7,15 @@ uses
WEBLib.Forms, WEBLib.Dialogs, WEBLib.Menus, WEBLib.ExtCtrls, WEBLib.StdCtrls,
WEBLib.JSON, Auth.Service, XData.Web.Client, WebLib.Storage,
ConnectionModule, App.Types, Vcl.StdCtrls, Vcl.Controls, WEBLib.DBCtrls,
Data.DB, XData.Web.JsonDataset, XData.Web.Dataset, WEBLib.DB;
Data.DB, XData.Web.JsonDataset, XData.Web.Dataset, WEBLib.DB, VCL.Forms;
type
TFOrderEntryWeb = class(TWebForm)
WebLabel2: TWebLabel;
pnlMessage: TWebPanel;
lblMessage: TWebLabel;
btnCloseNotification: TWebButton;
edtCompanyName: TWebDBEdit;
edtCompanyAccountName: TWebDBEdit;
edtInQuickBooks: TWebDBEdit;
XDataWebClient1: TXDataWebClient;
tmrScrollTop: TWebTimer;
XDataWebDataSet1: TXDataWebDataSet;
XDataWebDataSet1ORDER_ID: TIntegerField;
XDataWebDataSet1COMPANY_ID: TIntegerField;
......@@ -202,18 +198,14 @@ type
btnDelete: TWebButton;
btnClose: TWebButton;
edtOrderNum: TWebEdit;
btn_confirm_delete: TWebButton;
tmrReturn: TWebTimer;
btnEdit: TWebButton;
btnAdd: TWebButton;
WebButton2: TWebButton;
lblFormState: TWebLabel;
procedure WebFormCreate(Sender: TObject);
procedure HideNotification();
procedure ShowNotification(Notification: string);
procedure WebFormShow(Sender: TObject);
[async] procedure getOrder(Order_ID: string);
[async] procedure getCustomer(customerID: string);
procedure tmrScrollTopTimer(Sender: TObject);
procedure WebButton1Click(Sender: TObject);
procedure addColorRow(num, Color, LPI, Size: string);
procedure btnSaveClick(Sender: TObject);
......@@ -226,20 +218,17 @@ type
procedure btnCloseClick(Sender: TObject);
procedure btnDeleteClick(Sender: TObject);
[async] procedure DelOrder;
procedure btnCloseNotificationClick(Sender: TObject);
procedure tmrReturnTimer(Sender: TObject);
procedure btn_confirm_deleteClick(Sender: TObject);
function VerifyOrder(): boolean;
procedure btnAddClick(Sender: TObject);
procedure btnEditClick(Sender: TObject);
procedure EditMode();
procedure XDataWebDataSet1AfterEdit(DataSet: TDataSet);
procedure dtpOrderDateChange(Sender: TObject);
procedure ViewMode();
procedure WebButton2Click(Sender: TObject);
procedure ShowAddAddressForm();
[async] procedure SendAddressToServer(AddressJSON: TJSONObject);
private
FModalAction: string;
FAgencyCode: string;
FCurrentReportType: string;
FSelectProc: TSelectProc;
......@@ -247,9 +236,11 @@ type
customerID: string;
mode: string;
notification: string;
procedure RemoveColorRow(Sender: TObject);
[async] procedure InitializeForm;
//FJSONProc1: TJSONProc1;
public
class function CreateForm(AElementID, orderInfo, customerInfo, mode, info: string): TWebForm;
class function CreateForm(AElementID, orderInfo, customerInfo, modeParam, info: string): TWebForm;
end;
var
......@@ -262,6 +253,46 @@ implementation
uses
View.Home, View.Main, View.AddOrder, View.AddAddress, Utils;
class function TFOrderEntryWeb.CreateForm(AElementID, orderInfo, customerInfo, modeParam, info: string): TWebForm;
begin
Application.CreateForm(TFOrderEntryWeb, AElementID, Result,
procedure(AForm: TObject)
begin
with TFOrderEntryWeb(AForm) do
begin
customerID := customerInfo;
orderID := orderInfo;
mode := modeParam;
notification := info;
console.log('Mode in createform: ' + modeParam);
InitializeForm;
end;
end
);
end;
[async] procedure TFOrderEntryWeb.InitializeForm;
begin
if mode = 'ADD' then
begin
await(getCustomer(customerID));
EditMode;
end
else
begin
await(getOrder(orderID));
ViewMode;
end;
edtOrderNum.Text := orderID;
if notification <> '' then
ShowToast(notification);
end;
procedure TFOrderEntryWeb.WebButton2Click(Sender: TObject);
begin
ShowAddAddressForm();
......@@ -276,7 +307,7 @@ begin
[AddressJSON.ToString]));
notification := TJSObject(Response.Result);
ShowNotification(string(notification['status']));
ShowToast(string(notification['status']));
xdwdsShipTo.Close;
xdwdsShipTo.SetJSONData(notification['ADDRESS']);
xdwdsShipTo.Open;
......@@ -294,6 +325,7 @@ begin
newform.Caption := 'Input Shipping Information';
newForm.Popup := True;
newForm.Border := fbDialog;
newForm.Position := poScreenCenter;
// used to manage Back button handling to close subform
window.location.hash := 'subform';
......@@ -412,24 +444,27 @@ begin
dtpDigitalColorDate.Date := 0;
edtOrderNum.Text := '';
EditMode();
ShowNotification('Success:Order Successfully Copied');
ShowToast('Success: Order Successfully Copied');
window.scrollTo(0, 0);
end;
procedure TFOrderEntryWeb.btnDeleteClick(Sender: TObject);
begin
asm
var modal = document.getElementById('confirmation_modal');
// ensure the modal is directly under <body>
if (modal && modal.parentNode !== document.body) {
document.body.appendChild(modal);
}
var bsModal = new bootstrap.Modal(modal, {
keyboard: false
});
bsModal.show();
ShowConfirmationModal(
'Are you sure you want to delete this order?',
'Delete',
'Cancel',
procedure(confirmed: Boolean)
begin
if confirmed then
begin
Utils.ShowSpinner('spinner');
DelOrder();
tmrReturn.Enabled := true;
end;
end
);
end;
procedure TFOrderEntryWeb.btnEditClick(Sender: TObject);
......@@ -437,30 +472,12 @@ begin
EditMode();
end;
procedure TFOrderEntryWeb.EditMode;
begin
FViewMain.change := true;
btnCopy.Enabled := false;
btnPDF.Enabled := false;
btnDelete.Enabled := false;
btnClose.Enabled := false;
btnSave.Enabled := true;
btnCancel.Enabled := True;
btnEdit.Enabled := false;
btnAdd.Enabled := false;
end;
[async] procedure TFOrderEntryWeb.DelOrder();
var
Response: TXDataClientResponse;
begin
Response := await(XDataWebClient1.RawInvokeAsync('ILookupService.DelOrder',
[OrderID, 'web', JS.toString(AuthService.TokenPayload.Properties['user_id'])]));
end;
procedure TFOrderEntryWeb.dtpOrderDateChange(Sender: TObject);
begin
EditMode();
Response := await(XDataWebClient1.RawInvokeAsync('ILookupService.DelOrder', [OrderID, 'web', JS.toString(AuthService.TokenPayload.Properties['user_id'])]));
end;
procedure TFOrderEntryWeb.SendOrderToServer();
......@@ -550,7 +567,7 @@ begin
else
info := 'Success:Order Successfully Added';
AddWebOrder(orderJSON);
ShowNotification(info);
ShowToast(info);
end;
procedure TFOrderEntryWeb.btnPDFClick(Sender: TObject);
......@@ -558,38 +575,6 @@ begin
GenerateReportPDF;
end;
procedure TFOrderEntryWeb.btn_confirm_deleteClick(Sender: TObject);
begin
if document.getElementById('btn_confirm_delete').innerText = 'Yes' then
begin
FViewMain.change := false;
if OrderID <> '' then
begin
FViewMain.ViewOrderEntryWeb(OrderID, '', 'EDIT', 'Failure:Changes Discarded');
end
else
FViewMain.ViewOrders('');
end
else
begin
Utils.ShowSpinner('spinner');
asm
var modal = document.getElementById('confirmation_modal');
// ensure the modal is directly under <body>
if (modal && modal.parentNode !== document.body) {
document.body.appendChild(modal);
}
var bsModal = new bootstrap.Modal(modal, {
keyboard: false
});
bsModal.hide();
end;
delOrder();
tmrReturn.Enabled := true;
end;
end;
procedure TFOrderEntryWeb.GenerateReportPDF;
// sends the search to the server which then sends back a pdf of the results
var
......@@ -597,7 +582,7 @@ var
searchOptions, pdfURL: string;
jsObject: TJSObject;
begin
try
// Call the server method to generate the PDF
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GenerateOrderWebPDF', [orderID]));
jsObject := JS.TJSObject(xdcResponse.Result);
......@@ -606,99 +591,107 @@ begin
// Open the PDF in a new browser tab without needing a different form
// This method is much faster too, even for large datasets
window.open(pdfURL, '_blank');
except
on E: EXDataClientRequestException do
Utils.ShowErrorModal('Could not generate web order PDF: ' + E.ErrorResult.ErrorMessage);
end;
end;
procedure TFOrderEntryWeb.AddWebOrder(orderJSON: TJSONObject);
// sends the order JSON object to the server
var
Response: TXDataClientResponse;
jsObj: TJSObject;
begin
Response := await(XDataWebClient1.RawInvokeAsync('ILookupService.AddWebOrder',
[orderJSON.ToString]));
try
Response := await(XDataWebClient1.RawInvokeAsync('ILookupService.AddWebOrder', [orderJSON.ToString]));
jsObj := JS.TJSObject(Response.Result);
if mode = 'ADD' then
OrderID := String(jsObj.Properties['OrderID']);
console.log(OrderID);
edtOrderNum.Text := OrderID;
mode := 'EDIT';
end;
class function TFOrderEntryWeb.CreateForm(AElementID, orderInfo, customerInfo, mode, info: string): TWebForm;
var
localMode: string;
begin
localMode := mode;
Application.CreateForm(TFOrderEntryWeb, AElementID, Result,
procedure(AForm: TObject)
begin
with TFOrderEntryWeb(AForm) do
begin
HideNotification;
TFOrderEntryWeb(AForm).customerID := customerInfo;
TFOrderEntryWeb(AForm).orderID := orderInfo;
TFOrderEntryWeb(AForm).mode := localMode;
TFOrderEntryWeb(AForm).notification := info;
except
on E: EXDataClientRequestException do
Utils.ShowErrorModal('Could not save web order: ' + E.ErrorResult.ErrorMessage);
end;
end
);
end;
procedure TFOrderEntryWeb.addColorRow(num: string; Color: string; LPI: string; Size: string);
// Java script code to add a row of colors when a button is clicked
// all variables are information to be placed in the boxes when loading an order.
// TODO: convert to Delphi
begin
asm
const container = document.getElementById('additionalFields');
// Create a new row for the new fields
const newRow = document.createElement('div');
newRow.className = 'row mb-2';
const labels = ['#', 'Color', 'LPI', 'Size'];
const values = [num, Color, LPI, Size];
labels.forEach((label, index) => {
const col = document.createElement('div');
col.className = 'col-sm';
const labelElement = document.createElement('label');
labelElement.className = 'pe-2';
labelElement.style.fontWeight = '700';
labelElement.style.fontSize = '15px';
labelElement.textContent = label + ':';
const inputElement = document.createElement('input');
inputElement.className = 'form-control input-sm';
inputElement.style.width = '100%';
inputElement.id = 'input-' + container.childElementCount + '-' + index; // Unique ID based on count
inputElement.value = values[index]; // Set the value based on the parameter
col.appendChild(labelElement);
col.appendChild(inputElement);
var
container, newRow, col, labelEl, inputEl, removeCol: TJSHTMLElement;
removeBtn: TWebButton;
values: array[0..3] of string;
labels: array[0..3] of string;
i: Integer;
begin
container := TJSHTMLElement(document.getElementById('additionalFields'));
// Create the new row container
newRow := TJSHTMLElement(document.createElement('div'));
newRow.className := 'row mb-2';
labels[0] := '#'; values[0] := num;
labels[1] := 'Color'; values[1] := color;
labels[2] := 'LPI'; values[2] := LPI;
labels[3] := 'Size'; values[3] := size;
for i := 0 to 3 do
begin
col := TJSHTMLElement(document.createElement('div'));
col.className := 'col-sm';
labelEl := TJSHTMLElement(document.createElement('label'));
labelEl.className := 'pe-2';
labelEl.style.setProperty('font-weight', '700');
labelEl.style.setProperty('font-size', '15px');
labelEl.textContent := labels[i] + ':';
inputEl := TJSHTMLElement(document.createElement('input'));
inputEl.className := 'form-control input-sm';
inputEl.setAttribute('style', 'width: 100%');
inputEl.setAttribute('value', values[i]);
inputEl.setAttribute('id', 'input-' + IntToStr(container.childElementCount) + '-' + IntToStr(i));
col.appendChild(labelEl);
col.appendChild(inputEl);
newRow.appendChild(col);
});
const removeButtonCol = document.createElement('div');
removeButtonCol.className = 'col-auto d-flex align-items-center';
end;
const removeButton = document.createElement('button');
removeButton.className = 'btn btn-danger btn-sm';
removeButton.textContent = 'Remove';
removeButton.addEventListener('click', function() {
container.removeChild(newRow);
});
// Add remove button
removeCol := TJSHTMLElement(document.createElement('div'));
removeCol.className := 'col-auto d-flex align-items-end pb-1';
removeButtonCol.appendChild(removeButton);
newRow.appendChild(removeButtonCol);
removeBtn := TWebButton.Create(Self);
removeBtn.Caption := 'Remove';
removeBtn.ElementClassName := 'btn btn-danger btn-sm mt-1';
removeBtn.ParentElement := removeCol;
removeBtn.ElementHandle.style.setProperty('height', '30px');
removeBtn.OnClick := RemoveColorRow;
newRow.appendChild(removeCol);
container.appendChild(newRow);
end;
procedure TFOrderEntryWeb.RemoveColorRow(Sender: TObject);
var
btn: TWebButton;
rowElement: TJSHTMLElement;
begin
EditMode();
btn := TWebButton(Sender);
if Assigned(btn.ElementHandle) and Assigned(btn.ElementHandle.parentElement) then
begin
// Assuming button is inside a <div> inside the row
rowElement := TJSHTMLElement(btn.ElementHandle.parentElement.parentElement);
if Assigned(rowElement) then
rowElement.remove;
end;
end;
procedure TFOrderEntryWeb.WebButton1Click(Sender: TObject);
begin
EditMode();
addColorRow('','','','');
end;
......@@ -712,6 +705,7 @@ begin
newform.Caption := 'Select Customer and Order Type';
newForm.Popup := True;
newForm.Border := fbDialog;
newForm.Position := poScreenCenter;
// used to manage Back button handling to close subform
window.location.hash := 'subform';
......@@ -741,21 +735,22 @@ end;
procedure TFOrderEntryWeb.btnCancelClick(Sender: TObject);
begin
document.getElementById('modal_body').innerHTML := 'Are you sure you want to cancel all changes?';
document.getElementById('btn_confirm_cancel').innerText := 'No';
document.getElementById('btn_confirm_delete').innerText := 'Yes';
asm
var modal = document.getElementById('confirmation_modal');
// ensure the modal is directly under <body>
if (modal && modal.parentNode !== document.body) {
document.body.appendChild(modal);
}
var bsModal = new bootstrap.Modal(modal, {
keyboard: false
});
bsModal.show();
ShowConfirmationModal(
'Are you sure you want to cancel all changes?',
'Yes',
'No',
procedure(confirmed: Boolean)
begin
if confirmed then
begin
FViewMain.change := false;
if OrderID <> '' then
FViewMain.ViewOrderEntryWeb(OrderID, '', 'EDIT', 'Failure: Changes Discarded')
else
FViewMain.ViewOrders('');
end;
end
);
end;
procedure TFOrderEntryWeb.btnCloseClick(Sender: TObject);
......@@ -763,10 +758,6 @@ begin
FViewMain.ViewOrders('');
end;
procedure TFOrderEntryWeb.btnCloseNotificationClick(Sender: TObject);
begin
hideNotification();
end;
procedure TFOrderEntryWeb.WebFormCreate(Sender: TObject);
begin
......@@ -795,6 +786,8 @@ var
colorListJSON: TJSONArray;
items: TJSObject;
begin
Utils.ShowSpinner('spinner');
try
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GetWebOrder',
[Order_ID]));
order := TJSObject(xdcResponse.Result);
......@@ -802,6 +795,7 @@ begin
XDataWebDataSet1.Close;
XDataWebDataSet1.SetJsonData(order);
XDataWebDataSet1.Open;
if XDataWebDataSet1quantity_and_colors_qty_colors.Value <> '' then
begin
colorObject := TJSObject(TJSJSON.parse(XDataWebDataSet1quantity_and_colors_qty_colors.Value));
......@@ -814,7 +808,6 @@ begin
end;
// Dates need to be manually set
if not (XDataWebDataSet1staff_fields_order_date.AsString = '') then
dtpOrderDate.Date := StrToDateTime(XDataWebDataSet1staff_fields_order_date.Value)
else
......@@ -840,12 +833,10 @@ begin
dtpPDFDate1.Date := StrToDateTime(XDataWebDataSet1proofing_pdf_date_1.Value)
else
dtpPDFDate1.Date := 0;
if not (XDataWebDataSet1proofing_pdf_date_2.AsString = '') then
dtpPDFDate2.Date := StrToDateTime(XDataWebDataSet1proofing_pdf_date_2.Value)
else
dtpPDFDate2.Date := 0;
if not (XDataWebDataSet1proofing_pdf_date_3.AsString = '') then
dtpPDFDate3.Date := StrToDateTime(XDataWebDataSet1proofing_pdf_date_3.Value)
else
......@@ -855,12 +846,10 @@ begin
dtpInkJetDate1.Date := StrToDateTime(XDataWebDataSet1proofing_ink_jet_date_1.Value)
else
dtpInkJetDate1.Date := 0;
if not (XDataWebDataSet1proofing_ink_jet_date_2.AsString = '') then
dtpInkJetDate2.Date := StrToDateTime(XDataWebDataSet1proofing_ink_jet_date_2.Value)
else
dtpInkJetDate2.Date := 0;
if not (XDataWebDataSet1proofing_ink_jet_date_3.AsString = '') then
dtpInkJetDate3.Date := StrToDateTime(XDataWebDataSet1proofing_ink_jet_date_3.Value)
else
......@@ -870,18 +859,15 @@ begin
dtpColorContractDate1.Date := StrToDateTime(XDataWebDataSet1proofing_color_contrac_date_1.Value)
else
dtpColorContractDate1.Date := 0;
if not (XDataWebDataSet1proofing_color_contrac_date_2.AsString = '') then
dtpColorContractDate2.Date := StrToDateTime(XDataWebDataSet1proofing_color_contrac_date_2.Value)
else
dtpColorContractDate2.Date := 0;
if not (XDataWebDataSet1proofing_digital_color_date_1.AsString = '') then
dtpDigitalColorDate.Date := StrToDateTime(XDataWebDataSet1proofing_digital_color_date_1.Value)
else
dtpDigitalColorDate.Date := 0;
if mode = 'EDIT' then
begin
CustomerID := XDataWebDataSet1COMPANY_ID.AsString;
......@@ -894,9 +880,15 @@ begin
items := TJSObject(order['ITEMS']);
xdwdsQBItem.SetJsonData(items['data']);
xdwdsQBITEM.Open;
except
on E: EXDataClientRequestException do
Utils.ShowErrorModal('Could not retrieve order: ' + E.ErrorResult.ErrorMessage);
end;
Utils.HideSpinner('spinner');
end;
procedure TFOrderEntryWeb.getCustomer(customerID: string);
// gets a customer from the database then loads the appropiate fields
var
......@@ -940,68 +932,6 @@ begin
end;
procedure TFOrderEntryWeb.WebFormShow(Sender: TObject);
begin
if mode <> 'ADD' then
begin
getOrder(orderID);
ViewMode();
end
else
begin
getCustomer(customerID);
EditMode();
end;
edtOrderNum.Text := OrderID;
if notification = '' then
begin
HideNotification;
end
else
begin
ShowNotification(notification);
end;
end;
procedure TFOrderEntryWeb.XDataWebDataSet1AfterEdit(DataSet: TDataSet);
begin
EditMode();
end;
procedure TFOrderEntryWeb.HideNotification;
begin
pnlMessage.ElementHandle.hidden := True;
end;
procedure TFOrderEntryWeb.ShowNotification(Notification: string);
var
splitNotification: TArray<string>;
begin
if Notification <> '' then
begin
splitNotification := Notification.Split([':']);
if(splitNotification[0] = 'Success') then
begin
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-danger');
messageDiv.classList.add('alert-success');
end;
end
else
begin
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-success');
messageDiv.classList.add('alert-danger');
end;
end;
lblMessage.Caption := splitNotification[1];
pnlMessage.ElementHandle.hidden := False;
end;
end;
procedure TFOrderEntryWeb.tmrReturnTimer(Sender: TObject);
begin
Utils.HideSpinner('spinner');
......@@ -1009,10 +939,25 @@ begin
FViewMain.ViewOrders('Success: Order Successfully Deleted');
end;
procedure TFOrderEntryWeb.tmrScrollTopTimer(Sender: TObject);
procedure TFOrderEntryWeb.EditMode;
begin
tmrScrollTop.Enabled := False;
window.scrollTo(0, 0);
XDataWebDataSet1.Edit;
FViewMain.change := true;
btnCopy.Enabled := false;
btnPDF.Enabled := false;
btnDelete.Enabled := false;
btnClose.Enabled := false;
btnSave.Enabled := true;
btnCancel.Enabled := True;
btnEdit.Enabled := false;
btnAdd.Enabled := false;
cbPdf.Enabled := True;
cbInkJet.Enabled := True;
lblFormState.Caption := 'Edit Mode';
lblFormState.ElementHandle.classList.remove('text-danger');
lblFormState.ElementHandle.classList.add('text-success');
end;
procedure TFOrderEntryWeb.ViewMode;
......@@ -1026,6 +971,13 @@ begin
btnEdit.Enabled := true;
btnAdd.Enabled := true;
FViewMain.change := false;
cbPdf.Enabled := False;
cbInkJet.Enabled := False;
lblFormState.Caption := 'View Mode';
lblFormState.ElementHandle.classList.remove('text-success');
lblFormState.ElementHandle.classList.add('text-danger');
end;
......
......@@ -237,9 +237,7 @@ object FViewOrders: TFViewOrders
ItemIndex = -1
LookupValues = <
item
Value =
'COALESCE(cpo.staff_fields_order_date, wpo.staff_fields_order_dat' +
'e, cdo.staff_fields_order_date) DESC'
Value = 'o.ORDER_ID DESC'
DisplayText = 'ID'
end
item
......@@ -251,7 +249,9 @@ object FViewOrders: TFViewOrders
DisplayText = 'Job Name'
end
item
Value = 'o.ORDER_DATE DESC'
Value =
'COALESCE(cpo.staff_fields_order_date, wpo.staff_fields_order_dat' +
'e, cdo.staff_fields_order_date) DESC'
DisplayText = 'Order Date'
end
item
......@@ -309,36 +309,6 @@ object FViewOrders: TFViewOrders
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object pnlMessage: TWebPanel
Left = 12
Top = 16
Width = 121
Height = 33
ElementID = 'view.login.message'
ChildOrder = 17
TabOrder = 8
object lblMessage: TWebLabel
Left = 16
Top = 11
Width = 42
Height = 13
Caption = 'Message'
ElementID = 'view.login.message.label'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object btnCloseNotification: TWebButton
Left = 96
Top = 3
Width = 22
Height = 25
ChildOrder = 1
ElementID = 'view.login.message.button'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnClick = btnCloseNotificationClick
end
end
object XDataWebClient1: TXDataWebClient
Connection = DMConnection.ApiConnection
Left = 28
......
<div class="container h-100 d-flex flex-column mt-0 py-0" style="max-width: 100%;">
<!-- Alert Section -->
<div class="row">
<div class=col-sm>
<div id="view.login.message" class="alert alert-danger">
<button id="view.login.message.button" type="button" class="btn-close" aria-label="Close"></button>
<span id="view.login.message.label"></span>
</div>
</div>
</div>
<!-- Actions Row -->
<div class="row mt-2 justify-content-center">
<div class="col-auto d-flex align-items-center">
......
......@@ -13,8 +13,8 @@ uses
WEBLib.Forms, WEBLib.Dialogs, WEBLib.Menus, WEBLib.ExtCtrls, WEBLib.StdCtrls,
WEBLib.JSON, Auth.Service, XData.Web.Client, WebLib.Storage,
ConnectionModule, App.Types, Vcl.StdCtrls, Vcl.Controls, WEBLib.DBCtrls,
XData.Web.JsonDataset, WEBLib.DB, Data.DB, XData.Web.Dataset,
WEBLib.Grids;
XData.Web.JsonDataset, WEBLib.DB, Data.DB, XData.Web.Dataset, XData.Web.DatasetCommon,
WEBLib.Grids, VCL.Forms;
type
TFViewOrders = class(TWebForm)
......@@ -56,15 +56,11 @@ type
wcbPageSize: TWebComboBox;
wlcbOrderBy: TWebLookupComboBox;
edtSearch: TWebEdit;
pnlMessage: TWebPanel;
lblMessage: TWebLabel;
btnCloseNotification: TWebButton;
xdwdsOrdersDBID: TStringField;
tmrReturn: TWebTimer;
procedure WebFormCreate(Sender: TObject);
procedure btnAddOrderClick(Sender: TObject);
procedure btnSearchClick(Sender: TObject);
procedure btnCloseNotificationClick(Sender: TObject);
procedure WebFormShow(Sender: TObject);
procedure btnPDFClick(Sender: TObject);
procedure wcbPageSizeChange(Sender: TObject);
......@@ -73,20 +69,20 @@ type
procedure wdbtcOrdersClickCell(Sender: TObject; ACol, ARow: Integer);
procedure WebButton1Click(Sender: TObject);
procedure tmrReturnTimer(Sender: TObject);
[async] procedure GenerateReportPDFAsync(APdfTab: TJSWindow);
private
FChildForm: TWebForm;
FPendingPdfTab: TJSWindow;
procedure ClearTable();
procedure GeneratePagination(TotalPages: Integer);
function GenerateSearchOptions(): string;
procedure orderEntry(orderInfo, customerInfo, mode, orderType: string);
procedure HideNotification();
procedure ShowNotification(Notification: string);
procedure OrderEntry(orderInfo, customerInfo, mode, orderType: string);
procedure ShowAddOrderForm();
procedure ShowSearchForm();
procedure ShowSetStatusForm();
[async] procedure GetOrders(searchOptions: string);
[async] procedure GenerateReportPDF;
[async] procedure SetStatus(statusInfo: string);
procedure HandlePDFConfirmation;
var
PageNumber: integer;
PageSize: integer;
......@@ -143,32 +139,107 @@ begin
);
end;
procedure TFViewOrders.btnPDFClick(Sender: TObject);
begin
if xdwdsOrders.RecordCount >= 100 then
begin
FPendingPdfTab := nil;
ShowConfirmationModal(
'You are about to generate a PDF for over 100 orders. This may take some time. Continue?',
'Yes',
'Cancel',
procedure(confirmed: Boolean)
begin
if confirmed then
begin
HandlePDFConfirmation;
end;
end
);
end
else
begin
FPendingPdfTab := window.open('', '_blank');
if Assigned(FPendingPdfTab) then
FPendingPdfTab.document.write(
'<!DOCTYPE html>' +
'<html lang="en">' +
'<head>' +
'<meta charset="UTF-8">' +
'<meta name="viewport" content="width=device-width, initial-scale=1.0">' +
'<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">' +
'</head>' +
'<body class="d-flex flex-column justify-content-center align-items-center vh-100 bg-light">' +
'<div class="spinner-border text-primary" role="status" style="width: 3rem; height: 3rem;"></div>' +
'<div class="mt-3 fs-5 text-muted">Generating PDF, please wait</div>' +
'</body>' +
'</html>'
);
Utils.ShowSpinner('spinner');
GenerateReportPDF;
GenerateReportPDFAsync(FPendingPdfTab);
end;
end;
[async] procedure TFViewOrders.GenerateReportPDF;
// sends the search to the server which then sends back a pdf of the results
procedure TFViewOrders.HandlePDFConfirmation;
begin
// Open tab only now
FPendingPdfTab := window.open('', '_blank');
if Assigned(FPendingPdfTab) then
FPendingPdfTab.document.write(
'<!DOCTYPE html>' +
'<html lang="en">' +
'<head>' +
'<meta charset="UTF-8">' +
'<meta name="viewport" content="width=device-width, initial-scale=1.0">' +
'<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">' +
'</head>' +
'<body class="d-flex flex-column justify-content-center align-items-center vh-100 bg-light">' +
'<div class="spinner-border text-primary" role="status" style="width: 3rem; height: 3rem;"></div>' +
'<div class="mt-3 fs-5 text-muted">Generating PDF, please wait</div>' +
'</body>' +
'</html>'
);
Utils.ShowSpinner('spinner');
GenerateReportPDFAsync(FPendingPdfTab);
FPendingPdfTab := nil;
end;
[async] procedure TFViewOrders.GenerateReportPDFAsync(APdfTab: TJSWindow);
var
xdcResponse: TXDataClientResponse;
searchOptions, pdfURL: string;
jsObject: TJSObject;
begin
searchOptions := edtSearch.Text;
// Call the server method to generate the PDF
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GenerateOrderListPDF', [searchOptions]));
jsObject := JS.TJSObject(xdcResponse.Result);
pdfURL := JS.toString(jsObject.Properties['value']);
// Open the PDF in a new browser tab without needing a different form
// This method is much faster too, even for large datasets
window.open(pdfURL, '_blank');
begin
Utils.HideSpinner('Spinner');
try
searchOptions := edtSearch.Text + '&forPDF=true';
xdcResponse := await(
XDataWebClient1.RawInvokeAsync('ILookupService.GenerateOrderListPDF',
[searchOptions]));
jsObject := TJSObject(xdcResponse.Result);
pdfURL := String(jsObject.Properties['value']);
if Assigned(APdfTab) then
APdfTab.location.href := pdfURL;
except
on E: EXDataClientRequestException do
begin
Utils.ShowErrorModal('Could not generate report PDF: ' +
E.ErrorResult.ErrorMessage);
if Assigned(APdfTab) then
APdfTab.close; // close the blank tab on failure
end;
end;
Utils.HideSpinner('spinner');
end;
......@@ -183,7 +254,7 @@ begin
ShowSetStatusForm;
end
else
ShowNotification('Failure:Please select an order');
ShowToast('Failure: Please select an order');
end;
procedure TFViewOrders.WebFormCreate(Sender: TObject);
......@@ -266,14 +337,13 @@ end;
procedure TFViewOrders.WebFormShow(Sender: TObject);
begin
if info <> '' then
ShowNotification(info)
else
HideNotification();
ShowToast(info)
end;
procedure TFViewOrders.wlcbOrderByChange(Sender: TObject);
begin
//console.log(wlcbOrderBy.Value);
OrderBy := wlcbOrderBy.Value;
getOrders(generateSearchOptions());
end;
......@@ -288,6 +358,7 @@ begin
newform.Caption := 'Select Customer and Order Type';
newForm.Popup := True;
newForm.position:= poScreenCenter;
newForm.Border := fbDialog;
// used to manage Back button handling to close subform
......@@ -320,6 +391,7 @@ begin
newform.Caption := 'Input Search Options';
newForm.Popup := True;
newForm.Border := fbDialog;
newForm.position:= poScreenCenter;
newForm.searchOptions := FViewMain.search;
// used to manage Back button handling to close subform
......@@ -370,6 +442,7 @@ begin
newform.Caption := 'Input Search Options';
newForm.Popup := True;
newForm.Border := fbDialog;
newForm.Position := poScreenCenter;
newForm.OrderID := OrderID;
newForm.JobName := wdbtcOrders.Cells[3, row];
if wdbtcOrders.Cells[14, row] <> '' then
......@@ -656,52 +729,52 @@ begin
end);
PageItem.appendChild(PageLink);
PaginationElement.appendChild(PageItem);
end;
procedure TFViewOrders.GetOrders(searchOptions: string);
// retrieves a list of orders that fit a given search criteria
// searchOptions: search info to be sent to the server
var
xdcResponse: TXDataClientResponse;
orderList: TJSObject;
orderListLength: integer;
TotalPages: integer;
orderListLength, TotalPages: Integer;
begin
Utils.ShowSpinner('spinner');
if PageNumber > 0 then
try
try
xdcResponse := await(XDataWebClient1.RawInvokeAsync(
'ILookupService.GetOrders', [searchOptions]));
if Assigned(xdcResponse.Result) then
begin
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GetOrders', [searchOptions]));
orderList := TJSObject(xdcResponse.Result);
// Load data into the dataset
xdwdsOrders.Close;
xdwdsOrders.SetJsonData(orderList['data']);
xdwdsOrders.Open;
orderListLength := integer(orderList['count']);
TotalPages := ( (orderListLength + PageSize - 1) div PageSize);
orderListLength := Integer(orderList['count']);
TotalPages := (orderListLength + PageSize - 1) div PageSize;
GeneratePagination(TotalPages);
// Update label
if orderListLength = 0 then
begin
lblEntries.Caption := 'No entries found';
ShowToast('No entries found', 'danger');
end
else if (PageNumber * PageSize) < orderListLength then
begin
lblEntries.Caption := 'Showing entries ' + IntToStr((PageNumber - 1) * PageSize + 1) +
' - ' + IntToStr(PageNumber * PageSize) +
' of ' + IntToStr(orderListLength);
end
else if (PageNumber * PageSize) >= orderListLength then
begin
lblEntries.Caption := 'Showing entries ' + IntToStr((PageNumber - 1) * PageSize + 1) +
' - ' + IntToStr(orderListLength) +
' of ' + IntToStr(orderListLength);
lblEntries.Caption := Format('Showing entries %d - %d of %d',
[(PageNumber - 1) * PageSize + 1, PageNumber * PageSize, orderListLength])
else
lblEntries.Caption := Format('Showing entries %d - %d of %d',
[(PageNumber - 1) * PageSize + 1, orderListLength, orderListLength]);
end;
// Optional: Continue using pagination if needed
GeneratePagination(TotalPages);
except
on E: EXDataClientRequestException do
Utils.ShowErrorModal('Could not retrieve orders: ' + E.ErrorResult.ErrorMessage);
end;
finally
Utils.HideSpinner('spinner');
end;
end;
......@@ -713,20 +786,18 @@ begin
end;
procedure TFViewOrders.orderEntry(orderInfo, customerInfo, mode, orderType: string);
procedure TFViewOrders.OrderEntry(orderInfo, customerInfo, mode, orderType: string);
begin
if orderType = 'corrugated' then
FViewMain.ViewOrderEntryCorrugated(orderInfo, customerInfo, mode, '')
begin
FViewMain.ViewOrderEntryCorrugated(orderInfo, customerInfo, mode, '');
end
else if orderType = 'web' then
FViewMain.ViewOrderEntryWeb(orderInfo, customerInfo, mode, '')
else
FViewMain.ViewOrderEntryCuttingDie(orderInfo, customerInfo, mode, '');
end;
procedure TFViewOrders.btnCloseNotificationClick(Sender: TObject);
begin
HideNotification();
end;
procedure TFViewOrders.btnSearchClick(Sender: TObject);
var
......@@ -799,39 +870,5 @@ begin
end;
procedure TFViewOrders.HideNotification;
begin
pnlMessage.ElementHandle.hidden := True;
info := '';
end;
procedure TFViewOrders.ShowNotification(Notification: string);
var
splitNotification: TArray<string>;
begin
if Notification <> '' then
begin
splitNotification := Notification.Split([':']);
if(splitNotification[0] = 'Success') then
begin
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-danger');
messageDiv.classList.add('alert-success');
end;
end
else
begin
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-success');
messageDiv.classList.add('alert-danger');
end;
end;
lblMessage.Caption := splitNotification[1];
pnlMessage.ElementHandle.hidden := False;
end;
end;
end.
......@@ -231,6 +231,7 @@ object FSearch: TFSearch
TabStop = False
Text = 'PROOF DONE'
WidthPercent = 100.000000000000000000
OnChange = wcbFilterType1Change
ItemIndex = -1
Items.Strings = (
'NONE'
......@@ -365,6 +366,7 @@ object FSearch: TFSearch
TabStop = False
Text = 'PROOF DONE'
WidthPercent = 100.000000000000000000
OnChange = wcbFilterType2Change
ItemIndex = -1
Items.Strings = (
'NONE'
......
......@@ -64,6 +64,8 @@ type
procedure btnClearClick(Sender: TObject);
procedure cbNull1Click(Sender: TObject);
procedure cbNull2Click(Sender: TObject);
procedure wcbFilterType1Change(Sender: TObject);
procedure wcbFilterType2Change(Sender: TObject);
private
//FJSONProc: TJSONProc;
[async] procedure getCustomers;
......@@ -118,8 +120,8 @@ begin
DateFormatSettings.ShortDateFormat := 'yyyy/mm/dd';
wcbOrderType.Text := UpperCase(Copy(params.Values['orderType'], 1, 1)) + LowerCase(Copy(params.Values['orderType'], 2, MaxInt));
edtOrderID.Text := params.Values['orderID'];
edtCompanyID.Text := params.Values['companyID'];
edtJobName.Text := params.Values['jobName'];
DBID := params.Values['companyID'];
// Status 1
if params.Values['filterType1'] <> '' then
......@@ -175,9 +177,9 @@ begin
end;
end;
getCustomers();
params.Free;
getCustomers();
end;
procedure TFSearch.btnCancelClick(Sender: TObject);
......@@ -257,6 +259,13 @@ begin
// Manually populate the grid
PopulateGridManually;
if DBID <> '' then
begin
xdwdsCustomers.Locate('CUSTOMER_ID', DBID, []);
edtCompanyID.Text := xdwdsCustomers.FieldByName('SHORT_NAME').AsString;
edtCompanyName.Text := xdwdsCustomers.FieldByName('NAME').AsString;
end;
end;
procedure TFSearch.TMSFNCGrid1CellClick(Sender: TObject; ACol, ARow: Integer);
......@@ -267,6 +276,39 @@ begin
end;
procedure TFSearch.wcbFilterType1Change(Sender: TObject);
begin
if wcbFilterType1.Text = 'NONE' then
begin
dtpStartDate1.Visible := false;
dtpEndDate1.Visible := false;
cbNull1.Visible := false;
end
else
begin
dtpStartDate1.Visible := True;
dtpEndDate1.Visible := True;
cbNull1.Visible := True;
end;
end;
procedure TFSearch.wcbFilterType2Change(Sender: TObject);
begin
if wcbFilterType2.Text = 'NONE' then
begin
dtpStartDate2.Visible := false;
dtpEndDate2.Visible := false;
cbNull2.Visible := false;
end
else
begin
dtpStartDate2.Visible := True;
dtpEndDate2.Visible := True;
cbNull2.Visible := True;
end;
end;
procedure TFSearch.PopulateGridManually;
var
RowIndex: Integer;
......
object FSelectCustomer: TFSelectCustomer
Width = 765
Height = 480
Height = 416
OnCreate = WebFormCreate
OnShow = WebFormShow
object WebLabel1: TWebLabel
Left = 8
Top = 81
Top = 27
Width = 95
Height = 15
Caption = 'Search Customers'
......@@ -14,7 +14,7 @@ object FSelectCustomer: TFSelectCustomer
end
object WebLabel2: TWebLabel
Left = 279
Top = 81
Top = 27
Width = 134
Height = 15
Caption = 'Selected Customer Name'
......@@ -23,7 +23,7 @@ object FSelectCustomer: TFSelectCustomer
end
object WebLabel3: TWebLabel
Left = 131
Top = 81
Top = 27
Width = 113
Height = 15
Caption = 'Selected Customer ID'
......@@ -32,16 +32,17 @@ object FSelectCustomer: TFSelectCustomer
end
object edtSearch: TWebEdit
Left = 4
Top = 102
Top = 48
Width = 121
Height = 22
ChildOrder = 2
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnChange = edtSearchChange
end
object edtName: TWebEdit
Left = 279
Top = 102
Top = 48
Width = 142
Height = 22
ChildOrder = 1
......@@ -51,7 +52,7 @@ object FSelectCustomer: TFSelectCustomer
end
object TMSFNCGrid1: TTMSFNCGrid
Left = 0
Top = 163
Top = 99
Width = 765
Height = 317
Align = alBottom
......@@ -205,20 +206,22 @@ object FSelectCustomer: TFSelectCustomer
ScrollMode = scmItemScrolling
DesignTimeSampleData = True
OnCellClick = TMSFNCGrid1CellClick
ExplicitTop = 163
end
object btnCancel: TWebButton
Left = 556
Top = 101
Top = 47
Width = 96
Height = 25
Caption = 'Cancel'
ChildOrder = 5
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnClick = btnCancelClick
end
object btnConfirm: TWebButton
Left = 440
Top = 101
Top = 47
Width = 96
Height = 25
Caption = 'Select'
......@@ -227,30 +230,9 @@ object FSelectCustomer: TFSelectCustomer
WidthPercent = 100.000000000000000000
OnClick = btnConfirmClick
end
object edtNotification: TWebEdit
Left = 4
Top = 16
Width = 510
Height = 22
HelpType = htKeyword
TabStop = False
ChildOrder = 8
ElementFont = efCSS
Enabled = False
Font.Charset = ANSI_CHARSET
Font.Color = clRed
Font.Height = -13
Font.Name = 'Arial'
Font.Style = []
HeightPercent = 100.000000000000000000
HideSelection = False
ParentFont = False
TabOrder = 1
WidthPercent = 100.000000000000000000
end
object edtID: TWebEdit
Left = 131
Top = 102
Top = 48
Width = 142
Height = 22
ChildOrder = 1
......
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<title>TMS Web Project</title>
<style>
</style>
</head>
<body>
</body>
</html>
\ No newline at end of file
<div id="spinner" class="position-absolute top-50 start-50 translate-middle d-none">
<div class="lds-roller">
<div></div><div></div><div></div><div></div>
<div></div><div></div><div></div><div></div>
</div>
</div>
......@@ -21,7 +21,6 @@ type
TMSFNCGrid1: TTMSFNCGrid;
btnCancel: TWebButton;
btnConfirm: TWebButton;
edtNotification: TWebEdit;
XDataWebClient1: TXDataWebClient;
xdwdsCustomers: TXDataWebDataSet;
wdsCustomers: TWebDataSource;
......@@ -46,11 +45,14 @@ type
procedure TMSFNCGrid1CellDblClick(Sender: TObject; ACol, ARow: Integer);
procedure btnConfirmClick(Sender: TObject);
procedure TMSFNCGrid1CellClick(Sender: TObject; ACol, ARow: Integer);
procedure edtSearchChange(Sender: TObject);
procedure btnCancelClick(Sender: TObject);
private
{ Private declarations }
[Async] procedure GetCustomers();
[Async] procedure SendCustomerToServer();
procedure PopulateGridManually();
procedure ApplyFilter();
public
{ Public declarations }
end;
......@@ -75,14 +77,18 @@ end;
procedure TFSelectCustomer.WebFormShow(Sender: TObject);
begin
Utils.ShowSpinner('spinner');
getCustomers();
end;
procedure TFSelectCustomer.btnCancelClick(Sender: TObject);
begin
Close();
end;
procedure TFSelectCustomer.btnConfirmClick(Sender: TObject);
begin
if edtID.Text = '' then
edtNotification.Text := 'Please Select a Customer'
ShowToast('Please Select a Customer', 'danger')
else
begin
xdwdsCustomers.Locate('Id', edtID.Text, []);
......@@ -90,29 +96,38 @@ begin
end;
end;
[async] procedure TFSelectCustomer.getCustomers();
procedure TFSelectCustomer.edtSearchChange(Sender: TObject);
begin
ApplyFilter();
end;
procedure TFSelectCustomer.getCustomers();
// retrieves customer list from server
var
xdcResponse: TXDataClientResponse;
customerList: TJSObject;
i: integer;
begin
try
Utils.ShowSpinner('spinner');
// Fetch data from XData service
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.getQBCustomers', []));
customerList := TJSObject(xdcResponse.Result);
//console.log(customerList);
// Load data into TXDataWebDataset
xdwdsCustomers.Close;
xdwdsCustomers.SetJsonData(customerList);
xdwdsCustomers.Open;
// Manually populate the grid
PopulateGridManually;
Utils.HideSpinner('spinner');
except
on E: EXDataClientRequestException do
Utils.ShowErrorModal('Could not retrieve QuickBooks customers: ' + E.ErrorResult.ErrorMessage);
end;
end;
procedure TFSelectCustomer.PopulateGridManually;
// populates the grid with customers manually.
var
......@@ -148,6 +163,7 @@ begin
finally
TMSFNCGrid1.EndUpdate;
end;
Utils.HideSpinner('spinner');
end;
procedure TFSelectCustomer.TMSFNCGrid1CellClick(Sender: TObject; ACol,
......@@ -202,4 +218,35 @@ begin
end;
procedure TFSelectCustomer.ApplyFilter;
// filters the grid based on search textbox contents.
var
fd: TTMSFNCGridFilterData;
i: Integer;
SearchText: string;
begin
SearchText := Trim(edtSearch.Text);
TMSFNCGrid1.RemoveFilter;
TMSFNCGrid1.Filter.Clear;
// match on first 3 columns
for i := 0 to 2 do
begin
fd := TMSFNCGrid1.Filter.Add;
fd.Column := i;
fd.Condition := '*' + SearchText + '*'; // Match text anywhere in the cell
fd.CaseSensitive := False; // Make the filter case-insensitive
// Use foOR for "match any column" logic
if i > 0 then
fd.Operation := foOR
else
fd.Operation := foNONE; // First filter has no logical operation
end;
// Apply the filters to the grid
TMSFNCGrid1.ApplyFilter;
end;
end.
\ No newline at end of file
object FSetStatus: TFSetStatus
Width = 640
Height = 361
Height = 278
OnShow = WebFormShow
object lblStatus1: TWebLabel
Left = 326
Top = 80
Left = 328
Top = 32
Width = 38
Height = 14
Caption = 'Status:'
......@@ -18,8 +18,8 @@ object FSetStatus: TFSetStatus
WidthPercent = 100.000000000000000000
end
object WebLabel1: TWebLabel
Left = 484
Top = 80
Left = 486
Top = 32
Width = 91
Height = 14
Caption = 'Date Completed:'
......@@ -33,8 +33,8 @@ object FSetStatus: TFSetStatus
WidthPercent = 100.000000000000000000
end
object WebLabel2: TWebLabel
Left = 14
Top = 80
Left = 16
Top = 32
Width = 48
Height = 14
Caption = 'Order ID:'
......@@ -48,8 +48,8 @@ object FSetStatus: TFSetStatus
WidthPercent = 100.000000000000000000
end
object WebLabel3: TWebLabel
Left = 172
Top = 78
Left = 174
Top = 30
Width = 57
Height = 14
Caption = 'Job Name:'
......@@ -63,8 +63,8 @@ object FSetStatus: TFSetStatus
WidthPercent = 100.000000000000000000
end
object WebLabel4: TWebLabel
Left = 11
Top = 142
Left = 13
Top = 94
Width = 51
Height = 14
Caption = 'Ship Due:'
......@@ -78,8 +78,8 @@ object FSetStatus: TFSetStatus
WidthPercent = 100.000000000000000000
end
object WebLabel5: TWebLabel
Left = 169
Top = 142
Left = 171
Top = 94
Width = 78
Height = 14
Caption = 'New Due Date:'
......@@ -93,8 +93,8 @@ object FSetStatus: TFSetStatus
WidthPercent = 100.000000000000000000
end
object lblMount: TWebLabel
Left = 324
Top = 200
Left = 326
Top = 152
Width = 62
Height = 14
Caption = 'Mount Due:'
......@@ -108,8 +108,8 @@ object FSetStatus: TFSetStatus
WidthPercent = 100.000000000000000000
end
object lblMountNew: TWebLabel
Left = 482
Top = 200
Left = 484
Top = 152
Width = 78
Height = 14
Caption = 'New Due Date:'
......@@ -123,8 +123,8 @@ object FSetStatus: TFSetStatus
WidthPercent = 100.000000000000000000
end
object lblPlate: TWebLabel
Left = 11
Top = 200
Left = 13
Top = 152
Width = 54
Height = 14
Caption = 'Plate Due:'
......@@ -138,8 +138,8 @@ object FSetStatus: TFSetStatus
WidthPercent = 100.000000000000000000
end
object lblPlateNew: TWebLabel
Left = 169
Top = 200
Left = 171
Top = 152
Width = 78
Height = 14
Caption = 'New Due Date:'
......@@ -153,8 +153,8 @@ object FSetStatus: TFSetStatus
WidthPercent = 100.000000000000000000
end
object lblArt: TWebLabel
Left = 324
Top = 142
Left = 326
Top = 94
Width = 44
Height = 14
Caption = 'Art Due:'
......@@ -168,8 +168,8 @@ object FSetStatus: TFSetStatus
WidthPercent = 100.000000000000000000
end
object lblArtNew: TWebLabel
Left = 482
Top = 142
Left = 484
Top = 94
Width = 78
Height = 14
Caption = 'New Due Date:'
......@@ -183,8 +183,8 @@ object FSetStatus: TFSetStatus
WidthPercent = 100.000000000000000000
end
object wlcbStatus: TWebLookupComboBox
Left = 326
Top = 100
Left = 328
Top = 52
Width = 145
Height = 22
ElementClassName = 'custom-select'
......@@ -194,8 +194,8 @@ object FSetStatus: TFSetStatus
LookupValues = <>
end
object dtpDate: TWebDateTimePicker
Left = 484
Top = 100
Left = 486
Top = 52
Width = 145
Height = 22
BorderStyle = bsSingle
......@@ -206,8 +206,8 @@ object FSetStatus: TFSetStatus
Text = ''
end
object btnConfirm: TWebButton
Left = 14
Top = 273
Left = 16
Top = 225
Width = 96
Height = 25
Caption = 'Confirm'
......@@ -222,8 +222,8 @@ object FSetStatus: TFSetStatus
OnClick = btnConfirmClick
end
object btnCancel: TWebButton
Left = 125
Top = 273
Left = 127
Top = 225
Width = 96
Height = 25
Caption = 'Cancel'
......@@ -238,8 +238,8 @@ object FSetStatus: TFSetStatus
OnClick = btnCancelClick
end
object edtOrderID: TWebEdit
Left = 14
Top = 100
Left = 16
Top = 52
Width = 145
Height = 22
HelpType = htKeyword
......@@ -259,31 +259,9 @@ object FSetStatus: TFSetStatus
TabOrder = 1
WidthPercent = 100.000000000000000000
end
object edtNotification: TWebEdit
Left = 14
Top = 24
Width = 457
Height = 22
HelpType = htKeyword
TabStop = False
ChildOrder = 8
ElementClassName = 'form-control'
ElementFont = efCSS
Enabled = False
Font.Charset = ANSI_CHARSET
Font.Color = clBlack
Font.Height = -8
Font.Name = 'Arial'
Font.Style = []
HeightPercent = 100.000000000000000000
HideSelection = False
ParentFont = False
TabOrder = 1
WidthPercent = 100.000000000000000000
end
object edtJobName: TWebEdit
Left = 172
Top = 100
Left = 174
Top = 52
Width = 145
Height = 22
HelpType = htKeyword
......@@ -304,8 +282,8 @@ object FSetStatus: TFSetStatus
WidthPercent = 100.000000000000000000
end
object dtpShipDue: TWebDateTimePicker
Left = 11
Top = 162
Left = 13
Top = 114
Width = 145
Height = 22
BorderStyle = bsSingle
......@@ -317,8 +295,8 @@ object FSetStatus: TFSetStatus
Text = ''
end
object dtpNewShipDue: TWebDateTimePicker
Left = 169
Top = 162
Left = 171
Top = 114
Width = 145
Height = 22
BorderStyle = bsSingle
......@@ -329,8 +307,8 @@ object FSetStatus: TFSetStatus
Text = ''
end
object dtpMountDue: TWebDateTimePicker
Left = 324
Top = 220
Left = 326
Top = 172
Width = 145
Height = 22
BorderStyle = bsSingle
......@@ -342,8 +320,8 @@ object FSetStatus: TFSetStatus
Text = ''
end
object dtpNewMountDue: TWebDateTimePicker
Left = 482
Top = 220
Left = 484
Top = 172
Width = 145
Height = 22
BorderStyle = bsSingle
......@@ -354,8 +332,8 @@ object FSetStatus: TFSetStatus
Text = ''
end
object dtpPlateDue: TWebDateTimePicker
Left = 11
Top = 220
Left = 13
Top = 172
Width = 145
Height = 22
BorderStyle = bsSingle
......@@ -367,8 +345,8 @@ object FSetStatus: TFSetStatus
Text = ''
end
object dtpNewPlateDue: TWebDateTimePicker
Left = 169
Top = 220
Left = 171
Top = 172
Width = 145
Height = 22
BorderStyle = bsSingle
......@@ -379,8 +357,8 @@ object FSetStatus: TFSetStatus
Text = ''
end
object dtpArtDue: TWebDateTimePicker
Left = 324
Top = 162
Left = 326
Top = 114
Width = 145
Height = 22
BorderStyle = bsSingle
......@@ -392,8 +370,8 @@ object FSetStatus: TFSetStatus
Text = ''
end
object dtpNewArtDue: TWebDateTimePicker
Left = 482
Top = 162
Left = 484
Top = 114
Width = 145
Height = 22
BorderStyle = bsSingle
......
......@@ -5,7 +5,7 @@ interface
uses
System.SysUtils, System.Classes, JS, Web, WEBLib.Graphics, WEBLib.Controls,
WEBLib.Forms, WEBLib.Dialogs, Vcl.Controls, Vcl.StdCtrls, WEBLib.ExtCtrls,
WEBLib.StdCtrls;
WEBLib.StdCtrls, Utils;
type
TFSetStatus = class(TWebForm)
......@@ -17,7 +17,6 @@ type
btnCancel: TWebButton;
WebLabel2: TWebLabel;
edtOrderID: TWebEdit;
edtNotification: TWebEdit;
edtJobName: TWebEdit;
WebLabel3: TWebLabel;
WebLabel4: TWebLabel;
......@@ -41,8 +40,6 @@ type
procedure btnCancelClick(Sender: TObject);
private
{ Private declarations }
procedure HideNotification;
procedure ShowNotification(Notification: string);
public
{ Public declarations }
confirm: boolean;
......@@ -65,14 +62,15 @@ end;
procedure TFSetStatus.btnConfirmClick(Sender: TObject);
begin
if ( (dtpDate.Date = 0 ) or ( wlcbStatus.value = '' ) ) then
ShowNotification('Failure:Please fill in all information')
ShowToast('Failure: Please fill in all information')
else if ( ( OrderType = 'web plate' ) and ( wlcbStatus.Value = 'MOUNT' ) ) then
ShowNotification('Failure:Web Plate Orders do not have Mount Due/Done dates')
ShowToast('Failure: Web Plate Orders do not have Mount Due/Done dates')
else if ( ( OrderType = 'cutting die' ) and ( wlcbStatus.Value = 'MOUNT' ) or ( wlcbStatus.Value = 'ART' ) or (wlcbStatus.Value = 'PLATE') ) then
ShowNotification('Failure:Cutting Die Orders do not have Art/Plate/Mount Due or Done Dates')
ShowToast('Failure: Cutting Die Orders do not have Art/Plate/Mount Due or Done Dates')
else
begin
confirm := true;
ShowToast('Success: Status updated!');
Close;
end;
end;
......@@ -83,7 +81,6 @@ var
i: integer;
filteredItems: TJSArray;
begin
HideNotification();
edtOrderID.Text := OrderID;
dtpDate.Date := 0;
edtJobName.Text := JobName;
......@@ -137,17 +134,5 @@ begin
end;
end;
procedure TFSetStatus.HideNotification;
begin
//pnlMessage.ElementHandle.hidden := True;
end;
procedure TFSetStatus.ShowNotification(Notification: string);
begin
if Notification <> '' then
begin
edtNotification.Text := Notification;
end;
end;
end.
\ No newline at end of file
object FViewUserProfile: TFViewUserProfile
Color = clWhite
Width = 604
Height = 434
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Size = 8
Font.Style = []
FormStyle = fsNormal
Height = 434
Left = 0
OnShow = WebFormShow
ParentFont = False
TabOrder = 0
Top = 0
Width = 604
OnShow = WebFormShow
object WebLabel1: TWebLabel
Left = 24
Top = 24
Width = 55
Height = 13
Caption = 'User Profile'
ElementID = 'view.userprofile.title'
Font.Charset = ANSI_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Size = 8
Font.Style = []
Height = 16
Left = 24
Top = 24
HeightPercent = 100.000000000000000000
ParentFont = False
Visible = False
Width = 54
WidthPercent = 100.000000000000000000
end
object WebLabel3: TWebLabel
Left = 39
Top = 59
Width = 38
Height = 14
Caption = 'User ID:'
ElementID = 'view.userprofile.form.lblUserID'
ElementPosition = epRelative
......@@ -37,14 +37,16 @@ object FViewUserProfile: TFViewUserProfile
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Size = 8
Font.Style = []
Height = 16
Left = 39
Top = 59
Width = 40
HeightPercent = 100.000000000000000000
ParentFont = False
WidthPercent = 100.000000000000000000
end
object WebLabel2: TWebLabel
Left = 13
Top = 131
Width = 71
Height = 14
Caption = 'Email Address:'
ElementID = 'view.userprofile.form.lblEmail'
ElementPosition = epRelative
......@@ -52,14 +54,16 @@ object FViewUserProfile: TFViewUserProfile
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Size = 8
Font.Style = []
Height = 16
Left = 13
Top = 157
Width = 70
HeightPercent = 100.000000000000000000
ParentFont = False
WidthPercent = 100.000000000000000000
end
object WebLabel4: TWebLabel
Left = 29
Top = 83
Width = 52
Height = 14
Caption = 'Username:'
ElementID = 'view.userprofile.form.lblUserName'
ElementPosition = epRelative
......@@ -67,60 +71,49 @@ object FViewUserProfile: TFViewUserProfile
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Size = 8
Font.Style = []
Height = 16
Left = 29
Top = 83
Width = 51
HeightPercent = 100.000000000000000000
ParentFont = False
WidthPercent = 100.000000000000000000
end
object WebLabel5: TWebLabel
Caption = 'Full Name:'
ElementID = 'view.userprofile.form.lblFullName'
ElementPosition = epRelative
Font.Charset = ANSI_CHARSET
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Size = 8
Font.Style = []
Height = 16
Left = 29
Top = 107
Width = 51
end
object WebLabel6: TWebLabel
Caption = 'Phone Number:'
ElementID = 'view.userprofile.form.lblPhone'
Width = 49
Height = 14
Caption = 'Full Name:'
ElementID = 'view.userprofile.form.lblFullName'
ElementPosition = epRelative
Font.Charset = ANSI_CHARSET
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Size = 8
Font.Style = []
Height = 16
Left = 5
Top = 133
Width = 74
HeightPercent = 100.000000000000000000
ParentFont = False
WidthPercent = 100.000000000000000000
end
object lblResult: TWebLabel
Left = 85
Top = 246
Width = 3
Height = 14
ElementID = 'view.userprofile.form.lblresult'
ElementPosition = epRelative
Font.Charset = ANSI_CHARSET
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Size = 8
Font.Style = []
Height = 13
Left = 85
Top = 246
Width = 3
HeightPercent = 100.000000000000000000
ParentFont = False
WidthPercent = 100.000000000000000000
end
object edtUsername: TWebEdit
Alignment = taLeftJustify
Color = clWindow
Left = 85
Top = 80
Width = 121
Height = 21
ElementID = 'view.userprofile.form.edtUsername'
ElementPosition = epRelative
Enabled = False
......@@ -128,20 +121,18 @@ object FViewUserProfile: TFViewUserProfile
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Size = 8
Font.Style = []
Height = 21
HeightPercent = 100.000000000000000000
HideSelection = False
Left = 85
ParentFont = False
ReadOnly = True
ShowFocus = True
TabOrder = 0
Top = 80
Width = 121
WidthPercent = 100.000000000000000000
end
object edtUserId: TWebEdit
Alignment = taLeftJustify
Color = clWindow
Left = 85
Top = 56
Width = 121
Height = 21
ElementID = 'view.userprofile.form.edtUserID'
ElementPosition = epRelative
Enabled = False
......@@ -149,58 +140,37 @@ object FViewUserProfile: TFViewUserProfile
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Size = 8
Font.Style = []
Height = 21
HeightPercent = 100.000000000000000000
HideSelection = False
Left = 85
ParentFont = False
ReadOnly = True
ShowFocus = True
TabOrder = 1
Top = 56
Width = 121
WidthPercent = 100.000000000000000000
end
object edtFullName: TWebEdit
Alignment = taLeftJustify
ChildOrder = 5
Color = clWindow
ElementID = 'view.userprofile.form.edtFullName'
ElementPosition = epRelative
Font.Charset = ANSI_CHARSET
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Size = 8
Font.Style = []
Height = 21
HideSelection = False
Left = 85
ShowFocus = True
TabOrder = 0
Top = 104
Width = 121
end
object edtPhone: TWebEdit
Alignment = taLeftJustify
ChildOrder = 7
Color = clWindow
ElementID = 'view.userprofile.form.edtPhone'
Height = 21
ChildOrder = 5
ElementID = 'view.userprofile.form.edtFullName'
ElementPosition = epRelative
Font.Charset = ANSI_CHARSET
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Size = 8
Font.Style = []
Height = 21
HeightPercent = 100.000000000000000000
HideSelection = False
Left = 85
ShowFocus = True
TabOrder = 0
Top = 128
Width = 121
ParentFont = False
WidthPercent = 100.000000000000000000
end
object chkAdminUser: TWebCheckBox
Left = 85
Top = 179
Width = 113
Height = 22
Caption = 'chkAdminUser'
ChildOrder = 9
ElementID = 'view.userprofile.form.chkAdminUser'
......@@ -210,128 +180,72 @@ object FViewUserProfile: TFViewUserProfile
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Size = 8
Font.Style = []
Height = 22
Left = 85
HeightPercent = 100.000000000000000000
ParentFont = False
Role = 'null'
ShowFocus = True
TabOrder = 0
Top = 179
Width = 113
WidthPercent = 100.000000000000000000
end
object edtEmail: TWebEdit
Alignment = taLeftJustify
Left = 85
Top = 126
Width = 121
Height = 21
ChildOrder = 7
Color = clWindow
ElementID = 'view.userprofile.form.edtEmail'
ElementPosition = epRelative
Font.Charset = ANSI_CHARSET
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Size = 8
Font.Style = []
Height = 21
HeightPercent = 100.000000000000000000
HideSelection = False
Left = 85
ShowFocus = True
TabOrder = 0
Top = 152
Width = 121
ParentFont = False
WidthPercent = 100.000000000000000000
end
object btnConfirm: TWebButton
Left = 85
Top = 210
Width = 96
Height = 25
Caption = 'Confirm Changes'
ChildOrder = 12
Color = clNone
ElementID = 'view.userprofile.form.btnconfirm'
ElementPosition = epRelative
Font.Charset = ANSI_CHARSET
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Size = 8
Font.Style = []
Height = 25
Left = 85
OnClick = btnConfirmClick
HeightPercent = 100.000000000000000000
ParentFont = False
Role = 'button'
TabOrder = 0
WidthPercent = 100.000000000000000000
OnClick = btnConfirmClick
end
object btnCancel: TWebButton
Left = 208
Top = 210
Width = 96
end
object WebButton1: TWebButton
Height = 25
Caption = 'Cancel Changes'
ChildOrder = 14
Color = clNone
ElementID = 'view.userprofile.form.btncancel'
ElementPosition = epRelative
Font.Charset = ANSI_CHARSET
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Size = 8
Font.Style = []
Height = 25
Left = 208
OnClick = WebButton1Click
Role = 'button'
TabOrder = 0
Top = 210
Width = 96
end
object pnlMessage: TWebPanel
ChildOrder = 17
Color = clBtnFace
ElementID = 'view.login.message'
ElementPosition = epRelative
Font.Charset = ANSI_CHARSET
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Size = 8
Font.Style = []
Height = 33
Left = 236
Role = 'null'
TabOrder = 8
TabStop = False
Top = 4
Width = 121
object lblMessage: TWebLabel
Caption = 'Message'
ElementID = 'view.login.message.label'
Font.Charset = ANSI_CHARSET
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Size = 8
Font.Style = []
Height = 16
Left = 16
Top = 11
Width = 43
end
object btnCloseNotification: TWebButton
ChildOrder = 1
Color = clNone
ElementID = 'view.login.message.button'
Font.Charset = ANSI_CHARSET
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Size = 8
Font.Style = []
Height = 25
Left = 96
OnClick = btnCloseNotificationClick
HeightPercent = 100.000000000000000000
ParentFont = False
Role = 'button'
TabOrder = 0
Top = 3
Width = 22
end
WidthPercent = 100.000000000000000000
OnClick = btnCancelClick
end
object XDataWebClient1: TXDataWebClient
Connection = DMConnection.ApiConnection
Left = 359
Top = 52
end
......
<div class="row">
<div class="col-lg-12">
<div class="container">
<!-- Profile form -->
<div class="row">
<div class=col-sm>
<div id="view.login.message" class="alert alert-danger">
<button id="view.login.message.button" type="button" class="btn-close" aria-label="Close"></button>
<span id="view.login.message.label"></span>
</div>
</div>
<div role="form">
<div class="form-group">
<label id="view.userprofile.form.lblUserID">User ID:</label>
<input id="view.userprofile.form.edtUserID" class="form-control">
</div>
<div class="form-group">
<label id="view.userprofile.form.lblUserName">Username:</label>
<input id="view.userprofile.form.edtUsername" class="form-control">
</div>
<div class="form-group">
<label id="view.userprofile.form.lblFullName">Full Name:</label>
<input id="view.userprofile.form.edtFullName" class="form-control">
</div>
<div class="form-group">
<label id="view.userprofile.form.lblPhone">Phone Number:</label>
<input id="view.userprofile.form.edtPhone" class="form-control">
<div class="col-lg-8 col-xl-6 mx-auto">
<form id="userprofileform" class="needs-validation" role="form" autocomplete="off" novalidate>
<div class="mb-3">
<label id="view.userprofile.form.lblUserID"
for="view.userprofile.form.edtUserID"
class="form-label">User&nbsp;ID</label>
<input id="view.userprofile.form.edtUserID"
class="form-control"
readonly>
</div>
<div class="form-group">
<label id="view.userprofile.form.lblEmail">Email Address:</label>
<input id="view.userprofile.form.edtEmail" class="form-control">
<div class="mb-3">
<label id="view.userprofile.form.lblUserName"
for="view.userprofile.form.edtUsername"
class="form-label">Username</label>
<input id="view.userprofile.form.edtUsername"
class="form-control"
required>
<div class="invalid-feedback">Username is required.</div>
</div>
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="view.userprofile.form.chkAdminUser">
<label class="custom-control-label" for="view.userprofile.form.chkAdminUser">Admin User</label>
<div class="mb-3">
<label id="view.userprofile.form.lblFullName"
for="view.userprofile.form.edtFullName"
class="form-label">Full&nbsp;Name</label>
<input id="view.userprofile.form.edtFullName"
class="form-control"
required>
<div class="invalid-feedback">Full Name is required.</div>
</div>
<div class="form-group">
<button class="btn btn-primary" id="view.userprofile.form.btnconfirm">Confirm Changes</button>
<button class="btn btn-primary" id="view.userprofile.form.btncancel">Xancel Changes</button>
<div class="mb-3">
<label id="view.userprofile.form.lblEmail"
for="view.userprofile.form.edtEmail"
class="form-label">Email&nbsp;Address</label>
<input id="view.userprofile.form.edtEmail"
type="email"
class="form-control"
required>
<div class="invalid-feedback">Valid email is required.</div>
</div>
<div class="form-group">
<label id="view.userprofile.form.lblresult"></label>
<div class="form-check mb-4">
<input type="checkbox"
id="view.userprofile.form.chkAdminUser"
class="form-check-input">
<label for="view.userprofile.form.chkAdminUser"
class="form-check-label">
Admin&nbsp;User
</label>
</div>
<div class="d-flex gap-2 mb-4">
<button id="view.userprofile.form.btnconfirm"
class="btn btn-primary flex-grow-1"
type="button">
Confirm&nbsp;Changes
</button>
<button id="view.userprofile.form.btncancel"
class="btn btn-outline-secondary flex-grow-1"
type="button">
Cancel&nbsp;Changes
</button>
</div>
<label id="view.userprofile.form.lblresult" class="form-text"></label>
</form>
</div>
</div>
</div>
......@@ -6,7 +6,8 @@ uses
System.SysUtils, System.Classes, JS, Web, WEBLib.Graphics, WEBLib.Controls,
WEBLib.Forms, WEBLib.Dialogs, Vcl.Controls, Vcl.StdCtrls, WEBLib.StdCtrls,
XData.Web.Client, WEBLib.ExtCtrls, DB, XData.Web.JsonDataset,
XData.Web.Dataset, XData.Web.Connection, Vcl.Forms, ConnectionModule;
XData.Web.Dataset, XData.Web.Connection, Vcl.Forms, ConnectionModule,
WEBLib.Toast;
type
TFViewUserProfile = class(TWebForm)
......@@ -17,27 +18,18 @@ type
edtUserId: TWebEdit;
edtFullName: TWebEdit;
WebLabel4: TWebLabel;
edtPhone: TWebEdit;
WebLabel5: TWebLabel;
chkAdminUser: TWebCheckBox;
edtEmail: TWebEdit;
WebLabel6: TWebLabel;
btnConfirm: TWebButton;
lblResult: TWebLabel;
XDataWebClient1: TXDataWebClient;
WebButton1: TWebButton;
pnlMessage: TWebPanel;
lblMessage: TWebLabel;
btnCloseNotification: TWebButton;
btnCancel: TWebButton;
procedure WebFormShow(Sender: TObject);
procedure btnConfirmClick(Sender: TObject);
[async] procedure EditUser();
[async] procedure GetUser();
procedure WebButton1Click(Sender: TObject);
procedure HideNotification();
procedure ShowNotification(Notification: string);
procedure btnCloseNotificationClick(Sender: TObject);
function CheckInputs(): boolean;
procedure btnCancelClick(Sender: TObject);
end;
var
......@@ -47,81 +39,92 @@ implementation
uses
Auth.Service,
XData.Model.Classes;
XData.Model.Classes,
Utils,
View.Main;
{$R *.dfm}
procedure TFViewUserProfile.btnCloseNotificationClick(Sender: TObject);
begin
HideNotification;
end;
procedure TFViewUserProfile.btnConfirmClick(Sender: TObject);
var
resultString: string;
FormEl: TJSHTMLFormElement;
begin
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-success');
messageDiv.classList.add('alert-danger');
FormEl := TJSHTMLFormElement(document.querySelector('form'));
if not FormEl.checkValidity then
begin
FormEl.classList.add('was-validated');
Exit;
end;
if CheckInputs() then
ShowConfirmationModal(
'Are you sure you want to save changes to your profile?',
'Save',
'Cancel',
procedure(confirmed: Boolean)
begin
EditUser();
if confirmed then
EditUser;
end
);
end;
procedure TFViewUserProfile.EditUser();
[async] procedure TFViewUserProfile.EditUser;
var
xdcResponse: TXDataClientResponse;
responseString: TJSObject;
editOptions: string;
editOptions, resultMsg: string;
begin
if(checkInputs()) then
begin
console.log(edtFullName.Text);
try
editOptions := '&username=' + edtUsername.Text +
'&fullname=' + edtFullName.Text +
'&phonenumber=' + edtPhone.Text +
'&email=' + edtEmail.Text;
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.EditUser',
[editOptions]));
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.EditUser', [editOptions]));
responseString := TJSObject(xdcResponse.Result);
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-danger');
messageDiv.classList.add('alert-success');
end;
ShowNotification(string(responseString['value']));
resultMsg := string(responseString['value']);
Utils.ShowToast(resultMsg);
if resultMsg.ToLower.StartsWith('success:') then
FViewMain.ViewOrders('');
except
on E: EXDataClientRequestException do
Utils.ShowErrorModal('Error editing user: ' + E.ErrorResult.ErrorMessage);
on E: Exception do
Utils.ShowErrorModal('Unexpected error: ' + E.Message);
end;
end;
procedure TFViewUserProfile.WebButton1Click(Sender: TObject);
var
xdcResponse: TXDataClientResponse;
userList: TJSObject;
data: TJSArray;
user: TJSObject;
procedure TFViewUserProfile.btnCancelClick(Sender: TObject);
begin
ShowConfirmationModal(
'Are you sure you want to cancel all your changes?',
'Yes',
'No',
procedure(confirmed: Boolean)
begin
if confirmed then
begin
GetUser();
showNotification('Failure:Changes discarded');
ShowToast('Changes discarded', 'danger');
end;
end
);
end;
procedure TFViewUserProfile.WebFormShow(Sender: TObject);
var
xdcResponse: TXDataClientResponse;
userList: TJSObject;
data: TJSArray;
user: TJSObject;
begin
HideNotification;
GetUser();
//edtJwt.Text := TJSJSON.stringify(AuthService.TokenPayload);
chkAdminUser.Checked := JS.toBoolean(AuthService.TokenPayload.Properties['user_admin']);
// View.UserProfile.WebFormShow
chkAdminUser.Checked := SameText(string(AuthService.TokenPayload.Properties['user_admin']), 'true');
end;
procedure TFViewUserProfile.GetUser;
var
xdcResponse: TXDataClientResponse;
......@@ -129,6 +132,7 @@ var
data: TJSArray;
user: TJSObject;
begin
try
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GetUsers',
[JS.toString(AuthService.TokenPayload.Properties['user_name'])]));
userList := TJSObject(xdcResponse.Result);
......@@ -136,132 +140,14 @@ begin
user := TJSObject(data[0]);
edtUsername.Text := string(user['username']);
edtFullName.Text := string(user['full_name']);
edtPhone.Text := string(user['phone_number']);
edtEmail.Text := string(user['email_address']);
edtUserId.Text := string(user['userID']);
chkAdminUser.Checked := boolean(user['admin']);
end;
procedure TFViewUserProfile.HideNotification;
begin
pnlMessage.ElementHandle.hidden := True;
end;
procedure TFViewUserProfile.ShowNotification(Notification: string);
var
splitNotification: TArray<string>;
begin
if Notification <> '' then
begin
splitNotification := Notification.Split([':']);
if(splitNotification[0] = 'Success') then
begin
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-danger');
messageDiv.classList.add('alert-success');
end;
end
else
begin
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-success');
messageDiv.classList.add('alert-danger');
end;
end;
lblMessage.Caption := splitNotification[1];
pnlMessage.ElementHandle.hidden := False;
except
on E: EXDataClientRequestException do
Utils.ShowErrorModal('Could not retrieve users: ' + E.ErrorResult.ErrorMessage);
end;
end;
function TFViewUserProfile.CheckInputs(): boolean;
var
checkString: string;
charIndex: integer;
phoneNum: string;
begin
Result := false;
checkString := edtFullName.Text + edtUsername.Text + edtPhone.Text + edtEmail.Text;
if string(edtFullName.Text).IsEmpty then
begin
ShowNotification('Failure:Full Name field is blank!');
exit;
end;
if string(edtUsername.Text).IsEmpty then
begin
ShowNotification('Failure:Username field is blank!');
exit;
end;
if string(edtPhone.Text).IsEmpty then
begin
ShowNotification('Failure:Phone Number field is blank!');
exit;
end;
if string(edtEmail.Text).IsEmpty then
begin
ShowNotification('Failure:Email field is blank!');
exit;
end;
if checkString.Contains('&') then
begin
ShowNotification('Failure:No fields may contain "&&"!');
exit;
end;
if string(edtEmail.Text).Contains('@') = false then
begin
ShowNotification('Failure:Please enter a valid email address');
exit;
end;
if (length(string(edtEmail.Text).Split(['@'])) <> 2) or (string(edtEmail.text).CountChar('@') > 1) then
begin
ShowNotification('Failure:Please enter a valid email address');
exit;
end;
phoneNum := edtPhone.Text;
if (not phoneNum.Contains('(')) or (not phoneNum.Contains(')')) or (not phoneNum.Contains('-')) then
begin
ShowNotification('Failure:Please enter a valid phone number');
exit;
end;
if (phoneNum.CountChar('(') <> 1) or (phoneNum.CountChar(')') <> 1) or (phoneNum.CountChar('-') <> 1) or (phoneNum.CountChar(' ') > 1) then
begin
ShowNotification('Failure:Please enter a valid phone number');
exit;
end;
phoneNum := phoneNum.Replace('(', '');
phoneNum := phoneNum.Replace(')', '');
phoneNum := phoneNum.Replace('-', '');
phoneNum := phoneNum.Replace(' ', '');
console.log(phoneNum);
console.log(length(phoneNum));
if(length(phoneNum) <> 10) then
begin
ShowNotification('Failure:Please enter a valid phone number');
exit;
end;
for CharIndex := 1 to Length(phoneNum) do
begin
if not (phoneNum[CharIndex] in ['0' .. '9']) then
begin
console.log('here');
ShowNotification('Failure:Please enter a valid phone number');
exit;
end;
end;
result := true;
end;
end.
......@@ -45,36 +45,6 @@ object FViewUsers: TFViewUsers
WidthPercent = 100.000000000000000000
OnClick = btnConfirmDeleteClick
end
object pnlMessage: TWebPanel
Left = 12
Top = 16
Width = 121
Height = 33
ElementID = 'view.login.message'
ChildOrder = 17
TabOrder = 2
object lblMessage: TWebLabel
Left = 16
Top = 11
Width = 46
Height = 15
Caption = 'Message'
ElementID = 'view.login.message.label'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object btnCloseNotification: TWebButton
Left = 96
Top = 3
Width = 22
Height = 25
ChildOrder = 1
ElementID = 'view.login.message.button'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnClick = btnCloseNotificationClick
end
end
object XDataWebClient1: TXDataWebClient
Connection = DMConnection.ApiConnection
Left = 462
......
......@@ -5,10 +5,6 @@
<div class="col-12 col-md-8">
<div class="row">
<div class=col-sm>
<div id="view.login.message" class="alert alert-danger">
<button id="view.login.message.button" type="button" class="btn-close" aria-label="Close"></button>
<span id="view.login.message.label"></span>
</div>
</div>
</div>
</div>
......@@ -47,22 +43,5 @@
</div>
</div>
</div>
<!--</div> -->
<!--</div> -->
<div class="modal fade" id="confirmation_modal" tabindex="-1" aria-labelledby="confirmation_modal_label" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="confirmation_modal_label">Confirm</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
Are you sure you want to make these changes?
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" data-bs-dismiss="modal" id="btn_confirm_delete" >Confirm</button>
</div>
</div>
</div>
</div>
......@@ -6,7 +6,7 @@ uses
System.SysUtils, System.Classes, Web, WEBLib.Graphics, WEBLib.Forms, WEBLib.Dialogs,
Vcl.Controls, Vcl.StdCtrls, WEBLib.StdCtrls, WEBLib.Controls, WEBLib.Grids, WebLib.Lists,
XData.Web.Client, WEBLib.ExtCtrls, DB, XData.Web.JsonDataset,
XData.Web.Dataset, XData.Web.Connection, Vcl.Forms, WEBLib.DBCtrls, JS;
XData.Web.Dataset, XData.Web.Connection, Vcl.Forms, WEBLib.DBCtrls, JS, Utils;
type
TFViewUsers = class(TWebForm)
......@@ -16,9 +16,6 @@ type
btnAddUser: TWebButton;
WebDataSource1: TWebDataSource;
btnConfirmDelete: TWebButton;
pnlMessage: TWebPanel;
lblMessage: TWebLabel;
btnCloseNotification: TWebButton;
XDataWebDataSet1userID: TStringField;
XDataWebDataSet1username: TStringField;
XDataWebDataSet1full_name: TStringField;
......@@ -34,7 +31,6 @@ type
//AField: TField; AValue: string; AElement: TJSHTMLElementRecord);
procedure btnConfirmDeleteClick(Sender: TObject);
procedure btnAddUserClick(Sender: TObject);
procedure btnCloseNotificationClick(Sender: TObject);
//procedure btnApplyClick(Sender: TObject);
//procedure btnSearchClick(Sender: TObject);
private
......@@ -46,8 +42,6 @@ type
[async] procedure DelUser(username: string);
[async] procedure EditUser(row: TJSHTMLElement);
[async] procedure GetUsers(searchOptions: string);
procedure HideNotification;
procedure ShowNotification(Notification: string);
procedure AddRowToTable(UserID, Username, Password, Full_Name, Status,
Email, AType, PID, QBID: string; Rights: integer);
//[async] procedure addUser();
......@@ -98,10 +92,7 @@ begin
PageSize := 10;
GetUsers('');
if Info <> '' then
ShowNotification(Info)
else
HideNotification();
ShowToast(Info)
end;
procedure TFViewUsers.DelUser(username: string);
......@@ -112,7 +103,7 @@ begin
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.DelUser',
[username]));
responseString := TJSObject(xdcResponse.Result);
ShowNotification(string(responseString['value']));
ShowToast(string(responseString['value']));
getUsers('');
end;
......@@ -330,10 +321,11 @@ var
data: TJSArray;
user: TJSObject;
userListLength: integer;
begin
if PageNumber > 0 then
begin
Utils.ShowSpinner('spinner');
try
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GetUsers',
[searchOptions]));
......@@ -368,6 +360,11 @@ begin
' of ' + IntToStr(userListLength);
end;
GeneratePagination(TotalPages);
except
on E: EXDataClientRequestException do
Utils.ShowErrorModal('Could not retrieve users: ' + E.ErrorResult.ErrorMessage);
end;
Utils.HideSpinner('spinner');
end;
end;
......@@ -443,7 +440,7 @@ begin
Cell := TJSHTMLElement(document.createElement('td'));
Cell.setAttribute('data-label', 'Edit');
Button := TJSHTMLElement(document.createElement('a'));
Button.className := 'btn btn-primary';
Button.className := 'btn btn-sm btn-primary';
Button.innerHTML := '<i class="far fa-edit fa-fw"></i><span>Edit</span>';
Button.addEventListener('click', procedure(Event: TJSMouseEvent)
begin
......@@ -462,43 +459,6 @@ begin
FViewMain.EditUser('Add', '', '', '', '', '', '', '', '', '');
end;
procedure TFViewUsers.btnCloseNotificationClick(Sender: TObject);
begin
HideNotification;
end;
procedure TFViewUsers.HideNotification;
begin
pnlMessage.ElementHandle.hidden := True;
end;
procedure TFViewUsers.ShowNotification(Notification: string);
var
splitNotification: TArray<string>;
begin
if Notification <> '' then
begin
splitNotification := Notification.Split([':']);
if(splitNotification[0] = 'Success') then
begin
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-danger');
messageDiv.classList.add('alert-success');
end;
end
else
begin
asm
var messageDiv = document.getElementById('view.login.message');
messageDiv.classList.remove('alert-success');
messageDiv.classList.add('alert-danger');
end;
end;
lblMessage.Caption := splitNotification[1];
pnlMessage.ElementHandle.hidden := False;
end;
end;
procedure TFViewUsers.btnConfirmDeleteClick(Sender: TObject);
begin
......
......@@ -367,6 +367,30 @@ is-invalid .form-check-input {
}
@keyframes slideInLeft {
from {
transform: translateX(-120%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
.toast.slide-in {
animation: slideInLeft 0.4s ease-out forwards;
}
#spinner {
position: fixed !important;
z-index: 9999 !important;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
......
<html><head>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta content="width=device-width, initial-scale=1" name="viewport"/>
<noscript>Your browser does not support JavaScript!</noscript>
<link href="data:;base64,=" rel="icon"/>
<title>Web KG Orders</title>
<title>EM Systems webKGOrders App</title>
<link href="https://cdnjs.cloudflare.com/ajax/libs/flag-icon-css/2.3.1/css/flag-icon.min.css" rel="stylesheet"/>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.0/css/all.min.css" rel="stylesheet"/>
<link crossorigin="anonymous" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/js/bootstrap.bundle.min.js" type="text/javascript"></script>
<script crossorigin="anonymous" integrity="sha256-eKhayi8LEQwp4NKxN+CfCh+3qOVUtJn3QNZ0TciWLP4=" src="https://code.jquery.com/jquery-3.7.1.js"></script>
<script src="$(ProjectName).js" type="text/javascript"></script>
<title>EM Systems webKGOrders App</title>
<link href="css/app.css" rel="stylesheet" type="text/css"/>
<link href="css/spinner.css" rel="stylesheet" type="text/css">
<link href="css/spinner.css" rel="stylesheet" type="text/css"/>
<script crossorigin="anonymous" integrity="sha256-eKhayi8LEQwp4NKxN+CfCh+3qOVUtJn3QNZ0TciWLP4=" src="https://code.jquery.com/jquery-3.7.1.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/js/bootstrap.bundle.min.js" type="text/javascript"></script>
<link crossorigin="anonymous" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css" rel="stylesheet"/>
<script src="$(ProjectName).js" type="text/javascript"></script>
</head>
<body>
</body>
<script type="text/javascript">rtl.run();</script>
</html>
program webKGOrders;
uses
......@@ -29,7 +28,8 @@ uses
AddCustomer in 'AddCustomer.pas' {FViewAddCustomer: TWebForm} {*.html},
View.AddAddress in 'View.AddAddress.pas' {FViewAddAddress: TWebForm} {*.html},
View.SelectCustomer in 'View.SelectCustomer.pas' {FSelectCustomer: TWebForm} {*.html},
Utils in 'Utils.pas';
Utils in 'Utils.pas',
View.AddItem in 'View.AddItem.pas' {fViewAddItem: TWebForm} {*.html};
{$R *.res}
......
......@@ -69,9 +69,13 @@
<DCC_Namespace>Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)</DCC_Namespace>
<BT_BuildType>Debug</BT_BuildType>
<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
<VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>
<VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=0.9.5.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=0.9.5.0;Comments=</VerInfo_Keys>
<VerInfo_Locale>1033</VerInfo_Locale>
<Manifest_File>$(BDS)\bin\default_app.manifest</Manifest_File>
<VerInfo_MajorVer>0</VerInfo_MajorVer>
<VerInfo_MinorVer>9</VerInfo_MinorVer>
<VerInfo_Release>5</VerInfo_Release>
<AppDPIAwarenessMode>none</AppDPIAwarenessMode>
</PropertyGroup>
<PropertyGroup Condition="'$(Base_Win64)'!=''">
<DCC_UsePackage>DBXSqliteDriver;DataSnapServerMidas;DBXDb2Driver;DBXInterBaseDriver;vclactnband;vclFireDAC;tethering;FireDACADSDriver;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;Intraweb;DBXOracleDriver;inetdb;FmxTeeUI;emsedge;fmx;fmxdae;vclib;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;DataSnapCommon;DataSnapConnectors;VCLRESTComponents;vclie;bindengine;DBXMySQLDriver;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonODBC;DataSnapClient;bindcompdbx;IndyIPCommon;vcl;DBXSybaseASEDriver;IndyIPServer;IndySystem;FireDACDb2Driver;dsnapcon;FireDACMSAccDriver;fmxFireDAC;FireDACInfxDriver;vclimg;TeeDB;emshosting;FireDACPgDriver;ibmonitor;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;FMXTee;DbxCommonDriver;ibxpress;Tee;DataSnapServer;xmlrtl;DataSnapNativeClient;fmxobj;vclwinx;ibxbindings;rtl;FireDACDSDriver;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;vcldsnap;bindcomp;appanalytics;DBXInformixDriver;IndyIPClient;bindcompvcl;TeeUI;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;dsnapxml;DataSnapProviderClient;dbrtl;inetdbxpress;FireDACMongoDBDriver;IndyProtocols;fmxase;$(DCC_UsePackage)</DCC_UsePackage>
......@@ -90,13 +94,14 @@
<DCC_RemoteDebug>false</DCC_RemoteDebug>
<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
<VerInfo_Locale>1033</VerInfo_Locale>
<VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=0.9.2.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=0.9.2.0;Comments=;LastCompiledTime=2018/08/27 15:18:29</VerInfo_Keys>
<VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=0.9.5.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=0.9.5.0;Comments=;LastCompiledTime=2018/08/27 15:18:29</VerInfo_Keys>
<AppDPIAwarenessMode>PerMonitor</AppDPIAwarenessMode>
<VerInfo_MajorVer>0</VerInfo_MajorVer>
<VerInfo_MinorVer>9</VerInfo_MinorVer>
<TMSWebSingleInstance>1</TMSWebSingleInstance>
<TMSUseJSDebugger>2</TMSUseJSDebugger>
<VerInfo_Release>2</VerInfo_Release>
<VerInfo_Release>5</VerInfo_Release>
<TMSWebBrowser>3</TMSWebBrowser>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_2)'!=''">
<DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>
......@@ -107,11 +112,13 @@
<TMSWebDefines>RELEASE</TMSWebDefines>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_2_Win32)'!=''">
<VerInfo_Build>8</VerInfo_Build>
<VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.8;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;LastCompiledTime=2018/08/22 16:25:56</VerInfo_Keys>
<VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=0.9.6.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=0.9.6.0;Comments=;LastCompiledTime=2018/08/22 16:25:56</VerInfo_Keys>
<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
<VerInfo_Locale>1033</VerInfo_Locale>
<AppDPIAwarenessMode>PerMonitor</AppDPIAwarenessMode>
<VerInfo_MajorVer>0</VerInfo_MajorVer>
<VerInfo_MinorVer>9</VerInfo_MinorVer>
<VerInfo_Release>6</VerInfo_Release>
</PropertyGroup>
<ItemGroup>
<DelphiCompile Include="$(MainSource)">
......@@ -206,6 +213,10 @@
<DesignClass>TWebForm</DesignClass>
</DCCReference>
<DCCReference Include="Utils.pas"/>
<DCCReference Include="View.AddItem.pas">
<Form>fViewAddItem</Form>
<DesignClass>TWebForm</DesignClass>
</DCCReference>
<None Include="index.html"/>
<None Include="css\app.css"/>
<None Include="config\config.json"/>
......
......@@ -132,6 +132,7 @@ begin
JWT.Claims.SetClaimOfType<string>('user_email', userEmail);
JWT.Claims.SetClaimOfType<string>('user_qb_id', userQBID);
JWT.Claims.SetClaimOfType<string>('user_access_type', userAccessType);
JWT.Claims.SetClaimOfType<string>('user_admin', LowerCase(BoolToStr(SameText(userAccessType, 'ALL'), True)));
Result := TJOSE.SHA256CompactToken(serverConfig.jwtTokenSecret, JWT);
finally
......
......@@ -376,6 +376,100 @@ type
general_special_instructions: string;
end;
// These objects are only used for quickbooks estimates.
TRef = record
value: string;
name: string; // optional
end;
TCustomerMemo = record
value: string;
end;
TAddress = record
Line1: string;
Line2: string; // optional
Line3: string; // optional
Line4: string; //optional
Line5: string; //optional
City: string;
CountrySubDivisionCode: string;
PostalCode: string;
Country: string; // optional
end;
TTaxCodeRef = record
value: string;
end;
TClassRef = record
value: string;
end;
TSalesItemLineDetail = record
ItemRef: TRef;
Qty: Double;
UnitPrice: Double;
TaxCodeRef: TTaxCodeRef; // optional
ClassRef: TClassRef; // optional
ServiceDate: string; // optional
end;
TLine = record
Id: string; // optional (auto-generated if omitted)
LineNum: Integer; // optional
Description: string; // optional
Amount: Double;
DetailType: string;
SalesItemLineDetail: TSalesItemLineDetail;
end;
TCustomField = record
DefinitionId: string;
Name: string;
Type_: string;
StringValue: string;
end;
TTxnTaxCodeRef = record
value: string;
end;
TTxnTaxDetail = record
TxnTaxCodeRef: TTxnTaxCodeRef;
TotalTax: Double;
end;
TEmail = record
Address: string;
end;
TEstimate = record
DocNumber: string; // optional
TxnDate: string;
PrivateNote: string; // optional
CustomerRef: TRef;
CustomerMemo: TCustomerMemo; // optional
BillAddr: TAddress; // optional
ShipAddr: TAddress; // optional
ShipMethodRef: TRef; // optional
SalesTermRef: TRef; // optional
DueDate: string; // optional
ClassRef: TRef; // optional
DepartmentRef: TRef; // optional
CurrencyRef: TRef; // optional
ExchangeRate: Double; // optional
EmailStatus: string; // optional
BillEmail: TEmail; // optional
ShipDate: string; // optional
TrackingNum: string; // optional
CustomerMsgRef: TRef; // optional
CustomField: TArray<TCustomField>; // optional
Line: TArray<TLine>;
TxnTaxDetail: TTxnTaxDetail; // optional
end;
type
[ServiceContract, Model(API_MODEL)]
......@@ -394,10 +488,11 @@ type
[HttpGet] function GenerateOrderWebPDF(orderID: string): string;
[HttpGet] function GenerateOrderCuttingPDF(orderID: string): string;
[HttpGet] function getQBCustomers(): TJSONArray;
[HttpGet] function getQBItems(): TJSONArray;
function AddUser(userInfo: string): string;
function AddItem(itemInfo: string): string;
function AddItem(itemInfo: string): TJSONObject;
function AddShippingAddress(Addressinfo: string): TJSONObject;
function DelShippingAddress(AddressID, CustomerID: string): TJSONObject;
function DelUser(username: string): string;
......
......@@ -40,6 +40,7 @@ type
function GetWebOrder(orderInfo: string): TWebOrder;
function GetCuttingDieOrder(orderInfo: string): TCuttingDie;
function GetQBCustomers: TJSONArray;
function GetQBItems: TJSONArray;
function EditUser(const editOptions: string): string;
......@@ -51,7 +52,7 @@ type
function AddUser(userInfo: string): string;
function AddCustomer(customerInfo: string): TJSONObject;
function AddItem(itemInfo: string): string;
function AddItem(itemInfo: string): TJSONObject;
function DelUser(username: string): string;
function AddCorrugatedOrder(orderInfo: string): TJSONObject;
function AddWebOrder(orderInfo: string): TJSONObject;
......@@ -86,6 +87,7 @@ uses
System.Generics.Collections,
XData.Sys.Exceptions, uLibrary, rOrderWeb, rOrderCutting;
procedure TLookupService.AfterConstruction;
begin
inherited;
......@@ -93,12 +95,14 @@ begin
end;
procedure TLookupService.BeforeDestruction;
begin
ordersDB.Free;
inherited;
end;
function TLookupService.DelShippingAddress(AddressID, CustomerID: string): TJSONObject;
var
SQL: string;
......@@ -109,7 +113,7 @@ begin
OrdersDB.UniQuery1.SQL.Text := SQL;
OrdersDB.UniQuery1.ExecSQL;
result := TJSONObject.Create;
result.AddPair('status', 'Success:Address Successfully Deleted');
result.AddPair('status', 'Success: Address Successfully Deleted');
SQL := 'select * FROM customers c LEFT JOIN customers_ship s ON c.CUSTOMER_ID = s.customer_id WHERE c.CUSTOMER_ID = ' + CustomerID;
doQuery(ordersDB.UniQuery1, SQL);
ADDRESS_LIST := TJSONArray.Create;
......@@ -131,6 +135,7 @@ begin
TXDataOperationContext.Current.Handler.ManagedObjects.Add(Result);
end;
function TLookupService.GetCustomers: TCustomerList;
// Retrieves a list of customers and sends it to the client in object form.
// The object contains the ID, Name, Short Name, and the shipping address.
......@@ -138,18 +143,19 @@ var
SQL: string;
customer: TCustomerItem;
begin
try
SQL := 'select * from customers';
doQuery(ordersDB.UniQuery1, SQL);
result := TCustomerList.Create;
Result.data := TList<TCustomerItem>.Create;
TXDataOperationContext.Current.Handler.ManagedObjects.Add( Result.data );
TXDataOperationContext.Current.Handler.ManagedObjects.Add(Result.data);
result.count := 0;
while not ordersDB.UniQuery1.Eof do
begin
customer := TCustomerItem.Create;
TXDataOperationContext.Current.Handler.ManagedObjects.Add( customer );
TXDataOperationContext.Current.Handler.ManagedObjects.Add(customer);
customer.NAME := ordersDB.UniQuery1.FieldByName('NAME').AsString;
customer.CUSTOMER_ID := ordersDB.UniQuery1.FieldByName('CUSTOMER_ID').AsInteger;
......@@ -165,8 +171,16 @@ begin
ordersDB.UniQuery1.Next;
end;
ordersDB.UniQuery1.Close;
except
on E: Exception do
begin
Logger.Log(2, 'Error in GetCustomers: ' + E.Message);
raise EXDataHttpException.Create(500, 'Unable to retrieve customer list: ' + E.Message);
end;
end;
end;
function TLookupService.GetCustomer(ID: string): TCustomerItem;
// Gets one specific customer from the ID given by the client. This is used for
// the OrderEntry forms.
......@@ -175,6 +189,7 @@ var
ADDRESS: TAddressItem;
USER: TUserItem;
begin
try
if ID = '' then
SQL := 'select * FROM customers c LEFT JOIN customers_ship s ON c.CUSTOMER_ID = s.customer_id WHERE c.CUSTOMER_ID = -1'
else
......@@ -232,26 +247,38 @@ begin
result.USERS.Add(USER);
ordersDB.UniQuery1.Next;
end;
except
on E: Exception do
begin
Logger.Log(2, 'Error in GetCustomer: ' + E.Message);
raise EXDataHttpException.Create(500, 'Unable to retrieve customer: ' + E.Message);
end;
end;
end;
function TLookupService.GenerateOrderListPDF(searchOptions: string): string;
// Generates a report pdf based on the last search (if any) Linked to rOrders
// file which does most of the work.
var
SQL: string;
rptOrderList: TrptOrderList; // Local instance of rptOrders
rptOrderList: TrptOrderList;
CompanyID, CompanyName: string;
params: TStringList;
begin
rptOrderList := TrptOrderList.Create(nil);
try
try
params := TStringList.Create;
params.StrictDelimiter := true;
// parse the searchOptions
params.Delimiter := '&';
params.DelimitedText := searchOptions;
// Strip paging if this is a PDF export
if params.Values['forPDF'] = 'true' then
begin
params.Values['pagesize'] := '';
params.Values['pagenumber'] := '';
end;
companyID := params.Values['companyID'];
if companyID <> '' then
begin
......@@ -262,18 +289,20 @@ begin
else
CompanyName := '';
SQL := GenerateOrdersSQL(searchOptions).SQL;
SQL := GenerateOrdersSQL(params.DelimitedText).SQL;
result := rptOrderList.PrepareReport(SQL, CompanyName);
//rptOrderList.GeneratePDF;
// Optionally, log success
Logger.log(5, 'PDF Report successfully generated for searchOptions: ' + searchOptions);
Logger.log(5, 'PDF Report successfully generated for searchOptions: ' + params.DelimitedText);
except
on E: Exception do
raise EXDataHttpException.Create(500, 'Failed to generate PDF: ' + E.Message);
end;
finally
rptOrderList.Free;
end;
end;
function TLookupService.AddShippingAddress(AddressInfo: string): TJSONObject;
var
JSONData: TJSONObject;
......@@ -335,10 +364,10 @@ begin
if mode = 'ADD' then
begin
msg := 'Success:Shipping Address Successfully Added';
msg := 'Success: Shipping Address Successfully Added';
end
else
msg := 'Success:Shipping Address Successfully Edited';
msg := 'Success: Shipping Address Successfully Edited';
// Sends the updated Address List Back.
......@@ -464,9 +493,9 @@ begin
ordersDB.UniQuery1.Post;
if mode = 'ADD' then
msg := 'Success:Customer Successfully Added'
msg := 'Success: Customer Successfully Added'
else
msg := 'Success:Customer Successfully Edited';
msg := 'Success: Customer Successfully Edited';
Result := TJSONObject.Create.AddPair('status', msg);
......@@ -480,7 +509,7 @@ begin
end;
end
else
Result := TJSONObject.Create.AddPair('status', 'Failure:Company Account Name Must Be Unique');
Result := TJSONObject.Create.AddPair('status', 'Failure: Company Account Name Must Be Unique');
end;
function TLookupService.GenerateOrderCorrugatedPDF(orderID: string): string;
......@@ -490,6 +519,7 @@ var
begin
rptOrderCorrugated := TrptOrderCorrugated.Create(nil);
try
try
// Generate SQL query for a single order
SQL := 'SELECT * FROM corrugated_plate_orders WHERE ORDER_ID = ' + orderID;
......@@ -498,6 +528,13 @@ begin
// Optionally log success
Logger.Log(5, 'PDF Report successfully generated for order ID: ' + orderID);
except
on E: Exception do
begin
Logger.Log(1, 'Error generating corrugated PDF: ' + E.Message);
raise EXDataHttpException.Create(500, 'Error generating corrugated PDF: ' + E.Message);
end;
end;
finally
rptOrderCorrugated.Free;
end;
......@@ -510,15 +547,23 @@ var
begin
rptOrderWeb := TrptOrderWeb.Create(nil);
try
try
// Generate SQL query for a single order
//SQL := 'SELECT * FROM web_plate_orders w WHERE w.ORDER_ID = ' + orderID ;
SQL := 'SELECT * FROM web_plate_orders w LEFT JOIN qb_sales_orders q ON w.ORDER_ID = q.ORDER_ID WHERE w.ORDER_ID = ' + orderID ;
SQL := 'SELECT * FROM web_plate_orders w LEFT JOIN qb_sales_orders q ON w.ORDER_ID = q.ORDER_ID WHERE w.ORDER_ID = ' + orderID;
// Prepare the report with the query
Result := rptOrderWeb.PrepareReport(SQL);
// Optionally log success
Logger.Log(5, 'PDF Report successfully generated for order ID: ' + orderID);
except
on E: Exception do
begin
Logger.Log(1, 'Error generating web PDF: ' + E.Message);
raise EXDataHttpException.Create(500, 'Error generating web PDF: ' + E.Message);
end;
end;
finally
rptOrderWeb.Free;
end;
......@@ -531,6 +576,7 @@ var
begin
rptOrderCutting := TrptOrderCutting.Create(nil);
try
try
// Generate SQL query for a single order
SQL := 'SELECT * FROM cutting_die_orders WHERE ORDER_ID = ' + orderID;
......@@ -539,12 +585,20 @@ begin
// Optionally log success
Logger.Log(5, 'PDF Report successfully generated for order ID: ' + orderID);
except
on E: Exception do
begin
Logger.Log(1, 'Error generating cutting die PDF: ' + E.Message);
raise EXDataHttpException.Create(500, 'Error generating cutting die PDF: ' + E.Message);
end;
end;
finally
rptOrderCutting.Free;
end;
end;
function TLookupService.generateSubQuery(currStatus: string): string;
// Generates the subquery in order to retrieve all the status due/done dates
// This must be a subquery because there are at most 5 different entries which
......@@ -674,104 +728,81 @@ function TLookupService.generateOrdersSQL(searchOptions: string): TSQLQuery;
// searchOptions: search information sent form client to be parsed.
var
params: TStringList;
PageNum: integer;
PageSize: integer;
OrderBy: string;
offset: string;
limit: string;
SQL: string;
whereSQL: string;
orderBySQL: string;
OrderID: string;
CompanyID: string;
JobName: string;
orderType: string;
// These variables apply to the first status sent from the client
status1: TStatusSearchInfo;
// These variables apply to the second status sent from the client
status2: TStatusSearchInfo;
PageNum, PageSize: integer;
OrderBy, offset, limit: string;
SQL, whereSQL, orderBySQL: string;
OrderID, CompanyID, JobName, orderType: string;
status1, status2: TStatusSearchInfo;
ForPDF: Boolean;
begin
result := TSQLQuery.Create;
params := TStringList.Create;
params.StrictDelimiter := true;
// parse the searchOptions
params.Delimiter := '&';
params.DelimitedText := searchOptions;
orderBySQL := '';
PageNum := StrToInt(params.Values['pagenumber']);
PageSize := StrToInt(params.Values['pagesize']);
ForPDF := SameText(params.Values['forPDF'], 'true');
if not ForPDF then
begin
PageNum := StrToIntDef(params.Values['pagenumber'], 1);
PageSize := StrToIntDef(params.Values['pagesize'], 500);
offset := IntToStr((PageNum - 1) * PageSize);
limit := IntToStr(PageSize);
end;
OrderBy := params.Values['orderby'];
orderType := params.Values['orderType'].ToLower();
OrderID := params.Values['orderID'];
companyID := params.Values['companyID'];
jobName := params.Values['jobName'];
// Search infomation for first status type
status1 := createStatusSearchInfo(params, '1');
// Search Information for second status type
status2 := createStatusSearchInfo(params, '2');
offset := IntToStr((PageNum - 1) * PageSize);
limit := IntToStr(PageSize);
SQL := 'SELECT o.ORDER_ID, c.SHORT_NAME, o.LOCATION AS Loc, c.NAME AS COMPANY_NAME, o.JOB_NAME, o.ORDER_TYPE, ';
// Generate the subqueries that get the Status Dates(Due and Done)
SQL := SQL + generateSubquery('PROOF');
SQL := SQL + generateSubquery('ART');
SQL := SQL + generateSubquery('PLATE');
SQL := SQL + generateSubquery('MOUNT');
SQL := SQL + generateSubquery('SHIP');
SQL := 'SELECT o.ORDER_ID, c.SHORT_NAME, o.LOCATION AS Loc, c.NAME AS COMPANY_NAME, o.JOB_NAME, o.ORDER_TYPE, ' +
generateSubquery('PROOF') +
generateSubquery('ART') +
generateSubquery('PLATE') +
generateSubquery('MOUNT') +
generateSubquery('SHIP');
// Generate the Where SQL based on if there is a status filter applied or not
whereSQL := 'from orders o join customers c on ' +
'c.CUSTOMER_ID = o.COMPANY_ID left join qb_sales_orders qb on qb.ORDER_ID = o.ORDER_ID ' +
' LEFT JOIN corrugated_plate_orders cpo ON o.ORDER_ID = cpo.ORDER_ID ' +
whereSQL := ' FROM orders o JOIN customers c ON c.CUSTOMER_ID = o.COMPANY_ID ' +
'LEFT JOIN qb_sales_orders qb ON qb.ORDER_ID = o.ORDER_ID ' +
'LEFT JOIN corrugated_plate_orders cpo ON o.ORDER_ID = cpo.ORDER_ID ' +
'LEFT JOIN web_plate_orders wpo ON o.ORDER_ID = wpo.ORDER_ID ' +
'LEFT JOIN cutting_die_orders cdo ON o.ORDER_ID = cdo.ORDER_ID where 0 = 0';
'LEFT JOIN cutting_die_orders cdo ON o.ORDER_ID = cdo.ORDER_ID WHERE 0 = 0';
if ( ( status1.filterType <> '' ) and ( status1.filterType <> 'NONE' ) ) then
if (status1.filterType <> '') and (status1.filterType <> 'NONE') then
whereSQL := whereSQL + generateStatusWhereSQL(status1);
if ( (status2.filterType <> '' ) and ( status2.filterType <> 'NONE' ) ) then
if (status2.filterType <> '') and (status2.filterType <> 'NONE') then
whereSQL := whereSQL + generateStatusWhereSQL(status2);
if ( ( orderType <> '' ) and ( orderType <> 'any' ) ) then
if (orderType <> '') and (orderType <> 'any') then
begin
if ( orderType <> 'cutting die') then
whereSQL := whereSQL + ' AND o.ORDER_TYPE = ' + quotedStr(orderType + '_plate')
if (orderType <> 'cutting die') then
whereSQL := whereSQL + ' AND o.ORDER_TYPE = ' + QuotedStr(orderType + '_plate')
else
whereSQL := whereSQL + ' AND o.ORDER_TYPE = ' + quotedStr('cutting_die');
whereSQL := whereSQL + ' AND o.ORDER_TYPE = ' + QuotedStr('cutting_die');
end;
if orderID <> '' then
whereSQL := whereSQL + ' AND o.ORDER_ID = ' + orderID;
if OrderID <> '' then
whereSQL := whereSQL + ' AND o.ORDER_ID = ' + OrderID;
if companyID <> '' then
whereSQL := whereSQL + ' AND c.CUSTOMER_ID = ' + companyID;
if jobName <> '' then
whereSQL := whereSQL + ' AND o.JOB_NAME LIKE ' + quotedStr('%' + jobName + '%');
whereSQL := whereSQL + ' AND o.JOB_NAME LIKE ' + QuotedStr('%' + jobName + '%');
orderBySQL := 'ORDER BY ' + OrderBy;
orderBySQL := ' ORDER BY ' + OrderBy;
SQL := SQL + 'o.PRICE, qb.QB_REF_NUM, ' +
'coalesce( cpo.staff_fields_po_number, wpo.staff_fields_po_number, cdo.staff_fields_po_number ) AS po_number, ' +
'coalesce( cpo.staff_fields_quickbooks_item, wpo.staff_fields_quickbooks_item, cdo.staff_fields_quickbooks_item ) AS quickbooks_item, ' +
'coalesce( cpo.staff_fields_order_date, wpo.staff_fields_order_date, cdo.staff_fields_order_date ) AS ORDER_DATE ' +
whereSQL + ' ' + orderBySQL + ' LIMIT ' + limit + ' OFFSET ' + offset;
SQL := SQL + ' o.PRICE, qb.QB_REF_NUM, ' +
'COALESCE(cpo.staff_fields_po_number, wpo.staff_fields_po_number, cdo.staff_fields_po_number) AS po_number, ' +
'COALESCE(cpo.staff_fields_quickbooks_item, wpo.staff_fields_quickbooks_item, cdo.staff_fields_quickbooks_item) AS quickbooks_item, ' +
'COALESCE(cpo.staff_fields_order_date, wpo.staff_fields_order_date, cdo.staff_fields_order_date) AS ORDER_DATE ';
if not ForPDF then
SQL := SQL + whereSQL + orderBySQL + ' LIMIT ' + limit + ' OFFSET ' + offset
else
SQL := SQL + whereSQL + orderBySQL;
// send the SQL and whereSQL back. whereSQL is needed to get the total count.
// probably a way to getthe TotalCount in original SQL but it was giving me issues
result.SQL := SQL;
result.whereSQL := whereSQL;
end;
......@@ -817,13 +848,14 @@ var
SQLQuery: TSQLQuery;
begin
SQLQuery := generateOrdersSQL(searchOptions);
TXDataOperationContext.Current.Handler.ManagedObjects.Add(SQLQuery); // Added SQLQuery to ManagedObjects
TXDataOperationContext.Current.Handler.ManagedObjects.Add(SQLQuery);
Result := TOrderList.Create;
try
TXDataOperationContext.Current.Handler.ManagedObjects.Add(Result);
Result.data := TList<TOrderItem>.Create;
TXDataOperationContext.Current.Handler.ManagedObjects.Add(Result.data);
try
SQL := SQLQuery.SQL;
whereSQL := SQLQuery.whereSQL;
......@@ -835,24 +867,27 @@ begin
TXDataOperationContext.Current.Handler.ManagedObjects.Add(Order);
Result.data.Add(Order);
Order.DBID := ordersDB.UniQuery1.FieldByName('ORDER_ID').AsString;
Order.ID := ordersDB.UniQuery1.FieldByName('SHORT_NAME').AsString;
Order.companyName := ordersDB.UniQuery1.FieldByName('COMPANY_NAME').AsString;
Order.jobName := ordersDB.UniQuery1.FieldByName('JOB_NAME').AsString;
Order.orderDate := ordersDB.UniQuery1.FieldByName('ORDER_DATE').AsString;
Order.proofDue := ordersDB.UniQuery1.FieldByName('PROOF_DUE').AsString;
Order.proofDone := ordersDB.UniQuery1.FieldByName('PROOF_DONE').AsString;
Order.artDue := ordersDB.UniQuery1.FieldByName('ART_DUE').AsString;
Order.artDone := ordersDB.UniQuery1.FieldByName('ART_DONE').AsString;
Order.plateDue := ordersDB.UniQuery1.FieldByName('PLATE_DUE').AsString;
Order.plateDone := ordersDB.UniQuery1.FieldByName('PLATE_DONE').AsString;
Order.mountDue := ordersDB.UniQuery1.FieldByName('MOUNT_DUE').AsString;
Order.mountDone := ordersDB.UniQuery1.FieldByName('MOUNT_DONE').AsString;
Order.shipDue := ordersDB.UniQuery1.FieldByName('SHIP_DUE').AsString;
Order.shipDone := ordersDB.UniQuery1.FieldByName('SHIP_DONE').AsString;
Order.price := ordersDB.UniQuery1.FieldByName('PRICE').AsString;
Order.qbRefNum := ordersDB.UniQuery1.FieldByName('QB_REF_NUM').AsString;
Order.orderType := ordersDB.UniQuery1.FieldByName('ORDER_TYPE').AsString.Replace('_', ' ');
with ordersDB.UniQuery1 do
begin
Order.DBID := FieldByName('ORDER_ID').AsString;
Order.ID := FieldByName('SHORT_NAME').AsString;
Order.companyName := FieldByName('COMPANY_NAME').AsString;
Order.jobName := FieldByName('JOB_NAME').AsString;
Order.orderDate := FieldByName('ORDER_DATE').AsString;
Order.proofDue := FieldByName('PROOF_DUE').AsString;
Order.proofDone := FieldByName('PROOF_DONE').AsString;
Order.artDue := FieldByName('ART_DUE').AsString;
Order.artDone := FieldByName('ART_DONE').AsString;
Order.plateDue := FieldByName('PLATE_DUE').AsString;
Order.plateDone := FieldByName('PLATE_DONE').AsString;
Order.mountDue := FieldByName('MOUNT_DUE').AsString;
Order.mountDone := FieldByName('MOUNT_DONE').AsString;
Order.shipDue := FieldByName('SHIP_DUE').AsString;
Order.shipDone := FieldByName('SHIP_DONE').AsString;
Order.price := FieldByName('PRICE').AsString;
Order.qbRefNum := FieldByName('QB_REF_NUM').AsString;
Order.orderType := FieldByName('ORDER_TYPE').AsString.Replace('_', ' ');
end;
if ordersDB.UniQuery1.FieldByName('ORDER_TYPE').AsString = 'web_plate' then
begin
......@@ -877,10 +912,14 @@ begin
SQL := 'SELECT COUNT(*) AS total_count ' + whereSQL;
doQuery(ordersDB.UniQuery1, SQL);
Result.count := ordersDB.UniQuery1.FieldByName('total_count').AsInteger;
ordersDB.UniQuery1.Close;
except
Result.Free; // Cleaned up memory in case of exceptions
on E: Exception do
begin
Logger.Log(2, 'Error in GetOrders: ' + E.Message);
raise EXDataHttpException.Create(500, 'Unable to retrieve order list: ' + E.Message);
end;
end;
end;
......@@ -897,6 +936,7 @@ var
ADDRESS: TAddressItem;
begin
orderID := orderInfo;
try
SQL := 'select ORDER_TYPE from orders where ORDER_ID = ' + quotedStr(orderID);
doQuery(ordersDB.UniQuery1, SQL);
orderType := ordersDB.UniQuery1.FieldByName('ORDER_TYPE').AsString;
......@@ -1087,8 +1127,16 @@ begin
ordersDB.UniQuery1.Close;
result.ITEMS := GetItems('');
except
on E: Exception do
begin
Logger.Log(2, 'Error in GetOrder: ' + E.Message);
raise EXDataHttpException.Create(500, 'Unable to retrieve order: ' + E.Message);
end;
end;
end;
function TLookupService.GetWebOrder(orderInfo: string): TWebOrder;
var
orderType: string;
......@@ -1096,6 +1144,7 @@ var
SQL: string;
ADDRESS: TAddressItem;
begin
try
orderID := orderInfo;
SQL := 'select * from web_plate_orders o JOIN customers c ON c.CUSTOMER_ID = o.COMPANY_ID where ORDER_ID = ' + quotedStr(orderID);
doQuery(ordersDB.UniQuery1, SQL);
......@@ -1199,7 +1248,6 @@ begin
result.upc_distortion_percent := ordersDB.UniQuery1.FieldByName('upc_distortion_percent').AsString;
result.upc_distortion_amount := ordersDB.UniQuery1.FieldByName('upc_distortion_amount').AsString;
// General
result.general_comments := ordersDB.UniQuery1.FieldByName('general_comments').AsString;
......@@ -1208,7 +1256,7 @@ begin
SQL := 'SELECT s.ship_block FROM customers c JOIN customers_ship s ON c.CUSTOMER_ID = s.customer_id WHERE c.CUSTOMER_ID = ' + IntToStr(result.COMPANY_ID);
doQuery(ordersDB.UniQuery1, SQL);
result.ADDRESS_LIST := TList<TAddressItem>.Create;
TXDataOperationContext.Current.Handler.ManagedObjects.Add( Result.ADDRESS_LIST );
TXDataOperationContext.Current.Handler.ManagedObjects.Add( result.ADDRESS_LIST );
while not ordersDB.UniQuery1.Eof do
begin
......@@ -1222,10 +1270,16 @@ begin
ordersDB.UniQuery1.Close;
result.ITEMS := GetItems('');
except
on E: Exception do
begin
Logger.Log(2, 'Error in GetWebOrder: ' + E.Message);
raise EXDataHttpException.Create(500, 'Unable to retrieve web order: ' + E.Message);
end;
end;
end;
function TLookupService.GetCuttingDieOrder(orderInfo: string): TCuttingDie;
var
orderType: string;
......@@ -1233,6 +1287,7 @@ var
SQL: string;
ADDRESS: TAddressItem;
begin
try
orderID := orderInfo;
SQL := 'select * from cutting_die_orders o JOIN customers c ON c.CUSTOMER_ID = o.COMPANY_ID where ORDER_ID = ' + quotedStr(orderID);
doQuery(ordersDB.UniQuery1, SQL);
......@@ -1265,7 +1320,7 @@ begin
SQL := 'SELECT s.ship_block FROM customers c JOIN customers_ship s ON c.CUSTOMER_ID = s.customer_id WHERE c.CUSTOMER_ID = ' + IntToStr(result.COMPANY_ID);
doQuery(ordersDB.UniQuery1, SQL);
result.ADDRESS_LIST := TList<TAddressItem>.Create;
TXDataOperationContext.Current.Handler.ManagedObjects.Add( Result.ADDRESS_LIST );
TXDataOperationContext.Current.Handler.ManagedObjects.Add( result.ADDRESS_LIST );
while not ordersDB.UniQuery1.Eof do
begin
......@@ -1279,10 +1334,17 @@ begin
ordersDB.UniQuery1.Close;
result.ITEMS := GetItems('');
except
on E: Exception do
begin
raise EXDataHttpException.Create(500, 'Could not retrieve cutting die order: ' + E.Message);
end;
end;
end;
function TLookupService.GetItems(searchOptions: string): TItemList;
// retrueves all the quickbooks items for the items page on client.
// retrieves all the quickbooks items for the items page on client.
// searchOptions: probably not needed but adds limits to the page to prevent
// table on client side from getting too long. This table currently has about 27
// entries so probably not needed.
......@@ -1296,6 +1358,7 @@ var
SQL: string;
item: TItemItem;
begin
try
params := TStringList.Create;
params.StrictDelimiter := true;
// parse the searchOptions
......@@ -1310,13 +1373,11 @@ begin
PageSize := StrToInt(params.Values['pagesize']);
OrderBy := params.Values['orderby'];
limit := IntToStr(PageSize);
offset := IntToStr((PageNum - 1) * PageSize);
SQL := SQL + ' limit ' + limit + ' offset ' + offset;
end;
doQuery(ordersDB.UniQuery1, SQL);
Result:= TItemList.Create;
......@@ -1340,31 +1401,50 @@ begin
doQuery(ordersDB.UniQuery1, SQL);
Result.count := ordersDB.UniQuery1.FieldByName('total_count').AsInteger;
ordersDB.UniQuery1.Close;
except
on E: Exception do
begin
Logger.Log(2, 'Error in GetItems: ' + E.Message);
raise EXDataHttpException.Create(500, 'Unable to retrieve item list: ' + E.Message);
end;
end;
end;
function TLookupService.GetUsers(searchOptions: string): TUserList;
// Gets a list of all users for the user edit page.
// searchOptions: username of a specific user otherwise empty.
// TODO: change SQL to hide passwords instead of storing them in plain text.
// Returns all users, or one specific user when searchOptions <> ''.
// Uses parameterised SQL and the real column name USER_NAME.
var
SQL: string;
user: TUserItem;
begin
try
// Prepare and open the query
ordersDB.UniQuery1.Close;
if searchOptions = '' then
SQL := 'select * from users order by NAME ASC'
begin
ordersDB.UniQuery1.SQL.Text :=
'SELECT * FROM users ORDER BY NAME ASC';
end
else
SQL := 'select * from users where username=' + quotedStr(searchOptions);
doQuery(ordersDB.UniQuery1, SQL);
begin
ordersDB.UniQuery1.SQL.Text :=
'SELECT * FROM users WHERE USER_NAME = :uname';
ordersDB.UniQuery1.ParamByName('uname').AsString := searchOptions;
end;
Result:= TUserList.Create;
ordersDB.UniQuery1.Open;
// Build result list
Result := TUserList.Create;
Result.data := TList<TUserItem>.Create;
TXDataOperationContext.Current.Handler.ManagedObjects.Add( Result.data );
TXDataOperationContext.Current.Handler.ManagedObjects.Add(Result.data);
while not ordersDB.UniQuery1.Eof do
begin
user := TUserItem.Create;
TXDataOperationContext.Current.Handler.ManagedObjects.Add( user );
Result.data.Add( user );
TXDataOperationContext.Current.Handler.ManagedObjects.Add(user);
Result.data.Add(user);
user.userID := ordersDB.UniQuery1.FieldByName('USER_ID').AsString;
user.username := ordersDB.UniQuery1.FieldByName('USER_NAME').AsString;
user.password := ordersDB.UniQuery1.FieldByName('PASSWORD').AsString;
......@@ -1375,15 +1455,31 @@ begin
user.rights := ordersDB.UniQuery1.FieldByName('SYSTEM_RIGHTS').AsInteger;
user.perspectiveID := ordersDB.UniQuery1.FieldByName('PERSPECTIVE_ID').AsString;
user.QBID := ordersDB.UniQuery1.FieldByName('QB_ID').AsString;
ordersDB.UniQuery1.Next;
end;
ordersDB.UniQuery1.Close;
SQL:= 'select count(*) as total_count from users';
doQuery(ordersDB.UniQuery1, SQL);
// Get total-row count (keeps old behaviour)
ordersDB.UniQuery1.SQL.Text :=
'SELECT COUNT(*) AS total_count FROM users';
ordersDB.UniQuery1.Open;
Result.count := ordersDB.UniQuery1.FieldByName('total_count').AsInteger;
ordersDB.UniQuery1.Close;
except
on E: Exception do
begin
ordersDB.UniQuery1.Close;
raise EXDataHttpException.Create(
500,
'Unable to retrieve users: ' + E.Message
);
end;
end;
end;
function TLookupService.EditUser(const editOptions: string): string;
// Edits the user.
// editOptions: all user information that will be changed.
......@@ -1467,7 +1563,7 @@ begin
end;}
ordersDB.UniQuery1.Post;
Result := 'Success:Edit Successful';
Result := 'Success: User Successfully Edited';
end;
ordersDB.UniQuery1.Close;
end;
......@@ -1527,7 +1623,7 @@ var
DateFormat: TFormatSettings;
ORDER_ID: integer;
mode: string;
temp: string;
msg: string;
begin
DateFormat := TFormatSettings.Create;
DateFormat.ShortDateFormat := 'yyyy-mm-dd';
......@@ -1572,7 +1668,7 @@ begin
else
TDateTimeField(Field).AsDateTime := StrToDate(Pair.JsonValue.Value);
end
else if Pair.JsonValue.Value <> '' then
else
Field.AsString := Pair.JsonValue.Value;
end;
end;
......@@ -1581,26 +1677,27 @@ begin
// Post the record to the database
ordersDB.UniQuery1.Post;
temp := JSONData.GetValue<string>('staff_fields_proof_date');
if ( JSONData.GetValue<string>('staff_fields_proof_date') <> '' ) and ( JSONData.GetValue<string>('staff_fields_proof_date') <> '12/30/1899' ) then
AddStatusSchedule('PROOF', JSONData, ORDER_ID);
temp := JSONData.GetValue<string>('staff_fields_ship_date');
if ( JSONData.GetValue<string>('staff_fields_ship_date') <> '' ) and ( JSONData.GetValue<string>('staff_fields_ship_date') <> '12/30/1899' ) then
AddStatusSchedule('SHIP', JSONData, ORDER_ID);
temp := JSONData.GetValue<string>('staff_fields_art_due');
if ( JSONData.GetValue<string>('staff_fields_art_due') <> '' ) and ( JSONData.GetValue<string>('staff_fields_art_due') <> '12/30/1899' ) then
AddStatusSchedule('ART', JSONData, ORDER_ID);
temp := JSONData.GetValue<string>('staff_fields_plate_due');
if ( JSONData.GetValue<string>('staff_fields_plate_due') <> '' ) and ( JSONData.GetValue<string>('staff_fields_plate_due') <> '12/30/1899' ) then
AddStatusSchedule('PLATE', JSONData, ORDER_ID);
temp := JSONData.GetValue<string>('staff_fields_mount_due');
if ( JSONData.GetValue<string>('staff_fields_mount_due') <> '' ) and ( JSONData.GetValue<string>('staff_fields_mount_due') <> '12/30/1899' ) then
AddStatusSchedule('MOUNT', JSONData, ORDER_ID);
addToRevisionsTable(intToStr(ORDER_ID), 'corrugated_plate_orders_revisions', JSONData);
AddToRevisionsTable(intToStr(ORDER_ID), 'corrugated_plate_orders_revisions', JSONData);
if mode = 'ADD' then
msg := 'Success: Order Successfully Added'
else
msg := 'Success: Order Successfully Edited';
Result := TJSONObject.Create.AddPair('status', 'success');
Result := TJSONObject.Create.AddPair('status', msg);
Result.AddPair('OrderID', ORDER_ID);
TXDataOperationContext.Current.Handler.ManagedObjects.Add(Result);
except
on E: Exception do
......@@ -1611,7 +1708,6 @@ begin
end;
function TLookupService.AddStatusSchedule(StatusType: string; order: TJSONObject; ORDER_ID: integer): string;
// Adds/edits orders_status_schedule table.
// StatusType: name of the status getting added to the schedule.
......@@ -1788,13 +1884,11 @@ begin
OrdersDB.UniQuery1.FieldByName(StatusField).AsString := Date;
OrdersDB.UniQuery1.Post;
finally
order.Free;
end;
end;
result := 'success';
except
on E: Exception do
......@@ -1803,9 +1897,9 @@ begin
end;
function TLookupService.AddUser(userInfo:string): string;
function TLookupService.AddUser(userInfo: string): string;
// Adds a user to the database
// userInfo - user information being added
var
user: string;
password: string;
......@@ -1818,16 +1912,17 @@ var
QB: string;
SQL: string;
dateCreated: TDateTime;
hashString: string;
hashPW: string;
rightsInt: Integer;
params: TStringList;
begin
try
params := TStringList.Create;
params.StrictDelimiter := true;
// parse the searchOptions
params.StrictDelimiter := True;
params.Delimiter := '&';
params.DelimitedText := userInfo;
dateCreated := now;
dateCreated := Now;
user := params.Values['username'];
password := params.Values['password'];
full_name := params.Values['fullname'];
......@@ -1837,82 +1932,96 @@ begin
rights := params.Values['rights'];
perspective := params.Values['perspective'];
QB := params.Values['QB'];
//newUser := params.Values['newuser'];
//hashString := DateTimeToStr(dateCreated) + params.Values['password'];
//hashPW := THashSHA2.GetHashString(hashString, THashSHA2.TSHA2Version.SHA512).ToUpper;
SQL := 'select * from users where USER_NAME = ' + QuotedStr(params.Values['username'].toLower);
SQL := 'SELECT * FROM users WHERE USER_NAME = ' + QuotedStr(user.ToLower);
ordersDB.UniQuery1.Close;
ordersDB.UniQuery1.SQL.Text := SQL;
ordersDB.UniQuery1.Open;
if ordersDB.UniQuery1.IsEmpty then
begin
ordersDB.UniQuery1.Insert;
ordersDB.UniQuery1.FieldByName('USER_NAME').AsString := user;
ordersDB.UniQuery1.FieldByName('PASSWORD').AsString := password;
//THashSHA2.GetHashString(hashString, THashSHA2.TSHA2Version.SHA512).ToUpper;
//ordersDB.UniQuery1.FieldByName('date_created').AsString := DateTimeToStr(dateCreated);
ordersDB.UniQuery1.FieldByName('NAME').AsString := full_name;
if( StrToBool(status) ) then
if StrToBoolDef(status, False) then
ordersDB.UniQuery1.FieldByName('STATUS').AsString := 'ACTIVE'
else
ordersDB.UniQuery1.FieldByName('STATUS').AsString := 'INACTIVE';
ordersDB.UniQuery1.FieldByName('EMAIL').AsString := email;
ordersDB.UniQuery1.FieldByName('ACCESS_TYPE').AsString := Access;
ordersDB.UniQuery1.FieldByName('SYSTEM_RIGHTS').AsInteger := StrToInt(rights);
ordersDB.UniQuery1.FieldByName('ACCESS_TYPE').AsString := access;
if not TryStrToInt(rights, rightsInt) then
rightsInt := 0;
ordersDB.UniQuery1.FieldByName('SYSTEM_RIGHTS').AsInteger := rightsInt;
ordersDB.UniQuery1.FieldByName('PERSPECTIVE_ID').AsString := perspective;
ordersDB.UniQuery1.FieldByName('QB_ID').AsString := QB;
ordersDB.UniQuery1.Post;
Result := 'Success:User successfully added';
Result := 'Success: User successfully added';
end
else
Result := 'Failure:Username already taken';
Result := 'Failure: Username already taken';
except
on E: Exception do
raise EXDataHttpException.Create(500, 'AddUser failed: ' + E.Message);
end;
end;
function TLookupService.AddItem(itemInfo: string): string;
function TLookupService.AddItem(itemInfo: string): TJSONObject;
// Adds an item to the database
// itemInfo: item info to add to database
var
params: TStringList;
JSONData: TJSONObject;
Name: string;
Description: string;
Description, mode: string;
Status: boolean;
SQL: string;
begin
params := TStringList.Create;
params.StrictDelimiter := true;
// parse the searchOptions
params.Delimiter := '&';
params.DelimitedText := itemInfo;
result := TJSONObject.Create;
JSONData := TJSONObject.ParseJSONValue(itemInfo) as TJSONObject;
if JSONData = nil then
raise Exception.Create('Invalid JSON format'); // If parsing fails, raise an exception
mode := JSONData.GetValue<string>('mode');
Name := params.Values['name'];
Description := params.Values['description'];
Status := StrToBool(params.Values['status']);
Name := JSONData.GetValue<string>('qb_item_name');
Description := JSONData.GetValue<string>('item_desc');
Status := StrToBool(JSONData.GetValue<string>('status'));
SQL := 'select * from qb_items where qb_item_name = ' + QuotedStr(Name);
if mode = 'ADD' then
begin
doQuery(ordersDB.UniQuery1, SQL);
if ordersDB.UniQuery1.IsEmpty then
if true then //ordersDB.UniQuery1.IsEmpty then
begin
ordersDB.UniQuery1.Insert;
ordersDB.UniQuery1.FieldByName('qb_item_name').AsString := Name;
ordersDB.UniQuery1.FieldByName('item_desc').AsString := Description;
if Status then
if status then
ordersDB.UniQuery1.FieldByName('status').AsString := 'ACTIVE'
else
ordersDB.UniQuery1.FieldByName('status').AsString := 'INACTIVE';
ordersDB.UniQuery1.FieldByName('qb_items_qb_id').AsString := JSONData.GetValue<string>('qb_items_qb_id');
ordersDB.UniQuery1.Post;
Result := 'Success:Item successfully added';
Result.AddPair('msg', 'Success: Item successfully added');
end
else
Result := 'Failure: Item already exists';
Result.AddPair('msg', 'Failure: Item already exists');
end;
end;
function TLookupService.DelUser(username: string): string;
// deletes a user. not currently implemented definitely needs touching up to avoid
// deleting users prematurely.
......@@ -1938,7 +2047,6 @@ begin
end;
end;
function TLookupService.AddWebOrder(orderInfo: string): TJSONObject;
// Adds corrugated order to the database. This process is done in 3 different
// tables so if any changes are made make sure to check orders, corrugated_plate_orders
......@@ -1953,7 +2061,7 @@ var
CurrDate: TDateTime;
ORDER_ID: integer;
mode: string;
temp: string;
msg: string;
begin
DateFormat := TFormatSettings.Create;
DateFormat.ShortDateFormat := 'yyyy-mm-dd';
......@@ -1979,8 +2087,10 @@ begin
ORDER_ID := JSONData.GetValue<integer>('ORDER_ID');
SQL := 'select * from web_plate_orders where ORDER_ID = ' + IntToStr(ORDER_ID);
end;
doQuery(ordersDB.UniQuery1, SQL);
try
doQuery(ordersDB.UniQuery1, SQL);
if mode = 'ADD' then
ordersDB.UniQuery1.Insert
else
......@@ -1999,7 +2109,7 @@ begin
else
TDateTimeField(Field).AsDateTime := StrToDate(Pair.JsonValue.Value);
end
else if Pair.JsonValue.Value <> '' then
else
Field.AsString := Pair.JsonValue.Value;
end;
end;
......@@ -2020,17 +2130,24 @@ begin
AddToRevisionsTable(IntToStr(ORDER_ID), 'web_plate_orders_revisions', JSONData);
Result := TJSONObject.Create.AddPair('status', 'success');
if mode = 'ADD' then
msg := 'Success: Order Successfully Added'
else
msg := 'Success: Order Successfully Edited';
Result := TJSONObject.Create.AddPair('status', msg);
Result.AddPair('OrderID', ORDER_ID);
TXDataOperationContext.Current.Handler.ManagedObjects.Add(Result);
except
on E: Exception do
begin
Result := TJSONObject.Create.AddPair('error', E.Message);
end
Logger.Log(2, 'Error in AddWebOrder: ' + E.Message);
raise EXDataHttpException.Create(500, 'Unable to add or edit web order: ' + E.Message);
end;
end;
end;
function TLookupService.AddCuttingDieOrder(orderInfo: string): TJSONObject;
var
JSONData, ResponseData: TJSONObject;
......@@ -2041,7 +2158,7 @@ var
CurrDate: TDateTime;
ORDER_ID: integer;
mode: string;
temp: string;
msg: string;
begin
DateFormat := TFormatSettings.Create;
DateFormat.ShortDateFormat := 'yyyy-mm-dd';
......@@ -2087,7 +2204,7 @@ begin
else
TDateTimeField(Field).AsDateTime := StrToDate(Pair.JsonValue.Value);
end
else if Pair.JsonValue.Value <> '' then
else
Field.AsString := Pair.JsonValue.Value;
end;
end;
......@@ -2104,37 +2221,42 @@ begin
AddToRevisionsTable(IntToStr(ORDER_ID), 'cutting_die_orders_revisions', JSONData);
Result := TJSONObject.Create.AddPair('status', 'success');
if mode = 'ADD' then
msg := 'Success: Order Successfully Added'
else
msg := 'Success: Order Successfully Edited';
Result := TJSONObject.Create.AddPair('status', msg);
Result.AddPair('OrderID', ORDER_ID);
TXDataOperationContext.Current.Handler.ManagedObjects.Add(Result);
except
on E: Exception do
begin
Result := TJSONObject.Create.AddPair('error', E.Message);
end
Logger.Log(2, 'Error in AddCuttingDieOrder: ' + E.Message);
raise EXDataHttpException.Create(500, 'Unable to add cutting die order: ' + E.Message);
end;
end;
end;
function TLookupService.delOrder(OrderID, orderType, UserID: string): TJSONObject;
var
table: string;
table2: string;
sql: string;
CorrugatedOrder: TFullOrder;
WebOrder: TWebOrder;
CuttingDieOrder: TCuttingDie;
table, table2, SQL: string;
stream: TStringStream;
DateFormat: TFormatSettings;
JSONData: TJSONObject;
JSONValue: TJSONValue;
JSONObject, DataObject, JSONData: TJSONObject;
JSONArray: TJSONArray;
Pair: TJSONPair;
Field: TField;
mode: string;
stream: TStringStream;
RevisionID, rev_num: integer;
JSONValue: TJSONValue;
JSONObject: TJSONObject;
DataObject: TJSONObject;
RevisionID, rev_num, OrderIDInt: Integer;
begin
try
// Convert ORDER_ID to integer safely
OrderIDInt := StrToIntDef(OrderID, -1);
if OrderIDInt = -1 then
raise Exception.Create('Invalid OrderID: not a valid integer');
if orderType = 'corrugated' then
begin
table := 'corrugated_plate_orders';
......@@ -2151,64 +2273,58 @@ begin
table2 := 'cutting_die_orders_revisions';
end;
stream := TStringStream.Create('', TEncoding.UTF8);
DateFormat := TFormatSettings.Create;
DateFormat.ShortDateFormat := 'yyyy-mm-dd';
DateFormat.DateSeparator := '-';
//Update RevisionID
SQL := 'UPDATE idfield set KEYVALUE = KEYVALUE + 1 WHERE KEYNAME = ' + quotedStr('GEN_ORDER_REVISION_ID');
// Get new revision ID
SQL := 'UPDATE idfield SET KEYVALUE = KEYVALUE + 1 WHERE KEYNAME = ' + QuotedStr('GEN_ORDER_REVISION_ID');
OrdersDB.UniQuery1.SQL.Text := SQL;
OrdersDB.UniQuery1.ExecSQL;
//Retrieve updated RevisionID
SQL := 'select KEYVALUE from idfield where KEYNAME = ' + quotedStr('GEN_ORDER_REVISION_ID');
SQL := 'SELECT KEYVALUE FROM idfield WHERE KEYNAME = ' + QuotedStr('GEN_ORDER_REVISION_ID');
doQuery(OrdersDB.UniQuery1, SQL);
RevisionID := OrdersDB.UniQuery1.FieldByName('KEYVALUE').AsInteger;
// Convert Order into JSON
SQL := 'select * from ' + table + ' where ORDER_ID = ' + OrderID;
doQuery(ordersDB.UniQuery1, SQL);
// Fetch the order to archive it
SQL := 'SELECT * FROM ' + table + ' WHERE ORDER_ID = ' + IntToStr(OrderIDInt);
doQuery(OrdersDB.UniQuery1, SQL);
ordersDB.UniQuery1.SaveToJSON(stream);
stream := TStringStream.Create('', TEncoding.UTF8);
try
OrdersDB.UniQuery1.SaveToJSON(stream);
stream.Position := 0;
JSONValue := TJSONObject.ParseJSONValue(Stream.DataString);
JSONValue := TJSONObject.ParseJSONValue(stream.DataString);
if not Assigned(JSONValue) then
raise Exception.Create('Invalid JSON content');
try
if not (JSONValue is TJSONObject) then
raise Exception.Create('Expected JSON object');
JSONObject := TJSONObject(JSONValue);
// Get the "data" object
if not JSONObject.TryGetValue('data', DataObject) then
raise Exception.Create('Missing "data" object in JSON');
// Get the "rows" array
if not DataObject.TryGetValue('rows', JSONArray) then
raise Exception.Create('Missing "rows" array in JSON data');
JSONData := JSONArray.Items[0] as TJSONObject;
if JSONArray.Count = 0 then
raise Exception.Create('No order found with ORDER_ID = ' + IntToStr(OrderIDInt));
SQL := 'select max(REVISION_NUMBER) as rev_num from ' + table2 + ' where ORDER_ID = ' + orderID;
doQuery(ordersDB.UniQuery1, SQL);
rev_num := ordersDB.UniQuery1.FieldByName('rev_num').AsInteger + 1;
JSONData := JSONArray.Items[0] as TJSONObject;
SQL := 'select * from ' + table2 + ' where ORDER_ID = ' + orderID;
doQuery(ordersDB.UniQuery1, SQL);
// Get current max revision number
SQL := 'SELECT MAX(REVISION_NUMBER) AS rev_num FROM ' + table2 + ' WHERE ORDER_ID = ' + IntToStr(OrderIDInt);
doQuery(OrdersDB.UniQuery1, SQL);
rev_num := OrdersDB.UniQuery1.FieldByName('rev_num').AsInteger + 1;
doQuery(ordersDB.UniQuery1, SQL);
try
ordersDB.UniQuery1.Insert;
// Insert into revisions
SQL := 'SELECT * FROM ' + table2 + ' WHERE ORDER_ID = ' + IntToStr(OrderIDInt);
doQuery(OrdersDB.UniQuery1, SQL);
OrdersDB.UniQuery1.Insert;
for Pair in JSONData do
begin
Field := ordersDB.UniQuery1.FindField(Pair.JsonString.Value); // Checks if the field exists in the dataset
Field := OrdersDB.UniQuery1.FindField(Pair.JsonString.Value);
if Assigned(Field) then
begin
// handles any dates or datetimes
if (Field is TDateTimeField) and (Pair.JsonValue.Value <> '') then
TDateTimeField(Field).AsDateTime := ISO8601ToDate(Pair.JsonValue.Value, False)
else if Pair.JsonValue.Value <> '' then
......@@ -2216,34 +2332,43 @@ begin
end;
end;
ordersDB.UniQuery1.FieldByName('ORDER_ID').AsString := OrderID;
ordersDB.UniQuery1.FieldByName('ORDER_STATUS').AsString := 'DELETED';
ordersDB.UniQuery1.FieldByName('REVISION_NUMBER').AsInteger := 1;
ordersDB.UniQuery1.FieldByName('ORDER_REVISION_ID').AsInteger := RevisionID;
ordersDB.UniQuery1.FieldByName('REVISION_USER_ID').AsString := UserID;
// Post the record to the database
ordersDB.UniQuery1.Post;
OrdersDB.UniQuery1.FieldByName('ORDER_ID').AsInteger := OrderIDInt;
OrdersDB.UniQuery1.FieldByName('ORDER_STATUS').AsString := 'DELETED';
OrdersDB.UniQuery1.FieldByName('REVISION_NUMBER').AsInteger := rev_num;
OrdersDB.UniQuery1.FieldByName('ORDER_REVISION_ID').AsInteger := RevisionID;
OrdersDB.UniQuery1.FieldByName('REVISION_USER_ID').AsString := UserID;
OrdersDB.UniQuery1.Post;
Result := TJSONObject.Create.AddPair('status', 'success');
Result.AddPair('OrderID', OrderID);
TXDataOperationContext.Current.Handler.ManagedObjects.Add(Result);
except
on E: Exception do
begin
Result := TJSONObject.Create.AddPair('error', E.Message);
end
end;
finally
JSONData.Free;
stream.Free;
JSONValue.Free;
end;
sql := 'delete from ' + table + ' where ORDER_ID = ' + OrderID;
// Delete from order tables
SQL := 'DELETE FROM ' + table + ' WHERE ORDER_ID = ' + IntToStr(OrderIDInt);
OrdersDB.UniQuery1.SQL.Text := SQL;
OrdersDB.UniQuery1.ExecSQL;
sql := 'delete from orders where ORDER_ID = ' + OrderID;
SQL := 'DELETE FROM orders WHERE ORDER_ID = ' + IntToStr(OrderIDInt);
OrdersDB.UniQuery1.SQL.Text := SQL;
OrdersDB.UniQuery1.ExecSQL;
// Return result
Result := TJSONObject.Create;
Result.AddPair('status', 'success');
Result.AddPair('OrderID', IntToStr(OrderIDInt));
TXDataOperationContext.Current.Handler.ManagedObjects.Add(Result);
except
on E: Exception do
begin
Logger.Log(2, 'Error in delOrder: ' + E.Message);
raise EXDataHttpException.Create(500, 'Unable to delete order: ' + E.Message);
end;
end;
end;
procedure TLookupService.AddToRevisionsTable(OrderID: string; table: string; order: TJSONObject);
var
SQL, UserID: string;
......@@ -2298,9 +2423,9 @@ begin
ordersDB.UniQuery1.FieldByName('REVISION_USER_ID').AsString := order.GetValue<string>('USER_ID');
// Post the record to the database
ordersDB.UniQuery1.Post;
end;
function TLookupService.getQBCustomers: TJSONArray;
var
iniFile: TIniFile;
......@@ -2325,6 +2450,7 @@ begin
restResponse := TRESTResponse.Create(nil);
try
try
restRequest.Client := restClient;
restRequest.Response := restResponse;
......@@ -2369,7 +2495,6 @@ begin
for I := 0 to CustomerList.Count - 1 do
begin
Customer := CustomerList.Items[I] as TJSONObject;
ParsedCustomer := TJSONObject.Create;
......@@ -2378,7 +2503,6 @@ begin
try
ParsedCustomer.AddPair('In KGOrders', not(ordersDB.UniQuery1.IsEmpty));
ParsedCustomer.AddPair('Id', Customer.GetValue<string>('Id'));
ParsedCustomer.AddPair('CompanyName', Customer.GetValue<string>('DisplayName'));
......@@ -2426,7 +2550,13 @@ begin
raise;
end;
end;
except
on E: Exception do
begin
Logger.Log(2, 'Error in getQBCustomers: ' + E.Message);
raise EXDataHttpException.Create(500, 'Unable to retrieve QuickBooks customers: ' + E.Message);
end;
end;
finally
iniFile.Free;
restClient.Free;
......@@ -2435,7 +2565,108 @@ begin
end;
end;
function TLookupService.GetQBItems: TJSONArray;
var
restClient: TRESTClient;
restRequest: TRESTRequest;
restResponse: TRESTResponse;
param: TRESTRequestParameter;
res: string;
jsValue: TJSONValue;
jsObj: TJSONObject;
ItemList: TJSONArray;
pair: TJSONPair;
ModifiedList: TJSONArray;
ParsedItem, Item: TJSONObject;
I: integer;
AccessToken, RefreshToken, CompanyID, Client, Secret, SQL, desc: string;
LastRefresh: TDateTime;
iniFile: TIniFile;
begin
Result := TJSONArray.Create;
iniFile := TIniFile.Create(ExtractFilePath(Application.ExeName) + 'kgOrdersServer.ini');
restClient := TRESTClient.Create(nil);
restRequest := TRESTRequest.Create(nil);
restResponse := TRESTResponse.Create(nil);
restRequest.Client := restClient;
restRequest.Response := restResponse;
if iniFile.ReadString('Quickbooks', 'LastRefresh', '') = '' then
LastRefresh := 0
else
LastRefresh := StrToDateTime(iniFile.ReadString('Quickbooks', 'LastRefresh', ''));
if MinutesBetween(Now, LastRefresh) > 58 then
RefreshAccessToken();
Client := iniFile.ReadString('Quickbooks', 'ClientID', '');
Secret := iniFile.ReadString('Quickbooks', 'ClientSecret', '');
CompanyID := iniFile.ReadString('Quickbooks', 'CompanyID', '');
RefreshToken := iniFile.ReadString('Quickbooks', 'RefreshToken', '');
AccessToken := iniFile.ReadString('Quickbooks', 'AccessToken', '');
restClient.BaseURL := 'https://sandbox-quickbooks.api.intuit.com';
if MinutesBetween(Now, LastRefresh) > 58 then
begin
RefreshAccessToken();
end;
restRequest.Method := rmGET;
res := '/v3/company/' + companyID + '/query?query=select * from Item&minorversion=75';
restRequest.Resource := res;
param := restRequest.Params.AddItem;
param.Name := 'Authorization';
param.Kind := pkHTTPHEADER;
param.Options := param.Options + [TRESTRequestParameterOption.poDoNotEncode];
param.Value := 'Bearer ' + AccessToken;
restRequest.Execute;
//memo1.Lines.Add(restresponse.Content);
jsValue := restResponse.JSONValue;
jsObj := TJSONObject(jsValue);
//CustomerList := TJSONArray(restResponse.JSONValue);
//Memo1.Lines.Add( jsObj.Format(2) );
ItemList := TJSONArray( TJSONObject( jsObj.GetValue('QueryResponse') ).GetValue('Item'));
for I := 0 to ItemList.Count - 1 do
begin
Item := ItemList.Items[I] as TJSONObject;
ParsedItem := TJSONObject.Create;
SQL := 'select qb_items_id from qb_items where qb_item_name = ' + quotedStr(Item.GetValue<string>('Name'));
doQuery(ordersDB.UniQuery1, SQL);
ParsedItem.AddPair('qb_items_id', ordersDB.UniQuery1.FieldByName('qb_items_id').AsString);
ParsedItem.AddPair('qb_item_name', item.GetValue<string>('Name'));
if item.TryGetValue<string>('Description', desc) then
ParsedItem.AddPair('item_desc', desc)
else
ParsedItem.AddPair('item_desc', 'N/A');
ParsedItem.AddPair('status', item.GetValue<string>('Active'));
ParsedItem.AddPair('qb_items_qb_id', item.GetValue<string>('Id'));
Result.AddElement(ParsedItem);
end;
// Load customer info
restClient.Free;
restRequest.Free;
restResponse.Free;
iniFile.Free
end;
procedure TLookupService.AddAddrBlock(prefix: string; AddrJSON: TJSONObject);
// the point of this function would be to save space in import QB Customer
begin
//TODO
end;
......@@ -2522,6 +2753,7 @@ begin
end;
end;
procedure TLookupService.SaveTokens(AccessToken, RefreshToken: string);
var
f: TStringList;
......@@ -2615,9 +2847,9 @@ begin
OrdersDB.UniQuery1.Post;
if mode = 'ADD' then
msg := 'Success:Customer Successfully Added'
msg := 'Success: Customer Successfully Added'
else
msg := 'Success:Customer Successfully Edited';
msg := 'Success: Customer Successfully Edited';
Result := TJSONObject.Create;
Result.AddPair('status', msg);
......
......@@ -16,7 +16,7 @@ object FMain: TFMain
597)
TextHeight = 13
object memoInfo: TMemo
Left = 8
Left = 12
Top = 44
Width = 753
Height = 549
......
......@@ -2,8 +2,8 @@ object fQB: TfQB
Left = 0
Top = 0
Caption = 'fQB'
ClientHeight = 711
ClientWidth = 962
ClientHeight = 661
ClientWidth = 982
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
......@@ -13,57 +13,118 @@ object fQB: TfQB
OnCreate = FormCreate
OnDestroy = FormDestroy
TextHeight = 15
object Memo1: TMemo
object Splitter1: TSplitter
Left = 0
Top = 76
Width = 962
Height = 260
Top = 472
Width = 982
Height = 6
Cursor = crVSplit
Align = alBottom
Lines.Strings = (
'Memo1')
ScrollBars = ssVertical
end
object Splitter2: TSplitter
Left = 0
Top = 281
Width = 982
Height = 3
Cursor = crVSplit
Align = alBottom
ExplicitTop = 0
ExplicitWidth = 284
end
object Button2: TButton
Left = 4
Top = 32
Width = 111
Height = 25
Caption = 'Get QB Customers'
TabOrder = 0
OnClick = Button2Click
end
object Button1: TButton
Left = 42
Top = 18
Width = 87
object Button3: TButton
Left = 121
Top = 5
Width = 139
Height = 25
Caption = 'Company Info'
Caption = 'Get Customer By ID'
TabOrder = 1
OnClick = Button1Click
OnClick = Button3Click
end
object Memo2: TMemo
object Button4: TButton
Left = 266
Top = 5
Width = 95
Height = 25
Caption = 'Add Estimate'
TabOrder = 2
OnClick = Button4Click
end
object Button5: TButton
Left = 367
Top = 5
Width = 169
Height = 25
Caption = 'Show Customers with Orders'
TabOrder = 3
OnClick = Button5Click
end
object Memo1: TMemo
Left = 0
Top = 336
Width = 962
Height = 196
Top = 63
Width = 982
Height = 218
Align = alBottom
Lines.Strings = (
'')
ScrollBars = ssVertical
TabOrder = 2
TabOrder = 4
end
object Button2: TButton
Left = 135
Top = 22
Width = 87
object Button6: TButton
Left = 538
Top = 5
Width = 108
Height = 25
Caption = 'Get Customers'
TabOrder = 3
OnClick = Button2Click
Caption = 'Match Customers'
TabOrder = 5
OnClick = Button6Click
end
object asgData: TAdvStringGrid
object Button7: TButton
Left = 652
Top = 5
Width = 186
Height = 25
Caption = 'Show Customers without Orders'
TabOrder = 6
OnClick = Button7Click
end
object Button1: TButton
Left = 4
Top = 5
Width = 111
Height = 25
Caption = 'Get KG Customers'
TabOrder = 7
OnClick = Button1Click
end
object Panel1: TPanel
Left = 0
Top = 532
Width = 962
Height = 179
Top = 478
Width = 982
Height = 183
Align = alBottom
Caption = 'Panel1'
TabOrder = 8
OnResize = Panel1Resize
object asgData2: TAdvStringGrid
Left = 0
Top = 0
Width = 982
Height = 183
DrawingStyle = gdsClassic
FixedColor = clWhite
TabOrder = 4
TabOrder = 0
GridLineColor = 13948116
GridFixedLineColor = 11250603
OnClickCell = asgData2ClickCell
ActiveCellFont.Charset = DEFAULT_CHARSET
ActiveCellFont.Color = 4474440
ActiveCellFont.Height = -12
......@@ -178,7 +239,7 @@ object fQB: TfQB
SortSettings.HeaderColorTo = clWhite
SortSettings.HeaderMirrorColor = clWhite
SortSettings.HeaderMirrorColorTo = clWhite
Version = '9.1.4.1'
Version = '9.1.4.5'
ColWidths = (
64
64
......@@ -197,39 +258,213 @@ object fQB: TfQB
22
22)
end
object Button3: TButton
Left = 228
Top = 22
Width = 139
end
object Panel2: TPanel
Left = 0
Top = 284
Width = 982
Height = 188
Align = alBottom
Caption = 'Panel2'
TabOrder = 9
OnResize = Panel2Resize
object asgData: TAdvStringGrid
Left = 1
Top = 1
Width = 980
Height = 186
Align = alBottom
DrawingStyle = gdsClassic
FixedColor = clWhite
TabOrder = 0
GridLineColor = 13948116
GridFixedLineColor = 11250603
OnClickCell = asgDataClickCell
ActiveCellFont.Charset = DEFAULT_CHARSET
ActiveCellFont.Color = 4474440
ActiveCellFont.Height = -12
ActiveCellFont.Name = 'Segoe UI'
ActiveCellFont.Style = [fsBold]
ActiveCellColor = 11565130
ActiveCellColorTo = 11565130
BorderColor = 11250603
ControlLook.FixedGradientFrom = clWhite
ControlLook.FixedGradientTo = clWhite
ControlLook.FixedGradientHoverFrom = clGray
ControlLook.FixedGradientHoverTo = clWhite
ControlLook.FixedGradientHoverMirrorFrom = clWhite
ControlLook.FixedGradientHoverMirrorTo = clWhite
ControlLook.FixedGradientHoverBorder = 11645361
ControlLook.FixedGradientDownFrom = clWhite
ControlLook.FixedGradientDownTo = clWhite
ControlLook.FixedGradientDownMirrorFrom = clWhite
ControlLook.FixedGradientDownMirrorTo = clWhite
ControlLook.FixedGradientDownBorder = 11250603
ControlLook.DropDownHeader.Font.Charset = DEFAULT_CHARSET
ControlLook.DropDownHeader.Font.Color = clWindowText
ControlLook.DropDownHeader.Font.Height = -11
ControlLook.DropDownHeader.Font.Name = 'Segoe UI'
ControlLook.DropDownHeader.Font.Style = []
ControlLook.DropDownHeader.Visible = True
ControlLook.DropDownHeader.Buttons = <>
ControlLook.DropDownFooter.Font.Charset = DEFAULT_CHARSET
ControlLook.DropDownFooter.Font.Color = clWindowText
ControlLook.DropDownFooter.Font.Height = -11
ControlLook.DropDownFooter.Font.Name = 'Segoe UI'
ControlLook.DropDownFooter.Font.Style = []
ControlLook.DropDownFooter.Visible = True
ControlLook.DropDownFooter.Buttons = <>
ControlLook.ToggleSwitch.BackgroundBorderWidth = 1.000000000000000000
ControlLook.ToggleSwitch.ButtonBorderWidth = 1.000000000000000000
ControlLook.ToggleSwitch.CaptionFont.Charset = DEFAULT_CHARSET
ControlLook.ToggleSwitch.CaptionFont.Color = clWindowText
ControlLook.ToggleSwitch.CaptionFont.Height = -12
ControlLook.ToggleSwitch.CaptionFont.Name = 'Segoe UI'
ControlLook.ToggleSwitch.CaptionFont.Style = []
ControlLook.ToggleSwitch.Shadow = False
Filter = <>
FilterDropDown.Font.Charset = DEFAULT_CHARSET
FilterDropDown.Font.Color = clWindowText
FilterDropDown.Font.Height = -12
FilterDropDown.Font.Name = 'Segoe UI'
FilterDropDown.Font.Style = []
FilterDropDown.TextChecked = 'Checked'
FilterDropDown.TextUnChecked = 'Unchecked'
FilterDropDownClear = '(All)'
FilterEdit.TypeNames.Strings = (
'Starts with'
'Ends with'
'Contains'
'Not contains'
'Equal'
'Not equal'
'Larger than'
'Smaller than'
'Clear')
FixedRowHeight = 22
FixedFont.Charset = DEFAULT_CHARSET
FixedFont.Color = 3881787
FixedFont.Height = -11
FixedFont.Name = 'Segoe UI'
FixedFont.Style = [fsBold]
FloatFormat = '%.2f'
HoverButtons.Buttons = <>
HTMLSettings.ImageFolder = 'images'
HTMLSettings.ImageBaseName = 'img'
Look = glCustom
PrintSettings.DateFormat = 'dd/mm/yyyy'
PrintSettings.Font.Charset = DEFAULT_CHARSET
PrintSettings.Font.Color = clWindowText
PrintSettings.Font.Height = -12
PrintSettings.Font.Name = 'Segoe UI'
PrintSettings.Font.Style = []
PrintSettings.FixedFont.Charset = DEFAULT_CHARSET
PrintSettings.FixedFont.Color = clWindowText
PrintSettings.FixedFont.Height = -12
PrintSettings.FixedFont.Name = 'Segoe UI'
PrintSettings.FixedFont.Style = []
PrintSettings.HeaderFont.Charset = DEFAULT_CHARSET
PrintSettings.HeaderFont.Color = clWindowText
PrintSettings.HeaderFont.Height = -12
PrintSettings.HeaderFont.Name = 'Segoe UI'
PrintSettings.HeaderFont.Style = []
PrintSettings.FooterFont.Charset = DEFAULT_CHARSET
PrintSettings.FooterFont.Color = clWindowText
PrintSettings.FooterFont.Height = -12
PrintSettings.FooterFont.Name = 'Segoe UI'
PrintSettings.FooterFont.Style = []
PrintSettings.PageNumSep = '/'
SearchFooter.ColorTo = clNone
SearchFooter.FindNextCaption = 'Find &next'
SearchFooter.FindPrevCaption = 'Find &previous'
SearchFooter.Font.Charset = DEFAULT_CHARSET
SearchFooter.Font.Color = clWindowText
SearchFooter.Font.Height = -12
SearchFooter.Font.Name = 'Segoe UI'
SearchFooter.Font.Style = []
SearchFooter.HighLightCaption = 'Highlight'
SearchFooter.HintClose = 'Close'
SearchFooter.HintFindNext = 'Find next occurrence'
SearchFooter.HintFindPrev = 'Find previous occurrence'
SearchFooter.HintHighlight = 'Highlight occurrences'
SearchFooter.MatchCaseCaption = 'Match case'
SearchFooter.ResultFormat = '(%d of %d)'
SelectionColor = 13744549
SortSettings.HeaderColor = clWhite
SortSettings.HeaderColorTo = clWhite
SortSettings.HeaderMirrorColor = clWhite
SortSettings.HeaderMirrorColorTo = clWhite
Version = '9.1.4.5'
ColWidths = (
64
64
64
64
64)
RowHeights = (
22
22
22
22
22
22
22
22
22
22)
end
end
object Button8: TButton
Left = 844
Top = 5
Width = 75
Height = 25
Caption = 'Get Customer By ID'
TabOrder = 5
OnClick = Button3Click
Caption = 'Get Items'
TabOrder = 10
OnClick = Button8Click
end
object Button4: TButton
Left = 373
Top = 22
object Button9: TButton
Left = 121
Top = 32
Width = 95
Height = 25
Caption = 'Add Estimate'
TabOrder = 6
OnClick = Button4Click
end
object Button5: TButton
Left = 472
Top = 22
Width = 169
Caption = 'Get Estimate'
TabOrder = 11
OnClick = Button9Click
end
object Button10: TButton
Left = 222
Top = 32
Width = 75
Height = 25
Caption = 'Show Customers with Orders'
TabOrder = 7
OnClick = Button5Click
Caption = 'Update QB ID'
TabOrder = 12
OnClick = Button10Click
end
object Button11: TButton
Left = 316
Top = 32
Width = 113
Height = 25
Caption = 'update QB Items'
TabOrder = 13
OnClick = Button11Click
end
object Button12: TButton
Left = 435
Top = 32
Width = 190
Height = 25
Caption = 'Delete Customers without orders'
TabOrder = 14
OnClick = Button12Click
end
object uq: TUniQuery
Connection = ApiDatabase.ucKG
SQL.Strings = (
'select * from web_plate_orders')
Left = 743
Top = 36
Left = 851
Top = 182
object uqORDER_ID: TIntegerField
FieldName = 'ORDER_ID'
Required = True
......
unit qbAPI;
unit qbAPI;
interface
......@@ -16,11 +16,7 @@ uses
type
TfQB = class(TForm)
Memo1: TMemo;
Button1: TButton;
Memo2: TMemo;
Button2: TButton;
asgData: TAdvStringGrid;
Button3: TButton;
Button4: TButton;
Button5: TButton;
......@@ -110,6 +106,21 @@ type
uqupc_distortion_percent: TStringField;
uqupc_distortion_amount: TStringField;
uqstaff_fields_art_location: TStringField;
Memo1: TMemo;
Button6: TButton;
Button7: TButton;
Button1: TButton;
Panel1: TPanel;
asgData2: TAdvStringGrid;
Panel2: TPanel;
Splitter1: TSplitter;
asgData: TAdvStringGrid;
Splitter2: TSplitter;
Button8: TButton;
Button9: TButton;
Button10: TButton;
Button11: TButton;
Button12: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Button2Click(Sender: TObject);
......@@ -117,6 +128,17 @@ type
procedure Button4Click(Sender: TObject);
procedure Button5Click(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button6Click(Sender: TObject);
procedure Button7Click(Sender: TObject);
procedure asgData2ClickCell(Sender: TObject; ARow, ACol: Integer);
procedure asgDataClickCell(Sender: TObject; ARow, ACol: Integer);
procedure Panel1Resize(Sender: TObject);
procedure Panel2Resize(Sender: TObject);
procedure Button8Click(Sender: TObject);
procedure Button9Click(Sender: TObject);
procedure Button10Click(Sender: TObject);
procedure Button11Click(Sender: TObject);
procedure Button12Click(Sender: TObject);
private
{ Private declarations }
strict private
......@@ -126,14 +148,23 @@ type
var
AccessToken,RefreshToken,CompanyID,Client,Secret: string;
LastRefresh: TDateTime;
ID, QB_ID: string;
public
{ Public declarations }
procedure findMatches(CustomerList: TJSONArray; JSONfield, DBField: string);
procedure getCompanyInfo();
procedure LoadJsonArray(jaData: TJSONArray);
procedure LoadJsonArray2(jaData: TJSONArray);
function RefreshAccessToken(): string;
procedure ConfigureSSL(IOHandler: TIdSSLIOHandlerSocketOpenSSL);
procedure SaveTokens(AccessToken, RefreshToken: string);
procedure getCustomers();
procedure addEstimate(orderInfo: string);
procedure getQBCustomers();
procedure ShowDeleteConfirm(msg: string);
procedure ShowLinkConfirm(msg: string);
procedure DeleteCustomers();
procedure LinkCustomers();
end;
var
......@@ -142,13 +173,290 @@ var
implementation
uses
Common.Logging, uLibrary;
Common.Logging, uLibrary, Lookup.Service, Lookup.ServiceImpl;
{$R *.dfm}
procedure TfQB.asgData2ClickCell(Sender: TObject; ARow, ACol: Integer);
var
point, origin: TPoint;
begin
origin := TPoint.Create(1,1);
point := asgData.find(origin, asgData2.Cells[2, ARow], []);
if point.Y = -1 then
point.Y := 0;
if point.X = -1 then
point.X := 0;
asgData.Row := point.Y;
asgData.Col := point.X;
if ( (point.X <> 0) and (point.Y <> 0) ) then
begin
QB_ID := asgData.Cells[1, asgData.Row];
ID := asgData2.Cells[1, asgData2.Row];
end
else
ID := asgData2.Cells[1, asgData2.Row];
end;
procedure TfQB.asgDataClickCell(Sender: TObject; ARow, ACol: Integer);
var
point, origin: TPoint;
begin
QB_ID := asgData.Cells[1, asgData.Row];
end;
procedure TfQB.Button10Click(Sender: TObject);
var
msg: string;
begin
if( ( QB_ID = '' ) or ( ID = '' ) ) then
begin
Memo1.Lines.Add('Please select a Quickbooks Customer and a KG Orders Customer');
Memo1.Lines.Add('Current QB ID: ' + QB_ID);
Memo1.Lines.Add('Current KG Orders ID: ' + ID);
end
else
begin
msg := 'Are you sure you want to link QB ID: ' + QB_ID + ' with KG Orders ID: ' + ID;
ShowLinkConfirm(msg);
end;
end;
procedure TfQB.LinkCustomers();
var
sql: string;
begin
sql := 'select QB_LIST_ID from customers where CUSTOMER_ID = ' + ID;
doQuery(ordersDB.UniQuery1, SQL);
ordersDB.UniQuery1.Edit;
ordersDB.UniQuery1.FieldByName('QB_LIST_ID').AsString := QB_ID;
ordersDB.UniQuery1.Post;
getCustomers();
QB_ID := '';
ID := '';
end;
procedure TfQB.ShowLinkConfirm(msg: string);
begin
if MessageDlg(msg, mtConfirmation, [mbYes, mbNo], 0) = mrYes then
begin
// User confirmed
LinkCustomers();
end
else
begin
// User canceled
ShowMessage('Cancelled.');
end;
end;
procedure TfQB.Button11Click(Sender: TObject);
var
restClient: TRESTClient;
restRequest: TRESTRequest;
restResponse: TRESTResponse;
param: TRESTRequestParameter;
res: string;
jsValue: TJSONValue;
jsObj: TJSONObject;
ItemList: TJSONArray;
pair: TJSONPair;
ModifiedList: TJSONArray;
ParsedCustomer, Item: TJSONObject;
I: integer;
BillAddr: TJSONObject;
ShipAddr: TJSONObject;
sql: string;
begin
restClient := TRESTClient.Create(nil);
restClient.BaseURL := 'https://sandbox-quickbooks.api.intuit.com';
restRequest := TRESTRequest.Create(nil);
restRequest.Client := restClient;
restResponse := TRESTResponse.Create(nil);
restRequest.Response := restResponse;
if MinutesBetween(Now, LastRefresh) > 58 then
begin
RefreshAccessToken();
end;
restRequest.Method := rmGET;
//res := '/v3/company/' + companyID + '/preferences';
res := '/v3/company/' + companyID + '/query?query=select * from Item&minorversion=75'; // '/customer/58';
restRequest.Resource := res;
param := restRequest.Params.AddItem;
param.Name := 'Authorization';
param.Kind := pkHTTPHEADER;
param.Options := param.Options + [TRESTRequestParameterOption.poDoNotEncode];
param.Value := 'Bearer ' + AccessToken;
restRequest.Execute;
//memo1.Lines.Add(restresponse.Content);
jsValue := restResponse.JSONValue;
jsObj := TJSONObject(jsValue);
//CustomerList := TJSONArray(restResponse.JSONValue);
Memo1.Lines.Add( jsObj.Format(2) );
ItemList := TJSONArray( TJSONObject( jsObj.GetValue('QueryResponse') ).GetValue('Item'));
for i := 0 to ItemList.Count - 1 do
begin
Item := ItemList.Items[i] as TJSONObject;
sql := 'select * from qb_items where qb_item_name = ' + quotedStr(Item.GetValue<string>('Name'));
doQuery(ordersDB.UniQuery1, sql);
if ( not ordersDB.UniQuery1.IsEmpty ) then
begin
ordersDB.UniQuery1.Edit;
ordersDB.uniquery1.FieldByName('qb_items_qb_id').AsString := Item.GetValue<string>('Id');
ordersDB.UniQuery1.Post;
end;
end;
// Load customer info
restClient.Free;
restRequest.Free;
restResponse.Free;
end;
procedure TfQB.Button12Click(Sender: TObject);
var
SQL: string;
cust_count, ship_count: string;
msg: string;
begin
SQL := 'select count(*) as cust_count from customers c ' +
' WHERE NOT EXISTS (SELECT 1 FROM corrugated_plate_orders cpo WHERE cpo.COMPANY_ID = c.CUSTOMER_ID) '+
'AND NOT EXISTS (SELECT 1 FROM web_plate_orders wpo WHERE wpo.COMPANY_ID = c.CUSTOMER_ID) ORDER BY c.SHORT_NAME';
DoQuery(ordersDB.UniQuery1, SQL);
cust_count := ordersDB.UniQuery1.FieldByName('cust_count').AsString;
SQL := 'select count(*) as ship_count from customers c join customers_ship cs on c.CUSTOMER_ID = cs.customer_id' +
' WHERE NOT EXISTS (SELECT 1 FROM corrugated_plate_orders cpo WHERE cpo.COMPANY_ID = c.CUSTOMER_ID) '+
'AND NOT EXISTS (SELECT 1 FROM web_plate_orders wpo WHERE wpo.COMPANY_ID = c.CUSTOMER_ID) ORDER BY c.SHORT_NAME';
DoQuery(ordersDB.UniQuery1, SQL);
ship_count := ordersDB.UniQuery1.FieldByName('ship_count').AsString;
msg := 'You will be deleting ' + cust_count + ' customers and their ' + ship_count + ' assoicated shipping addresses. Are you sure you want to continue?';
ShowDeleteConfirm(msg);
end;
procedure TfQB.DeleteCustomers();
var
SQL: string;
count: integer;
ModifiedList: TJSONArray;
Customer, ParsedCustomer: TJSONObject;
I: integer;
ship_count, cust_count: integer;
begin
Memo1.Lines.Add('Beginning to Delete Customers');
SQL := 'SELECT * FROM customers c ' +
'WHERE NOT EXISTS (SELECT 1 FROM corrugated_plate_orders cpo WHERE cpo.COMPANY_ID = c.CUSTOMER_ID) '+
'AND NOT EXISTS (SELECT 1 FROM web_plate_orders wpo WHERE wpo.COMPANY_ID = c.CUSTOMER_ID) ORDER BY c.SHORT_NAME';
doQuery(ordersDB.UniQuery1, SQL);
cust_count := 0;
ship_count := 0;
while( not ordersDB.UniQuery1.Eof ) do
begin
SQL := 'Select * from customers_ship where customer_id = ' + ordersDB.UniQuery1.FieldByName('CUSTOMER_ID').AsString;
doQuery(ordersDB.UniQuery2, SQL);
ordersDB.UniQuery2.First;
while ( not ordersDB.UniQuery2.Eof) do
begin
ordersDB.UniQuery2.Delete;
ship_count := ship_count + 1;
end;
cust_count := cust_count + 1;
ordersDB.UniQuery1.Delete;
end;
Memo1.Lines.Add('Customers deleted: ' + inttostr(cust_count));
memo1.Lines.Add('Shipping Addresses deleted: '+ inttostr(ship_count));
end;
procedure TfQB.ShowDeleteConfirm(msg: string);
begin
if MessageDlg(msg, mtConfirmation, [mbYes, mbNo], 0) = mrYes then
begin
// User confirmed
DeleteCustomers();
end
else
begin
// User canceled
ShowMessage('Cancelled.');
end;
end;
procedure TfQB.Button1Click(Sender: TObject);
begin
getCompanyInfo();
getCustomers();
end;
procedure TfQB.getCustomers();
var
SQL: string;
count: integer;
ModifiedList: TJSONArray;
Customer, ParsedCustomer: TJSONObject;
I: integer;
begin
SQL := 'SELECT * FROM customers c';
doQuery(ordersDB.UniQuery1, SQL);
ModifiedList := TJSONArray.Create;
while not ordersDB.UniQuery1.Eof do
begin
ParsedCustomer := TJSONObject.Create;
//sql := 'select CUSTOMER_ID from customers where QB_LIST_ID = ' + Customer.GetValue<string>('Id');
//doQuery(ordersDB.UniQuery1, SQL);
try
//ParsedCustomer.AddPair('In KGOrders', not(ordersDB.UniQuery1.IsEmpty));
ParsedCustomer.AddPair('Id', ordersDB.UniQuery1.FieldByName('CUSTOMER_ID').AsString);
ParsedCustomer.AddPair('CompanyName', ordersDB.UniQuery1.FieldByName('NAME').AsString);
ParsedCustomer.AddPair('BillAddrCity', ordersDB.UniQuery1.FieldByName('BILL_CITY').AsString);
ParsedCustomer.AddPair('BillAddrLine1', ordersDB.UniQuery1.FieldByName('BILL_ADDRESS').AsString);
ParsedCustomer.AddPair('BillAddrState', ordersDB.UniQuery1.FieldByName('BILL_STATE').AsString);
ParsedCustomer.AddPair('BillAddrZip', ordersDB.UniQuery1.FieldByName('BILL_ZIP').AsString);
ParsedCustomer.AddPair('BillAddr', ordersDB.UniQuery1.FieldByName('BILL_ADDRESS_BLOCK').AsString);
ParsedCustomer.AddPair('QB_ID', TJSONString.Create(ordersDB.UniQuery1.FieldByName('QB_LIST_ID').AsString));
ModifiedList.AddElement(ParsedCustomer);
ordersDB.UniQuery1.Next;
except
ParsedCustomer.Free;
raise;
end;
end;
LoadJSONArray2(ModifiedList);
end;
procedure TfQB.SaveTokens(AccessToken, RefreshToken: string);
......@@ -174,10 +482,9 @@ begin
f.Free;
end;
procedure TfQB.Button2Click(Sender: TObject);
begin
GetCustomers();
GetQBCustomers();
end;
procedure TfQB.Button3Click(Sender: TObject);
......@@ -226,7 +533,6 @@ begin
jsValue := restResponse.JSONValue;
jsObj := TJSONObject(jsValue);
//Memo2.Lines.Add(res);
Memo1.Lines.Add( jsObj.Format(2) );
// CustomerList := TJSONArray( TJSONObject( jsObj.GetValue('QueryResponse') ).GetValue('Customer')) ;
......@@ -241,19 +547,172 @@ end;
procedure TfQB.Button4Click(Sender: TObject);
var
orderJSON: TJSONObject;
begin
orderJSON := TJSONObject.Create;
orderJSON.AddPair('ORDER_ID', '19814');
addEstimate(orderJSON.ToString);
end;
procedure tfQb.addEstimate(orderInfo: string);
var
restClient: TRESTClient;
restRequest: TRESTRequest;
restResponse: TRESTResponse;
param: TRESTRequestParameter;
res: string;
i: integer;
jsValue: TJSONValue;
Customer: TJSONValue;
jsObj: TJSONObject;
CustomerList: TJSONArray;
pair: TJSONPair;
estimateJSON: TJSONObject;
SQL: string;
estimate: TEstimate;
CustomerRef: TRef;
CustomerRefJSON: TJSONObject;
Lines: TArray<string>;
BillAddr: TAddress;
BillAddrJSON: TJSONObject;
CustomField:TJSONObject;
CustomFields: TJSONArray;
ShipAddr: TAddress;
ShipAddrJSON: TJSONObject;
Items: TArray<TLine>;
ItemRef: TRef;
SalesItemLineDetail: TSalesItemLineDetail;
LineArray: TJSONArray;
LineObj, DetailObj, ItemRefObj: TJSONObject;
TaxCodeRef: TJSONObject;
TxnTaxCodeRef: TJSONObject;
TxnTaxDetail: TJSONObject;
JSONData: TJSONObject;
ORDER_ID: string;
table: string;
ShipMethodRef: TJSONObject;
begin
///v3/company/<realmID>/estimate
BillAddrJSON := TJSONObject.Create;
ShipAddrJSON := TJSONObject.Create;
EstimateJSON := TJSONObject.Create;
CustomerRefJSON := TJSONObject.Create;
CustomFields := TJSONArray.Create;
CustomField := TJSONObject.Create;
LineArray := TJSONArray.Create;
LineObj := TJSONObject.Create;
DetailObj := TJSONObject.Create;
ItemRefObj := TJSONObject.Create;
TaxCodeRef := TJSONObject.Create;
TxnTaxCodeRef := TJSONObject.Create;
TxnTaxDetail := TJSONObject.Create;
JSONData := TJSONObject.ParseJSONValue(orderInfo) as TJSONObject;
ORDER_ID := JSONData.GetValue<string>('ORDER_ID');
// add logic to figure out what type of order it is
SQL := 'select * from orders where ORDER_ID = ' + ORDER_ID;
doQuery(ordersDB.UniQuery1, SQL);
if ordersDB.UniQuery1.FieldByName('ORDER_TYPE').AsString = 'corrugated_plate' then
begin
table := 'corrugated_plate_orders';
end
else if ordersDB.UniQuery1.FieldByName('ORDER_TYPE').AsString = 'web_plate' then
begin
table := 'web_plate_orders';
end
else
table := 'cutting_die_orders';
SQL := 'select * from ' + table + ' cpo join customers c on cpo.COMPANY_ID = c.CUSTOMER_ID join customers_ship cs on cpo.staff_fields_ship_to = cs.ship_block JOIN qb_items ON cpo.staff_fields_quickbooks_item = qb_items.qb_item_name where ORDER_ID = ' + ORDER_ID;
doQuery(ordersDB.UniQuery1, SQL);
estimateJSON.AddPair('TxnDate', ordersDB.UniQuery1.FieldByName('staff_fields_order_date').AsString);
// Update the Quickbooks list ID in the database
// CustomerRef.value :=
CustomerRefJSON := TJSONObject.Create;
CustomerRefJSON.AddPair('value', ordersDB.UniQuery1.FieldByName('QB_LIST_ID').AsString);
//CustomerRef.value := '59'
;
estimateJSON.AddPair('CustomerRef', CustomerRefJSON);
Lines := ordersDB.UniQuery1.FieldByName('staff_fields_invoice_to').AsString.Split([sLineBreak]);
for i := 0 to Length(Lines) - 2 do
begin
case i of
0: BillAddrJSON.AddPair('Line1', Lines[0]);
1: BillAddrJSON.AddPair('Line2', Lines[1]);
2: BillAddrJSON.AddPair('Line3', Lines[2]);
3: BillAddrJSON.AddPair('Line4', Lines[3]);
4: BillAddrJSON.AddPair('Line5', Lines[4]);
end;
end;
BillAddrJSON.AddPair('City', ordersDB.UniQuery1.FieldByName('BILL_CITY').AsString);
BillAddrJSON.AddPair('CountrySubDivisionCode', ordersDB.UniQuery1.FieldByName('BILL_STATE').AsString);
BillAddrJSON.AddPair('PostalCode', ordersDB.UniQuery1.FieldByName('BILL_ZIP').AsString);
estimateJSON.AddPair('BillAddr', BillAddrJSON);
CustomField.AddPair('DefinitionId', '1');
CustomField.AddPair('Name', 'CUSTID');
CustomField.AddPair('Type', 'StringType');
CustomField.AddPair('StringValue', ordersDB.UniQuery1.FieldByName('SHORT_NAME').AsString);
CustomFields.AddElement(CustomField);
EstimateJSON.AddPair('CustomField', CustomFields);
Lines := ordersDB.UniQuery1.FieldByName('ship_block').AsString.Split([sLineBreak]);
for i := 0 to Length(Lines) - 2 do
begin
case i of
0: ShipAddrJSON.AddPair('Line1', Lines[0]);
1: ShipAddrJSON.AddPair('Line2', Lines[1]);
2: ShipAddrJSON.AddPair('Line3', Lines[2]);
3: ShipAddrJSON.AddPair('Line4', Lines[3]);
4: ShipAddrJSON.AddPair('Line5', Lines[4]);
end;
end;
ShipAddrJSON.AddPair('City', ordersDB.UniQuery1.FieldByName('city').AsString);
ShipAddrJSON.AddPair('CountrySubDivisionCode', ordersDB.UniQuery1.FieldByName('state').AsString);
ShipAddrJSON.AddPair('PostalCode', ordersDB.UniQuery1.FieldByName('zip').AsString);
estimateJSON.AddPair('ShipAddr', ShipAddrJSON);
// 🔹 Line object representing one line item
LineObj := TJSONObject.Create;
if ( table = 'corrugated_plate_orders') or (table = 'cutting_die_orders' ) then
begin
if ordersDB.UniQuery1.FieldByName('general_special_instructions').AsString <> '' then
LineObj.AddPair('Description', ordersDB.UniQuery1.FieldByName('item_desc').AsString + ' - ' + ordersDB.UniQuery1.FieldByName('general_special_instructions').AsString);
end;
memo1.Lines.Add(ordersDB.UniQuery1.FieldByName('staff_fields_price').AsString);
memo1.Lines.Add(ordersDB.UniQuery1.FieldByName('staff_fields_quantity').AsString);
LineObj.AddPair('Amount', TJSONNumber.Create(ordersDB.UniQuery1.FieldByName('staff_fields_price').AsFloat));
memo1.Lines.Add(ordersDB.UniQuery1.FieldByName('staff_fields_price').AsString);
LineObj.AddPair('DetailType', 'SalesItemLineDetail');
ItemRefObj.AddPair('value', ordersDB.UniQuery1.FieldByName('qb_items_qb_id').AsString);
DetailObj.AddPair('ItemRef', ItemRefObj);
DetailObj.AddPair('Qty', TJSONNumber.Create(ordersDB.UniQuery1.FieldByName('staff_fields_quantity').AsFloat));
DetailObj.AddPair('UnitPrice', TJSONNumber.Create(ordersDB.UniQuery1.FieldByName('staff_fields_price').AsFloat));
LineObj.AddPair('SalesItemLineDetail', DetailObj);
LineArray.AddElement(LineObj);
EstimateJSON.AddPair('Line', LineArray);
if ordersDB.UniQuery1.FieldByName('staff_fields_ship_date').AsString <> '' then
begin
estimateJSON.AddPair('ShipDate', ordersDB.UniQuery1.FieldByName('staff_fields_ship_date').AsString)
end;
restClient := TRESTClient.Create(nil);
restClient.BaseURL := 'https://sandbox-quickbooks.api.intuit.com';
......@@ -279,6 +738,10 @@ begin
param.Options := param.Options + [TRESTRequestParameterOption.poDoNotEncode];
param.Value := 'Bearer ' + AccessToken;
Memo1.Lines.Add( estimateJSON.Format(2) );
restRequest.AddBody(estimateJSON.ToJSON, TRESTContentType.ctAPPLICATION_JSON);
restRequest.Execute;
//memo1.Lines.Add(restresponse.Content);
......@@ -286,7 +749,6 @@ begin
jsValue := restResponse.JSONValue;
jsObj := TJSONObject(jsValue);
//Memo2.Lines.Add(res);
Memo1.Lines.Add( jsObj.Format(2) );
//CustomerList := TJSONArray(restResponse.JSONValue);
......@@ -303,24 +765,48 @@ procedure TfQB.Button5Click(Sender: TObject);
var
SQL: string;
count: integer;
ModifiedList: TJSONArray;
Customer, ParsedCustomer: TJSONObject;
I: integer;
begin
SQL := 'SELECT c.CUSTOMER_ID, c.SHORT_NAME, c.NAME FROM customers c ' +
SQL := 'SELECT * FROM customers c ' +
'WHERE EXISTS (SELECT 1 FROM corrugated_plate_orders cpo WHERE cpo.COMPANY_ID = c.CUSTOMER_ID) '+
'OR EXISTS (SELECT 1 FROM web_plate_orders wpo WHERE wpo.COMPANY_ID = c.CUSTOMER_ID) ORDER BY c.SHORT_NAME';
doQuery(ordersDB.UniQuery1, SQL);
ModifiedList := TJSONArray.Create;
while not ordersDB.UniQuery1.Eof do
begin
Memo2.Lines.Add(ordersDB.UniQuery1.FieldByName('CUSTOMER_ID').AsString + ', ' + ordersDB.UniQuery1.FieldByName('SHORT_NAME').AsString + ', ' + ordersDB.UniQuery1.FieldByName('NAME').AsString);
OrdersDB.UniQuery1.Next;
count := count + 1;
ParsedCustomer := TJSONObject.Create;
//sql := 'select CUSTOMER_ID from customers where QB_LIST_ID = ' + Customer.GetValue<string>('Id');
//doQuery(ordersDB.UniQuery1, SQL);
try
//ParsedCustomer.AddPair('In KGOrders', not(ordersDB.UniQuery1.IsEmpty));
ParsedCustomer.AddPair('Id', ordersDB.UniQuery1.FieldByName('CUSTOMER_ID').AsString);
ParsedCustomer.AddPair('CompanyName', ordersDB.UniQuery1.FieldByName('NAME').AsString);
ParsedCustomer.AddPair('BillAddrCity', ordersDB.UniQuery1.FieldByName('BILL_CITY').AsString);
ParsedCustomer.AddPair('BillAddrLine1', ordersDB.UniQuery1.FieldByName('BILL_ADDRESS').AsString);
ParsedCustomer.AddPair('BillAddrState', ordersDB.UniQuery1.FieldByName('BILL_STATE').AsString);
ParsedCustomer.AddPair('BillAddrZip', ordersDB.UniQuery1.FieldByName('BILL_ZIP').AsString);
ParsedCustomer.AddPair('BillAddr', ordersDB.UniQuery1.FieldByName('BILL_ADDRESS_BLOCK').AsString);
ModifiedList.AddElement(ParsedCustomer);
ordersDB.UniQuery1.Next;
except
ParsedCustomer.Free;
raise;
end;
end;
Memo2.Lines.Add('Showing ' + IntToStr(count) + ' entries');
LoadJSONArray2(ModifiedList);
end;
procedure TfQB.getCustomers();
procedure TfQB.Button6Click(Sender: TObject);
var
restClient: TRESTClient;
restRequest: TRESTRequest;
......@@ -336,6 +822,7 @@ var
I: integer;
BillAddr: TJSONObject;
ShipAddr: TJSONObject;
SQL: string;
begin
restClient := TRESTClient.Create(nil);
restClient.BaseURL := 'https://sandbox-quickbooks.api.intuit.com';
......@@ -372,18 +859,321 @@ begin
jsValue := restResponse.JSONValue;
jsObj := TJSONObject(jsValue);
Memo2.Lines.Add(res);
Memo2.Lines.Add( jsObj.Format(2) );
//CustomerList := TJSONArray(restResponse.JSONValue);
CustomerList := TJSONArray( TJSONObject( jsObj.GetValue('QueryResponse') ).GetValue('Customer')) ;
LoadJSONArray( CustomerList );
//LoadJSONArray( CustomerList );
findMatches(CustomerList, 'DisplayName', 'Name');
//findMatches(CustomerList, 'BillAddrLine1', 'BILL_ADDRESS');
//findMatches(CustomerList, 'BillAddrCity', 'BILL_CITY');
//findMatches(CustomerList, 'BillAddrState', 'BILL_STATE');
//findMatches(CustomerList, 'BillAddrZip', 'BILL_ZIP');
end;
procedure TfQB.Button7Click(Sender: TObject);
var
SQL: string;
count: integer;
ModifiedList: TJSONArray;
Customer, ParsedCustomer: TJSONObject;
I: integer;
begin
SQL := 'SELECT * FROM customers c ' +
'WHERE NOT EXISTS (SELECT 1 FROM corrugated_plate_orders cpo WHERE cpo.COMPANY_ID = c.CUSTOMER_ID) '+
'AND NOT EXISTS (SELECT 1 FROM web_plate_orders wpo WHERE wpo.COMPANY_ID = c.CUSTOMER_ID) ORDER BY c.SHORT_NAME';
doQuery(ordersDB.UniQuery1, SQL);
ModifiedList := TJSONArray.Create;
while not ordersDB.UniQuery1.Eof do
begin
ParsedCustomer := TJSONObject.Create;
//sql := 'select CUSTOMER_ID from customers where QB_LIST_ID = ' + Customer.GetValue<string>('Id');
//doQuery(ordersDB.UniQuery1, SQL);
try
//ParsedCustomer.AddPair('In KGOrders', not(ordersDB.UniQuery1.IsEmpty));
ParsedCustomer.AddPair('Id', ordersDB.UniQuery1.FieldByName('CUSTOMER_ID').AsString);
ParsedCustomer.AddPair('CompanyName', ordersDB.UniQuery1.FieldByName('NAME').AsString);
ParsedCustomer.AddPair('BillAddrCity', ordersDB.UniQuery1.FieldByName('BILL_CITY').AsString);
ParsedCustomer.AddPair('BillAddrLine1', ordersDB.UniQuery1.FieldByName('BILL_ADDRESS').AsString);
ParsedCustomer.AddPair('BillAddrState', ordersDB.UniQuery1.FieldByName('BILL_STATE').AsString);
ParsedCustomer.AddPair('BillAddrZip', ordersDB.UniQuery1.FieldByName('BILL_ZIP').AsString);
ParsedCustomer.AddPair('BillAddr', ordersDB.UniQuery1.FieldByName('BILL_ADDRESS_BLOCK').AsString);
ModifiedList.AddElement(ParsedCustomer);
ordersDB.UniQuery1.Next;
except
ParsedCustomer.Free;
raise;
end;
end;
LoadJSONArray2(ModifiedList);
end;
procedure TfQB.Button8Click(Sender: TObject);
var
restClient: TRESTClient;
restRequest: TRESTRequest;
restResponse: TRESTResponse;
param: TRESTRequestParameter;
res: string;
jsValue: TJSONValue;
jsObj: TJSONObject;
CustomerList: TJSONArray;
pair: TJSONPair;
ModifiedList: TJSONArray;
ParsedCustomer, Customer: TJSONObject;
I: integer;
BillAddr: TJSONObject;
ShipAddr: TJSONObject;
begin
restClient := TRESTClient.Create(nil);
restClient.BaseURL := 'https://sandbox-quickbooks.api.intuit.com';
restRequest := TRESTRequest.Create(nil);
restRequest.Client := restClient;
restResponse := TRESTResponse.Create(nil);
restRequest.Response := restResponse;
if MinutesBetween(Now, LastRefresh) > 58 then
begin
RefreshAccessToken();
end;
restRequest.Method := rmGET;
//res := '/v3/company/' + companyID + '/preferences';
res := '/v3/company/' + companyID + '/query?query=select * from Item&minorversion=75'; // '/customer/58';
restRequest.Resource := res;
param := restRequest.Params.AddItem;
param.Name := 'Authorization';
param.Kind := pkHTTPHEADER;
param.Options := param.Options + [TRESTRequestParameterOption.poDoNotEncode];
param.Value := 'Bearer ' + AccessToken;
restRequest.Execute;
//memo1.Lines.Add(restresponse.Content);
jsValue := restResponse.JSONValue;
jsObj := TJSONObject(jsValue);
//CustomerList := TJSONArray(restResponse.JSONValue);
Memo1.Lines.Add( jsObj.Format(2) );
CustomerList := TJSONArray( TJSONObject( jsObj.GetValue('QueryResponse') ).GetValue('Item'));
loadJSONArray(CustomerList);
// Load customer info
restClient.Free;
restRequest.Free;
restResponse.Free;
end;
procedure TfQB.Button9Click(Sender: TObject);
var
restClient: TRESTClient;
restRequest: TRESTRequest;
restResponse: TRESTResponse;
param: TRESTRequestParameter;
res: string;
jsValue: TJSONValue;
jsObj: TJSONObject;
CustomerList: TJSONArray;
pair: TJSONPair;
ModifiedList: TJSONArray;
ParsedCustomer, Customer: TJSONObject;
I: integer;
BillAddr: TJSONObject;
ShipAddr: TJSONObject;
begin
restClient := TRESTClient.Create(nil);
restClient.BaseURL := 'https://sandbox-quickbooks.api.intuit.com';
restRequest := TRESTRequest.Create(nil);
restRequest.Client := restClient;
restResponse := TRESTResponse.Create(nil);
restRequest.Response := restResponse;
if MinutesBetween(Now, LastRefresh) > 58 then
begin
RefreshAccessToken();
end;
restRequest.Method := rmGET;
//GET /v3/company/9341454243251288/query?query=<selectStatement>&minorversion=75
res := '/v3/company/' + companyID + '/query?query=select * from estimate where DocNumber = ' + quotedStr('1002') + '&minorversion=75';
restRequest.Resource := res;
param := restRequest.Params.AddItem;
param.Name := 'Authorization';
param.Kind := pkHTTPHEADER;
param.Options := param.Options + [TRESTRequestParameterOption.poDoNotEncode];
param.Value := 'Bearer ' + AccessToken;
restRequest.Execute;
memo1.Lines.Add(restresponse.Content);
jsValue := restResponse.JSONValue;
jsObj := TJSONObject(jsValue);
Memo1.Lines.Add( jsObj.Format(2) );
restClient.Free;
restRequest.Free;
restResponse.Free;
end;
procedure TfQB.getQBCustomers();
var
restClient: TRESTClient;
restRequest: TRESTRequest;
restResponse: TRESTResponse;
param: TRESTRequestParameter;
res: string;
jsValue: TJSONValue;
jsObj: TJSONObject;
CustomerList: TJSONArray;
pair: TJSONPair;
ModifiedList: TJSONArray;
ParsedCustomer, Customer: TJSONObject;
I: integer;
BillAddr: TJSONObject;
ShipAddr: TJSONObject;
begin
restClient := TRESTClient.Create(nil);
restClient.BaseURL := 'https://sandbox-quickbooks.api.intuit.com';
restRequest := TRESTRequest.Create(nil);
restRequest.Client := restClient;
restResponse := TRESTResponse.Create(nil);
restRequest.Response := restResponse;
if MinutesBetween(Now, LastRefresh) > 58 then
begin
RefreshAccessToken();
end;
restRequest.Method := rmGET;
//res := '/v3/company/' + companyID + '/preferences';
res := '/v3/company/' + companyID + '/query?query=select * from Customer&minorversion=75'; // '/customer/58';
restRequest.Resource := res;
///query?query=select * from Customer where CompanyName = ' + quotedStr('TYOGA CONTAINER') + '&minorversion=75';
param := restRequest.Params.AddItem;
param.Name := 'Authorization';
param.Kind := pkHTTPHEADER;
param.Options := param.Options + [TRESTRequestParameterOption.poDoNotEncode];
param.Value := 'Bearer ' + AccessToken;
restRequest.Execute;
//memo1.Lines.Add(restresponse.Content);
jsValue := restResponse.JSONValue;
jsObj := TJSONObject(jsValue);
//CustomerList := TJSONArray(restResponse.JSONValue);
Memo1.Lines.Add( jsObj.Format(2) );
CustomerList := TJSONArray( TJSONObject( jsObj.GetValue('QueryResponse') ).GetValue('Customer')) ;
// Load customer info
ModifiedList := TJSONArray.Create;
for I := 0 to CustomerList.Count - 1 do
begin
Customer := CustomerList.Items[I] as TJSONObject;
Memo1.Lines.Add( Customer.Format(2) );
ParsedCustomer := TJSONObject.Create;
//sql := 'select CUSTOMER_ID from customers where QB_LIST_ID = ' + Customer.GetValue<string>('Id');
//doQuery(ordersDB.UniQuery1, SQL);
try
//ParsedCustomer.AddPair('In KGOrders', not(ordersDB.UniQuery1.IsEmpty));
ParsedCustomer.AddPair('Id', Customer.GetValue<string>('Id'));
ParsedCustomer.AddPair('CompanyName', Customer.GetValue<string>('DisplayName'));
// Handle Bill Address
if Customer.GetValue('BillAddr') is TJSONObject then
begin
BillAddr := Customer.GetValue('BillAddr') as TJSONObject;
ParsedCustomer.AddPair('BillAddrLine1', TJSONString.Create(BillAddr.GetValue<string>('Line1', '')));
ParsedCustomer.AddPair('BillAddrCity', TJSONString.Create(BillAddr.GetValue<string>('City', '')));
ParsedCustomer.AddPair('BillAddrState', TJSONString.Create(BillAddr.GetValue<string>('CountrySubDivisionCode', '')));
ParsedCustomer.AddPair('BillAddrZip', TJSONString.Create(BillAddr.GetValue<string>('PostalCode', '')));
ParsedCustomer.AddPair('BillAddr',
TJSONString.Create(
Customer.GetValue<string>('DisplayName') + sLineBreak +
BillAddr.GetValue('Line1', '') + ',' + sLineBreak +
BillAddr.GetValue('City', '') + ', ' +
BillAddr.GetValue('CountrySubDivisionCode', '') + ' ' +
BillAddr.GetValue('PostalCode', '')
)
);
end;
// Handle Ship Address
if Customer.GetValue('ShipAddr') is TJSONObject then
begin
BillAddr := Customer.GetValue('ShipAddr') as TJSONObject;
ParsedCustomer.AddPair('ShipAddrLine1', TJSONString.Create(BillAddr.GetValue<string>('Line1', '')));
ParsedCustomer.AddPair('ShipAddrCity', TJSONString.Create(BillAddr.GetValue<string>('City', '')));
ParsedCustomer.AddPair('ShipAddrState', TJSONString.Create(BillAddr.GetValue<string>('CountrySubDivisionCode', '')));
ParsedCustomer.AddPair('ShipAddrZip', TJSONString.Create(BillAddr.GetValue<string>('PostalCode', '')));
ParsedCustomer.AddPair('ShipAddr',
TJSONString.Create(
Customer.GetValue<string>('DisplayName') + sLineBreak +
BillAddr.GetValue('Line1', '') + ',' + sLineBreak +
BillAddr.GetValue('City', '') + ', ' +
BillAddr.GetValue('CountrySubDivisionCode', '') + ' ' +
BillAddr.GetValue('PostalCode', '')
)
);
end;
ModifiedList.AddElement(ParsedCustomer);
except
ParsedCustomer.Free;
raise;
end;
end;
LoadJSONArray(ModifiedList);
restClient.Free;
restRequest.Free;
restResponse.Free;
end;
procedure TfQB.ConfigureSSL(IOHandler: TIdSSLIOHandlerSocketOpenSSL);
......@@ -415,6 +1205,10 @@ begin
Secret := iniFile.ReadString('Quickbooks', 'ClientSecret', '');
CompanyID := iniFile.ReadString('Quickbooks', 'CompanyID', '');
RefreshToken := iniFile.ReadString('Quickbooks', 'RefreshToken', '');
AccessToken := iniFile.ReadString('Quickbooks', 'AccessToken', '');
LastRefresh := StrToDateTime(iniFile.ReadString('Quickbooks', 'LastRefresh', ''));
QB_ID := '';
ID := '';
end;
procedure TfQB.FormDestroy(Sender: TObject);
......@@ -475,7 +1269,6 @@ begin
// 4. Create and send request
RequestStream := TStringStream.Create(PostData, TEncoding.UTF8);
try
// Execute POST
try
response := IdHTTP.Post('https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer', RequestStream);
......@@ -488,7 +1281,7 @@ begin
Memo1.Lines.Add('Tokens Successfully Saved');
except
on E: EIdHTTPProtocolException do
Memo2.Lines.Add('Error: ' + E.Message + #13#10 + 'Response: ' + E.ErrorMessage);
Memo1.Lines.Add('Error: ' + E.Message + #13#10 + 'Response: ' + E.ErrorMessage);
end;
finally
RequestStream.Free;
......@@ -576,5 +1369,74 @@ begin
asgData.AutoSizeColumns(true);
end;
procedure TfQB.LoadJsonArray2(jaData: TJSONArray);
var
jso: TJSONObject;
i, j: integer;
row: integer;
begin
Memo1.Lines.Add( '---------------------------------------------------------------' );
Memo1.Lines.Add( 'LoadJsonArray into asgData2' );
asgData2.ClearAll;
asgData2.RowCount := 1;
asgData2.StartUpdate;
jso := TJSONObject(jaData.Items[0]);
asgData2.ColCount := jso.Count+1;
for i := 0 to jso.Count - 1 do
begin
asgData2.Cells[i+1, 0] := jso.Pairs[i].JsonString.Value;
Memo1.Lines.Add('Header Key: ' + jso.Pairs[i].JsonString.Value);
end;
for i := 0 to jaData.Count - 1 do
begin
jso := TJSONObject(jaData.Items[i]);
asgData2.RowCount := asgData2.RowCount + 1;
row := asgData2.RowCount - 1;
for j := 0 to jso.Count - 1 do
asgData2.Cells[j+1, row] := jso.Pairs[j].JsonValue.Value;
end;
asgData2.EndUpdate;
asgData2.AutoSizeColumns(true);
end;
procedure TfQB.Panel1Resize(Sender: TObject);
begin
AsgData2.Width := Panel1.ClientWidth;
AsgData2.Height := Panel1.ClientHeight;
end;
procedure TfQB.Panel2Resize(Sender: TObject);
begin
AsgData.Width := Panel2.ClientWidth;
AsgData.Height := Panel2.ClientHeight;
end;
procedure tfQB.findMatches(CustomerList: TJSONArray; JSONfield, DBField: string);
var
I: integer;
Customer: TJSONObject;
SQL: string;
begin
Memo1.Lines.Add('Matching ' + JSONfield + ' on ' + DBField);
for I := 0 to CustomerList.Count - 1 do
begin
Customer := CustomerList.Items[I] as TJSONObject;
SQL := 'select COUNT(*) as count from customers where NAME = ' + quotedStr(Customer.GetValue<string>(JSONfield));
doQuery(ordersDB.UniQuery1, SQL);
if ordersDB.UniQuery1.FieldByName('count').AsInteger = 1 then
begin
SQL := 'select * from customers where ' + DBField + ' = ' + quotedStr(Customer.GetValue<string>(JSONfield));
doQuery(ordersDB.UniQuery1, SQL);
Memo1.Lines.Add('Match at ' + ordersDB.UniQuery1.FieldByName('SHORT_NAME').AsString)
end
else if ordersDB.UniQuery1.FieldByName('count').AsInteger > 1 then
Memo1.Lines.Add(ordersDB.UniQuery1.FieldByName('count').AsString + ' Matches at ' + Customer.GetValue<string>(JSONfield) + ' in field ' + JSONfield);
end;
end;
end.
......@@ -212,7 +212,7 @@ begin
ForceDirectories(ReportDir);
Logger.Log(5, 'Reports directory created: ' + ReportDir);
end;
reportURL := FormatDateTime('yyyymmdd_hhnnss', Now) + '.pdf';
reportURL := 'reports/' + FormatDateTime('yyyymmdd_hhnnss', Now) + '.pdf';
ReportFileName := reportDir + reportUrl;
......
......@@ -1168,10 +1168,6 @@ object rptOrderList: TrptOrderList
Required = True
Size = 128
end
object uqOrdersORDER_DATE: TDateTimeField
FieldName = 'ORDER_DATE'
Required = True
end
object uqOrdersORDER_TYPE: TStringField
FieldName = 'ORDER_TYPE'
Required = True
......@@ -1272,6 +1268,9 @@ object rptOrderList: TrptOrderList
FieldName = 'NEW_SHIP_DONE'
Calculated = True
end
object uqOrdersORDER_DATE: TDateField
FieldName = 'ORDER_DATE'
end
end
object frxDBOrders: TfrxDBDataset
UserName = 'frxDBOrders'
......@@ -1281,126 +1280,6 @@ object rptOrderList: TrptOrderList
DataSetOptions = []
Left = 444
Top = 232
FieldDefs = <
item
FieldName = 'ORDER_ID'
end
item
FieldName = 'Loc'
FieldType = fftString
Size = 16
end
item
FieldName = 'COMPANY_NAME'
FieldType = fftString
Size = 90
end
item
FieldName = 'JOB_NAME'
FieldType = fftString
Size = 128
end
item
FieldName = 'ORDER_DATE'
FieldType = fftDateTime
end
item
FieldName = 'ORDER_TYPE'
FieldType = fftString
Size = 45
end
item
FieldName = 'PROOF_DUE'
FieldType = fftDateTime
end
item
FieldName = 'PROOF_DONE'
FieldType = fftDateTime
end
item
FieldName = 'ART_DUE'
FieldType = fftDateTime
end
item
FieldName = 'ART_DONE'
FieldType = fftDateTime
end
item
FieldName = 'PLATE_DUE'
FieldType = fftDateTime
end
item
FieldName = 'PLATE_DONE'
FieldType = fftDateTime
end
item
FieldName = 'MOUNT_DUE'
FieldType = fftDateTime
end
item
FieldName = 'MOUNT_DONE'
FieldType = fftDateTime
end
item
FieldName = 'SHIP_DUE'
FieldType = fftDateTime
end
item
FieldName = 'SHIP_DONE'
FieldType = fftDateTime
end
item
FieldName = 'PRICE'
end
item
FieldName = 'QB_REF_NUM'
FieldType = fftString
Size = 24
end
item
FieldName = 'COLORS'
FieldType = fftString
end
item
FieldName = 'po_number'
FieldType = fftString
Size = 16
end
item
FieldName = 'quickbooks_item'
FieldType = fftString
Size = 45
end
item
FieldName = 'NEW_ORDER_DATE'
FieldType = fftString
Size = 20
end
item
FieldName = 'NEW_PROOF_DONE'
FieldType = fftString
Size = 20
end
item
FieldName = 'NEW_ART_DONE'
FieldType = fftString
Size = 20
end
item
FieldName = 'NEW_PLATE_DONE'
FieldType = fftString
Size = 20
end
item
FieldName = 'NEW_MOUNT_DONE'
FieldType = fftString
Size = 20
end
item
FieldName = 'NEW_SHIP_DONE'
FieldType = fftString
Size = 20
end>
end
object uqColors: TUniQuery
Connection = ucKG
......
......@@ -18,7 +18,6 @@ type
uqOrdersLoc: TStringField;
uqOrdersCOMPANY_NAME: TStringField;
uqOrdersJOB_NAME: TStringField;
uqOrdersORDER_DATE: TDateTimeField;
uqOrdersORDER_TYPE: TStringField;
uqOrdersPROOF_DUE: TDateField;
uqOrdersPROOF_DONE: TDateTimeField;
......@@ -42,6 +41,7 @@ type
uqOrdersNEW_PLATE_DONE: TStringField;
uqOrdersNEW_MOUNT_DONE: TStringField;
uqOrdersNEW_SHIP_DONE: TStringField;
uqOrdersORDER_DATE: TDateField;
procedure DataModuleCreate(Sender: TObject);
procedure uqOrdersCalcFields(DataSet: TDataSet);
......@@ -125,6 +125,7 @@ var
OrderID: LongWord;
jsonStr: string;
begin
OrderID := uqOrdersORDER_ID.AsInteger;
if uqOrdersORDER_TYPE.AsString = 'web_plate' then
begin
......@@ -147,6 +148,10 @@ begin
uqColors.Close; // Ensure it is closed
end;
//uqOrdersORD.AsDateTime := uqOrdersORDER_DATE.AsDateTime;
//logger.Log(3, uqOrders.FieldByName('ORDER_DATE').AsString);
if uqOrdersORDER_DATE.AsString <> '' then
uqOrdersNEW_ORDER_DATE.AsString := FormatDateTime('m/d/yyyy HH:nn', uqOrdersORDER_DATE.AsDateTime)
else
......
......@@ -116,8 +116,8 @@
<DCC_UnitSearchPath>C:\RADTOOLS\FastMM4;$(DCC_UnitSearchPath)</DCC_UnitSearchPath>
<VerInfo_MajorVer>0</VerInfo_MajorVer>
<VerInfo_MinorVer>9</VerInfo_MinorVer>
<VerInfo_Release>4</VerInfo_Release>
<VerInfo_Keys>CompanyName=EM Systems;FileDescription=$(MSBuildProjectName);FileVersion=0.9.4.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=0.9.4.0;Comments=</VerInfo_Keys>
<VerInfo_Release>7</VerInfo_Release>
<VerInfo_Keys>CompanyName=EM Systems;FileDescription=$(MSBuildProjectName);FileVersion=0.9.7.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=0.9.7.0;Comments=</VerInfo_Keys>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_1_Win64)'!=''">
<AppDPIAwarenessMode>PerMonitorV2</AppDPIAwarenessMode>
......
[Settings]
MemoLogLevel=3
FileLogLevel=5
webClientVersion=0.9.4
LogFileNum=628
webClientVersion=0.9.7
LogFileNum=821
[Database]
--Server=192.168.159.131
--Server=192.168.159.153
Server=192.168.102.130
--Server=192.168.75.133
Database=kg_order_entry
......@@ -17,6 +17,6 @@ Password=emsys01
CompanyID=9341454272655710
ClientID=ABgO14uvjh8XqLud7spQ8lkb98AUpcdA7HbyMJfCAtl65sQ5yy
ClientSecret=bQ06TRemHeAGFzVHRaTUvUoBU9jpU9itK6MOMgqN
RefreshToken=RT1-113-H0-1757255538seyqgsf5e04vo9schkoa
AccessToken=eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwieC5vcmciOiJIMCJ9..Cqnj0xScf85NYKa6g4lanA.LN1AIU3ZlnDDbIMt-J4vl8V_gvcTfynSjGKYsmbhbfBJovq5IfZU4dHt6cqDAwUfnfOm42l-OpbwN9hWrZvUGlVx8x_3MA-vdtxIOByp7neq5vL2t4XcR5svPKIkX-CqlTsTb2ylBARiXehgk3tVHBysbHcnp0Ka0Ic_Waj64wQMYvE3Z-D19gCu-Xn9WFQwDICn8HSgJmHL2huLvRX-OrcxH6uERzLcQqRLsgT7fx9j68UWDW-KL_KRnzE43ieXlxXCwiCDnaF39Ei5iPHstnh19lGMgo1Z1mlF6tVZ9-8Z1prZutpiX8rzaPzS7Wdqo8pKtYaUqQZP6AGa6ZCqWR2BlF3y-R_FtheERNpafRiXWIDW68jOOrgp8QXc1uKA0sxDMjiLE7Bd0t9QAsIzln-0WiWIXFSlLGLimMd2oxxLoR7fpQvgB851I50b4S3V-c891WA8bHfuzScmjVwp40JxofhviFXwAevLNzRYvGkvIyz4oS9d6U6K_ZWKDB3iYxEgJzkFFwnfuPybWX7iNHwnmvFfAXz61jdaL9KRJM-lCChGuaQuv8_df9z_az_sbUtXJw2I8ivEppmDEQVxv49ZwzJlb6bFbqtnhy6ILO7_ecx3G1d4Utg-BrtgvzsR.oFJV6VBShL1-cERGZEqqkw
LastRefresh=5/28/2025 10:46:30 AM
RefreshToken=RT1-10-H0-1760618473k44t73jittvqlr4wynn6
AccessToken=eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwieC5vcmciOiJIMCJ9..IwosInYT2Am8LdNGXuY-zQ._QdW6AZ0up2uAna580wQy7qAZPo3nkfHo0eeSpKllcJ_s69nh33Ld41MnTkxeAv1v1bxhvkDxEvkevfNGnggNHU3XSqIqb6tTKcAqR4zPf14JYgOkn82tw_q2VXWLgboMMpP6CfcBHeZPIbJcEOkmX5g4CY0NOum1-_beYmDHE2sxAxnKxcg3rhjBo33BTFjXSg1xknvkTO_GVbyAWdyZmQOpFRfdXAeUDnPAEZhYNVfACFkEDubdK7PyfcAs_7un_E0NZf270tMc2W0HTyk24wCSLbfeeH2Su-G2wi21JszcNsXSNt9ayGtHEXNcWG6A54k1M8U7o_mvpCXLPEXDtJkx8HnBvTz_ZXrFaztQf0_c8DLld5zW8FC1wn-SzHyoCbYbR2M6tBjVLiK80_FlAal_YjBI8fk9BX7nBab6LbCBIcunt7hRsLWCPiRI8_fwM_Nj8rlvxtIoClcyV7_VpIpxCVUgmxKmgf7zuWD3fYc3i8Bg-DpgGgWPVATXSlfNKhOWIDZfyy0YOlkreXPlNdQwCJ1Su3_3yzu_DioV76C5orqoeWk25NiopiAqJ7cBMj15EiuFx-w3jaqCv6ovzEc5r3by510TNu6msjUh2RQ-nxVqLjyLt6VIp3O00e_.2itJJ0rFwI-foW2v1hDSrw
LastRefresh=7/7/2025 1:49:30 PM
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