fix: 🐛 add Quantity and WarningQuantity as VO
This commit is contained in:
parent
be382a53c0
commit
80da7ec333
13 changed files with 188 additions and 52 deletions
|
|
@ -13,8 +13,10 @@ use Domain\Models\ValueObjects\MoneyAmount;
|
|||
use Domain\Models\ValueObjects\Period;
|
||||
use Domain\Models\ValueObjects\ProcessingCode;
|
||||
use Domain\Models\ValueObjects\RequestedCoupon\RequestedCouponId;
|
||||
use Domain\Models\ValueObjects\RequestedCoupon\RequestedCouponQuantity;
|
||||
use Shared\DDD\Models\AggregateRoot;
|
||||
use Shared\DDD\Models\HasTimestampIdentifier;
|
||||
use Domain\Models\ValueObjects\WarningThresholdQuantity;
|
||||
|
||||
/**
|
||||
* @implements \Shared\DDD\Models\AggregateRoot<\Domain\Models\ValueObjects\RequestedCoupon\RequestedCouponId>
|
||||
|
|
@ -25,8 +27,8 @@ final readonly class RequestedCoupon implements AggregateRoot, HasTimestampIdent
|
|||
public RequestedCouponId $id,
|
||||
public CouponName $name,
|
||||
public CouponProductName $productName,
|
||||
public int $quantity,
|
||||
public int $warningThresholdQuantity,
|
||||
public RequestedCouponQuantity $quantity,
|
||||
public WarningThresholdQuantity $warningThresholdQuantity,
|
||||
public Period $period,
|
||||
public MoneyAmount $moneyAmount,
|
||||
public ProcessingCode $processingCode,
|
||||
|
|
@ -56,8 +58,8 @@ final readonly class RequestedCoupon implements AggregateRoot, HasTimestampIdent
|
|||
RequestedCouponId $id,
|
||||
CouponName $name,
|
||||
CouponProductName $productName,
|
||||
int $quantity,
|
||||
int $warningThresholdQuantity,
|
||||
RequestedCouponQuantity $quantity,
|
||||
WarningThresholdQuantity $warningThresholdQuantity,
|
||||
Period $period,
|
||||
MoneyAmount $moneyAmount,
|
||||
ProcessingCode $processingCode,
|
||||
|
|
|
|||
|
|
@ -7,17 +7,15 @@ namespace Domain\Models\ValueObjects\Campaign;
|
|||
use Domain\Models\ValueObjects\PrintRules;
|
||||
use Domain\Models\ValueObjects\ProcessingCode;
|
||||
use Domain\Models\ValueObjects\Stock\StockId;
|
||||
use Domain\Models\ValueObjects\WarningThresholdQuantity;
|
||||
|
||||
final readonly class CampaignCoupon
|
||||
{
|
||||
public function __construct(
|
||||
public ProcessingCode $code,
|
||||
public StockId $qty,
|
||||
public int $warningThresholdQty,
|
||||
public WarningThresholdQuantity $warningThresholdQty,
|
||||
public ?PrintRules $printRules = null,
|
||||
) {
|
||||
if ($this->warningThresholdQty <= 0) {
|
||||
throw new \DomainException('Campaign Coupon warningThresholdQty must be positive.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Domain\Models\ValueObjects\RequestedCoupon;
|
||||
|
||||
final readonly class RequestedCouponQuantity
|
||||
{
|
||||
public function __construct(
|
||||
public int $value,
|
||||
) {
|
||||
if ($this->value <= 0) {
|
||||
throw new \DomainException('Quantity should be more than 0.');
|
||||
}
|
||||
}
|
||||
}
|
||||
16
src/Domain/Models/ValueObjects/WarningThresholdQuantity.php
Normal file
16
src/Domain/Models/ValueObjects/WarningThresholdQuantity.php
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Domain\Models\ValueObjects;
|
||||
|
||||
final readonly class WarningThresholdQuantity
|
||||
{
|
||||
public function __construct(
|
||||
public int $value,
|
||||
) {
|
||||
if ($this->value < 0) {
|
||||
throw new \DomainException('Warning threshold quantity cannot be negative.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -35,6 +35,8 @@ use Domain\Models\ValueObjects\PicturePath;
|
|||
use Domain\Models\ValueObjects\PrintRules;
|
||||
use Domain\Models\ValueObjects\ProcessingCode;
|
||||
use Domain\Models\ValueObjects\RequestedCoupon\RequestedCouponId;
|
||||
use Domain\Models\ValueObjects\RequestedCoupon\RequestedCouponQuantity;
|
||||
use Domain\Models\ValueObjects\WarningThresholdQuantity;
|
||||
use Domain\Ports\Repositories\BrandRepository;
|
||||
use Domain\Ports\Repositories\CampaignRequestRepository;
|
||||
use Shared\DDD\UseCases\Input as BaseInput;
|
||||
|
|
@ -52,8 +54,8 @@ describe('find campaign request use case', function (): void {
|
|||
RequestedCouponId::generate(),
|
||||
new CouponName('Coupon A'),
|
||||
new CouponProductName('Product A'),
|
||||
100,
|
||||
10,
|
||||
new RequestedCouponQuantity(100),
|
||||
new WarningThresholdQuantity(10),
|
||||
new Period(new DateTime('2026-01-01'), new DateTime('2026-02-01')),
|
||||
new MoneyAmount(new Money(Currency::EUR, 300)),
|
||||
new ProcessingCode('PC1'),
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@ use Domain\Models\ValueObjects\PicturePath;
|
|||
use Domain\Models\ValueObjects\PrintRules;
|
||||
use Domain\Models\ValueObjects\ProcessingCode;
|
||||
use Domain\Models\ValueObjects\RequestedCoupon\RequestedCouponId;
|
||||
use Domain\Models\ValueObjects\RequestedCoupon\RequestedCouponQuantity;
|
||||
use Domain\Models\ValueObjects\WarningThresholdQuantity;
|
||||
use Domain\Ports\Repositories\CampaignRequestRepository;
|
||||
use Shared\DDD\UseCases\Input as BaseInput;
|
||||
use Shared\Enums\Currency;
|
||||
|
|
@ -46,8 +48,8 @@ describe('list campaigns request use case', function (): void {
|
|||
RequestedCouponId::generate(),
|
||||
new CouponName('Coupon A'),
|
||||
new CouponProductName('Product A'),
|
||||
100,
|
||||
10,
|
||||
new RequestedCouponQuantity(100),
|
||||
new WarningThresholdQuantity(10),
|
||||
new Period(new DateTime('2026-01-01'), new DateTime('2026-02-01')),
|
||||
new MoneyAmount(new Money(Currency::EUR, 300)),
|
||||
new ProcessingCode('PC1'),
|
||||
|
|
@ -60,8 +62,8 @@ describe('list campaigns request use case', function (): void {
|
|||
RequestedCouponId::generate(),
|
||||
new CouponName('Coupon B'),
|
||||
new CouponProductName('Product B'),
|
||||
100,
|
||||
10,
|
||||
new RequestedCouponQuantity(100),
|
||||
new WarningThresholdQuantity(10),
|
||||
new Period(new DateTime('2026-01-01'), new DateTime('2026-02-01')),
|
||||
new MoneyAmount(new Money(Currency::EUR, 300)),
|
||||
new ProcessingCode('PC2'),
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ use Domain\Models\ValueObjects\PicturePath;
|
|||
use Domain\Models\ValueObjects\PrintRules;
|
||||
use Domain\Models\ValueObjects\ProcessingCode;
|
||||
use Domain\Models\ValueObjects\RequestedCoupon\RequestedCouponId;
|
||||
use Domain\Models\ValueObjects\RequestedCoupon\RequestedCouponQuantity;
|
||||
use Domain\Models\ValueObjects\WarningThresholdQuantity;
|
||||
use Domain\Ports\Repositories\CampaignRequestRepository;
|
||||
use Shared\DDD\UseCases\Input as BaseInput;
|
||||
use Shared\Enums\Currency;
|
||||
|
|
@ -51,8 +53,8 @@ describe('reject campaign request use case', function (): void {
|
|||
RequestedCouponId::generate(),
|
||||
new CouponName('Coupon A'),
|
||||
new CouponProductName('Product A'),
|
||||
100,
|
||||
10,
|
||||
new RequestedCouponQuantity(100),
|
||||
new WarningThresholdQuantity(10),
|
||||
new Period(new DateTime('2026-01-01'), new DateTime('2026-02-01')),
|
||||
new MoneyAmount(new Money(Currency::EUR, 300)),
|
||||
new ProcessingCode('PC1'),
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ use Shared\ValueObjects\Email;
|
|||
use Shared\ValueObjects\Money;
|
||||
use Carbon\CarbonImmutable;
|
||||
use Domain\Models\ValueObjects\CountryAuthorized;
|
||||
use Domain\Models\ValueObjects\RequestedCoupon\RequestedCouponQuantity;
|
||||
use Domain\Models\ValueObjects\WarningThresholdQuantity;
|
||||
|
||||
covers(CampaignRequest::class);
|
||||
|
||||
|
|
@ -45,8 +47,8 @@ describe('campaign request', function (): void {
|
|||
RequestedCouponId::generate(),
|
||||
new CouponName('Coupon A'),
|
||||
new CouponProductName('Product A'),
|
||||
100,
|
||||
10,
|
||||
new RequestedCouponQuantity(100),
|
||||
new WarningThresholdQuantity(10),
|
||||
new Period(new DateTime('2026-01-01'), new DateTime('2026-02-01')),
|
||||
new MoneyAmount(new Money(Currency::EUR, 300)),
|
||||
new ProcessingCode('PC1'),
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ use Domain\Models\ValueObjects\ProcessingCode;
|
|||
use Domain\Models\ValueObjects\Stock\StockId;
|
||||
use Domain\Models\ValueObjects\Tag\TagId;
|
||||
use Domain\Models\ValueObjects\Tag\TagName;
|
||||
use Domain\Models\ValueObjects\WarningThresholdQuantity;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
|
||||
covers(Campaign::class);
|
||||
|
|
@ -43,7 +44,14 @@ describe('campaign', function (): void {
|
|||
$publication = \boolval(0);
|
||||
$printAllAtOnce = \boolval(1);
|
||||
$availableIn = new CountryAuthorized(Country::FRANCE);
|
||||
$coupons = [new CampaignCoupon(new ProcessingCode('PC1'), StockId::generate(), 100, new PrintRules(maxPerCustomer: 3))];
|
||||
$coupons = [
|
||||
new CampaignCoupon(
|
||||
new ProcessingCode('PC1'),
|
||||
StockId::generate(),
|
||||
new WarningThresholdQuantity(100),
|
||||
new PrintRules(maxPerCustomer: 3)
|
||||
)
|
||||
];
|
||||
$brand = new BrandCode('AAA01');
|
||||
|
||||
// WHEN
|
||||
|
|
@ -109,7 +117,14 @@ describe('campaign', function (): void {
|
|||
$publication = \boolval(0);
|
||||
$printAllAtOnce = \boolval(1);
|
||||
$availableIn = new CountryAuthorized(Country::FRANCE);
|
||||
$coupons = [new CampaignCoupon(new ProcessingCode('PC1'), StockId::generate(), 100, new PrintRules(maxPerCustomer: 3))];
|
||||
$coupons = [
|
||||
new CampaignCoupon(
|
||||
new ProcessingCode('PC1'),
|
||||
StockId::generate(),
|
||||
new WarningThresholdQuantity(100),
|
||||
new PrintRules(maxPerCustomer: 3)
|
||||
)
|
||||
];
|
||||
$brand = new BrandCode('AAA01');
|
||||
$updatedAt = new \DateTimeImmutable('2026-09-22 10:00:00', new \DateTimeZone('UTC'));
|
||||
|
||||
|
|
@ -139,7 +154,14 @@ describe('campaign', function (): void {
|
|||
$publication = \boolval(0);
|
||||
$printAllAtOnce = \boolval(1);
|
||||
$availableIn = new CountryAuthorized(Country::FRANCE);
|
||||
$coupons = [new CampaignCoupon(new ProcessingCode('PC1'), StockId::generate(), 100, new PrintRules(maxPerCustomer: 3))];
|
||||
$coupons = [
|
||||
new CampaignCoupon(
|
||||
new ProcessingCode('PC1'),
|
||||
StockId::generate(),
|
||||
new WarningThresholdQuantity(100),
|
||||
new PrintRules(maxPerCustomer: 3)
|
||||
)
|
||||
];
|
||||
$brand = new BrandCode('AAA01');
|
||||
|
||||
// WHEN
|
||||
|
|
@ -175,7 +197,14 @@ describe('campaign', function (): void {
|
|||
$publication = \boolval(0);
|
||||
$printAllAtOnce = \boolval(1);
|
||||
$availableIn = new CountryAuthorized(Country::FRANCE);
|
||||
$coupons = [new CampaignCoupon(new ProcessingCode('PC1'), StockId::generate(), 100, new PrintRules(maxPerCustomer: 3))];
|
||||
$coupons = [
|
||||
new CampaignCoupon(
|
||||
new ProcessingCode('PC1'),
|
||||
StockId::generate(),
|
||||
new WarningThresholdQuantity(100),
|
||||
new PrintRules(maxPerCustomer: 3)
|
||||
)
|
||||
];
|
||||
$brand = new BrandCode('AAA01');
|
||||
|
||||
// WHEN
|
||||
|
|
@ -216,7 +245,14 @@ describe('campaign', function (): void {
|
|||
\boolval(0),
|
||||
\boolval(1),
|
||||
new CountryAuthorized(Country::FRANCE),
|
||||
[new CampaignCoupon(new ProcessingCode('PC1'), StockId::generate(), 100, new PrintRules(maxPerCustomer: 3))],
|
||||
[
|
||||
new CampaignCoupon(
|
||||
new ProcessingCode('PC1'),
|
||||
StockId::generate(),
|
||||
new WarningThresholdQuantity(100),
|
||||
new PrintRules(maxPerCustomer: 3)
|
||||
)
|
||||
],
|
||||
new BrandCode('AAA01')
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ use Domain\Models\ValueObjects\Period;
|
|||
use Domain\Models\ValueObjects\PicturePath;
|
||||
use Domain\Models\ValueObjects\ProcessingCode;
|
||||
use Domain\Models\ValueObjects\RequestedCoupon\RequestedCouponId;
|
||||
use Domain\Models\ValueObjects\RequestedCoupon\RequestedCouponQuantity;
|
||||
use Domain\Models\ValueObjects\WarningThresholdQuantity;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use Shared\Enums\Currency;
|
||||
use Shared\ValueObjects\DateTime;
|
||||
|
|
@ -34,8 +36,8 @@ describe('requested coupon', function (): void {
|
|||
$id = RequestedCouponId::generate();
|
||||
$name = new CouponName('Coupon A');
|
||||
$productName = new CouponProductName('Product A');
|
||||
$quantity = 100;
|
||||
$warningThresholdQuantity = 10;
|
||||
$quantity = new RequestedCouponQuantity(100);
|
||||
$warningThresholdQuantity = new WarningThresholdQuantity(10);
|
||||
$period = new Period(new DateTime('2026-01-01'), new DateTime('2026-02-01'));
|
||||
$moneyAmount = new MoneyAmount(new Money(Currency::EUR, 300));
|
||||
$processingCode = new ProcessingCode('PC1');
|
||||
|
|
@ -83,8 +85,8 @@ describe('requested coupon', function (): void {
|
|||
RequestedCouponId::generate(),
|
||||
new CouponName('Coupon A'),
|
||||
new CouponProductName('Product A'),
|
||||
100,
|
||||
10,
|
||||
new RequestedCouponQuantity(100),
|
||||
new WarningThresholdQuantity(10),
|
||||
new Period(new DateTime('2026-01-01'), new DateTime('2026-02-01')),
|
||||
new MoneyAmount(new Money(Currency::EUR, 300)),
|
||||
new ProcessingCode('PC1'),
|
||||
|
|
@ -107,8 +109,8 @@ describe('requested coupon', function (): void {
|
|||
$id,
|
||||
new CouponName('Coupon A'),
|
||||
new CouponProductName('Product A'),
|
||||
100,
|
||||
10,
|
||||
new RequestedCouponQuantity(100),
|
||||
new WarningThresholdQuantity(10),
|
||||
new Period(new DateTime('2026-01-01'), new DateTime('2026-02-01')),
|
||||
new MoneyAmount(new Money(Currency::EUR, 300)),
|
||||
new ProcessingCode('PC1'),
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ use Domain\Models\ValueObjects\Campaign\CampaignCoupon;
|
|||
use Domain\Models\ValueObjects\PrintRules;
|
||||
use Domain\Models\ValueObjects\ProcessingCode;
|
||||
use Domain\Models\ValueObjects\Stock\StockId;
|
||||
use Domain\Models\ValueObjects\WarningThresholdQuantity;
|
||||
|
||||
covers(CampaignCoupon::class);
|
||||
|
||||
|
|
@ -17,7 +18,7 @@ describe('campaign coupon', function (): void {
|
|||
$code = new ProcessingCode('PC1');
|
||||
$qty = StockId::generate();
|
||||
$printRules = new PrintRules(maxPerCustomer: 3);
|
||||
$warningThresholdQty = 100;
|
||||
$warningThresholdQty = new WarningThresholdQuantity(100);
|
||||
|
||||
// WHEN
|
||||
$campaignCoupon = new CampaignCoupon($code, $qty, $warningThresholdQty, $printRules);
|
||||
|
|
@ -33,7 +34,7 @@ describe('campaign coupon', function (): void {
|
|||
// GIVEN
|
||||
$code = new ProcessingCode('PC1');
|
||||
$qty = StockId::generate();
|
||||
$warningThresholdQty = 100;
|
||||
$warningThresholdQty = new WarningThresholdQuantity(100);
|
||||
|
||||
// WHEN
|
||||
$campaignCoupon = new CampaignCoupon($code, $qty, $warningThresholdQty);
|
||||
|
|
@ -43,25 +44,4 @@ describe('campaign coupon', function (): void {
|
|||
->and($campaignCoupon->qty)->toBe($qty)
|
||||
->and($campaignCoupon->warningThresholdQty)->toBe($warningThresholdQty);
|
||||
});
|
||||
|
||||
it('rejects invalid campaign coupon', function (): void {
|
||||
// GIVEN
|
||||
$code = new ProcessingCode('PC1');
|
||||
$qty = StockId::generate();
|
||||
$printRules = new PrintRules(maxPerCustomer: 3);
|
||||
$warningThresholdQty = -100;
|
||||
|
||||
// GIVEN / THEN
|
||||
expect(fn (): CampaignCoupon => new CampaignCoupon($code, $qty, $warningThresholdQty, $printRules))->toThrow(\DomainException::class);
|
||||
});
|
||||
|
||||
it('rejects invalid campaign coupon whitout print rules', function (): void {
|
||||
// GIVEN
|
||||
$code = new ProcessingCode('PC1');
|
||||
$qty = StockId::generate();
|
||||
$warningThresholdQty = -100;
|
||||
|
||||
// GIVEN / THEN
|
||||
expect(fn (): CampaignCoupon => new CampaignCoupon($code, $qty, $warningThresholdQty))->toThrow(\DomainException::class);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Unit\Domain\Models\ValueObjects\RequestedCoupon;
|
||||
|
||||
use Domain\Models\ValueObjects\RequestedCoupon\RequestedCouponQuantity;
|
||||
|
||||
covers(RequestedCouponQuantity::class);
|
||||
|
||||
describe('quantity', function (): void {
|
||||
it('creates a valid quantity', function (): void {
|
||||
// GIVEN
|
||||
$value = 10;
|
||||
|
||||
// WHEN
|
||||
$quantity = new RequestedCouponQuantity($value);
|
||||
|
||||
// THEN
|
||||
expect($quantity)->toBeInstanceOf(RequestedCouponQuantity::class)
|
||||
->and($quantity->value)->toBe($value);
|
||||
});
|
||||
|
||||
it('rejects a quantity of zero', function (): void {
|
||||
// WHEN
|
||||
$action = fn (): RequestedCouponQuantity => new RequestedCouponQuantity(0);
|
||||
|
||||
// THEN
|
||||
expect($action)->toThrow(\DomainException::class, 'Quantity should be more than 0.');
|
||||
});
|
||||
|
||||
it('rejects a negative quantity', function (): void {
|
||||
// WHEN
|
||||
$action = fn (): RequestedCouponQuantity => new RequestedCouponQuantity(-1);
|
||||
|
||||
// THEN
|
||||
expect($action)->toThrow(\DomainException::class, 'Quantity should be more than 0.');
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Unit\Domain\Models\ValueObjects;
|
||||
|
||||
use Domain\Models\ValueObjects\WarningThresholdQuantity;
|
||||
|
||||
covers(WarningThresholdQuantity::class);
|
||||
|
||||
describe('warning threshold quantity', function (): void {
|
||||
it('creates a valid warning threshold quantity', function (): void {
|
||||
// GIVEN
|
||||
$value = 10;
|
||||
|
||||
// WHEN
|
||||
$threshold = new WarningThresholdQuantity($value);
|
||||
|
||||
// THEN
|
||||
expect($threshold)->toBeInstanceOf(WarningThresholdQuantity::class)
|
||||
->and($threshold->value)->toBe($value);
|
||||
});
|
||||
|
||||
it('accepts a zero value, meaning no warning', function (): void {
|
||||
// WHEN
|
||||
$threshold = new WarningThresholdQuantity(0);
|
||||
|
||||
// THEN
|
||||
expect($threshold->value)->toBe(0);
|
||||
});
|
||||
|
||||
it('rejects a negative value', function (): void {
|
||||
// WHEN
|
||||
$action = fn (): WarningThresholdQuantity => new WarningThresholdQuantity(-1);
|
||||
|
||||
// THEN
|
||||
expect($action)->toThrow(\DomainException::class, 'Warning threshold quantity cannot be negative.');
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Reference in a new issue