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/topswtw.komma.pro/app/KommaApp/Shop/Orders/Order.php
<?php
/**
 * Created by PhpStorm.
 * User: mike
 * Date: 13/01/15
 * Time: 15:20
 */

namespace KommaApp\Shop\Orders;

use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;

use Illuminate\Support\Facades\Log;
use Komma\Kms\Shipments\Shipment;

use KommaApp\Shop\Shops\Models\Domain;


class Order extends Model
{
    // Moet gelijk zijn aan back-end
    const OPEN = "openstaand";
    const PAYED = "betaald";
    const SENT = "verzonden";
    const COMPLETE = "voltooid";
    const CANCELLED = "geannuleerd";
    const TREATMENT = "in_behandeling";
    const BACKORDER = "in_backorder";
    const PARTLYSHIPPED = "gedeeltelijk_verzonden";

    /*
     * Fillable for invoice address
     * Snake-case for they are database-table names
     */
    protected $invoiceFillable = [
        'invoice_id',
        'invoice_gender',
        'invoice_title',
        'invoice_first_name',
        'invoice_name_insertion',
        'invoice_last_name',
        'invoice_email',
        'invoice_company',
        'invoice_company_vat',
        'invoice_postal',
        'invoice_house_number',
        'invoice_house_number_suffix',
        'invoice_street',
        'invoice_city',
        'invoice_country',
        'invoice_telephone',
    ];

    /*
     * Fillable for shipping address
     * Snake-case for they are database-table names
     */
    protected $shippingFillable = [
        'shipping_gender',
        'shipping_title',
        'shipping_first_name',
        'shipping_name_insertion',
        'shipping_last_name',
        'shipping_company',
        'shipping_postal',
        'shipping_house_number',
        'shipping_house_number_suffix',
        'shipping_street',
        'shipping_city',
        'shipping_country',
        'shipping_telephone'
    ];

    /*
     * Total fillable for order
     */
    protected $fillable = [
        'order_number',
        'shop_id',
        'language_id',
        'domain_country',
        'customer_id',
        'status',
        'shipping_costs',
        'price_total',
        'original_price',
        'discount_description',
        'discount',
        'discount_price',
        'discount_percentage',
        'coupon_code',
        'ordered_at',
        'payment_method',
        'payment_date',
        'payment_status',
        'payment_currency',
        'payment_acceptance',
        'payment_card_number',
        'payment_cardholder_name',
        'payment_provider_id',
        'payment_error_code',
        'payment_card_brand',
        'payment_ip',
        'kiyoh_response',
        'remarks',
        'internal_remarks',
        'original_order',
        'dpd_carrier_shop_id',
        'dpd_carrier_shop_details',
        'product_total_ex'

    ];

    function __construct()
    {

        $this->fillable = array_merge($this->fillable, $this->invoiceFillable, $this->shippingFillable);
    }

    public function createNewTransaction()
    {
        // Separator should be a dash, can't be an underscore
        $transaction = new OrderTransaction([
            'custom_identifier' => $this->order_number . '-' . (count($this->transactions) + 1)
        ]);
        $this->transactions()->save($transaction);
        return $transaction;
    }

    public static function findByCustomTransactionIdentifier($customTransactionIdentifier)
    {
        if(!$ot = OrderTransaction::where('custom_identifier', $customTransactionIdentifier)->first()) return  false;
        return $ot->order;
    }

    public static function getUnnotifiedOpenOrders()
    {
        return self::where('status', self::OPEN)
            ->whereNull('payment_open_notification_on')
            ->where('ordered_at', '<=', Carbon::now()->subDays(
                \Config::get('komma/tops.openOrderNotificationDelayInDays')
            ))
            ->orderBy('invoice_email')
            ->get();
    }

    public static function getOrdersForFirstNotification()
    {
        $start = new \DateTime((\Config::get('komma/tops.openOrderFirstReminderInDays') + 1) . ' days ago');
        $end = new \DateTime(\Config::get('komma/tops.openOrderFirstReminderInDays') . ' days ago');

        return self::where('status', self::OPEN)
            ->whereNull('payment_open_notification_on')
            ->whereBetween('ordered_at', array($start, $end))
            ->whereHas('transactions', function ($query) {
                $query->where('payment_method', 'not like', 'Bank transfer%');
            })
            ->orderBy('invoice_email')
            ->get();
    }

