Ver código fonte

Merge branch 'feature/producer/subscription' into dev

dev
Guillaume Bourgeois 5 anos atrás
pai
commit
dc6be2e762
26 arquivos alterados com 1613 adições e 107 exclusões
  1. +13
    -0
      backend/views/producer/update.php
  2. +1
    -6
      common/components/ActiveRecordCommon.php
  3. +1
    -1
      common/models/Order.php
  4. +0
    -1
      common/models/PointSale.php
  5. +12
    -7
      common/models/Producer.php
  6. +57
    -46
      common/models/Subscription.php
  7. +1
    -0
      common/models/SubscriptionForm.php
  8. +7
    -1
      common/models/SubscriptionSearch.php
  9. +15
    -0
      console/migrations/m190121_101211_ajout_config_option_gestion_abonnement_par_l_utilisateur.php
  10. +62
    -0
      producer/assets/VuejsSubscriptionFormAsset.php
  11. +13
    -8
      producer/controllers/OrderController.php
  12. +339
    -0
      producer/controllers/SubscriptionController.php
  13. +4
    -4
      producer/views/credit/history.php
  14. +22
    -4
      producer/views/layouts/main.php
  15. +1
    -1
      producer/views/order/history.php
  16. +249
    -0
      producer/views/subscription/_form.php
  17. +53
    -0
      producer/views/subscription/form.php
  18. +202
    -0
      producer/views/subscription/index.php
  19. +144
    -21
      producer/web/css/screen.css
  20. +5
    -0
      producer/web/js/lechatdesnoisettes.js
  21. +4
    -2
      producer/web/js/vuejs/order-order.js
  22. +287
    -0
      producer/web/js/vuejs/subscription-form.js
  23. +19
    -4
      producer/web/sass/_layout.scss
  24. +1
    -1
      producer/web/sass/order/_form.scss
  25. +1
    -0
      producer/web/sass/screen.scss
  26. +100
    -0
      producer/web/sass/subscription/_form.scss

+ 13
- 0
backend/views/producer/update.php Ver arquivo

@@ -131,6 +131,19 @@ $this->addBreadcrumb($this->getTitle()) ;
</div>

<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Abonnements</h3>
</div>
<div class="panel-body">
<?= $form->field($model, 'user_manage_subscription')
->dropDownList([
0 => 'Non',
1 => 'Oui',
], []) ; ?>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Crédit / paiement en ligne</h3>

+ 1
- 6
common/components/ActiveRecordCommon.php Ver arquivo

@@ -73,12 +73,7 @@ class ActiveRecordCommon extends \yii\db\ActiveRecord
if (isset($options['attribute_id_producer']) && strlen($options['attribute_id_producer'])
&& !isset($params[$options['attribute_id_producer']]) && !Yii::$app->user->isGuest)
{
if(Yii::$app->controller->module->id == 'app-producer') {
$params[$options['attribute_id_producer']] = Yii::$app->controller->getProducer()->id ;
}
else {
$params[$options['attribute_id_producer']] = Producer::getId() ;
}
$params[$options['attribute_id_producer']] = Producer::getId() ;
}
if(!isset($options['type_search'])) {

+ 1
- 1
common/models/Order.php Ver arquivo

@@ -408,7 +408,7 @@ class Order extends ActiveRecordCommon
}
}
else {
$html .= '<span class="label label-default">À régler sur place</span>';
$html .= '<span class="label label-default">Non réglé</span>';
}

return $html;

+ 0
- 1
common/models/PointSale.php Ver arquivo

@@ -330,5 +330,4 @@ class PointSale extends ActiveRecordCommon
}
return $str ;
}

}

+ 12
- 7
common/models/Producer.php Ver arquivo

@@ -87,7 +87,7 @@ class Producer extends ActiveRecordCommon
}
}],
[['description', 'order_infos','slug','secret_key_payplug'], 'string'],
[['negative_balance', 'credit', 'active','online_payment'], 'boolean'],
[['negative_balance', 'credit', 'active','online_payment','user_manage_subscription'], 'boolean'],
[['name', 'siret', 'logo', 'photo', 'postcode', 'city', 'code','type'], 'string', 'max' => 255],
[['free_price', 'credit_limit_reminder'], 'double'],
['free_price', 'compare', 'compareValue' => 0, 'operator' => '>=', 'type' => 'number', 'message' => 'Prix libre doit être supérieur ou égal à 0'],
@@ -120,7 +120,8 @@ class Producer extends ActiveRecordCommon
'type' => 'Type de producteur',
'credit_limit_reminder' => 'Seuil de crédit limite avant relance',
'online_payment' => 'Activer le paiement en ligne',
'secret_key_payplug' => 'Clé secrète Payplug'
'secret_key_payplug' => 'Clé secrète Payplug',
'user_manage_subscription' => 'Autoriser les utilisateurs à gérer leurs abonnements'
];
}

