<?php
namespace App\Form\Type\EventListener;
use App\Entity\Core\Customer;
use App\Service\EstimationCartService;
use DateTime;
use Doctrine\ORM\EntityManagerInterface;
use Sylius\Component\Addressing\Model\AddressInterface;
use Sylius\Component\Core\Model\CustomerInterface;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\OrderCheckoutTransitions;
use Sylius\Component\Core\OrderPaymentStates;
use Sylius\Component\Core\OrderShippingStates;
use Sylius\Component\Core\Repository\CustomerRepositoryInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
class AddOrderDataListener implements EventSubscriberInterface
{
private $customerRepository;
private $entityManager;
public function __construct(
CustomerRepositoryInterface $customerRepository,
EntityManagerInterface $entityManager
) {
$this->customerRepository = $customerRepository;
$this->entityManager = $entityManager;
}
public static function getSubscribedEvents()
{
return [
FormEvents::POST_SUBMIT => 'onPostSubmit',
];
}
public function onPostSubmit(FormEvent $event)
{
$order = $event->getData();
if (!$order) {
return;
}
$this->removeShippingAddress($event);
}
private function removeShippingAddress(FormEvent $event): void
{
$order = $event->getData();
$customerType = $event->getForm()->get('type')->getData();
$order->getCustomer()->setType($customerType);
if ($customerType == Customer::TYPE_PERSON) {
$order->getCustomer()->setLine($order->getCustomer()->getCurrentTypeValue());
}
$shippingMethod = count($order->getShipments()) > 0 ? $order->getShipments()->first()->getMethod() : null;
$customer = $this->getCustomer($order->getCustomer());
$billingAddress = $order->getBillingAddress();
$shippingAddress = $order->getShippingAddress();
$order->setCustomer($customer);
$this->processAddress($billingAddress, $customer, $order);
$this->processAddress($shippingAddress, $customer, $order);
if (
$shippingMethod &&
$shippingMethod->getCode() == 'retiro'
) {
$order->setShippingAddress(null);
}
$this->setOrderData($order);
}
private function setAddressData(AddressInterface $address, CustomerInterface $customer): void
{
if (!$address->getId()) {
$address->setPostCode('0');
$address->setCountryCode('CL');
$address->setFirstName($customer->getFirstName());
$address->setLastName($customer->getFirstName());
}
}
private function setOrderData(OrderInterface $order): void
{
$order->setCheckoutState(OrderCheckoutTransitions::TRANSITION_COMPLETE);
if ($order->getState() == EstimationCartService::SHOPPING_CART) {
$order->setState(OrderInterface::STATE_NEW);
} else {
$order->setState('estimation_' . OrderInterface::STATE_NEW);
}
$order->setPaymentState(OrderPaymentStates::STATE_AWAITING_PAYMENT);
$order->setShippingState(OrderShippingStates::STATE_READY);
$order->setCheckoutCompletedAt(new DateTime());
}
private function copyCustomerFieldsFromCustomer(CustomerInterface $oldCustomer, CustomerInterface $toCopyCustomer)
{
$oldCustomer->setFirstName($toCopyCustomer->getFirstName());
$oldCustomer->setLastName($toCopyCustomer->getLastName());
$oldCustomer->setPhoneNumber($toCopyCustomer->getPhoneNumber());
$oldCustomer->setEmail($toCopyCustomer->getEmail());
$oldCustomer->setLine($toCopyCustomer->getLine());
$oldCustomer->setCompany($toCopyCustomer->getCompany());
}
private function getCustomer(CustomerInterface $customer): CustomerInterface
{
$storedCustomer = $this->customerRepository->findOneByRut($customer->getRut());
if ($storedCustomer) {
$this->copyCustomerFieldsFromCustomer($storedCustomer, $customer);
$this->entityManager->persist($storedCustomer);
}
return $storedCustomer ?? $customer;
}
private function processAddress(
?AddressInterface $address,
CustomerInterface $customer,
OrderInterface $order
): void {
if ($address && $address->getStreet()) {
$this->setAddressData($address, $customer);
} else {
$order->setShippingAddress(null);
}
}
}