Skip to content
Code-Schnipsel Gruppen Projekte
Events.php 18,4 KiB
Newer Older
<?php

namespace QUI\ERP\Coupons;

use QUI;
Patrick Müller's avatar
Patrick Müller committed
use QUI\ERP\Order\AbstractOrder;
use QUI\ERP\Products\Handler\Fields;
use QUI\ERP\Products\Interfaces\ProductInterface;
use Quiqqer\Engine\Collector;
use QUI\ERP\Order\Basket\Basket;
use QUI\ERP\Order\Basket\BasketGuest;
use QUI\ERP\Coupons\Handler as CouponsHandler;
use QUI\ERP\Discount\EventHandling as DiscountEvents;
Patrick Müller's avatar
Patrick Müller committed
use QUI\ERP\Coupons\Products\CouponProductType;
use QUI\ERP\Coupons\Products\Handler as CouponProductsHandler;
use QUI\ERP\Products\Handler\Products;

/**
 * Class Events
 *
 * Global Event Handler for quiqqer/payment-paypal
 */
class Events
{
Patrick Müller's avatar
Patrick Müller committed
    /**
     * quiqqer/quiqqer: onPackageSetup
     *
     * @param QUI\Package\Package $Package
     * @return void
     */
    public static function onPackageSetup(QUI\Package\Package $Package)
    {
        try {
            self::createProductFields();
        } catch (\Exception $Exception) {
            QUI\System\Log::writeException($Exception);
        }
    }

