This commit is contained in:
TianyangZhang 2025-11-10 15:41:38 +08:00
commit 6e5db774b7
8 changed files with 122 additions and 13 deletions

View File

@ -212,11 +212,18 @@ class MIOItemCreateSerializer(CustomModelSerializer):
mio_type = mio.type mio_type = mio.type
if mio_type != "pur_in" and mio_type != "other_in": if mio_type != "pur_in" and mio_type != "other_in":
wprIds = [i["wpr"].id for i in mioitemw] wprIds = [i["wpr"].id for i in mioitemw]
mb_ids = list(Wpr.objects.filter(id__in=wprIds).values_list("mb__id", flat=True).distinct()) if instance.mb:
if len(mb_ids) == 1 and mb_ids[0] == instance.mb.id: mb_ids = list(Wpr.objects.filter(id__in=wprIds).values_list("mb__id", flat=True).distinct())
pass if len(mb_ids) == 1 and mb_ids[0] == instance.mb.id:
else: pass
raise ParseError(f'{batch}物料明细中存在{len(mb_ids)}个不同物料批次') else:
raise ParseError(f'{batch}物料明细中存在{len(mb_ids)}个不同物料批次')
elif instance.wm:
wm_ids = list(Wpr.objects.filter(id__in=wprIds).values_list("wm__id", flat=True).distinct())
if len(wm_ids) == 1 and wm_ids[0] == instance.wm.id:
pass
else:
raise ParseError(f'{batch}物料明细中存在{len(wm_ids)}个不同物料批次')
for item in mioitemw: for item in mioitemw:
if item.get("wpr", None) is None and mio_type != "pur_in" and mio_type != "other_in": if item.get("wpr", None) is None and mio_type != "pur_in" and mio_type != "other_in":
raise ParseError(f'{item["number"]}_请提供产品明细ID') raise ParseError(f'{item["number"]}_请提供产品明细ID')

View File

@ -0,0 +1,40 @@
# Generated by Django 3.2.12 on 2025-11-10 02:00
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 = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('system', '0006_auto_20241213_1249'),
('wf', '0004_workflow_view_path2'),
('pum', '0008_auto_20240731_1829'),
]
operations = [
migrations.CreateModel(
name='SupplierAudit',
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='删除标记')),
('name', models.CharField(max_length=100, verbose_name='供应商名称')),
('material_name', models.CharField(max_length=100, verbose_name='物料名称')),
('material_cate', models.CharField(max_length=100, verbose_name='物料类别')),
('business_license', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='supplier_audit_business_license', to='system.file', verbose_name='营业执照')),
('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='supplieraudit_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')),
('quality_certificate', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='supplier_audit_quality_certificate', to='system.file', verbose_name='质量证书')),
('survery_form', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='supplier_audit_survey_form', to='system.file', verbose_name='调查表')),
('ticket', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='wf.ticket', verbose_name='关联工单')),
('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='supplieraudit_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')),
],
options={
'abstract': False,
},
),
]

View File

@ -1,6 +1,7 @@
from django.db import models from django.db import models
from apps.utils.models import CommonBModel, BaseModel, CommonBDModel from apps.utils.models import CommonBModel, BaseModel, CommonBDModel, CommonADModel
from apps.mtm.models import Material from apps.mtm.models import Material
from apps.wf.models import Ticket
# Create your models here. # Create your models here.
@ -15,6 +16,15 @@ class Supplier(CommonBModel):
address = models.CharField('地址', max_length=200, default='', blank=True) address = models.CharField('地址', max_length=200, default='', blank=True)
can_outsource = models.BooleanField('是否可外协', default=False) can_outsource = models.BooleanField('是否可外协', default=False)
class SupplierAudit(CommonADModel):
name = models.CharField('供应商名称', max_length=100)
material_name = models.CharField('物料名称', max_length=100)
material_cate = models.CharField('物料类别', max_length=100)
survery_form = models.ForeignKey('system.file', verbose_name='调查表', on_delete=models.SET_NULL, null=True, blank=True, related_name='supplier_audit_survey_form')
business_license = models.ForeignKey('system.file', verbose_name='营业执照', on_delete=models.SET_NULL, null=True, blank=True, related_name='supplier_audit_business_license')
quality_certificate = models.ForeignKey('system.file', verbose_name='质量证书', on_delete=models.SET_NULL, null=True, blank=True, related_name='supplier_audit_quality_certificate')
ticket = models.ForeignKey('wf.ticket', verbose_name='关联工单', on_delete=models.SET_NULL, null=True, blank=True)
class PuPlan(CommonBModel): class PuPlan(CommonBModel):
""" """