@@ -354,15 +355,19 @@ class Producer extends ActiveRecordCommon
}
/**
* Retourne le producteur courant (le producteur auquel l'utilisateur
* connecté est rattaché).
* Retourne l'ID du producteur courant.
*
* @return integer|boolean
*/
public static function getId()
{
if(!Yii::$app->user->isGuest) {
return Yii::$app->user->identity->id_producer ;
{
if(Yii::$app->controller->module->id == 'app-backend') {
if(!Yii::$app->user->isGuest) {
return Yii::$app->user->identity->id_producer ;
}
}
else {
return Yii::$app->controller->getProducer()->id ; ;
}
return false ;

+ 57
- 46
common/models/Subscription.php Ver arquivo

@@ -262,51 +262,57 @@ class Subscription extends ActiveRecordCommon
$arrSubscriptions = [];

foreach ($subscriptions as $s) {
// vérif dates
if ($date >= $s->date_begin &&
(!$s->date_end || $date <= $s->date_end))
{
// périodicite
$nbDays = (strtotime($date) - strtotime($s->date_begin)) / (24 * 60 * 60);
if ($nbDays % ($s->week_frequency * 7) < 7) {
// jour de la semaine
$day = date('N', strtotime($date));
switch ($day) {
case 1 : $day = 'monday';
break;
case 2 : $day = 'tuesday';
break;
case 3 : $day = 'wednesday';
break;
case 4 : $day = 'thursday';
break;
case 5 : $day = 'friday';
break;
case 6 : $day = 'saturday';
break;
case 7 : $day = 'sunday';
break;
}

if ($s->$day) {
$arrSubscriptions[] = $s;
}
}
(!$s->date_end || $date <= $s->date_end) &&
$s->matchWith($date))
{
$arrSubscriptions[] = $s;
}
}

return $arrSubscriptions;
}
/**
* Valide le fait qu'un abonnement est bien compatible avec une date donnée.
*
* @param string $date
* @return boolean
*/
public function matchWith($date)
{
$arrayDays = [
1 => 'monday',
2 => 'tuesday',
3 => 'wednesday',
4 => 'thursday',
5 => 'friday',
6 => 'saturday',
7 => 'sunday'
] ;
$nbDays = (strtotime($date) - strtotime($this->date_begin)) / (24 * 60 * 60);
if ($nbDays % ($this->week_frequency * 7) < 7) {
$numDay = date('N', strtotime($date));
$day = $arrayDays[$numDay] ;
if ($this->$day) {
return true ;
}
}
return false ;
}
/**
* Recherche les distributions futures où l'abonnement peut s'appliquer.
*
* @return array
*/
public function searchMatchedIncomingDistributions()
{
{
$producer = Producer::getCurrent() ;
$params = [
':date_today' => date('Y-m-d'),
':date_earliest_order' => $producer->getEarliestDateOrder(),
':date_begin' => date('Y-m-d', strtotime($this->date_begin)),
':id_producer' => Producer::getId()
] ;
@@ -314,7 +320,7 @@ class Subscription extends ActiveRecordCommon
$incomingDistributions = Distribution::find()
->where('id_producer = :id_producer')
->andWhere('date >= :date_begin')
->andWhere('date >= :date_today') ;
->andWhere('date >= :date_earliest_order') ;
if($this->date_end) {
$incomingDistributions->andWhere('date < :date_end') ;
@@ -327,25 +333,14 @@ class Subscription extends ActiveRecordCommon
$incomingDistributionsArray = $incomingDistributions->all() ;
$matchedIncomingDistributionsArray = [] ;
$arrayDays = [
1 => 'monday',
2 => 'tuesday',
3 => 'wednesday',
4 => 'thursday',
5 => 'friday',
6 => 'saturday',
7 => 'sunday'
] ;
foreach($incomingDistributionsArray as $incomingDistribution) {
$numDay = date('N', strtotime($incomingDistribution->date)) ;
$day = $arrayDays[$numDay] ;
if($this->$day) {
if($this->matchWith($incomingDistribution->date)) {
$matchedIncomingDistributionsArray[] = $incomingDistribution ;
}
}
return $matchedIncomingDistributionsArray ;
}
}
public function deleteOrdersIncomingDistributions()
{
@@ -364,7 +359,7 @@ class Subscription extends ActiveRecordCommon
->andWhere('order.id_subscription = :id_subscription') ;
if($this->date_end) {
$orders->andWhere('distribution.date =< :date_end') ;
$orders->andWhere('distribution.date <= :date_end') ;
$params[':date_end'] = $this->date_end ;
}

@@ -374,8 +369,24 @@ class Subscription extends ActiveRecordCommon
if($ordersArray && count($ordersArray)) {
foreach($ordersArray as $order) {
ProductOrder::deleteAll(['id_order' => $order->id]) ;
$order->delete() ;
}
}
}
public function updateIncomingDistributions($update = false)
{
$matchedDistributionsArray = $this->searchMatchedIncomingDistributions() ;
if($update) {
$this->deleteOrdersIncomingDistributions() ;
}
if(count($matchedDistributionsArray)) {
foreach($matchedDistributionsArray as $distribution) {
$this->add($distribution->date) ;
}
}
}
}

+ 1
- 0
common/models/SubscriptionForm.php Ver arquivo

@@ -168,6 +168,7 @@ class SubscriptionForm extends Model
if(!$this->id) {
$this->id = $subscription->id ;
}
}
return true;
}

+ 7
- 1
common/models/SubscriptionSearch.php Ver arquivo

@@ -65,7 +65,7 @@ class SubscriptionSearch extends Subscription
->where(['subscription.id_producer' => Producer::getId()])
;
$dataProvider = new ActiveDataProvider([
$dataProvider = new \yii\data\ActiveDataProvider([
'query' => $query,
'sort' => ['attributes' => ['username']],
'pagination' => [
@@ -93,6 +93,12 @@ class SubscriptionSearch extends Subscription
return $dataProvider;
}

if(isset($this->id_user) && is_numeric($this->id_user)) {
$query->andWhere([
'subscription.id_user' => $this->id_user
]) ;
}
if(isset($this->id_point_sale) && is_numeric($this->id_point_sale)) {
$query->andWhere([
'subscription.id_point_sale' => $this->id_point_sale

+ 15
- 0
console/migrations/m190121_101211_ajout_config_option_gestion_abonnement_par_l_utilisateur.php Ver arquivo

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

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

class m190121_101211_ajout_config_option_gestion_abonnement_par_l_utilisateur extends Migration {

public function up() {
$this->addColumn('producer', 'user_manage_subscription', Schema::TYPE_BOOLEAN) ;
}

public function down() {
$this->dropColumn('producer', 'user_manage_subscription') ;
}
}

+ 62
- 0
producer/assets/VuejsSubscriptionFormAsset.php Ver arquivo

@@ -0,0 +1,62 @@
<?php
/**
Copyright La boîte à pain (2018)

contact@laboiteapain.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 producer\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') ;
}
}

+ 13
- 8
producer/controllers/OrderController.php Ver arquivo

@@ -93,7 +93,7 @@ class OrderController extends ProducerBaseController
->joinWith('distribution', 'distribution.producer')
->where([
'id_user' => Yii::$app->user->id,
'distribution.id_producer' => $this->getProducer()->id
'distribution.id_producer' => Producer::getId()
])
->orderBy('distribution.date DESC'),
'pagination' => [
@@ -449,14 +449,16 @@ class OrderController extends ProducerBaseController
':date' => $dateMini
]
]);
foreach($ordersUserArray as &$order) {
$order = array_merge($order->getAttributes(), [
'amount_total' => $order->getAmount(Order::AMOUNT_TOTAL),
'date_distribution' => $order->distribution->date,
'pointSale' => $order->pointSale->getAttributes()
]) ;
if(is_array($ordersUserArray) && count($ordersUserArray)) {
foreach($ordersUserArray as &$order) {
$order = array_merge($order->getAttributes(), [
'amount_total' => $order->getAmount(Order::AMOUNT_TOTAL),
'date_distribution' => $order->distribution->date,
'pointSale' => $order->pointSale->getAttributes()
]) ;
}
$json['orders'] = $ordersUserArray;
}
$json['orders'] = $ordersUserArray;
// User
$userProducer = UserProducer::searchOne([
@@ -507,6 +509,9 @@ class OrderController extends ProducerBaseController
],
'userPointSale' => ($pointSale->userPointSale ? $pointSale->userPointSale[0] : '')
]) ;
if($pointSale['code'] && strlen($pointSale['code'])) {
$pointSale['code'] = '***' ;
}
}
$json['points_sale'] = $pointsSaleArray;

+ 339
- 0
producer/controllers/SubscriptionController.php Ver arquivo

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

/**
Copyright La boîte à pain (2018)

contact@laboiteapain.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 La boîte à pain (2018)

contact@laboiteapain.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 producer\controllers;

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

class SubscriptionController extends ProducerBaseController
{
var $enableCsrfValidation = false;

public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'allow' => true,
'roles' => ['@'],
]
],
],
];
}

/**
* Liste les commandes récurrente du producteur.
*
* @return string
*/
public function actionIndex()
{
$searchModel = new SubscriptionSearch ;
$searchModel->id_user = User::getCurrentId() ;
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider
]);
}

public function actionAjaxProcess()
{
// form
$model = new SubscriptionForm;
$model->id_producer = Producer::getId();
$model->id_user = User::getCurrentId() ;
$posts = Yii::$app->request->post() ;
$idSubscription = (int) $posts['idSubscription'] ;
$isUpdate = false ;
if($idSubscription) {
$subscription = Subscription::findOne($idSubscription);
if ($subscription) {
$model->id = $idSubscription;
$isUpdate = true ;
}
}
if ($model->load($posts) && $model->validate()
&& $model->save())
{
$subscription = Subscription::searchOne([
'id' => $model->id
]) ;
$subscription->updateIncomingDistributions($isUpdate) ;
if($isUpdate) {
Yii::$app->getSession()->setFlash('success', 'Abonnement modifié');
}
else {
Yii::$app->getSession()->setFlash('success', 'Abonnement ajouté');
}
}
}
/**
* Crée une commande récurrente.
*
* @return string
*/
public function actionForm($id = 0)
{
return $this->render('form', [
'idSubscription' => (int) $id
]);
}

/**
* Modifie une commande récurrente.
*
* @param integer $id
* @return string
* @throws NotFoundHttpException
*/
public function actionUpdate($id)
{
// form
$model = new SubscriptionForm;
$subscription = Subscription::findOne($id);
if ($subscription) {
$model->id = $id;
$model->id_producer = $subscription->id_producer;
$model->id_user = $subscription->id_user;
$model->username = $subscription->username;
$model->id_point_sale = $subscription->id_point_sale;
$model->date_begin = date('d/m/Y', strtotime($subscription->date_begin));
if (strlen($subscription->date_end)) {
$model->date_end = date('d/m/Y', strtotime($subscription->date_end));
}
$model->monday = $subscription->monday;
$model->tuesday = $subscription->tuesday;
$model->wednesday = $subscription->wednesday;
$model->thursday = $subscription->thursday;
$model->friday = $subscription->friday;
$model->saturday = $subscription->saturday;
$model->sunday = $subscription->sunday;
$model->auto_payment = $subscription->auto_payment;
$model->week_frequency = $subscription->week_frequency;

// produits
$arrayProductsSubscription = ProductSubscription::searchAll([
'id_subscription' => $model->id
]) ;
foreach ($arrayProductsSubscription as $productSubscription) {
$model->products['product_' . $productSubscription->id_product] = $productSubscription->quantity;
}
} else {
throw new NotFoundHttpException('L\'abonnement est introuvable.', 404);
}

// produits
$productsArray = Product::searchAll() ;

if ($model->load(Yii::$app->request->post()) && $model->validate()) {
if (!strlen($model->date_end)) {
$model->date_end = null;
}
if ($model->save()) {
Yii::$app->getSession()->setFlash('success', 'Abonnement modifié');
$subscription = Subscription::findOne($model->id) ;
$matchedDistributionsArray = $subscription->searchMatchedIncomingDistributions() ;
if(count($matchedDistributionsArray)) {
return $this->redirect(['subscription/update-distributions', 'idSubscription' => $subscription->id,'update' => true]);
}
else {
return $this->redirect(['subscription/index']);
}
}
}

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

/**
* Supprime un abonnement
*
* @param integer $id
*/
public function actionDelete($id)
{
$subscription = Subscription::searchOne([
'id' => $id
]) ;
ProductSubscription::deleteAll(['id_subscription' => $id]);
$subscription->deleteOrdersIncomingDistributions() ;
$subscription->delete();
Yii::$app->getSession()->setFlash('success', 'Abonnement supprimé');
return $this->redirect(['subscription/index']);
}
public function actionAjaxInfos($idSubscription = 0)
{
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
$params = [] ;
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] ;
}
$product = array_merge(
$product->getAttributes(),
[
'index' => $indexProduct ++,
'quantity_form' => $quantity
]
) ;
}
$params['products'] = $productsArray ;
$pointsSaleArray = PointSale::searchAll() ;
foreach($pointsSaleArray as &$pointSale) {
$pointSale = array_merge($pointSale->getAttributes(),[
'userPointSale' => ($pointSale->userPointSale ? $pointSale->userPointSale[0] : '')
]) ;
if($pointSale['code'] && strlen($pointSale['code'])) {
$pointSale['code'] = '***' ;
}
}
$params['points_sale'] = $pointsSaleArray ;
if($idSubscription > 0) {
$subscription = Subscription::searchOne([
'id' => $idSubscription
]) ;
if(!$subscription || $subscription->id_user != User::getCurrentId()) {
throw new UserException('Abonnement introuvable') ;
}
else {
$params = array_merge($params, $subscription->getAttributes()) ;
}
}
return $params ;
}
/**
* Vérifie le code saisi pour un point de vente.
*
* @param integer $idPointSale
* @param string $code
* @return boolean
*/
public function actionAjaxValidateCodePointSale($idPointSale, $code)
{
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
$pointSale = PointSale::findOne($idPointSale);
if ($pointSale) {
if ($pointSale->validateCode($code)) {
return 1;
}
}
return 0;
}
}

+ 4
- 4
producer/views/credit/history.php Ver arquivo

@@ -41,11 +41,11 @@ use yii\helpers\Html;
$this->setTitle('Crédit : <span id="credit-user">'.number_format($creditUser, 2).' €</span>');
$this->setPageTitle('Crédit');

?>
if($this->context->getProducer()->online_payment) {
$this->addButton(['label' => '<span class="glyphicon glyphicon-credit-card"></span> Créditer mon compte', 'url' => 'credit/add', 'class' => 'btn btn-primary']) ;
}

<?php if($this->context->getProducer()->online_payment): ?>
<?= Html::a('<span class="glyphicon glyphicon-credit-card"></span> Créditer mon compte', ['credit/add'], ['class' => 'btn btn-primary']); ?><br /><br />
<?php endif; ?>
?>

<?= GridView::widget([
// 'filterModel' => $searchModel,

+ 22
- 4
producer/views/layouts/main.php Ver arquivo

@@ -41,6 +41,7 @@ use yii\bootstrap\NavBar;
use yii\widgets\Breadcrumbs;
use common\widgets\Alert;
use common\helpers\Url;
use common\models\Producer;

\common\assets\CommonAsset::register($this);
\producer\assets\AppAsset::register($this);
@@ -166,15 +167,21 @@ $producer = $this->context->getProducer() ;
'active' => $this->getControllerAction() == 'order/order',
],
[
'label' => '<span class="glyphicon glyphicon-folder-open"></span> Historique',
'label' => '<span class="glyphicon glyphicon-folder-open"></span> Mes commandes',
'url' => Yii::$app->urlManager->createUrl(['order/history']),
'visible' => !Yii::$app->user->isGuest,
'active' => $this->getControllerAction() == 'order/history',
],
[
'label' => '<span class="glyphicon glyphicon-repeat"></span> Abonnement',
'url' => Yii::$app->urlManager->createUrl(['subscription/index']),
'visible' => !Yii::$app->user->isGuest && $producer->user_manage_subscription,
'active' => $this->getControllerAction() == 'subscription/index',
],
[
'label' => '<span class="glyphicon glyphicon-euro"></span> Crédit',
'url' => Yii::$app->urlManager->createUrl(['credit/history']),
'visible' => !Yii::$app->user->isGuest && Producer::getConfig('credit'),
'visible' => !Yii::$app->user->isGuest && $producer->credit,
'active' => $this->getControllerAction() == 'credit/history',
],
[
@@ -194,7 +201,18 @@ $producer = $this->context->getProducer() ;
</nav>
<?php if(strlen($this->getTitle())): ?>
<h2 id="page-title"><?= $this->getTitle(); ?></h2>
<h2 id="page-title">
<?= $this->getTitle(); ?>
<?php
if(count($this->buttons)): ?>
<span id="buttons">
<?php foreach($this->buttons as $button) {
echo '<a href="'.Yii::$app->urlManagerProducer->createUrl($button['url']).'" class="'.$button['class'].'">'.$button['label'].'</a>' ;
}
?>
</span>
<?php endif; ?>
</h2>
<?php endif; ?>
<section id="content">
@@ -208,7 +226,7 @@ $producer = $this->context->getProducer() ;
<?= Yii::$app->session->getFlash('success') ?>
</div>
<?php endif; ?>
<?= $content ?>
</section>
</div>

+ 1
- 1
producer/views/order/history.php Ver arquivo

@@ -39,7 +39,7 @@ termes.
use yii\bootstrap\ActiveForm;
use common\models\Order ;

$this->setTitle('Historique de mes commandes') ;
$this->setTitle('Mes commandes') ;

?>


+ 249
- 0
producer/views/subscription/_form.php Ver arquivo

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

/**
Copyright La boîte à pain (2018)

contact@laboiteapain.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\widgets\ActiveForm;
use yii\helpers\ArrayHelper ;
use common\models\User ;
use common\models\PointSale ;

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

?>

<div class="subscription-form" id="app-subscription-form">
<form @submit.prevent="formSubmit()" v-show="loading == false">
<input type="hidden" id="subscription-id" value="<?= $idSubscription; ?>" />
<div class="alert alert-danger" v-if="errors.length">
<ul>
<li v-for="error in errors">
{{ error }}
</li>
</ul>
</div>
<div class="points-sale">
<h3><span>Point de vente</span></h3>
<table class="table table-bordered table-hovered" v-if="pointsSale.length">
<thead>
<tr>
<th>Nom</th>
<th>Localité</th>
<th></th>
</tr>
</thead>
<tbody>
<tr v-for="pointSale in pointsSale" v-if="pointSale" :class="(pointSaleActive && pointSale.id == pointSaleActive.id) ? 'selected' : ''">
<td class="name">
<span class="the-name">{{ pointSale.name }}</span>
<div class="comment" v-if="pointSale.userPointSale">
{{ pointSale.userPointSale.comment }}
</div>
</td>
<td class="locality">{{ pointSale.locality }}</td>
<td class="actions">
<div :class="'form-group' + (pointSale.invalid_code ? ' has-error' : '')">
<div class="input-group" v-if="pointSale.code && pointSale.code.length > 0">
<span class="input-group-addon"><span class="glyphicon glyphicon-lock"></span></span>
<input v-model="pointsSaleCodes[pointSale.id]" type="password" placeholder="Code" class="form-control input-code" />
</div>
</div>
<button class="btn btn-primary" @click.prevent="pointSaleClick" :data-code="pointSale.code && pointSale.code.length > 0" :data-id-point-sale="pointSale.id">
<span class="glyphicon glyphicon-map-marker"></span>
Choisir
</button>
</td>
</tr>
</tbody>
</table>
</div>
<h3 id="step-date"><span>Dates</span></h3>
<div class="col-md-4">
<div class="form-group">
<label>Date de début</label>
<v-date-picker
mode="single"
v-model="dateBegin"
:input-props='{class: "form-control", placeholder: "" }'>
</v-date-picker>
</div>
</div>
<div class="clr"></div>
<div class="col-md-4">
<div class="form-group">
<label>Date de fin</label>
<v-date-picker
mode="single"
v-model="dateEnd"
:min-date="dateBegin"
:input-props='{class: "form-control", placeholder: ""}'>
</v-date-picker>
<div class="hint-block">Laisser vide pour une durée indéterminée</div>
</div>
</div>
<div class="clr"></div>
<div class="col-md-4">
<label for="subscriptionform-week_frequency">Périodicité</label>
<select id="subscriptionform-week_frequency" class="form-control" v-model="weekFrequency">
<option value="1">Toutes les semaines</option>
<option value="2">Toutes les 2 semaines</option>
<option value="3">Toutes les 3 semaines</option>
<option value="4">Tous les mois</option>
</select>
</div>
<div class="clr"></div>
<h3><span>Paiement</span></h3>

<?php if(Producer::getConfig('credit')): ?>
<div class="form-group field-subscriptionform-auto_payment">
<label><input type="checkbox" id="subscriptionform-auto_payment" name="SubscriptionForm[auto_payment]" v-model="autoPayment"> Paiement automatique</label>
<div class="hint-block">Cochez cette case si vous souhaitez que votre Crédit soit automatiquement débité.</div>
<div class="help-block"></div>
</div>
<?php endif; ?>
<div class="days" v-if="pointSaleActive">
<h3 id="step-days"><span>Jours</span></h3>
<div v-if="pointSaleActive.delivery_monday == true">
<div class="form-group field-subscriptionform-monday">
<label><input type="checkbox" id="subscriptionform-monday" v-model="monday" @change="dayChange"> Lundi</label>
</div>
</div>
<div v-if="pointSaleActive.delivery_tuesday == true">
<div class="form-group field-subscriptionform-monday">
<label><input type="checkbox" id="subscriptionform-tuesday" v-model="tuesday" @change="dayChange"> Mardi</label>
</div>
</div>
<div v-if="pointSaleActive.delivery_wednesday == true">
<div class="form-group field-subscriptionform-wednesday">
<label><input type="checkbox" id="subscriptionform-wednesday" v-model="wednesday" @change="dayChange"> Mercredi</label>
</div>
</div>
<div v-if="pointSaleActive.delivery_thursday == true">
<div class="form-group field-subscriptionform-thursday">
<label><input type="checkbox" id="subscriptionform-thursday" v-model="thursday" @change="dayChange"> Jeudi</label>
</div>
</div>
<div v-if="pointSaleActive.delivery_friday == true">
<div class="form-group field-subscriptionform-friday">
<label><input type="checkbox" id="subscriptionform-friday" v-model="friday" @change="dayChange"> Vendredi</label>
</div>
</div>
<div v-if="pointSaleActive.delivery_saturday == true">
<div class="form-group field-subscriptionform-saturday">
<label><input type="checkbox" id="subscriptionform-saturday" v-model="saturday" @change="dayChange"> Samedi</label>
</div>
</div>
<div v-if="pointSaleActive.delivery_sunday == true">
<div class="form-group field-subscriptionform-sunday">
<label><input type="checkbox" id="subscriptionform-sunday" v-model="sunday" @change="dayChange"> Dimanche</label>
</div>
</div>

<div class="alert alert-warning" v-if="!pointSaleActive.delivery_monday && !pointSaleActive.delivery_tuesday && !pointSaleActive.delivery_wednesday && !pointSaleActive.delivery_thursday && !pointSaleActive.delivery_friday && !pointSaleActive.delivery_saturday && !pointSaleActive.delivery_sunday">
Aucun jour de distribution disponible pour ce point de vente.
</div>
</div>
<div class="clr"></div>
<div class="products" v-if="(monday || tuesday || wednesday || thursday || friday || saturday || sunday) && checkOneProductAvailable()">
<h3><span>Produits</span></h3>
<?php if(isset($model->errors['products']) && count($model->errors['products']))
{
echo '<div class="alert alert-danger">'.$model->errors['products'][0].'</div>' ;
}
?>
<table :class="'table table-bordered table-condensed table-hover' + (monday ? ' monday-active' : '') + (tuesday ? ' tuesday-active' : '') + (wednesday ? ' wednesday-active' : '') + (thursday ? ' thursday-active' : '') + (friday ? ' friday-active' : '') + (saturday ? ' saturday-active' : '') + (sunday ? ' sunday-active' : '')">
<thead>
<tr>
<th>Nom</th>
<th>Prix unitaire</th>
<th>Quantité</th>
<th>Total</th>
</tr>
</thead>
<tbody>
<tr v-for="product in products" v-if="checkProductAvailable(product)">
<td>
<span class="name">{{ product.name }}</span>
<span class="other">
<span v-if="product.description.length">/</span>
<span class="description">{{ product.description }}</span>
<span v-if="product.weight">({{ product.weight }}g)</span>
</span>
<div class="recipe" v-if="product.recipe.length">{{ product.recipe }}</div>
</td>
<td class="price-unit">
{{ formatPrice(product.price) }}
</td>
<td class="quantity">
<div class="input-group">
<span class="input-group-btn">
<button class="btn btn-default" type="button" @click="productQuantityClick(product, -1)"><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-btn">
<button class="btn btn-default" type="button" @click="productQuantityClick(product, 1)"><span class="glyphicon glyphicon-plus"></span></button>
</span>
</div>
</td>
<td class="price-total">
{{ formatPrice(product.price * product.quantity_form) }}
</td>
</tr>
<tr class="total">
<td colspan="3"></td>
<td class="price-total">{{ priceTotal(true) }}</td>
</tr>
</tbody>
</table>
<div v-if="!checkOneProductAvailable()" class="alert alert-warning">
Aucun produit n'est disponible pour les jours de distribution sélectionnés.
</div>
</div>
<button class="btn btn-primary" disabled="disabled" v-if="disableSubmitButton">Enregistrer</button>
<button class="btn btn-primary" v-else>Enregistrer</button>
</form>
</div>

+ 53
- 0
producer/views/subscription/form.php Ver arquivo

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

/**
Copyright La boîte à pain (2018)

contact@laboiteapain.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;

if($idSubscription > 0) {
$this->setTitle('Modifier un abonnement') ;
}
else {
$this->setTitle('Ajouter un abonnement') ;
}
?>

<div class="subscription-create">
<?= $this->render('_form', [
'idSubscription' => $idSubscription
]) ?>
</div>

+ 202
- 0
producer/views/subscription/index.php Ver arquivo

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

/**
Copyright La boîte à pain (2018)

contact@laboiteapain.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\grid\GridView;

$this->setTitle('Abonnements') ;
$this->addButton(['label' => '+ Ajouter', 'url' => 'subscription/form', 'class' => 'btn btn-primary']) ;

$columns = [
[
'attribute' => 'product_name',
'label' => 'Produits',
'format' => 'raw',
'value' => function($model) {
$html = '' ;
foreach($model->productSubscription as $productSubscription)
{
if(isset($productSubscription->product)) {
$html .= $productSubscription->quantity . '&nbsp;x&nbsp;'.Html::encode($productSubscription->product->name).'<br />' ;
}
else {
$html .= 'Produit non défini<br />' ;
}
}

// aucun produit
if(!count($model->productSubscription))
{
$html .= '<span class="glyphicon glyphicon-warning-sign"></span> Aucun produit' ;
}

return $html ;
}
],
[
'label' => 'Point de vente',
'format' => 'raw',
'filter' => ArrayHelper::map(PointSale::find()->where(['id_producer' => Producer::getId()])->asArray()->all(), 'id', 'name'),
'value' => function($model) {
return Html::encode($model->pointSale->name) ;
}
],
[
'attribute' => 'date_begin',
'label' => 'Date de début',
'format' => 'raw',
'value' => function($model) {
$html = date('d/m/Y',strtotime($model->date_begin)) ;
return $html ;
}
],
[
'attribute' => 'day',
'label' => 'Jours',
'format' => 'raw',
'filter' => [
'monday' => 'Lundi',
'tuesday' => 'Mardi',
'wednesday' => 'Mercredi',
'thursday' => 'Jeudi',
'friday' => 'Vendredi',
'saterday' => 'Samedi',
'sunday' => 'Dimanche',
],
'contentOptions' => ['class' => 'text-small'],
'value' => function($model) {
$html = '' ;
if($model->monday) {
$html .= 'lundi, ' ;
}
if($model->tuesday) {
$html .= 'mardi, ' ;
}
if($model->wednesday) {
$html .= 'mercredi, ' ;
}
if($model->thursday) {
$html .= 'jeudi, ' ;
}
if($model->friday) {
$html .= 'vendredi, ' ;
}
if($model->saturday) {
$html .= 'samedi, ' ;
}
if($model->sunday) {
$html .= 'dimanche, ' ;
}

if(strlen($html)) {
return substr ($html, 0, strlen($html) - 2) ;
}
else {
return '<span class="glyphicon glyphicon-warning-sign"></span> Aucun jour' ;
}
}
],
[
'attribute' => 'week_frequency',
'filter' => [
1 => 'Toutes les semaines',
2 => 'Toutes les 2 semaines',
3 => 'Toutes les 3 semaines',
4 => 'Tous les mois'],
'value' => function($model) {
if($model->week_frequency == 1) {
return 'Toutes les semaines' ;
}
else {
return 'Toutes les '.$model->week_frequency.' semaines' ;
}

}
],
] ;
if(Producer::getConfig('credit')) {
$columns[] = [
'format' => 'raw',
'label' => 'Paiement automatique',
'headerOptions' => ['class' => 'column-auto-payment'],
'contentOptions' => ['class' => 'column-auto-payment'],
'filter' => [0 => 'Non', 1 => 'Oui'],
'value' => function($model) {
if($model->auto_payment) {
return '<span class="label label-success">Oui</span>' ;
}
else {
return '<span class="label label-danger">Non</span>' ;
}
}
] ;
}
$columns[] = [
'class' => 'yii\grid\ActionColumn',
'template' => '{form} {delete}',
'headerOptions' => ['class' => 'column-actions'],
'contentOptions' => ['class' => 'column-actions'],
'buttons' => [
'form' => function ($url, $model) {
return Html::a('<span class="glyphicon glyphicon-pencil"></span>', $url, [
'title' => Yii::t('app', 'Modifier'), 'class' => 'btn btn-default'
]);
},
'delete' => function ($url, $model) {
return Html::a('<span class="glyphicon glyphicon-trash"></span>', $url, [
'title' => Yii::t('app', 'Supprimer'), 'class' => 'btn btn-default'
]);
}
],
] ;

?>
<div class="subscription-index">
<?php if($dataProvider->getCount()): ?>
<?= GridView::widget([
'dataProvider' => $dataProvider,
'columns' => $columns,
]); ?>
<?php else: ?>
<div class="alert alert-info">
Vous n'avez encore aucun abonnement chez ce producteur.
</div>
<?php endif; ?>
</div>

+ 144
- 21
producer/web/css/screen.css Ver arquivo

@@ -400,7 +400,7 @@ ul.pagination li a:hover, ul.pagination li a:focus, ul.pagination li a:active {
padding: 10px;
}
/* line 307, ../sass/_layout.scss */
#main #page-title {
#main h2#page-title {
padding-left: 15px;
padding-right: 15px;
padding-bottom: 15px;
@@ -412,7 +412,12 @@ ul.pagination li a:hover, ul.pagination li a:focus, ul.pagination li a:active {
top: -10px;
text-align: center;
}
/* line 320, ../sass/_layout.scss */
/* line 319, ../sass/_layout.scss */
#main h2#page-title #buttons {
margin-bottom: 15px;
font-family: "Arial";
}
/* line 326, ../sass/_layout.scss */
#main .container {
padding: 0px;
background-color: white;
@@ -420,39 +425,39 @@ ul.pagination li a:hover, ul.pagination li a:focus, ul.pagination li a:active {
border-left: solid 1px #e0e0e0;
border-right: solid 1px #e0e0e0;
}
/* line 328, ../sass/_layout.scss */
/* line 334, ../sass/_layout.scss */
#main #content {
padding-bottom: 20px;
padding: 0px 20px 20px 20px;
}
/* line 332, ../sass/_layout.scss */
/* line 338, ../sass/_layout.scss */
#main #content h1, #main #content h2, #main #content h3, #main #content h4, #main #content h5, #main #content h6 {
font-family: "myriadpro-regular";
margin-top: 30px;
margin-bottom: 20px;
}
/* line 337, ../sass/_layout.scss */
/* line 343, ../sass/_layout.scss */
#main #content h1.first, #main #content h2.first, #main #content h3.first, #main #content h4.first, #main #content h5.first, #main #content h6.first {
margin-top: 0px;
}
/* line 342, ../sass/_layout.scss */
/* line 348, ../sass/_layout.scss */
#main #content h1 {
font-size: 30px;
}
/* line 346, ../sass/_layout.scss */
/* line 352, ../sass/_layout.scss */
#main #content h2 {
font-size: 25px;
}
/* line 351, ../sass/_layout.scss */
/* line 357, ../sass/_layout.scss */
#main #content h3 {
font-family: "myriadpro-light";
text-transform: uppercase;
font-size: 23px;
padding: 10px 0px 10px 10px;
color: white;
text-align: center;
text-align: left;
margin-bottom: 30px;
margin-top: 45px;
}
/* line 358, ../sass/_layout.scss */
/* line 365, ../sass/_layout.scss */
#main #content h3 span {
background-color: #BB8757;
padding: 10px 20px;
@@ -461,29 +466,33 @@ ul.pagination li a:hover, ul.pagination li a:focus, ul.pagination li a:active {
color: #BB8757;
border: dotted 1px #BB8757;
}
/* line 369, ../sass/_layout.scss */
/* line 376, ../sass/_layout.scss */
#main #content h4 {
font-size: 20px;
}
/* line 373, ../sass/_layout.scss */
/* line 380, ../sass/_layout.scss */
#main #content h5 {
font-size: 18px;
}
/* line 377, ../sass/_layout.scss */
/* line 384, ../sass/_layout.scss */
#main #content h6 {
font-size: 16px;
}
/* line 390, ../sass/_layout.scss */
#main #content form .form-group .hint-block {
color: gray;
}

