feat(eims): file issued invoices on a cron sweep, off by default

Invoices are produced by the freight workflow rather than by a person, so the
production path for filing is a sweep, not the manual endpoint.

A @Cron picks the oldest never-submitted invoice and hands it to the existing
EimsInvoiceRegistrationService -- no registration logic is duplicated, and the
durable reservation still decides whether the submission may proceed. Sweeping
rather than hooking the eleven places an invoice can be created or issued keeps
the workflow untouched, puts the HTTP call outside the invoice transaction by
construction, and lets a crash or restart be picked up on the next tick.

invoices.eims_status is the queue; nothing new is persisted. Only NOT_SUBMITTED
is eligible: UNKNOWN is never retried automatically because the document may
already be filed, and FAILED waits for an explicit retry policy. The tick also
refuses to start while eims_system_state holds an in-flight submission or a
block, and only one invoice is filed per tick so a misconfiguration costs one
rejected document rather than a burst.

Requires both EIMS_ENABLED and EIMS_AUTO_SUBMIT; the second defaults to false
so authentication can be live long before filing is. Logs carry the invoice
number, status and IRN only.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Hagernesh
2026-08-07 14:58:32 +00:00
parent 02db3d2e73
commit 67573d0835
6 changed files with 298 additions and 0 deletions

View File

@@ -181,3 +181,10 @@ EIMS_UNIT_DEFAULT=PCS
EIMS_BUYER_COUNTRY_CODE=
EIMS_CASHIER_NAME=
EIMS_SALESPERSON_NAME=
# Automatic filing of issued invoices (@Cron sweep, one invoice per tick).
# Independent of EIMS_ENABLED on purpose: authentication can be live long before
# filing is. Both must be true before anything is submitted automatically.
EIMS_AUTO_SUBMIT=false
EIMS_AUTO_SUBMIT_CRON=0 */5 * * * *
# MoR rejects documents older than 3 days; the sweep will not attempt those.
EIMS_AUTO_SUBMIT_MAX_AGE_DAYS=3