Merge branch 'master' of http://gitea.xxhhcty.xyz:8080/zcdsj/factory
This commit is contained in:
commit
3ca7a2b539
|
|
@ -1,45 +0,0 @@
|
|||
from .models import MaterialBatch, MIOItem
|
||||
from apps.mtm.models import Material, Mgroup
|
||||
from apps.system.models import Dept
|
||||
from rest_framework.exceptions import ParseError
|
||||
from django.db.models import F, Sum
|
||||
from django.db import transaction
|
||||
from .services import InmService
|
||||
|
||||
def correct_material_batch():
|
||||
"""矫正物料批次
|
||||
"""
|
||||
mgroups = Mgroup.objects.all()
|
||||
p_dict = {}
|
||||
for mgroup in mgroups:
|
||||
if mgroup.process:
|
||||
processId = mgroup.process.id
|
||||
dept: Dept = mgroup.belong_dept
|
||||
if processId not in p_dict:
|
||||
p_dict[processId] = dept
|
||||
else:
|
||||
raise ParseError('存在多个同工序的工段:{}'.format(mgroup.name))
|
||||
mbs = MaterialBatch.objects.filter(material__type__in=[Material.MA_TYPE_GOOD, Material.MA_TYPE_HALFGOOD],
|
||||
production_dept=None)
|
||||
for mb in mbs:
|
||||
if mb.material.process:
|
||||
processId = mb.material.process.id
|
||||
mb.production_dept = p_dict[processId]
|
||||
mb.save()
|
||||
|
||||
|
||||
def correct_mb_count_notok():
|
||||
"""矫正因count_notok未记录导致的错误数据
|
||||
"""
|
||||
mis = MIOItem.objects.filter(mio__state=20, count_notok=0).exclude(
|
||||
test_date=None,
|
||||
count_notok=F('count_n_zw') + F('count_n_tw') + F('count_n_qp') + F('count_n_wq') + F('count_n_dl') + F('count_n_pb') + F('count_n_dxt') + F('count_n_js') + F('count_n_qx') + F('count_n_zz') + F('count_n_ysq') + F('count_n_hs') + F('count_n_b') + F('count_n_qt')
|
||||
)
|
||||
for mi in mis:
|
||||
count_notok = mi.count_n_zw + mi.count_n_tw + mi.count_n_qp + mi.count_n_wq + mi.count_n_dl + mi.count_n_pb + mi.count_n_dxt + mi.count_n_js + mi.count_n_qx + mi.count_n_zz + mi.count_n_ysq + mi.count_n_hs + mi.count_n_b + mi.count_n_qt
|
||||
# 先处理库存
|
||||
try:
|
||||
MIOItem.objects.filter(id=mi.id).update(count_notok=count_notok)
|
||||
InmService.update_mb_after_test(mi)
|
||||
except ParseError as e:
|
||||
MIOItem.objects.filter(id=mi.id).update(test_date=None)
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
# Generated by Django 3.2.12 on 2025-11-06 15:38
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('mtm', '0062_auto_20250902_1122'),
|
||||
('inm', '0036_mioitem_pack_index'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='materialbatch',
|
||||
name='material',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='mb_m', to='mtm.material', verbose_name='物料'),
|
||||
),
|
||||
]
|
||||
|
|
@ -25,7 +25,7 @@ class MaterialBatch(BaseModel):
|
|||
batch = models.TextField('批次号', db_index=True)
|
||||
state = models.PositiveSmallIntegerField('状态', default=10, choices=((10, '合格'), (20, '不合格'), (30, '返修'), (40, '检验'), (50, '报废')))
|
||||
material = models.ForeignKey(
|
||||
Material, on_delete=models.CASCADE, verbose_name='物料')
|
||||
Material, on_delete=models.CASCADE, verbose_name='物料', related_name="mb_m")
|
||||
warehouse = models.ForeignKey(
|
||||
WareHouse, on_delete=models.CASCADE, verbose_name='所在仓库')
|
||||
count = models.DecimalField('存量', max_digits=12, decimal_places=3, default=0)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ from apps.inm.models import (MIO, MIOItem,
|
|||
MIOItemA, MIOItemw)
|
||||
from rest_framework.exceptions import ParseError
|
||||
from apps.mtm.models import Material
|
||||
from apps.mtm.services_2 import cal_material_count
|
||||
from apps.wpm.models import WMaterial, BatchSt, BatchLog
|
||||
from apps.wpm.services_2 import ana_batch_thread
|
||||
from apps.wpmw.models import Wpr
|
||||
|
|
@ -268,16 +267,6 @@ def do_in(item: MIOItem):
|
|||
|
||||
class InmService:
|
||||
|
||||
@classmethod
|
||||
def update_material_count(cls, instance: MIO):
|
||||
"""
|
||||
更新物料数量
|
||||
"""
|
||||
# 统计物料数量
|
||||
m_ids = list(MIOItem.objects.filter(mio=instance).values_list('material_id', flat=True))
|
||||
m_ids2 = list(MIOItemA.objects.filter(mioitem__mio=instance).values_list('material_id', flat=True))
|
||||
cal_material_count(m_ids+m_ids2)
|
||||
|
||||
@classmethod
|
||||
def update_inm(cls, instance: MIO, is_reverse: bool = False):
|
||||
"""
|
||||
|
|
@ -484,3 +473,4 @@ class InmService:
|
|||
mioitem.delete()
|
||||
else:
|
||||
raise ParseError("不支持该出入库单明细撤销")
|
||||
|
||||
|
|
@ -2,7 +2,6 @@ from rest_framework.exceptions import ParseError
|
|||
from apps.mtm.models import Process, Material
|
||||
from apps.inm.models import WareHouse, MaterialBatch, MIOItem, MIOItemw, MIO
|
||||
from apps.utils.tools import ranstr
|
||||
from apps.mtm.services_2 import cal_material_count
|
||||
|
||||
def daoru_mb(path: str):
|
||||
"""
|
||||
|
|
@ -59,7 +58,6 @@ def daoru_mb(path: str):
|
|||
MaterialBatch.objects.get_or_create(
|
||||
material=material, batch=batch, warehouse=warehouse, defaults={"material": material, "batch": batch, "warehouse": warehouse, "count": count, "id": idWorker.get_id()}
|
||||
)
|
||||
cal_material_count([material.id])
|
||||
i = i + 1
|
||||
|
||||
def daoru_mioitem_test(path:str, mioitem:MIOItem):
|
||||
|
|
|
|||
|
|
@ -223,7 +223,6 @@ class MIOViewSet(CustomModelViewSet):
|
|||
ins.state = MIO.MIO_SUBMITED
|
||||
ins.save()
|
||||
InmService.update_inm(ins)
|
||||
InmService.update_material_count(ins)
|
||||
return Response(MIOListSerializer(instance=ins).data)
|
||||
|
||||
@action(methods=['post'], detail=True, perms_map={'post': 'mio.submit'}, serializer_class=serializers.Serializer)
|
||||
|
|
@ -245,7 +244,6 @@ class MIOViewSet(CustomModelViewSet):
|
|||
ins.submit_time = None
|
||||
ins.save()
|
||||
InmService.update_inm(ins, is_reverse=True)
|
||||
InmService.update_material_count(ins)
|
||||
return Response()
|
||||
|
||||
|
||||
|
|
@ -408,7 +406,6 @@ class MIOItemViewSet(CustomListModelMixin, BulkCreateModelMixin, BulkDestroyMode
|
|||
sr.save()
|
||||
# 开始变动库存
|
||||
InmService.update_mb_item(ins, -1, 'count_notok')
|
||||
InmService.update_material_count(ins.mio)
|
||||
return Response()
|
||||
|
||||
@action(methods=['post'], detail=True, perms_map={'post': 'mioitem.test'}, serializer_class=serializers.Serializer)
|
||||
|
|
@ -426,7 +423,6 @@ class MIOItemViewSet(CustomListModelMixin, BulkCreateModelMixin, BulkDestroyMode
|
|||
pass
|
||||
ins.test_date = None
|
||||
ins.save()
|
||||
InmService.update_material_count(ins.mio)
|
||||
return Response()
|
||||
|
||||
@action(methods=['post'], detail=True, perms_map={'post': 'mioitem.test'}, serializer_class=MIOItemPurInTestSerializer)
|
||||
|
|
@ -444,7 +440,6 @@ class MIOItemViewSet(CustomListModelMixin, BulkCreateModelMixin, BulkDestroyMode
|
|||
sr = MIOItemPurInTestSerializer(instance=ins, data=request.data)
|
||||
sr.is_valid(raise_exception=True)
|
||||
sr.save()
|
||||
InmService.update_material_count(ins.mio)
|
||||
return Response()
|
||||
|
||||
@action(methods=['post'], detail=False, perms_map={'post': '*'}, serializer_class=MioItemAnaSerializer)
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ class MaterialFilter(filters.FilterSet):
|
|||
"orderitem_material__order": ['exact'],
|
||||
"pu_orderitem_material__pu_order": ["exact"],
|
||||
"route_material_out__mgroup": ["exact"],
|
||||
"count": ["gte", "lte", "exact", "gt", "lt"],
|
||||
"count_safe": ["gte", "lte", "exact", "gt", "lt"]
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
# Generated by Django 3.2.12 on 2025-11-06 15:39
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('mtm', '0062_auto_20250902_1122'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='material',
|
||||
name='count',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='material',
|
||||
name='count_mb',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='material',
|
||||
name='count_wm',
|
||||
),
|
||||
]
|
||||
|
|
@ -93,9 +93,9 @@ class Material(CommonAModel):
|
|||
tracking = models.PositiveSmallIntegerField("追踪方式", default=10,
|
||||
choices=((MA_TRACKING_BATCH, '批次'),
|
||||
(MA_TRACKING_SINGLE, '单件')))
|
||||
count = models.DecimalField('总库存', max_digits=14, decimal_places=3, default=0)
|
||||
count_mb = models.DecimalField('仓库库存', max_digits=14, decimal_places=3, default=0)
|
||||
count_wm = models.DecimalField('车间库存', max_digits=14, decimal_places=3, default=0)
|
||||
# count = models.DecimalField('总库存', max_digits=14, decimal_places=3, default=0)
|
||||
# count_mb = models.DecimalField('仓库库存', max_digits=14, decimal_places=3, default=0)
|
||||
# count_wm = models.DecimalField('车间库存', max_digits=14, decimal_places=3, default=0)
|
||||
count_safe = models.DecimalField('安全库存数', max_digits=14, decimal_places=3, null=True, blank=True)
|
||||
week_esitimate_consume = models.DecimalField('周消耗预估', max_digits=14, decimal_places=3, null=True, blank=True)
|
||||
process = models.ForeignKey(
|
||||
|
|
|
|||
|
|
@ -33,6 +33,18 @@ class MaterialSimpleSerializer(CustomModelSerializer):
|
|||
class MaterialSerializer(CustomModelSerializer):
|
||||
process_name = serializers.CharField(source='process.name', read_only=True)
|
||||
full_name = serializers.SerializerMethodField()
|
||||
count_mb = serializers.SerializerMethodField()
|
||||
count_wm = serializers.SerializerMethodField()
|
||||
count = serializers.SerializerMethodField()
|
||||
|
||||
def get_count_mb(self, obj):
|
||||
return getattr(obj, 'count_mb', 0)
|
||||
|
||||
def get_count_wm(self, obj):
|
||||
return getattr(obj, 'count_wm', 0)
|
||||
|
||||
def get_count(self, obj):
|
||||
return getattr(obj, 'count_mb', 0) + getattr(obj, 'count_wm', 0)
|
||||
|
||||
class Meta:
|
||||
model = Material
|
||||
|
|
|
|||
|
|
@ -4,24 +4,24 @@ from django.db.models import Sum
|
|||
from apps.inm.models import MaterialBatch
|
||||
from apps.wpm.models import WMaterial
|
||||
|
||||
def cal_material_count(materialId_list: List[str]=None):
|
||||
"""
|
||||
计算物料总数量
|
||||
"""
|
||||
if materialId_list is None:
|
||||
materialId_list = []
|
||||
if materialId_list:
|
||||
objs = Material.objects.filter(id__in=set(materialId_list))
|
||||
else:
|
||||
objs = Material.objects.all()
|
||||
for material in objs:
|
||||
mb_count = MaterialBatch.objects.filter(material=material, state=10).aggregate(total=Sum("count"))["total"] or 0
|
||||
wm_count = WMaterial.objects.filter(material=material, state=10).aggregate(total=Sum("count"))["total"] or 0
|
||||
if mb_count is None:
|
||||
mb_count = 0
|
||||
if wm_count is None:
|
||||
wm_count = 0
|
||||
Material.objects.filter(id=material.id).update(
|
||||
count_wm=wm_count,
|
||||
count_mb=mb_count,
|
||||
count=mb_count + wm_count)
|
||||
# def cal_material_count(materialId_list: List[str]=None):
|
||||
# """
|
||||
# 计算物料总数量
|
||||
# """
|
||||
# if materialId_list is None:
|
||||
# materialId_list = []
|
||||
# if materialId_list:
|
||||
# objs = Material.objects.filter(id__in=set(materialId_list))
|
||||
# else:
|
||||
# objs = Material.objects.all()
|
||||
# for material in objs:
|
||||
# mb_count = MaterialBatch.objects.filter(material=material, state=10).aggregate(total=Sum("count"))["total"] or 0
|
||||
# wm_count = WMaterial.objects.filter(material=material, state=10).aggregate(total=Sum("count"))["total"] or 0
|
||||
# if mb_count is None:
|
||||
# mb_count = 0
|
||||
# if wm_count is None:
|
||||
# wm_count = 0
|
||||
# Material.objects.filter(id=material.id).update(
|
||||
# count_wm=wm_count,
|
||||
# count_mb=mb_count,
|
||||
# count=mb_count + wm_count)
|
||||
|
|
@ -17,12 +17,13 @@ from apps.utils.viewsets import CustomGenericViewSet, CustomModelViewSet
|
|||
from apps.utils.mixins import BulkCreateModelMixin, BulkDestroyModelMixin, CustomListModelMixin
|
||||
from rest_framework.serializers import Serializer
|
||||
from django.db import transaction
|
||||
from django.db.models import Q
|
||||
from apps.wf.models import Ticket
|
||||
from django.utils import timezone
|
||||
from rest_framework.permissions import IsAdminUser
|
||||
from apps.utils.export import export_excel
|
||||
from operator import itemgetter
|
||||
from django.db.models import Sum, Q, Value, F, ExpressionWrapper, DecimalField
|
||||
from django.db.models.functions import Coalesce
|
||||
|
||||
# Create your views here.
|
||||
class MaterialViewSet(CustomModelViewSet):
|
||||
|
|
@ -41,6 +42,28 @@ class MaterialViewSet(CustomModelViewSet):
|
|||
ordering_fields = ['name', 'model', 'specification',
|
||||
'type', 'process', 'process__sort', 'sort', 'id', 'number', 'create_time']
|
||||
|
||||
def get_queryset(self):
|
||||
qs = super().get_queryset()
|
||||
if self.action in ["list", "retrieve"]:
|
||||
return qs.annotate(
|
||||
count_wm=Coalesce(
|
||||
Sum('mb_m__count', filter=Q(mb_m__state=10)),
|
||||
Value(0),
|
||||
output_field=DecimalField()
|
||||
),
|
||||
count_mb=Coalesce(
|
||||
Sum('wm_m__count', filter=Q(wm_m__state=10)),
|
||||
Value(0),
|
||||
output_field=DecimalField()
|
||||
)
|
||||
).annotate(
|
||||
count=ExpressionWrapper(
|
||||
F('count_wm') + F('count_mb'),
|
||||
output_field=DecimalField()
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def perform_destroy(self, instance):
|
||||
from apps.inm.models import MaterialBatch
|
||||
if MaterialBatch.objects.filter(material=instance).exists():
|
||||
|
|
@ -60,18 +83,6 @@ class MaterialViewSet(CustomModelViewSet):
|
|||
daoru_material(settings.BASE_DIR + request.data.get('path', ''))
|
||||
return Response()
|
||||
|
||||
@action(methods=['post'], detail=True, serializer_class=Serializer, perms_map={'post': 'material.create'})
|
||||
@transaction.atomic
|
||||
def cal_count(self, request, *args, **kwargs):
|
||||
"""统计数量
|
||||
|
||||
统计数量
|
||||
"""
|
||||
ins = self.get_object()
|
||||
from apps.mtm.services_2 import cal_material_count
|
||||
cal_material_count([ins.id])
|
||||
return Response()
|
||||
|
||||
@action(methods=['put'], detail=True, serializer_class=Serializer, perms_map={'put': '*'})
|
||||
@transaction.atomic
|
||||
def set_week_esitimate_consume(self, request, *args, **kwargs):
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ from apps.pm.models import Mtask
|
|||
from apps.mtm.models import Mgroup, Shift, Material, Route, RoutePack, Team, Srule
|
||||
|
||||
from .models import SfLog, WMaterial, Mlog, Mlogb, Mlogbw, Handover, Handoverb, Handoverbw, MlogbDefect, BatchLog, BatchSt, MlogUser
|
||||
from apps.mtm.services_2 import cal_material_count
|
||||
from apps.wf.models import Ticket
|
||||
from apps.wf.services import WfService
|
||||
import logging
|
||||
|
|
@ -23,7 +22,6 @@ from ..qm.models import Defect, Ftest
|
|||
from django.db.models import Count, Q
|
||||
from apps.utils.tasks import ctask_run
|
||||
from apps.mtm.models import Process
|
||||
from apps.mtm.services_2 import cal_material_count
|
||||
from apps.utils.lock import lock_model_record_d_func
|
||||
|
||||
myLogger = logging.getLogger('log')
|
||||
|
|
@ -399,9 +397,6 @@ def mlog_submit(mlog: Mlog, user: User, now: Union[datetime.datetime, None]):
|
|||
# 更新任务进度
|
||||
cal_mtask_progress_from_mlog(mlog)
|
||||
|
||||
# 更新物料数量
|
||||
cal_material_count_from_mlog(mlog)
|
||||
|
||||
# 触发批次统计分析
|
||||
xbatches = list(Mlogb.objects.filter(mlog=mlog).values_list('batch', flat=True))
|
||||
ana_batch_thread(xbatchs=xbatches, mgroup=mlog.mgroup)
|
||||
|
|
@ -618,9 +613,6 @@ def mlog_revert(mlog: Mlog, user: User, now: Union[datetime.datetime, None]):
|
|||
# 更新任务进度
|
||||
cal_mtask_progress_from_mlog(mlog)
|
||||
|
||||
# 更新物料数量
|
||||
cal_material_count_from_mlog(mlog)
|
||||
|
||||
# 清除关系链
|
||||
BatchLog.clear(mlog=mlog)
|
||||
|
||||
|
|
@ -651,24 +643,6 @@ def cal_mtask_progress_from_mlog(mlog:Mlog):
|
|||
update_mtask(mtask, fill_way=mlog.fill_way)
|
||||
caled_mtask.append(mtask)
|
||||
|
||||
def cal_material_count_from_mlog(mlog: Mlog):
|
||||
"""
|
||||
更新mlog关联的物料数量(可单独执行)
|
||||
"""
|
||||
matid_list = []
|
||||
if mlog.material_in:
|
||||
matid_list.append(mlog.material_in.id)
|
||||
if mlog.material_out:
|
||||
matid_list.append(mlog.material_out.id)
|
||||
matid_list2 = Mlogb.objects.filter(mlog=mlog).values_list('material_in__id', 'material_out__id').distinct()
|
||||
for matid in matid_list2:
|
||||
if matid[0]:
|
||||
matid_list.append(matid[0])
|
||||
if matid[1]:
|
||||
matid_list.append(matid[1])
|
||||
matid_list = list(set(matid_list))
|
||||
cal_material_count(matid_list)
|
||||
|
||||
|
||||
def update_mtask(mtask: Mtask, fill_way: int = 10):
|
||||
mtask = Mtask.objects.get(id=mtask.id) # 防止并发修改获取最新的mtask
|
||||
|
|
@ -954,11 +928,6 @@ def handover_submit(handover:Handover, user: User, now: Union[datetime.datetime,
|
|||
handover.recive_user = user
|
||||
handover.save()
|
||||
|
||||
# 如果是改版交接需要触发统计数量
|
||||
if handover.type == Handover.H_CHANGE:
|
||||
mids.append(handover.material_changed.id)
|
||||
cal_material_count(mids)
|
||||
|
||||
ana_batch_thread(xbatchs=batches)
|
||||
|
||||
@lock_model_record_d_func(Handover)
|
||||
|
|
@ -1014,11 +983,6 @@ def handover_revert(handover:Handover, handler:User=None):
|
|||
# 删除追踪链
|
||||
BatchLog.clear(handover=handover)
|
||||
|
||||
# 如果是改版交接需要触发统计数量
|
||||
if handover.type == Handover.H_CHANGE:
|
||||
mids.append(handover.material_changed.id)
|
||||
cal_material_count(mids)
|
||||
|
||||
ana_batch_thread(xbatchs=xbatchs)
|
||||
|
||||
def mlog_submit_validate(ins: Mlog):
|
||||
|
|
|
|||
Loading…
Reference in New Issue