Merge branch 'printable-coupon' into 'coupon'
feat: 👷 add ListPrintableCoupon Use Case and tests
See merge request ldc-web/projets/mesbr!61
This commit is contained in:
commit
f55f4bb628
24 changed files with 1153 additions and 0 deletions
22
src/Application/UseCases/PrintableCoupon/List/Input.php
Normal file
22
src/Application/UseCases/PrintableCoupon/List/Input.php
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Application\UseCases\PrintableCoupon\List;
|
||||
|
||||
use Domain\Models\ValueObjects\Campaign\CampaignCode;
|
||||
use Domain\Models\ValueObjects\CrmHashcode;
|
||||
use Domain\Models\ValueObjects\PrintableCoupon\PrintableCouponSortCriteria;
|
||||
use Shared\DDD\UseCases\Input as UseCaseInput;
|
||||
use Shared\ValueObjects\Pagination\Pagination;
|
||||
|
||||
final readonly class Input implements UseCaseInput
|
||||
{
|
||||
public function __construct(
|
||||
public Pagination $pagination,
|
||||
public CampaignCode $campaignCode,
|
||||
public CrmHashcode $crmCustomerHashcode,
|
||||
public ?PrintableCouponSortCriteria $sortCriteria = null,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Application\UseCases\PrintableCoupon\List;
|
||||
|
||||
use Domain\Models\Entities\PrintableCoupon;
|
||||
use Domain\Models\ValueObjects\Coupon\CouponPicture;
|
||||
use Domain\Ports\Repositories\CouponRepository;
|
||||
use Domain\Ports\Repositories\PrintableCouponRepository;
|
||||
use Shared\DDD\UseCases\Input as BaseInput;
|
||||
use Shared\DDD\UseCases\UseCase;
|
||||
use Shared\ValueObjects\Pagination\Paginated;
|
||||
use Webmozart\Assert\Assert;
|
||||
|
||||
/** @implements UseCase<\Application\UseCases\PrintableCoupon\List\Input, \Application\UseCases\PrintableCoupon\List\Output> */
|
||||
final readonly class ListPrintableCoupons implements UseCase
|
||||
{
|
||||
public function __construct(
|
||||
private PrintableCouponRepository $repository,
|
||||
private CouponRepository $couponRepository,
|
||||
) {
|
||||
}
|
||||
|
||||
#[\Override]
|
||||
public function execute(BaseInput $input): Output
|
||||
{
|
||||
Assert::isInstanceOf($input, Input::class);
|
||||
|
||||
$result = $this->repository->findAllAvailable(
|
||||
pagination: $input->pagination,
|
||||
campaignCode: $input->campaignCode,
|
||||
crmCustomerHashcode: $input->crmCustomerHashcode,
|
||||
sortCriteria: $input->sortCriteria,
|
||||
);
|
||||
|
||||
$printableCoupons = $result->getItems();
|
||||
|
||||
/** @var array<string, CouponPicture> $picturesByCouponCode */
|
||||
$picturesByCouponCode = [];
|
||||
|
||||
foreach ($printableCoupons as $printableCoupon) {
|
||||
$couponCode = $printableCoupon->couponCode;
|
||||
|
||||
if (isset($picturesByCouponCode[$couponCode->value])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$coupon = $this->couponRepository->findByCode($couponCode)
|
||||
?? throw new \LogicException(sprintf('Coupon "%s" referenced by a printable coupon does not exist.', $couponCode->value));
|
||||
|
||||
$picturesByCouponCode[$couponCode->value] = $coupon->picture;
|
||||
}
|
||||
|
||||
$items = array_map(
|
||||
static fn (PrintableCoupon $printableCoupon): PrintableCouponListItem => new PrintableCouponListItem(
|
||||
code: $printableCoupon->code,
|
||||
couponCode: $printableCoupon->couponCode,
|
||||
couponName: $printableCoupon->couponName,
|
||||
couponPicture: $picturesByCouponCode[$printableCoupon->couponCode->value],
|
||||
distributableUntil: $printableCoupon->distributableUntil,
|
||||
createdAt: $printableCoupon->createdAt(),
|
||||
updatedAt: $printableCoupon->updatedAt(),
|
||||
),
|
||||
$printableCoupons,
|
||||
);
|
||||
|
||||
return new Output(
|
||||
printableCoupons: new Paginated(
|
||||
pagination: $result->getPagination(),
|
||||
items: $items,
|
||||
total: $result->getTotal(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
17
src/Application/UseCases/PrintableCoupon/List/Output.php
Normal file
17
src/Application/UseCases/PrintableCoupon/List/Output.php
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Application\UseCases\PrintableCoupon\List;
|
||||
|
||||
use Shared\DDD\UseCases\Output as UseCaseOutput;
|
||||
use Shared\ValueObjects\Pagination\Paginated;
|
||||
|
||||
final readonly class Output implements UseCaseOutput
|
||||
{
|
||||
/** @param Paginated<PrintableCouponListItem> $printableCoupons */
|
||||
public function __construct(
|
||||
public Paginated $printableCoupons,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Application\UseCases\PrintableCoupon\List;
|
||||
|
||||
use Domain\Models\ValueObjects\Coupon\CouponCode;
|
||||
use Domain\Models\ValueObjects\Coupon\CouponName;
|
||||
use Domain\Models\ValueObjects\Coupon\CouponPicture;
|
||||
use Domain\Models\ValueObjects\PrintableCoupon\PrintableCouponCode;
|
||||
|
||||
final readonly class PrintableCouponListItem
|
||||
{
|
||||
public function __construct(
|
||||
public PrintableCouponCode $code,
|
||||
public CouponCode $couponCode,
|
||||
public CouponName $couponName,
|
||||
public CouponPicture $couponPicture,
|
||||
public \DateTimeInterface $distributableUntil,
|
||||
public \DateTimeInterface $createdAt,
|
||||
public \DateTimeInterface $updatedAt,
|
||||
) {
|
||||
}
|
||||
}
|
||||
84
src/Domain/Models/Entities/PrintableCoupon.php
Normal file
84
src/Domain/Models/Entities/PrintableCoupon.php
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Domain\Models\Entities;
|
||||
|
||||
use Domain\Models\ValueObjects\Campaign\CampaignCode;
|
||||
use Domain\Models\ValueObjects\Coupon\CouponCode;
|
||||
use Domain\Models\ValueObjects\Coupon\CouponName;
|
||||
use Domain\Models\ValueObjects\PrintableCoupon\PrintableCouponCode;
|
||||
use Domain\Models\ValueObjects\CrmHashcode;
|
||||
use Shared\DDD\Models\AggregateRoot;
|
||||
use Shared\DDD\Models\HasTimestampIdentifier;
|
||||
use Shared\Helpers\DatesHelper;
|
||||
|
||||
/**
|
||||
* @implements \Shared\DDD\Models\AggregateRoot<\Domain\Models\ValueObjects\PrintableCoupon\PrintableCouponCode>
|
||||
*/
|
||||
final readonly class PrintableCoupon implements AggregateRoot, HasTimestampIdentifier
|
||||
{
|
||||
private function __construct(
|
||||
public PrintableCouponCode $code,
|
||||
public CampaignCode $campaignCode,
|
||||
public CouponCode $couponCode,
|
||||
public CouponName $couponName,
|
||||
public CrmHashcode $crmCustomerHashcode,
|
||||
public \DateTimeInterface $distributableUntil,
|
||||
public \DateTimeInterface $updatedAt,
|
||||
) {
|
||||
}
|
||||
|
||||
public function id(): PrintableCouponCode
|
||||
{
|
||||
return $this->code;
|
||||
}
|
||||
|
||||
public function createdAt(): \DateTimeInterface
|
||||
{
|
||||
return $this->code->toDateTime();
|
||||
}
|
||||
|
||||
public function updatedAt(): \DateTimeInterface
|
||||
{
|
||||
return $this->updatedAt;
|
||||
}
|
||||
|
||||
public static function create(
|
||||
CampaignCode $campaignCode,
|
||||
CouponCode $couponCode,
|
||||
CouponName $couponName,
|
||||
CrmHashcode $crmCustomerHashcode,
|
||||
\DateTimeInterface $distributableUntil,
|
||||
): self {
|
||||
$code = PrintableCouponCode::generate();
|
||||
return new self(
|
||||
code: $code,
|
||||
campaignCode: $campaignCode,
|
||||
couponCode: $couponCode,
|
||||
couponName: $couponName,
|
||||
crmCustomerHashcode: $crmCustomerHashcode,
|
||||
distributableUntil: $distributableUntil,
|
||||
updatedAt: $code->toDateTime(),
|
||||
);
|
||||
}
|
||||
|
||||
public static function hydrate(
|
||||
PrintableCouponCode $code,
|
||||
CampaignCode $campaignCode,
|
||||
CouponCode $couponCode,
|
||||
CouponName $couponName,
|
||||
CrmHashcode $crmCustomerHashcode,
|
||||
\DateTimeInterface $distributableUntil,
|
||||
): self {
|
||||
return new self(
|
||||
code: $code,
|
||||
campaignCode: $campaignCode,
|
||||
couponCode: $couponCode,
|
||||
couponName: $couponName,
|
||||
crmCustomerHashcode: $crmCustomerHashcode,
|
||||
distributableUntil: $distributableUntil,
|
||||
updatedAt: DatesHelper::now(),
|
||||
);
|
||||
}
|
||||
}
|
||||
28
src/Domain/Models/ValueObjects/CrmHashcode.php
Normal file
28
src/Domain/Models/ValueObjects/CrmHashcode.php
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Domain\Models\ValueObjects;
|
||||
|
||||
use Ramsey\Uuid\UuidInterface;
|
||||
use Shared\DDD\Models\Equatable;
|
||||
use Shared\Helpers\UuidHelper;
|
||||
|
||||
final readonly class CrmHashcode implements Equatable
|
||||
{
|
||||
public function __construct(
|
||||
public UuidInterface $value,
|
||||
) {
|
||||
if (! UuidHelper::isV4($value)) {
|
||||
throw new \DomainException(
|
||||
'Hash code must be a valid UUID v4.',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[\Override]
|
||||
public function equals(mixed $other): bool
|
||||
{
|
||||
return $other instanceof self && $this->value === $other->value;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Domain\Models\ValueObjects\PrintableCoupon;
|
||||
|
||||
use Shared\DDD\Models\Equatable;
|
||||
|
||||
final readonly class MarketingDirectCode implements \Stringable, Equatable
|
||||
{
|
||||
private const string PATTERN = '/^\d{13}\z/';
|
||||
|
||||
public function __construct(
|
||||
public string $value,
|
||||
) {
|
||||
if (preg_match(self::PATTERN, $this->value) !== 1) {
|
||||
throw new \DomainException(
|
||||
'Marketing Direct Code must be exactly 13 numeric characters, e.g. 5425003944130.',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static function fromInt(int $sequence): self
|
||||
{
|
||||
if ($sequence < 0) {
|
||||
throw new \DomainException('Marketing Direct sequence must be positive.');
|
||||
}
|
||||
|
||||
return new self(str_pad((string) $sequence, 13, '0', STR_PAD_LEFT));
|
||||
}
|
||||
|
||||
public function toInt(): int
|
||||
{
|
||||
return (int) $this->value;
|
||||
}
|
||||
|
||||
#[\Override]
|
||||
public function equals(mixed $other): bool
|
||||
{
|
||||
return $other instanceof self && $this->value === $other->value;
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Domain\Models\ValueObjects\PrintableCoupon;
|
||||
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use Shared\DDD\Models\Uuidv7EntityId;
|
||||
|
||||
final readonly class PrintableCouponCode extends Uuidv7EntityId
|
||||
{
|
||||
public static function generate(): self
|
||||
{
|
||||
return new self(Uuid::uuid7());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Domain\Models\ValueObjects\PrintableCoupon;
|
||||
|
||||
final readonly class PrintableCouponSortCriteria
|
||||
{
|
||||
public function __construct(
|
||||
public PrintableCouponSortField $field = PrintableCouponSortField::Name,
|
||||
public \SortDirection $direction = \SortDirection::Ascending,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Domain\Models\ValueObjects\PrintableCoupon;
|
||||
|
||||
enum PrintableCouponSortField: string
|
||||
{
|
||||
case CreatedAt = 'created_at';
|
||||
case Name = 'name';
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Domain\Models\ValueObjects\PrintableCoupon;
|
||||
|
||||
use Domain\Models\ValueObjects\Campaign\CampaignCode;
|
||||
use Domain\Models\ValueObjects\Coupon\CouponCode;
|
||||
use Domain\Models\ValueObjects\CrmHashcode;
|
||||
|
||||
final readonly class PrintedCoupon
|
||||
{
|
||||
public function __construct(
|
||||
public PrintedCouponId $id,
|
||||
public MarketingDirectCode $marketingCode,
|
||||
public PrintableCouponCode $printableCode,
|
||||
public CouponCode $couponCode,
|
||||
public CampaignCode $campaignCode,
|
||||
public CrmHashcode $customer,
|
||||
public \DateTimeInterface $printedAt,
|
||||
) {
|
||||
}
|
||||
|
||||
public function printedAt(): \DateTimeInterface
|
||||
{
|
||||
return $this->id->toDateTime();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Domain\Models\ValueObjects\PrintableCoupon;
|
||||
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use Shared\DDD\Models\Uuidv7EntityId;
|
||||
|
||||
final readonly class PrintedCouponId extends Uuidv7EntityId
|
||||
{
|
||||
public static function generate(): self
|
||||
{
|
||||
return new self(Uuid::uuid7());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Domain\Models\ValueObjects\PrintableCoupon;
|
||||
|
||||
use Domain\Models\ValueObjects\Campaign\CampaignCode;
|
||||
use Domain\Models\ValueObjects\Coupon\CouponCode;
|
||||
use Domain\Models\ValueObjects\CrmHashcode;
|
||||
|
||||
final readonly class UnprintedCoupon
|
||||
{
|
||||
public function __construct(
|
||||
public PrintableCouponCode $printableCode,
|
||||
public CouponCode $couponCode,
|
||||
public CampaignCode $campaignCode,
|
||||
public CrmHashcode $customer,
|
||||
public UnprintedReason $unprintedReason,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Domain\Models\ValueObjects\PrintableCoupon;
|
||||
|
||||
final readonly class UnprintedReason
|
||||
{
|
||||
public function __construct(
|
||||
public string $value,
|
||||
) {
|
||||
if (mb_trim($this->value) === '') {
|
||||
throw new \DomainException('Unprinted reason cannot be empty.');
|
||||
}
|
||||
}
|
||||
}
|
||||
31
src/Domain/Ports/Repositories/PrintableCouponRepository.php
Normal file
31
src/Domain/Ports/Repositories/PrintableCouponRepository.php
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Domain\Ports\Repositories;
|
||||
|
||||
use Domain\Models\Entities\PrintableCoupon;
|
||||
use Domain\Models\ValueObjects\Campaign\CampaignCode;
|
||||
use Domain\Models\ValueObjects\CrmHashcode;
|
||||
use Domain\Models\ValueObjects\PrintableCoupon\PrintableCouponSortCriteria;
|
||||
use Shared\DDD\Ports\Repository;
|
||||
use Shared\ValueObjects\Pagination\Paginated;
|
||||
use Shared\ValueObjects\Pagination\Pagination;
|
||||
|
||||
/**
|
||||
* @extends \Shared\DDD\Ports\Repository<\Domain\Models\ValueObjects\PrintableCoupon\PrintableCouponCode, \Domain\Models\Entities\PrintableCoupon>
|
||||
*/
|
||||
interface PrintableCouponRepository extends Repository
|
||||
{
|
||||
/**
|
||||
* @return Paginated<PrintableCoupon>
|
||||
*/
|
||||
public function findAllAvailable(
|
||||
Pagination $pagination,
|
||||
CampaignCode $campaignCode,
|
||||
CrmHashcode $crmCustomerHashcode,
|
||||
?PrintableCouponSortCriteria $sortCriteria = null,
|
||||
): Paginated;
|
||||
|
||||
public function save(PrintableCoupon $printableCoupon): void;
|
||||
}
|
||||
|
|
@ -0,0 +1,279 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Unit\Application\UseCases\PrintableCoupon\List;
|
||||
|
||||
use Application\UseCases\PrintableCoupon\List\Input;
|
||||
use Application\UseCases\PrintableCoupon\List\ListPrintableCoupons;
|
||||
use Application\UseCases\PrintableCoupon\List\Output;
|
||||
use Application\UseCases\PrintableCoupon\List\PrintableCouponListItem;
|
||||
use DateTime;
|
||||
use Domain\Models\Entities\Coupon;
|
||||
use Domain\Models\Entities\PrintableCoupon;
|
||||
use Domain\Models\ValueObjects\Actor\ActorId;
|
||||
use Domain\Models\ValueObjects\Brand\BrandCode;
|
||||
use Domain\Models\ValueObjects\Campaign\CampaignCode;
|
||||
use Domain\Models\ValueObjects\Coupon\CouponCode;
|
||||
use Domain\Models\ValueObjects\Coupon\CouponDiffusion;
|
||||
use Domain\Models\ValueObjects\Coupon\CouponLegalInformation;
|
||||
use Domain\Models\ValueObjects\Coupon\CouponLegalInformationArray;
|
||||
use Domain\Models\ValueObjects\Coupon\CouponMovement;
|
||||
use Domain\Models\ValueObjects\Coupon\CouponMovementArray;
|
||||
use Domain\Models\ValueObjects\Coupon\CouponName;
|
||||
use Domain\Models\ValueObjects\Coupon\CouponPicture;
|
||||
use Domain\Models\ValueObjects\Coupon\CouponProductArray;
|
||||
use Domain\Models\ValueObjects\Coupon\CouponQuantity;
|
||||
use Domain\Models\ValueObjects\Coupon\CouponValidityInformation;
|
||||
use Domain\Models\ValueObjects\Coupon\CouponValidityInformationArray;
|
||||
use Domain\Models\ValueObjects\CrmHashcode;
|
||||
use Domain\Models\ValueObjects\IncoCode;
|
||||
use Domain\Models\ValueObjects\MoneyAmount;
|
||||
use Domain\Models\ValueObjects\Period;
|
||||
use Domain\Models\ValueObjects\PicturePath;
|
||||
use Domain\Models\ValueObjects\PrintableCoupon\PrintableCouponCode;
|
||||
use Domain\Models\ValueObjects\PrintableCoupon\PrintableCouponSortCriteria;
|
||||
use Domain\Models\ValueObjects\PrintableCoupon\PrintableCouponSortField;
|
||||
use Domain\Models\ValueObjects\ProcessingCode;
|
||||
use Domain\Models\ValueObjects\ProcessingCodeArray;
|
||||
use Domain\Ports\Repositories\CouponRepository;
|
||||
use Domain\Ports\Repositories\PrintableCouponRepository;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use Shared\Enums\Country;
|
||||
use Shared\Enums\Currency;
|
||||
use Shared\ValueObjects\Money;
|
||||
use Shared\ValueObjects\Pagination\Paginated;
|
||||
use Shared\ValueObjects\Pagination\Pagination;
|
||||
|
||||
covers(ListPrintableCoupons::class, Input::class, Output::class, PrintableCouponListItem::class);
|
||||
|
||||
describe('list printable coupons use case', function (): void {
|
||||
$createPicture = fn (string $name): CouponPicture => new CouponPicture(
|
||||
new PicturePath("files/{$name}.jpg"),
|
||||
new PicturePath("files/{$name}-thumbnail.jpg"),
|
||||
new PicturePath("files/{$name}-mobile.jpg"),
|
||||
);
|
||||
|
||||
$createInput = fn (PrintableCouponSortCriteria | null $sortCriteria = null): Input => new Input(
|
||||
pagination: Pagination::firstPage(),
|
||||
campaignCode: new CampaignCode('AAA01'),
|
||||
crmCustomerHashcode: new CrmHashcode(Uuid::uuid4()),
|
||||
sortCriteria: $sortCriteria ?? new PrintableCouponSortCriteria(
|
||||
field: PrintableCouponSortField::CreatedAt,
|
||||
direction: \SortDirection::Descending,
|
||||
),
|
||||
);
|
||||
|
||||
$createPrintableCoupon = fn (CouponCode $couponCode): PrintableCoupon => PrintableCoupon::hydrate(
|
||||
code: PrintableCouponCode::generate(),
|
||||
campaignCode: new CampaignCode('AAA01'),
|
||||
couponCode: $couponCode,
|
||||
couponName: new CouponName('Coupon name'),
|
||||
crmCustomerHashcode: new CrmHashcode(Uuid::uuid4()),
|
||||
distributableUntil: new DateTime('2027-01-01'),
|
||||
);
|
||||
|
||||
$createCoupon = fn (CouponCode $code, CouponPicture $picture): Coupon => Coupon::create(
|
||||
code: $code,
|
||||
name: new CouponName('Coupon name'),
|
||||
amount: new MoneyAmount(new Money(Currency::EUR, 100)),
|
||||
picture: $picture,
|
||||
diffusion: new CouponDiffusion(
|
||||
new Period(
|
||||
new DateTime('2026-01-01'),
|
||||
new DateTime('2026-02-01'),
|
||||
),
|
||||
),
|
||||
validityInformations: new CouponValidityInformationArray([
|
||||
new CouponValidityInformation(
|
||||
'Lorem ipsum dolor sit amet consectetur adipiscing elit.',
|
||||
Country::FRANCE
|
||||
),
|
||||
]),
|
||||
legalInformations: new CouponLegalInformationArray([
|
||||
new CouponLegalInformation(
|
||||
'Lorem ipsum dolor sit amet consectetur adipiscing elit.',
|
||||
Country::FRANCE
|
||||
),
|
||||
]),
|
||||
processingCode: new ProcessingCodeArray([
|
||||
new ProcessingCode('5425003944130', Country::FRANCE),
|
||||
]),
|
||||
brandCode: new BrandCode('AAA01'),
|
||||
createdBy: ActorId::generate(),
|
||||
products: new CouponProductArray([
|
||||
new IncoCode(35784),
|
||||
new IncoCode(15522),
|
||||
]),
|
||||
movements: new CouponMovementArray([
|
||||
new CouponMovement(1000)
|
||||
]),
|
||||
quantity: new CouponQuantity(1000),
|
||||
);
|
||||
|
||||
it('returns the printable coupons with the picture of their coupon', function () use (
|
||||
$createInput,
|
||||
$createPicture,
|
||||
$createCoupon,
|
||||
$createPrintableCoupon,
|
||||
): void {
|
||||
// GIVEN
|
||||
$input = $createInput();
|
||||
$picture = $createPicture('picture');
|
||||
$couponCode = new CouponCode('AAA01');
|
||||
$printable = $createPrintableCoupon($couponCode);
|
||||
$coupon = $createCoupon($couponCode, $picture);
|
||||
|
||||
$paginated = new Paginated(pagination: $input->pagination, items: [$printable], total: 1);
|
||||
|
||||
$repository = \Mockery::mock(PrintableCouponRepository::class);
|
||||
$repository->shouldReceive('findAllAvailable')
|
||||
->once()
|
||||
->with($input->pagination, $input->campaignCode, $input->crmCustomerHashcode, $input->sortCriteria)
|
||||
->andReturn($paginated);
|
||||
|
||||
$couponRepository = \Mockery::mock(CouponRepository::class);
|
||||
$couponRepository->shouldReceive('findByCode')
|
||||
->once()
|
||||
->with($printable->couponCode)
|
||||
->andReturn($coupon);
|
||||
|
||||
$useCase = new ListPrintableCoupons($repository, $couponRepository);
|
||||
|
||||
// WHEN
|
||||
$output = $useCase->execute($input);
|
||||
|
||||
// THEN
|
||||
$items = $output->printableCoupons->getItems();
|
||||
|
||||
expect($items)->toHaveCount(1)
|
||||
->and($output->printableCoupons->getTotal())->toBe(1)
|
||||
->and($items[0]->code)->toBe($printable->code)
|
||||
->and($items[0]->couponCode)->toBe($printable->couponCode)
|
||||
->and($items[0]->couponName)->toBe($printable->couponName)
|
||||
->and($items[0]->couponPicture)->toBe($picture)
|
||||
->and($items[0]->distributableUntil)->toBe($printable->distributableUntil);
|
||||
});
|
||||
|
||||
it('forwards the sort criteria and keeps the order returned by the repository', function () use (
|
||||
$createInput,
|
||||
$createPicture,
|
||||
$createCoupon,
|
||||
$createPrintableCoupon,
|
||||
): void {
|
||||
// GIVEN
|
||||
$sortCriteria = new PrintableCouponSortCriteria(
|
||||
field: PrintableCouponSortField::Name,
|
||||
direction: \SortDirection::Descending,
|
||||
);
|
||||
$input = $createInput($sortCriteria);
|
||||
|
||||
$code1 = new CouponCode('AAA01');
|
||||
$code2 = new CouponCode('BBB02');
|
||||
$picture1 = $createPicture('picture-1');
|
||||
$picture2 = $createPicture('picture-2');
|
||||
|
||||
$printableCoupon1 = $createPrintableCoupon($code1);
|
||||
$printableCoupon2 = $createPrintableCoupon($code2);
|
||||
|
||||
$repository = \Mockery::mock(PrintableCouponRepository::class);
|
||||
$repository->shouldReceive('findAllAvailable')
|
||||
->once()
|
||||
->with($input->pagination, $input->campaignCode, $input->crmCustomerHashcode, $sortCriteria)
|
||||
->andReturn(new Paginated(pagination: $input->pagination, items: [$printableCoupon2, $printableCoupon1], total: 2));
|
||||
|
||||
$couponRepository = \Mockery::mock(CouponRepository::class);
|
||||
$couponRepository->shouldReceive('findByCode')->with($code2)->once()
|
||||
->andReturn($createCoupon($code2, $picture2));
|
||||
$couponRepository->shouldReceive('findByCode')->with($code1)->once()
|
||||
->andReturn($createCoupon($code1, $picture1));
|
||||
|
||||
$useCase = new ListPrintableCoupons($repository, $couponRepository);
|
||||
|
||||
// WHEN
|
||||
$items = $useCase->execute($input)->printableCoupons->getItems();
|
||||
|
||||
// THEN
|
||||
expect($items)->toHaveCount(2)
|
||||
->and($items[0]->code)->toBe($printableCoupon2->code)
|
||||
->and($items[0]->couponName)->toBe($printableCoupon2->couponName)
|
||||
->and($items[0]->couponPicture)->toBe($picture2)
|
||||
->and($items[1]->code)->toBe($printableCoupon1->code)
|
||||
->and($items[1]->couponName)->toBe($printableCoupon1->couponName)
|
||||
->and($items[1]->couponPicture)->toBe($picture1);
|
||||
});
|
||||
|
||||
it('returns an empty list without error when there is no printable coupon', function () use ($createInput): void {
|
||||
// GIVEN
|
||||
$input = $createInput();
|
||||
$paginated = new Paginated(pagination: $input->pagination, items: [], total: 0);
|
||||
|
||||
$repository = \Mockery::mock(PrintableCouponRepository::class);
|
||||
$repository->shouldReceive('findAllAvailable')->once()->andReturn($paginated);
|
||||
|
||||
$couponRepository = \Mockery::mock(CouponRepository::class);
|
||||
$couponRepository->shouldNotReceive('findByCode');
|
||||
|
||||
$useCase = new ListPrintableCoupons($repository, $couponRepository);
|
||||
|
||||
// WHEN
|
||||
$output = $useCase->execute($input);
|
||||
|
||||
// THEN
|
||||
expect($output->printableCoupons->getItems())->toBe([])
|
||||
->and($output->printableCoupons->getTotal())->toBe(0);
|
||||
});
|
||||
|
||||
it('loads a shared coupon only once', function () use (
|
||||
$createInput,
|
||||
$createPicture,
|
||||
$createPrintableCoupon,
|
||||
$createCoupon,
|
||||
): void {
|
||||
// GIVEN
|
||||
$input = $createInput();
|
||||
$picture = $createPicture('picture');
|
||||
$couponCode = new CouponCode('AAA01');
|
||||
$items = [$createPrintableCoupon($couponCode), $createPrintableCoupon($couponCode)];
|
||||
|
||||
$repository = \Mockery::mock(PrintableCouponRepository::class);
|
||||
$repository->shouldReceive('findAllAvailable')
|
||||
->once()
|
||||
->andReturn(new Paginated(pagination: $input->pagination, items: $items, total: 2));
|
||||
|
||||
$couponRepository = \Mockery::mock(CouponRepository::class);
|
||||
$couponRepository->shouldReceive('findByCode')
|
||||
->once()
|
||||
->andReturn($createCoupon($couponCode, $picture));
|
||||
|
||||
$useCase = new ListPrintableCoupons($repository, $couponRepository);
|
||||
|
||||
// WHEN
|
||||
$output = $useCase->execute($input);
|
||||
|
||||
// THEN
|
||||
expect($output->printableCoupons->getItems())->toHaveCount(2);
|
||||
});
|
||||
|
||||
it('throws when the coupon of a printable coupon does not exist', function () use ($createInput, $createPrintableCoupon): void {
|
||||
// GIVEN
|
||||
$input = $createInput();
|
||||
$printable = $createPrintableCoupon(new CouponCode('BBB02'));
|
||||
|
||||
$repository = \Mockery::mock(PrintableCouponRepository::class);
|
||||
$repository->shouldReceive('findAllAvailable')
|
||||
->once()
|
||||
->andReturn(new Paginated(pagination: $input->pagination, items: [$printable], total: 1));
|
||||
|
||||
$couponRepository = \Mockery::mock(CouponRepository::class);
|
||||
$couponRepository->shouldReceive('findByCode')->once()->andReturn(null);
|
||||
|
||||
$useCase = new ListPrintableCoupons($repository, $couponRepository);
|
||||
|
||||
// WHEN
|
||||
$action = fn (): Output => $useCase->execute($input);
|
||||
|
||||
// THEN
|
||||
expect($action)->toThrow(\LogicException::class);
|
||||
});
|
||||
});
|
||||
122
tests/Unit/Domain/Models/Entities/PrintableCouponTest.php
Normal file
122
tests/Unit/Domain/Models/Entities/PrintableCouponTest.php
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Unit\Domain\Models\Entities;
|
||||
|
||||
use Domain\Models\Entities\PrintableCoupon;
|
||||
use Domain\Models\ValueObjects\Campaign\CampaignCode;
|
||||
use Domain\Models\ValueObjects\Coupon\CouponCode;
|
||||
use Domain\Models\ValueObjects\Coupon\CouponName;
|
||||
use Domain\Models\ValueObjects\CrmHashcode;
|
||||
use Domain\Models\ValueObjects\PrintableCoupon\PrintableCouponCode;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
|
||||
covers(PrintableCoupon::class);
|
||||
|
||||
describe('printable coupon', function (): void {
|
||||
$campaignCode = new CampaignCode('AAA01');
|
||||
$couponCode = new CouponCode('AAA01');
|
||||
$couponName = new CouponName('Coupon name');
|
||||
$crmCustomerHashcode = new CrmHashcode(Uuid::uuid4());
|
||||
$distributableUntil = new \DateTimeImmutable('2027-01-01');
|
||||
|
||||
it('creates a printable coupon with the given values', function () use (
|
||||
$campaignCode,
|
||||
$couponCode,
|
||||
$couponName,
|
||||
$crmCustomerHashcode,
|
||||
$distributableUntil,
|
||||
): void {
|
||||
// GIVEN / WHEN
|
||||
$printable = PrintableCoupon::create(
|
||||
$campaignCode,
|
||||
$couponCode,
|
||||
$couponName,
|
||||
$crmCustomerHashcode,
|
||||
$distributableUntil,
|
||||
);
|
||||
|
||||
// THEN
|
||||
expect($printable->campaignCode)->toBe($campaignCode)
|
||||
->and($printable->couponCode)->toBe($couponCode)
|
||||
->and($printable->couponName)->toBe($couponName)
|
||||
->and($printable->crmCustomerHashcode)->toBe($crmCustomerHashcode)
|
||||
->and($printable->distributableUntil)->toBe($distributableUntil);
|
||||
});
|
||||
|
||||
it('generates a new code on each creation', function () use (
|
||||
$campaignCode,
|
||||
$couponCode,
|
||||
$couponName,
|
||||
$crmCustomerHashcode,
|
||||
$distributableUntil,
|
||||
): void {
|
||||
// GIVEN / WHEN
|
||||
$first = PrintableCoupon::create($campaignCode, $couponCode, $couponName, $crmCustomerHashcode, $distributableUntil);
|
||||
$second = PrintableCoupon::create($campaignCode, $couponCode, $couponName, $crmCustomerHashcode, $distributableUntil);
|
||||
|
||||
// THEN
|
||||
expect($first->code)->toBeInstanceOf(PrintableCouponCode::class)
|
||||
->and($first->code->equals($second->code))->toBeFalse();
|
||||
});
|
||||
|
||||
it('exposes its code as identifier', function () use (
|
||||
$campaignCode,
|
||||
$couponCode,
|
||||
$couponName,
|
||||
$crmCustomerHashcode,
|
||||
$distributableUntil,
|
||||
): void {
|
||||
// GIVEN
|
||||
$printable = PrintableCoupon::create($campaignCode, $couponCode, $couponName, $crmCustomerHashcode, $distributableUntil);
|
||||
|
||||
// WHEN / THEN
|
||||
expect($printable->id())->toBe($printable->code);
|
||||
});
|
||||
|
||||
it('has an update date equal to its creation date', function () use (
|
||||
$campaignCode,
|
||||
$couponCode,
|
||||
$couponName,
|
||||
$crmCustomerHashcode,
|
||||
$distributableUntil,
|
||||
): void {
|
||||
// GIVEN / WHEN
|
||||
$printable = PrintableCoupon::create($campaignCode, $couponCode, $couponName, $crmCustomerHashcode, $distributableUntil);
|
||||
|
||||
// THEN
|
||||
expect($printable->updatedAt)->toEqual($printable->createdAt())
|
||||
->and($printable->updatedAt())->toBe($printable->updatedAt);
|
||||
});
|
||||
|
||||
it('hydrates a printable coupon with the given values', function () use (
|
||||
$campaignCode,
|
||||
$couponCode,
|
||||
$couponName,
|
||||
$crmCustomerHashcode,
|
||||
$distributableUntil,
|
||||
): void {
|
||||
// GIVEN
|
||||
$code = PrintableCouponCode::generate();
|
||||
|
||||
// WHEN
|
||||
$printable = PrintableCoupon::hydrate(
|
||||
$code,
|
||||
$campaignCode,
|
||||
$couponCode,
|
||||
$couponName,
|
||||
$crmCustomerHashcode,
|
||||
$distributableUntil,
|
||||
);
|
||||
|
||||
// THEN
|
||||
expect($printable->code)->toBe($code)
|
||||
->and($printable->campaignCode)->toBe($campaignCode)
|
||||
->and($printable->couponCode)->toBe($couponCode)
|
||||
->and($printable->couponName)->toBe($couponName)
|
||||
->and($printable->crmCustomerHashcode)->toBe($crmCustomerHashcode)
|
||||
->and($printable->distributableUntil)->toBe($distributableUntil)
|
||||
->and($printable->createdAt())->toEqual($code->toDateTime());
|
||||
});
|
||||
});
|
||||
49
tests/Unit/Domain/Models/ValueObjects/CrmHashcodeTest.php
Normal file
49
tests/Unit/Domain/Models/ValueObjects/CrmHashcodeTest.php
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Unit\Domain\Models\ValueObjects;
|
||||
|
||||
use Domain\Models\ValueObjects\CrmHashcode;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
|
||||
covers(CrmHashcode::class);
|
||||
|
||||
describe('crm hashcode', function (): void {
|
||||
$value = Uuid::uuid4();
|
||||
|
||||
it('creates a valid hashcode', function () use ($value): void {
|
||||
// GIVEN / WHEN
|
||||
$hashcode = new CrmHashcode($value);
|
||||
|
||||
// THEN
|
||||
expect($hashcode->value)->toBe($value);
|
||||
});
|
||||
|
||||
it('is equal to a hashcode with the same value', function () use ($value): void {
|
||||
// GIVEN
|
||||
$hashcode = new CrmHashcode($value);
|
||||
$other = new CrmHashcode($value);
|
||||
|
||||
// WHEN / THEN
|
||||
expect($hashcode->equals($other))->toBeTrue();
|
||||
});
|
||||
|
||||
it('is not equal to a hashcode with a different value', function () use ($value): void {
|
||||
// GIVEN
|
||||
$hashcode = new CrmHashcode($value);
|
||||
$other = new CrmHashcode(Uuid::uuid4());
|
||||
|
||||
// WHEN / THEN
|
||||
expect($hashcode->equals($other))->toBeFalse();
|
||||
});
|
||||
|
||||
it('is not equal to a value that is not a hashcode', function () use ($value): void {
|
||||
// GIVEN
|
||||
$hashcode = new CrmHashcode($value);
|
||||
|
||||
// WHEN / THEN
|
||||
expect($hashcode->equals($value))->toBeFalse()
|
||||
->and($hashcode->equals(null))->toBeFalse();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Unit\Domain\Models\ValueObjects\PrintableCoupon;
|
||||
|
||||
use Domain\Models\ValueObjects\PrintableCoupon\MarketingDirectCode;
|
||||
|
||||
covers(MarketingDirectCode::class);
|
||||
|
||||
describe('marketing direct code', function (): void {
|
||||
it('builds a code from an incrementing integer', function (int $sequence, string $expected): void {
|
||||
expect(MarketingDirectCode::fromInt($sequence)->value)->toBe($expected);
|
||||
})->with([
|
||||
'one' => [1, '0000000000001'],
|
||||
'zero' => [0, '0000000000000'],
|
||||
'full size' => [5425003944130, '5425003944130'],
|
||||
]);
|
||||
|
||||
it('rejects a negative or too large sequence', function (int $sequence): void {
|
||||
$action = fn (): MarketingDirectCode => MarketingDirectCode::fromInt($sequence);
|
||||
|
||||
expect($action)->toThrow(\DomainException::class);
|
||||
})->with([
|
||||
'negative' => [-1],
|
||||
'too large' => [10_000_000_000_000],
|
||||
]);
|
||||
|
||||
it('converts back to its integer', function (): void {
|
||||
expect(MarketingDirectCode::fromInt(42)->toInt())->toBe(42);
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Unit\Domain\Models\ValueObjects\PrintableCoupon;
|
||||
|
||||
use Domain\Models\ValueObjects\PrintableCoupon\PrintableCouponCode;
|
||||
|
||||
covers(PrintableCouponCode::class);
|
||||
|
||||
describe('printable coupon code', function (): void {
|
||||
it('generates a unique campaign id', function (): void {
|
||||
// WHEN
|
||||
$id = PrintableCouponCode::generate();
|
||||
|
||||
// THEN
|
||||
expect($id)->toBeInstanceOf(PrintableCouponCode::class);
|
||||
});
|
||||
|
||||
it('generates different ids on each call', function (): void {
|
||||
// WHEN
|
||||
$first = PrintableCouponCode::generate();
|
||||
$second = PrintableCouponCode::generate();
|
||||
|
||||
// THEN
|
||||
expect((string) $first)->not->toBe((string) $second);
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Unit\Domain\Models\ValueObjects\PrintableCoupon;
|
||||
|
||||
use Domain\Models\ValueObjects\PrintableCoupon\PrintedCouponId;
|
||||
|
||||
covers(PrintedCouponId::class);
|
||||
|
||||
describe('printed coupon id', function (): void {
|
||||
it('generates a unique campaign id', function (): void {
|
||||
// WHEN
|
||||
$id = PrintedCouponId::generate();
|
||||
|
||||
// THEN
|
||||
expect($id)->toBeInstanceOf(PrintedCouponId::class);
|
||||
});
|
||||
|
||||
it('generates different ids on each call', function (): void {
|
||||
// WHEN
|
||||
$first = PrintedCouponId::generate();
|
||||
$second = PrintedCouponId::generate();
|
||||
|
||||
// THEN
|
||||
expect((string) $first)->not->toBe((string) $second);
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Unit\Domain\Models\ValueObjects\PrintableCoupon;
|
||||
|
||||
use Domain\Models\ValueObjects\Campaign\CampaignCode;
|
||||
use Domain\Models\ValueObjects\Coupon\CouponCode;
|
||||
use Domain\Models\ValueObjects\CrmHashcode;
|
||||
use Domain\Models\ValueObjects\PrintableCoupon\MarketingDirectCode;
|
||||
use Domain\Models\ValueObjects\PrintableCoupon\PrintableCouponCode;
|
||||
use Domain\Models\ValueObjects\PrintableCoupon\PrintedCoupon;
|
||||
use Domain\Models\ValueObjects\PrintableCoupon\PrintedCouponId;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
|
||||
covers(PrintedCoupon::class);
|
||||
|
||||
describe('printed coupon', function (): void {
|
||||
$printableCode = PrintableCouponCode::generate();
|
||||
$marketingCode = new MarketingDirectCode('0000000000001');
|
||||
$couponCode = new CouponCode('AAA01');
|
||||
$campaignCode = new CampaignCode('AAA01');
|
||||
$customer = new CrmHashcode(Uuid::uuid4());
|
||||
|
||||
it('keeps all the given values', function () use ($marketingCode, $printableCode, $couponCode, $campaignCode, $customer): void {
|
||||
// GIVEN
|
||||
$id = PrintedCouponId::generate();
|
||||
$printedAt = new \DateTimeImmutable('2026-01-01 12:00:00');
|
||||
|
||||
// WHEN
|
||||
$printed = new PrintedCoupon($id, $marketingCode, $printableCode, $couponCode, $campaignCode, $customer, $printedAt);
|
||||
|
||||
// THEN
|
||||
expect($printed->id)->toBe($id)
|
||||
->and($printed->printableCode)->toBe($printableCode)
|
||||
->and($printed->couponCode)->toBe($couponCode)
|
||||
->and($printed->campaignCode)->toBe($campaignCode)
|
||||
->and($printed->customer)->toBe($customer)
|
||||
->and($printed->printedAt)->toBe($printedAt);
|
||||
});
|
||||
|
||||
it('derives the printing date from its id', function () use ($marketingCode, $printableCode, $couponCode, $campaignCode, $customer): void {
|
||||
// GIVEN
|
||||
$id = PrintedCouponId::generate();
|
||||
$printed = new PrintedCoupon(
|
||||
$id,
|
||||
$marketingCode,
|
||||
$printableCode,
|
||||
$couponCode,
|
||||
$campaignCode,
|
||||
$customer,
|
||||
new \DateTimeImmutable('2020-01-01'),
|
||||
);
|
||||
|
||||
// WHEN
|
||||
$date = $printed->printedAt();
|
||||
|
||||
// THEN
|
||||
expect($date)->toEqual($id->toDateTime())
|
||||
->and($date)->not->toEqual($printed->printedAt);
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Unit\Domain\Models\ValueObjects\PrintableCoupon;
|
||||
|
||||
use Domain\Models\ValueObjects\Campaign\CampaignCode;
|
||||
use Domain\Models\ValueObjects\Coupon\CouponCode;
|
||||
use Domain\Models\ValueObjects\CrmHashcode;
|
||||
use Domain\Models\ValueObjects\PrintableCoupon\PrintableCouponCode;
|
||||
use Domain\Models\ValueObjects\PrintableCoupon\UnprintedCoupon;
|
||||
use Domain\Models\ValueObjects\PrintableCoupon\UnprintedReason;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
|
||||
covers(UnprintedCoupon::class);
|
||||
|
||||
describe('unprinted coupon', function (): void {
|
||||
$printableCode = PrintableCouponCode::generate();
|
||||
$couponCode = new CouponCode('AAA01');
|
||||
$campaignCode = new CampaignCode('AAA01');
|
||||
$customer = new CrmHashcode(Uuid::uuid4());
|
||||
|
||||
it('keeps all the given values', function () use ($printableCode, $couponCode, $campaignCode, $customer): void {
|
||||
// GIVEN
|
||||
$reason = new UnprintedReason('Coupon expired before printing.');
|
||||
|
||||
// WHEN
|
||||
$unprinted = new UnprintedCoupon($printableCode, $couponCode, $campaignCode, $customer, $reason);
|
||||
|
||||
// THEN
|
||||
expect($unprinted->printableCode)->toBe($printableCode)
|
||||
->and($unprinted->couponCode)->toBe($couponCode)
|
||||
->and($unprinted->campaignCode)->toBe($campaignCode)
|
||||
->and($unprinted->customer)->toBe($customer)
|
||||
->and($unprinted->unprintedReason)->toBe($reason);
|
||||
});
|
||||
|
||||
it('keeps the reason as given without trimming it', function () use ($printableCode, $couponCode, $campaignCode, $customer): void {
|
||||
// GIVEN
|
||||
$reason = new UnprintedReason(' Printer failure ');
|
||||
|
||||
// WHEN
|
||||
$unprinted = new UnprintedCoupon($printableCode, $couponCode, $campaignCode, $customer, $reason);
|
||||
|
||||
// THEN
|
||||
expect($unprinted->unprintedReason)->toBe($reason);
|
||||
});
|
||||
|
||||
it('rejects an empty reason', function (string $invalidReason) use ($printableCode, $couponCode, $campaignCode, $customer): void {
|
||||
// GIVEN / WHEN
|
||||
$action = fn (): UnprintedCoupon => new UnprintedCoupon(
|
||||
$printableCode,
|
||||
$couponCode,
|
||||
$campaignCode,
|
||||
$customer,
|
||||
new UnprintedReason($invalidReason),
|
||||
);
|
||||
|
||||
// THEN
|
||||
expect($action)->toThrow(\DomainException::class, 'Unprinted reason cannot be empty.');
|
||||
})->with([
|
||||
'empty' => '',
|
||||
'spaces' => ' ',
|
||||
'tab' => "\t",
|
||||
'new lines' => "\n\r\n",
|
||||
'mixed spaces' => " \t\n ",
|
||||
'unicode spaces' => "\u{00A0}\u{2003}",
|
||||
]);
|
||||
});
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Unit\Domain\Models\ValueObjects\PrintableCoupon;
|
||||
|
||||
use Domain\Models\ValueObjects\PrintableCoupon\UnprintedReason;
|
||||
|
||||
covers(UnprintedReason::class);
|
||||
|
||||
describe('unprinted reason', function (): void {
|
||||
$value = 'Expired date.';
|
||||
|
||||
it('creates a valid rejection reason', function () use ($value): void {
|
||||
// GIVEN / WHEN
|
||||
$reason = new UnprintedReason($value);
|
||||
|
||||
// THEN
|
||||
expect($reason)->toBeInstanceOf(UnprintedReason::class)
|
||||
->and($reason->value)->toBe($value);
|
||||
});
|
||||
|
||||
it('rejects an empty or whitespace-only reason', function (string $invalidValue): void {
|
||||
// WHEN
|
||||
$action = fn (): UnprintedReason => new UnprintedReason($invalidValue);
|
||||
|
||||
// THEN
|
||||
expect($action)->toThrow(\DomainException::class, 'Unprinted reason cannot be empty.');
|
||||
})->with([
|
||||
'empty' => '',
|
||||
'spaces' => ' ',
|
||||
]);
|
||||
});
|
||||
Loading…
Add table
Reference in a new issue