polish_invoicer 0.0.21 → 0.0.26

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: bda191d866cc449891ddda539f7d4488596ce329
4
- data.tar.gz: ac4b56ac399d2605d877ed5e8cb9edc80ae9191b
2
+ SHA256:
3
+ metadata.gz: 802e9cbe1c6b7ab58930b191e60ccab3655e9eb53b21d04eb657af483cca946b
4
+ data.tar.gz: 5b352fff7ac09baa01e2b8120b18fd4e665e507c5887266b6fe355e5f0285c9d
5
5
  SHA512:
6
- metadata.gz: 4c1b33a78b3da1dc507ea771709ffb1411ba230d89fd7cd03c920cdbcb4aded9613c374267bb29689364ef3db5f450c1e74c29044a1cc562097838c6e6c40b2c
7
- data.tar.gz: 95ffbb8601037dda21507c02285beb0c78301815babdcfed0e2069be11ca08e2d27f17e9aecf9bd257252b763b29470c17db5ffb6343c56deb498f3fe603eeda
6
+ metadata.gz: 86879c72be1a1e96e436863823192e00b933db64a9f9e2389a065bdb6211c87b2fd2cdacbc6e82aef44e9b582436199eceea73ade75cfc3d8e0fc1ad3b4f2c2a
7
+ data.tar.gz: 06bebb6a1a4743d5cb607332697d4b7bfbc80b7639c235358e363d356a0b3a63ae89892eaaafcc089f367925f98ad29f3e77f2ff4086062ab382cc9bd79ba945
data/.travis.yml CHANGED
@@ -1,6 +1,5 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.2.10
4
- - 2.3.7
5
- - 2.4.4
6
- - 2.5.1
3
+ - 2.5.8
4
+ - 2.6.6
5
+ - 2.7.2
data/README.md CHANGED
@@ -108,6 +108,7 @@ invoice.save_to_pdf('/path/to/invoice.pdf')
108
108
  :pkwiu, # numer PKWiU (string)
109
109
  :no_vat_reason, # podstawa prawna zwolnienia z VAT (string)
110
110
  :footer, # treść umieszczana w stopce faktury (string)
111
+ :price_paid, # kwota częściowego opłacenia faktury w złotych (float)
111
112
 
112
113
  ### Parametry systemowe
113
114
 
@@ -11,6 +11,7 @@ module PolishInvoicer
11
11
  :recipient, # odbiorca faktury (tablica stringów)
12
12
  :item_name, # nazwa usługi (string)
13
13
  :price, # cena w złotych (float)
14
+ :price_paid, # kwota częściowego opłacenia faktury w złotych
14
15
  :gross_price, # znacznik rodzaju ceny (netto/brutto), domyślnie: true (boolean)
15
16
  :vat, # stawka vat, domyślnie: 23 (integer)
16
17
  :pkwiu, # numer PKWiU (string)
@@ -22,6 +23,10 @@ module PolishInvoicer
22
23
  :proforma, # znacznik faktury pro-forma, domyślnie: false (boolean)
23
24
  :no_vat_reason, # podstawa prawna zwolnienia z VAT (string)
24
25
  :foreign_buyer, # nabywcą jest firma spoza Polski, domyślnie: false (boolean)
26
+ :lang, # język na fakturze, domyślnie: zależny od ustawienia foreign_buyer
27
+ # foreign_buyer = false => lang = 'pl'
28
+ # foreign_buyer = true => lang = 'pl_en'
29
+ # możliwe wartości: pl | pl_en | en
25
30
  :reverse_charge, # faktura z odwrotnym obciążeniem VAT
26
31
  :currency, # waluta rozliczeniowa, domyślnie: PLN (string)
27
32
  :exchange_rate # kurs waluty rozliczeniowej, domyślnie: 1.0000 (float)
@@ -80,6 +85,30 @@ module PolishInvoicer
80
85
  Presenter.new(self).data
81
86
  end
82
87
 
88
+ def exchanged_tax
89
+ (vat_value * exchange_rate)
90
+ end
91
+
92
+ def total_to_pay_value
93
+ reverse_charge ? net_value : gross_value
94
+ end
95
+
96
+ def paid_value
97
+ paid ? total_to_pay_value : price_paid.to_f
98
+ end
99
+
100
+ def to_pay_value
101
+ paid ? 0 : (total_to_pay_value - price_paid.to_f)
102
+ end
103
+
104
+ def template_lang
105
+ lang || (foreign_buyer ? 'pl_en' : 'pl')
106
+ end
107
+
108
+ def template_file
109
+ proforma ? "proforma-#{template_lang}.slim" : "invoice-#{template_lang}.slim"
110
+ end
111
+
83
112
  private
