Skip to content

Commit f305174

Browse files
committed
Merge remote-tracking branch 'origin/MC-38315' into 2.4-develop-pr44
2 parents aac3d31 + 101b711 commit f305174

File tree

5 files changed

+262
-16
lines changed

5 files changed

+262
-16
lines changed

app/code/Magento/Catalog/Model/Product/Option/Type/Date.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ public function validateUserValue($values)
7272
$dateValid = true;
7373
if ($this->_dateExists()) {
7474
if ($this->useCalendar()) {
75+
if (is_array($value) && $this->checkDateWithoutJSCalendar($value)) {
76+
$value['date'] = sprintf("%s/%s/%s", $value['day'], $value['month'], $value['year']);
77+
}
7578
/* Fixed validation if the date was not saved correctly after re-saved the order
7679
for example: "09\/24\/2020,2020-09-24 00:00:00" */
7780
if (is_string($value) && preg_match('/^\d{1,4}.+\d{1,4}.+\d{1,4},+(\w|\W)*$/', $value)) {
@@ -81,6 +84,9 @@ public function validateUserValue($values)
8184
}
8285
$dateValid = isset($value['date']) && preg_match('/^\d{1,4}.+\d{1,4}.+\d{1,4}$/', $value['date']);
8386
} else {
87+
if (is_array($value)) {
88+
$value = $this->prepareDateByDateInternal($value);
89+
}
8490
$dateValid = isset(
8591
$value['day']
8692
) && isset(
@@ -411,4 +417,38 @@ protected function _timeExists()
411417
]
412418
);
413419
}
420+
421+
/**
422+
* Check is date without JS Calendar
423+
*
424+
* @param array $value
425+
*
426+
* @return bool
427+
*/
428+
private function checkDateWithoutJSCalendar(array $value): bool
429+
{
430+
return empty($value['date'])
431+
&& !empty($value['day'])
432+
&& !empty($value['month'])
433+
&& !empty($value['year']);
434+
}
435+
436+
/**
437+
* Prepare date by date internal
438+
*
439+
* @param array $value
440+
* @return array
441+
*/
442+
private function prepareDateByDateInternal(array $value): array
443+
{
444+
if (!empty($value['date']) && !empty($value['date_internal'])) {
445+
$formatDate = explode(' ', $value['date_internal']);
446+
$date = explode('-', $formatDate[0]);
447+
$value['year'] = $date[0];
448+
$value['month'] = $date[1];
449+
$value['day'] = $date[2];
450+
}
451+
452+
return $value;
453+
}
414454
}

