feat: Migrate to ultrathin monolith architecture

Consolidate 3 separate applications (reports-app, data-entry-app, telegram-bot) into a unified
architecture with single backend and frontend:

Backend Changes:
- Unified FastAPI backend at backend/ with modular structure
- Modules: reports, data_entry, telegram in backend/modules/
- Centralized config.py and main.py with all routers registered
- Single worker mode (--workers 1) for Telegram bot compatibility
- Shared Oracle connection pool and JWT authentication
- Unified requirements.txt and environment configuration

Frontend Changes:
- Single Vue.js SPA with module-based routing
- Unified frontend at src/ with modules in src/modules/{reports,data-entry}/
- Shared components and stores in src/shared/
- Error boundaries for module isolation
- Dual API proxy in Vite for module communication

Infrastructure:
- New unified startup scripts: start-prod.sh, start-test.sh, start-backend.sh
- Environment templates: .env.dev.example, .env.test.example, .env.prod.example
- Updated deployment scripts for Windows IIS
- Simplified SSH tunnel management

Documentation:
- Comprehensive CLAUDE.md with architecture overview
- Module-specific docs in docs/{data-entry,telegram}/
- Architecture decision records in docs/ARCHITECTURE-DECISIONS.md
- Deployment guides consolidated in deployment/windows/docs/

This migration reduces complexity, improves maintainability, and enables easier
deployment while maintaining all existing functionality.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-29 23:48:14 +02:00
parent 2a101f1ef5
commit c5e051ad80
378 changed files with 7566 additions and 73730 deletions

View File

