diff --git a/app/code/Magento/Braintree/Gateway/Config/Config.php b/app/code/Magento/Braintree/Gateway/Config/Config.php index 59cd8f7a75aa3f66fe3e4b3c4b1fc71c0113189a..774b8e365368f0f843c239ffeaaa3855dd7249e8 100644 --- a/app/code/Magento/Braintree/Gateway/Config/Config.php +++ b/app/code/Magento/Braintree/Gateway/Config/Config.php @@ -193,4 +193,14 @@ class Config extends \Magento\Payment\Gateway\Config\Config } return $values; } + + /** + * Get Merchant account ID + * + * @return string + */ + public function getMerchantAccountId() + { + return $this->getValue(self::KEY_MERCHANT_ACCOUNT_ID); + } } diff --git a/app/code/Magento/Braintree/Gateway/Request/PaymentDataBuilder.php b/app/code/Magento/Braintree/Gateway/Request/PaymentDataBuilder.php index 9591d24465487d686771274abf0f800f9e2b337f..dd038e1f9f259304ff7f297732dbe0fad159fbae 100644 --- a/app/code/Magento/Braintree/Gateway/Request/PaymentDataBuilder.php +++ b/app/code/Magento/Braintree/Gateway/Request/PaymentDataBuilder.php @@ -87,7 +87,7 @@ class PaymentDataBuilder implements BuilderInterface self::ORDER_ID => $order->getOrderIncrementId() ]; - $merchantAccountId = $this->config->getValue(Config::KEY_MERCHANT_ACCOUNT_ID); + $merchantAccountId = $this->config->getMerchantAccountId(); if (!empty($merchantAccountId)) { $result[self::MERCHANT_ACCOUNT_ID] = $merchantAccountId; } diff --git a/app/code/Magento/Braintree/Model/Ui/ConfigProvider.php b/app/code/Magento/Braintree/Model/Ui/ConfigProvider.php index 77c83707bfc67aefb45f3ce5bb99b6183ac012e9..76788c3c1451073f0ecff3ca578ce384b98d1886 100644 --- a/app/code/Magento/Braintree/Model/Ui/ConfigProvider.php +++ b/app/code/Magento/Braintree/Model/Ui/ConfigProvider.php @@ -5,6 +5,7 @@ */ namespace Magento\Braintree\Model\Ui; +use Magento\Braintree\Gateway\Request\PaymentDataBuilder; use Magento\Checkout\Model\ConfigProviderInterface; use Magento\Braintree\Gateway\Config\Config; use Magento\Braintree\Model\Adapter\BraintreeAdapter; @@ -86,7 +87,14 @@ final class ConfigProvider implements ConfigProviderInterface public function getClientToken() { if (empty($this->clientToken)) { - $this->clientToken = $this->adapter->generate(); + $params = []; + + $merchantAccountId = $this->config->getMerchantAccountId(); + if (!empty($merchantAccountId)) { + $params[PaymentDataBuilder::MERCHANT_ACCOUNT_ID] = $merchantAccountId; + } + + $this->clientToken = $this->adapter->generate($params); } return $this->clientToken; diff --git a/app/code/Magento/Braintree/Test/Unit/Gateway/Request/PaymentDataBuilderTest.php b/app/code/Magento/Braintree/Test/Unit/Gateway/Request/PaymentDataBuilderTest.php index 47a9a49670eb43dca9a36270c7f074d444970227..7d30651c69e4230fd2a54ffa5250ad176a5792be 100644 --- a/app/code/Magento/Braintree/Test/Unit/Gateway/Request/PaymentDataBuilderTest.php +++ b/app/code/Magento/Braintree/Test/Unit/Gateway/Request/PaymentDataBuilderTest.php @@ -133,8 +133,7 @@ class PaymentDataBuilderTest extends \PHPUnit_Framework_TestCase ->willReturnMap($additionalData); $this->configMock->expects(static::once()) - ->method('getValue') - ->with(Config::KEY_MERCHANT_ACCOUNT_ID) + ->method('getMerchantAccountId') ->willReturn(self::MERCHANT_ACCOUNT_ID); $this->paymentDO->expects(static::once()) diff --git a/app/code/Magento/Braintree/Test/Unit/Model/Ui/ConfigProviderTest.php b/app/code/Magento/Braintree/Test/Unit/Model/Ui/ConfigProviderTest.php index 9147b0632583ab050f5cb76447bc61acdaea4950..04846f369eba9621f14baba9cec0d6cb7b455e0a 100644 --- a/app/code/Magento/Braintree/Test/Unit/Model/Ui/ConfigProviderTest.php +++ b/app/code/Magento/Braintree/Test/Unit/Model/Ui/ConfigProviderTest.php @@ -18,8 +18,8 @@ use PHPUnit_Framework_MockObject_MockObject as MockObject; class ConfigProviderTest extends \PHPUnit_Framework_TestCase { const SDK_URL = 'https://js.braintreegateway.com/v2/braintree.js'; - const CLIENT_TOKEN = 'token'; + const MERCHANT_ACCOUNT_ID = '245345'; /** * @var Config|MockObject @@ -76,11 +76,17 @@ class ConfigProviderTest extends \PHPUnit_Framework_TestCase /** * @covers \Magento\Braintree\Model\Ui\ConfigProvider::getClientToken + * @dataProvider getClientTokenDataProvider */ - public function testGetClientToken() + public function testGetClientToken($merchantAccountId, $params) { + $this->config->expects(static::once()) + ->method('getMerchantAccountId') + ->willReturn($merchantAccountId); + $this->braintreeAdapter->expects(static::once()) ->method('generate') + ->with($params) ->willReturn(self::CLIENT_TOKEN); static::assertEquals(self::CLIENT_TOKEN, $this->configProvider->getClientToken()); @@ -140,4 +146,21 @@ class ConfigProviderTest extends \PHPUnit_Framework_TestCase ] ]; } + + /** + * @return array + */ + public function getClientTokenDataProvider() + { + return [ + [ + 'merchantAccountId' => '', + 'params' => [] + ], + [ + 'merchantAccountId' => self::MERCHANT_ACCOUNT_ID, + 'params' => ['merchantAccountId' => self::MERCHANT_ACCOUNT_ID] + ] + ]; + } } diff --git a/app/code/Magento/Catalog/i18n/en_US.csv b/app/code/Magento/Catalog/i18n/en_US.csv index 8c412dace45354da7b6056d396c7168156f2d446..2ad2194b36466b0112afc78880ff91249a7ca6af 100644 --- a/app/code/Magento/Catalog/i18n/en_US.csv +++ b/app/code/Magento/Catalog/i18n/en_US.csv @@ -701,6 +701,7 @@ Image,Image "Allowed file types: jpeg, gif, png.","Allowed file types: jpeg, gif, png." "Image Opacity","Image Opacity" "Example format: 200x300.","Example format: 200x300." +"This value does not follow the specified format (for example, 200X300).","This value does not follow the specified format (for example, 200X300)." "Image Position","Image Position" Small,Small "Attribute Label","Attribute Label" diff --git a/app/code/Magento/Catalog/view/adminhtml/ui_component/design_config_form.xml b/app/code/Magento/Catalog/view/adminhtml/ui_component/design_config_form.xml index dc8ced173bc544b9b1aa24324b1294479374805d..9852ad74121c8c30f852600783a4fb91ab84ce61 100644 --- a/app/code/Magento/Catalog/view/adminhtml/ui_component/design_config_form.xml +++ b/app/code/Magento/Catalog/view/adminhtml/ui_component/design_config_form.xml @@ -55,12 +55,13 @@ <field name="watermark_image_size"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Catalog/component/image-size-field</item> <item name="label" xsi:type="string" translate="true">Image Size</item> <item name="dataType" xsi:type="string">text</item> <item name="formElement" xsi:type="string">input</item> <item name="dataScope" xsi:type="string">watermark_image_size</item> <item name="validation" xsi:type="array"> - <item name="validate-digits" xsi:type="boolean">true</item> + <item name="validate-image-size-range" xsi:type="boolean">true</item> </item> <item name="notice" xsi:type="string" translate="true">Example format: 200x300.</item> </item> @@ -118,12 +119,13 @@ <field name="watermark_thumbnail_size"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Catalog/component/image-size-field</item> <item name="label" xsi:type="string" translate="true">Image Size</item> <item name="dataType" xsi:type="string">text</item> <item name="formElement" xsi:type="string">input</item> <item name="dataScope" xsi:type="string">watermark_thumbnail_size</item> <item name="validation" xsi:type="array"> - <item name="validate-digits" xsi:type="boolean">true</item> + <item name="validate-image-size-range" xsi:type="boolean">true</item> </item> <item name="notice" xsi:type="string" translate="true">Example format: 200x300.</item> </item> @@ -181,12 +183,13 @@ <field name="watermark_small_image_size"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Catalog/component/image-size-field</item> <item name="label" xsi:type="string" translate="true">Image Size</item> <item name="dataType" xsi:type="string">text</item> <item name="formElement" xsi:type="string">input</item> <item name="dataScope" xsi:type="string">watermark_small_image_size</item> <item name="validation" xsi:type="array"> - <item name="validate-digits" xsi:type="boolean">true</item> + <item name="validate-image-size-range" xsi:type="boolean">true</item> </item> <item name="notice" xsi:type="string" translate="true">Example format: 200x300.</item> </item> diff --git a/app/code/Magento/Catalog/view/adminhtml/web/component/image-size-field.js b/app/code/Magento/Catalog/view/adminhtml/web/component/image-size-field.js new file mode 100644 index 0000000000000000000000000000000000000000..b330ccfd8c12531d4945fad1ea255bdee23a6404 --- /dev/null +++ b/app/code/Magento/Catalog/view/adminhtml/web/component/image-size-field.js @@ -0,0 +1,42 @@ +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'jquery', + 'Magento_Ui/js/lib/validation/utils', + 'Magento_Ui/js/form/element/abstract', + 'Magento_Ui/js/lib/validation/validator' +], function ($, utils, Abstract, validator) { + 'use strict'; + + validator.addRule( + 'validate-image-size-range', + function (value) { + var dataAttrRange = /^(\d+)x(\d+)$/, + m; + + if (utils.isEmptyNoTrim(value)) { + return true; + } + + m = dataAttrRange.exec(value); + + return !!(m && m[1] > 0 && m[2] > 0); + }, + $.mage.__('This value does not follow the specified format (for example, 200X300).') + ); + + return Abstract.extend({ + + /** + * Checks for relevant value + * + * @returns {Boolean} + */ + isRangeCorrect: function () { + return validator('validate-image-size-range', this.value()).passed; + } + }); +}); diff --git a/app/code/Magento/CatalogImportExport/Model/Export/Product.php b/app/code/Magento/CatalogImportExport/Model/Export/Product.php index 73551f332d140e0561dc5c481e9e6b0343f90f85..02953743662ebbfe52124c2b760258361810cd6f 100644 --- a/app/code/Magento/CatalogImportExport/Model/Export/Product.php +++ b/app/code/Magento/CatalogImportExport/Model/Export/Product.php @@ -1284,6 +1284,14 @@ class Product extends \Magento\ImportExport\Model\Export\Entity\AbstractEntity $row['max_characters'] = $option['max_characters']; } + foreach (['file_extension', 'image_size_x', 'image_size_y'] as $fileOptionKey) { + if (!isset($option[$fileOptionKey])) { + continue; + } + + $row[$fileOptionKey] = $option[$fileOptionKey]; + } + $values = $option->getValues(); if ($values) { diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php index cb4a603f54577edaa59412f89cb56298fde7350b..d78376e2d1479c336a7de99996648fdce8edd3b9 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php @@ -105,6 +105,7 @@ class Option extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity 'radio' => true, 'checkbox' => true, 'multiple' => true, + 'file' => ['sku', 'file_extension', 'image_size_x', 'image_size_y'], ]; /** @@ -1136,6 +1137,28 @@ class Option extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity $result[$this->columnMaxCharacters] = $optionRow['max_characters']; } + $result = $this->addFileOptions($result, $optionRow); + + return $result; + } + + /** + * Add file options + * + * @param array $result + * @param array $optionRow + * @return array + */ + private function addFileOptions($result, $optionRow) + { + foreach (['file_extension', 'image_size_x', 'image_size_y'] as $fileOptionKey) { + if (!isset($optionRow[$fileOptionKey])) { + continue; + } + + $result[self::COLUMN_PREFIX . $fileOptionKey] = $optionRow[$fileOptionKey]; + } + return $result; } diff --git a/app/code/Magento/CatalogInventory/Setup/InstallSchema.php b/app/code/Magento/CatalogInventory/Setup/InstallSchema.php index 67a126f4a20fc07f033c7ee13d243ca0cf54bd73..a19eb9d1cc57344e6f2fcce5f94b81be113cc84f 100644 --- a/app/code/Magento/CatalogInventory/Setup/InstallSchema.php +++ b/app/code/Magento/CatalogInventory/Setup/InstallSchema.php @@ -249,7 +249,7 @@ class InstallSchema implements InstallSchemaInterface \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT, 5, ['unsigned' => true, 'nullable' => false, 'default' => 0], - 'Is Divided into Multiple Boxes for Shipping' + 'Website ID' ) ->addIndex( $installer->getIdxName( diff --git a/app/code/Magento/CatalogInventory/etc/module.xml b/app/code/Magento/CatalogInventory/etc/module.xml index 5c7ade1e83cda16993fe5ea84bbe7d956923dc3d..2224da524fccc1029bd42e588b0696c65efd0408 100644 --- a/app/code/Magento/CatalogInventory/etc/module.xml +++ b/app/code/Magento/CatalogInventory/etc/module.xml @@ -6,7 +6,7 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> - <module name="Magento_CatalogInventory" setup_version="2.0.0"> + <module name="Magento_CatalogInventory" setup_version="2.0.1"> <sequence> <module name="Magento_Catalog"/> </sequence> diff --git a/app/code/Magento/Checkout/view/frontend/web/js/region-updater.js b/app/code/Magento/Checkout/view/frontend/web/js/region-updater.js index c51fa8fa16bfbddb017fcd743db580ed7587206a..e06b8922b2252fd497db66a79db35af8c543db09 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/region-updater.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/region-updater.js @@ -25,6 +25,10 @@ define([ isMultipleCountriesAllowed: true }, + /** + * + * @private + */ _create: function () { this._initCountryElement(); @@ -43,12 +47,18 @@ define([ }, this)); }, - _initCountryElement: function() { + /** + * + * @private + */ + _initCountryElement: function () { + if (this.options.isMultipleCountriesAllowed) { this.element.parents('div.field').show(); this.element.on('change', $.proxy(function (e) { this._updateRegion($(e.target).val()); }, this)); + if (this.options.isCountryRequired) { this.element.addClass('required-entry'); this.element.parents('div.field').addClass('required'); @@ -60,6 +70,7 @@ define([ /** * Remove options from dropdown list + * * @param {Object} selectElement - jQuery object for dropdown list * @private */ @@ -113,7 +124,7 @@ define([ * @private */ _clearError: function () { - if (this.options.clearError && typeof (this.options.clearError) === 'function') { + if (this.options.clearError && typeof this.options.clearError === 'function') { this.options.clearError.call(this); } else { if (!this.options.form) { @@ -122,12 +133,19 @@ define([ this.options.form = $(this.options.form); - this.options.form && this.options.form.data('validation') && this.options.form.validation('clearError', + this.options.form && this.options.form.data('validator') && this.options.form.validation('clearError', this.options.regionListId, this.options.regionInputId, this.options.postcodeId); + + // Clean up errors on region & zip fix + $(this.options.regionInputId).removeClass('mage-error').parent().find('[generated]').remove(); + $(this.options.regionListId).removeClass('mage-error').parent().find('[generated]').remove(); + $(this.options.postcodeId).removeClass('mage-error').parent().find('[generated]').remove(); } }, + /** * Update dropdown list based on the country selected + * * @param {String} country - 2 uppercase letter for country code * @private */ @@ -182,11 +200,12 @@ define([ if (!this.options.optionalRegionAllowed) { regionInput.attr('disabled', 'disabled'); } + requiredLabel.removeClass('required'); + regionInput.removeClass('required-entry'); } regionList.removeClass('required-entry').hide(); regionInput.show(); - requiredLabel.removeClass('required'); label.attr('for', regionInput.attr('id')); } @@ -208,10 +227,11 @@ define([ * @private */ _checkRegionRequired: function (country) { - this.options.isRegionRequired = false; var self = this; + + this.options.isRegionRequired = false; $.each(this.options.regionJson.config.regions_required, function (index, elem) { - if (elem == country) { + if (elem === country) { self.options.isRegionRequired = true; } }); diff --git a/app/code/Magento/Dhl/Model/Plugin/Rma/Block/Adminhtml/Rma/Edit/Tab/General/Shippingmethod.php b/app/code/Magento/Dhl/Model/Plugin/Rma/Block/Adminhtml/Rma/Edit/Tab/General/Shippingmethod.php deleted file mode 100644 index acc859ac8c27e879201eed9565eca5e91d0541ca..0000000000000000000000000000000000000000 --- a/app/code/Magento/Dhl/Model/Plugin/Rma/Block/Adminhtml/Rma/Edit/Tab/General/Shippingmethod.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Dhl\Model\Plugin\Rma\Block\Adminhtml\Rma\Edit\Tab\General; - -/** - * Checkout cart shipping block plugin - */ -class Shippingmethod -{ - /** - * @var \Magento\Framework\App\Config\ScopeConfigInterface - */ - protected $_scopeConfig; - - /** - * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig - */ - public function __construct(\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig) - { - $this->_scopeConfig = $scopeConfig; - } - - /** - * @param \Magento\Framework\DataObject $subject - * @param bool $result - * @return bool - */ - public function afterCanDisplayCustomValue(\Magento\Framework\DataObject $subject, $result) - { - $carrierCode = $subject->getShipment()->getCarrierCode(); - if (!$carrierCode) { - return (bool)$result || false; - } - return (bool)$result || (bool)$carrierCode == \Magento\Dhl\Model\Carrier::CODE; - } -} diff --git a/app/code/Magento/Dhl/composer.json b/app/code/Magento/Dhl/composer.json index cab7f39538d956a7f7359c9ef6d23bba58ddb80e..e88cd535952d628628bbc984137430d5370a6ecd 100644 --- a/app/code/Magento/Dhl/composer.json +++ b/app/code/Magento/Dhl/composer.json @@ -16,8 +16,7 @@ "lib-libxml": "*" }, "suggest": { - "magento/module-checkout": "100.2.*", - "magento/module-rma": "100.2.*" + "magento/module-checkout": "100.2.*" }, "type": "magento2-module", "version": "100.2.0-dev", diff --git a/app/code/Magento/Dhl/etc/di.xml b/app/code/Magento/Dhl/etc/di.xml index 25b90ce8850d8c5b2b5e29a8c40b659ab87e92a0..a215c2e82182535e14e659d20cf1f7db2317e915 100644 --- a/app/code/Magento/Dhl/etc/di.xml +++ b/app/code/Magento/Dhl/etc/di.xml @@ -9,8 +9,4 @@ <type name="Magento\Checkout\Block\Cart\LayoutProcessor"> <plugin name="checkout_cart_shipping_dhl" type="Magento\Dhl\Model\Plugin\Checkout\Block\Cart\Shipping"/> </type> - <type name="Magento\Rma\Block\Adminhtml\Rma\Edit\Tab\General\Shippingmethod"> - <plugin name="rma_tab_shippingmethod_dhl" - type="Magento\Dhl\Model\Plugin\Rma\Block\Adminhtml\Rma\Edit\Tab\General\Shippingmethod"/> - </type> </config> diff --git a/app/code/Magento/Fedex/Model/Carrier.php b/app/code/Magento/Fedex/Model/Carrier.php index 4f8aae4962db7536652e930a92c4719cf5f9ba19..3fe23389ea75baf8c5dfdaac2fab74ff48bf4ae4 100644 --- a/app/code/Magento/Fedex/Model/Carrier.php +++ b/app/code/Magento/Fedex/Model/Carrier.php @@ -126,6 +126,18 @@ class Carrier extends AbstractCarrierOnline implements \Magento\Shipping\Model\C 'Key', 'Password', 'MeterNumber', ]; + /** + * Version of tracking service + * @var int + */ + private static $trackServiceVersion = 10; + + /** + * List of TrackReply errors + * @var array + */ + private static $trackingErrors = ['FAILURE', 'ERROR']; + /** * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig * @param \Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory @@ -193,7 +205,7 @@ class Carrier extends AbstractCarrierOnline implements \Magento\Shipping\Model\C $wsdlBasePath = $configReader->getModuleDir(Dir::MODULE_ETC_DIR, 'Magento_Fedex') . '/wsdl/'; $this->_shipServiceWsdl = $wsdlBasePath . 'ShipService_v10.wsdl'; $this->_rateServiceWsdl = $wsdlBasePath . 'RateService_v10.wsdl'; - $this->_trackServiceWsdl = $wsdlBasePath . 'TrackService_v5.wsdl'; + $this->_trackServiceWsdl = $wsdlBasePath . 'TrackService_v' . self::$trackServiceVersion . '.wsdl'; } /** @@ -371,6 +383,9 @@ class Carrier extends AbstractCarrierOnline implements \Magento\Shipping\Model\C */ public function getResult() { + if (!$this->_result) { + $this->_result = $this->_trackFactory->create(); + } return $this->_result; } @@ -646,7 +661,6 @@ class Carrier extends AbstractCarrierOnline implements \Magento\Shipping\Model\C { $r = $this->_rawRequest; $xml = $this->_xmlElFactory->create( - ['data' => '<?xml version = "1.0" encoding = "UTF-8"?><FDXRateAvailableServicesRequest/>'] ); @@ -1035,9 +1049,16 @@ class Carrier extends AbstractCarrierOnline implements \Magento\Shipping\Model\C 'AccountNumber' => $this->getConfigData('account'), 'MeterNumber' => $this->getConfigData('meter_number'), ], - 'Version' => ['ServiceId' => 'trck', 'Major' => '5', 'Intermediate' => '0', 'Minor' => '0'], - 'PackageIdentifier' => ['Type' => 'TRACKING_NUMBER_OR_DOORTAG', 'Value' => $tracking], - 'IncludeDetailedScans' => 1, + 'Version' => [ + 'ServiceId' => 'trck', + 'Major' => self::$trackServiceVersion, + 'Intermediate' => '0', + 'Minor' => '0', + ], + 'SelectionDetails' => [ + 'PackageIdentifier' => ['Type' => 'TRACKING_NUMBER_OR_DOORTAG', 'Value' => $tracking], + ], + 'ProcessingOptions' => 'INCLUDE_DETAILED_SCANS' ]; $requestString = serialize($trackRequest); $response = $this->_getCachedQuotes($requestString); @@ -1064,114 +1085,48 @@ class Carrier extends AbstractCarrierOnline implements \Magento\Shipping\Model\C /** * Parse tracking response * - * @param string[] $trackingValue + * @param string $trackingValue * @param \stdClass $response * @return void - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.NPathComplexity) - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ protected function _parseTrackingResponse($trackingValue, $response) { - if (is_object($response)) { - if ($response->HighestSeverity == 'FAILURE' || $response->HighestSeverity == 'ERROR') { - $errorTitle = (string)$response->Notifications->Message; - } elseif (isset($response->TrackDetails)) { - $trackInfo = $response->TrackDetails; - $resultArray['status'] = (string)$trackInfo->StatusDescription; - $resultArray['service'] = (string)$trackInfo->ServiceInfo; - $timestamp = isset( - $trackInfo->EstimatedDeliveryTimestamp - ) ? $trackInfo->EstimatedDeliveryTimestamp : $trackInfo->ActualDeliveryTimestamp; - $timestamp = strtotime((string)$timestamp); - if ($timestamp) { - $resultArray['deliverydate'] = date('Y-m-d', $timestamp); - $resultArray['deliverytime'] = date('H:i:s', $timestamp); - } - - $deliveryLocation = isset( - $trackInfo->EstimatedDeliveryAddress - ) ? $trackInfo->EstimatedDeliveryAddress : $trackInfo->ActualDeliveryAddress; - $deliveryLocationArray = []; - if (isset($deliveryLocation->City)) { - $deliveryLocationArray[] = (string)$deliveryLocation->City; - } - if (isset($deliveryLocation->StateOrProvinceCode)) { - $deliveryLocationArray[] = (string)$deliveryLocation->StateOrProvinceCode; - } - if (isset($deliveryLocation->CountryCode)) { - $deliveryLocationArray[] = (string)$deliveryLocation->CountryCode; - } - if ($deliveryLocationArray) { - $resultArray['deliverylocation'] = implode(', ', $deliveryLocationArray); - } - - $resultArray['signedby'] = (string)$trackInfo->DeliverySignatureName; - $resultArray['shippeddate'] = date('Y-m-d', (int)$trackInfo->ShipTimestamp); - if (isset($trackInfo->PackageWeight) && isset($trackInfo->Units)) { - $weight = (string)$trackInfo->PackageWeight; - $unit = (string)$trackInfo->Units; - $resultArray['weight'] = "{$weight} {$unit}"; - } - - $packageProgress = []; - if (isset($trackInfo->Events)) { - $events = $trackInfo->Events; - if (isset($events->Address)) { - $events = [$events]; - } - foreach ($events as $event) { - $tempArray = []; - $tempArray['activity'] = (string)$event->EventDescription; - $timestamp = strtotime((string)$event->Timestamp); - if ($timestamp) { - $tempArray['deliverydate'] = date('Y-m-d', $timestamp); - $tempArray['deliverytime'] = date('H:i:s', $timestamp); - } - if (isset($event->Address)) { - $addressArray = []; - $address = $event->Address; - if (isset($address->City)) { - $addressArray[] = (string)$address->City; - } - if (isset($address->StateOrProvinceCode)) { - $addressArray[] = (string)$address->StateOrProvinceCode; - } - if (isset($address->CountryCode)) { - $addressArray[] = (string)$address->CountryCode; - } - if ($addressArray) { - $tempArray['deliverylocation'] = implode(', ', $addressArray); - } - } - $packageProgress[] = $tempArray; - } - } - - $resultArray['progressdetail'] = $packageProgress; - } + if (!is_object($response) || empty($response->HighestSeverity)) { + $this->appendTrackingError($trackingValue, __('Invalid response from carrier')); + return; + } else if (in_array($response->HighestSeverity, self::$trackingErrors)) { + $this->appendTrackingError($trackingValue, (string) $response->Notifications->Message); + return; + } else if (empty($response->CompletedTrackDetails) || empty($response->CompletedTrackDetails->TrackDetails)) { + $this->appendTrackingError($trackingValue, __('No available tracking items')); + return; } - if (!$this->_result) { - $this->_result = $this->_trackFactory->create(); + $trackInfo = $response->CompletedTrackDetails->TrackDetails; + + // Fedex can return tracking details as single object instead array + if (is_object($trackInfo)) { + $trackInfo = [$trackInfo]; } - if (isset($resultArray)) { + $result = $this->getResult(); + $carrierTitle = $this->getConfigData('title'); + $counter = 0; + foreach ($trackInfo as $item) { $tracking = $this->_trackStatusFactory->create(); - $tracking->setCarrier('fedex'); - $tracking->setCarrierTitle($this->getConfigData('title')); + $tracking->setCarrier(self::CODE); + $tracking->setCarrierTitle($carrierTitle); $tracking->setTracking($trackingValue); - $tracking->addData($resultArray); - $this->_result->append($tracking); - } else { - $error = $this->_trackErrorFactory->create(); - $error->setCarrier('fedex'); - $error->setCarrierTitle($this->getConfigData('title')); - $error->setTracking($trackingValue); - $error->setErrorMessage( - $errorTitle ? $errorTitle : __('For some reason we can\'t retrieve tracking info right now.') + $tracking->addData($this->processTrackingDetails($item)); + $result->append($tracking); + $counter ++; + } + + // no available tracking details + if (!$counter) { + $this->appendTrackingError( + $trackingValue, __('For some reason we can\'t retrieve tracking info right now.') ); - $this->_result->append($error); } } @@ -1596,4 +1551,169 @@ class Carrier extends AbstractCarrierOnline implements \Magento\Shipping\Model\C } return $data; } + + /** + * Parse track details response from Fedex + * @param \stdClass $trackInfo + * @return array + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + */ + private function processTrackingDetails(\stdClass $trackInfo) + { + $result = [ + 'shippeddate' => null, + 'deliverydate' => null, + 'deliverytime' => null, + 'deliverylocation' => null, + 'weight' => null, + 'progressdetail' => [], + ]; + + if (!empty($trackInfo->ShipTimestamp)) { + $datetime = \DateTime::createFromFormat(\DateTime::ISO8601, $trackInfo->ShipTimestamp); + $result['shippeddate'] = $datetime->format('Y-m-d'); + } + + $result['signedby'] = !empty($trackInfo->DeliverySignatureName) ? + (string) $trackInfo->DeliverySignatureName : + null; + + $result['status'] = (!empty($trackInfo->StatusDetail) && !empty($trackInfo->StatusDetail->Description)) ? + (string) $trackInfo->StatusDetail->Description : + null; + $result['service'] = (!empty($trackInfo->Service) && !empty($trackInfo->Service->Description)) ? + (string) $trackInfo->Service->Description : + null; + + $datetime = $this->getDeliveryDateTime($trackInfo); + if ($datetime) { + $result['deliverydate'] = $datetime->format('Y-m-d'); + $result['deliverytime'] = $datetime->format('H:i:s'); + } + + $address = null; + if (!empty($trackInfo->EstimatedDeliveryAddress)) { + $address = $trackInfo->EstimatedDeliveryAddress; + } elseif (!empty($trackInfo->ActualDeliveryAddress)) { + $address = $trackInfo->ActualDeliveryAddress; + } + + if (!empty($address)) { + $result['deliverylocation'] = $this->getDeliveryAddress($address); + } + + if (!empty($trackInfo->PackageWeight)) { + $result['weight'] = sprintf( + '%s %s', + (string) $trackInfo->PackageWeight->Value, + (string) $trackInfo->PackageWeight->Units + ); + } + + if (!empty($trackInfo->Events)) { + $events = $trackInfo->Events; + if (is_object($events)) { + $events = [$trackInfo->Events]; + } + $result['progressdetail'] = $this->processTrackDetailsEvents($events); + } + + return $result; + } + + /** + * Parse delivery datetime from tracking details + * @param \stdClass $trackInfo + * @return \Datetime|null + */ + private function getDeliveryDateTime(\stdClass $trackInfo) + { + $timestamp = null; + if (!empty($trackInfo->EstimatedDeliveryTimestamp)) { + $timestamp = $trackInfo->EstimatedDeliveryTimestamp; + } elseif (!empty($trackInfo->ActualDeliveryTimestamp)) { + $timestamp = $trackInfo->ActualDeliveryTimestamp; + } + + return $timestamp ? \DateTime::createFromFormat(\DateTime::ISO8601, $timestamp) : null; + } + + /** + * Get delivery address details in string representation + * Return City, State, Country Code + * + * @param \stdClass $address + * @return \Magento\Framework\Phrase|string + */ + private function getDeliveryAddress(\stdClass $address) + { + $details = []; + + if (!empty($address->City)) { + $details[] = (string) $address->City; + } + + if (!empty($address->StateOrProvinceCode)) { + $details[] = (string) $address->StateOrProvinceCode; + } + + if (!empty($address->CountryCode)) { + $details[] = (string) $address->CountryCode; + } + + return implode(', ', $details); + } + + /** + * Parse tracking details events from response + * Return list of items in such format: + * ['activity', 'deliverydate', 'deliverytime', 'deliverylocation'] + * + * @param array $events + * @return array + */ + private function processTrackDetailsEvents(array $events) + { + $result = []; + /** @var \stdClass $event */ + foreach ($events as $event) { + $item = [ + 'activity' => (string) $event->EventDescription, + 'deliverydate' => null, + 'deliverytime' => null, + 'deliverylocation' => null + ]; + + if (!empty($event->Timestamp)) { + $datetime = \DateTime::createFromFormat(\DateTime::ISO8601, $event->Timestamp); + $item['deliverydate'] = $datetime->format('Y-m-d'); + $item['deliverytime'] = $datetime->format('H:i:s'); + } + + if (!empty($event->Address)) { + $item['deliverylocation'] = $this->getDeliveryAddress($event->Address); + } + + $result[] = $item; + } + + return $result; + } + + /** + * Append error message to rate result instance + * @param string $trackingValue + * @param string $errorMessage + */ + private function appendTrackingError($trackingValue, $errorMessage) + { + $error = $this->_trackErrorFactory->create(); + $error->setCarrier('fedex'); + $error->setCarrierTitle($this->getConfigData('title')); + $error->setTracking($trackingValue); + $error->setErrorMessage($errorMessage); + $result = $this->getResult(); + $result->append($error); + } } diff --git a/app/code/Magento/Fedex/Model/Plugin/Rma/Block/Adminhtml/Rma/Edit/Tab/General/Shippingmethod.php b/app/code/Magento/Fedex/Model/Plugin/Rma/Block/Adminhtml/Rma/Edit/Tab/General/Shippingmethod.php deleted file mode 100644 index 7319a6e9e694cc3704a8904624a740c7cb276a04..0000000000000000000000000000000000000000 --- a/app/code/Magento/Fedex/Model/Plugin/Rma/Block/Adminhtml/Rma/Edit/Tab/General/Shippingmethod.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Fedex\Model\Plugin\Rma\Block\Adminhtml\Rma\Edit\Tab\General; - -/** - * Checkout cart shipping block plugin - */ -class Shippingmethod -{ - /** - * @var \Magento\Framework\App\Config\ScopeConfigInterface - */ - protected $_scopeConfig; - - /** - * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig - */ - public function __construct(\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig) - { - $this->_scopeConfig = $scopeConfig; - } - - /** - * @param \Magento\Framework\DataObject $subject - * @param bool $result - * @return bool - */ - public function afterCanDisplayCustomValue(\Magento\Framework\DataObject $subject, $result) - { - $carrierCode = $subject->getShipment()->getCarrierCode(); - if (!$carrierCode) { - return (bool)$result || false; - } - return (bool)$result || (bool)$carrierCode == \Magento\Fedex\Model\Carrier::CODE; - } -} diff --git a/app/code/Magento/Fedex/Test/Unit/Model/CarrierTest.php b/app/code/Magento/Fedex/Test/Unit/Model/CarrierTest.php index 702b6e69098baacf1f621e1e1b4066bb64eb9406..385ddf8414832bbc312f54abeee90450ca029795 100644 --- a/app/code/Magento/Fedex/Test/Unit/Model/CarrierTest.php +++ b/app/code/Magento/Fedex/Test/Unit/Model/CarrierTest.php @@ -5,167 +5,200 @@ */ namespace Magento\Fedex\Test\Unit\Model; +use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory; +use Magento\CatalogInventory\Model\StockRegistry; +use Magento\Directory\Helper\Data; +use Magento\Directory\Model\Country; +use Magento\Directory\Model\CountryFactory; +use Magento\Directory\Model\CurrencyFactory; +use Magento\Directory\Model\RegionFactory; use Magento\Fedex\Model\Carrier; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\Module\Dir\Reader; +use Magento\Framework\Pricing\PriceCurrencyInterface; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use Magento\Framework\Xml\Security; use Magento\Quote\Model\Quote\Address\RateRequest; +use Magento\Quote\Model\Quote\Address\RateResult\Error as RateResultError; +use Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory as RateErrorFactory; +use Magento\Quote\Model\Quote\Address\RateResult\Method; +use Magento\Quote\Model\Quote\Address\RateResult\MethodFactory; +use Magento\Shipping\Model\Rate\Result as RateResult; +use Magento\Shipping\Model\Rate\ResultFactory as RateResultFactory; +use Magento\Shipping\Model\Simplexml\ElementFactory; +use Magento\Shipping\Model\Tracking\Result; +use Magento\Shipping\Model\Tracking\Result\Error; +use Magento\Shipping\Model\Tracking\Result\ErrorFactory; +use Magento\Shipping\Model\Tracking\Result\Status; +use Magento\Shipping\Model\Tracking\Result\StatusFactory; +use Magento\Shipping\Model\Tracking\ResultFactory; +use Magento\Store\Model\Store; +use Magento\Store\Model\StoreManagerInterface; +use PHPUnit_Framework_MockObject_MockObject as MockObject; +use Psr\Log\LoggerInterface; /** - * Class CarrierTest - * @package Magento\Fedex\Model - * TODO refactor me + * CarrierTest contains units test for Fedex carrier methods * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class CarrierTest extends \PHPUnit_Framework_TestCase { /** - * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager + * @var ObjectManager */ - protected $_helper; + private $helper; /** - * @var \Magento\Fedex\Model\Carrier + * @var Carrier|MockObject */ - protected $_model; + private $model; /** - * @var \Magento\Framework\App\Config\ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject + * @var ScopeConfigInterface|MockObject */ - protected $scope; + private $scope; /** - * Model under test - * - * @var \Magento\Quote\Model\Quote\Address\RateResult\Error|\PHPUnit_Framework_MockObject_MockObject + * @var Error|MockObject */ - protected $error; + private $error; /** - * @var \Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory|\PHPUnit_Framework_MockObject_MockObject + * @var ErrorFactory|MockObject */ - protected $errorFactory; + private $errorFactory; /** - * @return void + * @var ErrorFactory|MockObject + */ + private $trackErrorFactory; + + /** + * @var StatusFactory|MockObject + */ + private $statusFactory; + + /** + * @var Result + */ + private $result; + + /** + * @inheritdoc */ protected function setUp() { - $this->scope = $this->getMockBuilder( - \Magento\Framework\App\Config\ScopeConfigInterface::class - )->disableOriginalConstructor()->getMock(); - - $this->scope->expects($this->any())->method('getValue')->willReturnCallback([$this, 'scopeConfiggetValue']); - $country = $this->getMock( - \Magento\Directory\Model\Country::class, - ['load', 'getData', '__wakeup'], - [], - '', - false - ); - $country->expects($this->any())->method('load')->will($this->returnSelf()); - $countryFactory = $this->getMock(\Magento\Directory\Model\CountryFactory::class, ['create'], [], '', false); - $countryFactory->expects($this->any())->method('create')->will($this->returnValue($country)); - - $rate = $this->getMock(\Magento\Shipping\Model\Rate\Result::class, ['getError'], [], '', false); - $rateFactory = $this->getMock(\Magento\Shipping\Model\Rate\ResultFactory::class, ['create'], [], '', false); - $rateFactory->expects($this->any())->method('create')->will($this->returnValue($rate)); - $this->error = $this->getMockBuilder(\Magento\Quote\Model\Quote\Address\RateResult\Error::class) - ->setMethods(['setCarrier', 'setCarrierTitle', 'setErrorMessage'])->getMock(); - $this->errorFactory = $this->getMockBuilder(\Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory::class) - ->disableOriginalConstructor()->setMethods(['create'])->getMock(); - $this->errorFactory->expects($this->any())->method('create')->willReturn($this->error); - - $store = $this->getMock(\Magento\Store\Model\Store::class, ['getBaseCurrencyCode', '__wakeup'], [], '', false); - $storeManager = $this->getMockForAbstractClass(\Magento\Store\Model\StoreManagerInterface::class); - $storeManager->expects($this->any())->method('getStore')->will($this->returnValue($store)); - $priceCurrency = $this->getMockBuilder(\Magento\Framework\Pricing\PriceCurrencyInterface::class)->getMock(); - - $rateMethod = $this->getMock( - \Magento\Quote\Model\Quote\Address\RateResult\Method::class, - null, - ['priceCurrency' => $priceCurrency] - ); - $rateMethodFactory = $this->getMock( - \Magento\Quote\Model\Quote\Address\RateResult\MethodFactory::class, - ['create'], - [], - '', - false - ); - $rateMethodFactory->expects($this->any())->method('create')->will($this->returnValue($rateMethod)); - $this->_model = $this->getMock( - \Magento\Fedex\Model\Carrier::class, - ['_getCachedQuotes', '_debug'], - [ - 'scopeConfig' => $this->scope, - 'rateErrorFactory' => $this->errorFactory, - 'logger' => $this->getMock(\Psr\Log\LoggerInterface::class), - 'xmlSecurity' => new Security(), - 'xmlElFactory' => $this->getMock( - \Magento\Shipping\Model\Simplexml\ElementFactory::class, - [], - [], - '', - false - ), - 'rateFactory' => $rateFactory, - 'rateMethodFactory' => $rateMethodFactory, - 'trackFactory' => $this->getMock( - \Magento\Shipping\Model\Tracking\ResultFactory::class, - [], - [], - '', - false - ), - 'trackErrorFactory' => $this->getMock(\Magento\Shipping\Model\Tracking\Result\ErrorFactory::class, [], [], '', false), - 'trackStatusFactory' => $this->getMock(\Magento\Shipping\Model\Tracking\Result\StatusFactory::class, [], [], '', false), - 'regionFactory' => $this->getMock(\Magento\Directory\Model\RegionFactory::class, [], [], '', false), - 'countryFactory' => $countryFactory, - 'currencyFactory' => $this->getMock(\Magento\Directory\Model\CurrencyFactory::class, [], [], '', false), - 'directoryData' => $this->getMock(\Magento\Directory\Helper\Data::class, [], [], '', false), - 'stockRegistry' => $this->getMock( - \Magento\CatalogInventory\Model\StockRegistry::class, - [], - [], - '', - false - ), - 'storeManager' => $storeManager, - 'configReader' => $this->getMock(\Magento\Framework\Module\Dir\Reader::class, [], [], '', false), - 'productCollectionFactory' => $this->getMock( - \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory::class, - [], - [], - '', - false - ), - 'data' => [], - ] - ); + $this->helper = new ObjectManager($this); + $this->scope = $this->getMockBuilder(ScopeConfigInterface::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->scope->expects(static::any()) + ->method('getValue') + ->willReturnCallback([$this, 'scopeConfigGetValue']); + + $countryFactory = $this->getCountryFactory(); + $rateFactory = $this->getRateFactory(); + $storeManager = $this->getStoreManager(); + $resultFactory = $this->getResultFactory(); + $this->initRateErrorFactory(); + + $rateMethodFactory = $this->getRateMethodFactory(); + + $this->trackErrorFactory = $this->getMockBuilder(ErrorFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + + $this->statusFactory = $this->getMockBuilder(StatusFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + + $elementFactory = $this->getMockBuilder(ElementFactory::class) + ->disableOriginalConstructor() + ->getMock(); + + $collectionFactory = $this->getMockBuilder(CollectionFactory::class) + ->disableOriginalConstructor() + ->getMock(); + + $regionFactory = $this->getMockBuilder(RegionFactory::class) + ->disableOriginalConstructor() + ->getMock(); + + $currencyFactory = $this->getMockBuilder(CurrencyFactory::class) + ->disableOriginalConstructor() + ->getMock(); + + $data = $this->getMockBuilder(Data::class) + ->disableOriginalConstructor() + ->getMock(); + + $stockRegistry = $this->getMockBuilder(StockRegistry::class) + ->disableOriginalConstructor() + ->getMock(); + + $reader = $this->getMockBuilder(Reader::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->model = $this->getMockBuilder(Carrier::class) + ->setMethods(['_getCachedQuotes', '_debug']) + ->setConstructorArgs( + [ + 'scopeConfig' => $this->scope, + 'rateErrorFactory' => $this->errorFactory, + 'logger' => $this->getMock(LoggerInterface::class), + 'xmlSecurity' => new Security(), + 'xmlElFactory' => $elementFactory, + 'rateFactory' => $rateFactory, + 'rateMethodFactory' => $rateMethodFactory, + 'trackFactory' => $resultFactory, + 'trackErrorFactory' => $this->trackErrorFactory, + 'trackStatusFactory' => $this->statusFactory, + 'regionFactory' => $regionFactory, + 'countryFactory' => $countryFactory, + 'currencyFactory' => $currencyFactory, + 'directoryData' => $data, + 'stockRegistry' => $stockRegistry, + 'storeManager' => $storeManager, + 'configReader' => $reader, + 'productCollectionFactory' => $collectionFactory, + ] + ) + ->getMock(); } + /** + * @covers \Magento\Fedex\Model\Carrier::setRequest + */ public function testSetRequestWithoutCity() { - $requestMock = $this->getMockBuilder(\Magento\Quote\Model\Quote\Address\RateRequest::class) + $request = $this->getMockBuilder(RateRequest::class) ->disableOriginalConstructor() ->setMethods(['getDestCity']) ->getMock(); - $requestMock->expects($this->once()) + $request->expects($this->once()) ->method('getDestCity') ->willReturn(null); - $this->_model->setRequest($requestMock); + $this->model->setRequest($request); } + /** + * @covers \Magento\Fedex\Model\Carrier::setRequest + */ public function testSetRequestWithCity() { - $requestMock = $this->getMockBuilder(\Magento\Quote\Model\Quote\Address\RateRequest::class) + $request = $this->getMockBuilder(RateRequest::class) ->disableOriginalConstructor() ->setMethods(['getDestCity']) ->getMock(); - $requestMock->expects($this->exactly(2)) + $request->expects(static::exactly(2)) ->method('getDestCity') ->willReturn('Small Town'); - $this->_model->setRequest($requestMock); + $this->model->setRequest($request); } /** @@ -173,7 +206,7 @@ class CarrierTest extends \PHPUnit_Framework_TestCase * @param $path * @return null|string */ - public function scopeConfiggetValue($path) + public function scopeConfigGetValue($path) { switch ($path) { case 'carriers/fedex/showmethod': @@ -183,53 +216,57 @@ class CarrierTest extends \PHPUnit_Framework_TestCase return 'ServiceType'; break; } + return null; } /** + * @param float $amount + * @param string $rateType + * @param float $expected * @dataProvider collectRatesDataProvider */ public function testCollectRatesRateAmountOriginBased($amount, $rateType, $expected) { - $this->scope->expects($this->any())->method('isSetFlag')->will($this->returnValue(true)); + $this->scope->expects(static::any()) + ->method('isSetFlag') + ->willReturn(true); // @codingStandardsIgnoreStart - $netAmount = new \Magento\Framework\DataObject([]); + $netAmount = new \stdClass(); $netAmount->Amount = $amount; - $totalNetCharge = new \Magento\Framework\DataObject([]); + $totalNetCharge = new \stdClass(); $totalNetCharge->TotalNetCharge = $netAmount; $totalNetCharge->RateType = $rateType; - $ratedShipmentDetail = new \Magento\Framework\DataObject([]); + $ratedShipmentDetail = new \stdClass(); $ratedShipmentDetail->ShipmentRateDetail = $totalNetCharge; - $rate = new \Magento\Framework\DataObject([]); + $rate = new \stdClass(); $rate->ServiceType = 'ServiceType'; $rate->RatedShipmentDetails = [$ratedShipmentDetail]; - $response = new \Magento\Framework\DataObject([]); + $response = new \stdClass(); $response->HighestSeverity = 'SUCCESS'; $response->RateReplyDetails = $rate; + // @codingStandardsIgnoreEnd - $this->_model->expects($this->any())->method('_getCachedQuotes')->will( - $this->returnValue(serialize($response)) - ); - $request = $this->getMock( - \Magento\Quote\Model\Quote\Address\RateRequest::class, - ['getDestCity'], - [], - '', - false - ); - $request->expects($this->exactly(2)) - ->method('getDestCity') - ->willReturn('Wonderful City'); - foreach ($this->_model->collectRates($request)->getAllRates() as $allRates) { + $this->model->expects(static::any()) + ->method('_getCachedQuotes') + ->willReturn(serialize($response)); + $request = $this->getMockBuilder(RateRequest::class) + ->disableOriginalConstructor() + ->getMock(); + + foreach ($this->model->collectRates($request)->getAllRates() as $allRates) { $this->assertEquals($expected, $allRates->getData('cost')); } - // @codingStandardsIgnoreEnd } + /** + * Get list of rates variations + * @return array + */ public function collectRatesDataProvider() { return [ @@ -246,16 +283,22 @@ class CarrierTest extends \PHPUnit_Framework_TestCase public function testCollectRatesErrorMessage() { - $this->scope->expects($this->once())->method('isSetFlag')->willReturn(false); + $this->scope->expects(static::once()) + ->method('isSetFlag') + ->willReturn(false); - $this->error->expects($this->once())->method('setCarrier')->with('fedex'); - $this->error->expects($this->once())->method('setCarrierTitle'); - $this->error->expects($this->once())->method('setErrorMessage'); + $this->error->expects(static::once()) + ->method('setCarrier') + ->with('fedex'); + $this->error->expects(static::once()) + ->method('setCarrierTitle'); + $this->error->expects(static::once()) + ->method('setErrorMessage'); $request = new RateRequest(); $request->setPackageWeight(1); - $this->assertSame($this->error, $this->_model->collectRates($request)); + static::assertSame($this->error, $this->model->collectRates($request)); } /** @@ -269,11 +312,11 @@ class CarrierTest extends \PHPUnit_Framework_TestCase $refClass = new \ReflectionClass(Carrier::class); $property = $refClass->getProperty('_debugReplacePrivateDataKeys'); $property->setAccessible(true); - $property->setValue($this->_model, $maskFields); + $property->setValue($this->model, $maskFields); $refMethod = $refClass->getMethod('filterDebugData'); $refMethod->setAccessible(true); - $result = $refMethod->invoke($this->_model, $data); + $result = $refMethod->invoke($this->model, $data); static::assertEquals($expected, $result); } @@ -312,4 +355,283 @@ class CarrierTest extends \PHPUnit_Framework_TestCase ], ]; } + + /** + * @covers \Magento\Fedex\Model\Carrier::getTracking + */ + public function testGetTrackingErrorResponse() + { + $tracking = '123456789012'; + $errorMessage = 'Tracking information is unavailable.'; + + // @codingStandardsIgnoreStart + $response = new \stdClass(); + $response->HighestSeverity = 'ERROR'; + $response->Notifications = new \stdClass(); + $response->Notifications->Message = $errorMessage; + // @codingStandardsIgnoreEnd + + $this->model->expects(static::once()) + ->method('_getCachedQuotes') + ->willReturn(serialize($response)); + + $error = $this->helper->getObject(Error::class); + $this->trackErrorFactory->expects(static::once()) + ->method('create') + ->willReturn($error); + + $this->model->getTracking($tracking); + $tracks = $this->model->getResult()->getAllTrackings(); + + static::assertEquals(1, count($tracks)); + + /** @var Error $current */ + $current = $tracks[0]; + static::assertInstanceOf(Error::class, $current); + static::assertEquals(__($errorMessage), $current->getErrorMessage()); + } + + /** + * @covers \Magento\Fedex\Model\Carrier::getTracking + */ + public function testGetTracking() + { + $tracking = '123456789012'; + + // @codingStandardsIgnoreStart + $response = new \stdClass(); + $response->HighestSeverity = 'SUCCESS'; + $response->CompletedTrackDetails = new \stdClass(); + + $trackDetails = new \stdClass(); + $trackDetails->ShipTimestamp = '2016-08-05T14:06:35+00:00'; + $trackDetails->DeliverySignatureName = 'signature'; + + $trackDetails->StatusDetail = new \stdClass(); + $trackDetails->StatusDetail->Description = 'SUCCESS'; + + $trackDetails->Service = new \stdClass(); + $trackDetails->Service->Description = 'ground'; + $trackDetails->EstimatedDeliveryTimestamp = '2016-08-10T10:20:26+00:00'; + + $trackDetails->EstimatedDeliveryAddress = new \stdClass(); + $trackDetails->EstimatedDeliveryAddress->City = 'Culver City'; + $trackDetails->EstimatedDeliveryAddress->StateOrProvinceCode = 'CA'; + $trackDetails->EstimatedDeliveryAddress->CountryCode = 'US'; + + $trackDetails->PackageWeight = new \stdClass(); + $trackDetails->PackageWeight->Value = 23; + $trackDetails->PackageWeight->Units = 'LB'; + + $response->CompletedTrackDetails->TrackDetails = [$trackDetails]; + // @codingStandardsIgnoreEnd + + $this->model->expects(static::once()) + ->method('_getCachedQuotes') + ->willReturn(serialize($response)); + + $status = $this->helper->getObject(Status::class); + $this->statusFactory->expects(static::once()) + ->method('create') + ->willReturn($status); + + $this->model->getTracking($tracking); + $tracks = $this->model->getResult()->getAllTrackings(); + static::assertEquals(1, count($tracks)); + + $current = $tracks[0]; + $fields = [ + 'signedby', + 'status', + 'service', + 'shippeddate', + 'deliverydate', + 'deliverytime', + 'deliverylocation', + 'weight', + ]; + array_walk($fields, function ($field) use ($current) { + static::assertNotEmpty($current[$field]); + }); + + static::assertEquals('2016-08-10', $current['deliverydate']); + static::assertEquals('10:20:26', $current['deliverytime']); + static::assertEquals('2016-08-05', $current['shippeddate']); + } + + /** + * @covers \Magento\Fedex\Model\Carrier::getTracking + */ + public function testGetTrackingWithEvents() + { + $tracking = '123456789012'; + + // @codingStandardsIgnoreStart + $response = new \stdClass(); + $response->HighestSeverity = 'SUCCESS'; + $response->CompletedTrackDetails = new \stdClass(); + + $event = new \stdClass(); + $event->EventDescription = 'Test'; + $event->Timestamp = '2016-08-05T19:14:53+00:00'; + $event->Address = new \stdClass(); + + $event->Address->City = 'Culver City'; + $event->Address->StateOrProvinceCode = 'CA'; + $event->Address->CountryCode = 'US'; + + $trackDetails = new \stdClass(); + $trackDetails->Events = $event; + + $response->CompletedTrackDetails->TrackDetails = $trackDetails; + // @codingStandardsIgnoreEnd + + $this->model->expects(static::once()) + ->method('_getCachedQuotes') + ->willReturn(serialize($response)); + + $status = $this->helper->getObject(Status::class); + $this->statusFactory->expects(static::once()) + ->method('create') + ->willReturn($status); + + $this->model->getTracking($tracking); + $tracks = $this->model->getResult()->getAllTrackings(); + static::assertEquals(1, count($tracks)); + + $current = $tracks[0]; + static::assertNotEmpty($current['progressdetail']); + static::assertEquals(1, count($current['progressdetail'])); + + $event = $current['progressdetail'][0]; + $fields = ['activity', 'deliverydate', 'deliverytime', 'deliverylocation']; + array_walk($fields, function ($field) use ($event) { + static::assertNotEmpty($event[$field]); + }); + static::assertEquals('2016-08-05', $event['deliverydate']); + static::assertEquals('19:14:53', $event['deliverytime']); + } + + /** + * Init RateErrorFactory and RateResultErrors mocks + * @return void + */ + private function initRateErrorFactory() + { + $this->error = $this->getMockBuilder(RateResultError::class) + ->disableOriginalConstructor() + ->setMethods(['setCarrier', 'setCarrierTitle', 'setErrorMessage']) + ->getMock(); + $this->errorFactory = $this->getMockBuilder(RateErrorFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $this->errorFactory->expects(static::any()) + ->method('create') + ->willReturn($this->error); + } + + /** + * Creates mock rate result factory + * @return RateResultFactory|MockObject + */ + private function getRateFactory() + { + $rate = $this->getMockBuilder(RateResult::class) + ->disableOriginalConstructor() + ->setMethods(['getError']) + ->getMock(); + $rateFactory = $this->getMockBuilder(RateResultFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $rateFactory->expects(static::any()) + ->method('create') + ->willReturn($rate); + + return $rateFactory; + } + + /** + * Creates mock object for CountryFactory class + * @return CountryFactory|MockObject + */ + private function getCountryFactory() + { + $country = $this->getMockBuilder(Country::class) + ->disableOriginalConstructor() + ->setMethods(['load', 'getData']) + ->getMock(); + $country->expects(static::any()) + ->method('load') + ->willReturnSelf(); + + $countryFactory = $this->getMockBuilder(CountryFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $countryFactory->expects(static::any()) + ->method('create') + ->willReturn($country); + + return $countryFactory; + } + + /** + * Creates mock object for ResultFactory class + * @return ResultFactory|MockObject + */ + private function getResultFactory() + { + $resultFactory = $this->getMockBuilder(ResultFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $this->result = $this->helper->getObject(Result::class); + $resultFactory->expects(static::any()) + ->method('create') + ->willReturn($this->result); + + return $resultFactory; + } + + /** + * Creates mock object for store manager + * @return StoreManagerInterface|MockObject + */ + private function getStoreManager() + { + $store = $this->getMockBuilder(Store::class) + ->disableOriginalConstructor() + ->setMethods(['getBaseCurrencyCode']) + ->getMock(); + $storeManager = $this->getMock(StoreManagerInterface::class); + $storeManager->expects(static::any()) + ->method('getStore') + ->willReturn($store); + + return $storeManager; + } + + /** + * Creates mock object for rate method factory + * @return MethodFactory|MockObject + */ + private function getRateMethodFactory() + { + $priceCurrency = $this->getMock(PriceCurrencyInterface::class); + $rateMethod = $this->getMockBuilder(Method::class) + ->setConstructorArgs(['priceCurrency' => $priceCurrency]) + ->setMethods(null) + ->getMock(); + $rateMethodFactory = $this->getMockBuilder(MethodFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $rateMethodFactory->expects(static::any()) + ->method('create') + ->willReturn($rateMethod); + + return $rateMethodFactory; + } } diff --git a/app/code/Magento/Fedex/composer.json b/app/code/Magento/Fedex/composer.json index 07c988e280da759e61aae0383618fdec40faddd3..d27d5c1c60d407ce4d1d5b3781b0209c5955a0d4 100644 --- a/app/code/Magento/Fedex/composer.json +++ b/app/code/Magento/Fedex/composer.json @@ -14,9 +14,6 @@ "magento/framework": "100.2.*", "lib-libxml": "*" }, - "suggest": { - "magento/module-rma": "100.2.*" - }, "type": "magento2-module", "version": "100.2.0-dev", "license": [ diff --git a/app/code/Magento/Fedex/etc/adminhtml/system.xml b/app/code/Magento/Fedex/etc/adminhtml/system.xml index 1de61c2c154941d836de0cbc64e137ce26ee6af9..16966322f25f96657071b9f7c1bf7d96dea9dda2 100644 --- a/app/code/Magento/Fedex/etc/adminhtml/system.xml +++ b/app/code/Magento/Fedex/etc/adminhtml/system.xml @@ -101,11 +101,11 @@ <source_model>Magento\Fedex\Model\Source\Freemethod</source_model> </field> <field id="free_shipping_enable" translate="label" type="select" sortOrder="220" showInDefault="1" showInWebsite="1" showInStore="0"> - <label>Free Shipping Amount Threshold</label> + <label>Enable Free Shipping Threshold</label> <source_model>Magento\Config\Model\Config\Source\Enabledisable</source_model> </field> <field id="free_shipping_subtotal" translate="label" type="text" sortOrder="230" showInDefault="1" showInWebsite="1" showInStore="0"> - <label>Enable Free Shipping Threshold</label> + <label>Free Shipping Amount Threshold</label> <validate>validate-number validate-zero-or-greater</validate> <depends> <field id="free_shipping_enable">1</field> diff --git a/app/code/Magento/Fedex/etc/di.xml b/app/code/Magento/Fedex/etc/di.xml deleted file mode 100644 index 454beffacba9ddd828c995726d4071321acefe39..0000000000000000000000000000000000000000 --- a/app/code/Magento/Fedex/etc/di.xml +++ /dev/null @@ -1,13 +0,0 @@ -<?xml version="1.0"?> -<!-- -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> - <type name="Magento\Rma\Block\Adminhtml\Rma\Edit\Tab\General\Shippingmethod"> - <plugin name="rma_tab_shippingmethod_fedex" - type="Magento\Fedex\Model\Plugin\Rma\Block\Adminhtml\Rma\Edit\Tab\General\Shippingmethod"/> - </type> -</config> diff --git a/app/code/Magento/Fedex/etc/wsdl/TrackService_v5.wsdl b/app/code/Magento/Fedex/etc/wsdl/TrackService_v10.wsdl similarity index 63% rename from app/code/Magento/Fedex/etc/wsdl/TrackService_v5.wsdl rename to app/code/Magento/Fedex/etc/wsdl/TrackService_v10.wsdl index f3ceaf5056a20ad907c9687275b38b40722583bf..77f53e02a539a0d1ce72871d8352bd1948b930a6 100644 --- a/app/code/Magento/Fedex/etc/wsdl/TrackService_v5.wsdl +++ b/app/code/Magento/Fedex/etc/wsdl/TrackService_v10.wsdl @@ -1,12 +1,12 @@ -<definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:ns="http://fedex.com/ws/track/v5" xmlns:s1="http://schemas.xmlsoap.org/wsdl/soap/" targetNamespace="http://fedex.com/ws/track/v5" name="TrackServiceDefinitions"> +<definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:ns="http://fedex.com/ws/track/v10" xmlns:s1="http://schemas.xmlsoap.org/wsdl/soap/" targetNamespace="http://fedex.com/ws/track/v10" name="TrackServiceDefinitions"> <types> - <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://fedex.com/ws/track/v5"> + <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://fedex.com/ws/track/v10"> + <xs:element name="SendNotificationsReply" type="ns:SendNotificationsReply"/> + <xs:element name="SendNotificationsRequest" type="ns:SendNotificationsRequest"/> <xs:element name="SignatureProofOfDeliveryFaxReply" type="ns:SignatureProofOfDeliveryFaxReply"/> <xs:element name="SignatureProofOfDeliveryFaxRequest" type="ns:SignatureProofOfDeliveryFaxRequest"/> <xs:element name="SignatureProofOfDeliveryLetterReply" type="ns:SignatureProofOfDeliveryLetterReply"/> <xs:element name="SignatureProofOfDeliveryLetterRequest" type="ns:SignatureProofOfDeliveryLetterRequest"/> - <xs:element name="TrackNotificationReply" type="ns:TrackNotificationReply"/> - <xs:element name="TrackNotificationRequest" type="ns:TrackNotificationRequest"/> <xs:element name="TrackReply" type="ns:TrackReply"/> <xs:element name="TrackRequest" type="ns:TrackRequest"/> <xs:complexType name="Address"> @@ -14,7 +14,7 @@ <xs:documentation>Descriptive data for a physical location. May be used as an actual physical address (place to which one could go), or as a container of "address parts" which should be handled as a unit (such as a city-state-ZIP combination within the US).</xs:documentation> </xs:annotation> <xs:sequence> - <xs:element name="StreetLines" type="xs:string" minOccurs="0" maxOccurs="2"> + <xs:element name="StreetLines" type="xs:string" minOccurs="0" maxOccurs="unbounded"> <xs:annotation> <xs:documentation>Combination of number, street name, etc. At least one line is required for a valid physical address; empty lines should not be included.</xs:documentation> </xs:annotation> @@ -44,6 +44,11 @@ <xs:documentation>The two-letter code used to identify a country.</xs:documentation> </xs:annotation> </xs:element> + <xs:element name="CountryName" type="xs:string" minOccurs="0"> + <xs:annotation> + <xs:documentation>The fully spelt out name of a country.</xs:documentation> + </xs:annotation> + </xs:element> <xs:element name="Residential" type="xs:boolean" minOccurs="0"> <xs:annotation> <xs:documentation>Indicates whether this address residential (as opposed to commercial).</xs:documentation> @@ -51,6 +56,48 @@ </xs:element> </xs:sequence> </xs:complexType> + <xs:complexType name="AppointmentDetail"> + <xs:annotation> + <xs:documentation>Specifies the different appointment times on a specific date.</xs:documentation> + </xs:annotation> + <xs:sequence> + <xs:element name="Date" type="xs:date" minOccurs="0"/> + <xs:element name="WindowDetails" type="ns:AppointmentTimeDetail" minOccurs="0" maxOccurs="unbounded"> + <xs:annotation> + <xs:documentation>Different appointment time windows on the date specified.</xs:documentation> + </xs:annotation> + </xs:element> + </xs:sequence> + </xs:complexType> + <xs:complexType name="AppointmentTimeDetail"> + <xs:annotation> + <xs:documentation>Specifies the details about the appointment time window.</xs:documentation> + </xs:annotation> + <xs:sequence> + <xs:element name="Type" type="ns:AppointmentWindowType" minOccurs="0"> + <xs:annotation> + <xs:documentation>The description that FedEx Ground uses for the appointment window being specified.</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="Window" type="ns:LocalTimeRange" minOccurs="0"> + <xs:annotation> + <xs:documentation>Specifies the window of time for an appointment.</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="Description" type="xs:string" minOccurs="0"/> + </xs:sequence> + </xs:complexType> + <xs:simpleType name="AppointmentWindowType"> + <xs:annotation> + <xs:documentation>The description that FedEx uses for a given appointment window.</xs:documentation> + </xs:annotation> + <xs:restriction base="xs:string"> + <xs:enumeration value="AFTERNOON"/> + <xs:enumeration value="LATE_AFTERNOON"/> + <xs:enumeration value="MID_DAY"/> + <xs:enumeration value="MORNING"/> + </xs:restriction> + </xs:simpleType> <xs:simpleType name="ArrivalLocationType"> <xs:annotation> <xs:documentation>Identifies where a tracking event occurs.</xs:documentation> @@ -73,11 +120,18 @@ <xs:enumeration value="PICKUP_LOCATION"/> <xs:enumeration value="PLANE"/> <xs:enumeration value="PORT_OF_ENTRY"/> + <xs:enumeration value="SHIP_AND_GET_LOCATION"/> <xs:enumeration value="SORT_FACILITY"/> <xs:enumeration value="TURNPOINT"/> <xs:enumeration value="VEHICLE"/> </xs:restriction> </xs:simpleType> + <xs:simpleType name="AvailableImageType"> + <xs:restriction base="xs:string"> + <xs:enumeration value="BILL_OF_LADING"/> + <xs:enumeration value="SIGNATURE_PROOF_OF_DELIVERY"/> + </xs:restriction> + </xs:simpleType> <xs:simpleType name="CarrierCodeType"> <xs:annotation> <xs:documentation>Identification of a FedEx operating company (transportation).</xs:documentation> @@ -108,7 +162,7 @@ </xs:element> <xs:element name="IntegratorId" type="xs:string" minOccurs="0"> <xs:annotation> - <xs:documentation>Only used in transactions which require identification of the Fed Ex Office integrator.</xs:documentation> + <xs:documentation>Only used in transactions which require identification of the FedEx Office integrator.</xs:documentation> </xs:annotation> </xs:element> <xs:element name="Localization" type="ns:Localization" minOccurs="0"> @@ -118,6 +172,75 @@ </xs:element> </xs:sequence> </xs:complexType> + <xs:complexType name="Commodity"> + <xs:sequence> + <xs:element name="CommodityId" type="xs:string" minOccurs="0"> + <xs:annotation> + <xs:documentation>Value used to identify a commodity description; must be unique within the containing shipment.</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="Name" type="xs:string" minOccurs="0"/> + <xs:element name="NumberOfPieces" type="xs:nonNegativeInteger" minOccurs="0"/> + <xs:element name="Description" type="xs:string" minOccurs="0"/> + <xs:element name="CountryOfManufacture" type="xs:string" minOccurs="0"/> + <xs:element name="HarmonizedCode" type="xs:string" minOccurs="0"/> + <xs:element name="Weight" type="ns:Weight" minOccurs="0"/> + <xs:element name="Quantity" type="xs:decimal" minOccurs="0"/> + <xs:element name="QuantityUnits" type="xs:string" minOccurs="0"/> + <xs:element name="AdditionalMeasures" type="ns:Measure" minOccurs="0" maxOccurs="unbounded"> + <xs:annotation> + <xs:documentation>Contains only additional quantitative information other than weight and quantity to calculate duties and taxes.</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="UnitPrice" type="ns:Money" minOccurs="0"/> + <xs:element name="CustomsValue" type="ns:Money" minOccurs="0"/> + <xs:element name="ExciseConditions" type="ns:EdtExciseCondition" minOccurs="0" maxOccurs="unbounded"> + <xs:annotation> + <xs:documentation>Defines additional characteristic of commodity used to calculate duties and taxes</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="ExportLicenseNumber" type="xs:string" minOccurs="0"/> + <xs:element name="ExportLicenseExpirationDate" type="xs:date" minOccurs="0"/> + <xs:element name="CIMarksAndNumbers" type="xs:string" minOccurs="0"/> + <xs:element name="PartNumber" type="xs:string" minOccurs="0"/> + <xs:element name="NaftaDetail" type="ns:NaftaCommodityDetail" minOccurs="0"> + <xs:annotation> + <xs:documentation>All data required for this commodity in NAFTA Certificate of Origin.</xs:documentation> + </xs:annotation> + </xs:element> + </xs:sequence> + </xs:complexType> + <xs:complexType name="CompletedTrackDetail"> + <xs:sequence> + <xs:element name="HighestSeverity" type="ns:NotificationSeverityType" minOccurs="0"/> + <xs:element name="Notifications" type="ns:Notification" minOccurs="0" maxOccurs="unbounded"/> + <xs:element name="DuplicateWaybill" type="xs:boolean" minOccurs="0"> + <xs:annotation> + <xs:documentation>True if duplicate packages (more than one package with the same tracking number) have been found, and only limited data will be provided for each one.</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="MoreData" type="xs:boolean" minOccurs="0"> + <xs:annotation> + <xs:documentation>True if additional packages remain to be retrieved.</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="PagingToken" type="xs:string" minOccurs="0"> + <xs:annotation> + <xs:documentation>Value that must be passed in a TrackNotification request to retrieve the next set of packages (when MoreDataAvailable = true).</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="TrackDetailsCount" type="xs:nonNegativeInteger" minOccurs="0"> + <xs:annotation> + <xs:documentation>Identifies the total number of available track details across all pages.</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="TrackDetails" type="ns:TrackDetail" minOccurs="0" maxOccurs="unbounded"> + <xs:annotation> + <xs:documentation>Contains detailed tracking information for the requested packages(s).</xs:documentation> + </xs:annotation> + </xs:element> + </xs:sequence> + </xs:complexType> <xs:complexType name="Contact"> <xs:annotation> <xs:documentation>The descriptive data for a point-of-contact person.</xs:documentation> @@ -148,6 +271,11 @@ <xs:documentation>Identifies the phone extension associated with this contact.</xs:documentation> </xs:annotation> </xs:element> + <xs:element name="TollFreePhoneNumber" type="xs:string" minOccurs="0"> + <xs:annotation> + <xs:documentation>Identifies a toll free number, if any, associated with this contact.</xs:documentation> + </xs:annotation> + </xs:element> <xs:element name="PagerNumber" type="xs:string" minOccurs="0"> <xs:annotation> <xs:documentation>Identifies the pager number associated with this contact.</xs:documentation> @@ -171,6 +299,84 @@ <xs:element name="Address" type="ns:Address" minOccurs="0"/> </xs:sequence> </xs:complexType> + <xs:complexType name="ContentRecord"> + <xs:sequence> + <xs:element name="PartNumber" type="xs:string" minOccurs="0"/> + <xs:element name="ItemNumber" type="xs:string" minOccurs="0"/> + <xs:element name="ReceivedQuantity" type="xs:nonNegativeInteger" minOccurs="0"/> + <xs:element name="Description" type="xs:string" minOccurs="0"/> + </xs:sequence> + </xs:complexType> + <xs:complexType name="CustomerExceptionRequestDetail"> + <xs:sequence> + <xs:element name="Id" type="xs:string" minOccurs="0"> + <xs:annotation> + <xs:documentation>Unique identifier for the customer exception request.</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="StatusCode" type="xs:string" minOccurs="0"/> + <xs:element name="StatusDescription" type="xs:string" minOccurs="0"/> + <xs:element name="CreateTime" type="xs:dateTime" minOccurs="0"/> + </xs:sequence> + </xs:complexType> + <xs:complexType name="CustomsOptionDetail"> + <xs:sequence> + <xs:element name="Type" type="ns:CustomsOptionType" minOccurs="0"/> + <xs:element name="Description" type="xs:string" minOccurs="0"> + <xs:annotation> + <xs:documentation>Specifies additional description about customs options. This is a required field when the customs options type is "OTHER".</xs:documentation> + </xs:annotation> + </xs:element> + </xs:sequence> + </xs:complexType> + <xs:simpleType name="CustomsOptionType"> + <xs:restriction base="xs:string"> + <xs:enumeration value="COURTESY_RETURN_LABEL"/> + <xs:enumeration value="EXHIBITION_TRADE_SHOW"/> + <xs:enumeration value="FAULTY_ITEM"/> + <xs:enumeration value="FOLLOWING_REPAIR"/> + <xs:enumeration value="FOR_REPAIR"/> + <xs:enumeration value="ITEM_FOR_LOAN"/> + <xs:enumeration value="OTHER"/> + <xs:enumeration value="REJECTED"/> + <xs:enumeration value="REPLACEMENT"/> + <xs:enumeration value="TRIAL"/> + </xs:restriction> + </xs:simpleType> + <xs:complexType name="DateRange"> + <xs:sequence> + <xs:element name="Begins" type="xs:date" minOccurs="0"/> + <xs:element name="Ends" type="xs:date" minOccurs="0"/> + </xs:sequence> + </xs:complexType> + <xs:complexType name="DeliveryOptionEligibilityDetail"> + <xs:annotation> + <xs:documentation>Details about the eligibility for a delivery option.</xs:documentation> + </xs:annotation> + <xs:sequence> + <xs:element name="Option" type="ns:DeliveryOptionType" minOccurs="0"> + <xs:annotation> + <xs:documentation>Type of delivery option.</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="Eligibility" type="ns:EligibilityType" minOccurs="0"> + <xs:annotation> + <xs:documentation>Eligibility of the customer for the specific delivery option.</xs:documentation> + </xs:annotation> + </xs:element> + </xs:sequence> + </xs:complexType> + <xs:simpleType name="DeliveryOptionType"> + <xs:annotation> + <xs:documentation>Specifies the different option types for delivery.</xs:documentation> + </xs:annotation> + <xs:restriction base="xs:string"> + <xs:enumeration value="INDIRECT_SIGNATURE_RELEASE"/> + <xs:enumeration value="REDIRECT_TO_HOLD_AT_LOCATION"/> + <xs:enumeration value="REROUTE"/> + <xs:enumeration value="RESCHEDULE"/> + </xs:restriction> + </xs:simpleType> <xs:complexType name="Dimensions"> <xs:annotation> <xs:documentation>The dimensions of this package and the unit type used for the measurements.</xs:documentation> @@ -280,6 +486,43 @@ <xs:enumeration value="SHIPPER"/> </xs:restriction> </xs:simpleType> + <xs:complexType name="EdtExciseCondition"> + <xs:sequence> + <xs:element name="Category" type="xs:string" minOccurs="0"/> + <xs:element name="Value" type="xs:string" minOccurs="0"> + <xs:annotation> + <xs:documentation>Customer-declared value, with data type and legal values depending on excise condition, used in defining the taxable value of the item.</xs:documentation> + </xs:annotation> + </xs:element> + </xs:sequence> + </xs:complexType> + <xs:simpleType name="EligibilityType"> + <xs:annotation> + <xs:documentation>Specifies different values of eligibility status</xs:documentation> + </xs:annotation> + <xs:restriction base="xs:string"> + <xs:enumeration value="ELIGIBLE"/> + <xs:enumeration value="INELIGIBLE"/> + <xs:enumeration value="POSSIBLY_ELIGIBLE"/> + </xs:restriction> + </xs:simpleType> + <xs:simpleType name="FedExLocationType"> + <xs:annotation> + <xs:documentation>Identifies a kind of FedEx facility.</xs:documentation> + </xs:annotation> + <xs:restriction base="xs:string"> + <xs:enumeration value="FEDEX_AUTHORIZED_SHIP_CENTER"/> + <xs:enumeration value="FEDEX_EXPRESS_STATION"/> + <xs:enumeration value="FEDEX_FACILITY"/> + <xs:enumeration value="FEDEX_FREIGHT_SERVICE_CENTER"/> + <xs:enumeration value="FEDEX_GROUND_TERMINAL"/> + <xs:enumeration value="FEDEX_HOME_DELIVERY_STATION"/> + <xs:enumeration value="FEDEX_OFFICE"/> + <xs:enumeration value="FEDEX_SELF_SERVICE_LOCATION"/> + <xs:enumeration value="FEDEX_SHIPSITE"/> + <xs:enumeration value="FEDEX_SMART_POST_HUB"/> + </xs:restriction> + </xs:simpleType> <xs:simpleType name="LinearUnits"> <xs:annotation> <xs:documentation>CM = centimeters, IN = inches</xs:documentation> @@ -289,6 +532,15 @@ <xs:enumeration value="IN"/> </xs:restriction> </xs:simpleType> + <xs:complexType name="LocalTimeRange"> + <xs:annotation> + <xs:documentation>Time Range specified in local time.</xs:documentation> + </xs:annotation> + <xs:sequence> + <xs:element name="Begins" type="xs:string" minOccurs="0"/> + <xs:element name="Ends" type="xs:string" minOccurs="0"/> + </xs:sequence> + </xs:complexType> <xs:complexType name="Localization"> <xs:annotation> <xs:documentation>Identifies the representation of human-readable text.</xs:documentation> @@ -306,6 +558,73 @@ </xs:element> </xs:sequence> </xs:complexType> + <xs:complexType name="Measure"> + <xs:sequence> + <xs:element name="Quantity" type="xs:decimal" minOccurs="0"/> + <xs:element name="Units" type="xs:string" minOccurs="0"/> + </xs:sequence> + </xs:complexType> + <xs:complexType name="Money"> + <xs:sequence> + <xs:element name="Currency" type="xs:string" minOccurs="0"/> + <xs:element name="Amount" type="xs:decimal" minOccurs="0"/> + </xs:sequence> + </xs:complexType> + <xs:complexType name="NaftaCommodityDetail"> + <xs:sequence> + <xs:element name="PreferenceCriterion" type="ns:NaftaPreferenceCriterionCode" minOccurs="0"> + <xs:annotation> + <xs:documentation>Defined by NAFTA regulations.</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="ProducerDetermination" type="ns:NaftaProducerDeterminationCode" minOccurs="0"> + <xs:annotation> + <xs:documentation>Defined by NAFTA regulations.</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="ProducerId" type="xs:string" minOccurs="0"> + <xs:annotation> + <xs:documentation>Identification of which producer is associated with this commodity (if multiple producers are used in a single shipment).</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="NetCostMethod" type="ns:NaftaNetCostMethodCode" minOccurs="0"/> + <xs:element name="NetCostDateRange" type="ns:DateRange" minOccurs="0"> + <xs:annotation> + <xs:documentation>Date range over which RVC net cost was calculated.</xs:documentation> + </xs:annotation> + </xs:element> + </xs:sequence> + </xs:complexType> + <xs:simpleType name="NaftaNetCostMethodCode"> + <xs:restriction base="xs:string"> + <xs:enumeration value="NC"/> + <xs:enumeration value="NO"/> + </xs:restriction> + </xs:simpleType> + <xs:simpleType name="NaftaPreferenceCriterionCode"> + <xs:annotation> + <xs:documentation>See instructions for NAFTA Certificate of Origin for code definitions.</xs:documentation> + </xs:annotation> + <xs:restriction base="xs:string"> + <xs:enumeration value="A"/> + <xs:enumeration value="B"/> + <xs:enumeration value="C"/> + <xs:enumeration value="D"/> + <xs:enumeration value="E"/> + <xs:enumeration value="F"/> + </xs:restriction> + </xs:simpleType> + <xs:simpleType name="NaftaProducerDeterminationCode"> + <xs:annotation> + <xs:documentation>See instructions for NAFTA Certificate of Origin for code definitions.</xs:documentation> + </xs:annotation> + <xs:restriction base="xs:string"> + <xs:enumeration value="NO_1"/> + <xs:enumeration value="NO_2"/> + <xs:enumeration value="NO_3"/> + <xs:enumeration value="YES"/> + </xs:restriction> + </xs:simpleType> <xs:complexType name="Notification"> <xs:annotation> <xs:documentation>The descriptive data regarding the result of the submitted transaction.</xs:documentation> @@ -382,7 +701,18 @@ <xs:documentation>Identification for a FedEx operating company (transportation and non-transportation).</xs:documentation> </xs:annotation> <xs:restriction base="xs:string"> + <xs:enumeration value="FEDEX_CARGO"/> + <xs:enumeration value="FEDEX_CORPORATE_SERVICES"/> + <xs:enumeration value="FEDEX_CORPORATION"/> + <xs:enumeration value="FEDEX_CUSTOMER_INFORMATION_SYSTEMS"/> + <xs:enumeration value="FEDEX_CUSTOM_CRITICAL"/> + <xs:enumeration value="FEDEX_EXPRESS"/> + <xs:enumeration value="FEDEX_FREIGHT"/> + <xs:enumeration value="FEDEX_GROUND"/> + <xs:enumeration value="FEDEX_KINKOS"/> <xs:enumeration value="FEDEX_OFFICE"/> + <xs:enumeration value="FEDEX_SERVICES"/> + <xs:enumeration value="FEDEX_TRADE_NETWORKS"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="PackagingType"> @@ -394,11 +724,42 @@ <xs:enumeration value="FEDEX_25KG_BOX"/> <xs:enumeration value="FEDEX_BOX"/> <xs:enumeration value="FEDEX_ENVELOPE"/> + <xs:enumeration value="FEDEX_EXTRA_LARGE_BOX"/> + <xs:enumeration value="FEDEX_LARGE_BOX"/> + <xs:enumeration value="FEDEX_MEDIUM_BOX"/> <xs:enumeration value="FEDEX_PAK"/> + <xs:enumeration value="FEDEX_SMALL_BOX"/> <xs:enumeration value="FEDEX_TUBE"/> <xs:enumeration value="YOUR_PACKAGING"/> </xs:restriction> </xs:simpleType> + <xs:complexType name="PagingDetail"> + <xs:sequence> + <xs:element name="PagingToken" type="xs:string" minOccurs="0"> + <xs:annotation> + <xs:documentation>When the MoreData field = true in a TrackReply the PagingToken must be sent in the subsequent TrackRequest to retrieve the next page of data.</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="NumberOfResultsPerPage" type="xs:nonNegativeInteger" minOccurs="0"> + <xs:annotation> + <xs:documentation>Specifies the number of results to display per page when the there is more than one page in the subsequent TrackReply.</xs:documentation> + </xs:annotation> + </xs:element> + </xs:sequence> + </xs:complexType> + <xs:simpleType name="PieceCountLocationType"> + <xs:restriction base="xs:string"> + <xs:enumeration value="DESTINATION"/> + <xs:enumeration value="ORIGIN"/> + </xs:restriction> + </xs:simpleType> + <xs:complexType name="PieceCountVerificationDetail"> + <xs:sequence> + <xs:element name="CountLocationType" type="ns:PieceCountLocationType" minOccurs="0"/> + <xs:element name="Count" type="xs:nonNegativeInteger" minOccurs="0"/> + <xs:element name="Description" type="xs:string" minOccurs="0"/> + </xs:sequence> + </xs:complexType> <xs:complexType name="QualifiedTrackingNumber"> <xs:annotation> <xs:documentation>Tracking number and additional shipment data used to identify a unique shipment for proof of delivery.</xs:documentation> @@ -431,13 +792,115 @@ </xs:element> </xs:sequence> </xs:complexType> - <xs:simpleType name="RedirectToHoldEligibilityType"> - <xs:restriction base="xs:string"> - <xs:enumeration value="ELIGIBLE"/> - <xs:enumeration value="INELIGIBLE"/> - <xs:enumeration value="POSSIBLY_ELIGIBLE"/> - </xs:restriction> - </xs:simpleType> + <xs:complexType name="SendNotificationsReply"> + <xs:sequence> + <xs:element name="HighestSeverity" type="ns:NotificationSeverityType" minOccurs="1"> + <xs:annotation> + <xs:documentation>This contains the severity type of the most severe Notification in the Notifications array.</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="Notifications" type="ns:Notification" minOccurs="1" maxOccurs="unbounded"> + <xs:annotation> + <xs:documentation>Information about the request/reply such was the transaction successful or not, and any additional information relevant to the request and/or reply. There may be multiple Notifications in a reply.</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="TransactionDetail" type="ns:TransactionDetail" minOccurs="0"> + <xs:annotation> + <xs:documentation>Contains the CustomerTransactionDetail that is echoed back to the caller for matching requests and replies and a Localization element for defining the language/translation used in the reply data.</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="Version" type="ns:VersionId" minOccurs="1"> + <xs:annotation> + <xs:documentation>Contains the version of the reply being used.</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="DuplicateWaybill" type="xs:boolean" minOccurs="0"> + <xs:annotation> + <xs:documentation>True if duplicate packages (more than one package with the same tracking number) have been found, the packages array contains information about each duplicate. Use this information to determine which of the tracking numbers is the one you need and resend your request using the tracking number and TrackingNumberUniqueIdentifier for that package.</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="MoreDataAvailable" type="xs:boolean" minOccurs="0"> + <xs:annotation> + <xs:documentation>True if additional packages remain to be retrieved.</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="PagingToken" type="xs:string" minOccurs="0"> + <xs:annotation> + <xs:documentation>Value that must be passed in a TrackNotification request to retrieve the next set of packages (when MoreDataAvailable = true).</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="Packages" type="ns:TrackNotificationPackage" minOccurs="0" maxOccurs="unbounded"> + <xs:annotation> + <xs:documentation>Information about the notifications that are available for this tracking number. If there are duplicates the ship date and destination address information is returned for determining which TrackingNumberUniqueIdentifier to use on a subsequent request.</xs:documentation> + </xs:annotation> + </xs:element> + </xs:sequence> + </xs:complexType> + <xs:complexType name="SendNotificationsRequest"> + <xs:sequence> + <xs:element name="WebAuthenticationDetail" type="ns:WebAuthenticationDetail" minOccurs="1"> + <xs:annotation> + <xs:documentation>Descriptive data to be used in authentication of the sender's identity (and right to use FedEx web services).</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="ClientDetail" type="ns:ClientDetail" minOccurs="1"> + <xs:annotation> + <xs:documentation>Descriptive data identifying the client submitting the transaction.</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="TransactionDetail" type="ns:TransactionDetail" minOccurs="0"> + <xs:annotation> + <xs:documentation>Contains a free form field that is echoed back in the reply to match requests with replies and data that governs the data payload language/translations</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="Version" type="ns:VersionId" minOccurs="1"/> + <xs:element name="TrackingNumber" type="xs:string" minOccurs="1"> + <xs:annotation> + <xs:documentation>The tracking number to which the notifications will be triggered from.</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="MultiPiece" type="xs:boolean" minOccurs="0"> + <xs:annotation> + <xs:documentation>Indicates whether to return tracking information for all associated packages.</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="PagingToken" type="xs:string" minOccurs="0"> + <xs:annotation> + <xs:documentation>When the MoreDataAvailable field is true in a TrackNotificationReply the PagingToken must be sent in the subsequent TrackNotificationRequest to retrieve the next page of data.</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="TrackingNumberUniqueId" type="xs:string" minOccurs="0"> + <xs:annotation> + <xs:documentation>Use this field when your original request informs you that there are duplicates of this tracking number. If you get duplicates you will also receive some information about each of the duplicate tracking numbers to enable you to chose one and resend that number along with the TrackingNumberUniqueId to get notifications for that tracking number.</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="ShipDateRangeBegin" type="xs:date" minOccurs="0"> + <xs:annotation> + <xs:documentation>To narrow the search to a period in time the ShipDateRangeBegin and ShipDateRangeEnd can be used to help eliminate duplicates.</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="ShipDateRangeEnd" type="xs:date" minOccurs="0"> + <xs:annotation> + <xs:documentation>To narrow the search to a period in time the ShipDateRangeBegin and ShipDateRangeEnd can be used to help eliminate duplicates.</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="SenderEMailAddress" type="xs:string" minOccurs="0"> + <xs:annotation> + <xs:documentation>Included in the email notification identifying the requester of this notification.</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="SenderContactName" type="xs:string" minOccurs="1"> + <xs:annotation> + <xs:documentation>Included in the email notification identifying the requester of this notification.</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="NotificationDetail" type="ns:EMailNotificationDetail" minOccurs="1"> + <xs:annotation> + <xs:documentation>Who to send the email notifications to and for which events. The notificationRecipientType and NotifyOnShipment fields are not used in this request.</xs:documentation> + </xs:annotation> + </xs:element> + </xs:sequence> + </xs:complexType> <xs:simpleType name="ServiceType"> <xs:annotation> <xs:documentation>The service type of the package/shipment.</xs:documentation> @@ -449,11 +912,34 @@ <xs:enumeration value="FEDEX_2_DAY_AM"/> <xs:enumeration value="FEDEX_2_DAY_FREIGHT"/> <xs:enumeration value="FEDEX_3_DAY_FREIGHT"/> + <xs:enumeration value="FEDEX_CARGO_AIRPORT_TO_AIRPORT"/> + <xs:enumeration value="FEDEX_CARGO_FREIGHT_FORWARDING"/> + <xs:enumeration value="FEDEX_CARGO_INTERNATIONAL_EXPRESS_FREIGHT"/> + <xs:enumeration value="FEDEX_CARGO_INTERNATIONAL_PREMIUM"/> + <xs:enumeration value="FEDEX_CARGO_MAIL"/> + <xs:enumeration value="FEDEX_CARGO_REGISTERED_MAIL"/> + <xs:enumeration value="FEDEX_CARGO_SURFACE_MAIL"/> + <xs:enumeration value="FEDEX_CUSTOM_CRITICAL_AIR_EXPEDITE"/> + <xs:enumeration value="FEDEX_CUSTOM_CRITICAL_AIR_EXPEDITE_EXCLUSIVE_USE"/> + <xs:enumeration value="FEDEX_CUSTOM_CRITICAL_AIR_EXPEDITE_NETWORK"/> + <xs:enumeration value="FEDEX_CUSTOM_CRITICAL_CHARTER_AIR"/> + <xs:enumeration value="FEDEX_CUSTOM_CRITICAL_POINT_TO_POINT"/> + <xs:enumeration value="FEDEX_CUSTOM_CRITICAL_SURFACE_EXPEDITE"/> + <xs:enumeration value="FEDEX_CUSTOM_CRITICAL_SURFACE_EXPEDITE_EXCLUSIVE_USE"/> + <xs:enumeration value="FEDEX_CUSTOM_CRITICAL_TEMP_ASSURE_AIR"/> + <xs:enumeration value="FEDEX_CUSTOM_CRITICAL_TEMP_ASSURE_VALIDATED_AIR"/> + <xs:enumeration value="FEDEX_CUSTOM_CRITICAL_WHITE_GLOVE_SERVICES"/> + <xs:enumeration value="FEDEX_DISTANCE_DEFERRED"/> <xs:enumeration value="FEDEX_EXPRESS_SAVER"/> <xs:enumeration value="FEDEX_FIRST_FREIGHT"/> <xs:enumeration value="FEDEX_FREIGHT_ECONOMY"/> <xs:enumeration value="FEDEX_FREIGHT_PRIORITY"/> <xs:enumeration value="FEDEX_GROUND"/> + <xs:enumeration value="FEDEX_NEXT_DAY_AFTERNOON"/> + <xs:enumeration value="FEDEX_NEXT_DAY_EARLY_MORNING"/> + <xs:enumeration value="FEDEX_NEXT_DAY_END_OF_DAY"/> + <xs:enumeration value="FEDEX_NEXT_DAY_FREIGHT"/> + <xs:enumeration value="FEDEX_NEXT_DAY_MID_MORNING"/> <xs:enumeration value="FIRST_OVERNIGHT"/> <xs:enumeration value="GROUND_HOME_DELIVERY"/> <xs:enumeration value="INTERNATIONAL_DISTRIBUTION_FREIGHT"/> @@ -465,10 +951,19 @@ <xs:enumeration value="INTERNATIONAL_PRIORITY_DISTRIBUTION"/> <xs:enumeration value="INTERNATIONAL_PRIORITY_FREIGHT"/> <xs:enumeration value="PRIORITY_OVERNIGHT"/> + <xs:enumeration value="SAME_DAY"/> + <xs:enumeration value="SAME_DAY_CITY"/> <xs:enumeration value="SMART_POST"/> <xs:enumeration value="STANDARD_OVERNIGHT"/> + <xs:enumeration value="TRANSBORDER_DISTRIBUTION_CONSOLIDATION"/> </xs:restriction> </xs:simpleType> + <xs:complexType name="SignatureImageDetail"> + <xs:sequence> + <xs:element name="Image" type="xs:base64Binary" minOccurs="0"/> + <xs:element name="Notifications" type="ns:Notification" minOccurs="0" maxOccurs="unbounded"/> + </xs:sequence> + </xs:complexType> <xs:complexType name="SignatureProofOfDeliveryFaxReply"> <xs:annotation> <xs:documentation>FedEx Signature Proof Of Delivery Fax reply.</xs:documentation> @@ -554,6 +1049,7 @@ </xs:annotation> <xs:restriction base="xs:string"> <xs:enumeration value="PDF"/> + <xs:enumeration value="PNG"/> </xs:restriction> </xs:simpleType> <xs:complexType name="SignatureProofOfDeliveryLetterReply"> @@ -635,6 +1131,32 @@ </xs:element> </xs:sequence> </xs:complexType> + <xs:complexType name="SpecialInstructionStatusDetail"> + <xs:sequence> + <xs:element name="Status" type="ns:SpecialInstructionsStatusCode" minOccurs="0"> + <xs:annotation> + <xs:documentation>Specifies the status of the track special instructions requested.</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="StatusCreateTime" type="xs:dateTime" minOccurs="0"> + <xs:annotation> + <xs:documentation>Time when the status was changed.</xs:documentation> + </xs:annotation> + </xs:element> + </xs:sequence> + </xs:complexType> + <xs:simpleType name="SpecialInstructionsStatusCode"> + <xs:restriction base="xs:string"> + <xs:enumeration value="ACCEPTED"/> + <xs:enumeration value="CANCELLED"/> + <xs:enumeration value="DENIED"/> + <xs:enumeration value="HELD"/> + <xs:enumeration value="MODIFIED"/> + <xs:enumeration value="RELINQUISHED"/> + <xs:enumeration value="REQUESTED"/> + <xs:enumeration value="SET"/> + </xs:restriction> + </xs:simpleType> <xs:complexType name="StringBarcode"> <xs:annotation> <xs:documentation>Each instance of this data type represents a barcode whose content must be represented as ASCII text (i.e. not binary data).</xs:documentation> @@ -662,22 +1184,64 @@ <xs:enumeration value="USPS"/> </xs:restriction> </xs:simpleType> + <xs:complexType name="TrackAdvanceNotificationDetail"> + <xs:sequence> + <xs:element name="EstimatedTimeOfArrival" type="xs:dateTime" minOccurs="0"/> + <xs:element name="Reason" type="xs:string" minOccurs="0"/> + <xs:element name="Status" type="ns:TrackAdvanceNotificationStatusType" minOccurs="0"/> + <xs:element name="StatusDescription" type="xs:string" minOccurs="0"/> + <xs:element name="StatusTime" type="xs:dateTime" minOccurs="0"/> + </xs:sequence> + </xs:complexType> + <xs:simpleType name="TrackAdvanceNotificationStatusType"> + <xs:restriction base="xs:string"> + <xs:enumeration value="BACK_ON_TRACK"/> + <xs:enumeration value="FAIL"/> + </xs:restriction> + </xs:simpleType> + <xs:complexType name="TrackChargeDetail"> + <xs:sequence> + <xs:element name="Type" type="ns:TrackChargeDetailType" minOccurs="0"/> + <xs:element name="ChargeAmount" type="ns:Money" minOccurs="0"/> + </xs:sequence> + </xs:complexType> + <xs:simpleType name="TrackChargeDetailType"> + <xs:restriction base="xs:string"> + <xs:enumeration value="ORIGINAL_CHARGES"/> + </xs:restriction> + </xs:simpleType> <xs:simpleType name="TrackDeliveryLocationType"> <xs:annotation> <xs:documentation>The delivery location at the delivered to address.</xs:documentation> </xs:annotation> <xs:restriction base="xs:string"> + <xs:enumeration value="APARTMENT_OFFICE"/> <xs:enumeration value="FEDEX_LOCATION"/> + <xs:enumeration value="GATE_HOUSE"/> <xs:enumeration value="GUARD_OR_SECURITY_STATION"/> <xs:enumeration value="IN_BOND_OR_CAGE"/> + <xs:enumeration value="LEASING_OFFICE"/> <xs:enumeration value="MAILROOM"/> + <xs:enumeration value="MAIN_OFFICE"/> + <xs:enumeration value="MANAGER_OFFICE"/> <xs:enumeration value="OTHER"/> <xs:enumeration value="PHARMACY"/> <xs:enumeration value="RECEPTIONIST_OR_FRONT_DESK"/> + <xs:enumeration value="RENTAL_OFFICE"/> <xs:enumeration value="RESIDENCE"/> <xs:enumeration value="SHIPPING_RECEIVING"/> </xs:restriction> </xs:simpleType> + <xs:simpleType name="TrackDeliveryOptionType"> + <xs:restriction base="xs:string"> + <xs:enumeration value="APPOINTMENT"/> + <xs:enumeration value="DATE_CERTAIN"/> + <xs:enumeration value="ELECTRONIC_SIGNATURE_RELEASE"/> + <xs:enumeration value="EVENING"/> + <xs:enumeration value="REDIRECT_TO_HOLD_AT_LOCATION"/> + <xs:enumeration value="REROUTE"/> + </xs:restriction> + </xs:simpleType> <xs:complexType name="TrackDetail"> <xs:annotation> <xs:documentation>Detailed tracking information about a particular package.</xs:documentation> @@ -699,16 +1263,12 @@ <xs:documentation>When duplicate tracking numbers exist this data is returned with summary information for each of the duplicates. The summary information is used to determine which of the duplicates the intended tracking number is. This identifier is used on a subsequent track request to retrieve the tracking data for the desired tracking number.</xs:documentation> </xs:annotation> </xs:element> - <xs:element name="StatusCode" type="xs:string" minOccurs="0"> + <xs:element name="StatusDetail" type="ns:TrackStatusDetail" minOccurs="0"> <xs:annotation> - <xs:documentation>A code that identifies this type of status. This is the most recent status.</xs:documentation> - </xs:annotation> - </xs:element> - <xs:element name="StatusDescription" type="xs:string" minOccurs="0"> - <xs:annotation> - <xs:documentation>A human-readable description of this status.</xs:documentation> + <xs:documentation>Specifies details about the status of the shipment being tracked.</xs:documentation> </xs:annotation> </xs:element> + <xs:element name="CustomerExceptionRequests" type="ns:CustomerExceptionRequestDetail" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="Reconciliation" type="ns:TrackReconciliation" minOccurs="0"> <xs:annotation> <xs:documentation>Used to report the status of a piece of a multiple piece shipment which is no longer traveling with the rest of the packages in the shipment or has not been accounted for.</xs:documentation> @@ -719,6 +1279,8 @@ <xs:documentation>Used to convey information such as. 1. FedEx has received information about a package but has not yet taken possession of it. 2. FedEx has handed the package off to a third party for final delivery. 3. The package delivery has been cancelled</xs:documentation> </xs:annotation> </xs:element> + <xs:element name="DestinationServiceArea" type="xs:string" minOccurs="0"/> + <xs:element name="DestinationServiceAreaDescription" type="xs:string" minOccurs="0"/> <xs:element name="CarrierCode" type="ns:CarrierCodeType" minOccurs="0"> <xs:annotation> <xs:documentation>Identifies a FedEx operating company (transportation).</xs:documentation> @@ -729,24 +1291,34 @@ <xs:documentation>Identifies operating transportation company that is the specific to the carrier code.</xs:documentation> </xs:annotation> </xs:element> + <xs:element name="OperatingCompanyOrCarrierDescription" type="xs:string" minOccurs="0"> + <xs:annotation> + <xs:documentation>Specifies a detailed description about the carrier or the operating company.</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="CartageAgentCompanyName" type="xs:string" minOccurs="0"> + <xs:annotation> + <xs:documentation>If the package was interlined to a cartage agent, this is the name of the cartage agent. (Returned for CSR SL only.)</xs:documentation> + </xs:annotation> + </xs:element> <xs:element name="ProductionLocationContactAndAddress" type="ns:ContactAndAddress" minOccurs="0"> <xs:annotation> <xs:documentation>Specifies the FXO production centre contact and address.</xs:documentation> </xs:annotation> </xs:element> - <xs:element name="OtherIdentifiers" type="ns:TrackPackageIdentifier" minOccurs="0" maxOccurs="unbounded"> + <xs:element name="OtherIdentifiers" type="ns:TrackOtherIdentifierDetail" minOccurs="0" maxOccurs="unbounded"> <xs:annotation> <xs:documentation>Other related identifiers for this package such as reference numbers.</xs:documentation> </xs:annotation> </xs:element> - <xs:element name="ServiceInfo" type="xs:string" minOccurs="0"> + <xs:element name="FormId" type="xs:string" minOccurs="0"> <xs:annotation> - <xs:documentation>Retained for legacy compatibility only. User/screen friendly description of the Service type (e.g. Priority Overnight).</xs:documentation> + <xs:documentation>(Returned for CSR SL only.)</xs:documentation> </xs:annotation> </xs:element> - <xs:element name="ServiceType" type="ns:ServiceType" minOccurs="0"> + <xs:element name="Service" type="ns:TrackServiceDescriptionDetail" minOccurs="0"> <xs:annotation> - <xs:documentation>Strict representation of the Service type (e.g. PRIORITY_OVERNIGHT).</xs:documentation> + <xs:documentation>Specifies details about service such as service description and type.</xs:documentation> </xs:annotation> </xs:element> <xs:element name="PackageWeight" type="ns:Weight" minOccurs="0"> @@ -789,8 +1361,40 @@ <xs:documentation>The number of packages in this shipment.</xs:documentation> </xs:annotation> </xs:element> - <xs:element name="TrackReturnLabelType" type="ns:TrackReturnLabelType" minOccurs="0"/> - <xs:element name="TrackReturnDescription" type="xs:string" minOccurs="0"/> + <xs:element name="Charges" type="ns:TrackChargeDetail" minOccurs="0" maxOccurs="unbounded"> + <xs:annotation> + <xs:documentation>Specifies the details about the SPOC details.</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="NickName" type="xs:string" minOccurs="0"/> + <xs:element name="Notes" type="xs:string" minOccurs="0"/> + <xs:element name="Attributes" type="ns:TrackDetailAttributeType" minOccurs="0" maxOccurs="unbounded"/> + <xs:element name="ShipmentContents" type="ns:ContentRecord" minOccurs="0" maxOccurs="unbounded"/> + <xs:element name="PackageContents" type="xs:string" minOccurs="0" maxOccurs="unbounded"/> + <xs:element name="ClearanceLocationCode" type="xs:string" minOccurs="0"/> + <xs:element name="Commodities" type="ns:Commodity" minOccurs="0" maxOccurs="unbounded"/> + <xs:element name="ReturnDetail" type="ns:TrackReturnDetail" minOccurs="0"/> + <xs:element name="CustomsOptionDetails" type="ns:CustomsOptionDetail" minOccurs="0" maxOccurs="unbounded"> + <xs:annotation> + <xs:documentation>Specifies the reason for return.</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="AdvanceNotificationDetail" type="ns:TrackAdvanceNotificationDetail" minOccurs="0"/> + <xs:element name="SpecialHandlings" type="ns:TrackSpecialHandling" minOccurs="0" maxOccurs="unbounded"> + <xs:annotation> + <xs:documentation>List of special handlings that applied to this package. (Returned for CSR SL only.)</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="Shipper" type="ns:Contact" minOccurs="0"> + <xs:annotation> + <xs:documentation>(Returned for CSR SL only.)</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="PossessionStatus" type="ns:TrackPossessionStatusType" minOccurs="0"> + <xs:annotation> + <xs:documentation>Indicates last-known possession of package (Returned for CSR SL only.)</xs:documentation> + </xs:annotation> + </xs:element> <xs:element name="ShipperAddress" type="ns:Address" minOccurs="0"> <xs:annotation> <xs:documentation>The address information for the shipper.</xs:documentation> @@ -801,6 +1405,11 @@ <xs:documentation>The address of the FedEx pickup location/facility.</xs:documentation> </xs:annotation> </xs:element> + <xs:element name="OriginStationId" type="xs:string" minOccurs="0"> + <xs:annotation> + <xs:documentation>(Returned for CSR SL only.)</xs:documentation> + </xs:annotation> + </xs:element> <xs:element name="EstimatedPickupTimestamp" type="xs:dateTime" minOccurs="0"> <xs:annotation> <xs:documentation>Estimated package pickup time for shipments that haven't been picked up.</xs:documentation> @@ -821,16 +1430,54 @@ <xs:documentation>Total distance package still has to travel. Returned for Custom Critical shipments.</xs:documentation> </xs:annotation> </xs:element> + <xs:element name="SpecialInstructions" type="ns:TrackSpecialInstruction" minOccurs="0" maxOccurs="unbounded"> + <xs:annotation> + <xs:documentation>Provides additional details about package delivery.</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="Recipient" type="ns:Contact" minOccurs="0"> + <xs:annotation> + <xs:documentation>(Returned for CSR SL only.)</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="LastUpdatedDestinationAddress" type="ns:Address" minOccurs="0"> + <xs:annotation> + <xs:documentation>This is the latest updated destination address.</xs:documentation> + </xs:annotation> + </xs:element> <xs:element name="DestinationAddress" type="ns:Address" minOccurs="0"> <xs:annotation> <xs:documentation>The address this package is to be (or has been) delivered.</xs:documentation> </xs:annotation> </xs:element> + <xs:element name="HoldAtLocationContact" type="ns:Contact" minOccurs="0"/> + <xs:element name="HoldAtLocationAddress" type="ns:Address" minOccurs="0"> + <xs:annotation> + <xs:documentation>The address this package is requested to placed on hold.</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="DestinationStationId" type="xs:string" minOccurs="0"> + <xs:annotation> + <xs:documentation>(Returned for CSR SL only.)</xs:documentation> + </xs:annotation> + </xs:element> <xs:element name="DestinationLocationAddress" type="ns:Address" minOccurs="0"> <xs:annotation> <xs:documentation>The address of the FedEx delivery location/facility.</xs:documentation> </xs:annotation> </xs:element> + <xs:element name="DestinationLocationType" type="ns:FedExLocationType" minOccurs="0"/> + <xs:element name="DestinationLocationTimeZoneOffset" type="xs:string" minOccurs="0"/> + <xs:element name="CommitmentTimestamp" type="xs:dateTime" minOccurs="0"> + <xs:annotation> + <xs:documentation>Date and time the package should be (or should have been) delivered. (Returned for CSR SL only.)</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="AppointmentDeliveryTimestamp" type="xs:dateTime" minOccurs="0"> + <xs:annotation> + <xs:documentation>Date and time the package would be delivered if the package has appointment delivery as a special service.</xs:documentation> + </xs:annotation> + </xs:element> <xs:element name="EstimatedDeliveryTimestamp" type="xs:dateTime" minOccurs="0"> <xs:annotation> <xs:documentation>Projected package delivery time based on ship time stamp, service and destination. Not populated if delivery has already occurred.</xs:documentation> @@ -861,16 +1508,28 @@ <xs:documentation>User/screen friendly representation of the DeliveryLocationType (delivery location at the delivered to address). Can be returned in localized text.</xs:documentation> </xs:annotation> </xs:element> + <xs:element name="DeliveryAttempts" type="xs:nonNegativeInteger" minOccurs="0"> + <xs:annotation> + <xs:documentation>Specifies the number of delivery attempts made to deliver the shipment.</xs:documentation> + </xs:annotation> + </xs:element> <xs:element name="DeliverySignatureName" type="xs:string" minOccurs="0"> <xs:annotation> <xs:documentation>This is either the name of the person that signed for the package or "Signature not requested" or "Signature on file".</xs:documentation> </xs:annotation> </xs:element> - <xs:element name="SignatureProofOfDeliveryAvailable" type="xs:boolean" minOccurs="0"> + <xs:element name="PieceCountVerificationDetails" type="ns:PieceCountVerificationDetail" minOccurs="0" maxOccurs="unbounded"> <xs:annotation> - <xs:documentation>True if signed for by signature image is available.</xs:documentation> + <xs:documentation>Specifies the details about the count of the packages delivered at the delivery location and the count of the packages at the origin.</xs:documentation> </xs:annotation> </xs:element> + <xs:element name="TotalUniqueAddressCountInConsolidation" type="xs:nonNegativeInteger" minOccurs="0"> + <xs:annotation> + <xs:documentation>Specifies the total number of unique addresses on the CRNs in a consolidation.</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="AvailableImages" type="ns:AvailableImageType" minOccurs="0" maxOccurs="unbounded"/> + <xs:element name="Signature" type="ns:SignatureImageDetail" minOccurs="0"/> <xs:element name="NotificationEventsAvailable" type="ns:EMailNotificationEventType" minOccurs="0" maxOccurs="unbounded"> <xs:annotation> <xs:documentation>The types of email notifications that are available for the package.</xs:documentation> @@ -881,9 +1540,9 @@ <xs:documentation>Returned for cargo shipments only when they are currently split across vehicles.</xs:documentation> </xs:annotation> </xs:element> - <xs:element name="RedirectToHoldEligibility" type="ns:RedirectToHoldEligibilityType" minOccurs="0"> + <xs:element name="DeliveryOptionEligibilityDetails" type="ns:DeliveryOptionEligibilityDetail" minOccurs="0" maxOccurs="unbounded"> <xs:annotation> - <xs:documentation>Indicates redirection eligibility as determined by tracking service, subject to refinement/override by redirect-to-hold service.</xs:documentation> + <xs:documentation>Specifies the details about the eligibility for different delivery options.</xs:documentation> </xs:annotation> </xs:element> <xs:element name="Events" type="ns:TrackEvent" minOccurs="0" maxOccurs="unbounded"> @@ -893,6 +1552,11 @@ </xs:element> </xs:sequence> </xs:complexType> + <xs:simpleType name="TrackDetailAttributeType"> + <xs:restriction base="xs:string"> + <xs:enumeration value="INCLUDED_IN_WATCHLIST"/> + </xs:restriction> + </xs:simpleType> <xs:complexType name="TrackEvent"> <xs:annotation> <xs:documentation>FedEx scanning information about a package.</xs:documentation> @@ -928,6 +1592,11 @@ <xs:documentation>Address information of the station that is responsible for the scan.</xs:documentation> </xs:annotation> </xs:element> + <xs:element name="StationId" type="xs:string" minOccurs="0"> + <xs:annotation> + <xs:documentation>FedEx location ID where the scan took place. (Returned for CSR SL only.)</xs:documentation> + </xs:annotation> + </xs:element> <xs:element name="ArrivalLocation" type="ns:ArrivalLocationType" minOccurs="0"> <xs:annotation> <xs:documentation>Indicates where the arrival actually occurred.</xs:documentation> @@ -945,6 +1614,7 @@ <xs:enumeration value="CUSTOMER_AUTHORIZATION_NUMBER"/> <xs:enumeration value="CUSTOMER_REFERENCE"/> <xs:enumeration value="DEPARTMENT"/> + <xs:enumeration value="DOCUMENT_AIRWAY_BILL"/> <xs:enumeration value="FREE_FORM_REFERENCE"/> <xs:enumeration value="GROUND_INTERNATIONAL"/> <xs:enumeration value="GROUND_SHIPMENT_ID"/> @@ -953,9 +1623,11 @@ <xs:enumeration value="JOB_GLOBAL_TRACKING_NUMBER"/> <xs:enumeration value="ORDER_GLOBAL_TRACKING_NUMBER"/> <xs:enumeration value="ORDER_TO_PAY_NUMBER"/> + <xs:enumeration value="OUTBOUND_LINK_TO_RETURN"/> <xs:enumeration value="PARTNER_CARRIER_NUMBER"/> <xs:enumeration value="PART_NUMBER"/> <xs:enumeration value="PURCHASE_ORDER"/> + <xs:enumeration value="REROUTE_TRACKING_NUMBER"/> <xs:enumeration value="RETURNED_TO_SHIPPER_TRACKING_NUMBER"/> <xs:enumeration value="RETURN_MATERIALS_AUTHORIZATION"/> <xs:enumeration value="SHIPPER_REFERENCE"/> @@ -1010,123 +1682,11 @@ </xs:element> </xs:sequence> </xs:complexType> - <xs:complexType name="TrackNotificationReply"> - <xs:annotation> - <xs:documentation>FedEx Track Notification reply.</xs:documentation> - </xs:annotation> - <xs:sequence> - <xs:element name="HighestSeverity" type="ns:NotificationSeverityType" minOccurs="1"> - <xs:annotation> - <xs:documentation>This contains the severity type of the most severe Notification in the Notifications array.</xs:documentation> - </xs:annotation> - </xs:element> - <xs:element name="Notifications" type="ns:Notification" minOccurs="1" maxOccurs="unbounded"> - <xs:annotation> - <xs:documentation>Information about the request/reply such was the transaction successful or not, and any additional information relevant to the request and/or reply. There may be multiple Notifications in a reply.</xs:documentation> - </xs:annotation> - </xs:element> - <xs:element name="TransactionDetail" type="ns:TransactionDetail" minOccurs="0"> - <xs:annotation> - <xs:documentation>Contains the CustomerTransactionDetail that is echoed back to the caller for matching requests and replies and a Localization element for defining the language/translation used in the reply data.</xs:documentation> - </xs:annotation> - </xs:element> - <xs:element name="Version" type="ns:VersionId" minOccurs="1"> - <xs:annotation> - <xs:documentation>Contains the version of the reply being used.</xs:documentation> - </xs:annotation> - </xs:element> - <xs:element name="DuplicateWaybill" type="xs:boolean" minOccurs="0"> - <xs:annotation> - <xs:documentation>True if duplicate packages (more than one package with the same tracking number) have been found, the packages array contains information about each duplicate. Use this information to determine which of the tracking numbers is the one you need and resend your request using the tracking number and TrackingNumberUniqueIdentifier for that package.</xs:documentation> - </xs:annotation> - </xs:element> - <xs:element name="MoreDataAvailable" type="xs:boolean" minOccurs="0"> - <xs:annotation> - <xs:documentation>True if additional packages remain to be retrieved.</xs:documentation> - </xs:annotation> - </xs:element> - <xs:element name="PagingToken" type="xs:string" minOccurs="0"> - <xs:annotation> - <xs:documentation>Value that must be passed in a TrackNotification request to retrieve the next set of packages (when MoreDataAvailable = true).</xs:documentation> - </xs:annotation> - </xs:element> - <xs:element name="Packages" type="ns:TrackNotificationPackage" minOccurs="0" maxOccurs="unbounded"> - <xs:annotation> - <xs:documentation>Information about the notifications that are available for this tracking number. If there are duplicates the ship date and destination address information is returned for determining which TrackingNumberUniqueIdentifier to use on a subsequent request.</xs:documentation> - </xs:annotation> - </xs:element> - </xs:sequence> - </xs:complexType> - <xs:complexType name="TrackNotificationRequest"> - <xs:annotation> - <xs:documentation>FedEx Track Notification request.</xs:documentation> - </xs:annotation> + <xs:complexType name="TrackOtherIdentifierDetail"> <xs:sequence> - <xs:element name="WebAuthenticationDetail" type="ns:WebAuthenticationDetail" minOccurs="1"> - <xs:annotation> - <xs:documentation>Descriptive data to be used in authentication of the sender's identity (and right to use FedEx web services).</xs:documentation> - </xs:annotation> - </xs:element> - <xs:element name="ClientDetail" type="ns:ClientDetail" minOccurs="1"> - <xs:annotation> - <xs:documentation>Descriptive data identifying the client submitting the transaction.</xs:documentation> - </xs:annotation> - </xs:element> - <xs:element name="TransactionDetail" type="ns:TransactionDetail" minOccurs="0"> - <xs:annotation> - <xs:documentation>Contains a free form field that is echoed back in the reply to match requests with replies and data that governs the data payload language/translations</xs:documentation> - </xs:annotation> - </xs:element> - <xs:element name="Version" type="ns:VersionId" minOccurs="1"> - <xs:annotation> - <xs:documentation>Identifies the version/level of a service operation expected by a caller (in each request) and performed by the callee (in each reply).</xs:documentation> - </xs:annotation> - </xs:element> - <xs:element name="TrackingNumber" type="xs:string" minOccurs="1"> - <xs:annotation> - <xs:documentation>The tracking number to which the notifications will be triggered from.</xs:documentation> - </xs:annotation> - </xs:element> - <xs:element name="MultiPiece" type="xs:boolean" minOccurs="0"> - <xs:annotation> - <xs:documentation>Indicates whether to return tracking information for all associated packages.</xs:documentation> - </xs:annotation> - </xs:element> - <xs:element name="PagingToken" type="xs:string" minOccurs="0"> - <xs:annotation> - <xs:documentation>When the MoreDataAvailable field is true in a TrackNotificationReply the PagingToken must be sent in the subsequent TrackNotificationRequest to retrieve the next page of data.</xs:documentation> - </xs:annotation> - </xs:element> - <xs:element name="TrackingNumberUniqueId" type="xs:string" minOccurs="0"> - <xs:annotation> - <xs:documentation>Use this field when your original request informs you that there are duplicates of this tracking number. If you get duplicates you will also receive some information about each of the duplicate tracking numbers to enable you to chose one and resend that number along with the TrackingNumberUniqueId to get notifications for that tracking number.</xs:documentation> - </xs:annotation> - </xs:element> - <xs:element name="ShipDateRangeBegin" type="xs:date" minOccurs="0"> - <xs:annotation> - <xs:documentation>To narrow the search to a period in time the ShipDateRangeBegin and ShipDateRangeEnd can be used to help eliminate duplicates.</xs:documentation> - </xs:annotation> - </xs:element> - <xs:element name="ShipDateRangeEnd" type="xs:date" minOccurs="0"> - <xs:annotation> - <xs:documentation>To narrow the search to a period in time the ShipDateRangeBegin and ShipDateRangeEnd can be used to help eliminate duplicates.</xs:documentation> - </xs:annotation> - </xs:element> - <xs:element name="SenderEMailAddress" type="xs:string" minOccurs="1"> - <xs:annotation> - <xs:documentation>Included in the email notification identifying the requester of this notification.</xs:documentation> - </xs:annotation> - </xs:element> - <xs:element name="SenderContactName" type="xs:string" minOccurs="1"> - <xs:annotation> - <xs:documentation>Included in the email notification identifying the requester of this notification.</xs:documentation> - </xs:annotation> - </xs:element> - <xs:element name="NotificationDetail" type="ns:EMailNotificationDetail" minOccurs="1"> - <xs:annotation> - <xs:documentation>Who to send the email notifications to and for which events. The notificationRecipientType and NotifyOnShipment fields are not used in this request.</xs:documentation> - </xs:annotation> - </xs:element> + <xs:element name="PackageIdentifier" type="ns:TrackPackageIdentifier" minOccurs="0"/> + <xs:element name="TrackingNumberUniqueIdentifier" type="xs:string" minOccurs="0"/> + <xs:element name="CarrierCode" type="ns:CarrierCodeType" minOccurs="0"/> </xs:sequence> </xs:complexType> <xs:complexType name="TrackPackageIdentifier"> @@ -1134,18 +1694,41 @@ <xs:documentation>The type and value of the package identifier that is to be used to retrieve the tracking information for a package.</xs:documentation> </xs:annotation> <xs:sequence> - <xs:element name="Value" type="xs:string" minOccurs="1"> + <xs:element name="Type" type="ns:TrackIdentifierType" minOccurs="1"> <xs:annotation> - <xs:documentation>The value to be used to retrieve tracking information for a package.</xs:documentation> + <xs:documentation>The type of the Value to be used to retrieve tracking information for a package (e.g. SHIPPER_REFERENCE, PURCHASE_ORDER, TRACKING_NUMBER_OR_DOORTAG, etc..) .</xs:documentation> </xs:annotation> </xs:element> - <xs:element name="Type" type="ns:TrackIdentifierType" minOccurs="1"> + <xs:element name="Value" type="xs:string" minOccurs="1"> <xs:annotation> - <xs:documentation>The type of the Value to be used to retrieve tracking information for a package (e.g. SHIPPER_REFERENCE, PURCHASE_ORDER, TRACKING_NUMBER_OR_DOORTAG, etc..) .</xs:documentation> + <xs:documentation>The value to be used to retrieve tracking information for a package.</xs:documentation> </xs:annotation> </xs:element> </xs:sequence> </xs:complexType> + <xs:simpleType name="TrackPaymentType"> + <xs:restriction base="xs:string"> + <xs:enumeration value="CASH_OR_CHECK_AT_DESTINATION"/> + <xs:enumeration value="CASH_OR_CHECK_AT_ORIGIN"/> + <xs:enumeration value="CREDIT_CARD_AT_DESTINATION"/> + <xs:enumeration value="CREDIT_CARD_AT_ORIGIN"/> + <xs:enumeration value="OTHER"/> + <xs:enumeration value="RECIPIENT_ACCOUNT"/> + <xs:enumeration value="SHIPPER_ACCOUNT"/> + <xs:enumeration value="THIRD_PARTY_ACCOUNT"/> + </xs:restriction> + </xs:simpleType> + <xs:simpleType name="TrackPossessionStatusType"> + <xs:restriction base="xs:string"> + <xs:enumeration value="BROKER"/> + <xs:enumeration value="CARRIER"/> + <xs:enumeration value="CUSTOMS"/> + <xs:enumeration value="RECIPIENT"/> + <xs:enumeration value="SHIPPER"/> + <xs:enumeration value="SPLIT_STATUS"/> + <xs:enumeration value="TRANSFER_PARTNER"/> + </xs:restriction> + </xs:simpleType> <xs:complexType name="TrackReconciliation"> <xs:annotation> <xs:documentation>Used to report the status of a piece of a multiple piece shipment which is no longer traveling with the rest of the packages in the shipment or has not been accounted for.</xs:documentation> @@ -1188,24 +1771,9 @@ <xs:documentation>Contains the version of the reply being used.</xs:documentation> </xs:annotation> </xs:element> - <xs:element name="DuplicateWaybill" type="xs:boolean" minOccurs="0"> - <xs:annotation> - <xs:documentation>True if duplicate packages (more than one package with the same tracking number) have been found, and only limited data will be provided for each one.</xs:documentation> - </xs:annotation> - </xs:element> - <xs:element name="MoreData" type="xs:boolean" minOccurs="0"> - <xs:annotation> - <xs:documentation>True if additional packages remain to be retrieved.</xs:documentation> - </xs:annotation> - </xs:element> - <xs:element name="PagingToken" type="xs:string" minOccurs="0"> - <xs:annotation> - <xs:documentation>Value that must be passed in a TrackNotification request to retrieve the next set of packages (when MoreDataAvailable = true).</xs:documentation> - </xs:annotation> - </xs:element> - <xs:element name="TrackDetails" type="ns:TrackDetail" minOccurs="0" maxOccurs="unbounded"> + <xs:element name="CompletedTrackDetails" type="ns:CompletedTrackDetail" minOccurs="0" maxOccurs="unbounded"> <xs:annotation> - <xs:documentation>Contains detailed tracking information for the requested packages(s).</xs:documentation> + <xs:documentation>Contains detailed tracking entity information.</xs:documentation> </xs:annotation> </xs:element> </xs:sequence> @@ -1235,6 +1803,46 @@ <xs:documentation>The version of the request being used.</xs:documentation> </xs:annotation> </xs:element> + <xs:element name="SelectionDetails" type="ns:TrackSelectionDetail" minOccurs="0" maxOccurs="unbounded"> + <xs:annotation> + <xs:documentation>Specifies the details needed to select the shipment being requested to be tracked.</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="TransactionTimeOutValueInMilliseconds" type="xs:nonNegativeInteger" minOccurs="0"> + <xs:annotation> + <xs:documentation>The customer can specify a desired time out value for this particular transaction.</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="ProcessingOptions" type="ns:TrackRequestProcessingOptionType" minOccurs="0" maxOccurs="unbounded"/> + </xs:sequence> + </xs:complexType> + <xs:simpleType name="TrackRequestProcessingOptionType"> + <xs:restriction base="xs:string"> + <xs:enumeration value="INCLUDE_DETAILED_SCANS"/> + </xs:restriction> + </xs:simpleType> + <xs:complexType name="TrackReturnDetail"> + <xs:sequence> + <xs:element name="MovementStatus" type="ns:TrackReturnMovementStatusType" minOccurs="0"/> + <xs:element name="LabelType" type="ns:TrackReturnLabelType" minOccurs="0"/> + <xs:element name="Description" type="xs:string" minOccurs="0"/> + <xs:element name="AuthorizationName" type="xs:string" minOccurs="0"/> + </xs:sequence> + </xs:complexType> + <xs:simpleType name="TrackReturnLabelType"> + <xs:restriction base="xs:string"> + <xs:enumeration value="EMAIL"/> + <xs:enumeration value="PRINT"/> + </xs:restriction> + </xs:simpleType> + <xs:simpleType name="TrackReturnMovementStatusType"> + <xs:restriction base="xs:string"> + <xs:enumeration value="MOVEMENT_OCCURRED"/> + <xs:enumeration value="NO_MOVEMENT"/> + </xs:restriction> + </xs:simpleType> + <xs:complexType name="TrackSelectionDetail"> + <xs:sequence> <xs:element name="CarrierCode" type="ns:CarrierCodeType" minOccurs="0"> <xs:annotation> <xs:documentation>The FedEx operating company (transportation) used for this package's delivery.</xs:documentation> @@ -1245,7 +1853,7 @@ <xs:documentation>Identifies operating transportation company that is the specific to the carrier code.</xs:documentation> </xs:annotation> </xs:element> - <xs:element name="PackageIdentifier" type="ns:TrackPackageIdentifier" minOccurs="1"> + <xs:element name="PackageIdentifier" type="ns:TrackPackageIdentifier" minOccurs="0"> <xs:annotation> <xs:documentation>The type and value of the package identifier that is to be used to retrieve the tracking information for a package or group of packages.</xs:documentation> </xs:annotation> @@ -1270,29 +1878,181 @@ <xs:documentation>For tracking by references information either the account number or destination postal code and country must be provided.</xs:documentation> </xs:annotation> </xs:element> + <xs:element name="SecureSpodAccount" type="xs:string" minOccurs="0"> + <xs:annotation> + <xs:documentation>Specifies the SPOD account number for the shipment being tracked.</xs:documentation> + </xs:annotation> + </xs:element> <xs:element name="Destination" type="ns:Address" minOccurs="0"> <xs:annotation> <xs:documentation>For tracking by references information either the account number or destination postal code and country must be provided.</xs:documentation> </xs:annotation> </xs:element> - <xs:element name="IncludeDetailedScans" type="xs:boolean" minOccurs="0"> + <xs:element name="PagingDetail" type="ns:PagingDetail" minOccurs="0"> <xs:annotation> - <xs:documentation>If false the reply will contain summary/profile data including current status. If true the reply contains profile + detailed scan activity for each package.</xs:documentation> + <xs:documentation>Specifies the details about how to retrieve the subsequent pages when there is more than one page in the TrackReply.</xs:documentation> </xs:annotation> </xs:element> - <xs:element name="PagingToken" type="xs:string" minOccurs="0"> + <xs:element name="CustomerSpecifiedTimeOutValueInMilliseconds" type="xs:nonNegativeInteger" minOccurs="0"> <xs:annotation> - <xs:documentation>When the MoreData field = true in a TrackReply the PagingToken must be sent in the subsequent TrackRequest to retrieve the next page of data.</xs:documentation> + <xs:documentation>The customer can specify a desired time out value for this particular tracking number.</xs:documentation> </xs:annotation> </xs:element> </xs:sequence> </xs:complexType> - <xs:simpleType name="TrackReturnLabelType"> + <xs:complexType name="TrackServiceDescriptionDetail"> + <xs:sequence> + <xs:element name="Type" type="ns:ServiceType" minOccurs="0"/> + <xs:element name="Description" type="xs:string" minOccurs="0"/> + <xs:element name="ShortDescription" type="xs:string" minOccurs="0"> + <xs:annotation> + <xs:documentation>Specifies a shorter description for the service that is calculated per the service code.</xs:documentation> + </xs:annotation> + </xs:element> + </xs:sequence> + </xs:complexType> + <xs:complexType name="TrackSpecialHandling"> + <xs:sequence> + <xs:element name="Type" type="ns:TrackSpecialHandlingType" minOccurs="0"/> + <xs:element name="Description" type="xs:string" minOccurs="0"/> + <xs:element name="PaymentType" type="ns:TrackPaymentType" minOccurs="0"/> + </xs:sequence> + </xs:complexType> + <xs:simpleType name="TrackSpecialHandlingType"> <xs:restriction base="xs:string"> - <xs:enumeration value="EMAIL"/> - <xs:enumeration value="PRINT"/> + <xs:enumeration value="ACCESSIBLE_DANGEROUS_GOODS"/> + <xs:enumeration value="ADULT_SIGNATURE_OPTION"/> + <xs:enumeration value="AIRBILL_AUTOMATION"/> + <xs:enumeration value="AIRBILL_DELIVERY"/> + <xs:enumeration value="ALCOHOL"/> + <xs:enumeration value="AM_DELIVERY_GUARANTEE"/> + <xs:enumeration value="APPOINTMENT_DELIVERY"/> + <xs:enumeration value="BILL_RECIPIENT"/> + <xs:enumeration value="BROKER_SELECT_OPTION"/> + <xs:enumeration value="CALL_BEFORE_DELIVERY"/> + <xs:enumeration value="CALL_TAG"/> + <xs:enumeration value="CALL_TAG_DAMAGE"/> + <xs:enumeration value="CHARGEABLE_CODE"/> + <xs:enumeration value="COD"/> + <xs:enumeration value="COLLECT"/> + <xs:enumeration value="CONSOLIDATION"/> + <xs:enumeration value="CONSOLIDATION_SMALLS_BAG"/> + <xs:enumeration value="CURRENCY"/> + <xs:enumeration value="CUT_FLOWERS"/> + <xs:enumeration value="DATE_CERTAIN_DELIVERY"/> + <xs:enumeration value="DELIVERY_ON_INVOICE_ACCEPTANCE"/> + <xs:enumeration value="DELIVERY_REATTEMPT"/> + <xs:enumeration value="DELIVERY_RECEIPT"/> + <xs:enumeration value="DELIVER_WEEKDAY"/> + <xs:enumeration value="DIRECT_SIGNATURE_OPTION"/> + <xs:enumeration value="DOMESTIC"/> + <xs:enumeration value="DO_NOT_BREAK_DOWN_PALLETS"/> + <xs:enumeration value="DO_NOT_STACK_PALLETS"/> + <xs:enumeration value="DRY_ICE"/> + <xs:enumeration value="DRY_ICE_ADDED"/> + <xs:enumeration value="EAST_COAST_SPECIAL"/> + <xs:enumeration value="ELECTRONIC_COD"/> + <xs:enumeration value="ELECTRONIC_SIGNATURE_SERVICE"/> + <xs:enumeration value="EVENING_DELIVERY"/> + <xs:enumeration value="EXCLUSIVE_USE"/> + <xs:enumeration value="EXTENDED_DELIVERY"/> + <xs:enumeration value="EXTENDED_PICKUP"/> + <xs:enumeration value="EXTRA_LABOR"/> + <xs:enumeration value="EXTREME_LENGTH"/> + <xs:enumeration value="FOOD"/> + <xs:enumeration value="FREIGHT_ON_VALUE_CARRIER_RISK"/> + <xs:enumeration value="FREIGHT_ON_VALUE_OWN_RISK"/> + <xs:enumeration value="FREIGHT_TO_COLLECT"/> + <xs:enumeration value="FULLY_REGULATED_DANGEROUS_GOODS"/> + <xs:enumeration value="GEL_PACKS_ADDED_OR_REPLACED"/> + <xs:enumeration value="GROUND_SUPPORT_FOR_SMARTPOST"/> + <xs:enumeration value="GUARANTEED_FUNDS"/> + <xs:enumeration value="HAZMAT"/> + <xs:enumeration value="HIGH_FLOOR"/> + <xs:enumeration value="HOLD_AT_LOCATION"/> + <xs:enumeration value="HOLIDAY_DELIVERY"/> + <xs:enumeration value="INACCESSIBLE_DANGEROUS_GOODS"/> + <xs:enumeration value="INDIRECT_SIGNATURE_OPTION"/> + <xs:enumeration value="INSIDE_DELIVERY"/> + <xs:enumeration value="INSIDE_PICKUP"/> + <xs:enumeration value="INTERNATIONAL"/> + <xs:enumeration value="INTERNATIONAL_CONTROLLED_EXPORT"/> + <xs:enumeration value="INTERNATIONAL_MAIL_SERVICE"/> + <xs:enumeration value="INTERNATIONAL_TRAFFIC_IN_ARMS_REGULATIONS"/> + <xs:enumeration value="LIFTGATE"/> + <xs:enumeration value="LIFTGATE_DELIVERY"/> + <xs:enumeration value="LIFTGATE_PICKUP"/> + <xs:enumeration value="LIMITED_ACCESS_DELIVERY"/> + <xs:enumeration value="LIMITED_ACCESS_PICKUP"/> + <xs:enumeration value="LIMITED_QUANTITIES_DANGEROUS_GOODS"/> + <xs:enumeration value="MARKING_OR_TAGGING"/> + <xs:enumeration value="NET_RETURN"/> + <xs:enumeration value="NON_BUSINESS_TIME"/> + <xs:enumeration value="NON_STANDARD_CONTAINER"/> + <xs:enumeration value="NO_SIGNATURE_REQUIRED_SIGNATURE_OPTION"/> + <xs:enumeration value="ORDER_NOTIFY"/> + <xs:enumeration value="OTHER"/> + <xs:enumeration value="OTHER_REGULATED_MATERIAL_DOMESTIC"/> + <xs:enumeration value="PACKAGE_RETURN_PROGRAM"/> + <xs:enumeration value="PIECE_COUNT_VERIFICATION"/> + <xs:enumeration value="POISON"/> + <xs:enumeration value="PREPAID"/> + <xs:enumeration value="PRIORITY_ALERT"/> + <xs:enumeration value="PRIORITY_ALERT_PLUS"/> + <xs:enumeration value="PROTECTION_FROM_FREEZING"/> + <xs:enumeration value="RAIL_MODE"/> + <xs:enumeration value="RECONSIGNMENT_CHARGES"/> + <xs:enumeration value="REROUTE_CROSS_COUNTRY_DEFERRED"/> + <xs:enumeration value="REROUTE_CROSS_COUNTRY_EXPEDITED"/> + <xs:enumeration value="REROUTE_LOCAL"/> + <xs:enumeration value="RESIDENTIAL_DELIVERY"/> + <xs:enumeration value="RESIDENTIAL_PICKUP"/> + <xs:enumeration value="RETURNS_CLEARANCE"/> + <xs:enumeration value="RETURNS_CLEARANCE_SPECIAL_ROUTING_REQUIRED"/> + <xs:enumeration value="RETURN_MANAGER"/> + <xs:enumeration value="SATURDAY_DELIVERY"/> + <xs:enumeration value="SHIPMENT_PLACED_IN_COLD_STORAGE"/> + <xs:enumeration value="SINGLE_SHIPMENT"/> + <xs:enumeration value="SMALL_QUANTITY_EXCEPTION"/> + <xs:enumeration value="SORT_AND_SEGREGATE"/> + <xs:enumeration value="SPECIAL_DELIVERY"/> + <xs:enumeration value="SPECIAL_EQUIPMENT"/> + <xs:enumeration value="STANDARD_GROUND_SERVICE"/> + <xs:enumeration value="STORAGE"/> + <xs:enumeration value="SUNDAY_DELIVERY"/> + <xs:enumeration value="THIRD_PARTY_BILLING"/> + <xs:enumeration value="THIRD_PARTY_CONSIGNEE"/> + <xs:enumeration value="TOP_LOAD"/> + <xs:enumeration value="WEEKEND_DELIVERY"/> + <xs:enumeration value="WEEKEND_PICKUP"/> </xs:restriction> </xs:simpleType> + <xs:complexType name="TrackSpecialInstruction"> + <xs:sequence> + <xs:element name="Description" type="xs:string" minOccurs="0"/> + <xs:element name="DeliveryOption" type="ns:TrackDeliveryOptionType" minOccurs="0"/> + <xs:element name="StatusDetail" type="ns:SpecialInstructionStatusDetail" minOccurs="0"> + <xs:annotation> + <xs:documentation>Specifies the status and status update time of the track special instructions.</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="OriginalEstimatedDeliveryTimestamp" type="xs:dateTime" minOccurs="0"> + <xs:annotation> + <xs:documentation>Specifies the estimated delivery time that was originally estimated when the shipment was shipped.</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="OriginalRequestTime" type="xs:dateTime" minOccurs="0"> + <xs:annotation> + <xs:documentation>Specifies the time the customer requested a change to the shipment.</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="RequestedAppointmentTime" type="ns:AppointmentDetail" minOccurs="0"> + <xs:annotation> + <xs:documentation>The requested appointment time for delivery.</xs:documentation> + </xs:annotation> + </xs:element> + </xs:sequence> + </xs:complexType> <xs:complexType name="TrackSplitShipmentPart"> <xs:annotation> <xs:documentation>Used when a cargo shipment is split across vehicles. This is used to give the status of each part of the shipment.</xs:documentation> @@ -1320,6 +2080,26 @@ </xs:element> </xs:sequence> </xs:complexType> + <xs:complexType name="TrackStatusAncillaryDetail"> + <xs:sequence> + <xs:element name="Reason" type="xs:string" minOccurs="0"/> + <xs:element name="ReasonDescription" type="xs:string" minOccurs="0"/> + <xs:element name="Action" type="xs:string" minOccurs="0"/> + <xs:element name="ActionDescription" type="xs:string" minOccurs="0"/> + </xs:sequence> + </xs:complexType> + <xs:complexType name="TrackStatusDetail"> + <xs:annotation> + <xs:documentation>Specifies the details about the status of the track information for the shipments being tracked.</xs:documentation> + </xs:annotation> + <xs:sequence> + <xs:element name="CreationTime" type="xs:dateTime" minOccurs="0"/> + <xs:element name="Code" type="xs:string" minOccurs="0"/> + <xs:element name="Description" type="xs:string" minOccurs="0"/> + <xs:element name="Location" type="ns:Address" minOccurs="0"/> + <xs:element name="AncillaryDetails" type="ns:TrackStatusAncillaryDetail" minOccurs="0" maxOccurs="unbounded"/> + </xs:sequence> + </xs:complexType> <xs:complexType name="TransactionDetail"> <xs:annotation> <xs:documentation>Descriptive data that governs data payload language/translations. The TransactionDetail from the request is echoed back to the caller in the corresponding reply.</xs:documentation> @@ -1368,6 +2148,11 @@ <xs:documentation>Used in authentication of the sender's identity.</xs:documentation> </xs:annotation> <xs:sequence> + <xs:element name="ParentCredential" type="ns:WebAuthenticationCredential" minOccurs="0"> + <xs:annotation> + <xs:documentation>This was renamed from cspCredential.</xs:documentation> + </xs:annotation> + </xs:element> <xs:element name="UserCredential" type="ns:WebAuthenticationCredential" minOccurs="1"> <xs:annotation> <xs:documentation>Credential used to authenticate a specific software application. This value is provided by FedEx after registration.</xs:documentation> @@ -1402,7 +2187,7 @@ <xs:documentation>Identifies a system or sub-system which performs an operation.</xs:documentation> </xs:annotation> </xs:element> - <xs:element name="Major" type="xs:int" fixed="5" minOccurs="1"> + <xs:element name="Major" type="xs:int" fixed="10" minOccurs="1"> <xs:annotation> <xs:documentation>Identifies the service business level.</xs:documentation> </xs:annotation> @@ -1421,6 +2206,9 @@ </xs:complexType> </xs:schema> </types> + <message name="SendNotificationsReply"> + <part name="SendNotificationsReply" element="ns:SendNotificationsReply"/> + </message> <message name="SignatureProofOfDeliveryFaxReply"> <part name="SignatureProofOfDeliveryFaxReply" element="ns:SignatureProofOfDeliveryFaxReply"/> </message> @@ -1433,11 +2221,8 @@ <message name="SignatureProofOfDeliveryLetterRequest"> <part name="SignatureProofOfDeliveryLetterRequest" element="ns:SignatureProofOfDeliveryLetterRequest"/> </message> - <message name="TrackNotificationRequest"> - <part name="TrackNotificationRequest" element="ns:TrackNotificationRequest"/> - </message> - <message name="TrackNotificationReply"> - <part name="TrackNotificationReply" element="ns:TrackNotificationReply"/> + <message name="SendNotificationsRequest"> + <part name="SendNotificationsRequest" element="ns:SendNotificationsRequest"/> </message> <message name="TrackReply"> <part name="TrackReply" element="ns:TrackReply"/> @@ -1446,10 +2231,6 @@ <part name="SignatureProofOfDeliveryLetterReply" element="ns:SignatureProofOfDeliveryLetterReply"/> </message> <portType name="TrackPortType"> - <operation name="getTrackNotification" parameterOrder="TrackNotificationRequest"> - <input message="ns:TrackNotificationRequest"/> - <output message="ns:TrackNotificationReply"/> - </operation> <operation name="retrieveSignatureProofOfDeliveryLetter" parameterOrder="SignatureProofOfDeliveryLetterRequest"> <input message="ns:SignatureProofOfDeliveryLetterRequest"/> <output message="ns:SignatureProofOfDeliveryLetterReply"/> @@ -1462,11 +2243,15 @@ <input message="ns:SignatureProofOfDeliveryFaxRequest"/> <output message="ns:SignatureProofOfDeliveryFaxReply"/> </operation> + <operation name="sendNotifications" parameterOrder="SendNotificationsRequest"> + <input message="ns:SendNotificationsRequest"/> + <output message="ns:SendNotificationsReply"/> + </operation> </portType> <binding name="TrackServiceSoapBinding" type="ns:TrackPortType"> <s1:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> - <operation name="getTrackNotification"> - <s1:operation soapAction="getTrackNotification" style="document"/> + <operation name="retrieveSignatureProofOfDeliveryLetter"> + <s1:operation soapAction="http://fedex.com/ws/track/v10/retrieveSignatureProofOfDeliveryLetter" style="document"/> <input> <s1:body use="literal"/> </input> @@ -1474,8 +2259,8 @@ <s1:body use="literal"/> </output> </operation> - <operation name="retrieveSignatureProofOfDeliveryLetter"> - <s1:operation soapAction="retrieveSignatureProofOfDeliveryLetter" style="document"/> + <operation name="track"> + <s1:operation soapAction="http://fedex.com/ws/track/v10/track" style="document"/> <input> <s1:body use="literal"/> </input> @@ -1483,8 +2268,8 @@ <s1:body use="literal"/> </output> </operation> - <operation name="track"> - <s1:operation soapAction="track" style="document"/> + <operation name="sendSignatureProofOfDeliveryFax"> + <s1:operation soapAction="http://fedex.com/ws/track/v10/sendSignatureProofOfDeliveryFax" style="document"/> <input> <s1:body use="literal"/> </input> @@ -1492,8 +2277,8 @@ <s1:body use="literal"/> </output> </operation> - <operation name="sendSignatureProofOfDeliveryFax"> - <s1:operation soapAction="sendSignatureProofOfDeliveryFax" style="document"/> + <operation name="sendNotifications"> + <s1:operation soapAction="http://fedex.com/ws/track/v10/sendNotifications" style="document"/> <input> <s1:body use="literal"/> </input> @@ -1504,7 +2289,7 @@ </binding> <service name="TrackService"> <port name="TrackServicePort" binding="ns:TrackServiceSoapBinding"> - <s1:address location=""/> + <s1:address location="https://wsbeta.fedex.com:443/web-services/track"/> </port> </service> -</definitions> +</definitions> \ No newline at end of file diff --git a/app/code/Magento/Payment/Model/Method/Adapter.php b/app/code/Magento/Payment/Model/Method/Adapter.php index 1d693e11fe51f5311ede057ffcdb7b7fd73a2338..07a4dcdef5f3c0e228b59de729139fc4ee781961 100644 --- a/app/code/Magento/Payment/Model/Method/Adapter.php +++ b/app/code/Magento/Payment/Model/Method/Adapter.php @@ -268,14 +268,17 @@ class Adapter implements MethodInterface $checkResult = new DataObject(); $checkResult->setData('is_available', true); try { - $validator = $this->getValidatorPool()->get('availability'); - $result = $validator->validate( - [ - 'payment' => $this->paymentDataObjectFactory->create($this->getInfoInstance()) - ] - ); - - $checkResult->setData('is_available', $result->isValid()); + $infoInstance = $this->getInfoInstance(); + if ($infoInstance !== null) { + $validator = $this->getValidatorPool()->get('availability'); + $result = $validator->validate( + [ + 'payment' => $this->paymentDataObjectFactory->create($infoInstance) + ] + ); + + $checkResult->setData('is_available', $result->isValid()); + } } catch (\Exception $e) { // pass } diff --git a/app/code/Magento/Payment/Test/Unit/Model/Method/AdapterTest.php b/app/code/Magento/Payment/Test/Unit/Model/Method/AdapterTest.php index b5229b57875f0ea6c14d907d4c5e232c81670661..d8fefb7345e0f075a7858b8d109dd86a0556eb01 100644 --- a/app/code/Magento/Payment/Test/Unit/Model/Method/AdapterTest.php +++ b/app/code/Magento/Payment/Test/Unit/Model/Method/AdapterTest.php @@ -13,9 +13,12 @@ use Magento\Payment\Gateway\Config\ValueHandlerInterface; use Magento\Payment\Gateway\Config\ValueHandlerPoolInterface; use Magento\Payment\Gateway\Data\PaymentDataObjectFactory; use Magento\Payment\Gateway\Data\PaymentDataObjectInterface; +use Magento\Payment\Gateway\Validator\ResultInterface; +use Magento\Payment\Gateway\Validator\ValidatorInterface; use Magento\Payment\Gateway\Validator\ValidatorPoolInterface; use Magento\Payment\Model\InfoInterface; use Magento\Payment\Model\Method\Adapter; +use PHPUnit_Framework_MockObject_MockObject as MockObject; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -23,27 +26,27 @@ use Magento\Payment\Model\Method\Adapter; class AdapterTest extends \PHPUnit_Framework_TestCase { /** - * @var \PHPUnit_Framework_MockObject_MockObject | ManagerInterface + * @var MockObject|ManagerInterface */ private $eventManager; /** - * @var \PHPUnit_Framework_MockObject_MockObject | ValueHandlerPoolInterface + * @var MockObject|ValueHandlerPoolInterface */ private $valueHandlerPool; /** - * @var \PHPUnit_Framework_MockObject_MockObject | ValidatorPoolInterface + * @var MockObject|ValidatorPoolInterface */ private $validatorPool; /** - * @var \PHPUnit_Framework_MockObject_MockObject | CommandPoolInterface + * @var MockObject|CommandPoolInterface */ private $commandPool; /** - * @var \PHPUnit_Framework_MockObject_MockObject | PaymentDataObjectFactory + * @var MockObject|PaymentDataObjectFactory */ private $paymentDataObjectFactory; @@ -69,21 +72,11 @@ class AdapterTest extends \PHPUnit_Framework_TestCase protected function setUp() { - $this->eventManager = $this->getMock( - \Magento\Framework\Event\ManagerInterface::class - ); - $this->valueHandlerPool = $this->getMock( - \Magento\Payment\Gateway\Config\ValueHandlerPoolInterface::class - ); - $this->validatorPool = $this->getMock( - \Magento\Payment\Gateway\Validator\ValidatorPoolInterface::class - ); - $this->commandPool = $this->getMock( - \Magento\Payment\Gateway\Command\CommandPoolInterface::class - ); - $this->paymentDataObjectFactory = $this->getMockBuilder( - \Magento\Payment\Gateway\Data\PaymentDataObjectFactory::class - ) + $this->eventManager = $this->getMock(ManagerInterface::class); + $this->valueHandlerPool = $this->getMock(ValueHandlerPoolInterface::class); + $this->validatorPool = $this->getMock(ValidatorPoolInterface::class); + $this->commandPool = $this->getMock(CommandPoolInterface::class); + $this->paymentDataObjectFactory = $this->getMockBuilder(PaymentDataObjectFactory::class) ->disableOriginalConstructor() ->getMock(); @@ -103,11 +96,12 @@ class AdapterTest extends \PHPUnit_Framework_TestCase ); } + /** + * @covers \Magento\Payment\Model\Method\Adapter::isAvailable + */ public function testIsAvailableNotActive() { - $activeValueHandler = $this->getMock( - \Magento\Payment\Gateway\Config\ValueHandlerInterface::class - ); + $activeValueHandler = $this->getMock(ValueHandlerInterface::class); $this->valueHandlerPool->expects(static::once()) ->method('get') @@ -124,17 +118,16 @@ class AdapterTest extends \PHPUnit_Framework_TestCase static::assertFalse($this->adapter->isAvailable(null)); } + /** + * @covers \Magento\Payment\Model\Method\Adapter::isAvailable + */ public function testIsAvailableEmptyQuote() { - $activeValueHandler = $this->getMock( - \Magento\Payment\Gateway\Config\ValueHandlerInterface::class - ); - $availabilityValidator = $this->getMock( - \Magento\Payment\Gateway\Validator\ValidatorInterface::class - ); - $paymentDO = $this->getMock(\Magento\Payment\Gateway\Data\PaymentDataObjectInterface::class); - $validationResult = $this->getMock(\Magento\Payment\Gateway\Validator\ResultInterface::class); - $paymentInfo = $this->getMock(\Magento\Payment\Model\InfoInterface::class); + $activeValueHandler = $this->getMock(ValueHandlerInterface::class); + $availabilityValidator = $this->getMock(ValidatorInterface::class); + $paymentDO = $this->getMock(PaymentDataObjectInterface::class); + $validationResult = $this->getMock(ResultInterface::class); + $paymentInfo = $this->getMock(InfoInterface::class); $this->valueHandlerPool->expects(static::once()) ->method('get') @@ -167,24 +160,49 @@ class AdapterTest extends \PHPUnit_Framework_TestCase static::assertTrue($this->adapter->isAvailable(null)); } + /** + * @covers \Magento\Payment\Model\Method\Adapter::isAvailable + */ + public function testIsAvailableWithEmptyInfoInstance() + { + $activeValueHandler = $this->getMock(ValueHandlerInterface::class); + $this->valueHandlerPool->expects(static::once()) + ->method('get') + ->with('active') + ->willReturn($activeValueHandler); + $activeValueHandler->expects(static::once()) + ->method('handle') + ->with(['field' => 'active']) + ->willReturn(true); + + $this->validatorPool->expects(static::never()) + ->method('get') + ->with('availability'); + + $this->eventManager->expects(static::once()) + ->method('dispatch'); + + static::assertTrue($this->adapter->isAvailable(null)); + } + public function testExecuteCommandWithCommandExecutor() { - /** @var ManagerInterface|\PHPUnit_Framework_MockObject_MockObject $eventManager */ + /** @var ManagerInterface|MockObject $eventManager */ $eventManager = $this->getMock( ManagerInterface::class ); - /** @var ValueHandlerPoolInterface|\PHPUnit_Framework_MockObject_MockObject $valueHandlerPool */ + /** @var ValueHandlerPoolInterface|MockObject $valueHandlerPool */ $valueHandlerPool = $this->getMock( ValueHandlerPoolInterface::class ); - /** @var CommandManagerInterface|\PHPUnit_Framework_MockObject_MockObject $commandManager */ + /** @var CommandManagerInterface|MockObject $commandManager */ $commandManager = $this->getMock( CommandManagerInterface::class ); - /** @var PaymentDataObjectFactory|\PHPUnit_Framework_MockObject_MockObject $paymentDataObjectFactory */ + /** @var PaymentDataObjectFactory|MockObject $paymentDataObjectFactory */ $paymentDataObjectFactory = $this->getMockBuilder( PaymentDataObjectFactory::class ) @@ -232,25 +250,17 @@ class AdapterTest extends \PHPUnit_Framework_TestCase public function testExecuteCommandWithCommandPool() { - /** @var ManagerInterface|\PHPUnit_Framework_MockObject_MockObject $eventManager */ - $eventManager = $this->getMock( - ManagerInterface::class - ); + /** @var ManagerInterface|MockObject $eventManager */ + $eventManager = $this->getMock(ManagerInterface::class); - /** @var ValueHandlerPoolInterface|\PHPUnit_Framework_MockObject_MockObject $valueHandlerPool */ - $valueHandlerPool = $this->getMock( - ValueHandlerPoolInterface::class - ); + /** @var ValueHandlerPoolInterface|MockObject $valueHandlerPool */ + $valueHandlerPool = $this->getMock(ValueHandlerPoolInterface::class); - /** @var CommandPoolInterface|\PHPUnit_Framework_MockObject_MockObject $commandPool */ - $commandPool = $this->getMock( - CommandPoolInterface::class - ); + /** @var CommandPoolInterface|MockObject $commandPool */ + $commandPool = $this->getMock(CommandPoolInterface::class); - /** @var PaymentDataObjectFactory|\PHPUnit_Framework_MockObject_MockObject $paymentDataObjectFactory */ - $paymentDataObjectFactory = $this->getMockBuilder( - PaymentDataObjectFactory::class - ) + /** @var PaymentDataObjectFactory|MockObject $paymentDataObjectFactory */ + $paymentDataObjectFactory = $this->getMockBuilder(PaymentDataObjectFactory::class) ->disableOriginalConstructor() ->getMock(); diff --git a/app/code/Magento/Paypal/Block/Express/InContext/Minicart/Button.php b/app/code/Magento/Paypal/Block/Express/InContext/Minicart/Button.php index 56e32da15c908ae4785b489a5112a13edb151af5..6785b95dadeea08b22556252a1a4e33a44f95956 100644 --- a/app/code/Magento/Paypal/Block/Express/InContext/Minicart/Button.php +++ b/app/code/Magento/Paypal/Block/Express/InContext/Minicart/Button.php @@ -54,7 +54,6 @@ class Button extends Template implements ShortcutInterface private $session; /** - * Constructor * @param Context $context * @param ResolverInterface $localeResolver * @param ConfigFactory $configFactory @@ -80,6 +79,8 @@ class Button extends Template implements ShortcutInterface } /** + * Check `in_context` config value + * * @return bool */ private function isInContext() @@ -88,13 +89,27 @@ class Button extends Template implements ShortcutInterface } /** + * Check `visible_on_cart` config value + * + * @return bool + */ + private function isVisibleOnCart() + { + return (bool)(int) $this->config->getValue('visible_on_cart'); + } + + /** + * Check is Paypal In-Context Express Checkout button + * should render in cart/mini-cart + * * @return bool */ protected function shouldRender() { return $this->payment->isAvailable($this->session->getQuote()) && $this->isMiniCart - && $this->isInContext(); + && $this->isInContext() + && $this->isVisibleOnCart(); } /** diff --git a/app/code/Magento/Shipping/Model/Carrier/AbstractCarrierOnline.php b/app/code/Magento/Shipping/Model/Carrier/AbstractCarrierOnline.php index af310da3064f892596cbe695eef6edc94a17e13b..296a3302de786f1c4e7c7c5d8def46e4fd0cf2f3 100644 --- a/app/code/Magento/Shipping/Model/Carrier/AbstractCarrierOnline.php +++ b/app/code/Magento/Shipping/Model/Carrier/AbstractCarrierOnline.php @@ -596,11 +596,12 @@ abstract class AbstractCarrierOnline extends AbstractCarrier * Check whether girth is allowed for the carrier * * @param null|string $countyDest + * @param null|string $carrierMethodCode * @return bool * @SuppressWarnings(PHPMD.UnusedFormalParameter) * @api */ - public function isGirthAllowed($countyDest = null) + public function isGirthAllowed($countyDest = null, $carrierMethodCode = null) { return false; } diff --git a/app/code/Magento/Shipping/view/frontend/templates/tracking/details.phtml b/app/code/Magento/Shipping/view/frontend/templates/tracking/details.phtml new file mode 100644 index 0000000000000000000000000000000000000000..d655d96e1dd365be8f5c19960876f00413b6ab7a --- /dev/null +++ b/app/code/Magento/Shipping/view/frontend/templates/tracking/details.phtml @@ -0,0 +1,95 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +// @codingStandardsIgnoreFile + +/** @var $block \Magento\Framework\View\Element\Template */ + +$track = $block->getData('track'); +$email = $block->getData('storeSupportEmail'); +$fields = [ + 'Status' => 'getStatus', + 'Signed by' => 'getSignedby', + 'Delivered to' => 'getDeliveryLocation', + 'Shipped or billed on' => 'getShippedDate', + 'Service Type' => 'getService', + 'Weight' => 'getWeight', +]; +?> +<table class="data table order tracking" id="tracking-table-popup-<?php /* @noEscape */ echo $track->getTracking(); ?>"> + <caption class="table-caption"><?php echo $block->escapeHtml(__('Order tracking')); ?></caption> + <tbody> + <?php if (is_object($track)): ?> + <tr> + <th class="col label" scope="row"><?php echo $block->escapeHtml(__('Tracking Number:')); ?></th> + <td class="col value"><?php echo $block->escapeHtml($track->getTracking()); ?></td> + </tr> + <?php if ($track->getCarrierTitle()): ?> + <tr> + <th class="col label" scope="row"><?php echo $block->escapeHtml(__('Carrier:')); ?></th> + <td class="col value"><?php echo $block->escapeHtml($track->getCarrierTitle()); ?></td> + </tr> + <?php endif; ?> + <?php if ($track->getErrorMessage()): ?> + <tr> + <th class="col label" scope="row"><?php echo $block->escapeHtml(__('Error:')); ?></th> + <td class="col error"> + <?php echo $block->escapeHtml(__('Tracking information is currently not available. Please ')); ?> + <?php if ($block->getContactUsEnabled()) : ?> + <a href="<?php echo $block->escapeUrl($block->getContactUs()); ?>" target="_blank" + title="<?php echo $block->escapeHtml(__('contact us')); ?>"> + <?php echo $block->escapeHtml(__('contact us')); ?> + </a> + <?php echo $block->escapeHtml(__(' for more information or ')); ?> + <?php endif; ?> + <?php echo $block->escapeHtml(__('email us at ')); ?> + <a href="mailto:<?php /* @noEscape */ echo $email; ?>"><?php /* @noEscape */ echo $email; ?></a> + </td> + </tr> + <?php elseif ($track->getTrackSummary()): ?> + <tr> + <th class="col label" scope="row"><?php echo $block->escapeHtml(__('Info:')); ?></th> + <td class="col value"><?php echo $block->escapeHtml($track->getTrackSummary()); ?></td> + </tr> + <?php elseif ($track->getUrl()): ?> + <tr> + <th class="col label" scope="row"><?php echo $block->escapeHtml(__('Track:')); ?></th> + <td class="col value"> + <a href="<?php echo $block->escapeUrl($track->getUrl()); ?>" target="_blank"> + <?php echo $block->escapeUrl($track->getUrl()); ?> + </a> + </td> + </tr> + <?php else: ?> + <?php foreach ($fields as $title => $property): ?> + <?php if (!empty($track->$property())): ?> + <tr> + <th class="col label" scope="row"><?php /* @noEscape */ echo $block->escapeHtml(__($title . ':')); ?></th> + <td class="col value"><?php echo $block->escapeHtml($track->$property()); ?></td> + </tr> + <?php endif;?> + <?php endforeach; ?> + + <?php if ($track->getDeliverydate()): ?> + <tr> + <th class="col label" scope="row"><?php echo $block->escapeHtml(__('Delivered on:')); ?></th> + <td class="col value"> + <?php /* @noEscape */ echo $block->formatDeliveryDateTime($track->getDeliverydate(), $track->getDeliverytime()); ?> + </td> + </tr> + <?php endif; ?> + <?php endif; ?> + <?php elseif (isset($track['title']) && isset($track['number']) && $track['number']): ?> + <?php /* if the tracking is custom value */ ?> + <tr> + <th class="col label" scope="row"> + <?php echo($track['title'] ? $block->escapeHtml($track['title']) : $block->escapeHtml(__('N/A'))); ?>: + </th> + <td class="col value"><?php echo(isset($track['number']) ? $block->escapeHtml($track['number']) : ''); ?></td> + </tr> + <?php endif; ?> + </tbody> +</table> diff --git a/app/code/Magento/Shipping/view/frontend/templates/tracking/popup.phtml b/app/code/Magento/Shipping/view/frontend/templates/tracking/popup.phtml index e9bb00df8b852f05ba991bb534692a2c6cd39968..412cb4b411a98b241995c5b9ef736d33e36c2fbc 100644 --- a/app/code/Magento/Shipping/view/frontend/templates/tracking/popup.phtml +++ b/app/code/Magento/Shipping/view/frontend/templates/tracking/popup.phtml @@ -4,156 +4,60 @@ * See COPYING.txt for license details. */ +use Magento\Framework\View\Element\Template; + // @codingStandardsIgnoreFile +/** @var $block \Magento\Shipping\Block\Tracking\Popup */ + +$results = $block->getTrackingInfo(); ?> -<?php /** @var $block \Magento\Shipping\Block\Tracking\Popup */ ?> -<?php $_results = $block->getTrackingInfo(); ?> <div class="page tracking"> - <?php if (sizeof($_results)>0): ?> - <?php foreach ($_results as $shipid => $_result): ?> - <?php if ($shipid): ?> - <div class="order subtitle caption"><?php /* @escapeNotVerified */ echo __('Shipment #') . $shipid; ?></div> - <?php endif; ?> - <?php if (sizeof($_result)>0): ?> - <?php $rowCount = sizeof($_result); $counter = 1; ?> - <?php $_id = 0; foreach ($_result as $track): ?> - <div class="table-wrapper"> - <table class="data table order tracking" id="tracking-table-popup-<?php /* @escapeNotVerified */ echo $_id ?>"> - <caption class="table-caption"><?php /* @escapeNotVerified */ echo __('Order tracking'); ?></caption> - <tbody> - <?php if (is_object($track)): ?> - <tr> - <th class="col label" scope="row"><?php /* @escapeNotVerified */ echo __('Tracking Number:'); ?></th> - <td class="col value"><?php echo $block->escapeHtml($track->getTracking()); ?></td> - </tr> - <?php if ($track->getCarrierTitle()): ?> - <tr> - <th class="col label" scope="row"><?php /* @escapeNotVerified */ echo __('Carrier:'); ?></th> - <td class="col value"><?php echo $block->escapeHtml($track->getCarrierTitle()); ?></td> - </tr> - <?php endif; ?> - <?php if ($track->getErrorMessage()): ?> - <tr> - <th class="col label" scope="row"><?php /* @escapeNotVerified */ echo __('Error:'); ?></th> - <td class="col error"><?php /* @escapeNotVerified */ echo __('Tracking information is currently not available. Please '); if ($block->getContactUsEnabled()) : ?><a href="<?php /* @escapeNotVerified */ echo $block->getContactUs() ?>" title="<?php /* @escapeNotVerified */ echo __('contact us') ?>" onclick="this.target='_blank'"><?php /* @escapeNotVerified */ echo __('contact us') ?></a><?php /* @escapeNotVerified */ echo __(' for more information or '); endif; /* @escapeNotVerified */ echo __('email us at '); ?><a href="mailto:<?php /* @escapeNotVerified */ echo $block->getStoreSupportEmail() ?>"><?php /* @escapeNotVerified */ echo $block->getStoreSupportEmail() ?></a></td> - </tr> - <?php elseif ($track->getTrackSummary()): ?> - <tr> - <th class="col label" scope="row"><?php /* @escapeNotVerified */ echo __('Info:'); ?></th> - <td class="col value"><?php /* @escapeNotVerified */ echo $track->getTrackSummary(); ?></td> - </tr> - <?php elseif ($track->getUrl()): ?> - <tr> - <th class="col label" scope="row"><?php /* @escapeNotVerified */ echo __('Track:'); ?></th> - <td class="col value"><a href="<?php echo $block->escapeHtml($track->getUrl()); ?>" onclick="this.target='_blank'"><?php echo $block->escapeHtml($track->getUrl()); ?></a></td> - </tr> - <?php else: ?> - <?php if ($track->getStatus()): ?> - <tr> - <th class="col label" scope="row"><?php /* @escapeNotVerified */ echo __('Status:'); ?></th> - <td class="col value"><?php /* @escapeNotVerified */ echo $track->getStatus(); ?></td> - </tr> - <?php endif; ?> - - <?php if ($track->getDeliverydate()): ?> - <tr> - <th class="col label" scope="row"><?php /* @escapeNotVerified */ echo __('Delivered on:'); ?></th> - <td class="col value"><?php /* @escapeNotVerified */ echo $block->formatDeliveryDateTime($track->getDeliverydate(), $track->getDeliverytime()); ?></td> - </tr> - <?php endif; ?> - - <?php if ($track->getSignedby()): ?> - <tr> - <th class="col label" scope="row"><?php /* @escapeNotVerified */ echo __('Signed by:'); ?></th> - <td class="col value"><?php /* @escapeNotVerified */ echo $track->getSignedby(); ?></td> - </tr> - <?php endif; ?> - - <?php if ($track->getDeliveryLocation()): ?> - <tr> - <th class="col label" scope="row"><?php /* @escapeNotVerified */ echo __('Delivered to:'); ?></th> - <td class="col value"><?php /* @escapeNotVerified */ echo $track->getDeliveryLocation(); ?></td> - </tr> - <?php endif; ?> - - <?php if ($track->getShippedDate()): ?> - <tr> - <th class="col label" scope="row"><?php /* @escapeNotVerified */ echo __('Shipped or billed on:'); ?></th> - <td class="col value"><?php /* @escapeNotVerified */ echo $track->getShippedDate(); ?></td> - </tr> - <?php endif; ?> - - <?php if ($track->getService()): ?> - <tr> - <th class="col label" scope="row"><?php /* @escapeNotVerified */ echo __('Service Type:'); ?></th> - <td class="col value"><?php /* @escapeNotVerified */ echo $track->getService(); ?></td> - </tr> - <?php endif; ?> - - <?php if ($track->getWeight()): ?> - <tr> - <th class="col label" scope="row"><?php /* @escapeNotVerified */ echo __('Weight:'); ?></th> - <td class="col value"><?php /* @escapeNotVerified */ echo $track->getWeight(); ?></td> - </tr> - <?php endif; ?> - <?php endif; ?> - <?php elseif (isset($track['title']) && isset($track['number']) && $track['number']): ?> - <?php /* if the tracking is custom value */ ?> - <tr> - <th class="col label" scope="row"><?php echo($track['title'] ? $block->escapeHtml($track['title']) : __('N/A')); ?>:</th> - <td class="col value"><?php echo(isset($track['number']) ? $block->escapeHtml($track['number']) : ''); ?></td> - </tr> - <?php endif; ?> - </tbody> - </table> - </div> - <?php if (is_object($track) && sizeof($track->getProgressdetail())>0): ?> + <?php if (!empty($results)): ?> + <?php foreach ($results as $shipId => $result): ?> + <?php if ($shipId): ?> + <div class="order subtitle caption"><?php /* @noEscape */ echo $block->escapeHtml(__('Shipment #')) . $shipId; ?></div> + <?php endif; ?> + <?php if (!empty($result)): ?> + <?php foreach ($result as $counter => $track): ?> <div class="table-wrapper"> - <table class="data table order tracking" id="track-history-table-<?php /* @escapeNotVerified */ echo $track->getTracking(); ?>"> - <caption class="table-caption"><?php /* @escapeNotVerified */ echo __('Track history'); ?></caption> - <thead> - <tr> - <th class="col location" scope="col"><?php /* @escapeNotVerified */ echo __('Location') ?></th> - <th class="col date" scope="col"><?php /* @escapeNotVerified */ echo __('Date') ?></th> - <th class="col time" scope="col"><?php /* @escapeNotVerified */ echo __('Local Time') ?></th> - <th class="col description" scope="col"><?php /* @escapeNotVerified */ echo __('Description') ?></th> - </tr> - </thead> - <tbody> - <?php foreach ($track->getProgressdetail() as $_detail): ?> - <?php $_detailDate = (isset($_detail['deliverydate']) ? $block->formatDeliveryDate($_detail['deliverydate']) : '') ?> - <?php $_detailTime = (isset($_detail['deliverytime']) ? $block->formatDeliveryTime($_detail['deliverytime'], $_detail['deliverydate']) : '') ?> - <tr> - <td data-th="<?php echo $block->escapeHtml(__('Location')) ?>" class="col location"><?php echo(isset($_detail['deliverylocation']) ? $_detail['deliverylocation'] : ''); ?></td> - <td data-th="<?php echo $block->escapeHtml(__('Date')) ?>" class="col date"><?php /* @escapeNotVerified */ echo $_detailDate ?></td> - <td data-th="<?php echo $block->escapeHtml(__('Local Time')) ?>" class="col time"><?php /* @escapeNotVerified */ echo $_detailTime ?></td> - <td data-th="<?php echo $block->escapeHtml(__('Description')) ?>" class="col description"><?php echo(isset($_detail['activity']) ? $_detail['activity'] : '') ?></td> - </tr> - <?php endforeach; ?> - </tbody> - </table> + <?php + $block->addChild('shipping.tracking.details.' . $counter, Template::class, [ + 'track' => $track, + 'template' => 'Magento_Shipping::tracking/details.phtml', + 'storeSupportEmail' => $block->getStoreSupportEmail() + ] + ); + ?> + <?php /* @noEscape */ echo $block->getChildHtml('shipping.tracking.details.' . $counter); ?> </div> - <?php endif; ?> - <?php if ($counter != $rowCount): ?> - <?php endif; ?> - <?php $counter++; ?> - <?php /* end for each tracking information */ ?> - <?php endforeach; ?> - <?php else: ?> - <div class="message info empty"><div><?php /* @escapeNotVerified */ echo __('There is no tracking available for this shipment.'); ?></div></div> - <?php endif; ?> - - <?php endforeach; ?> + <?php if (!empty($track->getProgressdetail())): ?> + <?php + $block->addChild('shipping.tracking.progress.'. $counter, Template::class, [ + 'track' => $track, + 'template' => 'Magento_Shipping::tracking/progress.phtml' + ]); + ?> + <?php /* @noEscape */echo $block->getChildHtml('shipping.tracking.progress.' . $counter); ?> + <?php endif; ?> + <?php endforeach; ?> + <?php else: ?> + <div class="message info empty"> + <div><?php echo $block->escapeHtml(__('There is no tracking available for this shipment.')); ?></div> + </div> + <?php endif; ?> + <?php endforeach; ?> <?php else: ?> - <div class="message info empty"><div><?php /* @escapeNotVerified */ echo __('There is no tracking available.'); ?></div></div> + <div class="message info empty"> + <div><?php echo $block->escapeHtml(__('There is no tracking available.')); ?></div> + </div> <?php endif; ?> <div class="actions"> <button type="button" - title="<?php /* @escapeNotVerified */ echo __('Close Window') ?>" + title="<?php echo $block->escapeHtml(__('Close Window')); ?>" class="action close" onclick="window.close(); window.opener.focus();"> - <span><?php /* @escapeNotVerified */ echo __('Close Window') ?></span> + <span><?php echo $block->escapeHtml(__('Close Window')); ?></span> </button> </div> </div> diff --git a/app/code/Magento/Shipping/view/frontend/templates/tracking/progress.phtml b/app/code/Magento/Shipping/view/frontend/templates/tracking/progress.phtml new file mode 100644 index 0000000000000000000000000000000000000000..d5ce13a277f8b07606e8d27b643e6f5dca6508ed --- /dev/null +++ b/app/code/Magento/Shipping/view/frontend/templates/tracking/progress.phtml @@ -0,0 +1,43 @@ +<?php +/** +* Copyright © 2016 Magento. All rights reserved. +* See COPYING.txt for license details. +*/ + +// @codingStandardsIgnoreFile + +/** @var $block \Magento\Framework\View\Element\Template */ +$track = $block->getData('track'); +?> +<div class="table-wrapper"> + <table class="data table order tracking" id="track-history-table-<?php /* @noEscape */ echo $track->getTracking(); ?>"> + <caption class="table-caption"><?php echo $block->escapeHtml(__('Track history')); ?></caption> + <thead> + <tr> + <th class="col location" scope="col"><?php echo $block->escapeHtml(__('Location')); ?></th> + <th class="col date" scope="col"><?php echo $block->escapeHtml(__('Date')); ?></th> + <th class="col time" scope="col"><?php echo $block->escapeHtml(__('Local Time')); ?></th> + <th class="col description" scope="col"><?php echo $block->escapeHtml(__('Description')); ?></th> + </tr> + </thead> + <tbody> + <?php foreach ($track->getProgressdetail() as $detail): ?> + <?php $detailDate = (!empty($detail['deliverydate']) ? $block->formatDeliveryDate($detail['deliverydate']) : ''); ?> + <?php $detailTime = (!empty($detail['deliverytime']) ? $block->formatDeliveryTime($detail['deliverytime'], $detail['deliverydate']) : ''); ?> + <tr> + <td data-th="<?php echo $block->escapeHtml(__('Location')); ?>" class="col location"> + <?php echo(!empty($detail['deliverylocation']) ? $block->escapeHtml($detail['deliverylocation']) : ''); ?> + </td> + <td data-th="<?php echo $block->escapeHtml(__('Date')); ?>" class="col date"> + <?php /* @noEscape */ echo $detailDate; ?> + </td> + <td data-th="<?php echo $block->escapeHtml(__('Local Time')); ?>" class="col time"> + <?php /* @noEscape */ echo $detailTime; ?></td> + <td data-th="<?php echo $block->escapeHtml(__('Description')); ?>" class="col description"> + <?php echo(!empty($detail['activity']) ? $block->escapeHtml($detail['activity']) : ''); ?> + </td> + </tr> + <?php endforeach; ?> + </tbody> + </table> +</div> \ No newline at end of file diff --git a/app/code/Magento/Swatches/view/adminhtml/ui_component/design_config_form.xml b/app/code/Magento/Swatches/view/adminhtml/ui_component/design_config_form.xml index 1b5ec69e5d5c246ee0acc735bce6990a07dbe1a8..0891fb351837697abcfe0f45f759d2006d35121e 100644 --- a/app/code/Magento/Swatches/view/adminhtml/ui_component/design_config_form.xml +++ b/app/code/Magento/Swatches/view/adminhtml/ui_component/design_config_form.xml @@ -48,12 +48,13 @@ <field name="watermark_swatch_image_size"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Catalog/component/image-size-field</item> <item name="label" xsi:type="string" translate="true">Image Size</item> <item name="dataType" xsi:type="string">text</item> <item name="formElement" xsi:type="string">input</item> <item name="dataScope" xsi:type="string">watermark_swatch_image_size</item> <item name="validation" xsi:type="array"> - <item name="validate-digits" xsi:type="boolean">true</item> + <item name="validate-image-size-range" xsi:type="boolean">true</item> </item> <item name="notice" xsi:type="string" translate="true">Example format: 200x300.</item> </item> diff --git a/app/code/Magento/Ups/Model/Carrier.php b/app/code/Magento/Ups/Model/Carrier.php index 17c313af9704fa28f82f08a4971aef503f5ba4c8..ec14e9db90ceccb4d9827d3b2fee921993afae9f 100644 --- a/app/code/Magento/Ups/Model/Carrier.php +++ b/app/code/Magento/Ups/Model/Carrier.php @@ -325,13 +325,13 @@ class Carrier extends AbstractCarrierOnline implements CarrierInterface $destCountry = self::GUAM_COUNTRY_ID; } - $rowRequest->setDestCountry($this->_countryFactory->create()->load($destCountry)->getData('iso2_code')); + $country = $this->_countryFactory->create()->load($destCountry); + $rowRequest->setDestCountry($country->getData('iso2_code') ?: $destCountry); $rowRequest->setDestRegionCode($request->getDestRegionCode()); if ($request->getDestPostcode()) { $rowRequest->setDestPostal($request->getDestPostcode()); - } else { } $weight = $this->getTotalNumOfBoxes($request->getPackageWeight()); diff --git a/app/code/Magento/Ups/Test/Unit/Model/CarrierTest.php b/app/code/Magento/Ups/Test/Unit/Model/CarrierTest.php index 8f42ea1c8040c3107611b18c725bcb4b08ec0969..ea46e534ae890d2f80bfb8a9120c03b43724aeec 100644 --- a/app/code/Magento/Ups/Test/Unit/Model/CarrierTest.php +++ b/app/code/Magento/Ups/Test/Unit/Model/CarrierTest.php @@ -7,6 +7,8 @@ namespace Magento\Ups\Test\Unit\Model; use Magento\Quote\Model\Quote\Address\RateRequest; use Magento\Ups\Model\Carrier; +use Magento\Directory\Model\Country; +use PHPUnit_Framework_MockObject_MockObject as MockObject; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -57,7 +59,7 @@ class CarrierTest extends \PHPUnit_Framework_TestCase protected $countryFactory; /** - * @var \Magento\Directory\Model\Country + * @var Country|MockObject */ protected $country; @@ -309,4 +311,47 @@ class CarrierTest extends \PHPUnit_Framework_TestCase ] ]; } + + /** + * @covers \Magento\Ups\Model\Carrier::setRequest + * @param string $countryCode + * @param string $foundCountryCode + * @dataProvider countryDataProvider + */ + public function testSetRequest($countryCode, $foundCountryCode) + { + /** @var RateRequest $request */ + $request = $this->helper->getObject(RateRequest::class); + $request->setData([ + 'orig_country' => 'USA', + 'orig_region_code' => 'CA', + 'orig_post_code' => 90230, + 'orig_city' => 'Culver City', + 'dest_country_id' => $countryCode, + ]); + + $this->country->expects(static::at(1)) + ->method('load') + ->with($countryCode) + ->willReturnSelf(); + + $this->country->expects(static::any()) + ->method('getData') + ->with('iso2_code') + ->willReturn($foundCountryCode); + + $this->model->setRequest($request); + } + + /** + * Get list of country variations + * @return array + */ + public function countryDataProvider() + { + return [ + ['countryCode' => 'PR', 'foundCountryCode' => null], + ['countryCode' => 'US', 'foundCountryCode' => 'US'], + ]; + } } diff --git a/app/code/Magento/Ups/etc/adminhtml/system.xml b/app/code/Magento/Ups/etc/adminhtml/system.xml index dd83ab7c4ed964ed0ec73c265fa95d61dcf64077..39bd613974d5ef80a28748929ffd4ff725bb253f 100644 --- a/app/code/Magento/Ups/etc/adminhtml/system.xml +++ b/app/code/Magento/Ups/etc/adminhtml/system.xml @@ -32,12 +32,15 @@ <source_model>Magento\Ups\Model\Config\Source\Container</source_model> </field> <field id="free_shipping_enable" translate="label" type="select" sortOrder="210" showInDefault="1" showInWebsite="1" showInStore="0"> - <label>Free Shipping Amount Threshold</label> + <label>Enable Free Shipping Threshold</label> <source_model>Magento\Config\Model\Config\Source\Enabledisable</source_model> </field> <field id="free_shipping_subtotal" translate="label" type="text" sortOrder="220" showInDefault="1" showInWebsite="1" showInStore="0"> <label>Free Shipping Amount Threshold</label> <validate>validate-number validate-zero-or-greater</validate> + <depends> + <field id="free_shipping_enable">1</field> + </depends> </field> <field id="dest_type" translate="label" type="select" sortOrder="60" showInDefault="1" showInWebsite="1" showInStore="0" canRestore="1"> <label>Destination Type</label> diff --git a/app/code/Magento/Usps/Block/Rma/Adminhtml/Rma/Edit/Tab/General/Shipping/Packaging/Plugin.php b/app/code/Magento/Usps/Block/Rma/Adminhtml/Rma/Edit/Tab/General/Shipping/Packaging/Plugin.php deleted file mode 100644 index b0a91da7a07bca6a1349661694edf9fb043cef98..0000000000000000000000000000000000000000 --- a/app/code/Magento/Usps/Block/Rma/Adminhtml/Rma/Edit/Tab/General/Shipping/Packaging/Plugin.php +++ /dev/null @@ -1,91 +0,0 @@ -<?php -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Usps\Block\Rma\Adminhtml\Rma\Edit\Tab\General\Shipping\Packaging; - -use Magento\Framework\App\RequestInterface; -use Magento\Usps\Helper\Data as UspsHelper; -use Magento\Usps\Model\Carrier; - -/** - * Rma block plugin - */ -class Plugin -{ - /** - * Usps helper - * - * @var \Magento\Usps\Helper\Data - */ - protected $uspsHelper; - - /** - * Request - * - * @var \Magento\Framework\App\RequestInterface - */ - protected $request; - - /** - * Construct - * - * @param \Magento\Usps\Helper\Data $uspsHelper - * @param \Magento\Framework\App\RequestInterface $request - */ - public function __construct(UspsHelper $uspsHelper, RequestInterface $request) - { - $this->uspsHelper = $uspsHelper; - $this->request = $request; - } - - /** - * Add rule to isGirthAllowed() method - * - * @param \Magento\Framework\DataObject $subject $subject - * @param bool $result - * @return bool - * @SuppressWarnings(PHPMD.UnusedFormalParameter) - */ - public function afterIsGirthAllowed(\Magento\Framework\DataObject $subject, $result) - { - return $result && $this->uspsHelper->displayGirthValue($this->request->getParam('method')); - } - - /** - * Add rule to isGirthAllowed() method - * - * @param \Magento\Framework\DataObject $subject - * @param \Closure $proceed - * @return array - * @SuppressWarnings(PHPMD.UnusedFormalParameter) - */ - public function aroundCheckSizeAndGirthParameter(\Magento\Framework\DataObject $subject, \Closure $proceed) - { - $carrier = $subject->getCarrier(); - $size = $subject->getSourceSizeModel(); - - $girthEnabled = false; - $sizeEnabled = false; - if ($carrier && isset($size[0]['value'])) { - if (in_array( - key($subject->getContainers()), - [Carrier::CONTAINER_NONRECTANGULAR, Carrier::CONTAINER_VARIABLE] - ) - ) { - $girthEnabled = true; - } - - if (in_array( - key($subject->getContainers()), - [Carrier::CONTAINER_NONRECTANGULAR, Carrier::CONTAINER_RECTANGULAR, Carrier::CONTAINER_VARIABLE] - ) - ) { - $sizeEnabled = true; - } - } - - return [$girthEnabled, $sizeEnabled]; - } -} diff --git a/app/code/Magento/Usps/Model/Carrier.php b/app/code/Magento/Usps/Model/Carrier.php index 3040d18ad8041d56ba66d231e55f9bb505702b88..d12341659cb6d8ad1fc4acabe0b8052e346ca102 100644 --- a/app/code/Magento/Usps/Model/Carrier.php +++ b/app/code/Magento/Usps/Model/Carrier.php @@ -8,11 +8,13 @@ namespace Magento\Usps\Model; +use Magento\Framework\App\ObjectManager; use Magento\Quote\Model\Quote\Address\RateRequest; use Magento\Shipping\Helper\Carrier as CarrierHelper; use Magento\Shipping\Model\Carrier\AbstractCarrierOnline; use Magento\Shipping\Model\Rate\Result; use Magento\Framework\Xml\Security; +use Magento\Usps\Helper\Data as DataHelper; /** * USPS shipping @@ -21,17 +23,19 @@ use Magento\Framework\Xml\Security; */ class Carrier extends AbstractCarrierOnline implements \Magento\Shipping\Model\Carrier\CarrierInterface { - /** - * USPS containers - */ + /** @deprecated */ const CONTAINER_VARIABLE = 'VARIABLE'; + /** @deprecated */ const CONTAINER_FLAT_RATE_BOX = 'FLAT RATE BOX'; + /** @deprecated */ const CONTAINER_FLAT_RATE_ENVELOPE = 'FLAT RATE ENVELOPE'; + /** @deprecated */ const CONTAINER_RECTANGULAR = 'RECTANGULAR'; + /** @deprecated */ const CONTAINER_NONRECTANGULAR = 'NONRECTANGULAR'; /** @@ -126,6 +130,11 @@ class Carrier extends AbstractCarrierOnline implements \Magento\Shipping\Model\C 'USERID' ]; + /** + * @var DataHelper + */ + private $dataHelper; + /** * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig * @param \Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory @@ -1980,11 +1989,13 @@ class Carrier extends AbstractCarrierOnline implements \Magento\Shipping\Model\C * Check whether girth is allowed for the USPS * * @param null|string $countyDest + * @param null|string $carrierMethodCode * @return bool */ - public function isGirthAllowed($countyDest = null) + public function isGirthAllowed($countyDest = null, $carrierMethodCode = null) { - return $this->_isUSCountry($countyDest) ? false : true; + return $this->_isUSCountry($countyDest) + && $this->getDataHelper()->displayGirthValue($carrierMethodCode) ? false : true; } /** @@ -2089,4 +2100,19 @@ class Carrier extends AbstractCarrierOnline implements \Magento\Shipping\Model\C return $data; } + + /** + * Gets Data helper object + * + * @return DataHelper + * @deprecated + */ + private function getDataHelper() + { + if (!$this->dataHelper) { + $this->dataHelper = ObjectManager::getInstance()->get(DataHelper::class); + } + + return $this->dataHelper; + } } diff --git a/app/code/Magento/Usps/Test/Unit/Model/CarrierTest.php b/app/code/Magento/Usps/Test/Unit/Model/CarrierTest.php index 1e2e9fd797b05281100488532f6f451d85cef43c..a79206553c5bc7fb66fa64b728593727422d2626 100644 --- a/app/code/Magento/Usps/Test/Unit/Model/CarrierTest.php +++ b/app/code/Magento/Usps/Test/Unit/Model/CarrierTest.php @@ -6,6 +6,7 @@ namespace Magento\Usps\Test\Unit\Model; use Magento\Quote\Model\Quote\Address\RateRequest; +use Magento\Usps\Helper\Data as DataHelper; use Magento\Usps\Model\Carrier; /** @@ -43,6 +44,11 @@ class CarrierTest extends \PHPUnit_Framework_TestCase */ protected $scope; + /** + * @var DataHelper|\PHPUnit_Framework_MockObject_MockObject + */ + private $dataHelper; + /** * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ @@ -154,7 +160,14 @@ class CarrierTest extends \PHPUnit_Framework_TestCase ]; + $this->dataHelper = $this->getMockBuilder(DataHelper::class) + ->disableOriginalConstructor() + ->setMethods(['displayGirthValue']) + ->getMock(); + $this->carrier = $this->helper->getObject(\Magento\Usps\Model\Carrier::class, $arguments); + + $this->helper->setBackwardCompatibleProperty($this->carrier, 'dataHelper', $this->dataHelper); } /** @@ -324,4 +337,33 @@ class CarrierTest extends \PHPUnit_Framework_TestCase ], ]; } + + /** + * @param string $countyCode + * @param string $carrierMethodCode + * @param bool $displayGirthValueResult + * @param bool $result + * @dataProvider isGirthAllowedDataProvider + */ + public function testIsGirthAllowed($countyCode, $carrierMethodCode, $displayGirthValueResult, $result) + { + $this->dataHelper->expects(static::any()) + ->method('displayGirthValue') + ->with($carrierMethodCode) + ->willReturn($displayGirthValueResult); + + self::assertEquals($result, $this->carrier->isGirthAllowed($countyCode, $carrierMethodCode)); + } + + /** + * @return array + */ + public function isGirthAllowedDataProvider() + { + return [ + ['US', 'usps_1', true, false], + ['UK', 'usps_1', true, true], + ['US', 'usps_0', false, true], + ]; + } } diff --git a/app/code/Magento/Usps/etc/adminhtml/di.xml b/app/code/Magento/Usps/etc/adminhtml/di.xml index f098306c6e99b5488c07a6aa152a1f4e74878087..f60c4d8eb58683f203e1aba6db8a01384101e2f4 100644 --- a/app/code/Magento/Usps/etc/adminhtml/di.xml +++ b/app/code/Magento/Usps/etc/adminhtml/di.xml @@ -6,12 +6,6 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> - <type name="Magento\Rma\Block\Adminhtml\Rma\Edit\Tab\General\Shipping\Packaging"> - <arguments> - <argument name="sourceSizeModel" xsi:type="object">Magento\Usps\Model\Source\Size</argument> - </arguments> - <plugin name="usps" type="Magento\Usps\Block\Rma\Adminhtml\Rma\Edit\Tab\General\Shipping\Packaging\Plugin"/> - </type> <type name="Magento\Shipping\Block\Adminhtml\Order\Packaging"> <arguments> <argument name="sourceSizeModel" xsi:type="object">Magento\Usps\Model\Source\Size</argument> diff --git a/app/code/Magento/Vault/Model/ResourceModel/PaymentToken.php b/app/code/Magento/Vault/Model/ResourceModel/PaymentToken.php index e7644080abb7defd380e24a8362f1774505dc4e7..b9ffc69cf7fe804175318d3715741ef7cafc5a26 100644 --- a/app/code/Magento/Vault/Model/ResourceModel/PaymentToken.php +++ b/app/code/Magento/Vault/Model/ResourceModel/PaymentToken.php @@ -104,7 +104,7 @@ class PaymentToken extends AbstractDb $connection = $this->getConnection(); $select = $connection->select() - ->from(InstallSchema::ORDER_PAYMENT_TO_PAYMENT_TOKEN_TABLE) + ->from($this->getTable(InstallSchema::ORDER_PAYMENT_TO_PAYMENT_TOKEN_TABLE)) ->where('order_payment_id = ?', (int) $orderPaymentId) ->where('payment_token_id =?', (int) $paymentTokenId); diff --git a/composer.lock b/composer.lock index 77553a16419e85258357d8b76c9aaea8302d7e37..6fd73ef405c822bcb049709ec1150c6e51254e35 100644 --- a/composer.lock +++ b/composer.lock @@ -922,16 +922,16 @@ }, { "name": "phpseclib/phpseclib", - "version": "2.0.2", + "version": "2.0.3", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "3d265f7c079f5b37d33475f996d7a383c5fc8aeb" + "reference": "41f85e9c2582b3f6d1b7d20395fb40c687ad5370" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/3d265f7c079f5b37d33475f996d7a383c5fc8aeb", - "reference": "3d265f7c079f5b37d33475f996d7a383c5fc8aeb", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/41f85e9c2582b3f6d1b7d20395fb40c687ad5370", + "reference": "41f85e9c2582b3f6d1b7d20395fb40c687ad5370", "shasum": "" }, "require": { @@ -1010,7 +1010,7 @@ "x.509", "x509" ], - "time": "2016-05-13 01:15:21" + "time": "2016-08-18 18:49:14" }, { "name": "psr/log", @@ -1381,16 +1381,16 @@ }, { "name": "symfony/event-dispatcher", - "version": "v2.8.8", + "version": "v2.8.9", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "b180b70439dca70049b6b9b7e21d75e6e5d7aca9" + "reference": "889983a79a043dfda68f38c38b6dba092dd49cd8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b180b70439dca70049b6b9b7e21d75e6e5d7aca9", - "reference": "b180b70439dca70049b6b9b7e21d75e6e5d7aca9", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/889983a79a043dfda68f38c38b6dba092dd49cd8", + "reference": "889983a79a043dfda68f38c38b6dba092dd49cd8", "shasum": "" }, "require": { @@ -1437,20 +1437,20 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2016-06-29 05:29:29" + "time": "2016-07-28 16:56:28" }, { "name": "symfony/filesystem", - "version": "v2.8.8", + "version": "v2.8.9", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "7258ddd6f987053f21fa43d03430580ba54e6096" + "reference": "ab4c3f085c8f5a56536845bf985c4cef30bf75fd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/7258ddd6f987053f21fa43d03430580ba54e6096", - "reference": "7258ddd6f987053f21fa43d03430580ba54e6096", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/ab4c3f085c8f5a56536845bf985c4cef30bf75fd", + "reference": "ab4c3f085c8f5a56536845bf985c4cef30bf75fd", "shasum": "" }, "require": { @@ -1486,11 +1486,11 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2016-06-29 05:31:50" + "time": "2016-07-20 05:41:28" }, { "name": "symfony/finder", - "version": "v3.1.2", + "version": "v3.1.3", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", @@ -1539,16 +1539,16 @@ }, { "name": "symfony/process", - "version": "v2.8.8", + "version": "v2.8.9", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "89f33c16796415ccfd8bb3cf8d520cbb79899bfe" + "reference": "d20332e43e8774ff8870b394f3dd6020cc7f8e0c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/89f33c16796415ccfd8bb3cf8d520cbb79899bfe", - "reference": "89f33c16796415ccfd8bb3cf8d520cbb79899bfe", + "url": "https://api.github.com/repos/symfony/process/zipball/d20332e43e8774ff8870b394f3dd6020cc7f8e0c", + "reference": "d20332e43e8774ff8870b394f3dd6020cc7f8e0c", "shasum": "" }, "require": { @@ -1584,7 +1584,7 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2016-06-29 05:29:29" + "time": "2016-07-28 11:13:19" }, { "name": "tedivm/jshrink", @@ -3233,35 +3233,35 @@ }, { "name": "fabpot/php-cs-fixer", - "version": "v1.11.5", + "version": "v1.12.0", "source": { "type": "git", "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", - "reference": "d3d08b76753092a232a4d8c3b94095ac06898719" + "reference": "ddac737e1c06a310a0bb4b3da755a094a31a916a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/d3d08b76753092a232a4d8c3b94095ac06898719", - "reference": "d3d08b76753092a232a4d8c3b94095ac06898719", + "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/ddac737e1c06a310a0bb4b3da755a094a31a916a", + "reference": "ddac737e1c06a310a0bb4b3da755a094a31a916a", "shasum": "" }, "require": { "ext-tokenizer": "*", - "php": ">=5.3.6", - "sebastian/diff": "~1.1", - "symfony/console": "~2.3|~3.0", - "symfony/event-dispatcher": "~2.1|~3.0", - "symfony/filesystem": "~2.1|~3.0", - "symfony/finder": "~2.1|~3.0", - "symfony/process": "~2.3|~3.0", - "symfony/stopwatch": "~2.5|~3.0" + "php": "^5.3.6 || >=7.0 <7.2", + "sebastian/diff": "^1.1", + "symfony/console": "^2.3 || ^3.0", + "symfony/event-dispatcher": "^2.1 || ^3.0", + "symfony/filesystem": "^2.1 || ^3.0", + "symfony/finder": "^2.1 || ^3.0", + "symfony/process": "^2.3 || ^3.0", + "symfony/stopwatch": "^2.5 || ^3.0" }, "conflict": { "hhvm": "<3.9" }, "require-dev": { "phpunit/phpunit": "^4.5|^5", - "satooshi/php-coveralls": "^0.7.1" + "satooshi/php-coveralls": "^1.0" }, "bin": [ "php-cs-fixer" @@ -3288,7 +3288,7 @@ ], "description": "A tool to automatically fix PHP code style", "abandoned": "friendsofphp/php-cs-fixer", - "time": "2016-07-06 22:49:35" + "time": "2016-08-17 00:17:27" }, { "name": "lusitanian/oauth", @@ -3951,23 +3951,23 @@ }, { "name": "sebastian/environment", - "version": "1.3.7", + "version": "1.3.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716" + "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/4e8f0da10ac5802913afc151413bc8c53b6c2716", - "reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea", + "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^5.3.3 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "~4.4" + "phpunit/phpunit": "^4.8 || ^5.0" }, "type": "library", "extra": { @@ -3997,7 +3997,7 @@ "environment", "hhvm" ], - "time": "2016-05-17 03:18:57" + "time": "2016-08-18 05:49:44" }, { "name": "sebastian/exporter", @@ -4321,16 +4321,16 @@ }, { "name": "symfony/config", - "version": "v2.8.8", + "version": "v2.8.9", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "0926e69411eba491803dbafb9f1f233e2ced58d0" + "reference": "4275ef5b59f18959df0eee3991e9ca0cc208ffd4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/0926e69411eba491803dbafb9f1f233e2ced58d0", - "reference": "0926e69411eba491803dbafb9f1f233e2ced58d0", + "url": "https://api.github.com/repos/symfony/config/zipball/4275ef5b59f18959df0eee3991e9ca0cc208ffd4", + "reference": "4275ef5b59f18959df0eee3991e9ca0cc208ffd4", "shasum": "" }, "require": { @@ -4370,20 +4370,20 @@ ], "description": "Symfony Config Component", "homepage": "https://symfony.com", - "time": "2016-06-29 05:31:50" + "time": "2016-07-26 08:02:44" }, { "name": "symfony/dependency-injection", - "version": "v2.8.8", + "version": "v2.8.9", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "2dd85de8216079d1360b2b14988cd5cdbbb49063" + "reference": "f2b5a00d176f6a201dc430375c0ef37706ea3d12" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/2dd85de8216079d1360b2b14988cd5cdbbb49063", - "reference": "2dd85de8216079d1360b2b14988cd5cdbbb49063", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/f2b5a00d176f6a201dc430375c0ef37706ea3d12", + "reference": "f2b5a00d176f6a201dc430375c0ef37706ea3d12", "shasum": "" }, "require": { @@ -4395,7 +4395,7 @@ "require-dev": { "symfony/config": "~2.2|~3.0.0", "symfony/expression-language": "~2.6|~3.0.0", - "symfony/yaml": "~2.1|~3.0.0" + "symfony/yaml": "~2.3.42|~2.7.14|~2.8.7|~3.0.7" }, "suggest": { "symfony/config": "", @@ -4433,11 +4433,11 @@ ], "description": "Symfony DependencyInjection Component", "homepage": "https://symfony.com", - "time": "2016-06-29 05:31:50" + "time": "2016-07-30 07:20:35" }, { "name": "symfony/stopwatch", - "version": "v3.1.2", + "version": "v3.1.3", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", @@ -4486,16 +4486,16 @@ }, { "name": "symfony/yaml", - "version": "v2.8.8", + "version": "v2.8.9", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "dba4bb5846798cd12f32e2d8f3f35d77045773c8" + "reference": "0ceab136f43ed9d3e97b3eea32a7855dc50c121d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/dba4bb5846798cd12f32e2d8f3f35d77045773c8", - "reference": "dba4bb5846798cd12f32e2d8f3f35d77045773c8", + "url": "https://api.github.com/repos/symfony/yaml/zipball/0ceab136f43ed9d3e97b3eea32a7855dc50c121d", + "reference": "0ceab136f43ed9d3e97b3eea32a7855dc50c121d", "shasum": "" }, "require": { @@ -4531,7 +4531,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2016-06-29 05:29:29" + "time": "2016-07-17 09:06:15" }, { "name": "theseer/fdomdocument", diff --git a/dev/tests/integration/testsuite/Magento/Vault/Model/ResourceModel/PaymentTokenTest.php b/dev/tests/integration/testsuite/Magento/Vault/Model/ResourceModel/PaymentTokenTest.php new file mode 100644 index 0000000000000000000000000000000000000000..88974f0d9cc5e4d09ad6cd173edf9ff5052711bb --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Vault/Model/ResourceModel/PaymentTokenTest.php @@ -0,0 +1,114 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Vault\Model\ResourceModel; + +use Magento\Braintree\Model\Ui\PayPal\ConfigProvider as PayPalConfigProvider; +use Magento\Framework\App\ResourceConnection; +use Magento\Framework\DB\Adapter\AdapterInterface; +use Magento\Framework\ObjectManagerInterface; +use Magento\Sales\Model\Order; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\Vault\Model\PaymentTokenManagement; +use Magento\Vault\Setup\InstallSchema; + +class PaymentTokenTest extends \PHPUnit_Framework_TestCase +{ + const CUSTOMER_ID = 1; + const TOKEN = 'mx29vk'; + const ORDER_INCREMENT_ID = '100000001'; + + /** + * @var ObjectManagerInterface + */ + private $objectManager; + + /** + * @var PaymentToken + */ + private $paymentToken; + + /** + * @var ResourceConnection + */ + private $resource; + + /** + * @var AdapterInterface + */ + private $connection; + + /** + * @var PaymentTokenManagement + */ + private $paymentTokenManagement; + + /** + * @var Order + */ + private $order; + + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->order = $this->objectManager->create(Order::class); + $this->paymentToken = $this->objectManager->create(PaymentToken::class); + $this->paymentTokenManagement = $this->objectManager->get(PaymentTokenManagement::class); + + $this->resource = $this->objectManager->get(ResourceConnection::class); + $this->connection = $this->resource->getConnection(); + } + + /** + * @magentoDataFixture Magento/Sales/_files/order.php + * @magentoDataFixture Magento/Braintree/_files/paypal_vault_token.php + */ + public function testAddLinkToOrderPaymentExists() + { + $this->order->loadByIncrementId(self::ORDER_INCREMENT_ID); + $paymentToken = $this->paymentTokenManagement + ->getByGatewayToken(self::TOKEN, PayPalConfigProvider::PAYPAL_CODE, self::CUSTOMER_ID); + + $this->connection->insert( + $this->resource->getTableName(InstallSchema::ORDER_PAYMENT_TO_PAYMENT_TOKEN_TABLE), + [ + 'order_payment_id' => $this->order->getPayment()->getEntityId(), + 'payment_token_id' => $paymentToken->getEntityId() + ] + ); + + static::assertTrue( + $this->paymentToken->addLinkToOrderPayment( + $paymentToken->getEntityId(), + $this->order->getPayment()->getEntityId() + ) + ); + } + + /** + * @magentoDataFixture Magento/Sales/_files/order.php + * @magentoDataFixture Magento/Braintree/_files/paypal_vault_token.php + */ + public function testAddLinkToOrderPaymentCreate() + { + $this->order->loadByIncrementId(self::ORDER_INCREMENT_ID); + $paymentToken = $this->paymentTokenManagement + ->getByGatewayToken(self::TOKEN, PayPalConfigProvider::PAYPAL_CODE, self::CUSTOMER_ID); + + $select = $this->connection->select() + ->from($this->resource->getTableName(InstallSchema::ORDER_PAYMENT_TO_PAYMENT_TOKEN_TABLE)) + ->where('order_payment_id = ?', (int) $this->order->getPayment()->getEntityId()) + ->where('payment_token_id =?', (int) $paymentToken->getEntityId()); + + static::assertEmpty($this->connection->fetchRow($select)); + static::assertTrue( + $this->paymentToken->addLinkToOrderPayment( + $paymentToken->getEntityId(), + $this->order->getPayment()->getEntityId() + ) + ); + static::assertNotEmpty($this->connection->fetchRow($select)); + } +} diff --git a/setup/pub/magento/setup/readiness-check.js b/setup/pub/magento/setup/readiness-check.js index dad3fc087c01601720813fe895fa9c4137ec8972..1b89ea2be06a5121c53b2ea8a97a681db067d0df 100644 --- a/setup/pub/magento/setup/readiness-check.js +++ b/setup/pub/magento/setup/readiness-check.js @@ -113,24 +113,6 @@ angular.module('readiness-check', ['remove-dialog']) updaterNoticeMessage: '' }; $scope.items = { - 'php-version': { - url:'index.php/environment/php-version', - params: $scope.actionFrom, - useGet: true, - show: function() { - $scope.startProgress(); - $scope.version.visible = true; - }, - process: function(data) { - $scope.version.processed = true; - angular.extend($scope.version, data); - $scope.updateOnProcessed($scope.version.responseType); - $scope.stopProgress(); - }, - fail: function() { - $scope.requestFailedHandler($scope.version); - } - }, 'php-settings': { url:'index.php/environment/php-settings', params: $scope.actionFrom, @@ -173,6 +155,24 @@ angular.module('readiness-check', ['remove-dialog']) }; if ($scope.actionFrom === 'installer') { + $scope.items['php-version'] = { + url:'index.php/environment/php-version', + params: $scope.actionFrom, + useGet: true, + show: function() { + $scope.startProgress(); + $scope.version.visible = true; + }, + process: function(data) { + $scope.version.processed = true; + angular.extend($scope.version, data); + $scope.updateOnProcessed($scope.version.responseType); + $scope.stopProgress(); + }, + fail: function() { + $scope.requestFailedHandler($scope.version); + } + }; $scope.items['file-permissions'] = { url:'index.php/environment/file-permissions', show: function() { @@ -260,22 +260,20 @@ angular.module('readiness-check', ['remove-dialog']) } }; } - } $scope.isCompleted = function() { - return $scope.version.processed - && $scope.settings.processed + var cronProcessed = ( + $scope.cronScript.processed + && ($scope.componentDependency.processed || !$scope.componentDependency.enabled) + && $scope.updater.processed + ); + + return $scope.settings.processed && $scope.extensions.processed && ($scope.permissions.processed || ($scope.actionFrom === 'updater')) - && ( - ( - $scope.cronScript.processed - && ($scope.componentDependency.processed || !$scope.componentDependency.enabled) - && $scope.updater.processed - ) - || ($scope.actionFrom !== 'updater') - ); + && ($scope.version.processed || ($scope.actionFrom === 'updater')) + && (cronProcessed || ($scope.actionFrom !== 'updater')); }; $scope.updateOnProcessed = function(value) { diff --git a/setup/src/Magento/Setup/Controller/CompleteBackup.php b/setup/src/Magento/Setup/Controller/CompleteBackup.php index d8996cca7fe642f8011df06ce8f6e0764259f937..f194f02ed1fc96209bbc11a5b7da22cd7e0fe65d 100644 --- a/setup/src/Magento/Setup/Controller/CompleteBackup.php +++ b/setup/src/Magento/Setup/Controller/CompleteBackup.php @@ -18,8 +18,8 @@ class CompleteBackup extends AbstractActionController public function indexAction() { $view = new ViewModel; - $view->setTerminal(true); - $view->setTemplate('/magento/setup/complete-backup.phtml'); + $view->setTemplate('/error/404.phtml'); + $this->getResponse()->setStatusCode(\Zend\Http\Response::STATUS_CODE_404); return $view; } diff --git a/setup/src/Magento/Setup/Test/Unit/Controller/CompleteBackupTest.php b/setup/src/Magento/Setup/Test/Unit/Controller/CompleteBackupTest.php index 7101629502cb26f3350e33da6d2082ff31ae6d55..efe87a98889e047c3b14c2a9977adff0f0c96017 100644 --- a/setup/src/Magento/Setup/Test/Unit/Controller/CompleteBackupTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Controller/CompleteBackupTest.php @@ -26,8 +26,11 @@ class CompleteBackupTest extends \PHPUnit_Framework_TestCase { $viewModel = $this->controller->indexAction(); $this->assertInstanceOf(\Zend\View\Model\ViewModel::class, $viewModel); - $this->assertTrue($viewModel->terminate()); - $this->assertSame('/magento/setup/complete-backup.phtml', $viewModel->getTemplate()); + $this->assertSame('/error/404.phtml', $viewModel->getTemplate()); + $this->assertSame( + \Zend\Http\Response::STATUS_CODE_404, + $this->controller->getResponse()->getStatusCode() + ); } public function testProgressAction() diff --git a/setup/view/magento/setup/create-admin-account.phtml b/setup/view/magento/setup/create-admin-account.phtml index 35c0c911b184cf9e3759eba4e9032cedd73216ff..135fb89b9773e40bfd879999def6a8af731d1a44 100644 --- a/setup/view/magento/setup/create-admin-account.phtml +++ b/setup/view/magento/setup/create-admin-account.phtml @@ -19,7 +19,7 @@ $passwordWizard = sprintf( </div> <p>%s</p>', 'Password Strength:', - 'Enter a mix of 7 or more numbers and letters. For a stronger password, include at least one small letter, big letter, and symbol (Ex: BuyIt$54).' + 'Enter a mix of 7 or more numbers and letters. For a stronger password, include at least one small letter, big letter, and symbol.' ); ?>