Files
api/services/nginx/app/tests/Api/OrdersApiTest.php
T

380 lines
12 KiB
PHP

<?php
declare(strict_types=1);
usesApiSuite();
it('lists orders for an admin-scoped user and limits the results to the permitted departments', function (): void {
api_test_covers('GET /orders', 'happy');
$departmentOne = api_fixtures()->createDepartment(['name' => 'Department One']);
$departmentTwo = api_fixtures()->createDepartment(['name' => 'Department Two']);
$customerOne = api_fixtures()->createUser(['display_name' => 'Customer One']);
$customerTwo = api_fixtures()->createUser(['display_name' => 'Customer Two']);
$cashier = api_fixtures()->createUser(['display_name' => 'Cashier']);
$visibleOrder = api_fixtures()->createOrder([
'customer_id' => $customerOne['customer_number'],
'cashier_id' => $cashier['id'],
'department_id' => $departmentOne['id'],
'reference' => 'VISIBLE',
'reg_1' => 'VISIBLE1',
]);
$hiddenOrder = api_fixtures()->createOrder([
'customer_id' => $customerTwo['customer_number'],
'cashier_id' => $cashier['id'],
'department_id' => $departmentTwo['id'],
'reference' => 'HIDDEN',
'reg_1' => 'HIDDEN1',
]);
$session = api_fixtures()->createUserSession([
'list_orders',
'department_access_' . $departmentOne['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('lists only the targeted customer orders for subuser sessions', function (): void {
api_test_covers('GET /orders', 'happy');
$department = api_fixtures()->createDepartment();
$targetCustomer = api_fixtures()->createUser(['display_name' => 'Target Customer']);
$otherCustomer = api_fixtures()->createUser(['display_name' => 'Other Customer']);
$cashier = api_fixtures()->createUser(['display_name' => 'Subuser Cashier']);
$targetOrder = api_fixtures()->createOrder([
'customer_id' => $targetCustomer['customer_number'],
'cashier_id' => $cashier['id'],
'department_id' => $department['id'],
'reference' => 'TARGET',
'reg_1' => 'TARGET1',
]);
$otherOrder = api_fixtures()->createOrder([
'customer_id' => $otherCustomer['customer_number'],
'cashier_id' => $cashier['id'],
'department_id' => $department['id'],
'reference' => 'OTHER',
'reg_1' => 'OTHER1',
]);
$session = api_fixtures()->createSubuserSession(
(int)$targetCustomer['customer_number'],
['ORDERS_LIST']
);
$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($targetOrder['id'])
->not->toContain($otherOrder['id']);
expect($response->meta())->toHaveKey('target_customer_number', $targetCustomer['customer_number']);
});
it('returns the current auth and permission failures when order listing is not allowed', function (): void {
api_test_covers('GET /orders', 'auth');
$missingToken = api_client()->get('/orders');
$missingToken
->assertStatus(400)
->assertEnvelope()
->assertSuccess(false)
->assertMessage('Invalid session');
$session = api_fixtures()->createUserSession([]);
$missingPermissions = api_client()->get('/orders', $session['headers']);
$missingPermissions
->assertStatus(403)
->assertEnvelope()
->assertSuccess(false)
->assertMissingPermissions(['list_own_orders', 'list_orders']);
});
it('creates orders through the real endpoint', function (): void {
api_test_covers('POST /orders', 'happy');
$customer = api_fixtures()->createUser(['display_name' => 'Order Customer']);
$department = api_fixtures()->createDepartment();
api_fixtures()->createInvoiceCollection([
'customer_number' => $customer['customer_number'],
]);
$session = api_fixtures()->createUserSession(['add_order']);
$response = api_client()->post('/orders', [
'customer_id' => $customer['customer_number'],
'department_id' => $department['id'],
'reference' => 'ORDER-POST',
'notes' => 'Created through HTTP',
'reg_1' => 'POST123',
], $session['headers']);
$response
->assertStatus(200)
->assertEnvelope()
->assertSuccess();
$orderId = (int)($response->data()['id'] ?? 0);
expect($orderId)->toBeGreaterThan(0);
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']);
$missingReference = api_client()->post('/orders', [
'customer_id' => $customer['customer_number'],
'department_id' => $department['id'],
'notes' => 'Missing reference',
'reg_1' => 'MISSREF',
], $session['headers']);
$missingReference
->assertStatus(400)
->assertEnvelope()
->assertSuccess(false)
->assertMessage('Reference is required');
$invalidDepartment = api_client()->post('/orders', [
'customer_id' => $customer['customer_number'],
'department_id' => 999999,
'reference' => 'BAD-DEPT',
'notes' => 'Bad department',
'reg_1' => 'BADDEPT',
], $session['headers']);
$invalidDepartment
->assertStatus(500)
->assertEnvelope()
->assertSuccess(false)
->assertMessageContains('getDepartmentById()');
$invalidCustomer = api_client()->post('/orders', [
'customer_id' => 999999,
'department_id' => $department['id'],
'reference' => 'BAD-CUSTOMER',
'notes' => 'Bad customer',
'reg_1' => 'BADCUST',
], $session['headers']);
$invalidCustomer
->assertStatus(500)
->assertEnvelope()
->assertSuccess(false)
->assertMessageContains('e-conomic request failed with HTTP 404');
api_fixtures()->addCustomerAttribute((int)$customer['id'], 'requiresReferenceNumber');
$missingRequiredReference = api_client()->post('/orders', [
'customer_id' => $customer['customer_number'],
'department_id' => $department['id'],
'reference' => '',
'notes' => 'Empty reference',
'reg_1' => 'REQREF1',
], $session['headers']);
$missingRequiredReference
->assertStatus(400)
->assertEnvelope()
->assertSuccess(false)
->assertMessage('Reference is required by the customer');
});
it('updates orders through the primary endpoint', function (): void {
api_test_covers('PUT /orders', 'happy');
$department = api_fixtures()->createDepartment();
$customer = api_fixtures()->createUser();
$cashier = api_fixtures()->createUser(['display_name' => 'Order Editor']);
$order = api_fixtures()->createOrder([
'customer_id' => $customer['customer_number'],
'cashier_id' => $cashier['id'],
'department_id' => $department['id'],
'notes' => 'Before update',
]);
$session = api_fixtures()->createUserSession(['edit_order']);
$response = api_client()->put('/orders', [
'id' => $order['id'],
'notes' => 'After update',
'po' => 'PO-123',
], $session['headers']);
$response
->assertStatus(200)
->assertEnvelope()
->assertSuccess()
->assertMessage('Order updated successfully');
$row = api_fixtures()->fetchRowById('orders', (int)$order['id']);
expect($row)->not->toBeNull();
expect($row['notes'] ?? null)->toBe('After update');
expect($row['po'] ?? null)->toBe('PO-123');
});
it('rejects invalid updates through the primary order endpoint', function (): void {
api_test_covers('PUT /orders', 'failure');
$session = api_fixtures()->createUserSession(['edit_order']);
$missingId = api_client()->put('/orders', [
'notes' => 'No id',
], $session['headers']);
$missingId
->assertStatus(400)
->assertEnvelope()
->assertSuccess(false)
->assertMessage('ID is required');
$missingOrder = api_client()->put('/orders', [
'id' => 999999,
'notes' => 'Missing order',
], $session['headers']);
$missingOrder
->assertStatus(500)
->assertEnvelope()
->assertSuccess(false)
->assertMessageContains('must not be accessed before initialization');
});
it('updates orders through the legacy alias endpoint', function (): void {
api_test_covers('PUT /order', 'happy');
$department = api_fixtures()->createDepartment();
$customer = api_fixtures()->createUser();
$cashier = api_fixtures()->createUser(['display_name' => 'Legacy Editor']);
$order = api_fixtures()->createOrder([
'customer_id' => $customer['customer_number'],
'cashier_id' => $cashier['id'],
'department_id' => $department['id'],
'notes' => 'Legacy before',
]);
$session = api_fixtures()->createUserSession(['edit_order']);
$response = api_client()->put('/order', [
'id' => $order['id'],
'notes' => 'Legacy after',
], $session['headers']);
$response
->assertStatus(200)
->assertEnvelope()
->assertSuccess()
->assertMessage('Order updated successfully');
$row = api_fixtures()->fetchRowById('orders', (int)$order['id']);
expect($row)->not->toBeNull();
expect($row['notes'] ?? null)->toBe('Legacy after');
});
it('rejects invalid updates through the legacy alias endpoint', function (): void {
api_test_covers('PUT /order', 'failure');
$session = api_fixtures()->createUserSession(['edit_order']);
$response = api_client()->put('/order', [
'id' => 999999,
'notes' => 'Missing alias order',
], $session['headers']);
$response
->assertStatus(500)
->assertEnvelope()
->assertSuccess(false)
->assertMessageContains('must not be accessed before initialization');
});
it('deletes orders through the real endpoint', function (): void {
api_test_covers('DELETE /orders', 'happy');
$department = api_fixtures()->createDepartment();
$customer = api_fixtures()->createUser();
$cashier = api_fixtures()->createUser(['display_name' => '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'],
]);
$response = api_client()->delete('/orders', [
'id' => $order['id'],
], $session['headers']);
$response
->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');
$department = api_fixtures()->createDepartment();
$session = api_fixtures()->createUserSession([
'delete_order',
'department_access_' . $department['id'],
]);
$missingId = api_client()->delete('/orders', [], $session['headers']);
$missingId
->assertStatus(400)
->assertEnvelope()
->assertSuccess(false)
->assertMessage('ID is required');
$missingOrder = api_client()->delete('/orders', [
'id' => 999999,
], $session['headers']);
$missingOrder
->assertStatus(500)
->assertEnvelope()
->assertSuccess(false)
->assertMessageContains('must not be accessed before initialization');
});