Appearance
Sales Invoices
| Backlog field | Value |
|---|---|
| Story ID | AP-SAL-011 |
| Epic | Sales |
| Story type | Business workflow |
| Review status | Draft - business analyst and business owner review required |
| Source evidence | AppsPortal.Apis controller, application command/query handlers, validators, domain entities, and matching MFE workflow where available |
| Last source review | 2026-07-10 |
User story
As sales users, I want to create, validate, post, print, send, and export customer invoices so that stock, revenue, tax, receivables, and payments are updated correctly.
Posting reference: AppsPortal Posting Ledger explains debit/credit construction. Delegation and Interaction Contracts explains module ownership, delegated commands, linked records, commit boundaries, and reversal propagation.
Acceptance criteria
- Only authorized users can view or execute the feature's actions.
- Required business data, active dependencies, tenant/branch scope, and current document state are validated.
- Invalid requests return actionable validation errors without applying a partial change.
- Search, list, view, print, and export operations use the same authorized business scope.
- Material create, edit, status, approval, posting, reversal, and integration actions are auditable where applicable.
- Financial or stock effects are applied atomically and no more than once.
Posting details
Post validates Draft state, open period, customer, currency/rate, lines, price and discount authority, credit limits, tax, payment terms, warehouse/UOM/tracking requirements, available stock, and source-order quantities. All rows below are committed as one operation; a failed row leaves the invoice Draft with no partial effect.
General ledger posting
| Condition / component | Debit | Credit | Amount basis | Account resolution and notes |
|---|---|---|---|---|
| Customer invoice total | Customer Receivable | - | Local grand total | Customer Receivable, then Customer Category Receivable; missing account blocks Post. |
| Revenue line | - | Sales Revenue | LocalTotalAfterDiscount + LocalDiscountAmount, grouped by account and line cost center | When Inventory is accessible: Item Revenue, then Item Category Items Revenue, then Inventory General Settings Items Revenue. When Inventory is inaccessible: Customer Sales, then Customer Category Sales. |
| Separate invoice discount | Customer Discount | - | Total local discount | Customer Discount, then Customer Category Discount. Created only when the configured posting model requires a separate discount line and discount is non-zero. |
| Additive output tax | - | Output Tax | Calculated local tax | Tax account, then Tax Group account. |
| Deductive/withholding tax | Tax / Withholding | - | Calculated local tax | Tax account, then Tax Group account; direction follows the tax effect. |
| Advance-payment VAT transfer | Payment-detail Tax | Finance Advanced Payment Tax | VAT transferred from the advance | Created only when the invoice consumes an eligible advance-payment VAT balance. |
| Inventory cost for each storable line | Cost of Goods Sold | Warehouse Inventory | Posted issue cost, not sales price | Created by delegated Stock Out. Current Stock Out service uses Inventory General Settings COGS; Warehouse GL comes from the issuing warehouse. |
| Service line inventory cost | - | - | None | No COGS or Warehouse GL entry because no Stock Out is created for a service line. The commercial revenue/tax/receivable rows still post. |
Inventory and Stock Out effect
| Line/source condition | Stock Out created? | Quantity and valuation effect | Tracking effect | Result returned to Sales |
|---|---|---|---|---|
| Storable inventory item and Inventory module accessible | Yes | Reduce warehouse on-hand/available quantity; consume valuation layers using the posted issue cost; update stock balances | Consume the selected batch/serial/expiry quantities; tracking totals must equal the line quantity | Stock Out ID, inventory journal ID, and posted cost links are stored against the invoice. |
| Service item | No | No warehouse quantity, cost layer, WMA, or last-purchase-cost change | None | Commercial invoice posts without a Stock Out link for that line. |
| Non-stock/service-only invoice | No | No Inventory document or inventory journal | None | Sales journal, balances, tax, and reconciliation may still post. |
| Inventory module inaccessible under the permitted commercial path | No | No stock validation or movement; revenue falls back to customer/customer-category Sales account | None | Invoice records no Stock Out. This path must only be allowed for lines that business policy permits without inventory control. |
| Insufficient stock, invalid UOM/tracking, count lock, missing COGS/Warehouse GL, or Stock Out failure | No committed Stock Out | No quantity or valuation change | No tracking change | Entire invoice Post rolls back and remains Draft. |
Other module and document effects
| Affected area | Effect when Post succeeds | No-effect / conditional rule |
|---|---|---|
| Accounting | Creates and posts the commercial journal and, for storable lines, links the Inventory Stock Out journal. | No journal is retained when any delegated operation fails. |
| Finance / reconciliation | Creates payment-term due balances and attempts eligible automatic reconciliation or advance-payment application. | No cash movement is created merely by posting an unpaid invoice; reconciliation occurs only when an eligible payment/advance exists. |
| Customer balances and credit | Increases customer receivable/outstanding balance and consumes applicable customer credit capacity. | Fully prepaid/reconciled amounts do not remain outstanding. |
| Salesperson credit | Updates salesperson credit exposure when that control is enabled. | No effect when no salesperson or no salesperson-credit policy applies. |
| Sales Order | Updates invoiced/remaining quantities and order fulfillment status when invoice lines originate from an order. | Standalone invoices do not affect a Sales Order. Service lines affect commercial fulfillment but not stock fulfillment. |
| Tax / e-invoicing | Records tax details and updates ETA/ZATCA eligibility/status data required by configuration. | Submission itself occurs only through the configured integration workflow. |
| Audit and reporting | Stores journal, Stock Out, reconciliation, source, balance, and posting references; marks the invoice Posted. | A retry after success creates no duplicate effect. |
Core acceptance scenarios
- Given a valid Draft invoice with accounts resolved Item -> Category -> Settings where applicable, when the sales user clicks Post, then commercial journal, optional Stock Out, balances, reconciliation, credit usage, links, and Posted state commit together.
- Given any revenue/receivable/discount/tax/COGS/warehouse account or delegated stock rule fails, when the operation is attempted, then the invoice remains Draft with no journal, stock, credit, or balance effect.
- Given the same Post request is retried after success, when the source is no longer Draft, then no duplicate journal, stock, balance, payment, or lifecycle effect is created.
Prerequisites and required data
- Draft invoice, authorized branch/company, open financial period, customer, currency/rate, invoice date, sequence, and at least one valid line.
- Each line requires item/service, UOM, quantity, price, and applicable warehouse/tracking for storable items.
- Tax is conditional on item/invoice VAT configuration. Salesperson, payment term, discount, project, notes, and payment intent are conditional/optional by policy.
- Customer credit, salesperson credit, price/discount authority, stock availability, UOM conversion, tax accounts, and source references are revalidated at Post.
Account resolution
- Receivable: customer accounting Receivable account, then customer category Receivable account, otherwise Post fails.
- Sales revenue when Inventory is accessible: item
ItemRevenueAccountId, then item categoryItemsRevenueAccountId, then Inventory General SettingsItemsRevenueAccountId; if all are missing, Post fails. Revenue lines are grouped by resolved account and optional line cost center. - Sales revenue when Inventory is not accessible: customer accounting Sales account, then customer category Sales account.
- Discount: customer accounting Discount account, then customer category Discount account when discount requires a separate line.
- VAT: tax account; if zero/missing, tax group account; if neither exists, Post fails.
- Inventory cost in the linked Stock Out: COGS uses Inventory General Settings in the current Stock Out journal service; a separate query supports category COGS then settings for consumers that call it.
Clicking Post
Post accepts Draft only, creates the sales journal, posts Stock Out for non-service items when Inventory is accessible, stores journal/Stock Out links, creates due balances from payment terms, attempts eligible automatic reconciliation, consumes customer and salesperson credit, marks Posted, and commits all effects together. Service-only invoices skip Stock Out.
Resulting balances and records
- Debit customer receivable for local grand total.
- Debit the customer discount account for total local discount when discount is greater than zero.
- Credit each resolved item/category/settings revenue account for
LocalTotalAfterDiscount + LocalDiscountAmount, grouped by account and line cost center. - For additive VAT, credit Tax account (or Tax Group account fallback); for deductive tax effect, debit it.
- When linked to advance payment VAT, debit the payment detail tax account and credit Finance Advanced Payment Tax account for the transferred VAT.
- Reduce warehouse stock and recognize COGS for storable items.
- Create/update invoice balance schedule, reconciliation state, customer credit, salesperson credit, ETA/ZATCA eligibility, reporting, and audit data.
If any journal, stock, tax, credit, period, or reconciliation prerequisite fails before commit, the invoice remains unposted without partial effects.
Field business definitions
| Field / group | Business meaning | Required and editable rules | Derived/default behavior | Posting dependency |
|---|---|---|---|---|
| Customer | Legal/commercial party that owes the invoice | Required on Add; cannot be replaced after Post | Drives currency, price policy, payment terms, receivable/discount accounts, tax treatment, and credit controls | Active, authorized customer with resolved Receivable account |
| Invoice date | Commercial and financial recognition date | Required; editable only while Draft and permitted | Determines financial period and may drive due date, exchange rate, tax period, and sequence scope | Date must belong to an open posting period |
| Due date / payment term | Date or schedule by which receivable becomes due | Payment term required by current Add form; due date may be calculated or adjusted by policy | Payment term generates one or more customer due-balance rows | Schedule total must equal invoice grand total |
| Currency and rate | Transaction currency and conversion to company local currency | Currency/rate required when invoice currency differs; rate must be positive | Customer/company defaults may prefill; local amounts are transaction amounts multiplied by the accepted rate and rounded by currency precision | All journal, tax, credit, and due values use the stored posting rate |
| Source type / source ID | Origin such as Sales Order or project context | Conditional; source ID required when a source type requires a document | Source lines and remaining quantities may prefill invoice lines | Source must be Posted/eligible and cannot be invoiced beyond remaining quantity |
| Warehouse | Issuing location for storable items | Required by current form; may be irrelevant to purely non-stock service policy | Filters available items, UOMs, tracking, and stock | Required for each storable line and supplies Warehouse GL |
| Price policy | Approved price-selection policy | Required by current Add form; change recalculates affected line prices/discount authority | Defaults from customer/settings when configured | Posted line price must satisfy policy and user authority |
| Salesperson | Commercial owner for reporting, target, commission, and optional credit control | Optional unless policy requires it | Customer or user context may default it | May update salesperson credit and commission reporting |
| Advanced-payment link | Whether eligible customer advance is applied | Optional toggle; available only when an eligible advance exists | Loads available advance and related VAT detail | Applied amount cannot exceed invoice or advance availability |
| Item/service | Sold product or service identity | Required for every line | Determines storable/service behavior, revenue fallback, taxes, UOMs, tracking, and description | Inactive/unauthorized item blocks Post |
| UOM | Commercial unit used for quantity and price | Required per item line | Conversion determines base quantity used by Inventory | Conversion must exist and remain valid at Post |
| Quantity | Number of selected UOM units invoiced | Required, positive, and within source/stock rules | Base quantity is derived from UOM conversion | Storable quantity must be available and tracking must reconcile |
| Price | Unit selling price before applicable discount/tax | Conditionally required/validated by frontend and mandatory for a valued line | Can default from price policy; changes recalculate totals and tax | Must respect price authority and stored precision |
| Discount amount | Authorized reduction of the line value | Optional; cannot exceed policy/line limits | Recalculates line net, tax base, totals, and possibly separate Discount GL | User/customer discount authority is revalidated at Post |
| Tax IDs | Applied tax rules for the line | Conditional on item/customer/company tax policy | Calculates additive/deductive tax and local tax values | Every posting tax requires a Tax or Tax Group account |
| Cost center | Management-accounting dimension for the revenue line | Optional unless account/policy requires it | Defaults may come from item/category/user context | Revenue journal grouping preserves the selected dimension |
| Tracking | Batch, serial, and/or expiry allocation | Required only for tracked storable items | Available identities are filtered by warehouse/item and remaining quantity | Tracking quantity must equal base issue quantity |
| Description / line description | Printable and audit narrative | Optional unless local policy requires it | May default from customer/item | Does not replace required account, item, or source data |
Status and action control matrix
| Action | Required state and permission | Preconditions | Successful result | Blocking/failure result |
|---|---|---|---|---|
| Add | InvoiceService_Add | Authorized company/branch; active dependencies available | Creates a Draft invoice and lines; no GL, stock, receivable, or tax ledger effect | Validation is shown and no incomplete document is committed unless draft-save policy explicitly permits it |
| Edit | Draft plus InvoiceService_Edit; route also uses preventPostedGuard | Record exists in user scope; no conflicting update; source quantities still valid | Updates Draft header/lines and recalculates totals | Posted, locked, deleted, stale, or unauthorized invoice remains unchanged |
| View | InvoiceService_View | Record belongs to authorized tenant/company/branch | Displays immutable business values, status, sources, journal, Stock Out, reconciliation, and e-invoice links | Forbidden/not-found does not expose invoice data |
| Delete | Draft plus Delete permission exposed by Sales controls | No posted effect or dependent document; deletion policy satisfied | Removes/cancels Draft from active workflow and refreshes list | Posted/dependent invoice is retained with business reason |
| Post | Draft plus Post permission | All commercial, financial, tax, stock, tracking, credit, source, and period checks pass | Commits commercial journal, conditional Stock Out, due balances, reconciliation/credit, source fulfillment, links, and Posted state | Any failed delegate rolls back every effect and invoice remains Draft |
| View/print permission and printable record | Required print template and integration context available | Produces current authorized invoice representation; may apply ZATCA confirmation workflow | Print/integration failure does not alter financial or stock state | |
| Open journal | Accounting view permission and linked journal ID | Invoice successfully produced a journal | Navigates to the exact immutable journal | Hidden/disabled when no link or no permission |
| Open stock issue | Inventory view permission and linked Stock Out ID | At least one storable line produced Stock Out | Navigates to the exact Stock Out | Hidden for service-only/no-stock invoices |
| Reverse/return | Return/Add permission through Sales Return workflow | Posted source, open period, remaining returnable quantity, eligible reconciliation and stock state | Creates linked opposite commercial and conditional stock effects; original audit record remains | Direct editing of Posted invoice is not used as reversal |
Reversal and dependency controls
| Dependency after invoice Post | Why it matters | Required treatment before/within reversal |
|---|---|---|
| Customer payment reconciliation | Due balance may already be settled | Unreconcile or allocate only the remaining eligible amount according to return/refund policy; never leave payment allocated above the revised due balance |
| Stock Out and later stock consumption | Returned stock may differ from original tracking/availability context | Sales Return creates a controlled Stock In for returned storable quantities; original Stock Out remains auditable |
| Sales Order fulfillment | Invoice consumed remaining order quantity | Return/cancellation policy must restore or retain order fulfillment consistently and prevent quantities exceeding ordered/returned totals |
| Customer and salesperson credit | Posting consumed exposure | Reverse/restore only the value actually reversed and keep other invoices/payments intact |
| Tax/e-invoice submission | External authority may have accepted the invoice | Use the configured credit-note/cancellation process; a local reversal must not silently invalidate an externally accepted document |
| Closed financial period | Original period may no longer permit changes | Post reversal in an allowed period under Finance policy; never mutate the original journal date/lines |
| Partial prior returns | Only remaining quantity/value is reversible | Validate cumulative return quantities, tax, discount, stock cost, and due-balance effects against the source |
Reconciliation checks
| Control total | Must reconcile to |
|---|---|
| Invoice local grand total | Customer Receivable journal debit and total due schedule before applied reconciliation |
| Sum of revenue, discount, and tax posting rows | Commercial journal balancing amount after rounding |
| Storable base quantities | Linked Stock Out detail and tracking quantities |
| Stock Out issue value | COGS debit and Warehouse GL credit |
| Applied advance/payment amount | Reduction in payment availability and invoice outstanding balance |
| Source invoiced quantities | Sales Order/project invoiced and remaining quantities |
Frontend page coverage
The following UI coverage is sourced from the pulled MFE route configuration. A Module-level supporting artifact mapping is evidence of a reachable screen, but requires BA confirmation that it belongs to this story rather than a more specific feature story.
| Route/page | Component | Mode | Route permission/guard | Mapping confidence | Source |
|---|---|---|---|---|---|
| (module default) | SalesInvoiceComponent | List/navigation | Permission: AppSalesPermissions.InvoiceService_List; Guards: PolicyAuthGuard | Explicit frontend feature rule | apps/sales/src/app/remote-entry/transaction/transaction.module.ts:170 |
| add | AddNewSalesInvoiceComponent | Add | Permission: AppSalesPermissions.InvoiceService_Add; Guards: PolicyAuthGuard | Explicit frontend feature rule | apps/sales/src/app/remote-entry/transaction/transaction.module.ts:216 |
| add/:id | AddNewSalesInvoiceComponent | Add | Permission: AppSalesPermissions.InvoiceService_Add; Guards: PolicyAuthGuard | Explicit frontend feature rule | apps/sales/src/app/remote-entry/transaction/transaction.module.ts:227 |
| edit/:id | EditNewSalesInvoiceComponent | Edit | Permission: AppSalesPermissions.InvoiceService_Edit; Guards: PolicyAuthGuard, preventPostedGuard | Explicit frontend feature rule | apps/sales/src/app/remote-entry/transaction/transaction.module.ts:204 |
| sales-invoice | MainSalesInvoiceComponent | List/navigation | Permission: AppSalesPermissions.InvoiceService_List; Guards: PolicyAuthGuard | Explicit frontend feature rule | apps/sales/src/app/remote-entry/transaction/transaction.module.ts:160 |
Observed frontend fields and validation
| Component | Control | Observed frontend rule | Component source |
|---|---|---|---|
| AddNewSalesInvoiceFormArrayComponent | costCenterId | Visible control; optional or API-dependent | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/add-new-sales-invoice/add-new-sales-invoice-form-array/add-new-sales-invoice-form-array.component.ts |
| AddNewSalesInvoiceFormArrayComponent | descriptionLine | Visible control; optional or API-dependent | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/add-new-sales-invoice/add-new-sales-invoice-form-array/add-new-sales-invoice-form-array.component.ts |
| AddNewSalesInvoiceFormArrayComponent | discountAmount | Visible control; optional or API-dependent | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/add-new-sales-invoice/add-new-sales-invoice-form-array/add-new-sales-invoice-form-array.component.ts |
| AddNewSalesInvoiceFormArrayComponent | itemId | Visible control; optional or API-dependent | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/add-new-sales-invoice/add-new-sales-invoice-form-array/add-new-sales-invoice-form-array.component.ts |
| AddNewSalesInvoiceFormArrayComponent | price | Conditionally required/validated in component | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/add-new-sales-invoice/add-new-sales-invoice-form-array/add-new-sales-invoice-form-array.component.ts |
| AddNewSalesInvoiceFormArrayComponent | quantity | Visible control; optional or API-dependent | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/add-new-sales-invoice/add-new-sales-invoice-form-array/add-new-sales-invoice-form-array.component.ts |
| AddNewSalesInvoiceFormArrayComponent | taxIds | Visible control; optional or API-dependent | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/add-new-sales-invoice/add-new-sales-invoice-form-array/add-new-sales-invoice-form-array.component.ts |
| AddNewSalesInvoiceFormArrayComponent | trackingType | Conditionally required/validated in component | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/add-new-sales-invoice/add-new-sales-invoice-form-array/add-new-sales-invoice-form-array.component.ts |
| AddNewSalesInvoiceFormArrayComponent | uomId | Visible control; optional or API-dependent | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/add-new-sales-invoice/add-new-sales-invoice-form-array/add-new-sales-invoice-form-array.component.ts |
| AddSalesInvoiceFormComponent | currencyRate | Required in component validator | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/add-new-sales-invoice/add-sales-invoice-form/add-sales-invoice-form.component.ts |
| AddSalesInvoiceFormComponent | customerId | Required in component validator | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/add-new-sales-invoice/add-sales-invoice-form/add-sales-invoice-form.component.ts |
| AddSalesInvoiceFormComponent | description | Visible control; optional or API-dependent | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/add-new-sales-invoice/add-sales-invoice-form/add-sales-invoice-form.component.ts |
| AddSalesInvoiceFormComponent | invoiceDate | Required in component validator | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/add-new-sales-invoice/add-sales-invoice-form/add-sales-invoice-form.component.ts |
| AddSalesInvoiceFormComponent | invoiceDueDate | Visible control; optional or API-dependent | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/add-new-sales-invoice/add-sales-invoice-form/add-sales-invoice-form.component.ts |
| AddSalesInvoiceFormComponent | isLinkedToAdvancedPayment | Visible control; optional or API-dependent | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/add-new-sales-invoice/add-sales-invoice-form/add-sales-invoice-form.component.ts |
| AddSalesInvoiceFormComponent | paymentTermId | Required in component validator | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/add-new-sales-invoice/add-sales-invoice-form/add-sales-invoice-form.component.ts |
| AddSalesInvoiceFormComponent | pricePolicyId | Required in component validator | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/add-new-sales-invoice/add-sales-invoice-form/add-sales-invoice-form.component.ts |
| AddSalesInvoiceFormComponent | salesManId | Visible control; optional or API-dependent | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/add-new-sales-invoice/add-sales-invoice-form/add-sales-invoice-form.component.ts |
| AddSalesInvoiceFormComponent | sourceId | Visible control; optional or API-dependent | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/add-new-sales-invoice/add-sales-invoice-form/add-sales-invoice-form.component.ts |
| AddSalesInvoiceFormComponent | sourceType | Required in component validator | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/add-new-sales-invoice/add-sales-invoice-form/add-sales-invoice-form.component.ts |
| AddSalesInvoiceFormComponent | warehouseId | Required in component validator | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/add-new-sales-invoice/add-sales-invoice-form/add-sales-invoice-form.component.ts |
| EditNewSalesInvoiceFormArrrayComponent | costCenterId | Visible control; optional or API-dependent | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/edit-new-sales-invoice/edit-new-sales-invoice-form-arrray/edit-new-sales-invoice-form-arrray.component.ts |
| EditNewSalesInvoiceFormArrrayComponent | descriptionLine | Visible control; optional or API-dependent | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/edit-new-sales-invoice/edit-new-sales-invoice-form-arrray/edit-new-sales-invoice-form-arrray.component.ts |
| EditNewSalesInvoiceFormArrrayComponent | discountAmount | Visible control; optional or API-dependent | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/edit-new-sales-invoice/edit-new-sales-invoice-form-arrray/edit-new-sales-invoice-form-arrray.component.ts |
| EditNewSalesInvoiceFormArrrayComponent | itemId | Required in component validator | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/edit-new-sales-invoice/edit-new-sales-invoice-form-arrray/edit-new-sales-invoice-form-arrray.component.ts |
| EditNewSalesInvoiceFormArrrayComponent | price | Conditionally required/validated in component | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/edit-new-sales-invoice/edit-new-sales-invoice-form-arrray/edit-new-sales-invoice-form-arrray.component.ts |
| EditNewSalesInvoiceFormArrrayComponent | quantity | Required in component validator | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/edit-new-sales-invoice/edit-new-sales-invoice-form-arrray/edit-new-sales-invoice-form-arrray.component.ts |
| EditNewSalesInvoiceFormArrrayComponent | taxIds | Visible control; optional or API-dependent | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/edit-new-sales-invoice/edit-new-sales-invoice-form-arrray/edit-new-sales-invoice-form-arrray.component.ts |
| EditNewSalesInvoiceFormArrrayComponent | trackingType | Conditionally required/validated in component | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/edit-new-sales-invoice/edit-new-sales-invoice-form-arrray/edit-new-sales-invoice-form-arrray.component.ts |
| EditNewSalesInvoiceFormArrrayComponent | uomId | Required in component validator | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/edit-new-sales-invoice/edit-new-sales-invoice-form-arrray/edit-new-sales-invoice-form-arrray.component.ts |
| EditSalesInvoiceFormComponent | currencyRate | Required in component validator | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/edit-new-sales-invoice/edit-sales-invoice-form/edit-sales-invoice-form.component.ts |
| EditSalesInvoiceFormComponent | customerId | Visible control; optional or API-dependent | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/edit-new-sales-invoice/edit-sales-invoice-form/edit-sales-invoice-form.component.ts |
| EditSalesInvoiceFormComponent | description | Visible control; optional or API-dependent | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/edit-new-sales-invoice/edit-sales-invoice-form/edit-sales-invoice-form.component.ts |
| EditSalesInvoiceFormComponent | invoiceDate | Required in component validator | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/edit-new-sales-invoice/edit-sales-invoice-form/edit-sales-invoice-form.component.ts |
| EditSalesInvoiceFormComponent | invoiceDueDate | Visible control; optional or API-dependent | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/edit-new-sales-invoice/edit-sales-invoice-form/edit-sales-invoice-form.component.ts |
| EditSalesInvoiceFormComponent | isLinkedToAdvancedPayment | Visible control; optional or API-dependent | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/edit-new-sales-invoice/edit-sales-invoice-form/edit-sales-invoice-form.component.ts |
| EditSalesInvoiceFormComponent | paymentTermId | Required in component validator | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/edit-new-sales-invoice/edit-sales-invoice-form/edit-sales-invoice-form.component.ts |
| EditSalesInvoiceFormComponent | pricePolicyId | Visible control; optional or API-dependent | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/edit-new-sales-invoice/edit-sales-invoice-form/edit-sales-invoice-form.component.ts |
| EditSalesInvoiceFormComponent | salesManId | Visible control; optional or API-dependent | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/edit-new-sales-invoice/edit-sales-invoice-form/edit-sales-invoice-form.component.ts |
| EditSalesInvoiceFormComponent | sourceId | Visible control; optional or API-dependent | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/edit-new-sales-invoice/edit-sales-invoice-form/edit-sales-invoice-form.component.ts |
| EditSalesInvoiceFormComponent | sourceType | Visible control; optional or API-dependent | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/edit-new-sales-invoice/edit-sales-invoice-form/edit-sales-invoice-form.component.ts |
| EditSalesInvoiceFormComponent | warehouseId | Required in component validator | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/edit-new-sales-invoice/edit-sales-invoice-form/edit-sales-invoice-form.component.ts |
Observed frontend actions
| Component | Click action/handler | Business review requirement | Component source |
|---|---|---|---|
| AddNewSalesInvoiceFormArrayComponent | addDiscount | Document the enabled state, permission, input context, resulting API or navigation effect, success refresh, and concrete failure behavior for this handler. | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/add-new-sales-invoice/add-new-sales-invoice-form-array/add-new-sales-invoice-form-array.component.ts |
| AddNewSalesInvoiceFormArrayComponent | addTax | Document the enabled state, permission, input context, resulting API or navigation effect, success refresh, and concrete failure behavior for this handler. | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/add-new-sales-invoice/add-new-sales-invoice-form-array/add-new-sales-invoice-form-array.component.ts |
| AddNewSalesInvoiceFormArrayComponent | onDelete | Available only in deletable states with Delete permission; identify the record in confirmation, call delete once, remove/refresh the list row on success, and retain the row with the API reason on failure. | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/add-new-sales-invoice/add-new-sales-invoice-form-array/add-new-sales-invoice-form-array.component.ts |
| AddNewSalesInvoiceFormArrayComponent | openDescriptionPopup | Document the enabled state, permission, input context, resulting API or navigation effect, success refresh, and concrete failure behavior for this handler. | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/add-new-sales-invoice/add-new-sales-invoice-form-array/add-new-sales-invoice-form-array.component.ts |
| AddNewSalesInvoiceFormArrayComponent | openDialogFromItemCode | Open the item/lookup/tracking dialog with the current warehouse, item, UOM, and remaining quantity context; accepted values must return to the correct line and cancel must not mutate it. | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/add-new-sales-invoice/add-new-sales-invoice-form-array/add-new-sales-invoice-form-array.component.ts |
| AddSalesInvoiceFormComponent | addDiscount | Document the enabled state, permission, input context, resulting API or navigation effect, success refresh, and concrete failure behavior for this handler. | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/add-new-sales-invoice/add-sales-invoice-form/add-sales-invoice-form.component.ts |
| AddSalesInvoiceFormComponent | openCustomerAdvancedSearch | Document the enabled state, permission, input context, resulting API or navigation effect, success refresh, and concrete failure behavior for this handler. | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/add-new-sales-invoice/add-sales-invoice-form/add-sales-invoice-form.component.ts |
| AddSalesInvoiceFormComponent | openDialog | Open the item/lookup/tracking dialog with the current warehouse, item, UOM, and remaining quantity context; accepted values must return to the correct line and cancel must not mutate it. | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/add-new-sales-invoice/add-sales-invoice-form/add-sales-invoice-form.component.ts |
| AddSalesInvoiceFormComponent | selectcustmerFirst | Document the enabled state, permission, input context, resulting API or navigation effect, success refresh, and concrete failure behavior for this handler. | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/add-new-sales-invoice/add-sales-invoice-form/add-sales-invoice-form.component.ts |
| EditNewSalesInvoiceFormArrrayComponent | addDiscount | Document the enabled state, permission, input context, resulting API or navigation effect, success refresh, and concrete failure behavior for this handler. | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/edit-new-sales-invoice/edit-new-sales-invoice-form-arrray/edit-new-sales-invoice-form-arrray.component.ts |
| EditNewSalesInvoiceFormArrrayComponent | addTax | Document the enabled state, permission, input context, resulting API or navigation effect, success refresh, and concrete failure behavior for this handler. | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/edit-new-sales-invoice/edit-new-sales-invoice-form-arrray/edit-new-sales-invoice-form-arrray.component.ts |
| EditNewSalesInvoiceFormArrrayComponent | deleteRow | Available only in deletable states with Delete permission; identify the record in confirmation, call delete once, remove/refresh the list row on success, and retain the row with the API reason on failure. | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/edit-new-sales-invoice/edit-new-sales-invoice-form-arrray/edit-new-sales-invoice-form-arrray.component.ts |
| EditNewSalesInvoiceFormArrrayComponent | openDescriptionPopup | Document the enabled state, permission, input context, resulting API or navigation effect, success refresh, and concrete failure behavior for this handler. | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/edit-new-sales-invoice/edit-new-sales-invoice-form-arrray/edit-new-sales-invoice-form-arrray.component.ts |
| EditNewSalesInvoiceFormArrrayComponent | openDialogFromItemCode | Open the item/lookup/tracking dialog with the current warehouse, item, UOM, and remaining quantity context; accepted values must return to the correct line and cancel must not mutate it. | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/edit-new-sales-invoice/edit-new-sales-invoice-form-arrray/edit-new-sales-invoice-form-arrray.component.ts |
| EditSalesInvoiceFormComponent | addDiscount | Document the enabled state, permission, input context, resulting API or navigation effect, success refresh, and concrete failure behavior for this handler. | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/edit-new-sales-invoice/edit-sales-invoice-form/edit-sales-invoice-form.component.ts |
| EditSalesInvoiceFormComponent | openCustomerAdvancedSearch | Document the enabled state, permission, input context, resulting API or navigation effect, success refresh, and concrete failure behavior for this handler. | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/edit-new-sales-invoice/edit-sales-invoice-form/edit-sales-invoice-form.component.ts |
| EditSalesInvoiceFormComponent | openDialog | Open the item/lookup/tracking dialog with the current warehouse, item, UOM, and remaining quantity context; accepted values must return to the correct line and cancel must not mutate it. | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/edit-new-sales-invoice/edit-sales-invoice-form/edit-sales-invoice-form.component.ts |
| SalesInvoiceComponent | onDelete | Available only in deletable states with Delete permission; identify the record in confirmation, call delete once, remove/refresh the list row on success, and retain the row with the API reason on failure. | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/sales-invoice-list/sales-invoice.component.ts |
| SalesInvoiceComponent | onEdit | Open the identified editable record only with Edit permission; posted/locked records remain blocked by route or action state and list context must be recoverable on return. | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/sales-invoice-list/sales-invoice.component.ts |
| SalesInvoiceComponent | onPost | Available only for a postable Draft and Post permission; confirm the document, prevent a second submission, call the posting API, and refresh status, journal/stock links, and row actions. Failure must keep the pre-post state. | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/sales-invoice-list/sales-invoice.component.ts |
| SalesInvoiceComponent | onPrintOutWithZatcaConfirm | Generate the printout for the selected record and authorized branch/tenant; use posted/current values and surface print, template, ZATCA/ETA, or popup failures without changing transaction state. | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/sales-invoice-list/sales-invoice.component.ts |
| SalesInvoiceComponent | onVeiw | Open the authorized record in view mode with its status, totals, lines, source and generated-document links; handle deleted, forbidden, and missing records without exposing stale data. | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/sales-invoice-list/sales-invoice.component.ts |
| SalesInvoiceComponent | routeToJournalentryView | Open the authorized record in view mode with its status, totals, lines, source and generated-document links; handle deleted, forbidden, and missing records without exposing stale data. | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/sales-invoice-list/sales-invoice.component.ts |
| SalesInvoiceComponent | routeToStock | Navigate only when the transaction produced a linked Stock In/Stock Out record and Inventory view permission is available; service-only/no-stock cases expose no stock link. | apps/sales/src/app/remote-entry/transaction/pages/sales-invoices/sales-invoice-list/sales-invoice.component.ts |
Page-specific frontend acceptance criteria
- (module default) - List/navigation: Load an authorized paged/searchable list or navigation page; preserve filters/sort/paging and expose only permitted row and bulk actions. Security observed: Permission: AppSalesPermissions.InvoiceService_List; Guards: PolicyAuthGuard
- add - Add: Render permitted fields, required indicators, defaults, dependent lookups, validation, Save/Cancel, loading, success, and API-error states. Security observed: Permission: AppSalesPermissions.InvoiceService_Add; Guards: PolicyAuthGuard
- add/:id - Add: Render permitted fields, required indicators, defaults, dependent lookups, validation, Save/Cancel, loading, success, and API-error states. Security observed: Permission: AppSalesPermissions.InvoiceService_Add; Guards: PolicyAuthGuard
- edit/:id - Edit: Load the identified record, enforce state/permission field locks, preserve concurrency identity, validate changes, and return without losing filters. Security observed: Permission: AppSalesPermissions.InvoiceService_Edit; Guards: PolicyAuthGuard, preventPostedGuard
- sales-invoice - List/navigation: Load an authorized paged/searchable list or navigation page; preserve filters/sort/paging and expose only permitted row and bulk actions. Security observed: Permission: AppSalesPermissions.InvoiceService_List; Guards: PolicyAuthGuard