Browse Source

Merge branch 'feature/specific_prices' into dev

# Conflicts:
#	backend/controllers/ProductController.php
#	backend/web/js/backend.js
#	common/models/Subscription.php
dev
Guillaume 3 years ago
parent
commit
708d230018
32 changed files with 1768 additions and 654 deletions
  1. +34
    -0
      backend/controllers/DistributionController.php
  2. +272
    -173
      backend/controllers/ProductController.php
  3. +19
    -0
      backend/controllers/UserController.php
  4. +6
    -4
      backend/views/distribution/index.php
  5. +4
    -0
      backend/views/point-sale/_form.php
  6. +89
    -128
      backend/views/product/_form.php
  7. +14
    -0
      backend/views/product/update/_nav.php
  8. +4
    -0
      backend/views/product/update/_nav_item.php
  9. +3
    -0
      backend/views/product/update/prices/_base_price.php
  10. +66
    -0
      backend/views/product/update/prices/_form.php
  11. +27
    -19
      backend/views/product/update/prices/create.php
  12. +227
    -0
      backend/views/product/update/prices/list.php
  13. +61
    -0
      backend/views/product/update/prices/update.php
  14. +62
    -0
      backend/views/product/update/update.php
  15. +4
    -0
      backend/views/user/_form.php
  16. +203
    -198
      backend/web/css/screen.css
  17. +43
    -8
      backend/web/js/backend.js
  18. +51
    -0
      backend/web/js/vuejs/distribution-index.js
  19. +0
    -8
      backend/web/sass/producer/_update.scss
  20. +18
    -0
      backend/web/sass/screen.scss
  21. +16
    -2
      common/models/PointSale.php
  22. +64
    -6
      common/models/Product.php
  23. +153
    -0
      common/models/ProductPrice.php
  24. +94
    -0
      common/models/ProductPriceSearch.php
  25. +4
    -1
      common/models/Subscription.php
  26. +39
    -3
      common/models/User.php
  27. +95
    -88
      common/models/UserProducer.php
  28. +30
    -0
      console/migrations/m201207_160043_specific_prices.php
  29. +34
    -0
      console/migrations/m201207_164410_specific_prices_percent.php
  30. +10
    -14
      producer/controllers/OrderController.php
  31. +18
    -1
      producer/controllers/SubscriptionController.php
  32. +4
    -1
      producer/web/js/vuejs/order-order.js

+ 34
- 0
backend/controllers/DistributionController.php View File

use common\models\DeliveryNote; use common\models\DeliveryNote;
use common\models\Distribution; use common\models\Distribution;
use common\models\Document; use common\models\Document;
use common\models\PointSale;
use common\models\Product; use common\models\Product;
use common\models\Producer; use common\models\Producer;
use common\models\Order; use common\models\Order;
]; ];
} }


public function actionAjaxUpdateProductOrder($idUser = false, $idPointSale = false)
{
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

$user = User::findOne($idUser) ;
$userProducer = UserProducer::searchOne([
'id_user' => $idUser,
]) ;
$pointSale = PointSale::findOne($idPointSale) ;

$productsArray = Product::find()
->where([
'id_producer' => GlobalParam::getCurrentProducerId(),
'product.active' => 1,
])->joinWith(['productPrice'])
->all();

$productOrderArray = [];
foreach ($productsArray as $product) {
$productOrderArray[$product['id']] = [
'quantity' => 0,
'unit' => $product->unit,
'price' => $product->getPriceWithTax([
'user' => $user,
'user_producer' => $userProducer,
'point_sale' => $pointSale
]),
];
}

return $productOrderArray ;
}

/** /**
* Génére un PDF récapitulatif des des commandes d'un producteur pour une * Génére un PDF récapitulatif des des commandes d'un producteur pour une
* date donnée (Méthode appelable via CRON) * date donnée (Méthode appelable via CRON)

+ 272
- 173
backend/controllers/ProductController.php View File

<?php <?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.
*/
/**
* 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\controllers; namespace backend\controllers;


use common\helpers\GlobalParam; use common\helpers\GlobalParam;
use common\models\ProductDistribution; use common\models\ProductDistribution;
use common\models\ProductPrice;
use common\models\ProductPriceSearch;
use common\models\ProductSearch;
use common\models\UserSearch;
use Yii; use Yii;
use yii\filters\AccessControl; use yii\filters\AccessControl;
use common\models\Product; use common\models\Product;
/** /**
* ProduitController implements the CRUD actions for Produit model. * ProduitController implements the CRUD actions for Produit model.
*/ */
class ProductController extends BackendController
class ProductController extends BackendController
{ {
var $enableCsrfValidation = false;

public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
],
],
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'allow' => true,
'roles' => ['@'],
'matchCallback' => function ($rule, $action) {
return User::hasAccessBackend();
}
]
],
],
];
}
var $enableCsrfValidation = false;


/**
* Liste les modèles Produit.
*
* @return mixed
*/
public function actionIndex()
{
$searchModel = new ProductSearch() ;
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
],
],
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'allow' => true,
'roles' => ['@'],
'matchCallback' => function ($rule, $action) {
return User::hasAccessBackend();
}
]
],
],
];
}


/**
* Crée un modèle Produit.
* Si la création réussit, le navigateur est redirigé vers la page 'index'.
*
* @return mixed
*/
public function actionCreate()
{
$model = new Product();
/**
* Liste les modèles Produit.
*
* @return mixed
*/
public function actionIndex()
{
$searchModel = new ProductSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);

return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}


