sunat_invoice 0.0.1 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +1 -0
- data/README.mkd +1 -25
- data/lib/sunat_invoice/client.rb +3 -6
- data/lib/sunat_invoice/clients/consult_client.rb +17 -0
- data/lib/sunat_invoice/clients/invoice_client.rb +11 -3
- data/lib/sunat_invoice/configuration.rb +1 -1
- data/lib/sunat_invoice/credit_note.rb +59 -0
- data/lib/sunat_invoice/credit_note_line.rb +15 -0
- data/lib/sunat_invoice/customer.rb +1 -0
- data/lib/sunat_invoice/daily_summary.rb +46 -0
- data/lib/sunat_invoice/debit_note.rb +33 -0
- data/lib/sunat_invoice/debit_note_line.rb +15 -0
- data/lib/sunat_invoice/invoice.rb +23 -144
- data/lib/sunat_invoice/item.rb +40 -26
- data/lib/sunat_invoice/line.rb +18 -0
- data/lib/sunat_invoice/provider.rb +20 -14
- data/lib/sunat_invoice/response_parser.rb +64 -0
- data/lib/sunat_invoice/signature.rb +29 -15
- data/lib/sunat_invoice/summary_line.rb +75 -0
- data/lib/sunat_invoice/tax.rb +6 -1
- data/lib/sunat_invoice/trade_calculations.rb +68 -0
- data/lib/sunat_invoice/trade_document.rb +85 -0
- data/lib/sunat_invoice/utils.rb +48 -9
- data/lib/sunat_invoice/voided.rb +22 -0
- data/lib/sunat_invoice/voided_line.rb +20 -0
- data/lib/sunat_invoice/xml_document.rb +52 -0
- data/lib/sunat_invoice.rb +14 -0
- data/sunat_invoice.gemspec +5 -5
- data/test/credit_note_test.rb +15 -0
- data/test/daily_summary_test.rb +35 -0
- data/test/debit_note_test.rb +15 -0
- data/test/factories.rb +70 -0
- data/test/fixtures/responses/invoice_success.xml +2 -0
- data/test/fixtures/responses/summary_success.xml +2 -0
- data/test/fixtures/responses/ticket_invalid.xml +2 -0
- data/test/helper.rb +1 -0
- data/test/invoice_client_test.rb +68 -16
- data/test/invoice_test.rb +19 -10
- data/test/item_test.rb +3 -2
- data/test/response_parser_test.rb +28 -0
- data/test/support/response_helper.rb +18 -0
- data/test/support/signature_helper.rb +15 -8
- metadata +34 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c15a897331d06af16937c9bf1020984592bcd0f3
|
4
|
+
data.tar.gz: 51cc6c5c299e0d2209a32ccc51be2158b7a4e780
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a5866087a7d0c40c4c88ad32ee94812d7e3dbd75892968ca39df00aa501fcdb9167a0ba06b60c3c38d0095b51c631d6de51055e01dfee4f4db029c473bac4b91
|
7
|
+
data.tar.gz: 20781a7b8110190a887a7c9740fbfebb4a8fd55893953a07fc12c8da05f549d1fae2630b301bc98329db94dc39c2ca23f2ce017541409774013d034c4626062e
|
data/Gemfile
CHANGED
data/README.mkd
CHANGED
@@ -1,26 +1,2 @@
|
|
1
1
|
# Sunat Invoice
|
2
|
-
Ruby
|
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
|
data/lib/sunat_invoice/client.rb
CHANGED
@@ -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
|
29
|
-
|
30
|
-
|
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)
|
@@ -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,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
|
@@ -1,171 +1,50 @@
|
|
1
1
|
# frozen_string_literal: false
|
2
|
-
|
2
|
+
|
3
3
|
require_relative 'provider'
|
4
4
|
require_relative 'customer'
|
5
5
|
require_relative 'signature'
|
6
|
-
require_relative '
|
7
|
-
require_relative 'catalogs'
|
6
|
+
require_relative 'trade_document'
|
8
7
|
|
9
8
|
module SunatInvoice
|
10
|
-
class Invoice <
|
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
|
-
|
22
|
-
|
23
|
-
|
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
|
-
@
|
21
|
+
@lines ||= []
|
28
22
|
@signature = SunatInvoice::Signature.new(provider: @provider)
|
29
23
|
end
|
30
24
|
|
31
|
-
def
|
32
|
-
|
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
|
127
|
-
|
128
|
-
|
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
|
-
|
133
|
-
|
36
|
+
invoice_xml = build.to_xml
|
37
|
+
@signature.sign(invoice_xml)
|
134
38
|
end
|
135
39
|
|
136
|
-
|
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
|
147
|
-
|
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
|
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
|
data/lib/sunat_invoice/item.rb
CHANGED
@@ -1,12 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
require_relative 'utils'
|
3
2
|
|
4
|
-
|
5
|
-
class Item < Model
|
6
|
-
include Utils
|
3
|
+
require_relative 'line'
|
7
4
|
|
8
|
-
|
9
|
-
|
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
|
49
|
-
xml['
|
50
|
-
|
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
|
74
|
-
|
75
|
-
|
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, :
|
10
|
-
|
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
|