102 lines
3.8 KiB
Python
102 lines
3.8 KiB
Python
"""打印中心 async ViewSets。
|
||
|
||
- PrintTemplateViewSet:模板 CRUD
|
||
- PrintSettingsViewSet:抬头读取/更新(单例)
|
||
- render_document_view:渲染整页打印 HTML(前端 axios 取回后 window.print())
|
||
"""
|
||
|
||
from asgiref.sync import sync_to_async
|
||
from adrf.decorators import api_view
|
||
from rest_framework import status
|
||
from rest_framework.response import Response
|
||
from rest_framework.exceptions import ValidationError, NotFound
|
||
|
||
from apps.core.viewset import BaseTenantViewSet
|
||
from .models import PrintSettings, PrintTemplate
|
||
from .serializers import PrintSettingsSerializer, PrintTemplateSerializer
|
||
from . import services as printing_services
|
||
|
||
|
||
class PrintTemplateViewSet(BaseTenantViewSet):
|
||
model = PrintTemplate
|
||
serializer_class = PrintTemplateSerializer
|
||
search_fields = ["code", "name", "doc_type"]
|
||
|
||
|
||
@api_view(["GET", "PUT", "PATCH"])
|
||
async def print_settings_detail(request):
|
||
"""打印抬头:租户单例。GET 读取 / PUT(整更) / PATCH(部分更)。"""
|
||
from apps.core.viewset import resolve_tenant
|
||
|
||
def _resolve():
|
||
return resolve_tenant(request.META.get("HTTP_X_TENANT_ID", ""))
|
||
|
||
tenant = await sync_to_async(_resolve)()
|
||
if tenant is None:
|
||
raise ValidationError({"tenant": "无法识别租户"})
|
||
obj = await sync_to_async(printing_services.ensure_settings)(tenant)
|
||
|
||
if request.method == "GET":
|
||
serializer = PrintSettingsSerializer(obj)
|
||
data = await serializer.adata if hasattr(serializer, "adata") else serializer.data
|
||
return Response(serializer.data)
|
||
|
||
partial = request.method == "PATCH"
|
||
serializer = PrintSettingsSerializer(obj, data=request.data, partial=partial)
|
||
await sync_to_async(serializer.is_valid)(raise_exception=True)
|
||
await sync_to_async(serializer.save)(
|
||
updated_by=request.user if request.user.is_authenticated else None
|
||
)
|
||
return Response(serializer.data)
|
||
|
||
|
||
@api_view(["GET"])
|
||
async def render_document_view(request, doc_type, document_id):
|
||
"""GET /api/v1/printing/render/<doc_type>/<id>/?template=code&autoprint=0
|
||
|
||
返回整页 HTML(Content-Type: text/html)。鉴权走 JWT + 租户中间件。
|
||
"""
|
||
from django.http import HttpResponse
|
||
|
||
from apps.core.viewset import resolve_tenant
|
||
|
||
if doc_type not in printing_services.DOC_CONTEXT_BUILDERS:
|
||
raise ValidationError({"doc_type": f"不支持的文档类型 {doc_type}"})
|
||
|
||
def _resolve():
|
||
code = request.META.get("HTTP_X_TENANT_ID", "")
|
||
return resolve_tenant(code)
|
||
|
||
tenant = await sync_to_async(_resolve)()
|
||
if tenant is None:
|
||
raise ValidationError({"tenant": "无法识别租户"})
|
||
|
||
module_name, model_name, _ = printing_services.DOC_CONTEXT_BUILDERS[doc_type]
|
||
model = getattr(__import__(module_name, fromlist=[model_name]), model_name)
|
||
|
||
def _load_doc():
|
||
qs = model.objects.filter(tenant=tenant, pk=document_id)
|
||
if doc_type == "sales_bill":
|
||
return qs.select_related(
|
||
"customer", "warehouse",
|
||
).prefetch_related(
|
||
"lines__product__base_unit", "lines__source_unit",
|
||
).first()
|
||
return qs.select_related(
|
||
"supplier", "warehouse",
|
||
).prefetch_related(
|
||
"lines__product__base_unit", "lines__source_unit",
|
||
).first()
|
||
|
||
document = await sync_to_async(_load_doc)()
|
||
if document is None:
|
||
raise NotFound("document not found")
|
||
|
||
template_code = request.GET.get("template", "") or ""
|
||
autoprint = request.GET.get("autoprint", "1") not in ("0", "false", "False")
|
||
html_out = await sync_to_async(printing_services.render_document)(
|
||
tenant=tenant, doc_type=doc_type, document=document,
|
||
template_code=template_code, autoprint=autoprint,
|
||
)
|
||
return HttpResponse(html_out, content_type="text/html; charset=utf-8")
|