Notify moderators about service center applications
This commit is contained in:
@@ -1,12 +1,10 @@
|
||||
from datetime import UTC, datetime
|
||||
|
||||
import httpx
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
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.models.car import (
|
||||
AuditLog,
|
||||
@@ -17,6 +15,7 @@ from app.models.car import (
|
||||
)
|
||||
from app.models.user import User
|
||||
from app.schemas.service_center import AdminModerationDecision, ServiceCenterRead, ServiceVisitRead
|
||||
from app.services.notifications import notify_user
|
||||
|
||||
router = APIRouter(prefix="/admin", tags=["admin"])
|
||||
|
||||
@@ -261,16 +260,3 @@ async def ensure_owner_employee(session: AsyncSession, service_center_id: int, o
|
||||
else:
|
||||
employee.role = "owner"
|
||||
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
|
||||
|
||||
@@ -46,6 +46,7 @@ from app.schemas.service_center import (
|
||||
VehicleSearchRequest,
|
||||
VehicleSearchResult,
|
||||
)
|
||||
from app.services.notifications import notify_platform_moderators
|
||||
from app.services.odometer import validate_odometer_change
|
||||
from app.services.vehicle_identity import mask_license_plate, mask_vin
|
||||
|
||||
@@ -101,9 +102,19 @@ async def create_service_center(
|
||||
status="active",
|
||||
)
|
||||
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.refresh(center)
|
||||
await notify_platform_moderators(
|
||||
session,
|
||||
f"Новая заявка СТО #{center.id}: {center.display_name or center.name}. Откройте /admin_sto_pending для модерации.",
|
||||
)
|
||||
return center
|
||||
|
||||
|
||||
|
||||
27
app/services/notifications.py
Normal file
27
app/services/notifications.py
Normal 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)
|
||||
@@ -14,11 +14,12 @@ async def test_license_plate_can_be_saved_and_edited(client, auth_headers) -> No
|
||||
updated = await client.patch(
|
||||
f"/api/cars/{car['id']}",
|
||||
headers=auth_headers,
|
||||
json={"plate_number": "34 나 7890"},
|
||||
json={"plate_number": "34 나 7890", "body_type": "SUV"},
|
||||
)
|
||||
|
||||
assert updated.status_code == 200
|
||||
assert updated.json()["plate_number"] == "34 나 7890"
|
||||
assert updated.json()["body_type"] == "SUV"
|
||||
|
||||
|
||||
@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.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()]
|
||||
|
||||
Reference in New Issue
Block a user