-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add fast checkout hydrateOrder endpoint (#261)
* Add fast checkout hydrateOrder endpoint * Add missing fields & return response * Add fee and discount calculations * Account for 0 discount total
- Loading branch information
1 parent
26e93b3
commit 1798d82
Showing
6 changed files
with
241 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
.idea | ||
.DS_Store |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<?php | ||
|
||
namespace Bold\Checkout\Api\Order; | ||
|
||
use Bold\Checkout\Api\Data\Http\Client\ResultInterface; | ||
use Magento\Quote\Api\Data\CartInterface; | ||
|
||
/** | ||
* Hydrate Bold order from Magento quote. | ||
*/ | ||
interface HydrateOrderFromQuoteInterface | ||
{ | ||
/** | ||
* Hydrate Bold simple order with Magento quote data | ||
* | ||
* @param CartInterface $quote | ||
* @param string $publicOrderId | ||
* @return ResultInterface | ||
*/ | ||
public function hydrate(CartInterface $quote, string $publicOrderId): ResultInterface; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,198 @@ | ||
<?php | ||
declare(strict_types=1); | ||
|
||
namespace Bold\Checkout\Model\Order; | ||
|
||
use Bold\Checkout\Api\Data\Http\Client\ResultInterface; | ||
use Bold\Checkout\Api\Http\ClientInterface; | ||
use Bold\Checkout\Api\Order\HydrateOrderFromQuoteInterface; | ||
use Bold\Checkout\Model\Order\Address\Converter; | ||
use Bold\Checkout\Model\Quote\GetCartLineItems; | ||
use Magento\Quote\Api\Data\CartInterface; | ||
use Magento\Quote\Model\Quote\Address\ToOrderAddress; | ||
|
||
/** | ||
* Hydrate Bold order from Magento quote. | ||
*/ | ||
class HydrateOrderFromQuote implements HydrateOrderFromQuoteInterface | ||
{ | ||
private const HYDRATE_ORDER_URL = 'checkout_sidekick/{{shopId}}/order/%s'; | ||
private const EXPECTED_SEGMENTS = [ | ||
'subtotal', | ||
'shipping', | ||
'discount', | ||
'tax', | ||
'grand_total', | ||
]; | ||
|
||
/** | ||
* @var ClientInterface | ||
*/ | ||
private $client; | ||
|
||
/** | ||
* @var GetCartLineItems | ||
*/ | ||
private $getCartLineItems; | ||
|
||
/** | ||
* @var Converter | ||
*/ | ||
private $addressConverter; | ||
|
||
/** | ||
* @var ToOrderAddress | ||
*/ | ||
private $quoteToOrderAddressConverter; | ||
|
||
/** | ||
* @param ClientInterface $client | ||
* @param GetCartLineItems $getCartLineItems | ||
* @param Converter $addressConverter | ||
* @param ToOrderAddress $quoteToOrderAddressConverter | ||
*/ | ||
public function __construct( | ||
ClientInterface $client, | ||
GetCartLineItems $getCartLineItems, | ||
Converter $addressConverter, | ||
ToOrderAddress $quoteToOrderAddressConverter, | ||
) { | ||
$this->client = $client; | ||
$this->getCartLineItems = $getCartLineItems; | ||
$this->addressConverter = $addressConverter; | ||
$this->quoteToOrderAddressConverter = $quoteToOrderAddressConverter; | ||
} | ||
|
||
/** | ||
* @param CartInterface $quote | ||
* @param string $publicOrderId | ||
* @return ResultInterface | ||
*/ | ||
public function hydrate(CartInterface $quote, string $publicOrderId): ResultInterface | ||
{ | ||
$websiteId = (int)$quote->getStore()->getWebsiteId(); | ||
$billingAddress = $this->quoteToOrderAddressConverter->convert($quote->getBillingAddress()); | ||
|
||
if ($quote->getIsVirtual()) { | ||
$totals = $quote->getBillingAddress()->getTotals(); | ||
} else { | ||
$totals = $quote->getShippingAddress()->getTotals(); | ||
$shippingDescription = $quote->getShippingAddress()->getShippingDescription(); | ||
} | ||
|
||
list($fees, $discounts) = $this->getFeesAndDiscounts($totals); | ||
$discountTotal = array_reduce($discounts, function($sum, $discountLine) { | ||
return $sum + $discountLine['value']; | ||
}); | ||
|
||
$body = [ | ||
'billing_address' => $this->addressConverter->convert($billingAddress), | ||
'cart_items' => $this->getCartLineItems->getItems($quote), | ||
'taxes' => $this->getTaxLines($totals['tax']['full_info']), | ||
'discounts' => $discounts, | ||
'fees' => $fees, | ||
'shipping_line' => [ | ||
'rate_name' => $shippingDescription ?? '', | ||
'cost' => $this->convertToCents($totals['shipping']['value']) | ||
], | ||
'totals' => [ | ||
'sub_total' => $this->convertToCents($totals['subtotal']['value']), | ||
'tax_total' => $this->convertToCents($totals['tax']['value']), | ||
'discount_total' => $discountTotal ?? 0, | ||
'shipping_total' => $this->convertToCents($totals['shipping']['value']), | ||
'order_total' => $this->convertToCents($totals['grand_total']['value']) | ||
], | ||
]; | ||
|
||
if ($quote->getCustomer()->getId()) { | ||
$body['customer'] = [ | ||
'platform_id' => (string)$quote->getCustomerId(), | ||
'first_name' => $quote->getCustomerFirstname(), | ||
'last_name' => $quote->getCustomerLastname(), | ||
'email_address' => $quote->getCustomerEmail(), | ||
]; | ||
} else { | ||
$body['customer'] = [ | ||
'platform_id' => null, | ||
'first_name' => $billingAddress->getFirstname(), | ||
'last_name' => $billingAddress->getLastname(), | ||
'email_address' => $billingAddress->getEmail(), | ||
]; | ||
} | ||
|
||
$url = sprintf(self::HYDRATE_ORDER_URL, $publicOrderId); | ||
return $this->client->put($websiteId, $url, $body); | ||
} | ||
|
||
/** | ||
* Converts a dollar amount to cents | ||
* | ||
* @param float|string $dollars | ||
* @return integer | ||
*/ | ||
private function convertToCents(float|string $dollars): int | ||
{ | ||
return (int)round(floatval($dollars) * 100); | ||
} | ||
|
||
/** | ||
* Get formatted tax lines | ||
* | ||
* @param array $taxes | ||
* @return array | ||
*/ | ||
private function getTaxLines(array $taxes): array | ||
{ | ||
$taxLines = []; | ||
|
||
foreach ($taxes as $tax){ | ||
$taxLines[] = [ | ||
'name' => $tax['id'], | ||
'value' => $this->convertToCents($tax['base_amount']) | ||
]; | ||
} | ||
|
||
return $taxLines; | ||
} | ||
|
||
/** | ||
* Looks at total segments and makes unrecognized segments into fees and discounts | ||
* | ||
* @param array $totals | ||
* @return array | ||
*/ | ||
private function getFeesAndDiscounts(array $totals): array | ||
{ | ||
$fees = []; | ||
$discounts = []; | ||
|
||
if (isset($totals['discount'])) { | ||
$discounts[] = [ | ||
'line_text' => $totals['discount']['code'], | ||
'value' => abs($this->convertToCents($totals['discount']['value'])) | ||
]; | ||
} | ||
|
||
foreach ($totals as $segment) { | ||
if (in_array($segment['code'], self::EXPECTED_SEGMENTS) || !$segment['value']) { | ||
continue; | ||
} | ||
|
||
$description = $totalSegment['title'] ?? ucfirst(str_replace('_', ' ', $segment['code'])); | ||
|
||
if ($segment['value'] > 0) { | ||
$fees[] = [ | ||
'description' => $description, | ||
'value' => $this->convertToCents($segment['value']) | ||
]; | ||
} else { | ||
$discounts[] = [ | ||
'line_text' => $description, | ||
'value' => abs($this->convertToCents($segment['value'])) | ||
]; | ||
} | ||
} | ||
|
||
return [$fees, $discounts]; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters