diff --git a/apps/wpm/migrations/0017_auto_20231031_0944.py b/apps/wpm/migrations/0017_auto_20231031_0944.py new file mode 100644 index 00000000..f23f58e3 --- /dev/null +++ b/apps/wpm/migrations/0017_auto_20231031_0944.py @@ -0,0 +1,63 @@ +# Generated by Django 3.2.12 on 2023-10-31 01:44 + +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', '0020_material_cate'), + ('system', '0002_myschedule'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('wpm', '0016_auto_20231030_1645'), + ] + + operations = [ + migrations.RemoveField( + model_name='mlog', + name='count_real_weight', + ), + migrations.AddField( + model_name='mlog', + name='count_real_eweight', + field=models.FloatField(default=0, verbose_name='单数重量'), + ), + migrations.AlterField( + model_name='mlog', + name='handle_user', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='mlog_handle_user', to=settings.AUTH_USER_MODEL, verbose_name='操作人'), + ), + migrations.AlterField( + model_name='mlog', + name='note', + field=models.TextField(default='', verbose_name='备注'), + ), + migrations.CreateModel( + name='Handover', + 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='删除标记')), + ('send_date', models.DateField(verbose_name='送料日期')), + ('batch', models.CharField(max_length=50, verbose_name='批次号')), + ('count', models.PositiveIntegerField(default=0, verbose_name='送料数')), + ('count_eweight', models.FloatField(default=0, verbose_name='单数重量')), + ('doin_date', models.DateField(blank=True, null=True, verbose_name='加料日期')), + ('doout_date', models.DateField(blank=True, null=True, verbose_name='出料日期')), + ('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='handover_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')), + ('material', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='mtm.material', verbose_name='物料')), + ('mlog', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='handover_mlog', to='wpm.mlog', verbose_name='关联日志记录')), + ('recive_dept', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='handover_recive_dept', to='system.dept', verbose_name='接收部门')), + ('recive_user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='接收人')), + ('send_dept', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='handover_send_dept', to='system.dept', verbose_name='送料部门')), + ('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='handover_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/apps/wpm/migrations/0018_auto_20231031_0950.py b/apps/wpm/migrations/0018_auto_20231031_0950.py new file mode 100644 index 00000000..eedd8561 --- /dev/null +++ b/apps/wpm/migrations/0018_auto_20231031_0950.py @@ -0,0 +1,26 @@ +# Generated by Django 3.2.12 on 2023-10-31 01:50 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('wpm', '0017_auto_20231031_0944'), + ] + + operations = [ + migrations.AddField( + model_name='handover', + name='send_user', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='handover_send_user', to=settings.AUTH_USER_MODEL, verbose_name='交送人'), + ), + migrations.AlterField( + model_name='handover', + name='recive_user', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='handover_recive_user', to=settings.AUTH_USER_MODEL, verbose_name='接收人'), + ), + ] diff --git a/apps/wpm/models.py b/apps/wpm/models.py index 9989b865..63d4cc1b 100644 --- a/apps/wpm/models.py +++ b/apps/wpm/models.py @@ -5,6 +5,7 @@ from apps.pm.models import Mtask from apps.system.models import User from django.utils.timezone import localtime from apps.em.models import Equipment +from apps.system.models import Dept # Create your models here. @@ -93,7 +94,8 @@ class Mlog(CommonADModel): batch = models.CharField('批次号', max_length=50) count_use = models.PositiveIntegerField('领用数', default=0) count_real = models.PositiveIntegerField('实际生产数', default=0) - count_real_weight = models.FloatField('生产重量', default=0) + count_real_eweight = models.FloatField('单数重量', default=0) + count_ok = models.PositiveIntegerField('合格数', default=0) count_notok = models.PositiveIntegerField('不合格数', default=0) @@ -109,9 +111,33 @@ class Mlog(CommonADModel): handle_date = models.DateField('操作日期') handle_user = models.ForeignKey( - User, verbose_name='操作人', on_delete=models.CASCADE, related_name='mlog_handle_user') + User, verbose_name='操作人', on_delete=models.CASCADE, related_name='mlog_handle_user', null=True, blank=True) handle_users = models.ManyToManyField( User, verbose_name='操作人(多选)', blank=True) handle_leader = models.ForeignKey( User, verbose_name='班长', on_delete=models.CASCADE, null=True, blank=True, related_name='mlog_handle_leader') - note = models.TextField('备注', default=0) + note = models.TextField('备注', default='') + + +class Handover(CommonADModel): + """ + 交接记录 + """ + send_date = models.DateField('送料日期') + send_user = models.ForeignKey( + User, verbose_name='交送人', on_delete=models.CASCADE, related_name='handover_send_user', null=True, blank=True) + send_dept = models.ForeignKey( + Dept, verbose_name='送料部门', on_delete=models.CASCADE, related_name='handover_send_dept') + batch = models.CharField('批次号', max_length=50) + material = models.ForeignKey( + Material, verbose_name='物料', on_delete=models.CASCADE, null=True, blank=True) + count = models.PositiveIntegerField('送料数', default=0) + count_eweight = models.FloatField('单数重量', default=0) + recive_dept = models.ForeignKey( + Dept, verbose_name='接收部门', on_delete=models.CASCADE, related_name='handover_recive_dept') + recive_user = models.ForeignKey( + User, verbose_name='接收人', on_delete=models.CASCADE, related_name='handover_recive_user') + mlog = models.ForeignKey(Mlog, verbose_name='关联日志记录', + on_delete=models.SET_NULL, null=True, blank=True, related_name='handover_mlog') + doin_date = models.DateField('加料日期', null=True, blank=True) + doout_date = models.DateField('出料日期', null=True, blank=True) diff --git a/apps/wpm/serializers.py b/apps/wpm/serializers.py index f012bea2..0ddded68 100644 --- a/apps/wpm/serializers.py +++ b/apps/wpm/serializers.py @@ -3,11 +3,11 @@ from apps.utils.serializers import CustomModelSerializer from rest_framework import serializers from rest_framework.exceptions import ValidationError -from .models import SfLog, StLog, SfLogExp, WMaterial, Mlog -from apps.system.models import Dictionary +from .models import SfLog, StLog, SfLogExp, WMaterial, Mlog, Handover +from apps.system.models import Dept, User from apps.pm.models import Mtask from apps.wpm.tasks import cal_enstat_when_pcoal_heat_change, cal_enstat_when_team_change -from apps.mtm.serializers import MaterialSerializer +from apps.mtm.serializers import MaterialSimpleSerializer class StLogSerializer(CustomModelSerializer): @@ -68,7 +68,7 @@ class SflogExpSerializer(CustomModelSerializer): class WMaterialSerializer(CustomModelSerializer): - material_ = MaterialSerializer(source='material', read_only=True) + material_ = MaterialSimpleSerializer(source='material', read_only=True) belong_dept_name = serializers.CharField( source='belong_dept.name', read_only=True) @@ -86,6 +86,8 @@ class MlogSerializer(CustomModelSerializer): source='create_by.name', read_only=True) update_by_name = serializers.CharField( source='update_by.name', read_only=True) + handovers = serializers.PrimaryKeyRelatedField( + source='handover_mlog', read_only=True, many=True) class Meta: model = Mlog @@ -138,3 +140,28 @@ class MlogRelatedSerializer(serializers.Serializer): class DeptBatchSerializer(serializers.Serializer): belong_dept_name = serializers.CharField(label='车间名称') + + +class HandoverSerializer(CustomModelSerializer): + send_user_name = serializers.CharField( + source='send_user.name', read_only=True) + recive_user_name = serializers.CharField( + source='send_user.name', read_only=True) + material_ = MaterialSimpleSerializer(source='material', read_only=True) + + class Meta: + model = Handover + fields = '__all__' + read_only_fields = EXCLUDE_FIELDS + + +class GenHandoverSerializer(serializers.Serializer): + mlogs = serializers.PrimaryKeyRelatedField( + label='mlog的ID列表', queryset=Mlog.objects.all(), many=True) + recive_dept = serializers.PrimaryKeyRelatedField( + label='交送车间', queryset=Dept.objects.all()) + recive_user = serializers.PrimaryKeyRelatedField( + label='交送人', queryset=User.objects.all()) + send_user = serializers.PrimaryKeyRelatedField( + label='交送人', queryset=User.objects.all()) + send_date = serializers.DateField(label='交送日期') diff --git a/apps/wpm/views.py b/apps/wpm/views.py index a17a7b5c..de98dcc9 100644 --- a/apps/wpm/views.py +++ b/apps/wpm/views.py @@ -11,8 +11,8 @@ from apps.utils.viewsets import CustomGenericViewSet, CustomModelViewSet from apps.utils.mixins import BulkCreateModelMixin from .filters import SfLogExpFilter, SfLogFilter, WMaterialFilter, MlogFilter -from .models import SfLog, SfLogExp, StLog, WMaterial, Mlog -from .serializers import SflogExpSerializer, SfLogSerializer, StLogSerializer, WMaterialSerializer, MlogSerializer, MlogRelatedSerializer, DeptBatchSerializer +from .models import SfLog, SfLogExp, StLog, WMaterial, Mlog, Handover +from .serializers import SflogExpSerializer, SfLogSerializer, StLogSerializer, WMaterialSerializer, MlogSerializer, MlogRelatedSerializer, DeptBatchSerializer, HandoverSerializer, GenHandoverSerializer # Create your views here. @@ -153,3 +153,52 @@ class MlogViewSet(CustomModelViewSet): if val['batch'] != before['batch']: res_data.append(val) return Response(res_data) + + +class HandoverViewSet(CustomModelViewSet): + """ + list: 交接记录 + + 交接记录 + """ + queryset = Handover.objects.all() + serializer_class = HandoverSerializer + select_related_fields = ['send_user', + 'send_dept', 'recive_user', 'recive_dept'] + filterset_fields = ['send_user', + 'send_dept', 'recive_user', 'recive_dept', 'recive_dept__name', 'send_date'] + + def perform_destroy(self, instance): + user = self.request.user + if instance.send_user != user and instance.recive_user != user and instance.create_by != user: + raise ParseError('非交送人和接收人不可删除该记录') + return super().perform_destroy(instance) + + @action(methods=['post'], detail=False, perms_map={'post': 'handover.create'}, serializer_class=GenHandoverSerializer) + @transaction.atomic + def gen_by_mlogs(self, request): + """从生产日志生成交接记录 + + 从生产日志生成交接记录 + """ + sr = GenHandoverSerializer(data=request.data) + sr.is_valid(raise_exception=True) + vdata = sr.validated_data + user = request.user + send_date, send_user, recive_dept, recive_user = vdata['send_date'], vdata[ + 'send_user'], vdata['recive_dept'], vdata['recive_user'] + for mlog in vdata['mlogs']: + Handover.objects.create( + send_date=send_date, + send_user=send_user, + recive_dept=recive_dept, + recive_user=recive_user, + send_dept=mlog.mgroup.belong_dept, + batch=mlog.batch, + material=mlog.material_out, + count=mlog.count_real, + count_eweight=mlog.count_real_eweight, + mlog=mlog, + create_by=user + ) + return Response()