From 43f78ff0e0a391a2cd5ee37a0e2f7f5b3884b255 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Mon, 27 Feb 2017 17:38:15 +0100 Subject: [PATCH] fix credits usage in space reservation --- app/models/plan.rb | 1 + app/models/price.rb | 50 +++++++++++++++++++-------- app/models/reservation.rb | 6 ++++ app/services/users_credits/manager.rb | 42 ++++++++++++++++++++-- 4 files changed, 83 insertions(+), 16 deletions(-) diff --git a/app/models/plan.rb b/app/models/plan.rb index 2248fa343..42f4e1f67 100644 --- a/app/models/plan.rb +++ b/app/models/plan.rb @@ -4,6 +4,7 @@ class Plan < ActiveRecord::Base has_many :credits, dependent: :destroy has_many :training_credits, -> {where(creditable_type: 'Training')}, class_name: 'Credit' has_many :machine_credits, -> {where(creditable_type: 'Machine')}, class_name: 'Credit' + has_many :space_credits, -> {where(creditable_type: 'Space')}, class_name: 'Credit' has_many :subscriptions has_one :plan_image, as: :viewable, dependent: :destroy has_one :plan_file, as: :viewable, dependent: :destroy diff --git a/app/models/price.rb b/app/models/price.rb index 2f192e19d..7516fb70c 100644 --- a/app/models/price.rb +++ b/app/models/price.rb @@ -31,6 +31,7 @@ class Price < ActiveRecord::Base new_plan_being_bought = true else plan = nil + new_plan_being_bought = false end # === compute reservation price === @@ -41,13 +42,13 @@ class Price < ActiveRecord::Base when Machine base_amount = reservable.prices.find_by(group_id: user.group_id, plan_id: plan.try(:id)).amount if plan - machine_credit = plan.machine_credits.select {|credit| credit.creditable_id == reservable.id}.first - if machine_credit - hours_available = machine_credit.hours - if !new_plan_being_bought - user_credit = user.users_credits.find_by(credit_id: machine_credit.id) + space_credit = plan.machine_credits.select {|credit| credit.creditable_id == reservable.id}.first + if space_credit + hours_available = space_credit.hours + unless new_plan_being_bought + user_credit = user.users_credits.find_by(credit_id: space_credit.id) if user_credit - hours_available = machine_credit.hours - user_credit.hours_used + hours_available = space_credit.hours - user_credit.hours_used end end slots.each_with_index do |slot, index| @@ -69,18 +70,18 @@ class Price < ActiveRecord::Base amount = reservable.amount_by_group(user.group_id).amount if plan # Return True if the subscription link a training credit for training reserved by the user - training_is_creditable = plan.training_credits.select {|credit| credit.creditable_id == reservable.id}.size > 0 + space_is_creditable = plan.training_credits.select {|credit| credit.creditable_id == reservable.id}.size > 0 # Training reserved by the user is free when : - # |-> the user already has a current subscription and if training_is_creditable is true and has at least one credit available. + # |-> the user already has a current subscription and if space_is_creditable is true and has at least one credit available. if !new_plan_being_bought - if user.training_credits.size < plan.training_credit_nb and training_is_creditable + if user.training_credits.size < plan.training_credit_nb and space_is_creditable amount = 0 end - # |-> the user buys a new subscription and if training_is_creditable is true. + # |-> the user buys a new subscription and if space_is_creditable is true. else - if training_is_creditable + if space_is_creditable amount = 0 end end @@ -101,9 +102,30 @@ class Price < ActiveRecord::Base # Space reservation when Space - amount = reservable.prices.find_by(group_id: user.group_id, plan_id: plan.try(:id)).amount - slots.each do |slot| - _amount += get_slot_price(amount, slot, admin, _elements) + base_amount = reservable.prices.find_by(group_id: user.group_id, plan_id: plan.try(:id)).amount + + if plan + space_credit = plan.space_credits.select {|credit| credit.creditable_id == reservable.id}.first + if space_credit + hours_available = space_credit.hours + unless new_plan_being_bought + user_credit = user.users_credits.find_by(credit_id: space_credit.id) + if user_credit + hours_available = space_credit.hours - user_credit.hours_used + end + end + slots.each_with_index do |slot, index| + _amount += get_slot_price(base_amount, slot, admin, _elements, (index < hours_available)) + end + else + slots.each do |slot| + _amount += get_slot_price(base_amount, slot, admin, _elements) + end + end + else + slots.each do |slot| + _amount += get_slot_price(base_amount, slot, admin, _elements) + end end # Unknown reservation type diff --git a/app/models/reservation.rb b/app/models/reservation.rb index 5d22d97d9..35d0b0fcc 100644 --- a/app/models/reservation.rb +++ b/app/models/reservation.rb @@ -132,11 +132,17 @@ class Reservation < ActiveRecord::Base # === Space reservation === when Space base_amount = reservable.prices.find_by(group_id: user.group_id, plan_id: plan.try(:id)).amount + users_credits_manager = UsersCredits::Manager.new(reservation: self, plan: plan) slots.each_with_index do |slot, index| description = reservable.name + " #{I18n.l slot.start_at, format: :long} - #{I18n.l slot.end_at, format: :hour_minute}" ii_amount = base_amount # ii_amount default to base_amount + + if users_credits_manager.will_use_credits? + ii_amount = (index < users_credits_manager.free_hours_count) ? 0 : base_amount + end + ii_amount = 0 if slot.offered and on_site # if it's a local payment and slot is offered free unless on_site # if it's local payment then do not create Stripe::InvoiceItem diff --git a/app/services/users_credits/manager.rb b/app/services/users_credits/manager.rb index eb29dc347..befeee260 100644 --- a/app/services/users_credits/manager.rb +++ b/app/services/users_credits/manager.rb @@ -156,11 +156,49 @@ module UsersCredits end class Space < Reservation - def will_use_credits? - false + def will_use_credits? # to known if a credit will be used in the context of the given reservation + _will_use_credits?[0] + end + + def free_hours_count + _will_use_credits?[1] end def update_credits + super + + will_use_credits, free_hours_count, space_credit = _will_use_credits? + if will_use_credits + users_credit = user.users_credits.find_or_initialize_by(credit_id: space_credit.id) + + if users_credit.new_record? + users_credit.hours_used = free_hours_count + else + users_credit.hours_used += free_hours_count + end + users_credit.save! + end + end + + private + def _will_use_credits? + return false, 0 unless plan + + if space_credit = plan.space_credits.find_by(creditable_id: reservation.reservable_id) + users_credit = user.users_credits.find_by(credit_id: space_credit.id) + already_used_hours = users_credit ? users_credit.hours_used : 0 + + remaining_hours = space_credit.hours - already_used_hours + + free_hours_count = [remaining_hours, reservation.slots.size].min + + if free_hours_count > 0 + return true, free_hours_count, space_credit + else + return false, free_hours_count, space_credit + end + end + return false, 0 end end end