531 lines
21 KiB
PHP
531 lines
21 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
usesApiSuite();
|
|
|
|
it('removes generated customer traces during fixture cleanup', function (): void {
|
|
$db = api_test_runtime()->db();
|
|
api_fixture_cleanup_ensure_optional_trace_tables($db);
|
|
|
|
$department = api_fixtures()->createDepartment(['name' => 'Fixture Cleanup Department']);
|
|
$customer = api_fixtures()->createUser(['display_name' => 'Fixture Cleanup Customer']);
|
|
$cashier = api_fixtures()->createUser(['display_name' => 'Fixture Cleanup Cashier']);
|
|
|
|
$userId = (int)$customer['id'];
|
|
$customerNumber = (int)$customer['customer_number'];
|
|
$cashierId = (int)$cashier['id'];
|
|
$departmentId = (int)$department['id'];
|
|
|
|
api_fixture_cleanup_seed_customer_traces($db, $userId, $customerNumber, $cashierId, $departmentId);
|
|
|
|
expect(api_fixture_cleanup_trace_counts($db, $userId, $customerNumber))->toMatchArray([
|
|
'users' => 1,
|
|
'customer_attributes' => 1,
|
|
'tokens' => 1,
|
|
'user_key_value_pairs' => 1,
|
|
'price_overrides' => 1,
|
|
'customer_default_department' => 1,
|
|
'customer_fixed_pricing' => 1,
|
|
'customer_fixed_pricing_versions' => 1,
|
|
'customer_vehicle_subscription_versions' => 1,
|
|
'customer_discount_override_versions' => 1,
|
|
'system_search_economic_customer_index' => 1,
|
|
'subuser_grants' => 1,
|
|
'collected_order_invoices' => 1,
|
|
'orders' => 1,
|
|
'order_items' => 1,
|
|
'economic_module_orders' => 1,
|
|
'stripe_module_orders' => 1,
|
|
'stripe_payment_intents' => 1,
|
|
'customer_vehicles' => 1,
|
|
'customer_vehicles_addons' => 1,
|
|
'object_attachments' => 4,
|
|
]);
|
|
|
|
api_test_runtime()->endTest();
|
|
|
|
expect(api_fixture_cleanup_trace_counts($db, $userId, $customerNumber))->toMatchArray([
|
|
'users' => 0,
|
|
'customer_attributes' => 0,
|
|
'tokens' => 0,
|
|
'user_key_value_pairs' => 0,
|
|
'price_overrides' => 0,
|
|
'customer_default_department' => 0,
|
|
'customer_fixed_pricing' => 0,
|
|
'customer_fixed_pricing_versions' => 0,
|
|
'customer_vehicle_subscription_versions' => 0,
|
|
'customer_discount_override_versions' => 0,
|
|
'system_search_economic_customer_index' => 0,
|
|
'subuser_grants' => 0,
|
|
'collected_order_invoices' => 0,
|
|
'orders' => 0,
|
|
'order_items' => 0,
|
|
'economic_module_orders' => 0,
|
|
'stripe_module_orders' => 0,
|
|
'stripe_payment_intents' => 0,
|
|
'customer_vehicles' => 0,
|
|
'customer_vehicles_addons' => 0,
|
|
'object_attachments' => 0,
|
|
]);
|
|
});
|
|
|
|
function api_fixture_cleanup_ensure_optional_trace_tables(mysqli $db): void
|
|
{
|
|
$statements = [
|
|
<<<'SQL'
|
|
CREATE TABLE IF NOT EXISTS `customer_default_department` (
|
|
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`customer_number` INT NOT NULL,
|
|
`department` INT NOT NULL,
|
|
`created_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
|
|
`updated_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (`id`),
|
|
KEY `idx_customer_default_department_customer_number` (`customer_number`)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
SQL,
|
|
<<<'SQL'
|
|
CREATE TABLE IF NOT EXISTS `customer_fixed_pricing` (
|
|
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`customer_number` INT NOT NULL,
|
|
`price` INT NOT NULL,
|
|
`description` VARCHAR(255) NULL,
|
|
`created_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
|
|
`updated_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (`id`),
|
|
KEY `idx_customer_fixed_pricing_customer_number` (`customer_number`)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
SQL,
|
|
<<<'SQL'
|
|
CREATE TABLE IF NOT EXISTS `customer_fixed_pricing_versions` (
|
|
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`customer_number` INT NOT NULL,
|
|
`price` INT NOT NULL,
|
|
`description` VARCHAR(255) NULL,
|
|
`effective_from` DATETIME NOT NULL,
|
|
`effective_to` DATETIME NULL,
|
|
`source` VARCHAR(64) NOT NULL DEFAULT 'fixture.test',
|
|
`confidence` DECIMAL(6,5) NOT NULL DEFAULT 1.00000,
|
|
`inferred` TINYINT(1) NOT NULL DEFAULT 0,
|
|
`metadata_json` TEXT NULL,
|
|
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (`id`),
|
|
KEY `idx_customer_fixed_pricing_versions_customer_number` (`customer_number`)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
SQL,
|
|
<<<'SQL'
|
|
CREATE TABLE IF NOT EXISTS `customer_vehicle_subscription_versions` (
|
|
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`vehicle_id` INT NULL,
|
|
`customer_number` INT NOT NULL,
|
|
`reg` VARCHAR(64) NOT NULL,
|
|
`vehicle_type` INT NOT NULL,
|
|
`wash_subscription` TINYINT(1) NOT NULL,
|
|
`effective_from` DATETIME NOT NULL,
|
|
`effective_to` DATETIME NULL,
|
|
`source` VARCHAR(64) NOT NULL DEFAULT 'fixture.test',
|
|
`confidence` DECIMAL(6,5) NOT NULL DEFAULT 1.00000,
|
|
`inferred` TINYINT(1) NOT NULL DEFAULT 0,
|
|
`metadata_json` TEXT NULL,
|
|
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (`id`),
|
|
KEY `idx_customer_vehicle_subscription_versions_customer_number` (`customer_number`)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
SQL,
|
|
<<<'SQL'
|
|
CREATE TABLE IF NOT EXISTS `customer_discount_override_versions` (
|
|
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`user_id` INT NOT NULL,
|
|
`customer_number` INT NOT NULL,
|
|
`is_category` TINYINT(1) NOT NULL,
|
|
`object_id` VARCHAR(64) NOT NULL,
|
|
`discount` INT NOT NULL,
|
|
`effective_from` DATETIME NOT NULL,
|
|
`effective_to` DATETIME NULL,
|
|
`source` VARCHAR(64) NOT NULL DEFAULT 'fixture.test',
|
|
`confidence` DECIMAL(6,5) NOT NULL DEFAULT 1.00000,
|
|
`inferred` TINYINT(1) NOT NULL DEFAULT 0,
|
|
`metadata_json` TEXT NULL,
|
|
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (`id`),
|
|
KEY `idx_customer_discount_override_versions_customer_number` (`customer_number`),
|
|
KEY `idx_customer_discount_override_versions_user_id` (`user_id`)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
SQL,
|
|
<<<'SQL'
|
|
CREATE TABLE IF NOT EXISTS `system_search_economic_customer_index` (
|
|
`customer_number` INT NOT NULL,
|
|
`user_id` INT NULL,
|
|
`local_display_name` VARCHAR(255) NULL,
|
|
`local_email` VARCHAR(255) NULL,
|
|
`local_phone` VARCHAR(64) NULL,
|
|
`economic_name` VARCHAR(255) NULL,
|
|
`economic_address` VARCHAR(255) NULL,
|
|
`economic_city` VARCHAR(255) NULL,
|
|
`economic_zip` VARCHAR(64) NULL,
|
|
`economic_email` VARCHAR(255) NULL,
|
|
`economic_cvr` VARCHAR(64) NULL,
|
|
`economic_mobile_phone` VARCHAR(64) NULL,
|
|
`economic_barred` TINYINT(1) NULL,
|
|
`search_text` TEXT NULL,
|
|
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (`customer_number`),
|
|
KEY `idx_system_search_economic_customer_index_user_id` (`user_id`)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
SQL,
|
|
];
|
|
|
|
foreach ($statements as $sql) {
|
|
$db->query($sql);
|
|
}
|
|
}
|
|
|
|
function api_fixture_cleanup_seed_customer_traces(
|
|
mysqli $db,
|
|
int $userId,
|
|
int $customerNumber,
|
|
int $cashierId,
|
|
int $departmentId
|
|
): void {
|
|
$now = '2026-04-14 12:00:00';
|
|
api_fixture_cleanup_insert($db, 'customer_attributes', [
|
|
'user_id' => $userId,
|
|
'attribute' => 'fixture_cleanup_attribute',
|
|
'created_at' => $now,
|
|
]);
|
|
api_fixture_cleanup_insert($db, 'tokens', [
|
|
'user_id' => $userId,
|
|
'type' => 'AUTH_TOKEN',
|
|
'description' => 'Fixture cleanup token',
|
|
'token' => 'fixture-cleanup-' . $userId,
|
|
'created_at' => $now,
|
|
]);
|
|
api_fixture_cleanup_insert($db, 'user_key_value_pairs', [
|
|
'user_id' => $userId,
|
|
'var' => 'fixture_cleanup_key',
|
|
'val' => 'fixture_cleanup_value',
|
|
'created_at' => $now,
|
|
'updated_at' => $now,
|
|
]);
|
|
api_fixture_cleanup_insert($db, 'price_overrides', [
|
|
'user_id' => $userId,
|
|
'is_category' => 1,
|
|
'product_or_category_id' => 'fixture_cleanup_category',
|
|
'percentage' => 25,
|
|
'created_at' => $now,
|
|
'updated_at' => $now,
|
|
]);
|
|
api_fixture_cleanup_insert($db, 'customer_default_department', [
|
|
'customer_number' => $customerNumber,
|
|
'department' => $departmentId,
|
|
'created_at' => $now,
|
|
'updated_at' => $now,
|
|
]);
|
|
api_fixture_cleanup_insert($db, 'customer_fixed_pricing', [
|
|
'customer_number' => $customerNumber,
|
|
'price' => 1999,
|
|
'description' => 'Fixture cleanup fixed pricing',
|
|
'created_at' => $now,
|
|
'updated_at' => $now,
|
|
]);
|
|
api_fixture_cleanup_insert($db, 'customer_fixed_pricing_versions', [
|
|
'customer_number' => $customerNumber,
|
|
'price' => 1999,
|
|
'description' => 'Fixture cleanup fixed pricing',
|
|
'effective_from' => $now,
|
|
'source' => 'fixture.test',
|
|
'confidence' => 1.00000,
|
|
'inferred' => 0,
|
|
'metadata_json' => '{}',
|
|
]);
|
|
api_fixture_cleanup_insert($db, 'customer_discount_override_versions', [
|
|
'user_id' => $userId,
|
|
'customer_number' => $customerNumber,
|
|
'is_category' => 1,
|
|
'object_id' => 'fixture_cleanup_category',
|
|
'discount' => 25,
|
|
'effective_from' => $now,
|
|
'source' => 'fixture.test',
|
|
'confidence' => 1.00000,
|
|
'inferred' => 0,
|
|
'metadata_json' => '{}',
|
|
]);
|
|
api_fixture_cleanup_insert($db, 'system_search_economic_customer_index', [
|
|
'customer_number' => $customerNumber,
|
|
'user_id' => $userId,
|
|
'local_display_name' => 'Fixture Cleanup Customer',
|
|
'local_email' => 'fixture-cleanup@example.test',
|
|
'search_text' => 'fixture cleanup customer',
|
|
]);
|
|
api_fixture_cleanup_insert($db, 'subuser_grants', [
|
|
'billing_customer_number' => $customerNumber,
|
|
'subuser' => $cashierId,
|
|
'enabled' => 1,
|
|
'note' => 'Fixture cleanup grant',
|
|
'permissions' => '[]',
|
|
'created_at' => $now,
|
|
'updated_at' => $now,
|
|
'deleted_at' => null,
|
|
]);
|
|
|
|
$invoiceCollectionId = api_fixture_cleanup_insert($db, 'collected_order_invoices', [
|
|
'customer_number' => $customerNumber,
|
|
'name' => 'Fixture cleanup invoice',
|
|
'notes' => 'Fixture cleanup notes',
|
|
'processor' => 0,
|
|
'created_at' => $now,
|
|
'updated_at' => $now,
|
|
]);
|
|
|
|
$orderId = api_fixture_cleanup_insert($db, 'orders', [
|
|
'customer_id' => $customerNumber,
|
|
'cashier_id' => $cashierId,
|
|
'department_id' => $departmentId,
|
|
'reference' => 'FIXTURE-CLEANUP',
|
|
'notes' => 'Fixture cleanup order',
|
|
'reg_1' => 'FC12345',
|
|
'invoice_collection_id' => $invoiceCollectionId,
|
|
'using_hand_held' => 0,
|
|
'include_in_invoice' => 1,
|
|
'created_at' => $now,
|
|
'updated_at' => $now,
|
|
'completed_at' => $now,
|
|
'deleted_at' => null,
|
|
]);
|
|
|
|
api_fixture_cleanup_insert($db, 'order_items', [
|
|
'order_id' => $orderId,
|
|
'product_id' => 61,
|
|
'reference' => 'FIXTURE-CLEANUP-ITEM',
|
|
'notes' => 'Fixture cleanup item',
|
|
'cashier_id' => $cashierId,
|
|
'price' => 250,
|
|
'quantity' => 1,
|
|
'include_in_invoice' => 1,
|
|
'created_at' => $now,
|
|
'updated_at' => $now,
|
|
'deleted_at' => null,
|
|
]);
|
|
api_fixture_cleanup_insert($db, 'economic_module_orders', [
|
|
'id' => $orderId,
|
|
'invoice_draft_id' => 9001,
|
|
'invoice_id' => 9002,
|
|
'created_at' => $now,
|
|
'updated_at' => $now,
|
|
]);
|
|
api_fixture_cleanup_insert($db, 'stripe_module_orders', [
|
|
'id' => $orderId,
|
|
'invoice_id' => 'in_fixture_cleanup',
|
|
'customer_id' => 'cus_fixture_cleanup',
|
|
'created_at' => $now,
|
|
'updated_at' => $now,
|
|
]);
|
|
api_fixture_cleanup_insert($db, 'stripe_payment_intents', [
|
|
'order_id' => $orderId,
|
|
'payment_intent_id' => 'pi_fixture_cleanup',
|
|
'client_secret' => 'secret_fixture_cleanup',
|
|
'data' => '{}',
|
|
'created_at' => $now,
|
|
'updated_at' => $now,
|
|
]);
|
|
|
|
$vehicleId = api_fixture_cleanup_insert($db, 'customer_vehicles', [
|
|
'customer_id' => $customerNumber,
|
|
'type' => 61,
|
|
'reg' => 'FC12345',
|
|
'wash_subscription' => 1,
|
|
'notes' => 'Fixture cleanup vehicle',
|
|
'reference' => 'Fixture cleanup reference',
|
|
'created_at' => $now,
|
|
'updated_at' => $now,
|
|
'deleted_at' => null,
|
|
]);
|
|
|
|
api_fixture_cleanup_insert($db, 'customer_vehicles_addons', [
|
|
'vehicle_id' => $vehicleId,
|
|
'addon_id' => 71,
|
|
'amount' => 1,
|
|
'created_at' => $now,
|
|
'updated_at' => $now,
|
|
]);
|
|
api_fixture_cleanup_insert($db, 'customer_vehicle_subscription_versions', [
|
|
'vehicle_id' => $vehicleId,
|
|
'customer_number' => $customerNumber,
|
|
'reg' => 'FC12345',
|
|
'vehicle_type' => 61,
|
|
'wash_subscription' => 1,
|
|
'effective_from' => $now,
|
|
'source' => 'fixture.test',
|
|
'confidence' => 1.00000,
|
|
'inferred' => 0,
|
|
'metadata_json' => '{}',
|
|
]);
|
|
|
|
$attachmentPayload = '{"fixture_cleanup":true}';
|
|
api_fixture_cleanup_insert($db, 'object_attachments', [
|
|
'object_type' => 'users',
|
|
'object_id' => $userId,
|
|
'content' => $attachmentPayload,
|
|
'created_at' => $now,
|
|
'updated_at' => $now,
|
|
'deleted_at' => null,
|
|
]);
|
|
api_fixture_cleanup_insert($db, 'object_attachments', [
|
|
'object_type' => 'orders',
|
|
'object_id' => $orderId,
|
|
'content' => $attachmentPayload,
|
|
'created_at' => $now,
|
|
'updated_at' => $now,
|
|
'deleted_at' => null,
|
|
]);
|
|
api_fixture_cleanup_insert($db, 'object_attachments', [
|
|
'object_type' => 'customer_vehicles',
|
|
'object_id' => $vehicleId,
|
|
'content' => $attachmentPayload,
|
|
'created_at' => $now,
|
|
'updated_at' => $now,
|
|
'deleted_at' => null,
|
|
]);
|
|
api_fixture_cleanup_insert($db, 'object_attachments', [
|
|
'object_type' => 'collected_order_invoices',
|
|
'object_id' => $invoiceCollectionId,
|
|
'content' => $attachmentPayload,
|
|
'created_at' => $now,
|
|
'updated_at' => $now,
|
|
'deleted_at' => null,
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* @return array<string, int>
|
|
*/
|
|
function api_fixture_cleanup_trace_counts(mysqli $db, int $userId, int $customerNumber): array
|
|
{
|
|
return [
|
|
'users' => api_fixture_cleanup_count($db, "SELECT COUNT(*) AS c FROM `users` WHERE `id` = {$userId}"),
|
|
'customer_attributes' => api_fixture_cleanup_count($db, "SELECT COUNT(*) AS c FROM `customer_attributes` WHERE `user_id` = {$userId}"),
|
|
'tokens' => api_fixture_cleanup_count($db, "SELECT COUNT(*) AS c FROM `tokens` WHERE `user_id` = {$userId}"),
|
|
'user_key_value_pairs' => api_fixture_cleanup_count($db, "SELECT COUNT(*) AS c FROM `user_key_value_pairs` WHERE `user_id` = {$userId}"),
|
|
'price_overrides' => api_fixture_cleanup_count($db, "SELECT COUNT(*) AS c FROM `price_overrides` WHERE `user_id` = {$userId}"),
|
|
'customer_default_department' => api_fixture_cleanup_count($db, "SELECT COUNT(*) AS c FROM `customer_default_department` WHERE `customer_number` = {$customerNumber}"),
|
|
'customer_fixed_pricing' => api_fixture_cleanup_count($db, "SELECT COUNT(*) AS c FROM `customer_fixed_pricing` WHERE `customer_number` = {$customerNumber}"),
|
|
'customer_fixed_pricing_versions' => api_fixture_cleanup_count($db, "SELECT COUNT(*) AS c FROM `customer_fixed_pricing_versions` WHERE `customer_number` = {$customerNumber}"),
|
|
'customer_vehicle_subscription_versions' => api_fixture_cleanup_count($db, "SELECT COUNT(*) AS c FROM `customer_vehicle_subscription_versions` WHERE `customer_number` = {$customerNumber}"),
|
|
'customer_discount_override_versions' => api_fixture_cleanup_count($db, "SELECT COUNT(*) AS c FROM `customer_discount_override_versions` WHERE `customer_number` = {$customerNumber}"),
|
|
'system_search_economic_customer_index' => api_fixture_cleanup_count($db, "SELECT COUNT(*) AS c FROM `system_search_economic_customer_index` WHERE `customer_number` = {$customerNumber}"),
|
|
'subuser_grants' => api_fixture_cleanup_count($db, "SELECT COUNT(*) AS c FROM `subuser_grants` WHERE `billing_customer_number` = {$customerNumber}"),
|
|
'collected_order_invoices' => api_fixture_cleanup_count($db, "SELECT COUNT(*) AS c FROM `collected_order_invoices` WHERE `customer_number` = {$customerNumber}"),
|
|
'orders' => api_fixture_cleanup_count($db, "SELECT COUNT(*) AS c FROM `orders` WHERE `customer_id` = {$customerNumber}"),
|
|
'order_items' => api_fixture_cleanup_count($db, "SELECT COUNT(*) AS c FROM `order_items` WHERE `order_id` IN (SELECT `id` FROM `orders` WHERE `customer_id` = {$customerNumber})"),
|
|
'economic_module_orders' => api_fixture_cleanup_count($db, "SELECT COUNT(*) AS c FROM `economic_module_orders` WHERE `id` IN (SELECT `id` FROM `orders` WHERE `customer_id` = {$customerNumber})"),
|
|
'stripe_module_orders' => api_fixture_cleanup_count($db, "SELECT COUNT(*) AS c FROM `stripe_module_orders` WHERE `id` IN (SELECT `id` FROM `orders` WHERE `customer_id` = {$customerNumber})"),
|
|
'stripe_payment_intents' => api_fixture_cleanup_count($db, "SELECT COUNT(*) AS c FROM `stripe_payment_intents` WHERE `order_id` IN (SELECT `id` FROM `orders` WHERE `customer_id` = {$customerNumber})"),
|
|
'customer_vehicles' => api_fixture_cleanup_count($db, "SELECT COUNT(*) AS c FROM `customer_vehicles` WHERE `customer_id` = {$customerNumber}"),
|
|
'customer_vehicles_addons' => api_fixture_cleanup_count($db, "SELECT COUNT(*) AS c FROM `customer_vehicles_addons` WHERE `vehicle_id` IN (SELECT `id` FROM `customer_vehicles` WHERE `customer_id` = {$customerNumber})"),
|
|
'object_attachments' => api_fixture_cleanup_count(
|
|
$db,
|
|
"SELECT COUNT(*) AS c
|
|
FROM `object_attachments`
|
|
WHERE (`object_type` = 'users' AND `object_id` = {$userId})
|
|
OR (`object_type` = 'orders' AND `object_id` IN (SELECT `id` FROM `orders` WHERE `customer_id` = {$customerNumber}))
|
|
OR (`object_type` = 'customer_vehicles' AND `object_id` IN (SELECT `id` FROM `customer_vehicles` WHERE `customer_id` = {$customerNumber}))
|
|
OR (`object_type` = 'collected_order_invoices' AND `object_id` IN (SELECT `id` FROM `collected_order_invoices` WHERE `customer_number` = {$customerNumber}))"
|
|
),
|
|
];
|
|
}
|
|
|
|
function api_fixture_cleanup_count(mysqli $db, string $sql): int
|
|
{
|
|
$result = $db->query($sql);
|
|
if ($result === false) {
|
|
throw new RuntimeException('Fixture cleanup assertion query failed: ' . $sql);
|
|
}
|
|
|
|
$row = $result->fetch_assoc();
|
|
$result->free();
|
|
|
|
return (int)($row['c'] ?? 0);
|
|
}
|
|
|
|
/**
|
|
* @param array<string, mixed> $data
|
|
*/
|
|
function api_fixture_cleanup_insert(mysqli $db, string $table, array $data): int
|
|
{
|
|
$filtered = [];
|
|
foreach ($data as $column => $value) {
|
|
if (api_fixture_cleanup_has_column($db, $table, $column)) {
|
|
$filtered[$column] = $value;
|
|
}
|
|
}
|
|
|
|
if ($filtered === []) {
|
|
throw new RuntimeException('No matching columns available for fixture cleanup insert into ' . $table . '.');
|
|
}
|
|
|
|
$columns = array_map(
|
|
static fn(string $column): string => '`' . $column . '`',
|
|
array_keys($filtered)
|
|
);
|
|
$values = array_map(
|
|
static fn(mixed $value): string => api_fixture_cleanup_sql_value($db, $value),
|
|
array_values($filtered)
|
|
);
|
|
|
|
$sql = 'INSERT INTO `' . $table . '` (' . implode(', ', $columns) . ') VALUES (' . implode(', ', $values) . ')';
|
|
if ($db->query($sql) === false) {
|
|
throw new RuntimeException('Fixture cleanup insert failed: ' . $sql);
|
|
}
|
|
|
|
return (int)$db->insert_id;
|
|
}
|
|
|
|
function api_fixture_cleanup_has_column(mysqli $db, string $table, string $column): bool
|
|
{
|
|
static $cache = [];
|
|
|
|
$cacheKey = $table . ':' . $column;
|
|
if (array_key_exists($cacheKey, $cache)) {
|
|
return $cache[$cacheKey];
|
|
}
|
|
|
|
$escapedTable = $db->real_escape_string($table);
|
|
$escapedColumn = $db->real_escape_string($column);
|
|
$result = $db->query(
|
|
"SELECT 1
|
|
FROM information_schema.COLUMNS
|
|
WHERE TABLE_SCHEMA = DATABASE()
|
|
AND TABLE_NAME = '{$escapedTable}'
|
|
AND COLUMN_NAME = '{$escapedColumn}'
|
|
LIMIT 1"
|
|
);
|
|
if ($result === false) {
|
|
return $cache[$cacheKey] = false;
|
|
}
|
|
|
|
$exists = $result->fetch_assoc() !== null;
|
|
$result->free();
|
|
|
|
return $cache[$cacheKey] = $exists;
|
|
}
|
|
|
|
function api_fixture_cleanup_sql_value(mysqli $db, mixed $value): string
|
|
{
|
|
if ($value === null) {
|
|
return 'NULL';
|
|
}
|
|
|
|
if (is_bool($value)) {
|
|
return $value ? '1' : '0';
|
|
}
|
|
|
|
if (is_int($value) || is_float($value)) {
|
|
return (string)$value;
|
|
}
|
|
|
|
return "'" . $db->real_escape_string((string)$value) . "'";
|
|
}
|