Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions changelog/_unreleased/2025-02-07-add-additiona-transition.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Changelog Entry for Migration 1738955309

**Summary:**
Added additional transitions for the "paid" status in the Order Transaction State Machine to resolve an inconsistency. According to the documentation, the action "paid" should be used to mark an order as fully paid. However, only the legacy action "pay" was available. This migration adds the following transitions without removing the legacy "pay" transition:

- Transition from `reminded` to `paid_partially` using action "paid_partially".
- Transition from `reminded` to `paid` using action "paid".
- Transition from `paid_partially` to `paid` using action "paid".

**Reason:**
This change ensures that the documented action "paid" is available for transitioning orders to a fully paid state, improving consistency across the platform while maintaining backward compatibility.

**Impact:**
The migration does not remove any existing transitions; it only adds new ones if they are not already present. All environments will receive this update automatically during the migration process.

Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
<?php declare(strict_types=1);

namespace Shopware\Core\Migration\V6_6;

use Doctrine\DBAL\Connection;
use Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionStates;
use Shopware\Core\Defaults;
use Shopware\Core\Framework\Log\Package;
use Shopware\Core\Framework\Migration\MigrationStep;
use Shopware\Core\Framework\Uuid\Uuid;

#[Package('core')]
class Migration1738955309AddAdditionalPaidTransition extends MigrationStep
{
public function getCreationTimestamp(): int
{
return 1738955309;
}

public function update(Connection $connection): void
{
$stateMachineId = (string) $connection->fetchOne(
'SELECT `id` FROM `state_machine`
WHERE `technical_name` = :technical_name LIMIT 1',
['technical_name' => OrderTransactionStates::STATE_MACHINE]
);

$statePaidPartiallyId = (string) $connection->fetchOne(
'SELECT `id` FROM `state_machine_state`
WHERE `state_machine_id` = :stateMachineId
AND `technical_name` = :technicalName
LIMIT 1',
[
'stateMachineId' => $stateMachineId,
'technicalName' => 'paid_partially',
]
);

$statePaidId = (string) $connection->fetchOne(
'SELECT `id` FROM `state_machine_state`
WHERE `state_machine_id` = :stateMachineId
AND `technical_name` = :technicalName
LIMIT 1',
[
'stateMachineId' => $stateMachineId,
'technicalName' => 'paid',
]
);

$remindedId = (string) $connection->fetchOne(
'SELECT `id` FROM `state_machine_state`
WHERE `state_machine_id` = :stateMachineId
AND `technical_name` = :technicalName
LIMIT 1',
[
'stateMachineId' => $stateMachineId,
'technicalName' => 'reminded',
]
);

$existingTransition1 = $connection->fetchOne(
'SELECT COUNT(*) FROM `state_machine_transition`
WHERE `state_machine_id` = :stateMachineId
AND `from_state_id` = :fromStateId
AND `to_state_id` = :toStateId
AND `action_name` = :actionName',
[
'stateMachineId' => $stateMachineId,
'fromStateId' => $remindedId,
'toStateId' => $statePaidPartiallyId,
'actionName' => 'paid_partially',
]
);
if ((int)$existingTransition1 === 0) {
$connection->insert('state_machine_transition', [
'id' => Uuid::randomBytes(),
'state_machine_id' => $stateMachineId,
'action_name' => 'paid_partially',
'from_state_id' => $remindedId,
'to_state_id' => $statePaidPartiallyId,
'created_at' => (new \DateTime())->format(Defaults::STORAGE_DATE_TIME_FORMAT),
]);
}

$existingTransition2 = $connection->fetchOne(
'SELECT COUNT(*) FROM `state_machine_transition`
WHERE `state_machine_id` = :stateMachineId
AND `from_state_id` = :fromStateId
AND `to_state_id` = :toStateId
AND `action_name` = :actionName',
[
'stateMachineId' => $stateMachineId,
'fromStateId' => $remindedId,
'toStateId' => $statePaidId,
'actionName' => 'paid',
]
);
if ((int)$existingTransition2 === 0) {
$connection->insert('state_machine_transition', [
'id' => Uuid::randomBytes(),
'state_machine_id' => $stateMachineId,
'action_name' => 'paid',
'from_state_id' => $remindedId,
'to_state_id' => $statePaidId,
'created_at' => (new \DateTime())->format(Defaults::STORAGE_DATE_TIME_FORMAT),
]);
}

$existingTransition3 = $connection->fetchOne(
'SELECT COUNT(*) FROM `state_machine_transition`
WHERE `state_machine_id` = :stateMachineId
AND `from_state_id` = :fromStateId
AND `to_state_id` = :toStateId
AND `action_name` = :actionName',
[
'stateMachineId' => $stateMachineId,
'fromStateId' => $statePaidPartiallyId,
'toStateId' => $statePaidId,
'actionName' => 'paid',
]
);
if ((int)$existingTransition3 === 0) {
$connection->insert('state_machine_transition', [
'id' => Uuid::randomBytes(),
'state_machine_id' => $stateMachineId,
'action_name' => 'paid',
'from_state_id' => $statePaidPartiallyId,
'to_state_id' => $statePaidId,
'created_at' => (new \DateTime())->format(Defaults::STORAGE_DATE_TIME_FORMAT),
]);
}
}

public function updateDestructive(Connection $connection): void
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<?php declare(strict_types=1);

namespace Shopware\Core\Migration\Test\V6_6;

use Doctrine\DBAL\Connection;
use PHPUnit\Framework\TestCase;
use Shopware\Core\Migration\V6_6\Migration1738955309AddAdditionalPaidTransition;
use Shopware\Core\Framework\Test\TestCaseBase\KernelTestBehaviour;

class Migration1738955309AddAdditionalPaidTransitionTest extends TestCase
{
use KernelTestBehaviour;

public function testMigrationAddsExpectedTransitions(): void
{
$connection = $this->getContainer()->get(Connection::class);

$stateMachineId = (string)$connection->fetchOne(
'SELECT `id` FROM `state_machine` WHERE `technical_name` = "order_transaction.state" LIMIT 1'
);

$remindedId = (string)$connection->fetchOne(
'SELECT `id` FROM `state_machine_state`
WHERE `state_machine_id` = :stateMachineId AND `technical_name` = "reminded" LIMIT 1',
['stateMachineId' => $stateMachineId]
);

$statePaidPartiallyId = (string)$connection->fetchOne(
'SELECT `id` FROM `state_machine_state`
WHERE `state_machine_id` = :stateMachineId AND `technical_name` = "paid_partially" LIMIT 1',
['stateMachineId' => $stateMachineId]
);

$statePaidId = (string)$connection->fetchOne(
'SELECT `id` FROM `state_machine_state`
WHERE `state_machine_id` = :stateMachineId AND `technical_name` = "paid" LIMIT 1',
['stateMachineId' => $stateMachineId]
);

$connection->executeUpdate(
'DELETE FROM state_machine_transition
WHERE state_machine_id = :stateMachineId
AND action_name IN ("paid_partially", "paid")
AND ((from_state_id = :remindedId AND to_state_id IN (:statePaidPartiallyId, :statePaidId))
OR (from_state_id = :statePaidPartiallyId AND to_state_id = :statePaidId))',
[
'stateMachineId' => $stateMachineId,
'remindedId' => $remindedId,
'statePaidPartiallyId'=> $statePaidPartiallyId,
'statePaidId' => $statePaidId,
]
);

$migration = new Migration1738955309AddAdditionalPaidTransition();
$migration->update($connection);

$countCase1 = (int)$connection->fetchOne(
'SELECT COUNT(*) FROM state_machine_transition
WHERE state_machine_id = :stateMachineId
AND action_name = "paid_partially"
AND from_state_id = :remindedId
AND to_state_id = :statePaidPartiallyId',
[
'stateMachineId' => $stateMachineId,
'remindedId' => $remindedId,
'statePaidPartiallyId'=> $statePaidPartiallyId,
]
);
$this->assertGreaterThanOrEqual(1, $countCase1, 'Expected a transition from reminded to paid_partially with action "paid_partially" to be added.');

$countCase2 = (int)$connection->fetchOne(
'SELECT COUNT(*) FROM state_machine_transition
WHERE state_machine_id = :stateMachineId
AND action_name = "paid"
AND from_state_id = :remindedId
AND to_state_id = :statePaidId',
[
'stateMachineId' => $stateMachineId,
'remindedId' => $remindedId,
'statePaidId' => $statePaidId,
]
);
$this->assertGreaterThanOrEqual(1, $countCase2, 'Expected a transition from reminded to paid with action "paid" to be added.');

$countCase3 = (int)$connection->fetchOne(
'SELECT COUNT(*) FROM state_machine_transition
WHERE state_machine_id = :stateMachineId
AND action_name = "paid"
AND from_state_id = :statePaidPartiallyId
AND to_state_id = :statePaidId',
[
'stateMachineId' => $stateMachineId,
'statePaidPartiallyId'=> $statePaidPartiallyId,
'statePaidId' => $statePaidId,
]
);
$this->assertGreaterThanOrEqual(1, $countCase3, 'Expected a transition from paid_partially to paid with action "paid" to be added.');
}
}