@@ -289,6 +289,12 @@ $this->addBreadcrumb($this->getTitle()) ; | |||
0 => 'Non', | |||
1 => 'Oui' | |||
], []); ?> | |||
<?= $form->field($model, 'option_order_entry_point') | |||
->dropDownList([ | |||
Producer::ORDER_ENTRY_POINT_DATE => 'Date', | |||
Producer::ORDER_ENTRY_POINT_POINT_SALE => 'Point de vente', | |||
], []); ?> | |||
</div> | |||
</div> | |||
@@ -103,6 +103,11 @@ class Distribution extends ActiveRecordCommon | |||
return $this->hasMany(ProductDistribution::className(), ['id_distribution' => 'id']); | |||
} | |||
public function getPointSaleDistribution() | |||
{ | |||
return $this->hasMany(PointSaleDistribution::className(), ['id_distribution' => 'id']) ; | |||
} | |||
/** | |||
* Retourne les options de base nécessaires à la fonction de recherche. | |||
* | |||
@@ -413,6 +418,21 @@ class Distribution extends ActiveRecordCommon | |||
$pointSaleDistribution->save(); | |||
} | |||
public function isPointSaleActive($distribution, $pointSaleId) | |||
{ | |||
$pointSaleActive = false ; | |||
if($distribution->pointSaleDistribution) { | |||
foreach($distribution->pointSaleDistribution as $pointSaleDistribution) { | |||
if($pointSaleDistribution->id_point_sale == $pointSaleId && $pointSaleDistribution->delivery) { | |||
$pointSaleActive = true ; | |||
} | |||
} | |||
} | |||
return $pointSaleActive ; | |||
} | |||
/** | |||
* Active ou désactive la distribution. | |||
*/ |
@@ -95,6 +95,9 @@ class Producer extends ActiveRecordCommon | |||
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' ; | |||
var $secret_key_payplug; | |||
/** | |||
@@ -136,7 +139,7 @@ class Producer extends ActiveRecordCommon | |||
} | |||
}], | |||
[['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'], 'string'], | |||
'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'], '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', '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'], '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'], 'string', 'max' => 255], | |||
[['free_price', 'credit_limit_reminder', 'credit_limit'], 'double'], | |||
@@ -229,6 +232,7 @@ class Producer extends ActiveRecordCommon | |||
'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' | |||
]; | |||
} | |||
@@ -0,0 +1,18 @@ | |||
<?php | |||
use yii\db\Migration; | |||
use yii\db\Schema; | |||
class m210326_104759_add_option_order_entry_point extends Migration | |||
{ | |||
public function safeUp() | |||
{ | |||
$this->addColumn('producer', 'option_order_entry_point', Schema::TYPE_STRING.' DEFAULT \''.Producer::ORDER_ENTRY_POINT_DATE.'\''); | |||
} | |||
public function safeDown() | |||
{ | |||
$this->dropColumn('producer', 'option_order_entry_point'); | |||
} | |||
} |
@@ -597,6 +597,7 @@ class OrderController extends ProducerBaseController | |||
'use_credit_checked_default' => $producer->use_credit_checked_default, | |||
'credit_limit' => is_numeric($producer->credit_limit) ? $producer->credit_limit : null, | |||
'option_allow_order_guest' => $producer->option_allow_order_guest, | |||
'option_order_entry_point' => $producer->option_order_entry_point, | |||
]; | |||
// Distributions | |||
@@ -608,22 +609,47 @@ class OrderController extends ProducerBaseController | |||
], [ | |||
'conditions' => ['date > :date'], | |||
'params' => [':date' => $dateMini], | |||
'join_with' => ['pointSaleDistribution'], | |||
]); | |||
$distributionsArray = Distribution::filterDistributionsByDateDelay($distributionsArray) ; | |||
$json['distributions'] = $distributionsArray; | |||
// Filtre par point de vente | |||
if($pointSaleId && $producer->option_order_entry_point == Producer::ORDER_ENTRY_POINT_POINT_SALE) { | |||
$distributionsArrayFilterPointSale = [] ; | |||
for($i = 0; $i < count($distributionsArray) ; $i++) { | |||
$distribution = $distributionsArray[$i] ; | |||
if(Distribution::isPointSaleActive($distribution, $pointSaleId)) { | |||
$distributionsArrayFilterPointSale[] = $distribution ; | |||
} | |||
} | |||
$json['distributions'] = $distributionsArrayFilterPointSale; | |||
} | |||
else { | |||
$json['distributions'] = $distributionsArray; | |||
} | |||
// Commandes de l'utilisateur | |||
$ordersUserArray = [] ; | |||
if(User::getCurrentId()) { | |||
$conditionsOrdersUser = [ | |||
'distribution.date > :date' | |||
] ; | |||
$paramsOrdersUser = [ | |||
':date' => $dateMini | |||
] ; | |||
if($pointSaleId && $producer->option_order_entry_point == Producer::ORDER_ENTRY_POINT_POINT_SALE) { | |||
$conditionsOrdersUser[] = 'order.id_point_sale = :id_point_sale' ; | |||
$paramsOrdersUser[':id_point_sale'] = $pointSaleId ; | |||
} | |||
$ordersUserArray = Order::searchAll([ | |||
'id_user' => User::getCurrentId() | |||
], [ | |||
'conditions' => [ | |||
'distribution.date > :date' | |||
], | |||
'params' => [ | |||
':date' => $dateMini | |||
] | |||
'conditions' => $conditionsOrdersUser, | |||
'params' => $paramsOrdersUser | |||
]); | |||
} | |||
@@ -658,10 +684,17 @@ class OrderController extends ProducerBaseController | |||
// Commande de l'utilisateur | |||
$orderUser = false ; | |||
if(User::getCurrentId()) { | |||
$orderUser = Order::searchOne([ | |||
$conditionOrderUser = [ | |||
'distribution.date' => $date, | |||
'id_user' => User::getCurrentId(), | |||
]); | |||
] ; | |||
//if($pointSaleId && $producer->option_order_entry_point == Producer::ORDER_ENTRY_POINT_POINT_SALE) { | |||
if($pointSaleId) { | |||
$conditionOrderUser['id_point_sale'] = $pointSaleId ; | |||
} | |||
$orderUser = Order::searchOne($conditionOrderUser); | |||
} | |||
if ($orderUser) { | |||
@@ -675,59 +708,8 @@ class OrderController extends ProducerBaseController | |||
$distribution = Distribution::initDistribution($date); | |||
$json['distribution'] = $distribution; | |||
$pointsSaleArray = PointSale::find() | |||
->joinWith(['pointSaleDistribution' => function ($query) use ($distribution) { | |||
$query->where(['id_distribution' => $distribution->id]); | |||
} | |||
]) | |||
->with(['userPointSale' => function ($query) { | |||
$query->onCondition(['id_user' => User::getCurrentId()]); | |||
}]) | |||
->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'); | |||
foreach ($pointsSaleArray as &$pointSale) { | |||
$pointSale = array_merge($pointSale->getAttributes(), [ | |||
'pointSaleDistribution' => [ | |||
'id_distribution' => $pointSale->pointSaleDistribution[0]->id_distribution, | |||
'id_point_sale' => $pointSale->pointSaleDistribution[0]->id_point_sale, | |||
'delivery' => $pointSale->pointSaleDistribution[0]->delivery | |||
], | |||
'userPointSale' => ($pointSale->userPointSale ? $pointSale->userPointSale[0] : '') | |||
]); | |||
if ($pointSale['code'] && strlen($pointSale['code'])) { | |||
$pointSale['code'] = '***'; | |||
} | |||
if (!strlen($pointSale['credit_functioning'])) { | |||
$pointSale['credit_functioning'] = $creditFunctioningProducer; | |||
} | |||
} | |||
$favoritePointSale = false ; | |||
if(User::getCurrent()) { | |||
$favoritePointSale = User::getCurrent()->getFavoritePointSale(); | |||
} | |||
if ($favoritePointSale) { | |||
for ($i = 0; $i < count($pointsSaleArray); $i++) { | |||
if ($pointsSaleArray[$i]['id'] == $favoritePointSale->id) { | |||
$theFavoritePointSale = $pointsSaleArray[$i]; | |||
unset($pointsSaleArray[$i]); | |||
} | |||
} | |||
if (isset($theFavoritePointSale)) { | |||
$pointsSaleArray = array_reverse($pointsSaleArray, false); | |||
$pointsSaleArray[] = $theFavoritePointSale; | |||
$pointsSaleArray = array_reverse($pointsSaleArray, false); | |||
} | |||
} | |||
$json['points_sale'] = $pointsSaleArray; | |||
// Points de vente | |||
$json['points_sale'] = $this->_initPointsSale($producer->id, $distribution); | |||
// Commandes totales | |||
$ordersArray = Order::searchAll([ | |||
@@ -808,10 +790,77 @@ class OrderController extends ProducerBaseController | |||
$json['products'] = $productsArray; | |||
} | |||
else { | |||
$json['points_sale'] = $this->_initPointsSale($producer->id) ; | |||
} | |||
return $json; | |||
} | |||
private function _initPointsSale($idProducer, $distribution = false) | |||
{ | |||
$pointsSaleArray = PointSale::find() ; | |||
if($distribution) { | |||
$pointsSaleArray = $pointsSaleArray->joinWith(['pointSaleDistribution' => function ($query) use ($distribution) { | |||
$query->where(['id_distribution' => $distribution->id]); | |||
} | |||
]) ; | |||
} | |||
if(User::getCurrentId()) { | |||
$pointsSaleArray = $pointsSaleArray->with(['userPointSale' => function ($query) { | |||
$query->onCondition(['id_user' => User::getCurrentId()]); | |||
}]) ; | |||
} | |||
$pointsSaleArray = $pointsSaleArray->where(['id_producer' => $idProducer]) | |||
->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'); | |||
foreach ($pointsSaleArray as &$pointSale) { | |||
$pointSale = array_merge($pointSale->getAttributes(), [ | |||
'pointSaleDistribution' => [ | |||
'id_distribution' => $pointSale->pointSaleDistribution ? $pointSale->pointSaleDistribution[0]->id_distribution : false, | |||
'id_point_sale' => $pointSale->pointSaleDistribution ? $pointSale->pointSaleDistribution[0]->id_point_sale : false, | |||
'delivery' => $pointSale->pointSaleDistribution ? $pointSale->pointSaleDistribution[0]->delivery : false, | |||
], | |||
'userPointSale' => ($pointSale->userPointSale ? $pointSale->userPointSale[0] : '') | |||
]); | |||
if ($pointSale['code'] && strlen($pointSale['code'])) { | |||
$pointSale['code'] = '***'; | |||
} | |||
if (!strlen($pointSale['credit_functioning'])) { | |||
$pointSale['credit_functioning'] = $creditFunctioningProducer; | |||
} | |||
} | |||
$favoritePointSale = false ; | |||
if(User::getCurrent()) { | |||
$favoritePointSale = User::getCurrent()->getFavoritePointSale(); | |||
} | |||
if ($favoritePointSale) { | |||
for ($i = 0; $i < count($pointsSaleArray); $i++) { | |||
if ($pointsSaleArray[$i]['id'] == $favoritePointSale->id) { | |||
$theFavoritePointSale = $pointsSaleArray[$i]; | |||
unset($pointsSaleArray[$i]); | |||
} | |||
} | |||
if (isset($theFavoritePointSale)) { | |||
$pointsSaleArray = array_reverse($pointsSaleArray, false); | |||
$pointsSaleArray[] = $theFavoritePointSale; | |||
$pointsSaleArray = array_reverse($pointsSaleArray, false); | |||
} | |||
} | |||
return $pointsSaleArray ; | |||
} | |||
public function actionConfirm($idOrder) | |||
{ | |||
$order = Order::searchOne(['id' => $idOrder]); |
@@ -48,7 +48,13 @@ $producer = GlobalParam::getCurrentProducer() ; | |||
?> | |||
<script> | |||
var appInitValues = { | |||
}; | |||
</script> | |||
<div id="app-order-order" :class="{'loaded': !loadingInit}"> | |||
<?php if(isset($order)): ?> | |||
<span id="order-distribution-date"><?= $order->distribution->date; ?></span> | |||
<?php endif; ?> | |||
@@ -62,22 +68,38 @@ $producer = GlobalParam::getCurrentProducer() ; | |||
<div> | |||
<div id="steps"> | |||
<ul> | |||
<li id="step-date" :class="'col-md-3 '+((step == 'date') ? 'active' : '')"> | |||
<button @click="changeStep('date')" :class="'btn '+ (step == 'date' ? 'btn-primary' : 'btn-default')"> | |||
<span class="button-content"><span class="glyphicon glyphicon-time"></span> Date</span></span> | |||
</button> | |||
<div class="info-step" v-if="dateFormat"> | |||
{{ dateFormat }} | |||
</div> | |||
</li> | |||
<li id="step-point-sale" :class="'col-md-3 '+((step == 'point-sale') ? 'active ' : '')"> | |||
<button @click="changeStep('point-sale')" :class="'btn '+ (step == 'point-sale' ? 'btn-primary' : 'btn-default')" :disabled="step == 'date'"> | |||
<span class="button-content"><span class="glyphicon glyphicon-map-marker"></span> Points de vente</span> | |||
</button> | |||
<div class="info-step" v-if="pointSaleActive"> | |||
{{ pointSaleActive.name }} | |||
</div> | |||
</li> | |||
<?php if($producer->option_order_entry_point == Producer::ORDER_ENTRY_POINT_DATE): ?> | |||
<step-date | |||
first="true" | |||
:step="step" | |||
:point-sale-active="pointSaleActive" | |||
:date-format="dateFormat" | |||
:change-step="changeStep" | |||
:producer="producer" | |||
></step-date> | |||
<step-point-sale | |||
:step="step" | |||
:point-sale-active="pointSaleActive" | |||
:change-step="changeStep" | |||
:producer="producer" | |||
></step-point-sale> | |||
<?php else: ?> | |||
<step-point-sale | |||
first="true" | |||
:step="step" | |||
:point-sale-active="pointSaleActive" | |||
:change-step="changeStep" | |||
:producer="producer" | |||
></step-point-sale> | |||
<step-date | |||
:step="step" | |||
:point-sale-active="pointSaleActive" | |||
:date-format="dateFormat" | |||
:change-step="changeStep" | |||
:producer="producer" | |||
></step-date> | |||
<?php endif; ?> | |||
<li id="step-products" :class="'col-md-3 '+((step == 'products') ? 'active ' : '')"> | |||
<button @click="changeStep('products')" :class="'btn '+ (step == 'products' ? 'btn-primary' : 'btn-default')" :disabled="step == 'date' || step == 'point-sale'"> | |||
<span class="button-content"><span class="glyphicon glyphicon-th-list"></span> Produits</span> | |||
@@ -102,8 +124,15 @@ $producer = GlobalParam::getCurrentProducer() ; | |||
</li> | |||
</ul> | |||
</div> | |||
<div v-if="loading && !step"> | |||
Chargement ... | |||
</div> | |||
<transition name="slide"> | |||
<div id="content-step-date" v-if="step == 'date'"> | |||
<div v-if="loading"> | |||
Chargement ... | |||
</div> | |||
<div v-else> | |||
<?php if($producer->behavior_order_select_distribution == Producer::BEHAVIOR_ORDER_SELECT_DISTRIBUTION_LIST ): ?> | |||
<div style="display:none ;"> | |||
<?php endif; ?> | |||
@@ -166,6 +195,7 @@ $producer = GlobalParam::getCurrentProducer() ; | |||
<?php endforeach; ?> | |||
</div> | |||
<?php endif; ?> | |||
</div> | |||
</div> | |||
</transition> | |||
<transition name="slide"> | |||
@@ -184,7 +214,7 @@ $producer = GlobalParam::getCurrentProducer() ; | |||
</tr> | |||
</thead> | |||
<tbody> | |||
<tr v-for="pointSale in orderedPointsSale" v-if="pointSale && pointSale.pointSaleDistribution.delivery" :class="(pointSaleActive && pointSale.id == pointSaleActive.id) ? 'selected' : ''"> | |||
<tr v-for="pointSale in orderedPointsSale" v-if="pointSale && (producer.option_order_entry_point == 'point-sale' || (producer.option_order_entry_point == 'date' && pointSale.pointSaleDistribution.delivery))" :class="(pointSaleActive && pointSale.id == pointSaleActive.id) ? 'selected' : ''"> | |||
<td class="name"> | |||
<span class="the-name">{{ pointSale.name }}</span> | |||
<div class="comment" v-if="pointSale.userPointSale"> | |||
@@ -215,96 +245,101 @@ $producer = GlobalParam::getCurrentProducer() ; | |||
</transition> | |||
<transition name="slide"> | |||
<div id="content-step-products" v-if="step == 'products'"> | |||
<div v-if="products.length"> | |||
<table id="products" class="table table-bordered" > | |||
<thead> | |||
<tr> | |||
<th>Photo</th> | |||
<th>Nom</th> | |||
<th>Prix unitaire</th> | |||
<th>Quantité</th> | |||
<th>Total</th> | |||
</tr> | |||
</thead> | |||
<tbody> | |||
<template v-for="category in categories"> | |||
<tr v-if="category.id && countProductsByCategory(category)"> | |||
<td class="category-name" colspan="5" @click="setCategoryCurrent(category)"> | |||
<span v-if="categoryCurrent && categoryCurrent.id == category.id" class="glyphicon glyphicon-triangle-bottom"></span> | |||
<span v-else class="glyphicon glyphicon-triangle-right"></span> | |||
{{ category.name }} | |||
<span class="label label-default">{{ countProductsByCategory(category) }} produit<template v-if="countProductsByCategory(category) > 1">s</template></span> | |||
<span v-if="countSelectedProductsByCategory(category) > 0" class="label label-success">{{ countSelectedProductsByCategory(category) }} produit<template v-if="countSelectedProductsByCategory(category) > 1">s</template> sélectionné<template v-if="countSelectedProductsByCategory(category) > 1">s</template></span> | |||
</td> | |||
<div v-if="loading"> | |||
Chargement ... | |||
</div> | |||
<div v-else> | |||
<div v-if="products.length"> | |||
<table id="products" class="table table-bordered" > | |||
<thead> | |||
<tr> | |||
<th>Photo</th> | |||
<th>Nom</th> | |||
<th>Prix unitaire</th> | |||
<th>Quantité</th> | |||
<th>Total</th> | |||
</tr> | |||
<template v-if="(categoryCurrent && categoryCurrent.id == category.id) || category.id == null"> | |||
<tr v-for="product in products" v-if="product.id_product_category == category.id && product.productDistribution && product.productDistribution[0] && product.productDistribution[0].active == 1"> | |||
<td class="photo"> | |||
<img v-if="product.photo.length" class="photo-product" :src="'<?php echo Yii::$app->urlManager->getBaseUrl(); ?>/uploads/'+product.photo" /> | |||
</td> | |||
<td class="name"> | |||
<span class="name">{{ product.name }}</span> | |||
<span class="other"> | |||
<span v-if="product.description.length">/</span> | |||
<span class="description">{{ product.description }}</span> | |||
<span v-if="product.weight">({{ product.weight }} g)</span> | |||
</span> | |||
<span v-if="product.quantity_max > 0 && ((product.quantity_form / product.coefficient_unit == product.quantity_remaining) || ((product.quantity_remaining * product.coefficient_unit) - product.quantity_form) < product.step)" class="label label-danger"> | |||
Épuisé | |||
</span> | |||
<div class="recipe" v-if="product.recipe.length">{{ product.recipe }}</div> | |||
</td> | |||
<td class="price-unit"> | |||
<template v-if="product.price_with_tax > 0">{{ formatPrice(product.price_with_tax) }}<br /><span class="unit">{{ product.wording_unit }}</span></template> | |||
</td> | |||
<td class="td-quantity"> | |||
<template v-if="product.price_with_tax > 0"> | |||
<div class="input-group"> | |||
<span class="input-group-btn"> | |||
<button class="btn btn-default btn-moins" type="button" @click="productQuantityClick(product, product.unit == 'piece' ? -1 : -parseFloat(product.step))" :disabled="product.quantity_form == 0"><span class="glyphicon glyphicon-minus"></span></button> | |||
</span> | |||
<input type="text" v-model="product.quantity_form" class="form-control quantity" readonly="readonly" /> | |||
<span class="input-group-addon">{{ product.unit == 'piece' ? 'p.' : product.unit }}</span> | |||
<span class="input-group-btn"> | |||
<button class="btn btn-default btn-plus" type="button" @click="productQuantityClick(product, product.unit == 'piece' ? 1 : parseFloat(product.step))" :disabled="product.quantity_form == product.quantity_remaining && product.quantity_max > 0"><span class="glyphicon glyphicon-plus"></span></button> | |||
</span> | |||
</div> | |||
</template> | |||
</td> | |||
<td class="price-total"> | |||
<template v-if="product.price_with_tax > 0 && product.quantity_form > 0"> | |||
{{ formatPrice(product.price_with_tax * (product.quantity_form / product.coefficient_unit )) }} | |||
</template> | |||
</thead> | |||
<tbody> | |||
<template v-for="category in categories"> | |||
<tr v-if="category.id && countProductsByCategory(category)"> | |||
<td class="category-name" colspan="5" @click="setCategoryCurrent(category)"> | |||
<span v-if="categoryCurrent && categoryCurrent.id == category.id" class="glyphicon glyphicon-triangle-bottom"></span> | |||
<span v-else class="glyphicon glyphicon-triangle-right"></span> | |||
{{ category.name }} | |||
<span class="label label-default">{{ countProductsByCategory(category) }} produit<template v-if="countProductsByCategory(category) > 1">s</template></span> | |||
<span v-if="countSelectedProductsByCategory(category) > 0" class="label label-success">{{ countSelectedProductsByCategory(category) }} produit<template v-if="countSelectedProductsByCategory(category) > 1">s</template> sélectionné<template v-if="countSelectedProductsByCategory(category) > 1">s</template></span> | |||
</td> | |||
</tr> | |||
</template> | |||
</template> | |||
<tr class="total"> | |||
<td class="summary" colspan="4"> | |||
<template v-if="priceTotal() > 0"> | |||
<h3>> Résumé</h3> | |||
<ul> | |||
<li v-for="product in products" v-if="product.quantity_form > 0"> | |||
<span class="quantity">{{ product.quantity_form }} x</span> | |||
<template v-if="(categoryCurrent && categoryCurrent.id == category.id) || category.id == null"> | |||
<tr v-for="product in products" v-if="product.id_product_category == category.id && product.productDistribution && product.productDistribution[0] && product.productDistribution[0].active == 1"> | |||
<td class="photo"> | |||
<img v-if="product.photo.length" class="photo-product" :src="'<?php echo Yii::$app->urlManager->getBaseUrl(); ?>/uploads/'+product.photo" /> | |||
</td> | |||
<td class="name"> | |||
<span class="name">{{ product.name }}</span> | |||
<span class="other"> | |||
<span v-if="product.description.length">/</span> | |||
<span class="description">{{ product.description }}</span> | |||
<span v-if="product.weight">({{ product.weight }} g)</span> | |||
</li> | |||
</ul> | |||
</span> | |||
<span v-if="product.quantity_max > 0 && ((product.quantity_form / product.coefficient_unit == product.quantity_remaining) || ((product.quantity_remaining * product.coefficient_unit) - product.quantity_form) < product.step)" class="label label-danger"> | |||
Épuisé | |||
</span> | |||
<div class="recipe" v-if="product.recipe.length">{{ product.recipe }}</div> | |||
</td> | |||
<td class="price-unit"> | |||
<template v-if="product.price_with_tax > 0">{{ formatPrice(product.price_with_tax) }}<br /><span class="unit">{{ product.wording_unit }}</span></template> | |||
</td> | |||
<td class="td-quantity"> | |||
<template v-if="product.price_with_tax > 0"> | |||
<div class="input-group"> | |||
<span class="input-group-btn"> | |||
<button class="btn btn-default btn-moins" type="button" @click="productQuantityClick(product, product.unit == 'piece' ? -1 : -parseFloat(product.step))" :disabled="product.quantity_form == 0"><span class="glyphicon glyphicon-minus"></span></button> | |||
</span> | |||
<input type="text" v-model="product.quantity_form" class="form-control quantity" readonly="readonly" /> | |||
<span class="input-group-addon">{{ product.unit == 'piece' ? 'p.' : product.unit }}</span> | |||
<span class="input-group-btn"> | |||
<button class="btn btn-default btn-plus" type="button" @click="productQuantityClick(product, product.unit == 'piece' ? 1 : parseFloat(product.step))" :disabled="product.quantity_form == product.quantity_remaining && product.quantity_max > 0"><span class="glyphicon glyphicon-plus"></span></button> | |||
</span> | |||
</div> | |||
</template> | |||
</td> | |||
<td class="price-total"> | |||
<template v-if="product.price_with_tax > 0 && product.quantity_form > 0"> | |||
{{ formatPrice(product.price_with_tax * (product.quantity_form / product.coefficient_unit )) }} | |||
</template> | |||
</td> | |||
</tr> | |||
</template> | |||
</td> | |||
<td class="price-total">{{ priceTotal(true) }}</td> | |||
</tr> | |||
</tbody> | |||
</table> | |||
<div class="block-actions"> | |||
<button class="btn btn-primary" @click="changeStep('payment')">Valider</button> | |||
</template> | |||
<tr class="total"> | |||
<td class="summary" colspan="4"> | |||
<template v-if="priceTotal() > 0"> | |||
<h3>> Résumé</h3> | |||
<ul> | |||
<li v-for="product in products" v-if="product.quantity_form > 0"> | |||
<span class="quantity">{{ product.quantity_form }} {{ product.unit == 'piece' ? 'p.' : product.unit }} x</span> | |||
<span class="name">{{ product.name }}</span> | |||
<span class="other"> | |||
<span v-if="product.description.length">/</span> | |||
<span class="description">{{ product.description }}</span> | |||
<span v-if="product.weight">({{ product.weight }} g)</span> | |||
</li> | |||
</ul> | |||
</template> | |||
</td> | |||
<td class="price-total">{{ priceTotal(true) }}</td> | |||
</tr> | |||
</tbody> | |||
</table> | |||
<div class="block-actions"> | |||
<button class="btn btn-primary" @click="changeStep('payment')">Valider</button> | |||
</div> | |||
</div> | |||
<div class="alert alert-warning" v-else> | |||
Aucun produit disponible | |||
</div> | |||
</div> | |||
<div class="alert alert-warning" v-else> | |||
Aucun produit disponible | |||
</div> | |||
</div> | |||
</transition> | |||
@@ -451,4 +486,26 @@ $producer = GlobalParam::getCurrentProducer() ; | |||
</div> | |||
<?php endif; ?> | |||
</div> | |||
</div> | |||
</div> | |||
<script type="text/x-template" id="template-step-date"> | |||
<li id="step-date" :class="'col-md-3'+((step == 'date') ? ' active' : '')+(first ? ' first' : '')"> | |||
<button @click="changeStep('date')" :class="'btn '+ (step == 'date' ? 'btn-primary' : 'btn-default')" :disabled="producer && producer.option_order_entry_point == 'point-sale' && !pointSaleActive"> | |||
<span class="button-content"><span class="glyphicon glyphicon-time"></span> Date</span></span> | |||
</button> | |||
<div class="info-step" v-if="dateFormat"> | |||
{{ dateFormat }} | |||
</div> | |||
</li> | |||
</script> | |||
<script type="text/x-template" id="template-step-point-sale"> | |||
<li id="step-point-sale" :class="'col-md-3'+((step == 'point-sale') ? ' active ' : '')+(first ? ' first' : '')"> | |||
<button @click="changeStep('point-sale')" :class="'btn '+ (step == 'point-sale' ? 'btn-primary' : 'btn-default')" :disabled="producer && (producer.option_order_entry_point == 'date' && step == 'date')"> | |||
<span class="button-content"><span class="glyphicon glyphicon-map-marker"></span> Points de vente</span> | |||
</button> | |||
<div class="info-step" v-if="pointSaleActive"> | |||
{{ pointSaleActive.name }} | |||
</div> | |||
</li> | |||
</script> |
@@ -1359,7 +1359,7 @@ termes. | |||
top: 10px; | |||
} | |||
/* line 61, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order #steps ul li#step-date { | |||
.order-order #main #app-order-order #steps ul li.first { | |||
padding-left: 0px; | |||
} | |||
/* line 65, ../sass/order/_order.scss */ | |||
@@ -1367,7 +1367,7 @@ termes. | |||
padding-right: 0px; | |||
} | |||
/* line 69, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order #steps ul li#step-payment .btn::after, .order-order #main #app-order-order #steps ul li#step-date .btn::before { | |||
.order-order #main #app-order-order #steps ul li#step-payment .btn::after, .order-order #main #app-order-order #steps ul li.first .btn::before { | |||
display: none; | |||
} | |||
/* line 74, ../sass/order/_order.scss */ |
@@ -1,67 +1,70 @@ | |||
var app = new Vue({ | |||
el: '#app-order-order', | |||
data: { | |||
loading: false, | |||
loadingInit: true, | |||
step: 'date', | |||
producer: null, | |||
user: null, | |||
date: null, | |||
dateFormat: null, | |||
distributions: [], | |||
distribution: null, | |||
pointsSale: [], | |||
pointSaleActive: null, | |||
pointsSaleCodes: [], | |||
products: [], | |||
categories: [], | |||
categoryCurrent: null, | |||
comment: '', | |||
creditCheckbox: false, | |||
useCredit: false, | |||
errors: [], | |||
disableConfirmButton: false, | |||
calendar: { | |||
mode: 'single', | |||
attrs: [], | |||
availableDates: [], | |||
themeStyles: { | |||
wrapper: { | |||
background: '#F7F7F7', | |||
color: '#333', | |||
border: 'solid 1px #e0e0e0' | |||
}, | |||
header: { | |||
padding: '10px 10px', | |||
}, | |||
headerHorizontalDivider: { | |||
borderTop: 'solid rgba(255, 255, 255, 0.2) 1px', | |||
width: '80%', | |||
}, | |||
weekdays: { | |||
color: 'gray', | |||
fontWeight: '600', | |||
padding: '10px 10px', | |||
fontSize: '2rem' | |||
}, | |||
weeks: { | |||
padding: '0 15px 15px 15px', | |||
}, | |||
dayContent: function(object) { | |||
var style = { | |||
fontSize: '1.5rem', | |||
padding: '20px', | |||
}; | |||
return style ; | |||
data() { | |||
return Object.assign({ | |||
loading: false, | |||
loadingInit: true, | |||
step: null, | |||
producer: null, | |||
user: null, | |||
date: null, | |||
dateFormat: null, | |||
distributions: [], | |||
distribution: null, | |||
pointsSale: [], | |||
pointSaleActive: null, | |||
pointsSaleCodes: [], | |||
products: [], | |||
categories: [], | |||
categoryCurrent: null, | |||
comment: '', | |||
creditCheckbox: false, | |||
useCredit: false, | |||
errors: [], | |||
disableConfirmButton: false, | |||
calendar: { | |||
mode: 'single', | |||
attrs: [], | |||
availableDates: [], | |||
themeStyles: { | |||
wrapper: { | |||
background: '#F7F7F7', | |||
color: '#333', | |||
border: 'solid 1px #e0e0e0' | |||
}, | |||
header: { | |||
padding: '10px 10px', | |||
}, | |||
headerHorizontalDivider: { | |||
borderTop: 'solid rgba(255, 255, 255, 0.2) 1px', | |||
width: '80%', | |||
}, | |||
weekdays: { | |||
color: 'gray', | |||
fontWeight: '600', | |||
padding: '10px 10px', | |||
fontSize: '2rem' | |||
}, | |||
weeks: { | |||
padding: '0 15px 15px 15px', | |||
}, | |||
dayContent: function (object) { | |||
var style = { | |||
fontSize: '1.5rem', | |||
padding: '20px', | |||
}; | |||
return style; | |||
}, | |||
}, | |||
}, | |||
formats: { | |||
dayPopover: 'DD/MM/YYYY' | |||
formats: { | |||
dayPopover: 'DD/MM/YYYY' | |||
} | |||
} | |||
}, | |||
}, window.appInitValues); | |||
}, | |||
mounted: function() { | |||
mounted: function() { | |||
if($('#order-distribution-date').size() || $('#distribution-date').size()) { | |||
if($('#order-distribution-date').size()) { | |||
this.date = new Date($('#order-distribution-date').html()) ; | |||
@@ -73,10 +76,13 @@ var app = new Vue({ | |||
this.dateFormat = ('0' + this.date.getDate()).slice(-2)+ '/' | |||
+ ('0' + (this.date.getMonth() +1)).slice(-2) + '/' | |||
+ this.date.getFullYear() ; | |||
this.changeStep('point-sale') ; | |||
if(this.producer.option_order_entry_point == 'date') { | |||
this.changeStep('point-sale') ; | |||
} | |||
} | |||
this.init() ; | |||
this.init('first') ; | |||
this.loadingInit = false ; | |||
}, | |||
methods: { | |||
@@ -106,75 +112,90 @@ var app = new Vue({ | |||
} | |||
} | |||
}, | |||
init: function(updateOnlyProducts) { | |||
init: function(type) { | |||
var app = this ; | |||
this.loading = true ; | |||
axios.get("ajax-infos",{params: { | |||
date : this.getDate(), | |||
pointSaleId: this.pointSaleActive ? this.pointSaleActive.id : 0 | |||
}}) | |||
.then(function(response) { | |||
if(!updateOnlyProducts) { | |||
app.producer = response.data.producer; | |||
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; | |||
if (distributions.length) { | |||
app.distributions = distributions; | |||
var arrayDate; | |||
for (var i = 0; i < distributions.length; i++) { | |||
var distributions = response.data.distributions; | |||
app.calendar.attrs = []; | |||
app.calendar.availableDates = []; | |||
if (distributions.length) { | |||
app.distributions = distributions; | |||
var arrayDate; | |||
for (var i = 0; i < distributions.length; i++) { | |||
app.calendar.attrs.push({ | |||
highlight: { | |||
backgroundColor: '#5cb85c', | |||
}, | |||
contentStyle: { | |||
color: 'white', | |||
}, | |||
dates: distributions[i].date, | |||
}); | |||
arrayDate = distributions[i].date.split('-'); | |||
app.calendar.availableDates.push({ | |||
start: new Date(arrayDate[0], arrayDate[1] - 1, arrayDate[2]), | |||
end: new Date(arrayDate[0], arrayDate[1] - 1, arrayDate[2]) | |||
}); | |||
} | |||
} | |||
if (response.data.distribution) { | |||
app.distribution = response.data.distribution; | |||
} | |||
var orders = []; | |||
if (response.data.orders) { | |||
orders = response.data.orders; | |||
} | |||
if (orders.length) { | |||
for (var i = 0; i < orders.length; i++) { | |||
arrayDate = orders[i].date_distribution.split('-'); | |||
var dateOrder = new Date(arrayDate[0], arrayDate[1] - 1, arrayDate[2]); | |||
if (app.isAvailableDate(dateOrder)) { | |||
app.calendar.attrs.push({ | |||
highlight: { | |||
backgroundColor: '#5cb85c', | |||
backgroundColor: '#FF7F00' | |||
}, | |||
contentStyle: { | |||
color: 'white', | |||
color: 'white' | |||
}, | |||
dates: distributions[i].date, | |||
}); | |||
arrayDate = distributions[i].date.split('-'); | |||
app.calendar.availableDates.push({ | |||
start: new Date(arrayDate[0], arrayDate[1] - 1, arrayDate[2]), | |||
end: new Date(arrayDate[0], arrayDate[1] - 1, arrayDate[2]) | |||
popover: { | |||
label: orders[i].pointSale.name + ' / ' + app.formatPrice(orders[i].amount_total), | |||
hideIndicator: true | |||
}, | |||
dates: orders[i].date_distribution, | |||
}); | |||
} | |||
} | |||
var orders = []; | |||
if (response.data.orders) { | |||
orders = response.data.orders; | |||
} | |||
} | |||
if (orders.length) { | |||
for (var i = 0; i < orders.length; i++) { | |||
arrayDate = orders[i].date_distribution.split('-'); | |||
var dateOrder = new Date(arrayDate[0], arrayDate[1] - 1, arrayDate[2]); | |||
if (app.isAvailableDate(dateOrder)) { | |||
app.calendar.attrs.push({ | |||
highlight: { | |||
backgroundColor: '#FF7F00' | |||
}, | |||
contentStyle: { | |||
color: 'white' | |||
}, | |||
popover: { | |||
label: orders[i].pointSale.name + ' / ' + app.formatPrice(orders[i].amount_total), | |||
hideIndicator: true | |||
}, | |||
dates: orders[i].date_distribution, | |||
}); | |||
} | |||
} | |||
} | |||
if(response.data.products) { | |||
app.products = response.data.products ; | |||
} | |||
if (response.data.distribution) { | |||
app.distribution = response.data.distribution; | |||
} | |||
if(response.data.categories) { | |||
app.categories = response.data.categories ; | |||
app.setCategoryCurrent(response.data.categories[0]) ; | |||
} | |||
if(type != 'products') { | |||
app.producer = response.data.producer; | |||
app.user = response.data.user; | |||
app.useCredit = response.data.producer.use_credit_checked_default; | |||
if (response.data.points_sale) { | |||
app.pointsSale = []; | |||
@@ -186,19 +207,7 @@ var app = new Vue({ | |||
Vue.set(app.pointsSaleCodes, response.data.points_sale[key].id, ''); | |||
} | |||
} | |||
} | |||
if(response.data.products) { | |||
app.products = response.data.products ; | |||
} | |||
if(response.data.categories) { | |||
app.categories = response.data.categories ; | |||
console.log(response.data.categories[0]) ; | |||
app.setCategoryCurrent(response.data.categories[0]) ; | |||
} | |||
if(!updateOnlyProducts) { | |||
app.order = null ; | |||
if(response.data.order) { | |||
app.order = response.data.order ; | |||
@@ -209,9 +218,49 @@ var app = new Vue({ | |||
} | |||
} | |||
if(type == 'first') { | |||
if(app.producer.option_order_entry_point == 'point-sale') { | |||
app.step = 'point-sale' ; | |||
} | |||
else { | |||
app.step = 'date' ; | |||
} | |||
} | |||
app.loading = false ; | |||
}); | |||
}, | |||
nextStep: function() { | |||
this.errors = [] ; | |||
var oldStep = this.step ; | |||
var nextStep = null ; | |||
// par point de vente | |||
if(this.producer && this.producer.option_order_entry_point == 'point-sale') { | |||
if(oldStep == 'point-sale') { | |||
nextStep = 'date' ; | |||
} | |||
else if(oldStep == 'date') { | |||
nextStep = 'products' ; | |||
} | |||
} | |||
// par date | |||
else { | |||
if(oldStep == 'date') { | |||
nextStep = 'point-sale' ; | |||
} | |||
else if(oldStep == 'point-sale') { | |||
nextStep = 'products' ; | |||
} | |||
} | |||
if(nextStep) { | |||
this.changeStep(nextStep) ; | |||
} | |||
}, | |||
changeStep: function(step) { | |||
this.errors = [] ; | |||
var oldStep = this.step ; | |||
@@ -222,8 +271,16 @@ var app = new Vue({ | |||
if(!this.errors.length) { | |||
this.step = step ; | |||
window.scroll(0, $('#page-title').position().top - 25) ; | |||
if(oldStep == 'date' && step == 'point-sale') { | |||
this.init() ; | |||
this.init('basic') ; | |||
} | |||
if((oldStep == 'date' && step == 'products') | |||
|| (oldStep == 'point-sale' && step == 'products') | |||
|| (oldStep == 'point-sale' && step == 'date')) { | |||
this.init('products') ; | |||
} | |||
} | |||
}, | |||
@@ -244,7 +301,8 @@ var app = new Vue({ | |||
this.dateFormat = ('0' + this.date.getDate()).slice(-2)+ '/' | |||
+ ('0' + (this.date.getMonth() +1)).slice(-2) + '/' | |||
+ this.date.getFullYear() ; | |||
this.changeStep('point-sale') ; | |||
this.nextStep() ; | |||
}, | |||
isAvailableDate: function(date) { | |||
for(var key in this.calendar.availableDates) { | |||
@@ -278,8 +336,6 @@ var app = new Vue({ | |||
else { | |||
this.validatePointSale(idPointSale) ; | |||
} | |||
app.init(true) ; | |||
}, | |||
validatePointSale: function(idPointSale) { | |||
@@ -287,8 +343,8 @@ var app = new Vue({ | |||
if(this.pointSaleActive.credit_functioning == 'mandatory' || (this.pointSaleActive.credit_functioning == 'user' && this.user.credit_active)) { | |||
this.useCredit = true ; | |||
} | |||
this.changeStep('products') ; | |||
this.nextStep() ; | |||
}, | |||
productQuantityClick: function(product, quantity) { | |||
if( this.products[product.index].quantity_form + quantity >= 0 && | |||
@@ -494,4 +550,39 @@ var app = new Vue({ | |||
} | |||
}); | |||
} | |||
}); | |||
}); | |||
Vue.component('step-date',{ | |||
props: [ | |||
'step', | |||
'pointSaleActive', | |||
'dateFormat', | |||
'changeStep', | |||
'producer', | |||
'first', | |||
], | |||
data: function() { | |||
return { | |||
} ; | |||
}, | |||
template: '#template-step-date', | |||
methods: { | |||
} | |||
}) ; | |||
Vue.component('step-point-sale',{ | |||
props: [ | |||
'step', | |||
'pointSaleActive', | |||
'changeStep', | |||
'producer', | |||
'first', | |||
], | |||
data: function() { | |||
return { | |||
} ; | |||
}, | |||
template: '#template-step-point-sale', | |||
methods: { | |||
} | |||
}) ; |
@@ -57,8 +57,8 @@ | |||
position: relative ; | |||
top: 10px ; | |||
} | |||
&#step-date { | |||
&.first { | |||
padding-left: 0px ; | |||
} | |||
@@ -67,7 +67,7 @@ | |||
} | |||
&#step-payment .btn::after, | |||
&#step-date .btn::before { | |||
&.first .btn::before { | |||
display: none ; | |||
} | |||