package yem.base.common.module.version.helper;

import kd.bos.dataentity.OperateOption;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.dataentity.metadata.IDataEntityProperty;
import kd.bos.dataentity.metadata.IDataEntityType;
import kd.bos.dataentity.metadata.ISimpleProperty;
import kd.bos.dataentity.metadata.clr.DataEntityPropertyCollection;
import kd.bos.dataentity.metadata.dynamicobject.DynamicLocaleProperty;
import kd.bos.dataentity.metadata.dynamicobject.DynamicObjectType;
import kd.bos.entity.operate.result.IOperateInfo;
import kd.bos.entity.operate.result.OperationResult;
import kd.bos.entity.property.BillTypeProp;
import kd.bos.entity.property.EntryProp;
import kd.bos.entity.property.MulBasedataProp;
import kd.bos.exception.KDBizException;
import kd.bos.mq.MQFactory;
import kd.bos.mq.MessagePublisher;
import kd.bos.orm.ORM;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.BusinessDataServiceHelper;
import kd.bos.servicehelper.QueryServiceHelper;
import kd.bos.servicehelper.operation.DeleteServiceHelper;
import kd.bos.servicehelper.operation.SaveServiceHelper;
import kd.bos.servicehelper.user.UserServiceHelper;
import yem.base.common.utils.DynamicObjectUtil;

import java.util.*;

/**
 * 版本变更帮助类
 *
 * @author longh
 * @description:
 * @date 2022年12月1日 下午4:50:18
 */
public class NewVersionHelper {
    public static final String KEY_REL = "yem_base_versionsrel";//【版本变更关联追踪表】单据标识-扩展开发库
    public static final String KEY_TPL = "yem_base_versionsetting";//【创建新版本方案维护】单据标识
    public static final String KEY_LIST = "yem_base_versionresume";//【变更履历】单据标识
    public static final Map<String, String> KEY_TPL_MAP = new HashMap<>();

    static {
        KEY_TPL_MAP.put(null, KEY_REL);
        KEY_TPL_MAP.put("secd", KEY_REL);
        KEY_TPL_MAP.put("scm", "yem_base_versionsrel_scm");
    }

    private boolean isChanged = false;
    private DynamicObject tplObj;
    private String requireKey;
    private String changeKey;

    public NewVersionHelper(String entityNumber) {
        tplObj = queryTemplate(entityNumber);
        if (tplObj != null) {
            requireKey = tplObj.getString("yem_requirebill.number");
            changeKey = tplObj.getString("yem_changebill.number");
            if (entityNumber.equals(changeKey)) {
                isChanged = true;
            }
        }
    }

/**
 * 根据实体编号查询相应的模板信息。
 * 该方法通过构建查询过滤条件，指定查询的字段，然后从缓存中加载模板数据。
 * 主要用于获取特定实体对应的模板配置信息，包括字段映射、检查映射、检查删除行和单据类型的配置。
 *
 * @param entityNumber 实体编号，用于精确匹配模板的实体要求或变更要求。
 * @return 返回查询结果，是一个DynamicObject对象，包含了根据实体编号查询到的模板配置信息。
 */
public static DynamicObject queryTemplate(String entityNumber) {
    // 构建查询过滤条件，只查询启用状态为1的模板
    QFilter qFilter = new QFilter("enable", QCP.equals, "1");
    // 添加过滤条件，查询实体要求编号或变更要求编号为指定实体编号的模板
    qFilter.and(new QFilter("yem_requirebill.number", QCP.equals, entityNumber)
            .or(new QFilter("yem_changebill.number", QCP.equals, entityNumber)));
    // 指定查询的字段，这里通过多次调用getEntrySelectfields方法，逐渐细化查询字段的配置
    String selectFields = DynamicObjectUtil.getSelectfields(KEY_TPL, false);
    selectFields = DynamicObjectUtil.getEntrySelectfields(selectFields, KEY_TPL, "yem_colsmap", false);
    selectFields = DynamicObjectUtil.getEntrySelectfields(selectFields, KEY_TPL, "yem_checkmap", false);
    selectFields = DynamicObjectUtil.getEntrySelectfields(selectFields, KEY_TPL, "yem_checkdelrow", false);
    selectFields = DynamicObjectUtil.getEntrySelectfields(selectFields, KEY_TPL, "yem_billtypes", false);
    // 从缓存中加载符合条件的模板数据
    return BusinessDataServiceHelper.loadSingleFromCache(KEY_TPL, selectFields, new QFilter[]{qFilter});
}

