#include <tc/tc.h>
#include "epm_handler_common.h"
#include <ict/ict_userservice.h>
#include <tccore/custom.h>
#include <epm/epm_toolkit_tc_utils.h>
#include <tccore/aom.h>
#include <tccore/aom_prop.h>
#include <tccore/item.h>

#include <bom/bom.h>
#include "ps/ps.h";
#include "ps/vrule.h"
#include "sstream"
#include <tccore/grm.h>
#include "epm/epm.h"
#include "sa/sa.h"
#include "libxl.h"
#include <map>
#include "epm/signoff.h"
#include <ctime>
#include <vector>
#include <locale>
#include <codecvt>
#include "ae/dataset.h"
#include <iostream>
#include <stdlib.h>
#include <tccore/aom.h>
#include <tc/emh.h>
#include <ict/ict_userservice.h>
#include <tc/tc.h>
#include <tccore/tctype.h>
#include <sa/tcfile.h>
#include <ss/ss_errors.h>
#include <ae/datasettype.h>
#include <chrono>
// #include "hx_custom.h"
#include "tc_log.h"
// #include "jk_custom.h"
#include "chint_Handler.h"
#include "tc_util.h"
#include <regex>
#include <ics/ics.h>
#include "ado.h"
#include "ocilib.h"
#include <property/nr.h>
#include "CRUL_server_call_httpserver.h"
//正则判断是否为 线圈 "1ZDB581000X-00055"; 线圈申请P物料
regex qq_reg("^1ZDB5.*\\d{1,}1000X.*"); //\\d{5,}$
struct newCBean
{
	int num;
	string blQty;
	tag_t cLine;
};
struct EBomBean
{
	boolean istop = false;
	vector<tag_t> topCcp;
	tag_t eRev; //原来的e物料
	tag_t eBomline; //Ebom行
	vector <tag_t> pRev; //另存的P物料
	tag_t pBomline = NULL; //PBOM
	tag_t designRev; //E物料的图纸
	vector<EBomBean> parentBean; //遍历EBOM时候的父级
	vector<newCBean> c_lines; //EBOM中的子件 只有线圈用
};

/*
primaryTag版本
secondTag数据集
relationType关系
*/
string getRemarkMsg(string remark,int len);
string Sql2 = "select t.PrhName,t.PrdLine,t.PrdNo,t.PrdFeatureCode,t.FeatureName,t.PrdCanInput,t.PrdSign from CcemVW_Prd t where t.prhcode = '%s' order by t.PrdNo";
string Sql1 = "select t.PmpcPrhCode, t.PmpcPType,t.PmpcMType from CcemVW_Pmpc t where t.PmpcCode='%s'";
string m_code1 = "230101001";
string m_code2 = "220103001";

struct PRD
{
	string prdFeatureCode;
	string featureName;
};
struct PMPC
{
	string m_code;
	string pmpcPrhCode;
	string pmpcPType;
	string pmpcMType;
};
PMPC pmpc;
vector<PRD> prds;
/**/
void save_representation2222(tag_t primaryTag, tag_t secondTag, char* relationType)
{

	//POM_AM__set_application_bypass(true);
	tag_t typeTag = NULLTAG;
	ITKCALL(GRM_find_relation_type(relationType, &typeTag));

	ITKCALL(AOM_refresh(primaryTag, TRUE));
	ITKCALL(AOM_refresh(secondTag, TRUE));
	tag_t relationTag = NULLTAG;
	ITKCALL(GRM_create_relation(primaryTag, secondTag, typeTag, NULLTAG, &relationTag));//如果关系已经存在，那么就是增加对象

	ITKCALL(GRM_save_relation(relationTag));//很必要
	ITKCALL(AOM_save(primaryTag));
	ITKCALL(AOM_save(secondTag));
	ITKCALL(AOM_refresh(primaryTag, FALSE));
	ITKCALL(AOM_refresh(secondTag, FALSE));
	//POM_AM__set_application_bypass(false);

}
void replaceBom(tag_t newTopLine, tag_t newChild) {
	int c_line_count, cnt2, numFac;
	tag_t* c_line_tags;
	char* uid1;
	ITK__convert_tag_to_uid(newChild, &uid1);
	ITKCALL(BOM_line_ask_all_child_lines(newTopLine, &c_line_count, &c_line_tags));
	for (int t = 0; t < c_line_count; t++) {
		tag_t c_line_tag = c_line_tags[t], eRev;
		ITKCALL(AOM_ask_value_tag(c_line_tag, "bl_line_object", &eRev));
		char* uid2;
		ITK__convert_tag_to_uid(eRev, &uid2);
		if (strcmp(uid2, uid1) == 0) {
			BOM_line_replace(c_line_tag, NULLTAG, newChild, NULLTAG);
		}
	}

}
string sql_query = "select FeatureList from CcemVW_GoodsFeature where GoodsCode ='%s' ";
/**
 * 另存EBOM，从下往上另存
 * @param childPm 存放EBOM信息
 * @param map 用来存放另存之后的信息 key:E val:P物料
 * @param topPrev 顶层P物料
 */
void saveAsCycle(EBomBean& childPm, map<string, tag_t>& map, tag_t& topPrev) {
	tag_t tcType, newItem, newRev;
	char* newId;
	if (childPm.parentBean.size() > 0) {
		saveAsCycle(childPm.parentBean[0], map, topPrev);
	}
	printf("1===>%d\n", childPm.pRev.size());
	char* eRevUid, *zt2_ifpbom;
	AOM_ask_value_string(childPm.eRev, "zt2_ifpbom", &zt2_ifpbom);
	if (strcmp(zt2_ifpbom, "P") == 0) {
		if (childPm.pRev.size() == 0) {
			childPm.pRev.push_back(childPm.eRev);
		}
		return;
	}
	ITK__convert_tag_to_uid(childPm.eRev, &eRevUid);
	if (childPm.pRev.size() == 0) {
		if (map.count(eRevUid) > 0) {
			childPm.pRev.push_back(map[eRevUid]);
		}
		else {
			//另存操作
			char* newid = NULL;
			logical isModified = FALSE;
			tag_t item_type_tag;
			ITKCALL(TCTYPE_ask_type("Item", &item_type_tag));
			ITKCALL(USER_new_item_id(NULLTAG, item_type_tag, &isModified, &newid));
			/*ITKCALL(NR_next_value("MEProcess", "item_id", NULLTAG, "", "", "",
				NULLTAG, "", "", &next_id));*/
			printf("next_id==>%s\n", newid);
			ITKCALL(ITEM_copy_item(childPm.eRev, newid, NULL, &newItem, &newRev));
			//ITKCALL(AOM_set_value_string(newRev, "zt2_PMaterial", "PBOM"));
			char* matnrNo;
			ITKCALL(AOM_ask_value_string(childPm.eRev, "zt2_MaterialNo", &matnrNo));
			AOM_lock(newRev);

			ITKCALL(AOM_set_value_string(newRev, "zt2_ifpbom", "P"));
			ITKCALL(AOM_set_value_string(newRev, "zt2_MaterialNo", matnrNo));
			AOM_save(newRev);
			AOM_unlock(newRev);
			if (topPrev == NULLTAG) {
				topPrev = newRev;
			}
			childPm.pRev.push_back(newRev);
			map[eRevUid] = newRev;
			int num = 0, revNum = 0, tagNum = 0;
			tag_t* mantrs, dsuser, *structure_revisions, *bom_view_tags;
			ITKCALL(AOM_ask_value_tags(childPm.eRev, "TC_Is_Represented_By", &num, &mantrs));
			if (num > 0) {
				ITKCALL(AOM_ask_value_tags(newRev, "structure_revisions", &revNum, &structure_revisions));
				ITKCALL(AOM_ask_value_tags(newRev, "bom_view_tags", &tagNum, &bom_view_tags));
				ITKCALL(AOM_ask_value_tag(mantrs[0], "owning_user", &dsuser));
				tag_t defGroup;
				ITKCALL(AOM_ask_value_tag(dsuser, "default_group", &defGroup));
				ITKCALL(AOM_set_ownership(newItem, dsuser, defGroup));
				ITKCALL(AOM_set_ownership(newRev, dsuser, defGroup));
				if (revNum > 0) {
					ITKCALL(AOM_set_ownership(structure_revisions[0], dsuser, defGroup));
				}
				if (tagNum > 0) {
					ITKCALL(AOM_set_ownership(bom_view_tags[0], dsuser, defGroup));
				}
			}
		}
	}
	//另存之后需要替换BOM，按EBOM结构搭建PBOM
	if (childPm.parentBean.size() > 0) {
		EBomBean parentBean = childPm.parentBean[0];
		vector <tag_t> pRevs = parentBean.pRev;
		if (pRevs.size() > 0) {
			int bvr_count = 0, c_line_count;
			tag_t ebom_window = NULLTAG;
			tag_t bom_line = NULLTAG, *c_line_tags;
			ITKCALL(BOM_create_window(&ebom_window));
			tag_t* bvr_list = NULL;
			ITKCALL(ITEM_rev_list_bom_view_revs(pRevs[0], &bvr_count, &bvr_list));
			printf("bvr_count=%d\n", bvr_count);

			ITKCALL(BOM_set_window_top_line_bvr(ebom_window, bvr_list[0], &bom_line)); //顶层bom获取
			//ITKCALL(AOM_ask_value_tag(bom_line, "bl_line_object", &mantr));
			ITKCALL(BOM_line_ask_all_child_lines(bom_line, &c_line_count, &c_line_tags));

			for (int ind = 0; ind < c_line_count; ind++) {
				tag_t c_line_tag = c_line_tags[ind], mantr;
				ITKCALL(AOM_ask_value_tag(c_line_tag, "bl_line_object", &mantr));
				char* eRevUid2;
				ITK__convert_tag_to_uid(mantr, &eRevUid2);
				if (strcmp(eRevUid2, eRevUid) == 0) {
					if (childPm.pRev.size() > 0) {
						printf("eRevUid===>%s\n", eRevUid);
						ITKCALL(BOM_line_replace(c_line_tag, NULLTAG, childPm.pRev[0], NULLTAG));
					}
				}
			}
			ITKCALL(BOM_save_window(ebom_window));
			ITKCALL(BOM_close_window(ebom_window));
		}
	}
}
void getSpecs(tag_t rev, vector<string> &vec) {
	tag_t* comps;
	int cnt;
	/*AOM_ask_value_string(line, "ZT2_TYSpecifications", &ZT2_TYSpecifications);
	if (strcmp(ZT2_TYSpecifications, "") == 0) {*/
	ITKCALL(AOM_ask_value_tags(rev, "representation_for", &cnt, &comps));
	char* zt2_Specifications;
	//if (cnt == 0) {
	ITKCALL(AOM_ask_value_string(rev, "zt2_Specifications", &zt2_Specifications));
	vec.push_back(zt2_Specifications);
	//	//}
	//}
}
string insertSql = "insert into chint_material(\"Code\",\"PUID\",\"PmpcCode\",\"GoodsCode\",\"GoodsName\",\"UnitCode\",\"CompanyCode\",\"BpNo\",\"Spec\",\"TeRe\",\"State\",\"User\",\"Time\",\"Condition\",\"Info\") values('%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s',to_date('%s','yyyy-mm-dd HH24:mi:ss'),'%s','%s')";

/**
 * 根据项数拆解线圈，并申请物料编码
 * @param rev 图纸对象
 * @param user_id 用户信息
 * @param jsons JSON
 * @param groupId 组
 * @param spec 规格
 * @param nameNum A项信息
 * @param dcproxy 转权限的用户
 */
