Class: Ksef::FA3::Correction
- Inherits:
-
Data
- Object
- Data
- Ksef::FA3::Correction
- Includes:
- Canonical
- Defined in:
- lib/ksef/fa3/correction.rb,
lib/ksef/fa3/correction.rb
Overview
Construction, canonicalisation and serialisation for Correction.
Constant Summary collapse
- CORRECTING_TYPES =
The
RodzajFakturyvalues these elements belong to — stated by the XSD itself, in the annotation on the anonymous sequence that holds them: "Dane dla przypadków, gdy pole RodzajFaktury przyjmuje wartości KOR, KOR_ZAL lub KOR_ROZ".What the schema cannot do is enforce it: the group sits in the same sequence whatever the type, so a
VATinvoice carryingDaneFaKorygowanejvalidates clean. That gap is tier 1's, and ModelValidator fills it (docs/REFERENCE.md §8.4). %w[KOR KOR_ZAL KOR_ROZ].freeze
- NAMES_NOTHING =
"A correction must name at least one corrected invoice. " \ "`DaneFaKorygowanej` is mandatory once any correction element is " \ "present, so a correction without one cannot be serialised."
Instance Attribute Summary collapse
-
#corrected ⇒ Object
readonly
Returns the value of attribute corrected.
-
#corrected_number ⇒ Object
readonly
Returns the value of attribute corrected_number.
-
#effect ⇒ Object
readonly
Returns the value of attribute effect.
-
#exchange_rate_before ⇒ Object
readonly
Returns the value of attribute exchange_rate_before.
-
#paid_before ⇒ Object
readonly
Returns the value of attribute paid_before.
-
#period ⇒ Object
readonly
Returns the value of attribute period.
-
#previous_buyers ⇒ Object
readonly
Returns the value of attribute previous_buyers.
-
#previous_seller ⇒ Object
readonly
Returns the value of attribute previous_seller.
-
#reason ⇒ Object
readonly
Returns the value of attribute reason.
Class Method Summary collapse
-
.canonical_amounts(paid_before, exchange_rate_before) ⇒ Object
P_15ZKisTKwotowy, so two places;KursWalutyZKisTIlosci, so six. -
.canonical_fields(reason, period, corrected_number, effect) ⇒ Object
TypKorektyrestrictsxsd:integer, whose value space is integers — so"03"and3denote the same thing and the model stores the value, not the lexical form (§8.2b). -
.scaled_rate(value) ⇒ Object
TIlosciagain, so Formatting::QUANTITY_SCALE — a rate is not an amount, but it is not unbounded either. -
.wrap(value) ⇒ Object
Array()is not usable here: it splats a Hash into an array of pairs, soCorrection.new(corrected: { number: ..., issue_date: ... })— a natural mistake — was accepted and then made#to_xmlraiseNoMethodErroron an Array.
Instance Method Summary collapse
-
#initialize(corrected:, reason: nil, effect: nil, period: nil, corrected_number: nil, previous_seller: nil, previous_buyers: [], paid_before: nil, exchange_rate_before: nil) ⇒ Correction
constructor
A new instance of Correction.
- #to_fa3 ⇒ Object
Methods included from Canonical
Constructor Details
#initialize(corrected:, reason: nil, effect: nil, period: nil, corrected_number: nil, previous_seller: nil, previous_buyers: [], paid_before: nil, exchange_rate_before: nil) ⇒ Correction
Returns a new instance of Correction.
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/ksef/fa3/correction.rb', line 65 def initialize(corrected:, reason: nil, effect: nil, period: nil, corrected_number: nil, previous_seller: nil, previous_buyers: [], paid_before: nil, exchange_rate_before: nil) entries = self.class.wrap(corrected) raise ValidationError, NAMES_NOTHING if entries.empty? # `dup` before freezing: `Array(x)` returns `x` itself when it is already an Array, so # freezing in place froze the *caller's* array and made their next `<<` raise. super( previous_seller: previous_seller, corrected: entries.dup.freeze, previous_buyers: self.class.wrap(previous_buyers).dup.freeze, **self.class.canonical_fields(reason, period, corrected_number, effect), **self.class.canonical_amounts(paid_before, exchange_rate_before) ) end |
Instance Attribute Details
#corrected ⇒ Object (readonly)
Returns the value of attribute corrected
25 26 27 |
# File 'lib/ksef/fa3/correction.rb', line 25 def corrected @corrected end |
#corrected_number ⇒ Object (readonly)
Returns the value of attribute corrected_number
25 26 27 |
# File 'lib/ksef/fa3/correction.rb', line 25 def corrected_number @corrected_number end |
#effect ⇒ Object (readonly)
Returns the value of attribute effect
25 26 27 |
# File 'lib/ksef/fa3/correction.rb', line 25 def effect @effect end |
#exchange_rate_before ⇒ Object (readonly)
Returns the value of attribute exchange_rate_before
25 26 27 |
# File 'lib/ksef/fa3/correction.rb', line 25 def exchange_rate_before @exchange_rate_before end |
#paid_before ⇒ Object (readonly)
Returns the value of attribute paid_before
25 26 27 |
# File 'lib/ksef/fa3/correction.rb', line 25 def paid_before @paid_before end |
#period ⇒ Object (readonly)
Returns the value of attribute period
25 26 27 |
# File 'lib/ksef/fa3/correction.rb', line 25 def period @period end |
#previous_buyers ⇒ Object (readonly)
Returns the value of attribute previous_buyers
25 26 27 |
# File 'lib/ksef/fa3/correction.rb', line 25 def previous_buyers @previous_buyers end |
#previous_seller ⇒ Object (readonly)
Returns the value of attribute previous_seller
25 26 27 |
# File 'lib/ksef/fa3/correction.rb', line 25 def previous_seller @previous_seller end |
#reason ⇒ Object (readonly)
Returns the value of attribute reason
25 26 27 |
# File 'lib/ksef/fa3/correction.rb', line 25 def reason @reason end |
Class Method Details
.canonical_amounts(paid_before, exchange_rate_before) ⇒ Object
P_15ZK is TKwotowy, so two places; KursWalutyZK is TIlosci, so six. Six is a
ceiling, not a preference — a seven-place rate is not a value FA(3) can express,
and #to_fa3 rounds it away at emit. Storing it unrounded made the model hold a figure
the document cannot carry, which is §8.2b's rule broken in the one place the rest of
the model keeps it: a Correction built with 4.12345678 emitted 4.123457 and then
failed DESIGN.md §7.6's round-trip law against itself.
100 101 102 103 104 105 |
# File 'lib/ksef/fa3/correction.rb', line 100 def self.canonical_amounts(paid_before, exchange_rate_before) { paid_before: paid_before && Formatting.decimal(paid_before).round(Formatting::AMOUNT_SCALE), exchange_rate_before: exchange_rate_before && scaled_rate(exchange_rate_before) } end |
.canonical_fields(reason, period, corrected_number, effect) ⇒ Object
TypKorekty restricts xsd:integer, whose value space is integers — so "03" and 3
denote the same thing and the model stores the value, not the lexical form (§8.2b).
Contrast Line#vat_rate, a token whose value space is strings.
85 86 87 88 89 90 91 92 |
# File 'lib/ksef/fa3/correction.rb', line 85 def self.canonical_fields(reason, period, corrected_number, effect) { reason: Formatting.text(reason), period: Formatting.text(period), corrected_number: Formatting.text(corrected_number), effect: effect.nil? ? nil : Formatting.integer(effect) } end |
.scaled_rate(value) ⇒ Object
TIlosci again, so Formatting::QUANTITY_SCALE — a rate is not an amount, but it is
not unbounded either.
109 |
# File 'lib/ksef/fa3/correction.rb', line 109 def self.scaled_rate(value) = Formatting.decimal(value).round(Formatting::QUANTITY_SCALE) |
.wrap(value) ⇒ Object
Array() is not usable here: it splats a Hash into an array of pairs, so
Correction.new(corrected: { number: ..., issue_date: ... }) — a natural mistake —
was accepted and then made #to_xml raise NoMethodError on an Array.
114 115 116 117 118 |
# File 'lib/ksef/fa3/correction.rb', line 114 def self.wrap(value) return [] if value.nil? value.is_a?(Array) ? value : [value] end |
Instance Method Details
#to_fa3 ⇒ Object
120 121 122 123 124 125 126 127 128 |
# File 'lib/ksef/fa3/correction.rb', line 120 def to_fa3 { "PrzyczynaKorekty" => reason, "TypKorekty" => effect&.to_s, "DaneFaKorygowanej" => corrected.map(&:to_fa3), "OkresFaKorygowanej" => period, "NrFaKorygowany" => corrected_number }.merge(parties).merge(amounts).compact end |