📁 Showcase
Invoice center

Invoice center

Set Backend

1. Invoice variables

a. Sequence variable

// variable sequence
 
ensure var VarInvoiceSeq kind: sequence deploy: fixedOnDeploy value: 1
 

b. InvoiceId pattern variable

// pattern variable for invoice id identifier
 
ensure var VarTextPatternFormInvoiceLinkInvoiceId kind: text 
  deploy: fixedOnDeploy 
  value: "INV-${p}" 
  paramSet: ["p"]
 

c. Rupee symbol variable

// pattern variable for rupee symbol
 
ensure var VarTextRupeeSymbol kind: text deploy: fixedOnDeploy value: "₹"
 

2. InvoiceHistory spreadsheet

// this spreadsheet stores the invoice informaion for a customer
 
ensure spreadsheet: InvoiceHistory
  withFields: [InvoiceId, DateRange, InvoiceDate, TeaPrice, CoffeePrice, OfficeRowId, OfficeName, OfficeNo, Mobile]
  ofTypes: [identifier, dateRange, date, number, number, rowId, text, text, mobileNumber]
  readRoleSet: [Owner]
  removeRoleSet: [Owner]
  updateRoleSet: [Owner]
 

3. Decorate spreadsheet

// update the properties of the fields in InvoiceHistory
 
ensure form FormInvoiceHistory 
  allowToPrintForm: true
ctx rename OutputInvoice
 
ensure section: Details
ensure field InvoiceId 
  setOnSend: true
  textPatternVar: {
      'var': 'VarTextPatternFormInvoiceLinkInvoiceId',
      'paramSet': [
        '${var:VarInvoiceSeq}'
      ]
    }
ensure field InvoiceDate defaultValue: "now"
ensure field TeaPrice 
  prefixVar: {
      'var': 'VarTextRupeeSymbol'
    }
ensure field CoffeePrice 
  prefixVar: {
      'var': 'VarTextRupeeSymbol'
    }
 
ensure grid: Items
ensure field Date kind: date
ensure field Time kind: pickText
  sourceVar: VarSetOfTextTime
ensure field TotalTea kind: number
ensure field TotalCoffee kind: number
ensure field TotalPrice kind: number
  prefixVar: {
      'var': 'VarTextRupeeSymbol'
    }
 
ensure layoutGrid Table kind: table 
  showComps: [Items.Date, Items.Time, TotalTea, TotalCoffee, TotalPrice]
  columnSizeSet: ["Flex"]
 
ensure section: Summary
ensure field TotalBill kind: number
  prefixVar: {
      'var': 'VarTextRupeeSymbol'
    }
ensure field GST kind: number
ensure field GrandTotal kind: number
  prefixVar: {
      'var': 'VarTextRupeeSymbol'
    }
ensure field PaymentStatus kind: paymentStatus
  defaultValue: pending
ensure field PaymentQR kind: showCode
  label: "Payment QR" 
  codeType: qrCode 
  showLabel: false
ensure field PaymentLink kind: hyperlink
ensure field InvoiceLink kind: hyperlink
ensure field PaymentQR defaultField: PaymentLink
 
ensure formula TotalPrizeFormula 
  assignToField: TotalPrice 
  formula: "(${f:TotalTea} * ${f:TeaPrice}) + (${f:TotalCoffee} * ${f:CoffeePrice})"
 
ensure formula TotalBillFormula 
  assignToField: TotalBill 
  formula: "SUM(${f:TotalPrice})"
 
ensure formula GSTFormula 
  assignToField: GST 
  formula: "${f:TotalBill} * 0.18"
 
ensure formula GrandTotalFormula 
  assignToField: GrandTotal 
  formula: "${f:TotalBill} + ${f:GST}"
 
ensure spreadsheet InvoiceHistory
  searchables: [OfficeName, OfficeNo, Mobile]
  queryables : [PaymentStatus]
 

4. FilterInvoice form

// this form is used for filter out the customer for invoice generation
 
ensure form FilterInvoice 
ensure section: Details 
 
ensure field DateRange kind: dateRange 
  autoFocus: false 
  required: true 
  fromDefault: "startOfMonth" 
  toDefault: "endOfMonth"
ensure field OfficeRef kind: ref
  spreadsheet: OfficeMaster 
  copyFieldMap: {
      'OfficeMasterRowId': '$RowId',
      'Name': 'Name'
    } 
  layoutSpreadsheet: ListLayout
 

5. Reports

a. GetInvoiceCustomerInfo report

// this report fetches customer information
 
