// Order Entry page of Corruguated Orders. Used for both editting and adding
// orders.
unit View.OrderEntryCorrugated;

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.Forms;

type
  TFOrderEntryCorrugated = class(TWebForm)
    WebLabel1: TWebLabel;
    WebLabel2: TWebLabel;
    WebLabel3: TWebLabel;
    WebLabel4: TWebLabel;
    WebLabel5: TWebLabel;
    WebLabel6: TWebLabel;
    btnAddColor: TWebButton;
    WebLabel7: TWebLabel;
    WebLabel8: TWebLabel;
    WebLabel9: TWebLabel;
    edtCompanyName: TWebDBEdit;
    edtCompanyAccountName: TWebDBEdit;
    edtShipVia: TWebDBEdit;
    edtQuantity: TWebDBEdit;
    edtPrice: TWebDBEdit;
    edtInvoiceTo: TWebDBEdit;
    edtPONumber: TWebDBEdit;
    edtJobName: TWebDBEdit;
    edtOther: TWebDBEdit;
    edtCADFile: TWebDBEdit;
    edtAroundNo: TWebDBEdit;
    edtAcrossNo: TWebDBEdit;
    edtDieCutNo: TWebDBEdit;
    edtRSCD: TWebDBEdit;
    edtRSCW: TWebDBEdit;
    edtRSCL: TWebDBEdit;
    edtCustomAdhesive: TWebDBEdit;
    edtCustomBacking: TWebDBEdit;
    edtStandardSetup: TWebDBEdit;
    edtStripMount: TWebDBEdit;
    edtLoose: TWebDBEdit;
    edtRSCStyle: TWebDBEdit;
    edtProofOther: TWebDBEdit;
    edtProofShipTo: TWebDBEdit;
    edtEmailAttn: TWebDBEdit;
    edtProofEmail: TWebDBEdit;
    edtFaxAttn: TWebDBEdit;
    edtFax: TWebDBEdit;
    edtClemson: TWebDBEdit;
    edtCrossHairs: TWebDBEdit;
    edtMachineIndent: TWebDBEdit;
    edtCylinderSize: TWebDBEdit;
    edtJobNumber: TWebDBEdit;
    cbArtApprovedAsIs: TWebDBCheckBox;
    cbPDFFile: TWebDBCheckBox;
    cbWideFormat: TWebDBCheckBox;
    cbPrintCard: TWebDBCheckBox;
    cbFullSizePanel: TWebDBCheckBox;
    XDataWebClient1: TXDataWebClient;
    edtSpecialInstructions: TWebDBEdit;
    xdwdsOrder: TXDataWebDataSet;
    wdsOrder: TWebDataSource;
    btnSave: TWebButton;
    xdwdsOrderORDER_ID: TIntegerField;
    xdwdsOrderCOMPANY_ID: TIntegerField;
    xdwdsOrderUSER_ID: TIntegerField;
    xdwdsOrderORDER_STATUS: TStringField;
    xdwdsOrderSCHED_JSON: TStringField;
    xdwdsOrderstaff_fields_ship_via: TStringField;
    xdwdsOrderstaff_fields_price: TStringField;
    xdwdsOrderstaff_fields_invoice_to: TStringField;
    xdwdsOrderstaff_fields_invoice_attention: TStringField;
    xdwdsOrderstaff_fields_ship_to: TStringField;
    xdwdsOrderstaff_fields_ship_attention: TStringField;
    xdwdsOrderstaff_fields_po_number: TStringField;
    xdwdsOrderstaff_fields_job_name: TStringField;
    xdwdsOrderORDER_DATE: TDateField;
    xdwdsOrderSTART_DATE: TDateField;
    xdwdsOrderEND_DATE: TDateField;
    xdwdsOrderplates_job_number: TStringField;
    xdwdsOrdersupplied_by_customer_dimension: TStringField;
    xdwdsOrdersupplied_by_customer_other: TStringField;
    xdwdsOrdercut_die_cutdier: TStringField;
    xdwdsOrdercut_die_cutdieb: TStringField;
    xdwdsOrdercut_die_cutdief: TStringField;
    xdwdsOrdercut_die_cutdierkr: TStringField;
    xdwdsOrdercut_die_cutdiefkr: TStringField;
    xdwdsOrdercut_die_cad_file: TStringField;
    xdwdsOrdercut_die_attached: TStringField;
    xdwdsOrdercut_die_boxpol250: TStringField;
    xdwdsOrdercut_die_boxpol155: TStringField;
    xdwdsOrdercut_die_boxpol125: TStringField;
    xdwdsOrdercut_die_brub: TStringField;
    xdwdsOrderproofing_fax: TStringField;
    xdwdsOrderproofing_fax_attn: TStringField;
    xdwdsOrderproofing_e_mail: TStringField;
    xdwdsOrderproofing_ship_to: TStringField;
    xdwdsOrderproofing_other: TStringField;
    xdwdsOrderproofing_changes_required: TStringField;
    xdwdsOrderproofing_changes_date: TDateField;
    xdwdsOrderlayout_rsc_l: TStringField;
    xdwdsOrderlayout_rcs_w: TStringField;
    xdwdsOrderlayout_rcs_d: TStringField;
    xdwdsOrderlayout_die_cut_no: TStringField;
    xdwdsOrderlayout_accross_no: TStringField;
    xdwdsOrderlayout_around_no: TStringField;
    xdwdsOrderlayout_cad_file: TStringField;
    xdwdsOrdercolors_cylinder_size: TStringField;
    xdwdsOrdercolors_machine_ident: TStringField;
    xdwdsOrdermounting_standard_setup: TStringField;
    xdwdsOrdermounting_custom_backing: TStringField;
    xdwdsOrdermounting_custom_adhesive: TStringField;
    xdwdsOrdercolors_cross_hairs: TStringField;
    xdwdsOrdercolors_clemson: TStringField;
    xdwdsOrderplates_thickness: TStringField;
    xdwdsOrderplates_plate_material: TStringField;
    xdwdsOrdergeneral_special_instructions: TStringField;
    xdwdsOrdercolors_colors: TStringField;
    xdwdsOrderstaff_fields_quickbooks_item: TStringField;
    xdwdsOrderstaff_fields_quantity: TStringField;
    xdwdsOrderlayout_rsc_style: TStringField;
    xdwdsOrderstaff_fields_art_location: TStringField;
    xdwdsOrderNAME: TStringField;
    xdwdsOrderSHORT_NAME: TStringField;
    xdwdsOrdermounting_loose: TStringField;
    xdwdsOrdermounting_strip_mount: TStringField;
    xdwdsOrderproofing_e_mail_attn: TStringField;
    xdwdsOrderproofing_approved_date: TStringField;
    xdwdsOrderstaff_fields_order_date: TStringField;
    xdwdsOrderstaff_fields_proof_date: TStringField;
    xdwdsOrderstaff_fields_ship_date: TStringField;
    xdwdsOrderstaff_fields_art_due: TStringField;
    xdwdsOrderstaff_fields_plate_due: TStringField;
    xdwdsOrderstaff_fields_mount_due: TStringField;
    xdwdsOrderADDRESS_LIST: TStringField;
    wdsShipTo: TWebDataSource;
    xdwdsShipTo: TXDataWebDataSet;
    wdbcbShipTo: TWebDBComboBox;
    xdwdsOrdersupplied_by_customer_order_date: TStringField;
    btnCancel: TWebButton;
    wdbcbQuickbooksItem: TWebDBComboBox;
    wdsQBItem: TWebDataSource;
    xdwdsQBItem: TXDataWebDataSet;
    xdwdsQBItemname: TStringField;
    WebDBComboBox3: TWebDBComboBox;
    WebDBComboBox4: TWebDBComboBox;
    btnPDF: TWebButton;
    btnCopy: TWebButton;
    btnDelete: TWebButton;
    btnClose: TWebButton;
    tmrReturn: TWebTimer;
    btnEdit: TWebButton;
    btnAdd: TWebButton;
    WebButton2: TWebButton;
    lblFormState: TWebLabel;
    xdwdsOrderinQuickBooks: TStringField;
    dtpShipDate: TWebDBDateTimePicker;
    dtpProofDate: TWebDBDateTimePicker;
    dtpOrderDate: TWebDBDateTimePicker;
    dtpApprovedDate: TWebDBDateTimePicker;
    dtpMountDue: TWebDBDateTimePicker;
    dtpPlateDue: TWebDBDateTimePicker;
    dtpArtDue: TWebDBDateTimePicker;
    cbPlates: TWebDBCheckBox;
    cbSampleCarton: TWebDBCheckBox;
    cbFTP: TWebDBCheckBox;
    cbColorCopy: TWebDBCheckBox;
    cbEmail: TWebDBCheckBox;
    cbExistingCuttingDie: TWebDBCheckBox;
    cbRefArtAPDF: TWebDBCheckBox;
    cbRefArtPrintCard: TWebDBCheckBox;
    cbFullMount: TWebDBCheckBox;
    cbStickyBak: TWebDBCheckBox;
    cbExcaliburDie: TWebDBCheckBox;
    cbLoose: TWebCheckBox;
    cbStripMount: TWebCheckBox;
    xdwdsOrdersupplied_by_customer_color_copy: TStringField;
    xdwdsOrdersupplied_by_customer_plates: TStringField;
    xdwdsOrdersupplied_by_customer_sample_ca: TStringField;
    xdwdsOrdersupplied_by_customer_ftp: TStringField;
    xdwdsOrdersupplied_by_customer_e_mail: TStringField;
    xdwdsOrdersupplied_by_customer_existing_: TStringField;
    xdwdsOrdersupplied_by_customer_ref_art_p: TStringField;
    xdwdsOrdersupplied_by_customer_ref_art_a: TStringField;
    xdwdsOrderlayout_excalibur_die: TStringField;
    xdwdsOrdermounting_sticky_bak: TStringField;
    xdwdsOrdermounting_full_mount: TStringField;
    xdwdsOrderproofing_full_size_panel: TStringField;
    xdwdsOrderproofing_print_card: TStringField;
    xdwdsOrderproofing_wide_format: TStringField;
    xdwdsOrderproofing_pdf_file: TStringField;
    xdwdsOrderproofing_art_approved_as_is: TStringField;
    edtQBItemDescription: TWebEdit;
    edtQBOrderNum: TWebDBEdit;
    wdbcbINQB: TWebDBCheckBox;
    edtOrderNum: TWebDBEdit;
    xdwdsQBItemdescription: TStringField;
    xdwdsQBItemQB_ID: TStringField;
    btnQB: TWebButton;
    xdwdsOrderIN_QB: TStringField;
    xdwdsOrderQB_ORDER_NUM: TStringField;
    xdwdsShipToship_block: TStringField;
    procedure WebFormCreate(Sender: TObject);
    [async] procedure getOrder(Order_ID: string);
    [async] procedure SetEmptyOrderInfo(customerID: string);
    procedure btnAddColorClick(Sender: TObject);
    procedure addColorRow(num, Color, LPI, Size: string);
    procedure btnSaveClick(Sender: TObject);
    [async] procedure SendCorrugatedOrder();
    [async] procedure GenerateReportPDF;
    [async] procedure DelOrder();
    procedure btnCancelClick(Sender: TObject);
    procedure btnPDFClick(Sender: TObject);
    procedure btnCopyClick(Sender: TObject);
    procedure btnCloseClick(Sender: TObject);
    procedure btnDeleteClick(Sender: TObject);
    procedure tmrReturnTimer(Sender: TObject);
    function VerifyOrder(): boolean;
    procedure EditMode();
    procedure btnEditClick(Sender: TObject);
    procedure btnAddClick(Sender: TObject);
    procedure ViewMode();
    procedure WebButton2Click(Sender: TObject);
    procedure ShowAddAddressForm();
    [async] procedure SendAddressToServer(AddressJSON: TJSONObject);
    procedure edtJobNameExit(Sender: TObject);
    procedure wdbcbQuickbooksItemChange(Sender: TObject);
    procedure btnQBClick(Sender: TObject);
    function VerifyQBOrder: Boolean;
    procedure edtPriceExit(Sender: TObject);
  private
    FAgencyCode: string;
    FCurrentReportType: string;
    FSelectProc: TSelectProc;
    mode: string;
    orderID: string;
    customerID: string;
    changed: boolean;
    notification: string;
    customer_qb_id: string;
    REVISION_NOTES: string;
    procedure RemoveColorRow(Sender: TObject);
    [async] procedure InitializeForm;
    [async] procedure AddEstimate(orderID: string);
    //FJSONProc1: TJSONProc1;
  public
    class function CreateForm(AElementID, orderInfo, customerInfo, modeparam, info: string): TWebForm;
  end;

