Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

1026 linhas
40KB

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