Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

462 rindas
15KB

  1. <?php
  2. namespace domain\Producer\Producer;
  3. use common\helpers\Departments;
  4. use common\helpers\Price;
  5. use domain\Document\Document\DocumentInterface;
  6. use domain\Document\Document\DocumentSolver;
  7. use domain\Order\Order\OrderRepositoryQuery;
  8. use domain\Order\OrderStatus\OrderStatus;
  9. use domain\PointSale\PointSale\PointSale;
  10. use domain\Producer\ProducerPriceRange\ProducerPriceRangeRepository;
  11. use domain\User\User\User;
  12. use domain\_\AbstractRepository;
  13. use yii\helpers\Html;
  14. class ProducerRepository extends AbstractRepository
  15. {
  16. protected ProducerRepositoryQuery $query;
  17. protected ProducerPriceRangeRepository $producerPriceRangeRepository;
  18. protected ProducerSolver $producerSolver;
  19. protected DocumentSolver $documentSolver;
  20. public function loadDependencies(): void
  21. {
  22. $this->loadQuery(ProducerRepositoryQuery::class);
  23. $this->producerPriceRangeRepository = $this->loadService(ProducerPriceRangeRepository::class);
  24. $this->producerSolver = $this->loadService(ProducerSolver::class);
  25. $this->documentSolver = $this->loadService(DocumentSolver::class);
  26. }
  27. /**
  28. * Retourne les options de base nécessaires à la fonction de recherche.
  29. *
  30. */
  31. public function getDefaultOptionsSearch(): array
  32. {
  33. return [
  34. self::WITH => ['taxRate', 'contact'],
  35. self::JOIN_WITH => [],
  36. self::ORDER_BY => 'name ASC',
  37. self::ATTRIBUTE_ID_PRODUCER => 'id'
  38. ];
  39. }
  40. public function findOneProducerById(int $id)
  41. {
  42. return $this->createQuery()
  43. ->filterById($id)
  44. ->findOne();
  45. }
  46. public function findOneProducerBySlug(string $slug)
  47. {
  48. return $this->createQuery()
  49. ->filterBySlug($slug)
  50. ->findOne();
  51. }
  52. public function queryProducersActive(string $orderByField = 'producer.name', string $orderByDirection = 'ASC')
  53. {
  54. return $this->createQuery()
  55. ->filterIsActive()
  56. ->orderBy($orderByField.' '.$orderByDirection);
  57. }
  58. /**
  59. * Retourne le compte producteur de démonstration.
  60. */
  61. public function findOneProducerDemoAccount()
  62. {
  63. return $this->createQuery()
  64. ->filterIsDemoAccount()
  65. ->findOne();
  66. }
  67. /**
  68. * Retourne la liste des établissements pour l'initialisation d'une listesélective.
  69. */
  70. public function populateProducerDropdown(bool $excludeProducerContext = false): array
  71. {
  72. $producerContext = $this->getProducerContext(false);
  73. $producers = $this->createQuery()
  74. ->filterIsActive()
  75. ->orderBy('postcode, city ASC')
  76. ->find();
  77. $departments = Departments::get();
  78. $dataProducers = [];
  79. $optionsProducers = [];
  80. foreach ($producers as $p) {
  81. if($excludeProducerContext && $producerContext && $producerContext->id != $p->id || !$excludeProducerContext) {
  82. $departmentCode = substr($p->postcode, 0, 2);
  83. if (!key_exists('d' . $departmentCode, $dataProducers) && isset($departments[$departmentCode])) {
  84. $dataProducers['d' . $departmentCode] = '<strong>' . $departments[$departmentCode] . '</strong>';
  85. $optionsProducers['d' . $departmentCode] = ['disabled' => true];
  86. }
  87. $dataProducers[$p->id] = '<span class="glyphicon glyphicon-lock"></span> ' . Html::encode(
  88. $p->name
  89. ) . ' - ' . Html::encode($p->postcode) . ' ' . Html::encode(
  90. $p->city
  91. ) . ' <span class="glyphicon glyphicon-lock"></span>';
  92. if (strlen($p->code)) {
  93. $optionsProducers[$p->id] = ['class' => 'lock'];
  94. }
  95. }
  96. }
  97. return [
  98. 'data' => $dataProducers,
  99. 'options' => $optionsProducers
  100. ];
  101. }
  102. public function getTurnoverLastMonth(Producer $producer, bool $format = false)
  103. {
  104. $period = date('Y-m', strtotime('-1 month'));
  105. return $this->getTurnover($producer, $period, false, $format);
  106. }
  107. public function getYearsWithTurnover(Producer $producer): array
  108. {
  109. $year = date('Y');
  110. $yearsArray = [];
  111. for($i = 0; $i <= 10; $i++) {
  112. if($this->hasTurnoverOverTheYear($producer, $year - $i)) {
  113. array_unshift($yearsArray, $year - $i);
  114. }
  115. }
  116. return $yearsArray;
  117. }
  118. public function hasTurnoverOverTheYear(Producer $producer, int $year): bool
  119. {
  120. for($month = 1; $month <= 12; $month++) {
  121. if($this->getTurnover($producer, $year.'-'.$month)) {
  122. return true;
  123. }
  124. }
  125. return false;
  126. }
  127. /**
  128. * Retourne le CA du producteur pour un mois donné
  129. */
  130. public function getTurnover(Producer $producer, string $period = '', bool $withTax = false, bool $format = false)
  131. {
  132. if (!$period) {
  133. $period = date('Y-m');
  134. }
  135. $dateStart = date('Y-m-31', strtotime("-1 month", strtotime($period)));
  136. $dateEnd = date('Y-m-01', strtotime("+1 month", strtotime($period)));
  137. return $this->getTurnoverByDateStartEnd($producer, $dateStart, $dateEnd, $withTax, $format);
  138. }
  139. public function getTurnoverByWeek(Producer $producer, int $year, int $week, bool $withTax = false, bool $format = false)
  140. {
  141. $date = new \DateTime();
  142. $date->setISODate($year, $week);
  143. $dateStart = $date->format('Y-m-d');
  144. $date->modify('+6 days');
  145. $dateEnd = $date->format('Y-m-d');
  146. return $this->getTurnoverByDateStartEnd($producer, $dateStart, $dateEnd, $withTax, $format);
  147. }
  148. public function getTurnoverByDateStartEnd(Producer $producer, string $dateStart, string $dateEnd, bool $withTax = false, bool $format = false)
  149. {
  150. $connection = \Yii::$app->getDb();
  151. $selectSum = 'product_order.price * product_order.quantity';
  152. if($withTax) {
  153. $selectSum .= ' * (tax_rate.value + 1)';
  154. }
  155. $command = $connection->createCommand(
  156. '
  157. SELECT SUM('.$selectSum.') AS turnover
  158. FROM `order`, product_order, distribution, tax_rate
  159. WHERE `order`.id = product_order.id_order
  160. AND '.OrderRepositoryQuery::getSqlFilterIsValid().'
  161. AND distribution.id_producer = :id_producer
  162. AND `order`.id_distribution = distribution.id
  163. AND distribution.date > :date_start
  164. AND distribution.date < :date_end
  165. AND product_order.id_tax_rate = tax_rate.id',
  166. [
  167. ':date_start' => $dateStart,
  168. ':date_end' => $dateEnd,
  169. ':id_producer' => $producer->id
  170. ]
  171. );
  172. $result = $command->queryOne();
  173. $turnover = (float) $result['turnover'];
  174. if ($format) {
  175. return number_format($turnover, 2) . ' €';
  176. } else {
  177. return $turnover;
  178. }
  179. }
  180. public function getTurnoverByNumberMonths(Producer $producer, $numberMonths = 1)
  181. {
  182. $totalTurnover = 0;
  183. for ($i = 1; $i <= $numberMonths; $i++) {
  184. $timeMonth = strtotime('-' . $i . ' month');
  185. $month = date('Y-m', $timeMonth);
  186. $totalTurnover += $this->getTurnover($producer, $month);
  187. }
  188. return $totalTurnover;
  189. }
  190. public function getAmountToBeBilledByMonth(Producer $producer, $month, bool $format = false)
  191. {
  192. $turnover = $this->getTurnover($producer, $month);
  193. return $this->producerPriceRangeRepository->getAmountToBeBilledByTurnover($turnover, $format);
  194. }
  195. public function getDatasChartTurnoverStatistics(Producer $producer, int $year, string $displayBy = 'month', bool $withTax = false)
  196. {
  197. $data = [];
  198. $dataLabels = [];
  199. $start = new \DateTime($year.'-01-01');
  200. if($year == date('Y')) {
  201. $end = new \DateTime('last day of this month');
  202. }
  203. else {
  204. $end = new \DateTime($year.'-12-31');
  205. }
  206. $interval = new \DateInterval(($displayBy == 'week') ? 'P1W' : 'P1M');
  207. $period = new \DatePeriod($start, $interval, $end);
  208. if($displayBy == 'week') {
  209. foreach ($period as $date) {
  210. $week = $date->format('W');
  211. $dataLabels[] = $week;
  212. $turnover = $this->getTurnoverByWeek($producer, $year, $date->format('W'), $withTax);
  213. $data[$week] = $turnover;
  214. }
  215. }
  216. else {
  217. foreach ($period as $date) {
  218. $month = $date->format('m/Y');
  219. $dataLabels[] = $month;
  220. $turnover = $this->getTurnover($producer, $date->format('Y-m'), $withTax);
  221. $data[$month] = $turnover;
  222. }
  223. }
  224. // création d'un tableau sans index car chart.js n'accepte pas les index
  225. $dataNoIndex = [];
  226. foreach ($data as $key => $val) {
  227. $dataNoIndex[] = round($val, 2);
  228. }
  229. return [
  230. 'labels' => $dataLabels,
  231. 'data' => $dataNoIndex
  232. ];
  233. }
  234. public function getSummaryAmountsToBeBilled(Producer $producer, string $label, int $numberOfMonths = 1, $context = 'list'): string
  235. {
  236. $text = '';
  237. $numMonthCurrent = date('m');
  238. $sumInvoicePrice = 0;
  239. if ($numberOfMonths == 1
  240. || ($numberOfMonths == 3 && (in_array($numMonthCurrent, [1, 4, 7, 10])))
  241. || ($numberOfMonths == 6 && (in_array($numMonthCurrent, [1, 7])))
  242. || $context == 'billing') {
  243. for ($i = 1; $i <= $numberOfMonths; $i++) {
  244. $timeMonth = strtotime('-' . $i . ' month');
  245. $month = date('Y-m', $timeMonth);
  246. $turnover = $this->getTurnover($producer, $month);
  247. if ($turnover) {
  248. if ($numberOfMonths > 1) {
  249. $text .= ucfirst(strftime('%B ', $timeMonth)) . ' ' . date('Y', $timeMonth) . ' : ';
  250. }
  251. $isBold = $this->producerSolver->isBillingTypeClassic($producer) && !$producer->option_billing_permanent_transfer;
  252. if ($isBold) $text .= '<strong>';
  253. $text .= $this->producerPriceRangeRepository->getAmountToBeBilledByTurnover($turnover, true);
  254. if ($isBold) $text .= '</strong>';
  255. $text .= ' (' . Price::format($turnover, 0) . ' CA)';
  256. $text .= '<br />';
  257. $sumInvoicePrice += $this->producerPriceRangeRepository->getAmountToBeBilledByTurnover($turnover, false);
  258. }
  259. }
  260. if (strlen($text)) {
  261. $text = '<i>' . $label . '</i>' . ' : <br />' . $text;
  262. }
  263. }
  264. if ($numberOfMonths > 1 && $sumInvoicePrice > 0) {
  265. $text .= '<br />Total : <strong>' . Price::format($sumInvoicePrice, 0) . '</strong>';
  266. }
  267. return $text;
  268. }
  269. public function getAmountToBillCurrentMonth()
  270. {
  271. $amountToBill = 0;
  272. $producersArray = $this->findProducersActive();
  273. foreach ($producersArray as $producer) {
  274. $amountToBill += $this->getAmountToBillCurrentMonthByProducer($producer);
  275. }
  276. return $amountToBill;
  277. }
  278. public function getAmountBilledLastMonth()
  279. {
  280. $amountBilled = 0;
  281. $producersArray = $this->findProducersActive();
  282. foreach ($producersArray as $producer) {
  283. $amountBilled += $this->getAmountBilledLastMonthByProducer($producer);
  284. }
  285. return $amountBilled;
  286. }
  287. public function getAmountToBillCurrentMonthByProducer(Producer $producer): float
  288. {
  289. return $this->getAmountToBeBilledByMonth($producer, date('Y-m'));
  290. }
  291. public function getAmountBilledLastMonthByProducer(Producer $producer): float
  292. {
  293. return $this->getAmountToBeBilledByMonth($producer, date('Y-m', strtotime('-1 month')));
  294. }
  295. public function getOnlinePaymentMinimumAmount(): float
  296. {
  297. $onlinePaymentMinimumAmount = $this->producerSolver->getConfig('option_online_payment_minimum_amount');
  298. if (!$onlinePaymentMinimumAmount) {
  299. $onlinePaymentMinimumAmount = Producer::ONLINE_PAYMENT_MINIMUM_AMOUNT_DEFAULT;
  300. }
  301. return $onlinePaymentMinimumAmount;
  302. }
  303. public function getNameProducer(User $user): string
  304. {
  305. $producer = $this->findOneProducerById($user->id_producer);
  306. return $producer->name;
  307. }
  308. public function isDocumentDisplayOrders(DocumentInterface $document)
  309. {
  310. return ($this->documentSolver->getClass($document) == 'Invoice') ?
  311. $this->producerSolver->getConfig('document_display_orders_invoice') :
  312. $this->producerSolver->getConfig('document_display_orders_delivery_note');
  313. }
  314. /**
  315. * Retourne le mode de fonctionnement de la cagnotte d'un point de vente.
  316. */
  317. public function getPointSaleCreditFunctioning(PointSale $pointSale): string
  318. {
  319. return strlen($pointSale->credit_functioning) > 0 ?
  320. $pointSale->credit_functioning :
  321. $this->producerSolver->getConfig('credit_functioning');
  322. }
  323. public function findProducersActive(string $orderByField = 'producer.name', string $orderByDirection = 'ASC')
  324. {
  325. return $this->queryProducersActive($orderByField, $orderByDirection)->find();
  326. }
  327. public function countProducersActiveWithTurnover(): int
  328. {
  329. $count = 0;
  330. $producersArray = $this->findProducersActive();
  331. foreach ($producersArray as $producer) {
  332. if ($this->getTurnoverByNumberMonths($producer, 3)) {
  333. $count++;
  334. }
  335. }
  336. return $count;
  337. }
  338. public function countCacheProducersActiveWithTurnover(): int
  339. {
  340. return \Yii::$app->cache->getOrSet('count_producers_active', function () {
  341. return $this->countProducersActiveWithTurnover();
  342. }, 60 * 60 * 24);
  343. }
  344. public function findProducers()
  345. {
  346. return $this->createQuery()->find();
  347. }
  348. public function findProducersWithTestimonials(): array
  349. {
  350. return $this->queryProducersActive()
  351. ->filterHasOptionTestimony()
  352. ->find();
  353. }
  354. public function findProducersWithTimeSaved(): array
  355. {
  356. return $this->queryProducersActive()
  357. ->filterHasOptionTimeSaved()
  358. ->find();
  359. }
  360. public function countProducersWithTimeSaved(): int
  361. {
  362. return count($this->findProducersWithTimeSaved());
  363. }
  364. public function getTimeSavedByProducersAverage(): int
  365. {
  366. $producersWithTimeSavedArray = $this->findProducersWithTimeSaved();
  367. $countProducersWithOptionTimeSaved = count($producersWithTimeSavedArray);
  368. if ($countProducersWithOptionTimeSaved) {
  369. $sumTimeSaved = 0;
  370. foreach ($producersWithTimeSavedArray as $producerWithTimeSaved) {
  371. $sumTimeSaved += $producerWithTimeSaved->option_time_saved;
  372. }
  373. return round($sumTimeSaved / $countProducersWithOptionTimeSaved);
  374. }
  375. return 0;
  376. }
  377. public function findOneProducerBySponsorshipCode(string $sponsorshipCode): ?Producer
  378. {
  379. return $this->createQuery()
  380. ->filterBySponsorshipCode($sponsorshipCode)
  381. ->findOne();
  382. }
  383. public function findProducersSponsorshipGodsons(Producer $producer): array
  384. {
  385. return $this->createQuery()
  386. ->filterBySponsoredBy($producer)
  387. ->find();
  388. }
  389. }