Skip to content

Commit 0cbeb25

Browse files
committed
Test surcharges
1 parent e227c5d commit 0cbeb25

File tree

5 files changed

+334
-4
lines changed

5 files changed

+334
-4
lines changed

README.md

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Croatia is a gem that contains various utilities for performing Croatia-specific
1616
- [x] Taxes
1717
- [x] Types
1818
- [x] Categories
19-
- [ ] Surcharges _(Naknade)_
19+
- [x] Surcharges _(Naknade)_
2020
- [ ] Margins _(Marza)_
2121
- [x] Payment barcodes
2222
- [x] HUB3 standard 2D barcode generation
@@ -174,12 +174,26 @@ invoice.add_line_item do |line_item|
174174

175175
# Clear all taxes
176176
# line_item.clear_taxes
177+
178+
# Add surcharges (naknade)
179+
line_item.add_surcharge(name: "Refundable deposit", amount: 2.50)
180+
line_item.add_surcharge do |surcharge|
181+
surcharge.name = "Handling fee"
182+
surcharge.amount = 1.25
183+
end
184+
185+
# Remove a surcharge
186+
# line_item.remove_surcharge("Refundable deposit")
187+
188+
# Clear all surcharges
189+
# line_item.clear_surcharges
177190
end
178191

179192
invoice.subtotal # => BigDecimal("200.00")
180193
invoice.tax # => BigDecimal("62.50")
181-
invoice.total # => BigDecimal("262.50")
182-
invoice.total_cents # => 26250
194+
invoice.surcharge # => BigDecimal("3.75")
195+
invoice.total # => BigDecimal("266.25")
196+
invoice.total_cents # => 26625
183197

184198
invoice.number # => "64/HQ1/123"
185199

lib/croatia/invoice.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ class Croatia::Invoice
1010
autoload :Payable, "croatia/invoice/payable"
1111
autoload :Party, "croatia/invoice/party"
1212
autoload :Tax, "croatia/invoice/tax"
13+
autoload :Surcharge, "croatia/invoice/surcharge"
1314
autoload :LineItem, "croatia/invoice/line_item"
1415

1516
include Croatia::Enum
@@ -55,6 +56,10 @@ def tax
5556
line_items.sum(&:tax).to_d
5657
end
5758

59+
def surcharge
60+
line_items.sum(&:surcharge).to_d
61+
end
62+
5863
def total
5964
line_items.sum(&:total).to_d
6065
end

lib/croatia/invoice/line_item.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ def tax
104104
end
105105

106106
def surcharge
107-
surcharges.values.sum(&:amount).round(2, BigDecimal::ROUND_HALF_UP)
107+
surcharges.values.sum(&:amount).to_d.round(2, BigDecimal::ROUND_HALF_UP)
108108
end
109109

110110
def total

