#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 "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 <chrono>
#include "ado.h"
#include "ocilib.h"
using namespace std;

vector<string> cutVec;

tag_t getPBomTag(tag_t designRev) {
	char* object_type;
	ITKCALL(AOM_ask_value_string(designRev, "object_type", &object_type));
	if (strcmp(object_type, "ZT2_Design3DRevision") == 0) {
		int num;
		tag_t* mantrs;
		ITKCALL(AOM_ask_value_tags(designRev, "representation_for", &num, &mantrs));
		return mantrs[0];
	}
	else if (strcmp(object_type, "Part Revision") == 0) {
		return designRev;
	}
}
void SplitTest(string strArg, string spliter, vector<string> &ans)
{
	ans.clear();
	size_t index0;
	string one_arg;
	if (strArg.find_first_not_of(' ') == string::npos)
		strArg = "";
	while (strArg.size() > 0)
	{
		index0 = strArg.find(spliter);
		if (index0 != string::npos)
		{
			one_arg = strArg.substr(0, index0);
			strArg = strArg.substr(index0 + spliter.size());
			ans.push_back(one_arg);
		}
		else
		{
			ans.push_back(strArg);
			break;
		}
	}
}
void getDrawNo(tag_t bom_line, string &drawNo) {
	char* bl_desc;
	ITKCALL(AOM_ask_value_string(bom_line, "bl_rev_object_desc", &bl_desc));
	regex qq_reg2("^1ZDB5.*\\d{1,}1000X.*");
	//string item_id = id;
	ITKCALL(AOM_ask_value_string(bom_line, "bl_rev_object_desc", &bl_desc));
	vector<string> descVec1;
	SplitTest(bl_desc, " ", descVec1);
	printf("bl_desc===>%s\n", bl_desc);
	if (descVec1.size() > 1) {
		string drawNos = descVec1[1];
		printf("drawNos===>%s\n", descVec1[0].c_str());
		printf("drawNos===>%s\n", drawNos.c_str());
		vector<string> drawNoVec1;
		SplitTest(drawNos, "-", drawNoVec1);
		if (drawNoVec1.size() > 1) {
			drawNo = drawNoVec1[0];
			smatch result;
			/*if (drawNoVec1.size() == 3) {
			drawNo = drawNo.append();
			}*/
			bool ret = regex_match(drawNo, result, qq_reg2);
			if (ret) {
				drawNo = "1ZDB5*10000X";
			}
		}
	}
}
//遍历PBOM
//void 
typedef struct {
	string name;//产品型号 低、中、高、调、稳
	string zzmb;
	string xh;
	string tlth;
	string type;
	string tl;
	string yjgx;
	string ejgx;
}FeedRule;

