diff --git a/hb_server/apps/develop/urls.py b/hb_server/apps/develop/urls.py index 22621ac..0048316 100644 --- a/hb_server/apps/develop/urls.py +++ b/hb_server/apps/develop/urls.py @@ -2,7 +2,7 @@ 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, UpdateEquipState, UpdateFIFOItem, UpdateLastTestResult, UpdateSpg +from apps.develop.views import CleanDataView, UpdateCuttingView, UpdateEquipState, UpdateFIFOItem, UpdateLastTestResult, UpdateNeedToOrder, UpdateSpg urlpatterns = [ path('cleandata/', CleanDataView.as_view()), @@ -11,6 +11,7 @@ urlpatterns = [ path('update_last_result/', UpdateLastTestResult.as_view()), path('update_fifoitem/', UpdateFIFOItem.as_view()), path('update_spg/', UpdateSpg.as_view()), - path('update_equip_state/', UpdateEquipState.as_view()) + path('update_equip_state/', UpdateEquipState.as_view()), + path('update_need_to_order/', UpdateNeedToOrder.as_view()) ] diff --git a/hb_server/apps/develop/views.py b/hb_server/apps/develop/views.py index c1b5b84..4d6c050 100644 --- a/hb_server/apps/develop/views.py +++ b/hb_server/apps/develop/views.py @@ -99,4 +99,10 @@ class UpdateEquipState(APIView): def post(self, request, format=None): update_equip_state_by_next_check_date() + return Response() + +class UpdateNeedToOrder(APIView): + permission_classes = [IsAdminUser] + def post(self, request): + WProduct.objects.exclude(to_order=None).update(need_to_order=True) return Response() \ No newline at end of file diff --git a/hb_server/apps/em/filters.py b/hb_server/apps/em/filters.py new file mode 100644 index 0000000..39fd93c --- /dev/null +++ b/hb_server/apps/em/filters.py @@ -0,0 +1,24 @@ +from django_filters import rest_framework as filters + +from apps.em.models import Equipment +from datetime import * + +from utils.mixins import DynamicFieldsFilterMixin + + +class EquipFilterSet(DynamicFieldsFilterMixin, filters.FilterSet): + tag = filters.CharFilter(method='filter_tag') + class Meta: + model = Equipment + fields = ['keeper', 'type', 'tag'] + + def filter_tag(self, queryset, name, value): + now = datetime.now() + day7_after = now + timedelta(days=7) + if value == 'near_check': + queryset = queryset.filter( + next_check_date__lte = datetime.date(day7_after)) + elif value == 'out_check': + queryset = queryset.filter( + next_check_date__gt = datetime.date(now)) + return queryset \ No newline at end of file diff --git a/hb_server/apps/em/serializers.py b/hb_server/apps/em/serializers.py index c22238d..614528f 100644 --- a/hb_server/apps/em/serializers.py +++ b/hb_server/apps/em/serializers.py @@ -2,11 +2,13 @@ from apps.mtm.models import Step from rest_framework import serializers from rest_framework.serializers import ModelSerializer from rest_framework import exceptions + +from utils.mixins import DynamicFieldsSerializerMixin from .models import Equipment, ECheckRecord from apps.system.serializers import OrganizationSimpleSerializer, UserSimpleSerializer -class EquipmentListSerializer(ModelSerializer): +class EquipmentListSerializer(DynamicFieldsSerializerMixin, ModelSerializer): keeper_ = UserSimpleSerializer(source='keeper', read_only=True) step_ = serializers.SerializerMethodField() class Meta: @@ -37,7 +39,7 @@ class EquipmentCreateUpdateSerializer(ModelSerializer): class EquipmentSimpleSerializer(ModelSerializer): class Meta: model = Equipment - fields = ['id', 'number', 'name', 'state', 'model'] + fields = ['id', 'number', 'name', 'state', 'model', 'type'] diff --git a/hb_server/apps/em/views.py b/hb_server/apps/em/views.py index aec05f7..4357479 100644 --- a/hb_server/apps/em/views.py +++ b/hb_server/apps/em/views.py @@ -7,6 +7,7 @@ from rest_framework.viewsets import ModelViewSet, GenericViewSet from rest_framework.mixins import CreateModelMixin, RetrieveModelMixin, ListModelMixin, DestroyModelMixin from rest_framework import serializers, status from rest_framework.response import Response +from apps.em.filters import EquipFilterSet from apps.em.models import Equipment, ECheckRecord from apps.em.serializers import DaqCreateSerializer, EChcekRecordCreateSerializer, ECheckRecordListSerializer, \ EquipmentCreateUpdateSerializer, EquipmentListSerializer @@ -26,7 +27,7 @@ class EquipmentViewSet(CreateUpdateModelAMixin, OptimizationMixin, ModelViewSet) queryset = Equipment.objects.all() serializer_class = EquipmentListSerializer search_fields = ['number', 'name','description'] - filterset_fields = ['keeper', 'type'] + filterset_class = EquipFilterSet ordering_fields = ['create_time'] ordering = ['-create_time'] diff --git a/hb_server/apps/hrm/filters.py b/hb_server/apps/hrm/filters.py index 40c9b45..8ec72fe 100644 --- a/hb_server/apps/hrm/filters.py +++ b/hb_server/apps/hrm/filters.py @@ -1,9 +1,16 @@ from django_filters import rest_framework as filters -from apps.hrm.models import ClockRecord +from apps.hrm.models import ClockRecord, Employee +from utils.mixins import DynamicFieldsFilterMixin class ClockRecordFilterSet(filters.FilterSet): create_time_start = filters.DateFilter(field_name="create_time", lookup_expr='gte') create_time_end = filters.DateFilter(field_name="create_time", lookup_expr='lte') class Meta: model = ClockRecord - fields = ['create_by', 'create_time_start', 'create_time_end'] \ No newline at end of file + fields = ['create_by', 'create_time_start', 'create_time_end'] + +class EmployeeFilterSet(DynamicFieldsFilterMixin, filters.FilterSet): + + class Meta: + model = Employee + fields = ['job_state'] \ No newline at end of file diff --git a/hb_server/apps/hrm/migrations/0005_auto_20220126_1351.py b/hb_server/apps/hrm/migrations/0005_auto_20220126_1351.py new file mode 100644 index 0000000..d6bd2c3 --- /dev/null +++ b/hb_server/apps/hrm/migrations/0005_auto_20220126_1351.py @@ -0,0 +1,37 @@ +# Generated by Django 3.2.9 on 2022-01-26 05:51 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('hrm', '0004_clockrecord'), + ] + + operations = [ + migrations.RenameField( + model_name='employee', + old_name='birthdate', + new_name='birthday', + ), + migrations.RenameField( + model_name='employee', + old_name='ID_number', + new_name='id_number', + ), + migrations.RenameField( + model_name='employee', + old_name='jobstate', + new_name='job_state', + ), + migrations.RenameField( + model_name='employee', + old_name='academic', + new_name='qualification', + ), + migrations.RemoveField( + model_name='employee', + name='job', + ), + ] diff --git a/hb_server/apps/hrm/models.py b/hb_server/apps/hrm/models.py index 490237e..219caea 100644 --- a/hb_server/apps/hrm/models.py +++ b/hb_server/apps/hrm/models.py @@ -14,20 +14,21 @@ class Employee(CommonAModel): """ 员工信息 """ + JOB_ON = 1 + JOB_OFF = 2 jobstate_choices = ( - (1, '在职'), - (2, '离职'), + (JOB_ON, '在职'), + (JOB_OFF, '离职'), ) user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='employee_user') number = models.CharField('人员编号', max_length=50,null=True, blank=True, unique=True) photo = models.CharField('证件照', max_length=1000, null=True, blank=True) - ID_number = models.CharField('身份证号', max_length=100, null=True, blank=True) + id_number = models.CharField('身份证号', max_length=100, null=True, blank=True) gender = models.CharField('性别', max_length=10, default='男') signature = models.CharField('签名图片', max_length=200, null=True, blank=True) - birthdate = models.DateField('出生年月', null=True, blank=True) - academic = models.CharField('学历', max_length=50, null=True, blank=True) - jobstate = models.IntegerField('在职状态', choices=jobstate_choices, default=1) - job = models.ForeignKey(Position, null=True, blank=True, on_delete=models.SET_NULL, verbose_name='岗位') + birthday = models.DateField('出生年月', null=True, blank=True) + qualification = models.CharField('学历', max_length=50, null=True, blank=True) + job_state = models.IntegerField('在职状态', choices=jobstate_choices, default=1) face_data = models.JSONField('人脸识别数据', null=True, blank=True) class Meta: verbose_name = '员工补充信息' diff --git a/hb_server/apps/hrm/serializers.py b/hb_server/apps/hrm/serializers.py index 31eb30d..4f70427 100644 --- a/hb_server/apps/hrm/serializers.py +++ b/hb_server/apps/hrm/serializers.py @@ -1,11 +1,15 @@ from apps.system.models import User from rest_framework.serializers import ModelSerializer from rest_framework import serializers + +from utils.mixins import DynamicFieldsSerializerMixin from .models import ClockRecord, Employee -from apps.system.serializers import UserListSerializer, UserSimpleSerializer +from apps.system.serializers import OrganizationSimpleSerializer, UserListSerializer, UserSimpleSerializer from django.db.models.query import Prefetch -class EmployeeSerializer(ModelSerializer): +class EmployeeSerializer(DynamicFieldsSerializerMixin, ModelSerializer): + name = serializers.CharField(source='user.name', read_only=True) + dept_ = OrganizationSimpleSerializer(source='user.dept_', read_only=True) class Meta: model = Employee exclude = ['face_data'] diff --git a/hb_server/apps/hrm/services.py b/hb_server/apps/hrm/services.py index 8cfb277..7f7334b 100644 --- a/hb_server/apps/hrm/services.py +++ b/hb_server/apps/hrm/services.py @@ -28,8 +28,11 @@ class HRMService: face_users = cache.get('face_users') if face_datas is None: update_all_user_facedata_cache() - - results = face_recognition.compare_faces(face_datas, unknown_face_encoding, tolerance=0.5) + try: + results = face_recognition.compare_faces(face_datas, + unknown_face_encoding, tolerance=0.5) + except: + return None, '识别失败' for index, value in enumerate(results): if value: # 识别成功 diff --git a/hb_server/apps/hrm/tasks.py b/hb_server/apps/hrm/tasks.py index d5d5a9f..65ffe92 100644 --- a/hb_server/apps/hrm/tasks.py +++ b/hb_server/apps/hrm/tasks.py @@ -11,7 +11,7 @@ def update_all_user_not_atwork(): """ 将所有员工设为非在岗状态 """ - User.objects.all().update(is_atwork=False) + User.objects.all().update(is_atwork=False, last_check_time = None) @shared_task def update_all_user_facedata_cache(): diff --git a/hb_server/apps/hrm/views.py b/hb_server/apps/hrm/views.py index dafe59c..61fb2f4 100644 --- a/hb_server/apps/hrm/views.py +++ b/hb_server/apps/hrm/views.py @@ -4,7 +4,7 @@ from django.utils import timezone from rest_framework.response import Response from rest_framework.viewsets import ModelViewSet, GenericViewSet from rest_framework.mixins import UpdateModelMixin, RetrieveModelMixin, CreateModelMixin, ListModelMixin -from apps.hrm.filters import ClockRecordFilterSet +from apps.hrm.filters import ClockRecordFilterSet, EmployeeFilterSet from apps.hrm.services import HRMService from apps.hrm.tasks import update_all_user_facedata_cache from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin @@ -30,6 +30,7 @@ class EmployeeViewSet(CreateUpdateModelAMixin, OptimizationMixin, UpdateModelMix """ perms_map = {'get': '*', 'put': 'employee_update'} queryset = Employee.objects.all() + filterset_class = EmployeeFilterSet serializer_class = EmployeeSerializer ordering = ['-pk'] @@ -91,6 +92,7 @@ class ClockRecordViewSet(CreateModelMixin, ListModelMixin, GenericViewSet): ins.save() # 设为在岗 user.is_atwork = True + user.last_check_time = now user.save() return Response(UserSimpleSerializer(instance=user).data) return Response(msg, status=status.HTTP_400_BAD_REQUEST) diff --git a/hb_server/apps/inm/filters.py b/hb_server/apps/inm/filters.py index 41dcf61..7f16ac4 100644 --- a/hb_server/apps/inm/filters.py +++ b/hb_server/apps/inm/filters.py @@ -3,9 +3,9 @@ from django_filters import rest_framework as filters from apps.mtm.models import Material from .models import IProduct, MaterialBatch from django.utils import timezone +from utils.mixins import DynamicFieldsFilterMixin - -class MbFilterSet(filters.FilterSet): +class MbFilterSet(DynamicFieldsFilterMixin, filters.FilterSet): material = filters.ModelMultipleChoiceFilter(field_name="material", queryset=Material.objects.all()) tag = filters.CharFilter(method="filter_tag") @@ -20,12 +20,14 @@ class MbFilterSet(filters.FilterSet): return queryset -class IProductFilterSet(filters.FilterSet): +class IProductFilterSet(DynamicFieldsFilterMixin, filters.FilterSet): order = filters.NumberFilter(field_name="wproduct__subproduction_plan__production_plan__order") to_order = filters.NumberFilter(field_name="wproduct__to_order") + need_to_order = filters.BooleanFilter(field_name="wproduct__need_to_order") update_time_start = filters.DateFilter(field_name="update_time", lookup_expr='gte') update_time_end = filters.DateFilter(field_name="update_time", lookup_expr='lte') class Meta: model = IProduct fields = ['material', 'warehouse', 'batch', 'order', 'material__type', - 'is_saled', 'update_time_start', 'update_time_end', 'to_order'] + 'is_saled', 'update_time_start', 'update_time_end', + 'to_order', 'need_to_order'] diff --git a/hb_server/apps/inm/serializers.py b/hb_server/apps/inm/serializers.py index 3569848..858c06d 100644 --- a/hb_server/apps/inm/serializers.py +++ b/hb_server/apps/inm/serializers.py @@ -3,10 +3,13 @@ from rest_framework import serializers from apps.inm.models import FIFO, FIFOItem, FIFOItemProduct, IProduct, MaterialBatch, WareHouse, Inventory from apps.qm.models import TestRecord, TestRecordItem +from apps.sam.serializers import OrderSimpleSerializer + from apps.system.serializers import FileSimpleSerializer, UserSimpleSerializer from apps.mtm.serializers import MaterialSimpleSerializer from django.db import transaction +from utils.mixins import DynamicFieldsSerializerMixin @@ -39,7 +42,7 @@ class InventorySerializer(serializers.ModelSerializer): fields = '__all__' -class MaterialBatchSerializer(serializers.ModelSerializer): +class MaterialBatchSerializer(DynamicFieldsSerializerMixin, serializers.ModelSerializer): material_ = MaterialSimpleSerializer(source='material', read_only=True) warehouse_ = WareHouseSimpleSerializer(source='warehouse', read_only=True) @@ -48,12 +51,15 @@ class MaterialBatchSerializer(serializers.ModelSerializer): fields = '__all__' -class IProductListSerializer(serializers.ModelSerializer): +class IProductListSerializer(DynamicFieldsSerializerMixin, serializers.ModelSerializer): material_ = MaterialSimpleSerializer(source='material', read_only=True) warehouse_ = WareHouseSimpleSerializer(source='warehouse', read_only=True) + need_to_order = serializers.BooleanField(source='wproduct.need_to_order', read_only=True) is_mtestok = serializers.BooleanField(source='wproduct.is_mtestok', read_only=True) remark_mtest = serializers.CharField(source='wproduct.remark_mtest', read_only=True) - + to_order_ = OrderSimpleSerializer(source='wproduct.to_order', read_only=True) + order_ = OrderSimpleSerializer( + source='wproduct.subproduction_plan.production_plan.order', read_only=True) class Meta: model = IProduct fields = '__all__' diff --git a/hb_server/apps/inm/views.py b/hb_server/apps/inm/views.py index 8f20cf7..26823cb 100644 --- a/hb_server/apps/inm/views.py +++ b/hb_server/apps/inm/views.py @@ -187,7 +187,9 @@ class IProductViewSet(ListModelMixin, GenericViewSet): """ perms_map = {'*': '*'} queryset = IProduct.objects.select_related( - 'material', 'warehouse', 'wproduct__subproduction_plan__production_plan__order') + 'material', 'warehouse', + 'wproduct__subproduction_plan__production_plan__order', + 'wproduct__to_order') serializer_class = IProductListSerializer filterset_class = IProductFilterSet search_fields = [] diff --git a/hb_server/apps/mtm/filters.py b/hb_server/apps/mtm/filters.py index 8eb6b52..723345a 100644 --- a/hb_server/apps/mtm/filters.py +++ b/hb_server/apps/mtm/filters.py @@ -1,6 +1,7 @@ from django.db.models.expressions import F from django_filters import rest_framework as filters from apps.mtm.models import Material, TechDoc +from utils.mixins import DynamicFieldsFilterMixin @@ -15,7 +16,7 @@ class TechDocFilterset(filters.FilterSet): def filter_operation(self, queryset, name, value): return queryset.filter(subproduction__subplan_subprod__ow_subplan__operation=value).distinct() -class MaterialFilterSet(filters.FilterSet): +class MaterialFilterSet(DynamicFieldsFilterMixin, filters.FilterSet): tag = filters.CharFilter(method='filter_tag') class Meta: model = Material diff --git a/hb_server/apps/mtm/serializers.py b/hb_server/apps/mtm/serializers.py index 99cdfb6..538e70f 100644 --- a/hb_server/apps/mtm/serializers.py +++ b/hb_server/apps/mtm/serializers.py @@ -1,11 +1,13 @@ from apps.em.serializers import EquipmentSimpleSerializer from rest_framework import serializers from rest_framework.exceptions import ParseError, ValidationError + +from utils.mixins import DynamicFieldsSerializerMixin from .models import Material, Process, RecordForm, RecordFormField, Step, SubprodctionMaterial, TechDoc, UsedStep, SubProduction from apps.system.serializers import FileSimpleSerializer, OrganizationSimpleSerializer -class MaterialSerializer(serializers.ModelSerializer): +class MaterialSerializer(DynamicFieldsSerializerMixin, serializers.ModelSerializer): class Meta: model = Material fields = '__all__' diff --git a/hb_server/apps/pm/filters.py b/hb_server/apps/pm/filters.py index f530238..aa9c6da 100644 --- a/hb_server/apps/pm/filters.py +++ b/hb_server/apps/pm/filters.py @@ -2,10 +2,13 @@ from django_filters import rest_framework as filters from apps.mtm.models import Material, Step from apps.pm.models import ProductionPlan, SubProductionProgress from apps.wpm.models import Operation, WProduct - +from datetime import * from apps.wpm.services import WpmServies +from django.db.models import F -class PlanFilterSet(filters.FilterSet): +from utils.mixins import DynamicFieldsFilterMixin + +class PlanFilterSet(DynamicFieldsFilterMixin, filters.FilterSet): create_time_start = filters.DateFilter(field_name="create_time", lookup_expr='gte') create_time_end = filters.DateFilter(field_name="create_time", lookup_expr='lte') tag = filters.CharFilter(method='filter_tag') @@ -15,10 +18,19 @@ class PlanFilterSet(filters.FilterSet): fields = ['product', 'order', 'create_time_start', 'create_time_end'] def filter_tag(self, queryset, name, value): + now = datetime.now() + day7_after = now + timedelta(days=7) if value == 'planed': queryset = queryset.filter(is_planed=True) elif value == 'working': - queryset = queryset.exclude(state__in=[ProductionPlan.PLAN_STATE_DONE, ProductionPlan.PLAN_MTEST_DONE]) + queryset = queryset.exclude(state__in=[ProductionPlan.PLAN_STATE_DONE, + ProductionPlan.PLAN_MTEST_DONE]) + elif value == 'near_done': + queryset = queryset.filter(count_ok__lt=F('count'), + end_date__lte = datetime.date(day7_after)) + elif value == 'out_done': + queryset = queryset.filter(count_ok__lt=F('count'), + end_date__gt = datetime.date(now)) return queryset def filter_material(self, queryset, name, value): diff --git a/hb_server/apps/pm/serializers.py b/hb_server/apps/pm/serializers.py index b3bfb7a..a77694f 100644 --- a/hb_server/apps/pm/serializers.py +++ b/hb_server/apps/pm/serializers.py @@ -3,6 +3,7 @@ from rest_framework import serializers from apps.sam.serializers import OrderSerializer, OrderSimpleSerializer from apps.mtm.serializers import MaterialSimpleSerializer, ProcessSimpleSerializer, SubProductionSimpleSerializer from apps.system.serializers import OrganizationSimpleSerializer +from utils.mixins import DynamicFieldsSerializerMixin class ProductionPlanCreateFromOrderSerializer(serializers.ModelSerializer): @@ -10,7 +11,7 @@ class ProductionPlanCreateFromOrderSerializer(serializers.ModelSerializer): model = ProductionPlan fields = ['order', 'count', 'start_date', 'end_date'] -class ProductionPlanSerializer(serializers.ModelSerializer): +class ProductionPlanSerializer(DynamicFieldsSerializerMixin, serializers.ModelSerializer): order_ = OrderSimpleSerializer(source='order', read_only=True) product_ = MaterialSimpleSerializer(source='product', read_only=True) class Meta: diff --git a/hb_server/apps/pm/views.py b/hb_server/apps/pm/views.py index 3761ead..0fea0a7 100644 --- a/hb_server/apps/pm/views.py +++ b/hb_server/apps/pm/views.py @@ -7,7 +7,7 @@ from apps.em.models import Equipment from apps.em.serializers import EquipmentSimpleSerializer from apps.inm.models import MaterialBatch from apps.inm.serializers import MaterialBatchSerializer -from apps.mtm.models import Step, SubProduction, SubprodctionMaterial, UsedStep +from apps.mtm.models import Material, Step, SubProduction, SubprodctionMaterial from apps.pm.filters import PlanFilterSet, SubproductionProgressFilterSet from apps.system.mixins import CreateUpdateModelAMixin from apps.pm.serializers import GenSubPlanSerializer, PickNeedSerializer, PlanDestorySerializer, ProductionPlanCreateFromOrderSerializer, ProductionPlanSerializer, ResourceCalListSerializer, ResourceCalSerializer, SubProductionPlanListSerializer, SubProductionPlanUpdateSerializer, SubProductionProgressSerializer @@ -220,8 +220,12 @@ class ResourceViewSet(GenericViewSet): for i in rdata: # 计算输入物料 materials = SubprodctionMaterial.objects.filter(subproduction__product__id=i['id'], - subproduction__is_deleted=False, is_deleted=False, material__type__in=[3,4], type=1).order_by('material__number')\ - .values('material__id', 'material__name', 'material__number', 'material__type', 'count', 'material__count') + subproduction__is_deleted=False, is_deleted=False, + material__type__in=[Material.MA_TYPE_MAINSO, + Material.MA_TYPE_HELPSO], type= SubprodctionMaterial.SUB_MA_TYPE_IN).order_by('material__number')\ + .values('material__id', 'material__name', + 'material__number', 'material__type', + 'count', 'material__count', 'material__count_safe') l_m = list(materials) for m in l_m: if m['material__id'] in res_d_list: @@ -231,7 +235,8 @@ class ResourceViewSet(GenericViewSet): res_d_list.append(m['material__id']) res.append({'id':m['material__id'], 'name':m['material__name'], 'type':m['material__type'], 'number':m['material__number'], - 'count':m['count']*i['count'], 'inv_count':m['material__count']}) + 'count':m['count']*i['count'], 'inv_count':m['material__count'], + 'count_safe':m['material__count_safe']}) return Response(res) @action(methods=['post'], detail=False, perms_map={'post':'*'}, serializer_class=ResourceCalListSerializer) diff --git a/hb_server/apps/sam/filters.py b/hb_server/apps/sam/filters.py index a0c3626..c1b7607 100644 --- a/hb_server/apps/sam/filters.py +++ b/hb_server/apps/sam/filters.py @@ -4,8 +4,10 @@ from apps.sam.models import Order from django.db.models import F from datetime import datetime, timedelta +from utils.mixins import DynamicFieldsFilterMixin -class OrderFilterSet(filters.FilterSet): + +class OrderFilterSet(DynamicFieldsFilterMixin, filters.FilterSet): create_time_start = filters.DateFilter(field_name="create_time", lookup_expr='gte') create_time_end = filters.DateFilter(field_name="create_time", lookup_expr='lte') material = filters.NumberFilter(method='filter_material') @@ -23,8 +25,9 @@ class OrderFilterSet(filters.FilterSet): plan_order__subplan_plan__progress_subplan__material__id=value).distinct() def filter_tag(self, queryset, name, value): + now = datetime.now() + day7_after = now + timedelta(days=7) if value == 'near_delivery': - day7_after = datetime.now() + timedelta(days=7) queryset = queryset.filter(delivered_count__lt=F('count'), delivery_date__lte = datetime.date(day7_after)) elif value == 'out_delivery': diff --git a/hb_server/apps/sam/serializers.py b/hb_server/apps/sam/serializers.py index 81ed0df..4aeaeb9 100644 --- a/hb_server/apps/sam/serializers.py +++ b/hb_server/apps/sam/serializers.py @@ -1,10 +1,9 @@ -from django.db import transaction -from rest_framework import exceptions, serializers -from apps.inm.models import IProduct -from apps.inm.serializers import IProductListSerializer +from rest_framework import serializers -from .models import Contract, Customer, Order, Sale, SaleProduct +from utils.mixins import DynamicFieldsSerializerMixin + +from .models import Contract, Customer, Order from apps.mtm.serializers import MaterialSimpleSerializer from utils.tools import ranstr @@ -44,13 +43,13 @@ class ContractCreateUpdateSerializer(serializers.ModelSerializer): class OrderCreateUpdateSerializer(serializers.ModelSerializer): class Meta: model = Order - fields = ['customer', 'contract', 'product', 'count', 'delivery_date'] + fields = ['customer', 'contract', 'product', 'count', 'delivery_date', 'need_mtest'] def create(self, validated_data): validated_data['number'] = 'DD' + ranstr(7) return super().create(validated_data) -class OrderSerializer(serializers.ModelSerializer): +class OrderSerializer(DynamicFieldsSerializerMixin, serializers.ModelSerializer): contract_ = ContractSimpleSerializer(source='contract', read_only=True) customer_ = CustomerSimpleSerializer(source='customer', read_only=True) product_ = MaterialSimpleSerializer(source='product', read_only=True) @@ -63,48 +62,5 @@ class OrderSimpleSerializer(serializers.ModelSerializer): customer_ = CustomerSimpleSerializer(source='customer', read_only=True) class Meta: model = Order - fields = ['id', 'number', 'contract_', 'customer_', 'need_mtest'] + fields = ['id', 'number', 'contract_', 'customer_', 'need_mtest', 'delivery_date'] -class SaleCreateSerializer(serializers.ModelSerializer): - iproducts = serializers.PrimaryKeyRelatedField(queryset=IProduct.objects.all(), many=True) - class Meta: - model = Sale - fields = ['customer', 'order', 'product', 'iproducts'] - - def validate(self, attrs): - order = attrs.get('order', None) - if order: - if order.customer: - attrs['customer'] = order.customer - attrs['product'] = order.product - for i in attrs['iproducts']: - if i.material != attrs['product']: - raise exceptions.APIException('产品选取错误') - return super().validate(attrs) - - -class SaleListSerializer(serializers.ModelSerializer): - customer_ = CustomerSimpleSerializer(source='customer', read_only=True) - order_ = OrderSimpleSerializer(source='order', read_only=True) - product_ = MaterialSimpleSerializer(source='product', read_only=True) - class Meta: - model = Sale - fields = '__all__' - -class SaleProductListSerializer(serializers.ModelSerializer): - iproduct_ = IProductListSerializer(source='iproduct', read_only=True) - class Meta: - model = SaleProduct - fields = '__all__' - -class SaleProductCreateSerializer(serializers.ModelSerializer): - class Meta: - model = SaleProduct - fields = ['sale', 'iproduct'] - - def create(self, validated_data): - validated_data['number'] = validated_data['iproduct'].number - instance = SaleProduct.objects.create(**validated_data) - instance.sale.count = SaleProduct.objects.filter(sale=instance.sale).count() - instance.sale.save() - return instance \ No newline at end of file diff --git a/hb_server/apps/sam/serializers_sale.py b/hb_server/apps/sam/serializers_sale.py new file mode 100644 index 0000000..627c4f2 --- /dev/null +++ b/hb_server/apps/sam/serializers_sale.py @@ -0,0 +1,51 @@ +from rest_framework import serializers +from rest_framework import exceptions +from apps.inm.models import IProduct +from apps.inm.serializers import IProductListSerializer +from apps.mtm.serializers import MaterialSimpleSerializer +from apps.sam.models import Sale, SaleProduct +from apps.sam.serializers import CustomerSimpleSerializer, OrderSimpleSerializer +class SaleCreateSerializer(serializers.ModelSerializer): + iproducts = serializers.PrimaryKeyRelatedField(queryset= + IProduct.objects.all(), many=True) + class Meta: + model = Sale + fields = ['customer', 'order', 'product', 'iproducts'] + + def validate(self, attrs): + order = attrs.get('order', None) + if order: + if order.customer: + attrs['customer'] = order.customer + attrs['product'] = order.product + for i in attrs['iproducts']: + if i.material != attrs['product']: + raise exceptions.APIException('产品选取错误') + return super().validate(attrs) + + +class SaleListSerializer(serializers.ModelSerializer): + customer_ = CustomerSimpleSerializer(source='customer', read_only=True) + order_ = OrderSimpleSerializer(source='order', read_only=True) + product_ = MaterialSimpleSerializer(source='product', read_only=True) + class Meta: + model = Sale + fields = '__all__' + +class SaleProductListSerializer(serializers.ModelSerializer): + iproduct_ = IProductListSerializer(source='iproduct', read_only=True) + class Meta: + model = SaleProduct + fields = '__all__' + +class SaleProductCreateSerializer(serializers.ModelSerializer): + class Meta: + model = SaleProduct + fields = ['sale', 'iproduct'] + + def create(self, validated_data): + validated_data['number'] = validated_data['iproduct'].number + instance = SaleProduct.objects.create(**validated_data) + instance.sale.count = SaleProduct.objects.filter(sale=instance.sale).count() + instance.sale.save() + return instance \ No newline at end of file diff --git a/hb_server/apps/sam/urls.py b/hb_server/apps/sam/urls.py index 7a66e01..5907df0 100644 --- a/hb_server/apps/sam/urls.py +++ b/hb_server/apps/sam/urls.py @@ -1,9 +1,11 @@ from django.db.models import base from rest_framework import urlpatterns -from apps.sam.views import CustomerViewSet,ContractViewSet,OrderViewSet, SaleProductViewSet, SaleViewSet +from apps.sam.views import CustomerViewSet,ContractViewSet, OrderViewSet from django.urls import path, include from rest_framework.routers import DefaultRouter +from apps.sam.views_sale import SaleProductViewSet, SaleViewSet + router = DefaultRouter() router.register('customer', CustomerViewSet, basename='customer') router.register('contract', ContractViewSet, basename='contract') diff --git a/hb_server/apps/sam/views.py b/hb_server/apps/sam/views.py index 357706e..ea52cb4 100644 --- a/hb_server/apps/sam/views.py +++ b/hb_server/apps/sam/views.py @@ -1,22 +1,12 @@ -from django.db import transaction -from django.db.models.aggregates import Count -from rest_framework import exceptions, serializers -from rest_framework.mixins import CreateModelMixin, DestroyModelMixin, ListModelMixin, RetrieveModelMixin -from apps.mtm.models import Material -from apps.inm.models import FIFO, FIFOItem, FIFOItemProduct, IProduct, WareHouse -from apps.inm.signals import update_inm from apps.sam.filters import ContractFilterSet, OrderFilterSet -from apps.sam.serializers import ContractCreateUpdateSerializer, ContractSerializer, CustomerCreateUpdateSerializer, CustomerSerializer, OrderCreateUpdateSerializer, OrderSerializer, SaleCreateSerializer, SaleListSerializer, SaleProductCreateSerializer, SaleProductListSerializer -from apps.sam.models import Contract, Customer, Order, Sale, SaleProduct -from rest_framework.viewsets import GenericViewSet, ModelViewSet +from apps.sam.serializers import ContractCreateUpdateSerializer, ContractSerializer, \ + CustomerCreateUpdateSerializer, CustomerSerializer, OrderCreateUpdateSerializer, OrderSerializer +from apps.sam.models import Contract, Customer, Order +from rest_framework.viewsets import ModelViewSet from apps.system.mixins import CreateUpdateCustomMixin -from django.shortcuts import render -from rest_framework.decorators import action from django.db.models import F from rest_framework.response import Response -from django.utils import timezone - -from apps.wf.models import Workflow +from rest_framework.decorators import action # Create your views here. class CustomerViewSet(CreateUpdateCustomMixin, ModelViewSet): """ @@ -81,129 +71,6 @@ class OrderViewSet(CreateUpdateCustomMixin, ModelViewSet): return Response(serializer.data) -class SaleViewSet(CreateUpdateCustomMixin, ListModelMixin, RetrieveModelMixin, CreateModelMixin, DestroyModelMixin, GenericViewSet): - """ - 销售记录 - """ - perms_map = {'*': '*'} - queryset = Sale.objects.select_related('customer', 'order', 'product', 'order__contract').all() - serializer_class = SaleListSerializer - search_fields = ['customer__name', 'order__number'] - filterset_fields = ['product', 'order', 'customer'] - ordering_fields = ['create_time'] - ordering = ['-create_time'] - def get_serializer_class(self): - if self.action == 'create': - return SaleCreateSerializer - elif self.action == 'retrieve': - return SaleListSerializer - return super().get_serializer_class() - - def create(self, request, *args, **kwargs): - data = request.data - serializer = SaleCreateSerializer(data=data) - serializer.is_valid(raise_exception=True) - vdata = serializer.validated_data - with transaction.atomic(): - iproducts = vdata.pop('iproducts') - vdata['count'] = len(iproducts) - sale = Sale.objects.create(**vdata) - i_l = [] - for i in iproducts: - i_d ={} - i_d['sale'] = sale - i_d['number'] = i.number - i_d['iproduct'] = i - i_l.append(SaleProduct(**i_d)) - SaleProduct.objects.bulk_create(i_l) - return Response() - - @action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=serializers.Serializer) - @transaction.atomic - def audit(self, request, pk=None): - """ - 审核 - """ - obj = self.get_object() - if obj.is_audited: - raise exceptions.APIException('已审核通过') - # 创建出库记录 - fifo = FIFO() - fifo.type = FIFO.FIFO_TYPE_SALE_OUT - fifo.is_audited = True - fifo.auditor = request.user - fifo.inout_date = timezone.now() - fifo.create_by = request.user - fifo.save() - # 创建出库条目 - ips = IProduct.objects.filter(sale_iproduct__sale=obj) - items = ips.values('warehouse', 'material', 'batch').annotate(total=Count('id')) - for i in items: - warehouse = WareHouse.objects.get(id=i['warehouse']) - material = Material.objects.get(id=i['material']) - fifoitem = FIFOItem() - fifoitem.need_test = False - fifoitem.warehouse = warehouse - fifoitem.material = material - fifoitem.count = i['total'] - fifoitem.batch = i['batch'] - fifoitem.fifo = fifo - fifoitem.save() - items_p = ips.filter(warehouse=warehouse, batch=i['batch']) - ipxs = [] - for i in items_p: - # 创建出库明细半成品 - ip = {} - ip['fifoitem'] = fifoitem - ip['number'] = i.number - ip['material'] = i.material - ip['iproduct'] = i - ipxs.append(FIFOItemProduct(**ip)) - FIFOItemProduct.objects.bulk_create(ipxs) - # 更新成品库情况 - ips.update(is_saled=True) - # 更新动态产品表情况 - from apps.wpm.models import WProduct - WProduct.objects.filter(iproduct_wproduct__sale_iproduct__sale=obj).update( - act_state=WProduct.WPR_ACT_STATE_SELLED) - # 更新库存 - update_inm(fifo) - # 变更审核状态 - obj.is_audited = True - obj.save() - # 变更订单状态 - if obj.order: - order = obj.order - order.delivered_count = order.delivered_count + obj.count - order.save() - return Response() - -class SaleProductViewSet(ListModelMixin, DestroyModelMixin, CreateModelMixin, GenericViewSet): - """ - 销售记录关联产品 - """ - perms_map = {'*': '*'} - queryset = SaleProduct.objects.select_related('iproduct', 'iproduct__material', 'iproduct__warehouse').all() - serializer_class = SaleProductListSerializer - search_fields = [] - filterset_fields = ['sale', 'iproduct'] - ordering_fields = ['create_time'] - ordering = ['id'] - - def get_serializer_class(self): - if self.action == 'create': - return SaleProductCreateSerializer - return super().get_serializer_class() - - def destroy(self, request, *args, **kwargs): - obj = self.get_object() - sale = obj.sale - if sale.is_audited: - raise exceptions.APIException('该销售记录已审核,不可删除产品') - sale.count = SaleProduct.objects.filter(sale=obj.sale).count() - sale.save() - obj.delete() - return Response() \ No newline at end of file diff --git a/hb_server/apps/sam/views_sale.py b/hb_server/apps/sam/views_sale.py new file mode 100644 index 0000000..c2c81a1 --- /dev/null +++ b/hb_server/apps/sam/views_sale.py @@ -0,0 +1,142 @@ +from rest_framework.mixins import ListModelMixin, DestroyModelMixin, CreateModelMixin, RetrieveModelMixin +from rest_framework.viewsets import GenericViewSet +from rest_framework.response import Response +from apps.inm.models import FIFO, FIFOItem, FIFOItemProduct, IProduct, WareHouse +from apps.mtm.models import Material +from apps.sam.models import Sale, SaleProduct +from apps.sam.serializers_sale import SaleCreateSerializer, SaleListSerializer, SaleProductCreateSerializer, SaleProductListSerializer +from rest_framework import exceptions +from django.db import transaction +from rest_framework.decorators import action +from django.utils import timezone + +from apps.system.mixins import CreateUpdateModelAMixin +from apps.inm.signals import update_inm +from rest_framework import serializers + +class SaleViewSet(CreateUpdateModelAMixin, ListModelMixin, RetrieveModelMixin, CreateModelMixin, DestroyModelMixin, GenericViewSet): + """ + 销售记录 + """ + perms_map = {'*': '*'} + queryset = Sale.objects.select_related('customer', 'order', 'product', 'order__contract').all() + serializer_class = SaleListSerializer + search_fields = ['customer__name', 'order__number'] + filterset_fields = ['product', 'order', 'customer'] + ordering_fields = ['create_time'] + ordering = ['-create_time'] + + def get_serializer_class(self): + if self.action == 'create': + return SaleCreateSerializer + elif self.action == 'retrieve': + return SaleListSerializer + return super().get_serializer_class() + + def create(self, request, *args, **kwargs): + data = request.data + serializer = SaleCreateSerializer(data=data) + serializer.is_valid(raise_exception=True) + vdata = serializer.validated_data + with transaction.atomic(): + iproducts = vdata.pop('iproducts') + vdata['count'] = len(iproducts) + sale = Sale.objects.create(**vdata) + i_l = [] + for i in iproducts: + i_d ={} + i_d['sale'] = sale + i_d['number'] = i.number + i_d['iproduct'] = i + i_l.append(SaleProduct(**i_d)) + SaleProduct.objects.bulk_create(i_l) + return Response() + + @action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=serializers.Serializer) + @transaction.atomic + def audit(self, request, pk=None): + """ + 审核 + """ + obj = self.get_object() + if obj.is_audited: + raise exceptions.APIException('已审核通过') + # 创建出库记录 + fifo = FIFO() + fifo.type = FIFO.FIFO_TYPE_SALE_OUT + fifo.is_audited = True + fifo.auditor = request.user + fifo.inout_date = timezone.now() + fifo.create_by = request.user + fifo.save() + # 创建出库条目 + ips = IProduct.objects.filter(sale_iproduct__sale=obj) + items = ips.values('warehouse', 'material', 'batch').annotate(total=Count('id')) + for i in items: + warehouse = WareHouse.objects.get(id=i['warehouse']) + material = Material.objects.get(id=i['material']) + fifoitem = FIFOItem() + fifoitem.need_test = False + fifoitem.warehouse = warehouse + fifoitem.material = material + fifoitem.count = i['total'] + fifoitem.batch = i['batch'] + fifoitem.fifo = fifo + fifoitem.save() + items_p = ips.filter(warehouse=warehouse, batch=i['batch']) + ipxs = [] + for i in items_p: + # 创建出库明细半成品 + ip = {} + ip['fifoitem'] = fifoitem + ip['number'] = i.number + ip['material'] = i.material + ip['iproduct'] = i + ipxs.append(FIFOItemProduct(**ip)) + FIFOItemProduct.objects.bulk_create(ipxs) + # 更新成品库情况 + ips.update(is_saled=True) + # 更新动态产品表情况 + from apps.wpm.models import WProduct + WProduct.objects.filter(iproduct_wproduct__sale_iproduct__sale=obj).update( + act_state=WProduct.WPR_ACT_STATE_SELLED) + # 更新库存 + update_inm(fifo) + # 变更审核状态 + obj.is_audited = True + obj.save() + # 变更订单状态 + if obj.order: + order = obj.order + order.delivered_count = order.delivered_count + obj.count + order.save() + return Response() + + + +class SaleProductViewSet(ListModelMixin, DestroyModelMixin, CreateModelMixin, GenericViewSet): + """ + 销售记录关联产品 + """ + perms_map = {'*': '*'} + queryset = SaleProduct.objects.select_related('iproduct', 'iproduct__material', 'iproduct__warehouse').all() + serializer_class = SaleProductListSerializer + search_fields = [] + filterset_fields = ['sale', 'iproduct'] + ordering_fields = ['create_time'] + ordering = ['id'] + + def get_serializer_class(self): + if self.action == 'create': + return SaleProductCreateSerializer + return super().get_serializer_class() + + def destroy(self, request, *args, **kwargs): + obj = self.get_object() + sale = obj.sale + if sale.is_audited: + raise exceptions.APIException('该销售记录已审核,不可删除产品') + sale.count = SaleProduct.objects.filter(sale=obj.sale).count() + sale.save() + obj.delete() + return Response() \ No newline at end of file diff --git a/hb_server/apps/system/migrations/0005_user_last_check_time.py b/hb_server/apps/system/migrations/0005_user_last_check_time.py new file mode 100644 index 0000000..284e91b --- /dev/null +++ b/hb_server/apps/system/migrations/0005_user_last_check_time.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.9 on 2022-01-25 08:51 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('system', '0004_user_is_atwork'), + ] + + operations = [ + migrations.AddField( + model_name='user', + name='last_check_time', + field=models.DateTimeField(blank=True, null=True, verbose_name='打卡时间'), + ), + ] diff --git a/hb_server/apps/system/models.py b/hb_server/apps/system/models.py index e77eae3..d69121a 100644 --- a/hb_server/apps/system/models.py +++ b/hb_server/apps/system/models.py @@ -117,6 +117,7 @@ class User(AbstractUser): 'self', null=True, blank=True, on_delete=models.SET_NULL, verbose_name='上级主管') roles = models.ManyToManyField(Role, blank=True, verbose_name='角色') is_atwork = models.BooleanField('当前在岗', default=False) + last_check_time = models.DateTimeField('打卡时间', null=True, blank=True) class Meta: verbose_name = '用户信息' diff --git a/hb_server/apps/system/serializers.py b/hb_server/apps/system/serializers.py index 1e397c5..209061c 100644 --- a/hb_server/apps/system/serializers.py +++ b/hb_server/apps/system/serializers.py @@ -144,7 +144,7 @@ class UserListSerializer(DynamicFieldsSerializerMixin, serializers.ModelSerializ fields = ['id', 'name', 'phone', 'email', 'position', 'username', 'is_active', 'date_joined', 'dept_name', 'dept', 'roles', 'avatar', - 'roles_name', 'is_atwork'] + 'roles_name', 'is_atwork', 'last_check_time'] @staticmethod def setup_eager_loading(queryset): diff --git a/hb_server/apps/wpm/filters.py b/hb_server/apps/wpm/filters.py index c4db494..5cfb6ea 100644 --- a/hb_server/apps/wpm/filters.py +++ b/hb_server/apps/wpm/filters.py @@ -41,7 +41,7 @@ class WProductFilterSet(DynamicFieldsFilterMixin, filters.FilterSet): class Meta: model = WProduct fields = ['step', 'subproduction_plan', 'material', - 'step__process', 'act_state', 'material__type'] + 'step__process', 'act_state', 'material__type', 'need_to_order'] def filter_tag(self, queryset, name, value): if value == 'no_scrap': diff --git a/hb_server/apps/wpm/migrations/0052_auto_20220125_1116.py b/hb_server/apps/wpm/migrations/0052_auto_20220125_1116.py new file mode 100644 index 0000000..ff2d3d1 --- /dev/null +++ b/hb_server/apps/wpm/migrations/0052_auto_20220125_1116.py @@ -0,0 +1,31 @@ +# Generated by Django 3.2.9 on 2022-01-25 03:16 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('wpm', '0051_auto_20220120_1541'), + ] + + operations = [ + migrations.RemoveField( + model_name='wproduct', + name='is_mtested', + ), + migrations.RemoveField( + model_name='wproductflow', + name='is_mtested', + ), + migrations.AddField( + model_name='wproduct', + name='need_to_order', + field=models.BooleanField(default=False, verbose_name='是否要指派订单'), + ), + migrations.AddField( + model_name='wproductflow', + name='need_to_order', + field=models.BooleanField(default=False, verbose_name='是否要指派订单'), + ), + ] diff --git a/hb_server/apps/wpm/models.py b/hb_server/apps/wpm/models.py index 9027301..571960e 100644 --- a/hb_server/apps/wpm/models.py +++ b/hb_server/apps/wpm/models.py @@ -119,6 +119,7 @@ class WProduct(CommonAModel): ticket = models.ForeignKey('wf.ticket', verbose_name='当前工单', on_delete=models.SET_NULL, null=True, blank=True, related_name='wp_ticket') + need_to_order = models.BooleanField('是否要指派订单', default=False) to_order = models.ForeignKey('sam.order', verbose_name='指派的订单', null=True, blank=True, on_delete = models.CASCADE) is_mtestok = models.BooleanField('是否军检合格', null=True, blank=True) remark_mtest = models.TextField('军检备注', null=True, blank=True) @@ -192,6 +193,8 @@ class WproductFlow(CommonAModel): on_delete=models.SET_NULL, null=True, blank=True) ticket = models.ForeignKey('wf.ticket', verbose_name='当前工单', on_delete=models.SET_NULL, null=True, blank=True) + + need_to_order = models.BooleanField('是否要指派订单', default=False) to_order = models.ForeignKey('sam.order', verbose_name='指派的订单', null=True, blank=True, on_delete = models.CASCADE) is_mtestok = models.BooleanField('是否军检合格', null=True, blank=True) remark_mtest = models.TextField('军检备注', null=True, blank=True) diff --git a/hb_server/apps/wpm/serializers.py b/hb_server/apps/wpm/serializers.py index cf7ca24..9636c0f 100644 --- a/hb_server/apps/wpm/serializers.py +++ b/hb_server/apps/wpm/serializers.py @@ -574,4 +574,7 @@ class WproductMtestSerializer(serializers.ModelSerializer): class WproductToOrderSerializer(serializers.Serializer): wproducts = serializers.PrimaryKeyRelatedField(queryset=WProduct.objects.all(), many=True) - order = serializers.PrimaryKeyRelatedField(queryset=Order.objects.all()) \ No newline at end of file + order = serializers.PrimaryKeyRelatedField(queryset=Order.objects.all()) + +class WproductNeedToOrderSerializer(serializers.Serializer): + wproducts = serializers.PrimaryKeyRelatedField(queryset=WProduct.objects.all(), many=True) \ No newline at end of file diff --git a/hb_server/apps/wpm/tasks.py b/hb_server/apps/wpm/tasks.py new file mode 100644 index 0000000..e69de29 diff --git a/hb_server/apps/wpm/views.py b/hb_server/apps/wpm/views.py index d1f9c5a..d9c24f4 100644 --- a/hb_server/apps/wpm/views.py +++ b/hb_server/apps/wpm/views.py @@ -26,7 +26,7 @@ from apps.wpm.serializers import CuttingListSerializer, OperationEquipListSerial OperationListSerializer, OperationWproductUpdateSerializer, PickHalfsSerializer, \ PickSerializer, OperationInitSerializer, OperationSubmitSerializer, ScrapSerializer, WMaterialListSerializer, \ WProductCardSerializer, WProductDetailSerializer, WProductListSerializer, \ - WpmTestFormInitSerializer, WproductMtestSerializer, WproductPutInSerializer, \ + WpmTestFormInitSerializer, WproductMtestSerializer, WproductNeedToOrderSerializer, WproductPutInSerializer, \ WproductPutInsSerializer, WproductTicketListSerializer, WproductToOrderSerializer from rest_framework.response import Response @@ -399,7 +399,7 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet): 军检 """ obj = self.get_object() - if obj.is_mtestok is None: + if obj.is_mtestok is not None: raise exceptions.APIException('已进行军检') if obj.material.type != Material.MA_TYPE_GOOD: raise exceptions.APIException('军检必须是成品') @@ -409,6 +409,7 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet): if is_mtestok: WpmServies.update_plan_state_by_mtestok( obj.subproduction_plan.production_plan) + obj.update_by = request.user obj.save() change_str = 'mtest_notok' if is_mtestok: @@ -441,6 +442,24 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet): ret.append([str(index + 1), item['step_name'], item['actions']]) return Response(ret) + @action(methods=['post'], detail=False, perms_map={'post': '*'}, serializer_class=WproductNeedToOrderSerializer) + @transaction.atomic + def need_to_order(self, request, pk=None): + """ + 设为需要指派订单 + """ + serializer = WproductNeedToOrderSerializer(data=request.data) + serializer.is_valid(raise_exception=True) + vdata = serializer.validated_data + wps = WProduct.objects.filter(id__in = [i.id for i in vdata.get('wproducts')]) + wps.update() + for i in wps: + i.need_to_order = True + i.update_by = request.user + i.save() + WpmServies.add_wproduct_flow_log(i, change_str='need_to_order') + return Response() + @action(methods=['post'], detail=False, perms_map={'post': '*'}, serializer_class=WproductToOrderSerializer) @transaction.atomic def to_order(self, request, pk=None): @@ -451,6 +470,8 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet): serializer.is_valid(raise_exception=True) vdata = serializer.validated_data wps = WProduct.objects.filter(id__in = [i.id for i in vdata.get('wproducts')]) + if wps.filter(need_to_order = False).exists(): + raise exceptions.ValidationError('存在不需要指派订单的产品') wp = wps.first() order = vdata['order'] if wp.material != order.product: diff --git a/hb_server/utils/response.py b/hb_server/utils/response.py index 0411547..864862c 100644 --- a/hb_server/utils/response.py +++ b/hb_server/utils/response.py @@ -48,11 +48,13 @@ class FitJSONRenderer(JSONRenderer): response_body = BaseResponse() response = renderer_context.get("response") status_code = response.status_code # Http状态异常码 + print(status_code) if status_code >= 400: # 如果http响应异常 if isinstance(data, dict) and 'code' in data: # 如果自定义了异常码 response_body = data else: response_body.data = data # data里是详细异常信息 + response_body.code = status_code prefix = "" if isinstance(data, dict): prefix = list(data.keys())[0]