fix: 🐛 add missing rejection field in campaignRequest
This commit is contained in:
parent
00a33f1b7e
commit
269ff25f0f
4 changed files with 130 additions and 6 deletions
|
|
@ -10,6 +10,7 @@ use Domain\Enums\Country;
|
|||
use Domain\Models\ValueObjects\Brand\BrandCode;
|
||||
use Domain\Models\ValueObjects\CampaignRequest\CampaignRequestId;
|
||||
use Domain\Models\ValueObjects\CampaignRequest\Applicant;
|
||||
use Domain\Models\ValueObjects\CampaignRequest\RejectionReason;
|
||||
use Domain\Models\ValueObjects\PrintRules;
|
||||
use Shared\DDD\Models\AggregateRoot;
|
||||
use Shared\DDD\Models\HasTimestampIdentifier;
|
||||
|
|
@ -28,8 +29,17 @@ final readonly class CampaignRequest implements AggregateRoot, HasTimestampIdent
|
|||
public ?PrintRules $printRules,
|
||||
public RequestedCoupon $requestedCoupon,
|
||||
public CampaignStatus $status,
|
||||
public ?RejectionReason $rejectionReason = null,
|
||||
public ?\DateTimeInterface $updatedAt = null,
|
||||
) {}
|
||||
) {
|
||||
if ($this->status === CampaignStatus::REJECTED && ! $this->rejectionReason instanceof RejectionReason) {
|
||||
throw new \DomainException('A rejection reason is required when the campaign request is rejected.');
|
||||
}
|
||||
|
||||
if ($this->status !== CampaignStatus::REJECTED && $this->rejectionReason instanceof RejectionReason) {
|
||||
throw new \DomainException('A rejection reason can only be set when the campaign request is rejected.');
|
||||
}
|
||||
}
|
||||
|
||||
public function id(): CampaignRequestId
|
||||
{
|
||||
|
|
@ -56,6 +66,7 @@ final readonly class CampaignRequest implements AggregateRoot, HasTimestampIdent
|
|||
?PrintRules $printRules,
|
||||
RequestedCoupon $requestedCoupon,
|
||||
CampaignStatus $status,
|
||||
?RejectionReason $rejectionReason = null,
|
||||
?\DateTimeInterface $updatedAt = null,
|
||||
): self {
|
||||
return new self(
|
||||
|
|
@ -67,6 +78,7 @@ final readonly class CampaignRequest implements AggregateRoot, HasTimestampIdent
|
|||
printRules: $printRules,
|
||||
requestedCoupon: $requestedCoupon,
|
||||
status: $status,
|
||||
rejectionReason: $rejectionReason,
|
||||
updatedAt: $updatedAt,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Domain\Models\ValueObjects\CampaignRequest;
|
||||
|
||||
final readonly class RejectionReason
|
||||
{
|
||||
public function __construct(
|
||||
public string $value,
|
||||
) {
|
||||
$trimmed = trim($value);
|
||||
|
||||
if ($trimmed === '') {
|
||||
throw new \DomainException('Rejection reason cannot be empty.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,6 @@ declare(strict_types=1);
|
|||
|
||||
namespace Tests\Unit\Domain\Models\Entities;
|
||||
|
||||
use Carbon\CarbonImmutable;
|
||||
use Domain\Enums\BarcodeFormat;
|
||||
use Domain\Enums\Campaign\CampaignStatus;
|
||||
use Domain\Enums\Campaign\CampaignType;
|
||||
|
|
@ -14,6 +13,7 @@ use Domain\Models\Entities\RequestedCoupon;
|
|||
use Domain\Models\ValueObjects\Brand\BrandCode;
|
||||
use Domain\Models\ValueObjects\CampaignRequest\Applicant;
|
||||
use Domain\Models\ValueObjects\CampaignRequest\CampaignRequestId;
|
||||
use Domain\Models\ValueObjects\CampaignRequest\RejectionReason;
|
||||
use Domain\Models\ValueObjects\Coupon\CouponValidity;
|
||||
use Domain\Models\ValueObjects\CouponName;
|
||||
use Domain\Models\ValueObjects\CouponPicture;
|
||||
|
|
@ -51,10 +51,6 @@ function aRequestedCoupon(): RequestedCoupon
|
|||
}
|
||||
|
||||
describe('campaign request', function (): void {
|
||||
afterEach(function (): void {
|
||||
CarbonImmutable::setTestNow();
|
||||
});
|
||||
|
||||
it('hydrates a campaign request with all its fields', function (): void {
|
||||
// GIVEN
|
||||
$id = CampaignRequestId::generate();
|
||||
|
|
@ -122,6 +118,7 @@ describe('campaign request', function (): void {
|
|||
new PrintRules(maxPerCustomer: 3),
|
||||
aRequestedCoupon(),
|
||||
CampaignStatus::CREATED,
|
||||
null,
|
||||
$updatedAt,
|
||||
);
|
||||
|
||||
|
|
@ -130,6 +127,69 @@ describe('campaign request', function (): void {
|
|||
->and($campaignRequest->updatedAt())->toBe($updatedAt);
|
||||
});
|
||||
|
||||
it('hydrates a rejected campaign request with a rejection reason', function (): void {
|
||||
// GIVEN
|
||||
$rejectionReason = new RejectionReason('Missing legal documents.');
|
||||
|
||||
// WHEN
|
||||
$campaignRequest = CampaignRequest::hydrate(
|
||||
CampaignRequestId::generate(),
|
||||
new BrandCode('AAA01'),
|
||||
new Applicant('John', 'Doe', new Email('john.doe@example.com')),
|
||||
Country::FR,
|
||||
CampaignType::CLUB,
|
||||
new PrintRules(maxPerCustomer: 3),
|
||||
aRequestedCoupon(),
|
||||
CampaignStatus::REJECTED,
|
||||
$rejectionReason,
|
||||
);
|
||||
|
||||
// THEN
|
||||
expect($campaignRequest->status)->toBe(CampaignStatus::REJECTED)
|
||||
->and($campaignRequest->rejectionReason)->toBe($rejectionReason);
|
||||
});
|
||||
|
||||
it('rejects a rejected campaign request without a rejection reason', function (): void {
|
||||
// WHEN
|
||||
$action = fn (): CampaignRequest => CampaignRequest::hydrate(
|
||||
CampaignRequestId::generate(),
|
||||
new BrandCode('AAA01'),
|
||||
new Applicant('John', 'Doe', new Email('john.doe@example.com')),
|
||||
Country::FR,
|
||||
CampaignType::CLUB,
|
||||
new PrintRules(maxPerCustomer: 3),
|
||||
aRequestedCoupon(),
|
||||
CampaignStatus::REJECTED,
|
||||
);
|
||||
|
||||
// THEN
|
||||
expect($action)->toThrow(
|
||||
\DomainException::class,
|
||||
'A rejection reason is required when the campaign request is rejected.'
|
||||
);
|
||||
});
|
||||
|
||||
it('rejects a non-rejected campaign request with a rejection reason', function (): void {
|
||||
// WHEN
|
||||
$action = fn (): CampaignRequest => CampaignRequest::hydrate(
|
||||
CampaignRequestId::generate(),
|
||||
new BrandCode('AAA01'),
|
||||
new Applicant('John', 'Doe', new Email('john.doe@example.com')),
|
||||
Country::FR,
|
||||
CampaignType::CLUB,
|
||||
new PrintRules(maxPerCustomer: 3),
|
||||
aRequestedCoupon(),
|
||||
CampaignStatus::CREATED,
|
||||
new RejectionReason('Missing legal documents.'),
|
||||
);
|
||||
|
||||
// THEN
|
||||
expect($action)->toThrow(
|
||||
\DomainException::class,
|
||||
'A rejection reason can only be set when the campaign request is rejected.'
|
||||
);
|
||||
});
|
||||
|
||||
it('returns the creation date extracted from the id', function (): void {
|
||||
// GIVEN
|
||||
$expected = new \DateTimeImmutable('2024-06-15 12:34:56.789000', new \DateTimeZone('UTC'));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Unit\Domain\Models\ValueObjects\CampaignRequest;
|
||||
|
||||
use Domain\Models\ValueObjects\CampaignRequest\RejectionReason;
|
||||
|
||||
covers(RejectionReason::class);
|
||||
|
||||
describe('rejection reason', function (): void {
|
||||
it('creates a valid rejection reason', function (): void {
|
||||
// GIVEN
|
||||
$value = 'Missing legal documents.';
|
||||
|
||||
// WHEN
|
||||
$reason = new RejectionReason($value);
|
||||
|
||||
// THEN
|
||||
expect($reason)->toBeInstanceOf(RejectionReason::class)
|
||||
->and($reason->value)->toBe($value);
|
||||
});
|
||||
|
||||
it('rejects an empty or whitespace-only reason', function (string $value): void {
|
||||
// WHEN
|
||||
$action = fn (): RejectionReason => new RejectionReason($value);
|
||||
|
||||
// THEN
|
||||
expect($action)->toThrow(\DomainException::class, 'Rejection reason cannot be empty.');
|
||||
})->with([
|
||||
'empty' => '',
|
||||
'spaces' => ' ',
|
||||
]);
|
||||
});
|
||||
Loading…
Add table
Reference in a new issue