ensure report GetInvoiceCustomerInfo kind: query 
  inputForm: FilterInvoice 
  outputForm: OutputInvoice 
  fromSpreadsheets: [OfficeMaster] 
  neoQL: "select
        { 'from' : ${in:Details.DateRange.from}, 'to' : ${in:Details.DateRange.to} } as ${out:Details.DateRange},
        ${ctx:row.id} as ${out:Details.OfficeRowId}, 
        ${ss:OfficeMaster.Details.Name} as ${out:Details.OfficeName},
        ${ss:OfficeMaster.Details.OfficeNumber} as ${out:Details.OfficeNo},
        ${ss:OfficeMaster.Details.MobileNumber} as ${out:Details.Mobile},
        ${ss:OfficeMaster.Details.TeaPrice} as ${out:Details.TeaPrice},
        ${ss:OfficeMaster.Details.CoffeePrice} as ${out:Details.CoffeePrice},
        MILLIS(CLOCK_LOCAL()) as ${out:Details.InvoiceDate}
    from ${ss}
    where ${ctx:row.type} = ${ss:OfficeMaster} and 
    ${ctx:row.id} = ${in:Details.OfficeMasterRowId}"
    

b. GetInvoiceOrders report

// this report fetches information of customer's order for given date range
 
ensure report GetInvoiceOrders kind: query 
  inputForm: FilterInvoice 
  outputForm: OutputInvoice 
  fromSpreadsheets: [OrderBook] 
  neoQL: "select
        ${ss:OrderBook.Order.Date} as ${out:Items.Date},
        ${ss:OrderBook.Order.Time} as ${out:Items.Time},
        ${ss:OrderBook.Order.TeaCount} as ${out:Items.TotalTea},
        ${ss:OrderBook.Order.CoffeeCount} as ${out:Items.TotalCoffee},
        ${ss:OrderBook.Order.Total} as ${out:Items.TotalPrice}
    from ${ss}
    where ${ctx:row.type} = ${ss:OrderBook}
    and ${ss:OrderBook.Order.Date} >= ${in:Details.DateRange.from}
    and ${ss:OrderBook.Order.Date} <= ${in:Details.DateRange.to}
    and ${ss:OrderBook.Office.OfficeMasterRowId} = ${in:Details.OfficeMasterRowId}
    order by ${ss:OrderBook.Order.Date}"
 

c. GetInvoiceComposite report

// this report combines output of GetInvoiceOrders and GetInvoiceCustomerInfo reports
 
ensure report GetInvoiceComposite kind: composite 
  inputForm: FilterInvoice 
  outputForm: OutputInvoice
  mergeReports: [GetInvoiceCustomerInfo, GetInvoiceOrders]
 

d. GetInvoice report

// this report maps GetInvoiceOrders report and save to spreadsheet as per output form
 
ensure report GetInvoice kind: mapper 
  description: "Prevents computing report invoice again for the same invoice filter" 
  label: "Get Invoice" 
  inputForm: FilterInvoice 
  outputForm: OutputInvoice 
  mappedReport: GetInvoiceComposite
  saveToSpreadsheet: InvoiceHistory
 

6. Payment

// adding payment
 
deploy payment RazorPay
  kind: razorpay
  allowedPaymentMethodSet: [netbanking, card, upi]
  defaultCurrency: "INR"
  apiKey: "rzp_test_Yi1HjKJIQC2NJS"
  apiSecret: "VQXKghIx5bJBTkHXcZ6g12HK"
  default: true  
 

7. Invoice automation

a. Automation variables

• Deeplink mapping variable
// mapping variable for deeplink form
 
ensure var VarMappingGenerateInvoiceDeeplink kind: mapping deploy: fixedOnDeploy
  fromForm: OutputInvoice 
  toForm: FilterInvoice 
  fieldMappingMap: {
      'map': {
        '${f:DateRange}': 'DateRange',
        '${f:OfficeName}': 'Name',
        '${f:OfficeRowId}': 'OfficeMasterRowId'
      }
    }
 
• Webhook mapping variable
// mapping variable for webhook automation step
 
ensure var VarMappingPaymentUpdateInvoiceSheet kind: mapping deploy: fixedOnDeploy
  toForm: OutputInvoice 
  fieldMappingMap: {
      'map': {
        '${d:PaymentStatus.paid}': 'Summary.PaymentStatus'
      }
    }
 
• Message variable
// message variable for message send on WhatsApp automation step
 
ensure var VarParagraphInvoiceMessageSendOnWhatsApp kind: paragraph 
  deploy: fixedOnDeploy 
  value: "Hello ${name}, 
 
    Here is your invoice dated, ${date} with total ${total}.
 
    * Invoice Link: ${invoice}
    * Payment Link: ${payment}" 
 

b. Deeplink

• OutputInvoice layouts
// layouts for form OutputInvoice
 
ensure form OutputInvoice
 
ensure layout Start1 kind: content 
  direction: vertical 
  start.fields: [Details.OfficeName, Details.OfficeNo, Details.Mobile, Details.InvoiceId] 
 
ensure layout Start2 kind: content 
  direction: vertical 
  start.fields: [Details.DateRange, Details.InvoiceDate, Details.TeaPrice, Details.CoffeePrice] 
 