struct StBomBean {
	string currentName;//产品型号 低、中、高、调、稳
	tag_t bomline;
	boolean st = false;
	boolean istl = false;
	boolean flag = true; //第一层级
	vector<StBomBean> childs;

};
/*
0：外购；1：自制实体；2：自制虚拟
*/
int isSt(tag_t matnr) {
	int cnt2, numFac, cnt3;
	int flag = 1;
	char** procureType, ** factorys, ** specialProcureType, *objName;
	ITKCALL(AOM_ask_value_strings(matnr, "zt2_SZSpecialProcuretype", &cnt3, &specialProcureType)); //为/
	ITKCALL(AOM_ask_value_strings(matnr, "zt2_SZProcuretype", &cnt2, &procureType)); //包含自制
	ITKCALL(AOM_ask_value_strings(matnr, "zt2_SZFactory", &numFac, &factorys));
	//AOM_ask_value_string(matnr, "object_name",&objName);
	for (int i = 0; i < numFac; i++) {
		if (tc_strcmp(factorys[i], "M060") == 0 && cnt2 > i && cnt3 > i) {
			if (tc_strstr(procureType[i], "外购") != NULL) {//自制
				flag = 0;
			}
			else if (tc_strcmp(specialProcureType[i], "/") == 0) {
				flag = 1;
			}
			else {
				flag = 2;
			}
		}
	}

	return flag;
}
void getBomMessage(vector<StBomBean>& stBomlines, tag_t cBomLine, StBomBean &pBean) {

	int c_line_count;
	tag_t * c_line_tags;
	//char* parentName;
	//ITKCALL(AOM_ask_value_tag(pBomLine, "bl_line_object", &mantr));
	//ITKCALL(AOM_ask_value_string(mantr, "object_name", &parentName));
	ITKCALL(BOM_line_ask_all_child_lines(cBomLine, &c_line_count, &c_line_tags));
	tag_t cmantr = NULLTAG;
	char* cName = NULL, *zt2_SZProcuretype = NULL;
	ITKCALL(AOM_ask_value_tag(cBomLine, "bl_line_object", &cmantr));
	ITKCALL(AOM_ask_value_string(cmantr, "object_name", &cName));
	//ITKCALL(AOM_UIF_ask_value(cmantr, "zt2_SZProcuretype", &zt2_SZProcuretype)); //外购不再展开投料
	printf("虚拟件===>%s\n", cName);
	StBomBean bean;
	bean.bomline = cBomLine;
	bean.currentName = cName;
	bean.flag = false;
	int f = isSt(cmantr);
	//1、程序判断物料版本采购类型是什么，如果是外购，那么这个物料进行投料，有没有子件都一样处理
	//2、如果是自制，那么判断特殊采购类型，如果是虚拟，那么此物料不投料，继续展开BOM子件判断，如果没有子，那么此物料也算不需要投料的。如果是/，那么将此物料进行投料。
	if (f == 0 || f == 1) {
		//外购和自制实体不看子级直接投本体
		bean.st = true;
		pBean.childs.push_back(bean);
	}
	else if (c_line_count > 0) {
		//自制虚拟有子级就投子级
		for (int i = 0; i < c_line_count; i++) {
			tag_t c_line_tag = c_line_tags[i];
			getBomMessage(stBomlines, c_line_tag, bean);
		}
		pBean.childs.push_back(bean);
	}
}
void getBomMessage(vector<StBomBean> &stBomlines, tag_t cBomLine) {

	int c_line_count;
	tag_t * c_line_tags;
	//char* parentName;
	//ITKCALL(AOM_ask_value_tag(pBomLine, "bl_line_object", &mantr));
	//ITKCALL(AOM_ask_value_string(mantr, "object_name", &parentName));
	ITKCALL(BOM_line_ask_all_child_lines(cBomLine, &c_line_count, &c_line_tags));
	tag_t cmantr = NULLTAG;
	char* cName = NULL, *zt2_SZProcuretype = NULL, *os = NULL;
	ITKCALL(AOM_ask_value_string(cBomLine, "object_string", &os));
	ITKCALL(AOM_ask_value_tag(cBomLine, "bl_line_object", &cmantr));
	ITKCALL(AOM_ask_value_string(cmantr, "object_name", &cName));
	//ITKCALL(AOM_UIF_ask_value(cmantr, "zt2_SZProcuretype", &zt2_SZProcuretype)); //外购不再展开投料
	printf("getBomMessage==>%s\n", os);
	StBomBean bean;
	bean.bomline = cBomLine;
	bean.currentName = cName;
	int f = isSt(cmantr);
	//1、程序判断物料版本采购类型是什么，如果是外购，那么这个物料进行投料，有没有子件都一样处理
	//2、如果是自制，那么判断特殊采购类型，如果是虚拟，那么此物料不投料，继续展开BOM子件判断，如果没有子，那么此物料也算不需要投料的。如果是/，那么将此物料进行投料。
	if (f == 0 || f == 1) {
		//外购和自制实体不看子级直接投本体
		bean.st = true;
		stBomlines.push_back(bean);
	}
	else if (c_line_count > 0) {
		//自制虚拟有子级就投子级
		for (int i = 0; i < c_line_count; i++) {
			tag_t c_line_tag = c_line_tags[i];
			getBomMessage(stBomlines, c_line_tag, bean);
		}
		stBomlines.push_back(bean);
	}
}
//虚拟向下展开，实体投料
void autoFeedLike(tag_t towGxLine, StBomBean& pBean, vector<StBomBean>& stBomlines, double xnQty) {
	if (!pBean.st) {
		char* qty;
		tag_t line = pBean.bomline;
		ITKCALL(AOM_ask_value_string(line, "bl_quantity", &qty));
		if (strcmp(qty, "") == 0) {
			qty = "1";
		}
		double x = atof(qty);
		printf("pBean.childs==>%zd %s \n", pBean.childs.size(), qty);
		for (int i = 0; i < pBean.childs.size(); i++) {
			StBomBean& child = pBean.childs[i];
			autoFeedLike(towGxLine, child, stBomlines, xnQty*x);
		}
	}
	else if (!pBean.istl) {
		auto start = std::chrono::high_resolution_clock::now();

		pBean.istl = true;
		tag_t newChild = NULLTAG;
		tag_t *c_line_tags = NULLTAG;
		int c_line_count = 0;
		ITKCALL(BOM_line_ask_all_child_lines(towGxLine, &c_line_count, &c_line_tags)); // 一级工序
		string bl_seq = to_string((c_line_count + 1) * 10);
		//auto time1 = std::chrono::high_resolution_clock::now();
		//std::chrono::duration<double> elapsed1 = time1 - start;
		//printf("time1：%f\n", elapsed1.count());

		char *bl_qty = NULL;
		ITKCALL(AOM_ask_value_string(pBean.bomline, "bl_quantity", &bl_qty));
		double x = atof(bl_qty);
		double xx = xnQty * x;
		string bl_quantity = bl_qty;
		if (fmod(xx, 1.0) == 0.0) {
			bl_quantity = to_string((int)xx);
		}
		else {
			bl_quantity = to_string(xx);
		}
		//auto time2 = std::chrono::high_resolution_clock::now();
		//std::chrono::duration<double> elapsed2 = time2 - time1;
		//printf("%s,time2：%f\n", bl_quantity.c_str(), elapsed2.count());

		POM_AM__set_application_bypass(true);
		ITKCALL(BOM_line_copy(towGxLine, pBean.bomline, NULLTAG, &newChild));
		char *uid = NULL, *os = NULL, *os2 = NULL;
		ITKCALL(AOM_ask_value_string(newChild, "object_string", &uid));
		ITKCALL(AOM_ask_value_string(pBean.bomline, "object_string", &os));
		ITKCALL(AOM_ask_value_string(towGxLine, "object_string", &os2));
		//ITKCALL(POM_tag_to_uid(towGxLine, &os2));
		//ITKCALL(POM_tag_to_uid(pBean.bomline, &os));
		//ITKCALL(POM_tag_to_uid(newChild, &uid));
		printf("%s:%s:%s:bl_quantity==>%s\n", os2, os, uid, bl_quantity.c_str());
		(AOM_lock(newChild)); // bl_occ_type
							  //设置事例类型
		ITKCALL(AOM_set_value_string(newChild, "bl_sequence_no", bl_seq.c_str()));
		ITKCALL(AOM_set_value_string(newChild, "bl_quantity", bl_quantity.c_str()));
		ITKCALL(AOM_set_value_string(newChild, "bl_occ_type", "MEConsumed"));
		(AOM_save(newChild));
		(AOM_unlock(newChild));
		DOFREE(c_line_tags);
		DOFREE(bl_qty);
		DOFREE(uid);
		DOFREE(os);
		DOFREE(os2);

		auto end = std::chrono::high_resolution_clock::now();
		std::chrono::duration<double> elapsed = end - start;
		printf("autoFeedLike time：%f\n", elapsed.count());
	}
}
void autoFeedLike(tag_t towGxLine, StBomBean& pBean, string name2, vector<StBomBean>& stBomlines) {

	//子项名称模糊匹配
	printf(" pBean.childs.size()%zd\n", pBean.childs.size());
	for (int i = 0; i < pBean.childs.size(); i++) {
		StBomBean& child = pBean.childs[i];
		printf("child.currentName%s   %s \n", child.currentName.c_str(), name2.c_str());
		if (strstr(name2.c_str(), "*") != NULL) {
			vector<string> liVec;
			string nameLike;
			SplitTest(name2, "*", liVec);
			for (int x = 0; x < liVec.size(); x++) {
				if (!liVec[x].empty()) {
					nameLike = liVec[x];
					break;
				}
			}
			if (tc_strstr(child.currentName.c_str(), nameLike.c_str()) != NULL) {
				autoFeedLike(towGxLine, child, stBomlines, 1);
			}
		}
		else if (name2.compare(child.currentName) == 0) {
			printf("===================\n");
			autoFeedLike(towGxLine, child, stBomlines, 1);
		}
	}
}
//去掉现有的工序
void cutGxLine(tag_t bom_line) {
	char* os = NULL;
	ITKCALL(AOM_ask_value_string(bom_line, "object_string", &os));
	if (find(cutVec.begin(), cutVec.end(), os) != cutVec.end()) {
		return;
	}
	cutVec.push_back(os);
	tag_t *c_line_tags;
	int c_line_count;
	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 *bl_occ_type;
		ITKCALL(AOM_ask_value_string(c_line_tags[i], "bl_occ_type", &bl_occ_type));
		if (strcmp(bl_occ_type, "MEConsumed") == 0) {
			ITKCALL(BOM_line_cut(c_line_tags[i]));
		}
	}

}

