File: D:/HostingSpaces/SBogers10/netwerkbrabant.komma.pro/app/KommaApp/Orders/OrderService.php
<?php
namespace App\KommaApp\Orders;
use App\KommaApp\Orders\Models\Order;
use App\KommaApp\Orders\Models\OrderPayment;
use App\KommaApp\WeFact\WeFactService;
use App\Mail\DebtorCreatedMail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Storage;
class OrderService
{
/**
* Define the amount of zero's we start the invoice number with
*/
const STARTING_NUMBER_POW = 3;
const INVOICE_NUMBER_PREFIX = 'NBW-';
/**
* Get order by id
*
* @param $id
* @return mixed
*/
public function getOrder($id)
{
return Order::find($id);
}
/**
* Get order by invoice id
*
* @param $invoiceId
* @return mixed
*/
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);
}
/**
* Create an order by the signee and the event information
*
* @param $signee
* @param $course
* @return Order|\Illuminate\Database\Eloquent\Model
*/
public function createOrderForSignee($signee, $model)
{
// TODO if we should expand the site with order management we should create a invoice_date (for now we use the create date)
$order = Order::create([
'price' => $model->price,
'price_including_vat' => $model->price_including_vat,
'email' => $signee->email,
'phone' => $signee->phone,
'invoice_company' => $signee->company,
'invoice_first_name' => $signee->first_name,
'invoice_last_name' => $signee->last_name,
'invoice_email' => $signee->invoice_email,
'invoice_address' => $signee->address,
'invoice_postal' => $signee->postal,
'invoice_city' => $signee->city,
'invoice_country' => $signee->country,
'invoice_reference' => (!empty($signee->reference)) ? $signee->reference : '',
]);
// Calculate unique invoice number
$this->calculateInvoiceNumber($order);
// Also create an invoice id with prefix
// $order->invoice_id_prefixed = $this::INVOICE_NUMBER_PREFIX. $order->invoice_id;
$order->save();
// Add products to the order
$order->products()->create((array) $model);
return $order;
}
public function createOrderForProductable($orderValues, $productable)
{
$orderValues['price'] = $productable->price;
$orderValues['price_including_vat'] = $productable->price_including_vat;
$order = Order::create($orderValues);
// Calculate unique invoice number
$this->calculateInvoiceNumber($order);
$order->save();
// Add products to the order
$order->products()->create((array)$productable);
return $order;
}
public function createPdfForInvoiceId(int $invoiceId)
{
// Check that the order is found
if(!$order = Order::where('invoice_id', $invoiceId)
->with('products')
->first()){
\App::abort(500);
}
if(config('app.env') !== 'production') $siteUrl = 'http://netwerkbrabant.komma.pro';
else $siteUrl = config('site.company.url');
$pdf = \PDF::loadView('pdfs.invoice', ['order' => $order, 'siteUrl' => $siteUrl]);
$storagePath = storage_path('app/pdfs/invoice-'.$order->invoice_id_prefixed. '.pdf');
$pdf->save($storagePath);
// dd('stop');
return $storagePath;
}
public function deletePdfFromPath(int $invoiceId)
{
// Check that the order is found
if(!$order = Order::where('invoice_id', $invoiceId)
->with('products')
->first()){
\App::abort(500);
}
Storage::delete('pdfs/invoice-'.$order->invoice_id_prefixed. '.pdf');
}
/**
* Send invoice by WeFact for Order.
*
* @param Order $order
* @param string $weFactCode
* @param bool $hasPaid
*/
public function sendInvoiceForOrderByWeFact(Order $order, string $weFactCode, bool $hasPaid = false)
{
/** @var WeFactService $weFactService */
$weFactService = app()->make(WeFactService::class);
$weFactDebtor = $this->findOrCreateDebtorByOrder($order);
if($order->products->count() != 1) {
throw new \RuntimeException(self::class . ': Order contains multiple products, the WeFactService has not been prepared for this.');
}
$invoice = $weFactService->addInvoice($weFactDebtor->DebtorCode, $weFactCode, $order->invoice_reference, $hasPaid);
$weFactService->sendInvoiceByMail($invoice->Identifier);
// Mark the invoice / order as send
$order->wefact_invoice_send = true;
$order->save();
}
/**
* Find or create a debtor by order model.
* So find by the invoice_email, if not create by the invoice information.
*
* @param Order $order
* @return mixed|object
*/
private function findOrCreateDebtorByOrder(Order $order)
{
/** @var WeFactService $weFactService */
$weFactService = app()->make(WeFactService::class);
$searchResult = $weFactService->searchDebtorsByEmail($order->invoice_email);
// We found one debtor.
if($searchResult->results == 1) {
$weFactDebtor = (object)$searchResult->debtors[0];
}
// We found none or multiple, and therefor have to create a new debtor
elseif($searchResult->results == 0 || $searchResult->results >= 2) {
$weFactDebtor = $weFactService->addDebtor([
'CompanyName' => $order->invoice_company,
'Initials' => $order->invoice_first_name,
'SurName' => $order->invoice_last_name,
'Address' => $order->invoice_address,
'ZipCode' => $order->invoice_postal,
'City' => $order->invoice_city,
'EmailAddress' => $order->invoice_email,
]);
// Send mail why new debtor has been created to Erik
if($searchResult->results == 0) {
Mail::send(new DebtorCreatedMail($weFactDebtor, __('site/emails.admin.debtor_created_no_results')));
}
else {
Mail::send(new DebtorCreatedMail($weFactDebtor, __('site/emails.admin.debtor_created_multiple_results')));
}
}
else {
throw new \RuntimeException(self::class.': Something went wrong with the searchResult');
}
return $weFactDebtor;
}
/**
* Calculate the invoice number
* If we still use this code in the year 2099 we need to check if year change won't crash the code
*
* @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 current year and starting with the defined zero's
if(isset($latestOrder)) $latestInvoiceId = $latestOrder->invoice_id;
else{
$orderYear = (int)Carbon::today()->format('y');
$yearMultiplier = pow(10, (self::STARTING_NUMBER_POW));
// For the prefixed for invoice we must get (year)0(index) so to get this we do an additional * 10
$order->invoice_id_prefixed = ($orderYear * $yearMultiplier * 10);
return $order->invoice_id = $orderYear * $yearMultiplier;
}
if ($latestInvoiceId <= 0) {
throw new \RuntimeException("Something went wrong when creating the invoice id, because the latest invoice id is 0");
}
// 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;
}
// 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);
// If the index (string) length exceeds the previous index we must increment the powNumber
if( strlen($latestOrderIndex) !== strlen($orderIndex)) $powNumber++;
// 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));
// Calculate the invoice id
$invoiceId = ($orderYear * $yearMultiplier) + $orderIndex;
// For the prefixed for invoice we must get (year)0(index) so to get this we do an additional * 10
$order->invoice_id_prefixed = ($orderYear * $yearMultiplier * 10) + $orderIndex;
// Bind it the order
return $order->invoice_id = $invoiceId;
}
}