84
113
 
85
114
  def set_defaults
@@ -31,7 +31,7 @@ module PolishInvoicer
31
31
  end
32
32
 
33
33
  def copy_additional_params
34
- %w[net_value vat_value gross_value].each do |field|
34
+ %w[net_value vat_value gross_value exchanged_tax].each do |field|
35
35
  @out[field.to_sym] = @invoice.send(field)
36
36
  end
37
37
  end
@@ -45,7 +45,7 @@ module PolishInvoicer
45
45
  end
46
46
 
47
47
  def format_prices
48
- %w[net_value vat_value gross_value].each do |field|
48
+ %w[net_value vat_value gross_value exchanged_tax total_to_pay_value paid_value to_pay_value].each do |field|
49
49
  v = @invoice.send(field)
50
50
  next unless v
51
51
  @out[field.to_sym] = sprintf('%02.2f', v).tr('.', ',')
@@ -15,10 +15,12 @@ module PolishInvoicer
15
15
  check_arrays
16
16
  check_booleans
17
17
  check_price
18
+ check_price_paid
18
19
  check_vat
19
20
  check_proforma
20
21
  check_create_and_payment_date
21
22
  check_currency
23
+ check_lang
22
24
  @errors.empty?
23
25
  end
24
26
 
@@ -82,6 +84,18 @@ module PolishInvoicer
82
84
  end
83
85
  end
84
86
 
87
+ def check_price_paid
88
+ return if @invoice.price_paid.nil?
89
+ return if @invoice.price.nil?
90
+
91
+ if @invoice.price_paid.is_a?(Numeric)
92
+ @errors[:price_paid] = 'Kwota zapłacona musi być liczbą dodatnią' unless @invoice.price_paid >= 0
93
+ @errors[:price_paid] = 'Kwota zapłacona musi być mniejsza lub równa cenie' unless @invoice.price_paid <= @invoice.price
94
+ else
95
+ @errors[:price_paid] = 'Kwota zapłacona musi być liczbą'
96
+ end
97
+ end
98
+
85
99
  def check_vat
86
100
  if Vat.valid?(@invoice.vat)
87
101
  if Vat.zw?(@invoice.vat) && blank?(@invoice.no_vat_reason)
@@ -111,6 +125,13 @@ module PolishInvoicer
111
125
  @errors[:currency] = 'Nieznana waluta'
112
126
  end
113
127
 
128
+ def check_lang
129
+ return if blank?(@invoice.lang)
130
+ return if %w[pl pl_en en].include?(@invoice.lang)
131
+
132
+ @errors[:lang] = 'Nieznany język'
133
+ end
134
+
114
135
  def blank?(value)
115
136
  value.to_s.strip == ''
116
137
  end
@@ -1,3 +1,3 @@
1
1
  module PolishInvoicer
2
- VERSION = '0.0.21'.freeze
2
+ VERSION = '0.0.26'.freeze
3
3
  end
@@ -21,11 +21,7 @@ module PolishInvoicer
21
21
  end
22
22
 
23
23
  def template_path
24
- tpl = if invoice.proforma
25
- invoice.foreign_buyer ? 'proforma-en.slim' : 'proforma.slim'
26
- else
27
- invoice.foreign_buyer ? 'invoice-en.slim' : 'invoice.slim'
28
- end
24
+ tpl = invoice.template_file
29
25
  invoice.template_path || File.expand_path("../../../tpl/#{tpl}", __FILE__)
30
26
  end
31
27
 
data/test/invoice_test.rb CHANGED
@@ -133,5 +133,97 @@ module PolishInvoicer
133
133
  assert_equal false, h[:gross_price] # params
134
134
  assert_equal '123,45', h[:net_value] # presenter
135
135
  end
