1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2024-12-13 23:48:55 +01:00
fab-manager/app/services/cart/find_or_create_service.rb

107 lines
3.8 KiB
Ruby

# frozen_string_literal: true
# Provides methods for find or create a cart
class Cart::FindOrCreateService
def initialize(operator = nil, customer = nil)
@operator = operator
@customer = customer
@customer = operator if @customer.nil? && operator&.member?
end
def call(order_token)
@order = Order.find_by(token: order_token, state: 'cart')
check_order_authorization
@order = last_cart if @order.nil?
check_operator_authorization
# find an existing order (and update it)
if @order
set_last_order_after_login
clean_old_cart
@order.update(statistic_profile_id: @customer.statistic_profile.id) if @order.statistic_profile_id.nil? && !@customer.nil?
@order.update(operator_profile_id: @operator.invoicing_profile.id) if @order.operator_profile_id.nil? && !@operator.nil?
Cart::UpdateTotalService.new.call(@order)
return @order
end
# OR create a new order
token = GenerateTokenService.new.call(Order)
order_param = {
token: token,
state: 'cart',
total: 0,
statistic_profile_id: @customer&.statistic_profile&.id,
operator_profile_id: @operator&.invoicing_profile&.id
}
Order.create!(order_param)
end
# This function check the access rights for the currently set order.
# If the rights are not validated, set the current order to nil
def check_order_authorization
# order belongs to the current user
@order = nil if belongs_to_another?(@order, @customer) && !@operator&.privileged?
# order has belonged to an user, but this user is not logged-in
@order = nil if !@operator && @order&.statistic_profile_id&.present?
# order creation date is before than the last paid order of the user
if @order&.statistic_profile_id&.present? && Order.where(statistic_profile_id: @order&.statistic_profile_id, state: 'paid')
.where('created_at > ?', @order&.created_at).last.present?
@order = nil
end
end
# Check that the current operator is allowed to operate on the current order
def check_operator_authorization
return if @order&.operator_profile_id.nil?
@order = nil if @order&.operator_profile_id != @operator&.invoicing_profile&.id
end
def belongs_to_another?(order, user)
order&.statistic_profile_id.present? && order&.statistic_profile_id != user&.statistic_profile&.id
end
# retrieve the last cart of the current user
def last_cart
return if @customer.nil?
last_paid_order = Order.where(statistic_profile_id: @customer&.statistic_profile&.id, state: 'paid')
.last
if last_paid_order
Order.where(statistic_profile_id: @customer&.statistic_profile&.id, state: 'cart')
.where('created_at > ?', last_paid_order.created_at)
.last
else
Order.where(statistic_profile_id: @customer&.statistic_profile&.id, state: 'cart')
.last
end
end
# Check if the provided order/cart is empty AND anonymous
def empty_and_anonymous?(order)
order&.order_items&.count&.zero? && (order&.operator_profile_id.nil? || order&.statistic_profile_id.nil?)
end
# If the current cart is empty and anonymous, set the current cart as the last unpaid order.
# This is relevant after the user has logged-in
def set_last_order_after_login
return unless empty_and_anonymous?(@order)
last_unpaid_order = last_cart
return if last_unpaid_order.nil? || last_unpaid_order.id == @order&.id
@order&.destroy
@order = last_unpaid_order
end
# delete all old cart if last cart of user isnt empty
# keep every user only one cart
def clean_old_cart
return if @customer.nil?
Order.where(statistic_profile_id: @customer&.statistic_profile&.id, state: 'cart')
.where.not(id: @order&.id)
.destroy_all
end
end