Browse Source

Refactoring services #885

refactoring
Guillaume 1 year ago
parent
commit
eacb1fc180
21 changed files with 575 additions and 465 deletions
  1. +16
    -15
      common/logic/Distribution/Distribution/DistributionBuilder.php
  2. +7
    -0
      common/logic/Distribution/Distribution/DistributionRepository.php
  3. +13
    -21
      common/logic/Distribution/PointSaleDistribution/PointSaleDistributionBuilder.php
  4. +7
    -0
      common/logic/Distribution/PointSaleDistribution/PointSaleDistributionRepository.php
  5. +51
    -83
      common/logic/Document/DeliveryNote/DeliveryNote.php
  6. +3
    -3
      common/logic/Document/DeliveryNote/DeliveryNoteContainer.php
  7. +44
    -42
      common/logic/Document/DeliveryNote/DeliveryNoteSearch.php
  8. +25
    -0
      common/logic/Document/DeliveryNote/DeliveryNoteSolver.php
  9. +8
    -133
      common/logic/Document/Document/Document.php
  10. +8
    -0
      common/logic/Document/Document/DocumentInterface.php
  11. +108
    -0
      common/logic/Document/Document/DocumentSolver.php
  12. +0
    -21
      common/logic/Order/Order/Order.php
  13. +16
    -0
      common/logic/Order/Order/OrderRepository.php
  14. +32
    -0
      common/logic/Order/ProductOrder/ProductOrderBuilder.php
  15. +13
    -1
      common/logic/PointSale/PointSale/PointSaleRepository.php
  16. +0
    -52
      common/logic/Product/Product/Product.php
  17. +49
    -1
      common/logic/Product/Product/ProductSolver.php
  18. +0
    -91
      common/logic/Product/ProductPrice/ProductPrice.php
  19. +113
    -0
      common/logic/Product/ProductPrice/ProductPriceSolver.php
  20. +2
    -1
      composer.json
  21. +60
    -1
      composer.lock

+ 16
- 15
common/logic/Distribution/Distribution/DistributionBuilder.php View File

use common\logic\Distribution\ProductDistribution\ProductDistributionRepository; use common\logic\Distribution\ProductDistribution\ProductDistributionRepository;
use common\logic\Order\Order\Order; use common\logic\Order\Order\Order;
use common\logic\Order\Order\OrderRepository; use common\logic\Order\Order\OrderRepository;
use common\logic\Order\ProductOrder\ProductOrderBuilder;
use common\logic\PointSale\PointSale\PointSale; use common\logic\PointSale\PointSale\PointSale;
use common\logic\Producer\Producer\Producer; use common\logic\Producer\Producer\Producer;
use common\logic\Product\Product\Product; use common\logic\Product\Product\Product;
use common\logic\Product\Product\ProductRepository; use common\logic\Product\Product\ProductRepository;
use common\logic\Subscription\Subscription\Subscription; use common\logic\Subscription\Subscription\Subscription;
use common\logic\User\UserProducer\UserProducer; use common\logic\User\UserProducer\UserProducer;
use common\logic\User\UserProducer\UserProducerRepository;


class DistributionBuilder extends BaseService implements BuilderInterface class DistributionBuilder extends BaseService implements BuilderInterface
{ {
protected ProductDistributionRepository $productDistributionRepository; protected ProductDistributionRepository $productDistributionRepository;
protected ProductDistributionBuilder $productDistributionBuilder; protected ProductDistributionBuilder $productDistributionBuilder;
protected OrderRepository $orderRepository; protected OrderRepository $orderRepository;
protected UserProducerRepository $userProducerRepository;
protected ProductOrderBuilder $productOrderBuilder;


public function __construct() public function __construct()
{ {
$this->productRepository = $this->loadService(ProductRepository::class); $this->productRepository = $this->loadService(ProductRepository::class);
$this->productDistributionRepository = $this->loadService(ProductDistributionRepository::class); $this->productDistributionRepository = $this->loadService(ProductDistributionRepository::class);
$this->orderRepository = $this->loadService(OrderRepository::class); $this->orderRepository = $this->loadService(OrderRepository::class);
$this->userProducerRepository = $this->loadService(UserProducerRepository::class);
$this->productOrderBuilder = $this->loadService(ProductOrderBuilder::class);
} }


public function instanciate(Producer $producer, string $date, bool $delivery = true): Distribution public function instanciate(Producer $producer, string $date, bool $delivery = true): Distribution
foreach ($ordersArray as $order) { foreach ($ordersArray as $order) {
foreach ($order->productOrder as $productOrder) { foreach ($order->productOrder as $productOrder) {
if ($productOrder->id_product == $product->id) { if ($productOrder->id_product == $product->id) {
$productOrder->price = $product->price;


$user = false;
$userProducer = false;
$user = null;
$userProducer = null;
if (isset($order->user) && $order->user) { if (isset($order->user) && $order->user) {
$user = $order->user; $user = $order->user;
$userProducer = UserProducer::searchOne([
'id_user' => $user->id,
'id_producer' => $order->distribution->id_producer
]);
$userProducer = $this->userProducerRepository->getOne($user, $distribution->producer);
} }


$productOrder->price = $product->getPrice([
'user' => $user,
'user_producer' => $userProducer,
'point_sale' => $order->pointSale,
'quantity' => $productOrder->quantity
]);

$productOrder->save();
$this->productOrderBuilder->updatePrice(
$productOrder,
$user,
$userProducer,
$order->pointSale,
$productOrder->quantity
);
} }
} }
} }

+ 7
- 0
common/logic/Distribution/Distribution/DistributionRepository.php View File

]; ];
} }


