fiscalizer 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,148 @@
1
+ require 'fiscalizer/communication'
2
+ require 'fiscalizer/echo'
3
+ require 'fiscalizer/office'
4
+ require 'fiscalizer/invoice'
5
+ require 'fiscalizer/response'
6
+
7
+ class Fiscalizer
8
+
9
+ # Accessible attributes
10
+ attr_accessor :url, :key_public_path, :key_private_path, :certificate_path,
11
+ :key_private, :key_public, :certificate,
12
+ :tns, :schemaLocation, :certificate_issued_by
13
+
14
+ # Public methods
15
+ def initialize( url: "https://cis.porezna-uprava.hr:8449/FiskalizacijaService",
16
+ key_public_path: nil, key_private_path: nil, certificate_path: nil,
17
+ tns: "http://www.apis-it.hr/fin/2012/types/f73",
18
+ schemaLocation: "http://www.apis-it.hr/fin/2012/types/f73 FiskalizacijaSchema.xsd",
19
+ certificate_issued_by: "OU=RDC,O=FINA,C=HR", certificate_p12_path: nil, password: nil)
20
+ @url = url
21
+ @key_public_path = key_public_path
22
+ @key_private_path = key_private_path
23
+ @certificate_path = certificate_path
24
+ @certificate_p12_path = certificate_p12_path
25
+ @tns = tns
26
+ @schemaLocation = schemaLocation
27
+
28
+ # Import certificates
29
+ export_keys password
30
+
31
+ if @key_public_path != nil && File.exists?(@key_public_path)
32
+ @key_public = OpenSSL::X509::Certificate.new(File.read(@key_public_path))
33
+ end
34
+
35
+ if @key_private_path != nil && File.exists?(@key_private_path)
36
+ @key_private = OpenSSL::PKey::RSA.new(File.read(@key_private_path))
37
+ end
38
+
39
+ if @certificate_path != nil && File.exists?(@certificate_path)
40
+ @certificate = OpenSSL::X509::Certificate.new(File.read(@certificate_path))
41
+ end
42
+ end # new
43
+
44
+ def echo echo=nil, text: "Hello World!"
45
+ # Build echo request
46
+ echo = Fiscalizer::Echo.new text: text if echo == nil
47
+ # Send it
48
+ comm = Fiscalizer::Communication.new url: @url, tns: @tns, schemaLocation: @schemaLocation,
49
+ key_public: @key_public, key_private: @key_private,
50
+ certificate: @certificate, certificate_issued_by: @certificate_issued_by
51
+ raw_response = comm.send echo
52
+ response = Fiscalizer::Response.new object: echo, html_response: raw_response, tns: @tns
53
+ return response
54
+ end # echo
55
+
56
+ def fiscalize_office( office=nil, uuid: nil, time_sent: nil, pin: nil,
57
+ office_label: nil, adress_street_name: nil, adress_house_num: nil,
58
+ adress_house_num_addendum: nil, adress_post_num: nil, adress_settlement: nil,
59
+ adress_township: nil, adress_other: nil, office_time: nil, take_effect_date: nil,
60
+ closure_mark: nil, specific_purpose: nil, reconnect_attempts: 3 )
61
+ # Test connection
62
+ response_alive = echo text: "Is the server alive?"
63
+ recconect_attempted = 1
64
+ reconnect_attempts = 0 if reconnect_attempts < 0
65
+ while recconect_attempted < reconnect_attempts && !response_alive.echo?
66
+ response_alive = echo text: "Is the server alive?"
67
+ recconect_attempted += 1
68
+ end
69
+ if !response_alive.echo?
70
+ response_alive.type = 0
71
+ response_alive.errors['f100'] = "Failed to connect to server"
72
+ return response_alive
73
+ end
74
+ # Build office
75
+ office = Fiscalizer::Office.new( uuid: uuid, time_sent: time_sent, pin: pin,
76
+ office_label: office_label, adress_street_name: adress_street_name, adress_house_num: adress_house_num,
77
+ adress_house_num_addendum: adress_house_num_addendum, adress_post_num: adress_post_num, adress_settlement: adress_settlement,
78
+ adress_township: adress_township, adress_other: adress_other, office_time: office_time, take_effect_date: take_effect_date,
79
+ closure_mark: closure_mark, specific_purpose: specific_purpose) if office == nil
80
+ # Send it
81
+ comm = Fiscalizer::Communication.new url: @url, tns: @tns, schemaLocation: @schemaLocation,
82
+ key_public: @key_public, key_private: @key_private,
83
+ certificate: @certificate, certificate_issued_by: @certificate_issued_by
84
+ raw_response = comm.send office
85
+ response = Fiscalizer::Response.new object: office, html_response: raw_response, tns: @tns
86
+ return response
87
+ end # fiscalize_office
88
+ alias_method :office, :fiscalize_office
89
+ alias_method :fiscalize_office_space, :fiscalize_office
90
+
91
+ def fiscalize_invoice( invoice=nil, uuid: nil, time_sent: nil, pin: nil,
92
+ in_vat_system: nil, time_issued: nil, consistance_mark: nil,
93
+ issued_number: nil, issued_office: nil, issued_machine: nil,
94
+ tax_vat: [], tax_spending: [], tax_other: [],
95
+ value_tax_liberation: nil, value_tax_margin: nil, value_non_taxable: nil,
96
+ fees: [], summed_total: nil, payment_method: nil,
97
+ operator_pin: nil, security_code: nil, subsequent_delivery: nil,
98
+ paragon_label: nil, specific_purpose: nil, unique_identifier: nil,
99
+ automatic: true, reconnect_attempts: 3)
100
+ # Test connection
101
+ response_alive = echo text: "Is the server alive"
102
+ recconect_attempted = 1
103
+ reconnect_attempts = 0 if reconnect_attempts < 0
104
+ while recconect_attempted < reconnect_attempts && !response_alive.echo?
105
+ response_alive = echo text: "Is the server alive"
106
+ recconect_attempted += 1
107
+ end
108
+ if !response_alive.echo?
109
+ response_alive.type = 0
110
+ response_alive.errors['f100'] = "Failed to connect to server"
111
+ return response_alive
112
+ end
113
+ # Build invoice
114
+ invoice = Fiscalizer::Invoice.new( uuid: uuid, time_sent: time_sent, pin: pin,
115
+ in_vat_system: in_vat_system, time_issued: time_issued, consistance_mark: consistance_mark,
116
+ issued_number: issued_number, issued_office: issued_office, issued_machine: issued_machine,
117
+ tax_vat: tax_vat, tax_spending: tax_spending, tax_other: tax_other,
118
+ value_tax_liberation: value_tax_liberation, value_tax_margin: value_tax_margin, value_non_taxable: value_non_taxable,
119
+ fees: fees, summed_total: summed_total, payment_method: payment_method,
120
+ operator_pin: operator_pin, security_code: security_code, subsequent_delivery: subsequent_delivery,
121
+ paragon_label: paragon_label, specific_purpose: specific_purpose, unique_identifier: unique_identifier,
122
+ automatic: automatic) if invoice == nil
123
+ # Send it
124
+ comm = Fiscalizer::Communication.new url: @url, tns: @tns, schemaLocation: @schemaLocation,
125
+ key_public: @key_public, key_private: @key_private,
126
+ certificate: @certificate, certificate_issued_by: @certificate_issued_by
127
+ raw_response = comm.send invoice
128
+ response = Fiscalizer::Response.new object: invoice, html_response: raw_response, tns: @tns
129
+ return response
130
+ end # fiscalize_invoice
131
+ alias_method :invoice, :fiscalize_invoice
132
+
133
+ def certificate_p12_path= path
134
+ @certificate_p12_path = path
135
+ export_keys
136
+ end # certificate_p12_path
137
+
138
+ private
139
+ def export_keys password
140
+ if @certificate_p12_path != nil && File.exists?(@certificate_p12_path) && password != nil
141
+ extracted = OpenSSL::PKCS12.new(File.read(@certificate_p12_path), password)
142
+ @key_public = OpenSSL::X509::Certificate.new(extracted.certificate)
143
+ @key_private = OpenSSL::PKey::RSA.new(extracted.key)
144
+ @certificate = OpenSSL::X509::Certificate.new(extracted.ca_certs.first.to_s) if extracted.ca_certs != nil && extracted.ca_certs.size != 0
145
+ end
146
+ end # export_keys
147
+
148
+ end # FiscalizerRuby
@@ -0,0 +1,190 @@
1
+ require 'fiscalizer/tax'
2
+ require 'fiscalizer/fee'
3
+
4
+ class Fiscalizer
5
+ class Invoice
6
+
7
+ attr_accessor :uuid, :time_sent, :pin,
8
+ :in_vat_system, :time_issued, :consistance_mark,
9
+ :issued_number, :issued_office, :issued_machine,
10
+ :tax_vat, :tax_spending, :tax_other,
11
+ :value_tax_liberation, :value_tax_margin, :value_non_taxable,
12
+ :fees, :summed_total, :payment_method,
13
+ :operator_pin, :security_code, :subsequent_delivery,
14
+ :paragon_label, :specific_purpose, :unique_identifier,
15
+ :automatic, :generated_xml
16
+
17
+ def initialize( uuid: nil, time_sent: nil, pin: nil,
18
+ in_vat_system: nil, time_issued: nil, consistance_mark: nil,
19
+ issued_number: nil, issued_office: nil, issued_machine: nil,
20
+ tax_vat: [], tax_spending: [], tax_other: [],
21
+ value_tax_liberation: nil, value_tax_margin: nil, value_non_taxable: nil,
22
+ fees: [], summed_total: nil, payment_method: nil,
23
+ operator_pin: nil, security_code: nil, subsequent_delivery: nil,
24
+ paragon_label: nil, specific_purpose: nil, unique_identifier: nil,
25
+ automatic: true)
26
+ @uuid = uuid
27
+ @time_sent = time_sent
28
+ @pin = pin
29
+ @in_vat_system = in_vat_system
30
+ @time_issued = time_issued
31
+ @consistance_mark = consistance_mark
32
+ @issued_number = issued_number
33
+ @issued_office = issued_office
34
+ @issued_machine = issued_machine
35
+ @tax_vat = tax_vat
36
+ @tax_spending = tax_spending
37
+ @tax_other = tax_other
38
+ @value_tax_liberation = value_tax_liberation
39
+ @value_tax_margin = value_tax_margin
40
+ @value_non_taxable = value_non_taxable
41
+ @fees = fees
42
+ @summed_total = summed_total
43
+ @payment_method = payment_method
44
+ @operator_pin = operator_pin
45
+ @security_code = security_code
46
+ @subsequent_delivery = subsequent_delivery
47
+ @paragon_label = paragon_label
48
+ @specific_purpose = specific_purpose
49
+ @unique_identifier = unique_identifier
50
+ @automatic = automatic
51
+
52
+ autocomplete_data_set if @automatic
53
+ end # initialize
54
+
55
+ # Add taxes
56
+ def add_tax_vat base: 0.0, rate: 0.0, name: "", tax: nil
57
+ tax = Fiscalizer::Tax.new base: base, rate: rate, name: name if tax == nil
58
+ @tax_vat = Array.new if @tax_vat.class != Array
59
+ @tax_vat << tax
60
+ end # add_tax_vat
61
+
62
+ def add_tax_spending base: 0.0, rate: 0.0, name: "", tax: nil
63
+ tax = Fiscalizer::Tax.new base: base, rate: rate, name: name if tax == nil
64
+ @tax_spending = Array.new if @tax_spending.class != Array
65
+ @tax_spending << tax
66
+ end # add_tax_spending
67
+
68
+ def add_tax_other base: 0.0, rate: 0.0, name: "", tax: nil
69
+ tax = Fiscalizer::Tax.new base: base, rate: rate, name: name if tax == nil
70
+ @tax_other = Array.new if @tax_other.class != Array
71
+ @tax_other << tax
72
+ end # add_tax_spending
73
+
74
+ # Add fees
75
+ def add_fee name: "", value: 0.0, fee: nil
76
+ fee = Fiscalizer::Fee.new name: base, value: rate if fee == nil
77
+ @fee << fee
78
+ end # add_fee
79
+
80
+ # Check if all necessary values are present
81
+ def is_valid
82
+ # Check values
83
+ return false if @uuid == nil
84
+ return false if @time_sent == nil
85
+ return false if @pin == nil
86
+ return false if @in_vat_system == nil
87
+ return false if @time_issued == nil
88
+ return false if @consistance_mark == nil
89
+ return false if @issued_number == nil
90
+ return false if @issued_office == nil
91
+ return false if @issued_machine == nil
92
+ return false if summed_total == nil
93
+ return false if @payment_method == nil
94
+ return false if @operator_pin == nil
95
+ return false if @security_code == nil
96
+ return false if @subsequent_delivery == nil
97
+
98
+ # Check taxes
99
+ tax_vat.each do |tax|
100
+ return false if tax.name == nil || tax.name.class != String
101
+ return false if tax.base == nil || tax.base.class != Float
102
+ return false if tax.rate == nil || tax.rate.class != Float
103
+ end # tax_vat.each
104
+
105
+ tax_spending.each do |tax|
106
+ return false if tax.name == nil || tax.name.class != String
107
+ return false if tax.base == nil || tax.base.class != Float
108
+ return false if tax.rate == nil || tax.rate.class != Float
109
+ end # tax_spending.each
110
+
111
+ tax_other.each do |tax|
112
+ return false if tax.name == nil || tax.name.class != String
113
+ return false if tax.base == nil || tax.base.class != Float
114
+ return false if tax.rate == nil || tax.rate.class != Float
115
+ end # tax_other.each
116
+
117
+ # Check fees
118
+ fees.each do |fee|
119
+ return false if fee.name == nil || fee.name.class != String
120
+ return false if fee.value == nil || fee.value.class != Float
121
+ end # fees.each
122
+
123
+ return true
124
+ end # is_valid
125
+ alias_method :valid?, :is_valid
126
+ alias_method :valdate, :is_valid
127
+
128
+ # Getters
129
+ def time_issued_str separator="T"
130
+ return @time_issued.strftime('%d.%m.%Y') + separator + @time_issued.strftime('%H:%M:%S')
131
+ end # time_issued_str
132
+
133
+ def time_sent_str separator="T"
134
+ return @time_sent.strftime('%d.%m.%Y') + separator + @time_sent.strftime('%H:%M:%S')
135
+ end # time_sent_str
136
+
137
+ def summed_total
138
+ return @summed_total if @summed_total != nil
139
+ total = 0.0
140
+ tax_vat.each do |tax|
141
+ total += tax.summed
142
+ end
143
+ tax_spending.each do |tax|
144
+ total += tax.summed
145
+ end
146
+ tax_other.each do |tax|
147
+ total += tax.summed
148
+ end
149
+ return total.round(2)
150
+ end # summed_total
151
+
152
+ def summed_total_str
153
+ return ("%15.2f" % summed_total).strip
154
+ end # summed_total_str
155
+
156
+ def payment_method
157
+ return "G" if @payment_method[0].downcase == "g"
158
+ return "K" if @payment_method[0].downcase == "k"
159
+ return "C" if @payment_method[0].downcase == "c"
160
+ return "T" if @payment_method[0].downcase == "t"
161
+ return "O" if @payment_method[0].downcase == "o"
162
+ raise "Invalid payment method type!"
163
+ end # payment_method
164
+
165
+ def consistance_mark
166
+ return @consistance_mark.upcase
167
+ end # consistance_mark
168
+
169
+ def value_tax_liberation_str
170
+ return nil if @value_tax_liberation == nil
171
+ return ("%15.2f" % @value_tax_liberation.round(2)).strip
172
+ end # value_tax_liberation_str
173
+
174
+ def value_tax_margin_str
175
+ return nil if @value_tax_margin == nil
176
+ return ("%15.2f" % @value_tax_margin.round(2)).strip
177
+ end # value_tax_margin_str
178
+
179
+ def value_non_taxable_str
180
+ return nil if @value_non_taxable == nil
181
+ return ("%15.2f" % @value_non_taxable.round(2)).strip
182
+ end # value_non_taxable_str
183
+
184
+
185
+ # Helpers
186
+ def autocomplete_data_set
187
+ end # autocomplete_data_set
188
+
189
+ end # Invoice
190
+ end # Fiscalizer
@@ -0,0 +1,66 @@
1
+ class Fiscalizer
2
+ class Office
3
+
4
+ attr_accessor :uuid, :time_sent, :pin,
5
+ :office_label, :adress_street_name, :adress_house_num,
6
+ :adress_house_num_addendum, :adress_post_num, :adress_settlement,
7
+ :adress_township, :adress_other, :office_time,
8
+ :take_effect_date, :closure_mark, :specific_purpose,
9
+ :generated_xml
10
+
11
+ def initialize( uuid: nil, time_sent: nil, pin: nil,
12
+ office_label: nil, adress_street_name: nil, adress_house_num: nil,
13
+ adress_house_num_addendum: nil, adress_post_num: nil, adress_settlement: nil,
14
+ adress_township: nil, adress_other: nil, office_time: nil, take_effect_date: nil,
15
+ closure_mark: nil, specific_purpose: nil)
16
+ @uuid = uuid
17
+ @time_sent = time_sent
18
+ @pin = pin
19
+ @office_label = office_label
20
+ @adress_street_name = adress_street_name
21
+ @adress_house_num = adress_house_num
22
+ @adress_house_num_addendum = adress_house_num_addendum
23
+ @adress_post_num = adress_post_num
24
+ @adress_settlement = adress_settlement
25
+ @adress_township = adress_township
26
+ @adress_other = adress_other
27
+ @office_time = office_time
28
+ @take_effect_date = take_effect_date
29
+ @closure_mark = closure_mark
30
+ @specific_purpose = specific_purpose
31
+
32
+ end # initialize
33
+
34
+ # Getters
35
+ def time_sent_str separator="T"
36
+ return @time_sent.strftime('%d.%m.%Y') + separator + @time_sent.strftime('%H:%M:%S')
37
+ end # time_issued_str
38
+
39
+ def take_effect_date_str
40
+ return @take_effect_date.strftime('%d.%m.%Y')
41
+ end # time_sent_str
42
+
43
+ def is_valid
44
+ # Check values
45
+ return false if @uuid == nil
46
+ return false if @time_sent == nil
47
+ return false if @pin == nil
48
+ return false if @office_label == nil
49
+ return false if @office_time == nil
50
+ return false if @take_effect_date == nil
51
+ # Check adress
52
+ if @adress_other == nil
53
+ return false if @adress_street_name == nil
54
+ return false if @adress_house_num == nil
55
+ return false if @adress_house_num_addendum == nil
56
+ return false if @adress_post_num == nil
57
+ return false if @adress_settlement == nil
58
+ return false if @adress_township == nil
59
+ end
60
+ return true
61
+ end # is_valid
62
+ alias_method :valid?, :is_valid
63
+ alias_method :valdate, :is_valid
64
+
65
+ end # Office
66
+ end # Fiscalizer
@@ -0,0 +1,124 @@
1
+ require 'fiscalizer/echo'
2
+ require 'fiscalizer/office'
3
+ require 'fiscalizer/invoice'
4
+
5
+ class Fiscalizer
6
+ class Response
7
+
8
+ attr_accessor :type, :errors, :object,
9
+ :uuid, :processed_at, :response,
10
+ :unique_identifier, :tns, :html_response
11
+
12
+ def initialize( type: 0, errors: {}, object: nil, html_response: nil,
13
+ tns: "http://www.apis-it.hr/fin/2012/types/f73", automatic: true)
14
+ # Save
15
+ @type = type
16
+ @errors = errors
17
+ @object = object
18
+ @uuid = uuid
19
+ @processed_at = processed_at
20
+ @response = response
21
+ @unique_identifier = unique_identifier
22
+ @tns = tns
23
+ @html_response = html_response
24
+
25
+ if automatic && @object != nil
26
+ @type = 0
27
+ @type = 1 if @object.class == Echo
28
+ @type = 2 if @object.class == Office
29
+ @type = 3 if @object.class == Invoice
30
+ end
31
+
32
+ # Automatically fill
33
+ parse_response @html_response.body if @html_response != nil && automatic
34
+ end # initialize
35
+
36
+ def generated_xml
37
+ return @object.generated_xml if @object != nil && @object.respond_to?(:generated_xml)
38
+ return nil
39
+ end # generated_xml
40
+
41
+ def has_error
42
+ return true if @errors.count > 0
43
+ return false
44
+ end # has_error
45
+ alias_method :errors?, :has_error
46
+
47
+ def error_codes
48
+ return errors.keys
49
+ end # error_keys
50
+
51
+ def error_messages
52
+ return errors.values
53
+ end # error_messages
54
+
55
+ def type_str
56
+ if @type == 0
57
+ return "Error"
58
+ elsif @type == 1
59
+ return "Echo"
60
+ elsif @type == 2
61
+ return "Office"
62
+ elsif @type == 3
63
+ return "Invoice"
64
+ end
65
+ return "Unknown"
66
+ end # type_str
67
+
68
+ def echo_succeeded
69
+ return false if @object == nil
70
+ parse_response_echo @html_response.body if @response == nil && @html_response != nil
71
+ return false if @response == nil
72
+ return true if @object.text == @response
73
+ return false
74
+ end
75
+ alias_method :echo?, :echo_succeeded
76
+
77
+
78
+ private
79
+ def parse_response object
80
+ return nil if object == nil || object.class != String
81
+ if @type == 1
82
+ parse_response_echo object
83
+ elsif @type == 2
84
+ parse_response_office object
85
+ elsif @type == 3
86
+ parse_response_invoice object
87
+ end
88
+ parse_response_errors object
89
+ end # parse_response
90
+
91
+ def parse_response_echo object
92
+ @response = Nokogiri::XML(object).root.xpath('//tns:EchoResponse', 'tns' => @tns).first
93
+ @response = @response.text if @response != nil
94
+ end # parse_response_echo
95
+
96
+ def parse_response_office object
97
+ @uuid = Nokogiri::XML(object).root.xpath('//tns:IdPoruke', 'tns' => @tns).first
98
+ @processed_at = Nokogiri::XML(object).root.xpath('//tns:DatumVrijeme', 'tns' => @tns).first
99
+ @uuid = @uuid.text if @uuid != nil
100
+ @processed_at = @processed_at.text if @processed_at != nil
101
+ end # parse_response_office
102
+
103
+ def parse_response_invoice object
104
+ @uuid = Nokogiri::XML(object).root.xpath('//tns:IdPoruke', 'tns' => @tns).first
105
+ @processed_at = Nokogiri::XML(object).root.xpath('//tns:DatumVrijeme', 'tns' => @tns).first
106
+ @unique_identifier = Nokogiri::XML(object).root.xpath('//tns:Jir', 'tns' => @tns).first
107
+ @uuid = @uuid.text if @uuid != nil
108
+ @processed_at = @processed_at.text if @processed_at != nil
109
+ @unique_identifier = @unique_identifier.text if @unique_identifier != nil
110
+ end # parse_response_office
111
+
112
+ def parse_response_errors object
113
+ raw_errors = Nokogiri::XML(object).root.xpath('//tns:Greske', 'tns' => @tns)
114
+ raw_errors.each do |raw_error|
115
+ error_code = raw_error.xpath('//tns:SifraGreske', 'tns' => @tns).first
116
+ error_message = raw_error.xpath('//tns:PorukaGreske', 'tns' => @tns).first
117
+ error_code = error_code.text.strip if error_code != nil
118
+ error_message = error_message.text.strip if error_message != nil
119
+ @errors[error_code] = error_message if error_code != nil
120
+ end
121
+ end
122
+
123
+ end # Response
124
+ end # Fiscalizer