Class: Secretariat::LineItem
- Inherits:
-
Struct
- Object
- Struct
- Secretariat::LineItem
- Includes:
- Versioner
- Defined in:
- lib/secretariat/line_item.rb
Instance Attribute Summary collapse
-
#basis_quantity ⇒ Object
Returns the value of attribute basis_quantity.
-
#billed_quantity ⇒ Object
Returns the value of attribute billed_quantity.
-
#charge_amount ⇒ Object
Returns the value of attribute charge_amount.
-
#currency_code ⇒ Object
Returns the value of attribute currency_code.
-
#discount_amount ⇒ Object
Returns the value of attribute discount_amount.
-
#discount_reason ⇒ Object
Returns the value of attribute discount_reason.
-
#gross_amount ⇒ Object
Returns the value of attribute gross_amount.
-
#name ⇒ Object
Returns the value of attribute name.
-
#net_amount ⇒ Object
Returns the value of attribute net_amount.
-
#origin_country_code ⇒ Object
Returns the value of attribute origin_country_code.
-
#service_period_end ⇒ Object
Returns the value of attribute service_period_end.
-
#service_period_start ⇒ Object
Returns the value of attribute service_period_start.
-
#tax_amount ⇒ Object
Returns the value of attribute tax_amount.
-
#tax_category ⇒ Object
Returns the value of attribute tax_category.
-
#tax_percent ⇒ Object
Returns the value of attribute tax_percent.
-
#unit ⇒ Object
Returns the value of attribute unit.
Instance Method Summary collapse
-
#effective_basis_quantity ⇒ Object
If not provided, BasisQuantity should be 1.0 (price per 1 unit).
- #errors ⇒ Object
-
#initialize(**kwargs) ⇒ LineItem
constructor
A new instance of LineItem.
- #quantity ⇒ Object
- #quantity=(val) ⇒ Object
- #tax_category_code(version: 2) ⇒ Object
- #to_xml(xml, line_item_index, version: 2, validate: true) ⇒ Object
- #unit_code ⇒ Object
- #untaxable? ⇒ Boolean
- #valid? ⇒ Boolean
- #warn_once_quantity ⇒ Object
Methods included from Versioner
Constructor Details
#initialize(**kwargs) ⇒ LineItem
43 44 45 46 47 48 |
# File 'lib/secretariat/line_item.rb', line 43 def initialize(**kwargs) if kwargs.key?(:quantity) && !kwargs.key?(:billed_quantity) kwargs[:billed_quantity] = kwargs.delete(:quantity) end super(**kwargs) end |
Instance Attribute Details
#basis_quantity ⇒ Object
Returns the value of attribute basis_quantity
21 22 23 |
# File 'lib/secretariat/line_item.rb', line 21 def basis_quantity @basis_quantity end |
#billed_quantity ⇒ Object
Returns the value of attribute billed_quantity
21 22 23 |
# File 'lib/secretariat/line_item.rb', line 21 def billed_quantity @billed_quantity end |
#charge_amount ⇒ Object
Returns the value of attribute charge_amount
21 22 23 |
# File 'lib/secretariat/line_item.rb', line 21 def charge_amount @charge_amount end |
#currency_code ⇒ Object
Returns the value of attribute currency_code
21 22 23 |
# File 'lib/secretariat/line_item.rb', line 21 def currency_code @currency_code end |
#discount_amount ⇒ Object
Returns the value of attribute discount_amount
21 22 23 |
# File 'lib/secretariat/line_item.rb', line 21 def discount_amount @discount_amount end |
#discount_reason ⇒ Object
Returns the value of attribute discount_reason
21 22 23 |
# File 'lib/secretariat/line_item.rb', line 21 def discount_reason @discount_reason end |
#gross_amount ⇒ Object
Returns the value of attribute gross_amount
21 22 23 |
# File 'lib/secretariat/line_item.rb', line 21 def gross_amount @gross_amount end |
#name ⇒ Object
Returns the value of attribute name
21 22 23 |
# File 'lib/secretariat/line_item.rb', line 21 def name @name end |
#net_amount ⇒ Object
Returns the value of attribute net_amount
21 22 23 |
# File 'lib/secretariat/line_item.rb', line 21 def net_amount @net_amount end |
#origin_country_code ⇒ Object
Returns the value of attribute origin_country_code
21 22 23 |
# File 'lib/secretariat/line_item.rb', line 21 def origin_country_code @origin_country_code end |
#service_period_end ⇒ Object
Returns the value of attribute service_period_end
21 22 23 |
# File 'lib/secretariat/line_item.rb', line 21 def service_period_end @service_period_end end |
#service_period_start ⇒ Object
Returns the value of attribute service_period_start
21 22 23 |
# File 'lib/secretariat/line_item.rb', line 21 def service_period_start @service_period_start end |
#tax_amount ⇒ Object
Returns the value of attribute tax_amount
21 22 23 |
# File 'lib/secretariat/line_item.rb', line 21 def tax_amount @tax_amount end |
#tax_category ⇒ Object
Returns the value of attribute tax_category
21 22 23 |
# File 'lib/secretariat/line_item.rb', line 21 def tax_category @tax_category end |
#tax_percent ⇒ Object
Returns the value of attribute tax_percent
21 22 23 |
# File 'lib/secretariat/line_item.rb', line 21 def tax_percent @tax_percent end |
#unit ⇒ Object
Returns the value of attribute unit
21 22 23 |
# File 'lib/secretariat/line_item.rb', line 21 def unit @unit end |
Instance Method Details
#effective_basis_quantity ⇒ Object
If not provided, BasisQuantity should be 1.0 (price per 1 unit)
109 110 111 112 113 |
# File 'lib/secretariat/line_item.rb', line 109 def effective_basis_quantity q = basis_quantity.nil? ? BigDecimal("1.0") : BigDecimal(basis_quantity.to_s) raise ArgumentError, "basis_quantity must be > 0" if q <= 0 q end |
#errors ⇒ Object
67 68 69 |
# File 'lib/secretariat/line_item.rb', line 67 def errors @errors end |
#quantity ⇒ Object
50 51 52 53 |
# File 'lib/secretariat/line_item.rb', line 50 def quantity warn_once_quantity billed_quantity end |
#quantity=(val) ⇒ Object
55 56 57 58 |
# File 'lib/secretariat/line_item.rb', line 55 def quantity=(val) warn_once_quantity self.billed_quantity = val end |
#tax_category_code(version: 2) ⇒ Object
115 116 117 118 119 120 |
# File 'lib/secretariat/line_item.rb', line 115 def tax_category_code(version: 2) if version == 1 return TAX_CATEGORY_CODES_1[tax_category] || 'S' end TAX_CATEGORY_CODES[tax_category] || 'S' end |
#to_xml(xml, line_item_index, version: 2, validate: true) ⇒ Object
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 |
# File 'lib/secretariat/line_item.rb', line 126 def to_xml(xml, line_item_index, version: 2, validate: true) net_price = net_amount && BigDecimal(net_amount) gross_price = gross_amount && BigDecimal(gross_amount) charge_price = charge_amount && BigDecimal(charge_amount) self.tax_percent ||= BigDecimal(0) if net_price&.zero? self.tax_percent = 0 end if net_price&.negative? # Zugferd doesn't allow negative amounts at the item level. # Instead, a negative quantity is used. self.billed_quantity = -billed_quantity self.gross_amount = gross_price&.abs self.net_amount = net_price&.abs self.charge_amount = charge_price&.abs end if validate && !valid? raise ValidationError.new("LineItem #{line_item_index} is invalid", errors) end xml['ram'].IncludedSupplyChainTradeLineItem do xml['ram'].AssociatedDocumentLineDocument do xml['ram'].LineID line_item_index end if (version == 2) xml['ram'].SpecifiedTradeProduct do xml['ram'].Name name xml['ram'].OriginTradeCountry do xml['ram'].ID origin_country_code end end end agreement = by_version(version, 'SpecifiedSupplyChainTradeAgreement', 'SpecifiedLineTradeAgreement') xml['ram'].send(agreement) do xml['ram'].GrossPriceProductTradePrice do Helpers.currency_element(xml, 'ram', 'ChargeAmount', gross_amount, currency_code, add_currency: version == 1, digits: 4) if version == 2 && discount_amount xml['ram'].BasisQuantity(unitCode: unit_code) do xml.text(Helpers.format(effective_basis_quantity, digits: 4)) end xml['ram'].AppliedTradeAllowanceCharge do xml['ram'].ChargeIndicator do xml['udt'].Indicator 'false' end Helpers.currency_element(xml, 'ram', 'ActualAmount', discount_amount, currency_code, add_currency: version == 1) xml['ram'].Reason discount_reason end end if version == 1 && discount_amount xml['ram'].AppliedTradeAllowanceCharge do xml['ram'].ChargeIndicator do xml['udt'].Indicator 'false' end Helpers.currency_element(xml, 'ram', 'ActualAmount', discount_amount, currency_code, add_currency: version == 1) xml['ram'].Reason discount_reason end end end xml['ram'].NetPriceProductTradePrice do Helpers.currency_element(xml, 'ram', 'ChargeAmount', net_amount, currency_code, add_currency: version == 1, digits: 4) if version == 2 xml['ram'].BasisQuantity(unitCode: unit_code) do xml.text(Helpers.format(effective_basis_quantity, digits: 4)) end end end end delivery = by_version(version, 'SpecifiedSupplyChainTradeDelivery', 'SpecifiedLineTradeDelivery') xml['ram'].send(delivery) do xml['ram'].BilledQuantity(unitCode: unit_code) do xml.text(Helpers.format(billed_quantity, digits: 4)) end end settlement = by_version(version, 'SpecifiedSupplyChainTradeSettlement', 'SpecifiedLineTradeSettlement') xml['ram'].send(settlement) do xml['ram'].ApplicableTradeTax do xml['ram'].TypeCode 'VAT' xml['ram'].CategoryCode tax_category_code(version: version) unless untaxable? percent = by_version(version, 'ApplicablePercent', 'RateApplicablePercent') xml['ram'].send(percent,Helpers.format(tax_percent)) end end if version == 2 && self.service_period_start && self.service_period_end xml['ram'].BillingSpecifiedPeriod do xml['ram'].StartDateTime do xml['udt'].DateTimeString(format: '102') do xml.text(service_period_start.strftime("%Y%m%d")) end end xml['ram'].EndDateTime do xml['udt'].DateTimeString(format: '102') do xml.text(service_period_end.strftime("%Y%m%d")) end end end end monetary_summation = by_version(version, 'SpecifiedTradeSettlementMonetarySummation', 'SpecifiedTradeSettlementLineMonetarySummation') xml['ram'].send(monetary_summation) do Helpers.currency_element(xml, 'ram', 'LineTotalAmount', (billed_quantity.negative? ? -charge_amount : charge_amount), currency_code, add_currency: version == 1) end end if version == 1 xml['ram'].SpecifiedTradeProduct do xml['ram'].Name name end end end end |
#unit_code ⇒ Object
104 105 106 |
# File 'lib/secretariat/line_item.rb', line 104 def unit_code UNIT_CODES[unit] || 'C62' end |
#untaxable? ⇒ Boolean
122 123 124 |
# File 'lib/secretariat/line_item.rb', line 122 def untaxable? tax_category == :UNTAXEDSERVICE end |
#valid? ⇒ Boolean
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/secretariat/line_item.rb', line 71 def valid? @errors = [] net_price = BigDecimal(net_amount) gross_price = BigDecimal(gross_amount) charge_price = BigDecimal(charge_amount) tax = BigDecimal(tax_amount) unit_price = net_price * BigDecimal(billed_quantity.abs) if charge_price != unit_price @errors << "charge price and gross price times quantity deviate: #{charge_price} / #{unit_price}" return false end if discount_amount discount = BigDecimal(discount_amount) calculated_net_price = (gross_price - discount).round(2, :down) if calculated_net_price != net_price @errors = "Calculated net price and net price deviate: #{calculated_net_price} / #{net_price}" return false end end if tax_category != :UNTAXEDSERVICE self.tax_percent ||= BigDecimal(0) calculated_tax = charge_price * BigDecimal(tax_percent) / BigDecimal(100) calculated_tax = calculated_tax.round(2) calculated_tax = -calculated_tax if billed_quantity.negative? if calculated_tax != tax @errors << "Tax and calculated tax deviate: #{tax} / #{calculated_tax}" return false end end return true end |
#warn_once_quantity ⇒ Object
60 61 62 63 64 65 |
# File 'lib/secretariat/line_item.rb', line 60 def warn_once_quantity unless @__warned_quantity Kernel.warn("[secretariat] LineItem#quantity is deprecated; use #billed_quantity") @__warned_quantity = true end end |