Skip to content
Code-Schnipsel Gruppen Projekte
Discount.php 14,4 KiB
Newer Older
  • Learn to ignore specific revisions
  • Henning Leutz's avatar
    Henning Leutz committed
    <?php
    
    /**
     * This file contains QUI\ERP\Discount\Discount
     */
    
    Henning Leutz's avatar
    Henning Leutz committed
    namespace QUI\ERP\Discount;
    
    use QUI;
    
    Henning Leutz's avatar
    Henning Leutz committed
    use QUI\Users\User;
    
    use QUI\Permissions\Permission;
    
    Henning Leutz's avatar
    Henning Leutz committed
    use QUI\Utils\Security\Orthos;
    
    Henning Leutz's avatar
    Henning Leutz committed
    use QUI\ERP\Areas\Utils as AreaUtils;
    
    Henning Leutz's avatar
    Henning Leutz committed
    
    /**
     * Class Discount
     * @package QUI\ERP\Discount
     */
    class Discount extends QUI\CRUD\Child
    {
    
    Henning Leutz's avatar
    Henning Leutz committed
        /**
         * Discount constructor.
    
    Henning Leutz's avatar
    Henning Leutz committed
         * @param int $id
         * @param Handler $Factory
         */
        public function __construct($id, Handler $Factory)
        {
            parent::__construct($id, $Factory);
    
    Henning Leutz's avatar
    Henning Leutz committed
            parent::refresh();
    
    
            // attributes
            switch ($this->getAttribute('discount_type')) {
                case Handler::DISCOUNT_TYPE_CURRENCY:
                case Handler::DISCOUNT_TYPE_PERCENT:
                    break;
    
                default:
                    $this->setAttribute('discount_type', Handler::DISCOUNT_TYPE_PERCENT);
                    break;
            }
    
    
            $scope = (int)$this->getAttribute('scope');
    
            switch ($scope) {
                case Handler::DISCOUNT_SCOPE_EVERY_PRODUCT:
                case Handler::DISCOUNT_SCOPE_TOTAL:
                case Handler::DISCOUNT_SCOPE_UNIQUE:
                    $this->setAttribute('scope', $scope);
                    break;
    
                default:
                    $this->setAttribute('scope', 0);
            }
    
    
            // cleanup user group save
            $cleanup = QUI\Utils\ArrayHelper::cleanup($this->getAttribute('user_groups'));
    
            $cleanup = \implode(',', $cleanup);
    
    
            if (!empty($cleanup)) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                $cleanup = ','.$cleanup.',';
    
            }
    
            $this->setAttribute('user_groups', $cleanup);
    
    
            // cleanup product(s)
            $cleanup = QUI\Utils\ArrayHelper::cleanup($this->getAttribute('articles'));
    
            $cleanup = \implode(',', $cleanup);
    
    
            if (!empty($cleanup)) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                $cleanup = ','.$cleanup.',';
    
            }
    
            $this->setAttribute('articles', $cleanup);
    
    
            // cleanup user group save
            $cleanup = QUI\Utils\ArrayHelper::cleanup($this->getAttribute('user_groups'));
    
            $cleanup = \implode(',', $cleanup);
    
    
            if (!empty($cleanup)) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                $cleanup = ','.$cleanup.',';
    
            }
    
            $this->setAttribute('user_groups', $cleanup);
    
    
            // cleanup product(s)
            $cleanup = QUI\Utils\ArrayHelper::cleanup($this->getAttribute('articles'));
    
            $cleanup = \implode(',', $cleanup);
    
    
            if (!empty($cleanup)) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                $cleanup = ','.$cleanup.',';
    
            }
    
            $this->setAttribute('articles', $cleanup);
    
    
    
            // events
    
    Henning Leutz's avatar
    Henning Leutz committed
            $this->Events->addEvent('onDeleteBegin', function () {
                Permission::checkPermission('quiqqer.areas.area.delete');
            });
    
            $this->Events->addEvent('onDeleteEnd', function () {
                QUI\Translator::delete(
                    'quiqqer/discount',
    
    Henning Leutz's avatar
    Henning Leutz committed
                    'discount.'.$this->getId().'.title'
    
    Henning Leutz's avatar
    Henning Leutz committed
                );
            });
    
            $this->Events->addEvent('onSaveBegin', function () {
                Permission::checkPermission('quiqqer.areas.area.edit');
    
                if ($this->getAttribute('date_from')
                    && !Orthos::checkMySqlDatetimeSyntax($this->getAttribute('date_from'))
                ) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                    throw new QUI\ERP\Discount\Exception([
    
    Henning Leutz's avatar
    Henning Leutz committed
                        'quiqqer/discount',
    
    Henning Leutz's avatar
    Henning Leutz committed
                        'exception.discount.date_from.wrong'
    
    Henning Leutz's avatar
    Henning Leutz committed
                    ]);
    
    Henning Leutz's avatar
    Henning Leutz committed
                }
    
                if ($this->getAttribute('date_until')
                    && !Orthos::checkMySqlDatetimeSyntax($this->getAttribute('date_until'))
                ) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                    throw new QUI\ERP\Discount\Exception([
    
    Henning Leutz's avatar
    Henning Leutz committed
                        'quiqqer/discount',
    
    Henning Leutz's avatar
    Henning Leutz committed
                        'exception.discount.date_until.wrong'
    
    Henning Leutz's avatar
    Henning Leutz committed
                    ]);
    
    Henning Leutz's avatar
    Henning Leutz committed
                $purchaseQuantityFrom  = $this->getAttribute('purchase_quantity_from');
                $purchaseQuantityUntil = $this->getAttribute('purchase_quantity_until');
                $purchaseValueFrom     = $this->getAttribute('purchase_value_from');
                $purchaseValueUntil    = $this->getAttribute('purchase_value_until');
    
    Henning Leutz's avatar
    Henning Leutz committed
                if ($purchaseQuantityFrom === false || $purchaseQuantityFrom < 0) {
                    throw new QUI\ERP\Discount\Exception([
    
    Henning Leutz's avatar
    Henning Leutz committed
                        'quiqqer/discount',
                        'exception.discount.purchase_quantity_from.wrong'
    
    Henning Leutz's avatar
    Henning Leutz committed
                    ]);
    
    Henning Leutz's avatar
    Henning Leutz committed
                }
    
    Henning Leutz's avatar
    Henning Leutz committed
                if ($purchaseQuantityUntil === false || $purchaseQuantityUntil < 0) {
                    throw new QUI\ERP\Discount\Exception([
    
    Henning Leutz's avatar
    Henning Leutz committed
                        'quiqqer/discount',
                        'exception.discount.purchase_quantity_until.wrong'
    
    Henning Leutz's avatar
    Henning Leutz committed
                    ]);
    
    Henning Leutz's avatar
    Henning Leutz committed
                if ($purchaseValueFrom === false || $purchaseValueFrom < 0) {
                    throw new QUI\ERP\Discount\Exception([
    
    Henning Leutz's avatar
    Henning Leutz committed
                        'quiqqer/discount',
                        'exception.discount.purchase_value_from.wrong'
    
    Henning Leutz's avatar
    Henning Leutz committed
                    ]);
    
    Henning Leutz's avatar
    Henning Leutz committed
                if ($purchaseValueUntil === false || $purchaseValueUntil < 0) {
                    throw new QUI\ERP\Discount\Exception([
    
    Henning Leutz's avatar
    Henning Leutz committed
                        'quiqqer/discount',
                        'exception.discount.purchase_value_until.wrong'
    
    Henning Leutz's avatar
    Henning Leutz committed
                    ]);
    
    Henning Leutz's avatar
    Henning Leutz committed
                }
    
    
                // default nulls
                $attributes = [
                    'discount',
                    'usage_type',
                    'discount_type',
                    'date_from',
                    'date_until',
                    'price_calculation_basis',
                    'purchase_quantity_from',
                    'purchase_quantity_until',
                    'purchase_value_from',
                    'purchase_value_until',
                    'areas',
                    'articles',
                    'categories',
                    'user_groups',
                    'combined',
                    'priority',
                    'scope',
                    'lastSumDiscount',
                    'lastProductDiscount',
                ];
    
                foreach ($attributes as $attribute) {
                    if ($this->getAttribute($attribute) === '') {
                        $this->setAttribute($attribute, null);
                    }
                }
    
    Henning Leutz's avatar
    Henning Leutz committed
        /**
         * @param string $key
         * @param array|bool|object|string $value
         * @return QUI\QDOM|void
         */
        public function setAttribute($key, $value)
        {
            if ($key === 'lastSumDiscount' && empty($value)) {
                $value = null;
            }
    
            if ($key === 'lastProductDiscount' && empty($value)) {
                $value = null;
            }
    
    
            if ($key === 'scope' ||
                $key === 'discount_type' ||
                $key === 'usage_type'
            ) {
                $value = (int)$value;
            }
    
    
    Henning Leutz's avatar
    Henning Leutz committed
            parent::setAttribute($key, $value);
        }
    
    
    Henning Leutz's avatar
    Henning Leutz committed
        /**
    
    Henning Leutz's avatar
    Henning Leutz committed
         * Return the discount title
         *
         * @param null|QUI\Locale $Locale - optional, locale object
    
    Henning Leutz's avatar
    Henning Leutz committed
         * @return string
         */
    
    Henning Leutz's avatar
    Henning Leutz committed
        public function getTitle($Locale = null)
    
    Henning Leutz's avatar
    Henning Leutz committed
            if (!$Locale) {
                $Locale = QUI::getLocale();
            }
    
            return $Locale->get(
    
    Henning Leutz's avatar
    Henning Leutz committed
                'quiqqer/discount',
    
    Henning Leutz's avatar
    Henning Leutz committed
                'discount.'.$this->getId().'.title'
    
    Henning Leutz's avatar
    Henning Leutz committed
            );
        }
    
        /**
         * Return the discount status
         *
         * @return boolean
         */
        public function isActive()
        {
            return $this->getAttribute('active') ? true : false;
        }
    
    Henning Leutz's avatar
    Henning Leutz committed
    
    
    Henning Leutz's avatar
    Henning Leutz committed
        /**
         * Is the discount combinable with another discount?
         *
         * @param Discount $Discount
         * @return bool
         */
        public function canCombinedWith(Discount $Discount)
        {
            $combine = $this->getAttribute('combine');
    
            if (empty($combine)) {
                return false;
            }
    
    
            $combine = \implode($combine, ',');
    
            if (!\is_array($combine)) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                return false;
            }
    
            foreach ($combine as $combineId) {
                if ($Discount->getId() == $combineId) {
                    return true;
                }
            }
    
            return false;
        }
    
        /**
         * is the user allowed to use the discount
         *
    
    Henning Leutz's avatar
    Henning Leutz committed
         * @param QUI\Interfaces\Users\User $User
    
    Henning Leutz's avatar
    Henning Leutz committed
         * @return boolean
         */
    
    Henning Leutz's avatar
    Henning Leutz committed
        public function canUsedBy(QUI\Interfaces\Users\User $User)
    
    Henning Leutz's avatar
    Henning Leutz committed
            if ($this->isActive() === false) {
                return false;
            }
    
    
            // usage definitions / limits
            $dateFrom  = $this->getAttribute('date_from');
            $dateUntil = $this->getAttribute('date_until');
    
            $now       = \time();
    
            if ($dateFrom && \strtotime($dateFrom) > $now) {
    
            if ($dateUntil && \strtotime($dateUntil) < $now) {
    
    Henning Leutz's avatar
    Henning Leutz committed
            $userGroupValue = $this->getAttribute('user_groups');
            $areasValue     = $this->getAttribute('areas');
    
            // if groups and areas are empty, everbody is allowed
            if (empty($userGroupValue) && empty($areasValue)) {
                return true;
            }
    
            // not in area
            if (!empty($areasValue) && !AreaUtils::isUserInAreas($User, $areasValue)) {
                return false;
            }
    
    
            $userGroups = QUI\Utils\UserGroups::parseUsersGroupsString(
    
    Henning Leutz's avatar
    Henning Leutz committed
                $this->getAttribute('user_groups')
            );
    
            $discountUsers  = $userGroups['users'];
            $discountGroups = $userGroups['groups'];
    
            // 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 discount usable with this product?
         *
         * @param QUI\ERP\Products\Interfaces\ProductInterface $Product
         * @return boolean
         */
        public function canUsedWith(QUI\ERP\Products\Interfaces\ProductInterface $Product)
        {
            if ($this->isActive() === false) {
                return false;
            }
    
    
            $categories = $this->getAttribute('categories');
    
            if (\is_string($articles)) {
                $articles = \explode(',', $articles);
    
            if (\is_string($categories)) {
                $categories = \explode(',', $categories);
    
    
            // article / product check
            if (empty($articles) && empty($categories)) {
                return true;
            }
    
            // article / product check
            foreach ($articles as $articleId) {
                if ((int)$Product->getId() === (int)$articleId) {
                    return true;
                }
            }
    
            // category check
    
            if (empty($categories)) {
                return true;
            }
    
            foreach ($categories as $category) {
                $productCategories = $Product->getCategories();
    
                foreach ($productCategories as $Category) {
    
                    /* @var $Category QUI\ERP\Products\Category\Category */
    
                    if ((int)$Category->getId() === (int)$category) {
                        return true;
                    }
                }
            }
    
    
            return false;
        }
    
    
    Henning Leutz's avatar
    Henning Leutz committed
        /**
         * Verify the combination between the discounts
         *
         * @param Discount $Discount
    
         * @throws QUI\ERP\Discount\Exception
    
    Henning Leutz's avatar
    Henning Leutz committed
         */
        public function verifyCombinationWith(Discount $Discount)
        {
            if ($this->canCombinedWith($Discount) === false) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                throw new QUI\ERP\Discount\Exception([
    
    Henning Leutz's avatar
    Henning Leutz committed
                    'quiqqer/discount',
                    'exception.discount.not.combinable',
    
    Henning Leutz's avatar
    Henning Leutz committed
                    [
    
                        'id'         => $this->getId(),
    
    Henning Leutz's avatar
    Henning Leutz committed
                        'discountId' => $Discount->getId()
    
    Henning Leutz's avatar
    Henning Leutz committed
                    ]
                ]);
    
    Henning Leutz's avatar
    Henning Leutz committed
            }
        }
    
        /**
         * Verify the usage of the discount by the user
         *
         * @param User $User
    
         * @throws QUI\ERP\Discount\Exception
    
    Henning Leutz's avatar
    Henning Leutz committed
         */
        public function verifyUser(User $User)
        {
            if ($this->canUsedBy($User) === false) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                throw new QUI\ERP\Discount\Exception([
    
    Henning Leutz's avatar
    Henning Leutz committed
                    'quiqqer/discount',
                    'exception.discount.user.cant.use.discount',
    
    Henning Leutz's avatar
    Henning Leutz committed
                    [
    
                        'id'     => $this->getId(),
    
    Henning Leutz's avatar
    Henning Leutz committed
                        'userId' => $User->getId()
    
    Henning Leutz's avatar
    Henning Leutz committed
                    ]
                ]);
    
    
        /**
         * Parse the discount to a price factor
         *
    
    Henning Leutz's avatar
    Henning Leutz committed
         * @param null|QUI\Locale $Locale - optional, locale object
    
    Henning Leutz's avatar
    Henning Leutz committed
         * @return QUI\ERP\Products\Interfaces\PriceFactorWithVatInterface|QUI\ERP\Products\Interfaces\PriceFactorInterface
    
    Henning Leutz's avatar
    Henning Leutz committed
        public function toPriceFactor($Locale = null)
    
        {
            switch ($this->getAttribute('discount_type')) {
    
                case QUI\ERP\Accounting\Calc::CALCULATION_PERCENTAGE:
                    $calculation = QUI\ERP\Accounting\Calc::CALCULATION_PERCENTAGE;
    
                case QUI\ERP\Accounting\Calc::CALCULATION_COMPLEMENT:
                    $calculation = QUI\ERP\Accounting\Calc::CALCULATION_COMPLEMENT;
    
                    break;
            }
    
            switch ($this->getAttribute('price_calculation_basis')) {
    
                case QUI\ERP\Accounting\Calc::CALCULATION_BASIS_NETTO:
                    $basis = QUI\ERP\Accounting\Calc::CALCULATION_BASIS_NETTO;
    
                    $basis = QUI\ERP\Accounting\Calc::CALCULATION_BASIS_CURRENTPRICE;
    
            try {
                $Plugin = QUI::getPackage('quiqqer/products');
                $Config = $Plugin->getConfig();
    
                $hideDiscounts = (int)$Config->getValue('products', 'hideDiscounts');
            } catch (QUI\Exception $Exception) {
                $hideDiscounts = false;
            }
    
            if ($this->getAttribute('scope') === Handler::DISCOUNT_SCOPE_TOTAL) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                return new PriceFactor([
    
                    'title'       => $this->getTitle($Locale),
                    'description' => '',
                    'priority'    => (int)$this->getAttribute('priority'),
                    'calculation' => $calculation,
                    'basis'       => $basis,
                    'value'       => $this->getAttribute('discount') * -1,
                    'visible'     => $hideDiscounts ? false : true,
                    'vat'         => $this->getAttribute('vat')
    
    Henning Leutz's avatar
    Henning Leutz committed
                ]);
    
    Henning Leutz's avatar
    Henning Leutz committed
            return new QUI\ERP\Products\Utils\PriceFactor([
    
    Henning Leutz's avatar
    Henning Leutz committed
                'title'       => $this->getTitle($Locale),
    
                'description' => '',
                'priority'    => (int)$this->getAttribute('priority'),
                'calculation' => $calculation,
                'basis'       => $basis,
    
                'value'       => $this->getAttribute('discount') * -1,
                'visible'     => $hideDiscounts ? false : true
    
    Henning Leutz's avatar
    Henning Leutz committed
            ]);
    
    Henning Leutz's avatar
    Henning Leutz committed
    }