tableStatements() as $name => $sql) { $this->execute($name, $sql); } $this->ensureDepartmentArchiveSchema(); $this->ensureOrderInvoiceCollectionSchema(); $this->ensurePriceOverrideSchema(); foreach ($this->viewStatements() as $name => $sql) { $this->execute($name, $sql); } } /** * @return array */ 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, 'logs' => <<<'SQL' CREATE TABLE IF NOT EXISTS `logs` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `module` VARCHAR(191) NOT NULL, `department` VARCHAR(191) NULL, `type` INT NOT NULL, `user_id` INT NULL, `action` VARCHAR(191) NOT NULL, `message` 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_logs_module` (`module`), KEY `idx_logs_action` (`action`), KEY `idx_logs_created_at` (`created_at`) ) 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 NULL DEFAULT NULL, `visible` TINYINT(1) NOT NULL DEFAULT 1, `archived` TINYINT(1) NOT NULL DEFAULT 0, `custom_pricing_only` 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_daily_reports' => <<<'SQL' CREATE TABLE IF NOT EXISTS `department_daily_reports` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `department_id` INT NOT NULL, `water_usage` INT NOT NULL DEFAULT 0, `water_usage_morning` INT NOT NULL DEFAULT 0, `notes` TEXT NULL, `filled_by` 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_department_daily_reports_department_id` (`department_id`), KEY `idx_department_daily_reports_created_at` (`created_at`), KEY `idx_department_daily_reports_department_created_at` (`department_id`, `created_at`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci SQL, 'department_time_bookings_opening_hours' => <<<'SQL' CREATE TABLE IF NOT EXISTS `department_time_bookings_opening_hours` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `department` INT NOT NULL, `monday_start` TIME NULL, `monday_end` TIME NULL, `tuesday_start` TIME NULL, `tuesday_end` TIME NULL, `wednesday_start` TIME NULL, `wednesday_end` TIME NULL, `thursday_start` TIME NULL, `thursday_end` TIME NULL, `friday_start` TIME NULL, `friday_end` TIME NULL, `saturday_start` TIME NULL, `saturday_end` TIME NULL, `sunday_start` TIME NULL, `sunday_end` TIME 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_time_bookings_opening_hours_department` (`department`) ) 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, 'branding' => <<<'SQL' CREATE TABLE IF NOT EXISTS `branding` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `name` VARCHAR(255) NULL, `description` TEXT NULL, `cvr` INT NULL, `address` VARCHAR(255) NULL, `phone_country_code` INT NULL, `phone` INT NULL, `email` VARCHAR(255) NULL, `website` VARCHAR(255) NULL, `banner` VARCHAR(255) NULL, `logo` VARCHAR(255) NULL, `favicon` VARCHAR(255) NULL, `signature` 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_branding_deleted_at` (`deleted_at`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci SQL, 'department_lanes' => <<<'SQL' CREATE TABLE IF NOT EXISTS `department_lanes` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `department` INT NOT NULL, `name` VARCHAR(255) NOT NULL, `relay_in_id` VARCHAR(255) NULL, `relay_out_id` VARCHAR(255) NULL, `relay_machine_id` VARCHAR(255) NULL, `relay_machine_program_picker_id` VARCHAR(255) NULL, `relay_machine_cleaner_id` VARCHAR(255) NULL, `dynamic_image_id` INT NULL, `machine_type_id` INT NULL, `selfserve_enabled` 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_department_lanes_department` (`department`), KEY `idx_department_lanes_deleted_at` (`deleted_at`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci SQL, 'department_selfserve_conditions' => <<<'SQL' CREATE TABLE IF NOT EXISTS `department_selfserve_conditions` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `department` INT NOT NULL, `lane` INT NULL, `product` INT NULL, `machine_type_id` INT NULL, `condition_id` INT NULL, `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, `deleted_at` DATETIME NULL, PRIMARY KEY (`id`), KEY `idx_department_selfserve_conditions_department` (`department`), KEY `idx_department_selfserve_conditions_lane` (`lane`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci SQL, 'department_selfserve_condition_rules' => <<<'SQL' CREATE TABLE IF NOT EXISTS `department_selfserve_condition_rules` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `condition_id` INT NOT NULL, `type` VARCHAR(64) NOT NULL, `object_type` VARCHAR(64) NOT NULL, `object_id` INT NOT NULL, `name` VARCHAR(255) NULL, `description` TEXT 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_selfserve_condition_rules_condition` (`condition_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci SQL, 'department_selfserve_questions' => <<<'SQL' CREATE TABLE IF NOT EXISTS `department_selfserve_questions` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `department` INT NOT NULL, `lane` INT NULL, `product` INT NULL, `condition_id` INT NULL, `question` VARCHAR(255) NOT NULL, `description` TEXT NULL, `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_department_selfserve_questions_department` (`department`), KEY `idx_department_selfserve_questions_lane` (`lane`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci SQL, 'department_selfserve_tasks' => <<<'SQL' CREATE TABLE IF NOT EXISTS `department_selfserve_tasks` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `department` INT NOT NULL, `lane` INT NULL, `product` INT NULL, `machine_type_id` INT NULL, `condition_id` INT NULL, `gate_type` VARCHAR(16) NULL DEFAULT 'ALWAYS', `gate_ref_id` INT NULL, `task` VARCHAR(255) NOT NULL, `description` TEXT NULL, `order_priority` INT NOT NULL DEFAULT 0, `services` JSON NULL, `buttons` JSON NULL, `dynamic_images_vehicle_type` INT 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_selfserve_tasks_department` (`department`), KEY `idx_department_selfserve_tasks_lane` (`lane`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci SQL, 'department_selfserve_vehicle_conditions' => <<<'SQL' CREATE TABLE IF NOT EXISTS `department_selfserve_vehicle_conditions` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `department` INT NOT NULL, `lane` INT NULL, `customer_id` INT NULL, `reg` VARCHAR(64) NULL, `question` INT NOT NULL, `value` TINYINT(1) 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_department_selfserve_vehicle_conditions_department` (`department`), KEY `idx_department_selfserve_vehicle_conditions_reg` (`reg`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci SQL, 'selfserve_machine_types' => <<<'SQL' CREATE TABLE IF NOT EXISTS `selfserve_machine_types` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `name` VARCHAR(255) NOT NULL, `description` 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`), UNIQUE KEY `uniq_selfserve_machine_types_name` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci SQL, 'selfserve_wash_sessions' => <<<'SQL' CREATE TABLE IF NOT EXISTS `selfserve_wash_sessions` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `lane_id` INT NOT NULL, `department_id` INT NOT NULL, `machine_type_id` INT NULL, `customer_number` INT NULL, `vehicle_id` INT NULL, `vehicle_type_id` INT NULL, `reg` VARCHAR(255) NOT NULL, `status` VARCHAR(64) NOT NULL DEFAULT 'PENDING_QUESTIONS', `allowed` TINYINT(1) NOT NULL DEFAULT 0, `machine_relay_enabled` TINYINT(1) NOT NULL DEFAULT 0, `machine_relay_enabled_at` DATETIME NULL, `machine_start_triggered` TINYINT(1) NOT NULL DEFAULT 0, `machine_start_triggered_at` DATETIME NULL, `wash_started_at` DATETIME NULL, `order_id` INT NULL, `completed_at` DATETIME NULL, `metadata_json` JSON 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_selfserve_wash_sessions_lane_reg` (`lane_id`, `reg`), KEY `idx_selfserve_wash_sessions_status` (`status`), KEY `idx_selfserve_wash_sessions_customer` (`customer_number`), KEY `idx_selfserve_wash_sessions_department_completed` (`department_id`, `completed_at`), KEY `idx_selfserve_wash_sessions_order` (`order_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci SQL, 'selfserve_wash_session_answers' => <<<'SQL' CREATE TABLE IF NOT EXISTS `selfserve_wash_session_answers` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `session_id` INT NOT NULL, `question_id` INT NOT NULL, `question_text` VARCHAR(255) NOT NULL, `answer_value` TINYINT(1) NOT NULL, `answered_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `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`), UNIQUE KEY `uniq_selfserve_wash_session_answer` (`session_id`, `question_id`), KEY `idx_selfserve_wash_session_answers_session` (`session_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci SQL, 'selfserve_wash_session_tasks' => <<<'SQL' CREATE TABLE IF NOT EXISTS `selfserve_wash_session_tasks` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `session_id` INT NOT NULL, `task_id` INT NULL, `task_text` VARCHAR(255) NOT NULL, `description` TEXT NULL, `services` JSON NULL, `buttons` JSON NULL, `dynamic_image_id` INT NULL, `dynamic_images_vehicle_type` INT 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_selfserve_wash_session_tasks_session` (`session_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci SQL, 'selfserve_wash_session_events' => <<<'SQL' CREATE TABLE IF NOT EXISTS `selfserve_wash_session_events` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `session_id` INT NOT NULL, `event_type` VARCHAR(64) NOT NULL, `payload_json` JSON NULL, `created_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_selfserve_wash_session_events_session` (`session_id`), KEY `idx_selfserve_wash_session_events_type` (`event_type`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci SQL, 'plate_scanners' => <<<'SQL' CREATE TABLE IF NOT EXISTS `plate_scanners` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `department_id` INT NOT NULL, `lane_id` INT NULL, `name` VARCHAR(255) NOT NULL, `notes` TEXT NULL, `api_key` VARCHAR(191) 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_plate_scanners_department_id` (`department_id`), KEY `idx_plate_scanners_lane_id` (`lane_id`), KEY `idx_plate_scanners_api_key` (`api_key`) ) 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, `max_quantity_per_order` 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_category` (`category`) ) 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, 'product_department_prices' => <<<'SQL' CREATE TABLE IF NOT EXISTS `product_department_prices` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `department_id` INT NOT NULL, `product_id` INT NOT NULL, `price` 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`), UNIQUE KEY `uniq_product_department_prices_lookup` (`department_id`, `product_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci SQL, 'limited_backoffice_employees' => <<<'SQL' CREATE TABLE IF NOT EXISTS `limited_backoffice_employees` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `user_id` INT NOT NULL, `managed_group_id` INT NOT NULL, `role_key` VARCHAR(64) NOT NULL, `department_ids` LONGTEXT NOT NULL, `created_by_user_id` INT NOT NULL, `updated_by_user_id` INT NULL, `deactivated_at` DATETIME 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_limited_backoffice_employees_user_id` (`user_id`), KEY `idx_limited_backoffice_employees_group_id` (`managed_group_id`), KEY `idx_limited_backoffice_employees_role_key` (`role_key`), KEY `idx_limited_backoffice_employees_deactivated_at` (`deactivated_at`) ) 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`), KEY `idx_orders_period_customer_created_deleted` (`customer_id`, `created_at`, `deleted_at`), KEY `idx_orders_period_created_deleted_customer` (`created_at`, `deleted_at`, `customer_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci SQL, 'bookings' => <<<'SQL' CREATE TABLE IF NOT EXISTS `bookings` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `customer_number` INT NOT NULL, `wash_type` VARCHAR(255) NULL, `contact_email` VARCHAR(255) NULL, `reference_number` VARCHAR(255) NULL, `regNrTraekker` VARCHAR(32) NULL, `regNrTrailer` VARCHAR(32) NULL, `washCertificateEmail` VARCHAR(255) NULL, `date` DATETIME NULL, `department` INT NOT NULL DEFAULT 0, `pickup_bool` TINYINT(1) NOT NULL DEFAULT 0, `notes` TEXT NULL, `washCertificateStatus` VARCHAR(32) NULL, `washCertificateUrl` TEXT NULL, `wash_certificate_pdf` VARCHAR(255) NULL, `status` VARCHAR(32) NULL, `data` LONGTEXT NULL, `virtual_cart` TINYINT(1) 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_bookings_customer_number` (`customer_number`), KEY `idx_bookings_department` (`department`), KEY `idx_bookings_status` (`status`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci SQL, 'order_bookings' => <<<'SQL' CREATE TABLE IF NOT EXISTS `order_bookings` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `customer_number` INT NOT NULL, `department` INT NOT NULL, `reg_1` VARCHAR(32) NULL, `reg_2` VARCHAR(32) NULL, `reg_3` VARCHAR(32) NULL, `datetime` DATETIME NULL, `note` TEXT NULL, `reference` VARCHAR(255) NULL, `po` VARCHAR(255) NULL, `pickup` TINYINT(1) NOT NULL DEFAULT 0, `items` LONGTEXT NULL, `order_id` INT 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_order_bookings_department` (`department`), KEY `idx_order_bookings_customer_number` (`customer_number`), KEY `idx_order_bookings_order_id` (`order_id`), KEY `idx_order_bookings_reg_1` (`reg_1`), KEY `idx_order_bookings_deleted_at` (`deleted_at`) ) 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`), KEY `idx_order_items_order_deleted` (`order_id`, `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, 'xlvask_usage_logs' => <<<'SQL' CREATE TABLE IF NOT EXISTS `xlvask_usage_logs` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `WashId` VARCHAR(191) NOT NULL, `CustomerId` VARCHAR(191) NULL, `Customer` VARCHAR(255) NULL, `VatNumber` VARCHAR(64) NULL, `Location` VARCHAR(255) NULL, `Hall` VARCHAR(255) NULL, `HallId` VARCHAR(191) NULL, `StartTime` VARCHAR(64) NULL, `FinishTime` VARCHAR(64) NULL, `RegistrationNumber` VARCHAR(64) NULL, `VehicleType` VARCHAR(191) NULL, `IdentificationType` VARCHAR(191) NULL, `IdentificationId` VARCHAR(191) NULL, `Info` TEXT NULL, `Updated` VARCHAR(64) NULL, `Prepaid` VARCHAR(64) NULL, `FinishStatus` VARCHAR(64) NULL, `CustomerGuid` VARCHAR(191) NULL, `VehicleId` VARCHAR(191) NULL, `WashItems` LONGTEXT NULL, `ignored_at` DATETIME NULL, `ignored_by` INT NULL, `ignored_reason` TEXT NULL, `cached_total_net_amount` DECIMAL(12,2) NULL, `cached_primary_product_name` VARCHAR(255) NULL, `cached_amount_at` DATETIME NULL, PRIMARY KEY (`id`), UNIQUE KEY `uniq_xlvask_usage_logs_wash_id` (`WashId`), KEY `idx_xlvask_usage_logs_customer` (`CustomerId`), KEY `idx_xlvask_usage_logs_start` (`StartTime`) ) 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, 'passkeys' => <<<'SQL' CREATE TABLE IF NOT EXISTS `passkeys` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `user_id` INT NOT NULL, `is_subuser` TINYINT(1) NOT NULL DEFAULT 0, `credential_id` VARCHAR(4096) NOT NULL, `public_key` TEXT NOT NULL, `algorithm` VARCHAR(32) NOT NULL, `transports` JSON NULL, `sign_count` INT NOT NULL DEFAULT 0, `backup_state` JSON NULL, `name` 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_passkeys_user` (`user_id`, `is_subuser`), KEY `idx_passkeys_deleted_at` (`deleted_at`) ) 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`), KEY `idx_customer_attributes_attribute_user` (`attribute`, `user_id`) ) 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, `fixed_price` INT NULL DEFAULT NULL, `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, 'department_customer_price_overrides' => <<<'SQL' CREATE TABLE IF NOT EXISTS `department_customer_price_overrides` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `department_id` INT NOT NULL, `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, `fixed_price` INT NULL DEFAULT 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_department_customer_price_overrides_lookup` (`department_id`, `user_id`, `is_category`, `product_or_category_id`), KEY `idx_department_customer_price_overrides_department` (`department_id`), KEY `idx_department_customer_price_overrides_user` (`user_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, 'invoice_period_flags' => <<<'SQL' CREATE TABLE IF NOT EXISTS `invoice_period_flags` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `source` VARCHAR(32) NOT NULL, `severity` VARCHAR(32) NOT NULL, `status` VARCHAR(32) NOT NULL DEFAULT 'active', `target_type` VARCHAR(64) NOT NULL, `target_id` BIGINT NOT NULL, `field` VARCHAR(64) NULL, `customer_number` INT NULL, `order_id` BIGINT NULL, `order_item_id` BIGINT NULL, `invoice_collection_id` BIGINT NULL, `xlvask_usage_log_id` BIGINT NULL, `definition_key` VARCHAR(128) NULL, `fingerprint` VARCHAR(191) NULL, `reason` TEXT NULL, `status_reason` TEXT NULL, `context_json` JSON NULL, `created_by` INT NULL, `status_changed_by` INT NULL, `status_changed_at` DATETIME NULL, `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` TIMESTAMP NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uniq_invoice_period_flags_auto_fingerprint` (`source`, `fingerprint`), KEY `idx_invoice_period_flags_target` (`target_type`, `target_id`, `status`), KEY `idx_invoice_period_flags_customer_status` (`customer_number`, `status`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci SQL, ]; } /** * @return array */ 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`)' ); } if (!$this->columnExists('departments', 'custom_pricing_only')) { $this->execute( 'departments.custom_pricing_only', 'ALTER TABLE `departments` ADD COLUMN `custom_pricing_only` TINYINT(1) NOT NULL DEFAULT 0 AFTER `archived`' ); } } private function ensureOrderInvoiceCollectionSchema(): void { if (!$this->columnExists('orders', 'invoice_collection_id')) { $this->execute( 'orders.invoice_collection_id', 'ALTER TABLE `orders` ADD COLUMN `invoice_collection_id` INT NULL' ); } if (!$this->indexExists('orders', 'idx_orders_invoice_collection_id')) { $this->execute( 'orders.idx_orders_invoice_collection_id', 'ALTER TABLE `orders` ADD INDEX `idx_orders_invoice_collection_id` (`invoice_collection_id`)' ); } if (!$this->columnExists('collected_order_invoices', 'processor')) { $this->execute( 'collected_order_invoices.processor', 'ALTER TABLE `collected_order_invoices` ADD COLUMN `processor` INT NOT NULL DEFAULT 0' ); } if (!$this->columnExists('collected_order_invoices', 'booked_invoice_id')) { $this->execute( 'collected_order_invoices.booked_invoice_id', 'ALTER TABLE `collected_order_invoices` ADD COLUMN `booked_invoice_id` INT NULL' ); } if (!$this->columnExists('collected_order_invoices', 'closed_at')) { $this->execute( 'collected_order_invoices.closed_at', 'ALTER TABLE `collected_order_invoices` ADD COLUMN `closed_at` DATETIME NULL' ); } } private function ensurePriceOverrideSchema(): void { if (!$this->columnExists('price_overrides', 'fixed_price')) { $this->execute( 'price_overrides.fixed_price', 'ALTER TABLE `price_overrides` ADD COLUMN `fixed_price` INT NULL DEFAULT NULL AFTER `percentage`' ); } } 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; } }