<?php

/**
 * Copyright distrib (2018)
 *
 * contact@opendistrib.net
 *
 * Ce logiciel est un programme informatique servant à aider les producteurs
 * à distribuer leur production en circuits courts.
 *
 * Ce logiciel est régi par la licence CeCILL soumise au droit français et
 * respectant les principes de diffusion des logiciels libres. Vous pouvez
 * utiliser, modifier et/ou redistribuer ce programme sous les conditions
 * de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA
 * sur le site "http://www.cecill.info".
 *
 * En contrepartie de l'accessibilité au code source et des droits de copie,
 * de modification et de redistribution accordés par cette licence, il n'est
 * offert aux utilisateurs qu'une garantie limitée.  Pour les mêmes raisons,
 * seule une responsabilité restreinte pèse sur l'auteur du programme,  le
 * titulaire des droits patrimoniaux et les concédants successifs.
 *
 * A cet égard  l'attention de l'utilisateur est attirée sur les risques
 * associés au chargement,  à l'utilisation,  à la modification et/ou au
 * développement et à la reproduction du logiciel par l'utilisateur étant
 * donné sa spécificité de logiciel libre, qui peut le rendre complexe à
 * manipuler et qui le réserve donc à des développeurs et des professionnels
 * avertis possédant  des  connaissances  informatiques approfondies.  Les
 * utilisateurs sont donc invités à charger  et  tester  l'adéquation  du
 * logiciel à leurs besoins dans des conditions permettant d'assurer la
 * sécurité de leurs systèmes et ou de leurs données et, plus généralement,
 * à l'utiliser et l'exploiter dans les mêmes conditions de sécurité.
 *
 * Le fait que vous puissiez accéder à cet en-tête signifie que vous avez
 * pris connaissance de la licence CeCILL, et que vous en avez accepté les
 * termes.
 */

namespace backend\controllers;

use common\helpers\CSV;
use common\helpers\GlobalParam;
use common\helpers\MeanPayment;
use common\helpers\Password;
use common\helpers\Price;
use common\helpers\Tiller;
use common\logic\Distribution\Distribution\Model\Distribution;
use common\logic\Document\DeliveryNote\Model\DeliveryNote;
use common\logic\Document\Document\Model\Document;
use common\logic\Order\Order\Model\Order;
use common\logic\PointSale\PointSale\Model\PointSale;
use common\logic\Product\Product\Model\Product;
use common\logic\User\User\Model\User;
use common\logic\User\UserProducer\Model\UserProducer;
use DateTime;
use kartik\mpdf\Pdf;
use yii\filters\AccessControl;

class DistributionController extends BackendController
{
    public function behaviors()
    {
        return [
            'access' => [
                'class' => AccessControl::class,
                'rules' => [
                    [
                        'actions' => ['report-cron', 'report-terredepains'],
                        'allow' => true,
                        'roles' => ['?']
                    ],
                    [
                        'allow' => true,
                        'roles' => ['@'],
                        'matchCallback' => function ($rule, $action) {
                            $userManager = $this->getUserManager();
                            return $userManager->isCurrentAdmin() || $userManager->isCurrentProducer();
                        }
                    ]
                ],
            ],
        ];
    }

    public function actionIndex($date = '', $idOrderUpdate = 0)
    {
        $this->checkProductsPointsSale();

        $orderManager = $this->getOrderManager();

        $format = 'Y-m-d';
        $theDate = '';
        $dateObject = DateTime::createFromFormat($format, $date);

        if ($dateObject && $dateObject->format($format) === $date) {
            $theDate = $date;
        }

        $orderUpdate = null;
        if ($idOrderUpdate) {
            $orderUpdate = $orderManager->findOneOrderById($idOrderUpdate);
        }

        return $this->render('index', [
            'date' => $theDate,
            'orderUpdate' => $orderUpdate
        ]);
    }