$model->active = 1;
$model->id_producer = GlobalParam::getCurrentProducerId();
/**
* Crée un modèle Produit.
* Si la création réussit, le navigateur est redirigé vers la page 'index'.
*
* @return mixed
*/
public function actionCreate()
{
$model = new Product();
$model->active = 1;
$model->id_producer = GlobalParam::getCurrentProducerId();


$model->monday = 1 ; $model->monday = 1 ;
$model->tuesday = 1 ; $model->tuesday = 1 ;


// link product / distribution // link product / distribution
Distribution::linkProductIncomingDistributions($model) ; Distribution::linkProductIncomingDistributions($model) ;
Yii::$app->getSession()->setFlash('success', 'Produit <strong>'.Html::encode($model->name).'</strong> ajouté'); Yii::$app->getSession()->setFlash('success', 'Produit <strong>'.Html::encode($model->name).'</strong> ajouté');


return $this->redirect(['index']); return $this->redirect(['index']);
}
}
else { else {
return $this->render('create', [ return $this->render('create', [
'model' => $model, 'model' => $model,
} }
} }


/**
* Modifie un modèle Produit existant.
* Si la modification réussit, le navigateur est redirigé vers la page 'index'.
*
* @param integer $id
* @return mixed
*/
public function actionUpdate($id)
{
$request = Yii::$app->request;
/**
* Modifie un modèle Produit existant.
* Si la modification réussit, le navigateur est redirigé vers la page 'index'.
*
* @param integer $id
* @return mixed
*/
public function actionUpdate($id)
{
$request = Yii::$app->request;


$model = $this->findModel($id);
$photoFilenameOld = $model->photo;
$model = $this->findModel($id);
$photoFilenameOld = $model->photo;


if ($model->load(Yii::$app->request->post()) && $model->save()) {
Upload::uploadFile($model, 'photo', $photoFilenameOld);
if ($model->load(Yii::$app->request->post()) && $model->save()) {


$deletePhoto = $request->post('delete_photo', 0);
if ($deletePhoto) {
$model->photo = '';
$model->save();
}
if($model->apply_distributions) {
// link product / distribution
Distribution::linkProductIncomingDistributions($model) ;
}
Yii::$app->getSession()->setFlash('success', 'Produit <strong>'.Html::encode($model->name).'</strong> modifié');
return $this->redirect(['index']);
} else {
return $this->render('update', [
'model' => $model,
]);
Upload::uploadFile($model, 'photo', $photoFilenameOld);

$deletePhoto = $request->post('delete_photo', 0);
if ($deletePhoto) {
$model->photo = '';
$model->save();
}

if ($model->apply_distributions) {
// link product / distribution
Distribution::linkProductIncomingDistributions($model);
}

Yii::$app->getSession()->setFlash('success', 'Produit <strong>' . Html::encode($model->name) . '</strong> modifié');
return $this->redirect(['index']);
}

return $this->render('update/update', [
'model' => $model,
'action' => 'update',
]);
} }
}


/**
* Supprime un modèle Produit.
* Si la suppression réussit, le navigateur est redirigé vers la page
* 'index'.
*
* @param integer $id
* @return mixed
*/
public function actionDelete($id, $confirm = false)
{
$product = $this->findModel($id) ;
if($confirm) {
$product->delete();
ProductDistribution::deleteAll(['id_product' => $id]) ;
Yii::$app->getSession()->setFlash('success', 'Produit <strong>'.Html::encode($product->name).'</strong> supprimé');
}
else {
Yii::$app->getSession()->setFlash('info', 'Souhaitez-vous vraiment supprimer le produit <strong>'.Html::encode($product->name).'</strong> ? '
. Html::a('Oui',['product/delete','id' => $id, 'confirm' => 1], ['class' => 'btn btn-default']).' '.Html::a('Non', ['product/index'], ['class' => 'btn btn-default']));
public function actionPricesList($id)
{
$request = Yii::$app->request;
$model = $this->findModel($id);

$searchModel = new ProductPriceSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);

$userProducerWithProductPercent = UserProducer::searchAll([], [
'join_with' => ['user'],
'conditions' => 'user_producer.product_price_percent != 0',
]) ;

$pointSaleWithProductPercent = PointSale::searchAll([], [
'conditions' => 'point_sale.product_price_percent != 0'
]) ;

return $this->render('update/prices/list', [
'model' => $model,
'action' => 'prices-list',
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
'userProducerWithProductPercent' => $userProducerWithProductPercent,
'pointSaleWithProductPercent' => $pointSaleWithProductPercent,
]);
} }
return $this->redirect(['index']);
}


/**
* Modifie l'ordre des produits.
*
* @param array $array
*/
public function actionOrder()
{
$array = Yii::$app->request->post('array') ;
$orderArray = json_decode(stripslashes($array));
foreach($orderArray as $id => $order) {
$product = $this->findModel($id);
$product->order = $order;
$product->save();
public function actionPricesCreate($idProduct)
{
$model = new ProductPrice();
$model->id_product = $idProduct;
$modelProduct = $this->findModel($idProduct) ;

if ($model->load(Yii::$app->request->post())) {

$conditionsProductPriceExist = [
'id_product' => $idProduct,
'id_user' => $model->id_user ? $model->id_user : null,
'id_point_sale' => $model->id_point_sale ? $model->id_point_sale : null,
] ;

$productPriceExist = ProductPrice::findOne($conditionsProductPriceExist) ;

if($productPriceExist) {
$productPriceExist->delete() ;
Yii::$app->getSession()->setFlash('warning', 'Un prix existait déjà pour cet utilisateur / point de vente, il a été supprimé.');
}

if($model->save()) {
Yii::$app->getSession()->setFlash('success', 'Le prix a bien été ajouté.');
return $this->redirect(['product/prices-list', 'id' => $idProduct]);
}
}

return $this->render('update/prices/create', [
'model' => $model,
'modelProduct' => $modelProduct,
]);
} }
}


/**
* Recherche un produit en fonction de son ID.
*
* @param integer $id
* @return Produit
* @throws NotFoundHttpException si le modèle n'est pas trouvé
*/
protected function findModel($id)
{
if (($model = Product::findOne($id)) !== null) {
return $model;
} else {
throw new NotFoundHttpException('The requested page does not exist.');
public function actionPricesUpdate($id)
{
$request = Yii::$app->request;

$model = $this->findModelProductPrice($id);
$modelProduct = $this->findModel($model->id_product) ;

if ($model->load(Yii::$app->request->post()) && $model->save()) {
Yii::$app->getSession()->setFlash('success', 'Prix modifié');
return $this->redirect(['product/prices-list', 'id' => $model->id_product]);
}

return $this->render('update/prices/update', [
'model' => $model,
'modelProduct' => $modelProduct,
'action' => 'prices-update',
]);
}

public function actionPricesDelete($id)
{
$productPrice = $this->findModelProductPrice($id);
$productPrice->delete();
Yii::$app->getSession()->setFlash('success', 'Prix supprimé');
return $this->redirect(['product/prices-list', 'id' => $productPrice->id_product]);
}

/**
* Supprime un modèle Produit.
* Si la suppression réussit, le navigateur est redirigé vers la page
* 'index'.
*
* @param integer $id
* @return mixed
*/
public function actionDelete($id, $confirm = false)
{
$product = $this->findModel($id);

if ($confirm) {
$product->delete();
ProductDistribution::deleteAll(['id_product' => $id]);
Yii::$app->getSession()->setFlash('success', 'Produit <strong>' . Html::encode($product->name) . '</strong> supprimé');
} else {
Yii::$app->getSession()->setFlash('info', 'Souhaitez-vous vraiment supprimer le produit <strong>' . Html::encode($product->name) . '</strong> ? '
. Html::a('Oui', ['product/delete', 'id' => $id, 'confirm' => 1], ['class' => 'btn btn-default']) . ' ' . Html::a('Non', ['product/index'], ['class' => 'btn btn-default']));
}

return $this->redirect(['index']);
}

/**
* Modifie l'ordre des produits.
*
* @param array $array
*/
public function actionOrder()
{
$array = Yii::$app->request->post('array');
$orderArray = json_decode(stripslashes($array));

foreach ($orderArray as $id => $order) {
$product = $this->findModel($id);
$product->order = $order;
$product->save();
}
}

/**
* Recherche un produit en fonction de son ID.
*
* @param integer $id
* @return Produit
* @throws NotFoundHttpException si le modèle n'est pas trouvé
*/
protected function findModel($id)
{
if (($model = Product::findOne($id)) !== null) {
return $model;
} else {
throw new NotFoundHttpException('The requested page does not exist.');
}
}

protected function findModelProductPrice($id)
{
if (($model = ProductPrice::findOne($id)) !== null) {
return $model;
} else {
throw new NotFoundHttpException('The requested page does not exist.');
}
} }
}


} }

+ 19
- 0
backend/controllers/UserController.php View File

$model->points_sale[] = $userPointSaleArray->id_point_sale; $model->points_sale[] = $userPointSaleArray->id_point_sale;
} }
} }

$userProducer = UserProducer::searchOne([
'id_producer' => GlobalParam::getCurrentProducerId(),
'id_user' => $model->id
]) ;
$model->product_price_percent = $userProducer->product_price_percent ;
} }


// points de vente // points de vente


$model->sendMailWelcome($password); $model->sendMailWelcome($password);
$this->processLinkPointSale($model); $this->processLinkPointSale($model);
$this->processProductPricePercent($model) ;


Yii::$app->getSession()->setFlash('success', 'Utilisateur créé.'); Yii::$app->getSession()->setFlash('success', 'Utilisateur créé.');
$model = new User(); $model = new User();
$model->sendMailWelcome($password); $model->sendMailWelcome($password);
} }
$this->processLinkPointSale($model); $this->processLinkPointSale($model);
$this->processProductPricePercent($model) ;
Yii::$app->getSession()->setFlash('success', 'Utilisateur modifié.'); Yii::$app->getSession()->setFlash('success', 'Utilisateur modifié.');
} }
} else { } else {
} }
} }


public function processProductPricePercent($model)
{
$userProducer = UserProducer::searchOne([
'id_producer' => GlobalParam::getCurrentProducerId(),
'id_user' => $model->id
]) ;
$userProducer->product_price_percent = $model->product_price_percent ;

$userProducer->save() ;
}

