Browse Source

Merge branch 'feature/vente_au_poids' into dev

dev
Guillaume Bourgeois 5 years ago
parent
commit
dca8a8394b
41 changed files with 1039 additions and 227 deletions
  1. +62
    -0
      backend/assets/VuejsSubscriptionFormAsset.php
  2. +44
    -19
      backend/controllers/DistributionController.php
  3. +14
    -2
      backend/controllers/OrderController.php
  4. +53
    -1
      backend/controllers/SubscriptionController.php
  5. +25
    -8
      backend/views/distribution/index.php
  6. +19
    -15
      backend/views/distribution/report.php
  7. +55
    -40
      backend/views/product/_form.php
  8. +12
    -0
      backend/views/product/index.php
  9. +35
    -26
      backend/views/site/index.php
  10. +25
    -9
      backend/views/subscription/_form.php
  11. +8
    -2
      backend/views/subscription/index.php
  12. +85
    -17
      backend/web/css/screen.css
  13. +51
    -0
      backend/web/js/lechatdesnoisettes.js
  14. +7
    -4
      backend/web/js/vuejs/distribution-index.js
  15. +90
    -0
      backend/web/js/vuejs/subscription-form.js
  16. +26
    -4
      backend/web/sass/distribution/_index.scss
  17. +8
    -3
      backend/web/sass/product/_form.scss
  18. +1
    -0
      backend/web/sass/screen.scss
  19. +1
    -0
      backend/web/sass/site/_index.scss
  20. +29
    -0
      backend/web/sass/subscription/_form.scss
  21. +16
    -10
      common/models/Order.php
  22. +84
    -8
      common/models/Product.php
  23. +3
    -0
      common/models/ProductOrder.php
  24. +21
    -0
      common/models/Subscription.php
  25. +39
    -7
      common/models/SubscriptionForm.php
  26. +26
    -0
      console/migrations/m190508_155647_ajout_champs_vente_kilo.php
  27. +15
    -0
      console/migrations/m190510_074749_ajout_champs_product_order_step.php
  28. +17
    -0
      console/migrations/m190511_061123_ajout_champs_unit_product_subscription.php
  29. +27
    -0
      console/migrations/m190515_122438_ajout_champs_price_product_subscription.php
  30. +24
    -7
      producer/controllers/OrderController.php
  31. +17
    -11
      producer/controllers/SubscriptionController.php
  32. +4
    -1
      producer/views/order/_form.php
  33. +8
    -7
      producer/views/order/order.php
  34. +1
    -1
      producer/views/site/index.php
  35. +7
    -4
      producer/views/subscription/_form.php
  36. +2
    -1
      producer/views/subscription/index.php
  37. +41
    -13
      producer/web/css/screen.css
  38. +9
    -3
      producer/web/js/vuejs/order-order.js
  39. +1
    -1
      producer/web/js/vuejs/subscription-form.js
  40. +14
    -1
      producer/web/sass/order/_order.scss
  41. +13
    -2
      producer/web/sass/subscription/_form.scss

+ 62
- 0
backend/assets/VuejsSubscriptionFormAsset.php View File

@@ -0,0 +1,62 @@
<?php
/**
Copyright distrib (2018)

contact@opendistrib.net

Ce logiciel est un programme informatique servant à aider les producteurs
à distribuer leur production en circuits courts.

Ce logiciel est régi par la licence CeCILL soumise au droit français et
respectant les principes de diffusion des logiciels libres. Vous pouvez
utiliser, modifier et/ou redistribuer ce programme sous les conditions
de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA
sur le site "http://www.cecill.info".

En contrepartie de l'accessibilité au code source et des droits de copie,
de modification et de redistribution accordés par cette licence, il n'est
offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons,
seule une responsabilité restreinte pèse sur l'auteur du programme, le
titulaire des droits patrimoniaux et les concédants successifs.

A cet égard l'attention de l'utilisateur est attirée sur les risques
associés au chargement, à l'utilisation, à la modification et/ou au
développement et à la reproduction du logiciel par l'utilisateur étant
donné sa spécificité de logiciel libre, qui peut le rendre complexe à
manipuler et qui le réserve donc à des développeurs et des professionnels
avertis possédant des connaissances informatiques approfondies. Les
utilisateurs sont donc invités à charger et tester l'adéquation du
logiciel à leurs besoins dans des conditions permettant d'assurer la
sécurité de leurs systèmes et ou de leurs données et, plus généralement,
à l'utiliser et l'exploiter dans les mêmes conditions de sécurité.

Le fait que vous puissiez accéder à cet en-tête signifie que vous avez
pris connaissance de la licence CeCILL, et que vous en avez accepté les
termes.
*/

namespace backend\assets;

use yii\web\AssetBundle;
use yii ;

/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class VuejsSubscriptionFormAsset extends \common\components\MyAssetBundle
{
public $basePath = '@webroot';
public $baseUrl = '@web';
public $css = [];
public $js = [];
public $depends = [
'common\assets\CommonAsset'
];
public function __construct()
{
parent::__construct() ;
$this->addAsset('js','js/vuejs/subscription-form.js') ;
}
}

+ 44
- 19
backend/controllers/DistributionController.php View File

