HEX
Server: Microsoft-IIS/8.5
System: Windows NT YDAWBH120 6.3 build 9600 (Windows Server 2012 R2 Standard Edition) AMD64
User: tentjecom_web (0)
PHP: 7.4.14
Disabled: NONE
Upload Files
File: D:/HostingSpaces/SBogers10/spire-checkout.komma-mediadesign.nl/app/KommaApp/Orders/OrderService.php
<?php


namespace App\KommaApp\Orders;


use App\KommaApp\Countries\CountryService;
use App\KommaApp\Orders\Models\Order;
use App\KommaApp\Orders\Models\OrderPayment;
use App\KommaApp\ShoppingCart\Models\ShoppingCart;
use Carbon\Carbon;

class OrderService
{

    const STARTING_NUMBER = 18000;

    private $countryService;

    public function __construct()
    {
        $this->countryService = new CountryService();
    }

    public function getOrder($id){
        return Order::find($id);
    }

    public function getOrderByInvoiceId($invoiceId){
        return Order::where('invoice_id', $invoiceId)->first();
    }

    /**
     * Get the status id of the given status name
     *
     * @param $statusName
     * @return integer
     */
    public function getPaymentStatusId($statusName){
        return OrderPayment::getStatus($statusName);
    }

    /**
     * Save an order by using the customer input and the Shopping Cart
     * NOTE: If needed $shoppingCart could be replace into a collection of array with Products
     *
     * @param $customerInput
     * @param ShoppingCart $shoppingCart
     * @return Order|\Illuminate\Database\Eloquent\Model
     */
    public function saveOrder($customerInput, ShoppingCart $shoppingCart){

        // Convert the input to the desired format and define the shipping address
        $customerInput = $this->convertFormInputFormat($customerInput);
        $this->defineShippingAddress($customerInput);

        // Fill the Order with the customer input
        $order = Order::create($customerInput);

        if( config('activeSiteSlug') == 'x2' ) $order->is_x2 = 1;

        // Generate the invoice id
        $this->calculateInvoiceNumber($order);

        // Create Payment
        $order->payment()->create([
            'status' => OrderPayment::EMPTY
        ]);

        $orderPriceEuro = 0;
        $orderPriceDollar = 0;

        // Append the products to the order
        foreach ($shoppingCart->getItems() as $shoppingCartItem){
            $order->products()->create($shoppingCartItem->toArray());

            // Calculate the total price of the order
            $orderPriceEuro += $shoppingCartItem->getCalculatedPrice(true, true, 1);
            $orderPriceDollar += $shoppingCartItem->getCalculatedPrice(true, false, 1);
        }

        // Append the total price for denormalization
        $order->sub_total_euro = $orderPriceEuro;
        $order->sub_total_dollar = $orderPriceDollar;

        // This we also could have added by adding it to the mass assign
        // But I think it's better to do this manual
        $order->shipping_costs_euro = $shoppingCart->calculateShippingCost(true, true, 1);
        $order->shipping_costs_dollar = $shoppingCart->calculateShippingCost(true, false, 1);

        $order->total_euro = $order->sub_total_euro + $order->shipping_costs_euro;
        $order->total_dollar = $order->sub_total_dollar + $order->shipping_costs_dollar;

        $order->save();

        return $order;

    }

    /**
     * Calculate the invoice number
     *
     * @param Order $order
     * @return int
     */
    private function calculateInvoiceNumber(Order &$order): int
    {

        //Get latest order (excluding this one
        $latestOrder =  Order::orderBy('id', 'desc')
            ->where('id', '!=', $order->id)
            ->select('id', 'invoice_id')
            ->where('invoice_id', '!=', 0)
            ->first();

        // If there are no orders then start from 18001
        if(isset($latestOrder)) $latestInvoiceId = $latestOrder->invoice_id;
        else $latestInvoiceId = self::STARTING_NUMBER;

        if($latestInvoiceId <= 0){
            throw new \RuntimeException("Something went wrong when creating the invoice id, because the latest invoice id is 0");
        }

        // Determine the year multiplier
        // Get the length of the invoice id (string) and decrement it by 1 to get the right multiplier
        $powNumber = (strlen($latestInvoiceId) - 1);

        // Then raise 10 to the power of powNumber
        // Also remove 1 for the powNumber because we already multiply by 10
        $yearMultiplier = pow(10, ($powNumber -  1));

        // Splice order id into year number and index number
        $latestOrderYear = (int) substr($latestInvoiceId, 0, 2);
        $latestOrderIndex = (int) substr($latestInvoiceId, 2);

        // Set the order year
        $orderYear = (int)Carbon::today()->format('y');

        // If the previous order isn't this year, reset the index to 1
        if($latestOrderYear !== $orderYear) $orderIndex = 1;
        else{
            // Else increment the previous index with 1
            $orderIndex = $latestOrderIndex + 1;
        }

        // Calculate the invoice id
        $invoiceId = ($orderYear * $yearMultiplier) + $orderIndex;

        // Bind it the order
        return $order->invoice_id = $invoiceId;

    }


    /**
     * Convert the input so we can use it to mass assign the model
     * also convert salutation to gender
     *
     * @param array $customerInput
     * @return array
     */
    private function convertFormInputFormat( $customerInput, $format = 0) : array
    {
        $formattedCustomerInput = [];

        foreach ($customerInput as $key => $value){

            // Keys to ignore for the order
            if(in_array($key, ['_token', 'legal'])) continue;

            // Convert salutation to gender
            if($key === 'salutation') $key = 'gender';

            // Convert country iso to country id
            if(in_array($key, ['country', 'shippingCountry'])){
                $key .= 'Id';
                $value = $this->getCountryIdFromIso2($value);
            }

            //Create desired format of key
            switch ($format){
                default:
                    $key = snake_case($key);
                    break;
            }

            // In case the input doesn't define 'invoice_' as pre key we append it in the front of the key
            if(!starts_with($key, ['shipping_', 'invoice_'])) $key = 'invoice_'.$key;

            $formattedCustomerInput[$key] = $value;
        }

        return $formattedCustomerInput;
    }

    /**
     * Removes the marker that there is another shipping address
     * or populated the shipping address from the invoice address
     *
     * @param $customerInput
     */
    private function defineShippingAddress(&$customerInput){

        // If there is another shipping address then remove this key and return
        if(isset($customerInput['invoice_other_shipping_address']) && $customerInput['invoice_other_shipping_address'] === 'on' ){
            unset($customerInput['invoice_other_shipping_address']);
            return;
        }
        // Else populate the shipping address from the invoice address
        else{
            // Keys which are use by invoice and shipping address so the ones we need to duplicate
            $shippingInfoKeys = ['street', 'postal', 'house_number','house_number_addition','city','country_id'];

            foreach ($shippingInfoKeys as $shippingInfoKey){
                // Check if the non required fields are filled
                if(isset($customerInput['invoice_'.$shippingInfoKey]))
                    $customerInput['shipping_'.$shippingInfoKey] = $customerInput['invoice_'.$shippingInfoKey];
            }
        }
    }

    /**
     * Get the country id by the iso_2
     *
     * @param $iso_2
     * @return int
     */
    private function getCountryIdFromIso2($iso_2){

        $countryService = \App::make(CountryService::class);
        return $countryService->getCountryByIso2($iso_2)->id;

    }


}