136
+
137
+ def test_total_to_pay_value
138
+ assert_equal 123, Invoice.new(price: 123).paid_value
139
+ assert_equal 100, Invoice.new(price: 123, reverse_charge: true).paid_value
140
+ end
141
+
142
+ def test_paid_value
143
+ assert_equal 123, Invoice.new(price: 123).paid_value
144
+ assert_equal 123, Invoice.new(price: 123, price_paid: 100).paid_value
145
+ assert_equal 0, Invoice.new(price: 123, paid: false).paid_value
146
+ assert_equal 100, Invoice.new(price: 123, paid: false, price_paid: 100).paid_value
147
+ assert_equal 100, Invoice.new(price: 123, gross_price: false, paid: false, price_paid: 100).paid_value
148
+ assert_equal 100, Invoice.new(price: 123, reverse_charge: true, paid: false, price_paid: 100).paid_value
149
+ end
150
+
151
+ def test_to_pay_value
152
+ assert_equal 0, Invoice.new(price: 123).to_pay_value
153
+ assert_equal 0, Invoice.new(price: 123, price_paid: 100).to_pay_value
154
+ assert_equal 123, Invoice.new(price: 123, paid: false).to_pay_value
155
+ assert_equal 23, Invoice.new(price: 123, paid: false, price_paid: 100).to_pay_value
156
+ assert_equal 23, Invoice.new(price: 100, gross_price: false, paid: false, price_paid: 100).to_pay_value
157
+ assert_equal 50, Invoice.new(price: 123, reverse_charge: true, paid: false, price_paid: 50).to_pay_value
158
+ end
159
+
160
+ def test_gross_and_net_price
161
+ gross_invoice = Invoice.new(price: 123, price_paid: 60, paid: false)
162
+ assert_equal 100, gross_invoice.net_value
163
+ assert_equal 23, gross_invoice.vat_value
164
+ assert_equal 123, gross_invoice.gross_value
165
+ assert_equal 123, gross_invoice.total_to_pay_value
166
+ assert_equal 60, gross_invoice.paid_value
167
+ assert_equal 63, gross_invoice.to_pay_value
168
+
169
+ net_invoice = Invoice.new(price: 100, price_paid: 60, paid: false, gross_price: false)
170
+ assert_equal 100, net_invoice.net_value
171
+ assert_equal 23, net_invoice.vat_value
172
+ assert_equal 123, net_invoice.gross_value
173
+ assert_equal 123, net_invoice.total_to_pay_value
174
+ assert_equal 60, net_invoice.paid_value
175
+ assert_equal 63, net_invoice.to_pay_value
176
+ end
177
+
178
+ def test_reverse_charge
179
+ gross_invoice = Invoice.new(price: 123, price_paid: 60, paid: false, reverse_charge: true)
180
+ assert_equal 100, gross_invoice.net_value
181
+ assert_equal 23, gross_invoice.vat_value
182
+ assert_equal 123, gross_invoice.gross_value
183
+ assert_equal 100, gross_invoice.total_to_pay_value
184
+ assert_equal 60, gross_invoice.paid_value
185
+ assert_equal 40, gross_invoice.to_pay_value
186
+
187
+ net_invoice = Invoice.new(price: 100, price_paid: 60, paid: false, gross_price: false, reverse_charge: true)
188
+ assert_equal 100, net_invoice.net_value
189
+ assert_equal 23, net_invoice.vat_value
190
+ assert_equal 123, net_invoice.gross_value
191
+ assert_equal 100, net_invoice.total_to_pay_value
192
+ assert_equal 60, net_invoice.paid_value
193
+ assert_equal 40, net_invoice.to_pay_value
194
+ end
195
+
196
+ def test_template_lang
197
+ i = Invoice.new
198
+ assert_equal 'pl', i.template_lang
199
+ i.foreign_buyer = true
200
+ assert_equal 'pl_en', i.template_lang
201
+ i.lang = 'en'
202
+ assert_equal 'en', i.template_lang
203
+ end
204
+
205
+ def test_template_file
206
+ i = Invoice.new(proforma: true)
207
+ assert_equal 'proforma-pl.slim', i.template_file
208
+ i.foreign_buyer = true
209
+ assert_equal 'proforma-pl_en.slim', i.template_file
210
+ i.lang = 'en'
211
+ assert_equal 'proforma-en.slim', i.template_file
212
+ i.lang = 'pl'
213
+ assert_equal 'proforma-pl.slim', i.template_file
214
+ i.lang = 'pl_en'
215
+ assert_equal 'proforma-pl_en.slim', i.template_file
216
+
217
+ i = Invoice.new
218
+ assert_equal 'invoice-pl.slim', i.template_file
219
+ i.foreign_buyer = true
220
+ assert_equal 'invoice-pl_en.slim', i.template_file
221
+ i.lang = 'en'
222
+ assert_equal 'invoice-en.slim', i.template_file
223
+ i.lang = 'pl'
224
+ assert_equal 'invoice-pl.slim', i.template_file
225
+ i.lang = 'pl_en'
226
+ assert_equal 'invoice-pl_en.slim', i.template_file
227
+ end
136
228
  end
