#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 <sa/workcontext.h>
#include <ss/ss_errors.h>
#include <ae/datasettype.h>
#include <thread>
// #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"
#include "cJSON.h"
boolean isUseGroup(char *groupName) {
	int url_num = 0;
	char** url_vals = NULL;
	PREF_ask_char_values("CHINT_AssignmentLimits", &url_num, &url_vals);
	if (url_num > 0) {
		if (strstr(url_vals[0], groupName)!=NULL) {
			return true;
		}
	}
	return false;
}
//(char*)projectVec[0].c_str()
tag_t getUserFromYP(char* designId, char** url_vals, int url_num,char* projectId) {
	vector<string> idVector;
	tag_t userTag = NULLTAG;

	char* url;
	PREF_ask_char_value("CHINT_PIUrl", 0, &url);
	string ypUrl = url;
	ypUrl.append("/api/open/task/getTaskInfo/").append(projectId);
	if (url_num > 0) {
		Split(url_vals[0], ";", idVector);
		for (int i = 0; i < idVector.size(); i++) {
			if (strstr(idVector[i].c_str(), designId)!=NULL) {
				vector<string> nameVector;
				Split(idVector[i], "=", nameVector);
				printf("nameVector===>%s \n", nameVector[1].c_str());
				string jsonStr = getAssignFromYP(ypUrl);
				cJSON* json = cJSON_Parse(jsonStr.c_str());
				char *json_to_char = cJSON_Print(json);
				printf("json_to_char===>%s \n", json_to_char);
				cJSON* dataJson = cJSON_GetObjectItem(json, "data");
				int size = cJSON_GetArraySize(dataJson);
				for (int i = 0; i < size; i++) {
					cJSON *arr = cJSON_GetArrayItem(dataJson, i);
					cJSON *taskName = cJSON_GetObjectItem(arr, "taskname");
					if (taskName != NULL && taskName->type == cJSON_String) {
						char* tskName = taskName->valuestring;
						if (strcmp(nameVector[1].c_str(), tskName) == 0) {
							cJSON *userIdJson = cJSON_GetObjectItem(arr, "userid");
							if (userIdJson != NULL && userIdJson->type == cJSON_String) {
								char* userId = userIdJson->valuestring;
								printf("tskName = %s\n", userId);
								printf("tskName = %s\n", tskName);
								SA_find_user(userId, &userTag);
							}
						}
					}
				}
			}
		}
	}
	return userTag;
}