    public function actionAjaxInfos($date = '')
    {
        \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

        $distributionManager = $this->getDistributionManager();
        $orderManager = $this->getOrderManager();
        $productManager = $this->getProductManager();
        $creditHistoryManager = $this->getCreditHistoryManager();
        $userManager = $this->getUserManager();
        $subscriptionManager = $this->getSubscriptionManager();

        $producer = $this->getProducerCurrent();

        $json = [
            'distribution' => [],
            'products' => []
        ];

        $format = 'Y-m-d';
        $dateObject = DateTime::createFromFormat($format, $date);

        $numberOfLoadedMonthes = '3 month';
        if (is_object($dateObject)) {
            $dateBegin = strtotime('-' . $numberOfLoadedMonthes, $dateObject->getTimestamp());
            $dateEnd = strtotime('+' . $numberOfLoadedMonthes, $dateObject->getTimestamp());
        } else {
            $dateBegin = strtotime('-' . $numberOfLoadedMonthes);
            $dateEnd = strtotime('+' . $numberOfLoadedMonthes);
        }

        $json['producer'] = [
            'credit' => $producer->credit,
            'tiller' => $producer->tiller,
            'option_display_export_grid' => $producer->option_display_export_grid
        ];

        $json['means_payment'] = MeanPayment::getAll();

        $distributionsArray = Distribution::searchAll([
            'active' => 1
        ], [
            'conditions' => [
                'date > :date_begin',
                'date < :date_end'
            ],
            'params' => [
                ':date_begin' => date(
                    'Y-m-d',
                    $dateBegin
                ),
                ':date_end' => date(
                    'Y-m-d',
                    $dateEnd
                ),
            ],
        ]);
        $json['distributions'] = $distributionsArray;

        if ($dateObject && $dateObject->format($format) === $date) {
            $distribution = $distributionManager->createDistributionIfNotExist($date);

            $json['distribution'] = [
                'id' => $distribution->id,
                'active' => $distribution->active,
                'url_report' => $this->getUrlManagerBackend()->createUrl(
                    ['distribution/report', 'date' => $distribution->date]
                ),
                'url_report_grid' => $this->getUrlManagerBackend()->createUrl(
                    ['distribution/report-grid', 'date' => $distribution->date]
                ),
            ];

            $ordersArray = Order::searchAll([
                'distribution.id' => $distribution->id,
            ], [
                'orderby' => 'user.lastname ASC, user.name ASC'
            ]);

            // montant et poids des commandes
            $revenues = 0;
            $weight = 0;
            if ($ordersArray) {
                foreach ($ordersArray as $order) {
                    $orderManager->initOrder($order);
                    if (is_null($order->date_delete)) {
                        $revenues += $orderManager->getOrderAmountWithTax($order);
                        $weight += $order->weight;
                    }
                }
            }
            $json['distribution']['revenues'] = Price::format($revenues);
            $json['distribution']['weight'] = number_format($weight, 2);

            // products
            $productsQuery = Product::find()
                ->orWhere(['id_producer' => GlobalParam::getCurrentProducerId(),])
                ->joinWith([
                    'taxRate',
                    'productDistribution' => function ($query) use ($distribution) {
                        $query->andOnCondition(
                            'product_distribution.id_distribution = ' . $distribution->id
                        );
                    }
                ])
                ->orderBy('product_distribution.active DESC, order ASC');

            $productsArray = $productsQuery->asArray()->all();
            $potentialRevenues = 0;
            $potentialWeight = 0;

            foreach ($productsArray as &$theProduct) {
                $productObject = $productManager->findOneProductById($theProduct['id']);
                $quantityOrder = $orderManager->getProductQuantity($productObject, $ordersArray);
                $theProduct['quantity_ordered'] = $quantityOrder;

                if (!isset($theProduct['productDistribution'][0])) {
                    $theProductObject = (object)$theProduct;
                    $theProduct['productDistribution'][0] = $distributionManager->addProduct($distribution, $productObject);
                }

                if (!is_numeric($theProduct['productDistribution'][0]['quantity_max'])) {
                    $theProduct['quantity_remaining'] = null;
                } else {
                    $theProduct['quantity_remaining'] = $theProduct['productDistribution'][0]['quantity_max'] - $quantityOrder;
                }

                $theProduct['quantity_form'] = 0;

                if ($theProduct['productDistribution'][0]['active'] && $theProduct['productDistribution'][0]['quantity_max']) {
                    $potentialRevenues += $theProduct['productDistribution'][0]['quantity_max'] * $theProduct['price'];
                    $potentialWeight += $theProduct['productDistribution'][0]['quantity_max'] * $theProduct['weight'] / 1000;
                }

                if (!isset($theProduct['taxRate'])) {
                    $theProduct['taxRate'] = $producer->taxRate;
                }
            }

            $json['distribution']['potential_revenues'] = Price::format($potentialRevenues);
            $json['distribution']['potential_weight'] = number_format($potentialWeight, 2);

            $json['products'] = $productsArray;

            // orders as array
            $ordersArrayObject = $ordersArray;
            if ($ordersArray) {
                foreach ($ordersArray as &$order) {

                    $orderManager->initOrder($order);

                    $productOrderArray = [];
                    foreach ($order->productOrder as $productOrder) {
                        $productOrderArray[$productOrder->id_product] = [
                            'quantity' => $productOrder->quantity * Product::$unitsArray[$productOrder->unit]['coefficient'],
                            'unit' => $productOrder->unit,
                            'price' => number_format($productOrder->price, 3),
                            'invoice_price' => number_format($productOrder->invoice_price, 3),
                            'price_with_tax' => Price::getPriceWithTax($productOrder->price, $productOrder->taxRate->value),
                        ];
                    }

                    foreach ($productsArray as $product) {
                        if (!isset($productOrderArray[$product['id']])) {
                            $productOrderArray[$product['id']] = [
                                'quantity' => 0,
                                'unit' => $product['unit'],
                                'price' => number_format($product['price'], 3),
                                'price_with_tax' => Price::getPriceWithTax($product['price'], $product['taxRate']['value']),
                            ];
                        }
                    }

                    $creditHistoryArray = [];

                    foreach ($order->creditHistory as $creditHistory) {
                        $creditHistoryArray[] = [
                            'date' => date('d/m/Y H:i:s', strtotime($creditHistory->date)),
                            'user' => $userManager->getUsername($creditHistory->getUserObject()),
                            'user_action' => $creditHistoryManager->getStrUserAction($creditHistory),
                            'wording' => $creditHistoryManager->getStrWording($creditHistory),
                            'debit' => ($creditHistoryManager->isTypeDebit($creditHistory) ? '-&nbsp;' . $creditHistoryManager->getAmount(
                                    $creditHistory,
                                    Order::AMOUNT_TOTAL,
                                    true
                                ) : ''),
                            'credit' => ($creditHistoryManager->isTypeCredit($creditHistory) ? '+&nbsp;' . $creditHistoryManager->getAmount(
                                    $creditHistory,
                                    Order::AMOUNT_TOTAL,
                                    true
                                ) : '')
                        ];
                    }

                    $arrayCreditUser = [];
                    if (isset($order->user) && isset($order->user->userProducer) && isset($order->user->userProducer[0])) {
                        $arrayCreditUser['credit'] = $order->user->userProducer[0]->credit;
                    }

                    $oneProductUnactivated = false;
                    foreach ($order->productOrder as $productOrder) {
                        foreach ($productsArray as $product) {
                            if ($productOrder->id_product == $product['id'] && !$product['productDistribution'][0]['active']) {
                                $oneProductUnactivated = true;
                            }
                        }
                    }

                    $order = array_merge($order->getAttributes(), [
                        'selected' => false,
                        'weight' => $order->weight,
                        'amount' => Price::numberTwoDecimals($orderManager->getOrderAmountWithTax($order, Order::AMOUNT_TOTAL)),
                        'amount_paid' => Price::numberTwoDecimals($orderManager->getOrderAmount($order, Order::AMOUNT_PAID)),
                        'amount_remaining' => Price::numberTwoDecimals($orderManager->getOrderAmount($order, Order::AMOUNT_REMAINING)),
                        'amount_surplus' => Price::numberTwoDecimals($orderManager->getOrderAmount($order, Order::AMOUNT_SURPLUS)),
                        'user' => (isset($order->user)) ? array_merge(
                            $order->user->getAttributes(),
                            $arrayCreditUser
                        ) : null,
                        'pointSale' => $order->pointSale ? ['id' => $order->pointSale->id, 'name' => $order->pointSale->name] : null,
                        'productOrder' => $productOrderArray,
                        'creditHistory' => $creditHistoryArray,
                        'oneProductUnactivated' => $oneProductUnactivated,
                        'isLinkedToValidDocument' => $orderManager->isLinkedToValidDocument($order),
                    ]);
                }
            }

            $json['orders'] = $ordersArray;

            $pointsSaleArray = PointSale::find()
                ->joinWith([
                    'pointSaleDistribution' => function ($q) use ($distribution) {
                        $q->where(['id_distribution' => $distribution->id]);
                    }
                ])
                ->where([
                    'id_producer' => $producer->id,
                ])
                ->asArray()
                ->all();

            $idPointSaleDefault = 0;
            foreach ($pointsSaleArray as $pointSale) {
                if ($pointSale['default']) {
                    $idPointSaleDefault = $pointSale['id'];
                }
            }
            $json['points_sale'] = $pointsSaleArray;

            // bons de livraison
            $deliveryNotesArray = DeliveryNote::searchAll([
                'distribution.date' => $date,
            ], [
                'join_with' => ['user AS user_delivery_note', 'orders', 'producer']
            ]);
            $deliveryNotesByPointSaleArray = [];
            foreach ($deliveryNotesArray as $deliveryNote) {
                if (isset($deliveryNote->orders[0])) {
                    $deliveryNotesByPointSaleArray[$deliveryNote->orders[0]->id_point_sale] =
                        $deliveryNote->getAttributes();
                }
            }
            $json['delivery_notes'] = $deliveryNotesByPointSaleArray;

            // order create
            $productOrderArray = [];
            foreach ($productsArray as $product) {
                $productOrderArray[$product['id']] = [
                    'quantity' => 0,
                    'unit' => $product['unit'],
                    'price' => Price::getPriceWithTax($product['price'], $product['taxRate']['value']),
                ];
            }
            $json['order_create'] = [
                'id_point_sale' => $idPointSaleDefault,
                'id_user' => 0,
                'username' => '',
                'comment' => '',
                'productOrder' => $productOrderArray
            ];

            // utilisateurs
            $usersArray = $userManager->findUsers();

            $json['users'] = $usersArray;

            // une production de la semaine activée ou non
            $oneDistributionWeekActive = false;
            $week = sprintf('%02d', date('W', strtotime($date)));
            $start = strtotime(date('Y', strtotime($date)) . 'W' . $week);
            $dateMonday = date('Y-m-d', strtotime('Monday', $start));
            $dateTuesday = date('Y-m-d', strtotime('Tuesday', $start));
            $dateWednesday = date('Y-m-d', strtotime('Wednesday', $start));
            $dateThursday = date('Y-m-d', strtotime('Thursday', $start));
            $dateFriday = date('Y-m-d', strtotime('Friday', $start));
            $dateSaturday = date('Y-m-d', strtotime('Saturday', $start));
            $dateSunday = date('Y-m-d', strtotime('Sunday', $start));

            $weekDistribution = Distribution::find()
                ->andWhere([
                    'id_producer' => GlobalParam::getCurrentProducerId(),
                    'active' => 1,
                ])
                ->andWhere([
                    'or',
                    ['date' => $dateMonday],
                    ['date' => $dateTuesday],
                    ['date' => $dateWednesday],
                    ['date' => $dateThursday],
                    ['date' => $dateFriday],
                    ['date' => $dateSaturday],
                    ['date' => $dateSunday],
                ])
                ->one();
            if ($weekDistribution) {
                $oneDistributionWeekActive = true;
            }

            $json['one_distribution_week_active'] = $oneDistributionWeekActive;

            // tiller
            if ($producer->tiller) {
                $tiller = new Tiller();
                $json['tiller_is_synchro'] = (int)$tiller->isSynchro($date);
            }

            // abonnements manquants
            $arraySubscriptions = $subscriptionManager->findSubscriptionsByDate($date);
            $json['missing_subscriptions'] = [];
            if ($distribution->active) {
                foreach ($arraySubscriptions as $subscription) {
                    if (!$subscriptionManager->hasOrderAlreadyExist($subscription, $ordersArrayObject)
                        && $subscription->productSubscription && count($subscription->productSubscription)
                        && $subscription->id_point_sale && $subscription->id_point_sale > 0) {
                        $json['missing_subscriptions'][] = [
                            'username' => $subscriptionManager->getUsername($subscription)
                        ];
                    }
                }
            }
        }

        return $json;
    }