View File

@ -3,10 +3,12 @@ from apps.utils.serializers import CustomModelSerializer
from apps.utils.constants import EXCLUDE_FIELDS_DEPT, EXCLUDE_FIELDS_BASE, EXCLUDE_FIELDS from apps.utils.constants import EXCLUDE_FIELDS_DEPT, EXCLUDE_FIELDS_BASE, EXCLUDE_FIELDS
from rest_framework.exceptions import ValidationError from rest_framework.exceptions import ValidationError
from apps.pum.models import Supplier, PuPlan, PuPlanItem, PuOrder, PuOrderItem from apps.pum.models import Supplier, PuPlan, PuPlanItem, PuOrder, PuOrderItem, SupplierAudit
from apps.mtm.serializers import MaterialSerializer, MaterialSimpleSerializer from apps.mtm.serializers import MaterialSerializer, MaterialSimpleSerializer
from django.db import transaction from django.db import transaction
from .services import PumService from .services import PumService
from apps.wf.serializers import TicketSimpleSerializer
from apps.system.serializers import FileSerializer
class SupplierSerializer(CustomModelSerializer): class SupplierSerializer(CustomModelSerializer):
@ -139,3 +141,13 @@ class AddSerializer(serializers.Serializer):
label='采购订单ID', queryset=PuOrder.objects.all()) label='采购订单ID', queryset=PuOrder.objects.all())
pu_planitems = serializers.PrimaryKeyRelatedField( pu_planitems = serializers.PrimaryKeyRelatedField(
label='计划明细ID', queryset=PuPlanItem.objects.all(), many=True) label='计划明细ID', queryset=PuPlanItem.objects.all(), many=True)
class SupplierAuditSerializer(CustomModelSerializer):
survery_form_ = FileSerializer(source="survery_form", read_only=True)
business_license_ = FileSerializer(source="business_license", read_only=True)
quality_certificate_ = FileSerializer(source="quality_certificate", read_only=True)
ticket_ = TicketSimpleSerializer(source="ticket", read_only=True)
class Meta:
model = SupplierAudit
fields = "__all__"

View File

@ -1,9 +1,9 @@
from rest_framework.exceptions import ValidationError from rest_framework.exceptions import ValidationError
from apps.pum.models import PuOrderItem, PuPlan, PuPlanItem, PuOrder from apps.pum.models import PuOrderItem, PuPlan, PuPlanItem, PuOrder, SupplierAudit
from django.db.models import F, Sum from django.db.models import F, Sum
from apps.inm.models import MIO, MIOItem from apps.inm.models import MIO, MIOItem
from rest_framework.exceptions import ParseError from rest_framework.exceptions import ParseError
from apps.wf.models import Ticket, Transition
class PumService: class PumService:
@ -95,3 +95,18 @@ class PumService:
puplan.state = PuPlan.PUPLAN_DONE puplan.state = PuPlan.PUPLAN_DONE
puplan.save() puplan.save()
def bind_supplieraudit(ticket: Ticket, transition: Transition, new_ticket_data: dict):
ins = SupplierAudit.objects.get(id=new_ticket_data['t_id'])
if ins.ticket and ins.ticket.id != ticket.id:
raise ParseError('重复创建工单')
ticket_data = ticket.ticket_data
ticket_data.update({
't_model': 'supplier_audit',
't_id': ins.id,
})
ticket.ticket_data = ticket_data
ticket.create_by = ins.create_by
ticket.save()
if ins.ticket is None:
ins.ticket = ticket
ins.save()

View File

