数仓成本科目同步接口1.0
This commit is contained in:
		
							parent
							
								
									e0f8d37841
								
							
						
					
					
						commit
						1df9368967
					
				| 
						 | 
				
			
			@ -12,7 +12,9 @@ import kd.bos.exception.KDException;
 | 
			
		|||
import kd.bos.id.ID;
 | 
			
		||||
import kd.bos.logging.Log;
 | 
			
		||||
import kd.bos.logging.LogFactory;
 | 
			
		||||
import kd.bos.orm.query.QCP;
 | 
			
		||||
import kd.bos.orm.query.QFilter;
 | 
			
		||||
import kd.bos.schedule.api.MessageHandler;
 | 
			
		||||
import kd.bos.schedule.executor.AbstractTask;
 | 
			
		||||
import kd.bos.servicehelper.BusinessDataServiceHelper;
 | 
			
		||||
import kd.bos.servicehelper.QueryServiceHelper;
 | 
			
		||||
| 
						 | 
				
			
			@ -25,11 +27,15 @@ import okhttp3.Response;
 | 
			
		|||
import shkd.utils.DobeDWUtils;
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 后台任务插件
 | 
			
		||||
 * 数仓成本科目同步
 | 
			
		||||
 * 同步规则:以编码为准,系统有则判断更新,无则新增
 | 
			
		||||
 */
 | 
			
		||||
public class DobeDWaccountTask extends AbstractTask implements Plugin {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -45,8 +51,8 @@ public class DobeDWaccountTask extends AbstractTask implements Plugin {
 | 
			
