Skip to content

Commit

Permalink
Merge pull request #28 from two-inc/brtknr/t-14138-add-new-fulfilment…
Browse files Browse the repository at this point in the history
…-trigger-on-complete

T-14138/feat: Add new fulfilment trigger on complete
  • Loading branch information
brtkwr authored Nov 15, 2023
2 parents 55ed0c3 + 1f72cd0 commit 62de2a1
Show file tree
Hide file tree
Showing 14 changed files with 308 additions and 38 deletions.
16 changes: 13 additions & 3 deletions Api/Config/RepositoryInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ interface RepositoryInterface
public const XML_PATH_MERCHANT_SHORT_NAME = 'payment/two_payment/merchant_short_name';
public const XML_PATH_API_KEY = 'payment/two_payment/api_key';
public const XML_PATH_DAYS_ON_INVOICE = 'payment/two_payment/days_on_invoice';
public const XML_PATH_FULFILL_ORDER_ORDER = 'payment/two_payment/fulfill_order';
public const XML_PATH_FULFILL_TRIGGER = 'payment/two_payment/fulfill_trigger';
public const XML_PATH_FULFILL_ORDER_STATUS = 'payment/two_payment/fulfill_order_status';
public const XML_PATH_INTERNATIONAL_TELEPHONE_ENABLED = 'payment/two_payment/international_telephone_enabled';
public const XML_PATH_COMPANY_NAME_AUTOCOMPLETE_ENABLED = 'payment/two_payment/company_autocomplete_enabled';
public const XML_PATH_ENABLE_DEPARTMENT_NAME = 'payment/two_payment/enable_department';
Expand Down Expand Up @@ -97,13 +98,22 @@ public function isDebugMode(int $storeId = null, ?string $scope = null): bool;
public function getDueInDays(?int $storeId = null): int;

/**
* Get Fulfill Order Type (invoice or shipment)
* Get Fulfill Trigger (invoice or shipment or complete)
*
* @param int|null $storeId
*
* @return string
*/
public function getFulfillOrderType(?int $storeId = null): string;
public function getFulfillTrigger(?int $storeId = null): string;

/**
* Get Fulfill Order Status
*
* @param int|null $storeId
*
* @return string
*/
public function getFulfillOrderStatus(?int $storeId = null): string;

/**
* Check if international telephone is enabled
Expand Down
12 changes: 10 additions & 2 deletions Model/Config/Repository.php
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,17 @@ public function getDueInDays(?int $storeId = null): int
/**
* @inheritDoc
*/
public function getFulfillOrderType(?int $storeId = null): string
public function getFulfillTrigger(?int $storeId = null): string
{
return (string)$this->getConfig(self::XML_PATH_FULFILL_ORDER_ORDER, $storeId);
return (string)$this->getConfig(self::XML_PATH_FULFILL_TRIGGER, $storeId);
}

/**
* @inheritDoc
*/
public function getFulfillOrderStatus(?int $storeId = null): string
{
return (string)$this->getConfig(self::XML_PATH_FULFILL_ORDER_STATUS, $storeId);
}