var
  FOrderEntryCorrugated: TFOrderEntryCorrugated;

implementation

{$R *.dfm}

uses
  View.Home, View.Main, View.Order.Add, View.Address.Add, Utils;

class function TFOrderEntryCorrugated.CreateForm(AElementID, orderInfo, customerInfo, modeParam, info: string): TWebForm;
begin
  Application.CreateForm(TFOrderEntryCorrugated, AElementID, Result,
    procedure(AForm: TObject)
    begin
      with TFOrderEntryCorrugated(AForm) do
      begin
        customerID := customerInfo;
        orderID := orderInfo;
        mode := modeParam;
        notification := info;
        InitializeForm;
      end;
    end
  );
end;


[async] procedure TFOrderEntryCorrugated.InitializeForm;
begin
  if mode = 'ADD' then
  begin
    await(SetEmptyOrderInfo(customerID));
    EditMode;
  end
  else
  begin
    await(getOrder(orderID));
    ViewMode;
  end;

  edtOrderNum.Text := orderID;
  if notification <> '' then
    ShowToast(notification);
end;

procedure TFOrderEntryCorrugated.btnSaveClick(Sender: TObject);
// Converts all the information on the page into a JSON to then send to the server
begin
  if VerifyOrder() then
  begin
    SendCorrugatedOrder();
    ViewMode();
  end;