    /**
     * 构建返回持久化的变更单实体
     *
     * @param entityNumber
     * @param fromPkId
     * @return
     */
    public static DynamicObject newVersion(String entityNumber, Object fromPkId) {
        return newVersion(queryTemplate(entityNumber), fromPkId);
    }

    /**
     * 构建返回持久化的变更单实体
     *
     * @param tplObj
     * @param fromPkId
     * @return
     */
    public static DynamicObject newVersion(DynamicObject tplObj, Object fromPkId) {
        noSettings(tplObj);
        String fromKey = tplObj.getString("yem_requirebill.number");
        String toKey = tplObj.getString("yem_changebill.number");
        DynamicObject oldDataEntity = BusinessDataServiceHelper.loadSingle(fromPkId, fromKey);
        DynamicObject newDataEntity = BusinessDataServiceHelper.newDynamicObject(toKey);
        DynamicObjectUtil.copyDynamicObject(oldDataEntity, newDataEntity, 2, false, true, true);
        newDataEntity.set("billstatus", "A");
        newDataEntity.set("yem_masterid", fromPkId);
        //判断oldDataEntity.getInt("yem_version")是否为0，如果为零，则set为1.做个判断
        int vno = oldDataEntity.getInt("yem_version") == 0 ? 1 : oldDataEntity.getInt("yem_version") + 1;
        newDataEntity.set("yem_version", vno);
        newDataEntity.set("yem_effective", false);
        newDataEntity.set("billno", oldDataEntity.getString("billno").concat("_V").concat(String.valueOf(vno)));
        newDataEntity.set("yem_changeman", UserServiceHelper.getCurrentUser("name"));
        newDataEntity.set("yem_changedate", new Date());
        newDataEntity.set("yem_effector", null);
        newDataEntity.set("yem_effectdate", null);
        setBillTypes(newDataEntity, tplObj.getDynamicObjectCollection("yem_billtypes"), true);
//		SaveServiceHelper.save(new DynamicObject[] {newDataEntity});

        OperationResult result = SaveServiceHelper.saveOperate(toKey, new DynamicObject[]{newDataEntity}, OperateOption.create());
        checkResult(result, "变更单保存失败。", newDataEntity);
        matchVersions(oldDataEntity, newDataEntity, tplObj.getPkValue());
        oldDataEntity.set("yem_changing", true);
        SaveServiceHelper.update(oldDataEntity);
        attachmentSend(oldDataEntity, newDataEntity);
        return newDataEntity;
    }
    //真删除变更单的数据
public static void deleteAllChangesForMaster(DynamicObject tplObj, DynamicObject dataEntity) {
    String entityNumber = dataEntity.getDynamicObjectType().getName();
    String yem_requirebill = tplObj.getString("yem_requirebill.number");
    String yem_changebill = tplObj.getString("yem_changebill.number"); // 添加这行来获取变更单的表名
    long masterid = dataEntity.getLong("yem_masterid");

    if (masterid > 0 && entityNumber.equals(yem_requirebill)) {
        //根据主数据内码查出所有的变更单
        DynamicObject[] changeList = BusinessDataServiceHelper.load(yem_changebill,"id", new QFilter("yem_masterid", QCP.equals, masterid).toArray());
        for (DynamicObject change : changeList) {
            Long pkValue = (Long) change.getPkValue();
            DeleteServiceHelper.delete(yem_changebill,new QFilter("id",QCP.equals,pkValue).toArray());
        }

        // 初始化原单状态
        DynamicObject oldDataEntity = BusinessDataServiceHelper.loadSingle(masterid, yem_requirebill);
        if (oldDataEntity != null) {
            oldDataEntity.set("yem_changing", false); // 或者其他初始化逻辑
            oldDataEntity.set("yem_effective", false);//变更生效给成false
            oldDataEntity.set("yem_version", 1);//版本号设置成1
            oldDataEntity.set("yem_changeman", null);
            oldDataEntity.set("yem_changedate", null);
            oldDataEntity.set("yem_effector", null);
            oldDataEntity.set("yem_effectdate", null);
            SaveServiceHelper.update(oldDataEntity);
        }
    }
}

