Skip to main content

Products

Products is the branch-scoped inventory lookup used by sales orders, booking price, transfer, goods receipt, and return flows. When opened from the Products menu, both Mobile and POS Terminal are read-only lookup screens. Mobile can show an add-to-sales-order form only when ProductList/ProductDetail is opened from an existing sales-order flow with orderId or draftOrder; the normal POS Terminal product menu follows the standalone Mobile behavior and does not show that add form.

The screen is useful for developers because it shows the product shape reused by downstream documents: item identity, warehouse, SAP stock, booked stock, available stock, price, UOM, weight control, company, color, and step-price rows.

App Entry Points

AppTarget
MobileProductList -> ProductDetail
POS Terminalproduct -> ProductDetailForm

User Workflow

Data And API Flow

ConcernBehavior
Branch contextBoth apps call getProductBranchContext(). The selected branch must contain whsGrpCode; otherwise the product menu fails with a missing branch data error.
Inventory refreshsyncProductInventory(context, page) triggers MST inventory refresh and fire-and-forget promotion sync to Firebase.
Main branch inventory APIIf branchCode === whsGrpCode, refresh calls /products?...&whGrpCode={whsGrpCode}.
Non-main branch inventory APIIf branch and warehouse group differ, refresh calls /products/sub-inventories?...&whGrpCode={branchCode}&whsCode={whsGrpCode}.
Firebase collectionInventory is read from ${whsGrpCode}-inventories.
Warehouse codesBoth apps include whsGrpCode, PC-{whsGrpCode}, and NF-{whsGrpCode}.
List filtersRows with price <= 0 are ignored, duplicate itemCode rows are deduped, and product detail/list require usable itemCode.
Step priceDetail loads getProductStepPrice({ itemCode, uomCode }) only when stepPriceFlag is truthy. Sales and booking screens reuse this concept when quantity changes.
Dummy productsSome document flows merge dummy products for operation-specific cases, but this product menu is the inventory-product lookup.

List Behavior

TopicMobilePOS Terminal
Loading modelCalls syncProductInventory() once, then subscribes to Firestore with subscribeProductInventory().Calls getProductSplitList({ page, search, bookingOnly }) and appends pages with duplicate IDs merged.
SearchLocal in-memory search by itemName and itemCode.Service search matches Mobile and searches only itemName and itemCode.
Tabsทั้งหมด and ติดจอง; booked tab keeps products where booking > 0.Same tabs; ติดจอง passes bookingOnly: true to the split list service.
SummaryHeader shows total product count and booked product count.Split list uses the generic pane count and supports load more.
RefreshPull-to-refresh calls syncProductInventory(branchContext).Pull-to-refresh and menu reload call the paged split list again.
Empty stateShows "not found" after the first snapshot is received.Uses the shared split-pane empty/error/loading states.

Detail Behavior And Actions

ActionMobilePOS Terminal
Open detailNavigates to ProductDetail with productId, itemCode, itemName, stepPriceFlag, uomCode, and optional sales-order context.HomeScreen calls getProductSplitDetail(item), loads detail by itemCode, and passes detail.raw to ProductDetailForm.
Refresh detailPull-to-refresh reloads getProductInventoryDetail(context, productId) and step price if needed.Detail is refreshed by selecting/reloading the split-pane detail; step prices are loaded before ProductDetailForm receives the raw record.
Add to sales orderVisible only when ProductList/ProductDetail was opened with orderId or draftOrder. It validates qty, creates an order first if only draftOrder exists, then calls createOrderItem().Not shown from the normal Products menu, matching standalone Mobile behavior. Terminal adds products through the sales-order product picker, not from this menu.
Quantity guardQuantity must be greater than 0.Quantity must be greater than 0.
Weight guardWeight-based products may be added or edited in a sales order with weight 0; weight is checked again when creating an invoice.Same guard: a weight-based product may have weight 0 in a sales order, but an invoice cannot be created until its weight is other than 0.
Price inputUser can adjust price in the add form; default is product price.User can adjust price in the add form; default is product price.
Amount previewWeight-base: qty * price * weight; otherwise qty * price.Same calculation.
Mutation boundaryThe standalone Products menu does not edit product master, inventory quantities, or sales-order items. Mobile's add action belongs to the sales-order route context, not the normal menu.Same standalone boundary.

Important Fields For Developers

FieldWhy It Matters
idFirestore document ID used by mobile detail lookup; terminal detail resolves latest data by itemCode.
itemCode / itemNamePrimary identity used by list, detail, and every document item payload.
whsCode / warehouseCodeRequired when adding items to order, booking, transfer, and stock-in flows. Missing warehouse data usually blocks document save in downstream screens.
price, salUomCode, salUomEntryUsed to build line price and UOM payloads.
onHand, booking, available stockUI displays SAP stock, booked stock, and available stock as onHand - booking. Downstream documents use these values for stock/booking validation.
weight, weightBaseFlagControls whether the product is sold by counted unit or by weight. Weight-based products may have weight 0 in a sales order, but must have a weight other than 0 before invoice creation.
stepPriceFlag / step price rowsDrives tiered price display and price selection in sales/booking quantity changes.
colorUsed by product cards/detail cards for visual grouping. Invalid hex falls back to app theme accent.
company fieldsDocument screens may use company fields to filter compatible products, but the Products menu search itself follows Mobile and uses item name/code.

Permissions And Guards

TopicBehavior
Mobile menu permissionThe home menu uses the same product deptCode set as terminal: -2, 1, 2, 3, 4, 7, 29, 21, 8, 9, 12, 20, 22, 23, 27, 28, 13, 16.
Terminal menu keyproduct
Terminal menu permissionMENU_PRODUCT uses -2, 1, 2, 3, 4, 7, 29, 21, 8, 9, 12, 20, 22, 23, 27, 28, 13, 16.
Branch ruleThe product menu is not main-branch-only. It depends on selected branch product context and whsGrpCode.
Add-to-sales-order permissionMobile shows the add form only when the screen was opened from a sales-order flow with orderId or draftOrder. POS Terminal does not expose this action from the standalone Products menu; sales-order item adding stays inside the sales-order flow.
Product mutationNo product master create/update/delete exists in this menu. Product quantity changes happen only through downstream document flows.

Mobile vs POS Terminal

TopicMobilePOS Terminal
NavigationDedicated product stackHomeScreen split-pane menu key product
ListSnapshot-backed product list with search, tabs, summary counts, pull refreshPaged split list with search, tabs, load more, pull refresh
DetailFull-screen detail with pull refresh and optional bottom add formRight-pane detail with optional add card
Add actionOnly when opened from Mobile sales-order route contextNot exposed from the standalone Products menu
ReuseProduct picker components in document stacksShared product picker/detail patterns in HomeScreen

Developer Handoff Map

AreaCode
Mobile list/detailapps/mobile/src/screens/productStack/productListScreen, productDetailScreen
Mobile home permissionapps/mobile/src/screens/homeScreen/index.tsx -> MENU_PRODUCT
Terminal detailapps/pos-terminal/src/screens/HomeScreen/ProductDetailForm.tsx
Terminal home wiringapps/pos-terminal/src/screens/HomeScreen/index.tsx, DetailPane.tsx, ListPane.tsx
Terminal split dataapps/pos-terminal/src/services/splitMenuData.ts -> getProductSplitList, getProductSplitDetail
Product serviceapps/*/src/services/products.ts
Picker reuseOrderFlowShared, BookingProductPicker, inventory transfer forms