From 8672c3861505eab574633889bafd0c35d931baac Mon Sep 17 00:00:00 2001 From: Returnless Date: Tue, 10 May 2022 23:38:28 +0300 Subject: [PATCH 1/2] Added Credit Memo functionality. Created Helper. Implemented method searchOrder. Set v1.2.2 --- Api/OrderCreditMemoInterface.php | 18 +++ Controller/Order/Refund.php | 66 ++++++++++ Helper/Data.php | 78 +++++++++++ Model/Api/OrderCreditMemo.php | 218 +++++++++++++++++++++++++++++++ Model/Api/OrderInfo.php | 34 ++--- Model/PartnersSourceAdapter.php | 31 ++--- composer.json | 2 +- etc/module.xml | 2 +- 8 files changed, 405 insertions(+), 44 deletions(-) create mode 100644 Api/OrderCreditMemoInterface.php create mode 100644 Controller/Order/Refund.php create mode 100644 Helper/Data.php create mode 100644 Model/Api/OrderCreditMemo.php diff --git a/Api/OrderCreditMemoInterface.php b/Api/OrderCreditMemoInterface.php new file mode 100644 index 0000000..95f0f32 --- /dev/null +++ b/Api/OrderCreditMemoInterface.php @@ -0,0 +1,18 @@ +orderCreditMemo = $orderCreditMemo; + return parent::__construct( + $config, + $logger, + $resultJsonFactory, + $context + ); + } + + /** + * @return \Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\Result\Json|\Magento\Framework\Controller\ResultInterface + */ + public function execute() + { + $requestData = json_decode($this->getRequest()->getContent(), true); + + // validate if Service is enabled + if ($this->checkEnabled() + && $this->checkSignature($requestData['return_id']) + ) { + $response = $this->orderCreditMemo->createCreditMemo($requestData); + // set Response + $this->setResponse($response['return_message'], $response['code'], false, $response); + } + + $resultJson = $this->resultJsonFactory->create(); + return $resultJson->setData($this->response); + } +} diff --git a/Helper/Data.php b/Helper/Data.php new file mode 100644 index 0000000..83556d8 --- /dev/null +++ b/Helper/Data.php @@ -0,0 +1,78 @@ +orderRepository = $orderRepository; + $this->searchCriteriaBuilder = $searchCriteriaBuilder; + + parent::__construct($context); + } + + /** + * @param $incrementId + * @param string $searchKey + * @return \Magento\Framework\DataObject + */ + public function searchOrder($incrementId, $searchKey = 'increment_id') + { + $searchCriteria = $this->searchCriteriaBuilder + ->addFilter( + $searchKey, + $incrementId, + 'eq' + ) + ->create(); + + return $this->orderRepository->getList($searchCriteria)->getFirstItem(); + } + + /** + * @param $order + * @param $sku + * @return false|mixed + */ + public function getItemBySku($order, $sku) + { + $items = $order->getAllVisibleItems(); + + foreach($items as $item){ + if ($sku == $item->getSku()) { + return $item; + } + } + + return false; + } +} diff --git a/Model/Api/OrderCreditMemo.php b/Model/Api/OrderCreditMemo.php new file mode 100644 index 0000000..7db1cff --- /dev/null +++ b/Model/Api/OrderCreditMemo.php @@ -0,0 +1,218 @@ +creditMemoSender = $creditMemoSender; + $this->creditMemoLoader = $creditMemoLoader; + $this->creditMemoFactory = $creditMemoFactory; + $this->creditMemoService = $creditMemoService; + $this->invoice = $invoice; + $this->retHelper = $retHelper; + $this->websiteCollection = $websiteCollection; + $this->logger = $logger; + $this->moduleResource = $moduleResource; + } + + /** + * @inheritdoc + */ + public function createCreditMemo($requestParams) + { + $response['installed_module_version'] = $this->moduleResource->getDbVersion(self::NAMESPACE_MODULE); + $response['return_message'] = 'Success!'; + $response['code'] = 200; + + $order = $this->retHelper->searchOrder($requestParams['order_id']); + + $orderId = $order->getId(); + if (!$orderId) { + $response['code'] = 404; + $response['return_message'] = __("Order is not found."); + + return $response; + } + + $creditMemoData = []; + $itemToCredit = []; + + $creditMemoData['shipping_amount'] = 0; + $creditMemoData['adjustment_positive'] = 0; + $creditMemoData['adjustment_negative'] = 0; + + $creditMemoData['do_offline'] = 0; + if (isset($requestParams['payment_refund']) + && $requestParams['payment_refund'] == 'on' + ) { + $creditMemoData['do_offline'] = 1; + } + + $creditMemoData['comment_text'] = ''; + if (isset($requestParams['comment_text']) + && !empty($requestParams['comment_text']) + && is_string($requestParams['comment_text']) + ) { + $creditMemoData['comment_text'] = $requestParams['comment_text']; + } + + $creditMemoData['send_email'] = 0; + if (isset($requestParams['email_to_customer']) + && $requestParams['email_to_customer'] == 'on' + ) { + $creditMemoData['send_email'] = 1; + } + + foreach ($requestParams['items'] as $requestItem) { + $item = $this->retHelper->getItemBySku($order, $requestItem['sku']); + $orderItemId = $item->getId(); + + $itemToCredit[$orderItemId] = [ + 'qty' => $requestItem['qty'] + ]; + } + $creditMemoData['items'] = $itemToCredit; + + try { + $this->creditMemoLoader->setOrderId($orderId); //pass order id + $this->creditMemoLoader->setCreditmemo($creditMemoData); + + $creditMemo = $this->creditMemoLoader->load(); + if ($creditMemo) { + if (!$creditMemo->isValidGrandTotal()) { + $response['code'] = 406; + $response['return_message'] = __('The credit memo\'s total must be positive.'); + + return $response; + } + + if (!empty($creditMemoData['comment_text'])) { + $creditMemo->addComment( + $creditMemoData['comment_text'], + isset($creditMemoData['comment_customer_notify']), + isset($creditMemoData['is_visible_on_front']) + ); + + $creditMemo->setCustomerNote($creditMemoData['comment_text']); + $creditMemo->setCustomerNoteNotify(isset($creditMemoData['comment_customer_notify'])); + } + + $creditMemo->getOrder()->setCustomerNoteNotify(!empty($creditMemoData['send_email'])); + $this->creditMemoService->refund($creditMemo, (bool)$creditMemoData['do_offline']); + + if (!empty($creditMemoData['send_email'])) { + $this->creditMemoSender->send($creditMemo); + } + + if ($creditMemo->getEntityId()) { + $entityId = $creditMemo->getEntityId(); + $response['result']['entity_id'] = $entityId; + } + + if ($creditMemo->getSubtotal()) { + $subtotal = $creditMemo->getSubtotal(); + $response['result']['subtotal'] = $subtotal; + } + + if ($creditMemo->getGrandTotal()) { + $grandTotal = $creditMemo->getGrandTotal(); + $response['result']['grand_total'] = $grandTotal; + } + } + } catch (\Exception $exception) { + $response['code'] = 406; + + $this->logger->error($exception->getMessage()); + $response['return_message'] = $exception->getMessage(); + } + + return $response; + } +} diff --git a/Model/Api/OrderInfo.php b/Model/Api/OrderInfo.php index ae70a5c..2cd37dc 100644 --- a/Model/Api/OrderInfo.php +++ b/Model/Api/OrderInfo.php @@ -13,6 +13,7 @@ use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\App\ObjectManager; use Magento\Weee\Helper\Data; +use Returnless\Connector\Helper\Data as RetHelper; /** * Interface OrderInfo @@ -77,6 +78,11 @@ class OrderInfo implements OrderInfoInterface */ protected $weeeHelper; + /** + * @var RetHelper + */ + protected $retHelper; + /** * OrderInfo constructor. * @@ -88,6 +94,7 @@ class OrderInfo implements OrderInfoInterface * @param OrderRepository $orderRepository * @param SearchCriteriaBuilder $searchCriteriaBuilder * @param Data $weeeHelper + * @param RetHelper $retHelper */ public function __construct( ProductRepository $productRepository, @@ -97,9 +104,9 @@ public function __construct( ResourceInterface $moduleResource, OrderRepository $orderRepository, SearchCriteriaBuilder $searchCriteriaBuilder, - Data $weeeHelper - ) - { + Data $weeeHelper, + RetHelper $retHelper + ){ $this->productRepository = $productRepository; $this->logger = $logger; $this->image = $image; @@ -108,6 +115,7 @@ public function __construct( $this->orderRepository = $orderRepository; $this->searchCriteriaBuilder = $searchCriteriaBuilder; $this->weeeHelper = $weeeHelper; + $this->retHelper = $retHelper; } /** @@ -121,7 +129,7 @@ public function getOrderInfoReturnless($incrementId) $this->logger->debug('[RET_ORDER_INFO] Increment Id', [$incrementId]); try { - $order = $this->getOrderByMagento($incrementId); + $order = $this->retHelper->searchOrder($incrementId); if (!$order->getId() && $this->config->getMarketplaceSearchEnabled()) { /** @var \Returnless\Connector\Model\PartnersSourceAdapter $partnersSourceAdapter */ $partnersSourceAdapter = ObjectManager::getInstance()->get('Returnless\Connector\Model\PartnersSourceAdapter'); @@ -278,24 +286,6 @@ public function getOrderInfoReturnless($incrementId) $this->returnResult($response); } - /** - * @param $incrementId - * @param string $searchKey - * @return \Magento\Framework\DataObject - */ - private function getOrderByMagento($incrementId, $searchKey = 'increment_id') - { - $searchCriteria = $this->searchCriteriaBuilder - ->addFilter( - $searchKey, - $incrementId, - 'eq' - ) - ->create(); - - return $this->orderRepository->getList($searchCriteria)->getFirstItem(); - } - /** * This method provides an ability to return Response Data * diff --git a/Model/PartnersSourceAdapter.php b/Model/PartnersSourceAdapter.php index fad970c..ef6503a 100644 --- a/Model/PartnersSourceAdapter.php +++ b/Model/PartnersSourceAdapter.php @@ -6,6 +6,7 @@ use Magento\Framework\Api\SearchCriteriaBuilder;; use Returnless\Connector\Model\Config; use Psr\Log\LoggerInterface as Logger; +use Returnless\Connector\Helper\Data as RetHelper; /** * Class PartnersSourceAdapter @@ -39,11 +40,17 @@ class PartnersSourceAdapter */ private $logger; + /** + * @var RetHelper + */ + protected $retHelper; + /** * PartnersSourceAdapter constructor. * @param OrderRepository $orderRepository * @param SearchCriteriaBuilder $searchCriteriaBuilder * @param \Returnless\Connector\Model\Config $config + * @param RetHelper $retHelper * @param array $partnersResource */ public function __construct( @@ -51,6 +58,7 @@ public function __construct( SearchCriteriaBuilder $searchCriteriaBuilder, Config $config, Logger $logger, + RetHelper $retHelper, $partnersResource = [] ) { $this->config = $config; @@ -58,6 +66,7 @@ public function __construct( $this->orderRepository = $orderRepository; $this->searchCriteriaBuilder = $searchCriteriaBuilder; $this->partnersResource = $partnersResource; + $this->retHelper = $retHelper; } /** @@ -68,7 +77,7 @@ public function __construct( */ public function getOrderById($orderId) { - $order = $this->getOrderByMagento($orderId); + $order = $this->retHelper->searchOrder($orderId); if (!$order->getId() && $this->config->getMarketplaceSearchEnabled()) { try { $order = $this->getOrderByMarketplace($orderId); @@ -94,29 +103,11 @@ public function getOrderByMarketplace($orderId) ) ->addFieldToSelect('order_id') ->getFirstItem(); - $order = $this->getOrderByMagento($partnerOrder->getOrderId(), 'increment_id'); + $order = $this->retHelper->searchOrder($partnerOrder->getOrderId()); return $order; } - /** - * @param $incrementId - * @param string $searchKey - * @return \Magento\Framework\DataObject - */ - private function getOrderByMagento($incrementId, $searchKey = 'increment_id') - { - $searchCriteria = $this->searchCriteriaBuilder - ->addFilter( - $searchKey, - $incrementId, - 'eq' - ) - ->create(); - - return $this->orderRepository->getList($searchCriteria)->getFirstItem(); - } - /** * @param $partnerId * @return false|mixed diff --git a/composer.json b/composer.json index 48adc7e..7aeb735 100644 --- a/composer.json +++ b/composer.json @@ -17,5 +17,5 @@ "OSL-3.0", "AFL-3.0" ], - "version": "1.2.1" + "version": "1.2.2" } diff --git a/etc/module.xml b/etc/module.xml index b0e84e1..4e28360 100644 --- a/etc/module.xml +++ b/etc/module.xml @@ -1,6 +1,6 @@ - + From 3384bcb2317754d88d9641ef7a714b06638410e7 Mon Sep 17 00:00:00 2001 From: Returnless Date: Wed, 22 Jun 2022 01:12:07 +0300 Subject: [PATCH 2/2] Added fields: di_shipping_costs, di_shipping_costs_vat. Added validating Invoices, Items. Implemented: shipping_amount, adjustment_positive, adjustment_negative. --- Model/Api/OrderCreditMemo.php | 34 +++++++++++++++++++++++++++++++++- Model/Api/OrderInfo.php | 3 +++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/Model/Api/OrderCreditMemo.php b/Model/Api/OrderCreditMemo.php index 7db1cff..34f38cb 100644 --- a/Model/Api/OrderCreditMemo.php +++ b/Model/Api/OrderCreditMemo.php @@ -113,6 +113,13 @@ public function createCreditMemo($requestParams) $order = $this->retHelper->searchOrder($requestParams['order_id']); + if (!$order->hasInvoices()) { + $response['code'] = 404; + $response['return_message'] = __("Order is not invoiced."); + + return $response; + } + $orderId = $order->getId(); if (!$orderId) { $response['code'] = 404; @@ -125,8 +132,25 @@ public function createCreditMemo($requestParams) $itemToCredit = []; $creditMemoData['shipping_amount'] = 0; + if (isset($requestParams['shipping_amount']) + && !empty($requestParams['shipping_amount']) + ) { + $creditMemoData['shipping_amount'] = (float) $requestParams['shipping_amount']; + } + $creditMemoData['adjustment_positive'] = 0; + if (isset($requestParams['adjustment_positive']) + && !empty($requestParams['adjustment_positive']) + ) { + $creditMemoData['adjustment_positive'] = (float) $requestParams['adjustment_positive']; + } + $creditMemoData['adjustment_negative'] = 0; + if (isset($requestParams['adjustment_negative']) + && !empty($requestParams['adjustment_negative']) + ) { + $creditMemoData['adjustment_negative'] = (float) $requestParams['adjustment_negative']; + } $creditMemoData['do_offline'] = 0; if (isset($requestParams['payment_refund']) @@ -152,10 +176,18 @@ public function createCreditMemo($requestParams) foreach ($requestParams['items'] as $requestItem) { $item = $this->retHelper->getItemBySku($order, $requestItem['sku']); + + if (!$item) { + $response['code'] = 404; + $response['return_message'] = __("Sku is not associated to Order."); + + return $response; + } + $orderItemId = $item->getId(); $itemToCredit[$orderItemId] = [ - 'qty' => $requestItem['qty'] + 'qty' => (float) $requestItem['qty'] ]; } $creditMemoData['items'] = $itemToCredit; diff --git a/Model/Api/OrderInfo.php b/Model/Api/OrderInfo.php index 2cd37dc..1b6fd57 100644 --- a/Model/Api/OrderInfo.php +++ b/Model/Api/OrderInfo.php @@ -182,6 +182,9 @@ public function getOrderInfoReturnless($incrementId) $orderInfo['customer']['phone'] = $shippingAddress->getTelephone(); } + $orderInfo['di_shipping_costs'] = $order->getShippingAmount(); + $orderInfo['di_shipping_costs_vat'] = $order->getShippingTaxAmount(); + $separateBundle = $this->config->getSeparateBundle(); $orderItems = $separateBundle ? $order->getAllItems() : $order->getAllVisibleItems();