From 808a1c825dc453f7cebdc35820dd8f12bc21dea8 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Mon, 19 Aug 2024 08:59:24 +0800 Subject: [PATCH 1/8] feat: check_opl_audit_imgs raise --- apps/opm/services.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opm/services.py b/apps/opm/services.py index c22df23f..88f0ed81 100644 --- a/apps/opm/services.py +++ b/apps/opm/services.py @@ -188,4 +188,4 @@ def check_opl_audit_imgs(ticket: Ticket, transition: Transition, new_ticket_data opl.audit_imgs = audit_imgs opl.save() else: - raise Exception('需提交审核照片') \ No newline at end of file + raise ParseError('需提交审核照片') \ No newline at end of file From 9ce56d3f34439376cfb9fa6144646c23c5f7c7a3 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Mon, 19 Aug 2024 11:35:36 +0800 Subject: [PATCH 2/8] =?UTF-8?q?feat:=20ftestwork=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=85=B3=E8=81=94=E4=BB=93=E5=BA=93=E5=BA=93=E5=AD=98=E5=AD=97?= =?UTF-8?q?=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/qm/migrations/0021_ftestwork_mb.py | 20 ++++++++++ apps/qm/models.py | 1 + apps/qm/serializers.py | 50 ++++++++++++++----------- apps/qm/views.py | 4 +- 4 files changed, 53 insertions(+), 22 deletions(-) create mode 100644 apps/qm/migrations/0021_ftestwork_mb.py diff --git a/apps/qm/migrations/0021_ftestwork_mb.py b/apps/qm/migrations/0021_ftestwork_mb.py new file mode 100644 index 00000000..72b4cba5 --- /dev/null +++ b/apps/qm/migrations/0021_ftestwork_mb.py @@ -0,0 +1,20 @@ +# Generated by Django 3.2.12 on 2024-08-19 03:25 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('inm', '0001_initial'), + ('qm', '0020_auto_20240814_1756'), + ] + + operations = [ + migrations.AddField( + model_name='ftestwork', + name='mb', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='inm.materialbatch', verbose_name='关联仓库'), + ), + ] diff --git a/apps/qm/models.py b/apps/qm/models.py index 55437375..e069a46d 100644 --- a/apps/qm/models.py +++ b/apps/qm/models.py @@ -108,6 +108,7 @@ class FtestWork(CommonBDModel): type = models.CharField('检验类型', max_length=20, choices=FTEST_TYPE_CHOICES, default='prod') type2 = models.PositiveSmallIntegerField('检验类型2', choices=((10, '抽检'), (20, '全检')), default=10) wm = models.ForeignKey(WMaterial, verbose_name='关联车间库存', on_delete=models.SET_NULL, null=True, blank=True) + mb = models.ForeignKey('inm.materialbatch', verbose_name='关联仓库', on_delete=models.SET_NULL, null=True, blank=True) test_date = models.DateField('检验日期') material = models.ForeignKey( Material, verbose_name='产品', on_delete=models.CASCADE) diff --git a/apps/qm/serializers.py b/apps/qm/serializers.py index 28d12c88..47e1561b 100644 --- a/apps/qm/serializers.py +++ b/apps/qm/serializers.py @@ -6,6 +6,7 @@ from rest_framework.exceptions import ValidationError from apps.system.models import Dept, Dictionary from apps.wpm.models import SfLog, WMaterial from django.db import transaction +from apps.inm.serializers import MaterialBatchDetailSerializer class TestItemSerializer(CustomModelSerializer): @@ -62,33 +63,39 @@ class QuaStatUpdateSerializer(CustomModelSerializer): class FtestWorkCreateUpdateSerializer(CustomModelSerializer): class Meta: model = FtestWork - fields = ['id', 'wm', 'type', 'type2', 'test_date', 'count', 'count_sampling', 'count_ok', 'count_notok', 'count_notok_json', 'test_user'] + fields = ['id', 'wm', 'mb', 'type', 'type2', 'test_date', 'count', 'count_sampling', 'count_ok', 'count_notok', 'count_notok_json', 'test_user'] extra_kwargs = {'test_user': {'required': True}, 'type': {'required': True}} def validate(self, attrs): type2 = attrs.get('type2', 20) if type2 == 20: # 如果是全检 attrs['count_sampling'] = attrs['count'] - if 'wm' not in attrs: - raise ValidationError('请选择车间库存') - wm:WMaterial = attrs['wm'] - if wm.state not in [WMaterial.WM_OK, WMaterial.WM_TEST]: - raise ValidationError('不支持对该物料检验') - attrs['material'] = wm.material - attrs['batch'] = wm.batch - count_notok_json = attrs.get('count_notok_json', None) - if count_notok_json is None: - raise ValidationError('不合格项不能为空') - count_notok = 0 - for k, v in count_notok_json.items(): - k_2 = k.replace('count_n_', '') - if k_2 not in NotOkOption.values: - raise ValidationError(f'不支持的不合格项{k_2}') - if isinstance(v, int) and v >= 0: - count_notok = count_notok + v - else: - raise ValidationError(f'不合格项{k_2}必须为非负整数') - attrs['count_notok'] = count_notok + if 'wm' in attrs and attrs['wm']: + attrs['mb'] = None + wm:WMaterial = attrs['wm'] + if wm.state not in [WMaterial.WM_OK, WMaterial.WM_TEST]: + raise ValidationError('不支持对该物料检验') + attrs['material'] = wm.material + attrs['batch'] = wm.batch + count_notok_json = attrs.get('count_notok_json', None) + if count_notok_json is None: + raise ValidationError('不合格项不能为空') + count_notok = 0 + for k, v in count_notok_json.items(): + k_2 = k.replace('count_n_', '') + if k_2 not in NotOkOption.values: + raise ValidationError(f'不支持的不合格项{k_2}') + if isinstance(v, int) and v >= 0: + count_notok = count_notok + v + else: + raise ValidationError(f'不合格项{k_2}必须为非负整数') + attrs['count_notok'] = count_notok + elif 'mb' in attrs and attrs['mb']: + attrs['wm'] = None + attrs['material'] = attrs['mb'].material + attrs['batch'] = attrs['mb'].batch + else: + raise ValidationError('请选择车间/仓库库存') return attrs @@ -96,6 +103,7 @@ class FtestWorkSerializer(CustomModelSerializer): material_name = serializers.StringRelatedField( source='material', read_only=True) material_cate = serializers.CharField(source='material.cate', read_only=True) + mb_ = MaterialBatchDetailSerializer(source='mb', read_only=True) class Meta: model = FtestWork diff --git a/apps/qm/views.py b/apps/qm/views.py index 9e11f534..f03aa727 100644 --- a/apps/qm/views.py +++ b/apps/qm/views.py @@ -125,7 +125,7 @@ class FtestWorkViewSet(CustomModelViewSet): serializer_class = FtestWorkSerializer create_serializer_class = FtestWorkCreateUpdateSerializer update_serializer_class = FtestWorkCreateUpdateSerializer - select_related_fields = ['material'] + select_related_fields = ['material', 'mb', 'mb__material'] filterset_class = FtestWorkFilter def update(self, request, *args, **kwargs): @@ -148,6 +148,8 @@ class FtestWorkViewSet(CustomModelViewSet): 提交检验工作 """ ins:FtestWork = self.get_object() + if ins.wm is None: + raise ParseError('该检验工作未关联车间库存') if ins.submit_time is None: ftestwork_submit(ins, request.user) else: From 28958b405c47fc44b7636ae4049a7e15cf9171ad Mon Sep 17 00:00:00 2001 From: caoqianming Date: Mon, 19 Aug 2024 13:41:47 +0800 Subject: [PATCH 3/8] fix: check_opl_audit_imgs bug --- apps/opm/services.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opm/services.py b/apps/opm/services.py index 88f0ed81..d9ef2c7f 100644 --- a/apps/opm/services.py +++ b/apps/opm/services.py @@ -185,7 +185,7 @@ def check_opl_audit_imgs(ticket: Ticket, transition: Transition, new_ticket_data audit_imgs = new_ticket_data.get('audit_imgs', []) if audit_imgs: opl = Opl.objects.get(ticket=ticket) - opl.audit_imgs = audit_imgs + opl.audit_imgs.set(audit_imgs) opl.save() else: raise ParseError('需提交审核照片') \ No newline at end of file From e2d652f9ef2dabcee377442afa23a28b1b720a82 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Mon, 19 Aug 2024 16:17:33 +0800 Subject: [PATCH 4/8] =?UTF-8?q?fix:=20get=5Farea=5Ffrom=5Fpoint=20?= =?UTF-8?q?=E8=8E=B7=E5=8F=96cache=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/ecm/service.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/ecm/service.py b/apps/ecm/service.py index bdf3471d..c85e5592 100644 --- a/apps/ecm/service.py +++ b/apps/ecm/service.py @@ -663,7 +663,8 @@ def get_area_from_point(x: int, y: int, floorNo: str, area_fix_id): area_temp = None area_list = cache.get('area_list', None) if not area_list: - area_list = cache_areas_info() + cache_areas_info() + area_list = cache.get('area_list', None) point = Point(x, y) for i in area_list: if floorNo == i['floor_no']: From d102f01c26e56dc5908d2d3b42fa2e6ad0a9f3a6 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Mon, 19 Aug 2024 16:51:46 +0800 Subject: [PATCH 5/8] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0check=5Fopl=5Fwor?= =?UTF-8?q?k=5Fimgs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/opm/services.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/apps/opm/services.py b/apps/opm/services.py index d9ef2c7f..8d425ad8 100644 --- a/apps/opm/services.py +++ b/apps/opm/services.py @@ -188,4 +188,14 @@ def check_opl_audit_imgs(ticket: Ticket, transition: Transition, new_ticket_data opl.audit_imgs.set(audit_imgs) opl.save() else: - raise ParseError('需提交审核照片') \ No newline at end of file + raise ParseError('需提交审核照片') + + +def check_opl_work_imgs(ticket: Ticket, transition: Transition, new_ticket_data: dict): + work_imgs = new_ticket_data.get('work_imgs', []) + if work_imgs: + opl = Opl.objects.get(ticket=ticket) + opl.work_imgs.set(work_imgs) + opl.save() + else: + raise ParseError('需提交作业开始照片') \ No newline at end of file From 592e34c07e6ec88d170093693475da6bca911fd8 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Tue, 20 Aug 2024 08:56:08 +0800 Subject: [PATCH 6/8] =?UTF-8?q?refector:=20mgroup=5Fon=5Fchange=E6=97=B6?= =?UTF-8?q?=E5=88=9B=E5=BB=BAstlog=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/mtm/services.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/apps/mtm/services.py b/apps/mtm/services.py index 3813a6ad..73f7e213 100644 --- a/apps/mtm/services.py +++ b/apps/mtm/services.py @@ -127,9 +127,16 @@ def mgroup_run_change(mgroup: Mgroup, new_run: bool, last_timex: datetime): last_stlog.save() cal_exp_duration_sec(last_stlog.id) # 触发时间分配 elif last_stlog.end_time and new_run is False and last_timex > last_stlog.end_time: # 从开到停 - has_same_stlog =StLog.objects.filter(mgroup=mgroup, is_shutdown=True, start_time=last_timex).exists() - if not has_same_stlog: - StLog.objects.create(title="停机", is_shutdown=True, mgroup=mgroup, end_time=None, start_time=last_timex, sflog=get_sflog(mgroup, last_timex)) + StLog.objects.get_or_create( + mgroup=mgroup, + is_shutdown=True, + start_time=last_timex, + defaults={ + 'title': '停机', + 'end_time': None, + 'sflog': get_sflog(mgroup, last_timex) + } + ) elif new_run is False: StLog.objects.create(title="停机", is_shutdown=True, mgroup=mgroup, end_time=None, start_time=last_timex, sflog=get_sflog(mgroup, last_timex)) mgroup.is_running = False From 561c2a0c31b813d4fdb285972225d5348b5c2c07 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Tue, 20 Aug 2024 14:25:01 +0800 Subject: [PATCH 7/8] =?UTF-8?q?feat:=20materialbatch=E4=B9=9F=E4=B8=8D?= =?UTF-8?q?=E8=BF=9B=E8=A1=8C=E7=89=A9=E7=90=86=E5=88=A0=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/inm/services.py | 7 ++++--- apps/inm/views.py | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/apps/inm/services.py b/apps/inm/services.py index d40768fe..78c5e672 100644 --- a/apps/inm/services.py +++ b/apps/inm/services.py @@ -87,7 +87,10 @@ class InmService: material = i.material warehouse = i.warehouse mb, is_created = MaterialBatch.objects.get_or_create( - material=material, warehouse=warehouse, batch=i.batch, defaults={"material": material, "warehouse": warehouse, "count": 0, "batch": i.batch} + material=material, + warehouse=warehouse, + batch=i.batch, + defaults={"material": material, "warehouse": warehouse, "count": 0, "batch": i.batch} ) if in_or_out == 1: mb.count = mb.count + getattr(i, field) @@ -107,8 +110,6 @@ class InmService: mb.count = mb.count - getattr(i, field) if mb.count < 0: raise ParseError("批次库存不足,操作失败") - elif mb.count == 0: - mb.delete() else: mb.save() else: diff --git a/apps/inm/views.py b/apps/inm/views.py index 6a69ba24..5e879f1c 100644 --- a/apps/inm/views.py +++ b/apps/inm/views.py @@ -45,7 +45,7 @@ class MaterialBatchViewSet(ListModelMixin, CustomGenericViewSet): 物料批次 """ perms_map = {'get': '*'} - queryset = MaterialBatch.objects.all() + queryset = MaterialBatch.objects.filter(count__gt=0) serializer_class = MaterialBatchSerializer retrieve_serializer_class = MaterialBatchDetailSerializer select_related_fields = ['warehouse', 'material'] From 1e667e69ac73325cd31dc223a2c767eb20984e6a Mon Sep 17 00:00:00 2001 From: caoqianming Date: Tue, 20 Aug 2024 14:39:38 +0800 Subject: [PATCH 8/8] =?UTF-8?q?feat:=20daoru=5Fmaterial=20=E5=A2=9E?= =?UTF-8?q?=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/mtm/services.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/apps/mtm/services.py b/apps/mtm/services.py index 73f7e213..06cac779 100644 --- a/apps/mtm/services.py +++ b/apps/mtm/services.py @@ -73,21 +73,24 @@ def daoru_material(path: str): type_str = sheet[f'b{i}'].value.replace(' ', '') try: type = type_dict[type_str] - number = sheet[f'a{i}'].value.replace(' ', '') - name = sheet[f'c{i}'].value.replace(' ', '') + number = sheet[f'a{i}'].value.replace(' ', '') if sheet[f'a{i}'].value else None + if sheet[f'c{i}'].value: + name = sheet[f'c{i}'].value.replace(' ', '') + else: + raise ParseError(f'{i}行物料信息错误: 物料名称必填') specification = sheet[f'd{i}'].value.replace( - '×', '*').replace(' ', '') - model = sheet[f'e{i}'].value.replace(' ', '') + '×', '*').replace(' ', '') if sheet[f'd{i}'].value else None + model = sheet[f'e{i}'].value.replace(' ', '') if sheet[f'e{i}'].value else None unit = sheet[f'f{i}'].value.replace(' ', '') count_safe = sheet[f'h{i}'].value unit_price = sheet[f'i{i}'].value except Exception as e: - raise ParseError(f'{i}行物料信息错误: {str(e)}') + raise ParseError(f'{i}行物料信息错误: {e}') if type in [20, 30]: try: process = process_d[sheet[f'g{i}'].value.replace(' ', '')] except Exception as e: - raise ParseError(f'{i}行物料信息错误: {str(e)}') + raise ParseError(f'{i}行物料信息错误: {e}') try: filters = {'type': type, 'name': name, 'specification': specification, 'model': model, 'unit__iexact': unit}