Guillaume Bourgeois 1 год назад
Родитель
Сommit
950b46d107
67 измененных файлов: 1450 добавлений и 671 удалений
  1. +8
    -38
      backend/controllers/CronController.php
  2. +14
    -70
      backend/controllers/DistributionController.php
  3. +1
    -1
      backend/controllers/DocumentController.php
  4. +2
    -2
      backend/controllers/ProductController.php
  5. +1
    -1
      backend/controllers/SiteController.php
  6. +4
    -4
      backend/controllers/SubscriptionController.php
  7. +2
    -1
      backend/models/MailForm.php
  8. +8
    -5
      backend/views/distribution/index.php
  9. +7
    -4
      backend/views/distribution/report-bourlingue.php
  10. +1
    -1
      backend/views/distribution/report-grid.php
  11. +15
    -5
      backend/views/distribution/shopping-cart-labels.php
  12. +1
    -1
      backend/views/document/_download_product_line.php
  13. +2
    -1
      backend/views/document/download.php
  14. +1
    -1
      backend/views/layouts/header.php
  15. +17
    -2
      backend/views/point-sale/_form.php
  16. +49
    -124
      backend/views/producer/update.php
  17. +1
    -1
      backend/views/product/_form.php
  18. +1
    -1
      backend/views/product/index.php
  19. +7
    -4
      backend/views/product/update/prices/_form.php
  20. +1
    -1
      backend/views/product/update/prices/list.php
  21. +1
    -1
      backend/views/subscription/index.php
  22. +13
    -4
      backend/views/user/_form.php
  23. +3
    -1
      backend/views/user/index.php
  24. +191
    -190
      backend/web/css/screen.css
  25. +2
    -2
      backend/web/js/backend.js
  26. +5
    -0
      backend/web/js/vuejs/producer-update.js
  27. +1
    -0
      backend/web/sass/screen.scss
  28. +14
    -3
      common/components/BusinessLogic.php
  29. +6
    -0
      common/components/BusinessLogicTrait.php
  30. +1
    -1
      common/config/params.php
  31. +3
    -1
      common/forms/SubscriptionForm.php
  32. +9
    -3
      common/helpers/CSV.php
  33. +35
    -0
      common/helpers/Dropdown.php
  34. +5
    -1
      common/helpers/GlobalParam.php
  35. +32
    -0
      common/logic/Config/Unit/Module/UnitModule.php
  36. +66
    -0
      common/logic/Config/Unit/Service/UnitDefinition.php
  37. +65
    -0
      common/logic/Config/Unit/Service/UnitSolver.php
  38. +10
    -0
      common/logic/Distribution/Distribution/Export/DistributionExportGeneratorInterface.php
  39. +98
    -0
      common/logic/Distribution/Distribution/Export/DistributionReport2CsvGenerator.php
  40. +10
    -7
      common/logic/Distribution/Distribution/Export/DistributionReportCsvGenerator.php
  41. +3
    -3
      common/logic/Distribution/Distribution/Export/DistributionReportGridPdfGenerator.php
  42. +7
    -4
      common/logic/Distribution/Distribution/Export/DistributionReportPdfGenerator.php
  43. +43
    -0
      common/logic/Distribution/Distribution/Export/DistributionReportTotalProductCsvGenerator.php
  44. +47
    -30
      common/logic/Distribution/Distribution/Export/DistributionShoppingCartLabelsPdfGenerator.php
  45. +14
    -26
      common/logic/Distribution/Distribution/Module/DistributionModule.php
  46. +151
    -0
      common/logic/Distribution/Distribution/Service/ExportManager.php
  47. +10
    -9
      common/logic/Order/Order/Repository/OrderRepository.php
  48. +1
    -0
      common/logic/Order/Order/Service/OrderDocumentManager.php
  49. +37
    -23
      common/logic/Order/Order/Service/OrderSolver.php
  50. +46
    -3
      common/logic/Order/ProductOrder/Service/ProductOrderSolver.php
  51. +3
    -2
      common/logic/PointSale/PointSale/Model/PointSale.php
  52. +21
    -7
      common/logic/Producer/Producer/Model/Producer.php
  53. +1
    -1
      common/logic/Product/Product/Model/Product.php
  54. +39
    -35
      common/logic/Product/Product/Service/ProductSolver.php
  55. +1
    -1
      common/logic/Subscription/Subscription/Service/SubscriptionSolver.php
  56. +5
    -2
      common/logic/User/User/Model/User.php
  57. +1
    -1
      common/logic/User/User/Service/UsersCreditCsvGenerator.php
  58. +29
    -0
      common/versions/23.10.E.php
  59. +4
    -3
      console/commands/ActiveDistributionsInAdvanceController.php
  60. +164
    -0
      console/commands/ClosingOrdersController.php
  61. +0
    -27
      console/commands/DemoAccountController.php
  62. +39
    -0
      console/migrations/m231024_062121_add_column_producer_options_exports.php
  63. +26
    -0
      console/migrations/m231024_092428_add_column_producer_option_document_height_logo.php
  64. +30
    -0
      console/migrations/m231025_064432_add_columns_shopping_cart_labels.php
  65. +9
    -7
      producer/controllers/OrderController.php
  66. +5
    -4
      producer/controllers/SubscriptionController.php
  67. +1
    -1
      producer/views/site/index.php

+ 8
- 38
backend/controllers/CronController.php Просмотреть файл

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

use common\helpers\GlobalParam;
use common\helpers\MeanPayment;
use common\logic\Distribution\Distribution\Service\ExportManager;
use common\logic\Order\Order\Model\Order;
use common\logic\User\User\Model\User;
use Yii;
@@ -106,7 +107,7 @@ class CronController extends BackendController
* @param string $key
* @param string $forceDate
*/
public function actionProcessOrders($key = '', $forceDate = '')
public function actionProcessOrders(string $key = '', string $forceDate = '')
{
$producerModule = $this->getProducerModule();
$distributionModule = $this-> getDistributionModule();
@@ -137,15 +138,12 @@ class CronController extends BackendController
$arrayProducers = $producerModule->findProducers();

foreach ($arrayProducers as $producer) {

$this->getLogic()->setProducerContext($producer);

$countOrders = 0;
$mailOrdersSend = false;
$distribution = $distributionModule
->findOneDistribution($date, true);

if ($distribution) {
// @TODO : attention, il faut prendre en compte les délais de commande spécifiques (lundi, mardi, mercredi etc.)
if ($hour == $producer->order_deadline || strlen($forceDate)) {
/*
* Paiement des commandes (paiement automatique)
@@ -165,7 +163,6 @@ class CronController extends BackendController
if ($order->auto_payment && $configCredit) {
if ($orderModule->isCreditAutoPayment($order) && $orderModule->getOrderAmount($order, Order::AMOUNT_REMAINING) > 0) {
$paymentManager->payOrder($order, MeanPayment::CREDIT, $userModule->findOneUserById(User::ID_USER_SYSTEM), false);
$countOrders++;
}
}
}
@@ -185,8 +182,8 @@ class CronController extends BackendController

$mail = Yii::$app->mailer->compose(
[
'html' => 'cronOrdersSummary-html',
'text' => 'cronOrdersSummary-text',
'html' => '@common/mail/cronOrdersSummary-html',
'text' => '@common/mail/cronOrdersSummary-text',
], [
'date' => $date,
'orders' => $arrayOrders
@@ -197,13 +194,9 @@ class CronController extends BackendController
if (is_array($arrayOrders) && count($arrayOrders)) {
$subject = '[Opendistrib] Commandes du ' . date('d/m', strtotime($date));

// génération du pdf de commande
Yii::$app->runAction('distribution/report-cron', [
'date' => $date,
'save' => true,
'idProducer' => $producer->id,
'key' => '64ac0bdab7e9f5e48c4d991ec5201d57'
]);
// @TODO : envoyer uniquement les exports qui sont activés dans les paramètres du producteur
$distributionModule->getExportManager()->generate(ExportManager::ORDERS_PDF, $distribution, true);

$mail->attach(
Yii::getAlias('@app/web/pdf/Commandes-' . $date . '-' . $producer->id . '.pdf')
);
@@ -222,32 +215,9 @@ class CronController extends BackendController
foreach ($userArray as $user) {
if($user->email && strlen($user->email) > 0) {
$mail->setTo($user->email)->send();
$mailOrdersSend = true;
}
}
}

if ($producer->active) {

$strCountOrders = 0;
if ($arrayOrders && is_array($arrayOrders)) {
$strCountOrders = count($arrayOrders);
}

$messageLog =
$producer->name . '<br />' .
'Distribution du ' . $date . '<br />' .
$strCountOrders . ' commande(s) enregistrée(s)<br />' .
$countOrders . ' commande(s) payée(s)<br .>' .
($mailOrdersSend ? 'Récapitulatif de commandes envoyé' : 'Aucun récapitulatif envoyé');

/*Yii::$app->mailer->compose()
->setFrom('contact@opendistrib.net')
->setTo('contact@opendistrib.net')
->setSubject('[Opendistrib] Log '.$producer->name)
->setTextBody($messageLog)
->send();*/
}
}
}
}

+ 14
- 70
backend/controllers/DistributionController.php Просмотреть файл

@@ -43,12 +43,13 @@ use common\helpers\GlobalParam;
use common\helpers\MeanPayment;
use common\helpers\Price;
use common\logic\Distribution\Distribution\Model\Distribution;
use common\logic\Distribution\Distribution\Service\ExportManager;
use common\logic\Document\DeliveryNote\Model\DeliveryNote;
use common\logic\Order\Order\Model\Order;
use common\logic\Producer\Producer\Model\Producer;
use common\logic\Product\Product\Model\Product;
use DateTime;
use kartik\mpdf\Pdf;
use yii\base\ErrorException;
use yii\base\Exception;
use yii\filters\AccessControl;

@@ -216,7 +217,7 @@ class DistributionController extends BackendController
return [
'credit' => $producer->credit,
'tiller' => $producer->tiller,
'option_display_export_grid' => $producer->option_display_export_grid
'option_distribution_export_orders_grid_pdf' => $producer->option_distribution_export_orders_grid_pdf
];
}

@@ -261,15 +262,7 @@ class DistributionController extends BackendController
$distributionJsonData = [
'id' => $distribution->id,
'active' => $distribution->active,
'url_report' => $this->getUrlManagerBackend()->createUrl(
['distribution/report', 'date' => $distribution->date]
),
'url_report_grid' => $this->getUrlManagerBackend()->createUrl(
['distribution/report-grid', 'date' => $distribution->date]
),
'url_export_shopping_cart_labels' => $this->getUrlManagerBackend()->createUrl(
['distribution/export-shopping-cart-labels', 'date' => $distribution->date]
),
'exports' => $distributionModule->getExportManager()->getAjaxArray($distribution),
'url_order' => $distributionModule->getLinkOrder($distribution),
];

@@ -298,6 +291,7 @@ class DistributionController extends BackendController
$userModule = $this->getUserModule();
$orderModule = $this->getOrderModule();
$paymentManager = $this->getPaymentModule();
$productOrderModule = $this->getProductOrderModule();