tag_t send1(tag_t rev, string now,
	char* user_id, vector<string>& jsons, string groupId, string spec, char* nameNum, char* idss, tag_t dcproxy) {
	//map<tag_t, vector<string>>::iterator it;
	//for (it = general_maps.begin(); it != general_maps.end(); it++) {
	char* item_id, *object_name, *zt2_DrawingNo1, *zt2_MaterialMark, *zt2_ProductModel
		, *object_desc, *zt2_SurfaceTreatment, *zt2_Source;
	ITKCALL(AOM_ask_value_string(rev, "item_id", &item_id)); //groupId
	ITKCALL(AOM_ask_value_string(rev, "object_name", &object_name));
	ITKCALL(AOM_ask_value_string(rev, "zt2_DrawingNo", &zt2_DrawingNo1));
	ITKCALL(AOM_ask_value_string(rev, "zt2_MaterialMark", &zt2_MaterialMark));
	ITKCALL(AOM_ask_value_string(rev, "zt2_ProductModel", &zt2_ProductModel));
	ITKCALL(AOM_ask_value_string(rev, "object_desc", &object_desc));
	ITKCALL(AOM_ask_value_string(rev, "zt2_SurfaceTreatment", &zt2_SurfaceTreatment));
	ITKCALL(AOM_UIF_ask_value(rev, "zt2_Source", &zt2_Source));
	PMPC m_pmpc;
	vector<PRD> m_prds;
	//if (strcmp(item_id, "1ZDB") == 0) {
	m_prds = prds;
	m_pmpc = pmpc;
	printf("m_pmpc\n");
	//}
	string pmpcCode = m_pmpc.m_code;
	string prhCode = m_pmpc.pmpcPrhCode;
	string pmpcType = m_pmpc.pmpcMType;
	WriteTcLog("pmpcType===>%s\n", pmpcType.c_str());
	if (pmpcType.length() == 0) {
		return NULLTAG;
	}
	string goodsCode = ""; // 申请时为空
	string prefixName = nameNum;
	string goodsName = prefixName.append(object_name);//rev.getProperty("object_name");
	string unitCode = "ST"; // 默认件，真实值ST
	string companyCode = groupId;
	string mp = "M";
	if (strcmp(zt2_Source, "外购") == 0) {
		mp = "P";
		pmpcType = m_pmpc.pmpcPType;
	}
	string bpNo = item_id;//rev.getProperty("item_id"); // 非必填
	string zt2_DrawingNo = zt2_DrawingNo1;//rev.getProperty("zt2_DrawingNo");
	if (!zt2_DrawingNo.empty()) {
		if (strcmp(item_id, zt2_DrawingNo1) != 0)
			bpNo = zt2_DrawingNo1;
	}
	vector<string> vec2;
	if (strstr(item_id, "-") != NULL) {
		Split(item_id, "-", vec2);
		string msg = vec2[0].append("-").append(idss).append("-").append(vec2[1]);
		string queryMsg;
		queryMsg.append("*").append(msg).append("*");
		tag_t query = NULLTAG, *tags;
		map<string, tag_t> map_revs;
		//fields.put("描述", "*" + item_id + "*" + zt2_TYJNo + "*");
		ITKCALL(QRY_find2("chint_query_material_test", &query));
		char* qry_entries[1] = { "描述" }, *qry_values[1] = { (char *)queryMsg.c_str() };
		int n_found;
		ITKCALL(QRY_execute(query, 1, qry_entries, qry_values, &n_found, &tags));
		WriteTcLog("n_found===>%d %s \n", n_found, queryMsg.c_str());
		if (n_found > 0) {
			return tags[0];
		}
	}
	if (strstr(bpNo.c_str(), "-") != NULL) {
		Split(bpNo, "-", vec2);
		bpNo = vec2[0].append("-").append(idss).append("-").append(vec2[1]);
	}
	string materialMark = zt2_MaterialMark;//rev.getProperty("zt2_MaterialMark"); // 非必填

	if (materialMark.compare("--") == 0) {
		materialMark = "";
	}
	// 产品型号 //所属产品
	string productModel = zt2_ProductModel;//rev.getProperty("zt2_ProductModel");
	string teRe = "";
	string state = ""; // 申请时为空
	string wbs = "";
	string product = "";
	string user = user_id;
	string time = now;
	string condition = "审核中";// 默认审核中
	string desc = object_desc;// properties[5];//rev.getProperty("object_desc");
	//for (int i = 0; i < specs.size(); i++) {
	string json = "{";
	string sql22 = "select CHINT_MATERIAL_SEQ.nextval as sid from dual";
	int colmun2 = 0, count2 = 0;
	char*** outputValue2 = NULL;
	printf("search1");
	QuerySQLNoInputParam((char*)sql22.c_str(), &colmun2, &count2, &outputValue2);
	char* projn = "";
	if (count2 > 0) {
		projn = outputValue2[0][0];
	}
	WriteTcLog("projn===>%s\n", projn);
	json.append("\"Code\":\"").append(projn).append("\",");
	//string spec = specs[i]; // 非必填
	string feature = "\"Feature\":{";
	for (int j = 0; j < m_prds.size(); j++) {
		PRD prd = m_prds[j];
		//System.out.println(prd.prdFeatureCode + "-" + prd.featureName);
		if (strstr(prd.featureName.c_str(), "材质") != NULL) {
			feature.append("\"").append(prd.prdFeatureCode).append("\":\"")
				.append(zt2_MaterialMark).append("\",");
		}
		else if (strstr(prd.featureName.c_str(), "名称") != NULL) {
			feature.append("\"").append(prd.prdFeatureCode).append("\":\"")
				.append(goodsName).append("\",");
		}
		else if (strstr(prd.featureName.c_str(), "型号") != NULL || strstr(prd.featureName.c_str(), "规格") != NULL) {
			feature.append("\"").append(prd.prdFeatureCode).append("\":\"")
				.append(spec).append("\",");
		}
		else if (strstr(prd.featureName.c_str(), "图样代号") != NULL) {
			feature.append("\"").append(prd.prdFeatureCode).append("\":\"")
				.append(bpNo).append("\",");
		}
		else if (strstr(prd.featureName.c_str(), "所属产品") != NULL) {
			feature.append("\"").append(prd.prdFeatureCode).append("\":\"")
				.append(zt2_ProductModel).append("\",");
		}
		else {
			feature.append("\"").append(prd.prdFeatureCode).append("\":\"").append("\",");
		}
	}
	
	if (strcmp(zt2_SurfaceTreatment, "") != 0) {
		feature.append("\"").append("F067").append("\":\"").append(zt2_SurfaceTreatment).append("\"");
	}
	else {
		feature = feature.substr(0, feature.length() - 1);
	}
	//feature.substr(0, feature.length());
	feature.append("},");
	string data = json;
	data.append("\"Data\":[{");
	data.append("\"PrhCode").append("\":\"").append(prhCode).append("\",");
	data.append("\"PmpcCode").append("\":\"").append(pmpcCode).append("\",");
	data.append("\"PmpcType").append("\":\"").append("ZPFG").append("\",");//pmpcType
	data.append("\"UnitCode").append("\":\"").append(unitCode).append("\",");
	data.append("\"CompanyCode").append("\":\"").append(companyCode).append("\",");
	data.append("\"UserCode").append("\":\"").append(user).append("\",");
	data.append("\"MP").append("\":\"").append("M").append("\",");//mp
	data.append(feature);
	data.append("\"ProductGroupCode").append("\":\"").append("\",");
	data.append("\"AssistUnitCode").append("\":\"").append("\",");
	data.append("\"UnitQty").append("\":\"").append("\",");
	data.append("\"AssistUnitQty").append("\":\"").append("\",");
	data.append("\"Desc").append("\":\"").append(desc).append("\"");
	data.append("}]}");
	jsons.push_back(data);
	tag_t newItem, newRev, pitem;
	ITKCALL(ITEM_create_item(NULL, goodsName.c_str(), "Part", NULL, &newItem, &newRev));
	AOM_lock(newItem);
	AOM_lock(newRev);
	ITKCALL(AOM_set_value_string(newRev, "zt2_Factory", groupId.c_str()));
	ITKCALL(AOM_set_value_string(newRev, "object_desc", spec.c_str()));
	ITKCALL(AOM_set_value_string(newRev, "zt2_ClassificationCode", "230101001"));
	char* zt2_unit, *newUid;
	ITK__convert_tag_to_uid(newRev, &newUid);
	ITKCALL(ITEM_ask_item_of_rev(rev, &pitem));
	ITKCALL(AOM_ask_value_string(pitem, "zt2_unit", &zt2_unit));
	ITKCALL(AOM_set_value_string(newItem, "zt2_unit", zt2_unit));

	tag_t defGroup;
	ITKCALL(AOM_ask_value_tag(dcproxy, "default_group", &defGroup));
	ITKCALL(AOM_set_ownership(newItem, dcproxy, defGroup));
	ITKCALL(AOM_set_ownership(newRev, dcproxy, defGroup));
	AOM_save(newRev);
	AOM_unlock(newRev);
	AOM_save(newItem);
	AOM_unlock(newItem);
	char selectGyId[400];
	sprintf(selectGyId, insertSql.c_str(), projn, newUid, pmpcCode.c_str(), "", goodsName.c_str(), "ST", companyCode.c_str(),
		bpNo.c_str(), spec.c_str(), "", "", user_id, now.c_str(), "审核中", "");
	WriteTcLog("selectGyId===>%s", selectGyId);
	ExecuteSQLNoInputParam(selectGyId);
	ExecuteSQLNoInputParam("commit");
	return newRev;
	/*uid = "";
	Object params[] = new Object[15];
	params[0] = code;
	params[1] = uid;
	params[2] = pmpcCode;
	params[3] = goodsCode;
	params[4] = goodsName;
	params[5] = unitCode;
	params[6] = companyCode;
	params[7] = bpNo;
	params[8] = spec;
	params[9] = teRe;
	params[10] = state;
	params[11] = user;
	params[12] = time;
	params[13] = condition;
	params[14] = "";*/
}
string getXqName(char *name) {
	string xq = "";
	if (strstr(name, "A相")!=NULL) {
		xq = "A";
	}else if (strstr(name, "B相") != NULL) {
		xq = "B";
	}
	else if (strstr(name, "C相") != NULL) {
		xq = "C";
	}
	else if (strstr(name, "D相") != NULL) {
		xq = "D";
	}
	else if (strstr(name, "E相") != NULL) {
		xq = "E";
	}
	return xq;
}

/**
 * 把线圈子项添加到A项线圈下面
 * @param c_line_tags 子行
 * @param c_line_count 子行数量
 * @param len 拆分数量
 * @param newPAmatnr 新的A项线圈
 * @param lastFlag 
 */
