您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

470 行
17KB

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