/** /**
* Désactive l'utilisateur de l'établissement. * Désactive l'utilisateur de l'établissement.
* *

+ 6
- 4
backend/views/distribution/index.php View File

:producer="producer" :producer="producer"
@close="showModalFormOrderCreate = false" @close="showModalFormOrderCreate = false"
@ordercreatedupdated="orderCreatedUpdated" @ordercreatedupdated="orderCreatedUpdated"
@updateproductorderprices="updateProductOrderPrices"
></order-form> ></order-form>


<div id="wrapper-nav-points-sale"> <div id="wrapper-nav-points-sale">
:producer="producer" :producer="producer"
@close="showModalFormOrderUpdate = false" @close="showModalFormOrderUpdate = false"
@ordercreatedupdated="orderCreatedUpdated" @ordercreatedupdated="orderCreatedUpdated"
@updateproductorderprices="updateProductOrderPrices"
></order-form> ></order-form>


<modal v-if="showModalPayment && idOrderPayment == order.id" class="modal-payment" @close="showModalPayment = false"> <modal v-if="showModalPayment && idOrderPayment == order.id" class="modal-payment" @close="showModalPayment = false">
<label class="control-label" for="select-id-user"> <label class="control-label" for="select-id-user">
Utilisateur Utilisateur
</label> </label>
<select class="form-control" v-model="order.id_user">
<select class="form-control" v-model="order.id_user" @change="userChange">
<option value="0">--</option> <option value="0">--</option>
<option v-for="user in users" :value="user.id_user" @click="userChange">
<option v-for="user in users" :value="user.id_user">
<template v-if="user.name_legal_person && user.name_legal_person.length"> <template v-if="user.name_legal_person && user.name_legal_person.length">
Personne morale / {{ user.name_legal_person }} Personne morale / {{ user.name_legal_person }}
</template> </template>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label" for="select-id-point-sale">Point de vente</label> <label class="control-label" for="select-id-point-sale">Point de vente</label>
<select class="form-control" id="select-id-point-sale" v-model="order.id_point_sale">
<select class="form-control" id="select-id-point-sale" v-model="order.id_point_sale" @change="pointSaleChange">
<option value="0">--</option> <option value="0">--</option>
<option v-for="pointSale in pointsSale" v-if="pointSale.pointSaleDistribution[0].delivery == 1" :value="pointSale.id">{{ pointSale.name }}</option>
<option v-for="pointSale in pointsSale" v-if="pointSale.pointSaleDistribution[0].delivery == 1" :value="pointSale.id"">{{ pointSale.name }}</option>
</select> </select>
</div> </div>
<div class="form-group"> <div class="form-group">

+ 4
- 0
backend/views/point-sale/_form.php View File

use yii\widgets\ActiveForm; use yii\widgets\ActiveForm;
use yii\helpers\ArrayHelper; use yii\helpers\ArrayHelper;
use common\models\Producer; use common\models\Producer;
use common\models\ProductPrice ;


/* @var $this yii\web\View */ /* @var $this yii\web\View */
/* @var $model backend\models\PointVente */ /* @var $model backend\models\PointVente */
Producer::CREDIT_FUNCTIONING_USER => Producer::$creditFunctioningArray[Producer::CREDIT_FUNCTIONING_USER], Producer::CREDIT_FUNCTIONING_USER => Producer::$creditFunctioningArray[Producer::CREDIT_FUNCTIONING_USER],
], [])->hint(Producer::HINT_CREDIT_FUNCTIONING); ?> ], [])->hint(Producer::HINT_CREDIT_FUNCTIONING); ?>


<?= $form->field($model, 'product_price_percent')
->dropDownList(ProductPrice::percentValues(), [])->hint('Pourcentage appliqué aux prix de chaque produit dans ce point de vente.'); ?>



<div id="delivery-days"> <div id="delivery-days">
<h2>Jours de livraison</h2> <h2>Jours de livraison</h2>

+ 89
- 128
backend/views/product/_form.php View File

<?php <?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.
*/

use yii\helpers\Html; use yii\helpers\Html;
use yii\bootstrap\ActiveForm; use yii\bootstrap\ActiveForm;
use common\models\Product; use common\models\Product;
use common\models\Producer; use common\models\Producer;
use common\helpers\GlobalParam; use common\helpers\GlobalParam;


/* @var $this yii\web\View */
/* @var $model app\models\Produit */
/* @var $form yii\widgets\ActiveForm */
?> ?>


<div class="product-form"> <div class="product-form">
'options' => ['enctype' => 'multipart/form-data'] 'options' => ['enctype' => 'multipart/form-data']
]); ?> ]); ?>


<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') ?>
<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, 'unit')
->dropDownList(ArrayHelper::map(Product::$unitsArray, 'unit', 'wording'))
->label('Unité (pièce, poids ou volume)'); ?>




<?php
<?php


//Récupère la tva par défaut du producteur courant
$producer = \common\helpers\GlobalParam::getCurrentProducer();
$taxRateDefault = $producer->taxRate;
//Récupère la tva par défaut du producteur courant
$producer = \common\helpers\GlobalParam::getCurrentProducer();
$taxRateDefault = $producer->taxRate;


$taxRateNamesArray = array_merge(array(0 => 'Tva par défaut'), ArrayHelper::map(TaxRate::find()->all(), 'id', function ($model) {
return $model->name;
}));
$taxRateValuesArray = array_merge(array(0 => $taxRateDefault->value), ArrayHelper::map(TaxRate::find()->all(), 'id', function ($model) {
return $model->value;
}));
foreach ($taxRateValuesArray as $key => $taxRateValue) {
$taxRateValuesArrayFormatted[$key] = array('data-tax-rate-value' => $taxRateValue);
}
$taxRateNamesArray = array_merge(array(0 => 'Tva par défaut'), ArrayHelper::map(TaxRate::find()->all(), 'id', function ($model) {
return $model->name;
}));
$taxRateValuesArray = array_merge(array(0 => $taxRateDefault->value), ArrayHelper::map(TaxRate::find()->all(), 'id', function ($model) {
return $model->value;
}));
foreach ($taxRateValuesArray as $key => $taxRateValue) {
$taxRateValuesArrayFormatted[$key] = array('data-tax-rate-value' => $taxRateValue);
}


?>
?>


<?php if($taxRateDefault->value != 0): ?>
<?= $form->field($model, 'id_tax_rate')->dropDownList($taxRateNamesArray, ['options' => $taxRateValuesArrayFormatted])->label('Taxe'); ?>
<?php endif; ?>
<?php if($taxRateDefault->value != 0): ?>
<?= $form->field($model, 'id_tax_rate')->dropDownList($taxRateNamesArray, ['options' => $taxRateValuesArrayFormatted])->label('Taxe'); ?>
<?php endif; ?>


<?= $form->field($model, 'price', [
'template' => '
<?= $form->field($model, 'price', [
'template' => '
<div class="row"> <div class="row">
<div class="col-xs-6"> <div class="col-xs-6">
<label for="product-price" class="control-label without-tax"></label> <label for="product-price" class="control-label without-tax"></label>
</div> </div>
', ',
]) ?>
<?= $form->field($model, 'step')->textInput()->hint('Définit ce qui est ajouté ou enlevé lors des changements de quantité.') ?>
]) ?>
<?= $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, 'weight')->textInput()->label('Poids (g)') ?>


<div class="col-md-3">
<?= $form->field($model, 'quantity_max')->textInput() ?>
</div>
<div class="col-md-3">
<?= $form->field($model, 'quantity_max_monday')->textInput() ?>
</div>
<div class="col-md-3">
<?= $form->field($model, 'quantity_max_tuesday')->textInput() ?>
</div>
<div class="col-md-3">
<?= $form->field($model, 'quantity_max_wednesday')->textInput() ?>
</div>
<div class="col-md-3">
<?= $form->field($model, 'quantity_max_thursday')->textInput() ?>
</div>
<div class="col-md-3">
<?= $form->field($model, 'quantity_max_friday')->textInput() ?>
</div>
<div class="col-md-3">
<?= $form->field($model, 'quantity_max_saturday')->textInput() ?>
<div class="col-md-3">
<?= $form->field($model, 'quantity_max')->textInput() ?>
</div>
<div class="col-md-3">
<?= $form->field($model, 'quantity_max_monday')->textInput() ?>
</div>
<div class="col-md-3">
<?= $form->field($model, 'quantity_max_tuesday')->textInput() ?>
</div>
<div class="col-md-3">
<?= $form->field($model, 'quantity_max_wednesday')->textInput() ?>
</div>
<div class="col-md-3">
<?= $form->field($model, 'quantity_max_thursday')->textInput() ?>
</div>
<div class="col-md-3">
<?= $form->field($model, 'quantity_max_friday')->textInput() ?>
</div>
<div class="col-md-3">
<?= $form->field($model, 'quantity_max_saturday')->textInput() ?>
</div>
<div class="col-md-3">
<?= $form->field($model, 'quantity_max_sunday')->textInput() ?>
</div>
<div class="clr"></div>

