Class: Ksef::FA3::AttachmentTable

Inherits:
Data
  • Object
show all
Includes:
Canonical
Defined in:
lib/ksef/fa3/attachment_table.rb,
lib/ksef/fa3/attachment_table.rb

Overview

Construction, invariants and serialisation for AttachmentTable.

Constant Summary collapse

NEEDS_COLUMNS =
"An attachment table needs at least one column. `Kol` is minOccurs=1 " \
"within `TNaglowek`, which is itself mandatory within `Tabela`."
NEEDS_ROWS =
"An attachment table needs at least one row. `Wiersz` is minOccurs=1 " \
"within `Tabela`."
EMPTY_ROW =
"An attachment table row needs at least one cell. `WKom` is minOccurs=1 " \
"within `Wiersz` — a cell may be *empty*, but a row may not have none."

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Canonical

#with

Constructor Details

#initialize(columns:, rows:, caption: nil, metadata: [], totals: nil) ⇒ AttachmentTable

Returns a new instance of AttachmentTable.

Parameters:

  • columns (TableColumn, Array<TableColumn>) —

    TNaglowek/Kol, 1..20

  • rows (Array<Array<String>>) —

    Wiersz/WKom; each row 1..20 cells, ragged

  • caption (String, nil) (defaults to: nil) —

    Opis, TZnakowy512

  • metadata (Hash, Array<MetaEntry>) (defaults to: []) —

    TMetaDane, 0..1000

  • totals (Array<String>, nil) (defaults to: nil) —

    Suma/SKom, a summary row

Raises:



42
43
44
45
46
47
48
# File 'lib/ksef/fa3/attachment_table.rb', line 42

def initialize(columns:, rows:, caption: nil, metadata: [], totals: nil)
  heads = Correction.wrap(columns)
  cells = self.class.rows_from(rows)
  self.class.check!(heads, cells)

  super(**self.class.canonical(heads, cells, caption, , totals))
end

Instance Attribute Details

#caption ⇒ Object (readonly)

Returns the value of attribute caption

Returns:

  • (Object) —

    the current value of caption



22
23
24
# File 'lib/ksef/fa3/attachment_table.rb', line 22

def caption
  @caption
end

#columns ⇒ Object (readonly)

Returns the value of attribute columns

Returns:

  • (Object) —

    the current value of columns



22
23
24
# File 'lib/ksef/fa3/attachment_table.rb', line 22

def columns
  @columns
end

#metadata ⇒ Object (readonly)

Returns the value of attribute metadata

Returns:

  • (Object) —

    the current value of metadata



22
23
24
# File 'lib/ksef/fa3/attachment_table.rb', line 22

def 
  @metadata
end

#rows ⇒ Object (readonly)

Returns the value of attribute rows

Returns:

  • (Object) —

    the current value of rows



22
23
24
# File 'lib/ksef/fa3/attachment_table.rb', line 22

def rows
  @rows
end

#totals ⇒ Object (readonly)

Returns the value of attribute totals

Returns:

  • (Object) —

    the current value of totals



22
23
24
# File 'lib/ksef/fa3/attachment_table.rb', line 22

def totals
  @totals
end

Class Method Details

.canonical(columns, rows, caption, metadata, totals) ⇒ Object



50
51
52
53
54
55
56
57
58
# File 'lib/ksef/fa3/attachment_table.rb', line 50

def self.canonical(columns, rows, caption, , totals)
  {
    columns: columns.dup.freeze,
    rows: rows.map { |row| cells(row) }.freeze,
    caption: Formatting.text(caption),
    metadata: DataBlock.entries().dup.freeze,
    totals: totals.nil? ? nil : cells(totals)
  }
end

.cells(row) ⇒ Object

to_s, not Formatting.text's nil. A cell that is absent and one that is empty are the same thing to TZnakowy2, so nil is normalised on the way in — and it has to be, because a nil that survives breaks §7.6: it serialises as an empty WKom (through nil.to_s) and parses back as "", so the invoice stops equalling itself. An earlier version of this comment said a nil cell "would shorten the row"; measured 2026-08-26, that is not what happens.



85
# File 'lib/ksef/fa3/attachment_table.rb', line 85

def self.cells(row) = Array(row).map { |cell| Formatting.text(cell).to_s }.freeze

.check!(columns, rows) ⇒ Object

Every one of these is a document the XSD rejects, so the useful moment to say so is construction rather than serialisation.

Raises:



62
63
64
65
66
# File 'lib/ksef/fa3/attachment_table.rb', line 62

def self.check!(columns, rows)
  raise ValidationError, NEEDS_COLUMNS if columns.empty?
  raise ValidationError, NEEDS_ROWS if rows.empty?
  raise ValidationError, EMPTY_ROW if rows.any?(&:empty?)
end

.rows_from(rows) ⇒ Object

A single row may be passed flat — rows: %w[a b] — because a one-row table is common enough that wrapping it twice is noise. An empty list stays empty rather than becoming one empty row, which is what the first version did: [].first is not an Array, so it took the flat branch and manufactured a Wiersz with no cells.



72
73
74
75
76
77
# File 'lib/ksef/fa3/attachment_table.rb', line 72

def self.rows_from(rows)
  list = Array(rows)
  return [] if list.empty?

  list.first.is_a?(Array) ? list : [list]
end

Instance Method Details

#to_fa3 ⇒ Object



87
88
89
90
91
92
93
94
95
# File 'lib/ksef/fa3/attachment_table.rb', line 87

def to_fa3
  {
    "TMetaDane" => .map { |e| e.to_fa3(key_element: "TKlucz", value_element: "TWartosc") },
    "Opis" => caption,
    "TNaglowek" => { "Kol" => columns.map(&:to_fa3) },
    "Wiersz" => rows.map { |row| { "WKom" => row } },
    "Suma" => totals.nil? ? nil : { "SKom" => totals }
  }.compact
end