/**
  * Extract tax data from the tax response payload and store tax records,
  * duties and fees.
  *
  * Extracts all three sets of tax data as each set of data can be retrieved
  * from the same address parser. Extracting all three sets at once prevents
  * nearly identical steps from being repeated for each ship group for each
  * type of tax data.
  *
  * @return self
  */
 protected function _extractTaxData()
 {
     // Each of these will hold an array of arrays of data extracted from each
     // ship group - e.g. $taxRecords = [[$recordA, $recordB], [$recordC, $recordD]].
     $taxRecords = [];
     $duties = [];
     $fees = [];
     foreach ($this->_taxResponse->getShipGroups() as $shipGroup) {
         $address = $this->_getQuoteAddressForShipGroup($shipGroup);
         if ($address) {
             $addressParser = $this->_taxFactory->createResponseAddressParser($shipGroup, $address);
             $taxRecords[] = $addressParser->getTaxRecords();
             $duties[] = $addressParser->getTaxDuties();
             $fees[] = $addressParser->getTaxFees();
         } else {
             $this->_logger->warn('Tax response ship group does not relate to any known address.', $this->_logContext->getMetaData(__CLASS__, ['rom_response_body' => $shipGroup->serialize()]));
         }
     }
     // Flatten each nested array of tax data - allows for a single array_merge
     // instead of iteratively calling array_merge on each pass when extracting
     // tax data for each ship group.
     $this->_taxRecords = $this->_flattenArray($taxRecords);
     $this->_taxDuties = $this->_flattenArray($duties);
     $this->_taxFees = $this->_flattenArray($fees);
     return $this;
 }
 /**
  * When extracting results from the SDK response, a tax
  * result model with the tax data extracted from the
  * response should be returned.
  */
 public function testExtractResponseResultsSuccess()
 {
     // Create an expected result, should be returned when successfully
     // extracting results from a response.
     $sdkResult = $this->getModelMockBuilder('ebayenterprise_tax/result')->disableOriginalConstructor()->getMock();
     // Mock the API to return an expected response body as the
     // reply to the SDK request.
     $this->_api->expects($this->any())->method('getResponseBody')->will($this->returnValue($this->_responseBody));
     // Mock up some SDK results - doesn't really matter what these
     // are, just that they can be recognized as the "right" results.
     $taxRecords = [$this->getModelMockBuilder('ebayenteprirse_tax/record')->disableOriginalConstructor()->getMock()];
     $taxDuties = [$this->getModelMockBuilder('ebayenteprirse_tax/duty')->disableOriginalConstructor()->getMock()];
     $taxFees = [$this->getModelMockBuilder('ebayenteprirse_tax/fee')->disableOriginalConstructor()->getMock()];
     // Create a quote response parser capable of returning the
     // proper results from the tax response.
     $this->_quoteResponseParser->expects($this->any())->method('getTaxRecords')->will($this->returnValue($taxRecords));
     $this->_quoteResponseParser->expects($this->any())->method('getTaxDuties')->will($this->returnValue($taxDuties));
     $this->_quoteResponseParser->expects($this->any())->method('getTaxFees')->will($this->returnValue($taxFees));
     // Setup the tax factory to be able to provide the proper quote
     // response parser if given the correct response payload and quote.
     $this->_taxFactory->expects($this->any())->method('createResponseQuoteParser')->with($this->identicalTo($this->_responseBody), $this->identicalTo($this->_quote))->will($this->returnValue($this->_quoteResponseParser));
     // Setup the tax factory to be able to provide the proper SDK result
     // if given the expected tax data.
     $this->_taxFactory->expects($this->any())->method('createTaxResults')->with($this->identicalTo($taxRecords), $this->identicalTo($taxDuties), $this->identicalTo($taxFees))->will($this->returnValue($sdkResult));
     // Ensure that the correct SDK result is returned when extracting
     // results from the SDK. For now, this will return the exact same
     // instance as is expected. In the future this may not be the case and
     // test could be expected to simply ensure the results available in
     // the returned result model match the expected results.
     $this->assertSame($sdkResult, EcomDev_Utils_Reflection::invokeRestrictedMethod($this->_sdkHelper, '_extractResponseResults', [$this->_api, $this->_quote]));
 }
 /**
  * Add data to the request for addresses in the quote.
  *
  * @return self
  */
 protected function _injectAddressData()
 {
     $destinationIterable = $this->_payload->getDestinations();
     $shipGroupIterable = $this->_payload->getShipGroups();
     foreach ($this->_quote->getAddressesCollection() as $address) {
         // Defer responsibility for building ship group and destination
         // payloads to address request builders.
         $addressBuilder = $this->_taxFactory->createRequestBuilderAddress($shipGroupIterable, $destinationIterable, $address);
         $destinationPayload = $addressBuilder->getDestinationPayload();
         // Billing addresses need to be set separately in the request payload.
         // The addres request builder should have created the destination
         // for the billing address, even if there were no items to add to
         // to the ship group for the billing address. E.g. a billing address
         // is still a destination so the returned payload will still have a
         // destination but may not be a valid ship group (checked separately).
         if ($address->getAddressType() === Mage_Sales_Model_Quote_Address::TYPE_BILLING) {
             $this->_payload->setBillingInformation($destinationPayload);
         }
         $shipGroupPayload = $addressBuilder->getShipGroupPayload();
         if ($shipGroupPayload) {
             $shipGroupIterable[$shipGroupPayload] = $shipGroupPayload;
         }
     }
     $this->_payload->setShipGroups($shipGroupIterable);
     return $this;
 }
 /**
  * Extract tax records from the API response body for the quote.
  *
  * @param IBidirectionalApi
  * @param Mage_Sales_Model_Order_Quote
  * @return EbayEnterprise_Tax_Model_Result
  */
 protected function _extractResponseResults(IBidirectionalApi $api, Mage_Sales_Model_Quote $quote)
 {
     try {
         $responseBody = $api->getResponseBody();
     } catch (UnsupportedOperation $e) {
         // This exception handling is probably not necessary but
         // is technically possible. If the sdk flow of
         // getRequest->setRequest->send->getResponse is followed,
         // which is is by the one public method of this class, this
         // exception should never be thrown in this instance. If it
         // were to be thrown at all by the SDK, it would have already
         // happened during the "send" step.
         $this->logger->critical('Tax quote service response unsupported by SDK.', $this->logContext->getMetaData(__CLASS__, [], $e));
         throw $this->_failTaxCollection();
     }
     $responseParser = $this->taxFactory->createResponseQuoteParser($responseBody, $quote);
     return $this->taxFactory->createTaxResults($responseParser->getTaxRecords(), $responseParser->getTaxDuties(), $responseParser->getTaxFees());
 }
 /**
  * Add order items to the ship group for each item shipping to the address.
  *
  * @return self
  */
 protected function _injectItemData()
 {
     $orderItemIterable = $this->_shipGroup->getItems();
     // The first item needs to include shipping totals, use this flag to
     // track when item is the first item.
     $first = true;
     foreach ($this->_address->getAllVisibleItems() as $item) {
         // Add shipping amounts to the first item - necessary way of sending
         // address level shipping totals which is the only way Magento can
         // report shipping totals.
         if ($first) {
             $item->setIncludeShippingTotals(true);
         }
         $itemBuilder = $this->_taxFactory->createRequestBuilderItem($orderItemIterable, $this->_address, $item);
         $itemPayload = $itemBuilder->getOrderItemPayload();
         if ($itemPayload) {
             $orderItemIterable[$itemPayload] = null;
         }
         // After the first iteration, this should always be false.
         $first = false;
     }
     return $this;
 }
 /**
  * Extract tax records from a gifting payload.
  *
  * @return EbayEnterprise_Tax_Model_Record[]
  */
 protected function _extractGiftingTaxRecords()
 {
     return $this->_taxFactory->createTaxRecordsForTaxContainer(EbayEnterprise_Tax_Model_Record::SOURCE_ADDRESS_GIFTING, $this->_quoteId, $this->_addressId, $this->_shipGroup->getGiftPricing());
 }
 /**
  * Extract tax records from a gifting payload.
  *
  * @return EbayEnterprise_Tax_Model_Record
  */
 protected function _extractGiftingTaxRecords()
 {
     return $this->_taxFactory->createTaxRecordsForTaxContainer(EbayEnterprise_Tax_Model_Record::SOURCE_ITEM_GIFTING, $this->_quoteId, $this->_addressId, $this->_orderItem->getGiftPricing(), ['item_id' => $this->_itemId]);
 }