Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 89 additions & 11 deletions backend/app/Services/Domain/Order/OrderItemProcessingService.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,20 @@

namespace HiEvents\Services\Domain\Order;

use HiEvents\DomainObjects\AccountConfigurationDomainObject;
use HiEvents\DomainObjects\Enums\TaxCalculationType;
use HiEvents\DomainObjects\EventDomainObject;
use HiEvents\DomainObjects\EventSettingDomainObject;
use HiEvents\DomainObjects\Generated\ProductDomainObjectAbstract;
use HiEvents\DomainObjects\OrderDomainObject;
use HiEvents\DomainObjects\ProductDomainObject;
use HiEvents\DomainObjects\ProductPriceDomainObject;
use HiEvents\DomainObjects\PromoCodeDomainObject;
use HiEvents\DomainObjects\TaxAndFeesDomainObject;
use HiEvents\Helper\Currency;
use HiEvents\Repository\Eloquent\Value\Relationship;
use HiEvents\Repository\Interfaces\AccountRepositoryInterface;
use HiEvents\Repository\Interfaces\EventRepositoryInterface;
use HiEvents\Repository\Interfaces\OrderRepositoryInterface;
use HiEvents\Repository\Interfaces\ProductRepositoryInterface;
use HiEvents\Services\Application\Handlers\Order\DTO\ProductOrderDetailsDTO;
Expand All @@ -21,11 +27,17 @@

