requestedCoupon = RequestedCoupon::hydrate( RequestedCouponId::generate(), new CouponName('Coupon A'), new CouponProductName('Product A'), 100, 10, new Period(new DateTime('2026-01-01'), new DateTime('2026-02-01')), new MoneyAmount(new Money(Currency::EUR, 300)), new ProcessingCode('PC1'), new CouponPicture(new PicturePath('coupons/product.jpg'), new PicturePath('coupons/thumbnail.jpg')), new GS1('01234567890128', BarcodeFormat::EAN13), new CouponValidity(30, DateTime::now()), ); }); it('hydrates a campaign request with all its fields', function (): void { // GIVEN $id = CampaignRequestId::generate(); $code = new BrandCode('AAA01'); $applicant = new Applicant('John', 'Doe', new Email('john.doe@example.com')); $country = Country::FR; $campaignType = CampaignType::CLUB; $printRules = new PrintRules(maxPerCustomer: 3); $requestedCoupon = $this->requestedCoupon; $status = CampaignStatus::CREATED; // WHEN $campaignRequest = CampaignRequest::hydrate( $id, $code, $applicant, $country, $campaignType, $printRules, $requestedCoupon, $status, ); // THEN expect($campaignRequest->id())->toBe($id) ->and($campaignRequest->code)->toBe($code) ->and($campaignRequest->applicant)->toBe($applicant) ->and($campaignRequest->country)->toBe($country) ->and($campaignRequest->campaignType)->toBe($campaignType) ->and($campaignRequest->printRules)->toBe($printRules) ->and($campaignRequest->requestedCoupon)->toBe($requestedCoupon) ->and($campaignRequest->status)->toBe($status) ->and($campaignRequest->updatedAt)->toBeNull() ->and($campaignRequest->updatedAt())->toBeNull(); }); it('hydrates a campaign request with a null printRules', function (): void { // WHEN $campaignRequest = CampaignRequest::hydrate( CampaignRequestId::generate(), new BrandCode('AAA01'), new Applicant('John', 'Doe', new Email('john.doe@example.com')), Country::FR, CampaignType::CLUB, null, $this->requestedCoupon, CampaignStatus::CREATED, ); // THEN expect($campaignRequest->printRules)->toBeNull(); }); it('hydrates a campaign request with an explicit updatedAt date', function (): void { // GIVEN $updatedAt = new \DateTimeImmutable('2026-06-15 12:00:00', new \DateTimeZone('UTC')); // 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), $this->requestedCoupon, CampaignStatus::CREATED, null, $updatedAt, ); // THEN expect($campaignRequest->updatedAt)->toBe($updatedAt) ->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), $this->requestedCoupon, 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), $this->requestedCoupon, 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), $this->requestedCoupon, 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')); $id = new CampaignRequestId(Uuid::uuid7($expected)); $campaignRequest = CampaignRequest::hydrate( $id, new BrandCode('AAA01'), new Applicant('John', 'Doe', new Email('john.doe@example.com')), Country::FR, CampaignType::CLUB, new PrintRules(maxPerCustomer: 3), $this->requestedCoupon, CampaignStatus::CREATED, ); // WHEN $result = $campaignRequest->createdAt(); // THEN expect($result->format('Y-m-d H:i:s.v'))->toBe($expected->format('Y-m-d H:i:s.v')); }); });