sunat_invoice 0.0.1 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -0
  3. data/README.mkd +1 -25
  4. data/lib/sunat_invoice/client.rb +3 -6
  5. data/lib/sunat_invoice/clients/consult_client.rb +17 -0
  6. data/lib/sunat_invoice/clients/invoice_client.rb +11 -3
  7. data/lib/sunat_invoice/configuration.rb +1 -1
  8. data/lib/sunat_invoice/credit_note.rb +59 -0
  9. data/lib/sunat_invoice/credit_note_line.rb +15 -0
  10. data/lib/sunat_invoice/customer.rb +1 -0
  11. data/lib/sunat_invoice/daily_summary.rb +46 -0
  12. data/lib/sunat_invoice/debit_note.rb +33 -0
  13. data/lib/sunat_invoice/debit_note_line.rb +15 -0
  14. data/lib/sunat_invoice/invoice.rb +23 -144
  15. data/lib/sunat_invoice/item.rb +40 -26
  16. data/lib/sunat_invoice/line.rb +18 -0
  17. data/lib/sunat_invoice/provider.rb +20 -14
  18. data/lib/sunat_invoice/response_parser.rb +64 -0
  19. data/lib/sunat_invoice/signature.rb +29 -15
  20. data/lib/sunat_invoice/summary_line.rb +75 -0
  21. data/lib/sunat_invoice/tax.rb +6 -1
  22. data/lib/sunat_invoice/trade_calculations.rb +68 -0
  23. data/lib/sunat_invoice/trade_document.rb +85 -0
  24. data/lib/sunat_invoice/utils.rb +48 -9
  25. data/lib/sunat_invoice/voided.rb +22 -0
  26. data/lib/sunat_invoice/voided_line.rb +20 -0
  27. data/lib/sunat_invoice/xml_document.rb +52 -0
  28. data/lib/sunat_invoice.rb +14 -0
  29. data/sunat_invoice.gemspec +5 -5
  30. data/test/credit_note_test.rb +15 -0
  31. data/test/daily_summary_test.rb +35 -0
  32. data/test/debit_note_test.rb +15 -0
  33. data/test/factories.rb +70 -0
  34. data/test/fixtures/responses/invoice_success.xml +2 -0
  35. data/test/fixtures/responses/summary_success.xml +2 -0
  36. data/test/fixtures/responses/ticket_invalid.xml +2 -0
  37. data/test/helper.rb +1 -0
  38. data/test/invoice_client_test.rb +68 -16
  39. data/test/invoice_test.rb +19 -10
  40. data/test/item_test.rb +3 -2
  41. data/test/response_parser_test.rb +28 -0
  42. data/test/support/response_helper.rb +18 -0
  43. data/test/support/signature_helper.rb +15 -8
  44. metadata +34 -13
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b49429704d8a0fd453f1210ee274c0b111dbb96e
4
- data.tar.gz: ecae8df2666c3e508abea79a594c375b12b03153
3
+ metadata.gz: c15a897331d06af16937c9bf1020984592bcd0f3
4
+ data.tar.gz: 51cc6c5c299e0d2209a32ccc51be2158b7a4e780
5
5
  SHA512:
6
- metadata.gz: 83d17d8b14f0bfb1bcbdea6e449346d7ac0b819859d434695f93ba306e8f979f0885683454fd655d1bfb54f4ee9f60cbe16e0266e429b1507df75d6745365d82
7
- data.tar.gz: c1992a23ae4817da9539e980bc3ee745335d70b802d1a18a32793eee7c6918140af4915ae84cd72c6e30a7b8edb2077808f656f596c0e8b4446cdf3eba362865
6
+ metadata.gz: a5866087a7d0c40c4c88ad32ee94812d7e3dbd75892968ca39df00aa501fcdb9167a0ba06b60c3c38d0095b51c631d6de51055e01dfee4f4db029c473bac4b91
7
+ data.tar.gz: 20781a7b8110190a887a7c9740fbfebb4a8fd55893953a07fc12c8da05f549d1fae2630b301bc98329db94dc39c2ca23f2ce017541409774013d034c4626062e
data/Gemfile CHANGED
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  source 'https://rubygems.org'
3
4
 
4
5
  gemspec
data/README.mkd CHANGED
@@ -1,26 +1,2 @@
1
1
  # Sunat Invoice