    public function actionAjaxPointSaleFavorite($idUser)
    {
        \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
        $userManager = $this->getUserManager();
        $user = $userManager->findOneUserById($idUser);
        $favoritePointSale = $userManager->getUserFavoritePointSale($user);
        $idFavoritePointSale = 0;
        if ($favoritePointSale) {
            $idFavoritePointSale = $favoritePointSale->id;
        }

        return [
            'id_favorite_point_sale' => $idFavoritePointSale
        ];
    }

    public function actionAjaxUpdateProductOrder(
        $idDistribution,
        $idUser = false,
        $idPointSale = false,
        $idOrder = false
    )
    {
        \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

        $distributionManager = $this->getDistributionManager();
        $orderManager = $this->getOrderManager();
        $userManager = $this->getUserManager();
        $pointSaleManager = $this->getPointSaleManager();
        $productManager = $this->getProductManager();

        $order = $orderManager->findOneOrderById($idOrder);
        $distribution = $distributionManager->findOneDistributionById($idDistribution);
        $user = $userManager->findOneUserById($idUser);
        $pointSale = $pointSaleManager->findOnePointSaleById($idPointSale);

        $productsArray = Product::find()
            ->where([
                'id_producer' => GlobalParam::getCurrentProducerId(),
            ])->joinWith([
                'productPrice',
                'productDistribution' => function ($q) use ($distribution) {
                    $q->where(['id_distribution' => $distribution->id]);
                }
            ])->all();

        $productOrderArray = [];
        foreach ($productsArray as $product) {
            $priceArray = $productManager->getPriceArray($product, $user, $pointSale);

            $quantity = 0;
            $invoicePrice = null;

            if (isset($order->productOrder)) {
                foreach ($order->productOrder as $productOrder) {
                    if ($productOrder->id_product == $product['id']) {
                        if ($productOrder->invoice_price) {
                            $invoicePrice = number_format($productOrder->invoice_price, 3);
                        } else {
                            $invoicePrice = number_format($productOrder->price, 3);
                        }
                        $quantity = $productOrder->quantity;
                    }
                }
            }

            $productOrderArray[$product['id']] = [
                'quantity' => $quantity,
                'unit' => $product->unit,
                'unit_coefficient' => Product::$unitsArray[$product->unit]['coefficient'],
                'prices' => $priceArray,
                'active' => $product->productDistribution[0]->active
                    && (!$pointSale || $productManager->isAvailableOnPointSale($product, $pointSale)),
                'invoice_price' => $invoicePrice
            ];
        }

        return $productOrderArray;
    }

    public function actionAjaxUpdateInvoicePrices($idOrder)
    {
        $orderManager = $this->getOrderManager();
        $userProducerManager = $this->getUserProducerManager();
        $productManager = $this->getProductManager();

        $order = $orderManager->findOneOrderById($idOrder);

        if ($order && $order->distribution->id_producer == GlobalParam::getCurrentProducerId()) {
            $userProducer = null;
            if ($order->id_user) {
                $userProducer = $userProducerManager->findOneUserProducer($order->user, $this->getProducerCurrent());
            }
            foreach ($order->productOrder as $productOrder) {
                $invoicePrice = $productManager->getPrice($productOrder->product, [
                    'user' => $order->user ?: null,
                    'point_sale' => $order->pointSale,
                    'user_producer' => $userProducer,
                    'quantity' => $productOrder->quantity
                ]);

                if ($invoicePrice != $productOrder->price) {
                    $productOrder->invoice_price = $invoicePrice;
                } else {
                    $productOrder->invoice_price = null;
                }
                $productOrder->save();
            }
        }
    }

    /**
     * Génére un PDF récapitulatif des des commandes d'un producteur pour une
     * date donnée (Méthode appelable via CRON)
     *
     * @param string $date
     * @param boolean $save
     * @param integer $idProducer
     * @param string $key
     * @return Pdf|null
     */
    public function actionReportCron($date = '', $save = false, $idProducer = 0, $key = '')
    {
        if ($key == '64ac0bdab7e9f5e48c4d991ec5201d57') {
            $this->actionReport($date, $save, $idProducer);
        }
    }

