Skip to content
This repository was archived by the owner on Aug 2, 2022. It is now read-only.

Commit 7b2f27e

Browse files
author
Willian Keller
committed
[#4] Implement split order by product attribute
Add custom attribute to select Capability to use multiselect Improve split method Split order by custom attribute Improve get ptoduct attribute Add release 1.0.2 Add release 1.0.2 Improve settings descriptions Enable capability to split shipping Add release 1.0.2 Add release 1.0.2
1 parent 3fdee75 commit 7b2f27e

File tree

8 files changed

+217
-42
lines changed

8 files changed

+217
-42
lines changed

Api/QuoteHandlerInterface.php

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,11 @@ interface QuoteHandlerInterface
2323
public function normalizeQuotes($quote);
2424

2525
/**
26-
* Check if quotes should be split.
27-
*
28-
* @param object $quotes
29-
* @return bool
26+
* @param object $product
27+
* @param string $attributes
28+
* @return string
3029
*/
31-
public function isSplittable($quotes);
30+
public function getProductAttributes($product, $attributes);
3231

3332
/**
3433
* Collect list of data addresses.
@@ -48,25 +47,33 @@ public function setCustomerData($quote, $split);
4847
/**
4948
* Populate quotes with new data.
5049
*
50+
* @param object $quotes
5151
* @param object $split
5252
* @param object $item
5353
* @param array $addresses
54-
* @param string $paymentMethod
54+
* @param string $payment
5555
* @return $this
5656
*/
57-
public function populateQuote($split, $item, $addresses, $paymentMethod);
57+
public function populateQuote($quotes, $split, $item, $addresses, $payment);
5858

5959
/**
6060
* Recollect order totals.
6161
*
62+
* @param object $quotes
6263
* @param object $item
6364
* @param object $quote
6465
* @param array $addresses
65-
* @param float $shippingAmount
6666
* @return $this
6767
*/
68-
public function recollectTotal($item, $quote, $addresses, $shippingAmount = 0);
68+
public function recollectTotal($quotes, $item, $quote, $addresses);
6969

70+
/**
71+
* @param object $quotes
72+
* @param object $quote
73+
* @param float $total
74+
*/
75+
public function shippingAmount($quotes, $quote, $total = 0);
76+
7077
/**
7178
* Set payment method.
7279
*

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,20 @@
11
# Changelog
22
All notable changes to this project will be documented in this file.
33

4+
## [1.0.2] - 2018-08-21
5+
### Added
6+
- Option to select a product attribute to define order split.
7+
- Capability to split shipping totals into all orders or only one.
8+
9+
### Fixed
10+
- Split shipping totals into all orders or only one.
11+
- Set shipping to one order only.
12+
13+
### Changed
14+
- Improved module architecture.
15+
- Stable order submission.
16+
17+
418
## [1.0.1] - 2018-07-20
519
### Added
620
- CMS module settings (Enable/Disable)

Helper/Data.php

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
namespace Magestat\SplitOrder\Helper;
1414

15+
use Magento\Store\Model\ScopeInterface;
16+
1517
class Data extends \Magento\Framework\App\Helper\AbstractHelper
1618
{
1719
/**
@@ -28,6 +30,34 @@ public function isActive($storeId = null)
2830
);
2931
}
3032

33+
/**
34+
* Get attributes to split.
35+
*
36+
* @param null $storeId
37+
* @return array
38+
*/
39+
public function getAttributes($storeId = null)
40+
{
41+
return $this->getConfig(
42+
'magestat_split_order/options/attributes',
43+
$storeId
44+
);
45+
}
46+
47+
/**
48+
* Check if should split delivery.
49+
*
50+
* @param null $storeId
51+
* @return bool
52+
*/
53+
public function getShippingSplit($storeId = null)
54+
{
55+
return (bool) $this->getConfig(
56+
'magestat_split_order/options/shipping',
57+
$storeId
58+
);
59+
}
60+
3161
/**
3262
* Return store configuration value.
3363
*
@@ -39,7 +69,7 @@ public function getConfig($path, $storeId = null)
3969
{
4070
return $this->scopeConfig->getValue(
4171
$path,
42-
\Magento\Store\Model\ScopeInterface::SCOPE_STORE,
72+
ScopeInterface::SCOPE_STORE,
4373
$storeId
4474
);
4575
}

Model/Config/Source/Attributes.php

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<?php
2+
3+
/**
4+
* A Magento 2 module named Magestat/SplitOrder
5+
* Copyright (C) 2018 Magestat
6+
*
7+
* This file included in Magestat/SplitOrder is licensed under OSL 3.0
8+
*
9+
* http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
10+
* Please see LICENSE.txt for the full text of the OSL 3.0 license
11+
*/
12+
13+
namespace Magestat\SplitOrder\Model\Config\Source;
14+
15+
use Magento\Framework\Option\ArrayInterface;
16+
use Magento\Catalog\Model\ResourceModel\Product\Attribute\CollectionFactory;
17+
18+
class Attributes implements ArrayInterface
19+
{
20+
/**
21+
* @var array
22+
*/
23+
protected $options;
24+
25+
/**
26+
* @var \Magento\Catalog\Model\ResourceModel\Product\Attribute\CollectionFactory
27+
*/
28+
protected $collection;
29+
30+
/**
31+
* @param CollectionFactory $collectionFactory
32+
*/
33+
public function __construct(
34+
CollectionFactory $collectionFactory
35+
) {
36+
$this->collection = $collectionFactory;
37+
}
38+
39+
/**
40+
* Get options as array
41+
*
42+
* @return array
43+
*/
44+
public function toOptionArray($isMultiselect = false)
45+
{
46+
if (!$this->options) {
47+
$collection = $this->collection->create();
48+
49+
foreach ($collection as $items) {
50+
$attributes[] = [
51+
'value' => $items->getAttributeCode(),
52+
'label' => $items->getFrontendLabel()
53+
];
54+
}
55+
$this->options = $attributes;
56+
}
57+
58+
$options = $this->options;
59+
if (!$isMultiselect) {
60+
array_unshift($options, ['value' => '', 'label' => __('--Please Select--')]);
61+
}
62+
return $options;
63+
}
64+
}

Model/QuoteHandler.php

Lines changed: 72 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
namespace Magestat\SplitOrder\Model;
1414

1515
use Magento\Checkout\Model\Session as CheckoutSession;
16+
use Magento\Quote\Api\CartManagementInterface;
17+
use Magento\Customer\Api\Data\GroupInterface;
1618
use Magestat\SplitOrder\Api\QuoteHandlerInterface;
1719
use Magestat\SplitOrder\Helper\Data as HelperData;
1820

@@ -45,23 +47,44 @@ public function __construct(
4547
*/
4648
public function normalizeQuotes($quote)
4749
{
50+
// if module is active.
51+
if (!$this->helperData->isActive()) {
52+
return false;
53+
}
54+
$attributes = $this->helperData->getAttributes();
55+
if (empty($attributes)) {
56+
return false;
57+
}
58+
4859
$groups = [];
4960
foreach ($quote->getAllVisibleItems() as $item) {
50-
$groups[$item->getProduct()->getSku()][] = $item;
61+
$product = $item->getProduct();
62+
63+
$attribute = $this->getProductAttributes($product, $attributes);
64+
if (empty($attribute)) {
65+
// Kill function if attribute is null.
66+
return false;
67+
}
68+
$groups[$attribute][] = $item;
5169
}
52-
return $groups;
70+
// If order have more than one item.
71+
if (count($groups) > 1) {
72+
return $groups;
73+
}
74+
return false;
5375
}
5476

5577
/**
5678
* {@inheritdoc}
5779
*/
58-
public function isSplittable($quotes)
80+
public function getProductAttributes($product, $attributes)
5981
{
60-
// If module is active and order have more than one item.
61-
if ($this->helperData->isActive() && count($quotes) > 1) {
62-
return true;
63-
}
64-
return false;
82+
$attribute = $product->getResource()
83+
->getAttribute($attributes)
84+
->getFrontend()
85+
->getValue($product);
86+
87+
return $attribute;
6588
}
6689

6790
/**
@@ -93,32 +116,31 @@ public function setCustomerData($quote, $split)
93116
$split->setCustomer($quote->getCustomer());
94117
$split->setCustomerIsGuest($quote->getCustomerIsGuest());
95118

96-
if ($quote->getCheckoutMethod() === \Magento\Quote\Api\CartManagementInterface::METHOD_GUEST) {
119+
if ($quote->getCheckoutMethod() === CartManagementInterface::METHOD_GUEST) {
97120
$split->setCustomerId(null);
98121
$split->setCustomerEmail($quote->getBillingAddress()->getEmail());
99122
$split->setCustomerIsGuest(true);
100-
$split->setCustomerGroupId(\Magento\Customer\Api\Data\GroupInterface::NOT_LOGGED_IN_ID);
123+
$split->setCustomerGroupId(GroupInterface::NOT_LOGGED_IN_ID);
101124
}
102125
return $this;
103126
}
104127

105128
/**
106129
* {@inheritdoc}
107130
*/
108-
public function populateQuote($split, $item, $addresses, $paymentMethod)
131+
public function populateQuote($quotes, $split, $item, $addresses, $payment)
109132
{
110-
$this->recollectTotal($item, $split, $addresses);
111-
133+
$this->recollectTotal($quotes, $item, $split, $addresses);
112134
// Set payment method.
113-
$this->setPaymentMethod($split, $addresses['payment'], $paymentMethod);
135+
$this->setPaymentMethod($split, $addresses['payment'], $payment);
114136

115137
return $this;
116138
}
117139

118140
/**
119141
* {@inheritdoc}
120142
*/
121-
public function recollectTotal($item, $quote, $addresses, $shippingAmount = 0)
143+
public function recollectTotal($quotes, $item, $quote, $addresses)
122144
{
123145
// Retrieve values.
124146
$tax = $item->getData('tax_amount');
@@ -131,14 +153,12 @@ public function recollectTotal($item, $quote, $addresses, $shippingAmount = 0)
131153
$quote->getShippingAddress()->setData($addresses['shipping']);
132154

133155
// Add shipping amount if product is not virual.
134-
if ($quote->hasVirtualItems() === false) {
135-
$shippingAmount = $quote->getShippingAddress()->getShippingAmount();
136-
}
156+
$shipping = $this->shippingAmount($quotes, $quote);
137157

138158
// Recollect totals into the quote.
139159
foreach ($quote->getAllAddresses() as $address) {
140160
// Build grand total.
141-
$grandTotal = (($finalPrice + $shippingAmount + $tax) - $discount);
161+
$grandTotal = (($finalPrice + $shipping + $tax) - $discount);
142162

143163
$address->setBaseSubtotal($finalPrice);
144164
$address->setSubtotal($finalPrice);
@@ -150,7 +170,39 @@ public function recollectTotal($item, $quote, $addresses, $shippingAmount = 0)
150170
}
151171
return $this;
152172
}
153-
173+
174+
/**
175+
* {@inheritdoc}
176+
*/
177+
public function shippingAmount($quotes, $quote, $total = 0)
178+
{
179+
// Add shipping amount if product is not virual.
180+
if ($quote->hasVirtualItems() === true) {
181+
return $total;
182+
}
183+
$shippingTotals = $quote->getShippingAddress()->getShippingAmount();
184+
185+
// If not, set shipping to one order only.
186+
if (!$this->helperData->getShippingSplit()) {
187+
static $process = 1;
188+
189+
if ($process > 1) {
190+
// Set zero price to next orders.
191+
$quote->getShippingAddress()->setShippingAmount($total);
192+
return $total;
193+
}
194+
$process ++;
195+
196+
return $shippingTotals;
197+
}
198+
if ($shippingTotals > 0) {
199+
// Divide shippinto to each order.
200+
$total = (float) ($shippingTotals / count($quotes));
201+
$quote->getShippingAddress()->setShippingAmount($total);
202+
}
203+
return $total;
204+
}
205+
154206
/**
155207
* {@inheritdoc}
156208
*/

Plugin/SplitQuote.php

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -65,21 +65,18 @@ public function __construct(
6565
* @param QuoteManagement $subject
6666
* @param callable $proceed
6767
* @param int $cartId
68-
* @param string $paymentMethod
68+
* @param string $payment
6969
* @return mixed
7070
* @throws LocalizedException
7171
*/
72-
public function aroundPlaceOrder(QuoteManagement $subject, callable $proceed, $cartId, $paymentMethod = null)
72+
public function aroundPlaceOrder(QuoteManagement $subject, callable $proceed, $cartId, $payment = null)
7373
{
7474
$quote = $this->quoteRepository->getActive($cartId);
7575

7676
// Separate all items in quote into new quotes.
77-
$quotes = $this->quoteHandler->normalizeQuotes($quote);
78-
79-
if (!$this->quoteHandler->isSplittable($quotes)) {
80-
return $result = $proceed($cartId, $paymentMethod);
77+
if (($quotes = $this->quoteHandler->normalizeQuotes($quote)) === false) {
78+
return $result = $proceed($cartId, $payment);
8179
}
82-
8380
// Collect list of data addresses.
8481
$addresses = $this->quoteHandler->collectAddressesData($quote);
8582

@@ -99,9 +96,8 @@ public function aroundPlaceOrder(QuoteManagement $subject, callable $proceed, $c
9996
$item->setId(null);
10097
$split->addItem($item);
10198
}
102-
10399
// Recollect order totals.
104-
$this->quoteHandler->populateQuote($split, $item, $addresses, $paymentMethod);
100+
$this->quoteHandler->populateQuote($quotes, $split, $item, $addresses, $payment);
105101

106102
// Dispatch event as Magento standard once per each quote split.
107103
$this->eventManager->dispatch(

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"license": [
1414
"OSL-3.0"
1515
],
16-
"version": "1.0.1",
16+
"version": "1.0.2",
1717
"authors": [
1818
{
1919
"name": "Magestat",

0 commit comments

Comments
 (0)