if ($ordersArray) {
foreach ($ordersArray as &$order) {
@@ -307,7 +301,7 @@ class DistributionController extends BackendController
$productOrderArray = [];
foreach ($order->productOrder as $productOrder) {
$productOrderArray[$productOrder->id_product] = [
'quantity' => $productOrder->quantity * Product::$unitsArray[$productOrder->unit]['coefficient'],
'quantity' => $productOrderModule->getSolver()->getQuantityToCoefficientOfUnit($productOrder),
'unit' => $productOrder->unit,
'price' => number_format($productOrder->price, 5),
'invoice_price' => number_format($productOrder->invoice_price, 5),
@@ -571,74 +565,24 @@ class DistributionController extends BackendController
}

/**
* Génére un PDF récapitulatif des des commandes d'un producteur pour une
* date donnée (Méthode appelable via CRON)
*
* @param string $date
* @param boolean $save
* @param integer $idProducer
* @param string $key
* @return Pdf|null
* Génére un export pour une distribution.
*/
public function actionReportCron($date = '', $save = false, $idProducer = 0, $key = '')
public function actionExport(string $name, string $date = '')
{
if ($key == '64ac0bdab7e9f5e48c4d991ec5201d57') {
$this->actionReport($date, $save, $idProducer);
}
}

/**
* Génére un PDF récapitulatif des commandes d'un producteur pour une
* date donnée.
*/
public function actionReport(string $date = '', bool $save = false, int $idProducer = 0, string $type = "pdf")
{
if (!$idProducer) {
$idProducer = $this->getProducerCurrent()->id;
}

$distributionModule = $this-> getDistributionModule();
$producerModule = $this->getProducerModule();
$producerCurrent = $producerModule->findOneProducerById($idProducer);
$this->getLogic()->setProducerContext($producerCurrent);
$distribution = $distributionModule->findOneDistribution($date);
$distribution = $distributionModule->getRepository()->findOneDistribution($date);

if ($distribution) {
if ($type == 'pdf') {
return $distributionModule->generateDistributionReportPdf($distribution, $save);
try {
return $distributionModule->getExportManager()->getGenerator($name)->generate($distribution);
}
elseif ($type == 'csv') {
$distributionModule->generateDistributionReportCsv($distribution);
catch(ErrorException $exception) {
$this->setFlash('error', "Une erreur est survenue lors de la génération de l'export.");
return $this->redirectReferer();
}
}
}

public function actionReportGrid(string $date = '', bool $save = false, int $idProducer = 0)
{
if (!$idProducer) {
$idProducer = $this->getProducerCurrent()->id;
}

$distributionModule = $this-> getDistributionModule();
$producerModule = $this->getProducerModule();
$producerCurrent = $producerModule->findOneProducerById($idProducer);
$this->getLogic()->setProducerContext($producerCurrent);
$distribution = $distributionModule->findOneDistribution($date);

if ($distribution) {
return $distributionModule->generateDistributionReportGridPdf($distribution, $save);
}
}

public function actionExportShoppingCartLabels(string $date)
{
$distributionModule = $this-> getDistributionModule();
$distribution = $distributionModule->findOneDistribution($date);
if($distribution) {
return $distributionModule->generateDistributionShoppingCartLabelsPdf($distribution);
}
}

public function actionAjaxProcessProductQuantityMax($idDistribution, $idProduct, $quantityMax)
{
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

+ 1
- 1
backend/controllers/DocumentController.php Просмотреть файл

@@ -618,7 +618,7 @@ class DocumentController extends BackendController
'order',
function ($product) use ($document, $userProducer, $pointSale, $productModule) {
return array_merge($product->getAttributes(), [
'unit_coefficient' => Product::$unitsArray[$product->unit]['coefficient'],
'unit_coefficient' => $productModule->getSolver()->getUnitCoefficient($product),
'prices' => $productModule->getPriceArray($product, $userProducer->user, $pointSale),
'wording_unit' => $product->wording_unit,
'tax_rate' => $product->taxRate->value

+ 2
- 2
backend/controllers/ProductController.php Просмотреть файл

@@ -504,7 +504,7 @@ class ProductController extends BackendController
'',
'',
'',
CSV::formatPrice($product->price)
CSV::formatNumber($product->price)
];

// prix spécifiques
@@ -518,7 +518,7 @@ class ProductController extends BackendController
$productPrice->userGroup ? $productPrice->userGroup->name : '',
$productPrice->pointSale ? $productPrice->pointSale->name : '',
$productPrice->from_quantity ?? '',
CSV::formatPrice($productPrice->price)
CSV::formatNumber($productPrice->price)
];
}
}

+ 1
- 1
backend/controllers/SiteController.php Просмотреть файл

@@ -149,6 +149,6 @@ class SiteController extends BackendController
$this->addFlash('error', 'Producteur introuvable.');
}

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

+ 4
- 4
backend/controllers/SubscriptionController.php Просмотреть файл

@@ -39,6 +39,7 @@ namespace backend\controllers;

use common\forms\SubscriptionForm;
use common\helpers\GlobalParam;
use common\logic\Config\Unit\Service\UnitDefinition;
use common\logic\Product\Product\Model\Product;
use common\logic\Subscription\Subscription\Model\SubscriptionSearch;
use yii\filters\AccessControl;
@@ -254,8 +255,6 @@ class SubscriptionController extends BackendController
{
$subscriptionModule = $this->getSubscriptionModule();
$distributionModule = $this-> getDistributionModule();
$orderModule = $this->getOrderModule();

$subscription = $subscriptionModule->findOneSubscriptionById($idSubscription);
$matchedDistributionsArray = $distributionModule->findDistributionsIncomingMatchWithSubscrtiption($subscription);

@@ -265,7 +264,7 @@ class SubscriptionController extends BackendController
->deleteOrdersIncomingDistributionsFromSubscription($subscription);
}
foreach ($matchedDistributionsArray as $distribution) {
$orderModule->createOrderFromSubscription($subscription, $distribution->date);
$subscriptionModule->createOrderFromSubscription($subscription, $distribution->date);
}
$this->setFlash('success', 'Commandes ' . ($update ? 're-' : '') . 'générées dans les distributions futures.');
return $this->redirect(['subscription/index']);
@@ -282,6 +281,7 @@ class SubscriptionController extends BackendController
{
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

$unitModule = $this->getUnitModule();
$productModule = $this->getProductModule();

$productsQuery = Product::find()
@@ -298,7 +298,7 @@ class SubscriptionController extends BackendController
$productsArray = $productsQuery->asArray()->orderBy('order ASC')->all();

foreach ($productsArray as &$theProduct) {
$theProduct['wording_unit'] = $productModule->strUnit($theProduct['unit'], 'wording_short');
$theProduct['wording_unit'] = $unitModule->getSolver()->strUnit($theProduct['unit']);

if (isset($theProduct['productSubscription'][0])) {
$theProduct['quantity'] = $theProduct['productSubscription'][0]['quantity'] * Product::$unitsArray[$theProduct['unit']]['coefficient'];

+ 2
- 1
backend/models/MailForm.php Просмотреть файл

@@ -40,6 +40,7 @@ namespace backend\models;

use common\helpers\GlobalParam;
use common\helpers\Mailjet;
use common\logic\Config\Unit\Service\UnitDefinition;
use common\logic\Distribution\Distribution\Model\Distribution;
use common\logic\Distribution\Distribution\Module\DistributionModule;
use common\logic\Producer\Producer\Module\ProducerModule;
@@ -155,7 +156,7 @@ Produits disponibles :
}
if($product->price) {
$productDescription .= ' / '.Price::format($productModule->getPriceWithTax($product)) ;
$productDescription .= ' ('. $productModule->strUnit($product->unit, 'wording_unit').')' ;
$productDescription .= ' ('. $productModule->getSolver()->strUnit($product, UnitDefinition::WORDING_UNIT).')' ;
}

$messageAutoText .= '- '.$productDescription.'

+ 8
- 5
backend/views/distribution/index.php Просмотреть файл

@@ -213,11 +213,16 @@ $this->setPageTitle('Distributions') ;
<div class="info-box-content">
<span class="info-box-text">
{{ countOrders }} Commande<span v-if="countOrders > 1">s</span><br />
<a :href="distribution.url_report" class="btn btn-xs btn-default" v-if="countOrders > 0">Liste (PDF)</a>
<a :href="distribution.url_report+'&type=csv'" class="btn btn-xs btn-default" v-if="countOrders > 0">Tableau (CSV)</a>

<template v-for="distributionExport in distribution.exports">
<a v-if="countOrders > 0" :href="distributionExport.url" class="btn btn-xs btn-default">{{ distributionExport.label }}</a><br />
</template>
<!--<a :href="distribution.url_report+'&type=csv'" class="btn btn-xs btn-default" v-if="countOrders > 0">Tableau (CSV)</a>
<a :href="distribution.url_report_csv2" class="btn btn-xs btn-default" v-if="countOrders > 0">Tableau 2 (CSV)</a>
<br />
<a :href="distribution.url_report_grid" class="btn btn-xs btn-default" v-if="producer && producer.option_display_export_grid && countOrders > 0">Grille (PDF)</a>
<a :href="distribution.url_report_grid" class="btn btn-xs btn-default" v-if="producer && producer.option_distribution_export_orders_grid_pdf && countOrders > 0">Grille (PDF)</a>
<a :href="distribution.url_export_shopping_cart_labels" class="btn btn-xs btn-default" v-if="countOrders > 0">Étiquettes (PDF)</a>
<a :href="distribution.url_report_total_products" class="btn btn-xs btn-default" v-if="countOrders > 0">Total produits (CSV)</a>-->
</span>
</div>
</div>
@@ -401,8 +406,6 @@ $this->setPageTitle('Distributions') ;
</div>
<div v-if="order.amount_paid > order.amount">
<span class="glyphicon glyphicon-alert"></span> Surplus à rembourser
{{ order.amount_paid }} /
{{ order.amount }}
</div>
</td>
<td class="column-credit" v-if="!idActivePointSale || (pointSaleActive && pointSaleActive.credit == 1)">

+ 7
- 4
backend/views/distribution/report-bourlingue.php Просмотреть файл

@@ -37,11 +37,14 @@ termes.
*/

use common\helpers\Price;
use common\logic\Config\Unit\Module\UnitModule;
use common\logic\Config\Unit\Service\UnitDefinition;
use common\logic\Order\Order\Module\OrderModule;
use common\logic\Product\Product\Model\Product;
use common\logic\Product\Product\Module\ProductModule;
use common\logic\User\UserProducer\Model\UserProducer;

$unitModule = UnitModule::getInstance();
$productModule = ProductModule::getInstance();
$orderModule = OrderModule::getInstance();

@@ -108,7 +111,7 @@ foreach ($pointsSaleArray as $pointSale) {
$add = false;
foreach ($order->productOrder as $productOrder) {
if($product->id == $productOrder->id_product) {
$unit = ( $productModule->strUnit($productOrder->unit, 'wording_short', true) == 'p.') ? '' : '&nbsp;'. $productModule->strUnit($productOrder->unit, 'wording_short', true) ;
$unit = ( $productModule->getSolver()->strUnit($productOrder->product, UnitDefinition::WORDING_SHORT, true) == 'p.') ? '' : '&nbsp;'. $productModule->getSolver()->strUnit($productOrder->unit, UnitDefinition::WORDING_SHORT, true) ;
$strProducts .= $product->name . ' (' .$productOrder->quantity .$unit.')<br />';
$add = true;
}
@@ -188,7 +191,7 @@ foreach ($pointsSaleArray as $pointSale) {
foreach( Product::$unitsArray as $unit => $dataUnit) {
$quantity = $orderModule->getProductQuantity($product, $pointSale->orders, false, $unit);
if ($quantity) {
$theUnit = ( $productModule->strUnit($unit, 'wording_short', true) == 'p.') ? '' : '&nbsp;'. $productModule->strUnit($unit, 'wording_short', true) ;
$theUnit = ( $unitModule->getSolver()->strUnit($unit, UnitDefinition::WORDING_SHORT, true) == 'p.') ? '' : '&nbsp;'. $unitModule->getSolver()->strUnit($unit, UnitDefinition::WORDING_SHORT, true) ;
$strProducts .= $product->name . ' (' .$quantity .$theUnit.')<br />';
}
}
@@ -237,7 +240,7 @@ foreach ($pointsSaleArray as $pointSale)
foreach( Product::$unitsArray as $unit => $dataUnit) {
$quantity = $orderModule->getProductQuantity($product, $pointSale->orders, false, $unit);
if ($quantity) {
$theUnit = ( $productModule->strUnit($unit, 'wording_short', true) == 'p.') ? '' : '&nbsp;'. $productModule->strUnit($unit, 'wording_short', true) ;
$theUnit = ( $unitModule->getSolver()->strUnit($unit, 'wording_short', true) == 'p.') ? '' : '&nbsp;'. $unitModule->getSolver()->strUnit($unit, 'wording_short', true) ;
$html .= $product->name . ' (' .$quantity .$theUnit.')<br />';
}
}
@@ -264,7 +267,7 @@ foreach ($productsArray as $product) {
foreach( Product::$unitsArray as $unit => $dataUnit) {
$quantity = $orderModule->getProductQuantity($product, $ordersArray, false, $unit);
if ($quantity) {
$theUnit = ( $productModule->strUnit($unit, 'wording_short', true) == 'p.') ? '' : '&nbsp;'. $productModule->strUnit($unit, 'wording_short', true) ;
$theUnit = ( $unitModule->getSolver()->strUnit($unit, 'wording_short', true) == 'p.') ? '' : '&nbsp;'. $unitModule->getSolver()->strUnit($unit, 'wording_short', true) ;
$html .= $product->name . ' (' .$quantity .$theUnit.')<br />';
}
}

+ 1
- 1
backend/views/distribution/report-grid.php Просмотреть файл

@@ -101,7 +101,7 @@ function line_product($product, $orders)
$quantity = '';
foreach ($order->productOrder as $productOrder) {
if ($product->id == $productOrder->id_product) {
$unit = ($productModule->strUnit($productOrder->unit, 'wording_short', true) == 'p.') ? '' : '&nbsp;' . $productModule->strUnit($productOrder->unit, 'wording_short', true);
$unit = ($productModule->getSolver()->strUnit($productOrder->product, 'wording_short', true) == 'p.') ? '' : '&nbsp;' . $productModule->getSolver()->strUnit($productOrder->product, 'wording_short', true);

$quantity .= $productOrder->quantity . $unit;
if ($productOrder->quantity > 1) {

+ 15
- 5
backend/views/distribution/shopping-cart-labels.php Просмотреть файл

@@ -4,22 +4,32 @@ use common\logic\Order\Order\Module\OrderModule;
use yii\helpers\Html;

$orderModule = OrderModule::getInstance();
$index = 0
$index = 0;

?>
<?php foreach($ordersArray as $order): ?>
<div class="shopping-cart-label shopping-cart-label-<?= $index ?>">
<?php
$i = 0;
foreach($ordersArray as $key => $order):
$index ++;
?>
<div class="shopping-cart-label">
<div class="inner">
<div class="username">
<?= $orderModule->getOrderUsername($order); ?>
</div>
<div class="point-sale">
<?= Html::encode($order->pointSale->name); ?> &bull; <?= date('d/m', strtotime($distribution->date)); ?>
<?= date('d/m', strtotime($distribution->date)); ?> &bull;
<?= Html::encode($order->pointSale->name); ?>
</div>
<div class="products">
<?= $orderModule->getCartSummary($order); ?>
</div>
</div>
</div>
<?php $index = ($index == 5) ? 0 : $index + 1; ?>
<?php if($index == $shoppingCartLabelsPerColumn) {
$index = 0;
} ?>
<?php if($index == 0 && $key !== array_key_last($ordersArray)): ?>
<columnbreak />
<?php endif; ?>
<?php endforeach; ?>

+ 1
- 1
backend/views/document/_download_product_line.php Просмотреть файл

@@ -37,7 +37,7 @@ $productModule = $this->getProductModule();
<td class="align-center">
<?= $productOrder->quantity * Product::$unitsArray[$productOrder->unit]['coefficient'] ?>
</td>
<td class="align-center"><?= $productModule->strUnit($productOrder->unit, 'wording') ?></td>
<td class="align-center"><?= $productModule->getSolver()->strUnit($productOrder->product, 'wording') ?></td>
<?php if($displayPrices): ?>
<?php if($producer->taxRate->value != 0): ?>
<td class="align-center"><?= $productOrder->taxRate->value * 100 ?> %</td>

+ 2
- 1
backend/views/document/download.php Просмотреть файл

@@ -21,7 +21,8 @@ $documentPriceDecimals = (int) $producerModule->getConfig('option_document_price
<div class="producer">
<?php if (strlen($producer->logo)) : ?>
<div class="logo">
<img style="max-height: 80px;" src="<?= $producerModule->getUrlLogo($producer) ?>"/>
<?php $optionDocumentHeightLogo = $producerModule->getSolver()->getConfig('option_document_height_logo'); ?>
<img style="height: <?= $optionDocumentHeightLogo ?: 100; ?>px;" src="<?= $producerModule->getUrlLogo($producer) ?>"/>
</div>
<?php endif; ?>
<div class="address">

+ 1
- 1
backend/views/layouts/header.php Просмотреть файл

@@ -66,7 +66,7 @@ $userCurrent = GlobalParam::getCurrentUser();
<?php if($producer->logo): ?>
<span class="logo">
<img class="img-logo"
src="<?= Yii::$app->urlManagerProducer->getHostInfo() . '/' . Yii::$app->urlManagerProducer->baseUrl; ?>uploads/<?= $producer->logo; ?>"
src="<?= Yii::$app->urlManagerProducer->getHostInfo() . '/' . Yii::$app->urlManagerProducer->baseUrl; ?>/uploads/<?= $producer->logo; ?>"
alt="Logo <?= Html::encode($producer->name) ?>" />
</span>
<?php endif; ?>

+ 17
- 2
backend/views/point-sale/_form.php Просмотреть файл

@@ -36,14 +36,18 @@
* termes.
*/

use common\logic\Distribution\Distribution\Module\DistributionModule;
use common\logic\Distribution\Distribution\Service\ExportManager;
use common\logic\Producer\Producer\Module\ProducerModule;
use yii\helpers\Html;
use yii\widgets\ActiveForm;
use yii\helpers\ArrayHelper;
use common\logic\Producer\Producer\Model\Producer;
use common\logic\User\User\Module\UserModule;

$producerModule = $this->getProducerModule();
$userModule = $this->getUserModule();
$producerModule = ProducerModule::getInstance();
$userModule = UserModule::getInstance();
$distributionModule = DistributionModule::getInstance();

?>

@@ -150,6 +154,17 @@ $userModule = $this->getUserModule();
<?= $form->field($model, 'button_generate_delivery_note_each_user')->checkbox() ?>
</div>
</div>

<?php if($distributionModule->getExportManager()->isEnabled(ExportManager::SHOPPING_CART_LABELS_PDF)): ?>
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Exports</h3>
</div>
<div class="panel-body">
<?= $form->field($model, 'exclude_export_shopping_cart_labels')->checkbox(); ?>
</div>
</div>
<?php endif; ?>
</div>
<div class="clr"></div>


+ 49
- 124
backend/views/producer/update.php Просмотреть файл

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

use common\helpers\Dropdown;
use common\helpers\GlobalParam;
use common\logic\Distribution\Distribution\Module\DistributionModule;
use common\logic\User\User\Module\UserModule;
use yii\helpers\Html;
use yii\widgets\ActiveForm;
@@ -46,8 +48,10 @@ use common\logic\Document\Document\Model\Document;
use yii\helpers\ArrayHelper;

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

$userModule = UserModule::getInstance();
$userCurrent = GlobalParam::getCurrentUser();
$distributionExportManager = DistributionModule::getInstance()->getExportManager();
$this->setTitle('Paramètres');
$this->addBreadcrumb($this->getTitle());

@@ -66,7 +70,6 @@ $this->addBreadcrumb($this->getTitle());
:class="'btn '+((currentSection == section.name) ? 'btn-primary' : 'btn-default')"
@click="changeSection(section)" :href="'#'+section.name">
{{ section.nameDisplay }}
<span class="glyphicon glyphicon-triangle-bottom"></span>
</a>
</div>

@@ -79,10 +82,7 @@ $this->addBreadcrumb($this->getTitle());
<div class="panel-body">
<h4>Accès</h4>
<?= $form->field($model, 'active')
->dropDownList([
0 => 'Non',
1 => 'Oui'
], [])
->dropDownList(Dropdown::noYesChoices())
->label('En ligne')
->hint('Activez cette option pour rendre votre espace visible à vos clients.'); ?>
<?= $form->field($model, 'code')->hint("Saisissez ce champs si vous souhaitez protéger l'accès à votre espace par un code, sinon laissez-le vide.<br />"
@@ -129,18 +129,7 @@ $this->addBreadcrumb($this->getTitle());
<div class="panel-body">
<h4>Tableau de bord administration</h4>
<?= $form->field($model, 'option_dashboard_number_distributions')
->dropDownList([
3 => '3',
6 => '6',
9 => '9',
12 => '12',
15 => '15',
18 => '18',
21 => '21',
24 => '24',
27 => '27',
30 => '30',
], []); ?>
->dropDownList(Dropdown::numberChoices(3, 30, false, '', 3)); ?>

<?= $form->field($model, 'option_dashboard_date_start')->textInput([
'class' => 'datepicker form-control'
@@ -253,66 +242,17 @@ $this->addBreadcrumb($this->getTitle());
Producer::BEHAVIOR_ORDER_SELECT_DISTRIBUTION_LIST => 'Liste',
]); ?>
<?= $form->field($model, 'option_delivery')
->dropDownList([
0 => 'Non',
1 => 'Oui'
], []); ?>
->dropDownList(Dropdown::noYesChoices()); ?>
<?php echo $form->field($model, 'option_allow_order_guest')
->dropDownList([
0 => 'Non',
1 => 'Oui'
], []); ?>

->dropDownList(Dropdown::noYesChoices()); ?>

<h4>Notifications</h4>
<?= $form->field($model, 'option_notify_producer_order_summary')
->dropDownList([
0 => 'Non',
1 => 'Oui',
], []); ?>
->dropDownList(Dropdown::noYesChoices()); ?>
<?= $form->field($model, 'option_email_confirm')
->dropDownList([
0 => 'Non',
1 => 'Oui'
], []); ?>
->dropDownList(Dropdown::noYesChoices()); ?>
<?= $form->field($model, 'option_email_confirm_producer')
->dropDownList([
0 => 'Non',
1 => 'Oui'
], []); ?>


<h4>Exports</h4>
<?= $form->field($model, 'option_csv_separator')
->dropDownList([
';' => 'Point-virgule (;)',
',' => 'Virgule (,)'
], []); ?>
<?= $form->field($model, 'option_csv_export_all_products')
->dropDownList([
0 => 'Non',
1 => 'Oui'
], []); ?>
<?= $form->field($model, 'option_csv_export_by_piece')
->dropDownList([
0 => 'Non',
1 => 'Oui'
], []); ?>
<?= $form->field($model, 'option_display_export_grid')
->dropDownList([
0 => 'Non',
1 => 'Oui'
], []); ?>
<?= $form->field($model, 'option_export_display_product_reference')
->dropDownList([
0 => 'Non',
1 => 'Oui'
], []); ?>
<?= $form->field($model, 'option_export_display_column_delivery_note')
->dropDownList([
0 => 'Non',
1 => 'Oui'
], []); ?>
->dropDownList(Dropdown::noYesChoices()); ?>

<h4>Divers</h4>
<?php
@@ -337,15 +277,35 @@ $this->addBreadcrumb($this->getTitle());
</div>
</div>

<div v-show="currentSection == 'exports'" class="panel panel-default">
<div class="panel-body">
<h4>Exports affichés dans les distributions</h4>
<?= $distributionExportManager->getProducerFormCheckboxes($form, $model) ?>

<h4>Options exports</h4>
<?= $form->field($model, 'option_csv_separator')
->dropDownList([
';' => 'Point-virgule (;)',
',' => 'Virgule (,)'
], []); ?>
<?= $form->field($model, 'option_export_display_product_reference')
->dropDownList(Dropdown::noYesChoices()); ?>
<?= $form->field($model, 'option_export_display_column_delivery_note')
->dropDownList(Dropdown::noYesChoices()); ?>
<?= $form->field($model, 'option_csv_export_all_products')
->dropDownList(Dropdown::noYesChoices()); ?>
<?= $form->field($model, 'option_csv_export_by_piece')
->dropDownList(Dropdown::noYesChoices()); ?>
<?= $form->field($model, 'export_shopping_cart_labels_number_per_column')
->dropDownList(Dropdown::numberChoices(1, 20)); ?>
</div>
</div>

<div v-show="currentSection == 'abonnements'" class="panel panel-default">
<div class="panel-body">
<h4>Abonnements</h4>
<?= $form->field($model, 'user_manage_subscription')
->dropDownList([
0 => 'Non',
1 => 'Oui',
], []); ?>
->dropDownList(Dropdown::noYesChoices()); ?>
</div>
</div>

@@ -353,10 +313,7 @@ $this->addBreadcrumb($this->getTitle());
<div class="panel-body">
<h4>Crédit</h4>
<?= $form->field($model, 'credit')
->dropDownList([
0 => 'Non',
1 => 'Oui',
], [])
->dropDownList(Dropdown::noYesChoices())
->label('Activer le système de Crédit')
->hint('Le système de Crédit permet à vos clients d\'avoir un compte prépayé sur le site <em>distrib</em>.<br />'
. 'Ils créditent leur compte en vous donnant la somme de leur choix et c\'est ensuite à vous de ' . Html::a('mettre à jour', ['user/index']) . ' leur Crédit en ligne.<br />'
@@ -370,43 +327,30 @@ $this->addBreadcrumb($this->getTitle());
], [])->hint(Producer::HINT_CREDIT_FUNCTIONING); ?>

<?= $form->field($model, 'use_credit_checked_default')
->dropDownList([
0 => 'Non',
1 => 'Oui',
], [])->hint('Utilisation optionnelle du Crédit.'); ?>
->dropDownList(Dropdown::noYesChoices())
->hint('Utilisation optionnelle du Crédit.'); ?>

<?= $form->field($model, 'credit_limit_reminder', [
'template' => '{label}<div class="input-group">{input}<span class="input-group-addon"><span class="glyphicon glyphicon-euro"></span></span></div>{hint}',
])
->hint("Une relance est envoyé au client dès que ce seuil est dépassé."); ?>



<?= $form->field($model, 'credit_limit', [
'template' => '{label}<div class="input-group">{input}<span class="input-group-addon"><span class="glyphicon glyphicon-euro"></span></span></div>{hint}',
])->hint('Limite de crédit que l\'utilisateur ne pourra pas dépasser. Laisser vide pour permettre un crédit négatif et infini.'); ?>

<h4>Paiement en ligne</h4>

<?= $form->field($model, 'online_payment')
->dropDownList([
0 => 'Non',
1 => 'Oui',
], []); ?>
->dropDownList(Dropdown::noYesChoices()); ?>
<?= $form->field($model, 'option_online_payment_minimum_amount')
->hint('Valeur par défaut si non défini : '.Producer::ONLINE_PAYMENT_MINIMUM_AMOUNT_DEFAULT.' €')
->textInput(); ?>
<?= $form->field($model, 'option_stripe_mode_test')->dropDownList([
0 => 'Non',
1 => 'Oui'
], []); ?>

<?= $form->field($model, 'option_stripe_mode_test')->dropDownList(Dropdown::noYesChoices()); ?>
<?= $form->field($model, 'option_online_payment_type')
->dropDownList([
'credit' => 'Alimentation du crédit',
'order' => 'Paiement à la commande',
], []); ?>

<?= $form->field($model, 'option_stripe_public_key')->textInput(); ?>
<?= $form->field($model, 'option_stripe_private_key')->textInput(); ?>
<?= $form->field($model, 'option_stripe_endpoint_secret')->textInput(); ?>
@@ -429,10 +373,7 @@ $this->addBreadcrumb($this->getTitle());
<div class="panel-body">
<h4>Tiller</h4>
<?= $form->field($model, 'tiller')
->dropDownList([
0 => 'Non',
1 => 'Oui'
], [])
->dropDownList(Dropdown::noYesChoices())
->label('Synchroniser avec Tiller'); ?>
<?= $form->field($model, 'tiller_provider_token'); ?>
<?= $form->field($model, 'tiller_restaurant_token'); ?>
@@ -449,10 +390,7 @@ $this->addBreadcrumb($this->getTitle());
->label('TVA à appliquer par défaut'); ?>
<?= $form->field($model, 'option_tax_calculation_method')
->dropDownList(Document::$taxCalculationMethodArray); ?>
<?= $form->field($model, 'option_export_evoliz')->dropDownList([
0 => 'Non',
1 => 'Oui'
]); ?>
<?= $form->field($model, 'option_export_evoliz')->dropDownList(Dropdown::noYesChoices()); ?>
<?php $hintKeywordsPrefix = "Saisissez [ANNEE] pour intégrer l'année courante"; ?>
<?= $form->field($model, 'document_quotation_prefix')->hint($hintKeywordsPrefix); ?>
<?= $form->field($model, 'document_quotation_first_reference'); ?>
@@ -465,22 +403,12 @@ $this->addBreadcrumb($this->getTitle());
0 => 'Non',
1 => 'Oui'
]); ?>
<?= $form->field($model, 'document_display_orders_invoice')->dropDownList([
0 => 'Non',
1 => 'Oui'
]); ?>
<?= $form->field($model, 'document_display_orders_delivery_note')->dropDownList([
0 => 'Non',
1 => 'Oui'
]); ?>
<?= $form->field($model, 'document_display_prices_delivery_note')->dropDownList([
0 => 'Non',
1 => 'Oui'
]); ?>
<?= $form->field($model, 'document_display_product_description')->dropDownList([
0 => 'Non',
1 => 'Oui'
]); ?>
<?= $form->field($model, 'option_document_height_logo')
->dropDownList(Dropdown::numberChoices(50, 250, true, 'px', 50)); ?>
<?= $form->field($model, 'document_display_orders_invoice')->dropDownList(Dropdown::noYesChoices()); ?>
<?= $form->field($model, 'document_display_orders_delivery_note')->dropDownList(Dropdown::noYesChoices()); ?>
<?= $form->field($model, 'document_display_prices_delivery_note')->dropDownList(Dropdown::noYesChoices()); ?>
<?= $form->field($model, 'document_display_product_description')->dropDownList(Dropdown::noYesChoices()); ?>
<?= $form->field($model, 'option_document_price_decimals')->dropDownList([
2 => '2',
3 => '3'
@@ -521,10 +449,7 @@ $this->addBreadcrumb($this->getTitle());
])
->hint("Sélectionnez le temps que vous estimez gagner chaque semaine en utilisant ce logiciel. Cette donnée sera utilisée sur la page <a href=\"".$urlAboutPage."\" target=\"_blanck\">À propos</a> du site.") ; ?>
<?= $form->field($model, 'option_display_message_new_opendistrib_version')
->dropDownList([
1 => 'Oui',
0 => 'Non'
], []); ?>
->dropDownList(Dropdown::noYesChoices()); ?>
</div>
</div>


+ 1
- 1
backend/views/product/_form.php Просмотреть файл

@@ -78,7 +78,7 @@ $taxRateModule = $this-> getTaxRateModule();
]) ?>
<?= $form->field($model, 'step')->textInput()->hint('Définit ce qui est ajouté ou enlevé lors des changements de quantité.') ?>

<?= $form->field($model, 'weight')->textInput()->label('Poids (g)') ?>
<?= $form->field($model, 'weight')->textInput()->label('Poids (g)')->hint("Si unité au poids ou volume, utilisé pour déterminer le nombre de pièces dans les exports.") ?>

<div class="col-md-3">
<?= $form->field($model, 'quantity_max')->textInput() ?>

+ 1
- 1
backend/views/product/index.php Просмотреть файл

@@ -128,7 +128,7 @@ $this->addButton(['label' => 'Nouveau produit <span class="glyphicon glyphicon-p
'value' => function ($model) use ($productModule) {
$return = '';
if ($model->price) {
$return = Price::format($productModule->getPriceWithTax($model)) . ' (' . $productModule->strUnit($model->unit, 'wording_unit', true) . ')';
$return = Price::format($productModule->getPriceWithTax($model)) . ' (' . $productModule->getSolver()->strUnit($model, 'wording_unit', true) . ')';
}

return $return;

+ 7
- 4
backend/views/product/update/prices/_form.php Просмотреть файл

@@ -1,13 +1,16 @@
<?php

use common\logic\Config\Unit\Module\UnitModule;
use common\logic\Product\Product\Module\ProductModule;
use yii\helpers\Html;
use yii\bootstrap\ActiveForm;
use common\helpers\GlobalParam;

$unitModule = UnitModule::getInstance();
$userModule = $this->getUserModule();
$userGroupModule = $this->getUserGroupModule();
$pointSaleModule = $this->getPointSaleModule();
$productModule = $this->getProductModule();
$productModule = ProductModule::getInstance();

?>

@@ -27,7 +30,7 @@ $productModule = $this->getProductModule();
<?= $form->field($model, 'id_user')->dropDownList($userModule->populateUserDropdownList()); ?>
<?= $form->field($model, 'id_user_group')->dropDownList($userGroupModule->populateUserGroupDropdownList()); ?>
<?= $form->field($model, 'id_point_sale')->dropDownList($pointSaleModule->populatePointSaleDropdownList()); ?>
<?= $form->field($model, 'from_quantity')->label('À partir de la quantité ('. $productModule->strUnit($productModule->getRefUnit($modelProduct->unit), 'wording').')'); ?>
<?= $form->field($model, 'from_quantity')->label('À partir de la quantité ('. $productModule->getSolver()->strUnit($modelProduct, 'wording', true).')'); ?>

<?php
$producer = GlobalParam::getCurrentProducer();
@@ -48,13 +51,13 @@ $productModule = $this->getProductModule();
</div>
</div>
<div class="col-xs-4">
<label for="product-price" class="control-label without-tax">Prix ('. $productModule->strUnit($productModule->getRefUnit($modelProduct->unit), 'wording_unit').') HT</label>
<label for="product-price" class="control-label without-tax">Prix ('. $productModule->getSolver()->strUnit($modelProduct, 'wording_unit', true).') HT</label>
<div class="input-group">
{input} <span class="input-group-addon"><span class="glyphicon glyphicon-euro"></span></span>
</div>
</div>
<div class="col-xs-4">
<label for="productprice-price-with-tax" class="control-label with-tax">Prix ('. $productModule->strUnit($productModule->getRefUnit($modelProduct->unit), 'wording_unit').') TTC</label>
<label for="productprice-price-with-tax" class="control-label with-tax">Prix ('. $productModule->getSolver()->strUnit($modelProduct, 'wording_unit', true).') TTC</label>
<div class="input-group">
<input type="text" id="productprice-price-with-tax" class="form-control" name="" value="" data-tax-rate-value="'.$taxRateValue.'">
<span class="input-group-addon"><span class="glyphicon glyphicon-euro"></span></span>

+ 1
- 1
backend/views/product/update/prices/list.php Просмотреть файл

@@ -112,7 +112,7 @@ $this->render('../_nav', [
'attribute' => 'from_quantity',
'value' => function ($productPrice) use ($productModule) {
if ($productPrice->from_quantity) {
return $productPrice->from_quantity . ' ' . $productModule->strUnit($productModule->getRefUnit($productPrice->product->unit), 'wording');
return $productPrice->from_quantity . ' ' . $productModule->getSolver()->strUnit($productPrice->product, 'wording', true);
}

return '';

+ 1
- 1
backend/views/subscription/index.php Просмотреть файл

@@ -90,7 +90,7 @@ $subscriptionsArray = Subscription::searchAll() ;
foreach($model->productSubscription as $productSubscription)
{
if(isset($productSubscription->product)) {
$html .= Html::encode($productSubscription->product->name).' ('.($productSubscription->quantity * Product::$unitsArray[$productSubscription->product->unit]['coefficient']).'&nbsp;'. $productModule->strUnit($productSubscription->product->unit, 'wording_short').')<br />' ;
$html .= Html::encode($productSubscription->product->name).' ('.($productSubscription->quantity * Product::$unitsArray[$productSubscription->product->unit]['coefficient']).'&nbsp;'. $productModule->getSolver()->strUnit($productSubscription->product, 'wording_short').')<br />' ;
}
else {
$html .= 'Produit non défini<br />' ;

+ 13
- 4
backend/views/user/_form.php Просмотреть файл

@@ -36,14 +36,19 @@
* termes.
*/

use common\logic\Distribution\Distribution\Module\DistributionModule;
use common\logic\Distribution\Distribution\Service\ExportManager;
use common\logic\Producer\Producer\Module\ProducerModule;
use common\logic\User\User\Module\UserModule;
use yii\helpers\Html;
use yii\widgets\ActiveForm;
use yii\helpers\ArrayHelper;

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

$userModule = $this->getUserModule();
$producerModule = $this->getProducerModule();
$userModule = UserModule::getInstance();
$producerModule = ProducerModule::getInstance();
$distributionModule = DistributionModule::getInstance();

?>

@@ -63,12 +68,16 @@ $producerModule = $this->getProducerModule();
<?= $form->field($model, 'name')->textInput() ?>
<?= $form->field($model, 'phone')->textInput() ?>
<?= $form->field($model, 'email')->textInput() ?>
<?= $form->field($model, 'newsletter')->checkbox() ?>
<?= $form->field($model, 'address')->textarea() ?>

<?php if ($producerModule->getConfig('option_export_evoliz')): ?>
<?php if ($producerModule->getSolver()->getConfig('option_export_evoliz')): ?>
<?= $form->field($model, 'evoliz_code')->textInput() ?>
<?php endif; ?>
<?= $form->field($model, 'newsletter')->checkbox() ?>

<?php if($distributionModule->getExportManager()->isEnabled(ExportManager::SHOPPING_CART_LABELS_PDF)): ?>
<?= $form->field($model, 'exclude_export_shopping_cart_labels')->checkbox(); ?>
<?php endif; ?>

<?php if($pointsSaleArray && count($pointsSaleArray) > 0): ?>
<?= $form->field($model, 'points_sale')->checkboxlist(

+ 3
- 1
backend/views/user/index.php Просмотреть файл

@@ -69,7 +69,9 @@ $this->render('_menu', [
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'summary' => $this->getProducerModule()->getProducerPageSizer()
'summary' =>
'Affichage de <b>{begin, number}-{end, number}</b> sur <b>{totalCount, number}</b> {totalCount, plural, one{élément} other{éléments}}.'.
$this->getProducerModule()->getProducerPageSizer()
->getPageSizeSummary($producer, 'user', 'Utilisateurs'),
'columns' => [
[

+ 191
- 190
backend/web/css/screen.css
Разница между файлами не показана из-за своего большого размера
Просмотреть файл


+ 2
- 2
backend/web/js/backend.js Просмотреть файл

@@ -233,11 +233,11 @@ function opendistrib_products_event_unit(change) {
if (unit == 'piece') {
$('.field-product-step').hide();
$('.field-product-weight label').html('Poids (g)');
$('.field-product-weight').show();
//$('.field-product-weight').show();
} else {
$('.field-product-step').show();
$('.field-product-weight label').html('Poids (' + $('#product-unit').val() + ')');
$('.field-product-weight').hide();
//$('.field-product-weight').hide();
}

var label_price_ttc = $('.field-product-price .control-label.with-tax');

+ 5
- 0
backend/web/js/vuejs/producer-update.js Просмотреть файл

@@ -51,6 +51,11 @@ var app = new Vue({
nameDisplay: 'Commandes',
isAdminSection: 0
},
{
name: 'exports',
nameDisplay: 'Exports',
isAdminSection: 0
},
{
name: 'credit-payment',
nameDisplay: 'Crédit',

+ 1
- 0
backend/web/sass/screen.scss Просмотреть файл

@@ -346,6 +346,7 @@ a.btn, button.btn {

a {
margin-right: 10px ;
margin-bottom: 10px;
}
}


+ 14
- 3
common/components/BusinessLogic.php Просмотреть файл

@@ -3,15 +3,19 @@
namespace common\components;

use common\logic\Producer\Producer\Model\Producer;
use common\logic\ProducerContextTrait;
use yii\base\ErrorException;

class BusinessLogic
{
protected ?Producer $producerContext = null;

use BusinessLogicTrait;

public function getModules()
{
return [
$this->getUnitModule(),
$this->getTaxRateModule(),
$this->getUserUserGroupModule(),
$this->getUserGroupModule(),
@@ -24,18 +28,18 @@ class BusinessLogic
$this->getProductDistributionModule(),
$this->getProductCategoryModule(),
$this->getProductPointSaleModule(),
$this->getProductOrderModule(),
$this->getProductPriceModule(),
$this->getProductSubscriptionModule(),
$this->getTicketUserModule(),
$this->getTicketMessageModule(),
$this->getTicketModule(),
$this->getPointSaleModule(),
$this->getProductModule(),
$this->getProductOrderModule(),
$this->getQuotationModule(),
$this->getInvoiceModule(),
$this->getDeliveryNoteModule(),
$this->getDocumentModule(),
$this->getPointSaleModule(),
$this->getProductModule(),
$this->getSubscriptionModule(),
$this->getDistributionModule(),
$this->getProducerModule(),
@@ -43,8 +47,15 @@ class BusinessLogic
];
}

public function getProducerContext(): ?Producer
{
return $this->producerContext;
}

public function setProducerContext(Producer $producer)
{
$this->producerContext = $producer;

foreach($this->getModules() as $module) {
foreach($module->getServices() as $serviceClass) {
$instanceService = $serviceClass::getInstance();

+ 6
- 0
common/components/BusinessLogicTrait.php Просмотреть файл

@@ -3,6 +3,7 @@
namespace common\components;

use common\logic\Config\TaxRate\Module\TaxRateModule;
use common\logic\Config\Unit\Module\UnitModule;
use common\logic\Distribution\Distribution\Module\DistributionModule;
use common\logic\Distribution\PointSaleDistribution\Module\PointSaleDistributionModule;
use common\logic\Distribution\ProductDistribution\Module\ProductDistributionModule;
@@ -34,6 +35,11 @@ use common\logic\User\UserUserGroup\Module\UserUserGroupModule;

trait BusinessLogicTrait
{
public function getUnitModule(): UnitModule
{
return UnitModule::getInstance();
}

public function getOpinionModule(): OpinionModule
{
return OpinionModule::getInstance();

+ 1
- 1
common/config/params.php Просмотреть файл

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

return [
'version' => '23.10.D',
'version' => '23.10.E',
'maintenanceMode' => false,
'siteName' => 'Opendistrib',
'adminEmail' => 'contact@opendistrib.net',

+ 3
- 1
common/forms/SubscriptionForm.php Просмотреть файл

@@ -39,6 +39,7 @@ termes.
namespace common\forms;

use common\logic\Product\Product\Model\Product;
use common\logic\Product\Product\Module\ProductModule;
use common\logic\Subscription\ProductSubscription\Model\ProductSubscription;
use common\logic\Subscription\Subscription\Model\Subscription;
use common\logic\Subscription\Subscription\Module\SubscriptionModule;
@@ -117,6 +118,7 @@ class SubscriptionForm extends Model
*/
public function save()
{
$productModule = ProductModule::getInstance();
$userModule = UserModule::getInstance();
$subscriptionModule = SubscriptionModule::getInstance();

@@ -175,7 +177,7 @@ class SubscriptionForm extends Model
$newProductSubscription = new ProductSubscription;
$newProductSubscription->id_subscription = $subscription->id;
$newProductSubscription->id_product = $idProduct;
$newProductSubscription->quantity = $quantity / Product::$unitsArray[$product->unit]['coefficient'];
$newProductSubscription->quantity = $quantity / $productModule->getSolver()->getUnitCoefficient($product);

$newProductSubscription->save();
}

+ 9
- 3
common/helpers/CSV.php Просмотреть файл

@@ -44,8 +44,8 @@ class CSV
{
public static function send(string $filename, array $data)
{
CSV::downloadSendHeaders($filename);
echo CSV::array2csv($data);
self::downloadSendHeaders($filename);
echo self::array2csv($data);
die();
}

@@ -110,8 +110,14 @@ class CSV
header("Content-Transfer-Encoding: binary");
}

public static function formatPrice($price)
public static function formatNumber($price): string
{
return str_replace('.', ',', $price);
}

public static function formatPhone($phone): string
{
return "'".$phone;
}

}

+ 35
- 0
common/helpers/Dropdown.php Просмотреть файл

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

namespace common\helpers;

class Dropdown
{
public static function noYesChoices(): array
{
return [
0 => 'Non',
1 => 'Oui'
];
}

public static function numberChoices(
int $start,
int $end,
bool $addNullValue = true,
string $appendToValues = '',
int $increment = 1
): array
{
$choicesArray = [];

if($addNullValue) {
$choicesArray[null] = '--';
}

for($i = $start; $i <= $end; $i += $increment) {
$choicesArray[$i] = $i.$appendToValues;
}

return $choicesArray;
}
}

+ 5
- 1
common/helpers/GlobalParam.php Просмотреть файл

@@ -80,7 +80,11 @@ class GlobalParam
if (!\Yii::$app->user->isGuest) {
return \Yii::$app->user->identity->id_producer;
}
} else {
}
elseif(\Yii::$app->controller->module->id == 'app-console') {
return \Yii::$app->logic->getProducerContext()->id;
}
else {
return \Yii::$app->controller->getProducerCurrent()->id;
}


+ 32
- 0
common/logic/Config/Unit/Module/UnitModule.php Просмотреть файл

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

namespace common\logic\Config\Unit\Module;

use common\logic\AbstractModule;
use common\logic\Config\Unit\Service\UnitDefinition;
use common\logic\Config\Unit\Service\UnitSolver;

/**
* @mixin UnitDefinition
* @mixin UnitSolver
*/
class UnitModule extends AbstractModule
{
public function getServices(): array
{
return [
UnitDefinition::class,
UnitSolver::class
];
}

public function getDefinition(): UnitDefinition
{
return UnitDefinition::getInstance();
}

public function getSolver(): UnitSolver
{
return UnitSolver::getInstance();
}
}

+ 66
- 0
common/logic/Config/Unit/Service/UnitDefinition.php Просмотреть файл

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

namespace common\logic\Config\Unit\Service;

use common\logic\AbstractDefinition;

class UnitDefinition extends AbstractDefinition
{
const UNIT_PIECE = 'PIECE';
const UNIT_G = 'g';
const UNIT_KG = 'kg';
const UNIT_ML = 'mL';
const UNIT_L = 'L';

const WORDING_UNIT = 'wording_unit';
const WORDING = 'wording';
const WORDING_SHORT = 'wording_short';

public function getUnits(): array
{
return [
'piece' => [
'unit' => 'piece',
'wording_unit' => 'la pièce',
'wording' => 'pièce(s)',
'wording_short' => 'p.',
'coefficient' => 1
],
'g' => [
'ref_unit' => 'kg',
'unit' => 'g',
'wording_unit' => 'le g',
'wording' => 'g',
'wording_short' => 'g',
'coefficient' => 1000
],
'kg' => [
'unit' => 'kg',
'wording_unit' => 'le kg',
'wording' => 'kg',
'wording_short' => 'kg',
'coefficient' => 1
],
'mL' => [
'ref_unit' => 'L',
'unit' => 'mL',
'wording_unit' => 'le mL',
'wording' => 'mL',
'wording_short' => 'mL',
'coefficient' => 1000
],
'L' => [
'unit' => 'L',
'wording_unit' => 'le litre',
'wording' => 'L',
'wording_short' => 'L',
'coefficient' => 1
],
];
}

public function getEntityFqcn(): string
{
return '';
}
}

+ 65
- 0
common/logic/Config/Unit/Service/UnitSolver.php Просмотреть файл

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

namespace common\logic\Config\Unit\Service;

use common\logic\AbstractSolver;

class UnitSolver extends AbstractSolver
{
protected UnitDefinition $unitDefinition;

public function loadDependencies(): void
{
$this->unitDefinition = $this->loadService(UnitDefinition::class);
}

public function getUnit(string $idUnit): ?array
{
$unitsArray = $this->unitDefinition->getUnits();
if(isset($unitsArray[$idUnit])) {
return $unitsArray[$idUnit];
}

return null;
}

// getRefUnit
public function getUnitReference(string $idUnit): string
{
$unit = $this->getUnit($idUnit);

if ($unit && isset($unit['ref_unit'])) {
return $unit['ref_unit'];
}

return $idUnit;
}

public function getUnitCoefficient(string $idUnit): int
{
$unit = $this->getUnit($idUnit);

if($unit) {
return $unit['coefficient'];
}

return 1;
}

/**
* Retourne le libellé d'une unité.
*/
public function strUnit(string $idUnit, $format = UnitDefinition::WORDING_SHORT, bool $unitReference = false): string
{
if ($unitReference) {
$idUnit = $this->getUnitReference($idUnit);
}

$unit = $this->getUnit($idUnit);
if ($unit && isset($unit[$format])) {
return $unit[$format];
}

return '';
}
}

+ 10
- 0
common/logic/Distribution/Distribution/Export/DistributionExportGeneratorInterface.php Просмотреть файл

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

namespace common\logic\Distribution\Distribution\Export;

use common\logic\Distribution\Distribution\Model\Distribution;

interface DistributionExportGeneratorInterface
{
public function generate(Distribution $distribution, bool $save = false);
}

+ 98
- 0
common/logic/Distribution/Distribution/Export/DistributionReport2CsvGenerator.php Просмотреть файл

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

namespace common\logic\Distribution\Distribution\Export;

use common\helpers\CSV;
use common\logic\AbstractGenerator;
use common\logic\Distribution\Distribution\Model\Distribution;
use common\logic\Order\Order\Model\Order;
use common\logic\Order\Order\Repository\OrderRepository;
use common\logic\Order\Order\Service\OrderBuilder;
use common\logic\Order\Order\Service\OrderSolver;
use common\logic\Order\ProductOrder\Service\ProductOrderSolver;
use common\logic\PointSale\PointSale\Model\PointSale;
use common\logic\PointSale\PointSale\Repository\PointSaleRepository;
use common\logic\Producer\Producer\Service\ProducerSolver;
use common\logic\Product\Product\Service\ProductSolver;

class DistributionReport2CsvGenerator extends AbstractGenerator implements DistributionExportGeneratorInterface
{
protected ProductSolver $productSolver;
protected OrderRepository $orderRepository;
protected OrderSolver $orderSolver;
protected PointSaleRepository $pointSaleRepository;
protected OrderBuilder $orderBuilder;
protected ProducerSolver $producerSolver;
protected ProductOrderSolver $productOrderSolver;

public function loadDependencies(): void
{
$this->productSolver = $this->loadService(ProductSolver::class);
$this->orderRepository = $this->loadService(OrderRepository::class);
$this->orderSolver = $this->loadService(OrderSolver::class);
$this->pointSaleRepository = $this->loadService(PointSaleRepository::class);
$this->orderBuilder = $this->loadService(OrderBuilder::class);
$this->producerSolver = $this->loadService(ProducerSolver::class);
$this->productOrderSolver = $this->loadService(ProductOrderSolver::class);
}

public function generate(Distribution $distribution, bool $save = false)
{
$datas = [['Distribution du '.date('d/m/Y', strtotime($distribution->date))]];
$ordersArray = $this->orderRepository->findOrdersByDistribution($distribution);
$pointsSaleArray = $this->pointSaleRepository->findPointSales();
foreach ($pointsSaleArray as $pointSale) {
$this->orderBuilder->initPointSaleOrders($pointSale, $ordersArray);
}

foreach($pointsSaleArray as $pointSale) {
if(count($pointSale->orders)) {
foreach($this->addOrder($pointSale->orders[0], $pointSale) as $line) {
$datas[] = $line;
}
foreach($pointSale->orders as $key => $order) {
if ($key !== array_key_first($pointSale->orders)) {
foreach($this->addOrder($order) as $line) {
$datas[] = $line;
}
}
}
}
}

CSV::send('Commandes.csv', $datas);
}

public function addOrder(Order $order, PointSale $pointSale = null)
{
$datas = [];

if(isset($order->productOrder[0])) {
$firstProductOrder = $order->productOrder[0];
$datas[] = [
$pointSale ? $pointSale->name : '',
$this->orderSolver->getOrderUsername($order),
CSV::formatNumber($this->productOrderSolver->getQuantityPriorityPieces($firstProductOrder)),
$this->productSolver->getNameExport($firstProductOrder->product),
$this->productSolver->getWeightAsString($firstProductOrder->product),
$this->orderSolver->hasPhone($order) ? CSV::formatPhone($this->orderSolver->getPhone($order)) : '',
$this->orderRepository->getPaymentLabelPaid($order),
CSV::formatNumber($this->orderSolver->getOrderAmountWithTax($order))
];

foreach($order->productOrder as $key => $productOrder) {
if ($key !== array_key_first($order->productOrder)) {
$datas[] = [
'',
'',
CSV::formatNumber($this->productOrderSolver->getQuantityPriorityPieces($productOrder)),
$this->productSolver->getNameExport($productOrder->product),
$this->productSolver->getWeightAsString($productOrder->product),
];
}
}
}

return $datas;
}
}

common/logic/Distribution/Distribution/Service/DistributionReportCsvGenerator.php → common/logic/Distribution/Distribution/Export/DistributionReportCsvGenerator.php Просмотреть файл

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

namespace common\logic\Distribution\Distribution\Service;
namespace common\logic\Distribution\Distribution\Export;

use common\helpers\CSV;
use common\logic\AbstractGenerator;
use common\logic\Config\Unit\Service\UnitSolver;
use common\logic\Distribution\Distribution\Model\Distribution;
use common\logic\Order\Order\Repository\OrderRepository;
use common\logic\Order\Order\Service\OrderBuilder;
@@ -15,8 +16,9 @@ use common\logic\Product\Product\Model\Product;
use common\logic\Product\Product\Repository\ProductRepository;
use common\logic\Product\Product\Service\ProductSolver;

class DistributionReportCsvGenerator extends AbstractGenerator
class DistributionReportCsvGenerator extends AbstractGenerator implements DistributionExportGeneratorInterface
{
protected UnitSolver $unitSolver;
protected ProducerRepository $producerRepository;
protected ProductRepository $productRepository;
protected ProductSolver $productSolver;
@@ -28,6 +30,7 @@ class DistributionReportCsvGenerator extends AbstractGenerator

public function loadDependencies(): void
{
$this->unitSolver = $this->loadService(UnitSolver::class);
$this->producerRepository = $this->loadService(ProducerRepository::class);
$this->productRepository = $this->loadService(ProductRepository::class);
$this->productSolver = $this->loadService(ProductSolver::class);
@@ -38,7 +41,7 @@ class DistributionReportCsvGenerator extends AbstractGenerator
$this->producerSolver = $this->loadService(ProducerSolver::class);
}

public function generateDistributionReportCsv(Distribution $distribution)
public function generate(Distribution $distribution, bool $save = false)
{
$datas = [];
$ordersArray = $this->orderRepository->findOrdersByDistribution($distribution);
@@ -72,7 +75,7 @@ class DistributionReportCsvGenerator extends AbstractGenerator
$productUnit = $product->unit;
}

$productName .= ' (' . $this->productSolver->strUnit($productUnit, 'wording_short', true) . ')';
$productName .= ' (' . $this->unitSolver->strUnit($productUnit, 'wording_short', true) . ')';

$productsNameArray[] = $productName;
$productsIndexArray[$product->id] = $cpt++;
@@ -90,7 +93,7 @@ class DistributionReportCsvGenerator extends AbstractGenerator

if ($optionCsvExportByPiece) {
foreach ($order->productOrder as $productOrder) {
$orderLine[$productsIndexArray[$productOrder->id_product]] = $this->orderSolver->getProductQuantityPieces(
$orderLine[$productsIndexArray[$productOrder->id_product]] = $this->orderSolver->getProductQuantityPiecesByOrders(
$productOrder->product,
[$order]
);
@@ -106,8 +109,8 @@ class DistributionReportCsvGenerator extends AbstractGenerator
}
$orderLine[$productsIndexArray[$productOrder->id_product]] .= $productOrder->quantity;
if ($productOrder->product->unit != $productOrder->unit) {
$orderLine[$productsIndexArray[$productOrder->id_product]] .= $productModule->strUnit(
$productOrder->unit,
$orderLine[$productsIndexArray[$productOrder->id_product]] .= $this->productSolver->strUnit(
$productOrder->product,
'wording_short',
true
);

common/logic/Distribution/Distribution/Service/DistributionReportGridPdfGenerator.php → common/logic/Distribution/Distribution/Export/DistributionReportGridPdfGenerator.php Просмотреть файл

@@ -1,6 +1,6 @@
<?php

namespace common\logic\Distribution\Distribution\Service;
namespace common\logic\Distribution\Distribution\Export;

use common\logic\AbstractGenerator;
use common\logic\Distribution\Distribution\Model\Distribution;
@@ -12,7 +12,7 @@ use common\logic\Product\Product\Repository\ProductRepository;
use common\logic\Product\ProductCategory\Repository\ProductCategoryRepository;
use kartik\mpdf\Pdf;

class DistributionReportGridPdfGenerator extends AbstractGenerator
class DistributionReportGridPdfGenerator extends AbstractGenerator implements DistributionExportGeneratorInterface
{
protected OrderRepository $orderRepository;
protected OrderBuilder $orderBuilder;
@@ -31,7 +31,7 @@ class DistributionReportGridPdfGenerator extends AbstractGenerator
$this->productRepository = $this->loadService(ProductRepository::class);
}

public function generateDistributionReportGridPdf(Distribution $distribution, bool $save = false)
public function generate(Distribution $distribution, bool $save = false)
{
$producer = $this->getProducerContext();
$ordersArray = $this->orderRepository->findOrdersByDistribution($distribution);

common/logic/Distribution/Distribution/Service/DistributionReportPdfGenerator.php → common/logic/Distribution/Distribution/Export/DistributionReportPdfGenerator.php Просмотреть файл

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

namespace common\logic\Distribution\Distribution\Service;
namespace common\logic\Distribution\Distribution\Export;

use common\helpers\Price;
use common\logic\AbstractGenerator;
use common\logic\Config\Unit\Service\UnitSolver;
use common\logic\Distribution\Distribution\Model\Distribution;
use common\logic\Distribution\ProductDistribution\Repository\ProductDistributionRepository;
use common\logic\Document\Document\Service\DocumentSolver;
@@ -20,10 +21,11 @@ use common\logic\Product\Product\Service\ProductSolver;
use common\logic\User\User\Repository\UserRepository;
use kartik\mpdf\Pdf;

class DistributionReportPdfGenerator extends AbstractGenerator
class DistributionReportPdfGenerator extends AbstractGenerator implements DistributionExportGeneratorInterface
{
const LIMIT_PRODUCTS = 120;

protected UnitSolver $unitSolver;
protected OrderRepository $orderRepository;
protected OrderBuilder $orderBuilder;
protected ProductRepository $productRepository;
@@ -36,6 +38,7 @@ class DistributionReportPdfGenerator extends AbstractGenerator

public function loadDependencies(): void
{
$this->unitSolver = $this->loadService(UnitSolver::class);
$this->orderRepository = $this->loadService(OrderRepository::class);
$this->orderBuilder = $this->loadService(OrderBuilder::class);
$this->productRepository = $this->loadService(ProductRepository::class);
@@ -47,7 +50,7 @@ class DistributionReportPdfGenerator extends AbstractGenerator
$this->userRepository = $this->loadService(UserRepository::class);
}

public function generateDistributionReportPdf(Distribution $distribution, bool $save = false)
public function generate(Distribution $distribution, bool $save = false)
{
$producer = $this->getProducerContext();
$ordersArray = $this->orderRepository->findOrdersByDistribution($distribution);
@@ -380,7 +383,7 @@ class DistributionReportPdfGenerator extends AbstractGenerator

public function displayOrderProduct(string $quantity, string $unit, Product $product)
{
$theUnit = ( $this->productSolver->strUnit($unit, 'wording_short', true) == 'p.') ? '' : '&nbsp;'. $this->productSolver->strUnit($unit, 'wording_short', true) ;
$theUnit = ( $this->unitSolver->strUnit($unit, 'wording_short', true) == 'p.') ? '' : '&nbsp;'. $this->unitSolver->strUnit($unit, 'wording_short', true) ;
return '<strong>'.$quantity. $theUnit.'</strong> '.$this->productSolver->getNameExport($product). '<br />';
}
}

+ 43
- 0
common/logic/Distribution/Distribution/Export/DistributionReportTotalProductCsvGenerator.php Просмотреть файл

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

namespace common\logic\Distribution\Distribution\Export;

use common\helpers\CSV;
use common\logic\AbstractGenerator;
use common\logic\Distribution\Distribution\Model\Distribution;
use common\logic\Order\Order\Repository\OrderRepository;
use common\logic\Order\Order\Service\OrderSolver;
use common\logic\Product\Product\Repository\ProductRepository;
use common\logic\Product\Product\Service\ProductSolver;

class DistributionReportTotalProductCsvGenerator extends AbstractGenerator implements DistributionExportGeneratorInterface
{
protected ProductRepository $productRepository;
protected ProductSolver $productSolver;
protected OrderRepository $orderRepository;
protected OrderSolver $orderSolver;

public function loadDependencies(): void
{
$this->productRepository = $this->loadService(ProductRepository::class);
$this->orderRepository = $this->loadService(OrderRepository::class);
$this->productSolver = $this->loadService(ProductSolver::class);
$this->orderSolver = $this->loadService(OrderSolver::class);
}

public function generate(Distribution $distribution, bool $save = false)
{
$datas = [];
$productsArray = $this->productRepository->findProductsByDistribution($distribution);
$ordersArray = $this->orderRepository->findOrdersByDistribution($distribution);

foreach($productsArray as $product) {
$datas[] = [
$this->productSolver->getNameExport($product),
$this->orderSolver->getProductQuantityPiecesByOrders($product, $ordersArray)
];
}

CSV::send('Total_produits_' . $distribution->date . '.csv', $datas);
}
}

common/logic/Distribution/Distribution/Service/DistributionShoppingCartLabelsPdfGenerator.php → common/logic/Distribution/Distribution/Export/DistributionShoppingCartLabelsPdfGenerator.php Просмотреть файл

@@ -1,28 +1,34 @@
<?php

namespace common\logic\Distribution\Distribution\Service;
namespace common\logic\Distribution\Distribution\Export;

use common\logic\AbstractGenerator;
use common\logic\Distribution\Distribution\Model\Distribution;
use common\logic\Order\Order\Model\Order;
use common\logic\Order\Order\Repository\OrderRepository;
use common\logic\Producer\Producer\Service\ProducerSolver;
use kartik\mpdf\Pdf;

class DistributionShoppingCartLabelsPdfGenerator extends AbstractGenerator
class DistributionShoppingCartLabelsPdfGenerator extends AbstractGenerator implements DistributionExportGeneratorInterface
{
protected ProducerSolver $producerSolver;
protected OrderRepository $orderRepository;

public function loadDependencies(): void
{
$this->producerSolver = $this->loadService(ProducerSolver::class);
$this->orderRepository = $this->loadService(OrderRepository::class);
}

public function generateDistributionShoppingCartLabelsPdf(Distribution $distribution)
public function generate(Distribution $distribution, bool $save = false)
{
$ordersArray = $this->orderRepository->findOrdersByDistribution($distribution);
$ordersArray = $this->filterOrdersExcludedUsersAndPointSales($ordersArray);

$content = \Yii::$app->getView()->render('@backend/views/distribution/shopping-cart-labels.php', [
'distribution' => $distribution,
'ordersArray' => $ordersArray,
'shoppingCartLabelsPerColumn' => $this->producerSolver->getConfig('export_shopping_cart_labels_number_per_column') ?: 8
]);

$pdf = new Pdf([
@@ -38,12 +44,39 @@ class DistributionShoppingCartLabelsPdfGenerator extends AbstractGenerator
'methods' => [
'SetHeader' => ['Étiquettes du ' . date('d/m/Y', strtotime($distribution->date))],
'SetFooter' => ['{PAGENO}'],
]
],
]);

$pdf->getApi()->SetColumns(4);
$pdf->getApi()->keepColumns = true;

return $pdf->render();
}

public function filterOrdersExcludedUsersAndPointSales(array $ordersArray)
{
$ordersArrayFilter = [];

foreach($ordersArray as $order) {
if(!$this->isOrderUserExcludeExport($order)
&& !$this->isOrderPointSaleExcludeExport($order)) {
$ordersArrayFilter[] = $order;
}
}

return $ordersArrayFilter;
}

public function isOrderUserExcludeExport(Order $order): bool
{
return $order->user && $order->user->exclude_export_shopping_cart_labels;
}

public function isOrderPointSaleExcludeExport(Order $order): bool
{
return $order->pointSale && $order->pointSale->exclude_export_shopping_cart_labels;
}

public function getCss(): string
{
return '
@@ -62,46 +95,30 @@ class DistributionShoppingCartLabelsPdfGenerator extends AbstractGenerator
}
.shopping-cart-label {
box-sizing: border-box;
width: 49.9%;
height: 368px;
float: left;
text-align: center;
}
.shopping-cart-label.shopping-cart-label-0,
.shopping-cart-label.shopping-cart-label-2 {
border-bottom: solid 1px #e0e0e0;
border-right: solid 1px #e0e0e0;
}
.shopping-cart-label.shopping-cart-label-1,
.shopping-cart-label.shopping-cart-label-3 {
border-bottom: solid 1px #e0e0e0;
}
.shopping-cart-label.shopping-cart-label-4 {
border-right: solid 1px #e0e0e0;
-webkit-column-break-inside:avoid;
column-break-inside: avoid;
-webkit-page-break-inside:avoid;
page-break-inside: avoid;
}
.shopping-cart-label .inner {
padding: 20px;
padding: 8px;
}
.shopping-cart-label .username {
margin-bottom: 3px;
font-weight: bold;
font-size: 18px;
font-size: 13px;
}
.shopping-cart-label .point-sale {
margin-bottom: 10px;
font-size: 15px;
font-size: 10px;
line-height: 12px;
text-transform: uppercase;
margin-bottom: 3px;
}
.shopping-cart-label .products {
font-size: 10px;
}
';
}

+ 14
- 26
common/logic/Distribution/Distribution/Module/DistributionModule.php Просмотреть файл

@@ -2,26 +2,25 @@

namespace common\logic\Distribution\Distribution\Module;

use common\logic\AbstractManager;
use common\logic\AbstractModule;
use common\logic\Distribution\Distribution\Export\DistributionReport2CsvGenerator;
use common\logic\Distribution\Distribution\Export\DistributionReportCsvGenerator;
use common\logic\Distribution\Distribution\Export\DistributionReportGridPdfGenerator;
use common\logic\Distribution\Distribution\Export\DistributionReportPdfGenerator;
use common\logic\Distribution\Distribution\Export\DistributionReportTotalProductCsvGenerator;
use common\logic\Distribution\Distribution\Export\DistributionShoppingCartLabelsPdfGenerator;
use common\logic\Distribution\Distribution\Repository\DistributionRepository;
use common\logic\Distribution\Distribution\Service\DistributionBuilder;
use common\logic\Distribution\Distribution\Service\DistributionDefinition;
use common\logic\Distribution\Distribution\Service\DistributionReportCsvGenerator;
use common\logic\Distribution\Distribution\Service\DistributionReportGridPdfGenerator;
use common\logic\Distribution\Distribution\Service\DistributionReportPdfGenerator;
use common\logic\Distribution\Distribution\Service\DistributionShoppingCartLabelsPdfGenerator;
use common\logic\Distribution\Distribution\Service\DistributionSolver;
use common\logic\Distribution\Distribution\Service\ExportManager;

/**
* @mixin DistributionDefinition
* @mixin DistributionSolver
* @mixin DistributionRepository
* @mixin DistributionBuilder
* @mixin DistributionReportCsvGenerator
* @mixin DistributionReportGridPdfGenerator
* @mixin DistributionReportPdfGenerator
* @mixin DistributionShoppingCartLabelsPdfGenerator
* @mixin ExportManager
*/
class DistributionModule extends AbstractModule
{
@@ -32,9 +31,13 @@ class DistributionModule extends AbstractModule
DistributionSolver::class,
DistributionRepository::class,
DistributionBuilder::class,

ExportManager::class,
DistributionReport2CsvGenerator::class,
DistributionReportCsvGenerator::class,
DistributionReportGridPdfGenerator::class,
DistributionReportPdfGenerator::class,
DistributionReportTotalProductCsvGenerator::class,
DistributionShoppingCartLabelsPdfGenerator::class
];
}
@@ -59,23 +62,8 @@ class DistributionModule extends AbstractModule
return DistributionBuilder::getInstance();
}

public function getReportCsvGenerator(): DistributionReportCsvGenerator
{
return DistributionReportCsvGenerator::getInstance();
}

public function getReportGridPdfGenerator(): DistributionReportGridPdfGenerator
{
return DistributionReportGridPdfGenerator::getInstance();
}

public function getReportPdfGenerator(): DistributionReportPdfGenerator
{
return DistributionReportPdfGenerator::getInstance();
}

public function getShoppingCartLabelsPdfGenerator(): DistributionShoppingCartLabelsPdfGenerator
public function getExportManager(): ExportManager
{
return DistributionShoppingCartLabelsPdfGenerator::getInstance();
return ExportManager::getInstance();
}
}

+ 151
- 0
common/logic/Distribution/Distribution/Service/ExportManager.php Просмотреть файл

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

namespace common\logic\Distribution\Distribution\Service;

use common\logic\AbstractManager;
use common\logic\Distribution\Distribution\Export\DistributionReport2CsvGenerator;
use common\logic\Distribution\Distribution\Export\DistributionReportCsvGenerator;
use common\logic\Distribution\Distribution\Export\DistributionReportGridPdfGenerator;
use common\logic\Distribution\Distribution\Export\DistributionReportPdfGenerator;
use common\logic\Distribution\Distribution\Export\DistributionReportTotalProductCsvGenerator;
use common\logic\Distribution\Distribution\Export\DistributionShoppingCartLabelsPdfGenerator;
use common\logic\Distribution\Distribution\Model\Distribution;
use common\logic\Producer\Producer\Model\Producer;
use yii\base\ErrorException;
use yii\widgets\ActiveForm;

class ExportManager extends AbstractManager
{
const ORDERS_PDF = 'orders_pdf';
const ORDERS_GRID_PDF = 'orders_grid_pdf';
const ORDERS1_CSV = 'orders1_csv';
const ORDERS2_CSV = 'orders2_csv';
const TOTAL_PRODUCTS_CSV = 'total_products_csv';
const SHOPPING_CART_LABELS_PDF = 'shopping_cart_labels_pdf';

public function getAll(): array
{
return [
self::ORDERS_PDF => [
'Commandes (PDF)',
DistributionReportPdfGenerator::class,
],
self::ORDERS_GRID_PDF => [
'Commandes grille (PDF)',
DistributionReportGridPdfGenerator::class,
],
self::ORDERS1_CSV => [
'Commandes #1 (CSV)',
DistributionReportCsvGenerator::class,
],
self::ORDERS2_CSV => [
'Commandes #2 (CSV)',
DistributionReport2CsvGenerator::class,
],
self::TOTAL_PRODUCTS_CSV => [
'Totaux produits (CSV)',
DistributionReportTotalProductCsvGenerator::class,
],
self::SHOPPING_CART_LABELS_PDF => [
'Étiquettes (PDF)',
DistributionShoppingCartLabelsPdfGenerator::class,
]
];
}

public function getExport(string $exportName): array
{
$exportsArray = $this->getAll();
return $exportsArray[$exportName];
}

public function getExportLabel(string $exportName): string
{
$export = $this->getExport($exportName);
return $export[0];
}

public function generate(string $exportName, Distribution $distribution, bool $save = false)
{
return $this->getGenerator($exportName)->generate($distribution, $save);
}

public function getGenerator(string $exportName)
{
if($this->exist($exportName)) {
$export = $this->getExport($exportName);
$classGenerator = $export[1];
return $classGenerator::getInstance();
}
else {
throw new ErrorException("Cet export n'existe pas.");
}
}

public function exist(string $exportName): bool
{
return array_key_exists($exportName, $this->getAll());
}

public function isEnabled(string $exportName): bool
{
return $this->exist($exportName) && $this->producerHasOptionExportEnabled($exportName);
}

public function getAjaxArray(Distribution $distribution): array
{
$datas = [];
$exportsArray = $this->getAll();

foreach($exportsArray as $exportName => $export) {
if($this->isEnabled($exportName)) {
$datas[] = $this->buildAjaxArray($distribution, $exportName, $export);
}
}

return $datas;
}

public function buildAjaxArray(Distribution $distribution, string $exportName, array $export): array
{
return [
'name' => $exportName,
'label' => $export[0],
'url' => \Yii::$app->urlManagerBackend->createUrl([
'distribution/export',
'date' => $distribution->date,
'name' => $exportName
])
];
}

private function producerHasOptionExportEnabled(string $exportName): ?bool
{
$producer = $this->getProducerContext();
$fieldOptionExport = $this->getProducerFieldOptionExport($exportName);
return $producer->$fieldOptionExport;
}

private function getProducerFieldOptionExport(string $exportName): string
{
return 'option_distribution_export_'.$exportName;
}

public function getProducerFormCheckboxes(ActiveForm $form, Producer $producer): string
{
$html = '';
$exportsArray = $this->getAll();

foreach($exportsArray as $exportName => $export) {
$html .= $this->getProducerFormCheckbox($form, $producer, $exportName);
}

return $html;
}

public function getProducerFormCheckbox(ActiveForm $form, Producer $producer, string $exportName): string
{
return $form->field($producer, $this->getProducerFieldOptionExport($exportName))
->checkbox(['label' => $this->getExportLabel($exportName)]);
}
}

+ 10
- 9
common/logic/Order/Order/Repository/OrderRepository.php Просмотреть файл

@@ -208,7 +208,7 @@ class OrderRepository extends AbstractRepository
* Retourne le résumé du panier au format HTML.
* @TODO : à déplacer dans OrderSolver
*/
public function getCartSummary(Order $order, $htmlFormat = true): string
public function getCartSummary(Order $order, bool $htmlFormat = true): string
{
if (!isset($order->productOrder)) {
$order->productOrder = $this->productOrderRepository->findProductOrdersByOrder($order);
@@ -217,17 +217,18 @@ class OrderRepository extends AbstractRepository
$html = '';
$i = 0;
$count = count($order->productOrder);
foreach ($order->productOrder as $p) {
if (isset($p->product)) {
$html .= Html::encode($p->product->name) . ' (' . $p->quantity . '&nbsp;' . $this->productSolver->strUnit(
$p->unit,
'wording_short',
true
) . ')';
foreach ($order->productOrder as $productOrder) {
if (isset($productOrder->product)) {
$html .=
'<strong>' . $productOrder->quantity . ($htmlFormat ? '&nbsp;' : ' '). $this->productSolver->strUnit($productOrder->product, 'wording_short', true) . '</strong> '.
Html::encode($productOrder->product->name);
if (++$i != $count) {
if ($htmlFormat) {
$html .= '<br />';
} else {
}
else {
$html .= "\n";
}
}

+ 1
- 0
common/logic/Order/Order/Service/OrderDocumentManager.php Просмотреть файл

@@ -37,6 +37,7 @@ class OrderDocumentManager extends AbstractManager
$firstOrder = $this->orderRepository->findOneOrderById((int)$idOrders[key($idOrders)]);
$ordersArray = Order::searchAll(['id' => $idOrders,]);
$deliveryNote = $this->deliveryNoteRepository->getOneDeliveryNoteExistingFromOrders($ordersArray);
$deliveryNote = $this->deliveryNoteBuilder->deleteDeliveryNoteIfStatusDraft($deliveryNote);

if ($deliveryNote && $this->documentSolver->isStatusValid($deliveryNote)) {
throw new Exception("Vous ne pouvez pas modifier un bon de livraison déjà validé.");

+ 37
- 23
common/logic/Order/Order/Service/OrderSolver.php Просмотреть файл

@@ -7,6 +7,7 @@ use common\logic\AbstractService;
use common\logic\Document\Document\Model\Document;
use common\logic\Document\Document\Service\DocumentSolver;
use common\logic\Order\Order\Model\Order;
use common\logic\Order\ProductOrder\Service\ProductOrderSolver;
use common\logic\Payment\Model\Payment;
use common\logic\Payment\Service\PaymentSolver;
use common\logic\PointSale\PointSale\Model\PointSale;
@@ -24,6 +25,7 @@ class OrderSolver extends AbstractService implements SolverInterface
protected DocumentSolver $documentSolver;
protected PaymentSolver $paymentSolver;
protected ProducerSolver $producerSolver;
protected ProductOrderSolver $productOrderSolver;

public function loadDependencies(): void
{
@@ -31,6 +33,7 @@ class OrderSolver extends AbstractService implements SolverInterface
$this->userSolver = $this->loadService(UserSolver::class);
$this->paymentSolver = $this->loadService(PaymentSolver::class);
$this->producerSolver = $this->loadService(ProducerSolver::class);
$this->productOrderSolver = $this->loadService(ProductOrderSolver::class);
}

public function getFieldNameAmount($typeTotal = Order::AMOUNT_TOTAL, string $typeField = ''): string
@@ -198,22 +201,16 @@ class OrderSolver extends AbstractService implements SolverInterface
return 0;
}

public function getProductQuantityPieces(Product $product, array $orders): float
public function getProductQuantityPiecesByOrders(Product $product, array $ordersArray): float
{
$quantity = 0;

if (isset($orders) && is_array($orders) && count($orders)) {
foreach ($orders as $c) {
if (is_null($c->date_delete)) {
foreach ($c->productOrder as $po) {
if ($po->id_product == $product->id) {
if ($po->unit == 'piece') {
$quantity += $po->quantity;
} else {
if (isset($po->product) && $po->product->weight > 0) {
$quantity += ($po->quantity * Product::$unitsArray[$po->unit]['coefficient']) / $po->product->weight;
}
}
if (count($ordersArray)) {
foreach ($ordersArray as $order) {
if (is_null($order->date_delete)) {
foreach ($order->productOrder as $productOrder) {
if ($productOrder->id_product == $product->id) {
$quantity += $this->productOrderSolver->getQuantityPieces($productOrder);
}
}
}
@@ -226,19 +223,18 @@ class OrderSolver extends AbstractService implements SolverInterface
/**
* Retourne la quantité d'un produit donné de plusieurs commandes.
*/
public function getProductQuantity(Product $product, array $orders, bool $ignoreCancel = false, string $unit = null): float
public function getProductQuantity(Product $product, array $ordersArray, bool $ignoreCancel = false, string $unit = null): float
{
$quantity = 0;

if (isset($orders) && is_array($orders) && count($orders)) {
foreach ($orders as $c) {
if (is_null($c->date_delete) || $ignoreCancel) {
foreach ($c->productOrder as $po) {
if ($po->id_product == $product->id &&
((is_null($unit) && $po->product->unit == $po->unit) || (!is_null($unit) && strlen(
$unit
) && $po->unit == $unit))) {
$quantity += $po->quantity;
if (count($ordersArray)) {
foreach ($ordersArray as $order) {
if (is_null($order->date_delete) || $ignoreCancel) {
foreach ($order->productOrder as $productOrder) {
if ($productOrder->id_product == $product->id &&
((is_null($unit) && $productOrder->product->unit == $productOrder->unit)
|| (!is_null($unit) && strlen($unit) && $productOrder->unit == $unit))) {
$quantity += $productOrder->quantity;
}
}
}
@@ -493,4 +489,22 @@ class OrderSolver extends AbstractService implements SolverInterface

return null;
}

public function hasPhone(Order $order): bool
{
if($order->user && $order->user->phone) {
return true;
}

return false;
}

public function getPhone(Order $order): string
{
if($this->hasPhone($order)) {
return $order->user->phone;
}

return '';
}
}

+ 46
- 3
common/logic/Order/ProductOrder/Service/ProductOrderSolver.php Просмотреть файл

@@ -4,15 +4,58 @@ namespace common\logic\Order\ProductOrder\Service;

use common\helpers\Price;
use common\logic\AbstractService;
use common\logic\Config\Unit\Service\UnitSolver;
use common\logic\Order\Order\Model\Order;
use common\logic\Order\ProductOrder\Model\ProductOrder;
use common\logic\Product\Product\Service\ProductSolver;
use common\logic\SolverInterface;

class ProductOrderSolver extends AbstractService implements SolverInterface
{
/**
* Retourne le prix du produit avec taxe
*/
protected UnitSolver $unitSolver;
protected ProductSolver $productSolver;

public function loadDependencies(): void
{
$this->unitSolver = $this->loadService(UnitSolver::class);
$this->productSolver = $this->loadService(ProductSolver::class);
}

public function getQuantityPriorityPieces(ProductOrder $productOrder): string
{
$quantityPieces = $this->getQuantityPieces($productOrder);
if($quantityPieces) {
return $quantityPieces;
}
else {
return $this->getQuantityWithUnit($productOrder);
}
}

public function getQuantityWithUnit(ProductOrder $productOrder): string
{
return $productOrder->quantity.' '.$this->productSolver->strUnit($productOrder->product);
}

public function getQuantityPieces(ProductOrder $productOrder): float
{
if ($productOrder->unit == 'piece') {
return $productOrder->quantity;
}
else {
if ($productOrder->product && $productOrder->product->weight > 0) {
return $productOrder->quantity / $this->productSolver->getWeightUnitReference($productOrder->product);
}
}

return 0;
}

public function getQuantityToCoefficientOfUnit(ProductOrder $productOrder): float
{
return $productOrder->quantity * $this->unitSolver->getUnitCoefficient($productOrder->unit);
}

public function getPriceWithTax(ProductOrder $productOrder)
{
return Price::getPriceWithTax($productOrder->price, $productOrder->taxRate->value);

+ 3
- 2
common/logic/PointSale/PointSale/Model/PointSale.php Просмотреть файл

@@ -80,7 +80,7 @@ class PointSale extends ActiveRecordCommon
[['point_production', 'credit', 'delivery_monday', 'delivery_tuesday',
'delivery_wednesday', 'delivery_thursday', 'delivery_friday',
'delivery_saturday', 'delivery_sunday', 'default', 'is_bread_box',
'button_generate_delivery_note_point_sale', 'button_generate_delivery_note_each_user'], 'boolean'],
'button_generate_delivery_note_point_sale', 'button_generate_delivery_note_each_user', 'exclude_export_shopping_cart_labels'], 'boolean'],
['point_production', 'default', 'value' => 0],
[['id_producer', 'id_user', 'maximum_number_orders', 'status'], 'integer'],
['id_producer', 'required'],
@@ -126,7 +126,8 @@ class PointSale extends ActiveRecordCommon
'bread_box_code' => 'Code boîte à pain',
'status' => 'Statut',
'button_generate_delivery_note_point_sale' => 'Activer le bouton de génération de bon de livraison par point de vente',
'button_generate_delivery_note_each_user' => 'Activer le bouton de génération de bon de livraison par client'
'button_generate_delivery_note_each_user' => 'Activer le bouton de génération de bon de livraison par client',
'exclude_export_shopping_cart_labels' => "Exclure de l'export d'étiquettes",
];
}


+ 21
- 7
common/logic/Producer/Producer/Model/Producer.php Просмотреть файл

@@ -164,7 +164,9 @@ class Producer extends ActiveRecordCommon
'option_billing_reduction_percentage',
'dolibarr_socid',
'dolibarr_product_id',
'option_weeks_distributions_activated_in_advance'
'option_weeks_distributions_activated_in_advance',
'option_document_height_logo',
'export_shopping_cart_labels_number_per_column'
],
'integer'
],
@@ -261,7 +263,12 @@ class Producer extends ActiveRecordCommon
'option_export_display_product_reference',
'option_allow_order_guest',
'option_delivery',
'option_display_export_grid',
'option_distribution_export_shopping_cart_labels_pdf',
'option_distribution_export_total_products_csv',
'option_distribution_export_orders1_csv',
'option_distribution_export_orders2_csv',
'option_distribution_export_orders_pdf',
'option_distribution_export_orders_grid_pdf',
'option_stripe_mode_test',
'option_notify_producer_order_summary',
'option_billing_reduction',
@@ -402,14 +409,20 @@ class Producer extends ActiveRecordCommon
'option_dashboard_number_distributions' => 'Nombre de distributions affichées sur le tableau de board',
'option_dashboard_date_start' => 'Date de début',
'option_dashboard_date_end' => 'Date de fin',
'option_csv_export_all_products' => 'Exporter tous les produits dans le fichier récapitulatif (CSV)',
'option_csv_export_by_piece' => 'Exporter les produits par pièce dans le fichier récapitulatif (CSV)',
'option_export_display_column_delivery_note' => "Commandes (PDF) : afficher une colonne bon de livraison",
'option_csv_export_all_products' => "Commandes #1 (CSV) : exporter tous les produits",
'option_csv_export_by_piece' => 'Commandes #1 (CSV) : exporter les produits par pièce',
'option_order_reference_type' => 'Type de référence',
'option_export_display_product_reference' => 'Afficher la référence des produits au moment de l\'export',
'option_allow_order_guest' => 'Autoriser les visiteurs à passer commande (création de compte à la fin du tunnel)',
'option_order_entry_point' => 'Point d\'entrée par point de vente ou par date',
'option_delivery' => 'Proposer la livraison à domicile',
'option_display_export_grid' => 'Afficher l\'export grille dans les distributions',
'option_distribution_export_shopping_cart_labels_pdf' => 'Étiquettes (PDF)',
'option_distribution_export_total_products_csv' => 'Totaux produits (CSV)',
'option_distribution_export_orders1_csv' => 'Commandes 1 (CSV)',
'option_distribution_export_orders2_csv' => 'Commandes 2 (CSV)',
'option_distribution_export_orders_pdf' => 'Commandes (PDF)',
'option_distribution_export_orders_grid_pdf' => 'Commandes grille (PDF)',
'document_display_product_description' => 'Documents : afficher la description des produits',
'option_notify_producer_order_summary' => 'Recevoir les récapitulatifs de commande par email',
'option_billing_type' => 'Type de facturation',
@@ -434,9 +447,10 @@ class Producer extends ActiveRecordCommon
'admin_comment' => 'Commentaire',
'dolibarr_socid' => 'Dolibarr : id user',
'dolibarr_product_id' => 'Dolibarr : id produit',
'option_export_display_column_delivery_note' => "Récapitulatif PDF : afficher une colonne bon de livraison",
'option_weeks_distributions_activated_in_advance' => "Semaines de distributions à activer à l'avance",
'option_invoice_only_based_on_delivery_notes' => 'Facturer uniquement sur la base des bons de livraison'
'option_invoice_only_based_on_delivery_notes' => 'Facturer uniquement sur la base des bons de livraison',
'option_document_height_logo' => 'Hauteur du logo dans les documents',
'export_shopping_cart_labels_number_per_column' => "Étiquettes (PDF) : nombre d'étiquettes par colonne",
];
}


+ 1
- 1
common/logic/Product/Product/Model/Product.php Просмотреть файл

@@ -198,7 +198,7 @@ class Product extends ActiveRecordCommon implements StatusInterface
parent::afterFind();

$productSolver = ProductSolver::getInstance();
$this->wording_unit = $productSolver->strUnit($this->unit);
$this->wording_unit = $productSolver->strUnit($this);
$this->price_with_tax = $productSolver->getPriceWithTax($this);
}


+ 39
- 35
common/logic/Product/Product/Service/ProductSolver.php Просмотреть файл

@@ -5,6 +5,8 @@ namespace common\logic\Product\Product\Service;
use common\helpers\GlobalParam;
use common\helpers\Price;
use common\logic\AbstractService;
use common\logic\Config\Unit\Service\UnitDefinition;
use common\logic\Config\Unit\Service\UnitSolver;
use common\logic\PointSale\PointSale\Model\PointSale;
use common\logic\PointSale\PointSale\Service\PointSaleSolver;
use common\logic\Product\Product\Model\Product;
@@ -13,15 +15,49 @@ use common\logic\SolverInterface;

class ProductSolver extends AbstractService implements SolverInterface
{
protected UnitSolver $unitSolver;
protected ProductPriceSolver $productPriceSolver;
protected PointSaleSolver $pointSaleSolver;

public function loadDependencies(): void
{
$this->unitSolver = $this->loadService(UnitSolver::class);
$this->productPriceSolver = $this->loadService(ProductPriceSolver::class);
$this->pointSaleSolver = $this->loadService(PointSaleSolver::class);
}

public function getUnitCoefficient(Product $product): int
{
return $this->unitSolver->getUnitCoefficient($product->unit);
}

public function getUnitReference(Product $product): string
{
return $this->unitSolver->getUnitReference($product->unit);
}

public function strUnit(Product $product, string $format = UnitDefinition::WORDING_SHORT, bool $unitReference = false): string
{
return $this->unitSolver->strUnit($product->unit, $format, $unitReference);
}

public function getWeightUnitReference(Product $product): float
{
if($product->weight) {
return $product->weight / 1000;
}

return 0;
}

public function getWeightAsString(Product $product): string
{
if ($product->weight) {
return $product->weight . ' g';
}
return '';
}

public function getPrice(Product $product, array $params = []): ?float
{
$specificPriceArray = $product->productPrice;
@@ -123,38 +159,6 @@ class ProductSolver extends AbstractService implements SolverInterface
return $product->name;
}

public function getRefUnit(string $unit): string
{
if (isset(Product::$unitsArray[$unit]) && isset(Product::$unitsArray[$unit]['ref_unit'])) {
return Product::$unitsArray[$unit]['ref_unit'];
}

return $unit;
}

/**
* Retourne le libellé d'une unité.
*/
public function strUnit(string $unit, $format = 'wording_short', $unitInDb = false): string
{
$strUnit = '';

if ($unitInDb) {
if ($unit == 'g') {
$unit = 'kg';
}
if ($unit == 'mL') {
$unit = 'L';
}
}

if (isset(Product::$unitsArray[$unit]) && isset(Product::$unitsArray[$unit][$format])) {
$strUnit = Product::$unitsArray[$unit][$format];
}

return $strUnit;
}

public function hasPriceWithQuantityZero(array $priceArray): bool
{
foreach ($priceArray as $price) {
@@ -233,7 +237,7 @@ class ProductSolver extends AbstractService implements SolverInterface
{
$productArrayFilter = [];

if($pointSale) {
if ($pointSale) {
foreach ($productArray as $product) {
if ($this->isAvailableOnPointSale($product, $pointSale)) {
$productArrayFilter[] = $product;
@@ -248,7 +252,7 @@ class ProductSolver extends AbstractService implements SolverInterface
{
$potentialRevenues = 0;

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

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

+ 1
- 1
common/logic/Subscription/Subscription/Service/SubscriptionSolver.php Просмотреть файл

@@ -81,7 +81,7 @@ class SubscriptionSolver extends AbstractService implements SolverInterface
foreach($subscription->productSubscription as $productSubscription)
{
if(isset($productSubscription->product) && $productSubscription->product) {
$html .= Html::encode($productSubscription->product->name).' ('.($productSubscription->quantity * Product::$unitsArray[$productSubscription->product->unit]['coefficient']) . '&nbsp'. $this->productSolver->strUnit($productSubscription->product->unit, 'wording_short').')<br />' ;
$html .= Html::encode($productSubscription->product->name).' ('.($productSubscription->quantity * Product::$unitsArray[$productSubscription->product->unit]['coefficient']) . '&nbsp'. $this->productSolver->strUnit($productSubscription->product, 'wording_short').')<br />' ;
}
else {
$html .= 'Produit non défini<br />' ;

+ 5
- 2
common/logic/User/User/Model/User.php Просмотреть файл

@@ -103,7 +103,9 @@ class User extends ActiveRecordCommon implements IdentityInterface
public function rules()
{
return [
[['no_mail', 'mail_distribution_monday', 'mail_distribution_tuesday', 'mail_distribution_wednesday', 'mail_distribution_thursday', 'mail_distribution_friday', 'mail_distribution_saturday', 'mail_distribution_sunday', 'is_main_contact', 'newsletter'], 'boolean'],
[['no_mail', 'mail_distribution_monday', 'mail_distribution_tuesday', 'mail_distribution_wednesday',
'mail_distribution_thursday', 'mail_distribution_friday', 'mail_distribution_saturday',
'mail_distribution_sunday', 'is_main_contact', 'newsletter', 'exclude_export_shopping_cart_labels'], 'boolean'],
[['lastname', 'name', 'phone', 'address', 'type', 'name_legal_person', 'evoliz_code'], 'string'],
['lastname', 'verifyOneName', 'skipOnError' => false, 'skipOnEmpty' => false],
['email', 'email', 'message' => 'Cette adresse email n\'est pas valide'],
@@ -146,7 +148,8 @@ class User extends ActiveRecordCommon implements IdentityInterface
'product_price_percent' => 'Prix produits : pourcentage',
'user_groups' => "Groupes d'utilisateurs",
'evoliz_code' => 'Code client Evoliz',
'newsletter' => "Inscrit au bulletin d'information"
'newsletter' => "Inscrit au bulletin d'information",
'exclude_export_shopping_cart_labels' => "Exclure de l'export d'étiquettes",
];
}


+ 1
- 1
common/logic/User/User/Service/UsersCreditCsvGenerator.php Просмотреть файл

@@ -41,7 +41,7 @@ class UsersCreditCsvGenerator extends AbstractGenerator
$this->userSolver->getUsernameFromArray($user, true),
$user['email'],
$user['phone'],
CSV::formatPrice($user['credit']),
CSV::formatNumber($user['credit']),
];
}


+ 29
- 0
common/versions/23.10.E.php Просмотреть файл

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

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

version(
'30/10/2023',
[
[
"[Administration] Distribution > nouvel export commandes CSV disponible (Paramètres > Exports)",
"[Administration] Distribution > étiquettes : finalisation première version (activer l'export dans Paramètres > Exports)",
"[Administration] Documents > PDF : hauteur du logo paramétrable (Paramètres > Facturation > Hauteur du logo dans les documents)",,
],
[
"[Administration] Utilisateurs > liste : rajout du nombre d'utilisateurs",
"[Administration] Distributions : correctif regénération BL pour un point de vente avec une commande supplémentaire"
]
],
[
[
],
[
"[Administration] Switch producteur : rester sur la même page",
"[Technique] Refactoring UnitModule"
]
],
$userCurrent
);

?>

+ 4
- 3
console/commands/ActiveDistributionsInAdvanceController.php Просмотреть файл

@@ -11,15 +11,16 @@ class ActiveDistributionsInAdvanceController extends Controller
public function actionIndex()
{
$producerModule = ProducerModule::getInstance();
$distributionModule =DistributionModule::getInstance();
$distributionModule = DistributionModule::getInstance();

$producersArray = $producerModule->findProducersActive();
foreach($producersArray as $producer) {
\Yii::$app->logic->setProducerContext($producer);
$weeksDistributionsActivatedInAdvance = $producerModule->getConfig('option_weeks_distributions_activated_in_advance');
$weeksDistributionsActivatedInAdvance = $producerModule->getSolver()->getConfig('option_weeks_distributions_activated_in_advance');
if($weeksDistributionsActivatedInAdvance) {
$date = new \DateTime('+'.$weeksDistributionsActivatedInAdvance.' weeks');
$distributionModule->activeDistributionByDate($date);
$distributionModule->getBuilder()->activeDistributionByDate($date);
echo $producer->name. ' : distribution du ' . $date->format('d/m/Y') .' activée' ."\n";
}
}
}

+ 164
- 0
console/commands/ClosingOrdersController.php Просмотреть файл

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

namespace console\commands;

use common\helpers\MeanPayment;
use common\logic\Distribution\Distribution\Model\Distribution;
use common\logic\Distribution\Distribution\Module\DistributionModule;
use common\logic\Distribution\Distribution\Service\ExportManager;
use common\logic\Order\Order\Model\Order;
use common\logic\Order\Order\Module\OrderModule;
use common\logic\Payment\Module\PaymentModule;
use common\logic\Producer\Producer\Model\Producer;
use common\logic\Producer\Producer\Module\ProducerModule;
use common\logic\User\User\Model\User;
use common\logic\User\User\Module\UserModule;
use yii\console\Controller;

class ClosingOrdersController extends Controller
{
public $date;
public $hour;
public $notification;

public function options($actionID)
{
return [
'date',
'hour',
'notification'
];
}

public function optionAliases()
{
return [
'date' => 'date',
'hour' => 'hour',
'notification' => 'notification'
];
}

public function actionIndex()
{
// exemple tâche planifiée : ./yii closing-orders -notification=1

$producerModule = ProducerModule::getInstance();
$distributionModule = DistributionModule::getInstance();
$orderModule = OrderModule::getInstance();
$userModule = UserModule::getInstance();

[$date, $hour] = $this->getDateHour();
$arrayProducers = $producerModule->getRepository()->findProducers();
$userSystem = $userModule->getRepository()->findOneUserById(User::ID_USER_SYSTEM)

foreach($arrayProducers as $producer) {
\Yii::$app->logic->setProducerContext($producer);
$distribution = $distributionModule->getRepository()->findOneDistribution($date, true);

if($distribution) {
// @TODO : gérer les horaires spécifiques
if($hour == $producer->order_deadline || !$hour) {
$ordersArray = $orderModule->getRepository()->findOrdersByDistribution($distribution);

foreach($ordersArray as $order) {
$orderModule->getBuilder()->initOrder($order);

$this->payOrder($order, $userSystem);
$this->notifyProducer($distribution);
}
}
}
}
}

public function notifyProducer(Distribution $distribution)
{
$producerModule = ProducerModule::getInstance();

if ($this->notification
&& $producerModule->getSolver()->getConfig('option_notify_producer_order_summary')) {

$mail = $this->buildMailNotificationProducer($distribution);
$this->sendMailNotificationProducer($mail, $distribution->producer);
}
}

public function buildMailNotificationProducer(Distribution $distribution)
{
$orderModule = OrderModule::getInstance();
$distributionModule = DistributionModule::getInstance();

$ordersArray = $orderModule->getRepository()->findOrdersByDistribution($distribution);
$mail = \Yii::$app->mailer->compose(
[
'html' => '@common/mail/cronOrdersSummary-html',
'text' => '@common/mail/cronOrdersSummary-text',
], [
'date' => $distribution->date,
'orders' => $ordersArray
]
)->setFrom([\Yii::$app->parameterBag->get('adminEmail') => 'Opendistrib']);

if (count($ordersArray)) {
$subject = '[Opendistrib] Commandes du ' . date('d/m', strtotime($distribution->date));
// @TODO : envoyer uniquement les exports qui sont activés dans les paramètres du producteur
$distributionModule->getExportManager()->generate(ExportManager::ORDERS_PDF, $distribution, true);
$mail->attach(\Yii::getAlias('@app/web/pdf/Commandes-' . $distribution->date . '-' . $distribution->producer->id . '.pdf'));
} else {
$subject = '[Opendistrib] Aucune commande';
}
$mail->setSubject($subject);

return $mail;
}

public function sendMailNotificationProducer($mail, Producer $producer)
{
$userModule = UserModule::getInstance();
$usersArray = $userModule->getRepository()->findUsersByProducer($producer);

foreach ($usersArray as $user) {
if($user->email && strlen($user->email)) {
$mail->setTo($user->email)->send();
}
}
}

public function payOrder(Order $order, User $userSystem)
{
$paymentModule = PaymentModule::getInstance();
$orderModule = OrderModule::getInstance();

if($orderModule->getRepository()->isCreditAutoPayment($order)
&& $orderModule->getSolver()->getOrderAmount($order, Order::AMOUNT_REMAINING) > 0) {

$paymentModule->getManager()->payOrder(
$order,
MeanPayment::CREDIT,
$userSystem,
false
);
}
}

public function getDateHour(): array
{
$hour = $this->hour;
$date = $this->date;

if(!$date) {
$hour = date('H');
if ($hour == '00') {
$date = date('Y-m-d');
$hour = 24;
} else {
$date = date('Y-m-d', time() + 24 * 60 * 60);
}
}

return [$date, $hour];
}
}

?>

+ 0
- 27
console/commands/DemoAccountController.php Просмотреть файл

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

namespace console\commands;

use common\logic\Distribution\Distribution\Module\DistributionModule;
use common\logic\Producer\Producer\Module\ProducerModule;
use yii\console\Controller;

class DemoAccountController extends Controller
{
public function actionIndex()
{
$producerModule = ProducerModule::getInstance();
$distributionModule =DistributionModule::getInstance();

$producerDemo = $producerModule->findOneProducerDemoAccount();
\Yii::$app->logic->setProducerContext($producerDemo);

if ($producerDemo) {
$dateTime = strtotime("+7 day");
$distribution = $distributionModule->createDistributionIfNotExist(date('Y-m-d', $dateTime));
$distributionModule->activeDistribution($distribution);
}
}
}

?>

+ 39
- 0
console/migrations/m231024_062121_add_column_producer_options_exports.php Просмотреть файл

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

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

/**
* Class m231024_062121_add_column_producer_options_exports
*/
class m231024_062121_add_column_producer_options_exports extends Migration
{
/**
* {@inheritdoc}
*/
public function safeUp()
{
$this->addColumn('producer', 'option_distribution_export_orders_pdf', Schema::TYPE_BOOLEAN.' DEFAULT 1');
$this->addColumn('producer', 'option_distribution_export_orders_grid_pdf', Schema::TYPE_BOOLEAN);
$this->addColumn('producer', 'option_distribution_export_orders1_csv', Schema::TYPE_BOOLEAN.' DEFAULT 1');
$this->addColumn('producer', 'option_distribution_export_orders2_csv', Schema::TYPE_BOOLEAN);
$this->addColumn('producer', 'option_distribution_export_total_products_csv', Schema::TYPE_BOOLEAN);
$this->addColumn('producer', 'option_distribution_export_shopping_cart_labels_pdf', Schema::TYPE_BOOLEAN);

$this->execute("UPDATE producer SET option_distribution_export_orders_grid_pdf = 1 WHERE option_display_export_grid = 1");
$this->dropColumn('producer', 'option_display_export_grid');
}

/**
* {@inheritdoc}
*/
public function safeDown()
{
$this->dropColumn('producer', 'option_distribution_export_shopping_cart_labels_pdf');
$this->dropColumn('producer', 'option_distribution_export_total_products_csv');
$this->dropColumn('producer', 'option_distribution_export_orders1_csv');
$this->dropColumn('producer', 'option_distribution_export_orders2_csv');
$this->dropColumn('producer', 'option_distribution_export_orders_pdf');
$this->dropColumn('producer', 'option_distribution_export_orders_grid_pdf');
}
}

+ 26
- 0
console/migrations/m231024_092428_add_column_producer_option_document_height_logo.php Просмотреть файл

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

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

/**
* Class m231024_092428_add_column_producer_option_document_height_logo
*/
class m231024_092428_add_column_producer_option_document_height_logo extends Migration
{
/**
* {@inheritdoc}
*/
public function safeUp()
{
$this->addColumn('producer', 'option_document_height_logo', Schema::TYPE_INTEGER);
}

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

+ 30
- 0
console/migrations/m231025_064432_add_columns_shopping_cart_labels.php Просмотреть файл

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

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

/**
* Class m231025_064432_add_columns_shopping_cart_labels
*/
class m231025_064432_add_columns_shopping_cart_labels extends Migration
{
/**
* {@inheritdoc}
*/
public function safeUp()
{
$this->addColumn('point_sale','exclude_export_shopping_cart_labels', Schema::TYPE_BOOLEAN);
$this->addColumn('user','exclude_export_shopping_cart_labels', Schema::TYPE_BOOLEAN);
$this->addColumn('producer','export_shopping_cart_labels_number_per_column', Schema::TYPE_INTEGER);
}

/**
* {@inheritdoc}
*/
public function safeDown()
{
$this->dropColumn('point_sale','exclude_export_shopping_cart_labels');
$this->dropColumn('user','exclude_export_shopping_cart_labels');
$this->dropColumn('producer','export_shopping_cart_labels_number_per_column');
}
}

+ 9
- 7
producer/controllers/OrderController.php Просмотреть файл

@@ -43,6 +43,7 @@ use common\helpers\Image;
use common\helpers\Mailjet;
use common\helpers\MeanPayment;
use common\helpers\Password;
use common\logic\Config\Unit\Service\UnitDefinition;
use common\logic\Distribution\Distribution\Model\Distribution;
use common\logic\Order\Order\Model\Order;
use common\logic\Order\ProductOrder\Model\ProductOrder;
@@ -253,9 +254,9 @@ class OrderController extends ProducerBaseController
'price_data' => [
'currency' => 'eur',
'product_data' => [
'name' => $product->name . ' (' . $productOrder->quantity . ' ' . $this->getProductModule()->strUnit(
$product->unit,
'wording_short',
'name' => $product->name . ' (' . $productOrder->quantity . ' ' . $this->getProductModule()->getSolver()->strUnit(
$product,
UnitDefinition::WORDING_SHORT,
true
) . ')',
],
@@ -882,6 +883,7 @@ class OrderController extends ProducerBaseController
Order $order = null
)
{
$unitModule = $this->getUnitModule();
$productModule = $this->getProductModule();
$orderModule = $this->getOrderModule();
$ordersArray = $this->getOrderModule()->findOrdersByDistribution($distribution);
@@ -933,8 +935,8 @@ class OrderController extends ProducerBaseController
$quantityOrder = $orderModule->getProductQuantity($productObject, $ordersArray);
$product['quantity_ordered'] = $quantityOrder;
$product['quantity_remaining'] = $product['quantity_max'] - $quantityOrder;
$product['wording_unit'] = $productModule->strUnit($product['unit'], 'wording_unit', true);
$product['wording_unit_ref'] = $productModule->strUnit($product['unit'], 'wording_short', true);
$product['wording_unit'] = $unitModule->getSolver()->strUnit($product['unit'], UnitDefinition::WORDING_UNIT, true);
$product['wording_unit_ref'] = $unitModule->getSolver()->strUnit($product['unit'], UnitDefinition::WORDING_SHORT, true);

if ($order) {
$quantityOrderUser = $orderModule->getProductQuantity($productObject, [$order], true);
@@ -943,13 +945,13 @@ class OrderController extends ProducerBaseController
$product['quantity_form'] = $quantityOrderUser * $coefficient_unit;
foreach ($order->productOrder as $productOrder) {
if ($productOrder->id_product == $product['id']) {
$product['wording_unit'] = $productModule->strUnit($productOrder->unit, 'wording_unit', true);
$product['wording_unit'] = $productModule->getSolver()->strUnit($productOrder->product, 'wording_unit', true);
$product['step'] = $productOrder->step;
}
}
} else {
$product['quantity_form'] = 0;
$product['wording_unit'] = $productModule->strUnit($product['unit'], 'wording_unit', true);
$product['wording_unit'] = $unitModule->getSolver()->strUnit($product['unit'], 'wording_unit', true);
}
$product['coefficient_unit'] = $coefficient_unit;


+ 5
- 4
producer/controllers/SubscriptionController.php Просмотреть файл

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

use common\forms\SubscriptionForm;
use common\helpers\GlobalParam;
use common\logic\Config\Unit\Service\UnitDefinition;
use common\logic\Product\Product\Model\Product;
use common\logic\Subscription\ProductSubscription\Model\ProductSubscription;
use common\logic\Subscription\Subscription\Model\Subscription;
@@ -264,11 +265,11 @@ class SubscriptionController extends ProducerBaseController
$indexProduct = 0;
foreach ($productsArray as &$product) {
$quantity = 0;
$coefficientUnit = Product::$unitsArray[$product->unit]['coefficient'];
$coefficientUnit = $productModule->getSolver()->getUnitCoefficient($product);
if (isset($arrayProductsSubscription) && count($arrayProductsSubscription)) {
foreach ($arrayProductsSubscription as $productSubscription) {
if ($product->id == $productSubscription->id_product) {
$coefficientUnit = Product::$unitsArray[$productSubscription->product->unit]['coefficient'];
$coefficientUnit = $productModule->getSolver()->getUnitCoefficient($productSubscription->product);
$quantity = $productSubscription->quantity * $coefficientUnit;
}
}
@@ -285,8 +286,8 @@ class SubscriptionController extends ProducerBaseController
'index' => $indexProduct++,
'quantity_form' => $quantity,
'coefficient_unit' => $coefficientUnit,
'wording_unit' => $productModule->strUnit($product->unit, 'wording_unit', true),
'wording_short' => $productModule->strUnit($product->unit, 'wording_short'),
'wording_unit' => $productModule->getSolver()->strUnit($product, UnitDefinition::WORDING_UNIT, true),
'wording_short' => $productModule->getSolver()->strUnit($product),
'price_with_tax' => $productModule->getPriceWithTax($product, [
'user' => $user,
'user_producer' => $userProducer,

+ 1
- 1
producer/views/site/index.php Просмотреть файл

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

Загрузка…
Отмена
Сохранить