1140 lines
50 KiB
PHP
1140 lines
50 KiB
PHP
<?php
|
||
/**
|
||
* Production Setup Script
|
||
* Run once on a fresh server via CLI: php setup.php
|
||
*
|
||
* What it does:
|
||
* 1. Reads DB credentials from app/config.php
|
||
* 2. Creates wms + wms2 databases if they don't exist
|
||
* 3. Creates all tables (CREATE TABLE IF NOT EXISTS — safe to re-run)
|
||
* 4. Prints a status report
|
||
*
|
||
* Dynamic td_stock_<warehouse_id> tables are created automatically by the app
|
||
* the first time a warehouse is used; they are NOT listed here.
|
||
*/
|
||
|
||
if (PHP_SAPI !== 'cli') {
|
||
http_response_code(403);
|
||
exit('Run via CLI only: php setup.php');
|
||
}
|
||
|
||
// ── Load config ───────────────────────────────────────────────────────────────
|
||
$config = __DIR__ . '/app/config.php';
|
||
if (!file_exists($config)) {
|
||
exit("ERROR: app/config.php not found. Configure it before running setup.\n");
|
||
}
|
||
require $config;
|
||
|
||
$host = $db_server ?? 'localhost';
|
||
$user = $db_user ?? 'root';
|
||
$pass = $db_pass ?? '';
|
||
$db1 = $db_database ?? 'wms';
|
||
$db2 = $db_database2 ?? 'wms2';
|
||
|
||
// ── Helpers ───────────────────────────────────────────────────────────────────
|
||
$ok_count = 0;
|
||
$skip_count = 0;
|
||
$err_count = 0;
|
||
|
||
function info(string $msg): void { echo "\033[36m •\033[0m {$msg}\n"; }
|
||
function ok(string $msg): void { global $ok_count; $ok_count++; echo "\033[32m ✓\033[0m {$msg}\n"; }
|
||
function skip(string $msg): void { global $skip_count; $skip_count++; echo "\033[33m –\033[0m {$msg}\n"; }
|
||
function fail(string $msg): void { global $err_count; $err_count++; echo "\033[31m ✗\033[0m {$msg}\n"; }
|
||
|
||
function run(PDO $pdo, string $sql, string $label): void {
|
||
try {
|
||
$pdo->exec($sql);
|
||
ok($label);
|
||
} catch (PDOException $e) {
|
||
if (str_contains($e->getMessage(), 'already exists')) {
|
||
skip($label . ' (already exists)');
|
||
} else {
|
||
fail($label . ': ' . $e->getMessage());
|
||
}
|
||
}
|
||
}
|
||
|
||
// ── Connect (no DB selected) ──────────────────────────────────────────────────
|
||
echo "\n\033[1m=== mn3wms Production Setup ===\033[0m\n\n";
|
||
echo "Host : {$host}\n";
|
||
echo "DB1 : {$db1} (auth / identity)\n";
|
||
echo "DB2 : {$db2} (business data)\n\n";
|
||
|
||
try {
|
||
$pdo = new PDO("mysql:host={$host};charset=utf8", $user, $pass);
|
||
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||
ok("Connected to MySQL as {$user}@{$host}");
|
||
} catch (PDOException $e) {
|
||
fail("Cannot connect: " . $e->getMessage());
|
||
exit(1);
|
||
}
|
||
|
||
// ── Create databases ──────────────────────────────────────────────────────────
|
||
echo "\n--- Databases ---\n";
|
||
run($pdo, "CREATE DATABASE IF NOT EXISTS `{$db1}` CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci", "Database `{$db1}`");
|
||
run($pdo, "CREATE DATABASE IF NOT EXISTS `{$db2}` CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci", "Database `{$db2}`");
|
||
|
||
// ─────────────────────────────────────────────────────────────────────────────
|
||
// WMS (auth / identity) tables
|
||
// ─────────────────────────────────────────────────────────────────────────────
|
||
echo "\n--- {$db1} tables ---\n";
|
||
$pdo->exec("USE `{$db1}`");
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `user` (
|
||
`user_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||
`username` varchar(255) NOT NULL,
|
||
`password` varchar(255) NOT NULL,
|
||
`email` varchar(255) NOT NULL,
|
||
`status` varchar(40) NOT NULL DEFAULT 'not activated',
|
||
`name` tinytext NOT NULL,
|
||
`surname` tinytext NOT NULL,
|
||
`address` tinytext DEFAULT NULL,
|
||
`country` varchar(50) NOT NULL DEFAULT '',
|
||
`profile_picture` tinytext NOT NULL,
|
||
`default_company` int(11) DEFAULT 0,
|
||
`language` varchar(3) NOT NULL DEFAULT 'th',
|
||
`regis_date` timestamp NOT NULL DEFAULT current_timestamp(),
|
||
`license` enum('owner','user') NOT NULL DEFAULT 'owner',
|
||
`app_access` enum('all','wms','accounting') NOT NULL DEFAULT 'all',
|
||
`active` varchar(255) NOT NULL DEFAULT 'yes',
|
||
`phone` varchar(50) NOT NULL DEFAULT '',
|
||
`verify_token` varchar(64) DEFAULT NULL,
|
||
`verify_expires_at` datetime DEFAULT NULL,
|
||
`login_attempts` int(11) NOT NULL DEFAULT 0,
|
||
`locked_until` datetime DEFAULT NULL,
|
||
PRIMARY KEY (`user_id`),
|
||
UNIQUE KEY `username` (`username`),
|
||
UNIQUE KEY `email` (`email`),
|
||
KEY `idx_user_verify_token` (`verify_token`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||
", 'user');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `company_list` (
|
||
`company_id` int(11) NOT NULL AUTO_INCREMENT,
|
||
`channel_name` varchar(100) NOT NULL DEFAULT '' COMMENT 'Unique slug used for login routing',
|
||
`company_name` varchar(255) NOT NULL DEFAULT '',
|
||
`company_name2` varchar(255) NOT NULL DEFAULT '' COMMENT 'Secondary / English name',
|
||
`company_logo` varchar(255) NOT NULL DEFAULT '',
|
||
`company_seal` varchar(255) NOT NULL DEFAULT '',
|
||
`branch` varchar(255) NOT NULL DEFAULT 'สำนักงานใหญ่',
|
||
`branch_no` varchar(50) NOT NULL DEFAULT '',
|
||
`fiscal_year` varchar(10) NOT NULL DEFAULT '',
|
||
`fx` varchar(10) NOT NULL DEFAULT 'thb',
|
||
`address` text NOT NULL DEFAULT '',
|
||
`address2` text NOT NULL DEFAULT '',
|
||
`tax_id` varchar(50) NOT NULL DEFAULT '',
|
||
`prompt_pay` varchar(50) NOT NULL DEFAULT '',
|
||
`entrepreneur` varchar(100) NOT NULL DEFAULT '',
|
||
`email` varchar(255) NOT NULL DEFAULT '',
|
||
`phone` varchar(50) NOT NULL DEFAULT '',
|
||
`fax` varchar(50) NOT NULL DEFAULT '',
|
||
`website` varchar(255) NOT NULL DEFAULT '',
|
||
`facebook_page` varchar(255) NOT NULL DEFAULT '',
|
||
`package` varchar(50) NOT NULL DEFAULT 'starter',
|
||
PRIMARY KEY (`company_id`),
|
||
UNIQUE KEY `channel_name` (`channel_name`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||
", 'company_list');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `company_map_user` (
|
||
`map_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) DEFAULT NULL,
|
||
`user_id` int(11) DEFAULT NULL,
|
||
`role` varchar(15) NOT NULL DEFAULT 'user',
|
||
`app_access` varchar(15) NOT NULL DEFAULT 'wms',
|
||
`invite_token` varchar(64) DEFAULT NULL,
|
||
`created_at` datetime DEFAULT NULL,
|
||
PRIMARY KEY (`map_id`),
|
||
KEY `user_id` (`user_id`),
|
||
KEY `company_id` (`company_id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||
", 'company_map_user');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `company_setting` (
|
||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) NOT NULL,
|
||
`setting_key` varchar(64) NOT NULL,
|
||
`value` varchar(255) NOT NULL DEFAULT '',
|
||
`updated_at` datetime DEFAULT NULL,
|
||
`log` mediumtext DEFAULT NULL,
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `company_key` (`company_id`,`setting_key`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||
", 'company_setting');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `company_smtp` (
|
||
`smtp_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(10) unsigned NOT NULL,
|
||
`server` varchar(255) NOT NULL,
|
||
`port` varchar(10) NOT NULL DEFAULT '587',
|
||
`username` varchar(255) NOT NULL,
|
||
`password` text NOT NULL,
|
||
`from_name` varchar(255) NOT NULL DEFAULT '',
|
||
`from_email` varchar(255) NOT NULL DEFAULT '',
|
||
`encryption` enum('tls','ssl','none') NOT NULL DEFAULT 'tls',
|
||
`updated_at` datetime DEFAULT NULL,
|
||
PRIMARY KEY (`smtp_id`),
|
||
UNIQUE KEY `uq_company_smtp` (`company_id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||
", 'company_smtp');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `company_usage` (
|
||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) NOT NULL,
|
||
`day_date` date NOT NULL,
|
||
`daily_count` int(11) NOT NULL DEFAULT 0,
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `uq_company_day` (`company_id`,`day_date`),
|
||
KEY `idx_company_id` (`company_id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||
", 'company_usage');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `schema_migrations` (
|
||
`version` varchar(64) NOT NULL,
|
||
`applied_at` datetime NOT NULL DEFAULT current_timestamp(),
|
||
PRIMARY KEY (`version`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||
", 'schema_migrations');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `whitelist` (
|
||
`list_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||
`cookie` varchar(32) NOT NULL,
|
||
`status` int(11) NOT NULL DEFAULT 1 COMMENT '0=block 1=wait 2=allow',
|
||
`ip` varchar(20) NOT NULL,
|
||
`dt` timestamp NOT NULL DEFAULT current_timestamp(),
|
||
PRIMARY KEY (`list_id`),
|
||
UNIQUE KEY `cookie` (`cookie`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||
", 'whitelist');
|
||
|
||
// ─────────────────────────────────────────────────────────────────────────────
|
||
// WMS2 (business data) tables
|
||
// ─────────────────────────────────────────────────────────────────────────────
|
||
echo "\n--- {$db2} tables ---\n";
|
||
$pdo->exec("USE `{$db2}`");
|
||
|
||
// ── Master data ───────────────────────────────────────────────────────────────
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `md_warehouse` (
|
||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) NOT NULL DEFAULT 0,
|
||
`warehouse_name` varchar(255) NOT NULL DEFAULT '',
|
||
`location` text NOT NULL DEFAULT '',
|
||
`manager` int(11) NOT NULL DEFAULT 0,
|
||
`description` text NOT NULL DEFAULT '',
|
||
`status` int(1) NOT NULL DEFAULT 1,
|
||
`log` mediumtext NOT NULL DEFAULT '{}',
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `company_id_warehouse_name` (`company_id`,`warehouse_name`),
|
||
KEY `company_id` (`company_id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||
", 'md_warehouse');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `md_storage` (
|
||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) NOT NULL DEFAULT 0,
|
||
`warehouse` varchar(255) NOT NULL DEFAULT '',
|
||
`zone` text NOT NULL DEFAULT '',
|
||
`aisle_from` varchar(255) NOT NULL DEFAULT '',
|
||
`aisle_to` varchar(255) NOT NULL DEFAULT '',
|
||
`rack_from` varchar(255) NOT NULL DEFAULT '',
|
||
`rack_to` varchar(255) NOT NULL DEFAULT '',
|
||
`description` text NOT NULL DEFAULT '',
|
||
`status` int(1) NOT NULL DEFAULT 1,
|
||
`log` mediumtext NOT NULL DEFAULT '{}',
|
||
PRIMARY KEY (`id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||
", 'md_storage');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `md_rack` (
|
||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) NOT NULL,
|
||
`td_stock_id` int(11) NOT NULL DEFAULT 0,
|
||
`warehouse` int(11) NOT NULL,
|
||
`storage_id` int(11) NOT NULL DEFAULT 0,
|
||
`zone` varchar(10) NOT NULL,
|
||
`aisle` varchar(10) NOT NULL,
|
||
`rack` varchar(10) NOT NULL,
|
||
`product_sku` varchar(50) DEFAULT NULL,
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `uk_rack_location` (`company_id`,`warehouse`,`zone`,`aisle`,`rack`),
|
||
KEY `idx_storage` (`storage_id`),
|
||
KEY `idx_sku` (`company_id`,`product_sku`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||
", 'md_rack');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `td_rack_log` (
|
||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(10) NOT NULL,
|
||
`md_rack_id` int(10) unsigned NOT NULL,
|
||
`user_id` int(10) unsigned DEFAULT NULL,
|
||
`dt` datetime NOT NULL DEFAULT current_timestamp(),
|
||
`login` datetime DEFAULT NULL,
|
||
`action` enum('occupy','release','transfer_in','transfer_out') NOT NULL,
|
||
`product_sku` varchar(100) DEFAULT NULL,
|
||
`td_stock_id` int(10) unsigned DEFAULT NULL,
|
||
PRIMARY KEY (`id`),
|
||
KEY `idx_rack` (`company_id`,`md_rack_id`),
|
||
KEY `idx_user` (`company_id`,`user_id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||
", 'td_rack_log');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `md_product_category` (
|
||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) NOT NULL DEFAULT 0,
|
||
`category` varchar(255) NOT NULL DEFAULT '',
|
||
`slug` varchar(255) NOT NULL DEFAULT '',
|
||
`description` text NOT NULL DEFAULT '',
|
||
`status` int(1) NOT NULL DEFAULT 1,
|
||
`log` mediumtext NOT NULL DEFAULT '{}',
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `company_id_product_id` (`company_id`,`category`),
|
||
KEY `company_id` (`company_id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||
", 'md_product_category');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `md_product` (
|
||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) NOT NULL DEFAULT 0,
|
||
`product_name` varchar(255) NOT NULL DEFAULT '',
|
||
`sku` varchar(255) NOT NULL DEFAULT '',
|
||
`barcode` varchar(64) DEFAULT NULL,
|
||
`price` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`cost_price` decimal(15,2) NOT NULL DEFAULT 0.00,
|
||
`tax_rate` decimal(5,2) NOT NULL DEFAULT 0.00,
|
||
`sales_account_code` varchar(20) DEFAULT NULL,
|
||
`purchase_account_code` varchar(20) DEFAULT NULL,
|
||
`uom` varchar(20) NOT NULL DEFAULT 'pcs',
|
||
`min_stock` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`reorder_point` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`category` int(11) NOT NULL DEFAULT 0,
|
||
`product_image` text NOT NULL DEFAULT '',
|
||
`description` text NOT NULL DEFAULT '',
|
||
`status` int(1) NOT NULL DEFAULT 1,
|
||
`log` mediumtext NOT NULL DEFAULT '{}',
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `company_id_product_id` (`company_id`,`product_name`),
|
||
KEY `company_id` (`company_id`),
|
||
KEY `idx_product_barcode` (`company_id`,`barcode`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||
", 'md_product');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `md_lot` (
|
||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(10) unsigned NOT NULL,
|
||
`product_sku` varchar(100) NOT NULL,
|
||
`lot_number` varchar(100) NOT NULL,
|
||
`expiry_date` date NOT NULL,
|
||
`description` varchar(255) DEFAULT NULL,
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `company_id_product_sku_lot_number` (`company_id`,`product_sku`,`lot_number`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||
", 'md_lot');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `md_contact_type` (
|
||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) NOT NULL DEFAULT 0,
|
||
`contact_type` varchar(255) NOT NULL DEFAULT '',
|
||
`description` text NOT NULL DEFAULT '',
|
||
`status` int(1) NOT NULL DEFAULT 1,
|
||
`log` mediumtext NOT NULL DEFAULT '{}',
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `company_id_product_id` (`company_id`,`contact_type`),
|
||
KEY `company_id` (`company_id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||
", 'md_contact_type');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `md_contact` (
|
||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) NOT NULL DEFAULT 0,
|
||
`contact_name` varchar(255) NOT NULL,
|
||
`tax_id` varchar(255) NOT NULL,
|
||
`organization` varchar(255) NOT NULL,
|
||
`branch` varchar(255) NOT NULL,
|
||
`contact_type` int(11) unsigned NOT NULL,
|
||
`billing_address` text NOT NULL,
|
||
`shipping_location` varchar(255) NOT NULL,
|
||
`shipping_address` text NOT NULL,
|
||
`remark` text NOT NULL,
|
||
`contact_image` mediumtext NOT NULL,
|
||
`status` int(1) unsigned NOT NULL DEFAULT 1,
|
||
`log` mediumtext NOT NULL DEFAULT '{}',
|
||
PRIMARY KEY (`id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||
", 'md_contact');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `md_barcode` (
|
||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(10) unsigned NOT NULL,
|
||
`barcode_type` varchar(20) NOT NULL,
|
||
`barcode` varchar(320) NOT NULL,
|
||
`product_sku` varchar(100) DEFAULT NULL,
|
||
`lot_number` varchar(100) DEFAULT NULL,
|
||
`serial_number` varchar(100) DEFAULT NULL,
|
||
`warehouse_id` int(10) unsigned DEFAULT NULL,
|
||
`zone` varchar(100) DEFAULT NULL,
|
||
`aisle` varchar(100) DEFAULT NULL,
|
||
`rack` varchar(100) DEFAULT NULL,
|
||
`print_count` int(10) unsigned NOT NULL DEFAULT 0,
|
||
`last_printed_dt` datetime DEFAULT NULL,
|
||
`created_dt` datetime NOT NULL DEFAULT current_timestamp(),
|
||
`status` tinyint(4) NOT NULL DEFAULT 1,
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `company_id_barcode` (`company_id`,`barcode`),
|
||
KEY `company_id_type` (`company_id`,`barcode_type`),
|
||
KEY `company_id_product_lot` (`company_id`,`product_sku`,`lot_number`),
|
||
KEY `company_id_location` (`company_id`,`warehouse_id`,`zone`,`aisle`,`rack`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||
", 'md_barcode');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `md_sku_barcode_label` (
|
||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(10) unsigned NOT NULL,
|
||
`product_sku` varchar(100) NOT NULL,
|
||
`lot_number` varchar(100) NOT NULL,
|
||
`serial_number` varchar(100) NOT NULL,
|
||
`barcode` varchar(320) NOT NULL,
|
||
`created_dt` datetime NOT NULL DEFAULT current_timestamp(),
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `company_id_barcode` (`company_id`,`barcode`),
|
||
KEY `company_id_product_lot` (`company_id`,`product_sku`,`lot_number`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||
", 'md_sku_barcode_label');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `md_lock_operation` (
|
||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) NOT NULL DEFAULT 0,
|
||
`operation_type` varchar(50) NOT NULL DEFAULT '',
|
||
`user_id` int(11) NOT NULL DEFAULT 0,
|
||
`locked_at` datetime NOT NULL,
|
||
`expires_at` datetime NOT NULL,
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `op` (`company_id`,`operation_type`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||
", 'md_lock_operation');
|
||
|
||
// ── Accounting master ─────────────────────────────────────────────────────────
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `md_department` (
|
||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) NOT NULL,
|
||
`dept_code` varchar(20) NOT NULL,
|
||
`dept_name` varchar(255) NOT NULL,
|
||
`description` text DEFAULT NULL,
|
||
`status` tinyint(1) NOT NULL DEFAULT 1,
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `uq_company_dept` (`company_id`,`dept_code`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||
", 'md_department');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `md_account` (
|
||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) NOT NULL,
|
||
`account_code` varchar(20) NOT NULL,
|
||
`account_name` varchar(255) NOT NULL,
|
||
`account_type` enum('asset','liability','equity','revenue','expense') NOT NULL,
|
||
`account_category` varchar(50) NOT NULL DEFAULT '',
|
||
`parent_code` varchar(20) DEFAULT NULL,
|
||
`is_posting` tinyint(1) NOT NULL DEFAULT 1,
|
||
`status` tinyint(1) NOT NULL DEFAULT 1,
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `uq_company_account` (`company_id`,`account_code`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||
", 'md_account');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `md_account_formula` (
|
||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) NOT NULL,
|
||
`formula_name` varchar(100) NOT NULL,
|
||
`document_type` varchar(50) NOT NULL,
|
||
`description` text DEFAULT NULL,
|
||
`is_default` tinyint(1) NOT NULL DEFAULT 0,
|
||
`status` tinyint(1) NOT NULL DEFAULT 1,
|
||
`created_at` datetime NOT NULL DEFAULT current_timestamp(),
|
||
`updated_at` datetime DEFAULT NULL,
|
||
PRIMARY KEY (`id`),
|
||
KEY `idx_company_doc` (`company_id`,`document_type`),
|
||
KEY `idx_status` (`company_id`,`status`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||
", 'md_account_formula');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `md_account_formula_item` (
|
||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) NOT NULL,
|
||
`formula_id` int(11) NOT NULL,
|
||
`drcr` enum('D','C') NOT NULL,
|
||
`account_code` varchar(20) NOT NULL,
|
||
`amount_key` enum('grand_total','total','tax','amount') NOT NULL,
|
||
`description` varchar(255) DEFAULT NULL,
|
||
`sort_order` int(11) NOT NULL DEFAULT 0,
|
||
PRIMARY KEY (`id`),
|
||
KEY `idx_formula` (`company_id`,`formula_id`),
|
||
KEY `idx_account` (`company_id`,`account_code`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||
", 'md_account_formula_item');
|
||
|
||
// ── Stock (template + base) ───────────────────────────────────────────────────
|
||
// td_stock_<warehouse_id> tables are created automatically by the app on first use.
|
||
// This base table matches the template used by WarehouseManager::createStockTableForWarehouse().
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `td_stock` (
|
||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||
`ref_id` int(11) unsigned NOT NULL DEFAULT 0,
|
||
`company_id` int(11) NOT NULL DEFAULT 0,
|
||
`uuid` varchar(20) NOT NULL,
|
||
`type` varchar(20) NOT NULL,
|
||
`ref_warehouse` varchar(20) NOT NULL DEFAULT '',
|
||
`date` datetime DEFAULT NULL,
|
||
`product_sku` varchar(255) NOT NULL DEFAULT '0',
|
||
`lot_number` varchar(255) NOT NULL DEFAULT '',
|
||
`serial_number` varchar(255) NOT NULL DEFAULT '',
|
||
`source` varchar(255) NOT NULL DEFAULT '',
|
||
`source_id` int(11) NOT NULL DEFAULT 0,
|
||
`in` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`out` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`price` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`zone` varchar(255) NOT NULL DEFAULT '',
|
||
`aisle` varchar(255) NOT NULL DEFAULT '',
|
||
`rack` varchar(255) NOT NULL DEFAULT '',
|
||
`contact_id` int(11) NOT NULL DEFAULT 0,
|
||
`description` text NOT NULL DEFAULT '',
|
||
`status` int(3) NOT NULL DEFAULT 0,
|
||
`log` mediumtext NOT NULL DEFAULT '{}',
|
||
PRIMARY KEY (`id`),
|
||
KEY `company_id` (`company_id`),
|
||
KEY `product_id` (`product_sku`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||
", 'td_stock (base template)');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `warehouse_balance` (
|
||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) unsigned NOT NULL DEFAULT 0,
|
||
`warehouse_id` int(11) unsigned NOT NULL DEFAULT 0,
|
||
`product_sku` varchar(255) NOT NULL DEFAULT '',
|
||
`month` varchar(10) NOT NULL,
|
||
`total_in` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`total_out` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `company_id_warehouse_id_product_sku_month` (`company_id`,`warehouse_id`,`product_sku`,`month`),
|
||
KEY `company_id` (`company_id`),
|
||
KEY `product_id` (`warehouse_id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||
", 'warehouse_balance');
|
||
|
||
// ── Transactions ──────────────────────────────────────────────────────────────
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `td_gl` (
|
||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) NOT NULL DEFAULT 0,
|
||
`source_type` varchar(50) NOT NULL DEFAULT '',
|
||
`source_id` int(11) NOT NULL DEFAULT 0,
|
||
`reference` varchar(100) NOT NULL DEFAULT '',
|
||
`description` varchar(255) NOT NULL DEFAULT '',
|
||
`journal_date` date DEFAULT NULL,
|
||
`formula_id` int(11) NOT NULL DEFAULT 0,
|
||
`period` varchar(7) NOT NULL DEFAULT '',
|
||
`current_version` tinyint(4) NOT NULL DEFAULT 1,
|
||
`history` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '[]' CHECK (json_valid(`history`)),
|
||
`created_at` datetime NOT NULL,
|
||
`updated_at` datetime NOT NULL,
|
||
PRIMARY KEY (`id`),
|
||
KEY `company_id` (`company_id`),
|
||
KEY `period` (`period`),
|
||
KEY `formula_id` (`formula_id`),
|
||
KEY `source` (`company_id`,`source_type`,`source_id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||
", 'td_gl');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `td_gl_item` (
|
||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) NOT NULL DEFAULT 0,
|
||
`gl_id` int(10) unsigned NOT NULL,
|
||
`account_code` varchar(20) NOT NULL DEFAULT '',
|
||
`department_id` int(11) NOT NULL DEFAULT 0,
|
||
`debit` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`credit` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`description` varchar(255) NOT NULL DEFAULT '',
|
||
PRIMARY KEY (`id`),
|
||
KEY `gl_id` (`gl_id`),
|
||
KEY `company_id` (`company_id`),
|
||
KEY `account_code` (`account_code`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||
", 'td_gl_item');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `td_batch_action` (
|
||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) NOT NULL DEFAULT 0,
|
||
`type` varchar(50) NOT NULL DEFAULT '',
|
||
`doc_type` varchar(50) NOT NULL DEFAULT '',
|
||
`total` int(11) NOT NULL DEFAULT 0,
|
||
`succeeded` int(11) NOT NULL DEFAULT 0,
|
||
`failed` int(11) NOT NULL DEFAULT 0,
|
||
`failed_ids` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '[]' CHECK (json_valid(`failed_ids`)),
|
||
`user_id` int(11) NOT NULL DEFAULT 0,
|
||
`created_at` datetime NOT NULL,
|
||
PRIMARY KEY (`id`),
|
||
KEY `company_id` (`company_id`),
|
||
KEY `type` (`type`),
|
||
KEY `doc_type` (`doc_type`),
|
||
KEY `user_id` (`user_id`),
|
||
KEY `created_at` (`created_at`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||
", 'td_batch_action');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `td_quotation` (
|
||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) NOT NULL DEFAULT 0,
|
||
`uuid` varchar(32) NOT NULL DEFAULT '',
|
||
`quotation_number` varchar(50) NOT NULL DEFAULT '',
|
||
`contact_id` int(11) NOT NULL DEFAULT 0,
|
||
`department_id` int(11) NOT NULL DEFAULT 0,
|
||
`quotation_date` date DEFAULT NULL,
|
||
`valid_until` date DEFAULT NULL,
|
||
`status` tinyint(1) NOT NULL DEFAULT 0,
|
||
`subtotal` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`discount` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`tax` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`grand_total` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`notes` text NOT NULL DEFAULT '',
|
||
`log` mediumtext NOT NULL DEFAULT '{}',
|
||
`created_at` datetime DEFAULT NULL,
|
||
PRIMARY KEY (`id`),
|
||
KEY `company_id` (`company_id`),
|
||
KEY `quotation_number` (`quotation_number`),
|
||
KEY `status` (`status`),
|
||
KEY `contact_id` (`contact_id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||
", 'td_quotation');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `td_quotation_item` (
|
||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) NOT NULL DEFAULT 0,
|
||
`quotation_id` int(11) unsigned NOT NULL DEFAULT 0,
|
||
`item_id` int(11) unsigned NOT NULL DEFAULT 0,
|
||
`product_sku` varchar(100) NOT NULL DEFAULT '',
|
||
`product_name` varchar(255) NOT NULL DEFAULT '',
|
||
`quantity` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`unit_price` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`total_price` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`tax_amount` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`tax_rate` decimal(5,2) NOT NULL DEFAULT 0.00,
|
||
`converted_qty` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `uq_qt_item` (`quotation_id`,`item_id`),
|
||
KEY `idx_quotation` (`company_id`,`quotation_id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||
", 'td_quotation_item');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `td_order` (
|
||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) NOT NULL DEFAULT 0,
|
||
`uuid` varchar(32) NOT NULL DEFAULT '',
|
||
`source_id` int(11) NOT NULL DEFAULT 0,
|
||
`source` varchar(20) NOT NULL DEFAULT '',
|
||
`order_number` varchar(50) NOT NULL DEFAULT '',
|
||
`contact_id` int(11) NOT NULL DEFAULT 0,
|
||
`department_id` int(11) NOT NULL DEFAULT 0,
|
||
`order_date` date DEFAULT NULL,
|
||
`status` tinyint(1) NOT NULL DEFAULT 0,
|
||
`subtotal` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`discount` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`tax` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`tax_adjustment` decimal(8,2) NOT NULL DEFAULT 0.00,
|
||
`shipping_fee` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`shipping_tracking_number` varchar(100) DEFAULT NULL,
|
||
`grand_total` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`notes` text NOT NULL DEFAULT '',
|
||
`log` mediumtext NOT NULL DEFAULT '{}',
|
||
`created_at` datetime DEFAULT NULL,
|
||
PRIMARY KEY (`id`),
|
||
KEY `company_id` (`company_id`),
|
||
KEY `contact_id` (`contact_id`),
|
||
KEY `order_number` (`order_number`),
|
||
KEY `status` (`status`),
|
||
KEY `order_date` (`order_date`),
|
||
KEY `quotation_id` (`source_id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||
", 'td_order');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `td_order_item` (
|
||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) NOT NULL DEFAULT 0,
|
||
`order_id` int(11) unsigned NOT NULL DEFAULT 0,
|
||
`item_id` int(11) unsigned NOT NULL DEFAULT 0,
|
||
`product_sku` varchar(100) NOT NULL DEFAULT '',
|
||
`product_name` varchar(255) NOT NULL DEFAULT '',
|
||
`quantity` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`unit_price` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`total_price` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`tax_amount` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`tax_rate` decimal(5,2) NOT NULL DEFAULT 0.00,
|
||
`warehouse_id` int(11) NOT NULL DEFAULT 0,
|
||
`stock_out_id` int(11) NOT NULL DEFAULT 0,
|
||
`lot_number` varchar(100) NOT NULL DEFAULT '',
|
||
`invoiced_qty` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `uq_order_item` (`order_id`,`item_id`),
|
||
KEY `idx_order` (`company_id`,`order_id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||
", 'td_order_item');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `td_invoice` (
|
||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) NOT NULL DEFAULT 0,
|
||
`uuid` varchar(32) NOT NULL DEFAULT '',
|
||
`source_id` int(11) NOT NULL DEFAULT 0,
|
||
`source` varchar(20) NOT NULL DEFAULT '',
|
||
`doc_type` varchar(20) NOT NULL DEFAULT 'invoice',
|
||
`invoice_number` varchar(50) NOT NULL DEFAULT '',
|
||
`ref_invoice_id` int(11) unsigned NOT NULL DEFAULT 0,
|
||
`order_id` int(11) unsigned NOT NULL DEFAULT 0,
|
||
`contact_id` int(11) NOT NULL DEFAULT 0,
|
||
`department_id` int(11) NOT NULL DEFAULT 0,
|
||
`issued_date` date DEFAULT NULL,
|
||
`due_date` date DEFAULT NULL,
|
||
`subtotal` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`discount` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`tax` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`tax_adjustment` decimal(8,2) NOT NULL DEFAULT 0.00,
|
||
`shipping_fee` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`grand_total` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`formula_id` int(11) DEFAULT NULL,
|
||
`status` tinyint(1) NOT NULL DEFAULT 0,
|
||
`notes` text NOT NULL DEFAULT '',
|
||
`log` mediumtext NOT NULL DEFAULT '{}',
|
||
PRIMARY KEY (`id`),
|
||
KEY `company_id` (`company_id`),
|
||
KEY `order_id` (`order_id`),
|
||
KEY `contact_id` (`contact_id`),
|
||
KEY `invoice_number` (`invoice_number`),
|
||
KEY `ref_invoice_id` (`ref_invoice_id`),
|
||
KEY `doc_type` (`doc_type`),
|
||
KEY `status` (`status`),
|
||
KEY `due_date` (`due_date`),
|
||
KEY `source_id` (`source_id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||
", 'td_invoice');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `td_invoice_item` (
|
||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) NOT NULL DEFAULT 0,
|
||
`invoice_id` int(11) unsigned NOT NULL DEFAULT 0,
|
||
`item_id` int(11) unsigned NOT NULL DEFAULT 0,
|
||
`product_sku` varchar(100) NOT NULL DEFAULT '',
|
||
`product_name` varchar(255) NOT NULL DEFAULT '',
|
||
`quantity` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`unit_price` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`total_price` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`tax_amount` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`tax_rate` decimal(5,2) NOT NULL DEFAULT 0.00,
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `uq_invoice_item` (`invoice_id`,`item_id`),
|
||
KEY `idx_invoice` (`company_id`,`invoice_id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||
", 'td_invoice_item');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `td_return` (
|
||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) NOT NULL DEFAULT 0,
|
||
`uuid` varchar(32) NOT NULL DEFAULT '',
|
||
`return_number` varchar(50) NOT NULL DEFAULT '',
|
||
`order_id` int(11) unsigned NOT NULL DEFAULT 0,
|
||
`invoice_id` int(11) unsigned NOT NULL DEFAULT 0,
|
||
`contact_id` int(11) NOT NULL DEFAULT 0,
|
||
`department_id` int(11) NOT NULL DEFAULT 0,
|
||
`return_date` date DEFAULT NULL,
|
||
`status` tinyint(1) NOT NULL DEFAULT 0,
|
||
`reason` text NOT NULL DEFAULT '',
|
||
`refund_amount` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`tax` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`tax_adjustment` decimal(8,2) NOT NULL DEFAULT 0.00,
|
||
`notes` text NOT NULL DEFAULT '',
|
||
`log` mediumtext NOT NULL DEFAULT '{}',
|
||
PRIMARY KEY (`id`),
|
||
KEY `company_id` (`company_id`),
|
||
KEY `order_id` (`order_id`),
|
||
KEY `invoice_id` (`invoice_id`),
|
||
KEY `contact_id` (`contact_id`),
|
||
KEY `return_number` (`return_number`),
|
||
KEY `status` (`status`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||
", 'td_return');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `td_return_item` (
|
||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) NOT NULL DEFAULT 0,
|
||
`return_id` int(11) unsigned NOT NULL DEFAULT 0,
|
||
`item_id` int(11) unsigned NOT NULL DEFAULT 0,
|
||
`product_sku` varchar(100) NOT NULL DEFAULT '',
|
||
`product_name` varchar(255) NOT NULL DEFAULT '',
|
||
`quantity` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`unit_price` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`total_price` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`tax_amount` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`tax_rate` decimal(5,2) NOT NULL DEFAULT 0.00,
|
||
`warehouse_id` int(11) NOT NULL DEFAULT 0,
|
||
`stock_out_id` int(11) NOT NULL DEFAULT 0,
|
||
`stock_out_warehouse_id` int(11) NOT NULL DEFAULT 0,
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `uq_return_item` (`return_id`,`item_id`),
|
||
KEY `idx_return` (`company_id`,`return_id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||
", 'td_return_item');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `td_purchase_request` (
|
||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) NOT NULL DEFAULT 0,
|
||
`uuid` varchar(32) NOT NULL DEFAULT '',
|
||
`request_number` varchar(50) NOT NULL DEFAULT '',
|
||
`contact_id` int(11) NOT NULL DEFAULT 0,
|
||
`department_id` int(11) NOT NULL DEFAULT 0,
|
||
`request_date` date DEFAULT NULL,
|
||
`required_date` date DEFAULT NULL,
|
||
`status` tinyint(1) NOT NULL DEFAULT 0,
|
||
`subtotal` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`discount` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`tax` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`shipping_fee` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`grand_total` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`notes` text NOT NULL DEFAULT '',
|
||
`log` mediumtext NOT NULL DEFAULT '{}',
|
||
`created_at` datetime DEFAULT NULL,
|
||
PRIMARY KEY (`id`),
|
||
KEY `company_id` (`company_id`),
|
||
KEY `request_number` (`request_number`),
|
||
KEY `status` (`status`),
|
||
KEY `contact_id` (`contact_id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||
", 'td_purchase_request');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `td_purchase_request_item` (
|
||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) NOT NULL DEFAULT 0,
|
||
`request_id` int(11) unsigned NOT NULL DEFAULT 0,
|
||
`item_id` int(11) unsigned NOT NULL DEFAULT 0,
|
||
`product_sku` varchar(100) NOT NULL DEFAULT '',
|
||
`product_name` varchar(255) NOT NULL DEFAULT '',
|
||
`quantity` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`unit_price` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`total_price` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`tax_amount` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`tax_rate` decimal(5,2) NOT NULL DEFAULT 0.00,
|
||
`converted_qty` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `uq_pr_item` (`request_id`,`item_id`),
|
||
KEY `idx_pr_item` (`company_id`,`request_id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||
", 'td_purchase_request_item');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `td_purchase_order` (
|
||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) NOT NULL,
|
||
`uuid` varchar(64) NOT NULL,
|
||
`source_id` int(11) NOT NULL DEFAULT 0,
|
||
`source` varchar(32) NOT NULL DEFAULT '',
|
||
`po_number` varchar(32) NOT NULL,
|
||
`contact_id` int(11) DEFAULT NULL,
|
||
`department_id` int(11) NOT NULL DEFAULT 0,
|
||
`po_date` date NOT NULL,
|
||
`expected_date` date DEFAULT NULL,
|
||
`closed_at` datetime DEFAULT NULL,
|
||
`warehouse_id` int(11) NOT NULL DEFAULT 0,
|
||
`status` tinyint(4) NOT NULL DEFAULT 0,
|
||
`subtotal` decimal(15,2) NOT NULL DEFAULT 0.00,
|
||
`discount` decimal(15,2) NOT NULL DEFAULT 0.00,
|
||
`tax` decimal(15,2) NOT NULL DEFAULT 0.00,
|
||
`tax_adjustment` decimal(8,2) NOT NULL DEFAULT 0.00,
|
||
`shipping_fee` decimal(15,2) NOT NULL DEFAULT 0.00,
|
||
`grand_total` decimal(15,2) NOT NULL DEFAULT 0.00,
|
||
`notes` text DEFAULT NULL,
|
||
`log` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`log`)),
|
||
`created_at` datetime NOT NULL,
|
||
PRIMARY KEY (`id`),
|
||
KEY `idx_po_company` (`company_id`),
|
||
KEY `idx_po_status` (`company_id`,`status`),
|
||
KEY `idx_po_contact` (`company_id`,`contact_id`),
|
||
KEY `idx_po_date` (`company_id`,`po_date`),
|
||
KEY `idx_po_source` (`company_id`,`source`,`source_id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||
", 'td_purchase_order');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `td_purchase_order_item` (
|
||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) NOT NULL DEFAULT 0,
|
||
`order_id` int(11) unsigned NOT NULL DEFAULT 0,
|
||
`item_id` int(11) unsigned NOT NULL DEFAULT 0,
|
||
`product_sku` varchar(100) NOT NULL DEFAULT '',
|
||
`product_name` varchar(255) NOT NULL DEFAULT '',
|
||
`quantity` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`unit_price` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`total_price` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`tax_amount` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`tax_rate` decimal(5,2) NOT NULL DEFAULT 0.00,
|
||
`received_qty` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`stock_in_id` int(11) NOT NULL DEFAULT 0,
|
||
`invoiced_qty` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `uq_po_item` (`order_id`,`item_id`),
|
||
KEY `idx_order` (`company_id`,`order_id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||
", 'td_purchase_order_item');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `td_supplier_return` (
|
||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) NOT NULL DEFAULT 0,
|
||
`uuid` varchar(32) NOT NULL DEFAULT '',
|
||
`return_number` varchar(32) NOT NULL DEFAULT '',
|
||
`po_id` int(11) unsigned NOT NULL DEFAULT 0,
|
||
`invoice_id` int(11) unsigned NOT NULL DEFAULT 0,
|
||
`contact_id` int(11) NOT NULL DEFAULT 0,
|
||
`department_id` int(11) NOT NULL DEFAULT 0,
|
||
`return_date` date NOT NULL,
|
||
`status` tinyint(1) NOT NULL DEFAULT 0,
|
||
`reason` text NOT NULL DEFAULT '',
|
||
`refund_amount` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`tax` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`tax_adjustment` decimal(8,2) NOT NULL DEFAULT 0.00,
|
||
`notes` text NOT NULL DEFAULT '',
|
||
`log` mediumtext NOT NULL DEFAULT '{}',
|
||
`shipping_tracking_number` varchar(100) NOT NULL DEFAULT '',
|
||
PRIMARY KEY (`id`),
|
||
KEY `idx_company_id` (`company_id`),
|
||
KEY `idx_po_id` (`po_id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||
", 'td_supplier_return');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `td_supplier_return_item` (
|
||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) NOT NULL DEFAULT 0,
|
||
`return_id` int(11) unsigned NOT NULL DEFAULT 0,
|
||
`item_id` int(11) unsigned NOT NULL DEFAULT 0,
|
||
`product_sku` varchar(100) NOT NULL DEFAULT '',
|
||
`product_name` varchar(255) NOT NULL DEFAULT '',
|
||
`quantity` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`unit_price` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`total_price` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`tax_amount` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`tax_rate` decimal(5,2) NOT NULL DEFAULT 0.00,
|
||
`warehouse_id` int(11) NOT NULL DEFAULT 0,
|
||
`stock_in_id` int(11) NOT NULL DEFAULT 0,
|
||
`zone` varchar(50) NOT NULL DEFAULT '',
|
||
`aisle` varchar(50) NOT NULL DEFAULT '',
|
||
`rack` varchar(50) NOT NULL DEFAULT '',
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `uq_sr_item` (`return_id`,`item_id`),
|
||
KEY `idx_return` (`company_id`,`return_id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||
", 'td_supplier_return_item');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `td_receipt_billing` (
|
||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) NOT NULL DEFAULT 0,
|
||
`uuid` varchar(32) NOT NULL DEFAULT '',
|
||
`billing_number` varchar(50) NOT NULL DEFAULT '',
|
||
`contact_id` int(11) NOT NULL DEFAULT 0,
|
||
`billing_date` date DEFAULT NULL,
|
||
`amount` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`status` tinyint(1) NOT NULL DEFAULT 1,
|
||
`notes` text NOT NULL DEFAULT '',
|
||
`log` mediumtext NOT NULL DEFAULT '{}',
|
||
`created_at` datetime DEFAULT NULL,
|
||
PRIMARY KEY (`id`),
|
||
KEY `company_id` (`company_id`),
|
||
KEY `contact_id` (`contact_id`),
|
||
KEY `billing_number` (`billing_number`),
|
||
KEY `status` (`status`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||
", 'td_receipt_billing');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `td_receipt_billing_item` (
|
||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) NOT NULL DEFAULT 0,
|
||
`billing_id` int(11) unsigned NOT NULL DEFAULT 0,
|
||
`invoice_id` int(11) unsigned NOT NULL DEFAULT 0,
|
||
`doc_type` varchar(20) NOT NULL DEFAULT '',
|
||
`amount` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
PRIMARY KEY (`id`),
|
||
KEY `company_id` (`company_id`),
|
||
KEY `billing_id` (`billing_id`),
|
||
KEY `invoice_id` (`invoice_id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||
", 'td_receipt_billing_item');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `td_receipt` (
|
||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) NOT NULL DEFAULT 0,
|
||
`uuid` varchar(32) NOT NULL DEFAULT '',
|
||
`receipt_number` varchar(50) NOT NULL DEFAULT '',
|
||
`contact_id` int(11) NOT NULL DEFAULT 0,
|
||
`department_id` int(11) NOT NULL DEFAULT 0,
|
||
`receipt_billing_id` int(11) unsigned NOT NULL DEFAULT 0,
|
||
`receipt_date` date DEFAULT NULL,
|
||
`payment_method` varchar(50) NOT NULL DEFAULT '',
|
||
`amount` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`formula_id` int(11) DEFAULT NULL,
|
||
`status` tinyint(1) NOT NULL DEFAULT 1,
|
||
`notes` text NOT NULL DEFAULT '',
|
||
`log` mediumtext NOT NULL DEFAULT '{}',
|
||
`created_at` datetime DEFAULT NULL,
|
||
PRIMARY KEY (`id`),
|
||
KEY `company_id` (`company_id`),
|
||
KEY `contact_id` (`contact_id`),
|
||
KEY `receipt_number` (`receipt_number`),
|
||
KEY `status` (`status`),
|
||
KEY `receipt_billing_id` (`receipt_billing_id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||
", 'td_receipt');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `td_receipt_item` (
|
||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) NOT NULL DEFAULT 0,
|
||
`receipt_id` int(11) unsigned NOT NULL DEFAULT 0,
|
||
`invoice_id` int(11) unsigned NOT NULL DEFAULT 0,
|
||
`doc_type` varchar(20) NOT NULL DEFAULT '',
|
||
`department_id` int(11) NOT NULL DEFAULT 0,
|
||
`amount` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
PRIMARY KEY (`id`),
|
||
KEY `company_id` (`company_id`),
|
||
KEY `receipt_id` (`receipt_id`),
|
||
KEY `invoice_id` (`invoice_id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||
", 'td_receipt_item');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `td_payment_billing` (
|
||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) NOT NULL DEFAULT 0,
|
||
`uuid` varchar(32) NOT NULL DEFAULT '',
|
||
`billing_number` varchar(50) NOT NULL DEFAULT '',
|
||
`contact_id` int(11) NOT NULL DEFAULT 0,
|
||
`billing_date` date DEFAULT NULL,
|
||
`amount` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`status` tinyint(1) NOT NULL DEFAULT 1,
|
||
`notes` text NOT NULL DEFAULT '',
|
||
`log` mediumtext NOT NULL DEFAULT '{}',
|
||
`created_at` datetime DEFAULT NULL,
|
||
PRIMARY KEY (`id`),
|
||
KEY `company_id` (`company_id`),
|
||
KEY `contact_id` (`contact_id`),
|
||
KEY `billing_number` (`billing_number`),
|
||
KEY `status` (`status`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||
", 'td_payment_billing');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `td_payment_billing_item` (
|
||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) NOT NULL DEFAULT 0,
|
||
`billing_id` int(11) unsigned NOT NULL DEFAULT 0,
|
||
`invoice_id` int(11) unsigned NOT NULL DEFAULT 0,
|
||
`doc_type` varchar(20) NOT NULL DEFAULT '',
|
||
`amount` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
PRIMARY KEY (`id`),
|
||
KEY `company_id` (`company_id`),
|
||
KEY `billing_id` (`billing_id`),
|
||
KEY `invoice_id` (`invoice_id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||
", 'td_payment_billing_item');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `td_payment` (
|
||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) NOT NULL DEFAULT 0,
|
||
`uuid` varchar(32) NOT NULL DEFAULT '',
|
||
`payment_number` varchar(50) NOT NULL DEFAULT '',
|
||
`contact_id` int(11) NOT NULL DEFAULT 0,
|
||
`department_id` int(11) NOT NULL DEFAULT 0,
|
||
`payment_billing_id` int(11) unsigned NOT NULL DEFAULT 0,
|
||
`payment_date` date DEFAULT NULL,
|
||
`payment_method` varchar(50) NOT NULL DEFAULT '',
|
||
`amount` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
`formula_id` int(11) DEFAULT NULL,
|
||
`status` tinyint(1) NOT NULL DEFAULT 1,
|
||
`notes` text NOT NULL DEFAULT '',
|
||
`log` mediumtext NOT NULL DEFAULT '{}',
|
||
`created_at` datetime DEFAULT NULL,
|
||
PRIMARY KEY (`id`),
|
||
KEY `company_id` (`company_id`),
|
||
KEY `contact_id` (`contact_id`),
|
||
KEY `payment_billing_id` (`payment_billing_id`),
|
||
KEY `payment_number` (`payment_number`),
|
||
KEY `status` (`status`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||
", 'td_payment');
|
||
|
||
run($pdo, "
|
||
CREATE TABLE IF NOT EXISTS `td_payment_item` (
|
||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||
`company_id` int(11) NOT NULL DEFAULT 0,
|
||
`payment_id` int(11) unsigned NOT NULL DEFAULT 0,
|
||
`invoice_id` int(11) unsigned NOT NULL DEFAULT 0,
|
||
`doc_type` varchar(20) NOT NULL DEFAULT '',
|
||
`department_id` int(11) NOT NULL DEFAULT 0,
|
||
`amount` decimal(18,4) NOT NULL DEFAULT 0.0000,
|
||
PRIMARY KEY (`id`),
|
||
KEY `company_id` (`company_id`),
|
||
KEY `payment_id` (`payment_id`),
|
||
KEY `invoice_id` (`invoice_id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
|
||
", 'td_payment_item');
|
||
|
||
// ── Summary ───────────────────────────────────────────────────────────────────
|
||
$total = $ok_count + $skip_count + $err_count;
|
||
echo "\n\033[1m=== Done ===\033[0m\n";
|
||
printf(" Created : %d\n", $ok_count);
|
||
printf(" Skipped : %d\n", $skip_count);
|
||
printf(" Errors : %d\n", $err_count);
|
||
echo PHP_EOL;
|
||
|
||
if ($err_count > 0) {
|
||
echo "\033[31mSetup completed with errors. Review the output above.\033[0m\n\n";
|
||
exit(1);
|
||
}
|
||
|
||
echo "\033[32mSetup complete. Both databases are ready.\033[0m\n";
|
||
echo "Next step: visit /login/index.php and register the first owner account.\n\n";
|
||
exit(0);
|