    /**
     * Génére un PDF récapitulatif des commandes d'un producteur pour une
     * date donnée.
     *
     * @param string $date
     * @param boolean $save
     * @param integer $idProducer
     * @return Pdf|null|string
     */
    public function actionReport($date = '', $save = false, $idProducer = 0, $type = "pdf")
    {
        $productDistributionManager = $this->getProductDistributionManager();
        $producerManager = $this->getProducerManager();
        $orderManager = $this->getOrderManager();
        $productManager = $this->getProductManager();
        $pointSaleManager = $this->getPointSaleManager();

        if (!\Yii::$app->user->isGuest) {
            $idProducer = GlobalParam::getCurrentProducerId();
        }

        $ordersArray = Order::searchAll(
            [
                'distribution.date' => $date,
                'distribution.id_producer' => $idProducer
            ],
            [
                'orderby' => 'user.lastname ASC, user.name ASC, comment_point_sale ASC',
                'conditions' => 'date_delete IS NULL'
            ]
        );

        $distribution = Distribution::searchOne([
            'id_producer' => $idProducer
        ], [
            'conditions' => 'date LIKE :date',
            'params' => [':date' => $date]
        ]);

        if ($distribution) {
            $selectedProductsArray = $productDistributionManager->findProductDistributionsByDistribution($distribution);
            $pointsSaleArray = PointSale::searchAll([
                'point_sale.id_producer' => $idProducer
            ]);

            foreach ($pointsSaleArray as $pointSale) {
                $orderManager->initPointSaleOrders($pointSale, $ordersArray);
            }

            // produits
            $productsArray = Product::find()
                ->joinWith([
                    'productDistribution' => function ($q) use ($distribution) {
                        $q->where(['id_distribution' => $distribution->id]);
                    }
                ])
                ->where([
                    'id_producer' => $idProducer,
                ])
                ->orderBy('order ASC')
                ->all();

            if ($type == 'pdf') {
                $viewPdf = 'report';
                $orientationPdf = Pdf::ORIENT_PORTRAIT;
                $producer = GlobalParam::getCurrentProducer();
                if ($producer->slug == 'bourlinguepacotille') {
                    $viewPdf = 'report-bourlingue';
                    $orientationPdf = Pdf::ORIENT_LANDSCAPE;
                }

                // get your HTML raw content without any layouts or scripts
                $content = $this->renderPartial($viewPdf, [
                    'date' => $date,
                    'distribution' => $distribution,
                    'selectedProductsArray' => $selectedProductsArray,
                    'pointsSaleArray' => $pointsSaleArray,
                    'productsArray' => $productsArray,
                    'ordersArray' => $ordersArray,
                    'producer' => $producerManager->findOneProducerById($idProducer)
                ]);

                $dateStr = date('d/m/Y', strtotime($date));

                if ($save) {
                    $destination = Pdf::DEST_FILE;
                } else {
                    $destination = Pdf::DEST_BROWSER;
                }

                $pdf = new Pdf([
                    // set to use core fonts only
                    'mode' => Pdf::MODE_UTF8,
                    // A4 paper format
                    'format' => Pdf::FORMAT_A4,
                    // portrait orientation
                    'orientation' => $orientationPdf,
                    // stream to browser inline
                    'destination' => $destination,
                    'filename' => \Yii::getAlias(
                        '@app/web/pdf/Commandes-' . $date . '-' . $idProducer . '.pdf'
                    ),
                    // your html content input
                    'content' => $content,
                    // format content from your own css file if needed or use the
                    // enhanced bootstrap css built by Krajee for mPDF formatting
                    //'cssFile' => Yii::getAlias('@web/css/distribution/report.css'),
                    // any css to be embedded if required
                    'cssInline' => '
                        table {
                            border-spacing : 0px ;
                            border-collapse : collapse ;
                            width: 100% ;
                        }
                        
                        table tr th,
                        table tr td {
                            padding: 0px ;
                            margin: 0px ;
                            border: solid 1px #e0e0e0 ;
                            padding: 3px 8px ;
                            vertical-align : top;
                            page-break-inside: avoid !important;
                            color: black;
                        }

                        table tr th { 
                            font-size: 13px ;
                        }

                        table tr td { 
                            font-size: 13px ;
                        }
                    ',
                    // set mPDF properties on the fly
                    //'options' => ['title' => 'Krajee Report Title'],
                    // call mPDF methods on the fly
                    'methods' => [
                        'SetHeader' => ['Commandes du ' . $dateStr],
                        'SetFooter' => ['{PAGENO}'],
                    ]
                ]);

                // return the pdf output as per the destination setting
                return $pdf->render();
            } elseif ($type == 'csv') {
                $datas = [];

                $optionCsvExportAllProducts = $producerManager->getConfig('option_csv_export_all_products');
                $optionCsvExportByPiece = $producerManager->getConfig('option_csv_export_by_piece');

                // produits en colonne
                $productsNameArray = ['', 'Commentaire'];
                $productsIndexArray = [];
                $productsHasQuantity = [];
                $cpt = 2;
                foreach ($productsArray as $product) {
                    $productsHasQuantity[$product->id] = 0;
                    foreach (Product::$unitsArray as $unit => $dataUnit) {
                        $quantity = $orderManager->getProductQuantity($product, $ordersArray, true, $unit);
                        if ($quantity) {
                            $productsHasQuantity[$product->id] += $quantity;
                        }
                    }
                    if ($productsHasQuantity[$product->id] > 0 || $optionCsvExportAllProducts) {
                        $productName = $productManager->getNameExport($product);

                        if ($optionCsvExportByPiece) {
                            $productUnit = 'piece';
                        } else {
                            $productUnit = $product->unit;
                        }

                        $productName .= ' (' . $productManager->strUnit($productUnit, 'wording_short', true) . ')';

                        $productsNameArray[] = $productName;
                        $productsIndexArray[$product->id] = $cpt++;
                    }
                }
                $datas[] = $productsNameArray;

                // points de vente
                foreach ($pointsSaleArray as $pointSale) {
                    if (count($pointSale->orders)) {
                        // listing commandes
                        $datas[] = ['> ' . $pointSale->name];
                        foreach ($pointSale->orders as $order) {
                            $orderLine = [$orderManager->getOrderUsername($order), $orderManager->getCommentReport($order)];

                            if ($optionCsvExportByPiece) {
                                foreach ($order->productOrder as $productOrder) {
                                    $orderLine[$productsIndexArray[$productOrder->id_product]] = $orderManager->getProductQuantityPieces(
                                        $productOrder->product,
                                        [$order]
                                    );
                                }
                            } else {
                                foreach ($productsIndexArray as $idProduct => $indexProduct) {
                                    $orderLine[$indexProduct] = '';
                                }

                                foreach ($order->productOrder as $productOrder) {
                                    if (strlen($orderLine[$productsIndexArray[$productOrder->id_product]])) {
                                        $orderLine[$productsIndexArray[$productOrder->id_product]] .= ' + ';
                                    }
                                    $orderLine[$productsIndexArray[$productOrder->id_product]] .= $productOrder->quantity;
                                    if ($productOrder->product->unit != $productOrder->unit) {
                                        $orderLine[$productsIndexArray[$productOrder->id_product]] .= $productManager->strUnit(
                                            $productOrder->unit,
                                            'wording_short',
                                            true
                                        );
                                    }
                                }
                            }

                            $datas[] = $this->_lineOrderReportCSV($orderLine, $cpt);
                        }

                        // total point de vente
                        if ($optionCsvExportByPiece) {
                            $totalsPointSaleArray = $this->_totalReportPiecesCSV(
                                'Total',
                                $pointSale->orders,
                                $productsArray,
                                $productsIndexArray
                            );
                        } else {
                            $totalsPointSaleArray = $this->_totalReportCSV(
                                'Total',
                                $pointSale->orders,
                                $productsArray,
                                $productsIndexArray
                            );
                        }

                        $datas[] = $this->_lineOrderReportCSV($totalsPointSaleArray, $cpt);

                        $datas[] = [];
                    }
                }

                // global
                if ($optionCsvExportByPiece) {
                    $totalsGlobalArray = $this->_totalReportPiecesCSV(
                        '> Totaux',
                        $ordersArray,
                        $productsArray,
                        $productsIndexArray
                    );
                } else {
                    $totalsGlobalArray = $this->_totalReportCSV(
                        '> Totaux',
                        $ordersArray,
                        $productsArray,
                        $productsIndexArray
                    );
                }

                $datas[] = $this->_lineOrderReportCSV($totalsGlobalArray, $cpt);

                CSV::downloadSendHeaders('Commandes_' . $date . '.csv');
                echo CSV::array2csv($datas);
                die();
            }
        }

        return null;
    }

