Explorar el Código

Merge branch 'develop'

master
Guillaume Bourgeois hace 1 año
padre
commit
827824a964
Se han modificado 51 ficheros con 509 adiciones y 223 borrados
  1. +7
    -6
      backend/controllers/DistributionController.php
  2. +3
    -2
      backend/controllers/DocumentController.php
  3. +22
    -49
      backend/controllers/ProducerController.php
  4. +48
    -34
      backend/controllers/ProductController.php
  5. +4
    -2
      backend/controllers/SubscriptionController.php
  6. +5
    -2
      backend/controllers/UserController.php
  7. +1
    -1
      backend/models/CreditForm.php
  8. +2
    -0
      backend/models/MailForm.php
  9. +10
    -10
      backend/views/distribution/index.php
  10. +2
    -2
      backend/views/document/_form.php
  11. +2
    -2
      backend/views/producer/update.php
  12. +2
    -2
      backend/views/product/_form.php
  13. +3
    -2
      backend/views/product/index.php
  14. +7
    -0
      backend/views/user/credit.php
  15. +5
    -3
      backend/web/css/screen.css
  16. +2
    -9
      backend/web/js/backend.js
  17. +19
    -5
      backend/web/js/vuejs/distribution-index.js
  18. +4
    -2
      backend/web/sass/_responsive.scss
  19. +1
    -1
      common/config/params.php
  20. +8
    -2
      common/forms/SubscriptionForm.php
  21. +1
    -1
      common/helpers/Opendistrib.php
  22. +4
    -2
      common/helpers/Upload.php
  23. +23
    -1
      common/logic/AbstractBuilder.php
  24. +12
    -2
      common/logic/AbstractRepository.php
  25. +23
    -0
      common/logic/AbstractRepositoryQuery.php
  26. +12
    -9
      common/logic/Distribution/Distribution/Service/DistributionBuilder.php
  27. +15
    -0
      common/logic/Distribution/ProductDistribution/Service/ProductDistributionBuilder.php
  28. +2
    -1
      common/logic/Document/Invoice/Service/InvoiceSolver.php
  29. +6
    -3
      common/logic/Order/Order/Repository/OrderRepository.php
  30. +1
    -0
      common/logic/Order/Order/Service/OrderBuilder.php
  31. +14
    -1
      common/logic/Payment/Model/Payment.php
  32. +6
    -6
      common/logic/Payment/Service/PaymentBuilder.php
  33. +22
    -16
      common/logic/Payment/Service/PaymentNotifier.php
  34. +14
    -7
      common/logic/Payment/Service/PaymentUtils.php
  35. +2
    -1
      common/logic/PointSale/PointSale/Repository/PointSaleRepositoryQuery.php
  36. +13
    -2
      common/logic/Producer/Producer/Model/Producer.php
  37. +52
    -0
      common/logic/Producer/Producer/Service/ProducerBuilder.php
  38. +13
    -8
      common/logic/Product/Product/Model/Product.php
  39. +6
    -6
      common/logic/Product/Product/Model/ProductSearch.php
  40. +8
    -8
      common/logic/Product/Product/Repository/ProductRepository.php
  41. +1
    -6
      common/logic/Product/Product/Repository/ProductRepositoryQuery.php
  42. +1
    -1
      common/logic/Product/Product/Service/ProductBuilder.php
  43. +8
    -3
      common/logic/Product/Product/Service/ProductSolver.php
  44. +10
    -0
      common/logic/StatusInterface.php
  45. +1
    -0
      common/logic/Subscription/Subscription/Service/SubscriptionBuilder.php
  46. +27
    -0
      common/versions/23.10.A.php
  47. +26
    -0
      console/migrations/m230929_065700_rename_column_product_active_status.php
  48. +26
    -0
      console/migrations/m231002_142915_add_column_payment_summary.php
  49. +1
    -1
      producer/controllers/OrderController.php
  50. +1
    -1
      producer/controllers/SiteController.php
  51. +1
    -1
      producer/web/js/vuejs/subscription-form.js

+ 7
- 6
backend/controllers/DistributionController.php Ver fichero

@@ -117,7 +117,6 @@ class DistributionController extends BackendController
$orderManager = $this->getOrderManager();
$productManager = $this->getProductManager();
$userManager = $this->getUserManager();
$pointSaleManager = $this->getPointSaleManager();

$producer = $this->getProducerCurrent();
$format = 'Y-m-d';
@@ -133,7 +132,7 @@ class DistributionController extends BackendController
$distribution = $distributionManager->createDistributionIfNotExist($date);
$ordersArray = $orderManager->findOrdersByDistribution($distribution);
$ordersArrayObject = $ordersArray;
$productsArray = $productManager->findProductsByDistribution($distribution);
$productsArray = $productManager->findProductsByDistribution($distribution, false);

$json['products'] = $this->buildAjaxInfosResponseProducts($distribution, $productsArray, $ordersArray);
$json['distribution'] = $this->buildAjaxInfosResponseDistribution($distribution, $ordersArrayObject, $productsArray);
@@ -192,8 +191,10 @@ class DistributionController extends BackendController

if (!isset($product->productDistribution[0])) {
$productDistributionAdd = $distributionManager->addProduct($distribution, $product);
$jsonProduct['productDistribution'][0] = $productDistributionAdd->getAttributes();
$product->populateRelation('productDistribution', [$productDistributionAdd]);
if($productDistributionAdd) {
$jsonProduct['productDistribution'][0] = $productDistributionAdd->getAttributes();
$product->populateRelation('productDistribution', [$productDistributionAdd]);
}
}
else {
foreach($product->productDistribution as $key => $productDistribution) {
@@ -201,7 +202,7 @@ class DistributionController extends BackendController
}
}