public function getOneById($id): ?Distribution
{
return Distribution::searchOne([
'id' => $id
]);
}

public function getOne(Producer $producer, string $date) public function getOne(Producer $producer, string $date)
{ {
$paramsDistribution = [ $paramsDistribution = [

+ 13
- 21
common/logic/Distribution/PointSaleDistribution/PointSaleDistributionBuilder.php View File

use common\logic\BaseService; use common\logic\BaseService;
use common\logic\BuilderInterface; use common\logic\BuilderInterface;
use common\logic\Distribution\Distribution\Distribution; use common\logic\Distribution\Distribution\Distribution;
use common\logic\Distribution\Distribution\DistributionRepository;
use common\logic\PointSale\PointSale\PointSale; use common\logic\PointSale\PointSale\PointSale;
use common\logic\PointSale\PointSale\PointSaleRepository;


class PointSaleDistributionBuilder extends BaseService implements BuilderInterface class PointSaleDistributionBuilder extends BaseService implements BuilderInterface
{ {
protected PointSaleDistributionRepository $pointSaleDistributionRepository; protected PointSaleDistributionRepository $pointSaleDistributionRepository;
protected PointSaleRepository $pointSaleRepository;
protected DistributionRepository $distributionRepository;


public function __construct() public function __construct()
{ {
$this->pointSaleDistributionRepository = $this->loadService(PointSaleDistributionRepository::class); $this->pointSaleDistributionRepository = $this->loadService(PointSaleDistributionRepository::class);
$this->pointSaleRepository = $this->loadService(PointSaleRepository::class);
$this->distributionRepository = $this->loadService(DistributionRepository::class);
} }


/** /**
{ {
$pointSaleDistribution = $this->pointSaleDistributionRepository->getOne($distribution, $pointSale); $pointSaleDistribution = $this->pointSaleDistributionRepository->getOne($distribution, $pointSale);


if(!$pointSaleDistribution) {
if (!$pointSaleDistribution) {
$pointSaleDistribution = $this->create($distribution, $pointSale); $pointSaleDistribution = $this->create($distribution, $pointSale);
} }


// setAll // setAll
public function createAll(Distribution $distribution, bool $delivery): void public function createAll(Distribution $distribution, bool $delivery): void
{ {
$arrPointsSale = PointSale::find()
->with(['pointSaleDistribution' => function($q) use ($distribution) {
$q->where(['id_distribution' => $distribution->id]);
}])
->where([
'id_producer' => GlobalParam::getCurrentProducerId(),
])
->all();

foreach ($arrPointsSale as $pointSale) {
if(!$pointSale->pointSaleDistribution) {
$pointSaleArray = $this->pointSaleRepository->getByDistribution($distribution);
foreach ($pointSaleArray as $pointSale) {
if (!$pointSale->pointSaleDistribution) {
$this->create($distribution, $pointSale); $this->create($distribution, $pointSale);
} }
} }


$distribution = Distribution::findOne($distribution->id);
if ($distribution) {

$arrPointsSaleDistribution = PointSaleDistribution::searchAll([
'id_distribution' => $distribution->id
]) ;
foreach ($arrPointsSaleDistribution as $pointSaleDistribution) {
$this->initDelivery($pointSaleDistribution, $delivery);
}
$pointSaleDistributionArray = $this->pointSaleDistributionRepository->getByDistribution($distribution);
foreach ($pointSaleDistributionArray as $pointSaleDistribution) {
$this->initDelivery($pointSaleDistribution, $delivery);
} }
} }



+ 7
- 0
common/logic/Distribution/PointSaleDistribution/PointSaleDistributionRepository.php View File

]); ]);
} }


public function getByDistribution(Distribution $distribution)
{
return PointSaleDistribution::searchAll([
'id_distribution' => $distribution->id
]) ;
}

public function countByDistribution(Distribution $distribution): int public function countByDistribution(Distribution $distribution): int
{ {
return PointSaleDistribution::searchCount([ return PointSaleDistribution::searchCount([

+ 51
- 83
common/logic/Document/DeliveryNote/DeliveryNote.php View File

<?php <?php


/**
Copyright distrib (2018)
contact@opendistrib.net
Ce logiciel est un programme informatique servant à aider les producteurs
à distribuer leur production en circuits courts.
Ce logiciel est régi par la licence CeCILL soumise au droit français et
respectant les principes de diffusion des logiciels libres. Vous pouvez
utiliser, modifier et/ou redistribuer ce programme sous les conditions
de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA
sur le site "http://www.cecill.info".
En contrepartie de l'accessibilité au code source et des droits de copie,
de modification et de redistribution accordés par cette licence, il n'est
offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons,
seule une responsabilité restreinte pèse sur l'auteur du programme, le
titulaire des droits patrimoniaux et les concédants successifs.
A cet égard l'attention de l'utilisateur est attirée sur les risques
associés au chargement, à l'utilisation, à la modification et/ou au
développement et à la reproduction du logiciel par l'utilisateur étant
donné sa spécificité de logiciel libre, qui peut le rendre complexe à
manipuler et qui le réserve donc à des développeurs et des professionnels
avertis possédant des connaissances informatiques approfondies. Les
utilisateurs sont donc invités à charger et tester l'adéquation du
logiciel à leurs besoins dans des conditions permettant d'assurer la
sécurité de leurs systèmes et ou de leurs données et, plus généralement,
à l'utiliser et l'exploiter dans les mêmes conditions de sécurité.
Le fait que vous puissiez accéder à cet en-tête signifie que vous avez
pris connaissance de la licence CeCILL, et que vous en avez accepté les
termes.
*/
/**
* Copyright distrib (2018)
*
* contact@opendistrib.net
*
* Ce logiciel est un programme informatique servant à aider les producteurs
* à distribuer leur production en circuits courts.
*
* Ce logiciel est régi par la licence CeCILL soumise au droit français et
* respectant les principes de diffusion des logiciels libres. Vous pouvez
* utiliser, modifier et/ou redistribuer ce programme sous les conditions
* de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA
* sur le site "http://www.cecill.info".
*
* En contrepartie de l'accessibilité au code source et des droits de copie,
* de modification et de redistribution accordés par cette licence, il n'est
* offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons,
* seule une responsabilité restreinte pèse sur l'auteur du programme, le
* titulaire des droits patrimoniaux et les concédants successifs.
*
* A cet égard l'attention de l'utilisateur est attirée sur les risques
* associés au chargement, à l'utilisation, à la modification et/ou au
* développement et à la reproduction du logiciel par l'utilisateur étant
* donné sa spécificité de logiciel libre, qui peut le rendre complexe à
* manipuler et qui le réserve donc à des développeurs et des professionnels
* avertis possédant des connaissances informatiques approfondies. Les
* utilisateurs sont donc invités à charger et tester l'adéquation du
* logiciel à leurs besoins dans des conditions permettant d'assurer la
* sécurité de leurs systèmes et ou de leurs données et, plus généralement,
* à l'utiliser et l'exploiter dans les mêmes conditions de sécurité.
*
* Le fait que vous puissiez accéder à cet en-tête signifie que vous avez
* pris connaissance de la licence CeCILL, et que vous en avez accepté les
* termes.
*/


namespace common\logic\Document\DeliveryNote; namespace common\logic\Document\DeliveryNote;




class DeliveryNote extends Document class DeliveryNote extends Document
{ {
/**
* @inheritdoc
*/
public static function tableName()
{
return 'delivery_note';
}

/*
* Relations
*/

public function getOrders()
{
return $this->relationOrders('id_delivery_note') ;
}

public function getInvoiceId()
{
if($this->orders && count($this->orders) > 0) {
foreach($this->orders as $order) {
if($order->id_invoice) {
return $order->id_invoice;
}
}
}

return false;
}

public function isInvoiced()
{
return (bool) $this->getInvoiceId();
}

public function getInvoice()
{
$invoice = null;
$idInvoice = $this->getInvoiceId();

if($idInvoice) {
$invoice = Invoice::searchOne([
'id' => $idInvoice
]);
}

return $invoice;
}
/**
* @inheritdoc
*/
public static function tableName()
{
return 'delivery_note';
}

/*
* Relations
*/

public function getOrders()
{
return $this->relationOrders('id_delivery_note');
}
} }

+ 3
- 3
common/logic/Document/DeliveryNote/DeliveryNoteContainer.php View File

public function getServices(): array public function getServices(): array
{ {
return [ return [
DeliveryNoteFactory::class,
DeliveryNoteBuilder::class,
DeliveryNoteSolver::class, DeliveryNoteSolver::class,
]; ];
} }


public function getFactory(): DeliveryNoteFactory
public function getFactory(): DeliveryNoteBuilder
{ {
return new DeliveryNoteFactory();
return new DeliveryNoteBuilder();
} }


public function getSolver(): DeliveryNoteSolver public function getSolver(): DeliveryNoteSolver

+ 44
- 42
common/logic/Document/DeliveryNote/DeliveryNoteSearch.php View File

namespace common\logic\Document\DeliveryNote; namespace common\logic\Document\DeliveryNote;


use common\helpers\GlobalParam; use common\helpers\GlobalParam;
use common\logic\PointSale\PointSale\DeliveryNoteRepository;
use yii\data\ActiveDataProvider; use yii\data\ActiveDataProvider;


class DeliveryNoteSearch extends DeliveryNote class DeliveryNoteSearch extends DeliveryNote
{ {
public $id_point_sale ;
public $date_distribution ;
public $id_point_sale;
public $date_distribution;


public function rules()
{
return [
[[], 'safe'],
[['comment', 'address', 'status', 'date_distribution'], 'string'],
[['id_user', 'id_point_sale'], 'integer'],
[['name', 'reference'], 'string', 'max' => 255],
];
}

public function search($params)
{
$optionsSearch = self::defaultOptionsSearch();
public function rules()
{
return [
[[], 'safe'],
[['comment', 'address', 'status', 'date_distribution'], 'string'],
[['id_user', 'id_point_sale'], 'integer'],
[['name', 'reference'], 'string', 'max' => 255],
];
}


$query = DeliveryNote::find()
->with($optionsSearch['with'])
->joinWith($optionsSearch['join_with'])
->where(['delivery_note.id_producer' => GlobalParam::getCurrentProducerId()])
->orderBy('delivery_note.status ASC, delivery_note.reference DESC')
->groupBy('delivery_note.id');
public function search($params)
{
$deliveryNoteRepository = new DeliveryNoteRepository();
$optionsSearch = $deliveryNoteRepository->defaultOptionsSearch();


$dataProvider = new ActiveDataProvider([
'query' => $query,
'sort' => ['attributes' => ['name', 'reference', 'date']],
'pagination' => [
'pageSize' => 20,
],
]);
$query = DeliveryNote::find()
->with($optionsSearch['with'])
->joinWith($optionsSearch['join_with'])
->where(['delivery_note.id_producer' => GlobalParam::getCurrentProducerId()])
->orderBy('delivery_note.status ASC, delivery_note.reference DESC')
->groupBy('delivery_note.id');


$this->load($params);
if (!$this->validate()) {
return $dataProvider;
}
$dataProvider = new ActiveDataProvider([
'query' => $query,
'sort' => ['attributes' => ['name', 'reference', 'date']],
'pagination' => [
'pageSize' => 20,
],
]);


$query->andFilterWhere(['like', 'delivery_note.name', $this->name]);
$query->andFilterWhere(['like', 'delivery_note.reference', $this->reference]);
$query->andFilterWhere(['like', 'delivery_note.status', $this->status]);
$this->load($params);
if (!$this->validate()) {
return $dataProvider;
}


if($this->id_point_sale) {
$query->andWhere(['order.id_point_sale' => $this->id_point_sale]);
}
$query->andFilterWhere(['like', 'delivery_note.name', $this->name]);
$query->andFilterWhere(['like', 'delivery_note.reference', $this->reference]);
$query->andFilterWhere(['like', 'delivery_note.status', $this->status]);


if($this->date_distribution && strlen($this->date_distribution)) {
$query->andFilterWhere(['like', 'distribution.date', date('Y-m-d',strtotime(str_replace('/','-',$this->date_distribution)))]);
}
if ($this->id_point_sale) {
$query->andWhere(['order.id_point_sale' => $this->id_point_sale]);
}


return $dataProvider;
if ($this->date_distribution && strlen($this->date_distribution)) {
$query->andFilterWhere(['like', 'distribution.date', date('Y-m-d', strtotime(str_replace('/', '-', $this->date_distribution)))]);
} }

return $dataProvider;
}
} }

+ 25
- 0
common/logic/Document/DeliveryNote/DeliveryNoteSolver.php View File

namespace common\logic\Document\DeliveryNote; namespace common\logic\Document\DeliveryNote;


use common\logic\BaseService; use common\logic\BaseService;
use common\logic\Document\Invoice\Invoice;
use common\logic\SolverInterface; use common\logic\SolverInterface;


class DeliveryNoteSolver extends BaseService implements SolverInterface class DeliveryNoteSolver extends BaseService implements SolverInterface
{ {
public function getInvoiceId(DeliveryNote $deliveryNote): ?int
{
if($deliveryNote->orders && count($deliveryNote->orders) > 0) {
foreach($deliveryNote->orders as $order) {
if($order->id_invoice) {
return $order->id_invoice;
}
}
}


return null;
}

public function isInvoiced(DeliveryNote $deliveryNote): bool
{
return (bool) $this->getInvoiceId($deliveryNote);
}

public function getInvoice(DeliveryNote $deliveryNote): ?Invoice
{
$idInvoice = (int) $this->getInvoiceId($deliveryNote);
return Invoice::searchOne([
'id' => $idInvoice
]);
}
} }

+ 8
- 133
common/logic/Document/Document/Document.php View File



use common\components\ActiveRecordCommon; use common\components\ActiveRecordCommon;
use common\helpers\GlobalParam; use common\helpers\GlobalParam;
use common\logic\Order\Order\Order;
use common\logic\Order\Order\OrderRepository;
use common\logic\Producer\Producer\Producer; use common\logic\Producer\Producer\Producer;
use common\logic\User\User\User;
use kartik\mpdf\Pdf; use kartik\mpdf\Pdf;
use yii\base\ErrorException; use yii\base\ErrorException;


class Document extends ActiveRecordCommon
class Document extends ActiveRecordCommon implements DocumentInterface
{ {
const STATUS_DRAFT = 'draft'; const STATUS_DRAFT = 'draft';
const STATUS_VALID = 'valid'; const STATUS_VALID = 'valid';


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


public function getProducer() public function getProducer()


public function relationOrders($fieldIdDocument) public function relationOrders($fieldIdDocument)
{ {
$defaultOptionsSearch = Order::defaultOptionsSearch();
$orderRepository = new OrderRepository();
$defaultOptionsSearch = $orderRepository->defaultOptionsSearch();


return $this->hasMany(Order::className(), [$fieldIdDocument => 'id'])
return $this->hasMany(Order::class, [$fieldIdDocument => 'id'])
->with($defaultOptionsSearch['with']) ->with($defaultOptionsSearch['with'])
->joinWith($defaultOptionsSearch['join_with']) ->joinWith($defaultOptionsSearch['join_with'])
->orderBy('distribution.date ASC'); ->orderBy('distribution.date ASC');
* Méthodes * Méthodes
*/ */


public function getAmount($type = Order::AMOUNT_TOTAL, $format = false)
{
return $this->_getAmountGeneric($type, false, $format);
}

public function getAmountWithTax($type = Order::AMOUNT_TOTAL, $format = false)
{
return $this->_getAmountGeneric($type, true, $format);
}

protected function _getAmountGeneric($type = Order::AMOUNT_TOTAL, $withTax = true, $format = false)
{
$amount = 0;
$totalVat = 0;
$ordersArray = $this->orders;

// Méthode de calcul via les commandes liées
/*foreach ($ordersArray as $order) {
$order->init($this->tax_calculation_method);
$amount += $order->getAmount($type);
$totalVat += $order->getTotalVat($type);
}*/

// Méthode de calcul via getProductOrders()
foreach($this->getProductsOrders() as $productOrderArray) {
foreach($productOrderArray as $productOrder) {
$priceLine = $productOrder->getPriceByTypeTotal($type) * $productOrder->quantity;
$amount += $priceLine;
$totalVat += Price::getVat($priceLine, $productOrder->taxRate->value, $this->tax_calculation_method);
}
}

if ($this->isTaxCalculationMethodRoundingOfTheSum()) {
$totalVat = Price::round($totalVat);
}

if ($withTax) {
$amount += $totalVat;
}

if ($format) {
return Price::format($amount);
} else {
return $amount;
}
}

public function getTotalVatArray($typeTotal)
{
$totalVatArray = [];

// Méthode de calcul via les commandes liées
/*$ordersArray = $this->orders;
foreach ($ordersArray as $order) {
$order->init($this->tax_calculation_method);
$fieldNameVat = $order->getFieldNameAmount($typeTotal, 'vat');
foreach ($order->$fieldNameVat as $idTaxRate => $vat) {
if (!isset($totalVatArray[$idTaxRate])) {
$totalVatArray[$idTaxRate] = 0;
}
$totalVatArray[$idTaxRate] += $vat;
}
}*/


// Méthode de calcul via getProductOrders()
foreach($this->getProductsOrders() as $productOrderArray) {
foreach ($productOrderArray as $productOrder) {

$idTaxRate = $productOrder->taxRate->id;
if (!isset($totalVatArray[$idTaxRate])) {
$totalVatArray[$idTaxRate] = 0;
}

$totalVatArray[$idTaxRate] += Price::getVat(
$productOrder->getPriceByTypeTotal($typeTotal) * $productOrder->quantity,
$productOrder->taxRate->value,
$this->tax_calculation_method
);
}
}

return $totalVatArray;
}

public function getPointSale()
{
if (isset($this->orders) && isset($this->orders[0])) {
return $this->orders[0]->pointSale;
} else {
return '';
}
}

public function getDistribution()
{
if (isset($this->orders) && isset($this->orders[0])) {
return $this->orders[0]->distribution;
} else {
return '';
}
}

public function getClass()
{
return str_replace('common\models\\', '', get_class($this));
}

public function getType()
{
$class = $this->getClass();

if ($class == 'Invoice') {
$documentType = 'Facture';
} elseif ($class == 'DeliveryNote') {
$documentType = 'Bon de livraison';
} elseif ($class == 'Quotation') {
$documentType = 'Devis';
}

if (isset($documentType)) {
return $documentType;
}

return '';
}

public function isValidClass($typeDocument)
{
return in_array($typeDocument, ['Invoice', 'DeliveryNote', 'Quotation']);
}


public function generateReference() public function generateReference()
{ {

+ 8
- 0
common/logic/Document/Document/DocumentInterface.php View File

<?php

namespace common\logic\Document\Document;

interface DocumentInterface
{

}

+ 108
- 0
common/logic/Document/Document/DocumentSolver.php View File

namespace common\logic\Document\Document; namespace common\logic\Document\Document;


use common\logic\BaseService; use common\logic\BaseService;
use common\logic\Order\Order\Order;
use common\logic\SolverInterface; use common\logic\SolverInterface;


class DocumentSolver extends BaseService implements SolverInterface class DocumentSolver extends BaseService implements SolverInterface
{ {
public function getAmount(DocumentInterface $document, $type = Order::AMOUNT_TOTAL, $format = false)
{
return $this->_getAmountGeneric($document, $type, false, $format);
}


public function getAmountWithTax(DocumentInterface $document, $type = Order::AMOUNT_TOTAL, $format = false)
{
return $this->_getAmountGeneric($document, $type, true, $format);
}

protected function _getAmountGeneric(DocumentInterface $document, $type = Order::AMOUNT_TOTAL, $withTax = true, $format = false)
{
$amount = 0;
$totalVat = 0;

foreach($document->getProductsOrders() as $productOrderArray) {
foreach($productOrderArray as $productOrder) {
$priceLine = $productOrder->getPriceByTypeTotal($type) * $productOrder->quantity;
$amount += $priceLine;
$totalVat += Price::getVat($priceLine, $productOrder->taxRate->value, $document->tax_calculation_method);
}
}

if ($this->isTaxCalculationMethodRoundingOfTheSum()) {
$totalVat = Price::round($totalVat);
}

if ($withTax) {
$amount += $totalVat;
}

if ($format) {
return Price::format($amount);
} else {
return $amount;
}
}

public function getTotalVatArray($typeTotal)
{
$totalVatArray = [];

// Méthode de calcul via getProductOrders()
foreach($this->getProductsOrders() as $productOrderArray) {
foreach ($productOrderArray as $productOrder) {

$idTaxRate = $productOrder->taxRate->id;
if (!isset($totalVatArray[$idTaxRate])) {
$totalVatArray[$idTaxRate] = 0;
}

$totalVatArray[$idTaxRate] += Price::getVat(
$productOrder->getPriceByTypeTotal($typeTotal) * $productOrder->quantity,
$productOrder->taxRate->value,
$this->tax_calculation_method
);
}
}

return $totalVatArray;
}

public function getPointSale()
{
if (isset($this->orders) && isset($this->orders[0])) {
return $this->orders[0]->pointSale;
} else {
return '';
}
}

public function getDistribution()
{
if (isset($this->orders) && isset($this->orders[0])) {
return $this->orders[0]->distribution;
} else {
return '';
}
}

public function getClass()
{
return str_replace('common\models\\', '', get_class($this));
}

public function getType()
{
$class = $this->getClass();

if ($class == 'Invoice') {
$documentType = 'Facture';
} elseif ($class == 'DeliveryNote') {
$documentType = 'Bon de livraison';
} elseif ($class == 'Quotation') {
$documentType = 'Devis';
}

if (isset($documentType)) {
return $documentType;
}

return '';
}

public function isValidClass($typeDocument)
{
return in_array($typeDocument, ['Invoice', 'DeliveryNote', 'Quotation']);
}
} }

+ 0
- 21
common/logic/Order/Order/Order.php View File

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


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

/** /**
* Initialise le montant total, le montant déjà payé et le poids de la * Initialise le montant total, le montant déjà payé et le poids de la
* commande. * commande.

+ 16
- 0
common/logic/Order/Order/OrderRepository.php View File



class OrderRepository extends BaseService implements RepositoryInterface class OrderRepository extends BaseService implements RepositoryInterface
{ {
public function defaultOptionsSearch(): array
{
return [
'with' => [
'productOrder',
'productOrder.product',
'creditHistory',
'creditHistory.userAction',
'pointSale'
],
'join_with' => ['distribution', 'user', 'user.userProducer'],
'orderby' => 'order.date ASC',
'attribute_id_producer' => 'distribution.id_producer'
];
}

public function getByDistribution(Distribution $distribution, string $conditionAppend = '') public function getByDistribution(Distribution $distribution, string $conditionAppend = '')
{ {
return Order::searchAll([ return Order::searchAll([

+ 32
- 0
common/logic/Order/ProductOrder/ProductOrderBuilder.php View File



use common\logic\BaseService; use common\logic\BaseService;
use common\logic\BuilderInterface; use common\logic\BuilderInterface;
use common\logic\PointSale\PointSale\PointSale;
use common\logic\Product\Product\ProductSolver;
use common\logic\User\User\User;
use common\logic\User\UserProducer\UserProducer;


class ProductOrderBuilder extends BaseService implements BuilderInterface class ProductOrderBuilder extends BaseService implements BuilderInterface
{ {
protected ProductSolver $productSolver;

public function __construct()
{
$this->productSolver = $this->loadService(ProductSolver::class);
}

public function instanciate(): ProductOrder public function instanciate(): ProductOrder
{ {
$productOrder = new ProductOrder(); $productOrder = new ProductOrder();


return $productOrder; return $productOrder;
} }

public function updatePrice(
ProductOrder $productOrder,
User $user = null,
UserProducer $userProducer = null,
PointSale $pointSale = null,
int $quantity = 1)
{
$productOrder->price = $this->productSolver->getPrice(
$productOrder->product,
[
'user' => $user,
'user_producer' => $userProducer,
'point_sale' => $pointSale,
'quantity' => $quantity
]);

$productOrder->save();

return $productOrder;
}
} }

+ 13
- 1
common/logic/PointSale/PointSale/PointSaleRepository.php View File



namespace common\logic\PointSale\PointSale; namespace common\logic\PointSale\PointSale;


use common\helpers\GlobalParam;
use common\logic\BaseService; use common\logic\BaseService;
use common\logic\BuilderInterface; use common\logic\BuilderInterface;
use common\logic\Distribution\Distribution\Distribution;
use common\logic\RepositoryInterface; use common\logic\RepositoryInterface;


class PointSaleRepository extends BaseService implements RepositoryInterface class PointSaleRepository extends BaseService implements RepositoryInterface
{ {

public function getByDistribution(Distribution $distribution)
{
return PointSale::find()
->with(['pointSaleDistribution' => function($q) use ($distribution) {
$q->where(['id_distribution' => $distribution->id]);
}])
->where([
'id_producer' => $distribution->producer->id,
])
->all();
}
} }

+ 0
- 52
common/logic/Product/Product/Product.php View File

return false; return false;
} }


public function getSpecificPricesFilterByPriorityMatch($specificPrices, $user, $pointSale)
{
$priorityMatchSpecificPrice = ProductPrice::getPriorityMatchOfSpecificPriceArray($specificPrices, $user, $pointSale);
$specificPricesFilter = [];

foreach ($specificPrices as $keySpecificPrice => $specificPrice) {
if (($priorityMatchSpecificPrice && $specificPrice->$priorityMatchSpecificPrice($user, $pointSale))
|| $specificPrice->matchFromQuantityOnly()) {

$specificPricesFilter[] = $specificPrice;
}
}

return $specificPricesFilter;
}

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

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

if ($specificPrices && ($user || $pointSale)) {
$specificPrices = $this->getSpecificPricesFilterByPriorityMatch($specificPrices, $user, $pointSale);
$bestPrice = 9999;
foreach ($specificPrices as $specificPrice) {
$fromQuantity = $specificPrice->from_quantity;
if ((($fromQuantity && $fromQuantity <= $quantity) || !$fromQuantity)
&& $specificPrice->price < $bestPrice) {
$bestPrice = $specificPrice->price;
}
}

if ($bestPrice != 9999) {
return $bestPrice;
}
}

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

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

return $this->price;
}

/** /**
* Retourne le prix du produit avec taxe * Retourne le prix du produit avec taxe
*/ */

+ 49
- 1
common/logic/Product/Product/ProductSolver.php View File

namespace common\logic\Product\Product; namespace common\logic\Product\Product;


use common\logic\BaseService; use common\logic\BaseService;
use common\logic\PointSale\PointSale\PointSale;
use common\logic\Product\ProductPrice\ProductPriceSolver;
use common\logic\SolverInterface; use common\logic\SolverInterface;
use common\logic\User\User\User;


class ProductSolver extends BaseService implements SolverInterface class ProductSolver extends BaseService implements SolverInterface
{ {
protected ProductPriceSolver $productPriceSolver;

public function __construct()
{
$this->productPriceSolver = $this->loadService(ProductPriceSolver::class);
}

public function getPrice(Product $product, array $params = []): float
{
$specificPriceArray = $product->productPrice;

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

if ($specificPriceArray && ($user || $pointSale)) {
$specificPriceArray = $this->productPriceSolver->filterByPriorityMatch(
$specificPriceArray,
$user,
$pointSale
);
$bestPrice = 9999;
foreach ($specificPriceArray as $specificPrice) {
$fromQuantity = $specificPrice->from_quantity;
if ((($fromQuantity && $fromQuantity <= $quantity) || !$fromQuantity)
&& $specificPrice->price < $bestPrice) {
$bestPrice = $specificPrice->price;
}
}

if ($bestPrice != 9999) {
return $bestPrice;
}
}

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

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

return $product->price;
}
} }

+ 0
- 91
common/logic/Product/ProductPrice/ProductPrice.php View File



return $percentValues; return $percentValues;
} }

public static function hasMatchOfType($specificPriceArray, $typeMatch, $user, $pointSale)
{
foreach($specificPriceArray as $specificPrice) {
if($specificPrice->$typeMatch($user, $pointSale)) {
return true;
}
}

return false;
}

public static function getPriorityMatchOfSpecificPriceArray($specificPriceArray, $user, $pointSale)
{
if(self::hasMatchOfType($specificPriceArray, 'matchUser', $user, $pointSale)) {
return 'matchUser';
}

if(self::hasMatchOfType($specificPriceArray, 'matchUserGroup', $user, $pointSale)) {
return 'matchUserGroup';
}

if(self::hasMatchOfType($specificPriceArray, 'matchPointSale', $user, $pointSale)) {
return 'matchPointSale';
}

if(self::hasMatchOfType($specificPriceArray, 'matchUserPointSale', $user, $pointSale)) {
return 'matchUserPointSale';
}

if(self::hasMatchOfType($specificPriceArray, 'matchUserGroupPointSale', $user, $pointSale)) {
return 'matchUserGroupPointSale';
}

return null;
}

public function matchUser($user, $pointSale)
{
return $user
&& $this->id_user
&& !$this->id_point_sale
&& !$this->id_user_group
&& $this->id_user == $user->id;
}

public function matchUserGroup($user, $pointSale)
{
return $user
&& $this->id_user_group
&& !$this->id_point_sale
&& !$this->id_user
&& $user->belongsToUserGroup($this->id_user_group);
}

public function matchPointSale($user, $pointSale)
{
return $pointSale
&& $this->id_point_sale
&& !$this->id_user
&& !$this->id_user_group
&& $this->id_point_sale == $pointSale->id;
}

public function matchUserPointSale($user, $pointSale)
{
return $pointSale && $user
&& $this->id_point_sale
&& $this->id_user
&& $this->id_point_sale == $pointSale->id
&& $this->id_user == $user->id;
}

public function matchUserGroupPointSale($user, $pointSale)
{
return $user
&& $pointSale
&& $this->id_user_group
&& $this->id_point_sale
&& !$this->id_user
&& $user->belongsToUserGroup($this->id_user_group)
&& $this->id_point_sale == $pointSale->id;
}

public function matchFromQuantityOnly()
{
return !$this->id_user
&& !$this->id_point_sale
&& !$this->id_user_group
&& $this->from_quantity;
}
} }

+ 113
- 0
common/logic/Product/ProductPrice/ProductPriceSolver.php View File

namespace common\logic\Product\ProductPrice; namespace common\logic\Product\ProductPrice;


use common\logic\BaseService; use common\logic\BaseService;
use common\logic\PointSale\PointSale\PointSale;
use common\logic\SolverInterface; use common\logic\SolverInterface;
use common\logic\User\User\User;


class ProductPriceSolver extends BaseService implements SolverInterface class ProductPriceSolver extends BaseService implements SolverInterface
{ {
// getSpecificPricesFilterByPriorityMatch
public function filterByPriorityMatch(
array $specificPrices,
User $user,
PointSale $pointSale): array
{
$priorityMatchSpecificPrice = $this->getPriorityMatch($specificPrices, $user, $pointSale);
$specificPricesFilter = [];


foreach ($specificPrices as $keySpecificPrice => $specificPrice) {
if (($priorityMatchSpecificPrice && $specificPrice->$priorityMatchSpecificPrice($user, $pointSale))
|| $specificPrice->matchFromQuantityOnly()) {

$specificPricesFilter[] = $specificPrice;
}
}

return $specificPricesFilter;
}

// getPriorityMatchOfSpecificPriceArray
public function getPriorityMatch(
array $specificPriceArray,
User $user = null,
PointSale $pointSale = null): ?string
{
$typeMatchArray = [
'matchUser',
'matchUserGroup',
'matchPointSale',
'matchUserPointSale',
'matchUserGroupPointSale'
];

foreach($typeMatchArray as $typeMatch) {
if($this->hasMatchOfType($specificPriceArray, $typeMatch, $user, $pointSale)) {
return $typeMatch;
}
}

return null;
}

public function hasMatchOfType(
array $specificPriceArray,
string $typeMatch,
User $user = null,
PointSale $pointSale = null): bool
{
foreach($specificPriceArray as $specificPrice) {
if($specificPrice->$typeMatch($user, $pointSale)) {
return true;
}
}

return false;
}

public function matchUser(ProductPrice $productPrice, User $user = null, PointSale $pointSale = null): bool
{
return $user
&& $productPrice->id_user
&& !$productPrice->id_point_sale
&& !$productPrice->id_user_group
&& $productPrice->id_user == $user->id;
}

public function matchUserGroup(ProductPrice $productPrice, User $user = null, PointSale $pointSale = null): bool
{
return $user
&& $productPrice->id_user_group
&& !$productPrice->id_point_sale
&& !$productPrice->id_user
&& $user->belongsToUserGroup($productPrice->id_user_group);
}

public function matchPointSale(ProductPrice $productPrice, User $user = null, PointSale $pointSale = null): bool
{
return $pointSale
&& $productPrice->id_point_sale
&& !$productPrice->id_user
&& !$productPrice->id_user_group
&& $productPrice->id_point_sale == $pointSale->id;
}

public function matchUserPointSale(ProductPrice $productPrice, User $user = null, PointSale $pointSale = null): bool
{
return $pointSale && $user
&& $productPrice->id_point_sale
&& $productPrice->id_user
&& $productPrice->id_point_sale == $pointSale->id
&& $productPrice->id_user == $user->id;
}

public function matchUserGroupPointSale(ProductPrice $productPrice, User $user = null, PointSale $pointSale = null): bool
{
return $user
&& $pointSale
&& $productPrice->id_user_group
&& $productPrice->id_point_sale
&& !$productPrice->id_user
&& $user->belongsToUserGroup($productPrice->id_user_group)
&& $productPrice->id_point_sale == $pointSale->id;
}

public function matchFromQuantityOnly(ProductPrice $productPrice): bool
{
return !$productPrice->id_user
&& !$productPrice->id_point_sale
&& !$productPrice->id_user_group
&& $productPrice->from_quantity;
}
} }

+ 2
- 1
composer.json View File

"yiisoft/yii2-debug": "*", "yiisoft/yii2-debug": "*",
"yiisoft/yii2-gii": "*", "yiisoft/yii2-gii": "*",
"yiisoft/yii2-faker": "*", "yiisoft/yii2-faker": "*",
"codeception/codeception": "^2.3"
"codeception/codeception": "^2.3",
"phpstan/phpstan": "^1.9"
}, },
"config": { "config": {
"process-timeout": 1800, "process-timeout": 1800,

+ 60
- 1
composer.lock View File

"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "78a16f604e3b8e2cb623f7204619682f",
"content-hash": "85c783330a1d88a3ed3c4674e84d10ba",
"packages": [ "packages": [
{ {
"name": "2amigos/yii2-chartjs-widget", "name": "2amigos/yii2-chartjs-widget",
}, },
"time": "2020-03-05T15:02:03+00:00" "time": "2020-03-05T15:02:03+00:00"
}, },
{
"name": "phpstan/phpstan",
"version": "1.9.17",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
"reference": "204e459e7822f2c586463029f5ecec31bb45a1f2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/204e459e7822f2c586463029f5ecec31bb45a1f2",
"reference": "204e459e7822f2c586463029f5ecec31bb45a1f2",
"shasum": ""
},
"require": {
"php": "^7.2|^8.0"
},
"conflict": {
"phpstan/phpstan-shim": "*"
},
"bin": [
"phpstan",
"phpstan.phar"
],
"type": "library",
"autoload": {
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "PHPStan - PHP Static Analysis Tool",
"keywords": [
"dev",
"static analysis"
],
"support": {
"issues": "https://github.com/phpstan/phpstan/issues",
"source": "https://github.com/phpstan/phpstan/tree/1.9.17"
},
"funding": [
{
"url": "https://github.com/ondrejmirtes",
"type": "github"
},
{
"url": "https://github.com/phpstan",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan",
"type": "tidelift"
}
],
"time": "2023-02-08T12:25:00+00:00"
},
{ {
"name": "phpunit/php-code-coverage", "name": "phpunit/php-code-coverage",
"version": "6.1.4", "version": "6.1.4",

Loading…
Cancel
Save