Skip to content

Asset Sales and Returns

Backlog fieldValue
Story IDAP-FA-006
EpicFixed Assets
Story typeBusiness workflow
Review statusDraft - business analyst and business owner review required
Source evidenceAppsPortal.Apis controller, application command/query handlers, validators, domain entities, and matching MFE workflow where available
Last source review2026-07-10

User story

As asset accountants, I want to record disposals by sale and eligible sales returns so that asset status, proceeds, tax, and gain/loss are accurate.

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

  1. Only authorized users can view or execute the feature's actions.
  2. Required business data, active dependencies, tenant/branch scope, and current document state are validated.
  3. Invalid requests return actionable validation errors without applying a partial change.
  4. Search, list, view, print, and export operations use the same authorized business scope.
  5. Material create, edit, status, approval, posting, reversal, and integration actions are auditable where applicable.
  6. Financial or stock effects are applied atomically and no more than once.

Posting details

  1. Sale Post validates Draft/open period/customer/assets/price/tax/payment terms and resolves Receivable through Sales, Asset and Accumulated Depreciation from asset then group, and P/L from asset then group then Fixed Assets settings.
  2. Delegate the journal to Accounting: debit Customer Receivable, remove asset cost and accumulated depreciation, post gain/loss, and credit output VAT. Create due balances and move assets to sold/waiting-for-return state.
  3. Return Post validates the source sale and eligible asset state, then builds the opposite commercial, asset, depreciation, P/L, and VAT effects.
  4. Update original remaining quantities/return status and restore asset lifecycle state.
  5. Accounting, Sales receivable/balances, asset values/status, and source status commit together.

General ledger posting

Transaction/componentDebitCreditRule
Asset saleCustomer Receivable and Accumulated DepreciationAsset GL and Output TaxResidual difference posts to gain/loss P/L.
Loss / gainLoss P/LGain P/LOnly one direction for difference between proceeds and NBV.
Sale returnOpposite original accountsOpposite original accountsReverses receivable, tax, asset, depreciation, and gain/loss.

Other module and document effects

AreaEffectConditional/no effect
Asset registerSale moves asset to sold/waiting state; return restores eligible state/value.No Inventory Stock Out/In.
Sales/FinanceCreates customer due balance eligible for Payment In; return reduces it.Posting alone does not move cash.
Source saleReturn updates remaining/status.Ineligible later lifecycle blocks return.

Core acceptance scenarios

  1. Given eligible assets, customer, open period, tax, and resolved asset/depreciation/P&L accounts, when the asset sale is posted, then receivable, asset removal, accumulated depreciation, gain/loss, VAT, balances, and asset state commit together.
  2. Given the posted sale is validly returned, when the operation is attempted, then all financial/lifecycle effects reverse and source return status updates atomically.
  3. 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.

Account resolution

  • Customer receivable follows Sales customer then category.
  • Asset account: asset override then asset group.
  • Accumulated depreciation: asset override then asset group.
  • Profit/Loss: asset override, then group, then Fixed Assets General Settings.
  • VAT: selected Tax account.

Sale Post

Requires Draft, open period, eligible assets, customer, price/currency/tax/payment terms, and all accounts. Post debits customer receivable, removes asset cost, removes accumulated depreciation, posts balancing gain/loss, credits VAT, creates due balances from payment terms, moves asset to the sold/waiting-for-return state, links journal, and marks Posted.

Sales Return Post