class OrderItemProcessingService
{
private ?AccountConfigurationDomainObject $accountConfiguration = null;
private ?EventSettingDomainObject $eventSettings = null;

public function __construct(
private readonly OrderRepositoryInterface $orderRepository,
private readonly ProductRepositoryInterface $productRepository,
private readonly TaxAndFeeCalculationService $taxCalculationService,
private readonly ProductPriceService $productPriceService,
private readonly OrderRepositoryInterface $orderRepository,
private readonly ProductRepositoryInterface $productRepository,
private readonly TaxAndFeeCalculationService $taxCalculationService,
private readonly ProductPriceService $productPriceService,
private readonly OrderPlatformFeePassThroughService $platformFeeService,
private readonly AccountRepositoryInterface $accountRepository,
private readonly EventRepositoryInterface $eventRepository,
)
{
}
Expand All @@ -44,6 +56,8 @@ public function process(
?PromoCodeDomainObject $promoCode
): Collection
{
$this->loadPlatformFeeConfiguration($event->getId());

$orderItems = collect();

foreach ($productsOrderDetails as $productOrderDetail) {
Expand All @@ -61,23 +75,42 @@ public function process(
);
}

$productOrderDetail->quantities->each(function (OrderProductPriceDTO $productPrice) use ($promoCode, $order, $orderItems, $product) {
$productOrderDetail->quantities->each(function (OrderProductPriceDTO $productPrice) use ($promoCode, $order, $orderItems, $product, $event) {
if ($productPrice->quantity === 0) {
return;
}
$orderItemData = $this->calculateOrderItemData($product, $productPrice, $order, $promoCode);
$orderItemData = $this->calculateOrderItemData($product, $productPrice, $order, $promoCode, $event->getCurrency());
$orderItems->push($this->orderRepository->addOrderItem($orderItemData));
});
}

return $orderItems;
}

private function loadPlatformFeeConfiguration(int $eventId): void
{
$account = $this->accountRepository
->loadRelation(new Relationship(
domainObject: AccountConfigurationDomainObject::class,
name: 'configuration',
))
->findByEventId($eventId);

$this->accountConfiguration = $account->getConfiguration();

$event = $this->eventRepository
->loadRelation(EventSettingDomainObject::class)
->findById($eventId);

$this->eventSettings = $event->getEventSettings();
}

private function calculateOrderItemData(
ProductDomainObject $product,
OrderProductPriceDTO $productPriceDetails,
OrderDomainObject $order,
?PromoCodeDomainObject $promoCode
?PromoCodeDomainObject $promoCode,
string $currency
): array
{
$prices = $this->productPriceService->getPrice($product, $productPriceDetails, $promoCode);
Expand All @@ -92,6 +125,23 @@ private function calculateOrderItemData(
quantity: $productPriceDetails->quantity
);

$totalTax = $taxesAndFees->taxTotal;
$totalFee = $taxesAndFees->feeTotal;
$rollUp = $taxesAndFees->rollUp;

$platformFee = $this->calculatePlatformFee(
$itemTotalWithDiscount + $taxesAndFees->feeTotal + $taxesAndFees->taxTotal,
$productPriceDetails->quantity,
$currency
);

if ($platformFee > 0) {
$totalFee += $platformFee;
$rollUp = $this->addPlatformFeeToRollup($rollUp, $platformFee);
}

$totalGross = Currency::round($itemTotalWithDiscount + $totalTax + $totalFee);

return [
'product_type' => $product->getProductType(),
'product_id' => $product->getId(),
Expand All @@ -102,13 +152,41 @@ private function calculateOrderItemData(
'price' => $priceWithDiscount,
'order_id' => $order->getId(),
'item_name' => $this->getOrderItemLabel($product, $productPriceDetails->price_id),
'total_tax' => $taxesAndFees->taxTotal,
'total_service_fee' => $taxesAndFees->feeTotal,
'total_gross' => Currency::round($itemTotalWithDiscount + $taxesAndFees->taxTotal + $taxesAndFees->feeTotal),
'taxes_and_fees_rollup' => $taxesAndFees->rollUp,
'total_tax' => $totalTax,
'total_service_fee' => $totalFee,
'total_gross' => $totalGross,
'taxes_and_fees_rollup' => $rollUp,
];
}

private function calculatePlatformFee(float $total, int $quantity, string $currency): float
{
if ($this->accountConfiguration === null || $this->eventSettings === null) {
return 0.0;
}

return $this->platformFeeService->calculatePlatformFee(
$this->accountConfiguration,
$this->eventSettings,
$total,
$quantity,
$currency,
);
}

private function addPlatformFeeToRollup(array $rollUp, float $platformFee): array
{
$rollUp['fees'] ??= [];
$rollUp['fees'][] = [
'name' => OrderPlatformFeePassThroughService::getPlatformFeeName(),
'rate' => $platformFee,
'type' => TaxCalculationType::FIXED->name,
'value' => $platformFee,
];

return $rollUp;
}

private function getOrderItemLabel(ProductDomainObject $product, int $priceId): string
{
if ($product->isTieredType()) {
Expand Down
65 changes: 5 additions & 60 deletions backend/app/Services/Domain/Order/OrderManagementService.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,23 @@
namespace HiEvents\Services\Domain\Order;

use Carbon\Carbon;
use HiEvents\DomainObjects\AccountConfigurationDomainObject;
use HiEvents\DomainObjects\AffiliateDomainObject;
use HiEvents\DomainObjects\Enums\TaxCalculationType;
use HiEvents\DomainObjects\EventDomainObject;
use HiEvents\DomainObjects\EventSettingDomainObject;
use HiEvents\DomainObjects\Generated\OrderDomainObjectAbstract;
use HiEvents\DomainObjects\OrderDomainObject;
use HiEvents\DomainObjects\OrderItemDomainObject;
use HiEvents\DomainObjects\PromoCodeDomainObject;
use HiEvents\DomainObjects\Status\OrderStatus;
use HiEvents\Helper\IdHelper;
use HiEvents\Repository\Eloquent\Value\Relationship;
use HiEvents\Repository\Interfaces\AccountRepositoryInterface;
use HiEvents\Repository\Interfaces\EventRepositoryInterface;
use HiEvents\Repository\Interfaces\OrderRepositoryInterface;
use HiEvents\Services\Domain\Tax\TaxAndFeeOrderRollupService;
use Illuminate\Support\Collection;

class OrderManagementService
{
public function __construct(
readonly private OrderRepositoryInterface $orderRepository,
readonly private TaxAndFeeOrderRollupService $taxAndFeeOrderRollupService,
readonly private OrderPlatformFeePassThroughService $platformFeeService,
readonly private AccountRepositoryInterface $accountRepository,
readonly private EventRepositoryInterface $eventRepository,
readonly private OrderRepositoryInterface $orderRepository,
readonly private TaxAndFeeOrderRollupService $taxAndFeeOrderRollupService,
)
{
}
Expand Down Expand Up @@ -70,6 +61,9 @@ public function createNewOrder(
}

/**
* Update order totals by summing up all order items.
* Platform fee and its tax are included at the item level.
*
* @param OrderDomainObject $order
* @param Collection<OrderItemDomainObject> $orderItems
* @return OrderDomainObject
Expand All @@ -90,21 +84,6 @@ public function updateOrderTotals(OrderDomainObject $order, Collection $orderIte

$rollup = $this->taxAndFeeOrderRollupService->rollup($orderItems);

$platformFee = $order->getIsManuallyCreated()
? 0.0
: $this->calculatePlatformFee($order->getEventId(), $orderItems, $order->getCurrency());

if ($platformFee > 0) {
$rollup['fees'][] = [
'name' => OrderPlatformFeePassThroughService::getPlatformFeeName(),
'rate' => $platformFee,
'type' => TaxCalculationType::FIXED->name,
'value' => $platformFee,
];
$totalFee += $platformFee;
$totalGross += $platformFee;
}

$this->orderRepository->updateFromArray($order->getId(), [
'total_before_additions' => $totalBeforeAdditions,
'total_tax' => $totalTax,
Expand All @@ -117,38 +96,4 @@ public function updateOrderTotals(OrderDomainObject $order, Collection $orderIte
->loadRelation(OrderItemDomainObject::class)
->findById($order->getId());
}

/**
* @param Collection<OrderItemDomainObject> $orderItems
*/
private function calculatePlatformFee(int $eventId, Collection $orderItems, string $currency): float
{
$account = $this->accountRepository
->loadRelation(new Relationship(
domainObject: AccountConfigurationDomainObject::class,
name: 'configuration',
))
->findByEventId($eventId);

$accountConfiguration = $account->getConfiguration();
if ($accountConfiguration === null) {
return 0.0;
}

$event = $this->eventRepository
->loadRelation(EventSettingDomainObject::class)
->findById($eventId);

$eventSettings = $event->getEventSettings();
if ($eventSettings === null) {
return 0.0;
}

return $this->platformFeeService->calculateForOrder(
accountConfiguration: $accountConfiguration,
eventSettings: $eventSettings,
orderItems: $orderItems,
currency: $currency,
);
}
}
Loading
Loading