    public static function getOrdersForSeccondNotification()
    {


        $start = new \DateTime((\Config::get('komma/tops.openOrderLastReminderInDays') + 1) . ' days ago');
        $end = new \DateTime(\Config::get('komma/tops.openOrderLastReminderInDays') . ' days ago');

        return self::where('status', self::OPEN)
            ->whereNull('payment_open_notification_reminder_on')
            ->whereBetween('ordered_at', array($start, $end))
            ->orderBy('invoice_email')
            ->get();
    }


    public static function getNotifiedOpenOrders()
    {
        return self::where('status', self::OPEN)
            ->whereNotNull('payment_open_notification_on')
            ->where('ordered_at', '<=', Carbon::now()->subDays(
                \Config::get('komma/tops.openOrderReminderDelayInDays')
            ))
            ->orderBy('invoice_email')
            ->get();
    }

    public static function getOrdersReadyToShip()
    {
        return self::select('orders.*')
            ->leftJoin('order_shipment', 'order_shipment.order_id', '=', 'orders.id')
            ->where(function ($q) {
                $q = $q->orWhere('status', self::TREATMENT);
                $q = $q->whereNull('order_shipment.order_id');
            })
            ->orWhere(function ($q) {
                $q = $q->orWhere('status', self::PAYED);
                $q = $q->orWhere('status', self::PARTLYSHIPPED);
            })
            ->groupBy('orders.id')
            ->orderBy('shop_id')
            ->orderBy('created_at')
            //todo check if they are not in an open shipment
            ->get();

    }

    public static function getBackorders()
    {
        return self::select('orders.*')
            ->leftJoin('order_shipment', 'order_shipment.order_id', '=', 'orders.id')
            ->Where(function ($q) {
                $q = $q->orWhere('status', self::BACKORDER);
            })
            ->groupBy('orders.id')
            ->orderBy('shop_id')
            ->orderBy('created_at')
            ->get();

    }

    public static function getOrdersForShipment($shipmentId)
    {
        return self::where('shipment_id', $shipmentId)
            ->with('customer')
            ->with('language')
            ->get();
    }

    public function language()
    {
        return $this->belongsTo('\Komma\Kms\Languages\Language');
    }

    public function products()
    {
        return $this->hasMany('\KommaApp\Shop\Orders\OrderProduct', 'order_id', 'id');
    }

    public function transactions()
    {
        return $this->hasMany('\KommaApp\Shop\Orders\OrderTransaction');
    }

    public function customer()
    {
        return $this->belongsTo('\KommaApp\Shop\Customers\Customer');
    }

    /**
     * @return array
     */
    public function invoiceFields()
    {
        return $this->invoiceFillable;
    }

    /**
     * @return array
     */
    public function shippingFields()
    {
        return $this->shippingFillable;
    }

    public function getFullInvoiceAddress()
    {
        $address = [];
        if ($this->invoice_company) $address[] = $this->invoice_company;
        $address[] = $this->getFullInvoiceName();
        $address[] = $this->invoice_street . ' ' . $this->invoice_house_number . ($this->invoice_house_number_suffix != '' ? ' - ' . $this->invoice_house_number_suffix : '');
        $address[] = $this->invoice_postal . ' ' . $this->invoice_city;
        $address[] = \Lang::get('countries.' . strtoupper($this->invoice_country));

        if ($this->invoice_telephone) $address[] = $this->invoice_telephone;

        return implode('<br/>', $address);
    }

    public function getFullShippingAddress()
    {
        $address = [];
        if ($this->shipping_company) $address[] = $this->shipping_company;
        $address[] = $this->getFullShippingName();
        $address[] = $this->shipping_street . ' ' . $this->shipping_house_number . ($this->shipping_house_number_suffix != '' ? ' - ' . $this->shipping_house_number_suffix : '');
        $address[] = $this->shipping_postal . ' ' . $this->shipping_city;
        $address[] = \Lang::get('countries.' . strtoupper($this->shipping_country));
        if ($this->shipping_telephone) $address[] = $this->shipping_telephone;

        return implode('<br/>', $address);
    }