    public function actionReportGrid($date = '', $save = false, $idProducer = 0, $type = "pdf")
    {
        $producerManager = $this->getProducerManager();
        $productDistribution = $this->getProductDistributionManager();
        $orderManager = $this->getOrderManager();
        $productCategoryManager = $this->getProductCategoryManager();

        if (!\Yii::$app->user->isGuest) {
            $idProducer = GlobalParam::getCurrentProducerId();
        }

        $distribution = Distribution::searchOne([
            'id_producer' => $idProducer
        ], [
            'conditions' => 'date LIKE :date',
            'params' => [':date' => $date]
        ]);

        if ($distribution) {
            $ordersArray = Order::searchAll(
                [
                    'distribution.date' => $date,
                    'distribution.id_producer' => $idProducer
                ],
                [
                    'orderby' => 'user.lastname ASC, user.name ASC, comment_point_sale ASC',
                    'conditions' => 'date_delete IS NULL'
                ]
            );

            $selectedProductsArray = $productDistribution->findProductDistributionsByDistribution($distribution);
            $pointsSaleArray = PointSale::searchAll([
                'point_sale.id_producer' => $idProducer
            ]);

            foreach ($pointsSaleArray as $pointSale) {
                $orderManager->initPointSaleOrders($pointSale, $ordersArray);
            }

            $ordersByPage = 22;
            $nbPages = ceil(count($ordersArray) / $ordersByPage);
            $ordersArrayPaged = [];

            foreach ($pointsSaleArray as $pointSale) {
                $index = 0;
                $indexPage = 0;

                foreach ($pointSale->orders as $order) {
                    if (!isset($ordersArrayPaged[$pointSale->id])) {
                        $ordersArrayPaged[$pointSale->id] = [];
                    }
                    if (!isset($ordersArrayPaged[$pointSale->id][$indexPage])) {
                        $ordersArrayPaged[$pointSale->id][$indexPage] = [];
                    }
                    $ordersArrayPaged[$pointSale->id][$indexPage][] = $order;

                    $index++;

                    if ($index == $ordersByPage) {
                        $index = 0;
                        $indexPage++;
                    }
                }
            }

            // catégories
            $categoriesArray = $productCategoryManager->findProductCategories();
            array_unshift($categoriesArray, null);

            // produits
            $productsArray = Product::find()
                ->joinWith([
                    'productDistribution' => function ($q) use ($distribution) {
                        $q->where(['id_distribution' => $distribution->id]);
                    }
                ])
                ->where([
                    'id_producer' => $idProducer,
                ])
                ->orderBy('order ASC')
                ->all();


            $viewPdf = 'report-grid';
            $orientationPdf = Pdf::ORIENT_PORTRAIT;
            $producer = GlobalParam::getCurrentProducer();
            if ($producer->slug == 'bourlinguepacotille') {
                $viewPdf = 'report-bourlingue';
                $orientationPdf = Pdf::ORIENT_LANDSCAPE;
            }

            // get your HTML raw content without any layouts or scripts
            $content = $this->renderPartial($viewPdf, [
                'date' => $date,
                'distribution' => $distribution,
                'selectedProductsArray' => $selectedProductsArray,
                'pointsSaleArray' => $pointsSaleArray,
                'categoriesArray' => $categoriesArray,
                'productsArray' => $productsArray,
                'ordersArray' => $ordersArrayPaged,
                'producer' => $producerManager->findOneProducerById($idProducer)
            ]);

            $dateStr = date('d/m/Y', strtotime($date));

            if ($save) {
                $destination = Pdf::DEST_FILE;
            } else {
                $destination = Pdf::DEST_BROWSER;
            }

            $pdf = new Pdf([
                // set to use core fonts only
                'mode' => Pdf::MODE_UTF8,
                // A4 paper format
                'format' => Pdf::FORMAT_A4,
                // portrait orientation
                'orientation' => $orientationPdf,
                // stream to browser inline
                'destination' => $destination,
                'filename' => \Yii::getAlias(
                    '@app/web/pdf/Commandes-' . $date . '-' . $idProducer . '.pdf'
                ),
                // your html content input
                'content' => $content,
                // format content from your own css file if needed or use the
                // enhanced bootstrap css built by Krajee for mPDF formatting
                //'cssFile' => Yii::getAlias('@web/css/distribution/report.css'),
                // any css to be embedded if required
                'cssInline' => '
                        table {
                            border-spacing : 0px ;
                            border-collapse : collapse ;
                            width: 100% ;
                        }
                        
                        table tr th,
                        table tr td {
                            padding: 0px ;
                            margin: 0px ;
                            border: solid 1px #e0e0e0 ;
                            padding: 3px ;
                            vertical-align : top;
                            page-break-inside: avoid !important;
                        }

                        table tr th { 
                            font-size: 10px ;
                        }
                       
                        table tr td { 
                            font-size: 10px ;
                        }
                        
                        table thead tr {
                                line-height: 220px;
                                text-align:left;
                        }
                       
                        .th-user,
                         .td-nb-products {
                                /* width: 35px ; */
                                text-align: center ;
                        }
                        
                        .th-user {
                                padding: 10px ;
                        }
                        
                        .category-name {
                                font-weight: bold ;
                        }
                        
                    ',
                // set mPDF properties on the fly
                //'options' => ['title' => 'Krajee Report Title'],
                // call mPDF methods on the fly
                'methods' => [
                    'SetHeader' => ['Commandes du ' . $dateStr],
                    'SetFooter' => ['{PAGENO}'],
                ]
            ]);

            // return the pdf output as per the destination setting
            return $pdf->render();
        }
    }

    /**
     * Génère un export des commandes au format CSV à destination du Google Drive
     * de Terre de pains.
     */

