(int)$customer['customer_number'], 'department' => (int)$department['id'], 'reg_1' => $reference, 'datetime' => '2026-07-07 10:00:00', 'note' => '', 'reference' => $reference, 'po' => '', 'pickup' => false, 'items' => [ [ 'id' => (int)$product['id'], 'quantity' => 1, ], ], ]; } function order_booking_create_department(string $name): array { $branding = api_fixtures()->createBranding([ 'name' => $name . ' Brand', 'address' => 'API Booking Street 1', ]); return api_fixtures()->createDepartment([ 'name' => $name, 'branding' => (int)$branding['id'], ]); } it('lets customers create their own order bookings without booking permissions', function (): void { api_test_covers('POST /order-bookings', 'auth'); $session = api_fixtures()->createUserSession(['user']); $department = order_booking_create_department('Own Booking Department'); $product = api_fixtures()->createProduct(['name' => 'Own Booking Product']); $response = api_client()->post( '/order-bookings', order_booking_create_payload($session['user'], $department, $product, 'OWNBOOK1'), $session['headers'] ); $response ->assertStatus(200) ->assertEnvelope() ->assertSuccess(); $bookingId = (int)($response->data()['id'] ?? 0); expect($bookingId)->toBeGreaterThan(0); $row = api_fixtures()->fetchRowById('order_bookings', $bookingId); expect($row)->not->toBeNull(); expect((int)($row['customer_number'] ?? 0))->toBe((int)$session['user']['customer_number']); api_fixtures()->cleanupDeleteById('order_bookings', $bookingId); }); it('lets subusers create own customer order bookings without the bookings add node', function (): void { api_test_covers('POST /order-bookings', 'auth'); $customer = api_fixtures()->createUser(['display_name' => 'Subuser Booking Customer']); $session = api_fixtures()->createSubuserSession((int)$customer['customer_number'], []); $department = order_booking_create_department('Subuser Booking Department'); $product = api_fixtures()->createProduct(['name' => 'Subuser Booking Product']); $response = api_client()->post( '/order-bookings', order_booking_create_payload($customer, $department, $product, 'SUBBOOK1'), $session['headers'] ); $response ->assertStatus(200) ->assertEnvelope() ->assertSuccess(); $bookingId = (int)($response->data()['id'] ?? 0); expect($bookingId)->toBeGreaterThan(0); $row = api_fixtures()->fetchRowById('order_bookings', $bookingId); expect($row)->not->toBeNull(); expect((int)($row['customer_number'] ?? 0))->toBe((int)$customer['customer_number']); api_fixtures()->cleanupDeleteById('order_bookings', $bookingId); }); it('still requires elevated access for creating another customer order booking', function (): void { api_test_covers('POST /order-bookings', 'auth'); $session = api_fixtures()->createUserSession(['user']); $otherCustomer = api_fixtures()->createUser(['display_name' => 'Other Booking Customer']); $department = api_fixtures()->createDepartment(['name' => 'Other Booking Department']); $product = api_fixtures()->createProduct(['name' => 'Other Booking Product']); $response = api_client()->post( '/order-bookings', order_booking_create_payload($otherCustomer, $department, $product, 'OTHBOOK1'), $session['headers'] ); $response ->assertStatus(403) ->assertEnvelope() ->assertSuccess(false) ->assertMissingPermissions(['add_bookings']); }); it('lets department-scoped users create order bookings for another customer', function (): void { api_test_covers('POST /order-bookings', 'happy'); $customer = api_fixtures()->createUser(['display_name' => 'Department Booking Customer']); $department = order_booking_create_department('Department Scoped Booking Department'); $product = api_fixtures()->createProduct(['name' => 'Department Scoped Booking Product']); $session = api_fixtures()->createUserSession([ 'add_bookings', 'department_access_' . $department['id'], ]); $response = api_client()->post( '/order-bookings', order_booking_create_payload($customer, $department, $product, 'DEPTBOOK'), $session['headers'] ); $response ->assertStatus(200) ->assertEnvelope() ->assertSuccess(); $bookingId = (int)($response->data()['id'] ?? 0); expect($bookingId)->toBeGreaterThan(0); api_fixtures()->cleanupDeleteById('order_bookings', $bookingId); });