$dhlOutboundShipments * @property-read int|null $dhl_outbound_shipments_count * @property-read \Illuminate\Database\Eloquent\Collection $dhlReturnShipments * @property-read int|null $dhl_return_shipments_count * @property-read \Illuminate\Database\Eloquent\Collection $dhlShipments * @property-read int|null $dhl_shipments_count * * @mixin \Eloquent */ class ShoppingOrder extends Model { protected $table = 'shopping_orders'; use SoftDeletes; protected $dates = ['deleted_at']; protected $fillable = [ 'shopping_user_id', 'auth_user_id', 'member_id', 'homeparty_id', 'payment_for', 'country_id', 'language', 'user_shop_id', 'total', 'subtotal', 'shipping', 'shipping_net', 'subtotal_ws', 'tax', 'tax_split', 'net_split', 'total_shipping', 'points', 'weight', 'paid', 'is_abo', 'abo_interval', 'txaction', 'wp_invoice_path', 'api_notice', 'api_status', 'mode', 'shipped', 'tracking', ]; protected $casts = [ 'api_notice' => 'array', 'tax_split' => 'array', 'net_split' => 'array', 'abo_interval' => 'int', 'is_abo' => 'bool', 'points' => 'float', ]; public static $shippedTypes = [ 0 => 'open', 1 => 'in_process', 2 => 'shipped', 3 => 'completed', 4 => 'trade_fair', 10 => 'cancelled', ]; public static $apiShippedTypes = [ 0 => 'open', // (Fullfilment durch Händler)', 1 => 'process', // (Fullfilment durch MIVITA: nicht Versand) 2 => 'sent', // (Fullfilment durch MIVITA: Versand erfolgt)' 3 => 'close', // (Fullfilment durch MIVITA: Versand erfolgt)', 4 => 'trade', // (Fullfilment durch MIVITA: Versand erfolgt)', 10 => 'cancel', ]; public static $apiStatusTypes = [ 0 => 'ordered', 1 => 'in_process', 2 => 'paid', 5 => 'removed', ]; public static $apiStatusColors = [ 0 => 'warning', 1 => 'warning', 2 => 'success', 5 => 'danger', ]; public static $shippedColors = [ 0 => 'warning', 1 => 'info', 2 => 'success', 3 => 'secondary', 4 => 'secondary', 10 => 'danger', ]; public static $paymentForTypes = [ 0 => '', 1 => 'registration', 2 => 'membership', 3 => 'order', 4 => 'customer_order', 5 => 'homeparty', 6 => 'shop', 7 => 'external', 8 => 'collective_invoice', 10 => '', ]; public static $paymentForColors = [ 0 => 'default', 1 => 'warning', 2 => 'warning', 3 => 'secondary', 4 => 'info', 5 => 'dark', 6 => 'secondary', 7 => 'dark', 8 => 'info', 9 => 'default', 10 => 'info', 11 => 'default', ]; public function shopping_user() { return $this->belongsTo('App\Models\ShoppingUser', 'shopping_user_id'); } public function country() { return $this->belongsTo('App\Models\ShippingCountry', 'country_id'); } public function shipping_country() { return $this->belongsTo('App\Models\ShippingCountry', 'country_id'); } public function homeparty() { return $this->belongsTo('App\Models\Homeparty', 'homeparty_id'); } public function user_shop() { return $this->belongsTo('App\Models\UserShop', 'user_shop_id'); } // can null public function member() { return $this->belongsTo('App\User', 'member_id'); } // can null public function auth_user() { return $this->belongsTo('App\User', 'auth_user_id'); } public function user_history() { return $this->hasOne('App\Models\UserHistory', 'shopping_order_id')->latest(); } /** * Original-Rechnung (nicht die Stornorechnung) * * Unterscheidung: Die Original-Rechnung hat entweder cancellation=false/null (vor Storno) * oder cancellation_id gesetzt (nach Storno, zeigt auf die Stornorechnung). * Die Stornorechnung hat cancellation=true UND cancellation_id=null. */ public function user_invoice() { return $this->hasOne('App\Models\UserInvoice', 'shopping_order_id', 'id') ->where(function ($query) { $query->where('cancellation', false) ->orWhereNull('cancellation') ->orWhereNotNull('cancellation_id'); }); } /** * Stornorechnung für diese Bestellung * * Die Stornorechnung hat cancellation=true und KEINEN cancellation_id * (cancellation_id wird nur auf der Original-Rechnung gesetzt). */ public function user_cancellation_invoice() { return $this->hasOne('App\Models\UserInvoice', 'shopping_order_id', 'id') ->where('cancellation', true) ->whereNull('cancellation_id'); } /** * Alle Rechnungen (Original + Storno) für diese Bestellung */ public function user_invoices() { return $this->hasMany('App\Models\UserInvoice', 'shopping_order_id', 'id'); } public function shopping_collect_order() { return $this->hasOne('App\Models\ShoppingCollectOrder', 'shopping_order_id', ''); } public function shopping_order_items() { return $this->hasMany('App\Models\ShoppingOrderItem', 'shopping_order_id'); } /** * Bezahlte Berater-Registrierung (payment_for = 1) mit mindestens einem Produkt, das keine * reine Mitgliedschaft ohne Starterpaket ist ({@see Product::$is_membership_only}). */ public function scopeWherePaidRegistrationIncludesStarterKit(Builder $query): Builder { return $query ->where('payment_for', 1) ->where(function (Builder $q) { $q->where('paid', true) ->orWhereIn('txaction', ['paid', 'extern_paid']); }) ->whereHas('shopping_order_items', function (Builder $q) { $q->whereHas('product', function (Builder $p) { $p->where('is_membership_only', false); }); }); } /** * Erfüllt diese Bestellung die Voraussetzung für Incentive-Neupartner-Tracking (Starterpaket)? */ public function qualifiesForIncentiveTrackedPartner(): bool { return static::query() ->whereKey($this->getKey()) ->wherePaidRegistrationIncludesStarterKit() ->exists(); } public function shopping_payments() { return $this->hasMany('App\Models\ShoppingPayment', 'shopping_order_id'); } public function user_sales_volume() { return $this->hasOne('App\Models\UserSalesVolume', 'shopping_order_id'); } public function user_sales_volume_no_userid() { return $this->hasOne('App\Models\UserSalesVolume', 'shopping_order_id')->where('user_id', '=', null)->first(); } public function getUserAbo() { $UserAboOrder = UserAboOrder::where('shopping_order_id', $this->id)->first(); if ($UserAboOrder && $UserAboOrder->user_abo) { return $UserAboOrder->user_abo; } return null; } public function getLocale() { return $this->language ? $this->language : \App::getLocale(); } public function setUserHistoryValue($values = []) { if ($user_history = $this->user_history) { foreach ($values as $key => $val) { $user_history->{$key} = $val; } $user_history->save(); } } public function getLastShoppingPayment($key = false) { $shopping_payment = $this->shopping_payments->last(); if ($shopping_payment) { if ($key === 'getPaymentType') { return $shopping_payment->getPaymentType(); } if ($key === 'reference') { return $shopping_payment->reference; } } return ''; } public function getLastShoppingPaymentTransaction() { if ($this->shopping_payments) { $shopping_payment = $this->shopping_payments->last(); if ($shopping_payment) { $payt = $shopping_payment->payment_transactions->last(); if ($payt) { return $payt; } } } return false; } public function getShippedType() { return isset(self::$shippedTypes[$this->shipped]) ? __('payment.'.self::$shippedTypes[$this->shipped]) : ''; } public static function getTransShippedType() { $ret = []; foreach (self::$shippedTypes as $key => $val) { $ret[$key] = trans('payment.'.$val); } return $ret; } public function getAPIShippedType() { return isset(self::$apiShippedTypes[$this->shipped]) ? self::$apiShippedTypes[$this->shipped] : 'free'; } public function getShippedColor() { return isset(self::$shippedColors[$this->shipped]) ? self::$shippedColors[$this->shipped] : 'default'; } public function getAPIStatusType() { return isset(self::$apiStatusTypes[$this->api_status]) ? __('payment.'.self::$apiStatusTypes[$this->api_status]) : 'bestellt'; } public function getAPIStatusColor() { return isset(self::$apiStatusColors[$this->api_status]) ? self::$apiStatusColors[$this->api_status] : 'warning'; } public function getFormattedTotal() { return formatNumber($this->attributes['total']); } public function getFormattedSubtotal() { return formatNumber($this->attributes['subtotal']); } public function getFormattedShipping() { return formatNumber($this->attributes['shipping']); } public function getFormattedShippingNet() { return formatNumber($this->attributes['shipping_net']); } public function getFormattedSubtotalWs() { return formatNumber($this->attributes['subtotal_ws']); } public function getFormattedSubtotalShipping() { return formatNumber($this->attributes['subtotal_shipping']); } public function getFormattedTax() { return formatNumber($this->attributes['tax']); } public function getFormattedTotalShipping() { return formatNumber($this->attributes['total_shipping']); } public function setPointsAttribute($value) { $this->attributes['points'] = $value !== null ? \Util::reFormatNumber($value) : null; } public function getFormattedPoints() { return isset($this->attributes['points']) ? formatNumber($this->attributes['points']) : ''; } public function getPriceVkNetBy($product_id) { if ($product = Product::find($product_id)) { if ($this->shipping_country && $this->shipping_country->country) { return $product->getPriceWith(true, false, $this->shipping_country->country); } } return 0; } public function getPaymentForType() { return isset(self::$paymentForTypes[$this->payment_for]) ? __('payment.'.self::$paymentForTypes[$this->payment_for]) : ''; } public function getPaymentForColor() { return isset(self::$paymentForColors[$this->payment_for]) ? self::$paymentForColors[$this->payment_for] : ''; } public function getUserDiscount() { if ($this->auth_user && $this->auth_user->user_level) { return $this->auth_user->user_level->getFormattedMargin(); } if ($this->member && $this->member->user_level) { return $this->member->user_level->getFormattedMargin(); } return 0; } public function getItemsCount() { $count = 0; if ($this->shopping_order_items) { foreach ($this->shopping_order_items as $shopping_order_item) { $count += $shopping_order_item->qty; } } return $count; } public function isInvoice() { return $this->user_invoice ? true : false; } /** * Prüft ob eine Stornorechnung für diese Bestellung existiert. * Die echte Stornorechnung hat cancellation=true und cancellation_id=null. */ public function isCancellationInvoice() { return \App\Models\UserInvoice::where('shopping_order_id', $this->id) ->where('cancellation', true) ->whereNull('cancellation_id') ->exists(); } /** * Holt die Stornorechnung für diese Bestellung. * Die echte Stornorechnung hat cancellation=true und cancellation_id=null. */ public function getCancellationInvoice() { return \App\Models\UserInvoice::where('shopping_order_id', $this->id) ->where('cancellation', true) ->whereNull('cancellation_id') ->first(); } public function getStatusByOrder() { if ($this->payment_for) { if ($this->payment_for === 6) { // Kunde-Shop return 2; } return 1; } return 0; } public function makeHomepartyTaxSplit() { $tax_split = []; $net_split = []; if ($this->homeparty) { foreach ($this->homeparty->homeparty_order_items as $item) { $tax_rate = intval($item->tax_rate); if ($tax_rate > 0) { $vk_tax = round((($item->price - $item->price_net) * $item->qty), 2); $ek_tax = round((($item->ek_price - $item->ek_price_net) * $item->qty), 2); $vk_net = round(($item->price_net * $item->qty), 2); $ek_net = round(($item->ek_price_net * $item->qty), 2); if (isset($tax_split[$tax_rate])) { $tax_split[$tax_rate]['vk_tax'] = round($tax_split[$tax_rate]['vk_tax'] + $vk_tax, 2); $tax_split[$tax_rate]['ek_tax'] = round($tax_split[$tax_rate]['ek_tax'] + $ek_tax, 2); $net_split[$tax_rate]['vk_net'] = round($net_split[$tax_rate]['vk_net'] + $vk_net, 2); $net_split[$tax_rate]['ek_net'] = round($net_split[$tax_rate]['ek_net'] + $ek_net, 2); } else { $tax_split[$tax_rate] = ['vk_tax' => $vk_tax, 'ek_tax' => $ek_tax]; $net_split[$tax_rate] = ['vk_net' => $vk_net, 'ek_net' => $ek_net]; } } } $order_vk_tax = 0; $order_ek_tax = 0; $order_vk_net = 0; $order_ek_net = 0; if ($this->homeparty->order) { if (isset($this->homeparty->order['ek_price_net'])) { $order_vk_tax = round((($this->homeparty->order['price'] - $this->homeparty->order['price_net'])), 2); $order_ek_tax = round((($this->homeparty->order['ek_price'] - $this->homeparty->order['ek_price_net'])), 2); $order_vk_net = $this->homeparty->order['price_net']; $order_ek_net = $this->homeparty->order['ek_price_net']; } } if (isset($tax_split[16])) { $tax_split[16] = ['vk_tax' => $order_vk_tax, 'ek_tax' => $order_ek_tax]; $net_split[16] = ['vk_net' => $order_vk_net, 'ek_net' => $order_ek_net]; } if (isset($tax_split[19])) { $tax_split[19] = ['vk_tax' => $order_vk_tax, 'ek_tax' => $order_ek_tax]; $net_split[19] = ['vk_net' => $order_vk_net, 'ek_net' => $order_ek_net]; } if (isset($tax_split[5])) { if (! isset($tax_split[16])) { $tax_split[16] = ['vk_tax' => $order_vk_tax, 'ek_tax' => $order_ek_tax]; $net_split[16] = ['vk_net' => $order_vk_net, 'ek_net' => $order_ek_net]; } $tax_split[16]['vk_tax'] = round($tax_split[16]['vk_tax'] - $tax_split[5]['vk_tax'], 2); $tax_split[16]['ek_tax'] = round($tax_split[16]['ek_tax'] - $tax_split[5]['ek_tax'], 2); $net_split[16]['vk_net'] = round($net_split[16]['vk_net'] - $net_split[5]['vk_net'], 2); $net_split[16]['ek_net'] = round($net_split[16]['ek_net'] - $net_split[5]['ek_net'], 2); } if (isset($tax_split[7])) { if (! isset($tax_split[19])) { $tax_split[19] = ['vk_tax' => $order_vk_tax, 'ek_tax' => $order_ek_tax]; $net_split[19] = ['vk_net' => $order_vk_net, 'ek_net' => $order_ek_net]; } $tax_split[19]['vk_tax'] = round($tax_split[19]['vk_tax'] - $tax_split[7]['vk_tax'], 2); $tax_split[19]['ek_tax'] = round($tax_split[19]['ek_tax'] - $tax_split[7]['ek_tax'], 2); $net_split[19]['vk_net'] = round($net_split[19]['vk_net'] - $net_split[7]['vk_net'], 2); $net_split[19]['ek_net'] = round($net_split[19]['ek_net'] - $net_split[7]['ek_net'], 2); } foreach ($tax_split as $key => $value) { $tax_split[$key]['vk_tax'] = number_format($value['vk_tax'], 2); $tax_split[$key]['ek_tax'] = number_format($value['ek_tax'], 2); } foreach ($net_split as $key => $value) { $net_split[$key]['vk_net'] = number_format($value['vk_net'], 2); $net_split[$key]['ek_net'] = number_format($value['ek_net'], 2); } } if (! isset($tax_split[16]) && ! isset($tax_split[19])) { $tax_split = null; } if (! isset($net_split[16]) && ! isset($net_split[19])) { $net_split = null; } $this->tax_split = $tax_split; $this->net_split = $net_split; $this->save(); } public function makeTaxSplit() { $tax_split = null; $net_split = null; if ($this->tax > 0) { $tax_split = []; $net_split = []; foreach ($this->shopping_order_items as $item) { $tax_rate = intval($item->tax_rate); if ($tax_rate > 0) { $tax_split[$tax_rate] = isset($tax_split[$tax_rate]) ? round($tax_split[$tax_rate] + ($item->tax * $item->qty), 2) : round(($item->tax * $item->qty), 2); $net_split[$tax_rate] = isset($net_split[$tax_rate]) ? round($net_split[$tax_rate] + ($item->price_net * $item->qty), 2) : round(($item->price_net * $item->qty), 2); } } if (isset($tax_split[16])) { $tax_split[16] = $this->tax; $net_split[16] = $this->subtotal_ws; } if (isset($tax_split[19])) { $tax_split[19] = $this->tax; $net_split[19] = $this->subtotal_ws; } if (isset($tax_split[5])) { if (! isset($tax_split[16])) { $tax_split[16] = $this->tax; $net_split[16] = $this->subtotal_ws; } $tax_split[16] = round($tax_split[16] - $tax_split[5], 2); $net_split[16] = round($net_split[16] - $net_split[5], 2); } if (isset($tax_split[7])) { if (! isset($tax_split[19])) { $tax_split[19] = $this->tax; $net_split[19] = $this->subtotal_ws; } $tax_split[19] = round($tax_split[19] - $tax_split[7], 2); $net_split[19] = round($net_split[19] - $net_split[7], 2); } foreach ($tax_split as $key => $value) { $tax_split[$key] = number_format($value, 2); } foreach ($net_split as $key => $value) { $net_split[$key] = number_format($value, 2); } } $this->tax_split = $tax_split; $this->net_split = $net_split; $this->save(); } public function getShoppingUserFullName() { if ($this->shopping_user) { $fullname = $this->shopping_user->getFullNameAsArray(); $ret = ''; $ret .= $fullname['company'] ? $fullname['company'].' | ' : ''; $ret .= $fullname['salutation'] ? \App\Services\HTMLHelper::getSalutationLang($fullname['salutation']).' ' : ''; $ret .= $fullname['firstname'] ? $fullname['firstname'].' ' : ''; $ret .= $fullname['lastname'] ? $fullname['lastname'] : ''; $ret .= $fullname['email'] ? ' | '.$fullname['email'].'' : ''; } return $ret; } /** * Get DHL shipments for this order */ public function dhlShipments() { return $this->hasMany('Acme\Dhl\Models\DhlShipment', 'order_id'); } /** * Get outbound DHL shipments only */ public function dhlOutboundShipments() { return $this->hasMany('Acme\Dhl\Models\DhlShipment', 'order_id')->where('type', 'outbound'); } /** * Get return DHL shipments only */ public function dhlReturnShipments() { return $this->hasMany('Acme\Dhl\Models\DhlShipment', 'order_id')->where('type', 'return'); } /** * Check if order has DHL shipments */ public function hasDhlShipments(): bool { return $this->dhlShipments()->exists(); } /** * Get latest DHL shipment */ public function getLatestDhlShipment() { return $this->dhlShipments()->latest()->first(); } }