end;

procedure TFOrderEntryCorrugated.AddEstimate(orderID: string);
var
  Response: TXDataClientResponse;
  notification: TJSObject;
  msg: string;
begin
  try
    Response := await(XDataWebClient1.RawInvokeAsync('ILookupService.AddEstimate',
                [orderID]));
    notification := TJSObject(Response.Result);
    msg := string(notification['status']);
    Utils.HideSpinner('spinner');
    getOrder(xdwdsOrder.FieldByName('ORDER_ID').AsString);

    ShowToast(msg);
  except
      on E: EXDataClientRequestException do
        Utils.ShowErrorModal(E.ErrorResult.ErrorMessage);
    end;
end;

procedure TFOrderEntryCorrugated.btnCopyClick(Sender: TObject);
begin
  mode := 'ADD';
  xdwdsOrder.Edit;
  xdwdsOrder.FieldByName('staff_fields_order_date').AsDateTime := 0;
  xdwdsOrder.FieldByName('staff_fields_proof_date').AsDateTime := 0;
  xdwdsOrder.FieldByName('staff_fields_art_due').AsDateTime := 0;
  xdwdsOrder.FieldByName('staff_fields_plate_due').AsDateTime := 0;
  xdwdsOrder.FieldByName('staff_fields_mount_due').AsDateTime := 0;
  xdwdsOrder.FieldByName('staff_fields_ship_date').AsDateTime := 0;
  xdwdsOrder.FieldByName('proofing_approved_date').AsDateTime := 0;

  xdwdsOrder.FieldByName('IN_QB').AsString := 'F';
  xdwdsOrder.FieldByName('QB_ORDER_NUM').AsString := '';
  REVISION_NOTES := 'Order was copied from ORDER_ID: ' + xdwdsOrder.FieldByName('ORDER_ID').AsString;
  xdwdsOrder.FieldByName('ORDER_ID').AsString := '';
  xdwdsOrder.Post;
  EditMode();
  ShowToast('Success: Order Successfully Copied');
  window.scrollTo(0, 0);
