mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2024-11-29 10:24:20 +01:00
updates users_credits module and manager and adds tests
This commit is contained in:
parent
28fcd121b4
commit
823b4c5e1d
136
app/services/users_credits/manager.rb
Normal file
136
app/services/users_credits/manager.rb
Normal file
@ -0,0 +1,136 @@
|
||||
require 'forwardable'
|
||||
|
||||
module UsersCredits
|
||||
class AlreadyUpdatedError < StandardError;end;
|
||||
|
||||
class Manager
|
||||
extend Forwardable
|
||||
attr_reader :manager
|
||||
|
||||
def initialize(reservation: nil, user: nil)
|
||||
if user
|
||||
@manager = Managers::User.new(user)
|
||||
elsif reservation
|
||||
if reservation.reservable_type == "Training"
|
||||
@manager = Managers::Training.new(reservation)
|
||||
elsif reservation.reservable_type == "Machine"
|
||||
@manager = Managers::Machine.new(reservation)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def_delegators :@manager, :will_use_credits?, :free_hours_count, :update_credits, :reset_credits
|
||||
end
|
||||
|
||||
module Managers
|
||||
class User
|
||||
attr_reader :user
|
||||
|
||||
def initialize(user)
|
||||
@user = user
|
||||
end
|
||||
|
||||
def reset_credits
|
||||
user.users_credits.destroy_all
|
||||
end
|
||||
end
|
||||
|
||||
class Reservation
|
||||
attr_reader :reservation
|
||||
|
||||
def initialize(reservation)
|
||||
@reservation = reservation
|
||||
@already_updated = false
|
||||
end
|
||||
|
||||
def plan
|
||||
user.subscribed_plan
|
||||
end
|
||||
|
||||
def user
|
||||
reservation.user
|
||||
end
|
||||
|
||||
def update_credits
|
||||
if @already_updated
|
||||
raise AlreadyUpdatedError, "update credit is not idempotent ! you can't invoke update_credits method twice."
|
||||
else
|
||||
@already_updated = true
|
||||
end
|
||||
end
|
||||
end
|
||||
private_constant :Reservation
|
||||
|
||||
|
||||
class Machine < Reservation
|
||||
def will_use_credits?
|
||||
_will_use_credits?[0]
|
||||
end
|
||||
|
||||
def free_hours_count
|
||||
_will_use_credits?[1]
|
||||
end
|
||||
|
||||
def update_credits
|
||||
super
|
||||
|
||||
will_use_credits, free_hours_count, machine_credit = _will_use_credits?
|
||||
if will_use_credits
|
||||
users_credit = user.users_credits.find_or_initialize_by(credit_id: machine_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?
|
||||
if machine_credit = plan.machine_credits.find_by(creditable_id: reservation.reservable_id)
|
||||
users_credit = user.users_credits.find_by(credit_id: machine_credit.id)
|
||||
already_used_hours = users_credit ? users_credit.hours_used : 0
|
||||
|
||||
remaining_hours = machine_credit.hours - already_used_hours
|
||||
|
||||
free_hours_count = [remaining_hours, reservation.slots.size].min
|
||||
|
||||
if free_hours_count > 0
|
||||
return true, free_hours_count, machine_credit
|
||||
else
|
||||
return false, free_hours_count, machine_credit
|
||||
end
|
||||
end
|
||||
return false, 0
|
||||
end
|
||||
end
|
||||
|
||||
class Training < Reservation
|
||||
def will_use_credits?
|
||||
_will_use_credits?[0]
|
||||
end
|
||||
|
||||
def update_credits
|
||||
super
|
||||
will_use_credits, training_credit = _will_use_credits?
|
||||
if will_use_credits
|
||||
user.credits << training_credit # we create a new UsersCredit object
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def _will_use_credits?
|
||||
# if there is a training_credit defined for this plan and this training
|
||||
if training_credit = plan.training_credits.find_by(creditable_id: reservation.reservable_id)
|
||||
# if user has not used all the plan credits
|
||||
if user.training_credits.count < plan.training_credit_nb
|
||||
return true, training_credit
|
||||
end
|
||||
end
|
||||
return false, nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -1,82 +0,0 @@
|
||||
class UsersCreditsManager
|
||||
attr_reader :manager
|
||||
|
||||
def initialize(reservation)
|
||||
if reservation.reservable_type == "Training"
|
||||
@manager = Training.new(reservation)
|
||||
elsif reservation.reservable_type == "Machine"
|
||||
@manager = Machine.new(reservation)
|
||||
end
|
||||
end
|
||||
|
||||
class Machine < Manager
|
||||
def will_use_credits?
|
||||
end
|
||||
|
||||
def credited_hours_number
|
||||
end
|
||||
|
||||
def update
|
||||
super
|
||||
end
|
||||
|
||||
private
|
||||
def _will_use_credits?
|
||||
end
|
||||
end
|
||||
|
||||
class Training < Manager
|
||||
def will_use_credits?
|
||||
_will_use_credits?[0]
|
||||
end
|
||||
|
||||
def update
|
||||
super
|
||||
will_use_credits, training_credit = _will_use_credits?
|
||||
if will_use_credits
|
||||
user.credits << training_credit # we create a new UsersCredit object
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def _will_use_credits?
|
||||
# if there is a training_credit defined for this plan and this training
|
||||
if training_credit = plan.training_credits.find_by(creditable_id: reservation.reservable_id)
|
||||
# if user has not used all the plan credits
|
||||
if user.training_credits.count < plan.training_credit_nb
|
||||
return true, training_credit
|
||||
end
|
||||
end
|
||||
return false, nil
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
class Manager
|
||||
attr_reader :reservation
|
||||
|
||||
def initialize(reservation)
|
||||
@reservation = reservation
|
||||
@already_updated = false
|
||||
end
|
||||
|
||||
def plan
|
||||
user.subscribed_plan
|
||||
end
|
||||
|
||||
def user
|
||||
reservation.user
|
||||
end
|
||||
|
||||
def update
|
||||
if @already_updated
|
||||
raise AlreadyUpdated, "update credit is not idempotent ! do not try to update twice."
|
||||
else
|
||||
@already_updated = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class AlreadyUpdated < StandardError
|
||||
end
|
||||
end
|
162
test/services/users_credits_manager_test.rb
Normal file
162
test/services/users_credits_manager_test.rb
Normal file
@ -0,0 +1,162 @@
|
||||
require 'test_helper'
|
||||
|
||||
class UsersCreditsManagerTest < ActiveSupport::TestCase
|
||||
setup do
|
||||
@machine = Machine.find(6)
|
||||
@training = Training.find(2)
|
||||
@plan = Plan.find(3)
|
||||
@user = User.joins(:subscriptions).find_by(subscriptions: { plan: @plan })
|
||||
@availability = @machine.availabilities.first
|
||||
@reservation_machine = Reservation.new(user: @user, reservable: @machine)
|
||||
@reservation_training = Reservation.new(user: @user, reservable: @training)
|
||||
end
|
||||
|
||||
## context machine reservation
|
||||
|
||||
test "machine reservation without credit associated" do
|
||||
Credit.where(creditable: @machine).destroy_all
|
||||
|
||||
@reservation_machine.assign_attributes(slots_attributes: [{
|
||||
start_at: @availability.start_at, end_at: @availability.start_at + 1.hour, availability_id: @availability.id
|
||||
}])
|
||||
manager = UsersCredits::Manager.new(reservation: @reservation_machine)
|
||||
|
||||
assert_equal false, manager.will_use_credits?
|
||||
assert_equal 0, manager.free_hours_count
|
||||
|
||||
assert_no_difference 'UsersCredit.count' do
|
||||
manager.update_credits
|
||||
end
|
||||
|
||||
assert_raise UsersCredits::AlreadyUpdatedError do
|
||||
manager.update_credits
|
||||
end
|
||||
end
|
||||
|
||||
test "machine reservation with credit associated and user never used his credit" do
|
||||
credit = Credit.find_by!(creditable: @machine, plan: @plan)
|
||||
credit.update!(hours: 2)
|
||||
@user.users_credits.destroy_all
|
||||
|
||||
@reservation_machine.assign_attributes(slots_attributes: [{
|
||||
start_at: @availability.start_at, end_at: @availability.start_at + 1.hour, availability_id: @availability.id
|
||||
}])
|
||||
manager = UsersCredits::Manager.new(reservation: @reservation_machine)
|
||||
|
||||
assert_equal true, manager.will_use_credits?
|
||||
assert_equal 1, manager.free_hours_count
|
||||
|
||||
assert_difference 'UsersCredit.count' do
|
||||
manager.update_credits
|
||||
end
|
||||
|
||||
assert_raise UsersCredits::AlreadyUpdatedError do
|
||||
manager.update_credits
|
||||
end
|
||||
end
|
||||
|
||||
test "machine reservation with credit associated and user already used partially his credit" do
|
||||
credit = Credit.find_by!(creditable: @machine, plan: @plan)
|
||||
credit.update!(hours: 2)
|
||||
users_credit = @user.users_credits.create!(credit: credit, hours_used: 1)
|
||||
|
||||
@reservation_machine.assign_attributes(slots_attributes: [
|
||||
{ start_at: @availability.start_at, end_at: @availability.start_at + 1.hour, availability_id: @availability.id },
|
||||
{ start_at: @availability.start_at + 1.hour, end_at: @availability.start_at + 2.hour, availability_id: @availability.id }
|
||||
])
|
||||
|
||||
manager = UsersCredits::Manager.new(reservation: @reservation_machine)
|
||||
|
||||
assert_equal true, manager.will_use_credits?
|
||||
assert_equal 1, manager.free_hours_count
|
||||
|
||||
assert_no_difference 'UsersCredit.count' do
|
||||
manager.update_credits
|
||||
end
|
||||
|
||||
users_credit.reload
|
||||
assert_equal 2, users_credit.hours_used
|
||||
end
|
||||
|
||||
test "machine reservation with credit associated and user already used all credit" do
|
||||
credit = Credit.find_by!(creditable: @machine, plan: @plan)
|
||||
users_credit = @user.users_credits.create!(credit: credit, hours_used: 1)
|
||||
|
||||
@reservation_machine.assign_attributes(slots_attributes: [
|
||||
{ start_at: @availability.start_at, end_at: @availability.start_at + 1.hour, availability_id: @availability.id },
|
||||
{ start_at: @availability.start_at + 1.hour, end_at: @availability.start_at + 2.hour, availability_id: @availability.id }
|
||||
])
|
||||
manager = UsersCredits::Manager.new(reservation: @reservation_machine)
|
||||
|
||||
assert_equal false, manager.will_use_credits?
|
||||
assert_equal 0, manager.free_hours_count
|
||||
|
||||
assert_no_difference 'UsersCredit.count' do
|
||||
manager.update_credits
|
||||
end
|
||||
|
||||
users_credit.reload
|
||||
assert_equal 1, users_credit.hours_used
|
||||
end
|
||||
|
||||
# context training reservation
|
||||
|
||||
test "training reservation without credit associated" do
|
||||
Credit.where(creditable: @training).destroy_all
|
||||
|
||||
manager = UsersCredits::Manager.new(reservation: @reservation_training)
|
||||
|
||||
assert_equal false, manager.will_use_credits?
|
||||
|
||||
assert_no_difference 'UsersCredit.count' do
|
||||
manager.update_credits
|
||||
end
|
||||
|
||||
assert_raise UsersCredits::AlreadyUpdatedError do
|
||||
manager.update_credits
|
||||
end
|
||||
end
|
||||
|
||||
test "training reservation with credit associated and user didnt use his credit yet" do
|
||||
credit = Credit.find_or_create_by!(creditable: @training, plan: @plan)
|
||||
@user.users_credits.destroy_all
|
||||
|
||||
manager = UsersCredits::Manager.new(reservation: @reservation_training)
|
||||
|
||||
assert_equal true, manager.will_use_credits?
|
||||
|
||||
assert_difference 'UsersCredit.count' do
|
||||
manager.update_credits
|
||||
end
|
||||
end
|
||||
|
||||
test "training reservation with credit associated but user already used all his credits" do
|
||||
@user.users_credits.destroy_all
|
||||
another_training = Training.where.not(id: @training.id).first
|
||||
credit = Credit.find_or_create_by!(creditable: another_training, plan: @plan)
|
||||
@user.users_credits.find_or_create_by!(credit: credit)
|
||||
@plan.update(training_credit_nb: 1)
|
||||
|
||||
manager = UsersCredits::Manager.new(reservation: @reservation_training)
|
||||
|
||||
assert_equal false, manager.will_use_credits?
|
||||
|
||||
assert_no_difference 'UsersCredit.count' do
|
||||
manager.update_credits
|
||||
end
|
||||
end
|
||||
|
||||
# context reset user credits
|
||||
|
||||
test "use UsersCredit::Manager to reset users_credits" do
|
||||
credit = Credit.find_by!(creditable: @machine, plan: @plan)
|
||||
users_credit = @user.users_credits.create!(credit: credit, hours_used: 1)
|
||||
|
||||
assert_not_empty @user.users_credits
|
||||
|
||||
manager = UsersCredits::Manager.new(user: @user)
|
||||
manager.reset_credits
|
||||
|
||||
assert_empty @user.users_credits.reload
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue
Block a user