mergeShippingAddress($request); $this->saveAddress($request); $this->addShippingMethodToCart($request); return tap($this->store($request), function ($order) { $this->storeOrderProducts($order); $this->storeOrderDownloads($order); $this->storeFlashSaleProductOrders($order); $this->incrementCouponUsage($order); $this->attachTaxes($order); $this->reduceStock(); }); } private function mergeShippingAddress($request) { $request->merge([ 'shipping' => $request->ship_to_a_different_address ? $request->shipping : $request->billing, ]); } private function saveAddress($request) { if (auth()->guest()) { return; } if ($request->newBillingAddress) { $address = auth() ->user() ->addresses() ->create($this->extractAddress($request->billing)); $this->makeDefaultAddress($address); } if ($request->ship_to_a_different_address && $request->newShippingAddress) { auth() ->user() ->addresses() ->create($this->extractAddress($request->shipping)); } } private function extractAddress($data) { return [ 'first_name' => $data['first_name'], 'last_name' => $data['last_name'], 'address_1' => $data['address_1'], 'address_2' => $data['address_2'] ?? null, 'city' => $data['city'], 'state' => $data['state'], 'zip' => $data['zip'], 'country' => $data['country'], ]; } private function makeDefaultAddress(Address $address) { if ( auth() ->user() ->addresses() ->count() > 1 ) { return; } DefaultAddress::create([ 'address_id' => $address->id, 'customer_id' => auth()->id(), ]); } private function addShippingMethodToCart($request) { if (!Cart::allItemsAreVirtual() && !Cart::hasShippingMethod()) { Cart::addShippingMethod(ShippingMethod::get($request->shipping_method)); } } private function store($request) { return Order::create([ 'customer_id' => auth()->id(), 'customer_email' => $request->customer_email, 'customer_phone' => $request->customer_phone, 'customer_first_name' => $request->billing['first_name'], 'customer_last_name' => $request->billing['last_name'], 'billing_first_name' => $request->billing['first_name'], 'billing_last_name' => $request->billing['last_name'], 'billing_address_1' => $request->billing['address_1'], 'billing_address_2' => $request->billing['address_2'] ?? null, 'billing_city' => $request->billing['city'], 'billing_state' => $request->billing['state'], 'billing_zip' => $request->billing['zip'], 'billing_country' => $request->billing['country'], 'shipping_first_name' => $request->shipping['first_name'], 'shipping_last_name' => $request->shipping['last_name'], 'shipping_address_1' => $request->shipping['address_1'], 'shipping_address_2' => $request->shipping['address_2'] ?? null, 'shipping_city' => $request->shipping['city'], 'shipping_state' => $request->shipping['state'], 'shipping_zip' => $request->shipping['zip'], 'shipping_country' => $request->shipping['country'], 'sub_total' => Cart::subTotal()->amount(), 'shipping_method' => Cart::shippingMethod()->name(), 'shipping_cost' => Cart::shippingCost()->amount(), 'coupon_id' => Cart::coupon()->id(), 'discount' => Cart::discount()->amount(), 'total' => Cart::total()->amount(), 'payment_method' => $request->payment_method, 'currency' => currency(), 'currency_rate' => CurrencyRate::for(currency()), 'locale' => locale(), 'status' => Order::PENDING_PAYMENT, 'note' => $request->order_note, ]); } private function storeOrderProducts(Order $order) { Cart::items()->each(function (CartItem $cartItem) use ($order) { $order->storeProducts($cartItem); }); } private function storeOrderDownloads(Order $order) { Cart::items()->each(function (CartItem $cartItem) use ($order) { $order->storeDownloads($cartItem); }); } private function storeFlashSaleProductOrders(Order $order) { Cart::items()->each(function (CartItem $cartItem) use ($order) { if (!FlashSale::contains($cartItem->product)) { return; } FlashSale::pivot($cartItem->product) ->orders() ->attach([ $cartItem->product->id => [ 'order_id' => $order->id, 'qty' => $cartItem->qty, ], ]); }); } private function incrementCouponUsage() { Cart::coupon()->usedOnce(); } private function attachTaxes(Order $order) { Cart::taxes()->each(function (CartTax $cartTax) use ($order) { $order->attachTax($cartTax); }); } public function reduceStock() { Cart::reduceStock(); } public function delete(Order $order) { $order->delete(); Cart::restoreStock(); } }