    public function getFullDpdAddress()
    {
        $address = [];
        if (!helper_isJSON($this->dpd_carrier_shop_details)) return '';

        $dpdData = json_decode($this->dpd_carrier_shop_details);

        $address[] = \Lang::get('checkout/checkout.dpd_name');
        $address[] = $dpdData->company;
        $address[] = $dpdData->street . ' ' . $dpdData->houseNo;
        $address[] = $dpdData->zipCode . ' ' . $dpdData->city;
        $address[] = \Lang::get('countries.' . strtoupper($dpdData->isoAlpha2));
        return implode('<br/>', $address);
    }

    public function getFullInvoiceName()
    {
        $name = [];
        if ($this->invoice_first_name) $name[] = $this->invoice_first_name;
        if ($this->invoice_name_insertion) $name[] = $this->invoice_name_insertion;
        if ($this->invoice_last_name) $name[] = $this->invoice_last_name;
        return implode(' ', $name);
    }

    public function getFullInvoiceLastName()
    {
        $name = [];
        if ($this->invoice_name_insertion) $name[] = ucfirst($this->invoice_name_insertion);
        if ($this->invoice_last_name) $name[] = ucfirst($this->invoice_last_name);
        return implode(' ', $name);
    }

    public function getFullShippingName()
    {
        $name = [];
        if ($this->shipping_first_name) $name[] = $this->shipping_first_name;
        if ($this->shipping_name_insertion) $name[] = $this->shipping_name_insertion;
        if ($this->shipping_last_name) $name[] = $this->shipping_last_name;
        return implode(' ', $name);
    }

    public function getSubTotal()
    {
        $subTotal = 0;
        foreach ($this->products as $product) {
            $subTotal += $product->price;
        }
        return $subTotal;
    }

    public function getSubTotalExVat()
    {
        $subTotal = 0;
        foreach ($this->products as $product) {
            $subTotal += $product->getPriceExVat();
        }
        return $subTotal;
    }

    public function getDiscountPriceExVat()
    {
        return round($this->getSubTotalExVat() * ($this->discount_percentage / 100));
    }

    public function getShippingCostsExVat()
    {
        return round($this->shipping_costs / (1 + ($this->getHighestProductTaxRate() / 100)));
    }

    public function getPriceTotalExVat()
    {
        return round($this->getSubTotalExVat() + $this->getShippingCostsExVat() - $this->getDiscountPriceExVat());
    }

    public static function getNewOrderNumber()
    {
        if (self::max('order_number') > 0) {
            return self::max('order_number') + 1;
        }
        return \Config::get('komma/tops.orderNumberStart');
    }

    public static function getNewInvoiceId()
    {
        if (self::max('invoice_id') > 0) {
            return self::max('invoice_id') + 1;
        }
        return \Config::get('komma/tops.invoiceIdStart');
    }

    public function getTaxTotals()
    {
        $taxTotals = [];
        foreach ($this->products as $product) {
            if (!isset($taxTotals[$product->tax_rate])) $taxTotals[$product->tax_rate] = [
                'name' => $product->tax_name,
                'total' => 0
            ];
            $taxTotals[$product->tax_rate]['rate'] = $product->tax_rate;
            $taxTotals[$product->tax_rate]['name'] = $product->tax_name;
            $taxTotals[$product->tax_rate]['total'] += ($product->price - $product->getPriceExVat());
        }

        // Subtract order discount percentage

        if (!isset($taxTotals[$this->getHighestProductTaxRate()])) {
            //throw new \Exception('KMS: Invalid tax rate');
            echo '||ERROR||';
            return [];
        }

        $taxTotals[$this->getHighestProductTaxRate()]['total'] = $taxTotals[$this->getHighestProductTaxRate()]['total'] * (1 - ($this->discount_percentage / 100));

        // Add shipping costs tax to highest tax rate
        $taxTotals[$this->getHighestProductTaxRate()]['total'] += ($this->shipping_costs - $this->getShippingCostsExVat());

        return $taxTotals;
    }

    public function getTotalToPay()
    {
        if ($this->invoice_company_vat && $this->invoice_country != 'NL')
            return $this->getPriceTotalExVat();
        return $this->price_total;
    }

