feat: 增加产品检验

This commit is contained in:
caoqianming 2024-01-17 15:55:42 +08:00
parent c11132e38f
commit e5ba779b00
6 changed files with 134 additions and 15 deletions

View File

@ -1,7 +1,9 @@
from django.contrib import admin from django.contrib import admin
from apps.qm.models import TestItem from apps.qm.models import TestItem
# Register your models here. # Register your models here.
@admin.register(TestItem) @admin.register(TestItem)
class TestItemAdmin(admin.ModelAdmin): class TestItemAdmin(admin.ModelAdmin):
date_hierarchy = 'create_time' date_hierarchy = 'create_time'
list_display = ('id', 'name') list_display = ('id', 'name', 'tags')

View File

@ -0,0 +1,60 @@
# Generated by Django 3.2.12 on 2024-01-17 07:54
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', '0025_auto_20231120_1139'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('system', '0003_alter_permission_parent'),
('qm', '0011_testitem_tags'),
]
operations = [
migrations.AddField(
model_name='ftest',
name='test_numer',
field=models.CharField(default='', max_length=20, verbose_name='检测编号'),
),
migrations.AddField(
model_name='ftest',
name='type',
field=models.CharField(choices=[('first', '首件检验'), ('prod', '成品检验')], default='first', max_length=20, verbose_name='检验类型'),
preserve_default=False,
),
migrations.AlterField(
model_name='ftest',
name='check_user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='ftest_check_user', to=settings.AUTH_USER_MODEL, verbose_name='专检人'),
),
migrations.CreateModel(
name='FtestWork',
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='删除标记')),
('test_date', models.DateField(verbose_name='检验日期')),
('batch', models.CharField(max_length=20, verbose_name='生产批次')),
('count', models.IntegerField(verbose_name='总数量')),
('count_sampling', models.IntegerField(verbose_name='抽检数量')),
('belong_dept', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='ftestwork_belong_dept', to='system.dept', verbose_name='所属部门')),
('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='ftestwork_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')),
('material', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='mtm.material', verbose_name='产品')),
('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='ftestwork_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')),
],
options={
'abstract': False,
},
),
migrations.AddField(
model_name='ftest',
name='ftest_work',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='qm.ftestwork', verbose_name='关联检验工作'),
),
]

View File

@ -1,5 +1,5 @@
from django.db import models from django.db import models
from apps.system.models import CommonAModel, User from apps.system.models import CommonAModel, CommonADModel, User
from apps.utils.models import CommonBDModel, BaseModel from apps.utils.models import CommonBDModel, BaseModel
from apps.mtm.models import Material, Mgroup, Team from apps.mtm.models import Material, Mgroup, Team
from apps.wpm.models import SfLog from apps.wpm.models import SfLog
@ -37,18 +37,38 @@ class QuaStat(CommonBDModel):
rate_pass = models.FloatField('合格率', null=True, blank=True) rate_pass = models.FloatField('合格率', null=True, blank=True)
class Ftest(CommonBDModel): class FtestWork(CommonBDModel):
""" """
首件检验 检验工作
""" """
test_date = models.DateField('检验日期') test_date = models.DateField('检验日期')
material = models.ForeignKey(
Material, verbose_name='产品', on_delete=models.CASCADE)
batch = models.CharField('生产批次', max_length=20)
count = models.IntegerField('总数量')
count_sampling = models.IntegerField('抽检数量')
class Ftest(CommonBDModel):
"""
检验记录
"""
FTEST_TYPE_CHOICES = (
('first', '首件检验'),
('prod', '成品检验')
)
type = models.CharField('检验类型', max_length=20, choices=FTEST_TYPE_CHOICES)
test_date = models.DateField('检验日期')
test_numer = models.CharField('检测编号', max_length=20, default='')
test_group = models.CharField('检验工序集', max_length=20, default='') test_group = models.CharField('检验工序集', max_length=20, default='')
test_user = models.ForeignKey( test_user = models.ForeignKey(
User, verbose_name='操作人', on_delete=models.CASCADE, related_name='ftest_test_user') User, verbose_name='操作人', on_delete=models.CASCADE, related_name='ftest_test_user')
check_user = models.ForeignKey( check_user = models.ForeignKey(
User, verbose_name='专检人', on_delete=models.CASCADE, related_name='ftest_check_user') User, verbose_name='专检人', on_delete=models.CASCADE, related_name='ftest_check_user', null=True, blank=True)
is_ok = models.BooleanField('是否合格', default=False) is_ok = models.BooleanField('是否合格', default=False)
note = models.TextField('备注', default='', blank=True) note = models.TextField('备注', default='', blank=True)
ftest_work = models.ForeignKey(
FtestWork, verbose_name='关联检验工作', on_delete=models.CASCADE, null=True, blank=True)
@property @property
def ftestitems(self): def ftestitems(self):

