You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

638 lines
19 KiB

#include "ZF_SendPart.h"
namespace sendBomPart {
std::string fullPath;
char** erpConfig;
char* processUserName;
char* url = NULL;
// 嵌套结构体定义
struct Host {
std::string prod;
std::string ip;
std::string lang;
std::string acct;
std::string timestamp;
};
struct Service {
std::string prod;
std::string name;
std::string ip;
std::string id;
};
struct DataKey {
std::string EntId;
std::string CompanyId;
};
struct DataItem {
std::string bmba003;
std::string bmba011;
std::string bmba012;
std::string bmba010;
std::string bmaacrtdt;
std::string acct;
std::string bmaastus;
};
struct Parameter {
std::string bmba001;
std::vector<DataItem> data;
};
struct StdData {
Parameter parameter;
};
struct Payload {
StdData std_data;
};
// 根结构体
struct Root {
std::string key;
std::string type;
Host host;
Service service;
DataKey datakey;
Payload payload;
};
// 序列化/反序列化适配
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Host, prod, ip, lang, acct, timestamp)
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Service, prod, name, ip, id)
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(DataKey, EntId, CompanyId)
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(DataItem, bmba003, bmba011, bmba012, bmba010, bmaacrtdt, acct, bmaastus)
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Parameter, bmba001, data)
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(StdData, parameter)
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Payload, std_data)
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Root, key, type, host, service, datakey, payload)
std::string tempPath;
// 文件读取与解析函数
Root parseBomJson(const std::string& file_path) {
try {
// 创建文件流对象
std::ifstream file_stream(file_path);
if (!file_stream.is_open()) {
throw std::runtime_error("文件打开失败: " + file_path);
}
// 读取文件内容
std::string file_content(
(std::istreambuf_iterator<char>(file_stream)),
std::istreambuf_iterator<char>());
// JSON解析
json j = json::parse(file_content);
return j.get<Root>();
}
catch (const json::exception& e) {
std::cerr << "JSON解析错误[" << e.id << "]: " << e.what() << std::endl;
throw;
}
catch (const std::exception& e) {
std::cerr << "系统异常: " << e.what() << std::endl;
throw;
}
}
// 写入日志信息到文件 writeBomLog("当前工时: "+ std::to_string(totalGs));
void writeBomLog(const std::string& message) {
std::ofstream logFile(logFilePath, std::ios_base::app); // 以追加模式打开文件
if (logFile.is_open()) {
std::string logEntry = "[" + getCurrentTime() + "] " + message + "\n";
logFile << logEntry;
logFile.close();
}
else {
std::cerr << "无法打开日志文件" << std::endl;
}
}
std::map<std::string, std::string> parseBomConfigString(const std::string& configString, tag_t top_line) {
int ifail = ITK_ok;
std::map<std::string, std::string> configMap;
std::stringstream ss(configString);
std::string keyValuePair;
tag_t attachmentTag = NULLTAG;
tag_t attachTagRev = NULLTAG;
ITKCALL(ifail = AOM_ask_value_tag(top_line, bomAttr_lineItemTag, &attachmentTag));
ITKCALL(ifail = AOM_ask_value_tag(top_line, bomAttr_lineItemRevTag, &attachTagRev));
int count = 0;
// relationValues ==> 对象对应关系下的子对象数组
tag_t* relationValues = NULLTAG;
tag_t form = NULLTAG;
// attachmentTag ==> 当前流程下的对象
ITKCALL(ifail = AOM_ask_value_tags(attachTagRev, "IMAN_master_form_rev", &count, &relationValues));
if (count != 0) {
form = relationValues[0];
}
char* propValue = NULL;
date_t dateValue;
// 使用分号分隔键值对
while (std::getline(ss, keyValuePair, ';')) {
try {
std::stringstream pairStream(keyValuePair);
std::string key, value;
// 使用等号分隔键和值
if (std::getline(pairStream, key, '=') && std::getline(pairStream, value)) {
writeBomLog("当前key ==> " + key);
//configMap[key] = value;
std::string obj, prop;
// 使用 stringstream 和 getline 进行分割
std::stringstream ss(value);
if (std::getline(ss, obj, '.') && std::getline(ss, prop, '.')) {
writeBomLog("obj: " + obj);
writeBomLog("prop: " + prop);
if (obj == "Item") {
if (!isPropertyExist(attachmentTag, prop.c_str())) {
printf("prop %s 不存在\n", prop.c_str());
configMap[key] = "";
continue;
}
if (strcmp(prop.c_str(), "uom_tag") == 0) {
ITKCALL(ifail = AOM_UIF_ask_value(attachmentTag, prop.c_str(), &propValue));
writeBomLog("当前propValue ==> " + std::string(propValue));
configMap[key] = propValue;
}
else {
ITKCALL(ifail = AOM_ask_value_string(attachmentTag, prop.c_str(), &propValue));
writeBomLog("当前propValue ==> " + std::string(propValue));
configMap[key] = propValue;
}
}
else if (obj == "Rev") {
if (!isPropertyExist(attachTagRev, prop.c_str())) {
printf("prop %s 不存在\n", prop.c_str());
configMap[key] = "";
continue;
}
if (strcmp(prop.c_str(), "creation_date") == 0) {
writeBomLog("进入date测试");
ITKCALL(ifail = AOM_ask_value_date(attachTagRev, prop.c_str(), &dateValue));
char createDate[128] = "";
sprintf_s(createDate, "%04d-%02d-%02d %02d:%02d:%02d", dateValue.year, dateValue.month + 1, dateValue.day, dateValue.hour, dateValue.minute, dateValue.second);
propValue = createDate;
}
else if ((strcmp(prop.c_str(), "zf6_cpxsyb") == 0)) {
writeBomLog("进入cpxsyb测试");
/*int cpxsybNum = 0;
char** propValues = NULL;
AOM_ask_value_strings(attachTagRev, prop.c_str(), &cpxsybNum, &propValues);*/
int tempNum = 0;
char** tempValues = NULL;
ITKCALL(ifail = AOM_UIF_ask_values(attachTagRev, prop.c_str(), &tempNum, &tempValues));
std::string tempValue = "";
ITKCALL(ifail = AOM_UIF_ask_values(attachTagRev, prop.c_str(), &tempNum, &tempValues));
for (int i = 0; i < tempNum; i++) {
tempValue += tempValues[i];
tempValue += ";";
}
writeBomLog("当前propValue ==> " + tempValue);
configMap[key] = tempValue;
}
else {
ITKCALL(ifail = AOM_ask_value_string(attachTagRev, prop.c_str(), &propValue));
writeBomLog("当前propValue ==> " + std::string(propValue));
configMap[key] = propValue;
}
}
else if (count != 0 && obj == "Form") {
if (!isPropertyExist(form, prop.c_str())) {
printf("prop %s 不存在\n", prop.c_str());
configMap[key] = "";
continue;
}
ITKCALL(ifail = AOM_ask_value_string(form, prop.c_str(), &propValue));
writeBomLog("当前propValue ==> " + std::string(propValue));
configMap[key] = propValue;
}
else if (obj == "BomLine") {
if (strcmp(prop.c_str(), "bl_quantity") == 0) {
ITKCALL(ifail = AOM_ask_value_string(top_line, prop.c_str(), &propValue));
writeBomLog("当前propValue ==> " + std::string(propValue));
if (propValue == NULL || std::strlen(propValue) == 0) {
propValue = "1";
}
configMap[key] = propValue;
}
else {
ITKCALL(ifail = AOM_ask_value_string(top_line, prop.c_str(), &propValue));
writeBomLog("当前propValue ==> " + std::string(propValue));
configMap[key] = propValue;
}
}
else {
configMap[key] = value;
writeBomLog("当前propValue使用默认值1: " + value);
}
}
else {
writeBomLog("特殊Value处理 ==> " + std::string(value));
// 如果没有正确分割,可以选择存储原始值或处理错误
if (value == "TimeStamp") {
std::string time = getCurrentTimestamp17();
configMap[key] = time;
writeBomLog("当前propValue ==> " + time);
}
/* else if (value == "OwningUser") {
int userNum = 0;
tag_t* owners = NULLTAG;
ITKCALL(ifail = AOM_ask_value_tags(attachTagRev, "owning_user", &userNum, &owners));
if (userNum != 0) {
AOM_ask_value_string(owners[0], "user_name", &propValue);
}
writeBomLog("当前propValue ==> " + std::string(propValue));
configMap[key] = propValue;
DOFREE(owners);
}*/
else if (value == "MaterialClass") {
//获取子行
int count = 0;
tag_t* children_line;
ITKCALL(BOM_line_ask_all_child_lines(top_line, &count, &children_line));
if (count != 0) {
writeBomLog("当前propValue ==> A");
configMap[key] = "A";
}
else {
writeBomLog("当前propValue ==> M");
configMap[key] = "M";
}
}
else {
configMap[key] = value;
writeBomLog("当前propValue使用默认值2: " + value);
}
}
}
}
catch (const std::exception& e) {
writeBomLog("Error: " + std::string(e.what()));
}
}
return configMap;
}
Root exportHeadItem(Root data, std::map<std::string, std::string> outerConfigMap) {
for (const auto& pair : outerConfigMap) {
const std::string& key = pair.first;
const std::string& value = pair.second;
if (key == "key") {
data.key = value;
}
else if (key == "type") {
data.type = value;
}
else if (key == "prod") {
data.host.prod = value;
}
else if (key == "lang") {
data.host.lang = value;
}
else if (key == "acct") {
data.host.acct = value;
}
else if (key == "timestamp") {
data.host.timestamp = value;
}
else if (key == "prod") {
data.service.prod = value;
}
else if (key == "name") {
data.service.name = value;
}
else if (key == "id") {
data.service.id = value;
}
else if (key == "EntId") {
data.datakey.EntId = value;
}
else if (key == "CompanyId") {
data.datakey.CompanyId = value;
}
else if (key == "bmba001") {
data.payload.std_data.parameter.bmba001 = value;
}
}
return data;
}
std::string writeBomJsonToString(Root data) {
std::ostringstream oss;
// 打印 Root 属性
oss << "{\n";
oss << " \"key\": \"" << data.key << "\",\n";
oss << " \"type\": \"" << data.type << "\",\n";
// 打印 Host 属性
oss << " \"host\": {\n";
oss << " \"prod\": \"" << data.host.prod << "\",\n";
oss << " \"ip\": \"" << data.host.ip << "\",\n";
oss << " \"lang\": \"" << data.host.lang << "\",\n";
oss << " \"acct\": \"" << data.host.acct << "\",\n";
oss << " \"timestamp\": \"" << data.host.timestamp << "\"\n";
oss << " },\n";
// 打印 Service 属性
oss << " \"service\": {\n";
oss << " \"prod\": \"" << data.service.prod << "\",\n";
oss << " \"name\": \"" << data.service.name << "\",\n";
oss << " \"ip\": \"" << data.service.ip << "\",\n";
oss << " \"id\": \"" << data.service.id << "\"\n";
oss << " },\n";
// 打印 DataKey 属性
oss << " \"datakey\": {\n";
oss << " \"EntId\": \"" << data.datakey.EntId << "\",\n";
oss << " \"CompanyId\": \"" << data.datakey.CompanyId << "\"\n";
oss << " },\n";
// 打印 Payload 和 StdData 属性
oss << " \"payload\": {\n";
oss << " \"std_data\": {\n";
oss << " \"parameter\": {\n";
oss << " \"bmba001\": \"" << data.payload.std_data.parameter.bmba001 << "\",\n";
oss << " \"data\": [\n";
// 打印每个 DataItem 的属性
for (size_t i = 0; i < data.payload.std_data.parameter.data.size(); ++i) {
const DataItem& di = data.payload.std_data.parameter.data[i];
oss << " {\n";
oss << " \"bmba003\": \"" << di.bmba003 << "\",\n";
oss << " \"bmba011\": \"" << di.bmba011 << "\",\n";
oss << " \"bmba012\": \"" << di.bmba012 << "\",\n";
oss << " \"bmba010\": \"" << di.bmba010 << "\",\n";
oss << " \"bmaacrtdt\": \"" << di.bmaacrtdt << "\",\n";
oss << " \"acct\": \"" << di.acct << "\",\n";
oss << " \"bmaastus\": \"" << di.bmaastus << "\"";
if (i != data.payload.std_data.parameter.data.size() - 1) {
oss << "\n },\n";
}
else {
oss << "\n }\n";
}
}
oss << " ]\n";
oss << " }\n";
oss << " }\n";
oss << " }\n";
oss << "}\n";
return oss.str();
}
DataItem exportDateItem(std::map<std::string, std::string> innerConfigMap) {
DataItem& dataItem = DataItem();
for (const auto& pair : innerConfigMap) {
const std::string& key = pair.first;
const std::string& value = pair.second;
if (key == "bmba003") {
dataItem.bmba003 = value;
}
else if (key == "bmba011") {
dataItem.bmba011 = value;
}
else if (key == "bmba012") {
dataItem.bmba012 = value;
}
else if (key == "bmba010") {
dataItem.bmba010 = value;
}
else if (key == "bmaacrtdt") {
dataItem.bmaacrtdt = value;
}
else if (key == "acct") {
dataItem.acct = value;
}
else if (key == "bmaastus") {
dataItem.bmaastus = value;
}
}
return dataItem;
}
int recursionBOM(tag_t top_line) {
int count = 0;
tag_t* children_line;
tag_t itemRevision = NULLTAG;
ITKCALL(BOM_line_ask_all_child_lines(top_line, &count, &children_line));
if (count > 0) {
ITKCALL(AOM_ask_value_tag(top_line, bomAttr_lineItemRevTag, &itemRevision));
writeBomLog("开始解析json");
Root data = parseBomJson(fullPath);
std::vector<DataItem> dataItems;
// 解析 erpConfig 字符串
std::map<std::string, std::string> outerConfigMap;
std::map<std::string, std::string> innerConfigMap;
writeBomLog("ErpConfig[0]: " + string(erpConfig[0]));
outerConfigMap = parseBomConfigString(erpConfig[0], top_line);
//tag_t tempRev = NULLTAG;
for (int i = 0; i < count; i++) {
//ITKCALL(AOM_ask_value_tag(children_line[i], bomAttr_lineItemRevTag, &tempRev));
writeBomLog("ErpConfig[1]: " + string(erpConfig[1]));
innerConfigMap = parseBomConfigString(erpConfig[1], children_line[i]);
DataItem item = exportDateItem(innerConfigMap);
dataItems.push_back(item);
}
try {
if (string(erpConfig[0]).find("OwningUser") != std::string::npos) {
data.host.acct = processUserName;
}
data.payload.std_data.parameter.data = dataItems;
// 遍历 innerConfigMap 并设置 DataItem 属性
data = exportHeadItem(data, outerConfigMap);
writeBomLog("开始拼接json ==>");
std::string jsonStr = writeBomJsonToString(data);
writeBomLog(jsonStr);
writeBomLog("json拼接成功 <==");
writeBomLog("开始读取json文件");
// 发送 POST 请求
writeBomLog("开始发送Post请求");
string jsonFileName = generate_uuid_v4();
std::string jsonFilePath = tempPath + "\\" + jsonFileName + ".txt";
writeJsonToFile(jsonFilePath, jsonStr);
writeBomLog("json文件已保存到: " + jsonFilePath);
string cmd = "java -jar %ZF_ROOT%\\bin\\SendERP.jar " + std::string(url) + " " + jsonFilePath;
string result;
char buf[8000] = { 0 };
//logf("popen");
FILE* pf = _popen(cmd.c_str(), "r");
while (fgets(buf, sizeof buf, pf)) {
result.append(buf);
}
_pclose(pf);
writeBomLog("result:" + result);
// 检查结果中是否包含 "code": "0",
if (result.length() > 0) {
EMH_store_error_s1(EMH_severity_error, ITK_err, result.c_str());
return -1;
}
else {
writeBomLog("发送成功");
return 0;
}
}
catch (const json::exception& e) {
writeBomLog("JSON序列化错误: " + std::string(e.what()));
return -1;
}
catch (const std::exception& e) {
writeBomLog("标准异常: " + std::string(e.what()));
return -1;
}
for (int i = 0; i < count; i++) {
int ifail = recursionBOM(children_line[i]);
if (ifail != 0) {
return -1;
}
}
}
return 0;
}
}
using namespace sendBomPart;
int ZF_SendPartBOMToERP(EPM_action_message_t msg) {
// 获取日志文件目录路径
// 获取日志文件目录路径
logFilePath = getLogFilePath("ZF_SendPartBOMToERP_");
writeBomLog("=========================物料BOM同步 Start===================");
int ifail = ITK_ok;
char* templateUid = NULL;
ITKCALL(PREF_ask_char_value("ZF_SendPartBOMToERP_URL", 0, &url));
writeBomLog("url : " + std::string(url));
ITKCALL(PREF_ask_char_value("ZF_SendPartBOMToERP_Template", 0, &templateUid));
char* argName = NULL, * argValue = NULL, * arg = NULL;
char objTypes[1024] = "";
bool isExistRev = false;
int arg_cnt = TC_number_of_arguments(msg.arguments);
writeBomLog("参数个数为:" + std::to_string(arg_cnt));
if (arg_cnt > 0)
{
for (int i = 0; i < arg_cnt; i++)
{
arg = TC_next_argument(msg.arguments);
ITKCALL(ifail = ITK_ask_argument_named_value((const char*)arg, &argName, &argValue));
if (strcmp(argName, "type") == 0)
{
if (argValue != NULL)
{
strcpy(objTypes, argValue);
}
}
}
}
MEM_free(argName);
MEM_free(argValue);
std::vector<std::string> typeVector;
getVector(objTypes, typeVector, ';');
tag_t attachmentTag = NULLTAG;
int attachmentCount = 0;
tag_t rootTask = NULLTAG, * attachmentTags = NULLTAG;
ITKCALL(ifail = EPM_ask_root_task(msg.task, &rootTask));
ITKCALL(ifail = EPM_ask_attachments(rootTask, EPM_target_attachment, &attachmentCount, &attachmentTags));
// 获取首选项
tag_t templateDataSet = NULLTAG;
char* fileName = NULL;
ITK__convert_uid_to_tag(templateUid, &templateDataSet);
ITKCALL(AOM_ask_value_string(templateDataSet, "object_name", &fileName));
int n_found = 0;
tag_t* ref_object = NULLTAG;
const char* ref_name = "Text";
//AE_reference_type_t reference_type;
ITKCALL(AE_ask_dataset_named_refs(templateDataSet, &n_found, &ref_object));
//ITKCALL(ifail = AE_ask_dataset_named_ref2(templateDataSet, ref_name, &reference_type, &ref_object));
// 使用 std::string 进行字符串拼接
tempPath = getenv("TEMP");
fullPath = tempPath + "\\" + fileName;
removeFile(fullPath);
// 导出文件到完整路径
if (IMF_export_file(ref_object[0], fullPath.c_str()) != 0) {
writeBomLog("导出文件失败,路径: " + fullPath);
EMH_store_error_s1(EMH_severity_error, ITK_err, "文件导出失败");
return 1;
}
else {
writeBomLog("文件已成功导出到: " + fullPath);
}
int configNum;
ITKCALL(PREF_ask_char_values("ZF_SendPartBOMToERP_Config", &configNum, &erpConfig));
tag_t processUser = NULLTAG;
ITKCALL(AOM_ask_value_tag(rootTask, "owning_user", &processUser));
ITKCALL(AOM_ask_value_string(processUser, "user_id", &processUserName));
//遍历所有的流程目标下的对象
char* itemType = NULL;
writeBomLog(std::to_string(attachmentCount));
for (int i = 0; i < attachmentCount; i++) {
attachmentTag = attachmentTags[i];
if (!isTypeOf(attachmentTag, "ItemRevision")) {
continue;
}
ITKCALL(ifail = AOM_ask_value_string(attachmentTag, "object_type", &itemType));
if (inArrays(typeVector, itemType)) {
tag_t top_line = NULLTAG, window = NULLTAG;
ITKCALL(BOM_create_window(&window)); // 调用 BOM_create_window 创建 BOM 窗口
ITKCALL(BOM_set_window_top_line(window, NULLTAG, attachmentTag, NULLTAG, &top_line));
if (recursionBOM(top_line) != 0) {
writeBomLog("发送异常");
MEM_free(attachmentTags);
MEM_free(itemType);
return -1;
}
}
}
MEM_free(attachmentTags);
MEM_free(itemType);
return ifail;
}