OrderService.php
Sat May 21 2022 15:06:05 GMT+0000 (Coordinated Universal Time)
Saved by @igor #drupal #pseudo-field #form-render
<?php
namespace Drupal\bb2b_order;
use Drupal\bb2b_company\CompanyInterface;
use Drupal\commerce_order\Adjustment;
use Drupal\commerce_order\Entity\OrderInterface;
use Drupal\commerce_price\Price;
use Drupal\commerce_product\Entity\ProductInterface;
use Drupal\commerce_product\Entity\ProductVariationInterface;
use Drupal\commerce_shipping\Entity\ShipmentInterface;
use Drupal\commerce_shipping\Entity\ShippingMethod;
use Drupal\commerce_shipping\Entity\ShippingMethodInterface;
use Drupal\commerce_shipping\ShippingOrderManagerInterface;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Database\Connection;
use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\TempStore\PrivateTempStoreFactory;
use Drupal\paragraphs\ParagraphInterface;
use Drupal\profile\Entity\ProfileInterface;
/**
* Class Order Service.
*/
class OrderService implements OrderServiceInterface {
use StringTranslationTrait;
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* The messenger.
*
* @var \Drupal\Core\Messenger\MessengerInterface
*/
protected $messenger;
/**
* The cache.
*
* @var \Drupal\Core\Cache\CacheBackendInterface
*/
protected $cache;
/**
* The shipping order manager.
*
* @var \Drupal\commerce_shipping\ShippingOrderManagerInterface
*/
protected $shippingOrderManager;
/**
* The database connection.
*
* @var \Drupal\Core\Database\Connection
*/
protected $database;
/**
* The private temp store.
*
* @var \Drupal\Core\TempStore\PrivateTempStore
*/
protected $tempStore;
/**
* The Base Linker config.
*
* @var \Drupal\Core\Config\Config
*/
protected $baseLinkerConfig;
/**
* Constructs a new OrderService object.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param \Drupal\Core\Messenger\MessengerInterface $messenger
* The messenger.
* @param \Drupal\Core\Cache\CacheBackendInterface $cache
* The cache.
* @param \Drupal\commerce_shipping\ShippingOrderManagerInterface $shipping_order_manager
* The shipping order manager.
* @param \Drupal\Core\Database\Connection $database
* The database connection.
* @param \Drupal\Core\TempStore\PrivateTempStoreFactory $temp_store_factory
* The tempstore factory.
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The configuration factory.
*/
public function __construct(
EntityTypeManagerInterface $entity_type_manager,
MessengerInterface $messenger,
CacheBackendInterface $cache,
ShippingOrderManagerInterface $shipping_order_manager,
Connection $database,
PrivateTempStoreFactory $temp_store_factory,
ConfigFactoryInterface $config_factory
) {
$this->entityTypeManager = $entity_type_manager;
$this->messenger = $messenger;
$this->cache = $cache;
$this->shippingOrderManager = $shipping_order_manager;
$this->database = $database;
$this->tempStore = $temp_store_factory->get('bb2b_order');
$this->baseLinkerConfig = $config_factory->get('bb2b_baselinker.settings');
}
/**
* {@inheritdoc}
*/
public function getApplicableWarehouse(ProductInterface $product) {
$cid = 'get_applicable_warehouse_' . $product->id();
$cache_data = $this->cache->get($cid);
if (isset($cache_data->data)) {
return $cache_data->data;
}
else {
// @todo Logic to check which warehouse will be used in reality.
$warehouse = $this->entityTypeManager->getStorage('taxonomy_term')->loadByProperties([
'vid' => 'warehouse',
'field_warehouse_code' => 'PL',
]);
$warehouse = reset($warehouse);
$product_warehouses = $product->get('field_warehouse')->referencedEntities();
$applicable_warehouse = NULL;
foreach ($product_warehouses as $product_warehouse) {
$warehouse_target_id = $product_warehouse->get('field_warehouse')->target_id;
if ($warehouse_target_id == $warehouse->id()) {
$applicable_warehouse = $product_warehouse;
}
}
if (!empty($applicable_warehouse)) {
$cache_tags = [
'commerce_product:' . $product->id(),
'paragraph:' . $applicable_warehouse->id(),
];
$this->cache->set($cid, $applicable_warehouse, CacheBackendInterface::CACHE_PERMANENT, $cache_tags);
}
return $applicable_warehouse;
}
}
/**
* {@inheritdoc}
*/
public function setStockOnWarehouse(ParagraphInterface $warehouse, int $stock) {
if ($stock <= 0) {
$warehouse->setUnpublished();
}
elseif (!$warehouse->isPublished() && $stock > 0) {
$warehouse->setPublished();
}
$warehouse->set('field_available', $stock);
$warehouse->set('field_last_linker_stock_sync', time());
$warehouse->save();
}
/**
* {@inheritdoc}
*/
public function getAvailableStock(ProductInterface $product, ?ParagraphInterface $product_warehouse = NULL) {
$cid = 'get_available_stock_' . $product->id();
$cache_data = $this->cache->get($cid);
if (isset($cache_data->data)) {
return $cache_data->data;
}
else {
// For regular non-bundle products.
if ($product->get('field_bundle_product_skus')->isEmpty()) {
$available_stock = $this->doGetAvailableStock($product, $product_warehouse);
}
// For bundle products we need to check all products that are part of the
// bundle.
else {
/** @var \Drupal\commerce_product\Entity\ProductVariationInterface $variation_item */
$available_stock_for_product = [];
foreach ($product->get('field_bundle_product_skus')->referencedEntities() as $variation_item) {
$product_item = $variation_item->getProduct();
$available_stock_for_product[] = $this->doGetAvailableStock($product_item, $product_warehouse);
}
$available_stock = min($available_stock_for_product);
}
$cache_tags = [
'commerce_product:' . $product->id(),
];
if ($product_warehouse !== NULL) {
$cache_tags[] = 'paragraph:' . $product_warehouse->id();
}
$this->cache->set($cid, $available_stock, CacheBackendInterface::CACHE_PERMANENT, $cache_tags);
return $available_stock;
}
}
/**
* Gets the available stock value.
*
* @param \Drupal\commerce_product\Entity\ProductInterface $product
* The product.
* @param \Drupal\paragraphs\ParagraphInterface|null $product_warehouse
* The warehouse.
*
* @return int
* The available stock.
*/
protected function doGetAvailableStock(ProductInterface $product, ?ParagraphInterface $product_warehouse = NULL) {
if (!$product_warehouse) {
/** @var \Drupal\paragraphs\ParagraphInterface $product_warehouse */
$product_warehouse = $this->getApplicableWarehouse($product);
if (!$product_warehouse) {
return 0;
}
}
$local_stock = (int) $product_warehouse->get('field_available')->value;
$stock_reserved_belmil_de = (int) $product->get('field_stock_reserved_belmil_de')->value;
if ($stock_reserved_belmil_de > 0) {
$local_stock -= $stock_reserved_belmil_de;
}
$stock_reserved = (int) $product_warehouse->get('field_reserved')->value;
if ($stock_reserved > 0) {
$local_stock -= $stock_reserved;
}
return $local_stock > 0 ? $local_stock : 0;
}
/**
* {@inheritdoc}
*/
public function checkAccessForProduct(ProductInterface $product) {
$cid = 'access_for_product_' . $product->id();
$cache_data = $this->cache->get($cid);
if (isset($cache_data->data)) {
return $cache_data->data;
}
else {
/** @var \Drupal\paragraphs\ParagraphInterface $warehouse */
$warehouse = $this->getApplicableWarehouse($product);
$available = $this->getAvailableStock($product, $warehouse);
$result = $warehouse && $available > 0;
$cache_tags = [
'commerce_product:' . $product->id(),
];
if ($warehouse !== NULL) {
$cache_tags[] = 'paragraph:' . $warehouse->id();
}
$this->cache->set($cid, $result, CacheBackendInterface::CACHE_PERMANENT, $cache_tags);
return $result;
}
}
/**
* {@inheritdoc}
*/
public function getCompanyForClient(OrderInterface $order) {
$customer_id = $order->getData('client_id', $order->getCustomerId());
if (!$customer_id) {
return NULL;
}
return $this->getCompanyForCustomer($customer_id);
}
/**
* {@inheritdoc}
*/
public function getCompanyForCustomer($customer_id) {
$company_storage = $this->entityTypeManager->getStorage('company');
$company = $company_storage->loadByProperties([
'employees' => $customer_id,
]);
$company = reset($company);
if (!$company) {
return NULL;
}
return $company;
}
/**
* {@inheritdoc}
*/
public function getProductPriceForClient(ProductVariationInterface $variation, OrderInterface $order, CompanyInterface $company = NULL) {
$price = $variation->getPrice();
$list_price = $variation->getListPrice();
$calculated_price = [
'price' => $price,
'list_price' => $list_price,
];
if (!$company) {
return $calculated_price;
}
$order_type = $order->get('field_order_type')->value;
$client_price_groups = $company->get('price_group')->referencedEntities() ?? NULL;
$with_return = $company->get('auto_generate_return_label')->value;
if (!$client_price_groups) {
return $calculated_price;
}
$client_price_group_ids = array_map(function ($client_price_group) {
return $client_price_group->id();
}, $client_price_groups);
$product = $variation->getProduct();
$product_price_groups = $product->get('field_price_group')->referencedEntities();
$price_groups = array_filter($product_price_groups, function ($product_price_group) use ($client_price_group_ids) {
$price_group_terms = $product_price_group->get('field_price_group')->referencedEntities();
/** @var \Drupal\taxonomy\Entity\Term $price_group_term */
$price_group_term = reset($price_group_terms);
return $price_group_term && in_array($price_group_term->id(), $client_price_group_ids);
});
if (!$price_groups) {
return $calculated_price;
}
$price_group_price = 0;
foreach ($price_groups as $price_group) {
if ($order_type === 'ddp' || $order_type === 'ddp_reservation') {
$price_group_price = $price_group->get('field_ddp')->value;
}
elseif ($order_type === 'drop_shipping' && !$with_return) {
$price_group_price = $price_group->get('field_dsnr')->value;
}
elseif ($order_type === 'drop_shipping' && $with_return) {
$price_group_price = $price_group->get('field_dswr')->value;
}
if ($price_group_price > 0) {
break;
}
}
if ($price_group_price == 0) {
return $calculated_price;
}
$currency = $price->getCurrencyCode();
$calculated_price['price'] = new Price((string) $price_group_price, $currency);
if ($list_price) {
$calculated_price['list_price'] = new Price((string) $price_group_price, $currency);
}
return $calculated_price;
}
/**
* {@inheritdoc}
*/
public function packageMinQuantityIsValid(OrderInterface $order): bool {
return $this->getNotFullPackageCount($order) === 0;
}
/**
* {@inheritdoc}
*/
public function getNotFullPackageCount(OrderInterface $order): int {
$order_type = $order->get('field_order_type')->value;
$not_valid_packages = 0;
if ($order_type === 'drop_shipping') {
return 0;
}
// Sum order item quantities by Tag.
$quantities = $this->getOrderedQuantitiesByTag($order->getItems());
if (!$quantities) {
return 1;
}
$shipment_packages = $this->entityTypeManager
->getStorage('shipment_package')
->loadMultiple();
// Check min quantities.
foreach ($shipment_packages as $shipment_package) {
$ordered_quantity = 0;
$min_order_quantity = (int) $shipment_package->get('max_item_per_package')->value;
$articles = $shipment_package->get('article_no')->referencedEntities();
foreach ($articles as $article) {
if (isset($quantities[$article->id()])) {
$ordered_quantity += $quantities[$article->id()];
}
}
if ($ordered_quantity > 0 &&
(!$min_order_quantity
|| $ordered_quantity < $min_order_quantity
|| $ordered_quantity % $min_order_quantity != 0)
) {
$not_valid_packages++;
}
}
return $not_valid_packages;
}
/**
* {@inheritdoc}
*/
public function firstPackageIsNotFull(OrderInterface $order): bool {
$order_type = $order->get('field_order_type')->value;
if ($order_type === 'drop_shipping') {
return FALSE;
}
// Sum order item quantities by Tag.
$quantities = $this->getOrderedQuantitiesByTag($order->getItems());
return $this->minQuantityIsNotValid($quantities);
}
/**
* Check ordered quantity.
*
* @param array $quantities
* The ordered quantities.
*
* @return bool
* Return TRUE if minimum ordered quantity is not valid.
*/
public function minQuantityIsNotValid(array $quantities): bool {
$shipment_packages = $this->entityTypeManager
->getStorage('shipment_package')
->loadMultiple();
// Check min quantities.
foreach ($shipment_packages as $shipment_package) {
$ordered_quantity = 0;
$min_order_quantity = (int) $shipment_package->get('max_item_per_package')->value;
$articles = $shipment_package->get('article_no')->referencedEntities();
foreach ($articles as $article) {
if (isset($quantities[$article->id()])) {
$ordered_quantity += $quantities[$article->id()];
}
}
if ($ordered_quantity > 0 && $ordered_quantity < $min_order_quantity) {
return TRUE;
}
}
return FALSE;
}
/**
* Gets the order item quantities by tag.
*
* @param \Drupal\commerce_order\Entity\OrderItemInterface[] $order_items
* The order items.
*/
public function getOrderedQuantitiesByTag(array $order_items): array {
$quantities = [];
foreach ($order_items as $order_item) {
/** @var \Drupal\commerce_product\Entity\ProductVariationInterface $purchased_entity */
$purchased_entity = $order_item->getPurchasedEntity();
if (!$purchased_entity || $purchased_entity->getEntityTypeId() != 'commerce_product_variation') {
continue;
}
/** @var \Drupal\commerce_product\Entity\ProductInterface $product */
$product = $purchased_entity->getProduct();
$tag = $product->get('field_tag')->referencedEntities();
$tag = reset($tag);
if (!$tag) {
return [];
}
$tag_id = $tag->id();
if (isset($quantities[$tag_id])) {
$quantities[$tag_id] += (int) $order_item->getQuantity();
}
else {
$quantities[$tag_id] = (int) $order_item->getQuantity();
}
}
return $quantities;
}
/**
* {@inheritdoc}
*/
public function getMinOrderQuantity(ProductInterface $product) {
$min_order_quantity = 1;
$tag = $product->get('field_tag')->referencedEntities();
$tag = reset($tag);
if ($tag) {
$shipment_packages = $this->entityTypeManager
->getStorage('shipment_package')
->loadMultiple();
$package = array_filter($shipment_packages, function ($shipment_package) use ($tag) {
$terms = $shipment_package->get('article_no')->referencedEntities();
$term_ids = array_map(function ($term) {
return $term->id();
}, $terms);
return in_array($tag->id(), $term_ids);
});
$package = reset($package);
$min_order_quantity = $package ? $package->get('max_item_per_package')->value : 1;
}
return $min_order_quantity;
}
/**
* Resolve shipping for order.
*
* @param \Drupal\commerce_order\Entity\OrderInterface $order
* The order.
* @param \Drupal\profile\Entity\ProfileInterface|null $billing_profile
* The billing profile.
* @param \Drupal\profile\Entity\ProfileInterface|null $shipping_profile
* The shipping profile.
* @param string|null $shipping_country
* The shipping country.
*/
public function resolveShipping(
OrderInterface $order,
?ProfileInterface $billing_profile = NULL,
?ProfileInterface $shipping_profile = NULL,
?string $shipping_country = NULL
) {
if (!$billing_profile) {
$billing_profile = $order->getBillingProfile();
}
if (!$shipping_profile) {
$shipping_profile = $order->collectProfiles()['shipping'] ?? NULL;
}
if (!$shipping_profile && $billing_profile) {
$shipping_profile = $billing_profile->createDuplicate();
$shipping_profile->unsetData('copy_to_address_book');
}
if (!$billing_profile && $shipping_profile) {
$billing_profile = $shipping_profile->createDuplicate();
$billing_profile->unsetData('copy_to_address_book');
}
if (!$billing_profile || !$shipping_profile) {
return;
}
$shipments = $this->shippingOrderManager->pack($order, $shipping_profile);
$store_key = 'shipping_force_resolve:' . $order->id();
$shipping_force_resolve = $this->tempStore->get($store_key);
$this->tempStore->delete($store_key);
$shipping_country = $shipping_country ?: $shipping_profile
->get('address')->country_code;
$shipping_method = $this->getShippingMethodForOrder($order, $billing_profile, $shipping_country);
if ($shipping_method) {
$shipping_adjustments = $order->getAdjustments(['shipping']);
foreach ($shipping_adjustments as $adjustment) {
$order->get('adjustments')->removeAdjustment($adjustment);
}
$adjustments = $order->getAdjustments();
/** @var \Drupal\commerce_shipping\Entity\ShipmentInterface $shipment */
foreach ($shipments as $key => $shipment) {
$this->setShippingMethodForShipment($order, $shipment, $shipping_method, $key, $adjustments);
if ($shipping_force_resolve) {
$shipment->save();
}
}
$order->set('adjustments', $adjustments);
}
$order->set('shipments', $shipments);
}
/**
* Get shipping method for order.
*
* @param \Drupal\commerce_order\Entity\OrderInterface $order
* The order.
* @param \Drupal\profile\Entity\ProfileInterface|null $profile
* The profile.
* @param string|null $shipping_country
* The shipping country.
*
* @return \Drupal\commerce_shipping\Entity\ShippingMethodInterface|null
* The shipping method.
*/
public function getShippingMethodForOrder(OrderInterface $order, ProfileInterface $profile, ?string $shipping_country = NULL) {
$shipping_method = NULL;
/** @var \Drupal\commerce_shipping\Entity\ShippingMethodInterface[] $shipping_methods */
$shipping_methods = ShippingMethod::loadMultiple();
$shipping_methods = array_filter($shipping_methods, function ($item) {
return $item->getPlugin()->getPluginId() == 'belmil_shipping' && $item->isEnabled();
});
usort($shipping_methods, function ($a, $b) {
return $a->getWeight() <=> $b->getWeight();
});
$time_now = DrupalDateTime::createFromTimestamp(time());
$time_now->setTimezone(new \DateTimeZone('Europe/Belgrade'));
// Saturday is also working day. Only sunday is weekend.
$is_weekend = $time_now->format('N') == 7;
$order_type = $order->get('field_order_type')->value;
$order_source = $order->get('field_source')->value;
$belmil_de_shipping_method = NULL;
if ($order_source === 'belmilde') {
$belmil_de_shipping_method = $order->getData('belmil_de_shipping_method', 'standard');
}
$amazon_shipping_method = NULL;
if ($order_source === 'amazon') {
$amazon_shipping_method = $order->getData('amazon_shipping_method', 'Std DE Dom_3');
}
$packstation_address = $profile->hasField('field_packstation_address') &&
$profile->get('field_packstation_address')->value;
$packstation_postnumber = $profile->hasField('field_packstation_postnumber') ?
$profile->get('field_packstation_postnumber')->value : NULL;
$shipping_profile_country = $shipping_country ?: $profile->get('address')->country_code;
$shipping_with_packstation = $shipping_profile_country === 'DE' &&
$packstation_address && $packstation_postnumber;
foreach ($shipping_methods as $shipping_method_entity) {
$method_configuration = $shipping_method_entity->getPlugin()
->getConfiguration();
$method_countries = $method_configuration['belmil'] ?? [];
// Set amazon related shipping method.
if ($order_source == 'amazon') {
// DE Standard or Express.
if ($shipping_method_entity->label() == 'DEDHL' &&
in_array($amazon_shipping_method, ['Std DE Dom_3', 'Exp DE Dom_1'])
) {
$shipping_method = $shipping_method_entity;
break;
}
// International EU.
elseif ($shipping_method_entity->label() == 'DHL DE INTERNATIONAL' &&
$amazon_shipping_method == 'Std DE Intl_2'
) {
$shipping_method = $shipping_method_entity;
break;
}
}
// DHL Packstation address.
if ($shipping_with_packstation &&
isset($method_configuration['address']) &&
$method_configuration['address']['packstation']
) {
foreach ($method_countries as $country_code => $country_config) {
if ($shipping_profile_country == $country_code &&
!empty($country_config['enabled'])
) {
$shipping_method = $shipping_method_entity;
break 2;
}
}
}
// Check store condition.
if (!in_array($order->getStoreId(), $shipping_method_entity->getStoreIds())) {
continue;
}
// Order total conditions check.
$conditions = $shipping_method_entity->getConditions();
if ($conditions) {
/** @var \Drupal\commerce\Plugin\Commerce\Condition\ConditionInterface[] $order_total_conditions */
$order_total_conditions = array_filter($conditions, function ($condition) {
/** @var \Drupal\commerce\Plugin\Commerce\Condition\ConditionInterface $condition */
return $condition->getEntityTypeId() == 'commerce_order' &&
$condition->getPluginId() === 'order_total_price';
});
$order_total_condition = reset($order_total_conditions);
if ($order_total_condition && !$order_total_condition->evaluate($order)) {
continue;
}
}
if (
isset($method_configuration['belmil']) &&
isset($method_configuration['order_types']) &&
isset($method_configuration['time']) &&
!$shipping_with_packstation
) {
foreach ($method_countries as $country_code => $country_config) {
if (
$shipping_profile_country == $country_code &&
!empty($country_config['enabled']) &&
!empty($method_configuration['order_types'][$order_type])
) {
// Check time conditions for weekend.
if ($is_weekend === TRUE) {
if (!empty($method_configuration['time']['use_on_weekends']) && !empty($method_configuration['time']['use_on_weekends_type'])) {
$weekends_time_until = new DrupalDateTime($method_configuration['time']['weekends_time_until']);
$weekends_time_after = new DrupalDateTime($method_configuration['time']['weekends_time_after']);
// For DDP orders we don't have to check time conditions.
$ignore_time_conditions_for_ddp = !empty($method_configuration['time']['ignore_for_ddp']);
if ($ignore_time_conditions_for_ddp === TRUE &&
in_array($order_type, ['ddp', 'ddp_reservation'])
) {
$shipping_method = $shipping_method_entity;
break 2;
}
// Check if the current time is in range for non-ddp orders.
if ($method_configuration['time']['use_on_weekends_type'] == 'included') {
if ($time_now >= $weekends_time_until && $time_now <= $weekends_time_after) {
$shipping_method = $shipping_method_entity;
break 2;
}
}
elseif ($method_configuration['time']['use_on_weekends_type'] == 'excluded') {
if ($time_now < $weekends_time_until || $time_now > $weekends_time_after) {
$shipping_method = $shipping_method_entity;
break 2;
}
}
}
}
// Check time conditions for weekdays.
else {
if (!empty($method_configuration['time']['use_on_workdays']) && !empty($method_configuration['time']['use_on_workdays_type'])) {
$workdays_time_until = new DrupalDateTime($method_configuration['time']['workdays_time_until']);
$workdays_time_after = new DrupalDateTime($method_configuration['time']['workdays_time_after']);
// For DDP orders we don't have to check time conditions.
$ignore_time_conditions_for_ddp = !empty($method_configuration['time']['ignore_for_ddp']);
if ($ignore_time_conditions_for_ddp === TRUE &&
in_array($order_type, ['ddp', 'ddp_reservation'])
) {
$shipping_method = $shipping_method_entity;
break 2;
}
// Check if the current time is in range for non-ddp orders.
if ($method_configuration['time']['use_on_workdays_type'] == 'included') {
if ($time_now >= $workdays_time_until && $time_now <= $workdays_time_after) {
$shipping_method = $shipping_method_entity;
break 2;
}
}
elseif ($method_configuration['time']['use_on_workdays_type'] == 'excluded') {
$excluded = $time_now < $workdays_time_until ||
$time_now > $workdays_time_after;
if ($excluded ||
(!$excluded && $belmil_de_shipping_method === 'standard')
) {
$shipping_method = $shipping_method_entity;
break 2;
}
}
}
}
}
}
}
}
return $shipping_method;
}
/**
* Set shipping method for shipment.
*
* @param \Drupal\commerce_shipping\Entity\ShipmentInterface $shipment
* The shipment.
* @param \Drupal\commerce_shipping\Entity\ShippingMethodInterface $shipping_method
* The shipping method.
* @param int|null $key
* The shipment key.
* @param \Drupal\commerce_order\Adjustment[] $adjustments
* The order adjustments.
*/
public function setShippingMethodForShipment(OrderInterface $order, ShipmentInterface $shipment, ShippingMethodInterface $shipping_method, ?int $key = 0, array &$adjustments = []) {
$shipment->setShippingMethod($shipping_method);
$order_type = $order->get('field_order_type')->value;
$order_source = $order->get('field_source')->value;
$your_order_id = $order->get('field_your_order_id')->value;
$shipping_method_plugin = $shipping_method->getPlugin();
$shipping_rates = $shipping_method_plugin->calculateRates($shipment);
$shipping_rate = reset($shipping_rates);
$shipping_label = $shipping_rate->getService()->getLabel();
/** @var \Drupal\commerce_price\Price $amount */
$amount = $shipping_rate->getAmount();
// Belmil.de express price is 10 EUR.
if ($order_source === 'belmilde' &&
$shipping_label === 'DEDHL Prime'
) {
$amount = new Price('10', $amount->getCurrencyCode());
}
// DDP is FREE.
if (in_array($order_type, ['ddp', 'ddp_reservation'])) {
$amount = new Price('0', $amount->getCurrencyCode());
}
// Amazon.
if ($order_source === 'amazon') {
$amount_number = 0;
$amazon_shipping_method = $order->getData('amazon_shipping_method', 'Std DE Dom_3');
// DE Standard.
if ($amazon_shipping_method === 'Std DE Dom_3') {
$amount_number = $this->baseLinkerConfig->get('amazon_standard_de_price');
}
// DE Express.
elseif ($amazon_shipping_method === 'Exp DE Dom_1') {
$amount_number = $this->baseLinkerConfig->get('amazon_express_de_price');
}
// International EU.
elseif ($amazon_shipping_method === 'Std DE Intl_2') {
$amount_number = $this->baseLinkerConfig->get('amazon_eu_price');
}
$items = count($shipment->getItems());
$amount = new Price($items * $amount_number, $amount->getCurrencyCode());
}
$shipment->setAmount($amount);
$shipping_service = $shipping_rate->getService()->getId();
$shipment->setShippingService($shipping_service);
$shipment_number = str_pad(($key + 1), 2, '0', STR_PAD_LEFT);
$shipment_number = $your_order_id ?
$shipment_number . ' #' . $your_order_id : $shipment_number;
$shipment_title = $this->t('Shipping for package @order_id', [
'@order_id' => $shipment_number,
]);
$shipment->setTitle($shipment_title);
// In case there are some changes on placed order that are
// affecting shipment information.
if (!empty($order->get('placed')->value)) {
$shipment->save();
}
$cloned_adjustment = NULL;
foreach ($adjustments as $key => $adjustment) {
// Edit existing shipment amount.
if ($adjustment->getSourceId() == $shipment->id()) {
$cloned_adjustment = $adjustment->toArray();
$cloned_adjustment['amount'] = $amount;
unset($adjustments[$key]);
$order->get('adjustments')->removeAdjustment($adjustment);
$adjustments[] = new Adjustment($cloned_adjustment);
}
}
if (!$cloned_adjustment) {
$adjustments[] = new Adjustment([
'type' => 'shipping',
'label' => $shipment_title,
'amount' => $amount,
'source_id' => $shipment->id(),
]);
}
}
/**
* Set surcharges on order.
*
* @param \Drupal\commerce_order\Entity\OrderInterface $order
* The order.
*/
public function setOrderSurcharges(OrderInterface $order) {
$adjustments = $order->getAdjustments(['custom']);
foreach ($adjustments as $adjustment) {
$order->get('adjustments')->removeAdjustment($adjustment);
}
$currency = $order->getTotalPrice()->getCurrencyCode();
$not_full_package_cnt = $this->getNotFullPackageCount($order);
// Convert back to while if we need more surcharge.
if ($not_full_package_cnt > 0) {
$order->addAdjustment(new Adjustment([
'type' => 'custom',
'label' => $this->t('Surcharge'),
'amount' => new Price('4.00', $currency),
'source_id' => $order->id() . '|' . $not_full_package_cnt,
]));
// $not_full_package_cnt--;
}
}
/**
* Get bundle products variation ids.
*
* @return mixed
* The ids.
*/
public function getBundleProductIds() {
$query = $this->database->query("SELECT DISTINCT p.field_bundle_product_skus_target_id AS field_bundle_product_skus_target_id
FROM {commerce_product__field_bundle_product_skus} p
INNER JOIN {commerce_product_variation_field_data} pv ON pv.variation_id = p.field_bundle_product_skus_target_id
LEFT OUTER JOIN {commerce_product__field_main_and_bundle_product} mb ON mb.entity_id = pv.product_id
WHERE (p.deleted = 0) AND ((mb.field_main_and_bundle_product_value IS NULL) OR (mb.field_main_and_bundle_product_value <> 1))");
return $query->fetchCol();
}
}



Comments