Merge branch 'develop' of https://e.coding.net/ctcdevteam/hberp/hberp into develop

This commit is contained in:
shilixia 2022-01-13 16:11:25 +08:00
commit e7cb82e562
26 changed files with 184 additions and 49 deletions

View File

@ -2,10 +2,11 @@ from django.db.models import base
from rest_framework import urlpatterns
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from apps.develop.views import CleanDataView, UpdateCuttingView
from apps.develop.views import CleanDataView, UpdateCuttingView, UpdateLastTestResult
urlpatterns = [
path('cleandata/', CleanDataView.as_view()),
path('update_cutting/', UpdateCuttingView.as_view())
path('update_cutting/', UpdateCuttingView.as_view()),
path('update_last_result/', UpdateLastTestResult.as_view())
]

View File

@ -47,3 +47,18 @@ class UpdateCuttingView(APIView):
WproductFlow.objects.filter(wproduct=i).update(coperation=op)
WpmServies.update_cutting_list_with_operation(op)
return Response()
from apps.qm.models import TestRecord
class UpdateLastTestResult(APIView):
permission_classes = [IsAdminUser]
@transaction.atomic
def post(self, request, format=None):
"""
更新最后一次检验结果
"""
for i in WProduct.objects.all():
tr = TestRecord.objects.filter(wproduct=i, is_submited=True).order_by('-id').first()
if tr:
i.last_test_result = tr.is_testok
i.save()
return Response()

View File

@ -36,4 +36,3 @@ class Employee(CommonAModel):
def __str__(self):
return self.name

View File

@ -2,12 +2,19 @@ from django_filters import rest_framework as filters
from apps.mtm.models import Material
from .models import IProduct, MaterialBatch
from django.utils import timezone
class MbFilterSet(filters.FilterSet):
material = filters.ModelMultipleChoiceFilter(field_name="material", queryset=Material.objects.all())
tag = filters.CharFilter(method="filter_tag")
class Meta:
model = MaterialBatch
fields = ['material', 'warehouse']
def filter_tag(self, queryset, name, value):
if value == 'expired':
queryset = queryset.exclude(expiration_date=None).filter(expiration_date__lte = timezone.now())
return queryset
class IProductFilterSet(filters.FilterSet):

View File

@ -0,0 +1,25 @@
# Generated by Django 3.2.9 on 2022-01-13 01:32
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('inm', '0024_auto_20211227_0948'),
]
operations = [
migrations.RemoveField(
model_name='iproduct',
name='is_mtested',
),
migrations.RemoveField(
model_name='iproduct',
name='is_mtestok',
),
migrations.RemoveField(
model_name='iproduct',
name='remark_mtest',
),
]

View File

@ -2,7 +2,7 @@ from django.db import models
from django.db.models.base import Model
import django.utils.timezone as timezone
from django.db.models.query import QuerySet
from apps.system.models import CommonAModel, CommonBModel, Organization, User, Dict, File
from apps.system.models import CommonADModel, CommonAModel, CommonBModel, Organization, User, Dict, File
from utils.model import SoftModel, BaseModel
from simple_history.models import HistoricalRecords
from apps.mtm.models import Material
@ -50,7 +50,7 @@ class MaterialBatch(BaseModel):
class FIFO(CommonAModel):
class FIFO(CommonADModel):
"""
出入库记录
"""

View File