137
229
  end
@@ -54,6 +54,16 @@ module PolishInvoicer
54
54
  check_ok(:price, 19.99)
55
55
  end
56
56
 
57
+ def test_price_paid_validation
58
+ @invoice.price = 200
59
+ check_ok(:price_paid)
60
+ check_error(:price_paid, 'test')
61
+ check_error(:price_paid, '100')
62
+ check_error(:price_paid, -10)
63
+ check_error(:price_paid, 300)
64
+ check_ok(:price_paid, 19.99)
65
+ end
66
+
57
67
  def test_gross_price_validation
58
68
  check_error(:gross_price)
59
69
  check_error(:gross_price, 'test')
@@ -168,6 +178,20 @@ module PolishInvoicer
168
178
  refute v.errors[:exchange_rate]
169
179
  end
170
180
 
181
+ def test_lang
182
+ v = Validator.new(@invoice)
183
+ v.valid?
184
+ refute v.errors[:lang]
185
+ @invoice.lang = 'xx'
186
+ v = Validator.new(@invoice)
187
+ v.valid?
188
+ assert v.errors[:lang]
189
+ @invoice.lang = 'en'
190
+ v = Validator.new(@invoice)
191
+ v.valid?
192
+ refute v.errors[:lang]
193
+ end
194
+
171
195
  private
172
196
 
173
197
  def check_error(field, value = nil)
data/tpl/invoice-en.slim CHANGED
@@ -2,7 +2,7 @@ doctype html
2
2
  html
3
3
  head
4
4
  meta charset="utf-8"
5
- title = "Faktura nr #{number}"
5
+ title = "Invoice number #{number}"
6
6
  css:
7
7
  /*!
8
8
  * Bootstrap v3.3.7 (http://getbootstrap.com)
@@ -16,32 +16,24 @@ html
16
16
  body
17
17
  .container
18
18
 
19
- h3 = "Faktura nr #{number}"
20
- h6.small
21
- em = "Invoice number #{number}"
19
+ h3 = "Invoice number #{number}"
22
20
 
23
21
  .row
24
22
  .col-xs-6
25
- h4 Sprzedawca
26
- h6.small
27
- em Seller
23
+ h4 Seller
28
24
  - seller.each do |line|
29
25
  = line
30
26
  br
31
- = "VAT no: #{seller_nip}"
27
+ = "TAX ID: #{seller_nip}"
32
28
  .col-xs-6
33
- h4 Nabywca
34
- h6.small
35
- em Buyer
29
+ h4 Buyer
36
30
  - buyer.each do |line|
37
31
  = line
38
32
  br
39
33
  - if buyer_nip.to_s.strip != ''
40
- = "VAT no: #{buyer_nip}"
34
+ = "TAX ID: #{buyer_nip}"
41
35
  - if recipient.any?
42
- h4 Odbiorca
43
- h6.small
44
- em Recipient
36
+ h4 Recipient
45
37
  - recipient.each do |line|
46
38
  = line
47
39
  br
@@ -50,96 +42,50 @@ html
50
42
  br
51
43
 
52
44
  .row
53
- .col-xs-3
54
- | Data wystawienia:
55
- .small
56
- em Date of issue:
57
- .col-xs-3
58
- = create_date
59
- .col-xs-3
60
- | Termin płatności:
61
- .small
62
- em Payment deadline:
63
- .col-xs-3
64
- = payment_date
45
+ .col-xs-3 Date of issue:
46
+ .col-xs-3 = create_date
47
+ .col-xs-3 Payment deadline:
48
+ .col-xs-3 = payment_date
65
49
  .row
66
- .col-xs-3
67
- | Data sprzedaży:
68
- .small
69
- em Date of sale:
70
- .col-xs-3
71
- = trade_date
72
- .col-xs-3
73
- | Sposób zapłaty:
74
- .small
75
- em Method of payment:
76
- .col-xs-3
77
- = payment_type
78
- .small
79
- em = payment_type.to_s.downcase == 'przelew' ? 'bank transfer' : 'cash'
50
+ .col-xs-3 Date of sale:
51
+ .col-xs-3 = trade_date
52
+ .col-xs-3 Method of payment:
53
+ .col-xs-3 = payment_type.to_s.downcase == 'przelew' ? 'bank transfer' : 'cash'
80
54
 
81
55
  br
82
56
  br
83
57
 
84
58
  table.table.table-condensed
85
59
  tr
86
- th width="40%"
87
- | Usługa
88
- .small
89
- em Service
60
+ th width="40%" Service
90
61
  - if pkwiu
91
62
  th.text-center width="1%" PKWiU
92
- th.text-center width="7%"
93
- | Ilość
94
- .small
95
- em Qty
96
- th.text-center width="7%"
97
- | Cena netto
98
- .small
99
- em Unit price
100
- th.text-center width="7%"
101
- | Wart. netto
102
- .small
103
- em Net amount
63
+ th.text-center width="7%" Qty
64
+ th.text-center width="7%" Unit price
65
+ th.text-center width="7%" Net amount
104
66
  - unless reverse_charge
105
- th.text-center width="1%"
106
- | VAT
107
- .small
108
- em VAT
109
- th.text-center width="7%"
110
- | Kwota VAT
111
- .small
112
- em VAT amount
113
- th.text-center width="7%"
114
- | Wart. brutto
115
- .small
116
- em Gross amount
67
+ th.text-center width="1%" VAT
68
+ th.text-center width="7%" VAT amount
69
+ th.text-center width="7%" Gross amount
117
70
  tr
118
71
  td = item_name
119
72
  - if pkwiu
120
73
  td.text-center = pkwiu
121
- td.text-center
122
- | 1&nbsp;usł.
123
- .small
124
- em 1&nbsp;service
74
+ td.text-center 1&nbsp;service
125
75
  td.text-center = net_value
126
76
  td.text-center = net_value
127
77
  - unless reverse_charge
128
78
  td.text-center = vat
129
79
  td.text-center = vat_value
130
- td.text-center = gross_value
80
+ td.text-center = total_to_pay_value
131
81
  tr
132
- td colspan="#{pkwiu ? 3 : 2}"
133
- | &nbsp;
134
- th.text-center
135
- | Razem
136
- .small
137
- em Total
82
+ td colspan="#{pkwiu ? 3 : 2}" &nbsp;
83
+ th.text-center Total
138
84
  td.text-center = net_value
139
85
  - unless reverse_charge
140
86
  td.text-center = vat
141
87
  td.text-center = vat_value
142
- th.text-center = gross_value
88
+ th.text-center = total_to_pay_value
143
89
 
144
90
  br
145
91
 
@@ -147,45 +93,19 @@ html
147
93
  .col-xs-6
148
94
  .row
149
95
  .col-xs-6
150
- b Razem do zapłaty:
151
- .small
152
- em Total to pay:
96
+ b Total to pay:
153
97
  .col-xs-6
154
- b = "#{reverse_charge == true ? net_value : gross_value} #{currency}"
98
+ b = "#{total_to_pay_value} #{currency}"
155
99
  .row
156
- .col-xs-6
157
- | Zapłacono:
158
- .small
159
- em Amount paid:
160
- .col-xs-6
161
- - if paid
162
- = "#{reverse_charge == true ? net_value : gross_value} #{currency}"
163
- - else
164
- = "0,00 #{currency}"
100
+ .col-xs-6 Amount paid:
101
+ .col-xs-6 = "#{paid_value} #{currency}"
165
102
  .row
166
- .col-xs-6
167
- | Zostało do zapłaty:
168
- .small
169
- em Left to pay:
170
- .col-xs-6
171
- - if paid
172
- = "0,00 #{currency}"
173
- - else
174
- = "#{reverse_charge == true ? net_value : gross_value} #{currency}"
175
- - if currency != 'PLN'
176
- .row
177
- .col-xs-6
178
- | Kurs waluty:
179
- .small
180
- em Exchange rate:
181
- .col-xs-6
182
- = exchange_rate
183
-
103
+ .col-xs-6 Left to pay:
104
+ .col-xs-6 = "#{to_pay_value} #{currency}"
184
105
  .col-xs-6
185
106
  - if comments.any?
186
- b Uwagi:
187
- .small
188
- em Remarks:
107
+ b Remarks:
108
+ br
189
109
  - comments.each do |line|
190
110
  = line
191
111
  br
@@ -194,6 +114,4 @@ html
194
114
  br
195
115
  br
196
116
 
197
- b Do rozliczenia podatku VAT zobowiązany jest nabywca usługi (odwrotne obciążenie)
198
- .small
199
- em Levy of VAT reverse charged to recipient of service (reverse charge)
117
+ b Levy of VAT reverse charged to recipient of service (reverse charge)