int CHINT_Assignment(EPM_action_message_t msg) {

	int ifail = ITK_ok;
	ECHO("=========================================================\n");
	ECHO("CHINT_Assignment 开始执行\n");
	ECHO("=========================================================\n");
	tag_t root_task = NULLTAG, *sub_tasks = NULL, current_task = NULLTAG, type_tag = NULLTAG;
	int sub_task_count = 0;
	tag_t cur_task = NULLTAG,groupTag;
	char* jobName;
	current_task = msg.task;
	//获取流程名称 截取项目ID
	AOM_ask_value_string(current_task, "job_name", &jobName);
	EPM_ask_root_task(msg.task, &root_task);
	EPM_ask_sub_tasks(root_task, &sub_task_count, &sub_tasks);
	printf("sub_task_count===>%d\n", sub_task_count);
	tag_t reviewTask = NULLTAG;
	for (int i = 0; i < sub_task_count; i++) {
		char*taskType, *objectName;
		WSOM_ask_object_type2(sub_tasks[i], &taskType);
		AOM_ask_value_string(sub_tasks[i],"object_name" ,&objectName);
		if (strcmp("EPMReviewTask", taskType) == 0 && strcmp(objectName,"校对")==0) {
			reviewTask = sub_tasks[i];
		}
	}
	int url_num = 0;
	char** url_vals = NULL, *groupName;
	POM_ask_group(&groupName, &groupTag);
	//首选项 配置哪些组可以使用
	if (isUseGroup(groupName) && reviewTask !=NULLTAG) {
		//1ZDB400000T=铁心校对; 1ZDB860000Y=油箱校对
		PREF_ask_char_values("CHINT_Assignment", &url_num, &url_vals);
		//获取当前节点信息 00089 和 ID前缀
		vector<string>nameVec;
		Split(jobName, "/", nameVec);
		vector<string> projectVec;
		Split(nameVec[0], "-", projectVec);
		tag_t query = NULLTAG, *tags;
		int n_found = 0;
		ITKCALL(QRY_find2("查询项目", &query));
		if (projectVec.size() > 1) {
			char* qry_entries[1] = { "工程编号" }, *qry_values[1] = { (char*)projectVec[1].c_str() };
			ITKCALL(QRY_execute(query, 1, qry_entries, qry_values, &n_found, &tags));
		}
		printf("n_found===>%d\n", n_found);
		for (int t = 0; t < n_found; t++) {
			tag_t project = tags[t], login_group;
			char *id;
			AOM_ask_value_string(project, "item_id", &id);
			tag_t userTag = getUserFromYP((char*)projectVec[0].c_str(), url_vals, url_num, id);
			if (userTag != NULLTAG) {
				int mem_cnt = 0, signoff_cnt = 0, n_signoff = 0;
				tag_t select_signoff_tag, *members, *signoffs;
				EPM_ask_sub_task(reviewTask, EPM_select_signoff_team_task, &select_signoff_tag);
				ITKCALL(SA_ask_user_login_group(userTag, &login_group));
				ITKCALL(SA_find_groupmembers(userTag, login_group, &mem_cnt, &members));
				//移除审核节点的审核人
				tag_t signoffTag;
				EPM_ask_attachments(select_signoff_tag, EPM_signoff_attachment,
					&n_signoff, &signoffs);
				printf(" n_signoff %d \n", n_signoff);
				if (n_signoff > 0) {
					try
					{
						tag_t member = NULLTAG;
						SIGNOFF_TYPE_t type;
						ITKCALL(EPM_ask_signoff_member(signoffs[0], &member, &type));
						tag_t groupmembers[1] = { member };
						int code = 0;
						ITKCALL(code = EPM_remove_signoffs(reviewTask, 1, &groupmembers[0]));
						printf("ifail %d \n", code);
						EMH_clear_errors();
					}
					catch (const IFail &e)
					{
						printf("ifail %d \n", ifail);
						ifail = e.ifail();
						
						if (ifail == EPM_signoff_profile_not_staffed)
						{
							cout << "INFORMATION: The required staffing for the signoff";
							cout << " profiles are not complete." << endl;
						}
					}
				}
				ITKCALL(EPM_create_adhoc_signoff(select_signoff_tag, members[0], &signoff_cnt, &signoffs));
				ITKCALL(EPM_set_adhoc_signoff_selection_done(select_signoff_tag, true));
			}
			
		}
	}
	
	return ifail;
}
void addToFlow(tag_t bom_line,tag_t rootTask_tag, map<string, string> &uidMap) {

	int structs = 0;
	tag_t rev = NULLTAG, *structure_revisions = NULL;
	ITKCALL(AOM_ask_value_tag(bom_line, "bl_line_object", &rev));
	int reference = EPM_reference_attachment;
	int target = EPM_target_attachment;
	//版本有BOM视图且发布
	ITKCALL(AOM_ask_value_tags(rev, "structure_revisions", &structs, &structure_revisions));
	printf("structs===>%d\n", structs);
	if (structs > 0) {
		int statusNum = 0, statusNum2=0;
		char *revUid = NULL, *bomUid = NULL;
		tag_t *release_status_list, *release_status_list2;
		ITK__convert_tag_to_uid(rev, &revUid);
		//printf("revUid:%s\n", revUid);
		if (uidMap.count(revUid) == 0) {
			uidMap[revUid] = "1";
			ITKCALL(AOM_ask_value_tags(rev, "release_status_list", &statusNum, &release_status_list2));
			printf("statusNum===>%d\n", statusNum);
			if (statusNum > 0) {
				//已发布的版本放在引用关系
				ITKCALL(EPM_add_attachments(rootTask_tag, 1, &rev, &reference));
			}
			else {
				tag_t *stageTags;
				int stageNum = 0;
				ITKCALL(AOM_ask_value_tags(rev, "process_stage_list", &stageNum, &stageTags));
				printf("stageNum===>%d\n", stageNum);
				if (stageNum > 0) {
					//已有流程的版本放在引用关系
					ITKCALL(EPM_add_attachments(rootTask_tag, 1, &rev, &reference));
				}
				else {
					//否则放在目标关系
					ITKCALL(EPM_add_attachments(rootTask_tag, 1, &rev, &target));
				}
			}
		}
		
		tag_t struct_revision = structure_revisions[0];
		ITK__convert_tag_to_uid(struct_revision, &bomUid);
		//printf("bomUid:%s\n", bomUid);
		statusNum = 0;
		ITKCALL(AOM_ask_value_tags(struct_revision, "release_status_list", &statusNum, &release_status_list));
		printf("statusNum2===>%d\n", statusNum);
		if (statusNum==0 && uidMap.count(bomUid)==0) {
			uidMap[bomUid] = "1";
			tag_t *stageTags;
			int stageNum = 0;
			ITKCALL(AOM_ask_value_tags(struct_revision, "process_stage_list", &stageNum, &stageTags));
			printf("stageNum2===>%d\n", stageNum);
			if (stageNum > 0) {
				ITKCALL(EPM_add_attachments(rootTask_tag, 1, &struct_revision, &reference));
			}
			else {
				ITKCALL(EPM_add_attachments(rootTask_tag, 1, &struct_revision, &target));
			}
			//ITKCALL(EPM_add_attachments(rootTask_tag, 1, &rev, &attachment_types));
		}
	}
	
	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 num = 0; num < c_line_count; num++) {
		addToFlow(c_line_tags[num], rootTask_tag, uidMap);
	}
}

string getPrefVal(char *url_vals,char *itemId) {
	vector<string> taskComps;
	string name;
	Split(url_vals, ";", taskComps);
	for (int i = 0; i < taskComps.size(); i++) {
		string taskComp = taskComps[i];
		if (strstr(taskComp.c_str(), itemId) != NULL) {
			vector<string> names;
			Split(taskComp, "=", names);
			name = names[1];
		}
	}
	return name;
}