Requires an eligible posted sale and asset in WaitingForSalesReturn. It credits customer receivable, restores asset cost and accumulated depreciation position, reverses gain/loss and VAT as calculated, updates original invoice remaining quantities and Partially/Fully Returned status, restores the asset state, and commits atomically.

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/pageComponentModeRoute permission/guardMapping confidenceSource
(module default)AssetSalesInvoiceReturnMainComponentList/navigationPermission: AppFixedAssetsPermissions.AssetsReturnSales_List; Guards: PolicyAuthGuardExplicit frontend feature ruleapps/fixedAssets/src/app/remote-entry/transactions/assets-sales-return/assets-sales-return-routing.module.ts:12
(module default)AssetSalesReturnListComponentList/navigationPermission: AppFixedAssetsPermissions.AssetsReturnSales_List; Guards: PolicyAuthGuardExplicit frontend feature ruleapps/fixedAssets/src/app/remote-entry/transactions/assets-sales-return/assets-sales-return-routing.module.ts:20
(module default)AssetsSalesInvoiceMainComponentList/navigationPermission: AppFixedAssetsPermissions.AssetsSalesInvoice_List; Guards: PolicyAuthGuardExplicit frontend feature ruleapps/fixedAssets/src/app/remote-entry/transactions/assets-sales-invoice/assets-sales-invoice-routing.module.ts:12
(module default)ListAssetsSalesInvoiceComponentList/navigationPermission: AppFixedAssetsPermissions.AssetsSalesInvoice_List; Guards: PolicyAuthGuardExplicit frontend feature ruleapps/fixedAssets/src/app/remote-entry/transactions/assets-sales-invoice/assets-sales-invoice-routing.module.ts:20
addAddAssetsSalesInvoiceComponentAddPermission: AppFixedAssetsPermissions.AssetsSalesInvoice_Add; Guards: PolicyAuthGuardExplicit frontend feature ruleapps/fixedAssets/src/app/remote-entry/transactions/assets-sales-invoice/assets-sales-invoice-routing.module.ts:29
addAssetSalesReturnAddComponentAddPermission: AppFixedAssetsPermissions.AssetsReturnSales_Add; Guards: PolicyAuthGuardExplicit frontend feature ruleapps/fixedAssets/src/app/remote-entry/transactions/assets-sales-return/assets-sales-return-routing.module.ts:30
assets-return-sales-invoiceLazy-loaded routeList/navigationNo route-level permission/guard found in source windowExplicit frontend feature ruleapps/fixedAssets/src/app/remote-entry/transactions/transactions-routing.module.ts:55
assets-sales-invoiceLazy-loaded routeList/navigationNo route-level permission/guard found in source windowExplicit frontend feature ruleapps/fixedAssets/src/app/remote-entry/transactions/transactions-routing.module.ts:34
assets-sales-invoice-reportFixedAssetsSalesReportComponentReport/printNo route-level permission/guard found in source windowFeature token matchapps/fixedAssets/src/app/remote-entry/reports/reports-routing.module.ts:18
edit/:idAssetSalesReturnEditComponentEditPermission: AppFixedAssetsPermissions.AssetsReturnSales_Edit; Guards: PolicyAuthGuardExplicit frontend feature ruleapps/fixedAssets/src/app/remote-entry/transactions/assets-sales-return/assets-sales-return-routing.module.ts:40
edit/:idEditAssetsSalesInvoiceComponentEditPermission: AppFixedAssetsPermissions.AssetsSalesInvoice_Edit; Guards: PolicyAuthGuardExplicit frontend feature ruleapps/fixedAssets/src/app/remote-entry/transactions/assets-sales-invoice/assets-sales-invoice-routing.module.ts:39
sequenceSequenceComponentSequenceNo route-level permission/guard found in source windowExplicit frontend feature ruleapps/fixedAssets/src/app/remote-entry/transactions/assets-sales-invoice/assets-sales-invoice-routing.module.ts:59
sequenceSequenceComponentSequenceNo route-level permission/guard found in source windowExplicit frontend feature ruleapps/fixedAssets/src/app/remote-entry/transactions/assets-sales-return/assets-sales-return-routing.module.ts:60
view/:idAssetSalesReturnViewComponentView/detailPermission: AppFixedAssetsPermissions.AssetsReturnSales_View; Guards: PolicyAuthGuardExplicit frontend feature ruleapps/fixedAssets/src/app/remote-entry/transactions/assets-sales-return/assets-sales-return-routing.module.ts:50
view/:idViewAssetsSalesInvoiceComponentView/detailPermission: AppFixedAssetsPermissions.AssetsSalesInvoice_View; Guards: PolicyAuthGuardExplicit frontend feature ruleapps/fixedAssets/src/app/remote-entry/transactions/assets-sales-invoice/assets-sales-invoice-routing.module.ts:49

Observed frontend fields and validation

