Skip to content
Code-Schnipsel Gruppen Projekte
ShippingRule.php 26,9 KiB
Newer Older
  • Learn to ignore specific revisions
  • <?php
    
    /**
     * This file contains QUI\ERP\Shipping\Rules\ShippingRule
     */
    
    namespace QUI\ERP\Shipping\Rules;
    
    use QUI;
    use QUI\CRUD\Factory;
    
    use QUI\ERP\Address;
    
    use QUI\ERP\Areas\Utils as AreaUtils;
    
    Henning Leutz's avatar
    Henning Leutz committed
    use QUI\ERP\Products\Handler\Fields;
    use QUI\ERP\Products\Handler\Products;
    
    use QUI\ERP\Products\Utils\Fields as FieldUtils;
    
    Henning Leutz's avatar
    Henning Leutz committed
    use QUI\ERP\Shipping\Debug;
    
    use QUI\ERP\Shipping\Exceptions\ShippingCanNotBeUsed;
    
    Henning Leutz's avatar
    Henning Leutz committed
    use QUI\ERP\Shipping\Rules\Factory as RuleFactory;
    
    use QUI\Locale;
    
    Henning Leutz's avatar
    Henning Leutz committed
    use QUI\Permissions\Permission;
    use QUI\Translator;
    
    Henning Leutz's avatar
    Henning Leutz committed
    use function array_filter;
    use function array_flip;
    use function array_map;
    use function array_merge;
    use function array_unique;
    
    Henning Leutz's avatar
    Henning Leutz committed
    use function count;
    
    Henning Leutz's avatar
    Henning Leutz committed
    use function explode;
    use function floatval;
    
    use function in_array;
    
    Henning Leutz's avatar
    Henning Leutz committed
    use function is_array;
    use function is_numeric;
    use function is_string;
    use function json_decode;
    use function json_encode;
    use function round;
    use function strtotime;
    use function time;
    use function trim;
    
    
    /**
     * 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();
    
    
    Henning Leutz's avatar
    Henning Leutz committed
                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');
    
    Henning Leutz's avatar
    Henning Leutz committed
                $id = $this->getId();
    
    Henning Leutz's avatar
    Henning Leutz committed
                $attributes = $this->getAttributes();
    
    
    Henning Leutz's avatar
    Henning Leutz committed
                if (is_array($attributes['title'])) {
    
                    QUI\Translator::edit(
    
    Henning Leutz's avatar
    Henning Leutz committed
                        'quiqqer/shipping',
    
    Henning Leutz's avatar
    Henning Leutz committed
                        'shipping.' . $id . '.rule.title',
    
    Henning Leutz's avatar
    Henning Leutz committed
                        'quiqqer/shipping',
                        $attributes['title']
                    );
    
    Henning Leutz's avatar
    Henning Leutz committed
                if (is_array($attributes['workingTitle'])) {
    
                    QUI\Translator::edit(
    
    Henning Leutz's avatar
    Henning Leutz committed
                        'quiqqer/shipping',
    
    Henning Leutz's avatar
    Henning Leutz committed
                        'shipping.' . $id . '.rule.workingTitle',
    
    Henning Leutz's avatar
    Henning Leutz committed
                        'quiqqer/shipping',
                        $attributes['workingTitle']
                    );
    
    Henning Leutz's avatar
    Henning Leutz committed
    
                QUI\Translator::publish('quiqqer/shipping');
    
    Henning Leutz's avatar
    Henning Leutz committed
                $attributes['discount'] = floatval($attributes['discount']);
    
    Henning Leutz's avatar
    Henning Leutz committed
                if (is_numeric($attributes['discount_type']) || empty($attributes['discount_type'])) {
    
                    $attributes['discount_type'] = (int)$attributes['discount_type'];
                }
    
    
    Henning Leutz's avatar
    Henning Leutz committed
                if (
                    $attributes['discount_type'] === RuleFactory::DISCOUNT_TYPE_PERCENTAGE ||
    
                    $attributes['discount_type'] === 'PERCENTAGE'
                ) {
                    $attributes['discount_type'] = RuleFactory::DISCOUNT_TYPE_PERCENTAGE;
    
    Henning Leutz's avatar
    Henning Leutz committed
                } elseif (
                    $attributes['discount_type'] === RuleFactory::DISCOUNT_TYPE_PC_ORDER ||
                    $attributes['discount_type'] === 'PERCENTAGE_ORDER'
                ) {
    
                    $attributes['discount_type'] = RuleFactory::DISCOUNT_TYPE_PC_ORDER;
    
                } else {
                    $attributes['discount_type'] = RuleFactory::DISCOUNT_TYPE_ABS;
                }
    
    
    Henning Leutz's avatar
    Henning Leutz committed
                if (empty($attributes['articles_only'])) {
    
                    $attributes['articles_only'] = 0;
                } else {
                    $attributes['articles_only'] = (int)$attributes['articles_only'];
                }
    
    
    Henning Leutz's avatar
    Henning Leutz committed
                if (empty($attributes['no_rule_after'])) {
    
                    $attributes['no_rule_after'] = 0;
                } else {
                    $attributes['no_rule_after'] = (int)$attributes['no_rule_after'];
                }
    
    
    Henning Leutz's avatar
    Henning Leutz committed
                if (isset($attributes['unit_terms']) && is_array($attributes['unit_terms'])) {
                    $attributes['unit_terms'] = json_encode($attributes['unit_terms']);
    
                }
    
                // null fix
    
                $nullEmpty = [
                    'purchase_quantity_from',
                    'purchase_quantity_until',
                    'purchase_value_from',
                    'purchase_value_until',
    
                    'unit_terms'
    
                ];
    
                foreach ($nullEmpty as $k) {
                    if (empty($attributes[$k])) {
                        $attributes[$k] = null;
                    }
    
    
                // update for saving
                $this->setAttributes($attributes);
    
        /**
         * Return the payment as an array
         *
         * @return array
         */
    
        public function toArray(): array
    
        {
            $lg = 'quiqqer/shipping';
            $id = $this->getId();
    
            $attributes = $this->getAttributes();
    
    Henning Leutz's avatar
    Henning Leutz committed
            $Locale = QUI::getLocale();
    
            $availableLanguages = QUI\Translator::getAvailableLanguages();
    
    
            foreach ($availableLanguages as $language) {
                $attributes['title'][$language] = $Locale->getByLang(
                    $language,
                    $lg,
    
    Henning Leutz's avatar
    Henning Leutz committed
                    'shipping.' . $id . '.rule.title'
    
                );
    
                $attributes['workingTitle'][$language] = $Locale->getByLang(
                    $language,
                    $lg,
    
    Henning Leutz's avatar
    Henning Leutz committed
                    'shipping.' . $id . '.rule.workingTitle'
    
            $attributes['unit_terms'] = $this->getUnitTerms();
    
    
            return $attributes;
        }
    
    
        /**
         * Return the shipping rule title
         *
    
         * @param Locale|null $Locale
    
         * @return string
         */
    
        public function getTitle(QUI\Locale $Locale = null): string
    
        {
            if ($Locale === null) {
                $Locale = QUI::getLocale();
            }
    
            $language = $Locale->getCurrent();
    
    Henning Leutz's avatar
    Henning Leutz committed
            $id = $this->getId();
    
    
            return $Locale->getByLang(
                $language,
                'quiqqer/shipping',
    
    Henning Leutz's avatar
    Henning Leutz committed
                'shipping.' . $id . '.rule.title'
    
            );
        }
    
        /**
         * Return the shipping rule priority
         *
         * @return int
         */
    
        public function getPriority(): int
    
        {
            return (int)$this->getAttribute('priority');
        }
    
        /**
         * Return the shipping rule discount value
         *
         * @return float
         */
    
        public function getDiscount(): float
    
    Henning Leutz's avatar
    Henning Leutz committed
            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): bool
    
        {
            if ($this->isActive() === false) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                Debug::addLog("{$this->getTitle()} :: is not active");
    
    
                return false;
            }
    
    
            if ($User instanceof QUI\ERP\User) {
                try {
    
    Henning Leutz's avatar
    Henning Leutz committed
                    $User = QUI::getUsers()->get($User->getUUID());
    
    Henning Leutz's avatar
    Henning Leutz committed
                } catch (QUI\Exception) {
    
            try {
                QUI::getEvents()->fireEvent('quiqqerShippingCanUsedBy', [$this, $User]);
    
            } catch (ShippingCanNotBeUsed) {
    
                return false;
            } catch (QUI\Exception $Exception) {
                QUI\System\Log::writeDebugException($Exception);
    
                return false;
            }
    
    
            // usage definitions / limits
    
    Henning Leutz's avatar
    Henning Leutz committed
            $dateFrom = $this->getAttribute('date_from');
    
            $dateUntil = $this->getAttribute('date_until');
    
    Henning Leutz's avatar
    Henning Leutz committed
            $now = time();
    
    Henning Leutz's avatar
    Henning Leutz committed
            if ($dateFrom && strtotime($dateFrom) > $now) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                Debug::addLog("{$this->getTitle()} :: date from is not valid $dateFrom > $now");
    
                return false;
            }
    
    
    Henning Leutz's avatar
    Henning Leutz committed
            if ($dateUntil && strtotime($dateUntil) < $now) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                Debug::addLog("{$this->getTitle()} :: date from is not valid $dateFrom < $now");
    
                return false;
            }
    
            // assignment
            $userGroupValue = $this->getAttribute('user_groups');
    
    Henning Leutz's avatar
    Henning Leutz committed
            $areasValue = $this->getAttribute('areas');
    
    
            // if groups and areas are empty, everybody is allowed
            if (empty($userGroupValue) && empty($areasValue)) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                Debug::addLog("{$this->getTitle()} :: empty user and areas [ok]");
    
    
                return true;
            }
    
            // not in area
    
            // address need to be checked via erp entity
    
            // user checking
    
            $userGroups = QUI\Utils\UserGroups::parseUsersGroupsString(
                $this->getAttribute('user_groups')
            );
    
    
    Henning Leutz's avatar
    Henning Leutz committed
            $discountUsers = $userGroups['users'];
    
            $discountGroups = $userGroups['groups'];
    
            if (empty($discountUsers) && empty($discountGroups)) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                Debug::addLog("{$this->getTitle()} :: empty discount [ok]");
    
    
                return true;
            }
    
            foreach ($discountUsers as $uid) {
    
                if ($User->getId() == $uid || $User->getUUID() === $uid) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                    Debug::addLog("{$this->getTitle()} :: user is found in users [ok]");
    
    
                    return true;
                }
            }
    
            // group checking
            $groupsOfUser = $User->getGroups();
    
            /* @var $Group QUI\Groups\Group */
            foreach ($discountGroups as $gid) {
                foreach ($groupsOfUser as $Group) {
    
                    if ($Group->getId() == $gid || $Group->getUUID() == $gid) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                        Debug::addLog("{$this->getTitle()} :: group is found in groups [ok]");
    
    
    Henning Leutz's avatar
    Henning Leutz committed
            Debug::addLog("{$this->getTitle()} :: shipping rule is not valid. is not found in users and groups");
    
    
            return false;
        }
    
    
        /**
         * Is this shipping rule allowed for this address?
         *
    
         * @param Address|QUI\Users\Address|null $Address
    
         * @return bool
         */
    
        public function canUsedWithAddress(QUI\ERP\Address|QUI\Users\Address $Address = null): bool
    
            $areasValue = $this->getAttribute('areas');
    
            if ($areasValue) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                $areasValue = explode(',', $areasValue);
                $areasValue = array_filter($areasValue);
    
            }
    
            if (!empty($areasValue) && !AreaUtils::isAddressInArea($Address, $areasValue)) {
                Debug::addLog("{$this->getTitle()} :: user address is not in areas");
    
                return false;
            }
    
            return true;
        }
    
    
         * is the shipping allowed in this erp entity?
    
         * @param QUI\ERP\ErpEntityInterface|null $ErpEntity
    
         * @return bool
         */
    
        public function canUsedIn(QUI\ERP\ErpEntityInterface $ErpEntity = null): bool
    
            if (!$this->isValid()) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                Debug::addLog("{$this->getTitle()} :: is not valid");
    
    
            if (!$ErpEntity) {
    
            if (!$this->canUsedBy($ErpEntity->getCustomer())) {
    
                Debug::addLog("{$this->getTitle()} :: can not be used by {$ErpEntity->getCustomer()->getUUID()}");
    
            $DeliveryAddress = $ErpEntity->getDeliveryAddress();
    
    
            if (!$this->canUsedWithAddress($DeliveryAddress)) {
                Debug::addLog("{$this->getTitle()} :: can not be used with address");
    
                return false;
            }
    
    
            $Articles = $ErpEntity->getArticles();
    
            $articleList = $Articles->getArticles();
    
    
            if (!$Articles->count()) {
                return false;
            }
    
    
    Henning Leutz's avatar
    Henning Leutz committed
            $articles = $this->getAttribute('articles');
    
            $articleOnly = (int)$this->getAttribute('articles_only');
    
    Henning Leutz's avatar
    Henning Leutz committed
            $unitTerms = $this->getUnitTerms();
    
            $categories = $this->getAttribute('categories');
            $categories = trim($categories, ',');
            $categories = explode(',', $categories);
            $categories = array_map('intval', $categories);
    
    
    Henning Leutz's avatar
    Henning Leutz committed
            $quantityFrom = $this->getAttribute('purchase_quantity_from');     // Einkaufsmenge ab
    
            $quantityUntil = $this->getAttribute('purchase_quantity_until');    // Einkaufsmenge bis
    
    Henning Leutz's avatar
    Henning Leutz committed
            $purchaseFrom = $this->getAttribute('purchase_value_from');        // Einkaufswert ab
    
            $purchaseUntil = $this->getAttribute('purchase_value_until');       // Einkaufswert bis
    
            // article checks
    
    Henning Leutz's avatar
    Henning Leutz committed
            $Shipping = QUI\ERP\Shipping\Shipping::getInstance();
            $unitIds = $Shipping->getShippingRuleUnitFieldIds();
    
            $articleFound = true;
            $articleUnits = [];
    
    Henning Leutz's avatar
    Henning Leutz committed
            $debugUnits = [];
    
    
            if (!empty($articles)) {
                $articleFound = false;
    
    
    Henning Leutz's avatar
    Henning Leutz committed
                if (is_string($articles)) {
                    $articles = explode(',', $articles);
                    $articles = array_filter($articles);
    
    Henning Leutz's avatar
    Henning Leutz committed
                if (!is_array($articles)) {
    
                    $articles = [$articles];
                }
    
    
    Henning Leutz's avatar
    Henning Leutz committed
                $articles = array_flip($articles);
    
            } else {
                $articleOnly = 0;
    
            $categoryIdsInEntity = [];
    
            $checkCategoryIds = function (array $catIds) use ($categories) {
                foreach ($catIds as $categoryId) {
                    if (in_array($categoryId, $categories)) {
                        return true;
                    }
                }
    
                return false;
            };
    
    
            foreach ($articleList as $Article) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                $aid = $Article->getId();
    
                $articleQuantity = $Article->getQuantity();
    
                // get product because of units
    
    Henning Leutz's avatar
    Henning Leutz committed
                    $Product = Products::getProduct($aid);
    
                    $productCategories = $Product->getCategories();
    
    
    Henning Leutz's avatar
    Henning Leutz committed
                    $categoryIds = array_map(function ($Category) {
    
                        return $Category->getId();
                    }, $productCategories);
    
    
                    // check categories
                    if ($checkCategoryIds($categoryIds) === false) {
                        return false;
                    }
    
    
                    $categoryIdsInEntity = array_merge($categoryIdsInEntity, $categoryIds);
    
                    foreach ($unitIds as $unitId) {
                        $Weight = $Product->getField($unitId);
                        $weight = $Weight->getValue();
    
    
                        if ((int)$unitId === Fields::FIELD_WEIGHT) {
    
                            $weight = FieldUtils::weightFieldToKilogram($Weight);
                        }
    
    
    Henning Leutz's avatar
    Henning Leutz committed
                        if (is_array($weight)) {
    
                            $weight = $weight['quantity'];
                        }
    
    
                        if (!isset($articleUnits[$unitId])) {
                            $articleUnits[$unitId] = 0;
                        }
    
    
                        $articleUnits[$unitId] = $articleUnits[$unitId] + ($weight * $articleQuantity);
    
    Henning Leutz's avatar
    Henning Leutz committed
    
                        $debugUnits[$unitId] = [
    
    Henning Leutz's avatar
    Henning Leutz committed
                            'field' => $Weight->getTitle(),
    
    Henning Leutz's avatar
    Henning Leutz committed
                            'amount' => $articleUnits[$unitId]
                        ];
    
                } catch (QUI\Exception $Exception) {
                    QUI\System\Log::writeDebugException($Exception);
                }
    
                if (empty($articles)) {
                    continue;
                }
    
                if (isset($articles[$aid])) {
                    $articleFound = true;
                    break;
                }
            }
    
    
    Henning Leutz's avatar
    Henning Leutz committed
            if (QUI\ERP\Shipping\Debug::isEnabled()) {
                foreach ($debugUnits as $debugUnit) {
                    QUI\ERP\Shipping\Debug::addLog(
                        "- Check units {$debugUnit['field']} -> {$debugUnit['amount']}"
                    );
                }
            }
    
    
    Henning Leutz's avatar
    Henning Leutz committed
            if ($articleFound && $articleOnly && count($articleList) !== 1) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                QUI\ERP\Shipping\Debug::addLog(
                    "{$this->getTitle()} :: is not a single article"
                );
    
    
            if ($articleFound === false) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                QUI\ERP\Shipping\Debug::addLog(
                    "{$this->getTitle()} :: article not found for this rule"
                );
    
    
            // category check
    
            $categoryIdsInEntity = array_unique($categoryIdsInEntity);
    
            if (!empty($categoryIdsInEntity) && (count($categories) === 1 && $categories[0] !== 0)) {
    
                $found = false;
    
                foreach ($categories as $cid) {
    
                    if (in_array($cid, $categoryIdsInEntity)) {
    
                        $found = true;
                        break;
                    }
                }
    
                if ($found === false) {
                    return false;
                }
            }
    
    
            // unit terms check
            if (!empty($unitTerms)) {
                foreach ($unitTerms as $unitTerm) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                    if (!is_array($unitTerm)) {
    
                        continue;
                    }
    
                    if (!isset($unitTerm['value'])) {
                        $unitTerm['value'] = '';
                    }
    
                    if (!isset($unitTerm['value2'])) {
                        $unitTerm['value2'] = '';
                    }
    
                    if ($unitTerm['value'] === '' && $unitTerm['value2'] === '') {
    
                    if (empty($unitTerm['term'])) {
                        $unitTerm['term'] = 'gt';
                    }
    
                    if (empty($unitTerm['term2'])) {
                        $unitTerm['term2'] = 'gt';
                    }
    
    
    Henning Leutz's avatar
    Henning Leutz committed
                    $id = (int)$unitTerm['id'];
                    $unit = $unitTerm['unit'];
    
    Henning Leutz's avatar
    Henning Leutz committed
                    $value = floatval($unitTerm['value']);
    
    Henning Leutz's avatar
    Henning Leutz committed
                    $term = $unitTerm['term'];
    
    Henning Leutz's avatar
    Henning Leutz committed
                    $hTerm = FieldUtils::termToHuman($term);
    
    
                    if (!isset($articleUnits[$id])) {
                        continue;
                    }
    
                    if ($id === Fields::FIELD_WEIGHT) {
                        $unitValue = FieldUtils::weightToKilogram($value, $unit);
    
    Henning Leutz's avatar
    Henning Leutz committed
                        $compare = FieldUtils::compare($articleUnits[$id], $unitValue, $term);
    
    
                        if ($compare === false) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                            QUI\ERP\Shipping\Debug::addLog(
    
    Henning Leutz's avatar
    Henning Leutz committed
                                "{$this->getTitle()} :: weight is not valid $articleUnits[$id] $hTerm $unitValue"
    
                            return false;
                        }
    
    
                        // term 2
                        if (!empty($unitTerm['value2'])) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                            $value2 = floatval($unitTerm['value2']);
    
    Henning Leutz's avatar
    Henning Leutz committed
                            $term2 = $unitTerm['term2'];
    
    Henning Leutz's avatar
    Henning Leutz committed
                            $hTerm2 = FieldUtils::termToHuman($term2);
    
    
                            $unitValue = FieldUtils::weightToKilogram($value2, $unit);
    
    Henning Leutz's avatar
    Henning Leutz committed
                            $compare2 = FieldUtils::compare($articleUnits[$id], $unitValue, $term2);
    
    Henning Leutz's avatar
    Henning Leutz committed
                                QUI\ERP\Shipping\Debug::addLog(
    
    Henning Leutz's avatar
    Henning Leutz committed
                                    "{$this->getTitle()} :: weight is not valid $articleUnits[$id] $hTerm2 $unitValue"
    
                        continue;
                    }
    
                    $compare = FieldUtils::compare($articleUnits[$id], $value, $term);
    
                    if ($compare === false) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                        QUI\ERP\Shipping\Debug::addLog(
    
    Henning Leutz's avatar
    Henning Leutz committed
                            "{$this->getTitle()} :: unit term is not valid $articleUnits[$id] $hTerm $value"
    
                        return false;
                    }
    
    Henning Leutz's avatar
    Henning Leutz committed
                        $value2 = floatval($unitTerm['value2']);
                        $term2 = $unitTerm['term2'];
                        $hTerm2 = FieldUtils::termToHuman($term2);
    
                        $compare2 = FieldUtils::compare($articleUnits[$id], $value2, $term2);
    
                        if ($compare2 === false) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                            QUI\ERP\Shipping\Debug::addLog(
    
    Henning Leutz's avatar
    Henning Leutz committed
                                "{$this->getTitle()} :: unit term is not valid $articleUnits[$id] $hTerm2 $value2"
    
            $count = $ErpEntity->count();
    
    
            if (!empty($quantityFrom) && $quantityFrom < $count) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                QUI\ERP\Shipping\Debug::addLog(
    
    Henning Leutz's avatar
    Henning Leutz committed
                    "{$this->getTitle()} :: quantity from is not valid, $count < $quantityFrom"
    
                return false;
            }
    
            if (!empty($quantityUntil) && $quantityFrom > $count) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                QUI\ERP\Shipping\Debug::addLog(
    
    Henning Leutz's avatar
    Henning Leutz committed
                    "{$this->getTitle()} :: quantity until is not valid, $count > $quantityFrom"
    
                return false;
            }
    
            // purchase
            try {
    
                $Calculation = $ErpEntity->getPriceCalculation();
                $Currency = $ErpEntity->getCurrency();
                $PriceFactors = $ErpEntity->getArticles()->getPriceFactors();
    
    Henning Leutz's avatar
    Henning Leutz committed
                $ShippingFactor = null;
    
                /* @var $Factor QUI\ERP\Products\Interfaces\PriceFactorInterface */
                foreach ($PriceFactors as $Factor) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                    if (str_contains($Factor->getIdentifier(), 'shipping-pricefactor')) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                        $ShippingFactor = $Factor;
                        break;
                    }
                }
    
                $Sum = $Calculation->getNettoSum();
                $sum = $Sum->precision($Currency->getPrecision())->get();
    
                /* quiqqer/shipping#25 */
                if ($ShippingFactor) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                    $sum = $sum - round($ShippingFactor->getNettoSum(), $Currency->getPrecision());
    
            } catch (QUI\Exception $Exception) {
                QUI\System\Log::writeDebugException($Exception);
    
                return false;
            }
    
            if (!empty($purchaseFrom)) {
    
                $purchaseFrom = QUI\ERP\Money\Price::validatePrice($purchaseFrom);
    
                if ($purchaseFrom >= $sum) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                    QUI\ERP\Shipping\Debug::addLog(
    
    Henning Leutz's avatar
    Henning Leutz committed
                        "{$this->getTitle()} :: purchase from is not valid, $purchaseFrom < $sum"
    
                    return false;
                }
            }
    
            if (!empty($purchaseUntil)) {
    
                $purchaseUntil = QUI\ERP\Money\Price::validatePrice($purchaseUntil);
    
                if ($purchaseUntil <= $sum) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                    QUI\ERP\Shipping\Debug::addLog(
    
    Henning Leutz's avatar
    Henning Leutz committed
                        "{$this->getTitle()} :: purchase from is not valid, $purchaseFrom > $sum"
    
            // categories check
    
            try {
    
                QUI::getEvents()->fireEvent('shippingCanUsedInOrder', [$this, $ErpEntity]);
                QUI::getEvents()->fireEvent('shippingCanUsedInEntity', [$this, $ErpEntity]);
    
    Henning Leutz's avatar
    Henning Leutz committed
            } catch (ShippingCanNotBeUsed) {
    
                return false;
            } catch (QUI\Exception $Exception) {
                QUI\System\Log::addDebug($Exception->getMessage());
    
                return false;
            }
    
    
    Henning Leutz's avatar
    Henning Leutz committed
            QUI\ERP\Shipping\Debug::addLog(
                "{$this->getTitle()} :: is valid [ok]"
            );
    
    
            return true;
        }
    
    
        /**
         * no further rules are used after this rule
         *
         * @return bool
         */
    
    Henning Leutz's avatar
    Henning Leutz committed
        public function noRulesAfter(): bool
    
        {
            if ($this->existsAttribute('no_rule_after')) {
                return !!$this->getAttribute('no_rule_after');
            }
    
            return false;
        }
    
    
        /**
         * Return the validation status of this rule
         * can the rule be used?
         */
    
    Henning Leutz's avatar
    Henning Leutz committed
        public function isValid(): bool
    
        {
            if (!$this->isActive()) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                QUI\ERP\Shipping\Debug::addLog(
    
    Henning Leutz's avatar
    Henning Leutz committed
                    $this->getTitle() . " :: is not active"
    
                return false;
            }
    
            // check date
    
    Henning Leutz's avatar
    Henning Leutz committed
            $usageFrom = $this->getAttribute('date_from');
    
            $usageUntil = $this->getAttribute('date_until');
    
    Henning Leutz's avatar
    Henning Leutz committed
            $time = time();
    
    
            if (!empty($usageFrom)) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                $usageFrom = strtotime($usageFrom);
    
    
                if ($usageFrom > $time) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                    QUI\ERP\Shipping\Debug::addLog(
    
    Henning Leutz's avatar
    Henning Leutz committed
                        $this->getTitle() . " :: usage from is not ok, $usageFrom > $time"
    
                    return false;
                }
            }
    
            if (!empty($usageUntil)) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                $usageUntil = strtotime($usageUntil);
    
    
                if ($usageUntil < $time) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                    QUI\ERP\Shipping\Debug::addLog(
    
    Henning Leutz's avatar
    Henning Leutz committed
                        $this->getTitle() . " :: usage from is not ok, $usageFrom < $time"
    
    Henning Leutz's avatar
    Henning Leutz committed
            QUI\ERP\Shipping\Debug::addLog(
    
    Henning Leutz's avatar
    Henning Leutz committed
                $this->getTitle() . " :: is valid, date from to is valid"
    
        /**
         * Return the discount type
         *
         * @return int
         */
    
    Henning Leutz's avatar
    Henning Leutz committed
        public function getDiscountType(): int
    
        {
            return (int)$this->getAttribute('discount_type');
        }
    
    
        /**
         * Return the unit terms
         *
         * @return bool|array
         */
    
    Henning Leutz's avatar
    Henning Leutz committed
        public function getUnitTerms(): bool|array
    
        {
            $unitTerms = $this->getAttribute('unit_terms');
    
            if (empty($unitTerms)) {
                return false;
            }
    
    
    Henning Leutz's avatar
    Henning Leutz committed
            $unitTerms = json_decode($unitTerms, true);
    
    
            if ($unitTerms) {
                return $unitTerms;
            }
    
            return false;
        }
    
    
        // region activation / deactivation
    
        /**
         * Activate the shipping type
         *
         * @throws QUI\ExceptionStack|QUI\Exception
         */
    
    Henning Leutz's avatar
    Henning Leutz committed
        public function activate(): void
    
        {
            $this->setAttribute('active', 1);
            $this->update();
            $this->refresh();
        }
    
        /**
         * Is the shipping active?
         *
         * @return bool
         */
    
    Henning Leutz's avatar
    Henning Leutz committed
        public function isActive(): bool
    
        {
            return !!$this->getAttribute('active');
        }
    
        /**
         * Deactivate the shipping type
         *
         * @throws QUI\ExceptionStack|QUI\Exception
         */
    
    Henning Leutz's avatar
    Henning Leutz committed
        public function deactivate(): void
    
        {
            $this->setAttribute('active', 0);
            $this->update();
            $this->refresh();
        }
    
        //endregion
    
    
        //region setter
    
        /**
         * Set the title
         *
         * @param array $titles
         */
    
    Henning Leutz's avatar
    Henning Leutz committed
        public function setTitle(array $titles): void
    
        {
            $this->setLocaleVar(
    
    Henning Leutz's avatar
    Henning Leutz committed
                'shipping.' . $this->getId() . '.rule.title',
    
                $titles
            );
        }
    
        /**
         * Set the working title
         *
         * @param array $titles
         */
    
    Henning Leutz's avatar
    Henning Leutz committed
        public function setWorkingTitle(array $titles): void
    
        {
            $this->setLocaleVar(
    
    Henning Leutz's avatar
    Henning Leutz committed
                'shipping.' . $this->getId() . '.rule.workingTitle',
    
                $titles
            );
        }
    
        /**
         * Creates a locale
         *
         * @param string $var
         * @param array $title
         */
    
    Henning Leutz's avatar
    Henning Leutz committed
        protected function setLocaleVar(string $var, array $title): void
    
        {
            $data = [
                'datatype' => 'php,js',
    
    Henning Leutz's avatar
    Henning Leutz committed
                'package' => 'quiqqer/shipping'
    
            ];
    
            $languages = QUI::availableLanguages();
    
            foreach ($languages as $language) {
                if (!isset($title[$language])) {
                    continue;
                }
    
    
    Henning Leutz's avatar
    Henning Leutz committed
                $data[$language] = $title[$language];
    
    Henning Leutz's avatar
    Henning Leutz committed
                $data[$language . '_edit'] = $title[$language];
    
            }
    
            $exists = Translator::getVarData('quiqqer/shipping', $var, 'quiqqer/shipping');
    
            try {
                if (empty($exists)) {
                    Translator::addUserVar('quiqqer/shipping', $var, $data);
                } else {
                    Translator::edit('quiqqer/shipping', $var, 'quiqqer/shipping', $data);
                }
            } catch (QUI\Exception $Exception) {
                QUI\System\Log::addNotice($Exception->getMessage());
            }
    
            try {
                Translator::publish('quiqqer/shipping');
            } catch (QUi\Exception $Exception) {
                QUI\System\Log::writeException($Exception);
            }
        }
    
        //endregion