订单数量统计,生产进度统计
This commit is contained in:
parent
80956f41c2
commit
1d0de666b8
|
@ -121,6 +121,10 @@ class UpdateFIFONumber(APIView):
|
||||||
i.save()
|
i.save()
|
||||||
return Response()
|
return Response()
|
||||||
|
|
||||||
|
class CorrectWproductState(APIView):
|
||||||
|
permission_classes = [IsAdminUser]
|
||||||
|
def post(self, request):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ReloadServer(APIView):
|
class ReloadServer(APIView):
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Generated by Django 3.2.9 on 2022-03-15 07:00
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('em', '0012_auto_20220120_1048'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='equipment',
|
||||||
|
name='state',
|
||||||
|
field=models.PositiveIntegerField(choices=[(10, '完好'), (20, '限用'), (30, '在修'), (40, '禁用'), (50, '报废')], default=0, verbose_name='设备状态'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,20 @@
|
||||||
|
# Generated by Django 3.2.9 on 2022-03-15 07:00
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('sam', '0016_sale_iproducts'),
|
||||||
|
('inm', '0033_fifoitem_expiration_date'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='fifo',
|
||||||
|
name='sale',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='fifo_sale', to='sam.sale', verbose_name='关联销售记录'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -1,6 +1,8 @@
|
||||||
|
from email.policy import default
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from apps.pm.models import ProductionPlan, SubProductionPlan
|
from apps.pm.models import ProductionPlan, SubProductionPlan
|
||||||
from apps.mtm.serializers import MaterialSimpleSerializer, ProcessSimpleSerializer
|
from apps.mtm.serializers import MaterialSimpleSerializer, ProcessSimpleSerializer
|
||||||
|
from apps.system.models import Organization
|
||||||
|
|
||||||
class SubplanGanttSerializer(serializers.ModelSerializer):
|
class SubplanGanttSerializer(serializers.ModelSerializer):
|
||||||
process_ = ProcessSimpleSerializer(source='process', read_only=True)
|
process_ = ProcessSimpleSerializer(source='process', read_only=True)
|
||||||
|
@ -25,10 +27,20 @@ class ProcessYieldSerializer(serializers.Serializer):
|
||||||
datetime_start = serializers.DateField(label='开始时间', required=False, allow_null=True)
|
datetime_start = serializers.DateField(label='开始时间', required=False, allow_null=True)
|
||||||
datetime_end = serializers.DateField(label='结束时间', required=False, allow_null=True)
|
datetime_end = serializers.DateField(label='结束时间', required=False, allow_null=True)
|
||||||
|
|
||||||
class ProductCountSerializer(serializers.Serializer):
|
class SrmCountSerializer(serializers.Serializer):
|
||||||
datetime_start = serializers.DateField(label='开始时间', required=False, allow_null=True)
|
datetime_start = serializers.DateField(label='开始时间', required=False, allow_null=True)
|
||||||
datetime_end = serializers.DateField(label='结束时间', required=False, allow_null=True)
|
datetime_end = serializers.DateField(label='结束时间', required=False, allow_null=True)
|
||||||
|
|
||||||
|
class ProductCountSerializer(serializers.Serializer):
|
||||||
|
tag_choices=(
|
||||||
|
(1, '统计成品'),
|
||||||
|
(2, '统计全部')
|
||||||
|
)
|
||||||
|
datetime_start = serializers.DateField(label='开始时间', required=False, allow_null=True)
|
||||||
|
datetime_end = serializers.DateField(label='结束时间', required=False, allow_null=True)
|
||||||
|
tag = serializers.ChoiceField(choices=tag_choices, label='统计范围1成品2全部', default=1)
|
||||||
|
dept = serializers.PrimaryKeyRelatedField(queryset=Organization.objects.all(), label="车间", required=False)
|
||||||
|
|
||||||
class AtWorkCountSerializer(serializers.Serializer):
|
class AtWorkCountSerializer(serializers.Serializer):
|
||||||
year = serializers.IntegerField(label='年')
|
year = serializers.IntegerField(label='年')
|
||||||
month = serializers.IntegerField(label='月')
|
month = serializers.IntegerField(label='月')
|
|
@ -1,25 +1,68 @@
|
||||||
from apps.mtm.models import Material
|
from apps.mtm.models import Material
|
||||||
|
from apps.pm.models import ProductionPlan
|
||||||
|
from apps.sam.models import Order
|
||||||
from apps.wpm.models import WProduct, WproductFlow
|
from apps.wpm.models import WProduct, WproductFlow
|
||||||
|
from django.db.models import F
|
||||||
|
|
||||||
class SrmServices:
|
class SrmServices:
|
||||||
"""
|
"""
|
||||||
数据统计分析
|
数据统计分析
|
||||||
"""
|
"""
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_wp_product_count(cls, datetime_start, datetime_end):
|
def get_product_count(cls, datetime_start=None, datetime_end=None, tag=1, dept=None):
|
||||||
"""
|
"""
|
||||||
根据生产情况统计相关数量
|
根据生产情况统计相关数量
|
||||||
"""
|
"""
|
||||||
|
if tag == 1:
|
||||||
objs = WproductFlow.objects.filter(is_lastlog=True, material__type=Material.MA_TYPE_GOOD)
|
objs = WproductFlow.objects.filter(is_lastlog=True, material__type=Material.MA_TYPE_GOOD)
|
||||||
|
else:
|
||||||
|
objs = WproductFlow.objects.filter(is_lastlog=True)
|
||||||
if datetime_start:
|
if datetime_start:
|
||||||
objs = objs.filter(create_time__gte=datetime_start)
|
objs = objs.filter(create_time__gte=datetime_start)
|
||||||
if datetime_end:
|
if datetime_end:
|
||||||
objs = objs.filter(create_time__lte=datetime_end)
|
objs = objs.filter(create_time__lte=datetime_end)
|
||||||
|
if dept:
|
||||||
|
objs = objs.filter(subproduction_plan__workshop=dept)
|
||||||
count = objs.count()
|
count = objs.count()
|
||||||
count_ok = objs.filter(act_state__in=[WProduct.WPR_ACT_STATE_INM,
|
count_ok = objs.filter(act_state__in=[WProduct.WPR_ACT_STATE_INM,
|
||||||
WProduct.WPR_ACT_STATE_OK, WProduct.WPR_ACT_STATE_SELLED]).count()
|
WProduct.WPR_ACT_STATE_OK, WProduct.WPR_ACT_STATE_SELLED]).count()
|
||||||
count_notok = objs.filter(act_state__in=[WProduct.WPR_ACT_STATE_NOTOK, WProduct.WPR_ACT_STATE_SCRAP]).count()
|
# count_notok = objs.filter(act_state__in=[WProduct.WPR_ACT_STATE_NOTOK, WProduct.WPR_ACT_STATE_SCRAP]).count()
|
||||||
|
count_notok = (
|
||||||
|
objs.filter(act_state__in=[WProduct.WPR_ACT_STATE_NOTOK, WProduct.WPR_ACT_STATE_SCRAP]).exclude(step__process__id=1)
|
||||||
|
| objs.filter(act_state__in=[WProduct.WPR_ACT_STATE_NOTOK, WProduct.WPR_ACT_STATE_SCRAP],
|
||||||
|
step__process__id=1).exclude(number=None)
|
||||||
|
).count()
|
||||||
count_selled = objs.filter(act_state=WProduct.WPR_ACT_STATE_SELLED).count()
|
count_selled = objs.filter(act_state=WProduct.WPR_ACT_STATE_SELLED).count()
|
||||||
count_mtestok = objs.filter(is_mtestok=True).count()
|
count_mtestok = objs.filter(is_mtestok=True).count()
|
||||||
return dict(count=count,count_ok=count_ok, count_notok=count_notok, count_selled=count_selled, count_mtestok=count_mtestok)
|
return dict(count=count,count_ok=count_ok, count_notok=count_notok, count_selled=count_selled, count_mtestok=count_mtestok)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_plan_count(cls, datetime_start=None, datetime_end=None):
|
||||||
|
"""
|
||||||
|
任务数量
|
||||||
|
"""
|
||||||
|
objs = ProductionPlan.objects.all()
|
||||||
|
if datetime_start:
|
||||||
|
objs = objs.filter(end_date__gte=datetime_start)
|
||||||
|
if datetime_end:
|
||||||
|
objs = objs.filter(end_date__lte=datetime_end)
|
||||||
|
count = objs.count()
|
||||||
|
count_use = objs.exclude(state__in=[ProductionPlan.PLAN_STATE_PAUSE, ProductionPlan.PLAN_STATE_STOP]).count()
|
||||||
|
count_completed = objs.filter(state__in=[ProductionPlan.PLAN_STATE_DONE, ProductionPlan.PLAN_MTEST_DONE]).count()
|
||||||
|
return dict(count=count, count_use=count_use, count_completed=count_completed)
|
||||||
|
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_order_count(cls, datetime_start=None, datetime_end=None):
|
||||||
|
"""
|
||||||
|
订单数量
|
||||||
|
"""
|
||||||
|
objs = Order.objects.all()
|
||||||
|
if datetime_start:
|
||||||
|
objs = objs.filter(delivery_date__gte=datetime_start)
|
||||||
|
if datetime_end:
|
||||||
|
objs = objs.filter(delivery_date__lte=datetime_end)
|
||||||
|
count = objs.count()
|
||||||
|
count_delivered = objs.filter(delivered_count__gte=F('count')).count()
|
||||||
|
return dict(count=count, count_delivered=count_delivered)
|
||||||
|
|
|
@ -3,13 +3,16 @@ from rest_framework import urlpatterns
|
||||||
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.srm.views import AtWorkCountView, GanttPlan, ProcessYieldView, ProductCountView
|
from apps.srm.views import AtWorkCountView, GanttPlan, OrderCountView, PlanCountView, ProcessNowView, ProcessYieldView, ProductCountView
|
||||||
|
|
||||||
router = DefaultRouter()
|
router = DefaultRouter()
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('gantt/plan/', GanttPlan.as_view()),
|
path('gantt/plan/', GanttPlan.as_view()),
|
||||||
path('product/count/', ProductCountView.as_view()),
|
path('product/count/', ProductCountView.as_view()),
|
||||||
|
path('plan/count/', PlanCountView.as_view()),
|
||||||
|
path('order/count/', OrderCountView.as_view()),
|
||||||
path('process/yield/', ProcessYieldView.as_view()),
|
path('process/yield/', ProcessYieldView.as_view()),
|
||||||
|
path('process/now/', ProcessNowView.as_view()),
|
||||||
path('at_work/', AtWorkCountView.as_view()),
|
path('at_work/', AtWorkCountView.as_view()),
|
||||||
path('', include(router.urls)),
|
path('', include(router.urls)),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
|
||||||
from datetime import date, timedelta
|
from datetime import date, timedelta
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
|
from idna import valid_contextj
|
||||||
from numpy import number
|
from numpy import number
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from rest_framework.generics import ListAPIView, CreateAPIView
|
from rest_framework.generics import ListAPIView, CreateAPIView
|
||||||
|
@ -9,10 +10,10 @@ from rest_framework.response import Response
|
||||||
from apps.hrm.models import ClockRecord
|
from apps.hrm.models import ClockRecord
|
||||||
from apps.mtm.models import Process, Step
|
from apps.mtm.models import Process, Step
|
||||||
from apps.pm.models import ProductionPlan, SubProductionPlan
|
from apps.pm.models import ProductionPlan, SubProductionPlan
|
||||||
from apps.srm.serializers import AtWorkCountSerializer, PlanGanttSerializer, ProcessYieldSerializer, ProductCountSerializer
|
from apps.srm.serializers import AtWorkCountSerializer, PlanGanttSerializer, ProcessYieldSerializer, ProductCountSerializer, SrmCountSerializer
|
||||||
from apps.srm.services import SrmServices
|
from apps.srm.services import SrmServices
|
||||||
from apps.wpm.models import WProduct, WproductFlow
|
from apps.wpm.models import WProduct, WproductFlow
|
||||||
from django.db.models import Count, F
|
from django.db.models import Count, F, Sum
|
||||||
# Create your views here.
|
# Create your views here.
|
||||||
|
|
||||||
class GanttPlan(ListAPIView):
|
class GanttPlan(ListAPIView):
|
||||||
|
@ -34,9 +35,52 @@ class ProductCountView(CreateAPIView):
|
||||||
serializer = self.get_serializer(data=request.data)
|
serializer = self.get_serializer(data=request.data)
|
||||||
serializer.is_valid(raise_exception=True)
|
serializer.is_valid(raise_exception=True)
|
||||||
vdata = serializer.validated_data
|
vdata = serializer.validated_data
|
||||||
res = SrmServices.get_wp_product_count(datetime_start= vdata.get('datetime_start', None), datetime_end= vdata.get('datetime_end', None))
|
res = SrmServices.get_product_count(**vdata)
|
||||||
return Response(res)
|
return Response(res)
|
||||||
|
|
||||||
|
|
||||||
|
class PlanCountView(CreateAPIView):
|
||||||
|
"""
|
||||||
|
计划数量统计
|
||||||
|
"""
|
||||||
|
perms_map = {'post':'*'}
|
||||||
|
serializer_class = SrmCountSerializer
|
||||||
|
|
||||||
|
def create(self, request, *args, **kwargs):
|
||||||
|
serializer = self.get_serializer(data=request.data)
|
||||||
|
serializer.is_valid(raise_exception=True)
|
||||||
|
vdata = serializer.validated_data
|
||||||
|
res = SrmServices.get_plan_count(**vdata)
|
||||||
|
return Response(res)
|
||||||
|
|
||||||
|
class OrderCountView(CreateAPIView):
|
||||||
|
"""
|
||||||
|
订单数量统计
|
||||||
|
"""
|
||||||
|
perms_map = {'post':'*'}
|
||||||
|
serializer_class = SrmCountSerializer
|
||||||
|
|
||||||
|
def create(self, request, *args, **kwargs):
|
||||||
|
serializer = self.get_serializer(data=request.data)
|
||||||
|
serializer.is_valid(raise_exception=True)
|
||||||
|
vdata = serializer.validated_data
|
||||||
|
res = SrmServices.get_order_count(**vdata)
|
||||||
|
return Response(res)
|
||||||
|
|
||||||
|
class ProcessNowView(CreateAPIView):
|
||||||
|
"""
|
||||||
|
工序当前进度
|
||||||
|
"""
|
||||||
|
perms_map = {'post':'*'}
|
||||||
|
serializers_class = serializers.Serializer
|
||||||
|
|
||||||
|
def create(self, request, *args, **kwargs):
|
||||||
|
objs = SubProductionPlan.objects.filter(production_plan__state__in =[ProductionPlan.PLAN_STATE_WORKING,
|
||||||
|
ProductionPlan.PLAN_STATE_ASSGINED]).order_by('process__number').values('process',
|
||||||
|
'process__name').annotate(count_ok=Sum('count_ok'),
|
||||||
|
count=Sum('count'), count_real=Sum('count_real'), count_notok=Sum('count_notok'))
|
||||||
|
return Response(objs)
|
||||||
|
|
||||||
class ProcessYieldView(CreateAPIView):
|
class ProcessYieldView(CreateAPIView):
|
||||||
"""
|
"""
|
||||||
工序成品率统计
|
工序成品率统计
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
# Generated by Django 3.2.9 on 2022-03-15 07:00
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('wpm', '0053_auto_20220129_1512'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='operationequip',
|
||||||
|
name='state',
|
||||||
|
field=models.PositiveSmallIntegerField(choices=[(10, '完好'), (20, '限用'), (30, '在修'), (40, '禁用'), (50, '报废')], default=10, verbose_name='当前设备状态'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='wproduct',
|
||||||
|
name='act_state',
|
||||||
|
field=models.IntegerField(choices=[(6, '待复检'), (8, '操作准备中'), (10, '操作进行中'), (20, '待检验'), (26, '待夹层检验'), (30, '已合格'), (40, '已入库'), (50, '不合格'), (60, '待成品检验'), (70, '已报废'), (80, '已售出'), (90, '已使用')], default=0, verbose_name='进行状态'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='wproductflow',
|
||||||
|
name='act_state',
|
||||||
|
field=models.IntegerField(choices=[(6, '待复检'), (8, '操作准备中'), (10, '操作进行中'), (20, '待检验'), (26, '待夹层检验'), (30, '已合格'), (40, '已入库'), (50, '不合格'), (60, '待成品检验'), (70, '已报废'), (80, '已售出'), (90, '已使用')], default=0, verbose_name='进行状态'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -43,6 +43,7 @@ class WProduct(CommonAModel):
|
||||||
WPR_ACT_STATE_TOFINALTEST = 60
|
WPR_ACT_STATE_TOFINALTEST = 60
|
||||||
WPR_ACT_STATE_SCRAP = 70
|
WPR_ACT_STATE_SCRAP = 70
|
||||||
WPR_ACT_STATE_SELLED = 80
|
WPR_ACT_STATE_SELLED = 80
|
||||||
|
WPR_ACT_STATE_USED = 90
|
||||||
act_state_choices = (
|
act_state_choices = (
|
||||||
(WPR_ACT_STATE_TORETEST, '待复检'),
|
(WPR_ACT_STATE_TORETEST, '待复检'),
|
||||||
(WPR_ACT_STATE_DOWAIT, '操作准备中'),
|
(WPR_ACT_STATE_DOWAIT, '操作准备中'),
|
||||||
|
@ -55,6 +56,7 @@ class WProduct(CommonAModel):
|
||||||
(WPR_ACT_STATE_TOFINALTEST, '待成品检验'),
|
(WPR_ACT_STATE_TOFINALTEST, '待成品检验'),
|
||||||
(WPR_ACT_STATE_SCRAP, '已报废'),
|
(WPR_ACT_STATE_SCRAP, '已报废'),
|
||||||
(WPR_ACT_STATE_SELLED, '已售出'),
|
(WPR_ACT_STATE_SELLED, '已售出'),
|
||||||
|
(WPR_ACT_STATE_USED, '已使用'),
|
||||||
)
|
)
|
||||||
SCRAP_REASON_QIPAO = 10
|
SCRAP_REASON_QIPAO = 10
|
||||||
SCRAP_REASON_PODIAN = 20
|
SCRAP_REASON_PODIAN = 20
|
||||||
|
|
|
@ -781,8 +781,9 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd
|
||||||
WpmService.add_wproduct_flow_log(wproduct, 'wproduct_create')
|
WpmService.add_wproduct_flow_log(wproduct, 'wproduct_create')
|
||||||
# 隐藏原半成品
|
# 隐藏原半成品
|
||||||
wps = WProduct.objects.filter(ow_wproduct__operation=op)
|
wps = WProduct.objects.filter(ow_wproduct__operation=op)
|
||||||
wps.update(is_hidden=True, child=wproduct,
|
wps.update(act_state=WProduct.WPR_ACT_STATE_USED, child=wproduct, is_hidden=True,
|
||||||
update_by=request.user, update_time=timezone.now())
|
update_by=request.user, update_time=timezone.now())
|
||||||
|
WpmService.add_wproducts_flow_log(wps, change_str='wproduct_create')
|
||||||
else:
|
else:
|
||||||
raise exceptions.APIException('产出物料未填写或填写错误')
|
raise exceptions.APIException('产出物料未填写或填写错误')
|
||||||
op.is_submited = True
|
op.is_submited = True
|
||||||
|
|
Loading…
Reference in New Issue