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.

280 lines
9.4KB

  1. <?php
  2. /**
  3. * Copyright Souke (2018)
  4. *
  5. * contact@souke.fr
  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 domain\Product\Product;
  38. use common\components\ActiveRecordCommon;
  39. use common\helpers\GlobalParam;
  40. use domain\Config\TaxRate\TaxRate;
  41. use domain\Distribution\ProductDistribution\ProductDistribution;
  42. use domain\Producer\Producer\Producer;
  43. use domain\Product\Accessory\Accessory;
  44. use domain\Product\ProductAccessory\ProductAccessory;
  45. use domain\Product\ProductCategory\ProductCategory;
  46. use domain\Product\ProductPointSale\ProductPointSale;
  47. use domain\Product\ProductPrice\Model\ProductPrice;
  48. use domain\Subscription\ProductSubscription\ProductSubscription;
  49. use domain\_\StatusInterface;
  50. use yii\db\ActiveQuery;
  51. use yii\web\UploadedFile;
  52. /**
  53. * This is the model class for table "product".
  54. *
  55. */
  56. class Product extends ActiveRecordCommon implements StatusInterface
  57. {
  58. public $total = 0;
  59. public $apply_distributions = true;
  60. public $price_with_tax = 0;
  61. public $wording_unit = '';
  62. public $pointsSale;
  63. /**
  64. * @var UploadedFile
  65. */
  66. public $photoFile;
  67. public static $unitsArray = [
  68. 'piece' => [
  69. 'unit' => 'piece',
  70. 'wording_unit' => 'la pièce',
  71. 'wording' => 'pièce(s)',
  72. 'wording_short' => 'p.',
  73. 'coefficient' => 1
  74. ],
  75. 'g' => [
  76. 'ref_unit' => 'kg',
  77. 'unit' => 'g',
  78. 'wording_unit' => 'le g',
  79. 'wording' => 'g',
  80. 'wording_short' => 'g',
  81. 'coefficient' => 1000
  82. ],
  83. 'kg' => [
  84. 'unit' => 'kg',
  85. 'wording_unit' => 'le kg',
  86. 'wording' => 'kg',
  87. 'wording_short' => 'kg',
  88. 'coefficient' => 1
  89. ],
  90. 'mL' => [
  91. 'ref_unit' => 'L',
  92. 'unit' => 'mL',
  93. 'wording_unit' => 'le mL',
  94. 'wording' => 'mL',
  95. 'wording_short' => 'mL',
  96. 'coefficient' => 1000
  97. ],
  98. 'L' => [
  99. 'unit' => 'L',
  100. 'wording_unit' => 'le litre',
  101. 'wording' => 'L',
  102. 'wording_short' => 'L',
  103. 'coefficient' => 1
  104. ],
  105. ];
  106. /**
  107. * @inheritdoc
  108. */
  109. public static function tableName()
  110. {
  111. return 'product';
  112. }
  113. /**
  114. * @inheritdoc
  115. */
  116. public function rules()
  117. {
  118. return [
  119. [['name', 'id_producer'], 'required'],
  120. [['order', 'id_producer', 'id_tax_rate', 'id_product_category', 'status'], 'integer'],
  121. [['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday', 'unavailable', 'apply_distributions', 'available_on_points_sale', 'is_available_for_subscriptions'], 'boolean'],
  122. [['price', 'weight', 'step', 'quantity_max', 'quantity_max_monday', 'quantity_max_tuesday', 'quantity_max_wednesday', 'quantity_max_thursday', 'quantity_max_friday', 'quantity_max_saturday', 'quantity_max_sunday'], 'number'],
  123. [['photoFile'], 'file', 'extensions' => 'png, jpg, jpeg', 'mimeTypes' => 'image/png, image/jpeg'],
  124. [['name', 'reference', 'description', 'photo', 'unit'], 'string', 'max' => 255],
  125. [['recipe'], 'string', 'max' => 1000],
  126. ['step', 'required', 'message' => 'Champs obligatoire', 'when' => function ($model) {
  127. if ($model->unit != 'piece') {
  128. return true;
  129. }
  130. return false;
  131. }],
  132. [['price_with_tax', 'wording_unit', 'pointsSale'], 'safe']
  133. ];
  134. }
  135. /**
  136. * @inheritdoc
  137. */
  138. public function attributeLabels()
  139. {
  140. return [
  141. 'id' => 'ID',
  142. 'name' => 'Nom',
  143. 'reference' => 'Référence',
  144. 'description' => 'Description',
  145. 'photoFile' => 'Photo',
  146. 'price' => 'Prix (€) TTC',
  147. 'weight' => 'Poids',
  148. 'recipe' => 'Recette',
  149. 'monday' => 'Lundi',
  150. 'tuesday' => 'Mardi',
  151. 'wednesday' => 'Mercredi',
  152. 'thursday' => 'Jeudi',
  153. 'friday' => 'Vendredi',
  154. 'saturday' => 'Samedi',
  155. 'sunday' => 'Dimanche',
  156. 'order' => 'Ordre',
  157. 'quantity_max' => 'Par défaut',
  158. 'quantity_max_monday' => 'Lundi',
  159. 'quantity_max_tuesday' => 'Mardi',
  160. 'quantity_max_wednesday' => 'Mercredi',
  161. 'quantity_max_thursday' => 'Jeudi',
  162. 'quantity_max_friday' => 'Vendredi',
  163. 'quantity_max_saturday' => 'Samedi',
  164. 'quantity_max_sunday' => 'Dimanche',
  165. 'unavailable' => 'Épuisé',
  166. 'apply_distributions' => 'Appliquer ces modifications dans les distributions à venir',
  167. 'unit' => 'Unité',
  168. 'step' => 'Pas',
  169. 'id_tax_rate' => 'TVA',
  170. 'id_product_category' => 'Catégorie',
  171. 'available_on_points_sale' => 'Par défaut',
  172. 'status' => 'Actif',
  173. 'is_available_for_subscriptions' => 'Disponible pour les abonnements'
  174. ];
  175. }
  176. public function afterFind()
  177. {
  178. // @TODO : à optimiser en rendant obligatoire le champs taxrate au niveau des produits pour ne pas avoir à la
  179. // charger depuis le producteur si elle n'est pas définie
  180. if ($this->taxRate == null) {
  181. if(GlobalParam::getCurrentProducerId() && $this->id_producer == GlobalParam::getCurrentProducerId()) {
  182. $producer = GlobalParam::getCurrentProducer();
  183. }
  184. else {
  185. $producer = Producer::searchOne(['id' => $this->id_producer]);
  186. }
  187. if ($producer) {
  188. $this->populateRelation('taxRate', $producer->taxRate);
  189. }
  190. }
  191. parent::afterFind();
  192. $productSolver = ProductSolver::getInstance();
  193. $this->wording_unit = $productSolver->strUnit($this);
  194. $this->price_with_tax = $productSolver->getPriceWithTax($this);
  195. }
  196. /* Getters / Setters */
  197. public function getProductAccessories(): array
  198. {
  199. return $this->productAccessoriesRelation;
  200. }
  201. /* Relations */
  202. public function getProductDistribution()
  203. {
  204. return $this->hasMany(ProductDistribution::class, ['id_product' => 'id']);
  205. }
  206. public function getProductSubscription()
  207. {
  208. return $this->hasMany(ProductSubscription::class, ['id_product' => 'id']);
  209. }
  210. public function getTaxRate()
  211. {
  212. return $this->hasOne(TaxRate::class, ['id' => 'id_tax_rate']);
  213. }
  214. public function populateTaxRate(TaxRate $taxRate): void
  215. {
  216. $this->populateFieldObject('id_tax_rate', 'taxRate', $taxRate);
  217. }
  218. public function getProductPrice()
  219. {
  220. return $this->hasMany( ProductPrice::class, ['id_product' => 'id']);
  221. }
  222. public function getProductCategory()
  223. {
  224. return $this->hasOne( ProductCategory::class, ['id' => 'id_product_category']);
  225. }
  226. public function populateProductCategory(ProductCategory $productCategory): void
  227. {
  228. $this->populateFieldObject('id_product_category', 'productCategory', $productCategory);
  229. }
  230. public function getProductPointSale()
  231. {
  232. return $this->hasMany(ProductPointSale::class, ['id_product' => 'id']);
  233. }
  234. public function getProductAccessoriesRelation(): ActiveQuery
  235. {
  236. return $this->hasMany(ProductAccessory::class, ['id_product' => 'id']);
  237. }
  238. /* Méthodes */
  239. public function hasAccessory(): bool
  240. {
  241. return $this->getProductAccessories() && count($this->getProductAccessories());
  242. }
  243. /**
  244. * Enregistre le produit.
  245. */
  246. public function save($runValidation = true, $attributeNames = NULL)
  247. {
  248. $this->id_producer = GlobalParam::getCurrentProducerId();
  249. return parent::save($runValidation, $attributeNames);
  250. }
  251. }