/**
Expand Down
41 changes: 41 additions & 0 deletions Model/Config/Source/FulfillOrderStatus.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php
/**
* Copyright © Two.inc All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Two\Gateway\Model\Config\Source;

use Magento\Framework\Data\OptionSourceInterface;
use Magento\Sales\Model\ResourceModel\Order\Status\Collection as OrderStatusCollection;

/**
* Fulfill Order Status Options
*/
class FulfillOrderStatus implements OptionSourceInterface
{
/**
* @var ConfigRepository
*/
private $orderStatusCollection;

/**
* @param ConfigRepository $configRepository
*/
public function __construct(
OrderStatusCollection $orderStatusCollection
) {
$this->orderStatusCollection = $orderStatusCollection;
}

/**
* Options getter
*
* @return array
*/
public function toOptionArray(): array
{
return $this->orderStatusCollection->addStateFilter("complete")->toOptionArray();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
use Magento\Framework\Data\OptionSourceInterface;

/**
* Fulfill Options
* Fulfill Trigger Options
*/
class Fulfill implements OptionSourceInterface
class FulfillTrigger implements OptionSourceInterface
{
/**
* Options getter
Expand All @@ -30,6 +30,10 @@ public function toOptionArray(): array
'value' => 'shipment',
'label' => __('On Shipment'),
],
[
'value' => 'complete',
'label' => __('On Completion'),
],
];
}
}
2 changes: 1 addition & 1 deletion Model/Two.php
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ public function capture(InfoInterface $payment, $amount)
*/
public function canCapture()
{
return $this->_canCapture && ($this->configRepository->getFulfillOrderType() == 'invoice');
return $this->_canCapture && ($this->configRepository->getFulfillTrigger() == 'invoice');
}

/**
Expand Down
Empty file modified Observer/SalesOrderPlaceAfter.php
100644 → 100755
Empty file.
174 changes: 174 additions & 0 deletions Observer/SalesOrderSaveAfter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
<?php
/**
* Copyright © Two.inc All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Two\Gateway\Observer;

use Exception;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Sales\Api\Data\OrderInterface;
use Magento\Sales\Api\OrderStatusHistoryRepositoryInterface;
use Magento\Sales\Model\Order;
use Magento\Sales\Model\Order\Status\HistoryFactory;
use Two\Gateway\Api\Config\RepositoryInterface as ConfigRepository;
use Two\Gateway\Model\Two;
use Two\Gateway\Service\Api\Adapter;

/**
* After Order Save Observer
* Fulfill Two paymemt after order saved
*/
class SalesOrderSaveAfter implements ObserverInterface
{
/**
* @var ConfigRepository
*/
private $configRepository;

/**
* @var Adapter
*/
private $apiAdapter;

/**
* @var HistoryFactory
*/
private $historyFactory;

/**
* @var OrderStatusHistoryRepositoryInterface
*/
private $orderStatusHistoryRepository;

/**
* SalesOrderSaveAfter constructor.
*
* @param ConfigRepository $configRepository
* @param Adapter $apiAdapter
* @param HistoryFactory $historyFactory
* @param OrderStatusHistoryRepositoryInterface $orderStatusHistoryRepository
*/
public function __construct(
ConfigRepository $configRepository,
Adapter $apiAdapter,
HistoryFactory $historyFactory,
OrderStatusHistoryRepositoryInterface $orderStatusHistoryRepository
) {
$this->configRepository = $configRepository;
$this->apiAdapter = $apiAdapter;
$this->historyFactory = $historyFactory;
$this->orderStatusHistoryRepository = $orderStatusHistoryRepository;
}

/**
* @param Observer $observer
* @throws LocalizedException
*/
public function execute(Observer $observer)
{
$order = $observer->getEvent()->getOrder();
if ($order
&& $order->getPayment()->getMethod() === Two::CODE
&& $order->getTwoOrderId()
) {
if (($this->configRepository->getFulfillTrigger() == 'complete')
&& ($this->configRepository->getFulfillOrderStatus() == $order->getStatus())
) {
if (!$this->isWholeOrderShipped($order)) {
$error = __("Two requires whole order to be shipped before it can be fulfilled.");
throw new LocalizedException($error);
}

$langParams = '?lang=en_US';
if ($order->getBillingAddress()->getCountryId() == 'NO') {
$langParams = '?lang=nb_NO';
}

//full fulfilment
$response = $this->apiAdapter->execute(
"/v1/order/" . $order->getTwoOrderId() . "/fulfilled" . $langParams
);

foreach ($order->getInvoiceCollection() as $invoice) {
$invoice->pay();
$invoice->setTransactionId($order->getPayment()->getLastTransId());
$invoice->save();
}

$this->parseResponse($response, $order);
}
}
}

/**
* @param OrderInterface $order
* @return bool
*/
private function isWholeOrderShipped(OrderInterface $order): bool
{
foreach ($order->getAllVisibleItems() as $orderItem) {
/** @var Order\Item $orderItem */
if ($orderItem->getQtyShipped() < $orderItem->getQtyOrdered()) {
return false;
}
}

return true;
}

/**
* @param array $response
* @param Order $order
* @return void
* @throws Exception
*/
private function parseResponse(array $response, Order $order): void
{
$error = $order->getPayment()->getMethodInstance()->getErrorFromResponse($response);

if ($error) {
throw new LocalizedException($error);
}

if (empty($response['invoice_details'] ||
empty($response['invoice_details']['invoice_number']))) {
return;
}

$additionalInformation = $order->getPayment()->getAdditionalInformation();
$additionalInformation['gateway_data']['invoice_number'] = $response['invoice_details']['invoice_number'];
$additionalInformation['gateway_data']['invoice_url'] = $response['invoice_url'];
$additionalInformation['marked_completed'] = true;

$order->getPayment()->setAdditionalInformation($additionalInformation);

$this->addStatusToOrderHistory(
$order,
sprintf(
'Two Order marked as completed with invoice number %s',
$response['invoice_details']['invoice_number']
)
);
}

/**
* @param Order $order
* @param string $comment
* @throws Exception
*/
private function addStatusToOrderHistory(Order $order, string $comment)
{
$history = $this->historyFactory->create();
$history->setParentId($order->getEntityId())
->setComment($comment)
->setEntityName('order')
->setStatus($order->getStatus());
$this->orderStatusHistoryRepository->save($history);
}
}
59 changes: 38 additions & 21 deletions Observer/SalesOrderShipmentAfter.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,30 +88,47 @@ public function execute(Observer $observer)
if ($order
&& $order->getPayment()->getMethod() === Two::CODE
&& $order->getTwoOrderId()
&& ($this->configRepository->getFulfillOrderType() == 'shipment')
) {
if (!$this->isWholeOrderShipped($order)) {
$response = $this->partialFulfill($shipment);
$this->parseResponse($response, $order);
return;
}

$langParams = '?lang=en_US';
if ($order->getBillingAddress()->getCountryId() == 'NO') {
$langParams = '?lang=nb_NO';
}
if ($this->configRepository->getFulfillTrigger() == 'shipment') {
if (!$this->isWholeOrderShipped($order)) {
$response = $this->partialFulfill($shipment);
$this->parseResponse($response, $order);
return;
}

$langParams = '?lang=en_US';
if ($order->getBillingAddress()->getCountryId() == 'NO') {
$langParams = '?lang=nb_NO';
}

//full fulfilment
$response = $this->apiAdapter->execute(
"/v1/order/" . $order->getTwoOrderId() . "/fulfilled" . $langParams
);
foreach ($order->getInvoiceCollection() as $invoice) {
$invoice->pay();
$invoice->setTransactionId($order->getPayment()->getLastTransId());
$invoice->save();
}

//full fulfilment
$response = $this->apiAdapter->execute(
"/v1/order/" . $order->getTwoOrderId() . "/fulfilled" . $langParams
);
foreach ($order->getInvoiceCollection() as $invoice) {
$invoice->pay();
$invoice->setTransactionId($order->getPayment()->getLastTransId());
$invoice->save();
$this->parseResponse($response, $order);
} elseif ($this->configRepository->getFulfillTrigger() == 'complete') {
foreach ($order->getInvoiceCollection() as $invoice) {
$invoice->pay();
$invoice->setTransactionId($order->getPayment()->getLastTransId());
$invoice->save();
}

$additionalInformation = $order->getPayment()->getAdditionalInformation();
$additionalInformation['marked_completed'] = true;

$order->getPayment()->setAdditionalInformation($additionalInformation);

$this->addStatusToOrderHistory(
$order,
'Two Order invoice has not been issued yet.',
);
}

$this->parseResponse($response, $order);
}
}

Expand Down
5 changes: 3 additions & 2 deletions Service/Payment/OrderService.php
Original file line number Diff line number Diff line change
Expand Up @@ -295,14 +295,15 @@ public function addOrderComment(Order $order, $message)
public function processOrder(Order $order, string $transactionId)
{
$payment = $order->getPayment();
if ($this->configRepository->getFulfillOrderType() == 'shipment') {
$fulfillTrigger = $this->configRepository->getFulfillTrigger();
if ($fulfillTrigger == 'shipment' || $fulfillTrigger == 'complete') {
$order->setIsInProcess(true);
$order->setState(Order::STATE_PROCESSING);
$order->setStatus(Order::STATE_PROCESSING);
$invoice = $this->invoiceService->prepareInvoice($order);
$invoice->setRequestedCaptureCase(Invoice::CAPTURE_ONLINE);
$invoice->register();
$this->addOrderComment($order, 'Payment has been verified');
$this->addOrderComment($order, 'Two Order payment has been verified');
$transactionSave = $this->transaction
->addObject(
$payment
Expand Down
2 changes: 1 addition & 1 deletion bumpver.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[tool.bumpver]
current_version = "1.3.4"
current_version = "1.3.5"
version_pattern = "MAJOR.MINOR.PATCH[-TAGNUM]"
commit_message = "chore: Bump version {old_version} -> {new_version}"
commit = true
Expand Down
Loading

0 comments on commit 62de2a1

Please sign in to comment.