ComponentControlObserved frontend ruleComponent source
AssetsSalesReturnHeaderComponentassetsSalesInvoiceHeaderIdRequired in component validatorapps/fixedAssets/src/app/remote-entry/transactions/assets-sales-return/component/assets-sales-return-header/assets-sales-return-header.component.ts
AssetsSalesReturnHeaderComponentcustomerIdRequired in component validatorapps/fixedAssets/src/app/remote-entry/transactions/assets-sales-return/component/assets-sales-return-header/assets-sales-return-header.component.ts
AssetsSalesReturnHeaderComponentdateRequired in component validatorapps/fixedAssets/src/app/remote-entry/transactions/assets-sales-return/component/assets-sales-return-header/assets-sales-return-header.component.ts
AssetsSalesReturnHeaderComponentdescriptionVisible control; optional or API-dependentapps/fixedAssets/src/app/remote-entry/transactions/assets-sales-return/component/assets-sales-return-header/assets-sales-return-header.component.ts
AssetsSalesReturnHeaderComponentreferenceVisible control; optional or API-dependentapps/fixedAssets/src/app/remote-entry/transactions/assets-sales-return/component/assets-sales-return-header/assets-sales-return-header.component.ts
FixedAssetsSalesReportComponentassetsGroupIdsVisible control; optional or API-dependentapps/fixedAssets/src/app/remote-entry/reports/fixed-assets-sales-report/fixed-assets-sales-report.component.ts
FixedAssetsSalesReportComponentassetsIdsVisible control; optional or API-dependentapps/fixedAssets/src/app/remote-entry/reports/fixed-assets-sales-report/fixed-assets-sales-report.component.ts
FixedAssetsSalesReportComponentassetsLocationIdsVisible control; optional or API-dependentapps/fixedAssets/src/app/remote-entry/reports/fixed-assets-sales-report/fixed-assets-sales-report.component.ts
FixedAssetsSalesReportComponentcustomerIdsVisible control; optional or API-dependentapps/fixedAssets/src/app/remote-entry/reports/fixed-assets-sales-report/fixed-assets-sales-report.component.ts
FixedAssetsSalesReportComponentfromDateVisible control; optional or API-dependentapps/fixedAssets/src/app/remote-entry/reports/fixed-assets-sales-report/fixed-assets-sales-report.component.ts
FixedAssetsSalesReportComponentStatusesVisible control; optional or API-dependentapps/fixedAssets/src/app/remote-entry/reports/fixed-assets-sales-report/fixed-assets-sales-report.component.ts
FixedAssetsSalesReportComponenttoDateVisible control; optional or API-dependentapps/fixedAssets/src/app/remote-entry/reports/fixed-assets-sales-report/fixed-assets-sales-report.component.ts
HeaderAssetsSalesInvoiceComponentassetsSalesInvoiceSelcetedAssetsVisible control; optional or API-dependentapps/fixedAssets/src/app/remote-entry/transactions/assets-sales-invoice/components/header-assets-sales-invoice/header-assets-sales-invoice.component.ts
HeaderAssetsSalesInvoiceComponentcustomerIdRequired in component validatorapps/fixedAssets/src/app/remote-entry/transactions/assets-sales-invoice/components/header-assets-sales-invoice/header-assets-sales-invoice.component.ts
HeaderAssetsSalesInvoiceComponentdateRequired in component validatorapps/fixedAssets/src/app/remote-entry/transactions/assets-sales-invoice/components/header-assets-sales-invoice/header-assets-sales-invoice.component.ts
HeaderAssetsSalesInvoiceComponentdescriptionVisible control; optional or API-dependentapps/fixedAssets/src/app/remote-entry/transactions/assets-sales-invoice/components/header-assets-sales-invoice/header-assets-sales-invoice.component.ts
HeaderAssetsSalesInvoiceComponentpaymentTermIdRequired in component validatorapps/fixedAssets/src/app/remote-entry/transactions/assets-sales-invoice/components/header-assets-sales-invoice/header-assets-sales-invoice.component.ts
HeaderAssetsSalesInvoiceComponentreferenceVisible control; optional or API-dependentapps/fixedAssets/src/app/remote-entry/transactions/assets-sales-invoice/components/header-assets-sales-invoice/header-assets-sales-invoice.component.ts

Observed frontend actions

