<?php declare(strict_types=1);
namespace DonCarneTheme\Core\Content\Flow\Dispatching\Action;
use Monolog\Logger;
use Shopware\Core\Checkout\Order\Aggregate\OrderLineItem\OrderLineItemEntity;
use Shopware\Core\Content\Flow\Dispatching\Action\FlowAction;
use Shopware\Core\Content\Media\MediaEntity;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\Event\FlowEvent;
use Shopware\Core\Framework\Event\OrderAware;
use DonCarneTheme\Service\GraphQLClient;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use DateTime;
use Shopware\Core\Checkout\Order\OrderEntity;
use Shopware\Core\Checkout\Order\OrderEvents;
class SendOrderDataAction extends FlowAction
{
const TRIGGER = 'order_inProgress';
const FEMALE_SALUTATION_ID = 'f3183bb9f683437e9f862cbe2b63237e';
private GraphQLClient $graphQLClient;
private EntityRepositoryInterface $productRepository;
private EntityRepositoryInterface $customerGroupRepository;
private EntityRepositoryInterface $orderAddressRepository;
private Logger $logger;
public function __construct(
GraphQLClient $graphQLClient,
EntityRepositoryInterface $productRepository,
EntityRepositoryInterface $customerGroupRepository,
EntityRepositoryInterface $orderAddressRepository,
Logger $logger
) {
$this->graphQLClient = $graphQLClient;
$this->productRepository = $productRepository;
$this->customerGroupRepository = $customerGroupRepository;
$this->orderAddressRepository = $orderAddressRepository;
$this->logger = $logger;
}
public static function getName(): string
{
return 'action.send.order.data';
}
public static function getSubscribedEvents(): array
{
return [
self::getName() => 'handle',
];
}
public function requirements(): array
{
return [OrderAware::class];
}
public function handle(FlowEvent $event): void
{
$orderEvent = $event->getEvent();
if (!$orderEvent instanceof OrderAware) {
return;
}
$orderData = [];
/** @var OrderEntity $order */
$order = $orderEvent->getOrder();
$customer = $order->getOrderCustomer()->getCustomer();
$shipping = $order->getDeliveries()->first();
$customFields = $order->getCustomFields() ?? [];
$expectedDelivery = $customFields['expected_delivery_date'] ?? date_format($shipping->getShippingDateEarliest(),"Y-m-d");
$orderData['email'] = $customer->getEmail();
$orderData['subscriberKey'] = $customer->getEmail();
$orderData['trigger'] = self::TRIGGER;
$orderData['order_date'] = date_format($order->getOrderDate(),"Y-m-d");
$orderData['delivery_date'] = $expectedDelivery;
$orderData['order_id'] = $order->getOrderNumber();
$orderData['gender'] = 'M';
// Billing data
$criteria = new Criteria([$order->getBillingAddressId()]);
$criteria->addAssociation('country');
$billingAddress = $this->orderAddressRepository->search($criteria, $event->getContext())->first();
//prior method did not work. Salutation was always empty. Salutation is not available here either, just the id is set
if($billingAddress->getSalutationId() == self::FEMALE_SALUTATION_ID) {
$orderData['gender'] = 'F';
}
$orderData['billing'] = $this->getBillingData($billingAddress);
// Shipping data
$orderData['shipping'] = $this->getShippingData($shipping);
$orderData['payment_method'] = $order->getTransactions()->first()->getPaymentMethod()->getName();
$orderData['positions'] = $this->getPositions($order, $event)['positions'];
$orderData['order_sum'] = (string) round($this->getPositions($order, $event)['totalPositionsPrice'],2);
$orderData['shipping_cost'] = (string) $shipping->getShippingCosts()->getTotalPrice();
$orderData['promotions'] = $this->getPromotions($order, $event);
$orderData['total_order_sum'] = (string) $order->getAmountTotal();
$orderData['customer_group'] = $this->customerGroupRepository->search(new Criteria([$customer->getGroupId()]), $event->getContext())->first()->getName();
$orderData['voucher'] = '[]';
$response = $this->graphQLClient->sendOrderData($orderData);
}
/* Get all billing infos */
private function getBillingData($billingAddress) {
$billingData = [];
$billingData['firstname'] = $billingAddress->getFirstName();
$billingData['lastname'] = $billingAddress->getLastName();
$billingData['company'] = $billingAddress->getCompany() ?: "";
$billingData['street'] = $billingAddress->getStreet();
$billingData['postalcode'] = $billingAddress->getZipcode();
$billingData['city'] = $billingAddress->getCity();
$billingData['country'] = $billingAddress->getCountry()->getIso();
return $billingData;
}
/* Get all shipping infos */
private function getShippingData($shipping) {
$shippingAddress = $shipping->getShippingOrderAddress();
$shippingData = [];
$shippingData['shipping_firstname'] = $shippingAddress->getFirstName();
$shippingData['shipping_lastname'] = $shippingAddress->getLastName();
$shippingData['shipping_company'] = $shippingAddress->getCompany() ?: "";
$shippingData['shipping_street'] = $shippingAddress->getStreet();
$shippingData['shipping_postalcode'] = $shippingAddress->getZipcode();
$shippingData['shipping_city'] = $shippingAddress->getCity();
$shippingData['shipping_country'] = $shippingAddress->getCountry()->getIso();
$shippingData['delivery_date'] = date_format($shipping->getShippingDateEarliest(),"Y-m-d");
$shippingData['delivery_method'] = $shipping->getShippingMethod()->getName();
$shippingCustomFields = $shipping->getShippingMethod()->getCustomFields();
/* If shipping method has a graphql id redo the delivery options request to retrieve the correct shipping method name and date */
if ($shippingCustomFields && isset($shippingCustomFields['custom_shipping_graphql_id'])) {
$availableShippingMethods = $this->graphQLClient->getDeliveryOptions($shippingData['shipping_country'], $shippingData['shipping_postalcode']);
$deliveryGqlOptions = json_decode($availableShippingMethods->getResponseBody())->data->deliveryOptions;
foreach ($deliveryGqlOptions as $deliveryGqlOption) {
if ($deliveryGqlOption->id === $shippingCustomFields['custom_shipping_graphql_id']) {
$shippingData['delivery_method'] = $deliveryGqlOption->name;
$shippingData['delivery_date'] = $this->getNearestDeliveryDate($deliveryGqlOption->dates);
}
}
}
return $shippingData;
}
/* Get all products data */
private function getPositions($order, $event) {
$positions = [];
// We need this variable to calculate the order_sum value
$positionsPrice = 0;
foreach ($order->getLineItems() as $lineItem) {
/**
* @var OrderLineItemEntity $lineItem
*/
if ($lineItem->getType() === 'product') {
$lineItemData = [];
$criteria = new Criteria([$lineItem->getProductId()]);
$criteria->addAssociation('properties.group');
$criteria->addAssociation('media');
$criteria->addAssociation('customFields');
$product = $this->productRepository->search($criteria, $event->getContext())->first();
$lineItemData['product_condition'] = "";
if ($product->getProperties()) {
foreach ($product->getProperties() as $property) {
$propertyGroupCustomFields = $property->getGroup()->getCustomFields();
if ($propertyGroupCustomFields &&
isset($propertyGroupCustomFields['custom_property_group_is_kuehlbedingung']) &&
$propertyGroupCustomFields['custom_property_group_is_kuehlbedingung']
) {
$lineItemData['product_condition'] = $property->getName();
}
if ($propertyGroupCustomFields &&
isset($propertyGroupCustomFields['custom_property_group_is_kuehlbedingung']) &&
$propertyGroupCustomFields['custom_property_group_is_kuehlbedingung']
) {
$lineItemData['product_condition'] = $property->getName();
}
}
}
$lineItemData['product_imageurl'] = '';
//Cover Image is not available. Therefore cycle through all images and use the one with position 0
if($customFields = $product->getCustomFields()) {
if(!empty($customFields['mail_thumb'])) {
$lineItemData['product_imageurl'] = 'https://doncarne.de' . $customFields['mail_thumb'];
}
}
if($lineItemData['product_imageurl'] == ''){
if ($media = $product->getMedia()) {
foreach($media as $m) {
if($m->getPosition() == 0) {
$lineItemData['product_imageurl'] = $m->getMedia()->getUrl();
}
}
if(empty($lineItemData['product_imageurl'])) {
$lineItemData['product_imageurl'] = $product->getMedia()->first()->getMedia()->getUrl();
}
}
}
$lineItemData['product_name'] = str_replace(["'",'"', '\\'], '',$lineItem->getLabel());
$lineItemData['product_weight'] = (string) $product->getWeight();
$lineItemData['product_id'] = $product->getProductNumber();
$lineItemData['order_amount'] = (string) $lineItem->getQuantity();
$lineItemData['product_price_per_amount'] = (string) $lineItem->getUnitPrice();
$lineItemData['product_price_total'] = (string) $lineItem->getTotalPrice();
$positions[] = addslashes(json_encode($lineItemData, JSON_UNESCAPED_UNICODE));
$positionsPrice += $lineItem->getTotalPrice();
}
if ($lineItem->getType() == 'easy-coupon') {
$lineItemData = [];
$lineItemData['product_imageurl'] = '';
$lineItemData['product_name'] = 'Gutschein Einlösung';
$lineItemData['product_condition'] = "";
$lineItemData['product_weight'] = '';
$lineItemData['product_id'] = 'voucher' . $lineItem->getUnitPrice();
$lineItemData['order_amount'] = (string) $lineItem->getQuantity();
$lineItemData['product_price_per_amount'] = (string) $lineItem->getUnitPrice();
$lineItemData['product_price_total'] = (string) $lineItem->getTotalPrice();
$positions[] = addslashes(json_encode($lineItemData, JSON_UNESCAPED_UNICODE));
$positionsPrice += $lineItem->getTotalPrice();
}
if ($lineItem->getType() == 'dvsn_pseudo_product') {
$lineItemData = [];
$lineItemData['product_imageurl'] = '';
$lineItemData['product_name'] = str_replace(["'",'"', '\\'], '',$lineItem->getLabel());
$lineItemData['product_condition'] = "";
$lineItemData['product_weight'] = '';
$lineItemData['product_id'] = '';
$lineItemData['order_amount'] = 1;
$lineItemData['product_price_per_amount'] = (string) $lineItem->getUnitPrice();
$lineItemData['product_price_total'] = (string) $lineItem->getTotalPrice();
$positions[] = addslashes(json_encode($lineItemData, JSON_UNESCAPED_UNICODE));
$positionsPrice += $lineItem->getTotalPrice();
}
}
$returnData = [
'positions' => implode(',', $positions),
'totalPositionsPrice' => $positionsPrice
];
return $returnData;
}
/* Get all the promotions */
private function getPromotions($order) {
$discounts = [];
foreach ($order->getLineItems() as $lineItem) {
if ($lineItem->getType() === 'promotion') {
$lineItemData = [];
$lineItemData['name'] = $lineItem->getLabel();
$lineItemData['value'] = (string) (-1 * $lineItem->getTotalPrice());
$discounts[] = addslashes(json_encode($lineItemData, JSON_UNESCAPED_UNICODE));
}
}
return implode(',', $discounts);
}
private function getNearestDeliveryDate($dates)
{
$nearestDate = null;
foreach ($dates as $date) {
$currentDate = $date->date;
if (!$nearestDate || $currentDate < $nearestDate) {
$nearestDate = $currentDate;
}
}
$nearestDate = DateTime::createFromFormat("Y-md-", strval($nearestDate));
return $nearestDate;
}
}