Implement department-specific customer pricing functionality
This commit is contained in:
@@ -0,0 +1,184 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use classes\limited_backoffice_service;
|
||||
|
||||
usesApiSuite();
|
||||
|
||||
function department_customer_pricing_price_insert(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();
|
||||
|
||||
api_fixtures()->cleanupDeleteWhere('product_department_prices', [
|
||||
'department_id' => $departmentId,
|
||||
'product_id' => $productId,
|
||||
]);
|
||||
}
|
||||
|
||||
function department_customer_pricing_setup(array $departmentAttributes = []): array
|
||||
{
|
||||
$department = api_fixtures()->createDepartment([
|
||||
'name' => 'Scoped Customer Pricing Department',
|
||||
'custom_pricing_only' => 1,
|
||||
...$departmentAttributes,
|
||||
]);
|
||||
$category = api_fixtures()->createCategory(['name' => 'Scoped Customer Pricing Category']);
|
||||
$product = api_fixtures()->createProduct([
|
||||
'name' => 'Scoped Customer Pricing Product',
|
||||
'category' => $category['id'],
|
||||
'price' => 1000,
|
||||
'apply_category_discount' => 1,
|
||||
]);
|
||||
api_fixtures()->linkDepartmentCategory((int)$department['id'], (int)$category['id']);
|
||||
department_customer_pricing_price_insert((int)$department['id'], (int)$product['id'], 1000);
|
||||
$customer = api_fixtures()->createUser(['display_name' => 'Scoped Customer Pricing Customer']);
|
||||
|
||||
return [
|
||||
'department' => $department,
|
||||
'category' => $category,
|
||||
'product' => $product,
|
||||
'customer' => $customer,
|
||||
];
|
||||
}
|
||||
|
||||
it('rejects department customer pricing when custom-only pricing is disabled', function (): void {
|
||||
api_test_covers('GET /superuser/department/customer-pricing', 'validation');
|
||||
|
||||
$fixture = department_customer_pricing_setup(['custom_pricing_only' => 0]);
|
||||
$session = api_fixtures()->createUserSession(['superuser_fetch_department_customer_pricing']);
|
||||
|
||||
$response = api_client()->get(
|
||||
'/superuser/department/customer-pricing?department_id=' . (int)$fixture['department']['id'] .
|
||||
'&user_id=' . (int)$fixture['customer']['id'],
|
||||
$session['headers']
|
||||
);
|
||||
|
||||
$response
|
||||
->assertStatus(409)
|
||||
->assertEnvelope()
|
||||
->assertSuccess(false);
|
||||
|
||||
expect($response->data()['code'] ?? null)->toBe('department_customer_pricing_disabled');
|
||||
});
|
||||
|
||||
it('sets and applies department-specific customer discounts without legacy fallback', function (): void {
|
||||
api_test_covers('GET /superuser/department/customer-pricing', 'happy');
|
||||
api_test_covers('PUT /superuser/department/customer-pricing', 'happy');
|
||||
api_test_covers('GET /products', 'pricing');
|
||||
|
||||
$fixture = department_customer_pricing_setup();
|
||||
api_fixtures()->createPriceOverride([
|
||||
'user_id' => $fixture['customer']['id'],
|
||||
'is_category' => 0,
|
||||
'product_or_category_id' => (string)$fixture['product']['id'],
|
||||
'percentage' => 80,
|
||||
]);
|
||||
|
||||
$session = api_fixtures()->createUserSession([
|
||||
'superuser_fetch_department_customer_pricing',
|
||||
'superuser_set_department_customer_pricing',
|
||||
'list_products',
|
||||
'department_access_' . (int)$fixture['department']['id'],
|
||||
]);
|
||||
|
||||
$updated = api_client()->put('/superuser/department/customer-pricing', [
|
||||
'department_id' => $fixture['department']['id'],
|
||||
'user_id' => $fixture['customer']['id'],
|
||||
'overrides' => [
|
||||
[
|
||||
'is_category' => false,
|
||||
'product_or_category_id' => $fixture['product']['id'],
|
||||
'discount' => 25,
|
||||
'fixed_price' => null,
|
||||
],
|
||||
],
|
||||
], $session['headers']);
|
||||
|
||||
$updated
|
||||
->assertStatus(200)
|
||||
->assertEnvelope()
|
||||
->assertSuccess();
|
||||
|
||||
expect($updated->data()['overrides'][0]['percentage'] ?? null)->toBe(25);
|
||||
expect($updated->data()['categories'][0]['products'][0]['effective_price'] ?? null)->toBe(750);
|
||||
|
||||
$byCustomerNumber = api_client()->get(
|
||||
'/superuser/department/customer-pricing?department_id=' . (int)$fixture['department']['id'] .
|
||||
'&customer_number=' . (int)$fixture['customer']['customer_number'],
|
||||
$session['headers']
|
||||
);
|
||||
$byCustomerNumber
|
||||
->assertStatus(200)
|
||||
->assertEnvelope()
|
||||
->assertSuccess();
|
||||
expect($byCustomerNumber->data()['customer']['id'] ?? null)->toBe((int)$fixture['customer']['id']);
|
||||
|
||||
$productResponse = api_client()->get(
|
||||
'/products?final_price=true&id=' . (int)$fixture['product']['id'] .
|
||||
'&department_id=' . (int)$fixture['department']['id'] .
|
||||
'&customer_id=' . (int)$fixture['customer']['customer_number'],
|
||||
$session['headers']
|
||||
);
|
||||
|
||||
$productResponse
|
||||
->assertStatus(200)
|
||||
->assertEnvelope()
|
||||
->assertSuccess();
|
||||
|
||||
expect((int)($productResponse->data()['price'] ?? 0))->toBe(750);
|
||||
});
|
||||
|
||||
it('limits department customer pricing to assigned limited-backoffice departments', function (): void {
|
||||
api_test_covers('GET /limited-backoffice/departments/{departmentId}/customer-pricing', 'auth');
|
||||
api_test_covers('PUT /limited-backoffice/departments/{departmentId}/customer-pricing', 'auth');
|
||||
|
||||
$fixture = department_customer_pricing_setup();
|
||||
$otherFixture = department_customer_pricing_setup(['name' => 'Denied Scoped Customer Pricing Department']);
|
||||
$session = api_fixtures()->createUserSession([
|
||||
limited_backoffice_service::PERMISSION_ACCESS,
|
||||
limited_backoffice_service::PERMISSION_MANAGE_PRICES,
|
||||
'department_access_' . (int)$fixture['department']['id'],
|
||||
]);
|
||||
|
||||
api_client()
|
||||
->get(
|
||||
'/limited-backoffice/departments/' . (int)$otherFixture['department']['id'] .
|
||||
'/customer-pricing?user_id=' . (int)$otherFixture['customer']['id'],
|
||||
$session['headers']
|
||||
)
|
||||
->assertStatus(403)
|
||||
->assertEnvelope()
|
||||
->assertSuccess(false)
|
||||
->assertMissingPermissions(['department_access_' . (int)$otherFixture['department']['id']]);
|
||||
|
||||
$updated = api_client()->put(
|
||||
'/limited-backoffice/departments/' . (int)$fixture['department']['id'] . '/customer-pricing',
|
||||
[
|
||||
'user_id' => $fixture['customer']['id'],
|
||||
'overrides' => [
|
||||
[
|
||||
'is_category' => true,
|
||||
'product_or_category_id' => (string)$fixture['category']['id'],
|
||||
'discount' => 30,
|
||||
],
|
||||
],
|
||||
],
|
||||
$session['headers']
|
||||
);
|
||||
|
||||
$updated
|
||||
->assertStatus(200)
|
||||
->assertEnvelope()
|
||||
->assertSuccess();
|
||||
|
||||
expect($updated->data()['overrides'][0]['percentage'] ?? null)->toBe(30);
|
||||
expect($updated->data()['categories'][0]['products'][0]['effective_price'] ?? null)->toBe(700);
|
||||
});
|
||||
Reference in New Issue
Block a user