feat: 根据光芯需求对wpm做兼容性处理

This commit is contained in:
caoqianming 2024-07-01 10:07:57 +08:00
parent 3c52125440
commit d579a7358d
7 changed files with 256 additions and 105 deletions

View File

@ -0,0 +1,18 @@
# Generated by Django 3.2.12 on 2024-06-28 10:41
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('mtm', '0030_route_hour_work'),
]
operations = [
migrations.AddField(
model_name='process',
name='into_wm_mgroup',
field=models.BooleanField(default=False, verbose_name='交接到工段'),
),
]

View File

@ -8,12 +8,14 @@ class Process(CommonBModel):
""" """
工序 工序
""" """
name = models.CharField('工序名称', max_length=100) name = models.CharField('工序名称', max_length=100)
cate = models.CharField('大类', max_length=10, default='') cate = models.CharField('大类', max_length=10, default='')
sort = models.PositiveSmallIntegerField('排序', default=1) sort = models.PositiveSmallIntegerField('排序', default=1)
instruction = models.ForeignKey( instruction = models.ForeignKey(
File, verbose_name='指导书', on_delete=models.SET_NULL, null=True, blank=True) File, verbose_name='指导书', on_delete=models.SET_NULL, null=True, blank=True)
instruction_content = models.TextField('指导书内容', null=True, blank=True) instruction_content = models.TextField('指导书内容', null=True, blank=True)
into_wm_mgroup = models.BooleanField('交接到工段', default=False)
class Meta: class Meta:
verbose_name = '工序' verbose_name = '工序'

View File

@ -1,6 +1,5 @@
from django_filters import rest_framework as filters from django_filters import rest_framework as filters
from apps.wpm.models import SfLog, StLog, WMaterial, Mlog, Handover from apps.wpm.models import SfLog, StLog, WMaterial, Mlog, Handover
['mgroup', 'shift', 'team', 'leader', 'team__belong_dept']
class SfLogFilter(filters.FilterSet): class SfLogFilter(filters.FilterSet):
@ -41,11 +40,12 @@ class WMaterialFilter(filters.FilterSet):
"material__process__name": ["exact", "contains", "in"], "material__process__name": ["exact", "contains", "in"],
"belong_dept": ["exact"], "belong_dept": ["exact"],
"belong_dept__name": ["exact", "in"], "belong_dept__name": ["exact", "in"],
"batch": ["exact", "in"], "batch": ["exact", "contains"],
"mgroup": ["exact", "in"],
"mgroup__name": ["exact", "in"],
"count": ["gte", "lte", "exact"] "count": ["gte", "lte", "exact"]
} }
class MlogFilter(filters.FilterSet): class MlogFilter(filters.FilterSet):
class Meta: class Meta:
model = Mlog model = Mlog
@ -78,5 +78,8 @@ class HandoverFilter(filters.FilterSet):
"material__type": ["exact", "in"], "material__type": ["exact", "in"],
"submit_time": ["isnull"], "submit_time": ["isnull"],
"mlog": ["isnull"], "mlog": ["isnull"],
"send_mgroup": ["exact"] "send_mgroup": ["exact"],
"send_mgroup__name": ["exact"],
"recive_mgroup": ["exact"],
"recive_mgroup__name": ["exact"],
} }

View File

