<?php /** * This file contains QUI\ERP\Shipping\Rules\ShippingRule */ namespace QUI\ERP\Shipping\Rules; use QUI; use QUI\CRUD\Factory; use QUI\Permissions\Permission; use QUI\ERP\Areas\Utils as AreaUtils; use QUI\ERP\Products\Utils\Fields as FieldUtils; use QUI\ERP\Shipping\Rules\Factory as RuleFactory; use QUI\ERP\Shipping\Exceptions\ShippingCanNotBeUsed; use QUI\ERP\Products\Handler\Products; use QUI\ERP\Products\Handler\Fields; /** * Class ShippingEntry * A user created shipping entry * * @package QUI\ERP\Shipping\Types */ class ShippingRule extends QUI\CRUD\Child { /** * Shipping constructor. * * @param int $id * @param Factory $Factory */ public function __construct($id, Factory $Factory) { parent::__construct($id, $Factory); $this->Events->addEvent('onDeleteBegin', function () { Permission::checkPermission('quiqqer.shipping.delete'); // delete locale $id = $this->getId(); QUI\Translator::delete('quiqqer/shipping', 'shipping.'.$id.'.rule.title'); QUI\Translator::delete('quiqqer/shipping', 'shipping.'.$id.'.rule.workingTitle'); }); $this->Events->addEvent('onSaveBegin', function () { Permission::checkPermission('quiqqer.shipping.edit'); $id = $this->getId(); $attributes = $this->getAttributes(); if (\is_array($attributes['title'])) { QUI\Translator::edit( 'quiqqer/shipping', 'shipping.'.$id.'.rule.title', 'quiqqer/shipping', $attributes['title'] ); }; if (\is_array($attributes['workingTitle'])) { QUI\Translator::edit( 'quiqqer/shipping', 'shipping.'.$id.'.rule.workingTitle', 'quiqqer/shipping', $attributes['workingTitle'] ); }; QUI\Translator::publish('quiqqer/shipping'); // discount $attributes['discount'] = \floatval($attributes['discount']); if (\is_numeric($attributes['discount_type']) || empty($attributes['discount_type'])) { $attributes['discount_type'] = (int)$attributes['discount_type']; } if ($attributes['discount_type'] === RuleFactory::DISCOUNT_TYPE_PERCENTAGE || $attributes['discount_type'] === 'PERCENTAGE' ) { $attributes['discount_type'] = RuleFactory::DISCOUNT_TYPE_PERCENTAGE; } else { $attributes['discount_type'] = RuleFactory::DISCOUNT_TYPE_ABS; } // purchase if (empty($attributes['purchase_quantity_from'])) { $attributes['purchase_quantity_from'] = null; } if (empty($attributes['purchase_quantity_to'])) { $attributes['purchase_quantity_until'] = null; } if (empty($attributes['purchase_value_to'])) { $attributes['purchase_value_until'] = null; } if (empty($attributes['purchase_value_to'])) { $attributes['purchase_value_until'] = null; } // update for saving $this->setAttributes($attributes); }); } /** * Return the payment as an array * * @return array */ public function toArray() { $lg = 'quiqqer/shipping'; $id = $this->getId(); $attributes = $this->getAttributes(); $Locale = QUI::getLocale(); try { $availableLanguages = QUI\Translator::getAvailableLanguages(); } catch (QUI\Exception $Exception) { QUI\System\Log::writeException($Exception); $availableLanguages = []; } foreach ($availableLanguages as $language) { $attributes['title'][$language] = $Locale->getByLang( $language, $lg, 'shipping.'.$id.'.rule.title' ); $attributes['workingTitle'][$language] = $Locale->getByLang( $language, $lg, 'shipping.'.$id.'.rule.workingTitle' ); } return $attributes; } /** * Return the shipping rule title * * @param null $Locale * @return string */ public function getTitle($Locale = null) { if ($Locale === null) { $Locale = QUI::getLocale(); } $language = $Locale->getCurrent(); $id = $this->getId(); return $Locale->getByLang( $language, 'quiqqer/shipping', 'shipping.'.$id.'.rule.title' ); } /** * Return the shipping rule priority * * @return int */ public function getPriority() { return (int)$this->getAttribute('priority'); } /** * Return the shipping rule discount value * * @return float */ public function getDiscount() { return \floatval($this->getAttribute('discount')); } /** * is the user allowed to use this shipping * * @param QUI\Interfaces\Users\User $User * @return boolean */ public function canUsedBy(QUI\Interfaces\Users\User $User) { if ($this->isActive() === false) { return false; } try { QUI::getEvents()->fireEvent('quiqqerShippingCanUsedBy', [$this, $User]); } catch (ShippingCanNotBeUsed $Exception) { return false; } catch (QUI\Exception $Exception) { QUI\System\Log::writeDebugException($Exception); return false; } // usage definitions / limits $dateFrom = $this->getAttribute('date_from'); $dateUntil = $this->getAttribute('date_until'); $now = \time(); if ($dateFrom && \strtotime($dateFrom) > $now) { return false; } if ($dateUntil && \strtotime($dateUntil) < $now) { return false; } // assignment $userGroupValue = $this->getAttribute('user_groups'); $areasValue = $this->getAttribute('areas'); // if groups and areas are empty, everybody is allowed if (empty($userGroupValue) && empty($areasValue)) { return true; } // not in area if ($areasValue) { $areasValue = \explode(',', $areasValue); } if (!empty($areasValue) && !AreaUtils::isUserInAreas($User, $areasValue)) { return false; } $userGroups = QUI\Utils\UserGroups::parseUsersGroupsString( $this->getAttribute('user_groups') ); $discountUsers = $userGroups['users']; $discountGroups = $userGroups['groups']; if (empty($discountUsers) && empty($discountGroups)) { return true; } // user checking foreach ($discountUsers as $uid) { if ($User->getId() == $uid) { return true; } } // group checking $groupsOfUser = $User->getGroups(); /* @var $Group QUI\Groups\Group */ foreach ($discountGroups as $gid) { foreach ($groupsOfUser as $Group) { if ($Group->getId() == $gid) { return true; } } } return false; } /** * is the shipping allowed in the order? * * @param QUI\ERP\Order\OrderInterface $Order * @return bool * * @todo check unit */ public function canUsedInOrder($Order) { if (!$this->isValid()) { return false; } if (!($Order instanceof QUI\ERP\Order\OrderInterface)) { return true; } if (!$this->canUsedBy($Order->getCustomer())) { return false; } /* @var $Order QUI\ERP\Order\Order */ $Articles = $Order->getArticles(); $articleList = $Articles->getArticles(); $articles = $this->getAttribute('articles'); $unitValue = $this->getAttribute('unit_value'); // weight amount $unit = $this->getAttribute('unit'); // weight type $quantityFrom = $this->getAttribute('purchase_quantity_from'); // Einkaufsmenge ab $quantityUntil = $this->getAttribute('purchase_quantity_until'); // Einkaufsmenge bis $purchaseFrom = $this->getAttribute('purchase_value_from'); // Einkaufswert ab $purchaseUntil = $this->getAttribute('purchase_value_until'); // Einkaufswert bis // article checks $articleFound = true; $articleWeight = 0; if (!empty($articles)) { $articleFound = false; if (\is_string($articles)) { $articles = \explode(',', $articles); } if (!\is_array($articles)) { $articles = [$articles]; } $articles = \array_flip($articles); } foreach ($articleList as $Article) { $aid = $Article->getId(); // get product because of weight try { $Product = Products::getProduct($aid); $Weight = $Product->getField(Fields::FIELD_WEIGHT); $weight = FieldUtils::weightFieldToKilogram($Weight); $articleWeight = $articleWeight + $weight; } catch (QUI\Exception $Exception) { QUI\System\Log::writeDebugException($Exception); } if (empty($articles)) { continue; } if (isset($articles[$aid])) { $articleFound = true; break; } } if ($articleFound === false) { return false; } // weight check if (!empty($unitValue) && !empty($unit)) { $unitValue = FieldUtils::weightToKilogram($unitValue, $unit); if ($articleWeight < $unitValue) { return false; } } // quantity check $count = $Order->count(); if (!empty($quantityFrom) && $quantityFrom < $count) { return false; } if (!empty($quantityUntil) && $quantityFrom > $count) { return false; } // purchase try { $Calculation = $Order->getPriceCalculation(); $sum = $Calculation->getSum(); } catch (QUI\Exception $Exception) { QUI\System\Log::writeDebugException($Exception); return false; } if (!empty($purchaseFrom)) { $purchaseFrom = \floatval($purchaseFrom); if ($purchaseFrom < $sum) { return false; } } if (!empty($purchaseUntil)) { $purchaseUntil = \floatval($purchaseUntil); if ($purchaseUntil > $sum) { return false; } } try { QUI::getEvents()->fireEvent('shippingCanUsedInOrder', [$this, $Order]); } catch (ShippingCanNotBeUsed $Exception) { return false; } catch (QUI\Exception $Exception) { QUI\System\Log::addDebug($Exception->getMessage()); return false; } return true; } /** * Return the validation status of this rule * can the rule be used? */ public function isValid() { if (!$this->isActive()) { return false; } // check date $usageFrom = $this->getAttribute('date_from'); $usageUntil = $this->getAttribute('date_until'); $time = \time(); if (!empty($usageFrom)) { $usageFrom = \strtotime($usageFrom); if ($usageFrom > $time) { return false; } } if (!empty($usageUntil)) { $usageUntil = \strtotime($usageUntil); if ($usageUntil < $time) { return false; } } return true; } /** * Return the discount type * * @return int */ public function getDiscountType() { return (int)$this->getAttribute('discount_type'); } // region activation / deactivation /** * Activate the shipping type * * @throws QUI\ExceptionStack|QUI\Exception */ public function activate() { $this->setAttribute('active', 1); $this->update(); $this->refresh(); } /** * Is the shipping active? * * @return bool */ public function isActive() { return !!$this->getAttribute('active'); } /** * Deactivate the shipping type * * @throws QUI\ExceptionStack|QUI\Exception */ public function deactivate() { $this->setAttribute('active', 0); $this->update(); $this->refresh(); } //endregion }