    /**
     * 变更单删除
     *
     * @param tplObj
     * @param dataEntity
     */
    public static void deleteChange(DynamicObject tplObj, DynamicObject dataEntity) {
        String entityNumber = dataEntity.getDynamicObjectType().getName();
        String yem_requirebill = tplObj.getString("yem_requirebill.number");
        String yem_changebill = tplObj.getString("yem_changebill.number");
        long masterid = dataEntity.getLong("yem_masterid");
        if (masterid > 0 && entityNumber.equals(yem_changebill)) {
            DynamicObject oldDataEntity = BusinessDataServiceHelper.loadSingle(masterid, yem_requirebill);
            oldDataEntity.set("yem_changing", false);
            SaveServiceHelper.update(oldDataEntity);
        }
    }

    /**
     * 变更单生效
     *
     * @param entityNumber
     * @param dataEntity
     */
    public static void effectChange(String entityNumber, DynamicObject dataEntity) {
        effectChange(queryTemplate(entityNumber), dataEntity);
    }

    /**
     * 变更单生效
     *
     * @param tplObj
     * @param dataEntity
     */
    public static void effectChange(DynamicObject tplObj, DynamicObject dataEntity) {
        noSettings(tplObj);
        String entityNumber = dataEntity.getDynamicObjectType().getName();
        String yem_requirebill = tplObj.getString("yem_requirebill.number");
        String yem_changebill = tplObj.getString("yem_changebill.number");
        dataEntity = BusinessDataServiceHelper.loadSingle(dataEntity.getPkValue(), yem_changebill);
        int vno = dataEntity.getInt("yem_version");
        long masterid = dataEntity.getLong("yem_masterid");
        if (masterid > 0 && entityNumber.equals(yem_changebill)) {
            DynamicObject oldDataEntity = BusinessDataServiceHelper.loadSingle(masterid, yem_requirebill);
            if (vno == 2) {//第一次变更要生成版本为一的变更单记录初版单据内容
                DynamicObject newDataEntity = BusinessDataServiceHelper.newDynamicObject(yem_changebill);
                DynamicObjectUtil.copyDynamicObject(oldDataEntity, newDataEntity, 2, false, true, true);
                newDataEntity.set("yem_version", 1);
                newDataEntity.set("yem_masterid", masterid);
                newDataEntity.set("billno", oldDataEntity.getString("billno").concat("_V1"));
                newDataEntity.set("yem_effective", true);
                setBillTypes(newDataEntity, tplObj.getDynamicObjectCollection("yem_billtypes"), true);
//				SaveServiceHelper.save(new DynamicObject[] {newDataEntity});
                OperationResult result1 = SaveServiceHelper.saveOperate(yem_changebill, new DynamicObject[]{newDataEntity}, OperateOption.create());
                checkResult(result1, "一版本变更单保存失败。", newDataEntity);
                matchVersions(oldDataEntity, newDataEntity, tplObj.getPkValue());
            }
            //查询关联表数据
            String dbRouteKey = oldDataEntity.getDynamicObjectType().getDBRouteKey();
            QFilter qFilter = new QFilter("yem_tplid", QCP.equals, tplObj.getPkValue());
            qFilter.and(new QFilter("yem_masterid", QCP.equals, oldDataEntity.getPkValue()));
            qFilter.and(new QFilter("yem_xmasterid", QCP.equals, dataEntity.getPkValue()));
            String selectFields = DynamicObjectUtil.getSelectfields(KEY_TPL_MAP.get(dbRouteKey), false);
            DynamicObject[] rels = BusinessDataServiceHelper.load(KEY_TPL_MAP.get(dbRouteKey), selectFields, new QFilter[]{qFilter});
            //根据关联表反写变更数据到源单
            dataEntity.set("yem_effector", UserServiceHelper.getCurrentUser("name"));
            dataEntity.set("yem_effectdate", new Date());
            dataEntity.set("yem_effective", true);

            List<DynamicObject> relObjList = new ArrayList<>();
            copyChange2SrcByVersionRelData(oldDataEntity, dataEntity, dataEntity, oldDataEntity, rels, relObjList, tplObj.getPkValue(),tplObj);
            if (relObjList.size() > 0) {
                SaveServiceHelper.save(relObjList.toArray(new DynamicObject[0]));
            }
            setBillTypes(oldDataEntity, tplObj.getDynamicObjectCollection("yem_billtypes"), false);
            attachmentSend(dataEntity, oldDataEntity);

//			SaveServiceHelper.save(new DynamicObject[] {dataEntity});
//			SaveServiceHelper.save(new DynamicObject[] {oldDataEntity});
            OperationResult result2 = SaveServiceHelper.saveOperate(yem_changebill, new DynamicObject[]{dataEntity}, OperateOption.create());
            checkResult(result2, "变更单生效保存失败。", dataEntity);
            OperationResult result3 = SaveServiceHelper.saveOperate(yem_requirebill, new DynamicObject[]{oldDataEntity}, OperateOption.create());
            checkResult(result3, "源单生效保存失败。", oldDataEntity);
        }
    }


