diff --git a/apps/wpm/migrations/0067_auto_20240904_0903.py b/apps/wpm/migrations/0067_auto_20240904_0903.py new file mode 100644 index 00000000..7b2a4520 --- /dev/null +++ b/apps/wpm/migrations/0067_auto_20240904_0903.py @@ -0,0 +1,42 @@ +# Generated by Django 3.2.12 on 2024-09-04 01:03 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('mtm', '0041_process_mstate_json'), + ('pm', '0020_mtaskb'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('wpm', '0066_auto_20240903_1401'), + ] + + operations = [ + migrations.CreateModel( + name='Fmlog', + fields=[ + ('id', models.CharField(editable=False, help_text='主键ID', max_length=20, primary_key=True, serialize=False, verbose_name='主键ID')), + ('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')), + ('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')), + ('is_deleted', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')), + ('note', models.TextField(blank=True, default='', verbose_name='备注')), + ('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='fmlog_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')), + ('mgroup', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='fmlog_mgroup', to='mtm.mgroup', verbose_name='工段')), + ('mtask', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='fmlog_mtask', to='pm.mtask', verbose_name='任务')), + ('route', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='mtm.route', verbose_name='生产路线')), + ('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='fmlog_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')), + ], + options={ + 'abstract': False, + }, + ), + migrations.AddField( + model_name='mlog', + name='fmlog', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='mlog_fmlog', to='wpm.fmlog', verbose_name='关联生产日志'), + ), + ] diff --git a/apps/wpm/models.py b/apps/wpm/models.py index 9c91e58a..ea45c53f 100644 --- a/apps/wpm/models.py +++ b/apps/wpm/models.py @@ -107,6 +107,12 @@ class WMaterial(CommonBDModel): count_xtest = models.PositiveIntegerField('已检数量', null=True, blank=True) +class Fmlog(CommonADModel): + route = models.ForeignKey(Route, verbose_name='生产路线', on_delete=models.SET_NULL, null=True, blank=True) + mtask = models.ForeignKey(Mtask, verbose_name='任务', on_delete=models.CASCADE, related_name='fmlog_mtask') + mgroup = models.ForeignKey(Mgroup, verbose_name='工段', on_delete=models.CASCADE, related_name='fmlog_mgroup') + note = models.TextField('备注', default='', blank=True) + class Mlog(CommonADModel): """ 生产日志 @@ -116,6 +122,7 @@ class Mlog(CommonADModel): MLOG_STEP = 20 MTYPE_SELF = 10 MTYPE_OUT = 20 + fmlog = models.ForeignKey(Fmlog, verbose_name='关联生产日志', on_delete=models.SET_NULL, null=True, blank=True, related_name='mlog_fmlog') fill_way = models.PositiveSmallIntegerField("填写方式", default=10, help_text='10:一次填写;20:分步填写') mtype = models.PositiveSmallIntegerField('生产类型', default=10, help_text='10:自生产;20:外协生产', choices=((10, '自生产'), (20, '外协生产'))) supplier = models.ForeignKey(Supplier, verbose_name='外协供应商', on_delete=models.SET_NULL, null=True, blank=True) diff --git a/apps/wpm/serializers.py b/apps/wpm/serializers.py index 46fdf69e..42338ecc 100644 --- a/apps/wpm/serializers.py +++ b/apps/wpm/serializers.py @@ -4,7 +4,7 @@ from rest_framework import serializers from rest_framework.exceptions import ValidationError, ParseError from datetime import datetime -from .models import SfLog, StLog, SfLogExp, WMaterial, Mlog, Handover, Mlogb, AttLog, OtherLog +from .models import SfLog, StLog, SfLogExp, WMaterial, Mlog, Handover, Mlogb, AttLog, OtherLog, Fmlog from apps.system.models import Dept, User from apps.system.serializers import UserSimpleSerializer from apps.pm.models import Mtask @@ -597,3 +597,18 @@ class AttLogSerializer(CustomModelSerializer): class Meta: model = AttLog fields = '__all__' + + +class FmlogSerializer(CustomModelSerializer): + routepack_name = serializers.CharField( + source='route.routepack.name', read_only=True) + mtask_number = serializers.CharField(source='mtask.number', read_only=True) + class Meta: + model = Fmlog + fields = '__all__' + read_only_fields = EXCLUDE_FIELDS + +class FmlogUpdateSerializer(CustomModelSerializer): + class Meta: + model = Fmlog + fields = ['id', 'note'] \ No newline at end of file diff --git a/apps/wpm/urls.py b/apps/wpm/urls.py index 005f4377..3de12711 100644 --- a/apps/wpm/urls.py +++ b/apps/wpm/urls.py @@ -3,7 +3,8 @@ from rest_framework.routers import DefaultRouter from apps.wpm.views import (SfLogViewSet, StLogViewSet, SfLogExpViewSet, WMaterialViewSet, MlogViewSet, HandoverViewSet, - AttlogViewSet, OtherLogViewSet, MlogbViewSet, MlogbInViewSet, MlogbOutViewSet) + AttlogViewSet, OtherLogViewSet, MlogbViewSet, MlogbInViewSet, + MlogbOutViewSet, FmlogViewSet) API_BASE_URL = 'api/wpm/' @@ -14,6 +15,7 @@ router.register('sflog', SfLogViewSet, basename='sflog') router.register('stlog', StLogViewSet, basename='stlog') router.register('sflogexp', SfLogExpViewSet, basename='sflogexp') router.register('wmaterial', WMaterialViewSet, basename='wmaterial') +router.register('fmlog', FmlogViewSet, basename='fmlog') router.register('mlog', MlogViewSet, basename='mlog') router.register('mlogb', MlogbViewSet) router.register('mlogb/in', MlogbInViewSet) diff --git a/apps/wpm/views.py b/apps/wpm/views.py index 6365295e..525951b2 100644 --- a/apps/wpm/views.py +++ b/apps/wpm/views.py @@ -16,12 +16,13 @@ from apps.utils.viewsets import CustomGenericViewSet, CustomModelViewSet from apps.utils.mixins import BulkCreateModelMixin from .filters import StLogFilter, SfLogFilter, WMaterialFilter, MlogFilter, HandoverFilter, MlogbFilter -from .models import SfLog, SfLogExp, StLog, WMaterial, Mlog, Handover, Mlogb, AttLog, OtherLog +from .models import SfLog, SfLogExp, StLog, WMaterial, Mlog, Handover, Mlogb, AttLog, OtherLog, Fmlog from .serializers import (SflogExpSerializer, SfLogSerializer, StLogSerializer, WMaterialSerializer, MlogRevertSerializer, MlogSerializer, MlogRelatedSerializer, DeptBatchSerializer, HandoverSerializer, HandoverUpdateSerializer, GenHandoverSerializer, GenHandoverWmSerializer, MlogAnaSerializer, AttLogSerializer, OtherLogSerializer, MlogInitSerializer, MlogChangeSerializer, - MlogbDetailSerializer, MlogbInSerializer, MlogbInUpdateSerializer, MlogbOutUpdateSerializer) + MlogbDetailSerializer, MlogbInSerializer, MlogbInUpdateSerializer, + MlogbOutUpdateSerializer, FmlogSerializer, FmlogUpdateSerializer) from .services import mlog_submit, update_mtask, handover_submit, mlog_revert, cal_material_count_from_mlog, cal_mtask_progress_from_mlog from apps.utils.thread import MyThread from apps.monitor.services import create_auditlog, delete_auditlog @@ -497,4 +498,19 @@ class MlogbInViewSet(CreateModelMixin, UpdateModelMixin, DestroyModelMixin, Cust class MlogbOutViewSet(UpdateModelMixin, CustomGenericViewSet): perms_map = {"put": "mlog.update"} queryset = Mlogb.objects.filter(material_out__isnull=False) - serializer_class = MlogbOutUpdateSerializer \ No newline at end of file + serializer_class = MlogbOutUpdateSerializer + + +class FmlogViewSet(CustomModelViewSet): + perms_map = {'get': '*', 'post': 'mlog.create', 'put': 'mlog.update', 'delete': 'mlog.delete'} + queryset = Fmlog.objects.all() + serializer_class = FmlogSerializer + update_serializer_class = FmlogUpdateSerializer + filterset_fields = ['mtask', 'mgroup', 'route'] + select_related_fields = ['mtask', 'mgroup', 'route', 'route__routepack'] + + def destroy(self, request, *args, **kwargs): + ins = self.get_object() + if Mlog.objects.filter(fmlog=ins).exists(): + raise ParseError('因存在二级日志不可删除') + return super().destroy(request, *args, **kwargs) \ No newline at end of file