<?php
declare(strict_types=1);
namespace CioFormBuilder\Subscriber;
use Psr\Log\LoggerInterface;
use Shopware\Core\Checkout\Cart\Event\CartProcessedEvent;
use Shopware\Core\Checkout\Cart\LineItem\LineItem;
use Shopware\Core\Checkout\Cart\Price\QuantityPriceCalculator;
use Shopware\Core\Checkout\Cart\Price\Struct\QuantityPriceDefinition;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class PodSurchargeCartProcessedSubscriber implements EventSubscriberInterface
{
private QuantityPriceCalculator $calculator;
private LoggerInterface $logger;
public function __construct(
QuantityPriceCalculator $calculator,
LoggerInterface $logger
) {
$this->calculator = $calculator;
$this->logger = $logger;
$this->logger->info('[CIO-AI-Driven] PodSurchargeCartProcessedSubscriber.construct');
}
public static function getSubscribedEvents(): array
{
return [
CartProcessedEvent::class => 'onCartProcessed',
];
}
public function onCartProcessed(CartProcessedEvent $event): void
{
$cart = $event->getCart();
$this->logger->info('[CIO-AI-Driven] PodSurchargeCartProcessedSubscriber.start', [
'cartToken' => $cart->getToken(),
'lineItemCount' => $cart->getLineItems()->count(),
'ids' => $cart->getLineItems()->getKeys(),
]);
foreach ($cart->getLineItems() as $lineItem) {
if (!$lineItem instanceof LineItem) {
continue;
}
if ($lineItem->getType() !== LineItem::PRODUCT_LINE_ITEM_TYPE) {
continue;
}
$payload = $lineItem->getPayload() ?? [];
$cf = $payload['customFields'] ?? [];
$isPod = $cf['custom_pod_products_isPodProduct'] ?? null;
$surcharges = $cf['cioFormSurcharges'] ?? [];
$formData = $cf['cioFormData'] ?? [];
$tableData = $cf['cioTableFormData'] ?? [];
if ($isPod !== true || empty($surcharges)) {
continue;
}
if (is_array($tableData)) {
foreach ($tableData as $row) {
if (is_array($row)) {
foreach ($row as $field) {
$formData[] = $field;
}
}
}
}
$matched = [];
$positionSurcharge = 0.0;
$perUnitSurcharge = 0.0;
$surchargeMap = [];
foreach ($surcharges as $s) {
if (!empty($s['id'])) {
$surchargeMap[$s['id']] = $s;
}
}
foreach ($formData as $fieldData) {
$fieldId = $fieldData['id'] ?? null;
if (!$fieldId || !isset($surchargeMap[$fieldId])) {
continue;
}
$cfg = $surchargeMap[$fieldId];
$amount = (float)($cfg['amount'] ?? 0.0);
if ($amount <= 0) {
continue;
}
$mode = $cfg['mode'] ?? 'position';
$value = $fieldData['value'] ?? null;
$type = $fieldData['type'] ?? '';
$hasValue = false;
if (in_array($type, ['text', 'multiline_text', 'date'], true)) {
$hasValue = is_string($value) && trim($value) !== '';
} elseif ($type === 'select') {
$hasValue = is_string($value) && $value !== '';
} elseif ($type === 'checkbox') {
$hasValue = (bool)$value;
}
if (!$hasValue) {
continue;
}
$matched[] = [
'id' => $fieldId,
'type' => $type,
'mode' => $mode,
'amount' => $amount,
'value' => $value,
];
if ($mode === 'per_unit') {
$perUnitSurcharge += $amount;
} else {
$positionSurcharge += $amount;
}
}
if (empty($matched)) {
continue;
}
$price = $lineItem->getPrice();
if ($price === null) {
continue;
}
$quantity = max(1, $lineItem->getQuantity());
$unitPrice = $price->getUnitPrice();
$perUnitPosition = $positionSurcharge > 0 ? ($positionSurcharge / $quantity) : 0.0;
$unitWith = $unitPrice + $perUnitSurcharge + $perUnitPosition;
$definition = new QuantityPriceDefinition(
$unitWith,
$price->getTaxRules(),
$quantity,
$price->getReferencePrice(),
$price->getListPrice(),
$price->getRegulationPrice()
);
$calculated = $this->calculator->calculate($definition, $event->getSalesChannelContext());
$lineItem->setPriceDefinition($definition);
$lineItem->setPrice($calculated);
$this->logger->info('[CIO-AI-Driven] PodSurchargeCartProcessedSubscriber.apply', [
'lineItemId' => $lineItem->getId(),
'referencedId' => $lineItem->getReferencedId(),
'quantity' => $quantity,
'baseUnitPrice' => $unitPrice,
'positionSurcharge' => $positionSurcharge,
'perUnitSurcharge' => $perUnitSurcharge,
'perUnitPositionPart' => $perUnitPosition,
'unitPriceWithSurcharge' => $unitWith,
'totalPrice' => $calculated->getTotalPrice(),
'matchedFields' => $matched,
]);
}
}
}