    /**
     * 同步附件面板
     *
     * @param fromObj
     * @param toObj
     */
    public static void attachmentSend(DynamicObject fromObj, DynamicObject toObj) {
        if (fromObj != null && toObj != null && fromObj.getDataEntityType().getProperties().containsKey("yem_attachmentcon")) {
            MessagePublisher mp = MQFactory.get().createSimplePublisher("yem_wm", "yem_attachmentsend");
            try {
                Map<String, DynamicObject> map = new HashMap<>();
                map.put("from", fromObj);
                map.put("to", toObj);
                mp.publishInDbTranscation("secd", map);
            } finally {
                mp.close();
            }
        }
    }

    private static void noSettings(DynamicObject tplObj) {
        if (tplObj == null) {
            throw new KDBizException("未设置版本变更方案。");
        }
    }

    /**
     * 检验单据生成结果，失败则提示并抛出异常
     *
     * @param result
     * @param dataEntity
     */
    public static void checkResult(OperationResult result, String errMsgTitle, DynamicObject dataEntity) {
        if (!result.isSuccess()) {
            StringBuffer buffer = new StringBuffer(errMsgTitle);
            buffer.append("\r\n").append("Message:").append(result.getMessage()).append("\r\n").append("Details:");
            List<IOperateInfo> allErrorOrValidateInfo = result.getAllErrorOrValidateInfo();
            for (IOperateInfo iOperateInfo : allErrorOrValidateInfo) {
                buffer.append("\r\n");
                String message = iOperateInfo.getMessage();
                if (message.contains("正在PC端编辑该记录") || message.contains("当前单据已在其他页签中打开")) {
                    SaveServiceHelper.save(new DynamicObject[]{dataEntity});
                    return;
                }
                buffer.append(message);
            }
            throw new KDBizException(buffer.toString());
        }
    }

    /**
     * 变更单单据类型映射
     *
     * @param newDataEntity
     * @param yem_billtypes
     */
//    public static void setBillTypes(DynamicObject newDataEntity, DynamicObjectCollection yem_billtypes, boolean change) {
//        String fromBilltype = change ? "yem_srcbilltype" : "yem_changebilltype";//yem_srcbilltype元旦单据类型
//        String toBilltype = change ? "yem_changebilltype" : "yem_srcbilltype";
//        DataEntityPropertyCollection properties = newDataEntity.getDynamicObjectType().getProperties();
//        for (IDataEntityProperty property : properties) {
//            String name = property.getName();
//            //分录处理
//            if (property instanceof EntryProp) {
//                DynamicObjectCollection dyObjCollection = newDataEntity.getDynamicObjectCollection(name);
//                for (DynamicObject row : dyObjCollection) {
//                    setBillTypes(row, yem_billtypes, change);
//                }
//            }//字段处理
//            else if (property instanceof BillTypeProp) {
//                DynamicObject newBillType = null;
//                String billTypeId = newDataEntity.getDynamicObject(name) == null ? "" : newDataEntity.getDynamicObject(name).getPkValue().toString();
//                for (DynamicObject row : yem_billtypes) {
//                    DynamicObject yem_srcbilltype = row.getDynamicObject(fromBilltype);
//                    if (yem_srcbilltype != null && yem_srcbilltype.getString("id").equals(billTypeId)) {
//                        newBillType = row.getDynamicObject(toBilltype);
//                    }
//                }
//                newDataEntity.set(name, newBillType);
//            }
//        }
//    }

