Initial commit: ROA2WEB - FastAPI + Vue.js + Telegram Bot

Modern ERP Reports Application with microservices architecture

Tech Stack:
- Backend: FastAPI + python-oracledb (Oracle DB integration)
- Frontend: Vue.js 3 + PrimeVue + Vite
- Telegram Bot: python-telegram-bot + SQLite
- Infrastructure: Shared database pool, JWT authentication, SSH tunnel

Features:
- FastAPI backend with async Oracle connection pool
- Vue.js 3 responsive frontend with PrimeVue components
- Telegram bot alternative interface
- Microservices architecture with shared components
- Complete deployment support (Linux Docker + Windows IIS)
- Comprehensive testing (Playwright E2E + pytest)

Repository Structure:
- reports-app/ - Main application (backend, frontend, telegram-bot)
- shared/ - Shared components (database pool, auth, utils)
- deployment/ - Deployment scripts (Linux & Windows)
- docs/ - Project documentation
- security/ - Security scanning and git hooks
This commit is contained in:
2025-10-25 14:55:08 +03:00
commit 6b13ffa183
237 changed files with 70035 additions and 0 deletions

View File

@@ -0,0 +1,37 @@
export class BasePage {
constructor(page) {
this.page = page;
}
async waitForApiResponse(url, status = 200) {
return await this.page.waitForResponse(response =>
response.url().includes(url) && response.status() === status
);
}
async waitForLoadingToFinish() {
// Wait for any loading spinners to disappear
await this.page.waitForFunction(() => {
const loadingElements = document.querySelectorAll('[data-testid="loading"], .p-progress-spinner');
return loadingElements.length === 0;
}, { timeout: 10000 });
}
async checkErrorMessage(expectedMessage) {
const errorElement = this.page.locator('.p-message-error, [data-testid="error"]');
await errorElement.waitFor({ state: 'visible', timeout: 5000 });
const actualMessage = await errorElement.textContent();
return actualMessage.includes(expectedMessage);
}
async checkSuccessMessage(expectedMessage) {
const successElement = this.page.locator('.p-message-success, [data-testid="success"]');
await successElement.waitFor({ state: 'visible', timeout: 5000 });
const actualMessage = await successElement.textContent();
return actualMessage.includes(expectedMessage);
}
async waitForNavigation() {
await this.page.waitForLoadState('networkidle');
}
}