dorsale 3.9.8 → 3.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/app/assets/javascripts/dorsale/engines/billing_machine.coffee +89 -80
- data/app/models/dorsale/billing_machine.rb +6 -2
- data/app/models/dorsale/billing_machine/invoice.rb +2 -2
- data/app/models/dorsale/billing_machine/invoice_line.rb +2 -2
- data/app/models/dorsale/billing_machine/quotation.rb +2 -2
- data/app/models/dorsale/billing_machine/quotation_line.rb +2 -2
- data/lib/dorsale/version.rb +1 -1
- data/spec/models/dorsale/billing_machine/invoice_line_spec.rb +5 -5
- data/spec/models/dorsale/billing_machine/invoice_spec.rb +26 -1
- data/spec/models/dorsale/billing_machine/quotation_line_spec.rb +5 -5
- data/spec/models/dorsale/billing_machine/quotation_spec.rb +26 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 99dec4abf499000f2dd5056f0ad64e158982020b
|
4
|
+
data.tar.gz: 8880c252a553956e6d24ac1723c20a9d46108a36
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 98a8ede0dc3303cf86f0f275a153df7d4cc0fd4409dfd0faee7baf3101cb5c03c0a6bd6d0bc72e64fbec1bc3f12bd012c5c3b989935f3964e59818c0d682fb04
|
7
|
+
data.tar.gz: 29e5a4f979b8fa53a478f65a6092ac5fd5c74bb6a92618d74f4a97e6d8fabe1264e468de69cae688555ea4195287809b9852947b08772e9633ebc71f0e3b238a
|
data/CHANGELOG.md
CHANGED
@@ -1,95 +1,104 @@
|
|
1
|
-
|
2
|
-
number:
|
3
|
-
precision : 2
|
4
|
-
thousand: " " # nbsp
|
5
|
-
decimal : ","
|
1
|
+
@BillingMachine = {}
|
6
2
|
|
7
|
-
|
3
|
+
BillingMachine.settings =
|
4
|
+
precision : 2
|
5
|
+
thousand : " " # nbsp
|
6
|
+
decimal : ","
|
7
|
+
|
8
|
+
BillingMachine.str2num = (str) ->
|
8
9
|
parseFloat(
|
9
10
|
String(str)
|
10
11
|
.replace(",", ".")
|
11
12
|
.replace(/[^-0-9\.]+/g, "")
|
12
13
|
) || 0.0
|
13
14
|
|
14
|
-
|
15
|
+
BillingMachine.num2str = (num) ->
|
15
16
|
num = parseFloat(num)
|
16
|
-
|
17
|
+
settings = BillingMachine.settings
|
18
|
+
accounting.formatNumber(num, settings.precision, settings.thousand, settings.decimal)
|
19
|
+
|
20
|
+
BillingMachine.round2 = (num) ->
|
21
|
+
return +(Math.round(num + "e+2") + "e-2")
|
22
|
+
|
23
|
+
BillingMachine.updateTotals = ->
|
24
|
+
total_excluding_taxes = 0.0
|
25
|
+
|
26
|
+
# Update line totals
|
27
|
+
$("#billing_machine-form .line").map ->
|
28
|
+
return if parseInt($(this).find("input[name*=destroy]").val()) == 1
|
29
|
+
quantity = BillingMachine.str2num $(this).find(".line-quantity input").val()
|
30
|
+
unit_price = BillingMachine.str2num $(this).find(".line-unit_price input").val()
|
31
|
+
line_total = BillingMachine.round2(unit_price * quantity)
|
32
|
+
$(this).find(".line-total input").val BillingMachine.num2str line_total
|
33
|
+
|
34
|
+
total_excluding_taxes += line_total
|
35
|
+
|
36
|
+
# Substract discount to total excluding taxes
|
37
|
+
commercial_discount = BillingMachine.str2num $(".commercial_discount input").val()
|
38
|
+
raw_total_excluding_taxes = total_excluding_taxes
|
39
|
+
total_excluding_taxes = raw_total_excluding_taxes - commercial_discount
|
40
|
+
$(".total_excluding_taxes input").val BillingMachine.num2str total_excluding_taxes
|
41
|
+
|
42
|
+
discount_rate = commercial_discount / raw_total_excluding_taxes
|
43
|
+
|
44
|
+
# VAT amount based on each line total with discount rate
|
45
|
+
vat_amount = 0.0
|
46
|
+
$("#billing_machine-form .line").map ->
|
47
|
+
return if parseInt($(this).find("input[name*=destroy]").val()) == 1
|
48
|
+
|
49
|
+
# Per line VAT rate
|
50
|
+
if $(this).find(".line-vat_rate input").length > 0
|
51
|
+
vat_rate = BillingMachine.str2num $(this).find(".line-vat_rate input").val()
|
52
|
+
# Global VAT rate
|
53
|
+
else
|
54
|
+
vat_rate = BillingMachine.str2num $("#totals-table .vat_rate input").val()
|
55
|
+
|
56
|
+
line_total = BillingMachine.str2num $(this).find(".line-total input").val()
|
57
|
+
discounted_line_total = line_total - (line_total * discount_rate)
|
58
|
+
line_vat_amount = BillingMachine.round2(discounted_line_total * vat_rate / 100)
|
59
|
+
vat_amount += line_vat_amount
|
60
|
+
$(".vat_amount input").val BillingMachine.num2str vat_amount
|
61
|
+
|
62
|
+
total_including_taxes = total_excluding_taxes + vat_amount
|
63
|
+
$(".total_including_taxes input").val BillingMachine.num2str total_including_taxes
|
64
|
+
|
65
|
+
# Advances is for invoices only, not for quotations
|
66
|
+
if $(".advance input").length > 0 && $(".balance input").length > 0
|
67
|
+
advance = BillingMachine.str2num $(".advance input").val()
|
68
|
+
balance = total_including_taxes - advance
|
69
|
+
$(".balance input").val BillingMachine.num2str balance
|
70
|
+
|
71
|
+
BillingMachine.formatInputs = ->
|
72
|
+
$("#billing_machine-form input.number").map ->
|
73
|
+
formatted_number = BillingMachine.num2str BillingMachine.str2num $(this).val()
|
74
|
+
$(this).val formatted_number
|
75
|
+
|
76
|
+
# Empty number inputs on focus if value is 0
|
77
|
+
$(document).on "focus", "#billing_machine-form input.number", ->
|
78
|
+
$(this).val("") if BillingMachine.str2num($(this).val()) == 0
|
79
|
+
|
80
|
+
# Auto ajust line label textarea height
|
81
|
+
$(document).on "keyup", "#billing_machine-form textarea", ->
|
82
|
+
this.rows = this.value.split("\n").length
|
83
|
+
$("#billing_machine-form textarea").keyup()
|
84
|
+
|
85
|
+
# Button to delete line
|
86
|
+
$(document).on "click", "#billing_machine-form a.delete", ->
|
87
|
+
e.preventDefault()
|
88
|
+
$(this).parents("td").find("input").val(1)
|
89
|
+
$(this).parents("tr").hide()
|
90
|
+
BillingMachine.updateTotals()
|
17
91
|
|
18
92
|
$(document).on "turbolinks:load cocoon:after-insert", ->
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
# Update line totals
|
23
|
-
$("#billing_machine-form .line").map ->
|
24
|
-
return if parseInt($(this).find("input[name*=destroy]").val()) == 1
|
25
|
-
quantity = str2num $(this).find(".line-quantity input").val()
|
26
|
-
unit_price = str2num $(this).find(".line-unit_price input").val()
|
27
|
-
line_total = unit_price * quantity
|
28
|
-
$(this).find(".line-total input").val num2str line_total
|
29
|
-
|
30
|
-
total_excluding_taxes += line_total
|
31
|
-
|
32
|
-
# Substract discount to total excluding taxes
|
33
|
-
commercial_discount = str2num $(".commercial_discount input").val()
|
34
|
-
raw_total_excluding_taxes = total_excluding_taxes
|
35
|
-
total_excluding_taxes = raw_total_excluding_taxes - commercial_discount
|
36
|
-
$(".total_excluding_taxes input").val num2str total_excluding_taxes
|
37
|
-
|
38
|
-
discount_rate = commercial_discount / raw_total_excluding_taxes
|
39
|
-
|
40
|
-
# VAT amount based on each line total with discount rate
|
41
|
-
vat_amount = 0.0
|
42
|
-
$("#billing_machine-form .line").map ->
|
43
|
-
return if parseInt($(this).find("input[name*=destroy]").val()) == 1
|
44
|
-
|
45
|
-
# Per line VAT rate
|
46
|
-
if $(this).find(".line-vat_rate input").length > 0
|
47
|
-
vat_rate = str2num $(this).find(".line-vat_rate input").val()
|
48
|
-
# Global VAT rate
|
49
|
-
else
|
50
|
-
vat_rate = str2num $("#totals-table .vat_rate input").val()
|
51
|
-
|
52
|
-
line_total = str2num $(this).find(".line-total input").val()
|
53
|
-
discounted_line_total = line_total - (line_total * discount_rate)
|
54
|
-
line_vat_amount = discounted_line_total * vat_rate / 100
|
55
|
-
vat_amount += line_vat_amount
|
56
|
-
$(".vat_amount input").val num2str vat_amount
|
57
|
-
|
58
|
-
total_including_taxes = total_excluding_taxes + vat_amount
|
59
|
-
$(".total_including_taxes input").val num2str total_including_taxes
|
60
|
-
|
61
|
-
# Advances is for invoices only, not for quotations
|
62
|
-
if $(".advance input").length > 0 && $(".balance input").length > 0
|
63
|
-
advance = str2num $(".advance input").val()
|
64
|
-
balance = total_including_taxes - advance
|
65
|
-
$(".balance input").val num2str balance
|
66
|
-
|
67
|
-
# Update amount on page load
|
68
|
-
$("#billing_machine-form input").keyup()
|
69
|
-
|
70
|
-
# Format all input correctly
|
71
|
-
$("#billing_machine-form input.number").blur ->
|
72
|
-
$("#billing_machine-form input.number").map ->
|
73
|
-
formatted_number = num2str str2num $(this).val()
|
74
|
-
$(this).val formatted_number
|
75
|
-
$("#billing_machine-form input.number").blur()
|
76
|
-
|
77
|
-
# Empty number inputs on focus if value is 0
|
78
|
-
$("#billing_machine-form input.number").focus ->
|
79
|
-
$(this).val("") if str2num($(this).val()) == 0
|
80
|
-
|
81
|
-
# Auto ajust line label textarea height
|
82
|
-
$("#billing_machine-form textarea").keyup ->
|
83
|
-
this.rows = this.value.split("\n").length
|
84
|
-
$("#billing_machine-form textarea").keyup()
|
93
|
+
BillingMachine.formatInputs()
|
94
|
+
BillingMachine.updateTotals()
|
85
95
|
|
86
96
|
# Fix Cocoon bug
|
87
97
|
$("#billing_machine-form .line textarea").map ->
|
88
98
|
this.value = this.value.trim()
|
89
99
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
return false
|
100
|
+
$(document).on "keyup", "#billing_machine-form input.number", ->
|
101
|
+
BillingMachine.updateTotals()
|
102
|
+
|
103
|
+
$(document).on "blur", "#billing_machine-form input.number", ->
|
104
|
+
BillingMachine.formatInputs()
|
@@ -1,6 +1,4 @@
|
|
1
1
|
module Dorsale::BillingMachine
|
2
|
-
DEFAULT_VAT_RATE = 20.00
|
3
|
-
|
4
2
|
class << self
|
5
3
|
def vat_modes
|
6
4
|
[:single, :multiple]
|
@@ -28,5 +26,11 @@ module Dorsale::BillingMachine
|
|
28
26
|
def default_currency
|
29
27
|
@default_currency ||= "€"
|
30
28
|
end
|
29
|
+
|
30
|
+
attr_writer :default_vat_rate
|
31
|
+
|
32
|
+
def default_vat_rate
|
33
|
+
@default_vat_rate ||= 20.0
|
34
|
+
end
|
31
35
|
end
|
32
36
|
end
|
@@ -71,7 +71,7 @@ class Dorsale::BillingMachine::Invoice < ::Dorsale::ApplicationRecord
|
|
71
71
|
|
72
72
|
lines.each do |line|
|
73
73
|
line_total = line.total - (line.total * discount_rate)
|
74
|
-
self.vat_amount += (line_total * line.vat_rate / 100.0)
|
74
|
+
self.vat_amount += (line_total * line.vat_rate / 100.0).round(2)
|
75
75
|
end
|
76
76
|
|
77
77
|
self.total_including_taxes = total_excluding_taxes + vat_amount
|
@@ -91,7 +91,7 @@ class Dorsale::BillingMachine::Invoice < ::Dorsale::ApplicationRecord
|
|
91
91
|
raise "Invoice has multiple vat rates"
|
92
92
|
end
|
93
93
|
|
94
|
-
vat_rates.first || ::Dorsale::BillingMachine
|
94
|
+
vat_rates.first || ::Dorsale::BillingMachine.default_vat_rate
|
95
95
|
end
|
96
96
|
|
97
97
|
attr_writer :vat_rate
|
@@ -14,12 +14,12 @@ class Dorsale::BillingMachine::InvoiceLine < ::Dorsale::ApplicationRecord
|
|
14
14
|
def assign_default_values
|
15
15
|
assign_default :quantity, 0
|
16
16
|
assign_default :unit_price, 0
|
17
|
-
assign_default :vat_rate, ::Dorsale::BillingMachine
|
17
|
+
assign_default :vat_rate, ::Dorsale::BillingMachine.default_vat_rate
|
18
18
|
end
|
19
19
|
|
20
20
|
def update_total
|
21
21
|
assign_default_values
|
22
|
-
self.total = quantity * unit_price
|
22
|
+
self.total = (quantity * unit_price).round(2)
|
23
23
|
end
|
24
24
|
|
25
25
|
after_save :update_invoice_total
|
@@ -76,7 +76,7 @@ class Dorsale::BillingMachine::Quotation < ::Dorsale::ApplicationRecord
|
|
76
76
|
|
77
77
|
lines.each do |line|
|
78
78
|
line_total = line.total - (line.total * discount_rate)
|
79
|
-
self.vat_amount += (line_total * line.vat_rate / 100.0)
|
79
|
+
self.vat_amount += (line_total * line.vat_rate / 100.0).round(2)
|
80
80
|
end
|
81
81
|
|
82
82
|
self.total_including_taxes = total_excluding_taxes + vat_amount
|
@@ -105,7 +105,7 @@ class Dorsale::BillingMachine::Quotation < ::Dorsale::ApplicationRecord
|
|
105
105
|
raise "Quotation has multiple vat rates"
|
106
106
|
end
|
107
107
|
|
108
|
-
vat_rates.first || ::Dorsale::BillingMachine
|
108
|
+
vat_rates.first || ::Dorsale::BillingMachine.default_vat_rate
|
109
109
|
end
|
110
110
|
|
111
111
|
attr_writer :vat_rate
|
@@ -14,12 +14,12 @@ class Dorsale::BillingMachine::QuotationLine < ::Dorsale::ApplicationRecord
|
|
14
14
|
def assign_default_values
|
15
15
|
assign_default :quantity, 0
|
16
16
|
assign_default :unit_price, 0
|
17
|
-
assign_default :vat_rate, ::Dorsale::BillingMachine
|
17
|
+
assign_default :vat_rate, ::Dorsale::BillingMachine.default_vat_rate
|
18
18
|
end
|
19
19
|
|
20
20
|
def update_total
|
21
21
|
assign_default_values
|
22
|
-
self.total = quantity * unit_price
|
22
|
+
self.total = (quantity * unit_price).round(2)
|
23
23
|
end
|
24
24
|
|
25
25
|
after_save :update_quotation_total
|
data/lib/dorsale/version.rb
CHANGED
@@ -25,7 +25,7 @@ describe Dorsale::BillingMachine::InvoiceLine, type: :model do
|
|
25
25
|
end
|
26
26
|
|
27
27
|
it "vat_rate should be 0" do
|
28
|
-
expect(described_class.new.vat_rate).to eq Dorsale::BillingMachine
|
28
|
+
expect(described_class.new.vat_rate).to eq Dorsale::BillingMachine.default_vat_rate
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
@@ -41,12 +41,12 @@ describe Dorsale::BillingMachine::InvoiceLine, type: :model do
|
|
41
41
|
end
|
42
42
|
|
43
43
|
it "should update the total upon save" do
|
44
|
-
|
45
|
-
expect(
|
44
|
+
line = create(:billing_machine_invoice_line, quantity: 12.34, unit_price: 12.34, total: 0)
|
45
|
+
expect(line.total).to eq(152.28)
|
46
46
|
end
|
47
47
|
|
48
48
|
it "should update the total gracefully with invalid data" do
|
49
|
-
|
50
|
-
expect(
|
49
|
+
line = create(:billing_machine_invoice_line, quantity: nil, unit_price: nil, total: 0)
|
50
|
+
expect(line.total).to eq(0)
|
51
51
|
end
|
52
52
|
end
|
@@ -120,7 +120,7 @@ describe Dorsale::BillingMachine::Invoice, type: :model do
|
|
120
120
|
|
121
121
|
describe "vat rate" do
|
122
122
|
it "default vat rate should be 20" do
|
123
|
-
expect(described_class.new.vat_rate).to eq ::Dorsale::BillingMachine
|
123
|
+
expect(described_class.new.vat_rate).to eq ::Dorsale::BillingMachine.default_vat_rate
|
124
124
|
end
|
125
125
|
|
126
126
|
it "it should be specified vat rate" do
|
@@ -202,6 +202,31 @@ describe Dorsale::BillingMachine::Invoice, type: :model do
|
|
202
202
|
expect(invoice.balance).to eq(108)
|
203
203
|
end
|
204
204
|
|
205
|
+
it "should round numbers" do
|
206
|
+
invoice = create(:billing_machine_invoice,
|
207
|
+
:commercial_discount => 0,
|
208
|
+
)
|
209
|
+
|
210
|
+
create(:billing_machine_invoice_line,
|
211
|
+
:quantity => 12.34,
|
212
|
+
:unit_price => 12.34,
|
213
|
+
:vat_rate => 20,
|
214
|
+
:invoice => invoice,
|
215
|
+
) # total 152.28
|
216
|
+
|
217
|
+
create(:billing_machine_invoice_line,
|
218
|
+
:quantity => 12.34,
|
219
|
+
:unit_price => 12.34,
|
220
|
+
:vat_rate => 20,
|
221
|
+
:invoice => invoice,
|
222
|
+
) # total 152.28
|
223
|
+
|
224
|
+
expect(invoice.total_excluding_taxes).to eq(304.56)
|
225
|
+
expect(invoice.vat_amount).to eq(60.92)
|
226
|
+
expect(invoice.total_including_taxes).to eq(365.48)
|
227
|
+
expect(invoice.balance).to eq(365.48)
|
228
|
+
end
|
229
|
+
|
205
230
|
it "should work fine even with empty lines" do
|
206
231
|
invoice = create(:billing_machine_invoice)
|
207
232
|
|
@@ -25,7 +25,7 @@ describe Dorsale::BillingMachine::QuotationLine do
|
|
25
25
|
end
|
26
26
|
|
27
27
|
it "vat_rate should be 0" do
|
28
|
-
expect(described_class.new.vat_rate).to eq ::Dorsale::BillingMachine
|
28
|
+
expect(described_class.new.vat_rate).to eq ::Dorsale::BillingMachine.default_vat_rate
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
@@ -40,12 +40,12 @@ describe Dorsale::BillingMachine::QuotationLine do
|
|
40
40
|
end
|
41
41
|
|
42
42
|
it "should update the total upon save" do
|
43
|
-
|
44
|
-
expect(
|
43
|
+
line = create(:billing_machine_quotation_line, quantity: 12.34, unit_price: 12.34, total: 0)
|
44
|
+
expect(line.total).to eq(152.28)
|
45
45
|
end
|
46
46
|
|
47
47
|
it "should update the total gracefully with invalid data" do
|
48
|
-
|
49
|
-
expect(
|
48
|
+
line = create(:billing_machine_quotation_line, quantity: nil, unit_price: nil, total: 0)
|
49
|
+
expect(line.total).to eq(0)
|
50
50
|
end
|
51
51
|
end
|
@@ -74,7 +74,7 @@ describe Dorsale::BillingMachine::Quotation do
|
|
74
74
|
|
75
75
|
describe "vat rate" do
|
76
76
|
it "default vat rate should be 20" do
|
77
|
-
expect(described_class.new.vat_rate).to eq ::Dorsale::BillingMachine
|
77
|
+
expect(described_class.new.vat_rate).to eq ::Dorsale::BillingMachine.default_vat_rate
|
78
78
|
end
|
79
79
|
|
80
80
|
it "it should be specified vat rate" do
|
@@ -152,6 +152,31 @@ describe Dorsale::BillingMachine::Quotation do
|
|
152
152
|
Dorsale::BillingMachine.vat_mode = :single
|
153
153
|
end
|
154
154
|
|
155
|
+
it "should round numbers" do
|
156
|
+
quotation = create(:billing_machine_quotation,
|
157
|
+
:commercial_discount => 0,
|
158
|
+
)
|
159
|
+
|
160
|
+
create(:billing_machine_quotation_line,
|
161
|
+
:quantity => 12.34,
|
162
|
+
:unit_price => 12.34,
|
163
|
+
:vat_rate => 20,
|
164
|
+
:quotation => quotation,
|
165
|
+
) # total 152.28
|
166
|
+
|
167
|
+
create(:billing_machine_quotation_line,
|
168
|
+
:quantity => 12.34,
|
169
|
+
:unit_price => 12.34,
|
170
|
+
:vat_rate => 20,
|
171
|
+
:quotation => quotation,
|
172
|
+
) # total 152.28
|
173
|
+
|
174
|
+
expect(quotation.total_excluding_taxes).to eq(304.56)
|
175
|
+
expect(quotation.vat_amount).to eq(60.92)
|
176
|
+
expect(quotation.total_including_taxes).to eq(365.48)
|
177
|
+
expect(quotation.balance).to eq(365.48)
|
178
|
+
end
|
179
|
+
|
155
180
|
it "should work fine even with empty lines" do
|
156
181
|
quotation = create(:billing_machine_quotation, commercial_discount: nil)
|
157
182
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dorsale
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- agilidée
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-07
|
11
|
+
date: 2018-08-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|