Commit 03b02ef4 by Cam Hayes

Fixed Minor Bugs in AddCustomer Form and began working on importing QB Customers

QB Implementation is currently commented out.
parent ec390bdd
...@@ -136,18 +136,6 @@ object FViewAddCustomer: TFViewAddCustomer ...@@ -136,18 +136,6 @@ object FViewAddCustomer: TFViewAddCustomer
DataField = 'FAX' DataField = 'FAX'
DataSource = WebDataSource1 DataSource = WebDataSource1
end end
object edtRep: TWebDBEdit
Left = 19
Top = 332
Width = 121
Height = 22
ChildOrder = 12
ElementID = 'edtrepid'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
DataField = 'REP_USER_ID'
DataSource = WebDataSource1
end
object btnSave: TWebButton object btnSave: TWebButton
Left = 19 Left = 19
Top = 402 Top = 402
...@@ -221,7 +209,7 @@ object FViewAddCustomer: TFViewAddCustomer ...@@ -221,7 +209,7 @@ object FViewAddCustomer: TFViewAddCustomer
ChildOrder = 5 ChildOrder = 5
ElementPosition = epRelative ElementPosition = epRelative
Role = 'null' Role = 'null'
TabOrder = 17 TabOrder = 16
object lblMessage: TWebLabel object lblMessage: TWebLabel
Left = 28 Left = 28
Top = 9 Top = 9
...@@ -505,6 +493,20 @@ object FViewAddCustomer: TFViewAddCustomer ...@@ -505,6 +493,20 @@ object FViewAddCustomer: TFViewAddCustomer
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
end end
object wdblcbRep: TWebDBLookupComboBox
Left = 19
Top = 336
Width = 145
Height = 22
ElementID = 'wdblcbrep'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
DataField = 'REP_USER_ID'
DataSource = WebDataSource1
KeyField = 'userID'
ListField = 'full_name'
ListSource = wdsUsers
end
object XDataWebClient1: TXDataWebClient object XDataWebClient1: TXDataWebClient
Connection = DMConnection.ApiConnection Connection = DMConnection.ApiConnection
Left = 454 Left = 454
...@@ -544,24 +546,24 @@ object FViewAddCustomer: TFViewAddCustomer ...@@ -544,24 +546,24 @@ object FViewAddCustomer: TFViewAddCustomer
object XDataWebDataSet1START_DATE: TStringField object XDataWebDataSet1START_DATE: TStringField
FieldName = 'START_DATE' FieldName = 'START_DATE'
end end
object XDataWebDataSet1END_DATE: TStringField
FieldName = 'END_DATE'
end
object XDataWebDataSet1QB_LIST_ID: TStringField object XDataWebDataSet1QB_LIST_ID: TStringField
FieldName = 'QB_LIST_ID' FieldName = 'QB_LIST_ID'
end end
object XDataWebDataSet1END_DATE: TStringField
FieldName = 'END_DATE'
end
object XDataWebDataSet1FAX: TStringField object XDataWebDataSet1FAX: TStringField
FieldName = 'FAX' FieldName = 'FAX'
end end
object XDataWebDataSet1PHONE: TStringField object XDataWebDataSet1PHONE: TStringField
FieldName = 'PHONE' FieldName = 'PHONE'
end end
object XDataWebDataSet1REP_USER_ID: TIntegerField
FieldName = 'REP_USER_ID'
end
object XDataWebDataSet1CUSTOMER_ID: TIntegerField object XDataWebDataSet1CUSTOMER_ID: TIntegerField
FieldName = 'CUSTOMER_ID' FieldName = 'CUSTOMER_ID'
end end
object XDataWebDataSet1REP_USER_ID: TStringField
FieldName = 'REP_USER_ID'
end
end end
object wdsShipTo: TWebDataSource object wdsShipTo: TWebDataSource
DataSet = xdwdsShipTo DataSet = xdwdsShipTo
...@@ -600,4 +602,20 @@ object FViewAddCustomer: TFViewAddCustomer ...@@ -600,4 +602,20 @@ object FViewAddCustomer: TFViewAddCustomer
Left = 542 Left = 542
Top = 42 Top = 42
end end
object wdsUsers: TWebDataSource
DataSet = xdwdsUsers
Left = 776
Top = 144
end
object xdwdsUsers: TXDataWebDataSet
Left = 776
Top = 54
object xdwdsUsersuserID: TStringField
FieldName = 'userID'
end
object xdwdsUsersfull_name: TStringField
FieldName = 'full_name'
Size = 0
end
end
end end
...@@ -70,8 +70,8 @@ ...@@ -70,8 +70,8 @@
<input id="edtfax" class="form-control input-sm"style="width: 200px"/> <input id="edtfax" class="form-control input-sm"style="width: 200px"/>
</div> </div>
<div class="col-auto"> <div class="col-auto">
<label for="wdbe_first_name" style="font-weight: 700; font-size: 15px;" class="form-label mt-2">Representative ID:</label> <label for="wdbe_first_name" style="font-weight: 700; font-size: 15px;" class="form-label mt-2">Representative:</label>
<input id="edtrepid" class="form-control input-sm" style="width: 200px"/> <select id="wdblcbrep" class='form-select'></select>
</div> </div>
</div> </div>
<h4 class="custom-h4 mt-3">Billing Information</h4> <h4 class="custom-h4 mt-3">Billing Information</h4>
......
// Add Customer page for KGOrders. Handles Adding and Editting Customers and
// Their shipping addresses.
unit AddCustomer; unit AddCustomer;
interface interface
...@@ -22,7 +24,6 @@ type ...@@ -22,7 +24,6 @@ type
edtBillContact: TWebDBEdit; edtBillContact: TWebDBEdit;
edtPhone: TWebDBEdit; edtPhone: TWebDBEdit;
edtFax: TWebDBEdit; edtFax: TWebDBEdit;
edtRep: TWebDBEdit;
btnSave: TWebButton; btnSave: TWebButton;
btnCancel: TWebButton; btnCancel: TWebButton;
btnDelete: TWebButton; btnDelete: TWebButton;
...@@ -51,7 +52,6 @@ type ...@@ -51,7 +52,6 @@ type
XDataWebDataSet1QB_LIST_ID: TStringField; XDataWebDataSet1QB_LIST_ID: TStringField;
XDataWebDataSet1FAX: TStringField; XDataWebDataSet1FAX: TStringField;
XDataWebDataSet1PHONE: TStringField; XDataWebDataSet1PHONE: TStringField;
XDataWebDataSet1REP_USER_ID: TIntegerField;
XDataWebDataSet1CUSTOMER_ID: TIntegerField; XDataWebDataSet1CUSTOMER_ID: TIntegerField;
edtShippingAddress: TWebEdit; edtShippingAddress: TWebEdit;
edtShippingState: TWebEdit; edtShippingState: TWebEdit;
...@@ -76,6 +76,12 @@ type ...@@ -76,6 +76,12 @@ type
btn_confirm_delete: TWebButton; btn_confirm_delete: TWebButton;
tmrReturn: TWebTimer; tmrReturn: TWebTimer;
edtFirstLine: TWebEdit; edtFirstLine: TWebEdit;
wdsUsers: TWebDataSource;
xdwdsUsers: TXDataWebDataSet;
wdblcbRep: TWebDBLookupComboBox;
xdwdsUsersuserID: TStringField;
XDataWebDataSet1REP_USER_ID: TStringField;
xdwdsUsersfull_name: TStringField;
procedure WebFormShow(Sender: TObject); procedure WebFormShow(Sender: TObject);
procedure btnCloseNotificationClick(Sender: TObject); procedure btnCloseNotificationClick(Sender: TObject);
procedure btnSaveClick(Sender: TObject); procedure btnSaveClick(Sender: TObject);
...@@ -131,6 +137,7 @@ implementation ...@@ -131,6 +137,7 @@ implementation
uses View.Main, View.Customers; uses View.Main, View.Customers;
procedure TFViewAddCustomer.Clear(); procedure TFViewAddCustomer.Clear();
// Clears the shipping address fields.
begin begin
edtShippingAddress.Text := ''; edtShippingAddress.Text := '';
edtShippingCity.Text := ''; edtShippingCity.Text := '';
...@@ -142,6 +149,7 @@ begin ...@@ -142,6 +149,7 @@ begin
end; end;
procedure TFViewAddCustomer.DelAddress; procedure TFViewAddCustomer.DelAddress;
// Deletes a shipping address.
var var
Response: TXDataClientResponse; Response: TXDataClientResponse;
notification: TJSObject; notification: TJSObject;
...@@ -159,6 +167,8 @@ begin ...@@ -159,6 +167,8 @@ begin
end; end;
procedure TFViewAddCustomer.SendAddressToServer; procedure TFViewAddCustomer.SendAddressToServer;
// Creates an Address JSON and then sends it to the server for the address to be
// Added or edited.
var var
Field: TField; Field: TField;
AddressJSON: TJSONObject; AddressJSON: TJSONObject;
...@@ -198,11 +208,13 @@ begin ...@@ -198,11 +208,13 @@ begin
end; end;
procedure TFViewAddCustomer.btnAddClick(Sender: TObject); procedure TFViewAddCustomer.btnAddClick(Sender: TObject);
// Takes the user to the Add Customer Page.
begin begin
FViewMain.ViewAddCustomer('', ''); FViewMain.ViewAddCustomer('', '');
end; end;
procedure TFViewAddCustomer.btnCancelClick(Sender: TObject); procedure TFViewAddCustomer.btnCancelClick(Sender: TObject);
// Shows a pop-up to confirm the user would like to cancel their changes.
begin begin
document.getElementById('modal_body').innerHTML := 'Are you sure you want to cancel all changes to the customer?'; 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_cancel').innerText := 'No';
...@@ -215,36 +227,44 @@ begin ...@@ -215,36 +227,44 @@ begin
end; end;
procedure TFViewAddCustomer.btnClearClick(Sender: TObject); procedure TFViewAddCustomer.btnClearClick(Sender: TObject);
// Clears the shipping address fields.
begin begin
Clear(); Clear();
end; end;
procedure TFViewAddCustomer.btnCloseClick(Sender: TObject); procedure TFViewAddCustomer.btnCloseClick(Sender: TObject);
// closes the Add Customer page.
begin begin
FViewMain.ShowForm(TFViewCustomers) FViewMain.ShowForm(TFViewCustomers)
end; end;
procedure TFViewAddCustomer.btnCloseNotificationClick(Sender: TObject); procedure TFViewAddCustomer.btnCloseNotificationClick(Sender: TObject);
// Closes a Notification.
begin begin
HideNotification(); HideNotification();
end; end;
procedure TFViewAddCustomer.btnDeleteClick(Sender: TObject); procedure TFViewAddCustomer.btnDeleteClick(Sender: TObject);
// Eventually will delete customers after a confirmation
// TODO implement deleting customers
begin begin
ShowMessage('Deleting Customers Is Not Yet Available'); ShowMessage('Deleting Customers Is Not Yet Available');
end; end;
procedure TFViewAddCustomer.btnEditClick(Sender: TObject); procedure TFViewAddCustomer.btnEditClick(Sender: TObject);
// Puts the form into edit mode
begin begin
EditMode(); EditMode();
end; end;
procedure TFViewAddCustomer.edtShippingAddressChange(Sender: TObject); procedure TFViewAddCustomer.edtShippingAddressChange(Sender: TObject);
// Puts the form into Address Edit Mode
begin begin
AddressEditMode(); AddressEditMode();
end; end;
procedure TFViewAddCustomer.EditMode; procedure TFViewAddCustomer.EditMode;
// Enables Customer Fields while disabling shipping address fields.
begin begin
FViewMain.change := true; FViewMain.change := true;
btnAdd.Enabled := false; btnAdd.Enabled := false;
...@@ -271,6 +291,7 @@ begin ...@@ -271,6 +291,7 @@ begin
end; end;
procedure TFViewAddCustomer.AddressEditMode; procedure TFViewAddCustomer.AddressEditMode;
// Enables Shipping Address fields while disabling customer fields.
begin begin
FViewMain.change := true; FViewMain.change := true;
btnDelete.Enabled := false; btnDelete.Enabled := false;
...@@ -304,10 +325,11 @@ begin ...@@ -304,10 +325,11 @@ begin
dtpEndDate.Enabled := false; dtpEndDate.Enabled := false;
edtFax.Enabled := false; edtFax.Enabled := false;
edtPhone.enabled := false; edtPhone.enabled := false;
edtRep.Enabled := false; wdblcbRep.Enabled := false;
end; end;
procedure TFViewAddCustomer.ViewMode; procedure TFViewAddCustomer.ViewMode;
// Enables Customer Fields while disabling shipping address fields.
begin begin
btnAdd.Enabled := true; btnAdd.Enabled := true;
btnDelete.Enabled := true; btnDelete.Enabled := true;
...@@ -318,13 +340,13 @@ begin ...@@ -318,13 +340,13 @@ begin
FViewMain.change := false; FViewMain.change := false;
btnShipAdd.Enabled := true; btnShipAdd.Enabled := true;
btnShipDelete.Enabled := true; if ( not xdwdsShipTo.IsEmpty ) then
btnShipDelete.Enabled := true;
btnShipSave.Enabled := false; btnShipSave.Enabled := false;
btnShipCancel.Enabled := false; btnShipCancel.Enabled := false;
btnShipEdit.Enabled := true; btnShipEdit.Enabled := true;
FViewMain.change := false; FViewMain.change := false;
// Make Sure Customer is editable
edtName.Enabled := true; edtName.Enabled := true;
edtShortName.Enabled := true; edtShortName.Enabled := true;
edtBillAddress.Enabled := true; edtBillAddress.Enabled := true;
...@@ -336,12 +358,13 @@ begin ...@@ -336,12 +358,13 @@ begin
dtpEndDate.Enabled := true; dtpEndDate.Enabled := true;
edtFax.Enabled := true; edtFax.Enabled := true;
edtPhone.enabled := true; edtPhone.enabled := true;
edtRep.Enabled := true; wdblcbRep.Enabled := true;
end; end;
procedure TFViewAddCustomer.wdbtcAddressesDblClickCell(Sender: TObject; ACol, procedure TFViewAddCustomer.wdbtcAddressesDblClickCell(Sender: TObject; ACol,
ARow: Integer); ARow: Integer);
// Retrieves the shipping address allowing it to be edited.
begin begin
xdwdsShipTo.Locate('ship_id', wdbtcAddresses.Cells[0, ARow], []); xdwdsShipTo.Locate('ship_id', wdbtcAddresses.Cells[0, ARow], []);
edtShippingAddress.Text := xdwdsShipTo.FieldByName('shipping_address').AsString; edtShippingAddress.Text := xdwdsShipTo.FieldByName('shipping_address').AsString;
...@@ -354,6 +377,7 @@ begin ...@@ -354,6 +377,7 @@ begin
end; end;
procedure TFViewAddCustomer.SendCustomerToServer(); procedure TFViewAddCustomer.SendCustomerToServer();
// Creates the customer JSON and then sends it to the server.
var var
customerJSON: TJSONObject; customerJSON: TJSONObject;
Field: TField; Field: TField;
...@@ -361,6 +385,7 @@ var ...@@ -361,6 +385,7 @@ var
notification: TJSObject; notification: TJSObject;
input: TJSHTMLElement; input: TJSHTMLElement;
msg: string; msg: string;
BILL_ADDRESS_BLOCK: string;
begin begin
customerJSON := TJSONObject.Create; customerJSON := TJSONObject.Create;
...@@ -392,19 +417,34 @@ begin ...@@ -392,19 +417,34 @@ begin
XDataWebDataSet1.Next; XDataWebDataSet1.Next;
end; end;
customerJSON.AddPair('BILL_ADDRESS_BLOCK', memoAddressBlock.Text); BILL_ADDRESS_BLOCK := edtName.Text + slinebreak +
edtBillContact.Text + slinebreak +
edtBillAddress.Text + slinebreak +
edtBillCity.Text + ', ' + edtBillState.Text + ' ' + edtBillZip.Text;
CustomerJSON.AddPair('BILL_ADDRESS_BLOCK', BILL_ADDRESS_BLOCK);
customerJSON.AddPair('mode', mode); customerJSON.AddPair('mode', mode);
if mode = 'EDIT' then if mode = 'EDIT' then
customerJSON.AddPair('CUSTOMER_ID', customerID); customerJSON.AddPair('CUSTOMER_ID', customerID);
console.log('working');
Response := await(XDataWebClient1.RawInvokeAsync('ILookupService.AddCustomer', Response := await(XDataWebClient1.RawInvokeAsync('ILookupService.AddCustomer',
[customerJSON.ToString])); [customerJSON.ToString]));
notification := TJSObject(Response.Result); notification := TJSObject(Response.Result);
console.log(response.Result);
msg := string(notification['status']); msg := string(notification['status']);
if CustomerID = '' then
CustomerID := string(notification['CustomerID']);
edtCustomerID.Text := CustomerID;
ShowNotification(msg); ShowNotification(msg);
//TODO update the BILL_ADDRESS_BLOCK memo after saving.
if msg.Contains('Failure') then if msg.Contains('Failure') then
begin begin
input := TJSHTMLInputElement(document.getElementById('edtcompanyaccountname')); input := TJSHTMLInputElement(document.getElementById('edtcompanyaccountname'));
...@@ -416,6 +456,7 @@ begin ...@@ -416,6 +456,7 @@ begin
end; end;
procedure TFViewAddCustomer.btnSaveClick(Sender: TObject); procedure TFViewAddCustomer.btnSaveClick(Sender: TObject);
// Sends the customer JSON to the server
begin begin
if VerifyCustomer() then if VerifyCustomer() then
begin begin
...@@ -425,6 +466,7 @@ begin ...@@ -425,6 +466,7 @@ begin
end; end;
procedure TFViewAddCustomer.btnShipAddClick(Sender: TObject); procedure TFViewAddCustomer.btnShipAddClick(Sender: TObject);
// Sets the form to address edit mode and allows the user to add a shipping address.
begin begin
shipmode := 'ADD'; shipmode := 'ADD';
Clear(); Clear();
...@@ -432,6 +474,7 @@ begin ...@@ -432,6 +474,7 @@ begin
end; end;
procedure TFViewAddCustomer.btnShipDeleteClick(Sender: TObject); procedure TFViewAddCustomer.btnShipDeleteClick(Sender: TObject);
// Allows the user to delete a Shipping Address.
begin begin
document.getElementById('modal_body').innerHTML := 'Are you sure you want to delete this address?'; 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_cancel').innerText := 'Cancel';
...@@ -444,12 +487,14 @@ begin ...@@ -444,12 +487,14 @@ begin
end; end;
procedure TFViewAddCustomer.btnShipEditClick(Sender: TObject); procedure TFViewAddCustomer.btnShipEditClick(Sender: TObject);
// Sets the form into AddressEdit mode.
begin begin
shipmode := 'EDIT'; shipmode := 'EDIT';
AddressEditMode(); AddressEditMode();
end; end;
procedure TFViewAddCustomer.btnShipSaveClick(Sender: TObject); procedure TFViewAddCustomer.btnShipSaveClick(Sender: TObject);
// After Verifying the Address it sends the address down to the server.
begin begin
if VerifyAddress() then if VerifyAddress() then
begin begin
...@@ -460,9 +505,12 @@ begin ...@@ -460,9 +505,12 @@ begin
end; end;
procedure TFViewAddCustomer.btn_confirm_deleteClick(Sender: TObject); procedure TFViewAddCustomer.btn_confirm_deleteClick(Sender: TObject);
// Modal Confirmation button. Checks if the user is cancelling changes, or
// Deleting a shipping address/ customer
begin begin
FViewMain.change := false;
if document.getElementById('btn_confirm_delete').innerText = 'Yes' then if document.getElementById('btn_confirm_delete').innerText = 'Yes' then
// checks if the modal is canceling // checks if the user is canceling or deleting
begin begin
if CustomerID <> '' then if CustomerID <> '' then
begin begin
...@@ -496,6 +544,8 @@ begin ...@@ -496,6 +544,8 @@ begin
end; end;
class function TFViewAddCustomer.CreateForm(AElementID: string; customerInfo: string; info: string): TWebForm; 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.
begin begin
Application.CreateForm(TFViewAddCustomer, AElementID, Result, Application.CreateForm(TFViewAddCustomer, AElementID, Result,
procedure(AForm: TObject) procedure(AForm: TObject)
...@@ -511,6 +561,7 @@ begin ...@@ -511,6 +561,7 @@ begin
end; end;
procedure TFViewAddCustomer.GetCustomer; procedure TFViewAddCustomer.GetCustomer;
// Retrieves a customer for a given CustomerID.
var var
xdcResponse: TXDataClientResponse; xdcResponse: TXDataClientResponse;
customer : TJSObject; customer : TJSObject;
...@@ -520,7 +571,6 @@ var ...@@ -520,7 +571,6 @@ var
begin begin
if CustomerID = '' then if CustomerID = '' then
begin begin
customerID := '-1';
mode := 'ADD'; mode := 'ADD';
end end
else else
...@@ -528,14 +578,18 @@ begin ...@@ -528,14 +578,18 @@ begin
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GetCustomer', xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GetCustomer',
[customerID])); [customerID]));
customer := TJSObject(xdcResponse.Result); customer := TJSObject(xdcResponse.Result);
console.log(customer);
xdwdsUsers.Close;
xdwdsUsers.SetJSONData(customer['USERS']);
xdwdsUsers.Open;
XDataWebDataSet1.Close; XDataWebDataSet1.Close;
XDataWebDataSet1.SetJsonData(customer); XDataWebDataSet1.SetJsonData(customer);
XDataWebDataSet1.Open; XDataWebDataSet1.Open;
if CustomerID = '-1' then
begin edtCustomerID.Text := CustomerID;
edtCustomerID.Text := '';
end;
if XDataWebDataSet1.FieldByName('START_DATE').AsString <> '' then if XDataWebDataSet1.FieldByName('START_DATE').AsString <> '' then
dtpStartDate.Date := XDataWebDataSet1.FieldByName('START_DATE').AsDateTime; dtpStartDate.Date := XDataWebDataSet1.FieldByName('START_DATE').AsDateTime;
...@@ -549,20 +603,29 @@ begin ...@@ -549,20 +603,29 @@ begin
memoAddressBlock.Text := string(customer['staff_fields_invoice_to']); memoAddressBlock.Text := string(customer['staff_fields_invoice_to']);
edtShippingAddress.Text := xdwdsShipTo.FieldByName('shipping_address').AsString; if ( not xdwdsShipTo.IsEmpty ) then
edtShippingCity.Text := xdwdsShipTo.FieldByName('city').AsString; begin
edtShippingState.Text := xdwdsShipTo.FieldByName('state').AsString; edtShippingAddress.Text := xdwdsShipTo.FieldByName('shipping_address').AsString;
edtShippingZip.Text := xdwdsShipTo.FieldByName('zip').AsString; edtShippingCity.Text := xdwdsShipTo.FieldByName('city').AsString;
edtShippingContact.Text := xdwdsShipTo.FieldByName('contact').AsString; edtShippingState.Text := xdwdsShipTo.FieldByName('state').AsString;
memoShipBlock.Text := xdwdsShipTo.FieldByName('ADDRESS').AsString; edtShippingZip.Text := xdwdsShipTo.FieldByName('zip').AsString;
edtFirstLine.Text := memoShipBlock.Lines[0]; edtShippingContact.Text := xdwdsShipTo.FieldByName('contact').AsString;
memoShipBlock.Text := xdwdsShipTo.FieldByName('ADDRESS').AsString;
edtFirstLine.Text := memoShipBlock.Lines[0];
end;
end; end;
procedure TFViewAddCustomer.WebFormShow(Sender: TObject); procedure TFViewAddCustomer.WebFormShow(Sender: TObject);
// Sets the form up whenever it is shown.
var var
SQL: string; SQL: string;
begin begin
if customerID = '' then
mode := 'ADD'
else
mode := 'EDIT';
if notification = '' then if notification = '' then
hideNotification() hideNotification()
else else
...@@ -628,6 +691,8 @@ begin ...@@ -628,6 +691,8 @@ begin
end; end;
procedure TFViewAddCustomer.tmrReturnTimer(Sender: TObject); procedure TFViewAddCustomer.tmrReturnTimer(Sender: TObject);
// Timer to returnto the customer page because it takes slightly too long to
// Delete customers causing ghost customers to show up.
begin begin
asm asm
endSpinner(); endSpinner();
...@@ -708,18 +773,10 @@ begin ...@@ -708,18 +773,10 @@ begin
end end
else else
input.classList.remove('is-invalid'); input.classList.remove('is-invalid');
input := TJSHTMLInputElement(document.getElementById('memoaddressblock'));
if memoAddressBlock.Lines.Count = 0 then
begin
input.classList.add('is-invalid');
result := false;
end
else
input.classList.remove('is-invalid');
end; end;
function TFViewAddCustomer.VerifyAddress: Boolean; function TFViewAddCustomer.VerifyAddress: Boolean;
// Verifies all the shipping information is filled in.
var var
input: TJSHTMLElement; input: TJSHTMLElement;
begin begin
......
object FViewAddAddress: TFViewAddAddress
Width = 281
Height = 402
object WebLabel1: TWebLabel
Left = 8
Top = 283
Width = 92
Height = 15
Caption = 'Shipping Contact'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object WebLabel2: TWebLabel
Left = 8
Top = 234
Width = 67
Height = 15
Caption = 'Shipping Zip'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object WebLabel3: TWebLabel
Left = 8
Top = 136
Width = 71
Height = 15
Caption = 'Shipping City'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object WebLabel4: TWebLabel
Left = 8
Top = 185
Width = 76
Height = 15
Caption = 'Shipping State'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object WebLabel5: TWebLabel
Left = 8
Top = 87
Width = 92
Height = 15
Caption = 'Shipping Address'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object WebLabel6: TWebLabel
Left = 8
Top = 36
Width = 47
Height = 15
Caption = 'First Line'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object edtState: TWebEdit
Left = 8
Top = 206
Width = 78
Height = 22
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object edtFirstLine: TWebEdit
Left = 8
Top = 59
Width = 198
Height = 22
ChildOrder = 1
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object edtCity: TWebEdit
Left = 8
Top = 157
Width = 149
Height = 22
ChildOrder = 2
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object edtZip: TWebEdit
Left = 8
Top = 255
Width = 121
Height = 22
ChildOrder = 3
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object edtContact: TWebEdit
Left = 8
Top = 304
Width = 198
Height = 22
ChildOrder = 4
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object edtAddress: TWebEdit
Left = 8
Top = 108
Width = 198
Height = 22
ChildOrder = 1
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object edtNotification: TWebEdit
Left = 8
Top = 8
Width = 198
Height = 22
ChildOrder = 12
Enabled = False
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object btnSave: TWebButton
Left = 8
Top = 340
Width = 96
Height = 25
Caption = 'Save'
ChildOrder = 13
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnClick = btnSaveClick
end
object btnCancel: TWebButton
Left = 110
Top = 340
Width = 96
Height = 25
Caption = 'Cancel'
ChildOrder = 13
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnClick = btnCancelClick
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
// Small Pop-Up page when adding orders if you want to quickly add an address
unit View.AddAddress;
interface
uses
System.SysUtils, System.Classes, JS, Web, WEBLib.Graphics, WEBLib.Controls,
WEBLib.Forms, WEBLib.Dialogs, Vcl.Controls, Vcl.StdCtrls, WEBLib.StdCtrls;
type
TFViewAddAddress = class(TWebForm)
edtState: TWebEdit;
edtFirstLine: TWebEdit;
edtCity: TWebEdit;
edtZip: TWebEdit;
edtContact: TWebEdit;
edtAddress: TWebEdit;
WebLabel1: TWebLabel;
WebLabel2: TWebLabel;
WebLabel3: TWebLabel;
WebLabel4: TWebLabel;
WebLabel5: TWebLabel;
WebLabel6: TWebLabel;
edtNotification: TWebEdit;
btnSave: TWebButton;
btnCancel: TWebButton;
procedure btnCancelClick(Sender: TObject);
procedure btnSaveClick(Sender: TObject);
private
{ Private declarations }
function Verify(): boolean;
public
{ Public declarations }
var
confirm: boolean;
end;
var
FViewAddAddress: TFViewAddAddress;
implementation
{$R *.dfm}
procedure TFViewAddAddress.btnSaveClick(Sender: TObject);
begin
if Verify() then
begin
confirm := true;
Close;
end;
end;
function TFViewAddAddress.Verify(): boolean;
// Makes sure the address is filled in.
begin
result := true;
if edtFirstLine.Text = '' then
begin
edtNotification.Text := 'Please Fill in the First Line';
result := false;
end
else if edtAddress.Text = '' then
begin
edtNotification.Text := 'Please Fill in the Address';
result := false;
end
else if edtCity.Text = '' then
begin
edtNotification.Text := 'Please Fill in the City';
result := false;
end
else
if edtState.Text = '' then
begin
edtNotification.Text := 'Please Fill in the State';
result := false;
end
else if edtZip.Text = '' then
begin
edtNotification.Text := 'Please Fill in the Zip Code';
result := false;
end
else if edtContact.Text = '' then
begin
edtNotification.Text := 'Please Fill in the Contact';
result := false;
end
end;
procedure TFViewAddAddress.btnCancelClick(Sender: TObject);
begin
Close;
end;
end.
\ No newline at end of file
unit View.AddOrder2;
interface
uses
System.SysUtils, System.Classes, JS, Web, WEBLib.Graphics, WEBLib.Controls,
WEBLib.Forms, WEBLib.Dialogs, WEBLib.StdCtrls, XData.Web.Client, WEBLib.ExtCtrls,
Data.DB, XData.Web.Dataset, VCL.TMSFNCTypes, VCL.TMSFNCGrid, VCL.TMSFNCGridData,
VCL.TMSFNCUtils, VCL.TMSFNCGraphics, VCL.TMSFNCGraphicsTypes,
VCL.TMSFNCGridCell, VCL.TMSFNCGridOptions, VCL.TMSFNCCustomComponent,
VCL.TMSFNCCustomGrid, VCL.TMSFNCGridDatabaseAdapter, VCL.TMSFNCCustomControl,
VCL.TMSFNCCustomScrollControl, WEBLib.DB, XData.Web.JsonDataset, Vcl.StdCtrls,
Vcl.Controls, ConnectionModule;
type
TFAddOrder = class(TWebForm)
edtSearch: TWebEdit;
edtID: TWebEdit;
btnCancel: TWebButton;
XDataWebClient1: TXDataWebClient;
wdsCustomers: TWebDataSource;
xdwdsCustomers: TXDataWebDataSet;
xdwdsCustomersID: TIntegerField;
xdwdsCustomersNAME: TStringField;
xdwdsCustomersSHORT_NAME: TStringField;
btnConfirm: TWebButton;
cbCorrugatedPlate: TWebCheckBox;
cbWebPlate: TWebCheckBox;
TMSFNCGrid1: TTMSFNCGrid;
procedure WebFormShow(Sender: TObject);
procedure cbCorrugatedPlateClick(Sender: TObject);
procedure cbWebPlateClick(Sender: TObject);
procedure btnConfirmClick(Sender: TObject);
procedure edtSearchChange(Sender: TObject);
procedure btnCancelClick(Sender: TObject);
procedure TMSFNCGrid1SelectedCell(Sender: TObject; ACol, ARow: Integer);
private
[async] procedure getCustomers();
procedure PopulateGridManually;
procedure ApplyFilter;
public
end;
var
FAddOrder: TFAddOrder;
implementation
{$R *.dfm}
procedure TFAddOrder.WebFormShow(Sender: TObject);
begin
getCustomers(); // Fetch and populate the grid with customer data
end;
[async]
procedure TFAddOrder.getCustomers();
var
xdcResponse: TXDataClientResponse;
customerList: TJSObject;
begin
// Fetch data from XData service
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GetCustomers', []));
customerList := TJSObject(xdcResponse.Result);
// Load data into TXDataWebDataset
xdwdsCustomers.Close;
xdwdsCustomers.SetJsonData(customerList['data']);
xdwdsCustomers.Open;
// Manually populate the grid
PopulateGridManually;
end;
procedure TFAddOrder.PopulateGridManually;
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] := 'ID';
TMSFNCGrid1.Cells[1, 0] := 'Short Name';
TMSFNCGrid1.Cells[2, 0] := 'Name';
// TMSFNCGrid1.ColumnWidths[0] := 40;
// TMSFNCGrid1.ColumnWidths[1] := 80;
// TMSFNCGrid1.ColumnWidths[2] := 250;
// 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('ID').AsString;
TMSFNCGrid1.Cells[1, RowIndex] := xdwdsCustomers.FieldByName('SHORT_NAME').AsString;
TMSFNCGrid1.Cells[2, RowIndex] := xdwdsCustomers.FieldByName('NAME').AsString;
Inc(RowIndex);
xdwdsCustomers.Next;
end;
finally
TMSFNCGrid1.EndUpdate;
end;
end;
procedure TFAddOrder.TMSFNCGrid1SelectedCell(Sender: TObject; ACol,
ARow: Integer);
begin
edtID.Text := TMSFNCGrid1.Cells[0, ARow];
end;
procedure TFAddOrder.ApplyFilter;
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;
procedure TFAddOrder.cbCorrugatedPlateClick(Sender: TObject);
begin
cbWebPlate.Checked := False;
end;
procedure TFAddOrder.cbWebPlateClick(Sender: TObject);
begin
cbCorrugatedPlate.Checked := False;
end;
procedure TFAddOrder.btnConfirmClick(Sender: TObject);
begin
Close;
end;
procedure TFAddOrder.btnCancelClick(Sender: TObject);
begin
edtID.Text := '';
Close;
end;
procedure TFAddOrder.edtSearchChange(Sender: TObject);
begin
ApplyFilter;
end;
end.
//unit View.AddOrder;
//
//interface
//
//uses
// System.SysUtils, System.Classes, JS, Web, WEBLib.Graphics, WEBLib.Controls,
// WEBLib.Forms, WEBLib.Dialogs, WEBLib.StdCtrls, XData.Web.Client, WEBLib.ExtCtrls,
// Data.DB, XData.Web.Dataset, VCL.TMSFNCTypes, VCL.TMSFNCGrid, VCL.TMSFNCGridData,
// VCL.TMSFNCUtils, VCL.TMSFNCGraphics, VCL.TMSFNCGraphicsTypes,
// VCL.TMSFNCGridCell, VCL.TMSFNCGridOptions, VCL.TMSFNCCustomComponent,
// VCL.TMSFNCCustomGrid, VCL.TMSFNCGridDatabaseAdapter, VCL.TMSFNCCustomControl,
// VCL.TMSFNCCustomScrollControl, WEBLib.DB, XData.Web.JsonDataset, Vcl.StdCtrls,
// Vcl.Controls, ConnectionModule, WEBLib.WebCtrls;
//
//type
// TFAddOrder = class(TWebForm)
// XDataWebClient1: TXDataWebClient;
// wdsCustomers: TWebDataSource;
// xdwdsCustomers: TXDataWebDataSet;
// xdwdsCustomersID: TIntegerField;
// xdwdsCustomersNAME: TStringField;
// xdwdsCustomersSHORT_NAME: TStringField;
// xdwdsCustomersADDRESS: TStringField;
// cbWebPlate: TWebCheckBox;
// cbCorrugatedPlate: TWebCheckBox;
// edtSearch: TWebEdit;
// edtID: TWebEdit;
// btnConfirm: TWebButton;
// btnCancel: TWebButton;
// TMSFNCGrid1: TTMSFNCGrid;
// procedure cbCorrugatedPlateClick(Sender: TObject);
// procedure cbWebPlateClick(Sender: TObject);
// procedure btnConfirmClick(Sender: TObject);
// procedure btnCancelClick(Sender: TObject);
// procedure TMSFNCGrid1SelectedCell(Sender: TObject; ACol, ARow: Integer);
// procedure edtSearchChange(Sender: TObject);
// private
// [async] procedure GetCustomers();
// procedure PopulateGridManually;
// procedure ApplyFilter;
// public
// class function CreateForm(AElementID: string): TWebForm;
// end;
//
//var
// FAddOrder: TFAddOrder;
//
//implementation
//
//{$R *.dfm}
//
//
//class function TFAddOrder.CreateForm(AElementID: string): TWebForm;
//begin
// Application.CreateForm(TFAddOrder, AElementID, Result,
// procedure(AForm: TObject)
// begin
// with TFAddOrder(AForm) do
// begin
// GetCustomers();
// Console.Log('AddOrder form created and dynamic styles applied.');
// end;
// end
// );
//end;
//
//
//
//procedure TFAddOrder.edtSearchChange(Sender: TObject);
//begin
// ApplyFilter;
//end;
//
//
//[async] procedure TFAddOrder.GetCustomers();
//var
// xdcResponse: TXDataClientResponse;
// customerList: TJSObject;
//begin
// // Fetch data from XData service
// xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GetCustomers', []));
// customerList := TJSObject(xdcResponse.Result);
//
// // Load data into TXDataWebDataset
// xdwdsCustomers.Close;
// xdwdsCustomers.SetJsonData(customerList['data']);
// xdwdsCustomers.Open;
//
// // Manually populate the grid
// PopulateGridManually;
//end;
//
//
//procedure TFAddOrder.PopulateGridManually;
//var
// RowIndex: Integer;
//begin
// TMSFNCGrid1.BeginUpdate;
// try
// TMSFNCGrid1.Clear; // Clear any existing data
//
// // Set up column headers
// TMSFNCGrid1.ColumnCount := 3;
// TMSFNCGrid1.RowCount := 1;
// TMSFNCGrid1.Cells[0, 0] := 'ID';
// TMSFNCGrid1.Cells[1, 0] := 'Short Name';
// TMSFNCGrid1.Cells[2, 0] := 'Name';
//
//// TMSFNCGrid1.ColumnWidths[0] := 40;
//// TMSFNCGrid1.ColumnWidths[1] := 80;
//// TMSFNCGrid1.ColumnWidths[2] := 250;
//
// // 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('ID').AsString;
// TMSFNCGrid1.Cells[1, RowIndex] := xdwdsCustomers.FieldByName('SHORT_NAME').AsString;
// TMSFNCGrid1.Cells[2, RowIndex] := xdwdsCustomers.FieldByName('NAME').AsString;
//
// Inc(RowIndex);
// xdwdsCustomers.Next;
// end;
//
// finally
// TMSFNCGrid1.EndUpdate;
// end;
//end;
//
//
//procedure TFAddOrder.TMSFNCGrid1SelectedCell(Sender: TObject; ACol,
// ARow: Integer);
//begin
// edtID.Text := TMSFNCGrid1.Cells[0, ARow];
//end;
//
//
//procedure TFAddOrder.ApplyFilter;
//var
// fd: TTMSFNCGridFilterData;
// i: Integer;
// SearchText: string;
//begin
// SearchText := Trim(edtSearch.Text);
// Console.Log('Filter Applied: ' + SearchText);
//
// TMSFNCGrid1.RemoveFilter;
// TMSFNCGrid1.Filter.Clear;
//
// 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;
//
// if i > 0 then
// fd.Operation := foOR
// else
// fd.Operation := foNONE;
// end;
//
// TMSFNCGrid1.ApplyFilter;
//end;
//
//
//procedure TFAddOrder.cbCorrugatedPlateClick(Sender: TObject);
//begin
// cbWebPlate.Checked := False;
//end;
//
//
//procedure TFAddOrder.cbWebPlateClick(Sender: TObject);
//begin
// cbCorrugatedPlate.Checked := False;
//end;
//
//procedure TFAddOrder.btnConfirmClick(Sender: TObject);
//begin
// edtID.Text := '';
// window.location.reload(true);
//end;
//
//
//procedure TFAddOrder.btnCancelClick(Sender: TObject);
//var
// OrdersPanel: TJSHTMLElement;
//begin
// edtID.Text := '';
//
// // Get the panel element by its ID
// OrdersPanel := TJSHTMLElement(document.getElementById('pnl_orders'));
//
// // Hide the panel
// if Assigned(OrdersPanel) then
// begin
// OrdersPanel.style.setProperty('display', 'none');
//
// // Remove all child nodes of the container to clear the DOM
// while OrdersPanel.firstChild <> nil do
// OrdersPanel.removeChild(OrdersPanel.firstChild);
// end;
//
// // Free the current form instance to clean up resources
// Free;
//
// Console.Log('Panel hidden, DOM cleared, and form instance destroyed.');
//end;
//
//
//
//
//
//end.
// Customer Form accessed from the ccustomer header in the main form.
unit View.Customers; unit View.Customers;
interface interface
...@@ -41,6 +43,7 @@ type ...@@ -41,6 +43,7 @@ type
function GenerateSearchOptions(): string; function GenerateSearchOptions(): string;
procedure HideNotification(); procedure HideNotification();
procedure ShowNotification(Notification: string); procedure ShowNotification(Notification: string);
procedure ShowSelectCustomerForm();
var var
PageNumber: integer; PageNumber: integer;
...@@ -58,10 +61,41 @@ var ...@@ -58,10 +61,41 @@ var
implementation implementation
uses uses
XData.Model.Classes, View.Main; XData.Model.Classes, View.Main, View.SelectCustomer;
{$R *.dfm} {$R *.dfm}
procedure TFViewCustomers.ShowSelectCustomerForm();
// displays the add order pop-up so the user can choose a customer
var
newform: TFSelectCustomer;
begin
newform := TFSelectCustomer.CreateNew;
newform.Caption := 'Select Customer and Order Type';
newForm.Popup := True;
newForm.Border := fbDialog;
// used to manage Back button handling to close subform
window.location.hash := 'subform';
newform.ShowModal(
procedure(AValue: TModalResult)
begin
{if newform.confirm then
begin
if newform.cbCorrugatedPlate.Checked then
orderType := 'corrugated'
else if newform.cbWebPlate.Checked then
orderType := 'web'
else
orderType := 'cutting';
orderEntry('', newForm.DBID, 'ADD', orderType);
end; }
end
);
end;
Procedure TFViewCustomers.WebFormCreate(Sender: TObject); Procedure TFViewCustomers.WebFormCreate(Sender: TObject);
// Initializes important values: // Initializes important values:
// PageNumber: What page number the user is on IE 1: 1-10, 2: 11-20 etc // PageNumber: What page number the user is on IE 1: 1-10, 2: 11-20 etc
...@@ -113,6 +147,9 @@ begin ...@@ -113,6 +147,9 @@ begin
lblEntries.Caption := 'No entries found'; lblEntries.Caption := 'No entries found';
end end
else if (PageNumber * PageSize) < customerListLength then 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 begin
lblEntries.Caption := 'Showing entries ' + IntToStr((PageNumber - 1) * PageSize + 1) + lblEntries.Caption := 'Showing entries ' + IntToStr((PageNumber - 1) * PageSize + 1) +
' - ' + IntToStr(customerListLength) + ' - ' + IntToStr(customerListLength) +
...@@ -184,6 +221,7 @@ end; ...@@ -184,6 +221,7 @@ end;
procedure TFViewCustomers.btnAddCustomerClick(Sender: TObject); procedure TFViewCustomers.btnAddCustomerClick(Sender: TObject);
begin begin
//ShowSelectCustomerForm();
FViewMain.ViewAddCustomer('', ''); FViewMain.ViewAddCustomer('', '');
end; end;
...@@ -196,6 +234,7 @@ end; ...@@ -196,6 +234,7 @@ end;
procedure TFViewCustomers.GeneratePagination(TotalPages: Integer); procedure TFViewCustomers.GeneratePagination(TotalPages: Integer);
// Generates pagination for the table. // Generates pagination for the table.
// TotalPages: Total amount of pages generated by the search // TotalPages: Total amount of pages generated by the search
// This could definitely be improved.
var var
PaginationElement, PageItem, PageLink: TJSHTMLElement; PaginationElement, PageItem, PageLink: TJSHTMLElement;
I, Start, Finish: Integer; I, Start, Finish: Integer;
......
...@@ -24,17 +24,6 @@ object FViewEditUser: TFViewEditUser ...@@ -24,17 +24,6 @@ object FViewEditUser: TFViewEditUser
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
end end
object lblQB: TWebLabel
Left = 256
Top = 65
Width = 80
Height = 15
Caption = 'Quickbooks ID:'
Color = clBtnFace
ElementID = 'lblQB'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object WebLabel5: TWebLabel object WebLabel5: TWebLabel
Left = 284 Left = 284
Top = 8 Top = 8
...@@ -92,20 +81,21 @@ object FViewEditUser: TFViewEditUser ...@@ -92,20 +81,21 @@ object FViewEditUser: TFViewEditUser
object lblAccess: TWebLabel object lblAccess: TWebLabel
Left = 272 Left = 272
Top = 96 Top = 96
Width = 66 Width = 67
Height = 15 Height = 15
Caption = 'Access Type:' Caption = 'Access Type:'
ElementID = 'lblaccess' ElementID = 'lblaccess'
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
end end
object lblPerspective: TWebLabel object lblQB: TWebLabel
Left = 3 Left = 256
Top = 132 Top = 65
Width = 77 Width = 80
Height = 15 Height = 15
Caption = 'Perspective ID:' Caption = 'Quickbooks ID:'
ElementID = 'lblperspective' Color = clBtnFace
ElementID = 'lblQB'
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
end end
...@@ -256,16 +246,6 @@ object FViewEditUser: TFViewEditUser ...@@ -256,16 +246,6 @@ object FViewEditUser: TFViewEditUser
ParentFont = False ParentFont = False
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
end end
object edtQB: TWebEdit
Left = 348
Top = 62
Width = 121
Height = 22
ChildOrder = 7
ElementID = 'edtQB'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object edtRights: TWebEdit object edtRights: TWebEdit
Left = 96 Left = 96
Top = 93 Top = 93
...@@ -293,13 +273,13 @@ object FViewEditUser: TFViewEditUser ...@@ -293,13 +273,13 @@ object FViewEditUser: TFViewEditUser
'ALL' 'ALL'
'ACTIVE') 'ACTIVE')
end end
object edtPerspective: TWebEdit object edtQB: TWebEdit
Left = 96 Left = 346
Top = 129 Top = 62
Width = 121 Width = 121
Height = 22 Height = 22
ChildOrder = 23 ChildOrder = 7
ElementID = 'edtperspective' ElementID = 'edtQB'
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
end end
......
...@@ -48,15 +48,10 @@ ...@@ -48,15 +48,10 @@
</div> </div>
</form> </form>
<div class="row"> <div class="row">
<div class="col-sm"> <div class="col-6">
<label class='pe-2' style="font-weight: 700;font-size: 15px;" id="lblrights">System Rights:</label> <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%'/> <input id="edtrights" class= "form-control input-sm" width='50%'/>
</div> </div>
<div class="col-sm-6">
<label class='pe-2' style="font-weight: 700;font-size: 15px;" id="lblperspective">Perspective ID:</label>
<input id="edtperspective" class= "form-control input-sm" width='50%'/>
</div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-sm py-3"> <div class="col-sm py-3">
......
...@@ -14,7 +14,6 @@ type ...@@ -14,7 +14,6 @@ type
TFViewEditUser = class(TWebForm) TFViewEditUser = class(TWebForm)
WebLabel2: TWebLabel; WebLabel2: TWebLabel;
WebLabel3: TWebLabel; WebLabel3: TWebLabel;
lblQB: TWebLabel;
WebLabel5: TWebLabel; WebLabel5: TWebLabel;
WebLabel6: TWebLabel; WebLabel6: TWebLabel;
WebLabel7: TWebLabel; WebLabel7: TWebLabel;
...@@ -34,12 +33,11 @@ type ...@@ -34,12 +33,11 @@ type
lblactive: TWebLabel; lblactive: TWebLabel;
cbStatus: TWebCheckBox; cbStatus: TWebCheckBox;
lblRights: TWebLabel; lblRights: TWebLabel;
edtQB: TWebEdit;
edtRights: TWebEdit; edtRights: TWebEdit;
lblAccess: TWebLabel; lblAccess: TWebLabel;
cbAccess: TWebComboBox; cbAccess: TWebComboBox;
lblPerspective: TWebLabel; lblQB: TWebLabel;
edtPerspective: TWebEdit; edtQB: TWebEdit;
procedure WebFormCreate(Sender: TObject); procedure WebFormCreate(Sender: TObject);
procedure btnConfirmClick(Sender: TObject); procedure btnConfirmClick(Sender: TObject);
procedure btnCancelClick(Sender: TObject); procedure btnCancelClick(Sender: TObject);
...@@ -121,7 +119,6 @@ begin ...@@ -121,7 +119,6 @@ begin
'&access=' + cbAccess.Text + '&access=' + cbAccess.Text +
'&newuser=' + edtUsername.Text + '&newuser=' + edtUsername.Text +
'&rights=' + edtRights.Text + '&rights=' + edtRights.Text +
'&perspective=' + edtPerspective.Text +
'&QB=' + edtQB.Text; '&QB=' + edtQB.Text;
xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.AddUser', xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.AddUser',
...@@ -160,7 +157,6 @@ begin ...@@ -160,7 +157,6 @@ begin
'&access=' + cbAccess.Text + '&access=' + cbAccess.Text +
'&newuser=' + edtUsername.Text + '&newuser=' + edtUsername.Text +
'&rights=' + edtRights.Text + '&rights=' + edtRights.Text +
'&perspective=' + edtPerspective.Text +
'&QB=' + edtQB.Text; '&QB=' + edtQB.Text;
console.log(editOptions); console.log(editOptions);
...@@ -215,7 +211,6 @@ begin ...@@ -215,7 +211,6 @@ begin
edtQB.Text := QB; edtQB.Text := QB;
if Status = 'ACTIVE' then if Status = 'ACTIVE' then
cbStatus.checked := true; cbStatus.checked := true;
edtPerspective.Text := Perspective
end; end;
procedure TFViewEditUser.WebTimer1Timer(Sender: TObject); procedure TFViewEditUser.WebTimer1Timer(Sender: TObject);
......
...@@ -1226,6 +1226,18 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated ...@@ -1226,6 +1226,18 @@ object FOrderEntryCorrugated: TFOrderEntryCorrugated
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
OnClick = btnAddClick OnClick = btnAddClick
end end
object WebButton2: TWebButton
Left = 186
Top = 429
Width = 96
Height = 25
Caption = 'Add Address'
ChildOrder = 85
ElementID = 'btnaddaddress'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnClick = WebButton2Click
end
object XDataWebClient1: TXDataWebClient object XDataWebClient1: TXDataWebClient
Connection = DMConnection.ApiConnection Connection = DMConnection.ApiConnection
Left = 1014 Left = 1014
......
...@@ -107,6 +107,9 @@ ...@@ -107,6 +107,9 @@
<div class="invalid-feedback" style="font-size: 15px;"> <div class="invalid-feedback" style="font-size: 15px;">
Please Provide a Ship To Address. Please Provide a Ship To Address.
</div> </div>
<div class="mt-2">
<button id="btnaddaddress" class="btn btn-primary btn-sm">Add Address</button>
</div>
</div> </div>
<div class="col-auto"> <div class="col-auto">
<label for="wdbe_first_name" style="font-weight: 700; font-size: 15px;" class="form-label mt-2">PO Number:</label> <label for="wdbe_first_name" style="font-weight: 700; font-size: 15px;" class="form-label mt-2">PO Number:</label>
......
...@@ -202,6 +202,7 @@ type ...@@ -202,6 +202,7 @@ type
tmrReturn: TWebTimer; tmrReturn: TWebTimer;
btnEdit: TWebButton; btnEdit: TWebButton;
btnAdd: TWebButton; btnAdd: TWebButton;
WebButton2: TWebButton;
procedure WebFormCreate(Sender: TObject); procedure WebFormCreate(Sender: TObject);
procedure HideNotification(); procedure HideNotification();
procedure ShowNotification(Notification: string); procedure ShowNotification(Notification: string);
...@@ -238,6 +239,9 @@ type ...@@ -238,6 +239,9 @@ type
procedure btnAddClick(Sender: TObject); procedure btnAddClick(Sender: TObject);
procedure xdwdsQBItemAfterEdit(DataSet: TDataSet); procedure xdwdsQBItemAfterEdit(DataSet: TDataSet);
procedure ViewMode(); procedure ViewMode();
procedure WebButton2Click(Sender: TObject);
procedure ShowAddAddressForm();
[async] procedure SendAddressToServer(AddressJSON: TJSONObject);
private private
FAgencyCode: string; FAgencyCode: string;
FCurrentReportType: string; FCurrentReportType: string;
...@@ -260,9 +264,12 @@ implementation ...@@ -260,9 +264,12 @@ implementation
{$R *.dfm} {$R *.dfm}
uses uses
View.Home, View.Main, View.AddOrder; View.Home, View.Main, View.AddOrder, View.AddAddress;
procedure TFOrderEntryCorrugated.sendOrderToServer(); 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
// Booleans it should work
var var
colorList: TJSONArray; colorList: TJSONArray;
container: TJSElement; container: TJSElement;
...@@ -654,6 +661,73 @@ begin ...@@ -654,6 +661,73 @@ begin
addColorRow('','','',''); addColorRow('','','','');
end; end;
procedure TFOrderEntryCorrugated.WebButton2Click(Sender: TObject);
begin
ShowAddAddressForm();
end;
procedure TFOrderEntryCorrugated.SendAddressToServer(AddressJSON: TJSONObject);
var
Response: TXDataClientResponse;
notification: TJSObject;
begin
Response := await(XDataWebClient1.RawInvokeAsync('ILookupService.AddShippingAddress',
[AddressJSON.ToString]));
notification := TJSObject(Response.Result);
ShowNotification(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
newform: TFViewAddAddress;
AddressJSON: TJSONObject;
ship_block: string;
begin
newform := TFViewAddAddress.CreateNew;
newform.Caption := 'Input Shipping Information';
newForm.Popup := True;
newForm.Border := fbDialog;
// used to manage Back button handling to close subform
window.location.hash := 'subform';
newform.ShowModal(
procedure(AValue: TModalResult)
var
searchOptions: string;
begin
if newform.confirm then
begin
AddressJSON := TJSONObject.Create;
AddressJSON.AddPair('address', newform.edtAddress.Text);
AddressJSON.AddPair('city', newform.edtCity.Text);
AddressJSON.AddPair('state', newform.edtState.Text);
AddressJSON.AddPair('zip', newform.edtZip.Text);
AddressJSON.AddPair('contact', newform.edtContact.Text);
AddressJSON.AddPair('customer_id', customerID);
ship_block := newform.edtFirstLine.Text + slinebreak +
edtCompanyName.Text + slinebreak +
newform.edtContact.Text + slinebreak +
newform.edtAddress.Text + slinebreak +
newform.edtCity.Text + ', ' + newform.edtState.Text + ' ' + newform.edtZip.Text;
AddressJSON.AddPair('ship_block', ship_block);
AddressJSON.AddPair('mode', 'ADD');
sendAddressToServer(AddressJSON);
end;
end
);
end;
procedure TFOrderEntryCorrugated.btnAddClick(Sender: TObject); procedure TFOrderEntryCorrugated.btnAddClick(Sender: TObject);
var var
newform: TFAddOrder; newform: TFAddOrder;
......
...@@ -386,6 +386,18 @@ object FOrderEntryCuttingDie: TFOrderEntryCuttingDie ...@@ -386,6 +386,18 @@ object FOrderEntryCuttingDie: TFOrderEntryCuttingDie
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
OnClick = btnAddClick OnClick = btnAddClick
end end
object WebButton2: TWebButton
Left = 186
Top = 429
Width = 96
Height = 25
Caption = 'Add Address'
ChildOrder = 85
ElementID = 'btnaddaddress'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnClick = WebButton2Click
end
object WebDataSource1: TWebDataSource object WebDataSource1: TWebDataSource
DataSet = XDataWebDataSet1 DataSet = XDataWebDataSet1
Left = 22 Left = 22
...@@ -470,13 +482,13 @@ object FOrderEntryCuttingDie: TFOrderEntryCuttingDie ...@@ -470,13 +482,13 @@ object FOrderEntryCuttingDie: TFOrderEntryCuttingDie
end end
object wdsShipTo: TWebDataSource object wdsShipTo: TWebDataSource
DataSet = xdwdsShipTo DataSet = xdwdsShipTo
Left = 212 Left = 302
Top = 436 Top = 418
end end
object xdwdsShipTo: TXDataWebDataSet object xdwdsShipTo: TXDataWebDataSet
AfterEdit = xdwdsShipToAfterEdit AfterEdit = xdwdsShipToAfterEdit
Left = 270 Left = 288
Top = 436 Top = 370
object xdwdsShipToADDRESS: TStringField object xdwdsShipToADDRESS: TStringField
FieldName = 'ADDRESS' FieldName = 'ADDRESS'
end end
......
...@@ -52,7 +52,7 @@ ...@@ -52,7 +52,7 @@
</div> </div>
</div> </div>
<div class="col-auto"> <div class="col-auto">
<label for="wdbe_first_name" style="font-weight: 700; font-size: 15px;" class="form-label mt-2">>In Quickbooks?:</label> <label for="wdbe_first_name" style="font-weight: 700; font-size: 15px;" class="form-label mt-2">In Quickbooks?:</label>
<input id="edtinquickbooks"type="text" class="form-control" style="width: 150px"/> <input id="edtinquickbooks"type="text" class="form-control" style="width: 150px"/>
</div> </div>
</div> </div>
...@@ -103,6 +103,9 @@ ...@@ -103,6 +103,9 @@
<div class="invalid-feedback" style="font-size: 15px;"> <div class="invalid-feedback" style="font-size: 15px;">
Please Provide a Ship To Address. Please Provide a Ship To Address.
</div> </div>
<div class="mt-2">
<button id="btnaddaddress" class="btn btn-primary btn-sm">Add Address</button>
</div>
</div> </div>
<div class="col-auto"> <div class="col-auto">
<label for="wdbe_first_name" style="font-weight: 700; font-size: 15px;" class="form-label mt-2">PO Number:</label> <label for="wdbe_first_name" style="font-weight: 700; font-size: 15px;" class="form-label mt-2">PO Number:</label>
......
...@@ -73,6 +73,7 @@ type ...@@ -73,6 +73,7 @@ type
tmrReturn: TWebTimer; tmrReturn: TWebTimer;
btnEdit: TWebButton; btnEdit: TWebButton;
btnAdd: TWebButton; btnAdd: TWebButton;
WebButton2: TWebButton;
procedure btnSaveClick(Sender: TObject); procedure btnSaveClick(Sender: TObject);
procedure btnCancelClick(Sender: TObject); procedure btnCancelClick(Sender: TObject);
procedure WebFormCreate(Sender: TObject); procedure WebFormCreate(Sender: TObject);
...@@ -101,6 +102,9 @@ type ...@@ -101,6 +102,9 @@ type
procedure dtpOrderDateChange(Sender: TObject); procedure dtpOrderDateChange(Sender: TObject);
procedure btnEditClick(Sender: TObject); procedure btnEditClick(Sender: TObject);
procedure ViewMode(); procedure ViewMode();
procedure WebButton2Click(Sender: TObject);
procedure ShowAddAddressForm();
[async] procedure SendAddressToServer(AddressJSON: TJSONObject);
private private
FAgencyCode: string; FAgencyCode: string;
FCurrentReportType: string; FCurrentReportType: string;
...@@ -121,7 +125,73 @@ implementation ...@@ -121,7 +125,73 @@ implementation
{$R *.dfm} {$R *.dfm}
uses uses
View.Home, View.Main, View.AddOrder; View.Home, View.Main, View.AddOrder, View.AddAddress;
procedure TFOrderEntryCuttingDie.WebButton2Click(Sender: TObject);
begin
ShowAddAddressForm();
end;
procedure TFOrderEntryCuttingDie.SendAddressToServer(AddressJSON: TJSONObject);
var
Response: TXDataClientResponse;
notification: TJSObject;
begin
Response := await(XDataWebClient1.RawInvokeAsync('ILookupService.AddShippingAddress',
[AddressJSON.ToString]));
notification := TJSObject(Response.Result);
ShowNotification(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
newform: TFViewAddAddress;
AddressJSON: TJSONObject;
ship_block: string;
begin
newform := TFViewAddAddress.CreateNew;
newform.Caption := 'Shipping Information';
newForm.Popup := True;
newForm.Border := fbDialog;
// used to manage Back button handling to close subform
window.location.hash := 'subform';
newform.ShowModal(
procedure(AValue: TModalResult)
var
searchOptions: string;
begin
if newform.confirm then
begin
AddressJSON := TJSONObject.Create;
AddressJSON.AddPair('address', newform.edtAddress.Text);
AddressJSON.AddPair('city', newform.edtCity.Text);
AddressJSON.AddPair('state', newform.edtState.Text);
AddressJSON.AddPair('zip', newform.edtZip.Text);
AddressJSON.AddPair('contact', newform.edtContact.Text);
AddressJSON.AddPair('customer_id', customerID);
ship_block := newform.edtFirstLine.Text + slinebreak +
edtCompanyName.Text + slinebreak +
newform.edtContact.Text + slinebreak +
newform.edtAddress.Text + slinebreak +
newform.edtCity.Text + ', ' + newform.edtState.Text + ' ' + newform.edtZip.Text;
AddressJSON.AddPair('ship_block', ship_block);
AddressJSON.AddPair('mode', 'ADD');
sendAddressToServer(AddressJSON);
end;
end
);
end;
function TFOrderEntryCuttingDie.VerifyOrder: Boolean; function TFOrderEntryCuttingDie.VerifyOrder: Boolean;
var var
......
...@@ -1284,6 +1284,18 @@ object FOrderEntryWeb: TFOrderEntryWeb ...@@ -1284,6 +1284,18 @@ object FOrderEntryWeb: TFOrderEntryWeb
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
OnClick = btnAddClick OnClick = btnAddClick
end end
object WebButton2: TWebButton
Left = 174
Top = 372
Width = 96
Height = 25
Caption = 'Add Address'
ChildOrder = 85
ElementID = 'btnaddaddress'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnClick = WebButton2Click
end
object XDataWebClient1: TXDataWebClient object XDataWebClient1: TXDataWebClient
Connection = DMConnection.ApiConnection Connection = DMConnection.ApiConnection
Left = 160 Left = 160
......
...@@ -103,6 +103,9 @@ ...@@ -103,6 +103,9 @@
<div class="invalid-feedback" style="font-size: 15px;"> <div class="invalid-feedback" style="font-size: 15px;">
Please Provide a Ship To Address. Please Provide a Ship To Address.
</div> </div>
<div class="mt-2">
<button id="btnaddaddress" class="btn btn-primary btn-sm">Add Address</button>
</div>
</div> </div>
<div class="col-auto"> <div class="col-auto">
<label style="font-weight: 700; font-size: 15px;" class="form-label mt-2">PO Number:</label> <label style="font-weight: 700; font-size: 15px;" class="form-label mt-2">PO Number:</label>
......
...@@ -206,6 +206,7 @@ type ...@@ -206,6 +206,7 @@ type
tmrReturn: TWebTimer; tmrReturn: TWebTimer;
btnEdit: TWebButton; btnEdit: TWebButton;
btnAdd: TWebButton; btnAdd: TWebButton;
WebButton2: TWebButton;
procedure WebFormCreate(Sender: TObject); procedure WebFormCreate(Sender: TObject);
procedure HideNotification(); procedure HideNotification();
procedure ShowNotification(Notification: string); procedure ShowNotification(Notification: string);
...@@ -235,6 +236,9 @@ type ...@@ -235,6 +236,9 @@ type
procedure XDataWebDataSet1AfterEdit(DataSet: TDataSet); procedure XDataWebDataSet1AfterEdit(DataSet: TDataSet);
procedure dtpOrderDateChange(Sender: TObject); procedure dtpOrderDateChange(Sender: TObject);
procedure ViewMode(); procedure ViewMode();
procedure WebButton2Click(Sender: TObject);
procedure ShowAddAddressForm();
[async] procedure SendAddressToServer(AddressJSON: TJSONObject);
private private
FAgencyCode: string; FAgencyCode: string;
FCurrentReportType: string; FCurrentReportType: string;
...@@ -256,7 +260,73 @@ implementation ...@@ -256,7 +260,73 @@ implementation
{$R *.dfm} {$R *.dfm}
uses uses
View.Home, View.Main, View.AddOrder; View.Home, View.Main, View.AddOrder, View.AddAddress;
procedure TFOrderEntryWeb.WebButton2Click(Sender: TObject);
begin
ShowAddAddressForm();
end;
procedure TFOrderEntryWeb.SendAddressToServer(AddressJSON: TJSONObject);
var
Response: TXDataClientResponse;
notification: TJSObject;
begin
Response := await(XDataWebClient1.RawInvokeAsync('ILookupService.AddShippingAddress',
[AddressJSON.ToString]));
notification := TJSObject(Response.Result);
ShowNotification(string(notification['status']));
xdwdsShipTo.Close;
xdwdsShipTo.SetJSONData(notification['ADDRESS']);
xdwdsShipTo.Open;
end;
procedure TFOrderEntryWeb.ShowAddAddressForm;
// displays the search pop-up that allows the user to filter the order list
var
newform: TFViewAddAddress;
AddressJSON: TJSONObject;
ship_block: string;
begin
newform := TFViewAddAddress.CreateNew;
newform.Caption := 'Input Shipping Information';
newForm.Popup := True;
newForm.Border := fbDialog;
// used to manage Back button handling to close subform
window.location.hash := 'subform';
newform.ShowModal(
procedure(AValue: TModalResult)
var
searchOptions: string;
begin
if newform.confirm then
begin
AddressJSON := TJSONObject.Create;
AddressJSON.AddPair('address', newform.edtAddress.Text);
AddressJSON.AddPair('city', newform.edtCity.Text);
AddressJSON.AddPair('state', newform.edtState.Text);
AddressJSON.AddPair('zip', newform.edtZip.Text);
AddressJSON.AddPair('contact', newform.edtContact.Text);
AddressJSON.AddPair('customer_id', customerID);
ship_block := newform.edtFirstLine.Text + slinebreak +
edtCompanyName.Text + slinebreak +
newform.edtContact.Text + slinebreak +
newform.edtAddress.Text + slinebreak +
newform.edtCity.Text + ', ' + newform.edtState.Text + ' ' + newform.edtZip.Text;
AddressJSON.AddPair('ship_block', ship_block);
AddressJSON.AddPair('mode', 'ADD');
sendAddressToServer(AddressJSON);
end;
end
);
end;
procedure TFOrderEntryWeb.btnSaveClick(Sender: TObject); procedure TFOrderEntryWeb.btnSaveClick(Sender: TObject);
begin begin
......
...@@ -735,7 +735,7 @@ end; ...@@ -735,7 +735,7 @@ end;
procedure TFViewOrders.btnSearchClick(Sender: TObject); procedure TFViewOrders.btnSearchClick(Sender: TObject);
var var
filterSection: TJSHTMLElement; filterSection: TJSHTMLElement;
begin begin
ShowSearchForm(); ShowSearchForm();
end; end;
......
object FAddOrder: TFAddOrder object FSelectCustomer: TFSelectCustomer
Width = 894 Width = 765
Height = 633 Height = 480
Align = alClient OnCreate = WebFormCreate
Font.Charset = ANSI_CHARSET
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Arial'
Font.Style = []
ParentFont = False
OnShow = WebFormShow OnShow = WebFormShow
object cbWebPlate: TWebCheckBox object WebLabel1: TWebLabel
Left = 172 Left = 4
Top = 55 Top = 81
Width = 113 Width = 95
Height = 22 Height = 15
Caption = 'Web Plate' Caption = 'Search Customers'
ChildOrder = 5
HeightStyle = ssAuto
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
WidthStyle = ssAuto
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
OnClick = cbWebPlateClick
end end
object cbCorrugatedPlate: TWebCheckBox object WebLabel2: TWebLabel
Left = 40 Left = 143
Top = 55 Top = 81
Width = 113 Width = 113
Height = 22 Height = 15
Caption = 'Corrugated Plate' Caption = 'Selected Customer ID'
Checked = True
ChildOrder = 5
HeightStyle = ssAuto
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
State = cbChecked
WidthStyle = ssAuto
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
OnClick = cbCorrugatedPlateClick
end end
object edtSearch: TWebEdit object edtSearch: TWebEdit
Left = 306 Left = 4
Top = 55 Top = 102
Width = 146 Width = 121
Height = 22 Height = 22
ChildOrder = 8 ChildOrder = 2
HeightStyle = ssAuto
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
WidthStyle = ssAuto
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
OnChange = edtSearchChange
end end
object edtID: TWebEdit object edtID: TWebEdit
Left = 475 Left = 143
Top = 55 Top = 102
Width = 121 Width = 142
Height = 22 Height = 22
ChildOrder = 8 ChildOrder = 1
HeightStyle = ssAuto Enabled = False
HeightPercent = 100.000000000000000000
WidthStyle = ssAuto
WidthPercent = 100.000000000000000000
end
object btnConfirm: TWebButton
Left = 612
Top = 52
Width = 96
Height = 25
Caption = 'Confirm'
ChildOrder = 9
HeightStyle = ssAuto
HeightPercent = 100.000000000000000000 HeightPercent = 100.000000000000000000
WidthStyle = ssAuto
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
OnClick = btnConfirmClick
end
object btnCancel: TWebButton
Left = 730
Top = 52
Width = 96
Height = 25
Caption = 'Cancel'
ChildOrder = 9
HeightStyle = ssAuto
HeightPercent = 100.000000000000000000
WidthStyle = ssAuto
WidthPercent = 100.000000000000000000
OnClick = btnCancelClick
end end
object TMSFNCGrid1: TTMSFNCGrid object TMSFNCGrid1: TTMSFNCGrid
Left = 0 Left = 0
Top = 220 Top = 163
Width = 894 Width = 765
Height = 413 Height = 317
Align = alBottom Align = alBottom
ParentDoubleBuffered = False ParentDoubleBuffered = False
DoubleBuffered = True DoubleBuffered = True
TabOrder = 6 TabOrder = 2
DefaultRowHeight = 40.000000000000000000 DefaultRowHeight = 40.000000000000000000
FixedColumns = 0 FixedColumns = 0
ColumnCount = 3 ColumnCount = 4
Options.Bands.Enabled = True Options.Bands.Enabled = True
Options.ColumnSize.Stretch = True Options.ColumnSize.Stretch = True
Options.Editing.CalcFormat = '%g' Options.Editing.CalcFormat = '%g'
...@@ -121,7 +75,7 @@ object FAddOrder: TFAddOrder ...@@ -121,7 +75,7 @@ object FAddOrder: TFAddOrder
Font.Name = 'Segoe UI' Font.Name = 'Segoe UI'
Font.Style = [] Font.Style = []
ID = '' ID = ''
Width = 327.000000000000000000 Width = 90.000000000000000000
end end
item item
BorderWidth = 1 BorderWidth = 1
...@@ -136,7 +90,7 @@ object FAddOrder: TFAddOrder ...@@ -136,7 +90,7 @@ object FAddOrder: TFAddOrder
Font.Name = 'Segoe UI' Font.Name = 'Segoe UI'
Font.Style = [] Font.Style = []
ID = '' ID = ''
Width = 327.000000000000000000 Width = 150.000000000000000000
end end
item item
BorderWidth = 1 BorderWidth = 1
...@@ -151,7 +105,37 @@ object FAddOrder: TFAddOrder ...@@ -151,7 +105,37 @@ object FAddOrder: TFAddOrder
Font.Name = 'Segoe UI' Font.Name = 'Segoe UI'
Font.Style = [] Font.Style = []
ID = '' ID = ''
Width = 239.000000000000000000 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 = 306.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> end>
DefaultFont.Charset = DEFAULT_CHARSET DefaultFont.Charset = DEFAULT_CHARSET
DefaultFont.Color = clWindowText DefaultFont.Color = clWindowText
...@@ -211,30 +195,110 @@ object FAddOrder: TFAddOrder ...@@ -211,30 +195,110 @@ object FAddOrder: TFAddOrder
LeftCol = 0 LeftCol = 0
ScrollMode = scmItemScrolling ScrollMode = scmItemScrolling
DesignTimeSampleData = True DesignTimeSampleData = True
ExplicitWidth = 982 ExplicitLeft = -231
ExplicitTop = 160
ExplicitWidth = 871
end
object cbCorrugatedPlate: TWebCheckBox
Left = 4
Top = 49
Width = 113
Height = 22
Caption = 'Corrugated Plate'
ChildOrder = 3
ElementID = 'cbcorrugatedplate'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object cbWebPlate: TWebCheckBox
Left = 134
Top = 49
Width = 83
Height = 22
Caption = 'Web Plate'
ChildOrder = 3
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object btnCancel: TWebButton
Left = 436
Top = 105
Width = 96
Height = 25
Caption = 'Cancel'
ChildOrder = 5
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object btnConfirm: TWebButton
Left = 328
Top = 105
Width = 96
Height = 25
Caption = 'Select'
ChildOrder = 5
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object cbCuttingDie: TWebCheckBox
Left = 239
Top = 49
Width = 83
Height = 22
Caption = 'Cutting Die'
ChildOrder = 3
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
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 end
object XDataWebClient1: TXDataWebClient object XDataWebClient1: TXDataWebClient
Connection = DMConnection.ApiConnection Connection = DMConnection.ApiConnection
Left = 370 Left = 560
Top = 562 Top = 61
end end
object xdwdsCustomers: TXDataWebDataSet object xdwdsCustomers: TXDataWebDataSet
Connection = DMConnection.ApiConnection Connection = DMConnection.ApiConnection
Left = 206 Left = 70
Top = 564 Top = 129
object xdwdsCustomersID: TIntegerField object xdwdsCustomersBillAddr: TStringField
FieldName = 'ID' FieldName = 'BillAddr'
end
object xdwdsCustomersCompanyName: TStringField
FieldName = 'CompanyName'
end
object xdwdsCustomersId: TStringField
FieldName = 'Id'
end end
object xdwdsCustomersNAME: TStringField object xdwdsCustomersPrimaryPhone: TStringField
FieldName = 'NAME' FieldName = 'PrimaryPhone'
end end
object xdwdsCustomersSHORT_NAME: TStringField object xdwdsCustomersShipAddr: TStringField
FieldName = 'SHORT_NAME' FieldName = 'ShipAddr'
end end
end end
object wdsCustomers: TWebDataSource object wdsCustomers: TWebDataSource
DataSet = xdwdsCustomers DataSet = xdwdsCustomers
Left = 38 Left = 18
Top = 562 Top = 127
end end
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.SelectCustomer;
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;
type
TFSelectCustomer = class(TWebForm)
WebLabel1: TWebLabel;
WebLabel2: TWebLabel;
edtSearch: TWebEdit;
edtID: TWebEdit;
TMSFNCGrid1: TTMSFNCGrid;
cbCorrugatedPlate: TWebCheckBox;
cbWebPlate: TWebCheckBox;
btnCancel: TWebButton;
btnConfirm: TWebButton;
cbCuttingDie: TWebCheckBox;
edtNotification: TWebEdit;
XDataWebClient1: TXDataWebClient;
xdwdsCustomers: TXDataWebDataSet;
wdsCustomers: TWebDataSource;
xdwdsCustomersBillAddr: TStringField;
xdwdsCustomersCompanyName: TStringField;
xdwdsCustomersId: TStringField;
xdwdsCustomersPrimaryPhone: TStringField;
xdwdsCustomersShipAddr: TStringField;
procedure WebFormCreate(Sender: TObject);
procedure WebFormShow(Sender: TObject);
private
{ Private declarations }
[Async] procedure GetCustomers();
procedure PopulateGridManually();
public
{ Public declarations }
end;
var
FSelectCustomer: TFSelectCustomer;
implementation
{$R *.dfm
}
procedure TFSelectCustomer.WebFormCreate(Sender: TObject);
begin
if not DMConnection.ApiConnection.Connected then
begin
DMConnection.ApiConnection.OpenAsync;
console.log('report requirements connection open')
end;
end;
procedure TFSelectCustomer.WebFormShow(Sender: TObject);
begin
getCustomers();
end;
[async] procedure TFSelectCustomer.getCustomers();
// retrieves customer list from server
var
xdcResponse: TXDataClientResponse;
customerList: TJSObject;
i: integer;
begin
// 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;
console.log(customerList);
// Manually populate the grid
PopulateGridManually;
end;
procedure TFSelectCustomer.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] := 'Quickbooks ID';
TMSFNCGrid1.Cells[1, 0] := 'Customer ID';
TMSFNCGrid1.Cells[2, 0] := 'Customer Name';
TMSFNCGrid1.Cells[3, 0] := 'Address';
// 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('Id').AsString;
// TMSFNCGrid1.Cells[1, RowIndex] := xdwdsCustomers.FieldByName('SHORT_NAME').AsString;
TMSFNCGrid1.Cells[2, RowIndex] := xdwdsCustomers.FieldByName('CompanyName').AsString;
TMSFNCGrid1.Cells[3, RowIndex] := xdwdsCustomers.FieldByName('BillAddr').AsString;
Inc(RowIndex);
xdwdsCustomers.Next;
end;
finally
TMSFNCGrid1.EndUpdate;
end;
end;
end.
\ No newline at end of file
...@@ -28,7 +28,6 @@ ...@@ -28,7 +28,6 @@
<th scope="col">Email Address</th> <th scope="col">Email Address</th>
<th scope="col">Access Type</th> <th scope="col">Access Type</th>
<th scope="col">System Rights</th> <th scope="col">System Rights</th>
<th scope="col">Perspective ID</th>
<th scope="col">QB ID</th> <th scope="col">QB ID</th>
<th scope="col">Edit</th> <th scope="col">Edit</th>
</tr> </tr>
......
...@@ -433,12 +433,6 @@ begin ...@@ -433,12 +433,6 @@ begin
Cell.innerText := IntToStr(Rights); Cell.innerText := IntToStr(Rights);
NewRow.appendChild(Cell); NewRow.appendChild(Cell);
// Perspective ID Cell
Cell := TJSHTMLElement(document.createElement('td'));
Cell.setAttribute('data-label', 'Perspective ID');
Cell.innerText := PID;
NewRow.appendChild(Cell);
// QB ID Cell // QB ID Cell
Cell := TJSHTMLElement(document.createElement('td')); Cell := TJSHTMLElement(document.createElement('td'));
Cell.setAttribute('data-label', 'QB ID'); Cell.setAttribute('data-label', 'QB ID');
......
program webKGOrders; program webKGOrders;
uses uses
...@@ -25,7 +26,9 @@ uses ...@@ -25,7 +26,9 @@ uses
View.OrderEntryCuttingDie in 'View.OrderEntryCuttingDie.pas' {FOrderEntryCuttingDie: TWebForm} {*.html}, View.OrderEntryCuttingDie in 'View.OrderEntryCuttingDie.pas' {FOrderEntryCuttingDie: TWebForm} {*.html},
View.OrderEntryWeb in 'View.OrderEntryWeb.pas' {FOrderEntryWeb: TWebForm} {*.html}, View.OrderEntryWeb in 'View.OrderEntryWeb.pas' {FOrderEntryWeb: TWebForm} {*.html},
View.Customers in 'View.Customers.pas' {FViewCustomers: TWebForm} {*.html}, View.Customers in 'View.Customers.pas' {FViewCustomers: TWebForm} {*.html},
AddCustomer in 'AddCustomer.pas' {FViewAddCustomer: TWebForm} {*.html}; 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};
{$R *.res} {$R *.res}
......
...@@ -196,6 +196,16 @@ ...@@ -196,6 +196,16 @@
<FormType>dfm</FormType> <FormType>dfm</FormType>
<DesignClass>TWebForm</DesignClass> <DesignClass>TWebForm</DesignClass>
</DCCReference> </DCCReference>
<DCCReference Include="View.AddAddress.pas">
<Form>FViewAddAddress</Form>
<FormType>dfm</FormType>
<DesignClass>TWebForm</DesignClass>
</DCCReference>
<DCCReference Include="View.SelectCustomer.pas">
<Form>FSelectCustomer</Form>
<FormType>dfm</FormType>
<DesignClass>TWebForm</DesignClass>
</DCCReference>
<None Include="index.html"/> <None Include="index.html"/>
<None Include="css\app.css"/> <None Include="css\app.css"/>
<None Include="config\config.json"/> <None Include="config\config.json"/>
......
unit QBService;
interface
uses
XData.Service.Common,
Aurelius.Mapping.Attributes,
System.JSON,
System.Generics.Collections,
System.Classes;
type
[ServiceContract]
IQBService = interface(IInvokable)
['{D119A273-0644-484B-B75E-B6FE57BB422C}']
[HttpGet] function getCustomers(): TJSONArray;
end;
implementation
initialization
RegisterServiceType(TypeInfo(IQBService));
end.
unit QBServiceImplementation;
interface
uses
XData.Server.Module,
XData.Service.Common,
Api.Database, Data.DB, frxClass, frxExportPDF, JS, System.Hash, System.JSON,
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, MemDS, DBAccess, Uni,
hyiedefs, hyieutils, iexBitmaps, iesettings, iexLayers, iexRulers,
iexToolbars, iexUserInteractions, imageenio, imageenproc, QuickRpt, QRCtrls,
dbimageen, Vcl.ExtCtrls, ieview, imageenview, IdBaseComponent, IdComponent,
IdTCPConnection, IdTCPClient, IdExplicitTLSClientServerBase, IdFTP,
iexProcEffects, frCoreClasses, Common.Logging,
DateUtils, QBService, WEBLib.REST, WEBLib.WebTools,System.Net.HttpClient,
System.Net.URLClient, System.Net.HttpClientComponent, System.netencoding,
IdHTTP, IdSSLOpenSSL, IdSSLOpenSSLHeaders, System.IniFiles, REST.Client, REST.Types;
type
[ServiceImplementation]
TQBService = class(TInterfacedObject, IQBService)
private
procedure SaveTokens(AccessToken, RefreshToken: string);
function getCustomers(): TJSONArray;
function refreshAccessToken(): string;
var
AccessToken,RefreshToken,CompanyID,Client,Secret: string;
LastRefresh: TDateTime;
end;
implementation
function TQBService.getCustomers: TJSONArray;
var
restClient: TRESTClient;
restRequest: TRESTRequest;
restResponse: TRESTResponse;
param: TRESTRequestParameter;
res: string;
jsValue: TJSONValue;
Customer: TJSONValue;
jsObj: TJSONObject;
CustomerList: TJSONArray;
pair: TJSONPair;
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/<realmId>/customer/<customerId>
res := '/v3/company/' + companyid + '/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;
jsValue := restResponse.JSONValue;
jsObj := TJSONObject(jsValue);
CustomerList := TJSONArray( TJSONObject( jsObj.GetValue('QueryResponse') ).GetValue('Customer')) ;
result := CustomerList;
// LoadJSONArray( CustomerList );
restClient.Free;
restRequest.Free;
restResponse.Free;
end;
function TQBService.RefreshAccessToken: string;
// Refresh Token changes so make sure to save refresh token.
var
IdHTTP: TIdHTTP;
SSLIO: TIdSSLIOHandlerSocketOpenSSL;
RequestStream: TStringStream;
EncodedAuth, EncodedAuth2, PostData, response: string;
f: TStringList;
fi: string;
JSObj: TJSONObject;
iniFile: TIniFile;
Encoder: TBase64Encoding;
begin
// 1. Encode credentials (same as working Postman request)
// TNetEncoding.Base64.Encode adds a new line every 72 chars, this stops that
Encoder := TBase64Encoding.Create(0);
if( (Client = '') or (Secret = '') ) then
begin
Logger.Log(1, 'Missing Client ID or Client Secret in INI File');
Exit();
end;
EncodedAuth := Encoder.Encode(Client + ':' + Secret);
if RefreshToken = '' then
begin
Logger.Log(3, 'Missing Refresh Token, Please Manually Get a New One and Store in INI File');
Exit();
end;
// 2. Prepare POST data (EXACTLY as in Postman)
PostData := 'grant_type=refresh_token&refresh_token=' + RefreshToken;
// 3. Configure HTTP client
IdHTTP := TIdHTTP.Create(nil);
SSLIO := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
try
// Force TLS 1.2
SSLIO.SSLOptions.Method := sslvTLSv1_2;
SSLIO.SSLOptions.SSLVersions := [sslvTLSv1_2];
IdHTTP.IOHandler := SSLIO;
// Set headers (EXACT match with Postman)
IdHTTP.Request.ContentType := 'application/x-www-form-urlencoded';
IdHTTP.Request.Accept := 'application/json';
IdHTTP.Request.CustomHeaders.AddValue('Authorization', 'Basic ' + EncodedAuth);
// 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);
JSObj := TJSONObject.ParseJSONValue(response) as TJSONObject;
RefreshToken := JSObj.GetValue('refresh_token').ToString.Trim(['"']);
AccessToken := JSObj.GetValue('access_token').ToString.Trim(['"']);
SaveTokens(AccessToken, RefreshToken);
Result := AccessToken;
Logger.Log(1, 'qbAPI - Tokens Successfully Saved');
except
on E: EIdHTTPProtocolException do
// Memo2.Lines.Add('Error: ' + E.Message + #13#10 + 'Response: ' + E.ErrorMessage);
end;
finally
RequestStream.Free;
end;
finally
SSLIO.Free;
IdHTTP.Free;
end;
end;
procedure TQBService.SaveTokens(AccessToken, RefreshToken: string);
var
f: TStringList;
iniStr, line: string;
iniFile: TIniFile;
begin
iniFile := TIniFile.Create( ExtractFilePath(Application.ExeName) + 'kgOrdersServer.ini' );
try
iniFile.WriteString('Quickbooks', 'RefreshToken', RefreshToken);
LastRefresh := Now;
Logger.Log(1, 'Tokens Successfully Saved');
finally
IniFile.Free;
end;
f := TStringList.Create;
// Save to file (overwrites existing file)
f.SaveToFile('QB.txt');
f.Free;
end;
initialization
RegisterServiceType(TQBService);
end.
...@@ -132,10 +132,11 @@ type ...@@ -132,10 +132,11 @@ type
START_DATE: String; START_DATE: String;
END_DATE: string; END_DATE: string;
QB_LIST_ID: string; QB_LIST_ID: string;
FAX: string; FFAX: string;
REP_USER_ID: string; REP_USER_ID: string;
ADDRESS_LIST: TList<TAddressItem>; ADDRESS_LIST: TList<TAddressItem>;
ITEMS: TItemList; ITEMS: TItemList;
USERS: TList<TUserItem>
end; end;
TCustomerList = class TCustomerList = class
...@@ -392,6 +393,7 @@ type ...@@ -392,6 +393,7 @@ type
[HttpGet] function GenerateOrderCorrugatedPDF(orderID: string): string; [HttpGet] function GenerateOrderCorrugatedPDF(orderID: string): string;
[HttpGet] function GenerateOrderWebPDF(orderID: string): string; [HttpGet] function GenerateOrderWebPDF(orderID: string): string;
[HttpGet] function GenerateOrderCuttingPDF(orderID: string): string; [HttpGet] function GenerateOrderCuttingPDF(orderID: string): string;
[HttpGet] function getQBCustomers(): TJSONArray;
function AddUser(userInfo: string): string; function AddUser(userInfo: string): string;
......
...@@ -20,7 +20,9 @@ uses ...@@ -20,7 +20,9 @@ uses
dbimageen, Vcl.ExtCtrls, ieview, imageenview, IdBaseComponent, IdComponent, dbimageen, Vcl.ExtCtrls, ieview, imageenview, IdBaseComponent, IdComponent,
IdTCPConnection, IdTCPClient, IdExplicitTLSClientServerBase, IdFTP, IdTCPConnection, IdTCPClient, IdExplicitTLSClientServerBase, IdFTP,
iexProcEffects, frxDBSet, frxExportBaseDialog, frCoreClasses, rOrderList, rOrderCorrugated, Common.Logging, iexProcEffects, frxDBSet, frxExportBaseDialog, frCoreClasses, rOrderList, rOrderCorrugated, Common.Logging,
DateUtils; DateUtils, REST.Client, REST.Types, WEBLib.REST, WEBLib.WebTools,System.Net.HttpClient,
System.Net.URLClient, System.Net.HttpClientComponent, System.netencoding,
IdHTTP, IdSSLOpenSSL, IdSSLOpenSSLHeaders, System.IniFiles;
type type
...@@ -37,6 +39,7 @@ type ...@@ -37,6 +39,7 @@ type
function GetCustomer(ID: string): TCustomerItem; function GetCustomer(ID: string): TCustomerItem;
function GetWebOrder(orderInfo: string): TWebOrder; function GetWebOrder(orderInfo: string): TWebOrder;
function GetCuttingDieOrder(orderInfo: string): TCuttingDie; function GetCuttingDieOrder(orderInfo: string): TCuttingDie;
function GetQBCustomers: TJSONArray;
function EditUser(const editOptions: string): string; function EditUser(const editOptions: string): string;
...@@ -70,6 +73,8 @@ type ...@@ -70,6 +73,8 @@ type
procedure AfterConstruction; override; procedure AfterConstruction; override;
procedure BeforeDestruction; override; procedure BeforeDestruction; override;
procedure AddToRevisionsTable(OrderID, table: string; order: TJSONObject); procedure AddToRevisionsTable(OrderID, table: string; order: TJSONObject);
procedure SaveTokens(AccessToken, RefreshToken: string);
function RefreshAccessToken: string;
end; end;
implementation implementation
...@@ -165,8 +170,12 @@ function TLookupService.GetCustomer(ID: string): TCustomerItem; ...@@ -165,8 +170,12 @@ function TLookupService.GetCustomer(ID: string): TCustomerItem;
var var
SQL: string; SQL: string;
ADDRESS: TAddressItem; ADDRESS: TAddressItem;
USER: TUserItem;
begin begin
SQL := 'select * FROM customers c LEFT JOIN customers_ship s ON c.CUSTOMER_ID = s.customer_id WHERE c.CUSTOMER_ID = ' + ID; 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
SQL := 'select * FROM customers c LEFT JOIN customers_ship s ON c.CUSTOMER_ID = s.customer_id WHERE c.CUSTOMER_ID = ' + ID;
doQuery(ordersDB.UniQuery1, SQL); doQuery(ordersDB.UniQuery1, SQL);
result := TCustomerItem.Create; result := TCustomerItem.Create;
result.ADDRESS_LIST := TList<TAddressItem>.Create; result.ADDRESS_LIST := TList<TAddressItem>.Create;
...@@ -186,7 +195,7 @@ begin ...@@ -186,7 +195,7 @@ begin
result.PHONE := ordersDB.UniQuery1.FieldByName('PHONE').AsString; result.PHONE := ordersDB.UniQuery1.FieldByName('PHONE').AsString;
result.END_DATE := ordersDB.UniQuery1.FieldByName('END_DATE').AsString; result.END_DATE := ordersDB.UniQuery1.FieldByName('END_DATE').AsString;
result.QB_LIST_ID := ordersDB.UniQuery1.FieldByName('QB_LIST_ID').AsString; result.QB_LIST_ID := ordersDB.UniQuery1.FieldByName('QB_LIST_ID').AsString;
result.FAX := ordersDB.UniQuery1.FieldByName('FAX').AsString; result.FFAX := ordersDB.UniQuery1.FieldByName('FAX').AsString;
result.REP_USER_ID := ordersDB.UniQuery1.FieldByName('REP_USER_ID').AsString; result.REP_USER_ID := ordersDB.UniQuery1.FieldByName('REP_USER_ID').AsString;
while not ordersDB.UniQuery1.Eof do while not ordersDB.UniQuery1.Eof do
...@@ -207,6 +216,21 @@ begin ...@@ -207,6 +216,21 @@ begin
ordersDB.UniQuery1.Close; ordersDB.UniQuery1.Close;
result.ITEMS := GetItems(''); result.ITEMS := GetItems('');
SQL := 'SELECT USER_ID, NAME from users where QB_ID IS NOT NULL AND QB_ID <> ' + quotedStr('');
result.USERS := TList<TUserItem>.Create;
doQuery(ordersDB.UniQuery1, SQL);
while not ordersDB.UniQuery1.Eof do
begin
USER := TUserItem.Create;
TXDataOperationContext.Current.Handler.ManagedObjects.Add( USER );
USER.userID := ordersDB.UniQuery1.FieldByName('USER_ID').AsString;
USER.full_name := ordersDB.UniQuery1.FieldByName('NAME').AsString;
result.USERS.Add(USER);
ordersDB.UniQuery1.Next;
end;
end; end;
function TLookupService.GenerateOrderListPDF(searchOptions: string): string; function TLookupService.GenerateOrderListPDF(searchOptions: string): string;
...@@ -313,6 +337,8 @@ begin ...@@ -313,6 +337,8 @@ begin
else else
msg := 'Success:Shipping Address Successfully Edited'; msg := 'Success:Shipping Address Successfully Edited';
// Sends the updated Address List Back.
SQL := 'select * FROM customers c LEFT JOIN customers_ship s ON c.CUSTOMER_ID = s.customer_id WHERE c.CUSTOMER_ID = ' + CustomerID; 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); doQuery(ordersDB.UniQuery1, SQL);
ADDRESS_LIST := TJSONArray.Create; ADDRESS_LIST := TJSONArray.Create;
...@@ -428,6 +454,7 @@ begin ...@@ -428,6 +454,7 @@ begin
Field.AsString := Pair.JsonValue.Value; Field.AsString := Pair.JsonValue.Value;
end; end;
end; end;
ordersDB.UniQuery1.FieldByName('CUSTOMER_ID').AsInteger := CustomerID; ordersDB.UniQuery1.FieldByName('CUSTOMER_ID').AsInteger := CustomerID;
// Post the record to the database // Post the record to the database
...@@ -438,7 +465,9 @@ begin ...@@ -438,7 +465,9 @@ begin
else else
msg := 'Success:Customer Successfully Edited'; msg := 'Success:Customer Successfully Edited';
Result := TJSONObject.Create.AddPair('status', msg); Result := TJSONObject.Create.AddPair('status', msg);
Result.AddPair('CustomerID', CustomerID);
TXDataOperationContext.Current.Handler.ManagedObjects.Add(Result); TXDataOperationContext.Current.Handler.ManagedObjects.Add(Result);
except except
on E: Exception do on E: Exception do
...@@ -2269,6 +2298,214 @@ begin ...@@ -2269,6 +2298,214 @@ begin
end; end;
function TLookupService.getQBCustomers: TJSONArray;
var
iniFile: TIniFile;
restClient: TRESTClient;
restRequest: TRESTRequest;
restResponse: TRESTResponse;
param: TRESTRequestParameter;
res: string;
jsValue: TJSONValue;
ParsedCustomer, Customer, BillAddr: TJSONObject;
jsObj: TJSONObject;
CustomerList: TJSONArray;
AccessToken, RefreshToken, CompanyID, Client, Secret: string;
LastRefresh: TDateTime;
I: integer;
begin
Result := TJSONArray.Create;
iniFile := TIniFile.Create(ExtractFilePath(Application.ExeName) + 'kgOrdersServer.ini');
restClient := TRESTClient.Create(nil);
restRequest := TRESTRequest.Create(nil);
restResponse := TRESTResponse.Create(nil);
try
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';
restRequest.Method := rmGET;
res := '/v3/company/' + CompanyID + '/query?query=select * from Customer&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;
jsValue := restResponse.JSONValue;
if not Assigned(jsValue) then
Exit;
jsObj := jsValue as TJSONObject;
if not Assigned(jsObj) then
Exit;
CustomerList := jsObj.GetValue<TJSONArray>('QueryResponse.Customer');
if not Assigned(CustomerList) then
Exit;
for I := 0 to CustomerList.Count - 1 do
begin
Customer := CustomerList.Items[I] as TJSONObject;
ParsedCustomer := TJSONObject.Create;
try
ParsedCustomer.AddPair('Id', Customer.GetValue('Id').Clone as TJSONValue);
ParsedCustomer.AddPair('CompanyName', Customer.GetValue('DisplayName').Clone as TJSONValue);
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', BillAddr.GetValue('Line1', '') + ', '
+ BillAddr.GetValue('City', '') + ', '
+ BillAddr.GetValue('CountrySubDivisionCode', '') + ' '
+ BillAddr.GetValue('PostalCode', '') );
end;
Result.AddElement(ParsedCustomer);
except
ParsedCustomer.Free;
raise;
end;
end;
finally
iniFile.Free;
restClient.Free;
restRequest.Free;
restResponse.Free;
end;
end;
function TLookupService.RefreshAccessToken: string;
// Refresh Token changes so make sure to save refresh token.
var
IdHTTP: TIdHTTP;
SSLIO: TIdSSLIOHandlerSocketOpenSSL;
RequestStream: TStringStream;
EncodedAuth, EncodedAuth2, PostData, response: string;
f: TStringList;
fi: string;
JSObj: TJSONObject;
iniFile: TIniFile;
Encoder: TBase64Encoding;
AccessToken,RefreshToken,CompanyID,Client,Secret: string;
LastRefresh: TDateTime;
begin
iniFile := TIniFile.Create( ExtractFilePath(Application.ExeName) + 'kgOrdersServer.ini' );
Client := iniFile.ReadString('Quickbooks', 'ClientID', '');
Secret := iniFile.ReadString('Quickbooks', 'ClientSecret', '');
CompanyID := iniFile.ReadString('Quickbooks', 'CompanyID', '');
RefreshToken := iniFile.ReadString('Quickbooks', 'RefreshToken', '');
// 1. Encode credentials (same as working Postman request)
// TNetEncoding.Base64.Encode adds a new line every 72 chars, this stops that
Encoder := TBase64Encoding.Create(0);
if( (Client = '') or (Secret = '') ) then
begin
Logger.Log(1, 'Missing Client ID or Client Secret in INI File');
Exit();
end;
EncodedAuth := Encoder.Encode(Client + ':' + Secret);
if RefreshToken = '' then
begin
Logger.Log(3, 'Missing Refresh Token, Please Manually Get a New One and Store in INI File');
Exit();
end;
// 2. Prepare POST data (EXACTLY as in Postman)
PostData := 'grant_type=refresh_token&refresh_token=' + RefreshToken;
// 3. Configure HTTP client
IdHTTP := TIdHTTP.Create(nil);
SSLIO := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
try
// Force TLS 1.2
SSLIO.SSLOptions.Method := sslvTLSv1_2;
SSLIO.SSLOptions.SSLVersions := [sslvTLSv1_2];
IdHTTP.IOHandler := SSLIO;
// Set headers (EXACT match with Postman)
IdHTTP.Request.ContentType := 'application/x-www-form-urlencoded';
IdHTTP.Request.Accept := 'application/json';
IdHTTP.Request.CustomHeaders.AddValue('Authorization', 'Basic ' + EncodedAuth);
// 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);
JSObj := TJSONObject.ParseJSONValue(response) as TJSONObject;
RefreshToken := JSObj.GetValue('refresh_token').ToString.Trim(['"']);
AccessToken := JSObj.GetValue('access_token').ToString.Trim(['"']);
SaveTokens(AccessToken, RefreshToken);
Result := AccessToken;
Logger.Log(1, 'qbAPI - Tokens Successfully Saved');
except
on E: EIdHTTPProtocolException do
// Memo2.Lines.Add('Error: ' + E.Message + #13#10 + 'Response: ' + E.ErrorMessage);
end;
finally
RequestStream.Free;
end;
finally
SSLIO.Free;
IdHTTP.Free;
end;
end;
procedure TLookupService.SaveTokens(AccessToken, RefreshToken: string);
var
f: TStringList;
iniStr, line: string;
iniFile: TIniFile;
begin
iniFile := TIniFile.Create( ExtractFilePath(Application.ExeName) + 'kgOrdersServer.ini' );
try
iniFile.WriteString('Quickbooks', 'RefreshToken', RefreshToken);
iniFile.WriteString('Quickbooks', 'AccessToken', AccessToken);
iniFile.WriteString('Quickbooks', 'LastRefresh', DateTimeToStr(Now));
Logger.Log(1, 'Tokens Successfully Saved');
finally
IniFile.Free;
end;
f := TStringList.Create;
// Save to file (overwrites existing file)
f.SaveToFile('QB.txt');
f.Free;
end;
initialization initialization
RegisterServiceType(TLookupService); RegisterServiceType(TLookupService);
end. end.
......
...@@ -205,4 +205,13 @@ object fQB: TfQB ...@@ -205,4 +205,13 @@ object fQB: TfQB
TabOrder = 5 TabOrder = 5
OnClick = Button3Click OnClick = Button3Click
end end
object Button4: TButton
Left = 460
Top = 18
Width = 95
Height = 25
Caption = 'Add Estimate'
TabOrder = 6
OnClick = Button4Click
end
end end
...@@ -22,10 +22,12 @@ type ...@@ -22,10 +22,12 @@ type
Button2: TButton; Button2: TButton;
asgData: TAdvStringGrid; asgData: TAdvStringGrid;
Button3: TButton; Button3: TButton;
Button4: TButton;
procedure Button1Click(Sender: TObject); procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject); procedure FormCreate(Sender: TObject);
procedure Button2Click(Sender: TObject); procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject); procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
private private
{ Private declarations } { Private declarations }
httpReqTokenRefresh: TWebHttpRequest; httpReqTokenRefresh: TWebHttpRequest;
...@@ -88,7 +90,7 @@ begin ...@@ -88,7 +90,7 @@ begin
end; end;
procedure TfQB.Button3Click(Sender: TObject); procedure TfQB.Button3Click(Sender: TObject);
var var
restClient: TRESTClient; restClient: TRESTClient;
restRequest: TRESTRequest; restRequest: TRESTRequest;
restResponse: TRESTResponse; restResponse: TRESTResponse;
...@@ -146,7 +148,7 @@ begin ...@@ -146,7 +148,7 @@ begin
end; end;
procedure TfQB.getCustomers(); procedure TfQB.Button4Click(Sender: TObject);
var var
restClient: TRESTClient; restClient: TRESTClient;
restRequest: TRESTRequest; restRequest: TRESTRequest;
...@@ -158,7 +160,9 @@ var ...@@ -158,7 +160,9 @@ var
jsObj: TJSONObject; jsObj: TJSONObject;
CustomerList: TJSONArray; CustomerList: TJSONArray;
pair: TJSONPair; pair: TJSONPair;
estimateJSON: TJSONObject;
begin begin
///v3/company/<realmID>/estimate
restClient := TRESTClient.Create(nil); restClient := TRESTClient.Create(nil);
restClient.BaseURL := 'https://sandbox-quickbooks.api.intuit.com'; restClient.BaseURL := 'https://sandbox-quickbooks.api.intuit.com';
...@@ -174,12 +178,9 @@ begin ...@@ -174,12 +178,9 @@ begin
RefreshAccessToken(); RefreshAccessToken();
end; end;
restRequest.Method := rmGET; restRequest.Method := rmPOST;
//res := '/v3/company/' + companyID + '/preferences'; res := '/v3/company/' + companyID + '/estimate';
res := '/v3/company/' + companyID + '/query?query=select * from Customer where CompanyName = ' + quotedStr('TYOGA CONTAINER') + '&minorversion=75'; // '/customer/58';
restRequest.Resource := res; restRequest.Resource := res;
///query?query=select * from Customer where CompanyName = ' + quotedStr('TYOGA CONTAINER') + '&minorversion=75';
param := restRequest.Params.AddItem; param := restRequest.Params.AddItem;
param.Name := 'Authorization'; param.Name := 'Authorization';
...@@ -205,6 +206,101 @@ begin ...@@ -205,6 +206,101 @@ begin
restClient.Free; restClient.Free;
restRequest.Free; restRequest.Free;
restResponse.Free; restResponse.Free;
end;
procedure TfQB.getCustomers();
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);
{Memo2.Lines.Add(res);
Memo2.Lines.Add( jsObj.Format(2) ); }
//CustomerList := TJSONArray(restResponse.JSONValue);
CustomerList := TJSONArray( TJSONObject( jsObj.GetValue('QueryResponse') ).GetValue('Customer')) ;
ModifiedList := TJSONArray.Create;
for I := 0 to CustomerList.Count - 1 do
begin
Customer := CustomerList.Items[I] as TJSONObject;
ParsedCustomer := TJSONObject.Create;
try
// Directly add values without cloning
ParsedCustomer.AddPair('id', Customer.GetValue('Id'));
ParsedCustomer.AddPair('name', Customer.GetValue('DisplayName'));
if Customer.GetValue('BillAddr') <> nil then
begin
BillAddr := Customer.GetValue('BillAddr') as TJSONObject;
ParsedCustomer.AddPair('BillAddr_line1', BillAddr.GetValue('Line1', ''));
ParsedCustomer.AddPair('BillAddr_City', BillAddr.GetValue('City', ''));
ParsedCustomer.AddPair('BillAddr_State', BillAddr.GetValue('CountrySubDivisionCode', ''));
ParsedCustomer.AddPair('BillAddr_Zip', BillAddr.GetValue('PostalCode', ''));
ParsedCustomer.AddPair('BillAddr', BillAddr.GetValue('Line1', '') + ', '
+ BillAddr.GetValue('City', '') + ', '
+ BillAddr.GetValue('CountrySubDivisionCode', '') + ' '
+ BillAddr.GetValue('PostalCode', '') );
end;
except
ParsedCustomer.Free;
raise;
end;
end;
LoadJSONArray( ModifiedList );
restClient.Free;
restRequest.Free;
restResponse.Free;
end; end;
......
...@@ -26,7 +26,9 @@ uses ...@@ -26,7 +26,9 @@ uses
rOrderCorrugated in 'Source\rOrderCorrugated.pas' {rptOrderCorrugated: TDataModule}, rOrderCorrugated in 'Source\rOrderCorrugated.pas' {rptOrderCorrugated: TDataModule},
rOrderWeb in 'Source\rOrderWeb.pas' {rptOrderWeb: TDataModule}, rOrderWeb in 'Source\rOrderWeb.pas' {rptOrderWeb: TDataModule},
rOrderCutting in 'Source\rOrderCutting.pas' {rptOrderCutting: TDataModule}, rOrderCutting in 'Source\rOrderCutting.pas' {rptOrderCutting: TDataModule},
qbAPI in 'Source\qbAPI.pas' {fQB}; qbAPI in 'Source\qbAPI.pas' {fQB},
QBService in 'QBService.pas',
QBServiceImplementation in 'QBServiceImplementation.pas';
type type
TMemoLogAppender = class( TInterfacedObject, ILogAppender ) TMemoLogAppender = class( TInterfacedObject, ILogAppender )
......
...@@ -201,6 +201,8 @@ ...@@ -201,6 +201,8 @@
<Form>fQB</Form> <Form>fQB</Form>
<FormType>dfm</FormType> <FormType>dfm</FormType>
</DCCReference> </DCCReference>
<DCCReference Include="QBService.pas"/>
<DCCReference Include="QBServiceImplementation.pas"/>
<BuildConfiguration Include="Base"> <BuildConfiguration Include="Base">
<Key>Base</Key> <Key>Base</Key>
</BuildConfiguration> </BuildConfiguration>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
MemoLogLevel=3 MemoLogLevel=3
FileLogLevel=5 FileLogLevel=5
webClientVersion=0.9.2 webClientVersion=0.9.2
LogFileNum=555 LogFileNum=591
[Database] [Database]
Server=192.168.159.131 Server=192.168.159.131
...@@ -17,5 +17,6 @@ Password=emsys01 ...@@ -17,5 +17,6 @@ Password=emsys01
CompanyID=9341454272655710 CompanyID=9341454272655710
ClientID=ABgO14uvjh8XqLud7spQ8lkb98AUpcdA7HbyMJfCAtl65sQ5yy ClientID=ABgO14uvjh8XqLud7spQ8lkb98AUpcdA7HbyMJfCAtl65sQ5yy
ClientSecret=bQ06TRemHeAGFzVHRaTUvUoBU9jpU9itK6MOMgqN ClientSecret=bQ06TRemHeAGFzVHRaTUvUoBU9jpU9itK6MOMgqN
RefreshToken=RT1-86-H0-17551964757vq6lk1eu183mmu09c1o RefreshToken=RT1-25-H0-1756568183wceqmvmfoz1ccfcr1fcq
AccessToken=eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwieC5vcmciOiJIMCJ9..oXhfeeG4jA22E97aNL7zcg.ie7-Ny9UQ8NuozYWGP5YLDk1KZqrMc8U1qD4hQWBV7-J4To2zk1CBvp3of53lbQTqH2tUu8QoMAwJy7RkuwQ9-Y3PmPesu_LxgGTW-6b2K-W5fUSat03C62ExFr1e1RLgaQGcnJSJOVUyGP3DlwwmKk0YyHMeWkSwkKNYVpdgnUpOHFzXBDbYlF0vI6M6oY6PwEooEWK-K6TCo6tW_AhqxBiMAW4CDPvEKw1iGlrwJDouemK-ttd4PL2-mNaKcpAL6KWT8qeIIgHNySf3Y3Kd5EVmlp6v_NaHu4cYidmIsk1FhKlPRLoiCZoK4Rm0WA3OWKu55_T4rbbqUf6ZpLZZMzZfnzQPslZxV8N6L0fqyik6u4arkY1oCIOvM0TyCyRxP-mdd0rDyEOvrOusehoTrtVi-DG0C8t2rdYxsm8bVAWQew_S77-aWq_y8MQGaQ1TY9gtlTmIeVPLfK6wPZ4jZ3jiC6Yc4SQsIosz_hC5qE.YIBYv0DUUeO2d_6s6SiIOA
LastRefresh=5/21/2025 11:39:37 AM
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