additionalServicesMutable = false; $travel->transportationServicesMutable = false; $travel->pickupsMutable = false; $workingParticipant = new ParticipantDto(); $workingParticipant->index = 0; $workingParticipant->additionalServices = [$this->createService(99)]; $workingParticipant->veg = $this->createService(88); $workingParticipant->transportationOutbound = $this->createService(88); $workingParticipant->pickup = $this->createPickup(77); $workingDto = new BookingDto($travel, 1); $workingDto->participants = [$workingParticipant]; $baselineParticipant = new ParticipantDto(); $baselineParticipant->index = 0; $baselineParticipant->additionalServices = [$this->createService(10)]; $baselineParticipant->veg = $this->createService(11); $baselineParticipant->transportationOutbound = $this->createService(20); $baselineParticipant->pickup = $this->createPickup(30); $baselineDto = new BookingDto($travel, 1); $baselineDto->participants = [$baselineParticipant]; $processor = $this->createMock(BookingDataProcessor::class); $processor->expects($this->once()) ->method('createBookingDtoFromBooking') ->willReturn($baselineDto); $service = new BookingEditSubmitGuard($processor); $changed = $service->reconcileImmutableCategories($workingDto, new Booking()); $this->assertTrue($changed); $this->assertSame([10], array_map(static fn (Service $s) => $s->id, $workingParticipant->additionalServices)); $this->assertSame(11, $workingParticipant->veg?->id); $this->assertSame(20, $workingParticipant->transportationOutbound?->id); $this->assertSame(30, $workingParticipant->pickup?->id); } public function testReconcileImmutableCategoriesDoesNotChangeMutableCategories(): void { $travel = new Travel(); $travel->additionalServicesMutable = true; $travel->transportationServicesMutable = true; $travel->pickupsMutable = true; $workingParticipant = new ParticipantDto(); $workingParticipant->index = 0; $workingParticipant->additionalServices = [$this->createService(99)]; $workingDto = new BookingDto($travel, 1); $workingDto->participants = [$workingParticipant]; $baselineParticipant = new ParticipantDto(); $baselineParticipant->index = 0; $baselineParticipant->additionalServices = [$this->createService(10)]; $baselineDto = new BookingDto($travel, 1); $baselineDto->participants = [$baselineParticipant]; $processor = $this->createMock(BookingDataProcessor::class); $processor->expects($this->once()) ->method('createBookingDtoFromBooking') ->willReturn($baselineDto); $service = new BookingEditSubmitGuard($processor); $changed = $service->reconcileImmutableCategories($workingDto, new Booking()); $this->assertFalse($changed); $this->assertSame([99], array_map(static fn (Service $s) => $s->id, $workingParticipant->additionalServices)); } public function testReconcileImmutableCategoriesLocksRentalsFromFourDaysBeforeTravelStart(): void { CarbonImmutable::setTestNow('2026-01-08 12:00:00'); $travel = new Travel(); $travel->dateFrom = new \DateTimeImmutable('2026-01-10 09:00:00'); $travel->additionalServicesMutable = true; $travel->transportationServicesMutable = true; $travel->pickupsMutable = true; $workingParticipant = new ParticipantDto(); $workingParticipant->index = 0; $workingParticipant->rentals = [$this->createService(99)]; $workingDto = new BookingDto($travel, 1); $workingDto->participants = [$workingParticipant]; $baselineParticipant = new ParticipantDto(); $baselineParticipant->index = 0; $baselineParticipant->rentals = [$this->createService(10)]; $baselineDto = new BookingDto($travel, 1); $baselineDto->participants = [$baselineParticipant]; $processor = $this->createMock(BookingDataProcessor::class); $processor->expects($this->once()) ->method('createBookingDtoFromBooking') ->willReturn($baselineDto); $service = new BookingEditSubmitGuard($processor); $changed = $service->reconcileImmutableCategories($workingDto, new Booking()); $this->assertTrue($changed); $this->assertSame([10], array_map(static fn (Service $s) => $s->id, $workingParticipant->rentals)); } private function createService(int $id): Service { $service = new Service(); $service->id = $id; return $service; } private function createPickup(int $id): Pickup { $pickup = new Pickup(); $pickup->id = $id; return $pickup; } }