2
- Ruby wrapper to use SUNAT Electronic Invoice API
3
-
4
- homologacion
5
- https://www.sunat.gob.pe/ol-ti-itcpgem-sqa/billService?wsdl
6
-
7
- valid_service
8
-
9
- http://www.sunat.gob.pe/ol-ti-itconsvalicpe/ConsValiCpe.htm
10
-
11
- {:validaCDPcriterios=>{:rucEmisor=>"string", :tipoCDP=>"string", :serieCDP=>"string", :numeroCDP=>"string", :tipoDocIdReceptor=>"string", :numeroDocIdReceptor=>"string", :fechaEmision=>"string", :importeTotal=>"double", :nroAutorizacion=>"string"}}
12
-
13
- http://www.sunat.gob.pe/ol-ti-itconsverixml/ConsVeriXml.htm
14
-
15
- {:verificaCPEarchivo=>{:nombre=>"string", :archivo=>"string"}}
16
-
17
- errors
18
- https://www.facturacionperu.ws/?p=138
19
-
20
-
21
- To write:
22
- https://www.xml.com/pub/a/2001/08/08/xmldsig.html
23
- https://www.di-mgt.com.au/xmldsig.html
24
-
25
- https://github.com/ebeigarts/signer
26
- https://github.com/benoist/xmldsig
2
+ Ruby gem to use [SUNAT Electronic Billing](http://cpe.sunat.gob.pe/factura-desde-los-sistemas-del-contribuyente) from your app
@@ -5,15 +5,12 @@ require 'savon'
5
5
 
6
6
  module SunatInvoice
7
7
  class Client
8
- def initialize(env = 'dev')
8
+ def initialize(env = 'dev', log = false)
9
9
  @env = env
10
+ @log = log
10
11
  @soap_client = savon_client
11
12
  end
12
13
 
13
- def log
14
- (@env != 'prod')
15
- end
16
-
17
14
  private
18
15
 
19
16
  def config
@@ -30,7 +27,7 @@ module SunatInvoice
30
27
  Savon.client(wsdl: wsdl,
31
28
  wsse_auth: authentication,
32
29
  namespace: 'http://service.sunat.gob.pe',
33
- log: log)
30
+ log: @log)
34
31
  end
35
32
  end
36
33
  end
@@ -7,5 +7,22 @@ module SunatInvoice
7
7
  def wsdl
8
8
  'https://www.sunat.gob.pe/ol-it-wsconscpegem/billConsultService?wsdl'
9
9
  end
10
+
11
+ def get_status(ticket)
12
+ @soap_client.call(:get_status, message: { ticket: ticket })
13
+ end
14
+
15
+ def get_status_cdr(options = {})
16
+ # Available document_type to use:
17
+ # 01: Factura.
18
+ # 07: Nota de crédito.
19
+ # 08: Nota de débito
20
+ @soap_client.call(:get_status, message: {
21
+ rucComprobante: options[:ruc],
22
+ tipoComprobante: options[:document_type],
23
+ serieComprobante: options[:document_serial],
24
+ numeroComprobante: options[:document_number]
25
+ })
26
+ end
10
27
  end
11
28
  end
@@ -25,12 +25,20 @@ module SunatInvoice
25
25
  encode(zip_file.sysread)
26
26
  end
27
27
 
