package nc.bs.ic.m4d.update;

import nc.bs.ic.general.insert.rule.before.CheckCliabilityValue;
import nc.bs.ic.general.rule.after.AtpAfterUpdate;
import nc.bs.ic.general.rule.before.CtplcustomeridCheck;
import nc.bs.ic.general.update.IUpdateBP;
import nc.bs.ic.general.update.rule.after.RewriteQCUpdateRule;
import nc.bs.ic.m4d.base.BPPlugInPoint;
import nc.bs.ic.m4d.base.MaterialOutCheckRule;
import nc.bs.ic.m4d.base.MaterialOutValueProcRule;
import nc.bs.ic.m4d.base.MaterialOutWarehouseAttriCheck;
import nc.bs.ic.m4d.base.PurchaseInDateCheck;
import nc.bs.ic.m4d.insert.rule.MaterialOutProjectRule;
import nc.bs.ic.m4d.update.rule.ReWriteSOUpdateRule;
import nc.bs.ic.m4d.update.rule.UpdReWritePIM;
import nc.bs.ic.m4d.update.rule.UpdateRewriteMMDP;
import nc.bs.ic.pub.base.ICCompareAroundProcesser;
import nc.bs.ic.pub.base.IUpdateRuleProvider;
import nc.bs.scmpub.rule.CrossRuleValidateRule;
import nc.bs.scmpub.rule.VOSagaFrozenValidateRule;
import nc.impl.pubapp.pattern.rule.processer.CompareAroundProcesser;
import nc.vo.ic.general.define.MetaNameConst;
import nc.vo.ic.m4d.entity.MaterialOutVO;

/**
 * <p>
 * <b>材料出库单修改BP：</b>
 * <ul>
 * <li>
 * </ul>
 * <p>
 * <p>
 *
 * @version 6.0
 * @since 6.0
 * @author chennn
 * @time 2010-4-19 上午09:56:22
 */
public class UpdateBP implements IUpdateBP<MaterialOutVO>,
        IUpdateRuleProvider<MaterialOutVO> {

    @Override
    public void addAfterRule(MaterialOutVO[] vos, MaterialOutVO[] originVOs,
                             CompareAroundProcesser<MaterialOutVO> processor) {
        /*
         * 放在现存量更新规则之后，因为回写销售订单，发货单时，如果出库数量等于订单数量，
         * 订单自动行关闭，行关闭会执行预留解除，导致现存量更新时，处理预留业务产生错误
         */
        ((ICCompareAroundProcesser<MaterialOutVO>) processor).addAfterRuleAt(
                new UpdRewriteWorkOrder(), AtpAfterUpdate.class);
        // processor.addAfterRule(new UpdRewriteWorkOrder());

        processor.addAfterRule(new UpdReWriteSapplyBillRule());// 回写出库申请单
        processor.addAfterRule(new UpdReWriteBuyingReqRule());// 回写物资需求申请

        // 回写资产的领用单
        processor.addAfterRule(new UpdRewriteRM());
        // 回写紧急放行单
        processor.addAfterRule(new RewriteQCUpdateRule<MaterialOutVO>());

        // 回写批次关联
        processor.addAfterRule(new UpdRewriteBacthJoin());

        //回写发货单
        processor.addAfterRule(new ReWriteSOUpdateRule());

        /*
         * 放在现存量更新规则之后，因为回写销售订单，发货单时，如果出库数量等于订单数量，
         * 订单自动行关闭，行关闭会执行预留解除，导致现存量更新时，处理预留业务产生错误
         */
        ((ICCompareAroundProcesser<MaterialOutVO>) processor).addAfterRuleAt(
                new UpdRewriteMMPAC(), AtpAfterUpdate.class);
        // 回写备料计划
        processor.addAfterRule(new UpdRewriteMMSFC());
        // 回写计划独立需求
        processor.addAfterRule(new UpdateRewriteMMDP());

        // 回写项目管理备料表，放在回写出库申请之前，为了解决以下问题：
        // 不能计算预占量的问题，根本原因是因为出库申请的行关闭状态导致。
        // 之前出库单先回写出库申请，再回写备料备料表，回写备料表时，项目管理要查询当前出库申请的行状态是否关闭，根据该状态计算预占量。
        // 这样就不能区分此状态是因为出库单保存回写的还是出库单保存前就是关闭的
        ((ICCompareAroundProcesser<MaterialOutVO>) processor).addAfterRuleAt(
                new UpdReWritePIM(), UpdReWriteSapplyBillRule.class);

//    ((ICCompareAroundProcesser<MaterialOutVO>) processor).replaceAfterRuleAt(
//        new UpdAfterEventRuleFor4D(), UpdateAfterEventRule.class);

    }

    @Override
    public void addBeforeRule(MaterialOutVO[] vos, MaterialOutVO[] originVOs,
                              CompareAroundProcesser<MaterialOutVO> processor) {

        //saga状态校验，材料出库既要校验表头也要校验表体
        processor.addBeforeRule(new VOSagaFrozenValidateRule<MaterialOutVO>(true));
        processor.addBeforeRule(new CtplcustomeridCheck<MaterialOutVO>());//表体“货主客户”与“寄存供应商”不能同时存在
        processor.addBeforeRule(new MaterialOutValueProcRule());
        processor.addBeforeRule(new MaterialOutCheckRule());
        // 利润中心校验规则
        processor.addBeforeRule(new CheckCliabilityValue<MaterialOutVO>(MetaNameConst.CIOLIABILITYOID,MetaNameConst.CLIABILITYOID));
        processor.addBeforeRule(new MaterialOutWarehouseAttriCheck());

        // 交叉校验规则
        processor.addBeforeRule(new CrossRuleValidateRule<MaterialOutVO>());
        // 材料出库参照采购入库业务日期校验
        processor.addBeforeRule(new PurchaseInDateCheck());

//    ((ICCompareAroundProcesser<MaterialOutVO>) processor).replaceBeforeRuleAt(
//        new UpdBeforeEventRuleFor4D(), UpdateBeforeEventRule.class);

        //2025年6月13日09点38分 -- 物料档案基本页签启用项目辅助属性+库存组织未启用项目，采购入库单保存时（包含接口导入）清除行项目，材料出库单保存时（包含接口导入）清除行项目
        processor.addBeforeRule(new MaterialOutProjectRule());
    }

    @Override
    public MaterialOutVO[] update(MaterialOutVO[] vos, MaterialOutVO[] originVOs) {
        M4DUpdateBPTempate<MaterialOutVO> updateBP =
                new M4DUpdateBPTempate<MaterialOutVO>(BPPlugInPoint.UpdateBP, this);
        return updateBP.update(vos, originVOs);
    }

}
