From be8411245bff91358cfe4d381d54660445e37b34 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Fri, 24 Oct 2025 16:33:13 +0800 Subject: [PATCH 1/6] =?UTF-8?q?feat:=20base=20execute=5Fraw=5Fsql=20?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0timeout=E5=8F=82=E6=95=B0=E5=8F=AF=E4=BC=A0no?= =?UTF-8?q?ne=E4=B8=8D=E9=99=90=E6=97=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/utils/sql.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/utils/sql.py b/apps/utils/sql.py index 99497908..0318d5b1 100644 --- a/apps/utils/sql.py +++ b/apps/utils/sql.py @@ -10,7 +10,8 @@ def execute_raw_sql(sql: str, params=None, timeout=30): params (_type_, optional): 参数列表. Defaults to None. """ with connection.cursor() as cursor: - cursor.execute(f"SET statement_timeout TO '{int(timeout*1000)}ms';") + if timeout: + cursor.execute(f"SET statement_timeout TO '{int(timeout*1000)}ms';") if params: cursor.execute(sql, params=params) else: From 1ea8a30d1483ff5d3aaf84139e446ec08a158adc Mon Sep 17 00:00:00 2001 From: caoqianming Date: Fri, 24 Oct 2025 16:33:38 +0800 Subject: [PATCH 2/6] =?UTF-8?q?feat:=20base=20clean=5Ftimescaledb=5Fjob=5F?= =?UTF-8?q?his=20=E4=BC=98=E5=8C=962?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/monitor/tasks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/monitor/tasks.py b/apps/monitor/tasks.py index 27fc56a6..6bec763d 100644 --- a/apps/monitor/tasks.py +++ b/apps/monitor/tasks.py @@ -74,4 +74,4 @@ def clean_timescaledb_job_his(num: int = 30): RAISE NOTICE 'Table _timescaledb_internal.bgw_job_stat_history not found.'; END IF; END$$; - """, timeout=300) \ No newline at end of file + """, timeout=None) \ No newline at end of file From bc0200669b8621418660d2bab3e27e371b352d4d Mon Sep 17 00:00:00 2001 From: caoqianming Date: Mon, 27 Oct 2025 16:33:23 +0800 Subject: [PATCH 3/6] =?UTF-8?q?feat:=20gen=5Fnumber=5Fwith=5Frule=20?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/wpm/views.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/wpm/views.py b/apps/wpm/views.py index 2fb9cbf8..d1dd67cb 100644 --- a/apps/wpm/views.py +++ b/apps/wpm/views.py @@ -948,6 +948,10 @@ class MlogbInViewSet(BulkCreateModelMixin, BulkUpdateModelMixin, BulkDestroyMode c_year2 = str(c_year)[-2:] c_month = handle_date.month m_model = material_out.model + if m_model is None: + raise ParseError("生成编号出错:产品型号不能为空") + elif m_model and m_model.is_lower(): + raise ParseError("生成编号出错:产品型号不能为小写") # 按生产日志查询 wpr = ( Wpr.objects.filter( From 4e817d9954a883e4f7299a7eb0789924d9062943 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Mon, 27 Oct 2025 19:56:14 +0800 Subject: [PATCH 4/6] fix: gen_number_with_rule bug --- apps/wpm/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/wpm/views.py b/apps/wpm/views.py index d1dd67cb..5e0b8551 100644 --- a/apps/wpm/views.py +++ b/apps/wpm/views.py @@ -950,7 +950,7 @@ class MlogbInViewSet(BulkCreateModelMixin, BulkUpdateModelMixin, BulkDestroyMode m_model = material_out.model if m_model is None: raise ParseError("生成编号出错:产品型号不能为空") - elif m_model and m_model.is_lower(): + elif m_model and m_model.islower(): raise ParseError("生成编号出错:产品型号不能为小写") # 按生产日志查询 wpr = ( From dda876092e3504b4bd6b4b17612c3fe53368d7b6 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Tue, 28 Oct 2025 16:22:02 +0800 Subject: [PATCH 5/6] =?UTF-8?q?feat:=20=E7=BC=96=E5=8F=B7=E7=94=9F?= =?UTF-8?q?=E6=88=90=E5=90=8E=E5=9C=A8=E6=8F=90=E4=BA=A4=E6=97=B6=E8=BF=9B?= =?UTF-8?q?=E8=A1=8C=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/wpm/services.py | 7 +++++++ apps/wpm/views.py | 4 +++- apps/wpmw/serializers.py | 4 ++++ apps/wpmw/views.py | 22 +++++++++++++++++++++- 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/apps/wpm/services.py b/apps/wpm/services.py index 14272d61..52d75881 100644 --- a/apps/wpm/services.py +++ b/apps/wpm/services.py @@ -28,6 +28,11 @@ from apps.utils.lock import lock_model_record_d_func myLogger = logging.getLogger('log') +def check_wpr_number(number: str): + return (len(number) >= 5 and + number[-4:].isdigit() and + not any(char.islower() for char in number)) + def generate_new_batch(old_batch: str, mlog: Mlog): new_batch = old_batch supplier = mlog.supplier @@ -372,6 +377,8 @@ def mlog_submit(mlog: Mlog, user: User, now: Union[datetime.datetime, None]): if item.wpr: Wpr.change_or_new(wpr=item.wpr, wm=wm, ftest=item.ftest) else: + if not check_wpr_number(item.number): + raise ParseError(f'{item.number} 该编号格式有误') wpr_from = None if item.mlogbw_from: wpr_from = item.mlogbw_from.wpr diff --git a/apps/wpm/views.py b/apps/wpm/views.py index 5e0b8551..456cded1 100644 --- a/apps/wpm/views.py +++ b/apps/wpm/views.py @@ -65,6 +65,7 @@ from django.db.models import Prefetch from drf_yasg.utils import swagger_auto_schema from drf_yasg import openapi from django.db import connection +from django.db.models.functions import Substr, Length # Create your views here. @@ -962,7 +963,8 @@ class MlogbInViewSet(BulkCreateModelMixin, BulkUpdateModelMixin, BulkDestroyMode wpr_mlogbw__mlogb__mlog__handle_date__year=c_year, wpr_mlogbw__mlogb__mlog__handle_date__month=c_month, ) - .order_by("number") + .annotate(last_four=Substr("number", Length("number")-3)) + .order_by("last_four") .last() ) cq_w = 4 diff --git a/apps/wpmw/serializers.py b/apps/wpmw/serializers.py index 8191af4d..707d74eb 100644 --- a/apps/wpmw/serializers.py +++ b/apps/wpmw/serializers.py @@ -51,3 +51,7 @@ class WproutSerializer(serializers.Serializer): class WproutListSerializer(serializers.Serializer): items = WproutSerializer(many=True) + +class WprChangeNumberSerializer(serializers.Serializer): + old_number = serializers.CharField(label="原编号") + new_number = serializers.CharField(label="新编号") \ No newline at end of file diff --git a/apps/wpmw/views.py b/apps/wpmw/views.py index 3c9a9a59..5aaa1eac 100644 --- a/apps/wpmw/views.py +++ b/apps/wpmw/views.py @@ -3,7 +3,7 @@ from apps.utils.viewsets import CustomModelViewSet, CustomGenericViewSet from apps.utils.mixins import CustomListModelMixin, RetrieveModelMixin, ComplexQueryMixin from apps.wpmw.models import Wpr, WprDefect -from apps.wpmw.serializers import WprSerializer, WprNewSerializer, WprDetailSerializer, WproutListSerializer +from apps.wpmw.serializers import WprSerializer, WprNewSerializer, WprDetailSerializer, WproutListSerializer, WprChangeNumberSerializer from rest_framework.response import Response from apps.mtm.models import Material from rest_framework.exceptions import ParseError @@ -41,6 +41,26 @@ class WprViewSet(CustomListModelMixin, RetrieveModelMixin, ComplexQueryMixin, Cu else: qs.exclude(mb=None, wm=None) return qs + + @action(methods=["post"], detail=False, perms_map={"post": "*"}, serializer_class=WprChangeNumberSerializer) + @transaction.atomic + def change_number(self, request, *args, **kwargs): + """修改编号""" + sr = WprChangeNumberSerializer(data=request.data) + sr.is_valid(raise_exception=True) + vdata = sr.validated_data + new_number = vdata["new_number"] + old_number = vdata["old_number"] + if Wpr.objects.filter(number=new_number).exists(): + raise ParseError("新编号已存在,不可使用") + wpr = Wpr.objects.get(number=old_number) + from apps.wpm.models import Mlogbw, Handoverbw + from apps.inm.models import MIOItemw + Wpr.objects.filter(id=wpr.id).update(number=new_number) + Mlogbw.objects.filter(wpr=wpr).update(number=new_number) + Handoverbw.objects.filter(wpr=wpr).update(number=new_number) + MIOItemw.objects.filter(wpr=wpr).update(number=new_number) + return Response() @action(methods=["post"], detail=False, perms_map={"post": "*"}, serializer_class=WprNewSerializer) def new_number(self, request, *args, **kwargs): From fa2edf72985c69af8611d93cd5df8577e99427d5 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Tue, 28 Oct 2025 16:55:36 +0800 Subject: [PATCH 6/6] =?UTF-8?q?fix:=20wpr=5Fbxerp=20=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E7=BB=9F=E8=AE=A1=E5=9C=A8mlogbw=E5=AD=98=E5=9C=A8=E6=89=8D?= =?UTF-8?q?=E7=BB=A7=E7=BB=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/wpm/scripts/wpr_bxerp.py | 49 ++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/apps/wpm/scripts/wpr_bxerp.py b/apps/wpm/scripts/wpr_bxerp.py index 851a3376..011ae5d2 100644 --- a/apps/wpm/scripts/wpr_bxerp.py +++ b/apps/wpm/scripts/wpr_bxerp.py @@ -9,27 +9,28 @@ def main(wprId, mgroup:Mgroup): data = {} mgroup_name = mgroup.name mlogbw = Mlogbw.objects.filter(wpr=wpr, mlogb__mlog__submit_time__isnull=False).order_by("-update_time").first() - data[f"{mgroup_name}_批次号"] = mlogbw.mlogb.batch - data[f"{mgroup_name}_日期"] = mlogbw.mlogb.mlog.handle_date.strftime("%Y-%m-%d") - ftestitems = FtestItem.objects.filter(ftest__mlogbw_ftest__wpr=wpr, - ftest__mlogbw_ftest__mlogb__mlog__mgroup=mgroup, - ftest__mlogbw_ftest__mlogb__mlog__submit_time__isnull=False, - ftest__mlogbw_ftest__mlogb__mlog__is_fix=False) - for ftestitem in ftestitems: - data[f"{mgroup_name}_检测项_{ftestitem.testitem.name}"] = ftestitem.test_val_json - - ftestdefects = FtestDefect.objects.filter(ftest__mlogbw_ftest__wpr=wpr, - ftest__mlogbw_ftest__mlogb__mlog__mgroup=mgroup, - ftest__mlogbw_ftest__mlogb__mlog__submit_time__isnull=False, - ftest__mlogbw_ftest__mlogb__mlog__is_fix=False) - for ftestdefect in ftestdefects: - data[f"{mgroup_name}_缺陷项_{ftestdefect.defect.name}"] = 1 if ftestdefect.has is True else 0 - - old_data:dict = wpr.data - if old_data: - for item in list(old_data.keys()): - if f'{mgroup_name}_' in item: - del old_data[item] - old_data.update(data) - wpr.data = old_data - wpr.save(update_fields=["data"]) \ No newline at end of file + if mlogbw: + data[f"{mgroup_name}_批次号"] = mlogbw.mlogb.batch + data[f"{mgroup_name}_日期"] = mlogbw.mlogb.mlog.handle_date.strftime("%Y-%m-%d") + ftestitems = FtestItem.objects.filter(ftest__mlogbw_ftest__wpr=wpr, + ftest__mlogbw_ftest__mlogb__mlog__mgroup=mgroup, + ftest__mlogbw_ftest__mlogb__mlog__submit_time__isnull=False, + ftest__mlogbw_ftest__mlogb__mlog__is_fix=False) + for ftestitem in ftestitems: + data[f"{mgroup_name}_检测项_{ftestitem.testitem.name}"] = ftestitem.test_val_json + + ftestdefects = FtestDefect.objects.filter(ftest__mlogbw_ftest__wpr=wpr, + ftest__mlogbw_ftest__mlogb__mlog__mgroup=mgroup, + ftest__mlogbw_ftest__mlogb__mlog__submit_time__isnull=False, + ftest__mlogbw_ftest__mlogb__mlog__is_fix=False) + for ftestdefect in ftestdefects: + data[f"{mgroup_name}_缺陷项_{ftestdefect.defect.name}"] = 1 if ftestdefect.has is True else 0 + + old_data:dict = wpr.data + if old_data: + for item in list(old_data.keys()): + if f'{mgroup_name}_' in item: + del old_data[item] + old_data.update(data) + wpr.data = old_data + wpr.save(update_fields=["data"]) \ No newline at end of file