/* line 383, ../sass/_layout.scss */
/* line 398, ../sass/_layout.scss */
#footer {
background-color: #BB8757;
height: 100px;
}
/* line 387, ../sass/_layout.scss */
/* line 402, ../sass/_layout.scss */
#footer .container {
padding: 0px;
}
/* line 389, ../sass/_layout.scss */
/* line 404, ../sass/_layout.scss */
#footer .container .overflow {
height: 30px;
background-color: white;
@@ -491,18 +500,18 @@ ul.pagination li a:hover, ul.pagination li a:focus, ul.pagination li a:active {
border-right: solid 1px #e0e0e0;
border-bottom: solid 1px #e0e0e0;
}
/* line 397, ../sass/_layout.scss */
/* line 412, ../sass/_layout.scss */
#footer .container .content {
padding-top: 20px;
color: white;
}
/* line 401, ../sass/_layout.scss */
/* line 416, ../sass/_layout.scss */
#footer .container .content a {
color: white;
text-decoration: underline;
margin-right: 10px;
}
/* line 409, ../sass/_layout.scss */
/* line 424, ../sass/_layout.scss */
#footer .container #code-source img {
height: 20px;
}
@@ -1454,6 +1463,120 @@ termes.
color: gray;
}

/* line 7, ../sass/subscription/_form.scss */
.subscription-create .subscription-form .points-sale .locality,
.subscription-update .subscription-form .points-sale .locality {
color: gray;
}
/* line 10, ../sass/subscription/_form.scss */
.subscription-create .subscription-form .points-sale label,
.subscription-update .subscription-form .points-sale label {
cursor: pointer;
}
/* line 16, ../sass/subscription/_form.scss */
.subscription-create .subscription-form .days .form-group,
.subscription-update .subscription-form .days .form-group {
float: left;
margin-right: 15px;
}
/* line 26, ../sass/subscription/_form.scss */
.subscription-create .subscription-form .points-sale table tr.selected td,
.subscription-update .subscription-form .points-sale table tr.selected td {
background-color: #F8F1DD;
}
/* line 31, ../sass/subscription/_form.scss */
.subscription-create .subscription-form .points-sale table .block-code,
.subscription-update .subscription-form .points-sale table .block-code {
width: 150px;
}
/* line 35, ../sass/subscription/_form.scss */
.subscription-create .subscription-form .points-sale table .actions,
.subscription-update .subscription-form .points-sale table .actions {
width: 150px;
}
/* line 38, ../sass/subscription/_form.scss */
.subscription-create .subscription-form .points-sale table .actions button,
.subscription-update .subscription-form .points-sale table .actions button {
width: 100%;
display: block;
}
/* line 47, ../sass/subscription/_form.scss */
.subscription-create .subscription-form .products .monday, .subscription-create .subscription-form .products .tuesday, .subscription-create .subscription-form .products .wednesday, .subscription-create .subscription-form .products .thursday,
.subscription-create .subscription-form .products .friday, .subscription-create .subscription-form .products .saturday, .subscription-create .subscription-form .products .sunday, .subscription-create .subscription-form .products .no-day,
.subscription-update .subscription-form .products .monday,
.subscription-update .subscription-form .products .tuesday,
.subscription-update .subscription-form .products .wednesday,
.subscription-update .subscription-form .products .thursday,
.subscription-update .subscription-form .products .friday,
.subscription-update .subscription-form .products .saturday,
.subscription-update .subscription-form .products .sunday,
.subscription-update .subscription-form .products .no-day {
display: none;
}
/* line 52, ../sass/subscription/_form.scss */
.subscription-create .subscription-form .products .monday-active .monday,
.subscription-create .subscription-form .products .tuesday-active .tuesday,
.subscription-create .subscription-form .products .wednesday-active .wednesday,
.subscription-create .subscription-form .products .thursday-active .thursday,
.subscription-create .subscription-form .products .friday-active .friday,
.subscription-create .subscription-form .products .saturday-active .saturday,
.subscription-create .subscription-form .products .sunday-active .sunday,
.subscription-update .subscription-form .products .monday-active .monday,
.subscription-update .subscription-form .products .tuesday-active .tuesday,
.subscription-update .subscription-form .products .wednesday-active .wednesday,
.subscription-update .subscription-form .products .thursday-active .thursday,
.subscription-update .subscription-form .products .friday-active .friday,
.subscription-update .subscription-form .products .saturday-active .saturday,
.subscription-update .subscription-form .products .sunday-active .sunday {
display: block;
}
/* line 62, ../sass/subscription/_form.scss */
.subscription-create .subscription-form .products td.quantity,
.subscription-update .subscription-form .products td.quantity {
width: 150px;
}
/* line 65, ../sass/subscription/_form.scss */
.subscription-create .subscription-form .products td.quantity input,
.subscription-update .subscription-form .products td.quantity input {
text-align: center;
}
/* line 68, ../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 74, ../sass/subscription/_form.scss */
.subscription-create .subscription-form .products .name,
.subscription-update .subscription-form .products .name {
font-family: "comfortaalight";
font-weight: bold;
text-transform: uppercase;
font-size: 18px;
}
/* line 81, ../sass/subscription/_form.scss */
.subscription-create .subscription-form .products .description,
.subscription-update .subscription-form .products .description {
font-style: italic;
}
/* line 85, ../sass/subscription/_form.scss */
.subscription-create .subscription-form .products .recipe,
.subscription-update .subscription-form .products .recipe {
font-size: 12px;
}
/* line 89, ../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 94, ../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;
font-size: 20px;
}

/**
Copyright La boîte à pain (2018)


+ 5
- 0
producer/web/js/lechatdesnoisettes.js Ver arquivo

@@ -80,8 +80,13 @@ $(document).ready(function() {
chat_systeme_commande() ;
chat_profil_user() ;
$('.dropdown-toggle').dropdown() ;
chat_datepicker() ;
}) ;

function chat_datepicker() {
$('input.datepicker').datepicker({dateFormat:'dd/mm/yy'}) ;
}

function chat_profil_user() {
if($('#profil-user').size()) {
if($('#user-no_mail').is(':checked')) {

+ 4
- 2
producer/web/js/vuejs/order-order.js Ver arquivo

@@ -120,8 +120,11 @@ var app = new Vue({
}) ;
}
}
var orders = [] ;
if(response.data.orders) {
orders = response.data.orders ;
}
var orders = response.data.orders ;
if(orders.length) {
for(var i= 0; i < orders.length; i++) {
this.calendar.attrs.push({
@@ -226,7 +229,6 @@ var app = new Vue({
(this.products[product.index].quantity_form + quantity <= this.products[product.index].quantity_remaining ||
!this.products[product.index].quantity_max)
) {
this.products[product.index].quantity_form += quantity ;
}
},

+ 287
- 0
producer/web/js/vuejs/subscription-form.js Ver arquivo

@@ -0,0 +1,287 @@

var app = new Vue({
el: '#app-subscription-form',
data: {
loading: true,
idSubscription: 0,
pointsSale: [],
idPointSaleActive: 0,
pointSaleActive: null,
pointsSaleCodes: [],
dateBegin: null,
dateEnd: null,
weekFrequency: 1,
autoPayment: true,
monday: false,
tuesday: false,
wednesday: false,
thursday: false,
friday: false,
saturday: false,
sunday: false,
products: [],
errors: [],
disableSubmitButton: false,
lastCountDays: 0,
},
mounted: function() {
this.init();
},
methods: {
init: function() {
if($('#subscription-id').val() != 0) {
this.idSubscription = $('#subscription-id').val() ;
}
this.dateBegin = new Date() ;

axios.get("ajax-infos",{params: {idSubscription : this.idSubscription}})
.then(response => {
this.products = response.data.products ;
this.pointsSale = response.data.points_sale ;
if(this.idSubscription > 0) {
this.validatePointSale(response.data.id_point_sale) ;
this.weekFrequency = response.data.week_frequency ;
this.autoPayment = response.data.auto_payment ;
var arrayDateBegin = response.data.date_begin.split('-') ;
this.dateBegin = new Date(arrayDateBegin[0], arrayDateBegin[1] - 1, arrayDateBegin[2]) ;
if(response.data.date_end && response.data.date_end.length > 0) {
var arrayDateEnd = response.data.date_begin.split('-') ;
this.dateEnd = new Date(arrayDateEnd[0], arrayDateEnd[1] - 1, arrayDateEnd[2]) ;
}
this.monday = response.data.monday ;
this.tuesday = response.data.tuesday ;
this.wednesday = response.data.wednesday ;
this.thursday = response.data.thursday ;
this.friday = response.data.friday ;
this.saturday = response.data.saturday ;
this.sunday = response.data.sunday ;
}
this.loading = false ;
});
},
formatDate: function(date) {
if(date) {
return ('0' + date.getDate()).slice(-2) + '/' + ('0' + (date.getMonth() + 1)).slice(-2) + '/' + date.getFullYear() ;
}
return false ;
},
pointSaleClick: function(event) {
var idPointSale = event.currentTarget.getAttribute('data-id-point-sale') ;
var hasCode = event.currentTarget.getAttribute('data-code') ;
if(hasCode) {
axios.get('ajax-validate-code-point-sale',{params: {
idPointSale: idPointSale,
code: this.pointsSaleCodes[idPointSale]
}}).then(response => {
if(response.data) {
this.getPointSale(idPointSale).invalid_code = false ;
this.validatePointSale(idPointSale) ;
}
else {
this.getPointSale(idPointSale).invalid_code = true ;
Vue.set(this.pointsSaleCodes, idPointSale, '');
}
}) ;
}
else {
this.validatePointSale(idPointSale) ;
}
},
validatePointSale: function(idPointSale) {
if(this.idPointSaleActive != idPointSale) {
this.monday = false ;
this.tuesday = false ;
this.wednesday = false ;
this.thursday = false ;
this.friday = false ;
this.saturday = false ;
this.sunday = false ;
}
this.pointSaleActive = this.getPointSale(idPointSale) ;
this.idPointSaleActive = idPointSale ;
boulange_scroll('step-date') ;
},
getPointSale: function(idPointSale) {
for(var key in this.pointsSale) {
if(this.pointsSale[key].id == idPointSale) {
return this.pointsSale[key] ;
}
}
},
dayChange: function() {
console.log(this.monday+' '+this.tuesday+' '+this.wednesday+' '+
this.thursday+' '+this.friday+' '+this.saturday+' '+this.sunday) ;
var count = Number(this.monday) + Number(this.tuesday) + Number(this.wednesday)
+ Number(this.thursday) + Number(this.friday) + Number(this.saturday)
+ Number(this.sunday) ;
if(count == 1 && this.lastCountDays == 0) {
this.lastCountDays = count ;
boulange_scroll('step-days') ;
}
},
checkProductAvailable: function(product) {
var available = product.active &&
(!this.monday || (this.monday && product.monday)) &&
(!this.tuesday || (this.tuesday && product.tuesday)) &&
(!this.wednesday || (this.wednesday && product.wednesday)) &&
(!this.thursday || (this.thursday && product.thursday)) &&
(!this.friday || (this.friday && product.friday)) &&
(!this.saturday || (this.saturday && product.saturday)) &&
(!this.sunday || (this.sunday && product.sunday)) ;
if(!available) {
product.quantity_form = 0 ;
}
return available ;
},
checkOneProductAvailable: function() {
var count = 0 ;
for(key in this.products) {
if(this.checkProductAvailable(this.products[key])) {
count ++ ;
}
}
return count ;
},
productQuantityClick: function(product, quantity) {
if( this.products[product.index].quantity_form + quantity >= 0) {
this.products[product.index].quantity_form += quantity ;
}
},
oneProductOrdered: function() {
for(var key in this.products) {
if(this.products[key].quantity_form > 0) {
return true ;
}
}
return false ;
},
formatPrice: function(price) {
var isNumberRegExp = new RegExp(/^[-+]?[0-9]+(\.[0-9]+)*$/);
if(isNumberRegExp.test(price) && price > 0) {
return Number(price).toFixed(2).replace('.',',')+' €' ;
}
return '--' ;
},
priceTotal: function(format) {
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 ;
}
}
if(format) {
return this.formatPrice(price) ;
}
else {
return price ;
}
},
formSubmit: function() {
this.checkForm() ;
if(!this.errors.length && !this.disableSubmitButton) {

this.disableSubmitButton = true ;

var productsArray = {} ;
for(var key in this.products) {
if( this.products[key].quantity_form != null &&
this.products[key].quantity_form > 0) {
productsArray['product_'+this.products[key].id] = this.products[key].quantity_form ;
}
}
axios.post('ajax-process', {
idSubscription: this.idSubscription,
SubscriptionForm: {
id_point_sale: this.idPointSaleActive,
date_begin: this.dateBegin ? this.formatDate(this.dateBegin) : '',
date_end: this.dateEnd ? this.formatDate(this.dateEnd) : '',
week_frequency: this.weekFrequency,
auto_payment: this.autoPayment,
monday: this.monday == true ? 1 : 0,
tuesday: this.tuesday == true ? 1 : 0,
wednesday: this.wednesday == true ? 1 : 0,
thursday: this.thursday == true ? 1 : 0,
friday: this.friday == true ? 1 : 0,
saturday: this.saturday == true ? 1 : 0,
sunday: this.sunday == true ? 1 : 0,
products: productsArray
}
}).then(response => {
window.location.href = chat_base_url(true)+'subscription/index' ;
});
}
},
checkForm: function() {
this.errors = [] ;
if(!this.idPointSaleActive) {
this.errors.push('Veuillez sélectionner un point de vente') ;
}
else {
if(this.pointSaleActive.code && this.pointSaleActive.code.length > 0) {
axios.get('ajax-validate-code-point-sale',{params: {
idPointSale: this.idPointSaleActive,
code: this.pointSaleActive.code
}}).then(response => {
if(response.data) {
this.pointsSale[idPointSale].invalid_code = false ;
}
else {
this.pointsSale[idPointSale].invalid_code = true ;
Vue.set(this.pointsSaleCodes, idPointSale, '');
}
}) ;
}
}
var regexDate = /^[0-9]{2}\/[0-9]{2}\/[0-9]{4}$/;
if(!this.dateBegin) {
this.errors.push('Veuillez sélectionner une date de début') ;
}
else {
if(!regexDate.test(this.formatDate(this.dateBegin))) {
this.errors.push('Mauvais format de date de début') ;
}
}
if(this.dateEnd && this.dateEnd.length > 0 && !regexDate.test(this.formatDate(this.dateEnd))) {
this.errors.push('Mauvais format de date de fin') ;
}
if(this.weekFrequency != 1 && this.weekFrequency != 2 &&
this.weekFrequency != 3 && this.weekFrequency != 4) {
this.errors.push('Veuillez sélectionner une périodicité') ;
}
if(!this.monday && !this.tuesday && !this.wednesday && !this.thursday &&
!this.friday && !this.saturday) {
this.errors.push('Veuillez sélectionner un jour de distribution') ;
}
if(!this.oneProductOrdered()) {
this.errors.push('Veuillez choisir au moins un produit') ;
}
if(this.errors.length) {
window.scroll(0, $('#page-title').position().top - 25) ;
}
}
}
});


+ 19
- 4
producer/web/sass/_layout.scss Ver arquivo

@@ -304,7 +304,7 @@ ul.pagination {
}
}
#page-title {
h2#page-title {
padding-left: 15px ;
padding-right: 15px ;
padding-bottom: 15px ;
@@ -315,6 +315,12 @@ ul.pagination {
position: relative ;
top: -10px ;
text-align: center ;
#buttons {
//float: right ;
margin-bottom: 15px ;
font-family: 'Arial' ;
}
}
.container {
@@ -352,9 +358,10 @@ ul.pagination {
font-family: 'myriadpro-light' ;
text-transform: uppercase ;
font-size: 23px ;
padding: 10px 0px 10px 10px ;
color: white ;
text-align: center ;
text-align: left ;
margin-bottom: 30px ;
margin-top: 45px ;
span {
background-color: $color1 ;
padding: 10px 20px ;
@@ -377,6 +384,14 @@ ul.pagination {
h6 {
font-size: 16px ;
}
form {
.form-group {
.hint-block {
color: gray ;
}
}
}
}
}


+ 1
- 1
producer/web/sass/order/_form.scss Ver arquivo

@@ -63,7 +63,7 @@ termes.
}

.ui-datepicker-title {
color: white
color: white ;
}

.ui-datepicker-prev,

+ 1
- 0
producer/web/sass/screen.scss Ver arquivo

@@ -43,4 +43,5 @@ termes.
@import "order/_history.scss";
@import "order/_order.scss";
@import "credit/_add.scss";
@import "subscription/_form.scss";
@import "_responsive.scss";

+ 100
- 0
producer/web/sass/subscription/_form.scss Ver arquivo

@@ -0,0 +1,100 @@

.subscription-create,
.subscription-update {
.subscription-form {
.points-sale {
.locality {
color: gray ;
}
label {
cursor: pointer ;
}
}
.days {
.form-group {
float: left ;
margin-right: 15px ;
}
}
.points-sale {
table {
tr.selected {
td {
background-color: $color2 ;
}
}
.block-code {
width: 150px ;
}
.actions {
width: 150px ;
button {
width: 100% ;
display: block ;
}
}
}
}
.products {
.monday, .tuesday, .wednesday, .thursday,
.friday, .saturday, .sunday, .no-day {
display: none ;
}
.monday-active .monday,
.tuesday-active .tuesday,
.wednesday-active .wednesday,
.thursday-active .thursday,
.friday-active .friday,
.saturday-active .saturday,
.sunday-active .sunday {
display: block ;
}
td.quantity {
width: 150px ;
input {
text-align: center ;
&.has-quantity {
font-weight: bold ;
}
}
}
.name {
font-family: "comfortaalight" ;
font-weight: bold ;
text-transform: uppercase ;
font-size: 18px ;
}

.description {
font-style: italic;
}

.recipe {
font-size: 12px ;
}
.price-unit, .price-total {
text-align: center ;
width: 150px ;
}
tr.total .price-total {
text-align: center ;
font-size: 20px ;
}
}
}
}

Carregando…
Cancelar
Salvar