Skip to content

Commit 316c296

Browse files
Merge branch 'ACQE-8970' into ACQE-functional-deployment-v4-7
2 parents 1bed86b + a5d57ea commit 316c296

File tree

2 files changed

+311
-17
lines changed

2 files changed

+311
-17
lines changed
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
<?php
2+
/**
3+
* Copyright 2025 Adobe
4+
* All Rights Reserved.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Sales\Test\Fixture;
9+
10+
use Exception;
11+
use Magento\Catalog\Api\ProductRepositoryInterface;
12+
use Magento\Framework\DataObject;
13+
use Magento\Framework\Exception\NoSuchEntityException;
14+
use Magento\Sales\Api\Data\OrderInterface;
15+
use Magento\Sales\Api\OrderRepositoryInterface;
16+
use Magento\Sales\Model\Order;
17+
use Magento\Sales\Model\Order\AddressFactory;
18+
use Magento\Sales\Model\Order\ItemFactory;
19+
use Magento\Sales\Model\Order\PaymentFactory;
20+
use Magento\Store\Model\StoreManagerInterface;
21+
use Magento\TestFramework\Fixture\RevertibleDataFixtureInterface;
22+
use Random\RandomException;
23+
24+
/**
25+
* Generic order fixture that supports both customer and guest orders.
26+
*/
27+
class PlaceOrderWithCustomerOrGuest implements RevertibleDataFixtureInterface
28+
{
29+
private const DEFAULT_ADDRESS = [
30+
'firstname' => 'John',
31+
'lastname' => 'Doe',
32+
'street' => ['123 Test Street'],
33+
'city' => 'Los Angeles',
34+
'postcode' => '90001',
35+
'country_id' => 'US',
36+
'telephone' => '5555555555',
37+
'region_id' => 12,
38+
];
39+
40+
private const DEFAULT_ITEM = [
41+
'sku' => 'simple',
42+
'qty' => 1,
43+
'price' => 100.00,
44+
'base_price' => 100.00,
45+
];
46+
47+
private const DEFAULT_DATA = [
48+
'increment_id' => null,
49+
'state' => Order::STATE_PROCESSING,
50+
'status' => null,
51+
'subtotal' => 100.00,
52+
'base_subtotal' => 100.00,
53+
'grand_total' => 100.00,
54+
'base_grand_total' => 100.00,
55+
'currency' => 'USD',
56+
'base_currency' => 'USD',
57+
'customer_id' => null,
58+
'customer_email' => 'customer@example.com',
59+
'customer_firstname' => 'John',
60+
'customer_lastname' => 'Doe',
61+
'customer_is_guest' => false,
62+
'billing_address' => [],
63+
'shipping_address' => [],
64+
'items' => [],
65+
'payment_method' => 'checkmo',
66+
];
67+
68+
/**
69+
* @param OrderRepositoryInterface $orderRepository
70+
* @param OrderInterface $orderPrototype
71+
* @param AddressFactory $addressFactory
72+
* @param ItemFactory $itemFactory
73+
* @param PaymentFactory $paymentFactory
74+
* @param ProductRepositoryInterface $productRepository
75+
* @param StoreManagerInterface $storeManager
76+
*/
77+
public function __construct(
78+
private readonly OrderRepositoryInterface $orderRepository,
79+
private readonly OrderInterface $orderPrototype,
80+
private readonly AddressFactory $addressFactory,
81+
private readonly ItemFactory $itemFactory,
82+
private readonly PaymentFactory $paymentFactory,
83+
private readonly ProductRepositoryInterface $productRepository,
84+
private readonly StoreManagerInterface $storeManager
85+
) {
86+
}
87+
88+
/**
89+
* @param array $data
90+
* @return DataObject|null
91+
* @throws NoSuchEntityException
92+
* @throws Exception
93+
*/
94+
public function apply(array $data = []): ?DataObject
95+
{
96+
$data = array_replace_recursive(self::DEFAULT_DATA, $data);
97+
98+
/** @var Order $order */
99+
$order = clone $this->orderPrototype;
100+
101+
$incrementId = $data['increment_id'] ?? sprintf('%09d', random_int(100000000, 999999999));
102+
$order->setIncrementId($incrementId)
103+
->setState($data['state'])
104+
->setStatus($data['status'] ?? $order->getConfig()->getStateDefaultStatus($data['state']))
105+
->setSubtotal($data['subtotal'])
106+
->setBaseSubtotal($data['base_subtotal'])
107+
->setGrandTotal($data['grand_total'])
108+
->setBaseGrandTotal($data['base_grand_total'])
109+
->setOrderCurrencyCode($data['currency'])
110+
->setBaseCurrencyCode($data['base_currency'])
111+
->setCustomerId($data['customer_id'])
112+
->setCustomerEmail($data['customer_email'])
113+
->setCustomerFirstname($data['customer_firstname'])
114+
->setCustomerLastname($data['customer_lastname'])
115+
->setCustomerIsGuest((bool)$data['customer_is_guest'])
116+
->setStoreId($this->storeManager->getStore()->getId());
117+
118+
$billingAddress = $this->addressFactory->create([
119+
'data' => array_replace(self::DEFAULT_ADDRESS, $data['billing_address'])
120+
]);
121+
$shippingAddress = $this->addressFactory->create([
122+
'data' => array_replace(self::DEFAULT_ADDRESS, $data['shipping_address'])
123+
]);
124+
$billingAddress->setAddressType('billing');
125+
$shippingAddress->setAddressType('shipping')->setId(null);
126+
127+
$order->setBillingAddress($billingAddress);
128+
$order->setShippingAddress($shippingAddress);
129+
130+
$payment = $this->paymentFactory->create();
131+
$payment->setMethod($data['payment_method']);
132+
$order->setPayment($payment);
133+
134+
$items = $data['items'] ?: [self::DEFAULT_ITEM];
135+
foreach ($items as $itemData) {
136+
$itemData = array_replace(self::DEFAULT_ITEM, $itemData);
137+
$product = $this->productRepository->get($itemData['sku']);
138+
139+
$orderItem = $this->itemFactory->create();
140+
$orderItem->setProductId((int)$product->getId())
141+
->setQtyOrdered((float)$itemData['qty'])
142+
->setPrice((float)$itemData['price'])
143+
->setBasePrice((float)$itemData['base_price'])
144+
->setRowTotal((float)$itemData['price'] * (float)$itemData['qty'])
145+
->setBaseRowTotal((float)$itemData['base_price'] * (float)$itemData['qty'])
146+
->setProductType($product->getTypeId())
147+
->setName($product->getName())
148+
->setSku($product->getSku());
149+
150+
$order->addItem($orderItem);
151+
}
152+
153+
$this->orderRepository->save($order);
154+
155+
return $order;
156+
}
157+
158+
/**
159+
* @param DataObject $data
160+
* @return void
161+
*/
162+
public function revert(DataObject $data): void
163+
{
164+
$order = $this->orderRepository->get((int)$data->getEntityId());
165+
$this->orderRepository->delete($order);
166+
}
167+
}

0 commit comments

Comments
 (0)