@ -115,7 +115,7 @@ class FIFOItemViewSet(ListModelMixin, DestroyModelMixin, GenericViewSet):
obj.fifo_item.save()
return Response()
class FIFOViewSet(ListModelMixin, GenericViewSet):
class FIFOViewSet(ListModelMixin, DestroyModelMixin, GenericViewSet):
"""
出入库记录
"""
@ -132,6 +132,12 @@ class FIFOViewSet(ListModelMixin, GenericViewSet):
return FIFOListSerializer
return super().get_serializer_class()
def destroy(self, request, *args, **kwargs):
obj = self.get_object()
if obj.is_submited:
raise exceptions.APIException('该记录已审核,不可删除')
return super().destroy(request, *args, **kwargs)
@action(methods=['post'], detail=False, perms_map={'post':'*'}, serializer_class=FIFOInPurSerializer)
def in_pur(self, request, pk=None):
"""
@ -148,9 +154,9 @@ class FIFOViewSet(ListModelMixin, GenericViewSet):
审核通过
"""
obj = self.get_object()
# for i in FIFOItem.objects.filter(fifo=obj):
# if not i.is_testok:
# raise APIException('未检验通过, 不可审核')
for i in FIFOItem.objects.filter(fifo=obj):
if not i.is_testok:
raise APIException('未检验通过, 不可审核')
if obj.is_audited:
raise APIException('该入库记录已审核通过')
with transaction.atomic():
@ -166,7 +172,7 @@ class IProductViewSet(ListModelMixin, GenericViewSet):
半成品库存表
"""
perms_map = {'*': '*'}
queryset = IProduct.objects.select_related('material', 'warehouse', 'wproduct__subproduction_plan__production_plan__order').filter(is_saled=False)
queryset = IProduct.objects.select_related('material', 'warehouse', 'wproduct__subproduction_plan__production_plan__order')
serializer_class = IProductListSerializer
filterset_class = IProductFilterSet
search_fields = []

View File

@ -1,3 +0,0 @@
from django.contrib import admin
# Register your models here.

View File

@ -1,7 +0,0 @@
from django.apps import AppConfig
class MnsConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'apps.mns'
verbose_name = '消息通知系统'

View File

@ -1,6 +0,0 @@
from django.db import models
from utils.model import BaseModel
# Create your models here.
class Notify(BaseModel)
pass

View File

@ -1,3 +0,0 @@
from django.test import TestCase
# Create your tests here.

View File

@ -1,3 +0,0 @@
from django.shortcuts import render
# Create your views here.

View File

@ -186,7 +186,7 @@ class RecordFormFieldViewSet(OptimizationMixin, CreateUpdateModelAMixin, ModelVi
queryset = RecordFormField.objects.all()
filterset_fields = ['field_type', 'form']
search_fields = ['field_name', 'field_key']
ordering = 'id'
ordering = 'sort'
ordering_fields = ['sort', 'id']
def get_serializer_class(self):

View File

@ -7,7 +7,7 @@ from apps.wpm.services import WpmServies
class PlanFilterSet(filters.FilterSet):
create_time_start = filters.DateFilter(field_name="create_time", lookup_expr='gte')
create_time_end = filters.NumberFilter(field_name="create_time", lookup_expr='lte')
create_time_end = filters.DateFilter(field_name="create_time", lookup_expr='lte')
tag = filters.CharFilter(method='filter_tag')
class Meta:
model = ProductionPlan

View File

@ -5,7 +5,7 @@ from apps.sam.models import Order
class OrderFilterSet(filters.FilterSet):
create_time_start = filters.DateFilter(field_name="create_time", lookup_expr='gte')
create_time_end = filters.NumberFilter(field_name="create_time", lookup_expr='lte')
create_time_end = filters.DateFilter(field_name="create_time", lookup_expr='lte')
class Meta:
model = Order
fields = ['product', 'contract', 'customer', 'create_time_start', 'create_time_end']
@ -13,6 +13,6 @@ class OrderFilterSet(filters.FilterSet):
class ContractFilterSet(filters.FilterSet):
create_time_start = filters.DateFilter(field_name="create_time", lookup_expr='gte')
create_time_end = filters.NumberFilter(field_name="create_time", lookup_expr='lte')
create_time_end = filters.DateFilter(field_name="create_time", lookup_expr='lte')
class Meta:
fields = ['customer', 'create_time_start', 'create_time_end']

View File

@ -38,7 +38,7 @@ class ContractSimpleSerializer(serializers.ModelSerializer):
class ContractCreateUpdateSerializer(serializers.ModelSerializer):
class Meta:
model = Contract
fields = ['name', 'number', 'amount', 'customer', 'sign_date', 'description']
fields = ['name', 'number', 'amount', 'customer', 'sign_date', 'description', 'invoice']
class OrderCreateUpdateSerializer(serializers.ModelSerializer):

View File

@ -2,7 +2,7 @@ from django_filters import rest_framework as filters
from apps.mtm.models import Material, Step
from apps.wpm.services import WpmServies
from .models import Operation, OperationMaterial, WMaterial, WProduct
from .models import Operation, OperationMaterial, OperationRecord, WMaterial, WProduct
class WMaterialFilterSet(filters.FilterSet):
@ -40,3 +40,14 @@ class CuttingFilterSet(filters.FilterSet):
class Meta:
model = OperationMaterial
fields = ['operation', 'subproduction_plan', 'material']
class OperationRecordFilterSet(filters.FilterSet):
wproduct = filters.NumberFilter(method='filter_wproduct')
class Meta:
model = OperationRecord
fields = ['operation', 'form']
def filter_wproduct(self, queryset, name, value):
queryset = queryset.filter(operation__ow_operation__wproduct__id=value)
return queryset

View File

@ -0,0 +1,34 @@
# Generated by Django 3.2.9 on 2022-01-13 01:32
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('wpm', '0045_auto_20220107_0917'),
]
operations = [
migrations.AddField(
model_name='wproduct',
name='last_test_result',
field=models.BooleanField(blank=True, null=True, verbose_name='最后一次检验结果'),
),
migrations.AlterField(
model_name='operationmaterial',
name='operation',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='om_operation', to='wpm.operation', verbose_name='关联的生产操作'),
),
migrations.AlterField(
model_name='wproduct',
name='child',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='wproduct_child', to='wpm.wproduct'),
),
migrations.AlterField(
model_name='wproductflow',
name='child',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='wproduct_child', to='wpm.wproductflow'),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 3.2.9 on 2022-01-13 01:36
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('wpm', '0046_auto_20220113_0932'),
]
operations = [
migrations.AddField(
model_name='wproductflow',
name='last_test_result',
field=models.BooleanField(blank=True, null=True, verbose_name='最后一次检验结果'),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 3.2.9 on 2022-01-13 07:35
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('wpm', '0047_wproductflow_last_test_result'),
]
operations = [
migrations.AddField(
model_name='operationwproduct',
name='place',
field=models.CharField(blank=True, max_length=200, null=True, verbose_name='摆放位置'),
),
]

View File

@ -107,6 +107,7 @@ class WProduct(CommonAModel):
is_mtested = models.BooleanField('是否军检', default=False)
is_mtestok = models.BooleanField('是否军检合格', null=True, blank=True)
remark_mtest = models.TextField('军检备注', null=True, blank=True)
last_test_result = models.BooleanField('最后一次检验结果', null=True, blank=True)
@property
def last_process_test(self):
@ -162,6 +163,7 @@ class WproductFlow(CommonAModel):
is_mtested = models.BooleanField('是否军检', default=False)
is_mtestok = models.BooleanField('是否军检合格', null=True, blank=True)
remark_mtest = models.TextField('军检备注', null=True, blank=True)
last_test_result = models.BooleanField('最后一次检验结果', null=True, blank=True)
is_lastlog = models.BooleanField('是否该子计划下的最后一条日志', default=True)
change_str = models.CharField('变动描述', default='', max_length=1000)
@ -209,6 +211,7 @@ class OperationWproduct(BaseModel):
material = models.ForeignKey(Material, verbose_name='操作时的物料状态', on_delete=models.CASCADE)
subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='当前子生产计划', on_delete=models.CASCADE, related_name='ow_subplan')
ng_sign = models.PositiveSmallIntegerField('当时的不合格标记', choices= WProduct.ng_choices, null=True, blank=True)
place = models.CharField('摆放位置', null=True, blank=True, max_length=200)
class Meta:
unique_together = (
('operation','wproduct')

View File

@ -244,15 +244,25 @@ class OperationDetailSerializer(serializers.ModelSerializer):
class OperationListSerializer(serializers.ModelSerializer):
create_by_ = UserSimpleSerializer(source='create_by', read_only=True)
step_ = StepSimpleSerializer(source='step', read_only=True)
wproduct_ = serializers.SerializerMethodField()
# wproduct_ = serializers.SerializerMethodField()
count_work = serializers.SerializerMethodField()
equip_ = serializers.SerializerMethodField()
record_ = serializers.SerializerMethodField()
class Meta:
model = Operation
fields = '__all__'
def get_wproduct_(self, obj):
return WProduct.objects.filter(ow_wproduct__operation=obj).values('id', 'number')
# def get_wproduct_(self, obj):
# return WProduct.objects.filter(ow_wproduct__operation=obj).values('id', 'number')
def get_count_work(self, obj):
from django.db.models.aggregates import Sum
count_work = 0
if obj.step.type == Step.STEP_TYPE_NOM:
count_work = OperationWproduct.objects.filter(operation=obj).count()
else:
count_work = OperationMaterial.objects.filter(operation=obj).aggregate(count_work=Sum('count'))['count_work']
return count_work
def get_equip_(self, obj):
return EquipmentSimpleSerializer(instance=Equipment.objects.filter(oe_equip__operation=obj), many=True).data
@ -360,6 +370,10 @@ class OperationWproductListSerializer(serializers.ModelSerializer):
model = OperationWproduct
fields = '__all__'
class OperationWproductUpdateSerializer(serializers.ModelSerializer):
class Meta:
model = OperationWproduct
fields = ['place']
class OperationSubmitSerializer(serializers.Serializer):
step = serializers.PrimaryKeyRelatedField(queryset=Step.objects.all(), label="子工序ID")

View File

@ -94,6 +94,7 @@ class WpmServies(object):
wproduct.update_by = user
wproduct.update_time = timezone.now()
wproduct.test = None
wproduct.last_test_result = is_testok
wproduct.save()
# 添加日志
cls.add_wproduct_flow_log(wproduct, 'test_ok' if is_testok else 'test_notok')

View File

@ -19,10 +19,10 @@ from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin
from rest_framework.decorators import action
from apps.wf.models import Workflow
from apps.wf.serializers import WorkflowSimpleSerializer
from apps.wpm.filters import CuttingFilterSet, WMaterialFilterSet, WProductFilterSet
from apps.wpm.filters import CuttingFilterSet, OperationRecordFilterSet, WMaterialFilterSet, WProductFilterSet
from apps.wpm.models import OperationEquip, OperationWproduct, Pick, PickWproduct, WMaterial, WProduct, Operation, OperationMaterial, OperationRecord, OperationRecordItem, WprouctTicket
from apps.wpm.serializers import CuttingListSerializer, OperationEquipListSerializer, OperationEquipUpdateSerializer, OperationMaterialCreate1ListSerailizer, OperationMaterialCreate1Serailizer, OperationMaterialCreate2ListSerailizer, OperationMaterialCreate2Serailizer, OperationMaterialCreate3Serializer, OperationMaterialListSerializer, OperationRecordDetailSerializer, OperationRecordListSerializer, OperationRecordSubmitSerializer, OperationUpdateSerializer, OperationWproductListSerializer, OperationCreateSerializer, OperationDetailSerializer, OperationListSerializer, PickHalfSerializer, PickHalfsSerializer, PickSerializer, OperationInitSerializer, OperationSubmitSerializer, ScrapSerializer, WMaterialListSerializer, WProductCardSerializer, WProductDetailSerializer, WProductListSerializer, WplanPutInSerializer, WpmTestFormInitSerializer, WpmTestRecordCreateSerializer, WproductMtestSerializer, WproductPutInSerializer, WproductPutInsSerializer, WproductTicketListSerializer
from apps.wpm.serializers import CuttingListSerializer, OperationEquipListSerializer, OperationEquipUpdateSerializer, OperationMaterialCreate1ListSerailizer, OperationMaterialCreate1Serailizer, OperationMaterialCreate2ListSerailizer, OperationMaterialCreate2Serailizer, OperationMaterialCreate3Serializer, OperationMaterialListSerializer, OperationRecordDetailSerializer, OperationRecordListSerializer, OperationRecordSubmitSerializer, OperationUpdateSerializer, OperationWproductListSerializer, OperationCreateSerializer, OperationDetailSerializer, OperationListSerializer, OperationWproductUpdateSerializer, PickHalfSerializer, PickHalfsSerializer, PickSerializer, OperationInitSerializer, OperationSubmitSerializer, ScrapSerializer, WMaterialListSerializer, WProductCardSerializer, WProductDetailSerializer, WProductListSerializer, WplanPutInSerializer, WpmTestFormInitSerializer, WpmTestRecordCreateSerializer, WproductMtestSerializer, WproductPutInSerializer, WproductPutInsSerializer, WproductTicketListSerializer
from rest_framework.response import Response
from django.db import transaction
from rest_framework import exceptions, serializers
@ -616,10 +616,10 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd
omos = OperationMaterial.objects.filter(operation=op,
type=SubprodctionMaterial.SUB_MA_TYPE_OUT)
sps_omo_l = omos.filter(use_scrap=False).values_list('subproduction_plan', flat=True)
if set(list(sps_omi_l)) == set(list(sps_omo_l)) or op.step.type == Step.STEP_TYPE_COMB:
pass
else:
if not (set(list(sps_omi_l)) == set(list(sps_omo_l)) and op.step.type == Step.STEP_TYPE_DIV):
raise exceptions.APIException('消耗与产出不一致')
# 实际消耗物料校验
# 检查自定义表单填写
if OperationRecord.objects.filter(operation=op, is_filled=False).exists():
raise exceptions.APIException('存在自定义表单未填写')
@ -722,7 +722,7 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd
class OperationWproductViewSet(ListModelMixin, DestroyModelMixin, GenericViewSet):
class OperationWproductViewSet(ListModelMixin, DestroyModelMixin, UpdateModelMixin, GenericViewSet):
"""
操作使用的半成品
"""
@ -733,6 +733,11 @@ class OperationWproductViewSet(ListModelMixin, DestroyModelMixin, GenericViewSet
ordering_fields = ['id']
ordering = ['-id']
def get_serializer_class(self):
if self.action == 'update':
return OperationWproductUpdateSerializer
return super().get_serializer_class()
@transaction.atomic()
def destroy(self, request, *args, **kwargs):
instance = self.get_object()
@ -781,7 +786,7 @@ class OperationRecordViewSet(ListModelMixin, DestroyModelMixin, UpdateModelMixin
perms_map={'*':'*'}
queryset = OperationRecord.objects.select_related('operation', 'form').all()
serializer_class = OperationRecordListSerializer
filterset_fields = ['operation', 'form']
filterset_class = OperationRecordFilterSet
ordering_fields = ['id']
ordering = ['-id']