void addToAmatnr(tag_t *c_line_tags, int c_line_count, int len, tag_t newPAmatnr,boolean lastFlag) {

	tag_t mantr = newPAmatnr, ebom_window = NULLTAG, bom_line = NULLTAG;
	tag_t* bvr_list = NULL;
	int bvr_count = 0;
	ITKCALL(ITEM_rev_list_bom_view_revs(mantr, &bvr_count, &bvr_list));
	if (bvr_count == 0) {
		tag_t newView, newViewBvr, pitem;
		ITKCALL(ITEM_ask_item_of_rev(mantr, &pitem));
		ITKCALL(PS_create_bom_view(NULL, NULL, NULL, pitem, &newView));
		AOM_save(newView);
		(AOM_unlock(newView));//20241211
		ITKCALL(PS_create_bvr(newView, NULL, NULL, FALSE, mantr, &newViewBvr));
		AOM_save(newViewBvr);
		(AOM_unlock(newViewBvr));//20241211
		AOM_save(mantr);
		(AOM_unlock(mantr));//20241211
	}
	
	ITKCALL(BOM_create_window(&ebom_window));
	ITKCALL(BOM_set_window_top_line(ebom_window, NULL, mantr, NULLTAG, &bom_line));
	char *name;
	ITKCALL(AOM_ask_value_string(mantr,"object_name",&name));
	string xqType = getXqName(name); //ABCDE
	for (int i = 0; i < c_line_count; i++) {
		tag_t newChild;
		char* oldQty,*seqNo,*remark,*bl_line_name;
		ITKCALL(AOM_ask_value_string(c_line_tags[i], "ZT2_Remark", &remark));
		string msg = getRemarkMsg(remark,len);
		int xqLen = len;
		if (msg.length()>0) {
			xqLen = msg.length();
			if (tc_strstr(msg.c_str(), xqType.c_str()) == NULL) {
				continue;
			}
		}
		ITKCALL(BOM_line_copy(bom_line, c_line_tags[i], NULLTAG, &newChild));
		ITKCALL(AOM_ask_value_string(c_line_tags[i], "bl_quantity", &oldQty));
		ITKCALL(AOM_ask_value_string(c_line_tags[i], "bl_sequence_no", &seqNo));
		ITKCALL(AOM_ask_value_string(c_line_tags[i], "bl_line_name", &bl_line_name));
		if (lastFlag && strstr(bl_line_name, "线") != NULL) {
			double blQty = atof(oldQty);
			int num = blQty / xqLen;
			double fmodVal = fmod(blQty, xqLen);
			double lastVal = num + fmodVal;
			string numNew = to_string(lastVal);
			(AOM_lock(newChild));
			ITKCALL(AOM_set_value_string(newChild, "bl_quantity", numNew.c_str()));
			ITKCALL(AOM_set_value_string(newChild, "bl_sequence_no", seqNo));
			AOM_save(newChild);
			AOM_unlock(newChild);
		}
		else {
			int blQty = atoi(oldQty);
			int num = blQty / xqLen;
			string numNew = to_string(num);
			AOM_lock(newChild);
			ITKCALL(AOM_set_value_string(newChild, "bl_quantity", numNew.c_str()));
			ITKCALL(AOM_set_value_string(newChild, "bl_sequence_no", seqNo));
			AOM_save(newChild);
			AOM_unlock(newChild);
		}
		
	}

	ITKCALL(BOM_save_window(ebom_window));
	ITKCALL(BOM_close_window(ebom_window));
}
char* G2U222(const char* gb2312)
{
	int len = MultiByteToWideChar(CP_ACP, 0, gb2312, -1, NULL, 0);
	wchar_t* wstr = new wchar_t[len + 1];
	memset(wstr, 0, len + 1);
	MultiByteToWideChar(CP_ACP, 0, gb2312, -1, wstr, len);
	len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
	char* str = new char[len + 1];
	memset(str, 0, len + 1);
	WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, len, NULL, NULL);
	if (wstr) delete[] wstr;
	return str;
}
//childPm存放线圈的E物料，P物料
void replaceBom(EBomBean& childPm, map<string, tag_t>& map, int len, tag_t dcproxy, tag_t &topPrev) {

	vector<EBomBean> parentBeans = childPm.parentBean;

	//另存P物料 放到关系文件夹下
	saveAsCycle(childPm, map, topPrev);

	printf("saveAsCycle OVER \n");
	tag_t owning_group, owning_user;
	char* grpId, *user_id,*uidTest;
	int num = 0;
	tag_t* mantrs, designRev;
	string errBuff;
	ITK__convert_tag_to_uid(childPm.eRev, &uidTest);
	printf("uidTest OVER %s \n", uidTest);
	ITKCALL(AOM_ask_value_tags(childPm.eRev, "TC_Is_Represented_By", &num, &mantrs));
	if (num > 0) {
		tag_t tzRev = mantrs[0];
		ITKCALL(AOM_ask_value_tag(tzRev, "owning_user", &owning_user));
		ITKCALL(AOM_ask_value_tag(tzRev, "owning_group", &owning_group));
		ITKCALL(AOM_ask_value_string(owning_group, "name", &grpId));
		ITKCALL(AOM_ask_value_string(owning_user, "user_id", &user_id));
		vector<string> specs;
		//获取物料属性规格
		getSpecs(tzRev, specs);
		printf("获取规格结束 \n");
		time_t now;
		struct tm* p;
		time(&now);
		p = localtime(&now);
		char buffer[80];
		sprintf_s(buffer, "%04d%02d%02d %02d:%02d:%02d", 1900 + p->tm_year, p->tm_mon + 1, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec);
		string now1 = buffer;
		vector<string> jsons;
		char* names[5] = { "A相","B相","C相","D相","E相" };
		char* idss[5] = { "A","B","C","D","E" };
		tag_t axqPmatnr = childPm.pRev[0]; //另存的线圈P物料

		int bvr_count = 0, c_line_count;
		tag_t ebom_window = NULLTAG;
		tag_t bom_line = NULLTAG, *c_line_tags;
		tag_t* bvr_list = NULL;
		ITKCALL(ITEM_rev_list_bom_view_revs(axqPmatnr, &bvr_count, &bvr_list));
		printf("bvr_count=%d\n", bvr_count);
		//没有物料视图的时候需要创建一个
		if (bvr_count == 0) {
			tag_t newView, newViewBvr, pitem;
			ITEM_ask_item_of_rev(axqPmatnr, &pitem);
			ITKCALL(PS_create_bom_view(NULL, NULL, NULL, pitem, &newView));
			AOM_save(newView);
			(AOM_unlock(newView));//20241211
			ITKCALL(PS_create_bvr(newView, NULL, NULL, FALSE, axqPmatnr, &newViewBvr));
			AOM_save(newViewBvr);
			(AOM_unlock(newViewBvr));//20241211
			AOM_save(axqPmatnr);
			(AOM_unlock(axqPmatnr));//20241211
			tag_t dsuser, *structure_revisions, *bom_view_tags;
			ITKCALL(AOM_ask_value_tag(tzRev, "owning_user", &dsuser));
			tag_t defGroup;
			ITKCALL(AOM_ask_value_tag(dsuser, "default_group", &defGroup));
			ITKCALL(AOM_set_ownership(newView, dsuser, defGroup));
			ITKCALL(AOM_set_ownership(newViewBvr, dsuser, defGroup));
			//return;
			ITKCALL(ITEM_rev_list_bom_view_revs(axqPmatnr, &bvr_count, &bvr_list));
		}
		ITKCALL(BOM_create_window(&ebom_window));
		ITKCALL(BOM_set_window_top_line_bvr(ebom_window, bvr_list[0], &bom_line)); //顶层bom获取
		//ITKCALL(AOM_ask_value_tag(bom_line, "bl_line_object", &mantr));
		//线圈转PBOM时候的特殊处理:申请物料 A、B、C项线圈 然后把原来的线圈的子项拆分数量复制
		ITKCALL(BOM_line_ask_all_child_lines(bom_line, &c_line_count, &c_line_tags));
		WriteTcLog("int===>%d\n", len);
		vector<tag_t> newPAmatnrs;
		for (int i = 0; i < len; i++) {
			//创建A项物料
			WriteTcLog("names[i]===>%s\n", names[i]);
			tag_t newPAmatnr = send1(tzRev, now1, user_id, jsons, grpId, specs[0], names[i], idss[i], dcproxy);
			newPAmatnrs.push_back(newPAmatnr);
			//如果名称中包含 线的 拆分后多余的放到最后
			boolean lastFlag = false;
			if (i == len - 1) {
				lastFlag = true;
			}
			addToAmatnr(c_line_tags, c_line_count, len, newPAmatnr, lastFlag);
			//ITKCALL(BOM_line_add(bom_line, NULLTAG, newPAmatnr, NULLTAG, &bomLineAdd));
		}
		for (int i = 0; i < c_line_count; i++) {
			ITKCALL(BOM_line_cut(c_line_tags[i]));
		}
		for (int t = 0; t < newPAmatnrs.size(); t++) {
			tag_t bomLineAdd = NULLTAG;
			ITKCALL(BOM_line_add(bom_line, NULLTAG, newPAmatnrs[t], NULLTAG, &bomLineAdd));
			char *name = NULL;
			ITKCALL(AOM_ask_value_string(newPAmatnrs[t], "object_name", &name));
			string seqNo = "";
			if (tc_strstr(name, "A相") != NULL) {
				seqNo = "10";
			}else if (tc_strstr(name, "B相") != NULL) {
				seqNo = "20";
			}
			else if(tc_strstr(name, "C相") != NULL) {
				seqNo = "30";
			}
			ITKCALL(AOM_set_value_string(bomLineAdd, "bl_sequence_no", seqNo.c_str()));
		}
		//ITKCALL(AOM_save(bom_line));
		ITKCALL(BOM_save_window(ebom_window));
		ITKCALL(BOM_close_window(ebom_window));
		for (int i = 0; i < jsons.size(); i++) {
			WriteTcLog("jsons ===> %s \n", jsons[i].c_str());
			string url = "http://10.128.20.35:9002/Post/PLM_Goods";
			string jsonUf = G2U222(jsons[i].c_str());
			//调用接口申请物料
			string msg = callHttpserver(jsonUf, url);
			WriteTcLog("result===>%s\n", msg.c_str());
		}
	}
}
//获取分类属性 判断是否整除
int getClassVal2(tag_t topItem, string& errMessage) {
	tag_t top_classificationObject;
	ITKCALL(ICS_ask_classification_object(topItem, &top_classificationObject));
	if (top_classificationObject == NULL_TAG)
	{
		errMessage.append("顶层对象没有发送到分类\n");
		return  0;
	}
	char* top_class_id = NULL, *top_class_name = NULL;
	//ICS_ask_class_of_classification_obj(top_classificationObject, &top_class_tag);
	//ICS_ask_id_name(top_class_tag, &top_class_id, &top_class_name);
	printf("BOM TOP LINE CLASS ID = %s | NAME = %s \n", top_class_id, top_class_name);
	int n_attrs;
	char** attr_names;
	char** attr_vals;
	ITKCALL(ICS_ask_attributes_of_classification_obj(top_classificationObject, &n_attrs, &attr_names, &attr_vals));
	cout << n_attrs << endl;
	int num = 1;
	for (int ii = 0; ii < n_attrs; ii++)
	{
		printf("attr_names[ii]==>%sTTT\n", attr_names[ii]);
		printf("attr_vals[ii]==>%sTTT\n", attr_vals[ii]);
		if (strcmp(attr_names[ii], "相数") == 0) {
			if (strcmp(attr_vals[ii], "") == 0) {
				errMessage.append("分类属性相数为空，请检查。\n");
				return 0;
			}
			else {
				printf("111[ii]==TTT\n");
				if (strstr(attr_vals[ii],"3") != NULL) {
					num = 3;
				}else if (strstr(attr_vals[ii], "1") != NULL) {
					num = 1;
				}
				else if (strstr(attr_vals[ii], "5") != NULL) {
					num = 5;
				}
				//num = atoi(attr_vals[ii]);
			}
			break;
		}
	}
	return num;
}

string getRemarkMsg(string remark,int len) {
	char* idss[5] = { (char*)"A",(char*)"B",(char*)"C",(char*)"D",(char*)"E" };
	//tring x = "9A9.1B2C3";
	string xs = "";
	for (int i = 0; i < len; i++) {
		if (strstr(remark.c_str(), idss[i]) != NULL) {
			xs.append(idss[i]);
		}
	}
	return xs;
}
/**
 * 记遍历EBOM
 * @param tag_t EBOM头
 * @param parentBean EBOM对应的PBOM结构
 * @param len 根据分类属性项数获取的拆分数
 * @param pErev EBOM对应的E物料
 * @param errBuff 记录错误信息
 */
