test player_inventory

This commit is contained in:
2025-12-16 00:15:29 +05:00
parent 80a9fbe148
commit bb74dbbba7
8 changed files with 204 additions and 43 deletions

95
app/services/inventory.py Normal file
View File

@ -0,0 +1,95 @@
from datetime import datetime
from uuid import uuid4
from fastapi import HTTPException
from app.db.database import db
player_inventory_collection = db.player_inventory
marketplace_operations_collection = db.marketplace_operations
def _serialize_mongodb_doc(doc):
"""Преобразует MongoDB документ для JSON сериализации"""
if doc is None:
return None
# Добавить проверку на список
if isinstance(doc, list):
return [_serialize_mongodb_doc(item) for item in doc]
result = {}
for key, value in doc.items():
# Обработка ObjectId
if key == "_id":
result["_id"] = str(value)
continue
# Обработка ISODate
if isinstance(value, datetime):
result[key] = value.isoformat()
# Обработка вложенных словарей
elif isinstance(value, dict):
if "$date" in value:
# Это ISODate
result[key] = datetime.fromisoformat(value["$date"].replace("Z", "+00:00")).isoformat()
else:
result[key] = _serialize_mongodb_doc(value)
# Обработка списков
elif isinstance(value, list):
result[key] = [_serialize_mongodb_doc(item) if isinstance(item, dict) else item for item in value]
else:
result[key] = value
return result
class InventoryService:
async def list_items(self, username: str, server_ip: str, page: int = 1, limit: int = 20):
q = {"username": username, "server_ip": server_ip, "status": {"$in": ["stored", "withdrawing"]}}
skip = max(page - 1, 0) * limit
items = await player_inventory_collection.find(q) \
.sort("created_at", -1) \
.skip(skip) \
.limit(limit) \
.to_list(length=limit)
serialized_items = _serialize_mongodb_doc(items)
total = await player_inventory_collection.count_documents(q)
return {"items": serialized_items, "page": page, "limit": limit, "total": total}
async def withdraw_item(self, username: str, item_id: str, server_ip: str):
item = await player_inventory_collection.find_one({"id": item_id})
if not item:
raise HTTPException(status_code=404, detail="Item not found")
if item["username"] != username:
raise HTTPException(status_code=403, detail="Not your item")
if item["server_ip"] != server_ip:
raise HTTPException(status_code=400, detail="Wrong server_ip for this item")
if item.get("status") != "stored":
raise HTTPException(status_code=400, detail="Item is not available for withdraw")
# создаём операцию выдачи НА СЕРВЕР (тип оставляем case_reward)
op_id = str(uuid4())
operation = {
"id": op_id,
"type": "case_reward",
"player_name": username,
"item_data": item["item_data"],
"server_ip": server_ip,
"status": "pending",
"created_at": datetime.utcnow(),
# важно: связка с инвентарём, чтобы confirm мог отметить delivered
"inventory_item_id": item_id,
"source": item.get("source"),
}
await marketplace_operations_collection.insert_one(operation)
# помечаем предмет как withdrawing
await player_inventory_collection.update_one(
{"id": item_id},
{"$set": {"status": "withdrawing", "withdraw_operation_id": op_id}}
)
return {"ok": True, "operation_id": op_id, "item_id": item_id}