feat: initialize full-stack architecture with backend routes, database schema, and glassmorphic frontend UI
This commit is contained in:
@@ -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 ----------
|
||||
|
||||
Reference in New Issue
Block a user