@ -0,0 +1,81 @@
# Generated by Django 3.2.12 on 2024-07-01 01:36
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('pm', '0018_mtask_hour_work'),
('mtm', '0031_process_into_wm_mgroup'),
('system', '0004_auto_20240605_1011'),
('wpm', '0049_auto_20240522_1447'),
]
operations = [
migrations.AddField(
model_name='handover',
name='recive_mgroup',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='handover_recive_mgroup', to='mtm.mgroup', verbose_name='接收工段'),
),
migrations.AddField(
model_name='mlog',
name='hour_work',
field=models.FloatField(blank=True, null=True, verbose_name='预计工时'),
),
migrations.AddField(
model_name='mlog',
name='work_end_time',
field=models.DateTimeField(blank=True, null=True, verbose_name='生产结束时间'),
),
migrations.AddField(
model_name='mlog',
name='work_start_time',
field=models.DateTimeField(blank=True, null=True, verbose_name='生产开始时间'),
),
migrations.AddField(
model_name='mlogb',
name='batch',
field=models.CharField(blank=True, max_length=50, null=True, verbose_name='批次号'),
),
migrations.AddField(
model_name='mlogb',
name='count_real',
field=models.PositiveIntegerField(default=0, verbose_name='实际生产数'),
),
migrations.AddField(
model_name='mlogb',
name='count_use',
field=models.PositiveIntegerField(default=0, verbose_name='领用数量'),
),
migrations.AddField(
model_name='mlogb',
name='material_in',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='mlogb_material_in', to='mtm.material', verbose_name='投入物料'),
),
migrations.AddField(
model_name='mlogb',
name='mtask',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='mlogb_mtask', to='pm.mtask', verbose_name='关联任务'),
),
migrations.AddField(
model_name='wmaterial',
name='mgroup',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='mtm.mgroup', verbose_name='所在工段'),
),
migrations.AlterField(
model_name='mlog',
name='handle_date',
field=models.DateField(blank=True, null=True, verbose_name='操作日期'),
),
migrations.AlterField(
model_name='mlogb',
name='material_out',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='mlogb_material_out', to='mtm.material', verbose_name='产物'),
),
migrations.AlterUniqueTogether(
name='wmaterial',
unique_together={('material', 'batch', 'belong_dept', 'mgroup')},
),
]

View File