void recyReadEBom(tag_t pLine, EBomBean parentBean, vector<EBomBean>& beans, int len, tag_t pErev, string& errBuff) {

	int c_line_count, cnt2, numFac, cnt3;
	tag_t* c_line_tags;
	ITKCALL(BOM_line_ask_all_child_lines(pLine, &c_line_count, &c_line_tags));
	char* sffc, *name, *pRevId, ** sealeds, ** factorys,**procureType;
	ITKCALL(AOM_ask_value_string(pErev, "item_id", &pRevId));
	ITKCALL(AOM_ask_value_string(pErev, "object_name", &name));
	ITKCALL(AOM_ask_value_string(pErev, "zt2_State", &sffc));
	if (strcmp(sffc, "D1") == 0 || strcmp(sffc, "封存") == 0) {
		errBuff.append("物料:").append(pRevId).append("/").append(name).append("已封存无法转换PBOM.\n");
		//return;
	}
	ITKCALL(AOM_ask_value_strings(pErev, "zt2_SZProcuretype", &cnt3, &procureType)); //包含自制
	ITKCALL(AOM_ask_value_strings(pErev, "zt2_SZSealedornot", &cnt2, &sealeds));
	ITKCALL(AOM_ask_value_strings(pErev, "zt2_SZFactory", &numFac, &factorys));
	boolean flagWh = false;
	//检查物料是否符合条件
	for (int i = 0; i < numFac; i++) {
		if (strcmp(factorys[i], "M060") == 0 && cnt2 > i) {
			flagWh = true;
			if (strcmp(sealeds[i], "Y") == 0) {
				errBuff.append("物料:").append(pRevId).append("/").append(name).append("已封存无法转换PBOM.\n");
				//return;
			}
			if (cnt3 > i && strcmp(procureType[i], "/") == 0) {
				errBuff.append("物料:").append(pRevId).append("/").append(name).append("物料不可用无法转换PBOM.\n");
			}
		}
	}
	if (!flagWh && strstr(name,"总装图")==NULL) {
		//errBuff.append("物料:").append(pRevId).append("/").append(name).append("物料视图没有维护,请检查.\n");
	}
	for (int i = 0; i < c_line_count; i++) {

		tag_t c_line_tag = c_line_tags[i], eRev;
		ITKCALL(AOM_ask_value_tag(c_line_tag, "bl_line_object", &eRev));
		EBomBean cBean;
		cBean.eRev = eRev;
		cBean.eBomline = c_line_tag;
		cBean.parentBean.push_back(parentBean);
		//获取图纸对象 判断是否是线圈，线圈要整除
		//如果判断正则表达式通过 加到beans下最后检查整除并搭建
		int num = 0;
		tag_t* mantrs;
		ITKCALL(AOM_ask_value_tags(eRev, "TC_Is_Represented_By", &num, &mantrs));
		if (num > 0) {
			char* id;
			ITKCALL(AOM_ask_value_string(mantrs[0], "item_id", &id));
			string item_id = id;
			smatch result;//regex qq_reg("^1ZDB5.*\\d{1,}1000X.*");
			bool ret = regex_match(item_id, result, qq_reg);
			if (ret) {
				char *zt2_ifpbom;
				ITKCALL(AOM_ask_value_string(eRev, "zt2_ifpbom", &zt2_ifpbom));
				if (zt2_ifpbom != NULL && strcmp(zt2_ifpbom, "P") == 0) {
					continue;
				}
				int cc_cnt;
				tag_t* cc_lines;
				ITKCALL(BOM_line_ask_all_child_lines(c_line_tag, &cc_cnt, &cc_lines));
				
				//线圈下对象检查是否可以整除 取总装图分类属性线圈项数  新增逻辑 拆解ZT2_Remark上包含ABC的 
				//12.4新增 物料下子件名称带 线 的，11.3 分成3，3，5.3
				for (int tt = 0; tt < cc_cnt; tt++) {
					tag_t cc_line = cc_lines[tt], c_eRev;
					char* bl_quantity = NULL, *pId = NULL, *c_pId, *remark = NULL, *bl_line_name = NULL;
					ITKCALL(AOM_ask_value_string(eRev, "item_id", &pId));
					ITKCALL(AOM_ask_value_string(cc_line, "bl_quantity", &bl_quantity));
					ITKCALL(AOM_ask_value_string(cc_line, "ZT2_Remark", &remark));
					ITKCALL(AOM_ask_value_string(cc_line, "bl_line_name", &bl_line_name));
					ITKCALL(AOM_ask_value_tag(cc_line, "bl_line_object", &c_eRev));
					ITKCALL(AOM_ask_value_string(c_eRev, "item_id", &c_pId));
					printf("c_pId===>  %s bl_quantity ==> %s  len==> %d \n", c_pId, bl_quantity, len);
					if (tc_strcmp(bl_quantity, "") == 0) {
						errBuff.append("P类物料:").append(pId).append("下子件").append(c_pId)
							.append("无法整除，请检查。").append("\n");
					}
					else {
						string markMsg = getRemarkMsg(remark, len);
						printf("markMsg===>  %s \n", markMsg.c_str());
						if (markMsg.length() == 0) {
							int blQty = atoi(bl_quantity);
							if (blQty % len != 0 && tc_strstr(bl_line_name, "线") == NULL) {
								errBuff.append("P类物料:").append(pId).append("下子件").append(c_pId)
									.append("无法整除，请检查。").append("\n");
							}
							else {
								newCBean aBean;
								aBean.num = blQty / len;
								aBean.cLine = cc_line;
								cBean.c_lines.push_back(aBean);
							}
						}
						else {
							int blQty = atoi(bl_quantity);
							if (blQty % markMsg.length() != 0 && tc_strstr(bl_line_name, "线") == NULL) {
								errBuff.append("P类物料:").append(pId).append("下子件").append(c_pId)
									.append("无法整除，请检查。").append("\n");
							}
							else {
								newCBean aBean;
								aBean.num = blQty / markMsg.length();
								aBean.cLine = cc_line;
								cBean.c_lines.push_back(aBean);
							}
						}
						
					}
				}
				beans.push_back(cBean);
				continue;
			}
		}
		recyReadEBom(c_line_tag, cBean, beans, len, eRev, errBuff);
		//判断子件数量是否整除 线圈数量
	}

}
//获取dcproxy用户
tag_t findDcUser() {
	tag_t* tags;
	tag_t query = NULLTAG;
	//查询所有符合的物料编码
	ITKCALL(QRY_find2("__WEB_find_user", &query));
	if (query == NULLTAG) {
		cout << "没有找到当前查询" << endl;
	}
	int cnt;
	char** qry_entries1, **qry_values2;
	ITKCALL(QRY_find_user_entries(query, &cnt, &qry_entries1, &qry_values2));
	char * qry_values[1] = { "dcproxy" };
	int n_found;
	ITKCALL(QRY_execute(query, 1, qry_entries1, qry_values, &n_found, &tags));
	if (n_found == 0) {
		return NULLTAG;
	}
	else {
		return tags[0];
	}
}
class E2PBean //以class 开头
{
public:
	string key;//wbs号+物料号组成的标识
	tag_t pMantr=NULLTAG; // p物料 发布升版，没发布更新，取最新版本 (不带P的移除添加)
	string prevId = "";
	tag_t eMantr; // e物料
	string erevId = "";
public:
	//定义成员函数
	void isSameKey(string newKey)
	{
		if (key.compare(newKey) == 0) {
			//一样的
		}
	}

};
struct EBomUpBean
{
	string blQuantity;
	string matnrNo;
	tag_t bomline;
	tag_t mantr;
	vector<EBomUpBean> parentBean; //遍历EBOM时候的父级
	vector<newCBean> c_lines; //EBOM中的子件 只有线圈用
};
//遍历EBOM 存放所有EBOM的更新时使用
void updatePbomCycle(tag_t eLine, string &errBuff, int len, EBomUpBean &upBean) {
	int c_line_count;
	tag_t *c_line_tags;
	ITKCALL(BOM_line_ask_all_child_lines(eLine, &c_line_count, &c_line_tags));
	//printf("upBean===>%s\n", upBean.matnrNo.c_str());
	for (int i = 0; i < c_line_count; i++) {
		char* ifpBom, *matnrNo, *childQty;
		tag_t c_line_tag = c_line_tags[i], eRev;
		ITKCALL(AOM_ask_value_tag(c_line_tag, "bl_line_object", &eRev));
		ITKCALL(AOM_ask_value_string(c_line_tag, BL_QUANTITY, &childQty));
		ITKCALL(AOM_ask_value_string(eRev, "zt2_ifpbom", &ifpBom));
		ITKCALL(AOM_ask_value_string(eRev, "zt2_MaterialNo", &matnrNo));

		EBomUpBean cBean;
		cBean.matnrNo = matnrNo;
		//printf("CChild===>%s\n", matnrNo);
		cBean.blQuantity = childQty;
		cBean.mantr = eRev; //E物料
		cBean.bomline = c_line_tag;
		int num = 0;
		tag_t* mantrs;
		ITKCALL(AOM_ask_value_tags(eRev, "TC_Is_Represented_By", &num, &mantrs));
		if (num == 1) {
			char* id;
			ITKCALL(AOM_ask_value_string(mantrs[0], "item_id", &id));
			string item_id = id;
			smatch result;
			bool ret = regex_match(item_id, result, qq_reg);
			if (ret) {
				char* zt2_ifpbom;
				ITKCALL(AOM_ask_value_string(eRev, "zt2_ifpbom", &zt2_ifpbom));
				if (zt2_ifpbom != NULL && strcmp(zt2_ifpbom, "P") == 0) {
					continue;
				}
				int cc_cnt;
				tag_t* cc_lines;
				ITKCALL(BOM_line_ask_all_child_lines(c_line_tag, &cc_cnt, &cc_lines));
				printf("cc_cnt===>  %d item_id ==> %s \n", cc_cnt, id);
				//新增逻辑
				for (int tt = 0; tt < cc_cnt; tt++) {
					tag_t cc_line = cc_lines[tt], c_eRev;
					char* bl_quantity, *pId, *c_pId,*bl_line_name,*remark;
					ITKCALL(AOM_ask_value_string(eRev, "item_id", &pId));
					ITKCALL(AOM_ask_value_string(cc_line, "bl_quantity", &bl_quantity));
					ITKCALL(AOM_ask_value_tag(cc_line, "bl_line_object", &c_eRev));
					ITKCALL(AOM_ask_value_string(cc_line, "bl_line_name", &bl_line_name));
					ITKCALL(AOM_ask_value_string(c_eRev, "item_id", &c_pId));
					ITKCALL(AOM_ask_value_string(cc_line, "ZT2_Remark", &remark));
					printf("c_pId===>  %s bl_quantity ==> %s  len==> %d \n", c_pId, bl_quantity, len);
					if (tc_strcmp("bl_quantity", "") == 0) {
						errBuff.append("P类物料:").append(pId).append("下子件").append(c_pId)
							.append("无法整除，请检查。").append("\n");
					}
					else {
						string markMsg = getRemarkMsg(remark, len);
						printf("markMsg===>  %s \n", markMsg.c_str());
						if (markMsg.length() == 0) {
							int blQty = atoi(bl_quantity);
							if (blQty % len != 0 && tc_strstr(bl_line_name, "线") == NULL) {
								errBuff.append("P类物料:").append(pId).append("下子件").append(c_pId)
									.append("无法整除，请检查。").append("\n");
							}
							else {
								newCBean aBean;
								aBean.num = blQty / len;
								aBean.cLine = cc_line;
								aBean.blQty = blQty;
								cBean.c_lines.push_back(aBean);
							}
						}
						else {
							int blQty = atoi(bl_quantity);
							if (blQty % markMsg.length() != 0 && tc_strstr(bl_line_name, "线") == NULL) {
								errBuff.append("P类物料:").append(pId).append("下子件").append(c_pId)
									.append("无法整除，请检查。").append("\n");
							}
							else {
								newCBean aBean;
								aBean.num = blQty / len;
								aBean.blQty = blQty;
								aBean.cLine = cc_line;
								cBean.c_lines.push_back(aBean);
							}
						}
					}
				}
				//beans.push_back(cBean);
				//continue;
			}
		}
		updatePbomCycle(c_line_tag, errBuff, len, cBean);
		upBean.parentBean.push_back(cBean);
	}
}
boolean checkName(char* name) {

	if (strstr(name, "A相") != NULL || strstr(name, "B相") != NULL || strstr(name, "C相") != NULL
		|| strstr(name, "E相") != NULL || strstr(name, "D相") != NULL) {
		return true;
	}
	else {
		return false;
	}
}
tag_t saveAsUpdate(tag_t eRev, char *uid, tag_t pLine) {
	char* newid = NULL;
	logical isModified = FALSE;
	tag_t item_type_tag, newItem, newRev;
	ITKCALL(TCTYPE_ask_type("Item", &item_type_tag));
	ITKCALL(USER_new_item_id(NULLTAG, item_type_tag, &isModified, &newid));
	/*ITKCALL(NR_next_value("MEProcess", "item_id", NULLTAG, "", "", "",
		NULLTAG, "", "", &next_id));*/
	printf("next_id==>%s\n", newid);
	ITKCALL(ITEM_copy_item(eRev, newid, NULL, &newItem, &newRev));
	//ITKCALL(AOM_set_value_string(newRev, "zt2_PMaterial", "PBOM"));
	char* matnrNo;
	ITKCALL(AOM_ask_value_string(eRev, "zt2_MaterialNo", &matnrNo));
	AOM_lock(newRev);

	ITKCALL(AOM_set_value_string(newRev, "zt2_ifpbom", "P"));
	ITKCALL(AOM_set_value_string(newRev, "zt2_MaterialNo", matnrNo));
	AOM_save(newRev);
	AOM_unlock(newRev);

	int num = 0, revNum = 0, tagNum = 0;
	tag_t* mantrs, dsuser, *structure_revisions, *bom_view_tags;
	ITKCALL(AOM_ask_value_tags(eRev, "TC_Is_Represented_By", &num, &mantrs));
	if (num > 0) {
		ITKCALL(AOM_ask_value_tags(newRev, "structure_revisions", &revNum, &structure_revisions));
		ITKCALL(AOM_ask_value_tags(newRev, "bom_view_tags", &tagNum, &bom_view_tags));
		ITKCALL(AOM_ask_value_tag(mantrs[0], "owning_user", &dsuser));
		tag_t defGroup;
		ITKCALL(AOM_ask_value_tag(dsuser, "default_group", &defGroup));
		ITKCALL(AOM_set_ownership(newItem, dsuser, defGroup));
		ITKCALL(AOM_set_ownership(newRev, dsuser, defGroup));
		if (revNum > 0) {
			ITKCALL(AOM_set_ownership(structure_revisions[0], dsuser, defGroup));
		}
		if (tagNum > 0) {
			ITKCALL(AOM_set_ownership(bom_view_tags[0], dsuser, defGroup));
		}
	}
	{
		//ITKCALL(BOM_line_replace(newChild, NULLTAG, newRev, NULLTAG));
		int bvr_count = 0, c_line_count;
		tag_t ebom_window = NULLTAG;
		tag_t bom_line = NULLTAG, *c_line_tags;
		ITKCALL(BOM_create_window(&ebom_window));
		tag_t* bvr_list = NULL;
		ITKCALL(ITEM_rev_list_bom_view_revs(pLine, &bvr_count, &bvr_list));
		printf("bvr_count=%d\n", bvr_count);

		ITKCALL(BOM_set_window_top_line_bvr(ebom_window, bvr_list[0], &bom_line)); //顶层bom获取
		//ITKCALL(AOM_ask_value_tag(bom_line, "bl_line_object", &mantr));
		ITKCALL(BOM_line_ask_all_child_lines(bom_line, &c_line_count, &c_line_tags));

		for (int ind = 0; ind < c_line_count; ind++) {
			tag_t c_line_tag = c_line_tags[ind], mantr;
			ITKCALL(AOM_ask_value_tag(c_line_tag, "bl_line_object", &mantr));
			char* eRevUid2;
			ITK__convert_tag_to_uid(mantr, &eRevUid2);
			if (strcmp(eRevUid2, uid) == 0) {
				ITKCALL(BOM_line_replace(c_line_tag, NULLTAG, newRev, NULLTAG));
			}
		}
		ITKCALL(BOM_save_window(ebom_window));
		ITKCALL(BOM_close_window(ebom_window));
	}
	return newRev;
}
/**
 * 另存E物料转为P物料，并在BOM中替换
 * @param eRev 要另存的E物料
 * @param newChild 判断单元是否多次出现
 */
tag_t saveAsUpdate(tag_t eRev, tag_t newChild) {
	char* newid = NULL;
	logical isModified = FALSE;
	tag_t item_type_tag, newItem, newRev;
	ITKCALL(TCTYPE_ask_type("Item", &item_type_tag));
	ITKCALL(USER_new_item_id(NULLTAG, item_type_tag, &isModified, &newid));
	/*ITKCALL(NR_next_value("MEProcess", "item_id", NULLTAG, "", "", "",
		NULLTAG, "", "", &next_id));*/
	printf("next_id==>%s\n", newid);
	ITKCALL(ITEM_copy_item(eRev, newid, NULL, &newItem, &newRev));
	//ITKCALL(AOM_set_value_string(newRev, "zt2_PMaterial", "PBOM"));
	char* matnrNo;
	ITKCALL(AOM_ask_value_string(eRev, "zt2_MaterialNo", &matnrNo));
	AOM_lock(newRev);

	ITKCALL(AOM_set_value_string(newRev, "zt2_ifpbom", "P"));
	ITKCALL(AOM_set_value_string(newRev, "zt2_MaterialNo", matnrNo));
	AOM_save(newRev);
	AOM_unlock(newRev);

	int num = 0, revNum = 0, tagNum = 0;
	tag_t* mantrs, dsuser, *structure_revisions, *bom_view_tags;
	ITKCALL(AOM_ask_value_tags(eRev, "TC_Is_Represented_By", &num, &mantrs));
	if (num > 0) {
		ITKCALL(AOM_ask_value_tags(newRev, "structure_revisions", &revNum, &structure_revisions));
		ITKCALL(AOM_ask_value_tags(newRev, "bom_view_tags", &tagNum, &bom_view_tags));
		ITKCALL(AOM_ask_value_tag(mantrs[0], "owning_user", &dsuser));
		tag_t defGroup;
		ITKCALL(AOM_ask_value_tag(dsuser, "default_group", &defGroup));
		ITKCALL(AOM_set_ownership(newItem, dsuser, defGroup));
		ITKCALL(AOM_set_ownership(newRev, dsuser, defGroup));
		if (revNum > 0) {
			ITKCALL(AOM_set_ownership(structure_revisions[0], dsuser, defGroup));
		}
		if (tagNum > 0) {
			ITKCALL(AOM_set_ownership(bom_view_tags[0], dsuser, defGroup));
		}
	}
	{
		ITKCALL(BOM_line_replace(newChild, NULLTAG, newRev, NULLTAG));
	}
	return newRev;
}

