222 lines
7.9 KiB
PHP
222 lines
7.9 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
usesApiSuite();
|
|
|
|
function order_booking_create_payload(array $customer, array $department, array $product, string $reference): array
|
|
{
|
|
return [
|
|
'customer_number' => (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'],
|
|
]);
|
|
}
|
|
|
|
function order_booking_create_department_price(int $departmentId, int $productId, int $price): void
|
|
{
|
|
$statement = api_test_runtime()->db()->prepare(
|
|
'INSERT INTO `product_department_prices` (`department_id`, `product_id`, `price`)
|
|
VALUES (?, ?, ?)
|
|
ON DUPLICATE KEY UPDATE `price` = VALUES(`price`)'
|
|
);
|
|
$statement->bind_param('iii', $departmentId, $productId, $price);
|
|
$statement->execute();
|
|
$statement->close();
|
|
}
|
|
|
|
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('normalizes booking item prices from server-side customer and department pricing', function (): void {
|
|
api_test_covers('POST /order-bookings', 'pricing');
|
|
|
|
$session = api_fixtures()->createUserSession(['user']);
|
|
$department = order_booking_create_department('Own Booking Pricing Department');
|
|
$product = api_fixtures()->createProduct([
|
|
'name' => 'Booking Price Normalized Product',
|
|
'price' => 0,
|
|
'is_wash' => 0,
|
|
'display_in_booking_form' => 1,
|
|
]);
|
|
order_booking_create_department_price((int)$department['id'], (int)$product['id'], 425);
|
|
|
|
$payload = order_booking_create_payload($session['user'], $department, $product, 'PRICEFIX1');
|
|
$payload['items'][0]['price'] = 0;
|
|
|
|
$response = api_client()->post('/order-bookings', $payload, $session['headers']);
|
|
|
|
$response
|
|
->assertStatus(200)
|
|
->assertEnvelope()
|
|
->assertSuccess();
|
|
|
|
$bookingId = (int)($response->data()['id'] ?? 0);
|
|
expect($bookingId)->toBeGreaterThan(0);
|
|
|
|
$responseItems = $response->data()['items'] ?? [];
|
|
expect($responseItems)
|
|
->toBeArray()
|
|
->and((int)($responseItems[0]['price'] ?? 0))->toBe(425);
|
|
|
|
$row = api_fixtures()->fetchRowById('order_bookings', $bookingId);
|
|
$storedItems = json_decode((string)($row['items'] ?? '[]'), true);
|
|
expect($storedItems)
|
|
->toBeArray()
|
|
->and((int)($storedItems[0]['price'] ?? 0))->toBe(425);
|
|
|
|
api_fixtures()->cleanupDeleteWhere('product_department_prices', [
|
|
'department_id' => (int)$department['id'],
|
|
'product_id' => (int)$product['id'],
|
|
]);
|
|
api_fixtures()->cleanupDeleteById('order_bookings', $bookingId);
|
|
});
|
|
|
|
it('blocks subusers creating 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(403)
|
|
->assertEnvelope()
|
|
->assertSuccess(false)
|
|
->assertMissingPermissions(['add_own_bookings']);
|
|
});
|
|
|
|
it('lets subusers create own customer order bookings with the bookings add node', function (): void {
|
|
api_test_covers('POST /order-bookings', 'auth');
|
|
|
|
$customer = api_fixtures()->createUser(['display_name' => 'Subuser Booking Customer With Add']);
|
|
$session = api_fixtures()->createSubuserSession((int)$customer['customer_number'], ['BOOKINGS_ADD']);
|
|
$department = order_booking_create_department('Subuser Booking Add Department');
|
|
$product = api_fixtures()->createProduct(['name' => 'Subuser Booking Add Product']);
|
|
|
|
$response = api_client()->post(
|
|
'/order-bookings',
|
|
order_booking_create_payload($customer, $department, $product, 'SUBBOOK2'),
|
|
$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);
|
|
});
|