From f337e6c6aab1ab1632e81821cf0b4763ca4b7558 Mon Sep 17 00:00:00 2001 From: Micheal Lutz Date: Mon, 20 Mar 2017 14:05:59 -0400 Subject: [PATCH 1/6] Issue #2861378 by mikeNCM: Implement FedEx Special Services as plugins --- .../PurchasableEntityDangerousGoods.php | 17 +++- .../Commerce/FedEx/DangerousGoodsPlugin.php | 51 ++++++++++ .../src/PurchasableEntityHazardousBase.php | 96 ------------------- .../Plugin/Commerce/FedEx/DryIcePlugin.php | 4 +- src/Plugin/Commerce/ShippingMethod/FedEx.php | 37 +++---- 5 files changed, 88 insertions(+), 117 deletions(-) create mode 100644 modules/dangerous/src/Plugin/Commerce/FedEx/DangerousGoodsPlugin.php delete mode 100644 modules/dangerous/src/PurchasableEntityHazardousBase.php diff --git a/modules/dangerous/src/Plugin/Commerce/EntityTrait/PurchasableEntityDangerousGoods.php b/modules/dangerous/src/Plugin/Commerce/EntityTrait/PurchasableEntityDangerousGoods.php index 33fee43..363f0d0 100644 --- a/modules/dangerous/src/Plugin/Commerce/EntityTrait/PurchasableEntityDangerousGoods.php +++ b/modules/dangerous/src/Plugin/Commerce/EntityTrait/PurchasableEntityDangerousGoods.php @@ -2,7 +2,10 @@ namespace Drupal\commerce_fedex_dangerous\Plugin\Commerce\EntityTrait; -use Drupal\commerce_fedex_dangerous\PurchasableEntityHazardousBase; +use Drupal\commerce\BundleFieldDefinition; +use Drupal\commerce\Plugin\Commerce\EntityTrait\EntityTraitBase; +use Drupal\commerce_fedex\Plugin\Commerce\ShippingMethod\FedEx; +use NicholasCreativeMedia\FedExPHP\Enums\DangerousGoodsAccessibilityType; /** * Provides the "fedex_dangerous" trait. @@ -13,14 +16,22 @@ * entity_types = {"commerce_product_variation"} * ) */ -class PurchasableEntityDangerousGoods extends PurchasableEntityHazardousBase { +class PurchasableEntityDangerousGoods extends EntityTraitBase { /** * {@inheritdoc} */ public function buildFieldDefinitions() { - $fields = $this->baseFields(); + $id = $this->getPluginId(); + $fields[$id . '_accessibility'] = BundleFieldDefinition::create('list_string') + ->setLabel($this->t('Require Dangerous Goods/Hazardous Materials Shipping')) + ->setCardinality(1) + ->setSetting('allowed_values', [0 => "None"] + FedEx::enumToList(DangerousGoodsAccessibilityType::getValidValues())) + ->setDisplayOptions('form', [ + 'type' => 'options_select', + 'weight' => 95, + ]); return $fields; } diff --git a/modules/dangerous/src/Plugin/Commerce/FedEx/DangerousGoodsPlugin.php b/modules/dangerous/src/Plugin/Commerce/FedEx/DangerousGoodsPlugin.php new file mode 100644 index 0000000..b5e813b --- /dev/null +++ b/modules/dangerous/src/Plugin/Commerce/FedEx/DangerousGoodsPlugin.php @@ -0,0 +1,51 @@ + ''] + parent::defaultConfiguration(); + + } + + /** + * {@inheritdoc} + */ + public function buildConfigurationForm(array $form, FormStateInterface $form_state) { + $form = parent::buildConfigurationForm($form, $form_state); + $form['contact_number'] = [ + '#type' => 'textfield', + '#title' => $this->t("Contact Number"), + '#description' => $this->t('Enter the Phone number of your dangerous goods/hazardous materials contact person'), + '#default_value' => $this->configuration['contact_number'], + ]; + return $form; + } + + /** + * {@inheritdoc} + */ + public function submitConfigurationForm(array &$form, FormStateInterface $form_state) { + parent::submitConfigurationForm($form, $form_state); + $this->configuration['contact_number'] = $form_state->getValue('contact_number'); + } + +} diff --git a/modules/dangerous/src/PurchasableEntityHazardousBase.php b/modules/dangerous/src/PurchasableEntityHazardousBase.php deleted file mode 100644 index d82404e..0000000 --- a/modules/dangerous/src/PurchasableEntityHazardousBase.php +++ /dev/null @@ -1,96 +0,0 @@ -getPluginId(); - $label = $this->getLabel(); - - $fields[$id] = BundleFieldDefinition::create('boolean') - ->setLabel($label) - ->setDisplayOptions('form', [ - 'type' => 'boolean_checkbox', - 'weight' => 95, - ]); - - $fields[$id . '_options'] = BundleFieldDefinition::create('list_string') - ->setLabel($label . ' ' . $this->t('options')) - ->setCardinality(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) - ->setSetting('allowed_values', [ - HazardousCommodityOptionType::VALUE_BATTERY => $this->t('Battery'), - HazardousCommodityOptionType::VALUE_HAZARDOUS_MATERIALS => $this->t('Hazardous materials'), - HazardousCommodityOptionType::VALUE_LIMITED_QUANTITIES_COMMODITIES => $this->t('Limited quantities commodities'), - HazardousCommodityOptionType::VALUE_ORM_D => $this->t('ORD M'), - HazardousCommodityOptionType::VALUE_REPORTABLE_QUANTITIES => $this->t('Reportable quantities'), - HazardousCommodityOptionType::VALUE_SMALL_QUANTITY_EXCEPTION => $this->t('Small quantity exception'), - ]) - ->setDisplayOptions('form', [ - 'type' => 'options_buttons', - 'weight' => 95, - ]); - - $fields[$id . '_quantity'] = BundleFieldDefinition::create('float') - ->setLabel($label . ' ' . $this->t('quantity')) - ->setDescription($this->t('Specify the quantity of hazardous materials being shipped.')) - ->setDisplayOptions('form', [ - 'type' => 'number', - 'weight' => 95, - ]); - - $fields[$id . '_units'] = BundleFieldDefinition::create('list_string') - ->setLabel($label . ' ' . $this->t('quantity units')) - ->setDescription($this->t('Specify the unit of measurement to use for the quantity.')) - ->setSetting('allowed_values', [ - 'ml' => $this->t('ml'), - 'L' => $this->t('L'), - 'g' => $this->t('g'), - 'kg' => $this->t('kg'), - 'kg G' => $this->t('kg G'), - ]) - ->setDisplayOptions('form', [ - 'type' => 'options_select', - 'weight' => 95, - ]); - - $fields[$id . '_regulation_type'] = BundleFieldDefinition::create('list_string') - ->setLabel($label . ' ' . $this->t('regulation type')) - ->setDescription($this->t('Select the regulation type of the hazardous materials')) - ->setSetting('allowed_values', [ - HazardousCommodityRegulationType::VALUE_ADR => $this->t('ADR'), - HazardousCommodityRegulationType::VALUE_DOT => $this->t('DOT'), - HazardousCommodityRegulationType::VALUE_IATA => $this->t('IATA'), - HazardousCommodityRegulationType::VALUE_ORMD => $this->t('ORMD'), - ]) - ->setDisplayOptions('form', [ - 'type' => 'options_select', - 'weight' => 95, - ]); - - $fields[$id . '_description'] = BundleFieldDefinition::create('string') - ->setLabel($label . ' ' . $this->t('description')) - ->setDescription($this->t('Identify and describe this hazardous commodity.')) - ->setDisplayOptions('form', [ - 'type' => 'string_textfield', - 'weight' => 95, - ]); - - return $fields; - } - -} diff --git a/modules/dry_ice/src/Plugin/Commerce/FedEx/DryIcePlugin.php b/modules/dry_ice/src/Plugin/Commerce/FedEx/DryIcePlugin.php index a892b88..6bd1e29 100644 --- a/modules/dry_ice/src/Plugin/Commerce/FedEx/DryIcePlugin.php +++ b/modules/dry_ice/src/Plugin/Commerce/FedEx/DryIcePlugin.php @@ -14,8 +14,8 @@ * @CommerceFedExPlugin( * id = "dry_ice", * label = @Translation("FedEx Dry Ice"), - * options_label = @Translation("Dry Ice Shipment Options") - * options_description = @Translation(" + * options_label = @Translation("Dry Ice Shipment Options"), + * options_description = @Translation("Enter your global shipping options for dry ice shipments") * ) */ class DryIcePlugin extends FedExPluginBase { diff --git a/src/Plugin/Commerce/ShippingMethod/FedEx.php b/src/Plugin/Commerce/ShippingMethod/FedEx.php index e110cc3..b7b5ee1 100644 --- a/src/Plugin/Commerce/ShippingMethod/FedEx.php +++ b/src/Plugin/Commerce/ShippingMethod/FedEx.php @@ -28,7 +28,6 @@ use NicholasCreativeMedia\FedExPHP\Structs\Address; use NicholasCreativeMedia\FedExPHP\Structs\Dimensions; use NicholasCreativeMedia\FedExPHP\Structs\Money; -use NicholasCreativeMedia\FedExPHP\Structs\PackageSpecialServicesRequested; use NicholasCreativeMedia\FedExPHP\Structs\Party; use NicholasCreativeMedia\FedExPHP\Structs\RequestedPackageLineItem; use NicholasCreativeMedia\FedExPHP\Structs\RequestedShipment; @@ -230,10 +229,10 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta '#default_value' => $this->configuration['api_information']['api_key'], ]; $form['api_information']['api_password'] = [ - '#type' => 'textfield', + '#type' => 'password', '#title' => $this->t('API password'), '#description' => $this->t('Enter your FedEx API password only if you wish to change its value.'), - '#default_value' => $this->configuration['api_information']['api_password'], + '#default_value' => '', ]; $form['api_information']['account_number'] = [ '#type' => 'number', @@ -315,9 +314,13 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta $plugin = $this->plugins->get($plugin_id); $subform = [ '#type' => 'details', - '#title' => $definition['optionsLabel']->render(), + '#title' => $definition['options_label']->render(), + '#description' => $definition['options_description']->render(), ]; $form[$plugin_id] = $plugin->buildConfigurationForm($subform, $form_state); + if ($form[$plugin_id] == $subform) { + unset($form[$plugin_id]); + } } return $form; } @@ -332,9 +335,11 @@ public function validateConfigurationForm(array &$form, FormStateInterface $form parent::validateConfigurationForm($form, $form_state); foreach ($this->fedExServiceManager->getDefinitions() as $plugin_id => $definition) { - /** @var \Drupal\commerce_fedex\Plugin\Commerce\FedEx\FedExPluginInterface $plugin */ - $plugin = $this->plugins->get($plugin_id); - $plugin->validateConfigurationForm($form[$plugin_id], SubformState::createForSubform($form[$plugin_id], $form_state->getCompleteForm(), $form_state)); + if (!empty($form[$plugin_id])) { + /** @var \Drupal\commerce_fedex\Plugin\Commerce\FedEx\FedExPluginInterface $plugin */ + $plugin = $this->plugins->get($plugin_id); + $plugin->validateConfigurationForm($form[$plugin_id], SubformState::createForSubform($form[$plugin_id], $form_state->getCompleteForm(), $form_state)); + } } } @@ -366,8 +371,11 @@ public function submitConfigurationForm(array &$form, FormStateInterface $form_s foreach ($this->fedExServiceManager->getDefinitions() as $plugin_id => $definition) { /** @var \Drupal\commerce_fedex\Plugin\Commerce\FedEx\FedExPluginInterface $plugin */ $plugin = $this->plugins->get($plugin_id); - $plugin->submitConfigurationForm($form[$plugin_id], SubformState::createForSubform($form[$plugin_id], $form_state->getCompleteForm(), $form_state)); + if (!empty($form[$plugin_id])) { + $plugin->submitConfigurationForm($form[$plugin_id], SubformState::createForSubform($form[$plugin_id], $form_state->getCompleteForm(), $form_state)); + } $this->configuration['plugins'][$plugin_id]['configuration'] = $plugin->getConfiguration(); + } } parent::submitConfigurationForm($form, $form_state); @@ -479,9 +487,9 @@ public function getPlugins() { * @return array * The options list. */ - protected static function enumToList(array $enums) { + public static function enumToList(array $enums) { return array_combine($enums, array_map(function ($d) { - return ucwords(str_replace('_', ' ', $d)); + return ucwords(strtolower(str_replace('_', ' ', $d))); }, $enums)); } @@ -601,8 +609,7 @@ protected function getRequestedPackageLineItemsAllInOne(ShipmentInterface $shipm ->setWeight($this->physicalWeightToFedex($shipment->getWeight())) ->setDimensions($this->packageToFedexDimensions($shipment->getPackageType())) ->setPhysicalPackaging(PhysicalPackagingType::VALUE_BOX) - ->setItemDescription($shipment_title) - ->setSpecialServicesRequested(new PackageSpecialServicesRequested()); + ->setItemDescription($shipment_title); if ($this->configuration['options']['insurance']) { $requested_package_line_item->setInsuredValue(new Money( @@ -646,8 +653,7 @@ protected function getRequestedPackageLineItemsCalculate(ShipmentInterface $ship ->setWeight($this->physicalWeightToFedex($package_weight)) ->setDimensions($this->packageToFedexDimensions($shipment->getPackageType())) ->setPhysicalPackaging(PhysicalPackagingType::VALUE_BOX) - ->setItemDescription($shipment_title) - ->setSpecialServicesRequested(new PackageSpecialServicesRequested()); + ->setItemDescription($shipment_title); if ($this->configuration['options']['insurance']) { $requested_package_line_item->setInsuredValue(new Money( @@ -680,8 +686,7 @@ protected function getRequestedPackageLineItemsIndividual(ShipmentInterface $shi ->setWeight($this->physicalWeightToFedex($shipment_item->getWeight())) ->setDimensions($this->packageToFedexDimensions($shipment->getPackageType())) ->setPhysicalPackaging(PhysicalPackagingType::VALUE_BOX) - ->setItemDescription($this->getCleanTitle($shipment_item)) - ->setSpecialServicesRequested(new PackageSpecialServicesRequested()); + ->setItemDescription($this->getCleanTitle($shipment_item)); if ($this->configuration['options']['insurance']) { $requested_package_line_item->setInsuredValue(new Money( From 0264a35534de3ecaee771298e7f0e1cfecdb751e Mon Sep 17 00:00:00 2001 From: Micheal Lutz Date: Mon, 20 Mar 2017 16:46:53 -0400 Subject: [PATCH 2/6] By mikeNCM: Finish dry ice schema file --- .../config/schema/commerce_fedex_dry_ice.yml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/modules/dry_ice/config/schema/commerce_fedex_dry_ice.yml b/modules/dry_ice/config/schema/commerce_fedex_dry_ice.yml index 5a0556f..cada769 100644 --- a/modules/dry_ice/config/schema/commerce_fedex_dry_ice.yml +++ b/modules/dry_ice/config/schema/commerce_fedex_dry_ice.yml @@ -10,4 +10,15 @@ commerce_fedex.fedex_plugin.plugin.dry_ice: type: string label: 'Package Type' weight: - type: mapping + type: field.value.physical_measurement + label: 'Weight' + intl: + type: mapping + label: 'International' + mapping: + package_type: + type: string + label: 'Package Type' + weight: + type: field.value.physical_measurement + label: 'Weight' From ae81e7671a45c9c9ac783d22a8c16b22a6a640c7 Mon Sep 17 00:00:00 2001 From: Micheal Lutz Date: Sun, 30 Apr 2017 10:53:07 -0400 Subject: [PATCH 3/6] Issue #2861378 by mikeNCM: Implement FedEx Special Services as plugins --- .../Plugin/Commerce/FedEx/DryIcePlugin.php | 135 ++++++++ src/Annotation/CommerceFedExPlugin.php | 1 + src/Plugin/Commerce/FedEx/FedExPluginBase.php | 26 ++ .../Commerce/FedEx/FedExPluginInterface.php | 30 ++ src/Plugin/Commerce/ShippingMethod/FedEx.php | 296 ++++++++++++++---- 5 files changed, 422 insertions(+), 66 deletions(-) diff --git a/modules/dry_ice/src/Plugin/Commerce/FedEx/DryIcePlugin.php b/modules/dry_ice/src/Plugin/Commerce/FedEx/DryIcePlugin.php index 6bd1e29..6f7b71c 100644 --- a/modules/dry_ice/src/Plugin/Commerce/FedEx/DryIcePlugin.php +++ b/modules/dry_ice/src/Plugin/Commerce/FedEx/DryIcePlugin.php @@ -2,10 +2,18 @@ namespace Drupal\commerce_fedex_dry_ice\Plugin\Commerce\FedEx; +use Drupal\address\Plugin\Field\FieldType\AddressItem; use Drupal\commerce_fedex\Plugin\Commerce\FedEx\FedExPluginBase; +use Drupal\commerce_fedex\Plugin\Commerce\ShippingMethod\FedEx; +use Drupal\commerce_shipping\Entity\ShipmentInterface; use Drupal\commerce_shipping\PackageTypeManagerInterface; +use Drupal\commerce_shipping\ShipmentItem; use Drupal\Core\Form\FormStateInterface; +use Drupal\physical\Weight; use Drupal\physical\WeightUnit; +use NicholasCreativeMedia\FedExPHP\Enums\PackageSpecialServiceType; +use NicholasCreativeMedia\FedExPHP\Structs\PackageSpecialServicesRequested; +use NicholasCreativeMedia\FedExPHP\Structs\RequestedPackageLineItem; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -20,6 +28,9 @@ */ class DryIcePlugin extends FedExPluginBase { + const NOT_DRY_ICE = 0; + const DRY_ICE = 1; + /** * The Package Type Manager. * @@ -144,4 +155,128 @@ public function submitConfigurationForm(array &$form, FormStateInterface $form_s } } + /** + * {@inheritdoc} + */ + public function adjustPackage(RequestedPackageLineItem $package, array $shipment_items, ShipmentInterface $shipment) { + $type = $this->getType($shipment); + if (!$this->verifyPackage($shipment_items, $type)) { + throw new \Exception("Package cannot be shipped, mix of Dry Ice and non Dry Ice Items"); + } + + if ($this->isDryIceItem(reset($shipment_items), $type)) { + $special_services_requested = $package->getSpecialServicesRequested(); + if (empty($special_services_requested)) { + $special_services_requested = new PackageSpecialServicesRequested(); + } + $dry_ice_weight = new Weight($this->configuration[$type]['weight']['number'], $this->configuration[$type]['weight']['unit']); + $special_services_requested->addToSpecialServiceTypes(PackageSpecialServiceType::VALUE_DRY_ICE); + $special_services_requested->setDryIceWeight(FedEx::physicalWeightToFedex($dry_ice_weight)); + /** @var \Drupal\commerce_shipping\Plugin\Commerce\PackageType\PackageType $package_type */ + $package_type = $this->packageTypeManager->createInstance($this->configuration[$type]['package_type']); + $package->setDimensions(Fedex::packageToFedexDimensions($package_type)); + $package->setWeight(FedEx::packageTotalWeight($shipment_items, $package_type, $dry_ice_weight)); + $package->setSpecialServicesRequested($special_services_requested); + } + $package = parent::adjustPackage($package, $shipment_items, $shipment); + return $package; + } + + /** + * {@inheritdoc} + */ + public function splitPackage(array $shipment_items, ShipmentInterface $shipment) { + $type = $this->getType($shipment); + $packages = [static::NOT_DRY_ICE => [], static::DRY_ICE => []]; + foreach ($shipment_items as $shipment_item) { + if ($this->isDryIceItem($shipment_item, $type)) { + $packages[static::DRY_ICE][] = $shipment_item; + } + else { + $packages[static::NOT_DRY_ICE][] = $shipment_item; + } + } + + return $packages; + } + + /** + * Verified a package has all dry ic eor non-dry ice items. + * + * @param array $shipment_items + * The shipment items to check. + * @param string $type + * The type, 'domestic' or 'intl' depending on the shipping distance. + * + * @return bool + * True if the package is internally consistant. + */ + protected function verifyPackage(array $shipment_items, string $type) { + $dryIceBox = $this->isDryIceBox($shipment_items, $type); + $storage = \Drupal::entityTypeManager()->getStorage('commerce_order_item'); + foreach ($shipment_items as $shipment_item) { + if ($dryIceBox xor $this->isDryIceItem($shipment_item, $type)) { + return FALSE; + } + + } + return TRUE; + } + + /** + * Determine whether a droup of shipment items requires dry ice shipping. + * + * @param array $shipment_items + * The shipment items to check. + * @param string $type + * The type, 'domestic' or 'intl' depending on the shipping distance. + * + * @return bool + * True if the package needs dry ice shipping. + */ + protected function isDryIceBox(array $shipment_items, string $type) { + return $this->isDryIceItem(reset($shipment_items), $type); + } + + /** + * Determine whether a shipment item requires dry ice shipping or not. + * + * @param \Drupal\commerce_shipping\ShipmentItem $shipment_item + * The shipment item. + * @param string $type + * The type, 'domestic' or 'intl' depending on the shipping distance. + * + * @return bool + * true if the shipment item requires dry ice shipping. + */ + protected function isDryIceItem(ShipmentItem $shipment_item, string $type) { + $storage = \Drupal::entityTypeManager()->getStorage('commerce_order_item'); + /** @var \Drupal\commerce_order\Entity\OrderItemInterface $order_item */ + $order_item = $storage->load($shipment_item->getOrderItemId()); + $purchased_entity = $order_item->getPurchasedEntity(); + return $purchased_entity->hasField('fedex_dry_ice_' . $type) && !$purchased_entity->get('fedex_dry_ice_' . $type)->isEmpty() && $purchased_entity->get('fedex_dry_ice_' . $type)->first()->getValue()['value'] == 1; + + } + + /** + * Determine if this is a domestic or international shipment. + * + * @param \Drupal\commerce_shipping\Entity\ShipmentInterface $shipment + * The shipment to check. + * + * @return string + * either 'domestic' or 'intl' + */ + protected function getType(ShipmentInterface $shipment) { + + /* @var AddressItem $shipping_address */ + $shipping_address = $shipment->getShippingProfile()->get('address')->first(); + + $domestic = ($shipping_address instanceof AddressItem) + ? $shipment->getOrder()->getStore()->getAddress()->getCountryCode() == $shipping_address->getCountryCode() + : FALSE; + + return $domestic ? 'domestic' : 'intl'; + } + } diff --git a/src/Annotation/CommerceFedExPlugin.php b/src/Annotation/CommerceFedExPlugin.php index bdcdd45..f62c7f2 100644 --- a/src/Annotation/CommerceFedExPlugin.php +++ b/src/Annotation/CommerceFedExPlugin.php @@ -48,4 +48,5 @@ class CommerceFedExPlugin extends Plugin { * @ingroup plugin_translatable */ public $options_description; + } diff --git a/src/Plugin/Commerce/FedEx/FedExPluginBase.php b/src/Plugin/Commerce/FedEx/FedExPluginBase.php index 05bfcf4..0916e08 100644 --- a/src/Plugin/Commerce/FedEx/FedExPluginBase.php +++ b/src/Plugin/Commerce/FedEx/FedExPluginBase.php @@ -2,11 +2,13 @@ namespace Drupal\commerce_fedex\Plugin\Commerce\FedEx; +use Drupal\commerce_shipping\Entity\ShipmentInterface; use Drupal\Component\Plugin\PluginBase; use Drupal\Component\Utility\NestedArray; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; +use NicholasCreativeMedia\FedExPHP\Structs\RequestedPackageLineItem; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -96,4 +98,28 @@ public function submitConfigurationForm(array &$form, FormStateInterface $form_s return $form; } + /** + * Adjust a package based on the items, shipment and profile. + * + * @param \NicholasCreativeMedia\FedExPHP\Structs\RequestedPackageLineItem $package + * The package to adjust. + * @param array $items + * An array of shipment items. + * @param \Drupal\commerce_shipping\Entity\ShipmentInterface $shipment + * The shipment. + * + * @return \NicholasCreativeMedia\FedExPHP\Structs\RequestedPackageLineItem + * The adjusted Package. + */ + public function adjustPackage(RequestedPackageLineItem $package, array $items, ShipmentInterface $shipment) { + return $package; + } + + /** + * @inheritdoc + */ + public function splitPackage(array $shipment_items, ShipmentInterface $shipment) { + return [$shipment_items]; + } + } diff --git a/src/Plugin/Commerce/FedEx/FedExPluginInterface.php b/src/Plugin/Commerce/FedEx/FedExPluginInterface.php index 75098d0..43df6f3 100644 --- a/src/Plugin/Commerce/FedEx/FedExPluginInterface.php +++ b/src/Plugin/Commerce/FedEx/FedExPluginInterface.php @@ -2,9 +2,11 @@ namespace Drupal\commerce_fedex\Plugin\Commerce\FedEx; +use Drupal\commerce_shipping\Entity\ShipmentInterface; use Drupal\Component\Plugin\ConfigurablePluginInterface; use Drupal\Component\Plugin\PluginInspectionInterface; use Drupal\Core\Plugin\PluginFormInterface; +use NicholasCreativeMedia\FedExPHP\Structs\RequestedPackageLineItem; /** * Defines the base interface for FedEx Service Plugins. @@ -13,4 +15,32 @@ */ interface FedExPluginInterface extends ConfigurablePluginInterface, PluginFormInterface, PluginInspectionInterface { + /** + * Function adjustPackage. + * + * @param \NicholasCreativeMedia\FedExPHP\Structs\RequestedPackageLineItem $package + * The package to adjust. + * @param array $items + * An array of Shipment Items. + * @param \Drupal\commerce_shipping\Entity\ShipmentInterface $shipment + * The Shipment. + * + * @return \NicholasCreativeMedia\FedExPHP\Structs\RequestedPackageLineItem + * The Adjusted Package + */ + public function adjustPackage(RequestedPackageLineItem $package, array $items, ShipmentInterface $shipment); + + /** + * Function splitPackage. + * + * @param array $shipment_items + * An Array of shipment items. + * @param \Drupal\commerce_shipping\Entity\ShipmentInterface $shipment + * The Shipment. + * + * @return array + * An array of arrays of shipment items. + */ + public function splitPackage(array $shipment_items, ShipmentInterface $shipment); + } diff --git a/src/Plugin/Commerce/ShippingMethod/FedEx.php b/src/Plugin/Commerce/ShippingMethod/FedEx.php index b7b5ee1..8ce69b7 100644 --- a/src/Plugin/Commerce/ShippingMethod/FedEx.php +++ b/src/Plugin/Commerce/ShippingMethod/FedEx.php @@ -17,11 +17,14 @@ use Drupal\commerce_shipping\ShippingRate; use Drupal\Core\Form\SubformState; use Drupal\Core\Plugin\DefaultLazyPluginCollection; +use Drupal\physical\Volume; +use Drupal\physical\VolumeUnit; use Drupal\physical\Weight as PhysicalWeight; use Drupal\physical\WeightUnit as PhysicalWeightUnits; use Drupal\physical\LengthUnit as PhysicalLengthUnits; use Drupal\Core\Form\FormStateInterface; use NicholasCreativeMedia\FedExPHP\Enums\DropoffType; +use NicholasCreativeMedia\FedExPHP\Enums\LinearUnits; use NicholasCreativeMedia\FedExPHP\Enums\PhysicalPackagingType; use NicholasCreativeMedia\FedExPHP\Enums\RateRequestType; use NicholasCreativeMedia\FedExPHP\Services\RateService; @@ -203,10 +206,7 @@ public function defaultConfiguration() { public function buildConfigurationForm(array $form, FormStateInterface $form_state) { /* @todo Remove hack when commerce issue #2859423 is resolved */ - if ($this->configuration == $this->defaultConfiguration()) { - $this->fixConfiguration($form_state); - } - + // $this->fixConfiguration($form_state); $form = parent::buildConfigurationForm($form, $form_state); // Select all services by default. @@ -330,8 +330,7 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta */ public function validateConfigurationForm(array &$form, FormStateInterface $form_state) { /* @todo Remove hack when commerce issue #2859423 is resolved */ - $this->fixConfiguration($form_state); - + // $this->fixConfiguration($form_state); parent::validateConfigurationForm($form, $form_state); foreach ($this->fedExServiceManager->getDefinitions() as $plugin_id => $definition) { @@ -348,8 +347,7 @@ public function validateConfigurationForm(array &$form, FormStateInterface $form */ public function submitConfigurationForm(array &$form, FormStateInterface $form_state) { /* @todo Remove hack when commerce issue #2859423 is resolved */ - $this->fixConfiguration($form_state); - + // $this->fixConfiguration($form_state); if (!$form_state->getErrors()) { $values = $form_state->getValue($form['#parents']); @@ -394,8 +392,13 @@ public function submitConfigurationForm(array &$form, FormStateInterface $form_s * Whether to skip the check to log or not. */ protected function logRequest($message, $data, $level = LogLevel::INFO, $skip_config_check = FALSE) { - if ($skip_config_check || $this->configuration['options']['log']['request']) { - $this->watchdog->log($level, "$message
@rate_request", [ + /* If we are using the old configuration */ + if (is_array($this->configuration['options']['log'])) { + + } + + if ($skip_config_check || @$this->configuration['options']['log']['request']) { + $this->watchdog->log($level, "$message
@rate_request
", [ '@rate_request' => var_export($data, TRUE), ]); } @@ -418,14 +421,17 @@ public function calculateRates(ShipmentInterface $shipment) { $response = $rate_service->getRates($rate_request); if (!$response) { + /** @var \SoapFault $error */ + $error = $rate_service->getLastError(); $this->logRequest('FedEx sent no response back.', $rate_request, LogLevel::NOTICE, TRUE); + return []; } else { - $this->logRequest('FedEx response received.', $rate_request); + $this->logRequest('FedEx response received.', $response); } $rates = []; - if ($response->getHighestSeverity() == 'SUCCESS') { + if ($response->getHighestSeverity() == 'SUCCESS' || ($response->getHighestSeverity() == 'WARNING' && is_array($response->getRateReplyDetails()))) { foreach ($response->getRateReplyDetails() as $rate_details) { if (in_array($rate_details->getServiceType(), array_keys($this->getServices()))) { $cost = $rate_details @@ -596,29 +602,38 @@ protected function getCleanTitle(ShipmentItem $shipment_item) { * The package line items. */ protected function getRequestedPackageLineItemsAllInOne(ShipmentInterface $shipment) { - $requested_package_line_item = new RequestedPackageLineItem(); - $shipment_title = $shipment->getTitle(); - if (!is_string($shipment_title)) { - $shipment_title = $shipment_title->render(); - } + $packages = $this->splitPackages($shipment); - $requested_package_line_item - ->setSequenceNumber(1) - ->setGroupPackageCount(1) - ->setWeight($this->physicalWeightToFedex($shipment->getWeight())) - ->setDimensions($this->packageToFedexDimensions($shipment->getPackageType())) - ->setPhysicalPackaging(PhysicalPackagingType::VALUE_BOX) - ->setItemDescription($shipment_title); + $requested_package_line_items = []; - if ($this->configuration['options']['insurance']) { - $requested_package_line_item->setInsuredValue(new Money( - $shipment->getTotalDeclaredValue()->getCurrencyCode(), - $shipment->getTotalDeclaredValue()->getNumber() - )); + foreach ($packages as $delta => $package) { + $requested_package_line_item = new RequestedPackageLineItem(); + $shipment_title = $shipment->getTitle(); + + if (!is_string($shipment_title)) { + $shipment_title = $shipment_title->render(); + } + + $requested_package_line_item + ->setSequenceNumber($delta + 1) + ->setGroupPackageCount(1) + ->setWeight(static::packageTotalWeight($package, $shipment->getPackageType())) + ->setDimensions($this->packageToFedexDimensions($shipment->getPackageType())) + ->setPhysicalPackaging(PhysicalPackagingType::VALUE_BOX) + ->setItemDescription($shipment_title); + + if ($this->configuration['options']['insurance']) { + $requested_package_line_item->setInsuredValue(new Money( + $shipment->getTotalDeclaredValue()->getCurrencyCode(), + $shipment->getTotalDeclaredValue()->getNumber() + )); + } + + $requested_package_line_items[] = $this->adjustPackage($requested_package_line_item, $package, $shipment); } - return [$requested_package_line_item]; + return $requested_package_line_items; } /** @@ -631,38 +646,18 @@ protected function getRequestedPackageLineItemsAllInOne(ShipmentInterface $shipm * The package line items. */ protected function getRequestedPackageLineItemsCalculate(ShipmentInterface $shipment) { - $package_volume = $this->getPackageVolume($shipment->getPackageType()); - $total_volume = $this->getShipmentTotalVolume($shipment); - - $count = ($total_volume == 0 || $total_volume < $package_volume) - ? 1 - : ceil($total_volume / $package_volume); - - $package_weight = $shipment->getWeight()->divide((string) $count); - - $shipment_title = $shipment->getTitle(); - if (!is_string($shipment_title)) { - $shipment_title = $shipment_title->render(); - } - - $requested_package_line_item = new RequestedPackageLineItem(); - - $requested_package_line_item - ->setGroupNumber(1) - ->setGroupPackageCount($count) - ->setWeight($this->physicalWeightToFedex($package_weight)) - ->setDimensions($this->packageToFedexDimensions($shipment->getPackageType())) - ->setPhysicalPackaging(PhysicalPackagingType::VALUE_BOX) - ->setItemDescription($shipment_title); - - if ($this->configuration['options']['insurance']) { - $requested_package_line_item->setInsuredValue(new Money( - $shipment->getTotalDeclaredValue()->getCurrencyCode(), - $shipment->getTotalDeclaredValue()->getNumber() - )); + $requested_package_line_items = $this->getRequestedPackageLineItemsAllInOne($shipment); + $packages = $this->splitPackages($shipment); + foreach ($requested_package_line_items as &$requested_package_line_item) { + /** @var \NicholasCreativeMedia\FedExPHP\Structs\RequestedPackageLineItem $requested_package_line_item */ + $count = static::calculatePackageCount($requested_package_line_item, $packages[$requested_package_line_item->getSequenceNumber() - 1]); + if ($count) { + $requested_package_line_item->setGroupPackageCount($count); + $requested_package_line_item->getWeight()->setValue($requested_package_line_item->getWeight()->getValue() / $count); + } } - return [$requested_package_line_item]; + return $requested_package_line_items; } /** @@ -676,14 +671,18 @@ protected function getRequestedPackageLineItemsCalculate(ShipmentInterface $ship */ protected function getRequestedPackageLineItemsIndividual(ShipmentInterface $shipment) { $requested_package_line_items = []; - + $weightUnits = ''; foreach ($shipment->getItems() as $delta => $shipment_item) { $requested_package_line_item = new RequestedPackageLineItem(); + if ($weightUnits == '') { + /* All packages must have the same Weight Unit */ + $weightUnits = $shipment_item->getWeight()->getUnit(); + } $requested_package_line_item ->setSequenceNumber($delta + 1) ->setGroupPackageCount(1) - ->setWeight($this->physicalWeightToFedex($shipment_item->getWeight())) + ->setWeight($this->physicalWeightToFedex($shipment_item->getWeight()->convert($weightUnits))) ->setDimensions($this->packageToFedexDimensions($shipment->getPackageType())) ->setPhysicalPackaging(PhysicalPackagingType::VALUE_BOX) ->setItemDescription($this->getCleanTitle($shipment_item)); @@ -694,7 +693,7 @@ protected function getRequestedPackageLineItemsIndividual(ShipmentInterface $shi $shipment_item->getDeclaredValue()->getNumber() )); } - + // $this->adjustPackage($requested_package_line_item, [$shipment_item], $shipment);. $requested_package_line_items[] = $requested_package_line_item; } @@ -724,7 +723,6 @@ protected function getFedExShipment(ShipmentInterface $shipment) { $fedex_shipment = new RequestedShipment(); $fedex_shipment - ->setTotalWeight($this->physicalWeightToFedex($shipment->getWeight())) ->setShipper($this->getAddressForFedEx($shipper_address)) ->setRecipient($this->getAddressForFedEx($recipient_address)) ->setRequestedPackageLineItems($line_items) @@ -744,6 +742,51 @@ protected function getFedExShipment(ShipmentInterface $shipment) { return $fedex_shipment; } + /** + * Queries plugins to split shipments into fedex packages. + * + * @param \Drupal\commerce_shipping\Entity\ShipmentInterface $shipment + * The shipment to split. + * + * @return array + * An array of arrays or shipment items. + */ + protected function splitPackages(ShipmentInterface $shipment) { + $packages = [$shipment->getItems()]; + foreach ($this->fedExServiceManager->getDefinitions() as $plugin_id => $definition) { + /** @var \Drupal\commerce_fedex\Plugin\Commerce\FedEx\FedExPluginInterface $plugin */ + $plugin = $this->plugins->get($plugin_id); + $new_packages = []; + foreach ($packages as $package) { + $new_packages = array_merge($new_packages, $plugin->splitPackage($package, $shipment)); + } + $packages = array_filter($new_packages); + } + return $packages; + } + + /** + * Query plugins for package adjustments. + * + * @param \NicholasCreativeMedia\FedExPHP\Structs\RequestedPackageLineItem $requested_package_line_item + * Te package line item to be adjusted. + * @param array $shipment_items + * The shipment items in the package. + * @param \Drupal\commerce_shipping\Entity\ShipmentInterface $shipment + * The full shipment. + * + * @return \NicholasCreativeMedia\FedExPHP\Structs\RequestedPackageLineItem + * The adjusted line item. + */ + protected function adjustPackage(RequestedPackageLineItem $requested_package_line_item, array $shipment_items, ShipmentInterface $shipment) { + foreach ($this->fedExServiceManager->getDefinitions() as $plugin_id => $definition) { + /** @var \Drupal\commerce_fedex\Plugin\Commerce\FedEx\FedExPluginInterface $plugin */ + $plugin = $this->plugins->get($plugin_id); + $requested_package_line_item = $plugin->adjustPackage($requested_package_line_item, $shipment_items, $shipment); + } + return $requested_package_line_item; + } + /** * Gets a rate request object for FedEx. * @@ -767,6 +810,54 @@ protected function getRateRequest(RateService $rate_service, ShipmentInterface $ return $rate_request; } + /** + * + */ + protected static function getPackageTotalVolume(array $shipment_items, $volume_unit) { + switch ($volume_unit) { + case VolumeUnit::CUBIC_CENTIMETER: + $linear_unit = PhysicalLengthUnits::CENTIMETER; + break; + + case VolumeUnit::CUBIC_INCH: + $linear_unit = PhysicalLengthUnits::INCH; + break; + + default: + throw new \Exception("Invalid Units"); + } + $order_item_storage = \Drupal::entityTypeManager()->getStorage('commerce_order_item'); + $order_item_ids = []; + foreach ($shipment_items as $shipment_item) { + $order_item_ids[] = $shipment_item->getOrderItemId(); + } + + $order_items = $order_item_storage->loadMultiple($order_item_ids); + + $total_volume = 0; + foreach ($order_items as $order_item) { + /** @var \Drupal\commerce_order\Entity\OrderItem $order_item */ + /** @var \Drupal\commerce_product\Entity\ProductVariationInterface $purchased_entity */ + $purchased_entity = $order_item->getPurchasedEntity(); + + if ($purchased_entity->hasField('dimensions') && !$purchased_entity->get('dimensions')->isEmpty()) { + /** @var \Drupal\physical\Plugin\Field\FieldType\DimensionsItem $dimensions */ + $dimensions = $purchased_entity->get('dimensions')->first(); + + $volume = $dimensions + ->getHeight() + ->convert($linear_unit) + ->multiply($dimensions->getWidth()->convert($linear_unit)->getNumber()) + ->multiply($dimensions->getLength()->convert($linear_unit)->getNumber()) + ->getNumber(); + + $total_volume += (float) $volume * $order_item->getQuantity(); + } + } + + return new Volume((string) $total_volume, $volume_unit); + } + /** * Gets the shipment's total volume in the same units as the package type. * @@ -838,7 +929,7 @@ protected function isConfigured() { * * @throws \Exception */ - protected function physicalWeightToFedex(PhysicalWeight $weight) { + public static function physicalWeightToFedex(PhysicalWeight $weight) { if (!$weight instanceof PhysicalWeight) { throw new \Exception("Invalid units for weight"); } @@ -882,7 +973,7 @@ protected function physicalWeightToFedex(PhysicalWeight $weight) { * * @throws \Exception */ - protected function packageToFedexDimensions(PackageTypeInterface $package) { + public static function packageToFedexDimensions(PackageTypeInterface $package) { $length = $package->getLength(); $width = $package->getWidth(); $height = $package->getHeight(); @@ -985,4 +1076,77 @@ private function fixConfiguration(FormStateInterface $form_state) { } } + /** + * Function packageTotalWeight. + * + * @param array $shipment_items + * An array of shipment items. + * @param \Drupal\commerce_shipping\Plugin\Commerce\PackageType\PackageTypeInterface $package_type + * The commerce_shipping package type. + * @param \Drupal\physical\Weight|null $adjustment + * Any weight adjustment to add or subtract. + * + * @return \NicholasCreativeMedia\FedExPHP\Structs\Weight + * The total weight of the package. + */ + public static function packageTotalWeight(array $shipment_items, PackageTypeInterface $package_type, $adjustment = NULL) { + + if (empty($shipment_items)) { + return new FedexWeight('LB', 0); + } + + $storage = \Drupal::entityTypeManager()->getStorage('commerce_order_item'); + $unit = $storage->load(reset($shipment_items)->getOrderItemId())->getPurchasedEntity()->weight->first()->toMeasurement()->getUnit(); + $total_weight = new PhysicalWeight("0", $unit); + foreach ($shipment_items as $shipment_item) { + /* @var ShipmentItem $shipment_item */ + /* @var \Drupal\commerce_order\Entity\OrderItem $order_item */ + $order_item = $storage->load($shipment_item->getOrderItemId()); + $purchased_entity = $order_item->getPurchasedEntity(); + $order_item_weight = $purchased_entity->weight->first()->toMeasurement() + ->convert($unit) + ->multiply($order_item->getQuantity()); + $total_weight = $total_weight->add($order_item_weight); + } + $total_weight = $total_weight->add($package_type->getWeight()->convert($unit)); + if ($adjustment) { + $total_weight = $total_weight->add($adjustment->convert($unit)); + } + return static::physicalWeightToFedex($total_weight); + } + + /** + * + */ + public static function calculatePackageCount(RequestedPackageLineItem $requested_package_line_item, array $shipment_items) { + $package_volume = static::getFedexPackageVolume($requested_package_line_item->getDimensions()); + $items_volume = static::getPackageTotalVolume($shipment_items, $package_volume->getUnit()); + + if ($package_volume->getNumber() != 0) { + return ceil($items_volume->getNumber() / $package_volume->getNumber()); + } + return FALSE; + + } + + /** + * + */ + public static function getFedexPackageVolume(Dimensions $dimensions) { + $volume_value = $dimensions->getHeight() * $dimensions->getLength() * $dimensions->getWidth(); + switch ($dimensions->getUnits()) { + case LinearUnits::VALUE_CM: + $volume_units = VolumeUnit::CUBIC_CENTIMETER; + break; + + case LinearUnits::VALUE_IN: + $volume_units = VolumeUnit::CUBIC_INCH; + break; + + default: + throw new \Exception("Invalid Dimensions"); + } + return new Volume((string) $volume_value, $volume_units); + } + } From d537b572c505c07822d5a8756587ff657fe52485 Mon Sep 17 00:00:00 2001 From: Micheal Lutz Date: Sat, 6 May 2017 23:21:22 -0400 Subject: [PATCH 4/6] Issue #2861378 by mikeNCM: Implement FedEx Special Services as plugins --- .../schema/commerce_fedex_dangerous.yml | 7 ++ .../Commerce/FedEx/DangerousGoodsPlugin.php | 65 ++++++++++++++++++- src/Plugin/Commerce/FedEx/FedExPluginBase.php | 2 +- src/Plugin/Commerce/ShippingMethod/FedEx.php | 13 +++- 4 files changed, 82 insertions(+), 5 deletions(-) create mode 100644 modules/dangerous/config/schema/commerce_fedex_dangerous.yml diff --git a/modules/dangerous/config/schema/commerce_fedex_dangerous.yml b/modules/dangerous/config/schema/commerce_fedex_dangerous.yml new file mode 100644 index 0000000..a709275 --- /dev/null +++ b/modules/dangerous/config/schema/commerce_fedex_dangerous.yml @@ -0,0 +1,7 @@ +commerce_fedex.fedex_plugin.plugin.dangerous: + type: commerce_fedex_service + label: 'Commerce Fedex Dry Ice Service' + mapping: + contact_number: + type: string + label: 'Contact Number' diff --git a/modules/dangerous/src/Plugin/Commerce/FedEx/DangerousGoodsPlugin.php b/modules/dangerous/src/Plugin/Commerce/FedEx/DangerousGoodsPlugin.php index b5e813b..358c7f8 100644 --- a/modules/dangerous/src/Plugin/Commerce/FedEx/DangerousGoodsPlugin.php +++ b/modules/dangerous/src/Plugin/Commerce/FedEx/DangerousGoodsPlugin.php @@ -3,8 +3,13 @@ namespace Drupal\commerce_fedex_dangerous\Plugin\Commerce\FedEx; use Drupal\commerce_fedex\Plugin\Commerce\FedEx\FedExPluginBase; +use Drupal\commerce_shipping\Entity\ShipmentInterface; +use Drupal\commerce_shipping\ShipmentItem; use Drupal\Core\Form\FormStateInterface; -use Drupal\Core\Form\SubformState; +use NicholasCreativeMedia\FedExPHP\Enums\PackageSpecialServiceType; +use NicholasCreativeMedia\FedExPHP\Structs\DangerousGoodsDetail; +use NicholasCreativeMedia\FedExPHP\Structs\PackageSpecialServicesRequested; +use NicholasCreativeMedia\FedExPHP\Structs\RequestedPackageLineItem; /** * Providex the FedEx Dangerous Goods Service Plugin. @@ -17,6 +22,7 @@ * ) */ class DangerousGoodsPlugin extends FedExPluginBase { + const NOT_DANGEROUS = 0; /** * {@inheritdoc} @@ -48,4 +54,61 @@ public function submitConfigurationForm(array &$form, FormStateInterface $form_s $this->configuration['contact_number'] = $form_state->getValue('contact_number'); } + /** + * {@inheritdoc} + */ + public function adjustPackage(RequestedPackageLineItem $package, array $shipment_items, ShipmentInterface $shipment) { + $status = $this->getDangerousStatus(reset($shipment_items)); + + if ($status === static::NOT_DANGEROUS) { + return $package; + } + + $special_services_requested = $package->getSpecialServicesRequested(); + if (empty($special_services_requested)) { + $special_services_requested = new PackageSpecialServicesRequested(); + } + $special_services_requested->addToSpecialServiceTypes(PackageSpecialServiceType::VALUE_DANGEROUS_GOODS); + $dangerous_goods_detail = $special_services_requested->getDangerousGoodsDetail(); + if (empty($dangerous_goods_detail)) { + $dangerous_goods_detail = new DangerousGoodsDetail(); + } + $dangerous_goods_detail->setAccessibility($status); + $special_services_requested->setDangerousGoodsDetail($dangerous_goods_detail); + $package->setSpecialServicesRequested($special_services_requested); + + return $package; + } + + /** + * {@inheritdoc} + */ + public function splitPackage(array $shipment_items, ShipmentInterface $shipment) { + $packages = []; + foreach ($shipment_items as $shipment_item) { + $packages[$this->getDangerousStatus($shipment_item)][] = $shipment_item; + } + return array_values($packages); + } + + /** + * Returns the DG status of an item. + * + * @param \Drupal\commerce_shipping\ShipmentItem $shipment_item + * The item to check. + * + * @return mixed + * The DG status. + */ + protected function getDangerousStatus(ShipmentItem $shipment_item) { + $storage = \Drupal::entityTypeManager()->getStorage('commerce_order_item'); + /** @var \Drupal\commerce_order\Entity\OrderItemInterface $order_item */ + $order_item = $storage->load($shipment_item->getOrderItemId()); + $purchased_entity = $order_item->getPurchasedEntity(); + if (!$purchased_entity->hasField('fedex_dangerous_accessibility') || $purchased_entity->get('fedex_dangerous_accessibility')->isEmpty()) { + return static::NOT_DANGEROUS; + } + return $purchased_entity->get('fedex_dangerous_accessibility')->value; + } + } diff --git a/src/Plugin/Commerce/FedEx/FedExPluginBase.php b/src/Plugin/Commerce/FedEx/FedExPluginBase.php index 0916e08..907c7e8 100644 --- a/src/Plugin/Commerce/FedEx/FedExPluginBase.php +++ b/src/Plugin/Commerce/FedEx/FedExPluginBase.php @@ -116,7 +116,7 @@ public function adjustPackage(RequestedPackageLineItem $package, array $items, S } /** - * @inheritdoc + * {@inheritdoc} */ public function splitPackage(array $shipment_items, ShipmentInterface $shipment) { return [$shipment_items]; diff --git a/src/Plugin/Commerce/ShippingMethod/FedEx.php b/src/Plugin/Commerce/ShippingMethod/FedEx.php index 7146200..1537210 100644 --- a/src/Plugin/Commerce/ShippingMethod/FedEx.php +++ b/src/Plugin/Commerce/ShippingMethod/FedEx.php @@ -755,9 +755,16 @@ protected function getRequestedPackageLineItemsIndividual(ShipmentInterface $shi protected function getFedExShipment(ShipmentInterface $shipment) { $line_items = $this->getRequestedPackageLineItems($shipment); - $count = ($this->configuration['options']['packaging'] == static::PACKAGE_CALCULATE) - ? $line_items[0]->getGroupPackageCount() - : count($line_items); + if ($this->configuration['options']['packaging'] == static::PACKAGE_CALCULATE) { + $count = 0; + foreach ($line_items as $line_item) { + $count += $line_item->getGroupPackageCount(); + } + } + else { + $count = count($line_items); + } + /** @var \Drupal\address\AddressInterface $recipient_address */ $recipient_address = $shipment->getShippingProfile()->get('address')->first(); From 3a0f9ed329b963a76ad6127ed7fc5eced7c71dab Mon Sep 17 00:00:00 2001 From: mdlutz Date: Mon, 8 May 2017 23:47:47 -0400 Subject: [PATCH 5/6] Issue #2876815 by mikeNCM: Create test suite --- tests/src/Unit/FedExRequestTest.php | 89 +++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 tests/src/Unit/FedExRequestTest.php diff --git a/tests/src/Unit/FedExRequestTest.php b/tests/src/Unit/FedExRequestTest.php new file mode 100644 index 0000000..82422ac --- /dev/null +++ b/tests/src/Unit/FedExRequestTest.php @@ -0,0 +1,89 @@ +request = new FedExRequest(); + $this->configuration = [ + 'api_information' => [ + 'api_key' => 'testkey', + 'api_password' => 'testpass', + 'account_number' => '1234567', + 'meter_number' => '9876543', + 'mode' => 'test', + ], + ]; + } + + /** + * @covers ::getRateRequest + */ + public function testRateRequest() { + + $rate_request = $this->request->getRateRequest($this->configuration); + $this->assertInstanceOf("\NicholasCreativeMedia\FedExPHP\Structs\RateRequest", $rate_request); + + $client_detail = $rate_request->getClientDetail(); + $this->assertInstanceOf("\NicholasCreativeMedia\FedExPHP\Structs\ClientDetail", $client_detail); + $this->assertEquals('1234567', $client_detail->getAccountNumber()); + $this->assertEquals('9876543', $client_detail->getMeterNumber()); + + $web_authentication_detail = $rate_request->getWebAuthenticationDetail(); + $this->assertInstanceOf("\NicholasCreativeMedia\FedExPHP\Structs\WebAuthenticationDetail", $web_authentication_detail); + + $user_credential = $web_authentication_detail->getUserCredential(); + $this->assertInstanceOf("\NicholasCreativeMedia\FedExPHP\Structs\WebAuthenticationCredential", $user_credential); + + $this->assertEquals('testkey', $user_credential->getKey()); + $this->assertEquals('testpass', $user_credential->getPassword()); + } + + /** + * @covers ::getRateService + */ + public function testRateService() { + $rate_service = $this->request->getRateService($this->configuration); + $this->assertInstanceOf("\NicholasCreativeMedia\FedExPHP\Services\RateService", $rate_service); + + /** @var \NicholasCreativeMedia\FedExPHP\Structs\VersionId $version */ + $version = $rate_service->version; + $this->assertInstanceOf("\NicholasCreativeMedia\FedExPHP\Structs\VersionId", $version); + + $this->assertEquals(static::RATE_SERVICE_SERVICE_ID, $version->getServiceId()); + $this->assertEquals(static::RATE_SERVICE_MAJOR_VERSION, $version->getMajor()); + } + +} From 7d01a419478338b79cd2f14219946202f1088fef Mon Sep 17 00:00:00 2001 From: bmcclure Date: Fri, 12 May 2017 13:39:38 -0500 Subject: [PATCH 6/6] Issue #2878092 by bmcclure: "Each item in its own box" combines items with a qty higher than 1 --- src/Plugin/Commerce/ShippingMethod/FedEx.php | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/Plugin/Commerce/ShippingMethod/FedEx.php b/src/Plugin/Commerce/ShippingMethod/FedEx.php index 6885d95..e70722d 100644 --- a/src/Plugin/Commerce/ShippingMethod/FedEx.php +++ b/src/Plugin/Commerce/ShippingMethod/FedEx.php @@ -736,12 +736,12 @@ protected function getRequestedPackageLineItemsIndividual(ShipmentInterface $shi $requested_package_line_items = []; foreach ($shipment->getItems() as $delta => $shipment_item) { + $qty = $shipment_item->getQuantity(); $requested_package_line_item = new RequestedPackageLineItem(); - $requested_package_line_item ->setSequenceNumber($delta + 1) - ->setGroupPackageCount(1) - ->setWeight($this->physicalWeightToFedex($shipment_item->getWeight())) + ->setGroupPackageCount($qty) + ->setWeight($this->physicalWeightToFedex($shipment_item->getWeight()->divide($qty))) ->setDimensions($this->packageToFedexDimensions($shipment->getPackageType())) ->setPhysicalPackaging(PhysicalPackagingType::VALUE_BOX) ->setItemDescription($this->getCleanTitle($shipment_item)) @@ -772,9 +772,10 @@ protected function getRequestedPackageLineItemsIndividual(ShipmentInterface $shi protected function getFedExShipment(ShipmentInterface $shipment) { $line_items = $this->getRequestedPackageLineItems($shipment); - $count = ($this->configuration['options']['packaging'] == static::PACKAGE_CALCULATE) - ? $line_items[0]->getGroupPackageCount() - : count($line_items); + $count = 0; + foreach ($line_items as $index => $line_item) { + $count += $line_item->getGroupPackageCount(); + } /** @var \Drupal\address\AddressInterface $recipient_address */ $recipient_address = $shipment->getShippingProfile()->get('address')->first();