ensure layout Start kind: content 
  direction: horizontal 
  showBorderSet: ["bottom", "top"] 
  contentPadding: thick 
  showPaddingSet: ["bottom", "top"] 
  start.formLayouts: [Start1, Start2] 
 
ensure layout End1 kind: content 
  direction: vertical 
  start.fields: [Summary.TotalBill, Summary.GST, Summary.GrandTotal] 
 
ensure layout End2 kind: content 
  direction: vertical 
  end.fields: [Summary.PaymentQR]
 
ensure layout End kind: content 
  direction: horizontal 
  showBorderSet: ["top"] 
  contentPadding: thick 
  showPaddingSet: ["top", "bottom"] 
  start.formLayouts: [End1]  
  end.formLayouts: [End2]
 
ensure layout Template kind: template showEnterprise: true paperSize: a4Size
 
ensure layout Main kind: content 
  direction: vertical 
  start.formLayouts: [Start] 
  flexCenter.gridLayouts: [Items.Table] 
  end.formLayouts: [End]
 
• GetInvoice deeplink
// deeplink for report GetInvoice to send the invoice in WhatsApp message
 
ensure deeplink DeeplinkGetInvoice kind: report 
  visibilityConstraint: allowPublicSharing 
  creationRoles: [Owner] 
  expiry: noExpiry 
  showEnterpriseImageInLinkPreview: true 
  report: GetInvoice 
  outputFormContentLayout: Main 
  outputFormTemplateLayout: Template
 

c. Automation

// spreadsheet automation to perform task on spreadsheet insert
 
ensure automation AutomateInvoiceCache kind: spreadsheet spreadsheet: InvoiceHistory
 
ensure event BeforeInsert fire: beforeInsert
 
ensure step GenerateInvoiceDeeplink kind: generateDeeplink
  deeplink: DeeplinkGetInvoice 
  deeplinkField: InvoiceLink 
  inputFormMappingVar: VarMappingGenerateInvoiceDeeplink
  
 
ensure step GeneratePaymentLink kind: generatePaymentLink 
  expiryDurationValue.argName: "expiryDurationValue" 
  expiryDurationValue.kind: constant 
  allowedPaymentMethodSet: ["upi"] 
  referenceIdField: Details.InvoiceId 
  spreadsheetRowIdField: $RowId 
  paymentLinkField: Summary.PaymentLink 
  currencyValue.argName: "currencyValue" 
  currencyValue.kind: constant 
  amountValue.argName: "amountValue" 
  amountValue.kind: field
 
ensure event AfterInsert fire: afterInsert
 
// TODO: Change in Dto will have to decide the new Cli pattern
ensure step MessageSendOnWhatsapp kind: messageSendOnWhatsapp
 messageVar: {
      'var': 'VarParagraphInvoiceMessageSendOnWhatsApp',
      'paramSet': [
        '${f:Details.OfficeName}',
        '${f:Details.InvoiceDate}',
        '${f:Summary.GrandTotal}',
        '${f:Summary.InvoiceLink}',
        '${f:Summary.PaymentLink}'
      ]
    }
 dataSourceField: Details.Mobile
 
ensure automation WebhookRazorpayPayment kind: webhook callbackKind: razorpayPaymentReceipt
 
ensure event OnCallback fire: onCallback
 
ensure step UpdateSpreadsheet kind: updateSpreadsheet 
  targetSpreadsheet: InvoiceHistory 
  sourceToTargetMappingVar: VarMappingPaymentUpdateInvoiceSheet
 

Set frontend

1. SendInvoiceReport action

// creates the invoice for a customer and sends it on WhatsApp as deeplink
 
ensure action SendInvoiceReport kind: report 
  label: "Send invoice" 
  icon: "AnalyticsRounded" 
  report: GetInvoice 
  outputFormContentLayout: Main 
  outputFormTemplateLayout: Template 
  sendMessageToInbox: true
 

2. ShowInvoiceHistory action

// fetches the history of invoices
 
ensure spreadsheet InvoiceHistory
ensure layoutSpreadsheet Table kind: table 
  showComps: [InvoiceId, DateRange, InvoiceDate, OfficeName, GrandTotal, PaymentStatus]
 
ensure action ShowInvoiceHistory kind: spreadsheetEditor 
  icon: "EditNoteRounded" 
  spreadsheet: InvoiceHistory 
  layoutSpreadsheet: Table
 

3. InvoiceCenter group

//  this group has all the actions those can generate invoice
 
ensure group InvoiceCenter hideActionMenu: true
pinnedActions: [SendInvoiceReport, ShowInvoiceHistory] 
  actionPermission: {
      'SendInvoiceReport': {
        'roles': [
          'Owner'
        ]
      },
      'ShowInvoiceHistory': {
        'roles': [
          'Owner'
        ]
      }
    }