Skip to content

Commit 98e1c0c

Browse files
committed
Merge branch '4.x' into t9n/4.x
2 parents 49175a3 + 0e5f2b3 commit 98e1c0c

16 files changed

Lines changed: 270 additions & 30 deletions

CHANGELOG.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,40 @@
11
# Release Notes for Craft Commerce
22

3+
## Unreleased
4+
5+
- Fixed a PHP error that could occur when saving an Order. ([#3283](https://github.com/craftcms/commerce/issues/3283))
6+
7+
## 4.8.4 - 2025-05-01
8+
9+
- Fixed a bug where products weren’t getting updated when default variants were saved directly. ([#3988](https://github.com/craftcms/commerce/issues/3988))
10+
11+
## 4.8.3 - 2025-03-19
12+
13+
- Fixed a PHP error that could occur when registering a custom shipping method.
14+
15+
## 4.8.2 - 2025-03-12
16+
17+
- Fixed a bug where line items’ sale prices could be calculated incorrectly. ([#3928](https://github.com/craftcms/commerce/issues/3928))
18+
19+
## 4.8.1.2 - 2025-02-10
20+
21+
- Fixed a bug where carts’ adjustment totals could be calculated incorrectly. ([#3888](https://github.com/craftcms/commerce/issues/3888))
22+
23+
## 4.8.1.1 - 2025-02-07
24+
25+
- Fixed a bug where taxes and shipping totals weren’t being recalculated in `commerce/cart/*` action requests. ([#3888](https://github.com/craftcms/commerce/issues/3888))
26+
27+
## 4.8.1 - 2025-02-05
28+
29+
- Improved logging when a user deletion is prevented due to the user having Commerce orders. ([#3686](https://github.com/craftcms/commerce/issues/3686))
30+
- Added `craft\commerce\base\Gateway::transactionSupportsRefund()`.
31+
- Fixed a bug where the `commerce/cart/update-cart` action could return unnecessary validation errors. ([3873](https://github.com/craftcms/commerce/issues/3873))
32+
33+
## 4.8.0.1 - 2025-02-03
34+
35+
- Fixed a bug where the deprecated `craft\commerce\models\TaxRate::$isVat` property was still being set. ([#3874](https://github.com/craftcms/commerce/issues/3874))
36+
- Fixed a PHP error that could occur when updating an order’s status from the CLI. ([#3858](https://github.com/craftcms/commerce/issues/3858))
37+
338
## 4.8.0 - 2025-01-30
439

540
### Store Management

src/Plugin.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ public static function editions(): array
210210
/**
211211
* @inheritDoc
212212
*/
213-
public string $schemaVersion = '4.8.0.0';
213+
public string $schemaVersion = '4.8.1.0';
214214

215215
/**
216216
* @inheritdoc

src/base/Gateway.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use craft\base\SavableComponent;
1212
use craft\commerce\elements\Order;
1313
use craft\commerce\models\payments\BasePaymentForm;
14+
use craft\commerce\models\Transaction;
1415
use craft\helpers\StringHelper;
1516
use craft\helpers\UrlHelper;
1617

@@ -146,4 +147,14 @@ public function getTransactionHashFromWebhook(): ?string
146147
{
147148
return null;
148149
}
150+
151+
/**
152+
* @param Transaction $transaction
153+
* @return bool
154+
* @since 4.8.1
155+
*/
156+
public function transactionSupportsRefund(Transaction $transaction): bool
157+
{
158+
return true;
159+
}
149160
}

src/elements/Order.php

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242
use craft\commerce\Plugin;
4343
use craft\commerce\records\LineItem as LineItemRecord;
4444
use craft\commerce\records\Order as OrderRecord;
45-
use craft\commerce\records\OrderAdjustment as OrderAdjustmentRecord;
4645
use craft\commerce\records\OrderNotice as OrderNoticeRecord;
4746
use craft\commerce\records\Transaction as TransactionRecord;
4847
use craft\commerce\validators\StoreCountryValidator;
@@ -1995,11 +1994,11 @@ public function getAvailableShippingMethodOptions(): array
19951994
{
19961995
// Matching will contain the core shipping methods and any plugin dynamically returned shipping methods.
19971996
$methods = Plugin::getInstance()->getShippingMethods()->getMatchingShippingMethods($this);
1998-
$matchingMethodHandles = ArrayHelper::getColumn($methods, 'handle');
1997+
$matchingMethodHandles = ArrayHelper::getColumn($methods, fn(ShippingMethodInterface $sm) => $sm->getHandle());
19991998

20001999
// Get all regular methods and add them to the list, for use only when the order is complete.
20012000
if ($this->isCompleted) {
2002-
$allShippingMethods = ArrayHelper::index(Plugin::getInstance()->getShippingMethods()->getAllShippingMethods(), 'handle');
2001+
$allShippingMethods = ArrayHelper::index(Plugin::getInstance()->getShippingMethods()->getAllShippingMethods(), fn(ShippingMethodInterface $sm) => $sm->getHandle());
20032002
$methods = ArrayHelper::merge($allShippingMethods, $methods);
20042003
}
20052004

@@ -3402,11 +3401,6 @@ public function getMetadata(): array
34023401
*/
34033402
private function _saveAdjustments(): void
34043403
{
3405-
/** @var null|array|OrderAdjustmentRecord[] $previousAdjustments */
3406-
$previousAdjustments = OrderAdjustmentRecord::find()
3407-
->where(['orderId' => $this->id])
3408-
->all();
3409-
34103404
$newAdjustmentIds = [];
34113405

34123406
foreach ($this->getAdjustments() as $adjustment) {
@@ -3416,12 +3410,6 @@ private function _saveAdjustments(): void
34163410
$adjustment->orderId = $this->id;
34173411
}
34183412

3419-
foreach ($previousAdjustments as $previousAdjustment) {
3420-
if (!in_array($previousAdjustment->id, $newAdjustmentIds, false)) {
3421-
$previousAdjustment->delete();
3422-
}
3423-
}
3424-
34253413
// Make sure all other adjustments have been cleaned up.
34263414
Db::delete(
34273415
Table::ORDERADJUSTMENTS,

src/elements/Product.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -889,6 +889,15 @@ public function afterSave(bool $isNew): void
889889
$record->defaultWidth = $defaultVariant->width ?? 0;
890890
$record->defaultWeight = $defaultVariant->weight ?? 0;
891891

892+
// Make sure to update the object
893+
$this->defaultVariantId = $defaultVariant->id ?? null;
894+
$this->defaultSku = $defaultVariant->skuAsText ?? '';
895+
$this->defaultPrice = $defaultVariant->price ?? 0.0;
896+
$this->defaultHeight = $defaultVariant->height ?? 0;
897+
$this->defaultLength = $defaultVariant->length ?? 0;
898+
$this->defaultWidth = $defaultVariant->width ?? 0;
899+
$this->defaultWeight = $defaultVariant->weight ?? 0;
900+
892901
// We want to always have the same date as the element table, based on the logic for updating these in the element service i.e resaving
893902
$record->dateUpdated = $this->dateUpdated;
894903
$record->dateCreated = $this->dateCreated;

src/elements/Variant.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
use craft\elements\conditions\ElementConditionInterface;
3131
use craft\gql\types\DateTime;
3232
use craft\helpers\ArrayHelper;
33+
use craft\helpers\Db;
3334
use craft\helpers\Html;
3435
use craft\models\FieldLayout;
3536
use Throwable;
@@ -1006,6 +1007,19 @@ public function afterSave(bool $isNew): void
10061007
}
10071008

10081009
$record->save(false);
1010+
1011+
// Fallback updating of default variant data if the variant is being saved in isolation
1012+
if ($this->duplicateOf === null && $this->isDefault) {
1013+
Db::update(Table::PRODUCTS, [
1014+
'defaultVariantId' => $this->id,
1015+
'defaultSku' => $this->getSkuAsText(),
1016+
'defaultPrice' => $this->price ?? 0.0,
1017+
'defaultHeight' => $this->height ?? 0,
1018+
'defaultLength' => $this->length ?? 0,
1019+
'defaultWidth' => $this->width ?? 0,
1020+
'defaultWeight' => $this->weight ?? 0,
1021+
], ['id' => $this->productId]);
1022+
}
10091023
}
10101024

10111025
parent::afterSave($isNew);
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
namespace craft\commerce\migrations;
4+
5+
use craft\commerce\db\Table;
6+
use craft\commerce\elements\Order;
7+
use craft\db\Migration;
8+
9+
/**
10+
* m250210_125139_fix_cart_recalculation_modes migration.
11+
*/
12+
class m250210_125139_fix_cart_recalculation_modes extends Migration
13+
{
14+
/**
15+
* @inheritdoc
16+
*/
17+
public function safeUp(): bool
18+
{
19+
$this->update(Table::ORDERS, ['recalculationMode' => Order::RECALCULATION_MODE_ALL], [
20+
'recalculationMode' => Order::RECALCULATION_MODE_NONE,
21+
'isCompleted' => false,
22+
], [], false);
23+
24+
return true;
25+
}
26+
27+
/**
28+
* @inheritdoc
29+
*/
30+
public function safeDown(): bool
31+
{
32+
echo "m250210_125139_fix_cart_recalculation_modes cannot be reverted.\n";
33+
return false;
34+
}
35+
}

src/models/LineItem.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -610,10 +610,16 @@ public function populateFromPurchasable(PurchasableInterface $purchasable): void
610610
$ignoreSales = false;
611611
foreach (Plugin::getInstance()->getDiscounts()->getAllActiveDiscounts($this->getOrder()) as $discount) {
612612
if (Plugin::getInstance()->getDiscounts()->matchLineItem($this, $discount, true)) {
613+
// Break if matched discount is set to ignore sales.
613614
$ignoreSales = $discount->ignoreSales;
614615
if ($ignoreSales) {
615616
break;
616617
}
618+
619+
// Break if matched discount is set to not apply any subsequent discounts.
620+
if ($discount->stopProcessing) {
621+
break;
622+
}
617623
}
618624
}
619625

src/models/OrderHistory.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class OrderHistory extends Model
5656
/**
5757
* @var int|null User ID
5858
*/
59-
public ?int $userId;
59+
public ?int $userId = null;
6060

6161
/**
6262
* @var string|null User name or email

src/models/TaxRate.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,13 +225,13 @@ public function getIsEverywhere(): bool
225225
*/
226226
public function getIsVat(): bool
227227
{
228-
Craft::$app->getDeprecator()->log(__METHOD__, 'TaxRate::setIsVat() is deprecated.');
229-
228+
// Don't throw deprecation log as `isVat` is still set as an attribute so will be called when the model is serialized.
230229
return $this->hasTaxIdValidators();
231230
}
232231

233232
/**
234233
* @param bool $isVat
234+
* @throws DeprecationException
235235
* @deprecated in 4.8.0.
236236
*/
237237
public function setIsVat(bool $isVat): void

0 commit comments

Comments
 (0)