if (!is_numeric($product->productDistribution[0]->quantity_max)) {
if (!isset($product->productDistribution[0]) || !is_numeric($product->productDistribution[0]->quantity_max)) {
$jsonProduct['quantity_remaining'] = null;
} else {
$jsonProduct['quantity_remaining'] = $product->productDistribution[0]->quantity_max - $quantityOrder;
@@ -356,7 +357,7 @@ class DistributionController extends BackendController
$oneProductUnactivated = false;
foreach ($order->productOrder as $productOrder) {
foreach ($productsArray as $product) {
if ($productOrder->id_product == $product['id'] && !$product['productDistribution'][0]['active']) {
if ($productOrder->id_product == $product['id'] && isset($product['productDistribution'][0]) && !$product['productDistribution'][0]['active']) {
$oneProductUnactivated = true;
}
}

+ 3
- 2
backend/controllers/DocumentController.php Ver fichero

@@ -179,12 +179,13 @@ class DocumentController extends BackendController
if($documentManager->isDocumentInvoice($document) && $documentManager->isStatusValid($document)) {
$payment = $paymentManager->instanciatePayment(
Payment::TYPE_PAYMENT,
number_format($documentManager->getAmountWithTax($document), 3),
number_format($documentManager->getAmountWithTax($document, Order::INVOICE_AMOUNT_TOTAL), 2),
$this->getProducerCurrent(),
null,
null,
MeanPayment::TRANSFER,
null,
null,
$document
);
$payment->amount = number_format($payment->amount, 2);
@@ -578,7 +579,7 @@ class DocumentController extends BackendController

if ($document) {
$ordersArray = [];
$productsArray = $productManager->findProducts();
$productsArray = $productManager->findProducts(false);

foreach ($document->orders as $order) {
$orderManager->initOrder($order);

+ 22
- 49
backend/controllers/ProducerController.php Ver fichero

@@ -47,6 +47,7 @@ use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
use yii\filters\AccessControl;
use common\helpers\Upload;
use yii\web\UploadedFile;

/**
* UserController implements the CRUD actions for User model.
@@ -84,68 +85,40 @@ class ProducerController extends BackendController
*/
public function actionUpdate()
{
$producerManager = $this->getProducerManager();
$producerContainer = $this->getProducerContainer();
$producerBuilder = $producerContainer->getBuilder();
$request = Yii::$app->request;
$model = $this->findModel(GlobalParam::getCurrentProducerId());

$logoFilenameOld = $model->logo;
$photoFilenameOld = $model->photo;
if (strlen($model->option_dashboard_date_start)) {
$model->option_dashboard_date_start = date('d/m/Y', strtotime($model->option_dashboard_date_start));
}
if (strlen($model->option_dashboard_date_end)) {
$model->option_dashboard_date_end = date('d/m/Y', strtotime($model->option_dashboard_date_end));
}
$producerBuilder->initOptionDashboardDatesDisplay($model);

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

if (strlen($model->option_dashboard_date_start)) {
$model->option_dashboard_date_start = date(
'Y-m-d',
strtotime(str_replace('/', '-', $model->option_dashboard_date_start)
));
$model->save();
}

if (strlen($model->option_dashboard_date_end)) {
$model->option_dashboard_date_end = date(
'Y-m-d',
strtotime(str_replace('/', '-', $model->option_dashboard_date_end))
);
$model->save();
}
$model->logoFile = UploadedFile::getInstance($model, 'logoFile');
$model->photoFile = UploadedFile::getInstance($model, 'photoFile');

Upload::uploadFile($model, 'logo', $logoFilenameOld);
Upload::uploadFile($model, 'photo', $photoFilenameOld);
if($model->validate()) {

$deleteLogo = $request->post('delete_logo', 0);
if ($deleteLogo) {
$model->logo = '';
$producerBuilder->processUploadImage($model, 'logo', $logoFilenameOld, $request->post('delete_logo', 0));
$producerBuilder->processUploadImage($model, 'photo', $photoFilenameOld, $request->post('delete_photo', 0));
$producerBuilder->initOptionDashboardDatesBeforeSave($model);
$producerBuilder->savePrivateKeysStripe($model);
$model->save();
}

$deletePhoto = $request->post('delete_photo', 0);
if ($deletePhoto) {
$model->photo = '';
$model->save();
$this->setFlash('success', 'Paramètres mis à jour.');
return $this->redirect(['update', 'id' => $model->id, 'edit_ok' => true]);
}
}

$producerManager->savePrivateKeyApiStripe($model);
$producerManager->savePrivateKeyEndpointStripe($model);

$model->option_stripe_private_key = '';
$model->option_stripe_endpoint_secret = '';
$model->save();

$this->setFlash('success', 'Paramètres mis à jour.');
return $this->redirect(['update', 'id' => $model->id, 'edit_ok' => true]);
} else {
if ($model->load(\Yii::$app->request->post())) {
$this->setFlash('error', 'Le formulaire comporte des erreurs.');
}
return $this->render('update', [
'model' => $model,
]);
if ($model->load(\Yii::$app->request->post())) {
$this->setFlash('error', 'Le formulaire comporte des erreurs.');
}

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

/**

+ 48
- 34
backend/controllers/ProductController.php Ver fichero

@@ -114,7 +114,7 @@ class ProductController extends BackendController

$model = $productManager->instanciateProduct();

$model->active = 1;
$model->status = Product::STATUS_ONLINE;
$model->id_producer = GlobalParam::getCurrentProducerId();
$model->monday = 1;
$model->tuesday = 1;
@@ -125,27 +125,33 @@ class ProductController extends BackendController
$model->sunday = 1;
$model->available_on_points_sale = 1;

if ($model->load(\Yii::$app->request->post()) && $productManager->saveCreate($model)) {
if ($model->load(\Yii::$app->request->post())) {

$lastProductOrder = Product::find()->where('id_producer = :id_producer')->params([':id_producer' => GlobalParam::getCurrentProducerId()])->orderBy('order DESC')->one();
if ($lastProductOrder) {
$model->order = ++$lastProductOrder->order;
}
$model->photoFile = UploadedFile::getInstance($model, 'photoFile');
if($model->validate()) {

Upload::uploadFile($model, 'photo');
$productManager->saveUpdate($model);
$lastProductOrder = Product::find()->where('id_producer = :id_producer')->params([':id_producer' => GlobalParam::getCurrentProducerId()])->orderBy('order DESC')->one();
if ($lastProductOrder) {
$model->order = ++$lastProductOrder->order;
}
$productManager->create($model);

$this->processAvailabilityPointsSale($model);
$distributionManager->addProductIncomingDistributions($model);
if($model->photoFile) {
Upload::uploadFile($model, 'photoFile', 'photo');
}

$this->setFlash('success', 'Produit <strong>' . Html::encode($model->name) . '</strong> ajouté');
$this->processAvailabilityPointsSale($model);
$distributionManager->addProductIncomingDistributions($model);

return $this->redirect(['index']);
} else {
return $this->render('create', [
'model' => $model,
]);
$this->setFlash('success', 'Produit <strong>' . Html::encode($model->name) . '</strong> ajouté');

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

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

/**
@@ -165,24 +171,30 @@ class ProductController extends BackendController

$photoFilenameOld = $model->photo;

if ($model->load(\Yii::$app->request->post()) && $productManager->saveUpdate($model)) {
if (Yii::$app->request->isPost && $model->load(\Yii::$app->request->post())) {

Upload::uploadFile($model, 'photo', $photoFilenameOld);
$model->photoFile = UploadedFile::getInstance($model, 'photoFile');

$deletePhoto = $request->post('delete_photo', 0);
if ($deletePhoto) {
$model->photo = '';
$model->save();
}
if($model->validate()) {
if($model->photoFile) {
Upload::uploadFile($model, 'photoFile', 'photo', $photoFilenameOld);
}

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

if ($model->apply_distributions) {
$distributionManager->addProductIncomingDistributions($model);
}
$this->processAvailabilityPointsSale($model);
if ($model->apply_distributions) {
$distributionManager->addProductIncomingDistributions($model);
}
$productManager->update($model);

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

return $this->render('update/update', [
@@ -310,11 +322,13 @@ class ProductController extends BackendController
*/
public function actionDelete(int $id, bool $confirm = false)
{
$productContainer = $this->getProductContainer();
$productDistributionContainer = $this->getProductDistributionContainer();
$product = $this->findModel($id);

if ($confirm) {
$product->delete();
ProductDistribution::deleteAll(['id_product' => $id]);
$productContainer->getBuilder()->updateStatusDeleted($product);
$productDistributionContainer->getBuilder()->disableProductDistributionsIncomingByProduct($product);

$this->setFlash('success', 'Produit <strong>' . Html::encode($product->name) . '</strong> supprimé');
} else {
@@ -340,19 +354,19 @@ class ProductController extends BackendController
}
}

public function actionAjaxToggleActive($id, $active)
public function actionAjaxToggleStatus($id, $status)
{
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

$distributionManager = $this->getDistributionManager();

$product = $this->findModel($id);
$product->active = (int) $active;
$product->status = (int) $status;
$product->save();

$distributionManager->addProductIncomingDistributions($product);

return ['success', 'id' => $id, 'active' => $active];
return ['success', 'id' => $id, 'status' => $status];
}

/**

+ 4
- 2
backend/controllers/SubscriptionController.php Ver fichero

@@ -152,8 +152,8 @@ class SubscriptionController extends BackendController
$subscriptionManager = $this->getSubscriptionManager();
$productSubscriptionManager = $this->getProductSubscriptionManager();
$productManager = $this->getProductManager();
$orderManager = $this->getOrderManager();
$distributionManager = $this->getDistributionManager();
$orderManager = $this->getOrderManager();

$model = new SubscriptionForm;
$model->isAdmin = true;
@@ -281,7 +281,9 @@ class SubscriptionController extends BackendController
$productManager = $this->getProductManager();

$productsQuery = Product::find()
->where(['id_producer' => GlobalParam::getCurrentProducerId(),]);
->where(['id_producer' => GlobalParam::getCurrentProducerId()])
->andWhere('status >= :status')
->addParams(['status' => Product::STATUS_OFFLINE]);

if ($idSubscription) {
$productsQuery->joinWith(['productSubscription' => function ($query) use ($idSubscription) {

+ 5
- 2
backend/controllers/UserController.php Ver fichero

@@ -402,14 +402,17 @@ class UserController extends BackendController
if ($creditForm->load(\Yii::$app->request->post()) && $creditForm->validate()) {

$paymentContainer->getUtils()
->creditOrDebitUser($creditForm->type, $user, $creditForm->amount, $creditForm->mean_payment, $user);
->creditOrDebitUser($creditForm->type, $user, $creditForm->amount, $creditForm->mean_payment, $this->getUserCurrent(), $creditForm->comment);

if($creditForm->send_mail) {
$paymentContainer->getNotifier()
->notifyUserCreditMovement($user, $creditForm->type, $creditForm->amount);
if(!$user->email) {
$this->addFlash('error', "L'utilisateur n'a pas pu être prévenu car son adresse email n'est pas définie.");
}
}

$this->setFlash('success', 'Crédit mis à jour.');
$this->addFlash('success', 'Crédit mis à jour.');

return $this->refresh();
}

+ 1
- 1
backend/models/CreditForm.php Ver fichero

@@ -103,7 +103,7 @@ class CreditForm extends Model

if ($this->validate()) {
$user = $userManager->findOneUserById($this->id_user);
$paymentManager->creditOrDebitUser($this->type, $user, $this->amount, $this->mean_payment, $userManager->getCurrent());
$paymentManager->creditOrDebitUser($this->type, $user, $this->amount, $this->mean_payment, $userManager->getCurrent(), $this->comment);
// on prévient l'utilisateur que son compte vient d'être crédité
if($this->send_mail) {

+ 2
- 0
backend/models/MailForm.php Ver fichero

@@ -128,6 +128,8 @@ class MailForm extends Model
->where([
'id_producer' => GlobalParam::getCurrentProducerId(),
])
->andWhere('status >= :status')
->addParams(['status' => Product::STATUS_OFFLINE])
->innerJoinWith(['productDistribution' => function($query) use($distribution) {
$query->andOnCondition([
'product_distribution.id_distribution' => $distribution->id,

+ 10
- 10
backend/views/distribution/index.php Ver fichero

@@ -128,11 +128,11 @@ $this->setPageTitle('Distributions') ;
</tr>
</thead>
<tbody>
<tr v-for="product in products">
<tr v-for="product in products" v-if="getProductDistribution(product)">
<td>
<button class="btn btn-success" v-if="product.productDistribution[0].active == 1"><span class="glyphicon glyphicon-ok"></span></button>
<button class="btn btn-success" v-if="getProductDistribution(product).active == 1"><span class="glyphicon glyphicon-ok"></span></button>
<button class="btn btn-default" v-else data-active-product="1" :data-id-product="product.id" @click="productActiveClick"><span class="glyphicon glyphicon-ok"></span></button>
<button class="btn btn-danger" v-if="product.productDistribution[0].active == 0"><span class="glyphicon glyphicon-remove"></span></button>
<button class="btn btn-danger" v-if="getProductDistribution(product).active == 0"><span class="glyphicon glyphicon-remove"></span></button>
<button class="btn btn-default" v-else data-active-product="0" :data-id-product="product.id" @click="productActiveClick"><span class="glyphicon glyphicon-remove"></span></button>
</td>
<td>{{ product.name }}</td>
@@ -142,7 +142,7 @@ $this->setPageTitle('Distributions') ;
</td>
<td class="quantity-max">
<div class="input-group">
<input type="text" class="form-control quantity-max" placeholder="&infin;" :data-id-product="product.id" v-model="product.productDistribution[0].quantity_max" @keyup="productQuantityMaxChange" />
<input type="text" class="form-control quantity-max" placeholder="&infin;" :data-id-product="product.id" v-model="getProductDistribution(product).quantity_max" @keyup="productQuantityMaxChange" />
<span class="input-group-addon">{{ (product.unit == 'piece') ? 'p.' : ' '+((product.unit == 'g' || product.unit == 'kg') ? 'kg' : 'litre(s)') }}</span>
</div>
</td>
@@ -392,7 +392,7 @@ $this->setPageTitle('Distributions') ;
<a href="javascript:void(0);" @click="orderPaymentModalClick" :data-id-order="order.id">
<order-state-payment :order="order" :producer="producer"></order-state-payment>
</a>
<span class="glyphicon glyphicon-time" title="Débit automatique du crédit la veille de la distribution" v-if="order.auto_payment && (order.amount_paid == 0 || order.amount_paid < order.amount)"></span>
<span class="glyphicon glyphicon-time" title="Débit automatique du crédit la veille de la distribution" v-if="order.amount != 0 && order.auto_payment && (order.amount_paid == 0 || order.amount_paid < order.amount)"></span>
</td>
<td class="column-credit" v-if="!idActivePointSale || (pointSaleActive && pointSaleActive.credit == 1)">
<template v-if="order.isCreditContext">
@@ -613,8 +613,8 @@ $this->setPageTitle('Distributions') ;
<td colspan="6">
<strong><span class="glyphicon glyphicon-menu-right"></span> Produits</strong>
<ul>
<li v-for="product in products" v-if="order.productOrder[product.id].quantity > 0">
{{ product.name }} : {{ order.productOrder[product.id].quantity }} {{ order.productOrder[product.id].unit == 'piece' ? ' pièce(s)' : ' '+order.productOrder[product.id].unit }} <span v-if="product.productDistribution[0].active == 0" class="glyphicon glyphicon-warning-sign" title="Ce produit n'est pas activé"></span>
<li v-for="product in products" v-if="getProductDistribution(product) && order.productOrder[product.id].quantity > 0">
{{ product.name }} : {{ order.productOrder[product.id].quantity }} {{ order.productOrder[product.id].unit == 'piece' ? ' pièce(s)' : ' '+order.productOrder[product.id].unit }} <span v-if="getProductDistribution(product).active == 0" class="glyphicon glyphicon-warning-sign" title="Ce produit n'est pas activé"></span>
</li>
</ul>
<div v-if="order.comment && order.comment.length > 0" class="comment">
@@ -720,7 +720,7 @@ $this->setPageTitle('Distributions') ;
</tr>
</thead>
<tbody>
<tr v-for="product in products" :class="(order.productOrder[product.id].quantity > 0) ? 'product-ordered' : ''">
<tr v-for="product in products" v-if="product.status >= 0 || order.productOrder[product.id].quantity > 0" :class="(order.productOrder[product.id].quantity > 0) ? 'product-ordered' : ''">
<td>
<span class="label label-success" v-if="loadingUpdateProductOrder || order.productOrder[product.id].active">Actif</span>
<span class="label label-danger" v-else>Inactif</span>
@@ -768,11 +768,11 @@ $this->setPageTitle('Distributions') ;
</div>
<div slot="footer">
<div class="actions-form">
<button class="modal-default-button btn btn-danger" @click="$emit('close')">Fermer</button>

<button class="modal-default-button btn btn-primary" @click="submitFormUpdate" v-if="order.id">Modifier</button>
<button class="modal-default-button btn btn-primary" @click="submitFormCreate" v-if="!order.id">Créer</button>

<button class="modal-default-button btn btn-danger" @click="$emit('close')">Fermer</button>

<div class="right">
<button class="modal-default-button btn btn-info btn-update-prices" @click="updateProductOrderPrices(true)">Recharger les prix</button>
<button v-if="order.id" class="modal-default-button btn btn-info btn-update-prices" @click="updateInvoicePrices(true)">

+ 2
- 2
backend/views/document/_form.php Ver fichero

@@ -246,7 +246,7 @@ $documentClass = $documentManager->getClass($model);

<?php if ($action == 'update' && $documentClass == 'Invoice'): ?>

<?= $this->render('form/_payment', ['model' => $model]); ?>
<?= $this->render('form/_payment', ['model' => $model, 'payment' => $payment]); ?>

<div v-if="(deliveryNoteUpdateArray && deliveryNoteUpdateArray.length > 0) || (deliveryNoteCreateArray && deliveryNoteCreateArray.length > 0)">
<div class="panel panel-default">
@@ -311,7 +311,7 @@ $documentClass = $documentManager->getClass($model);
<select class="form-control" v-model="productAddId"
@change="changeProductAdd">
<option value="0" selected="selected">--</option>
<option v-for="product in productsArray" :value="product.id">
<option v-for="product in productsArray" v-if="product.status >= 0" :value="product.id">
{{ product.name }}
</option>
</select>

+ 2
- 2
backend/views/producer/update.php Ver fichero

@@ -100,14 +100,14 @@ $this->addBreadcrumb($this->getTitle());

<h4>Apparence</h4>
<?= $form->field($model, 'background_color_logo') ?>
<?= $form->field($model, 'logo')->fileInput() ?>
<?= $form->field($model, 'logoFile')->fileInput() ?>
<?php
if (strlen($model->logo)) {
echo '<img src="' . Yii::$app->urlManagerProducer->getHostInfo() . '/' . Yii::$app->urlManagerProducer->baseUrl . '/uploads/' . $model->logo . '" width="200px" /><br />';
echo '<input type="checkbox" name="delete_logo" id="delete_logo" /> <label for="delete_logo">Supprimer le logo</label><br /><br />';
}
?>
<?= $form->field($model, 'photo')->fileInput()->hint('Format idéal : 900 x 150 px') ?>
<?= $form->field($model, 'photoFile')->fileInput()->hint('Format idéal : 900 x 150 px') ?>
<?php
if (strlen($model->photo)) {
echo '<img src="' . Yii::$app->urlManagerProducer->getHostInfo() . '/' . Yii::$app->urlManagerProducer->baseUrl . '/uploads/' . $model->photo . '" width="400px" /><br />';

+ 2
- 2
backend/views/product/_form.php Ver fichero

@@ -22,7 +22,7 @@ $taxRateManager = $this->getTaxRateManager();

<div>
<div class="col-md-8">
<?= $form->field($model, 'active')->radioList([1 => 'Oui', 0 => 'Non']) ?>
<?= $form->field($model, 'status')->radioList([1 => 'Oui', 0 => 'Non']) ?>
<?= $form->field($model, 'name')->textInput(['maxlength' => 255]) ?>
<?= $form->field($model, 'reference')->textInput(['maxlength' => 255]) ?>
<?= $form->field($model, 'id_product_category')->dropDownList($productCategoryManager->populateProductCategoriesDropdownList()); ?>
@@ -115,7 +115,7 @@ $taxRateManager = $this->getTaxRateManager();
?>
</div>
<div class="col-md-4">
<?= $form->field($model, 'photo')->fileInput() ?>
<?= $form->field($model, 'photoFile')->fileInput() ?>
<?php
if (strlen($model->photo)) {
echo '<img class="photo-product" src="' . Image::getThumbnailSmall($model->photo, true). '" width="200px" /><br />';

+ 3
- 2
backend/views/product/index.php Ver fichero

@@ -135,7 +135,8 @@ $this->addButton(['label' => 'Nouveau produit <span class="glyphicon glyphicon-p
}
],
[
'attribute' => 'active',
'attribute' => 'status',
'label' => 'Actif',
'headerOptions' => ['class' => 'active column-hide-on-mobile'],
'filterOptions' => ['class' => 'column-hide-on-mobile'],
'contentOptions' => ['class' => 'center column-hide-on-mobile'],
@@ -145,7 +146,7 @@ $this->addButton(['label' => 'Nouveau produit <span class="glyphicon glyphicon-p
return Toggle::widget(
[
'name' => 'active',
'checked' => $model->active,
'checked' => $model->status,
'options' => [
'data-id' => $model->id,
'data-on' => 'Oui',

+ 7
- 0
backend/views/user/credit.php Ver fichero

@@ -163,6 +163,13 @@ $this->addBreadcrumb('Créditer') ;
return '';
}
],
[
'label' => 'Commentaire',
'format' => 'raw',
'value' => function ($model) {
return nl2br($model->comment);
}
],
],
]); ?>
</div>

+ 5
- 3
backend/web/css/screen.css Ver fichero

@@ -2897,14 +2897,16 @@ termes.
/* line 148, ../sass/_responsive.scss */
.distribution-index #orders table button.dropdown-toggle,
.distribution-index #orders table button.btn-moins,
.distribution-index #orders table button.btn-plus {
padding: 15px;
.distribution-index #orders table button.btn-plus,
.distribution-index #orders table .btn {
padding: 10px;
}
/* line 155, ../sass/_responsive.scss */
/* line 156, ../sass/_responsive.scss */
.distribution-index #orders table .column-origin,
.distribution-index #orders table .column-point-sale,
.distribution-index #orders table .column-state-payment,
.distribution-index #orders table .column-payment,
.distribution-index #orders table .column-credit,
.distribution-index #orders table .column-tiller,
.distribution-index #orders table .column-delivery-note {
display: none;

+ 2
- 9
backend/web/js/backend.js Ver fichero

@@ -134,17 +134,10 @@ function opendistrib_product_index() {
$('body.product-index .toggle input').change(function() {
var id = $(this).data('id');
var checked = $(this).prop('checked');

var active = 0;
if(checked) {
active = 1;
}

$.get(UrlManager.getBaseUrl() + 'product/ajax-toggle-active', {
$.get(UrlManager.getBaseUrl() + 'product/ajax-toggle-status', {
id: id,
active: active
status: checked ? 1 : 0
});

})
}


+ 19
- 5
backend/web/js/vuejs/distribution-index.js Ver fichero

@@ -260,7 +260,7 @@ var app = new Vue({
initCountActiveProducts: function () {
this.countActiveProducts = 0;
for (var i = 0; i < this.products.length; i++) {
if (this.products[i].productDistribution[0].active == 1) {
if (this.products[i].productDistribution && this.products[i].productDistribution[0].active == 1) {
this.countActiveProducts++;
}
}
@@ -324,7 +324,7 @@ var app = new Vue({
});

for (i = 0; i < this.products.length; i++) {
if (this.products[i].id == idProduct) {
if (this.products[i].productDistribution && this.products[i].id == idProduct) {
this.products[i].productDistribution[0].active = activeProduct;
}
}
@@ -340,9 +340,11 @@ var app = new Vue({
return false;
},
isProductMaximumQuantityExceeded: function (product) {
return product.productDistribution[0].quantity_max
return
this.getProductDistribution(product)
&& this.getProductDistribution(product).quantity_max
&& product.quantity_ordered
&& product.quantity_ordered > product.productDistribution[0].quantity_max;
&& product.quantity_ordered > this.getProductDistribution(product).quantity_max;
},
pointSaleActiveClick: function (event) {
var idPointSale = event.currentTarget.getAttribute('data-id-point-sale');
@@ -923,6 +925,13 @@ var app = new Vue({
},
getUnitCoefficient: function(unit) {
return this.units[unit].coefficient;
},
getProductDistribution: function(product) {
if(typeof product.productDistribution !== 'undefined' && product.productDistribution[0]) {
return product.productDistribution[0];
}

return null;
}
},
});
@@ -1157,7 +1166,7 @@ Vue.component('order-form', {
productQuantityOrder += this.getProductQuantityProductOrder(this.order, product);
}

quantityRemaining = product.productDistribution[0].quantity_max - productQuantityOrder;
quantityRemaining = this.getProductDistribution(product).quantity_max - productQuantityOrder;
if(unit != 'piece') {
quantityRemaining = quantityRemaining.toFixed(2);
}
@@ -1172,6 +1181,11 @@ Vue.component('order-form', {
},
getUnitCoefficient: function(unit) {
return this.units[unit].coefficient;
},
getProductDistribution: function(product) {
if(typeof product.productDistribution !== 'undefined' && product.productDistribution[0]) {
return product.productDistribution[0];
}
}
}
});

+ 4
- 2
backend/web/sass/_responsive.scss Ver fichero

@@ -147,8 +147,9 @@ termes.

button.dropdown-toggle,
button.btn-moins,
button.btn-plus {
padding: 15px;
button.btn-plus,
.btn {
padding: 10px;
}

//.column-checkbox,
@@ -159,6 +160,7 @@ termes.
//.column-amount,
.column-state-payment,
.column-payment,
.column-credit,
.column-tiller,
//.column-actions,
.column-delivery-note {

+ 1
- 1
common/config/params.php Ver fichero

@@ -37,7 +37,7 @@
*/

return [
'version' => '23.9.E',
'version' => '23.10.A',
'siteName' => 'Opendistrib',
'adminEmail' => 'contact@opendistrib.net',
'supportEmail' => 'contact@opendistrib.net',

+ 8
- 2
common/forms/SubscriptionForm.php Ver fichero

@@ -41,6 +41,7 @@ namespace common\forms;
use common\logic\Product\Product\Model\Product;
use common\logic\Subscription\ProductSubscription\Model\ProductSubscription;
use common\logic\Subscription\Subscription\Model\Subscription;
use common\logic\Subscription\Subscription\Wrapper\SubscriptionManager;
use Yii;
use yii\base\Model;

@@ -115,11 +116,13 @@ class SubscriptionForm extends Model
*/
public function save()
{
$subscriptionManager = SubscriptionManager::getInstance();

if ($this->id) {
$subscription = Subscription::searchOne(['id' => $this->id]) ;
}
else {
$subscription = new Subscription ;
$subscription = $subscriptionManager->instanciateSubscription() ;
}

if ($subscription) {
@@ -147,7 +150,10 @@ class SubscriptionForm extends Model
$subscription->saturday = $this->saturday;
$subscription->sunday = $this->sunday;
$subscription->week_frequency = $this->week_frequency;
$subscription->auto_payment = Subscription::AUTO_PAYMENT_DEDUCTED;
$subscription->auto_payment = $this->auto_payment;
if(is_null($subscription->auto_payment)) {
$subscription->auto_payment = Subscription::AUTO_PAYMENT_DEDUCTED;
}
$subscription->comment = $this->comment;

$subscription->save();

+ 1
- 1
common/helpers/Opendistrib.php Ver fichero

@@ -56,7 +56,7 @@ class Opendistrib
}
}

rsort($versionsArray);
rsort($versionsArray, SORT_NATURAL);

return $versionsArray;
}

+ 4
- 2
common/helpers/Upload.php Ver fichero

@@ -43,9 +43,9 @@ use Yii;

class Upload
{
public static function uploadFile($model, $champs, $filename_old = '')
public static function uploadFile($model, $champsFile, $champs, $filename_old = '')
{
$file = UploadedFile::getInstance($model, $champs);
$file = $model->$champsFile;
if ($file) {
$file_name = $file->baseName . '-' . uniqid();
$file_name_extension = $file_name . '.' . $file->extension;
@@ -79,6 +79,8 @@ class Upload
$model->$champs = $filename_old;
}

$model->$champsFile = null;

$model->save();
}
}

+ 23
- 1
common/logic/AbstractBuilder.php Ver fichero

@@ -37,4 +37,26 @@ abstract class AbstractBuilder extends AbstractService implements BuilderInterfa
{
return $model->save();
}
}

/**
* Status
*/

public function updateStatusOnline(Model $model)
{
$model->status = StatusInterface::STATUS_ONLINE;
$this->update($model);
}

public function updateStatusOffline(Model $model)
{
$model->status = StatusInterface::STATUS_OFFLINE;
$this->update($model);
}

public function updateStatusDeleted(Model $model)
{
$model->status = StatusInterface::STATUS_DELETED;
$this->update($model);
}
}

+ 12
- 2
common/logic/AbstractRepository.php Ver fichero

@@ -26,10 +26,12 @@ abstract class AbstractRepository extends AbstractService implements RepositoryI
return $this->query;
}

public function createDefaultQuery(): RepositoryQueryInterface
public function createDefaultQuery(bool $filterStatus = true): RepositoryQueryInterface
{
$this->createQuery();

if($filterStatus) {
$this->defaultStatus();
}
$this->defaultWith();
$this->defaultJoinWith();
$this->defaultFilterProducerContext();
@@ -38,6 +40,14 @@ abstract class AbstractRepository extends AbstractService implements RepositoryI
return $this->query;
}

public function defaultStatus(): void
{
$class = new \ReflectionClass($this->query->getDefinition()->getEntityFqcn());
if($class->implementsInterface('common\logic\StatusInterface')) {
$this->query->filterIsStatusOnlineAndOffline();
}
}

public function defaultWith(): void
{
$defaultOptions = $this->getDefaultOptionsSearch();

+ 23
- 0
common/logic/AbstractRepositoryQuery.php Ver fichero

@@ -16,6 +16,11 @@ abstract class AbstractRepositoryQuery extends AbstractService implements Reposi
$this->definition = $this->loadService($serviceClass);
}

public function getDefinition()
{
return $this->definition;
}

public function baseQuery(): ActiveQuery
{
$class = $this->definition->getEntityFqcn();
@@ -76,6 +81,24 @@ abstract class AbstractRepositoryQuery extends AbstractService implements Reposi
return $this;
}

public function filterIsStatusOnline()
{
$this->andWhere(['status' => StatusInterface::STATUS_ONLINE]);
return $this;
}

public function filterIsStatusOnlineAndOffline()
{
$this->andWhere('status >= :status')->addParams(['status' => StatusInterface::STATUS_OFFLINE]);
return $this;
}

public function filterIsStatusDeleted()
{
$this->andWhere(['status' => StatusInterface::STATUS_DELETED]);
return $this;
}

public function getDataProvider(int $pageSize): ActiveDataProvider
{
return new ActiveDataProvider([

+ 12
- 9
common/logic/Distribution/Distribution/Service/DistributionBuilder.php Ver fichero

@@ -17,6 +17,7 @@ use common\logic\Order\ProductOrder\Service\ProductOrderBuilder;
use common\logic\PointSale\PointSale\Model\PointSale;
use common\logic\Product\Product\Model\Product;
use common\logic\Product\Product\Repository\ProductRepository;
use common\logic\Product\Product\Service\ProductSolver;
use common\logic\User\UserProducer\Repository\UserProducerRepository;

class DistributionBuilder extends AbstractBuilder
@@ -31,6 +32,7 @@ class DistributionBuilder extends AbstractBuilder
protected OrderRepository $orderRepository;
protected UserProducerRepository $userProducerRepository;
protected ProductOrderBuilder $productOrderBuilder;
protected ProductSolver $productSolver;

public function loadDependencies(): void
{
@@ -44,6 +46,7 @@ class DistributionBuilder extends AbstractBuilder
$this->orderRepository = $this->loadService(OrderRepository::class);
$this->userProducerRepository = $this->loadService(UserProducerRepository::class);
$this->productOrderBuilder = $this->loadService(ProductOrderBuilder::class);
$this->productSolver = $this->loadService(ProductSolver::class);
}

public function instanciateDistribution(string $date, bool $delivery = true): Distribution
@@ -57,13 +60,10 @@ class DistributionBuilder extends AbstractBuilder
return $distribution;
}

// initDistribution
public function createDistribution(string $date, bool $delivery = true): Distribution
{
$distribution = $this->instanciateDistribution($date, $delivery);

$this->saveCreate($distribution);

$this->create($distribution);
$this->createPointSaleDistributions($distribution);
$this->createProductDistributions($distribution);

@@ -99,13 +99,16 @@ class DistributionBuilder extends AbstractBuilder
/**
* Ajoute un produit à une distribution.
*/
public function addProduct(Distribution $distribution, Product $product): ProductDistribution
public function addProduct(Distribution $distribution, Product $product): ?ProductDistribution
{
$productDistribution = $this->productDistributionBuilder->createProductDistributionIfNotExist($distribution, $product);
$this->productDistributionBuilder->updateProductDistribution($productDistribution);
$this->updateOrderProductPrices($distribution, $product);
if($this->productSolver->isStatusOnlineOrOffline($product)) {
$productDistribution = $this->productDistributionBuilder->createProductDistributionIfNotExist($distribution, $product);
$this->productDistributionBuilder->updateProductDistribution($productDistribution);
$this->updateOrderProductPrices($distribution, $product);
return $productDistribution;
}

return $productDistribution;
return null;
}

/**

+ 15
- 0
common/logic/Distribution/ProductDistribution/Service/ProductDistributionBuilder.php Ver fichero

@@ -4,6 +4,7 @@ namespace common\logic\Distribution\ProductDistribution\Service;

use common\logic\AbstractBuilder;
use common\logic\Distribution\Distribution\Model\Distribution;
use common\logic\Distribution\Distribution\Repository\DistributionRepository;
use common\logic\Distribution\Distribution\Service\DistributionSolver;
use common\logic\Distribution\ProductDistribution\Model\ProductDistribution;
use common\logic\Distribution\ProductDistribution\Repository\ProductDistributionRepository;
@@ -15,12 +16,14 @@ class ProductDistributionBuilder extends AbstractBuilder
protected ProductDistributionRepository $productDistributionRepository;
protected DistributionSolver $distributionSolver;
protected ProductSolver $productSolver;
protected DistributionRepository $distributionRepository;

public function loadDependencies(): void
{
$this->productDistributionRepository = $this->loadService(ProductDistributionRepository::class);
$this->distributionSolver = $this->loadService(DistributionSolver::class);
$this->productSolver = $this->loadService(ProductSolver::class);
$this->distributionRepository = $this->loadService(DistributionRepository::class);
}

public function instanciateProductDistribution(Distribution $distribution, Product $product): ProductDistribution
@@ -96,4 +99,16 @@ class ProductDistributionBuilder extends AbstractBuilder
$productDistribution->active = $active;
$this->update($productDistribution);
}

public function disableProductDistributionsIncomingByProduct(Product $product)
{
$distributionsIncomingArray = $this->distributionRepository->findDistributionsIncoming(true);
foreach($distributionsIncomingArray as $distribution) {
ProductDistribution::updateAll([
'id_product' => $product->id,
'id_distribution' => $distribution->id,
'active' => false
]);
}
}
}

+ 2
- 1
common/logic/Document/Invoice/Service/InvoiceSolver.php Ver fichero

@@ -5,6 +5,7 @@ namespace common\logic\Document\Invoice\Service;
use common\helpers\Price;
use common\logic\Document\Document\Service\DocumentSolver;
use common\logic\Document\Invoice\Model\Invoice;
use common\logic\Order\Order\Model\Order;

class InvoiceSolver extends DocumentSolver
{
@@ -21,6 +22,6 @@ class InvoiceSolver extends DocumentSolver

public function isInvoicePaid(Invoice $invoice): bool
{
return $this->getInvoiceAmountPaid($invoice) >= Price::numberTwoDecimals($this->getAmountWithTax($invoice));
return $this->getInvoiceAmountPaid($invoice) >= Price::numberTwoDecimals($this->getAmountWithTax($invoice, Order::INVOICE_AMOUNT_TOTAL));
}
}

+ 6
- 3
common/logic/Order/Order/Repository/OrderRepository.php Ver fichero

@@ -543,10 +543,10 @@ class OrderRepository extends AbstractRepository
$titleLabel = '';

if(!$amountPaid) {
if($isOrderPaid) {
if($isOrderPaid && $amountTotal != 0) {
$label = 'Facture payée';
}
elseif($this->isCreditAutoPayment($order)) {
elseif($this->isCreditAutoPayment($order) && $amountTotal != 0) {
if($order->subscription && $order->subscription->auto_payment == 0) {
$label = 'Crédit désactivé';
}
@@ -554,6 +554,9 @@ class OrderRepository extends AbstractRepository
$label = 'Crédit non débité';
}
}
elseif($amountTotal == 0) {
$label = 'Gratuit';
}
else {
$label = 'Non réglé';
}
@@ -578,7 +581,7 @@ class OrderRepository extends AbstractRepository
$classLabel = 'warning';
$titleLabel = 'Paiement en surplus';
}
elseif($isOrderPaid) {
elseif(($isOrderPaid && $amountTotal != 0) || $amountTotal == 0) {
$classLabel = 'success';
}
elseif($orderPaymentStatus == Order::PAYMENT_UNPAID) {

+ 1
- 0
common/logic/Order/Order/Service/OrderBuilder.php Ver fichero

@@ -451,6 +451,7 @@ class OrderBuilder extends AbstractBuilder
$order->user,
$this->userSolver->getCurrent(),
MeanPayment::CREDIT,
null,
$order
);
}

+ 14
- 1
common/logic/Payment/Model/Payment.php Ver fichero

@@ -73,7 +73,7 @@ class Payment extends ActiveRecordCommon
[['amount'], 'double'],
[['date_transaction'], 'date', 'format' => 'php:Y-m-d'],
[['type', 'mean_payment'], 'string', 'max' => 255],
[['comment'], 'string', 'max' => 2048],
[['comment', 'summary'], 'string', 'max' => 2048],
];
}

@@ -94,6 +94,7 @@ class Payment extends ActiveRecordCommon
'id_producer' => 'Producteur',
'mean_payment' => 'Moyen de paiement',
'comment' => 'Commentaire',
'summary' => 'Résumé',
'date_transaction' => 'Date transaction'
];
}
@@ -288,4 +289,16 @@ class Payment extends ActiveRecordCommon

return $this;
}

public function getSummary(): ?string
{
return $this->summary;
}

public function setSummary(?string $summary): self
{
$this->summary = $summary;

return $this;
}
}

+ 6
- 6
common/logic/Payment/Service/PaymentBuilder.php Ver fichero

@@ -28,6 +28,7 @@ class PaymentBuilder extends AbstractBuilder
User $user = null,
User $userAction = null,
string $meanPayment = null,
string $comment = null,
Order $order = null,
Invoice $invoice = null
): Payment
@@ -37,6 +38,8 @@ class PaymentBuilder extends AbstractBuilder
$payment->type = $type;
$payment->amount = round($amount, 2);
$payment->populateProducer($producer);
$payment->setMeanPayment($meanPayment);
$payment->setComment($comment);

if($user) {
$payment->populateUser($user);
@@ -54,10 +57,6 @@ class PaymentBuilder extends AbstractBuilder
$payment->populateInvoice($invoice);
}

if($meanPayment) {
$payment->mean_payment = $meanPayment;
}

return $payment;
}

@@ -68,6 +67,7 @@ class PaymentBuilder extends AbstractBuilder
User $user = null,
User $userAction = null,
string $meanPayment = null,
string $comment = null,
Order $order = null,
Invoice $invoice = null
): ?Payment
@@ -76,8 +76,8 @@ class PaymentBuilder extends AbstractBuilder
return null;
}

$payment = $this->instanciatePayment($type, $amount, $producer, $user, $userAction, $meanPayment, $order, $invoice);
$payment->setComment($payment->getComment() . $this->orderSolver->getPaymentComment($payment));
$payment = $this->instanciatePayment($type, $amount, $producer, $user, $userAction, $meanPayment, $comment, $order, $invoice);
$payment->setSummary($this->orderSolver->getPaymentComment($payment));
$this->create($payment);

return $payment;

+ 22
- 16
common/logic/Payment/Service/PaymentNotifier.php Ver fichero

@@ -18,21 +18,27 @@ class PaymentNotifier extends AbstractNotifier

public function notifyUserCreditMovement(User $user, string $type, float $amount)
{
$producer = $this->getProducerContext();
$credit = $this->userRepository->getCredit($user, true);

$this->mailer->sendFromProducer(
'Mouvement de crédit',
'creditUser',
[
'user' => $user,
'producer' => $producer,
'credit' => $credit,
'type' => $type,
'amount' => $amount
],
$user->email,
$producer
);
if($user->email) {
$producer = $this->getProducerContext();
$credit = $this->userRepository->getCredit($user, true);

$this->mailer->sendFromProducer(
'Mouvement de crédit',
'creditUser',
[
'user' => $user,
'producer' => $producer,
'credit' => $credit,
'type' => $type,
'amount' => $amount
],
$user->email,
$producer
);

return true;
}

return false;
}
}

+ 14
- 7
common/logic/Payment/Service/PaymentUtils.php Ver fichero

@@ -28,7 +28,7 @@ class PaymentUtils extends AbstractService implements UtilsInterface
$this->producerSolver = $this->loadService(ProducerSolver::class);
}

public function creditUser(User $user, float $amount, string $meanPayment, User $userAction): void
public function creditUser(User $user, float $amount, string $meanPayment, User $userAction, string $comment = null): void
{
$this->paymentBuilder->createPayment(
Payment::TYPE_CREDIT,
@@ -36,11 +36,12 @@ class PaymentUtils extends AbstractService implements UtilsInterface
$this->getProducerContext(),
$user,
$userAction,
$meanPayment
$meanPayment,
$comment
);
}

public function debitUser(User $user, float $amount, string $meanPayment, User $userAction): void
public function debitUser(User $user, float $amount, string $meanPayment, User $userAction, string $comment = null): void
{
$this->paymentBuilder->createPayment(
Payment::TYPE_DEBIT,
@@ -48,17 +49,18 @@ class PaymentUtils extends AbstractService implements UtilsInterface
$this->getProducerContext(),
$user,
$userAction,
$meanPayment
$meanPayment,
$comment
);
}

public function creditOrDebitUser(string $type, User $user, float $amount, string $meanPayment, User $userAction): void
public function creditOrDebitUser(string $type, User $user, float $amount, string $meanPayment, User $userAction, string $comment): void
{
if($type == Payment::TYPE_CREDIT) {
$this->creditUser($user, $amount, $meanPayment, $userAction);
$this->creditUser($user, $amount, $meanPayment, $userAction, $comment);
}
elseif($type == Payment::TYPE_DEBIT) {
$this->debitUser($user, $amount, $meanPayment, $userAction);
$this->debitUser($user, $amount, $meanPayment, $userAction, $comment);
}
else {
throw new ErrorException('$type a une valeur incorrect');
@@ -78,6 +80,7 @@ class PaymentUtils extends AbstractService implements UtilsInterface
$order->user,
$userAction,
$meanPayment,
null,
$order
);
}
@@ -107,6 +110,7 @@ class PaymentUtils extends AbstractService implements UtilsInterface
$order->user,
$userAction,
MeanPayment::CREDIT,
null,
$order
);
}
@@ -124,6 +128,7 @@ class PaymentUtils extends AbstractService implements UtilsInterface
$order->user,
$userAction,
$meanPayment,
null,
$order
);
}
@@ -140,6 +145,7 @@ class PaymentUtils extends AbstractService implements UtilsInterface
$order->user,
$userAction,
MeanPayment::CREDIT,
null,
$order
);
}
@@ -158,6 +164,7 @@ class PaymentUtils extends AbstractService implements UtilsInterface
$order->user,
$userAction,
MeanPayment::CREDIT,
null,
$order
);
}

+ 2
- 1
common/logic/PointSale/PointSale/Repository/PointSaleRepositoryQuery.php Ver fichero

@@ -5,6 +5,7 @@ namespace common\logic\PointSale\PointSale\Repository;
use common\logic\AbstractRepositoryQuery;
use common\logic\PointSale\PointSale\Model\PointSale;
use common\logic\PointSale\PointSale\Service\PointSaleDefinition;
use common\logic\StatusInterface;
use yii\db\ActiveQuery;

class PointSaleRepositoryQuery extends AbstractRepositoryQuery
@@ -32,7 +33,7 @@ class PointSaleRepositoryQuery extends AbstractRepositoryQuery

public function filterIsOnline(): self
{
$this->andWhere(['status' => 1]);
$this->andWhere(['status' => StatusInterface::STATUS_ONLINE]);

return $this;
}

+ 13
- 2
common/logic/Producer/Producer/Model/Producer.php Ver fichero

@@ -42,6 +42,7 @@ use common\logic\Config\TaxRate\Model\TaxRate;
use common\logic\User\User\Model\User;
use common\logic\User\UserProducer\Model\UserProducer;
use common\components\ActiveRecordCommon;
use yii\web\UploadedFile;

/**
* This is the model class for table "producer".
@@ -98,13 +99,22 @@ class Producer extends ActiveRecordCommon
self::BILLING_TYPE_FREE_PRICE => 'Prix libre',
];

var $secret_key_payplug;

const ONLINE_PAYMENT_MINIMUM_AMOUNT_DEFAULT = 25;

const ORDER_DEADLINE_DEFAULT = 20;
const ORDER_DELAY_DEFAULT = 1;

var $secret_key_payplug;

/**
* @var UploadedFile
*/
public $logoFile;
/**
* @var UploadedFile
*/
public $photoFile;

/**
* @inheritdoc
*/
@@ -127,6 +137,7 @@ class Producer extends ActiveRecordCommon
return $model->tiller == true;
}
],
[['logoFile', 'photoFile'], 'file', 'extensions' => 'png, jpg, jpeg', 'mimeTypes' => 'image/png, image/jpeg'],
[
[
'order_delay',

+ 52
- 0
common/logic/Producer/Producer/Service/ProducerBuilder.php Ver fichero

@@ -4,6 +4,7 @@ namespace common\logic\Producer\Producer\Service;

use common\helpers\Opendistrib;
use common\helpers\Password;
use common\helpers\Upload;
use common\logic\AbstractBuilder;
use common\logic\Producer\Producer\Model\Producer;
use common\logic\Producer\Producer\Repository\ProducerRepository;
@@ -109,4 +110,55 @@ class ProducerBuilder extends AbstractBuilder
$producer->option_stripe_endpoint_secret
);
}

public function savePrivateKeysStripe(Producer $producer)
{
$this->savePrivateKeyApiStripe($producer);
$this->savePrivateKeyEndpointStripe($producer);

$producer->option_stripe_private_key = '';
$producer->option_stripe_endpoint_secret = '';

$producer->save();
}

public function initOptionDashboardDatesBeforeSave(Producer $producer): void
{
$this->initOptionDashboardDateStartEndBeforeSave($producer, true);
$this->initOptionDashboardDateStartEndBeforeSave($producer, false);
}

private function initOptionDashboardDateStartEndBeforeSave(Producer $producer, bool $dateStart): void
{
$field = 'option_dashboard_date_'.($dateStart ? 'start' : 'end');
if ($producer->$field && strlen($producer->$field)) {
$producer->$field = date(
'Y-m-d',
strtotime(str_replace('/', '-', $producer->$field))
);
}
}

public function initOptionDashboardDatesDisplay(Producer $producer, bool $dateStart = true): void
{
$this->initOptionDashboardDateStartEndDisplay($producer, true);
$this->initOptionDashboardDateStartEndDisplay($producer, false);
}

private function initOptionDashboardDateStartEndDisplay(Producer $producer, bool $dateStart): void
{
$field = 'option_dashboard_date_'.($dateStart ? 'start' : 'end');
if (strlen($producer->$field)) {
$producer->$field = date('d/m/Y', strtotime($producer->$field));
}
}

public function processUploadImage(Producer $producer, string $name, string $filenameOld, bool $deleteImage)
{
Upload::uploadFile($producer, $name.'File', $name, $filenameOld);
if ($deleteImage) {
$producer->$name = '';
$producer->save();
}
}
}

+ 13
- 8
common/logic/Product/Product/Model/Product.php Ver fichero

@@ -47,22 +47,27 @@ use common\logic\Product\ProductCategory\Model\ProductCategory;
use common\logic\Product\ProductPointSale\Model\ProductPointSale;
use common\logic\Product\ProductPrice\Model\ProductPrice;
use common\components\ActiveRecordCommon;
use common\logic\StatusInterface;
use common\logic\Subscription\ProductSubscription\Model\ProductSubscription;
use yii\web\UploadedFile;

/**
* This is the model class for table "product".
*
*/
class Product extends ActiveRecordCommon
class Product extends ActiveRecordCommon implements StatusInterface
{
public $total = 0;
public $apply_distributions = true;

public $price_with_tax = 0;
public $wording_unit = '';

public $pointsSale;

/**
* @var UploadedFile
*/
public $photoFile;

public static $unitsArray = [
'piece' => [
'unit' => 'piece',
@@ -118,10 +123,10 @@ class Product extends ActiveRecordCommon
{
return [
[['name', 'id_producer'], 'required'],
[['active', 'order', 'id_producer', 'id_tax_rate', 'id_product_category'], 'integer'],
[['order', 'id_producer', 'id_tax_rate', 'id_product_category', 'status'], 'integer'],
[['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday', 'unavailable', 'apply_distributions', 'available_on_points_sale'], 'boolean'],
[['price', 'weight', 'step', 'quantity_max', 'quantity_max_monday', 'quantity_max_tuesday', 'quantity_max_wednesday', 'quantity_max_thursday', 'quantity_max_friday', 'quantity_max_saturday', 'quantity_max_sunday'], 'number'],
[['photo'], 'file'],
[['photoFile'], 'file', 'extensions' => 'png, jpg, jpeg', 'mimeTypes' => 'image/png, image/jpeg'],
[['name', 'reference', 'description', 'photo', 'unit'], 'string', 'max' => 255],
[['recipe'], 'string', 'max' => 1000],
['step', 'required', 'message' => 'Champs obligatoire', 'when' => function ($model) {
@@ -144,8 +149,7 @@ class Product extends ActiveRecordCommon
'name' => 'Nom',
'reference' => 'Référence',
'description' => 'Description',
'active' => 'Actif',
'photo' => 'Photo',
'photoFile' => 'Photo',
'price' => 'Prix (€) TTC',
'weight' => 'Poids',
'recipe' => 'Recette',
@@ -171,7 +175,8 @@ class Product extends ActiveRecordCommon
'step' => 'Pas',
'id_tax_rate' => 'TVA',
'id_product_category' => 'Catégorie',
'available_on_points_sale' => 'Par défaut'
'available_on_points_sale' => 'Par défaut',
'status' => 'Actif',
];
}


+ 6
- 6
common/logic/Product/Product/Model/ProductSearch.php Ver fichero

@@ -47,7 +47,7 @@ class ProductSearch extends Product
public function rules()
{
return [
[['active', 'order', 'quantity_max', 'id_producer'], 'integer'],
[['order', 'quantity_max', 'id_producer', 'status'], 'integer'],
[['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday', 'unavailable'], 'boolean'],
[['price', 'weight'], 'number'],
[[ 'photo'], 'file'],
@@ -65,12 +65,12 @@ class ProductSearch extends Product
->with($optionsSearch['with'])
->innerJoinWith($optionsSearch['join_with'], true)
->where(['product.id_producer' => GlobalParam::getCurrentProducerId()])
->orderBy('product.order ASC')
;
->andWhere('status >= :status')->addParams(['status' => Product::STATUS_OFFLINE])
->orderBy('product.order ASC');
$dataProvider = new ActiveDataProvider([
'query' => $query,
'sort' => ['attributes' => ['order', 'photo', 'name', 'description','active']],
'sort' => ['attributes' => ['order', 'photo', 'name', 'description','status']],
'pagination' => [
'pageSize' => 1000,
],
@@ -84,9 +84,9 @@ class ProductSearch extends Product
$query->andFilterWhere(['like', 'product.name', $this->name]) ;
$query->andFilterWhere(['like', 'product.description', $this->description]) ;
if(isset($this->active) && is_numeric($this->active)) {
if(isset($this->status) && is_numeric($this->status)) {
$query->andWhere([
'product.active' => $this->active
'product.status' => $this->status
]) ;
}

+ 8
- 8
common/logic/Product/Product/Repository/ProductRepository.php Ver fichero

@@ -53,9 +53,9 @@ class ProductRepository extends AbstractRepository
->findOne();
}

public function findProducts(): array
public function findProducts(bool $filterStatus = true): array
{
return $this->createDefaultQuery()->find();
return $this->createDefaultQuery($filterStatus)->find();
}

/**
@@ -66,9 +66,9 @@ class ProductRepository extends AbstractRepository
return $this->createDefaultQuery()->count();
}

public function queryProductsByDistribution(Distribution $distribution)
public function queryProductsByDistribution(Distribution $distribution, bool $filterStatus = true)
{
return $this->createDefaultQuery()
return $this->createDefaultQuery($filterStatus)
->joinWith([
'productDistribution' => function ($query) use ($distribution) {
$query->andOnCondition(
@@ -82,9 +82,9 @@ class ProductRepository extends AbstractRepository
/**
* Retourne les produits d'une production donnée.
*/
public function findProductsByDistribution(Distribution $distribution)
public function findProductsByDistribution(Distribution $distribution, bool $filterStatus = true)
{
$productArray = $this->queryProductsByDistribution($distribution)->find();
$productArray = $this->queryProductsByDistribution($distribution, $filterStatus)->find();
return $this->buildProductsArrayById($productArray);
}

@@ -106,14 +106,14 @@ class ProductRepository extends AbstractRepository
public function queryProductsByProductCategory(ProductCategory $productCategory)
{
return $this->createDefaultQuery()
->filterIsActive()
->filterIsStatusOnline()
->filterByProductCategory($productCategory);
}

public function countProductsWithoutCategory(Producer $producer): int
{
return $this->createDefaultQuery()
->filterIsActive()
->filterIsStatusOnline()
->filterByProductCategory(null)
->count();
}

+ 1
- 6
common/logic/Product/Product/Repository/ProductRepositoryQuery.php Ver fichero

@@ -6,6 +6,7 @@ use common\logic\AbstractRepositoryQuery;
use common\logic\Distribution\Distribution\Model\Distribution;
use common\logic\Product\Product\Service\ProductDefinition;
use common\logic\Product\ProductCategory\Model\ProductCategory;
use common\logic\StatusInterface;

class ProductRepositoryQuery extends AbstractRepositoryQuery
{
@@ -28,12 +29,6 @@ class ProductRepositoryQuery extends AbstractRepositoryQuery
return $this;
}

public function filterIsActive(): self
{
$this->andWhere(['product.active' => true]);
return $this;
}

public function filterByProductCategory(ProductCategory $productCategory = null) : self
{
if($productCategory) {

+ 1
- 1
common/logic/Product/Product/Service/ProductBuilder.php Ver fichero

@@ -17,7 +17,7 @@ class ProductBuilder extends AbstractBuilder
public function createProduct(): Product
{
$product = $this->instanciateProduct();
$this->saveCreate($product);
$this->create($product);

return $product;
}

+ 8
- 3
common/logic/Product/Product/Service/ProductSolver.php Ver fichero

@@ -189,7 +189,7 @@ class ProductSolver extends AbstractService implements SolverInterface

public function isProductActiveByDay(Product $product, string $day): bool
{
return $product->active && $product->$day;
return $product->status && $product->$day;
}

public function getProductFieldNameQuantityMax(string $day): string
@@ -249,7 +249,7 @@ class ProductSolver extends AbstractService implements SolverInterface
$potentialRevenues = 0;

foreach($productsArray as $product) {
if ($product['productDistribution'][0]['active'] && $product['productDistribution'][0]['quantity_max']) {
if (isset($product['productDistribution'][0]) && $product['productDistribution'][0]['active'] && $product['productDistribution'][0]['quantity_max']) {
$potentialRevenues += $product['productDistribution'][0]['quantity_max'] * $product['price'];
}
}
@@ -262,11 +262,16 @@ class ProductSolver extends AbstractService implements SolverInterface
$potentialWeight = 0;

foreach($productsArray as $product) {
if ($product['productDistribution'][0]['active'] && $product['productDistribution'][0]['quantity_max']) {
if (isset($product['productDistribution'][0]) && $product['productDistribution'][0]['active'] && $product['productDistribution'][0]['quantity_max']) {
$potentialWeight += $product['productDistribution'][0]['quantity_max'] * $product['weight'] / 1000;
}
}

return $potentialWeight;
}

public function isStatusOnlineOrOffline(Product $product): bool
{
return $product->status >= Product::STATUS_OFFLINE;
}
}

+ 10
- 0
common/logic/StatusInterface.php Ver fichero

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

namespace common\logic;

interface StatusInterface
{
const STATUS_DELETED = -1;
const STATUS_OFFLINE = 0;
const STATUS_ONLINE = 1;
}

+ 1
- 0
common/logic/Subscription/Subscription/Service/SubscriptionBuilder.php Ver fichero

@@ -19,6 +19,7 @@ class SubscriptionBuilder extends AbstractBuilder
public function instanciateSubscription(): Subscription
{
$subscription = new Subscription();
$subscription->auto_payment = Subscription::AUTO_PAYMENT_DEDUCTED;

return $subscription;
}

+ 27
- 0
common/versions/23.10.A.php Ver fichero

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

require_once dirname(__FILE__).'/_macros.php';

version(
'03/10/2023',
[
[

],
[
"[Administration] Distributions > commandes : accès boutons d'action en version mobile",
"[Administration] Utilisateurs > historique crédit : remise en place colonne commentaire",
"[Administration] Distributions > liste commandes : libellé 'Gratuit' si montant à 0€",
"[Administration] Abonnements : correctif champs débit automatique non mis à jour lors de la modification",
]
],
[
[],
[
"[Administration] Produits : gestion statut 'supprimé'",
"[Administration] Correctif problème upload images webp"
]
],
);

?>

+ 26
- 0
console/migrations/m230929_065700_rename_column_product_active_status.php Ver fichero

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

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

/**
* Class m230929_065700_rename_column_product_active_status
*/
class m230929_065700_rename_column_product_active_status extends Migration
{
/**
* {@inheritdoc}
*/
public function safeUp()
{
$this->renameColumn('product', 'active', 'status');
}

/**
* {@inheritdoc}
*/
public function safeDown()
{
$this->renameColumn('product', 'status', 'active');
}
}

+ 26
- 0
console/migrations/m231002_142915_add_column_payment_summary.php Ver fichero

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

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

/**
* Class m231002_142915_add_column_payment_summary
*/
class m231002_142915_add_column_payment_summary extends Migration
{
/**
* {@inheritdoc}
*/
public function safeUp()
{
$this->addColumn('payment', 'summary', Schema::TYPE_TEXT);
}

/**
* {@inheritdoc}
*/
public function safeDown()
{
$this->dropColumn('payment', 'summary');
}
}

+ 1
- 1
producer/controllers/OrderController.php Ver fichero

@@ -890,7 +890,7 @@ class OrderController extends ProducerBaseController
$productsArray = Product::find()
->where([
'id_producer' => $producer->id,
'product.active' => 1,
'product.status' => 1,
]);

$productsArray = $productsArray->joinWith([

+ 1
- 1
producer/controllers/SiteController.php Ver fichero

@@ -116,7 +116,7 @@ class SiteController extends ProducerBaseController
$queryProducts = Product::find()
->andWhere([
'id_producer' => $this->getProducerCurrent()->id,
'active' => true,
'status' => Product::STATUS_ONLINE,
'id_product_category' => null,
])
->with('productPointSale')

+ 1
- 1
producer/web/js/vuejs/subscription-form.js Ver fichero

@@ -126,7 +126,7 @@ var app = new Vue({
}
},
checkProductAvailable: function (product) {
var available = product.active &&
var available = product.status &&
(!this.monday || (this.monday && product.monday)) &&
(!this.tuesday || (this.tuesday && product.tuesday)) &&
(!this.wednesday || (this.wednesday && product.wednesday)) &&

Cargando…
Cancelar
Guardar