mivita/app/Services/Yard.php
2026-02-20 17:55:06 +01:00

734 lines
25 KiB
PHP

<?php
namespace App\Services;
use App\Models\Country;
use App\Models\Product;
use App\Models\ShippingCountry;
use Gloudemans\Shoppingcart\Cart;
use Gloudemans\Shoppingcart\CartItem;
use Gloudemans\Shoppingcart\Contracts\Buyable;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Session\SessionManager;
use Illuminate\Support\Collection;
class Yard extends Cart
{
private $shipping_price = 0;
private $shipping_price_net = 0;
private $shipping_tax_rate = 0;
private $shipping_tax = 0;
private $shipping_country_id = 0; // default de
private $shipping_is_for;
private $num_comp;
private $user_tax_free;
private $shipping_free;
private $user_reverse_charge;
private $user_country_id;
private $user_country;
private $shopping_data = [];
private $initShippingExtras = false;
public function __construct(SessionManager $session, Dispatcher $events)
{
parent::__construct($session, $events);
}
public function instance($instance = null)
{
parent::instance($instance);
if (! $this->initShippingExtras) {
$this->initShippingExtras = true; // erst true, sonst wird es immer wieder aufgerufen
$this->makeShippingExtras($instance);
}
return $this;
}
private function makeShippingExtras($instance)
{
if ($this->getYardExtra('shipping_price')) {
$this->shipping_price = (float) ($this->getYardExtra('shipping_price'));
}
if ($this->getYardExtra('shipping_price_net')) {
$this->shipping_price_net = (float) ($this->getYardExtra('shipping_price_net'));
}
if ($this->getYardExtra('shipping_tax_rate')) {
$this->shipping_tax_rate = (float) ($this->getYardExtra('shipping_tax_rate'));
}
if ($this->getYardExtra('shipping_tax')) {
$this->shipping_tax = (float) ($this->getYardExtra('shipping_tax'));
}
if ($this->getYardExtra('shipping_country_id')) {
$this->shipping_country_id = $this->getYardExtra('shipping_country_id');
}
if ($this->getYardExtra('shipping_is_for')) {
$this->shipping_is_for = $this->getYardExtra('shipping_is_for');
}
if ($this->getYardExtra('num_comp')) {
$this->num_comp = $this->getYardExtra('num_comp');
}
if ($this->getYardExtra('user_tax_free')) {
$this->user_tax_free = $this->getYardExtra('user_tax_free');
}
if ($this->getYardExtra('shipping_free')) {
$this->shipping_free = $this->getYardExtra('shipping_free');
}
if ($this->getYardExtra('user_reverse_charge')) {
$this->user_reverse_charge = $this->getYardExtra('user_reverse_charge');
}
if ($this->getYardExtra('user_country_id')) {
$this->user_country_id = $this->getYardExtra('user_country_id');
}
if ($this->getYardExtra('user_country')) {
$this->user_country = $this->getYardExtra('user_country');
}
if (gettype($this->shipping_country_id) !== 'object' && $this->shipping_country_id == 0) {
$shippingCountry = ShippingCountry::first();
if ($shippingCountry) {
$this->shipping_country_id = $shippingCountry->id;
}
}
if ($this->shipping_price == 0) {
self::instance($instance)->setShippingCountryWithPrice($this->shipping_country_id, $this->shipping_is_for);
}
}
public function getTaxRate()
{
return config('cart.tax');
}
public function putYardExtra($key, $value)
{
$content = $this->getYContent();
$content->put($key, $value);
$this->putShippingExtras($content);
// $this->ysession->put($this->yinstance, $content);
}
public function getYardExtra($key)
{
$content = $this->getYContent();
if ($content->has($key)) {
return $content->get($key);
}
return false;
}
public function getYContent()
{
return $this->getShippingExtras();
/* if (is_null($this->ysession->get($this->yinstance))) {
return new Collection([]);
}
return $this->ysession->get($this->yinstance);*/
}
public function getShippingCountryName()
{
$shippingCountry = ShippingCountry::find($this->shipping_country_id);
if ($shippingCountry && $shippingCountry->country) {
return $shippingCountry->country->getLocated();
}
return '';
}
public function getShippingCountryCountryId()
{
$shippingCountry = ShippingCountry::find($this->shipping_country_id);
if ($shippingCountry && $shippingCountry->country) {
return $shippingCountry->country->id;
}
return 1; // default DE
}
public function getShippingCountryId()
{
return $this->shipping_country_id;
}
public function getShippingPrice()
{
return $this->shipping_price;
}
public function reCalculateShippingPrice()
{
$this->calculateShippingPrice();
}
public function setShippingCountryWithPrice($shipping_country_id, $shipping_is_for = 'ot-member')
{
$this->shipping_country_id = $shipping_country_id;
$this->putYardExtra('shipping_country_id', $shipping_country_id);
$this->shipping_is_for = $shipping_is_for;
$this->putYardExtra('shipping_is_for', $shipping_is_for);
$this->calculateShippingPrice();
}
public function setUserPriceInfos($user_price_infos = [])
{
$this->shipping_free = isset($user_price_infos['shipping_free']) ? $user_price_infos['shipping_free'] : false;
$this->putYardExtra('shipping_free', $this->shipping_free);
$this->user_tax_free = $user_price_infos['user_tax_free'];
$this->putYardExtra('user_tax_free', $this->user_tax_free);
$this->user_reverse_charge = $user_price_infos['user_reverse_charge'];
$this->putYardExtra('user_reverse_charge', $this->user_reverse_charge);
$this->user_country_id = $user_price_infos['user_country_id'];
$this->putYardExtra('user_country_id', $this->user_country_id);
$this->user_country = Country::findOrFail($user_price_infos['user_country_id']);
$this->putYardExtra('user_country', $this->user_country);
}
public function getUserPriceInfos()
{
return [
'user_tax_free' => $this->user_tax_free,
'user_reverse_charge' => $this->user_reverse_charge,
'user_country_id' => $this->user_country_id,
'shipping_free' => $this->shipping_free,
];
}
public function getUserCountryId()
{
return $this->user_country_id;
}
public function getUserCountry()
{
return $this->user_country;
}
public function getUserTaxFree()
{
return $this->user_tax_free ? true : false;
}
public function getShippingFree()
{
return $this->shipping_free;
}
public function getShippingFreeMissingValue()
{
if ($this->shipping_free && $this->total(2, '.', '') < $this->shipping_free) {
return $this->shipping_free - $this->total(2, '.', '');
}
return 0;
}
private function calculateShippingPrice()
{
$shippingCountry = ShippingCountry::find($this->shipping_country_id);
if (! $shippingCountry) {
return;
}
$shipping = $shippingCountry->shipping;
$shipping_price = $shipping->shipping_prices->first();
if (! $shipping_price) {
return;
}
if ($this->allItemsFreeShippingConsultant() || $this->weight() == 0) {
$shipping_price->price = 0;
$shipping_price->price_comp = 0;
} else {
if ($this->shipping_free && $this->total(2, '.', '') >= $this->shipping_free) {
if ($this->weightByFreeShipping() == 0) {
$shipping_price->price = 0;
$shipping_price->price_comp = 0;
} else {
$shipping_price = $this->shippingPriceByWeight($shipping->shipping_prices, $this->weightByFreeShipping());
}
} else {
$shipping_price = $this->shippingPriceByWeight($shipping->shipping_prices, $this->weight());
// first by price
// $shipping_price = $this->shippingPriceByTotal($shipping->shipping_prices, $this->total(2, '.', ''));
// sec by weight
// if(!$shipping_price){
// }
}
// default
if (! $shipping_price) {
$shipping_price = $shipping->shipping_prices->first();
}
}
if ($shipping_price) {
$price = $shipping_price->price;
$this->num_comp = 0; // compensation is checked in Settings
if (Shop::isCompProducts($this->shipping_is_for)) {
$price = $shipping_price->price_comp;
$this->num_comp = $shipping_price->num_comp;
}
$this->shipping_price = $price;
$this->shipping_tax_rate = $shipping_price->tax_rate;
$this->shipping_price_net = round($price / ((100 + $shipping_price->tax_rate) / 100), 2);
$this->shipping_tax = round($price / (100 + $shipping_price->tax_rate) * 100, 2);
$this->putYardExtra('num_comp', $this->num_comp);
$this->putYardExtra('shipping_price', $this->shipping_price);
$this->putYardExtra('shipping_tax_rate', $this->shipping_tax_rate);
$this->putYardExtra('shipping_tax', $this->shipping_tax);
$this->putYardExtra('shipping_price_net', $this->shipping_price_net);
}
}
private function shippingPriceByTotal($prices, $total)
{
foreach ($prices as $price) {
if ($price->total_from > 0 && $price->total_to > 0) {
if ($total >= $price->total_from && $total <= $price->total_to) {
return $price;
}
}
}
return false;
}
private function shippingPriceByWeight($prices, $weight)
{
foreach ($prices as $price) {
if ($price->weight_from > 0 && $price->weight_to > 0) {
if ($weight >= $price->weight_from && $weight <= $price->weight_to) {
return $price;
}
}
}
return false;
}
/**
* @param null $decimals
* @param null $decimalPoint
* @param null $thousandSeperator
* @return string
*/
public function shipping($decimals = null, $decimalPoint = null, $thousandSeperator = null)
{
return $this->numberFormat($this->shipping_price, $decimals, $decimalPoint, $thousandSeperator);
}
public function shippingNet($decimals = null, $decimalPoint = null, $thousandSeperator = null)
{
return $this->numberFormat($this->shipping_price_net, $decimals, $decimalPoint, $thousandSeperator);
}
//
private function shippingTax($decimals = null, $decimalPoint = null, $thousandSeperator = null)
{
return $this->numberFormat($this->shipping_tax, $decimals, $decimalPoint, $thousandSeperator);
}
/* private function subShipping($decimals = null, $decimalPoint = null, $thousandSeperator = null){
$subShipping = $this->shipping_price_net
return $this->numberFormat($subShipping, $decimals, $decimalPoint, $thousandSeperator);
}*/
// netto
public function subtotalWithShipping($decimals = null, $decimalPoint = null, $thousandSeperator = null)
{
$subtotal = (float) $this->shipping_price_net + $this->subtotal(2, '.', '');
return $this->numberFormat($subtotal, $decimals, $decimalPoint, $thousandSeperator);
}
public function taxWithShipping($decimals = null, $decimalPoint = null, $thousandSeperator = null)
{
if ($this->user_tax_free) {
return $this->numberFormat(0, $decimals, $decimalPoint, $thousandSeperator);
}
$total = $this->totalWithShipping(2, '.', '');
// $totalTax = (float) $this->tax(2, '.', '') + $this->shipping_tax;
$totalTax = $this->subtotalWithShipping(2, '.', '');
return $this->numberFormat(($total - $totalTax), $decimals, $decimalPoint, $thousandSeperator);
}
public function totalWithShipping($decimals = null, $decimalPoint = null, $thousandSeperator = null)
{
if ($this->user_tax_free) {
$total = (float) ($this->subtotal(2, '.', '')) + $this->shipping_price_net;
} else {
$total = (float) ($this->total(2, '.', '')) + $this->shipping_price;
}
return $this->numberFormat($total, $decimals, $decimalPoint, $thousandSeperator);
}
/**
* Get the total price of the items in the cart.
*
* @param int $decimals
* @param string $decimalPoint
* @param string $thousandSeperator
* @return string
*/
public function weight($decimals = null, $decimalPoint = null, $thousandSeperator = null)
{
$content = $this->getContent();
$total = $content->reduce(function ($total, CartItem $cartItem) {
return $total + ($cartItem->options->weight ? ($cartItem->options->weight * $cartItem->qty) : 0);
}, 0);
return $total;
}
public function weightByFreeShipping($decimals = null, $decimalPoint = null, $thousandSeperator = null)
{
$content = $this->getContent();
$total = $content->reduce(function ($total, CartItem $cartItem) {
if ($cartItem->options->no_free_shipping) {
return $total + ($cartItem->options->weight ? ($cartItem->options->weight * $cartItem->qty) : 0);
}
return $total;
}, 0);
return $total;
}
public function allItemsFreeShippingConsultant()
{
$content = $this->getContent();
if ($content->isEmpty()) {
return false;
}
return $content->every(function (CartItem $cartItem) {
return (bool) $cartItem->options->free_shipping_consultant;
});
}
public function points()
{
$content = $this->getContent();
$total = $content->reduce(function ($total, CartItem $cartItem) {
// Punkte als Float konvertieren (falls als String mit Komma gespeichert)
$points = $cartItem->options->points ? Util::reFormatNumber($cartItem->options->points) : 0;
return $total + ($points * $cartItem->qty);
}, 0);
return $total;
}
public function compCount()
{
$content = $this->getContent();
$count = parent::count();
$comp_count = $content->reduce(function ($comp_count, CartItem $cartItem) {
return $cartItem->options->comp ? $comp_count + 1 : $comp_count;
}, 0);
return $count - $comp_count;
}
/**
* Get the total price of the items in the cart.
*
* @param int $decimals
* @param string $decimalPoint
* @param string $thousandSeperator
* @return string
*/
public function total($decimals = null, $decimalPoint = null, $thousandSeperator = null, $withFees = true)
{
$content = $this->getContent();
$total = $content->reduce(function ($total, CartItem $cartItem) {
return $total + ($cartItem->qty * $cartItem->price);
}, 0);
return $this->numberFormat($total, $decimals, $decimalPoint, $thousandSeperator);
}
/**
* Get the total tax of the items in the cart.
*
* @param int $decimals
* @param string $decimalPoint
* @param string $thousandSeperator
* @return float
*/
public function tax($decimals = null, $decimalPoint = null, $thousandSeperator = null, $withFees = true)
{
$content = $this->getContent();
$tax = $content->reduce(function ($tax, CartItem $cartItem) {
$priceTax = $cartItem->price / (100 + $cartItem->taxRate) * $cartItem->taxRate;
return $tax + ($cartItem->qty * $priceTax);
}, 0);
return $this->numberFormat($tax, $decimals, $decimalPoint, $thousandSeperator);
}
/**
* Get the subtotal (total - tax) of the items in the cart.
*
* @param int $decimals
* @param string $decimalPoint
* @param string $thousandSeperator
* @return float
*/
public function subtotal($decimals = null, $decimalPoint = null, $thousandSeperator = null)
{
$content = $this->getContent();
$subTotal = $content->reduce(function ($subTotal, CartItem $cartItem) {
$price_net = $cartItem->price / ((100 + $cartItem->taxRate) / 100);
return $subTotal + ($cartItem->qty * $price_net);
}, 0);
return $this->numberFormat($subTotal, $decimals, $decimalPoint, $thousandSeperator);
}
public function getCartItemByProduct($product_id, $set_price = 'with')
{
if ($product = Product::find($product_id)) {
$image = '';
if ($product->images->count()) {
$image = $product->images->first()->slug;
}
$price = $product->price;
if ($set_price === 'with') {
$cartItem = $this->getCartItem($product->id, $product->getLang('name'), 1, $price, ['image' => $image, 'slug' => $product->slug, 'weight' => $product->weight, 'points' => $product->points, 'no_commission' => $product->no_commission, 'no_free_shipping' => $product->no_free_shipping, 'show_on' => $product->show_on]);
$price = $product->getPriceWith(false, true, $this->getUserCountry());
}
if ($set_price === 'withTaxFree') {
$cartItem = $this->getCartItem($product->id, $product->getLang('name'), 1, $price, ['image' => $image, 'slug' => $product->slug, 'weight' => $product->weight, 'points' => $product->points, 'no_commission' => $product->no_commission, 'no_free_shipping' => $product->no_free_shipping, 'show_on' => $product->show_on]);
$price = $product->getPriceWith($this->getUserTaxFree(), false, $this->getUserCountry());
}
$content = $this->getContent();
if ($content->has($cartItem->rowId)) {
return $content->get($cartItem->rowId);
}
return $cartItem;
}
return null;
}
public function getCartItem($id, $name = null, $qty = null, $price = null, array $options = [])
{
if ($id instanceof Buyable) {
$cartItem = CartItem::fromBuyable($id, $qty ?: []);
} elseif (is_array($id)) {
$cartItem = CartItem::fromArray($id);
} else {
$cartItem = CartItem::fromAttributes($id, $name, $price, $options);
}
return $cartItem;
}
public function destroy()
{
// $this->ysession->remove($this->yinstance);
parent::destroy();
}
public function rowPriceNet(CartItem $row, $decimals = null, $decimalPoint = null, $thousandSeperator = null)
{
$price = round($row->price / ((100 + $row->taxRate) / 100), 4);
return $this->numberFormat($price, $decimals, $decimalPoint, $thousandSeperator);
}
public function rowSubtotalNet(CartItem $row, $decimals = null, $decimalPoint = null, $thousandSeperator = null)
{
$price = round($row->price / ((100 + $row->taxRate) / 100), 4);
return $this->numberFormat(($price * $row->qty), $decimals, $decimalPoint, $thousandSeperator);
}
public function isPriceCurrency()
{
return ($this->user_country && $this->user_country->currency) ? true : false;
}
public function getPriceCurrencyUnit()
{
return ($this->user_country && $this->user_country->currency) ? $this->user_country->currency_unit : false;
}
public function convertCurrency($value = 0, $decimals = null, $decimalPoint = null, $thousandSeperator = null)
{
if ($this->isPriceCurrency()) {
$faktor = isset($this->user_country->currency_faktor) ? $this->user_country->currency_faktor : 1;
$value = Util::reFormatNumber($value);
return $this->numberFormat($value, $decimals, $decimalPoint, $thousandSeperator);
}
return '';
}
public function getCurrencyByKey($key = false, ?CartItem $row = null, $decimals = null, $decimalPoint = null, $thousandSeperator = null)
{
if ($this->isPriceCurrency()) {
$rNumber = 0;
$faktor = isset($this->user_country->currency_faktor) ? $this->user_country->currency_faktor : 1;
switch ($key) {
case 'rowPriceNetCurrency':
if ($row) {
$price = round($row->price / ((100 + $row->taxRate) / 100), 4);
$rNumber = $price * $faktor;
}
break;
case 'rowSubtotalCurrency':
if ($row) {
$price = round($row->price / ((100 + $row->taxRate) / 100), 4);
$rNumber = $price * $faktor * $row->qty;
}
break;
case 'subtotal':
$rNumber = (float) ($this->subtotal(2, '.', '')) * $faktor;
break;
case 'price':
$rNumber = (float) $row->price * $faktor;
break;
case 'shippingNet':
$rNumber = (float) ($this->shippingNet(2, '.', '')) * $faktor;
break;
case 'subtotalWithShipping':
$rNumber = (float) ($this->subtotalWithShipping(2, '.', '')) * $faktor;
break;
case 'taxWithShipping':
$rNumber = (float) ($this->taxWithShipping(2, '.', '')) * $faktor;
break;
case 'totalWithShipping':
$rNumber = (float) ($this->totalWithShipping(2, '.', '')) * $faktor;
break;
case 'total':
$rNumber = (float) ($this->total(2, '.', '')) * $faktor;
break;
case 'shipping':
$rNumber = (float) ($this->shipping(2, '.', '')) * $faktor;
break;
}
return $this->numberFormat($rNumber, $decimals, $decimalPoint, $thousandSeperator);
}
return '';
}
public function getNumComp()
{
return $this->num_comp;
}
public function getCompProductBy($comp, $product_id = false)
{
foreach ($this->content() as $row) {
if ($row->options->comp == $comp) {
return $row->options->product_id;
}
}
return false;
}
public function getContentByOrder()
{
$ret = [];
$comp = [];
foreach ($this->content() as $row) {
if ($row->options->comp) {
$comp[100 + $row->options->comp] = $row;
} else {
$ret[] = $row;
}
}
ksort($comp);
$ret = array_merge($ret, $comp);
return $ret;
}
/**
* Get the Formated number
*
* @return string
*/
protected function numberFormat($value, $decimals, $decimalPoint, $thousandSeperator)
{
if (is_null($decimals)) {
$decimals = is_null(config('cart.format.decimals')) ? 2 : config('cart.format.decimals');
}
if (is_null($decimalPoint)) {
$decimalPoint = is_null(config('cart.format.decimal_point')) ? '.' : config('cart.format.decimal_point');
}
if (is_null($thousandSeperator)) {
$thousandSeperator = is_null(config('cart.format.thousand_seperator')) ? ',' : config('cart.format.thousand_seperator');
}
return number_format($value, $decimals, $decimalPoint, $thousandSeperator);
}
public function myStore($identifier, array $eventOptions = [])
{
// Remove any existing identifiers
// Although possibly first or update could work in future
$this
->getConnection()
->table($this->getTableName())
->where('identifier', $identifier)
->delete();
// Insert into the database with the new cart
$content = $this->getContent();
$this->getConnection()->table($this->getTableName())->insert([
'identifier' => $identifier,
'instance' => $this->currentInstance(),
'content' => serialize($content),
]);
$eventOptions = array_merge([
'cartInstance' => $this->currentInstance(),
], $eventOptions);
// $this->events->dispatch('cart.stored', $eventOptions);
}
/**
* Restore the cart with the given identifier.
*
* @param mixed $identifier
* @return void
*/
}