feat: Improve Windows deployment and fix production paths
Data Entry App: - Fix shared path finding for both dev and production environments - Add base URL support for IIS subdirectory deployment (/data-entry/) - Use import.meta.env.BASE_URL in router for correct path handling - Add email-validator and python-jose dependencies Deployment Scripts: - Enhance Build-ROA2WEB.ps1 with improved build process - Update ROA2WEB-Console.ps1 with Data Entry support - Improve Publish-And-Deploy.ps1 deployment workflow - Update deploy-config.json with new settings Gitignore: - Add more build cache patterns to ignore - Add temp frontend build directories 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
9
.gitignore
vendored
9
.gitignore
vendored
@@ -356,8 +356,17 @@ deploy-package/
|
|||||||
|
|
||||||
# Build cache (npm node_modules cache for faster builds)
|
# Build cache (npm node_modules cache for faster builds)
|
||||||
deployment/windows/.build-cache/
|
deployment/windows/.build-cache/
|
||||||
|
deployment/windows/.build-cache-*/
|
||||||
.build-cache/
|
.build-cache/
|
||||||
|
.build-cache-*/
|
||||||
**/.build-cache/
|
**/.build-cache/
|
||||||
|
**/.build-cache-*/
|
||||||
|
|
||||||
|
# Shared folder copied during build (temporary)
|
||||||
|
deployment/shared/
|
||||||
|
|
||||||
|
# Temp frontend build directories
|
||||||
|
**/.temp-frontend-build/
|
||||||
|
|
||||||
# Deployment logs and temporary files
|
# Deployment logs and temporary files
|
||||||
deployment/windows/scripts/*.log
|
deployment/windows/scripts/*.log
|
||||||
|
|||||||
@@ -22,8 +22,26 @@ from fastapi.middleware.cors import CORSMiddleware
|
|||||||
from fastapi.staticfiles import StaticFiles
|
from fastapi.staticfiles import StaticFiles
|
||||||
|
|
||||||
# Add shared modules to path
|
# Add shared modules to path
|
||||||
project_root = Path(__file__).parent.parent.parent.parent
|
# Development: data-entry-app/backend/app/main.py -> 4 parents to project root
|
||||||
sys.path.insert(0, str(project_root / "shared"))
|
# Production: data-entry-backend/app/main.py -> 3 parents to roa2web root
|
||||||
|
def find_shared_path():
|
||||||
|
"""Find shared folder - works in both dev and production."""
|
||||||
|
current = Path(__file__).parent # app/
|
||||||
|
|
||||||
|
# Try different parent levels to find shared folder
|
||||||
|
for levels in range(1, 6):
|
||||||
|
candidate = current
|
||||||
|
for _ in range(levels):
|
||||||
|
candidate = candidate.parent
|
||||||
|
shared_path = candidate / "shared"
|
||||||
|
if shared_path.exists() and (shared_path / "auth").exists():
|
||||||
|
return shared_path
|
||||||
|
|
||||||
|
# Fallback to original logic
|
||||||
|
return Path(__file__).parent.parent.parent.parent / "shared"
|
||||||
|
|
||||||
|
shared_path = find_shared_path()
|
||||||
|
sys.path.insert(0, str(shared_path))
|
||||||
|
|
||||||
from app.config import settings
|
from app.config import settings
|
||||||
from app.db.database import init_db
|
from app.db.database import init_db
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ alembic>=1.13.1
|
|||||||
# Pydantic
|
# Pydantic
|
||||||
pydantic>=2.5.3
|
pydantic>=2.5.3
|
||||||
pydantic-settings>=2.1.0
|
pydantic-settings>=2.1.0
|
||||||
|
email-validator>=2.1.0
|
||||||
|
|
||||||
# File handling
|
# File handling
|
||||||
python-multipart>=0.0.6
|
python-multipart>=0.0.6
|
||||||
@@ -19,6 +20,7 @@ Pillow>=10.2.0
|
|||||||
|
|
||||||
# Authentication (shared)
|
# Authentication (shared)
|
||||||
PyJWT>=2.8.0
|
PyJWT>=2.8.0
|
||||||
|
python-jose[cryptography]>=3.3.0
|
||||||
|
|
||||||
# Oracle (for nomenclatures)
|
# Oracle (for nomenclatures)
|
||||||
oracledb>=2.0.1
|
oracledb>=2.0.1
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ const routes = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHistory(),
|
history: createWebHistory(import.meta.env.BASE_URL),
|
||||||
routes
|
routes
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import { fileURLToPath, URL } from 'node:url'
|
|||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [vue()],
|
plugins: [vue()],
|
||||||
|
// Base path for production deployment in IIS subdirectory
|
||||||
|
base: process.env.NODE_ENV === 'production' ? '/data-entry/' : '/',
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
'@': fileURLToPath(new URL('./src', import.meta.url)),
|
'@': fileURLToPath(new URL('./src', import.meta.url)),
|
||||||
|
|||||||
@@ -68,7 +68,7 @@
|
|||||||
|
|
||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
param(
|
param(
|
||||||
[ValidateSet("All", "Frontend", "Backend", "TelegramBot")]
|
[ValidateSet("All", "Frontend", "Backend", "TelegramBot", "DataEntryApp", "DataEntryBackend")]
|
||||||
[string]$Component = "",
|
[string]$Component = "",
|
||||||
|
|
||||||
[string]$OutputPath = "./deploy-package",
|
[string]$OutputPath = "./deploy-package",
|
||||||
@@ -85,9 +85,14 @@ $ErrorActionPreference = "Stop"
|
|||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
$config = @{
|
$config = @{
|
||||||
|
# Reports App sources
|
||||||
BackendSource = "../../reports-app/backend"
|
BackendSource = "../../reports-app/backend"
|
||||||
FrontendSource = "../../reports-app/frontend"
|
FrontendSource = "../../reports-app/frontend"
|
||||||
TelegramBotSource = "../../reports-app/telegram-bot"
|
TelegramBotSource = "../../reports-app/telegram-bot"
|
||||||
|
# Data Entry App sources
|
||||||
|
DataEntryBackendSource = "../../data-entry-app/backend"
|
||||||
|
DataEntryFrontendSource = "../../data-entry-app/frontend"
|
||||||
|
# Shared sources
|
||||||
SharedSource = "../../shared"
|
SharedSource = "../../shared"
|
||||||
ConfigSource = "../config"
|
ConfigSource = "../config"
|
||||||
RequiredNodeVersion = 16
|
RequiredNodeVersion = 16
|
||||||
@@ -175,17 +180,25 @@ function Show-BuildMenu {
|
|||||||
Write-Host " Select components to build:" -ForegroundColor Yellow
|
Write-Host " Select components to build:" -ForegroundColor Yellow
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host " [1] All Components" -ForegroundColor White
|
Write-Host " [1] All Components" -ForegroundColor White
|
||||||
Write-Host " (Frontend + Backend + Telegram Bot)" -ForegroundColor Gray
|
Write-Host " (Reports App + Telegram Bot + Data Entry App)" -ForegroundColor Gray
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host " [2] Frontend + Backend" -ForegroundColor White
|
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 " (Vue.js build + FastAPI backend files)" -ForegroundColor Gray
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host " [3] Backend Only" -ForegroundColor White
|
Write-Host " [3] Reports Backend Only" -ForegroundColor White
|
||||||
Write-Host " (FastAPI backend files + shared modules)" -ForegroundColor Gray
|
Write-Host " (FastAPI backend files + shared modules)" -ForegroundColor Gray
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host " [4] Telegram Bot Only" -ForegroundColor White
|
Write-Host " [4] Telegram Bot Only" -ForegroundColor White
|
||||||
Write-Host " (Telegram bot standalone package)" -ForegroundColor Gray
|
Write-Host " (Telegram bot standalone package)" -ForegroundColor Gray
|
||||||
Write-Host ""
|
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 ""
|
||||||
Write-Host " [C] Clean Build Cache" -ForegroundColor Yellow
|
Write-Host " [C] Clean Build Cache" -ForegroundColor Yellow
|
||||||
Write-Host " (Remove cached node_modules to free disk space)" -ForegroundColor Gray
|
Write-Host " (Remove cached node_modules to free disk space)" -ForegroundColor Gray
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
@@ -202,6 +215,8 @@ function Show-BuildMenu {
|
|||||||
"2" { return "Frontend" }
|
"2" { return "Frontend" }
|
||||||
"3" { return "Backend" }
|
"3" { return "Backend" }
|
||||||
"4" { return "TelegramBot" }
|
"4" { return "TelegramBot" }
|
||||||
|
"5" { return "DataEntryApp" }
|
||||||
|
"6" { return "DataEntryBackend" }
|
||||||
"C" {
|
"C" {
|
||||||
Clear-BuildCache
|
Clear-BuildCache
|
||||||
Write-Host "`nPress any key to return to menu..." -ForegroundColor Gray
|
Write-Host "`nPress any key to return to menu..." -ForegroundColor Gray
|
||||||
@@ -213,7 +228,7 @@ function Show-BuildMenu {
|
|||||||
exit 0
|
exit 0
|
||||||
}
|
}
|
||||||
default {
|
default {
|
||||||
Write-Host "Invalid choice. Please select 1-4, C or Q." -ForegroundColor Red
|
Write-Host "Invalid choice. Please select 1-6, C or Q." -ForegroundColor Red
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while ($true)
|
} while ($true)
|
||||||
@@ -258,18 +273,28 @@ function Build-Frontend {
|
|||||||
throw "Frontend source path not found: $SourcePath"
|
throw "Frontend source path not found: $SourcePath"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Create temporary build directory
|
# Determine if this is reports-app or data-entry-app based on source path
|
||||||
$tempBuildDir = Join-Path $OutputPath ".temp-frontend-build"
|
$appFolder = Split-Path (Split-Path $SourcePath -Parent) -Leaf # "reports-app" or "data-entry-app"
|
||||||
if (Test-Path $tempBuildDir) {
|
|
||||||
|
# Create temporary build directory with full project structure
|
||||||
|
# Structure:
|
||||||
|
# .temp-frontend-build/
|
||||||
|
# ├── reports-app/frontend/ (or data-entry-app/frontend/)
|
||||||
|
# └── shared/
|
||||||
|
$tempRootDir = Join-Path $OutputPath ".temp-frontend-build"
|
||||||
|
if (Test-Path $tempRootDir) {
|
||||||
Write-Step "Cleaning existing temp build directory..."
|
Write-Step "Cleaning existing temp build directory..."
|
||||||
Remove-Item -Path $tempBuildDir -Recurse -Force
|
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
|
New-Item -ItemType Directory -Path $tempBuildDir -Force | Out-Null
|
||||||
Write-Success "Created temp build directory (isolated from WSL)"
|
Write-Success "Created temp build directory (isolated from WSL)"
|
||||||
|
|
||||||
# Create cache directory for node_modules (OUTSIDE deploy-package)
|
# Create cache directory for node_modules (OUTSIDE deploy-package)
|
||||||
$scriptDir = Split-Path -Parent $PSScriptRoot
|
$scriptDir = Split-Path -Parent $PSScriptRoot
|
||||||
$cacheDir = Join-Path $scriptDir ".build-cache"
|
$cacheDir = Join-Path $scriptDir ".build-cache-$appFolder"
|
||||||
if (-not (Test-Path $cacheDir)) {
|
if (-not (Test-Path $cacheDir)) {
|
||||||
New-Item -ItemType Directory -Path $cacheDir -Force | Out-Null
|
New-Item -ItemType Directory -Path $cacheDir -Force | Out-Null
|
||||||
}
|
}
|
||||||
@@ -318,7 +343,30 @@ function Build-Frontend {
|
|||||||
}
|
}
|
||||||
Write-Success "Frontend sources copied to temp"
|
Write-Success "Frontend sources copied to temp"
|
||||||
|
|
||||||
# Build in temp directory
|
# 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
|
||||||
|
$sharedSourcePath = Join-Path $projectRoot "shared"
|
||||||
|
|
||||||
|
if (Test-Path $sharedSourcePath) {
|
||||||
|
$sharedDestPath = Join-Path $tempRootDir "shared"
|
||||||
|
|
||||||
|
Write-Step "Copying shared components for build..."
|
||||||
|
Write-Info "Source: $sharedSourcePath"
|
||||||
|
Write-Info "Dest: $sharedDestPath"
|
||||||
|
|
||||||
|
# Remove existing shared folder in dest if exists
|
||||||
|
if (Test-Path $sharedDestPath) {
|
||||||
|
Remove-Item -Path $sharedDestPath -Recurse -Force
|
||||||
|
}
|
||||||
|
|
||||||
|
Copy-Item -Path $sharedSourcePath -Destination $sharedDestPath -Recurse -Force -Exclude @("__pycache__", "*.pyc", "tests")
|
||||||
|
Write-Success "Shared components copied for relative imports"
|
||||||
|
} else {
|
||||||
|
Write-Warning "Shared folder not found at: $sharedSourcePath"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Build in temp directory (now at tempRootDir/appFolder/frontend)
|
||||||
Push-Location $tempBuildDir
|
Push-Location $tempBuildDir
|
||||||
try {
|
try {
|
||||||
# Check if dependencies need to be reinstalled
|
# Check if dependencies need to be reinstalled
|
||||||
@@ -386,6 +434,24 @@ function Build-Frontend {
|
|||||||
throw "Vite not found in node_modules - devDependencies not installed"
|
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)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# Build for production
|
# Build for production
|
||||||
Write-Step "Building for production..."
|
Write-Step "Building for production..."
|
||||||
$env:NODE_ENV = "production"
|
$env:NODE_ENV = "production"
|
||||||
@@ -596,6 +662,112 @@ function Copy-TelegramBotFiles {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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"
|
||||||
|
}
|
||||||
|
|
||||||
function Copy-SharedModules {
|
function Copy-SharedModules {
|
||||||
param(
|
param(
|
||||||
[string]$SourcePath,
|
[string]$SourcePath,
|
||||||
@@ -726,10 +898,12 @@ function New-DeploymentReadme {
|
|||||||
Write-Step "Creating deployment README..."
|
Write-Step "Creating deployment README..."
|
||||||
|
|
||||||
$componentDesc = switch ($ComponentType) {
|
$componentDesc = switch ($ComponentType) {
|
||||||
"All" { "COMPLETE DEPLOYMENT PACKAGE (Frontend + Backend + Telegram Bot)" }
|
"All" { "COMPLETE DEPLOYMENT PACKAGE (Reports + Telegram + Data Entry)" }
|
||||||
"Frontend" { "FRONTEND + BACKEND DEPLOYMENT PACKAGE" }
|
"Frontend" { "REPORTS FRONTEND + BACKEND DEPLOYMENT PACKAGE" }
|
||||||
"Backend" { "BACKEND DEPLOYMENT PACKAGE" }
|
"Backend" { "REPORTS BACKEND DEPLOYMENT PACKAGE" }
|
||||||
"TelegramBot" { "TELEGRAM BOT DEPLOYMENT PACKAGE" }
|
"TelegramBot" { "TELEGRAM BOT DEPLOYMENT PACKAGE" }
|
||||||
|
"DataEntryApp" { "DATA ENTRY APP DEPLOYMENT PACKAGE (Frontend + Backend)" }
|
||||||
|
"DataEntryBackend" { "DATA ENTRY BACKEND DEPLOYMENT PACKAGE" }
|
||||||
}
|
}
|
||||||
|
|
||||||
$readme = @"
|
$readme = @"
|
||||||
@@ -743,11 +917,11 @@ CONTENTS:
|
|||||||
---------
|
---------
|
||||||
"@
|
"@
|
||||||
|
|
||||||
if ($ComponentType -eq "All" -or $ComponentType -eq "Frontend") {
|
if ($ComponentType -eq "All" -or $ComponentType -eq "Frontend" -or $ComponentType -eq "Backend") {
|
||||||
$readme += @"
|
$readme += @"
|
||||||
|
|
||||||
backend/ FastAPI backend application (Python)
|
backend/ Reports App - FastAPI backend (Python, port 8000)
|
||||||
frontend/ Vue.js static files (production build)
|
frontend/ Reports App - Vue.js static files (production build)
|
||||||
shared/ Shared Python modules (auth, database, utils)
|
shared/ Shared Python modules (auth, database, utils)
|
||||||
config/ Configuration templates (.env, web.config)
|
config/ Configuration templates (.env, web.config)
|
||||||
"@
|
"@
|
||||||
@@ -756,7 +930,20 @@ CONTENTS:
|
|||||||
if ($ComponentType -eq "All" -or $ComponentType -eq "TelegramBot") {
|
if ($ComponentType -eq "All" -or $ComponentType -eq "TelegramBot") {
|
||||||
$readme += @"
|
$readme += @"
|
||||||
|
|
||||||
telegram-bot/ Telegram bot application
|
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)
|
||||||
"@
|
"@
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -922,15 +1109,15 @@ function New-DeploymentPackage {
|
|||||||
# Build based on component type
|
# Build based on component type
|
||||||
switch ($ComponentType) {
|
switch ($ComponentType) {
|
||||||
"All" {
|
"All" {
|
||||||
# Frontend
|
# Reports Frontend
|
||||||
$frontendDistPath = Build-Frontend -SourcePath $Paths.FrontendSource -OutputPath $OutputPath
|
$frontendDistPath = Build-Frontend -SourcePath $Paths.FrontendSource -OutputPath $OutputPath
|
||||||
$frontendDest = Join-Path $OutputPath "frontend"
|
$frontendDest = Join-Path $OutputPath "frontend"
|
||||||
New-Item -ItemType Directory -Path $frontendDest -Force | Out-Null
|
New-Item -ItemType Directory -Path $frontendDest -Force | Out-Null
|
||||||
Write-Step "Copying frontend files..."
|
Write-Step "Copying Reports frontend files..."
|
||||||
Copy-Item -Path "$frontendDistPath\*" -Destination $frontendDest -Recurse -Force
|
Copy-Item -Path "$frontendDistPath\*" -Destination $frontendDest -Recurse -Force
|
||||||
Write-Success "Frontend files copied"
|
Write-Success "Reports frontend files copied"
|
||||||
|
|
||||||
# Backend
|
# Reports Backend
|
||||||
$backendDest = Join-Path $OutputPath "backend"
|
$backendDest = Join-Path $OutputPath "backend"
|
||||||
Copy-BackendFiles -SourcePath $Paths.BackendSource -DestPath $backendDest
|
Copy-BackendFiles -SourcePath $Paths.BackendSource -DestPath $backendDest
|
||||||
|
|
||||||
@@ -945,6 +1132,18 @@ function New-DeploymentPackage {
|
|||||||
# Telegram Bot
|
# Telegram Bot
|
||||||
$telegramDest = Join-Path $OutputPath "telegram-bot"
|
$telegramDest = Join-Path $OutputPath "telegram-bot"
|
||||||
Copy-TelegramBotFiles -SourcePath $Paths.TelegramBotSource -DestPath $telegramDest
|
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" {
|
||||||
@@ -988,10 +1187,46 @@ function New-DeploymentPackage {
|
|||||||
$telegramDest = Join-Path $OutputPath "telegram-bot"
|
$telegramDest = Join-Path $OutputPath "telegram-bot"
|
||||||
Copy-TelegramBotFiles -SourcePath $Paths.TelegramBotSource -DestPath $telegramDest
|
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
|
# Cleanup temporary directories
|
||||||
if ($ComponentType -eq "All" -or $ComponentType -eq "Frontend") {
|
if ($ComponentType -eq "All" -or $ComponentType -eq "Frontend" -or $ComponentType -eq "DataEntryApp") {
|
||||||
Remove-TempDirectories -OutputPath $OutputPath
|
Remove-TempDirectories -OutputPath $OutputPath
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1041,9 +1276,14 @@ function Main {
|
|||||||
try {
|
try {
|
||||||
# Resolve paths
|
# Resolve paths
|
||||||
$paths = @{
|
$paths = @{
|
||||||
|
# Reports App sources
|
||||||
BackendSource = Resolve-FullPath -Path $config.BackendSource
|
BackendSource = Resolve-FullPath -Path $config.BackendSource
|
||||||
FrontendSource = Resolve-FullPath -Path $config.FrontendSource
|
FrontendSource = Resolve-FullPath -Path $config.FrontendSource
|
||||||
TelegramBotSource = Resolve-FullPath -Path $config.TelegramBotSource
|
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
|
SharedSource = Resolve-FullPath -Path $config.SharedSource
|
||||||
ConfigSource = Resolve-FullPath -Path $config.ConfigSource
|
ConfigSource = Resolve-FullPath -Path $config.ConfigSource
|
||||||
}
|
}
|
||||||
@@ -1055,7 +1295,7 @@ function Main {
|
|||||||
Write-Host " Output Path: $outputFullPath"
|
Write-Host " Output Path: $outputFullPath"
|
||||||
|
|
||||||
# Validate Node.js for frontend builds
|
# Validate Node.js for frontend builds
|
||||||
if ($Component -eq "All" -or $Component -eq "Frontend") {
|
if ($Component -eq "All" -or $Component -eq "Frontend" -or $Component -eq "DataEntryApp") {
|
||||||
Test-NodeJS
|
Test-NodeJS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -315,6 +315,7 @@ function Invoke-Deployment {
|
|||||||
Services = @{
|
Services = @{
|
||||||
backend = "Running"
|
backend = "Running"
|
||||||
telegramBot = "Running"
|
telegramBot = "Running"
|
||||||
|
dataEntry = "Running"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
- ViewConfig: Display current configuration
|
- ViewConfig: Display current configuration
|
||||||
|
|
||||||
.PARAMETER Component
|
.PARAMETER Component
|
||||||
Component to build (All, Frontend, Backend, TelegramBot)
|
Component to build (All, Frontend, Backend, TelegramBot, DataEntryApp, DataEntryBackend)
|
||||||
|
|
||||||
.PARAMETER TransferMethod
|
.PARAMETER TransferMethod
|
||||||
Transfer method (Auto, WindowsShare, SSH)
|
Transfer method (Auto, WindowsShare, SSH)
|
||||||
@@ -41,9 +41,13 @@
|
|||||||
.\Publish-And-Deploy.ps1 -NonInteractive -Action Build -Component Frontend -TransferMethod SSH
|
.\Publish-And-Deploy.ps1 -NonInteractive -Action Build -Component Frontend -TransferMethod SSH
|
||||||
Build frontend and publish via SSH
|
Build frontend and publish via SSH
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
.\Publish-And-Deploy.ps1 -NonInteractive -Action Build -Component DataEntryApp
|
||||||
|
Build Data Entry App (frontend + backend) and publish
|
||||||
|
|
||||||
.NOTES
|
.NOTES
|
||||||
Author: ROA2WEB Team
|
Author: ROA2WEB Team
|
||||||
Version: 1.0 (Interactive Build & Publish)
|
Version: 1.1 (Added Data Entry App support)
|
||||||
Requires: PowerShell 5.1+, SSH key configured for remote access
|
Requires: PowerShell 5.1+, SSH key configured for remote access
|
||||||
#>
|
#>
|
||||||
|
|
||||||
@@ -54,7 +58,7 @@ param(
|
|||||||
[ValidateSet("Build", "TestConnections", "ViewConfig")]
|
[ValidateSet("Build", "TestConnections", "ViewConfig")]
|
||||||
[string]$Action = "",
|
[string]$Action = "",
|
||||||
|
|
||||||
[ValidateSet("All", "Frontend", "Backend", "TelegramBot")]
|
[ValidateSet("All", "Frontend", "Backend", "TelegramBot", "DataEntryApp", "DataEntryBackend")]
|
||||||
[string]$Component = "",
|
[string]$Component = "",
|
||||||
|
|
||||||
[ValidateSet("Auto", "WindowsShare", "SSH")]
|
[ValidateSet("Auto", "WindowsShare", "SSH")]
|
||||||
@@ -295,7 +299,7 @@ function Test-AllConnections {
|
|||||||
function Invoke-Build {
|
function Invoke-Build {
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory)]
|
[Parameter(Mandatory)]
|
||||||
[ValidateSet("All", "Frontend", "Backend", "TelegramBot")]
|
[ValidateSet("All", "Frontend", "Backend", "TelegramBot", "DataEntryApp", "DataEntryBackend")]
|
||||||
[string]$Component
|
[string]$Component
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -554,7 +558,8 @@ function Edit-Configuration {
|
|||||||
}
|
}
|
||||||
"4" {
|
"4" {
|
||||||
Write-Host "`nEdit Build Settings:" -ForegroundColor Yellow
|
Write-Host "`nEdit Build Settings:" -ForegroundColor Yellow
|
||||||
Write-Host "Default Component (All/Frontend/Backend/TelegramBot) [current: $($script:Config.build.defaultComponent)]: " -NoNewline
|
Write-Host "Default Component (All/Frontend/Backend/TelegramBot/DataEntryApp/DataEntryBackend)" -ForegroundColor Gray
|
||||||
|
Write-Host "[current: $($script:Config.build.defaultComponent)]: " -NoNewline
|
||||||
$newComp = Read-Host
|
$newComp = Read-Host
|
||||||
if ($newComp) { $script:Config.build.defaultComponent = $newComp }
|
if ($newComp) { $script:Config.build.defaultComponent = $newComp }
|
||||||
|
|
||||||
@@ -658,17 +663,25 @@ function Show-ComponentMenu {
|
|||||||
Write-Host ("=" * 70) -ForegroundColor Cyan
|
Write-Host ("=" * 70) -ForegroundColor Cyan
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host " [1] All Components" -ForegroundColor White
|
Write-Host " [1] All Components" -ForegroundColor White
|
||||||
Write-Host " (Frontend + Backend + Telegram Bot)" -ForegroundColor Gray
|
Write-Host " (Reports + Telegram Bot + Data Entry)" -ForegroundColor Gray
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host " [2] Frontend + Backend" -ForegroundColor White
|
Write-Host " --- Reports App ---" -ForegroundColor Cyan
|
||||||
|
Write-Host " [2] Reports Frontend + Backend" -ForegroundColor White
|
||||||
Write-Host " (Vue.js build + FastAPI backend)" -ForegroundColor Gray
|
Write-Host " (Vue.js build + FastAPI backend)" -ForegroundColor Gray
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host " [3] Backend Only" -ForegroundColor White
|
Write-Host " [3] Reports Backend Only" -ForegroundColor White
|
||||||
Write-Host " (FastAPI backend + shared modules)" -ForegroundColor Gray
|
Write-Host " (FastAPI backend + shared modules)" -ForegroundColor Gray
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host " [4] Telegram Bot Only" -ForegroundColor White
|
Write-Host " [4] Telegram Bot Only" -ForegroundColor White
|
||||||
Write-Host " (Telegram bot standalone package)" -ForegroundColor Gray
|
Write-Host " (Telegram bot standalone package)" -ForegroundColor Gray
|
||||||
Write-Host ""
|
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)" -ForegroundColor Gray
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host " [6] Data Entry Backend Only" -ForegroundColor White
|
||||||
|
Write-Host " (FastAPI backend only)" -ForegroundColor Gray
|
||||||
|
Write-Host ""
|
||||||
Write-Host " [B] Back to Main Menu" -ForegroundColor Yellow
|
Write-Host " [B] Back to Main Menu" -ForegroundColor Yellow
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host ("=" * 70) -ForegroundColor Cyan
|
Write-Host ("=" * 70) -ForegroundColor Cyan
|
||||||
@@ -682,9 +695,11 @@ function Show-ComponentMenu {
|
|||||||
"2" { return "Frontend" }
|
"2" { return "Frontend" }
|
||||||
"3" { return "Backend" }
|
"3" { return "Backend" }
|
||||||
"4" { return "TelegramBot" }
|
"4" { return "TelegramBot" }
|
||||||
|
"5" { return "DataEntryApp" }
|
||||||
|
"6" { return "DataEntryBackend" }
|
||||||
"B" { return "Back" }
|
"B" { return "Back" }
|
||||||
default {
|
default {
|
||||||
Write-Host "Invalid choice. Please select 1-4 or B." -ForegroundColor Red
|
Write-Host "Invalid choice. Please select 1-6 or B." -ForegroundColor Red
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while ($true)
|
} while ($true)
|
||||||
|
|||||||
@@ -42,8 +42,9 @@
|
|||||||
param(
|
param(
|
||||||
[switch]$NonInteractive,
|
[switch]$NonInteractive,
|
||||||
|
|
||||||
[ValidateSet("DeployBackend", "DeployTelegramBot", "DeployAll",
|
[ValidateSet("DeployBackend", "DeployTelegramBot", "DeployDataEntry", "DeployAll",
|
||||||
"StartAll", "StopAll", "RestartAll", "Status")]
|
"StartAll", "StopAll", "RestartAll",
|
||||||
|
"StartDataEntry", "StopDataEntry", "RestartDataEntry", "Status")]
|
||||||
[string]$Action = ""
|
[string]$Action = ""
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -72,16 +73,16 @@ $script:Config = @{
|
|||||||
SourcePath = $detectedSourcePath
|
SourcePath = $detectedSourcePath
|
||||||
BackupPath = "C:\inetpub\wwwroot\roa2web\backups"
|
BackupPath = "C:\inetpub\wwwroot\roa2web\backups"
|
||||||
|
|
||||||
# Backend
|
# Reports Backend
|
||||||
BackendPath = "C:\inetpub\wwwroot\roa2web\backend"
|
BackendPath = "C:\inetpub\wwwroot\roa2web\backend"
|
||||||
BackendServiceName = "ROA2WEB-Backend"
|
BackendServiceName = "ROA2WEB-Backend"
|
||||||
BackendServiceDisplayName = "ROA2WEB Backend API"
|
BackendServiceDisplayName = "ROA2WEB Backend API"
|
||||||
BackendServiceDescription = "FastAPI backend service for ROA2WEB application"
|
BackendServiceDescription = "FastAPI backend service for ROA2WEB Reports application"
|
||||||
BackendPort = 8000
|
BackendPort = 8000
|
||||||
BackendHealthUrl = "http://localhost:8000/health"
|
BackendHealthUrl = "http://localhost:8000/health"
|
||||||
BackendHealthTimeout = 5
|
BackendHealthTimeout = 5
|
||||||
|
|
||||||
# Frontend
|
# Reports Frontend
|
||||||
FrontendPath = "C:\inetpub\wwwroot\roa2web\frontend"
|
FrontendPath = "C:\inetpub\wwwroot\roa2web\frontend"
|
||||||
|
|
||||||
# IIS Configuration
|
# IIS Configuration
|
||||||
@@ -98,9 +99,24 @@ $script:Config = @{
|
|||||||
TelegramBotHealthUrl = "http://localhost:8002/internal/health"
|
TelegramBotHealthUrl = "http://localhost:8002/internal/health"
|
||||||
TelegramBotHealthTimeout = 10
|
TelegramBotHealthTimeout = 10
|
||||||
|
|
||||||
|
# Data Entry Backend
|
||||||
|
DataEntryBackendPath = "C:\inetpub\wwwroot\roa2web\data-entry-backend"
|
||||||
|
DataEntryServiceName = "ROA2WEB-DataEntry"
|
||||||
|
DataEntryServiceDisplayName = "ROA2WEB Data Entry API"
|
||||||
|
DataEntryServiceDescription = "FastAPI backend service for ROA2WEB Data Entry application"
|
||||||
|
DataEntryPort = 8003
|
||||||
|
DataEntryHealthUrl = "http://localhost:8003/health"
|
||||||
|
DataEntryHealthTimeout = 5
|
||||||
|
|
||||||
|
# Data Entry Frontend
|
||||||
|
DataEntryFrontendPath = "C:\inetpub\wwwroot\roa2web\data-entry-frontend"
|
||||||
|
DataEntryIISAppName = "data-entry"
|
||||||
|
DataEntryAppPoolName = "DataEntry-AppPool"
|
||||||
|
|
||||||
# Logs
|
# Logs
|
||||||
LogsPath = "C:\inetpub\wwwroot\roa2web\logs"
|
LogsPath = "C:\inetpub\wwwroot\roa2web\logs"
|
||||||
TelegramBotLogsPath = "C:\inetpub\wwwroot\roa2web\telegram-bot\logs"
|
TelegramBotLogsPath = "C:\inetpub\wwwroot\roa2web\telegram-bot\logs"
|
||||||
|
DataEntryLogsPath = "C:\inetpub\wwwroot\roa2web\data-entry-backend\logs"
|
||||||
|
|
||||||
# Timeouts
|
# Timeouts
|
||||||
ServiceTimeout = 30
|
ServiceTimeout = 30
|
||||||
@@ -208,6 +224,36 @@ function Test-TelegramBotInstalled {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Test-DataEntryInstalled {
|
||||||
|
Write-Step "Checking if Data Entry is installed..."
|
||||||
|
|
||||||
|
$venvPath = Join-Path $Config.DataEntryBackendPath "venv"
|
||||||
|
$venvExists = Test-Path $venvPath
|
||||||
|
$service = Get-ServiceSafe -ServiceName $Config.DataEntryServiceName
|
||||||
|
$serviceExists = $null -ne $service
|
||||||
|
|
||||||
|
$appPath = Join-Path $Config.DataEntryBackendPath "app"
|
||||||
|
$hasApp = Test-Path $appPath
|
||||||
|
|
||||||
|
$requirementsPath = Join-Path $Config.DataEntryBackendPath "requirements.txt"
|
||||||
|
$hasRequirements = Test-Path $requirementsPath
|
||||||
|
|
||||||
|
if ($venvExists -and $serviceExists -and $hasApp -and $hasRequirements) {
|
||||||
|
Write-Success "Data Entry is installed (venv + service exist)"
|
||||||
|
return $true
|
||||||
|
} else {
|
||||||
|
Write-Warning "Data Entry NOT installed (missing: $(
|
||||||
|
@(
|
||||||
|
if (-not $venvExists) { 'venv' }
|
||||||
|
if (-not $serviceExists) { 'service' }
|
||||||
|
if (-not $hasApp) { 'app files' }
|
||||||
|
if (-not $hasRequirements) { 'requirements.txt' }
|
||||||
|
) -join ', '
|
||||||
|
))"
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function Get-ServiceSafe {
|
function Get-ServiceSafe {
|
||||||
param([string]$ServiceName)
|
param([string]$ServiceName)
|
||||||
try {
|
try {
|
||||||
@@ -859,6 +905,256 @@ function Install-TelegramBotFirstTime {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Install-DataEntryFirstTime {
|
||||||
|
Write-Host "`n" + ("=" * 70) -ForegroundColor Yellow
|
||||||
|
Write-Host " FIRST-TIME INSTALLATION: DATA ENTRY APP" -ForegroundColor Yellow
|
||||||
|
Write-Host ("=" * 70) -ForegroundColor Yellow
|
||||||
|
|
||||||
|
try {
|
||||||
|
# Install prerequisites
|
||||||
|
Write-Step "Installing prerequisites..."
|
||||||
|
Install-Chocolatey | Out-Null
|
||||||
|
|
||||||
|
if (-not (Install-Python)) {
|
||||||
|
throw "Python installation failed"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not (Install-NSSM)) {
|
||||||
|
throw "NSSM installation failed"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create directory structure
|
||||||
|
Write-Step "Creating directory structure..."
|
||||||
|
$directories = @(
|
||||||
|
$Config.DataEntryBackendPath,
|
||||||
|
$Config.DataEntryFrontendPath,
|
||||||
|
(Join-Path $Config.DataEntryBackendPath "app"),
|
||||||
|
(Join-Path $Config.DataEntryBackendPath "data"),
|
||||||
|
$Config.DataEntryLogsPath,
|
||||||
|
(Join-Path $Config.DataEntryBackendPath "temp"),
|
||||||
|
(Join-Path $Config.DataEntryBackendPath "migrations")
|
||||||
|
)
|
||||||
|
|
||||||
|
foreach ($dir in $directories) {
|
||||||
|
if (-not (Test-Path $dir)) {
|
||||||
|
New-Item -ItemType Directory -Path $dir -Force | Out-Null
|
||||||
|
Write-Success "Created: $dir"
|
||||||
|
} else {
|
||||||
|
Write-Success "Already exists: $dir"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Set permissions
|
||||||
|
try {
|
||||||
|
$acl = Get-Acl $Config.DataEntryBackendPath
|
||||||
|
$systemRule = New-Object System.Security.AccessControl.FileSystemAccessRule("SYSTEM", "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow")
|
||||||
|
$acl.SetAccessRule($systemRule)
|
||||||
|
Set-Acl -Path $Config.DataEntryBackendPath -AclObject $acl
|
||||||
|
|
||||||
|
$iisRule = New-Object System.Security.AccessControl.FileSystemAccessRule("IIS_IUSRS", "ReadAndExecute", "ContainerInherit,ObjectInherit", "None", "Allow")
|
||||||
|
$acl.SetAccessRule($iisRule)
|
||||||
|
Set-Acl -Path $Config.DataEntryFrontendPath -AclObject $acl
|
||||||
|
|
||||||
|
Write-Success "Permissions set for SYSTEM and IIS_IUSRS"
|
||||||
|
} catch {
|
||||||
|
Write-Warning "Could not set permissions: $_"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Copy data entry backend files
|
||||||
|
Write-Step "Copying Data Entry backend files..."
|
||||||
|
$sourceDataEntryBackend = Join-Path $Config.SourcePath "data-entry-backend"
|
||||||
|
|
||||||
|
if (-not (Test-Path $sourceDataEntryBackend)) {
|
||||||
|
throw "Source data-entry-backend path not found: $sourceDataEntryBackend"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Copy app directory
|
||||||
|
$sourceApp = Join-Path $sourceDataEntryBackend "app"
|
||||||
|
$destApp = Join-Path $Config.DataEntryBackendPath "app"
|
||||||
|
|
||||||
|
if (Test-Path $destApp) {
|
||||||
|
Remove-Item -Path $destApp -Recurse -Force
|
||||||
|
}
|
||||||
|
|
||||||
|
Copy-Item -Path $sourceApp -Destination $destApp -Recurse -Force
|
||||||
|
Write-Success "Application files copied"
|
||||||
|
|
||||||
|
# Copy migrations directory
|
||||||
|
$sourceMigrations = Join-Path $sourceDataEntryBackend "migrations"
|
||||||
|
$destMigrations = Join-Path $Config.DataEntryBackendPath "migrations"
|
||||||
|
if (Test-Path $sourceMigrations) {
|
||||||
|
if (Test-Path $destMigrations) {
|
||||||
|
Remove-Item -Path $destMigrations -Recurse -Force
|
||||||
|
}
|
||||||
|
Copy-Item -Path $sourceMigrations -Destination $destMigrations -Recurse -Force
|
||||||
|
Write-Success "Migrations copied"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Copy alembic.ini
|
||||||
|
$sourceAlembic = Join-Path $sourceDataEntryBackend "alembic.ini"
|
||||||
|
if (Test-Path $sourceAlembic) {
|
||||||
|
Copy-Item -Path $sourceAlembic -Destination $Config.DataEntryBackendPath -Force
|
||||||
|
Write-Success "alembic.ini copied"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Copy requirements.txt
|
||||||
|
$sourceReq = Join-Path $sourceDataEntryBackend "requirements.txt"
|
||||||
|
if (Test-Path $sourceReq) {
|
||||||
|
$destReq = Join-Path $Config.DataEntryBackendPath "requirements.txt"
|
||||||
|
Copy-Item -Path $sourceReq -Destination $destReq -Force
|
||||||
|
Write-Success "requirements.txt copied"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Copy .env.example and .env.prod templates
|
||||||
|
foreach ($envFile in @(".env.example", ".env.prod", ".env.test")) {
|
||||||
|
$sourceEnv = Join-Path $sourceDataEntryBackend $envFile
|
||||||
|
if (Test-Path $sourceEnv) {
|
||||||
|
$destEnv = Join-Path $Config.DataEntryBackendPath $envFile
|
||||||
|
Copy-Item -Path $sourceEnv -Destination $destEnv -Force
|
||||||
|
Write-Success "$envFile template copied"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Copy shared modules (always update to ensure latest version)
|
||||||
|
$sourceShared = Join-Path $Config.SourcePath "shared"
|
||||||
|
if (Test-Path $sourceShared) {
|
||||||
|
$destShared = Join-Path $Config.InstallPath "shared"
|
||||||
|
if (-not (Test-Path $destShared)) {
|
||||||
|
New-Item -ItemType Directory -Path $destShared -Force | Out-Null
|
||||||
|
}
|
||||||
|
# Always copy/update shared modules to ensure all subfolders are present
|
||||||
|
Copy-Item -Path "$sourceShared\*" -Destination $destShared -Recurse -Force -Exclude @("__pycache__", "*.pyc")
|
||||||
|
Write-Success "Shared modules updated"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Copy frontend files
|
||||||
|
Write-Step "Copying Data Entry frontend files..."
|
||||||
|
$sourceDataEntryFrontend = Join-Path $Config.SourcePath "data-entry-frontend"
|
||||||
|
if (Test-Path $sourceDataEntryFrontend) {
|
||||||
|
Copy-Item -Path "$sourceDataEntryFrontend\*" -Destination $Config.DataEntryFrontendPath -Recurse -Force
|
||||||
|
Write-Success "Frontend files copied"
|
||||||
|
} else {
|
||||||
|
Write-Warning "Frontend source not found: $sourceDataEntryFrontend"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create virtual environment
|
||||||
|
Write-Step "Creating Python virtual environment..."
|
||||||
|
$venvPath = Join-Path $Config.DataEntryBackendPath "venv"
|
||||||
|
& python -m venv $venvPath
|
||||||
|
Write-Success "Virtual environment created"
|
||||||
|
|
||||||
|
# Define paths
|
||||||
|
$pipPath = Join-Path $venvPath "Scripts\pip.exe"
|
||||||
|
$pythonPath = Join-Path $venvPath "Scripts\python.exe"
|
||||||
|
$requirementsPath = Join-Path $Config.DataEntryBackendPath "requirements.txt"
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
Write-Step "Installing Python dependencies..."
|
||||||
|
|
||||||
|
if (Test-Path $requirementsPath) {
|
||||||
|
Write-Info "Upgrading pip..."
|
||||||
|
& $pythonPath -m pip install --upgrade pip | Out-Default
|
||||||
|
|
||||||
|
Write-Info "Installing dependencies..."
|
||||||
|
& $pipPath install -r $requirementsPath | Out-Default
|
||||||
|
Write-Success "Python dependencies installed"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create Windows Service
|
||||||
|
Write-Step "Creating Windows Service for Data Entry..."
|
||||||
|
|
||||||
|
# Remove existing service if present
|
||||||
|
$oldErrorAction = $ErrorActionPreference
|
||||||
|
$ErrorActionPreference = "SilentlyContinue"
|
||||||
|
$nssmOutput = & nssm status $Config.DataEntryServiceName 2>&1
|
||||||
|
$serviceExists = $LASTEXITCODE -eq 0
|
||||||
|
$ErrorActionPreference = $oldErrorAction
|
||||||
|
|
||||||
|
if ($serviceExists) {
|
||||||
|
Write-Info "Removing existing service..."
|
||||||
|
& nssm stop $Config.DataEntryServiceName 2>&1 | Out-Null
|
||||||
|
Start-Sleep -Seconds 2
|
||||||
|
& nssm remove $Config.DataEntryServiceName confirm 2>&1 | Out-Null
|
||||||
|
Start-Sleep -Seconds 2
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create service (using 1 worker to avoid Windows socket sharing issues with multiple workers)
|
||||||
|
& nssm install $Config.DataEntryServiceName $pythonPath "-m" "uvicorn" "app.main:app" "--host" "127.0.0.1" "--port" $Config.DataEntryPort.ToString() "--workers" "1"
|
||||||
|
& nssm set $Config.DataEntryServiceName DisplayName $Config.DataEntryServiceDisplayName
|
||||||
|
& nssm set $Config.DataEntryServiceName Description $Config.DataEntryServiceDescription
|
||||||
|
& nssm set $Config.DataEntryServiceName Start SERVICE_AUTO_START
|
||||||
|
& nssm set $Config.DataEntryServiceName AppDirectory $Config.DataEntryBackendPath
|
||||||
|
|
||||||
|
# Set PYTHONPATH to include shared modules
|
||||||
|
$sharedPath = Join-Path $Config.InstallPath "shared"
|
||||||
|
& nssm set $Config.DataEntryServiceName AppEnvironmentExtra "PYTHONPATH=$sharedPath"
|
||||||
|
|
||||||
|
# Set logging
|
||||||
|
$stdoutLog = Join-Path $Config.DataEntryLogsPath "stdout.log"
|
||||||
|
$stderrLog = Join-Path $Config.DataEntryLogsPath "stderr.log"
|
||||||
|
& nssm set $Config.DataEntryServiceName AppStdout $stdoutLog
|
||||||
|
& nssm set $Config.DataEntryServiceName AppStderr $stderrLog
|
||||||
|
& nssm set $Config.DataEntryServiceName AppStdoutCreationDisposition 4
|
||||||
|
& nssm set $Config.DataEntryServiceName AppStderrCreationDisposition 4
|
||||||
|
& nssm set $Config.DataEntryServiceName AppExit Default Restart
|
||||||
|
& nssm set $Config.DataEntryServiceName AppRestartDelay 5000
|
||||||
|
|
||||||
|
Write-Success "Windows Service created: $($Config.DataEntryServiceName)"
|
||||||
|
|
||||||
|
# Configure IIS for frontend
|
||||||
|
if (Install-IISModules) {
|
||||||
|
Write-Step "Configuring IIS for Data Entry frontend..."
|
||||||
|
Import-Module WebAdministration -ErrorAction Stop
|
||||||
|
|
||||||
|
# Create Application Pool
|
||||||
|
if (Test-Path "IIS:\AppPools\$($Config.DataEntryAppPoolName)") {
|
||||||
|
Remove-WebAppPool -Name $Config.DataEntryAppPoolName -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
|
|
||||||
|
New-WebAppPool -Name $Config.DataEntryAppPoolName -Force | Out-Null
|
||||||
|
Set-ItemProperty -Path "IIS:\AppPools\$($Config.DataEntryAppPoolName)" -Name "managedRuntimeVersion" -Value ""
|
||||||
|
Write-Success "Application Pool created: $($Config.DataEntryAppPoolName)"
|
||||||
|
|
||||||
|
# Create/update application
|
||||||
|
$existingApp = Get-WebApplication -Name $Config.DataEntryIISAppName -Site $Config.IISSiteName -ErrorAction SilentlyContinue
|
||||||
|
if ($existingApp) {
|
||||||
|
Remove-WebApplication -Name $Config.DataEntryIISAppName -Site $Config.IISSiteName -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
|
|
||||||
|
New-WebApplication -Name $Config.DataEntryIISAppName `
|
||||||
|
-Site $Config.IISSiteName `
|
||||||
|
-PhysicalPath $Config.DataEntryFrontendPath `
|
||||||
|
-ApplicationPool $Config.DataEntryAppPoolName `
|
||||||
|
-Force | Out-Null
|
||||||
|
|
||||||
|
Write-Success "IIS Application created: /$($Config.DataEntryIISAppName)"
|
||||||
|
|
||||||
|
# Copy web.config for data-entry frontend
|
||||||
|
$webConfigSource = Join-Path (Split-Path $Config.SourcePath -Parent) "config\web.config.data-entry"
|
||||||
|
$webConfigDest = Join-Path $Config.DataEntryFrontendPath "web.config"
|
||||||
|
if (Test-Path $webConfigSource) {
|
||||||
|
Copy-Item -Path $webConfigSource -Destination $webConfigDest -Force
|
||||||
|
Write-Success "web.config copied for Data Entry frontend"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Write-Warning "IIS modules not installed, skipping IIS configuration"
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "`n" + ("=" * 70) -ForegroundColor Green
|
||||||
|
Write-Host " DATA ENTRY INSTALLATION COMPLETED" -ForegroundColor Green
|
||||||
|
Write-Host ("=" * 70) -ForegroundColor Green
|
||||||
|
Write-Host "`nIMPORTANT: Configure .env file before starting service" -ForegroundColor Yellow
|
||||||
|
Write-Host "Location: $($Config.DataEntryBackendPath)\.env" -ForegroundColor Yellow
|
||||||
|
Write-Host "Copy .env.prod to .env and edit with your settings" -ForegroundColor Yellow
|
||||||
|
|
||||||
|
return $true
|
||||||
|
} catch {
|
||||||
|
Write-Host "`n[INSTALLATION FAILED] $_" -ForegroundColor Red
|
||||||
|
Write-Host $_.ScriptStackTrace -ForegroundColor Red
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# MENU FUNCTIONS
|
# MENU FUNCTIONS
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
@@ -872,10 +1168,10 @@ function Show-MainMenu {
|
|||||||
Write-Host " Main Menu:" -ForegroundColor Yellow
|
Write-Host " Main Menu:" -ForegroundColor Yellow
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host " [1] Deploy Components" -ForegroundColor White
|
Write-Host " [1] Deploy Components" -ForegroundColor White
|
||||||
Write-Host " (Update application files and configurations)" -ForegroundColor Gray
|
Write-Host " (Update Reports, Telegram Bot, Data Entry)" -ForegroundColor Gray
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host " [2] Manage Services" -ForegroundColor White
|
Write-Host " [2] Manage Services" -ForegroundColor White
|
||||||
Write-Host " (Start, stop, restart Backend and Telegram Bot)" -ForegroundColor Gray
|
Write-Host " (Start, stop, restart all services)" -ForegroundColor Gray
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host " [3] Check Status" -ForegroundColor White
|
Write-Host " [3] Check Status" -ForegroundColor White
|
||||||
Write-Host " (View service status and health checks)" -ForegroundColor Gray
|
Write-Host " (View service status and health checks)" -ForegroundColor Gray
|
||||||
@@ -908,14 +1204,20 @@ function Show-DeployMenu {
|
|||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host " Select what to deploy:" -ForegroundColor Yellow
|
Write-Host " Select what to deploy:" -ForegroundColor Yellow
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host " [1] Backend + Frontend" -ForegroundColor White
|
Write-Host " --- Reports App ---" -ForegroundColor Cyan
|
||||||
|
Write-Host " [1] Reports Backend + Frontend" -ForegroundColor White
|
||||||
Write-Host " (FastAPI backend + Vue.js frontend files)" -ForegroundColor Gray
|
Write-Host " (FastAPI backend + Vue.js frontend files)" -ForegroundColor Gray
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host " [2] Telegram Bot" -ForegroundColor White
|
Write-Host " [2] Telegram Bot" -ForegroundColor White
|
||||||
Write-Host " (Telegram bot application only)" -ForegroundColor Gray
|
Write-Host " (Telegram bot application only)" -ForegroundColor Gray
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host " [3] All Components" -ForegroundColor White
|
Write-Host " --- Data Entry App ---" -ForegroundColor Cyan
|
||||||
Write-Host " (Backend + Frontend + Telegram Bot)" -ForegroundColor Gray
|
Write-Host " [3] Data Entry App" -ForegroundColor White
|
||||||
|
Write-Host " (Data Entry backend + frontend)" -ForegroundColor Gray
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host " --- Combined ---" -ForegroundColor Cyan
|
||||||
|
Write-Host " [4] All Components" -ForegroundColor White
|
||||||
|
Write-Host " (Reports + Telegram Bot + Data Entry)" -ForegroundColor Gray
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host " [B] Back to Main Menu" -ForegroundColor Yellow
|
Write-Host " [B] Back to Main Menu" -ForegroundColor Yellow
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
@@ -928,10 +1230,11 @@ function Show-DeployMenu {
|
|||||||
switch ($choice.ToUpper()) {
|
switch ($choice.ToUpper()) {
|
||||||
"1" { return "Backend" }
|
"1" { return "Backend" }
|
||||||
"2" { return "TelegramBot" }
|
"2" { return "TelegramBot" }
|
||||||
"3" { return "All" }
|
"3" { return "DataEntry" }
|
||||||
|
"4" { return "All" }
|
||||||
"B" { return "Back" }
|
"B" { return "Back" }
|
||||||
default {
|
default {
|
||||||
Write-Host "Invalid choice. Please select 1-3 or B." -ForegroundColor Red
|
Write-Host "Invalid choice. Please select 1-4 or B." -ForegroundColor Red
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while ($true)
|
} while ($true)
|
||||||
@@ -948,16 +1251,21 @@ function Show-ManageMenu {
|
|||||||
Write-Host " [2] Stop All Services" -ForegroundColor Red
|
Write-Host " [2] Stop All Services" -ForegroundColor Red
|
||||||
Write-Host " [3] Restart All Services" -ForegroundColor Yellow
|
Write-Host " [3] Restart All Services" -ForegroundColor Yellow
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host " Backend Service:" -ForegroundColor Yellow
|
Write-Host " Reports Backend Service:" -ForegroundColor Yellow
|
||||||
Write-Host " [4] Start Backend" -ForegroundColor Green
|
Write-Host " [4] Start Reports Backend" -ForegroundColor Green
|
||||||
Write-Host " [5] Stop Backend" -ForegroundColor Red
|
Write-Host " [5] Stop Reports Backend" -ForegroundColor Red
|
||||||
Write-Host " [6] Restart Backend" -ForegroundColor Yellow
|
Write-Host " [6] Restart Reports Backend" -ForegroundColor Yellow
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host " Telegram Bot Service:" -ForegroundColor Yellow
|
Write-Host " Telegram Bot Service:" -ForegroundColor Yellow
|
||||||
Write-Host " [7] Start Telegram Bot" -ForegroundColor Green
|
Write-Host " [7] Start Telegram Bot" -ForegroundColor Green
|
||||||
Write-Host " [8] Stop Telegram Bot" -ForegroundColor Red
|
Write-Host " [8] Stop Telegram Bot" -ForegroundColor Red
|
||||||
Write-Host " [9] Restart Telegram Bot" -ForegroundColor Yellow
|
Write-Host " [9] Restart Telegram Bot" -ForegroundColor Yellow
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
|
Write-Host " Data Entry Service:" -ForegroundColor Yellow
|
||||||
|
Write-Host " [A] Start Data Entry" -ForegroundColor Green
|
||||||
|
Write-Host " [S] Stop Data Entry" -ForegroundColor Red
|
||||||
|
Write-Host " [D] Restart Data Entry" -ForegroundColor Yellow
|
||||||
|
Write-Host ""
|
||||||
Write-Host " [B] Back to Main Menu" -ForegroundColor Gray
|
Write-Host " [B] Back to Main Menu" -ForegroundColor Gray
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host ("=" * 70) -ForegroundColor Cyan
|
Write-Host ("=" * 70) -ForegroundColor Cyan
|
||||||
@@ -976,9 +1284,12 @@ function Show-ManageMenu {
|
|||||||
"7" { return @{ Action = "Start"; Component = "TelegramBot" } }
|
"7" { return @{ Action = "Start"; Component = "TelegramBot" } }
|
||||||
"8" { return @{ Action = "Stop"; Component = "TelegramBot" } }
|
"8" { return @{ Action = "Stop"; Component = "TelegramBot" } }
|
||||||
"9" { return @{ Action = "Restart"; Component = "TelegramBot" } }
|
"9" { return @{ Action = "Restart"; Component = "TelegramBot" } }
|
||||||
|
"A" { return @{ Action = "Start"; Component = "DataEntry" } }
|
||||||
|
"S" { return @{ Action = "Stop"; Component = "DataEntry" } }
|
||||||
|
"D" { return @{ Action = "Restart"; Component = "DataEntry" } }
|
||||||
"B" { return @{ Action = "Back"; Component = "" } }
|
"B" { return @{ Action = "Back"; Component = "" } }
|
||||||
default {
|
default {
|
||||||
Write-Host "Invalid choice. Please select 1-9 or B." -ForegroundColor Red
|
Write-Host "Invalid choice. Please select 1-9, A, S, D, or B." -ForegroundColor Red
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while ($true)
|
} while ($true)
|
||||||
@@ -1496,6 +1807,18 @@ function Deploy-Backend {
|
|||||||
|
|
||||||
# Update files
|
# Update files
|
||||||
Update-BackendFiles
|
Update-BackendFiles
|
||||||
|
|
||||||
|
# Update shared modules (always update to ensure all subfolders are present)
|
||||||
|
$sourceShared = Join-Path $Config.SourcePath "shared"
|
||||||
|
if (Test-Path $sourceShared) {
|
||||||
|
$destShared = Join-Path $Config.InstallPath "shared"
|
||||||
|
if (-not (Test-Path $destShared)) {
|
||||||
|
New-Item -ItemType Directory -Path $destShared -Force | Out-Null
|
||||||
|
}
|
||||||
|
Copy-Item -Path "$sourceShared\*" -Destination $destShared -Recurse -Force -Exclude @("__pycache__", "*.pyc")
|
||||||
|
Write-Success "Shared modules updated"
|
||||||
|
}
|
||||||
|
|
||||||
Update-FrontendFiles
|
Update-FrontendFiles
|
||||||
|
|
||||||
# Start backend service
|
# Start backend service
|
||||||
@@ -1558,10 +1881,12 @@ function Deploy-TelegramBot {
|
|||||||
$originalSourcePath = $Config.SourcePath
|
$originalSourcePath = $Config.SourcePath
|
||||||
$Config.SourcePath = Join-Path $originalSourcePath "telegram-bot"
|
$Config.SourcePath = Join-Path $originalSourcePath "telegram-bot"
|
||||||
|
|
||||||
Update-TelegramBotFiles
|
try {
|
||||||
|
Update-TelegramBotFiles
|
||||||
# Restore original source path
|
} finally {
|
||||||
$Config.SourcePath = $originalSourcePath
|
# ALWAYS restore original source path (even on error)
|
||||||
|
$Config.SourcePath = $originalSourcePath
|
||||||
|
}
|
||||||
|
|
||||||
# Start telegram bot service
|
# Start telegram bot service
|
||||||
$started = Start-ServiceComponent -ComponentName "Telegram Bot" `
|
$started = Start-ServiceComponent -ComponentName "Telegram Bot" `
|
||||||
@@ -1585,6 +1910,297 @@ function Deploy-TelegramBot {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Update-DataEntryBackendFiles {
|
||||||
|
Write-Step "Updating Data Entry backend files..."
|
||||||
|
|
||||||
|
$sourceDataEntryBackend = Join-Path $Config.SourcePath "data-entry-backend"
|
||||||
|
|
||||||
|
if (-not (Test-Path $sourceDataEntryBackend)) {
|
||||||
|
throw "Source data-entry-backend path not found: $sourceDataEntryBackend"
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
# Copy app directory
|
||||||
|
$sourceApp = Join-Path $sourceDataEntryBackend "app"
|
||||||
|
$destApp = Join-Path $Config.DataEntryBackendPath "app"
|
||||||
|
|
||||||
|
if (Test-Path $destApp) {
|
||||||
|
Remove-Item -Path $destApp -Recurse -Force
|
||||||
|
Write-Success "Removed old app directory"
|
||||||
|
}
|
||||||
|
|
||||||
|
Copy-Item -Path $sourceApp -Destination $destApp -Recurse -Force
|
||||||
|
Write-Success "Application files updated"
|
||||||
|
|
||||||
|
# Copy migrations directory
|
||||||
|
$sourceMigrations = Join-Path $sourceDataEntryBackend "migrations"
|
||||||
|
$destMigrations = Join-Path $Config.DataEntryBackendPath "migrations"
|
||||||
|
if (Test-Path $sourceMigrations) {
|
||||||
|
if (Test-Path $destMigrations) {
|
||||||
|
Remove-Item -Path $destMigrations -Recurse -Force
|
||||||
|
}
|
||||||
|
Copy-Item -Path $sourceMigrations -Destination $destMigrations -Recurse -Force
|
||||||
|
Write-Success "Migrations updated"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Copy alembic.ini
|
||||||
|
$sourceAlembic = Join-Path $sourceDataEntryBackend "alembic.ini"
|
||||||
|
if (Test-Path $sourceAlembic) {
|
||||||
|
Copy-Item -Path $sourceAlembic -Destination $Config.DataEntryBackendPath -Force
|
||||||
|
Write-Success "alembic.ini updated"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Update requirements.txt if changed
|
||||||
|
$sourceReq = Join-Path $sourceDataEntryBackend "requirements.txt"
|
||||||
|
$destReq = Join-Path $Config.DataEntryBackendPath "requirements.txt"
|
||||||
|
|
||||||
|
if (Test-Path $sourceReq) {
|
||||||
|
$sourceHash = (Get-FileHash $sourceReq -Algorithm SHA256).Hash
|
||||||
|
$destHash = if (Test-Path $destReq) {
|
||||||
|
(Get-FileHash $destReq -Algorithm SHA256).Hash
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($sourceHash -ne $destHash) {
|
||||||
|
Write-Step "Requirements changed, updating Python dependencies..."
|
||||||
|
Copy-Item -Path $sourceReq -Destination $destReq -Force
|
||||||
|
|
||||||
|
# Use virtual environment pip
|
||||||
|
$venvPath = Join-Path $Config.DataEntryBackendPath "venv"
|
||||||
|
$pipPath = Join-Path $venvPath "Scripts\pip.exe"
|
||||||
|
|
||||||
|
if (Test-Path $pipPath) {
|
||||||
|
& $pipPath install -r $destReq --upgrade
|
||||||
|
Write-Success "Python dependencies updated"
|
||||||
|
} else {
|
||||||
|
Write-Warning "Virtual environment not found, skipping dependency update"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Write-Success "Python dependencies unchanged"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Copy .env templates (always update to keep in sync)
|
||||||
|
foreach ($envFile in @(".env.example", ".env.prod", ".env.test")) {
|
||||||
|
$sourceEnv = Join-Path $sourceDataEntryBackend $envFile
|
||||||
|
$destEnv = Join-Path $Config.DataEntryBackendPath $envFile
|
||||||
|
if (Test-Path $sourceEnv) {
|
||||||
|
Copy-Item -Path $sourceEnv -Destination $destEnv -Force
|
||||||
|
Write-Success "$envFile template updated"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Preserve .env file (or create from .env.prod if missing)
|
||||||
|
$envFile = Join-Path $Config.DataEntryBackendPath ".env"
|
||||||
|
if (-not (Test-Path $envFile)) {
|
||||||
|
$sourceEnvProd = Join-Path $sourceDataEntryBackend ".env.prod"
|
||||||
|
if (Test-Path $sourceEnvProd) {
|
||||||
|
Copy-Item -Path $sourceEnvProd -Destination $envFile -Force
|
||||||
|
Write-Warning "Created .env from .env.prod - PLEASE CONFIGURE"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Write-Success ".env file preserved"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Run database migrations
|
||||||
|
Write-Step "Running database migrations..."
|
||||||
|
$venvPath = Join-Path $Config.DataEntryBackendPath "venv"
|
||||||
|
$pythonPath = Join-Path $venvPath "Scripts\python.exe"
|
||||||
|
$alembicPath = Join-Path $venvPath "Scripts\alembic.exe"
|
||||||
|
|
||||||
|
if (Test-Path $alembicPath) {
|
||||||
|
Push-Location $Config.DataEntryBackendPath
|
||||||
|
try {
|
||||||
|
& $alembicPath upgrade head
|
||||||
|
if ($LASTEXITCODE -eq 0) {
|
||||||
|
Write-Success "Database migrations completed"
|
||||||
|
} else {
|
||||||
|
Write-Warning "Migration returned non-zero exit code"
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
Pop-Location
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Write-Warning "Alembic not found, skipping migrations"
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch {
|
||||||
|
Write-Error "Failed to update Data Entry backend files: $_"
|
||||||
|
throw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Update-DataEntryFrontendFiles {
|
||||||
|
Write-Step "Updating Data Entry frontend files..."
|
||||||
|
|
||||||
|
$sourceDataEntryFrontend = Join-Path $Config.SourcePath "data-entry-frontend"
|
||||||
|
|
||||||
|
if (-not (Test-Path $sourceDataEntryFrontend)) {
|
||||||
|
throw "Source data-entry-frontend path not found: $sourceDataEntryFrontend"
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
# Remove old frontend files (except web.config)
|
||||||
|
if (Test-Path $Config.DataEntryFrontendPath) {
|
||||||
|
Get-ChildItem -Path $Config.DataEntryFrontendPath -Exclude "web.config" | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
|
|
||||||
|
# Copy new frontend files
|
||||||
|
Copy-Item -Path "$sourceDataEntryFrontend\*" -Destination $Config.DataEntryFrontendPath -Recurse -Force
|
||||||
|
|
||||||
|
# Ensure web.config exists (copy from config if missing)
|
||||||
|
$webConfigDest = Join-Path $Config.DataEntryFrontendPath "web.config"
|
||||||
|
if (-not (Test-Path $webConfigDest)) {
|
||||||
|
$webConfigSource = Join-Path (Split-Path $Config.SourcePath -Parent) "config\web.config.data-entry"
|
||||||
|
if (Test-Path $webConfigSource) {
|
||||||
|
Copy-Item -Path $webConfigSource -Destination $webConfigDest -Force
|
||||||
|
Write-Success "web.config copied for Data Entry frontend (was missing)"
|
||||||
|
} else {
|
||||||
|
Write-Warning "web.config.data-entry not found in config folder"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Success "Data Entry frontend files updated"
|
||||||
|
} catch {
|
||||||
|
Write-Error "Failed to update Data Entry frontend files: $_"
|
||||||
|
throw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Backup-DataEntryDeployment {
|
||||||
|
Write-Step "Backing up Data Entry deployment..."
|
||||||
|
|
||||||
|
New-BackupDirectory
|
||||||
|
|
||||||
|
$timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
|
||||||
|
$backupName = "backup-DataEntry-$timestamp"
|
||||||
|
$backupFullPath = Join-Path $Config.BackupPath $backupName
|
||||||
|
|
||||||
|
try {
|
||||||
|
New-Item -ItemType Directory -Path $backupFullPath -Force | Out-Null
|
||||||
|
|
||||||
|
# Backup app directory
|
||||||
|
$appPath = Join-Path $Config.DataEntryBackendPath "app"
|
||||||
|
if (Test-Path $appPath) {
|
||||||
|
$backupAppPath = Join-Path $backupFullPath "app"
|
||||||
|
Copy-Item -Path $appPath -Destination $backupAppPath -Recurse -Force
|
||||||
|
Write-Success "App files backed up"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Backup migrations
|
||||||
|
$migrationsPath = Join-Path $Config.DataEntryBackendPath "migrations"
|
||||||
|
if (Test-Path $migrationsPath) {
|
||||||
|
$backupMigrationsPath = Join-Path $backupFullPath "migrations"
|
||||||
|
Copy-Item -Path $migrationsPath -Destination $backupMigrationsPath -Recurse -Force
|
||||||
|
Write-Success "Migrations backed up"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Backup requirements.txt
|
||||||
|
$reqFile = Join-Path $Config.DataEntryBackendPath "requirements.txt"
|
||||||
|
if (Test-Path $reqFile) {
|
||||||
|
Copy-Item -Path $reqFile -Destination (Join-Path $backupFullPath "requirements.txt") -Force
|
||||||
|
Write-Success "Requirements file backed up"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Backup .env
|
||||||
|
$envFile = Join-Path $Config.DataEntryBackendPath ".env"
|
||||||
|
if (Test-Path $envFile) {
|
||||||
|
Copy-Item -Path $envFile -Destination (Join-Path $backupFullPath ".env") -Force
|
||||||
|
Write-Success ".env file backed up"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Backup database
|
||||||
|
$dbFile = Join-Path $Config.DataEntryBackendPath "data\receipts*.db"
|
||||||
|
$dbFiles = Get-ChildItem -Path (Join-Path $Config.DataEntryBackendPath "data") -Filter "*.db" -ErrorAction SilentlyContinue
|
||||||
|
if ($dbFiles) {
|
||||||
|
$backupDataPath = Join-Path $backupFullPath "data"
|
||||||
|
New-Item -ItemType Directory -Path $backupDataPath -Force | Out-Null
|
||||||
|
foreach ($db in $dbFiles) {
|
||||||
|
Copy-Item -Path $db.FullName -Destination (Join-Path $backupDataPath $db.Name) -Force
|
||||||
|
}
|
||||||
|
Write-Success "Database(s) backed up"
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Success "Backup created at: $backupFullPath"
|
||||||
|
return $backupFullPath
|
||||||
|
} catch {
|
||||||
|
Write-Error "Backup failed: $_"
|
||||||
|
throw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Deploy-DataEntry {
|
||||||
|
Write-Host "`n" + ("=" * 70) -ForegroundColor Cyan
|
||||||
|
Write-Host " DEPLOYING DATA ENTRY APP" -ForegroundColor Cyan
|
||||||
|
Write-Host ("=" * 70) -ForegroundColor Cyan
|
||||||
|
|
||||||
|
try {
|
||||||
|
# Auto-detect: First-time install or update?
|
||||||
|
$isInstalled = Test-DataEntryInstalled
|
||||||
|
|
||||||
|
if (-not $isInstalled) {
|
||||||
|
Write-Host ""
|
||||||
|
Write-Warning "Data Entry NOT detected - performing FIRST-TIME INSTALLATION"
|
||||||
|
Write-Host ""
|
||||||
|
Start-Sleep -Seconds 2
|
||||||
|
|
||||||
|
# Route to first-time installation
|
||||||
|
return Install-DataEntryFirstTime
|
||||||
|
}
|
||||||
|
|
||||||
|
# Data Entry is already installed - proceed with UPDATE
|
||||||
|
Write-Host ""
|
||||||
|
Write-Info "Data Entry detected - performing UPDATE"
|
||||||
|
Write-Host ""
|
||||||
|
|
||||||
|
# Create backup
|
||||||
|
$backupPath = Backup-DataEntryDeployment
|
||||||
|
|
||||||
|
# Stop data entry service
|
||||||
|
$stopped = Stop-ServiceComponent -ComponentName "Data Entry" -ServiceName $Config.DataEntryServiceName
|
||||||
|
if (-not $stopped) {
|
||||||
|
throw "Failed to stop Data Entry service"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Update files
|
||||||
|
Update-DataEntryBackendFiles
|
||||||
|
|
||||||
|
# Update shared modules (always update to ensure all subfolders are present)
|
||||||
|
$sourceShared = Join-Path $Config.SourcePath "shared"
|
||||||
|
if (Test-Path $sourceShared) {
|
||||||
|
$destShared = Join-Path $Config.InstallPath "shared"
|
||||||
|
if (-not (Test-Path $destShared)) {
|
||||||
|
New-Item -ItemType Directory -Path $destShared -Force | Out-Null
|
||||||
|
}
|
||||||
|
Copy-Item -Path "$sourceShared\*" -Destination $destShared -Recurse -Force -Exclude @("__pycache__", "*.pyc")
|
||||||
|
Write-Success "Shared modules updated"
|
||||||
|
}
|
||||||
|
|
||||||
|
Update-DataEntryFrontendFiles
|
||||||
|
|
||||||
|
# Start data entry service
|
||||||
|
$started = Start-ServiceComponent -ComponentName "Data Entry" `
|
||||||
|
-ServiceName $Config.DataEntryServiceName `
|
||||||
|
-HealthUrl $Config.DataEntryHealthUrl `
|
||||||
|
-HealthTimeout $Config.DataEntryHealthTimeout
|
||||||
|
|
||||||
|
if ($started) {
|
||||||
|
Write-Host "`n" + ("=" * 70) -ForegroundColor Green
|
||||||
|
Write-Host " DATA ENTRY APP DEPLOYED SUCCESSFULLY" -ForegroundColor Green
|
||||||
|
Write-Host ("=" * 70) -ForegroundColor Green
|
||||||
|
Write-Host " Backup: $backupPath" -ForegroundColor Gray
|
||||||
|
return $true
|
||||||
|
} else {
|
||||||
|
throw "Failed to start Data Entry service after deployment"
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch {
|
||||||
|
Write-Host "`n[DEPLOYMENT FAILED] $_" -ForegroundColor Red
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# MAIN EXECUTION FLOW
|
# MAIN EXECUTION FLOW
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
@@ -1601,15 +2217,17 @@ function Execute-ManageAction {
|
|||||||
switch ($Component) {
|
switch ($Component) {
|
||||||
"All" {
|
"All" {
|
||||||
$components = @(
|
$components = @(
|
||||||
@{ Name = "Backend"; ServiceName = $Config.BackendServiceName;
|
@{ Name = "Reports Backend"; ServiceName = $Config.BackendServiceName;
|
||||||
HealthUrl = $Config.BackendHealthUrl; HealthTimeout = $Config.BackendHealthTimeout },
|
HealthUrl = $Config.BackendHealthUrl; HealthTimeout = $Config.BackendHealthTimeout },
|
||||||
@{ Name = "Telegram Bot"; ServiceName = $Config.TelegramBotServiceName;
|
@{ Name = "Telegram Bot"; ServiceName = $Config.TelegramBotServiceName;
|
||||||
HealthUrl = $Config.TelegramBotHealthUrl; HealthTimeout = $Config.TelegramBotHealthTimeout }
|
HealthUrl = $Config.TelegramBotHealthUrl; HealthTimeout = $Config.TelegramBotHealthTimeout },
|
||||||
|
@{ Name = "Data Entry"; ServiceName = $Config.DataEntryServiceName;
|
||||||
|
HealthUrl = $Config.DataEntryHealthUrl; HealthTimeout = $Config.DataEntryHealthTimeout }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
"Backend" {
|
"Backend" {
|
||||||
$components = @(
|
$components = @(
|
||||||
@{ Name = "Backend"; ServiceName = $Config.BackendServiceName;
|
@{ Name = "Reports Backend"; ServiceName = $Config.BackendServiceName;
|
||||||
HealthUrl = $Config.BackendHealthUrl; HealthTimeout = $Config.BackendHealthTimeout }
|
HealthUrl = $Config.BackendHealthUrl; HealthTimeout = $Config.BackendHealthTimeout }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -1619,6 +2237,12 @@ function Execute-ManageAction {
|
|||||||
HealthUrl = $Config.TelegramBotHealthUrl; HealthTimeout = $Config.TelegramBotHealthTimeout }
|
HealthUrl = $Config.TelegramBotHealthUrl; HealthTimeout = $Config.TelegramBotHealthTimeout }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
"DataEntry" {
|
||||||
|
$components = @(
|
||||||
|
@{ Name = "Data Entry"; ServiceName = $Config.DataEntryServiceName;
|
||||||
|
HealthUrl = $Config.DataEntryHealthUrl; HealthTimeout = $Config.DataEntryHealthTimeout }
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($comp in $components) {
|
foreach ($comp in $components) {
|
||||||
@@ -1665,11 +2289,16 @@ function Execute-DeployAction {
|
|||||||
$result = Deploy-TelegramBot
|
$result = Deploy-TelegramBot
|
||||||
$result # Explicitly output the boolean
|
$result # Explicitly output the boolean
|
||||||
}
|
}
|
||||||
|
"DataEntry" {
|
||||||
|
$result = Deploy-DataEntry
|
||||||
|
$result # Explicitly output the boolean
|
||||||
|
}
|
||||||
"All" {
|
"All" {
|
||||||
$backendOk = Deploy-Backend
|
$backendOk = Deploy-Backend
|
||||||
$telegramOk = Deploy-TelegramBot
|
$telegramOk = Deploy-TelegramBot
|
||||||
|
$dataEntryOk = Deploy-DataEntry
|
||||||
# Return combined result
|
# Return combined result
|
||||||
($backendOk -and $telegramOk)
|
($backendOk -and $telegramOk -and $dataEntryOk)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1695,7 +2324,7 @@ function Show-AllStatus {
|
|||||||
Write-Host " ROA2WEB - System Status" -ForegroundColor Cyan
|
Write-Host " ROA2WEB - System Status" -ForegroundColor Cyan
|
||||||
Write-Host ("=" * 70) -ForegroundColor Cyan
|
Write-Host ("=" * 70) -ForegroundColor Cyan
|
||||||
|
|
||||||
Show-ServiceStatus -ComponentName "Backend" `
|
Show-ServiceStatus -ComponentName "Reports Backend" `
|
||||||
-ServiceName $Config.BackendServiceName `
|
-ServiceName $Config.BackendServiceName `
|
||||||
-HealthUrl $Config.BackendHealthUrl `
|
-HealthUrl $Config.BackendHealthUrl `
|
||||||
-HealthTimeout $Config.BackendHealthTimeout
|
-HealthTimeout $Config.BackendHealthTimeout
|
||||||
@@ -1705,6 +2334,11 @@ function Show-AllStatus {
|
|||||||
-HealthUrl $Config.TelegramBotHealthUrl `
|
-HealthUrl $Config.TelegramBotHealthUrl `
|
||||||
-HealthTimeout $Config.TelegramBotHealthTimeout
|
-HealthTimeout $Config.TelegramBotHealthTimeout
|
||||||
|
|
||||||
|
Show-ServiceStatus -ComponentName "Data Entry" `
|
||||||
|
-ServiceName $Config.DataEntryServiceName `
|
||||||
|
-HealthUrl $Config.DataEntryHealthUrl `
|
||||||
|
-HealthTimeout $Config.DataEntryHealthTimeout
|
||||||
|
|
||||||
Write-Host "`n" + ("=" * 70) -ForegroundColor Cyan
|
Write-Host "`n" + ("=" * 70) -ForegroundColor Cyan
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1722,10 +2356,14 @@ function Main {
|
|||||||
$success = switch ($Action) {
|
$success = switch ($Action) {
|
||||||
"DeployBackend" { Execute-DeployAction -Component "Backend" }
|
"DeployBackend" { Execute-DeployAction -Component "Backend" }
|
||||||
"DeployTelegramBot" { Execute-DeployAction -Component "TelegramBot" }
|
"DeployTelegramBot" { Execute-DeployAction -Component "TelegramBot" }
|
||||||
|
"DeployDataEntry" { Execute-DeployAction -Component "DataEntry" }
|
||||||
"DeployAll" { Execute-DeployAction -Component "All" }
|
"DeployAll" { Execute-DeployAction -Component "All" }
|
||||||
"StartAll" { Execute-ManageAction -Action "Start" -Component "All"; $true }
|
"StartAll" { Execute-ManageAction -Action "Start" -Component "All"; $true }
|
||||||
"StopAll" { Execute-ManageAction -Action "Stop" -Component "All"; $true }
|
"StopAll" { Execute-ManageAction -Action "Stop" -Component "All"; $true }
|
||||||
"RestartAll" { Execute-ManageAction -Action "Restart" -Component "All"; $true }
|
"RestartAll" { Execute-ManageAction -Action "Restart" -Component "All"; $true }
|
||||||
|
"StartDataEntry" { Execute-ManageAction -Action "Start" -Component "DataEntry"; $true }
|
||||||
|
"StopDataEntry" { Execute-ManageAction -Action "Stop" -Component "DataEntry"; $true }
|
||||||
|
"RestartDataEntry" { Execute-ManageAction -Action "Restart" -Component "DataEntry"; $true }
|
||||||
"Status" { Show-AllStatus; $true }
|
"Status" { Show-AllStatus; $true }
|
||||||
default { $false }
|
default { $false }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,5 +20,33 @@
|
|||||||
"deployment": {
|
"deployment": {
|
||||||
"autoDeployEnabled": true,
|
"autoDeployEnabled": true,
|
||||||
"checkIntervalMinutes": 5
|
"checkIntervalMinutes": 5
|
||||||
|
},
|
||||||
|
"paths": {
|
||||||
|
"installRoot": "C:\\inetpub\\wwwroot\\roa2web",
|
||||||
|
"reportsBackend": "C:\\inetpub\\wwwroot\\roa2web\\backend",
|
||||||
|
"reportsFrontend": "C:\\inetpub\\wwwroot\\roa2web\\frontend",
|
||||||
|
"telegramBot": "C:\\inetpub\\wwwroot\\roa2web\\telegram-bot",
|
||||||
|
"dataEntryBackend": "C:\\inetpub\\wwwroot\\roa2web\\data-entry-backend",
|
||||||
|
"dataEntryFrontend": "C:\\inetpub\\wwwroot\\roa2web\\data-entry-frontend",
|
||||||
|
"shared": "C:\\inetpub\\wwwroot\\roa2web\\shared",
|
||||||
|
"logs": "C:\\inetpub\\wwwroot\\roa2web\\logs",
|
||||||
|
"backups": "C:\\inetpub\\wwwroot\\roa2web\\backups"
|
||||||
|
},
|
||||||
|
"services": {
|
||||||
|
"reportsBackend": {
|
||||||
|
"name": "ROA2WEB-Backend",
|
||||||
|
"displayName": "ROA2WEB Reports Backend API",
|
||||||
|
"port": 8000
|
||||||
|
},
|
||||||
|
"telegramBot": {
|
||||||
|
"name": "ROA2WEB-TelegramBot",
|
||||||
|
"displayName": "ROA2WEB Telegram Bot",
|
||||||
|
"port": 8002
|
||||||
|
},
|
||||||
|
"dataEntry": {
|
||||||
|
"name": "ROA2WEB-DataEntry",
|
||||||
|
"displayName": "ROA2WEB Data Entry API",
|
||||||
|
"port": 8003
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user