@@ -0,0 +1,28 @@ | |||
<?php | |||
namespace Lc\CaracoleBundle\Builder\Order; | |||
use Lc\CaracoleBundle\Model\Order\OrderProductInterface; | |||
use Lc\CaracoleBundle\Resolver\Price\PriceResolver; | |||
class OrderProductBuilder | |||
{ | |||
protected PriceResolver $priceResolver; | |||
public function __construct(PriceResolver $priceResolver) | |||
{ | |||
$this->priceResolver = $priceResolver; | |||
} | |||
public function init(OrderProductInterface $orderProduct) | |||
{ | |||
$orderProduct->setTitle($orderProduct->getTitleOrderShop()); | |||
$orderProduct->setPrice($this->priceResolver->getPrice($orderProduct->getProduct())); | |||
$orderProduct->setBuyingPrice($this->priceResolver->getBuyingPrice($orderProduct->getProduct())); | |||
$orderProduct->setUnit($orderProduct->getProduct()->getUnitInherited()); | |||
$orderProduct->setTaxRate($orderProduct->getProduct()->getTaxRateInherited()); | |||
$orderProduct->setQuantityProduct($orderProduct->getProduct()->getQuantityInherited()); | |||
return $orderProduct; | |||
} | |||
} |
@@ -0,0 +1,242 @@ | |||
<?php | |||
namespace Lc\CaracoleBundle\Builder\Order; | |||
use App\Entity\Order\OrderProductReductionCatalog; | |||
use Doctrine\ORM\EntityManagerInterface; | |||
use Lc\CaracoleBundle\Event\Order\OrderShopChangeStatusEvent; | |||
use Lc\CaracoleBundle\Factory\Order\OrderPaymentFactory; | |||
use Lc\CaracoleBundle\Factory\Order\OrderProductReductionCatalogFactory; | |||
use Lc\CaracoleBundle\Factory\Order\OrderShopFactory; | |||
use Lc\CaracoleBundle\Factory\Order\OrderStatusHistoryFactory; | |||
use Lc\CaracoleBundle\Model\Merchant\MerchantInterface; | |||
use Lc\CaracoleBundle\Model\Order\OrderProductInterface; | |||
use Lc\CaracoleBundle\Model\Order\OrderShopInterface; | |||
use Lc\CaracoleBundle\Model\Order\OrderStatusHistoryModel; | |||
use Lc\CaracoleBundle\Model\Order\OrderStatusModel; | |||
use Lc\CaracoleBundle\Model\Section\SectionInterface; | |||
use Lc\CaracoleBundle\Model\User\VisitorInterface; | |||
use Lc\CaracoleBundle\Repository\Order\OrderProductStore; | |||
use Lc\CaracoleBundle\Repository\Order\OrderStatusStore; | |||
use Lc\CaracoleBundle\Repository\Product\ProductFamilyStore; | |||
use Lc\CaracoleBundle\Resolver\Price\PriceResolver; | |||
use Lc\SovBundle\Model\User\UserInterface; | |||
class OrderShopBuilder | |||
{ | |||
protected EntityManagerInterface $entityManager; | |||
protected OrderStatusStore $orderStatusStore; | |||
protected OrderProductStore $orderProductStore; | |||
protected ProductFamilyStore $productFamilyStore; | |||
protected PriceResolver $priceResolver; | |||
protected OrderProductBuilder $orderProductBuilder; | |||
public function __construct( | |||
EntityManagerInterface $entityManager, | |||
OrderStatusStore $orderStatusStore, | |||
OrderProductStore $orderProductStore, | |||
ProductFamilyStore $productFamilyStore, | |||
OrderProductBuilder $orderProductBuilder, | |||
PriceResolver $priceResolver | |||
) { | |||
$this->entityManager = $entityManager; | |||
$this->orderStatusStore = $orderStatusStore; | |||
$this->orderProductStore = $orderProductStore; | |||
$this->productFamilyStore = $productFamilyStore; | |||
$this->orderProductBuilder = $orderProductBuilder; | |||
$this->priceResolver = $priceResolver; | |||
} | |||
public function create( | |||
MerchantInterface $merchant, | |||
SectionInterface $section, | |||
UserInterface $user = null, | |||
VisitorInterface $visitor = null | |||
) { | |||
$orderShopFactory = new OrderShopFactory(); | |||
$orderShop = $orderShopFactory->create($merchant, $section, $user, $visitor); | |||
$this->changeOrderStatus($orderShop, OrderStatusModel::ALIAS_CART); | |||
return $orderShop; | |||
} | |||
public function changeOrderStatus(OrderShopInterface $orderShop, string $alias) | |||
{ | |||
$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 | |||
); | |||
$orderShop->setOrderStatusProtected($orderStatus); | |||
$orderStatusHistoryFactory = new OrderStatusHistoryFactory(); | |||
$orderStatusHistory = $orderStatusHistoryFactory->create($orderShop, $orderStatus); | |||
$orderShop->addOrderStatusHistory($orderStatusHistory); | |||
} | |||
return $orderShop; | |||
} | |||
public function addOrderProduct( | |||
OrderShopInterface $orderShop, | |||
OrderProductInterface $orderProductAdd, | |||
bool $persist = true | |||
) { | |||
$return = false; | |||
if ($this->orderProductStore->isOrderProductAvailableAddCart($orderProductAdd, $orderShop)) { | |||
if ($orderProductAdd->getQuantityOrder() > 0) { | |||
$updated = false; | |||
$this->orderProductBuilder->init($orderProductAdd); | |||
$productFamily = $this->productFamilyStore->getOneBySlug( | |||
$orderProductAdd->getProduct()->getProductFamily()->getSlug() | |||
); | |||
if ($productFamily) { | |||
$reductionCatalog = $productFamily->getReductionCatalog(); | |||
if ($reductionCatalog) { | |||
$orderProductReductionCatalogFactory = new OrderProductReductionCatalogFactory(); | |||
$orderProductReductionCatalog = $orderProductReductionCatalogFactory->create( | |||
$reductionCatalog->getTitle(), | |||
$reductionCatalog->getValue(), | |||
$reductionCatalog->getUnit(), | |||
$reductionCatalog->getBehaviorTaxRate() | |||
); | |||
$orderProductAdd->setOrderProductReductionCatalog($orderProductReductionCatalog); | |||
} | |||
} | |||
foreach ($orderShop->getOrderProducts() as $orderProduct) { | |||
if ($orderProduct->getProduct()->getId() == $orderProductAdd->getProduct()->getId() | |||
&& $orderProduct->getRedelivery() == $orderProductAdd->getRedelivery() | |||
&& (string)$this->priceResolver->getPrice($orderProduct) | |||
== (string)$this->priceResolver->getPrice($orderProductAdd) | |||
&& $orderProduct->getOrderProductReductionCatalog()->compare( | |||
$orderProductAdd->getOrderProductReductionCatalog() | |||
)) { | |||
$orderProduct->setQuantityOrder( | |||
$orderProduct->getQuantityOrder() + $orderProductAdd->getQuantityOrder() | |||
); | |||
if ($persist) { | |||
$this->entityManager->persist($orderProduct); | |||
} | |||
$updated = true; | |||
$return = true; | |||
break; | |||
} | |||
} | |||
if (!$updated) { | |||
$orderShop->addOrderProduct($orderProductAdd); | |||
if ($persist) { | |||
if (isset($orderProductReductionCatalog)) { | |||
$this->entityManager->persist($orderProductReductionCatalog); | |||
} | |||
$this->entityManager->persist($orderProductAdd); | |||
$this->entityManager->persist($orderShop); | |||
} | |||
$return = true; | |||
} | |||
if ($persist) { | |||
$this->entityManager->flush(); | |||
} | |||
// @TODO : dispatch event cart change | |||
//$this->eventCartChange($orderShop); | |||
} | |||
} else { | |||
// @TODO : retourner le message d'erreur et faire le addFlash dans le contrôleur | |||
/*$availableQuantity = $orderProductAdd->getProduct()->getAvailableQuantityInherited(); | |||
$textError = "Le produit <strong>" . $orderProductAdd->getTitleOrderShop( | |||
) . "</strong> n'est pas disponible"; | |||
if ($availableQuantity !== false && $availableQuantity > 0) { | |||
$unit = ''; | |||
if ($orderProductAdd->getProduct()->getProductFamily()->getBehaviorCountStock( | |||
) == ProductFamily::BEHAVIOR_COUNT_STOCK_BY_MEASURE) { | |||
$unit = $orderProductAdd->getProduct()->getUnitInherited()->getUnitReference()->getUnit(); | |||
} | |||
$textError .= ' dans cette quantité '; | |||
$user = $this->security->getUser(); | |||
if ($user && $user->hasRole('ROLE_USER')) { | |||
$textError .= '<br />' . $availableQuantity . $unit . ' disponible(s) dont ' . $this->getQuantityOrderByProduct( | |||
$orderShop, | |||
$orderProductAdd->getProduct() | |||
) . $unit . ' déjà dans votre panier.'; | |||
} | |||
} | |||
$this->utils->addFlash('error', $textError);*/ | |||
} | |||
return $return; | |||
} | |||
public function merge(OrderShopInterface $orderShop1, OrderShopInterface $orderShop2, $persist = true) | |||
{ | |||
if ($orderShop1 && $orderShop2) { | |||
foreach ($orderShop2->getOrderProducts() as $orderProduct) { | |||
$orderProductAlreadyInCart = $orderShop1->hasOrderProductAlreadyInCart($orderProduct); | |||
if ($orderProductAlreadyInCart) { | |||
if ($orderProduct->getQuantityOrder() > $orderProductAlreadyInCart->getQuantityOrder()) { | |||
$orderShop1->removeOrderProduct($orderProductAlreadyInCart); | |||
$this->addOrderProduct($orderShop1, $orderProduct); | |||
} | |||
} else { | |||
$this->addOrderProduct($orderShop1, $orderProduct); | |||
} | |||
if ($persist) { | |||
$this->entityManager->remove($orderProduct); | |||
} | |||
} | |||
if ($persist) { | |||
$this->entityManager->remove($orderShop2); | |||
$this->entityManager->persist($orderShop1); | |||
$this->entityManager->flush(); | |||
} | |||
return $orderShop1; | |||
} | |||
} | |||
public function addPayment(OrderShopInterface $orderShop, $meanPayment, $amount) | |||
{ | |||
$orderPaymentFactory = new OrderPaymentFactory(); | |||
$orderPayment = $orderPaymentFactory->create($orderShop, $meanPayment, $amount); | |||
$orderShop->addOrderPayment($orderPayment); | |||
if ($this->isOrderPaid($orderShop)) { | |||
$nextStatus = OrderStatusModel::ALIAS_PAID; | |||
} else { | |||
$nextStatus = OrderStatusModel::ALIAS_PARTIAL_PAYMENT; | |||
} | |||
if ($orderShop->getOrderStatus()->getAlias() != $nextStatus) { | |||
$orderShop = $this->changeOrderStatus($orderShop, $nextStatus); | |||
} | |||
$this->entityManager->persist($orderPayment); | |||
$this->entityManager->update($orderShop); | |||
$this->entityManager->flush(); | |||
return $orderShop; | |||
} | |||
} |
@@ -0,0 +1,27 @@ | |||
<?php | |||
namespace Lc\CaracoleBundle\Event\EntityManager; | |||
use Symfony\Contracts\EventDispatcher\Event; | |||
class EntityManagerEvent extends Event | |||
{ | |||
const CREATE_EVENT = 'entity_manager_event.create'; | |||
const UPDATE_EVENT = 'entity_manager_event.update'; | |||
const DELETE_EVENT = 'entity_manager_event.delete'; | |||
const PRE_CREATE_EVENT = 'entity_manager_event.pre_create'; | |||
const PRE_UPDATE_EVENT = 'entity_manager_event.pre_update'; | |||
const PRE_DELETE_EVENT = 'entity_manager_event.pre_delete'; | |||
protected $entity; | |||
public function __construct($entity) | |||
{ | |||
$this->entity = $entity; | |||
} | |||
public function getEntity() | |||
{ | |||
return $this->entity; | |||
} | |||
} |
@@ -0,0 +1,30 @@ | |||
<?php | |||
namespace Lc\CaracoleBundle\Event\Order; | |||
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; | |||
} | |||
} |
@@ -4,14 +4,19 @@ namespace Lc\CaracoleBundle\Factory\Order; | |||
use App\Entity\Order\OrderPayment; | |||
use Lc\CaracoleBundle\Model\Order\OrderPaymentInterface; | |||
use Lc\CaracoleBundle\Model\Order\OrderShopInterface; | |||
use Lc\SovBundle\Factory\AbstractFactory; | |||
class OrderPaymentFactory extends AbstractFactory | |||
{ | |||
public function create(): OrderPaymentInterface | |||
public function create(OrderShopInterface $orderShop, string $meanPayment, float $amount): OrderPaymentInterface | |||
{ | |||
$orderPayment = new OrderPayment(); | |||
$orderPayment->setOrderShop($orderShop); | |||
$orderPayment->setMeanPayment($meanPayment); | |||
$orderPayment->setAmount($amount); | |||
return $orderPayment; | |||
} | |||
@@ -8,10 +8,15 @@ use Lc\SovBundle\Factory\AbstractFactory; | |||
class OrderProductReductionCatalogFactory extends AbstractFactory | |||
{ | |||
public function create(): OrderProductReductionCatalogInterface | |||
public function create(string $title, float $value, string $unit, string $behaviorTaxRate): OrderProductReductionCatalogInterface | |||
{ | |||
$orderProductReductionCatalog = new OrderProductReductionCatalog(); | |||
$orderProductReductionCatalog->setTitle($title); | |||
$orderProductReductionCatalog->setValue($value); | |||
$orderProductReductionCatalog->setUnit($unit); | |||
$orderProductReductionCatalog->setBehaviorTaxRate($behaviorTaxRate); | |||
return $orderProductReductionCatalog; | |||
} | |||
@@ -3,23 +3,57 @@ | |||
namespace Lc\CaracoleBundle\Factory\Order; | |||
use App\Entity\Order\OrderShop; | |||
use Lc\CaracoleBundle\Factory\MerchantFactoryTrait; | |||
use Lc\CaracoleBundle\Factory\SectionFactoryTrait; | |||
use Lc\CaracoleBundle\Event\Order\OrderShopChangeStatusEvent; | |||
use Lc\CaracoleBundle\Model\Merchant\MerchantInterface; | |||
use Lc\CaracoleBundle\Model\Order\OrderShopInterface; | |||
use Lc\CaracoleBundle\Model\Order\OrderStatusModel; | |||
use Lc\CaracoleBundle\Model\Section\SectionInterface; | |||
use Lc\CaracoleBundle\Model\User\VisitorInterface; | |||
use Lc\SovBundle\Factory\AbstractFactory; | |||
use Lc\SovBundle\Model\User\UserInterface; | |||
use Symfony\Component\EventDispatcher\EventDispatcherInterface; | |||
class OrderShopFactory extends AbstractFactory | |||
{ | |||
protected EventDispatcherInterface $eventDispatcher; | |||
protected OrderStatusHistoryFactory $orderStatusHistoryFactory; | |||
public function __construct( | |||
EventDispatcherInterface $eventDispatcher, | |||
OrderStatusHistoryFactory $orderStatusHistoryFactory | |||
) { | |||
$this->eventDispatcher = $eventDispatcher; | |||
$this->orderStatusHistoryFactory = $orderStatusHistoryFactory; | |||
} | |||
public function create( | |||
MerchantInterface $merchant, | |||
SectionInterface $section, | |||
UserInterface $user = null, | |||
VisitorInterface $visitor = null | |||
): OrderShopInterface { | |||
public function create(MerchantInterface $merchant, SectionInterface $section): OrderShopInterface | |||
{ | |||
$orderShop = new OrderShop(); | |||
$orderShop->setMerchant($merchant); | |||
$orderShop->setSection($section); | |||
$orderShopBelongTo = false; | |||
if (!is_null($user)) { | |||
$orderShopBelongTo = true; | |||
$orderShop->setUser($user); | |||
} | |||
if (!is_null($visitor) && !$orderShop->getUser()) { | |||
$orderShopBelongTo = true; | |||
$orderShop->setVisitor($visitor); | |||
} | |||
if (!$orderShopBelongTo) { | |||
throw new \ErrorException('La commande doit être liée à un utilisateur ou à un visiteur.'); | |||
} | |||
return $orderShop; | |||
} | |||
@@ -3,15 +3,21 @@ | |||
namespace Lc\CaracoleBundle\Factory\Order; | |||
use App\Entity\Order\OrderStatusHistory; | |||
use Lc\CaracoleBundle\Model\Order\OrderShopInterface; | |||
use Lc\CaracoleBundle\Model\Order\OrderStatusHistoryInterface; | |||
use Lc\CaracoleBundle\Model\Order\OrderStatusHistoryModel; | |||
use Lc\SovBundle\Factory\AbstractFactory; | |||
class OrderStatusHistoryFactory extends AbstractFactory | |||
{ | |||
public function create(): OrderStatusHistoryInterface | |||
public function create(OrderShopInterface $orderShop, string $status, string $origin = OrderStatusHistoryModel::ORIGIN_USER): OrderStatusHistoryInterface | |||
{ | |||
$orderStatusHistory = new OrderStatusHistory(); | |||
$orderStatusHistory->setOrderShop($orderShop); | |||
$orderStatusHistory->setOrderStatus($status); | |||
$orderStatusHistory->setOrigin($origin); | |||
return $orderStatusHistory; | |||
} | |||
@@ -28,4 +28,12 @@ abstract class OrderProductReductionCatalogModel | |||
return $this; | |||
} | |||
public function compare($orderProductReductionCatalog) | |||
{ | |||
return $orderProductReductionCatalog | |||
&& $this->getUnit() == $orderProductReductionCatalog->getUnit() | |||
&& (string)$this->getValue() == (string)$orderProductReductionCatalog->getValue() | |||
&& $this->getBehaviorTaxRate() == $orderProductReductionCatalog->getBehaviorTaxRate(); | |||
} | |||
} |
@@ -153,6 +153,63 @@ abstract class OrderShopModel extends AbstractLightEntity implements FilterSecti | |||
} | |||
} | |||
public function countQuantities() | |||
{ | |||
return self::countQuantitiesByOrderProducts($this->getOrderProducts()); | |||
} | |||
public static function countQuantitiesByOrderProducts($orderProducts = []) | |||
{ | |||
$count = 0; | |||
foreach ($orderProducts as $orderProduct) { | |||
$count += $orderProduct->getQuantityOrder(); | |||
} | |||
return $count; | |||
} | |||
public function getOrderProductsByParentCategory() | |||
{ | |||
$categoriesArray = []; | |||
foreach ($this->getOrderProducts() as $orderProduct) { | |||
$productCategories = $orderProduct->getProduct()->getProductFamily()->getProductCategories(); | |||
$category = $productCategories[0]->getParentCategory(); | |||
$labelCategory = $category->getTitle(); | |||
if (!isset($categoriesArray[$labelCategory])) { | |||
$categoriesArray[$labelCategory] = []; | |||
} | |||
$categoriesArray[$labelCategory][] = $orderProduct; | |||
} | |||
return $categoriesArray; | |||
} | |||
public function hasOrderProductAlreadyInCart($orderProductTest) | |||
{ | |||
foreach($this->getOrderProducts() as $orderProduct) { | |||
if($orderProduct->getProduct() == $orderProductTest->getProduct()) { | |||
return $orderProduct ; | |||
} | |||
} | |||
return false ; | |||
} | |||
public function getOrderProductsByProductFamily($productFamily) | |||
{ | |||
$arrayOrderProducts = [] ; | |||
foreach($this->getOrderProducts() as $orderProduct) { | |||
if($orderProduct->getProduct()->getProductFamily() == $productFamily) { | |||
$arrayOrderProducts[] = $orderProduct ; | |||
} | |||
} | |||
return $arrayOrderProducts ; | |||
} | |||
public function getValidationDate(): ?\DateTimeInterface | |||
{ | |||
return $this->validationDate; |
@@ -24,6 +24,10 @@ abstract class OrderStatusHistoryModel extends AbstractLightEntity | |||
*/ | |||
protected $orderStatus; | |||
const ORIGIN_USER = 'user'; | |||
const ORIGIN_ADMIN = 'admin'; | |||
const ORIGIN_SYSTEM = 'system'; | |||
/** | |||
* @ORM\Column(type="string", length=31) | |||
*/ |
@@ -2,14 +2,141 @@ | |||
namespace Lc\CaracoleBundle\Repository\Order; | |||
use Lc\CaracoleBundle\Model\Order\OrderShopInterface; | |||
use Lc\CaracoleBundle\Resolver\Price\PriceResolver; | |||
use Lc\SovBundle\Repository\AbstractStore; | |||
class OrderShopStore extends AbstractStore | |||
{ | |||
protected OrderShopRepositoryQuery $query; | |||
protected PriceResolver $priceResolver; | |||
public function __construct(OrderShopRepositoryQuery $query) | |||
{ | |||
public function __construct( | |||
OrderShopRepositoryQuery $query, | |||
PriceResolver $priceResolver | |||
) { | |||
$this->query = $query; | |||
$this->priceResolver = $priceResolver; | |||
} | |||
public function getDatas(OrderShopInterface $orderShop = null): array | |||
{ | |||
$data = []; | |||
if (is_null($orderShop)) { | |||
$orderShop = $this->getCartCurrent(); | |||
} | |||
$data['order'] = $orderShop; | |||
if ($orderShop) { | |||
$data['count'] = $orderShop->countQuantities(); | |||
$data['total_with_tax'] = $this->priceResolver->getTotalWithTax($orderShop); | |||
$data['order_products_by_category'] = $orderShop->getOrderProductsByParentCategory(); | |||
$data['total_remaining_to_be_paid'] = $this->getTotalRemainingToBePaid($orderShop); | |||
} | |||
return $data; | |||
} | |||
public function getAsJsonObject(OrderShopInterface $orderShop): array | |||
{ | |||
$data['id'] = $orderShop->getId(); | |||
$data['user'] = $orderShop->getUser()->getSummary(); | |||
$data['orderStatus'] = $orderShop->getOrderStatus()->__toString(); | |||
$data['deliveryAddress'] = $orderShop->getDeliveryAddress()->getSummary(); | |||
$data['invoiceAddress'] = $orderShop->getInvoiceAddress()->getSummary(); | |||
$data['total'] = $this->priceResolver->getTotal($orderShop); | |||
$data['totalWithTax'] = $this->priceResolver->getTotalWithTax($orderShop); | |||
$data['totalWithTaxAndReduction'] = $this->priceResolver->getTotalWithTax($orderShop); | |||
$i = 0; | |||
foreach ($orderShop->getOrderProductsByParentCategory() as $labelCategory => $orderProducts) { | |||
foreach ($orderProducts as $orderProduct) { | |||
$data['orderProducts'][$i]['id'] = $orderProduct->getId(); | |||
$data['orderProducts'][$i]['product'] = $orderProduct->getProduct()->getId(); | |||
$data['orderProducts'][$i]['quantityOrder'] = $orderProduct->getQuantityOrder(); | |||
$data['orderProducts'][$i]['labelCategory'] = $labelCategory; | |||
$data['orderProducts'][$i]['title'] = $orderProduct->getTitle(); | |||
$data['orderProducts'][$i]['price'] = $this->priceResolver->getPrice($orderProduct); | |||
$data['orderProducts'][$i]['priceWithTax'] = $this->priceResolver->getPriceWithTax($orderProduct); | |||
$data['orderProducts'][$i]['priceWithTaxAndReduction'] = $this->priceResolver->getPriceWithTaxAndReduction( | |||
$orderProduct | |||
); | |||
$data['orderProducts'][$i]['quantity'] = $orderProduct->getQuantityOrder(); | |||
$data['orderProducts'][$i]['totalWithTaxAndReduction'] = $this->priceResolver->getTotalOrderProductsWithTaxAndReduction( | |||
array($orderProduct) | |||
); | |||
$i++; | |||
} | |||
} | |||
return $data; | |||
} | |||
public function groupOrderProductsByProductFamily(array $orderProducts): array | |||
{ | |||
$orderProductsByProductFamily = []; | |||
foreach ($orderProducts as $orderProduct) { | |||
if ($orderProduct->getProduct() && $orderProduct->getProduct()->getProductFamily()) { | |||
$productFamily = $orderProduct->getProduct()->getProductFamily(); | |||
if (!isset($orderProductsByProductFamily[$productFamily->getId()])) { | |||
$orderProductsByProductFamily[$productFamily->getId()] = [ | |||
'order_products' => [], | |||
'total_quantity_weight' => 0, | |||
]; | |||
} | |||
$orderProductsByProductFamily[$productFamily->getId()]['order_products'][] = $orderProduct; | |||
$orderProductsByProductFamily[$productFamily->getId( | |||
)]['total_quantity_weight'] += ($orderProduct->getQuantityProduct() / $orderProduct->getUnit( | |||
)->getCoefficient()) * $orderProduct->getQuantityOrder(); | |||
} | |||
} | |||
return $orderProductsByProductFamily; | |||
} | |||
public function isPositiveAmount(OrderShopInterface $orderShop) | |||
{ | |||
return $this->priceResolver->getTotalWithTax($orderShop) >= 0; | |||
} | |||
public function isPaid(OrderShopInterface $orderShop, $mergeComplementaryOrderShop = false) | |||
{ | |||
$totalOrderPayments = $this->getTotalOrderPayments($orderShop, $mergeComplementaryOrderShop); | |||
$totalOrder = $this->priceResolver->getTotalWithTax($orderShop); | |||
if ((abs($totalOrderPayments - $totalOrder) < 0.00001 | |||
|| $totalOrderPayments >= $totalOrder) | |||
&& $totalOrder > 0) { | |||
return true; | |||
} else { | |||
return false; | |||
} | |||
} | |||
public function getTotalOrderPayments(OrderShopInterface $orderShop, $mergeComplementaryOrderShop = false): float | |||
{ | |||
$totalAmount = floatval(0); | |||
foreach ($orderShop->getOrderPayments() as $orderPayment) { | |||
$totalAmount = $orderPayment->getAmount() + $totalAmount; | |||
} | |||
if ($mergeComplementaryOrderShop) { | |||
foreach ($orderShop->getComplementaryOrderShops() as $complementaryOrderShop) { | |||
foreach ($complementaryOrderShop->getOrderPayments() as $orderPayment) { | |||
$totalAmount = $orderPayment->getAmount() + $totalAmount; | |||
} | |||
} | |||
} | |||
return $totalAmount; | |||
} | |||
public function getTotalRemainingToBePaid(OrderShopInterface $orderShop): float | |||
{ | |||
return $this->priceResolver->getTotalWithTax($orderShop) - $this->getTotalOrderPayments($orderShop); | |||
} | |||
public function isOrderShopPositiveAmountRemainingToBePaid(OrderShopInterface $orderShop): bool | |||
{ | |||
return $this->getTotalRemainingToBePaid($orderShop) > 0; | |||
} | |||
} |
@@ -0,0 +1,140 @@ | |||
<?php | |||
namespace Lc\CaracoleBundle\Resolver\Price; | |||
use Lc\CaracoleBundle\Model\Order\OrderProductInterface; | |||
class OrderProductPriceResolver | |||
{ | |||
use PriceResolverTrait; | |||
protected $ProductPriceResolver; | |||
public function __construct(ProductPriceResolver $ProductPriceResolver) | |||
{ | |||
$this->ProductPriceResolver = $ProductPriceResolver; | |||
} | |||
public function getPrice(OrderProductInterface $orderProduct, $round = false) | |||
{ | |||
if ($round) { | |||
return $this->round($orderProduct->getPrice()); | |||
} else { | |||
return $orderProduct->getPrice(); | |||
} | |||
} | |||
public function getBuyingPrice(OrderProductInterface $orderProduct, $round = false) | |||
{ | |||
if ($round) { | |||
return $this->round($orderProduct->getBuyingPrice()); | |||
} else { | |||
return $orderProduct->getBuyingPrice(); | |||
} | |||
} | |||
public function getPriceWithTax(OrderProductInterface $orderProduct) | |||
{ | |||
return $this->applyTax( | |||
$this->getPrice($orderProduct), | |||
$orderProduct->getTaxRate()->getValue() | |||
); | |||
} | |||
public function getPriceWithTaxAndReduction(OrderProductInterface $orderProduct) | |||
{ | |||
return $this->applyReductionCatalog( | |||
$orderProduct, | |||
$this->getPrice($orderProduct), | |||
$this->getPriceWithTax($orderProduct) | |||
); | |||
} | |||
public function getPriceWithReduction(OrderProductInterface $orderProduct, $round = true) | |||
{ | |||
return $this->applyReductionCatalog( | |||
$orderProduct, | |||
$this->getPrice($orderProduct), | |||
$this->getPriceWithTax($orderProduct), | |||
1, | |||
null, | |||
false, | |||
$round | |||
); | |||
} | |||
public function getTotal(OrderProductInterface $orderProduct) | |||
{ | |||
return $orderProduct->getQuantityOrder() * $this->getPrice($orderProduct); | |||
} | |||
public function getTotalBuyingPrice(OrderProductInterface $orderProduct) | |||
{ | |||
return $orderProduct->getQuantityOrder() * $this->getBuyingPrice($orderProduct); | |||
} | |||
public function getMargin(OrderProductInterface $orderProduct) | |||
{ | |||
return $this->round($this->getPriceWithReduction($orderProduct, false) - $this->getBuyingPrice($orderProduct)); | |||
} | |||
public function getMarginPercent(OrderProductInterface $orderProduct) | |||
{ | |||
if ($this->getBuyingPrice($orderProduct) && $this->getPriceWithReduction($orderProduct)) { | |||
return $this->round(($this->getMargin($orderProduct) / $this->getPriceWithReduction($orderProduct)) * 100); | |||
} else { | |||
return 0; | |||
} | |||
} | |||
public function getTotalMargin(OrderProductInterface $orderProduct) | |||
{ | |||
return $orderProduct->getQuantityOrder() * $this->getMargin($orderProduct); | |||
} | |||
public function getTotalWithReduction(OrderProductInterface $orderProduct) | |||
{ | |||
return $this->applyReductionCatalog( | |||
$orderProduct, | |||
$this->getTotal($orderProduct), | |||
$this->getTotalWithTax($orderProduct), | |||
$orderProduct->getQuantityOrder(), | |||
null, | |||
false | |||
); | |||
} | |||
public function getTotalWithTax(OrderProductInterface $orderProduct) | |||
{ | |||
return $this->applyTax( | |||
$this->getTotal($orderProduct), | |||
$orderProduct->getTaxRateInherited()->getValue() | |||
); | |||
} | |||
public function getTotalWithTaxAndReduction(OrderProductInterface $orderProduct) | |||
{ | |||
return $this->applyReductionCatalog( | |||
$orderProduct, | |||
$this->getTotal($orderProduct), | |||
$this->getTotalWithTax($orderProduct), | |||
$orderProduct->getQuantityOrder() | |||
); | |||
} | |||
public function getTotalBuyingPriceWithTax(OrderProductInterface $orderProduct) | |||
{ | |||
return $this->applyTax( | |||
$this->getTotalBuyingPrice($orderProduct), | |||
$orderProduct->getTaxRateInherited()->getValue() | |||
); | |||
} | |||
//inclus toujours les réductions catalogues | |||
public function getTotalTaxes(OrderProductInterface $orderProduct) | |||
{ | |||
return $this->getTotalWithTaxAndReduction($orderProduct) - $this->getTotalWithReduction($orderProduct); | |||
} | |||
} | |||
@@ -0,0 +1,382 @@ | |||
<?php | |||
namespace Lc\CaracoleBundle\Resolver\Price; | |||
use Lc\CaracoleBundle\Model\Order\OrderReductionCreditInterface; | |||
use Lc\CaracoleBundle\Model\Order\OrderShopInterface; | |||
use Lc\CaracoleBundle\Model\Reduction\ReductionCartModel; | |||
use Lc\CaracoleBundle\Model\Reduction\ReductionCreditModel; | |||
class OrderShopPriceResolver | |||
{ | |||
use PriceResolverTrait; | |||
protected $orderProductPriceResolver; | |||
public function __construct(OrderProductPriceResolver $orderProductPriceResolver) | |||
{ | |||
$this->orderProductPriceResolver = $orderProductPriceResolver; | |||
} | |||
//Inclus les ReductionCatalog des OrderProducts | |||
public function getTotalOrderProducts(OrderShopInterface $orderShop): float | |||
{ | |||
// A tester calculer ce montant en faisant TotalOrderWithTax - TotalOrderTaxes | |||
$total = 0; | |||
foreach ($orderShop->getOrderProducts() as $orderProduct) { | |||
$total += $this->orderProductPriceResolver->getTotalWithReduction($orderProduct); | |||
} | |||
return $total; | |||
} | |||
//Inclus les ReductionCatalog des OrderProducts | |||
public function getMarginOrderProducts(OrderShopInterface $orderShop): float | |||
{ | |||
$total = 0; | |||
foreach ($orderShop->getOrderProducts() as $orderProduct) { | |||
$total += $this->orderProductPriceResolver->getTotalMargin($orderProduct); | |||
} | |||
return $total; | |||
} | |||
public function getMarginOrderProductsWithReductions(OrderShopInterface $orderShop, $cache = false): float | |||
{ | |||
if ($cache && $orderShop->getStatMarginOrderProductsWithReductions() !== null) { | |||
return $orderShop->getStatMarginOrderProductsWithReductions(); | |||
} else { | |||
$total = $this->getMarginOrderProducts($orderShop); | |||
$totalReductionAmount = 0; | |||
foreach ($orderShop->getOrderReductionCarts() as $orderReductionCart) { | |||
$totalReductionAmount += $this->getOrderProductsReductionCartAmountWithoutTax( | |||
$orderShop, | |||
$orderReductionCart | |||
); | |||
} | |||
foreach ($orderShop->getOrderReductionCredits() as $orderReductionCredit) { | |||
$totalReductionAmount += $this->getOrderProductsReductionCreditAmountWithoutTax( | |||
$orderShop, | |||
$orderReductionCredit | |||
); | |||
} | |||
$total -= $totalReductionAmount; | |||
return $total; | |||
} | |||
} | |||
public function getMarginOrderProductsWithReductionsPercent(OrderShopInterface $orderShop): float | |||
{ | |||
if ($this->getTotalOrderProducts($orderShop)) { | |||
return $this->round( | |||
$this->getMarginOrderProductsWithReductions( | |||
$orderShop | |||
) / $this->getTotalOrderProductsWithReductions($orderShop) * 100 | |||
); | |||
} else { | |||
return 0; | |||
} | |||
} | |||
public function getMarginOrderProductsPercent(OrderShopInterface $orderShop): float | |||
{ | |||
if ($this->getTotalOrderProducts($orderShop)) { | |||
return $this->round( | |||
$this->getMarginOrderProducts($orderShop) / $this->getTotalOrderProducts($orderShop) * 100 | |||
); | |||
} else { | |||
return 0; | |||
} | |||
} | |||
public function getBrandTaxesOrderProductsWithReductionsPercent(OrderShopInterface $orderShop): float | |||
{ | |||
if ($this->getTotalOrderProducts($orderShop)) { | |||
return $this->round( | |||
$this->getMarginOrderProducts($orderShop) / $this->getTotalBuyingPriceOrderProducts( | |||
$orderShop->getOrderProducts() | |||
) * 100 | |||
); | |||
} else { | |||
return 0; | |||
} | |||
} | |||
public function getTotalOrderProductsWithTax(OrderShopInterface $orderShop): float | |||
{ | |||
return $this->getTotalOrderProductsWithTaxByOrderProducts($orderShop->getOrderProducts()); | |||
} | |||
public function getTotalBuyingPriceOrderProducts($orderProducts): float | |||
{ | |||
$total = 0; | |||
foreach ($orderProducts as $orderProduct) { | |||
$total += $this->orderProductPriceResolver->getTotalBuyingPrice($orderProduct); | |||
} | |||
return $total; | |||
} | |||
public function getTotalBuyingPriceOrderProductsWithTax($orderProducts): float | |||
{ | |||
$total = 0; | |||
foreach ($orderProducts as $orderProduct) { | |||
$total += $this->orderProductPriceResolver->getTotalBuyingPriceWithTax($orderProduct); | |||
} | |||
return $total; | |||
} | |||
public function getTotalOrderProductsWithTaxByOrderProducts($orderProducts): float | |||
{ | |||
$total = 0; | |||
foreach ($orderProducts as $orderProduct) { | |||
$total += $this->orderProductPriceResolver->getTotalWithTaxAndReduction($orderProduct); | |||
} | |||
return $total; | |||
} | |||
public function getTotalOrderProductsTaxes(OrderShopInterface $orderShop): float | |||
{ | |||
$total = 0; | |||
foreach ($orderShop->getOrderProducts() as $orderProduct) { | |||
$total += $this->orderProductPriceResolver->getTotalTaxes($orderProduct) / $this->getReductionsCoef( | |||
$orderShop | |||
); | |||
} | |||
return $total; | |||
} | |||
public function getOrderProductsTaxesAsArray(OrderShopInterface $orderShop): array | |||
{ | |||
$orderProductsTaxes = []; | |||
foreach ($orderShop->getOrderProducts() as $orderProduct) { | |||
$idTaxRate = $orderProduct->getTaxRate()->getId(); | |||
if (!isset($orderProductsTaxes[$idTaxRate])) { | |||
$orderProductsTaxes[$idTaxRate] = [ | |||
'label' => $orderProduct->getTaxRate()->getValue() . '%', | |||
'totalOrderProducts' => 0, | |||
'totalTaxes' => 0, | |||
]; | |||
} | |||
$orderProductsTaxes[$idTaxRate]['totalOrderProducts'] += $this->orderProductPriceResolver->getTotalWithReduction( | |||
$orderProduct | |||
) / $this->getReductionsCoef($orderShop); | |||
$orderProductsTaxes[$idTaxRate]['totalTaxes'] += $this->orderProductPriceResolver->getTotalTaxes( | |||
$orderProduct | |||
) / $this->getReductionsCoef($orderShop); | |||
} | |||
return $orderProductsTaxes; | |||
} | |||
private function getReductionsCoef(OrderShopInterface $orderShop): float | |||
{ | |||
return $this->getTotalOrderProducts($orderShop) / $this->getTotalOrderProductsWithReductions($orderShop); | |||
} | |||
private function getTaxRateAverage(OrderShopInterface $orderShop): float | |||
{ | |||
return $this->getTotalOrderProductsWithTax($orderShop) / $this->getTotalOrderProducts($orderShop); | |||
} | |||
public function getTotalOrderProductsWithReductions(OrderShopInterface $orderShop, $cache = false) | |||
{ | |||
if ($cache && $orderShop->getStatTotalOrderProductsWithReductions() !== null) { | |||
return $orderShop->getStatTotalOrderProductsWithReductions(); | |||
} else { | |||
$total = $this->getTotalOrderProducts($orderShop); | |||
$total -= $this->getTotalReductionCartsAmount($orderShop); | |||
$total -= $this->getTotalReductionCreditsAmount($orderShop); | |||
return $total; | |||
} | |||
} | |||
public function getTotalOrderProductsWithReductionCarts(OrderShopInterface $orderShop) | |||
{ | |||
$total = $this->getTotalOrderProducts($orderShop); | |||
$total -= $this->getTotalReductionCartsAmount($orderShop); | |||
return $total; | |||
} | |||
public function getTotalReductionCartsAmount(OrderShopInterface $orderShop) | |||
{ | |||
$totalReductionAmount = 0; | |||
foreach ($orderShop->getOrderReductionCarts() as $orderReductionCart) { | |||
$totalReductionAmount += $this->getOrderProductsReductionCartAmountWithoutTax( | |||
$orderShop, | |||
$orderReductionCart | |||
); | |||
} | |||
return $totalReductionAmount; | |||
} | |||
public function getTotalReductionCreditsAmount(OrderShopInterface $orderShop) | |||
{ | |||
$totalReductionAmount = 0; | |||
foreach ($orderShop->getOrderReductionCredits() as $orderReductionCredit) { | |||
$totalReductionAmount += $this->getOrderProductsReductionCreditAmountWithoutTax( | |||
$orderShop, | |||
$orderReductionCredit | |||
); | |||
} | |||
return $totalReductionAmount; | |||
} | |||
public function getTotalOrderProductsWithTaxAndReductions(OrderShopInterface $orderShop, $cache = false) | |||
{ | |||
if ($cache && $orderShop->getStatTotalOrderProductsWithTaxAndReductions() !== null) { | |||
return $orderShop->getStatTotalOrderProductsWithTaxAndReductions(); | |||
} else { | |||
$total = $this->getTotalOrderProductsWithTax($orderShop); | |||
$total -= $this->getTotalReductionCartsAmountWithTax($orderShop); | |||
$total -= $this->getTotalReductionCreditsAmountWithTax($orderShop); | |||
return $total; | |||
} | |||
} | |||
public function getTotalOrderProductsWithTaxAndReductionCarts(OrderShopInterface $orderShop) | |||
{ | |||
$total = $this->getTotalOrderProductsWithTax($orderShop); | |||
$total -= $this->getTotalReductionCartsAmountWithTax($orderShop); | |||
return $total; | |||
} | |||
public function getTotalReductionCartsAmountWithTax(OrderShopInterface $orderShop) | |||
{ | |||
$totalReductionAmount = 0; | |||
foreach ($orderShop->getOrderReductionCarts() as $orderReductionCart) { | |||
$totalReductionAmount += $this->getOrderProductsReductionCartAmountWithTax($orderShop, $orderReductionCart); | |||
} | |||
return $totalReductionAmount; | |||
} | |||
public function getTotalReductionCreditsAmountWithTax(OrderShopInterface $orderShop) | |||
{ | |||
$totalReductionAmount = 0; | |||
foreach ($orderShop->getOrderReductionCredits() as $orderReductionCredit) { | |||
$totalReductionAmount += $this->getOrderProductsReductionCreditAmountWithTax( | |||
$orderShop, | |||
$orderReductionCredit | |||
); | |||
} | |||
return $totalReductionAmount; | |||
} | |||
public function getOrderProductsReductionCartAmountWithoutTax(OrderShopInterface $order, $orderReductionCart) | |||
{ | |||
$amount = 0; | |||
if ($orderReductionCart->getAppliedTo() === ReductionCartModel::APPLIED_TO_ORDER_PRODUCTS) { | |||
if ($orderReductionCart->getUnit() == 'percent') { | |||
$amount = $this->amountReductionByPercentValue( | |||
$this->getTotalOrderProducts($order), | |||
$orderReductionCart->getValue() | |||
); | |||
} else { | |||
if ($orderReductionCart->getUnit() == 'amount') { | |||
if ($orderReductionCart->getBehaviorTaxRate() == 'tax-excluded') { | |||
$amount = $orderReductionCart->getValue(); | |||
} else { | |||
if ($orderReductionCart->getBehaviorTaxRate() == 'tax-included') { | |||
$amount = $this->round($orderReductionCart->getValue() / $this->getTaxRateAverage($order)); | |||
} | |||
} | |||
} | |||
} | |||
} | |||
return $amount; | |||
} | |||
public function getOrderProductsReductionCartAmountWithTax(OrderShopInterface $order, $orderReductionCart) | |||
{ | |||
$amount = 0; | |||
if ($orderReductionCart->getAppliedTo() === ReductionCartModel::APPLIED_TO_ORDER_PRODUCTS) { | |||
if ($orderReductionCart->getUnit() == 'percent') { | |||
$amount = $this->amountReductionByPercentValue( | |||
$this->getTotalOrderProductsWithTax($order), | |||
$orderReductionCart->getValue() | |||
); | |||
} elseif ($orderReductionCart->getUnit() == 'amount') { | |||
if ($orderReductionCart->getBehaviorTaxRate() == 'tax-excluded') { | |||
$amount = $this->round($orderReductionCart->getValue() * $this->getTaxRateAverage($order)); | |||
} elseif ($orderReductionCart->getBehaviorTaxRate() == 'tax-included') { | |||
$amount = $orderReductionCart->getValue(); | |||
} | |||
} | |||
} | |||
return $amount; | |||
} | |||
public function getOrderProductsReductionCreditAmountWithoutTax( | |||
OrderShopInterface $order, | |||
OrderReductionCreditInterface $orderReductionCredit | |||
) { | |||
$amount = 0; | |||
if ($orderReductionCredit->getBehaviorTaxRate() == 'tax-excluded') { | |||
$amount = $orderReductionCredit->getValue(); | |||
} else { | |||
if ($orderReductionCredit->getBehaviorTaxRate() == 'tax-included') { | |||
$amount = $this->round($orderReductionCredit->getValue() / $this->getTaxRateAverage($order)); | |||
} | |||
} | |||
return $amount; | |||
} | |||
public function getOrderProductsReductionCreditAmountWithTax( | |||
OrderShopInterface $order, | |||
OrderReductionCreditInterface $orderReductionCredit | |||
) { | |||
$amountWithTax = 0; | |||
if ($orderReductionCredit->getBehaviorTaxRate() == 'tax-excluded') { | |||
$amountWithTax = $this->round($orderReductionCredit->getValue() * $this->getTaxRateAverage($order)); | |||
} elseif ($orderReductionCredit->getBehaviorTaxRate() == 'tax-included') { | |||
$amountWithTax = $orderReductionCredit->getValue(); | |||
} | |||
return $amountWithTax; | |||
} | |||
public function getTotalReductions(OrderShopInterface $orderShop) | |||
{ | |||
$total = 0; | |||
foreach ($orderShop->getOrderReductionCarts() as $orderReductionCart) { | |||
$total += $this->getOrderProductsReductionCartAmountWithoutTax($orderShop, $orderReductionCart); | |||
} | |||
foreach ($orderShop->getOrderReductionCredits() as $orderReductionCredit) { | |||
$total += $this->getOrderProductsReductionCreditAmountWithoutTax($orderShop, $orderReductionCredit); | |||
} | |||
return $total; | |||
} | |||
public function getTotalReductionsWithTax(OrderShopInterface $orderShop) | |||
{ | |||
$total = 0; | |||
foreach ($orderShop->getOrderReductionCarts() as $orderReductionCart) { | |||
$total += $this->getOrderProductsReductionCartAmountWithTax($orderShop, $orderReductionCart); | |||
} | |||
foreach ($orderShop->getOrderReductionCredits() as $orderReductionCredit) { | |||
$total += $this->getOrderProductsReductionCreditAmountWithTax($orderShop, $orderReductionCredit); | |||
} | |||
return $total; | |||
} | |||
} | |||
@@ -0,0 +1,68 @@ | |||
<?php | |||
namespace Lc\CaracoleBundle\Resolver\Price; | |||
use Lc\CaracoleBundle\Doctrine\Extension\ProductPropertyInterface; | |||
use Lc\CaracoleBundle\Model\Order\OrderProductInterface; | |||
use Lc\CaracoleBundle\Model\Order\OrderShopInterface; | |||
class PriceResolver | |||
{ | |||
protected ProductPriceResolver $productPriceResolver; | |||
protected OrderProductPriceResolver $orderProductPriceResolver; | |||
protected OrderShopPriceResolver $orderShopPriceResolver; | |||
public function __construct( | |||
ProductPriceResolver $productPriceResolver, | |||
OrderProductPriceResolver $orderProductPriceResolver, | |||
OrderShopPriceResolver $orderShopPriceResolver | |||
) { | |||
$this->productPriceResolver = $productPriceResolver; | |||
$this->orderProductPriceResolver = $orderProductPriceResolver; | |||
$this->orderShopPriceResolver = $orderShopPriceResolver; | |||
} | |||
public function __call($name, $arguments) | |||
{ | |||
if (strpos($name, 'apply') === false) { | |||
$entity = $arguments[0]; | |||
$service = ''; | |||
if ($entity instanceof ProductPropertyInterface) { | |||
$service = 'productPriceResolver'; | |||
} | |||
if ($entity instanceof OrderProductInterface) { | |||
$service = 'orderProductPriceResolver'; | |||
} | |||
if ($entity instanceof OrderShopInterface || is_iterable($entity) || is_array($entity)) { | |||
$service = 'orderShopPriceResolver'; | |||
} | |||
if (strlen($service) && $entity && method_exists($this->$service, $name)) { | |||
if (isset($arguments[1]) && isset($arguments[2]) && isset($arguments[3])) { | |||
return $this->$service->$name($entity, $arguments[1], $arguments[2], $arguments[3]); | |||
} elseif (isset($arguments[1]) && isset($arguments[2])) { | |||
return $this->$service->$name($entity, $arguments[1], $arguments[2]); | |||
} elseif (isset($arguments[1])) { | |||
return $this->$service->$name($entity, $arguments[1]); | |||
} else { | |||
return $this->$service->$name($entity); | |||
} | |||
} else { | |||
if (!strlen($service)) { | |||
throw new \ErrorException("PriceResolver : le type d'entité n'est pas géré"); | |||
} else { | |||
if (!method_exists($this->$service, $name)) { | |||
throw new \ErrorException( | |||
"PriceResolver : la méthode " . $name . " du service " . $service . " n'existe pas." | |||
); | |||
} | |||
} | |||
} | |||
return false; | |||
} | |||
} | |||
} |
@@ -0,0 +1,115 @@ | |||
<?php | |||
namespace Lc\CaracoleBundle\Resolver\Price; | |||
use Lc\CaracoleBundle\Doctrine\Extension\ProductPropertyInterface; | |||
use Lc\CaracoleBundle\Model\Order\OrderProductInterface; | |||
trait PriceResolverTrait | |||
{ | |||
public function applyTax($price, $taxRateValue) | |||
{ | |||
return $this->round($this->applyPercent($price, $taxRateValue)); | |||
} | |||
public function applyReductionPercent($price, $percentage) | |||
{ | |||
return $this->applyPercent($price, -$percentage); | |||
} | |||
public function applyReductionAmount($price, $amount) | |||
{ | |||
return $price - $amount; | |||
} | |||
public function applyPercent($price, $percentage) | |||
{ | |||
return $price * ($percentage / 100 + 1); | |||
} | |||
public function applyPercentNegative($price, $percentage) | |||
{ | |||
return $price / ($percentage / 100 + 1); | |||
} | |||
public function round($price) | |||
{ | |||
return round((($price * 100)) / 100, 2); | |||
} | |||
public function amountReductionByPercentValue($price, $percent) | |||
{ | |||
return round((($price * $percent)) / 100, 2); | |||
} | |||
public function applyReductionCatalog( | |||
$entity, | |||
$price, | |||
$priceWithTax, | |||
$quantity = 1, | |||
$reductionCatalog = null, | |||
$withTax = true, | |||
$round = true | |||
): ?float { | |||
if ($reductionCatalog) { | |||
$reductionCatalogValue = $reductionCatalog->getValue(); | |||
$reductionCatalogUnit = $reductionCatalog->getUnit(); | |||
$reductionCatalogBehaviorTaxRate = $reductionCatalog->getBehaviorTaxRate(); | |||
} else { | |||
if ($entity instanceof ProductPropertyInterface) { | |||
$reductionCatalog = $entity->getReductionCatalogInherited(); | |||
if ($reductionCatalog) { | |||
$reductionCatalogValue = $reductionCatalog->getValue(); | |||
$reductionCatalogUnit = $reductionCatalog->getUnit(); | |||
$reductionCatalogBehaviorTaxRate = $reductionCatalog->getBehaviorTaxRate(); | |||
} | |||
} | |||
if ($entity instanceof OrderProductInterface) { | |||
$orderProductReductionCatalog = $entity->getOrderProductReductionCatalog(); | |||
if ($orderProductReductionCatalog) { | |||
$reductionCatalogValue = $orderProductReductionCatalog->getValue(); | |||
$reductionCatalogUnit = $orderProductReductionCatalog->getUnit(); | |||
$reductionCatalogBehaviorTaxRate = $orderProductReductionCatalog->getBehaviorTaxRate(); | |||
} | |||
} | |||
} | |||
if (isset($reductionCatalogValue) && isset($reductionCatalogUnit) && isset($reductionCatalogBehaviorTaxRate)) { | |||
if ($reductionCatalogUnit == 'percent') { | |||
$priceWithTax = $this->applyReductionPercent( | |||
$priceWithTax, | |||
$reductionCatalogValue | |||
); | |||
} elseif ($reductionCatalogUnit == 'amount') { | |||
if ($reductionCatalogBehaviorTaxRate == 'tax-excluded') { | |||
$priceWithTax = $this->applyTax( | |||
$this->applyReductionAmount( | |||
$price, | |||
$reductionCatalogValue * $quantity | |||
), | |||
$entity->getTaxRateInherited()->getValue() | |||
); | |||
} elseif ($reductionCatalogBehaviorTaxRate == 'tax-included') { | |||
$priceWithTax = $this->applyReductionAmount( | |||
$priceWithTax, | |||
$reductionCatalogValue * $quantity | |||
); | |||
} | |||
} | |||
} | |||
if ($withTax) { | |||
$priceReturn = $priceWithTax; | |||
} else { | |||
$priceReturn = $this->applyPercentNegative($priceWithTax, $entity->getTaxRateInherited()->getValue()); | |||
} | |||
if ($round) { | |||
return $this->round($priceReturn); | |||
} else { | |||
return $priceReturn; | |||
} | |||
} | |||
} |
@@ -0,0 +1,110 @@ | |||
<?php | |||
namespace Lc\CaracoleBundle\Resolver\Price; | |||
use Lc\CaracoleBundle\Doctrine\Extension\ProductPropertyInterface; | |||
class ProductPriceResolver | |||
{ | |||
use PriceResolverTrait; | |||
public function getPrice(ProductPropertyInterface $product) | |||
{ | |||
if ($product->getBehaviorPriceInherited() == 'by-piece') { | |||
return $product->getPriceInherited(); | |||
} elseif ($product->getBehaviorPriceInherited() == 'by-reference-unit') { | |||
if ($product->getQuantityInherited() > 0) { | |||
return $product->getPriceByRefUnitInherited() * ($product->getQuantityInherited( | |||
) / $product->getUnitInherited()->getCoefficient()); | |||
} else { | |||
return 0; | |||
} | |||
} | |||
} | |||
public function getPriceWithTax(ProductPropertyInterface $product) | |||
{ | |||
return $this->applyTax( | |||
$this->getPrice($product), | |||
$product->getTaxRateInherited()->getValue() | |||
); | |||
} | |||
public function getPriceByRefUnit(ProductPropertyInterface $product) | |||
{ | |||
if ($product->getBehaviorPriceInherited() == 'by-piece') { | |||
return ($this->getPrice($product) * $product->getUnitInherited()->getCoefficient( | |||
)) / $product->getQuantityInherited(); | |||
} elseif ($product->getBehaviorPriceInherited() == 'by-reference-unit') { | |||
return $product->getPriceByRefUnitInherited(); | |||
} | |||
} | |||
public function getPriceByRefUnitWithTax(ProductPropertyInterface $product) | |||
{ | |||
return $this->applyTax( | |||
$this->getPriceByRefUnit($product), | |||
$product->getTaxRateInherited()->getValue() | |||
); | |||
} | |||
public function getPriceWithTaxAndReduction(ProductPropertyInterface $product) | |||
{ | |||
return $this->applyReductionCatalog( | |||
$product, | |||
$this->getPrice($product), | |||
$this->getPriceWithTax($product) | |||
); | |||
} | |||
public function getPriceByRefUnitWithTaxAndReduction(ProductPropertyInterface $product) | |||
{ | |||
return ($this->getPriceByRefUnitWithTax($product) * $this->getPriceWithTaxAndReduction($product)) | |||
/ $this->getPriceWithTax($product); | |||
} | |||
public function getBuyingPrice(ProductPropertyInterface $product) | |||
{ | |||
if ($product->getBehaviorPriceInherited() == 'by-piece') { | |||
return $product->getBuyingPriceInherited(); | |||
} elseif ($product->getBehaviorPriceInherited() == 'by-reference-unit') { | |||
if ($product->getQuantityInherited() > 0) { | |||
return $product->getBuyingPriceByRefUnitInherited() * ($product->getQuantityInherited( | |||
) / $product->getUnitInherited()->getCoefficient()); | |||
} else { | |||
return 0; | |||
} | |||
} | |||
} | |||
public function getBuyingPriceWithTax(ProductPropertyInterface $product) | |||
{ | |||
return $this->applyTax( | |||
$this->getBuyingPrice($product), | |||
$product->getTaxRateInherited()->getValue() | |||
); | |||
} | |||
public function getBuyingPriceByRefUnit(ProductPropertyInterface $product) | |||
{ | |||
return $product->getBuyingPriceByRefUnitInherited(); | |||
} | |||
public function getBuyingPriceByRefUnitWithTax(ProductPropertyInterface $product) | |||
{ | |||
return $this->applyTax( | |||
$this->getBuyingPriceByRefUnit($product), | |||
$product->getTaxRateInherited()->getValue() | |||
); | |||
} | |||
public function getMultiplyingFactor(ProductPropertyInterface $product) | |||
{ | |||
return $this->round($this->getPriceWithTax($product) / $this->getBuyingPrice($product)); | |||
} | |||
} | |||