@ -1,12 +1,13 @@
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.pum.views import (SupplierViewSet, PuPlanViewSet, PuPlanItemViewSet, PuOrderViewSet, PuOrderItemViewSet) from apps.pum.views import (SupplierViewSet, PuPlanViewSet, PuPlanItemViewSet, PuOrderViewSet, PuOrderItemViewSet, SupplierAuditViewSet)
API_BASE_URL = 'api/pum/' API_BASE_URL = 'api/pum/'
HTML_BASE_URL = 'dhtml/pum/' HTML_BASE_URL = 'dhtml/pum/'
router = DefaultRouter() router = DefaultRouter()
router.register('supplier', SupplierViewSet, basename='supplier') router.register('supplier', SupplierViewSet, basename='supplier')
router.register('supplieraudit', SupplierAuditViewSet, basename='supplieraudit')
router.register('pu_plan', PuPlanViewSet, basename='pu_plan') router.register('pu_plan', PuPlanViewSet, basename='pu_plan')
router.register('pu_planitem', PuPlanItemViewSet, basename='pu_planitem') router.register('pu_planitem', PuPlanItemViewSet, basename='pu_planitem')
router.register('pu_order', PuOrderViewSet, basename='pu_order') router.register('pu_order', PuOrderViewSet, basename='pu_order')

View File

@ -1,8 +1,8 @@
from django.shortcuts import render from django.shortcuts import render
from apps.pum.models import Supplier, PuPlan, PuPlanItem, PuOrder, PuOrderItem from apps.pum.models import Supplier, PuPlan, PuPlanItem, PuOrder, PuOrderItem, SupplierAudit
from apps.utils.viewsets import CustomGenericViewSet, CustomModelViewSet from apps.utils.viewsets import CustomGenericViewSet, CustomModelViewSet, EuModelViewSet
from apps.pum.serializers import (SupplierSerializer, PuPlanSerializer, PuPlanItemSerializer, from apps.pum.serializers import (SupplierSerializer, PuPlanSerializer, PuPlanItemSerializer,
PuOrderSerializer, PuOrderItemSerializer, AddSerializer) PuOrderSerializer, PuOrderItemSerializer, AddSerializer, SupplierAuditSerializer)
from rest_framework.exceptions import ParseError, PermissionDenied from rest_framework.exceptions import ParseError, PermissionDenied
from rest_framework.decorators import action from rest_framework.decorators import action
from rest_framework import serializers from rest_framework import serializers
@ -11,6 +11,7 @@ from django.db import transaction
from rest_framework.response import Response from rest_framework.response import Response
from django.utils import timezone from django.utils import timezone
from apps.pum.services import PumService from apps.pum.services import PumService
from apps.wf.models import Ticket
# Create your views here. # Create your views here.
@ -30,6 +31,23 @@ class SupplierViewSet(CustomModelViewSet):
raise ParseError('该供应商存在采购订单不可删除') raise ParseError('该供应商存在采购订单不可删除')
instance.delete() instance.delete()
class SupplierAuditViewSet(CustomModelViewSet):
"""
list: 供应商审核
供应商审核
"""
queryset = SupplierAudit.objects.all()
serializer_class = SupplierAuditSerializer
search_fields = ['name', 'material_name', 'material_cate']
def perform_destroy(self, instance):
ticket:Ticket = instance.ticket
if ticket and ticket.state.type != 1:
raise ParseError('该记录关联的工单已被处理,不可删除')
instance.delete()
if ticket:
ticket.delete()
class PuPlanViewSet(CustomModelViewSet): class PuPlanViewSet(CustomModelViewSet):
""" """

View File

@ -91,6 +91,12 @@ class BulkCreateModelMixin(CreateModelMixin):
rdata = request.data rdata = request.data
many = False many = False
if isinstance(rdata, list): if isinstance(rdata, list):
for item in rdata:
if "id" in item and item["id"]:
raise ParseError('创建数据中不能包含id字段')
else:
if "id" in rdata and rdata["id"]:
raise ParseError('创建数据中不能包含id字段')
many = True many = True
sr = self.get_serializer(data=rdata, many=many) sr = self.get_serializer(data=rdata, many=many)
sr.is_valid(raise_exception=True) sr.is_valid(raise_exception=True)