Kaynağa Gözat

Merge branch 'feature/order_by_point_sale' into dev

refactoring
Guillaume 3 yıl önce
ebeveyn
işleme
41a597d42a
9 değiştirilmiş dosya ile 542 ekleme ve 297 silme
  1. +6
    -0
      backend/views/producer/update.php
  2. +20
    -0
      common/models/Distribution.php
  3. +5
    -1
      common/models/Producer.php
  4. +18
    -0
      console/migrations/m210326_104759_add_option_order_entry_point.php
  5. +111
    -62
      producer/controllers/OrderController.php
  6. +155
    -98
      producer/views/order/order.php
  7. +2
    -2
      producer/web/css/screen.css
  8. +222
    -131
      producer/web/js/vuejs/order-order.js
  9. +3
    -3
      producer/web/sass/order/_order.scss

+ 6
- 0
backend/views/producer/update.php Dosyayı Görüntüle

@@ -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>


+ 20
- 0
common/models/Distribution.php Dosyayı Görüntüle

@@ -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.
*/

+ 5
- 1
common/models/Producer.php Dosyayı Görüntüle

@@ -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'
];
}


+ 18
- 0
console/migrations/m210326_104759_add_option_order_entry_point.php Dosyayı Görüntüle

@@ -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');
}

}

+ 111
- 62
producer/controllers/OrderController.php Dosyayı Görüntüle

@@ -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]);

+ 155
- 98
producer/views/order/order.php Dosyayı Görüntüle

@@ -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 }}&nbsp;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>&gt; 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 }}&nbsp;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>&gt; 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 }}&nbsp;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>

+ 2
- 2
producer/web/css/screen.css Dosyayı Görüntüle

@@ -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 */

+ 222
- 131
producer/web/js/vuejs/order-order.js Dosyayı Görüntüle

@@ -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: {
}
}) ;

+ 3
- 3
producer/web/sass/order/_order.scss Dosyayı Görüntüle

@@ -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 ;
}

Yükleniyor…
İptal
Kaydet