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.

Producer.php 38KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018
  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\components\ActiveRecordCommon;
  40. use common\helpers\Departments;
  41. use yii\helpers\Html;
  42. /**
  43. * This is the model class for table "etablissement".
  44. *
  45. * @property integer $id
  46. * @property string $name
  47. * @property string $siret
  48. * @property string $logo
  49. * @property string $photo
  50. * @property string $description
  51. * @property string $postcode
  52. * @property string $city
  53. * @property float credit_limit_reminder
  54. * @property boolean online_payment
  55. * @property string mentions
  56. * @property string gcs
  57. * @property boolean option_allow_user_gift
  58. * @property string credit_functioning
  59. * @property boolean use_credit_checked_default
  60. * @property float credit_limit
  61. * @property string background_color_logo
  62. *
  63. */
  64. class Producer extends ActiveRecordCommon
  65. {
  66. const CREDIT_FUNCTIONING_MANDATORY = 'mandatory';
  67. const CREDIT_FUNCTIONING_OPTIONAL = 'optional';
  68. const CREDIT_FUNCTIONING_USER = 'user';
  69. const HINT_CREDIT_FUNCTIONING = '<ul>'
  70. . '<li>Optionnelle : l\'utilisateur choisit s\'il utilise son Crédit ou non. Les commandes peuvent être payées ou impayées.</li>'
  71. . '<li>Obligatoire : toutes les commandes de l\'utilisateur son comptabilisées au niveau du Crédit. Toutes les commandes sont payées.</li>'
  72. . '<li>Basée sur l\'utilisateur : Crédit obligatoire si l\'utilisateur a le crédit activé au niveau de son compte, système de Crédit non affiché sinon.</li>'
  73. . '</ul>';
  74. public static $creditFunctioningArray = [
  75. self::CREDIT_FUNCTIONING_MANDATORY => 'Obligatoire',
  76. self::CREDIT_FUNCTIONING_OPTIONAL => 'Optionnelle',
  77. self::CREDIT_FUNCTIONING_USER => 'Basée sur l\'utilisateur',
  78. ];
  79. const BEHAVIOR_DELETE_ORDER_DELETE = 'delete';
  80. const BEHAVIOR_DELETE_ORDER_STATUS = 'status';
  81. const BEHAVIOR_HOME_POINT_SALE_DAY_LIST_WEEK = 'days-of-week';
  82. const BEHAVIOR_HOME_POINT_SALE_DAY_LIST_INCOMING_DISTRIBUTIONS = 'incoming-distributions';
  83. const BEHAVIOR_ORDER_SELECT_DISTRIBUTION_CALENDAR = 'calendar';
  84. const BEHAVIOR_ORDER_SELECT_DISTRIBUTION_LIST = 'list';
  85. const ORDER_REFERENCE_TYPE_NONE = '';
  86. const ORDER_REFERENCE_TYPE_YEARLY = 'yearly';
  87. const ORDER_ENTRY_POINT_DATE = 'date';
  88. const ORDER_ENTRY_POINT_POINT_SALE = 'point-sale';
  89. const BILLING_FREQUENCY_MONTHLY = 'monthly';
  90. const BILLING_FREQUENCY_QUARTERLY = 'quarterly';
  91. const BILLING_FREQUENCY_BIANNUAL = 'biannual';
  92. public static $billingFrequencyArray = [
  93. self::BILLING_FREQUENCY_MONTHLY => 'Mensuelle',
  94. self::BILLING_FREQUENCY_QUARTERLY => 'Trimestrielle',
  95. self::BILLING_FREQUENCY_BIANNUAL => 'Biannuelle',
  96. ];
  97. const BILLING_TYPE_CLASSIC = 'classic';
  98. const BILLING_TYPE_FREE_PRICE = 'free-price';
  99. public static $billingTypeArray = [
  100. self::BILLING_TYPE_CLASSIC => 'Classique',
  101. self::BILLING_TYPE_FREE_PRICE => 'Prix libre',
  102. ];
  103. var $secret_key_payplug;
  104. const ONLINE_PAYMENT_MINIMUM_AMOUNT_DEFAULT = 25;
  105. /**
  106. * @inheritdoc
  107. */
  108. public static function tableName()
  109. {
  110. return 'producer';
  111. }
  112. /**
  113. * @inheritdoc
  114. */
  115. public function rules()
  116. {
  117. return [
  118. [['name', 'type', 'id_tax_rate_default'], 'required'],
  119. [
  120. ['tiller_provider_token', 'tiller_restaurant_token'],
  121. 'required',
  122. 'when' => function ($model) {
  123. return $model->tiller == true;
  124. }
  125. ],
  126. [
  127. [
  128. 'order_delay',
  129. 'order_deadline',
  130. 'order_delay_monday',
  131. 'order_deadline_monday',
  132. 'order_delay_tuesday',
  133. 'order_deadline_tuesday',
  134. 'order_delay_wednesday',
  135. 'order_deadline_wednesday',
  136. 'order_delay_thursday',
  137. 'order_deadline_thursday',
  138. 'order_delay_friday',
  139. 'order_deadline_friday',
  140. 'order_delay_saturday',
  141. 'order_deadline_saturday',
  142. 'order_delay_sunday',
  143. 'order_deadline_sunday',
  144. 'id_tax_rate_default',
  145. 'document_quotation_duration',
  146. 'option_dashboard_number_distributions',
  147. 'option_online_payment_minimum_amount',
  148. 'option_document_price_decimals',
  149. 'option_billing_reduction_percentage',
  150. 'option_billing_permanent_transfer_amount',
  151. ],
  152. 'integer'
  153. ],
  154. [
  155. [
  156. 'order_deadline',
  157. 'order_deadline_monday',
  158. 'order_deadline_tuesday',
  159. 'order_deadline_wednesday',
  160. 'order_deadline_thursday',
  161. 'order_deadline_friday',
  162. 'order_deadline_saturday',
  163. 'order_deadline_sunday',
  164. ],
  165. 'in',
  166. 'range' => [8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]
  167. ],
  168. ['order_delay', 'in', 'range' => [1, 2, 3, 4, 5, 6, 7]],
  169. ['option_csv_separator', 'in', 'range' => [',', ';']],
  170. [
  171. 'code',
  172. function ($attribute, $params) {
  173. $code = $this->$attribute;
  174. $producer = Producer::findOne(['code' => $code]);
  175. if ($producer && $producer->id != $this->id) {
  176. $this->addError($attribute, 'Ce code est déjà utilisé par un autre producteur.');
  177. }
  178. }
  179. ],
  180. [
  181. ['document_quotation_prefix', 'document_invoice_prefix', 'document_delivery_note_prefix'],
  182. function ($attribute, $params) {
  183. if (!ctype_upper($this->$attribute)) {
  184. $this->addError($attribute, 'Ne doit contenir que des majuscules');
  185. }
  186. }
  187. ],
  188. [
  189. [
  190. 'description',
  191. 'mentions',
  192. 'gcs',
  193. 'order_infos',
  194. 'slug',
  195. 'secret_key_payplug',
  196. 'background_color_logo',
  197. 'option_behavior_cancel_order',
  198. 'tiller_provider_token',
  199. 'tiller_restaurant_token',
  200. 'status',
  201. 'document_infos_bottom',
  202. 'document_infos_quotation',
  203. 'document_infos_invoice',
  204. 'document_infos_delivery_note',
  205. 'address',
  206. 'behavior_home_point_sale_day_list',
  207. 'behavior_order_select_distribution',
  208. 'option_payment_info',
  209. 'option_order_reference_type',
  210. 'option_order_entry_point',
  211. 'option_stripe_public_key',
  212. 'option_stripe_private_key',
  213. 'option_stripe_endpoint_secret',
  214. 'option_online_payment_type',
  215. 'option_tax_calculation_method',
  216. 'latest_version_opendistrib',
  217. 'option_csv_separator',
  218. 'option_point_sale_wording'
  219. ],
  220. 'string'
  221. ],
  222. [
  223. [
  224. 'negative_balance',
  225. 'credit',
  226. 'active',
  227. 'online_payment',
  228. 'user_manage_subscription',
  229. 'option_allow_user_gift',
  230. 'use_credit_checked_default',
  231. 'tiller',
  232. 'document_display_orders_invoice',
  233. 'document_display_orders_delivery_note',
  234. 'document_display_prices_delivery_note',
  235. 'document_display_product_description',
  236. 'option_email_confirm',
  237. 'option_email_confirm_producer',
  238. 'option_csv_export_all_products',
  239. 'option_csv_export_by_piece',
  240. 'option_export_display_product_reference',
  241. 'option_allow_order_guest',
  242. 'option_delivery',
  243. 'option_display_export_grid',
  244. 'option_stripe_mode_test',
  245. 'option_notify_producer_order_summary',
  246. 'option_billing_reduction',
  247. 'option_export_evoliz',
  248. 'option_display_message_new_opendistrib_version',
  249. 'option_billing_permanent_transfer'
  250. ],
  251. 'boolean'
  252. ],
  253. [
  254. [
  255. 'name',
  256. 'siret',
  257. 'logo',
  258. 'photo',
  259. 'postcode',
  260. 'city',
  261. 'code',
  262. 'type',
  263. 'credit_functioning',
  264. 'option_behavior_cancel_order',
  265. 'document_quotation_prefix',
  266. 'document_quotation_first_reference',
  267. 'document_invoice_prefix',
  268. 'document_invoice_first_reference',
  269. 'document_delivery_note_prefix',
  270. 'document_delivery_note_first_reference',
  271. 'option_billing_type',
  272. 'option_billing_frequency',
  273. 'option_point_sale_wording'
  274. ],
  275. 'string',
  276. 'max' => 255
  277. ],
  278. [['free_price', 'credit_limit_reminder', 'credit_limit'], 'double'],
  279. [
  280. 'free_price',
  281. 'compare',
  282. 'compareValue' => 0,
  283. 'operator' => '>=',
  284. 'type' => 'number',
  285. 'message' => 'Prix libre doit être supérieur ou égal à 0'
  286. ],
  287. [['option_dashboard_date_start', 'option_dashboard_date_end'], 'safe'],
  288. ];
  289. }
  290. /**
  291. * @inheritdoc
  292. */
  293. public function attributeLabels()
  294. {
  295. return [
  296. 'id' => 'ID',
  297. 'name' => 'Nom',
  298. 'siret' => 'Siret',
  299. 'logo' => 'Logo',
  300. 'photo' => 'Photo',
  301. 'description' => 'Description',
  302. 'postcode' => 'Code postal',
  303. 'city' => 'Ville',
  304. 'code' => "Code d'accès",
  305. 'order_delay' => 'Délai de commande',
  306. 'order_deadline' => 'Heure limite de commande',
  307. 'order_delay_monday' => 'Délai de commande (lundi)',
  308. 'order_deadline_monday' => 'Heure limite de commande (lundi)',
  309. 'order_delay_tuesday' => 'Délai de commande (mardi)',
  310. 'order_deadline_tuesday' => 'Heure limite de commande (mardi)',
  311. 'order_delay_wednesday' => 'Délai de commande (mercredi)',
  312. 'order_deadline_wednesday' => 'Heure limite de commande (mercredi)',
  313. 'order_delay_thursday' => 'Délai de commande (jeudi)',
  314. 'order_deadline_thursday' => 'Heure limite de commande (jeudi)',
  315. 'order_delay_friday' => 'Délai de commande (vendredi)',
  316. 'order_deadline_friday' => 'Heure limite de commande (vendredi)',
  317. 'order_delay_saturday' => 'Délai de commande (samedi)',
  318. 'order_deadline_saturday' => 'Heure limite de commande (samedi)',
  319. 'order_delay_sunday' => 'Délai de commande (dimanche)',
  320. 'order_deadline_sunday' => 'Heure limite de commande (dimanche)',
  321. 'negative_balance' => 'Solde négatif',
  322. 'credit' => 'Crédit pain',
  323. 'active' => 'Actif',
  324. 'date_creation' => 'Date de création',
  325. 'order_infos' => 'Informations',
  326. 'slug' => 'Slug',
  327. 'type' => 'Type de producteur',
  328. 'credit_limit_reminder' => 'Seuil de crédit limite avant relance',
  329. 'online_payment' => 'Activer le paiement en ligne (Stripe)',
  330. 'option_online_payment_type' => 'Type de paiement',
  331. 'option_stripe_mode_test' => 'Mode test',
  332. 'option_stripe_public_key' => 'Clé publique',
  333. 'option_stripe_private_key' => 'Clé secrète',
  334. 'option_stripe_endpoint_secret' => 'Clé secrète (endpoint)',
  335. 'user_manage_subscription' => 'Autoriser les utilisateurs à gérer leurs abonnements',
  336. 'mentions' => 'Mentions légales',
  337. 'gcs' => 'Conditions générales de vente',
  338. 'option_allow_user_gift' => 'Autoriser les utilisateurs à effectuer un don à la plateforme lors de leur commande',
  339. 'credit_functioning' => 'Utilisation du Crédit par l\'utilisateur',
  340. 'credit_limit' => 'Crédit limite',
  341. 'use_credit_checked_default' => 'Cocher par défaut l\'option "Utiliser mon crédit" lors de la commande de l\'utilisateur',
  342. 'background_color_logo' => 'Couleur de fond du logo',
  343. 'option_behavior_cancel_order' => 'Comportement lors de la suppression d\'une commande',
  344. 'tiller' => 'Tiller',
  345. 'tiller_provider_token' => 'Token provider',
  346. 'tiller_restaurant_token' => 'Token restaurant',
  347. 'status' => 'Statut',
  348. 'id_tax_rate_default' => 'Taxe',
  349. 'document_quotation_prefix' => 'Préfixe des devis',
  350. 'document_quotation_first_reference' => 'Première référence des devis',
  351. 'document_quotation_duration' => 'Durée du devis',
  352. 'document_invoice_prefix' => 'Préfixe des factures',
  353. 'document_invoice_first_reference' => 'Première référence des factures',
  354. 'document_delivery_note_prefix' => 'Préfixe des bons de livraison',
  355. 'document_delivery_note_first_reference' => 'Première référence des bons de livraison',
  356. 'document_infos_bottom' => 'Informations affichées en bas des documents',
  357. 'document_infos_quotation' => 'Informations affichées en bas des devis',
  358. 'document_infos_invoice' => 'Informations affichées en bas des factures',
  359. 'document_infos_delivery_note' => 'Informations affichées en bas des bons de livraison',
  360. 'address' => 'Adresse',
  361. 'document_display_orders_invoice' => 'Afficher le détail des commandes dans les factures',
  362. 'document_display_orders_delivery_note' => 'Afficher le détail des commandes dans les bons de livraison',
  363. 'document_display_prices_delivery_note' => 'Afficher le chiffrage dans les bons de livraison',
  364. 'behavior_home_point_sale_day_list' => 'Accueil : affichage des jours de distribution',
  365. 'behavior_order_select_distribution' => 'Sélection de la date de distribution',
  366. 'option_payment_info' => 'Informations liées au paiement',
  367. 'option_email_confirm' => 'Envoyer un email de confirmation au client',
  368. 'option_email_confirm_producer' => 'Envoyer un email de confirmation au producteur',
  369. 'option_dashboard_number_distributions' => 'Nombre de distributions affichées sur le tableau de board',
  370. 'option_dashboard_date_start' => 'Date de début',
  371. 'option_dashboard_date_end' => 'Date de fin',
  372. 'option_csv_export_all_products' => 'Exporter tous les produits dans le fichier récapitulatif (CSV)',
  373. 'option_csv_export_by_piece' => 'Exporter les produits par pièce dans le fichier récapitulatif (CSV)',
  374. 'option_order_reference_type' => 'Type de référence',
  375. 'option_export_display_product_reference' => 'Afficher la référence des produits au moment de l\'export',
  376. 'option_allow_order_guest' => 'Autoriser les visiteurs à passer commande (création de compte à la fin du tunnel)',
  377. 'option_order_entry_point' => 'Point d\'entrée par point de vente ou par date',
  378. 'option_delivery' => 'Proposer la livraison à domicile',
  379. 'option_display_export_grid' => 'Afficher l\'export grille dans les distributions',
  380. 'document_display_product_description' => 'Documents : afficher la description des produits',
  381. 'option_notify_producer_order_summary' => 'Recevoir les récapitulatifs de commande par email',
  382. 'option_billing_type' => 'Type de facturation',
  383. 'option_billing_frequency' => 'Fréquence de facturation',
  384. 'option_billing_reduction' => 'Réduction appliquée au moment de la facturation',
  385. 'option_tax_calculation_method' => 'Méthode de calcul de la TVA',
  386. 'option_export_evoliz' => 'Activer l\'export vers Evoliz',
  387. 'latest_version_opendistrib' => 'Dernière version d\'Opendistrib',
  388. 'option_csv_separator' => 'Séparateur de colonnes (CSV)',
  389. 'option_display_message_new_opendistrib_version' => 'Afficher les messages de mise à jour du logiciel Opendistrib',
  390. 'option_online_payment_minimum_amount' => 'Paiement en ligne : montant minimum',
  391. 'option_document_price_decimals' => 'Prix : nombre de décimales affichées',
  392. 'option_billing_reduction_percentage' => 'Réduction : pourcentage',
  393. 'option_billing_permanent_transfer' => 'Virement permanent',
  394. 'option_billing_permanent_transfer_amount' => 'Virement permanent : montant',
  395. 'option_point_sale_wording' => 'Libellé points de vente'
  396. ];
  397. }
  398. /*
  399. * Relations
  400. */
  401. public function getUserProducer()
  402. {
  403. return $this->hasMany(
  404. UserProducer::className(),
  405. ['id_producer' => 'id']
  406. );
  407. }
  408. public function getUser()
  409. {
  410. return $this->hasMany(User::className(), ['id_producer' => 'id']);
  411. }
  412. public function getContact()
  413. {
  414. return $this->hasMany(User::className(), ['id_producer' => 'id'])
  415. ->where(['status' => User::STATUS_PRODUCER]);
  416. }
  417. public function getTaxRate()
  418. {
  419. return $this->hasOne(TaxRate::className(), ['id' => 'id_tax_rate_default']);
  420. }
  421. /**
  422. * Retourne les options de base nécessaires à la fonction de recherche.
  423. *
  424. * @return array
  425. */
  426. public static function defaultOptionsSearch()
  427. {
  428. return [
  429. 'with' => ['taxRate'],
  430. 'join_with' => [],
  431. 'orderby' => 'name ASC',
  432. 'attribute_id_producer' => 'id'
  433. ];
  434. }
  435. /**
  436. * Retourne la liste des établissements pour l'initialisation d'une liste
  437. * sélective.
  438. *
  439. * @return array
  440. */
  441. public static function getProducerPopulateDropdown()
  442. {
  443. $producers = Producer::find()
  444. ->where([
  445. 'active' => true,
  446. ])
  447. ->orderBy('postcode, city ASC')
  448. ->all();
  449. $departments = Departments::get();
  450. $dataProducers = [];
  451. $optionsProducers = [];
  452. foreach ($producers as $p) {
  453. $departmentCode = substr($p->postcode, 0, 2);
  454. if (!key_exists('d' . $departmentCode, $dataProducers) && isset($departments[$departmentCode])) {
  455. $dataProducers['d' . $departmentCode] = '<strong>' . $departments[$departmentCode] . '</strong>';
  456. $optionsProducers['d' . $departmentCode] = ['disabled' => true];
  457. }
  458. $dataProducers[$p->id] = '<span class="glyphicon glyphicon-lock"></span> ' . Html::encode(
  459. $p->name
  460. ) . ' - ' . Html::encode($p->postcode) . ' ' . Html::encode(
  461. $p->city
  462. ) . ' <span class="glyphicon glyphicon-lock"></span>';
  463. if (strlen($p->code)) {
  464. $optionsProducers[$p->id] = ['class' => 'lock'];
  465. }
  466. }
  467. return ['data' => $dataProducers, 'options' => $optionsProducers];
  468. }
  469. /**
  470. * Retourne le CA de l'établissement pour un mois donné.
  471. *
  472. * @param string $period
  473. * @param boolean $format
  474. * @return string
  475. */
  476. public function getTurnover($period = '', $format = false)
  477. {
  478. if (!$period) {
  479. $period = date('Y-m');
  480. }
  481. $connection = Yii::$app->getDb();
  482. $command = $connection->createCommand(
  483. '
  484. SELECT SUM(product_order.price * product_order.quantity) AS turnover
  485. FROM `order`, product_order, distribution, product
  486. WHERE `order`.id = product_order.id_order
  487. AND distribution.id_producer = :id_producer
  488. AND `order`.id_distribution = distribution.id
  489. AND product_order.id_product = product.id
  490. AND distribution.date > :date_begin
  491. AND distribution.date < :date_end',
  492. [
  493. ':date_begin' => date('Y-m-31', strtotime("-1 month", strtotime($period))),
  494. ':date_end' => date('Y-m-01', strtotime("+1 month", strtotime($period))),
  495. ':id_producer' => $this->id
  496. ]
  497. );
  498. $result = $command->queryOne();
  499. $turnover = $result['turnover'];
  500. if ($format) {
  501. return number_format($turnover, 2) . ' €';
  502. } else {
  503. return $turnover;
  504. }
  505. }
  506. public function getAmountToBeBilledByTurnover($turnover, $format = false)
  507. {
  508. $amountToBeBilled = 0;
  509. $producerPriceRangeArray = ProducerPriceRange::find()->all();
  510. foreach($producerPriceRangeArray as $priceRange) {
  511. if($turnover >= $priceRange->range_begin && $turnover < $priceRange->range_end) {
  512. $amountToBeBilled = $priceRange->price;
  513. }
  514. }
  515. if($format) {
  516. return Price::format($amountToBeBilled, 0);
  517. }
  518. else {
  519. return $amountToBeBilled;
  520. }
  521. }
  522. public function getAmountToBeBilledByMonth($month, $format = false)
  523. {
  524. $turnover = $this->getTurnover($month);
  525. return $this->getAmountToBeBilledByTurnover($turnover, $format);
  526. }
  527. public function getSummaryAmountsToBeBilled($label, $numberOfMonths = 1)
  528. {
  529. $text = '';
  530. $numMonthCurrent = date('m');
  531. if($numberOfMonths == 1
  532. || ($numberOfMonths == 3 && (in_array($numMonthCurrent, [1, 4, 7, 10])))
  533. || ($numberOfMonths == 6 && (in_array($numMonthCurrent, [1, 7])))) {
  534. for ($i = 1; $i <= $numberOfMonths; $i++) {
  535. $month = date('Y-m', strtotime('-' . $i . ' month'));
  536. $turnover = $this->getTurnover($month);
  537. if ($turnover) {
  538. $isBold = $this->isBillingTypeClassic() && !$this->option_billing_permanent_transfer;
  539. if ($isBold) $text .= '<strong>';
  540. $text .= $this->getAmountToBeBilledByTurnover($turnover, true);
  541. if ($isBold) $text .= '</strong>';
  542. $text .= ' / '.Price::format($turnover, 0);
  543. $text .= '<br />';
  544. }
  545. }
  546. if (strlen($text)) {
  547. $text = $label . ' : <br />' . $text;
  548. }
  549. }
  550. return $text;
  551. }
  552. public function getAmountBilledLastMonth()
  553. {
  554. if($this->isBillingTypeClassic()) {
  555. $month = date('Y-m', strtotime('-1 month'));
  556. return $this->getAmountToBeBilledByMonth($month);
  557. }
  558. elseif($this->isBillingTypeFreePrice()) {
  559. return $this->free_price;
  560. }
  561. return 0;
  562. }
  563. /**
  564. * Retourne le montant à facturer pour une période donnée.
  565. *
  566. * @param string $periode
  567. * @param float $ca
  568. * @param boolean $format
  569. * @return string
  570. */
  571. public function getMAmountBilled($format = false)
  572. {
  573. if ($format) {
  574. return number_format($this->free_price, 2) . ' €';
  575. } else {
  576. return $this->free_price;
  577. }
  578. }
  579. /**
  580. * Retourne la facture d'une période donnée.
  581. *
  582. * @param string $periode
  583. * @return Facture
  584. */
  585. public function getInvoice($period = '')
  586. {
  587. if (!$period) {
  588. $period = date('Y-m', strtotime('-1 month'));
  589. }
  590. $invoice = Invoice::searchOne(
  591. ['id_producer' => $this->id, 'period' => ':period'],
  592. ['params' => [':period' => $period]]
  593. );
  594. return $invoice;
  595. }
  596. /**
  597. * Retourne la facture du mois dernier.
  598. *
  599. * @return Facture
  600. */
  601. public function getInvoiceLastMonth()
  602. {
  603. return $this->getInvoice(date('Y-m', strtotime('-1 month')));
  604. }
  605. /**
  606. * Retourne une configuration d'un établissement donné.
  607. *
  608. * @param string $config
  609. * @param integer $id_etablissement
  610. * @return mixed
  611. */
  612. public static function getConfig($config = '', $idProducer = 0)
  613. {
  614. if (strlen($config)) {
  615. if (!$idProducer) {
  616. $idProducer = GlobalParam::getCurrentProducerId();
  617. }
  618. $producer = self::findOne($idProducer);
  619. if ($producer) {
  620. return $producer->$config;
  621. }
  622. }
  623. return false;
  624. }
  625. /**
  626. * Retourne le montant de l'abonnement à prix libre définit par
  627. * le producteur.
  628. *
  629. * @param boolean $format
  630. * @return mixed
  631. */
  632. public function getFreePrice($format = true)
  633. {
  634. if (!is_null($this->free_price)) {
  635. if ($format) {
  636. return number_format($this->free_price, 2, ',', false) . ' €';
  637. } else {
  638. return $this->free_price;
  639. }
  640. }
  641. }
  642. /**
  643. * Lie un utilisateur à un producteur.
  644. *
  645. * @param integer $id_user
  646. * @param integer $id_producer
  647. * @return UserProducer
  648. */
  649. public static function addUser($idUser, $idProducer, $bookmark = 1)
  650. {
  651. $userProducer = UserProducer::searchOne([
  652. 'user_producer.id_user' => $idUser,
  653. 'user_producer.id_producer' => $idProducer
  654. ]);
  655. if (!$userProducer) {
  656. $newUserProducer = new UserProducer;
  657. $newUserProducer->id_producer = $idProducer;
  658. $newUserProducer->id_user = $idUser;
  659. $newUserProducer->credit = 0;
  660. $newUserProducer->active = 1;
  661. $newUserProducer->bookmark = (int)$bookmark;
  662. $newUserProducer->save();
  663. } else {
  664. if (!$userProducer->active) {
  665. $userProducer->active = 1;
  666. $userProducer->save();
  667. }
  668. }
  669. return $userProducer;
  670. }
  671. public function getSpecificDelays()
  672. {
  673. $array = [];
  674. $daysArray = [
  675. 'monday',
  676. 'tuesday',
  677. 'wednesday',
  678. 'thursday',
  679. 'friday',
  680. 'saturday',
  681. 'sunday'
  682. ];
  683. foreach ($daysArray as $day) {
  684. $fieldDelay = 'order_delay_' . $day;
  685. $fieldDeadline = 'order_deadline_' . $day;
  686. $delay = $this->order_delay;
  687. $deadline = $this->order_deadline;
  688. if ($this->$fieldDelay) {
  689. $delay = $this->$fieldDelay;
  690. }
  691. if ($this->$fieldDeadline) {
  692. $deadline = $this->$fieldDeadline;
  693. }
  694. $array[$day] = [
  695. 'order_delay' => $delay,
  696. 'order_deadline' => $deadline,
  697. ];
  698. }
  699. return $array;
  700. }
  701. public function hasSpecificDelays()
  702. {
  703. $daysArray = [
  704. 'monday',
  705. 'tuesday',
  706. 'wednesday',
  707. 'thursday',
  708. 'friday',
  709. 'saturday',
  710. 'sunday'
  711. ];
  712. foreach ($daysArray as $day) {
  713. $fieldDelay = 'order_delay_' . $day;
  714. $fieldDeadline = 'order_deadline_' . $day;
  715. if ($this->$fieldDelay || $this->$fieldDeadline) {
  716. return true;
  717. }
  718. }
  719. return false;
  720. }
  721. /**
  722. * Retourne le chemin vers le fichier contenant la clé secrète d'API de Stripe
  723. *
  724. * @return string
  725. */
  726. public function getFilenamePrivateKeyApiStripe()
  727. {
  728. return '../../common/config/stripe/api-' . $this->id . '.key';
  729. }
  730. public function getFilenamePrivateKeyEndpointStripe()
  731. {
  732. return '../../common/config/stripe/endpoint-' . $this->id . '.key';
  733. }
  734. public function savePrivateKeyStripe($filename, $value)
  735. {
  736. if (strlen($value) > 0) {
  737. $handle = fopen($filename, "w");
  738. fwrite($handle, $value);
  739. fclose($handle);
  740. }
  741. }
  742. public function savePrivateKeyApiStripe()
  743. {
  744. $this->savePrivateKeyStripe(
  745. $this->getFilenamePrivateKeyApiStripe(),
  746. $this->option_stripe_private_key
  747. );
  748. }
  749. public function savePrivateKeyEndpointStripe()
  750. {
  751. $this->savePrivateKeyStripe(
  752. $this->getFilenamePrivateKeyEndpointStripe(),
  753. $this->option_stripe_endpoint_secret
  754. );
  755. }
  756. /**
  757. * Retourne la clé secrète d'API de Stripe.
  758. *
  759. * @return string
  760. */
  761. public function getPrivateKeyStripe($filename)
  762. {
  763. if (file_exists($filename)) {
  764. $handle = fopen($filename, "r");
  765. $filesize = filesize($filename);
  766. if ($handle && $filesize) {
  767. $secretKey = fread($handle, $filesize);
  768. fclose($handle);
  769. return $secretKey;
  770. }
  771. }
  772. return '';
  773. }
  774. public function getPrivateKeyApiStripe()
  775. {
  776. return $this->getPrivateKeyStripe($this->getFilenamePrivateKeyApiStripe());
  777. }
  778. public function getPrivateKeyEndpointStripe()
  779. {
  780. return $this->getPrivateKeyStripe($this->getFilenamePrivateKeyEndpointStripe());
  781. }
  782. /**
  783. * Retourne le compte producteur de démonstration.
  784. *
  785. * @return Producer
  786. */
  787. public static function getDemoAccount()
  788. {
  789. $producer = Producer::find()->where('name LIKE \'Démo\'')->one();
  790. return $producer;
  791. }
  792. /**
  793. * Retourne true si le compte est un compte de démo.
  794. *
  795. * @return boolean
  796. */
  797. public function isDemo()
  798. {
  799. if (strpos($this->name, 'Démo') !== false) {
  800. return true;
  801. }
  802. return false;
  803. }
  804. public function getFullAddress($nl2br = false)
  805. {
  806. $address = '';
  807. $address .= $this->name . "\n";
  808. if (strlen($this->address)) {
  809. $address .= $this->address . "\n";
  810. }
  811. if (strlen($this->postcode) || strlen($this->city)) {
  812. $address .= $this->postcode . ' ' . $this->city;
  813. }
  814. if ($nl2br) {
  815. $address = nl2br($address);
  816. }
  817. return $address;
  818. }
  819. public function getHtmlLogo()
  820. {
  821. $html = '';
  822. if (strlen($this->logo)) {
  823. $html = '<img src="' . $this->getUrlLogo() . '" class="producer-logo" />';
  824. }
  825. return $html;
  826. }
  827. public function getUrlLogo()
  828. {
  829. return Yii::$app->urlManagerProducer->getHostInfo(
  830. ) . '/' . Yii::$app->urlManagerProducer->baseUrl . '/uploads/' . $this->logo;
  831. }
  832. public function getEmailOpendistrib()
  833. {
  834. return $this->slug . '@opendistrib.net';
  835. }
  836. public function getMainContact()
  837. {
  838. if ($this->contact) {
  839. foreach ($this->contact as $contact) {
  840. if ($contact->is_main_contact) {
  841. return $contact;
  842. }
  843. }
  844. }
  845. return false;
  846. }
  847. public function isOnlinePaymentActive()
  848. {
  849. return $this->online_payment || ($this->option_stripe_mode_test && !Yii::$app->user->isGuest && Yii::$app->user->identity->status > 10);
  850. }
  851. public function isOnlinePaymentActiveAndTypeOrder()
  852. {
  853. return $this->isOnlinePaymentActive() && $this->option_online_payment_type == 'order' ;
  854. }
  855. public static function getBillingFrequencyPopulateDropdown()
  856. {
  857. return self::$billingFrequencyArray;
  858. }
  859. public function isBillingFrequencyMonthly()
  860. {
  861. return $this->option_billing_frequency == self::BILLING_FREQUENCY_MONTHLY;
  862. }
  863. public function isBillingFrequencyQuarterly()
  864. {
  865. return $this->option_billing_frequency == self::BILLING_FREQUENCY_QUARTERLY;
  866. }
  867. public function isBillingFrequencyBiannual()
  868. {
  869. return $this->option_billing_frequency == self::BILLING_FREQUENCY_BIANNUAL;
  870. }
  871. public static function getBillingTypePopulateDropdown()
  872. {
  873. return self::$billingTypeArray;
  874. }
  875. public function isBillingTypeClassic()
  876. {
  877. return $this->option_billing_type == self::BILLING_TYPE_CLASSIC;
  878. }
  879. public function isBillingTypeFreePrice()
  880. {
  881. return $this->option_billing_type == self::BILLING_TYPE_FREE_PRICE;
  882. }
  883. public function isUpToDateWithOpendistribVersion()
  884. {
  885. return $this->latest_version_opendistrib == GlobalParam::getOpendistribVersion();
  886. }
  887. public function updateOpendistribVersion() {
  888. $versionsArray = Opendistrib::getVersions();
  889. $this->latest_version_opendistrib = array_values($versionsArray)[0];
  890. $this->save();
  891. }
  892. public function getOnlinePaymentMinimumAmount()
  893. {
  894. $onlinePaymentMinimumAmount = self::getConfig('option_online_payment_minimum_amount');
  895. if(!$onlinePaymentMinimumAmount) {
  896. $onlinePaymentMinimumAmount = self::ONLINE_PAYMENT_MINIMUM_AMOUNT_DEFAULT;
  897. }
  898. return $onlinePaymentMinimumAmount;
  899. }
  900. public function getPointSaleWording()
  901. {
  902. if($this->option_point_sale_wording && strlen($this->option_point_sale_wording)) {
  903. return Html::encode($this->option_point_sale_wording);
  904. }
  905. return 'Points de vente';
  906. }
  907. }