Files
lserp_cs_6.0/其他程序/GetApiData/GetApiData/FrmMain.cs
T
tdx f89aeb9e6c SVN r995
SVN-Revision: r995
2025-09-18 03:55:47 +00:00

588 lines
26 KiB
C#

using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using GetApiData.KingdeeModel; // 你项目里的模型命名空间(保持不变)
using Kingdee.BOS.WebApi.Client; // K3 Cloud API 客户端
using Lskj.Core; // 你项目里的 DBConfig / SqlHelper 等
using Lskj.Util; // IniHelper 等
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace GetApiData
{
public partial class FrmMain : Form
{
#region Fields
private int _stepCount = 0;
// 金蝶 → 本地:字段映射(K3 原字段 -> 本地列别名)
private readonly string FieldKeys_MATERIAL = "FNumber,FName,FSpecification,F_PAEZ_Base,FBaseUnitId.FName,FModifyDate,FModifierId.FName";
private readonly string AsFieldKeys_MATERIAL = "ProductId,appellation,spec,model,Productunitname,Operatedate,OperatorName";
private readonly string FieldKeys_BOM = "FMATERIALID.FNumber,FITEMNAME,FITEMMODEL,FNumber,Fid,FModifyDate";
private readonly string AsFieldKeys_BOM = "ProductId,mappellation,mspec,TechnicsName,Billdocument_Id,Operatedate";
private readonly string FieldKeys_BOMList = "FMATERIALIDCHILD.FNumber,FNUMERATOR,FDENOMINATOR,Fid";
private readonly string AsFieldKeys_BOMList = "ProductId,Famount,Amount,Billdocument_Id";
private readonly string FieldKeys_PRD_MO_Main = "Fid,FBILLNO,FBillType.FNAME,FDate";
private readonly string AsFieldKeys_PRD_MO_Main = "mps_mpt_jdid,mps_mpt_billdocument_id,mps_mpt_inoutspecies,mps_mpt_operatedate";
private readonly string FieldKeys_PRD_MO_List = "FTreeEntity_FEntryId,FBILLNO,FMaterialId.FNumber,FQty,FLot.FNumber";
private readonly string AsFieldKeys_PRD_MO_List = "mps_lpt_jdid,mps_lpt_billdocument_id,mps_lpt_productid,mps_lpt_amount,mps_lpt_waferbatch_id";
private K3CloudApiClient apiClient = new K3CloudApiClient("https://rychip.ik3cloud.com/k3cloud/");
private string zzjgNumber = "";
#endregion
public FrmMain()
{
InitializeComponent();
this.Load += OnFrmMain_Load;
}
#region Form events
private void OnFrmMain_Load(object sender, EventArgs e)
{
// 从 ini 读默认连接参数
textServerName.Text = IniHelper.Read("startColund.ini", "ServiceKey");
textBaseName.Text = IniHelper.Read("startColund.ini", "ServiceData");
k3ServerName.Text = IniHelper.Read("startColund.ini", "K3Service");
k3appId.Text = IniHelper.Read("startColund.ini", "K3AppId");
k3appSecret.Text = IniHelper.Read("startColund.ini", "K3AppSecret");
k3dbId.Text = IniHelper.Read("startColund.ini", "K3DbId");
k3userName.Text = IniHelper.Read("startColund.ini", "K3UserName");
k3number.Text = IniHelper.Read("startColund.ini", "K3Number");
}
private void OnbtnCheck_Click(object sender, EventArgs e)
{
zzjgNumber = "";
resultText.Clear();
if (string.IsNullOrWhiteSpace(textServerName.Text) || string.IsNullOrWhiteSpace(textBaseName.Text))
{
resultText.AppendText("数据库地址或数据库名不能为空!\r\n");
return;
}
if (string.IsNullOrWhiteSpace(k3ServerName.Text))
{
resultText.AppendText("金蝶地址不能为空!\r\n");
return;
}
apiClient = new K3CloudApiClient(k3ServerName.Text);
if (string.IsNullOrWhiteSpace(k3appId.Text))
{
resultText.AppendText("金蝶appId不能为空!\r\n");
return;
}
if (string.IsNullOrWhiteSpace(k3appSecret.Text))
{
resultText.AppendText("金蝶appSecret不能为空!\r\n");
return;
}
if (string.IsNullOrWhiteSpace(k3dbId.Text))
{
resultText.AppendText("金蝶dbId不能为空!\r\n");
return;
}
if (string.IsNullOrWhiteSpace(k3userName.Text))
{
resultText.AppendText("金蝶userName不能为空!\r\n");
return;
}
if (string.IsNullOrWhiteSpace(k3number.Text))
{
resultText.AppendText("金蝶组织机构编码不能为空!\r\n");
return;
}
DBConfig.Instance.ServerName = textServerName.Text.Trim();
DBConfig.Instance.DataBase = textBaseName.Text.Trim();
if (!(LoginByAppSecret() && DBConfig.Instance.CreateConnection()))
{
resultText.AppendText("数据库连接失败!请检查数据库设置\r\n");
return;
}
IniHelper.Write("startColund.ini", "ServiceKey", textServerName.Text);
IniHelper.Write("startColund.ini", "ServiceData", textBaseName.Text);
IniHelper.Write("startColund.ini", "K3Service", k3ServerName.Text);
IniHelper.Write("startColund.ini", "K3AppId", k3appId.Text);
IniHelper.Write("startColund.ini", "K3AppSecret", k3appSecret.Text);
IniHelper.Write("startColund.ini", "K3DbId", k3dbId.Text);
IniHelper.Write("startColund.ini", "K3UserName", k3userName.Text);
IniHelper.Write("startColund.ini", "K3Number", k3number.Text);
resultText.AppendText("数据库连接成功,开始同步...\r\n");
#region 获取组织机构内码
var payload = new
{
Number = k3number.Text,
};
string data = JsonConvert.SerializeObject(payload);
var jsonList = apiClient.View("ORG_Organizations", data);
JObject zzjgJObject = (JObject)JsonConvert.DeserializeObject(jsonList);
if ((zzjgJObject["Result"]["ResponseStatus"]["IsSuccess"] + "").Equals("True"))
{
string name = zzjgJObject["Result"]["Result"]["Name"][0]["Value"] + "";
zzjgNumber = zzjgJObject["Result"]["Result"]["Id"] + "";
resultText.AppendText($"正在同步组织机构名称:{ name},内码:{zzjgNumber}\r\n");
}
else
{
resultText.AppendText($"不存在编码为{ k3number.Text}的组织机构\r\n");
return;
}
#endregion
bool kd2ry = kingdoToRyCheck.Checked;
bool ry2kd = RyToKingdoCheck.Checked;
if (kd2ry && !ry2kd)
{
ResetProgress(10);
Sync_Kingdee_To_Local();
}
else if (!kd2ry && ry2kd)
{
string mainCols = "wms_mjoins_billdocument_id,wms_mjoins_operatedate,wms_mjoins_mstr1,wms_mjoins_bak,wms_mjoins_jdid";
DataTable mainDb = SqlHelper.ExecuteDataTable($"SELECT {mainCols} FROM Wms_BillJoinSMainTab");
ResetProgress(Math.Max(1, mainDb.Rows.Count));
Sync_Ry_To_Kingdee();
}
else if (!kd2ry && !ry2kd)
{
resultText.AppendText("请勾选操作类型\r\n");
}
else
{
string mainCols = "wms_mjoins_billdocument_id,wms_mjoins_operatedate,wms_mjoins_mstr1,wms_mjoins_bak,wms_mjoins_jdid";
DataTable mainDb = SqlHelper.ExecuteDataTable($"SELECT {mainCols} FROM Wms_BillJoinSMainTab");
ResetProgress(10 + Math.Max(1, mainDb.Rows.Count));
Sync_Kingdee_To_Local();
Sync_Ry_To_Kingdee();
}
}
private void OnbtnClose_Click(object sender, EventArgs e) => this.Close();
#endregion
#region K3 Login
private bool LoginByAppSecret()
{
// 注意:以下 appId/appSecret 是硬编码在客户端
string json = apiClient.LoginByAppSecret(k3dbId.Text, k3userName.Text, k3appId.Text, k3appSecret.Text, 2052);
JObject jo = JObject.Parse(json);
return jo.TryGetValue("LoginResultType", out var v) && v?.Value<int>() == 1;
}
#endregion
#region Progress helpers
private void ResetProgress(int maximum)
{
_stepCount = 0;
progressBar.Value = 0;
progressBar.Style = ProgressBarStyle.Blocks;
progressBar.Minimum = 0;
progressBar.Step = 1;
progressBar.MarqueeAnimationSpeed = 100;
progressBar.Maximum = Math.Max(1, maximum);
SetProgressText(0);
}
private void StepProgress()
{
_stepCount++;
if (progressBar.Value < progressBar.Maximum)
progressBar.PerformStep();
double percent = progressBar.Maximum > 0 ? (progressBar.Value * 100.0 / progressBar.Maximum) : 0.0;
SetProgressText(percent);
progressBar.Refresh();
}
private void SetProgressText(double percent)
{
progressBar.Text = $"{percent:0.##}%"; // ProgressBar 本身不显示文本,仅保留
}
#endregion
#region Kingdee API helpers
private static DataTable ToDataTable(List<List<object>> jsonList, DataTable dataBaseShape, string asFieldKeys)
{
var dt = new DataTable();
var cols = asFieldKeys.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < cols.Length; i++)
{
var colName = cols[i];
var type = (dataBaseShape != null && i < dataBaseShape.Columns.Count) ? dataBaseShape.Columns[i].DataType : typeof(string);
dt.Columns.Add(colName, type);
}
if (jsonList != null && jsonList.Count > 0)
{
foreach (var row in jsonList)
{
var dr = dt.NewRow();
for (int j = 0; j < Math.Min(row.Count, dt.Columns.Count); j++)
dr[j] = row[j] ?? "";
dt.Rows.Add(dr);
}
}
return dt;
}
private DataTable GetApiSource(string formId, DataTable localShape, string fieldKeys, string asFieldKeys, string filterStr = "")
{
string filter = BuildOrgFilter(formId, filterStr, zzjgNumber);
var payload = new
{
FormId = formId,
FieldKeys = fieldKeys,
FilterString = filter,
OrderString = "",
TopRowCount = 0,
StartRow = 0,
Limit = 0
};
string data = JsonConvert.SerializeObject(payload);
var jsonList = apiClient.ExecuteBillQuery(data);
var result = ToDataTable(jsonList, localShape, asFieldKeys);
StepProgress();
return result;
}
private DataTable GetApiSource(string formId, string fieldKeys, string filterStr = "")
{
string filter = BuildOrgFilter(formId, filterStr, zzjgNumber);
var payload = new
{
FormId = formId,
FieldKeys = fieldKeys,
FilterString = filter,
OrderString = "",
TopRowCount = 0,
StartRow = 0,
Limit = 0
};
string data = JsonConvert.SerializeObject(payload);
var list = apiClient.ExecuteBillQuery(data)?.ToList() ?? new List<List<object>>();
var cols = fieldKeys.Split(',').ToList();
var dt = new DataTable();
foreach (var c in cols) dt.Columns.Add(c);
foreach (var row in list)
{
var dr = dt.NewRow();
for (int i = 0; i < cols.Count && i < row.Count; i++)
dr[cols[i]] = row[i];
dt.Rows.Add(dr);
}
return dt;
}
private static string BuildOrgFilter(string formId, string filterStr, string zzjgNumber)
{
bool isPrd = (formId == "PRD_MO" || formId == "PRD_MORPT");
string orgField = isPrd ? "FPrdOrgId" : "FUseOrgId";
string baseFilter = $"{orgField}='{zzjgNumber}'";
if (string.IsNullOrWhiteSpace(filterStr)) return baseFilter;
return $"{baseFilter} and {filterStr}";
}
private static DataTable GetDataBase(string tableName)
{
string sql = $"SELECT top 1 * FROM {tableName}";
return SqlHelper.ExecuteDataTable(sql);
}
private static DataTable GetDataBase(string tableName, string asFieldKeys)
{
string sql = $"SELECT {asFieldKeys} FROM {tableName}";
return SqlHelper.ExecuteDataTable(sql);
}
#endregion
#region Diff & Upsert
private static string BuildWhere(string primaryKey, DataRow row)
{
var keys = primaryKey.Split(',').Select(k => k.Trim());
return string.Join(" AND ", keys.Select(k =>
{
string v = row[k] == null ? "" : $"{row[k]}".Replace("'", "''");
return $"{k}='{v}'";
}));
}
private DataTable GetExcept(DataTable firstTable, DataTable secondTable, string primaryKey)
{
try
{
DataTable dataTable = firstTable.Clone();
foreach (DataRow row in firstTable.Rows)
{
DataRow dataRow2 = dataTable.NewRow();
foreach (DataColumn column in firstTable.Columns)
{
dataRow2[column.ColumnName] = row[column.ColumnName];
}
DataRow[] array;
if (primaryKey.Split(',').Length > 1)
{
string text = string.Empty;
for (int num = 0; num < primaryKey.Split(',').Length; num++)
{
text = text + string.Format("{0}='{1}'", primaryKey.Split(',')[num] ?? "", string.Concat(row[primaryKey.Split(',')[num]])) + " And ";
}
array = secondTable.Select(text.TrimEnd(' ', 'd', 'n', 'A'));
}
else
{
array = secondTable.Select(string.Format("{0}='{1}'", primaryKey ?? "", string.Concat(row[primaryKey])));
}
if (array.Length > 0)
{
for (int num = 0; num < array[0].ItemArray.Length; num++)
{
if (array[0][num].GetType() == typeof(DateTime))
{
if (string.IsNullOrEmpty(string.Concat(array[0][num])))
{
array[0][num] = DateTime.Now;
}
if (string.IsNullOrEmpty(string.Concat(row[num])))
{
row[num] = DateTime.Now;
}
if (Convert.ToDateTime(string.Concat(array[0][num])).ToString("yyyy-MM-dd HH:mm:ss") != Convert.ToDateTime(string.Concat(row[num])).ToString("yyyy-MM-dd HH:mm:ss"))
{
dataTable.Rows.Add(dataRow2);
break;
}
}
else if (array[0][num].GetType() == typeof(decimal))
{
if (!Convert.ToDecimal(string.Concat(array[0][num])).Equals(Convert.ToDecimal(string.Concat(row[num]))))
{
dataTable.Rows.Add(dataRow2);
break;
}
}
else if (string.Concat(array[0][num]) != string.Concat(row[num]))
{
dataTable.Rows.Add(dataRow2);
break;
}
}
}
else
{
dataTable.Rows.Add(dataRow2);
}
}
return dataTable;
}
catch (Exception)
{
throw;
}
}
private bool GetExceptAndUpdate(DataTable apiSource, DataTable dataBase, string tableName, string primaryKey, string identityKeys, string asfieldKeys)
{
try
{
DataTable dataBase2 = GetDataBase(tableName);
DataTable dataTable = SqlHelper.ExecuteDataTable($"select COLUMN_NAME,IS_NULLABLE from information_schema.columns where table_name = '{tableName}'");
DataTable dataTable2 = new DataTable();
dataTable2 = GetExcept(dataBase, apiSource, primaryKey);
DataTable dataTable3 = new DataTable();
dataTable3 = GetExcept(apiSource, dataBase, primaryKey);
string text = string.Empty;
foreach (DataRow row in dataTable3.Rows)
{
string text2 = string.Empty;
DataRow[] array;
if (primaryKey.Split(',').Length > 1)
{
for (int num = 0; num < primaryKey.Split(',').Length; num++)
{
text2 = text2 + string.Format("{0}='{1}'", primaryKey.Split(',')[num] ?? "", string.Concat(row[primaryKey.Split(',')[num]])) + " And ";
}
text2 = text2.TrimEnd(' ', 'd', 'n', 'A');
array = dataBase.Select(text2);
}
else
{
text2 = string.Format("{0}='{1}'", primaryKey ?? "", string.Concat(row[primaryKey]));
array = dataBase.Select(text2);
}
if (array.Length != 0)
{
foreach (DataColumn column in row.Table.Columns)
{
if (!string.Concat(row[column.ColumnName]).Equals(string.Concat(array[0][column.ColumnName])))
{
string format = "update {0} set {1} = N'{2}' where {3};\r\n";
text += string.Format(format, tableName, column.ColumnName, string.Concat(row[column.ColumnName]).Replace("'", "''"), text2);
}
}
continue;
}
string format2 = "insert into {0} ({1}) values ({2});\r\n";
string text3 = string.Empty;
string text4 = string.Empty;
foreach (DataColumn column2 in dataBase2.Columns)
{
if (asfieldKeys.Split(',').Contains(column2.ColumnName))
{
text4 += string.Format("'{0}',", string.Concat(row[column2.ColumnName]).Replace("'", "''"));
text3 += string.Format(column2.ColumnName + ",");
}
else if (string.Concat(dataTable.Select(string.Format("COLUMN_NAME='{0}'", column2.ColumnName ?? "")).First()["IS_NULLABLE"]) == "NO" && !(column2.ColumnName == identityKeys))
{
if (column2.DataType == typeof(decimal) || column2.DataType == typeof(double) || column2.DataType == typeof(short) || column2.DataType == typeof(int) || column2.DataType == typeof(long))
{
text4 += "0,";
text3 += string.Format(column2.ColumnName + ",");
}
else if (column2.DataType == typeof(DateTime))
{
text4 += $"'{DateTime.Now}',";
text3 += string.Format(column2.ColumnName + ",");
}
else
{
text4 += $"'',";
text3 += string.Format(column2.ColumnName + ",");
}
}
}
text += string.Format(format2, tableName, text3.TrimEnd(','), text4.TrimEnd(','));
}
if (!string.IsNullOrEmpty(text))
{
SqlHelper.ExecuteNonQuery(text);
}
StepProgress();
return true;
}
catch (Exception ex)
{
resultText.AppendText(ex.Message + "\r\n");
StepProgress();
return false;
}
}
#endregion
#region Sync flows
private void Sync_Kingdee_To_Local()
{
try
{
DataTable dbProduct = GetDataBase("p_producttab", AsFieldKeys_MATERIAL);
DataTable apiMaterial = GetApiSource("BD_MATERIAL", dbProduct, FieldKeys_MATERIAL, AsFieldKeys_MATERIAL);
DataTable dbBom = GetDataBase("bom_billtab", AsFieldKeys_BOM);
DataTable apiBom = GetApiSource("ENG_BOM", dbBom, FieldKeys_BOM, AsFieldKeys_BOM);
DataTable dbBomList = GetDataBase("bom_billlisttab", AsFieldKeys_BOMList);
DataTable apiBomList = GetApiSource("ENG_BOM", dbBomList, FieldKeys_BOMList, AsFieldKeys_BOMList);
DataTable dbMoMain = GetDataBase("mps_planTaskMainTab", AsFieldKeys_PRD_MO_Main);
DataTable apiMoMain = GetApiSource("PRD_MO", dbMoMain, FieldKeys_PRD_MO_Main, AsFieldKeys_PRD_MO_Main, "FDate>'2021-10-26'");
DataTable dbMoList = GetDataBase("mps_planTaskListTab", AsFieldKeys_PRD_MO_List);
DataTable apiMoList = GetApiSource("PRD_MO", dbMoList, FieldKeys_PRD_MO_List, AsFieldKeys_PRD_MO_List, "FDate>'2021-10-26'");
if (GetExceptAndUpdate(apiMaterial, dbProduct, "p_producttab", "ProductId", "id", AsFieldKeys_MATERIAL))
resultText.AppendText("金蝶 Material 物料清单 => p_producttab 同步完成\r\n");
else
resultText.AppendText("金蝶 Material 物料清单 => p_producttab 同步失败\r\n");
if (GetExceptAndUpdate(apiBom, dbBom, "bom_billtab", "Billdocument_Id", "id", AsFieldKeys_BOM))
resultText.AppendText("金蝶 BOM 主表 => bom_billtab 同步完成\r\n");
else
resultText.AppendText("金蝶 BOM 主表 => bom_billtab 同步失败\r\n");
if (GetExceptAndUpdate(apiBomList, dbBomList, "bom_billlisttab", "ProductId,Billdocument_Id", "id", AsFieldKeys_BOMList))
resultText.AppendText("金蝶 BOM 明细表 => bom_billlisttab 同步完成\r\n");
else
resultText.AppendText("金蝶 BOM 明细表 => bom_billlisttab 同步失败\r\n");
if (GetExceptAndUpdate(apiMoMain, dbMoMain, "mps_planTaskMainTab", "mps_mpt_billdocument_id", "mps_mpt_id", AsFieldKeys_PRD_MO_Main))
resultText.AppendText("金蝶 PRD_MO 生产订单主表 => mps_planTaskMainTab 同步完成\r\n");
else
resultText.AppendText("金蝶 PRD_MO 生产订单主表 => mps_planTaskMainTab 同步失败\r\n");
if (GetExceptAndUpdate(apiMoList, dbMoList, "mps_planTaskListTab", "mps_lpt_billdocument_id", "mps_lpt_id", AsFieldKeys_PRD_MO_List))
resultText.AppendText("金蝶 PRD_MO 生产订单明细表 => mps_planTaskListTab 同步完成\r\n");
else
resultText.AppendText("金蝶 PRD_MO 生产订单明细表 => mps_planTaskListTab 同步失败\r\n");
}
catch (Exception ex)
{
resultText.AppendText(ex.Message + "\r\n");
}
finally
{
resultText.AppendText("同步结束!\r\n");
}
}
private void Sync_Ry_To_Kingdee()
{
try
{
string mainCols = "wms_mjoins_billdocument_id,wms_mjoins_operatedate,wms_mjoins_mstr1,wms_mjoins_bak,wms_mjoins_jdid";
string listCols = "wms_ljoins_productid,wms_ljoins_rwlno,wms_ljoins_id,wms_ljoins_lstr2,wms_ljoins_lstr1,wms_ljoins_amount,wms_ljoins_famount,wms_ljoins_lstr3,wms_ljoins_batch_id,wms_ljoins_lstr4,wms_ljoins_billdocument_id,wms_ljoins_jdid";
DataTable mainDb = SqlHelper.ExecuteDataTable($"SELECT {mainCols} FROM Wms_BillJoinSMainTab");
DataTable listDb = SqlHelper.ExecuteDataTable($"SELECT {listCols} FROM wms_billjoinslistTab");
DataTable morptApi = GetApiSource("PRD_MORPT", mainDb, "FBillNo,FDate,FWorkshipId.FNumber,FDescription", mainCols);
DataTable moIdNo = GetApiSource("PRD_MO", "Fid,FBillNo");
foreach (DataRow mainRow in mainDb.Rows)
{
try
{
string billNo = $"{mainRow["wms_mjoins_billdocument_id"]}";
string jdid = $"{mainRow["wms_mjoins_jdid"]}".Trim();
bool exists = morptApi.Select($"wms_mjoins_billdocument_id='{billNo.Replace("'", "''")}'").Any();
if (exists || string.IsNullOrEmpty(jdid) || jdid == "0") continue;
var details = listDb.Select($"wms_ljoins_billdocument_id='{billNo.Replace("'", "''")}'").ToList();
if (details.Count == 0) continue;
decimal amount = details.Sum(d => SafeToDecimal(d, "wms_ljoins_amount"));
decimal famount = details.Sum(d => SafeToDecimal(d, "wms_ljoins_famount"));
string jsonDraft = apiClient.Draft("PRD_MORPT",