diff --git a/app/models/price.rb b/app/models/price.rb index ddb95a6d3..1f3e6468f 100644 --- a/app/models/price.rb +++ b/app/models/price.rb @@ -112,7 +112,7 @@ class Price < ActiveRecord::Base # === apply Coupon if any === _amount_no_coupon = _amount - _amount = CouponApplyService.new.(_amount, coupon_code) + _amount = CouponService.new.apply(_amount, coupon_code) # return result {elements: _elements, total: _amount, before_coupon: _amount_no_coupon} diff --git a/app/models/reservation.rb b/app/models/reservation.rb index 5f74e4b3c..7214597c4 100644 --- a/app/models/reservation.rb +++ b/app/models/reservation.rb @@ -409,7 +409,7 @@ class Reservation < ActiveRecord::Base def get_wallet_amount_debit total = get_cart_total if @coupon - total = CouponApplyService.new.(total, @coupon, user.id) + total = CouponService.new.apply(total, @coupon, user.id) end wallet_amount = (user.wallet.amount * 100).to_i @@ -443,7 +443,7 @@ class Reservation < ActiveRecord::Base unless coupon_code.nil? cp = Coupon.find_by(code: coupon_code) if not cp.nil? and cp.status(user.id) == 'active' - total = CouponApplyService.new.(total, cp, user.id) + total = CouponService.new.apply(total, cp, user.id) self.invoice.coupon_id = cp.id else raise InvalidCouponError diff --git a/app/models/subscription.rb b/app/models/subscription.rb index b6224a6e0..dae9d6d4f 100644 --- a/app/models/subscription.rb +++ b/app/models/subscription.rb @@ -178,7 +178,7 @@ class Subscription < ActiveRecord::Base @coupon = Coupon.find_by(code: coupon_code) unless @coupon.nil? - total = CouponApplyService.new.(plan.amount, @coupon, user.id) + total = CouponService.new.apply(plan.amount, @coupon, user.id) coupon_id = @coupon.id end end @@ -309,7 +309,7 @@ class Subscription < ActiveRecord::Base def get_wallet_amount_debit total = plan.amount if @coupon - total = CouponApplyService.new.(total, @coupon, user.id) + total = CouponService.new.apply(total, @coupon, user.id) end wallet_amount = (user.wallet.amount * 100).to_i return wallet_amount >= total ? total : wallet_amount diff --git a/app/services/coupon_service.rb b/app/services/coupon_service.rb index 0da03e83b..7600de148 100644 --- a/app/services/coupon_service.rb +++ b/app/services/coupon_service.rb @@ -1,4 +1,4 @@ -class CouponApplyService +class CouponService ## # Apply the provided coupon, if active, to the given price. Usability tests will be run depending on the # provided parameters. @@ -9,7 +9,7 @@ class CouponApplyService # @param user_id {Number} user's id against the coupon will be tested for usability # @return {Number} ## - def call(total, coupon, user_id = nil) + def apply(total, coupon, user_id = nil) price = total _coupon = nil @@ -34,4 +34,27 @@ class CouponApplyService price end + + + ## + # 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 coupon {Coupon} coupon applied to the invoice, amount_off expressed in centimes if applicable + ## + def ventilate(total, amount, coupon) + price = amount + if !coupon.nil? and total != 0 + if coupon.type == 'percent_off' + price = amount - ( amount * coupon.percent_off / 100.0 ) + elsif coupon.type == 'amount_off' + ratio = (coupon.amount_off / 100.0) / total + discount = amount * ratio.abs + price = amount - discount + else + raise InvalidCouponError + end + end + price + end end \ No newline at end of file diff --git a/app/services/statistic_service.rb b/app/services/statistic_service.rb index f22c47b26..b824e370e 100644 --- a/app/services/statistic_service.rb +++ b/app/services/statistic_service.rb @@ -127,7 +127,7 @@ class StatisticService if sub ca = i.amount.to_i / 100.0 unless i.invoice.coupon_id.nil? - ca = CouponApplyService.new.(ca, i.invoice.coupon) + ca = CouponService.new.ventilate(get_invoice_total_no_coupon(i.invoice), ca, i.invoice.coupon) end u = sub.user p = sub.plan @@ -261,7 +261,7 @@ class StatisticService def members_list(options = default_options) result = [] User.with_role(:member).includes(:profile).where('users.created_at >= :start_date AND users.created_at <= :end_date', options).each do |u| - if !u.need_completion? + unless u.need_completion? result.push OpenStruct.new({ date: options[:start_date].to_date }.merge(user_info(u))) @@ -353,7 +353,7 @@ class StatisticService end # subtract coupon discount from invoices and refunds unless invoice.coupon_id.nil? - ca = CouponApplyService.new.(ca, invoice.coupon) + ca = CouponService.new.ventilate(get_invoice_total_no_coupon(invoice), ca, invoice.coupon) end # divide the result by 100 to convert from centimes to monetary unit ca == 0 ? ca : ca / 100.0 @@ -366,7 +366,7 @@ class StatisticService end # subtract coupon discount from the refund unless invoice.coupon_id.nil? - ca = CouponApplyService.new.(ca, invoice.coupon) + ca = CouponService.new.ventilate(get_invoice_total_no_coupon(invoice), ca, invoice.coupon) end ca == 0 ? ca : ca / 100.0 end @@ -451,6 +451,11 @@ class StatisticService user_subscription_ca.inject {|sum,x| sum.ca + x.ca } || 0 end + def get_invoice_total_no_coupon(invoice) + total = (invoice.invoice_items.map(&:amount).map(&:to_i).reduce(:+) or 0) + total / 100.0 + end + def find_or_create_user_info_info_list(user, list) found = list.select do |l| l.user_id == user.id diff --git a/test/services/coupon_service_test.rb b/test/services/coupon_service_test.rb index f42db7f9c..884145caa 100644 --- a/test/services/coupon_service_test.rb +++ b/test/services/coupon_service_test.rb @@ -7,22 +7,22 @@ class CouponServiceTest < ActiveSupport::TestCase end test 'user apply percent coupon to cart' do - total = CouponService.new.(1000, 'SUNNYFABLAB', @jdupond.id) + total = CouponService.new.apply(1000, 'SUNNYFABLAB', @jdupond.id) assert_equal 850, total end test 'user cannot apply excessive coupon to cart' do - total = CouponService.new.(1000, @cash_coupon, @jdupond.id) + total = CouponService.new.apply(1000, @cash_coupon, @jdupond.id) assert_equal 1000, total end test 'user cannot apply invalid coupon to cart' do - total = CouponService.new.(1000, 'INVALIDCODE', @jdupond.id) + total = CouponService.new.apply(1000, 'INVALIDCODE', @jdupond.id) assert_equal 1000, total end test 'user cannot apply expired coupon to cart' do - total = CouponService.new.(1000, 'XMAS10', @jdupond.id) + total = CouponService.new.apply(1000, 'XMAS10', @jdupond.id) assert_equal 1000, total end end