⏰ Payment due date: DueDate
Updated
← Developer wiki For the user: what the interface shows.
IPaymentDueService (Common): DaysOfAsync(Guid) reads PaymentTerm.Days; an
empty id or no row → 0. DueOn(start, days) is .Date plus the days; a year
< 1902 → today (an optional document DateTime). Negative days = 0.
The contract uses no generated entities. The dictionary is resolved at the call, not in the constructor (otherwise the scoped manager is dead by the time of the save).
Stamped in OnBeforeSave once PaymentTerm has been resolved. An empty term →
days from the setting. On the form this is a DefaultPaymentTerm reference to
the PaymentTerm dictionary; saving the settings stamps
DefaultPaymentTermDays. An empty reference does not clear the number (partial
UPDATE and tests that write the days directly). Loading with an empty reference
and days greater than zero substitutes a term with the same day count.
A term that is filled in with Days = 0 puts the due date on the document
date, and the setting is not mixed in.
A partial UPDATE of an invoice (a subtype change, a due date set from outside)
reaches the typed handler as the whole invoice: the written columns over the
stored row (see Document save).
So the stamp sees the chosen PaymentTerm and the stored date and keeps them.
MergeStoredHeaderAsync in Sales is unused: the platform already hydrates the
whole record.
InvoiceZr appends the date to the term's name. OrderZr does not.
Tests PaymentDueDateTest, PurchaseDueDateTest.
Stamping DueDate on every save is a header edit. On a read-only subtype the
stamp must be echoed back to the caller, or the next save is no longer a
transition-only write — see
Document save and read-only subtypes.
Same topic for other readers: Analyst · User