    public function actionReportTerredepains($date, $key)
    {
        $producerManager = $this->getProducerManager();
        $orderManager = $this->getOrderManager();
        $productManager = $this->getProductManager();

        if ($key == 'ef572cc148c001f0180c4a624189ed30') {
            $producer = $producerManager->findOneProducerBySlug('terredepains');
            $idProducer = $producer->id;

            $ordersArray = Order::searchAll(
                [
                    'distribution.date' => $date,
                    'distribution.id_producer' => $idProducer
                ],
                [
                    'orderby' => 'user.lastname ASC, user.name ASC, comment_point_sale ASC',
                    'conditions' => 'date_delete IS NULL'
                ]
            );

            $distribution = Distribution::searchOne([
                'distribution.id_producer' => $idProducer
            ], [
                'conditions' => 'date LIKE :date',
                'params' => [
                    ':date' => $date,
                ]
            ]);

            if ($distribution) {
                $pointsSaleArray = PointSale::searchAll([
                    'point_sale.id_producer' => $idProducer
                ]);

                foreach ($pointsSaleArray as $pointSale) {
                    $orderManager->initPointSaleOrders($pointSale, $ordersArray);
                }

                // produits
                $productsArray = Product::find()
                    ->joinWith([
                        'productDistribution' => function ($q) use ($distribution) {
                            $q->where(['id_distribution' => $distribution->id]);
                        }
                    ])
                    ->where([
                        'id_producer' => $idProducer,
                    ])
                    ->orderBy('order ASC')
                    ->all();

                $datas = [];

                // produits en colonne
                $productsNameArray = [''];
                $productsIndexArray = [];
                $productsHasQuantity = [];
                $cpt = 1;
                foreach ($productsArray as $product) {
                    $theUnit = $productManager->strUnit($product->unit, 'wording_short', true);
                    $theUnit = ($theUnit == 'p.') ? '' : ' (' . $theUnit . ')';
                    $productsNameArray[] = $product->name . $theUnit;
                    $productsIndexArray[$product->id] = $cpt++;
                }
                $productsNameArray[] = 'Total';
                $datas[] = $productsNameArray;

                // global
                $totalsGlobalArray = $this->_totalReportCSV(
                    '> Totaux',
                    $ordersArray,
                    $productsArray,
                    $productsIndexArray
                );
                $datas[] = $this->_lineOrderReportCSV($totalsGlobalArray, $cpt - 1, true);

                $datas[] = [];

                // points de vente
                foreach ($pointsSaleArray as $pointSale) {
                    if (count($pointSale->orders)) {
                        // total point de vente
                        $totalsPointSaleArray = $this->_totalReportCSV(
                            '> ' . $pointSale->name,
                            $pointSale->orders,
                            $productsArray,
                            $productsIndexArray
                        );
                        $datas[] = $this->_lineOrderReportCSV($totalsPointSaleArray, $cpt - 1, true);
                    }
                }

                CSV::downloadSendHeaders('Commandes_' . $date . '.csv');
                echo CSV::array2csv($datas);
                die();
            }

            return null;
        }
    }

    public function _totalReportCSV($label, $ordersArray, $productsArray, $productsIndexArray)
    {
        $orderManager = $this->getOrderManager();
        $productManager = $this->getProductManager();

        $totalsPointSaleArray = [$label];
        foreach ($productsArray as $product) {
            foreach (Product::$unitsArray as $unit => $dataUnit) {
                $quantity = $orderManager->getProductQuantity($product, $ordersArray, false, $unit);
                if ($quantity) {
                    $index = $productsIndexArray[$product->id];
                    if (!isset($totalsPointSaleArray[$index])) {
                        $totalsPointSaleArray[$index] = '';
                    }

                    if (strlen($totalsPointSaleArray[$index])) {
                        $totalsPointSaleArray[$index] .= ' + ';
                    }

                    $totalsPointSaleArray[$index] .= $quantity;

                    if ($product->unit != $unit) {
                        $totalsPointSaleArray[$index] .= '' . $productManager->strUnit($unit, 'wording_short', true);
                    }
                }
            }
        }
        return $totalsPointSaleArray;
    }

    public function _totalReportPiecesCSV($label, $ordersArray, $productsArray, $productsIndexArray)
    {
        $orderManager = $this->getOrderManager();

        $totalsPointSaleArray = [$label];
        foreach ($productsArray as $product) {
            $quantity = 0;
            foreach (Product::$unitsArray as $unit => $dataUnit) {
                $quantityProduct = $orderManager->getProductQuantity($product, $ordersArray, false, $unit);

                if ($unit == 'piece') {
                    $quantity += $quantityProduct;
                } else {
                    if ($product->weight > 0) {
                        $quantity += ($quantityProduct * $dataUnit['coefficient']) / $product->weight;
                    }
                }
            }

            if ($quantity) {
                $index = $productsIndexArray[$product->id];
                $totalsPointSaleArray[$index] = $quantity;
            }
        }

        return $totalsPointSaleArray;
    }

    public function _lineOrderReportCSV($orderLine, $cptMax, $showTotal = false)
    {
        $line = [];
        $cptTotal = 0;

        for ($i = 0; $i <= $cptMax; $i++) {
            if (isset($orderLine[$i]) && $orderLine[$i]) {
                $line[] = $orderLine[$i];
                if (is_numeric($orderLine[$i])) {
                    $cptTotal += $orderLine[$i];
                }
            } else {
                $line[] = '';
            }
        }

        if ($cptTotal > 0 && $showTotal) {
            $line[] = $cptTotal;
        }

        return $line;
    }

    public function actionAjaxProcessProductQuantityMax($idDistribution, $idProduct, $quantityMax)
    {
        \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

        $productDistributionManager = $this->getProductDistributionManager();
        $productDistribution = $this->getProductDistribution($idProduct, $idDistribution);

        $productDistribution->quantity_max = (!$quantityMax) ? null : (float)$quantityMax;
        $productDistributionManager->saveUpdate($productDistribution);

        return ['success'];
    }

    public function actionAjaxProcessActiveProduct($idDistribution, $idProduct, $active)
    {
        \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

        $productDistributionManager = $this->getProductDistributionManager();
        $productDistribution = $this->getProductDistribution($idProduct, $idDistribution);

        $productDistribution->active = $active;
        $productDistributionManager->saveUpdate($productDistribution);

        return ['success'];
    }

    public function actionAjaxProcessActivePointSale($idDistribution, $idPointSale, $delivery)
    {
        \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

        $distributionManager = $this->getDistributionManager();
        $pointSaleManager = $this->getPointSaleManager();
        $pointSaleDistributionManager = $this->getPointSaleDistributionManager();

        $pointSaleDistribution = $pointSaleDistributionManager->findOnePointSaleDistribution(
            $distributionManager->findOneDistributionById($idDistribution),
            $pointSaleManager->findOnePointSaleById($idPointSale)
        );
        $pointSaleDistribution->delivery = $delivery;
        $pointSaleDistributionManager->saveUpdate($pointSaleDistribution);

        return ['success'];
    }

    public function getProductDistribution(int $idProduct, int $idDistribution)
    {
        $distributionManager = $this->getDistributionManager();
        $productManager = $this->getProductManager();
        $productDistributionManager = $this->getProductDistributionManager();

        return $productDistributionManager->findOneProductDistribution(
            $distributionManager->findOneDistributionById($idDistribution),
            $productManager->findOneProductById($idProduct)
        );
    }

    /**
     * Active/désactive un jour de distribution.
     *
     * @param integer $idDistribution
     * @param string $date
     * @param boolean $active
     * @return array
     */
    public function actionAjaxProcessActiveDistribution($idDistribution = 0, $date = '', $active)
    {
        \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

        $distributionManager = $this->getDistributionManager();
        $producerCurrent = $this->getProducerCurrent();

        if ($idDistribution) {
            $distribution = $distributionManager->findOneDistributionById($idDistribution);
        }

        $format = 'Y-m-d';
        $dateObject = DateTime::createFromFormat($format, $date);
        if ($dateObject && $dateObject->format($format) === $date) {
            $distribution = $distributionManager->createDistributionIfNotExist($date);
        }

        if ($distribution) {
            $distributionManager->activeDistribution($distribution, $active);
            return ['success'];
        }

        return ['error'];
    }

