From f8db7adab5f4b841152524fd0f309e8dec2b916d Mon Sep 17 00:00:00 2001 From: caoqianming Date: Wed, 19 Nov 2025 10:54:42 +0800 Subject: [PATCH 01/12] =?UTF-8?q?feat:=20=E6=94=B9=E7=89=88=E4=BA=A4?= =?UTF-8?q?=E6=8E=A5=E6=94=AF=E6=8C=81new=5Fwm?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/wpm/services.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/wpm/services.py b/apps/wpm/services.py index 7bb9a5d5..27ea58fa 100644 --- a/apps/wpm/services.py +++ b/apps/wpm/services.py @@ -857,7 +857,9 @@ def handover_submit(handover:Handover, user: User, now: Union[datetime.datetime, else: raise ParseError("不支持非工段报废") elif handover.type == Handover.H_CHANGE: - if handover.recive_mgroup: + if handover.new_wm: + wm_to = handover.new_wm + elif handover.recive_mgroup: wm_to, _ = WMaterial.objects.get_or_create( batch=batch, material=handover.material_changed, From 01d93d7814123f463ed4ea2e9b4521c218716872 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Wed, 19 Nov 2025 13:51:32 +0800 Subject: [PATCH 02/12] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96ana=20batchwork?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/wpm/views_ana.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/wpm/views_ana.py b/apps/wpm/views_ana.py index 3688b3a6..fc9f563f 100644 --- a/apps/wpm/views_ana.py +++ b/apps/wpm/views_ana.py @@ -7,6 +7,7 @@ from apps.wpm.serializers import BatchMgroupSerializer from apps.wpm.models import WMaterial, Mlogb from django.db.models import Q, Sum, F, ExpressionWrapper from collections import defaultdict +from apps.mtm.models import Material @@ -26,12 +27,12 @@ class BatchWorkView(APIView): mgroup:Mgroup = Mgroup.objects.get(name=vdata['mgroup_name']) except Exception: raise ParseError(f"获取工段信息失败-{vdata['mgroup_name']}") - matoutIds = mgroup.process.get_canout_mat_ids() + matinIds = mgroup.process.get_canin_mat_ids() # 待加工的批次 wm_qs = WMaterial.objects.filter(mgroup=mgroup, count__gt=0) - wm_todo_qs = wm_qs.filter(state=WMaterial.WM_OK).exclude(material__id__in=matoutIds)|wm_qs.filter(state=WMaterial.WM_REPAIR) + wm_todo_qs = wm_qs.filter(material__id__in=matinIds).exclude(state=WMaterial.WM_REPAIRED)|wm_qs.filter(state=WMaterial.WM_REPAIR, mgroup=mgroup) wm_v = wm_todo_qs.order_by("batch").values("count", "batch", wmid=F("id")) # 对应的操作子日志投入 From caf1bba050b6949a88f30207c7efd1c7dc44032d Mon Sep 17 00:00:00 2001 From: caoqianming Date: Wed, 19 Nov 2025 15:53:38 +0800 Subject: [PATCH 03/12] =?UTF-8?q?feat:=20do=5Fout=E6=8A=A5=E9=94=99?= =?UTF-8?q?=E6=9B=B4=E6=98=8E=E7=A1=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/inm/services.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/inm/services.py b/apps/inm/services.py index f4039b7b..8f00a830 100644 --- a/apps/inm/services.py +++ b/apps/inm/services.py @@ -88,7 +88,7 @@ def do_out(item: MIOItem, is_reverse: bool = False): defect=defect ) except (MaterialBatch.DoesNotExist, MaterialBatch.MultipleObjectsReturned) as e: - raise ParseError(f"批次错误!{e}") + raise ParseError(f"批次{xbatch}错误!{e}") mb.count = mb.count - xcount if mb.count < 0: raise ParseError(f"{mb.batch}-{str(mb.material)}-批次库存不足,操作失败") From cbd458a8a5511eb69272f0e384fff627943878a9 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Wed, 19 Nov 2025 16:05:11 +0800 Subject: [PATCH 04/12] =?UTF-8?q?feat:=20do=5Fout=E6=8A=A5=E9=94=99?= =?UTF-8?q?=E6=9B=B4=E6=98=8E=E7=A1=AE2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/inm/services.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/inm/services.py b/apps/inm/services.py index 8f00a830..ab5d56e2 100644 --- a/apps/inm/services.py +++ b/apps/inm/services.py @@ -88,7 +88,7 @@ def do_out(item: MIOItem, is_reverse: bool = False): defect=defect ) except (MaterialBatch.DoesNotExist, MaterialBatch.MultipleObjectsReturned) as e: - raise ParseError(f"批次{xbatch}错误!{e}") + raise ParseError(f"{str(xmaterial)}批次{xbatch}错误!{e}") mb.count = mb.count - xcount if mb.count < 0: raise ParseError(f"{mb.batch}-{str(mb.material)}-批次库存不足,操作失败") From 29f1a96c3b39dbc7d154c926ca332012976f9722 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Wed, 19 Nov 2025 16:53:39 +0800 Subject: [PATCH 05/12] =?UTF-8?q?fix:=20format=5Fjson=5Fwith=5Fplaceholder?= =?UTF-8?q?s=20=E5=A4=84=E7=90=86decimal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/bi/services.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/bi/services.py b/apps/bi/services.py index 0bba6d35..ee896bd8 100644 --- a/apps/bi/services.py +++ b/apps/bi/services.py @@ -4,6 +4,7 @@ from jinja2 import Template from apps.bi.models import Dataset import concurrent from apps.utils.sql import execute_raw_sql, format_sqldata +from apps.utils.tools import MyJSONEncoder forbidden_keywords = ["UPDATE", "DELETE", "DROP", "TRUNCATE", "INSERT", "CREATE", "ALTER", "GRANT", "REVOKE", "EXEC", "EXECUTE"] @@ -25,7 +26,7 @@ def format_json_with_placeholders(json_str, **kwargs): # 遍历关键字参数,将占位符替换为对应的值 for key, value in kwargs.items(): - formatted_json = formatted_json.replace("{" + key + "}", json.dumps(value)) + formatted_json = formatted_json.replace("{" + key + "}", json.dumps(value, cls=MyJSONEncoder)) # 格式化后的字符串依然是 JSON 字符串,没有使用 json.loads() return formatted_json From 706cfd502b98b046d291caa90c4d6733539e75c4 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Thu, 20 Nov 2025 12:00:44 +0800 Subject: [PATCH 06/12] =?UTF-8?q?feat:=20wpr=5Fbxerp=E4=BC=98=E5=8C=96mlog?= =?UTF-8?q?bw=E7=9A=84=E8=8E=B7=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/wpm/scripts/wpr_bxerp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/wpm/scripts/wpr_bxerp.py b/apps/wpm/scripts/wpr_bxerp.py index 011ae5d2..8ef74e42 100644 --- a/apps/wpm/scripts/wpr_bxerp.py +++ b/apps/wpm/scripts/wpr_bxerp.py @@ -8,7 +8,7 @@ def main(wprId, mgroup:Mgroup): wpr = Wpr.objects.get(id=wprId) data = {} mgroup_name = mgroup.name - mlogbw = Mlogbw.objects.filter(wpr=wpr, mlogb__mlog__submit_time__isnull=False).order_by("-update_time").first() + mlogbw = Mlogbw.objects.filter(wpr=wpr, mlogb__mlog__mgroup=mgroup, mlogb__mlog__submit_time__isnull=False).order_by("-update_time").first() if mlogbw: data[f"{mgroup_name}_批次号"] = mlogbw.mlogb.batch data[f"{mgroup_name}_日期"] = mlogbw.mlogb.mlog.handle_date.strftime("%Y-%m-%d") From 5ed3b7c483cbab0966c8cfd2122ca07b246e5548 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Thu, 20 Nov 2025 12:27:35 +0800 Subject: [PATCH 07/12] =?UTF-8?q?feat:=20mioitemw=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E7=AD=9B=E9=80=89=E6=9D=A1=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/inm/views.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/apps/inm/views.py b/apps/inm/views.py index 56159b1f..b4f7667f 100644 --- a/apps/inm/views.py +++ b/apps/inm/views.py @@ -482,13 +482,25 @@ class MIOItemwViewSet(CustomModelViewSet): perms_map = {'get': '*', 'post': 'mio.update', 'put': 'mio.update', 'delete': 'mio.update'} queryset = MIOItemw.objects.all() serializer_class = MIOItemwCreateUpdateSerializer - filterset_fields = ['mioitem', 'wpr'] + filterset_fields = { + 'mioitem': ['exact'], + 'mioitem__material__type': ['exact'], + "wpr": ['exact'], + "number": ["exact"], + "ftest": ["isnull"], + "mioitem__mio__state": ["exact"] + } + select_related_fields = ["ftest"] ordering = ["number", "create_time"] ordering_fields = ["number", "create_time"] def filter_queryset(self, queryset): - if not self.detail and not self.request.query_params.get('mioitem', None): - raise ParseError('请指定所属出入库记录明细') + if not self.detail: + if not self.request.query_params.get('mioitem', None): + if "ftest__isnull" in self.request.query_params: + pass + else: + raise ParseError('请指定所属出入库记录明细') return super().filter_queryset(queryset) def cal_mioitem_count(self, mioitem:MIOItem): From 5d7c6819830a64e335998283782ab4703f78e8ec Mon Sep 17 00:00:00 2001 From: caoqianming Date: Fri, 21 Nov 2025 10:53:36 +0800 Subject: [PATCH 08/12] =?UTF-8?q?feat:=20mioitemcreate=E6=97=B6=E6=8E=A5?= =?UTF-8?q?=E6=94=B6count=5Fsend?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/inm/serializers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/inm/serializers.py b/apps/inm/serializers.py index 5174c439..afd2d089 100644 --- a/apps/inm/serializers.py +++ b/apps/inm/serializers.py @@ -126,7 +126,7 @@ class MIOItemCreateSerializer(CustomModelSerializer): class Meta: model = MIOItem fields = ['mio', 'warehouse', 'material', - 'batch', 'count', 'assemb', 'is_testok', 'mioitemw', 'mb', 'wm', 'unit_price', 'note', "pack_index"] + 'batch', 'count', 'assemb', 'is_testok', 'mioitemw', 'mb', 'wm', 'unit_price', 'note', "pack_index", "count_send"] extra_kwargs = { 'mio': {'required': True}, 'warehouse': {'required': False}, 'material': {'required': False}, 'batch': {'required': False, "allow_null": True, "allow_blank": True}} From 5fa4881614cff7859236672161f74ba1970f77f8 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Fri, 21 Nov 2025 11:01:59 +0800 Subject: [PATCH 09/12] =?UTF-8?q?feat:=20=E6=89=B9=E6=AC=A1=E5=8F=B7?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E9=94=99=E8=AF=AF=E7=9A=84=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/inm/serializers.py | 2 ++ apps/inm/services_daoru.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/apps/inm/serializers.py b/apps/inm/serializers.py index afd2d089..a1a6a6e6 100644 --- a/apps/inm/serializers.py +++ b/apps/inm/serializers.py @@ -156,6 +156,8 @@ class MIOItemCreateSerializer(CustomModelSerializer): batch = validated_data.get("batch", None) if not batch: batch = "无" + if batch != '无' and len(batch) < 5: + raise ParseError('批次号格式错误') if material.is_hidden: raise ParseError('隐式物料不可出入库') if mio.type in [MIO.MIO_TYPE_RETURN_IN, MIO.MIO_TYPE_BORROW_OUT]: diff --git a/apps/inm/services_daoru.py b/apps/inm/services_daoru.py index a4c8421f..d1bbb2fa 100644 --- a/apps/inm/services_daoru.py +++ b/apps/inm/services_daoru.py @@ -156,6 +156,8 @@ def daoru_mioitems(path:str, mio:MIO): pass else: batch = "无" + if batch != '无' and len(batch) < 5: + raise ParseError('批次号格式错误') count = sheet[f"f{ind}"].value warehouse_name = sheet[f"g{ind}"].value try: From 99df0166f8a4e39676e17fa98ddc9f180b272f68 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Fri, 21 Nov 2025 11:08:02 +0800 Subject: [PATCH 10/12] =?UTF-8?q?feat:=20=E6=89=B9=E6=AC=A1=E5=8F=B7?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E9=94=99=E8=AF=AF=E7=9A=84=E6=A0=A1=E9=AA=8C?= =?UTF-8?q?2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/inm/services_daoru.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/inm/services_daoru.py b/apps/inm/services_daoru.py index d1bbb2fa..a5eb1fc9 100644 --- a/apps/inm/services_daoru.py +++ b/apps/inm/services_daoru.py @@ -157,7 +157,7 @@ def daoru_mioitems(path:str, mio:MIO): else: batch = "无" if batch != '无' and len(batch) < 5: - raise ParseError('批次号格式错误') + raise ParseError(f'第{ind}行批次号{batch}:格式错误') count = sheet[f"f{ind}"].value warehouse_name = sheet[f"g{ind}"].value try: From 081758975850d0777caa45084e49be43e4b7e8e4 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Fri, 21 Nov 2025 15:34:56 +0800 Subject: [PATCH 11/12] =?UTF-8?q?feat:=20=E7=9F=AD=E4=BF=A1=E5=8F=91?= =?UTF-8?q?=E9=80=81=E5=8A=9F=E8=83=BD=E6=9C=AA=E5=BC=80=E5=90=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/utils/sms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/utils/sms.py b/apps/utils/sms.py index 17526cf5..c10e4982 100644 --- a/apps/utils/sms.py +++ b/apps/utils/sms.py @@ -15,7 +15,7 @@ def send_sms(phone: str, template_code: int, template_param: dict): from aliyunsdkcore.request import CommonRequest config = get_sysconfig() if config.get("sms", {}).get('enabled', False) is False: - return False, {} + raise ParseError("短信发送功能未开启") try: client = AcsClient(config['sms']['xn_key'], config['sms']['xn_secret'], 'default') From a58d95843f18dd792559d3c6811020f57aeefdb2 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Fri, 21 Nov 2025 16:24:08 +0800 Subject: [PATCH 12/12] =?UTF-8?q?feat:=20base=20ticketDetail=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0create=5Fby=5Fname?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/wf/serializers.py | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/wf/serializers.py b/apps/wf/serializers.py index 738bb4d9..58e4b8d9 100755 --- a/apps/wf/serializers.py +++ b/apps/wf/serializers.py @@ -149,6 +149,7 @@ class TicketDetailSerializer(CustomModelSerializer): state_ = StateSimpleSerializer(source='state', read_only=True) ticket_data_ = serializers.SerializerMethodField() participant_ = serializers.SerializerMethodField() + create_by_name = serializers.CharField(source='create_by.name', read_only=True) class Meta: model = Ticket