dorsale 3.9.8 → 3.10.0
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 +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
|