Notify moderators about service center applications

This commit is contained in:
VPN SaaS Dev
2026-05-15 04:45:54 +09:00
parent c0014ab4ea
commit 85b46a94b9
4 changed files with 65 additions and 17 deletions

View File

@@ -1,12 +1,10 @@
from datetime import UTC, datetime from datetime import UTC, datetime
import httpx
from fastapi import APIRouter, Depends, HTTPException from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy import select from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.ext.asyncio import AsyncSession
from app.api.deps import get_current_telegram_user, log_audit, require_platform_role from app.api.deps import get_current_telegram_user, log_audit, require_platform_role
from app.core.config import settings
from app.db.session import get_session from app.db.session import get_session
from app.models.car import ( from app.models.car import (
AuditLog, AuditLog,
@@ -17,6 +15,7 @@ from app.models.car import (
) )
from app.models.user import User from app.models.user import User
from app.schemas.service_center import AdminModerationDecision, ServiceCenterRead, ServiceVisitRead from app.schemas.service_center import AdminModerationDecision, ServiceCenterRead, ServiceVisitRead
from app.services.notifications import notify_user
router = APIRouter(prefix="/admin", tags=["admin"]) router = APIRouter(prefix="/admin", tags=["admin"])
@@ -261,16 +260,3 @@ async def ensure_owner_employee(session: AsyncSession, service_center_id: int, o
else: else:
employee.role = "owner" employee.role = "owner"
employee.status = "active" employee.status = "active"
async def notify_user(user: User, text: str) -> None:
if not settings.bot_token:
return
try:
async with httpx.AsyncClient(timeout=5) as client:
await client.post(
f"https://api.telegram.org/bot{settings.bot_token}/sendMessage",
data={"chat_id": str(user.telegram_id), "text": text},
)
except Exception:
return

View File

@@ -46,6 +46,7 @@ from app.schemas.service_center import (
VehicleSearchRequest, VehicleSearchRequest,
VehicleSearchResult, VehicleSearchResult,
) )
from app.services.notifications import notify_platform_moderators
from app.services.odometer import validate_odometer_change from app.services.odometer import validate_odometer_change
from app.services.vehicle_identity import mask_license_plate, mask_vin from app.services.vehicle_identity import mask_license_plate, mask_vin
@@ -101,9 +102,19 @@ async def create_service_center(
status="active", status="active",
) )
session.add(employee) session.add(employee)
await log_audit(session, actor=current_user, action="service_center.create", target_type="service_center", target_id=center.id) await log_audit(
session,
actor=current_user,
action="service_center.create",
target_type="service_center",
target_id=center.id,
)
await session.commit() await session.commit()
await session.refresh(center) await session.refresh(center)
await notify_platform_moderators(
session,
f"Новая заявка СТО #{center.id}: {center.display_name or center.name}. Откройте /admin_sto_pending для модерации.",
)
return center return center

View File

@@ -0,0 +1,27 @@
import httpx
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from app.core.config import settings
from app.models.user import User
MODERATOR_ROLES = {"admin", "verifier", "moderator"}
async def notify_user(user: User, text: str) -> None:
if not settings.bot_token or settings.app_env == "test":
return
try:
async with httpx.AsyncClient(timeout=5) as client:
await client.post(
f"https://api.telegram.org/bot{settings.bot_token}/sendMessage",
data={"chat_id": str(user.telegram_id), "text": text},
)
except Exception:
return
async def notify_platform_moderators(session: AsyncSession, text: str) -> None:
result = await session.execute(select(User).where(User.platform_role.in_(MODERATOR_ROLES)))
for user in result.scalars():
await notify_user(user, text)

View File

@@ -14,11 +14,12 @@ async def test_license_plate_can_be_saved_and_edited(client, auth_headers) -> No
updated = await client.patch( updated = await client.patch(
f"/api/cars/{car['id']}", f"/api/cars/{car['id']}",
headers=auth_headers, headers=auth_headers,
json={"plate_number": "34 나 7890"}, json={"plate_number": "34 나 7890", "body_type": "SUV"},
) )
assert updated.status_code == 200 assert updated.status_code == 200
assert updated.json()["plate_number"] == "34 나 7890" assert updated.json()["plate_number"] == "34 나 7890"
assert updated.json()["body_type"] == "SUV"
@pytest.mark.asyncio @pytest.mark.asyncio
@@ -312,3 +313,26 @@ async def test_admin_request_changes_keeps_application_visible_to_moderation(
assert response.status_code == 200 assert response.status_code == 200
assert response.json()["verification_status"] == "needs_changes" assert response.json()["verification_status"] == "needs_changes"
@pytest.mark.asyncio
async def test_service_center_application_is_visible_to_moderators(
client, auth_headers, admin_auth_headers, internal_headers
) -> None:
center = (
await client.post(
"/api/service-centers",
headers=auth_headers,
json={"display_name": "Pending Review Service", "country": "KR"},
)
).json()
await client.post(
"/api/users",
headers=internal_headers,
json={"telegram_id": 9001, "platform_role": "moderator"},
)
pending = await client.get("/api/admin/service-centers/pending", headers=admin_auth_headers)
assert pending.status_code == 200
assert center["id"] in [item["id"] for item in pending.json()]