Skip to content

Supplier Settlement ​

This document is the living decision record for supplier bank-payment allocation, document debt, FIFO, overpayment, and supplier advances.

Confirmed business rules ​

  1. A document can receive payment only when Syrve/iiko reliably confirms IsProcessed == true and IsDeleted == false.

  2. Unknown processing state is blocked. PaymentStatus, UnpaidAmount, candidate membership, and unpaid-batch membership are not evidence that a document was processed.

  3. The complete bank-transaction amount must have an accounting destination:

    BankTransaction.Amount = DocumentSettlementAmount + SupplierAdvanceAmount.

  4. UnallocatedPaymentAmount may exist in preview/draft only. Confirm, approve, posting preview, queue, dry-run, execute, and retry are blocked unless it is zero.

  5. A document may remain partially unpaid after the complete bank payment is allocated. Remaining document debt is not unallocated bank money.

  6. Automatic allocation uses deterministic FIFO over eligible current debt.

  7. Money exceeding eligible document debt is a required supplier advance. It must reach Syrve on a separate supplier-advance accounting operation and may not remain as a local balance.

  8. A transport success is Posted, not Reconciled; independent readback must confirm every expected document remainder.

Current sources of truth ​

QuestionCurrent source
Document processed/deletedList-record processed/deleted normalized into SyrveDocumentSnapshot
Current document debtRefreshed snapshot UnpaidAmount and payment readback
Bank amountPersisted BankTransaction.Amount
Confirmed allocationPersisted PaymentAllocation plus ordered PaymentAllocationLine rows
External document writeSyrvePaymentPosting evidence and connector result
Reconciled document debtIndependent live readback matched to ExpectedUnpaidAmountAfter
Supplier advanceSyrve advance operation and readback — contract not yet available

Allocation preview always replaces the caller-supplied preview amount with persisted BankTransaction.Amount. A reduced request value therefore cannot hide an unallocated remainder. Every later write boundary rereads that bank transaction. If it is missing or hidden by the deletion lifecycle, processing fails closed with bank_transaction_not_found; PaymentAllocation.TotalAmount is never used as a substitute source of truth.

Historical snapshot rows migrated before processing-state support remain IsProcessed = NULL and are ineligible until refreshed. Historical Posted/Reconciled allocations are not bulk-rewritten.

Canonical amounts ​

  • DocumentSettlementAmount: amount assigned to current document debt.
  • SupplierAdvanceAmount: amount assigned to a real planned supplier-advance operation.
  • UnallocatedPaymentAmount: signed bank money without an accounting destination.
  • InvoiceDebtRemaining: document debt expected after the planned document settlements.

The canonical calculation is:

UnallocatedPaymentAmount = BankTransaction.Amount - DocumentSettlementAmount - SupplierAdvanceAmount.

No absolute-value conversion is used. A positive result has no accounting destination; a negative result over-assigns the bank transaction. Both block the financial workflow.

Examples:

Bank paymentDocument debtDocument settlementSupplier advanceUnallocatedDebt remainingRunnable now
300000300000300000000Yes
2500003000002500000050000Yes
35000030000030000050000 required0 in the future plan0No, advance transport unavailable

Legacy RemainingAmount, HasOverpayment, HasUnderpayment, and line IsOverpayment remain API compatibility fields. They are not accounting sources of truth.

FIFO foundation ​

SupplierSettlementAllocator is pure and deterministic. It has no database, connector, transport, clock, or side effects. Its eligibility filter requires:

  • processed and not deleted;
  • payment status Unpaid or PartiallyPaid;
  • positive UnpaidAmount;
  • supported direction/document type;
  • matching supplier and currency.

Order:

  1. reliable DueDate, if supplied;
  2. otherwise DocumentDate;
  3. ordinal ExternalDocumentId.

Current production snapshots do not expose a confirmed due date, so the application maps DocumentDate. The accounting choice of final FIFO date remains to be confirmed.

AutomaticFifo is generated only for a matched supplier when preview receives no explicit lines. Explicit lines imply the operator's manual allocation and are never replaced. Confirm persists AllocationMethod, exact amounts, and Sequence. Worker and retry consume the saved lines and never recalculate FIFO.

Workflow and safety boundaries ​

The same document eligibility and payment-completeness rules are evaluated at:

  • candidate build and persisted candidate read;
  • automatic safe proposal and workbench prepare;
  • explicit preview lines;
  • confirm;
  • allocation approval;
  • posting preview/approval/queue;
  • dry-run;
  • retry;
  • worker preflight immediately before transport;
  • reconciliation where current document state is relevant.

A snapshot regression to unknown, not processed, deleted, or no longer payable moves the active allocation to review/failure according to its current boundary. Queue creates no posting/outbox work, and worker does not call transport.

The worker atomically persists Posting, attempt count, claim timestamp, bounded lease, stable posting date, and stable request hash before the external call. A timeout, exception, or expired lease becomes WriteOutcomeUnknown; normal retry is disabled and readback is queued. Blind retry is forbidden.

Reconciliation compares every saved line's ExpectedUnpaidAmountAfter with independent readback. Only a complete match sets ReconciledAtUtc. A mismatch persists/links an anomaly and leaves the timestamp null. Until that successful readback, a Posted posting and its allocation remain Processing in the accountant workbench; idempotent replay does not report AlreadyCompleted. Workbench classification uses canonical UnallocatedPaymentAmount for incomplete/over-assigned bank-payment reasons. A line with IsPartialPayment = true and zero unallocated bank amount is not an attention reason: its positive InvoiceDebtRemaining is valid supplier debt.

Current transport boundary ​

Production document posting remains PaymentAllocation 1:1 SyrvePaymentPosting and uses the existing document-based connector contract, including saved split items for multi-document settlement. A single shared document-settlement PostingType, AccountId, and CashFlowArticleId is used for the bank payment.

SupplierSettlementPlan and SupplierSettlementPostingOperationPlanner are non-runtime foundation models for the future 1:N relationship:

  • one document-settlement operation;
  • one separate supplier-advance operation when required.

The advance operation is always TransportUnavailable/non-runnable. It has no external id, write/readback evidence, queue row, transport call, or local accounting ledger.

Unconfirmed rules ​

  • Whether Syrve can perform supplier-level FIFO itself.
  • Whether one Syrve operation can settle multiple documents atomically.
  • The supplier-advance RPC/endpoint and XML request/response.
  • Amount signs, account correspondence, cash-flow requirements, dates, and mandatory fields.
  • Advance external id and readback.
  • Full/partial application of advance to a processed document.
  • Cancellation, reversal/storno, duplicate-call, timeout, RMS, and CHAIN behavior.

The required research prompt is IikoConnector: FIFO supplier settlement and supplier advances.

Prohibited temporary solutions ​

  • Inventing supplier-level or advance RPC contracts.
  • Sending an advance as an ordinary payment without a document.
  • Treating RemainingAmount or RequiredSupplierAdvanceAmount as a posted advance.
  • Creating a fake external advance id or returning fake success.
  • Building a parallel local advance ledger as the accounting source of truth.
  • Sending only the document portion of an overpaid bank transaction and retaining the remainder.
  • Recalculating FIFO in the worker after confirm.

Migration path after verified traces ​

  1. Add source/trace-backed typed connector APIs for advance create, readback, apply, and reversal.
  2. Consume a new verified NuGet package; do not vendor connector source.
  3. Add persisted settlement plan and 1:N posting-operation entities with independent idempotency, request hash, write/readback/reversal evidence, and status.
  4. Keep document settlement and supplier advance as separate accounting groups and operations.
  5. Enable an advance operation only after create + independent readback + reversal contracts pass RMS/CHAIN tests.
  6. Define recovery for partial group success before allowing the combined plan into production.
  7. Add UI/API for advance only after runtime evidence is authoritative.