void createAXxq(tag_t eRev, tag_t pRev, int len, tag_t dcproxy) {
	tag_t owning_group, owning_user;
	char* grpId = NULL, *user_id = NULL, *os = NULL;
	int num = 0;
	tag_t* mantrs, designRev;
	string errBuff;
	ITKCALL(AOM_ask_value_string(eRev, "object_string", &os));
	WriteTcLog("createAXxq:%s", os);
	ITKCALL(AOM_ask_value_tags(eRev, "TC_Is_Represented_By", &num, &mantrs));
	if (num > 0) {
		tag_t tzRev = mantrs[0];
		ITKCALL(AOM_ask_value_tag(tzRev, "owning_user", &owning_user));
		ITKCALL(AOM_ask_value_tag(tzRev, "owning_group", &owning_group));
		ITKCALL(AOM_ask_value_string(owning_group, "name", &grpId));
		ITKCALL(AOM_ask_value_string(owning_user, "user_id", &user_id));
		vector<string> specs;
		getSpecs(tzRev, specs);
		WriteTcLog("获取规格结束:%zd\n", specs.size());
		time_t now;
		struct tm* p;
		time(&now);
		p = localtime(&now);
		char buffer[80];
		sprintf_s(buffer, "%04d%02d%02d %02d:%02d:%02d", 1900 + p->tm_year, p->tm_mon + 1, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec);
		string now1 = buffer;
		vector<string> jsons;
		char* names[5] = { "A相","B相","C相","D相","E相" };
		char* idss[5] = { "A","B","C","D","E" };
		tag_t axqPmatnr = pRev; //另存的线圈P物料

		int bvr_count = 0, c_line_count;
		tag_t ebom_window = NULLTAG;
		tag_t bom_line = NULLTAG, *c_line_tags = NULLTAG;
		tag_t* bvr_list = NULL;
		ITKCALL(ITEM_rev_list_bom_view_revs(axqPmatnr, &bvr_count, &bvr_list));
		WriteTcLog("bvr_count=%d\n", bvr_count);

		if (bvr_count == 0) {
			tag_t newView = NULLTAG, newViewBvr = NULLTAG, pitem = NULLTAG;
			ITEM_ask_item_of_rev(axqPmatnr, &pitem);
			ITKCALL(PS_create_bom_view(NULL, NULL, NULL, pitem, &newView));
			AOM_save(newView);
			(AOM_unlock(newView));//20241211
			ITKCALL(PS_create_bvr(newView, NULL, NULL, FALSE, axqPmatnr, &newViewBvr));
			AOM_save(newViewBvr);
			(AOM_unlock(newViewBvr));//20241211
			AOM_save(axqPmatnr);
			(AOM_unlock(axqPmatnr));//20241211
			//return;
			tag_t dsuser = NULLTAG, *structure_revisions = NULLTAG, *bom_view_tags = NULLTAG;
			ITKCALL(AOM_ask_value_tag(tzRev, "owning_user", &dsuser));
			tag_t defGroup = NULLTAG;
			ITKCALL(AOM_ask_value_tag(dsuser, "default_group", &defGroup));
			ITKCALL(AOM_set_ownership(newView, dsuser, defGroup));
			ITKCALL(AOM_set_ownership(newViewBvr, dsuser, defGroup));
			ITKCALL(ITEM_rev_list_bom_view_revs(axqPmatnr, &bvr_count, &bvr_list));
		}
		ITKCALL(BOM_create_window(&ebom_window));
		ITKCALL(BOM_set_window_top_line_bvr(ebom_window, bvr_list[0], &bom_line)); //顶层bom获取
		//ITKCALL(AOM_ask_value_tag(bom_line, "bl_line_object", &mantr));
		ITKCALL(BOM_line_ask_all_child_lines(bom_line, &c_line_count, &c_line_tags));
		WriteTcLog("int===>%d\n", len);
		vector<tag_t> newPAmatnrs;
		for (int i = 0; i < len; i++) {
			//创建A项物料 idss[i]
			WriteTcLog("names[i]===>%s\n", names[i]);
			tag_t newPAmatnr = send1(tzRev, now1, user_id, jsons, grpId, specs[0], names[i], idss[i], dcproxy);
			newPAmatnrs.push_back(newPAmatnr);
			boolean lastFlag = false;
			if (i == len - 1) {
				lastFlag = true;
			}
			addToAmatnr(c_line_tags, c_line_count, len, newPAmatnr, lastFlag);
			//ITKCALL(BOM_line_add(bom_line, NULLTAG, newPAmatnr, NULLTAG, &bomLineAdd));
		}
		for (int i = 0; i < c_line_count; i++) {
			ITKCALL(BOM_line_cut(c_line_tags[i]));
		}
		for (int t = 0; t < newPAmatnrs.size(); t++) {
			tag_t bomLineAdd;
			ITKCALL(BOM_line_add(bom_line, NULLTAG, newPAmatnrs[t], NULLTAG, &bomLineAdd));
		}
		//ITKCALL(AOM_save(bom_line));
		ITKCALL(BOM_save_window(ebom_window));
		ITKCALL(BOM_close_window(ebom_window));
		for (int i = 0; i < jsons.size(); i++) {
			WriteTcLog("jsons ===> %s \n", jsons[i].c_str());
			string url = "http://10.128.20.35:9002/Post/PLM_Goods";
			string jsonUf = G2U222(jsons[i].c_str());
			string msg = callHttpserver(jsonUf, url);
			WriteTcLog("result===>%s\n", msg.c_str());
		}
	}
}
//添加A项线圈的子行
void addToAmatnrUp(vector<EBomUpBean> vecs, int len, tag_t newPAmatnr, boolean lastFlag) {

	tag_t mantr = newPAmatnr, ebom_window = NULLTAG, bom_line = NULLTAG;
	tag_t* bvr_list = NULL;
	int bvr_count;
	POM_AM__set_application_bypass(true);
	ITKCALL(ITEM_rev_list_bom_view_revs(mantr, &bvr_count, &bvr_list));
	if (bvr_count == 0) {
		tag_t newView = NULLTAG, newViewBvr = NULLTAG, pitem = NULLTAG;
		ITKCALL(ITEM_ask_item_of_rev(mantr, &pitem));
		ITKCALL(PS_create_bom_view(NULL, NULL, NULL, pitem, &newView));
		(AOM_save(newView));
		(AOM_unlock(newView));//20241211
		ITKCALL(PS_create_bvr(newView, NULL, NULL, FALSE, mantr, &newViewBvr));
		(AOM_save(newViewBvr));
		(AOM_unlock(newViewBvr));//20241211
		(AOM_save(mantr));
		(AOM_unlock(mantr));//20241211
	}
	ITKCALL(BOM_create_window(&ebom_window));
	ITKCALL(BOM_set_window_top_line(ebom_window, NULL, mantr, NULLTAG, &bom_line));
	char *os = NULL;
	ITKCALL(AOM_ask_value_string(bom_line, "object_string", &os));
	printf("bom_line====>%s\n", os);
	char *name;
	ITKCALL(AOM_ask_value_string(mantr, "object_name", &name));
	string xqType = getXqName(name); //ABCDE
	for (int i = 0; i < vecs.size(); i++) {
		tag_t newChild = NULLTAG;
		tag_t cline = vecs[i].bomline;

		char* oldQty, *seqNo, *remark,*bl_line_name;
		ITKCALL(AOM_ask_value_string(cline, "ZT2_Remark", &remark));
		string msg = getRemarkMsg(remark, len);
		int xqLen = len;
		if (msg.length() > 0) {
			xqLen = msg.length();
			if (strstr(msg.c_str(), xqType.c_str()) == NULL) {
				continue;
			}
		}
		ITKCALL(BOM_line_copy(bom_line, cline, NULLTAG, &newChild));
		if (newChild == NULLTAG) {
			continue;
		}
		char *os2 = NULL;
		ITKCALL(AOM_ask_value_string(newChild, "object_string", &os2));
		printf("newChild====>%s  ", os2);
		ITKCALL(AOM_ask_value_string(cline, "bl_quantity", &oldQty));
		ITKCALL(AOM_ask_value_string(cline, "bl_sequence_no", &seqNo));
		ITKCALL(AOM_ask_value_string(cline, "bl_line_name", &bl_line_name));
		if (lastFlag && strstr(bl_line_name,"线")!=NULL) {
			double blQty = atof(oldQty);
			int num = blQty / xqLen;
			double fmodVal = fmod(blQty, xqLen);
			double lastVal = num + fmodVal;
			string numNew = to_string(lastVal);
			printf("numNew1====> %s\n", numNew.c_str());
			(AOM_lock(newChild));
			int result = 0;
			ITKCALL(result = AOM_set_value_string(newChild, "bl_quantity", numNew.c_str()));
			if (result != 0) {
				int iblQty = atoi(oldQty);
				//double fmodVal = fmod(blQty, xqLen);
				int val = iblQty / xqLen + iblQty % xqLen;
				numNew = to_string(val);
				printf("numNew1====> %s >>> %s\n", numNew.c_str(), vecs[i].blQuantity.c_str());
				ITKCALL(AOM_set_value_string(newChild, "bl_quantity", numNew.c_str()));
				//ITKCALL(AOM_set_value_string(newChild, "bl_quantity", vecs[i].blQuantity.c_str()));
			}
			ITKCALL(AOM_set_value_string(newChild, "bl_sequence_no", seqNo));
			ITKCALL(AOM_set_value_string(newChild, "ZT2_Remark", remark));
			(AOM_save(newChild));
			(AOM_unlock(newChild));
		}
		else {
			int blQty = atoi(oldQty);
			int num = blQty / xqLen;
			string numNew = to_string(num);
			printf("numNew2====> %s\n", numNew.c_str());
			(AOM_lock(newChild));
			ITKCALL(AOM_set_value_string(newChild, "bl_quantity", numNew.c_str()));
			ITKCALL(AOM_set_value_string(newChild, "bl_sequence_no", seqNo));
			ITKCALL(AOM_set_value_string(newChild, "ZT2_Remark", remark));
			(AOM_save(newChild));
			(AOM_unlock(newChild));
		}
	}

	ITKCALL(BOM_save_window(ebom_window));
	ITKCALL(BOM_close_window(ebom_window));
}

/**
 * 获取单层EBOM的信息 跟EBOM比较用的
 * @param upBean 记录的EBOM结构
 */
map<string, double> getEBomMesg(EBomUpBean upBean) {
	vector<EBomUpBean> childs = upBean.parentBean;
	map<string, double> eMap;
	for (int i = 0; i < childs.size(); i++) {
		EBomUpBean cBean = childs[i];
		double qtyPXn = 1;
		string matnrNo = cBean.matnrNo;
		string cnt = cBean.blQuantity;
		if (tc_strcmp(cnt.c_str(), "") != 0) {
			qtyPXn = atof(cnt.c_str()); //atof(oldQty);
		}
		if (eMap.count(matnrNo) > 0) {
			eMap[matnrNo] = eMap[matnrNo] + qtyPXn;
		}
		else {
			eMap[matnrNo] = qtyPXn;
		}
		printf("getEBomMesg====> %s == %f\n", matnrNo.c_str(), eMap[matnrNo]);
	}
	return eMap;
}
/**
 * 计算PBOM里线圈的数量
 * @param mantrRev P物料
 * @param flag 记录有没有bom视图
 */
