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

    }

}