@@ -68,7 +68,7 @@
[CmdletBinding()]
param(
[ValidateSet("All", "Frontend", "Backend", "TelegramBot", "DataEntryApp", "DataEntryBackend")]
[ValidateSet("All", "Frontend", "Backend")]
[string]$Component = "",
[string]$OutputPath = "./deploy-package",
@@ -85,14 +85,9 @@ $ErrorActionPreference = "Stop"
# =============================================================================
$config = @{
# Reports App sources
BackendSource = "../../reports-app/backend"
FrontendSource = "../../reports-app/frontend"
TelegramBotSource = "../../reports-app/telegram-bot"
# Data Entry App sources
DataEntryBackendSource = "../../data-entry-app/backend"
DataEntryFrontendSource = "../../data-entry-app/frontend"
# Shared sources
# Ultrathin Monolith sources (relative to deployment/windows/ directory)
BackendSource = "../../backend"
FrontendSource = "../../src"
SharedSource = "../../shared"
ConfigSource = "../config"
RequiredNodeVersion = 16
@@ -175,29 +170,21 @@ function Clear-BuildCache {
function Show-BuildMenu {
Write-Host "`n" + ("=" * 70) -ForegroundColor Cyan
Write-Host " ROA2WEB - Build Component Selection Menu" -ForegroundColor Cyan
Write-Host " Ultrathin Monolith Architecture" -ForegroundColor Cyan
Write-Host ("=" * 70) -ForegroundColor Cyan
Write-Host ""
Write-Host " Select components to build:" -ForegroundColor Yellow
Write-Host ""
Write-Host " [1] All Components" -ForegroundColor White
Write-Host " (Reports App + Telegram Bot + Data Entry App)" -ForegroundColor Gray
Write-Host " (Unified Backend + Frontend)" -ForegroundColor Gray
Write-Host " Includes: Reports, Data Entry, and Telegram modules" -ForegroundColor DarkGray
Write-Host ""
Write-Host " --- Reports App ---" -ForegroundColor Cyan
Write-Host " [2] Reports Frontend + Backend" -ForegroundColor White
Write-Host " (Vue.js build + FastAPI backend files)" -ForegroundColor Gray
Write-Host " [2] Frontend + Backend" -ForegroundColor White
Write-Host " (Vue.js SPA build + Unified FastAPI backend)" -ForegroundColor Gray
Write-Host ""
Write-Host " [3] Reports Backend Only" -ForegroundColor White
Write-Host " (FastAPI backend files + shared modules)" -ForegroundColor Gray
Write-Host ""
Write-Host " [4] Telegram Bot Only" -ForegroundColor White
Write-Host " (Telegram bot standalone package)" -ForegroundColor Gray
Write-Host ""
Write-Host " --- Data Entry App ---" -ForegroundColor Cyan
Write-Host " [5] Data Entry Frontend + Backend" -ForegroundColor White
Write-Host " (Vue.js build + FastAPI backend files)" -ForegroundColor Gray
Write-Host ""
Write-Host " [6] Data Entry Backend Only" -ForegroundColor White
Write-Host " (FastAPI backend files only)" -ForegroundColor Gray
Write-Host " [3] Backend Only" -ForegroundColor White
Write-Host " (Unified FastAPI backend + shared modules)" -ForegroundColor Gray
Write-Host " All modules included - control via MODULE_*_ENABLED flags" -ForegroundColor DarkGray
Write-Host ""
Write-Host " [C] Clean Build Cache" -ForegroundColor Yellow
Write-Host " (Remove cached node_modules to free disk space)" -ForegroundColor Gray
@@ -214,9 +201,6 @@ function Show-BuildMenu {
"1" { return "All" }
"2" { return "Frontend" }
"3" { return "Backend" }
"4" { return "TelegramBot" }
"5" { return "DataEntryApp" }
"6" { return "DataEntryBackend" }
"C" {
Clear-BuildCache
Write-Host "`nPress any key to return to menu..." -ForegroundColor Gray
@@ -228,7 +212,7 @@ function Show-BuildMenu {
exit 0
}
default {
Write-Host "Invalid choice. Please select 1-6, C or Q." -ForegroundColor Red
Write-Host "Invalid choice. Please select 1-3, C or Q." -ForegroundColor Red
}
}
} while ($true)
@@ -273,25 +257,34 @@ function Build-Frontend {
throw "Frontend source path not found: $SourcePath"
}
# Determine if this is reports-app or data-entry-app based on source path
$appFolder = Split-Path (Split-Path $SourcePath -Parent) -Leaf # "reports-app" or "data-entry-app"
# For ultrathin monolith, frontend sources are in src/ directory
# but package.json and vite.config.js are in project root
$appFolder = "roa2web-ultrathin-monolith"
# Create temporary build directory with full project structure
# Create temporary build directory - this is the project root
# Structure:
# .temp-frontend-build/
# ├── reports-app/frontend/ (or data-entry-app/frontend/)
# └── shared/
# |- package.json (from project root)
# |- vite.config.js (from project root)
# |- src/ (frontend source)
# \- shared/
$tempRootDir = Join-Path $OutputPath ".temp-frontend-build"
if (Test-Path $tempRootDir) {
Write-Step "Cleaning existing temp build directory..."
Remove-Item -Path $tempRootDir -Recurse -Force
}
# Create the app-specific path inside temp
$tempBuildDir = Join-Path $tempRootDir "$appFolder\frontend"
New-Item -ItemType Directory -Path $tempBuildDir -Force | Out-Null
# Create temp root (this will be where npm install runs)
New-Item -ItemType Directory -Path $tempRootDir -Force | Out-Null
# Create src subdirectory
$tempSrcDir = Join-Path $tempRootDir "src"
New-Item -ItemType Directory -Path $tempSrcDir -Force | Out-Null
Write-Success "Created temp build directory (isolated from WSL)"
# The build directory is the root, not src
$tempBuildDir = $tempRootDir
# Create cache directory for node_modules (OUTSIDE deploy-package)
$scriptDir = Split-Path -Parent $PSScriptRoot
$cacheDir = Join-Path $scriptDir ".build-cache-$appFolder"
@@ -299,7 +292,7 @@ function Build-Frontend {
New-Item -ItemType Directory -Path $cacheDir -Force | Out-Null
}
# Copy frontend sources to temp (exclude node_modules, dist, .git)
# Copy src/ contents to temp src/ subdirectory
Write-Step "Copying frontend sources to temp directory..."
$excludeDirs = @("node_modules", "dist", ".git", "__pycache__", ".vscode", ".idea")
$excludeFiles = @(".env", ".env.local", "*.log")
@@ -327,7 +320,8 @@ function Build-Frontend {
}
if ($isExcludedFile) { return }
$destPath = Join-Path $tempBuildDir $relativePath
# Copy to src/ subdirectory
$destPath = Join-Path $tempSrcDir $relativePath
if ($_.PSIsContainer) {
if (-not (Test-Path $destPath)) {
@@ -343,9 +337,25 @@ function Build-Frontend {
}
Write-Success "Frontend sources copied to temp"
# Copy shared folder to maintain relative imports (../../../shared/frontend/)
# Now shared goes into tempRootDir/shared (same level as reports-app or data-entry-app)
$projectRoot = Split-Path (Split-Path $SourcePath -Parent) -Parent
# Copy package.json, vite.config.js, package-lock.json, index.html from project root
Write-Step "Copying build configuration files..."
$projectRoot = Split-Path $SourcePath -Parent
$configFiles = @("package.json", "vite.config.js", "package-lock.json", "index.html")
foreach ($file in $configFiles) {
$srcFile = Join-Path $projectRoot $file
if (Test-Path $srcFile) {
$destFile = Join-Path $tempBuildDir $file
Copy-Item -Path $srcFile -Destination $destFile -Force
Write-Success "Copied: $file"
} else {
Write-Warning "Not found: $file"
}
}
# Copy shared folder to maintain relative imports (../shared/)
# For ultrathin monolith: src/ and shared/ are siblings at project root
$projectRoot = Split-Path $SourcePath -Parent
$sharedSourcePath = Join-Path $projectRoot "shared"
if (Test-Path $sharedSourcePath) {
@@ -366,7 +376,7 @@ function Build-Frontend {
Write-Warning "Shared folder not found at: $sharedSourcePath"
}
# Build in temp directory (now at tempRootDir/appFolder/frontend)
# Build in temp directory (now at tempRootDir/src)
Push-Location $tempBuildDir
try {
# Check if dependencies need to be reinstalled
@@ -434,23 +444,8 @@ function Build-Frontend {
throw "Vite not found in node_modules - devDependencies not installed"
}
# Create junction for node_modules at tempRootDir level
# This allows shared folder to resolve npm dependencies
$tempRootNodeModules = Join-Path $tempRootDir "node_modules"
if (-not (Test-Path $tempRootNodeModules)) {
Write-Step "Creating node_modules junction for shared imports..."
# Use cmd /c mklink /J for directory junction (works without admin rights)
$junctionResult = cmd /c mklink /J "$tempRootNodeModules" "$nodeModulesPath" 2>&1
if (Test-Path $tempRootNodeModules) {
Write-Success "Node modules junction created for shared folder access"
} else {
Write-Warning "Could not create junction: $junctionResult"
# Fallback: copy node_modules (slower but works)
Write-Info "Falling back to copying node_modules..."
Copy-Item -Path $nodeModulesPath -Destination $tempRootNodeModules -Recurse -Force
Write-Success "Node modules copied to root (fallback)"
}
}
# node_modules is already in tempBuildDir (which is tempRootDir)
# No need for junction since we build from project root
# Build for production
Write-Step "Building for production..."
@@ -572,201 +567,9 @@ function Copy-BackendFiles {
Write-Success "Verified: requirements.txt present"
}
function Copy-TelegramBotFiles {
param(
[string]$SourcePath,
[string]$DestPath
)
# Copy-TelegramBotFiles function removed - Telegram is now part of unified backend (backend/modules/telegram/)
Write-Step "Copying Telegram bot files..."
if (-not (Test-Path $SourcePath)) {
throw "Telegram bot source path not found: $SourcePath"
}
if (-not (Test-Path $DestPath)) {
New-Item -ItemType Directory -Path $DestPath -Force | Out-Null
}
# Exclude patterns
$excludeDirs = @("venv", "data", "logs", "temp", "backups", "__pycache__", ".pytest_cache", "tests", ".git")
$excludeFiles = @(".env", "*.pyc", "*.pyo", "*.log", "*.db", ".DS_Store", "Thumbs.db")
# Copy app/ directory
$sourceApp = Join-Path $SourcePath "app"
$destApp = Join-Path $DestPath "app"
New-Item -ItemType Directory -Path $destApp -Force | Out-Null
$fileCount = 0
Get-ChildItem -Path $sourceApp -Recurse | ForEach-Object {
# Check exclusions
$inExcludedDir = $false
foreach ($excludeDir in $excludeDirs) {
if ($_.FullName -like "*\$excludeDir\*" -or $_.FullName -like "*/$excludeDir/*") {
$inExcludedDir = $true
break
}
}
if ($inExcludedDir) {
return
}
$isExcludedFile = $false
foreach ($pattern in $excludeFiles) {
if ($_.Name -like $pattern) {
$isExcludedFile = $true
break
}
}
if ($isExcludedFile) {
return
}
$relativePath = $_.FullName.Substring($sourceApp.Length)
$destFile = Join-Path $destApp $relativePath
if ($_.PSIsContainer) {
if (-not (Test-Path $destFile)) {
New-Item -ItemType Directory -Path $destFile -Force | Out-Null
}
} else {
$destFileDir = Split-Path $destFile -Parent
if (-not (Test-Path $destFileDir)) {
New-Item -ItemType Directory -Path $destFileDir -Force | Out-Null
}
Copy-Item -Path $_.FullName -Destination $destFile -Force
$fileCount++
}
}
Write-Success "Copied $fileCount app files"
# Copy requirements.txt
$sourceReq = Join-Path $SourcePath "requirements.txt"
$destReq = Join-Path $DestPath "requirements.txt"
if (Test-Path $sourceReq) {
Copy-Item -Path $sourceReq -Destination $destReq -Force
Write-Success "requirements.txt copied"
}
# Copy .env.example from source (keeps it synchronized with development)
$sourceEnvExample = Join-Path $SourcePath ".env.example"
$destEnvExample = Join-Path $DestPath ".env.example"
if (Test-Path $sourceEnvExample) {
Copy-Item -Path $sourceEnvExample -Destination $destEnvExample -Force
Write-Success ".env.example template copied"
} else {
Write-Warning ".env.example not found in source - manual configuration required"
}
}
function Copy-DataEntryBackendFiles {
param(
[string]$SourcePath,
[string]$DestPath
)
Write-Step "Copying Data Entry backend files..."
if (-not (Test-Path $SourcePath)) {
throw "Data Entry backend source path not found: $SourcePath"
}
if (-not (Test-Path $DestPath)) {
New-Item -ItemType Directory -Path $DestPath -Force | Out-Null
}
# Exclude patterns
$excludeDirs = @("venv", "__pycache__", ".pytest_cache", "logs", "temp", "node_modules", "data")
$excludeFiles = @("*.pyc", "*.pyo", "*.log", ".env", ".env.local", "*.db")
$normalizedSourcePath = $SourcePath.TrimEnd('\', '/') + '\'
$testExclude = {
param([string]$RelativePath, [bool]$IsDirectory, [array]$ExcludeDirs, [array]$ExcludeFiles)
if ($IsDirectory) {
$dirName = Split-Path $RelativePath -Leaf
if ($ExcludeDirs -contains $dirName) {
return $true
}
}
$pathParts = $RelativePath -split '[\\/]'
foreach ($part in $pathParts) {
if ($ExcludeDirs -contains $part) {
return $true
}
}
if (-not $IsDirectory) {
foreach ($pattern in $ExcludeFiles) {
if ($RelativePath -like $pattern) {
return $true
}
}
}
return $false
}
Get-ChildItem -Path $SourcePath -Recurse | ForEach-Object {
if ($_.FullName.Length -le $normalizedSourcePath.Length) {
return
}
$relativePath = $_.FullName.Substring($normalizedSourcePath.Length)
$shouldExclude = & $testExclude -RelativePath $relativePath -IsDirectory $_.PSIsContainer -ExcludeDirs $excludeDirs -ExcludeFiles $excludeFiles
if ($shouldExclude) {
return
}
$destFile = Join-Path $DestPath $relativePath
if ($_.PSIsContainer) {
if (-not (Test-Path $destFile)) {
New-Item -ItemType Directory -Path $destFile -Force | Out-Null
}
} else {
$destDir = Split-Path $destFile -Parent
if (-not (Test-Path $destDir)) {
New-Item -ItemType Directory -Path $destDir -Force | Out-Null
}
Copy-Item -Path $_.FullName -Destination $destFile -Force
}
}
$backendFiles = Get-ChildItem -Path $DestPath -Recurse -File
Write-Success "Copied $(($backendFiles).Count) Data Entry backend files"
# Copy .env.example explicitly
$sourceEnvExample = Join-Path $SourcePath ".env.example"
$destEnvExample = Join-Path $DestPath ".env.example"
if (Test-Path $sourceEnvExample) {
Copy-Item -Path $sourceEnvExample -Destination $destEnvExample -Force
Write-Success ".env.example template copied"
}
# Copy .env.prod and .env.test templates
foreach ($envFile in @(".env.prod", ".env.test")) {
$sourceEnv = Join-Path $SourcePath $envFile
$destEnv = Join-Path $DestPath $envFile
if (Test-Path $sourceEnv) {
Copy-Item -Path $sourceEnv -Destination $destEnv -Force
Write-Success "$envFile template copied"
}
}
# Verify requirements.txt
$requirementsTxt = Join-Path $DestPath "requirements.txt"
if (-not (Test-Path $requirementsTxt)) {
Write-Error "CRITICAL: requirements.txt not found!"
throw "Data Entry backend package incomplete - missing requirements.txt"
}
Write-Success "Verified: requirements.txt present"
}
# Copy-DataEntryBackendFiles function removed - Data Entry is now part of unified backend (backend/modules/data_entry/)
function Copy-SharedModules {
param(
@@ -898,12 +701,9 @@ function New-DeploymentReadme {
Write-Step "Creating deployment README..."
$componentDesc = switch ($ComponentType) {
"All" { "COMPLETE DEPLOYMENT PACKAGE (Reports + Telegram + Data Entry)" }
"Frontend" { "REPORTS FRONTEND + BACKEND DEPLOYMENT PACKAGE" }
"Backend" { "REPORTS BACKEND DEPLOYMENT PACKAGE" }
"TelegramBot" { "TELEGRAM BOT DEPLOYMENT PACKAGE" }
"DataEntryApp" { "DATA ENTRY APP DEPLOYMENT PACKAGE (Frontend + Backend)" }
"DataEntryBackend" { "DATA ENTRY BACKEND DEPLOYMENT PACKAGE" }
"All" { "COMPLETE DEPLOYMENT PACKAGE (Ultrathin Monolith - All Modules)" }
"Frontend" { "UNIFIED FRONTEND + BACKEND DEPLOYMENT PACKAGE" }
"Backend" { "UNIFIED BACKEND DEPLOYMENT PACKAGE (All Modules)" }
}
$readme = @"
@@ -915,68 +715,46 @@ function New-DeploymentReadme {
CONTENTS:
---------
"@
if ($ComponentType -eq "All" -or $ComponentType -eq "Frontend" -or $ComponentType -eq "Backend") {
$readme += @"
backend/ Unified FastAPI backend (port 8000)
|- modules/
| |- reports/ Reports module (Oracle)
| |- data_entry/ Data Entry module (SQLite)
| \- telegram/ Telegram bot module (background task)
\- main.py Single entry point (uvicorn)
backend/ Reports App - FastAPI backend (Python, port 8000)
frontend/ Reports App - Vue.js static files (production build)
shared/ Shared Python modules (auth, database, utils)
config/ Configuration templates (.env, web.config)
"@
}
frontend/ Unified Vue.js SPA (production build)
Single-page application with integrated modules
if ($ComponentType -eq "All" -or $ComponentType -eq "TelegramBot") {
$readme += @"
shared/ Shared Python modules
|- auth/ JWT authentication & middleware
|- database/ Oracle connection pool
\- routes/ Shared API routes (companies, calendar)
telegram-bot/ Telegram bot application (port 8002)
"@
}
if ($ComponentType -eq "All" -or $ComponentType -eq "DataEntryApp" -or $ComponentType -eq "DataEntryBackend") {
$readme += @"
data-entry-backend/ Data Entry App - FastAPI backend (Python, port 8003)
"@
}
if ($ComponentType -eq "All" -or $ComponentType -eq "DataEntryApp") {
$readme += @"
data-entry-frontend/ Data Entry App - Vue.js static files (production build)
"@
}
$readme += @"
config/ Configuration templates
\- web.config IIS configuration for unified backend
scripts/ PowerShell deployment scripts
MODULE CONTROL:
---------------
Enable/disable modules via environment variables in backend/.env:
MODULE_REPORTS_ENABLED=true # Reports module
MODULE_DATA_ENTRY_ENABLED=true # Data Entry module
MODULE_TELEGRAM_ENABLED=true # Telegram bot module
DEPLOYMENT SCRIPTS:
-------------------
ROA2WEB-Console.ps1 Unified deployment & management console
- Deploy components (Backend/Frontend/TelegramBot)
- Manage services (Start/Stop/Restart)
- Deploy components (Backend/Frontend)
- Manage single unified service
- Check system status and health
Install-ROA2WEB.ps1 First-time backend + frontend setup
Install-TelegramBot.ps1 First-time Telegram bot setup
"@
if ($ComponentType -eq "All" -or $ComponentType -eq "TelegramBot") {
$readme += @"
Backup-TelegramDB.ps1 Backup Telegram bot database
Setup-DailyBackup.ps1 Schedule automated backups
Setup-ClaudeAuth.ps1 Configure Claude API credentials
"@
}
if ($ComponentType -eq "All" -or $ComponentType -eq "Frontend") {
$readme += @"
Install-ROA2WEB.ps1 First-time installation (creates Windows service)
Enable-HTTPS.ps1 Configure HTTPS/SSL certificates
"@
}
$readme += @"
@@ -987,72 +765,50 @@ DEPLOYMENT WORKFLOW
>> FIRST TIME INSTALLATION:
---------------------------
"@
if ($ComponentType -eq "All" -or $ComponentType -eq "Frontend") {
$readme += @"
1. Install Main Application (Backend + Frontend):
1. Install Application (creates Windows service):
cd scripts
.\Install-ROA2WEB.ps1
2. Configure environment:
2. Configure environment (.env file):
notepad C:\inetpub\wwwroot\roa2web\backend\.env
3. Start services using the unified console:
IMPORTANT - Configure module flags:
MODULE_REPORTS_ENABLED=true # Enable/disable Reports module
MODULE_DATA_ENTRY_ENABLED=true # Enable/disable Data Entry module
MODULE_TELEGRAM_ENABLED=true # Enable/disable Telegram bot module
3. Start the unified backend service:
Start-Service ROA2WEB-Backend
OR using console:
.\ROA2WEB-Console.ps1
(Select: Manage Services > Start All)
"@
}
(Select: Manage Services > Start Service)
if ($ComponentType -eq "All" -or $ComponentType -eq "TelegramBot") {
$readme += @"
4. Verify installation:
- Backend API: http://localhost:8000/docs
- Health check: http://localhost:8000/health
- Frontend: http://localhost/ (via IIS)
4. Install Telegram Bot:
.\Install-TelegramBot.ps1
5. Configure Telegram bot:
notepad C:\inetpub\wwwroot\roa2web\telegram-bot\.env
6. Start Telegram bot:
.\ROA2WEB-Console.ps1
(Select: Manage Services > Start Telegram Bot)
"@
}
$readme += @"
>> UPDATES (Interactive Console):
>> UPDATES (Deploy New Version):
----------------------------------
cd scripts
.\ROA2WEB-Console.ps1
(Select: Deploy Components > choose what to update)
.\ROA2WEB-Console.ps1 -NonInteractive -Action DeployAll
(Stops service, updates files, restarts service)
>> UPDATES (Command Line):
---------------------------
.\ROA2WEB-Console.ps1 -NonInteractive -Action DeployBackend # Update backend + frontend
.\ROA2WEB-Console.ps1 -NonInteractive -Action DeployTelegramBot # Update Telegram bot
.\ROA2WEB-Console.ps1 -NonInteractive -Action DeployAll # Update everything
>> SERVICE MANAGEMENT:
-----------------------
# Start service
Start-Service ROA2WEB-Backend
>> SERVICE MANAGEMENT (Interactive):
-------------------------------------
.\ROA2WEB-Console.ps1
(Select: Manage Services > choose action)
# Stop service
Stop-Service ROA2WEB-Backend
>> SERVICE MANAGEMENT (Command Line):
--------------------------------------
# Start all services
.\ROA2WEB-Console.ps1 -NonInteractive -Action StartAll
# Stop all services
.\ROA2WEB-Console.ps1 -NonInteractive -Action StopAll
# Restart all services
.\ROA2WEB-Console.ps1 -NonInteractive -Action RestartAll
# Restart service
Restart-Service ROA2WEB-Backend
# Check status
Get-Service ROA2WEB-Backend
.\ROA2WEB-Console.ps1 -NonInteractive -Action Status
================================================================================
@@ -1070,12 +826,21 @@ NOTES:
- Automatic backup before each update
- Default install location: C:\inetpub\wwwroot\roa2web\
- Build cache NOT included in this package (stays on build machine)
- Single Windows service: ROA2WEB-Backend (manages all modules)
ARCHITECTURE:
-------------
ULTRATHIN MONOLITH: One backend process with multiple modules
- Modules controlled via .env flags (MODULE_*_ENABLED)
- All modules share: Oracle pool, auth, cache
- Telegram bot runs as background task (not separate service)
TROUBLESHOOTING:
----------------
Backend logs: C:\inetpub\wwwroot\roa2web\logs\
Telegram logs: C:\inetpub\wwwroot\roa2web\telegram-bot\logs\
Backend logs: C:\inetpub\wwwroot\roa2web\logs\backend-stdout.log
C:\inetpub\wwwroot\roa2web\logs\backend-stderr.log
IIS logs: C:\inetpub\logs\LogFiles\
Service status: Get-Service ROA2WEB-Backend
For detailed documentation, see: deployment/windows/docs/WINDOWS_DEPLOYMENT.md
@@ -1109,15 +874,15 @@ function New-DeploymentPackage {
# Build based on component type
switch ($ComponentType) {
"All" {
# Reports Frontend
# Unified Frontend (Vue.js SPA)
$frontendDistPath = Build-Frontend -SourcePath $Paths.FrontendSource -OutputPath $OutputPath
$frontendDest = Join-Path $OutputPath "frontend"
New-Item -ItemType Directory -Path $frontendDest -Force | Out-Null
Write-Step "Copying Reports frontend files..."
Write-Step "Copying Unified Frontend files (SPA)..."
Copy-Item -Path "$frontendDistPath\*" -Destination $frontendDest -Recurse -Force
Write-Success "Reports frontend files copied"
Write-Success "Unified Frontend files copied"
# Reports Backend
# Unified Backend (includes Reports, Data Entry, Telegram modules)
$backendDest = Join-Path $OutputPath "backend"
Copy-BackendFiles -SourcePath $Paths.BackendSource -DestPath $backendDest
@@ -1128,34 +893,18 @@ function New-DeploymentPackage {
# Config templates
$configDest = Join-Path $OutputPath "config"
Copy-ConfigTemplates -SourcePath $Paths.ConfigSource -DestPath $configDest
# Telegram Bot
$telegramDest = Join-Path $OutputPath "telegram-bot"
Copy-TelegramBotFiles -SourcePath $Paths.TelegramBotSource -DestPath $telegramDest
# Data Entry Frontend
$dataEntryFrontendDistPath = Build-Frontend -SourcePath $Paths.DataEntryFrontendSource -OutputPath $OutputPath
$dataEntryFrontendDest = Join-Path $OutputPath "data-entry-frontend"
New-Item -ItemType Directory -Path $dataEntryFrontendDest -Force | Out-Null
Write-Step "Copying Data Entry frontend files..."
Copy-Item -Path "$dataEntryFrontendDistPath\*" -Destination $dataEntryFrontendDest -Recurse -Force
Write-Success "Data Entry frontend files copied"
# Data Entry Backend
$dataEntryBackendDest = Join-Path $OutputPath "data-entry-backend"
Copy-DataEntryBackendFiles -SourcePath $Paths.DataEntryBackendSource -DestPath $dataEntryBackendDest
}
"Frontend" {
# Frontend build
# Unified Frontend build (Vue.js SPA)
$frontendDistPath = Build-Frontend -SourcePath $Paths.FrontendSource -OutputPath $OutputPath
$frontendDest = Join-Path $OutputPath "frontend"
New-Item -ItemType Directory -Path $frontendDest -Force | Out-Null
Write-Step "Copying frontend files..."
Write-Step "Copying Unified Frontend files (SPA)..."
Copy-Item -Path "$frontendDistPath\*" -Destination $frontendDest -Recurse -Force
Write-Success "Frontend files copied"
Write-Success "Unified Frontend files copied"
# Backend
# Unified Backend (includes all modules)
$backendDest = Join-Path $OutputPath "backend"
Copy-BackendFiles -SourcePath $Paths.BackendSource -DestPath $backendDest
@@ -1169,7 +918,7 @@ function New-DeploymentPackage {
}
"Backend" {
# Backend only
# Unified Backend only (includes Reports, Data Entry, Telegram modules)
$backendDest = Join-Path $OutputPath "backend"
Copy-BackendFiles -SourcePath $Paths.BackendSource -DestPath $backendDest
@@ -1181,52 +930,10 @@ function New-DeploymentPackage {
$configDest = Join-Path $OutputPath "config"
Copy-ConfigTemplates -SourcePath $Paths.ConfigSource -DestPath $configDest
}
"TelegramBot" {
# Telegram Bot only
$telegramDest = Join-Path $OutputPath "telegram-bot"
Copy-TelegramBotFiles -SourcePath $Paths.TelegramBotSource -DestPath $telegramDest
}
"DataEntryApp" {
# Data Entry Frontend build
$dataEntryFrontendDistPath = Build-Frontend -SourcePath $Paths.DataEntryFrontendSource -OutputPath $OutputPath
$dataEntryFrontendDest = Join-Path $OutputPath "data-entry-frontend"
New-Item -ItemType Directory -Path $dataEntryFrontendDest -Force | Out-Null
Write-Step "Copying Data Entry frontend files..."
Copy-Item -Path "$dataEntryFrontendDistPath\*" -Destination $dataEntryFrontendDest -Recurse -Force
Write-Success "Data Entry frontend files copied"
# Data Entry Backend
$dataEntryBackendDest = Join-Path $OutputPath "data-entry-backend"
Copy-DataEntryBackendFiles -SourcePath $Paths.DataEntryBackendSource -DestPath $dataEntryBackendDest
# Shared modules
$sharedDest = Join-Path $OutputPath "shared"
Copy-SharedModules -SourcePath $Paths.SharedSource -DestPath $sharedDest
# Config templates
$configDest = Join-Path $OutputPath "config"
Copy-ConfigTemplates -SourcePath $Paths.ConfigSource -DestPath $configDest
}
"DataEntryBackend" {
# Data Entry Backend only
$dataEntryBackendDest = Join-Path $OutputPath "data-entry-backend"
Copy-DataEntryBackendFiles -SourcePath $Paths.DataEntryBackendSource -DestPath $dataEntryBackendDest
# Shared modules
$sharedDest = Join-Path $OutputPath "shared"
Copy-SharedModules -SourcePath $Paths.SharedSource -DestPath $sharedDest
# Config templates
$configDest = Join-Path $OutputPath "config"
Copy-ConfigTemplates -SourcePath $Paths.ConfigSource -DestPath $configDest
}
}
# Cleanup temporary directories
if ($ComponentType -eq "All" -or $ComponentType -eq "Frontend" -or $ComponentType -eq "DataEntryApp") {
if ($ComponentType -eq "All" -or $ComponentType -eq "Frontend") {
Remove-TempDirectories -OutputPath $OutputPath
}
@@ -1276,14 +983,9 @@ function Main {
try {
# Resolve paths
$paths = @{
# Reports App sources
# Ultrathin Monolith sources
BackendSource = Resolve-FullPath -Path $config.BackendSource
FrontendSource = Resolve-FullPath -Path $config.FrontendSource
TelegramBotSource = Resolve-FullPath -Path $config.TelegramBotSource
# Data Entry App sources
DataEntryBackendSource = Resolve-FullPath -Path $config.DataEntryBackendSource
DataEntryFrontendSource = Resolve-FullPath -Path $config.DataEntryFrontendSource
# Shared sources
SharedSource = Resolve-FullPath -Path $config.SharedSource
ConfigSource = Resolve-FullPath -Path $config.ConfigSource
}