Intranet · Store sales declaration & month closing

The monthly sales cycle for every store: a calendar of declared daily sales, manual entry, bulk XLSX import, estimated-sales declaration, month closing and validation, reopen requests, rejection with an automatic communication to the store, and an audit log of who changed what.

AreaIntranet
Routesintranet.sales · intranet.sales.index
Centre modulesintranet · intranet-sovos · intranet-yardi
Staff levelsroot · admin · manager · scmanager · storeManager · commerce · owner · sales
Modelsclosed-month · commerce · estimated-sale · intranet-sale · intranet-sales-year · sale-concept
UI labeltitle.header.sales / menu.navbar.intranet.sale.index
Coverage7 use cases · 4 happy · 12 failure

How it works

The most state-heavy part of the intranet. A store-month moves through four states (without_sales, unclosed, closed, validated) each with its own colour and icon. Role logic is deliberately split: canReopenMonth is true for admin/manager on a validated month, while canRequestToReopenMonth is the inverse role test for everyone else — so store users request and management grants. canAddNewSale combines the closed-month ability with ‘the month is not validated’, and the ability itself requires the month to be in the past, not already closed, and to have at least one sale. New-sale dates are clamped to the selected month (minAllowedNewSaleDate/maxAllowedNewSaleDate). Type guards are unusually strict: closeMonth, confirmCloseMonth and rejectCloseMonth all throw TypeError/IllegalStateError when given the wrong shape. Rejecting a close creates an intranet-communication addressed to the store, so the rejection is auditable and the store is notified in one step. parseXLSX reads the file through the xlsx service into draft sales for review before saveSales commits them, and downloadTemplate emits the expected shape. IntelliSales/Sovos centres hide the manual delete column and show Sovos totals instead (canShowSovosSales additionally requires a non-zero value).

Use cases

Why someone opens this (7)

  • A store manager entering daily turnover for the month.
  • Importing a month of sales from the till system as an XLSX instead of typing them.
  • Declaring estimated sales when actuals are not yet available.
  • A store closing its month so the centre can consolidate.
  • Centre management validating or rejecting a closed month, with the store notified automatically.
  • A store asking management to reopen a validated month to fix an error.
  • Auditing who entered or changed a figure via the log table.

Path map

flowchart LR
    F(["Store sales declaration and month closing"]):::feat
    F --> H1["Month declared, closed and validated"]:::ok
    F --> H2["Bulk import from XLSX"]:::ok
    F --> H3["Close rejected and store notified"]:::ok
    F --> H4["Estimated sales declared"]:::ok
    F -.-> X1["Sale in a future date"]:::bad
    F -.-> X2["Sale in a closed month"]:::bad
    F -.-> X3["Amount missing or zero"]:::bad
    F -.-> X4["Date missing"]:::bad
    F -.-> X5["Month cannot be closed"]:::bad
    F -.-> X6["Close fails"]:::bad
    F -.-> X7["Reject-close fails"]:::bad
    F -.-> X8["Wrong argument types"]:::bad
    F -.-> X9["Invalid XLSX"]:::bad
    F -.-> X10["Estimated sales save fails"]:::bad
    F -.-> X11["API error with a detail key"]:::bad
    F -.-> X12["Month already validated"]:::bad
    classDef feat fill:#26688f,stroke:#26688f,color:#ffffff,font-weight:bold
    classDef ok fill:#e3f1ea,stroke:#0d6b42,color:#0d4a2e
    classDef bad fill:#f7e6e2,stroke:#9a2d1c,color:#6e1f13

Happy paths

Month declared, closed and validated

  1. Store user selects the store and month; the calendar shows the current state.
  2. Daily sales are added with date, concept, amount and ticket count — dates constrained to the month.
  3. When complete, the user closes the month; the confirmation modal names the store and month (intranet.close_month-message).
  4. confirmCloseMonth validates the types and marks the month closed; informative-message.close-month.success.message confirms.
  5. Management later validates it, moving the state to validated.

Bulk import from XLSX

  1. User downloads the template, fills it and opens the import modal.
  2. parseXLSX reads the file into draft sales shown for review.
  3. User confirms; saveSales persists them and sales.upload-xlsx-success is shown.

Close rejected and store notified

  1. Management opens the reject-close modal on a closed month and writes a reason.
  2. rejectCloseMonth validates the communication model and saves both the rejection and an intranet-communication to the store.
  3. informative-message.reject-close-month.success.message confirms and the store sees the communication.

Estimated sales declared

  1. User with declareEstimatesSales opens the estimated-sales form.
  2. The month’s start/end dates and the store are attached automatically.
  3. Save succeeds with intranet.sales.estimated-sales-has-been-succesfully-saved.

Failure paths

QA checklist

Tick these off while regression-testing this feature. The boxes are plain Markdown, so progress is visible in git diffs.

  • ✅ Month declared, closed and validated
  • ✅ Bulk import from XLSX
  • ✅ Close rejected and store notified
  • ✅ Estimated sales declared
  • ⛔ Sale in a future date
  • ⛔ Sale in a closed month
  • ⛔ Amount missing or zero
  • ⛔ Date missing
  • ⛔ Month cannot be closed
  • ⛔ Close fails
  • ⛔ Reject-close fails
  • ⛔ Wrong argument types
  • ⛔ Invalid XLSX
  • ⛔ Estimated sales save fails
  • ⛔ API error with a detail key
  • ⛔ Month already validated

Implementation


Generated from doc/feature-inventory.json · id intranet-sales · commit 276788ca6