modify('-1 month'); $couponDiffusionEnd = new DateTime()->modify('+1 month'); $makeCoupon = fn (array $overrides = []): Coupon => Coupon::create( code: $couponCode, name: $couponName, amount: new MoneyAmount(new Money(Currency::EUR, 100)), picture: new CouponPicture( new PicturePath('files/product.jpg'), new PicturePath('files/thumbnail.jpg'), new PicturePath('files/mobile_thumbnail.jpg'), ), diffusion: new CouponDiffusion( new Period( $overrides['diffusionStart'] ?? $couponDiffusionStart, $overrides['diffusionEnd'] ?? $couponDiffusionEnd, ), ), 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: $brandCode, createdBy: ActorId::generate(), products: new CouponProductArray([ new IncoCode(35784), new IncoCode(15522), ]), movements: new CouponMovementArray([ new CouponMovement(1000) ]), availabilityCalendar: $overrides['availabilityCalendar'] ?? null, ); $printRules = fn (?int $maxPerCustomer = null, ?int $cooldownDays = null): ?PrintRules => ($maxPerCustomer || $cooldownDays) ? new PrintRules( maxPerCustomer: $maxPerCustomer, cooldownDays: $cooldownDays, ) : null; $campaignCoupon = fn (?int $maxPerCustomer = null, ?int $cooldownDays = null): CampaignCoupon => new CampaignCoupon( $couponCode, $printRules($maxPerCustomer, $cooldownDays), ); $makeCampaign = fn (?int $maxPerCustomer = null, ?int $cooldownDays = null, $published = true): Campaign => Campaign::hydrate( id: CampaignId::generate(), code: $campaignCode, name: new CampaignName('Campaign name'), publication: $published, printAllAtOnce: true, coupons: new CampaignCouponArray([ $campaignCoupon($maxPerCustomer, $cooldownDays), ]), brandCode: $brandCode, actorId: ActorId::generate(), ); $printedCoupon = new PrintedCoupon( id: PrintedCouponId::generate(), marketingCode: new MarketingDirectCode('0000000000001'), printableCode: PrintableCouponCode::generate(), couponCode: $couponCode, campaignCode: $campaignCode, customer: $crmCustomerHashcode, printedAt: DatesHelper::now(), ); $makeInput = fn (Campaign $campaign): Input => new Input( campaignCode: $campaign->code, couponCode: $couponCode, crmCustomerHashcode: $crmCustomerHashcode, ); it('creates a printable coupon', function () use ($makeInput, $crmCustomerHashcode, $makeCampaign, $makeCoupon, $campaignCoupon): void { // GIVEN $campaign = $makeCampaign(); $input = $makeInput($campaign); $coupon = $makeCoupon(); $campaignRepository = \Mockery::mock(CampaignRepository::class); $campaignRepository->shouldReceive('findByCode')->once()->with($campaign->code)->andReturn($campaign); $campaignRepository->shouldReceive('findCampaignCoupon')->once()->with($campaign->code, $coupon->code) ->andReturn($campaignCoupon()); $couponRepository = \Mockery::mock(CouponRepository::class); $couponRepository->shouldReceive('findByCode')->once()->with($coupon->code)->andReturn($coupon); $printableCouponRepository = \Mockery::mock(PrintableCouponRepository::class); $printableCouponRepository->shouldReceive('save')->once()->with(\Mockery::type(PrintableCoupon::class)); $printEligibilityChecker = new PrintEligibilityChecker( $printableCouponRepository, ); $useCase = new CreatePrintableCoupon( $printableCouponRepository, $couponRepository, $campaignRepository, $printEligibilityChecker, ); // WHEN $result = $useCase->execute($input); // THEN expect($result)->toBeInstanceOf(PrintableCouponCreated::class) ->and($result->campaignCode)->toEqual($campaign->code) ->and($result->couponCode)->toEqual($coupon->code) ->and($result->crmCustomerHashcode)->toEqual($crmCustomerHashcode) ->and($result->distributableUntil)->toEqual($coupon->diffusion->period->end); }); it('rejects a printable coupon when campaign not found', function () use ($makeInput, $makeCampaign): void { // GIVEN $campaign = $makeCampaign(); $input = $makeInput($campaign); $campaignRepository = \Mockery::mock(CampaignRepository::class); $campaignRepository->shouldReceive('findByCode')->once()->with($campaign->code)->andReturn(null); $couponRepository = \Mockery::mock(CouponRepository::class); $printableCouponRepository = \Mockery::mock(PrintableCouponRepository::class); $printEligibilityChecker = new PrintEligibilityChecker( $printableCouponRepository, ); $useCase = new CreatePrintableCoupon( $printableCouponRepository, $couponRepository, $campaignRepository, $printEligibilityChecker, ); // WHEN $result = $useCase->execute($input); // THEN expect($result)->toBeInstanceOf(CampaignNotFound::class); }); it('rejects a printable coupon when campaign is not published', function () use ($makeInput, $makeCampaign): void { // GIVEN $campaign = $makeCampaign(published: false); $input = $makeInput($campaign); $campaignRepository = \Mockery::mock(CampaignRepository::class); $campaignRepository->shouldReceive('findByCode')->once()->with($campaign->code)->andReturn($campaign); $couponRepository = \Mockery::mock(CouponRepository::class); $printableCouponRepository = \Mockery::mock(PrintableCouponRepository::class); $printEligibilityChecker = new PrintEligibilityChecker( $printableCouponRepository, ); $useCase = new CreatePrintableCoupon( $printableCouponRepository, $couponRepository, $campaignRepository, $printEligibilityChecker, ); // WHEN // WHEN $result = $useCase->execute($input); // THEN expect($result)->toBeInstanceOf(CampaignNotPublished::class); }); it('rejects a printable coupon when coupon is not found', function () use ($makeInput, $makeCampaign, $makeCoupon): void { // GIVEN $campaign = $makeCampaign(); $input = $makeInput($campaign); $coupon = $makeCoupon(); $campaignRepository = \Mockery::mock(CampaignRepository::class); $campaignRepository->shouldReceive('findByCode')->once()->with($campaign->code)->andReturn($campaign); $couponRepository = \Mockery::mock(CouponRepository::class); $couponRepository->shouldReceive('findByCode')->once()->with($coupon->code)->andReturn(null); $printableCouponRepository = \Mockery::mock(PrintableCouponRepository::class); $printEligibilityChecker = new PrintEligibilityChecker( $printableCouponRepository, ); $useCase = new CreatePrintableCoupon( $printableCouponRepository, $couponRepository, $campaignRepository, $printEligibilityChecker, ); // WHEN // WHEN $result = $useCase->execute($input); // THEN expect($result)->toBeInstanceOf(CouponNotFound::class); }); it('rejects a printable coupon when campaign coupon is not found', function () use ($makeInput, $makeCampaign, $makeCoupon): void { // GIVEN $campaign = $makeCampaign(); $input = $makeInput($campaign); $coupon = $makeCoupon(); $campaignRepository = \Mockery::mock(CampaignRepository::class); $campaignRepository->shouldReceive('findByCode')->once()->with($campaign->code)->andReturn($campaign); $campaignRepository->shouldReceive('findCampaignCoupon')->once()->with($campaign->code, $coupon->code) ->andReturn(null); $couponRepository = \Mockery::mock(CouponRepository::class); $couponRepository->shouldReceive('findByCode')->once()->with($coupon->code)->andReturn($coupon); $printableCouponRepository = \Mockery::mock(PrintableCouponRepository::class); $printEligibilityChecker = new PrintEligibilityChecker( $printableCouponRepository, ); $useCase = new CreatePrintableCoupon( $printableCouponRepository, $couponRepository, $campaignRepository, $printEligibilityChecker, ); // WHEN // WHEN $result = $useCase->execute($input); // THEN expect($result)->toBeInstanceOf(CouponNotAssociated::class); }); it('rejects a printable coupon when outside of diffusion start', function () use ($makeInput, $makeCampaign, $makeCoupon, $campaignCoupon): void { // GIVEN $campaign = $makeCampaign(); $input = $makeInput($campaign); $coupon = $makeCoupon(['diffusionStart' => new DateTime()->modify('+1 day')]); $campaignRepository = \Mockery::mock(CampaignRepository::class); $campaignRepository->shouldReceive('findByCode')->once()->with($campaign->code)->andReturn($campaign); $campaignRepository->shouldReceive('findCampaignCoupon')->once()->with($campaign->code, $coupon->code) ->andReturn($campaignCoupon()); $couponRepository = \Mockery::mock(CouponRepository::class); $couponRepository->shouldReceive('findByCode')->once()->with($coupon->code)->andReturn($coupon); $printableCouponRepository = \Mockery::mock(PrintableCouponRepository::class); $printEligibilityChecker = new PrintEligibilityChecker( $printableCouponRepository, ); $useCase = new CreatePrintableCoupon( $printableCouponRepository, $couponRepository, $campaignRepository, $printEligibilityChecker, ); // WHEN $action = fn () => $useCase->execute($input); // THEN expect($action)->toThrow(\DomainException::class, 'The printing period has not yet begun.'); }); it('rejects a printable coupon when outside of diffusion end', function () use ($makeInput, $makeCampaign, $makeCoupon, $campaignCoupon): void { // GIVEN $campaign = $makeCampaign(); $input = $makeInput($campaign); $coupon = $makeCoupon(['diffusionEnd' => new DateTime()->modify('-1 day')]); $campaignRepository = \Mockery::mock(CampaignRepository::class); $campaignRepository->shouldReceive('findByCode')->once()->with($campaign->code)->andReturn($campaign); $campaignRepository->shouldReceive('findCampaignCoupon')->once()->with($campaign->code, $coupon->code) ->andReturn($campaignCoupon()); $couponRepository = \Mockery::mock(CouponRepository::class); $couponRepository->shouldReceive('findByCode')->once()->with($coupon->code)->andReturn($coupon); $printableCouponRepository = \Mockery::mock(PrintableCouponRepository::class); $printEligibilityChecker = new PrintEligibilityChecker( $printableCouponRepository, ); $useCase = new CreatePrintableCoupon( $printableCouponRepository, $couponRepository, $campaignRepository, $printEligibilityChecker, ); // WHEN $action = fn () => $useCase->execute($input); // THEN expect($action)->toThrow(\DomainException::class, 'The printing period has expired.'); }); it('creates a printable coupon when calendar period is inside diffusion period', function () use ( $makeInput, $crmCustomerHashcode, $makeCampaign, $makeCoupon, $campaignCoupon, ): void { // GIVEN $calendarStart = new DateTime()->modify('-1 day'); $calendarEnd = new DateTime()->modify('+1 day'); $campaign = $makeCampaign(); $input = $makeInput($campaign); $coupon = $makeCoupon([ 'availabilityCalendar' => new CouponAvailabilityCalendar([ new Period( start: $calendarStart, end: $calendarEnd, ), ]), ]); $campaignRepository = \Mockery::mock(CampaignRepository::class); $campaignRepository->shouldReceive('findByCode')->once()->with($campaign->code)->andReturn($campaign); $campaignRepository->shouldReceive('findCampaignCoupon')->once()->with($campaign->code, $coupon->code) ->andReturn($campaignCoupon()); $couponRepository = \Mockery::mock(CouponRepository::class); $couponRepository->shouldReceive('findByCode')->once()->with($coupon->code)->andReturn($coupon); $printableCouponRepository = \Mockery::mock(PrintableCouponRepository::class); $printableCouponRepository->shouldReceive('save')->once()->with(\Mockery::type(PrintableCoupon::class)); $printEligibilityChecker = new PrintEligibilityChecker( $printableCouponRepository, ); $useCase = new CreatePrintableCoupon( $printableCouponRepository, $couponRepository, $campaignRepository, $printEligibilityChecker, ); // WHEN $result = $useCase->execute($input); // THEN expect($result)->toBeInstanceOf(PrintableCouponCreated::class) ->and($result->campaignCode)->toEqual($campaign->code) ->and($result->crmCustomerHashcode)->toEqual($crmCustomerHashcode) ->and($result->distributableUntil)->toEqual($calendarEnd); }); it('rejects a printable coupon when maximum number of prints reached', function () use ( $makeInput, $crmCustomerHashcode, $makeCampaign, $makeCoupon, $campaignCoupon, ): void { // GIVEN $campaign = $makeCampaign(maxPerCustomer: 1); $input = $makeInput($campaign); $coupon = $makeCoupon(); $campaignRepository = \Mockery::mock(CampaignRepository::class); $campaignRepository->shouldReceive('findByCode')->once()->with($campaign->code)->andReturn($campaign); $campaignRepository->shouldReceive('findCampaignCoupon')->once()->with($campaign->code, $coupon->code) ->andReturn($campaignCoupon(maxPerCustomer: 1)); $couponRepository = \Mockery::mock(CouponRepository::class); $couponRepository->shouldReceive('findByCode')->once()->with($coupon->code)->andReturn($coupon); $printableCouponRepository = \Mockery::mock(PrintableCouponRepository::class); $printableCouponRepository->shouldReceive('countPrintedCouponForCustomer')->once()->with( $campaign->code, $coupon->code, $crmCustomerHashcode, )->andReturn(5); $printEligibilityChecker = new PrintEligibilityChecker( $printableCouponRepository, ); $useCase = new CreatePrintableCoupon( $printableCouponRepository, $couponRepository, $campaignRepository, $printEligibilityChecker, ); // WHEN $action = fn () => $useCase->execute($input); // THEN expect($action)->toThrow(\DomainException::class, 'Maximum number of prints reached.'); }); it('rejects a printable coupon when reprint period has expired', function () use ( $makeInput, $crmCustomerHashcode, $makeCampaign, $makeCoupon, $campaignCoupon, $printedCoupon, ): void { // GIVEN $campaign = $makeCampaign(cooldownDays: 30); $input = $makeInput($campaign); $coupon = $makeCoupon(); $campaignRepository = \Mockery::mock(CampaignRepository::class); $campaignRepository->shouldReceive('findByCode')->once()->with($campaign->code)->andReturn($campaign); $campaignRepository->shouldReceive('findCampaignCoupon')->once()->with($campaign->code, $coupon->code) ->andReturn($campaignCoupon(cooldownDays: 30)); $couponRepository = \Mockery::mock(CouponRepository::class); $couponRepository->shouldReceive('findByCode')->once()->with($coupon->code)->andReturn($coupon); $printableCouponRepository = \Mockery::mock(PrintableCouponRepository::class); $printableCouponRepository->shouldReceive('countPrintedCouponForCustomer')->once()->with( $campaign->code, $coupon->code, $crmCustomerHashcode, )->andReturn(5); $printableCouponRepository->shouldReceive('findLastPrintedCouponForCustomer')->once()->with( $campaign->code, $coupon->code, $crmCustomerHashcode, )->andReturn($printedCoupon); $printEligibilityChecker = new PrintEligibilityChecker( $printableCouponRepository, ); $useCase = new CreatePrintableCoupon( $printableCouponRepository, $couponRepository, $campaignRepository, $printEligibilityChecker, ); // WHEN $action = fn () => $useCase->execute($input); // THEN expect($action)->toThrow(\DomainException::class, 'Reprint period has not expired.'); }); });