polish_invoicer 0.0.21 → 0.0.26

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.
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)