void getPBomMsg(tag_t bom_line, map<string, double>& bomMsgMap) {
	int c_line_count;
	tag_t* c_line_tags;
	ITKCALL(BOM_line_ask_all_child_lines(bom_line, &c_line_count, &c_line_tags));
	printf("c_line_count===>%d\n", c_line_count);
	for (int t = 0; t < c_line_count; t++) {
		tag_t c_Rev;
		char *matnrNo, *cnt, *objName;
		ITKCALL(AOM_ask_value_tag(c_line_tags[t], BL_LINE_OBJECT, &c_Rev));
		ITKCALL(AOM_ask_value_string(c_Rev, MATERIALNO, &matnrNo));
		double qtyPXn = 1;
		ITKCALL(AOM_ask_value_string(c_line_tags[t], BL_QUANTITY, &cnt));
		if (strcmp(cnt, "") != 0) {
			qtyPXn = atof(cnt);
		}
		if (bomMsgMap.count(matnrNo) > 0) {
			bomMsgMap[matnrNo] = bomMsgMap[matnrNo] + qtyPXn;
		}
		else {
			bomMsgMap[matnrNo] = qtyPXn;
		}
		printf("zt2_MaterialNo===>%s == %f\n", matnrNo, bomMsgMap[matnrNo]);
	}
}
/**
 * 获取单层PBOM的信息 跟EBOM比较用的
 * 线圈装配P - 线圈P - ABC项 - 线圈E拆分的子项
 * @param mantrRev P物料
 * @param flag 记录有没有bom视图
 */
map<string, double> getPBomMsg(tag_t mantrRev, bool& flag, vector<tag_t>& termCoils) {
	map<string, double> bomMsgMap;
	tag_t* bvr_list = NULL, bom_line, ebom_window;
	int bvr_count = 0;
	ITKCALL(ITEM_rev_list_bom_view_revs(mantrRev, &bvr_count, &bvr_list));
	//没有BOM视图创建
	if (bvr_count == 0) {
		flag = true;
		return bomMsgMap;
	}
	ITKCALL(BOM_create_window(&ebom_window));
	//移除原来的
	ITKCALL(BOM_set_window_top_line(ebom_window, NULL, mantrRev, NULLTAG, &bom_line));
	int c_line_count;
	tag_t* c_line_tags;
	ITKCALL(BOM_line_ask_all_child_lines(bom_line, &c_line_count, &c_line_tags));
	printf("c_line_count===>%d\n", c_line_count);
	for (int t = 0; t < c_line_count; t++) {
		tag_t c_Rev;
		char *matnrNo, *cnt, *objName;
		ITKCALL(AOM_ask_value_tag(c_line_tags[t], "bl_line_object", &c_Rev));
		ITKCALL(AOM_ask_value_string(c_Rev, "zt2_MaterialNo", &matnrNo));
		
		double qtyPXn = 1;
		ITKCALL(AOM_ask_value_string(c_line_tags[t], "bl_quantity", &cnt));
		ITKCALL(AOM_ask_value_string(c_Rev, OBJECT_NAME, &objName));
		if (checkName(objName)) {
			termCoils.push_back(c_Rev);
			getPBomMsg(c_line_tags[t], bomMsgMap);
			continue;
		}
		if (strcmp(cnt, "") != 0) {
			qtyPXn = atof(cnt);
		}
		if (bomMsgMap.count(matnrNo) > 0) {
			bomMsgMap[matnrNo] = bomMsgMap[matnrNo] + qtyPXn;
		}
		else {
			bomMsgMap[matnrNo] = qtyPXn;
		}
		printf("getPBomMsg===>%s objName===> %s == %f\n", matnrNo, objName, bomMsgMap[matnrNo]);
	}
	ITKCALL(BOM_close_window(ebom_window));
	return bomMsgMap;
}
/**
 * 对比Ebom和Dbom
 * @param dMap D物料编码 - 数量
 * @param eMap E物料编码 - 数量
 */
boolean combEAndDbom(map<string, double> dMap, map<string, double> eMap) {
	map<string, double>::iterator it;
	//名称模糊匹配
	for (it = dMap.begin(); it != dMap.end(); it++) {
		string s = it->first;
		double dnum = dMap[s];
		printf("combEAndDbom：%s == %d == ", s.c_str(), dnum);
		if (eMap.count(s) == 0) {
			printf("0\n");
			return true;
		}
		else if (dnum != eMap[s]) {
			printf("%d\n", eMap[s]);
			return true;
		}
		printf("\n");
	}
	return false;
}
/**
 * 根据升版前的线圈视图权限，修改升版后的
 * @param newPMantr 升版后的
 * @param oldPMantr 升版前的
 */
void changeCoilOwner(tag_t newPMantr, tag_t oldPMantr) {
	tag_t dsuser, *oldRevisions;
	int revNum = 0, revNumOld = 0;
	ITKCALL(AOM_ask_value_tags(newPMantr, "structure_revisions", &revNumOld, &oldRevisions));
	if (revNumOld > 0) {
		ITKCALL(AOM_ask_value_tag(oldRevisions[0], "owning_user", &dsuser));
		tag_t defGroup, *structure_revisions;
		ITKCALL(AOM_ask_value_tag(dsuser, "default_group", &defGroup));
		ITKCALL(AOM_ask_value_tags(newPMantr, "structure_revisions", &revNum, &structure_revisions));
		if (revNum > 0) {
			ITKCALL(AOM_set_ownership(structure_revisions[0], dsuser, defGroup));
		}
	}
}
/**
 * 比较DBOM、EBOM是否相同，不同则升版
 * @param topBean 存放BOM信息
 * @param isTop 是否产成品
 * @param hasChange 是否发布
 * @param saveAsMap 存放升版之前的版本uid - 升版之后的新版本 存在打包的对象防止多次升版
 * @param pMaterial P物料
 */
tag_t saveAsMaterial(EBomUpBean topBean, boolean isTop,
	string &hasChange, map<string, tag_t>& saveAsMap, tag_t pMaterial) {
	char* oldUid;
	ITK__convert_tag_to_uid(pMaterial, &oldUid);
	if (saveAsMap.count(oldUid) > 0) {
		return saveAsMap[oldUid];
	}
	bool flagTest = false;
	map<string, double> dBomMesg = getEBomMesg(topBean);
	vector<tag_t> termCoils;
	map<string, double> eBomMesg = getPBomMsg(pMaterial, flagTest, termCoils);
	if (flagTest) {
		printf("dddd=====\n");
		return pMaterial;
	}
	printf("eBomMesg[%d]", dBomMesg.size());
	printf("pBomMesg[%d]\n", eBomMesg.size());
	boolean needAs = false;
	if (dBomMesg.size() != eBomMesg.size()) {
		//升版 + 发布
		needAs = true;
	}
	else if (combEAndDbom(dBomMesg, eBomMesg)) {
		//升版 + 发布
		needAs = true;
	}
	if (needAs) {
		printf("=======TEST====== %d \n", termCoils.size());
		//升版并发布 没发布的产成品直接更新
		if (isTcm(pMaterial) && isBomViewTcm(pMaterial)) {
			printf("ITEM_copy_rev::%s\n", oldUid);
			POM_AM__set_application_bypass(true);
			ITKCALL(ITEM_copy_rev(pMaterial, NULL, &pMaterial));
			TCMAndOwner(pMaterial);
			if (isTop) {
				hasChange = "true";
			}
			saveAsMap[oldUid] = pMaterial;
		}
		for (int i = 0; i < termCoils.size(); i++) {
			char* itemId;
			ITKCALL(AOM_ask_value_string(termCoils[i], "item_id", &itemId));
			printf("=======itemId====== %s \n", itemId);
			if (isTcm(termCoils[i]) && isBomViewTcm(termCoils[i])) {
				tag_t newPMantr;
				POM_AM__set_application_bypass(true);
				ITKCALL(ITEM_copy_rev(termCoils[i], NULL, &newPMantr));
				changeCoilOwner(newPMantr, termCoils[i]);
				//TCMAndOwner(newPMantr);
			}
		}
	}
	return pMaterial;
}
/**
 * 更新PBOM逻辑 
 * @param upBean EBOM结构
 * @param pBomTag PBOM顶层
 * @param len 拆分数量
 * @param dcproxy dcproxy用户
 * @param isTop 是否最上层
 * @param hasChange 最顶层是否变更
 * @param saveAsMap 记录已经另存过的对象，防止解包之后重复另存
 */
void startUpdate(EBomUpBean upBean, tag_t pBomTag, int len, tag_t dcproxy, 
	boolean isTop, string &hasChange, map<string, tag_t>& saveAsMap) {
	auto start = std::chrono::high_resolution_clock::now();
	//记录的EBOM下面的子件
	printf("startUpdate===>%s\n", upBean.matnrNo.c_str());
	vector<EBomUpBean> vecs = upBean.parentBean;
	int c_line_count = 0;
	tag_t* c_line_tags;
	vector<string> matnrVec;
	//线圈
	vector<tag_t> xqTagVec;
	//PBOM
	map<string, tag_t> pBomMap;
	//线圈对象需要特别处理
	tag_t pBomTop = saveAsMaterial(upBean, isTop, hasChange, saveAsMap, pBomTag);
	tag_t ebom_window2, *bvr_list2, bom_line;
	int bvr_count2 = 0;
	char* pBomUid;
	ITKCALL(BOM_create_window(&ebom_window2));
	ITK__convert_tag_to_uid(pBomTop, &pBomUid);
	
	ITKCALL(ITEM_rev_list_bom_view_revs(pBomTop, &bvr_count2, &bvr_list2));
	printf(" pBomUid ===>%s \n", pBomUid);
	if (bvr_count2 == 0) {
		printf("不存在EBOM请检查\n");
		//原来没有PBOM
		return;
	}
	auto bomtime = std::chrono::high_resolution_clock::now();
	std::chrono::duration<double> elapsed = bomtime - start;
	printf("startUpdate1 %s：%f\n", upBean.matnrNo.c_str(), elapsed.count());

	ITKCALL(BOM_set_window_top_line_bvr(ebom_window2, bvr_list2[0], &bom_line)); //顶层bom获取
	ITKCALL(BOM_line_ask_all_child_lines(bom_line, &c_line_count, &c_line_tags));
	for (int i = 0; i < c_line_count; i++) {
		char* ifpBom, *matnrNo, *name;
		tag_t c_line_tag = c_line_tags[i], eRev;
		ITKCALL(AOM_ask_value_tag(c_line_tag, "bl_line_object", &eRev));
		ITKCALL(AOM_ask_value_string(eRev, "zt2_ifpbom", &ifpBom));
		ITKCALL(AOM_ask_value_string(eRev, "zt2_MaterialNo", &matnrNo));
		ITKCALL(AOM_ask_value_string(eRev, "object_name", &name));
		//移除PBOM
		printf("zt2_MaterialNo ===>%s ifpBom==>%s\n", matnrNo, ifpBom);
		if (tc_strcmp(ifpBom, "P") == 0) {
			//A项线圈是不带P的
			matnrVec.push_back(matnrNo);
			pBomMap[matnrNo] = c_line_tag;
			//ITKCALL(BOM_line_cut(c_line_tag));
		}
		else if (checkName(name)) {
			xqTagVec.push_back(c_line_tag);
		}
		else {
			ITKCALL(BOM_line_cut(c_line_tag));//pBomMap[matnrNo] = c_line_tag;
		}
	}
	bomtime = std::chrono::high_resolution_clock::now();
	elapsed = bomtime - start;
	printf("startUpdate2 %s：%f\n", upBean.matnrNo.c_str(), elapsed.count());
	//移除所有非P 再从EBOM复制
	printf("xqTagVec===>%d\n", xqTagVec.size());
	POM_AM__set_application_bypass(true);
	for (int i = 0; i < xqTagVec.size(); i++) {
		tag_t xqLine = xqTagVec[i],*c_xqLine_tags, newPAmatnr;
		int c_line_countXq = 0;
		ITKCALL(BOM_line_ask_all_child_lines(xqLine, &c_line_countXq, &c_xqLine_tags));
		printf("c_line_countXq===>%d\n", c_line_countXq);
		//移除原来的 -> 进行对比是否有修改
		for (int j = 0; j < c_line_countXq; j++) {
			ITKCALL(BOM_line_cut(c_xqLine_tags[j]));
		}
		ITKCALL(AOM_ask_value_tag(xqLine, "bl_line_object", &newPAmatnr));
		//添加线圈下的东西
		boolean lastFlag = false;
		if (i == xqTagVec.size() - 1) {
			lastFlag = true;
		}
		addToAmatnrUp(vecs, len, newPAmatnr, lastFlag);
	}
	bomtime = std::chrono::high_resolution_clock::now();
	elapsed = bomtime - start;
	printf("startUpdate3 %s：%f\n", upBean.matnrNo.c_str(), elapsed.count());
	if (xqTagVec.size() == 0) {
		//不是线圈 移除后复制
		printf("vecs===>%zd\n", vecs.size());
		for (int i = 0; i < vecs.size(); i++) {
			//printf("i===>%d\n", i);
			EBomUpBean cupBean = vecs[i];
			//重新复制
			if (std::find(matnrVec.begin(), matnrVec.end(), cupBean.matnrNo) != matnrVec.end()) {
				//printf("matnrVec ===>%s\n", cupBean.matnrNo.c_str());
				tag_t c_line_tag = pBomMap[cupBean.matnrNo], bomView = NULLTAG, childPTag = NULLTAG;
				boolean flagAs = false;
				
				ITKCALL(AOM_ask_value_tag(c_line_tag, BL_LINE_OBJECT, &childPTag));
				//ITKCALL(BOM_line_cut(c_line_tag));
				startUpdate(cupBean, childPTag, len, dcproxy, isTop, hasChange, saveAsMap);
				if (bomView != NULLTAG && flagAs) {
					ITKCALL(BOM_save_window(bomView));
					ITKCALL(BOM_close_window(bomView));
				}
				tag_t cline = cupBean.bomline;
				char* qty = NULL;
				ITKCALL(AOM_ask_value_string(cline, "bl_quantity", &qty));
				(AOM_lock(c_line_tag));
				ITKCALL(AOM_set_value_string(c_line_tag, "bl_quantity", qty));
				(AOM_save(c_line_tag));
				(AOM_unlock(c_line_tag));
				//printf("i2===>%d\n", i);
			}
			else {
				boolean flagLc = false;
				char* seq = NULL, *ZT2_Remark = NULL;
				//printf("matnrVecNotP===>%s\n", cupBean.matnrNo.c_str());
				tag_t cline = cupBean.bomline, newChild = NULLTAG;
				ITKCALL(BOM_line_copy(bom_line, cline, NULLTAG, &newChild));
				if (newChild == NULLTAG) {
					printf(" newChild === NULLTAG 没有权限修改BOM视图 \n");
					continue;
				}
				ITKCALL(AOM_ask_value_string(cline, "bl_sequence_no", &seq));
				ITKCALL(AOM_ask_value_string(cline, "ZT2_Remark", &ZT2_Remark));
				(AOM_lock(newChild));
				ITKCALL(AOM_set_value_string(newChild, "bl_sequence_no", seq));
				ITKCALL(AOM_set_value_string(newChild, "ZT2_Remark", ZT2_Remark));
				(AOM_save(newChild));
				(AOM_unlock(newChild));
				tag_t c_Rev;
				ITKCALL(AOM_ask_value_tag(cline, "bl_line_object", &c_Rev));

				vector<EBomUpBean> ccBeans = cupBean.parentBean;
				//线圈装配
				for (int j = 0; j < ccBeans.size(); j++) {
					EBomUpBean ccBean = ccBeans[j];
					//创建线圈对象
					if (ccBean.c_lines.size() > 0) {
						//要另存操作
						char* uid;
						tag_t cc_Rev;
						tag_t newPrev = saveAsUpdate(c_Rev, newChild); //另存调压线圈装配
						ITKCALL(AOM_ask_value_tag(ccBean.bomline, "bl_line_object", &cc_Rev));
						ITK__convert_tag_to_uid(cc_Rev, &uid);
						tag_t cc_PRev = saveAsUpdate(cc_Rev, uid, newPrev);//另存调压线圈
						createAXxq(cc_Rev, cc_PRev, len, dcproxy);
					}
				}
			}
		}
		bomtime = std::chrono::high_resolution_clock::now();
		elapsed = bomtime - start;
		printf("startUpdate4 %s：%f\n", upBean.matnrNo.c_str(), elapsed.count());
		for (int i = 0; i < matnrVec.size(); i++) {
			bool cut = true;
			for (int j = 0; j < vecs.size(); j++) {
				if (tc_strcmp(vecs[j].matnrNo.c_str(), matnrVec[i].c_str()) == 0) {
					cut = false;
					break;
				}
			}
			if (cut) {
				printf(" cut === %s\n", matnrVec[i].c_str());
				tag_t c_line_tag = pBomMap[matnrVec[i]];
				ITKCALL(BOM_line_cut(c_line_tag));
			}
		}/**/
		bomtime = std::chrono::high_resolution_clock::now();
		elapsed = bomtime - start;
		printf("startUpdate5 %s：%f\n", upBean.matnrNo.c_str(), elapsed.count());
	}
	//移除所有非P 再从EBOM复制
	
	ITKCALL(BOM_save_window(ebom_window2));
	ITKCALL(BOM_close_window(ebom_window2));
	bomtime = std::chrono::high_resolution_clock::now();
	elapsed = bomtime - start;
	printf("startUpdate6 %s：%f\n", upBean.matnrNo.c_str(), elapsed.count());
	printf("startUpdate end===>%s\n", upBean.matnrNo.c_str());
}
/**
 * 复制BOM信息
 * @param matnrTop 旧
 * @param otherPbom 新
 */