int CHINT_task_complete(EPM_action_message_t msg) {

	int ifail = ITK_ok;
	ECHO("=========================================================\n");
	ECHO("CHINT_task_complete 开始执行\n");
	ECHO("=========================================================\n");
	tag_t root_task = NULLTAG, *sub_tasks = NULL, current_task = NULLTAG, type_tag = NULLTAG;
	int sub_task_count = 0, occur_of_counts = 0;
	tag_t* taskAttches = NULLTAG;
	tag_t cur_task = NULLTAG;
	char* jobName = NULL;
	current_task = msg.task;
	ITKCALL(AOM_ask_value_string(current_task, "job_name", &jobName));
	ITKCALL(EPM_ask_root_task(msg.task, &root_task));
	ITKCALL(EPM_ask_sub_tasks(root_task, &sub_task_count, &sub_tasks));
	ITKCALL(EPM_ask_attachments(root_task, EPM_target_attachment, &occur_of_counts, &taskAttches));
	int url_num = 0;
	char** url_vals = NULL, *uid = NULL, *yp_url = NULL;
	ITKCALL(PREF_ask_char_values("CHINT_TaskComplete", &url_num, &url_vals));
	ITKCALL(PREF_ask_char_value("CHINT_YPTaskURL", 0, &yp_url));

	char* userName = NULL;
	int numl = 0;
	tag_t workContents = NULLTAG, userTag = NULLTAG, *task_list = NULLTAG;
	//EPM_inbox_query
	ITKCALL(POM_get_user(&userName, &userTag));
	ITKCALL(EPM_ask_assigned_tasks(userTag, 2, &numl, &task_list));
	printf("提示:uid%d\n", numl);
	//获取当前节点信息 00089 和 ID前缀
	vector<string>nameVec;
	Split(jobName, "/", nameVec);
	vector<string> projectVec;
	Split(nameVec[0], "-", projectVec);
	//SA_workcontext_invalid_group_member
	tag_t query = NULLTAG, *tags;
	//fields.put("描述", "*" + item_id + "*" + zt2_TYJNo + "*");
	int n_found = 0;
	ITKCALL(QRY_find2("查询项目", &query));
	if (projectVec.size() > 1) {
		char* qry_entries[1] = { "工程编号" }, *qry_values[1] = { (char*)projectVec[1].c_str() };
		ITKCALL(QRY_execute(query, 1, qry_entries, qry_values, &n_found, &tags));
	}
	
	printf("n_found===>%d\n", n_found);
	for (int t = 0; t < n_found; t++) {
		tag_t pItem = tags[t];
		char *zt2_ProjectCode = NULL;
		string tasklists = "";
		//通过项目ID属性item_id找工作列表任务的逻辑改成通过项目属性“zt2_ProjectCode”查找
		ITKCALL(AOM_ask_value_string(pItem, "zt2_ProjectCode", &zt2_ProjectCode));
		string names = getPrefVal(url_vals[0], (char*)projectVec[0].c_str());
		vector<string> nameVec;
		Split(names,"&", nameVec);
		for (int i = 0; i < nameVec.size(); i++) {
			string projName = zt2_ProjectCode;
			projName.append("-").append(nameVec[i]);
			printf("projName %s \n", projName.c_str());
			bool find = true;
			for (int j = 0; j < numl; j++) {
				tag_t taskTag = task_list[j];
				char *taskName = NULL;
				ITKCALL(AOM_ask_value_string(taskTag, "job_name", &taskName));
				printf("taskName %s \n", taskName);
				if (tc_strstr(taskName, projName.c_str()) != NULL && tc_strcmp(taskName, jobName) != 0) {
					ITKCALL(EPM_set_task_result(taskTag, EPM_RESULT_Completed));
					ITKCALL(EPM_trigger_action(taskTag, EPM_complete_action, ""));
				}
			}
			if (find) {
				//有数据需要完成计划任务但是实际要执行任务里没有的，需要单独调用查询执行处理，不需要等待接口返回
				if (tasklists.size() > 0)
					tasklists.append(",");
				tasklists.append("{\"taskname\": \"").append(nameVec[i]).append("\"}");
			}
		}
		if (tasklists.size() > 0) {
			string json = "{\"projectcode\":\"";
			json.append(zt2_ProjectCode).append("\",\"tasklists\":[").append(tasklists).append("]}");
			printf("json %s \n", json.c_str());

			//yp_query(yp_url, json);
			thread newThread(yp_query, yp_url, json);
			newThread.detach();
		}
	}
	return ifail;
}

