Files
openfoodnetwork/app/services/order_factory.rb
2020-06-22 16:51:43 +01:00

95 lines
2.2 KiB
Ruby

require 'open_food_network/scope_variant_to_hub'
# Builds orders based on a set of attributes
# There are some idiosyncracies in the order creation process,
# and it is nice to have them dealt with in one place.
class OrderFactory
def initialize(attrs, opts = {})
@attrs = attrs.with_indifferent_access
@opts = opts.with_indifferent_access
end
def create
create_order
set_user
build_line_items
set_addresses
create_shipment
set_shipping_method
create_payment
@order
end
private
attr_reader :attrs, :opts
def customer
@customer ||= Customer.find(attrs[:customer_id])
end
def shop
@shop ||= Enterprise.find(attrs[:distributor_id])
end
def create_order
@order = Spree::Order.create!(create_attrs)
end
def create_attrs
create_attrs = attrs.slice(:customer_id, :order_cycle_id, :distributor_id)
create_attrs[:email] = customer.email
create_attrs
end
def build_line_items
attrs[:line_items].each do |li|
next unless variant = Spree::Variant.find_by(id: li[:variant_id])
scoper.scope(variant)
li[:quantity] = stock_limited_quantity(variant.on_demand, variant.on_hand, li[:quantity])
li[:price] = variant.price
build_item_from(li)
end
end
def build_item_from(attrs)
@order.line_items.build(
attrs.merge(skip_stock_check: opts[:skip_stock_check])
)
end
def set_user
@order.update_attribute(:user_id, customer.user_id)
end
def set_addresses
@order.update(attrs.slice(:bill_address_attributes, :ship_address_attributes))
end
def create_shipment
@order.create_proposed_shipments
end
def set_shipping_method
@order.select_shipping_method(attrs[:shipping_method_id])
end
def create_payment
@order.update_distribution_charge!
@order.payments.create(payment_method_id: attrs[:payment_method_id], amount: @order.reload.total)
end
def stock_limited_quantity(variant_on_demand, variant_on_hand, requested)
return requested if opts[:skip_stock_check] || variant_on_demand
[variant_on_hand, requested].min
end
def scoper
@scoper ||= OpenFoodNetwork::ScopeVariantToHub.new(shop)
end
end