Intranet · SAFT-E / IntelliSales import

Lets a store upload its SAFT-E fiscal file for a month so sales are derived from the official accounting export instead of being typed in, with anonymisation and a history of uploaded files and their processing status.

AreaIntranet
Routesintranet.safte · intranet.safte.import · intranet.safte.import.index
Centre modulesintranet · intranet-sovos
Staff levelsroot · admin · manager · storeManager
Modelsanonymazed-saft · closed-month · commerce · sovos-file
UI labeltitle.header.safte / menu.navbar.intranet.saft
Coverage3 use cases · 1 happy · 7 failure

Known issues (1)

Missing translations

These keys are used on this screen but do not exist in translations.json, so users see the raw key:

  • error.month.required
  • sovosFile

How it works

A wizard with three steps and no per-step attribute validation (validateAttrs: null throughout); the real check is anonymazedSaft.validate() requiring a file, a commerce and a month. The month picker is filtered by notValidatedMonths, computed as the store’s closed months minus those already validated — so a store cannot upload against a settled month. The upload posts directly and converts a non-OK response into a rejection (response.json().then((error) => Promise.reject(error))), which is a cleaner pattern than most fetches here. The index tab lists history with amount, commerce, month, name and status, and the sales screen branches on hasIntelliSalesEnabled to hide manual editing when this is the source of truth.

Use cases

Why someone opens this (3)

  • A Portuguese/Spanish tenant submitting its SAFT-E file so the centre derives turnover from certified accounting data.
  • Avoiding manual sales entry entirely for IntelliSales-enabled stores.
  • Checking whether last month’s file was processed successfully.

Path map

flowchart LR
    F(["SAFT-E / IntelliSales import"]):::feat
    F --> H1["SAFT file uploaded and processed"]:::ok
    F -.-> X1["File missing"]:::bad
    F -.-> X2["Store missing"]:::bad
    F -.-> X3["Month missing"]:::bad
    F -.-> X4["Month already validated"]:::bad
    F -.-> X5["Upload rejected by the API"]:::bad
    F -.-> X6["Sovos list unavailable"]:::bad
    F -.-> X7["Raw translation key on screen"]:::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

SAFT file uploaded and processed

  1. Store user opens IntelliSales → import and selects the store.
  2. Picks a month from the not-yet-validated list.
  3. Attaches the SAFT-E file and chooses the anonymisation option.
  4. anonymazedSaft.validate() passes and the file is uploaded.
  5. The history tab shows it with its processing status and the derived amount.

Failure paths

QA checklist

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

  • ✅ SAFT file uploaded and processed
  • ⛔ File missing
  • ⛔ Store missing
  • ⛔ Month missing
  • ⛔ Month already validated
  • ⛔ Upload rejected by the API
  • ⛔ Sovos list unavailable
  • ⛔ Raw translation key on screen

Implementation


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