    /**
     * Change l'état d'une semaine de production (activé, désactivé).
     *
     * @param string $date
     * @param integer $active
     */
    public function actionAjaxProcessActiveWeekDistribution($date, $active)
    {
        \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

        $week = sprintf('%02d', date('W', strtotime($date)));
        $start = strtotime(date('Y', strtotime($date)) . 'W' . $week);
        $dateMonday = date('Y-m-d', strtotime('Monday', $start));
        $dateTuesday = date('Y-m-d', strtotime('Tuesday', $start));
        $dateWednesday = date('Y-m-d', strtotime('Wednesday', $start));
        $dateThursday = date('Y-m-d', strtotime('Thursday', $start));
        $dateFriday = date('Y-m-d', strtotime('Friday', $start));
        $dateSaturday = date('Y-m-d', strtotime('Saturday', $start));
        $dateSunday = date('Y-m-d', strtotime('Sunday', $start));

        $pointsSaleArray = PointSale::searchAll();

        $activeMonday = false;
        $activeTuesday = false;
        $activeWednesday = false;
        $activeThursday = false;
        $activeFriday = false;
        $activeSaturday = false;
        $activeSunday = false;

        foreach ($pointsSaleArray as $pointSale) {
            if ($pointSale->delivery_monday) {
                $activeMonday = true;
            }
            if ($pointSale->delivery_tuesday) {
                $activeTuesday = true;
            }
            if ($pointSale->delivery_wednesday) {
                $activeWednesday = true;
            }
            if ($pointSale->delivery_thursday) {
                $activeThursday = true;
            }
            if ($pointSale->delivery_friday) {
                $activeFriday = true;
            }
            if ($pointSale->delivery_saturday) {
                $activeSaturday = true;
            }
            if ($pointSale->delivery_sunday) {
                $activeSunday = true;
            }
        }

        if ($activeMonday || !$active) {
            $this->actionAjaxProcessActiveDistribution(0, $dateMonday, $active);
        }
        if ($activeTuesday || !$active) {
            $this->actionAjaxProcessActiveDistribution(0, $dateTuesday, $active);
        }
        if ($activeWednesday || !$active) {
            $this->actionAjaxProcessActiveDistribution(0, $dateWednesday, $active);
        }
        if ($activeThursday || !$active) {
            $this->actionAjaxProcessActiveDistribution(0, $dateThursday, $active);
        }
        if ($activeFriday || !$active) {
            $this->actionAjaxProcessActiveDistribution(0, $dateFriday, $active);
        }
        if ($activeSaturday || !$active) {
            $this->actionAjaxProcessActiveDistribution(0, $dateSaturday, $active);
        }
        if ($activeSunday || !$active) {
            $this->actionAjaxProcessActiveDistribution(0, $dateSunday, $active);
        }

        return ['success'];
    }

    /**
     * Ajoute les commandes récurrentes pour une date donnée.
     *
     * @param string $date
     */
    public function actionAjaxProcessAddSubscriptions($date)
    {
        \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
        $this->getOrderManager()->createAllOrdersFromSubscriptions($date, true);
        return ['success'];
    }

    /**
     * Synchronise les commandes avec la plateforme Tiller pour une date donnée.
     *
     * @param string $date
     */
    public function actionAjaxProcessSynchroTiller($date)
    {
        \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

        $producerManager = $this->getProducerManager();
        $productOrderManager = $this->getProductOrderManager();
        $orderManager = $this->getOrderManager();

        $return = [];
        $producerTiller = $producerManager->getConfig('tiller');

        if ($producerTiller) {
            $tiller = new Tiller();
            $isSynchro = $tiller->isSynchro($date);

            if (!$isSynchro) {
                $orders = Order::searchAll([
                    'distribution.date' => $date,
                    'order.tiller_synchronization' => 1
                ], [
                    'conditions' => 'date_delete IS NULL'
                ]);

                $strDate = date('Y-m-d\T12:i:s+0000', strtotime($date) + 1);

                if ($orders && count($orders)) {
                    foreach ($orders as $order) {
                        $orderManager->initOrder($order);
                        $lines = [];
                        foreach ($order->productOrder as $productOrder) {
                            $lines[] = [
                                'name' => $productOrder->product->name,
                                'price' => $productOrderManager->getPriceWithTax($productOrder) * 100 * $productOrder->quantity,
                                'tax' => $productOrder->taxRate->value * 100,
                                'date' => $strDate,
                                'quantity' => $productOrder->quantity
                            ];
                        }

                        $typePaymentTiller = '';
                        if ($order->mean_payment == MeanPayment::MONEY) {
                            $typePaymentTiller = 'CASH';
                        }
                        if ($order->mean_payment == MeanPayment::CREDIT_CARD
                            || $order->mean_payment == MeanPayment::CREDIT
                            || $order->mean_payment == MeanPayment::TRANSFER
                            || $order->mean_payment == MeanPayment::OTHER) {
                            $typePaymentTiller = 'CARD';
                        }
                        if ($order->mean_payment == MeanPayment::CHEQUE) {
                            $typePaymentTiller = 'BANK_CHECK';
                        }
                        if (!strlen($typePaymentTiller) || !$order->mean_payment) {
                            $typePaymentTiller = 'CASH';
                        }

                        $returnTiller = $tiller->postOrder([
                            'externalId' => $order->id,
                            'type' => 1,
                            'status' => 'IN_PROGRESS',
                            'openDate' => $strDate,
                            'closeDate' => $strDate,
                            'lines' => $lines,
                            'payments' => [
                                [
                                    'type' => $typePaymentTiller,
                                    'amount' => $orderManager->getOrderAmountWithTax(
                                            $order,
                                            Order::AMOUNT_PAID
                                        ) * 100,
                                    'status' => 'ACCEPTED',
                                    'date' => $strDate
                                ]
                            ]
                        ]);

                        $returnTillerObject = json_decode($returnTiller);
                        $order->tiller_external_id = '' . $returnTillerObject->id;
                        $order->save();

                        $return[] = $returnTiller;
                    }
                }
            }
        }

        return $return;
    }

    public function actionAjaxValidateDeliveryNotes($idOrders)
    {
        \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

        $deliveryNoteManager = $this->getDeliveryNoteManager();

        if (strlen($idOrders)) {
            $idOrders = json_decode($idOrders, true);

            if (is_array($idOrders) && count($idOrders) > 0) {
                foreach ($idOrders as $idOrder) {
                    $order = Order::searchOne([
                        'id' => (int)$idOrder
                    ]);

                    if ($order && $order->distribution->id_producer == GlobalParam::getCurrentProducerId()) {
                        $deliveryNote = DeliveryNote::searchOne([
                            'id' => (int)$order->id_delivery_note
                        ]);

                        if ($deliveryNote && $deliveryNoteManager->isStatusDraft($deliveryNote)) {
                            $deliveryNoteManager->changeStatus($deliveryNote, Document::STATUS_VALID);
                            $deliveryNoteManager->saveUpdate($deliveryNote);
                        }
                    }
                }

                return [
                    'return' => 'success',
                    'alert' => [
                        'type' => 'success',
                        'message' => 'Bon(s) de livraison validé(s)'
                    ]
                ];
            }
        }

        return [
            'return' => 'error',
            'alert' => [
                'type' => 'danger',
                'message' => 'Une erreur est survenue lors de la validation des bons de livraison'
            ]
        ];
    }

