Module: Ksef::FA3::SummaryChecks
Overview
Tier 1a's checks on Totals — the summary an invoice states rather than derives.
Its own module because the rule spans two families that share nothing else. A correction states its summary because the buckets are deltas its rows need not determine (§8.4); an advance or settlement invoice states one because the rows describe the goods while the buckets describe money this document does not contain enough to compute (§8.5).
Both directions are checked, and the second is why this module exists
Set where it does not belong: emitted verbatim, never read back, and free to contradict the rows with nothing to notice.
Absent where it is needed: the summary falls through to DocumentMapping's
line-derived buckets. That fallback shipped once — a KOR built without stated totals
counted its StanPrzed rows as sales and emitted a refund as a charge, XSD-valid and
tier 1 silent (§8.4b). The rule below is what closed it, generalised as the family grew.
Constant Summary collapse
- DERIVATION_BLOCKERS =
The three constructs that mean "the rows do not determine the summary". Each is structural — an element the document either carries or does not — rather than a judgement about the arithmetic, which is tier 3's and is not built.
{ "a line is marked state_before" => ->(invoice) { invoice.lines.any? { |line| line.is_a?(Line) && line.state_before } }, "an order is stated" => ->(invoice) { !invoice.order.nil? }, "an advance invoice is settled" => ->(invoice) { !invoice.advances.empty? } }.freeze
Constants included from FieldChecks
FieldChecks::BUYER_ID_TEXT, FieldChecks::COLLAPSE, FieldChecks::FORBIDDEN_IN_XML, FieldChecks::LONG_TEXT, FieldChecks::SHORT_TEXT