test/croatia/invoice/line_item_test.rb

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,4 +396,194 @@ def test_floating_point_with_discounts
396396
# total: 3.14 + 0.69 = 3.83
397397
assert_equal BigDecimal("3.83"), line_item.total
398398
end
399+
400+
def test_add_surcharge_with_options
401+
line_item = Croatia::Invoice::LineItem.new(description: "Test")
402+
403+
surcharge = line_item.add_surcharge(name: "Environmental fee", amount: 2.50)
404+
405+
assert_instance_of Croatia::Invoice::Surcharge, surcharge
406+
assert_equal "Environmental fee", surcharge.name
407+
assert_equal BigDecimal("2.50"), surcharge.amount
408+
assert_equal 1, line_item.surcharges.length
409+
end
410+
411+
def test_add_surcharge_with_block
412+
line_item = Croatia::Invoice::LineItem.new(description: "Test")
413+
414+
surcharge = line_item.add_surcharge(name: "Recycling fee", amount: 1.25) do |s|
415+
s.amount = 2.50 # Override the amount
416+
end
417+
418+
assert_instance_of Croatia::Invoice::Surcharge, surcharge
419+
assert_equal "Recycling fee", surcharge.name
420+
assert_equal BigDecimal("2.50"), surcharge.amount
421+
assert_equal 1, line_item.surcharges.length
422+
end
423+
424+
def test_add_surcharge_with_object
425+
line_item = Croatia::Invoice::LineItem.new(description: "Test")
426+
surcharge_obj = Croatia::Invoice::Surcharge.new(name: "Handling fee", amount: 3.75)
427+
428+
result = line_item.add_surcharge(surcharge_obj)
429+
430+
assert_equal surcharge_obj, result
431+
assert_equal 1, line_item.surcharges.length
432+
assert_equal surcharge_obj, line_item.surcharges.values.first
433+
end
434+
435+
def test_remove_surcharge
436+
line_item = Croatia::Invoice::LineItem.new(description: "Test")
437+
line_item.add_surcharge(name: "Delivery fee", amount: 5.0)
438+
line_item.add_surcharge(name: "Service fee", amount: 2.0)
439+
440+
assert_equal 2, line_item.surcharges.length
441+
442+
line_item.remove_surcharge("Delivery fee")
443+
444+
assert_equal 1, line_item.surcharges.length
445+
assert_nil line_item.surcharges["Delivery fee"]
446+
refute_nil line_item.surcharges["Service fee"]
447+
end
448+
449+
def test_clear_surcharges
450+
line_item = Croatia::Invoice::LineItem.new(description: "Test")
451+
line_item.add_surcharge(name: "Fee 1", amount: 1.0)
452+
line_item.add_surcharge(name: "Fee 2", amount: 2.0)
453+
454+
assert_equal 2, line_item.surcharges.length
455+
456+
line_item.clear_surcharges
457+
458+
assert_equal 0, line_item.surcharges.length
459+
end
460+
461+
def test_surcharge_calculation_single_surcharge
462+
line_item = Croatia::Invoice::LineItem.new(
463+
description: "Test item",
464+
quantity: 2,
465+
unit_price: 10.0
466+
)
467+
line_item.add_surcharge(name: "Environmental fee", amount: 2.50)
468+
469+
assert_equal BigDecimal("2.50"), line_item.surcharge
470+
end
471+
472+
def test_surcharge_calculation_multiple_surcharges
473+
line_item = Croatia::Invoice::LineItem.new(
474+
description: "Test item",
475+
quantity: 2,
476+
unit_price: 10.0
477+
)
478+
line_item.add_surcharge(name: "Environmental fee", amount: 2.50)
479+
line_item.add_surcharge(name: "Handling fee", amount: 1.75)
480+
481+
assert_equal BigDecimal("4.25"), line_item.surcharge
482+
end
483+
484+
def test_surcharge_calculation_no_surcharges
485+
line_item = Croatia::Invoice::LineItem.new(
486+
description: "Test item",
487+
quantity: 2,
488+
unit_price: 10.0
489+
)
490+
491+
assert_equal BigDecimal("0.00"), line_item.surcharge
492+
end
493+
494+
def test_total_calculation_with_surcharges
495+
line_item = Croatia::Invoice::LineItem.new(
496+
description: "Test item",
497+
quantity: 2,
498+
unit_price: 10.0
499+
)
500+
line_item.add_tax(rate: 0.25)
501+
line_item.add_surcharge(name: "Environmental fee", amount: 3.0)
502+
503+
# subtotal: 20.0, tax: 5.0, surcharge: 3.0, total: 28.0
504+
assert_equal BigDecimal("20.00"), line_item.subtotal
505+
assert_equal BigDecimal("5.00"), line_item.tax
506+
assert_equal BigDecimal("3.00"), line_item.surcharge
507+
assert_equal BigDecimal("28.00"), line_item.total
508+
end
509+
510+
def test_total_calculation_with_taxes_and_multiple_surcharges
511+
line_item = Croatia::Invoice::LineItem.new(
512+
description: "Test item",
513+
quantity: 1,
514+
unit_price: 100.0
515+
)
516+
line_item.add_tax(rate: 0.25)
517+
line_item.add_surcharge(name: "Environmental fee", amount: 5.0)
518+
line_item.add_surcharge(name: "Handling fee", amount: 2.50)
519+
520+
# subtotal: 100.0, tax: 25.0, surcharge: 7.5, total: 132.5
521+
assert_equal BigDecimal("100.00"), line_item.subtotal
522+
assert_equal BigDecimal("25.00"), line_item.tax
523+
assert_equal BigDecimal("7.50"), line_item.surcharge
524+
assert_equal BigDecimal("132.50"), line_item.total
525+
end
526+
527+
def test_surcharge_with_discount_and_tax
528+
line_item = Croatia::Invoice::LineItem.new(
529+
description: "Test item",
530+
quantity: 2,
531+
unit_price: 10.0
532+
)
533+
line_item.discount_rate = 0.1
534+
line_item.add_tax(rate: 0.25)
535+
line_item.add_surcharge(name: "Service fee", amount: 1.5)
536+
537+
# gross: 20.0, discount: 2.0, subtotal: 18.0
538+
# tax: 18.0 * 0.25 = 4.5, surcharge: 1.5
539+
# total: 18.0 + 4.5 + 1.5 = 24.0
540+
assert_equal BigDecimal("20.00"), line_item.gross
541+
assert_equal BigDecimal("2.00"), line_item.discount
542+
assert_equal BigDecimal("18.00"), line_item.subtotal
543+
assert_equal BigDecimal("4.50"), line_item.tax
544+
assert_equal BigDecimal("1.50"), line_item.surcharge
545+
assert_equal BigDecimal("24.00"), line_item.total
546+
end
547+
548+
def test_surcharge_with_reverse_line_item
549+
line_item = Croatia::Invoice::LineItem.new(
550+
description: "Test item",
551+
quantity: 2,
552+
unit_price: 10.0
553+
)
554+
line_item.add_tax(rate: 0.25)
555+
line_item.add_surcharge(name: "Fee", amount: 3.0)
556+
line_item.reverse
557+
558+
# After reverse, quantity is negative but surcharge remains positive
559+
assert_equal BigDecimal("-2"), line_item.quantity
560+
assert_equal BigDecimal("-20.00"), line_item.subtotal
561+
assert_equal BigDecimal("-5.00"), line_item.tax
562+
assert_equal BigDecimal("3.00"), line_item.surcharge # Surcharge stays positive
563+
assert_equal BigDecimal("-22.00"), line_item.total # -20 + (-5) + 3 = -22
564+
end
565+
566+
def test_surcharge_bigdecimal_precision
567+
line_item = Croatia::Invoice::LineItem.new(description: "Test")
568+
line_item.add_surcharge(name: "Precision test", amount: 1.234567)
569+
570+
surcharge = line_item.surcharges["Precision test"]
571+
assert_instance_of BigDecimal, surcharge.amount
572+
assert_equal BigDecimal("1.234567"), surcharge.amount
573+
574+
# Test that surcharge total is rounded to 2 decimal places
575+
assert_equal BigDecimal("1.23"), line_item.surcharge
576+
assert_equal 2, line_item.surcharge.scale
577+
end
578+
579+
def test_initialize_with_surcharges
580+
surcharge = Croatia::Invoice::Surcharge.new(name: "Initial fee", amount: 2.0)
581+
line_item = Croatia::Invoice::LineItem.new(
582+
description: "Test item",
583+
surcharges: { surcharge.name => surcharge }
584+
)
585+
586+
assert_equal 1, line_item.surcharges.length
587+
assert_equal surcharge, line_item.surcharges["Initial fee"]
588+
end
399589
end
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
# frozen_string_literal: true
2+
3+
require "test_helper"
4+
5+
class Croatia::Invoice::SurchargeTest < Minitest::Test
6+
def test_initialize
7+
surcharge = Croatia::Invoice::Surcharge.new(name: "Environmental fee", amount: 2.50)
8+
9+
assert_equal "Environmental fee", surcharge.name
10+
assert_equal BigDecimal("2.50"), surcharge.amount
11+
end
12+
13+
def test_initialize_with_string_amount
14+
surcharge = Croatia::Invoice::Surcharge.new(name: "Handling fee", amount: "3.75")
15+
16+
assert_equal "Handling fee", surcharge.name
17+
assert_equal BigDecimal("3.75"), surcharge.amount
18+
end
19+
20+
def test_initialize_with_integer_amount
21+
surcharge = Croatia::Invoice::Surcharge.new(name: "Service fee", amount: 5)
22+
23+
assert_equal "Service fee", surcharge.name
24+
assert_equal BigDecimal("5"), surcharge.amount
25+
end
26+
27+
def test_name_validation_nil
28+
assert_raises(ArgumentError, "Name cannot be nil") do
29+
Croatia::Invoice::Surcharge.new(name: nil, amount: 1.0)
30+
end
31+
end
32+
33+
def test_amount_validation_nil
34+
assert_raises(ArgumentError, "Amount cannot be nil") do
35+
Croatia::Invoice::Surcharge.new(name: "Test", amount: nil)
36+
end
37+
end
38+
39+
def test_name_setter
40+
surcharge = Croatia::Invoice::Surcharge.new(name: "Original", amount: 1.0)
41+
surcharge.name = "Updated"
42+
43+
assert_equal "Updated", surcharge.name
44+
end
45+
46+
def test_name_setter_with_whitespace
47+
surcharge = Croatia::Invoice::Surcharge.new(name: "Original", amount: 1.0)
48+
surcharge.name = " Trimmed "
49+
50+
assert_equal "Trimmed", surcharge.name
51+
end
52+
53+
def test_name_setter_with_number
54+
surcharge = Croatia::Invoice::Surcharge.new(name: "Original", amount: 1.0)
55+
surcharge.name = 123
56+
57+
assert_equal "123", surcharge.name
58+
end
59+
60+
def test_name_setter_nil_validation
61+
surcharge = Croatia::Invoice::Surcharge.new(name: "Original", amount: 1.0)
62+
63+
assert_raises(ArgumentError, "Name cannot be nil") do
64+
surcharge.name = nil
65+
end
66+
end
67+
68+
def test_amount_setter
69+
surcharge = Croatia::Invoice::Surcharge.new(name: "Test", amount: 1.0)
70+
surcharge.amount = 5.25
71+
72+
assert_equal BigDecimal("5.25"), surcharge.amount
73+
end
74+
75+
def test_amount_setter_with_string
76+
surcharge = Croatia::Invoice::Surcharge.new(name: "Test", amount: 1.0)
77+
surcharge.amount = "7.50"
78+
79+
assert_equal BigDecimal("7.50"), surcharge.amount
80+
end
81+
82+
def test_amount_setter_with_integer
83+
surcharge = Croatia::Invoice::Surcharge.new(name: "Test", amount: 1.0)
84+
surcharge.amount = 10
85+
86+
assert_equal BigDecimal("10"), surcharge.amount
87+
end
88+
89+
def test_amount_setter_nil_validation
90+
surcharge = Croatia::Invoice::Surcharge.new(name: "Test", amount: 1.0)
91+
92+
assert_raises(ArgumentError, "Amount cannot be nil") do
93+
surcharge.amount = nil
94+
end
95+
end
96+
97+
def test_bigdecimal_precision
98+
surcharge = Croatia::Invoice::Surcharge.new(name: "Precision test", amount: 1.123456789)
99+
100+
assert_instance_of BigDecimal, surcharge.amount
101+
assert_equal BigDecimal("1.123456789"), surcharge.amount
102+
end
103+
104+
def test_negative_amounts_allowed
105+
surcharge = Croatia::Invoice::Surcharge.new(name: "Credit", amount: -2.50)
106+
107+
assert_equal BigDecimal("-2.50"), surcharge.amount
108+
end
109+
110+
def test_zero_amount_allowed
111+
surcharge = Croatia::Invoice::Surcharge.new(name: "Free", amount: 0)
112+
113+
assert_equal BigDecimal("0"), surcharge.amount
114+
end
115+
116+
def test_enum_inclusion
117+
surcharge = Croatia::Invoice::Surcharge.new(name: "Test", amount: 1.0)
118+
119+
assert_includes surcharge.class.ancestors, Croatia::Enum
120+
end
121+
end

0 commit comments

Comments
 (0)