' . '
  • Optionnelle : l\'utilisateur choisit s\'il utilise son Crédit ou non. Les commandes peuvent être payées ou impayées.
  • ' . '
  • Obligatoire : toutes les commandes de l\'utilisateur son comptabilisées au niveau du Crédit. Toutes les commandes sont payées.
  • ' . '
  • 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.
  • ' . ''; public static $creditFunctioningArray = [ self::CREDIT_FUNCTIONING_MANDATORY => 'Obligatoire', self::CREDIT_FUNCTIONING_OPTIONAL => 'Optionnelle', self::CREDIT_FUNCTIONING_USER => 'Basée sur l\'utilisateur', ]; const BEHAVIOR_DELETE_ORDER_DELETE = 'delete'; const BEHAVIOR_DELETE_ORDER_STATUS = 'status'; const BEHAVIOR_HOME_POINT_SALE_DAY_LIST_WEEK = 'days-of-week'; const BEHAVIOR_HOME_POINT_SALE_DAY_LIST_INCOMING_DISTRIBUTIONS = 'incoming-distributions'; const BEHAVIOR_ORDER_SELECT_DISTRIBUTION_CALENDAR = 'calendar'; const BEHAVIOR_ORDER_SELECT_DISTRIBUTION_LIST = 'list'; const ORDER_REFERENCE_TYPE_NONE = ''; const ORDER_REFERENCE_TYPE_YEARLY = 'yearly'; const ORDER_ENTRY_POINT_DATE = 'date'; const ORDER_ENTRY_POINT_POINT_SALE = 'point-sale'; const BILLING_FREQUENCY_MONTHLY = 'monthly'; const BILLING_FREQUENCY_QUARTERLY = 'quarterly'; const BILLING_FREQUENCY_BIANNUAL = 'biannual'; public static $billingFrequencyArray = [ self::BILLING_FREQUENCY_MONTHLY => 'Mensuelle', self::BILLING_FREQUENCY_QUARTERLY => 'Trimestrielle', self::BILLING_FREQUENCY_BIANNUAL => 'Biannuelle', ]; const BILLING_TYPE_CLASSIC = 'classic'; const BILLING_TYPE_FREE_PRICE = 'free-price'; public static $billingTypeArray = [ self::BILLING_TYPE_CLASSIC => 'Classique', self::BILLING_TYPE_FREE_PRICE => 'Prix libre', ]; var $secret_key_payplug; /** * @inheritdoc */ public static function tableName() { return 'producer'; } /** * @inheritdoc */ public function rules() { return [ [['name', 'type', 'id_tax_rate_default'], 'required'], [ ['tiller_provider_token', 'tiller_restaurant_token'], 'required', 'when' => function ($model) { return $model->tiller == true; } ], [ [ 'order_delay', 'order_deadline', 'order_delay_monday', 'order_deadline_monday', 'order_delay_tuesday', 'order_deadline_tuesday', 'order_delay_wednesday', 'order_deadline_wednesday', 'order_delay_thursday', 'order_deadline_thursday', 'order_delay_friday', 'order_deadline_friday', 'order_delay_saturday', 'order_deadline_saturday', 'order_delay_sunday', 'order_deadline_sunday', 'id_tax_rate_default', 'document_quotation_duration', 'option_dashboard_number_distributions' ], 'integer' ], [ [ 'order_deadline', 'order_deadline_monday', 'order_deadline_tuesday', 'order_deadline_wednesday', 'order_deadline_thursday', 'order_deadline_friday', 'order_deadline_saturday', 'order_deadline_sunday', ], 'in', 'range' => [8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24] ], ['order_delay', 'in', 'range' => [1, 2, 3, 4, 5, 6, 7]], [ 'code', function ($attribute, $params) { $code = $this->$attribute; $producer = Producer::findOne(['code' => $code]); if ($producer && $producer->id != $this->id) { $this->addError($attribute, 'Ce code est déjà utilisé par un autre producteur.'); } } ], [ ['document_quotation_prefix', 'document_invoice_prefix', 'document_delivery_note_prefix'], function ($attribute, $params) { if (!ctype_upper($this->$attribute)) { $this->addError($attribute, 'Ne doit contenir que des majuscules'); } } ], [ [ 'description', 'mentions', 'gcs', 'order_infos', 'slug', 'secret_key_payplug', 'background_color_logo', 'option_behavior_cancel_order', 'tiller_provider_token', 'tiller_restaurant_token', 'status', 'document_infos_bottom', 'document_infos_quotation', 'document_infos_invoice', 'document_infos_delivery_note', 'address', 'behavior_home_point_sale_day_list', 'behavior_order_select_distribution', 'option_payment_info', 'option_order_reference_type', 'option_order_entry_point', 'option_stripe_public_key', 'option_stripe_private_key', 'option_stripe_endpoint_secret', 'option_online_payment_type', 'option_tax_calculation_method', 'latest_version_opendistrib' ], 'string' ], [ [ 'negative_balance', 'credit', 'active', 'online_payment', 'user_manage_subscription', 'option_allow_user_gift', 'use_credit_checked_default', 'tiller', 'document_display_orders_invoice', 'document_display_orders_delivery_note', 'document_display_prices_delivery_note', 'document_display_product_description', 'option_email_confirm', 'option_email_confirm_producer', 'option_csv_export_all_products', 'option_csv_export_by_piece', 'option_export_display_product_reference', 'option_allow_order_guest', 'option_delivery', 'option_display_export_grid', 'option_stripe_mode_test', 'option_notify_producer_order_summary', 'option_billing_reduction', 'option_export_evoliz' ], 'boolean' ], [ [ 'name', 'siret', 'logo', 'photo', 'postcode', 'city', 'code', 'type', 'credit_functioning', 'option_behavior_cancel_order', 'document_quotation_prefix', 'document_quotation_first_reference', 'document_invoice_prefix', 'document_invoice_first_reference', 'document_delivery_note_prefix', 'document_delivery_note_first_reference', 'option_billing_type', 'option_billing_frequency', ], 'string', 'max' => 255 ], [['free_price', 'credit_limit_reminder', 'credit_limit'], 'double'], [ 'free_price', 'compare', 'compareValue' => 0, 'operator' => '>=', 'type' => 'number', 'message' => 'Prix libre doit être supérieur ou égal à 0' ], [['option_dashboard_date_start', 'option_dashboard_date_end'], 'safe'], ]; } /** * @inheritdoc */ public function attributeLabels() { return [ 'id' => 'ID', 'name' => 'Nom', 'siret' => 'Siret', 'logo' => 'Logo', 'photo' => 'Photo', 'description' => 'Description', 'postcode' => 'Code postal', 'city' => 'Ville', 'code' => "Code d'accès", 'order_delay' => 'Délai de commande', 'order_deadline' => 'Heure limite de commande', 'order_delay_monday' => 'Délai de commande (lundi)', 'order_deadline_monday' => 'Heure limite de commande (lundi)', 'order_delay_tuesday' => 'Délai de commande (mardi)', 'order_deadline_tuesday' => 'Heure limite de commande (mardi)', 'order_delay_wednesday' => 'Délai de commande (mercredi)', 'order_deadline_wednesday' => 'Heure limite de commande (mercredi)', 'order_delay_thursday' => 'Délai de commande (jeudi)', 'order_deadline_thursday' => 'Heure limite de commande (jeudi)', 'order_delay_friday' => 'Délai de commande (vendredi)', 'order_deadline_friday' => 'Heure limite de commande (vendredi)', 'order_delay_saturday' => 'Délai de commande (samedi)', 'order_deadline_saturday' => 'Heure limite de commande (samedi)', 'order_delay_sunday' => 'Délai de commande (dimanche)', 'order_deadline_sunday' => 'Heure limite de commande (dimanche)', 'negative_balance' => 'Solde négatif', 'credit' => 'Crédit pain', 'active' => 'Actif', 'date_creation' => 'Date de création', 'order_infos' => 'Informations', 'slug' => 'Slug', 'type' => 'Type de producteur', 'credit_limit_reminder' => 'Seuil de crédit limite avant relance', 'online_payment' => 'Activer le paiement en ligne (Stripe)', 'option_online_payment_type' => 'Type de paiement', 'option_stripe_mode_test' => 'Mode test', 'option_stripe_public_key' => 'Clé publique', 'option_stripe_private_key' => 'Clé secrète', 'option_stripe_endpoint_secret' => 'Clé secrète (endpoint)', 'user_manage_subscription' => 'Autoriser les utilisateurs à gérer leurs abonnements', 'mentions' => 'Mentions légales', 'gcs' => 'Conditions générales de vente', 'option_allow_user_gift' => 'Autoriser les utilisateurs à effectuer un don à la plateforme lors de leur commande', 'credit_functioning' => 'Utilisation du Crédit par l\'utilisateur', 'credit_limit' => 'Crédit limite', 'use_credit_checked_default' => 'Cocher par défaut l\'option "Utiliser mon crédit" lors de la commande de l\'utilisateur', 'background_color_logo' => 'Couleur de fond du logo', 'option_behavior_cancel_order' => 'Comportement lors de la suppression d\'une commande', 'tiller' => 'Tiller', 'tiller_provider_token' => 'Token provider', 'tiller_restaurant_token' => 'Token restaurant', 'status' => 'Statut', 'id_tax_rate_default' => 'Taxe', 'document_quotation_prefix' => 'Préfixe des devis', 'document_quotation_first_reference' => 'Première référence des devis', 'document_quotation_duration' => 'Durée du devis', 'document_invoice_prefix' => 'Préfixe des factures', 'document_invoice_first_reference' => 'Première référence des factures', 'document_delivery_note_prefix' => 'Préfixe des bons de livraison', 'document_delivery_note_first_reference' => 'Première référence des bons de livraison', 'document_infos_bottom' => 'Informations affichées en bas des documents', 'document_infos_quotation' => 'Informations affichées en bas des devis', 'document_infos_invoice' => 'Informations affichées en bas des factures', 'document_infos_delivery_note' => 'Informations affichées en bas des bons de livraison', 'address' => 'Adresse', 'document_display_orders_invoice' => 'Afficher le détail des commandes dans les factures', 'document_display_orders_delivery_note' => 'Afficher le détail des commandes dans les bons de livraison', 'document_display_prices_delivery_note' => 'Afficher le chiffrage dans les bons de livraison', 'behavior_home_point_sale_day_list' => 'Accueil : affichage des jours de distribution', 'behavior_order_select_distribution' => 'Sélection de la date de distribution', 'option_payment_info' => 'Informations liées au paiement', 'option_email_confirm' => 'Envoyer un email de confirmation au client', 'option_email_confirm_producer' => 'Envoyer un email de confirmation au producteur', 'option_dashboard_number_distributions' => 'Nombre de distributions affichées sur le tableau de board', 'option_dashboard_date_start' => 'Date de début', 'option_dashboard_date_end' => 'Date de fin', 'option_csv_export_all_products' => 'Exporter tous les produits dans le fichier récapitulatif (CSV)', 'option_csv_export_by_piece' => 'Exporter les produits par pièce dans le fichier récapitulatif (CSV)', 'option_order_reference_type' => 'Type de référence', 'option_export_display_product_reference' => 'Afficher la référence des produits au moment de l\'export', 'option_allow_order_guest' => 'Autoriser les visiteurs à passer commande (création de compte à la fin du tunnel)', 'option_order_entry_point' => 'Point d\'entrée par point de vente ou par date', 'option_delivery' => 'Proposer la livraison à domicile', 'option_display_export_grid' => 'Afficher l\'export grille dans les distributions', 'document_display_product_description' => 'Documents : afficher la description des produits', 'option_notify_producer_order_summary' => 'Recevoir les récapitulatifs de commande par email', 'option_billing_type' => 'Type de facturation', 'option_billing_frequency' => 'Fréquence de facturation', 'option_billing_reduction' => 'Réduction appliquée au moment de la facturation', 'option_tax_calculation_method' => 'Méthode de calcul de la TVA', 'option_export_evoliz' => 'Activer l\'export vers Evoliz', 'latest_version_opendistrib' => 'Dernière version d\'Opendistrib', ]; } /* * Relations */ public function getUserProducer() { return $this->hasMany( UserProducer::className(), ['id_producer' => 'id'] ); } public function getUser() { return $this->hasMany(User::className(), ['id_producer' => 'id']); } public function getContact() { return $this->hasMany(User::className(), ['id_producer' => 'id']) ->where(['status' => User::STATUS_PRODUCER]); } public function getTaxRate() { return $this->hasOne(TaxRate::className(), ['id' => 'id_tax_rate_default']); } /** * Retourne les options de base nécessaires à la fonction de recherche. * * @return array */ public static function defaultOptionsSearch() { return [ 'with' => ['taxRate'], 'join_with' => [], 'orderby' => 'name ASC', 'attribute_id_producer' => 'id' ]; } /** * Retourne la liste des établissements pour l'initialisation d'une liste * sélective. * * @return array */ public static function getProducerPopulateDropdown() { $producers = Producer::find() ->where([ 'active' => true, ]) ->orderBy('postcode, city ASC') ->all(); $departments = Departments::get(); $dataProducers = []; $optionsProducers = []; foreach ($producers as $p) { $departmentCode = substr($p->postcode, 0, 2); if (!key_exists('d' . $departmentCode, $dataProducers) && isset($departments[$departmentCode])) { $dataProducers['d' . $departmentCode] = '' . $departments[$departmentCode] . ''; $optionsProducers['d' . $departmentCode] = ['disabled' => true]; } $dataProducers[$p->id] = ' ' . Html::encode( $p->name ) . ' - ' . Html::encode($p->postcode) . ' ' . Html::encode( $p->city ) . ' '; if (strlen($p->code)) { $optionsProducers[$p->id] = ['class' => 'lock']; } } return ['data' => $dataProducers, 'options' => $optionsProducers]; } /** * Retourne le CA de l'établissement pour un mois donné. * * @param string $period * @param boolean $format * @return string */ public function getTurnover($period = '', $format = false) { if (!$period) { $period = date('Y-m'); } $connection = Yii::$app->getDb(); $command = $connection->createCommand( ' SELECT SUM(product_order.price * product_order.quantity) AS turnover FROM `order`, product_order, distribution, product WHERE `order`.id = product_order.id_order AND distribution.id_producer = :id_producer AND `order`.id_distribution = distribution.id AND product_order.id_product = product.id AND distribution.date > :date_begin AND distribution.date < :date_end', [ ':date_begin' => date('Y-m-31', strtotime("-1 month", strtotime($period))), ':date_end' => date('Y-m-01', strtotime("+1 month", strtotime($period))), ':id_producer' => $this->id ] ); $result = $command->queryOne(); $turnover = $result['turnover']; if ($format) { return number_format($turnover, 2) . ' €'; } else { return $turnover; } } public function getAmountToBeBilledByTurnover($turnover, $format = false) { $amountToBeBilled = 0; $producerPriceRangeArray = ProducerPriceRange::find()->all(); foreach($producerPriceRangeArray as $priceRange) { if($turnover >= $priceRange->range_begin && $turnover < $priceRange->range_end) { $amountToBeBilled = $priceRange->price; } } if($format) { return Price::format($amountToBeBilled); } else { return $amountToBeBilled; } } public function getAmountToBeBilledByMonth($month, $format = false) { $turnover = $this->getTurnover($month); return $this->getAmountToBeBilledByTurnover($turnover, $format); } public function getSummaryAmountsToBeBilled($label, $numberOfMonths = 1) { $text = ''; $numMonthCurrent = date('m'); if($numberOfMonths == 1 || ($numberOfMonths == 3 && (in_array($numMonthCurrent, [1, 4, 7, 10]))) || ($numberOfMonths == 6 && (in_array($numMonthCurrent, [1, 7])))) { for ($i = 1; $i <= $numberOfMonths; $i++) { $month = date('Y-m', strtotime('-' . $i . ' month')); $turnover = $this->getTurnover($month); if ($turnover) { if ($this->isBillingTypeClassic()) { $text .= ''; } $text .= $this->getAmountToBeBilledByTurnover($turnover, true); if ($this->isBillingTypeClassic()) { $text .= ''; } $text .= ' / '.Price::format($turnover); $text .= '
    '; } } if (strlen($text)) { $text = $label . ' :
    ' . $text; } } return $text; } public function getAmountBilledLastMonth() { if($this->isBillingTypeClassic()) { $month = date('Y-m', strtotime('-1 month')); return $this->getAmountToBeBilledByMonth($month); } elseif($this->isBillingTypeFreePrice()) { return $this->free_price; } return 0; } /** * Retourne le montant à facturer pour une période donnée. * * @param string $periode * @param float $ca * @param boolean $format * @return string */ public function getMAmountBilled($format = false) { if ($format) { return number_format($this->free_price, 2) . ' €'; } else { return $this->free_price; } } /** * Retourne la facture d'une période donnée. * * @param string $periode * @return Facture */ public function getInvoice($period = '') { if (!$period) { $period = date('Y-m', strtotime('-1 month')); } $invoice = Invoice::searchOne( ['id_producer' => $this->id, 'period' => ':period'], ['params' => [':period' => $period]] ); return $invoice; } /** * Retourne la facture du mois dernier. * * @return Facture */ public function getInvoiceLastMonth() { return $this->getInvoice(date('Y-m', strtotime('-1 month'))); } /** * Retourne une configuration d'un établissement donné. * * @param string $config * @param integer $id_etablissement * @return mixed */ public static function getConfig($config = '', $idProducer = 0) { if (strlen($config)) { if (!$idProducer) { $idProducer = GlobalParam::getCurrentProducerId(); } $producer = self::findOne($idProducer); if ($producer) { return $producer->$config; } } return false; } /** * Retourne le montant de l'abonnement à prix libre définit par * le producteur. * * @param boolean $format * @return mixed */ public function getFreePrice($format = true) { if (!is_null($this->free_price)) { if ($format) { return number_format($this->free_price, 2, ',', false) . ' €'; } else { return $this->free_price; } } } /** * Lie un utilisateur à un producteur. * * @param integer $id_user * @param integer $id_producer * @return UserProducer */ public static function addUser($idUser, $idProducer, $bookmark = 1) { $userProducer = UserProducer::searchOne([ 'user_producer.id_user' => $idUser, 'user_producer.id_producer' => $idProducer ]); if (!$userProducer) { $newUserProducer = new UserProducer; $newUserProducer->id_producer = $idProducer; $newUserProducer->id_user = $idUser; $newUserProducer->credit = 0; $newUserProducer->active = 1; $newUserProducer->bookmark = (int)$bookmark; $newUserProducer->save(); } else { if (!$userProducer->active) { $userProducer->active = 1; $userProducer->save(); } } return $userProducer; } public function getSpecificDelays() { $array = []; $daysArray = [ 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday' ]; foreach ($daysArray as $day) { $fieldDelay = 'order_delay_' . $day; $fieldDeadline = 'order_deadline_' . $day; $delay = $this->order_delay; $deadline = $this->order_deadline; if ($this->$fieldDelay) { $delay = $this->$fieldDelay; } if ($this->$fieldDeadline) { $deadline = $this->$fieldDeadline; } $array[$day] = [ 'order_delay' => $delay, 'order_deadline' => $deadline, ]; } return $array; } public function hasSpecificDelays() { $daysArray = [ 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday' ]; foreach ($daysArray as $day) { $fieldDelay = 'order_delay_' . $day; $fieldDeadline = 'order_deadline_' . $day; if ($this->$fieldDelay || $this->$fieldDeadline) { return true; } } return false; } /** * Retourne le chemin vers le fichier contenant la clé secrète d'API de Stripe * * @return string */ public function getFilenamePrivateKeyApiStripe() { return '../../common/config/stripe/api-' . $this->id . '.key'; } public function getFilenamePrivateKeyEndpointStripe() { return '../../common/config/stripe/endpoint-' . $this->id . '.key'; } public function savePrivateKeyStripe($filename, $value) { if (strlen($value) > 0) { $handle = fopen($filename, "w"); fwrite($handle, $value); fclose($handle); } } public function savePrivateKeyApiStripe() { $this->savePrivateKeyStripe( $this->getFilenamePrivateKeyApiStripe(), $this->option_stripe_private_key ); } public function savePrivateKeyEndpointStripe() { $this->savePrivateKeyStripe( $this->getFilenamePrivateKeyEndpointStripe(), $this->option_stripe_endpoint_secret ); } /** * Retourne la clé secrète d'API de Stripe. * * @return string */ public function getPrivateKeyStripe($filename) { if (file_exists($filename)) { $handle = fopen($filename, "r"); $filesize = filesize($filename); if ($handle && $filesize) { $secretKey = fread($handle, $filesize); fclose($handle); return $secretKey; } } return ''; } public function getPrivateKeyApiStripe() { return $this->getPrivateKeyStripe($this->getFilenamePrivateKeyApiStripe()); } public function getPrivateKeyEndpointStripe() { return $this->getPrivateKeyStripe($this->getFilenamePrivateKeyEndpointStripe()); } /** * Retourne le compte producteur de démonstration. * * @return Producer */ public static function getDemoAccount() { $producer = Producer::find()->where('name LIKE \'Démo\'')->one(); return $producer; } /** * Retourne true si le compte est un compte de démo. * * @return boolean */ public function isDemo() { if (strpos($this->name, 'Démo') !== false) { return true; } return false; } public function getFullAddress($nl2br = false) { $address = ''; $address .= $this->name . "\n"; if (strlen($this->address)) { $address .= $this->address . "\n"; } if (strlen($this->postcode) || strlen($this->city)) { $address .= $this->postcode . ' ' . $this->city; } if ($nl2br) { $address = nl2br($address); } return $address; } public function getHtmlLogo() { $html = ''; if (strlen($this->logo)) { $html = ''; } return $html; } public function getUrlLogo() { return Yii::$app->urlManagerProducer->getHostInfo( ) . '/' . Yii::$app->urlManagerProducer->baseUrl . '/uploads/' . $this->logo; } public function getEmailOpendistrib() { return $this->slug . '@opendistrib.net'; } public function getMainContact() { if ($this->contact) { foreach ($this->contact as $contact) { if ($contact->is_main_contact) { return $contact; } } } return false; } public function isOnlinePaymentActive() { return $this->online_payment || ($this->option_stripe_mode_test && !Yii::$app->user->isGuest && Yii::$app->user->identity->status > 10); } public function isOnlinePaymentActiveAndTypeOrder() { return $this->isOnlinePaymentActive() && $this->option_online_payment_type == 'order' ; } public static function getBillingFrequencyPopulateDropdown() { return self::$billingFrequencyArray; } public function isBillingFrequencyMonthly() { return $this->option_billing_frequency == self::BILLING_FREQUENCY_MONTHLY; } public function isBillingFrequencyQuarterly() { return $this->option_billing_frequency == self::BILLING_FREQUENCY_QUARTERLY; } public function isBillingFrequencyBiannual() { return $this->option_billing_frequency == self::BILLING_FREQUENCY_BIANNUAL; } public static function getBillingTypePopulateDropdown() { return self::$billingTypeArray; } public function isBillingTypeClassic() { return $this->option_billing_type == self::BILLING_TYPE_CLASSIC; } public function isBillingTypeFreePrice() { return $this->option_billing_type == self::BILLING_TYPE_FREE_PRICE; } }