<?php
if (!$model->isNewRecord) {
echo $form->field($model, 'apply_distributions')
->checkbox()
->hint('Sélectionnez cette option si vous souhaitez que ces modifications (actif / non actif, quantité max) soient répercutées dans les distributions à venir déjà initialisées.');
}
?>
</div> </div>
<div class="col-md-3">
<?= $form->field($model, 'quantity_max_sunday')->textInput() ?>
<div class="col-md-4">
<?= $form->field($model, 'photo')->fileInput() ?>
<?php
if (strlen($model->photo)) {
$url = Yii::$app->urlManagerProducer->getHostInfo() . '/' . Yii::$app->urlManagerProducer->baseUrl . '/uploads/' . $model->photo;
$url = str_replace('//uploads','/uploads', $url) ;
echo '<img class="photo-product" src="' . $url . '" 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>
<div class="clr"></div> <div class="clr"></div>

<?php
if (!$model->isNewRecord) {
echo $form->field($model, 'apply_distributions')
->checkbox()
->hint('Sélectionnez cette option si vous souhaitez que ces modifications (actif / non actif, quantité max) soient répercutées dans les distributions à venir déjà initialisées.');
}
?>
</div> </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 . '/uploads/' . $model->photo;
$url = str_replace('//uploads','/uploads', $url) ;
echo '<img class="photo-product" src="' . $url . '" 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>


<?= $form->field($model, 'id_producer')->hiddenInput()->label('') ?> <?= $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>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? 'Ajouter' : 'Modifier', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
</div>


<?php ActiveForm::end(); ?> <?php ActiveForm::end(); ?>



+ 14
- 0
backend/views/product/update/_nav.php View File

<div id="nav-params">
<?= $this->render('_nav_item', [
'title' => 'Général',
'action' => 'update',
'currentAction' => $action,
'model' => $model,
]); ?>
<?= $this->render('_nav_item', [
'title' => 'Prix spécifiques',
'action' => 'prices-list',
'currentAction' => $action,
'model' => $model,
]); ?>
</div>

+ 4
- 0
backend/views/product/update/_nav_item.php View File

<a href="<?= Yii::$app->urlManager->createUrl(['product/'.$action, 'id' => $model->id]) ?>" class="btn <?php if($action == $currentAction): ?>btn-primary<?php else: ?>btn-default<?php endif; ?>">
<?= $title ?>
<span class="glyphicon glyphicon-triangle-bottom"></span>
</a>

+ 3
- 0
backend/views/product/update/prices/_base_price.php View File

<div class="alert alert-warning">
Prix de base : <strong><?= Price::format($model->getPrice()); ?> HT</strong> / <strong><?= Price::format($model->getPriceWithTax()); ?> TTC</strong><br />
</div>

+ 66
- 0
backend/views/product/update/prices/_form.php View File

<?php

use yii\helpers\Html;
use yii\bootstrap\ActiveForm;
use common\models\Product;
use yii\helpers\ArrayHelper;
use common\models\TaxRate;
use common\models\Producer;
use common\helpers\GlobalParam;
use common\models\User ;


?>

<div class="product-form">

<?=

$this->render('_base_price', [
'model' => $modelProduct,
]) ;

?>

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

<?= $form->field($model, 'id_user')->dropDownList(User::populateDropdownList()); ?>
<?= $form->field($model, 'id_point_sale')->dropDownList(PointSale::populateDropdownList()) ?>

<?php
$producer = GlobalParam::getCurrentProducer();
$taxRateValue = $producer->taxRate->value;
if($modelProduct->taxRate) {
$taxRateValue = $modelProduct->taxRate->value ;
}
?>
<?= $form->field($model, 'price', [
'template' => '
<div class="row">
<div class="col-xs-6">
<label for="product-price" class="control-label without-tax">Prix ('.Product::strUnit($modelProduct->unit, 'wording_unit').') HT</label>
<div class="input-group">
{input} <span class="input-group-addon"><span class="glyphicon glyphicon-euro"></span></span>
</div>
</div>
<div class="col-xs-6">
<label for="productprice-price-with-tax" class="control-label with-tax">Prix ('.Product::strUnit($modelProduct->unit, 'wording_unit').') TTC</label>
<div class="input-group">
<input type="text" id="productprice-price-with-tax" class="form-control" name="" value="" data-tax-rate-value="'.$taxRateValue.'">
<span class="input-group-addon"><span class="glyphicon glyphicon-euro"></span></span>
</div>
</div>
</div>',
]) ?>

<div class="form-group">
<?= Html::a('Annuler', ['prices-list', 'id' => $model->id_product], ['class' => 'btn btn-default']) ?>
<?= Html::submitButton($model->isNewRecord ? 'Ajouter' : 'Modifier', ['class' => 'btn btn-primary']) ?>
</div>

<?php ActiveForm::end(); ?>

</div>

backend/views/product/update.php → backend/views/product/update/prices/create.php View File

<?php <?php


/**
Copyright distrib (2018)
/**
Copyright distrib (2018)


contact@opendistrib.net contact@opendistrib.net


Ce logiciel est un programme informatique servant à aider les producteurs
à distribuer leur production en circuits courts.
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 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 respectant les principes de diffusion des logiciels libres. Vous pouvez
utiliser, modifier et/ou redistribuer ce programme sous les conditions 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
de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA
sur le site "http://www.cecill.info". sur le site "http://www.cecill.info".


En contrepartie de l'accessibilité au code source et des droits de copie, En contrepartie de l'accessibilité au code source et des droits de copie,


A cet égard l'attention de l'utilisateur est attirée sur les risques 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 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 à
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 manipuler et qui le réserve donc à des développeurs et des professionnels
avertis possédant des connaissances informatiques approfondies. Les avertis possédant des connaissances informatiques approfondies. Les
utilisateurs sont donc invités à charger et tester l'adéquation du utilisateurs sont donc invités à charger et tester l'adéquation du
logiciel à leurs besoins dans des conditions permettant d'assurer la 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é.
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
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 pris connaissance de la licence CeCILL, et que vous en avez accepté les
termes. termes.
*/
*/


use yii\helpers\Html; use yii\helpers\Html;



$this->setTitle('Modifier un produit') ;
$this->setTitle('Ajouter un prix ('.Html::encode($model->product->name).')') ;
$this->addBreadcrumb(['label' => 'Produits', 'url' => ['index']]) ; $this->addBreadcrumb(['label' => 'Produits', 'url' => ['index']]) ;
$this->addBreadcrumb(['label' => $model->name, 'url' => ['update', 'id' => $model->id]]) ;
$this->addBreadcrumb('Modifier') ;
$this->addBreadcrumb(['label' => $model->product->name, 'url' => ['update', 'id' => $model->product->id]]);
$this->addBreadcrumb(['label' => 'Prix', 'url' => ['prices-list', 'id' => $model->product->id]]) ;
$this->addBreadcrumb('Ajouter un prix') ;

?>


<?=
$this->render('../_nav', [
'model' => $modelProduct,
'action' => 'prices-list',
]) ;
?> ?>


<div class="product-update">
<?= $this->render('_form', [
'model' => $model,
]) ?>
<div class="product-prices-create">
<?= $this->render('_form', [
'model' => $model,
'modelProduct' => $modelProduct
]) ?>
</div> </div>

+ 227
- 0
backend/views/product/update/prices/list.php View File

<?php

use common\helpers\Price ;

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

$this->setTitle('Liste des prix ('.Html::encode($model->name).')');
$this->addBreadcrumb(['label' => 'Produits', 'url' => ['index']]);
$this->addBreadcrumb(['label' => $model->name, 'url' => ['update', 'id' => $model->id]]);
$this->addBreadcrumb('Modifier');
//$this->addButton(['label' => 'Nouveau prix <span class="glyphicon glyphicon-plus"></span>', 'url' => ['product/prices-create', 'idProduct' => $model->id ], 'class' => 'btn btn-primary']);

?>

<?=
$this->render('../_nav', [
'model' => $model,
'action' => $action,
]) ;
?>

<div class="col-md-8">

<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">
Prix spécifiques à ce produit
<a href="<?= Yii::$app->urlManager->createUrl(['product/prices-create', 'idProduct' => $model->id ]) ?>" class="btn btn-default btn-xs">
Nouveau prix
<span class="glyphicon glyphicon-plus"></span>
</a>
</h3>
</div>
<div class="panel-body">
<?php

echo GridView::widget([
//'filterModel' => $searchModel,
'dataProvider' => $dataProvider,
'columns' => [
[
'attribute' => 'id_point_sale',
'format' => 'raw',
'value' => function ($model) {
if($model->pointSale) {
return $model->pointSale->name ;
}
return '<span class="label label-success">Tous</span>' ;
}
],
[
'attribute' => 'id_user',
'format' => 'raw',
'value' => function ($model) {
if($model->user) {
return $model->user->getUsername() ;
}
return '<span class="label label-success">Tous</span>' ;
}
],
[
'attribute' => 'price',
'value' => function ($productPrice) {
return Price::numberTwoDecimals($productPrice->price).' €' ;
}
],
[
'attribute' => 'price',
'header' => 'Prix (TTC)',
'value' => function ($productPrice) use ($model) {
return Price::numberTwoDecimals(Price::getPriceWithTax($productPrice->price, $model->taxRate->value)).' €' ;
}
],
[
'class' => 'yii\grid\ActionColumn',
'template' => '{update} {delete}',
'headerOptions' => ['class' => 'column-actions'],
'contentOptions' => ['class' => 'column-actions'],
'buttons' => [
'update' => function ($url, $model) {
return Html::a('<span class="glyphicon glyphicon-pencil"></span>', ['product/prices-update', 'id' => $model->id], [
'title' => Yii::t('app', 'Modifier'), 'class' => 'btn btn-default'
]);
},
'delete' => function ($url, $model) {
return Html::a('<span class="glyphicon glyphicon-trash"></span>', ['product/prices-delete', 'id' => $model->id], [
'title' => Yii::t('app', 'Supprimer'), 'class' => 'btn btn-default'
]);
}
],
],
],
]);

?>
</div>
</div>

<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Pourcentage global / Utilisateurs</h3>
</div>
<div class="panel-body">
<table class="table table-bordered">
<thead>
<tr>
<th>Utilisateur</th>
<th>Pourcentage</th>
<th>Prix (HT)</th>
<th>Prix (TTC)</th>
</tr>
</thead>
<tbody>
<?php if($userProducerWithProductPercent && count($userProducerWithProductPercent) > 0): ?>
<?php foreach($userProducerWithProductPercent as $userProducer): ?>
<?php if($userProducer->user): ?>
<tr>
<td><?= $userProducer->user->getUsername() ?></td>
<td><?= $userProducer->product_price_percent ?> %</td>
<td><?= Price::format($model->getPrice(['user_producer' => $userProducer])) ?></td>
<td><?= Price::format($model->getPriceWithTax(['user_producer' => $userProducer])) ?></td>
</tr>
<?php endif; ?>
<?php endforeach; ?>
<?php else: ?>
<tr><td colspan="4">Aucun résultat</td></tr>
<?php endif; ?>
</tbody>
</table>
</div>
</div>

<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Pourcentage global / Points de vente</h3>
</div>
<div class="panel-body">
<table class="table table-bordered">
<thead>
<tr>
<th>Point de vente</th>
<th>Pourcentage</th>
<th>Prix (HT)</th>
<th>Prix (TTC)</th>
</tr>
</thead>
<tbody>
<?php if($pointSaleWithProductPercent && count($pointSaleWithProductPercent) > 0): ?>
<?php foreach($pointSaleWithProductPercent as $pointSale): ?>
<tr>
<td><?= Html::encode($pointSale->name) ?></td>
<td><?= $pointSale->product_price_percent ?> %</td>
<td><?= Price::format($model->getPrice(['point_sale' => $pointSale])) ?></td>
<td><?= Price::format($model->getPriceWithTax(['point_sale' => $pointSale])) ?></td>
</tr>
<?php endforeach; ?>
<?php else: ?>
<tr><td colspan="4">Aucun résultat</td></tr>
<?php endif; ?>
</tbody>
</table>
</div>
</div>

<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Prix de base</h3>
</div>
<div class="panel-body">
<p>Prix de base : <strong><?= Price::format($model->getPrice()); ?> HT</strong> / <strong><?= Price::format($model->getPriceWithTax()); ?> TTC</strong><br /></p>
</div>
</div>
</div>

<div class="col-md-4">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Priorités de résolution</h3>
</div>
<div class="panel-body">
<p>Le prix d'un produit se déduit dans un ordre précis de résolution, le voici : </p>
<ul>
<li>Les prix spécifiques définis au niveau du produit</li>
<li>Les pourcentages globaux définis au niveau des utilisateurs et points de vente</li>
<li>Le prix de base défini au niveau du produit</li>
</ul>
<p>À chaque étape de résolution, on vérifie si le contexte courant (utilisateur / point de vente) correspond à un prix.
Si c'est le cas, on l'utilise, sinon on passe à l'étape suivante jusqu'à arriver au prix de base
défini dans "Général".
</p>
</div>
</div>
</div>

+ 61
- 0
backend/views/product/update/prices/update.php View File

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

use yii\helpers\Html;

$this->setTitle('Modifier un prix ('.Html::encode($model->product->name).')') ;
$this->addBreadcrumb(['label' => 'Produits', 'url' => ['index']]) ;
$this->addBreadcrumb(['label' => $model->product->name, 'url' => ['update', 'id' => $model->product->id]]);
$this->addBreadcrumb(['label' => 'Prix', 'url' => ['prices-list', 'id' => $model->product->id]]) ;
$this->addBreadcrumb('Modifier un prix') ;

?>

<?=
$this->render('../_nav', [
'model' => $modelProduct,
'action' => 'prices-list',
]) ;
?>

<div class="product-prices-update">
<?= $this->render('_form', [
'model' => $model,
'modelProduct' => $modelProduct
]) ?>
</div>

+ 62
- 0
backend/views/product/update/update.php View File

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



/* @var $this yii\web\View */
/* @var $model app\models\Produit */
/* @var $form yii\widgets\ActiveForm */

$this->setTitle('Modifier un produit ('.Html::encode($model->name).')');
$this->addBreadcrumb(['label' => 'Produits', 'url' => ['index']]);
$this->addBreadcrumb(['label' => $model->name, 'url' => ['update', 'id' => $model->id]]);
$this->addBreadcrumb('Modifier');

?>

<?= $this->render('_nav', [
'model' => $model,
'action' => $action,
])
?>

<div class="product-update">
<?= $this->render('../_form', [
'model' => $model,
]) ?>
</div>

+ 4
- 0
backend/views/user/_form.php View File



use yii\helpers\Html; use yii\helpers\Html;
use yii\widgets\ActiveForm; use yii\widgets\ActiveForm;
use common\models\ProductPrice ;


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


]); ]);
?> ?>


