db->table_exists($table) && !$this->db->field_exists($column, $table)) { $this->db->query("ALTER TABLE `{$table}` ADD `{$column}` {$definition}"); } } private function index($table, $name, $columns, $unique = false) { if (!$this->db->table_exists($table)) return; foreach ($this->db->query("SHOW INDEX FROM `{$table}`")->result() as $index) { if ($index->Key_name === $name) return; } $this->db->query("ALTER TABLE `{$table}` ADD ".($unique ? 'UNIQUE ' : '')."KEY `{$name}` ({$columns})"); } public function up() { $this->column('invoices', 'idempotency_key', 'VARCHAR(100) NULL AFTER `source_sales_order_id`'); $this->column('invoices', 'version', 'INT NOT NULL DEFAULT 1'); $this->column('invoice_details', 'line_type', "ENUM('inventory','service') NOT NULL DEFAULT 'inventory' AFTER `invoice_id`"); $this->column('invoice_details', 'idempotency_key', 'VARCHAR(100) NULL'); if ($this->db->table_exists('invoice_details') && $this->db->field_exists('line_type', 'invoice_details')) { $this->db->query("UPDATE invoice_details SET line_type=IF(items_id IS NULL,'service','inventory')"); } $this->index('invoices', 'uq_invoice_editor_idempotency', '`company_id`,`idempotency_key`', true); $this->index('invoices', 'idx_invoice_list_filters', '`company_id`,`workflow_status`,`status`,`invoice_type`,`tanggal`'); $this->index('invoice_details', 'uq_invoice_line_idempotency', '`company_id`,`idempotency_key`', true); $this->index('invoice_details', 'idx_invoice_line_page', '`company_id`,`invoice_id`,`service_date`,`id`'); $this->index('sales_deliveries', 'idx_delivery_draft_group', '`company_id`,`invoice_id`,`delivery_date`,`warehouse_id`,`status`'); if ($this->db->table_exists('roles')) { foreach ($this->db->select('id,permissions')->get('roles')->result() as $role) { $permissions = json_decode((string)$role->permissions, true); if (!is_array($permissions) || empty($permissions['invoices']) || !is_array($permissions['invoices'])) continue; if ((in_array('can_create', $permissions['invoices'], true) || in_array('can_update', $permissions['invoices'], true)) && !in_array('can_submit', $permissions['invoices'], true)) { $permissions['invoices'][] = 'can_submit'; $this->db->where('id', $role->id)->update('roles', array('permissions'=>json_encode($permissions))); } } } } public function down() { throw new RuntimeException('Gunakan backup database untuk rollback finalisasi editor Invoice.'); } }