    public static void setBillTypes(DynamicObject newDataEntity, DynamicObjectCollection yem_billtypes, boolean isForwardChange) {
        // 根据变更方向确定当前处理的单据类型字段
        String fromBilltypeField = isForwardChange ? "yem_srcbilltype" : "yem_changebilltype";
        String toBilltypeField = isForwardChange ? "yem_changebilltype" : "yem_srcbilltype";

        // 获取动态对象的属性集合
        DataEntityPropertyCollection properties = newDataEntity.getDynamicObjectType().getProperties();
        for (IDataEntityProperty property : properties) {
            String name = property.getName();

            // 处理条目属性（这部分逻辑保持不变）
            if (property instanceof EntryProp) {
                DynamicObjectCollection dyObjCollection = newDataEntity.getDynamicObjectCollection(name);
                for (DynamicObject row : dyObjCollection) {
                    setBillTypes(row, yem_billtypes, isForwardChange);
                }
            }

            // 处理单据类型属性
            else if (property instanceof BillTypeProp) {
                DynamicObject newBillType = null;
                String billTypeId = newDataEntity.getDynamicObject(name) == null ? "" : newDataEntity.getDynamicObject(name).getPkValue().toString();

                // 正向变更逻辑：根据映射关系查找新的单据类型
                if (isForwardChange) {
                    for (DynamicObject row : yem_billtypes) {
                        DynamicObject srcBillType = row.getDynamicObject(fromBilltypeField);
                        if (srcBillType != null && srcBillType.getString("id").equals(billTypeId)) {
                            newBillType = row.getDynamicObject(toBilltypeField);
                            break;
                        }
                    }
                }
                // 反向变更逻辑：直接保留当前单据类型值，无需映射
                else {
                    // 直接保留当前的单据类型值，无需改变
                    //赋值的方法在前面已经执行过了，当然这个实体是变更单赋值过的值，两种方式 一查库，库里查出来的数据是原来的值------pass不用这个
                    //二 跳过单据类型赋值
                    newBillType = newDataEntity.getDynamicObject(name); // 这里直接使用name，即当前的单据类型属性字段
                }

                // 更新动态对象的单据类型
                newDataEntity.set(name, newBillType);
            }
        }
    }


    /**
     * 构建原始单据和变更单据的关联关系
     *
     * @param from
     * @param to
     * @param tplPkId
     */
    private static void matchVersions(DynamicObject from, DynamicObject to, Object tplPkId) {
        List<DynamicObject> relObjList = new ArrayList<>();
        DynamicObjectType toType = to.getDynamicObjectType();
        DataEntityPropertyCollection toProperties = toType.getProperties();
        DynamicObjectType fromType = from.getDynamicObjectType();
        DataEntityPropertyCollection fromProperties = fromType.getProperties();
        //表头处理
        DynamicObject relObj = newVersionRelData(from, to, tplPkId, fromType.getName(), from.getPkValue(), to.getPkValue());
        relObjList.add(relObj);
        for (IDataEntityProperty toProperty : toProperties) {
            //分录处理
            if (toProperty instanceof EntryProp) {
                String name = toProperty.getName();
                if (!fromProperties.containsKey(name)) {
                    continue;
                }
                DynamicObjectCollection toDynamicObjectCollection = to.getDynamicObjectCollection(name);
                DynamicObjectCollection fromDynamicObjectCollection = from.getDynamicObjectCollection(name);
                for (DynamicObject fromObj : fromDynamicObjectCollection) {
                    if (fromObj.getPkValue() == null) {
                        continue;
                    }
                    Object fromEntryPk = fromObj.getPkValue();//原始主键
                    String fromEntrySeq = fromObj.getString("seq");//原始序号
                    for (DynamicObject toObj : toDynamicObjectCollection) {
                        if (toObj.getPkValue() == null) {
                            continue;
                        }
                        Object toEntryPk = toObj.getPkValue();//变更主键
                        String toEntrySeq = toObj.getString("seq");//原始序号
                        if (fromEntrySeq.equals(toEntrySeq)) {
                            DynamicObject relEntryObj = newVersionRelData(from, to, tplPkId, fromDynamicObjectCollection.getDynamicObjectType().getName(), fromEntryPk, toEntryPk);
                            relObjList.add(relEntryObj);
                            break;
                        }
                    }
                }
            }
        }
        SaveServiceHelper.save(relObjList.toArray(new DynamicObject[0]));
    }