int CHINT_yptask_complete(EPM_action_message_t msg) {

	ECHO("=========================================================\n");
	ECHO("CHINT_yptask_complete 开始执行\n");
	ECHO("=========================================================\n");
	int ifail = ITK_ok, sub_task_count = 0, targetCnt = 0, url_num = 0, numl = 0;
	char** url_vals = NULL, * userName = NULL, *yp_url = NULL;
	tag_t root_task = NULLTAG, * sub_tasks = NULL, current_task = NULLTAG, type_tag = NULLTAG;
	tag_t* targets = NULLTAG, userTag = NULLTAG, * task_list = NULLTAG, query = NULLTAG;
	vector<string> prefVec;

	ITKCALL(PREF_ask_char_values("CHINT_yptask_complete", &url_num, &url_vals));
	if (url_num == 0) {
		printf("CHINT_yptask_complete首选项配置不正确\n");
		return ifail;
	}
	Split(url_vals[0], ";", prefVec);

	ITKCALL(PREF_ask_char_value("CHINT_YPTaskURL", 0, &yp_url));

	current_task = msg.task;
	ITKCALL(EPM_ask_root_task(msg.task, &root_task));
	ITKCALL(EPM_ask_sub_tasks(root_task, &sub_task_count, &sub_tasks));
	ITKCALL(EPM_ask_attachments(root_task, EPM_target_attachment, &targetCnt, &targets));

	//获取当前用户任务列表
	ITKCALL(POM_get_user(&userName, &userTag));
	ITKCALL(EPM_ask_assigned_tasks(userTag, 2, &numl, &task_list));
	printf("task_list===>%d\n", numl);
	ITKCALL(QRY_find2("查询项目", &query));

	printf("targetCnt===>%d\n", targetCnt);
	for (int t = 0; t < targetCnt; t++) {
		tag_t rev = targets[t], item = NULLTAG;
		char* id = NULL, *type = NULL, *name = NULL;
		string tasklists = "";
		bool finish = true;
		ITKCALL(WSOM_ask_object_type2(rev, &type));
		ITKCALL(WSOM_ask_name2(rev, &name));
		ITKCALL(AOM_ask_value_string(rev, "item_id", &id));
		for (int p = 0; finish && p < prefVec.size(); p++) {
			vector<string> split, types, tasks;
			Split(prefVec[p], "=", split);
			if (tc_strstr(split[0].c_str(), type) == nullptr) {
				//若首选项不包含该对象类型则跳过
				continue;
			}
			printf("pref===>%s\n", prefVec[p].c_str());
			int index = -1;
			Split(split[0], "&", types);
			if (p == 0)
				printf("types===>%zd\n", types.size());
			for (int i = 0; i < types.size(); i++) {
				if (tc_strstr(types[i].c_str(), type) != nullptr) {
					if (tc_strcmp(types[i].c_str(), type) == 0) {
						index = i;
						break;
					}
					else if (tc_strcmp("ZT2_Design3DRevision", type) == 0) {
						//类型如果为ZT2_Design3DRevision，需判断id是否包含首选项中-后的子字符串
						vector<string> sp;
						Split(types[i], "-", sp);
						if (tc_strstr(id, sp[1].c_str()) != NULL) {
							index = i;
							break;
						}
					}
					else {
						//部分类型不仅需要匹配类型，还要匹配名称
						string typeStr = type;
						typeStr.append("-").append(name);
						if (tc_strcmp(types[i].c_str(), typeStr.c_str()) == 0) {
							index = i;
							break;
						}
					}
				}
			}
			printf("index===>%d\n", index);
			if (index < 0) {
				continue;
			}

			//调用查询（查询项目，“zt2_WBSNo”-WBS号，“zt2_ProjectCode”-工程编号）查找对应的项目（ZT2_ProjectItem）
			printf("query\n");
			tag_t* projects = NULLTAG;
			char* zt2_WBSNo = NULL, * zt2_ProjectNo = NULL;
			ITKCALL(ITEM_ask_item_of_rev(rev, &item));
			ITKCALL(AOM_ask_value_string(item, "zt2_WBSNo", &zt2_WBSNo));
			ITKCALL(AOM_ask_value_string(item, "zt2_ProjectNo", &zt2_ProjectNo));
			char* qry_entries[2] = { "WBS号", "工程编号" }, * qry_values[2] = { zt2_WBSNo, zt2_ProjectNo };
			int queryCnt = 0;
			ITKCALL(QRY_execute(query, 2, qry_entries, qry_values, &queryCnt, &projects));
			printf("queryCnt===>%d\n", queryCnt);
			if (queryCnt == 0) {
				printf("未找到项目对象\n");
				finish = false;
				break;
			}

			//根据当前任务流程目标下的item类型，在定义好的首选项中查询另外的对象版本是否已发布
			//（对象存在项目文件夹“1 - 电磁设计”和“2 - 组件布置图”）
			tag_t* projectFolder = NULLTAG, * folders = NULLTAG;
			int pfolderCnt = 0, folderCnt = 0;
			ITKCALL(AOM_ask_value_tags(projects[0], "IMAN_reference", &pfolderCnt, &projectFolder));
			if (pfolderCnt == 0) {
				printf("未找到项目执行文件夹\n");
				finish = false;
				break;
			}
			ITKCALL(AOM_ask_value_tags(projectFolder[0], "contents", &folderCnt, &folders));
			for (int f = 0; f < folderCnt; f++) {
				char* folderName = NULL;
				ITKCALL(WSOM_ask_name2(folders[f], &folderName));
				if (tc_strcmp(folderName, "1-电磁设计") == 0 || tc_strcmp(folderName, "2-组件布置图") == 0) {
					tag_t* subItems = NULLTAG, subRev = NULLTAG;
					int subCnt = 0;
					ITKCALL(AOM_ask_value_tags(folders[f], "contents", &subCnt, &subItems));
					for (int j = 0; j < subCnt; j++) {
						char* subType = NULL, * subId = NULL, * subName = NULL;
						ITKCALL(ITEM_ask_latest_rev(subItems[j], &subRev));
						ITKCALL(WSOM_ask_object_type2(subRev, &subType));
						ITKCALL(WSOM_ask_name2(subRev, &subName));
						ITKCALL(AOM_ask_value_string(subRev, "item_id", &subId));
						for (int i = 0; i < types.size(); i++) {
							if (i != index && tc_strstr(types[i].c_str(), subType) != NULL) {
								if (tc_strcmp(types[i].c_str(), subType) == 0) {
									tag_t* status = NULLTAG;
									int statusCnt = 0;
									ITKCALL(WSOM_status_ask_effectivities(subRev, &statusCnt, &status));
									if (statusCnt == 0) {
										printf("No Status===>%s\n", subId);
										goto ENDCOMPLETE;
									}
									break;
								}
								else if (tc_strcmp("ZT2_Design3DRevision", subType) == 0) {
									//类型如果为ZT2_Design3DRevision，需判断id是否包含首选项中-后的子字符串
									vector<string> sp;
									Split(types[i], "-", sp);
									if (tc_strstr(subId, sp[1].c_str()) != NULL) {
										tag_t* status = NULLTAG;
										int statusCnt = 0;
										ITKCALL(WSOM_status_ask_effectivities(subRev, &statusCnt, &status));
										if (statusCnt == 0) {
											printf("No Status===>%s\n", subId);
											goto ENDCOMPLETE;
										}
										break;
									}
								}
								else {
									//部分类型不仅需要匹配类型，还要匹配名称
									string typeStr = subType;
									typeStr.append("-").append(subName);
									if (tc_strcmp(types[i].c_str(), typeStr.c_str()) == 0) {
										tag_t* status = NULLTAG;
										int statusCnt = 0;
										ITKCALL(WSOM_status_ask_effectivities(subRev, &statusCnt, &status));
										if (statusCnt == 0) {
											printf("No Status===>%s\n", subId);
											goto ENDCOMPLETE;
										}
										break;
									}
								}
							}
						}
					}
				}
			}
			//通过项目ID属性item_id找工作列表任务的逻辑改成通过项目属性“zt2_ProjectCode”查找
			char* zt2_ProjectCode = NULL;
			ITKCALL(AOM_ask_value_string(projects[0], "zt2_ProjectCode", &zt2_ProjectCode));
			Split(split[1], "&", tasks);
			for (int i = 0; i < tasks.size(); i++) {
				string projName = zt2_ProjectCode;
				projName.append("-").append(tasks[i]);
				printf("projName %s \n", projName.c_str());
				bool find = true;
				for (int j = 0; j < numl; j++) {
					tag_t taskTag = task_list[j];
					char* taskName;
					ITKCALL(AOM_ask_value_string(taskTag, "job_name", &taskName));
					printf("taskName %s \n", taskName);
					if (strstr(taskName, projName.c_str()) != NULL) {
						ITKCALL(EPM_set_task_result(taskTag, EPM_RESULT_Completed));
						ITKCALL(EPM_trigger_action(taskTag, EPM_complete_action, ""));
						finish = false;
						find = false;
					}
				}
				if (find) {
					//有数据需要完成计划任务但是实际要执行任务里没有的，需要单独调用查询执行处理，不需要等待接口返回
					if (tasklists.size() > 0)
						tasklists.append(",");
					tasklists.append("{\"taskname\": \"").append(tasks[i]).append("\"}");
				}
			}
			if (tasklists.size() > 0) {
				string json = "{\"projectcode\":\"";
				json.append(zt2_ProjectCode).append("\",\"tasklists\":[").append(tasklists).append("]}");

				thread newThread(yp_query, yp_url, json);
				newThread.detach();
			}
			ENDCOMPLETE:
			printf("ENDCOMPLETE\n");
			break;
		}
	}
	return ifail;
}
int chint_CheckTable_State(EPM_action_message_t msg) {

	int ifail = ITK_ok;
	ECHO("=========================================================\n");
	ECHO("chint_CheckTable_State 开始执行\n");
	ECHO("=========================================================\n");
	tag_t root_task = NULLTAG, *sub_tasks = NULL, current_task = NULLTAG, type_tag = NULLTAG;
	int sub_task_count = 0, occur_of_counts = 0;
	tag_t* taskAttches = NULLTAG;
	tag_t cur_task = NULLTAG;
	char* taskName;
	current_task = msg.task;
	AOM_ask_value_string(current_task,"object_name",&taskName);
	EPM_ask_root_task(msg.task, &root_task);
	EPM_ask_sub_tasks(root_task, &sub_task_count, &sub_tasks);
	EPM_ask_attachments(root_task, EPM_target_attachment, &occur_of_counts, &taskAttches);
	int url_num = 0;
	char** url_vals = NULL;
	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;
	}
	string errmsg;
	for (int count = 0; count < occur_of_counts; count++)
	{
		char *type, *itemId;
		tag_t taskTag = taskAttches[count];
		AOM_ask_value_string(taskTag, "object_type", &type);
		if (strcmp(type, "ZT2_Design3DRevision") == 0) {
			AOM_ask_value_string(taskTag, "item_id", &itemId);
			//检查是否需要校对表 
			vector<string> vec;
			Split(itemId,"-",vec);
			string sql = "select * from CHINT_CHECK_TITLE_TEMPLATE where drawingno = '%s' ";
			char selectRecord[400];
			sprintf(selectRecord, sql.c_str(), vec[0]);
			printf("selectRecord ===> %s\n", selectRecord);
			int outputColumn = 0, outputValueCount = 0;
			char*** outputValue = NULL;
			QuerySQLNoInputParam(selectRecord, &outputColumn, &outputValueCount, &outputValue);
			if (outputValueCount > 0) {
				/*select * from CHINT_CHECK_TITLE where DRAWINGNO = '1ZDB530000X-PLM21' and
					AUDITDATE is not NULL and NUMBEROFCHECKS = (select max(NUMBEROFCHECKS)from CHINT_CHECK_TITLE where DRAWINGNO = '1ZDB530000X-PLM21')*/
				string sqlTitle = "select datastatus,%s from CHINT_CHECK_TITLE where DRAWINGNO = '%s' order by NUMBEROFCHECKS desc ";
				char selectRecord2[400];
				string taskCol = "";
				if (strcmp(taskName, "设计") == 0) {
					//审核
					taskCol = "DESIGNDATE"; //PROOFREADDATE AUDITDATE
				}else if (strcmp(taskName, "校对") == 0) {
					taskCol = "PROOFREADDATE"; //PROOFREADDATE AUDITDATE
				}
				else if (strcmp(taskName, "审核") == 0) {
					taskCol = "AUDITDATE"; //PROOFREADDATE AUDITDATE
				}
				sprintf(selectRecord2, sqlTitle.c_str(), taskCol.c_str(), itemId);
				int outputColumn1 = 0, outputValueCount1 = 0;
				char*** outputValue1 = NULL;
				printf("selectRecord2 ===> %s\n", selectRecord2);
				QuerySQLNoInputParam(selectRecord2, &outputColumn1, &outputValueCount1, &outputValue1);
				if (outputValueCount1>0) {
					//string status = ;
					//string date = outputValue1[0][1];
					if (strcmp(outputValue1[0][0],"正式提交") != 0 || strcmp(outputValue1[0][1], "") == 0) {
						ifail = 1;
						errmsg.append("图纸:").append(itemId).append(" 校对表没有正式提交,请检查.\n");
					}
				}
				else {
					ifail = 1;
					errmsg.append("图纸:").append(itemId).append(" 没有校对表,请检查.\n");
				}
			}
		}
	}
	DisConnServer();
	if (ifail == 1) {
		EMH_store_error_s1(EMH_severity_user_error, EMH_USER_error_base, errmsg.c_str());
	}
	return ifail;
}
int chint_check_ZC_ZJ_BOM(EPM_action_message_t msg) {

	int ifail = ITK_ok;
	ECHO("=========================================================\n");
	ECHO("chint_check_ZC_ZJ_BOM 开始执行\n");
	ECHO("=========================================================\n");
	tag_t root_task = NULLTAG, *sub_tasks = NULL, current_task = NULLTAG, type_tag = NULLTAG;
	int sub_task_count = 0, occur_of_counts = 0;
	tag_t* taskAttches = NULLTAG;
	tag_t cur_task = NULLTAG;

	current_task = msg.task;

	EPM_ask_root_task(msg.task, &root_task);
	EPM_ask_sub_tasks(root_task, &sub_task_count, &sub_tasks);
	EPM_ask_attachments(root_task, EPM_target_attachment, &occur_of_counts, &taskAttches);
	string errmsg;
	for (int count = 0; count < occur_of_counts; count++)
	{
		char *type, *itemId;
		tag_t taskTag = taskAttches[count],ebom_window,bom_line;
		AOM_ask_value_string(taskTag, "object_type", &type);
		if (strstr(type, "ZT2_MainMat") != NULL) {
			//主材BOM检查BOM行属性ZT2_REMARK

			ITKCALL(BOM_create_window(&ebom_window));
			ITKCALL(BOM_set_window_top_line(ebom_window, NULL, taskTag, NULLTAG, &bom_line));
			boolean flag = false;
			int c_line_count;
			tag_t * c_line_tags;
			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*ztRemark;
				tag_t line = c_line_tags[i];
				AOM_ask_value_string(line,"ZT2_Remark",&ztRemark);
				if (strcmp(ztRemark, "") != 0) {
					flag = true;
				}
			}
			if (!flag) {
				ifail = 1;
				char*itemID;
				AOM_ask_value_string(taskTag, "item_id", &itemID);
				errmsg.append("主材BOM:").append(itemID).append(" 未填写备注，请填写备注后重新执行.\n");
				//当前数据未填写备注，请填写备注后重新执行
			}
			ITKCALL(BOM_close_window(ebom_window));
		}
		else if (strcmp(type, "ZT2_RequisitionRevision") == 0) {
			//提前请购单，检查下面有没有主材BOM
			ITKCALL(BOM_create_window(&ebom_window));
			ITKCALL(BOM_set_window_top_line(ebom_window, NULL, taskTag, NULLTAG, &bom_line));
			int c_line_count;
			tag_t * c_line_tags;
			boolean flag = false;
			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*ztRemark;
				tag_t line = c_line_tags[i];
				AOM_ask_value_string(line, "fnd0bl_line_object_type", &ztRemark);
				if (strcmp(ztRemark, "ZT2_MainMatRevision") == 0) {
					flag = true;
				}
			}
			if (!flag) {
				ifail = 1;
				char*itemID;
				AOM_ask_value_string(taskTag, "item_id", &itemID);
				errmsg.append("提前请购组件BOM:").append(itemID).append(" 缺少主材BOM成分,请检查BOM,并重新执行.\n");
				//当前数据未填写备注，请填写备注后重新执行
			}
			ITKCALL(BOM_close_window(ebom_window));
		}
		
	}
	if (ifail == 1) {
		EMH_store_error_s1(EMH_severity_user_error, EMH_USER_error_base, errmsg.c_str());
	}
	return ifail;
}
int chint_backCheckTable(EPM_action_message_t msg) {

	int ifail = ITK_ok;
	ECHO("=========================================================\n");
	ECHO("chint_backCheckTable 开始执行\n");
	ECHO("=========================================================\n");
	tag_t root_task = NULLTAG, *sub_tasks = NULL, current_task = NULLTAG, type_tag = NULLTAG;
	int sub_task_count = 0, occur_of_counts = 0;
	tag_t* taskAttches = NULLTAG;
	tag_t cur_task = NULLTAG;

	current_task = msg.task;

	EPM_ask_root_task(msg.task, &root_task);
	EPM_ask_sub_tasks(root_task, &sub_task_count, &sub_tasks);
	EPM_ask_attachments(root_task, EPM_target_attachment, &occur_of_counts, &taskAttches);
	int url_num = 0;
	char** url_vals = NULL;
	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 count = 0; count < occur_of_counts; count++)
	{
		char *type,*itemId;
		tag_t taskTag = taskAttches[count];
		AOM_ask_value_string(taskTag, "object_type", &type);
		if (strcmp(type, "ZT2_Design3DRevision") == 0) {
			AOM_ask_value_string(taskTag, "item_id", &itemId);
			string sqlTitle = "select CHECKNO,NUMBEROFCHECKS from CHINT_CHECK_TITLE where DRAWINGNO = '%s' order by NUMBEROFCHECKS desc";
			char selectRecord[400];
			sprintf(selectRecord, sqlTitle.c_str(), itemId);
			int outputColumn = 0, outputValueCount = 0;
			char*** outputValue = NULL;
			printf("search3 ===> %s\n", selectRecord);
			QuerySQLNoInputParam(selectRecord, &outputColumn, &outputValueCount, &outputValue);
			if (outputValueCount > 0) {
				printf("outputValueCount ===> %d\n", outputValueCount);
				string code = outputValue[0][0];
				string cnt = outputValue[0][1];
				printf("code,cnt ===> %s %s \n", code.c_str(), cnt.c_str());
				int num = atoi(cnt.c_str())+1;
				string newCnt = to_string(num);
				string title = "INSERT INTO CHINT_CHECK_TITLE (CHECKNO,CODE, MODELVERSION, NAME, DRAWINGNO,SPEC,WORKING,VERSION , CREATEDATE , OWNINGUSER , MODEDATE , NUMBEROFCHECKS , DATASTATUS , DESIGNDATE , PROOFREADDATE , AUDITDATE , PROOFREADISSUE , AUDITISSUE , DESIGNISSUE,drawingversion) SELECT CHECKNO, CODE, MODELVERSION, NAME, DRAWINGNO, SPEC, WORKING, VERSION, CREATEDATE, OWNINGUSER, MODEDATE, %s, '驳回引用', '', '', '', PROOFREADISSUE, AUDITISSUE, DESIGNISSUE,drawingversion FROM CHINT_CHECK_TITLE WHERE CHECKNO = '%s' and NUMBEROFCHECKS = %s ";
				char selectRecord2[600];
				sprintf(selectRecord2, title.c_str(), newCnt.c_str(), code.c_str(),cnt.c_str());
				printf("selectRecord2 ===> %s\n", selectRecord2);
				ExecuteSQLNoInputParam(selectRecord2);
				ExecuteSQLNoInputParam("commit");
				string details = "INSERT INTO CHINT_CHECK_DETAILS (CHECKNO,CODE,MODELVERSION , NUMBEROFCHECKS , NO , IMCHECKPROJECT , IPCHECKDETIALS , DESIGNRESULT , DESIGNRESULTRULE , PROOFREADRESULT , PROOFREADRESULTRULE 	, ISSTRONGCHECK , DESIGN , DESIGNDATE , PROOFREAD , PROOFREADDATE , \"AUDIT\", AUDITDATE) 	SELECT CHECKNO, CODE, MODELVERSION,%s, NO, IMCHECKPROJECT , IPCHECKDETIALS, DESIGNRESULT, DESIGNRESULTRULE , PROOFREADRESULT, PROOFREADRESULTRULE, ISSTRONGCHECK , DESIGN, DESIGNDATE, PROOFREAD, PROOFREADDATE, \"AUDIT\", AUDITDATE FROM CHINT_CHECK_DETAILS WHERE CHECKNO = '%s' and NUMBEROFCHECKS = %s ";
				char selectRecord3[600];
				sprintf(selectRecord3, details.c_str(), newCnt.c_str(), code.c_str(), cnt.c_str());
				printf("selectRecord3 ===> %s\n", selectRecord3);
				ExecuteSQLNoInputParam(selectRecord3);
				ExecuteSQLNoInputParam("commit");
			}
		}
	}
	DisConnServer();
	return ifail;
}
int chint_add_to_workflow(EPM_action_message_t msg) {

	int ifail = ITK_ok;
	tag_t root_task = NULLTAG, *sub_tasks = NULL, current_task = NULLTAG, type_tag = NULLTAG;
	int sub_task_count = 0, occur_of_counts = 0;
	tag_t* taskAttches = NULLTAG;
	tag_t cur_task = NULLTAG;

	current_task = msg.task;
	ECHO("=========================================================\n");
	ECHO("chint_add_to_workflow 开始执行\n");
	ECHO("=========================================================\n");

	ITKCALL(EPM_ask_root_task(msg.task, &root_task));
	ITKCALL(EPM_ask_sub_tasks(root_task, &sub_task_count, &sub_tasks));
	ITKCALL(EPM_ask_attachments(root_task, EPM_target_attachment, &occur_of_counts, &taskAttches));
	map<string, tag_t> itemMap;
	map<string, string> uidMap;
	for (int count = 0; count < occur_of_counts; count++)
	{
		char *uid;
		tag_t taskTag = taskAttches[count];
		ITK__convert_tag_to_uid(taskTag, &uid);
		uidMap[uid] = "1";
	}
	
	for (int count = 0; count < occur_of_counts; count++)
	{
		//ITKCALL(TCTYPE_ask_object_type(taskAttches[count], &type_tag));
		char *type;
		tag_t taskTag = taskAttches[count];
		ITKCALL(AOM_ask_value_string(taskTag, "object_type", &type));
		if (strcmp(type, "Part Revision") == 0) {
			tag_t itemTag;
			char *itemId;
			ITKCALL(AOM_ask_value_string(taskTag, "item_id", &itemId));
			ITKCALL(ITEM_ask_item_of_rev(taskTag, &itemTag));
			itemMap[itemId] = itemTag;
			break;
		}
		else if (strcmp(type, "ZT2_Design3DRevision") == 0) {
			tag_t* comps;
			int cnt;
			ITKCALL(AOM_ask_value_tags(taskTag, "representation_for", &cnt, &comps));
			for (int i = 0; i < cnt; i++) {
				tag_t comp = comps[i];
				char *partType,*zt2_ifpbom;
				ITKCALL(AOM_ask_value_string(comp, "object_type", &partType));
				ITKCALL(AOM_ask_value_string(comp, "zt2_ifpbom", &zt2_ifpbom));
				if (strcmp(partType, "Part Revision") == 0 && strcmp(zt2_ifpbom,"P")!=0) {
					char *itemId;
					tag_t itemTag;
					ITKCALL(AOM_ask_value_string(comp, "item_id", &itemId));
					ITKCALL(ITEM_ask_item_of_rev(comp, &itemTag));
					if (itemMap.count(itemId) == 0) {
						printf("itemId===>%s\n", itemId);
						itemMap[itemId] = itemTag;
					}
				}
			}
		}
	}
	map<string, tag_t>::iterator it;
	//名称模糊匹配
	for (it = itemMap.begin(); it != itemMap.end(); it++) {
		string s = it->first;
		tag_t part = itemMap[s];
		printf("itemMap===>%s\n", s.c_str());

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

		addToFlow(bom_line, root_task, uidMap);

		ITKCALL(BOM_close_window(ebom_window));
	}
	return ifail;
}