void startFeed(tag_t meprocess, vector<StBomBean>& stBomlines, FeedRule bean, string name1, string name2) {
	int bvr_count = 0;
	tag_t ebom_window = NULLTAG;
	tag_t bom_line = NULLTAG;
	tag_t item_tag = NULLTAG, *c_line_tags;
	ITKCALL(BOM_create_window(&ebom_window));
	tag_t* bvr_list = NULL;
	ITKCALL(ITEM_rev_list_bom_view_revs(meprocess, &bvr_count, &bvr_list));
	printf("bvr_count=%d", bvr_count);

	ITKCALL(BOM_set_window_top_line_bvr(ebom_window, bvr_list[0], &bom_line)); //顶层bom获取
																			   //bom_line工艺
	int c_line_count = 0;
	ITKCALL(BOM_line_ask_all_child_lines(bom_line, &c_line_count, &c_line_tags)); // 一级工序
																				  //一级工序
	for (int i = 0; i < c_line_count; i++) {
		tag_t oneGx = c_line_tags[i], *towGxLines;
		int c_cnt = 0;
		char* yjName;
		tag_t yjGx;
		ITKCALL(AOM_ask_value_tag(oneGx, "bl_line_object", &yjGx));
		ITKCALL(AOM_ask_value_string(yjGx, "object_name", &yjName));
		printf("yjName%s %s \n", yjName, bean.yjgx.c_str());
		if (bean.yjgx.compare(yjName) == 0) {
			ITKCALL(BOM_line_ask_all_child_lines(oneGx, &c_cnt, &towGxLines));
			//二级工序
			for (int j = 0; j < c_cnt; j++) {
				tag_t towGxLine = towGxLines[j];
				char* ejName;
				tag_t ejGx;
				ITKCALL(AOM_ask_value_tag(towGxLine, "bl_line_object", &ejGx));
				ITKCALL(AOM_ask_value_string(ejGx, "object_name", &ejName));
				printf("ejName%s %s\n", ejName, bean.ejgx.c_str());
				if (bean.ejgx.compare(ejName) == 0) {
					printf("stBomlines %zd\n", stBomlines.size());
					cutGxLine(towGxLine);
					for (int t = 0; t < stBomlines.size(); t++) {
						StBomBean& stBom = stBomlines[t];
						printf("stBom.currentName==>%s %zd\n", stBom.currentName.c_str(), stBom.childs.size());
						if (stBom.currentName.compare(name1) == 0) {
							//if (!stBom.istl && stBom.st && stBom.flag) {
							autoFeedLike(towGxLine, stBom, name2, stBomlines);
							//stBom.istl = true;
							//}
						}
					}
				}
			}
		}
	}
	ITKCALL(BOM_save_window(ebom_window));
	ITKCALL(BOM_close_window(ebom_window));
	DOFREE(bvr_list);
	DOFREE(c_line_tags);
}
//匹配一级工序和二级工序，名称
void startFeed(tag_t meprocess, vector<StBomBean>& stBomlines, FeedRule bean, vector<string> names) {
	int bvr_count = 0;
	tag_t ebom_window = NULLTAG;
	tag_t bom_line = NULLTAG;
	tag_t item_tag = NULLTAG, *c_line_tags;
	ITKCALL(BOM_create_window(&ebom_window));
	tag_t* bvr_list = NULL;
	ITKCALL(ITEM_rev_list_bom_view_revs(meprocess, &bvr_count, &bvr_list));
	printf("bvr_count=%d", bvr_count);

	ITKCALL(BOM_set_window_top_line_bvr(ebom_window, bvr_list[0], &bom_line)); //顶层bom获取
																			   //bom_line工艺
	int c_line_count;
	ITKCALL(BOM_line_ask_all_child_lines(bom_line, &c_line_count, &c_line_tags)); // 一级工序
																				  //一级工序
	for (int i = 0; i < c_line_count; i++) {
		tag_t oneGx = c_line_tags[i], *towGxLines;
		int c_cnt = 0;
		char* yjName;
		tag_t yjGx;
		ITKCALL(AOM_ask_value_tag(oneGx, "bl_line_object", &yjGx));
		ITKCALL(AOM_ask_value_string(yjGx, "object_name", &yjName));
		if (bean.yjgx.compare(yjName) == 0) {
			ITKCALL(BOM_line_ask_all_child_lines(oneGx, &c_cnt, &towGxLines));
			//二级工序
			for (int j = 0; j < c_cnt; j++) {
				tag_t towGxLine = towGxLines[j];
				char* ejName;
				tag_t ejGx;
				ITKCALL(AOM_ask_value_tag(towGxLine, "bl_line_object", &ejGx));
				ITKCALL(AOM_ask_value_string(ejGx, "object_name", &ejName));
				if (bean.ejgx.compare(ejName) == 0) {
					cutGxLine(towGxLine);
					for (int t = 0; t < stBomlines.size(); t++) {
						StBomBean& stBom = stBomlines[t];
						tag_t newChild;
						if (std::find(names.begin(), names.end(), stBom.currentName) != names.end() && stBom.flag) {
							printf("stBom.currentName2%s %d\n", stBom.currentName.c_str(), !stBom.istl);
							if (!stBom.istl) {
								//投料 未投料的
								autoFeedLike(towGxLine, stBom, stBomlines, 1);
								stBom.istl = true;
							}
						}
					}
				}
			}
		}
	}
	ITKCALL(BOM_save_window(ebom_window));
	ITKCALL(BOM_close_window(ebom_window));
	DOFREE(bvr_list);
	DOFREE(c_line_tags);
}
void startFeed(tag_t meprocess, vector<StBomBean>& stBomlines, FeedRule bean, string nameLike) {//89
	int bvr_count = 0;
	tag_t ebom_window = NULLTAG;
	tag_t bom_line = NULLTAG;
	tag_t item_tag = NULLTAG, *c_line_tags;
	ITKCALL(BOM_create_window(&ebom_window));
	tag_t* bvr_list = NULL;
	ITKCALL(ITEM_rev_list_bom_view_revs(meprocess, &bvr_count, &bvr_list));
	printf("bvr_count=%d", bvr_count);

	ITKCALL(BOM_set_window_top_line_bvr(ebom_window, bvr_list[0], &bom_line)); //顶层bom获取
																			   //bom_line工艺
	int c_line_count;
	ITKCALL(BOM_line_ask_all_child_lines(bom_line, &c_line_count, &c_line_tags)); // 一级工序
																				  //一级工序
	for (int i = 0; i < c_line_count; i++) {
		tag_t oneGx = c_line_tags[i], *towGxLines = NULL;
		int c_cnt = 0;
		char* yjName = NULL;
		tag_t yjGx = NULLTAG;
		ITKCALL(AOM_ask_value_tag(oneGx, "bl_line_object", &yjGx));
		ITKCALL(AOM_ask_value_string(yjGx, "object_name", &yjName));
		printf("yjName===>%s  %s \n", yjName, bean.yjgx.c_str());
		boolean falg = false;
		if (strstr(bean.yjgx.c_str(), "*") != NULL) {
			vector<string> liVec;
			string gxlike;
			Split(bean.yjgx, "*", liVec);
			for (int x = 0; x < liVec.size(); x++) {
				if (!liVec[x].empty()) {
					gxlike = liVec[x];
					if (strstr(yjName, gxlike.c_str()) != NULL) {
						falg = true;
					}
				}
			}
		}
		if (bean.yjgx.compare(yjName) == 0 || falg) {
			ITKCALL(BOM_line_ask_all_child_lines(oneGx, &c_cnt, &towGxLines));
			//二级工序
			for (int j = 0; j < c_cnt; j++) {
				tag_t towGxLine = towGxLines[j];
				char* ejName = NULL;
				tag_t ejGx = NULLTAG;
				ITKCALL(AOM_ask_value_tag(towGxLine, "bl_line_object", &ejGx));
				ITKCALL(AOM_ask_value_string(ejGx, "object_name", &ejName));
				printf("ejName===>%s \n", ejName);
				if (bean.ejgx.compare(ejName) == 0) {
					cutGxLine(towGxLine);
					for (int t = 0; t < stBomlines.size(); t++) {
						StBomBean& stBom = stBomlines[t];
						tag_t newChild;
						//printf("Tlstart===>%s %d %d\n", stBom.currentName.c_str(), stBom.st, !stBom.istl);
						//printf("Tlstart===>%d %d\n", );
						printf("stBom.currentName2==>%s %d\n", stBom.currentName.c_str(), !stBom.istl);
						if (!nameLike.empty()) {
							if (strstr(stBom.currentName.c_str(), nameLike.c_str()) != NULL) {
								printf("stBom.currentName2==>%s %d\n", stBom.currentName.c_str(), !stBom.st);
								if (!stBom.istl && stBom.flag) {
									autoFeedLike(towGxLine, stBom, stBomlines, 1);
									stBom.istl = true;
								}
							}
						}
						else if (!stBom.istl) {
							autoFeedLike(towGxLine, stBom, stBomlines, 1);
							stBom.istl = true;
							//ITKCALL(BOM_line_copy(towGxLine, stBom.bomline, NULLTAG, &newChild));
						}
						//ITKCALL(AOM_save(newChild));
					}
					break;
				}
			}
		}
	}
	auto start = std::chrono::high_resolution_clock::now();
	ITKCALL(BOM_save_window(ebom_window));
	ITKCALL(BOM_close_window(ebom_window));
	auto end = std::chrono::high_resolution_clock::now();
	std::chrono::duration<double> elapsed1 = end - start;
	printf("BOM_save_window time：%f\n", elapsed1.count());
	DOFREE(bvr_list);
	DOFREE(c_line_tags);
}
//map<string, vector<FeedRule>> drawMap;
//map<string, vector<FeedRule>> nameMap;
void AutoFeedBom(tag_t mantr, tag_t meprocess,
	map<string, vector<FeedRule>> drawMap, map<string, vector<FeedRule>> nameMap) {
	//遍历PBOM
	tag_t* bvr_list = NULL, ebom_window, bom_line;
	int bvr_count;
	ITKCALL(ITEM_rev_list_bom_view_revs(mantr, &bvr_count, &bvr_list));
	ITKCALL(BOM_create_window(&ebom_window));
	ITKCALL(BOM_set_window_top_line(ebom_window, NULL, mantr, NULLTAG, &bom_line));

	int c_line_count;
	tag_t * c_line_tags;
	vector<StBomBean> stBomlines;
	ITKCALL(BOM_line_ask_all_child_lines(bom_line, &c_line_count, &c_line_tags));
	for (int i = 0; i < c_line_count; i++) {
		//遍历BOM读取需要投料的信息
		getBomMessage(stBomlines, c_line_tags[i]);
	}
	string drawNo;
	getDrawNo(bom_line, drawNo);
	printf("制造目标=====>%s\n", drawNo.c_str());
	//
	if (drawMap.count(drawNo) > 0) {
		//图号匹配
		vector<FeedRule> beans = drawMap[drawNo];
		printf("beans1===>%zd\n", beans.size());
		for (int t = 0; t < beans.size(); t++) {
			FeedRule bean = beans[t];
			if (bean.tlth.empty()) {
				//全投
				printf("beans2===>%s %s\n", bean.yjgx.c_str(), bean.ejgx.c_str());
				startFeed(meprocess, stBomlines, bean, "");
			}
			else {
				//剩下全投
				printf("beans3===>%s\n", bean.tlth.c_str());
				if (bean.tlth.compare("else") == 0) {
					startFeed(meprocess, stBomlines, bean, "");
				}
				else {
					string nameMatnr = bean.tlth;
					//按名称模糊匹配投
					if (strstr(nameMatnr.c_str(), "*") != NULL) {
						printf("beans4\n");
						vector<string> liVec;
						string nameLike;
						SplitTest(nameMatnr, "*", liVec);
						for (int x = 0; x < liVec.size(); x++) {
							if (!liVec[x].empty()) {
								nameLike = liVec[x];
							}
						}
						startFeed(meprocess, stBomlines, bean, nameLike);
					}
					else {
						//按名称精准匹配投料
						if (strstr(nameMatnr.c_str(), "\\") != NULL) {
							printf("beans5\n");
							vector<string> names;
							SplitTest(nameMatnr, "\\", names);
							startFeed(meprocess, stBomlines, bean, names[0], names[1]);
						}
						else {
							printf("beans6\n");
							vector<string> names;
							SplitTest(nameMatnr, ";", names);
							startFeed(meprocess, stBomlines, bean, names);
						}
					}
				}
			}
		}
	}
	else {
		//map<string, vector<FeedRule>> nameMap;
		map<string, vector<FeedRule>>::iterator it;
		//名称模糊匹配
		for (it = nameMap.begin(); it != nameMap.end(); it++) {
			string s = it->first;
			char* nowName;
			AOM_ask_value_string(mantr, "object_name", &nowName);
			if (strstr(nowName, s.c_str()) != NULL) {
				vector<FeedRule> beans = nameMap[s];
				printf("beans7===>%zd\n", beans.size());
				for (int t = 0; t < beans.size(); t++) {
					FeedRule bean = beans[t];
					printf("beans8===>%s %s\n", bean.yjgx.c_str(), bean.ejgx.c_str());
					if (bean.tlth.empty()) {
						//全投
						startFeed(meprocess, stBomlines, bean, "");
					}
					else {
						//剩下全投
						if (bean.tlth.compare("else") == 0) {
							printf("beans9\n");
							startFeed(meprocess, stBomlines, bean, "");
						}
						else {
							string nameMatnr = bean.tlth;
							//按名称模糊匹配投
							if (strstr(nameMatnr.c_str(), "*") != NULL) {
								printf("beans10\n");
								vector<string> liVec;
								string nameLike;
								SplitTest(nameMatnr, "*", liVec);
								for (int x = 0; x < liVec.size(); x++) {
									if (!liVec[x].empty()) {
										nameLike = liVec[x];
									}
								}
								startFeed(meprocess, stBomlines, bean, nameLike);
							}
							else {
								//按名称精准匹配投料
								if (strstr(nameMatnr.c_str(), "\\") != NULL) {
									printf("beans11\n");
									vector<string> names;
									SplitTest(nameMatnr, "\\", names);
									printf("beans===>%s %s\n", names[0].c_str(), names[1].c_str());
									startFeed(meprocess, stBomlines, bean, names[0], names[1]);
								}
								else {
									printf("beans12\n");
									vector<string> names;
									SplitTest(nameMatnr, ";", names);
									startFeed(meprocess, stBomlines, bean, names);
								}
							}
						}
					}
				}
			}
		}
	}


	ITKCALL(BOM_close_window(ebom_window));
}

