[ 'class' => AccessControl::class, 'rules' => [ [ 'allow' => true, 'roles' => ['@'], 'matchCallback' => function ($rule, $action) { return $this->getUserModule() ->getAuthorizationChecker() ->isGrantedAsProducer($this->getUserCurrent()); } ] ], ], ]; } public function actionGeneratePdfValidatedDocuments() { set_time_limit(0); $validatedDocumentsArray = array_merge( Quotation::find()->where(['status' => Document::STATUS_VALID])->all(), DeliveryNote::find()->where(['status' => Document::STATUS_VALID])->all(), Invoice::find()->where(['status' => Document::STATUS_VALID])->all() ); foreach ($validatedDocumentsArray as $document) { if (!file_exists($document->getFilenameComplete())) { $document->generatePdf(Pdf::DEST_FILE); } } } public function actionCreate() { $documentModule = $this->getDocumentModule(); $class = $this->getClass(); $class = 'common\\logic\\Document\\'.$class.'\\Model\\'.$class; $model = new $class(); $documentModule->initTaxCalculationMethod($model); if ($model->load(\Yii::$app->request->post())) { $model->id_producer = GlobalParam::getCurrentProducerId(); if ($model->save()) { $this->processInvoiceViaDeliveryNotes($model); $this->processInvoiceViaOrders($model); $this->setFlash('success', $this->getFlashMessage('create', $model)); return $this->redirect(['/' . $this->getControllerUrl() . '/update', 'id' => $model->id]); } else { $this->setFlash('error', 'Un problème est survenu lors de la création du document.'); } } return $this->render('/document/create', [ 'title' => $this->getTitle('Ajouter'), 'typeDocument' => $this->getDocumentType(), 'model' => $model, ]); } public function processInvoiceViaDeliveryNotes($model) { $orderModule = $this->getOrderModule(); $documentModule = $this->getDocumentModule(); $deliveryNoteModule = $this->getDeliveryNoteModule(); if ($documentModule->getClass($model) == 'Invoice') { if ($model->deliveryNotes && is_array($model->deliveryNotes) && count($model->deliveryNotes)) { foreach ($model->deliveryNotes as $key => $idDeliveryNote) { $deliveryNote = $deliveryNoteModule->findOneDeliveryNoteById($idDeliveryNote); $orderModule->assignAllOrdersInvoiceByDeliveryNote($model, $deliveryNote); } } } } public function processInvoiceViaOrders($model) { $orderModule = $this->getOrderModule(); $documentModule = $this->getDocumentModule(); if ($documentModule->getClass($model) == 'Invoice') { if ($model->ordersOnCreate && is_array($model->ordersOnCreate) && count($model->ordersOnCreate)) { foreach ($model->ordersOnCreate as $key => $idOrder) { $order = $orderModule->findOneOrderById($idOrder); $orderModule->updateOrderInvoice($order, $model); } } } } public function actionUpdate($id) { $documentModule = $this->getDocumentModule(); $paymentManager = $this->getPaymentModule(); $document = $this->findModel($id); if (!$document) { throw new yii\web\NotFoundHttpException('Le document n\'a pas été trouvé.'); } if ($document && $document->load(\Yii::$app->request->post()) && $document->save()) { $this->setFlash('success', $this->getFlashMessage('update', $document)); } $payment = null; if($documentModule->isDocumentInvoice($document) && $documentModule->isStatusValid($document)) { $payment = $paymentManager->instanciatePayment( Payment::TYPE_PAYMENT, number_format($documentModule->getAmountWithTax($document, Order::INVOICE_AMOUNT_TOTAL), 2), $this->getProducerCurrent(), null, null, MeanPayment::TRANSFER, null, null, $document ); $payment->amount = number_format($payment->amount, 2); $posts = \Yii::$app->request->post(); if(isset($posts['Payment']['date_transaction']) && $posts['Payment']['date_transaction']) { $posts['Payment']['date_transaction'] = date('Y-m-d', strtotime(str_replace('/', '-', $posts['Payment']['date_transaction']))); } if ($payment->load($posts) && $payment->save()) { $this->setFlash('success', 'Le règlement a bien été ajouté.'); return $this->redirect(['invoice/update', 'id' => $document->id]); } else { if($payment->date_transaction) { $payment->date_transaction = date('d/m/Y', strtotime($payment->date_transaction)); } } } return $this->render('/document/update', [ 'title' => $this->getTitle('Modifier'), 'typeDocument' => $this->getDocumentType(), 'model' => $document, 'payment' => $payment ]); } public function actionDelete($id) { $documentModule = $this->getDocumentModule(); $model = $this->findModel($id); if ($documentModule->isStatusValid($model)) { throw new UserException('Vous ne pouvez pas supprimer un document validé.'); } $documentModule->delete($model); if ($this->getClass() == 'DeliveryNote') { Order::updateAll([ 'order.id_delivery_note' => null ], [ 'order.id_delivery_note' => $id ]); } if ($this->getClass() == 'Quotation') { Order::updateAll([ 'order.id_quotation' => null ], [ 'order.id_quotation' => $id ]); } if ($this->getClass() == 'Invoice') { Order::updateAll([ 'order.id_invoice' => null ], [ 'order.id_invoice' => $id ]); } $this->setFlash('success', $this->getFlashMessage('delete', $model)); $this->redirect([$this->getControllerUrl() . '/index']); } public function actionExportCsvEvoliz(int $id) { $documentModule = $this->getDocumentModule(); $productOrderModule = $this->getProductOrderModule(); $datas = []; $document = $this->findModel($id); // données $datas[] = [ 'N° facture externe *', 'Date facture *', 'Client', 'Code client *', 'Total TVA', 'Total HT', 'Total TTC', 'Total réglé', 'Etat', 'Date Etat', 'Date de création', 'Objet', 'Date d\'échéance', 'Date d\'exécution', 'Taux de pénalité', 'Frais de recouvrement', 'Taux d\'escompte', 'Conditions de règlement *', 'Mode de paiement', 'Remise globale', 'Acompte', 'Nombre de relance', 'Commentaires', 'N° facture', 'Annulé', 'Catalogue', 'Réf.', 'Désignation *', 'Qté *', 'Unité', 'PU HT *', 'Remise', 'TVA', 'Total TVA', 'Total HT', 'Classification vente', 'Code Classification vente', ]; foreach ($documentModule->getProductsOrders($document, true) as $productOrderArray) { foreach ($productOrderArray as $productOrder) { $price = $productOrder->getPrice(); if ($documentModule->isInvoicePrice($document) && $productOrder->getInvoicePrice()) { $price = $productOrder->getInvoicePrice(); } $typeTotal = $documentModule->isInvoicePrice($document) ? Order::INVOICE_AMOUNT_TOTAL : Order::AMOUNT_TOTAL; $priceTotal = $productOrderModule->getPriceByTypeTotal($productOrder, $typeTotal) * $productOrder->quantity; $tva = Price::getVat( $priceTotal, $productOrder->taxRate->value, $document->tax_calculation_method ); $datas[] = [ $document->reference, // N° facture externe * date('d/m/Y', strtotime($document->date)), // Date facture * '', // Client $document->user->evoliz_code, // Code client * '', // Total TVA '', // Total HT '', // Total TTC '', // Total réglé '', // Etat '', // Date Etat '', // Date de création $document->name, // Objet '', // Date d'échéance '', // Date d'exécution '', // Taux de pénalité '', // Frais de recouvrement '', // Taux d\'escompte 'A réception', // Conditions de règlement * '', // Mode de paiement '', // Remise globale '', // Acompte '', // Nombre de relance '', // Commentaires '', // N° facture '', // Annulé 'Non', // Catalogue '', // Réf. $productOrder->product->name, // Désignation * $productOrder->quantity, // Qté * '', // Product::strUnit($productOrder->unit, 'wording'), // Unité $price, // PU HT * '', // Remise $productOrder->taxRate->value * 100, // TVA $tva, // Total TVA $priceTotal, // Total HT '', // Classification vente '01', // Code Classification vente ]; } } // nom fichier $reference = $document->id; if ($document->reference && strlen($document->reference)) { $reference = $document->reference; } // status $status = ''; if ($documentModule->isStatusDraft($document)) { $status = 'brouillon_'; } CSV::downloadSendHeaders(strtolower($this->getDocumentType()) . '_' . $status . $reference . '.csv'); echo CSV::array2csv($datas); die(); } public function actionDownload($id) { $documentModule = $this->getDocumentModule(); $document = $this->findModel($id); return $documentModule->downloadPdf($document); } public function actionRegenerate($id) { $documentModule = $this->getDocumentModule(); $document = $this->findModel($id); $documentModule->downloadPdf($document, true); $this->setFlash('success', 'Le document PDF a bien été regénéré.'); return $this->redirect([$this->getControllerUrl() . '/update', 'id' => $id]); } public function actionSend(int $id, $backUpdateForm = false) { $documentModule = $this->getDocumentModule(); $document = $this->findModel($id); if ($documentModule->sendDocument($document)) { $this->setFlash('success', $this->getFlashMessage('send', $document)); } else { $this->setFlash('danger', $this->getFlashMessage('send', $document)); } if ($backUpdateForm) { return $this->redirect([$this->getControllerUrl() . '/update', 'id' => $id]); } else { return $this->redirectReferer(); } } public function actionAjaxUserInfos($typeAction, $idUser, $classDocument, $idDocument = false) { $userModule = $this->getUserModule(); $documentModule = $this->getDocumentModule(); $orderModule = $this->getOrderModule(); $producerModule = $this->getProducerModule(); $producerCurrent = $this->getProducerCurrent(); \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; if ($idUser > 0) { $user = $userModule->findOneUserById($idUser); if ($user) { $document = null; if ($documentModule->isValidClass($classDocument) && $idDocument) { $document = $this->findModel($idDocument, $classDocument); } if ($document && $document->id_user == $user->id) { $address = $document->address; } else { $address = $userModule->getFullAddress($user); } $json = [ 'return' => 'success', 'address' => $address ]; if ($classDocument == 'Invoice') { $options = [ 'orderby' => 'distribution.date ASC', 'join_with' => ['user AS user_delivery_note', 'orders', 'producer'] ]; $deliveryNotesCreateArray = DeliveryNote::searchAll([ 'id_user' => $user->id, 'status' => Document::STATUS_VALID, 'ignore_when_invoicing' => null ], $options); $deliveryNotesUpdateArray = DeliveryNote::searchAll([ 'id_user' => $user->id, 'status' => Document::STATUS_VALID, 'order.id_invoice' => $idDocument, 'ignore_when_invoicing' => null ], $options); $json['delivery_note_create_array'] = $this->initDeliveryNoteArray('create', $deliveryNotesCreateArray); $json['delivery_note_update_array'] = $this->initDeliveryNoteArray('update', $deliveryNotesUpdateArray); $json['orders_create_array'] = []; $json['orders_update_array'] = []; if(!$producerModule->getConfig('option_invoice_only_based_on_delivery_notes')) { $json['orders_create_array'] = $this->initOrdersArray($orderModule->findOrdersByUserNotInvoiced($user)); $json['orders_update_array'] = $document ? $this->initOrdersArray($orderModule->findOrdersByUserAndInvoice($user, $document)) : []; } } if ($classDocument == 'DeliveryNote') { $json['orders_create_array'] = $this->initOrdersArray($orderModule->findOrdersByUserNotLinkedDeliveryNote($user)); $json['orders_update_array'] = $document ? $this->initOrdersArray($orderModule->findOrdersByUserAndDeliveryNote($user, $document)) : []; } return $json; } } return ['return' => 'error']; } public function initOrdersArray(array $ordersArray) { $orderModule = $this->getOrderModule(); $ordersReturnArray = []; foreach($ordersArray as &$order) { $orderModule->initOrder($order); $ordersReturnArray[] = [ 'id' => $order->id, 'date' => $order->distribution->date, 'name' => date('d/m/Y', strtotime($order->distribution->date)), 'amount_with_tax' => $orderModule->getOrderAmountWithTax($order, Order::INVOICE_AMOUNT_TOTAL) ]; } return $ordersReturnArray; } public function initDeliveryNoteArray($type, $deliveryNoteArrayResults) { $deliveryNoteArray = []; $isCreate = false; if ($type == 'create') { $isCreate = true; } if ($deliveryNoteArrayResults) { foreach ($deliveryNoteArrayResults as $deliveryNote) { $deliveryNoteData = $this->addDeliveryNoteToArray($deliveryNote, $isCreate); if ($deliveryNoteData) { $deliveryNoteArray[] = $deliveryNoteData; } } } return $deliveryNoteArray; } public function addDeliveryNoteToArray($deliveryNote, $isCreate = true) { $deliveryNoteModule = $this->getDeliveryNoteModule(); $deliveryNoteData = array_merge( $deliveryNote->getAttributes(), [ 'url' => $this->getUrlManagerBackend()->createUrl(['delivery-note/update', 'id' => $deliveryNote->id]), 'total' => $deliveryNoteModule->getAmountWithTax($deliveryNote, Order::INVOICE_AMOUNT_TOTAL) ] ); if (($isCreate && !$deliveryNoteModule->isInvoiced($deliveryNote)) || !$isCreate) { return $deliveryNoteData; } return false; } public function actionValidate($id, $backUpdateForm = false) { $documentModule = $this->getDocumentModule(); $classDocument = $this->getClass(); if ($id > 0 && $documentModule->isValidClass($classDocument)) { $document = $this->findModel($id); if ($document) { $documentModule->getManager()->validateDocument($document); // @TODO : gérer via un événement $documentModule->generatePdf($document, Pdf::DEST_FILE); $this->setFlash('success', $this->getFlashMessage('validate', $document)); if ($backUpdateForm) { return $this->redirect([$this->getControllerUrl() . '/update', 'id' => $id]); } else { return $this->redirect([$this->getControllerUrl() . '/index']); } } } $this->setFlash('danger', 'Une erreur est survenue lors de la validation du document.'); return $this->redirect([$this->getControllerUrl() . '/index']); } public function actionAjaxInit($idDocument, $classDocument) { \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; $orderModule = $this->getOrderModule(); $productModule = $this->getProductModule(); $documentModule = $this->getDocumentModule(); $deliveryNoteModule = $this->getDeliveryNoteModule(); $userProducerModule = $this->getUserProducerModule(); $pointSaleModule = $this->getPointSaleModule(); if ($idDocument > 0 && $documentModule->isValidClass($classDocument)) { $document = $this->findModel($idDocument, $classDocument); if ($document) { $ordersArray = []; $productsArray = $productModule->findProducts(false); foreach ($document->orders as $order) { $orderModule->initOrder($order); $productsOrderArray = []; foreach ($order->productOrder as $productOrder) { $productsOrderArray[$productOrder->id] = array_merge($productOrder->getAttributes(), [ 'url_product' => $this->getUrlManagerBackend()->createUrl(['product/update', 'id' => $productOrder->id_product]), 'url_order' => $this->getUrlManagerBackend()->createUrl(['distribution/index', 'idOrderUpdate' => $productOrder->id_order]) ]); } $ordersArray[$order->id] = array_merge( $order->getAttributes(), [ 'username' => $orderModule->getOrderUsername($order), 'distribution_date' => isset($order->distribution) ? date( 'd/m/Y', strtotime( $order->distribution->date ) ) : null, 'point_sale_name' => isset($order->pointSale) ? $order->pointSale->name : null, 'productOrder' => $productsOrderArray, ] ); } $userProducer = $userProducerModule->findOneUserProducer($document->user); $pointSale = $pointSaleModule->findOnePointSaleByIdUser($document->user->id); $productsArray = yii\helpers\ArrayHelper::map( $productsArray, 'order', function ($product) use ($document, $userProducer, $pointSale, $productModule) { return array_merge($product->getAttributes(), [ 'unit_coefficient' => $productModule->getSolver()->getUnitCoefficient($product), 'prices' => $productModule->getPriceArray($product, $userProducer->user, $pointSale), 'wording_unit' => $product->wording_unit, 'tax_rate' => $product->taxRate->value ]); } ); return [ 'return' => 'success', 'tax_rate_producer' => GlobalParam::getCurrentProducer()->taxRate->value, 'document' => array_merge($document->getAttributes(), [ 'html_label' => $documentModule->getHtmlLabel($document), 'class' => $documentModule->getClass($document) ]), 'id_user' => $document->user->id, 'products' => $productsArray, 'orders' => $ordersArray, 'total' => ($documentModule->getClass($document) == 'Invoice' || $documentModule->getClass($document) == 'DeliveryNote') ? $documentModule->getAmount( $document, Order::INVOICE_AMOUNT_TOTAL ) : $documentModule->getAmount($document, Order::AMOUNT_TOTAL), 'total_with_tax' => ($documentModule->getClass($document) == 'Invoice' || $documentModule->getClass($document) == 'DeliveryNote') ? $documentModule->getAmountWithTax( $document, Order::INVOICE_AMOUNT_TOTAL ) : $documentModule->getAmountWithTax($document, Order::AMOUNT_TOTAL), 'invoice_url' => ($documentModule->getClass($document) == 'DeliveryNote' && $deliveryNoteModule->getInvoice($document)) ? $this->getUrlManagerBackend()->createUrl(['invoice/update', 'id' => $deliveryNoteModule->getInvoice($document)->id]) : null ]; } } return ['return' => 'error']; } public function actionAjaxAddProduct($idDocument, $classDocument, $idProduct, $quantity, $price) { $documentModule = $this->getDocumentModule(); $productModule = $this->getProductModule(); if ($documentModule->isValidClass($classDocument)) { $document = $this->findModel($idDocument, $classDocument); $classDocumentComplete = $documentModule->getClass($document, true); $product = $productModule->findOneProductById($idProduct); if ($document && $product) { if (count($document->orders) == 0) { $order = new Order; $order->id_user = $document->id_user; $order->id_point_sale = null; $order->id_distribution = null; $order->status = 'tmp-order'; $order->origin = Order::ORIGIN_ADMIN; $order->date = date('Y-m-d H:i:s'); $fieldIdDocument = 'id_' . $classDocumentComplete::tableName(); $order->$fieldIdDocument = $document->id; $order->save(); } else { $order = $document->orders[0]; } if ($order) { $productOrder = new ProductOrder(); $productOrder->id_order = $order->id; $productOrder->id_product = $idProduct; $quantity = $quantity / Product::$unitsArray[$product->unit]['coefficient']; $productOrder->quantity = $quantity; $productOrder->price = (float)$price; $productOrder->unit = $product->unit; $productOrder->step = $product->step; $productOrder->id_tax_rate = $product->taxRate->id; $productOrder->save(); return Ajax::responseSuccess('Produit ajouté'); } } } return Ajax::responseError('Une erreur est survenue lors de la suppression du produit.'); } public function actionAjaxDeleteProductOrder($idProductOrder) { $productOrderModule = $this->getProductOrderModule(); $productOrder = $productOrderModule->findOneProductOrderById($idProductOrder); if ($productOrder) { $productOrderModule->delete($productOrder); return Ajax::responseSuccess('Produit supprimé'); } return Ajax::responseError('Une erreur est survenue lors de la suppression du produit.'); } public function actionAjaxAddOrder($idDocument, $classDocument, $idOrder) { $documentModule = $this->getDocumentModule(); $orderModule = $this->getOrderModule(); $document = $documentModule->findOneDocumentByIdAndClass($idDocument, $classDocument); $order = $orderModule->findOneOrderById($idOrder); if ($document && $documentModule->isStatusDraft($document) && $order) { $orderModule->updateOrderDocument($order, $document); return Ajax::responseSuccess("Commande ajoutée à la facture."); } else { return Ajax::responseError("Une erreur est survenue lors de l'ajout de la commande."); } } public function actionAjaxDeleteOrder($idDocument, $classDocument, $idOrder) { $documentModule = $this->getDocumentModule(); $orderModule = $this->getOrderModule(); $document = $documentModule->findOneDocumentByIdAndClass($idDocument, $classDocument); $order = $orderModule->findOneOrderById($idOrder); if ($document && $documentModule->isStatusDraft($document)) { if($documentModule->isDocumentDeliveryNote($document)) { $orderModule->updateOrderDeliveryNote($order, null); } elseif($documentModule->isDocumentInvoice($document)) { $orderModule->updateOrderInvoice($order, null); } return Ajax::responseSuccess('Commande supprimée de la facture.'); } else { return Ajax::responseError('Une erreur est survenue lors de la suppression de la commande.'); } } public function actionAjaxIgnoreOrderWhenInvoicing($idDocument, $classDocument, $idOrder) { $documentModule = $this->getDocumentModule(); $orderModule = $this->getOrderModule(); $document = $documentModule->findOneDocumentByIdAndClass($idDocument, $classDocument); $order = $orderModule->findOneOrderById($idOrder); if ($document && $documentModule->isStatusDraft($document) && $order) { $orderModule->updateOrderIgnoreWhenInvoicing($order, true); return Ajax::responseSuccess("La commande sera maintenant ignorée au moment de la facturation."); } else { return Ajax::responseError("Une erreur est survenue."); } } public function actionAjaxUpdateProductOrderInvoicePrice($idProductOrder, $invoicePrice) { $productOrderModule = $this->getProductOrderModule(); $productOrder = $productOrderModule->getRepository()->findOneProductOrderById((int) $idProductOrder); if($productOrder) { $productOrderModule->getBuilder()->updateProductOrderInvoicePriceByValue($productOrder, (float) $invoicePrice); return Ajax::responseSuccess("Prix mis à jour", [ 'invoice_price' => $productOrder->invoice_price ]); } return Ajax::responseError("Une erreur est survenue."); } public function getClass() { $class = get_class($this); $class = str_replace('Controller', '', $class); $class = str_replace('backend\controllers\\', '', $class); return $class; } public function getDocumentType() { $class = $this->getClass(); if ($class == 'Invoice') { $documentType = 'Facture'; } elseif ($class == 'DeliveryNote') { $documentType = 'Bon de livraison'; } elseif ($class == 'Quotation') { $documentType = 'Devis'; } if (isset($documentType)) { return $documentType; } return ''; } public function getFlashMessage(string $type, $model) { $class = $this->getClass(); $message = $this->getDocumentType(); $message .= ' ' . Html::encode($model->name) . ' '; if ($type == 'create') { $message .= 'ajouté'; } elseif ($type == 'update') { $message .= 'modifié'; } elseif ($type == 'delete') { $message .= 'supprimé'; } elseif ($type == 'validate') { $message .= 'validé'; } elseif ($type == 'send') { $message .= 'envoyé'; } if ($class == 'Invoice') { $message .= 'e'; } return $message; } protected function getTitle($prepend) { $class = $this->getClass(); switch ($class) { case 'Invoice' : $title = $prepend . ' une facture'; break; case 'DeliveryNote' : $title = $prepend . ' un bon de livraison'; break; case 'Quotation' : $title = $prepend . ' un devis'; break; } return $title; } public function getControllerUrl() { $path = strtolower($this->getClass()); $path = str_replace('deliverynote', 'delivery-note', $path); return $path; } /** * Recherche un Document en fonction de son ID. * * @param integer $id * @return Document * @throws NotFoundHttpException si le modèle n'est pas trouvé */ protected function findModel($idDocument, $classDocument = null) { $documentModule = $this->getDocumentModule(); $model = $documentModule->findOneDocumentByIdAndClass($idDocument, $classDocument ?? $this->getClass()); if ($model) { return $model; } else { throw new NotFoundHttpException('The requested page does not exist.'); } } }