end;

procedure TFOrderEntryCorrugated.btnDeleteClick(Sender: TObject);
begin
  ShowConfirmationModal(
    'Are you sure you want to delete this order?',
    'Yes',
    'No',
    procedure(confirmed: Boolean)
    begin
      if confirmed then
      begin
        Utils.ShowSpinner('spinner');
        DelOrder();
        tmrReturn.Enabled := true;
      end;
    end
  );
end;



procedure TFOrderEntryCorrugated.btnEditClick(Sender: TObject);
begin
  EditMode();
end;


procedure TFOrderEntryCorrugated.btnPDFClick(Sender: TObject);
begin
  if mode = 'EDIT' then
    GenerateReportPDF
  else
    ShowToast('Failure: Cannot Generate PDF when Adding an Order');
end;


procedure TFOrderEntryCorrugated.btnQBClick(Sender: TObject);
var
  orderJSON: TJSONObject;
  qbEnabled: boolean;
  AccessType: string;
begin
  AccessType := JS.toString(AuthService.TokenPayload.Properties['user_access_type']);
  if( ( AccessType =  'ADMIN' ) or ( AccessType = 'QBUSR' ) ) then
  begin
    if ( VerifyQBOrder() )then
    begin
      if wdbcbINQB.Checked = false  then
      begin
          Utils.ShowSpinner('spinner');
          orderJSON := TJSONObject.Create;
          orderJSON.AddPair('ORDER_ID', xdwdsOrder.FieldByName('ORDER_ID').AsString);
          orderJSON.AddPair('USER_ID', JS.toString(AuthService.TokenPayload.Properties['user_id']));
          addEstimate(orderJSON.ToString);
      end
      else
        ShowToast('Failure:Cannot submit orders already in QuickBooks', 'failure');
    end;
  end
  else
    ShowToast('Failure:User not authorized to add to QuickBooks', 'failure');
end;

[async] procedure TFOrderEntryCorrugated.GenerateReportPDF;
// sends the search to the server which then sends back a pdf of the results
var
  xdcResponse: TXDataClientResponse;
  searchOptions, pdfURL: string;
  jsObject: TJSObject;
begin
  try
    // Call the server method to generate the PDF
    xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GenerateOrderCorrugatedPDF', [xdwdsOrder.FieldByName('ORDER_ID').AsString]));
    jsObject := JS.TJSObject(xdcResponse.Result);
    pdfURL := JS.toString(jsObject.Properties['value']);

    // Open the PDF in a new browser tab without needing a different form
    // This method is much faster too, even for large datasets
    window.open(pdfURL, '_blank');
  except
    on E: EXDataClientRequestException do
      Utils.ShowErrorModal(E.ErrorResult.ErrorMessage);
  end;
end;


procedure TFOrderEntryCorrugated.SendCorrugatedOrder();
// sends the order JSON object to the server
var
  Response: TXDataClientResponse;
  jsObj: TJSObject;
  colorList: TJSONArray;
  container: TJSElement;
  colorCollection: TJSHTMLCollection;
  color: TJSHTMLElement;
  I, J: integer;
  colorJSON, orderJSON, colorListJSON: TJSONObject;
  fieldNames: TStringList;
  itemList: TJSNodeList;
  header, value: string;
  Field: TField;
begin
  orderJSON := TJSONObject.Create;
  colorList := TJSONArray.Create;
  container := document.getElementById('additionalFields');
  colorCollection := container.children;

  for I := 0 to colorCollection.length - 1 do
  begin
    colorJSON := TJSONObject.Create;
    itemList := colorCollection[I].childNodes;
    for J := 0 to itemList.length - 2 do
    begin
      header := TJSHTMLElement(itemList[J]).children[0].innerText.Replace(':', '').Trim();
      value := TJSHTMLInputElement(TJSHTMLElement(itemList[J]).childNodes[1]).value;
      colorJSON.AddPair(header, value);
    end;
    colorList.Add(colorJSON);
  end;
  colorListJSON := TJSONObject.Create;
  colorListJSON.AddPair('items', colorList);
  xdwdsOrder.Edit;

  xdwdsOrdercolors_colors.Value := colorListJSON.ToString;
  xdwdsOrderUSER_ID.AsString := JS.toString(AuthService.TokenPayload.Properties['user_id']);

  xdwdsOrder.Post;

  xdwdsOrder.First;
  while not xdwdsOrder.Eof do
  begin
    for Field in xdwdsOrder.Fields do
    begin
      if Field is TStringField then
      begin
        if Field.AsString = '' then
        begin
          orderJSON.AddPair(Field.FieldName, '');
        end
        else
          orderJSON.AddPair(Field.FieldName, Field.AsString);  // Add all other fields
      end
      else if Field is TBooleanField then
      begin
        if Field.AsBoolean then
          orderJSON.AddPair(Field.FieldName, 'T')
        else
          orderJSON.AddPair(Field.FieldName, 'F');
      end
      else if Field is TIntegerField then
        orderJSON.AddPair(Field.FieldName, Field.AsInteger);
    end;
    xdwdsOrder.Next;
  end;

  orderJSON.AddPair('mode', mode);
  orderJSON.AddPair('REVISION_NOTES', REVISION_NOTES);

  Response := await(XDataWebClient1.RawInvokeAsync('ILookupService.AddCorrugatedOrder',
              [orderJSON.ToString]));
  jsObj := JS.TJSObject(Response.Result);

  xdwdsOrder.Close;
  xdwdsOrder.SetJsonData(jsObj);
  xdwdsOrder.Open;
  cbLoose.Checked := ( xdwdsOrder.FieldByName('mounting_loose').AsString <> '' );
  cbStripMount.Checked := ( xdwdsOrder.FieldByName('mounting_strip_mount').AsString <> '' );
  OrderID := xdwdsOrderORDER_ID.AsString;

  mode := 'EDIT';

  ShowToast(string(jsObj.Properties['status']));
