SynchronizeEdifactOrders.php
Thu Jan 06 2022 14:52:48 GMT+0000 (Coordinated Universal Time)
<?php
namespace Drupal\stormtextil_synchronization\Controller;
use Drupal\commerce_shipping\Entity\Shipment;
use Drupal\commerce_shipping\Entity\ShippingMethod;
use Drupal\commerce_shipping\ShipmentItem;
use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Controller\ControllerBase;
use Drupal\physical\Weight;
use Drupal\physical\WeightUnit;
use Drupal\profile\Entity\Profile;
use EDI\Parser;
use Drupal\commerce_price\Price;
use Drupal\commerce_order\Entity\OrderItem;
use Drupal\commerce_order\Entity\Order;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Class Synchronize Edifact Orders.
*
* @package Drupal\stormtextil_synchronization\Controller
*/
class SynchronizeEdifactOrders extends ControllerBase {
/**
* The time service.
*
* @var \Drupal\Component\Datetime\TimeInterface
*/
protected $time;
/**
* The config factory.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected $config;
/**
* Logger interface.
*
* @var \Psr\Log\LoggerInterface
*/
protected $logger;
/**
* Constructs Synchronize Edifact Orders.
*
* @param \Drupal\Component\Datetime\TimeInterface $time
* The Time service.
* @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory
* The config factory.
* @param \Psr\Log\LoggerInterface $logger
* Logger interface.
*/
public function __construct(TimeInterface $time, ConfigFactoryInterface $configFactory, LoggerInterface $logger) {
$this->time = $time;
$this->config = $configFactory;
$this->logger = $logger;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('datetime.time'),
$container->get('config.factory'),
$container->get('logger.channel.default')
);
}
/**
* Parse the edi file and create an order.
*
* @return string[]|void
* Response.
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
* @throws \Drupal\Core\Entity\EntityStorageException
* @throws \Drupal\Core\TypedData\Exception\MissingDataException
*/
public function parse() {
// Login information.
$login_data = $this->config->get('stormtextil_config.settings');
$ftp_server = $login_data->get('edifact')['server'];
$ftp_user = $login_data->get('edifact')['username'];
$ftp_pass = $login_data->get('edifact')['password'];
// Set up a connection or die.
$ftp = ftp_connect($ftp_server) or die("Couldn't connect to $ftp_server");
// Try to login.
if (ftp_login($ftp, $ftp_user, $ftp_pass)) {
echo "Connected as $ftp_user@$ftp_server\n";
}
else {
echo "Couldn't connect as $ftp_user\n";
}
// Turn passive mode on,
// e have to use passive mode because the,
// running docker container is listening on a different port.
ftp_set_option($ftp, FTP_USEPASVADDRESS, FALSE);
ftp_pasv($ftp, TRUE);
// Listing all companies in root folder.
$companies = ftp_nlist($ftp, '/');
foreach ($companies as $company) {
// Check if this is a valid C5 ID.
if (is_numeric(basename($company))) {
$company_id = basename($company);
}
// Listing all files in stores directory.
$files = ftp_nlist($ftp, './' . $company_id . '/archive/');
foreach ($files as $file) {
if ((preg_match('/^.*\.(edi)$/i', $file))) {
// Edi file for proceeding the order.
$ediFile = file_get_contents('ftp://' . $ftp_user . ':' . $ftp_pass . '@' . $ftp_server . '/'
. $company_id . '/archive/' . basename($file));
// Parsing the file.
$parser = new Parser();
$parsedEdiFile = $parser->loadString($ediFile);
$lineItems = [];
$orderItems = [];
// Looping through all parsed EDI elements and taking
// data for order information.
foreach ($parsedEdiFile as $ediElement) {
switch ($ediElement[0]) {
// Delivery information.
case 'NAD':
if ($ediElement[1] == 'DP') {
$organization = $ediElement[3][0];
$address_line1 = $ediElement[3][1];
$postal_local = explode(" ", $ediElement[3][2]);
$postal_code = $postal_local[0];
$locality = $postal_local[1];
$country_code = $ediElement[3][3];
}
elseif ($ediElement[1] == 'BY') {
$billing_address = $ediElement[5];
$billing_city = $ediElement[6];
$billing_company = $ediElement[4];
$billing_zip_code = $ediElement[8];
};
break;
// Name that we are going to use in shipment profile.
case 'CTA':
$name = explode(" ", $ediElement[2][1]);
$given_name = $name[0];
$family_name = $name[1];
break;
// Currency code.
case 'CUX':
$currency = $ediElement[1][1];
break;
// Tax percentage.
case 'TAX':
if (!isset($tax)) {
$tax = $ediElement[5][3] / 100;
}
break;
// Name of shipping method.
case 'ALC':
$shipping_method_name = $ediElement[2];
break;
// Shipping price.
case 'MOA':
if ($ediElement[1][0] == '8') {
$shipping_price = $ediElement[1][1];
}
break;
// Line item variation.
case 'PIA':
if ($ediElement[1] == '5') {
$sku = $ediElement[2][0];
$rawProductVariation = $this->entityTypeManager()
->getStorage('commerce_product_variation')
->loadByProperties([
'sku' => $sku,
]);
$productVariation = reset($rawProductVariation);
$lineItems[$productVariation->getTitle()]['variation'] = $productVariation;
}
break;
// Line item quantity.
case 'QTY':
$quantity = $ediElement[1][1];
$lineItems[$productVariation->getTitle()]['quantity'] = $quantity;
break;
// Line item price.
case 'PRI':
if ($ediElement[1][0] == 'AAA') {
$price = $ediElement[1][1];
$lineItems[$productVariation->getTitle()]['price'] = $price;
}
break;
// Number of line items.
case 'CNT':
$numberOfLineItems = $ediElement[1][1];
break;
}
}
// Creating order items.
foreach ($lineItems as $lineItem) {
$orderItem = OrderItem::create([
'type' => 'default',
'purchased_entity' => $lineItem['variation'],
'quantity' => $lineItem['quantity'],
'unit_price' => new Price($lineItem['price'], $currency),
'overridden_unit_price' => TRUE,
]);
$orderItem->save();
$orderItems[] = $orderItem;
}
// Creating order.
$order = Order::create([
'type' => 'default',
'mail' => $this->currentUser()->getEmail(),
'uid' => $this->currentUser()->id(),
'store_id' => 1,
'order_items' => [$orderItems[0], $orderItems[1]],
'placed' => $this->time->getCurrentTime(),
]);
$order->save();
// Creating shipment.
if ($order->get('shipments')->count() == 0) {
$first_shipment = Shipment::create([
'type' => 'default',
'order_id' => $order->id(),
'title' => 'Shipment',
'state' => 'ready',
]);
$first_shipment->save();
}
// Caclculating weight for shipment.
foreach ($orderItems as $order_item) {
$quantity = $order_item->getQuantity();
$purchased_entity = $order_item->getPurchasedEntity();
if ($purchased_entity->get('weight')->isEmpty()) {
$weight = new Weight(1, WeightUnit::GRAM);
}
else {
$weight_item = $purchased_entity->get('weight')->first();
$weight = $weight_item->toMeasurement();
}
// Creating shipment item.
$shipment_item = new ShipmentItem([
'order_item_id' => $order_item->id(),
'title' => $purchased_entity->label(),
'quantity' => $quantity,
'weight' => $weight->multiply($quantity),
'declared_value' => $order_item->getTotalPrice(),
]);
$first_shipment->addItem($shipment_item);
}
// Creating shipping method.
$shipping_method = ShippingMethod::create([
'stores' => 1,
'name' => $shipping_method_name,
'plugin' => [
'target_plugin_id' => 'flat_rate',
'target_plugin_configuration' => [
'rate_label' => 'Shipping GG',
'rate_amount' => [
'number' => $shipping_price,
'currency_code' => $currency,
],
],
],
'status' => TRUE,
'weight' => 0,
]);
$shipping_method->save();
// Adding newly created shipment method to shipment.
$first_shipment->setShippingMethod($shipping_method);
// Adding amount to shipment.
$shipping_method_plugin = $shipping_method->getPlugin();
$shipping_rates = $shipping_method_plugin->calculateRates($first_shipment);
$shipping_rate = reset($shipping_rates);
$shipping_service = $shipping_rate->getService()->getId();
$amount = reset($shipping_rates)->getAmount();
$first_shipment->setAmount($amount);
$first_shipment->save();
$order->set('shipments', [$first_shipment]);
$order->save();
// Creating shipment profile using data from EDI file.
$shipment_profile = Profile::create([
'uid' => $order->getCustomerId(),
'type' => 'customer',
]);
$shipment_profile->address->given_name = $given_name;
$shipment_profile->set('field_contact_person', implode(" ", $name));
$shipment_profile->address->family_name = $family_name;
$shipment_profile->address->organization = $organization;
$shipment_profile->set('field_company', $organization);
$shipment_profile->address->country_code = $country_code;
$shipment_profile->set('field_new_country', $country_code);
$shipment_profile->address->locality = $locality;
$shipment_profile->set('field_city', $locality);
$shipment_profile->address->postal_code = $postal_code;
$shipment_profile->set('field_zip_code', $postal_code);
$shipment_profile->address->address_line1 = $address_line1;
$shipment_profile->set('field_address_1', $address_line1);
$shipment_profile->save();
$first_shipment->setShippingProfile($shipment_profile);
$first_shipment->setShippingService($shipping_service);
$first_shipment->save();
$order->set('shipments', $first_shipment);
// Create a billing profile.
if (empty($order->getBillingProfile())) {
$billing_profile = Profile::create([
'type' => 'customer',
'uid' => $order->getCustomerId(),
]);
$billing_profile->save();
$billing_profile->set('field_address_1', $billing_address);
$billing_profile->set('field_city', $billing_city);
$billing_profile->set('field_company', $billing_company);
$billing_profile->set('field_zip_code', $billing_zip_code);
$billing_profile->save();
$order->setBillingProfile($billing_profile);
$order->save();
}
// Including tax into price.
$priceWithTax = $order->getTotalPrice()->getNumber() + ($order->getTotalPrice()->getNumber() * $tax);
$order->set('total_price', new Price(round($priceWithTax, 2), $currency));
$order->save();
// Checking the number of line items.
if ($numberOfLineItems == count($orderItems)) {
$poruka = 'Order created.';
}
else {
$poruka = 'Order was not created.';
}
// @todo Ovo će trebati da se otkomentariše u nekom momentu.
// ftp_delete($ftp, $file);.
return [
'#markup' => $poruka,
];
}
else {
// @todo Create a logic for putting wrong files in the error directory.
$this->logger->error('Wrong file format');
}
}
}
// Closing ftp connection.
ftp_close($ftp);
}
}



Comments