feat: initialize full-stack architecture with backend routes, database schema, and glassmorphic frontend UI

This commit is contained in:
2026-05-13 00:12:19 +03:00
parent bd73f18d5c
commit 0732acbda5
21 changed files with 1937 additions and 307 deletions

View File

@@ -27,6 +27,30 @@ def serialize_case(row):
@cases_blueprint.route('/cases', methods=['GET'])
@token_required
def list_cases(current_user_id):
"""
Получить список всех кейсов пользователя
---
tags:
- Cases
security:
- APIKeyHeader: []
parameters:
- name: article
in: query
type: string
description: Фильтр по артикулу
- name: status
in: query
type: string
description: Фильтр по статусу
- name: platform
in: query
type: string
description: Фильтр по площадке
responses:
200:
description: Список кейсов
"""
# optional filters: ?article=...&status=...&platform=...
article = request.args.get('article')
status = request.args.get('status')
@@ -56,13 +80,55 @@ def list_cases(current_user_id):
@cases_blueprint.route('/cases', methods=['POST'])
@token_required
def create_case(current_user_id):
"""
Создать новый кейс
---
tags:
- Cases
security:
- APIKeyHeader: []
parameters:
- name: body
in: body
required: true
schema:
type: object
required: [platform, violator_url, violator_article]
properties:
platform:
type: string
violator_url:
type: string
violator_article:
type: string
my_article:
type: string
comment:
type: string
responses:
201:
description: Кейс создан
"""
data = request.json
required = ["platform", "violator_url", "violator_article"]
for f in required:
if f not in data:
return jsonify({"error": f"Missing field {f}"}), 400
# --- PLAN LIMIT CHECK ---
conn = get_db_connection()
cur = conn.cursor()
cur.execute("SELECT plan FROM users WHERE id = %s", (current_user_id,))
user_plan = cur.fetchone()[0]
if user_plan == 'free':
cur.execute("SELECT COUNT(*) FROM cases WHERE user_id = %s", (current_user_id,))
count = cur.fetchone()[0]
if count >= 5:
release_db_connection(conn)
return jsonify({"error": "Лимит кейсов для Free тарифа (5 шт) исчерпан. Перейдите на PRO."}), 403
# ------------------------
cur.execute(
"""INSERT INTO cases (user_id, platform, violator_url, violator_article, my_article, comment, status)
VALUES (%s, %s, %s, %s, %s, %s, %s) RETURNING id""",
@@ -79,6 +145,40 @@ def create_case(current_user_id):
case_id = cur.fetchone()[0]
conn.commit()
release_db_connection(conn)
# --- TELEGRAM NOTIFICATION ---
from ..utils.telegram_utils import send_telegram_notification
msg = (
f"🚀 <b>Новый кейс #{case_id}</b>\n"
f"Площадка: {data.get('platform').upper()}\n"
f"Артикул: {data.get('violator_article')}\n"
f"Статус: NEW"
)
send_telegram_notification(msg)
# -----------------------------
# --- AUDIT LOG ---
from ..utils.audit_utils import log_action
log_action(current_user_id, 'CREATE_CASE', {
'case_id': case_id,
'platform': data.get('platform'),
'article': data.get('violator_article')
})
# -----------------
# --- WEBSOCKET NOTIFICATION ---
try:
from ..app import socketio
socketio.emit('case_created', {
'id': case_id,
'platform': data.get('platform'),
'article': data.get('violator_article'),
'message': f"Новый кейс на {data.get('platform').upper()} создан!"
})
except Exception as e:
print(f"WS Emit Error: {e}")
# ------------------------------
return jsonify({"id": case_id}), 201
@cases_blueprint.route('/cases/<int:case_id>', methods=['GET'])
@@ -123,6 +223,12 @@ def delete_case(current_user_id, case_id):
cur.execute("DELETE FROM cases WHERE id = %s AND user_id = %s", (case_id, current_user_id))
conn.commit()
release_db_connection(conn)
# --- AUDIT LOG ---
from ..utils.audit_utils import log_action
log_action(current_user_id, 'DELETE_CASE', {'case_id': case_id})
# -----------------
return jsonify({"message": "Case deleted"})
# ---------- FILE UPLOAD ----------