    public function actionAjaxGenerateDeliveryNoteEachUser($idOrders)
    {
        \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

        $userManager = $this->getUserManager();
        $userProducerManager = $this->getUserProducerManager();
        $orderManager = $this->getOrderManager();
        $deliveryNoteManager = $this->getDeliveryNoteManager();

        $producerCurrent = $this->getProducerCurrent();


        if (strlen($idOrders)) {
            $idOrders = json_decode($idOrders, true);

            if (is_array($idOrders) && count($idOrders) > 0) {
                foreach ($idOrders as $idOrder) {
                    $order = Order::searchOne([
                        'id' => (int)$idOrder
                    ]);

                    if ($order && $order->distribution->id_producer == GlobalParam::getCurrentProducerId() && $order->id_user) {

                        $deliveryNote = null;
                        $idDeliveryNote = $order->id_delivery_note;
                        if ($idDeliveryNote) {
                            $deliveryNote = DeliveryNote::searchOne([
                                'id' => (int)$idDeliveryNote
                            ]);
                        }

                        // on regénére le document si c'est un brouillon
                        if ($deliveryNote && $deliveryNoteManager->isStatusDraft($deliveryNote)) {
                            $deliveryNote->delete();
                            $deliveryNote = null;
                        }

                        if (!$deliveryNote) {
                            $deliveryNote = new DeliveryNote();
                            $deliveryNoteManager->initTaxCalculationMethod($deliveryNote);
                            $deliveryNote->id_producer = GlobalParam::getCurrentProducerId();
                            $deliveryNote->id_user = $order->id_user;
                            $deliveryNote->name = 'Bon de livraison ' . $orderManager->getOrderUsername($order) . ' (' . date(
                                    'd/m/Y',
                                    strtotime(
                                        $order->distribution->date
                                    )
                                ) . ')';
                            $deliveryNote->address = $userManager->getFullAddress($order->user);
                            $deliveryNote->save();
                        }

                        if ($deliveryNote) {
                            $order->id_delivery_note = $deliveryNote->id;
                            $order->save();

                            // init invoice prices
                            $user = $userManager->findOneUserById($deliveryNote->id_user);
                            $userProducer = $userProducerManager->findOneUserProducer($user, $producerCurrent);
                            $orderManager->updateOrderInvoicePrices($order, [
                                'user' => $user,
                                'user_producer' => $userProducer,
                                'point_sale' => $order->pointSale
                            ]);
                        }
                    }
                }
            }

            return [
                'return' => 'success',
                'alert' => [
                    'type' => 'success',
                    'message' => 'Bon(s) de livraison généré(s)'
                ]
            ];
        }

        return [
            'return' => 'error',
            'alert' => [
                'type' => 'danger',
                'message' => 'Une erreur est survenue lors de la génération du bon de livraison.'
            ]
        ];
    }

    public function actionAjaxGenerateDeliveryNote($idOrders)
    {
        \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

        $userManager = $this->getUserManager();
        $userProducerManager = $this->getUserProducerManager();
        $orderManager = $this->getOrderManager();
        $deliveryNoteManager = $this->getDeliveryNoteManager();

        $producerCurrent = $this->getProducerCurrent();

        if (strlen($idOrders)) {
            $idOrders = json_decode($idOrders, true);

            if (is_array($idOrders) && count($idOrders) > 0) {
                // récupération première commande pour obtenir des infos
                reset($idOrders);
                $firstOrder = Order::searchOne([
                    'id' => (int)$idOrders[key($idOrders)]
                ]);

                // deliveryNote existant
                $deliveryNote = null;
                $isUpdate = false;
                $i = 0;
                $ordersArray = Order::searchAll([
                    'id' => $idOrders,
                ]);
                do {
                    $order = $ordersArray[$i];
                    if ($order->distribution->id_producer == GlobalParam::getCurrentProducerId() && $order->id_delivery_note > 0) {
                        $deliveryNote = DeliveryNote::searchOne([
                            'id' => $order->id_delivery_note
                        ]);
                        $isUpdate = true;
                    }
                    $i++;
                } while ($deliveryNote == null && isset($ordersArray[$i]));

                if ($deliveryNote && $deliveryNote->status == Document::STATUS_VALID) {
                    return [
                        'return' => 'error',
                        'alert' => [
                            'type' => 'danger',
                            'message' => 'Vous ne pouvez pas modifier un bon de livraison déjà validé.'
                        ]
                    ];
                }

                if ($firstOrder) {
                    // génération du BL
                    if (!$deliveryNote) {
                        $deliveryNote = new DeliveryNote;
                        $deliveryNoteManager->initTaxCalculationMethod($deliveryNote);
                        $deliveryNote->name = 'Bon de livraison ' . $firstOrder->pointSale->name . ' (' . date(
                                'd/m/Y',
                                strtotime(
                                    $firstOrder->distribution->date
                                )
                            ) . ')';
                        $deliveryNote->id_producer = GlobalParam::getCurrentProducerId();

                        if ($firstOrder->pointSale->id_user) {
                            $deliveryNote->id_user = $firstOrder->pointSale->id_user;
                            $user = $userManager->findOneUserById($deliveryNote->id_user);
                            $userProducer = $userProducerManager->findOneUserProducer($user, $producerCurrent);
                        } else {
                            $user = new  User();
                            $user->type = User::TYPE_LEGAL_PERSON;
                            $user->name_legal_person = $firstOrder->pointSale->name;
                            $user->address = $firstOrder->pointSale->address;
                            $user->id_producer = 0;
                            $userManager->setPassword($user, Password::generate());
                            $userManager->generateAuthKey($user);
                            $user->email = '';
                            if (!strlen($user->email)) {
                                $user->username = 'inconnu@opendistrib.net';
                            }
                            $user->save();

                            $userProducer = new  UserProducer();
                            $userProducer->id_user = $user->id;
                            $userProducer->id_producer = GlobalParam::getCurrentProducerId();
                            $userProducer->credit = 0;
                            $userProducer->active = 1;
                            $userProducer->save();

                            $firstOrder->pointSale->id_user = $user->id;
                            $firstOrder->pointSale->save();

                            $deliveryNote->id_user = $user->id;
                        }

                        $deliveryNote->address = $userManager->getFullAddress($user);
                        $deliveryNote->save();
                    } else {
                        // réinitialisation des order.id_delivery_note
                        Order::updateAll([
                            'id_delivery_note' => null
                        ], [
                            'id_delivery_note' => $deliveryNote->id
                        ]);
                    }

                    if (!isset($user) || !$user) {
                        $user = $userManager->findOneUserById($deliveryNote->id_user);
                        $userProducer = $userProducerManager->findOneUserProducer($user, $producerCurrent);
                    }

                    // affectation du BL aux commandes
                    foreach ($idOrders as $idOrder) {
                        $order = $orderManager->findOneOrderById((int)$idOrder);
                        if ($order && $order->distribution->id_producer == GlobalParam::getCurrentProducerId()) {
                            $order->id_delivery_note = $deliveryNote->id;
                            $order->save();
                        }

                        // init invoice price
                        $order = $orderManager->findOneOrderById((int)$idOrder);
                        if ($order) {
                            $orderManager->updateOrderInvoicePrices($order,
                                [
                                    'user' => $user,
                                    'user_producer' => $userProducer,
                                    'point_sale' => $firstOrder->pointSale
                                ]);
                        }
                    }

                    return [
                        'return' => 'success',
                        'alert' => [
                            'type' => 'success',
                            'message' => 'Bon de livraison ' . ($isUpdate ? 'modifié' : 'généré')
                        ]
                    ];
                }
            }
        }

        return [
            'return' => 'error',
            'alert' => [
                'type' => 'danger',
                'message' => 'Une erreur est survenue lors de la génération du bon de livraison.'
            ]
        ];
    }

}