polish_invoicer 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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