<?php
namespace MbPayerAddress\Subscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Doctrine\DBAL\Connection;
use MbPayerAddress\Entity\OrderPayerAddressEntity;
use MojeBambino\Extensions\Struct\Kafelki;
use Shopware\Core\Checkout\Cart\Event\CheckoutOrderPlacedEvent;
use Shopware\Core\Checkout\Customer\Aggregate\CustomerAddress\CustomerAddressEntity;
use Shopware\Core\Checkout\Order\Aggregate\OrderDelivery\OrderDeliveryEntity;
use Shopware\Core\Checkout\Order\OrderEntity;
use Shopware\Core\Checkout\Order\OrderEvents;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityLoadedEvent;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenEvent;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsAnyFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\Struct\ArrayEntity;
use Shopware\Core\Framework\Struct\ArrayStruct;
use Shopware\Core\Framework\Uuid\Uuid;
use Shopware\Storefront\Page\Account\Overview\AccountOverviewPageLoadedEvent;
use Shopware\Storefront\Page\Address\Listing\AddressListingPageLoadedEvent;
use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent;
use Shopware\Storefront\Page\Checkout\Finish\CheckoutFinishPageLoadedEvent;
class OrderPayerAddressSubscriber implements EventSubscriberInterface {
private EntityRepository $customerAddressRespository;
private EntityRepository $orderPayerAddressRespository;
private EntityRepository $customerRespository;
public function __construct(
EntityRepository $customerAddressRespository,
EntityRepository $orderPayerAddressRespository,
EntityRepository $customerRespository,
){
$this->customerAddressRespository = $customerAddressRespository;
$this->orderPayerAddressRespository = $orderPayerAddressRespository;
$this->customerRespository = $customerRespository;
}
public static function getSubscribedEvents(): array{
return [
CheckoutOrderPlacedEvent::class => 'onCheckoutOrderPlacedEvent',
OrderEvents::ORDER_LOADED_EVENT => 'onOrderLoaded',
];
}
public function onCheckoutOrderPlacedEvent(CheckoutOrderPlacedEvent $event) {
$orderId = $event->getOrder()->getId();
$customer = $event->getOrder()->getOrderCustomer()->getCustomer();
$customFields = $customer->getCustomFields();
$billingId = $customer->getDefaultBillingAddressId();
$shippingId = $customer->getDefaultShippingAddressId();
$addressId = $customFields['payerAddressId'] ?? $billingId;
$type = 'other';
$id = Uuid::randomHex();
$customFields = $this->getShippingAndBilling($event->getOrder());
if($addressId == $billingId) {
$type = 'billing';
$id = $customFields['currentBillingOrderAddressId'];
} else if($addressId == $shippingId) {
$type = 'shipping';
$id = $customFields['currentShippingOrderAddressId'];
}
$payerAddressEntity = $this->customerAddressRespository
->search(new Criteria([$addressId]), $event->getContext())
->first();
$this->createOrderPayerAddress($orderId, $payerAddressEntity, $type, $id, $event->getContext());
}
private function getShippingAndBilling($order) {
$customFieldsArr['currentBillingOrderAddressId'] = $order->getBillingAddressId();
if(!$order->getDeliveries()) return [];
$activeDelivery = $order->getDeliveries()->getAt(0);
/** @var OrderDeliveryEntity $delivery */
foreach($order->getDeliveries() as $delivery) {
if($delivery->getShippingCosts()->getUnitPrice() > $activeDelivery->getShippingCosts()->getUnitPrice()) {
$activeDelivery = $delivery;
}
}
$customFieldsArr['currentShippingOrderAddressId']= $delivery->getShippingOrderAddressId();
return $customFieldsArr;
}
private function createOrderPayerAddress(string $orderId, $payerAddressEntity, string $type, string $id, $context)
{
$this->orderPayerAddressRespository->create([
[
'id' => $id,
'orderId' => $orderId,
'company' => $payerAddressEntity->getCompany(),
'vatId' => $payerAddressEntity->getCustomFields()['address_NIP'] ?? '',
'firstName' => $payerAddressEntity->getFirstName(),
'lastName' => $payerAddressEntity->getLastName(),
'street' => $payerAddressEntity->getStreet(),
'zipcode' => $payerAddressEntity->getZipcode(),
'city' => $payerAddressEntity->getCity(),
'phoneNumber' => $payerAddressEntity->getPhoneNumber(),
'additionalAddressLine1' => $payerAddressEntity->getAdditionalAddressLine1(),
'additionalAddressLine2' => $payerAddressEntity->getAdditionalAddressLine2(),
'equalTo' => $type,
'customFields' => $payerAddressEntity->getCustomFields()
]
], $context);
}
public function onOrderLoaded(EntityLoadedEvent $event)
{
$orderIds = [];
foreach ($event->getEntities() as $orderEntity) {
$orderIds[] = $orderEntity->getId();
}
$criteria = new Criteria();
$criteria->addFilter(new EqualsAnyFilter('orderId', $orderIds));
$payerAddressSearchResult = $this->orderPayerAddressRespository
->search($criteria, $event->getContext());
/** @var OrderEntity $orderEntity */
foreach ($event->getEntities() as $orderEntity) {
/** @var OrderPayerAddressEntity $payerAddress */
$payerAddress = $payerAddressSearchResult->filter(function (OrderPayerAddressEntity $orderPayerAddressEntity) use ($orderEntity) {
return $orderPayerAddressEntity->getOrderId() == $orderEntity->getId();
})->first();
$orderEntity->addExtension('order_payer_address', $payerAddress);
$customFields = $orderEntity->getCustomFields();
$shippingAndBilling = $this->getShippingAndBilling($orderEntity);
if($customFields !== null) {
$customFields = array_merge($customFields, $shippingAndBilling);
} else {
$customFields = $shippingAndBilling;
}
if ($payerAddress != null) {
$customFields['currentPayerOrderAddressId'] = $payerAddress->getId();
}
$orderEntity->setCustomFields($customFields);
}
}
}