Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

1000 lines
39KB

  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 common\models;
  38. use common\helpers\Debug;
  39. use common\helpers\GlobalParam;
  40. use common\helpers\Price;
  41. use common\models\Producer;
  42. use Yii;
  43. use yii\helpers\Html;
  44. use common\components\ActiveRecordCommon;
  45. use yii\web\NotFoundHttpException;
  46. /**
  47. * This is the model class for table "order".
  48. *
  49. * @property integer $id
  50. * @property integer $id_user
  51. * @property string $date
  52. * @property string $date_update
  53. * @property integer $id_point_sale
  54. * @property integer $id_distribution
  55. * @property boolean $auto_payment
  56. * @property integer $id_subscription
  57. */
  58. class Order extends ActiveRecordCommon
  59. {
  60. var $amount = 0;
  61. var $amount_with_tax = 0;
  62. var $invoice_amount = 0;
  63. var $invoice_amount_with_tax = 0;
  64. var $paid_amount = 0;
  65. var $weight = 0;
  66. const ORIGIN_AUTO = 'auto';
  67. const ORIGIN_USER = 'user';
  68. const ORIGIN_ADMIN = 'admin';
  69. const PAYMENT_PAID = 'paid';
  70. const PAYMENT_UNPAID = 'unpaid';
  71. const PAYMENT_SURPLUS = 'surplus';
  72. const INVOICE_AMOUNT_TOTAL = 'invoice-total' ;
  73. const AMOUNT_TOTAL = 'total';
  74. const AMOUNT_PAID = 'paid';
  75. const AMOUNT_REMAINING = 'remaining';
  76. const AMOUNT_SURPLUS = 'surplus';
  77. const STATE_OPEN = 'open';
  78. const STATE_PREPARATION = 'preparation';
  79. const STATE_DELIVERED = 'delivered';
  80. /**
  81. * @inheritdoc
  82. */
  83. public static function tableName()
  84. {
  85. return 'order';
  86. }
  87. /**
  88. * @inheritdoc
  89. */
  90. public function rules()
  91. {
  92. return [
  93. [['id_user', 'date', 'status'], 'required', 'message' => ''],
  94. [['id_user', 'id_point_sale', 'id_distribution', 'id_subscription', 'id_invoice', 'id_quotation', 'id_delivery_note'], 'integer'],
  95. [['auto_payment', 'tiller_synchronization'], 'boolean'],
  96. [['status', 'reference'], 'string'],
  97. [['date', 'date_update', 'comment', 'comment_point_sale', 'mean_payment'], 'safe']
  98. ];
  99. }
  100. /**
  101. * @inheritdoc
  102. */
  103. public function attributeLabels()
  104. {
  105. return [
  106. 'id' => 'ID',
  107. 'id_user' => 'Id User',
  108. 'date' => 'Date',
  109. 'date_update' => 'Date de modification',
  110. 'id_point_sale' => 'Point de vente',
  111. 'id_distribution' => 'Date de distribution',
  112. 'id_subscription' => 'Abonnement',
  113. 'status' => 'Statut',
  114. 'id_invoice' => 'Facture',
  115. 'id_quotation' => 'Devis',
  116. 'id_delivery_note' => 'Bon de livraison',
  117. 'reference' => 'Référence'
  118. ];
  119. }
  120. /*
  121. * Relations
  122. */
  123. public function getUser()
  124. {
  125. return $this->hasOne(User::className(), ['id' => 'id_user']);
  126. }
  127. public function getProductOrder()
  128. {
  129. return $this->hasMany(ProductOrder::className(), ['id_order' => 'id'])
  130. ->orderBy(['product.order' => SORT_ASC])
  131. ->joinWith('product');
  132. }
  133. public function getDistribution()
  134. {
  135. return $this->hasOne(Distribution::className(), ['id' => 'id_distribution'])
  136. ->with('producer');
  137. }
  138. public function getPointSale()
  139. {
  140. return $this->hasOne(PointSale::className(), ['id' => 'id_point_sale'])
  141. ->with('userPointSale');
  142. }
  143. public function getCreditHistory()
  144. {
  145. return $this->hasMany(CreditHistory::className(), ['id_order' => 'id']);
  146. }
  147. public function getSubscription()
  148. {
  149. return $this->hasOne(Subscription::className(), ['id' => 'id_subscription'])
  150. ->with('productSubscription');
  151. }
  152. public function getInvoice()
  153. {
  154. return $this->hasOne(Invoice::className(), ['id' => 'id_invoice']);
  155. }
  156. public function getQuotation()
  157. {
  158. return $this->hasOne(Quotation::className(), ['id' => 'id_quotation']);
  159. }
  160. public function getDeliveryNote()
  161. {
  162. return $this->hasOne(DeliveryNote::className(), ['id' => 'id_delivery_note']);
  163. }
  164. /**
  165. * Retourne les options de base nécessaires à la fonction de recherche.
  166. *
  167. * @return array
  168. */
  169. public static function defaultOptionsSearch()
  170. {
  171. return [
  172. 'with' => ['productOrder', 'productOrder.product', 'creditHistory', 'creditHistory.userAction', 'pointSale'],
  173. 'join_with' => ['distribution', 'user', 'user.userProducer'],
  174. 'orderby' => 'order.date ASC',
  175. 'attribute_id_producer' => 'distribution.id_producer'
  176. ];
  177. }
  178. /**
  179. * Initialise le montant total, le montant déjà payé et le poids de la
  180. * commande.
  181. */
  182. public function init()
  183. {
  184. $this->initAmount();
  185. $this->initPaidAmount();
  186. return $this;
  187. }
  188. /**
  189. * Initialise le montant de la commande.
  190. *
  191. */
  192. public function initAmount()
  193. {
  194. $this->amount = 0;
  195. $this->amount_with_tax = 0;
  196. $this->invoice_amount = 0;
  197. $this->invoice_amount_with_tax = 0;
  198. $this->weight = 0;
  199. if (isset($this->productOrder)) {
  200. foreach ($this->productOrder as $productOrder) {
  201. $this->amount += $productOrder->price * $productOrder->quantity;
  202. $this->amount_with_tax += Price::getPriceWithTax($productOrder->price, $productOrder->taxRate->value) * $productOrder->quantity;
  203. $invoicePrice = $productOrder->invoice_price ? $productOrder->invoice_price : $productOrder->price ;
  204. $this->invoice_amount += $invoicePrice * $productOrder->quantity;
  205. $this->invoice_amount_with_tax += Price::getPriceWithTax($invoicePrice, $productOrder->taxRate->value) * $productOrder->quantity;
  206. if ($productOrder->unit == 'piece') {
  207. if (isset($productOrder->product)) {
  208. $this->weight += ($productOrder->quantity * $productOrder->product->weight) / 1000;
  209. }
  210. } else {
  211. $this->weight += $productOrder->quantity;
  212. }
  213. }
  214. }
  215. }
  216. /**
  217. * Initialise le montant payé de la commande et le retourne.
  218. *
  219. * @return float
  220. */
  221. public function initPaidAmount()
  222. {
  223. if (isset($this->creditHistory)) {
  224. $history = $this->creditHistory;
  225. } else {
  226. $history = CreditHistory::find()
  227. ->where(['id_order' => $this->id])
  228. ->all();
  229. }
  230. $this->paid_amount = 0;
  231. if (count($history)) {
  232. foreach ($history as $ch) {
  233. if ($ch->type == CreditHistory::TYPE_PAYMENT) {
  234. $this->paid_amount += $ch->amount;
  235. } elseif ($ch->type == CreditHistory::TYPE_REFUND) {
  236. $this->paid_amount -= $ch->amount;
  237. }
  238. }
  239. }
  240. }
  241. public function delete()
  242. {
  243. // remboursement si l'utilisateur a payé pour cette commande
  244. $amountPaid = $this->getAmount(Order::AMOUNT_PAID);
  245. if ($amountPaid > 0.01) {
  246. $this->saveCreditHistory(
  247. CreditHistory::TYPE_REFUND,
  248. $amountPaid,
  249. GlobalParam::getCurrentProducerId(),
  250. $this->id_user,
  251. User::getCurrentId()
  252. );
  253. }
  254. // delete
  255. if (Producer::getConfig('option_behavior_cancel_order') == Producer::BEHAVIOR_DELETE_ORDER_DELETE ||
  256. (Producer::getConfig('option_behavior_cancel_order') == Producer::BEHAVIOR_DELETE_ORDER_STATUS && strlen($this->date_delete))) {
  257. ProductOrder::deleteAll(['id_order' => $this->id]);
  258. return parent::delete();
  259. } // status 'delete'
  260. elseif (Producer::getConfig('option_behavior_cancel_order') == Producer::BEHAVIOR_DELETE_ORDER_STATUS) {
  261. $this->date_delete = date('Y-m-d H:i:s');
  262. return $this->save();
  263. }
  264. }
  265. /**
  266. * Changement de statut d'une commande
  267. *
  268. * @param $newStatus
  269. */
  270. public function changeOrderStatus($newStatus, $origin)
  271. {
  272. $orderStatusArray = GlobalParam::get('orderStatus');
  273. switch ($newStatus) {
  274. case 'new-order' :
  275. $this->addOrderStatusHistory($newStatus, $origin);
  276. $this->status = $newStatus;
  277. $this->save();
  278. break;
  279. case 'waiting-paiement-on-delivery':
  280. if(in_array($newStatus, $orderStatusArray[$this->status]['nextStatusAllow'])){
  281. $this->addOrderStatusHistory($newStatus, $origin);
  282. $this->status = $newStatus;
  283. $this->save();
  284. }
  285. break;
  286. case 'waiting-paiement-by-credit':
  287. if(in_array($newStatus, $orderStatusArray[$this->status]['nextStatusAllow'])){
  288. $this->addOrderStatusHistory($newStatus, $origin);
  289. $this->status = $newStatus;
  290. $this->save();
  291. }
  292. break;
  293. case 'paid-by-credit':
  294. if(in_array($newStatus, $orderStatusArray[$this->status]['nextStatusAllow'])){
  295. $this->addOrderStatusHistory($newStatus, $origin);
  296. $this->status = $newStatus;
  297. $this->save();
  298. }
  299. break;
  300. case 'waiting-delevery' :
  301. if(in_array($newStatus, $orderStatusArray[$this->status]['nextStatusAllow'])){
  302. $this->addOrderStatusHistory($newStatus, $origin);
  303. $this->status = $newStatus;
  304. $this->save();
  305. }
  306. break;
  307. case 'delivered':
  308. if(in_array($newStatus, $orderStatusArray[$this->status]['nextStatusAllow'])){
  309. $this->addOrderStatusHistory($newStatus, $origin);
  310. $this->status = $newStatus;
  311. $this->save();
  312. }
  313. break;
  314. case 'refunded':
  315. if(in_array($newStatus, $orderStatusArray[$this->status]['nextStatusAllow'])){
  316. $this->addOrderStatusHistory($newStatus, $origin);
  317. $this->status = $newStatus;
  318. $this->save();
  319. }
  320. break;
  321. case 'cancel':
  322. if(in_array($newStatus, $orderStatusArray[$this->status]['nextStatusAllow'])){
  323. $this->addOrderStatusHistory($newStatus, $origin);
  324. $this->status = $newStatus;
  325. $this->save();
  326. }
  327. break;
  328. default:
  329. throw new NotFoundHttpException('Statut de commande inconnu.');
  330. break;
  331. }
  332. }
  333. public function addOrderStatusHistory($newStatus,$origin)
  334. {
  335. $orderStatusHistory = new OrderStatusHistory();
  336. $orderStatusHistory->id_user = User::getCurrentId();
  337. $orderStatusHistory->id_order = $this->id;
  338. $orderStatusHistory->status = $newStatus;
  339. $orderStatusHistory->origin = $origin;
  340. $orderStatusHistory->date = date('Y-m-d H:i:s');
  341. $orderStatusHistory->save();
  342. }
  343. /**
  344. * Retourne le montant de la commande (total, payé, restant, ou en surplus).
  345. *
  346. * @param boolean $format
  347. * @return float
  348. */
  349. public function getAmount($type = self::AMOUNT_TOTAL, $format = false)
  350. {
  351. $amount = $this->amount ;
  352. if($type == self::INVOICE_AMOUNT_TOTAL) {
  353. $amount = $this->invoice_amount ;
  354. }
  355. return $this->_getAmountGeneric($type, $amount, $format) ;
  356. }
  357. public function getAmountWithTax($type = self::AMOUNT_TOTAL, $format = false)
  358. {
  359. $amount = $this->amount_with_tax ;
  360. if($type == self::INVOICE_AMOUNT_TOTAL) {
  361. $amount = $this->invoice_amount_with_tax ;
  362. }
  363. return $this->_getAmountGeneric($type, $amount, $format) ;
  364. }
  365. protected function _getAmountGeneric($type, $amountOrder, $format)
  366. {
  367. switch ($type) {
  368. case self::AMOUNT_TOTAL :
  369. case self::INVOICE_AMOUNT_TOTAL :
  370. $amount = $amountOrder;
  371. break;
  372. case self::AMOUNT_PAID :
  373. $this->initPaidAmount();
  374. $amount = $this->paid_amount;
  375. break;
  376. case self::AMOUNT_REMAINING :
  377. $amount = $this->getAmountWithTax(self::AMOUNT_TOTAL)
  378. - $this->getAmountWithTax(self::AMOUNT_PAID);
  379. break;
  380. case self::AMOUNT_SURPLUS :
  381. $amount = $this->getAmountWithTax(self::AMOUNT_PAID)
  382. - $this->getAmountWithTax(self::AMOUNT_TOTAL);
  383. break;
  384. default:
  385. throw new NotFoundHttpException('Type de montant inconnu.') ;
  386. }
  387. if ($format) {
  388. return Price::format($amount) ;
  389. } else {
  390. return $amount;
  391. }
  392. }
  393. /**
  394. * Retourne les informations relatives à la commande au format JSON.
  395. *
  396. * @return string
  397. */
  398. public function getDataJson()
  399. {
  400. $order = Order::searchOne(['order.id' => $this->id]);
  401. $jsonOrder = [];
  402. if ($order) {
  403. $jsonOrder = [
  404. 'products' => [],
  405. 'amount' => $order->amount,
  406. 'str_amount' => $order->getAmountWithTax(self::AMOUNT_TOTAL, true),
  407. 'paid_amount' => $order->getAmount(self::AMOUNT_PAID),
  408. 'comment' => $order->comment,
  409. ];
  410. foreach ($order->productOrder as $productOrder) {
  411. $jsonOrder['products'][$productOrder->id_product] = $productOrder->quantity;
  412. }
  413. }
  414. return json_encode($jsonOrder);
  415. }
  416. /**
  417. * Enregistre un modèle de type CreditHistory.
  418. *
  419. * @param string $type
  420. * @param float $montant
  421. * @param integer $idProducer
  422. * @param integer $idUser
  423. * @param integer $idUserAction
  424. */
  425. public function saveCreditHistory($type, $amount, $idProducer, $idUser, $idUserAction)
  426. {
  427. $creditHistory = new CreditHistory;
  428. $creditHistory->id_user = $this->id_user;
  429. $creditHistory->id_order = $this->id;
  430. $creditHistory->amount = $amount;
  431. $creditHistory->type = $type;
  432. $creditHistory->id_producer = $idProducer;
  433. $creditHistory->id_user_action = $idUserAction;
  434. $creditHistory->populateRelation('order', $this);
  435. $creditHistory->populateRelation('user', User::find()->where(['id' => $this->id_user])->one());
  436. $creditHistory->save();
  437. }
  438. /**
  439. * Ajuste le crédit pour que la commande soit payée.
  440. *
  441. * @return boolean
  442. */
  443. public function processCredit()
  444. {
  445. if ($this->id_user) {
  446. $paymentStatus = $this->getPaymentStatus();
  447. if ($paymentStatus == self::PAYMENT_PAID) {
  448. return true;
  449. } elseif ($paymentStatus == self::PAYMENT_SURPLUS) {
  450. $type = CreditHistory::TYPE_REFUND;
  451. $amount = $this->getAmount(self::AMOUNT_SURPLUS);
  452. } elseif ($paymentStatus == self::PAYMENT_UNPAID) {
  453. $type = CreditHistory::TYPE_PAYMENT;
  454. $amount = $this->getAmount(self::AMOUNT_REMAINING);
  455. }
  456. $this->saveCreditHistory(
  457. $type,
  458. $amount,
  459. GlobalParam::getCurrentProducerId(),
  460. $this->id_user,
  461. User::getCurrentId()
  462. );
  463. }
  464. }
  465. public function setTillerSynchronization()
  466. {
  467. $order = Order::searchOne(['id' => $this->id]);
  468. $paymentStatus = $order->getPaymentStatus();
  469. if ($paymentStatus == self::PAYMENT_PAID) {
  470. $order->tiller_synchronization = 1 ;
  471. }
  472. else {
  473. $order->tiller_synchronization = 0 ;
  474. }
  475. $order->save() ;
  476. return $order ;
  477. }
  478. /**
  479. * Retourne le statut de paiement de la commande (payée, surplus, ou impayée).
  480. *
  481. * @return string
  482. */
  483. public function getPaymentStatus()
  484. {
  485. // payé
  486. if ($this->getAmountWithtax() - $this->getAmount(self::AMOUNT_PAID) < 0.01 &&
  487. $this->getAmountWithtax() - $this->getAmount(self::AMOUNT_PAID) > -0.01) {
  488. return self::PAYMENT_PAID;
  489. } // à rembourser
  490. elseif ($this->getAmountWithtax() - $this->getAmount(self::AMOUNT_PAID) <= -0.01) {
  491. return self::PAYMENT_SURPLUS;
  492. } // reste à payer
  493. elseif ($this->getAmountWithtax() - $this->getAmount(self::AMOUNT_PAID) >= 0.01) {
  494. return self::PAYMENT_UNPAID;
  495. }
  496. }
  497. /**
  498. * Retourne le résumé du panier au format HTML.
  499. *
  500. * @return string
  501. */
  502. public function getCartSummary($htmlFormat = true)
  503. {
  504. if (!isset($this->productOrder)) {
  505. $this->productOrder = productOrder::find()->where(['id_order' => $this->id])->all();
  506. }
  507. $html = '';
  508. $count = count($this->productOrder);
  509. $i = 0;
  510. foreach ($this->productOrder as $p) {
  511. if (isset($p->product)) {
  512. $html .= Html::encode($p->product->name) . ' (' . $p->quantity . '&nbsp;' . Product::strUnit($p->unit, 'wording_short', true) . ')';
  513. if (++$i != $count) {
  514. if($htmlFormat) {
  515. $html .= '<br />';
  516. }
  517. else {
  518. $html .= "\n";
  519. }
  520. }
  521. }
  522. }
  523. return $html;
  524. }
  525. /**
  526. * Retourne le résumé du point de vente lié à la commande au format HTML.
  527. *
  528. * @return string
  529. */
  530. public function getPointSaleSummary()
  531. {
  532. $html = '';
  533. if (isset($this->pointSale)) {
  534. $html .= '<span class="name-point-sale">' .
  535. Html::encode($this->pointSale->name) .
  536. '</span>' .
  537. '<br /><span class="locality">'
  538. . Html::encode($this->pointSale->locality)
  539. . '</span>';
  540. if (strlen($this->comment_point_sale)) {
  541. $html .= '<div class="comment"><span>'
  542. . Html::encode($this->comment_point_sale)
  543. . '</span></div>';
  544. }
  545. } else {
  546. $html .= 'Point de vente supprimé';
  547. }
  548. return $html;
  549. }
  550. /**
  551. * Retourne le résumé du paiement (montant, statut).
  552. *
  553. * @return string
  554. */
  555. public function getAmountSummary()
  556. {
  557. $html = '';
  558. $creditActive = Producer::getConfig('credit') ;
  559. $html .= $this->getAmountWithTax(self::AMOUNT_TOTAL, true) ;
  560. if($creditActive) {
  561. $html .= '<br />' ;
  562. if ($this->paid_amount) {
  563. if ($this->getPaymentStatus() == Order::PAYMENT_PAID) {
  564. $html .= '<span class="label label-success">Payée</span>';
  565. }
  566. elseif ($this->getPaymentStatus() == Order::PAYMENT_UNPAID) {
  567. $html .= '<span class="label label-danger">Non payée</span><br />
  568. Reste <strong>' . $this->getAmount(Order::AMOUNT_REMAINING, true) . '</strong> à payer';
  569. }
  570. elseif ($this->getPaymentStatus() == Order::PAYMENT_SURPLUS) {
  571. $html .= '<span class="label label-success">Payée</span>';
  572. }
  573. }
  574. else {
  575. $html .= '<span class="label label-default">Non réglé</span>';
  576. }
  577. }
  578. return $html;
  579. }
  580. /**
  581. * Retourne une chaine de caractère décrivant l'utilisateur lié à la commande.
  582. *
  583. * @return string
  584. */
  585. public function getStrUser()
  586. {
  587. if (isset($this->user)) {
  588. if(isset($this->user->name_legal_person) && strlen($this->user->name_legal_person)) {
  589. return Html::encode($this->user->name_legal_person);
  590. }
  591. else {
  592. return Html::encode($this->user->lastname . ' ' . $this->user->name);
  593. }
  594. }
  595. elseif (strlen($this->username)) {
  596. return Html::encode($this->username);
  597. }
  598. else {
  599. return 'Client introuvable';
  600. }
  601. }
  602. /**
  603. * Retourne l'état de la commande (livrée, modifiable ou en préparation)
  604. *
  605. * @return string
  606. */
  607. public function getState()
  608. {
  609. $orderDate = strtotime($this->distribution->date);
  610. $today = strtotime(date('Y-m-d'));
  611. $todayHour = date('G');
  612. $dayDistribution = strtolower(date('l', strtotime($this->distribution->date))) ;
  613. $orderDelay = Producer::getConfig(
  614. 'order_delay',
  615. $this->distribution->id_producer
  616. );
  617. $orderDelaySpecific = Producer::getConfig(
  618. 'order_delay_'.$dayDistribution,
  619. $this->distribution->id_producer
  620. );
  621. if($orderDelaySpecific) {
  622. $orderDelay = $orderDelaySpecific ;
  623. }
  624. $orderDeadline = Producer::getConfig(
  625. 'order_deadline',
  626. $this->distribution->id_producer
  627. );
  628. $orderDeadlineSpecific = Producer::getConfig(
  629. 'order_deadline_'.$dayDistribution,
  630. $this->distribution->id_producer
  631. );
  632. if($orderDeadlineSpecific) {
  633. $orderDeadline = $orderDeadlineSpecific ;
  634. }
  635. $nbDays = (int) round((($orderDate - $today) / (24 * 60 * 60)));
  636. if ($nbDays <= 0) {
  637. return self::STATE_DELIVERED;
  638. } elseif ($nbDays >= $orderDelay &&
  639. ($nbDays != $orderDelay ||
  640. ($nbDays == $orderDelay && $todayHour < $orderDeadline))) {
  641. return self::STATE_OPEN;
  642. }
  643. return self::STATE_PREPARATION;
  644. }
  645. /**
  646. * Retourne l'origine de la commande (client, automatique ou admin) sous forme
  647. * texte ou HTML.
  648. *
  649. * @param boolean $with_label
  650. * @return string
  651. */
  652. public function getStrOrigin($withLabel = false)
  653. {
  654. $classLabel = '';
  655. $str = '';
  656. if ($this->origin == self::ORIGIN_USER) {
  657. $classLabel = 'success';
  658. $str = 'Client';
  659. } elseif ($this->origin == self::ORIGIN_AUTO) {
  660. $classLabel = 'default';
  661. $str = 'Auto';
  662. } elseif ($this->origin == self::ORIGIN_ADMIN) {
  663. $classLabel = 'warning';
  664. $str = 'Vous';
  665. }
  666. if ($withLabel) {
  667. return '<span class="label label-' . $classLabel . '">'
  668. . $str . '</span>';
  669. } else {
  670. return $str;
  671. }
  672. }
  673. /**
  674. * Retourne l'historique de la commande (ajoutée, modifiée, supprimée) au
  675. * format HTML.
  676. *
  677. * @return string
  678. */
  679. public function getStrHistory()
  680. {
  681. $arr = [
  682. 'class' => 'create',
  683. 'glyphicon' => 'plus',
  684. 'str' => 'Ajoutée',
  685. 'date' => $this->date
  686. ];
  687. if (!is_null($this->date_update)) {
  688. $arr = [
  689. 'class' => 'update',
  690. 'glyphicon' => 'pencil',
  691. 'str' => 'Modifiée',
  692. 'date' => $this->date_update
  693. ];
  694. }
  695. if (!is_null($this->date_delete)) {
  696. $arr = [
  697. 'class' => 'delete',
  698. 'glyphicon' => 'remove',
  699. 'str' => 'Annulée',
  700. 'date' => $this->date_delete
  701. ];
  702. }
  703. $html = '<div class="small"><span class="' . $arr['class'] . '">'
  704. . '<span class="glyphicon glyphicon-' . $arr['glyphicon'] . '"></span> '
  705. . $arr['str'] . '</span> le <strong>'
  706. . date('d/m/Y à G\hi', strtotime($arr['date'])) . '</strong></div>';
  707. return $html;
  708. }
  709. /**
  710. * Retourne une classe identifiant l'historique de la commande (ajoutée,
  711. * modifiée, supprimée).
  712. *
  713. * @return string
  714. */
  715. public function getClassHistory()
  716. {
  717. if (!is_null($this->date_delete)) {
  718. return 'commande-delete';
  719. }
  720. if (!is_null($this->date_update)) {
  721. return 'commande-update';
  722. }
  723. return 'commande-create';
  724. }
  725. /**
  726. * Retourne la quantité d'un produit donné de plusieurs commandes.
  727. *
  728. * @param integer $idProduct
  729. * @param array $orders
  730. * @param boolean $ignoreCancel
  731. *
  732. * @return integer
  733. */
  734. public static function getProductQuantity($idProduct, $orders, $ignoreCancel = false, $unit = null)
  735. {
  736. $quantity = 0;
  737. if (isset($orders) && is_array($orders) && count($orders)) {
  738. foreach ($orders as $c) {
  739. if (is_null($c->date_delete) || $ignoreCancel) {
  740. foreach ($c->productOrder as $po) {
  741. if ($po->id_product == $idProduct &&
  742. ((is_null($unit) && $po->product->unit == $po->unit) || (!is_null($unit) && strlen($unit) && $po->unit == $unit))) {
  743. $quantity += $po->quantity;
  744. }
  745. }
  746. }
  747. }
  748. }
  749. return $quantity;
  750. }
  751. public static function getProductQuantityPieces($idProduct, $orders)
  752. {
  753. $quantity = 0;
  754. if (isset($orders) && is_array($orders) && count($orders)) {
  755. foreach ($orders as $c) {
  756. if (is_null($c->date_delete)) {
  757. foreach ($c->productOrder as $po) {
  758. if ($po->id_product == $idProduct) {
  759. if($po->unit == 'piece') {
  760. $quantity += $po->quantity ;
  761. }
  762. else {
  763. if(isset($po->product) && $po->product->weight > 0) {
  764. $quantity += ($po->quantity * Product::$unitsArray[$po->unit]['coefficient']) / $po->product->weight ;
  765. }
  766. }
  767. }
  768. }
  769. }
  770. }
  771. }
  772. return $quantity;
  773. }
  774. /**
  775. * Recherche et initialise des commandes.
  776. *
  777. * @param array $params
  778. * @param array $conditions
  779. * @param string $orderby
  780. * @param integer $limit
  781. * @return array
  782. */
  783. public static function searchBy($params = [], $options = [])
  784. {
  785. $orders = parent::searchBy($params, $options);
  786. /*
  787. * Initialisation des commandes
  788. */
  789. if (is_array($orders)) {
  790. if (count($orders)) {
  791. foreach ($orders as $order) {
  792. if (is_a($order, 'common\models\Order')) {
  793. $order->init();
  794. }
  795. }
  796. return $orders;
  797. }
  798. } else {
  799. $order = $orders;
  800. if (is_a($order, 'common\models\Order')) {
  801. return $order->init();
  802. } // count
  803. else {
  804. return $order;
  805. }
  806. }
  807. return false;
  808. }
  809. /**
  810. * Retourne le nombre de produits commandés
  811. *
  812. * @return integer
  813. */
  814. public function countProducts()
  815. {
  816. $count = 0;
  817. if ($this->productOrder && is_array($this->productOrder)) {
  818. return count($this->productOrder) ;
  819. }
  820. return 0;
  821. }
  822. /**
  823. * Retourne un bloc html présentant une date.
  824. *
  825. * @return string
  826. */
  827. public function getBlockDate()
  828. {
  829. return '<div class="block-date">
  830. <div class="day">' . strftime('%A', strtotime($this->distribution->date)) . '</div>
  831. <div class="num">' . date('d', strtotime($this->distribution->date)) . '</div>
  832. <div class="month">' . strftime('%B', strtotime($this->distribution->date)) . '</div>
  833. </div>';
  834. }
  835. public function getUsername()
  836. {
  837. $username = '' ;
  838. if($this->user) {
  839. $username = $this->user->getUsername() ;
  840. }
  841. if(strlen($this->username)) {
  842. $username = $this->username ;
  843. }
  844. return $username ;
  845. }
  846. public function initInvoicePrices($params = [])
  847. {
  848. foreach($this->productOrder as $productOrder) {
  849. if($productOrder->product) {
  850. $productOrder->invoice_price = $productOrder->product->getPrice([
  851. 'user' => isset($params['user']) ? $params['user'] : null,
  852. 'user_producer' => isset($params['user_producer']) ? $params['user_producer'] : null,
  853. 'point_sale' => isset($params['point_sale']) ? $params['point_sale'] : null
  854. ]) ;
  855. $productOrder->save() ;
  856. }
  857. }
  858. }
  859. public function initReference()
  860. {
  861. $producer = GlobalParam::getCurrentProducer() ;
  862. if($producer->option_order_reference_type == Producer::ORDER_REFERENCE_TYPE_YEARLY)
  863. {
  864. $lastOrder = Order::find()->innerJoinWith('distribution', true)
  865. ->where(['>=', 'distribution.date', date('Y').'-01-01'])
  866. ->andWhere([
  867. 'distribution.id_producer' => $producer->id
  868. ])
  869. ->andWhere(['not', ['order.reference' => null]])
  870. ->orderBy('order.id DESC')
  871. ->one() ;
  872. if($lastOrder && $lastOrder->reference && strlen($lastOrder->reference) > 0) {
  873. $pattern = '#A([0-9]+)C([0-9]+)#';
  874. preg_match($pattern, $lastOrder->reference, $matches, PREG_OFFSET_CAPTURE);
  875. $sizeNumReference = strlen($matches[2][0]);
  876. $numReference = ((int)$matches[2][0]) + 1;
  877. $numReference = str_pad($numReference, $sizeNumReference, '0', STR_PAD_LEFT);
  878. $this->reference = 'A'.$matches[1][0].'C'.$numReference ;
  879. }
  880. else {
  881. $this->reference = 'A'.date('y').'C0001' ;
  882. }
  883. $this->save() ;
  884. }
  885. }
  886. }