@ -90,18 +90,23 @@ class WMaterial(CommonBDModel):
""" """
material = models.ForeignKey( material = models.ForeignKey(
Material, verbose_name='物料', on_delete=models.CASCADE) Material, verbose_name='物料', on_delete=models.CASCADE)
mgroup = models.ForeignKey(Mgroup, verbose_name='所在工段', on_delete=models.CASCADE, null=True, blank=True)
batch = models.CharField('批次号', max_length=50) batch = models.CharField('批次号', max_length=50)
count = models.PositiveIntegerField('当前数量', default=0) count = models.PositiveIntegerField('当前数量', default=0)
count_eweight = models.FloatField('单数重量', default=0) count_eweight = models.FloatField('单数重量', default=0)
class Meta: class Meta:
unique_together = ('material', 'batch', 'belong_dept') unique_together = ('material', 'batch', 'belong_dept', 'mgroup')
class Mlog(CommonADModel): class Mlog(CommonADModel):
""" """
生产日志 生产日志
""" """
# 变成父级的字段
work_start_time = models.DateTimeField('生产开始时间', null=True, blank=True)
work_end_time = models.DateTimeField('生产结束时间', null=True, blank=True)
hour_work = models.FloatField('预计工时', null=True, blank=True)
mtask = models.ForeignKey( mtask = models.ForeignKey(
Mtask, verbose_name='关联任务', on_delete=models.CASCADE, null=True, blank=True, related_name='mlog_mtask') Mtask, verbose_name='关联任务', on_delete=models.CASCADE, null=True, blank=True, related_name='mlog_mtask')
mgroup = models.ForeignKey( mgroup = models.ForeignKey(
@ -157,7 +162,7 @@ class Mlog(CommonADModel):
count_n_thhs = models.PositiveIntegerField('退火后碎', default=0) count_n_thhs = models.PositiveIntegerField('退火后碎', default=0)
count_n_qt = models.PositiveIntegerField('其他', default=0) count_n_qt = models.PositiveIntegerField('其他', default=0)
handle_date = models.DateField('操作日期') handle_date = models.DateField('操作日期', null=True, blank=True)
handle_user = models.ForeignKey( handle_user = models.ForeignKey(
User, verbose_name='操作人', on_delete=models.CASCADE, related_name='mlog_handle_user', null=True, blank=True) # 成型人 User, verbose_name='操作人', on_delete=models.CASCADE, related_name='mlog_handle_user', null=True, blank=True) # 成型人
handle_user_2 = models.ForeignKey( handle_user_2 = models.ForeignKey(
@ -168,7 +173,7 @@ class Mlog(CommonADModel):
User, verbose_name='班长', on_delete=models.CASCADE, null=True, blank=True, related_name='mlog_handle_leader') User, verbose_name='班长', on_delete=models.CASCADE, null=True, blank=True, related_name='mlog_handle_leader')
note = models.TextField('备注', default='', blank=True) note = models.TextField('备注', default='', blank=True)
material_outs = models.ManyToManyField( material_outs = models.ManyToManyField(
Material, verbose_name='多个产出', blank=True, through='wpm.mlogb', related_name='mlog_material_outs') Material, verbose_name='多个产出', blank=True, through='wpm.mlogb', related_name='mlog_material_outs', through_fields=('mlog', 'material_out'))
submit_time = models.DateTimeField('提交时间', null=True, blank=True) submit_time = models.DateTimeField('提交时间', null=True, blank=True)
submit_user = models.ForeignKey( submit_user = models.ForeignKey(
@ -176,7 +181,7 @@ class Mlog(CommonADModel):
@property @property
def mlogb(self): def mlogb(self):
return Mlogb.objects.filter(mlog=self) return Mlogb.objects.filter(mlog=self).exclude(material_out=None)
@property @property
def audit_ignore_fields(self): def audit_ignore_fields(self):
@ -187,8 +192,15 @@ class Mlog(CommonADModel):
class Mlogb(BaseModel): class Mlogb(BaseModel):
mlog = models.ForeignKey(Mlog, verbose_name='关联日志', mlog = models.ForeignKey(Mlog, verbose_name='关联日志',
on_delete=models.CASCADE, related_name='b_mlog') on_delete=models.CASCADE, related_name='b_mlog')
batch = models.CharField('批次号', max_length=50, null=True, blank=True)
mtask = models.ForeignKey(Mtask, verbose_name='关联任务',
on_delete=models.CASCADE, related_name='mlogb_mtask', null=True, blank=True)
material_in = models.ForeignKey(
Material, verbose_name='投入物料', on_delete=models.CASCADE, related_name='mlogb_material_in', null=True, blank=True)
material_out = models.ForeignKey( material_out = models.ForeignKey(
Material, verbose_name='产物', on_delete=models.CASCADE, related_name='mlogb_material_out') Material, verbose_name='产物', on_delete=models.CASCADE, related_name='mlogb_material_out', null=True, blank=True)
count_use = models.PositiveIntegerField('领用数量', default=0)
count_real = models.PositiveIntegerField('实际生产数', default=0)
count_ok = models.PositiveIntegerField('合格数量', default=0) count_ok = models.PositiveIntegerField('合格数量', default=0)
@ -200,8 +212,7 @@ class Handover(CommonADModel):
send_user = models.ForeignKey( send_user = models.ForeignKey(
User, verbose_name='交送人', on_delete=models.CASCADE, related_name='handover_send_user') User, verbose_name='交送人', on_delete=models.CASCADE, related_name='handover_send_user')
send_mgroup = models.ForeignKey( send_mgroup = models.ForeignKey(
Mgroup, verbose_name='送料工段', on_delete=models.CASCADE, null=True, blank=True Mgroup, verbose_name='送料工段', on_delete=models.CASCADE, null=True, blank=True)
)
send_dept = models.ForeignKey( send_dept = models.ForeignKey(
Dept, verbose_name='送料部门', on_delete=models.CASCADE, related_name='handover_send_dept') Dept, verbose_name='送料部门', on_delete=models.CASCADE, related_name='handover_send_dept')
batch = models.CharField('批次号', max_length=50) batch = models.CharField('批次号', max_length=50)
@ -211,6 +222,7 @@ class Handover(CommonADModel):
count_eweight = models.FloatField('单数重量', default=0) count_eweight = models.FloatField('单数重量', default=0)
recive_dept = models.ForeignKey( recive_dept = models.ForeignKey(
Dept, verbose_name='接收部门', on_delete=models.CASCADE, related_name='handover_recive_dept') Dept, verbose_name='接收部门', on_delete=models.CASCADE, related_name='handover_recive_dept')
recive_mgroup = models.ForeignKey(Mgroup, verbose_name='接收工段', on_delete=models.CASCADE, related_name='handover_recive_mgroup', null=True, blank=True)
recive_user = models.ForeignKey( recive_user = models.ForeignKey(
User, verbose_name='接收人', on_delete=models.CASCADE, related_name='handover_recive_user') User, verbose_name='接收人', on_delete=models.CASCADE, related_name='handover_recive_user')
wm = models.ForeignKey(WMaterial, verbose_name='关联车间库存', on_delete=models.SET_NULL, wm = models.ForeignKey(WMaterial, verbose_name='关联车间库存', on_delete=models.SET_NULL,

View File

@ -1,4 +1,4 @@
from apps.utils.constants import EXCLUDE_FIELDS from apps.utils.constants import EXCLUDE_FIELDS, EXCLUDE_FIELDS_BASE
from apps.utils.serializers import CustomModelSerializer from apps.utils.serializers import CustomModelSerializer
from rest_framework import serializers from rest_framework import serializers
from rest_framework.exceptions import ValidationError, ParseError from rest_framework.exceptions import ValidationError, ParseError
@ -169,6 +169,7 @@ class WMaterialSerializer(CustomModelSerializer):
material_ = MaterialSimpleSerializer(source='material', read_only=True) material_ = MaterialSimpleSerializer(source='material', read_only=True)
material_name = serializers.StringRelatedField( material_name = serializers.StringRelatedField(
source='material', read_only=True) source='material', read_only=True)
mgroup_name = serializers.StringRelatedField(source='mgroup.name', read_only=True)
belong_dept_name = serializers.CharField( belong_dept_name = serializers.CharField(
source='belong_dept.name', read_only=True) source='belong_dept.name', read_only=True)
@ -187,7 +188,8 @@ class MlogbSerializer(CustomModelSerializer):
model = Mlogb model = Mlogb
fields = ['id', 'material_out', 'count_ok', fields = ['id', 'material_out', 'count_ok',
'material_out_', 'material_out_name'] 'material_out_', 'material_out_name']
extra_kwargs = {
'material_out': {'required': True, 'allow_null': False}}
class MlogSerializer(CustomModelSerializer): class MlogSerializer(CustomModelSerializer):
belong_dept = serializers.CharField( belong_dept = serializers.CharField(
@ -244,38 +246,27 @@ class MlogSerializer(CustomModelSerializer):
def create(self, validated_data): def create(self, validated_data):
mtask: Mtask = validated_data.get('mtask', None) mtask: Mtask = validated_data.get('mtask', None)
# batch = validated_data['batch']
# handle_date = validated_data['handle_date']
# handle_user = validated_data.get('handle_user', None)
if mtask: if mtask:
validated_data['mgroup'] = mtask.mgroup validated_data['mgroup'] = mtask.mgroup
validated_data['material_in'] = mtask.material_in validated_data['material_in'] = mtask.material_in
material_out = mtask.material_out material_out = mtask.material_out
validated_data['material_out'] = material_out validated_data['material_out'] = material_out
validated_data['handle_date'] = mtask.start_date validated_data['handle_date'] = mtask.end_date
# if not WMaterial.objects.filter(batch=batch).exists():
# raise ValidationError('批次号不存在')
else: else:
mgroup = validated_data['mgroup'] mgroup = validated_data['mgroup']
material_out = validated_data['material_out'] material_out = validated_data['material_out']
if not (mgroup and material_out): if not (mgroup and material_out):
raise ValidationError('缺少工段或产物!') raise ValidationError('缺少工段或产物!')
# if handle_user:
# if Mlog.objects.filter(mtask=mtask, batch=batch, handle_date=handle_date, handle_user=handle_user).exists():
# raise ValidationError('存在相同的日志记录')
# else:
# if Mlog.objects.filter(mtask=mtask, batch=batch, handle_date=handle_date).exists():
# raise ValidationError('存在相同的日志记录')
with transaction.atomic(): with transaction.atomic():
mlogb = validated_data.pop('mlogb', []) mlogb = validated_data.pop('mlogb', [])
instance = super().create(validated_data) instance: Mlog = super().create(validated_data)
brotherId_should_list = material_out.brothers brotherId_should_list = material_out.brothers
if brotherId_should_list: if brotherId_should_list:
if mlogb: if mlogb:
for item in mlogb: for item in mlogb:
if item['material_out'].id in brotherId_should_list: if item['material_out'].id in brotherId_should_list:
Mlogb.objects.create( Mlogb.objects.create(
mlog=instance, material_out=item['material_out'], count_ok=item['count_ok']) mlog=instance, batch=instance.batch, mtask=instance.mtask, material_out=item['material_out'], count_ok=item['count_ok'])
else: else:
raise ValidationError('缺少产出物信息') raise ValidationError('缺少产出物信息')
return instance return instance
@ -290,7 +281,7 @@ class MlogSerializer(CustomModelSerializer):
mlogb = validated_data.pop('mlogb', []) mlogb = validated_data.pop('mlogb', [])
instance = super().update(instance, validated_data) instance = super().update(instance, validated_data)
if mlogb: if mlogb:
Mlogb.objects.filter(mlog=instance).update(count_ok=0) Mlogb.objects.filter(mlog=instance, material_out__isnull=False).update(count_ok=0)
for item in mlogb: for item in mlogb:
Mlogb.objects.filter(mlog=instance, material_out=item['material_out']).update( Mlogb.objects.filter(mlog=instance, material_out=item['material_out']).update(
count_ok=item['count_ok']) count_ok=item['count_ok'])
@ -332,10 +323,10 @@ class DeptBatchSerializer(serializers.Serializer):
class HandoverSerializer(CustomModelSerializer): class HandoverSerializer(CustomModelSerializer):
wm = serializers.PrimaryKeyRelatedField( # wm = serializers.PrimaryKeyRelatedField(
label='车间库存ID', queryset=WMaterial.objects.all()) # label='车间库存ID', queryset=WMaterial.objects.all())
material = serializers.PrimaryKeyRelatedField( # material = serializers.PrimaryKeyRelatedField(
required=True, label='物料ID', queryset=Material.objects.all()) # required=True, label='物料ID', queryset=Material.objects.all())
send_user_name = serializers.CharField( send_user_name = serializers.CharField(
source='send_user.name', read_only=True) source='send_user.name', read_only=True)
recive_user_name = serializers.CharField( recive_user_name = serializers.CharField(
@ -347,17 +338,26 @@ class HandoverSerializer(CustomModelSerializer):
source='material', read_only=True) source='material', read_only=True)
def validate(self, attrs): def validate(self, attrs):
if attrs.get('mlog', None): material: Material = attrs['material']
attrs['send_mgroup'] = attrs['mlog'].mgroup if material.process.into_wm_mgroup and 'recive_mgroup' not in attrs:
attrs['send_dept'] = attrs['mlog'].mgroup.belong_dept raise ValidationError('必须指定交接工段')
elif attrs.get('wm', None): if attrs.get('wm', None):
attrs['send_dept'] = attrs['wm'].belong_dept attrs['send_dept'] = attrs['wm'].belong_dept
return super().validate(attrs) attrs['send_mgroup'] = attrs['wm'].mgroup
if attrs.get('recive_mgroup', None):
attrs['recive_dept'] = attrs['recive_mgroup'].belong_dept
if 'recive_dept' not in attrs and 'recive_mgroup' not in attrs:
raise ValidationError('交送车间和交送工段必须有一个')
return attrs
class Meta: class Meta:
model = Handover model = Handover
fields = '__all__' fields = '__all__'
read_only_fields = EXCLUDE_FIELDS read_only_fields = EXCLUDE_FIELDS + ["batch", "material", "send_dept", "send_mgroup", "mlog"]
extra_kwargs = {
"wm": {"required": True},
"recive_mgroup": {"required": False}
}
class GenHandoverSerializer(serializers.Serializer): class GenHandoverSerializer(serializers.Serializer):

View File

@ -14,6 +14,7 @@ from apps.pm.models import Mtask
from apps.mtm.models import Mgroup, Shift, Material, Route from apps.mtm.models import Mgroup, Shift, Material, Route
from .models import SfLog, SfLogExp, WMaterial, Mlog, Mlogb, Handover from .models import SfLog, SfLogExp, WMaterial, Mlog, Mlogb, Handover
from apps.mtm.models import Process
def get_sflog(mgroup: Mgroup, happen_time: datetime): def get_sflog(mgroup: Mgroup, happen_time: datetime):
@ -89,7 +90,7 @@ def do_out(mio: MIO):
for item in mioitems: for item in mioitems:
# 用于混料的原料不与车间库存交互 # 用于混料的原料不与车间库存交互
material = item.material material = item.material
if material.type in [Material.MA_TYPE_MAINSO, Material.MA_TYPE_HELPSO]: if material.type in [Material.MA_TYPE_MAINSO, Material.MA_TYPE_HELPSO]: # hard code
continue continue
action_list = [] action_list = []
mias = MIOItemA.objects.filter(mioitem=item) mias = MIOItemA.objects.filter(mioitem=item)
@ -127,7 +128,7 @@ def do_in(mio: MIO):
for item in mioitems: for item in mioitems:
# 用于混料的原料不与车间库存交互 # 用于混料的原料不与车间库存交互
material = item.material material = item.material
if material.type in [Material.MA_TYPE_MAINSO, Material.MA_TYPE_HELPSO]: if material.type in [Material.MA_TYPE_MAINSO, Material.MA_TYPE_HELPSO]: # hard code
continue continue
action_list = [] action_list = []
mias = MIOItemA.objects.filter(mioitem=item) mias = MIOItemA.objects.filter(mioitem=item)
@ -169,48 +170,65 @@ def mlog_submit(mlog: Mlog, user: User, now: Union[datetime.datetime, None]):
now = timezone.now() now = timezone.now()
if now.date() < mlog.handle_date: if now.date() < mlog.handle_date:
raise ParseError('不可提交未来的日志') raise ParseError('不可提交未来的日志')
belong_dept = mlog.mgroup.belong_dept
mgroup = mlog.mgroup
belong_dept = mgroup.belong_dept
material_out = mlog.material_out material_out = mlog.material_out
material_in = mlog.material_in material_in = mlog.material_in
if material_in: # 需要进行车间库存管理 if material_in: # 需要进行车间库存管理
# 需要判断领用数是否合理 into_wm_mgroup = material_in.process.into_wm_mgroup
material_has_qs = WMaterial.objects.filter( m_ins = Mlogb.objects.filter(mlog=mlog, material_in__isnull=False)
batch=mlog.batch, material=material_in, belong_dept=belong_dept) if m_ins.exists():
count_x = material_has_qs.count() m_ins_list = [(mi.material_in, mi.batch, mi.count_use) for mi in m_ins.all()]
if count_x == 1:
material_has = material_has_qs.first()
elif count_x == 0:
raise ParseError(
f'{str(material_in)}-{mlog.batch}-批次库存不存在!')
else: else:
raise ParseError( m_ins_list = [(material_in, mlog.batch, mlog.count_use)]
f'{str(material_in)}-{mlog.batch}-存在多个相同批次!') for mi in m_ins_list:
if mlog.count_use > material_has.count: mi_ma, mi_batch, mi_count = mi
raise ParseError( # 需要判断领用数是否合理
f'{str(material_in)}-{mlog.batch}-该批次车间库存不足!') lookup = {'batch': mi_batch, 'material': mi_ma, 'mgroup': None}
else: if into_wm_mgroup:
material_has.count = material_has.count - mlog.count_use lookup['mgroup'] = mgroup
if material_has.count == 0:
material_has.delete()
else: else:
material_has.save() lookup['belong_dept'] = belong_dept
material_has_qs = WMaterial.objects.filter(**lookup)
count_x = material_has_qs.count()
if count_x == 1:
material_has = material_has_qs.first()
elif count_x == 0:
raise ParseError(
f'{str(mi_ma)}-{mi_batch}-批次库存不存在!')
else:
raise ParseError(
f'{str(mi_ma)}-{mi_batch}-存在多个相同批次!')
if mi_count > material_has.count:
raise ParseError(
f'{str(mi_ma)}-{mi_batch}-该批次车间库存不足!')
else:
material_has.count = material_has.count - mi_count
if material_has.count == 0:
material_has.delete()
else:
material_has.save()
if material_out: # 需要入车间库存 if material_out: # 需要入车间库存
# 有多个产物的情况 into_wm_mgroup = material_out.process.into_wm_mgroup
if material_out.brothers and Mlogb.objects.filter(mlog=mlog).exists(): m_outs = Mlogb.objects.filter(mlog=mlog, material_out__isnull=False)
for item in Mlogb.objects.filter(mlog=mlog): if m_outs.exists():
wmaterial, _ = WMaterial.objects.get_or_create(batch=mlog.batch, material=item.material_out, belong_dept=belong_dept, defaults={ m_outs_list = [(mo.material, mo.batch if mo.batch else mlog.batch, mo.count_ok, mlog.count_real_eweight) for mo in m_outs.all()]
'batch': mlog.batch, 'material': item.material_out, 'belong_dept': belong_dept
})
wmaterial.count = wmaterial.count + item.count_ok
if hasattr(item, 'count_real_eweight'):
wmaterial.count_eweight = item.count_real_eweight
wmaterial.save()
else: else:
wmaterial, _ = WMaterial.objects.get_or_create(batch=mlog.batch, material=material_out, belong_dept=belong_dept, defaults={ m_outs_list = [(material_out, mlog.batch, mlog.count_ok, mlog.count_real_eweight)]
'batch': mlog.batch, 'material': material_out, 'belong_dept': belong_dept
}) for mo in m_outs_list:
wmaterial.count = wmaterial.count + mlog.count_ok mo_ma, mo_batch, mo_count, mo_count_eweight = mo
wmaterial.count_eweight = mlog.count_real_eweight lookup = {'batch': mo_batch, 'material': mo_ma, 'mgroup': None}
if into_wm_mgroup:
lookup['mgroup'] = mgroup
else:
lookup['belong_dept'] = belong_dept
if mo_count > 0:
wmaterial, _ = WMaterial.objects.get_or_create(**lookup, defaults=lookup)
wmaterial.count = wmaterial.count + mo_count
wmaterial.count_eweight = mo_count_eweight
wmaterial.save() wmaterial.save()
mlog.submit_time = now mlog.submit_time = now
mlog.submit_user = user mlog.submit_user = user
@ -224,34 +242,48 @@ def mlog_revert(mlog: Mlog, user: User, now: Union[datetime.datetime, None]):
return return
if now is None: if now is None:
now = timezone.now() now = timezone.now()
belong_dept = mlog.mgroup.belong_dept
mgroup = mlog.mgroup
belong_dept = mgroup.belong_dept
material_out = mlog.material_out material_out = mlog.material_out
material_in = mlog.material_in material_in = mlog.material_in
if material_in: if material_in:
# 领用数退回 # 领用数退回
wmaterial, _ = WMaterial.objects.get_or_create(batch=mlog.batch, material=material_in, belong_dept=belong_dept, defaults={ into_wm_mgroup = material_in.process.into_wm_mgroup
'batch': mlog.batch, 'material': material_in, 'belong_dept': belong_dept}) m_ins = Mlogb.objects.filter(mlog=mlog, material_in__isnull=False)
wmaterial.count = wmaterial.count + mlog.count_use if m_ins.exists():
wmaterial.save() m_ins_list = [(mi.material_in, mi.batch, mi.count_use) for mi in m_ins.all()]
else:
m_ins_list = [(material_in, mlog.batch, mlog.count_use)]
for mi in m_ins_list:
mi_ma, mi_batch, mi_count = mi
lookup = {'batch': mi_batch, 'material': mi_ma, 'mgroup': None}
if into_wm_mgroup:
lookup['mgroup'] = mgroup
else:
lookup['belong_dept'] = belong_dept
wmaterial, _ = WMaterial.objects.get_or_create(**lookup, defaults=lookup)
wmaterial.count = wmaterial.count + mi_count
wmaterial.save()
if material_out: # 产物退回 if material_out: # 产物退回
# 有多个产物的情况 # 有多个产物的情况
if material_out.brothers and Mlogb.objects.filter(mlog=mlog).exists(): into_wm_mgroup = material_out.process.into_wm_mgroup
for item in Mlogb.objects.filter(mlog=mlog): m_outs = Mlogb.objects.filter(mlog=mlog, material_out__isnull=False)
wmaterial, _ = WMaterial.objects.get_or_create(batch=mlog.batch, material=item.material_out, belong_dept=belong_dept, defaults={ if m_outs.exists():
'batch': mlog.batch, 'material': item.material_out, 'belong_dept': belong_dept m_outs_list = [(mo.material, mo.batch if mo.batch else mlog.batch, mo.count_ok, mlog.count_real_eweight) for mo in m_outs.all()]
})
wmaterial.count = wmaterial.count - item.count_ok
if wmaterial.count < 0:
raise ParseError('车间库存不足, 产物无法回退')
elif wmaterial.count == 0:
wmaterial.delete()
else:
wmaterial.save()
else: else:
wmaterial, _ = WMaterial.objects.get_or_create(batch=mlog.batch, material=material_out, belong_dept=belong_dept, defaults={ m_outs_list = [(material_out, mlog.batch, mlog.count_ok, mlog.count_real_eweight)]
'batch': mlog.batch, 'material': material_out, 'belong_dept': belong_dept
}) for mo in m_outs_list:
wmaterial.count = wmaterial.count - mlog.count_ok mo_ma, mo_batch, mo_count, _ = mo
lookup = {'batch': mo_batch, 'material': mo_ma, 'mgroup': None}
if into_wm_mgroup:
lookup['mgroup'] = mgroup
else:
lookup['belong_dept'] = belong_dept
wmaterial, _ = WMaterial.objects.get_or_create(**lookup, defaults=lookup)
wmaterial.count = wmaterial.count - mo_count
if wmaterial.count < 0: if wmaterial.count < 0:
raise ParseError('车间库存不足, 产物无法回退') raise ParseError('车间库存不足, 产物无法回退')
elif wmaterial.count == 0: elif wmaterial.count == 0:
@ -296,11 +328,9 @@ def handover_submit(handover: Handover, user: User, now: Union[datetime.datetime
wm_from_need_delete = False wm_from_need_delete = False
material = handover.material material = handover.material
batch = handover.batch batch = handover.batch
try: wm_from = handover.wm
wm_from = WMaterial.objects.get( if wm_from is None:
material=material, batch=batch, belong_dept=handover.send_dept) raise ParseError('找不到车间库存')
except Exception as e:
raise ParseError(f'找不到车间库存:{e}')
if '混料' in material.name: # hard code if '混料' in material.name: # hard code
need_add = False need_add = False
count_x = wm_from.count - handover.count count_x = wm_from.count - handover.count
@ -312,9 +342,14 @@ def handover_submit(handover: Handover, user: User, now: Union[datetime.datetime
wm_from.count = count_x wm_from.count = count_x
wm_from.save() wm_from.save()
if need_add: if need_add:
wm_to, _ = WMaterial.objects.get_or_create(batch=batch, material=material, belong_dept=handover.recive_dept, defaults={ if handover.recive_mgroup:
'batch': batch, 'material': material, 'belong_dept': handover.recive_dept wm_to, _ = WMaterial.objects.get_or_create(batch=batch, material=material, mgroup=handover.recive_mgroup, defaults={
}) 'batch': batch, 'material': material, 'mgroup': handover.recive_mgroup, 'belong_dept': handover.recive_dept
})
else:
wm_to, _ = WMaterial.objects.get_or_create(batch=batch, material=material, belong_dept=handover.recive_dept, defaults={
'batch': batch, 'material': material, 'belong_dept': handover.recive_dept
})
wm_to.count = wm_to.count + handover.count wm_to.count = wm_to.count + handover.count
wm_to.count_eweight = handover.count_eweight wm_to.count_eweight = handover.count_eweight
wm_to.save() wm_to.save()