int chint_remove_other_deisgndata(EPM_action_message_t msg) {

	int ifail = ITK_ok;
	tag_t root_task = NULLTAG, *sub_tasks = NULL, current_task = NULLTAG, type_tag = NULLTAG;
	int sub_task_count = 0, occur_of_counts = 0, occur_of_counts2 = 0;
	tag_t* taskAttches = NULLTAG, *taskAttches2 = NULLTAG;
	tag_t cur_task = NULLTAG, owning_user;

	current_task = msg.task;
	ECHO("=========================================================\n");
	ECHO("chint_remove_other_deisgndata 开始执行\n");
	ECHO("=========================================================\n");
	ITKCALL(EPM_ask_root_task(msg.task, &root_task));
	ITKCALL(EPM_ask_sub_tasks(root_task, &sub_task_count, &sub_tasks));
	ITKCALL(EPM_ask_attachments(root_task, EPM_target_attachment, &occur_of_counts, &taskAttches));

	ITKCALL(EPM_ask_attachments(root_task, EPM_reference_attachment, &occur_of_counts2, &taskAttches2));
	ITKCALL(AOM_ask_value_tag(root_task, "owning_user", &owning_user));
	char *userId = NULL;
	ITKCALL(AOM_ask_value_string(owning_user,"user_id",&userId));
	for (int count = 0; count < occur_of_counts2; count++)
	{
		//ITKCALL(TCTYPE_ask_object_type(taskAttches[count], &type_tag));
		char *type = NULL, *tagId = NULL, *os = NULL;
		tag_t taskTag = taskAttches2[count], tagUser;
		ITKCALL(AOM_ask_value_string(taskTag, "object_type", &type));
		ITKCALL(AOM_ask_value_tag(taskTag, "owning_user", &tagUser));
		ITKCALL(AOM_ask_value_string(tagUser, "user_id", &tagId));
		if (strcmp(tagId, userId) != 0) {
			ITKCALL(EPM_remove_attachments(root_task, 1, &taskTag));
			/*if (strcmp(type, "ZT2_Design3DRevision") == 0) {
				ITKCALL(EPM_remove_attachments(root_task, 1, &taskTag));
			}
			else if (strcmp(type, "BOMView Revision") == 0) {
				ITKCALL(EPM_remove_attachments(root_task, 1, &taskTag));
			}*/
		}
	}
	for (int count = 0; count < occur_of_counts; count++)
	{
		//ITKCALL(TCTYPE_ask_object_type(taskAttches[count], &type_tag));
		char *type = NULL, *tagId = NULL, *os = NULL;
		tag_t taskTag = taskAttches[count], tagUser = NULLTAG;
		ITKCALL(AOM_ask_value_string(taskTag, "object_type", &type));
		ITKCALL(AOM_ask_value_string(taskTag, "object_string", &os));
		printf("taskTag:%s===>%s\n", os, type);
		//物料版本和物料视图版本的权限由物料所关联的图纸的所有权进行判断
		//如果物料版本所关联的图纸（itemid是1ZDB开头）是当前流程发起人，那么此物料版本不需要移除，反之需要移除，如果物料关联的2ZD开头的图纸，那么也是不需要移除的
		if (strcmp(type, "Part Revision") == 0) {
			tag_t* comps = NULL;
			int cnt = 0;
			ITKCALL(AOM_ask_value_tags(taskTag, "TC_Is_Represented_By", &cnt, &comps));
			if (cnt > 0) {
				char *id = NULL;
				ITKCALL(AOM_ask_value_string(comps[0], "item_id", &id));
				printf("id===>%s\n", id);
				if (id[0] == '2') {
					continue;
				}
				ITKCALL(AOM_ask_value_tag(comps[0], "owning_user", &tagUser));
			}
			else {
				continue;
			}
		}
		else if (strcmp(type, "BOMView Revision") == 0) {
			int refCnt = 0, *levels = NULL;
			tag_t *refs = NULL;
			char **rels = NULL;
			ITKCALL(WSOM_where_referenced2(taskTag, 1, &refCnt, &levels, &refs, &rels));
			for (int i = 0; i < refCnt; i++) {
				printf("rels===>%s\n", rels[i]);
				if (tc_strcmp(rels[i], "") == 0) {//structure_revisions
					char *revtype = NULL;
					ITKCALL(AOM_ask_value_string(refs[i], "object_type", &revtype));
					printf("revtype===>%s\n", revtype);
					if (tc_strcmp(revtype, "Part Revision") != 0) {
						ITKCALL(AOM_ask_value_tag(taskTag, "owning_user", &tagUser));
						break;
					}
					tag_t* comps = NULL;
					int cnt = 0;
					ITKCALL(AOM_ask_value_tags(refs[i], "TC_Is_Represented_By", &cnt, &comps));
					if (cnt > 0) {
						char *id = NULL;
						ITKCALL(AOM_ask_value_string(comps[0], "item_id", &id));
						printf("id===>%s\n", id);
						if (id[0] == '2') {
							continue;
						}
						ITKCALL(AOM_ask_value_tag(comps[0], "owning_user", &tagUser));
					}
					break;
				}
			}
			if (tagUser == NULLTAG)
				continue;
		}
		else {
			ITKCALL(AOM_ask_value_tag(taskTag, "owning_user", &tagUser));
		}
		ITKCALL(AOM_ask_value_string(tagUser, "user_id", &tagId));
		printf("tagId===>%s\n", tagId);
		if (strcmp(tagId, userId) != 0) {
			ITKCALL(EPM_remove_attachments(root_task, 1, &taskTag));
			/*if (strcmp(type, "ZT2_Design3DRevision") == 0) {
				ITKCALL(EPM_remove_attachments(root_task, 1, &taskTag));
			}
			else if (strcmp(type, "BOMView Revision") == 0) {
				ITKCALL(EPM_remove_attachments(root_task, 1, &taskTag));
			}*/
		}
	}
	return ifail;
}