factory/apps/cm/views.py

162 lines
7.1 KiB
Python

from apps.cm.models import LableMat, LabelTemplate
from rest_framework.decorators import action
from apps.cm.serializers import TidSerializer, LabelMatSerializer, LabelTemplateSerializer, Tid2Serializer, CoderSendSerializer
from apps.cm.coder import CoderClient
from apps.inm.models import MaterialBatch, MIOItem
from apps.wpm.models import WMaterial
from rest_framework.exceptions import ParseError, NotFound
from rest_framework.response import Response
from apps.utils.viewsets import CustomGenericViewSet, RetrieveModelMixin, CustomListModelMixin, CustomModelViewSet
from apps.cm.filters import LabelTemplateFilter
# Create your views here.
SPLIT_FIELD = "#"
class LableMatViewSet(CustomListModelMixin, RetrieveModelMixin, CustomGenericViewSet):
perms_map = {"post": "*", "get": "*"}
serializer_class = LabelMatSerializer
queryset = LableMat.objects.all()
select_related_fields = ["material", "material_origin", "supplier"]
@action(methods=["post"], detail=False, serializer_class=TidSerializer)
def get_from_mb(self, request, pk=None):
"""
从仓库明细获取物料标签
从仓库明细获取物料标签
"""
tid = request.data.get("tid")
label_template = request.data.get("label_template", None)
label_template_name = request.data.get("label_template_name", None)
extra_data = request.data.get("extra_data", {})
try:
mb = MaterialBatch.objects.get(id=tid)
except MaterialBatch.DoesNotExist:
raise NotFound("仓库明细不存在")
obj, _ = LableMat.objects.get_or_create(state=mb.state, material=mb.material, batch=mb.batch, defect=mb.defect, defaults={"supplier": mb.supplier})
rdata = LabelMatSerializer(obj).data
rdata["code_label"] = f"mat{SPLIT_FIELD}{obj.id}"
if label_template or label_template_name:
tdata = {**rdata, **extra_data}
commands = LabelTemplate.gen_commands(label_template, label_template_name, tdata)
rdata["commands"] = commands
return Response(rdata)
@action(methods=["post"], detail=False, serializer_class=TidSerializer)
def get_from_wm(self, request, pk=None):
"""
从车间库存明细获取物料标签
从车间库存明细获取物料标签
"""
tid = request.data.get("tid")
label_template = request.data.get("label_template", None)
label_template_name = request.data.get("label_template_name", None)
extra_data = request.data.get("extra_data", {})
try:
wm = WMaterial.objects.get(id=tid)
except WMaterial.DoesNotExist:
raise NotFound("车间库存不存在")
obj, _ = LableMat.objects.get_or_create(state=wm.state, material=wm.material, batch=wm.batch,
notok_sign=wm.notok_sign, defect=wm.defect,
material_origin=wm.material_origin)
rdata = LabelMatSerializer(obj).data
rdata["code_label"] = f"mat{SPLIT_FIELD}{obj.id}"
if label_template or label_template_name:
tdata = {**rdata, **extra_data}
commands = LabelTemplate.gen_commands(label_template, label_template_name, tdata)
rdata["commands"] = commands
return Response(rdata)
@action(methods=["post"], detail=False, serializer_class=TidSerializer)
def get_from_mioitem(self, request, pk=None):
"""
从出入库明细获取物料标签
从出入库明细获取物料标签
"""
tid = request.data.get("tid")
label_template = request.data.get("label_template", None)
label_template_name = request.data.get("label_template_name", None)
extra_data = request.data.get("extra_data", {})
try:
mioitem: MIOItem = MIOItem.objects.get(id=tid)
except MIOItem.DoesNotExist:
raise NotFound("出入库明细不存在")
obj, _ = LableMat.objects.get_or_create(state=10, material=mioitem.material, batch=mioitem.batch, defaults={"supplier": mioitem.mio.supplier})
rdata = LabelMatSerializer(obj).data
rdata["code_label"] = f"mat{SPLIT_FIELD}{obj.id}"
if label_template or label_template_name:
tdata = {**rdata, **extra_data}
commands = LabelTemplate.gen_commands(label_template, label_template_name, tdata)
rdata["commands"] = commands
return Response(rdata)
class LabelTemplateViewSet(CustomModelViewSet):
"""
list: 标签模板
标签模板
"""
queryset = LabelTemplate.objects.all()
serializer_class = LabelTemplateSerializer
filterset_class = LabelTemplateFilter
@action(methods=["post"], detail=False, serializer_class=Tid2Serializer, perms_map={"post": "*"})
def commands(self, request, *args, **kwargs):
"""
获取标签指令
获取标签指令
"""
label_template = request.data.get("label_template", None)
label_template_name = request.data.get("label_template_name", None)
data = request.data.get("data", {})
return Response({"commands": LabelTemplate.gen_commands(label_template, label_template_name, data)})
@action(methods=["post"], detail=True, serializer_class=CoderSendSerializer, perms_map={"post": "*"})
def send_to_coder(self, request, pk=None, *args, **kwargs):
"""
下发指令到伟迪捷 1880 喷码机 (统一走 CQI + JDI 队列模式)
body 传 tdata_list (列表, 至少一条), 每条对应一个产品。
每次调用先 CQI 清空队列, 再按顺序 JDI 入队 N 条;
喷码机每个外部触发(光电)消费一条, 喷一个产品。
每条 tdata 走模板 commands, 解析为 <字段>=<内容> 合并成一帧 JDI;
commands 中不含 '=' 的元素, 会绑定到默认 coder_field 上。
"""
sr = CoderSendSerializer(data=request.data)
sr.is_valid(raise_exception=True)
vdata = sr.validated_data
lt: LabelTemplate = self.get_object()
ip = vdata.get("coder_ip")
port = vdata.get("coder_port") or 3100
field = vdata.get("coder_field") or "1"
batched = []
for tdata in vdata["tdata_list"]:
commands = LabelTemplate.gen_commands(lt.id, None, tdata)
if not commands:
raise ParseError("模板未生成任何指令")
fields = {}
for item in commands:
text = str(item)
if "=" in text:
k, v = text.split("=", 1)
fields[k.strip()] = v
else:
fields[field] = text
batched.append(fields)
client = CoderClient(ip=ip, port=port)
coder_jobname = vdata.get("coder_jobname")
client.clear_queue()
if coder_jobname:
client.select_job(coder_jobname)
client.clear_queue()
for fields in batched:
client.push_queue(fields)
return Response({"queued": len(batched), "fields": batched, "ip": ip, "port": port, "jobname": coder_jobname})