Техническое Задание по calc-ref
Last modified by Mihail Opinca on 2026/08/16 09:12
Техническая документация — calc-ref
1. Назначение
Учёт импорта товаров, содержащих хладагенты, расчёт массы хладагента и CO2-эквивалента, контроль годовых квот и формирование отчётности для внутреннего использования.
2. Архитектура
Монолит: один backend-процесс отдаёт и API, и собранный фронтенд.
Браузер
| HTTPS
v
nginx (calc-ref.online) -- proxy_pass --> gunicorn (127.0.0.1:5002)
|
Flask app (app.py)
+- /api/* -> JSON API
+- /* -> dist/ (Vue SPA, статика)
|
python-oracledb (Thick Mode)
|
Oracle DB (una.md:4024, схема DIPPFRUCT)
| HTTPS
v
nginx (calc-ref.online) -- proxy_pass --> gunicorn (127.0.0.1:5002)
|
Flask app (app.py)
+- /api/* -> JSON API
+- /* -> dist/ (Vue SPA, статика)
|
python-oracledb (Thick Mode)
|
Oracle DB (una.md:4024, схема DIPPFRUCT)
- Frontend: Vue 3 (<script setup>), Vue Router, без Vuex/Pinia. Сборка — Vite.
- Backend: Flask 3, сессии на cookie, Oracle через python-oracledb в Thick Mode (БД — Oracle 11g, для Thin Mode слишком старая).
- БД: Oracle, схема DIPPFRUCT, таблицы с префиксом CR_*.
- Прод-инфраструктура: systemd (gunicorn) + nginx (reverse proxy + TLS через Let's Encrypt/certbot).
3. Структура репозитория
app.py, config.py - точка входа Flask, конфиг из .env
controllers/auth_controller.py - аутентификация (БД + fallback из .env)
models/ - доступ к данным, один файл на сущность
services/ - зарезервировано, пока пусто
migrate.py - вспомогательный скрипт миграций/данных
sql/ - DDL и миграции схемы (01...08)
src/ - Vue-приложение
dist/ - собранный фронтенд, генерируется npm run build
deploy/calc-ref.service - systemd-юнит (gunicorn)
deploy/push.sh - скрипт деплоя изменений на прод
docs/ - документация (этот раздел)
controllers/auth_controller.py - аутентификация (БД + fallback из .env)
models/ - доступ к данным, один файл на сущность
services/ - зарезервировано, пока пусто
migrate.py - вспомогательный скрипт миграций/данных
sql/ - DDL и миграции схемы (01...08)
src/ - Vue-приложение
dist/ - собранный фронтенд, генерируется npm run build
deploy/calc-ref.service - systemd-юнит (gunicorn)
deploy/push.sh - скрипт деплоя изменений на прод
docs/ - документация (этот раздел)
4. Backend: модели
| Файл | Отвечает за |
|---|---|
| models/database.py | Инициализация Oracle Instant Client (Thick Mode), пул соединений |
| models/user_model.py | Проверка логина/пароля (CR_USERS) |
| models/refrigerant_model.py | Справочник хладагентов: код, GWP, REQUIRES_QUOTA |
| models/product_model.py | Справочник товаров: связь с хладагентом, кг/ед., код ТНВЭД |
| models/import_doc_model.py | Документы импорта и строки: CRUD, расчёт масс/CO2, проверка квот, отчёт |
| models/quota_model.py | Годовые квоты по хладагентам (CR_QUOTAS) |
| models/tax_rate_model.py | Ставки эконалога (CR_TAX_RATES), вводятся администратором вручную |
Расчёт в документах импорта: TOTAL_KG = QUANTITY ? REFRIGERANT_KG, CO2_KG = TOTAL_KG ? GWP. Считается на backend при сохранении.
5. API
Аутентификация — сессионная cookie. @require_auth — нужен вход, @require_admin — нужна роль admin.
| Метод | Путь | Доступ | Назначение |
|---|---|---|---|
| POST | /api/auth/login | публичный | Вход по логину/паролю |
| POST | /api/auth/logout | - | Выход |
| GET | /api/auth/me | - | Текущий пользователь |
| GET | /api/refrigerants | auth | Список хладагентов |
| POST | /api/refrigerants | admin | Новый хладагент |
| PUT | /api/refrigerants/<id> | admin | Правка хладагента |
| POST | /api/refrigerants/<id>/toggle | admin | Вкл/выкл активность |
| GET | /api/products | auth | Список товаров |
| POST | /api/products | auth | Новый товар |
| PUT | /api/products/<id> | auth | Правка товара |
| POST | /api/products/<id>/toggle | auth | Вкл/выкл активность |
| GET | /api/import-docs | auth | Список документов импорта |
| GET | /api/import-docs/next-number | auth | Следующий свободный номер документа |
| POST | /api/import-docs | auth | Создать документ (черновик) |
| GET | /api/import-docs/<id> | auth | Документ + строки |
| PUT | /api/import-docs/<id> | auth | Обновить документ и строки |
| DELETE | /api/import-docs/<id> | auth | Удалить документ |
| POST | /api/import-docs/<id>/status | auth | Смена статуса, проверка квот при POSTED |
| GET | /api/quotas | auth | Квоты по году/хладагенту |
| GET | /api/quotas/years | auth | Список годов с квотами |
| POST | /api/quotas | auth | Новая квота |
| PUT | /api/quotas/<id> | auth | Правка квоты |
| DELETE | /api/quotas/<id> | auth | Удалить квоту |
| GET | /api/report | auth | Отчёт по хладагентам с фильтрами |
| GET | /api/report/excel | auth | Тот же отчёт, выгрузка в .xlsx |
| GET | /* | публичный | Отдача SPA и статики фронтенда |
6. База данных
| Таблица | Ключевые поля | Смысл |
|---|---|---|
| CR_USERS | USERNAME, PASSWORD_HASH, ROLE | Сотрудники с доступом |
| CR_REFRIGERANTS | CODE, GWP, REQUIRES_QUOTA | Справочник хладагентов |
| CR_TAX_RATES | REFRIGERANT_ID, RATE, VALID_FROM/TO | Ставки эконалога |
| CR_PRODUCTS | HAS_REFRIGERANT, REFRIGERANT_ID, REFRIGERANT_KG, TNVED_CODE | Справочник товаров |
| CR_IMPORT_DOCS | DOC_DATE, DOC_NUMBER, SUPPLIER (NOT NULL), STATUS | Заголовки документов импорта |
| CR_IMPORT_LINES | DOC_ID, PRODUCT_ID, ORIGIN_COUNTRY, QUANTITY, TOTAL_KG, CO2_KG | Строки документов |
| CR_QUOTAS | YEAR, REFRIGERANT_ID, QUOTA_KG | Годовые квоты на ввоз |
7. Аутентификация и роли
Сессия хранится на сервере (Flask session cookie). Сперва проверка по Oracle (CR_USERS), при недоступности БД — fallback на пользователей из .env. Роли: admin (полный доступ) и operator (без справочника хладагентов).
8. Деплой
- Backend: gunicorn под systemd, 2 воркера ? 4 потока, порт 127.0.0.1:5002.
2. Oracle Instant Client (Thick Mode) в /opt/oracle/instantclient_19_19, путь зарегистрирован в ldconfig.
3. nginx терминирует TLS (Let's Encrypt/certbot, автопродление), проксирует на gunicorn.
4. Frontend собирается локально (base: '/') и копируется вместе с backend-кодом.
5. Обновление — скрипт deploy/push.sh.