void copyBomLine(tag_t matnrTop, tag_t otherPbom) {
	tag_t ebom_window, ebom_window2, *bvr_list, *bvr_list2, bom_line, bom_line2, *c_line_tags, *c_line_tags2;
	int bvr_count = 0, bvr_count2 = 0, c_line_count, c_line_count2;
	ITKCALL(BOM_create_window(&ebom_window));
	ITKCALL(ITEM_rev_list_bom_view_revs(matnrTop, &bvr_count, &bvr_list));
	printf("bvr_count=%d \n", bvr_count);
	if (bvr_count == 0) {
		//errBuff.append("不存在EBOM请检查\n");
		char* os = NULL;
		ITKCALL(AOM_ask_value_string(matnrTop, "object_string", &os));
		printf("%sBOM数量为0\n", os);
		return;
	}
	ITKCALL(BOM_set_window_top_line_bvr(ebom_window, bvr_list[0], &bom_line)); //顶层bom获取
	printf("顶层bom获取\n");
	//ITKCALL(AOM_ask_value_tag(bom_line, "bl_line_object", &mantr));
	ITKCALL(BOM_line_ask_all_child_lines(bom_line, &c_line_count, &c_line_tags));


	ITKCALL(ITEM_rev_list_bom_view_revs(otherPbom, &bvr_count2, &bvr_list2));
	if (bvr_count2 == 0) {
		tag_t newView = NULLTAG, newViewBvr = NULLTAG, pitem = NULLTAG;
		ITKCALL(ITEM_ask_item_of_rev(otherPbom, &pitem));
		ITKCALL(PS_create_bom_view(NULL, NULL, NULL, pitem, &newView));
		(AOM_save(newView));
		(AOM_unlock(newView));//20241211
		ITKCALL(PS_create_bvr(newView, NULL, NULL, FALSE, otherPbom, &newViewBvr));
		(AOM_save(newViewBvr));
		(AOM_unlock(newViewBvr));//20241211
		(AOM_save(otherPbom));
		(AOM_unlock(otherPbom));//20241211
		//return;
		ITKCALL(ITEM_rev_list_bom_view_revs(otherPbom, &bvr_count2, &bvr_list2));
	}
	ITKCALL(BOM_create_window(&ebom_window2));
	ITKCALL(BOM_set_window_top_line_bvr(ebom_window2, bvr_list2[0], &bom_line2)); //顶层bom获取
	ITKCALL(BOM_line_ask_all_child_lines(bom_line2, &c_line_count2, &c_line_tags2));
	POM_AM__set_application_bypass(true);
	for (int i = 0; i < c_line_count2; i++) {
		ITKCALL(BOM_line_cut(c_line_tags2[i]));
	}
	for (int i = 0; i < c_line_count; i++) {
		tag_t newChild = NULLTAG;
		char *bl_seqNo = NULL, *ZT2_Remark = NULL;
		ITKCALL(BOM_line_copy(bom_line2, c_line_tags[i], NULLTAG, &newChild));

		char* pos = NULL;
		ITKCALL(AOM_ask_value_string(c_line_tags[i], "object_string", &pos));
		printf("copyBomLine:%s\n", pos);

		ITKCALL(AOM_ask_value_string(c_line_tags[i], "bl_sequence_no", &bl_seqNo));
		ITKCALL(AOM_ask_value_string(c_line_tags[i], "ZT2_Remark", &ZT2_Remark));
		AOM_lock(newChild);
		ITKCALL(AOM_set_value_string(newChild, "bl_sequence_no", bl_seqNo));
		ITKCALL(AOM_set_value_string(newChild, "ZT2_Remark", ZT2_Remark));
		AOM_save(newChild);
		//最后unlock
		AOM_unlock(newChild);
	}
	//tag_t newChild;
	//ITKCALL(BOM_line_copy(bom_line2, c_line_tags[i], NULLTAG, &newChild));

	ITKCALL(BOM_save_window(ebom_window2));
	ITKCALL(BOM_close_window(ebom_window2));
	ITKCALL(BOM_close_window(ebom_window));
}

