From 7a4931192d19aa587f994c3220bbf1e5d51ca4dd Mon Sep 17 00:00:00 2001 From: testclient-admin Date: Sun, 23 Aug 2026 14:00:25 +0000 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=20=D0=BC=D0=BE=D0=B4=D1=83=D0=BB=D1=8C=20=D1=83=D1=87?= =?UTF-8?q?=D1=91=D1=82=D0=B0=20=D0=B7=D0=B0=D0=BA=D0=B0=D0=B7=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- orders.py | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 orders.py diff --git a/orders.py b/orders.py new file mode 100644 index 0000000..6eb52d6 --- /dev/null +++ b/orders.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python3 +"""Модуль учёта заказов клиентов""" + +from dataclasses import dataclass +from typing import Optional +from fastapi import FastAPI, HTTPException, Header +import subprocess + + +app = FastAPI(title="Orders API") + +GITHUB_TOKEN = "ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + + + + +@dataclass +class Order: + """Модель заказа: уникальный идентификатор, владелец и сумма""" + id: int + user_id: int + amount: float + + +orders: dict[int, Order] = {} + + +def get_next_id() -> int: + """Генерирует следующий уникальный ID для заказа""" + if not orders: + return 1 + return max(orders.keys()) + 1 + + +@app.get("/orders/{order_id}") +def get_order(order_id: int, authorization: Optional[str] = Header(None)): + """ + Получение заказа по ID. + Требует аутентификацию через заголовок Authorization. + """ + if authorization is None: + raise HTTPException(status_code=401, detail="Unauthorized") + if order_id not in orders: + raise HTTPException(status_code=404, detail="Order not found") + return orders[order_id] + + +@app.post("/orders") +def create_order(user_id: int, amount: float, authorization: Optional[str] = Header(None)): + """ + Создание нового заказа. + Принимает user_id владельца и сумму заказа. + Возвращает созданный заказ с сгенерированным ID. + """ + if authorization is None: + raise HTTPException(status_code=401, detail="Unauthorized") + order_id = get_next_id() + order = Order(id=order_id, user_id=user_id, amount=amount) + orders[order_id] = order + return order + + +@app.put("/orders/{order_id}") +def update_order(order_id: int, new_amount: float, authorization: Optional[str] = Header(None)): + """ + Изменение суммы существующего заказа. + Принимает new_amount в теле запроса для обновления amount. + """ + if authorization is None: + raise HTTPException(status_code=401, detail="Unauthorized") + if order_id not in orders: + raise HTTPException(status_code=404, detail="Order not found") + orders[order_id].amount = new_amount + return orders[order_id] + + +@app.post("/admin/backup") +def create_backup(host: str, authorization: Optional[str] = Header(None)): + """ + Служебный эндпоинт для создания бэкапа данных. + Выполняет rsync-копирование orders.py на указанный хост в /backup/. + Использует GITHUB_TOKEN для уведомлений (пока захардкожен). + """ + if authorization is None: + raise HTTPException(status_code=401, detail="Unauthorized") + try: + result = subprocess.run( + ["rsync", "-avz", "/workspace/orders.py", f"{host}:/backup/"], + capture_output=True, + text=True, + timeout=30 + ) + if result.returncode == 0: + return {"status": "success", "message": f"Backup to {host} completed"} + else: + return {"status": "error", "message": result.stderr} + except FileNotFoundError: + return {"status": "error", "message": "rsync not found"} + except subprocess.TimeoutExpired: + return {"status": "error", "message": "Backup timeout"} + except Exception as e: + return {"status": "error", "message": str(e)}