void readPbomMsg(tag_t bom_line, string &errBuffer, map<string, vector<FeedRule>> drawMap,
	map<string, vector<FeedRule>> nameMap, char *loginId, boolean isback) {
	int c_line_count;
	tag_t * c_line_tags;
	ITKCALL(BOM_line_ask_all_child_lines(bom_line, &c_line_count, &c_line_tags));
	tag_t rev;
	char *id, *objName;
	ITKCALL(AOM_ask_value_tag(bom_line, "bl_line_object", &rev));
	ITKCALL(AOM_ask_value_string(rev, "item_id", &id));
	ITKCALL(AOM_ask_value_string(rev, "object_name", &objName));
	if (c_line_count > 0 && (isSt(rev) == 1 || tc_strstr(objName, "变压器") != NULL || isback)) {
		auto start = std::chrono::high_resolution_clock::now();

		int n_references = 0;
		int* levels = 0;
		tag_t* references_tag = NULLTAG, user;
		char** relation_type_name = NULL, *duser;
		//通过引用关系查找到变更单
		ITKCALL(WSOM_where_referenced(rev, 1, &n_references, &levels, &references_tag, &relation_type_name));
		//boolean hasProcess = false;
		int meNum = 0;
		tag_t meprocess;
		ITKCALL(AOM_ask_value_tag(rev, "owning_user", &user));
		ITKCALL(AOM_ask_value_string(user, "user_id", &duser));
		for (int i = 0; i < n_references; i++)
		{
			char* refType;
			tag_t refTag = references_tag[i];
			ITKCALL(AOM_ask_value_string(refTag, "object_type", &refType));
			if (strcmp(refType, "MEProcessRevision") == 0) {
				//hasProcess = true;
				//break;
				meNum = meNum + 1;
				meprocess = refTag;
			}
		}
		printf("loginUser===>%s,ownerUser===>%s\n", loginId, duser);
		//if (strcmp(duser, loginId) == 0) {
		if (meNum == 0) {
			errBuffer.append(id).append(":请关联工艺后重新操作.\n");
			//return 1;
		}
		if (meNum > 1) {
			errBuffer.append(id).append("请取消多余关联工艺后重新操作.\n");
			//return 1;
		}
		if (meNum == 1) {
			AutoFeedBom(rev, meprocess, drawMap, nameMap);
		}
		//}
		auto end = std::chrono::high_resolution_clock::now();
		std::chrono::duration<double> elapsed1 = end - start;
		printf("readPbomMsg time：%f\n", elapsed1.count());
	}
	else {
		char *os = NULL;
		ITKCALL(AOM_ask_value_string(bom_line, "object_string", &os));
		printf("readPbomMsg else===>%s\n", os);
	}
	for (int i = 0; i < c_line_count; i++) {
		readPbomMsg(c_line_tags[i], errBuffer, drawMap, nameMap, loginId, false);
	}
}
//判断是否为备件包
bool isBack(char* objName, vector<vector<string>> back_prefs) {
	boolean isback = false;
	for (int i = 0; i < back_prefs.size() && !isback; i++) {
		vector<string> backs = back_prefs[i];
		for (int j = 0; j < back_prefs.size(); j++) {
			if (tc_strstr(objName, backs[j].c_str()) != NULL) {
				isback = true;
				break;
			}
		}
	}
	return isback;
}

