using BaseOUDAL;
using NPOI.SS.Formula.Functions;
using Qdp.Foundation.Utilities;
using YLErp.DBModels;
using YLErp.DBModels.Consts;
using YLErp.DBModels.Enums;
using YLErp.Model;
using YLErp.Modules.ApiModule;
using YLErp.Modules.TradeDalModule;
using YLErp.Modules.UnderlyingModule;
using static YLErp.ConsGlobal;
namespace YLErp.Modules.TradeModule
{
///
/// 交易OA服务
///
public class TradeOAService : YLBaseService
{
private static readonly IYcLogger logger = LogFactory.GetLogger();
private static readonly System.Net.Http.HttpClient _httpClient = new System.Net.Http.HttpClient
{
Timeout = TimeSpan.FromMinutes(2)
};
public TradeOAService(OptUserInfo userInfo) : base(userInfo)
{
}
public TradeOAService(YLBaseService baseService) : base(baseService)
{
}
///
/// 处理单个交易的OA提交
///
/// 交易ID
/// 处理结果
public async Task ProcessSingleOAAsync(int tradeId)
{
try
{
// 获取交易信息
var trade = DbContext.trade.FirstOrDefault(x => x.id == tradeId);
if (trade == null)
{
return new TradeOAResult { TradeId = tradeId, Success = false, Message = "未找到交易信息" };
}
// 获取交易确认书信息
var tcr = DbContext.trade_contract_r.Where(t => t.Type == ContractTypeEnum.Trade && t.IsValid && t.TradeId == tradeId)
.FirstOrDefault();
trade_contract_document tdoc = null;
if (tcr != null)
{
tdoc = DbContext.trade_contract_document.Where(t => t.Code == tcr.ContractCode && t.Type == tcr.Type).FirstOrDefault();
}
// 将之前的OA记录设置为无效
var existingOAResults = DbContext.tradeContractOaResult.Where(x => x.trade_id == tradeId && x.is_valid == true).ToList();
foreach (var existingResult in existingOAResults)
{
existingResult.is_valid = false;
existingResult.SetOpt(UserInfo);
}
// 创建OA结果记录
var oaResult = new trade_contract_oa_result
{
trade_id = tradeId,
contract_code = tcr?.ContractCode,
status = "提交中",
is_valid = true,
};
oaResult.SetOpt(UserInfo);
DbContext.tradeContractOaResult.Add(oaResult);
await DbContext.SaveChangesAsync();
// 调用OA接口
var oaResp = await CallOAInterfaceAsync(trade, tcr?.ContractCode, tdoc, oaResult.id);
if (oaResp != null && oaResp.code == 0)
{
oaResult.status = "提交成功";
oaResult.oa_fileid = oaResp.data?.requestid;
oaResult.oa_msg = oaResp.data?.msg ?? "提交成功";
}
else
{
oaResult.status = "提交失败";
oaResult.oa_msg = oaResp?.data?.msg ?? "OA接口调用失败";
}
await DbContext.SaveChangesAsync();
return new TradeOAResult { TradeId = tradeId, Success = oaResult.status == "提交成功", Message = oaResult.oa_msg };
}
catch (Exception ex)
{
logger.Error($"处理交易ID {tradeId} 的OA时发生错误: {ex.Message}", ex);
return new TradeOAResult { TradeId = tradeId, Success = false, Message = $"提交OA失败: {ex.Message}" };
}
}
///
/// 上传附件到OA系统
///
/// 文件路径
/// 附件数据列表(包含 annexId 和 annexName)
private async Task> UploadAttachmentAsync(string filePath)
{
try
{
// 从配置文件读取上传配置
var oaConfigSection = AppManager.GetConfiguration().GetSection("oa_confg");
var uploadUrl = oaConfigSection["UploadUrl"];
var systemToken = oaConfigSection["SystemToken"];
if (string.IsNullOrEmpty(uploadUrl))
{
logger.Info("OA接口配置中UploadUrl为空");
throw new Exception("OA接口配置中上传地址为空");
}
if (string.IsNullOrEmpty(systemToken))
{
logger.Info("OA接口配置中SystemToken为空");
throw new Exception("OA接口配置中上传令牌为空");
}
if (!File.Exists(filePath))
{
logger.Info($"附件文件不存在:{filePath}");
throw new Exception("附件文件不存在");
}
// 创建multipart/form-data请求
using (var httpClient = new HttpClient())
{
// 设置超时时间为2分钟
httpClient.Timeout = TimeSpan.FromMinutes(2);
using (var form = new MultipartFormDataContent())
{
// 添加文件
using var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
var fileName = Path.GetFileName(filePath);
form.Add(new StreamContent(fileStream), "file", fileName);
// 添加systemToken
form.Add(new StringContent(systemToken), "systemToken");
// 发送请求
try
{
var response = await httpClient.PostAsync(uploadUrl, form);
response.EnsureSuccessStatusCode(); // 确保响应成功
var responseContent = await response.Content.ReadAsStringAsync();
logger.Info($"附件上传接口返回: {responseContent}");
// 解析响应
try
{
var uploadResponse = JsonHelper.Deserialize(responseContent);
if (uploadResponse != null)
{
if (uploadResponse.code == "0" && uploadResponse.data != null)
{
// 返回完整的附件数据列表(包含 annexId 和 annexName)
logger.Info($"成功上传附件,获取到{uploadResponse.data.Count}个附件");
return uploadResponse.data;
}
else
{
logger.Error($"附件上传失败:{uploadResponse.status},code:{uploadResponse.code}");
throw new Exception($"附件上传失败:{uploadResponse.status}");
}
}
else
{
logger.Error("附件上传响应解析为空");
throw new Exception("附件上传响应解析失败");
}
}
catch (Exception ex)
{
logger.Error($"解析附件上传响应失败:{ex.Message},响应内容:{responseContent}", ex);
throw new Exception($"解析附件上传响应失败:{ex.Message}");
}
}
catch (TaskCanceledException ex)
{
logger.Error($"上传附件时任务被取消:{ex.Message}", ex);
throw new Exception("上传附件超时,请检查网络连接");
}
catch (Exception ex)
{
logger.Error($"上传附件时发生异常:{ex.Message}", ex);
throw;
}
}
}
}
catch (Exception ex)
{
logger.Error($"上传附件时发生异常:{ex.Message}", ex);
throw;
}
}
///
/// 调用OA接口
///
/// 交易信息
/// 合同编号
/// 交易确认书文档
/// OA结果记录ID
/// 是否成功
private async Task CallOAInterfaceAsync(trade trade, string contractCode, trade_contract_document tdoc, int oaResultId)
{
try
{
// 获取OA配置
var oaConfigSection = AppManager.GetConfiguration().GetSection("oa_confg");
var baseUrl = oaConfigSection["BaseUrl"];
var subUrl = oaConfigSection["SubUrl"];
var systemToken = oaConfigSection["SystemToken"];
var systemName = oaConfigSection["SystemName"];
var isNextFlow = oaConfigSection["IsNextFlow"] ?? "0";
var flowId = oaConfigSection["FlowId"];
if (string.IsNullOrEmpty(baseUrl))
{
logger.Info("OA接口配置中BaseUrl为空");
return new GuoLianOAResponse() { code = -1, data = new GuoLianOAData { msg = "OA接口配置中地址为空" } };
}
if (string.IsNullOrEmpty(systemToken))
{
logger.Info("OA接口配置中SystemToken为空");
return new GuoLianOAResponse() { code = -1, data = new GuoLianOAData { msg = "OA接口配置中SystemToken为空" } };
}
// 处理附件
List attachmentDataList = null;
if (tdoc != null && !string.IsNullOrEmpty(tdoc.AbsolutePath))
{
try
{
attachmentDataList = await UploadAttachmentAsync(tdoc.AbsolutePath);
logger.Info($"成功上传附件并获取到annexId:{string.Join(", ", attachmentDataList.Select(a => a.annexId))}");
}
catch (Exception ex)
{
logger.Error($"上传附件失败:{tdoc.AbsolutePath},错误:{ex.Message}", ex);
return new GuoLianOAResponse() { code = -1, data = new GuoLianOAData { msg = "上传附件失败" } };
}
}
if (tdoc == null)
{
logger.Info("未找到确认书文档");
return new GuoLianOAResponse() { code = -1, data = new GuoLianOAData { msg = "未找到确认书文档" } };
}
//通过UserName找到LoginName
var applicantLoginName = DbContextFactory.GetErpBaseContext().SystemUsers.Where(u => u.Name == UserInfo.UserName).Select(u => u.LoginName).FirstOrDefault();
// 构建detailList,yycl(应用场景/附件)放在明细列表中
var detailList = new List