		|||
    public void execute(RequestContext requestContext, Map<String, Object> map) throws KDException {
 | 
			
		||||
        //调用数仓查询接口
 | 
			
		||||
        OkHttpClient client = new OkHttpClient();
 | 
			
		||||
        Request request = new Request.Builder().url(DobeDWUtils.dwUrl+dw_menthod)
 | 
			
		||||
                .post(DobeDWUtils.createRequestBody("account",1))
 | 
			
		||||
        Request request = new Request.Builder().url(DobeDWUtils.dwUrl + dw_menthod)
 | 
			
		||||
                .post(DobeDWUtils.createRequestBody("account", 1))
 | 
			
		||||
                .header("Content-Type", "application/json")
 | 
			
		||||
                .header("Authorization", DobeDWUtils.appCode)
 | 
			
		||||
                .build();
 | 
			
		||||
| 
						 | 
				
			
			@ -62,127 +68,323 @@ public class DobeDWaccountTask extends AbstractTask implements Plugin {
 | 
			
		|||
        }
 | 
			
		||||
        JSONObject json_body = JSON.parseObject(resultData);
 | 
			
		||||
        //定时任务获取的参数和参数值是配置调度程序和作业的时候设置,根据参数值保存从数仓获取到的完整json
 | 
			
		||||
        if(map != null && "yes".equals(map.get("savedwjson"))){
 | 
			
		||||
            DobeDWUtils.saveLog("savedwjson1","科目接口",resultData,null,true,"定时任务");
 | 
			
		||||
        if (map != null && "yes".equals(map.get("savedwjson"))) {
 | 
			
		||||
            DobeDWUtils.saveLog("savedwjson1", "成本科目接口", resultData, null, true, "定时任务");
 | 
			
		||||
        }
 | 
			
		||||
        //接口返回的数据进行了分页
 | 
			
		||||
//        int totalNum = json_body.getIntValue("totalNum");//分页-SQL查询总数据量
 | 
			
		||||
        //根据id查找标准成本科目的表头信息
 | 
			
		||||
        long bzkmid;
 | 
			
		||||
        String accountId = requestContext.getAccountId();//获取账套ID
 | 
			
		||||
        if("2008012388581769216".equals(accountId)){
 | 
			
		||||
            bzkmid = 2012525353133704192L;//测试id
 | 
			
		||||
        }else{
 | 
			
		||||
        if ("2231954870896690176".equals(accountId)) {
 | 
			
		||||
            bzkmid = 2234107107932663808L;//测试id
 | 
			
		||||
        } else {
 | 
			
		||||
            bzkmid = 2037039962179791872L;//正式id
 | 
			
		||||
        }
 | 
			
		||||
        logger.info("accountId "+accountId);
 | 
			
		||||
        DynamicObject billinfo = BusinessDataServiceHelper.loadSingle(entityName,new QFilter[]{new QFilter("id","=",bzkmid)});
 | 
			
		||||
        if(billinfo == null){
 | 
			
		||||
        logger.info("accountId " + accountId);
 | 
			
		||||
        DynamicObject billinfo = BusinessDataServiceHelper.loadSingle(entityName, new QFilter[]{new QFilter("id", "=", bzkmid)});
 | 
			
		||||
        if (billinfo == null) {
 | 
			
		||||
            //根据标准科目id未找到对应记录
 | 
			
		||||
            DobeDWUtils.saveLog(bzkmid+"","数仓成本科目同步","","根据标准科目ID未找到对应记录:"+bzkmid,false,"定时任务");
 | 
			
		||||
            DobeDWUtils.saveLog(bzkmid + "", "数仓成本科目同步", "", "根据标准科目ID未找到对应记录:" + bzkmid, false, "定时任务");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
//        String acctid = null;//成本科目数仓id
 | 
			
		||||
        String number;//成本科目编号
 | 
			
		||||
        String name;//成本科名称
 | 
			
		||||
//        String ciaccountflag = null; //科目类别 非建安科目and建安科目
 | 
			
		||||
//        String apportionway = null;
 | 
			
		||||
//        String taxrate = null;
 | 
			
		||||
        String kjkm_num;//会计科目编号
 | 
			
		||||
        String kjkm_name;//会计科目名称
 | 
			
		||||
        String parentnumber;//成本科目父级编号
 | 
			
		||||
        DynamicObject acctinfo;//成本科目对象
 | 
			
		||||
        DynamicObject parentAcctinfo;//父级成本科目对象
 | 
			
		||||
        DynamicObject acctViewinfo;//会计科目对象
 | 
			
		||||
        Map<String,DynamicObject> parentAccts = new HashMap<>();//现有成本科目集合
 | 
			
		||||
        Map<String,DynamicObject> acctViewMap = new HashMap<>();//会计科目缓存
 | 
			
		||||
        JSONArray detailsJson = json_body.getJSONArray("data");
 | 
			
		||||
        DynamicObjectCollection doDetails = billinfo.getDynamicObjectCollection("costaccountentry");//标准科目分录数据
 | 
			
		||||
        for (int i = 0; i < doDetails.size(); i++) {
 | 
			
		||||
            acctinfo = doDetails.get(i);
 | 
			
		||||
            //以数仓科目id作为key,科目对象为value
 | 
			
		||||
//            parentAccts.put(acctinfo.getString("caentry_srcid"),acctinfo);
 | 
			
		||||
            if(acctinfo.getBoolean("caentry_enable")){
 | 
			
		||||
                //只加载已启用的科目
 | 
			
		||||
                parentAccts.put(acctinfo.getString("caentry_number"),acctinfo);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        //循环入参,判断哪些科目该修改,哪些该新增
 | 
			
		||||
        for (int i = 0; i < detailsJson.size(); i++) {
 | 
			
		||||
            json_body = detailsJson.getJSONObject(i);
 | 
			
		||||
//            acctid = json_body.getString("costsubject_id");//科目id
 | 
			
		||||
            number = json_body.getString("costsubject_code");//科目编号
 | 
			
		||||
            name = json_body.getString("costsubject_name");//科目名称
 | 
			
		||||
            kjkm_num = json_body.getString("accsubject_code");//会计科目编码
 | 
			
		||||
            kjkm_name = json_body.getString("accsubject_name");//会计科目名称
 | 
			
		||||
//            ciaccountflag = json_body.getString("ciaccountflag");//科目类别 非建安科目and建安科目
 | 
			
		||||
//            apportionway = json_body.getString("apportionway");//分摊方式
 | 
			
		||||
//            taxrate = json_body.getString("taxrate");//税率
 | 
			
		||||
            parentnumber = json_body.getString("costsubject_pcode");//科目父级code
 | 
			
		||||
            if(DobeDWUtils.isEmpty(number) || DobeDWUtils.isEmpty(name) || DobeDWUtils.isEmpty(parentnumber)){
 | 
			
		||||
                //根节点数仓不体现,故,所有科目都会有父级科目编号,没有的不处理
 | 
			
		||||
                logger.info(String.format("成本科目入参为空异常:%s", json_body.toJSONString()));
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            //先从现有科目集合中获取,未获取到则新增
 | 
			
		||||
            acctinfo = parentAccts.get(number);
 | 
			
		||||
            if(acctinfo == null){
 | 
			
		||||
                acctinfo = doDetails.addNew();
 | 
			
		||||
//                acctinfo.set("caentry_srcid", number);//源ID 用于存储数仓的科目id
 | 
			
		||||
//                acctinfo.set("caentry_project", projectinfo.getLong("id"));//项目
 | 
			
		||||
                acctinfo.set("caentry_enable", true);//默认 启用
 | 
			
		||||
                acctinfo.set("caentry_isstdaccount", true);//是否标准科目
 | 
			
		||||
                acctinfo.set("caentry_standlibflag", true);//是否标准科目库
 | 
			
		||||
                acctinfo.set("caentry_isleaf", true);//是否叶子节点,新增默认为true
 | 
			
		||||
                acctinfo.set("caentry_ciaccountflag", "1");//科目类别 建安 1 非建安 0 默认都是建安类
 | 
			
		||||
                //新增时指定一个ID,防止父级和子级都创建的情况下,子级拿不到父级id而报错
 | 
			
		||||
                acctinfo.set("id", ID.genLongId());
 | 
			
		||||
//                acctinfo.set("caentry_longnumber", number);//科目长编号
 | 
			
		||||
//                acctinfo.set("caentry_fullname", name);//科目长名称
 | 
			
		||||
                //将此次新增的科目放到现有科目集合中,方便后续科目能获取到父级科目
 | 
			
		||||
                parentAccts.put(number,acctinfo);
 | 
			
		||||
            }
 | 
			
		||||
            //已存在,做更新 编号、名称、长编号、名称、科目类别等
 | 
			
		||||
            acctinfo.set("caentry_number", number);
 | 
			
		||||
            acctinfo.set("caentry_name", name);
 | 
			
		||||
//            acctinfo.set("caentry_apportionway", null);//分摊方式 基础资料
 | 
			
		||||
//            acctinfo.set("caentry_taxrate", taxrate);//税率
 | 
			
		||||
            //创建组织 caentry_createorg
 | 
			
		||||
            //组织 caentry_org
 | 
			
		||||
            //业务组织 caentry_useorg
 | 
			
		||||
            //处理父级科目
 | 
			
		||||
            parentAcctinfo = parentAccts.get(parentnumber);
 | 
			
		||||
            if(parentAcctinfo != null){
 | 
			
		||||
                acctinfo.set("pid", parentAcctinfo.getLong("id"));//设置父级科目
 | 
			
		||||
                //如果数仓不指定长编码和长名称,则需要在此处手动处理
 | 
			
		||||
                acctinfo.set("caentry_longnumber", parentAcctinfo.getString("caentry_longnumber")+"."+number);
 | 
			
		||||
                acctinfo.set("caentry_fullname", parentAcctinfo.getString("caentry_fullname")+"_"+name);
 | 
			
		||||
                //科目级次=父级科目级次+1
 | 
			
		||||
                acctinfo.set("caentry_level", parentAcctinfo.getInt("caentry_level")+1);
 | 
			
		||||
                //父级科目的是否叶子节点为否
 | 
			
		||||
                parentAcctinfo.set("caentry_isleaf", false);//是否叶子节点为否
 | 
			
		||||
            }else{
 | 
			
		||||
                logger.info("根据父级科目编号未找到对应科目"+parentnumber);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            //设置对应会计科目字段id
 | 
			
		||||
            if(!DobeDWUtils.isEmpty(kjkm_num)){
 | 
			
		||||
                acctViewinfo = acctViewMap.get(kjkm_num);
 | 
			
		||||
                if(acctViewinfo == null){
 | 
			
		||||
                    acctViewinfo = QueryServiceHelper.queryOne(acctViewEntity,"id,number,longnumber",new QFilter[]{new QFilter("longnumber","=",kjkm_num)});
 | 
			
		||||
                }
 | 
			
		||||
                if(acctViewinfo == null){
 | 
			
		||||
                    DobeDWUtils.saveLog(number,"数仓科目同步",json_body.toString(),kjkm_num+" 会计科目在金蝶中找不到:"+kjkm_name,false,"定时任务");
 | 
			
		||||
                }else{
 | 
			
		||||
                    acctViewMap.put(kjkm_num,acctViewinfo);
 | 
			
		||||
                    acctinfo.set("caentry_account",acctViewinfo.getLong("id"));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        JSONArray detailsJson = json_body.getJSONArray("data");
 | 
			
		||||
        if (detailsJson==null || detailsJson.isEmpty()){
 | 
			
		||||
            logger.info("解析data为空,不继续处理!");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        DynamicObjectCollection doDetails = billinfo.getDynamicObjectCollection("costaccountentry");//标准科目分录数据
 | 
			
		||||
        if (doDetails!=null && doDetails.size()!=0){
 | 
			
		||||
            //成本科目最少需要一级数据一条,例:CB
 | 
			
		||||
            this.dataComparison(detailsJson,doDetails,billinfo);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //调用保存操作
 | 
			
		||||
        OperationResult save = OperationServiceHelper.executeOperate("save", entityName, new DynamicObject[]{billinfo}, OperateOption.create());
 | 
			
		||||
        if (!save.isSuccess()){
 | 
			
		||||
        if (!save.isSuccess()) {
 | 
			
		||||
            logger.error(save.getMessage());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void dataComparison(JSONArray detailsJson, DynamicObjectCollection doDetails,DynamicObject billinfo) {
 | 
			
		||||
        // 用于存储需要新增的数据(接口中有但系统中没有的)
 | 
			
		||||
        List<JSONObject> toAddList = new ArrayList<>();
 | 
			
		||||
        int updateCount = 0; // 记录更新条数
 | 
			
		||||
        int addCount = 0;    // 记录新增条数
 | 
			
		||||
 | 
			
		||||
        for (int i = 0; i < detailsJson.size(); i++) {
 | 
			
		||||
            JSONObject jsonObject = detailsJson.getJSONObject(i);
 | 
			
		||||
            String status = jsonObject.getString("costsubject_status");
 | 
			
		||||
 | 
			
		||||
            if ("启用".equals(status)) {
 | 
			
		||||
                String code = jsonObject.getString("costsubject_code");
 | 
			
		||||
                if (code != null) {
 | 
			
		||||
                    boolean found = false;
 | 
			
		||||
 | 
			
		||||
                    for (int j = 0; j < doDetails.size(); j++) {
 | 
			
		||||
                        DynamicObject dynamicObject = doDetails.get(j);
 | 
			
		||||
                        String longNumber = dynamicObject.getString("caentry_longnumber");
 | 
			
		||||
 | 
			
		||||
                        if (longNumber != null) {
 | 
			
		||||
                            // 去除系统中的"."后与接口编码比较
 | 
			
		||||
                            String cleanedLongNumber = longNumber.replace(".", "");
 | 
			
		||||
 | 
			
		||||
                            if (code.equals(cleanedLongNumber)) {
 | 
			
		||||
                                found = true;
 | 
			
		||||
                                // 检查名称或其他字段是否有变化
 | 
			
		||||
                                String systemName = dynamicObject.getString("caentry_name"); // 假设系统中名称字段为caentry_name
 | 
			
		||||
                                String jsonName = jsonObject.getString("costsubject_name");
 | 
			
		||||
                                // 如果名称不同或需要检查其他字段变化,则直接更新
 | 
			
		||||
                                if (!jsonName.equals(systemName)) {
 | 
			
		||||
                                    //更新科目名称
 | 
			
		||||
                                    dynamicObject.set("caentry_name",jsonName);
 | 
			
		||||
                                    updateCount++;
 | 
			
		||||
                                    System.out.println("[MyLog]更新科目: " + jsonName + ", 编码: " + code);
 | 
			
		||||
                                    logger.info("更新科目名称: {}, 编码: {}", jsonName, code);
 | 
			
		||||
                                }
 | 
			
		||||
                                //会计科目
 | 
			
		||||
                                String accSubjectCode = jsonObject.getString("accsubject_code");
 | 
			
		||||
                                if (accSubjectCode!=null){
 | 
			
		||||
                                    DynamicObject sysAccount = dynamicObject.getDynamicObject("caentry_account");
 | 
			
		||||
                                    if (sysAccount==null){
 | 
			
		||||
                                        //直接匹配会计科目赋值id
 | 
			
		||||
                                        Long accountId=this.getSysAccountId(accSubjectCode);
 | 
			
		||||
                                        if (accountId!=null){
 | 
			
		||||
                                            dynamicObject.set("caentry_account",accountId);
 | 
			
		||||
                                            logger.info("成功关联会计科目,科目编码: {}, 会计科目ID: {}", code, accountId);
 | 
			
		||||
                                            System.out.println("[MyLog]关联会计科目: " + code + " -> " + accountId);
 | 
			
		||||
                                        }
 | 
			
		||||
                                    }else {
 | 
			
		||||
                                        //编码匹配是否改变
 | 
			
		||||
                                        String number = sysAccount.getString("number");
 | 
			
		||||
                                        if (!accSubjectCode.equals(number)){
 | 
			
		||||
                                            //匹配会计科目赋值id
 | 
			
		||||
                                            Long accountId=this.getSysAccountId(accSubjectCode);
 | 
			
		||||
                                            if (accountId!=null){
 | 
			
		||||
                                                dynamicObject.set("caentry_account",accountId);
 | 
			
		||||
                                                logger.info("更新会计科目关联成功,科目编码: {}, 新会计科目ID: {}", code, accountId);
 | 
			
		||||
                                                System.out.println("[MyLog]更新会计科目关联: " + code + " -> " + accountId);
 | 
			
		||||
                                            }
 | 
			
		||||
                                        }
 | 
			
		||||
                                    }
 | 
			
		||||
                                }
 | 
			
		||||
                                break; // 找到匹配项后跳出循环
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    // 如果没有找到匹配项,则加入新增列表
 | 
			
		||||
                    if (!found) {
 | 
			
		||||
                        toAddList.add(jsonObject);
 | 
			
		||||
                        addCount++;
 | 
			
		||||
                        System.out.println("[MyLog]准备新增科目: " + jsonObject.getString("costsubject_name") + ", 编码: " + code);
 | 
			
		||||
                        logger.info("准备新增科目: {}, 编码: {}", jsonObject.getString("costsubject_name"), code);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // 打印统计信息
 | 
			
		||||
        System.out.println("[MyLog]数据比对结果 - 更新条数: " + updateCount + ", 新增条数: " + addCount);
 | 
			
		||||
        logger.info("数据比对结果 - 更新条数: {}, 新增条数: {}", updateCount, addCount);
 | 
			
		||||
 | 
			
		||||
        //更新
 | 
			
		||||
        if (toAddList.size()!=0){
 | 
			
		||||
            this.addCostSubject(toAddList,doDetails,billinfo);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取会计科目id
 | 
			
		||||
     * @param accSubjectCode
 | 
			
		||||
     * @return
 | 
			
		||||
     */
 | 
			
		||||
    private Long getSysAccountId(String accSubjectCode) {
 | 
			
		||||
        Long pkValue = null;
 | 
			
		||||
        QFilter number = new QFilter("number", QCP.equals, accSubjectCode);
 | 
			
		||||
        DynamicObject dynamicObject = BusinessDataServiceHelper.loadSingle("bd_accountview", number.toArray());
 | 
			
		||||
        if (dynamicObject!=null){
 | 
			
		||||
            pkValue= (Long) dynamicObject.getPkValue();
 | 
			
		||||
        }
 | 
			
		||||
        return pkValue;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 新增标准成本科目数据
 | 
			
		||||
     * @param toAddList 需要新增的数据
 | 
			
		||||
     * @param doDetails 单据体
 | 
			
		||||
     */
 | 
			
		||||
    private void addCostSubject(List<JSONObject> toAddList, DynamicObjectCollection doDetails,DynamicObject billinfo) {
 | 
			
		||||
        System.out.println("[MyLog]开始新增科目,数量: " + toAddList.size());
 | 
			
		||||
        logger.info("开始新增科目,数量: {}", toAddList.size());
 | 
			
		||||
 | 
			
		||||
        // 用于缓存已创建的父级科目
 | 
			
		||||
        Map<String, DynamicObject> parentCache = new HashMap<>();
 | 
			
		||||
 | 
			
		||||
        for (JSONObject jsonObject : toAddList) {
 | 
			
		||||
            try {
 | 
			
		||||
                // 1. 准备基础数据
 | 
			
		||||
 | 
			
		||||
                //父级编码CB001
 | 
			
		||||
                String pCode = jsonObject.getString("costsubject_pcode");
 | 
			
		||||
                //系统需要的编码CB.001
 | 
			
		||||
                String formattedCode = formatParentCode(pCode);
 | 
			
		||||
                //科目编码CB001002
 | 
			
		||||
                String code = jsonObject.getString("costsubject_code");
 | 
			
		||||
                //系统短编码002
 | 
			
		||||
                String shortNumber = code.substring(pCode.length());
 | 
			
		||||
 | 
			
		||||
                // 2. 处理父级科目
 | 
			
		||||
                DynamicObject parentEntry = findOrCreateParent(
 | 
			
		||||
                        jsonObject, pCode, formattedCode, doDetails, parentCache,billinfo);
 | 
			
		||||
 | 
			
		||||
                // 设置父级科目行号(如果父级是新创建的)
 | 
			
		||||
                if (!parentCache.containsKey(formattedCode)) {
 | 
			
		||||
                    parentEntry.set("seq", doDetails.size()-1); // 使用当前总条数作为行号
 | 
			
		||||
                    parentCache.put(formattedCode, parentEntry);
 | 
			
		||||
                    System.out.println("[MyLog]新增父级科目: " + parentEntry.getString("caentry_name") +
 | 
			
		||||
                            ", 编码: " + parentEntry.getString("caentry_longnumber"));
 | 
			
		||||
                    logger.info("新增父级科目: {}, 编码: {}",
 | 
			
		||||
                         parentEntry.getString("caentry_name"),
 | 
			
		||||
                         parentEntry.getString("caentry_longnumber"));
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // 3. 创建当前科目
 | 
			
		||||
                DynamicObject dynamicObject = doDetails.addNew();
 | 
			
		||||
                setupDynamicObject(dynamicObject, jsonObject, parentEntry, formattedCode, shortNumber);
 | 
			
		||||
 | 
			
		||||
                // 4. 设置当前科目行号
 | 
			
		||||
                dynamicObject.set("seq", doDetails.size()-1); // 使用当前总条数-1作为行号
 | 
			
		||||
 | 
			
		||||
                System.out.println("[MyLog]新增科目: " + dynamicObject.getString("caentry_name") +
 | 
			
		||||
                        ", 编码: " + dynamicObject.getString("caentry_longnumber"));
 | 
			
		||||
                logger.info("新增科目: {}, 编码: {}",
 | 
			
		||||
                     dynamicObject.getString("caentry_name"),
 | 
			
		||||
                     dynamicObject.getString("caentry_longnumber"));
 | 
			
		||||
            } catch (Exception e) {
 | 
			
		||||
                System.err.println("[MyLog]新增科目失败: " + jsonObject.getString("costsubject_name") +
 | 
			
		||||
                        ", 错误: " + e.getMessage());
 | 
			
		||||
                logger.error("新增科目失败: {}, 错误: {}", jsonObject.getString("costsubject_name"), e.getMessage(), e);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        System.out.println("[MyLog]科目新增完成,共新增: " + toAddList.size() + "条记录");
 | 
			
		||||
        logger.info("科目新增完成,共新增: {}条记录", toAddList.size());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 查找或创建父级科目
 | 
			
		||||
     */
 | 
			
		||||
    private DynamicObject findOrCreateParent(JSONObject jsonObject, String pCode,
 | 
			
		||||
                                             String formattedCode, DynamicObjectCollection doDetails,
 | 
			
		||||
                                             Map<String, DynamicObject> cache,DynamicObject billinfo) {
 | 
			
		||||
        // 1. 先检查缓存
 | 
			
		||||
        if (cache.containsKey(formattedCode)) {
 | 
			
		||||
            return cache.get(formattedCode);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 2. 在现有数据中查找
 | 
			
		||||
        for (DynamicObject entry : doDetails) {
 | 
			
		||||
            if (formattedCode.equals(entry.getString("caentry_longnumber"))) {
 | 
			
		||||
                return entry;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 3. 查找顶级父级科目(CB)
 | 
			
		||||
        DynamicObject topParent = findTopParent(doDetails);
 | 
			
		||||
        if (topParent == null) {
 | 
			
		||||
            throw new RuntimeException("未找到顶级父级科目(CB)");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 4. 创建新的父级科目
 | 
			
		||||
        DynamicObject parentEntry = doDetails.addNew();
 | 
			
		||||
        String parentShortCode = pCode.substring(2);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        // 设置父级科目属性
 | 
			
		||||
        parentEntry.set("pid", topParent.getPkValue()); // 父级 ID——CB
 | 
			
		||||
        parentEntry.set("caentry_number", parentShortCode);
 | 
			
		||||
        parentEntry.set("caentry_longnumber", formattedCode);
 | 
			
		||||
        parentEntry.set("caentry_name", jsonObject.getString("costsubject_pname"));
 | 
			
		||||
        parentEntry.set("caentry_enable", true);
 | 
			
		||||
        parentEntry.set("caentry_org", 100000L);
 | 
			
		||||
        parentEntry.set("caentry_createorg", 100000L);
 | 
			
		||||
        parentEntry.set("caentry_useorg", 100000L);
 | 
			
		||||
        parentEntry.set("caentry_isleaf", false);
 | 
			
		||||
        parentEntry.set("caentry_level", 2);
 | 
			
		||||
        parentEntry.set("caentry_standlibflag", true);
 | 
			
		||||
        parentEntry.set("caentry_isimportaccount", false);
 | 
			
		||||
        parentEntry.set("caentry_isstdaccount", true);
 | 
			
		||||
 | 
			
		||||
        // 立即保存父级科目以生成pkValue
 | 
			
		||||
        OperationResult saveResult = OperationServiceHelper.executeOperate("save", entityName,
 | 
			
		||||
                new DynamicObject[]{billinfo}, OperateOption.create());
 | 
			
		||||
 | 
			
		||||
        if (!saveResult.isSuccess()) {
 | 
			
		||||
            throw new RuntimeException("保存父级科目失败: " + saveResult.getMessage());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        return parentEntry;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 设置科目属性
 | 
			
		||||
     */
 | 
			
		||||
    private void setupDynamicObject(DynamicObject dynamicObject, JSONObject jsonObject,
 | 
			
		||||
                                    DynamicObject parentEntry, String formattedCode, String shortNumber) {
 | 
			
		||||
        // 1. 设置基础属性
 | 
			
		||||
        dynamicObject.set("pid", parentEntry.getPkValue());
 | 
			
		||||
        dynamicObject.set("caentry_fullname", "开发成本_" + parentEntry.getString("caentry_name") +
 | 
			
		||||
                "_" + jsonObject.getString("costsubject_name"));
 | 
			
		||||
        dynamicObject.set("caentry_number", shortNumber);
 | 
			
		||||
        dynamicObject.set("caentry_longnumber", formattedCode + "." + shortNumber);
 | 
			
		||||
        dynamicObject.set("caentry_name", jsonObject.getString("costsubject_name"));
 | 
			
		||||
 | 
			
		||||
        // 2. 设置固定属性
 | 
			
		||||
        dynamicObject.set("caentry_ciaccountflag", "1");
 | 
			
		||||
        dynamicObject.set("caentry_measureway", 1026043947790783488L);
 | 
			
		||||
        dynamicObject.set("caentry_apportionway", 1026043947790783488L);
 | 
			
		||||
        dynamicObject.set("caentry_enable", true);
 | 
			
		||||
        dynamicObject.set("caentry_org", 100000L);
 | 
			
		||||
        dynamicObject.set("caentry_createorg", 100000L);
 | 
			
		||||
        dynamicObject.set("caentry_useorg", 100000L);
 | 
			
		||||
        dynamicObject.set("caentry_isleaf", true);
 | 
			
		||||
        dynamicObject.set("caentry_level", 3);
 | 
			
		||||
        dynamicObject.set("caentry_srcid", dynamicObject.getPkValue());
 | 
			
		||||
        dynamicObject.set("caentry_standlibflag", true);
 | 
			
		||||
        dynamicObject.set("caentry_isimportaccount", false);
 | 
			
		||||
        dynamicObject.set("caentry_isstdaccount", true);
 | 
			
		||||
 | 
			
		||||
        // 3. 会计科目
 | 
			
		||||
        String accSubjectCode = jsonObject.getString("accsubject_code");
 | 
			
		||||
        if (jsonObject.getString("accsubject_code") != null) {
 | 
			
		||||
             Long accountId=this.getSysAccountId(accSubjectCode);
 | 
			
		||||
             if (accountId!=null){
 | 
			
		||||
                 dynamicObject.set("caentry_account",accountId);
 | 
			
		||||
             }
 | 
			
		||||
         }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 查找顶级父级科目(CB)
 | 
			
		||||
     */
 | 
			
		||||
    private DynamicObject findTopParent(DynamicObjectCollection doDetails) {
 | 
			
		||||
        for (DynamicObject entry : doDetails) {
 | 
			
		||||
            if ("CB".equals(entry.getString("caentry_longnumber"))) {
 | 
			
		||||
                return entry;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 格式化父级编码(CB0010 → CB.0010;CB001 → CB.001)
 | 
			
		||||
     */
 | 
			
		||||
    private String formatParentCode(String pCode) {
 | 
			
		||||
        String prefix = pCode.substring(0, 2);  // 获取前两位字母(CB)
 | 
			
		||||
        String numberPart = pCode.substring(2);  // 获取数字部分(001)
 | 
			
		||||
 | 
			
		||||
        return prefix + "." + numberPart;//CB.001
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue