feat: 增加车间库存并完成生产领料
This commit is contained in:
parent
8934186460
commit
9504b527cb
|
@ -0,0 +1,26 @@
|
|||
# Generated by Django 3.2.12 on 2023-09-27 07:16
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('inm', '0002_mio_mioitem'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='mio',
|
||||
name='pick_user',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='领料人'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='mioitem',
|
||||
name='batch',
|
||||
field=models.CharField(max_length=50, verbose_name='批次号'),
|
||||
),
|
||||
]
|
|
@ -3,8 +3,10 @@ from apps.utils.models import BaseModel, CommonBModel, CommonBDModel
|
|||
from apps.pum.models import Supplier, PuOrder
|
||||
from apps.sam.models import Customer, Order
|
||||
from apps.mtm.models import Material
|
||||
from apps.system.models import User
|
||||
# Create your models here.
|
||||
|
||||
|
||||
class WareHouse(CommonBModel):
|
||||
"""
|
||||
仓库信息
|
||||
|
@ -31,7 +33,7 @@ class MIO(CommonBDModel):
|
|||
"""
|
||||
出入库记录
|
||||
"""
|
||||
MIO_TYPE_DO_OUT = 'do_out'
|
||||
MIO_TYPE_DO_OUT = 'do_out'
|
||||
MIO_TYPE_SALE_OUT = 'sale_out'
|
||||
MIO_TYPE_PUR_IN = 'pur_in'
|
||||
MIO_TYPE_DO_IN = 'do_in'
|
||||
|
@ -53,24 +55,35 @@ class MIO(CommonBDModel):
|
|||
(MIO_SUBMITED, '已提交')
|
||||
)
|
||||
number = models.CharField('编号', max_length=20)
|
||||
state = models.PositiveSmallIntegerField('状态', choices=MIO_STATES, default=10, help_text=str(MIO_CREATE))
|
||||
type = models.CharField('出入库类型', max_length=10, default=MIO_TYPE_DO_OUT, choices=MIO_TYPES, help_text=str(MIO_TYPES))
|
||||
state = models.PositiveSmallIntegerField(
|
||||
'状态', choices=MIO_STATES, default=10, help_text=str(MIO_CREATE))
|
||||
type = models.CharField('出入库类型', max_length=10, default=MIO_TYPE_DO_OUT,
|
||||
choices=MIO_TYPES, help_text=str(MIO_TYPES))
|
||||
inout_date = models.DateField('出入库日期', null=True, blank=True)
|
||||
supplier = models.ForeignKey(Supplier, verbose_name='供应商', on_delete=models.CASCADE, null=True, blank=True)
|
||||
customer = models.ForeignKey(Customer, verbose_name='客户', on_delete=models.CASCADE, null=True, blank=True)
|
||||
pu_order = models.ForeignKey(PuOrder, verbose_name='关联采购订单', on_delete=models.CASCADE, null=True, blank=True)
|
||||
order = models.ForeignKey(Order, verbose_name='关联订单', on_delete=models.CASCADE, null=True, blank=True)
|
||||
supplier = models.ForeignKey(
|
||||
Supplier, verbose_name='供应商', on_delete=models.CASCADE, null=True, blank=True)
|
||||
customer = models.ForeignKey(
|
||||
Customer, verbose_name='客户', on_delete=models.CASCADE, null=True, blank=True)
|
||||
pu_order = models.ForeignKey(
|
||||
PuOrder, verbose_name='关联采购订单', on_delete=models.CASCADE, null=True, blank=True)
|
||||
order = models.ForeignKey(
|
||||
Order, verbose_name='关联订单', on_delete=models.CASCADE, null=True, blank=True)
|
||||
note = models.CharField('备注', max_length=1000, default='')
|
||||
expiration_date = models.DateField('有效期', null=True, blank=True)
|
||||
submit_time = models.DateTimeField('提交时间', null=True, blank=True)
|
||||
pick_user = models.ForeignKey(
|
||||
User, verbose_name='领料人', on_delete=models.CASCADE, null=True, blank=True)
|
||||
|
||||
|
||||
class MIOItem(BaseModel):
|
||||
"""
|
||||
出入库明细
|
||||
"""
|
||||
mio = models.ForeignKey(MIO, verbose_name='关联出入库', on_delete=models.CASCADE)
|
||||
warehouse = models.ForeignKey(WareHouse, on_delete=models.CASCADE, verbose_name='仓库')
|
||||
material = models.ForeignKey(Material, verbose_name='物料', on_delete=models.CASCADE)
|
||||
batch = models.CharField('批次号', max_length=20)
|
||||
count = models.PositiveIntegerField('数量', default=0)
|
||||
mio = models.ForeignKey(MIO, verbose_name='关联出入库',
|
||||
on_delete=models.CASCADE)
|
||||
warehouse = models.ForeignKey(
|
||||
WareHouse, on_delete=models.CASCADE, verbose_name='仓库')
|
||||
material = models.ForeignKey(
|
||||
Material, verbose_name='物料', on_delete=models.CASCADE)
|
||||
batch = models.CharField('批次号', max_length=50)
|
||||
count = models.PositiveIntegerField('数量', default=0)
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
from rest_framework import serializers
|
||||
from apps.utils.serializers import CustomModelSerializer
|
||||
from apps.inm.models import WareHouse, MaterialBatch, MIO, MIOItem
|
||||
from apps.utils.constants import EXCLUDE_FIELDS_DEPT, EXCLUDE_FIELDS_BASE
|
||||
from apps.pum.models import PuOrder
|
||||
from rest_framework.exceptions import ValidationError
|
||||
|
||||
from apps.mtm.serializers import MaterialSerializer
|
||||
from apps.pum.models import PuOrder
|
||||
from apps.system.models import Dept, User
|
||||
from apps.utils.constants import EXCLUDE_FIELDS_BASE, EXCLUDE_FIELDS_DEPT
|
||||
from apps.utils.serializers import CustomModelSerializer
|
||||
|
||||
from .models import MIO, MaterialBatch, MIOItem, WareHouse
|
||||
|
||||
|
||||
class WareHourseSerializer(CustomModelSerializer):
|
||||
|
@ -15,8 +18,11 @@ class WareHourseSerializer(CustomModelSerializer):
|
|||
|
||||
|
||||
class MaterialBatchSerializer(CustomModelSerializer):
|
||||
warehouse_name = serializers.CharField(source='warehouse.name', read_only=True)
|
||||
material_name = serializers.CharField(source='material.name', read_only=True)
|
||||
warehouse_name = serializers.CharField(
|
||||
source='warehouse.name', read_only=True)
|
||||
material_name = serializers.CharField(
|
||||
source='material.name', read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = MaterialBatch
|
||||
fields = '__all__'
|
||||
|
@ -24,12 +30,14 @@ class MaterialBatchSerializer(CustomModelSerializer):
|
|||
|
||||
|
||||
class MIOSerializer(CustomModelSerializer):
|
||||
create_by_name = serializers.CharField(source='create_by.name', read_only=True)
|
||||
create_by_name = serializers.CharField(
|
||||
source='create_by.name', read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = MIO
|
||||
fields = '__all__'
|
||||
read_only_fields = EXCLUDE_FIELDS_DEPT + ['state', 'submit_time']
|
||||
|
||||
|
||||
def validate(self, attrs):
|
||||
if 'pu_order' in attrs and attrs['pu_order']:
|
||||
attrs['supplier'] = attrs['pu_order'].supplier
|
||||
|
@ -46,15 +54,16 @@ class MIOSerializer(CustomModelSerializer):
|
|||
else:
|
||||
raise ValidationError('该采购订单不可选')
|
||||
return super().create(validated_data)
|
||||
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
validated_data.pop('type')
|
||||
return super().update(instance, validated_data)
|
||||
|
||||
|
||||
|
||||
class MIOItemSerializer(CustomModelSerializer):
|
||||
warehouse_name = serializers.CharField(source='warehouse', read_only=True)
|
||||
material_ = MaterialSerializer(source='material', read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = MIOItem
|
||||
fields = '__all__'
|
||||
|
@ -64,3 +73,23 @@ class MIOItemSerializer(CustomModelSerializer):
|
|||
if mio.state != MIO.MIO_CREATE:
|
||||
raise ValidationError('出入库记录非创建中不可新增')
|
||||
return super().create(validated_data)
|
||||
|
||||
|
||||
class PickSerializer(CustomModelSerializer):
|
||||
belong_dept = serializers.PrimaryKeyRelatedField(
|
||||
label="领料车间", queryset=Dept.objects.all(), required=True)
|
||||
pick_user = serializers.PrimaryKeyRelatedField(
|
||||
label="领料人", queryset=User.objects.all(), required=True)
|
||||
|
||||
class Meta:
|
||||
model = MIO
|
||||
fields = ['number', 'note', 'pick_user', 'belong_dept']
|
||||
|
||||
def create(self, validated_data):
|
||||
validated_data['type'] = MIO.MIO_TYPE_DO_OUT
|
||||
return super().create(validated_data)
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
if instance.state != MIO.MIO_CREATE:
|
||||
raise ValidationError('记录非创建中')
|
||||
return super().update(instance, validated_data)
|
||||
|
|
|
@ -4,33 +4,36 @@ from django.db.models.aggregates import Sum
|
|||
|
||||
|
||||
class InmService:
|
||||
|
||||
|
||||
@classmethod
|
||||
def update_inm(cls, instance: MIO):
|
||||
"""
|
||||
更新库存, 暂不支持反向操作
|
||||
"""
|
||||
if instance.type in [MIO.MIO_TYPE_PUR_IN, MIO.MIO_TYPE_DO_IN, MIO.MIO_TYPE_OTHER_IN]: # 采购入库, 生产入库, 其他入库
|
||||
if instance.type in [MIO.MIO_TYPE_PUR_IN, MIO.MIO_TYPE_DO_IN, MIO.MIO_TYPE_OTHER_IN]: # 采购入库, 生产入库, 其他入库
|
||||
cls.update_mb(instance)
|
||||
if instance.type == MIO.MIO_TYPE_PUR_IN: # 需要更新订单
|
||||
from apps.pum.services import PumService
|
||||
PumService.mio_purin(instance)
|
||||
elif instance.type in [MIO.MIO_TYPE_DO_OUT, MIO.MIO_TYPE_SALE_OUT, MIO.MIO_TYPE_OTHER_OUT]: # 生产领料 销售出库
|
||||
elif instance.type in [MIO.MIO_TYPE_DO_OUT, MIO.MIO_TYPE_SALE_OUT, MIO.MIO_TYPE_OTHER_OUT]: # 生产领料 销售出库
|
||||
cls.update_mb(instance, -1)
|
||||
if instance.type == MIO.MIO_TYPE_SALE_OUT:
|
||||
from apps.sam.services import SamService
|
||||
SamService.mio_saleout(instance)
|
||||
elif instance.type == MIO.MIO_TYPE_DO_OUT:
|
||||
from apps.wpm.services import pick
|
||||
pick(instance)
|
||||
|
||||
@classmethod
|
||||
def update_mb(cls, instance: MIO, in_or_out: int =1):
|
||||
def update_mb(cls, instance: MIO, in_or_out: int = 1):
|
||||
"""
|
||||
更新物料批次
|
||||
"""
|
||||
for i in MIOItem.objects.filter(mio=instance):
|
||||
material = i.material
|
||||
warehouse = i.warehouse
|
||||
mb, _ = MaterialBatch.objects.get_or_create(material=material, warehouse=warehouse, batch=i.batch,\
|
||||
defaults={'material':material, 'warehouse':warehouse, 'count':0, 'batch':i.batch})
|
||||
mb, _ = MaterialBatch.objects.get_or_create(material=material, warehouse=warehouse, batch=i.batch,
|
||||
defaults={'material': material, 'warehouse': warehouse, 'count': 0, 'batch': i.batch})
|
||||
if in_or_out == 1:
|
||||
mb.count = mb.count + i.count
|
||||
if mb.expiration_date is None:
|
||||
|
@ -43,5 +46,6 @@ class InmService:
|
|||
mb.save()
|
||||
else:
|
||||
raise ValidationError('不支持的操作')
|
||||
material.count = MaterialBatch.objects.filter(material=material).aggregate(total=Sum('count')).get('total', 0)
|
||||
material.save()
|
||||
material.count = MaterialBatch.objects.filter(
|
||||
material=material).aggregate(total=Sum('count')).get('total', 0)
|
||||
material.save()
|
||||
|
|
|
@ -8,7 +8,8 @@ from django.utils import timezone
|
|||
from rest_framework.response import Response
|
||||
|
||||
from apps.inm.models import WareHouse, MaterialBatch, MIO, MIOItem
|
||||
from apps.inm.serializers import (MaterialBatchSerializer, WareHourseSerializer, MIOSerializer, MIOItemSerializer)
|
||||
from apps.inm.serializers import (
|
||||
MaterialBatchSerializer, WareHourseSerializer, MIOSerializer, MIOItemSerializer, PickSerializer)
|
||||
from apps.utils.viewsets import CustomGenericViewSet, CustomModelViewSet
|
||||
from apps.inm.services import InmService
|
||||
from apps.utils.mixins import BulkCreateModelMixin, BulkDestroyModelMixin
|
||||
|
@ -60,7 +61,19 @@ class MIOViewSet(ListModelMixin, DestroyModelMixin, CustomGenericViewSet):
|
|||
if instance.state != MIO.MIO_CREATE:
|
||||
raise ParseError('非创建中不可删除')
|
||||
return super().perform_destroy(instance)
|
||||
|
||||
|
||||
@action(methods=['post'], detail=False, perms_map={'post': 'mio.pick'}, serializer_class=PickSerializer)
|
||||
@transaction.atomic
|
||||
def pick(self, request, *args, **kwargs):
|
||||
"""生产领料
|
||||
|
||||
生产领料
|
||||
"""
|
||||
sr = PickSerializer(data=request.data)
|
||||
sr.is_valid(raise_exception=True)
|
||||
sr.save()
|
||||
return Response()
|
||||
|
||||
@action(methods=['post'], detail=True, perms_map={'post': 'mio.update'}, serializer_class=serializers.Serializer)
|
||||
@transaction.atomic
|
||||
def submit(self, request, *args, **kwargs):
|
||||
|
@ -70,16 +83,17 @@ class MIOViewSet(ListModelMixin, DestroyModelMixin, CustomGenericViewSet):
|
|||
"""
|
||||
ins = self.get_object()
|
||||
user = request.user
|
||||
if ins.create_by != user:
|
||||
if ins.state != MIO.MIO_TYPE_DO_OUT and ins.create_by != user:
|
||||
raise PermissionDenied('非创建人不可提交')
|
||||
if ins.state != MIO.MIO_CREATE:
|
||||
raise ParseError('订单非创建中')
|
||||
raise ParseError('记录状态异常')
|
||||
ins.submit_time = timezone.now()
|
||||
ins.state = MIO.MIO_SUBMITED
|
||||
ins.save()
|
||||
InmService.update_inm(ins)
|
||||
return Response()
|
||||
|
||||
|
||||
class MIOItemViewSet(ListModelMixin, BulkCreateModelMixin, BulkDestroyModelMixin, CustomGenericViewSet):
|
||||
"""
|
||||
list: 出入库明细
|
||||
|
@ -91,8 +105,8 @@ class MIOItemViewSet(ListModelMixin, BulkCreateModelMixin, BulkDestroyModelMixin
|
|||
select_related_fields = ['warehouse', 'mio', 'material']
|
||||
filterset_fields = ['warehouse', 'mio', 'material']
|
||||
ordering = ['create_time']
|
||||
|
||||
|
||||
def perform_destroy(self, instance):
|
||||
if instance.state != MIO.MIO_CREATE:
|
||||
raise ParseError('出入库记录非创建中不可删除')
|
||||
return super().perform_destroy(instance)
|
||||
return super().perform_destroy(instance)
|
||||
|
|
|
@ -62,7 +62,7 @@ class Material(CommonAModel):
|
|||
ordering = ['sort', '-create_time']
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
return f'{self.specification}-{self.name}'
|
||||
|
||||
|
||||
class Shift(CommonAModel):
|
||||
|
|
|
@ -26,12 +26,11 @@ class CustomGenericViewSet(MyLoggingMixin, GenericViewSet):
|
|||
"""
|
||||
增强的GenericViewSet
|
||||
"""
|
||||
perms_map = {} # 权限标识
|
||||
perms_map = {'get': '*'} # 权限标识
|
||||
throttle_classes = [UserRateThrottle]
|
||||
logging_methods = ['POST', 'PUT', 'PATCH', 'DELETE']
|
||||
ordering_fields = '__all__'
|
||||
ordering = '-create_time'
|
||||
filterset_fields = []
|
||||
create_serializer_class = None
|
||||
update_serializer_class = None
|
||||
partial_update_serializer_class = None
|
||||
|
@ -44,15 +43,18 @@ class CustomGenericViewSet(MyLoggingMixin, GenericViewSet):
|
|||
data_filter_field = 'belong_dept'
|
||||
hash_k = None
|
||||
cache_seconds = 5 # 接口缓存时间默认5秒
|
||||
filterset_fields = select_related_fields
|
||||
|
||||
def finalize_response(self, request, response, *args, **kwargs):
|
||||
if self.hash_k and self.cache_seconds:
|
||||
cache.set(self.hash_k, response.data, timeout=self.cache_seconds) # 将结果存入缓存,设置超时时间
|
||||
cache.set(self.hash_k, response.data,
|
||||
timeout=self.cache_seconds) # 将结果存入缓存,设置超时时间
|
||||
return super().finalize_response(request, response, *args, **kwargs)
|
||||
|
||||
|
||||
def initial(self, request, *args, **kwargs):
|
||||
super().initial(request, *args, **kwargs)
|
||||
cache_seconds = getattr(self, f"{self.action}_cache_seconds", getattr(self, 'cache_seconds', 0))
|
||||
cache_seconds = getattr(
|
||||
self, f"{self.action}_cache_seconds", getattr(self, 'cache_seconds', 0))
|
||||
if cache_seconds:
|
||||
self.cache_seconds = cache_seconds
|
||||
rdata = {}
|
||||
|
@ -164,6 +166,7 @@ class CustomModelViewSet(BulkCreateModelMixin, BulkUpdateModelMixin, ListModelMi
|
|||
"""
|
||||
增强的ModelViewSet
|
||||
"""
|
||||
|
||||
def __init__(self, **kwargs) -> None:
|
||||
super().__init__(**kwargs)
|
||||
# 增加默认权限标识
|
||||
|
@ -210,4 +213,3 @@ class CustomModelViewSet(BulkCreateModelMixin, BulkUpdateModelMixin, ListModelMi
|
|||
return self.get_paginated_response(serializer.data)
|
||||
serializer = self.get_serializer(new_qs, many=True)
|
||||
return Response(serializer.data)
|
||||
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
# Generated by Django 3.2.12 on 2023-09-27 07:16
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('mtm', '0014_alter_process_options'),
|
||||
('system', '0002_myschedule'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('wpm', '0010_auto_20230808_1413'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='WMaterial',
|
||||
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='删除标记')),
|
||||
('batch', models.CharField(max_length=50, verbose_name='批次号')),
|
||||
('count', models.PositiveIntegerField(default=0, verbose_name='当前数量')),
|
||||
('belong_dept', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='wmaterial_belong_dept', to='system.dept', verbose_name='所属部门')),
|
||||
('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='wmaterial_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')),
|
||||
('material', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='mtm.material', verbose_name='物料')),
|
||||
('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='wmaterial_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
]
|
|
@ -1,6 +1,6 @@
|
|||
from django.db import models
|
||||
from apps.utils.models import CommonADModel
|
||||
from apps.mtm.models import Mgroup, Team, Shift
|
||||
from apps.utils.models import CommonADModel, CommonBDModel
|
||||
from apps.mtm.models import Mgroup, Team, Shift, Material
|
||||
from django.utils.timezone import localtime
|
||||
|
||||
# Create your models here.
|
||||
|
@ -63,3 +63,13 @@ class SfLogExp(CommonADModel):
|
|||
handler = models.CharField('处理人', default='', max_length=100)
|
||||
is_current_down = models.BooleanField('是否本班停机', default=False)
|
||||
duration = models.FloatField('停机时长(h)', null=True, blank=True)
|
||||
|
||||
|
||||
class WMaterial(CommonBDModel):
|
||||
"""
|
||||
belong_dept是所在车间
|
||||
"""
|
||||
material = models.ForeignKey(
|
||||
Material, verbose_name='物料', on_delete=models.CASCADE)
|
||||
batch = models.CharField('批次号', max_length=50)
|
||||
count = models.PositiveIntegerField('当前数量', default=0)
|
||||
|
|
|
@ -2,12 +2,15 @@ from apps.utils.constants import EXCLUDE_FIELDS
|
|||
from apps.utils.serializers import CustomModelSerializer
|
||||
from rest_framework import serializers
|
||||
|
||||
from apps.wpm.models import SfLog, StLog, SfLogExp
|
||||
from .models import SfLog, StLog, SfLogExp, WMaterial
|
||||
from apps.system.models import Dictionary
|
||||
from apps.wpm.tasks import cal_enstat_when_pcoal_heat_change, cal_enstat_when_team_change
|
||||
from apps.mtm.serializers import MaterialSerializer
|
||||
|
||||
|
||||
class StLogSerializer(CustomModelSerializer):
|
||||
mgroup_name = serializers.CharField(source='mgroup.name', read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = StLog
|
||||
fields = '__all__'
|
||||
|
@ -18,10 +21,12 @@ class SfLogSerializer(CustomModelSerializer):
|
|||
team_name = serializers.CharField(source='team.name', read_only=True)
|
||||
shift_name = serializers.CharField(source='shift.name', read_only=True)
|
||||
leader_name = serializers.CharField(source='leader.name', read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = SfLog
|
||||
fields = '__all__'
|
||||
read_only_fields = EXCLUDE_FIELDS + ['mgroup', 'start_time', 'end_time', 'belong_dept']
|
||||
read_only_fields = EXCLUDE_FIELDS + \
|
||||
['mgroup', 'start_time', 'end_time', 'belong_dept']
|
||||
extra_kwargs = {
|
||||
'team': {'required': True},
|
||||
'leader': {'required': True}
|
||||
|
@ -48,11 +53,23 @@ class SfLogSerializer(CustomModelSerializer):
|
|||
|
||||
class SflogExpSerializer(CustomModelSerializer):
|
||||
mgroup = serializers.CharField(source='sflog.mgroup.id', read_only=True)
|
||||
mgroup_name = serializers.CharField(source='sflog.mgroup.name', read_only=True)
|
||||
mgroup_name = serializers.CharField(
|
||||
source='sflog.mgroup.name', read_only=True)
|
||||
stlog_ = StLogSerializer(source='stlog', read_only=True)
|
||||
happen_time = serializers.DateTimeField(required=True, label='发生时间')
|
||||
cate = serializers.CharField(required=True, label='原因类别')
|
||||
|
||||
class Meta:
|
||||
model = SfLogExp
|
||||
fields = '__all__'
|
||||
read_only_fields = EXCLUDE_FIELDS + ['stlog', 'is_current_down']
|
||||
read_only_fields = EXCLUDE_FIELDS + ['stlog', 'is_current_down']
|
||||
|
||||
|
||||
class WMaterialSerializer(CustomModelSerializer):
|
||||
material_ = MaterialSerializer(source='material', read_only=True)
|
||||
belong_dept_name = serializers.CharField(
|
||||
source='belong_dept.name', read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = WMaterial
|
||||
fields = '__all__'
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
from apps.wpm.models import SfLog, SfLogExp
|
||||
from apps.mtm.models import Shift, Mgroup
|
||||
import datetime
|
||||
from django.utils.timezone import localtime
|
||||
from django.db.models import Sum
|
||||
|
||||
from django.core.cache import cache
|
||||
from django.db.models import Sum
|
||||
from django.utils.timezone import localtime
|
||||
|
||||
from apps.inm.models import MIO, MIOItem
|
||||
from apps.mtm.models import Mgroup, Shift
|
||||
|
||||
from .models import SfLog, SfLogExp, WMaterial
|
||||
|
||||
|
||||
def make_sflogs(mgroup: Mgroup, start_date: datetime.date, end_date: datetime.date):
|
||||
for shift in Shift.objects.all():
|
||||
|
@ -24,6 +29,7 @@ def make_sflogs(mgroup: Mgroup, start_date: datetime.date, end_date: datetime.da
|
|||
})
|
||||
current_date = current_date + datetime.timedelta(days=1)
|
||||
|
||||
|
||||
def get_pcoal_heat(year_s: int, month_s: int, day_s: int):
|
||||
"""
|
||||
获取煤粉热值
|
||||
|
@ -36,11 +42,33 @@ def get_pcoal_heat(year_s: int, month_s: int, day_s: int):
|
|||
else:
|
||||
try:
|
||||
qs = SfLog.objects.get(end_time__year=year_s, end_time__month=month_s, end_time__day=day_s,
|
||||
mgroup__name='回转窑', shift__name='白班')
|
||||
mgroup__name='回转窑', shift__name='白班')
|
||||
if qs.pcoal_heat is None:
|
||||
qs.pcoal_heat = 0
|
||||
qs.save()
|
||||
cache.set(f'pgoal_val_{year_s}_{month_s}_{day_s}', qs.pcoal_heat)
|
||||
return qs.pcoal_heat
|
||||
except:
|
||||
except Exception:
|
||||
return 0
|
||||
|
||||
|
||||
def pick(mio: MIO):
|
||||
"""
|
||||
生产领料到车间
|
||||
"""
|
||||
belong_dept = mio.belong_dept
|
||||
pick_user = mio.pick_user
|
||||
mioitems = MIOItem.objects.filter(mio=mio)
|
||||
for item in mioitems:
|
||||
wm, new_create = WMaterial.objects.get_or_create(batch=item.batch, material=item.material,
|
||||
belong_dept=belong_dept, defaults={
|
||||
"batch": item.batch,
|
||||
"material": item.material,
|
||||
"count": item.count,
|
||||
"create_by": pick_user,
|
||||
"belong_dept": belong_dept
|
||||
})
|
||||
if not new_create:
|
||||
wm.count = wm.count + item.count
|
||||
wm.update_by = pick_user
|
||||
wm.save()
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from django.urls import path, include
|
||||
from rest_framework.routers import DefaultRouter
|
||||
|
||||
from apps.wpm.views import SfLogViewSet, StLogViewSet, SfLogExpViewSet
|
||||
from apps.wpm.views import SfLogViewSet, StLogViewSet, SfLogExpViewSet, WMaterialViewSet
|
||||
|
||||
|
||||
API_BASE_URL = 'api/wpm/'
|
||||
|
@ -11,7 +11,7 @@ router = DefaultRouter()
|
|||
router.register('sflog', SfLogViewSet, basename='sflog')
|
||||
router.register('stlog', StLogViewSet, basename='stlog')
|
||||
router.register('sflogexp', SfLogExpViewSet, basename='sflogexp')
|
||||
|
||||
router.register('wmaterial', WMaterialViewSet, basename='wmaterial')
|
||||
urlpatterns = [
|
||||
path(API_BASE_URL, include(router.urls)),
|
||||
]
|
||||
]
|
||||
|
|
|
@ -1,18 +1,20 @@
|
|||
from django.shortcuts import render
|
||||
from rest_framework.mixins import ListModelMixin, UpdateModelMixin
|
||||
from rest_framework.decorators import action
|
||||
from django.db import transaction
|
||||
from rest_framework.response import Response
|
||||
from django.shortcuts import render
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.exceptions import ParseError
|
||||
from rest_framework.mixins import DestroyModelMixin, UpdateModelMixin, ListModelMixin
|
||||
from rest_framework.mixins import DestroyModelMixin, ListModelMixin, UpdateModelMixin
|
||||
from rest_framework.response import Response
|
||||
|
||||
from apps.utils.viewsets import CustomGenericViewSet, CustomModelViewSet
|
||||
from apps.wpm.models import SfLog, StLog, SfLogExp
|
||||
from apps.wpm.serializers import SfLogSerializer, StLogSerializer, SflogExpSerializer
|
||||
from apps.wpm.filters import SfLogFilter, SfLogExpFilter
|
||||
from apps.mtm.models import Material
|
||||
from apps.utils.viewsets import CustomGenericViewSet, CustomModelViewSet
|
||||
|
||||
from .filters import SfLogExpFilter, SfLogFilter
|
||||
from .models import SfLog, SfLogExp, StLog, WMaterial
|
||||
from .serializers import SflogExpSerializer, SfLogSerializer, StLogSerializer, WMaterialSerializer
|
||||
|
||||
# Create your views here.
|
||||
|
||||
|
||||
class StLogViewSet(ListModelMixin, CustomGenericViewSet):
|
||||
"""
|
||||
list:停机记录
|
||||
|
@ -51,16 +53,21 @@ class SfLogViewSet(UpdateModelMixin, ListModelMixin, DestroyModelMixin, CustomGe
|
|||
from apps.qm.models import QuaStat, TestItem
|
||||
from apps.qm.serializers import QuaStatSerializer
|
||||
obj = self.get_object()
|
||||
test_materials = Material.objects.filter(id__in=obj.mgroup.test_materials).order_by('sort', '-create_time')
|
||||
test_materials = Material.objects.filter(
|
||||
id__in=obj.mgroup.test_materials).order_by('sort', '-create_time')
|
||||
for material in test_materials:
|
||||
testitems = TestItem.objects.filter(id__in=material.testitems).order_by('sort', '-create_time')
|
||||
testitems = TestItem.objects.filter(
|
||||
id__in=material.testitems).order_by('sort', '-create_time')
|
||||
for testitem in testitems:
|
||||
params = {'material': material, 'testitem': testitem, 'sflog': obj}
|
||||
QuaStat.objects.get_or_create(**params, defaults={**params, **{'create_by': request.user, 'belong_dept': obj.mgroup.belong_dept}})
|
||||
qs = QuaStat.objects.filter(sflog=obj).order_by('material__sort', 'material__create_time', 'testitem__sort', 'testitem__create_time')
|
||||
params = {'material': material,
|
||||
'testitem': testitem, 'sflog': obj}
|
||||
QuaStat.objects.get_or_create(
|
||||
**params, defaults={**params, **{'create_by': request.user, 'belong_dept': obj.mgroup.belong_dept}})
|
||||
qs = QuaStat.objects.filter(sflog=obj).order_by(
|
||||
'material__sort', 'material__create_time', 'testitem__sort', 'testitem__create_time')
|
||||
sr = QuaStatSerializer(instance=qs, many=True)
|
||||
return Response(sr.data)
|
||||
|
||||
|
||||
|
||||
class SfLogExpViewSet(CustomModelViewSet):
|
||||
"""
|
||||
|
@ -71,4 +78,18 @@ class SfLogExpViewSet(CustomModelViewSet):
|
|||
queryset = SfLogExp.objects.all()
|
||||
serializer_class = SflogExpSerializer
|
||||
select_related_fields = ['sflog', 'sflog__mgroup', 'stlog']
|
||||
filterset_class = SfLogExpFilter
|
||||
filterset_class = SfLogExpFilter
|
||||
|
||||
|
||||
class WMaterialViewSet(ListModelMixin, CustomGenericViewSet):
|
||||
"""
|
||||
list: 车间库存
|
||||
|
||||
车间库存
|
||||
"""
|
||||
queryset = WMaterial.objects.all()
|
||||
serializer_class = WMaterialSerializer
|
||||
select_related_fields = ['material', 'belong_dept']
|
||||
search_fields = ['material__name',
|
||||
'material__number', 'material__specification']
|
||||
filterset_fields = ['material', 'belong_dept']
|
||||
|
|
Loading…
Reference in New Issue