db->table_exists($t)&&!$this->db->field_exists($c,$t))$this->db->query("ALTER TABLE `$t` ADD `$c` $sql");} public function up(){ $tables=array( 'companies'=>"id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,company_code VARCHAR(30) NOT NULL,name VARCHAR(150) NOT NULL,legal_name VARCHAR(200) NULL,tax_number VARCHAR(60) NULL,address TEXT NULL,base_currency CHAR(3) NOT NULL DEFAULT 'IDR',is_active TINYINT(1) NOT NULL DEFAULT 1,created_at DATETIME NOT NULL,UNIQUE KEY uq_company_code(company_code)", 'user_companies'=>"id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,user_id INT NOT NULL,company_id BIGINT UNSIGNED NOT NULL,is_default TINYINT(1) NOT NULL DEFAULT 0,can_consolidate TINYINT(1) NOT NULL DEFAULT 0,UNIQUE KEY uq_user_company(user_id,company_id)", 'currencies'=>"code CHAR(3) PRIMARY KEY,name VARCHAR(80) NOT NULL,symbol VARCHAR(10) NULL,decimal_places TINYINT NOT NULL DEFAULT 2,is_active TINYINT(1) NOT NULL DEFAULT 1", 'exchange_rates'=>"id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,company_id BIGINT UNSIGNED NOT NULL,rate_date DATE NOT NULL,from_currency CHAR(3) NOT NULL,to_currency CHAR(3) NOT NULL,rate DECIMAL(20,8) NOT NULL,source VARCHAR(80) NULL,created_by INT NULL,created_at DATETIME NOT NULL,UNIQUE KEY uq_exchange_rate(company_id,rate_date,from_currency,to_currency)", 'fx_revaluations'=>"id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,company_id BIGINT UNSIGNED NOT NULL,revaluation_no VARCHAR(60) NOT NULL,revaluation_date DATE NOT NULL,status ENUM('draft','posted','reversed') NOT NULL DEFAULT 'draft',gain_amount DECIMAL(18,2) NOT NULL DEFAULT 0,loss_amount DECIMAL(18,2) NOT NULL DEFAULT 0,journal_id INT NULL,created_by INT NULL,posted_at DATETIME NULL,UNIQUE KEY uq_fx_revaluation(company_id,revaluation_no)", 'intercompany_transactions'=>"id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,document_no VARCHAR(60) NOT NULL,from_company_id BIGINT UNSIGNED NOT NULL,to_company_id BIGINT UNSIGNED NOT NULL,transaction_date DATE NOT NULL,amount DECIMAL(18,2) NOT NULL,currency CHAR(3) NOT NULL,exchange_rate DECIMAL(20,8) NOT NULL,status ENUM('draft','posted','eliminated','reversed') NOT NULL DEFAULT 'draft',from_journal_id INT NULL,to_journal_id INT NULL,elimination_journal_id INT NULL,created_by INT NULL,UNIQUE KEY uq_intercompany_doc(document_no)" );foreach($tables as$t=>$s)$this->db->query("CREATE TABLE IF NOT EXISTS `$t`($s) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"); if(!$this->db->count_all('companies'))$this->db->insert('companies',array('company_code'=>'MAIN','name'=>'Perusahaan Utama','base_currency'=>'IDR','is_active'=>1,'created_at'=>date('Y-m-d H:i:s')));$company=$this->db->order_by('id')->get('companies')->row();$this->db->query("INSERT IGNORE INTO currencies(code,name,symbol,decimal_places,is_active)VALUES('IDR','Rupiah','Rp',2,1),('USD','US Dollar','$',2,1),('SGD','Singapore Dollar','S$',2,1),('EUR','Euro','EUR',2,1)");$this->db->query("INSERT IGNORE INTO user_companies(user_id,company_id,is_default,can_consolidate) SELECT id,".(int)$company->id.",1,IF(role_id=(SELECT id FROM roles WHERE nama_role='Admin' LIMIT 1),1,0) FROM users"); $critical=array('accounts','journals','journal_details','accounting_periods','fiscal_years','document_sequences','system_account_mappings','customers','invoices','payments','suppliers','purchase_orders','supplier_invoices','supplier_payments','items','warehouses','assets','cash_accounts','cash_transactions','k_employees','k_payroll_periods','k_payrolls','tax_codes','tax_transactions','budgets','business_dimensions');foreach($critical as$t)$this->col($t,'company_id','BIGINT UNSIGNED NULL');foreach($critical as$t)if($this->db->table_exists($t)&&$this->db->field_exists('company_id',$t))$this->db->where('company_id IS NULL',null,false)->update($t,array('company_id'=>$company->id)); foreach(array('journals','invoices','supplier_invoices','cash_transactions')as$t){$this->col($t,'transaction_currency',"CHAR(3) NOT NULL DEFAULT 'IDR'");$this->col($t,'exchange_rate','DECIMAL(20,8) NOT NULL DEFAULT 1');$this->col($t,'base_amount','DECIMAL(18,2) NULL');} foreach(array('journal_details','payment_allocations','supplier_payment_allocations')as$t){$this->col($t,'currency_amount','DECIMAL(18,2) NULL');$this->col($t,'currency_code',"CHAR(3) NULL");$this->col($t,'exchange_rate','DECIMAL(20,8) NULL');} } public function down(){throw new RuntimeException('Gunakan backup untuk rollback Tahap 14.');} }