    public function getVat()
    {
        return $this->price_total - $this->getPriceTotalExVat();
    }

    protected function getHighestProductTaxRate()
    {
        $highestTaxRate = 0;
        foreach ($this->products as $product) {
            if ($product->tax_rate > $highestTaxRate) $highestTaxRate = $product->tax_rate;
        }
        return $highestTaxRate;
    }

    public function getSalutation()
    {
        // Salutation
        $salutation[] = \Lang::get('form.salutation_' . $this->invoice_title);

        // Name
        if ($this->invoice_name_insertion) $salutation[] = ucfirst($this->invoice_name_insertion);
        if ($this->invoice_last_name) $salutation[] = $this->invoice_last_name;

        return implode(' ', $salutation);
    }

    public function getInvoiceGender($input)
    {
        // Get gender from title
        if ($input['invoice-title'] == 'mr') {
            return 'male';
        } else {
            return 'female';
        }
    }

    public function getGenderCodeShipping()
    {
        switch ($this->shipping_gender)
        {
            case 'male':
                return '&#9794;';
                break;
            case 'female':
                return '&#9792;';
                break;
            default:
                return '&#9893;?';
        }
    }

    public function getGenderCodeInvoice()
    {
        switch ($this->invoice_gender)
        {
            case 'male':
                return '&#9794;';
                break;
            case 'female':
                return '&#9792;';
                break;
            default:
                return '&#9893;?';
        }
    }

    public function getShippingGender($input)
    {
        // Get gender from title
        if ($input['shipping-title'] == 'mr') {
            return 'male';
        } else {
            return 'female';
        }
    }

    public function getPaymentMethod()
    {
        if(!$this->transactions->last()) return '-';
        return $this->transactions->last()->payment_method;
    }


    public function shipments()
    {
        // Let op: Frontend Model
        return $this->belongsToMany('Komma\Kms\Shipments\Shipment')->withPivot('order_id');
    }


    public function getPaymentLink()
    {

        //if Order is canceld return status text CANCELLED
        if ($this->status == $this::CANCELLED) return $this::CANCELLED;
        //If the order isnot open return text PAYED
        if ($this->status != $this::OPEN) return $this::PAYED;

        //Load the url of shop where is payed
        /***
         * Select the domain string from Domains
         * Where the domain country equals the domain country from the order
         * Where the domain shop id equals the the order country
         * With multiple results the domain witch is the shop.name gets the preference
         */
        $domain = Domain::select('domains.domain', \Db::raw('IF( shops.name = domains.domain,1,0 ) as preferred_domain'))
            ->leftJoin('countries', 'countries.id', '=', 'domains.country_id')
            ->leftJoin('shops', 'shops.id', '=', 'domains.shop_id')
            ->where('domains.shop_id', '=', $this->shop_id)
            ->where('countries.iso_2', '=', $this->domain_country)
            ->orderBy('preferred_domain', 'DESC')
            ->first();

        if (empty($domain)) return ' - ';

        //Get the correct page
        if (!$route = \Shop::getPageService()->getPageByShopAndLang('pendingPayment', $this->shop_id, $this->language_id)) return ' - ';
        //Glue together
        $url = 'http';
        if (\Config::get('komma/tops.https')) $url .= 's';
        $url .= '://';
        if (\Config::get('komma/tops.www')) $url .= 'www.';
        $url .= $domain->domain;
        $url .= '/';
        $url .= $route;
        $url .= '?token=' . $this->order_token;
        return $url;
    }

    public function googleEcommercePurchaseData()
    {
        $data = [
            'ecommerce' => [
                'purchase' => [
                    'actionField' => [
                        'id' => $this->order_number, // Transaction ID. Required for purchases and refunds.
                        'affiliation' => $this->shop_id,
                        'revenue' => $this->price_total / 100, // Total transaction value (incl. tax and shipping)
                        'shipping' => $this->shipping_costs / 100
                    ],
                    'products' => [

                    ]
                ],

            ]
        ];

        foreach($this->products as $orderdProduct)
        {
            /** @var \KommaApp\Shop\Orders\OrderProduct $orderdProduct */
            $data['ecommerce']['purchase']['products'][] = $orderdProduct->googleEcommerceProductFieldObjectData();
        }

        return $data;
    }
}