CartData.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544
  1. <?php
  2. namespace Webkul\BagistoApi\Dto;
  3. use ApiPlatform\Metadata\ApiProperty;
  4. use Symfony\Component\Serializer\Annotation\Groups;
  5. /**
  6. * Shopping cart data transfer object
  7. */
  8. class CartData
  9. {
  10. #[Groups(['query', 'mutation'])]
  11. public ?int $id = null;
  12. #[Groups(['query', 'mutation'])]
  13. #[ApiProperty(description: 'Cart token for guest users')]
  14. public ?string $cartToken = null;
  15. #[Groups(['query', 'mutation'])]
  16. public ?int $customerId = null;
  17. #[Groups(['query', 'mutation'])]
  18. public ?int $channelId = null;
  19. #[Groups(['query', 'mutation'])]
  20. public ?int $itemsCount = null;
  21. /**
  22. * Individual cart items - array of CartItemData DTO objects
  23. *
  24. * @var array<CartItemData>|null
  25. */
  26. #[Groups(['query', 'mutation'])]
  27. #[ApiProperty(description: 'Individual cart items')]
  28. public ?array $items = [];
  29. #[Groups(['query', 'mutation'])]
  30. #[ApiProperty(description: 'Subtotal before discounts and taxes')]
  31. public ?float $subtotal = null;
  32. #[Groups(['query', 'mutation'])]
  33. public ?float $baseSubtotal = null;
  34. #[Groups(['query', 'mutation'])]
  35. #[ApiProperty(description: 'Total discount amount')]
  36. public ?float $discountAmount = null;
  37. #[Groups(['query', 'mutation'])]
  38. public ?float $baseDiscountAmount = null;
  39. #[Groups(['query', 'mutation'])]
  40. #[ApiProperty(description: 'Total tax amount')]
  41. public ?float $taxAmount = null;
  42. #[Groups(['query', 'mutation'])]
  43. public ?float $baseTaxAmount = null;
  44. #[Groups(['query', 'mutation'])]
  45. #[ApiProperty(description: 'Shipping cost')]
  46. public ?float $shippingAmount = null;
  47. #[Groups(['query', 'mutation'])]
  48. public ?float $baseShippingAmount = null;
  49. #[Groups(['query', 'mutation'])]
  50. #[ApiProperty(description: 'Grand total')]
  51. public ?float $grandTotal = null;
  52. #[Groups(['query', 'mutation'])]
  53. public ?float $baseGrandTotal = null;
  54. #[Groups(['query', 'mutation'])]
  55. #[ApiProperty(description: 'Formatted subtotal price')]
  56. public ?string $formattedSubtotal = null;
  57. #[Groups(['query', 'mutation'])]
  58. #[ApiProperty(description: 'Formatted discount amount')]
  59. public ?string $formattedDiscountAmount = null;
  60. #[Groups(['query', 'mutation'])]
  61. #[ApiProperty(description: 'Formatted tax amount')]
  62. public ?string $formattedTaxAmount = null;
  63. #[Groups(['query', 'mutation'])]
  64. #[ApiProperty(description: 'Formatted shipping amount')]
  65. public ?string $formattedShippingAmount = null;
  66. #[Groups(['query', 'mutation'])]
  67. #[ApiProperty(description: 'Formatted grand total price')]
  68. public ?string $formattedGrandTotal = null;
  69. #[Groups(['query', 'mutation'])]
  70. #[ApiProperty(description: 'Applied coupon code')]
  71. public ?string $couponCode = null;
  72. #[Groups(['query', 'mutation'])]
  73. #[ApiProperty(description: 'Applied gift card number')]
  74. public ?string $giftcardNumber = null;
  75. #[Groups(['query', 'mutation'])]
  76. #[ApiProperty(description: 'Gift card discount amount')]
  77. public ?float $giftcardAmount = null;
  78. #[Groups(['query', 'mutation'])]
  79. #[ApiProperty(description: 'Base gift card discount amount')]
  80. public ?float $baseGiftcardAmount = null;
  81. #[Groups(['query', 'mutation'])]
  82. #[ApiProperty(description: 'Formatted gift card discount amount')]
  83. public ?string $formattedGiftcardAmount = null;
  84. #[Groups(['query', 'mutation'])]
  85. #[ApiProperty(description: 'Remaining gift card balance after use')]
  86. public ?float $remainingGiftcardAmount = null;
  87. #[Groups(['query', 'mutation'])]
  88. #[ApiProperty(description: 'Formatted remaining gift card balance')]
  89. public ?string $formattedRemainingGiftcardAmount = null;
  90. #[Groups(['query', 'mutation'])]
  91. #[ApiProperty(description: 'VIP member discount amount')]
  92. public ?float $vipPlusAmount = null;
  93. #[Groups(['query', 'mutation'])]
  94. #[ApiProperty(description: 'Base VIP member discount amount')]
  95. public ?float $baseVipPlusAmount = null;
  96. #[Groups(['query', 'mutation'])]
  97. #[ApiProperty(description: 'Formatted VIP member discount amount')]
  98. public ?string $formattedVipPlusAmount = null;
  99. #[Groups(['query', 'mutation'])]
  100. #[ApiProperty(description: 'VIP discount amount (5%)')]
  101. public ?float $vipDiscountAmount = null;
  102. #[Groups(['query', 'mutation'])]
  103. #[ApiProperty(description: 'Base VIP discount amount (5%)')]
  104. public ?float $baseVipDiscountAmount = null;
  105. #[Groups(['query', 'mutation'])]
  106. #[ApiProperty(description: 'Formatted VIP discount amount (5%)')]
  107. public ?string $formattedVipDiscountAmount = null;
  108. #[Groups(['query', 'mutation'])]
  109. #[ApiProperty(description: 'Whether the current customer is a VIP member')]
  110. public ?bool $isVip = null;
  111. #[Groups(['query', 'mutation'])]
  112. #[ApiProperty(description: 'VIP Plus expiration date')]
  113. public ?string $vipExpireDate = null;
  114. #[Groups(['query', 'mutation'])]
  115. #[ApiProperty(description: 'Whether shipping insurance is used')]
  116. public ?bool $useShippingInsurance = null;
  117. #[Groups(['query', 'mutation'])]
  118. #[ApiProperty(description: 'Whether shipping insurance is enabled in admin')]
  119. public ?bool $shippingInsuranceEnabled = null;
  120. #[Groups(['query', 'mutation'])]
  121. #[ApiProperty(description: 'Shipping insurance name')]
  122. public ?string $shippingInsuranceName = null;
  123. #[Groups(['query', 'mutation'])]
  124. #[ApiProperty(description: 'Shipping insurance type (fixed|percentage)')]
  125. public ?string $shippingInsuranceType = null;
  126. #[Groups(['query', 'mutation'])]
  127. #[ApiProperty(description: 'Shipping insurance value (percentage or fixed amount)')]
  128. public ?float $shippingInsuranceValue = null;
  129. #[Groups(['query', 'mutation'])]
  130. #[ApiProperty(description: 'Shipping insurance amount')]
  131. public ?float $shippingInsuranceAmount = null;
  132. #[Groups(['query', 'mutation'])]
  133. #[ApiProperty(description: 'Base shipping insurance amount')]
  134. public ?float $baseShippingInsuranceAmount = null;
  135. #[Groups(['query', 'mutation'])]
  136. #[ApiProperty(description: 'Formatted shipping insurance amount')]
  137. public ?string $formattedShippingInsuranceAmount = null;
  138. #[Groups(['query', 'mutation'])]
  139. public ?bool $success = null;
  140. #[Groups(['query', 'mutation'])]
  141. public ?string $message = null;
  142. #[Groups(['query', 'mutation'])]
  143. public ?array $carts = null;
  144. #[Groups(['query', 'mutation'])]
  145. #[ApiProperty(description: 'Unique session token for guest cart')]
  146. public ?string $sessionToken = null;
  147. #[Groups(['query', 'mutation'])]
  148. #[ApiProperty(description: 'Is this a guest cart')]
  149. public bool $isGuest = false;
  150. #[Groups(['query', 'mutation'])]
  151. #[ApiProperty(description: 'Total quantity of all items')]
  152. public ?int $itemsQty = null;
  153. #[Groups(['query', 'mutation'])]
  154. #[ApiProperty(description: "Customer's current reward points balance")]
  155. public int $rewardPoints = 0;
  156. #[Groups(['query', 'mutation'])]
  157. #[ApiProperty(description: 'Reward points that can be earned from the current cart')]
  158. public int $earnableRewardPoints = 0;
  159. #[Groups(['query', 'mutation'])]
  160. #[ApiProperty(description: 'Reward points redeemed against the current cart')]
  161. public int $rewardPointsUsed = 0;
  162. #[Groups(['query', 'mutation'])]
  163. #[ApiProperty(description: 'Reward points discount amount')]
  164. public ?float $rewardPointsAmount = null;
  165. #[Groups(['query', 'mutation'])]
  166. #[ApiProperty(description: 'Base reward points discount amount')]
  167. public ?float $baseRewardPointsAmount = null;
  168. #[Groups(['query', 'mutation'])]
  169. #[ApiProperty(description: 'Formatted reward points discount amount')]
  170. public ?string $formattedRewardPointsAmount = null;
  171. #[Groups(['query', 'mutation'])]
  172. #[ApiProperty(description: 'Subtotal including tax')]
  173. public ?float $subTotalInclTax = null;
  174. #[Groups(['query', 'mutation'])]
  175. #[ApiProperty(description: 'Base subtotal including tax')]
  176. public ?float $baseSubTotalInclTax = null;
  177. #[Groups(['query', 'mutation'])]
  178. #[ApiProperty(description: 'Formatted subtotal including tax')]
  179. public ?string $formattedSubTotalInclTax = null;
  180. #[Groups(['query', 'mutation'])]
  181. #[ApiProperty(description: 'Tax total')]
  182. public ?float $taxTotal = null;
  183. #[Groups(['query', 'mutation'])]
  184. #[ApiProperty(description: 'Formatted tax total')]
  185. public ?string $formattedTaxTotal = null;
  186. #[Groups(['query', 'mutation'])]
  187. #[ApiProperty(description: 'Shipping amount including tax')]
  188. public ?float $shippingAmountInclTax = null;
  189. #[Groups(['query', 'mutation'])]
  190. #[ApiProperty(description: 'Base shipping amount including tax')]
  191. public ?float $baseShippingAmountInclTax = null;
  192. #[Groups(['query', 'mutation'])]
  193. #[ApiProperty(description: 'Formatted shipping amount including tax')]
  194. public ?string $formattedShippingAmountInclTax = null;
  195. #[Groups(['query', 'mutation'])]
  196. #[ApiProperty(description: 'Billing address')]
  197. public ?array $billingAddress = null;
  198. #[Groups(['query', 'mutation'])]
  199. #[ApiProperty(description: 'Shipping address')]
  200. public ?array $shippingAddress = null;
  201. #[Groups(['query', 'mutation'])]
  202. #[ApiProperty(description: 'Applied taxes')]
  203. public ?array $appliedTaxes = null;
  204. #[Groups(['query', 'mutation'])]
  205. #[ApiProperty(description: 'Has stockable items')]
  206. public ?bool $haveStockableItems = null;
  207. #[Groups(['query', 'mutation'])]
  208. #[ApiProperty(description: 'Payment method code')]
  209. public ?string $paymentMethod = null;
  210. #[Groups(['query', 'mutation'])]
  211. #[ApiProperty(description: 'Payment method title')]
  212. public ?string $paymentMethodTitle = null;
  213. #[Groups(['query', 'mutation'])]
  214. #[ApiProperty(readable: true, writable: false, description: 'Selected shipping rate')]
  215. public ?string $selectedShippingRate = null;
  216. #[Groups(['query', 'mutation'])]
  217. #[ApiProperty(readable: true, writable: false, description: 'Selected shipping rate title')]
  218. public ?string $selectedShippingRateTitle = null;
  219. #[Groups(['query', 'mutation'])]
  220. #[ApiProperty(description: 'Payment redirect URL (if payment gateway redirect needed)')]
  221. public ?string $paymentRedirectUrl = null;
  222. #[Groups(['query', 'mutation'])]
  223. #[ApiProperty(description: 'Order ID after order creation')]
  224. public ?string $orderId = null;
  225. #[Groups(['query', 'mutation'])]
  226. #[ApiProperty(description: 'Redirect URL for buy now checkout')]
  227. public ?string $redirectUri = null;
  228. public function getSelectedShippingRate(): ?string
  229. {
  230. return $this->selectedShippingRate;
  231. }
  232. public function setSelectedShippingRate(?string $selectedShippingRate): void
  233. {
  234. $this->selectedShippingRate = $selectedShippingRate;
  235. }
  236. public function getSelectedShippingRateTitle(): ?string
  237. {
  238. return $this->selectedShippingRateTitle;
  239. }
  240. public function setSelectedShippingRateTitle(?string $selectedShippingRateTitle): void
  241. {
  242. $this->selectedShippingRateTitle = $selectedShippingRateTitle;
  243. }
  244. public static function fromModel(\Webkul\Checkout\Models\Cart $cart): self
  245. {
  246. $data = new self;
  247. $data->id = $cart->id;
  248. $data->cartToken = (string) $cart->id;
  249. $data->customerId = $cart->customer_id;
  250. $data->isGuest = ! $cart->customer_id;
  251. $data->channelId = $cart->channel_id;
  252. $data->itemsCount = $cart->items()->count();
  253. $data->itemsQty = (int) ($cart->items_qty ?? 0);
  254. $items = $cart->items()
  255. ->with(['product'])
  256. ->get()
  257. ->map(fn ($item) => CartItemData::fromModel($item));
  258. $data->items = $items->toArray();
  259. $data->subtotal = (float) core()->convertPrice($cart->base_sub_total ?? 0);
  260. $data->baseSubtotal = (float) ($cart->base_sub_total ?? 0);
  261. $data->formattedSubtotal = core()->currency($cart->base_sub_total ?? 0);
  262. $data->subTotalInclTax = (float) core()->convertPrice($cart->base_sub_total_incl_tax ?? $cart->base_sub_total ?? 0);
  263. $data->baseSubTotalInclTax = (float) ($cart->base_sub_total_incl_tax ?? $cart->base_sub_total ?? 0);
  264. $data->formattedSubTotalInclTax = core()->currency($cart->base_sub_total_incl_tax ?? $cart->base_sub_total ?? 0);
  265. $data->taxAmount = (float) core()->convertPrice($cart->base_tax_amount ?? 0);
  266. $data->baseTaxAmount = (float) ($cart->base_tax_amount ?? 0);
  267. $data->taxTotal = (float) core()->convertPrice($cart->base_tax_total ?? $cart->base_tax_amount ?? 0);
  268. $data->formattedTaxTotal = core()->currency($cart->base_tax_total ?? $cart->base_tax_amount ?? 0);
  269. $data->formattedTaxAmount = core()->currency($cart->base_tax_amount ?? 0);
  270. $data->discountAmount = (float) core()->convertPrice($cart->base_discount_amount ?? 0);
  271. $data->baseDiscountAmount = (float) ($cart->base_discount_amount ?? 0);
  272. $data->formattedDiscountAmount = core()->currency($cart->base_discount_amount ?? 0);
  273. $data->shippingAmount = (float) core()->convertPrice($cart->base_shipping_amount ?? 0);
  274. $data->baseShippingAmount = (float) ($cart->base_shipping_amount ?? 0);
  275. $data->formattedShippingAmount = core()->currency($cart->base_shipping_amount ?? 0);
  276. $data->shippingAmountInclTax = (float) core()->convertPrice($cart->base_shipping_amount_incl_tax ?? $cart->base_shipping_amount ?? 0);
  277. $data->baseShippingAmountInclTax = (float) ($cart->base_shipping_amount_incl_tax ?? $cart->base_shipping_amount ?? 0);
  278. $data->formattedShippingAmountInclTax = core()->currency($cart->base_shipping_amount_incl_tax ?? $cart->base_shipping_amount ?? 0);
  279. $data->grandTotal = (float) core()->convertPrice($cart->base_grand_total ?? 0);
  280. $data->baseGrandTotal = (float) ($cart->base_grand_total ?? 0);
  281. $data->formattedGrandTotal = core()->currency($cart->base_grand_total ?? 0);
  282. $data->couponCode = $cart->coupon_code;
  283. // Gift card
  284. $data->giftcardNumber = $cart->giftcard_number ?? null;
  285. $data->giftcardAmount = (float) ($cart->giftcard_amount ?? 0);
  286. $data->baseGiftcardAmount = (float) ($cart->base_giftcard_amount ?? 0);
  287. $data->formattedGiftcardAmount = core()->currency($cart->base_giftcard_amount ?? 0);
  288. $data->remainingGiftcardAmount = (float) ($cart->remaining_giftcard_amount ?? 0);
  289. $data->formattedRemainingGiftcardAmount = core()->formatPrice($cart->remaining_giftcard_amount ?? 0);
  290. // VIP member discount
  291. $data->vipPlusAmount = (float) ($cart->vip_plus_amount ?? 0);
  292. $data->baseVipPlusAmount = (float) ($cart->base_vip_plus_amount ?? 0);
  293. $data->formattedVipPlusAmount = core()->currency($cart->base_vip_plus_amount ?? 0);
  294. // VIP discount (5%)
  295. $data->vipDiscountAmount = (float) ($cart->vip_discount_amount ?? 0);
  296. $data->baseVipDiscountAmount = (float) ($cart->base_vip_discount_amount ?? 0);
  297. $data->formattedVipDiscountAmount = core()->currency($cart->base_vip_discount_amount ?? 0);
  298. // VIP status
  299. $data->isVip = false;
  300. $data->vipExpireDate = null;
  301. if ($cart->customer_id) {
  302. $customer = \Webkul\Customer\Models\Customer::find($cart->customer_id);
  303. if ($customer && $customer->vip_expire_date) {
  304. $expireDate = \Carbon\Carbon::parse($customer->vip_expire_date);
  305. $data->isVip = !$expireDate->isPast();
  306. $data->vipExpireDate = $expireDate->toIso8601String();
  307. }
  308. }
  309. // Shipping insurance
  310. $data->useShippingInsurance = (bool) ($cart->use_shipping_insurance ?? false);
  311. $data->shippingInsuranceEnabled = (bool) ($cart->shipping_insurance_enabled ?? false);
  312. $data->shippingInsuranceName = $cart->shipping_insurance_name ?? null;
  313. $data->shippingInsuranceType = $cart->shipping_insurance_type ?? null;
  314. $data->shippingInsuranceValue = (float) ($cart->shipping_insurance_value ?? 0);
  315. $data->shippingInsuranceAmount = (float) ($cart->shipping_insurance_amount ?? 0);
  316. $data->baseShippingInsuranceAmount = (float) ($cart->base_shipping_insurance_amount ?? 0);
  317. $data->formattedShippingInsuranceAmount = core()->currency($cart->base_shipping_insurance_amount ?? 0);
  318. if ($cart->billing_address) {
  319. $data->billingAddress = [
  320. 'id' => $cart->billing_address->id,
  321. 'firstName' => $cart->billing_address->first_name,
  322. 'lastName' => $cart->billing_address->last_name,
  323. 'email' => $cart->billing_address->email,
  324. 'address' => $cart->billing_address->address,
  325. 'city' => $cart->billing_address->city,
  326. 'state' => $cart->billing_address->state,
  327. 'country' => $cart->billing_address->country,
  328. 'postcode' => $cart->billing_address->postcode,
  329. 'phone' => $cart->billing_address->phone,
  330. ];
  331. }
  332. if ($cart->shipping_address) {
  333. $data->shippingAddress = [
  334. 'id' => $cart->shipping_address->id,
  335. 'firstName' => $cart->shipping_address->first_name,
  336. 'lastName' => $cart->shipping_address->last_name,
  337. 'email' => $cart->shipping_address->email,
  338. 'address' => $cart->shipping_address->address,
  339. 'city' => $cart->shipping_address->city,
  340. 'state' => $cart->shipping_address->state,
  341. 'country' => $cart->shipping_address->country,
  342. 'postcode' => $cart->shipping_address->postcode,
  343. 'phone' => $cart->shipping_address->phone,
  344. ];
  345. }
  346. if ($cart->payment) {
  347. $data->paymentMethod = $cart->payment->method;
  348. $data->paymentMethodTitle = core()->getConfigData('sales.payment_methods.'.$cart->payment->method.'.title');
  349. }
  350. try {
  351. $taxes = collect(\Webkul\Tax\Facades\Tax::getTaxRatesWithAmount($cart, true))->map(function ($rate) {
  352. return core()->currency($rate ?? 0);
  353. })->toArray();
  354. $data->appliedTaxes = $taxes;
  355. } catch (\Exception $e) {
  356. $data->appliedTaxes = [];
  357. }
  358. $data->haveStockableItems = $cart->haveStockableItems();
  359. if ($cart->selected_shipping_rate) {
  360. $data->selectedShippingRate = $cart->selected_shipping_rate->method ?? null;
  361. $data->selectedShippingRateTitle = $cart->selected_shipping_rate->method_title ?? null;
  362. } else {
  363. $data->selectedShippingRate = null;
  364. $data->selectedShippingRateTitle = null;
  365. }
  366. // 积分信息:用户当前积分 + 当前购物车可获得积分
  367. $data->rewardPoints = 0;
  368. $data->earnableRewardPoints = 0;
  369. // 积分抵扣信息
  370. $data->rewardPointsUsed = (int) ($cart->reward_points_used ?? 0);
  371. $data->rewardPointsAmount = (float) core()->convertPrice($cart->base_reward_points_amount ?? 0);
  372. $data->baseRewardPointsAmount = (float) ($cart->base_reward_points_amount ?? 0);
  373. $data->formattedRewardPointsAmount = core()->currency($cart->base_reward_points_amount ?? 0);
  374. if ($cart->customer_id) {
  375. try {
  376. $rewardPointRepository = app(\Longyi\RewardPoints\Repositories\RewardPointRepository::class);
  377. // 用户当前积分
  378. $data->rewardPoints = (int) $rewardPointRepository->getCustomerPoints($cart->customer_id);
  379. // 当前购物车可获得积分(复用订单积分计算逻辑)
  380. $rule = \Longyi\RewardPoints\Models\RewardActiveRule::active()
  381. ->ofType(\Longyi\RewardPoints\Models\RewardActiveRule::TYPE_ORDER)
  382. ->first();
  383. if ($rule) {
  384. $customer = \Webkul\Customer\Models\Customer::find($cart->customer_id);
  385. if ($customer && $rule->isApplicableToCustomer($customer)) {
  386. $pointsPerCurrency = $rule->getPointsForCustomer($customer);
  387. if ($pointsPerCurrency > 0) {
  388. $data->earnableRewardPoints = (int) floor(($cart->base_grand_total ?? 0) * $pointsPerCurrency);
  389. }
  390. }
  391. }
  392. } catch (\Throwable $e) {
  393. // 积分计算失败不阻塞购物车接口
  394. report($e);
  395. }
  396. }
  397. return $data;
  398. }
  399. public static function collection(iterable $carts): array
  400. {
  401. $cartDataCollection = [];
  402. foreach ($carts as $cart) {
  403. $cartDataCollection[] = self::fromModel($cart);
  404. }
  405. return $cartDataCollection;
  406. }
  407. public function getItems(): ?array
  408. {
  409. return $this->items;
  410. }
  411. public function setItems(?array $items): void
  412. {
  413. $this->items = $items;
  414. }
  415. #[Groups(['query', 'mutation'])]
  416. #[ApiProperty(description: 'Redirect URL for payment gateway')]
  417. public ?string $redirectUrl = null;
  418. #[Groups(['query', 'mutation'])]
  419. #[ApiProperty(description: 'Order ID after successful order creation')]
  420. public ?string $orderIncrementId = null;
  421. #[Groups(['query', 'mutation'])]
  422. #[ApiProperty(description: 'Payment transaction ID returned by gateway')]
  423. public ?string $paymentTransactionId = null;
  424. }