end;


procedure TFOrderEntryCorrugated.DelOrder();
var
  Response: TXDataClientResponse;
begin
  try
    Response := await(XDataWebClient1.RawInvokeAsync('ILookupService.DelOrder',
                [OrderID, 'corrugated', JS.toString(AuthService.TokenPayload.Properties['user_id'])]));
  except
    on E: EXDataClientRequestException do
      Utils.ShowErrorModal(E.ErrorResult.ErrorMessage);
  end;
end;


procedure TFOrderEntryCorrugated.addColorRow(num, color, LPI, size: string);
var
  container, newRow, col, labelEl, inputEl, removeCol: TJSHTMLElement;
  removeBtn: TWebButton;
  values: array[0..3] of string;
  labels: array[0..3] of string;
  i: Integer;
begin
  container := TJSHTMLElement(document.getElementById('additionalFields'));

  // Create the new row container
  newRow := TJSHTMLElement(document.createElement('div'));
  newRow.className := 'row mb-2';

  labels[0] := '#';     values[0] := num;
  labels[1] := 'Color'; values[1] := color;
  labels[2] := 'LPI';   values[2] := LPI;
  labels[3] := 'Size';  values[3] := size;

  for i := 0 to 3 do
  begin
    col := TJSHTMLElement(document.createElement('div'));
    col.className := 'col-sm';

    labelEl := TJSHTMLElement(document.createElement('label'));
    labelEl.className := 'pe-2';
    labelEl.style.setProperty('font-weight', '700');
    labelEl.style.setProperty('font-size', '15px');
    labelEl.textContent := labels[i] + ':';

    inputEl := TJSHTMLElement(document.createElement('input'));
    inputEl.className := 'form-control input-sm';
    inputEl.setAttribute('style', 'width: 100%');
    inputEl.setAttribute('value', values[i]);
    inputEl.setAttribute('id', 'input-' + IntToStr(container.childElementCount) + '-' + IntToStr(i));

    col.appendChild(labelEl);
    col.appendChild(inputEl);
    newRow.appendChild(col);
  end;

  // Add remove button
  removeCol := TJSHTMLElement(document.createElement('div'));
  removeCol.className := 'col-auto d-flex align-items-end pb-1';

  removeBtn := TWebButton.Create(Self);
  removeBtn.Caption := 'Remove';
  removeBtn.ElementClassName := 'btn btn-danger btn-sm mt-1';
  removeBtn.ParentElement := removeCol;
  removeBtn.ElementHandle.style.setProperty('height', '30px');
  removeBtn.OnClick := RemoveColorRow;

  newRow.appendChild(removeCol);
  container.appendChild(newRow);
end;


procedure TFOrderEntryCorrugated.RemoveColorRow(Sender: TObject);
var
  btn: TWebButton;
  rowElement: TJSHTMLElement;
begin
  EditMode();
  btn := TWebButton(Sender);
  if Assigned(btn.ElementHandle) and Assigned(btn.ElementHandle.parentElement) then
  begin
    // Assuming button is inside a <div> inside the row
    rowElement := TJSHTMLElement(btn.ElementHandle.parentElement.parentElement);
    if Assigned(rowElement) then
      rowElement.remove;
  end;
end;


procedure TFOrderEntryCorrugated.btnAddColorClick(Sender: TObject);
begin
  EditMode();
  addColorRow('','','','');
end;


procedure TFOrderEntryCorrugated.WebButton2Click(Sender: TObject);
begin
  ShowAddAddressForm();
end;

procedure TFOrderEntryCorrugated.SendAddressToServer(AddressJSON: TJSONObject);
var
  Response: TXDataClientResponse;
  notification: TJSObject;
begin
  Response := await(XDataWebClient1.RawInvokeAsync('ILookupService.AddShippingAddress',
              [AddressJSON.ToString]));

  notification := TJSObject(Response.Result);
  ShowToast(string(notification['status']));
  xdwdsShipTo.Close;
  xdwdsShipTo.SetJSONData(TJSObject(notification['customer'])['SHIPPING_ADDRESS_LIST']);
  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.Position := poScreenCenter;
  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', xdwdsOrder.FieldByName('COMPANY_ID').AsString);

        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');
        console.log(AddressJSON);
        sendAddressToServer(AddressJSON);
      end;
    end
  );
end;


procedure TFOrderEntryCorrugated.btnAddClick(Sender: TObject);
var
  newform: TFAddOrder;
  orderType: string;