ComponentClick action/handlerBusiness review requirementComponent source
AssetSalesReturnListComponentonDeleteAvailable 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/fixedAssets/src/app/remote-entry/transactions/assets-sales-return/pages/asset-sales-return-list/asset-sales-return-list.component.ts
AssetSalesReturnListComponentonEditOpen 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/fixedAssets/src/app/remote-entry/transactions/assets-sales-return/pages/asset-sales-return-list/asset-sales-return-list.component.ts
AssetSalesReturnListComponentonPostAvailable 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/fixedAssets/src/app/remote-entry/transactions/assets-sales-return/pages/asset-sales-return-list/asset-sales-return-list.component.ts
AssetSalesReturnListComponentonPrintOutGenerate 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/fixedAssets/src/app/remote-entry/transactions/assets-sales-return/pages/asset-sales-return-list/asset-sales-return-list.component.ts
AssetSalesReturnListComponentonViewOpen 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/fixedAssets/src/app/remote-entry/transactions/assets-sales-return/pages/asset-sales-return-list/asset-sales-return-list.component.ts
AssetSalesReturnListComponentrouteToJournalViewOpen 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/fixedAssets/src/app/remote-entry/transactions/assets-sales-return/pages/asset-sales-return-list/asset-sales-return-list.component.ts
BodyAssetsSalesInvoiceComponentonDeleteRowAvailable 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/fixedAssets/src/app/remote-entry/transactions/assets-sales-invoice/components/body-assets-sales-invoice/body-assets-sales-invoice.component.ts
BodyAssetsSalesInvoiceComponentopenDialogOpen 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/fixedAssets/src/app/remote-entry/transactions/assets-sales-invoice/components/body-assets-sales-invoice/body-assets-sales-invoice.component.ts
FixedAssetsSalesReportComponentprintReportGenerate 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/fixedAssets/src/app/remote-entry/reports/fixed-assets-sales-report/fixed-assets-sales-report.component.ts
FixedAssetsSalesReportComponentrouteToAssetViewOpen 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/fixedAssets/src/app/remote-entry/reports/fixed-assets-sales-report/fixed-assets-sales-report.component.ts
FixedAssetsSalesReportComponentrouteToCustomerDefDocument the enabled state, permission, input context, resulting API or navigation effect, success refresh, and concrete failure behavior for this handler.apps/fixedAssets/src/app/remote-entry/reports/fixed-assets-sales-report/fixed-assets-sales-report.component.ts
FixedAssetsSalesReportComponentrouteToInvoiceDocument the enabled state, permission, input context, resulting API or navigation effect, success refresh, and concrete failure behavior for this handler.apps/fixedAssets/src/app/remote-entry/reports/fixed-assets-sales-report/fixed-assets-sales-report.component.ts
FixedAssetsSalesReportComponentrouteToJournalEntryViewOpen 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/fixedAssets/src/app/remote-entry/reports/fixed-assets-sales-report/fixed-assets-sales-report.component.ts
FixedAssetsSalesReportComponentviewDataOpen 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/fixedAssets/src/app/remote-entry/reports/fixed-assets-sales-report/fixed-assets-sales-report.component.ts
HeaderAssetsSalesInvoiceComponentopenDialogOpen 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/fixedAssets/src/app/remote-entry/transactions/assets-sales-invoice/components/header-assets-sales-invoice/header-assets-sales-invoice.component.ts
ListAssetsSalesInvoiceComponentonDeleteAvailable 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/fixedAssets/src/app/remote-entry/transactions/assets-sales-invoice/pages/list-assets-sales-invoice/list-assets-sales-invoice.component.ts
ListAssetsSalesInvoiceComponentonEditOpen 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/fixedAssets/src/app/remote-entry/transactions/assets-sales-invoice/pages/list-assets-sales-invoice/list-assets-sales-invoice.component.ts
ListAssetsSalesInvoiceComponentonPostAvailable 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/fixedAssets/src/app/remote-entry/transactions/assets-sales-invoice/pages/list-assets-sales-invoice/list-assets-sales-invoice.component.ts
ListAssetsSalesInvoiceComponentonViewOpen 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/fixedAssets/src/app/remote-entry/transactions/assets-sales-invoice/pages/list-assets-sales-invoice/list-assets-sales-invoice.component.ts
ListAssetsSalesInvoiceComponentprintoutGenerate 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/fixedAssets/src/app/remote-entry/transactions/assets-sales-invoice/pages/list-assets-sales-invoice/list-assets-sales-invoice.component.ts
ListAssetsSalesInvoiceComponentrouteToJournalViewOpen 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/fixedAssets/src/app/remote-entry/transactions/assets-sales-invoice/pages/list-assets-sales-invoice/list-assets-sales-invoice.component.ts

Page-specific frontend acceptance criteria

  1. (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: AppFixedAssetsPermissions.AssetsSalesInvoice_List; Guards: PolicyAuthGuard
  2. add - Add: Render permitted fields, required indicators, defaults, dependent lookups, validation, Save/Cancel, loading, success, and API-error states. Security observed: Permission: AppFixedAssetsPermissions.AssetsReturnSales_Add; Guards: PolicyAuthGuard
  3. assets-return-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: No route-level permission/guard found in source window
  4. assets-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: No route-level permission/guard found in source window
  5. assets-sales-invoice-report - Report/print: Expose documented filters, validation, empty/loading/error states, authorized results, totals, drill-through, print, and export behavior where present. Security observed: No route-level permission/guard found in source window
  6. 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: AppFixedAssetsPermissions.AssetsSalesInvoice_Edit; Guards: PolicyAuthGuard
  7. sequence - Sequence: Show current numbering scope and permit only authorized, valid sequence configuration without retroactively renumbering posted documents. Security observed: No route-level permission/guard found in source window
  8. 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: AppFixedAssetsPermissions.AssetsSalesInvoice_View; Guards: PolicyAuthGuard

Internal Documentation — Microtec