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.

478 lines
18KB

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