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.

Distribution.php 18KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  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 Yii;
  39. use common\helpers\GlobalParam;
  40. use common\models\Order;
  41. use common\components\ActiveRecordCommon;
  42. /**
  43. * This is the model class for table "production".
  44. *
  45. * @property integer $id
  46. * @property string $date
  47. * @property integer $active
  48. */
  49. class Distribution extends ActiveRecordCommon
  50. {
  51. /**
  52. * @inheritdoc
  53. */
  54. public static function tableName()
  55. {
  56. return 'distribution';
  57. }
  58. public function getProducer()
  59. {
  60. return $this->hasOne(Producer::className(), ['id' => 'id_producer']);
  61. }
  62. /**
  63. * @inheritdoc
  64. */
  65. public function rules()
  66. {
  67. return [
  68. [['date'], 'required'],
  69. [['date'], 'safe'],
  70. [['active'], 'integer']
  71. ];
  72. }
  73. /**
  74. * @inheritdoc
  75. */
  76. public function attributeLabels()
  77. {
  78. return [
  79. 'id' => 'ID',
  80. 'date' => 'Date',
  81. 'active' => 'Actif',
  82. ];
  83. }
  84. /*
  85. * Relations
  86. */
  87. public function getOrder()
  88. {
  89. return $this->hasMany(Order::className(), ['id_distribution' => 'id']);
  90. }
  91. public function getProductDistribution()
  92. {
  93. return $this->hasMany(ProductDistribution::className(), ['id_distribution' => 'id']);
  94. }
  95. public function getPointSaleDistribution()
  96. {
  97. return $this->hasMany(PointSaleDistribution::className(), ['id_distribution' => 'id']) ;
  98. }
  99. /**
  100. * Retourne les options de base nécessaires à la fonction de recherche.
  101. *
  102. * @return array
  103. */
  104. public static function defaultOptionsSearch()
  105. {
  106. return [
  107. 'with' => [],
  108. 'join_with' => [],
  109. 'orderby' => 'date ASC',
  110. 'attribute_id_producer' => 'distribution.id_producer'
  111. ];
  112. }
  113. public function getDate(): string
  114. {
  115. return $this->date;
  116. }
  117. /**
  118. * Retourne si un produit est actif ou non.
  119. *
  120. * @param integer $idProduit
  121. * @return boolean
  122. */
  123. public function isActiveProduct($idProduit)
  124. {
  125. if ($idProduit &&
  126. isset($this->productDistribution) &&
  127. count($this->productDistribution) > 0) {
  128. foreach ($this->productDistribution as $productDistribution) {
  129. if ($productDistribution['id_product'] == $idProduit &&
  130. $productDistribution['active']) {
  131. return true;
  132. }
  133. }
  134. }
  135. return false;
  136. }
  137. /**
  138. * Initialise un jour de production.
  139. *
  140. * @param string $date
  141. * @return Production
  142. */
  143. public static function initDistribution($date, $idProducer = 0)
  144. {
  145. $distribution = null;
  146. if ($date != '') {
  147. $paramsDistribution = [
  148. 'date' => $date
  149. ];
  150. if ($idProducer) {
  151. $paramsDistribution['distribution.id_producer'] = (int)$idProducer;
  152. } else {
  153. $idProducer = GlobalParam::getCurrentProducerId();
  154. }
  155. $distribution = Distribution::searchOne($paramsDistribution);
  156. if (!$distribution) {
  157. $distribution = new Distribution;
  158. $distribution->date = $date;
  159. $distribution->delivery = 1;
  160. $distribution->id_producer = $idProducer;
  161. $distribution->save();
  162. }
  163. }
  164. // point_sale_distribution à définir s'ils ne sont pas initialisés
  165. if ($distribution) {
  166. $countPointSaleDistribution = PointSaleDistribution::searchCount([
  167. 'id_distribution' => $distribution->id
  168. ]);
  169. if (!$countPointSaleDistribution) {
  170. PointSaleDistribution::setAll($distribution->id, true);
  171. }
  172. }
  173. // init produits sélectionnés pour cette production
  174. $products = Product::searchAll();
  175. if ($distribution) {
  176. $productsDistribution = ProductDistribution::searchAll([
  177. 'id_distribution' => $distribution->id
  178. ]);
  179. if (!count($productsDistribution)) {
  180. foreach ($products as $product) {
  181. $distribution->linkProduct($product);
  182. }
  183. }
  184. $distribution->linkProductGift();
  185. }
  186. return $distribution;
  187. }
  188. /**
  189. * Retourne les distributions futures.
  190. *
  191. * @return array
  192. */
  193. public static function getIncomingDistributions()
  194. {
  195. $distributionsArray = Distribution::find()
  196. ->where('date > \'' . date('Y-m-d') . '\'')
  197. ->andWhere([
  198. 'id_producer' => GlobalParam::getCurrentProducerId(),
  199. 'active' => 1
  200. ])
  201. ->orderBy('date ASC')
  202. ->all();
  203. return $distributionsArray;
  204. }
  205. public static function filterDistributionsByDateDelay($distributionsArray)
  206. {
  207. $producer = GlobalParam::getCurrentProducer() ;
  208. $dateToday = date('Y-m-d') ;
  209. foreach($distributionsArray as $keyDistribution => $distribution) {
  210. $dateDistribution = $distribution->date ;
  211. $dayDistribution = strtolower(date('l', strtotime($dateDistribution))) ;
  212. $fieldDayDistributionDelay = 'order_delay_'.$dayDistribution ;
  213. $fieldDayDistributionDeadline = 'order_deadline_'.$dayDistribution ;
  214. $delay = $producer->order_delay ;
  215. $deadline = $producer->order_deadline ;
  216. if($producer->$fieldDayDistributionDelay) {
  217. $delay = $producer->$fieldDayDistributionDelay ;
  218. }
  219. if($producer->$fieldDayDistributionDeadline) {
  220. $deadline = $producer->$fieldDayDistributionDeadline ;
  221. }
  222. $countDaysTodayDistribution = number_format((strtotime($dateDistribution) - strtotime($dateToday)) / (24 * 60 * 60) , 0);
  223. if(date('H') >= $deadline) {
  224. $countDaysTodayDistribution -- ;
  225. }
  226. if($countDaysTodayDistribution < $delay) {
  227. unset($distributionsArray[$keyDistribution]) ;
  228. }
  229. }
  230. $newDistributionsArray = [] ;
  231. foreach($distributionsArray as $distribution) {
  232. $newDistributionsArray[] = $distribution ;
  233. }
  234. return $newDistributionsArray ;
  235. }
  236. /**
  237. * Lie un produit aux jours de distribution futurs.
  238. *
  239. * @param Product $product
  240. */
  241. public static function linkProductIncomingDistributions($product)
  242. {
  243. $distributionsArray = self::getIncomingDistributions();
  244. foreach ($distributionsArray as $distribution) {
  245. $distribution->linkProduct($product);
  246. }
  247. }
  248. /**
  249. * Lie un produit à la distribution.
  250. *
  251. * @param Product $product
  252. */
  253. public function linkProduct($product)
  254. {
  255. $productDistribution = ProductDistribution::searchOne([
  256. 'id_distribution' => $this->id,
  257. 'id_product' => $product->id
  258. ]);
  259. if (!$productDistribution) {
  260. $productDistribution = new ProductDistribution();
  261. $productDistribution->id_distribution = $this->id;
  262. $productDistribution->id_product = $product->id;
  263. }
  264. $dayDistribution = date('N', strtotime($this->date));
  265. $daysArray = [
  266. 1 => 'monday',
  267. 2 => 'tuesday',
  268. 3 => 'wednesday',
  269. 4 => 'thursday',
  270. 5 => 'friday',
  271. 6 => 'saturday',
  272. 7 => 'sunday',
  273. ];
  274. $productDistribution->active = 0;
  275. $day = $daysArray[$dayDistribution];
  276. if ($product->active && $product->$day) {
  277. $productDistribution->active = 1;
  278. }
  279. $productDistribution->quantity_max = $product->quantity_max;
  280. $fieldQuantityMax = 'quantity_max_'.$day ;
  281. if(isset($product->$fieldQuantityMax) && $product->$fieldQuantityMax > 0) {
  282. $productDistribution->quantity_max = $product->$fieldQuantityMax ;
  283. }
  284. $productDistribution->save();
  285. // update prices product order
  286. $ordersArray = Order::searchAll([
  287. 'distribution.date' => $this->date,
  288. 'distribution.id_producer' => $this->id_producer
  289. ],
  290. [
  291. 'conditions' => 'date_delete IS NULL AND origin != "user"'
  292. ]);
  293. if($ordersArray) {
  294. foreach($ordersArray as $order) {
  295. foreach($order->productOrder as $productOrder) {
  296. if($productOrder->id_product == $product->id) {
  297. $productOrder->price = $product->price ;
  298. $user = false;
  299. $userProducer = false;
  300. if(isset($order->user) && $order->user) {
  301. $user = $order->user;
  302. $userProducer = UserProducer::searchOne([
  303. 'id_user' => $user->id,
  304. 'id_producer' => $order->distribution->id_producer
  305. ]) ;
  306. }
  307. $productOrder->price = $product->getPrice([
  308. 'user' => $user,
  309. 'user_producer' => $userProducer,
  310. 'point_sale' => $order->pointSale,
  311. 'quantity' => $productOrder->quantity
  312. ]);
  313. $productOrder->save() ;
  314. }
  315. }
  316. }
  317. }
  318. return $productDistribution;
  319. }
  320. /**
  321. * Lie le produit "Don" à la distribution
  322. */
  323. public function linkProductGift()
  324. {
  325. $productGift = Product::getProductGift();
  326. if ($productGift) {
  327. $productDistribution = ProductDistribution::searchOne([
  328. 'id_distribution' => $this->id,
  329. 'id_product' => $productGift->id
  330. ]);
  331. if (!$productDistribution) {
  332. $productDistribution = new ProductDistribution();
  333. $productDistribution->id_distribution = $this->id;
  334. $productDistribution->id_product = $productGift->id;
  335. $productDistribution->active = 1;
  336. $productDistribution->save();
  337. }
  338. }
  339. }
  340. /**
  341. * Lie un point de vente aux jours de distribution futurs.
  342. *
  343. * @param PointSale $pointSale
  344. */
  345. public static function linkPointSaleIncomingDistributions($pointSale)
  346. {
  347. $distributionsArray = self::getIncomingDistributions();
  348. foreach ($distributionsArray as $distribution) {
  349. $distribution->linkPointSale($pointSale);
  350. }
  351. }
  352. /**
  353. *
  354. * @param type $pointSale
  355. */
  356. public function linkPointSale($pointSale)
  357. {
  358. $pointSaleDistribution = PointSaleDistribution::searchOne([
  359. 'id_distribution' => $this->id,
  360. 'id_point_sale' => $pointSale->id
  361. ]);
  362. if (!$pointSaleDistribution) {
  363. $pointSaleDistribution = new PointSaleDistribution();
  364. $pointSaleDistribution->id_distribution = $this->id;
  365. $pointSaleDistribution->id_point_sale = $pointSale->id;
  366. }
  367. $dayDistribution = date('N', strtotime($this->date));
  368. $daysArray = [
  369. 1 => 'monday',
  370. 2 => 'tuesday',
  371. 3 => 'wednesday',
  372. 4 => 'thursday',
  373. 5 => 'friday',
  374. 6 => 'saturday',
  375. 7 => 'sunday',
  376. ];
  377. $pointSaleDistribution->delivery = 0;
  378. $deliveryDay = 'delivery_' . $daysArray[$dayDistribution];
  379. if ($pointSale->$deliveryDay) {
  380. $pointSaleDistribution->delivery = 1;
  381. }
  382. $pointSaleDistribution->save();
  383. }
  384. public function isPointSaleActive($distribution, $pointSaleId)
  385. {
  386. $pointSaleActive = false ;
  387. if($distribution->pointSaleDistribution) {
  388. foreach($distribution->pointSaleDistribution as $pointSaleDistribution) {
  389. if($pointSaleDistribution->id_point_sale == $pointSaleId && $pointSaleDistribution->delivery) {
  390. $pointSaleActive = true ;
  391. }
  392. }
  393. }
  394. return $pointSaleActive ;
  395. }
  396. /**
  397. * Active ou désactive la distribution.
  398. */
  399. public function active($active = true)
  400. {
  401. PointSaleDistribution::setAll($this->id, true);
  402. $this->active = (int)$active;
  403. $this->save();
  404. if ($active) {
  405. // ajout des abonnements
  406. Subscription::addAll($this->date);
  407. }
  408. }
  409. }