Module: Declaration232

Defined in:
app/services/declaration232.rb

Overview

Section 232 steel/aluminum/copper declaration ("232 SAD") for CAN→USA
cross-border deliveries, built line-for-line from the same scope the
commercial invoice renders (line_items.parents_only.goods) so the broker
can match declaration lines to invoice lines — the mismatch Willson rejected
on ST728704 (2026-07-21) is structurally impossible when both documents read
the same rows.

Two artifacts are generated per delivery, mirroring what operations submits
by hand today:

  • XlsmWriter fills the broker's macro-enabled template
    (data/excel/declaration_232_willson.xlsm, "Revised - 06/12/2026").
  • Pdf::Document::Declaration232 renders the same rows as a printable PDF
    folded into the delivery's combined international forms packet.

Per the template's own instructions, every invoice line becomes a pair of
rows: NON-STEEL CONTENT (the non-steel share of the line value) and STEEL
CONTENT (the steel share). Steel shares come from the per-item fields
steel_content_value_ratio / steel_content_weight_kg /
steel_melt_pour_coo, which default to zero/blank — matching the
zero-steel declarations the broker has accepted for our product range.

Defined Under Namespace

Classes: Line, XlsmWriter

Constant Summary collapse

TEMPLATE_PATH =
Rails.root.join('data/excel/declaration_232_willson.xlsm')
LB_TO_KG =
0.45359237
PREPARER =

ponytail: static preparer block, matches what ops submits today; make it a
Setting if the certifying manager ever changes.

{
  name: 'Venu Adepu',
  title: 'Accounting Manager',
  phone: '800-875-5285',
  email: 'vadepu@warmlyyours.com'
}.freeze

Class Method Summary collapse

Class Method Details

.lines(delivery) ⇒ Array<Line>

Returns one per parent goods line item, in commercial-invoice order.

Parameters:

Returns:

  • (Array<Line>)

    one per parent goods line item, in commercial-invoice order



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'app/services/declaration232.rb', line 54

def self.lines(delivery)
  delivery.line_items.parents_only.goods.each_with_index.map do |li, i|
    item = li.item
    value = (li.quantity * li.unit_value_for_commercial_invoice.to_f).round(2)
    steel_ratio = item.steel_content_value_ratio.to_f
    steel_weight = (li.quantity * item.steel_content_weight_kg.to_f).round(2)
    Line.new(
      ln: i + 1,
      description: "#{li.name} / SKU: #{li.sku}",
      hts: item.harmonization_code,
      coo: item.coo.presence || 'CN',
      value: value,
      weight_kg: (li.quantity * item.shipping_weight.to_f * LB_TO_KG).round(2),
      steel_value: (value * steel_ratio).round(2),
      steel_weight_kg: steel_weight,
      steel_melt_pour: steel_ratio.positive? || steel_weight.positive? ? (item.steel_melt_pour_coo.presence || item.coo) : nil
    )
  end
end

.rows(delivery) ⇒ Array<Hash>

Returns flattened row pairs for both writers.

Returns:

  • (Array<Hash>)

    flattened row pairs for both writers



75
76
77
# File 'app/services/declaration232.rb', line 75

def self.rows(delivery)
  lines(delivery).flat_map(&:rows)
end