Files

102 lines
3.8 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""打印中心 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")