From 9f7e19fcba1ab17e23199b909806b53cf4b193cd Mon Sep 17 00:00:00 2001 From: Marvin-Magmodules Date: Tue, 8 Mar 2022 20:54:59 +0100 Subject: [PATCH 1/4] Transfer transaction fee from quote to order #146 --- Block/Adminhtml/Order/Totals.php | 54 +++++++++----------------------- Service/Order/Import.php | 2 ++ etc/db_schema.xml | 8 +++++ 3 files changed, 24 insertions(+), 40 deletions(-) diff --git a/Block/Adminhtml/Order/Totals.php b/Block/Adminhtml/Order/Totals.php index ee90cc5..fa841d2 100755 --- a/Block/Adminhtml/Order/Totals.php +++ b/Block/Adminhtml/Order/Totals.php @@ -8,63 +8,37 @@ namespace Magmodules\Channable\Block\Adminhtml\Order; use Magento\Framework\Exception\NoSuchEntityException; -use Magento\Framework\Registry; -use Magento\Framework\View\Element\Template\Context; -use Magento\Quote\Api\CartRepositoryInterface; use Magento\Sales\Block\Adminhtml\Order\Totals as MagentoTotals; -use Magento\Sales\Helper\Admin; /** * Class to add Marketplace Transaction Fee */ class Totals extends MagentoTotals { - /** - * @var CartRepositoryInterface - */ - private $quote; - - /** - * @param Context $context - * @param Registry $registry - * @param Admin $adminHelper - * @param CartRepositoryInterface $cartRepositoryInterface - * @param array $data - */ - public function __construct( - Context $context, - Registry $registry, - Admin $adminHelper, - CartRepositoryInterface $cartRepositoryInterface, - array $data = [] - ) { - $this->quote = $cartRepositoryInterface; - parent::__construct($context, $registry, $adminHelper, $data); - } /** - * Initialize all order totals relates with tax + * Add Marketplace Transaction Fee to totals * * @return Totals * @throws NoSuchEntityException */ public function initTotals() { - $quoteId = $this->getOrder()->getQuoteId(); - $quote = $this->quote->get($quoteId); $parent = $this->getParentBlock(); - $this->_order = $parent->getOrder(); - if ($quote->getTransactionFee() > 0) { - $fee = new \Magento\Framework\DataObject( - [ - 'code' => 'transaction_fee', - 'strong' => false, - 'value' => $quote->getTransactionFee(), - 'label' => __('Marketplace Transaction Fee'), - ] - ); + $order = $parent->getOrder(); - $parent->addTotal($fee, 'transaction_fee'); + if ($order->getTransactionFee() != 0) { + $parent->addTotal( + new \Magento\Framework\DataObject( + [ + 'code' => 'transaction_fee', + 'strong' => false, + 'value' => $order->getTransactionFee(), + 'label' => __('Marketplace Transaction Fee'), + ] + ), + 'transaction_fee' + ); } return $this; diff --git a/Service/Order/Import.php b/Service/Order/Import.php index cd9ae0c..827459a 100755 --- a/Service/Order/Import.php +++ b/Service/Order/Import.php @@ -232,6 +232,8 @@ public function execute(ChannableOrderData $orderData): OrderInterface } $orderId = $this->quoteManagement->placeOrder($quote->getId()); $order = $this->orderRepository->get($orderId); + $order->setTransactionFee($quote->getTransactionFee()); + if (isset($orderData['price']['discount']) && $orderData['price']['discount']) { $order->setDiscountDescription(__('Channable discount')); $order->setBaseDiscountAmount($orderData['price']['discount']); diff --git a/etc/db_schema.xml b/etc/db_schema.xml index 727f13d..8f5ed6b 100755 --- a/etc/db_schema.xml +++ b/etc/db_schema.xml @@ -335,6 +335,14 @@ comment="Transaction Fee"/> + + +
+ Date: Tue, 8 Mar 2022 20:55:38 +0100 Subject: [PATCH 2/4] Fixed order simulation product --- Model/Generate.php | 6 +++--- Service/Order/Validator/Data.php | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Model/Generate.php b/Model/Generate.php index 5c2773b..6230bf0 100644 --- a/Model/Generate.php +++ b/Model/Generate.php @@ -105,7 +105,7 @@ public function generateByStore($storeId, $page, $productIds = [], $type = 'feed $size = $this->productModel->getCollectionCountWithFilters($productCollection); - if (($config['filters']['limit'] > 0) && empty($productId)) { + if (($config['filters']['limit'] > 0) && empty($productIds)) { $productCollection->setPage($page, $config['filters']['limit'])->getCurPage(); $pages = ceil($size / $config['filters']['limit']); } @@ -141,7 +141,7 @@ public function generateByStore($storeId, $page, $productIds = [], $type = 'feed } $return = []; - if (empty($productId)) { + if (empty($productIds)) { $limit = $config['filters']['limit']; $return['config'] = $this->feedHelper->getFeedSummary($timeStart, $size, $limit, count($feed), $page, $pages); $return['products'] = $feed; @@ -174,7 +174,7 @@ public function getSize($storeId) { try { $this->appEmulation->startEnvironmentEmulation($storeId, Area::AREA_FRONTEND, true); - $config = $this->sourceHelper->getConfig($storeId, 'szie'); + $config = $this->sourceHelper->getConfig($storeId, 'size'); $productCollection = $this->productModel->getCollection($config, 1, []); $size = $this->productModel->getCollectionCountWithFilters($productCollection); $this->appEmulation->stopEnvironmentEmulation(); diff --git a/Service/Order/Validator/Data.php b/Service/Order/Validator/Data.php index a9e2dd0..f71640c 100755 --- a/Service/Order/Validator/Data.php +++ b/Service/Order/Validator/Data.php @@ -132,7 +132,7 @@ public function validateOrderData($orderData, $request) if ($test) { if (!isset($request['product_id'])) { - return $this->jsonResponse('Post data empty!'); + $request['product_id'] = $test; } if (!isset($request['country'])) { $request['country'] = 'NL'; From 5397511ef4b54d16e60c2208dbc697a2758e3187 Mon Sep 17 00:00:00 2001 From: Marvin-Magmodules Date: Tue, 8 Mar 2022 21:11:46 +0100 Subject: [PATCH 3/4] Feature: add option to use return labels for Channable --- Api/Config/System/OrderInterface.php | 19 ++++ .../Config/Form/Field/Renderer/Carriers.php | 90 +++++++++++++++++++ .../System/Config/Form/Field/ReturnLabel.php | 77 ++++++++++++++++ .../Config/Backend/Serialized/ReturnLabel.php | 32 +++++++ Model/Config/Source/ReturnLabel.php | 42 +++++++++ Model/Config/System/OrderRepository.php | 16 ++++ Service/Order/Shipping/Fulfillment.php | 88 ++++++++++++++++++ Service/Webhook/OrderStatus.php | 37 ++++---- Service/Webhook/Shipments.php | 28 +++--- etc/adminhtml/system/order.xml | 34 ++++++- 10 files changed, 428 insertions(+), 35 deletions(-) mode change 100644 => 100755 Api/Config/System/OrderInterface.php create mode 100644 Block/Adminhtml/System/Config/Form/Field/Renderer/Carriers.php create mode 100644 Block/Adminhtml/System/Config/Form/Field/ReturnLabel.php create mode 100644 Model/Config/Backend/Serialized/ReturnLabel.php create mode 100755 Model/Config/Source/ReturnLabel.php mode change 100644 => 100755 Model/Config/System/OrderRepository.php create mode 100644 Service/Order/Shipping/Fulfillment.php diff --git a/Api/Config/System/OrderInterface.php b/Api/Config/System/OrderInterface.php old mode 100644 new mode 100755 index a2707cc..b45d9ac --- a/Api/Config/System/OrderInterface.php +++ b/Api/Config/System/OrderInterface.php @@ -22,6 +22,8 @@ interface OrderInterface const XML_PATH_SHIPPING_METHOD = 'magmodules_channable_marketplace/order/shipping_method'; const XML_PATH_SHIPPING_CUSTOM = 'magmodules_channable_marketplace/order/shipping_method_custom'; const XML_PATH_SHIPPING_METHOD_FALLBACK = 'magmodules_channable_marketplace/order/shipping_method_fallback'; + const XML_PATH_RETURN_LABEL = 'magmodules_channable_marketplace/order/return_label'; + const XML_PATH_RETURN_LABEL_REGEXP = 'magmodules_channable_marketplace/order/return_label_regexp'; const XML_PATH_IMPORT_CUSTOMER = 'magmodules_channable_marketplace/order/import_customer'; const XML_PATH_CUSTOMER_GROUP_ID = 'magmodules_channable_marketplace/order/customers_group'; const XML_PATH_SEPERATE_HOUSENUMBER = 'magmodules_channable_marketplace/order/seperate_housenumber'; @@ -289,6 +291,23 @@ public function getStatusUrl(int $storeId): string; */ public function getCarrierTitle(int $storeId = null): string; + /** + * Returns labels option + * Options: \Magmodules\Channable\Model\Config\Source\ReturnLabel + * + * @param null|int $storeId + * @return null|string + */ + public function useReturnLabel(int $storeId = null): ?string; + + /** + * Retruns array of carrier_code and regex to determine is label is return label + * + * @param null|int $storeId + * @return array + */ + public function getReturnLabelRegexp(int $storeId = null): array; + /** * @param null|int $storeId * @return string diff --git a/Block/Adminhtml/System/Config/Form/Field/Renderer/Carriers.php b/Block/Adminhtml/System/Config/Form/Field/Renderer/Carriers.php new file mode 100644 index 0000000..eea050c --- /dev/null +++ b/Block/Adminhtml/System/Config/Form/Field/Renderer/Carriers.php @@ -0,0 +1,90 @@ + 'all' , 'label' => 'All'] + ]; + /** + * @var Config + */ + private $shippingConfig; + + /** + * Countries constructor. + * + * @param Context $context + * @param Config $shippingConfig + * @param array $data + */ + public function __construct( + Context $context, + Config $shippingConfig, + array $data = [] + ) { + parent::__construct($context, $data); + $this->shippingConfig = $shippingConfig; + } + + /** + * Render block HTML + * + * @return string + */ + public function _toHtml() + { + if (!$this->getOptions()) { + foreach ($this->getCarriersSource() as $carriers) { + $this->addOption($carriers['value'], $carriers['label']); + } + } + + return parent::_toHtml(); + } + + /** + * Get all countries + * + * @return array + */ + private function getCarriersSource() + { + if (!$this->carriers) { + foreach ($this->shippingConfig->getAllCarriers() as $carrier) { + $this->carriers[] = [ + 'value' => $carrier->getCarrierCode(), + 'label' => $carrier->getCarrierCode() + ]; + } + } + + return $this->carriers; + } + + /** + * Sets name for input element + * + * @param $value + * + * @return mixed + */ + public function setInputName($value) + { + return $this->setName($value); + } +} diff --git a/Block/Adminhtml/System/Config/Form/Field/ReturnLabel.php b/Block/Adminhtml/System/Config/Form/Field/ReturnLabel.php new file mode 100644 index 0000000..9bee95a --- /dev/null +++ b/Block/Adminhtml/System/Config/Form/Field/ReturnLabel.php @@ -0,0 +1,77 @@ +addColumn('carrier_code', [ + 'label' => __('Carrier Code'), + 'renderer' => $this->getCarrierRenderer() + ]); + $this->addColumn('title_regexp', [ + 'label' => __('Title should contain'), + ]); + $this->_addAfter = false; + $this->_addButtonLabel = __('Add'); + } + + /** + * Returns render of stores + * + * @return BlockInterface + */ + public function getCarrierRenderer() + { + if (!$this->carriersRenderer) { + try { + $this->carriersRenderer = $this->getLayout()->createBlock( + Renderer\Carriers::class, + '', + ['data' => ['is_render_to_js_template' => true]] + ); + } catch (\Exception $e) { + $this->carriersRenderer = []; + } + } + + return $this->carriersRenderer; + } + + /** + * Prepare existing row data object + * + * @param DataObject $row + */ + public function _prepareArrayRow(DataObject $row) + { + $attribute = $row->getData('carrier_code'); + $options = []; + if ($attribute) { + $options['option_' . $this->getCarrierRenderer()->calcOptionHash($attribute)] = 'selected="selected"'; + } + $row->setData('option_extra_attrs', $options); + } +} diff --git a/Model/Config/Backend/Serialized/ReturnLabel.php b/Model/Config/Backend/Serialized/ReturnLabel.php new file mode 100644 index 0000000..2734eec --- /dev/null +++ b/Model/Config/Backend/Serialized/ReturnLabel.php @@ -0,0 +1,32 @@ +getValue(); + if (is_array($data)) { + foreach ($data as $key => $row) { + if (empty($row['carrier_code'])) { + unset($data[$key]); + continue; + } + } + } + $this->setValue($data); + return parent::beforeSave(); + } +} diff --git a/Model/Config/Source/ReturnLabel.php b/Model/Config/Source/ReturnLabel.php new file mode 100755 index 0000000..d9f195a --- /dev/null +++ b/Model/Config/Source/ReturnLabel.php @@ -0,0 +1,42 @@ + 'No', + 'regex' => 'Yes, use regex', + ]; + + /** + * Options array + * + * @var array + */ + public $options = null; + + /** + * @return array + */ + public function toOptionArray(): array + { + if (!$this->options) { + foreach (self::OPTIONS as $key => $option) { + $this->options[] = ['value' => $key, 'label' => __($option)]; + } + } + return $this->options; + } +} diff --git a/Model/Config/System/OrderRepository.php b/Model/Config/System/OrderRepository.php old mode 100644 new mode 100755 index fd4e39a..63bc6fa --- a/Model/Config/System/OrderRepository.php +++ b/Model/Config/System/OrderRepository.php @@ -277,4 +277,20 @@ public function getDefaultManageStock($storeId = null): bool { return $this->isSetFlag(CatalogInventoryConfiguration::XML_PATH_MANAGE_STOCK, $storeId); } + + /** + * @inheritDoc + */ + public function useReturnLabel(int $storeId = null): ?string + { + return $this->getStoreValue(self::XML_PATH_RETURN_LABEL, $storeId); + } + + /** + * @inheritDoc + */ + public function getReturnLabelRegexp(int $storeId = null): array + { + return $this->getStoreValueArray(self::XML_PATH_RETURN_LABEL_REGEXP, $storeId); + } } diff --git a/Service/Order/Shipping/Fulfillment.php b/Service/Order/Shipping/Fulfillment.php new file mode 100644 index 0000000..2894d62 --- /dev/null +++ b/Service/Order/Shipping/Fulfillment.php @@ -0,0 +1,88 @@ +configProvider = $configProvider; + } + + /** + * Returns fulfillment data for shipment. + * See; https://docs.channable.com/api/v1/#shipment-update + * + * @param Shipment $shipment + * + * @return array + */ + public function execute(Shipment $shipment): array + { + $fulfillment = []; + $storeId = (int)$shipment->getStoreId(); + + foreach ($shipment->getAllTracks() as $track) { + if ($this->isReturnLabel($track, $storeId)) { + $fulfillment['return_tracking_code'][] = $track->getNumber(); + $fulfillment['return_transporter'][] = $track->getCarrierCode(); + } else { + $fulfillment['tracking_code'][] = $track->getNumber(); + $fulfillment['title'][] = $track->getTitle(); + $fulfillment['carrier_code'][] = $track->getCarrierCode(); + } + } + + return $fulfillment; + } + + /** + * Check if tracking entry should be used as a return tracking label + * + * @param ShipmentTrackInterface $track + * @param int $storeId + * + * @return bool + */ + public function isReturnLabel(ShipmentTrackInterface $track, int $storeId): bool + { + switch ($this->configProvider->useReturnLabel($storeId)) { + case 'regex': + foreach ($this->configProvider->getReturnLabelRegexp($storeId) as $conditions) { + if ($conditions['carrier_code'] != $track->getCarrierCode() + && $conditions['carrier_code'] != 'all' + ) { + return false; + } + if (strpos($track->getTitle(), $conditions['title_regexp']) !== false) { + return true; + } + } + break; + } + + return false; + } +} diff --git a/Service/Webhook/OrderStatus.php b/Service/Webhook/OrderStatus.php index b365fff..32c46ea 100644 --- a/Service/Webhook/OrderStatus.php +++ b/Service/Webhook/OrderStatus.php @@ -11,6 +11,7 @@ use Magento\Sales\Api\Data\OrderInterface; use Magento\Sales\Api\OrderRepositoryInterface; use Magmodules\Channable\Model\Payment\Channable; +use Magmodules\Channable\Service\Order\Shipping\Fulfillment; class OrderStatus { @@ -26,6 +27,10 @@ class OrderStatus * @var SearchCriteriaBuilder */ private $searchCriteriaBuilder; + /** + * @var Fulfillment + */ + private $fulfillment; /** * @param SearchCriteriaBuilder $searchCriteriaBuilder @@ -33,10 +38,12 @@ class OrderStatus */ public function __construct( SearchCriteriaBuilder $searchCriteriaBuilder, - OrderRepositoryInterface $orderRepository + OrderRepositoryInterface $orderRepository, + Fulfillment $fulfillment ) { $this->searchCriteriaBuilder = $searchCriteriaBuilder; $this->orderRepository = $orderRepository; + $this->fulfillment = $fulfillment; } /** @@ -71,14 +78,11 @@ public function execute(string $incrementId): array 'id' => $order->getIncrementId(), 'status' => $order->getStatus() ]; - if (!$tracking = $this->getTracking($order)) { - return $response; - } - foreach ($tracking as $track) { - $response['fulfillment']['tracking_code'][] = $track['tracking']; - $response['fulfillment']['title'][] = $track['title']; - $response['fulfillment']['carrier_code'][] = $track['carrier_code']; + + if (!$fulfillments = $this->getFulfillment($order)) { + $response['fulfillment'] = $fulfillments; } + return $response; } @@ -87,21 +91,16 @@ public function execute(string $incrementId): array * * @return array|bool */ - private function getTracking(OrderInterface $order) + private function getFulfillment(OrderInterface $order) { - $tracking = []; + $fulfillment = []; $shipmentCollection = $order->getShipmentsCollection(); foreach ($shipmentCollection as $shipment) { - foreach ($shipment->getAllTracks() as $tracknum) { - $tracking[] = [ - 'tracking' => $tracknum->getNumber(), - 'title' => $tracknum->getTitle(), - 'carrier_code' => $tracknum->getCarrierCode() - ]; - } + $fulfillment += $this->fulfillment->execute($shipment); } - return (!empty($tracking)) - ? ($tracking) + + return (!empty($fulfillment)) + ? ($fulfillment) : (false); } } diff --git a/Service/Webhook/Shipments.php b/Service/Webhook/Shipments.php index 94c1878..0c7e086 100644 --- a/Service/Webhook/Shipments.php +++ b/Service/Webhook/Shipments.php @@ -12,6 +12,7 @@ use Magento\Sales\Model\Order as OrderModel; use Magento\Sales\Model\ResourceModel\Order\CollectionFactory as OrderCollectionFactory; use Magento\Sales\Model\ResourceModel\Order\Shipment\CollectionFactory as ShipmentCollectionFactory; +use Magmodules\Channable\Service\Order\Shipping\Fulfillment; class Shipments { @@ -36,6 +37,11 @@ class Shipments */ private $orderCollectionFactory; + /** + * @var Fulfillment + */ + private $fulfillment; + /** * @param ShipmentCollectionFactory $shipmentCollectionFactory * @param DateTime $coreDate @@ -46,12 +52,14 @@ public function __construct( ShipmentCollectionFactory $shipmentCollectionFactory, DateTime $coreDate, TimezoneInterface $localeDate, - OrderCollectionFactory $orderCollectionFactory + OrderCollectionFactory $orderCollectionFactory, + Fulfillment $fulfillment ) { $this->shipmentCollectionFactory = $shipmentCollectionFactory; $this->coreDate = $coreDate; $this->localeDate = $localeDate; $this->orderCollectionFactory = $orderCollectionFactory; + $this->fulfillment = $fulfillment; } /** @@ -81,17 +89,13 @@ public function execute(int $timespan): array )->addFieldToFilter('sop.method', 'channable'); foreach ($collection as $shipment) { - $data['id'] = $shipment->getOrderIncrementId(); - $data['type'] = 'shipment'; - $data['status'] = $shipment->getStatus(); - $data['date'] = $this->localeDate->date($shipment->getCreatedAt())->format('Y-m-d H:i:s'); - foreach ($shipment->getAllTracks() as $tracknum) { - $data['fulfillment']['tracking_code'][] = $tracknum->getNumber(); - $data['fulfillment']['title'][] = $tracknum->getTitle(); - $data['fulfillment']['carrier_code'][] = $tracknum->getCarrierCode(); - } - - $response[] = $data; + $response[] = [ + 'id' => $shipment->getOrderIncrementId(), + 'type'=> 'shipment', + 'status' => $shipment->getStatus(), + 'date' => $this->localeDate->date($shipment->getCreatedAt())->format('Y-m-d H:i:s'), + 'fulfillment' => $this->fulfillment->execute($shipment) + ]; $orderIncrements[] = $shipment->getOrderIncrementId(); unset($data); } diff --git a/etc/adminhtml/system/order.xml b/etc/adminhtml/system/order.xml index 32bd532..1d072a0 100755 --- a/etc/adminhtml/system/order.xml +++ b/etc/adminhtml/system/order.xml @@ -226,20 +226,46 @@ 1 - + + Magmodules\Channable\Block\Adminhtml\Magmodules\Heading + Enable this option if you are using the default Magento Track and Trace method within a + shipment to enter your returns so Channable can get this information and share this with the + Marketplaces. + + + + + Magmodules\Channable\Model\Config\Source\ReturnLabel + magmodules_channable_marketplace/order/return_label + + + + Magmodules\Channable\Block\Adminhtml\System\Config\Form\Field\ReturnLabel + Magmodules\Channable\Model\Config\Backend\Serialized\ReturnLabel + magmodules_channable_marketplace/order/return_label_regexp + + regex + + + Magmodules\Channable\Block\Adminhtml\Magmodules\Heading Enable the Order Logging option to log all the incoming orders from the connected Marketplaces. - Magento\Config\Model\Config\Source\Yesno magmodules_channable_marketplace/order/log - Magmodules\Channable\Block\Adminhtml\Magmodules\Heading @@ -248,7 +274,7 @@ because of the length.

You can simulate a test order by adding /test/{productID} to the end of the Webhook.]]>
-