    /**
     * 构建【版本变更关联追踪表】数据
     *
     * @param from
     * @param to
     * @param tplPkId
     * @param entitykey
     * @param fromEntryPk
     * @param toEntryPk
     * @return
     */
    private static DynamicObject newVersionRelData(DynamicObject from, DynamicObject to, Object tplPkId, String entitykey, Object fromEntryPk, Object toEntryPk) {
        DynamicObject relObj = null;
        String dbRouteKey = from.getDynamicObjectType().getDBRouteKey();
        if (KEY_TPL_MAP.containsKey(dbRouteKey)) {
            relObj = BusinessDataServiceHelper.newDynamicObject(KEY_TPL_MAP.get(dbRouteKey));
        } else {
            throw new KDBizException("当前模块分库未配置版本关联追踪表，请联系管理员。");
        }
        relObj.set("yem_tplid", tplPkId);//变更方案ID
        relObj.set("yem_masterid", from.getPkValue());//主数据内码
        relObj.set("yem_xmasterid", to.getPkValue());//变更单内码
        relObj.set("yem_vno", to.get("yem_version"));//版本号
        relObj.set("yem_entitykey", entitykey);//单据(体)标识
        relObj.set("yem_pkid", fromEntryPk);//原始主键
        relObj.set("yem_xpkid", toEntryPk);//变更单主键

        return relObj;
    }