<?= $form->field($model, 'product_price_percent')
->dropDownList(ProductPrice::percentValues(), [])->hint('Pourcentage appliqué aux prix de chaque produit pour cet utilisateur.'); ?>

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

+ 203
- 198
backend/web/css/screen.css
File diff suppressed because it is too large
View File


+ 43
- 8
backend/web/js/backend.js View File

opendistrib_tooltip() ; opendistrib_tooltip() ;
opendistrib_ordre_produits() ; opendistrib_ordre_produits() ;
opendistrib_products() ; opendistrib_products() ;
opendistrib_product_prices() ;
opendistrib_confirm_delete() ; opendistrib_confirm_delete() ;
}) ; }) ;


if(typeof taxRateSelected == 'undefined') { if(typeof taxRateSelected == 'undefined') {
taxRateSelected = 0 ; taxRateSelected = 0 ;
} }
if($('#product-price').val()) {
$('#product-price-with-tax').val(getPriceWithTax($('#product-price').val(), taxRateSelected));
//formattage des prix
$('#product-price').val(parseFloat($('#product-price').val()).toFixed(3));

var price = $('#product-price').val() ;
if(price) {
$('#product-price-with-tax').val(getPriceWithTax(price, taxRateSelected));
// formattage
$('#product-price').val(parseFloat(price).toFixed(3));
} }
} }
function opendistrib_products_event_price(){ function opendistrib_products_event_price(){
taxRateSelected = $('#product-id_tax_rate').find('option:selected').data('tax-rate-value'); taxRateSelected = $('#product-id_tax_rate').find('option:selected').data('tax-rate-value');
$('#product-price').val(getPrice($('#product-price-with-tax').val(), taxRateSelected));

//formattage des prix
$('#product-price-with-tax').val(parseFloat($('#product-price-with-tax').val()).toFixed(2));
var priceWithTax = $('#product-price-with-tax').val() ;
if(priceWithTax) {
$('#product-price').val(getPrice(priceWithTax, taxRateSelected));
// formattage
$('#product-price-with-tax').val(parseFloat(priceWithTax).toFixed(2));
}
} }