28
- def send_invoice(invoice, name)
29
- zip = prepare_zip(invoice, "#{name}.xml")
30
- @soap_client.call(:send_bill,
28
+ def dispatch(document)
29
+ # * document - Invoice or DailySummary instance
30
+ xml_build = document.xml
31
+ name = document.document_name
32
+ operation = document.operation
33
+ zip = prepare_zip(xml_build, "#{name}.xml")
34
+ @soap_client.call(operation,
31
35
  message: { fileName: "#{name}.zip", contentFile: zip })
32
36
  end
33
37
 
38
+ def get_status(ticket)
39
+ @soap_client.call(:get_status, message: { ticket: ticket })
40
+ end
41
+
34
42
  private
35
43
 
36
44
  def encode(zip_str)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module SunatInvoice
4
4
  class Configuration
5
- attr_accessor :account_ruc, :account_user, :account_password, :provider
5
+ attr_accessor :account_ruc, :account_user, :account_password
6
6
  end
7
7
  end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: false
2
+
3
+ require_relative 'trade_document'
4
+
5
+ module SunatInvoice
6
+ class CreditNote < TradeDocument
7
+ # * date - issued date
8
+ # * ref_document_number - serial and number of document affected
9
+ # * ref_document_type - type of document affected
10
+ # * response_code - reason for which credit note is issued (CATALOG_09)
11
+ # * description - description of reason
12
+ # * document_type - should be '07' according CATALOG_01
13
+ # * document_number - serial and correlative number of document
14
+ # * provider - a SunatInvoice::Provider instance
15
+ # * customer - a SunatInvoice::Customer instance
16
+ # * signature - a SunatInvoice::Signature instance
17
+ # * lines - array of SunatInvoice::CreditNoteLine instances
18
+
19
+ attr_accessor :ref_document_number, :ref_document_type, :response_code,
20
+ :description
21
+
22
+ def xml
23
+ build = build_xml do |xml|
24
+ build_document_data(xml)
25
+ build_discrepancy_response(xml)
26
+ build_billing_reference(xml)
27
+ build_common_content(xml)
28
+ end
29
+ @signature.sign(build.to_xml)
30
+ end
31
+
32
+ private
33
+
34
+ def root_name
35
+ 'CreditNote'
36
+ end
37
+
38
+ def namespaces
39
+ CREDIT_NOTE_NAMESPACES.merge(TRADE_NAMESPACES)
40
+ end
41
+
42
+ def build_discrepancy_response(xml)
43
+ xml['cac'].DiscrepancyResponse do
44
+ xml['cbc'].ReferenceID ref_document_number
45
+ xml['cbc'].ResponseCode response_code # CATALOG_09
46
+ xml['cbc'].Description description
47
+ end
48
+ end
49
+
50
+ def build_billing_reference(xml)
51
+ xml['cac'].BillingReference do
52
+ xml['cac'].InvoiceDocumentReference do
53
+ xml['cbc'].ID ref_document_number
54
+ xml['cbc'].DocumentTypeCode ref_document_type
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: false
2
+
3
+ require_relative 'item'
4
+
5
+ module SunatInvoice
6
+ class CreditNoteLine < Item
7
+ def line_tag_name
8
+ 'CreditNoteLine'
9
+ end
10
+
11
+ def quantity_tag_name
12
+ 'CreditedQuantity'
13
+ end
14
+ end
15
+ end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require_relative 'tributer'
3
4
 
4
5
  module SunatInvoice
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SunatInvoice
4
+ class DailySummary < XmlDocument
5
+ attr_accessor :reference_date
6
+
7
+ def namespaces
8
+ DAILY_SUMMARY_NAMESPACES.merge(SUMMARY_NAMESPACES)
9
+ end
10
+
11
+ def xml
12
+ build = build_xml do |xml|
13
+ build_number(xml)
14
+ build_summary_info(xml)
15
+ @signature.signer_data(xml)
16
+ @provider.info(xml, false)
17
+ build_lines_xml(xml)
18
+ end
19
+ @signature.sign(build.to_xml)
20
+ end
21
+
22
+ def operation
23
+ :send_summary
24
+ end
25
+
26
+ def document_name
27
+ "#{@provider.ruc}-#{document_number}"
28
+ end
29
+
30
+ private
31
+
32
+ def root_name
33
+ 'SummaryDocuments'
34
+ end
35
+
36
+ def document_number
37
+ formatted = date.strftime('%Y%m%d') # YYYYMMDD
38
+ "RC-#{formatted}-1"
39
+ end
40
+
41
+ def build_summary_info(xml)
42
+ xml['cbc'].ReferenceDate formatted_date(reference_date)
43
+ xml['cbc'].IssueDate formatted_date(date)
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: false
2
+
3
+ require_relative 'credit_note'
4
+
5
+ module SunatInvoice
6
+ class DebitNote < CreditNote
7
+ # * date - issued date
8
+ # * ref_document_number - serial and number of document affected
9
+ # * ref_document_type - type of document affected
10
+ # * response_code - reason for which debit note is issued (CATALOG_10)
11
+ # * description - description of reason
12
+ # * document_type - should be '08' according CATALOG_01
13
+ # * document_number - serial and correlative number of document
14
+ # * provider - a SunatInvoice::Provider instance
15
+ # * customer - a SunatInvoice::Customer instance
16
+ # * signature - a SunatInvoice::Signature instance
17
+ # * lines - array of SunatInvoice::DebitNoteLine instances
18
+
19
+ private
20
+
21
+ def root_name
22
+ 'DebitNote'
23
+ end
24
+
25
+ def namespaces
26
+ DEBIT_NOTE_NAMESPACES.merge(TRADE_NAMESPACES)
27
+ end
28
+
29
+ def total_tag
30
+ 'RequestedMonetaryTotal'
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: false
2
+
3
+ require_relative 'item'
4
+
5
+ module SunatInvoice
6
+ class DebitNoteLine < Item
7
+ def line_tag_name
8
+ 'DebitNoteLine'
9
+ end
10
+
11
+ def quantity_tag_name
12
+ 'DebitedQuantity'
13
+ end
14
+ end
15
+ end
@@ -1,171 +1,50 @@
1
1
  # frozen_string_literal: false
2
- require_relative 'utils'
2
+
3
3
  require_relative 'provider'
4
4
  require_relative 'customer'
5
5
  require_relative 'signature'
6
- require_relative 'tax'
7
- require_relative 'catalogs'
6
+ require_relative 'trade_document'
8
7
 
9
8
  module SunatInvoice
10
- class Invoice < Model
11
- include Utils
12
-
13
- attr_accessor :document_type, :document_number, :items
14
-
15
- UBL_VERSION = '2.0'
16
- CUSTOMIZATION = '1.0'
17
-
9
+ class Invoice < TradeDocument
18
10
  def initialize(*args)
19
11
  super(*args)
20
12
  opts = args[0] || {}
21
- @provider = opts[:provider] || SunatInvoice::Provider.new
22
- @customer = opts[:customer] || SunatInvoice::Customer.new
23
- @date = opts[:date] || DateTime.now.strftime('%Y-%m-%d')
13
+ init_defaults(opts)
14
+ end
15
+
16
+ def init_defaults(opts)
17
+ parties_default(opts)
24
18
  @document_type = opts[:document_type] || '01'
25
19
  @document_number = opts[:document_number] || 'F001-1'
26
20
  @currency = opts[:currency] || 'PEN'
27
- @items ||= []
21
+ @lines ||= []
28
22
  @signature = SunatInvoice::Signature.new(provider: @provider)
29
23
  end
30
24
 
31
- def xml
32
- prepare_totals
33
-
34
- build = Nokogiri::XML::Builder.new do |xml|
35
- xml.Invoice(UBL_NAMESPACES) do
36
- xml['ext'].UBLExtensions do
37
- build_sale_totals(xml)
38
- @signature.signature_ext(xml)
39
- end
40
-
41
- xml['cbc'].UBLVersionID UBL_VERSION
42
- xml['cbc'].CustomizationID CUSTOMIZATION
43
- xml['cbc'].ID @document_number
44
- xml['cbc'].IssueDate @date
45
- xml['cbc'].InvoiceTypeCode @document_type
46
- xml['cbc'].DocumentCurrencyCode @currency
47
-
48
- @signature.signer_data(xml)
49
- @provider.info(xml)
50
- @customer.info(xml)
51
- build_tax_totals(xml)
52
- build_total(xml)
53
- build_items(xml)
54
- end
55
- end
56
- invoice_xml = build.to_xml
57
- @signature.sign(invoice_xml)
58
- end
59
-
60
- def prepare_totals
61
- calculate_tax_totals
62
- calculate_sale_totals
63
- calculate_total
64
- end
65
-
66
- def calculate_total
67
- # calculate invoice total
68
- @total = 0
69
- @total += @tax_totals.values.sum
70
- @total += @sale_totals.values.sum
71
- end
72
-
73
- def calculate_sale_totals
74
- @sale_totals = {}
75
- # get bi totals according kind of sale (gravado, inafecto, exonerado ..)
76
- items.each do |item|
77
- # TODO: I think in most cases only be one tax for item, but should
78
- # handle more cases
79
- total_code = get_total_code(item.taxes.first)
80
- if total_code
81
- @sale_totals[total_code] = 0 unless @sale_totals[total_code]
82
- @sale_totals[total_code] += item.bi_value
83
- end
84
- end
85
- end
86
-
87
- def calculate_tax_totals
88
- # concat item's sale_taxes
89
- @tax_totals = {}
90
- taxes = items.map(&:sale_taxes).flatten
91
- taxes.each do |tax|
92
- @tax_totals[tax.keys.first] ||= 0
93
- @tax_totals[tax.keys.first] += tax.values.sum
94
- end
95
- end
96
-
97
- def build_items(xml)
98
- items.each_with_index do |item, index|
99
- item.xml(xml, index, @currency)
100
- end
101
- end
102
-
103
- def document_name
104
- "#{@provider.ruc}-#{document_type}-#{document_number}"
105
- end
106
-
107
- def build_tax_totals(xml)
108
- @tax_totals.each do |key, value|
109
- SunatInvoice::Tax.new(tax_type: key, amount: value).xml(xml, @currency)
110
- end
111
- end
112
-
113
- def build_sale_totals(xml)
114
- ubl_ext(xml) do
115
- xml['sac'].AdditionalInformation do
116
- @sale_totals.each do |code, amount|
117
- xml['sac'].AdditionalMonetaryTotal do
118
- xml['cbc'].ID code
119
- amount_xml(xml['cbc'], 'PayableAmount', amount, @currency)
120
- end
121
- end
122
- end
123
- end
25
+ def parties_default(opts)
26
+ @provider = opts[:provider] || SunatInvoice::Provider.new
27
+ @customer = opts[:customer] || SunatInvoice::Customer.new
124
28
  end
125
29
 
126
- def build_total(xml)
127
- xml['cac'].LegalMonetaryTotal do
128
- amount_xml(xml['cbc'], 'PayableAmount', @total, @currency)
30
+ def xml
31
+ build = build_xml do |xml|
32
+ build_document_data(xml)
33
+ build_common_content(xml)
129
34
  end
130
- end
131
35
 
132
- def add_item(item)
133
- items << item if item.is_a?(SunatInvoice::Item)
36
+ invoice_xml = build.to_xml
37
+ @signature.sign(invoice_xml)
134
38
  end
135
39
 
136
- def get_total_code(tax)
137
- return unless tax
138
- case tax.tax_type
139
- when :igv
140
- get_total_igv_code(tax.tax_exemption_reason)
141
- # when :isc
142
- # tax.tier_range
143
- end
144
- end
40
+ private
145
41
 
146
- def get_total_igv_code(exemption_reason)
147
- if Catalogs::CATALOG_07.first == exemption_reason
148
- Catalogs::CATALOG_14.first
149
- elsif Catalogs::CATALOG_07[1..6].include?(exemption_reason)
150
- Catalogs::CATALOG_14[3]
151
- elsif Catalogs::CATALOG_07[7] == exemption_reason
152
- Catalogs::CATALOG_14[2]
153
- elsif Catalogs::CATALOG_07[8..14].include?(exemption_reason)
154
- Catalogs::CATALOG_14[1]
155
- end
42
+ def root_name
43
+ 'Invoice'
156
44
  end
157
45
 
158
- def attributes
159
- {
160
- attributes!: {
161
- 'cbc:InvoicedQuantity' => { '@unitCode' => :unit },
162
- 'cbc:PriceAmount' => { '@currencyID' => :currency }, # PEN
163
- 'cbc:TaxAmount' => { '@currencyID' => :currency }, # PEN
164
- 'cbc:PayableAmount' => { '@currencyID' => :currency }, # PEN
165
- 'cbc:LineExtensionAmount' => { '@currencyID' => :currency }, # PEN
166
- 'cbc:ChargeTotalAmount' => { '@currencyID' => :currency }, # PEN
167
- }
168
- }
46
+ def namespaces
47
+ INVOICE_NAMESPACES.merge(TRADE_NAMESPACES)
169
48
  end
170
49
  end
171
50
  end
@@ -1,12 +1,10 @@
1
1
  # frozen_string_literal: true
2
- require_relative 'utils'
3
2
 
4
- module SunatInvoice
5
- class Item < Model
6
- include Utils
3
+ require_relative 'line'
7
4
 
8
- attr_accessor :quantity, :description, :price, :price_code, :unit_code,
9
- :taxes
5
+ module SunatInvoice
6
+ class Item < Line
7
+ attr_accessor :quantity, :description, :price, :price_code, :unit_code
10
8
 
11
9
  def initialize(*args)
12
10
  # * quantity - quantity of item
@@ -21,6 +19,25 @@ module SunatInvoice
21
19
  @taxes ||= []
22
20
  end
23
21
 
22
+ def line_tag_name
23
+ 'InvoiceLine'
24
+ end
25
+
26
+ def quantity_tag_name
27
+ 'InvoicedQuantity'
28
+ end
29
+
30
+ def xml(xml, index, currency)
31
+ xml['cac'].send(line_tag_name) do
32
+ build_basic_line_xml(xml, index)
33
+ amount_xml(xml['cbc'], 'LineExtensionAmount', bi_value, currency)
34
+ build_pricing_reference(xml, currency)
35
+ build_taxes_xml(xml, currency)
36
+ build_item(xml)
37
+ build_price(xml, currency)
38
+ end
39
+ end
40
+
24
41
  def bi_value
25
42
  # bi of sale = price without taxes * quantity
26
43
  (@price.to_f * @quantity.to_f).round(2)
@@ -41,27 +58,15 @@ module SunatInvoice
41
58
  (@price.to_f + sum_taxes).round(2)
42
59
  end
43
60
 
61
+ private
62
+
44
63
  def sum_taxes
45
64
  taxes.map(&:amount).sum
46
65
  end
47
66
 
48
- def xml(xml, index, currency)
49
- xml['cac'].InvoiceLine do
50
- xml['cbc'].ID(index + 1)
51
- xml['cbc'].InvoicedQuantity(@quantity, unitCode: unit_code)
52
- amount_xml(xml['cbc'], 'LineExtensionAmount', bi_value, currency)
53
- xml['cac'].PricingReference do
54
- xml['cac'].AlternativeConditionPrice do
55
- amount_xml(xml['cbc'], 'PriceAmount', sale_price, currency)
56
- xml['cbc'].PriceTypeCode price_code
57
- end
58
- end
59
- taxes_xml(xml, currency)
60
- build_item(xml)
61
- xml['cac'].Price do
62
- amount_xml(xml['cbc'], 'PriceAmount', price, currency)
63
- end
64
- end
67
+ def build_basic_line_xml(xml, index)
68
+ xml['cbc'].ID(index + 1)
69
+ xml['cbc'].send(quantity_tag_name, quantity, unitCode: unit_code)
65
70
  end
66
71
 
67
72
  def build_item(xml)
@@ -70,9 +75,18 @@ module SunatInvoice
70
75
  end
71
76
  end
72
77
 
73
- def taxes_xml(xml, currency)
74
- taxes&.each do |tax|
75
- tax.xml(xml, currency)
78
+ def build_pricing_reference(xml, currency)
79
+ xml['cac'].PricingReference do
80
+ xml['cac'].AlternativeConditionPrice do
81
+ amount_xml(xml['cbc'], 'PriceAmount', sale_price, currency)
82
+ xml['cbc'].PriceTypeCode price_code
83
+ end
84
+ end
85
+ end
86
+
87
+ def build_price(xml, currency)
88
+ xml['cac'].Price do
89
+ amount_xml(xml['cbc'], 'PriceAmount', price, currency)
76
90
  end
77
91
  end
78
92
  end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'model'
4
+ require_relative 'utils'
5
+
6
+ module SunatInvoice
7
+ class Line < Model
8
+ include Utils
9
+
10
+ attr_accessor :taxes
11
+
12
+ def build_taxes_xml(xml, currency)
13
+ taxes&.each do |tax|
14
+ tax.xml(xml, currency)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require_relative 'tributer'
3
4
  require_relative 'utils'
4
5
 
@@ -6,8 +7,25 @@ module SunatInvoice
6
7
  class Provider < Tributer
7
8
  include Utils
8
9
 
9
- attr_accessor :signature_id, :signature_location_id, :uri, :pk_file,
10
- :cert_file
10
+ attr_accessor :signature_id, :signature_location_id, :pk_file, :cert_file
11
+
12
+ def info(xml, with_address = true)
13
+ xml['cac'].AccountingSupplierParty do
14
+ xml['cbc'].CustomerAssignedAccountID ruc
15
+ xml['cbc'].AdditionalAccountID document_type
16
+ build_party_xml(xml, with_address)
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def build_party_xml(xml, with_address)
23
+ xml['cac'].Party do
24
+ build_name(xml)
25
+ xml['cac'].PostalAddress { address(xml) } if with_address
26
+ build_registration_name(xml)
27
+ end
28
+ end
11
29
 
12
30
  def address(xml)
13
31
  xml['cbc'].ID @ubigeo
@@ -36,17 +54,5 @@ module SunatInvoice
36
54
  xml['cbc'].RegistrationName name
37
55
  end
38
56
  end
39
-
40
- def info(xml)
41
- xml['cac'].AccountingSupplierParty do
42
- xml['cbc'].CustomerAssignedAccountID ruc
43
- xml['cbc'].AdditionalAccountID document_type
44
- xml['cac'].Party do
45
- build_name(xml)
46
- xml['cac'].PostalAddress { address(xml) }
47
- build_registration_name(xml)
48
- end
49
- end
50
- end
51
57
  end
52
58
  end