Skip to content

Commit acab048

Browse files
authored
Merge branch '2.4-develop' into issue-36208
2 parents 54872dd + 65c71f2 commit acab048

File tree

10 files changed

+360
-25
lines changed

10 files changed

+360
-25
lines changed

app/code/Magento/CatalogGraphQl/DataProvider/Product/LayeredNavigation/AttributeOptionProvider.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ public function getOptions(array $optionIds, ?int $storeId, array $attributeCode
110110

111111
if (!empty($attributeCodes)) {
112112
$select->orWhere(
113-
'a.attribute_code in (?) AND a.frontend_input = \'boolean\'',
113+
'a.attribute_code in (?) AND a.frontend_input in (\'boolean\', \'price\')',
114114
$attributeCodes
115115
);
116116
}

app/code/Magento/Customer/Model/Config/Backend/Show/Customer.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
class Customer extends \Magento\Framework\App\Config\Value
1717
{
18+
public const XML_PATH_CUSTOMER_ADDRESS_SHOW_COMPANY = 'customer/address/company_show';
19+
1820
/**
1921
* @var \Magento\Eav\Model\Config
2022
*/

app/code/Magento/OfflineShipping/etc/db_schema.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@
3838
</constraint>
3939
</table>
4040
<table name="salesrule" resource="default" comment="Salesrule">
41-
<column xsi:type="smallint" name="simple_free_shipping" unsigned="true" nullable="false"
42-
identity="false" default="0" comment="Simple Free Shipping"/>
41+
<column xsi:type="smallint" name="simple_free_shipping" unsigned="true" nullable="true"
42+
identity="false" default="null" comment="Simple Free Shipping"/>
4343
</table>
4444
<table name="sales_order_item" resource="sales" comment="Sales Flat Order Item">
4545
<column xsi:type="smallint" name="free_shipping" unsigned="true" nullable="false" identity="false"

app/code/Magento/Quote/Model/ShippingAddressManagement.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
namespace Magento\Quote\Model;
88

9+
use Magento\Customer\Model\Config\Backend\Show\Customer;
910
use Magento\Framework\App\ObjectManager;
1011
use Magento\Framework\Exception\InputException;
1112
use Magento\Framework\Exception\NoSuchEntityException;
@@ -18,15 +19,11 @@
1819
class ShippingAddressManagement implements \Magento\Quote\Model\ShippingAddressManagementInterface
1920
{
2021
/**
21-
* Quote repository.
22-
*
2322
* @var \Magento\Quote\Api\CartRepositoryInterface
2423
*/
2524
protected $quoteRepository;
2625

2726
/**
28-
* Logger.
29-
*
3027
* @var Logger
3128
*/
3229
protected $logger;
@@ -81,6 +78,7 @@ public function __construct(
8178
/**
8279
* @inheritDoc
8380
* @SuppressWarnings(PHPMD.NPathComplexity)
81+
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
8482
*/
8583
public function assign($cartId, \Magento\Quote\Api\Data\AddressInterface $address)
8684
{
@@ -95,6 +93,10 @@ public function assign($cartId, \Magento\Quote\Api\Data\AddressInterface $addres
9593
$saveInAddressBook = $address->getSaveInAddressBook() ? 1 : 0;
9694
$sameAsBilling = $address->getSameAsBilling() ? 1 : 0;
9795
$customerAddressId = $address->getCustomerAddressId();
96+
if ($saveInAddressBook &&
97+
!$this->scopeConfig->getValue(Customer::XML_PATH_CUSTOMER_ADDRESS_SHOW_COMPANY)) {
98+
$address->setCompany(null);
99+
}
98100
$this->addressValidator->validateForCart($quote, $address);
99101
$quote->setShippingAddress($address);
100102
$address = $quote->getShippingAddress();
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Quote\Test\Unit\Model;
9+
10+
use Magento\Customer\Api\AddressRepositoryInterface;
11+
use Magento\Framework\App\Config\ScopeConfigInterface;
12+
use Magento\Framework\Exception\InputException;
13+
use Magento\Framework\Exception\NoSuchEntityException;
14+
use Magento\Quote\Api\CartRepositoryInterface;
15+
use Magento\Quote\Api\Data\AddressInterface;
16+
use Magento\Quote\Model\Quote;
17+
use Magento\Quote\Model\Quote\TotalsCollector;
18+
use Magento\Quote\Model\QuoteAddressValidator;
19+
use Magento\Quote\Model\ShippingAddressManagement;
20+
use PHPUnit\Framework\TestCase;
21+
use Psr\Log\LoggerInterface;
22+
23+
class ShippingAddressManagementTest extends TestCase
24+
{
25+
/**
26+
* @var ShippingAddressManagement
27+
*/
28+
private ShippingAddressManagement $model;
29+
30+
/**
31+
* @var CartRepositoryInterface
32+
*/
33+
private $quoteRepositoryMock;
34+
35+
/**
36+
* @var QuoteAddressValidator
37+
*/
38+
private $addressValidatorMock;
39+
40+
/**
41+
* @var LoggerInterface
42+
*/
43+
private $loggerMock;
44+
45+
/**
46+
* @var AddressRepositoryInterface
47+
*/
48+
private $addressRepositoryMock;
49+
50+
/**
51+
* @var ScopeConfigInterface
52+
*/
53+
private $scopeConfigMock;
54+
55+
/**
56+
* @var TotalsCollector
57+
*/
58+
private $totalsCollectorMock;
59+
60+
/**
61+
* @var Quote
62+
*/
63+
private $quoteMock;
64+
65+
/**
66+
* @inheritdoc
67+
*/
68+
protected function setUp(): void
69+
{
70+
$this->quoteRepositoryMock = $this->createMock(CartRepositoryInterface::class);
71+
$this->addressValidatorMock = $this->createMock(QuoteAddressValidator::class);
72+
$this->loggerMock = $this->createMock(LoggerInterface::class);
73+
$this->addressRepositoryMock = $this->createMock(AddressRepositoryInterface::class);
74+
$this->scopeConfigMock = $this->createMock(ScopeConfigInterface::class);
75+
$this->totalsCollectorMock = $this->createMock(TotalsCollector::class);
76+
$this->quoteMock = $this->createMock(Quote::class);
77+
$this->model = new ShippingAddressManagement(
78+
$this->quoteRepositoryMock,
79+
$this->addressValidatorMock,
80+
$this->loggerMock,
81+
$this->addressRepositoryMock,
82+
$this->scopeConfigMock,
83+
$this->totalsCollectorMock
84+
);
85+
}
86+
87+
/**
88+
* @throws InputException
89+
* @throws NoSuchEntityException
90+
* @dataProvider assignDataProvider
91+
*/
92+
public function testAssign(bool $saveInAddressBook, bool $showCompany): void
93+
{
94+
$cartId = $customerId = 123;
95+
$addressMock = $this->getMockBuilder(AddressInterface::class)
96+
->addMethods(['setCollectShippingRates', 'save', 'importCustomerAddressData'])
97+
->disableOriginalConstructor()
98+
->getMockForAbstractClass();
99+
$this->quoteMock
100+
->expects($this->once())
101+
->method('isVirtual')
102+
->willReturn(false);
103+
$this->quoteRepositoryMock
104+
->expects($this->once())
105+
->method('getActive')
106+
->with($cartId)
107+
->willReturn($this->quoteMock);
108+
$addressMock
109+
->expects($this->once())
110+
->method('getSaveInAddressBook')
111+
->willReturn($saveInAddressBook);
112+
$addressMock
113+
->expects($this->once())
114+
->method('getSameAsBilling')
115+
->willReturn(true);
116+
$addressMock
117+
->expects($this->once())
118+
->method('getCustomerAddressId')
119+
->willReturn($customerId);
120+
$addressMock
121+
->expects($saveInAddressBook && !$showCompany ? $this->once() : $this->never())
122+
->method('setCompany')
123+
->with(null);
124+
$addressMock
125+
->expects($this->once())
126+
->method('importCustomerAddressData')
127+
->willReturn($addressMock);
128+
$addressMock
129+
->expects($this->once())
130+
->method('setSameAsBilling')
131+
->with(true);
132+
$addressMock
133+
->expects($this->once())
134+
->method('setSaveInAddressBook')
135+
->with($saveInAddressBook);
136+
$addressMock->method('setCollectShippingRates');
137+
$addressMock->method('save');
138+
$this->scopeConfigMock
139+
->expects($saveInAddressBook ? $this->once() : $this->never())
140+
->method('getValue')
141+
->willReturn($showCompany);
142+
$this->addressValidatorMock
143+
->expects($this->once())
144+
->method('validateForCart');
145+
$this->quoteMock
146+
->expects($this->once())
147+
->method('setShippingAddress')
148+
->with($addressMock);
149+
$this->quoteMock
150+
->method('getShippingAddress')
151+
->willReturn($addressMock);
152+
$this->model->assign($cartId, $addressMock);
153+
}
154+
155+
/**
156+
* @return array
157+
*/
158+
public function assignDataProvider(): array
159+
{
160+
return [
161+
[true, true],
162+
[true, false],
163+
[false, true],
164+
[false, false],
165+
];
166+
}
167+
}

app/code/Magento/Sales/Model/ResourceModel/Order/Handler/State.php

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@ public function check(Order $order)
3838
) {
3939
$order->setState(Order::STATE_CLOSED)
4040
->setStatus($order->getConfig()->getStateDefaultStatus(Order::STATE_CLOSED));
41-
} elseif ($currentState === Order::STATE_PROCESSING && !$order->canShip()) {
41+
} elseif ($currentState === Order::STATE_PROCESSING
42+
&& (!$order->canShip() || $this->isPartiallyRefundedOrderShipped($order))
43+
) {
4244
$order->setState(Order::STATE_COMPLETE)
4345
->setStatus($order->getConfig()->getStateDefaultStatus(Order::STATE_COMPLETE));
4446
} elseif ($order->getIsVirtual() && $order->getStatus() === Order::STATE_CLOSED) {
@@ -47,4 +49,53 @@ public function check(Order $order)
4749
}
4850
return $this;
4951
}
52+
53+
/**
54+
* Check if all items are remaining items after partially refunded are shipped
55+
*
56+
* @param Order $order
57+
* @return bool
58+
*/
59+
public function isPartiallyRefundedOrderShipped(Order $order): bool
60+
{
61+
$isPartiallyRefundedOrderShipped = false;
62+
if ($this->getShippedItems($order) > 0
63+
&& $order->getTotalQtyOrdered() <= $this->getRefundedItems($order) + $this->getShippedItems($order)) {
64+
$isPartiallyRefundedOrderShipped = true;
65+
}
66+
67+
return $isPartiallyRefundedOrderShipped;
68+
}
69+
70+
/**
71+
* Get all refunded items number
72+
*
73+
* @param Order $order
74+
* @return int
75+
*/
76+
private function getRefundedItems(Order $order): int
77+
{
78+
$numOfRefundedItems = 0;
79+
foreach ($order->getAllItems() as $item) {
80+
if ($item->getProductType() == 'simple') {
81+
$numOfRefundedItems += (int)$item->getQtyRefunded();
82+
}
83+
}
84+
return $numOfRefundedItems;
85+
}
86+
87+
/**
88+
* Get all shipped items number
89+
*
90+
* @param Order $order
91+
* @return int
92+
*/
93+
private function getShippedItems(Order $order): int
94+
{
95+
$numOfShippedItems = 0;
96+
foreach ($order->getAllItems() as $item) {
97+
$numOfShippedItems += (int)$item->getQtyShipped();
98+
}
99+
return $numOfShippedItems;
100+
}
50101
}

0 commit comments

Comments
 (0)