polish_invoicer 0.0.1

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.
@@ -0,0 +1,36 @@
1
+ module PolishInvoicer
2
+ class Vat
3
+ def self.rates
4
+ [23, 8, 5, 0, -1] # -1 oznacza zwolniony z VAT
5
+ end
6
+
7
+ def self.valid?(rate)
8
+ rates.include?(rate)
9
+ end
10
+
11
+ # Czy stawka VAT to "zwolniony"?
12
+ def self.zw?(rate)
13
+ rate == -1
14
+ end
15
+
16
+ def self.to_s(rate)
17
+ hash.invert[rate]
18
+ end
19
+
20
+ # Potrzebne do obliczeń netto/vat/brutto
21
+ def self.to_i(rate)
22
+ (rate != -1) ? rate : 0
23
+ end
24
+
25
+ protected
26
+ def self.hash
27
+ h = {}
28
+ rates.each do |r|
29
+ name = "#{r}%"
30
+ name = 'zw.' if r == -1
31
+ h[name] = r
32
+ end
33
+ h
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,3 @@
1
+ module PolishInvoicer
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,34 @@
1
+ module PolishInvoicer
2
+ class Writer
3
+ attr_accessor :invoice, :template_path
4
+ attr_accessor :logger, :wkhtmltopdf_command
5
+
6
+ def initialize(invoice)
7
+ @invoice = invoice
8
+ default_template_path = File.expand_path('../../../tpl/invoice.slim', __FILE__)
9
+ @template_path = @invoice.template_path || default_template_path
10
+ @logger = @invoice.logger
11
+ @wkhtmltopdf_command = @invoice.wkhtmltopdf_command
12
+ end
13
+
14
+ def save_to_html(path)
15
+ create_writer
16
+ @writer.save_to_html(path)
17
+ end
18
+
19
+ def save_to_pdf(path)
20
+ create_writer
21
+ @writer.save_to_pdf(path)
22
+ end
23
+
24
+ protected
25
+ def create_writer
26
+ @writer = Slim2pdf::Writer.new(template_path)
27
+ @writer.wkhtmltopdf_command = wkhtmltopdf_command
28
+ @writer.logger = logger
29
+ data = @invoice.to_hash
30
+ @writer.data = data
31
+ @writer.footer_text = data[:footer]
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'polish_invoicer/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "polish_invoicer"
8
+ spec.version = PolishInvoicer::VERSION
9
+ spec.authors = ["Piotr Macuk"]
10
+ spec.email = ["piotr@macuk.pl"]
11
+ spec.description = %q{Creates polish invoices and proforms as HTML or PDF files}
12
+ spec.summary = %q{Creates polish invoices and proforms as HTML or PDF files}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "simplecov"
24
+
25
+ spec.add_dependency 'slim2pdf', '~> 0.0.2'
26
+ end
@@ -0,0 +1,115 @@
1
+ # encoding: utf-8
2
+ require 'test_helper'
3
+
4
+ module PolishInvoicer
5
+ class InvoiceTest < MiniTest::Unit::TestCase
6
+ def test_init
7
+ i = Invoice.new
8
+ assert i.is_a?(Invoice)
9
+ end
10
+
11
+ def test_set_available_param
12
+ i = Invoice.new({number: '1/2014'})
13
+ assert_equal '1/2014', i.number
14
+ end
15
+
16
+ def test_set_unavailable_param
17
+ assert_raises(RuntimeError) { i = Invoice.new({test: 'abc'}) }
18
+ end
19
+
20
+ def test_validation_delegation
21
+ i = Invoice.new
22
+ assert_equal false, i.valid?
23
+ assert i.errors[:number]
24
+ i.number = '1/2014'
25
+ i.valid?
26
+ assert_nil i.errors[:number]
27
+ end
28
+
29
+ def test_net_value
30
+ i = Invoice.new({price: 123.45, gross_price: false, vat: 23})
31
+ assert_in_delta 123.45, i.net_value, 0.01
32
+ i.gross_price = true
33
+ assert_in_delta 100.37, i.net_value, 0.01
34
+ i.vat = 0
35
+ assert_in_delta 123.45, i.net_value, 0.01
36
+ i.vat = -1
37
+ assert_in_delta 123.45, i.net_value, 0.01
38
+ i.gross_price = false
39
+ i.vat = 0
40
+ assert_in_delta 123.45, i.net_value, 0.01
41
+ i.vat = -1
42
+ assert_in_delta 123.45, i.net_value, 0.01
43
+ end
44
+
45
+ def test_vat_value
46
+ i = Invoice.new({price: 123.45, gross_price: false, vat: 23})
47
+ assert_in_delta 28.39, i.vat_value, 0.01
48
+ i.gross_price = true
49
+ assert_in_delta 23.08, i.vat_value, 0.01
50
+ i.vat = 0
51
+ assert_equal 0.00, i.vat_value
52
+ i.vat = -1
53
+ assert_equal 0.00, i.vat_value
54
+ end
55
+
56
+ def test_gross_value
57
+ i = Invoice.new({price: 123.45, gross_price: false, vat: 23})
58
+ assert_in_delta 151.84, i.gross_value, 0.01
59
+ i.gross_price = true
60
+ assert_in_delta 123.45, i.gross_value, 0.01
61
+ i.vat = 0
62
+ assert_in_delta 123.45, i.gross_value, 0.01
63
+ i.vat = -1
64
+ assert_in_delta 123.45, i.gross_value, 0.01
65
+ i.gross_price = false
66
+ i.vat = 0
67
+ assert_in_delta 123.45, i.gross_value, 0.01
68
+ i.vat = -1
69
+ assert_in_delta 123.45, i.gross_value, 0.01
70
+ end
71
+
72
+ def test_defaults
73
+ i = Invoice.new
74
+ assert i.gross_price
75
+ assert 23, i.vat
76
+ assert 'Przelew', i.payment_type
77
+ assert i.paid
78
+ assert_equal false, i.proforma
79
+ end
80
+
81
+ def test_raise_when_save_to_html_and_not_valid
82
+ i = Invoice.new
83
+ assert_raises(RuntimeError) { i.save_to_html('/tmp/test.html') }
84
+ end
85
+
86
+ def test_raise_when_save_to_pdf_and_not_valid
87
+ i = Invoice.new
88
+ assert_raises(RuntimeError) { i.save_to_pdf('/tmp/test.pdf') }
89
+ end
90
+
91
+ def test_save_to_html
92
+ i = create_valid_invoice
93
+ path = '/tmp/test.html'
94
+ i.save_to_html(path)
95
+ assert File.exists?(path)
96
+ File.unlink(path)
97
+ end
98
+
99
+ def test_save_to_pdf
100
+ i = create_valid_invoice
101
+ path = '/tmp/test.pdf'
102
+ i.save_to_pdf(path)
103
+ assert File.exists?(path)
104
+ File.unlink(path)
105
+ end
106
+
107
+ def test_to_hash
108
+ i = Invoice.new({price: 123.45, gross_price: false})
109
+ h = i.to_hash
110
+ assert h[:paid] # default
111
+ assert_equal false, h[:gross_price] # params
112
+ assert_equal '123,45', h[:net_value] # presenter
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,56 @@
1
+ # encoding: utf-8
2
+ require 'test_helper'
3
+
4
+ module PolishInvoicer
5
+ class PresenterTest < MiniTest::Unit::TestCase
6
+ require 'ostruct'
7
+
8
+ def setup
9
+ @invoice = OpenStruct.new
10
+ end
11
+
12
+ def test_format_dates
13
+ @invoice.trade_date = Date.parse('2014-01-01')
14
+ @invoice.create_date = Date.parse('2014-01-15')
15
+ @invoice.payment_date = Date.parse('2014-01-30')
16
+ data = Presenter.new(@invoice).data
17
+ assert_equal '01.01.2014', data[:trade_date]
18
+ assert_equal '15.01.2014', data[:create_date]
19
+ assert_equal '30.01.2014', data[:payment_date]
20
+ end
21
+
22
+ def test_format_prices
23
+ @invoice.net_value = 123.4567
24
+ @invoice.vat_value = 23.9876
25
+ @invoice.gross_value = 456.3378
26
+ data = Presenter.new(@invoice).data
27
+ assert_equal '123,46', data[:net_value]
28
+ assert_equal '23,99', data[:vat_value]
29
+ assert_equal '456,34', data[:gross_value]
30
+ end
31
+
32
+ def test_format_comments
33
+ @invoice.comments = nil
34
+ data = Presenter.new(@invoice).data
35
+ assert_equal [], data[:comments]
36
+ @invoice.comments = 'Test'
37
+ data = Presenter.new(@invoice).data
38
+ assert_equal ['Test'], data[:comments]
39
+ @invoice.comments = ['A', 'B']
40
+ data = Presenter.new(@invoice).data
41
+ assert_equal ['A', 'B'], data[:comments]
42
+ end
43
+
44
+ def test_vat
45
+ @invoice.vat = 23
46
+ data = Presenter.new(@invoice).data
47
+ assert_equal '23%', data[:vat]
48
+ @invoice.vat = 0
49
+ data = Presenter.new(@invoice).data
50
+ assert_equal '0%', data[:vat]
51
+ @invoice.vat = -1
52
+ data = Presenter.new(@invoice).data
53
+ assert_equal 'zw.', data[:vat]
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,19 @@
1
+ require 'simplecov'
2
+ SimpleCov.start do
3
+ add_filter '/test/'
4
+ end
5
+
6
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
7
+ require 'polish_invoicer'
8
+ require 'minitest/autorun'
9
+
10
+ def create_valid_invoice
11
+ invoice = PolishInvoicer::Invoice.new({
12
+ number: '1/2014', create_date: Date.today, trade_date: Date.today,
13
+ seller: ['Seller'], buyer: ['Buyer'],
14
+ seller_nip: '123-123-22-33', buyer_nip: '554-333-22-11',
15
+ item_name: 'Title', price: 123.45, payment_date: Date.today
16
+ })
17
+ assert invoice.valid?
18
+ invoice
19
+ end
@@ -0,0 +1,176 @@
1
+ require 'test_helper'
2
+
3
+ module PolishInvoicer
4
+ class ValidatorTest < MiniTest::Unit::TestCase
5
+ require 'ostruct'
6
+
7
+ def setup
8
+ @invoice = OpenStruct.new
9
+ end
10
+
11
+ def check_error(field, value=nil)
12
+ @invoice.send("#{field}=", value)
13
+ v = Validator.new(@invoice)
14
+ v.valid?
15
+ assert v.errors[field]
16
+ end
17
+
18
+ def check_ok(field, value=nil)
19
+ @invoice.send("#{field}=", value)
20
+ v = Validator.new(@invoice)
21
+ v.valid?
22
+ assert_nil v.errors[field]
23
+ end
24
+
25
+ def test_number_validation
26
+ check_error(:number)
27
+ check_ok(:number, '1/2014')
28
+ end
29
+
30
+ def test_create_date_validation
31
+ check_error(:create_date)
32
+ check_error(:create_date, 'test')
33
+ check_error(:create_date, 100)
34
+ check_error(:create_date, '2014-01-01')
35
+ check_ok(:create_date, Date.parse('2014-01-01'))
36
+ end
37
+
38
+ def test_trade_date_validation
39
+ check_error(:trade_date)
40
+ check_error(:trade_date, 'test')
41
+ check_error(:trade_date, 100)
42
+ check_error(:trade_date, '2014-01-01')
43
+ check_ok(:trade_date, Date.parse('2014-01-01'))
44
+ end
45
+
46
+ def test_seller_validation
47
+ check_error(:seller)
48
+ check_error(:seller, 'test')
49
+ check_ok(:seller, ['Jan Nowak', 'Gdynia'])
50
+ end
51
+
52
+ def test_buyer_validation
53
+ check_error(:buyer)
54
+ check_error(:buyer, 'test')
55
+ check_ok(:buyer, ['Jan Nowak', 'Gdynia'])
56
+ end
57
+
58
+ def test_item_name_validation
59
+ check_error(:item_name)
60
+ check_ok(:item_name, 'test')
61
+ end
62
+
63
+ def test_price_validation
64
+ check_error(:price)
65
+ check_error(:price, 'test')
66
+ check_error(:price, '100')
67
+ check_error(:price, -10)
68
+ check_ok(:price, 19.99)
69
+ end
70
+
71
+ def test_gross_price_validation
72
+ check_error(:gross_price)
73
+ check_error(:gross_price, 'test')
74
+ check_ok(:gross_price, true)
75
+ check_ok(:gross_price, false)
76
+ end
77
+
78
+ def test_vat_validation
79
+ check_error(:vat)
80
+ check_error(:vat, '23')
81
+ check_error(:vat, 100)
82
+ check_ok(:vat, 8)
83
+ check_ok(:vat, -1)
84
+ end
85
+
86
+ def test_payment_type_validation
87
+ check_error(:payment_type)
88
+ check_ok(:payment_type, 'Przelew')
89
+ end
90
+
91
+ def test_payment_date_validation
92
+ check_error(:payment_date)
93
+ check_error(:payment_date, 'test')
94
+ check_error(:payment_date, 100)
95
+ check_error(:payment_date, '2014-01-01')
96
+ check_ok(:payment_date, Date.parse('2014-01-01'))
97
+ end
98
+
99
+ def test_paid_validation
100
+ check_error(:paid)
101
+ check_error(:paid, 'test')
102
+ check_ok(:paid, true)
103
+ check_ok(:paid, false)
104
+ end
105
+
106
+ def test_proforma_validation
107
+ check_error(:proforma)
108
+ check_error(:proforma, 'test')
109
+ check_ok(:proforma, true)
110
+ check_ok(:proforma, false)
111
+ end
112
+
113
+ def test_proforma_could_not_be_paid
114
+ @invoice.paid = true
115
+ @invoice.proforma = true
116
+ v = Validator.new(@invoice)
117
+ v.valid?
118
+ assert v.errors[:paid]
119
+ @invoice.paid = false
120
+ v = Validator.new(@invoice)
121
+ v.valid?
122
+ assert_nil v.errors[:paid]
123
+ end
124
+
125
+ def test_seller_and_buyer_nip_presence
126
+ check_error(:seller_nip)
127
+ check_error(:buyer_nip)
128
+ check_ok(:seller_nip, '123')
129
+ check_ok(:buyer_nip, '123')
130
+ end
131
+
132
+ def check_dates_ok(create_date, trade_date, msg=nil)
133
+ @invoice.create_date = Date.parse(create_date)
134
+ @invoice.trade_date = Date.parse(trade_date)
135
+ v = Validator.new(@invoice); v.valid?
136
+ assert_nil v.errors[:create_date], msg
137
+ end
138
+
139
+ def check_dates_error(create_date, trade_date, msg=nil)
140
+ @invoice.create_date = Date.parse(create_date)
141
+ @invoice.trade_date = Date.parse(trade_date)
142
+ v = Validator.new(@invoice); v.valid?
143
+ assert v.errors[:create_date], msg
144
+ end
145
+
146
+ # data wystawienia max 30 dni przed wykonaniem usługi
147
+ def test_create_and_trade_date_correlation_before_trade
148
+ check_dates_ok('2014-01-01', '2014-01-01', 'B1')
149
+ check_dates_ok('2014-01-01', '2014-01-31', 'B2')
150
+ check_dates_error('2014-01-01', '2014-02-01', 'B3')
151
+ check_dates_ok('2014-01-02', '2014-02-01', 'B4')
152
+ end
153
+
154
+ # data wystawienie max 15 dnia następnego miesiąca po wykonaniu usługi
155
+ def test_create_and_trade_date_correlation_after_trade
156
+ check_dates_ok('2014-02-15', '2014-01-01', 'A1')
157
+ check_dates_error('2014-02-16', '2014-01-01', 'A2')
158
+ check_dates_error('2014-02-16', '2014-01-02', 'A3')
159
+ check_dates_error('2014-02-16', '2014-01-31', 'A4')
160
+ check_dates_ok('2014-02-15', '2014-01-31', 'A5')
161
+ check_dates_ok('2014-03-15', '2014-02-15', 'A6')
162
+ end
163
+
164
+ def test_no_vat_reason_presence
165
+ @invoice.vat = 23
166
+ v = Validator.new(@invoice); v.valid?
167
+ assert_nil v.errors[:no_vat_reason]
168
+ @invoice.vat = -1
169
+ v = Validator.new(@invoice); v.valid?
170
+ assert v.errors[:no_vat_reason]
171
+ @invoice.no_vat_reason = 'reason'
172
+ v = Validator.new(@invoice); v.valid?
173
+ assert_nil v.errors[:no_vat_reason]
174
+ end
175
+ end
176
+ end