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;
}
}