'
. '
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'
],
'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',
'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'
];
}
/*
* 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;
}
}