Merge branch 'master' of https://e.coding.net/ctcdevteam/ehs/ehs_server
This commit is contained in:
commit
88c029f66d
|
@ -0,0 +1,11 @@
|
|||
from django_filters import rest_framework as filters
|
||||
from django.utils import timezone
|
||||
from .models import LabelTemplate
|
||||
from apps.utils.filters import MyJsonListFilter
|
||||
|
||||
class LabelTemplateFilter(filters.FilterSet):
|
||||
process = MyJsonListFilter(label='按工序查询', field_name="process_json")
|
||||
|
||||
class Meta:
|
||||
model = LabelTemplate
|
||||
fields = ['process', "name"]
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 3.2.12 on 2025-05-06 02:25
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('cm', '0004_labeltemplate'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='labeltemplate',
|
||||
name='process_json',
|
||||
field=models.JSONField(blank=True, default=list, verbose_name='工序'),
|
||||
),
|
||||
]
|
|
@ -3,6 +3,7 @@ from apps.utils.models import BaseModel
|
|||
from apps.mtm.models import Material
|
||||
from apps.pum.models import Supplier
|
||||
from apps.wpm.models import WmStateOption
|
||||
from rest_framework.exceptions import NotFound, ParseError
|
||||
# Create your models here.
|
||||
|
||||
class LableMat(BaseModel):
|
||||
|
@ -17,5 +18,25 @@ class LableMat(BaseModel):
|
|||
|
||||
|
||||
class LabelTemplate(BaseModel):
|
||||
"""TN: 标签模板"""
|
||||
name = models.TextField("名称")
|
||||
commands = models.JSONField("指令模板", default=list, blank=True)
|
||||
commands = models.JSONField("指令模板", default=list, blank=True)
|
||||
process_json = models.JSONField("工序", default=list, blank=True)
|
||||
|
||||
@classmethod
|
||||
def gen_commands(cls, label_template, label_template_name, tdata):
|
||||
if label_template:
|
||||
lt = LabelTemplate.objects.get(id=label_template)
|
||||
else:
|
||||
lt = LabelTemplate.objects.filter(name=label_template_name).first()
|
||||
if not lt:
|
||||
raise NotFound("标签模板不存在")
|
||||
commands:list = lt.commands
|
||||
try:
|
||||
n_commands = []
|
||||
for item in commands:
|
||||
item = item.format(**tdata)
|
||||
n_commands.append(item)
|
||||
except Exception as e:
|
||||
raise ParseError(f"标签解析错误-{str(e)}")
|
||||
return n_commands
|
|
@ -7,6 +7,14 @@ from apps.utils.serializers import CustomModelSerializer
|
|||
|
||||
class TidSerializer(serializers.Serializer):
|
||||
tid = serializers.CharField(label='表ID')
|
||||
label_template = serializers.CharField(label='标签模板ID', allow_null=True, required=False)
|
||||
label_template_name = serializers.CharField(label='标签模板名称', allow_null=True, required=False)
|
||||
extra_data = serializers.JSONField(label='额外数据', allow_null=True, required=False)
|
||||
|
||||
class Tid2Serializer(serializers.Serializer):
|
||||
label_template = serializers.CharField(label='标签模板ID', allow_null=True, required=False)
|
||||
label_template_name = serializers.CharField(label='标签模板名称', allow_null=True, required=False)
|
||||
data = serializers.JSONField(label='数据', allow_null=True, required=False)
|
||||
|
||||
|
||||
class LabelMatSerializer(serializers.ModelSerializer):
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
from apps.cm.models import LableMat, LabelTemplate
|
||||
from rest_framework.decorators import action
|
||||
from apps.cm.serializers import TidSerializer, LabelMatSerializer, LabelTemplateSerializer
|
||||
from apps.cm.serializers import TidSerializer, LabelMatSerializer, LabelTemplateSerializer, Tid2Serializer
|
||||
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 = "#"
|
||||
|
@ -24,6 +25,9 @@ class LableMatViewSet(CustomListModelMixin, RetrieveModelMixin, CustomGenericVie
|
|||
从仓库明细获取物料标签
|
||||
"""
|
||||
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:
|
||||
|
@ -31,6 +35,10 @@ class LableMatViewSet(CustomListModelMixin, RetrieveModelMixin, CustomGenericVie
|
|||
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)
|
||||
|
@ -41,6 +49,9 @@ class LableMatViewSet(CustomListModelMixin, RetrieveModelMixin, CustomGenericVie
|
|||
从车间库存明细获取物料标签
|
||||
"""
|
||||
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:
|
||||
|
@ -50,6 +61,10 @@ class LableMatViewSet(CustomListModelMixin, RetrieveModelMixin, CustomGenericVie
|
|||
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)
|
||||
|
@ -60,6 +75,9 @@ class LableMatViewSet(CustomListModelMixin, RetrieveModelMixin, CustomGenericVie
|
|||
从出入库明细获取物料标签
|
||||
"""
|
||||
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:
|
||||
|
@ -67,6 +85,10 @@ class LableMatViewSet(CustomListModelMixin, RetrieveModelMixin, CustomGenericVie
|
|||
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)
|
||||
|
||||
|
||||
|
@ -77,4 +99,18 @@ class LabelTemplateViewSet(CustomModelViewSet):
|
|||
标签模板
|
||||
"""
|
||||
queryset = LabelTemplate.objects.all()
|
||||
serializer_class = LabelTemplateSerializer
|
||||
serializer_class = LabelTemplateSerializer
|
||||
filterset_class = LabelTemplateFilter
|
||||
|
||||
@action(methods=["post"], detail=False, serializer_class=Tid2Serializer)
|
||||
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)})
|
||||
|
|
@ -616,14 +616,14 @@ class TestViewSet(CustomGenericViewSet):
|
|||
'apps.rpm.tasks.close_rpj_by_leave_time']).delete()
|
||||
if 'mes' in datas:
|
||||
from apps.inm.models import MaterialBatch, MIO
|
||||
from apps.mtm.models import Material
|
||||
from apps.mtm.models import Material, RoutePack
|
||||
from apps.wpmw.models import Wpr
|
||||
from apps.wpm.models import WMaterial, Mlog
|
||||
from apps.wpm.models import WMaterial, Mlog, Handover, BatchSt
|
||||
from apps.pum.models import PuOrder
|
||||
from apps.sam.models import Order
|
||||
from apps.pm.models import Utask, Mtask
|
||||
from apps.wpm.models import Handover
|
||||
from apps.qm.models import Ftest, FtestWork
|
||||
from apps.wf.models import Ticket
|
||||
MaterialBatch.objects.all().delete()
|
||||
MIO.objects.all().delete()
|
||||
Wpr.objects.all().delete()
|
||||
|
@ -636,7 +636,9 @@ class TestViewSet(CustomGenericViewSet):
|
|||
Handover.objects.all().delete()
|
||||
Ftest.objects.all().delete()
|
||||
FtestWork.objects.all().delete()
|
||||
Material.objects.all().update(count=0, count_mb=0, count_wm=0)
|
||||
Material.objects.get_queryset(all=True).update(count=0, count_mb=0, count_wm=0)
|
||||
BatchSt.objects.all().delete()
|
||||
Ticket.objects.get_queryset(all=True).delete()
|
||||
return Response()
|
||||
|
||||
@action(methods=['post'], detail=False, serializer_class=Serializer, permission_classes=[])
|
||||
|
|
|
@ -254,6 +254,7 @@ class MIOItemViewSet(CustomListModelMixin, BulkCreateModelMixin, BulkDestroyMode
|
|||
"test_date": ["isnull", "exact"]
|
||||
}
|
||||
ordering = ['create_time']
|
||||
ordering_fields = ['create_time', 'test_date']
|
||||
|
||||
def add_info_for_list(self, data):
|
||||
|
||||
|
|
|
@ -3,13 +3,16 @@ from django_filters import rest_framework as filters
|
|||
|
||||
class MyJsonListFilter(filters.CharFilter):
|
||||
def filter(self, qs, value):
|
||||
|
||||
if value in ['all', '']:
|
||||
return qs
|
||||
elif ',' in value:
|
||||
value_l = value.split(',')
|
||||
qsx = qs.none()
|
||||
for i in value_l:
|
||||
qsx = qsx | qs.filter(tags__contains=i)
|
||||
kv = {f"{self.field_name}__contains": i}
|
||||
qsx = qsx | qs.filter(**kv)
|
||||
return qsx
|
||||
else:
|
||||
return qs.filter(tags__contains=value)
|
||||
kv = {f"{self.field_name}__contains": value}
|
||||
return qs.filter(**kv)
|
||||
|
|
|
@ -4,6 +4,7 @@ import json
|
|||
import logging
|
||||
from server.settings import get_sysconfig
|
||||
from apps.utils.decorators import auto_log
|
||||
from rest_framework.exceptions import ParseError
|
||||
|
||||
# 实例化myLogger
|
||||
myLogger = logging.getLogger('log')
|
||||
|
@ -12,8 +13,8 @@ myLogger = logging.getLogger('log')
|
|||
@auto_log(name='阿里云短信', raise_exception=True, send_mail=True)
|
||||
def send_sms(phone: str, template_code: int, template_param: dict):
|
||||
config = get_sysconfig()
|
||||
if config.get("sms", {}).get('enabled', True) is False:
|
||||
return
|
||||
if config.get("sms", {}).get('enabled', False) is False:
|
||||
raise ParseError("短信发送功能未启用")
|
||||
try:
|
||||
client = AcsClient(config['sms']['xn_key'],
|
||||
config['sms']['xn_secret'], 'default')
|
||||
|
|
|
@ -178,9 +178,11 @@ class BatchStFilter(filters.FilterSet):
|
|||
model = BatchSt
|
||||
fields = {
|
||||
"batch": ["exact", "contains", "startswith"],
|
||||
"first_time": ["exact", "gte", "lte"],
|
||||
"last_time": ["exact", "gte", "lte"],
|
||||
"update_time": ["exact", "gte", "lte"],
|
||||
"material_start": ["exact"],
|
||||
"material_start__cate": ["exact"],
|
||||
"material_start__type": ["exact"],
|
||||
"material_start__process": ["exact"]
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 3.2.12 on 2025-05-08 08:23
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('wpm', '0114_auto_20250428_1350'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='batchst',
|
||||
name='first_time',
|
||||
field=models.DateTimeField(blank=True, null=True, verbose_name='首次操作时间'),
|
||||
),
|
||||
]
|
|
@ -609,6 +609,7 @@ class BatchSt(BaseModel):
|
|||
"""
|
||||
batch = models.TextField("批次号", db_index=True)
|
||||
version = models.IntegerField("版本号", default=1, db_index=True)
|
||||
first_time = models.DateTimeField("首次操作时间", null=True, blank=True)
|
||||
last_time = models.DateTimeField("最后操作时间", null=True, blank=True)
|
||||
data = models.JSONField("数据", default=list, blank=True)
|
||||
material_start = models.ForeignKey(Material, verbose_name="起始物料", on_delete=models.SET_NULL, null=True, blank=True)
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
from apps.wpm.models import BatchSt
|
||||
import logging
|
||||
from apps.qm.models import Defect
|
||||
from apps.wpm.models import Mlogb, MlogbDefect
|
||||
import decimal
|
||||
from django.db.models import Sum
|
||||
|
||||
myLogger = logging.getLogger("log")
|
||||
|
||||
def main(batch: str):
|
||||
try:
|
||||
batchst = BatchSt.objects.get(batch=batch, version=1)
|
||||
except BatchSt.DoesNotExist:
|
||||
myLogger.error(f"Batch {batch} does not exist")
|
||||
return None, None
|
||||
|
||||
data = {"批次号": batch}
|
||||
|
||||
mgroup_names = ["尺寸检验", "外观检验"]
|
||||
for mgroup_name in mgroup_names:
|
||||
mlogb1_qs = Mlogb.objects.filter(mlog__submit_time__isnull=False, material_out__isnull=False, mlog__mgroup__name=mgroup_name, batch=batch)
|
||||
if mlogb1_qs.exists():
|
||||
data[f"{mgroup_name}_日期"] = []
|
||||
data[f"{mgroup_name}_操作人"] = []
|
||||
data[f"{mgroup_name}_count_real"] = 0
|
||||
data[f"{mgroup_name}_count_ok"] = 0
|
||||
data[f"{mgroup_name}_count_ok_full"] = 0
|
||||
for item in mlogb1_qs:
|
||||
if item.mlog.handle_user:
|
||||
data[f"{mgroup_name}_操作人"].append(item.mlog.handle_user)
|
||||
if item.mlog.handle_date:
|
||||
data[f"{mgroup_name}_日期"].append(item.mlog.handle_date)
|
||||
data[f"{mgroup_name}_count_real"] += item.count_real
|
||||
data[f"{mgroup_name}_count_ok"] += item.count_ok
|
||||
data[f"{mgroup_name}_count_ok_full"] += item.count_ok_full
|
||||
|
||||
try:
|
||||
data[f"{mgroup_name}_合格率"] = round((data[f"{mgroup_name}-count_ok"] / data[f"{mgroup_name}-count_real"])*100, 2)
|
||||
except decimal.InvalidOperation:
|
||||
data[f"{mgroup_name}_合格率"] = 0
|
||||
|
||||
mlogbd1_qs = MlogbDefect.objects.filter(mlogb__in=mlogb1_qs, count__gt=0).values("defect__name").annotate(total=Sum("count"))
|
||||
|
||||
for item in mlogbd1_qs:
|
||||
data[f"{mgroup_name}_缺陷_{item['defect__name']}"] = item["total"]
|
||||
data[f"{mgroup_name}_缺陷_{item['defect__name']}-比例"] = round((item["total"] / data[f"{mgroup_name}-count_real"])*100, 2)
|
||||
|
||||
data[f"{mgroup_name}_日期"] = list(set(data[f"{mgroup_name}_日期"]))
|
||||
data[f"{mgroup_name}_日期"] = ";".join([item.strftime("%Y-%m-%d") for item in data[f"{mgroup_name}_日期"]])
|
||||
data[f"{mgroup_name}_操作人"] = list(set(data[f"{mgroup_name}_操作人"]))
|
||||
data[f"{mgroup_name}_操作人"] = ";".join([item.name for item in data[f"{mgroup_name}_操作人"]])
|
||||
|
||||
mlogb2_qs = Mlogb.objects.filter(mlog__submit_time__isnull=False, material_out__isnull=False, mlog__mgroup__name="外观检验", mlog__is_fix=True, batch=batch)
|
||||
if mlogb2_qs.exists():
|
||||
data["外观检验_返修_日期"] = []
|
||||
data["外观检验_返修_操作人"] = []
|
||||
data["外观检验_返修_count_real"] = 0
|
||||
data["外观检验_返修_count_ok"] = 0
|
||||
data["外观检验_返修_count_ok_full"] = 0
|
||||
for item in mlogb2_qs:
|
||||
if item.mlog.handle_user:
|
||||
data["外观检验_返修_操作人"].append(item.mlog.handle_user)
|
||||
if item.mlog.handle_date:
|
||||
data["外观检验_返修_日期"].append(item.mlog.handle_date)
|
||||
data["外观检验_返修_count_real"] += item.count_real
|
||||
data["外观检验_返修_count_ok"] += item.count_ok
|
||||
data["外观检验_返修_count_ok_full"] += item.count_ok_full
|
||||
|
||||
data["外观检验_返修_日期"] = list(set(data["外观检验_返修_日期"]))
|
||||
data["外观检验_返修_日期"] = ";".join([item.strftime("%Y-%m-%d") for item in data["外观检验_返修_日期"]])
|
||||
data["外观检验_返修_操作人"] = list(set(data["外观检验_返修_操作人"]))
|
||||
data["外观检验_返修_操作人"] = ";".join([item.name for item in data["外观检验_返修_操作人"]])
|
||||
|
||||
mlogbd2_qs = MlogbDefect.objects.filter(mlogb__in=mlogb2_qs, count__gt=0).values("defect__name").annotate(total=Sum("count"))
|
||||
|
||||
for item in mlogbd2_qs:
|
||||
data[f"外观检验_返修_缺陷_{item['defect__name']}"] = item["total"]
|
||||
data[f"外观检验_返修_缺陷_{item['defect__name']}-比例"] = round((item["total"] / data["外观检验_返修-count_real"])*100, 2)
|
||||
|
||||
if "外观检验_count_ok" in data:
|
||||
data["外观检验_总合格数"] = data["外观检验_count_ok"] + data["外观检验_返修_count_ok"] if "外观检验_返修_count_ok" in data else 0
|
||||
try:
|
||||
data["外观检验_总合格率"] = round((data["外观检验_总合格数"] / data["外观检验_count_real"])*100, 2)
|
||||
except decimal.InvalidOperation:
|
||||
data["外观检验_总合格率"] = 0
|
||||
|
||||
try:
|
||||
data["外观检验_直通合格率"] = round((data["外观检验_总合格率"]* data["尺寸检验_合格率"])/100, 2)
|
||||
except decimal.InvalidOperation:
|
||||
data["外观检验_直通合格率"] = 0
|
||||
|
||||
return data, {}
|
||||
|
||||
if __name__ == '__main__':
|
||||
pass
|
|
@ -12,33 +12,31 @@ import decimal
|
|||
import logging
|
||||
myLogger = logging.getLogger('log')
|
||||
|
||||
def get_alldata_with_batch_and_store(batch: str, need_update_time=True):
|
||||
def get_alldata_with_batch_and_store(batch: str):
|
||||
"""
|
||||
获取某个批次的整体生产数据并保存
|
||||
"""
|
||||
need_update = False
|
||||
data = None
|
||||
action = "get"
|
||||
BASE_PROJECT_CODE = getattr(settings, "BASE_PROJECT_CODE", None)
|
||||
if BASE_PROJECT_CODE == "gzerp":
|
||||
need_update = True
|
||||
last_time, data = get_alldata_with_batch(batch)
|
||||
action = "get_or_create"
|
||||
data, extra = get_alldata_with_batch(batch)
|
||||
elif BASE_PROJECT_CODE == "gxerp":
|
||||
need_update = True
|
||||
last_time, data = get_alldata_with_batch_gx(batch)
|
||||
|
||||
if need_update and last_time and data:
|
||||
bobj, _ = BatchSt.objects.get_or_create(batch=batch, defaults={
|
||||
"last_time": last_time
|
||||
})
|
||||
if need_update_time:
|
||||
bobj.last_time = last_time
|
||||
from apps.wpm.scripts.batch_gxerp import main
|
||||
data, extra = main(batch)
|
||||
|
||||
if data:
|
||||
if action == "get_or_create":
|
||||
bobj, _ = BatchSt.objects.get_or_create(batch=batch, version=1)
|
||||
elif action == "get":
|
||||
bobj = BatchSt.objects.get(batch=batch, version=1)
|
||||
bobj.data = json.loads(json.dumps(data, cls=MyJSONEncoder))
|
||||
for k, v in extra.items():
|
||||
if hasattr(bobj, k):
|
||||
setattr(bobj, k, v)
|
||||
bobj.save()
|
||||
|
||||
def get_alldata_with_batch_gx(batch: str):
|
||||
"""
|
||||
光芯获取batch的统计数据
|
||||
"""
|
||||
return None, None
|
||||
|
||||
def get_alldata_with_batch(batch: str):
|
||||
"""
|
||||
|
@ -54,13 +52,19 @@ def get_alldata_with_batch(batch: str):
|
|||
|
||||
mlog_count_fields = Mlog.count_fields()
|
||||
|
||||
first_time = None
|
||||
material_start = None
|
||||
if mlogs_blcx_qs.exists():
|
||||
data["产品规格"] = []
|
||||
data["棒料成型_出料人"] = []
|
||||
data["棒料成型_切料人"] = []
|
||||
data["棒料成型_备注"] = ""
|
||||
for item in mlogs_blcx_qs:
|
||||
last_time = item.update_time if item.update_time > last_time else last_time
|
||||
utime = item.submit_time
|
||||
last_time = utime if utime > last_time else last_time
|
||||
first_time = utime if first_time is None else (utime if utime < first_time else first_time)
|
||||
if material_start is None:
|
||||
material_start = item.material_out
|
||||
data["产品规格"].append(item.material_out) # 对象
|
||||
if item.handle_user:
|
||||
data["棒料成型_出料人"].append(item.handle_user) # 对象
|
||||
|
@ -86,7 +90,7 @@ def get_alldata_with_batch(batch: str):
|
|||
except ZeroDivisionError:
|
||||
data["棒料成型_合格率"] = 0
|
||||
except decimal.InvalidOperation:
|
||||
myLogger.error(f"棒料成型_合格率计算错误decimal.InvalidOperation-{data}")
|
||||
# myLogger.error(f"棒料成型_合格率计算错误decimal.InvalidOperation-{data}")
|
||||
data["棒料成型_合格率"] = 0
|
||||
|
||||
# 管料成型数据
|
||||
|
@ -96,7 +100,11 @@ def get_alldata_with_batch(batch: str):
|
|||
data["产品规格"] = []
|
||||
data["管料成型_备注"] = ""
|
||||
for item in mlogs_glcx_qs:
|
||||
last_time = item.update_time if item.update_time > last_time else last_time
|
||||
utime = item.submit_time
|
||||
last_time = utime if utime > last_time else last_time
|
||||
first_time = utime if first_time is None else (utime if utime < first_time else first_time)
|
||||
if material_start is None:
|
||||
material_start = item.material_out
|
||||
data["产品规格"].append(item.material_out) # 对象
|
||||
if item.note:
|
||||
data["管料成型_备注"] = ";".join([data["管料成型_备注"], item.note])
|
||||
|
@ -119,7 +127,11 @@ def get_alldata_with_batch(batch: str):
|
|||
data["七车间入库_仓库执行人"] = []
|
||||
data["七车间入库_检验备注"] = ""
|
||||
for item in mioitem_qs:
|
||||
last_time = item.update_time if item.update_time > last_time else last_time
|
||||
utime = item.mio.submit_time
|
||||
last_time = utime if utime > last_time else last_time
|
||||
first_time = utime if first_time is None else (utime if utime < first_time else first_time)
|
||||
if material_start is None:
|
||||
material_start = item.material
|
||||
data["七车间入库_日期"].append(item.mio.inout_date)
|
||||
if item.test_note:
|
||||
data["七车间入库_检验备注"] = ";".join([data["七车间入库_检验备注"], item.test_note])
|
||||
|
@ -153,7 +165,11 @@ def get_alldata_with_batch(batch: str):
|
|||
data["十车间入库_日期"] = []
|
||||
data["十车间入库_检验备注"] = ""
|
||||
for item in mioitem10_qs:
|
||||
last_time = item.update_time if item.update_time > last_time else last_time
|
||||
utime = item.mio.submit_time
|
||||
last_time = utime if utime > last_time else last_time
|
||||
first_time = utime if first_time is None else (utime if utime < first_time else first_time)
|
||||
if material_start is None:
|
||||
material_start = item.material
|
||||
if item.test_note:
|
||||
data["十车间入库_检验备注"] = ";".join([data["十车间入库_检验备注"], item.test_note])
|
||||
if item.mio.do_user:
|
||||
|
@ -188,7 +204,15 @@ def get_alldata_with_batch(batch: str):
|
|||
data["产品规格"] = []
|
||||
for item in mlogs_glth_qs:
|
||||
data["产品规格"].append(item.material_out)
|
||||
last_time = item.update_time if item.update_time > last_time else last_time
|
||||
utime = item.submit_time
|
||||
last_time = utime if utime > last_time else last_time
|
||||
first_time = utime if first_time is None else (utime if utime < first_time else first_time)
|
||||
if first_time is None:
|
||||
first_time = item.update_time
|
||||
else:
|
||||
first_time = item.update_time if item.update_time < first_time else first_time
|
||||
if material_start is None:
|
||||
material_start = item.material_out
|
||||
if item.note:
|
||||
data["管料退火_备注"] = ";".join([data["管料退火_备注"], item.note])
|
||||
if item.handle_date:
|
||||
|
@ -220,7 +244,11 @@ def get_alldata_with_batch(batch: str):
|
|||
data["产品规格"] = []
|
||||
for item in mioitem6_qs:
|
||||
data["产品规格"].append(item.material)
|
||||
last_time = item.update_time if item.update_time > last_time else last_time
|
||||
utime = item.mio.submit_time
|
||||
last_time = utime if utime > last_time else last_time
|
||||
first_time = utime if first_time is None else (utime if utime < first_time else first_time)
|
||||
if material_start is None:
|
||||
material_start = item.material
|
||||
data["六车间领料_日期"].append(item.mio.inout_date)
|
||||
if item.mio.do_user:
|
||||
data["六车间领料_仓库执行人"].append(item.mio.do_user)
|
||||
|
@ -252,11 +280,15 @@ def get_alldata_with_batch(batch: str):
|
|||
mgroups = Mgroup.objects.filter(name=mgroup_name)
|
||||
mlogs_qs = Mlog.objects.filter(submit_time__isnull=False, mgroup__in=mgroups, batch=batch)
|
||||
if mlogs_qs.exists():
|
||||
last_time = item.update_time if item.update_time > last_time else last_time
|
||||
data[f'六车间_{mgroup_name}_日期'] = []
|
||||
data[f'六车间_{mgroup_name}_操作人'] = []
|
||||
data[f'六车间_{mgroup_name}_备注'] = ""
|
||||
for item in mlogs_qs:
|
||||
utime = item.submit_time
|
||||
last_time = utime if utime > last_time else last_time
|
||||
first_time = utime if first_time is None else (utime if utime < first_time else first_time)
|
||||
if material_start is None:
|
||||
material_start = item.material_out
|
||||
if item.note:
|
||||
data[f'六车间_{mgroup_name}_备注'] = ";".join([data[f'六车间_{mgroup_name}_备注'], item.note])
|
||||
if item.handle_date:
|
||||
|
@ -276,7 +308,7 @@ def get_alldata_with_batch(batch: str):
|
|||
try:
|
||||
data[f'六车间_{mgroup_name}_合格率'] = round(data[f'六车间_{mgroup_name}_count_ok'] * 100/ data[f'六车间_{mgroup_name}_count_real'], 1)
|
||||
except decimal.InvalidOperation:
|
||||
myLogger.error(f"六车间_{mgroup_name}_合格率decimal.InvalidOperation-{data}")
|
||||
# myLogger.error(f"六车间_{mgroup_name}_合格率decimal.InvalidOperation-{data}")
|
||||
data[f'六车间_{mgroup_name}_合格率'] = 0
|
||||
|
||||
ftestwork_count_fields = FtestWork.count_fields()
|
||||
|
@ -286,7 +318,11 @@ def get_alldata_with_batch(batch: str):
|
|||
data["六车间中检_日期"] = []
|
||||
data['六车间中检_检验人'] = []
|
||||
for item in ftestwork_qs:
|
||||
last_time = item.update_time if item.update_time > last_time else last_time
|
||||
utime = item.update_time
|
||||
last_time = utime if utime > last_time else last_time
|
||||
first_time = utime if first_time is None else (utime if utime < first_time else first_time)
|
||||
if material_start is None:
|
||||
material_start = item.material
|
||||
if item.test_date:
|
||||
data["六车间中检_日期"].append(item.test_date)
|
||||
if item.test_user:
|
||||
|
@ -318,6 +354,11 @@ def get_alldata_with_batch(batch: str):
|
|||
data["六车间生产入库_检验日期"] = []
|
||||
data["六车间生产入库_检验人"] = []
|
||||
for item in mioitem6_qs2:
|
||||
utime = item.mio.submit_time
|
||||
last_time = utime if utime > last_time else last_time
|
||||
first_time = utime if first_time is None else (utime if utime < first_time else first_time)
|
||||
if material_start is None:
|
||||
material_start = item.material
|
||||
data["六车间生产入库_日期"].append(item.mio.inout_date)
|
||||
if item.test_date:
|
||||
data["六车间生产入库_检验日期"].append(item.test_date)
|
||||
|
@ -334,7 +375,7 @@ def get_alldata_with_batch(batch: str):
|
|||
try:
|
||||
data['六车间生产入库_合格率'] = round((data['六车间生产入库_count'] - data['六车间生产入库_count_notok']) * 100/ data['六车间生产入库_count'], 1)
|
||||
except decimal.InvalidOperation:
|
||||
myLogger.error("六车间生产入库_合格率decimal.InvalidOperation-{data}")
|
||||
# myLogger.error("六车间生产入库_合格率decimal.InvalidOperation-{data}")
|
||||
data['六车间生产入库_合格率'] = 0
|
||||
|
||||
# 成品检验数据
|
||||
|
@ -343,7 +384,11 @@ def get_alldata_with_batch(batch: str):
|
|||
data["成品检验_日期"] = []
|
||||
data['成品检验_检验人'] = []
|
||||
for item in ftestwork_qs:
|
||||
last_time = item.update_time if item.update_time > last_time else last_time
|
||||
utime = item.update_time
|
||||
last_time = utime if utime > last_time else last_time
|
||||
first_time = utime if first_time is None else (utime if utime < first_time else first_time)
|
||||
if material_start is None:
|
||||
material_start = item.material
|
||||
if item.test_date:
|
||||
data["成品检验_日期"].append(item.test_date)
|
||||
if item.test_user:
|
||||
|
@ -378,7 +423,11 @@ def get_alldata_with_batch(batch: str):
|
|||
data['销售发货_仓库执行人'] = []
|
||||
data['销售发货_count'] = 0
|
||||
for item in mioitem_qs:
|
||||
last_time = item.mio.update_time if item.mio.update_time > last_time else last_time
|
||||
utime = item.mio.submit_time
|
||||
last_time = utime if utime > last_time else last_time
|
||||
first_time = utime if first_time is None else (utime if utime < first_time else first_time)
|
||||
if material_start is None:
|
||||
material_start = item.material
|
||||
if item.mio.inout_date:
|
||||
data["销售发货_日期"].append(item.mio.inout_date)
|
||||
if item.mio.do_user:
|
||||
|
@ -390,5 +439,5 @@ def get_alldata_with_batch(batch: str):
|
|||
data["六车间_批次发货合格率"] = round(data["销售发货_count"] * 100/ data["六车间领料_count"], 1)
|
||||
data['销售发货_仓库执行人'] = ";".join([item.name for item in data['销售发货_仓库执行人']])
|
||||
|
||||
return last_time, data
|
||||
return data, {"material_start": material_start, "last_time": last_time, "first_time": first_time}
|
||||
|
|
@ -602,8 +602,8 @@ class MlogbInViewSet(CreateModelMixin, UpdateModelMixin, DestroyModelMixin, Cust
|
|||
m_dict['batch'] = generate_new_batch(mlogbin.batch, mlog)
|
||||
|
||||
if mtype == Process.PRO_NORMAL: # 正常 支持批到批, 个到个
|
||||
d_count_real = mlogbin.count_use
|
||||
d_count_ok = mlogbin.count_use
|
||||
d_count_real = mlogbin.count_use - mlogbin.count_pn_jgqbl
|
||||
d_count_ok = d_count_real
|
||||
mlogbout, _ = Mlogb.objects.get_or_create(mlogb_from=mlogbin, defaults=
|
||||
update_dict(m_dict, {"count_real": d_count_real, "count_ok": d_count_ok}))
|
||||
mlogbout.count_json_from = mlogbin.count_json_from
|
||||
|
@ -627,7 +627,7 @@ class MlogbInViewSet(CreateModelMixin, UpdateModelMixin, DestroyModelMixin, Cust
|
|||
mlogbout.number_from = mlogbwin.number
|
||||
mlogbout.save()
|
||||
elif material_in.tracking == Material.MA_TRACKING_SINGLE and material_out.tracking == Material.MA_TRACKING_SINGLE:
|
||||
d_count_real = mlogbin.count_use * div_number
|
||||
d_count_real = (mlogbin.count_use-mlogbin.count_pn_jgqbl) * div_number
|
||||
d_count_ok = d_count_real
|
||||
mlogbout, _ = Mlogb.objects.get_or_create(mlogb_from=mlogbin, defaults=update_dict(m_dict,
|
||||
{"count_real": d_count_real, "count_ok": d_count_ok}))
|
||||
|
@ -639,13 +639,13 @@ class MlogbInViewSet(CreateModelMixin, UpdateModelMixin, DestroyModelMixin, Cust
|
|||
for i in range(div_number):
|
||||
Mlogbw.objects.get_or_create(mlogb=mlogbout, number=f'{wpr_.number}-{i+1}', defaults={"mlogbw_from": mlogbwin})
|
||||
elif material_in.tracking == Material.MA_TRACKING_BATCH and material_out.tracking == Material.MA_TRACKING_BATCH:
|
||||
d_count_real = mlogbin.count_use * div_number
|
||||
d_count_real = (mlogbin.count_use-mlogbin.count_pn_jgqbl) * div_number
|
||||
d_count_ok = d_count_real
|
||||
mlogbout, _ = Mlogb.objects.get_or_create(mlogb_from=mlogbin, defaults=update_dict(m_dict,{"count_real": d_count_real, "count_ok": d_count_ok}))
|
||||
mlogbout.count_json_from = mlogbin.count_json_from
|
||||
mlogbout.save(update_fields=["count_json_from"])
|
||||
elif mtype == Process.PRO_MERGE: # 支持批到批,批到个
|
||||
xcount = math.floor( mlogbin.count_use / route.div_number)
|
||||
xcount = math.floor( (mlogbin.count_use-mlogbin.count_pn_jgqbl) / route.div_number)
|
||||
d_count_real = xcount
|
||||
d_count_ok = xcount
|
||||
mlogbout, _ = Mlogb.objects.get_or_create(mlogb_from=mlogbin, defaults=update_dict(m_dict, {"count_real": d_count_real, "count_ok": d_count_ok}))
|
||||
|
@ -661,8 +661,8 @@ class MlogbInViewSet(CreateModelMixin, UpdateModelMixin, DestroyModelMixin, Cust
|
|||
for i in range(d_count_real):
|
||||
Mlogbw.objects.get_or_create(number=f'{number}-{i+1}', mlogb=mlogbout)
|
||||
elif is_fix:# 支持批到批,个到个
|
||||
d_count_real = mlogbin.count_use
|
||||
d_count_ok = mlogbin.count_use
|
||||
d_count_real = mlogbin.count_use-mlogbin.count_pn_jgqbl
|
||||
d_count_ok = d_count_real
|
||||
Mlogb.objects.get_or_create(mlogb_from=mlogbin, defaults=update_dict(m_dict,{"count_real": d_count_real, "count_ok": d_count_ok}))
|
||||
if material_in.tracking == Material.MA_TRACKING_SINGLE and material_out.tracking == Material.MA_TRACKING_SINGLE:
|
||||
for mlogbwin in Mlogbw.objects.filter(mlogb=mlogbin).order_by("number"):
|
||||
|
|
18
changelog.md
18
changelog.md
|
@ -1,3 +1,21 @@
|
|||
## 2.6.2025051208
|
||||
- feat: 新增功能
|
||||
- 光芯质检表格 [caoqianming]
|
||||
- base 短信发送功能启动抛出异常 [caoqianming]
|
||||
- batchst字段同步数据库 [caoqianming]
|
||||
## 2.6.2025050816
|
||||
- feat: 新增功能
|
||||
- batchst添加字段并更新光子的统计 [caoqianming]
|
||||
- 由输入转输出需考虑到加工前不良的影响 [caoqianming]
|
||||
- 初步添加光芯的批次分析函数 [caoqianming]
|
||||
- myjsonfield优化 [caoqianming]
|
||||
- mioitem添加排序字段 [caoqianming]
|
||||
- 标签物料根据模板打印功能 [caoqianming]
|
||||
- ichat 修改接口去掉langchain [zty]
|
||||
- fix: 问题修复
|
||||
- gen_commands bug [caoqianming]
|
||||
- labeltemplate filter bug [caoqianming]
|
||||
- 标签模板筛选bug [caoqianming]
|
||||
## 2.6.2025043014
|
||||
- feat: 新增功能
|
||||
- 生产入库和领料支持b类合格品 [caoqianming]
|
||||
|
|
|
@ -35,7 +35,7 @@ sys.path.insert(0, os.path.join(BASE_DIR, 'apps'))
|
|||
ALLOWED_HOSTS = ['*']
|
||||
|
||||
SYS_NAME = '星途工厂综合管理系统'
|
||||
SYS_VERSION = '2.6.2025043014'
|
||||
SYS_VERSION = '2.6.2025051208'
|
||||
X_FRAME_OPTIONS = 'SAMEORIGIN'
|
||||
|
||||
# Application definition
|
||||
|
|
Loading…
Reference in New Issue