152 lines
5.4 KiB
Python
152 lines
5.4 KiB
Python
from fastapi import APIRouter, Depends, HTTPException
|
||
from bson import ObjectId
|
||
from datetime import datetime
|
||
from models import DeliveryAcceptRequest, DeliverySendRequest
|
||
from db import delivery_collection, notify_collection
|
||
from auth import get_current_user
|
||
from tasks import notify_in_profile
|
||
from models import NotifyItem
|
||
|
||
|
||
router = APIRouter(prefix="/api/delivery", tags=["delivery"])
|
||
|
||
|
||
@router.post("/send")
|
||
async def send_delivery(
|
||
payload: DeliverySendRequest,
|
||
current_user: dict = Depends(get_current_user)
|
||
):
|
||
"""
|
||
Массовая отправка: создаёт новый документ для каждого выбранного item.
|
||
"""
|
||
results = []
|
||
errors = []
|
||
|
||
for entry in payload.items:
|
||
# Проверяем, что текущий пользователь — отправитель
|
||
if str(current_user["_id"]) != entry.sender:
|
||
errors.append({"item": entry.item, "error": "Не авторизован как отправитель"})
|
||
continue
|
||
|
||
# Валидация delivery_id
|
||
try:
|
||
delivery_id = ObjectId(entry.item)
|
||
except Exception:
|
||
errors.append({"item": entry.item, "error": "Неверный delivery ID"})
|
||
continue
|
||
|
||
update_data = {
|
||
"status": "Ожидает получения",
|
||
"delivery_type": payload.delivery_type,
|
||
"sent_at": datetime.utcnow(),
|
||
"updated_at": datetime.utcnow(),
|
||
}
|
||
|
||
# Добавляем трек только для СДЭК
|
||
if payload.delivery_type == "СДЭК" and payload.track:
|
||
update_data["track"] = payload.track
|
||
|
||
# Ищем существующую запись
|
||
existing = await delivery_collection.find_one(
|
||
{"_id": delivery_id, "sender._id": entry.sender},
|
||
{"_id": 0}
|
||
)
|
||
if not existing:
|
||
errors.append({"item": entry.item, "error": "Доставка не найдена или не для вас"})
|
||
continue
|
||
|
||
# Уведомление получателю
|
||
if (exhibition:=existing.get('exhibition',{})) and (exhibition_id:=existing.get('exhibition_id')):
|
||
link = f'/profile/delivery/exhibition/{exhibition_id}'
|
||
else:
|
||
link = f'/profile/delivery'
|
||
notify = await notify_in_profile(NotifyItem(
|
||
user_id=str(existing["receiver"]["_id"]),
|
||
type_item="delivery",
|
||
title="Доставка картин",
|
||
link=link,
|
||
text=f"{str(existing['sender']['username'])} — прислал вам картины."
|
||
))
|
||
|
||
new_doc = {**existing, **update_data, "notify": notify.upserted_id}
|
||
|
||
result = await delivery_collection.insert_one(new_doc)
|
||
if result.inserted_id:
|
||
# TODO: send email
|
||
results.append({
|
||
"item": entry.item,
|
||
"delivery_id": str(result.inserted_id)
|
||
})
|
||
|
||
return {
|
||
"status": "success" if not errors else "partial",
|
||
"processed": results,
|
||
"errors": errors
|
||
}
|
||
|
||
|
||
@router.post("/accept")
|
||
async def accept_delivery(
|
||
payload: DeliveryAcceptRequest,
|
||
current_user: dict = Depends(get_current_user)
|
||
):
|
||
"""
|
||
Массовое получение: создаёт новый документ со статусом 'Получено' для каждого item.
|
||
"""
|
||
results = []
|
||
errors = []
|
||
|
||
for item_id in payload.items:
|
||
try:
|
||
delivery_id = ObjectId(item_id)
|
||
except Exception:
|
||
errors.append({"item": item_id, "error": "Неверный delivery ID"})
|
||
continue
|
||
|
||
existing = await delivery_collection.find_one(
|
||
{"_id": delivery_id, "receiver._id": current_user["_id"]},
|
||
{"_id": 0}
|
||
)
|
||
if not existing:
|
||
errors.append({"item": item_id, "error": "Доставка не найдена или не для вас"})
|
||
continue
|
||
if (exhibition:=existing.get('exhibition',{})) and (exhibition_id:=existing.get('exhibition_id')):
|
||
link = f'/profile/delivery/exhibition/{exhibition_id}'
|
||
else:
|
||
link = f'/profile/delivery'
|
||
# Уведомление отправителю
|
||
notify = await notify_in_profile(NotifyItem(
|
||
user_id=str(existing["sender"]["_id"]),
|
||
type_item="delivery",
|
||
title="Доставка картин",
|
||
link=link,
|
||
text=f"Картина «{existing['title']}» получена — {str(existing['receiver']['username'])}."
|
||
))
|
||
|
||
new_doc = {
|
||
**existing,
|
||
"status": "Получено",
|
||
"notify": notify.upserted_id,
|
||
"received_at": datetime.utcnow(),
|
||
"updated_at": datetime.utcnow(),
|
||
}
|
||
|
||
result = await delivery_collection.insert_one(new_doc)
|
||
|
||
# Помечаем предыдущее уведомление как непрочитанное (если нужно)
|
||
if existing.get("notify"):
|
||
await notify_collection.update_one(
|
||
{"_id": existing["notify"]},
|
||
{"$set": {"read": False}}
|
||
)
|
||
|
||
results.append({
|
||
"item": item_id,
|
||
"delivery_id": str(result.inserted_id)
|
||
})
|
||
|
||
return {
|
||
"status": "success" if not errors else "partial",
|
||
"processed": results,
|
||
"errors": errors
|
||
} |