[ 'class' => AccessControl::class, 'rules' => [ [ 'actions' => ['report-cron', 'report-terredepains'], 'allow' => true, 'roles' => ['?'] ], [ 'allow' => true, 'roles' => ['@'], 'matchCallback' => function ($rule, $action) { return $this->getUserModule() ->getAuthorizationChecker() ->isGrantedAsProducer($this->getUserCurrent()); } ] ], ], ]; } public function actionIndex(string $date = '', int $idOrderUpdate = 0) { $this->checkProductsPointsSale(); if(!$this->getDistributionModule()->getSolver()->validateDistributionDate($date)) { $date = ''; } $orderUpdate = null; if($idOrderUpdate) { $orderUpdate = $this->getOrderModule()->getRepository() ->findOneOrderById($idOrderUpdate); } return $this->render('index', [ 'date' => $date, 'orderUpdate' => $orderUpdate ]); } public function actionAjaxInfos($date = '') { \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; $distributionModule = $this-> getDistributionModule(); $orderModule = $this->getOrderModule(); $productModule = $this->getProductModule(); $userModule = $this->getUserModule(); $producerModule = $this->getProducerModule(); $producer = $this->getProducerCurrent(); $dateObject = DateTime::createFromFormat('Y-m-d', $date); $json = ['distribution' => [], 'products' => []]; $json['means_payment'] = MeanPayment::getAll(); $json['producer'] = $this->buildAjaxInfosResponseProducer($producer); $json['distributions'] = $this->buildAjaxInfosResponseDistributions($dateObject); $json['leave_period_dates'] = $this->buildAjaxInfosResponseLeavePeriod($producer); $json['units'] = Product::$unitsArray; if ($distributionModule->getSolver()->validateDistributionDate($date)) { $distribution = $distributionModule->createDistributionIfNotExist($date); $ordersArray = $orderModule->findOrdersByDistribution($distribution, false); $ordersArrayObject = $ordersArray; $productsArray = $productModule->findProductsByDistribution($distribution, false); $json['products'] = $this->buildAjaxInfosResponseProducts($distribution, $productsArray, $ordersArray); $json['distribution'] = $this->buildAjaxInfosResponseDistribution($distribution, $ordersArrayObject, $productsArray); $json['orders'] = $this->buildAjaxInfosResponseOrders($ordersArray, $productsArray); $json['points_sale'] = $this->buildAjaxInfosResponsePointsSale($distribution); $json['delivery_notes'] = $this->buildAjaxInfosResponseDeliveryNotes($date); $json['order_create'] = $this->buildAjaxInfosResponseOrderCreate($distribution, $productsArray); $json['users'] = $userModule->findUsers(); $json['one_distribution_week_active'] = $distributionModule->isOneDistributionWeekActive($date); $json['tiller_is_synchro'] = $this->buildAjaxInfosResponseTiller($producer, $date); $json['tiller_is_authenticated'] = $this->getOrderModule()->getTillerManager()->isAuthenticated(); $json['tiller_url_authorize_code'] = $this->getOrderModule()->getTillerManager()->getUrlAuthorizeCode(); $json['missing_subscriptions'] = $this->buildAjaxInfosResponseMissingSubscriptions($date, $distribution, $ordersArrayObject); } return $json; } public function buildAjaxInfosResponseLeavePeriod(Producer $producer) { $producerModule = $this->getProducerModule(); $leavePeriodDatesArray = []; if($producerModule->getSolver()->hasLeavePeriodDefined($producer)) { $leavePeriodStart = $producerModule->getSolver()->getLeavePeriodStartDateTime($producer); $leavePeriodEnd = $producerModule->getSolver()->getLeavePeriodEndDateTime($producer); for($date = $leavePeriodStart; $date <= $leavePeriodEnd; $date->modify('+1 day')) { $leavePeriodDatesArray[] = $date->format('Y-m-d'); } } return $leavePeriodDatesArray; } public function buildAjaxInfosResponsePointsSale(Distribution $distribution) { $producerModule = $this->getProducerModule(); $pointSaleModule = $this->getPointSaleModule(); $pointSaleDistributionModule = $this->getPointSaleDistributionModule(); $pointsSaleArray = $pointSaleModule->findPointSalesByDistributionAsArray($distribution); // @TODO : à gérer autrement foreach($pointsSaleArray as &$pointSaleArray) { $idPointSale = $pointSaleArray['id']; $pointSale = $pointSaleModule->findOnePointSaleById($idPointSale); if(!isset($pointSaleArray['pointSaleDistribution']) || !$pointSaleArray['pointSaleDistribution'] || !count($pointSaleArray['pointSaleDistribution'])) { $pointSaleDistribution = $pointSaleDistributionModule->createPointSaleDistributionIfNotExist($distribution, $pointSale); $pointSaleArray['pointSaleDistribution'] = [ [ 'id_distribution' => $pointSaleDistribution->id_distribution, 'id_point_sale' => $pointSaleDistribution->id_point_sale, 'delivery' => $pointSaleDistribution->delivery ] ]; } $pointSaleArray['credit_functioning'] = $producerModule->getPointSaleCreditFunctioning($pointSale); } return $pointsSaleArray; } public function buildAjaxInfosResponseProducts(Distribution $distribution, array $productsArray, array $ordersArray) { $distributionModule = $this-> getDistributionModule(); $orderModule = $this->getOrderModule(); $jsonProductsArray = []; foreach ($productsArray as $product) { $jsonProduct = $product->getAttributes(); $quantityOrder = $orderModule->getProductQuantity($product, $ordersArray); $jsonProduct['quantity_ordered'] = $quantityOrder; if (!isset($product->productDistribution[0])) { $productDistributionAdd = $distributionModule->addProduct($distribution, $product); if($productDistributionAdd) { $jsonProduct['productDistribution'][0] = $productDistributionAdd->getAttributes(); $product->populateRelation('productDistribution', [$productDistributionAdd]); } } else { foreach($product->productDistribution as $key => $productDistribution) { $jsonProduct['productDistribution'][$key] = $productDistribution->getAttributes(); } } if (!isset($product->productDistribution[0]) || !is_numeric($product->productDistribution[0]->quantity_max)) { $jsonProduct['quantity_remaining'] = null; } else { $jsonProduct['quantity_remaining'] = $product->productDistribution[0]->quantity_max - $quantityOrder; } $jsonProduct['quantity_form'] = 0; if ($product->taxRate) { $jsonProduct['taxRate'] = $product->taxRate->getAttributes(); } else { $jsonProduct['taxRate'] = $this->getProducerCurrent()->taxRate->getAttributes(); } $jsonProductsArray[] = $jsonProduct; } return $jsonProductsArray; } public function buildAjaxInfosResponseProducer($producer) { return [ 'credit' => $producer->credit, 'tiller' => $producer->tiller, 'option_distribution_export_orders_grid_pdf' => $producer->option_distribution_export_orders_grid_pdf ]; } public function buildAjaxInfosResponseDistributions($dateObject) { $numberOfLoadedMonthes = '3 month'; if (is_object($dateObject)) { $dateBegin = strtotime('-' . $numberOfLoadedMonthes, $dateObject->getTimestamp()); $dateEnd = strtotime('+' . $numberOfLoadedMonthes, $dateObject->getTimestamp()); } else { $dateBegin = strtotime('-' . $numberOfLoadedMonthes); $dateEnd = strtotime('+' . $numberOfLoadedMonthes); } return 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 ), ], 'as_array' => true ]); } public function buildAjaxInfosResponseDistribution(Distribution $distribution, array $ordersArray, array $productsArray) { $producerModule = $this->getProducerModule(); $productModule = $this->getProductModule(); $orderModule = $this->getOrderModule(); $distributionModule = $this-> getDistributionModule(); $distributionJsonData = [ 'id' => $distribution->id, 'active' => $distribution->active, 'exports' => $distributionModule->getExportManager()->getAjaxArray($distribution), 'url_order' => $distributionModule->getLinkOrder($distribution), 'is_leave_period' => $producerModule->getSolver()->isOnLeavePeriod($distribution->producer, DateTime::createFromFormat('Y-m-d', $distribution->date)) ]; // montant et poids des commandes $revenues = 0; $revenuesWithTax = 0; $weight = 0; if ($ordersArray) { foreach ($ordersArray as $order) { $orderModule->initOrder($order); if (is_null($order->date_delete)) { $revenues += $orderModule->getOrderAmount($order); $revenuesWithTax += $orderModule->getOrderAmountWithTax($order); $weight += $order->weight; } } } $distributionJsonData['revenues'] = Price::format($revenues); $distributionJsonData['revenues_with_tax'] = Price::format($revenuesWithTax); $distributionJsonData['weight'] = number_format($weight, 2); $distributionJsonData['potential_revenues'] = Price::format($productModule->getProductDistributionPotentialRevenues($productsArray)); $distributionJsonData['potential_revenues_with_tax'] = Price::format($productModule->getProductDistributionPotentialRevenues($productsArray, true)); $distributionJsonData['potential_weight'] = number_format($productModule->getProductDistributionPotentialWeight($productsArray), 2); return $distributionJsonData; } public function buildAjaxInfosResponseOrders(array $ordersArray, array $productsArray) { $userModule = $this->getUserModule(); $orderModule = $this->getOrderModule(); $paymentManager = $this->getPaymentModule(); $productOrderModule = $this->getProductOrderModule(); $userProducerModule = $this->getUserProducerModule(); if ($ordersArray) { foreach ($ordersArray as &$order) { $orderModule->initOrder($order); $productOrderArray = []; foreach ($order->productOrder as $productOrder) { $productOrderArray[$productOrder->id_product] = [ 'quantity' => $productOrderModule->getSolver()->getQuantityToCoefficientOfUnit($productOrder), 'unit' => $productOrder->unit, 'price' => number_format($productOrder->price, 5), 'invoice_price' => number_format($productOrder->invoice_price, 5), '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'], 5), 'price_with_tax' => Price::getPriceWithTax($product['price'], $product['taxRate']['value']), ]; } } $paymentArray = []; foreach ($order->payment as $payment) { $paymentArray[] = [ 'type' => $payment->type, 'wording_type' => $paymentManager->getStrType($payment), 'mean_payment' => $payment->mean_payment, 'wording_mean_payment' => $paymentManager->getStrMeanPayment($payment), 'date' => date('d/m/Y H:i:s', strtotime($payment->date)), 'user' => $payment->getUserObject() ? $userModule->getUsername($payment->getUserObject()) : '', 'user_action' => $paymentManager->getStrUserAction($payment), 'wording' => $paymentManager->getStrWording($payment, $order), 'amount' => $paymentManager->getAmount($payment, Order::AMOUNT_TOTAL, true), ]; } $arrayDatasUser = []; if(isset($order->user) && $order->user) { $arrayDatasUser['credit'] = $userModule->getCredit($order->user); $arrayDatasUser['credit_active'] = $userModule->getCreditActive($order->user); $userProducer = $userProducerModule->getRepository()->findOneUserProducer($order->user); $arrayDatasUser['trust_alert'] = $userProducer->trust_alert; $arrayDatasUser['trust_alert_comment'] = $userProducer->trust_alert_comment; } $oneProductUnactivated = false; foreach ($order->productOrder as $productOrder) { foreach ($productsArray as $product) { if ($productOrder->id_product == $product['id'] && isset($product['productDistribution'][0]) && !$product['productDistribution'][0]['active']) { $oneProductUnactivated = true; } } } $order = array_merge($order->getAttributes(), [ 'selected' => false, 'weight' => $order->weight, 'amount' => (float) Price::numberTwoDecimals($orderModule->getOrderAmountWithTax($order, Order::AMOUNT_TOTAL)), 'amount_paid' => (float) Price::numberTwoDecimals($orderModule->getOrderAmount($order, Order::AMOUNT_PAID)), 'amount_remaining' => Price::numberTwoDecimals($orderModule->getOrderAmount($order, Order::AMOUNT_REMAINING)), 'amount_surplus' => Price::numberTwoDecimals($orderModule->getOrderAmount($order, Order::AMOUNT_SURPLUS)), 'user' => (isset($order->user)) ? array_merge( $order->user->getAttributes(), $arrayDatasUser ) : null, 'pointSale' => $order->pointSale ? ['id' => $order->pointSale->id, 'name' => $order->pointSale->name] : null, 'productOrder' => $productOrderArray, 'paymentsArray' => $paymentArray, 'oneProductUnactivated' => $oneProductUnactivated, 'isLinkedToValidDocument' => $orderModule->isLinkedToValidDocument($order), 'isLinkedToValidInvoice' => $orderModule->isLinkedToValidInvoice($order), 'isCreditAutoPayment' => $orderModule->isCreditAutoPayment($order), 'isCreditContext' => $orderModule->isCreditContext($order), 'isPaid' => $orderModule->isOrderPaid($order), 'isPaidViaInvoice' => $orderModule->isOrderPaidViaInvoice($order), 'paymentLabelShort' => $orderModule->getPaymentLabelShort($order), 'isCreditFunctioningMandatory' => $orderModule->isOrderCreditFunctioningMandatory($order), 'isCreditFunctioningUser' => $orderModule->isOrderCreditFunctioningUser($order), 'debitCredit' => false, ]); } } return $ordersArray; } public function buildAjaxInfosResponseDeliveryNotes(string $date) { $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(); } } return $deliveryNotesByPointSaleArray; } public function buildAjaxInfosResponseOrderCreate(Distribution $distribution, array $productsArray) { $pointSaleModule = $this->getPointSaleModule(); $pointSaleDefault = $pointSaleModule->findOnePointSaleDefaultByDistribution($distribution); $productOrderArray = []; foreach ($productsArray as $product) { $productOrderArray[$product['id']] = [ 'quantity' => 0, 'unit' => $product['unit'], 'price' => number_format($product['price'], 5), 'price_with_tax' => Price::getPriceWithTax($product['price'], $product['taxRate']['value']), ]; } return [ 'id_point_sale' => $pointSaleDefault ? $pointSaleDefault->id : 0, 'id_user' => 0, 'username' => '', 'comment' => '', 'productOrder' => $productOrderArray ]; } public function buildAjaxInfosResponseTiller(Producer $producer, string $date) { return $this->getOrderModule()->getTillerManager()->isSynchronized($date); } public function buildAjaxInfosResponseMissingSubscriptions(string $date, Distribution $distribution, array $ordersArray) { $subscriptionModule = $this->getSubscriptionModule(); $missingSubscriptionsArray = []; $arraySubscriptions = $subscriptionModule->findSubscriptionsByDate($date); if ($distribution->active) { foreach ($arraySubscriptions as $subscription) { if (!$subscriptionModule->hasOrderAlreadyExist($subscription, $ordersArray) && $subscription->productSubscription && count($subscription->productSubscription) && $subscription->id_point_sale && $subscription->id_point_sale > 0) { $missingSubscriptionsArray[] = [ 'username' => $subscriptionModule->getUsername($subscription) ]; } } } return $missingSubscriptionsArray; } public function actionAjaxPointSaleFavorite($idUser, $idDistribution) { \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; $userModule = $this->getUserModule(); $orderModule = $this->getOrderModule(); $distributionModule = $this->getDistributionModule(); $user = $userModule->findOneUserById($idUser); $distribution = $distributionModule->getRepository()->findOneDistributionById($idDistribution); $idFavoritePointSale = 0; if($user) { $favoritePointSale = $orderModule->getUserFavoritePointSale($user, $distribution); 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; $distributionModule = $this-> getDistributionModule(); $orderModule = $this->getOrderModule(); $userModule = $this->getUserModule(); $pointSaleModule = $this->getPointSaleModule(); $productModule = $this->getProductModule(); $order = $orderModule->findOneOrderById($idOrder); $distribution = $distributionModule->findOneDistributionById($idDistribution); $user = $userModule->findOneUserById($idUser); $pointSale = $pointSaleModule->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 = $productModule->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, 5); } else { $invoicePrice = number_format($productOrder->price, 5); } $quantity = $productOrder->quantity; } } } $productOrderArray[$product['id']] = [ 'quantity' => $quantity, 'unit' => $product->unit, 'prices' => $priceArray, 'active' => $product->productDistribution[0]->active && (!$pointSale || $productModule->isAvailableOnPointSale($product, $pointSale)), 'invoice_price' => $invoicePrice ]; } return $productOrderArray; } public function actionAjaxUpdateInvoicePrices($idOrder) { $orderModule = $this->getOrderModule(); $userProducerModule = $this->getUserProducerModule(); $productModule = $this->getProductModule(); $order = $orderModule->findOneOrderById($idOrder); if ($order && $order->distribution->id_producer == GlobalParam::getCurrentProducerId()) { $userProducer = null; if ($order->id_user) { $userProducer = $userProducerModule->findOneUserProducer($order->user); } foreach ($order->productOrder as $productOrder) { $invoicePrice = $productModule->getPrice($productOrder->product, [ 'user' => $orderModule->getUserForInvoicing($order), '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 export pour une distribution. */ public function actionExport(string $name, string $date = '') { $distributionModule = $this-> getDistributionModule(); $distribution = $distributionModule->getRepository()->findOneDistribution($date); if ($distribution) { try { return $distributionModule->getExportManager()->getGenerator($name)->generate($distribution); } catch(ErrorException $exception) { //$this->setFlash('error', "Une erreur est survenue lors de la génération de l'export."); $this->setFlash('error', $exception->getMessage()); return $this->redirectReferer(); } } } public function actionAjaxProcessProductQuantityMax($idDistribution, $idProduct, $quantityMax) { \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; $productDistributionModule = $this->getProductDistributionModule(); $productDistribution = $this->getProductDistribution($idProduct, $idDistribution); $productDistributionModule->updateProductDistributionQuantityMax($productDistribution, (float) $quantityMax); return ['success']; } public function actionAjaxProcessActiveProduct(int $idDistribution, int $idProduct, int $active) { \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; $productDistributionModule = $this->getProductDistributionModule(); $productDistribution = $this->getProductDistribution($idProduct, $idDistribution); $productDistributionModule->updateProductDistributionActive($productDistribution, $active); return ['success']; } public function actionAjaxProcessActivePointSale(int $idDistribution, int $idPointSale, int $delivery) { \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; $distributionModule = $this-> getDistributionModule(); $pointSaleModule = $this->getPointSaleModule(); $pointSaleDistributionModule = $this->getPointSaleDistributionModule(); $pointSaleDistribution = $pointSaleDistributionModule->findOnePointSaleDistribution( $distributionModule->findOneDistributionById($idDistribution), $pointSaleModule->findOnePointSaleById($idPointSale) ); $pointSaleDistribution->delivery = $delivery; $pointSaleDistributionModule->update($pointSaleDistribution); return ['success']; } public function getProductDistribution(int $idProduct, int $idDistribution) { $distributionModule = $this-> getDistributionModule(); $productModule = $this->getProductModule(); $productDistributionModule = $this->getProductDistributionModule(); return $productDistributionModule->findOneProductDistribution( $distributionModule->findOneDistributionById($idDistribution), $productModule->findOneProductById($idProduct) ); } /** * Active/désactive un jour de distribution. */ public function actionAjaxProcessActiveDistribution(int $idDistribution = 0, string $date = '', bool $active = false) { \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; $distributionModule = $this-> getDistributionModule(); $distribution = null; if ($idDistribution) { $distribution = $distributionModule->getRepository()->findOneDistributionById($idDistribution); } if ($distributionModule->getSolver()->validateDistributionDate($date)) { $distribution = $distributionModule->getBuilder()->createDistributionIfNotExist($date); } if ($distribution) { $distributionModule->getBuilder()->activeDistribution($distribution, $active); return ['success']; } return ['error']; } /** * Change l'état d'une semaine de distribution (activé, désactivé). */ public function actionAjaxProcessActiveWeekDistribution(string $date, int $active) { \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; $this->getDistributionModule()->getBuilder()->activeDistributionsOfWeek($date, $active); return ['success']; } /** * Ajoute les commandes récurrentes pour une date donnée. */ public function actionAjaxProcessAddSubscriptions(string $date) { $ordersArray = $this->getSubscriptionModule()->getOrderManager() ->createAllOrdersFromSubscriptions($date, true); if($ordersArray && count($ordersArray)) { return Ajax::responseSuccess('Les abonnements ont bien été importés.'); } return Ajax::responseError('Aucun abonnement à importer.'); } /** * Synchronise les commandes avec la plateforme Tiller pour une date donnée. */ public function actionAjaxProcessSynchroTiller(string $date) { \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; return $this->getOrderModule()->getTillerManager()->synchronizeDistribution($date); } public function actionAjaxGenerateDeliveryNotePointSale(string $idOrders) { if (strlen($idOrders)) { $idOrders = json_decode($idOrders, true); if(is_array($idOrders)) { try { if($this->getOrderModule()->getDocumentManager()->generateDeliveryNoteForPointSale($idOrders)) { return Ajax::responseSuccess("Bon de livraison généré"); } } catch(Exception $exception) { return Ajax::responseError($exception->getMessage()); } } } return Ajax::responseError('Une erreur est survenue lors de la génération du bon de livraison.'); } public function actionAjaxGenerateDeliveryNote(int $idOrder) { $orderModule = $this->getOrderModule(); $order = $orderModule->getRepository()->findOneOrderById($idOrder); $orderModule->getDocumentManager()->generateDeliveryNoteForUser($order); return Ajax::responseSuccess('Bon de livraison généré'); } public function actionAjaxGenerateDeliveryNoteEachUser(string $idOrders) { if (strlen($idOrders)) { $idOrders = json_decode($idOrders, true); $this->getOrderModule()->getDocumentManager()->generateDeliveryNotesForUser($idOrders); return Ajax::responseSuccess('Bon(s) de livraison généré(s)'); } return Ajax::responseError('Une erreur est survenue lors de la génération du bon de livraison.'); } public function actionAjaxValidateDeliveryNotes(string $idOrders) { if (strlen($idOrders)) { $idOrders = json_decode($idOrders, true); if($this->getOrderModule()->getDocumentManager()->validateDeliveryNotes($idOrders)) { return Ajax::responseSuccess('Bon(s) de livraison validé(s)'); } } return Ajax::responseError('Une erreur est survenue lors de la validation des bons de livraison'); } }