@@ -4,15 +4,15 @@ namespace Lc\CaracoleBundle\Builder\File; | |||
use Lc\CaracoleBundle\Model\File\DocumentInterface; | |||
use Lc\CaracoleBundle\Model\Order\OrderShopInterface; | |||
use Lc\CaracoleBundle\Resolver\Reference\DocumentReferenceResolver; | |||
use Lc\CaracoleBundle\Generator\Reference\DocumentReferenceGenerator; | |||
class DocumentBuilder | |||
{ | |||
protected DocumentReferenceResolver $documentReferenceResolver; | |||
protected DocumentReferenceGenerator $documentReferenceGenerator; | |||
public function __construct(DocumentReferenceResolver $documentReferenceResolver) | |||
public function __construct(DocumentReferenceGenerator $documentReferenceGenerator) | |||
{ | |||
$this->documentReferenceResolver = $documentReferenceResolver; | |||
$this->documentReferenceGenerator = $documentReferenceGenerator; | |||
} | |||
public function initFromOrderShop(DocumentInterface $document, OrderShopInterface $orderShop) | |||
@@ -20,7 +20,7 @@ class DocumentBuilder | |||
$merchantAddress = $orderShop->getMerchant()->getAddress(); | |||
$buyerAddress = $orderShop->getInvoiceAddress(); | |||
$document->setReference($this->documentReferenceResolver->buildReference($orderShop->getMerchant())) ; | |||
$document->setReference($this->documentReferenceGenerator->buildReference($orderShop->getMerchant())) ; | |||
$document->setMerchantAddress($merchantAddress); | |||
$document->setBuyerAddress($buyerAddress); | |||
$document->setMerchantAddressText($merchantAddress->getSummary()); |
@@ -2,16 +2,25 @@ | |||
namespace Lc\CaracoleBundle\Builder\Order; | |||
use Doctrine\ORM\EntityManagerInterface; | |||
use Lc\CaracoleBundle\Model\Order\OrderProductInterface; | |||
use Lc\CaracoleBundle\Repository\Order\OrderProductStore; | |||
use Lc\CaracoleBundle\Resolver\Price\PriceResolver; | |||
class OrderProductBuilder | |||
{ | |||
protected EntityManagerInterface $entityManager; | |||
protected PriceResolver $priceResolver; | |||
protected OrderProductStore $orderProductStore; | |||
public function __construct(PriceResolver $priceResolver) | |||
{ | |||
public function __construct( | |||
EntityManagerInterface $entityManager, | |||
PriceResolver $priceResolver, | |||
OrderProductStore $orderProductStore | |||
) { | |||
$this->entityManager = $entityManager; | |||
$this->priceResolver = $priceResolver; | |||
$this->orderProductStore = $orderProductStore; | |||
} | |||
public function init(OrderProductInterface $orderProduct) |
@@ -15,6 +15,7 @@ use Lc\CaracoleBundle\Factory\Order\OrderStatusHistoryFactory; | |||
use Lc\CaracoleBundle\Model\File\DocumentModel; | |||
use Lc\CaracoleBundle\Model\Order\OrderProductInterface; | |||
use Lc\CaracoleBundle\Model\Order\OrderShopInterface; | |||
use Lc\CaracoleBundle\Model\Order\OrderStatusInterface; | |||
use Lc\CaracoleBundle\Model\Order\OrderStatusModel; | |||
use Lc\CaracoleBundle\Model\Product\ProductFamilyModel; | |||
use Lc\CaracoleBundle\Model\Reduction\ReductionCartInterface; | |||
@@ -27,6 +28,8 @@ use Lc\CaracoleBundle\Repository\Order\OrderStatusStore; | |||
use Lc\CaracoleBundle\Repository\Product\ProductFamilyStore; | |||
use Lc\CaracoleBundle\Resolver\Price\PriceResolver; | |||
use Lc\SovBundle\Model\User\UserInterface; | |||
use Symfony\Component\EventDispatcher\EventDispatcherInterface; | |||
use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface; | |||
class OrderShopBuilder | |||
{ | |||
@@ -37,6 +40,8 @@ class OrderShopBuilder | |||
protected PriceResolver $priceResolver; | |||
protected OrderProductBuilder $orderProductBuilder; | |||
protected DocumentBuilder $documentBuilder; | |||
protected EventDispatcherInterface $eventDispatcher; | |||
protected FlashBagInterface $flashBag; | |||
public function __construct( | |||
EntityManagerInterface $entityManager, | |||
@@ -46,7 +51,9 @@ class OrderShopBuilder | |||
ProductFamilyStore $productFamilyStore, | |||
OrderProductBuilder $orderProductBuilder, | |||
DocumentBuilder $documentBuilder, | |||
PriceResolver $priceResolver | |||
PriceResolver $priceResolver, | |||
EventDispatcherInterface $eventDispatcher, | |||
FlashBagInterface $flashBag | |||
) { | |||
$this->entityManager = $entityManager; | |||
$this->orderShopStore = $orderShopStore; | |||
@@ -56,6 +63,8 @@ class OrderShopBuilder | |||
$this->orderProductBuilder = $orderProductBuilder; | |||
$this->documentBuilder = $documentBuilder; | |||
$this->priceResolver = $priceResolver; | |||
$this->eventDispatcher = $eventDispatcher; | |||
$this->flashBag = $flashBag; | |||
} | |||
public function create( | |||
@@ -91,28 +100,46 @@ class OrderShopBuilder | |||
return $cart; | |||
} | |||
public function changeOrderStatus(OrderShopInterface $orderShop, string $alias) | |||
public function changeOrderStatus(OrderShopInterface $orderShop, string $alias, bool $forceByAdmin = false) | |||
{ | |||
$orderStatus = $this->orderStatusStore->getRepositoryQuery()->findOneByAlias($alias); | |||
if ($orderShop->getOrderStatus() === null | |||
|| $orderShop->getOrderStatus()->getNextStatusAllowed()->contains($orderStatus)) { | |||
$this->eventDispatcher->dispatch( | |||
new OrderShopChangeStatusEvent($orderShop, $orderStatus), | |||
OrderShopChangeStatusEvent::PRE_CHANGE_STATUS | |||
); | |||
if ($orderStatus) { | |||
if ($orderShop->getOrderStatus() === null | |||
|| $orderShop->getOrderStatus()->getNextStatusAllowed()->contains($orderStatus)) { | |||
$orderShop->setOrderStatusProtected($orderStatus); | |||
$orderStatusHistoryFactory = new OrderStatusHistoryFactory(); | |||
$orderStatusHistory = $orderStatusHistoryFactory->create($orderShop, $orderStatus); | |||
$orderShop->addOrderStatusHistory($orderStatusHistory); | |||
$this->applyChangeOrderStatus($orderShop, $orderStatus, $forceByAdmin); | |||
} | |||
} else { | |||
throw new \ErrorException('La statut demandé n\'existe pas.'); | |||
} | |||
return $orderShop; | |||
} | |||
public function applyChangeOrderStatus( | |||
OrderShopInterface $orderShop, | |||
OrderStatusInterface $orderStatus, | |||
bool $forceByAdmin = false | |||
) { | |||
$this->eventDispatcher->dispatch( | |||
new OrderShopChangeStatusEvent($orderShop, $orderStatus, $forceByAdmin), | |||
OrderShopChangeStatusEvent::PRE_CHANGE_STATUS | |||
); | |||
$orderShop->setOrderStatusProtected($orderStatus); | |||
$orderStatusHistoryFactory = new OrderStatusHistoryFactory(); | |||
$orderStatusHistory = $orderStatusHistoryFactory->create($orderShop, $orderStatus); | |||
$orderShop->addOrderStatusHistory($orderStatusHistory); | |||
$this->eventDispatcher->dispatch( | |||
new OrderShopChangeStatusEvent($orderShop, $orderStatus, $forceByAdmin), | |||
OrderShopChangeStatusEvent::POST_CHANGE_STATUS | |||
); | |||
} | |||
public function addOrderProduct( | |||
OrderShopInterface $orderShop, | |||
OrderProductInterface $orderProductAdd, | |||
@@ -282,18 +309,16 @@ class OrderShopBuilder | |||
$orderReductionCartFactory = new OrderReductionCartFactory(); | |||
$orderReductionCart = $orderReductionCartFactory->create($orderShop, $reductionCart); | |||
$orderShop->addOrderReductionCart($orderReductionCart) ; | |||
$orderShop->addOrderReductionCart($orderReductionCart); | |||
if($this->orderShopStore->isPositiveAmount($orderShop) | |||
if ($this->orderShopStore->isPositiveAmount($orderShop) | |||
&& $this->isPositiveAmountRemainingToBePaid($orderShop)) { | |||
$this->entityManager->persist($orderReductionCart); | |||
$this->entityManager->flush(); | |||
return $orderReductionCart ; | |||
} | |||
else { | |||
$orderShop->removeOrderReductionCart($orderReductionCart) ; | |||
return $orderReductionCart; | |||
} else { | |||
$orderShop->removeOrderReductionCart($orderReductionCart); | |||
return false; | |||
} | |||
} | |||
@@ -304,18 +329,16 @@ class OrderShopBuilder | |||
$orderReductionCreditFactory = new OrderReductionCreditFactory(); | |||
$orderReductionCredit = $orderReductionCreditFactory->create($orderShop, $reductionCredit); | |||
$orderShop->addOrderReductionCredit($orderReductionCredit) ; | |||
$orderShop->addOrderReductionCredit($orderReductionCredit); | |||
if($this->isOrderShopPositiveAmount($orderShop) | |||
if ($this->isOrderShopPositiveAmount($orderShop) | |||
&& $this->isOrderShopPositiveAmountRemainingToBePaid($orderShop)) { | |||
$this->entityManager->persist($orderReductionCredit); | |||
$this->entityManager->flush(); | |||
return $orderReductionCredit; | |||
} | |||
else { | |||
$orderShop->removeOrderReductionCredit($orderReductionCredit) ; | |||
} else { | |||
$orderShop->removeOrderReductionCredit($orderReductionCredit); | |||
return false; | |||
} | |||
@@ -326,13 +349,17 @@ class OrderShopBuilder | |||
// @TODO : à refactorer en plaçant dans src tout ce qui est spécifique à PDL | |||
foreach ($orderShop->getOrderProducts() as $orderProduct) { | |||
//Si ce n'esrt pas une relivraison OU si c'est une relivraison + relivraison + ce n'est pas une erruer producteur | |||
if (!$orderProduct->isRedelivery() || ($orderProduct->isRedelivery() && $orderProduct->isRedeliverySupplierOrder() && !$orderProduct->isRedeliverySupplierMistake())) { | |||
if (!$orderProduct->isRedelivery() || ($orderProduct->isRedelivery( | |||
) && $orderProduct->isRedeliverySupplierOrder( | |||
) && !$orderProduct->isRedeliverySupplierMistake())) { | |||
switch ($orderProduct->getProduct()->getProductFamily()->getBehaviorCountStock()) { | |||
case ProductFamilyModel::BEHAVIOR_COUNT_STOCK_BY_MEASURE : | |||
//Disponibilité par unité de référence | |||
$oldAvailability = $orderProduct->getProduct()->getAvailableQuantityInherited(); | |||
$newAvailability = $oldAvailability - ($orderProduct->getQuantityOrder() * ($orderProduct->getQuantityProduct() / $orderProduct->getUnit()->getCoefficient())); | |||
$newAvailability = $oldAvailability - ($orderProduct->getQuantityOrder( | |||
) * ($orderProduct->getQuantityProduct() / $orderProduct->getUnit( | |||
)->getCoefficient())); | |||
$productFamily = $orderProduct->getProduct()->getProductFamily(); | |||
$productFamily->setAvailableQuantity($newAvailability); |
@@ -0,0 +1,25 @@ | |||
<?php | |||
namespace Lc\CaracoleBundle\Event\Order; | |||
use Lc\CaracoleBundle\Model\Order\OrderShopInterface; | |||
use Lc\CaracoleBundle\Model\Order\OrderStatusInterface; | |||
use Symfony\Contracts\EventDispatcher\Event; | |||
class CartChangeEvent extends Event | |||
{ | |||
const PRE_UPDATE = 'cart_event.pre_update'; | |||
const POST_UPDATE = 'cart_event.post_update'; | |||
protected OrderShopInterface $orderShop; | |||
public function __construct(OrderShopInterface $orderShop, OrderStatusInterface $orderStatus, bool $forceByAdmin) | |||
{ | |||
$this->orderShop = $orderShop; | |||
} | |||
public function getOrderShop() | |||
{ | |||
return $this->orderShop; | |||
} | |||
} |
@@ -2,29 +2,38 @@ | |||
namespace Lc\CaracoleBundle\Event\Order; | |||
use Lc\CaracoleBundle\Model\Order\OrderShopInterface; | |||
use Lc\CaracoleBundle\Model\Order\OrderStatusInterface; | |||
use Symfony\Contracts\EventDispatcher\Event; | |||
class OrderShopChangeStatusEvent extends Event | |||
{ | |||
const PRE_CHANGE_STATUS = 'order_shop_event.pre_change_status'; | |||
const POST_CHANGE_STATUS = 'order_shop_event.post_change_status'; | |||
protected $orderShop; | |||
protected $orderStatus; | |||
public function __construct($orderShop, $orderStatus) | |||
{ | |||
$this->orderShop = $orderShop; | |||
$this->orderStatus = $orderStatus; | |||
} | |||
public function getOrderShop() | |||
{ | |||
return $this->orderShop; | |||
} | |||
public function getOrderStatus() | |||
{ | |||
return $this->orderStatus; | |||
} | |||
const PRE_CHANGE_STATUS = 'order_shop_event.pre_change_status'; | |||
const POST_CHANGE_STATUS = 'order_shop_event.post_change_status'; | |||
protected OrderShopInterface $orderShop; | |||
protected OrderStatusInterface $orderStatus; | |||
protected bool $forceByAdmin; | |||
public function __construct(OrderShopInterface $orderShop, OrderStatusInterface $orderStatus, bool $forceByAdmin) | |||
{ | |||
$this->orderShop = $orderShop; | |||
$this->orderStatus = $orderStatus; | |||
$this->forceByAdmin = $forceByAdmin; | |||
} | |||
public function getOrderShop() | |||
{ | |||
return $this->orderShop; | |||
} | |||
public function getOrderStatus() | |||
{ | |||
return $this->orderStatus; | |||
} | |||
public function getForceByAdmin() | |||
{ | |||
return $this->forceByAdmin; | |||
} | |||
} |
@@ -4,14 +4,18 @@ namespace Lc\CaracoleBundle\Factory\Order; | |||
use App\Entity\Order\OrderProduct; | |||
use Lc\CaracoleBundle\Model\Order\OrderProductInterface; | |||
use Lc\CaracoleBundle\Model\Product\ProductInterface; | |||
use Lc\SovBundle\Factory\AbstractFactory; | |||
class OrderProductFactory extends AbstractFactory | |||
{ | |||
public function create(): OrderProductInterface | |||
public function create(ProductInterface $product, int $quantityOrder): OrderProductInterface | |||
{ | |||
$orderProduct = new OrderProduct(); | |||
$orderProduct->setProduct($product); | |||
$orderProduct->setQuantityOrder($quantityOrder); | |||
return $orderProduct; | |||
} | |||
@@ -1,6 +1,6 @@ | |||
<?php | |||
namespace Lc\CaracoleBundle\Resolver\Reference; | |||
namespace Lc\CaracoleBundle\Generator\Reference; | |||
use Lc\CaracoleBundle\Definition\SectionSettingDefinition; | |||
use Lc\CaracoleBundle\Model\File\DocumentModel; | |||
@@ -9,7 +9,7 @@ use Lc\CaracoleBundle\Model\Order\OrderShopInterface; | |||
use Lc\CaracoleBundle\Model\Section\SectionModel; | |||
use Lc\CaracoleBundle\Repository\File\DocumentStore; | |||
class DocumentReferenceResolver | |||
class DocumentReferenceGenerator | |||
{ | |||
protected DocumentStore $documentStore; |
@@ -1,12 +1,12 @@ | |||
<?php | |||
namespace Lc\CaracoleBundle\Resolver\Reference; | |||
namespace Lc\CaracoleBundle\Generator\Reference; | |||
use Lc\CaracoleBundle\Definition\SectionSettingDefinition; | |||
use Lc\CaracoleBundle\Model\Order\OrderShopInterface; | |||
use Lc\CaracoleBundle\Model\Section\SectionModel; | |||
class OrderReferenceResolver | |||
class OrderReferenceGenerator | |||
{ | |||
public function buildReference(OrderShopInterface $orderShop, \DateTime $distributionDate = null): string |
@@ -121,6 +121,7 @@ abstract class AddressModel extends AbstractLightEntity implements StatusInterfa | |||
return $this->getTitle() . ' - ' . $this->getZip() . ' ' . $this->getCity(); | |||
} | |||
// getAddressSummary | |||
public function getSummaryShort() | |||
{ | |||
return $this->getAddress() . ' - ' . $this->getZip() . ' ' . $this->getCity(); |
@@ -14,4 +14,33 @@ class OrderProductStore extends AbstractStore | |||
{ | |||
$this->query = $query; | |||
} | |||
// getOrderProductsFormOrderShopsGroupByStorageOrder | |||
public function getByOrderShopsGroupByStorageOrder(array $orderShops): array | |||
{ | |||
$orderProductsByStorageOrder = []; | |||
foreach ($orderShops as $orderShop) { | |||
foreach ($orderShop->getOrderProducts() as $orderProduct) { | |||
if ($orderProduct->getProduct() && $orderProduct->getProduct()->getProductFamily()) { | |||
$storageOrder = 0; | |||
if ($orderProduct->getProduct()->getProductFamily()->getStorageOrder()) $storageOrder = $productFamily->getStorageOrder(); | |||
if (!isset($orderProductsByStorageOrder[$storageOrder])) { | |||
$orderProductsByStorageOrder[$productFamily->getId()] = [ | |||
'order_products' => [], | |||
'total_quantity_weight' => 0, | |||
]; | |||
} | |||
$orderProductsByStorageOrder[$storageOrder]['order_products'][] = $orderProduct; | |||
$orderProductsByStorageOrder[$storageOrder]['total_quantity_weight'] += ($orderProduct->getQuantityProduct() / $orderProduct->getUnit()->getCoefficient()) * $orderProduct->getQuantityOrder(); | |||
} | |||
} | |||
} | |||
return $orderProductsByStorageOrder; | |||
} | |||
} |
@@ -2,40 +2,153 @@ | |||
namespace Lc\CaracoleBundle\Repository\Order; | |||
use App\Entity\Order\OrderProduct; | |||
use App\Entity\Section\Section; | |||
use Doctrine\ORM\EntityManagerInterface; | |||
use Lc\CaracoleBundle\Builder\File\DocumentBuilder; | |||
use Lc\CaracoleBundle\Factory\File\DocumentFactory; | |||
use Lc\CaracoleBundle\Model\File\DocumentModel; | |||
use Lc\CaracoleBundle\Model\Merchant\MerchantInterface; | |||
use Lc\CaracoleBundle\Model\Order\OrderShopInterface; | |||
use Lc\CaracoleBundle\Model\Section\SectionInterface; | |||
use Lc\CaracoleBundle\Repository\Merchant\MerchantStore; | |||
use Lc\CaracoleBundle\Repository\Reduction\ReductionCreditStore; | |||
use Lc\CaracoleBundle\Repository\Section\SectionStore; | |||
use Lc\CaracoleBundle\Resolver\OpeningResolver; | |||
use Lc\CaracoleBundle\Resolver\Price\PriceResolver; | |||
use Lc\CaracoleBundle\Resolver\Reference\DocumentReferenceResolver; | |||
use Lc\SovBundle\Model\User\UserInterface; | |||
use Lc\SovBundle\Repository\AbstractStore; | |||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; | |||
use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface; | |||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface; | |||
class OrderShopStore extends AbstractStore | |||
{ | |||
protected OrderShopRepositoryQuery $query; | |||
protected EntityManagerInterface $entityManager; | |||
protected PriceResolver $priceResolver; | |||
protected DocumentReferenceResolver $documentReferenceResolver; | |||
protected DocumentBuilder $documentBuilder; | |||
protected ReductionCreditStore $reductionCreditStore; | |||
protected SectionStore $sectionStore; | |||
protected OrderProductStore $orderProductStore; | |||
protected MerchantStore $merchantStore; | |||
protected FlashBagInterface $flashBag; | |||
protected OpeningResolver $openingResolver; | |||
protected ParameterBagInterface $parameterBag; | |||
protected UrlGeneratorInterface $router; | |||
public function __construct( | |||
OrderShopRepositoryQuery $query, | |||
EntityManagerInterface $entityManager, | |||
PriceResolver $priceResolver, | |||
DocumentReferenceResolver $documentReferenceResolver, | |||
DocumentBuilder $documentBuilder | |||
DocumentBuilder $documentBuilder, | |||
ReductionCreditStore $reductionCreditStore, | |||
SectionStore $sectionStore, | |||
OrderProductStore $orderProductStore, | |||
MerchantStore $merchantStore, | |||
FlashBagInterface $flashBag, | |||
OpeningResolver $openingResolver, | |||
ParameterBagInterface $parameterBag, | |||
UrlGeneratorInterface $router | |||
) { | |||
$this->query = $query; | |||
$this->entityManager = $entityManager; | |||
$this->priceResolver = $priceResolver; | |||
$this->documentReferenceResolver = $documentReferenceResolver; | |||
$this->documentBuilder = $documentBuilder; | |||
$this->reductionCreditStore = $reductionCreditStore; | |||
$this->sectionStore = $sectionStore; | |||
$this->orderProductStore = $orderProductStore; | |||
$this->merchantStore = $merchantStore; | |||
$this->flashBag = $flashBag; | |||
$this->openingResolver = $openingResolver; | |||
$this->parameterBag = $parameterBag; | |||
$this->router = $router; | |||
} | |||
public function getDatas(OrderShopInterface $orderShop = null): array | |||
// getOrderShopsOfWeek | |||
public function getByCycle(SectionInterface $section, $params = []) | |||
{ | |||
$data = []; | |||
$orderShops = $this->getBy( | |||
array_merge( | |||
[ | |||
'section' => $section, | |||
'cycleNumber' => $this->getCycleNumberCurrentOrder($section), | |||
'isValid' => true, | |||
], | |||
$params | |||
) | |||
); | |||
return $orderShops; | |||
} | |||
// getOrderShopsOfWeekByUser | |||
public function getByCycleAndUser(SectionInterface $section, UserInterface $user, array $params = []) | |||
{ | |||
return $this->getByCycle( | |||
$section, | |||
array_merge( | |||
[ | |||
'user' => $user, | |||
'weekNumber' => $this->getCycleNumberCurrentOrder($section), | |||
'excludeComplementaryOrderShops' => true | |||
], | |||
$params | |||
) | |||
); | |||
} | |||
//public $countOrderShopsOfWeek = null; | |||
public function countByCycle(SectionInterface $section, bool $excludeComplementaryOrderShops = true) | |||
{ | |||
return $this->getByCycle( | |||
$section, | |||
[ | |||
'count' => true, | |||
'excludeComplementaryOrderShops' => $excludeComplementaryOrderShops | |||
] | |||
); | |||
// @TODO : optimisation à remettre en place | |||
/*if (is_null($this->countOrderShopsOfWeek)) { | |||
$this->countOrderShopsOfWeek = $this->getByCycle( | |||
$section, | |||
[ | |||
'count' => true, | |||
'excludeComplementaryOrderShops' => $excludeComplementaryOrderShops | |||
] | |||
); | |||
} | |||
return $this->countOrderShopsOfWeek;*/ | |||
} | |||
// getNextWeekId | |||
public function getNextCycleId(SectionInterface $section, int $cycleNumber): int | |||
{ | |||
$lastOrder = $this->getOneLastOrderValidOfCycle($section, $cycleNumber); | |||
if ($lastOrder) { | |||
return intval($lastOrder->getCycleId() + 1); | |||
} else { | |||
return 1; | |||
} | |||
} | |||
public function getNextIdValidOrder(Section $section) | |||
{ | |||
$lastOrder = $this->getOneLastOrderValid($section); | |||
if (is_null($orderShop)) { | |||
$orderShop = $this->getCartCurrent(); | |||
if ($lastOrder) { | |||
return intval($lastOrder->getIdValidOrder() + 1); | |||
} else { | |||
return 1; | |||
} | |||
} | |||
// getOrderDatas | |||
public function getDatas(OrderShopInterface $orderShop, UserInterface $user = null): array | |||
{ | |||
$data = []; | |||
$data['order'] = $orderShop; | |||
@@ -167,11 +280,36 @@ class OrderShopStore extends AbstractStore | |||
return $newOrderShop; | |||
} | |||
public function isCartAllowToBeOrder(OrderShopInterface $orderShop) | |||
public function isCartAllowToBeOrder(OrderShopInterface $orderShop, bool $forceByAdmin = false) | |||
{ | |||
return true; | |||
} | |||
// countValidOrderShopByUserAllMerchant | |||
public function countValidByUserAllMerchant($user) | |||
{ | |||
$totalOrder = 0; | |||
foreach ($this->merchantStore->getRepositoryQuery()->findAll() as $merchant) { | |||
$totalOrder += $this->countValidByUser($user, $merchant); | |||
} | |||
return $totalOrder; | |||
} | |||
public function countValidByUser(UserInterface $user, MerchantInterface $merchant = null) | |||
{ | |||
return $this->getBy( | |||
[ | |||
'user' => $user, | |||
'isValid' => true, | |||
'merchant' => $merchant, | |||
'excludeComplementaryOrderShops' => true, | |||
'count' => true | |||
] | |||
); | |||
} | |||
/* | |||
public function getCartCurrent(SectionInterface $section, UserInterface $user = null, VisitorInterface $visitor = null) | |||
{ |
@@ -2,22 +2,32 @@ | |||
namespace Lc\CaracoleBundle\Repository\Reduction; | |||
use App\Entity\Order\OrderShop; | |||
use App\Entity\Reduction\ReductionCart; | |||
use App\Resolver\Price\PriceResolver; | |||
use Lc\CaracoleBundle\Model\Reduction\ReductionCartInterface; | |||
use Lc\CaracoleBundle\Repository\Order\OrderShopStore; | |||
use Lc\SovBundle\Model\User\UserInterface; | |||
use Lc\SovBundle\Repository\AbstractStore; | |||
use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface; | |||
class ReductionCartStore extends AbstractStore | |||
{ | |||
protected ReductionCartRepositoryQuery $query; | |||
protected OrderShopStore $orderShopStore; | |||
protected PriceResolver $priceResolver; | |||
protected FlashBagInterface $flashBag; | |||
public function __construct( | |||
ReductionCartRepositoryQuery $query, | |||
OrderShopStore $orderShopStore | |||
OrderShopStore $orderShopStore, | |||
PriceResolver $priceResolver, | |||
FlashBagInterface $flashBag | |||
) { | |||
$this->query = $query; | |||
$this->orderShopStore = $orderShopStore; | |||
$this->priceResolver = $priceResolver; | |||
$this->flashBag = $flashBag; | |||
} | |||
// getReductionCartByCode | |||
@@ -48,13 +58,13 @@ class ReductionCartStore extends AbstractStore | |||
// getReductionCartUsedQuantityPerUser | |||
public function getUsedQuantityByUser(ReductionCartInterface $reductionCart, UserInterface $user): float | |||
{ | |||
return $this->orderShopStore->countValidOrderWithReductionCartPerUser($reductionCart, $user); | |||
return $this->orderShopStore->countValidWithReductionCartPerUser($reductionCart, $user); | |||
} | |||
// getReductionCartUsedQuantity | |||
public function getUsedQuantity(ReductionCartInterface $reductionCart): float | |||
{ | |||
return $this->orderShopStore->countValidOrderWithReductionCart($reductionCart); | |||
return $this->orderShopStore->countValidWithReductionCartPerUser($reductionCart); | |||
} | |||
// getReductionCartRemainingQuantityPerUser | |||
@@ -62,7 +72,7 @@ class ReductionCartStore extends AbstractStore | |||
{ | |||
if ($reductionCart->getAvailableQuantityPerUser()) { | |||
return $reductionCart->getAvailableQuantityPerUser( | |||
) - $this->orderShopRepo->countValidOrderWithReductionCartPerUser($reductionCart, $user); | |||
) - $this->orderShopStore->countValidWithReductionCartPerUser($reductionCart, $user); | |||
} | |||
return false; |
@@ -12,42 +12,11 @@ use Lc\SovBundle\Repository\AbstractStore; | |||
class ReductionCreditStore extends AbstractStore | |||
{ | |||
protected ReductionCreditRepositoryQuery $query; | |||
protected OrderShopStore $orderShopStore; | |||
public function __construct( | |||
ReductionCreditRepositoryQuery $query, | |||
OrderShopStore $orderShopStore | |||
ReductionCreditRepositoryQuery $query | |||
) { | |||
$this->query = $query; | |||
$this->orderShopStore = $orderShopStore; | |||
} | |||
// isReductionCreditAllowAddToOrder | |||
public function isAllowAddToOrder(OrderShopInterface $orderShop, ReductionCreditInterface $reductionCredit) | |||
{ | |||
$user = $orderShop->getUser(); | |||
// appartient à l'utilisateur | |||
if (!$reductionCredit->getUsers()->contains($user)) { | |||
// @TODO : gérer les addFlash dans le controleur | |||
//$this->utils->addFlash('error', 'error.reductionCredit.userNotAllow'); | |||
return false; | |||
} | |||
// n'a pas été utilisé | |||
if ($reductionCredit->getType() == ReductionCredit::TYPE_CREDIT) { | |||
if ($this->orderShopStore->countValidOrderWithReductionCredit($reductionCredit, $user) > 0) { | |||
//$this->utils->addFlash('error', 'error.reductionCredit.alreadyUse'); | |||
return false; | |||
} | |||
} else { | |||
if ($this->orderShopStore->countValidOrderWithReductionCredit($reductionCredit) > 0) { | |||
//$this->utils->addFlash('error', 'error.reductionCredit.alreadyUse'); | |||
return false; | |||
} | |||
} | |||
return true; | |||
} | |||
// findReductionCreditsByUser |
@@ -4,6 +4,7 @@ namespace Lc\CaracoleBundle\Repository\Section; | |||
use Lc\CaracoleBundle\Model\Section\SectionInterface; | |||
use Lc\CaracoleBundle\Repository\MerchantStoreTrait; | |||
use Lc\CaracoleBundle\Repository\Order\OrderShopStore; | |||
use Lc\SovBundle\Repository\AbstractStore; | |||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; | |||
@@ -12,6 +13,7 @@ class SectionStore extends AbstractStore | |||
use MerchantStoreTrait; | |||
protected SectionRepositoryQuery $query; | |||
protected OrderShopStore $orderShopStore; | |||
public function __construct(SectionRepositoryQuery $query) | |||
{ | |||
@@ -35,4 +37,9 @@ class SectionStore extends AbstractStore | |||
return $section; | |||
} | |||
public function countOpenDays(SectionInterface $section): int | |||
{ | |||
// @TODO : à implémenter avec le nouveau système d'ouverture des commandes | |||
} | |||
} |
@@ -2,9 +2,11 @@ | |||
namespace Lc\CaracoleBundle\Resolver; | |||
use App\Entity\Section\Section; | |||
use Lc\CaracoleBundle\Definition\SectionSettingDefinition; | |||
use Lc\CaracoleBundle\Model\Section\OpeningInterface; | |||
use Lc\CaracoleBundle\Model\Section\SectionInterface; | |||
use Lc\CaracoleBundle\Repository\Order\OrderShopStore; | |||
use Lc\SovBundle\Model\User\UserInterface; | |||
use Symfony\Component\Security\Core\Security; | |||
@@ -13,17 +15,20 @@ class OpeningResolver | |||
protected array $messages = []; | |||
protected SectionResolver $sectionResolver; | |||
protected Security $security; | |||
//protected OrderShopStore $orderShopStore; | |||
public function __construct(SectionResolver $sectionResolver, Security $security) | |||
public function __construct(SectionResolver $sectionResolver, Security $security /*, OrderShopStore $orderShopStore*/) | |||
{ | |||
$this->sectionResolver = $sectionResolver; | |||
$this->security = $security; | |||
//$this->orderShopStore = $orderShopStore; | |||
} | |||
public function isOpenSale( | |||
SectionInterface $section = null, | |||
UserInterface $user = null, | |||
\DateTime $date = null | |||
\DateTime $date = null, | |||
string $context = null | |||
): bool { | |||
// Initialisation | |||
$this->messages = []; | |||
@@ -54,18 +59,13 @@ class OpeningResolver | |||
} | |||
// Nombre maximum de commandes par cycle (voir configuration de section) | |||
$countOrderShopCycle = 0; | |||
$orderMaximumPerCycle = $section->getSettingValue(SectionSettingDefinition::SETTING_ORDER_MAXIMUM_PER_CYCLE); | |||
if ($orderMaximumPerCycle && $countOrderShopCycle >= $orderMaximumPerCycle) { | |||
if($this->isMaximumOrderCycleAchieved($section)) { | |||
$this->addMessage('Le nombre maximum de commande a été atteint.'); | |||
return false; | |||
} | |||
// Période de fermeture des commandes issue de la configuration de la section (congés) | |||
$orderClosedStart = $section->getSettingValue(SectionSettingDefinition::SETTING_ORDER_CLOSED_START); | |||
$orderClosedEnd = $section->getSettingValue(SectionSettingDefinition::SETTING_ORDER_CLOSED_END); | |||
if ($orderClosedStart && $orderClosedEnd && $date >= $orderClosedStart && $date <= $orderClosedEnd) { | |||
if($this->isClosingPeriod($section)) { | |||
$this->addMessage( | |||
'Les commandes sont fermées (période de fermeture des commandes dans la configuration de la section).' | |||
); | |||
@@ -89,6 +89,34 @@ class OpeningResolver | |||
return false; | |||
} | |||
// isHolidays | |||
public function isClosingPeriod(Section $section, \DateTime $date) | |||
{ | |||
$orderClosedStart = $section->getSettingValue(SectionSettingDefinition::SETTING_ORDER_CLOSED_START); | |||
$orderClosedEnd = $section->getSettingValue(SectionSettingDefinition::SETTING_ORDER_CLOSED_END); | |||
if ($orderClosedStart && $orderClosedEnd && $date >= $orderClosedStart && $date <= $orderClosedEnd) { | |||
return true; | |||
} | |||
return false; | |||
} | |||
// isMaximumOrderWeekAchieved | |||
public function isMaximumOrderCycleAchieved(SectionInterface $section) | |||
{ | |||
// @TODO : countValidByCycle | |||
//$countOrderShopCycle = $this->orderShopStore->countValidByCycle($section); | |||
$countOrderShopCycle = 0 ; | |||
$orderMaximumPerCycle = $section->getSettingValue(SectionSettingDefinition::SETTING_ORDER_MAXIMUM_PER_CYCLE); | |||
if ($orderMaximumPerCycle && $countOrderShopCycle >= $orderMaximumPerCycle) { | |||
return true; | |||
} | |||
return false; | |||
} | |||
public function isDateMatchWithOpening(\DateTime $date, OpeningInterface $opening): bool | |||
{ | |||
$day = $date->format('N'); | |||
@@ -130,7 +158,6 @@ class OpeningResolver | |||
return false; | |||
} | |||
public function getDateEndCurrentSale(SectionInterface $section, $formatDate = '', $delimiterDayTime = 'à') | |||
{ | |||
// @TODO : à réécrire |
@@ -0,0 +1,190 @@ | |||
<?php | |||
namespace Lc\CaracoleBundle\Statistic; | |||
use Doctrine\ORM\EntityManagerInterface; | |||
use Symfony\Component\OptionsResolver\OptionsResolver; | |||
class Statistic | |||
{ | |||
protected $properties = array(); | |||
protected $averageProperties = array(); | |||
protected $labels; | |||
protected $dateStart; | |||
protected $dateEnd; | |||
protected $interval; | |||
protected $em; | |||
protected $resultsSort; | |||
public function __construct( | |||
EntityManagerInterface $entityManager, | |||
?\DateTime $dateStart = null, | |||
?\DateTime $dateEnd = null, | |||
?string $interval = null | |||
) { | |||
$this->em = $entityManager; | |||
$this->dateStart = $dateStart; | |||
$this->dateEnd = $dateEnd; | |||
$this->interval = $interval; | |||
} | |||
public function addProperty(string $propertyName, array $options) | |||
{ | |||
$resolver = new OptionsResolver(); | |||
$this->configurePropertyOptions($resolver); | |||
$this->properties[$propertyName] = $resolver->resolve($options); | |||
$this->resultsSort[$propertyName] = $propertyName; | |||
} | |||
public function addAverageProperty(string $propertyName, array $options) | |||
{ | |||
$resolver = new OptionsResolver(); | |||
$this->configurePropertyOptions($resolver); | |||
$this->averageProperties[$propertyName] = $resolver->resolve($options); | |||
$this->resultsSort[$propertyName] = $propertyName; | |||
} | |||
public function setAverageData(string $propertyName, string $key, $value) | |||
{ | |||
if (isset($this->averageProperties[$propertyName])) { | |||
$this->averageProperties[$propertyName]['data'][$key] += number_format($value, 2); | |||
} else { | |||
throw new \Exception('La proprieté "' . $propertyName . '" n\'existe pas '); | |||
} | |||
} | |||
public function setData(string $propertyName, string $key, $value) | |||
{ | |||
if (isset($this->properties[$propertyName])) { | |||
$this->properties[$propertyName]['data'][$key] += number_format($value, 2); | |||
$this->properties[$propertyName]['total_period'] += number_format($value, 2); | |||
} else { | |||
throw new \Exception('La proprieté "' . $propertyName . '" n\'existe pas '); | |||
} | |||
} | |||
public function setAveragePropertiesData() | |||
{ | |||
foreach ($this->getLabels() as $key => $label) { | |||
foreach ($this->getAverageProperties() as $averagePropertyName => $averageProperty) { | |||
if ($this->getData($averageProperty['divider'], $key)) { | |||
$this->setAverageData( | |||
$averagePropertyName, | |||
$key, | |||
$this->getData($averageProperty['dividend'], $key) / $this->getData( | |||
$averageProperty['divider'], | |||
$key | |||
) | |||
); | |||
} | |||
if ($this->getTotalPeriod($averageProperty['divider'])) { | |||
$this->averageProperties[$averagePropertyName]['total_period'] = $this->getTotalPeriod( | |||
$averageProperty['dividend'] | |||
) / $this->getTotalPeriod($averageProperty['divider']); | |||
} | |||
} | |||
} | |||
foreach ($this->getProperties() as $propertyName => $property) { | |||
$this->properties[$propertyName]['average_period'] = number_format( | |||
$this->properties[$propertyName]['total_period'] / count($this->getLabels()), | |||
2 | |||
); | |||
} | |||
foreach ($this->getAverageProperties() as $averagePropertyName => $averageProperty) { | |||
$this->averageProperties[$averagePropertyName]['average_period'] = number_format( | |||
$this->averageProperties[$averagePropertyName]['total_period'] / count($this->getLabels()), | |||
2 | |||
); | |||
} | |||
} | |||
public function getLabels() | |||
{ | |||
return $this->labels; | |||
} | |||
public function getProperties() | |||
{ | |||
return $this->properties; | |||
} | |||
public function getData($propertyName, $key) | |||
{ | |||
if (!isset($this->properties[$propertyName])) { | |||
throw new \Exception('La proprieté "' . $propertyName . '" n\'existe pas '); | |||
} | |||
return $this->properties[$propertyName]['data'][$key]; | |||
} | |||
public function getTotalPeriod($propertyName) | |||
{ | |||
if (!isset($this->properties[$propertyName])) { | |||
throw new \Exception('La proprieté "' . $propertyName . '" n\'existe pas '); | |||
} | |||
return $this->properties[$propertyName]['total_period']; | |||
} | |||
public function getAverageProperties() | |||
{ | |||
return $this->averageProperties; | |||
} | |||
public function getResults() | |||
{ | |||
$results = array_replace($this->resultsSort, $this->properties, $this->averageProperties); | |||
return $results; | |||
} | |||
public function getAsArray() | |||
{ | |||
return array( | |||
'label' => $this->getLabels(), | |||
'data' => $this->getResults(), | |||
); | |||
} | |||
public function getDateRange() | |||
{ | |||
return new \DatePeriod( | |||
$this->getDateStart(), | |||
new \DateInterval('P1' . $this->getInterval()), | |||
$this->getDateEnd() | |||
); | |||
} | |||
public function getDateStart() | |||
{ | |||
return $this->dateStart; | |||
} | |||
public function getDateEnd() | |||
{ | |||
return $this->dateEnd; | |||
} | |||
public function getInterval() | |||
{ | |||
return $this->interval; | |||
} | |||
public function configurePropertyOptions(OptionsResolver $resolver) | |||
{ | |||
$resolver->setDefaults( | |||
[ | |||
'unit' => '', | |||
'label' => 'Chiffre affaire produit', | |||
'label_short' => 'CA produit', | |||
'data' => array(), | |||
'total_period' => 0, | |||
'average_period' => 0, | |||
'dividend' => null, | |||
'divider' => null, | |||
] | |||
); | |||
} | |||
} |