begin
  newform := TFAddOrder.CreateNew;

  newform.Caption := 'Select Customer and Order Type';
  newForm.Popup := True;
  newForm.Position := poScreenCenter;
  newForm.Border := fbDialog;

  // used to manage Back button handling to close subform
  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';

        if orderType = 'corrugated' then
          FViewMain.ViewOrderEntryCorrugated('', newForm.DBID, 'ADD', '')
        else if orderType = 'web' then
          FViewMain.ViewOrderEntryWeb('', newForm.DBID, 'ADD', '')
        else
          FViewMain.ViewOrderEntryCuttingDie('', newForm.DBID, 'ADD', '');
      end;
    end
  );
end;


procedure TFOrderEntryCorrugated.btnCancelClick(Sender: TObject);
begin
  ShowConfirmationModal(
    'Are you sure you want to cancel all changes?',
    'Yes',
    'No',
    procedure(confirmed: Boolean)
    begin
      if confirmed then
      begin
        FViewMain.change := false;
        if OrderID <> '' then
          FViewMain.ViewOrderEntryCorrugated(OrderID, '', 'EDIT', 'Failure:  Changes Discarded')
        else
          FViewMain.ViewOrders('');
      end;
    end
  );
end;


procedure TFOrderEntryCorrugated.btnCloseClick(Sender: TObject);
begin
  FViewMain.ViewOrders('');
end;


procedure TFOrderEntryCorrugated.WebFormCreate(Sender: TObject);
begin
   if not DMConnection.ApiConnection.Connected then
   begin
    DMConnection.ApiConnection.OpenAsync;
   end;
end;


procedure TFOrderEntryCorrugated.getOrder(Order_ID: string);
// retrieves an order from the server then loads the info into the page
var
  xdcResponse: TXDataClientResponse;
  orderList : TJSObject;
  i: integer;
  data: TJSArray;
  order, customer, items: TJSObject;
  callListLength: integer;
  tempString, strColorList: string;
  colorObject: TJSObject;
  colorList: TJSArray;
  colorLength: integer;
  color: TJSObject;
  colorJSON: TJSONObject;
  colorListJSON: TJSONArray;
  container: TJSHTMLElement;
begin
  try
    xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GetCorrugatedOrder', [Order_ID]));
    order :=  TJSObject(xdcResponse.Result);
    data := TJSArray(order['data']);
    xdwdsOrder.Close;
    xdwdsOrder.SetJsonData(order);
    xdwdsOrder.Open;
    console.log(order);

    container := TJSHTMLElement(document.getElementById('additionalFields'));
    if Assigned(container) then
      container.innerHTML := '';  // Wipe previous colors

    if xdwdsOrdercolors_colors.Value <> '' then
    begin
    colorObject := TJSObject(TJSJSON.parse(xdwdsOrdercolors_colors.Value));
    colorList := TJSArray(colorObject['items']);
    for I := 0 to colorList.length -1 do
      begin
        color := TJSObject(colorList[i]);
        addColorRow(String(color['#']), string(color['Color']), string(color['LPI']), string(color['Size']));
      end;
    end;


    if xdwdsOrder.FieldByName('mounting_loose').AsString <> '' then
      cbLoose.Checked := true;

    if xdwdsOrder.FieldByName('mounting_strip_mount').AsString <> '' then
      cbStripMount.Checked := true;

    xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GetCustomer', [xdwdsOrder.FieldByName('COMPANY_ID').AsString]));
    customer :=  TJSObject(xdcResponse.Result);
    console.log(customer);

    xdwdsShipTo.Close;
    xdwdsShipTo.SetJSONData(customer['SHIPPING_ADDRESS_LIST']);
    xdwdsShipTo.Open;

    customer_qb_id := string(customer['QB_LIST_ID']);

    xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GetItems', []));
    items := TJSObject(xdcResponse.Result);
    xdwdsQBItem.Close;
    xdwdsQBItem.SetJsonData(items['data']);
    xdwdsQBITEM.Open;

    xdwdsQBItem.Locate('name', wdbcbQuickbooksItem.Text , []);
    wdbcbQuickbooksItem.Text := xdwdsQBItem.FieldByName('name').AsString;
    edtQBItemDescription.text := xdwdsQBItem.FieldByName('description').AsString +
                                ' - ' + xdwdsOrder.FieldByName('staff_fields_job_name').AsString;
  except
    on E: EXDataClientRequestException do
      Utils.ShowErrorModal(E.ErrorResult.ErrorMessage);
  end;
end;


procedure TFOrderEntryCorrugated.SetEmptyOrderInfo(customerID: string);
// gets a customer from the database then loads the appropiate fields
var
  xdcResponse: TXDataClientResponse;
  customer : TJSObject;
  address: string;
  items: TJSObject;