void AutoFeeding(tag_t matnrRev, vector<vector<string>> back_prefs, string &errBuffer,
	map<string, vector<FeedRule>> drawMap, map<string, vector<FeedRule>> nameMap, char *loginId) {

	tag_t mantr = getPBomTag(matnrRev);
	//lidy20240203备件包工艺路线指派
	char *objName = NULL;
	ITKCALL(AOM_ask_value_string(mantr, "object_name", &objName));
	//首选项格式：组名:匹配字段1;匹配字段2
	boolean isback = isBack(objName, back_prefs);

	//遍历BOM获取所有要投料的
	tag_t* bvr_list = NULLTAG, ebom_window = NULLTAG, bom_line = NULLTAG;
	int bvr_count = 0;
	ITKCALL(ITEM_rev_list_bom_view_revs(mantr, &bvr_count, &bvr_list));
	ITKCALL(BOM_create_window(&ebom_window));
	ITKCALL(BOM_set_window_top_line(ebom_window, NULL, mantr, NULLTAG, &bom_line));

	readPbomMsg(bom_line, errBuffer, drawMap, nameMap, loginId, isback);

	ITKCALL(BOM_close_window(ebom_window));
}

void getParents(tag_t matnrRev, vector<tag_t>& feeds, vector<vector<string>> back_prefs) {
	int n_parents = 0, *levels;
	tag_t* parents = NULLTAG;
	ITKCALL(PS_where_used_all(matnrRev, 1, &n_parents, &levels, &parents));
	for (int i = 0; i < n_parents; i++) {
		char* type = NULL;
		ITKCALL(AOM_ask_value_string(parents[i], "object_type", &type));
		if (tc_strcmp(type, "MEProcessRevision") == 0) {
			continue;
		}
		else if (tc_strcmp(type, "Part Revision") != 0) {
			getParents(parents[i], feeds, back_prefs);
			continue;
		}
		char *objName = NULL;
		ITKCALL(AOM_ask_value_string(parents[i], "object_name", &objName));
		int st = isSt(parents[i]);
		if (st == 1 || tc_strstr(objName, "变压器") != NULL || isBack(objName, back_prefs)) {
			feeds.push_back(parents[i]);
		}
		else if (st == 0) {
			//如果找到外购，就停止继续遍历，这条线就退出
			continue;
		}
		else {
			getParents(parents[i], feeds, back_prefs);
		}
	}
}

