Appearance
Stock In
| Backlog field | Value |
|---|---|
| Story ID | INV-DASH-019 |
| Epic | Inventory |
| Story type | Dashboard |
| Review status | Draft - business analyst and business owner review required |
| Source evidence | Inventory MFE route/form, Inventory.Apis controller, application command/query handlers, validators, domain entities, and posting services |
| Last source review | 2026-07-10 |
Purpose
Record stock received into a warehouse outside or from connected source documents.
User stories
- As a warehouse receiver, I want to create a Stock In with date, warehouse, operational tag, and item lines so that received stock is recorded.
- As a receiver, I want to scan a barcode, select multiple items, or import lines so that entry is efficient.
- As a receiver, I want to assign batch/serial tracking details so that tracked stock remains traceable.
- As an authorized supervisor, I want to post a valid draft so that on-hand stock and related accounting become effective.
- As an auditor, I want to view, print, search, and export Stock In records.
Acceptance criteria
- A draft requires a valid date, destination warehouse, operational tag where applicable, and at least one valid positive-quantity line.
- Barcode selection resolves the correct item variant/unit.
- Tracking quantities equal their parent line quantity for tracked items.
- Drafts may be edited or deleted only with permission and while business state allows it.
- Posting validates open period, settings, item/warehouse status, tracking, costs, and accounts.
- Successful posting increases stock exactly once and marks the transaction Posted.
- Repeated posting requests do not duplicate stock or journals.
- Posted records are viewable/printable but not changed through normal draft editing.
- List export respects search, sorting, and visible scope.
Posting details
- Post accepts only a valid Draft in an open financial period. The warehouse opening balance must already be posted, no physical count may lock the affected stock, and every item, UOM, quantity, cost, and tracking allocation must validate.
- For a manual Stock In, the journal debits the destination Warehouse GL account and credits the selected Operational Tag GL account. Both accounts are mandatory; Post fails rather than silently substituting an unrelated account.
- For a delegated receipt, the calling document supplies the source-specific counter-account. Purchase and transfer flows normally use Goods in Transit; sales-return or other source flows use the account defined by that source contract. This replaces the manual Operational Tag credit.
- Posting creates or updates stock headers, receipt details, tracking records, valuation layers, weighted-moving-average/last-purchase cost values, the linked journal, and the Stock In status. The source document receives the resulting Stock In/journal references where its contract requires them.
- Stock, valuation, journal, links, and status commit as one operation. A validation, account, delegate, or persistence failure leaves the document Draft with no partial effect; a repeated Post must not create a second receipt or journal. Unposting is available only through the explicitly supported source reversal workflow.
General ledger posting
| Condition | Debit | Credit | Amount basis | Notes |
|---|---|---|---|---|
| Manual Stock In | Destination Warehouse GL | Operational Tag GL | Received quantity x posted unit cost | Both accounts are required. |
| Purchase or transfer receipt | Destination Warehouse GL | Goods in Transit | Delegated receipt value | Counter-account is supplied by the source flow. |
| Other delegated receipt | Destination Warehouse GL | Source-supplied account | Delegated receipt value | The source contract, not the manual tag, controls the credit. |
| Failed/no-op post | - | - | None | No journal is retained. |
Module and data effects
| Affected area | Effect | Conditional/no-effect rule |
|---|---|---|
| Inventory quantity | Increases destination on-hand/available stock. | No effect for an invalid or rolled-back post. |
| Valuation | Creates receipt layers and updates WMA/last-purchase cost. | Source-supplied cost is used for delegated receipts. |
| Tracking | Creates batch/serial/expiry balances and movement history. | Untracked items create no tracking identity. |
| Source document | Returns Stock In and journal IDs and advances source status. | Manual Stock In has no purchase/transfer source to update. |
| Accounting | Posts the table above atomically with stock. | No commercial receivable/payable/revenue entry is created. |
Core acceptance scenarios
- Given a valid Draft Stock In, posted warehouse opening balance, no open count, valid tracking/UOM, Warehouse GL, and Operational Tag GL, when Post is clicked, then stock quantities/cost layers increase, Warehouse GL is debited, Operational Tag GL is credited, the journal is linked, and status becomes Posted in one commit.
- Given source-document Stock In, when it posts, then the delegate uses the source-specific COGS or Goods-in-Transit account instead of the manual Operational Tag account.
- Given any prerequisite fails, when Post is attempted, then no stock header/detail, journal, or status change is committed.
Data classification
| Data | Rule |
|---|---|
| Receipt date | Required; defaults to the current clock for the API command and must resolve to a valid financial period. |
| Source document type and ID | Required by the manual command validator; identifies the operational tag or upstream source. |
| Warehouse | Required; must exist, have a Warehouse GL account, have its opening balance posted, and have no open reconciliation. |
| Notes | Optional; copied to the journal description/line descriptions. |
| Lines | At least one required. Service lines are removed from source-document posted Stock In because services do not create stock. |
| Item/variant/UOM | Required and active. UOM base calculation must be non-zero. |
| Quantity | Required and positive. Serial-tracked line quantity must equal 1. |
| Cost | Required and greater than zero for the manual flow. Subcost is quantity multiplied by cost. |
| Barcode | Optional; if supplied it must exist and is linked to the line. |
| Batch number | Required for batch tracking. |
| Serial ID | Required and globally unique for serial tracking, including within the submitted document. |
| Expiry date | Required for batch tracking, expiry-enabled serials, and expiry-enabled untracked items. |
Clicking Save
Save creates a Draft Stock In with a generated Stock In sequence. It records header/lines/tracking but does not change available stock or create a journal. Draft lines may be edited/deleted subject to permissions and state.
Clicking Post
- Re-loads the document and rejects missing or non-Draft records.
- Revalidates active item, variant, UOM, and warehouse references.
- Blocks posting while a reconciliation is open or before the warehouse opening balance is posted.
- Converts each line to base quantity and resolves tracking identity: vendor batch, serial, or generated system batch for expiry-only stock.
- Creates/updates item-warehouse and batch stock headers and adds inbound stock-detail history.
- Recalculates available quantity, last-purchase cost, and weighted-average cost where applicable.
- Creates the journal and stores its ID/code on the Stock In.
- Changes status from Draft to Posted and commits once.
GL effect
- Manual Stock In: debit Warehouse GL, credit selected Operational Tag GL, for total line subcost.
- Source-document Stock In: debit Warehouse GL; credit COGS for Sales Return, otherwise Goods in Transit from Inventory settings.
- Purchase Stock In with landed cost can debit warehouse for inventory plus landed cost and add credits to the resolved landed-cost expense accounts.
See Posting and Account Resolution.
Post failures
Posting makes no committed change when the document is not Draft, Accounting is unavailable, the period/UOM/setup is invalid, the warehouse opening balance is missing, a count is open, a required GL account is absent, tracking is invalid, or journal creation fails.
Status, action, and reversal controls
| Action | Required state/authority | Preconditions and affected data | Failure/reversal rule |
|---|---|---|---|
| Add/Save | Stock In Add; new/Draft | Receipt date, source type, warehouse, positive lines, UOM and conditional tracking; saves Draft only | No quantity, valuation, or GL effect until Post |
| Edit | Draft plus Stock In Edit and preventPostedGuard | Reload current Draft; preserve line/tracking identity and revalidate source | Posted or concurrently changed receipt remains unchanged |
| Delete | Draft plus Delete | No dependent posted source state | Removes Draft only; posted receipt requires source reversal |
| Post | Draft plus Post | Open period, posted warehouse opening, no count lock, valid cost/UOM/tracking and resolved Warehouse/counter accounts | Stock, layers, tracking, journal, source links, and status commit together or all roll back |
| View/Print | View/print authority | Authorized record and template | Read-only; print failure has no business effect |
| Reverse | Source-specific reversal authority | Open allowed period and no incompatible later consumption/count/transfer dependency | Reverse journal and stock layers/tracking through originating workflow; never delete the Posted receipt |
Reconciliation controls
| Control | Required equality |
|---|---|
| Line quantity in base UOM | Sum of batch/serial/expiry tracking quantity |
| Receipt value | Warehouse GL debit and counter-account credit |
| Posted receipt details | Increase in warehouse stock/layers by item and tracking identity |
| Delegated source quantity/value | Stock In links and source document received/remaining totals |
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) | StockInListComponent | List/navigation | Permission: AppInventoryPermissions.StockIn_List; Guards: PolicyAuthGuard | Explicit frontend feature rule | apps/inventory/src/app/remote-entry/transactions/transactions.module.ts:66 |
| add | AddStockInComponent | Add | Permission: AppInventoryPermissions.StockIn_Add; Guards: PolicyAuthGuard | Explicit frontend feature rule | apps/inventory/src/app/remote-entry/transactions/transactions.module.ts:78 |
| edit/:id | EditStockInComponent | Edit | Permission: AppInventoryPermissions.StockIn_Edit; Guards: PolicyAuthGuard, preventPostedGuard | Explicit frontend feature rule | apps/inventory/src/app/remote-entry/transactions/transactions.module.ts:89 |
| stockin | MainStockInListComponentComponent | List/navigation | Permission: AppInventoryPermissions.StockIn_List; Guards: PolicyAuthGuard | Explicit frontend feature rule | apps/inventory/src/app/remote-entry/transactions/transactions.module.ts:56 |
| view/:id | ViewStockInComponent | View/detail | Permission: AppInventoryPermissions.StockIn_View; Guards: PolicyAuthGuard | Explicit frontend feature rule | apps/inventory/src/app/remote-entry/transactions/transactions.module.ts:101 |
Observed frontend fields and validation
| Component | Control | Observed frontend rule | Component source |
|---|---|---|---|
| AddStockInComponent | barCode | Visible control; optional or API-dependent | apps/inventory/src/app/remote-entry/transactions/pages/stock-In/add-stock-in/add-stock-in.component.ts |
| AddStockInComponent | cost | Visible control; optional or API-dependent | apps/inventory/src/app/remote-entry/transactions/pages/stock-In/add-stock-in/add-stock-in.component.ts |
| AddStockInComponent | itemId | Visible control; optional or API-dependent | apps/inventory/src/app/remote-entry/transactions/pages/stock-In/add-stock-in/add-stock-in.component.ts |
| AddStockInComponent | notes | Visible control; optional or API-dependent | apps/inventory/src/app/remote-entry/transactions/pages/stock-In/add-stock-in/add-stock-in.component.ts |
| AddStockInComponent | quantity | Visible control; optional or API-dependent | apps/inventory/src/app/remote-entry/transactions/pages/stock-In/add-stock-in/add-stock-in.component.ts |
| AddStockInComponent | receiptDate | Conditionally required/validated in component | apps/inventory/src/app/remote-entry/transactions/pages/stock-In/add-stock-in/add-stock-in.component.ts |
| AddStockInComponent | sourceDocumentId | Required in component validator | apps/inventory/src/app/remote-entry/transactions/pages/stock-In/add-stock-in/add-stock-in.component.ts |
| AddStockInComponent | sourceDocumentType | Required in component validator | apps/inventory/src/app/remote-entry/transactions/pages/stock-In/add-stock-in/add-stock-in.component.ts |
| AddStockInComponent | uomId | Visible control; optional or API-dependent | apps/inventory/src/app/remote-entry/transactions/pages/stock-In/add-stock-in/add-stock-in.component.ts |
| EditStockInComponent | barCode | Visible control; optional or API-dependent | apps/inventory/src/app/remote-entry/transactions/pages/stock-In/edit-stock-in/edit-stock-in.component.ts |
| EditStockInComponent | cost | Required in component validator | apps/inventory/src/app/remote-entry/transactions/pages/stock-In/edit-stock-in/edit-stock-in.component.ts |
| EditStockInComponent | itemId | Visible control; optional or API-dependent | apps/inventory/src/app/remote-entry/transactions/pages/stock-In/edit-stock-in/edit-stock-in.component.ts |
| EditStockInComponent | notes | Visible control; optional or API-dependent | apps/inventory/src/app/remote-entry/transactions/pages/stock-In/edit-stock-in/edit-stock-in.component.ts |
| EditStockInComponent | quantity | Required in component validator | apps/inventory/src/app/remote-entry/transactions/pages/stock-In/edit-stock-in/edit-stock-in.component.ts |
| EditStockInComponent | receiptDate | Conditionally required/validated in component | apps/inventory/src/app/remote-entry/transactions/pages/stock-In/edit-stock-in/edit-stock-in.component.ts |
| EditStockInComponent | sourceDocumentId | Required in component validator | apps/inventory/src/app/remote-entry/transactions/pages/stock-In/edit-stock-in/edit-stock-in.component.ts |
| EditStockInComponent | sourceDocumentType | Required in component validator | apps/inventory/src/app/remote-entry/transactions/pages/stock-In/edit-stock-in/edit-stock-in.component.ts |
| EditStockInComponent | uomId | Required in component validator | apps/inventory/src/app/remote-entry/transactions/pages/stock-In/edit-stock-in/edit-stock-in.component.ts |
| EditStockInComponent | warehouseId | Required in component validator | apps/inventory/src/app/remote-entry/transactions/pages/stock-In/edit-stock-in/edit-stock-in.component.ts |
| ViewStockInComponent | code | Visible control; optional or API-dependent | apps/inventory/src/app/remote-entry/transactions/pages/stock-In/view-stock-in/view-stock-in.component.ts |
| ViewStockInComponent | notes | Visible control; optional or API-dependent | apps/inventory/src/app/remote-entry/transactions/pages/stock-In/view-stock-in/view-stock-in.component.ts |
| ViewStockInComponent | receiptDate | Visible control; optional or API-dependent | apps/inventory/src/app/remote-entry/transactions/pages/stock-In/view-stock-in/view-stock-in.component.ts |
| ViewStockInComponent | sourceDocumentType | Visible control; optional or API-dependent | apps/inventory/src/app/remote-entry/transactions/pages/stock-In/view-stock-in/view-stock-in.component.ts |
| ViewStockInComponent | warehouseName | Visible control; optional or API-dependent | apps/inventory/src/app/remote-entry/transactions/pages/stock-In/view-stock-in/view-stock-in.component.ts |
Observed frontend actions
| Component | Click action/handler | Business review requirement | Component source |
|---|---|---|---|
| AddStockInComponent | addLineStockIn | 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/inventory/src/app/remote-entry/transactions/pages/stock-In/add-stock-in/add-stock-in.component.ts |
| AddStockInComponent | 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/inventory/src/app/remote-entry/transactions/pages/stock-In/add-stock-in/add-stock-in.component.ts |
| AddStockInComponent | 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/inventory/src/app/remote-entry/transactions/pages/stock-In/add-stock-in/add-stock-in.component.ts |
| AddStockInComponent | setTracking | 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/inventory/src/app/remote-entry/transactions/pages/stock-In/add-stock-in/add-stock-in.component.ts |
| EditStockInComponent | 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/inventory/src/app/remote-entry/transactions/pages/stock-In/edit-stock-in/edit-stock-in.component.ts |
| EditStockInComponent | noDelete | 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/inventory/src/app/remote-entry/transactions/pages/stock-In/edit-stock-in/edit-stock-in.component.ts |
| EditStockInComponent | 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/inventory/src/app/remote-entry/transactions/pages/stock-In/edit-stock-in/edit-stock-in.component.ts |
| EditStockInComponent | setStockInTracking | 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/inventory/src/app/remote-entry/transactions/pages/stock-In/edit-stock-in/edit-stock-in.component.ts |
| StockInListComponent | navigateHelpPageComponent | Document the enabled state, permission, input context, resulting API or navigation effect, success refresh, and concrete failure behavior for this handler. | apps/inventory/src/app/remote-entry/transactions/pages/stock-In/stock-in-list/stock-in-list.component.ts |
| StockInListComponent | 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/inventory/src/app/remote-entry/transactions/pages/stock-In/stock-in-list/stock-in-list.component.ts |
| StockInListComponent | 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/inventory/src/app/remote-entry/transactions/pages/stock-In/stock-in-list/stock-in-list.component.ts |
| StockInListComponent | 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/inventory/src/app/remote-entry/transactions/pages/stock-In/stock-in-list/stock-in-list.component.ts |
| StockInListComponent | 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/inventory/src/app/remote-entry/transactions/pages/stock-In/stock-in-list/stock-in-list.component.ts |
| StockInListComponent | printout | 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/inventory/src/app/remote-entry/transactions/pages/stock-In/stock-in-list/stock-in-list.component.ts |
| StockInListComponent | 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/inventory/src/app/remote-entry/transactions/pages/stock-In/stock-in-list/stock-in-list.component.ts |
| StockInListComponent | routeToView | 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/inventory/src/app/remote-entry/transactions/pages/stock-In/stock-in-list/stock-in-list.component.ts |
| ViewStockInComponent | 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/inventory/src/app/remote-entry/transactions/pages/stock-In/view-stock-in/view-stock-in.component.ts |
| ViewStockInComponent | routeToSourceType | Open the correct originating document type and ID only when a source link exists and its module view permission is available. | apps/inventory/src/app/remote-entry/transactions/pages/stock-In/view-stock-in/view-stock-in.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: AppInventoryPermissions.StockIn_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: AppInventoryPermissions.StockIn_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: AppInventoryPermissions.StockIn_Edit; Guards: PolicyAuthGuard, preventPostedGuard
- stockin - 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: AppInventoryPermissions.StockIn_List; Guards: PolicyAuthGuard
- view/:id - View/detail: Load an authorized immutable/detail representation with status-aware actions, linked records, print/export where exposed, and not-found/forbidden handling. Security observed: Permission: AppInventoryPermissions.StockIn_View; Guards: PolicyAuthGuard