Skip to content
Code-Schnipsel Gruppen Projekte
Shipping.php 11,8 KiB
Newer Older
  • Learn to ignore specific revisions
  • Henning Leutz's avatar
    Henning Leutz committed
    <?php
    
    /**
     * This class contains \QUI\ERP\Shipping\Shipping
     */
    
    namespace QUI\ERP\Shipping;
    
    use QUI;
    use QUI\ERP\Shipping\Types\Factory;
    use QUI\ERP\Shipping\Api\AbstractShippingProvider;
    
    /**
     * Shipping
     *
     * @author www.pcsg.de (Henning Leutz)
     */
    class Shipping extends QUI\Utils\Singleton
    {
    
        /**
         * Product fields provided by quiqqer/shipping
         */
        const PRODUCT_FIELD_SHIPPING_TIME = 300;
    
        /**
         * Product field types provided by quiqqer/shipping
         */
        const PRODUCT_FIELD_TYPE_SHIPPING_TIME = 'shipping.ShippingTimePeriod';
    
    
        /**
         * Continue order if no rule was found
         */
        const NO_RULE_FOUND_ORDER_CONTINUE = 1;
    
        /**
         * Cancel order if no rule was found
         */
        const NO_RULE_FOUND_ORDER_CANCEL = 0;
    
    
    Henning Leutz's avatar
    Henning Leutz committed
        /**
         * @var array
         */
        protected $shipping = [];
    
    
    Henning Leutz's avatar
    Henning Leutz committed
        /**
         * @var bool
         */
        protected $debugging = null;
    
    
        /**
         * @var null
         */
        protected $shippingDisabled = null;
    
    
    Henning Leutz's avatar
    Henning Leutz committed
        /**
         * Return all available shipping provider
         *
         * @return array
         */
        public function getShippingProviders()
        {
            $cacheProvider = 'package/quiqqer/shipping/provider';
    
            try {
                $providers = QUI\Cache\Manager::get($cacheProvider);
            } catch (QUI\Cache\Exception $Exception) {
                $packages = \array_map(function ($package) {
                    return $package['name'];
                }, QUI::getPackageManager()->getInstalled());
    
                $providers = [];
    
                foreach ($packages as $package) {
                    try {
                        $Package = QUI::getPackage($package);
    
                        if ($Package->isQuiqqerPackage()) {
                            $providers = array_merge($providers, $Package->getProvider('shipping'));
                        }
                    } catch (QUI\Exception $Exception) {
                    }
                }
    
                try {
                    QUI\Cache\Manager::set($cacheProvider, $providers);
                } catch (\Exception $Exception) {
                    QUI\System\Log::writeException($Exception);
                }
            }
    
            // filter provider
            $result = [];
    
            foreach ($providers as $provider) {
    
                if (!\class_exists($provider)) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                    continue;
                }
    
                $Provider = new $provider();
    
                if (!($Provider instanceof AbstractShippingProvider)) {
                    continue;
                }
    
                $result[] = $Provider;
            }
    
            return $result;
        }
    
    
        /**
         * Is the shipping module disabled?
         *
         * @return bool
         */
        public function shippingDisabled()
        {
            if ($this->shippingDisabled !== null) {
                return $this->shippingDisabled;
            }
    
            try {
                $Config                 = QUI::getPackage('quiqqer/shipping')->getConfig();
                $this->shippingDisabled = !!$Config->getValue('shipping', 'disabled');
            } catch (QUI\Exception $Exception) {
                $this->shippingDisabled = false;
            }
    
            return $this->shippingDisabled;
        }
    
    
    Henning Leutz's avatar
    Henning Leutz committed
        /**
         * Is shipping debugging enabled?
         *
         * @return bool
         */
        public function debuggingEnabled()
        {
            if ($this->debugging !== null) {
                return $this->debugging;
            }
    
            try {
                $Config          = QUI::getPackage('quiqqer/shipping')->getConfig();
                $this->debugging = !!$Config->getValue('shipping', 'debug');
            } catch (QUI\Exception $Exception) {
                $this->debugging = false;
            }
    
            return $this->debugging;
        }
    
    
    Henning Leutz's avatar
    Henning Leutz committed
        /**
         * Return all available Shipping methods
         *
         * @return array
         */
        public function getShippingTypes()
        {
            $shipping  = [];
            $providers = $this->getShippingProviders();
    
            foreach ($providers as $Provider) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                $types = $Provider->getShippingTypes();
    
    Henning Leutz's avatar
    Henning Leutz committed
                foreach ($types as $type) {
                    if (!\class_exists($type)) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                    $ShippingType = new $type();
    
    Henning Leutz's avatar
    Henning Leutz committed
                    if ($ShippingType instanceof QUI\ERP\Shipping\Api\ShippingTypeInterface) {
                        $shipping[$ShippingType->getType()] = $ShippingType;
    
    Henning Leutz's avatar
    Henning Leutz committed
         * Return a wanted shipping type
         *
         * @param string $shippingType - type of the shipping type
         * @return QUI\ERP\Shipping\Api\ShippingTypeInterface
    
    Henning Leutz's avatar
    Henning Leutz committed
         * @throws Exception
         */
    
    Henning Leutz's avatar
    Henning Leutz committed
        public function getShippingType($shippingType)
    
    Henning Leutz's avatar
    Henning Leutz committed
            if (empty($shippingType)) {
                throw new Exception([
                    'quiqqer/shipping',
                    'exception.shipping.type.not.found',
                    ['shippingType' => '']
                ]);
            }
    
    
    Henning Leutz's avatar
    Henning Leutz committed
            $types = $this->getShippingTypes();
    
    
    Henning Leutz's avatar
    Henning Leutz committed
            /* @var $Shipping QUI\ERP\Shipping\Api\ShippingTypeInterface */
    
    Henning Leutz's avatar
    Henning Leutz committed
            foreach ($types as $Shipping) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                if ($Shipping->getType() === $shippingType) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                    return $Shipping;
                }
            }
    
            throw new Exception([
                'quiqqer/shipping',
                'exception.shipping.type.not.found',
    
    Henning Leutz's avatar
    Henning Leutz committed
                ['shippingType' => $shippingType]
    
    Henning Leutz's avatar
    Henning Leutz committed
            ]);
        }
    
        /**
         * Return a shipping
         *
         * @param int|string $shippingId - ID of the shipping type
    
         * @return QUI\ERP\Shipping\Types\ShippingEntry
    
    Henning Leutz's avatar
    Henning Leutz committed
         *
         * @throws Exception
         */
        public function getShippingEntry($shippingId)
        {
            try {
                return Factory::getInstance()->getChild($shippingId);
            } catch (QUI\Exception $Exception) {
                throw new Exception([
                    'quiqqer/shipping',
                    'exception.shipping.not.found'
                ]);
            }
        }
    
        /**
         * Return all active shipping
         *
         * @param array $queryParams
         * @return QUI\ERP\Shipping\Types\ShippingEntry[]
         */
        public function getShippingList($queryParams = [])
        {
            if (!isset($queryParams['order'])) {
                $queryParams['order'] = 'priority ASC';
            }
    
            try {
                return Factory::getInstance()->getChildren($queryParams);
            } catch (QUi\Exception $Exception) {
                return [];
            }
        }
    
        /**
         * Return all shipping entries for the user
         *
         * @param \QUI\Interfaces\Users\User|null $User - optional
    
         * @param QUI\ERP\Order\AbstractOrder $Order - optional
    
    Henning Leutz's avatar
    Henning Leutz committed
         * @return QUI\ERP\Shipping\Types\ShippingEntry[]
    
        public function getUserShipping($User = null, $Order = null)
    
    Henning Leutz's avatar
    Henning Leutz committed
        {
            if ($User === null) {
                $User = QUI::getUserBySession();
            }
    
    
            if ($Order === null) {
                return [];
            }
    
            return \array_filter($this->getShippingList(), function ($Shipping) use ($User, $Order) {
    
    Henning Leutz's avatar
    Henning Leutz committed
                /* @var $Shipping QUI\ERP\Shipping\Types\ShippingEntry */
    
                if ($Shipping->isActive() === false) {
                    return false;
                }
    
    
                return $Shipping->canUsedBy($User, $Order);
    
        /**
         * Get all valid shipping entries for an order
         *
         * @param QUI\ERP\Order\AbstractOrder $Order
         * @return QUI\ERP\Shipping\Types\ShippingEntry[]
         */
        public function getValidShippingEntriesByOrder(QUI\ERP\Order\AbstractOrder $Order)
        {
            $User = $Order->getCustomer();
    
            $userShipping = QUI\ERP\Shipping\Shipping::getInstance()->getUserShipping($User, $Order);
            $shippingList = [];
    
            foreach ($userShipping as $ShippingEntry) {
                $ShippingEntry->setOrder($Order);
    
                if ($ShippingEntry->isValid()
                    && $ShippingEntry->canUsedInOrder($Order)
                    && $ShippingEntry->canUsedBy($User, $Order)) {
                    $shippingList[] = $ShippingEntry;
                }
            }
    
            return $shippingList;
        }
    
    
        /**
         * Return the unit field ids, for the shipping rule definition
         *
         * @return array
         */
        public function getShippingRuleUnitFieldIds()
        {
            try {
                $Config = QUI::getPackage('quiqqer/shipping')->getConfig();
            } catch (QUI\Exception $Exception) {
                return [QUI\ERP\Products\Handler\Fields::FIELD_WEIGHT];
            }
    
            $ids = $Config->getValue('shipping', 'ruleFields');
    
            if (empty($ids)) {
                return [QUI\ERP\Products\Handler\Fields::FIELD_WEIGHT];
            }
    
            return \explode(',', $ids);
        }
    
    
    Henning Leutz's avatar
    Henning Leutz committed
        /**
         * @return bool|string
         */
        public function getHost()
        {
            try {
                $Project = QUI::getRewrite()->getProject();
            } catch (QUI\Exception $Exception) {
                try {
                    $Project = QUI::getProjectManager()->getStandard();
                } catch (QUI\Exception $Exception) {
                    QUI\System\Log::writeException($Exception);
    
                    return '';
                }
            }
    
            $host = $Project->getVHost(true, true);
    
            $host = \trim($host, '/');
    
    Henning Leutz's avatar
    Henning Leutz committed
    
            return $host;
        }
    
    Henning Leutz's avatar
    Henning Leutz committed
    
        /**
         * @param QUI\ERP\Order\Order|
         *      QUI\ERP\Order\OrderInProcess|
         *      QUI\ERP\Accounting\Invoice\Invoice|
         *      QUI\ERP\Accounting\Invoice\InvoiceTemporary
         * $Order
    
    Henning Leutz's avatar
    Henning Leutz committed
         *
    
         * @return QUI\ERP\Shipping\Types\ShippingEntry|QUI\ERP\Shipping\Types\ShippingUnique
    
    Henning Leutz's avatar
    Henning Leutz committed
         */
        public function getShippingByObject($Object)
        {
    
            if (!($Object instanceof QUI\ERP\Order\Order) &&
                !($Object instanceof QUI\ERP\Order\OrderInProcess) &&
                !($Object instanceof QUI\ERP\Accounting\Invoice\Invoice) &&
                !($Object instanceof QUI\ERP\Accounting\Invoice\InvoiceTemporary)
            ) {
                return null;
            }
    
    
            $Shipping = $Object->getShipping();
            $Delivery = $Object->getDeliveryAddress();
    
            if ($Delivery && $Shipping) {
    
                $Shipping->setAddress($Delivery);
    
            }
    
            return $Shipping;
    
    Henning Leutz's avatar
    Henning Leutz committed
        /**
         * @param $orderId
    
         * @return QUI\ERP\Shipping\Types\ShippingEntry|QUI\ERP\Shipping\Types\ShippingUnique
    
    Henning Leutz's avatar
    Henning Leutz committed
         */
    
    Henning Leutz's avatar
    Henning Leutz committed
        public function getShippingByOrderId($orderId)
        {
    
            try {
                $Order = QUI\ERP\Order\Handler::getInstance()->getOrderById($orderId);
            } catch (QUI\Exception $Exception) {
                return null;
            }
    
            return $this->getShippingByObject($Order);
    
    Henning Leutz's avatar
    Henning Leutz committed
    
    
        /**
         * Notify customer about an Order status change (via e-mail)
         *
         * @param QUI\ERP\Order\AbstractOrder $Order
         * @param int $statusId
         * @param string $message (optional) - Custom notification message [default: default status change message]
         * @return void
         *
         * @throws QUI\Exception
         */
        public function sendStatusChangeNotification(
            QUI\ERP\Order\AbstractOrder $Order,
            $statusId,
            $message = null
        ) {
            $Customer      = $Order->getCustomer();
            $customerEmail = $Customer->getAttribute('email');
    
            if (empty($customerEmail)) {
                QUI\System\Log::addWarning(
                    'Status change notification for order #'.$Order->getPrefixedId().' cannot be sent'
                    .' because customer #'.$Customer->getId().' has no e-mail address.'
                );
    
                return;
            }
    
            if (empty($message)) {
                $Status  = ShippingStatus\Handler::getInstance()->getShippingStatus($statusId);
                $message = $Status->getStatusChangeNotificationText($Order);
            }
    
            $Mailer = new QUI\Mail\Mailer();
            /** @var QUI\Locale $Locale */
            $Locale = $Order->getCustomer()->getLocale();
    
            $Mailer->setSubject(
                $Locale->get('quiqqer/shipping', 'shipping.status.notification.subject', [
                    'orderNo' => $Order->getPrefixedId()
                ])
            );
    
            $Mailer->setBody($message);
            $Mailer->addRecipient($customerEmail);
    
            try {
                $Mailer->send();
                $Order->addStatusMail($message);
            } catch (\Exception $Exception) {
                QUI\System\Log::writeException($Exception);
            }
        }