<?php
namespace CioTetra\Subscriber;
use CioTetra\CioTetra;
use CioTetra\Traits\SftpTrait;
use CioTetra\Traits\UTF8Trait;
use Shopware\Core\Framework\Context;
use Shopware\Core\Checkout\Cart\Event\CheckoutOrderPlacedEvent;
use Shopware\Core\Checkout\Order\Aggregate\OrderCustomer\OrderCustomerEntity;
use Shopware\Core\Checkout\Order\OrderEntity;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
class OrderExportSubscriber implements EventSubscriberInterface
{
use SftpTrait;
use UTF8Trait;
private SystemConfigService $configService;
private EntityRepositoryInterface $customerRepository;
private EntityRepositoryInterface $countryRepository;
private EntityRepositoryInterface $languageRepository;
private $GERMAN_LANGUAGE_ID;
public function __construct(SystemConfigService $configService, EntityRepositoryInterface $customerRepository, EntityRepositoryInterface $countryRepository, EntityRepositoryInterface $languageRepository)
{
$this->configService = $configService;
$this->customerRepository = $customerRepository;
$this->countryRepository = $countryRepository;
$this->languageRepository = $languageRepository;
$this->GERMAN_LANGUAGE_ID = $this->getGermanLanguageId();
}
public static function getSubscribedEvents(): array
{
return [
CheckoutOrderPlacedEvent::class => 'onOrderPlaced',
];
}
public function onOrderPlaced(CheckoutOrderPlacedEvent $event): void
{
[$fullPath, $filename] = $this->getFileName($event->getOrder()->getOrderNumber());
$filecontent = $this->generateOrderFile($event->getOrder()->getOrderCustomer(), $event->getOrder(), $event);
if (file_put_contents($fullPath, $filecontent)) {
$uploadSuccess = $this->directUpload($fullPath, $filename, $filecontent);
if (!$uploadSuccess) {
// TODO: inplement false handling
}
} else {
// TODO: inplement false handling
}
}
private function getCountryNameInGerman($isoCode)
{
$criteria = new Criteria();
$criteria->addAssociation('translations');
$criteria->addFilter(new EqualsFilter('iso3', $isoCode));
$country = $this->countryRepository->search($criteria, Context::createDefaultContext())->first();
foreach ($country->translations->getElements() as $item){
if( $item->getLanguageId() == $this->GERMAN_LANGUAGE_ID){
return $item->getName();
}
}
}
private function getKStatus1($isoCode)
{
if( in_array($isoCode, ["DEU"]))
{
return "EU";
}
if( in_array($isoCode, ["AUT", "BEL", "BGR", "HRV", "CYP", "CZE", "DNK", "EST", "FIN", "FRA", "GRC", "HUN", "IRL", "ITA", "LVA", "LTU", "LUX", "MLT", "NLD", "POL", "PRT", "ROU", "SVK", "SVN", "ESP", "SWE"]))
{
return "EU";
}
return "Int";
}
private function getGermanLanguageId()
{
$criteria = new Criteria();
$criteria->addAssociation('locale');
$criteria->addFilter(new EqualsFilter('locale.code', 'de-DE'));
$language = $this->languageRepository->search($criteria, Context::createDefaultContext())->first();
return $language->getId();
}
private function getShippingCost($deliveries = null)
{
$shippingCost = 0;
if($deliveries){
foreach($deliveries as $delivery){
if($delivery->getShippingCosts()->getTotalPrice() > $shippingCost){
$shippingCost = $delivery->getShippingCosts()->getTotalPrice();
}
}
}
return number_format($shippingCost,2,',', '');
}
private function getShippingCostDiscount($deliveries = null)
{
$shippingCostDiscount = 0;
if($deliveries){
foreach($deliveries as $delivery){
if($delivery->getShippingCosts()->getTotalPrice() < $shippingCostDiscount){
$shippingCostDiscount = $delivery->getShippingCosts()->getTotalPrice();
}
}
}
return $shippingCostDiscount;
}
private function generateOrderFile(OrderCustomerEntity $customer, OrderEntity $order, CheckoutOrderPlacedEvent $event): string
{
$criteria = new Criteria([$customer->getCustomerId()]);
$customer = $this->customerRepository->search($criteria, Context::createDefaultContext())->first();
$existingCustomer = false;
$differentDeliveryAddress = false;
$exportText[] = '[Vor]';
$exportText[] = 'Art=164';
$exportText[] = 'StArt=4';
$exportText[] = 'VDat=#' . $order->getCreatedAt()->format('m.d.Y') . '#';
$exportText[] = 'Zeichen="' . $order->getOrderNumber() . '"';
$exportText[] = 'Betreff="Webshop Bestellung"';
$useObjID = false;
$useObjIDString = '';
if( $order->getCustomerComment() != '') {
$useObjID = true;
$useObjIDString .= "Bestellkommentar: " . str_replace(array("\r\n", "\r", "\n"), " ", $order->getCustomerComment());
}
if( $order->getCustomFields() ){
if( array_key_exists('custom_field_budget_name_save_on_order', $order->getCustomFields())){
if( $useObjID ){
$useObjIDString .= " | ";
}
$useObjIDString .= 'Budgetbestellung: ' . $order->getCustomFields()['custom_field_budget_name_save_on_order'];
}
}
if( $useObjID == true ){
$exportText[] = 'ObjID="' . $useObjIDString . '"';
}
$customFields = $customer->getCustomFields();
$billingAddress = $order->getAddresses()->first();
$shippingAddress = $order->getAddresses()->last();
if( $billingAddress->getId() != $shippingAddress->getId() )
{
$differentDeliveryAddress = true;
}
if(is_array($customFields))
{
if(array_key_exists('custom_customer_itpnumber', $customFields) && !empty($customFields['custom_customer_itpnumber']))
{
$existingCustomer = true;
$itpNumber = $customFields['custom_customer_itpnumber'];
}
}
if( $existingCustomer )
{
$exportText[] = '[VAdr]';
$exportText[] = 'AdrNr="' . $itpNumber . '"';
$exportText[] = 'Name1="' . $billingAddress->getFirstName() . ' ' . $billingAddress->getLastName() . '"';
if( $differentDeliveryAddress )
{
$exportText[] = '[Adr]';
$exportText[] = 'AdrNr="######"';
$exportText[] = 'Anrede="(Firma)"';
$exportText[] = 'Name="' . $shippingAddress->getFirstName() . ' ' . $shippingAddress->getLastName() . '"';
$exportText[] = 'Str="' . $shippingAddress->getStreet() . '"';
$exportText[] = 'Plz="' . $shippingAddress->getZipcode() . '"';
$exportText[] = 'Ort="' . $shippingAddress->getCity() . '"';
$exportText[] = 'Nation=Nation("' . $this->getCountryNameInGerman($shippingAddress->getCountry()->getIso3()) . '")';
$exportText[] = 'KGruppe=32';
$exportText[] = 'KStatus1="' . $this->getKStatus1($shippingAddress->getCountry()->getIso3()) . '"';
$exportText[] = '[Ansp]';
$exportText[] = 'Anrede="Herr"';
$exportText[] = 'Name="Ingo Hillebrand"';
$exportText[] = '[Komm]';
$exportText[] = 'MOpt=0';
$exportText[] = 'Typ=48';
$exportText[] = 'Nr="Ingo.Hillebrand@connect-io.de"';
$exportText[] = '[VAdr]';
$exportText[] = 'Typ=30';
}
}else
{
$exportText[] = '[Adr]';
$exportText[] = 'AdrNr="######"';
$exportText[] = 'Anrede="(Firma)"';
$exportText[] = 'Name="' . $customer->getCompany() . '"';
$exportText[] = 'Str="' . $billingAddress->getStreet() . '"';
$exportText[] = 'Plz="' . $billingAddress->getZipcode() . '"';
$exportText[] = 'Ort="' . $billingAddress->getCity() . '"';
$exportText[] = 'Nation=Nation("' . $billingAddress->getCountry()->getName() . '")';
$exportText[] = 'KGruppe=32';
$exportText[] = 'KStatus1="' . $this->getKStatus1($billingAddress->getCountry()->getIso3()) . '"';
$exportText[] = '[Ansp]';
$exportText[] = 'Anrede="' . $billingAddress->getSalutation()->getDisplayName() . '"';
$exportText[] = 'Name="' . $billingAddress->getFirstName() . ' ' . $billingAddress->getLastName() . '"';
$exportText[] = '[Komm]';
$exportText[] = 'MOpt=0';
$exportText[] = 'Typ=48';
$exportText[] = 'Nr="' . $customer->getEmail() . '"';
$exportText[] = '[VAdr]';
$exportText[] = 'Typ=0';
if( $differentDeliveryAddress )
{
$exportText[] = 'AdrNr="######"';
$exportText[] = 'Anrede="(Firma)"';
$exportText[] = 'Name="' . $shippingAddress->getCompany() . '"';
$exportText[] = 'Str="' . $shippingAddress->getStreet() . '"';
$exportText[] = 'Plz="' . $shippingAddress->getZipcode() . '"';
$exportText[] = 'Ort="' . $shippingAddress->getCity() . '"';
$exportText[] = 'Nation=Nation("' . $shippingAddress->getCountry()->getName() . '")';
$exportText[] = 'KGruppe=32';
$exportText[] = 'KStatus1="' . $this->getKStatus1($shippingAddress->getCountry()->getIso3()) . '"';
$exportText[] = '[Ansp]';
$exportText[] = 'Anrede="' . $shippingAddress->getSalutation()->getDisplayName() . '"';
$exportText[] = 'Name="' . $shippingAddress->getFirstName() . ' ' . $shippingAddress->getLastName() . '"';
$exportText[] = '[Komm]';
$exportText[] = 'MOpt=0';
$exportText[] = 'Typ=48';
$exportText[] = 'Nr="' . $customer->getEmail() . '"';
$exportText[] = '[VAdr]';
$exportText[] = 'Typ=30';
}
}
$i = 1;
$isShippingDiscountUsed = false;
foreach ($order->getLineItems() as $item) {
$payload = $item->getPayload();
if( $item->getType() == 'product' ) {
if (array_key_exists('productNumber', $payload)) {
$exportText[] = "[VPos]";
$exportText[] = 'Pos=' . $i++;
$exportText[] = 'ArtId=ArtNr2ID("' . $item->getPayload()['productNumber'] . '")';
$exportText[] = 'VarId=ArtNr2ID("' . $item->getPayload()['productNumber'] . '-I";1)';
$exportText[] = 'PosMg=' . number_format($item->getQuantity(), 2, ',', '');
$exportText[] = 'Preis=' . number_format($item->getTotalPrice(), 2, ',', '');
}
}
if( $item->getType() == 'promotion') {
$price = $item->getTotalPrice();
if( $price == 0 && $isShippingDiscountUsed == false ){
$price += $this->getShippingCostDiscount($order->getDeliveries());
}
$exportText[] = "[VPos]";
$exportText[] = 'Pos=' . $i++;
$exportText[] = 'ObjID="Rabatt"';
$exportText[] = 'ArtNr="Rabatt"';
$exportText[] = 'PosMg=' . number_format($item->getQuantity(), 2, ',', '');
$exportText[] = 'Preis=' . number_format($price, 2, ',', '');
}
}
$exportText[] = "[VPos]";
$exportText[] = 'Pos=' . $i++;
$exportText[] = 'ObjID="Versandkosten"';
$exportText[] = 'ArtNr="Versandkosten"';
$exportText[] = 'PosMg=1';
$exportText[] = 'Preis=' . $this->getShippingCost($order->getDeliveries());
$exportText = implode(PHP_EOL, $exportText);
return $exportText;
}
private function getFileName(string $ordernumber): array
{
$path = getcwd() . '/..' . CioTetra::ROUTE_EXPORT_DIRECTORY;
$filename = date('d_m_Y_H_i_s') . '_tetra_export-' . $ordernumber;
return [$path . $filename . '.txt', $filename . '.txt'];
}
private function directUpload(string $fullPath, string $filename, string $data): bool
{
$message = "Start direct Upload from Order File" . PHP_EOL;
$success = $this->uploadOrderFile($data, $filename, $message);
if ($success) {
unlink($fullPath);
}
return $success;
}
}