    /**
     * Template event quiqqer/order: onQuiqqer::order::orderProcessBasketEnd
     *
     * @param Collector $Collector
     * @param BasketGuest $Basket
    public static function templateOrderProcessBasketEnd(Collector $Collector, $Basket, $Order)
        if (!($Basket instanceof Basket)
            && !($Basket instanceof QUI\ERP\Order\Basket\BasketOrder)
        ) {
        if (isset($Order) && isset($_GET['coupon'])) {
            try {
                $code = Handler::sanitizeCode($_GET['coupon']);

                $CouponCode = Handler::getCouponCodeByCode($code);
                $CouponCode->checkRedemption(QUI::getUserBySession());
                $CouponCode->addToOrder($Order);
            } catch (\Exception $Exception) {
            }
        }

        $Collector->append(
            '<div data-qui="package/quiqqer/coupons/bin/frontend/controls/CouponCodeInput"></div>'
        );
    }

    /**
     * @param QUI\ERP\Order\OrderProcess $OrderProcess
     * @throws QUI\ERP\Order\Exception
     * @throws QUI\Exception
     */
    public static function onOrderProcess(QUI\ERP\Order\OrderProcess $OrderProcess)
    {
        $CurrentStep = $OrderProcess->getCurrentStep();
        $currentStep = $CurrentStep->getType();

        if ($currentStep !== QUI\ERP\Order\Controls\OrderProcess\Basket::class) {
            return;
        }

        $coupons = QUI::getSession()->get('quiqqer-coupons');

        if (\is_string($coupons)) {
            $coupons = \json_decode($coupons, true);
        }

        if (!\is_array($coupons)) {
            $coupons = [];
        }

        if (isset($_GET['coupon'])) {
            $coupons[] = $_GET['coupon'];
        }

        $coupons = \array_unique($coupons);

        if (empty($coupons)) {
        $Order = $OrderProcess->getOrder();

        foreach ($coupons as $coupon) {
            self::addCouponToOrder($Order, $coupon);
        }
    }

    /**
     * @param QUI\ERP\Order\Basket\Basket $Basket
     * @param $pos
     */
    public static function onQuiqqerOrderBasketRemovePos(
        QUI\ERP\Order\Basket\Basket $Basket,
        $pos
    ) {
        $Order = null;
            $Order = $Basket->getOrder();
        } catch (QUI\Exception $Exception) {
            $Orders = QUI\ERP\Order\Handler::getInstance();
            try {
                $Order = $Orders->getLastOrderInProcessFromUser(QUI::getUserBySession());
            } catch (QUI\Exception $Exception) {
            }
        }
        if (!$Order) {
            QUI::getSession()->remove('quiqqer-coupons');
            return;
        }
        $Article      = $Order->getArticles()->getArticle($pos);
        $customData   = $Article->getCustomData();
        $orderCoupons = $Order->getDataEntry('quiqqer-coupons');
        $articleCouponCode = false;

        if (isset($customData['package']) && isset($customData['code'])) {
            $articleCouponCode = $customData['code'];
        }

        if (!$articleCouponCode) {
            return;
        }

        // custom data has code params, so article is an coupon code
        // we need to delete it
        if (\in_array($articleCouponCode, $orderCoupons)) {
            $pos = \array_search($articleCouponCode, $orderCoupons);
            unset($orderCoupons[$pos]);

            $Order->setData('quiqqer-coupons', $orderCoupons);

            try {
                $Order->save();
            } catch (QUI\Exception $Exception) {
            }
        }

        // look at session coupons
        // we need to delete it
        $coupons = QUI::getSession()->get('quiqqer-coupons');

        if (\is_string($coupons)) {
            $coupons = \json_decode($coupons, true);
        }

        if (!\is_array($coupons) || empty($coupons)) {
            return;
        }

        if (!\in_array($customData['code'], $coupons)) {
            return;
        }

        // remove code from session
        // because code is deleted
        $newCouponList = [];

        foreach ($coupons as $coupon) {
            if ($customData['code'] !== $coupon) {
                $newCouponList[] = $coupon;
            }
        }

        if (empty($newCouponList)) {
            QUI::getSession()->remove('quiqqer-coupons');
        } else {
            QUI::getSession()->set('quiqqer-coupons', \json_encode($newCouponList));
    /**
     * event - on price factor init
     *
     * @param $Basket
     * @param QUI\ERP\Order\AbstractOrder $Order
     * @param QUI\ERP\Products\Product\ProductList $Products
     */
    public static function onQuiqqerOrderBasketToOrder(
        $Basket,
        QUI\ERP\Order\AbstractOrder $Order,
        QUI\ERP\Products\Product\ProductList $Products
        $coupons        = $Order->getDataEntry('quiqqer-coupons');
        $sessionCoupons = QUI::getSession()->get('quiqqer-coupons');
        if (!\is_array($coupons)) {
            $coupons = [];
        if (\is_string($sessionCoupons)) {
            $sessionCoupons = \json_decode($sessionCoupons, true);

            if (\is_array($sessionCoupons)) {
                $coupons = \array_merge($coupons, $sessionCoupons);
            }

            $coupons = \array_unique($coupons);

            self::addSessionCouponsToOrder($Order, $sessionCoupons);
        $PriceFactors = $Products->getPriceFactors();
        $products     = $Products->toArray();
        $productCount = $Products->count();
        $subSum       = $products['calculations']['subSum'];
        $checkRedeemable = !$Order->isSuccessful(); // if order is successful we dont need a check
        $OrderInProcess  = $Order->getAttribute('OrderInProcess');
        $added           = false;

        if ($Order->getAttribute('inOrderCreation')) {
            $checkRedeemable = false;
        }

        if ($OrderInProcess instanceof QUI\ERP\Order\OrderInProcess
            && $OrderInProcess->getAttribute('inOrderCreation')
        ) {
            $checkRedeemable = false;
        }

        foreach ($coupons as $coupon) {
            /* @var $Coupon CouponCode */
            try {
                $Coupon = Handler::getCouponCodeByCode($coupon);
            } catch (\Exception $Exception) {
                continue;
            }

            // coupon check
            if ($checkRedeemable && !$Coupon->isRedeemable($Order->getCustomer())) {
                continue;
            }

            /* @var $Discount QUI\ERP\Discount\Discount */
            $discounts = $Coupon->getDiscounts();

            foreach ($discounts as $Discount) {
                if (!DiscountEvents::isDiscountUsableWithQuantity($Discount, $productCount)) {
                    continue;
                }

                if (!DiscountEvents::isDiscountUsableWithPurchaseValue($Discount, $subSum)) {
                    continue;
                }

                $PriceFactor = $Discount->toPriceFactor(null, $Order->getCustomer());
                $PriceFactor->setTitle(
                    QUI::getLocale()->get('quiqqer/coupons', 'coupon.discount.title', [
                        'code' => $Coupon->getCode()
                    ])
Henning Leutz's avatar
Henning Leutz committed
                $isUnique     = $Discount->getAttribute('scope') === QUI\ERP\Discount\Handler::DISCOUNT_SCOPE_UNIQUE;
                $everyProduct = $Discount->getAttribute('scope') === QUI\ERP\Discount\Handler::DISCOUNT_SCOPE_EVERY_PRODUCT;

                if ($everyProduct || $isUnique) {
                    // add to the product
Henning Leutz's avatar
Henning Leutz committed
                    $products     = $Products->getProducts();
                    $alreadyAdded = false;
Henning Leutz's avatar
Henning Leutz committed

                    foreach ($products as $Product) {
                        if ($Discount->canUsedWith($Product) === false) {
                            continue;
                        }

Henning Leutz's avatar
Henning Leutz committed
                        if ($isUnique && $alreadyAdded) {
                            continue;
                        }

                        if ($Product instanceof QUI\ERP\Products\Product\UniqueProduct) {
                            $Product->getPriceFactors()->add($PriceFactor);
Henning Leutz's avatar
Henning Leutz committed
                            $added        = true;
                            $alreadyAdded = true;
                $PriceFactors->addToEnd($PriceFactor);
            }
        }

        if ($added) {
            try {
                $Products->recalculation();
            } catch (QUI\Exception $Exception) {
                QUI\System\Log::writeDebugException($Exception);
            }

    /**
     * quiqqer/order: onQuiqqerOrderSuccessful
     *
     * Redeem coupons used in (completed) orders
     *
     * @param QUI\ERP\Order\Order|QUI\ERP\Order\OrderInProcess $Order
     * @return void
     */
    public static function onQuiqqerOrderSuccessful($Order)
    {
        $coupons = $Order->getDataEntry('quiqqer-coupons');

        foreach ($coupons as $couponCode) {
            try {
                $CouponCode = CouponsHandler::getCouponCodeByCode($couponCode);
                $CouponCode->redeem($Order->getCustomer(), $Order);
            } catch (\Exception $Exception) {
                QUI\System\Log::writeException($Exception);
            }
        }
    }

    /**
     * @param $Order
     * @param $coupons
     */
    protected static function addSessionCouponsToOrder($Order, $coupons)
    {
        if (!\is_array($coupons)) {
            return;
        }

        // coupons as article if not added
        $Articles     = $Order->getArticles();
        $isInArticles = function ($code) use ($Articles) {
            foreach ($Articles as $Article) {
                $customData = $Article->getCustomData();

                if (isset($customData['code']) && $customData['code'] === $code) {
                    return true;
                }
            }

            return false;
        };

        foreach ($coupons as $coupon) {
            if ($isInArticles($coupon) === false) {
                self::addCouponToOrder($Order, $coupon);
            }
        }
    }

    /**
     * @param $Order
     * @param $coupon
     */
    protected static function addCouponToOrder($Order, $coupon)
    {
        if (!($Order instanceof QUI\ERP\Order\OrderInProcess)) {
            return;
        }

        try {
            $code = Handler::sanitizeCode($coupon);

            $CouponCode = Handler::getCouponCodeByCode($code);
            $CouponCode->checkRedemption(QUI::getUserBySession());
Henning Leutz's avatar
Henning Leutz committed
            $CouponCode->checkOrderRedemption($Order);

            $coupons   = $Order->getDataEntry('quiqqer-coupons');
            $coupons[] = $code;

            $coupons = \array_unique($coupons);

            $Order->setData('quiqqer-coupons', $coupons);
            $Order->update();

            $CouponCode->addToOrder($Order);
        } catch (\Exception $Exception) {
        }
    }
Patrick Müller's avatar
Patrick Müller committed

    /**
     * Create all fixed product fields that quiqqer/stock-management provides
     *
     * @return void
     * @throws QUI\Exception
     */
    protected static function createProductFields()
    {
        $fields = [
Patrick Müller's avatar
Patrick Müller committed
            CouponProductType::PRODUCT_FIELD_ID_TRANSFERABLE       => [
Patrick Müller's avatar
Patrick Müller committed
                'title'    => [
                    'de' => 'Gutschein-Code ist übertragbar',
                    'en' => 'Coupon code is transferable'
                ],
                'type'     => Fields::TYPE_BOOL,
                'public'   => false,
                'standard' => false
            ],
Patrick Müller's avatar
Patrick Müller committed
            CouponProductType::PRODUCT_FIELD_ID_GENERATE_PDF       => [
Patrick Müller's avatar
Patrick Müller committed
                'title'    => [
                    'de' => 'Gutschein-Code als PDF bereitstellen',
Patrick Müller's avatar
Patrick Müller committed
                    'en' => 'Provide coupon code as PDF'
Patrick Müller's avatar
Patrick Müller committed
                ],
                'type'     => Fields::TYPE_BOOL,
                'public'   => false,
                'standard' => false
            ],
Patrick Müller's avatar
Patrick Müller committed
            CouponProductType::PRODUCT_FIELD_ID_COUPON_AMOUNT      => [
Patrick Müller's avatar
Patrick Müller committed
                'title'    => [
Patrick Müller's avatar
Patrick Müller committed
                    'de' => 'Gutschein Wert',
                    'en' => 'Coupon amount'
Patrick Müller's avatar
Patrick Müller committed
                ],
                'type'     => Fields::TYPE_FLOAT,
                'public'   => false,
                'standard' => false
Patrick Müller's avatar
Patrick Müller committed
            ],
            CouponProductType::PRODUCT_FIELD_ID_DAYS_VALID         => [
                'title'    => [
                    'de' => 'Gutschein-Code Gültigkeit (Tage)',
                    'en' => 'Coupon code validity (days)'
                ],
                'type'     => Fields::TYPE_INT,
                'public'   => false,
                'standard' => false
            ],
            CouponProductType::PRODUCT_FIELD_ID_COUPON_DESCRIPTION => [
                'title'    => [
                    'de' => 'Gutschein-Beschreibung',
                    'en' => 'Coupon description'
                ],
                'type'     => Fields::TYPE_INPUT_MULTI_LANG,
                'public'   => false,
                'standard' => false
Patrick Müller's avatar
Patrick Müller committed
            ]
        ];

        $fieldsCreated = false;

        foreach ($fields as $fieldId => $field) {
            try {
                Fields::getField($fieldId);
                continue;
            } catch (\Exception $Exception) {
                // Field does not exist -> create it
            }

            try {
                Fields::createField([
                    'id'            => $fieldId,
                    'type'          => $field['type'],
                    'titles'        => $field['title'],
                    'workingtitles' => $field['title'],
                    'systemField'   => 0,
                    'standardField' => !empty($field['standard']) ? 1 : 0,
                    'publicField'   => !empty($field['public']) ? 1 : 0,
                    'options'       => !empty($field['options']) ? $field['options'] : null
                ]);
            } catch (\Exception $Exception) {
                QUI\System\Log::writeException($Exception);
                continue;
            }

            $fieldsCreated = true;
        }

        if ($fieldsCreated) {
            QUI\Translator::publish('quiqqer/products');
        }
    }

    /**
     * Assign plan product fields to a product
     *
     * @param ProductInterface $Product
     * @return void
     */
    public static function onQuiqqerProductsProductCreate(ProductInterface $Product)
    {
        if (!($Product instanceof CouponProductType)) {
            return;
        }

        $fields = [
Patrick Müller's avatar
Patrick Müller committed
            CouponProductType::PRODUCT_FIELD_ID_TRANSFERABLE       => true,
            CouponProductType::PRODUCT_FIELD_ID_GENERATE_PDF       => true,
            CouponProductType::PRODUCT_FIELD_ID_COUPON_AMOUNT      => null,
            CouponProductType::PRODUCT_FIELD_ID_DAYS_VALID         => 1095, // 3 years
            CouponProductType::PRODUCT_FIELD_ID_COUPON_DESCRIPTION => null
Patrick Müller's avatar
Patrick Müller committed
        ];

        foreach ($fields as $fieldId => $value) {
            try {
                $Field = Fields::getField($fieldId);
                $Field->setValue($value);

                $Product->addOwnField($Field);
            } catch (\Exception $Exception) {
                QUI\System\Log::writeException($Exception);
            }
        }

        try {
            $Product->update(QUI::getUsers()->getSystemUser());
        } catch (\Exception $Exception) {
            QUI\System\Log::writeException($Exception);
        }
    }

    /**
     * quiqqer/order: onQuiqqerOrderCreated
     *
     * Parse coupon attributes from order and create coupon codes for the buyer.
     *
     * @param AbstractOrder $Order
     * @return void
     */
    public static function onQuiqqerOrderCreated(AbstractOrder $Order)
    {
Patrick Müller's avatar
Patrick Müller committed
        QUI\ERP\Coupons\Products\Handler::createCouponCodesFromOrder($Order);
Patrick Müller's avatar
Patrick Müller committed
    }
Patrick Müller's avatar
Patrick Müller committed

    public static function onQuiqqerOrderBasketToOrderBegin(
        QUI\ERP\Order\Basket\BasketOrder $BasketOrder,
        AbstractOrder $Order,
        array &$products
    ) {
        foreach ($products as $k => $product) {
            $products[$k]['vat'] = 0;
        }
    }

    /**
     * quiqqer/order: onQuiqqerOrderOrderProcessGetBodyBegin
     *
     * Set VAT to 0% for specific coupons.
     *
     * @param QUI\ERP\Order\OrderProcess $OrderProcess
     * @return void
     */
    public static function onQuiqqerOrderOrderProcessGetBodyBegin(QUI\ERP\Order\OrderProcess $OrderProcess)
    {
        try {
            $Order = $OrderProcess->getOrder();
        } catch (\Exception $Exception) {
            QUI\System\Log::writeException($Exception);
            return;
        }

        if (empty($Order)) {
            return;
        }
//
//        $OrderBasket = new QUI\ERP\Order\Basket\BasketOrder($Order->getHash());
//
//        foreach ($OrderBasket->get)

        $Articles     = $Order->getArticles();
        $articleStock = [];

        /** @var QUI\ERP\Accounting\Article $Article */
        foreach ($Articles as $Article) {
            try {
                // Do not parse coupon codes / discounts
                if (empty($Article->getId()) || !\is_numeric($Article->getId())) {
                    continue;
                }

                $Product = Products::getProduct($Article->getId());

                if ($Product instanceof CouponProductType) {
Patrick Müller's avatar
Patrick Müller committed
                    // @todo
Patrick Müller's avatar
Patrick Müller committed
                }
            } catch (\Exception $Exception) {
                QUI\System\Log::writeDebugException($Exception);
                continue;
            }
        }
    }