createDepartment(['name' => 'Orders List Visible']); $hiddenDepartment = api_fixtures()->createDepartment(['name' => 'Orders List Hidden']); $visibleCustomer = api_fixtures()->createUser(['display_name' => 'Orders List Visible Customer']); $hiddenCustomer = api_fixtures()->createUser(['display_name' => 'Orders List Hidden Customer']); $cashier = api_fixtures()->createUser(['display_name' => 'Orders List Cashier']); $visibleOrder = api_fixtures()->createOrder([ 'customer_id' => $visibleCustomer['customer_number'], 'cashier_id' => $cashier['id'], 'department_id' => $visibleDepartment['id'], 'reference' => 'VISIBLE-ORDER', 'reg_1' => 'VISIBLE1', ]); $hiddenOrder = api_fixtures()->createOrder([ 'customer_id' => $hiddenCustomer['customer_number'], 'cashier_id' => $cashier['id'], 'department_id' => $hiddenDepartment['id'], 'reference' => 'HIDDEN-ORDER', 'reg_1' => 'HIDDEN1', ]); $session = api_fixtures()->createUserSession([ 'list_orders', 'department_access_' . $visibleDepartment['id'], ]); $response = api_client()->get('/orders', $session['headers']); $response ->assertStatus(200) ->assertEnvelope() ->assertSuccess(); $orderIds = array_map( static fn(array $order): int => (int)($order['id'] ?? 0), is_array($response->data()) ? $response->data() : [] ); expect($orderIds) ->toContain($visibleOrder['id']) ->not->toContain($hiddenOrder['id']); }); it('returns auth and permission failures when order listing is not allowed', function (): void { api_test_covers('GET /orders', 'auth'); api_client()->get('/orders') ->assertStatus(400) ->assertEnvelope() ->assertSuccess(false) ->assertMessage('Invalid session'); $session = api_fixtures()->createUserSession([]); api_client()->get('/orders', $session['headers']) ->assertStatus(403) ->assertEnvelope() ->assertSuccess(false) ->assertMissingPermissions(['list_own_orders', 'list_orders']); }); it('creates orders through the orders endpoint', function (): void { api_test_covers('POST /orders', 'happy'); $customer = api_fixtures()->createUser(['display_name' => 'Order Create Customer']); $department = api_fixtures()->createDepartment(['name' => 'Order Create Department']); $session = api_fixtures()->createUserSession(['add_order']); $response = api_client()->post('/orders', [ 'customer_id' => $customer['customer_number'], 'department_id' => $department['id'], 'reference' => 'ORDER-CREATE', 'notes' => 'Created through HTTP', 'reg_1' => ' create-123 ', 'safety_seal' => 'SEAL-CREATE', ], $session['headers']); $response ->assertStatus(200) ->assertEnvelope() ->assertSuccess(); $orderId = (int)($response->data()['id'] ?? 0); expect($orderId)->toBeGreaterThan(0); $row = api_fixtures()->fetchRowById('orders', $orderId); expect($row)->not->toBeNull(); expect($row['reference'] ?? null)->toBe('ORDER-CREATE'); expect($row['reg_1'] ?? null)->toBe('CREATE123'); expect($row['safety_seal'] ?? null)->toBe('SEAL-CREATE'); api_fixtures()->cleanupDeleteById('orders', $orderId); }); it('rejects invalid order creation requests', function (): void { api_test_covers('POST /orders', 'failure'); $customer = api_fixtures()->createUser(); $department = api_fixtures()->createDepartment(); $session = api_fixtures()->createUserSession(['add_order']); api_client()->post('/orders', [ 'customer_id' => $customer['customer_number'], 'department_id' => $department['id'], 'notes' => 'Missing reference', 'reg_1' => 'MISSREF', ], $session['headers']) ->assertStatus(400) ->assertEnvelope() ->assertSuccess(false) ->assertMessage('Reference is required'); }); it('updates orders through the primary and legacy endpoints', function (): void { api_test_covers('PUT /orders', 'happy'); api_test_covers('PUT /order', 'happy'); $department = api_fixtures()->createDepartment(['name' => 'Order Update Department']); $customer = api_fixtures()->createUser(['display_name' => 'Order Update Customer']); $cashier = api_fixtures()->createUser(['display_name' => 'Order Update Cashier']); $order = api_fixtures()->createOrder([ 'customer_id' => $customer['customer_number'], 'cashier_id' => $cashier['id'], 'department_id' => $department['id'], 'reference' => 'BEFORE-UPDATE', 'notes' => 'Before update', 'reg_1' => 'BEFORE1', ]); $session = api_fixtures()->createUserSession(['edit_order']); api_client()->put('/orders', [ 'id' => $order['id'], 'reference' => 'AFTER-UPDATE', 'notes' => 'After update', 'reg_1' => ' after-123 ', ], $session['headers']) ->assertStatus(200) ->assertEnvelope() ->assertSuccess() ->assertMessage('Order updated successfully'); api_client()->put('/order', [ 'id' => $order['id'], 'field' => 'reg_2', 'value' => ' legacy-456 ', ], $session['headers']) ->assertStatus(200) ->assertEnvelope() ->assertSuccess() ->assertMessage('Order updated successfully'); $row = api_fixtures()->fetchRowById('orders', (int)$order['id']); expect($row)->not->toBeNull(); expect($row['reference'] ?? null)->toBe('AFTER-UPDATE'); expect($row['notes'] ?? null)->toBe('After update'); expect($row['reg_1'] ?? null)->toBe('AFTER123'); expect($row['reg_2'] ?? null)->toBe('LEGACY456'); }); it('rejects invalid order update requests', function (): void { api_test_covers('PUT /orders', 'failure'); api_test_covers('PUT /order', 'failure'); $session = api_fixtures()->createUserSession(['edit_order']); foreach (['/orders', '/order'] as $endpoint) { api_client()->put($endpoint, [ 'notes' => 'Missing id', ], $session['headers']) ->assertStatus(400) ->assertEnvelope() ->assertSuccess(false) ->assertMessage('ID is required'); } }); it('deletes orders through the orders endpoint', function (): void { api_test_covers('DELETE /orders', 'happy'); $department = api_fixtures()->createDepartment(['name' => 'Order Delete Department']); $customer = api_fixtures()->createUser(['display_name' => 'Order Delete Customer']); $cashier = api_fixtures()->createUser(['display_name' => 'Order Delete Cashier']); $order = api_fixtures()->createOrder([ 'customer_id' => $customer['customer_number'], 'cashier_id' => $cashier['id'], 'department_id' => $department['id'], ]); $session = api_fixtures()->createUserSession([ 'delete_order', 'department_access_' . $department['id'], ]); api_client()->delete('/orders', [ 'id' => $order['id'], ], $session['headers']) ->assertStatus(200) ->assertEnvelope() ->assertSuccess() ->assertMessage('Order deleted successfully'); $row = api_fixtures()->fetchRowById('orders', (int)$order['id']); expect($row)->not->toBeNull(); expect($row['deleted_at'] ?? null)->not->toBeNull(); }); it('rejects invalid order delete requests', function (): void { api_test_covers('DELETE /orders', 'failure'); $session = api_fixtures()->createUserSession(['delete_order']); api_client()->delete('/orders', [], $session['headers']) ->assertStatus(400) ->assertEnvelope() ->assertSuccess(false) ->assertMessage('ID is required'); });