@@ -295,10 +295,10 @@ class CronController extends BackendController | |||
$subject = '[distrib] Commandes du ' . date('d/m', strtotime($date)); | |||
// génération du pdf de commande | |||
Yii::$app->runAction('order/report-cron', [ | |||
Yii::$app->runAction('distribution/report-cron', [ | |||
'date' => $date, | |||
'save' => true, | |||
'id_producer' => $producer['id'], | |||
'idProducer' => $producer['id'], | |||
'key' => '64ac0bdab7e9f5e48c4d991ec5201d57' | |||
]); | |||
$mail->attach(Yii::getAlias('@app/web/pdf/Orders-' . $date . '-' . $producer['id'] . '.pdf')); | |||
@@ -313,5 +313,4 @@ class CronController extends BackendController | |||
} | |||
} | |||
} | |||
} |
@@ -50,6 +50,31 @@ use DateTime; | |||
class DistributionController extends BackendController | |||
{ | |||
public function behaviors() | |||
{ | |||
return [ | |||
'access' => [ | |||
'class' => AccessControl::className(), | |||
'rules' => [ | |||
[ | |||
'actions' => ['report-cron'], | |||
'allow' => true, | |||
'roles' => ['?'] | |||
], | |||
[ | |||
'allow' => true, | |||
'roles' => ['@'], | |||
'matchCallback' => function ($rule, $action) { | |||
return User::getCurrentStatus() == USER::STATUS_ADMIN | |||
|| User::getCurrentStatus() == USER::STATUS_PRODUCER; | |||
} | |||
] | |||
], | |||
], | |||
]; | |||
} | |||
public function actionIndex($date = '') | |||
{ | |||
$format = 'Y-m-d' ; | |||
@@ -173,6 +198,15 @@ class DistributionController extends BackendController | |||
$arrayCreditUser['credit'] = $order->user->userProducer[0]->credit ; | |||
} | |||
$oneProductUnactivated = false ; | |||
foreach($order->productOrder as $productOrder) { | |||
foreach($productsArray as $product) { | |||
if($productOrder->id_product == $product['id'] && !$product['productDistribution'][0]['active']) { | |||
$oneProductUnactivated = true ; | |||
} | |||
} | |||
} | |||
$order = array_merge($order->getAttributes(), [ | |||
'amount' => $order->getAmount(Order::AMOUNT_TOTAL), | |||
'amount_paid' => $order->getAmount(Order::AMOUNT_PAID), | |||
@@ -181,10 +215,9 @@ class DistributionController extends BackendController | |||
'user' => (isset($order->user)) ? array_merge($order->user->getAttributes(), $arrayCreditUser) : null, | |||
'pointSale' => ['id' => $order->pointSale->id, 'name' => $order->pointSale->name], | |||
'productOrder' => $productOrderArray, | |||
'creditHistory' => $creditHistoryArray | |||
'creditHistory' => $creditHistoryArray, | |||
'oneProductUnactivated' => $oneProductUnactivated | |||
]) ; | |||
} | |||
} | |||
@@ -265,6 +298,23 @@ class DistributionController extends BackendController | |||
return $json ; | |||
} | |||
/** | |||
* Génére un PDF récapitulatif des des commandes d'un producteur pour une | |||
* date donnée (Méthode appelable via CRON) | |||
* | |||
* @param string $date | |||
* @param boolean $save | |||
* @param integer $idProducer | |||
* @param string $key | |||
* @return PDF|null | |||
*/ | |||
public function actionReportCron($date = '', $save = false, $idProducer = 0, $key = '') | |||
{ | |||
if($key == '64ac0bdab7e9f5e48c4d991ec5201d57') { | |||
$this->actionReport($date, $save, $idProducer) ; | |||
} | |||
} | |||
/** | |||
* Génére un PDF récapitulatif des commandes d'un producteur pour une | |||
* date donnée. |
@@ -55,11 +55,6 @@ class OrderController extends BackendController | |||
'access' => [ | |||
'class' => AccessControl::className(), | |||
'rules' => [ | |||
[ | |||
'actions' => ['report-cron'], | |||
'allow' => true, | |||
'roles' => ['?'] | |||
], | |||
[ | |||
'allow' => true, | |||
'roles' => ['@'], |
@@ -42,6 +42,7 @@ use common\models\User ; | |||
use common\models\Producer ; | |||
use common\models\Distribution ; | |||
use backend\models\MailForm ; | |||
use common\models\UserProducer ; | |||
/** | |||
* UserController implements the CRUD actions for User model. | |||
@@ -300,12 +301,13 @@ class UserController extends BackendController | |||
return $this->render('credit', [ | |||
'user' => $user, | |||
'userProducer' => $userProducer, | |||
'creditForm' => $creditForm, | |||
'history' => $history | |||
]); | |||
} | |||
else { | |||
throw new UserException("Vous ne pouvez pas créditer un utilisateur qui n'est pas associé à votre boulangerie."); | |||
throw new UserException("Vous ne pouvez pas créditer un utilisateur qui n'est pas associé à votre établissement."); | |||
} | |||
} | |||
@@ -328,6 +330,27 @@ class UserController extends BackendController | |||
'user' => $user | |||
]); | |||
} | |||
/** | |||
* Modifie l'option "credit_active" d'un utilisateur pour le producteur courant. | |||
* Redirige vers la page de crédit de l'utilisateur. | |||
* | |||
* @param integer $idUser | |||
* @param boolean $state | |||
*/ | |||
public function actionStateCredit($idUser, $state) | |||
{ | |||
$userProducer = UserProducer::searchOne([ | |||
'id_user' => $idUser | |||
]) ; | |||
if($userProducer) { | |||
$userProducer->credit_active = $state ; | |||
$userProducer->save() ; | |||
} | |||
return $this->redirect(['user/credit','id' => $idUser]) ; | |||
} | |||
/** | |||
* Finds the User model based on its primary key value. |
@@ -264,7 +264,7 @@ $this->setPageTitle('Distributions') ; | |||
</div> | |||
</td> | |||
<td class="column-payment"> | |||
<div class="btn-group" v-if="order.user"> | |||
<div class="btn-group" v-if="order.user && !order.date_delete"> | |||
<button class="btn btn-xs btn-default" v-if="order.amount_paid == order.amount" @click="orderPaymentClick" :data-id-order="order.id" data-type="refund" :data-amount="order.amount"> | |||
<span class="glyphicon glyphicon-euro"></span> Rembourser | |||
</button> | |||
@@ -288,6 +288,7 @@ $this->setPageTitle('Distributions') ; | |||
</div> | |||
</td> | |||
<td class="column-actions"> | |||
<span v-if="order.oneProductUnactivated" class="glyphicon glyphicon-warning-sign" title="Contient un produit non activé"></span> | |||
<button class="btn btn-default" :data-id-order="order.id" @click="orderViewClick"><span :class="'glyphicon ' + ((showViewProduct && idOrderView == order.id) ? 'glyphicon-eye-close' : 'glyphicon-eye-open')"></span></button> | |||
<button class="btn btn-default" :data-id-order="order.id" @click="updateOrderClick"><span class="glyphicon glyphicon-pencil"></span></button> | |||
<button class="btn btn-default" :data-id-order="order.id" @click="deleteOrderClick"><span class="glyphicon glyphicon-trash"></span></button> | |||
@@ -301,7 +302,7 @@ $this->setPageTitle('Distributions') ; | |||
:points-sale="pointsSale" | |||
:users="users" | |||
:products="products" | |||
:order="order" | |||
:order="order.clone" | |||
@close="showModalFormOrderUpdate = false" | |||
@ordercreatedupdated="orderCreatedUpdated" | |||
></order-form> | |||
@@ -408,7 +409,7 @@ $this->setPageTitle('Distributions') ; | |||
<strong><span class="glyphicon glyphicon-menu-right"></span> Produits</strong> | |||
<ul> | |||
<li v-for="product in products" v-if="order.productOrder[product.id] > 0"> | |||
{{ order.productOrder[product.id] }} x {{ product.name }} | |||
{{ order.productOrder[product.id] }} x {{ product.name }} <span v-if="product.productDistribution[0].active == 0" class="glyphicon glyphicon-warning-sign" title="Ce produit n'est pas activé"></span> | |||
</li> | |||
</ul> | |||
<div v-if="order.comment && order.comment.length > 0" class="comment"> | |||
@@ -448,7 +449,7 @@ $this->setPageTitle('Distributions') ; | |||
<div class="form-group"> | |||
<label class="control-label" for="select-id-user">Utilisateur</label> | |||
<select class="form-control" v-model="order.id_user"> | |||
<option v-for="user in users" :value="user.id_user">{{ user.name +' '+ user.lastname }}</option> | |||
<option v-for="user in users" :value="user.id_user">{{ user.lastname +' '+ user.name }}</option> | |||
</select> | |||
<input v-model="order.username" type="text" class="form-control" placeholder="Ou saisissez ici le nom de l'utilisateur" /> | |||
</div> |
@@ -71,9 +71,10 @@ use common\models\Producer ; | |||
<?= $form->field($model, 'credit_functioning') | |||
->dropDownList([ | |||
'' => 'Paramètres globaux ('.Producer::$creditFunctioningArray[Producer::getConfig('credit_functioning')].')', | |||
Producer::CREDIT_FUNCTIONING_OPTIONAL => 'Optionnelle', | |||
Producer::CREDIT_FUNCTIONING_MANDATORY => 'Obligatoire', | |||
], []) ; ?> | |||
Producer::CREDIT_FUNCTIONING_OPTIONAL => Producer::$creditFunctioningArray[Producer::CREDIT_FUNCTIONING_OPTIONAL], | |||
Producer::CREDIT_FUNCTIONING_MANDATORY => Producer::$creditFunctioningArray[Producer::CREDIT_FUNCTIONING_MANDATORY], | |||
Producer::CREDIT_FUNCTIONING_USER => Producer::$creditFunctioningArray[Producer::CREDIT_FUNCTIONING_USER], | |||
], [])->hint(Producer::HINT_CREDIT_FUNCTIONING) ; ?> | |||
<div id="delivery-days"> |
@@ -173,16 +173,30 @@ $this->addBreadcrumb($this->getTitle()) ; | |||
. 'Ils créditent leur compte en vous donnant la somme de leur choix et c\'est ensuite à vous de '.Html::a('mettre à jour', ['user/index']).' leur Crédit en ligne.<br />' | |||
. 'Ceci fait, les clients paient leur commande directement via leur Crédit.') ; ?> | |||
<?= $form->field($model, 'credit_functioning') | |||
->dropDownList([ | |||
Producer::CREDIT_FUNCTIONING_OPTIONAL => Producer::$creditFunctioningArray[Producer::CREDIT_FUNCTIONING_OPTIONAL], | |||
Producer::CREDIT_FUNCTIONING_MANDATORY => Producer::$creditFunctioningArray[Producer::CREDIT_FUNCTIONING_MANDATORY], | |||
Producer::CREDIT_FUNCTIONING_USER => Producer::$creditFunctioningArray[Producer::CREDIT_FUNCTIONING_USER], | |||
], [])->hint(Producer::HINT_CREDIT_FUNCTIONING) ; ?> | |||
<?= $form->field($model, 'use_credit_checked_default') | |||
->dropDownList([ | |||
0 => 'Non', | |||
1 => 'Oui', | |||
], [])->hint('Utilisation optionnelle du Crédit.') ; ?> | |||
<?= $form->field($model, 'credit_limit_reminder',[ | |||
'template' => '{label}<div class="input-group">{input}<span class="input-group-addon"><span class="glyphicon glyphicon-euro"></span></span></div>{hint}', | |||
]) | |||
->hint("Une relance est envoyé au client dès que ce seuil est dépassé.") ; ?> | |||
<?= $form->field($model, 'credit_functioning') | |||
->dropDownList([ | |||
Producer::CREDIT_FUNCTIONING_OPTIONAL => 'Optionnelle', | |||
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.'); ?> | |||
</div> | |||
</div> | |||
@@ -62,29 +62,52 @@ $this->addBreadcrumb('Créditer') ; | |||
} | |||
?> | |||
<div class="col-md-12"> | |||
<?php $form = ActiveForm::begin(); ?> | |||
<?= $form->field($creditForm, 'type')->dropDownList([ | |||
CreditHistory::TYPE_CREDIT => 'Crédit', | |||
CreditHistory::TYPE_DEBIT => 'Débit', | |||
]) ?> | |||
<?= $form->field($creditForm, 'amount')->textInput() ?> | |||
<?= $form->field($creditForm, 'mean_payment')->dropDownList([ | |||
CreditHistory::MEAN_PAYMENT_MONEY => CreditHistory::getStrMeanPaymentBy(CreditHistory::MEAN_PAYMENT_MONEY), | |||
CreditHistory::MEAN_PAYMENT_CREDIT_CARD => CreditHistory::getStrMeanPaymentBy(CreditHistory::MEAN_PAYMENT_CREDIT_CARD), | |||
CreditHistory::MEAN_PAYMENT_CHEQUE => CreditHistory::getStrMeanPaymentBy(CreditHistory::MEAN_PAYMENT_CHEQUE), | |||
CreditHistory::MEAN_PAYMENT_OTHER => CreditHistory::getStrMeanPaymentBy(CreditHistory::MEAN_PAYMENT_OTHER), | |||
]) ?> | |||
<?= $form->field($creditForm, 'comment')->textarea() ?> | |||
<?= $form->field($creditForm, 'send_mail')->checkbox() ?> | |||
<div class="col-md-4"> | |||
<div class="panel panel-default"> | |||
<div class="panel-heading"> | |||
<h3 class="panel-title"> | |||
Crédit obligatoire | |||
<?= Html::a($userProducer->credit_active ? 'Désactiver' : 'Activer', ['user/state-credit', 'idUser' => $user->id,'state' => !$userProducer->credit_active], ['class' => 'btn btn-default btn-xs']); ?> | |||
</h3> | |||
</div> | |||
<div class="panel-body"> | |||
<?php if($userProducer->credit_active): ?> | |||
<div class="alert alert-success">Activé</div> | |||
<?php else: ?> | |||
<div class="alert alert-danger">Désactivé</div> | |||
<?php endif; ?> | |||
</div> | |||
</div> | |||
<div class="form-group"> | |||
<?= Html::submitButton( 'Créditer', ['class' => 'btn btn-primary']) ?> | |||
<div class="panel panel-default"> | |||
<div class="panel-heading"> | |||
<h3 class="panel-title">Crédit / débit</h3> | |||
</div> | |||
<div class="panel-body"> | |||
<?php $form = ActiveForm::begin(); ?> | |||
<?= $form->field($creditForm, 'type')->dropDownList([ | |||
CreditHistory::TYPE_CREDIT => 'Crédit', | |||
CreditHistory::TYPE_DEBIT => 'Débit', | |||
]) ?> | |||
<?= $form->field($creditForm, 'amount')->textInput() ?> | |||
<?= $form->field($creditForm, 'mean_payment')->dropDownList([ | |||
CreditHistory::MEAN_PAYMENT_MONEY => CreditHistory::getStrMeanPaymentBy(CreditHistory::MEAN_PAYMENT_MONEY), | |||
CreditHistory::MEAN_PAYMENT_CREDIT_CARD => CreditHistory::getStrMeanPaymentBy(CreditHistory::MEAN_PAYMENT_CREDIT_CARD), | |||
CreditHistory::MEAN_PAYMENT_CHEQUE => CreditHistory::getStrMeanPaymentBy(CreditHistory::MEAN_PAYMENT_CHEQUE), | |||
CreditHistory::MEAN_PAYMENT_OTHER => CreditHistory::getStrMeanPaymentBy(CreditHistory::MEAN_PAYMENT_OTHER), | |||
]) ?> | |||
<?= $form->field($creditForm, 'comment')->textarea() ?> | |||
<?= $form->field($creditForm, 'send_mail')->checkbox() ?> | |||
<div class="form-group"> | |||
<?= Html::submitButton( 'Créditer', ['class' => 'btn btn-primary']) ?> | |||
</div> | |||
<?php ActiveForm::end(); ?> | |||
</div> | |||
</div> | |||
<?php ActiveForm::end(); ?> | |||
</div> | |||
<div class="col-md-12"> | |||
<div class="col-md-8"> | |||
<h2>Historique <span class="the-credit"><?= number_format($user->getCredit($producer->id), 2); ?> €</span></h2> | |||
<table class="table table-bordered"> | |||
<thead> |
@@ -117,16 +117,22 @@ $this->render('_menu',[ | |||
'attribute' => 'credit', | |||
'format' => 'raw', | |||
'value' => function($model) use($producer) { | |||
$user = User::findOne($model->id) ; | |||
$userProducer = UserProducer::searchOne([ | |||
'id_user' => $model->id | |||
]) ; | |||
$credit = $userProducer ? $userProducer->credit : 0 ; | |||
$classBtnCredit = $userProducer->credit_active ? 'btn-success' : 'btn-default' ; | |||
$html = '<div class="input-group"> | |||
<input type="text" class="form-control input-credit" readonly="readonly" value="'.number_format($user->getCredit($producer->id),2).' €" placeholder=""> | |||
<input type="text" class="form-control input-credit" readonly="readonly" value="'.number_format($credit,2).' €" placeholder=""> | |||
<span class="input-group-btn"> | |||
'.Html::a( | |||
'<span class="glyphicon glyphicon-euro"></span>', | |||
Yii::$app->urlManager->createUrl(['user/credit','id' => $model->id]), | |||
[ | |||
'title' => 'Crédit', | |||
'class' => 'btn btn-default' | |||
'class' => 'btn '.$classBtnCredit | |||
] | |||
).' | |||
</span> |
@@ -1962,6 +1962,11 @@ termes. | |||
margin-bottom: 20px; | |||
} | |||
/* line 5, ../sass/user/_credit.scss */ | |||
.user-credit .panel .panel-heading .btn { | |||
float: right; | |||
} | |||
/* line 4, ../sass/producer/_update.scss */ | |||
.producer-update #nav-params { | |||
margin-bottom: 30px; |
@@ -123,6 +123,9 @@ var app = new Vue({ | |||
app.orders = response.data.orders ; | |||
for(i=0 ; i < app.orders.length ; i++) { | |||
app.orders[i].clone = app.cloneOrder(app.orders[i]) ; | |||
if(!app.orders[i].date_delete) { | |||
app.countOrders ++ ; | |||
} | |||
@@ -346,6 +349,16 @@ var app = new Vue({ | |||
closeModalProducts: function() { | |||
this.showModalProducts = false ; | |||
this.init(this.idActivePointSale) ; | |||
}, | |||
cloneOrder: function(order) { | |||
var clone = Object.assign({}, order) ; | |||
clone.productOrder = {} ; | |||
for(var key in order.productOrder) { | |||
clone.productOrder[key] = order.productOrder[key] ; | |||
} | |||
return clone ; | |||
} | |||
}, | |||
}); | |||
@@ -437,7 +450,7 @@ Vue.component('order-form',{ | |||
idUser: this.order.id_user, | |||
username: ''+this.order.username, | |||
products: JSON.stringify(this.order.productOrder), | |||
comment: this.comment, | |||
comment: this.order.comment, | |||
processCredit: processCredit | |||
}}) | |||
.then(function(response) { |
@@ -1333,5 +1333,6 @@ a.btn, button.btn { | |||
@import "stats/_products.scss" ; | |||
@import "distribution/_index.scss" ; | |||
@import "user/_emails.scss" ; | |||
@import "user/_credit.scss" ; | |||
@import "producer/_update.scss" ; | |||
@import "point_sale/_index.scss" ; |
@@ -0,0 +1,10 @@ | |||
.user-credit { | |||
.panel { | |||
.panel-heading { | |||
.btn { | |||
float: right ; | |||
} | |||
} | |||
} | |||
} |
@@ -198,7 +198,8 @@ class CreditHistory extends ActiveRecordCommon | |||
} | |||
$newCredit = $userProducer->credit ; | |||
if($oldCredit > $creditLimitReminder && $newCredit <= $creditLimitReminder) { | |||
if(!is_null($creditLimitReminder) && | |||
$oldCredit > $creditLimitReminder && $newCredit <= $creditLimitReminder) { | |||
$user = User::findOne($this->id_user) ; | |||
$producer = Producer::findOne($this->id_producer) ; | |||
Yii::$app->mailer->compose( |
@@ -333,4 +333,14 @@ class PointSale extends ActiveRecordCommon | |||
} | |||
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') ; | |||
} | |||
} |
@@ -60,15 +60,26 @@ use yii\helpers\Html; | |||
* @property string gcs | |||
* @property boolean option_allow_user_gift | |||
* @property string credit_functioning | |||
* @property boolean use_credit_checked_default | |||
* @property float credit_limit | |||
* | |||
*/ | |||
class Producer extends ActiveRecordCommon | |||
{ | |||
const CREDIT_FUNCTIONING_MANDATORY = 'mandatory' ; | |||
const CREDIT_FUNCTIONING_OPTIONAL = 'optional' ; | |||
const CREDIT_FUNCTIONING_USER = 'user' ; | |||
const HINT_CREDIT_FUNCTIONING = '<ul>' | |||
. '<li>Optionnelle : l\'utilisateur choisit s\'il utilise son Crédit ou non. Les commandes peuvent être payées ou impayées.</li>' | |||
. '<li>Obligatoire : toutes les commandes de l\'utilisateur son comptabilisées au niveau du Crédit. Toutes les commandes sont payées.</li>' | |||
. '<li>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.</li>' | |||
. '</ul>' ; | |||
public static $creditFunctioningArray = [ | |||
self::CREDIT_FUNCTIONING_MANDATORY => 'Obligatoire', | |||
self::CREDIT_FUNCTIONING_OPTIONAL => 'Optionnelle', | |||
self::CREDIT_FUNCTIONING_USER => 'Basée sur l\'utilisateur', | |||
]; | |||
var $secret_key_payplug ; | |||
@@ -99,9 +110,9 @@ class Producer extends ActiveRecordCommon | |||
} | |||
}], | |||
[['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], | |||
[['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'], | |||
]; | |||
} | |||
@@ -137,7 +148,9 @@ class Producer extends ActiveRecordCommon | |||
'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_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' | |||
]; | |||
} | |||
@@ -337,6 +337,8 @@ class User extends ActiveRecordCommon implements IdentityInterface | |||
$query->andFilterWhere(['like', 'phone', $params['phone']]); | |||
} | |||
$query->orderBy('user.lastname ASC, user.name ASC') ; | |||
return $query; | |||
} | |||
@@ -68,7 +68,7 @@ class UserProducer extends ActiveRecordCommon | |||
return [ | |||
[['id_user', 'id_producer'], 'required'], | |||
[['id_user', 'id_producer'], 'integer'], | |||
[['active','bookmark'], 'boolean'], | |||
[['active','bookmark','credit_active'], 'boolean'], | |||
[['credit'], 'double'], | |||
]; | |||
} | |||
@@ -83,6 +83,7 @@ class UserProducer extends ActiveRecordCommon | |||
'id_producer' => 'Producteur', | |||
'active' => 'Actif', | |||
'bookmark' => 'Favoris', | |||
'credit_active' => 'Crédit' | |||
]; | |||
} | |||
@@ -0,0 +1,17 @@ | |||
<?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') ; | |||
} | |||
} |
@@ -0,0 +1,15 @@ | |||
<?php | |||
use yii\db\Migration; | |||
use yii\db\mysql\Schema; | |||
class m190225_093245_ajout_champs_gestion_credit_utilisateur extends Migration { | |||
public function up() { | |||
$this->addColumn('user_producer', 'credit_active', Schema::TYPE_BOOLEAN.' DEFAULT 0') ; | |||
} | |||
public function down() { | |||
$this->dropColumn('user_producer', 'credit_active') ; | |||
} | |||
} |
@@ -42,6 +42,7 @@ use common\models\ProductDistribution ; | |||
use common\models\User ; | |||
use common\models\Producer ; | |||
use common\models\Order ; | |||
use common\models\UserPointSale ; | |||
use DateTime; | |||
class OrderController extends ProducerBaseController | |||
@@ -216,8 +217,8 @@ class OrderController extends ProducerBaseController | |||
{ | |||
$posts = Yii::$app->request->post(); | |||
$productsArray = []; | |||
$totalQuantity = 0; | |||
$producer = $this->getProducer() ; | |||
foreach ($posts['products'] as $key => $quantity) { | |||
$product = Product::find()->where(['id' => (int) $key])->one(); | |||
@@ -227,7 +228,6 @@ class OrderController extends ProducerBaseController | |||
} | |||
} | |||
$producer = $this->getProducer() ; | |||
// date | |||
$errorDate = false; | |||
@@ -263,18 +263,31 @@ class OrderController extends ProducerBaseController | |||
} else { | |||
$errorPointSale = true; | |||
} | |||
$userPointSale = UserPointSale::searchOne([ | |||
'id_user' => User::getCurrentId(), | |||
'id_point_sale' => $pointSale->id | |||
]) ; | |||
if($pointSale->restricted_access && !$userPointSale) { | |||
$errorPointSale = true; | |||
} | |||
} | |||
$errors = [] ; | |||
if ($order->validate() && count($productsArray) && !$errorDate && !$errorPointSale) { | |||
$userProducer = UserProducer::searchOne([ | |||
'id_producer' => $order->distribution->id_producer, | |||
'id_user' => User::getCurrentId() | |||
]) ; | |||
// gestion point de vente | |||
$pointSale = PointSale::searchOne([ | |||
'id' => $order->id_point_sale | |||
]) ; | |||
$order->comment_point_sale = ($pointSale && strlen($pointSale->getComment())) ? | |||
$pointSale->getComment() : '' ; | |||
@@ -318,17 +331,28 @@ class OrderController extends ProducerBaseController | |||
// 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([ | |||
'id' => $order->id | |||
]) ; | |||
if($credit && $pointSale->credit && ($posts['use_credit'] || $pointSale->credit_functioning == Producer::CREDIT_FUNCTIONING_MANDATORY)) { | |||
$amountPaid = $order->getAmount(Order::AMOUNT_PAID); | |||
$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 || | |||
($pointSale->credit_functioning == Producer::CREDIT_FUNCTIONING_USER && $userProducer->credit_active) | |||
)) { | |||
// à payer | |||
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) { | |||
$order->saveCreditHistory( | |||
CreditHistory::TYPE_PAYMENT, | |||
@@ -352,17 +376,18 @@ class OrderController extends ProducerBaseController | |||
} | |||
} | |||
} | |||
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 ; | |||
} | |||
@@ -445,6 +470,8 @@ class OrderController extends ProducerBaseController | |||
'order_infos' => $producer->order_infos, | |||
'credit' => $producer->credit, | |||
'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 | |||
@@ -486,7 +513,10 @@ class OrderController extends ProducerBaseController | |||
'id_user' => User::getCurrentId() | |||
]) ; | |||
$json['credit'] = $userProducer->credit ; | |||
$json['user'] = [ | |||
'credit' => $userProducer->credit, | |||
'credit_active' => $userProducer->credit_active, | |||
] ; | |||
if($dateObject && $dateObject->format($format) === $date) { | |||
@@ -506,7 +536,7 @@ class OrderController extends ProducerBaseController | |||
// distribution | |||
$distribution = Distribution::initDistribution($date) ; | |||
$json['distribution'] = $distribution ; | |||
$pointsSaleArray = PointSale::find() | |||
->joinWith(['pointSaleDistribution' => function($query) use ($distribution) { | |||
$query->where(['id_distribution' => $distribution->id]); | |||
@@ -515,9 +545,9 @@ class OrderController extends ProducerBaseController | |||
->with(['userPointSale' => function($query) { | |||
$query->onCondition(['id_user' => User::getCurrentId()]) ; | |||
}]) | |||
->where([ | |||
'id_producer' => $distribution->id_producer, | |||
]) | |||
->where(['id_producer' => $distribution->id_producer]) | |||
->andWhere('restricted_access = 0 OR (restricted_access = 1 AND (SELECT COUNT(*) FROM user_point_sale WHERE point_sale.id = user_point_sale.id_point_sale AND user_point_sale.id_user = :id_user) > 0)') | |||
->params([':id_user' => User::getCurrentId()]) | |||
->all(); | |||
$creditFunctioningProducer = Producer::getConfig('credit_functioning') ; |
@@ -118,9 +118,6 @@ GridView::widget([ | |||
if($c->date_delete) { | |||
$html .= '<span class="label label-danger">Annulée</span><br />' ; | |||
if($c->getState() == Order::STATE_OPEN) { | |||
$html .= '<a href="'.Yii::$app->urlManager->createUrl(['order/order','id'=>$c->id]).'" class="btn btn-default"><span class="glyphicon glyphicon-pencil"></span> Modifier</a>' ; | |||
} | |||
} | |||
else { | |||
if($c->getState() == Order::STATE_DELIVERED) { |
@@ -232,25 +232,49 @@ $this->setTitle('Commander') ; | |||
<label for="order-comment">Commentaire</label> | |||
<textarea id="order-comment" v-model="comment" class="form-control"></textarea> | |||
</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 && (pointSaleActive.credit_functioning != 'user' || (pointSaleActive.credit_functioning == 'user' && user.credit_active))"> | |||
<input type="checkbox" id="use-credit" v-model="useCredit" disabled="disabled" v-if="pointSaleActive.credit_functioning == 'mandatory' || (pointSaleActive.credit_functioning == 'user' && user.credit_active)" /> | |||
<input type="checkbox" id="use-credit" v-model="useCredit" v-else /> <label for="use-credit">Utiliser mon Crédit ({{ formatPrice(user.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(user.credit) }} seront débités. (Limite de crédit à {{ formatPrice(producer.credit_limit) }})<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(user.credit) }} seront débités. (Limite de crédit à {{ formatPrice(producer.credit_limit) }})<br /> | |||
Restera {{ formatPrice(priceTotal() - order.amount_paid - user.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 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 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> | |||
</transition> | |||
</div> |
@@ -1457,20 +1457,20 @@ termes. | |||
.order-order #app-order-order table#products tr.total .price-total { | |||
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 { | |||
margin-left: 20px; | |||
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 { | |||
margin-top: 30px; | |||
} | |||
/* line 251, ../sass/order/_order.scss */ | |||
/* line 253, ../sass/order/_order.scss */ | |||
.order-order #app-order-order #infos .panel-body { | |||
padding-top: 0px; | |||
white-space: pre-line; |
@@ -6,6 +6,7 @@ var app = new Vue({ | |||
loadingInit: true, | |||
step: 'date', | |||
producer: null, | |||
user: null, | |||
date: null, | |||
dateFormat: null, | |||
distributions: [], | |||
@@ -16,7 +17,6 @@ var app = new Vue({ | |||
products: [], | |||
comment: '', | |||
creditCheckbox: false, | |||
credit: 0, | |||
useCredit: false, | |||
errors: [], | |||
disableConfirmButton: false, | |||
@@ -91,10 +91,10 @@ var app = new Vue({ | |||
}, | |||
formatPrice: function(price) { | |||
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 '--' ; | |||
return '0 €' ; | |||
}, | |||
getPointSale: function(idPointSale) { | |||
for(var key in this.pointsSale) { | |||
@@ -109,8 +109,8 @@ var app = new Vue({ | |||
axios.get("ajax-infos",{params: {date : this.getDate()}}) | |||
.then(function(response) { | |||
app.producer = response.data.producer ; | |||
app.credit = response.data.credit ; | |||
app.user = response.data.user ; | |||
app.useCredit = response.data.producer.use_credit_checked_default ; | |||
app.calendar.attrs = [] ; | |||
app.calendar.availableDates = [] ; | |||
var distributions = response.data.distributions ; | |||
@@ -248,7 +248,12 @@ var app = new Vue({ | |||
validatePointSale: function(idPointSale) { | |||
this.pointSaleActive = this.getPointSale(idPointSale) ; | |||
this.useCredit = true ; | |||
if(this.pointSaleActive.credit_functioning == 'mandatory' || (this.pointSaleActive.credit_functioning == 'user' && this.user.credit_active)) { | |||
this.useCredit = true ; | |||
} | |||
else { | |||
this.useCredit = false ; | |||
} | |||
this.changeStep('products') ; | |||
}, | |||
@@ -321,6 +326,13 @@ var app = new Vue({ | |||
if(!this.oneProductOrdered()) { | |||
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.producer.credit_limit == null || (this.producer.credit_limit != null && (this.user.credit - total >= this.producer.credit_limit)) ; | |||
} | |||
} | |||
}); |
@@ -237,13 +237,15 @@ | |||
#content-step-payment { | |||
.credit { | |||
margin-top: 20px ; | |||
.info { | |||
margin-left: 20px ; | |||
color: gray ; | |||
} | |||
} | |||
.comment { | |||
margin-bottom: 20px ; | |||
} | |||
} | |||
#infos { |