# frozen_string_literal: true require 'test_helper' class Trainings::AutoCancelServiceTest < ActiveSupport::TestCase include ApplicationHelper setup do @training = Training.find(4) @availability = Availability.find(22) end test 'auto cancel reservation with less reservations than the threshold' do Setting.set('wallet_module', false) @training.update(auto_cancel: true, auto_cancel_threshold: 3, auto_cancel_deadline: 24) customer = User.find(3) slot = @availability.slots.first r = Reservation.create!( reservable_id: @training.id, reservable_type: Training.name, slots_reservations_attributes: [{ slot_id: slot.id }], statistic_profile_id: StatisticProfile.find_by(user: customer).id ) Trainings::AutoCancelService.auto_cancel_reservations(@training) # Check availability was locked @availability.reload assert @availability.lock # Check reservation was cancelled r.reload assert_not_nil r.slots_reservations.first&.canceled_at # Check notification was sent to the user notification = Notification.find_by( notification_type_id: NotificationType.find_by(name: 'notify_member_training_auto_cancelled'), attached_object_type: 'SlotsReservation', attached_object_id: r.slots_reservations.first&.id ) assert_not_nil notification, 'user notification was not created' assert_not notification.get_meta_data(:auto_refund) # Check notification was sent to the admin notification = Notification.find_by( notification_type_id: NotificationType.find_by(name: 'notify_admin_training_auto_cancelled'), attached_object_type: 'Availability', attached_object_id: @availability.id ) assert_not_nil notification, 'admin notification was not created' assert_not notification.get_meta_data(:auto_refund) end test 'do not auto cancel reservation with more reservations than the threshold' do @training.update(auto_cancel: true, auto_cancel_threshold: 3, auto_cancel_deadline: 24) slot = @availability.slots.first # first reservation c1 = User.find(2) r1 = Reservation.create!( reservable_id: @training.id, reservable_type: Training.name, slots_reservations_attributes: [{ slot_id: slot.id }], statistic_profile_id: StatisticProfile.find_by(user: c1).id ) # second reservation c2 = User.find(3) r2 = Reservation.create!( reservable_id: @training.id, reservable_type: Training.name, slots_reservations_attributes: [{ slot_id: slot.id }], statistic_profile_id: StatisticProfile.find_by(user: c2).id ) # third reservation c3 = User.find(3) r3 = Reservation.create!( reservable_id: @training.id, reservable_type: Training.name, slots_reservations_attributes: [{ slot_id: slot.id }], statistic_profile_id: StatisticProfile.find_by(user: c3).id ) Trainings::AutoCancelService.auto_cancel_reservations(@training) # Check availability was not locked @availability.reload assert_not @availability.lock # Check nothing was cancelled r1.reload assert_nil r1.slots_reservations.first&.canceled_at r2.reload assert_nil r2.slots_reservations.first&.canceled_at r3.reload assert_nil r3.slots_reservations.first&.canceled_at # Check no notifications were sent assert_empty Notification.where( notification_type_id: NotificationType.find_by(name: 'notify_member_training_auto_cancelled'), attached_object_type: 'SlotsReservation', attached_object_id: [r1.slots_reservations.first&.id, r2.slots_reservations.first&.id, r3.slots_reservations.first&.id] ) assert_nil Notification.find_by( notification_type_id: NotificationType.find_by(name: 'notify_admin_training_auto_cancelled'), attached_object_type: 'Availability', attached_object_id: @availability.id ) end test 'auto cancel reservation but do not generate any refunds if it was free' do Setting.set('wallet_module', true) wallet_transactions = WalletTransaction.count @training.update(auto_cancel: true, auto_cancel_threshold: 3, auto_cancel_deadline: 24) # user 3 has subscription's credits from training 4 customer = User.find(3) slot = @availability.slots.first # Reserve through the cart service to get an invoice associated with the reservation cs = CartService.new(User.admins.first) cs.from_hash(ActionController::Parameters.new({ customer_id: customer.id, items: [ reservation: { reservable_id: @training.id, reservable_type: @training.class.name, slots_reservations_attributes: [{ slot_id: slot.id }] } ] })).build_and_save(nil, nil) # Go with cancelling Trainings::AutoCancelService.auto_cancel_reservations(@training) # Check reservation was cancelled r = Reservation.last assert_not_nil r.slots_reservations.first&.canceled_at # Check notification was sent to the user notification = Notification.find_by( notification_type_id: NotificationType.find_by(name: 'notify_member_training_auto_cancelled'), attached_object_type: 'SlotsReservation', attached_object_id: r.slots_reservations.first&.id ) assert_not_nil notification, 'user notification was not created' assert notification.get_meta_data(:auto_refund) # Check notification was sent to the admin notification = Notification.find_by( notification_type_id: NotificationType.find_by(name: 'notify_admin_training_auto_cancelled'), attached_object_type: 'Availability', attached_object_id: @availability.id ) assert_not_nil notification, 'admin notification was not created' assert notification.get_meta_data(:auto_refund) # Check customer was not refunded on his wallet assert_equal wallet_transactions, WalletTransaction.count end test 'auto cancel reservation and generate a refund' do Setting.set('wallet_module', true) wallet_transactions = WalletTransaction.count @training.update(auto_cancel: true, auto_cancel_threshold: 3, auto_cancel_deadline: 24) customer = User.find(4) slot = @availability.slots.first # Reserve through the cart service to get an invoice associated with the reservation cs = CartService.new(User.admins.first) cs.from_hash(ActionController::Parameters.new({ customer_id: customer.id, items: [ reservation: { reservable_id: @training.id, reservable_type: @training.class.name, slots_reservations_attributes: [{ slot_id: slot.id }] } ] })).build_and_save(nil, nil) # Go with cancelling Trainings::AutoCancelService.auto_cancel_reservations(@training) # Check reservation was cancelled r = Reservation.last assert_not_nil r.slots_reservations.first&.canceled_at # Check notification was sent to the user notification = Notification.find_by( notification_type_id: NotificationType.find_by(name: 'notify_member_training_auto_cancelled'), attached_object_type: 'SlotsReservation', attached_object_id: r.slots_reservations.first&.id ) assert_not_nil notification, 'user notification was not created' assert notification.get_meta_data(:auto_refund) # Check notification was sent to the admin notification = Notification.find_by( notification_type_id: NotificationType.find_by(name: 'notify_admin_training_auto_cancelled'), attached_object_type: 'Availability', attached_object_id: @availability.id ) assert_not_nil notification, 'admin notification was not created' assert notification.get_meta_data(:auto_refund) # Check customer was refunded on his wallet assert_equal wallet_transactions + 1, WalletTransaction.count transaction = WalletTransaction.last assert_equal transaction.wallet.user.id, customer.id assert_equal transaction.transaction_type, 'credit' assert_equal to_centimes(transaction.amount), r.invoice_items.first.amount end test 'training with default general parameters' do assert_not Trainings::AutoCancelService.override_settings?(@training) end test 'training with specific parameters' do @training.update(auto_cancel: true, auto_cancel_threshold: 3, auto_cancel_deadline: 24) assert Trainings::AutoCancelService.override_settings?(@training) end end