242 lines
8.5 KiB
Python
242 lines
8.5 KiB
Python
from typing import Any, Dict, List, Optional
|
|
|
|
from fastapi import APIRouter, Body, Depends, Request
|
|
from sqlalchemy.orm import Session
|
|
|
|
from adapters.db.session import get_db
|
|
from app.core.auth_dependency import get_current_user, AuthContext
|
|
from app.core.permissions import require_business_access
|
|
from app.core.responses import ApiError, success_response
|
|
from app.services.report_template_service import ReportTemplateService
|
|
|
|
router = APIRouter(prefix="/report-templates", tags=["report-templates"])
|
|
|
|
|
|
@router.get(
|
|
"/business/{business_id}",
|
|
summary="لیست قالبهای گزارش",
|
|
description="لیست قالبها با امکان فیلتر بر اساس ماژول و زیرنوع. کاربران عادی فقط Published را میبینند.",
|
|
)
|
|
@require_business_access("business_id")
|
|
async def list_report_templates(
|
|
request: Request,
|
|
business_id: int,
|
|
module_key: Optional[str] = None,
|
|
subtype: Optional[str] = None,
|
|
status: Optional[str] = None,
|
|
ctx: AuthContext = Depends(get_current_user),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
only_published = True
|
|
# فقط کسانی که write در report_templates دارند، میتوانند پیشنویسها را ببینند
|
|
if ctx.can_write_section("report_templates"):
|
|
only_published = False
|
|
templates = ReportTemplateService.list_templates(
|
|
db=db,
|
|
business_id=business_id,
|
|
module_key=module_key,
|
|
subtype=subtype,
|
|
status=status,
|
|
only_published=only_published,
|
|
)
|
|
data: List[Dict[str, Any]] = []
|
|
for t in templates:
|
|
data.append({
|
|
"id": t.id,
|
|
"business_id": t.business_id,
|
|
"module_key": t.module_key,
|
|
"subtype": t.subtype,
|
|
"name": t.name,
|
|
"description": t.description,
|
|
"status": t.status,
|
|
"is_default": t.is_default,
|
|
"version": t.version,
|
|
"paper_size": t.paper_size,
|
|
"orientation": t.orientation,
|
|
"margins": t.margins,
|
|
"updated_at": t.updated_at.isoformat() if t.updated_at else None,
|
|
})
|
|
return {"items": data}
|
|
|
|
|
|
@router.get(
|
|
"/{template_id}/business/{business_id}",
|
|
summary="جزئیات یک قالب گزارش (فقط سازندگان)",
|
|
description="اطلاعات کامل قالب شامل محتوا برای ویرایشگر",
|
|
)
|
|
@require_business_access("business_id")
|
|
async def get_report_template(
|
|
request: Request,
|
|
template_id: int,
|
|
business_id: int,
|
|
ctx: AuthContext = Depends(get_current_user),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
if not ctx.can_write_section("report_templates"):
|
|
raise ApiError("FORBIDDEN", "Missing permission: report_templates.write", http_status=403)
|
|
entity = ReportTemplateService.get_template(db=db, template_id=template_id, business_id=business_id)
|
|
if not entity:
|
|
raise ApiError("NOT_FOUND", "Template not found", http_status=404)
|
|
return {
|
|
"id": entity.id,
|
|
"business_id": entity.business_id,
|
|
"module_key": entity.module_key,
|
|
"subtype": entity.subtype,
|
|
"name": entity.name,
|
|
"description": entity.description,
|
|
"engine": entity.engine,
|
|
"status": entity.status,
|
|
"is_default": entity.is_default,
|
|
"version": entity.version,
|
|
"content_html": entity.content_html,
|
|
"content_css": entity.content_css,
|
|
"header_html": entity.header_html,
|
|
"footer_html": entity.footer_html,
|
|
"paper_size": entity.paper_size,
|
|
"orientation": entity.orientation,
|
|
"margins": entity.margins,
|
|
"assets": entity.assets,
|
|
"created_by": entity.created_by,
|
|
"created_at": entity.created_at.isoformat() if entity.created_at else None,
|
|
"updated_at": entity.updated_at.isoformat() if entity.updated_at else None,
|
|
}
|
|
|
|
|
|
@router.post(
|
|
"/business/{business_id}",
|
|
summary="ایجاد قالب جدید (فقط سازندگان)",
|
|
)
|
|
@require_business_access("business_id")
|
|
async def create_report_template(
|
|
request: Request,
|
|
business_id: int,
|
|
body: Dict[str, Any] = Body(...),
|
|
ctx: AuthContext = Depends(get_current_user),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
if not ctx.can_write_section("report_templates"):
|
|
raise ApiError("FORBIDDEN", "Missing permission: report_templates.write", http_status=403)
|
|
body = dict(body or {})
|
|
body["business_id"] = business_id
|
|
entity = ReportTemplateService.create_template(db=db, data=body, user_id=ctx.get_user_id())
|
|
return {"id": entity.id}
|
|
|
|
|
|
@router.put(
|
|
"/{template_id}/business/{business_id}",
|
|
summary="ویرایش قالب (فقط سازندگان)",
|
|
)
|
|
@require_business_access("business_id")
|
|
async def update_report_template(
|
|
request: Request,
|
|
template_id: int,
|
|
business_id: int,
|
|
body: Dict[str, Any] = Body(...),
|
|
ctx: AuthContext = Depends(get_current_user),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
if not ctx.can_write_section("report_templates"):
|
|
raise ApiError("FORBIDDEN", "Missing permission: report_templates.write", http_status=403)
|
|
entity = ReportTemplateService.update_template(db=db, template_id=template_id, data=body or {}, business_id=business_id)
|
|
return {"id": entity.id, "version": entity.version}
|
|
|
|
|
|
@router.delete(
|
|
"/{template_id}/business/{business_id}",
|
|
summary="حذف قالب (فقط سازندگان)",
|
|
)
|
|
@require_business_access("business_id")
|
|
async def delete_report_template(
|
|
request: Request,
|
|
template_id: int,
|
|
business_id: int,
|
|
ctx: AuthContext = Depends(get_current_user),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
if not ctx.can_write_section("report_templates"):
|
|
raise ApiError("FORBIDDEN", "Missing permission: report_templates.write", http_status=403)
|
|
ReportTemplateService.delete_template(db=db, template_id=template_id, business_id=business_id)
|
|
return success_response(data={"deleted": True}, request=request, message="Deleted")
|
|
|
|
|
|
@router.post(
|
|
"/{template_id}/business/{business_id}/publish",
|
|
summary="انتشار/بازگشت به پیشنویس (فقط سازندگان)",
|
|
)
|
|
@require_business_access("business_id")
|
|
async def publish_report_template(
|
|
request: Request,
|
|
template_id: int,
|
|
business_id: int,
|
|
body: Dict[str, Any] = Body(...),
|
|
ctx: AuthContext = Depends(get_current_user),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
if not ctx.can_write_section("report_templates"):
|
|
raise ApiError("FORBIDDEN", "Missing permission: report_templates.write", http_status=403)
|
|
is_published = bool((body or {}).get("published", True))
|
|
entity = ReportTemplateService.publish_template(db=db, template_id=template_id, business_id=business_id, is_published=is_published)
|
|
return {"id": entity.id, "status": entity.status}
|
|
|
|
|
|
@router.post(
|
|
"/business/{business_id}/set-default",
|
|
summary="تنظیم قالب پیشفرض یک ماژول/زیرنوع (فقط سازندگان)",
|
|
)
|
|
@require_business_access("business_id")
|
|
async def set_default_template(
|
|
request: Request,
|
|
business_id: int,
|
|
body: Dict[str, Any] = Body(...),
|
|
ctx: AuthContext = Depends(get_current_user),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
if not ctx.can_write_section("report_templates"):
|
|
raise ApiError("FORBIDDEN", "Missing permission: report_templates.write", http_status=403)
|
|
module_key = str((body or {}).get("module_key") or "")
|
|
if not module_key:
|
|
raise ApiError("VALIDATION_ERROR", "module_key is required", http_status=400)
|
|
subtype = (body or {}).get("subtype")
|
|
template_id = int((body or {}).get("template_id") or 0)
|
|
if template_id <= 0:
|
|
raise ApiError("VALIDATION_ERROR", "template_id is required", http_status=400)
|
|
entity = ReportTemplateService.set_default(
|
|
db=db,
|
|
business_id=business_id,
|
|
module_key=module_key,
|
|
subtype=(str(subtype) if subtype is not None else None),
|
|
template_id=template_id,
|
|
)
|
|
return {"id": entity.id, "is_default": entity.is_default}
|
|
|
|
|
|
@router.post(
|
|
"/business/{business_id}/preview",
|
|
summary="پیشنمایش قالب (فقط سازندگان)",
|
|
description="بدون ذخیرهسازی؛ HTML/CSS ارسالی با داده نمونه رندر و به PDF تبدیل میشود.",
|
|
)
|
|
@require_business_access("business_id")
|
|
async def preview_report_template(
|
|
request: Request,
|
|
business_id: int,
|
|
body: Dict[str, Any] = Body(...),
|
|
ctx: AuthContext = Depends(get_current_user),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
from weasyprint import HTML
|
|
from weasyprint.text.fonts import FontConfiguration
|
|
if not ctx.can_write_section("report_templates"):
|
|
raise ApiError("FORBIDDEN", "Missing permission: report_templates.write", http_status=403)
|
|
content_html = (body or {}).get("content_html") or ""
|
|
content_css = (body or {}).get("content_css") or ""
|
|
context = (body or {}).get("context") or {}
|
|
temp = type("T", (), {"content_html": content_html, "content_css": content_css})() # شیء موقت شبیه ReportTemplate
|
|
html = ReportTemplateService.render_with_template(temp, context)
|
|
pdf_bytes = HTML(string=html).write_pdf(font_config=FontConfiguration())
|
|
return {
|
|
"content_length": len(pdf_bytes),
|
|
"ok": True,
|
|
}
|
|
|
|
|