    /**
     * 根据关联表反写变更数据到源单
     *
     * @param srcEntity
     * @param changeEntity
     * @param from
     * @param to
     * @param rels
     * @param relObjList
     * @param tplPkId
     */
    private static void copyChange2SrcByVersionRelData(DynamicObject srcEntity, DynamicObject changeEntity, DynamicObject from, DynamicObject to, DynamicObject[] rels, List<DynamicObject> relObjList, Object tplPkId,DynamicObject tpl) {
        DynamicObjectType toType = to.getDynamicObjectType();
        DataEntityPropertyCollection toProperties = toType.getProperties();
        DynamicObjectType fromType = from.getDynamicObjectType();
        DataEntityPropertyCollection fromProperties = fromType.getProperties();
        //新建一个list用来存入需要name中包含的
        List list=new ArrayList();
        list.add("id");
        list.add("billno");
        list.add("auditor");
        list.add("auditor_id");
        list.add("auditdate");
        list.add("creator");
        list.add("creator_id");
        list.add("createtime");
        DynamicObjectCollection yemColsmap = tpl.getDynamicObjectCollection("yem_colsmap");
        for (DynamicObject yemColsmapObj : yemColsmap) {
            //添加一个执行的地方，就是在模板中读取不更新的字段，如果是false则反写，true的时候则不反写
            if(yemColsmapObj.getBoolean("yem_notupdate")){
                //获取标识
                String yemBillcol = yemColsmapObj.getString("yem_billcolno");
                list.add(yemBillcol);
            }
        }

        for (IDataEntityProperty toProperty : toProperties) {
            String name = toProperty.getName();
            if (!fromProperties.containsKey(name)) {
                continue;
            }
            //分录处理
            if (toProperty instanceof EntryProp) {
                List<String> fromEntryPks = new ArrayList<>();
                List<String> toEntryPks = new ArrayList<>();
                DynamicObjectCollection toDynamicObjectCollection = to.getDynamicObjectCollection(name);
                DynamicObjectCollection fromDynamicObjectCollection = from.getDynamicObjectCollection(name);
                for (DynamicObject fromObj : fromDynamicObjectCollection) {
                    String fromEntryPk = fromObj.getPkValue() == null ? "" : fromObj.getPkValue().toString();//变更分录ID
                    DynamicObject dynamicObject = null;
                    boolean isadd = false;//是追加的行
                    if (fromEntryPk.length() > 0) {
                        fromEntryPks.add(fromEntryPk);
                        A:
                        for (DynamicObject toObj : toDynamicObjectCollection) {
                            String toEntryPk = toObj.getPkValue() == null ? "" : toObj.getPkValue().toString();//原始分录ID
                            if (toEntryPk.length() > 0) {
                                //关联处理
                                for (DynamicObject rel : rels) {
                                    String yem_entitykey = rel.getString("yem_entitykey");//单据体标识
                                    String yem_pkid = rel.getString("yem_pkid");//原始主键
                                    String yem_xpkid = rel.getString("yem_xpkid");//变更单主键
                                    if (name.equals(yem_entitykey) && toEntryPk.equals(yem_pkid) && fromEntryPk.equals(yem_xpkid)) {
                                        dynamicObject = toObj;
                                        break A;
                                    }
                                }
                            }
                        }
                    }
                    DynamicObjectType toObjType = toDynamicObjectCollection.getDynamicObjectType();
                    if (dynamicObject == null) {
                        dynamicObject = new DynamicObject(toObjType);
                        isadd = true;
                    }

                    copyChange2SrcByVersionRelData(srcEntity, changeEntity, fromObj, dynamicObject, rels, relObjList, tplPkId,tpl);
                    if (isadd) {
                        long genLongId = ORM.create().genLongId(toObjType);
                        toEntryPks.add(String.valueOf(genLongId));
                        dynamicObject.set("id", genLongId);
                        toDynamicObjectCollection.add(dynamicObject);
                        DynamicObject relObj = newVersionRelData(srcEntity, changeEntity, tplPkId, toObjType.getName(), genLongId, fromObj.getPkValue());
                        relObjList.add(relObj);
                    }
                }
                //去掉删除的行
                for (DynamicObject rel : rels) {
                    String yem_entitykey = rel.getString("yem_entitykey");//单据体标识
                    String yem_pkid = rel.getString("yem_pkid");//原始主键
                    String yem_xpkid = rel.getString("yem_xpkid");//变更单主键
                    if (name.equals(yem_entitykey) && fromEntryPks.contains(yem_xpkid)) {
                        toEntryPks.add(yem_pkid);
                    }
                }
                for (int i = 0; i < toDynamicObjectCollection.size(); i++) {
                    DynamicObject toObj = toDynamicObjectCollection.get(i);
                    String toEntryPk = toObj.getPkValue() == null ? "0" : toObj.getPkValue().toString();
                    if (!"0".equals(toEntryPk) && !toEntryPks.contains(toEntryPk)) {
                        toDynamicObjectCollection.remove(i--);
                    }
                }
            }//多选基础资料类处理
            else if (toProperty instanceof MulBasedataProp) {
                MulBasedataProp mulBasedataProp = ((MulBasedataProp) toProperty);

                IDataEntityType itemType = mulBasedataProp.getItemType();
                ISimpleProperty primaryKey = itemType.getPrimaryKey();
                DynamicObjectCollection toColls = (DynamicObjectCollection) to.get(name);
                toColls.clear();
                DynamicObjectType toDynamicObjectType = toColls.getDynamicObjectType();

                DynamicObjectCollection fromColls = (DynamicObjectCollection) from.get(name);
                for (DynamicObject coll : fromColls) {
                    DynamicObject mulBaseData = new DynamicObject(toDynamicObjectType);
                    copyChange2SrcByVersionRelData(srcEntity, changeEntity, coll, mulBaseData, rels, relObjList, tplPkId,tpl);
                    primaryKey.resetValue(mulBaseData);
                    toColls.add(mulBaseData);
                }
            }//多语言表处理
            else if (toProperty instanceof DynamicLocaleProperty) {
                DynamicLocaleProperty localeProperty = ((DynamicLocaleProperty) toProperty);

                IDataEntityType itemType = localeProperty.getItemType();
                ISimpleProperty primaryKey = itemType.getPrimaryKey();
                DynamicObjectCollection toColls = (DynamicObjectCollection) to.get(name);
                toColls.clear();
                DynamicObjectType toDynamicObjectType = toColls.getDynamicObjectType();

                DynamicObjectCollection fromColls = (DynamicObjectCollection) from.get(name);
                for (DynamicObject coll : fromColls) {
                    DynamicObject mulBaseData = new DynamicObject(toDynamicObjectType);
                    copyChange2SrcByVersionRelData(srcEntity, changeEntity, coll, mulBaseData, rels, relObjList, tplPkId,tpl);
                    primaryKey.resetValue(mulBaseData);
                    toColls.add(mulBaseData);
                }
            }//字段处理
            else {
                if (from.get(name) == null) {
                    continue;
                }
                //需要修改(生成变更单时的控制反写字段的)
                if (list.contains(name)) {
                    continue;
                }
                if(toProperty instanceof BillTypeProp){
                    continue;
                }
                to.set(name, from.get(name));
            }
        }
    }

    public boolean isChanged() {
        return isChanged;
    }

    public DynamicObject getTplObj() {
        return tplObj;
    }

    public String getRequireKey() {
        return requireKey;
    }

    public String getChangeKey() {
        return changeKey;
    }

}