if(unit == 'piece') { if(unit == 'piece') {
$('.field-product-step').hide() ; $('.field-product-step').hide() ;
$('.field-product-weight label').html('Poids (g)') ; $('.field-product-weight label').html('Poids (g)') ;
$('.field-product-weight').show() ;
} }
else { else {
$('.field-product-step').show() ; $('.field-product-step').show() ;
$('.field-product-weight label').html('Poids ('+$('#product-unit').val()+')') ; $('.field-product-weight label').html('Poids ('+$('#product-unit').val()+')') ;
$('.field-product-weight').hide() ;
} }
var label_price_ttc = $('.field-product-price .control-label.with-tax') ; var label_price_ttc = $('.field-product-price .control-label.with-tax') ;
} }


function opendistrib_product_prices() {
if($('.product-prices-create').size() || $('.product-prices-update').size()) {
opendistrib_product_prices_event_price_with_tax() ;
$('#productprice-price').change(opendistrib_product_prices_event_price_with_tax);
$('#productprice-price-with-tax').change(opendistrib_product_prices_event_price);
}
}

function opendistrib_product_prices_event_price_with_tax() {
var taxRateValue = $('#productprice-price-with-tax').data('tax-rate-value');
var price = $('#productprice-price').val() ;
if(price) {
$('#productprice-price-with-tax').val(getPriceWithTax(price, taxRateValue));
// formattage
$('#productprice-price').val(parseFloat(price).toFixed(3));
}
}

function opendistrib_product_prices_event_price() {
var taxRateValue = $('#productprice-price-with-tax').data('tax-rate-value');
var priceWithTax = $('#productprice-price-with-tax').val() ;
if(priceWithTax) {
$('#productprice-price').val(getPrice(priceWithTax, taxRateValue));
// formattage
$('#productprice-price-with-tax').val(parseFloat(priceWithTax).toFixed(2));
}
}

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

+ 51
- 0
backend/web/js/vuejs/distribution-index.js View File

openModalFormOrderCreate: function() { openModalFormOrderCreate: function() {
this.showModalFormOrderCreate = true ; this.showModalFormOrderCreate = true ;
this.initModalFormOrder() ; this.initModalFormOrder() ;
this.updateProductOrderPrices() ;
}, },
initModalFormOrder: function() { initModalFormOrder: function() {
setTimeout(function() { setTimeout(function() {
appAlerts.alertResponse(response) ; appAlerts.alertResponse(response) ;
app.init(app.idActivePointSale) ; app.init(app.idActivePointSale) ;
}) ; }) ;
},

updateProductOrderPrices: function() {
var app = this ;
var order = null ;

if(app.showModalFormOrderCreate) {
order = app.orderCreate ;
}

if(app.showModalFormOrderUpdate && app.idOrderUpdate) {
for (keyOrderUpdate in app.ordersUpdate) {
if (app.ordersUpdate[keyOrderUpdate].id == app.idOrderUpdate) {
order = app.ordersUpdate[keyOrderUpdate] ;
}
}
}

if(order) {
axios.get(UrlManager.getBaseUrlAbsolute() + "distribution/ajax-update-product-order", {
params: {
idUser: order.id_user,
idPointSale: order.id_point_sale
}
})
.then(function (response) {
if (response.data) {
for (idProduct in response.data) {
if (app.showModalFormOrderCreate) {
Vue.set(app.orderCreate.productOrder[idProduct], 'price', response.data[idProduct].price);
}

if (app.showModalFormOrderUpdate && app.idOrderUpdate) {
for (keyOrderUpdate in app.ordersUpdate) {
if (order.id == app.idOrderUpdate) {
Vue.set(app.ordersUpdate[keyOrderUpdate].productOrder[idProduct], 'price', response.data[idProduct].price);
}
}
}
}
}
});
}
} }
}, },
}); });
}}) }})
.then(function(response) { .then(function(response) {
app.order.id_point_sale = response.data.id_favorite_point_sale ; app.order.id_point_sale = response.data.id_favorite_point_sale ;
app.updateProductOrderPrices() ;
}) ; }) ;
},
pointSaleChange: function(event) {
this.updateProductOrderPrices() ;
},
updateProductOrderPrices: function() {
this.$emit('updateproductorderprices') ;
} }
} }
}) ; }) ;

+ 0
- 8
backend/web/sass/producer/_update.scss View File



.producer-update { .producer-update {
#nav-params {
margin-bottom: 30px ;
button {
margin-right: 10px ;
}
}
} }

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

} }
} }


#nav-params {
margin-bottom: 30px ;

button {
margin-right: 10px ;
}
}

.panel {
.panel-heading {
.panel-title {
.btn {
float: right ;
}
}
}
}

/* modals */ /* modals */


.modal-mask { .modal-mask {

+ 16
- 2
common/models/PointSale.php View File

['point_production', 'default', 'value' => 0], ['point_production', 'default', 'value' => 0],
[['id_producer', 'id_user'], 'integer'], [['id_producer', 'id_user'], 'integer'],
['id_producer', 'required'], ['id_producer', 'required'],
[['users', 'users_comment', 'code'], 'safe']
[['users', 'users_comment', 'code'], 'safe'],
[['product_price_percent'], 'double'],
]; ];
} }


'code' => 'Code', 'code' => 'Code',
'credit_functioning' => 'Utilisation du Crédit par l\'utilisateur', 'credit_functioning' => 'Utilisation du Crédit par l\'utilisateur',
'default' => 'Point de vente par défaut', 'default' => 'Point de vente par défaut',
'id_user' => 'Contact'
'id_user' => 'Contact',
'product_price_percent' => 'Prix produits : pourcentage'
]; ];
} }


} }
} }
} }

public static function populateDropdownList()
{
$pointSalesArrayDropdown = ['' => '--'] ;
$pointSalesArray = PointSale::find()->where('id_producer = ' . GlobalParam::getCurrentProducerId())->all() ;

foreach($pointSalesArray as $pointSale) {
$pointSalesArrayDropdown[$pointSale['id']] = $pointSale['name'] ;
}

return $pointSalesArrayDropdown ;
}
} }

+ 64
- 6
common/models/Product.php View File

if($producer) { if($producer) {
$this->populateRelation('taxRate', $producer->taxRate); $this->populateRelation('taxRate', $producer->taxRate);
} }
//$this->populateRelation('taxRate', GlobalParam::getCurrentProducer()->taxRate);
} }


$this->wording_unit = Product::strUnit($this->unit) ; $this->wording_unit = Product::strUnit($this->unit) ;
$this->price_with_tax = $this->getpriceWithTax() ;
$this->price_with_tax = $this->getPriceWithTax() ;


parent::afterFind(); parent::afterFind();
} }


public function getTaxRate() public function getTaxRate()
{ {

return $this->hasOne(TaxRate::className(), ['id' => 'id_tax_rate']); return $this->hasOne(TaxRate::className(), ['id' => 'id_tax_rate']);
} }


public function getProductPrice()
{
return $this->hasMany(ProductPrice::className(), ['id_product' => 'id']);
}

/** /**
* Retourne les options de base nécessaires à la fonction de recherche. * Retourne les options de base nécessaires à la fonction de recherche.
* *
return $strUnit; return $strUnit;
} }


public function getPrice()
public function getPrice($params = [])
{ {
$specificPrices = $this->productPrice ;

$user = isset($params['user']) ? $params['user'] : false ;
$userProducer = isset($params['user_producer']) ? $params['user_producer'] : false ;
$pointSale = isset($params['point_sale']) ? $params['point_sale'] : false ;

if($specificPrices && ($user || $pointSale)) {

$specificPricesArray = [
'user' => false,
'pointsale' => false,
'user_pointsale' => false,
] ;

foreach($specificPrices as $specificPrice) {
if($user
&& $specificPrice->id_user && !$specificPrice->id_point_sale
&& $specificPrice->id_user == $user->id) {

$specificPricesArray['user'] = $specificPrice->price ;
}
if($pointSale
&& $specificPrice->id_point_sale && !$specificPrice->id_user
&& $specificPrice->id_point_sale == $pointSale->id) {

$specificPricesArray['pointsale'] = $specificPrice->price ;
}

if($pointSale && $user
&& $specificPrice->id_point_sale && $specificPrice->id_user
&& $specificPrice->id_point_sale == $pointSale->id && $specificPrice->id_user == $user->id) {

$specificPricesArray['user_pointsale'] = $specificPrice->price ;
}
}

if($specificPricesArray['user_pointsale']) {
return $specificPricesArray['user_pointsale'] ;
}
elseif($specificPricesArray['user']) {
return $specificPricesArray['user'] ;
}
elseif($specificPricesArray['pointsale']) {
return $specificPricesArray['pointsale'] ;
}
}

if($userProducer && $userProducer->product_price_percent) {
return $this->price * (1 + $userProducer->product_price_percent / 100) ;
}

if($pointSale && $pointSale->product_price_percent) {
return $this->price * (1 + $pointSale->product_price_percent / 100) ;
}

return $this->price ; return $this->price ;
} }


/** /**
* Retourne le prix du produit avec taxe * Retourne le prix du produit avec taxe
*/ */
public function getPriceWithTax()
public function getPriceWithTax($params = [])
{ {
$taxRateValue = $this->taxRate ? $this->taxRate->value : 0 ; $taxRateValue = $this->taxRate ? $this->taxRate->value : 0 ;
return Price::getPriceWithTax($this->price, $taxRateValue);
return Price::getPriceWithTax($this->getPrice($params), $taxRateValue);
} }