app/code/Magento/Sales/Model/AdminOrder/Create.php

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -670,12 +670,14 @@ public function initFromOrderItem(\Magento\Sales\Model\Order\Item $orderItem, $q
670670
$productOptions = $orderItem->getProductOptions();
671671
if ($productOptions !== null && !empty($productOptions['options'])) {
672672
$formattedOptions = [];
673-
$useFrontendCalendar = $this->useFrontendCalendar();
674673
foreach ($productOptions['options'] as $option) {
675-
if (in_array($option['option_type'], ['date', 'date_time']) && $useFrontendCalendar) {
674+
if (in_array($option['option_type'], ['date', 'date_time', 'time', 'file'])) {
676675
$product->setSkipCheckRequiredOption(false);
677-
break;
676+
$formattedOptions[$option['option_id']] =
677+
$buyRequest->getDataByKey('options')[$option['option_id']];
678+
continue;
678679
}
680+
679681
$formattedOptions[$option['option_id']] = $option['option_value'];
680682
}
681683
if (!empty($formattedOptions)) {
@@ -2129,17 +2131,4 @@ private function isAddressesAreEqual(Order $order)
21292131

21302132
return $shippingData == $billingData;
21312133
}
2132-
2133-
/**
2134-
* Use Calendar on frontend or not
2135-
*
2136-
* @return bool
2137-
*/
2138-
private function useFrontendCalendar(): bool
2139-
{
2140-
return (bool)$this->_scopeConfig->getValue(
2141-
'catalog/custom_options/use_calendar',
2142-
\Magento\Store\Model\ScopeInterface::SCOPE_STORE
2143-
);
2144-
}
21452134
}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
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\Sales\Controller\Adminhtml\Order\Create;
9+
10+
use Magento\Customer\Model\Session;
11+
use Magento\Framework\Api\SearchCriteriaBuilder;
12+
use Magento\Framework\Escaper;
13+
use Magento\Framework\Registry;
14+
use Magento\Quote\Api\CartRepositoryInterface;
15+
use Magento\Quote\Api\Data\CartInterface;
16+
use Magento\Sales\Api\Data\OrderInterfaceFactory;
17+
use Magento\TestFramework\Core\Version\View;
18+
use Magento\TestFramework\Request;
19+
use Magento\TestFramework\TestCase\AbstractBackendController;
20+
21+
/**
22+
* Test for reorder controller.
23+
*
24+
* @see \Magento\Sales\Controller\Adminhtml\Order\Create\Reorder
25+
* @magentoAppArea adminhtml
26+
*/
27+
class ReorderTest extends AbstractBackendController
28+
{
29+
/** @var OrderInterfaceFactory */
30+
private $orderFactory;
31+
32+
/** @var CartRepositoryInterface */
33+
private $quoteRepository;
34+
35+
/** @var CartInterface */
36+
private $quote;
37+
38+
/**
39+
* @inheritdoc
40+
*/
41+
protected function setUp(): void
42+
{
43+
parent::setUp();
44+
$this->orderFactory = $this->_objectManager->get(OrderInterfaceFactory::class);
45+
$this->quoteRepository = $this->_objectManager->get(CartRepositoryInterface::class);
46+
}
47+
48+
/**
49+
* @inheritdoc
50+
*/
51+
protected function tearDown(): void
52+
{
53+
if ($this->quote instanceof CartInterface) {
54+
$this->quoteRepository->delete($this->quote);
55+
}
56+
57+
parent::tearDown();
58+
}
59+
60+
/**
61+
* Reorder with JS calendar options
62+
*
63+
* @magentoConfigFixture current_store catalog/custom_options/use_calendar 1
64+
* @magentoDataFixture Magento/Sales/_files/order_with_date_time_option_product.php
65+
*
66+
* @return void
67+
*/
68+
public function testReorderAfterJSCalendarEnabled(): void
69+
{
70+
$order = $this->orderFactory->create()->loadByIncrementId('100000001');
71+
$this->dispatchReorderRequest((int)$order->getId());
72+
$this->assertRedirect($this->stringContains('backend/sales/order_create'));
73+
$this->quote = $this->getQuote('customer@example.com');
74+
$this->assertTrue(!empty($this->quote));
75+
}
76+
77+
/**
78+
* Dispatch reorder request.
79+
*
80+
* @param null|int $orderId
81+
* @return void
82+
*/
83+
private function dispatchReorderRequest(?int $orderId = null): void
84+
{
85+
$this->getRequest()->setMethod(Request::METHOD_GET);
86+
$this->getRequest()->setParam('order_id', $orderId);
87+
$this->dispatch('backend/sales/order_create/reorder');
88+
}
89+
90+
/**
91+
* Gets quote by reserved order id.
92+
*
93+
* @return \Magento\Quote\Api\Data\CartInterface
94+
*/
95+
private function getQuote(string $customerEmail): \Magento\Quote\Api\Data\CartInterface
96+
{
97+
/** @var SearchCriteriaBuilder $searchCriteriaBuilder */
98+
$searchCriteriaBuilder = $this->_objectManager->get(SearchCriteriaBuilder::class);
99+
$searchCriteria = $searchCriteriaBuilder->addFilter('customer_email', $customerEmail)
100+
->create();
101+
102+
/** @var CartRepositoryInterface $quoteRepository */
103+
$quoteRepository = $this->_objectManager->get(CartRepositoryInterface::class);
104+
$items = $quoteRepository->getList($searchCriteria)->getItems();
105+
106+
return array_pop($items);
107+
}
108+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
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+
use Magento\TestFramework\Workaround\Override\Fixture\Resolver;
9+
10+
Resolver::getInstance()->requireDataFixture('Magento/Customer/_files/customer.php');
11+
Resolver::getInstance()->requireDataFixture('Magento/Catalog/_files/product_simple.php');
12+
13+
$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
14+
15+
$addressData = include __DIR__ . '/../../../Magento/Sales/_files/address_data.php';
16+
17+
$billingAddress = $objectManager->create(\Magento\Sales\Model\Order\Address::class, ['data' => $addressData]);
18+
$billingAddress->setAddressType('billing');
19+
20+
$shippingAddress = clone $billingAddress;
21+
$shippingAddress->setId(null)->setAddressType('shipping');
22+
23+
$payment = $objectManager->create(\Magento\Sales\Model\Order\Payment::class);
24+
$payment->setMethod('checkmo');
25+
26+
/** @var $product \Magento\Catalog\Model\Product */
27+
$product = $objectManager->create(\Magento\Catalog\Model\Product::class);
28+
$repository = $objectManager->create(\Magento\Catalog\Model\ProductRepository::class);
29+
$product = $repository->get('simple');
30+
31+
$optionValuesByType = [
32+
'field' => 'Test value',
33+
'date_time' => [
34+
'month' => '3',
35+
'day' => '5',
36+
'year' => '2020',
37+
'hour' => '2',
38+
'minute' => '15',
39+
'day_part' => 'am',
40+
'date_internal' => '2020-09-30 02:15:00'
41+
],
42+
'drop_down' => '3-1-select',
43+
'radio' => '4-1-radio',
44+
];
45+
$optionsDate = [
46+
[
47+
'label' => 'date',
48+
'value' => 'Mar 5, 2020',
49+
'print_value' => 'Mar 5, 2020',
50+
'option_id' => '1',
51+
'option_type' => 'date',
52+
'option_value' => '2020-03-05 00:00:00',
53+
'custom_view' => '',
54+
]
55+
];
56+
57+
$requestInfo = ['options' => []];
58+
$productOptions = $product->getOptions();
59+
foreach ($productOptions as $option) {
60+
$requestInfo['options'][$option->getOptionId()] = $optionValuesByType[$option->getType()];
61+
}
62+
63+
/** @var \Magento\Sales\Model\Order\Item $orderItem */
64+
$orderItem = $objectManager->create(\Magento\Sales\Model\Order\Item::class);
65+
$orderItem->setProductId($product->getId());
66+
$orderItem->setSku($product->getSku());
67+
$orderItem->setQtyOrdered(1);
68+
$orderItem->setBasePrice($product->getPrice());
69+
$orderItem->setPrice($product->getPrice());
70+
$orderItem->setRowTotal($product->getPrice());
71+
$orderItem->setProductType($product->getTypeId());
72+
$orderItem->setProductOptions([
73+
'info_buyRequest' => $requestInfo,
74+
'options' => $optionsDate,
75+
]);
76+
77+
/** @var \Magento\Sales\Model\Order $order */
78+
$order = $objectManager->create(\Magento\Sales\Model\Order::class);
79+
$order->setIncrementId('100000001');
80+
$order->setState(\Magento\Sales\Model\Order::STATE_NEW);
81+
$order->setStatus($order->getConfig()->getStateDefaultStatus(\Magento\Sales\Model\Order::STATE_NEW));
82+
$order->setCustomerIsGuest(true);
83+
$order->setCustomerEmail('customer@example.com');
84+
$order->setCustomerFirstname('firstname');
85+
$order->setCustomerLastname('lastname');
86+
$order->setBillingAddress($billingAddress);
87+
$order->setShippingAddress($shippingAddress);
88+
$order->setAddresses([$billingAddress, $shippingAddress]);
89+
$order->setPayment($payment);
90+
$order->addItem($orderItem);
91+
$order->setStoreId($objectManager->get(\Magento\Store\Model\StoreManagerInterface::class)->getStore()->getId());
92+
$order->setSubtotal(100);
93+
$order->setBaseSubtotal(100);
94+
$order->setBaseGrandTotal(100);
95+
$order->setCustomerId(1)
96+
->setCustomerIsGuest(false)
97+
->save();
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
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+
use Magento\TestFramework\Workaround\Override\Fixture\Resolver;
9+
10+
Resolver::getInstance()->requireDataFixture('Magento/Customer/_files/customer_rollback.php');
11+
Resolver::getInstance()->requireDataFixture('Magento/Catalog/_files/product_simple_rollback.php');
12+
Resolver::getInstance()->requireDataFixture('Magento/Sales/_files/default_rollback.php');

0 commit comments

Comments
 (0)