From 9b235cc01f62e377af0158a7f717b851b4035984 Mon Sep 17 00:00:00 2001 From: DevSoftTech Server Date: Mon, 2 Mar 2026 23:09:40 +0530 Subject: [PATCH] Improve setup installation diagnostics and sync error visibility --- app/Controllers/Opd_prescription.php | 2 - app/Controllers/Setup.php | 117 +++++++++++++-- app/Views/billing/opd_prescription_basic.php | 141 +------------------ app/Views/setup/db_setup.php | 29 ++++ public/index.php | 40 ++++++ 5 files changed, 177 insertions(+), 152 deletions(-) diff --git a/app/Controllers/Opd_prescription.php b/app/Controllers/Opd_prescription.php index 5adee23..b1f57d5 100644 --- a/app/Controllers/Opd_prescription.php +++ b/app/Controllers/Opd_prescription.php @@ -113,8 +113,6 @@ class Opd_prescription extends BaseController 'co_morbidities_prefilled_from_history' => $this->hasHistoricalCoMorbiditySelection($patientId), 'history_alerts' => $this->buildPatientHistoryAlerts((int) ($opdRow->p_id ?? 0), $opdId), 'left_remarks' => $this->fetchPatientRemarks((int) ($opdRow->p_id ?? 0), 8), - 'old_rx_fast' => $this->buildOldPrescriptionFastView((int) ($opdRow->p_id ?? 0), $opdId), - 'current_opd_scans' => $this->getCurrentOpdScansForConsult($opdId), ]); } diff --git a/app/Controllers/Setup.php b/app/Controllers/Setup.php index 2e60b61..f14a392 100644 --- a/app/Controllers/Setup.php +++ b/app/Controllers/Setup.php @@ -79,7 +79,24 @@ class Setup extends BaseController return $deny; } - return view('setup/db_setup', $this->buildDbToolsViewData()); + try { + return view('setup/db_setup', $this->buildDbToolsViewData()); + } catch (\Throwable $e) { + log_message('error', 'Setup dbTools load failed: {message}', ['message' => $e->getMessage()]); + + return view('setup/db_setup', [ + 'tables' => [], + 'msg' => 'Setup tools could not load completely: ' . $e->getMessage(), + 'lock_file' => $this->lockFilePath(), + 'setup_key' => trim((string) env('setup.dbToolsKey', '')), + 'sync_result' => null, + 'sync_master_database' => (string) env('setup.sync.master.database', ''), + 'sync_client_database' => (string) env('setup.sync.client.database', ''), + 'master_schema_file' => $this->masterSchemaFilePath(), + 'master_schema_exists' => is_file($this->masterSchemaFilePath()), + 'diagnostics' => $this->collectSetupDiagnostics($e->getMessage()), + ]); + } } public function schemaSync() @@ -93,19 +110,29 @@ class Setup extends BaseController @set_time_limit(0); @ignore_user_abort(true); - $action = strtolower(trim((string) $this->request->getPost('sync_action'))); - if (!in_array($action, ['analyze', 'apply'], true)) { - $action = 'analyze'; - } + try { + $action = strtolower(trim((string) $this->request->getPost('sync_action'))); + if (!in_array($action, ['analyze', 'apply'], true)) { + $action = 'analyze'; + } - $syncResult = $this->buildSchemaSyncPlan(); - if ($action === 'apply' && empty($syncResult['errors']) && !empty($syncResult['sql'])) { - $applyResult = $this->applySchemaSyncSql($syncResult['sql']); - $syncResult['applied'] = $applyResult['applied']; - $syncResult['apply_errors'] = $applyResult['errors']; - } + $syncResult = $this->buildSchemaSyncPlan(); + if ($action === 'apply' && empty($syncResult['errors']) && !empty($syncResult['sql'])) { + $applyResult = $this->applySchemaSyncSql($syncResult['sql']); + $syncResult['applied'] = $applyResult['applied']; + $syncResult['apply_errors'] = $applyResult['errors']; + } - $this->lastSyncResult = $syncResult; + $this->lastSyncResult = $syncResult; + } catch (\Throwable $e) { + log_message('error', 'Setup schemaSync failed: {message}', ['message' => $e->getMessage()]); + $this->lastSyncResult = [ + 'errors' => ['Schema sync failed: ' . $e->getMessage()], + 'sql' => [], + 'summary' => [], + 'source' => 'runtime-exception', + ]; + } return view('setup/db_setup', $this->buildDbToolsViewData()); } @@ -322,8 +349,18 @@ class Setup extends BaseController */ private function buildDbToolsViewData(): array { - $allTables = $this->db->listTables(); - $scripted = $this->detectScriptedTables(); + $allTables = []; + $scripted = []; + $dbError = null; + + try { + $allTables = $this->db->listTables(); + $scripted = $this->detectScriptedTables(); + } catch (\Throwable $e) { + $dbError = $e->getMessage(); + log_message('error', 'Setup buildDbToolsViewData DB failure: {message}', ['message' => $dbError]); + session()->setFlashdata('setup_msg', 'Database connection/setup error: ' . $dbError); + } $tableRows = []; foreach ($allTables as $tableName) { @@ -351,6 +388,58 @@ class Setup extends BaseController 'sync_client_database' => (string) env('setup.sync.client.database', ''), 'master_schema_file' => $this->masterSchemaFilePath(), 'master_schema_exists' => is_file($this->masterSchemaFilePath()), + 'diagnostics' => $this->collectSetupDiagnostics($dbError), + ]; + } + + /** + * @return array> + */ + private function collectSetupDiagnostics(?string $dbError = null): array + { + $errors = []; + $warnings = []; + $info = []; + + $env = (string) env('CI_ENVIRONMENT', 'production'); + $info[] = 'CI_ENVIRONMENT: ' . $env; + + $setupKey = trim((string) env('setup.dbToolsKey', '')); + if ($setupKey === '') { + $warnings[] = 'setup.dbToolsKey is empty. Setup endpoint can only be accessed by authenticated privileged users.'; + } else { + $info[] = 'setup.dbToolsKey is configured.'; + } + + $dbHost = trim((string) env('database.default.hostname', '')); + $dbName = trim((string) env('database.default.database', '')); + $dbUser = trim((string) env('database.default.username', '')); + + if ($dbHost === '' || $dbName === '' || $dbUser === '') { + $errors[] = 'Missing database.default.* values in .env (hostname/database/username).'; + } else { + $info[] = 'DB target: ' . $dbHost . ' / ' . $dbName . ' / user=' . $dbUser; + } + + if ($dbError !== null && $dbError !== '') { + $errors[] = 'Database error: ' . $dbError; + } + + $logPath = WRITEPATH . 'logs'; + if (!is_dir($logPath) || !is_writable($logPath)) { + $warnings[] = 'writable/logs is not writable. Error diagnostics may be incomplete.'; + } else { + $info[] = 'Logs path: ' . $logPath; + } + + if ($this->isSetupLocked()) { + $warnings[] = 'Setup lock file exists. Remove lock file if this is a fresh installation attempt.'; + } + + return [ + 'errors' => $errors, + 'warnings' => $warnings, + 'info' => $info, ]; } diff --git a/app/Views/billing/opd_prescription_basic.php b/app/Views/billing/opd_prescription_basic.php index 2436148..ff8ce7b 100644 --- a/app/Views/billing/opd_prescription_basic.php +++ b/app/Views/billing/opd_prescription_basic.php @@ -328,143 +328,12 @@
-
Old Consult (Fast View)
+
Extracted Scan Text
-
- - -
- -
-
-
-
- - PDF - - - scan - - -
-
-
- - - AI Ready - AI Failed - Alert -
- -
- - -
Report details are not available yet.
- -
-
-
-
-
- -
- -
No uploaded scan found for this OPD yet.
- -
- - - - - - - -
-
-
- - - -
- -
C:
- - -
D:
- - -
- - - - - - - - - - $oldMed) { ?> - - - - - - - -
#Medicine NameAction
- -
-
- - -
- - - Open PDF - - scan - - - -
- -
- - -
No old consult record found.
- - -
No old consult record found.
- - -
- - -
- - -
+ +
+ +
diff --git a/app/Views/setup/db_setup.php b/app/Views/setup/db_setup.php index 42398aa..40818d1 100644 --- a/app/Views/setup/db_setup.php +++ b/app/Views/setup/db_setup.php @@ -12,6 +12,35 @@
+ + +
+ Installation Diagnostics (Errors) + +
+ +
+ + + +
+ Installation Diagnostics (Warnings) + +
+ +
+ + + +
+ Installation Diagnostics (Info) + +
+ +
+ + +

Compares master schema file (or optional master DB) with client DB schema and generates CREATE TABLE IF NOT EXISTS / ALTER TABLE statements. diff --git a/public/index.php b/public/index.php index 8e834f2..a7dee49 100644 --- a/public/index.php +++ b/public/index.php @@ -37,6 +37,46 @@ if (getcwd() . DIRECTORY_SEPARATOR !== FCPATH) { chdir(FCPATH); } +/* + *--------------------------------------------------------------- + * TEMPORARY SERVER DEBUG FALLBACK + *--------------------------------------------------------------- + * New servers sometimes force CI_ENVIRONMENT=production via Apache/PHP-FPM, + * which hides the real 500 error details. Keep this block while debugging + * migration issues, then remove it after root cause is fixed. + */ +$_SERVER['CI_ENVIRONMENT'] = 'development'; +putenv('CI_ENVIRONMENT=development'); +error_reporting(E_ALL); +ini_set('display_errors', '1'); +ini_set('display_startup_errors', '1'); +ini_set('log_errors', '1'); + +$fallbackErrorLog = rtrim(sys_get_temp_dir(), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . 'hms_ci4_php_errors.log'; +ini_set('error_log', $fallbackErrorLog); + +register_shutdown_function(static function () use ($fallbackErrorLog): void { + $lastError = error_get_last(); + if ($lastError === null) { + return; + } + + $fatalTypes = [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR]; + if (! in_array((int) ($lastError['type'] ?? 0), $fatalTypes, true)) { + return; + } + + $line = sprintf( + "[%s] FATAL %s in %s:%d\n", + date('Y-m-d H:i:s'), + (string) ($lastError['message'] ?? 'Unknown fatal error'), + (string) ($lastError['file'] ?? 'unknown'), + (int) ($lastError['line'] ?? 0) + ); + + @file_put_contents($fallbackErrorLog, $line, FILE_APPEND); +}); + /* *--------------------------------------------------------------- * BOOTSTRAP THE APPLICATION