//EBOM转PBOM
int EbomToPMethod(void* returnValue) {
	auto start = std::chrono::high_resolution_clock::now();
	int ifail = ITK_ok;
	char *sql = NULL, *revUid;
	tag_t matnrRev1;
	ITKCALL(ifail = USERARG_get_string_argument(&revUid));
	ITK__convert_uid_to_tag(revUid, &matnrRev1);

	string log_path = "D:\\Siemens\\logs\\material\\";
	log_path.append(getNow("yyyyMMdd")).append(".log");
	CreateTcLogFile(log_path.c_str());
	WriteTcLog("*******************   EbomToPMethod start %s   *******************", getNow("LOG").c_str());
	//链接mdm数据库获取物料申请需要的信息
	if (open("PLMUser", "PLMUser", "BDP2020", "10.128.20.35")) {
		printf("链接SQLSERVER失败\n");
	}
	else {
		printf("链接SQLSERVER成功\n");
	}
	{
		char selectRecord[200], selectRecord1[200];
		sprintf(selectRecord, Sql1.c_str(), m_code1.c_str());
		printf("执行查询 %s\n", selectRecord);
		int outputColumn = 0, outputValueCount = 0;
		char*** outputValue = NULL;
		ado_QuerySQLNoInputParam(selectRecord, &outputColumn, &outputValueCount, &outputValue);
		prds.clear();
		string pmpcPrhCode, pmpcPType, pmpcMType;
		for (int j = 0; j < outputValueCount; j++) {
			pmpcPrhCode = outputValue[j][0];
			pmpcPType = outputValue[j][1];
			pmpcMType = outputValue[j][2];
			pmpc.m_code = m_code1;
			pmpc.pmpcPrhCode = pmpcPrhCode;
			pmpc.pmpcPType = pmpcPType;
			pmpc.pmpcMType = pmpcMType;
			printf("pmpcMType====>%s\n", outputValue[j][2]);
		}
		sprintf(selectRecord1, Sql2.c_str(), pmpcPrhCode.c_str());
		int outputColumn1 = 0, outputValueCount1 = 0;
		char*** outputValue1 = NULL;
		printf("执行查询 %s\n", selectRecord1);
		ado_QuerySQLNoInputParam(selectRecord1, &outputColumn1, &outputValueCount1, &outputValue1);
		for (int j = 0; j < outputValueCount1; j++) {
			string prdFeatureCode = outputValue1[j][3];
			string featureName = outputValue1[j][4];
			PRD prd;
			prd.prdFeatureCode = prdFeatureCode;
			prd.featureName = featureName;
			prds.push_back(prd);
		}
	}
	close();
	auto time1 = std::chrono::high_resolution_clock::now();
	std::chrono::duration<double> elapsed = time1 - start;
	printf("time1：%f\n", elapsed.count());
	//遍历design BOM 获取物料信息
	int bvr_count = 0, c_line_count;
	tag_t ebom_window = NULLTAG;
	tag_t bom_line = NULLTAG;
	tag_t item_tag = NULLTAG, *c_line_tags;
	
	int num = 0,num2=0;
	tag_t* mantrs, designRev;
	string errBuff;
	//获取E物料的图纸
	ITKCALL(AOM_ask_value_tags(matnrRev1, "TC_Is_Represented_By", &num, &mantrs));
	int len = 1;
	if (num >= 1) {
		//找到图纸获取下面所有符合条件的E物料和P物料已有就更新
		designRev = mantrs[0];
		tag_t designItem;
		ITKCALL(ITEM_ask_item_of_rev(designRev,&designItem));
		ITKCALL(ITEM_ask_latest_rev(designItem,&designRev));
		char* itemId;
		ITKCALL(AOM_ask_value_string(designRev, "item_id", &itemId));
		vector<string> vec2;
		Split(itemId, "-", vec2);
		string idTop = "1ZDB300000P";
		if (vec2.size() > 0) {
			idTop = idTop.append("-").append(vec2[1]);
		}
		tag_t topItem, topDesginRev;
		ITKCALL(ITEM_find_item(idTop.c_str(), &topItem));
		ITKCALL(ITEM_ask_latest_rev(topItem, &topDesginRev));
		len = getClassVal2(topItem, errBuff);
		printf("len%d\n", len);
		if (len > 0) {
			boolean isUpdate = false;

			tag_t* bvr_list = NULL, *topMatnrs;
			ITKCALL(AOM_ask_value_tags(topDesginRev, "representation_for", &num2, &topMatnrs));
			//tag_t matnrTop = NULLTAG;
			printf("num2===>%d\n", num2);
			map<string, E2PBean> wlbmMap;
			//遍历变压器图纸获取最新版本的E和P对象
			for (int t = 0; t < num2; t++) {
				char* isPm, *zt2_MaterialNo, *zt2_WBSNo;
				ITKCALL(AOM_ask_value_string(topMatnrs[t], "zt2_WBSNo", &zt2_WBSNo));
				ITKCALL(AOM_ask_value_string(topMatnrs[t], "zt2_MaterialNo", &zt2_MaterialNo));
				ITKCALL(AOM_ask_value_string(topMatnrs[t], "zt2_ifpbom", &isPm));
				string key = "";
				key.append(zt2_WBSNo).append(zt2_MaterialNo);
				printf("key===>%s\n", key.c_str());

				if (wlbmMap.count(key) > 0) {
					E2PBean &bean = wlbmMap[key];
					char* revId;
					//获取最新的版本
					ITKCALL(AOM_ask_value_string(topMatnrs[t], "item_revision_id", &revId));
					//if (strcmp(revId, bean.revId.c_str()) > 0) {}
					if (strcmp(isPm, "P") == 0) {
						if (strcmp(revId, bean.prevId.c_str()) > 0) {
							printf("3\n");
							bean.pMantr = topMatnrs[t];
							bean.prevId = revId;
						}
					}
					else {
						if (strcmp(revId, bean.erevId.c_str()) > 0) {
							printf("4\n");
							bean.eMantr = topMatnrs[t];
							bean.erevId = revId;
						}
					}
				}
				else {
					E2PBean bean;
					bean.key = key;
					char* revId;
					ITKCALL(AOM_ask_value_string(topMatnrs[t], "item_revision_id", &revId));
					if (strcmp(isPm, "P") == 0) {
						printf("1\n");
						bean.pMantr = topMatnrs[t];
						bean.prevId = revId;
					}
					else {
						printf("2\n");
						bean.eMantr = topMatnrs[t];
						bean.erevId = revId;
					}
					wlbmMap[key] = bean;
				}
				if (strcmp(isPm, "P") == 0) {
					isUpdate = true;
				}
			}
			auto time2 = std::chrono::high_resolution_clock::now();
			elapsed = time2 - start;
			printf("time2：%f\n", elapsed.count());

			POM_AM__set_application_bypass(true);
			tag_t dcproxy = findDcUser();
			//创建PBOM原来逻辑
			if (!isUpdate && wlbmMap.size() > 0) {
				printf("wlbmMap.size()===>%d\n", wlbmMap.size());
				map<string, E2PBean>::iterator it;
				map<string, E2PBean>::iterator it2;
				//名称模糊匹配
				tag_t matnrTop = NULLTAG;
				string keyNum = "";
				//第一个创建，其他复制就行
				for (it = wlbmMap.begin(); it != wlbmMap.end(); it++) {
					string s = it->first;
					keyNum = s;
					E2PBean tagBean = wlbmMap[s];
					printf("tagBean.key.c_str()=%s \n", tagBean.key.c_str()); //tagBean.key.c_str()
					matnrTop = tagBean.eMantr;
					break;
				}
				char* uida;
				ITK__convert_tag_to_uid(matnrTop, &uida);
				printf("uida=%s \n", uida);
				//只有E物料新建的逻辑
				ITKCALL(BOM_create_window(&ebom_window));
				ITKCALL(ITEM_rev_list_bom_view_revs(matnrTop, &bvr_count, &bvr_list));
				printf("bvr_count=%d \n", bvr_count);
				if (bvr_count == 0) {
					errBuff.append("不存在EBOM请检查\n");
				}
				ITKCALL(BOM_set_window_top_line_bvr(ebom_window, bvr_list[0], &bom_line)); //顶层bom获取
				printf("顶层bom获取\n");
				EBomBean topBean;
				topBean.eRev = matnrTop;
				topBean.eBomline = bom_line;
				//遍历EBOM获取P物料
				vector<EBomBean> beans;
				//遍历BOM
				recyReadEBom(bom_line, topBean, beans, len, matnrTop, errBuff);
				printf("read end %d\n", beans.size());

				ITKCALL(BOM_close_window(ebom_window));
				//搭建BOM
				auto time3 = std::chrono::high_resolution_clock::now();
				elapsed = time3 - start;
				printf("time3：%f\n", elapsed.count());

				printf("buff %s==>\n", errBuff.c_str());
				tag_t topPrev = NULLTAG;
				if (errBuff.empty()) {
					map<string, tag_t> map;

					int url_num = 0;
					char** url_vals = NULL;
					ITKCALL(PREF_ask_char_values("database_tc", &url_num, &url_vals));
					string url = url_vals[0];
					url.append("/").append(url_vals[2]);
					printf("url ==> %s \n", url.c_str());
					if (ConnServer(url_vals[3], url_vals[4], (char*)url.c_str()) == -1)
					{
						printf("提示:中间数据表访问失败\n");
						ifail = 1;
					}
					for (int t = 0; t < beans.size(); t++) {
						replaceBom(beans[t], map, len, dcproxy, topPrev);
					}
					DisConnServer();
					auto time4 = std::chrono::high_resolution_clock::now();
					elapsed = time4 - start;
					printf("time4：%f\n", elapsed.count());

					//多个产成品直接复制BOM
					for (it2 = wlbmMap.begin(); it2 != wlbmMap.end(); it2++) {
						auto sub = std::chrono::high_resolution_clock::now();
						string ss = it2->first;
						tag_t eMantr = wlbmMap[ss].eMantr;
						if (keyNum.compare(ss) == 0) {
							continue;
						}
						char* newid = NULL;
						logical isModified = FALSE;
						tag_t item_type_tag, newRev, newItem;
						ITKCALL(TCTYPE_ask_type("Item", &item_type_tag));
						ITKCALL(USER_new_item_id(NULLTAG, item_type_tag, &isModified, &newid));
						/*ITKCALL(NR_next_value("MEProcess", "item_id", NULLTAG, "", "", "",
							NULLTAG, "", "", &next_id));*/
						printf("next_id==>%s\n", newid);
						ITKCALL(ITEM_copy_item(eMantr, newid, NULL, &newItem, &newRev));
						//ITKCALL(AOM_set_value_string(newRev, "zt2_PMaterial", "PBOM"));
						char* matnrNo;
						ITKCALL(AOM_ask_value_string(eMantr, "zt2_MaterialNo", &matnrNo));
						ITKCALL(AOM_lock(newRev));
						ITKCALL(AOM_set_value_string(newRev, "zt2_ifpbom", "P"));
						ITKCALL(AOM_set_value_string(newRev, "zt2_MaterialNo", matnrNo));
						ITKCALL(AOM_save(newRev));
						ITKCALL(AOM_unlock(newRev));
						tag_t *structure_revisions,* bom_view_tags, dsuser;
						int revNum = 0, tagNum=0;
						ITKCALL(AOM_ask_value_tags(eMantr, "TC_Is_Represented_By", &num, &mantrs));
						//该权限
						if (num > 0) {
							ITKCALL(AOM_ask_value_tags(newRev, "structure_revisions", &revNum, &structure_revisions));
							ITKCALL(AOM_ask_value_tags(newRev, "bom_view_tags", &tagNum, &bom_view_tags));
							ITKCALL(AOM_ask_value_tag(mantrs[0], "owning_user", &dsuser));
							tag_t defGroup;
							ITKCALL(AOM_ask_value_tag(dsuser, "default_group", &defGroup));
							ITKCALL(AOM_set_ownership(newItem, dsuser, defGroup));
							ITKCALL(AOM_set_ownership(newRev, dsuser, defGroup));
							if (revNum > 0) {
								ITKCALL(AOM_set_ownership(structure_revisions[0], dsuser, defGroup));
							}
							if (tagNum > 0) {
								ITKCALL(AOM_set_ownership(bom_view_tags[0], dsuser, defGroup));
							}
						}
						//复制一份
						copyBomLine(topPrev, newRev);
						auto sub1 = std::chrono::high_resolution_clock::now();
						elapsed = sub1 - sub;
						printf("sub1：%f\n", elapsed.count());
					}
				}
			}
			else {
				//更新逻辑 遍历Ebom 不带P的和带P的 目前更新逻辑移除所有重新添加 2024/1/15增加对比逻辑
				tag_t matnrTop = NULLTAG;
				tag_t pBomTop = NULLTAG;
				map<string, E2PBean>::iterator it;
				//第一个创建，其他复制就行
				string keyNum = "";
				for (it = wlbmMap.begin(); it != wlbmMap.end(); it++) {
					string s = it->first;
					keyNum = s;
					//printf("newRev===>%s\n", tagBean.revId.c_str());
					E2PBean tagBean = wlbmMap[s];
					matnrTop = tagBean.eMantr;
					pBomTop = tagBean.pMantr;
					//判断版本视图是否发布，如果发布了，升版
					break;
				}
				ITKCALL(BOM_create_window(&ebom_window));
				ITKCALL(ITEM_rev_list_bom_view_revs(matnrTop, &bvr_count, &bvr_list));
				printf("bvr_count=%d \n", bvr_count);
				if (bvr_count == 0) {
					errBuff.append("不存在EBOM请检查\n");
				}
				ITKCALL(BOM_set_window_top_line_bvr(ebom_window, bvr_list[0], &bom_line)); //顶层bom获取
				printf("顶层bom获取\n");
				EBomUpBean upBean;
				upBean.bomline = bom_line;
				//遍历获取EBOM信息
				updatePbomCycle(bom_line, errBuff, len, upBean);

				auto time3 = std::chrono::high_resolution_clock::now();
				elapsed = time3 - start;
				printf("time3：%f\n", elapsed.count());
				//ITKCALL(BOM_set_window_top_line_bvr(ebom_window2, bvr_list2[0], &bom_line2)); //顶层bom获取
				int url_num = 0;
				char** url_vals = NULL;
				ITKCALL(PREF_ask_char_values("database_tc", &url_num, &url_vals));
				string url = url_vals[0];
				url.append("/").append(url_vals[2]);
				printf("url ==> %s \n", url.c_str());
				if (ConnServer(url_vals[3], url_vals[4], (char*)url.c_str()) == -1)
				{
					printf("提示:中间数据表访问失败\n");
					ifail = 1;
				}
				//更新PBOM
				string hasChange;
				map<string, tag_t> saveAsMap;
				startUpdate(upBean, pBomTop, len, dcproxy, true, hasChange, saveAsMap);
				DisConnServer();
				//保存PBOM
				auto time4 = std::chrono::high_resolution_clock::now();
				elapsed = time4 - start;
				printf("time4：%f\n", elapsed.count());

				//ITKCALL(BOM_save_window(ebom_window2));
				////ITKCALL(AOM_unlock(ebom_window2));
				//ITKCALL(BOM_close_window(ebom_window2));
				char* oldUid = NULL;
				ITK__convert_tag_to_uid(pBomTop, &oldUid);

				ITKCALL(BOM_close_window(ebom_window));
				printf("keyNum===>%s\n", keyNum.c_str());
				map<string, E2PBean>::iterator it2;
				for (it2 = wlbmMap.begin(); it2 != wlbmMap.end(); it2++) {
					auto sub = std::chrono::high_resolution_clock::now();
					string ss = it2->first;
					E2PBean tagBean = wlbmMap[ss];
					printf("ss===>%s\n", ss.c_str());
					if (keyNum.compare(ss) == 0) {
						continue;
					}
					tag_t newRev = tagBean.pMantr;
					//printf("newRev===>%s\n", tagBean.revId.c_str());
					int structs = 0, statusNum = 0;
					tag_t* structure_revisions, *release_status_list;
					ITKCALL(AOM_ask_value_tags(newRev, "structure_revisions", &structs, &structure_revisions));
					printf("structs%d hasChange=>%s\n", structs, hasChange.c_str());
					if (structs > 0 && hasChange.compare("true") == 0) {// && hasChange.compare("true") != 0
						ITKCALL(AOM_ask_value_tags(structure_revisions[0], "release_status_list", &statusNum, &release_status_list));
						printf("statusNum===>%d\n", statusNum);
						if (statusNum > 0) {
							int revNum = 0;
							tag_t *mantrsAs, dsuser;
							ITKCALL(ITEM_copy_rev(newRev, NULL, &newRev));
							ITKCALL(AOM_ask_value_tags(matnrTop, "TC_Is_Represented_By", &num, &mantrsAs));
							ITKCALL(AOM_ask_value_tag(mantrsAs[0], "owning_user", &dsuser));
							tag_t defGroup;
							ITKCALL(AOM_ask_value_tag(dsuser, "default_group", &defGroup));
							ITKCALL(AOM_set_ownership(newRev, dsuser, defGroup));
							if (num > 0) {
								ITKCALL(AOM_ask_value_tags(newRev, "structure_revisions", &revNum, &structure_revisions));
								if (revNum > 0) {
									ITKCALL(AOM_set_ownership(structure_revisions[0], dsuser, defGroup));
								}
							}
						}
					}
					tag_t newP = NULLTAG;
					if (saveAsMap[oldUid] == NULL) {
						newP = pBomTop;
					}
					else {
						newP = saveAsMap[oldUid];
					}
					char* pos = NULL, *nos = NULL;
					ITKCALL(AOM_ask_value_string(newP, "object_string", &pos));
					ITKCALL(AOM_ask_value_string(newRev, "object_string", &nos));
					printf("copyBomLine:%s ==> %s\n", pos, nos);
					copyBomLine(newP, newRev);
					auto sub1 = std::chrono::high_resolution_clock::now();
					elapsed = sub1 - sub;
					printf("sub1：%f\n", elapsed.count());
				}
			}

			POM_AM__set_application_bypass(false);
		}
	}
	string buff = errBuff;
	if (buff.empty()) {
		buff = "succ";
	}
	CloseTcLog();
	// 计算时间间隔
	auto end = std::chrono::high_resolution_clock::now();
	elapsed = end - start;
	printf("用时：%f\n", elapsed.count());
	*((char**)returnValue) = (char*)MEM_alloc((strlen(buff.c_str()) + 1) * sizeof(char));
	tc_strcpy(*((char**)returnValue), buff.c_str());
	return ifail;
}