@@ -164,8 +164,13 @@ class DistributionController extends BackendController
foreach($productsArray as &$theProduct) {
$quantityOrder = Order::getProductQuantity($theProduct['id'], $ordersArray) ;
$theProduct['quantity_ordered'] = $quantityOrder ;
$theProduct['quantity_remaining'] = $theProduct['quantity_max'] - $quantityOrder ;
if($theProduct['quantity_remaining'] < 0) $theProduct['quantity_remaining'] = 0 ;
if(!is_numeric($theProduct['productDistribution'][0]['quantity_max'])) {
$theProduct['quantity_remaining'] = null ;
}
else {
$theProduct['quantity_remaining'] = $theProduct['productDistribution'][0]['quantity_max'] - $quantityOrder ;
}
$theProduct['quantity_form'] = 0 ;
if($theProduct['productDistribution'][0]['active'] && $theProduct['productDistribution'][0]['quantity_max']) {
@@ -181,11 +186,24 @@ class DistributionController extends BackendController
// orders as array
if($ordersArray) {
foreach($ordersArray as &$order) {
$productOrderArray = \yii\helpers\ArrayHelper::map($order->productOrder, 'id_product', 'quantity') ;
foreach($ordersArray as &$order) {
$productOrderArray = [] ;
foreach($order->productOrder as $productOrder) {
$productOrderArray[$productOrder->id_product] = [
'quantity' => $productOrder->quantity * Product::$unitsArray[$productOrder->unit]['coefficient'],
'unit' => $productOrder->unit,
] ;
}
/*$productOrderArray = \yii\helpers\ArrayHelper::map($order->productOrder, 'id_product', 'quantity') ;
*/
foreach($productsArray as $product) {
if(!isset($productOrderArray[$product['id']])) {
$productOrderArray[$product['id']] = 0 ;
$productOrderArray[$product['id']] = [
'quantity' => 0,
'unit' => $product['unit']
] ;
}
}
@@ -254,7 +272,10 @@ class DistributionController extends BackendController
// order create
$productOrderArray = [] ;
foreach($productsArray as $product) {
$productOrderArray[$product['id']] = 0 ;
$productOrderArray[$product['id']] = [
'quantity' => 0,
'unit' => $product['unit']
] ;
}
$json['order_create'] = [
'id_point_sale' => $idPointSaleDefault,
@@ -443,7 +464,7 @@ class DistributionController extends BackendController
foreach($pointSale->orders as $order) {
$orderLine = [$order->getStrUser()] ;
foreach($order->productOrder as $productOrder) {
$orderLine[$productsIndexArray[$productOrder->id_product]] = $productOrder->quantity ;
$orderLine[$productsIndexArray[$productOrder->id_product]] = $productOrder->quantity . ' '.Product::strUnit($productOrder->unit, 'wording_short', true);
}
$datas[] = $this->_lineOrderReportCSV($orderLine, $cpt) ;
}
@@ -451,13 +472,15 @@ class DistributionController extends BackendController
// total point de vente
$totalsPointSaleArray = ['Total'] ;
foreach ($productsArray as $product) {
$quantity = Order::getProductQuantity($product->id, $pointSale->orders);
if($quantity) {
$index = $productsIndexArray[$product->id] ;
if(!isset($totalsPointSaleArray[$index])) {
$totalsPointSaleArray[$index] = 0 ;
foreach(Product::$unitsArray as $unit => $dataUnit) {
$quantity = Order::getProductQuantity($product->id, $pointSale->orders, false, $unit);
if ($quantity) {
$index = $productsIndexArray[$product->id] ;
if(!isset($totalsPointSaleArray[$index])) {
$totalsPointSaleArray[$index] = '' ;
}
$totalsPointSaleArray[$index] .= $quantity . ' '.Product::strUnit($unit, 'wording_short', true).' ';
}
$totalsPointSaleArray[$index] += $quantity ;
}
}
@@ -469,13 +492,15 @@ class DistributionController extends BackendController
// global
$totalsGlobalArray = ['> Totaux'] ;
foreach ($productsArray as $product) {
$quantity = Order::getProductQuantity($product->id, $ordersArray);
if($quantity) {
$index = $productsIndexArray[$product->id] ;
if(!isset($totalsGlobalArray[$index])) {
$totalsGlobalArray[$index] = 0 ;
foreach(Product::$unitsArray as $unit => $dataUnit) {
$quantity = Order::getProductQuantity($product->id, $ordersArray, false, $unit);
if ($quantity) {
$index = $productsIndexArray[$product->id] ;
if(!isset($totalsGlobalArray[$index])) {
$totalsGlobalArray[$index] = '' ;
}
$totalsGlobalArray[$index] .= $quantity . ' '.Product::strUnit($unit, 'wording_short', true).' ';
}
$totalsGlobalArray[$index] += $quantity ;
}
}


+ 14
- 2
backend/controllers/OrderController.php View File

@@ -105,6 +105,8 @@ class OrderController extends BackendController
$productOrder->id_product = $product->id;
$productOrder->quantity = $quantity;
$productOrder->price = $p->price;
$productOrder->unit = $p->unit;
$productOrder->step = $p->step;
$productOrder->save();
}
}
@@ -138,6 +140,8 @@ class OrderController extends BackendController
$productOrder->id_product = $product->id;
$productOrder->quantity = $quantity;
$productOrder->price = $p->price;
$productOrder->unit = $p->unit;
$productOrder->step = $p->step;
$productOrder->save();
}
}
@@ -860,13 +864,16 @@ class OrderController extends BackendController

$order->save();

foreach ($products as $key => $quantity) {
foreach ($products as $key => $dataProductOrder) {
$product = Product::findOne($key);
$quantity = $dataProductOrder->quantity / Product::$unitsArray[$dataProductOrder->unit]['coefficient'] ;
if ($product && $quantity) {
$productOrder = new ProductOrder;
$productOrder->id_order = $order->id;
$productOrder->id_product = $key;
$productOrder->quantity = $quantity;
$productOrder->unit = $product->unit;
$productOrder->step = $product->step;
$productOrder->price = $product->price;
$productOrder->save();
}
@@ -906,12 +913,15 @@ class OrderController extends BackendController
$order->distribution->id_producer == Producer::getId()) {
$products = json_decode($products);
foreach ($products as $key => $quantity) {
foreach ($products as $key => $dataProductOrder) {
$productOrder = ProductOrder::findOne([
'id_order' => $idOrder,
'id_product' => $key
]);

$quantity = $dataProductOrder->quantity
/ Product::$unitsArray[$dataProductOrder->unit]['coefficient'] ;
if ($quantity) {
if ($productOrder) {
$productOrder->quantity = $quantity;
@@ -923,6 +933,8 @@ class OrderController extends BackendController
$productOrder->id_order = $idOrder;
$productOrder->id_product = $key;
$productOrder->quantity = $quantity;
$productOrder->unit = $product->unit;
$productOrder->step = $product->step;
$productOrder->price = $product->price;
}
}

+ 53
- 1
backend/controllers/SubscriptionController.php View File

@@ -38,6 +38,8 @@ termes.
namespace backend\controllers;

use common\models\Order ;
use common\models\Product ;
use common\models\SubscriptionSearch ;

class SubscriptionController extends BackendController
{
@@ -88,6 +90,7 @@ class SubscriptionController extends BackendController
{
// form
$model = new SubscriptionForm;
$model->isAdmin = true ;
$model->id_producer = Producer::getId();

if($idOrder) {
@@ -148,6 +151,7 @@ class SubscriptionController extends BackendController
{
// form
$model = new SubscriptionForm;
$model->isAdmin = true ;
$subscription = Subscription::findOne($id);
if ($subscription) {
$model->id = $id;
@@ -170,7 +174,6 @@ class SubscriptionController extends BackendController
$model->auto_payment = $subscription->auto_payment;
$model->week_frequency = $subscription->week_frequency;


// produits
$arrayProductsSubscription = ProductSubscription::searchAll([
'id_subscription' => $model->id
@@ -249,6 +252,55 @@ class SubscriptionController extends BackendController
'update' => $update
]) ;
}
public function actionAjaxInfos($idSubscription = 0)
{
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
$productsQuery = Product::find()
->where(['id_producer' => Producer::getId(),]) ;
if($idSubscription) {
$productsQuery->joinWith(['productSubscription' => function($query) use($idSubscription) {
$query->andOnCondition('product_subscription.id_subscription = '.((int) $idSubscription)) ;
}]) ;
}
$productsArray = $productsQuery->asArray()->all() ;
foreach($productsArray as &$theProduct) {
$theProduct['unit_save'] = $theProduct['unit'] ;
$theProduct['units'] = [] ;
$theProduct['units'][] = [
'unit' => $theProduct['unit'],
'wording_unit' => Product::strUnit($theProduct['unit'], 'wording_short'),
'step' => $theProduct['step'],
'price' => $theProduct['price']
] ;
if(isset($theProduct['productSubscription'][0])) {
if($theProduct['productSubscription'][0]['unit'] != $theProduct['unit']) {
$theProduct['units'][] = [
'unit' => $theProduct['productSubscription'][0]['unit'],
'wording_unit' => Product::strUnit($theProduct['productSubscription'][0]['unit'], 'wording_short'),
'step' => $theProduct['productSubscription'][0]['step'],
'price' => $theProduct['productSubscription'][0]['price'],
] ;
$theProduct['unit'] = $theProduct['productSubscription'][0]['unit'] ;
$theProduct['step'] = $theProduct['productSubscription'][0]['step'] ;
$theProduct['price'] = $theProduct['productSubscription'][0]['price'] ;
}
$theProduct['quantity'] = $theProduct['productSubscription'][0]['quantity'] * Product::$unitsArray[$theProduct['unit']]['coefficient'] ;
}
else {
$theProduct['quantity'] = '' ;
}
}
return [
'products' => $productsArray
] ;
}
}

+ 25
- 8
backend/views/distribution/index.php View File

@@ -119,8 +119,14 @@ $this->setPageTitle('Distributions') ;
<button class="btn btn-default" v-else data-active-product="0" :data-id-product="product.id" @click="productActiveClick"><span class="glyphicon glyphicon-remove"></span></button>
</td>
<td>{{ product.name }}</td>
<td class="quantity-ordered">{{ product.quantity_ordered ? product.quantity_ordered : '-' }}</td>
<td class="quantity-max"><input type="text" class="form-control quantity-max" placeholder="&infin;" :data-id-product="product.id" v-model="product.productDistribution[0].quantity_max" @keyup="productQuantityMaxChange" /></td>
<td class="quantity-ordered">{{ product.quantity_ordered ? product.quantity_ordered + ' '+ ((product.unit == 'piece') ? ' p.' : ' '+(product.unit == 'g' || product.unit == 'kg') ? 'kg' : 'litre(s)') : '&empty;' }}</td>
<td class="quantity-max">
<div class="input-group">
<input type="text" class="form-control quantity-max" placeholder="&infin;" :data-id-product="product.id" v-model="product.productDistribution[0].quantity_max" @keyup="productQuantityMaxChange" />
<span class="input-group-addon">{{ (product.unit == 'piece') ? 'p.' : ' '+((product.unit == 'g' || product.unit == 'kg') ? 'kg' : 'litre(s)') }}</span>
</div>
</td>
</tr>
</tbody>
</table>
@@ -415,8 +421,8 @@ $this->setPageTitle('Distributions') ;
<td colspan="6">
<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 }} <span v-if="product.productDistribution[0].active == 0" class="glyphicon glyphicon-warning-sign" title="Ce produit n'est pas activé"></span>
<li v-for="product in products" v-if="order.productOrder[product.id].quantity > 0">
{{ product.name }} : {{ order.productOrder[product.id].quantity }} {{ order.productOrder[product.id].unit == 'piece' ? ' pièce(s)' : ' '+order.productOrder[product.id].unit }} <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">
@@ -468,6 +474,14 @@ $this->setPageTitle('Distributions') ;
<div class="col-md-8">
<label class="control-label">Produits</label>
<table class="table table-condensed table-bordered table-hover table-products">
<thead>
<tr>
<th></th>
<th>Nom</th>
<th>Quantité</th>
<th>Reste</th>
</tr>
</thead>
<tbody>
<tr v-for="product in products" :class="(order.productOrder[product.id] > 0) ? 'product-ordered' : ''">
<td>
@@ -478,15 +492,18 @@ $this->setPageTitle('Distributions') ;
<td class="quantity">
<div class="input-group">
<span class="input-group-btn">
<button class="btn btn-default btn-moins" type="button" @click="productQuantityClick(product.id, -1)"><span class="glyphicon glyphicon-minus"></span></button>
<button class="btn btn-default btn-moins" type="button" @click="productQuantityClick(product.id, order.productOrder[product.id].unit == 'piece' ? -1 : -parseFloat(product.step))"><span class="glyphicon glyphicon-minus"></span></button>
</span>
<input type="text" v-model="order.productOrder[product.id]" class="form-control" />
<input type="text" v-model="order.productOrder[product.id].quantity" class="form-control" />
<span class="input-group-addon">{{ order.productOrder[product.id].unit == 'piece' ? 'p.' : order.productOrder[product.id].unit }}</span>
<span class="input-group-btn">
<button class="btn btn-default btn-plus" type="button" @click="productQuantityClick(product.id, 1)"><span class="glyphicon glyphicon-plus"></span></button>
<button class="btn btn-default btn-plus" type="button" @click="productQuantityClick(product.id, order.productOrder[product.id].unit == 'piece' ? 1 : parseFloat(product.step))"><span class="glyphicon glyphicon-plus"></span></button>
</span>
</div>
</td>
<td class="quantity-remaining">/ {{ product.quantity_remaining }}</td>
<td class="quantity-remaining infinite" v-if="product.quantity_remaining === null || order.productOrder[product.id].unit != product.unit">&infin;</td>
<td class="quantity-remaining negative" v-else-if="product.quantity_remaining <= 0">{{ product.quantity_remaining }} {{ order.productOrder[product.id].unit == 'piece' ? ' p.' : ' '+(order.productOrder[product.id].unit == 'g' || order.productOrder[product.id].unit == 'kg') ? 'kg' : 'litre(s)' }}</td>
<td class="quantity-remaining has-quantity" v-else>{{ product.quantity_remaining }} {{ order.productOrder[product.id].unit == 'piece' ? ' p.' : ' '+(order.productOrder[product.id].unit == 'g' || order.productOrder[product.id].unit == 'kg') ? 'kg' : 'litre(s)' }}</td>
</tr>
</tbody>
</table>

+ 19
- 15
backend/views/distribution/report.php View File

@@ -37,6 +37,7 @@ termes.
*/

use common\models\Order ;
use common\models\Product ;

$dayWeek = date('w', strtotime($date));
$dayWeekArray = [0 => 'sunday', 1 => 'monday', 2 => 'tuesday', 3 => 'wednesday', 4 => 'thursday', 5 => 'friday', 6 => 'saturday'];
@@ -91,7 +92,7 @@ foreach ($pointsSaleArray as $pointSale) {
$add = false;
foreach ($order->productOrder as $productOrder) {
if ($product->id == $productOrder->id_product) {
$strProducts .= $productOrder->quantity . '&nbsp;' . $product->name . ', ';
$strProducts .= $product->name . ' (' .$productOrder->quantity . '&nbsp;'.Product::strUnit($productOrder->unit, 'wording_short', true).'), ';
$add = true;
}
}
@@ -133,11 +134,11 @@ foreach ($pointsSaleArray as $pointSale) {
$strProducts = '';
foreach ($productsArray as $product) {
$quantity = Order::getProductQuantity($product->id, $pointSale->orders);
$strQuantity = '';
if ($quantity) {
$strQuantity = $quantity;
$strProducts .= $strQuantity .'&nbsp;'. $product->name . ', ';
foreach(Product::$unitsArray as $unit => $dataUnit) {
$quantity = Order::getProductQuantity($product->id, $pointSale->orders, false, $unit);
if ($quantity) {
$strProducts .= $product->name . ' (' .$quantity . '&nbsp;'.Product::strUnit($unit, 'wording_short', true).'), ';
}
}
}
@@ -170,14 +171,14 @@ foreach ($pointsSaleArray as $pointSale)
if (count($pointSale->orders))
{
$html .= '<tr><td>'.$pointSale->name.'</td><td>' ;
foreach ($productsArray as $product) {
$quantity = Order::getProductQuantity($product->id, $pointSale->orders);
$strQuantity = ($quantity) ? $quantity : '' ;
if(strlen($strQuantity)) {
$html .= $strQuantity . '&nbsp;'.$product->name.', ' ;
foreach(Product::$unitsArray as $unit => $dataUnit) {
$quantity = Order::getProductQuantity($product->id, $pointSale->orders, false, $unit);
if ($quantity) {
$html .= $product->name . ' (' .$quantity . '&nbsp;'.Product::strUnit($unit, 'wording_short', true).'), ';
}
}
}
$html = substr($html, 0, strlen($html) - 2) ;
@@ -189,10 +190,13 @@ foreach ($pointsSaleArray as $pointSale)

// total
$html .= '<tr><td><strong>Total</strong></td><td>' ;

foreach ($productsArray as $product) {
$quantity = Order::getProductQuantity($product->id, $ordersArray);
if($quantity) {
$html .= $quantity . '&nbsp;'.$product->name.', ' ;
foreach(Product::$unitsArray as $unit => $dataUnit) {
$quantity = Order::getProductQuantity($product->id, $ordersArray, false, $unit);
if ($quantity) {
$html .= $product->name . ' (' .$quantity . '&nbsp;'.Product::strUnit($unit, 'wording_short', true).'), ';
}
}
}


+ 55
- 40
backend/views/product/_form.php View File

@@ -37,7 +37,9 @@ termes.
*/

use yii\helpers\Html;
use yii\widgets\ActiveForm;
use yii\bootstrap\ActiveForm;
use common\models\Product;
use yii\helpers\ArrayHelper ;

/* @var $this yii\web\View */
/* @var $model app\models\Produit */
@@ -48,47 +50,60 @@ use yii\widgets\ActiveForm;

<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]); ?>

<?= $form->field($model, 'active')->radioList([1 => 'Oui',0 => 'Non' ]) ?>
<?= $form->field($model, 'name')->textInput(['maxlength' => 255]) ?>
<?= $form->field($model, 'description')->textInput(['maxlength' => 255]) ?>
<?= $form->field($model, 'recipe')->textarea() ?>
<?= $form->field($model, 'price')->textInput() ?>
<?= $form->field($model, 'weight')->textInput() ?>
<?= $form->field($model, 'quantity_max')
->hint('Renseignez ce champs si vous souhaitez limiter la quantité commandable pour ce produit.')
->textInput() ?>
<?= $form->field($model, 'photo')->fileInput() ?>
<?php
if(strlen($model->photo)) {
$url = Yii::$app->urlManagerProducer->getHostInfo().'/'.Yii::$app->urlManagerProducer->baseUrl ;
echo '<img class="photo-product" src="'.$url.'/uploads/'.$model->photo.'" width="200px" /><br />' ;
echo '<input type="checkbox" name="delete_photo" id="delete_photo" /> <label for="delete_photo">Supprimer la photo</label><br /><br />' ;
}
?>
<h2>Jours de distribution</h2>
<div id="days-production">
<?= $form->field($model, 'monday')->checkbox() ?>
<?= $form->field($model, 'tuesday')->checkbox() ?>
<?= $form->field($model, 'wednesday')->checkbox() ?>
<?= $form->field($model, 'thursday')->checkbox() ?>
<?= $form->field($model, 'friday')->checkbox() ?>
<?= $form->field($model, 'saturday')->checkbox() ?>
<?= $form->field($model, 'sunday')->checkbox() ?>
<div>
<div class="col-md-8">
<?= $form->field($model, 'active')->radioList([1 => 'Oui',0 => 'Non' ]) ?>
<?= $form->field($model, 'name')->textInput(['maxlength' => 255]) ?>
<?= $form->field($model, 'description')->textInput(['maxlength' => 255]) ?>
<?= $form->field($model, 'recipe')->textarea()->label('Description longue') ?>
<?= $form->field($model, 'unit')
->dropDownList(ArrayHelper::map(Product::$unitsArray, 'unit', 'wording'))
->label('Unité (pièce, poids ou volume)'); ?>
<?= $form->field($model, 'price',[
'inputTemplate' => '<div class="input-group">{input}<span class="input-group-addon"><span class="glyphicon glyphicon-euro"></span></span></div>',
]) ?>
<?= $form->field($model, 'step')->textInput()->hint('Définit ce qui est ajouté ou enlevé lors des changements de quantité.') ?>
<?= $form->field($model, 'weight')->textInput()->label('Poids (g)') ?>
<?= $form->field($model, 'quantity_max')
->hint('Renseignez ce champs si vous souhaitez limiter la quantité commandable pour une distribution.')
->textInput() ?>
<?php
if(!$model->isNewRecord) {
echo $form->field($model, 'apply_distributions')
->checkbox()
->hint('Sélectionnez cette option si vous souhaitez que ces modifications soient répercutées dans les distributions à venir déjà initialisées.');
}
?>
</div>
<div class="col-md-4">
<?= $form->field($model, 'photo')->fileInput() ?>
<?php
if(strlen($model->photo)) {
$url = Yii::$app->urlManagerProducer->getHostInfo().'/'.Yii::$app->urlManagerProducer->baseUrl ;
echo '<img class="photo-product" src="'.$url.'/uploads/'.$model->photo.'" width="200px" /><br />' ;
echo '<input type="checkbox" name="delete_photo" id="delete_photo" /> <label for="delete_photo">Supprimer la photo</label><br /><br />' ;
}
?>

<div id="days-production">
<h2>Jours de distribution</h2>
<?= $form->field($model, 'monday')->checkbox() ?>
<?= $form->field($model, 'tuesday')->checkbox() ?>
<?= $form->field($model, 'wednesday')->checkbox() ?>
<?= $form->field($model, 'thursday')->checkbox() ?>
<?= $form->field($model, 'friday')->checkbox() ?>
<?= $form->field($model, 'saturday')->checkbox() ?>
<?= $form->field($model, 'sunday')->checkbox() ?>
</div>
<div class="clr"></div>
</div>
<div class="clr"></div>
</div>
<div class="clr"></div>
<?= $form->field($model, 'id_producer')->hiddenInput()->label('') ?>
<?php
if(!$model->isNewRecord) {
echo $form->field($model, 'apply_distributions')
->checkbox()
->hint('Sélectionnez cette option si vous souhaitez que ces modifications soient répercutées dans les distributions à venir déjà initialisées.');
}
?>
<?= $form->field($model, 'id_producer')->hiddenInput()->label('') ?>

<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? 'Ajouter' : 'Modifier', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
</div>

+ 12
- 0
backend/views/product/index.php View File

@@ -39,6 +39,7 @@ termes.
use yii\helpers\Html;
use yii\grid\GridView;
use common\helpers\Url ;
use common\models\Product ;

$this->setTitle('Produits') ;
$this->addBreadcrumb($this->getTitle()) ;
@@ -76,6 +77,17 @@ $this->addButton(['label' => 'Nouveau produit <span class="glyphicon glyphicon-p
],
'name',
'description',
[
'attribute' => 'price',
'value' => function($model) {
$return = '' ;
if($model->price) {
$return = Price::format($model->price).' ('.Product::strUnit($model->unit, 'wording_unit', true).')' ;
}
return $return ;
}
],
[
'attribute' => 'active',
'headerOptions' => ['class' => 'active'],

+ 35
- 26
backend/views/site/index.php View File

@@ -92,34 +92,43 @@ $this->title = 'Tableau de bord';
<?php endif; ?>
<div id="distributions">
<!-- distributions -->
<?php if(count($distributionsArray)): ?>
<?php foreach($distributionsArray as $distribution): ?>
<div class="col-md-4 col-sm-12 col-xs-12">
<div class="info-box">
<span class="info-box-icon bg-green date">
<span class="day"><?= strftime('%A', strtotime($distribution->date)) ?></span>
<span class="num"><?= date('d', strtotime($distribution->date)) ?></span>
<span class="month"><?= strftime('%B', strtotime($distribution->date)) ?></span>
</span>
<div class="info-box-content">
<span class="info-box-text">
<?php if(count($distribution->order)): ?>
<strong><?= count($distribution->order); ?></strong> COMMANDES
<?php else: ?>
AUCUNE COMMANDE
<?php endif; ?>
</span>
<span class="info-box-number"></span>
<div class="buttons">
<?= Html::a('<span class="fa fa-eye"></span>', ['distribution/index', 'date' => $distribution->date], ['class' => 'btn btn-default']); ?>
<?php if(count($distribution->order)): ?><?= Html::a('<span class="fa fa-download"></span>', ['distribution/report', 'date' => $distribution->date], ['class' => 'btn btn-default']); ?><?php endif; ?>
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">
Prochaines distributions
</h3>
</div>
<div class="panel-body">
<!-- distributions -->
<?php if(count($distributionsArray)): ?>
<?php foreach($distributionsArray as $distribution): ?>
<div class="col-md-4 col-sm-12 col-xs-12">
<div class="info-box">
<span class="info-box-icon bg-green date">
<span class="day"><?= strftime('%A', strtotime($distribution->date)) ?></span>
<span class="num"><?= date('d', strtotime($distribution->date)) ?></span>
<span class="month"><?= strftime('%B', strtotime($distribution->date)) ?></span>
</span>
<div class="info-box-content">
<span class="info-box-text">
<?php if(count($distribution->order)): ?>
<strong><?= count($distribution->order); ?></strong> COMMANDES
<?php else: ?>
AUCUNE COMMANDE
<?php endif; ?>
</span>
<span class="info-box-number"></span>
<div class="buttons">
<?= Html::a('<span class="fa fa-eye"></span>', ['distribution/index', 'date' => $distribution->date], ['class' => 'btn btn-default']); ?>
<?php if(count($distribution->order)): ?><?= Html::a('<span class="fa fa-download"></span>', ['distribution/report', 'date' => $distribution->date], ['class' => 'btn btn-default']); ?><?php endif; ?>
</div>
</div>
</div>
</div>
</div>
</div>
<?php endforeach; ?>
<?php endif; ?>
<?php endforeach; ?>
<?php endif; ?>
</div>
</div>
</div>
<div class="clr"></div>

+ 25
- 9
backend/views/subscription/_form.php View File

@@ -42,10 +42,15 @@ use yii\helpers\ArrayHelper ;
use common\models\User ;
use common\models\PointSale ;

\backend\assets\VuejsSubscriptionFormAsset::register($this);

?>

<div class="subscription-form">
<div class="subscription-form" id="app-subscription-form">
<?php $form = ActiveForm::begin(['enableClientValidation' => false]); ?>
<?php if($model->id): ?>
<?= $form->field($model, 'id')->hiddenInput() ?>
<?php endif; ?>
<div class="col-md-5" id="bloc-select-user">
<?= $form->field($model, 'id_user')->dropDownList( ArrayHelper::map(User::find()->joinWith('userProducer')->where('user_producer.id_producer = '.Producer::getId())->andWhere('user_producer.active = 1')->orderBy('lastname ASC, name ASC')->all(), 'id', function($model, $defaultValue) {
return $model['lastname'].' '.$model['name'];
@@ -91,23 +96,34 @@ use common\models\PointSale ;
echo '<div class="alert alert-danger">'.$model->errors['products'][0].'</div>' ;
}
?>
<table class="table table-bordered table-condensed table-hover">
<?php foreach ($productsArray as $p) : ?>
<tr>
<td><?= Html::encode($p->name) ?></td>
<table class="table table-bordered table-condensed table-hover" id="products">
<tr v-for="product in products">
<td>{{ product.name }}</td>
<td>
<input type="hidden" :value="product.step" :name="'product_step_'+product.step" />
<input type="hidden" :value="product.price" :name="'product_price_'+product.price" />
<div class="input-group">
<span class="input-group-btn">
<button class="btn btn-default btn-moins" type="button"><span class="glyphicon glyphicon-minus"></span></button>
<button class="btn btn-default" type="button" @click="changeQuantityProductSubscription(false, product)"><span class="glyphicon glyphicon-minus"></span></button>
</span>
<?= Html::input('text', 'SubscriptionForm[products][product_'.$p->id.']', (isset($model->products['product_'.$p->id])) ? $model->products['product_'.$p->id] : '', ['class' => 'form-control quantity']) ?>
<input v-model="product.quantity" :name="'SubscriptionForm[products][product_'+product.id+']'" class="form-control input-quantity" />
<div class="input-group-addon">
<select class="form-control select-unit" :name="'product_unit_'+product.id" v-model="product.unit" v-if="product.units.length > 1" @change="changeUnitProductSubscription" :data-id-product="product.id">
<option v-for="unit in product.units" :value="unit.unit">{{ unit.wording_unit }}</option>
</select>
<span v-else>
{{ product.units[0].wording_unit }}
</span>
</div>
<span class="input-group-btn">
<button class="btn btn-default btn-plus" type="button"><span class="glyphicon glyphicon-plus"></span></button>
<button class="btn btn-default" type="button" @click="changeQuantityProductSubscription(true, product)"><span class="glyphicon glyphicon-plus"></span></button>
</span>
</div>
</td>
<td>
<span v-if="product.units.length > 1 && product.unit != product.unit_save" class="glyphicon glyphicon-warning-sign" title="Unité différente du produit"></span>
</td>
</tr>
<?php endforeach; ?>
</table>
</div>

+ 8
- 2
backend/views/subscription/index.php View File

@@ -38,6 +38,7 @@ termes.

use yii\helpers\Html;
use yii\grid\GridView;
use common\models\Product ;


$this->setTitle('Abonnements') ;
@@ -76,7 +77,7 @@ $this->addButton(['label' => 'Nouvel abonnement <span class="glyphicon glyphicon
foreach($model->productSubscription as $productSubscription)
{
if(isset($productSubscription->product)) {
$html .= $productSubscription->quantity . '&nbsp;x&nbsp;'.Html::encode($productSubscription->product->name).'<br />' ;
$html .= Html::encode($productSubscription->product->name).' ('.($productSubscription->quantity * Product::$unitsArray[$productSubscription->unit]['coefficient']).'&nbsp;'.Product::strUnit($productSubscription->unit, 'wording_short').')<br />' ;
}
else {
$html .= 'Produit non défini<br />' ;
@@ -86,7 +87,12 @@ $this->addButton(['label' => 'Nouvel abonnement <span class="glyphicon glyphicon
// aucun produit
if(!count($model->productSubscription))
{
$html .= '<span class="glyphicon glyphicon-warning-sign"></span> Aucun produit' ;
$html .= '<span class="glyphicon glyphicon-warning-sign"></span> Aucun produit<br />' ;
}
// des unités ne correspondent pas
if($model->hasUnitsNotMatch()) {
$html .= '<span class="glyphicon glyphicon-warning-sign" title="Des unités ne correspondent pas"></span>' ;
}
return $html ;

+ 85
- 17
backend/web/css/screen.css View File

@@ -1683,24 +1683,28 @@ body.login-page .login-box .login-box-body a:hover {
color: #ff8c1a;
}

/* line 5, ../sass/site/_index.scss */
/* line 4, ../sass/site/_index.scss */
.site-index #distributions .info-box {
border: solid 1px #e0e0e0;
}
/* line 6, ../sass/site/_index.scss */
.site-index #distributions .info-box .date {
text-transform: uppercase;
font-size: 12px;
line-height: 20px;
padding-top: 10px;
}
/* line 11, ../sass/site/_index.scss */
/* line 12, ../sass/site/_index.scss */
.site-index #distributions .info-box .date span {
display: block;
}
/* line 17, ../sass/site/_index.scss */
/* line 18, ../sass/site/_index.scss */
.site-index #distributions .info-box .date .num {
font-size: 30px;
padding-top: 5px;
padding-bottom: 5px;
}
/* line 29, ../sass/site/_index.scss */
/* line 30, ../sass/site/_index.scss */
.site-index #distributions .info-box-content .buttons {
margin-top: 10px;
}
@@ -1710,6 +1714,36 @@ body.login-page .login-box .login-box-body a:hover {
width: 50px;
}

/* line 3, ../sass/subscription/_form.scss */
.subscription-form .field-subscriptionform-id {
display: none;
}
/* line 7, ../sass/subscription/_form.scss */
.subscription-form table#products .input-quantity {
text-align: center;
border-right: 0px none;
}
/* line 11, ../sass/subscription/_form.scss */
.subscription-form table#products .input-group-addon {
padding: 5px;
padding-left: 0px;
margin: 0px;
border-left: 0px none;
border-right: 0px none;
}
/* line 18, ../sass/subscription/_form.scss */
.subscription-form table#products .select-unit {
padding: 0px;
width: 58px;
text-align: center;
height: 22px;
}
/* line 24, ../sass/subscription/_form.scss */
.subscription-form table#products .glyphicon-warning-sign {
position: relative;
top: 10px;
}

/* line 3, ../sass/product/_index.scss */
.product-index .td-photo {
max-width: 100px;
@@ -1725,16 +1759,25 @@ body.login-page .login-box .login-box-body a:hover {
background-color: white;
}

/* line 5, ../sass/product/_form.scss */
/* line 6, ../sass/product/_form.scss */
.product-create #product-active label,
.product-update #product-active label {
margin-right: 15px;
}
/* line 10, ../sass/product/_form.scss */
.product-create #days-production .form-group,
.product-update #days-production .form-group {
float: left;
margin-right: 15px;
.product-create #days-production,
.product-update #days-production {
margin-top: 30px;
}
/* line 13, ../sass/product/_form.scss */
.product-create #days-production h2,
.product-update #days-production h2 {
font-size: 20px;
}
/* line 16, ../sass/product/_form.scss */
.product-create #days-production label,
.product-update #days-production label {
font-weight: normal;
}

/**
@@ -1883,7 +1926,7 @@ termes.
}
/* line 155, ../sass/distribution/_index.scss */
.distribution-index #modal-products table.table td.quantity-max {
width: 70px;
width: 120px;
}
/* line 158, ../sass/distribution/_index.scss */
.distribution-index #modal-products table.table td.quantity-max input {
@@ -1979,30 +2022,55 @@ termes.
}
/* line 267, ../sass/distribution/_index.scss */
.distribution-index .modal-form-order table.table-products td.quantity {
width: 150px;
width: 165px;
}
/* line 270, ../sass/distribution/_index.scss */
.distribution-index .modal-form-order table.table-products td.quantity input {
text-align: center;
color: gray;
color: black;
}
/* line 276, ../sass/distribution/_index.scss */
/* line 274, ../sass/distribution/_index.scss */
.distribution-index .modal-form-order table.table-products td.quantity .form-control {
border-right: 0px none;
padding-right: 4px;
}
/* line 278, ../sass/distribution/_index.scss */
.distribution-index .modal-form-order table.table-products td.quantity .input-group-addon {
padding: 5px;
padding-left: 0px;
margin: 0px;
border-left: 0px none;
border-right: 0px none;
}
/* line 286, ../sass/distribution/_index.scss */
.distribution-index .modal-form-order table.table-products td.quantity-remaining {
text-align: right;
}
/* line 282, ../sass/distribution/_index.scss */
/* line 289, ../sass/distribution/_index.scss */
.distribution-index .modal-form-order table.table-products td.quantity-remaining.quantity-remaining, .distribution-index .modal-form-order table.table-products td.quantity-remaining.infinite {
color: #00A65A;
}
/* line 293, ../sass/distribution/_index.scss */
.distribution-index .modal-form-order table.table-products td.quantity-remaining.negative {
color: #DD4B39;
}
/* line 297, ../sass/distribution/_index.scss */
.distribution-index .modal-form-order table.table-products td.quantity-remaining.infinite, .distribution-index .modal-form-order table.table-products td.quantity-remaining.empty {
font-size: 18px;
}
/* line 304, ../sass/distribution/_index.scss */
.distribution-index .modal-form-order .actions-form button {
margin-left: 15px;
}
/* line 290, ../sass/distribution/_index.scss */
/* line 312, ../sass/distribution/_index.scss */
.distribution-index .modal-payment .info-box .info-box-icon {
width: 50px;
}
/* line 292, ../sass/distribution/_index.scss */
/* line 314, ../sass/distribution/_index.scss */
.distribution-index .modal-payment .info-box .info-box-icon i {
font-size: 30px;
}
/* line 296, ../sass/distribution/_index.scss */
/* line 318, ../sass/distribution/_index.scss */
.distribution-index .modal-payment .info-box .info-box-content {
margin-left: 50px;
}

+ 51
- 0
backend/web/js/lechatdesnoisettes.js View File

@@ -52,6 +52,7 @@ $(document).ready(function() {
chat_index_commandes_maj_points_vente() ;
// admin
chat_select_etablissement() ;
chat_products() ;
}) ;

var UrlManager = {
@@ -64,6 +65,56 @@ var UrlManager = {
}
};

function chat_products() {
if($('.product-create').size() || $('.product-update').size()) {
chat_products_event_unit(false) ;
$('#product-unit').change(function() {
chat_products_event_unit(true) ;
}) ;
}
}

function chat_products_event_unit(change) {
var unit = $('#product-unit').val() ;
if(unit == 'piece') {
$('.field-product-step').hide() ;
$('.field-product-weight').show() ;
}
else {
$('.field-product-step').show() ;
$('.field-product-weight').hide() ;
}
var label_price = $('.field-product-price .control-label') ;
var label_step = $('.field-product-step .control-label') ;
var label_quantity_max = $('.field-product-quantity_max .control-label') ;
if(unit == 'piece') {
label_price.html('Prix (la pièce)') ;
label_quantity_max.html('Quantité max par défaut (pièces)') ;
}
else if(unit == 'g' || unit == 'kg') {
label_price.html('Prix (au kg)') ;
label_quantity_max.html('Quantité max par défaut (kg)') ;
label_step.html('Pas ('+unit+')') ;
}
else if(unit == 'mL' || unit == 'L') {
label_price.html('Prix (au litre)') ;
label_quantity_max.html('Quantité max par défaut (litres)') ;
label_step.html('Pas ('+unit+')') ;
}
if(change) {
if(unit == 'piece') {
$('#product-step').val(1) ;
}
else {
$('#product-step').val('') ;
}
}
}

function chat_tooltip() {
$('[data-toggle="tooltip"]').tooltip({container:'body'});
}

+ 7
- 4
backend/web/js/vuejs/distribution-index.js View File

@@ -428,7 +428,7 @@ Vue.component('order-form',{
var countProducts = 0 ;
for(var key in this.order.productOrder) {
if(this.order.productOrder[key] > 0) {
if(this.order.productOrder[key].quantity > 0) {
countProducts ++ ;
}
}
@@ -502,9 +502,12 @@ Vue.component('order-form',{
}
},
productQuantityClick: function(id_product, quantity) {
if(this.order.productOrder[id_product] + quantity >= 0) {
var theQuantity = this.order.productOrder[id_product] + quantity ;
Vue.set(this.order.productOrder, id_product, theQuantity);
if(!this.order.productOrder[id_product].quantity) {
this.order.productOrder[id_product].quantity = 0 ;
}
if(parseFloat(this.order.productOrder[id_product].quantity) + quantity >= 0) {
var theQuantity = parseFloat(this.order.productOrder[id_product].quantity) + parseFloat(quantity) ;
Vue.set(this.order.productOrder, id_product, {quantity: theQuantity, unit: this.order.productOrder[id_product].unit});
}
}
}

+ 90
- 0
backend/web/js/vuejs/subscription-form.js View File

@@ -0,0 +1,90 @@

/**
Copyright distrib (2018)

contact@opendistrib.net

Ce logiciel est un programme informatique servant à aider les producteurs
à distribuer leur production en circuits courts.

Ce logiciel est régi par la licence CeCILL soumise au droit français et
respectant les principes de diffusion des logiciels libres. Vous pouvez
utiliser, modifier et/ou redistribuer ce programme sous les conditions
de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA
sur le site "http://www.cecill.info".

En contrepartie de l'accessibilité au code source et des droits de copie,
de modification et de redistribution accordés par cette licence, il n'est
offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons,
seule une responsabilité restreinte pèse sur l'auteur du programme, le
titulaire des droits patrimoniaux et les concédants successifs.

A cet égard l'attention de l'utilisateur est attirée sur les risques
associés au chargement, à l'utilisation, à la modification et/ou au
développement et à la reproduction du logiciel par l'utilisateur étant
donné sa spécificité de logiciel libre, qui peut le rendre complexe à
manipuler et qui le réserve donc à des développeurs et des professionnels
avertis possédant des connaissances informatiques approfondies. Les
utilisateurs sont donc invités à charger et tester l'adéquation du
logiciel à leurs besoins dans des conditions permettant d'assurer la
sécurité de leurs systèmes et ou de leurs données et, plus généralement,
à l'utiliser et l'exploiter dans les mêmes conditions de sécurité.

Le fait que vous puissiez accéder à cet en-tête signifie que vous avez
pris connaissance de la licence CeCILL, et que vous en avez accepté les
termes.
*/

var app = new Vue({
el: '#app-subscription-form',
data: {
showLoading: false,
loading: true,
products: [],
units: []
},
mounted: function() {
this.init() ;
this.loading = false ;
},
methods: {
init: function() {
var app = this ;
this.showLoading = true ;
axios.get("ajax-infos",{params: {idSubscription: $('#subscriptionform-id').val()}})
.then(function(response) {
app.products = response.data.products ;
app.units = response.data.units ;
app.showLoading = false ;
}) ;
},
changeUnitProductSubscription: function(event) {
for(var i = 0; i < this.products.length ; i++) {
if(this.products[i].id == event.currentTarget.getAttribute('data-id-product')) {
this.products[i].quantity = '' ;
for(var j = 0; j < this.products[i].units.length ; j ++) {
if(this.products[i].unit == this.products[i].units[j].unit) {
this.products[i].step = this.products[i].units[j].step ;
this.products[i].price = this.products[i].units[j].price ;
}
}
}
}
},
changeQuantityProductSubscription: function(increase, product) {
var step = parseFloat(product.step) ;
if(!product.quantity) product.quantity = 0 ;
var quantity = parseFloat(product.quantity) ;
if(!increase) {
step = -step ;
}
if(quantity + step >= 0) {
product.quantity = quantity + step ;
}
if(!product.quantity) product.quantity = '' ;
}
}
});

+ 26
- 4
backend/web/sass/distribution/_index.scss View File

@@ -153,7 +153,7 @@ termes.
width: 50px ;
}
td.quantity-max {
width: 70px ;
width: 120px ;
input {
text-align: center ;
@@ -265,16 +265,38 @@ termes.
}
td.quantity {
width: 150px ;
width: 165px ;
input {
text-align: center ;
color: gray ;
color: black ;
}
.form-control {
border-right: 0px none ;
padding-right: 4px ;
}
.input-group-addon {
padding: 5px ;
padding-left: 0px ;
margin: 0px ;
border-left: 0px none ;
border-right: 0px none ;
}
}
td.quantity-remaining {
text-align: right ;
&.quantity-remaining, &.infinite {
color: #00A65A ;
}
&.negative {
color: #DD4B39 ;
}
&.infinite, &.empty {
font-size: 18px ;
}
}
}

+ 8
- 3
backend/web/sass/product/_form.scss View File

@@ -1,15 +1,20 @@

.product-create,
.product-update {
#product-active {
label {
margin-right: 15px ;
}
}
#days-production {
.form-group {
float: left ;
margin-right: 15px ;
margin-top: 30px ;
h2 {
font-size: 20px ;
}
label {
font-weight: normal ;
}
}
}

+ 1
- 0
backend/web/sass/screen.scss View File

@@ -1458,6 +1458,7 @@ a.btn, button.btn {
@import "_adminlte.scss" ;
@import "site/_index.scss" ;
@import "subscription/_index.scss" ;
@import "subscription/_form.scss" ;
@import "product/_index.scss" ;
@import "product/_form.scss" ;
@import "stats/_products.scss" ;

+ 1
- 0
backend/web/sass/site/_index.scss View File

@@ -2,6 +2,7 @@
.site-index {
#distributions {
.info-box {
border: solid 1px #e0e0e0 ;
.date {
text-transform: uppercase ;
font-size: 12px ;

+ 29
- 0
backend/web/sass/subscription/_form.scss View File

@@ -0,0 +1,29 @@

.subscription-form {
.field-subscriptionform-id {
display: none;
}
table#products {
.input-quantity {
text-align: center ;
border-right: 0px none ;
}
.input-group-addon {
padding: 5px ;
padding-left: 0px ;
margin: 0px ;
border-left: 0px none ;
border-right: 0px none ;
}
.select-unit {
padding: 0px;
width: 58px;
text-align: center;
height: 22px;
}
.glyphicon-warning-sign {
position: relative;
top: 10px ;
}
}
}

+ 16
- 10
common/models/Order.php View File

@@ -160,7 +160,7 @@ class Order extends ActiveRecordCommon
*/
public static function defaultOptionsSearch() {
return [
'with' => ['productOrder', 'creditHistory','creditHistory.userAction' , 'pointSale'],
'with' => ['productOrder','productOrder.product','creditHistory','creditHistory.userAction' , 'pointSale'],
'join_with' => ['distribution', 'user', 'user.userProducer'],
'orderby' => 'order.date ASC',
'attribute_id_producer' => 'distribution.id_producer'
@@ -186,14 +186,14 @@ class Order extends ActiveRecordCommon
public function initAmount() {
if (isset($this->productOrder)) {
foreach ($this->productOrder as $productOrder) {
if ($productOrder->sale_mode == Product::SALE_MODE_UNIT) {
$this->amount += $productOrder->price * $productOrder->quantity ;
$this->amount += $productOrder->price * $productOrder->quantity ;
if ($productOrder->unit == 'piece') {
if(isset($productOrder->product)) {
$this->weight += ($productOrder->quantity * $productOrder->product->weight) / 1000 ;
}
}
elseif ($productOrder->sale_mode == Product::SALE_MODE_WEIGHT) {
$this->amount += $productOrder->price * $productOrder->quantity / 1000;
else {
$this->weight += $productOrder->quantity ;
}
}
}
@@ -379,7 +379,7 @@ class Order extends ActiveRecordCommon
$i = 0;
foreach ($this->productOrder as $p) {
if (isset($p->product)) {
$html .= $p->quantity . ' x ' . Html::encode($p->product->name);
$html .= Html::encode($p->product->name) .' ('. $p->quantity .'&nbsp;'.Product::strUnit($p->unit, 'wording_short', true).')';
if (++$i != $count) {
$html .= '<br />';
}
@@ -598,15 +598,16 @@ class Order extends ActiveRecordCommon
*
* @return integer
*/
public static function getProductQuantity($idProduct, $orders, $ignoreCancel = false)
{
public static function getProductQuantity($idProduct, $orders, $ignoreCancel = false, $unit = null)
{
$quantity = 0;
if (isset($orders) && is_array($orders) && count($orders)) {
foreach ($orders as $c) {
if(is_null($c->date_delete) || $ignoreCancel) {
foreach ($c->productOrder as $po) {
if ($po->id_product == $idProduct) {
if ($po->id_product == $idProduct &&
((is_null($unit) && $po->product->unit == $po->unit) || (!is_null($unit) && strlen($unit) && $po->unit == $unit))) {
$quantity += $po->quantity ;
}
}
@@ -666,7 +667,12 @@ class Order extends ActiveRecordCommon
$count = 0 ;
if($this->productOrder && is_array($this->productOrder)) {
foreach($this->productOrder as $productOrder) {
$count += $productOrder->quantity ;
if($productOrder->unit == 'piece') {
$count ++ ;
}
else {
$count += $productOrder->quantity ;
}
}
}
return $count ;

+ 84
- 8
common/models/Product.php View File

@@ -52,14 +52,51 @@ use common\components\ActiveRecordCommon ;
* @property double $price
* @property double $pweight
* @property string $recipe
* @property string $unit
* @property double $step
*/
class Product extends ActiveRecordCommon
{
var $total = 0;
var $apply_distributions = false ;
const SALE_MODE_UNIT = 'unit' ;
const SALE_MODE_WEIGHT = 'weight' ;
public static $unitsArray = [
'piece' => [
'unit' => 'piece',
'wording_unit' => 'la pièce',
'wording' => 'pièce(s)',
'wording_short' => 'p.',
'coefficient' => 1
],
'g' => [
'unit' => 'g',
'wording_unit' => 'le g',
'wording' => 'g',
'wording_short' => 'g',
'coefficient' => 1000
],
'kg' => [
'unit' => 'kg',
'wording_unit' => 'le kg',
'wording' => 'kg',
'wording_short' => 'kg',
'coefficient' => 1
],
'mL' => [
'unit' => 'mL',
'wording_unit' => 'le mL',
'wording' => 'mL',
'wording_short' => 'mL',
'coefficient' => 1000
],
'L' => [
'unit' => 'L',
'wording_unit' => 'le litre',
'wording' => 'L',
'wording_short' => 'L',
'coefficient' => 1
],
];
/**
* @inheritdoc
@@ -78,10 +115,16 @@ class Product extends ActiveRecordCommon
[['name', 'id_producer'], 'required'],
[['active', 'order', 'quantity_max', 'id_producer'], 'integer'],
[['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday', 'unavailable','apply_distributions'], 'boolean'],
[['price', 'weight'], 'number'],
[['price', 'weight', 'step'], 'number'],
[[ 'photo'], 'file'],
[['name', 'description', 'photo'], 'string', 'max' => 255],
[['name', 'description', 'photo', 'unit'], 'string', 'max' => 255],
[['recipe'], 'string', 'max' => 1000],
['step', 'required', 'message' => 'Champs obligatoire', 'when' => function($model) {
if($model->unit == 'piece') {
return true ;
}
return false ;
}],
];
}

@@ -96,8 +139,8 @@ class Product extends ActiveRecordCommon
'description' => 'Description',
'active' => 'Actif',
'photo' => 'Photo',
'price' => 'Prix',
'weight' => 'Poids (g)',
'price' => 'Prix (€)',
'weight' => 'Poids',
'recipe' => 'Recette',
'monday' => 'Lundi',
'tuesday' => 'Mardi',
@@ -109,7 +152,9 @@ class Product extends ActiveRecordCommon
'order' => 'Ordre',
'quantity_max' => 'Quantité max par défaut',
'unavailable' => 'Épuisé',
'apply_distributions' => 'Appliquer ces modifications dans les distributions futures'
'apply_distributions' => 'Appliquer ces modifications dans les distributions futures',
'unit' => 'Unité',
'step' => 'Pas'
];
}
@@ -118,6 +163,11 @@ class Product extends ActiveRecordCommon
return $this->hasMany(ProductDistribution::className(), ['id_product' => 'id']);
}
public function getProductSubscription()
{
return $this->hasMany(ProductSubscription::className(), ['id_product' => 'id']);
}
/**
* Retourne les options de base nécessaires à la fonction de recherche.
*
@@ -216,5 +266,31 @@ class Product extends ActiveRecordCommon
return $productGift ;
}

/**
* Retourne le libellé d'une unité.
*
* @param $format wording_unit, wording, short
* @param $unitInDb Unité stockée en base de données (ex: si g > kg, si mL > L)
* @return $string Libellé de l'unité
*/
public static function strUnit($unit, $format = 'wording_short', $unitInDb = false)
{
$strUnit = '' ;
if($unitInDb) {
if($unit == 'g') {
$unit = 'kg' ;
}
if($unit == 'mL') {
$unit = 'L' ;
}
}
if(isset(self::$unitsArray[$unit]) && isset(self::$unitsArray[$unit][$format])) {
$strUnit = self::$unitsArray[$unit][$format] ;
}
return $strUnit ;
}
}

+ 3
- 0
common/models/ProductOrder.php View File

@@ -48,6 +48,7 @@ use common\components\ActiveRecordCommon ;
* @property integer $id_order
* @property integer $id_product
* @property double $quantity
* @property string $unit
*/
class ProductOrder extends ActiveRecordCommon
{
@@ -77,6 +78,7 @@ class ProductOrder extends ActiveRecordCommon
return [
[['id_order', 'id_product', 'quantity'], 'required'],
[['id_order', 'id_product'], 'integer'],
[['unit'], 'string', 'max' => 255],
[['quantity'], 'number', 'min' => 0]
];
}
@@ -91,6 +93,7 @@ class ProductOrder extends ActiveRecordCommon
'id_order' => 'Commande',
'id_product' => 'Product',
'quantity' => 'Quantité',
'unit' => 'Unité'
];
}

+ 21
- 0
common/models/Subscription.php View File

@@ -240,6 +240,8 @@ class Subscription extends ActiveRecordCommon
$productOrder->id_product = $productSubscription->product->id;
$productOrder->quantity = $productSubscription->quantity;
$productOrder->price = $productSubscription->product->price;
$productOrder->unit = $productSubscription->unit;
$productOrder->step = $productSubscription->step;
$productOrder->save();
$productsAdd = true;
}
@@ -453,4 +455,23 @@ class Subscription extends ActiveRecordCommon
}
}
}
/**
* Retourne true si des unités des ProductSubscription ne correspondent pas
* aux Product.
*
* @return boolean
*/
public function hasUnitsNotMatch()
{
if(isset($this->productSubscription) && is_array($this->productSubscription)) {
foreach($this->productSubscription as $productSubscription) {
if(isset($productSubscription->product) && $productSubscription->unit != $productSubscription->product->unit) {
return true ;
}
}
}
return false ;
}
}

+ 39
- 7
common/models/SubscriptionForm.php View File

@@ -48,7 +48,7 @@ use common\models\SubscriptionProduct;
*/
class SubscriptionForm extends Model
{
public $isAdmin = false ;
public $id;
public $id_user;
public $username;
@@ -151,17 +151,49 @@ class SubscriptionForm extends Model

// produits
if ($this->id) {
$productsSubscriptionsArray = ProductSubscription::findAll(['id_subscription' => $this->id]) ;
ProductSubscription::deleteAll(['id_subscription' => $this->id]);
}

foreach ($this->products as $nameInput => $quantity) {
if ($quantity) {
$idProduct = str_replace('product_', '', $nameInput);
$subscriptionProduct = new ProductSubscription;
$subscriptionProduct->id_subscription = $subscription->id;
$subscriptionProduct->id_product = $idProduct;
$subscriptionProduct->quantity = $quantity;
$subscriptionProduct->save();
$idProduct = (int) str_replace('product_', '', $nameInput);
$product = Product::findOne($idProduct) ;

$newProductSubscription = new ProductSubscription;
$newProductSubscription->id_subscription = $subscription->id;
$newProductSubscription->id_product = $idProduct;
if($this->isAdmin) {
$unit = (Yii::$app->getRequest()->post('product_unit_'.$idProduct)) ? Yii::$app->getRequest()->post('product_unit_'.$idProduct) : $product->unit ;
$newProductSubscription->unit = $unit;
$step = (Yii::$app->getRequest()->post('product_step_'.$idProduct)) ? Yii::$app->getRequest()->post('product_step_'.$idProduct) : $product->step ;
$newProductSubscription->step = $step;
$price = (Yii::$app->getRequest()->post('product_price_'.$idProduct)) ? Yii::$app->getRequest()->post('product_price_'.$idProduct) : $product->price ;
$newProductSubscription->price = $price;
}
else {
foreach($productsSubscriptionsArray as $productSubscription) {
if($productSubscription->id_product == $idProduct) {
$newProductSubscription->unit = $productSubscription->unit ;
$newProductSubscription->step = $productSubscription->step ;
$newProductSubscription->price = $productSubscription->price ;
}
}
if(!$newProductSubscription->unit) {
$newProductSubscription->unit = $product->unit ;
}
if(!$newProductSubscription->step) {
$newProductSubscription->step = $product->step;
}
if(!$newProductSubscription->price) {
$newProductSubscription->price = $product->price;
}
}
$newProductSubscription->quantity = $quantity / Product::$unitsArray[$newProductSubscription->unit]['coefficient'];

$newProductSubscription->save();
}
}

+ 26
- 0
console/migrations/m190508_155647_ajout_champs_vente_kilo.php View File

@@ -0,0 +1,26 @@
<?php

use yii\db\Migration;
use yii\db\mysql\Schema;

class m190508_155647_ajout_champs_vente_kilo extends Migration {

public function up() {
$this->dropColumn('product', 'sale_mode') ;
$this->addColumn('product', 'unit', Schema::TYPE_STRING.' DEFAULT \'piece\'') ;
$this->addColumn('product', 'step', Schema::TYPE_FLOAT.' DEFAULT 1') ;
$this->dropColumn('product_order', 'sale_mode') ;
$this->addColumn('product_order', 'unit', Schema::TYPE_STRING.' DEFAULT \'piece\'') ;
}

public function down() {
$this->addColumn('product', 'sale_mode', Schema::TYPE_STRING.' DEFAULT \'unit\'') ;
$this->dropColumn('product', 'unit') ;
$this->dropColumn('product', 'step') ;
$this->addColumn('product_order', 'sale_mode', Schema::TYPE_STRING.' DEFAULT \'unit\'') ;
$this->dropColumn('product_order', 'unit') ;
}

}

+ 15
- 0
console/migrations/m190510_074749_ajout_champs_product_order_step.php View File

@@ -0,0 +1,15 @@
<?php

use yii\db\Migration;
use yii\db\mysql\Schema;

class m190510_074749_ajout_champs_product_order_step extends Migration {

public function up() {
$this->addColumn('product_order', 'step', Schema::TYPE_FLOAT.' DEFAULT 1') ;
}

public function down() {
$this->dropColumn('product_order','step') ;
}
}

+ 17
- 0
console/migrations/m190511_061123_ajout_champs_unit_product_subscription.php View File

@@ -0,0 +1,17 @@
<?php

use yii\db\Migration;
use yii\db\mysql\Schema;

class m190511_061123_ajout_champs_unit_product_subscription extends Migration {

public function up() {
$this->addColumn('product_subscription', 'unit', Schema::TYPE_STRING . ' DEFAULT \'piece\'');
$this->addColumn('product_subscription', 'step', Schema::TYPE_FLOAT . ' DEFAULT 1');
}

public function down() {
$this->dropColumn('product_subscription', 'unit');
$this->dropColumn('product_subscription', 'step');
}
}

+ 27
- 0
console/migrations/m190515_122438_ajout_champs_price_product_subscription.php View File

@@ -0,0 +1,27 @@
<?php

use yii\db\Migration;
use yii\db\mysql\Schema;

class m190515_122438_ajout_champs_price_product_subscription extends Migration {

public function up() {
$this->addColumn('product_subscription', 'price', Schema::TYPE_FLOAT. ' DEFAULT 0') ;
$productsSubscriptionsArray = common\models\ProductSubscription::find()->all() ;
$productsArray = common\models\Product::find()->all() ;
foreach($productsSubscriptionsArray as $productSubscription) {
foreach($productsArray as $product) {
if($productSubscription->id_product == $product->id) {
$productSubscription->price = $product->price ;
$productSubscription->save() ;
}
}
}
}

public function down() {
$this->dropColumn('product_subscription', 'price') ;
}
}

+ 24
- 7
producer/controllers/OrderController.php View File

@@ -43,6 +43,7 @@ use common\models\User ;
use common\models\Producer ;
use common\models\Order ;
use common\models\UserPointSale ;
use common\models\Product ;
use DateTime;

class OrderController extends ProducerBaseController
@@ -228,7 +229,6 @@ class OrderController extends ProducerBaseController
}
}

// date
$errorDate = false;
if (isset($order->id_distribution)) {
@@ -303,6 +303,13 @@ class OrderController extends ProducerBaseController
// suppression de tous les enregistrements ProductOrder
if (!is_null($order)) {
ProductOrder::deleteAll(['id_order' => $order->id]);
$stepsArray = [] ;
if(isset($order->productOrder)) {
foreach($order->productOrder as $productOrder) {
$unitsArray[$productOrder->id_product] = $productOrder->unit;
}
}
}

// produits dispos
@@ -317,14 +324,16 @@ class OrderController extends ProducerBaseController

$productOrder->price = $product->price;

$quantity = (int) $posts['products'][$product->id] ;
$unit = (!is_null($order) && isset($unitsArray[$product->id])) ? $unitsArray[$product->id] : $product->unit ;
$coefficient = Product::$unitsArray[$unit]['coefficient'] ;
$quantity = ((int) $posts['products'][$product->id]) / $coefficient ;
if ($availableProducts[$product->id]['quantity_max'] && $quantity > $availableProducts[$product->id]['quantity_remaining']) {
$quantity = $availableProducts[$product->id]['quantity_remaining'];
}
$productOrder->quantity = $quantity;
$productOrder->sale_mode = Product::SALE_MODE_UNIT ;
$productOrder->unit = $product->unit ;
$productOrder->step = $product->step ;
$productOrder->save();
}
}
@@ -600,6 +609,8 @@ class OrderController extends ProducerBaseController
$indexProduct = 0 ;
foreach($productsArray as &$product) {
$coefficient_unit = Product::$unitsArray[$product['unit']]['coefficient'] ;
if(is_null($product['photo'])) {
$product['photo'] = '' ;
}
@@ -613,17 +624,23 @@ class OrderController extends ProducerBaseController
$quantityOrderUser = Order::getProductQuantity($product['id'], [$orderUser], true) ;
$product['quantity_ordered'] = $quantityOrder ;
$product['quantity_remaining'] = $product['quantity_max'] - $quantityOrder + $quantityOrderUser ;
$product['quantity_form'] = $quantityOrderUser ;
$product['quantity_form'] = $quantityOrderUser * $coefficient_unit ;
foreach($orderUser->productOrder as $productOrder) {
if($productOrder->id_product == $product['id']) {
$product['wording_unit'] = Product::strUnit($productOrder->unit,'wording_unit', true) ;
$product['step'] = $productOrder->step ;
}
}
}
else {
$product['quantity_form'] = 0 ;
$product['wording_unit'] = Product::strUnit($product['unit'],'wording_unit', true) ;
}
$product['coefficient_unit'] = $coefficient_unit ;
if($product['quantity_remaining'] < 0) $product['quantity_remaining'] = 0 ;
$product['index'] = $indexProduct ++ ;
}
$json['products'] = $productsArray;
}

+ 17
- 11
producer/controllers/SubscriptionController.php View File

@@ -40,6 +40,7 @@ namespace producer\controllers;

use common\models\SubscriptionForm ;
use common\models\SubscriptionSearch ;
use common\models\Product ;

class SubscriptionController extends ProducerBaseController
{
@@ -221,33 +222,38 @@ class SubscriptionController extends ProducerBaseController
if($idSubscription > 0) {
// Quantités produit de l'abonnement
$productQuantitiesArray = [] ;
$arrayProductsSubscription = ProductSubscription::searchAll([
'id_subscription' => $idSubscription
]) ;
if(count($arrayProductsSubscription)) {
foreach ($arrayProductsSubscription as $productSubscription) {
$productQuantitiesArray[$productSubscription->id_product] = $productSubscription->quantity;
}
}
}
// Produits
$productsArray = Product::searchAll() ;
$indexProduct = 0 ;
foreach($productsArray as &$product) {
$quantity = 0 ;
if(isset($productQuantitiesArray) && count($productQuantitiesArray) && isset($productQuantitiesArray[$product->id])) {
$quantity = $productQuantitiesArray[$product->id] ;
$coefficientUnit = Product::$unitsArray[$product->unit]['coefficient'] ;
if(isset($arrayProductsSubscription) && count($arrayProductsSubscription)) {
foreach ($arrayProductsSubscription as $productSubscription) {
if($product->id == $productSubscription->id_product) {
$coefficientUnit = Product::$unitsArray[$productSubscription->unit]['coefficient'] ;
$quantity = $productSubscription->quantity * $coefficientUnit;
$product->step = $productSubscription->step;
$product->unit = $productSubscription->unit;
$product->price = $productSubscription->price;
}
}
}
$product = array_merge(
$product->getAttributes(),
[
'index' => $indexProduct ++,
'quantity_form' => $quantity
'quantity_form' => $quantity,
'coefficient_unit' => $coefficientUnit,
'wording_unit' => Product::strUnit($product->unit, 'wording_unit', true),
'wording_short' => Product::strUnit($product->unit, 'wording_short'),
]
) ;
}

+ 4
- 1
producer/views/order/_form.php View File

@@ -37,6 +37,7 @@ termes.
*/

use yii\widgets\ActiveForm;
use common\models\Product;

?>
<div class="order-form">
@@ -216,7 +217,9 @@ use yii\widgets\ActiveForm;
<span class="name"><?= Html::encode($product->name); ?></span> - <span class="description"><?= Html::encode($product->getDescription()); ?></span><br />
<span class="recipe"><?= Html::encode($product->recipe); ?></span>
</td>
<td class="price-unit"><span class="price"><?= number_format($product->price, 2); ?></span> €</td>
<td class="price-unit">
<span class="price"><?= Price::format($product->price); ?></span> €
</td>
<td class="column-quantity">
<div class="input-group" <?php if (isset($availableProducts[$product->id]) && $availableProducts[$product->id]['quantity_remaining'] == 0 && $quantity == 0): ?>style="display:none;"<?php endif; ?>>
<span class="input-group-btn">

+ 8
- 7
producer/views/order/order.php View File

@@ -186,33 +186,34 @@ $this->setTitle('Commander') ;
<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 v-if="product.unit == 'piece' && product.weight">({{ product.weight }}g)</span>
</span>
<span v-if="product.quantity_form == product.quantity_remaining && product.quantity_max > 0" class="label label-danger">
<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">
{{ formatPrice(product.price) }}
{{ formatPrice(product.price) }}<br /><span class="unit">{{ product.wording_unit }}</span>
</td>
<td class="td-quantity">
<div class="input-group">
<span class="input-group-btn">
<button class="btn btn-default btn-moins" type="button" @click="productQuantityClick(product, -1)" :disabled="product.quantity_form == 0"><span class="glyphicon glyphicon-minus"></span></button>
<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, 1)" :disabled="product.quantity_form == product.quantity_remaining && product.quantity_max > 0"><span class="glyphicon glyphicon-plus"></span></button>
<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>
</td>
<td class="price-total">
{{ formatPrice(product.price * product.quantity_form) }}
{{ formatPrice(product.price * (product.quantity_form / product.coefficient_unit )) }}
</td>
</tr>
<tr class="total">
<td colspan="3"></td>
<td colspan="4"></td>
<td class="price-total">{{ priceTotal(true) }}</td>
</tr>
</tbody>

+ 1
- 1
producer/views/site/index.php View File

@@ -125,7 +125,7 @@ $this->setPageTitle(Html::encode($producer->type.' à '.$producer->city)) ;
'attribute' => 'price',
'value' => function($model) {
if($model->price) {
return Price::format($model->price) ;
return Price::format($model->price).' ('.Product::strUnit($model->unit, 'wording_unit', true).')' ;
}
return '' ;
}

+ 7
- 4
producer/views/subscription/_form.php View File

@@ -215,21 +215,24 @@ use common\models\PointSale ;
<div class="recipe" v-if="product.recipe.length">{{ product.recipe }}</div>
</td>
<td class="price-unit">
{{ formatPrice(product.price) }}
{{ formatPrice(product.price) }}<br /><span class="unit">{{ product.wording_unit }}</span>
</td>
<td class="quantity">
<div class="input-group">
<input type="hidden" :value="product.step" :name="'product_step_'+product.step" />
<input type="hidden" :value="product.unit" :name="'product_unit_'+product.unit" />
<span class="input-group-btn">
<button class="btn btn-default" type="button" @click="productQuantityClick(product, -1)"><span class="glyphicon glyphicon-minus"></span></button>
<button class="btn btn-default" type="button" @click="productQuantityClick(product, -product.step)"><span class="glyphicon glyphicon-minus"></span></button>
</span>
<input type="text" v-model="product.quantity_form" :class="'form-control '+((product.quantity_form > 0) ? 'has-quantity' : '')">
<span class="input-group-addon">{{ product.wording_short }}</span>
<span class="input-group-btn">
<button class="btn btn-default" type="button" @click="productQuantityClick(product, 1)"><span class="glyphicon glyphicon-plus"></span></button>
<button class="btn btn-default" type="button" @click="productQuantityClick(product, product.step)"><span class="glyphicon glyphicon-plus"></span></button>
</span>
</div>
</td>
<td class="price-total">
{{ formatPrice(product.price * product.quantity_form) }}
{{ formatPrice(product.price * (product.quantity_form / product.coefficient_unit )) }}
</td>
</tr>
<tr class="total">

+ 2
- 1
producer/views/subscription/index.php View File

@@ -38,6 +38,7 @@ termes.

use yii\helpers\Html;
use yii\grid\GridView;
use common\models\Product ;

$this->setTitle('Abonnements') ;
$this->addButton(['label' => '<span class="glyphicon glyphicon-plus"></span> Ajouter', 'url' => 'subscription/form', 'class' => 'btn btn-primary']) ;
@@ -52,7 +53,7 @@ $columns = [
foreach($model->productSubscription as $productSubscription)
{
if(isset($productSubscription->product)) {
$html .= $productSubscription->quantity . '&nbsp;x&nbsp;'.Html::encode($productSubscription->product->name).'<br />' ;
$html .= Html::encode($productSubscription->product->name).' ('.($productSubscription->quantity * Product::$unitsArray[$productSubscription->unit]['coefficient']) . '&nbsp'.Product::strUnit($productSubscription->unit, 'wording_short').')<br />' ;
}
else {
$html .= 'Produit non défini<br />' ;

+ 41
- 13
producer/web/css/screen.css View File

@@ -1486,31 +1486,45 @@ termes.
text-align: center;
}
/* line 224, ../sass/order/_order.scss */
.order-order #app-order-order table#products .price-unit .unit, .order-order #app-order-order table#products .price-total .unit {
color: gray;
font-size: 13px;
}
/* line 229, ../sass/order/_order.scss */
.order-order #app-order-order table#products .td-quantity {
width: 150px;
width: 175px;
}
/* line 226, ../sass/order/_order.scss */
/* line 231, ../sass/order/_order.scss */
.order-order #app-order-order table#products .td-quantity input.quantity {
text-align: center;
border-right: 0px none;
}
/* line 232, ../sass/order/_order.scss */
/* line 235, ../sass/order/_order.scss */
.order-order #app-order-order table#products .td-quantity .input-group-addon {
padding: 5px;
padding-left: 0px;
margin: 0px;
border-left: 0px none;
border-right: 0px none;
}
/* line 245, ../sass/order/_order.scss */
.order-order #app-order-order table#products tr.total .price-total {
font-size: 23px;
}
/* line 240, ../sass/order/_order.scss */
/* line 253, ../sass/order/_order.scss */
.order-order #app-order-order #content-step-payment .credit .info {
margin-left: 20px;
color: gray;
}
/* line 246, ../sass/order/_order.scss */
/* line 259, ../sass/order/_order.scss */
.order-order #app-order-order #content-step-payment .comment {
margin-bottom: 20px;
}
/* line 251, ../sass/order/_order.scss */
/* line 264, ../sass/order/_order.scss */
.order-order #app-order-order #infos {
margin-top: 30px;
}
/* line 253, ../sass/order/_order.scss */
/* line 266, ../sass/order/_order.scss */
.order-order #app-order-order #infos .panel-body {
padding-top: 0px;
white-space: pre-line;
@@ -1663,43 +1677,57 @@ termes.
/* line 73, ../sass/subscription/_form.scss */
.subscription-create .subscription-form .products td.quantity,
.subscription-update .subscription-form .products td.quantity {
width: 150px;
width: 180px;
}
/* line 76, ../sass/subscription/_form.scss */
.subscription-create .subscription-form .products td.quantity input,
.subscription-update .subscription-form .products td.quantity input {
text-align: center;
border-right: 0px none;
}
/* line 79, ../sass/subscription/_form.scss */
.subscription-create .subscription-form .products td.quantity input.has-quantity,
.subscription-update .subscription-form .products td.quantity input.has-quantity {
font-weight: bold;
}
/* line 85, ../sass/subscription/_form.scss */
/* line 84, ../sass/subscription/_form.scss */
.subscription-create .subscription-form .products td.quantity .input-group-addon,
.subscription-update .subscription-form .products td.quantity .input-group-addon {
background-color: white;
padding-left: 0px;
border-left: 0px none;
}
/* line 91, ../sass/subscription/_form.scss */
.subscription-create .subscription-form .products .name,
.subscription-update .subscription-form .products .name {
font-family: "capsuularegular";
font-size: 20px;
color: black;
}
/* line 91, ../sass/subscription/_form.scss */
/* line 97, ../sass/subscription/_form.scss */
.subscription-create .subscription-form .products .description,
.subscription-update .subscription-form .products .description {
font-style: italic;
}
/* line 95, ../sass/subscription/_form.scss */
/* line 101, ../sass/subscription/_form.scss */
.subscription-create .subscription-form .products .recipe,
.subscription-update .subscription-form .products .recipe {
font-size: 12px;
}
/* line 99, ../sass/subscription/_form.scss */
/* line 105, ../sass/subscription/_form.scss */
.subscription-create .subscription-form .products .price-unit, .subscription-create .subscription-form .products .price-total,
.subscription-update .subscription-form .products .price-unit,
.subscription-update .subscription-form .products .price-total {
text-align: center;
width: 150px;
}
/* line 104, ../sass/subscription/_form.scss */
/* line 110, ../sass/subscription/_form.scss */
.subscription-create .subscription-form .products .unit,
.subscription-update .subscription-form .products .unit {
color: gray;
font-size: 13px;
}
/* line 115, ../sass/subscription/_form.scss */
.subscription-create .subscription-form .products tr.total .price-total,
.subscription-update .subscription-form .products tr.total .price-total {
text-align: center;

+ 9
- 3
producer/web/js/vuejs/order-order.js View File

@@ -255,8 +255,9 @@ var app = new Vue({
this.changeStep('products') ;
},
productQuantityClick: function(product, quantity) {
console.log(this.products[product.index].quantity_remaining) ;
if( this.products[product.index].quantity_form + quantity >= 0 &&
(this.products[product.index].quantity_form + quantity <= this.products[product.index].quantity_remaining ||
(this.products[product.index].quantity_form + quantity <= (this.products[product.index].quantity_remaining * this.products[product.index].coefficient_unit) ||
!this.products[product.index].quantity_max)
) {
this.products[product.index].quantity_form += quantity ;
@@ -274,7 +275,12 @@ var app = new Vue({
var count = 0 ;
for(var key in this.products) {
if(this.products[key].quantity_form > 0) {
count += this.products[key].quantity_form ;
if(this.products[key].unit != 'piece') {
count ++ ;
}
else {
count += this.products[key].quantity_form ;
}
}
}
return count ;
@@ -283,7 +289,7 @@ var app = new Vue({
var price = 0 ;
for(var key in this.products) {
if(this.products[key].quantity_form > 0) {
price += this.products[key].quantity_form * this.products[key].price ;
price += (this.products[key].quantity_form / this.products[key].coefficient_unit) * this.products[key].price ;
}
}
if(format) {

+ 1
- 1
producer/web/js/vuejs/subscription-form.js View File

@@ -179,7 +179,7 @@ var app = new Vue({
var price = 0 ;
for(var key in this.products) {
if(this.products[key].quantity_form > 0) {
price += this.products[key].quantity_form * this.products[key].price ;
price += (this.products[key].quantity_form / this.products[key].coefficient_unit) * this.products[key].price ;
}
}
if(format) {

+ 14
- 1
producer/web/sass/order/_order.scss View File

@@ -220,11 +220,24 @@
.price-unit, .price-total {
width: 100px ;
text-align: center ;
.unit {
color: gray ;
font-size: 13px ;
}
}
.td-quantity {
width: 150px ;
width: 175px ;
input.quantity {
text-align: center ;
border-right: 0px none ;
}
.input-group-addon {
padding: 5px ;
padding-left: 0px ;
margin: 0px ;
border-left: 0px none ;
border-right: 0px none ;
}
}

+ 13
- 2
producer/web/sass/subscription/_form.scss View File

@@ -71,15 +71,21 @@
}
td.quantity {
width: 150px ;
width: 180px ;
input {
text-align: center ;
border-right: 0px none ;
&.has-quantity {
font-weight: bold ;
}
}
.input-group-addon {
background-color: white ;
padding-left: 0px ;
border-left: 0px none ;
}
}
.name {
@@ -101,6 +107,11 @@
width: 150px ;
}
.unit {
color: gray ;
font-size: 13px ;
}
tr.total .price-total {
text-align: center ;
font-size: 20px ;

Loading…
Cancel
Save