Invoice
The Invoice menu is used to track invoices created from the sales order flow, inspect customer/product/status details, send invoice data to B1, manage invoice cancellation requests, reopen a sales order from an existing invoice, and view today's sales summary for the current user and the whole branch.
In this system, invoices are not the main entry point for creating sales. The primary sales entry point is Sales Order. The invoice menu is the review, B1 handoff, cancellation, and summary surface after the order/invoice/payment flow has started.
Open workflowOpen sales summary notesOpen permissions
App Entry Points
| App | Entry point | Main files |
|---|---|---|
| Mobile | Home -> InvoiceList -> InvoiceDetail | invoiceListScreen, invoiceDetailScreen |
| POS Terminal | invoice menu in split home | HomeScreen/index.tsx, ListPane.tsx, InvoicePanels.tsx |
Both apps use the same service boundary:
| Job | Endpoint / service |
|---|---|
| Load invoice list | GET /invoices via getInvoices(...) |
| Load pending B1 list | GET /invoices?toB1=0 via getInvoicesPendingB1(...) |
| Load invoice detail | GET /invoices/{invoiceId}?includeLot=true |
| Send to B1 | POST /payment/to-b1 with an array of invoiceId values |
| Retry payment/incoming send | POST /payment/{invoiceId}/retry |
| Sales summary | GET /invoices/summary |
| Approve cancel request | POST /invoices/{invoiceId}/approve |
| Reject cancel request | POST /invoices/{invoiceId}/reject |
| Request invoice cancellation | POST /invoices/{invoiceId}/cancel |
Main Workflow
Invoice List
The main list loads through getInvoices(...) with the selected branch context:
branchIdfrom selected branchwhGrpCodefrom selected warehouse grouppage,pageLimit,search- base filters:
shippingType,invoiceStatus,toB1,inStock,withOutCN,dateFrom,dateTo - sorted
DESCbyinvoiceId
List behavior:
- search covers invoice number, customer, or sales order number
- tabs are
AllandPending B1 - rows are deduped by
invoiceIdorinvoiceStorageId - tapping a row in normal mode opens invoice detail
- tapping a row in manual payment mode selects or deselects the invoice for sending
Invoice Detail
Detail loads GET /invoices/{invoiceId}?includeLot=true and renders:
- invoice number, customer, sales order number, invoice owner, and invoice date
- invoice summary through
InvoiceSummarySection - product item lines and item count
- shipping invoices attached to the order, with retry buttons for shipping/incoming when retry is available
Open sales order from invoicewhen the user can create sales orders
Opening a sales order from an invoice passes these values into order detail:
{
duplicateInvoiceId,
duplicateInvoiceNo,
duplicateDocumentMove,
duplicateVehicleRelease,
}
Main branches can open the duplicated order draft directly. Non-main branches must first choose vehicleRelease and documentMove in the duplicate configuration modal.
Send To B1
B1 sending can run from a per-row action or from multi-select manual payment mode. The API call is POST /payment/to-b1.
Before sending, the app checks:
| Guard | Detail |
|---|---|
Has invoiceId | Uses invoiceId or fallback invoiceStorageId |
Has refKey | Missing refKey blocks sending |
toB1 = 0 | Already-sent invoices show a disabled action |
orderStatus = CONFIRMED | Unpaid/unconfirmed sales orders show an error |
| No pending cancellation request | canceledNote without rejectCanceledAt blocks sending |
| Invoice date | Normal users can send only today's/yesterday's invoices; dept 3 bypasses the date guard |
Sales Summary Button
The Sales Summary button is available in the invoice header:
| App | Button location |
|---|---|
| Mobile | header menu item named สรุปยอดขาย |
| POS Terminal | bar-chart-2 icon beside the Invoice menu header in ListPane |
When pressed, the app calls /invoices/summary twice for the current day:
The modal groups BFP and NFF and then renders a total block:
| Value | Calculation |
|---|---|
| Invoice count | invCount |
| Sales amount | amountTotal |
| point/coupon discount | discount |
| credit note discount | useCreditNote |
| net remaining | amountTotal - discount - useCreditNote |
| total weight | weightTotal |
| COD transaction count | codCount |
| COD fee total | codTotal |
For each company and for the grand total, the modal renders the COD metrics as ค่าธรรมเนียม COD : codCount @ codTotal. These are additional summary values; the net remaining calculation remains amountTotal - discount - useCreditNote and does not subtract codTotal.
Manual Payment Status Mode
This mode opens from the same header menu area as the sales summary:
- Mobile label:
ปรับสถานะการชำระเงินด้วยตนเอง - Terminal icon:
check-square; once active, it changes toxfor cancelling the mode - the list switches to the
Pending B1tab - normal users are limited to today/yesterday and their own
userCode - dept
3sees every user and bypasses the manual-mode date guard - users select multiple invoices and press
ส่งข้อมูล - selected invoices must not be canceled, must have
refKey, and their order must beCONFIRMED
Cancellation Requests
This menu is not always the origin of invoice cancellation requests, but it is where pending requests on invoices are managed.
Cancellation handling:
- actions appear only when the invoice has
canceledNoteand norejectCanceledAt invoiceStatus = CANCELEDcannot be processed again- approving calls
approveCancelInvoice(invoiceId) - rejecting calls
rejectCancelInvoice(invoiceId) - the current invoice list refreshes after the action
Permissions And Guards
| Area | Condition |
|---|---|
| See Invoice menu | MENU_INVOICE.has(deptCode) or admin/full non-main warehouse access |
| menu dept codes | -2, 1, 2, 3, 4, 7, 8, 9, 13, 16, 20, 21, 22, 23, 27, 29 |
| Send one invoice to B1 | invoice owner, dept 3, or override user 012265, 999999 |
| Send older than today/yesterday | dept 3 only |
| Manage cancel request | invoice owner or override user 012265, 999999 |
| Open sales order from invoice | must pass canCreateSalesOrder |
main canCreateSalesOrder dept codes | admin, full non-main warehouse access, or dept -2, 1, 2, 4, 7, 8, 9, 13, 16, 21, 29 |
Important: “can see the menu” and “can perform an action” are separate gates. For example, dept 20 can see the Invoice menu and some Home shortcuts, but Open sales order from invoice still uses the detail-screen canCreateSalesOrder gate.
Mobile vs POS Terminal
| Topic | Mobile | POS Terminal |
|---|---|---|
| UI shape | stack screen: list -> detail | split pane: menu, list, detail |
| sales summary button | header menu item | icon beside invoice menu title |
| invoice detail | InvoiceDetailScreen | InvoicePanels detail panel |
| manual payment mode | bottom rail with ยกเลิก / ส่งข้อมูล | header action plus list-pane actions |
| duplicate order | navigate to OrderDetail | create/open order detail in split panel with progress |
| summary modal | InvoiceSummaryModal component | InvoiceSummaryModal in InvoicePanels.tsx |
Developer Handoff Map
| Job | Mobile | POS Terminal |
|---|---|---|
| invoice list | apps/mobile/src/screens/invoiceStack/invoiceListScreen/index.tsx | apps/pos-terminal/src/screens/HomeScreen/index.tsx, ListPane.tsx |
| invoice detail | apps/mobile/src/screens/invoiceStack/invoiceDetailScreen/index.tsx | apps/pos-terminal/src/screens/HomeScreen/InvoicePanels.tsx |
| invoice service | apps/mobile/src/services/invoices.ts | apps/pos-terminal/src/services/invoices.ts, splitMenuData.ts |
| summary modal | apps/mobile/src/components/InvoiceSummaryModal/index.tsx | InvoicePanels.tsx |
| Home menu permission | apps/mobile/src/screens/homeScreen/index.tsx | apps/pos-terminal/src/screens/HomeScreen/config.ts |
| open order from invoice permission | apps/mobile/src/utils/salesOrders.ts | canCreateSalesOrder(...) in Terminal config |