[ 'unit' => 'piece', 'wording_unit' => 'la pièce', 'wording' => 'pièce(s)', 'wording_short' => 'p.', 'coefficient' => 1 ], 'g' => [ 'ref_unit' => 'kg', 'unit' => 'g', 'wording_unit' => 'le g', 'wording' => 'g', 'wording_short' => 'g', 'coefficient' => 1000 ], 'kg' => [ 'unit' => 'kg', 'wording_unit' => 'le kg', 'wording' => 'kg', 'wording_short' => 'kg', 'coefficient' => 1 ], 'mL' => [ 'ref_unit' => 'L', 'unit' => 'mL', 'wording_unit' => 'le mL', 'wording' => 'mL', 'wording_short' => 'mL', 'coefficient' => 1000 ], 'L' => [ 'unit' => 'L', 'wording_unit' => 'le litre', 'wording' => 'L', 'wording_short' => 'L', 'coefficient' => 1 ], ]; /** * @inheritdoc */ public static function tableName() { return 'product'; } /** * @inheritdoc */ public function rules() { return [ [['name', 'id_producer'], 'required'], [['active', 'order', 'id_producer', 'id_tax_rate', 'id_product_category'], 'integer'], [['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday', 'unavailable', 'apply_distributions', 'available_on_points_sale'], 'boolean'], [['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'], [['photo'], 'file'], [['name', 'reference', 'description', 'photo', 'unit'], 'string', 'max' => 255], [['recipe'], 'string', 'max' => 1000], ['step', 'required', 'message' => 'Champs obligatoire', 'when' => function ($model) { if ($model->unit != 'piece') { return true; } return false; }], [['price_with_tax', 'wording_unit', 'pointsSale'], 'safe'] ]; } /** * @inheritdoc */ public function attributeLabels() { return [ 'id' => 'ID', 'name' => 'Nom', 'reference' => 'Référence', 'description' => 'Description', 'active' => 'Actif', 'photo' => 'Photo', 'price' => 'Prix (€) TTC', 'weight' => 'Poids', 'recipe' => 'Recette', 'monday' => 'Lundi', 'tuesday' => 'Mardi', 'wednesday' => 'Mercredi', 'thursday' => 'Jeudi', 'friday' => 'Vendredi', 'saturday' => 'Samedi', 'sunday' => 'Dimanche', 'order' => 'Ordre', 'quantity_max' => 'Quantité max par défaut', 'quantity_max_monday' => 'Quantité max : lundi', 'quantity_max_tuesday' => 'Quantité max : mardi', 'quantity_max_wednesday' => 'Quantité max : mercredi', 'quantity_max_thursday' => 'Quantité max : jeudi', 'quantity_max_friday' => 'Quantité max : vendredi', 'quantity_max_saturday' => 'Quantité max : samedi', 'quantity_max_sunday' => 'Quantité max : dimanche', 'unavailable' => 'Épuisé', 'apply_distributions' => 'Appliquer ces modifications dans les distributions futures', 'unit' => 'Unité', 'step' => 'Pas', 'id_tax_rate' => 'TVA', 'id_product_category' => 'Catégorie', 'available_on_points_sale' => 'Par défaut' ]; } public function afterFind() { if ($this->taxRate == null) { $producer = Producer::searchOne(['id' => GlobalParam::getCurrentProducerId()]); if ($producer) { $this->populateRelation('taxRate', $producer->taxRate); } } $this->wording_unit = Product::strUnit($this->unit); $this->price_with_tax = $this->getPriceWithTax(); parent::afterFind(); } public function getProductDistribution() { return $this->hasMany(ProductDistribution::className(), ['id_product' => 'id']); } public function getProductSubscription() { return $this->hasMany(ProductSubscription::className(), ['id_product' => 'id']); } public function getTaxRate() { return $this->hasOne(TaxRate::className(), ['id' => 'id_tax_rate']); } public function getProductPrice() { return $this->hasMany(ProductPrice::className(), ['id_product' => 'id']); } public function getProductCategory() { return $this->hasOne(ProductCategory::className(), ['id' => 'id_product_category']); } public function getProductPointSale() { return $this->hasMany(ProductPointSale::className(), ['id_product' => 'id']); } /** * Retourne les options de base nécessaires à la fonction de recherche. * * @return array */ public static function defaultOptionsSearch() { return [ 'with' => ['taxRate', 'productPointSale'], 'join_with' => [], 'orderby' => 'order ASC', 'attribute_id_producer' => 'product.id_producer' ]; } public function isAvailableOnPointSale($pointSale) { if(!$pointSale) { return false; } // disponible par défaut if ($this->available_on_points_sale) { foreach ($this->productPointSale as $productPointSale) { if ($pointSale->id == $productPointSale->id_point_sale //&& $productPointSale->id_product == $this->id && !$productPointSale->available) { return false; } } return true; } // indisponible par défaut else { foreach ($this->productPointSale as $productPointSale) { if ($pointSale->id == $productPointSale->id_point_sale //&& $productPointSale->id_product == $this->id && $productPointSale->available) { return true; } } return false; } } /** * Retourne la description du produit. * * @return string */ public function getDescription() { $description = $this->description; if (isset($this->weight) && is_numeric($this->weight) && $this->weight > 0) { if ($this->weight >= 1000) { $description .= ' (' . ($this->weight / 1000) . 'kg)'; } else { $description .= ' (' . $this->weight . 'g)'; } } return $description; } /** * Retourne le libellé (admin) du produit. * @return type */ public function getStrWordingAdmin() { return $this->name; } /** * Enregistre le produit. * * @param boolean $runValidation * @param array $attributeNames * @return boolean */ public function save($runValidation = true, $attributeNames = NULL) { $this->id_producer = GlobalParam::getCurrentProducerId(); return parent::save($runValidation, $attributeNames); } /** * Retourne les produits d'une production donnée. * * @param integer $idDistribution * @return array */ public static function searchByDistribution($idDistribution) { return Product::find() ->leftJoin('product_distribution', 'product.id = product_distribution.id_product') ->where([ 'id_producer' => GlobalParam::getCurrentProducerId(), 'product_distribution.id_distribution' => $idDistribution ]) ->orderBy('product_distribution.active DESC, product.order ASC') ->all(); } /** * Retourne le nombre de produits du producteur courant. * * @return integer */ public static function count() { return self::searchCount(); } /** * Retourne le produit "Don". * * @return Product */ public static function getProductGift() { $productGift = Product::find() ->where([ 'product.id_producer' => 0 ]) ->andFilterWhere(['like', 'product.name', 'Don']) ->one(); return $productGift; } public function getRefUnit($unit) { if (isset(self::$unitsArray[$unit]) && isset(self::$unitsArray[$unit]['ref_unit'])) { return self::$unitsArray[$unit]['ref_unit']; } return $unit; } /** * Retourne le libellé d'une unité. * * @param $format wording_unit, wording, short * @param $unitInDb Unité stockée en base de données (ex: si g > kg, si mL > L) * @return $string Libellé de l'unité */ public static function strUnit($unit, $format = 'wording_short', $unitInDb = false) { $strUnit = ''; if ($unitInDb) { if ($unit == 'g') { $unit = 'kg'; } if ($unit == 'mL') { $unit = 'L'; } } if (isset(self::$unitsArray[$unit]) && isset(self::$unitsArray[$unit][$format])) { $strUnit = self::$unitsArray[$unit][$format]; } return $strUnit; } public function getPriceArray($user, $pointSale) { $priceArray = []; $userProducer = null; if ($user) { $userProducer = UserProducer::searchOne([ 'id_user' => $user->id, ]); } // specific prices $specificPriceArray = $this->getSpecificPricesFilterByPriorityMatch( $this->productPrice, $user, $pointSale ); foreach ($specificPriceArray as $specificPrice) { $priceArray[] = [ 'from_quantity' => $specificPrice->from_quantity ? $specificPrice->from_quantity : 0, 'price' => number_format($this->getPrice([ 'user' => $user, 'user_producer' => $userProducer, 'point_sale' => $pointSale, 'quantity' => $specificPrice->from_quantity ]), 3), 'price_with_tax' => number_format($this->getPriceWithTax([ 'user' => $user, 'user_producer' => $userProducer, 'point_sale' => $pointSale, 'quantity' => $specificPrice->from_quantity ]), 2), ]; } if (!$this->hasPriceWithQuantityZero($priceArray)) { // base price $priceArray[] = [ 'from_quantity' => 0, 'price' => $this->getPrice(), 'price_with_tax' => $this->getPriceWithTax(), ]; } usort($priceArray, function ($a, $b) { if ($a['price'] < $b['price']) { return 1; } elseif ($a['price'] > $b['price']) { return -1; } else { return 0; } }); return $priceArray; } public function hasPriceWithQuantityZero($priceArray) { foreach ($priceArray as $price) { if ($price['from_quantity'] == 0) { return true; } } return false; } public function getSpecificPricesFilterByPriorityMatch($specificPrices, $user, $pointSale) { $priorityMatchSpecificPrice = ProductPrice::getPriorityMatchOfSpecificPriceArray($specificPrices, $user, $pointSale); $specificPricesFilter = []; foreach ($specificPrices as $keySpecificPrice => $specificPrice) { if (($priorityMatchSpecificPrice && $specificPrice->$priorityMatchSpecificPrice($user, $pointSale)) || $specificPrice->matchFromQuantityOnly()) { $specificPricesFilter[] = $specificPrice; } } return $specificPricesFilter; } public function getPrice($params = []) { $specificPrices = $this->productPrice; $user = isset($params['user']) ? $params['user'] : false; $userProducer = isset($params['user_producer']) ? $params['user_producer'] : false; $pointSale = isset($params['point_sale']) ? $params['point_sale'] : false; $quantity = (isset($params['quantity']) && $params['quantity']) ? $params['quantity'] : 1; if ($specificPrices && ($user || $pointSale)) { $specificPrices = $this->getSpecificPricesFilterByPriorityMatch($specificPrices, $user, $pointSale); $bestPrice = 9999; foreach ($specificPrices as $specificPrice) { $fromQuantity = $specificPrice->from_quantity; if ((($fromQuantity && $fromQuantity <= $quantity) || !$fromQuantity) && $specificPrice->price < $bestPrice) { $bestPrice = $specificPrice->price; } } if ($bestPrice != 9999) { return $bestPrice; } } if ($userProducer && $userProducer->product_price_percent) { return $this->price * (1 + $userProducer->product_price_percent / 100); } if ($pointSale && $pointSale->product_price_percent) { return $this->price * (1 + $pointSale->product_price_percent / 100); } return $this->price; } /** * Retourne le prix du produit avec taxe */ public function getPriceWithTax($params = []) { $taxRateValue = $this->taxRate ? $this->taxRate->value : 0; return Price::getPriceWithTax($this->getPrice($params), $taxRateValue); } public function getTheTaxRate() { if ($this->id_tax_rate) { return $this->id_tax_rate; } else { return GlobalParam::getCurrentProducer()->taxRate->id; } } public function getNameExport() { $producer = GlobalParam::getCurrentProducer(); if ($producer->option_export_display_product_reference && $this->reference && strlen($this->reference) > 0) { return $this->reference; } return $this->name; } }