You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

462 lines
19KB

  1. <?php
  2. /**
  3. * Copyright distrib (2018)
  4. *
  5. * contact@opendistrib.net
  6. *
  7. * Ce logiciel est un programme informatique servant à aider les producteurs
  8. * à distribuer leur production en circuits courts.
  9. *
  10. * Ce logiciel est régi par la licence CeCILL soumise au droit français et
  11. * respectant les principes de diffusion des logiciels libres. Vous pouvez
  12. * utiliser, modifier et/ou redistribuer ce programme sous les conditions
  13. * de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA
  14. * sur le site "http://www.cecill.info".
  15. *
  16. * En contrepartie de l'accessibilité au code source et des droits de copie,
  17. * de modification et de redistribution accordés par cette licence, il n'est
  18. * offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons,
  19. * seule une responsabilité restreinte pèse sur l'auteur du programme, le
  20. * titulaire des droits patrimoniaux et les concédants successifs.
  21. *
  22. * A cet égard l'attention de l'utilisateur est attirée sur les risques
  23. * associés au chargement, à l'utilisation, à la modification et/ou au
  24. * développement et à la reproduction du logiciel par l'utilisateur étant
  25. * donné sa spécificité de logiciel libre, qui peut le rendre complexe à
  26. * manipuler et qui le réserve donc à des développeurs et des professionnels
  27. * avertis possédant des connaissances informatiques approfondies. Les
  28. * utilisateurs sont donc invités à charger et tester l'adéquation du
  29. * logiciel à leurs besoins dans des conditions permettant d'assurer la
  30. * sécurité de leurs systèmes et ou de leurs données et, plus généralement,
  31. * à l'utiliser et l'exploiter dans les mêmes conditions de sécurité.
  32. *
  33. * Le fait que vous puissiez accéder à cet en-tête signifie que vous avez
  34. * pris connaissance de la licence CeCILL, et que vous en avez accepté les
  35. * termes.
  36. */
  37. namespace backend\controllers;
  38. use common\models\Product;
  39. use common\models\User;
  40. use common\models\Document;
  41. use common\helpers\GlobalParam;
  42. use common\models\Order;
  43. use yii\base\UserException;
  44. class DocumentController extends BackendController
  45. {
  46. public function behaviors()
  47. {
  48. return [
  49. 'verbs' => [
  50. 'class' => VerbFilter::className(),
  51. 'actions' => [
  52. ],
  53. ],
  54. 'access' => [
  55. 'class' => AccessControl::className(),
  56. 'rules' => [
  57. [
  58. 'allow' => true,
  59. 'roles' => ['@'],
  60. 'matchCallback' => function ($rule, $action) {
  61. return User::hasAccessBackend();
  62. }
  63. ]
  64. ],
  65. ],
  66. ];
  67. }
  68. public function actionCreate()
  69. {
  70. $class = $this->getClass();
  71. $model = new $class();
  72. if ($model->load(Yii::$app->request->post())) {
  73. $model->id_producer = GlobalParam::getCurrentProducerId();
  74. if ($model->save()) {
  75. Yii::$app->getSession()->setFlash('success', $this->getFlashMessage('create', $model));
  76. return $this->redirect(['/' . $model->getControllerUrlPath() . '/update', 'id' => $model->id]);
  77. } else {
  78. Yii::$app->getSession()->setFlash('error', 'Un problème est survenu lors de la création du document.');
  79. }
  80. }
  81. return $this->render('/document/create', [
  82. 'title' => $this->getTitle('Ajouter'),
  83. 'typeDocument' => $this->getDocumentType(),
  84. 'model' => $model,
  85. ]);
  86. }
  87. /**
  88. * Modifie un modèle Produit existant.
  89. * Si la modification réussit, le navigateur est redirigé vers la page 'index'.
  90. *
  91. * @param integer $id
  92. * @return mixed
  93. */
  94. public function actionUpdate($id)
  95. {
  96. $model = $this->findModel($id);
  97. $class = $this->getClass();
  98. $model = $class::searchOne([
  99. 'id' => $id
  100. ]);
  101. if ($model->isStatusValid()) {
  102. throw new UserException('Vous ne pouvez pas modifier un document validé.');
  103. }
  104. if ($model && $model->load(Yii::$app->request->post()) && $model->save()) {
  105. Yii::$app->getSession()->setFlash('success', $this->getFlashMessage('update', $model));
  106. }
  107. return $this->render('/document/update', [
  108. 'title' => $this->getTitle('Modifier'),
  109. 'typeDocument' => $this->getDocumentType(),
  110. 'model' => $model,
  111. ]);
  112. }
  113. public function actionDelete($id)
  114. {
  115. $model = $this->findModel($id);
  116. if ($model->isStatusValid()) {
  117. throw new UserException('Vous ne pouvez pas supprimer un document validé.');
  118. }
  119. $model->delete() ;
  120. Order::updateAll([
  121. 'order.id_delivery_note' => null
  122. ],[
  123. 'order.id_delivery_note' => $id
  124. ]) ;
  125. Yii::$app->getSession()->setFlash('success', $this->getFlashMessage('delete', $model));
  126. $this->redirect(['delivery-note/index']) ;
  127. }
  128. public function actionAjaxAddressUser($idUser)
  129. {
  130. \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
  131. if ($idUser > 0) {
  132. $user = User::searchOne([
  133. 'id' => $idUser
  134. ]) ;
  135. if ($user) {
  136. return [
  137. 'return' => 'success',
  138. 'address' => $user->getFullAddress()
  139. ];
  140. }
  141. }
  142. return ['return' => 'error'];
  143. }
  144. public function actionValidate($id)
  145. {
  146. $classDocument = $this->getClass() ;
  147. if ($id > 0 && Document::isValidClass($classDocument)) {
  148. $document = $classDocument::searchOne([
  149. 'id' => $id
  150. ]);
  151. if ($document) {
  152. $document->changeStatus(Document::STATUS_VALID);
  153. $document->save();
  154. Yii::$app->getSession()->setFlash('success', $this->getFlashMessage('validate', $document));
  155. return $this->redirect(['delivery-note/index']) ;
  156. }
  157. }
  158. Yii::$app->getSession()->setFlash('danger', 'Une erreur est survenue lors de la validation du document.');
  159. return $this->redirect(['delivery-note/index']) ;
  160. }
  161. public function actionAjaxValidateDocument($idDocument, $classDocument)
  162. {
  163. \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
  164. if ($idDocument > 0 && Document::isValidClass($classDocument)) {
  165. $document = $classDocument::searchOne([
  166. 'id' => $idDocument
  167. ]);
  168. if ($document) {
  169. $document->changeStatus(Document::STATUS_VALID);
  170. $document->save();
  171. return [
  172. 'return' => 'success',
  173. 'alert' => [
  174. 'type' => 'success',
  175. 'message' => 'Document validé'
  176. ]
  177. ];
  178. }
  179. }
  180. return [
  181. 'return' => 'error',
  182. 'alert' => [
  183. 'type' => 'danger',
  184. 'message' => 'Une erreur est survenue lors de la validation du document.'
  185. ]
  186. ];
  187. }
  188. public function actionAjaxInit($idDocument, $classDocument)
  189. {
  190. \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
  191. if ($idDocument > 0 && Document::isValidClass($classDocument)) {
  192. $document = $classDocument::searchOne([
  193. 'id' => $idDocument
  194. ]);
  195. if ($document) {
  196. $productsArray = Product::searchAll();
  197. $ordersArray = [];
  198. foreach ($document->orders as $order) {
  199. $order->init();
  200. $productsOrderArray = [];
  201. foreach ($order->productOrder as $productOrder) {
  202. $productsOrderArray[$productOrder->id] = $productOrder->getAttributes();
  203. }
  204. $ordersArray[$order->id] = array_merge(
  205. $order->getAttributes(),
  206. [
  207. 'productOrder' => $productsOrderArray,
  208. ]
  209. );
  210. }
  211. return [
  212. 'return' => 'success',
  213. 'document' => array_merge($document->getAttributes(), [
  214. 'html_label' => $document->getHtmlLabel(),
  215. 'class' => $document->getClass()
  216. ]),
  217. 'idUser' => $document->user->id,
  218. 'products' => ArrayHelper::map($productsArray, 'id', function ($product) {
  219. return array_merge($product->getAttributes(), [
  220. 'price_with_tax' => $product->price_with_tax,
  221. 'wording_unit' => $product->wording_unit,
  222. 'tax_rate' => $product->taxRate->value
  223. ]);
  224. }),
  225. 'orders' => $ordersArray,
  226. 'total' => $document->getAmount(Order::AMOUNT_TOTAL),
  227. 'total_with_tax' => $document->getAmountWithTax(Order::AMOUNT_TOTAL),
  228. ];
  229. }
  230. }
  231. return ['return' => 'error'];
  232. }
  233. public function actionAjaxAddProduct($idDocument, $classDocument, $idProduct, $quantity, $price)
  234. {
  235. \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
  236. if (Document::isValidClass($classDocument)) {
  237. $document = $classDocument::searchOne([
  238. 'id' => $idDocument
  239. ]);
  240. $product = Product::searchOne([
  241. 'id' => $idProduct
  242. ]);
  243. if ($document && $product) {
  244. if (count($document->orders) == 0) {
  245. $order = new Order;
  246. $order->id_user = $document->id_user;
  247. $order->id_point_sale = null;
  248. $order->id_distribution = null;
  249. $order->origin = Order::ORIGIN_ADMIN;
  250. $order->date = date('Y-m-d H:i:s');
  251. $fieldIdDocument = 'id_' . $classDocument::tableName();
  252. $order->$fieldIdDocument = $document->id;
  253. $order->save();
  254. } else {
  255. $order = $document->orders[0];
  256. }
  257. if ($order) {
  258. $productOrder = new ProductOrder;
  259. $productOrder->id_order = $order->id;
  260. $productOrder->id_product = $idProduct;
  261. $quantity = $quantity / Product::$unitsArray[$product->unit]['coefficient'];
  262. $productOrder->quantity = $quantity;
  263. $productOrder->price = (float)$price;
  264. $productOrder->unit = $product->unit;
  265. $productOrder->step = $product->step;
  266. $productOrder->id_tax_rate = $productOrder->id_tax_rate ?
  267. $product->taxRate->id : GlobalParam::getCurrentProducer()->taxRate->id;
  268. $productOrder->save();
  269. return [
  270. 'return' => 'error',
  271. 'alert' => [
  272. 'type' => 'success',
  273. 'message' => 'Produit ajouté'
  274. ]
  275. ];
  276. }
  277. }
  278. }
  279. return [
  280. 'return' => 'error',
  281. 'alert' => [
  282. 'type' => 'danger',
  283. 'message' => 'Une erreur est survenue lors de la suppression du produit.'
  284. ]
  285. ];
  286. }
  287. public function actionAjaxDeleteProductOrder($idProductOrder)
  288. {
  289. \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
  290. $productOrder = ProductOrder::searchOne([
  291. 'id' => $idProductOrder
  292. ]);
  293. if ($productOrder) {
  294. $productOrder->delete();
  295. return [
  296. 'return' => 'success',
  297. 'alert' => [
  298. 'type' => 'danger',
  299. 'message' => 'Produit supprimé'
  300. ]
  301. ];
  302. }
  303. return [
  304. 'return' => 'error',
  305. 'alert' => [
  306. 'type' => 'danger',
  307. 'message' => 'Une erreur est survenue lors de la suppression du produit.'
  308. ]
  309. ];
  310. }
  311. protected function getClass()
  312. {
  313. $class = get_class($this);
  314. $class = str_replace('Controller', '', $class);
  315. $class = str_replace('backend\controllers\\', '', $class);
  316. return $class;
  317. }
  318. protected function getDocumentType()
  319. {
  320. $class = $this->getClass();
  321. if ($class == 'Invoice') {
  322. $documentType = 'Facture';
  323. } elseif ($class == 'DeliveryNote') {
  324. $documentType = 'Bon de livraison';
  325. } elseif ($class == 'Quotation') {
  326. $documentType = 'Devis';
  327. }
  328. if (isset($documentType)) {
  329. return $documentType;
  330. }
  331. return '';
  332. }
  333. public function getFlashMessage($type = 'create', $model)
  334. {
  335. $class = $this->getClass();
  336. $message = $this->getDocumentType();
  337. $message .= ' <strong>' . Html::encode($model->name) . '</strong> ';
  338. if ($type == 'create') {
  339. $message .= 'ajouté';
  340. }
  341. elseif ($type == 'update') {
  342. $message .= 'modifié';
  343. }
  344. elseif ($type == 'delete') {
  345. $message .= 'supprimé';
  346. }
  347. elseif ($type == 'validate') {
  348. $message .= 'validé';
  349. }
  350. if ($class == 'Invoice') {
  351. $message .= 'e';
  352. }
  353. return $message;
  354. }
  355. protected function getTitle($prepend)
  356. {
  357. $class = $this->getClass();
  358. switch ($class) {
  359. case 'Invoice' :
  360. $title = $prepend . ' une facture';
  361. break;
  362. case 'DeliveryNote' :
  363. $title = $prepend . ' un bon de livraison';
  364. break;
  365. case 'Quotation' :
  366. $title = $prepend . ' un devis';
  367. break;
  368. }
  369. return $title;
  370. }
  371. /**
  372. * Recherche un Document en fonction de son ID.
  373. *
  374. * @param integer $id
  375. * @return Produit
  376. * @throws NotFoundHttpException si le modèle n'est pas trouvé
  377. */
  378. protected function findModel($id)
  379. {
  380. $class = $this->getClass();
  381. $model = $class::searchOne([
  382. 'id' => $id
  383. ]) ;
  384. if ($model) {
  385. return $model;
  386. } else {
  387. throw new NotFoundHttpException('The requested page does not exist.');
  388. }
  389. }
  390. }