public function getTheTaxRate() public function getTheTaxRate()

+ 153
- 0
common/models/ProductPrice.php View File

<?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 common\models;

use common\helpers\GlobalParam;
use Yii;
use yii\helpers\Html;
use common\models\UserPointSale;
use common\models\PointSaleDistribution;
use common\components\ActiveRecordCommon;

/**
* This is the model class for table "product_price".
*
* @property integer $id
*/
class ProductPrice extends ActiveRecordCommon
{

/**
* @inheritdoc
*/
public static function tableName()
{
return 'product_price';
}

/**
* @inheritdoc
*/
public function rules()
{
return [
['id_user', 'required', 'when' => function($model) {
return !$model->id_point_sale ;
}, 'message' => 'Vous devez renseigner un utilisateur et/ou un point de vente'],
['id_point_sale', 'required', 'when' => function($model) {
return !$model->id_user ;
}, 'message' => 'Vous devez renseigner un utilisateur et/ou un point de vente'],
[['id_product', 'price'], 'required'],
[['id_product', 'id_user', 'id_point_sale', 'percent'], 'integer'],
[['price'], 'double'],
];
}

/**
* @inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'id_product' => 'Produit',
'id_user' => 'Utilisateur',
'id_point_sale' => 'Point de vente',
'price' => 'Prix (HT)',
'percent' => 'Pourcentage',
];
}

/*
* Relations
*/

public function getProduct()
{
return $this->hasOne(
Product::className(),
['id' => 'id_product']
);
}

public function getPointSale()
{
return $this->hasOne(
PointSale::className(),
['id' => 'id_point_sale']
);
}

public function getUser()
{
return $this->hasOne(
User::className(),
['id' => 'id_user']
) ;
}

/**
* Retourne les options de base nécessaires à la fonction de recherche.
*
* @return array
*/
public static function defaultOptionsSearch()
{
return [
'with' => ['user', 'pointSale'],
'join_with' => ['product'],
'orderby' => '',
'attribute_id_producer' => 'product.id_producer'
];
}

public static function percentValues()
{
$percentValues = [
'' => 'Aucun'
] ;

for($i = -50 ; $i < 51 ; $i = $i + 5) {
$percentValues[$i] = $i.' %' ;
}

return $percentValues ;
}

}

+ 94
- 0
common/models/ProductPriceSearch.php View File

<?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 common\models;

use common\helpers\GlobalParam;
use Yii;
use yii\helpers\Html;
use common\models\UserPointSale;
use common\models\PointSaleDistribution;
use common\components\ActiveRecordCommon;

/**
* This is the model class for table "product_price".
*
* @property integer $id
*/
class ProductPriceSearch extends ProductPrice
{

public function rules()
{
return [
[['id_user', 'id_point_sale'], 'string'],
[['price'], 'double'],
];
}

public function search($params)
{
$optionsSearch = self::defaultOptionsSearch() ;

$query = ProductPrice::find()
->with($optionsSearch['with'])
->innerJoinWith($optionsSearch['join_with'], true)
->where(['product.id_producer' => GlobalParam::getCurrentProducerId()])
->orderBy('product_price.price ASC')
;

$dataProvider = new ActiveDataProvider([
'query' => $query,
'sort' => false,
'pagination' => [
'pageSize' => 1000,
],
]);

$this->load($params);
if (!$this->validate()) {
return $dataProvider;
}

//$query->andFilterWhere(['like', 'user.name', $this->id_user]) ;
//$query->andFilterWhere(['like', 'point_sale.name', $this->id_point_sale]) ;

return $dataProvider;
}

}

+ 4
- 1
common/models/Subscription.php View File

$productOrder->id_order = $order->id; $productOrder->id_order = $order->id;
$productOrder->id_product = $productSubscription->product->id; $productOrder->id_product = $productSubscription->product->id;
$productOrder->quantity = $productSubscription->quantity; $productOrder->quantity = $productSubscription->quantity;
$productOrder->price = $productSubscription->product->price;
$productOrder->price = $productSubscription->product->getPrice([
'id_user' => $this->id_user,
'id_point_sale' => $this->id_point_sale
]);
$productOrder->unit = $productSubscription->product->unit; $productOrder->unit = $productSubscription->product->unit;
$productOrder->step = $productSubscription->product->step; $productOrder->step = $productSubscription->product->step;
$productOrder->id_tax_rate = $productSubscription->product->taxRate->id; $productOrder->id_tax_rate = $productSubscription->product->taxRate->id;

+ 39
- 3
common/models/User.php View File

var $password_new_confirm; var $password_new_confirm;
var $points_sale = []; var $points_sale = [];
var $one_name ; var $one_name ;
var $product_price_percent ;


/** /**
* @inheritdoc * @inheritdoc
['password_old', 'verifyPasswordOld'], ['password_old', 'verifyPasswordOld'],
['password_new', 'verifyPasswordNew'], ['password_new', 'verifyPasswordNew'],
['password_new_confirm', 'verifyPasswordNewConfirm'], ['password_new_confirm', 'verifyPasswordNewConfirm'],
[['date_last_connection', 'password_old', 'password_new', 'password_new_confirm', 'password_hash', 'points_sale'], 'safe'],
[['date_last_connection', 'password_old', 'password_new', 'password_new_confirm', 'password_hash', 'points_sale', 'product_price_percent'], 'safe'],
]; ];
} }


'points_sale' => 'Points de vente', 'points_sale' => 'Points de vente',
'type' => 'Type', 'type' => 'Type',
'name_legal_person' => 'Libellé', 'name_legal_person' => 'Libellé',
'is_main_contact' => 'Contact principal'
'is_main_contact' => 'Contact principal',
'product_price_percent' => 'Prix produits : pourcentage'
]; ];
} }


return $address; return $address;
} }


public function getUsername()
public function getUsername($withType = false)
{ {
$username = '' ; $username = '' ;
if(isset($this->name_legal_person) && strlen($this->name_legal_person)) { if(isset($this->name_legal_person) && strlen($this->name_legal_person)) {
$username = $this->name_legal_person ; $username = $this->name_legal_person ;

if($withType) {
$username = 'Personne morale / '.$username ;
}
} }
else { else {
$username = $this->lastname.' '.$this->name ; $username = $this->lastname.' '.$this->name ;
return $username ; return $username ;
} }


public static function getUsernameFromArray($modelArray, $withType = false)
{
$username = '' ;
if(isset($modelArray['name_legal_person']) && strlen($modelArray['name_legal_person'])) {
$username = $modelArray['name_legal_person'] ;

if($withType) {
$username = 'Personne morale / '.$username ;
}
}
else {
$username = $modelArray['lastname'].' '.$modelArray['name'] ;
}

return $username ;
}

public static function populateDropdownList()
{
$usersArray = User::findBy()->all() ;
$usersArrayDropdown = ['' => '--'] ;

foreach($usersArray as $user) {
$usersArrayDropdown[$user['user_id']] = User::getUsernameFromArray($user, true) ;
}

return $usersArrayDropdown ;;
}


/** /**
* Retourne l'ID de l'utilisateur courant connecté. * Retourne l'ID de l'utilisateur courant connecté.
* *

+ 95
- 88
common/models/UserProducer.php View File

<?php <?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.
*/
/**
* 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 common\models; namespace common\models;


use Yii; use Yii;
use common\components\ActiveRecordCommon ;
use common\components\ActiveRecordCommon;


/** /**
* This is the model class for table "user_etablissement". * This is the model class for table "user_etablissement".
* @property boolean $actif * @property boolean $actif
* @property boolean $favoris * @property boolean $favoris
*/ */
class UserProducer extends ActiveRecordCommon
class UserProducer extends ActiveRecordCommon
{ {


/**
* @inheritdoc
*/
public static function tableName()
{
return 'user_producer';
}
/**
* @inheritdoc
*/
public static function tableName()
{
return 'user_producer';
}

/**
* @inheritdoc
*/
public function rules()
{
return [
[['id_user', 'id_producer'], 'required'],
[['id_user', 'id_producer', 'product_price_percent'], 'integer'],
[['active', 'bookmark', 'credit_active'], 'boolean'],
[['credit', 'product_price_percent'], 'double'],
];
}

/**
* @inheritdoc
*/
public function attributeLabels()
{
return [
'id_user' => 'Utilisateur',
'id_producer' => 'Producteur',
'active' => 'Actif',
'bookmark' => 'Favoris',
'credit_active' => 'Crédit',
'product_price_percent' => 'Prix produits : pourcentage'
];
}

public function getProducer()
{
return $this->hasOne(Producer::className(), ['id' => 'id_producer']);
}


/**
* @inheritdoc
*/
public function rules()
{
return [
[['id_user', 'id_producer'], 'required'],
[['id_user', 'id_producer'], 'integer'],
[['active','bookmark','credit_active'], 'boolean'],
[['credit'], 'double'],
];
}
public function getUser()
{
return $this->hasOne(User::className(), ['id' => 'id_user']);
}


/**
* @inheritdoc
*/
public function attributeLabels()
{
return [
'id_user' => 'Utilisateur',
'id_producer' => 'Producteur',
'active' => 'Actif',
'bookmark' => 'Favoris',
'credit_active' => 'Crédit'
];
}
public function getProducer()
{
return $this->hasOne(Producer::className(), ['id' => 'id_producer']);
}
/**
* Retourne les options de base nécessaires à la fonction de recherche.
*
* @return array
*/
public static function defaultOptionsSearch() {
return [
'with' => [],
'join_with' => [],
'orderby' => '',
'attribute_id_producer' => 'user_producer.id_producer'
] ;
}
/**
* Retourne les options de base nécessaires à la fonction de recherche.
*
* @return array
*/
public static function defaultOptionsSearch()
{
return [
'with' => [],
'join_with' => [],
'orderby' => '',
'attribute_id_producer' => 'user_producer.id_producer'
];
}


} }