View File

@ -1,4 +1,4 @@
from apps.qm.models import QuaStat, TestItem, Ftest, FtestItem, Ptest from apps.qm.models import QuaStat, TestItem, Ftest, FtestItem, FtestWork, Ptest
from apps.utils.constants import EXCLUDE_FIELDS, EXCLUDE_FIELDS_BASE from apps.utils.constants import EXCLUDE_FIELDS, EXCLUDE_FIELDS_BASE
from apps.utils.serializers import CustomModelSerializer from apps.utils.serializers import CustomModelSerializer
from rest_framework import serializers from rest_framework import serializers
@ -58,6 +58,21 @@ class QuaStatUpdateSerializer(CustomModelSerializer):
return super().validate(attrs) return super().validate(attrs)
class FtestWorkCreateUpdateSerializer(CustomModelSerializer):
class Meta:
model = FtestWork
fields = ['id', 'test_date', 'material', 'batch', 'count']
class FtestWorkSerializer(CustomModelSerializer):
material_name = serializers.StringRelatedField(
source='material', read_only=True)
class Meta:
model = FtestWork
fields = "__all__"
class FtestItemSerializer(CustomModelSerializer): class FtestItemSerializer(CustomModelSerializer):
testitem_name = serializers.CharField( testitem_name = serializers.CharField(
source='testitem.name', read_only=True) source='testitem.name', read_only=True)
@ -71,8 +86,6 @@ class FtestItemSerializer(CustomModelSerializer):
class FtestSerializer(CustomModelSerializer): class FtestSerializer(CustomModelSerializer):
belong_dept = serializers.PrimaryKeyRelatedField(
required=True, queryset=Dept.objects.all())
test_user_name = serializers.CharField( test_user_name = serializers.CharField(
source='test_user.name', read_only=True) source='test_user.name', read_only=True)
check_user_name = serializers.CharField( check_user_name = serializers.CharField(
@ -82,7 +95,13 @@ class FtestSerializer(CustomModelSerializer):
class Meta: class Meta:
model = Ftest model = Ftest
fields = '__all__' fields = '__all__'
read_only_fields = EXCLUDE_FIELDS read_only_fields = EXCLUDE_FIELDS + ['type']
def validate(self, attrs):
ftest_work = attrs.get('ftest_work', None)
if ftest_work:
attrs['type'] = 'prod' # 带检验工作的标记为成品检验
return attrs
def create(self, validated_data): def create(self, validated_data):
ftestitems = validated_data.pop('ftestitems', []) ftestitems = validated_data.pop('ftestitems', [])
@ -93,6 +112,7 @@ class FtestSerializer(CustomModelSerializer):
return instance return instance
def update(self, instance, validated_data): def update(self, instance, validated_data):
validated_data.pop('ftest_work', None)
ftestitems = validated_data.pop('ftestitems', []) ftestitems = validated_data.pop('ftestitems', [])
with transaction.atomic(): with transaction.atomic():
instance = super().update(instance, validated_data) instance = super().update(instance, validated_data)

View File

@ -1,7 +1,7 @@
from django.urls import path, include from django.urls import path, include
from rest_framework.routers import DefaultRouter from rest_framework.routers import DefaultRouter
from apps.qm.views import QuaStatViewSet, TestItemViewSet, FtestViewSet, PtestViewSet from apps.qm.views import QuaStatViewSet, TestItemViewSet, FtestWorkViewSet, FtestViewSet, PtestViewSet
API_BASE_URL = 'api/qm/' API_BASE_URL = 'api/qm/'
HTML_BASE_URL = 'qm/' HTML_BASE_URL = 'qm/'
@ -10,6 +10,7 @@ router = DefaultRouter()
router.register('quastat', QuaStatViewSet, basename='quastat') router.register('quastat', QuaStatViewSet, basename='quastat')
router.register('testitem', TestItemViewSet, basename='testitem') router.register('testitem', TestItemViewSet, basename='testitem')
router.register('ftest', FtestViewSet, basename='ftest') router.register('ftest', FtestViewSet, basename='ftest')
router.register('ftestwork', FtestWorkViewSet, basename='ftestwork')
router.register('ptest', PtestViewSet, basename='ptest') router.register('ptest', PtestViewSet, basename='ptest')
urlpatterns = [ urlpatterns = [
path(API_BASE_URL, include(router.urls)), path(API_BASE_URL, include(router.urls)),

View File

@ -1,8 +1,9 @@
from django.shortcuts import render from django.shortcuts import render
from rest_framework.mixins import ListModelMixin, CreateModelMixin, UpdateModelMixin from rest_framework.mixins import ListModelMixin, CreateModelMixin, UpdateModelMixin
from rest_framework.decorators import action from rest_framework.decorators import action
from apps.qm.models import QuaStat, TestItem, Ftest, Ptest from apps.qm.models import QuaStat, TestItem, Ftest, Ptest, FtestWork
from apps.qm.serializers import QuaStatSerializer, TestItemSerializer, QuaStatUpdateSerializer, FtestSerializer, PtestSerializer from apps.qm.serializers import QuaStatSerializer, TestItemSerializer, QuaStatUpdateSerializer, FtestSerializer, PtestSerializer, \
FtestWorkCreateUpdateSerializer, FtestWorkSerializer
from apps.qm.tasks import cal_quastat_sflog from apps.qm.tasks import cal_quastat_sflog
from rest_framework.response import Response from rest_framework.response import Response
from apps.utils.mixins import BulkCreateModelMixin, BulkUpdateModelMixin from apps.utils.mixins import BulkCreateModelMixin, BulkUpdateModelMixin
@ -55,13 +56,14 @@ class QuaStatViewSet(ListModelMixin, BulkUpdateModelMixin, CustomGenericViewSet)
class FtestViewSet(CustomModelViewSet): class FtestViewSet(CustomModelViewSet):
""" """
list:首件检验 list:首件/成品检验
首件检验 首件/成品检验
""" """
queryset = Ftest.objects.all() queryset = Ftest.objects.all()
serializer_class = FtestSerializer serializer_class = FtestSerializer
select_related_fields = ['test_user', 'check_user'] select_related_fields = ['test_user', 'check_user', 'ftest_work']
filterset_fields = ['type', 'ftest_work']
class PtestViewSet(CustomModelViewSet): class PtestViewSet(CustomModelViewSet):
@ -74,3 +76,17 @@ class PtestViewSet(CustomModelViewSet):
serializer_class = PtestSerializer serializer_class = PtestSerializer
select_related_fields = ['testitem'] select_related_fields = ['testitem']
filterset_fields = ['testitem', 'test_date'] filterset_fields = ['testitem', 'test_date']
class FtestWorkViewSet(CustomModelViewSet):
"""
list: 检验工作
检验工作
"""
queryset = FtestWork.objects.all()
serializer_class = FtestWorkSerializer
create_serializer_class = FtestWorkCreateUpdateSerializer
update_serializer_class = FtestWorkCreateUpdateSerializer
select_related_fields = ['material']
filterset_fields = ['material', 'batch']