<?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(); } }