fiscalizer 0.0.12 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/.rspec +2 -0
  4. data/Gemfile +0 -4
  5. data/LICENSE.txt +1 -1
  6. data/README.md +187 -171
  7. data/bin/console +14 -0
  8. data/bin/setup +7 -0
  9. data/doc/Tehnicka specifikacija za korisnike 1.4.pdf +0 -0
  10. data/fiscalizer.gemspec +14 -13
  11. data/lib/fiscalizer.rb +33 -4
  12. data/lib/fiscalizer/constants.rb +11 -0
  13. data/lib/fiscalizer/data_objects/echo.rb +10 -0
  14. data/lib/fiscalizer/data_objects/fee.rb +18 -0
  15. data/lib/fiscalizer/data_objects/invoice.rb +79 -0
  16. data/lib/fiscalizer/data_objects/office.rb +41 -0
  17. data/lib/fiscalizer/{tax.rb → data_objects/tax.rb} +3 -5
  18. data/lib/fiscalizer/deserializers/base.rb +58 -0
  19. data/lib/fiscalizer/deserializers/echo.rb +13 -0
  20. data/lib/fiscalizer/deserializers/invoice.rb +9 -0
  21. data/lib/fiscalizer/deserializers/office.rb +6 -0
  22. data/lib/fiscalizer/fiscalizer.rb +36 -152
  23. data/lib/fiscalizer/fiscalizers/base.rb +54 -0
  24. data/lib/fiscalizer/fiscalizers/echo.rb +13 -0
  25. data/lib/fiscalizer/fiscalizers/invoice.rb +24 -0
  26. data/lib/fiscalizer/fiscalizers/office.rb +15 -0
  27. data/lib/fiscalizer/serializers/base.rb +58 -0
  28. data/lib/fiscalizer/serializers/echo.rb +21 -0
  29. data/lib/fiscalizer/serializers/invoice.rb +92 -0
  30. data/lib/fiscalizer/serializers/office.rb +85 -0
  31. data/lib/fiscalizer/serializers/signature.rb +62 -0
  32. data/lib/fiscalizer/serializers/tax.rb +81 -0
  33. data/lib/fiscalizer/services/request_sender.rb +68 -0
  34. data/lib/fiscalizer/services/security_code_generator.rb +29 -0
  35. data/lib/fiscalizer/version.rb +1 -1
  36. data/spec/fiscalizer_spec.rb +119 -0
  37. data/spec/spec_helper.rb +9 -0
  38. metadata +67 -39
  39. data/doc/README.md +0 -3
  40. data/doc/Tehnicka_specifikacija_za_korisnike_1.2.pdf +0 -0
  41. data/example/README.md +0 -25
  42. data/example/echo_P12.rb +0 -13
  43. data/example/echo_public_and_private_keys.rb +0 -16
  44. data/example/invoice_fiscalization_passing_arguments.rb +0 -44
  45. data/example/invoice_fiscalization_passing_object.rb +0 -48
  46. data/example/office_fiscalization_passing_arguments.rb +0 -22
  47. data/example/office_fiscalization_passing_object.rb +0 -26
  48. data/lib/README.md +0 -0
  49. data/lib/fiscalizer/README.md +0 -9
  50. data/lib/fiscalizer/communication.rb +0 -305
  51. data/lib/fiscalizer/echo.rb +0 -11
  52. data/lib/fiscalizer/fee.rb +0 -20
  53. data/lib/fiscalizer/invoice.rb +0 -190
  54. data/lib/fiscalizer/office.rb +0 -66
  55. data/lib/fiscalizer/response.rb +0 -124
  56. data/test/README.md +0 -13
  57. data/test/test_echo.rb +0 -20
  58. data/test/test_fee +0 -64
  59. data/test/test_fiscalizer.rb +0 -222
  60. data/test/test_fiscalizer_communication.rb +0 -28
  61. data/test/test_invoice.rb +0 -11
  62. data/test/test_office.rb +0 -11
  63. data/test/test_tax.rb +0 -89
