#Requires -Version 5.1 <# .SYNOPSIS Post-installation configuration for ROA Oracle Database. .DESCRIPTION Performs complete post-installation configuration including: - Creates ROAUPDATE physical folders (54 directories) - Creates Oracle DIRECTORY objects for PACK_UPDATE - Initializes SERVER_INFO with encoded passwords and paths - Sets AUTH_DETALII.CUSTOMER_ID for licensing - Creates scheduler jobs for automatic updates (disabled by default) .PARAMETER OracleHome Oracle home directory. If not specified, auto-detects from registry or environment. .PARAMETER ServiceName Database service name. Auto-detects: ROA for non-CDB, XEPDB1 for Oracle XE CDB. .PARAMETER SystemPassword SYSTEM user password. Default: romfastsoft .PARAMETER ContafinPassword CONTAFIN_ORACLE user password. Default: ROMFASTSOFT .PARAMETER RoaUpdatePath Base path for ROAUPDATE folder. Default: D:\ROAUPDATE .PARAMETER CustomerId Customer ID for licensing. Leave empty if not required. .PARAMETER EmailFrom Email sender address for update notifications. .PARAMETER EmailTo Email recipient address for update notifications. .PARAMETER EmailSmtp SMTP server hostname for update notifications. .PARAMETER EmailUsername SMTP authentication username (optional). .PARAMETER EmailPassword SMTP authentication password (optional). .PARAMETER SkipDirectories Skip creating physical directories (they may already exist). .PARAMETER SkipServerInfo Skip SERVER_INFO initialization. .PARAMETER SkipSchedulerJobs Skip creating scheduler jobs. .EXAMPLE .\08-post-install-config.ps1 .EXAMPLE .\08-post-install-config.ps1 -RoaUpdatePath "E:\ROAUPDATE" -CustomerId "138" .EXAMPLE .\08-post-install-config.ps1 -ServiceName "XEPDB1" -EmailTo "admin@company.ro" -EmailSmtp "mail.company.ro" .NOTES File Name : 08-post-install-config.ps1 Prerequisite : Oracle Database installed, CONTAFIN_ORACLE schema imported Run After : 01-07 scripts completed Copyright 2024 : ROMFAST #> [CmdletBinding()] param( [Parameter(Mandatory = $false)] [string]$OracleHome, [Parameter(Mandatory = $false)] [string]$ServiceName, [Parameter(Mandatory = $false)] [string]$DbHost, [Parameter(Mandatory = $false)] [int]$Port = 1521, [Parameter(Mandatory = $false)] [string]$SystemPassword = "romfastsoft", [Parameter(Mandatory = $false)] [string]$ContafinPassword = "ROMFASTSOFT", [Parameter(Mandatory = $false)] [string]$RoaUpdatePath = "D:\ROAUPDATE", [Parameter(Mandatory = $false)] [string]$CustomerId, [Parameter(Mandatory = $false)] [string]$EmailFrom = "roaupdate@romfast.ro", [Parameter(Mandatory = $false)] [string]$EmailTo, [Parameter(Mandatory = $false)] [string]$EmailSmtp = "mail.romfast.ro", [Parameter(Mandatory = $false)] [string]$EmailUsername, [Parameter(Mandatory = $false)] [string]$EmailPassword, [Parameter(Mandatory = $false)] [switch]$SkipDirectories, [Parameter(Mandatory = $false)] [switch]$SkipServerInfo, [Parameter(Mandatory = $false)] [switch]$SkipSchedulerJobs ) $ErrorActionPreference = 'Stop' # Load config.ps1 if exists (provides defaults) $configPath = Join-Path (Split-Path $PSScriptRoot -Parent) "config.ps1" if (Test-Path $configPath) { . $configPath # Use config values if parameters not provided if (-not $OracleHome -and $ORACLE_HOME) { $OracleHome = $ORACLE_HOME } if (-not $ServiceName -and $SERVICE_NAME) { $ServiceName = $SERVICE_NAME } if (-not $DbHost -and $DB_HOST) { $DbHost = $DB_HOST } if (-not $Port -and $DB_PORT) { $Port = $DB_PORT } if ($SystemPassword -eq "romfastsoft" -and $SYSTEM_PASSWORD) { $SystemPassword = $SYSTEM_PASSWORD } if ($ContafinPassword -eq "ROMFASTSOFT" -and $CONTAFIN_PASSWORD) { $ContafinPassword = $CONTAFIN_PASSWORD } } # Source library functions . "$PSScriptRoot\lib\logging-functions.ps1" . "$PSScriptRoot\lib\oracle-functions.ps1" # Initialize logging $logPath = Join-Path $PSScriptRoot "..\logs\08-post-install-config_$(Get-Date -Format 'yyyyMMdd_HHmmss').log" Initialize-LogFile -LogPath $logPath -ScriptName "08-post-install-config.ps1" # Define ROAUPDATE subdirectories (54 total) $roaUpdateSubdirs = @( "COMUNROA", "USERREPORTS", "ROAAPROV", "ROAAUTO", "ROABAVERT", "ROACASA", "ROACOMENZI", "ROACONIMPORT", "ROACONSTRUCTII", "ROACONT", "ROACONTRACTE", "ROADECL", "ROADEF", "ROADEFSALARII", "ROADEPOZIT", "ROADEVIZE", "ROAFACTURARE", "ROAFURNIZORI", "ROAGEN", "ROAGEST", "ROAGRESTAURANT", "ROAHOTEL", "ROAHOTELCONFIG", "ROAIMOB", "ROAINCHIDSAL", "ROALUCRARI", "ROAMANAGER", "ROAMASINI", "ROANOR", "ROANORFRUVIMED", "ROANORRENAV", "ROANORUTMIDIA", "ROAOBINV", "ROAOFERTARE", "ROAPRETURI", "ROAPRINT", "ROAPRINT_INITIALIZARI", "ROAPRODAGR", "ROAPRODUCTIE", "ROAREGISTRATURA", "ROAREPARTIZSAL", "ROARES", "ROARESTAURANT", "ROARETAIL", "ROARETAILMON", "ROASAL", "ROASALSPEC", "ROASITFIN", "ROASITOP", "ROASTART", "ROASUPORT", "ROATELCOMM", "ROATELMON", "ROAVIN" ) try { Write-LogSection "ROA Post-Installation Configuration" # Step 1: Validate Oracle installation Write-Log "Detecting Oracle installation..." $oraHome = Get-OracleHome -OracleHome $OracleHome Write-LogSuccess "Oracle Home: $oraHome" # Step 2: Auto-detect service name if not specified if (-not $ServiceName) { Write-Log "Auto-detecting service name..." try { $version = Get-OracleVersion -OracleHome $oraHome -ServiceName "XE" -DbHost $DbHost -Port $Port -Password $SystemPassword if ($version.IsCDB) { $ServiceName = "XEPDB1" } else { $ServiceName = "XE" } } catch { try { $null = Test-OracleConnection -OracleHome $oraHome -ServiceName "ROA" -DbHost $DbHost -Port $Port -Password $SystemPassword $ServiceName = "ROA" } catch { $ServiceName = "XEPDB1" } } } Write-LogSuccess "Service Name: $ServiceName" if ($DbHost) { Write-Log "Database Host: ${DbHost}:${Port}" } # Step 3: Test connection Write-Log "Testing database connection..." if (-not (Test-OracleConnection -OracleHome $oraHome -ServiceName $ServiceName -DbHost $DbHost -Port $Port -Password $SystemPassword)) { throw "Cannot connect to database. Please verify ServiceName, Host and SystemPassword." } Write-LogSuccess "Database connection successful" # Step 4: Verify CONTAFIN_ORACLE schema exists Write-Log "Verifying CONTAFIN_ORACLE schema..." if (-not (Test-OracleUser -OracleHome $oraHome -ServiceName $ServiceName -Password $SystemPassword -SchemaName "CONTAFIN_ORACLE")) { throw "CONTAFIN_ORACLE schema not found. Please run scripts 01-07 first." } Write-LogSuccess "CONTAFIN_ORACLE schema exists" # Step 5: Create ROAUPDATE physical directories if (-not $SkipDirectories) { Write-LogSection "Creating ROAUPDATE Physical Directories" # Create main ROAUPDATE directory if (-not (Test-Path $RoaUpdatePath)) { New-Item -ItemType Directory -Path $RoaUpdatePath -Force | Out-Null Write-Log "Created: $RoaUpdatePath" } else { Write-Log "Exists: $RoaUpdatePath" } # Create _ARHIVE subdirectory $arhivePath = Join-Path $RoaUpdatePath "_ARHIVE" if (-not (Test-Path $arhivePath)) { New-Item -ItemType Directory -Path $arhivePath -Force | Out-Null Write-Log "Created: $arhivePath" } # Create all module subdirectories $createdCount = 0 $existsCount = 0 foreach ($subdir in $roaUpdateSubdirs) { $subdirPath = Join-Path $arhivePath $subdir if (-not (Test-Path $subdirPath)) { New-Item -ItemType Directory -Path $subdirPath -Force | Out-Null $createdCount++ } else { $existsCount++ } } Write-LogSuccess "Created $createdCount new directories, $existsCount already existed" Write-LogSuccess "Total: $($roaUpdateSubdirs.Count) module directories" } else { Write-Log "Skipping physical directory creation as requested" } # Step 6: Create Oracle DIRECTORY objects Write-LogSection "Creating Oracle DIRECTORY Objects" $sqlDir = Join-Path $PSScriptRoot "..\sql" $directoriesScript = Join-Path $sqlDir "directories-roaupdate.sql" if (Test-Path $directoriesScript) { # Create temp SQL file with substitution $tempSql = [System.IO.Path]::GetTempFileName() $tempSql = [System.IO.Path]::ChangeExtension($tempSql, ".sql") $sqlContent = @" DEFINE roaupdate_path = '$RoaUpdatePath' @"$directoriesScript" EXIT; "@ Set-Content -Path $tempSql -Value $sqlContent -Encoding ASCII $result = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName -DbHost $DbHost -Port $Port ` -Username "SYS" -Password $SystemPassword -SqlFile $tempSql -AsSysdba Remove-Item -Path $tempSql -Force -ErrorAction SilentlyContinue if ($result -match "UPD_ROAUPDATE") { Write-LogSuccess "Oracle DIRECTORY objects created successfully" } else { Write-LogWarning "Could not verify DIRECTORY objects creation" Write-LogDebug $result } } else { Write-LogWarning "directories-roaupdate.sql not found at $directoriesScript" } # Step 7: Initialize SERVER_INFO if (-not $SkipServerInfo) { Write-LogSection "Initializing SERVER_INFO" # Get SQLPlus path $sqlplusPath = Join-Path $oraHome "bin\sqlplus.exe" # Encode passwords using Oracle PACK_UTILS Write-Log "Encoding passwords..." $encodeSql = @" SET PAGESIZE 0 FEEDBACK OFF VERIFY OFF HEADING OFF ECHO OFF LINESIZE 500 SELECT 'SYS_ENCODED:' || CAST(pack_utils.encodebase64(pack_utils.zipblob(pack_utils.Clob2Blob('$SystemPassword'))) AS VARCHAR2(500)) FROM dual; SELECT 'CONTAFIN_ENCODED:' || CAST(pack_utils.encodebase64(pack_utils.zipblob(pack_utils.Clob2Blob('$ContafinPassword'))) AS VARCHAR2(500)) FROM dual; EXIT; "@ $encodeResult = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName -DbHost $DbHost -Port $Port ` -Username "CONTAFIN_ORACLE" -Password $ContafinPassword -SqlCommand $encodeSql -Silent $sysPasswordEncoded = "" $contafinPasswordEncoded = "" foreach ($line in $encodeResult -split "`n") { if ($line -match "^SYS_ENCODED:(.+)$") { $sysPasswordEncoded = $Matches[1].Trim() } elseif ($line -match "^CONTAFIN_ENCODED:(.+)$") { $contafinPasswordEncoded = $Matches[1].Trim() } } if ($sysPasswordEncoded -and $contafinPasswordEncoded) { Write-LogSuccess "Passwords encoded successfully" } else { Write-LogWarning "Could not encode passwords - using placeholders" $sysPasswordEncoded = "ENCODE_FAILED" $contafinPasswordEncoded = "ENCODE_FAILED" } # Set default email values if not provided if (-not $EmailTo) { $EmailTo = "admin@" + $env:USERDOMAIN + ".local" } if (-not $EmailUsername) { $EmailUsername = $EmailFrom } if (-not $EmailPassword) { $EmailPassword = "changeme" } # Initialize SERVER_INFO $serverInfoSql = @" SET FEEDBACK ON SERVEROUTPUT ON VERIFY OFF -- System passwords (encoded) MERGE INTO server_info t USING (SELECT 'PASSWORD_SYS' AS varname, '$sysPasswordEncoded' AS varvalue FROM dual) s ON (t.varname = s.varname) WHEN MATCHED THEN UPDATE SET t.varvalue = s.varvalue WHEN NOT MATCHED THEN INSERT (varname, varvalue) VALUES (s.varname, s.varvalue); MERGE INTO server_info t USING (SELECT 'PASSWORD_CONTAFIN_ORACLE' AS varname, '$contafinPasswordEncoded' AS varvalue FROM dual) s ON (t.varname = s.varname) WHEN MATCHED THEN UPDATE SET t.varvalue = s.varvalue WHEN NOT MATCHED THEN INSERT (varname, varvalue) VALUES (s.varname, s.varvalue); -- Local paths MERGE INTO server_info t USING (SELECT 'ROAUPDATEPATH' AS varname, '$RoaUpdatePath' AS varvalue FROM dual) s ON (t.varname = s.varname) WHEN MATCHED THEN UPDATE SET t.varvalue = s.varvalue WHEN NOT MATCHED THEN INSERT (varname, varvalue) VALUES (s.varname, s.varvalue); MERGE INTO server_info t USING (SELECT 'SQLPLUSPATH' AS varname, '$sqlplusPath' AS varvalue FROM dual) s ON (t.varname = s.varname) WHEN MATCHED THEN UPDATE SET t.varvalue = s.varvalue WHEN NOT MATCHED THEN INSERT (varname, varvalue) VALUES (s.varname, s.varvalue); MERGE INTO server_info t USING (SELECT 'POWERSHELLPATH' AS varname, 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe' AS varvalue FROM dual) s ON (t.varname = s.varname) WHEN MATCHED THEN UPDATE SET t.varvalue = s.varvalue WHEN NOT MATCHED THEN INSERT (varname, varvalue) VALUES (s.varname, s.varvalue); -- Update configuration MERGE INTO server_info t USING (SELECT 'UPDATEPREREQ' AS varname, '1' AS varvalue FROM dual) s ON (t.varname = s.varname) WHEN MATCHED THEN UPDATE SET t.varvalue = s.varvalue WHEN NOT MATCHED THEN INSERT (varname, varvalue) VALUES (s.varname, s.varvalue); MERGE INTO server_info t USING (SELECT 'POWERSHELLDOWNLOAD' AS varname, '1' AS varvalue FROM dual) s ON (t.varname = s.varname) WHEN MATCHED THEN UPDATE SET t.varvalue = s.varvalue WHEN NOT MATCHED THEN INSERT (varname, varvalue) VALUES (s.varname, s.varvalue); MERGE INTO server_info t USING (SELECT 'POWERSHELLTIMEOUT' AS varname, '30' AS varvalue FROM dual) s ON (t.varname = s.varname) WHEN MATCHED THEN UPDATE SET t.varvalue = s.varvalue WHEN NOT MATCHED THEN INSERT (varname, varvalue) VALUES (s.varname, s.varvalue); -- Email configuration MERGE INTO server_info t USING (SELECT 'EMAIL_FROM' AS varname, '$EmailFrom' AS varvalue FROM dual) s ON (t.varname = s.varname) WHEN MATCHED THEN UPDATE SET t.varvalue = s.varvalue WHEN NOT MATCHED THEN INSERT (varname, varvalue) VALUES (s.varname, s.varvalue); MERGE INTO server_info t USING (SELECT 'EMAIL_TO' AS varname, '$EmailTo' AS varvalue FROM dual) s ON (t.varname = s.varname) WHEN MATCHED THEN UPDATE SET t.varvalue = s.varvalue WHEN NOT MATCHED THEN INSERT (varname, varvalue) VALUES (s.varname, s.varvalue); MERGE INTO server_info t USING (SELECT 'EMAIL_CC' AS varname, '' AS varvalue FROM dual) s ON (t.varname = s.varname) WHEN MATCHED THEN UPDATE SET t.varvalue = s.varvalue WHEN NOT MATCHED THEN INSERT (varname, varvalue) VALUES (s.varname, s.varvalue); MERGE INTO server_info t USING (SELECT 'EMAIL_SMTP' AS varname, '$EmailSmtp' AS varvalue FROM dual) s ON (t.varname = s.varname) WHEN MATCHED THEN UPDATE SET t.varvalue = s.varvalue WHEN NOT MATCHED THEN INSERT (varname, varvalue) VALUES (s.varname, s.varvalue); MERGE INTO server_info t USING (SELECT 'EMAIL_PORT' AS varname, '25' AS varvalue FROM dual) s ON (t.varname = s.varname) WHEN MATCHED THEN UPDATE SET t.varvalue = s.varvalue WHEN NOT MATCHED THEN INSERT (varname, varvalue) VALUES (s.varname, s.varvalue); MERGE INTO server_info t USING (SELECT 'EMAIL_METHOD' AS varname, 'UTL_SMTP' AS varvalue FROM dual) s ON (t.varname = s.varname) WHEN MATCHED THEN UPDATE SET t.varvalue = s.varvalue WHEN NOT MATCHED THEN INSERT (varname, varvalue) VALUES (s.varname, s.varvalue); MERGE INTO server_info t USING (SELECT 'EMAIL_USERNAME' AS varname, '$EmailUsername' AS varvalue FROM dual) s ON (t.varname = s.varname) WHEN MATCHED THEN UPDATE SET t.varvalue = s.varvalue WHEN NOT MATCHED THEN INSERT (varname, varvalue) VALUES (s.varname, s.varvalue); MERGE INTO server_info t USING (SELECT 'EMAIL_PASSWORD' AS varname, '$EmailPassword' AS varvalue FROM dual) s ON (t.varname = s.varname) WHEN MATCHED THEN UPDATE SET t.varvalue = s.varvalue WHEN NOT MATCHED THEN INSERT (varname, varvalue) VALUES (s.varname, s.varvalue); -- Update server URLs MERGE INTO server_info t USING (SELECT 'UPD_URL_APP' AS varname, 'https://update.romfast.ro/roa/' AS varvalue FROM dual) s ON (t.varname = s.varname) WHEN MATCHED THEN UPDATE SET t.varvalue = s.varvalue WHEN NOT MATCHED THEN INSERT (varname, varvalue) VALUES (s.varname, s.varvalue); MERGE INTO server_info t USING (SELECT 'UPD_URL_APP_BACKUP' AS varname, 'https://update2.romfast.ro/roa/' AS varvalue FROM dual) s ON (t.varname = s.varname) WHEN MATCHED THEN UPDATE SET t.varvalue = s.varvalue WHEN NOT MATCHED THEN INSERT (varname, varvalue) VALUES (s.varname, s.varvalue); MERGE INTO server_info t USING (SELECT 'UPD_URL_VERSION' AS varname, 'https://update.romfast.ro/version.txt' AS varvalue FROM dual) s ON (t.varname = s.varname) WHEN MATCHED THEN UPDATE SET t.varvalue = s.varvalue WHEN NOT MATCHED THEN INSERT (varname, varvalue) VALUES (s.varname, s.varvalue); COMMIT; SELECT 'SERVER_INFO_CONFIGURED' FROM dual; EXIT; "@ $result = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName -DbHost $DbHost -Port $Port ` -Username "CONTAFIN_ORACLE" -Password $ContafinPassword -SqlCommand $serverInfoSql if ($result -match "SERVER_INFO_CONFIGURED") { Write-LogSuccess "SERVER_INFO initialized successfully" } else { Write-LogWarning "Could not verify SERVER_INFO configuration" Write-LogDebug $result } } else { Write-Log "Skipping SERVER_INFO initialization as requested" } # Step 8: Initialize AUTH_DETALII.CUSTOMER_ID if ($CustomerId) { Write-LogSection "Setting AUTH_DETALII Customer ID" $authSql = @" SET FEEDBACK ON SERVEROUTPUT ON VERIFY OFF DECLARE v_count NUMBER; BEGIN SELECT COUNT(*) INTO v_count FROM sys.auth_detalii; IF v_count > 0 THEN UPDATE sys.auth_detalii SET detalii = '$CustomerId' WHERE ROWNUM = 1; DBMS_OUTPUT.PUT_LINE('Updated existing record with Customer ID: $CustomerId'); ELSE INSERT INTO sys.auth_detalii (detalii) VALUES ('$CustomerId'); DBMS_OUTPUT.PUT_LINE('Inserted new record with Customer ID: $CustomerId'); END IF; COMMIT; END; / SELECT 'CUSTOMER_ID_SET' FROM dual; EXIT; "@ $result = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName -DbHost $DbHost -Port $Port ` -Username "SYS" -Password $SystemPassword -SqlCommand $authSql -AsSysdba if ($result -match "CUSTOMER_ID_SET") { Write-LogSuccess "Customer ID set to: $CustomerId" } else { Write-LogWarning "Could not verify Customer ID configuration" Write-LogDebug $result } } else { Write-Log "No Customer ID specified - skipping AUTH_DETALII configuration" } # Step 9: Create scheduler jobs if (-not $SkipSchedulerJobs) { Write-LogSection "Creating Scheduler Jobs" $schedulerScript = Join-Path $sqlDir "scheduler-jobs.sql" if (Test-Path $schedulerScript) { $result = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName -DbHost $DbHost -Port $Port ` -Username "SYS" -Password $SystemPassword -SqlFile $schedulerScript -AsSysdba if ($result -match "UPDATEROA_ZILNIC") { Write-LogSuccess "Scheduler jobs created (DISABLED by default)" Write-Log "To enable jobs, run:" Write-Log " EXEC DBMS_SCHEDULER.ENABLE('CONTAFIN_ORACLE.UPDATEROA_ZILNIC');" Write-Log " EXEC DBMS_SCHEDULER.ENABLE('CONTAFIN_ORACLE.UPDATERTVAI_ZILNIC');" } else { Write-LogWarning "Could not verify scheduler jobs creation" Write-LogDebug $result } } else { Write-LogWarning "scheduler-jobs.sql not found at $schedulerScript" } } else { Write-Log "Skipping scheduler jobs creation as requested" } # Step 10: Verification Write-LogSection "Post-Installation Verification" $verifySql = @" SET PAGESIZE 100 FEEDBACK OFF VERIFY OFF HEADING ON ECHO OFF LINESIZE 200 PROMPT PROMPT === Oracle DIRECTORY Objects (UPD_*) === SELECT directory_name, SUBSTR(directory_path, 1, 60) AS directory_path FROM dba_directories WHERE directory_name LIKE 'UPD_%' ORDER BY directory_name; PROMPT PROMPT === SERVER_INFO Configuration === SELECT varname, CASE WHEN UPPER(varname) LIKE '%PASSWORD%' THEN '***HIDDEN***' ELSE SUBSTR(varvalue, 1, 50) END AS varvalue FROM contafin_oracle.server_info WHERE varname IN ( 'ROAUPDATEPATH', 'SQLPLUSPATH', 'POWERSHELLPATH', 'UPDATEPREREQ', 'POWERSHELLDOWNLOAD', 'EMAIL_FROM', 'EMAIL_TO', 'EMAIL_SMTP', 'UPD_URL_APP', 'PASSWORD_SYS', 'PASSWORD_CONTAFIN_ORACLE' ) ORDER BY varname; PROMPT PROMPT === AUTH_DETALII Customer ID === SELECT detalii AS customer_id FROM sys.auth_detalii; PROMPT PROMPT === Scheduler Jobs === SELECT job_name, enabled, state FROM dba_scheduler_jobs WHERE owner = 'CONTAFIN_ORACLE' AND job_name IN ('UPDATEROA_ZILNIC', 'UPDATERTVAI_ZILNIC'); EXIT; "@ $verifyResult = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName -DbHost $DbHost -Port $Port ` -Username "SYS" -Password $SystemPassword -SqlCommand $verifySql -AsSysdba Write-Host "" Write-Host $verifyResult Write-Host "" # Summary Write-LogSection "Setup Complete" Write-LogSuccess "Post-installation configuration completed successfully!" Write-Host "" Write-Log "Summary:" Write-Log " Oracle Home: $oraHome" Write-Log " Service Name: $ServiceName" Write-Log " ROAUPDATE Path: $RoaUpdatePath" Write-Log " Directories: $($roaUpdateSubdirs.Count) module folders" if ($CustomerId) { Write-Log " Customer ID: $CustomerId" } Write-Log " Scheduler Jobs: DISABLED (enable manually when ready)" Write-Host "" Write-Log "Next steps:" Write-Log " 1. Run 07-verify-installation.ps1 to verify complete installation" Write-Log " 2. Test PACK_UPDATE.UPDATEROA manually before enabling scheduler" Write-Log " 3. Enable scheduler jobs when ready for automatic updates" Close-LogFile -Success $true exit 0 } catch { Write-LogError "Post-installation configuration failed: $_" Write-LogError $_.ScriptStackTrace Close-LogFile -Success $false exit 1 }