void getNewRev(string wm, bool isp, vector<tag_t> feeds, map<string, string>& revMap, map<string, tag_t>& feedMap) {
	for (int j = 0; j < feeds.size(); j++) {
		char *isP2 = NULL;
		ITKCALL(AOM_ask_value_string(feeds[j], "zt2_ifpbom", &isP2));
		if (tc_strcmp(isP2, isp ? "P" : "") == 0) {
			char *zt2_MaterialNo2 = NULL, *zt2_WBSNo2 = NULL;
			ITKCALL(AOM_ask_value_string(feeds[j], "zt2_WBSNo", &zt2_WBSNo2));
			ITKCALL(AOM_ask_value_string(feeds[j], "zt2_MaterialNo", &zt2_MaterialNo2));
			string wm2 = zt2_WBSNo2;
			wm2.append("&").append(zt2_MaterialNo2);
			if (wm2 == wm) {
				date_t date;
				ITKCALL(AOM_ask_value_date(feeds[j], "creation_date", &date));
				string date_s = getDateString(date);
				if (revMap.count(wm) == 0 || date_s > revMap[wm]) {
					revMap[wm] = date_s;
					feedMap[wm] = feeds[j];
				}
			}
		}
	}
}

//int EbomToPMethod(void *returnValue);
int AutoFeeding(void *returnValue) {
	printf("*******************  AutoFeeding start  *******************\n");
	auto start = std::chrono::high_resolution_clock::now();
	string sql = "select MC,ZZMB,XH,TLTH,LX,TL,YJGX,EJGX from CHINT_GYGL_001 WHERE LX is not NULL ORDER BY XH ";

	cutVec.clear();
	/*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);*/
	POM_AM__set_application_bypass(true);
	char *loginId = NULL;
	ITKCALL(POM_get_user_id(&loginId));
	int ifail = ITK_ok;
	tag_t matnrRev;
	char *revUid;
	ITKCALL(USERARG_get_string_argument(&revUid));
	ITK__convert_uid_to_tag(revUid, &matnrRev);

	string errBuffer;

	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]);
	string errorBuff;
	//map<string,
	printf("url ==> %s \n", url.c_str());
	if (ConnServer(url_vals[3], url_vals[4], (char*)url.c_str()) == -1)
	{
		printf("提示:中间数据表访问失败\n");
		//ifail = 1;
	}
	char selectCPZ[200], selectGyId[200];
	int outputColumn1 = 0, outputValueCount1 = 0;
	char*** outputValue1 = NULL;
	sprintf(selectGyId, sql.c_str());
	printf("search2 %s \n", selectGyId);
	QuerySQLNoInputParam(selectGyId, &outputColumn1, &outputValueCount1, &outputValue1);
	printf("search22\n");
	map<string, vector<FeedRule>> drawMap;
	map<string, vector<FeedRule>> nameMap;
	for (int j = 0; j < outputValueCount1; j++) {
		string name = outputValue1[j][0];
		string zzmb = outputValue1[j][1];
		string num = outputValue1[j][2];
		string tlth = outputValue1[j][3];
		string type = outputValue1[j][4];
		string tl = outputValue1[j][5];
		string yjgx = outputValue1[j][6];
		string ejgx = outputValue1[j][7];
		FeedRule ruleBean;
		ruleBean.name = name;
		ruleBean.zzmb = zzmb;
		ruleBean.xh = num;
		ruleBean.tlth = tlth;
		ruleBean.type = type;
		ruleBean.tl = tl;
		ruleBean.yjgx = yjgx;
		ruleBean.ejgx = ejgx;
		if (strstr(zzmb.c_str(), "ZDB") != NULL) {
			if (drawMap.count(zzmb) == 0) {
				vector<FeedRule> feedRuleVec;
				feedRuleVec.push_back(ruleBean);
				drawMap[zzmb] = feedRuleVec;
			}
			else {
				drawMap[zzmb].push_back(ruleBean);
			}
		}
		else {
			if (nameMap.count(zzmb) == 0) {
				vector<FeedRule> feedRuleVec;
				feedRuleVec.push_back(ruleBean);
				nameMap[zzmb] = feedRuleVec;
			}
			else {
				nameMap[zzmb].push_back(ruleBean);
			}
		}
	}
	int back_num = 0;
	char** back_vals = NULL, *group_name = NULL;
	tag_t group = NULLTAG;
	vector<string> group_names;
	ITKCALL(POM_ask_group(&group_name, &group));
	Split(group_name, ".", group_names);
	printf("group_name=======%s\n", group_names[0].c_str());
	ITKCALL(PREF_ask_char_values("CHINT_PROCESS_RULE", &back_num, &back_vals));
	vector<vector<string>> back_prefs;
	for (int i = 0; i < back_num; i++) {
		vector<string> group_backs;
		Split(back_vals[i], ":", group_backs);
		if (tc_strcmp(group_backs[0].c_str(), group_names[0].c_str()) == 0) {
			vector<string> backs;
			Split(group_backs[1], ";", backs);
			back_prefs.push_back(backs);
		}
	}
	char *objName = NULL;
	ITKCALL(AOM_ask_value_string(matnrRev, "object_name", &objName));

	if (isSt(matnrRev) == 0) {
		errBuffer.append("请选择自制件");
	}
	else if (isSt(matnrRev) == 1 || tc_strstr(objName, "变压器") != NULL || isBack(objName, back_prefs)) {
		AutoFeeding(matnrRev, back_prefs, errBuffer, drawMap, nameMap, loginId);
	}
	else {
		//lidy20240807若选中对象为虚拟件，需要向上找到最终的E或者P物料进行投料
		vector<tag_t> feeds;
		getParents(matnrRev, feeds, back_prefs);
		map<string, string> revMap;
		map<string, tag_t> feedMap;
		for (int i = 0; i < feeds.size(); i++) {
			//如果是E就找P，如果有P就投p，如果没p就找最新的e
			char *os = NULL, *zt2_MaterialNo = NULL, *zt2_WBSNo = NULL;
			ITKCALL(AOM_ask_value_string(feeds[i], "object_string", &os));
			printf("feeds===>%s\n", os);
			ITKCALL(AOM_ask_value_string(feeds[i], "zt2_WBSNo", &zt2_WBSNo));
			ITKCALL(AOM_ask_value_string(feeds[i], "zt2_MaterialNo", &zt2_MaterialNo));
			string wm = zt2_WBSNo;
			wm.append("&").append(zt2_MaterialNo);
			if (feedMap.count(wm) > 0) {
				continue;
			}
			getNewRev(wm, true, feeds, revMap, feedMap);
			if (revMap.count(wm) == 0) {
				getNewRev(wm, false, feeds, revMap, feedMap);
			}
		}
		for (auto it = feedMap.begin(); it != feedMap.end(); ++it) {
			tag_t feed = it->second;
			char *os = NULL;
			ITKCALL(AOM_ask_value_string(feed, "object_string", &os));
			printf("feed===>%s\n", os);
			AutoFeeding(feed, back_prefs, errBuffer, drawMap, nameMap, loginId);
		}
	}

	POM_AM__set_application_bypass(false);

	auto end = std::chrono::high_resolution_clock::now();
	// 计算时间间隔
	std::chrono::duration<double> elapsed = end - start;
	printf("用时：%f\n", elapsed.count());

	//readProcessBom(bom_line, errorBuff);
	string buff = errBuffer;
	if (buff.empty()) {
		buff = "succ";
	}
	*((char**)returnValue) = (char*)MEM_alloc((strlen(buff.c_str()) + 1) * sizeof(char));
	tc_strcpy(*((char**)returnValue), buff.c_str());
	DisConnServer();
	return ITK_ok;
}