This commit is contained in:
zty 2025-05-12 09:54:18 +08:00
commit 88c029f66d
17 changed files with 335 additions and 51 deletions

11
apps/cm/filters.py Normal file
View File

@ -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"]

View File

@ -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='工序'),
),
]

View File

@ -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

View File

@ -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):

View File

@ -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)})

View File

@ -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=[])

View File

@ -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):

View File

@ -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)

View File

@ -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')

View File

@ -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"]
}

View File

@ -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='首次操作时间'),
),
]

View File

@ -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)

View File

@ -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

View File

@ -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}

View File

@ -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"):

View File

@ -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]

View File

@ -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