diff --git a/CHANGELOG.md b/CHANGELOG.md index a9371208b..85940de69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - Fix a bug: unable to build homepage custom stylesheet - Fix a bug: unable to access embedded plan views - Fix a bug: warning message overflow in credit wallet modal +- Fix a bug: when a cash coupon was used, an invalid amount is shown in the statistics - [TODO DEPLOY] `rails fablab:stripe:plans_prices` - [TODO DEPLOY] `rails fablab:maintenance:rebuild_stylesheet` diff --git a/app/services/coupon_service.rb b/app/services/coupon_service.rb index dde414508..68287c727 100644 --- a/app/services/coupon_service.rb +++ b/app/services/coupon_service.rb @@ -53,8 +53,8 @@ class CouponService ## # Ventilate the discount of the provided coupon over the given amount proportionately to the invoice's total - # @param total {Number} total amount of the invoice expressed in monetary units - # @param amount {Number} price of the invoice's sub-item expressed in monetary units + # @param total {Number} total amount of the invoice expressed in centimes + # @param amount {Number} price of the invoice's sub-item expressed in centimes # @param coupon {Coupon} coupon applied to the invoice, amount_off expressed in centimes if applicable ## def ventilate(total, amount, coupon) @@ -64,7 +64,7 @@ class CouponService price = amount - (amount * coupon.percent_off / 100.00) elsif coupon.type == 'amount_off' ratio = (coupon.amount_off / 100.00) / total - discount = amount * ratio.abs + discount = (amount * ratio.abs) * 100 price = amount - discount else raise InvalidCouponError @@ -77,9 +77,9 @@ class CouponService # Compute the total amount of the given invoice, without the applied coupon # Invoice.total stores the amount payed by the customer, coupon deducted # @param invoice {Invoice} invoice object, its total before discount will be computed + # @return {Number} total in centimes ## def invoice_total_no_coupon(invoice) - total = (invoice.invoice_items.map(&:amount).map(&:to_i).reduce(:+) or 0) - total / 100.0 + invoice.invoice_items.map(&:amount).map(&:to_i).reduce(:+) or 0 end end diff --git a/app/services/statistic_service.rb b/app/services/statistic_service.rb index 5b4c8725a..acf0cc895 100644 --- a/app/services/statistic_service.rb +++ b/app/services/statistic_service.rb @@ -134,9 +134,10 @@ class StatisticService next unless sub - ca = i.amount.to_i / 100.0 + ca = i.amount.to_i cs = CouponService.new ca = cs.ventilate(cs.invoice_total_no_coupon(i.invoice), ca, i.invoice.coupon) unless i.invoice.coupon_id.nil? + ca /= 100.00 profile = sub.statistic_profile p = sub.plan result.push OpenStruct.new({ diff --git a/test/fixtures/coupons.yml b/test/fixtures/coupons.yml index 41d78d4f4..f2d485c34 100644 --- a/test/fixtures/coupons.yml +++ b/test/fixtures/coupons.yml @@ -25,4 +25,13 @@ cash: valid_until: <%= 1.year.from_now.utc.strftime('%Y-%m-%d %H:%M:%S.%9N Z') %> max_usages: 1 active: true - validity_per_user: once \ No newline at end of file + validity_per_user: once + +cash2: + name: Small Cash Code + code: GIME3EUR + amount_off: 300 + valid_until: <%= 1.year.from_now.utc.strftime('%Y-%m-%d %H:%M:%S.%9N Z') %> + max_usages: nil + active: true + validity_per_user: once diff --git a/test/services/coupon_service_test.rb b/test/services/coupon_service_test.rb index 884145caa..17bac44a6 100644 --- a/test/services/coupon_service_test.rb +++ b/test/services/coupon_service_test.rb @@ -1,5 +1,8 @@ +# frozen_string_literal: true + require 'test_helper' +# In the following tests, amounts are expressed in centimes, ie. 1000 = 1000 cts = 10,00 EUR class CouponServiceTest < ActiveSupport::TestCase setup do @jdupond = User.find_by(username: 'jdupond') @@ -25,4 +28,16 @@ class CouponServiceTest < ActiveSupport::TestCase total = CouponService.new.apply(1000, 'XMAS10', @jdupond.id) assert_equal 1000, total end + + test 'ventilate 15 percent coupon' do + coupon = Coupon.find_by(code: 'SUNNYFABLAB') + total = CouponService.new.ventilate(1000, 500, coupon) + assert_equal 425, total + end + + test 'ventilate 100 euros coupon' do + coupon = Coupon.find_by(code: 'GIME3EUR') + total = CouponService.new.ventilate(1000, 500, coupon) + assert_equal 350, total + end end