begin
  try
    xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GetCustomer', [customerID]));
    customer :=  TJSObject(xdcResponse.Result);
    console.log(customer);
    xdwdsOrder.Close;
    xdwdsOrder.SetJsonData(customer);
    xdwdsOrder.Open;
    xdwdsOrder.Edit;

    xdwdsShipTo.Close;
    xdwdsShipTo.SetJSONData(customer['SHIPPING_ADDRESS_LIST']);
    xdwdsShipTo.Open;

    customer_qb_id := string(customer['QB_LIST_ID']);

    xdwdsOrder.Close;
    xdwdsOrder.Open;
    xdwdsOrder.Append;
    xdwdsOrder.FieldByName('NAME').AsString := string(customer['NAME']);
    xdwdsOrder.FieldByName('SHORT_NAME').AsString := string(customer['SHORT_NAME']);
    xdwdsOrder.FieldByName('staff_fields_invoice_to').AsString := string(customer['staff_fields_invoice_to']);

    xdwdsOrder.FieldByName('COMPANY_ID').AsString := customerID;
    xdwdsOrder.Post;

    xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GetItems', []));
    items :=  TJSObject(xdcResponse.Result);
    xdwdsQBItem.Close;
    xdwdsQBItem.SetJsonData(items['data']);
    xdwdsQBITEM.Open;

    {dtpOrderDate.Date := 0;
    dtpProofDate.Date := 0;
    dtpArtDue.Date := 0;
    dtpPlateDue.Date := 0;
    dtpMountDue.Date := 0;
    dtpShipDate.Date := 0;
    dtpApprovedDate.Date := 0;}
  except
    on E: EXDataClientRequestException do
      Utils.ShowErrorModal(E.ErrorResult.ErrorMessage);
  end;
end;




procedure TFOrderEntryCorrugated.tmrReturnTimer(Sender: TObject);
begin
  Utils.HideSpinner('spinner');
  tmrReturn.Enabled := false;
  FViewMain.ViewOrders('Success: Order Successfully Deleted');
end;


procedure TFOrderEntryCorrugated.EditMode();
begin
  xdwdsShipTo.Edit;
  xdwdsQBItem.Edit;
  xdwdsOrder.Edit;

  FViewMain.change := true;
  btnCopy.Enabled := false;
  btnPDF.Enabled := false;
  btnDelete.Enabled := false;
  btnClose.Enabled := false;
  btnSave.Enabled := true;
  btnCancel.Enabled := True;
  btnEdit.Enabled := false;
  btnAdd.Enabled := false;
  btnQB.Enabled := false;

  // Enable all non-DB checkboxes manually
  cbRefArtAPDF.Enabled := True;
  cbRefArtPrintCard.Enabled := True;
  cbExistingCuttingDie.Enabled := True;
  cbFTP.Enabled := True;
  cbSampleCarton.Enabled := True;
  cbPlates.Enabled := True;
  cbColorCopy.Enabled := True;
  cbStripMount.Enabled := True;
  cbFullMount.Enabled := True;
  cbStickyBak.Enabled := True;
  cbLoose.Enabled := True;
  cbExcaliburDie.Enabled := True;
  cbEmail.Enabled := True;
  cbArtApprovedAsIs.Enabled := True;
  cbPDFFile.Enabled := True;
  cbWideFormat.Enabled := True;
  cbPrintCard.Enabled := True;
  cbFullSizePanel.Enabled := True;
  wdbcbQuickbooksItem.Enabled := true;
  wdbcbShipTo.Enabled := true;

  lblFormState.Caption := 'Edit Mode';
  lblFormState.ElementHandle.classList.remove('text-danger');
  lblFormState.ElementHandle.classList.add('text-success');
end;


procedure TFOrderEntryCorrugated.edtJobNameExit(Sender: TObject);
begin
  edtQBItemDescription.text := xdwdsQBItem.FieldByName('description').AsString +
                              ' - ' + xdwdsOrder.FieldByName('staff_fields_job_name').AsString;
end;

procedure TFOrderEntryCorrugated.edtPriceExit(Sender: TObject);
var
  v: Double;
begin
  if TryStrToFloat(edtPrice.Text, v) then
  begin
    xdwdsOrderstaff_fields_price.AsFloat := v;
    xdwdsOrderstaff_fields_price.AsString := FormatFloat('0.00', v);
    edtPrice.Text := FormatFloat('0.00', v)
  end;
end;

procedure TFOrderEntryCorrugated.ViewMode;
begin
  btnPDF.Enabled := true;
  btnDelete.Enabled := true;
  btnClose.Enabled := true;
  btnCopy.Enabled := true;
  btnSave.Enabled := false;
  btnCancel.Enabled := false;
  btnEdit.Enabled := true;
  btnAdd.Enabled := true;
  btnQB.Enabled := true;
  FViewMain.change := false;

  // Explicitly disable all non-DB checkboxes
  cbRefArtAPDF.Enabled := False;
  cbRefArtPrintCard.Enabled := False;
  cbExistingCuttingDie.Enabled := False;
  cbFTP.Enabled := False;
  cbSampleCarton.Enabled := False;
  cbPlates.Enabled := False;
  cbColorCopy.Enabled := False;
  cbStripMount.Enabled := False;
  cbFullMount.Enabled := False;
  cbStickyBak.Enabled := False;
  cbLoose.Enabled := False;
  cbExcaliburDie.Enabled := False;
  cbEmail.Enabled := False;
  cbArtApprovedAsIs.Enabled := False;
  cbPDFFile.Enabled := False;
  cbWideFormat.Enabled := False;
  cbPrintCard.Enabled := False;
  cbFullSizePanel.Enabled := False;
  wdbcbQuickbooksItem.Enabled := false;
  wdbcbShipTo.Enabled := false;

  lblFormState.Caption := 'View Mode';
  lblFormState.ElementHandle.classList.remove('text-success');
  lblFormState.ElementHandle.classList.add('text-danger');
