Files
api/services/nginx/app/tests/Support/Api/ApiSchemaBootstrap.php
T
Jeppe Bundgaard 0cbc3e9aa5 Add support for archived departments with schema updates, API integration, and filtering logic
- Added `archived` column and index to `departments` table, ensuring schema initialization via `departments_schema_bootstrap`.
- Updated OpenAPI spec to include `archived` attribute and `filters=archived` query parameter with superuser access control.
- Enhanced `Departments` API to support archived department filtering and retrieval.
- Modified `ApiFixtures`, `departments_o`, and related tests to validate behavior for archived departments.
- Added unit and API tests to ensure correct handling of archived departments and filter enforceability.
2026-05-07 13:50:32 +02:00

529 lines
21 KiB
PHP

<?php
declare(strict_types=1);
namespace Tests\Support\Api;
use mysqli;
use RuntimeException;
final class ApiSchemaBootstrap
{
public function __construct(private readonly mysqli $db)
{
}
public function ensureSchema(): void
{
foreach ($this->tableStatements() as $name => $sql) {
$this->execute($name, $sql);
}
$this->ensureDepartmentArchiveSchema();
foreach ($this->viewStatements() as $name => $sql) {
$this->execute($name, $sql);
}
}
/**
* @return array<string, string>
*/
private function tableStatements(): array
{
return [
'groups' => <<<'SQL'
CREATE TABLE IF NOT EXISTS `groups` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL,
`description` TEXT NULL,
`created_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SQL,
'users' => <<<'SQL'
CREATE TABLE IF NOT EXISTS `users` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`customer_number` INT NOT NULL,
`display_name` VARCHAR(255) NULL,
`email` VARCHAR(255) NULL,
`phone_country_code` INT NULL,
`phone` BIGINT NULL,
`password` VARCHAR(255) NULL,
`group_id` INT NOT NULL DEFAULT 0,
`xlvask_customer_id` VARCHAR(255) NULL,
`sms_notifications_enabled` TINYINT(1) NOT NULL DEFAULT 0,
`email_notifications_enabled` TINYINT(1) NOT NULL DEFAULT 0,
`wash_certificate_email` VARCHAR(255) NULL,
`two_factor_enabled` TINYINT(1) NOT NULL DEFAULT 0,
`two_factor_secret` VARCHAR(255) NULL,
`created_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`deleted_at` DATETIME NULL,
PRIMARY KEY (`id`),
KEY `idx_users_customer_number` (`customer_number`),
KEY `idx_users_group_id` (`group_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SQL,
'groups_permissions' => <<<'SQL'
CREATE TABLE IF NOT EXISTS `groups_permissions` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`group_id` INT NOT NULL,
`permission` VARCHAR(191) NOT NULL,
`created_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_groups_permissions_group_id` (`group_id`),
KEY `idx_groups_permissions_permission` (`permission`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SQL,
'departments' => <<<'SQL'
CREATE TABLE IF NOT EXISTS `departments` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL,
`description` TEXT NULL,
`economic_department_id` INT NOT NULL DEFAULT 0,
`slack_webhook` TEXT NULL,
`dimension` INT NOT NULL DEFAULT 0,
`branding` INT NOT NULL DEFAULT 0,
`visible` TINYINT(1) NOT NULL DEFAULT 1,
`archived` TINYINT(1) NOT NULL DEFAULT 0,
`latitude` DECIMAL(10,7) NOT NULL DEFAULT 0,
`longitude` DECIMAL(10,7) NOT NULL DEFAULT 0,
`order_priority` INT NOT NULL DEFAULT 0,
`created_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_departments_visible` (`visible`),
KEY `idx_departments_archived` (`archived`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SQL,
'department_variables' => <<<'SQL'
CREATE TABLE IF NOT EXISTS `department_variables` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`department_id` INT NOT NULL,
`variable` VARCHAR(191) NOT NULL,
`value` TEXT NULL,
`created_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_department_variables_department_id` (`department_id`),
KEY `idx_department_variables_variable` (`variable`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SQL,
'department_gates' => <<<'SQL'
CREATE TABLE IF NOT EXISTS `department_gates` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`department` INT NOT NULL,
`is_entrance` TINYINT(1) NOT NULL DEFAULT 0,
`is_exit` TINYINT(1) NOT NULL DEFAULT 0,
`name` VARCHAR(255) NOT NULL,
`config` LONGTEXT NULL,
`created_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`deleted_at` DATETIME NULL,
PRIMARY KEY (`id`),
KEY `idx_department_gates_department` (`department`),
KEY `idx_department_gates_deleted_at` (`deleted_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SQL,
'categories' => <<<'SQL'
CREATE TABLE IF NOT EXISTS `categories` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL,
`description` TEXT NULL,
`created_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SQL,
'products' => <<<'SQL'
CREATE TABLE IF NOT EXISTS `products` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL,
`description` TEXT NULL,
`price` INT NOT NULL DEFAULT 0,
`subscription_allowed` TINYINT(1) NOT NULL DEFAULT 0,
`category` INT NOT NULL DEFAULT 0,
`piktogram` VARCHAR(255) NULL,
`economic_product_id` INT NULL,
`apply_category_discount` TINYINT(1) NOT NULL DEFAULT 1,
`requires_note` TINYINT(1) NOT NULL DEFAULT 0,
`is_wash` TINYINT(1) NOT NULL DEFAULT 0,
`display_in_booking_form` TINYINT(1) NOT NULL DEFAULT 0,
`order_priority` INT NOT NULL DEFAULT 0,
`created_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`deleted_at` DATETIME NULL,
PRIMARY KEY (`id`),
KEY `idx_products_category` (`category`),
KEY `idx_products_deleted_at` (`deleted_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SQL,
'department_categories' => <<<'SQL'
CREATE TABLE IF NOT EXISTS `department_categories` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`department_id` INT NOT NULL,
`category_id` INT NOT NULL,
`created_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`deleted_at` DATETIME NULL,
PRIMARY KEY (`id`),
KEY `idx_department_categories_department_id` (`department_id`),
KEY `idx_department_categories_category_id` (`category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SQL,
'collected_order_invoices' => <<<'SQL'
CREATE TABLE IF NOT EXISTS `collected_order_invoices` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`customer_number` INT NOT NULL,
`name` VARCHAR(255) NOT NULL,
`notes` TEXT NULL,
`processor` INT NOT NULL DEFAULT 0,
`external_id` VARCHAR(255) NULL,
`booked_invoice_id` INT NULL,
`po_number` VARCHAR(255) NULL,
`error_message` TEXT NULL,
`closed_at` DATETIME NULL,
`created_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`deleted_at` DATETIME NULL,
PRIMARY KEY (`id`),
KEY `idx_collected_order_invoices_customer_number` (`customer_number`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SQL,
'orders' => <<<'SQL'
CREATE TABLE IF NOT EXISTS `orders` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`customer_id` INT NOT NULL,
`cashier_id` INT NOT NULL DEFAULT 0,
`department_id` INT NOT NULL,
`reference` VARCHAR(255) NOT NULL,
`notes` TEXT NULL,
`reg_1` VARCHAR(32) NULL,
`reg_2` VARCHAR(32) NULL,
`reg_3` VARCHAR(32) NULL,
`invoice_collection_id` INT NULL,
`booking_id` INT NULL,
`wash_id` VARCHAR(255) NULL,
`lane` INT NULL,
`po` VARCHAR(255) NULL,
`safety_seal` VARCHAR(255) NULL,
`using_hand_held` TINYINT(1) NOT NULL DEFAULT 0,
`include_in_invoice` TINYINT(1) NOT NULL DEFAULT 1,
`created_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`completed_at` DATETIME NULL,
`deleted_at` DATETIME NULL,
PRIMARY KEY (`id`),
KEY `idx_orders_customer_id` (`customer_id`),
KEY `idx_orders_department_id` (`department_id`),
KEY `idx_orders_invoice_collection_id` (`invoice_collection_id`),
KEY `idx_orders_reg_1` (`reg_1`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SQL,
'order_items' => <<<'SQL'
CREATE TABLE IF NOT EXISTS `order_items` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`order_id` INT NOT NULL,
`product_id` INT NOT NULL,
`reference` VARCHAR(255) NULL,
`notes` TEXT NULL,
`cashier_id` INT NOT NULL DEFAULT 0,
`price` INT NOT NULL DEFAULT 0,
`quantity` INT NOT NULL DEFAULT 1,
`related_item_id` INT NULL,
`include_in_invoice` TINYINT(1) NOT NULL DEFAULT 1,
`created_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`deleted_at` DATETIME NULL,
PRIMARY KEY (`id`),
KEY `idx_order_items_order_id` (`order_id`),
KEY `idx_order_items_deleted_at` (`deleted_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SQL,
'customer_vehicles' => <<<'SQL'
CREATE TABLE IF NOT EXISTS `customer_vehicles` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`customer_id` INT NOT NULL,
`type` INT NOT NULL DEFAULT 0,
`reg` VARCHAR(32) NOT NULL,
`wash_subscription` TINYINT(1) NOT NULL DEFAULT 0,
`notes` TEXT NULL,
`reference` VARCHAR(255) NULL,
`created_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`deleted_at` DATETIME NULL,
PRIMARY KEY (`id`),
KEY `idx_customer_vehicles_customer_id` (`customer_id`),
KEY `idx_customer_vehicles_reg` (`reg`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SQL,
'xlvask_vehicle_types' => <<<'SQL'
CREATE TABLE IF NOT EXISTS `xlvask_vehicle_types` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`vehicleTypeId` VARCHAR(255) NOT NULL,
`name` VARCHAR(255) NULL,
`product` INT NOT NULL DEFAULT 0,
`created_at` INT NOT NULL DEFAULT 0,
`updated_at` INT NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
KEY `idx_xlvask_vehicle_types_product` (`product`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SQL,
'customer_vehicles_addons' => <<<'SQL'
CREATE TABLE IF NOT EXISTS `customer_vehicles_addons` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`vehicle_id` INT NOT NULL,
`addon_id` INT NOT NULL,
`amount` INT NOT NULL DEFAULT 1,
`created_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_customer_vehicles_addons_vehicle_id` (`vehicle_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SQL,
'subusers' => <<<'SQL'
CREATE TABLE IF NOT EXISTS `subusers` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`username` VARCHAR(255) NULL,
`password` VARCHAR(255) NULL,
`name` VARCHAR(255) NULL,
`email` VARCHAR(255) NULL,
`phone_country_code` INT NULL,
`phone` BIGINT NULL,
`two_factor_enabled` TINYINT(1) NOT NULL DEFAULT 0,
`two_factor_secret` VARCHAR(255) NULL,
`created_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`suspended_at` DATETIME NULL,
PRIMARY KEY (`id`),
KEY `idx_subusers_username` (`username`),
KEY `idx_subusers_phone` (`phone`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SQL,
'subuser_grants' => <<<'SQL'
CREATE TABLE IF NOT EXISTS `subuser_grants` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`billing_customer_number` INT NOT NULL,
`subuser` INT NOT NULL,
`enabled` TINYINT(1) NOT NULL DEFAULT 1,
`note` TEXT NULL,
`permissions` LONGTEXT NULL,
`created_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`deleted_at` DATETIME NULL,
PRIMARY KEY (`id`),
KEY `idx_subuser_grants_subuser` (`subuser`),
KEY `idx_subuser_grants_billing_customer_number` (`billing_customer_number`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SQL,
'tokens' => <<<'SQL'
CREATE TABLE IF NOT EXISTS `tokens` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` INT NOT NULL,
`type` VARCHAR(64) NOT NULL,
`description` VARCHAR(255) NULL,
`token` VARCHAR(255) NOT NULL,
`created_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uniq_tokens_token` (`token`),
KEY `idx_tokens_user_id` (`user_id`),
KEY `idx_tokens_type` (`type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SQL,
'customer_attributes' => <<<'SQL'
CREATE TABLE IF NOT EXISTS `customer_attributes` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` INT NOT NULL,
`attribute` VARCHAR(191) NOT NULL,
`created_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_customer_attributes_user_id` (`user_id`),
KEY `idx_customer_attributes_attribute` (`attribute`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SQL,
'module_config' => <<<'SQL'
CREATE TABLE IF NOT EXISTS `module_config` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`module` VARCHAR(191) NOT NULL,
`variable` VARCHAR(191) NOT NULL,
`value` LONGTEXT NULL,
`type` VARCHAR(64) NULL,
`created_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uniq_module_config_module_variable` (`module`, `variable`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SQL,
'user_key_value_pairs' => <<<'SQL'
CREATE TABLE IF NOT EXISTS `user_key_value_pairs` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` INT NOT NULL,
`var` VARCHAR(191) NOT NULL,
`val` LONGTEXT NULL,
`created_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_user_key_value_pairs_user_id` (`user_id`),
KEY `idx_user_key_value_pairs_var` (`var`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SQL,
'price_overrides' => <<<'SQL'
CREATE TABLE IF NOT EXISTS `price_overrides` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` INT NOT NULL,
`is_category` TINYINT(1) NOT NULL DEFAULT 0,
`product_or_category_id` VARCHAR(191) NOT NULL,
`percentage` INT NOT NULL DEFAULT 0,
`created_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_price_overrides_user_id` (`user_id`),
KEY `idx_price_overrides_lookup` (`user_id`, `is_category`, `product_or_category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SQL,
'products_options' => <<<'SQL'
CREATE TABLE IF NOT EXISTS `products_options` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`product_id` INT NOT NULL,
`option_id` INT NOT NULL,
`name` VARCHAR(255) NULL,
`min` INT NULL,
`max` INT NULL,
`created_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_products_options_product_id` (`product_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SQL,
'economic_module_orders' => <<<'SQL'
CREATE TABLE IF NOT EXISTS `economic_module_orders` (
`id` INT NOT NULL,
`invoice_draft_id` INT NULL,
`invoice_id` INT NULL,
`created_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SQL,
'stripe_module_orders' => <<<'SQL'
CREATE TABLE IF NOT EXISTS `stripe_module_orders` (
`id` INT NOT NULL,
`invoice_id` VARCHAR(255) NULL,
`customer_id` VARCHAR(255) NULL,
`email_sent` DATETIME NULL,
`url` TEXT NULL,
`created_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SQL,
'stripe_module_customers' => <<<'SQL'
CREATE TABLE IF NOT EXISTS `stripe_module_customers` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`email` VARCHAR(255) NOT NULL,
`customer_id` VARCHAR(255) NOT NULL,
`created_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uniq_stripe_module_customers_email` (`email`),
KEY `idx_stripe_module_customers_customer_id` (`customer_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SQL,
'stripe_payment_intents' => <<<'SQL'
CREATE TABLE IF NOT EXISTS `stripe_payment_intents` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`order_id` INT NOT NULL,
`payment_intent_id` VARCHAR(255) NOT NULL,
`client_secret` VARCHAR(255) NULL,
`data` LONGTEXT NULL,
`reader_id` VARCHAR(255) NULL,
`tax_percentage` INT NULL,
`created_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_stripe_payment_intents_order_id` (`order_id`),
KEY `idx_stripe_payment_intents_payment_intent_id` (`payment_intent_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SQL,
'object_attachments' => <<<'SQL'
CREATE TABLE IF NOT EXISTS `object_attachments` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`object_type` VARCHAR(191) NOT NULL,
`object_id` INT NOT NULL,
`content` LONGTEXT NULL,
`created_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`deleted_at` DATETIME NULL,
PRIMARY KEY (`id`),
KEY `idx_object_attachments_lookup` (`object_type`, `object_id`),
KEY `idx_object_attachments_deleted_at` (`deleted_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SQL,
];
}
/**
* @return array<string, string>
*/
private function viewStatements(): array
{
return [
'orders_with_invoice_collections' => <<<'SQL'
CREATE OR REPLACE VIEW `orders_with_invoice_collections` AS
SELECT
o.*,
coi.closed_at,
coi.booked_invoice_id,
coi.processor
FROM `orders` o
LEFT JOIN `collected_order_invoices` coi ON coi.id = o.invoice_collection_id
SQL,
];
}
private function execute(string $name, string $sql): void
{
if ($this->db->query($sql) === false) {
throw new RuntimeException(
sprintf('Failed to bootstrap API test schema for "%s": %s', $name, (string)$this->db->error)
);
}
}
private function ensureDepartmentArchiveSchema(): void
{
if (!$this->columnExists('departments', 'archived')) {
$this->execute(
'departments.archived',
'ALTER TABLE `departments` ADD COLUMN `archived` TINYINT(1) NOT NULL DEFAULT 0 AFTER `visible`'
);
}
if (!$this->indexExists('departments', 'idx_departments_archived')) {
$this->execute(
'departments.idx_departments_archived',
'ALTER TABLE `departments` ADD INDEX `idx_departments_archived` (`archived`)'
);
}
}
private function columnExists(string $table, string $column): bool
{
$table = $this->db->real_escape_string($table);
$column = $this->db->real_escape_string($column);
$result = $this->db->query("SHOW COLUMNS FROM `{$table}` LIKE '{$column}'");
return $result !== false && $result->num_rows > 0;
}
private function indexExists(string $table, string $index): bool
{
$table = $this->db->real_escape_string($table);
$index = $this->db->real_escape_string($index);
$result = $this->db->query("SHOW INDEX FROM `{$table}` WHERE Key_name = '{$index}'");
return $result !== false && $result->num_rows > 0;
}
}