Producer::CREDIT_FUNCTIONING_OPTIONAL => 'Optionnelle', | Producer::CREDIT_FUNCTIONING_OPTIONAL => 'Optionnelle', | ||||
Producer::CREDIT_FUNCTIONING_MANDATORY => 'Obligatoire', | Producer::CREDIT_FUNCTIONING_MANDATORY => 'Obligatoire', | ||||
], []) ; ?> | ], []) ; ?> | ||||
<?= $form->field($model, 'credit_limit',[ | |||||
'template' => '{label}<div class="input-group">{input}<span class="input-group-addon"><span class="glyphicon glyphicon-euro"></span></span></div>{hint}', | |||||
])->hint('Limite de crédit que l\'utilisateur ne pourra pas dépasser. Laisser vide pour permettre un crédit négatif et infini.'); ?> | |||||
<?= $form->field($model, 'use_credit_checked_default') | |||||
->dropDownList([ | |||||
0 => 'Non', | |||||
1 => 'Oui', | |||||
], []) ; ?> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
} | } | ||||
return $str ; | return $str ; | ||||
} | } | ||||
/** | |||||
* Retourne le mode de fonctionnement du crédit du point de vente. | |||||
* | |||||
* @return string | |||||
*/ | |||||
public function getCreditFunctioning() | |||||
{ | |||||
return $this->credit_functioning ? $this->credit_functioning : Producer::getConfig('credit_functioning') ; | |||||
} | |||||
} | } |
* @property string gcs | * @property string gcs | ||||
* @property boolean option_allow_user_gift | * @property boolean option_allow_user_gift | ||||
* @property string credit_functioning | * @property string credit_functioning | ||||
* @property boolean use_credit_checked_default | |||||
* @property float credit_limit | |||||
* | |||||
*/ | */ | ||||
class Producer extends ActiveRecordCommon | class Producer extends ActiveRecordCommon | ||||
{ | { | ||||
} | } | ||||
}], | }], | ||||
[['description','mentions','gcs','order_infos','slug','secret_key_payplug'], 'string'], | [['description','mentions','gcs','order_infos','slug','secret_key_payplug'], 'string'], | ||||
[['negative_balance', 'credit', 'active','online_payment','user_manage_subscription', 'option_allow_user_gift'], 'boolean'], | |||||
[['negative_balance', 'credit', 'active','online_payment','user_manage_subscription', 'option_allow_user_gift','use_credit_checked_default'], 'boolean'], | |||||
[['name', 'siret', 'logo', 'photo', 'postcode', 'city', 'code','type','credit_functioning'], 'string', 'max' => 255], | [['name', 'siret', 'logo', 'photo', 'postcode', 'city', 'code','type','credit_functioning'], 'string', 'max' => 255], | ||||
[['free_price', 'credit_limit_reminder'], 'double'], | |||||
[['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'], | ['free_price', 'compare', 'compareValue' => 0, 'operator' => '>=', 'type' => 'number', 'message' => 'Prix libre doit être supérieur ou égal à 0'], | ||||
]; | ]; | ||||
} | } | ||||
'mentions' => 'Mentions légales', | 'mentions' => 'Mentions légales', | ||||
'gcs' => 'Conditions générales de vente', | 'gcs' => 'Conditions générales de vente', | ||||
'option_allow_user_gift' => 'Autoriser les utilisateurs à effectuer un don à la plateforme lors de leur commande', | '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_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' | |||||
]; | ]; | ||||
} | } | ||||
<?php | |||||
use yii\db\Migration; | |||||
use yii\db\mysql\Schema; | |||||
class m190222_090304_ajout_champs_options_credit extends Migration { | |||||
public function up() { | |||||
$this->addColumn('producer', 'credit_limit', Schema::TYPE_FLOAT) ; | |||||
$this->addColumn('producer', 'use_credit_checked_default', Schema::TYPE_BOOLEAN.' DEFAULT 1') ; | |||||
} | |||||
public function down() { | |||||
$this->dropColumn('producer', 'credit_limit') ; | |||||
$this->dropColumn('producer', 'use_credit_checked_default') ; | |||||
} | |||||
} |
'id' => $order->id_point_sale | 'id' => $order->id_point_sale | ||||
]) ; | ]) ; | ||||
$order->comment_point_sale = ($pointSale && strlen($pointSale->getComment())) ? | $order->comment_point_sale = ($pointSale && strlen($pointSale->getComment())) ? | ||||
$pointSale->getComment() : '' ; | $pointSale->getComment() : '' ; | ||||
// credit | // credit | ||||
$credit = Producer::getConfig('credit'); | $credit = Producer::getConfig('credit'); | ||||
$creditLimit = Producer::getConfig('credit_limit'); | |||||
$creditFunctioning = $pointSale->getCreditFunctioning() ; | |||||
$creditUser = Yii::$app->user->identity->getCredit($distribution->id_producer); | |||||
$order = Order::searchOne([ | $order = Order::searchOne([ | ||||
'id' => $order->id | 'id' => $order->id | ||||
]) ; | ]) ; | ||||
$amountPaid = $order->getAmount(Order::AMOUNT_PAID); | |||||
$amountRemaining = $order->getAmount(Order::AMOUNT_REMAINING) ; | |||||
if($credit && $pointSale->credit && ($posts['use_credit'] || $pointSale->credit_functioning == Producer::CREDIT_FUNCTIONING_MANDATORY)) { | if($credit && $pointSale->credit && ($posts['use_credit'] || $pointSale->credit_functioning == Producer::CREDIT_FUNCTIONING_MANDATORY)) { | ||||
$amountPaid = $order->getAmount(Order::AMOUNT_PAID); | |||||
// à payer | // à payer | ||||
if ($order->getPaymentStatus() == Order::PAYMENT_UNPAID) { | if ($order->getPaymentStatus() == Order::PAYMENT_UNPAID) { | ||||
$amountRemaining = $order->getAmount(Order::AMOUNT_REMAINING) ; | |||||
$credit = Yii::$app->user->identity->getCredit($distribution->id_producer); | |||||
if(!is_null($creditLimit) && $amountRemaining > $creditUser - $creditLimit) { | |||||
$amountRemaining = $creditUser - $creditLimit ; | |||||
} | |||||
if ($amountRemaining > 0) { | if ($amountRemaining > 0) { | ||||
$order->saveCreditHistory( | $order->saveCreditHistory( | ||||
CreditHistory::TYPE_PAYMENT, | CreditHistory::TYPE_PAYMENT, | ||||
} | } | ||||
} | } | ||||
} | } | ||||
else { | |||||
if (!count($productsArray)) { | |||||
$errors[] = "Vous n'avez choisi aucun produit" ; | |||||
} | |||||
if ($errorDate) { | |||||
$errors[] = "Vous ne pouvez pas commander pour cette date." ; | |||||
} | |||||
if ($errorPointSale) { | |||||
$errors[] = "Point de vente invalide." ; | |||||
} | |||||
if (!count($productsArray)) { | |||||
$errors[] = "Vous n'avez choisi aucun produit" ; | |||||
} | } | ||||
if ($errorDate) { | |||||
$errors[] = "Vous ne pouvez pas commander pour cette date." ; | |||||
} | |||||
if ($errorPointSale) { | |||||
$errors[] = "Point de vente invalide." ; | |||||
} | |||||
return $errors ; | return $errors ; | ||||
} | } | ||||
'order_infos' => $producer->order_infos, | 'order_infos' => $producer->order_infos, | ||||
'credit' => $producer->credit, | 'credit' => $producer->credit, | ||||
'credit_functioning' => $producer->credit_functioning, | 'credit_functioning' => $producer->credit_functioning, | ||||
'use_credit_checked_default' => $producer->use_credit_checked_default, | |||||
'credit_limit' => is_numeric($producer->credit_limit) ? $producer->credit_limit : null | |||||
] ; | ] ; | ||||
// Distributions | // Distributions |
<label for="order-comment">Commentaire</label> | <label for="order-comment">Commentaire</label> | ||||
<textarea id="order-comment" v-model="comment" class="form-control"></textarea> | <textarea id="order-comment" v-model="comment" class="form-control"></textarea> | ||||
</div> | </div> | ||||
<div class="credit"> | |||||
<div v-if="producer.credit == 1 && pointSaleActive.credit == 1"> | |||||
<input type="checkbox" id="use-credit" v-model="useCredit" disabled="disabled" v-if="pointSaleActive.credit_functioning == 'mandatory'" /> | |||||
<input type="checkbox" id="use-credit" v-model="useCredit" v-else /> <label for="use-credit">Utiliser mon Crédit ({{ formatPrice(credit) }})</label> | |||||
<div class="info" v-if="useCredit"> | |||||
<span v-if="order == null || order.amount_paid == 0">{{ priceTotal(true) }} seront débités</span> | |||||
<span v-else-if="order != null && order.amount_paid > 0 && order.amount_paid < priceTotal()">{{ formatPrice(priceTotal() - order.amount_paid) }} seront débités</span> | |||||
<span v-else-if="order != null && order.amount_paid > priceTotal()">{{ formatPrice(order.amount_paid - priceTotal()) }} seront remboursés</span> | |||||
<template v-if="!checkCreditLimit(order) && pointSaleActive.credit_functioning == 'mandatory'"> | |||||
<div class="alert alert-danger">Vous devez recharger votre crédit ou supprimer des produits. Votre producteur n'autorise pas un crédit inférieur à <strong>{{ formatPrice(creditLimit) }}</strong>.</div> | |||||
<div class="block-actions"> | |||||
<a class="btn btn-primary" href="<?= Yii::$app->urlManager->createUrl(['site/index']) ?>">Retour à l'accueil</a> | |||||
</div> | |||||
</template> | |||||
<template v-else> | |||||
<div class="credit"> | |||||
<div v-if="producer.credit == 1 && pointSaleActive.credit == 1"> | |||||
<input type="checkbox" id="use-credit" v-model="useCredit" disabled="disabled" v-if="pointSaleActive.credit_functioning == 'mandatory'" /> | |||||
<input type="checkbox" id="use-credit" v-model="useCredit" v-else /> <label for="use-credit">Utiliser mon Crédit ({{ formatPrice(credit) }})</label> | |||||
<div class="info" v-if="useCredit"> | |||||
<template v-if="order == null || order.amount_paid == 0"> | |||||
<span v-if="checkCreditLimit(order)">{{ priceTotal(true) }} seront débités</span> | |||||
<span v-else> | |||||
{{ formatPrice(credit) }} seront débités. (Limite de crédit à {{ formatPrice(creditLimit) }})<br /> | |||||
Restera {{ formatPrice(priceTotal() - credit) }} à régler. | |||||
</span> | |||||
</template> | |||||
<template v-else-if="order != null && order.amount_paid > 0 && order.amount_paid < priceTotal()"> | |||||
<span v-if="checkCreditLimit(order)">{{ formatPrice(priceTotal() - order.amount_paid) }} seront débités</span> | |||||
<span v-else> | |||||
{{ formatPrice(credit) }} seront débités. (Limite de crédit à {{ formatPrice(creditLimit) }})<br /> | |||||
Restera {{ formatPrice(priceTotal() - order.amount_paid - credit) }} à régler. | |||||
</span> | |||||
</template> | |||||
<template v-else-if="order != null && order.amount_paid > priceTotal()"> | |||||
<span>{{ formatPrice(order.amount_paid - priceTotal()) }} seront remboursés</span> | |||||
</template> | |||||
</div> | |||||
</div> | |||||
<div v-else> | |||||
<span class="glyphicon glyphicon-chevron-right"></span> La commande sera à régler sur place. | |||||
</div> | </div> | ||||
</div> | </div> | ||||
<div v-else> | |||||
<span class="glyphicon glyphicon-chevron-right"></span> La commande sera à régler sur place. | |||||
<div class="block-actions"> | |||||
<button class="btn btn-primary" disabled="disabled" v-if="disableConfirmButton">Je confirme ma commande</button> | |||||
<button class="btn btn-primary" v-else @click="confirmClick">Je confirme ma commande</button> | |||||
</div> | </div> | ||||
</div> | |||||
<div class="block-actions"> | |||||
<button class="btn btn-primary" disabled="disabled" v-if="disableConfirmButton">Je confirme ma commande</button> | |||||
<button class="btn btn-primary" v-else @click="confirmClick">Je confirme ma commande</button> | |||||
</div> | |||||
</template> | |||||
</div> | </div> | ||||
</transition> | </transition> | ||||
</div> | </div> |
.order-order #app-order-order table#products tr.total .price-total { | .order-order #app-order-order table#products tr.total .price-total { | ||||
font-size: 23px; | font-size: 23px; | ||||
} | } | ||||
/* line 239, ../sass/order/_order.scss */ | |||||
.order-order #app-order-order #content-step-payment .credit { | |||||
margin-top: 20px; | |||||
} | |||||
/* line 242, ../sass/order/_order.scss */ | |||||
/* line 240, ../sass/order/_order.scss */ | |||||
.order-order #app-order-order #content-step-payment .credit .info { | .order-order #app-order-order #content-step-payment .credit .info { | ||||
margin-left: 20px; | margin-left: 20px; | ||||
color: gray; | color: gray; | ||||
} | } | ||||
/* line 249, ../sass/order/_order.scss */ | |||||
/* line 246, ../sass/order/_order.scss */ | |||||
.order-order #app-order-order #content-step-payment .comment { | |||||
margin-bottom: 20px; | |||||
} | |||||
/* line 251, ../sass/order/_order.scss */ | |||||
.order-order #app-order-order #infos { | .order-order #app-order-order #infos { | ||||
margin-top: 30px; | margin-top: 30px; | ||||
} | } | ||||
/* line 251, ../sass/order/_order.scss */ | |||||
/* line 253, ../sass/order/_order.scss */ | |||||
.order-order #app-order-order #infos .panel-body { | .order-order #app-order-order #infos .panel-body { | ||||
padding-top: 0px; | padding-top: 0px; | ||||
white-space: pre-line; | white-space: pre-line; |
comment: '', | comment: '', | ||||
creditCheckbox: false, | creditCheckbox: false, | ||||
credit: 0, | credit: 0, | ||||
creditLimit: null, | |||||
useCredit: false, | useCredit: false, | ||||
errors: [], | errors: [], | ||||
disableConfirmButton: false, | disableConfirmButton: false, | ||||
}, | }, | ||||
formatPrice: function(price) { | formatPrice: function(price) { | ||||
var isNumberRegExp = new RegExp(/^[-+]?[0-9]+(\.[0-9]+)*$/); | var isNumberRegExp = new RegExp(/^[-+]?[0-9]+(\.[0-9]+)*$/); | ||||
if(isNumberRegExp.test(price) && price > 0) { | |||||
if(isNumberRegExp.test(price)) { | |||||
return Number(price).toFixed(2).replace('.',',')+' €' ; | return Number(price).toFixed(2).replace('.',',')+' €' ; | ||||
} | } | ||||
return '--' ; | |||||
return '0 €' ; | |||||
}, | }, | ||||
getPointSale: function(idPointSale) { | getPointSale: function(idPointSale) { | ||||
for(var key in this.pointsSale) { | for(var key in this.pointsSale) { | ||||
.then(function(response) { | .then(function(response) { | ||||
app.producer = response.data.producer ; | app.producer = response.data.producer ; | ||||
app.credit = response.data.credit ; | app.credit = response.data.credit ; | ||||
app.useCredit = response.data.producer.use_credit_checked_default ; | |||||
app.creditLimit = response.data.producer.credit_limit ; | |||||
app.calendar.attrs = [] ; | app.calendar.attrs = [] ; | ||||
app.calendar.availableDates = [] ; | app.calendar.availableDates = [] ; | ||||
var distributions = response.data.distributions ; | var distributions = response.data.distributions ; | ||||
validatePointSale: function(idPointSale) { | validatePointSale: function(idPointSale) { | ||||
this.pointSaleActive = this.getPointSale(idPointSale) ; | this.pointSaleActive = this.getPointSale(idPointSale) ; | ||||
this.useCredit = true ; | |||||
this.changeStep('products') ; | this.changeStep('products') ; | ||||
}, | }, | ||||
productQuantityClick: function(product, quantity) { | productQuantityClick: function(product, quantity) { | ||||
if(!this.oneProductOrdered()) { | if(!this.oneProductOrdered()) { | ||||
this.errors.push('Veuillez sélectionner au moins un produit.') ; | this.errors.push('Veuillez sélectionner au moins un produit.') ; | ||||
} | } | ||||
}, | |||||
checkCreditLimit: function(order) { | |||||
var total = this.priceTotal() ; | |||||
if(order != null) { | |||||
total = this.priceTotal() - order.amount_paid ; | |||||
} | |||||
return this.creditLimit == null || (this.creditLimit != null && (this.credit - total >= this.creditLimit)) ; | |||||
} | } | ||||
} | } | ||||
}); | }); |
#content-step-payment { | #content-step-payment { | ||||
.credit { | .credit { | ||||
margin-top: 20px ; | |||||
.info { | .info { | ||||
margin-left: 20px ; | margin-left: 20px ; | ||||
color: gray ; | color: gray ; | ||||
} | } | ||||
} | } | ||||
.comment { | |||||
margin-bottom: 20px ; | |||||
} | |||||
} | } | ||||
#infos { | #infos { |