183 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			183 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			Python
		
	
	
	
from django.utils import timezone
 | 
						|
from typing import List
 | 
						|
 | 
						|
from django.db.models.expressions import F
 | 
						|
from apps.pm.models import ProductionPlan, SubProductionPlan, SubProductionProgress
 | 
						|
from apps.mtm.models import Material, Step, SubprodctionMaterial
 | 
						|
from apps.qm.models import TestRecord
 | 
						|
from apps.system.models import User
 | 
						|
from apps.wf.models import State, TicketFlow, Transition
 | 
						|
from apps.wpm.models import Operation, OperationMaterial, WProduct, WproductFlow, WprouctTicket
 | 
						|
from utils.tools import ranstr
 | 
						|
class WpmServies(object):
 | 
						|
 | 
						|
    @classmethod    
 | 
						|
    def get_next_step(cls, subproduction_plan:SubProductionPlan, nowstep:Step):
 | 
						|
        """
 | 
						|
        获取下一步骤
 | 
						|
        """
 | 
						|
        stepIds = [i['id'] for i in subproduction_plan.steps]
 | 
						|
        pindex = stepIds.index(nowstep.id)
 | 
						|
        if pindex + 1 < len(stepIds):
 | 
						|
            return Step.objects.get(pk=stepIds[pindex+1]), True
 | 
						|
        else:
 | 
						|
            return nowstep, False
 | 
						|
 | 
						|
    @classmethod
 | 
						|
    def get_subplans_queryset_from_wproducts(cls, wproducts:List):
 | 
						|
        """
 | 
						|
        通过半成品列表获取所属子计划
 | 
						|
        """
 | 
						|
        splans = SubProductionPlan.objects.filter(is_deleted=False, wproduct_subplan__in=wproducts)
 | 
						|
        return splans
 | 
						|
 | 
						|
    @classmethod
 | 
						|
    def get_subplans_queyset_from_step(cls, step:Step):
 | 
						|
        """
 | 
						|
        通过当前操作获取所有正在进行的子计划
 | 
						|
        """
 | 
						|
        splans = SubProductionPlan.objects.filter(is_deleted=False, 
 | 
						|
                subproduction__usedstep_subproduction__step=step, state=SubProductionPlan.SUBPLAN_STATE_WORKING)
 | 
						|
        return splans
 | 
						|
    
 | 
						|
    @classmethod
 | 
						|
    def update_wproduct_by_test(cls, test:TestRecord, user:User):
 | 
						|
        """
 | 
						|
        根据检验结果更新玻璃及相关状态
 | 
						|
        """
 | 
						|
        is_testok = test.is_testok
 | 
						|
        wproduct = test.wproduct
 | 
						|
        if is_testok:
 | 
						|
            if wproduct.act_state == WProduct.WPR_ACT_STATE_TORETEST: # 复检
 | 
						|
                wproduct.act_state = WProduct.WPR_ACT_STATE_DOWAIT
 | 
						|
 | 
						|
            elif wproduct.act_state == WProduct.WPR_ACT_STATE_TOTEST and wproduct.material.type == Material.MA_TYPE_GOOD: # 成品检验
 | 
						|
                wproduct.act_state = WProduct.WPR_ACT_STATE_TOFINALTEST 
 | 
						|
            else:
 | 
						|
                wproduct.act_state = WProduct.WPR_ACT_STATE_OK
 | 
						|
            if wproduct.number is None: # 产生半成品编号
 | 
						|
                wproduct.number = 'WP'+ranstr(7)
 | 
						|
 | 
						|
            # 去除ng_sign
 | 
						|
            if wproduct.ng_sign:
 | 
						|
                wt = WprouctTicket.objects.order_by('id').last() #取最后的工单
 | 
						|
                if wt.step.process == test.step.process:
 | 
						|
                    wproduct.ng_sign = None
 | 
						|
                    ticket = wt.ticket
 | 
						|
                    ticket_data = wt.ticket_data
 | 
						|
                    ticket_data['retest_result'] = 1
 | 
						|
                    ticket.update_by = user
 | 
						|
                    ticket.save()
 | 
						|
                    # 创建处理日志
 | 
						|
                    TicketFlow.objects.create(ticket=ticket, state=ticket.state, 
 | 
						|
                            participant_type=State.PARTICIPANT_TYPE_PERSONAL, 
 | 
						|
                            intervene_type=0,
 | 
						|
                            participant=user)
 | 
						|
        else:# 如果不合格
 | 
						|
            wproduct.act_state = WProduct.WPR_ACT_STATE_NOTOK
 | 
						|
            # 需要走不合格品审理的工单
 | 
						|
            # 如果已经是返工返修的产品
 | 
						|
            if wproduct.ng_sign:
 | 
						|
                wt = WprouctTicket.objects.order_by('id').last() #取最后的工单
 | 
						|
                if wt.step.process == test.step.process:
 | 
						|
                    ticket = wt.ticket
 | 
						|
                    ticket_data = wt.ticket_data
 | 
						|
                    ticket_data['retest_result'] = 0
 | 
						|
                    ticket.update_by = user
 | 
						|
                    ticket.save()
 | 
						|
                    # 创建处理日志
 | 
						|
                    TicketFlow.objects.create(ticket=ticket, state=ticket.state, 
 | 
						|
                            participant_type=State.PARTICIPANT_TYPE_PERSONAL, 
 | 
						|
                            intervene_type=0,
 | 
						|
                            participant=user)
 | 
						|
 | 
						|
        wproduct.update_by = user
 | 
						|
        wproduct.update_time = timezone.now()
 | 
						|
        wproduct.test = None
 | 
						|
        wproduct.save()
 | 
						|
        # 添加日志
 | 
						|
        cls.add_wproduct_flow_log(wproduct, 'test_ok' if is_testok else 'test_notok')
 | 
						|
        # 更新子计划相关进度
 | 
						|
        cls.update_subproduction_progress_main(sp=wproduct.subproduction_plan)
 | 
						|
        
 | 
						|
 | 
						|
    @classmethod
 | 
						|
    def update_subproduction_progress_main(cls, sp:SubProductionPlan):
 | 
						|
        """
 | 
						|
        根据产品变动日志更新生产进度
 | 
						|
        """
 | 
						|
        objs = WproductFlow.objects.filter(subproduction_plan=sp, is_lastlog=True)
 | 
						|
        count_ok = objs.filter(act_state__in=[WProduct.WPR_ACT_STATE_INM, 
 | 
						|
                    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_real = objs.exclude(act_state__in=[WProduct.WPR_ACT_STATE_TORETEST, 
 | 
						|
        WProduct.WPR_ACT_STATE_DOWAIT, WProduct.WPR_ACT_STATE_DOING]).count()
 | 
						|
        ins = SubProductionProgress.objects.filter(subproduction_plan=sp, 
 | 
						|
                is_main=True, type=SubprodctionMaterial.SUB_MA_TYPE_OUT).first()
 | 
						|
        if ins:
 | 
						|
            ins.count_ok = count_ok
 | 
						|
            ins.count_notok = count_notok
 | 
						|
            ins.count_real = count_real
 | 
						|
            ins.save()
 | 
						|
    
 | 
						|
    @classmethod
 | 
						|
    def update_plan_state_by_mtestok(cls, plan:ProductionPlan):
 | 
						|
        """
 | 
						|
        根据军检结果更新主计划状态
 | 
						|
        """
 | 
						|
        # 计算计划军检合格数并进行状态变更
 | 
						|
        count_mtestok = WProduct.objects.filter(material=plan.product, is_mtestok=True, is_deleted=False).count()
 | 
						|
        plan.count_mtestok = count_mtestok
 | 
						|
        if count_mtestok >= plan.count:
 | 
						|
            plan.state = ProductionPlan.PLAN_MTEST_DONE
 | 
						|
            plan.save()
 | 
						|
 | 
						|
    @classmethod
 | 
						|
    def add_wproduct_flow_log(cls, instance:WProduct, change_str:str=''):
 | 
						|
        """
 | 
						|
        创建产品变动日志
 | 
						|
        """
 | 
						|
        # update_fields = kwargs['update_fields']
 | 
						|
        WproductFlow.objects.filter(wproduct=instance, subproduction_plan=instance.subproduction_plan).update(is_lastlog=False)
 | 
						|
        ins = WproductFlow()
 | 
						|
        ins.wproduct = instance
 | 
						|
        for f in WproductFlow._meta.fields:
 | 
						|
            if f.name not in ['id', 'wproduct', 'is_lastlog']:
 | 
						|
                setattr(ins, f.name, getattr(instance, f.name, None))
 | 
						|
        ins.change_str = change_str
 | 
						|
        ins.save()
 | 
						|
    
 | 
						|
    @classmethod
 | 
						|
    def update_cutting_list_with_operation(cls, op:Operation):
 | 
						|
        """
 | 
						|
        根据车间操作更新下料清单
 | 
						|
        """
 | 
						|
        inputs = OperationMaterial.objects.filter(operation=op, type=SubprodctionMaterial.SUB_MA_TYPE_IN)
 | 
						|
        outputs = OperationMaterial.objects.filter(operation=op, type=SubprodctionMaterial.SUB_MA_TYPE_OUT)
 | 
						|
        for i in outputs:
 | 
						|
            if i.use_scrap: # 如果使用了边角料
 | 
						|
                i.count_cut = 0
 | 
						|
                i.from_material = SubprodctionMaterial.objects.filter(type=SubprodctionMaterial.SUB_MA_TYPE_IN,
 | 
						|
                    subproduction__subplan_subprod=i.subproduction_plan).first().material
 | 
						|
            else:
 | 
						|
                input_q = inputs.filter(subproduction_plan=i.subproduction_plan) # 同计划的消耗
 | 
						|
                i.from_material = input_q.first().material
 | 
						|
                count_cut = 0
 | 
						|
                from_batch = ''
 | 
						|
                for m in input_q:
 | 
						|
                    count_cut = count_cut + m.count
 | 
						|
                    if from_batch and m.batch:
 | 
						|
                        from_batch = from_batch + ';' + m.batch
 | 
						|
                    else:
 | 
						|
                        from_batch = m.batch
 | 
						|
                i.count_cut = count_cut
 | 
						|
                i.from_batch = from_batch
 | 
						|
            wpfs = WproductFlow.objects.filter(subproduction_plan=i.subproduction_plan, 
 | 
						|
                is_lastlog=True, coperation=op)# 筛选本次操作下子计划的产品日志
 | 
						|
            i.count_real = wpfs.count()
 | 
						|
            i.count_ok = wpfs.filter(scrap_reason=None).count()
 | 
						|
            i.count_qipao = wpfs.filter(scrap_reason=WProduct.SCRAP_REASON_QIPAO).count()
 | 
						|
            i.count_podian = wpfs.filter(scrap_reason=WProduct.SCRAP_REASON_PODIAN).count()
 | 
						|
            i.count_hua = wpfs.filter(scrap_reason=WProduct.SCRAP_REASON_HUA).count()
 | 
						|
            i.count_other = wpfs.filter(scrap_reason=WProduct.SCRAP_REASON_OTHER).count()
 | 
						|
            i.save() |