@@ -1,44 +0,0 @@
1
- fiscal = Fiscalizer.new certificate_p12_path: "/path/to/FISKAL 1.p12",
2
- password: "12345678"
3
- # Generate taxes
4
- taxes_vat = []
5
- taxes_spending = []
6
- taxes_other = []
7
- (0..5).each do |i|
8
- tax = Fiscalizer::Tax.new
9
- tax.base = rand(10000 * 100).to_f / 100.0
10
- tax.rate = rand(100 * 100).to_f / 100.0
11
- taxes_vat << tax
12
- end
13
- (0..5).each do |i|
14
- tax = Fiscalizer::Tax.new
15
- tax.base = rand(10000 * 100).to_f / 100.0
16
- tax.rate = rand(100 * 100).to_f / 100.0
17
- taxes_spending << tax
18
- end
19
- (0..5).each do |i|
20
- tax = Fiscalizer::Tax.new
21
- tax.base = rand(10000 * 100).to_f / 100.0
22
- tax.rate = rand(100 * 100).to_f / 100.0
23
- tax.name = "My Test Tax #{i}"
24
- taxes_other << tax
25
- end
26
- # Generate invoice
27
- invoice_response = fiscal.fiscalize_invoice uuid: UUID,
28
- time_sent: Time.now,
29
- pin: "00123456789",
30
- in_vat_system: true,
31
- time_issued: Time.now - 3600,
32
- consistance_mark: "P",
33
- issued_number: "1",
34
- issued_office: "Pm2",
35
- issued_machine: "3",
36
- tax_vat: taxes_vat,
37
- tax_spending: taxes_spending,
38
- tax_other: taxes_other,
39
- payment_method: "g",
40
- operator_pin: "12345678900",
41
- subsequent_delivery: false,
42
- value_non_taxable: 200.0
43
-
44
- puts "The server returned the following JIR: " + invoice_response.unique_identifier if !invoice_response.errors?
@@ -1,48 +0,0 @@
1
- fiscal = Fiscalizer.new certificate_p12_path: "/path/to/FISKAL 1.p12",
2
- password: "12345678"
3
-
4
- # Generate Invoice
5
- invoice = Fiscalizer::Invoice.new
6
- invoice.uuid = UUID
7
- invoice.time_sent = Time.now
8
- invoice.pin = "00123456789"
9
- invoice.in_vat_system = true
10
- invoice.time_issued = Time.now - 3600
11
- invoice.consistance_mark = "P"
12
- invoice.issued_number = "1"
13
- invoice.issued_office = "Pm2"
14
- invoice.issued_machine = "3"
15
- invoice.payment_method = "g"
16
- invoice.operator_pin = "12345678900"
17
- invoice.subsequent_delivery = false
18
- invoice.value_non_taxable = 200.0
19
-
20
- # Generate taxes
21
- (0..5).each do |i|
22
- tax = Fiscalizer::Tax.new
23
- tax.base = rand(10000 * 100).to_f / 100.0
24
- tax.rate = rand(100 * 100).to_f / 100.0
25
- invoice.add_tax_vat tax
26
- end
27
- (0..5).each do |i|
28
- tax = Fiscalizer::Tax.new
29
- tax.base = rand(10000 * 100).to_f / 100.0
30
- tax.rate = rand(100 * 100).to_f / 100.0
31
- invoice.add_tax_other base: base, rate: rate, name: "Other tax #{i}"
32
- end
33
- (0..5).each do |i|
34
- fee = Fiscalizer::Fee.new
35
- fee.value = rand(10000 * 100).to_f / 100.0
36
- fee.name = "My Test Fee #{i}"
37
- invoice.add_fee fee
38
- end
39
- (0..5).each do |i|
40
- fee = Fiscalizer::Fee.new
41
- fee.value = rand(10000 * 100).to_f / 100.0
42
- fee.name = "My Test Fee #{i}"
43
- invoice.add_fee value: value, name: name
44
- end
45
- # Generate invoice
46
- invoice_response = fiscal.fiscalize_invoice invoice
47
-
48
- puts "The server returned the following JIR: " + invoice_response.unique_identifier if !invoice_response.errors?
@@ -1,22 +0,0 @@
1
- fiscal = Fiscalizer.new certificate_p12_path: "/path/to/FISKAL 1.p12",
2
- password: "12345678"
3
-
4
- # Generate office
5
- office_response = fiscal.office uuid: "ca996cc7-fcc3-4c50-961b-40c8b875a5e8",
6
- time_sent: Time.now,
7
- pin: "00123456789",
8
- office_label: "Poslovnica1",
9
- adress_street_name: "Somewhere",
10
- adress_house_num: "42",
11
- adress_house_num_addendum: "AD",
12
- adress_post_num: "10000",
13
- adress_settlement: "Block 25-C",
14
- adress_township: "Vogsphere",
15
- adress_other: nil,
16
- office_time: "Pon-Pet: 8:00-16:00",
17
- take_effect_date: Time.now + 3600 * 24 * 7,
18
- closure_mark: nil,
19
- specific_purpose: nil
20
-
21
- puts "The server returned the following UUID: " + office_response.uuid if !office_response.errors?
22
- puts "Office space fiscalization was successful!" if !office_response.errors?
@@ -1,26 +0,0 @@
1
- fiscal = Fiscalizer.new certificate_p12_path: "/path/to/FISKAL 1.p12",
2
- password: "12345678"
3
-
4
- # Generate office
5
- office = Fiscalizer::Office.new
6
- office.uuid = "ca996cc7-fcc3-4c50-961b-40c8b875a5e8"
7
- office.time_sent = Time.now
8
- office.pin = "00123456789"
9
- office.office_label = "Poslovnica1"
10
- office.adress_street_name = "Somewhere"
11
- office.adress_house_num = "42"
12
- office.adress_house_num_addendum = "AD"
13
- office.adress_post_num = "10000"
14
- office.adress_settlement = "Block 25-C"
15
- office.adress_township = "Vogsphere"
16
- office.adress_other = nil
17
- office.office_time = "Pon-Pet: 8:00-16:00"
18
- office.take_effect_date = Time.now + 3600 * 24 * 7
19
- office.closure_mark = nil
20
- office.specific_purpose = nil
21
-
22
- # Generate office
23
- office_response = fiscal.fiscalize_office office
24
-
25
- puts "The server returned the following UUID: " + office_response.uuid if !office_response.errors?
26
- puts "Office space fiscalization was successful!" if !office_response.errors?
File without changes
@@ -1,9 +0,0 @@
1
- # Fiscalizer
2
-
3
- Fiscalizer is the main class of this gem. It interacts with all other classes, handles certificate decription and connection establishment.
4
-
5
- Methods:
6
-
7
- * `echo` : Creates an echo request to the fiscalization servers
8
- * `fiscalize_office` : Creates or recives an office object and fiscalizes it (alias methods `office` and `fiscalize_office_space`)
9
- * `fiscalize_invoice` : Creates or recives an invoice object and fiscalizes it (alias methods `invoice`)
@@ -1,305 +0,0 @@
1
- class Fiscalizer
2
- class Communication
3
- attr_accessor :url, :tns, :schemaLocation,
4
- :key_public, :key_private, :certificate,
5
- :certificate_issued_by, :timeout
6
-
7
- def initialize( tns: "http://www.apis-it.hr/fin/2012/types/f73",
8
- url: "https://cis.porezna-uprava.hr:8449/FiskalizacijaService",
9
- schemaLocation: "http://www.apis-it.hr/fin/2012/types/f73 FiskalizacijaSchema.xsd",
10
- key_public: nil, key_private: nil, certificate: nil,
11
- certificate_issued_by: "OU=RDC,O=FINA,C=HR", timeout:3 )
12
- @tns = tns
13
- @url = url
14
- @schemaLocation = schemaLocation
15
- @key_public = key_public
16
- @key_private = key_private
17
- @certificate = certificate
18
- @certificate_issued_by = certificate_issued_by
19
- @timeout = timeout
20
- end # initialize
21
-
22
- def send object
23
- # Check input
24
- raise "Missing keys" if @key_public == nil || @key_private == nil
25
- raise "Missing certificate" if @certificate == nil
26
- raise "Can't send nil object" if object == nil
27
-
28
- # Prepare data
29
- uri = URI.parse(@url)
30
- http = Net::HTTP.new(uri.host, uri.port)
31
- http.read_timeout = @timeout
32
- http.use_ssl = true
33
- http.cert_store = OpenSSL::X509::Store.new
34
- http.cert_store.set_default_paths
35
- begin
36
- http.cert_store.add_cert(@certificate)
37
- rescue OpenSSL::X509::StoreError
38
- puts "Certificate alreay exists"
39
- end
40
- http.verify_mode = OpenSSL::SSL::VERIFY_PEER
41
-
42
- # Encode object
43
- encoded_object = encode_object object
44
- return false if encoded_object.nil?
45
-
46
- # Send it
47
- request = Net::HTTP::Post.new(uri.request_uri)
48
- request.content_type = 'application/xml'
49
- request.body = encoded_object
50
- response = http.request(request)
51
-
52
- return response
53
- end # send
54
-
55
- def encode_object object
56
- encoded_object = nil
57
- if object.class == Echo
58
- encoded_object = encode_echo object
59
- elsif object.class == Office
60
- encoded_object = encode_office object
61
- elsif object.class == Invoice
62
- encoded_object = encode_invoice object
63
- end
64
- return encoded_object
65
- end # encode_object
66
-
67
- def generate_security_code invoice
68
- # Build data set to generate security code
69
- unsigned_code = ""
70
- unsigned_code += invoice.pin
71
- unsigned_code += invoice.time_issued_str " "
72
- unsigned_code += invoice.issued_number.to_s
73
- unsigned_code += invoice.issued_office.to_s
74
- unsigned_code += invoice.issued_machine.to_s
75
- unsigned_code += invoice.summed_total_str
76
- # Sign with my private key
77
- signed_code = OpenSSL::PKey::RSA.new(key_private).sign(OpenSSL::Digest::SHA1.new, unsigned_code)
78
- # Create a MD5 digest from it
79
- md5_digest = Digest::MD5.hexdigest(signed_code)
80
- invoice.security_code = md5_digest
81
- return md5_digest
82
- end # generate_security_code
83
-
84
- private
85
- def encode_echo object
86
- echo_xml = Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
87
- xml['tns'].EchoRequest(
88
- 'xmlns:tns' => @tns,
89
- 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
90
- 'xsi:schemaLocation' => @schemaLocation
91
- ) {
92
- xml.text object.text
93
- }
94
- end
95
- xml = soap_envelope(echo_xml).to_xml
96
- object.generated_xml = soap_envelope(echo_xml).to_xml
97
- return xml
98
- end # encode_echo
99
-
100
- def encode_office object
101
- office_request_xml = Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
102
- xml['tns'].PoslovniProstorZahtjev(
103
- 'xmlns:tns' => @tns,
104
- 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
105
- 'xsi:schemaLocation' => schemaLocation,
106
- 'Id' => 'PoslovniProstorZahtjev'
107
- ) {
108
- # Header
109
- xml['tns'].Zaglavlje {
110
- xml['tns'].IdPoruke object.uuid
111
- xml['tns'].DatumVrijeme object.time_sent_str
112
- }
113
- # Body
114
- xml['tns'].PoslovniProstor {
115
- # Important info
116
- xml['tns'].Oib object.pin
117
- xml['tns'].OznPoslProstora object.office_label
118
- xml['tns'].AdresniPodatak {
119
- xml['tns'].Adresa {
120
- xml['tns'].Ulica object.adress_street_name if object.adress_street_name != nil && object.adress_street_name.length != 0
121
- xml['tns'].KucniBroj object.adress_house_num if object.adress_house_num != nil && object.adress_house_num.length != 0
122
- xml['tns'].KucniBrojDodatak object.adress_house_num_addendum if object.adress_house_num_addendum != nil && object.adress_house_num_addendum.length != 0
123
- xml['tns'].BrojPoste object.adress_post_num if object.adress_post_num != nil && object.adress_post_num.length != 0
124
- xml['tns'].Naselje object.adress_settlement if object.adress_settlement != nil && object.adress_settlement.length != 0
125
- xml['tns'].Opcina object.adress_township if object.adress_township != nil && object.adress_township.length != 0
126
- } if object.adress_other == nil || object.adress_other.length == 0
127
- xml['tns'].OstaliTipoviPP object.adress_other if object.adress_other != nil && object.adress_other.length != 0
128
- }
129
- xml['tns'].RadnoVrijeme object.office_time
130
- xml['tns'].DatumPocetkaPrimjene object.take_effect_date_str
131
- # Optional info
132
- xml['tns'].OznakaZatvaranja object.closure_mark if object.closure_mark != nil
133
- xml['tns'].SpecNamj object.specific_purpose if object.specific_purpose != nil
134
- }
135
- xml.Signature('xmlns' => 'http://www.w3.org/2000/09/xmldsig#') {
136
- xml.SignedInfo {
137
- xml.CanonicalizationMethod('Algorithm' => 'http://www.w3.org/2001/10/xml-exc-c14n#')
138
- xml.SignatureMethod('Algorithm' => 'http://www.w3.org/2000/09/xmldsig#rsa-sha1')
139
- xml.Reference('URI' => '#PoslovniProstorZahtjev') {
140
- xml.Transforms {
141
- xml.Transform('Algorithm' => 'http://www.w3.org/2000/09/xmldsig#enveloped-signature')
142
- xml.Transform('Algorithm' => 'http://www.w3.org/2001/10/xml-exc-c14n#')
143
- }
144
- xml.DigestMethod('Algorithm' => 'http://www.w3.org/2000/09/xmldsig#sha1')
145
- xml.DigestValue
146
- }
147
- }
148
- xml.SignatureValue
149
- xml.KeyInfo {
150
- xml.X509Data {
151
- xml.X509Certificate key_public.to_s.gsub('-----BEGIN CERTIFICATE-----','').gsub('-----END CERTIFICATE-----','').gsub("\n",'')
152
- xml.X509IssuerSerial {
153
- xml.X509IssuerName @certificate_issued_by
154
- xml.X509SerialNumber "1053520622" # Explane
155
- }
156
- }
157
- }
158
- }
159
- }
160
- end
161
-
162
- body = soap_envelope(office_request_xml)
163
- unsigned_document = Xmldsig_fiscalizer::SignedDocument.new(body.doc.root.to_xml)
164
- signed_xml = unsigned_document.sign(@key_private)
165
- signed_xml.sub! '<?xml version="1.0"?>', ''
166
- signed_xml = signed_xml.gsub /^$\n/, ''
167
-
168
- object.generated_xml = signed_xml
169
-
170
- return signed_xml
171
- end # encode_office
172
-
173
- def encode_invoice object
174
- generate_security_code object
175
- invoice_request_xml = Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
176
- xml['tns'].RacunZahtjev(
177
- 'xmlns:tns' => @tns,
178
- 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
179
- 'xsi:schemaLocation' => schemaLocation,
180
- 'Id' => 'RacunZahtjev'
181
- ) {
182
- # Header
183
- xml['tns'].Zaglavlje {
184
- xml['tns'].IdPoruke object.uuid
185
- xml['tns'].DatumVrijeme object.time_sent_str
186
- }
187
- # Body
188
- xml['tns'].Racun {
189
- # Important info
190
- xml['tns'].Oib object.pin
191
- xml['tns'].USustPdv object.in_vat_system
192
- xml['tns'].DatVrijeme object.time_issued_str
193
- xml['tns'].OznSlijed object.consistance_mark
194
- # Invoice issued numbers
195
- xml['tns'].BrRac {
196
- xml['tns'].BrOznRac object.issued_number.to_s
197
- xml['tns'].OznPosPr object.issued_office.to_s
198
- xml['tns'].OznNapUr object.issued_machine.to_s
199
- }
200
- # Optional info
201
- # Tax VAT
202
- xml['tns'].Pdv {
203
- object.tax_vat.each do |tax|
204
- xml['tns'].Porez {
205
- xml['tns'].Stopa tax.rate_str
206
- xml['tns'].Osnovica tax.base_str
207
- xml['tns'].Iznos tax.total_str
208
- }
209
- end
210
- } if object.tax_vat != nil && object.tax_vat.size != 0
211
- # Tax Spending
212
- xml['tns'].Pnp {
213
- object.tax_spending.each do |tax|
214
- xml['tns'].Porez {
215
- xml['tns'].Stopa tax.rate_str
216
- xml['tns'].Osnovica tax.base_str
217
- xml['tns'].Iznos tax.total_str
218
- }
219
- end
220
- } if object.tax_spending != nil && object.tax_spending.size != 0
221
- # Tax Other
222
- xml['tns'].OstaliPor {
223
- object.tax_other.each do |tax|
224
- xml['tns'].Porez {
225
- xml['tns'].Naziv tax.name
226
- xml['tns'].Stopa tax.rate_str
227
- xml['tns'].Osnovica tax.base_str
228
- xml['tns'].Iznos tax.total_str
229
- }
230
- end
231
- } if object.tax_other != nil && object.tax_other.size != 0
232
- # Tax info
233
- xml['tns'].IznosOslobPdv object.value_tax_liberation_str if object.value_tax_liberation_str != nil
234
- xml['tns'].IznosMarza object.value_tax_margin_str if object.value_tax_margin_str != nil
235
- xml['tns'].IznosNePodlOpor object.value_non_taxable_str if object.value_non_taxable_str != nil
236
- # Fees
237
- xml['tns'].Naknade {
238
- object.tax_other.each do |tax|
239
- xml['tns'].Naknada {
240
- xml['tns'].NazivN tax.name
241
- xml['tns'].IznosN tax.rate_str
242
- }
243
- end
244
- } if object.fees != nil && object.fees.size != 0
245
- # Important info
246
- xml['tns'].IznosUkupno object.summed_total_str
247
- xml['tns'].NacinPlac object.payment_method
248
- xml['tns'].OibOper object.operator_pin
249
- xml['tns'].ZastKod object.security_code
250
- xml['tns'].NakDost object.subsequent_delivery
251
- # Optional info
252
- xml['tns'].ParagonBrRac object.paragon_label if object.paragon_label != nil
253
- xml['tns'].SpecNamj object.specific_purpose if object.specific_purpose != nil
254
- }
255
- xml.Signature('xmlns' => 'http://www.w3.org/2000/09/xmldsig#') {
256
- xml.SignedInfo {
257
- xml.CanonicalizationMethod('Algorithm' => 'http://www.w3.org/2001/10/xml-exc-c14n#')
258
- xml.SignatureMethod('Algorithm' => 'http://www.w3.org/2000/09/xmldsig#rsa-sha1')
259
- xml.Reference('URI' => '#RacunZahtjev') {
260
- xml.Transforms {
261
- xml.Transform('Algorithm' => 'http://www.w3.org/2000/09/xmldsig#enveloped-signature')
262
- xml.Transform('Algorithm' => 'http://www.w3.org/2001/10/xml-exc-c14n#')
263
- }
264
- xml.DigestMethod('Algorithm' => 'http://www.w3.org/2000/09/xmldsig#sha1')
265
- xml.DigestValue
266
- }
267
- }
268
- xml.SignatureValue
269
- xml.KeyInfo {
270
- xml.X509Data {
271
- xml.X509Certificate key_public.to_s.gsub('-----BEGIN CERTIFICATE-----','').gsub('-----END CERTIFICATE-----','').gsub("\n",'')
272
- xml.X509IssuerSerial {
273
- xml.X509IssuerName @certificate_issued_by
274
- xml.X509SerialNumber "1053520622" # Explane
275
- }
276
- }
277
- }
278
- }
279
- }
280
- end
281
-
282
- body = soap_envelope(invoice_request_xml)
283
- unsigned_document = Xmldsig_fiscalizer::SignedDocument.new(body.doc.root.to_xml)
284
- signed_xml = unsigned_document.sign(@key_private)
285
- signed_xml.sub! '<?xml version="1.0"?>', ''
286
- signed_xml = signed_xml.gsub /^$\n/, ''
287
-
288
- object.generated_xml = signed_xml
289
-
290
- return signed_xml
291
- end # encode_invoice
292
-
293
- def soap_envelope req_xml
294
- return Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
295
- xml['soapenv'].Envelope('xmlns:soapenv' => 'http://schemas.xmlsoap.org/soap/envelope/') {
296
- xml['soapenv'].Body {
297
- xml << req_xml.doc.root.to_xml
298
- }
299
- }
300
- end
301
- end # soap_envelope
302
-
303
-
304
- end # Communication
305
- end # Fiscalizer