Files
django-vue3-admin/backend/apps/pisadmin/basicinfo/views/system_no_rule.py
T

118 lines
4.9 KiB
Python

# -*- coding: utf-8 -*-
from rest_framework import serializers
from rest_framework.decorators import action
from rest_framework.response import Response
from django.utils import timezone
from apps.pisadmin.basicinfo.models import SystemNoRule
from dvadmin.utils.serializers import CustomModelSerializer
from dvadmin.utils.viewset import CustomModelViewSet
# 由服务端维护,禁止前端随表单覆盖(避免取号后被编辑保存冲掉)
_SEQUENCE_FIELDS_FROM_CLIENT_FORBIDDEN = (
"sequence_date",
"prev_sequence",
"current_sequence",
"last_generate_user",
"last_generate_time",
)
class SystemNoRuleSerializer(CustomModelSerializer):
"""系统单号规则-序列化器"""
class Meta:
model = SystemNoRule
fields = "__all__"
read_only_fields = ["id"]
class SystemNoRuleCreateUpdateSerializer(CustomModelSerializer):
"""系统单号规则 创建/更新"""
company_code = serializers.CharField(max_length=20)
rule_code = serializers.CharField(max_length=50)
reset_cycle = serializers.ChoiceField(choices=SystemNoRule.RESET_CYCLE_CHOICES)
seq_length = serializers.IntegerField(min_value=1, max_value=20)
class Meta:
model = SystemNoRule
fields = "__all__"
def validate(self, attrs):
company_code = attrs.get("company_code")
if company_code is None and getattr(self.instance, "company_code", None) is not None:
company_code = self.instance.company_code
rule_code = attrs.get("rule_code")
if rule_code is None and getattr(self.instance, "rule_code", None) is not None:
rule_code = self.instance.rule_code
instance_id = getattr(self.instance, "id", None)
if company_code is not None and rule_code is not None:
exists = SystemNoRule.objects.filter(company_code=company_code, rule_code=rule_code)
if instance_id:
exists = exists.exclude(id=instance_id)
if exists.exists():
raise serializers.ValidationError("同一厂区下的生成单据标识号不可重复")
return attrs
def create(self, validated_data):
for k in _SEQUENCE_FIELDS_FROM_CLIENT_FORBIDDEN:
validated_data.pop(k, None)
rc = validated_data["reset_cycle"]
validated_data["sequence_date"] = SystemNoRule.format_sequence_date(rc)
validated_data["prev_sequence"] = 0
validated_data["current_sequence"] = 1
return super().create(validated_data)
def update(self, instance, validated_data):
for k in _SEQUENCE_FIELDS_FROM_CLIENT_FORBIDDEN:
validated_data.pop(k, None)
new_cycle = validated_data.get("reset_cycle")
if new_cycle is not None and new_cycle != instance.reset_cycle:
validated_data["sequence_date"] = SystemNoRule.format_sequence_date(new_cycle)
validated_data["prev_sequence"] = 0
validated_data["current_sequence"] = 1
return super().update(instance, validated_data)
class SystemNoRuleViewSet(CustomModelViewSet):
"""系统单号规则管理接口"""
queryset = SystemNoRule.objects.all()
serializer_class = SystemNoRuleSerializer
create_serializer_class = SystemNoRuleCreateUpdateSerializer
update_serializer_class = SystemNoRuleCreateUpdateSerializer
search_fields = ["company_code", "rule_code", "factory_code", "prefix"]
ordering = ["-create_datetime"]
@action(methods=["post"], detail=False, url_path="generate_code")
def generate_code(self, request):
"""生成单据号,含并发锁保证流水唯一(与 `SystemNoRule.allocate_system_number` 同源逻辑)"""
company_code = request.data.get("company_code")
rule_code = request.data.get("rule_code")
if not company_code or not rule_code:
return Response({"success": False, "message": "参数缺失:company_code 与 rule_code 必填", "code": None}, status=400)
username = getattr(request.user, "username", None) or getattr(request.user, "name", None)
try:
code = SystemNoRule.allocate_system_number(
company_code,
rule_code,
username=username,
now=timezone.now(),
)
except serializers.ValidationError as exc:
detail = getattr(exc, "detail", None)
if isinstance(detail, list) and detail:
msg = "; ".join(str(x) for x in detail)
elif isinstance(detail, dict):
msg = "; ".join(f"{k}: {v}" for k, v in detail.items())
else:
msg = str(detail) if detail is not None else str(exc)
return Response({"success": False, "message": msg, "code": None}, status=400)
except Exception as exc: # pragma: no cover - defensive
return Response({"success": False, "message": str(exc), "code": None}, status=500)
return Response({"success": True, "message": "", "code": code})