id = -1; $this->booking_id = new object_property('orders', -1, 'booking_id', 'int', false); $this->safety_seal = new object_property('orders', -1, 'safety_seal', 'string', false); $this->completed_at = new object_property('orders', -1, 'completed_at', 'timestamp', false); } public bool $washCertificateAttached = false; public bool $containsWashCertificate = false; public function objectChanged(): void { } public function containsWashCertificateItem(): bool { return $this->containsWashCertificate; } public function hasWashCertificateAttached(): bool { return $this->washCertificateAttached; } } } if (!class_exists('OrderBookingsCompletionDouble')) { class OrderBookingsCompletionDouble extends order_bookings_o { public bool $containsWashCertificate = false; public bool $orderWasCreated = false; public bool $orderItemsWereCreated = false; public int $attachCalls = 0; public int $sendCalls = 0; public orders_o $linkedOrder; public function __construct(orders_o $linkedOrder) { $this->id = -1; $this->linkedOrder = $linkedOrder; $this->order_id = new object_property('order_bookings', -1, 'order_id', 'int', false); $this->items = new object_property('order_bookings', -1, 'items', 'json', false); $this->items->set([]); } public function createOrderBy(int $user_id): void { $this->orderWasCreated = true; $this->order_id->set(999); } public function createOrderItemsBy(int $user_id): void { $this->orderItemsWereCreated = true; } public function containsWashCertificateItem(): bool { return $this->containsWashCertificate; } public function getOrder(): orders_o { return $this->linkedOrder; } protected function attachWashCertificate(int $user_id, ?string $safety_seal = null): void { $this->attachCalls++; $this->linkedOrder->washCertificateAttached = true; } public function sendWashCertificateToCustomer(): void { $this->sendCalls++; } } } it('attaches and emails a wash certificate when a booking is already linked to a pos order without one', function (): void { $order = new OrderBookingsCompletionOrderDouble(); $booking = new OrderBookingsCompletionDouble($order); $booking->order_id->set(321); $booking->containsWashCertificate = true; $booking->completeBooking(77, 'LINKED-SEAL'); expect($order->getSafetySealValue())->toBe('LINKED-SEAL'); expect($booking->attachCalls)->toBe(1); expect($booking->sendCalls)->toBe(1); }); it('uses the linked pos order wash certificate item added during mobile completion', function (): void { $order = new OrderBookingsCompletionOrderDouble(); $order->containsWashCertificate = true; $booking = new OrderBookingsCompletionDouble($order); $booking->order_id->set(321); $booking->containsWashCertificate = false; $booking->completeBooking(77, 'MOBILE-SEAL'); expect($order->getSafetySealValue())->toBe('MOBILE-SEAL'); expect($booking->attachCalls)->toBe(1); expect($booking->sendCalls)->toBe(1); }); it('does not create or email a duplicate wash certificate when a linked pos order already has one', function (): void { $order = new OrderBookingsCompletionOrderDouble(); $order->washCertificateAttached = true; $booking = new OrderBookingsCompletionDouble($order); $booking->order_id->set(321); $booking->containsWashCertificate = true; $booking->completeBooking(77, 'LINKED-SEAL'); expect($order->getSafetySealValue())->toBe('LINKED-SEAL'); expect($booking->attachCalls)->toBe(0); expect($booking->sendCalls)->toBe(0); }); it('keeps standalone booking completion behavior unchanged for wash certificates', function (): void { $order = new OrderBookingsCompletionOrderDouble(); $booking = new OrderBookingsCompletionDouble($order); $booking->containsWashCertificate = true; $booking->completeBooking(77, null); expect($booking->orderWasCreated)->toBeTrue(); expect($booking->orderItemsWereCreated)->toBeTrue(); expect($booking->attachCalls)->toBe(1); expect($booking->sendCalls)->toBe(1); });