end;


procedure TFOrderEntryCorrugated.wdbcbQuickbooksItemChange(Sender: TObject);
begin
  xdwdsQBItem.Locate('name', wdbcbQuickbooksItem.Text , []);
  wdbcbQuickbooksItem.Text := xdwdsQBItem.FieldByName('name').AsString;
  edtQBItemDescription.text := xdwdsQBItem.FieldByName('description').AsString +
                              ' - ' + xdwdsOrder.FieldByName('staff_fields_job_name').AsString;
end;

function TFOrderEntryCorrugated.VerifyQBOrder: Boolean;
var
  msg, SQL: string;
begin
  Result := True;
  msg := 'To add an order to QuickBooks, the following must be present:' + sLineBreak;

  if edtCompanyName.Text = '' then
  begin
    msg := msg + '- Company Name cannot be empty' + sLineBreak;
    Result := False;
  end;

  if edtCompanyAccountName.Text = '' then
  begin
    msg := msg + '- Company ID cannot be empty' + sLineBreak;
    Result := False;
  end;

  if edtInvoiceTo.Text = '' then
  begin
    msg := msg + '- Invoice To cannot be empty' + sLineBreak;
    Result := False;
  end;

  if wdbcbShipTo.Text = '' then
  begin
    msg := msg + '- Ship To cannot be empty' + sLineBreak;
    Result := False;
  end;

  if dtpOrderDate.Date = 0 then
  begin
    msg := msg + '- Order Date cannot be empty' + sLineBreak;
    Result := False;
  end;

  if edtPrice.Text = '' then
  begin
    msg := msg + '- Price cannot be empty' + sLineBreak;
    Result := False;
  end;

  if edtQuantity.Text = '' then
  begin
    msg := msg + '- Quantity cannot be empty' + sLineBreak;
    Result := False;
  end;

  if wdbcbQuickBooksItem.Text = '' then
  begin
    msg := msg + '- Item cannot be empty' + sLineBreak;
    Result := False;
  end;

  if edtJobName.Text = '' then
  begin
    msg := msg + '- Job Name Cannot be empty' + sLineBreak;
    Result := False;
  end;

  xdwdsQBItem.Locate('name', xdwdsOrder.FieldByName('staff_fields_quickbooks_item').AsString, []);
  if xdwdsQBItem.FieldByName('QB_ID').AsString = '' then
  begin
    msg := msg + '- Item Must be Linked to QuickBooks' + sLineBreak;
    Result := False;
  end;

  if customer_qb_id = '' then
  begin
    msg := msg + '- Customer Must be Linked to QuickBooks' + sLineBreak;
    Result := False;
  end;

  if not result then
  asm
    alert(msg);
  end;
end;

function TFOrderEntryCorrugated.VerifyOrder: Boolean;
var
  input: TJSHTMLInputElement;
begin
  result := true;

  input := TJSHTMLInputElement(document.getElementById('edtcompanyname'));
  if edtCompanyName.Text = '' then
  begin
    input.classList.add('is-invalid');
    result := false;
  end
  else
    input.classList.remove('is-invalid');

  input := TJSHTMLInputElement(document.getElementById('edtjobname'));
  if edtJobName.Text = '' then
  begin
    input.classList.add('is-invalid');
    result := false;
  end
  else
    input.classList.remove('is-invalid');


  input := TJSHTMLInputElement(document.getElementById('edtaccountcompanyname'));
  if edtCompanyAccountName.Text = '' then
  begin

    input.classList.add('is-invalid');
    result := false;
  end
  else
    input.classList.remove('is-invalid');

  input := TJSHTMLInputElement(document.getElementById('edtinvoiceto'));
  if edtInvoiceTo.Text = '' then
  begin
    input.classList.add('is-invalid');
    result := false;
  end
  else
    input.classList.remove('is-invalid');


  input := TJSHTMLInputElement(document.getElementById('wcbshipto'));
  if wdbcbShipTo.Text = '' then
  begin
    input.classList.add('is-invalid');
    result := false;
  end
  else
    input.classList.remove('is-invalid');

  input := TJSHTMLInputElement(document.getElementById('dtporderdate'));
  if dtpOrderDate.Date = 0 then
  begin
    input.classList.add('is-invalid');
    result := false;
  end
  else
    input.classList.remove('is-invalid');

  input := TJSHTMLInputElement(document.getElementById('edtprice'));
  if ( ( edtPrice.Text = '' ) or ( StrToFloat(edtPrice.Text) < 0 ) )then
  begin

    input.classList.add('is-invalid');
    result := false;
  end
  else
    input.classList.remove('is-invalid');

  input := TJSHTMLInputElement(document.getElementById('edtquantity'));
  if ( ( edtQuantity.Text = '' ) or ( StrToFloat(edtQuantity.Text) <= 0 ) ) then
  begin

    input.classList.add('is-invalid');
    result := false;
  end
  else
    input.classList.remove('is-invalid');

  input := TJSHTMLInputElement(document.getElementById('wcbqbitem'));
  if wdbcbQuickbooksItem.Text = '' then
  begin

    input.classList.add('is-invalid');
    result := false;
  end
  else
    input.classList.remove('is-invalid');
end;

initialization
  RegisterClass(TFOrderEntryCorrugated);

end.