+ 30
- 0
console/migrations/m201207_160043_specific_prices.php View File

<?php

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

class m201207_160043_specific_prices extends Migration
{
public function safeUp()
{
$this->createTable('product_price', [
'id' => 'pk',
'id_product' => Schema::TYPE_INTEGER . ' NOT NULL',
'id_user' => Schema::TYPE_INTEGER,
'id_point_sale' => Schema::TYPE_INTEGER,
'price' => Schema::TYPE_FLOAT,
]);

$this->addColumn('user_producer', 'product_price_percent', Schema::TYPE_INTEGER) ;
$this->addColumn('point_sale', 'product_price_percent', Schema::TYPE_INTEGER) ;
}

public function safeDown()
{
$this->dropTable('product_price') ;
$this->dropColumn('user_producer', 'product_price_percent') ;
$this->dropColumn('point_sale', 'product_price_percent') ;

return false;
}
}

+ 34
- 0
console/migrations/m201207_164410_specific_prices_percent.php View File

<?php

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

class m201207_164410_specific_prices_percent extends Migration
{
public function safeUp()
{
$this->addColumn('product_price', 'percent', Schema::TYPE_INTEGER) ;
}

public function safeDown()
{
$this->dropColumn('product_price', 'percent') ;

return false;
}

/*
// Use up()/down() to run migration code without a transaction.
public function up()
{

}

public function down()
{
echo "m201207_164410_specific_prices_percent cannot be reverted.\n";

return false;
}
*/
}

+ 10
- 14
producer/controllers/OrderController.php View File

return 0; return 0;
} }


public function actionAjaxInfos($date = '')
public function actionAjaxInfos($date = '', $pointSaleId = 0)
{ {
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;


$format = 'Y-m-d'; $format = 'Y-m-d';
$dateObject = DateTime::createFromFormat($format, $date); $dateObject = DateTime::createFromFormat($format, $date);


// PointSale current
$pointSaleCurrent = PointSale::findOne($pointSaleId) ;

// Producteur // Producteur
$producer = Producer::searchOne([ $producer = Producer::searchOne([
'id' => $this->getProducer()->id 'id' => $this->getProducer()->id
]); ]);


// Produits // Produits
/*if (Producer::getConfig('option_allow_user_gift')) {
$productsArray = Product::find()
->orWhere(['id_producer' => $this->getProducer()->id,])
//->orWhere(['id_producer' => 0,]) // produit "Don";
;
} else {
$productsArray = Product::find()
->where(['id_producer' => $this->getProducer()->id,]);
}*/

$productsArray = Product::find() $productsArray = Product::find()
->where([ ->where([
'id_producer' => $this->getProducer()->id, 'id_producer' => $this->getProducer()->id,


$productsArray = $productsArray->joinWith(['productDistribution' => function ($query) use ($distribution) { $productsArray = $productsArray->joinWith(['productDistribution' => function ($query) use ($distribution) {
$query->andOnCondition('product_distribution.id_distribution = ' . $distribution->id); $query->andOnCondition('product_distribution.id_distribution = ' . $distribution->id);
}])
}, 'productPrice'])
->orderBy('product_distribution.active DESC, order ASC') ->orderBy('product_distribution.active DESC, order ASC')
->all(); ->all();


$product = array_merge( $product = array_merge(
$product->getAttributes(), $product->getAttributes(),
[ [
'price_with_tax' => $product->getPriceWithTax(),
'price_with_tax' => $product->getPriceWithTax([
'user' => User::getCurrent(),
'user_producer' => $userProducer,
'point_sale' => $pointSaleCurrent
]),
'productDistribution' => $product['productDistribution'] 'productDistribution' => $product['productDistribution']
] ]
); );



$coefficient_unit = Product::$unitsArray[$product['unit']]['coefficient']; $coefficient_unit = Product::$unitsArray[$product['unit']]['coefficient'];


if (is_null($product['photo'])) { if (is_null($product['photo'])) {

+ 18
- 1
producer/controllers/SubscriptionController.php View File

\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
$params = []; $params = [];


$user = User::getCurrent() ;
$userProducer = UserProducer::searchOne([
'id_user' => User::getCurrentId()
]) ;
$pointSale = false ;


if ($idSubscription > 0) { if ($idSubscription > 0) {
$arrayProductsSubscription = ProductSubscription::searchAll([ $arrayProductsSubscription = ProductSubscription::searchAll([
'id_subscription' => $idSubscription 'id_subscription' => $idSubscription
]); ]);

$subscription = Subscription::findOne($idSubscription) ;

if($subscription) {
if($subscription->id_point_sale) {
$pointSale = PointSale::findOne($subscription->id_point_sale) ;
}
}
} }


// Produits // Produits
'coefficient_unit' => $coefficientUnit, 'coefficient_unit' => $coefficientUnit,
'wording_unit' => Product::strUnit($product->unit, 'wording_unit', true), 'wording_unit' => Product::strUnit($product->unit, 'wording_unit', true),
'wording_short' => Product::strUnit($product->unit, 'wording_short'), 'wording_short' => Product::strUnit($product->unit, 'wording_short'),
'price_with_tax' => $product->getPriceWithTax(),
'price_with_tax' => $product->getPriceWithTax([
'user' => $user,
'user_producer' => $userProducer,
'point_sale' => $pointSale
]),
] ]
); );
} }

+ 4
- 1
producer/web/js/vuejs/order-order.js View File

init: function() { init: function() {
var app = this ; var app = this ;
this.loading = true ; this.loading = true ;
axios.get("ajax-infos",{params: {date : this.getDate()}})
axios.get("ajax-infos",{params: {
date : this.getDate(),
pointSaleId: this.pointSaleActive ? this.pointSaleActive.id : 0
}})
.then(function(response) { .then(function(response) {
app.producer = response.data.producer ; app.producer = response.data.producer ;
app.user = response.data.user ; app.user = response.data.user ;

Loading…
Cancel
Save