fix(casts): update OrderReferenceCast to use base58 encoding
Refactor OrderReferenceCast to utilize base58 encoding for order references instead of UUID. This change improves compatibility with the new OrderReference implementation.
This commit is contained in:
parent
91a82af969
commit
713c937890
10 changed files with 159 additions and 27 deletions
|
|
@ -6,7 +6,6 @@ namespace App\Casts;
|
|||
|
||||
use Domain\Models\ValueObjects\OrderReference;
|
||||
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
|
||||
/**
|
||||
* @implements CastsAttributes<OrderReference,OrderReference>
|
||||
|
|
@ -20,7 +19,7 @@ class OrderReferenceCast implements CastsAttributes
|
|||
throw new \UnexpectedValueException('OrderReference cannot be null.');
|
||||
}
|
||||
|
||||
return new OrderReference(Uuid::fromString($value));
|
||||
return OrderReference::fromString($value);
|
||||
}
|
||||
|
||||
/** @param array<string, mixed> $attributes */
|
||||
|
|
@ -30,6 +29,6 @@ class OrderReferenceCast implements CastsAttributes
|
|||
throw new \UnexpectedValueException('The given value is not an instance of OrderReference.');
|
||||
}
|
||||
|
||||
return $value->value->toString();
|
||||
return (string) $value;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ declare(strict_types=1);
|
|||
namespace Domain\Models\ValueObjects;
|
||||
|
||||
use Ramsey\Uuid\UuidInterface;
|
||||
use Shared\Exceptions\InvalidUuidException;
|
||||
use Shared\Helpers\UuidHelper;
|
||||
|
||||
final readonly class OrderReference implements \Stringable
|
||||
|
|
@ -17,9 +18,29 @@ final readonly class OrderReference implements \Stringable
|
|||
}
|
||||
}
|
||||
|
||||
public static function fromString(string $value): self
|
||||
{
|
||||
if (UuidHelper::isValid($value)) {
|
||||
return new self(\Ramsey\Uuid\Uuid::fromString($value));
|
||||
}
|
||||
|
||||
return self::fromBase58($value);
|
||||
}
|
||||
|
||||
public static function fromBase58(string $base58): self
|
||||
{
|
||||
try {
|
||||
$uuid = UuidHelper::fromBase58($base58);
|
||||
} catch (InvalidUuidException) {
|
||||
throw new \DomainException('Order reference must be a valid base-58 string');
|
||||
}
|
||||
|
||||
return new self($uuid);
|
||||
}
|
||||
|
||||
#[\Override]
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->value->toString();
|
||||
return UuidHelper::toBase58($this->value);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
{{ __('Hello') }},
|
||||
|
||||
{{ __('The order') }} **{{ $order->reference->value }}** {{ __('from') }} {{ $order->employee->firstname }} {{ Str::upper($order->employee->lastname) }} ({{ $order->employee->matricule }}) {{ __('is confirmed.') }}
|
||||
{{ __('The order') }} **{{ $order->reference }}** {{ __('from') }} {{ $order->employee->firstname }} {{ Str::upper($order->employee->lastname) }} ({{ $order->employee->matricule }}) {{ __('is confirmed.') }}
|
||||
|
||||
<x-mail::table>
|
||||
| {{ __('Product') }} | {{ __('Quantity') }} | {{ __('Total TTC') }} |
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
{{ __('Hello') }} {{ $order->employee->firstname }} {{ Str::upper($order->employee->lastname) }} ({{ $order->employee->matricule }}),
|
||||
|
||||
{{ __('Your order') }} **{{ $order->reference->value }}** {{ __('is confirmed.') }}
|
||||
{{ __('Your order') }} **{{ $order->reference }}** {{ __('is confirmed.') }}
|
||||
|
||||
<x-mail::table>
|
||||
| {{ __('Product') }} | {{ __('Quantity') }} | {{ __('Price per kilo TTC') }} | {{ __('Total TTC') }} |
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface;
|
|||
use Ramsey\Uuid\Uuid;
|
||||
use Ramsey\Uuid\UuidInterface;
|
||||
use Shared\Exceptions\InvalidUuidException;
|
||||
use Symfony\Component\Uid\Uuid as SymfonyUuid;
|
||||
|
||||
final readonly class UuidHelper
|
||||
{
|
||||
|
|
@ -16,6 +17,31 @@ final readonly class UuidHelper
|
|||
// Static class
|
||||
}
|
||||
|
||||
public static function isValid(string $uuid): bool
|
||||
{
|
||||
return Uuid::isValid($uuid);
|
||||
}
|
||||
|
||||
public static function toBase58(UuidInterface $uuid): string
|
||||
{
|
||||
return SymfonyUuid::fromString($uuid->toString())->toBase58();
|
||||
}
|
||||
|
||||
public static function fromBase58(string $base58): UuidInterface
|
||||
{
|
||||
$base58 = trim($base58);
|
||||
|
||||
if ($base58 === '' || ! preg_match('/^[1-9A-HJ-NP-Za-km-z]{21,22}$/', $base58)) {
|
||||
throw InvalidUuidException::forValue($base58);
|
||||
}
|
||||
|
||||
try {
|
||||
return Uuid::fromString(SymfonyUuid::fromBase58($base58)->toString());
|
||||
} catch (\Throwable) {
|
||||
throw InvalidUuidException::forValue($base58);
|
||||
}
|
||||
}
|
||||
|
||||
public static function isV4(UuidInterface $uuid): bool
|
||||
{
|
||||
return self::version($uuid) === 4;
|
||||
|
|
|
|||
|
|
@ -93,13 +93,14 @@ describe('Bo\OrdersController', function (): void {
|
|||
it('can filter index by search term', function (): void {
|
||||
/** @var \Tests\TestCase $this */
|
||||
// GIVEN
|
||||
$refUuid = Uuid::uuid7();
|
||||
$ref = $refUuid->toString();
|
||||
$shop = Shop::factory()->create(['name' => 'UniqueShopSearch']);
|
||||
$refUuid = Uuid::uuid7();
|
||||
$reference = new OrderReference($refUuid);
|
||||
$ref = (string) $reference;
|
||||
$shop = Shop::factory()->create(['name' => 'UniqueShopSearch']);
|
||||
Order::forceCreate([
|
||||
'id' => Uuid::uuid7()->toString(),
|
||||
'shop_id' => $shop->id,
|
||||
'reference' => new OrderReference($refUuid),
|
||||
'reference' => $reference,
|
||||
'status' => OrderStatus::VALIDATED->value,
|
||||
'total' => new Money(1500, new Currency('EUR')),
|
||||
'employee' => new OrderEmployee(new Matricule('1000102'), 'Bob', 'Jones', new ShopperEstablishmentCode('FAC01'), new ShopperSiteCode('SITE'), new ShopperServiceCode('101')),
|
||||
|
|
|
|||
|
|
@ -115,13 +115,14 @@ describe('OrderController', function () {
|
|||
'updated_at' => CarbonImmutable::now(),
|
||||
]);
|
||||
|
||||
$shop = Shop::factory()->create();
|
||||
$refUuid = Uuid::uuid7();
|
||||
$ref = $refUuid->toString();
|
||||
$shop = Shop::factory()->create();
|
||||
$refUuid = Uuid::uuid7();
|
||||
$reference = new OrderReference($refUuid);
|
||||
$ref = (string) $reference;
|
||||
Order::forceCreate([
|
||||
'id' => Uuid::uuid7()->toString(),
|
||||
'shop_id' => $shop->id,
|
||||
'reference' => new OrderReference($refUuid),
|
||||
'reference' => $reference,
|
||||
'status' => OrderStatus::VALIDATED->value,
|
||||
'total' => new Money(5000, new Currency('EUR')),
|
||||
'employee' => new OrderEmployee(new Matricule('8888001'), 'Jean', 'Dupont', new ShopperEstablishmentCode('FAC01'), new ShopperSiteCode('SITE'), new ShopperServiceCode('101')),
|
||||
|
|
@ -197,13 +198,14 @@ describe('OrderController', function () {
|
|||
'updated_at' => CarbonImmutable::now(),
|
||||
]);
|
||||
|
||||
$shop = Shop::factory()->create();
|
||||
$refUuid = Uuid::uuid7();
|
||||
$ref = $refUuid->toString();
|
||||
$order = Order::forceCreate([
|
||||
$shop = Shop::factory()->create();
|
||||
$refUuid = Uuid::uuid7();
|
||||
$reference = new OrderReference($refUuid);
|
||||
$ref = (string) $reference;
|
||||
$order = Order::forceCreate([
|
||||
'id' => Uuid::uuid7()->toString(),
|
||||
'shop_id' => $shop->id,
|
||||
'reference' => new OrderReference($refUuid),
|
||||
'reference' => $reference,
|
||||
'status' => OrderStatus::VALIDATED->value,
|
||||
'total' => new Money(5000, new Currency('EUR')),
|
||||
'employee' => new OrderEmployee(new Matricule('8888002'), 'Paul', 'Martin', new ShopperEstablishmentCode('FAC01'), new ShopperSiteCode('SITE'), new ShopperServiceCode('101')),
|
||||
|
|
|
|||
|
|
@ -501,7 +501,7 @@ describe('TunnelController', function (): void {
|
|||
]);
|
||||
|
||||
// THEN
|
||||
$response->assertRedirectToRoute('fo.sales.confirmation.show-confirmed', $orderReference->value);
|
||||
$response->assertRedirectToRoute('fo.sales.confirmation.show-confirmed', (string) $orderReference);
|
||||
});
|
||||
|
||||
it('redirects back with message when limit exception occurs on confirmation submit', function (): void {
|
||||
|
|
@ -596,7 +596,7 @@ describe('TunnelController', function (): void {
|
|||
$order->save();
|
||||
|
||||
// WHEN
|
||||
$response = $this->get('/commande/confirmation/' . $orderReference->value);
|
||||
$response = $this->get('/commande/confirmation/' . (string) $orderReference);
|
||||
|
||||
// THEN
|
||||
$response->assertOk()
|
||||
|
|
|
|||
|
|
@ -6,8 +6,25 @@ use App\Casts\OrderReferenceCast;
|
|||
use Domain\Models\ValueObjects\OrderReference;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use Shared\Helpers\UuidHelper;
|
||||
|
||||
it('gets a reference', function () {
|
||||
// GIVEN
|
||||
$cast = new OrderReferenceCast();
|
||||
$model = \Mockery::mock(Model::class);
|
||||
$uuid = Uuid::uuid7();
|
||||
$value = UuidHelper::toBase58($uuid);
|
||||
|
||||
// WHEN
|
||||
$reference = $cast->get($model, 'reference', $value, []);
|
||||
|
||||
// THEN
|
||||
expect($reference)->toBeInstanceOf(OrderReference::class)
|
||||
->and((string) $reference)->toBe($value)
|
||||
->and($reference->value->equals($uuid))->toBeTrue();
|
||||
});
|
||||
|
||||
it('gets a reference from raw uuid string', function () {
|
||||
// GIVEN
|
||||
$cast = new OrderReferenceCast();
|
||||
$model = \Mockery::mock(Model::class);
|
||||
|
|
@ -19,7 +36,7 @@ it('gets a reference', function () {
|
|||
|
||||
// THEN
|
||||
expect($reference)->toBeInstanceOf(OrderReference::class)
|
||||
->and((string) $reference)->toBe($value)
|
||||
->and((string) $reference)->toBe(UuidHelper::toBase58($uuid))
|
||||
->and($reference->value->equals($uuid))->toBeTrue();
|
||||
});
|
||||
|
||||
|
|
@ -49,7 +66,7 @@ it('throws exception when setting invalid reference type', function () {
|
|||
// GIVEN
|
||||
$cast = new OrderReferenceCast();
|
||||
$model = \Mockery::mock(Model::class);
|
||||
$value = Uuid::uuid7()->toString();
|
||||
$value = UuidHelper::toBase58(Uuid::uuid7());
|
||||
|
||||
// WHEN
|
||||
$cast->set($model, 'reference', $value, []);
|
||||
|
|
@ -71,5 +88,5 @@ it('sets a reference', function () {
|
|||
$value = $cast->set($model, 'reference', $reference, []);
|
||||
|
||||
// THEN
|
||||
expect($value)->toBe($uuid->toString());
|
||||
expect($value)->toBe(UuidHelper::toBase58($uuid));
|
||||
});
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ namespace Tests\Unit\Domain\Models\ValueObjects;
|
|||
use Domain\Models\ValueObjects\OrderReference;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use Ramsey\Uuid\UuidInterface;
|
||||
use Shared\Helpers\UuidHelper;
|
||||
|
||||
describe('OrderReference', function () {
|
||||
function getNewOrderReference(UuidInterface $value): OrderReference
|
||||
|
|
@ -22,9 +23,51 @@ describe('OrderReference', function () {
|
|||
$vo = getNewOrderReference($uuidV7);
|
||||
|
||||
// THEN
|
||||
expect($vo)->toBeInstanceOf(OrderReference::class);
|
||||
expect((string) $vo)->toBe($uuidV7->toString());
|
||||
expect($vo->value)->toBe($uuidV7);
|
||||
expect($vo)->toBeInstanceOf(OrderReference::class)
|
||||
->and((string) $vo)->toBe(UuidHelper::toBase58($uuidV7))
|
||||
->and($vo->value)->toBe($uuidV7);
|
||||
});
|
||||
|
||||
it('can instantiate from a valid base-58 UUID v7 string', function () {
|
||||
// GIVEN
|
||||
$uuidV7 = Uuid::uuid7();
|
||||
$base58 = UuidHelper::toBase58($uuidV7);
|
||||
|
||||
// WHEN
|
||||
$vo = OrderReference::fromBase58($base58);
|
||||
|
||||
// THEN
|
||||
expect($vo)->toBeInstanceOf(OrderReference::class)
|
||||
->and((string) $vo)->toBe($base58)
|
||||
->and($vo->value->equals($uuidV7))->toBeTrue();
|
||||
});
|
||||
|
||||
it('can instantiate from a valid UUID v7 string via fromString', function () {
|
||||
// GIVEN
|
||||
$uuidV7 = Uuid::uuid7();
|
||||
$uuidString = $uuidV7->toString();
|
||||
|
||||
// WHEN
|
||||
$vo = OrderReference::fromString($uuidString);
|
||||
|
||||
// THEN
|
||||
expect($vo)->toBeInstanceOf(OrderReference::class)
|
||||
->and((string) $vo)->toBe(UuidHelper::toBase58($uuidV7))
|
||||
->and($vo->value->equals($uuidV7))->toBeTrue();
|
||||
});
|
||||
|
||||
it('can instantiate from a valid base-58 string via fromString', function () {
|
||||
// GIVEN
|
||||
$uuidV7 = Uuid::uuid7();
|
||||
$base58 = UuidHelper::toBase58($uuidV7);
|
||||
|
||||
// WHEN
|
||||
$vo = OrderReference::fromString($base58);
|
||||
|
||||
// THEN
|
||||
expect($vo)->toBeInstanceOf(OrderReference::class)
|
||||
->and((string) $vo)->toBe($base58)
|
||||
->and($vo->value->equals($uuidV7))->toBeTrue();
|
||||
});
|
||||
|
||||
it('throws exception if provided UUID is not v7', function () {
|
||||
|
|
@ -37,4 +80,27 @@ describe('OrderReference', function () {
|
|||
// THEN
|
||||
expect($action)->toThrow(\DomainException::class, 'value must be a valid UUID v7');
|
||||
});
|
||||
|
||||
it('throws exception if base-58 string is invalid', function () {
|
||||
// GIVEN
|
||||
$invalidBase58 = 'invalid-base58-string!';
|
||||
|
||||
// WHEN
|
||||
$action = fn () => OrderReference::fromBase58($invalidBase58);
|
||||
|
||||
// THEN
|
||||
expect($action)->toThrow(\DomainException::class, 'Order reference must be a valid base-58 string');
|
||||
});
|
||||
|
||||
it('throws exception if base-58 string is not from a UUID v7', function () {
|
||||
// GIVEN
|
||||
$uuidV4 = Uuid::uuid4();
|
||||
$base58 = UuidHelper::toBase58($uuidV4);
|
||||
|
||||
// WHEN
|
||||
$action = fn () => OrderReference::fromBase58($base58);
|
||||
|
||||
// THEN
|
||||
expect($action)->toThrow(\DomainException::class, 'value must be a valid UUID v7');
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue