TRS-ZS-574 交易确认书对接OA自动提交审批
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace YLErp.DBModels
|
||||
{
|
||||
@@ -54,6 +55,13 @@ namespace YLErp.DBModels
|
||||
[DisplayName("品种")]
|
||||
public string VarietyIds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// oa账号
|
||||
/// </summary>
|
||||
[DisplayName("OA账号")]
|
||||
[Column("oa_account")]
|
||||
public string OaAccount { get; set; }
|
||||
|
||||
public List<int> VarietyIdList
|
||||
{
|
||||
get
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace YLErp.DBModels
|
||||
{
|
||||
/// <summary>
|
||||
/// 确认书OA审批结果
|
||||
/// </summary>
|
||||
[Table("trade_contract_oa_result")]
|
||||
public class trade_contract_oa_result : DBModelBaseV6
|
||||
{
|
||||
/// <summary>
|
||||
/// 交易id
|
||||
/// </summary>
|
||||
public int trade_id { get; set; }
|
||||
/// <summary>
|
||||
/// 确认书编号
|
||||
/// </summary>
|
||||
public string contract_code { get; set; }
|
||||
/// <summary>
|
||||
/// oa审批返回id
|
||||
/// </summary>
|
||||
public string oa_fileid { get; set; }
|
||||
/// <summary>
|
||||
/// 状态
|
||||
/// </summary>
|
||||
public string status { get; set; }
|
||||
/// <summary>
|
||||
/// oa审批返回消息
|
||||
/// </summary>
|
||||
public string oa_msg { get; set; }
|
||||
/// <summary>
|
||||
/// oa返回url
|
||||
/// </summary>
|
||||
public string oa_url { get; set; }
|
||||
/// <summary>
|
||||
/// 是否有效
|
||||
/// </summary>
|
||||
public bool is_valid { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,10 @@ namespace YLErp
|
||||
/// 用户名称
|
||||
/// </summary>
|
||||
public string UserName { get; set; }
|
||||
/// <summary>
|
||||
/// oa账户
|
||||
/// </summary>
|
||||
public string OaAccount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户组
|
||||
|
||||
@@ -27,10 +27,10 @@ namespace YLErp.UnitTestProject.Modules.UnderlyingModule
|
||||
|
||||
// (5,10]年,应返回10年
|
||||
var code3 = "UNLIMITED_10Y";
|
||||
var maturity3 = new DateTime(2040, 1, 1);
|
||||
var maturity3 = new DateTime(2030, 8, 2);
|
||||
var underlying3 = CreateTestUnderlying(code3, null, maturity3);
|
||||
var valueDate3 = maturity3.AddYears(-7); // 剩余13年
|
||||
var valueDate3_2 = maturity3.AddYears(-10); // 剩余10年
|
||||
var valueDate3_2 = DateTime.Now.Date; // 剩余10年
|
||||
var result3 = UnderlyingHelper.GetApplicableMarginTerm(code3, valueDate3_2);
|
||||
Assert.AreEqual(ConsMarginTerm.TenYear, result3, "(5,10]年 应为10年");
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace YLErp
|
||||
});
|
||||
|
||||
ServiceProvider = services.BuildServiceProvider();
|
||||
|
||||
YLServiceLocator.SetServiceProvider(ServiceProvider);
|
||||
OtcAppContext.Initialize(s =>
|
||||
{
|
||||
var s2 = s.Trim('/').Replace("/", "\\");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Autofac;
|
||||
using Autofac;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Diagnostics;
|
||||
@@ -176,6 +176,14 @@ namespace YLErp
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取配置对象
|
||||
/// </summary>
|
||||
public static IConfiguration GetConfiguration()
|
||||
{
|
||||
return _configuration;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解析IOC容器中的实现(当前主要用于插件)
|
||||
/// </summary>
|
||||
|
||||
@@ -289,6 +289,7 @@ namespace BaseOUDAL
|
||||
State = source.State,
|
||||
UserGroup = source.UserGroup,
|
||||
AccountPost = source.AccountPost + "",
|
||||
OaAccount=source.OaAccount
|
||||
};
|
||||
|
||||
var result = query.OrderBy(u => u.id).ToSearchList(req);
|
||||
|
||||
@@ -37,5 +37,7 @@ namespace BaseOUDAL
|
||||
public string UserGroup { get; set; }
|
||||
|
||||
public string AccountPost { get; set; }
|
||||
|
||||
public string OaAccount { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -405,5 +405,6 @@ namespace YLErp.BLL
|
||||
|
||||
public DbSet<client_margin_config> clientMarginConfig { get; set; }
|
||||
public DbSet<client_margin_detail> clientMarginDetail { get; set; }
|
||||
public DbSet<trade_contract_oa_result> tradeContractOaResult { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -65,6 +65,7 @@ namespace BaseOUDAL
|
||||
AccountPost = newValue.AccountPost;
|
||||
ParentId = newValue.ParentId;
|
||||
VarietyIds = newValue.VarietyIds;
|
||||
OaAccount=newValue.OaAccount;
|
||||
db.SaveChanges();
|
||||
//刷新缓存
|
||||
UserBLL.UpdateUsers();
|
||||
|
||||
@@ -153,7 +153,7 @@ namespace YLErp.Modules.SwapModule
|
||||
var curEodPosis = DealFloatPositions(posiList, realPosiList, eodPositions, todyEodPositions, settleDate, td, preSettleDate, flowEvents);
|
||||
var posiLongNotional = curEodPosis.Where(s => s.PositionType == (int)PositionTypeFlag.Long).Sum(s => s.PosiNotionalValue);
|
||||
var posiShortNotional = curEodPosis.Where(s => s.PositionType == (int)PositionTypeFlag.Short).Sum(s => s.PosiNotionalValue);
|
||||
var closePosiNotional = curEodPosis.Where(s => s.TdCloseQty > 0).Sum(s => s.TdCloseQty * s.ContractSize * s.PosiNetPrice);
|
||||
var closePosiNotional = curEodPosis.Where(s => s.TdCloseQty > 0).Sum(s => s.TdCloseQty * s.ContractSize * s.PosiGrossPrice);
|
||||
var grossPrice = curEodPosis.Where(x => x.PosiDirection > 0).FirstOrDefault()?.PosiGrossPrice ?? 0;
|
||||
//处理利息腿
|
||||
DealInterests(interestList, eodPositions, todyEodPositions, settleDate, td, flowEvents, autoInterests, lastEodSwap, posiLongNotional, posiShortNotional, closePosiNotional, grossPrice, orginPv);
|
||||
|
||||
@@ -535,6 +535,9 @@ namespace YLErp.Modules.TradeModule.DealModule
|
||||
from tcd in tcdsGroup.DefaultIfEmpty()
|
||||
join sp in DbContext.swap_position.AsNoTracking().Where(s => s.IsInitial && s.PositionType > 0 && !s.Invalid)
|
||||
on t.id equals sp.SwapTradeId
|
||||
join oa in DbContext.tradeContractOaResult on t.id equals oa.trade_id into oaTemp
|
||||
from oa in oaTemp.DefaultIfEmpty()
|
||||
where oa == null || oa.is_valid == true
|
||||
select new
|
||||
{
|
||||
t.id,
|
||||
@@ -555,6 +558,9 @@ namespace YLErp.Modules.TradeModule.DealModule
|
||||
tcr.OptDate,
|
||||
tcr.OptName,
|
||||
ContractDocId = tcd != null ? tcd.id : 0,
|
||||
OAStatus = oa != null ? oa.status : "",
|
||||
OAURL = oa != null ? oa.oa_url : "",
|
||||
OAMessage = oa != null ? oa.oa_msg : ""
|
||||
};
|
||||
|
||||
if (req.StartDate != null && req.StartDate != DateTime.MinValue)
|
||||
@@ -611,7 +617,10 @@ namespace YLErp.Modules.TradeModule.DealModule
|
||||
StampDocumentFileName = group.FirstOrDefault().StampDocumentFileName,
|
||||
OptDate = group.FirstOrDefault().OptDate,
|
||||
OptName = group.FirstOrDefault().OptName,
|
||||
ContractDocId = group.FirstOrDefault().ContractDocId
|
||||
ContractDocId = group.FirstOrDefault().ContractDocId,
|
||||
OAStatus = group.FirstOrDefault().OAStatus,
|
||||
OAURL = group.FirstOrDefault().OAURL,
|
||||
OAMessage = group.FirstOrDefault().OAMessage
|
||||
});
|
||||
}
|
||||
result = contractList.OrderByDescending(r => r.TradeDate).AsQueryable().ToSearchList(req);
|
||||
@@ -694,5 +703,9 @@ namespace YLErp.Modules.TradeModule.DealModule
|
||||
|
||||
public int ContractDocId { get; set; }
|
||||
|
||||
public string OAStatus { get; set; }
|
||||
public string OAURL { get; set; }
|
||||
public string OAMessage { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
|
||||
namespace YLErp.Modules.TradeModule
|
||||
{
|
||||
/// <summary>
|
||||
/// OA接口响应模型
|
||||
/// </summary>
|
||||
public class OAResponse
|
||||
{
|
||||
public bool success { get; set; }
|
||||
public long time { get; set; }
|
||||
public int messageCode { get; set; }
|
||||
public string message { get; set; }
|
||||
public OAResponseData data { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OA接口响应数据模型
|
||||
/// </summary>
|
||||
public class OAResponseData
|
||||
{
|
||||
public string url { get; set; }
|
||||
public string fileid { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace YLErp.Modules.TradeModule
|
||||
{
|
||||
/// <summary>
|
||||
/// 交易OA处理结果
|
||||
/// </summary>
|
||||
public class TradeOAResult
|
||||
{
|
||||
public int TradeId { get; set; }
|
||||
public bool Success { get; set; }
|
||||
public string Message { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 交易OA批量处理结果
|
||||
/// </summary>
|
||||
public class TradeOABatchResult : TradeOAResult
|
||||
{
|
||||
// 继承自TradeOAResult,避免重复定义相同属性
|
||||
// 如果需要批量处理特有的属性,可以在这里添加
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
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
|
||||
{
|
||||
/// <summary>
|
||||
/// 交易OA服务
|
||||
/// </summary>
|
||||
public class TradeOAService : YLBaseService
|
||||
{
|
||||
private static readonly IYcLogger logger = LogFactory.GetLogger<TradeOAService>();
|
||||
|
||||
public TradeOAService(OptUserInfo userInfo) : base(userInfo)
|
||||
{
|
||||
}
|
||||
|
||||
public TradeOAService(YLBaseService baseService) : base(baseService)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理单个交易的OA提交
|
||||
/// </summary>
|
||||
/// <param name="tradeId">交易ID</param>
|
||||
/// <returns>处理结果</returns>
|
||||
public async Task<TradeOAResult> 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.success)
|
||||
{
|
||||
oaResult.status = "提交成功";
|
||||
oaResult.oa_fileid = oaResp.data?.fileid;
|
||||
oaResult.oa_msg = oaResp.data?.url;
|
||||
}
|
||||
else
|
||||
{
|
||||
oaResult.status = "提交失败";
|
||||
oaResult.oa_msg = oaResp?.message ?? "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}" };
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 调用OA接口
|
||||
/// </summary>
|
||||
/// <param name="trade">交易信息</param>
|
||||
/// <param name="contractCode">合同编号</param>
|
||||
/// <param name="tdoc">交易确认书文档</param>
|
||||
/// <param name="oaResultId">OA结果记录ID</param>
|
||||
/// <returns>是否成功</returns>
|
||||
private async Task<OAResponse> 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 loginName = UserInfo.OaAccount;
|
||||
var systemKey = oaConfigSection["SystemKey"];
|
||||
var objectClass = oaConfigSection["ObjectClass"];
|
||||
var urgent = int.Parse(oaConfigSection["Urgent"] ?? "1");
|
||||
var issend = int.Parse(oaConfigSection["Issend"] ?? "0");
|
||||
|
||||
if (string.IsNullOrEmpty(loginName))
|
||||
{
|
||||
logger.Error("OA账号未配置");
|
||||
return new OAResponse() { data = null, success = false, message = "OA账号未配置" };
|
||||
|
||||
}
|
||||
if (string.IsNullOrEmpty(baseUrl))
|
||||
{
|
||||
logger.Error("OA接口配置中BaseUrl为空");
|
||||
return new OAResponse() { data = null, success = false, message = "OA接口配置中地址为空" };
|
||||
}
|
||||
|
||||
// 处理附件
|
||||
var attachments = new List<object>();
|
||||
if (tdoc != null && !string.IsNullOrEmpty(tdoc.AbsolutePath))
|
||||
{
|
||||
try
|
||||
{
|
||||
if (File.Exists(tdoc.AbsolutePath))
|
||||
{
|
||||
var fileBytes = await File.ReadAllBytesAsync(tdoc.AbsolutePath);
|
||||
var base64Content = Convert.ToBase64String(fileBytes);
|
||||
var fileName = Path.GetFileName(tdoc.AbsolutePath);
|
||||
|
||||
attachments.Add(new
|
||||
{
|
||||
nrtitle = fileName,
|
||||
nrtype= "1",
|
||||
content = base64Content
|
||||
});
|
||||
|
||||
logger.Info($"成功读取附件文件:{tdoc.AbsolutePath},文件大小:{fileBytes.Length} 字节");
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Error($"附件文件不存在:{tdoc.AbsolutePath}");
|
||||
return new OAResponse() { data = null, success = false, message = $"附件文件不存在" };
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Error($"读取附件文件失败:{tdoc.AbsolutePath},错误:{ex.Message}", ex);
|
||||
return new OAResponse() { data = null, success = false, message = $"读取附件文件失败" };
|
||||
}
|
||||
}
|
||||
|
||||
// 计算同一客户、同一交易日期、同一多空方向的名义本金汇总
|
||||
// 1. 先获取当前交易的多空方向
|
||||
var currentPosition = DbContext.swap_position.AsNoTracking()
|
||||
.Where(sp => sp.SwapTradeId == trade.id && sp.IsInitial && sp.PositionType > 0 && !sp.Invalid)
|
||||
.FirstOrDefault();
|
||||
var currentPositionType = currentPosition.PositionType;
|
||||
// 2. 查询同一客户、同一交易日期的所有有效交易
|
||||
var sameClientTrades = DbContext.trade.AsNoTracking()
|
||||
.Where(t => t.ClientId == trade.ClientId
|
||||
&& t.TradeDate == trade.TradeDate
|
||||
&& t.ValidState != "InValid");
|
||||
|
||||
// 3. 关联持仓表,筛选相同多空方向的持仓
|
||||
var matchingPositions = from t in sameClientTrades
|
||||
join sp in DbContext.swap_position.AsNoTracking()
|
||||
on t.id equals sp.SwapTradeId
|
||||
where sp.PositionType == currentPositionType
|
||||
&& sp.IsInitial && sp.PositionType > 0 && !sp.Invalid
|
||||
select sp;
|
||||
|
||||
// 4. 计算名义本金汇总
|
||||
var totalNotionalPrincipal = matchingPositions.Sum(sp => sp.PosiNotionalValue);
|
||||
var posiTypeStr= currentPositionType == (int)PositionTypeFlag.Long ? "买入" : "卖出";
|
||||
var marginDetail=UnderlyingHelper.GetApplicableMarginRate(trade.ClientId, trade.UnderlyingCode, trade.TradeDate.Value);
|
||||
var marginRate = marginDetail?.init_rate ?? 0;
|
||||
// 构建OA请求参数
|
||||
var oaRequest = new
|
||||
{
|
||||
loginname = loginName,
|
||||
systemkey = systemKey,
|
||||
objectclass = objectClass,
|
||||
title = $"交易确认书OA申请-{trade.ClientName}-{contractCode}",
|
||||
urgent = urgent,
|
||||
issend = issend,
|
||||
copyattfileid = "",
|
||||
je = (double)totalNotionalPrincipal,
|
||||
filerela = new object[0],
|
||||
groupno = "",
|
||||
extinfo = new
|
||||
{
|
||||
busdata = new
|
||||
{
|
||||
BM1 = "",
|
||||
BM2 = "",
|
||||
BGRQ = trade.TradeDate.Value.ToString("yyyy-MM-dd"),
|
||||
NGR1 = "",
|
||||
NGR2 = "",
|
||||
CKDX1 = "",
|
||||
CKDX2 = "",
|
||||
LB = "",
|
||||
QSBGNR = $"各位领导:\n\t\t经友好协商,我司拟与交易对手开展以下场外利率收益互换交易:\n浮动收益交付方\t存款收益接收方\t标的\t方向\t起始日\t到期日\t合约名义本金\t保证金支付方\n浙商证券\t{trade.ClientName}\t{trade.UnderlyingInstrumentTypeCn}\t{posiTypeStr}\t{trade.StartDate?.ToString("yyyy/M/d")}\t{trade.ExerciseDate?.ToString("yyyy/M/d")}\t{totalNotionalPrincipal:N0}元\t{trade.ClientName}\n交易标的满足浙商证券标的池管理要求,交易对手方为非交易商,提供【{marginRate*100}%】名义本金的履约担保品作为初始保证金。保证金预警线与盯市追保符合内外规要求。",
|
||||
MX = new object[0],
|
||||
SQMX = new object[0]
|
||||
},
|
||||
attachments = attachments.ToArray()
|
||||
}
|
||||
};
|
||||
logger.Info($"OA接口参数:{JsonHelper.Serialize(oaRequest)}");
|
||||
// 调用OA接口
|
||||
var httpClient = new HttpClientWrap(baseUrl);
|
||||
var response = httpClient.PostJson("/fileDraft", oaRequest, null);
|
||||
logger.Info($"OA接口返回:{response}");
|
||||
// 解析响应
|
||||
var responseObj = JsonHelper.Deserialize<OAResponse>(response);
|
||||
return responseObj;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Error($"调用OA接口时发生异常,交易ID:{trade.id},异常信息:{ex.Message}", ex);
|
||||
return new OAResponse() { data = null, success = false, message = $"调用OA接口时发生异常" };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -262,12 +262,14 @@ namespace YLErp.Modules.UnderlyingModule
|
||||
int totalMonths = (sourceDate.Value.Year - calcDate.Value.Year) * 12
|
||||
+ (sourceDate.Value.Month - calcDate.Value.Month);
|
||||
|
||||
if (sourceDate.Value.Day < calcDate.Value.Day)
|
||||
double fractionalMonth = 0;
|
||||
if (sourceDate.Value.Day != calcDate.Value.Day)
|
||||
{
|
||||
totalMonths--;
|
||||
int daysInMonth = DateTime.DaysInMonth(sourceDate.Value.Year, sourceDate.Value.Month);
|
||||
fractionalMonth = (sourceDate.Value.Day - calcDate.Value.Day) / (double)daysInMonth;
|
||||
}
|
||||
|
||||
double yearTerm = totalMonths / 12.0;
|
||||
double yearTerm = (totalMonths + fractionalMonth) / 12.0;
|
||||
return yearTerm;
|
||||
}
|
||||
/// <summary>
|
||||
|
||||
@@ -265,6 +265,7 @@ namespace YLErp.Web
|
||||
user.UserToken = systemuser.UserToken;
|
||||
user.UserId = systemuser.Id;
|
||||
user.UserName = systemuser.Name;
|
||||
user.OaAccount = systemuser.OaAccount;
|
||||
using (var db = new ErpBaseContext())
|
||||
{
|
||||
user.Roles = (from o in db.RoleUsers
|
||||
|
||||
@@ -684,13 +684,13 @@ namespace YLErp.Web.Controllers
|
||||
public ActionResult userEditJson(IFormCollection collection, SystemUserDto req)
|
||||
{
|
||||
var result = UserEdit(req.Id, req.LoginName, req.Name, req.Password,
|
||||
req.State, req.QQ, req.Mobile, req.Tel, req.RoleType, req.Email, req.UserGroup, collection, req.AccountPost, req.ParentId);
|
||||
req.State, req.QQ, req.Mobile, req.Tel, req.RoleType, req.Email, req.UserGroup, collection, req.AccountPost, req.ParentId,req.OaAccount);
|
||||
return result;
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult UserEdit(int id, string loginname, string name, string password, int state, string qq,
|
||||
string Mobile, string tel, string roletype, string email, string userGroup, IFormCollection collection, int accountPost, int? parentId)
|
||||
string Mobile, string tel, string roletype, string email, string userGroup, IFormCollection collection, int accountPost, int? parentId,string oaAccount)
|
||||
{
|
||||
var roles = roletype?.Split(',');
|
||||
|
||||
@@ -778,6 +778,7 @@ namespace YLErp.Web.Controllers
|
||||
r.UserGroup = userGroup;
|
||||
r.AccountPost = accountPost;
|
||||
r.ParentId = parentId;
|
||||
r.OaAccount = oaAccount;
|
||||
return View(r);
|
||||
}
|
||||
else
|
||||
@@ -797,7 +798,8 @@ namespace YLErp.Web.Controllers
|
||||
UserGroup = userGroup,
|
||||
AccountPost = accountPost,
|
||||
ParentId = parentId,
|
||||
VarietyIds = ""
|
||||
VarietyIds = "",
|
||||
OaAccount=oaAccount
|
||||
};
|
||||
|
||||
r.Save(basedb, vo);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Org.BouncyCastle.Ocsp;
|
||||
using Org.BouncyCastle.Ocsp;
|
||||
using System.Diagnostics.Contracts;
|
||||
using YLErp.Commons;
|
||||
using YLErp.Configuration;
|
||||
@@ -108,6 +108,28 @@ namespace YLErp.Web.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送OA
|
||||
/// </summary>
|
||||
/// <param name="id">交易ID</param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<JsonResult> SendOA(int id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var oaService = new TradeOAService(CurUser);
|
||||
var result = await oaService.ProcessSingleOAAsync(id);
|
||||
|
||||
return result.Success ? JsonSuccess(result.Message) : JsonError(result.Message);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Error($"提交OA失败: {ex.Message}", ex);
|
||||
return JsonError($"提交OA失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<EmailTradeConfirmResultType> DoSendMailSywg(string tradeId, List<string> reciver,bool needDecryption = true)
|
||||
{
|
||||
try
|
||||
|
||||
@@ -2628,7 +2628,7 @@ namespace YLErp.Web.Controllers
|
||||
From = reqModel.TradeMarketReportDateType == "当日" ? reqModel.ValueDate : (reqModel.TradeMarketReportDateType == "当月区间" ? QdpCalendarHelper.GetNonHoliday(reqModel.ValueDate.Date.AddDays(1 - reqModel.ValueDate.Day)) : DateTime.MinValue),
|
||||
To = reqModel.ValueDate,
|
||||
CurUserName = exParam.CurUser.UserName,
|
||||
SendContent = string.IsNullOrEmpty(sheets) ? new List<string>() { "账户状况", "持仓明细", "历史交易", "资金明细", "质押记录" } : sheets.Split(',').ToList(),
|
||||
SendContent = string.IsNullOrEmpty(sheets) ? new List<string>() { "账户状况", "互换估值", "互换交易流水", "资金明细"} : sheets.Split(',').ToList(),
|
||||
PayableFund = -1,//表示从后台获取
|
||||
PayableMargin = -1,//表示从后台获取
|
||||
ReportType = reqModel.ClientBalanceDataType,
|
||||
@@ -2662,32 +2662,6 @@ namespace YLErp.Web.Controllers
|
||||
message += "[客户" + clientName + "发送结算报告失败," + e.Message + "]; ";
|
||||
}
|
||||
}
|
||||
|
||||
if (reqModel.HasTradeDetails)
|
||||
{
|
||||
try
|
||||
{
|
||||
var req = new TradeDetailsReq()
|
||||
{
|
||||
ClientId = client.Key,
|
||||
StartDate = reqModel.TradeDetailsDateType == "当日" ? reqModel.ValueDate : (reqModel.TradeDetailsDateType == "当月区间" ? QdpCalendarHelper.GetNonHoliday(reqModel.ValueDate.Date.AddDays(1 - reqModel.ValueDate.Day)) : DateTime.MinValue),
|
||||
EndDate = reqModel.ValueDate,
|
||||
DetailStatuses = "成交,提前终止,到期"
|
||||
};
|
||||
var tradeDetailsResult = new tradeController().SendReportMails(req, exParam.CurUser, exParam.detailTemplateName, exParam.tradeListHtmlViewPath, exParam.detailReceiver).Result;
|
||||
var data = tradeDetailsResult.Value as Result;
|
||||
if (!data.success)
|
||||
{
|
||||
message += "[客户" + clientName + "发送交易明细失败," + data.msg + "]; ";
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LogFactory.GetLogger<ClientController>().Error(e, "发送结算报告失败2");
|
||||
var msg = e.InnerException != null ? e.InnerException.Message : e.Message;
|
||||
message += "[客户" + clientName + "发送交易明细失败," + msg + "]; ";
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
@@ -2827,11 +2801,9 @@ namespace YLErp.Web.Controllers
|
||||
var message = "";
|
||||
var tempFolder = Server.MapPath("~/App_Docs/Temp");
|
||||
var marketFolder = Path.Combine(tempFolder, "结算报告" + DateTime.Now.ToString("yyyyMMddHHmmss"));
|
||||
var detailsFolder = Path.Combine(tempFolder, "交易明细" + DateTime.Now.ToString("yyyyMMddHHmmss"));
|
||||
|
||||
//如果没有相关数据,会创建一个空文件夹
|
||||
Directory.CreateDirectory(marketFolder);
|
||||
Directory.CreateDirectory(detailsFolder);
|
||||
|
||||
foreach (var clientId in clientIds)
|
||||
{
|
||||
@@ -2879,29 +2851,6 @@ namespace YLErp.Web.Controllers
|
||||
message += "[客户" + clientName + "生成结算报告失败," + e.Message + "]; ";
|
||||
}
|
||||
}
|
||||
|
||||
if (input.HasTradeDetails)
|
||||
{
|
||||
try
|
||||
{
|
||||
var req = new TradeDetailsReq()
|
||||
{
|
||||
ClientId = int.Parse(clientId),
|
||||
StartDate = input.TradeDetailsDateType == "当日" ? input.ValueDate : (input.TradeDetailsDateType == "当月区间" ? QdpCalendarHelper.GetNonHoliday(input.ValueDate.Date.AddDays(1 - input.ValueDate.Day)) : DateTime.MinValue),
|
||||
EndDate = input.ValueDate,
|
||||
DetailStatuses = "成交,提前终止,到期",
|
||||
OutputFolder = detailsFolder
|
||||
};
|
||||
var biaoTou = DBCacheManager.Single.GetStr(CacheTable.TradeDetailsBiaoTou, detailTemplate);
|
||||
var biaoWei = DBCacheManager.Single.GetStr(CacheTable.TradeDetailsBiaoWei, detailTemplate);
|
||||
var tradeDetailsService = new TradeDetailsQueryService(CurUser);
|
||||
tradeDetailsService.ExportReport(req, biaoTou, biaoWei, true);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
message += "[客户" + clientName + "生成交易明细失败," + e.Message + "]; ";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2909,22 +2858,15 @@ namespace YLErp.Web.Controllers
|
||||
+ (input.TradeMarketReportDateType == "当日" ? (input.ValueDate.ToString("yyyyMMdd") + "-") : (input.TradeMarketReportDateType == "当月区间" ? (QdpCalendarHelper.GetNonHoliday(input.ValueDate.Date.AddDays(1 - input.ValueDate.Day)).ToString("yyyyMMdd") + "-") : ""))
|
||||
+ input.ValueDate.ToString("yyyyMMdd")
|
||||
+ ".zip";
|
||||
var detailsZipFileName = "交易明细"
|
||||
+ (input.TradeDetailsDateType == "当日" ? (input.ValueDate.ToString("yyyyMMdd") + "-") : (input.TradeDetailsDateType == "当月区间" ? (QdpCalendarHelper.GetNonHoliday(input.ValueDate.Date.AddDays(1 - input.ValueDate.Day)).ToString("yyyyMMdd") + "-") : ""))
|
||||
+ input.ValueDate.ToString("yyyyMMdd")
|
||||
+ ".zip";
|
||||
|
||||
var zipWebPath = $"/App_Docs/Temp/";
|
||||
var zipLocalFolder = Server.MapPath(zipWebPath);
|
||||
Directory.CreateDirectory(zipLocalFolder);
|
||||
|
||||
var marketZipFile = Path.Combine(zipLocalFolder, marketZipFileName);
|
||||
var detailsZipFile = Path.Combine(zipLocalFolder, detailsZipFileName);
|
||||
ZipHelper.ZipDirectory(marketFolder, marketZipFile);
|
||||
ZipHelper.ZipDirectory(detailsFolder, detailsZipFile);
|
||||
|
||||
Directory.Delete(marketFolder, true);
|
||||
Directory.Delete(detailsFolder, true);
|
||||
|
||||
if (!string.IsNullOrEmpty(message))
|
||||
{
|
||||
@@ -2933,8 +2875,7 @@ namespace YLErp.Web.Controllers
|
||||
|
||||
return JsonSuccess("批量下载成功", new
|
||||
{
|
||||
marketZipFile = zipWebPath + marketZipFileName,
|
||||
detailsZipFile = zipWebPath + detailsZipFileName
|
||||
marketZipFile = zipWebPath + marketZipFileName
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -563,8 +563,8 @@ namespace YLErp.Web.Controllers
|
||||
}
|
||||
else
|
||||
{
|
||||
var report = new SettlementReportService(user).GetReportData(emailData, userAssetUnits, template);
|
||||
new SettlementReportService(user).GenerateFileEntry(report, "excel");
|
||||
var report = new SettlementReportFotShanXiService(user).GetReportData(emailData, userAssetUnits, template);
|
||||
new SettlementReportFotShanXiService(user).GenerateFileEntry(report, "excel");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using YLErp.DBModels;
|
||||
using YLErp.Enums;
|
||||
using YLErp.MailKit;
|
||||
using YLErp.Model;
|
||||
using YLErp.Modules.RiskModule;
|
||||
using YLErp.Modules.SwapModule;
|
||||
using YLErp.Modules.TradeModule;
|
||||
using static YLErp.ConsGlobal;
|
||||
|
||||
namespace YLErp.Web.Hubs
|
||||
{
|
||||
public class TradeConfirmSendOAHub : Hub
|
||||
{
|
||||
private static bool isProcessing = false;
|
||||
protected static IYcLogger Log = LogFactory.GetLogger(typeof(TradeConfirmSendOAHub).FullName);
|
||||
static readonly Dictionary<string, DateTime> _dic = new Dictionary<string, DateTime>(StringComparer.OrdinalIgnoreCase);
|
||||
private static readonly Dictionary<string, string> _clientProgressDic = new Dictionary<string, string>();
|
||||
|
||||
public async Task StartProcessing(string jsonString)
|
||||
{
|
||||
var req = JsonHelper.Deserialize<dynamic>(jsonString);
|
||||
var client = Clients.Caller;
|
||||
|
||||
if (Context.User == null)
|
||||
{
|
||||
await client.SendAsync("ExceptionMessage", "登录已失效,请重新登录");
|
||||
return;
|
||||
}
|
||||
|
||||
var user = Server.CacheProvider.Get("loginUser^" + Context.User.GetUserId()) as UserInfo;
|
||||
if (user == null)
|
||||
{
|
||||
await client.SendAsync("ExceptionMessage", "登录已失效,请重新登录");
|
||||
return;
|
||||
}
|
||||
|
||||
if (isProcessing)
|
||||
{
|
||||
await client.SendAsync("ExceptionMessage", "正在发送OA,请稍后再试");
|
||||
return;
|
||||
}
|
||||
isProcessing = true;
|
||||
|
||||
try
|
||||
{
|
||||
await ProcessOAByIds(req.ids.ToString(), user);
|
||||
isProcessing = false;
|
||||
await Clients.Caller.SendAsync("ProcessCompleted", "");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex.Message, ex);
|
||||
isProcessing = false;
|
||||
await Clients.Caller.SendAsync("ExceptionMessage", ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ProcessOAByIds(string idsJson, UserInfo user)
|
||||
{
|
||||
var ids = JsonHelper.Deserialize<List<int>>(idsJson);
|
||||
|
||||
foreach (var id in ids)
|
||||
{
|
||||
var key = id.ToString();
|
||||
_clientProgressDic[key] = "提交中";
|
||||
await Clients.All.SendAsync("UpdateProgress", GetUpdateProcess(key, "提交中"));
|
||||
var result = await ProcessSingleOA(id, user);
|
||||
_clientProgressDic[key] = result;
|
||||
await Clients.All.SendAsync("UpdateProgress", GetUpdateProcess(key, result));
|
||||
}
|
||||
}
|
||||
private async Task<string> ProcessSingleOA(int id, UserInfo user)
|
||||
{
|
||||
try
|
||||
{
|
||||
var oaService = new TradeOAService(user);
|
||||
var result = await oaService.ProcessSingleOAAsync(id);
|
||||
|
||||
return result.Success ? "提交成功" : result.Message;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error($"处理交易ID {id} 的OA时发生错误: {ex.Message}", ex);
|
||||
return $"提交失败: {ex.Message}";
|
||||
}
|
||||
}
|
||||
|
||||
private string GetUpdateProcess(string key, string msg)
|
||||
{
|
||||
var resp = new
|
||||
{
|
||||
key = key,
|
||||
send_oa_result = msg
|
||||
};
|
||||
return JsonHelper.Serialize(resp);
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -1,4 +1,4 @@
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.ResponseCompression;
|
||||
using Microsoft.AspNetCore.StaticFiles;
|
||||
using Microsoft.Extensions.FileProviders;
|
||||
@@ -151,6 +151,7 @@ try
|
||||
endpoints.MapHub<SwapFlowCombookingHub>("/swapflow/combookinghub"); // 映射Hub路径
|
||||
endpoints.MapHub<SwapFlowResetHub>("/swapflow/resethub"); // 映射Hub路径
|
||||
endpoints.MapHub<SwapConfirmSendEmailHub>("/tradeconfirm/sendemailhub"); // 映射Hub路径
|
||||
endpoints.MapHub<TradeConfirmSendOAHub>("/tradeconfirm/sendoahub"); // 映射OA Hub路径
|
||||
});
|
||||
var provider = new FileExtensionContentTypeProvider();
|
||||
provider.Mappings[".pdf"] = "application/pdf";
|
||||
|
||||
@@ -133,6 +133,7 @@
|
||||
@Html.MyTextFor(model => model.Mobile)
|
||||
@Html.MyTextFor(model => model.Tel)
|
||||
@Html.MyTextFor(model => model.QQ)
|
||||
@Html.MyTextFor(model => model.OaAccount)
|
||||
@if (ConsUserGroup.HasGroup)
|
||||
{
|
||||
<div class="form-group col-md-6">
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
{ name: 'Tel', label: "座机", index: 'Tel', width: 100 },
|
||||
{ name: 'Mobile', label: "手机", index: 'Mobile', width: 100 },
|
||||
{ name: 'QQ', label: "QT", index: 'QQ', width: 100 },
|
||||
{ name: 'OaAccount', label: "OA账号", index: 'OaAccount', width: 100 },
|
||||
{ name: 'UserGroup', label: "用户组", sortable: false, width: 150, hide: page.HasGroup, optionHide: page.HasGroup },
|
||||
{ name: 'Roles', label: "角色", sortable: false, align: 'left', width: 200 },
|
||||
{ name: 'AccountPost', label: "账号岗位", sortable: false, align: 'left', width: 200 },
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
<tr>@Html.MyDisplayFor(m => m.Mobile)</tr>
|
||||
<tr>@Html.MyDisplayFor(m => m.Tel)</tr>
|
||||
<tr>@Html.MyDisplayFor(m => m.QQ)</tr>
|
||||
<tr>@Html.MyDisplayFor(m => m.OaAccount)</tr>
|
||||
@if (ConsUserGroup.HasGroup)
|
||||
{
|
||||
<tr>
|
||||
|
||||
@@ -69,6 +69,7 @@
|
||||
}
|
||||
@MyControls.Btn("批量下载交易确认书", "BatchDownLoadDoc()")
|
||||
<button class="btn btn-primary" id="batchSendEmail" style="margin-left:16px;">批量发送邮件</button>
|
||||
<button class="btn btn-primary" id="batchSendOA" style="margin-left:16px;">批量发送OA</button>
|
||||
@if (PS.GetErpConfig().IsAutoSealAndUploadFiles && !PS.GetErpConfig().IsAutoSealAfterGeneratedBook)
|
||||
{
|
||||
@MyControls.Btn("批量确认书用印", "BatchSealContracts()")
|
||||
|
||||
@@ -77,12 +77,7 @@
|
||||
var balanceTemplate = $("#setTemplate").val();
|
||||
if (thisObj.Model.HasTradeDetails || thisObj.Model.HasTradeMarketReport) {
|
||||
main.post("/client/BatchDownloadClientRiskMonitor", { input: thisObj.Model, balanceTemplate: balanceTemplate, detailTemplate: detailTemplate}).done(function (res) {
|
||||
if (thisObj.Model.HasTradeDetails) {
|
||||
window.open(res.obj.detailsZipFile);
|
||||
}
|
||||
if (thisObj.Model.HasTradeMarketReport) {
|
||||
window.open(res.obj.marketZipFile);
|
||||
}
|
||||
window.open(res.obj.marketZipFile);
|
||||
});;
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"ConnectionStrings": {
|
||||
"ylcms": "server=139.196.109.225;uid=root;pooling=true;port=3306;pwd=Midnight001!@#$;database=yltrs_ylcms;charset=utf8;Allow User Variables=True;SslMode=none;Connection Timeout=30;IgnoreCommandTransaction=true;",
|
||||
"yladmin": "server=139.196.109.225;uid=root;pooling=true;port=3306;pwd=Midnight001!@#$;database=yltrs_admin;charset=utf8;Allow User Variables=True;SslMode=none;Connection Timeout=30;IgnoreCommandTransaction=true;",
|
||||
"ylclient": "server=139.196.109.225;uid=root;pooling=true;port=3306;pwd=Midnight001!@#$;database=yltrs_client;charset=utf8;Allow User Variables=True;SslMode=none;Connection Timeout=30;IgnoreCommandTransaction=true;",
|
||||
"bondoms": "server=139.196.109.225;uid=root;pooling=true;port=3306;pwd=Midnight001!@#$;database=bond_oms;charset=utf8;Allow User Variables=True;SslMode=none;Connection Timeout=30;IgnoreCommandTransaction=true;"
|
||||
// "apex_oracle": "Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=122.112.205.57)(PORT=11521)))(CONNECT_DATA=(SERVICE_NAME=xe)));User ID=system;Password=oracle;"
|
||||
},
|
||||
"AppSettings": {
|
||||
"VirtualPathRoot": "",
|
||||
"UseRightAligned": "",
|
||||
"PluginFolder": "D:\\gitCode\\zszq-trs\\Plugins\\build\\ZheShang\\Debug\\net6.0"
|
||||
},
|
||||
"LibreOffice": {
|
||||
"ExePath": "",
|
||||
"UserInstallation": ""
|
||||
},
|
||||
"EPPlus": {
|
||||
"ExcelPackage": {
|
||||
"LicenseContext": "NonCommercial" //The license context used
|
||||
}
|
||||
},
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"ConnectionStrings": {
|
||||
"ylcms": "server=139.196.109.225;uid=root;pooling=true;port=3306;pwd=Midnight001!@#$;database=yltrs_ylcms;charset=utf8;Allow User Variables=True;SslMode=none;Connection Timeout=30;IgnoreCommandTransaction=true;",
|
||||
"yladmin": "server=139.196.109.225;uid=root;pooling=true;port=3306;pwd=Midnight001!@#$;database=yltrs_admin;charset=utf8;Allow User Variables=True;SslMode=none;Connection Timeout=30;IgnoreCommandTransaction=true;",
|
||||
"ylclient": "server=139.196.109.225;uid=root;pooling=true;port=3306;pwd=Midnight001!@#$;database=yltrs_client;charset=utf8;Allow User Variables=True;SslMode=none;Connection Timeout=30;IgnoreCommandTransaction=true;",
|
||||
"bondoms": "server=139.196.109.225;uid=root;pooling=true;port=3306;pwd=Midnight001!@#$;database=bond_oms;charset=utf8;Allow User Variables=True;SslMode=none;Connection Timeout=30;IgnoreCommandTransaction=true;"
|
||||
// "apex_oracle": "Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=122.112.205.57)(PORT=11521)))(CONNECT_DATA=(SERVICE_NAME=xe)));User ID=system;Password=oracle;"
|
||||
},
|
||||
"AppSettings": {
|
||||
"VirtualPathRoot": "",
|
||||
"UseRightAligned": "",
|
||||
"PluginFolder": "D:\\project\\zsza-trs\\Plugins\\build\\ZheShang\\Debug\\net6.0"
|
||||
},
|
||||
"LibreOffice": {
|
||||
"ExePath": "",
|
||||
"UserInstallation": ""
|
||||
},
|
||||
"EPPlus": {
|
||||
"ExcelPackage": {
|
||||
"LicenseContext": "NonCommercial" //The license context used
|
||||
}
|
||||
},
|
||||
"KafkaConfig": {
|
||||
"BootstrapServers": "139.196.109.225:9092", // Kafka 集群的地址
|
||||
"Acks": -1, // 消息确认方式,可以是 All(-1)、Leader(1)、None(0) 中的一种
|
||||
@@ -65,14 +65,21 @@
|
||||
"YiLian_HolidayResetGroupId": "YiLian_HedgingOrderGroup1", //交易日历缓存重新加载消费 Group
|
||||
"YiLian_SwapFlowTopic": "YiLian_SwapFlow", //交易端同步流水
|
||||
"YiLian_SwapFlowGroup": "YiLian_SwapFlowGroup1", //交易端同步流水消费组
|
||||
"YiLian_SysUserInfoChangeTopic": "YiLian_SysUserInfoChangeTopic"//管理端系统用户变更
|
||||
"YiLian_SysUserInfoChangeTopic": "YiLian_SysUserInfoChangeTopic" //管理端系统用户变更
|
||||
},
|
||||
"BondOmsInterface": {
|
||||
"BaseUrl": "http://trs.yiliantech.com:8080/trs_hub_api"
|
||||
},
|
||||
"OrcaleDatabaseConfig": {
|
||||
"Schema": "APEX_040000"
|
||||
},
|
||||
"SendKafakaCron": "10 0 * * *",
|
||||
"MaxThreadPercent": 0.6 //占系统资源最多60%的线程数量
|
||||
"BondOmsInterface": {
|
||||
"BaseUrl": "http://trs.yiliantech.com:8080/trs_hub_api"
|
||||
},
|
||||
"OrcaleDatabaseConfig": {
|
||||
"Schema": "APEX_040000"
|
||||
},
|
||||
"SendKafakaCron": "10 0 * * *",
|
||||
"MaxThreadPercent": 0.6, //占系统资源最多60%的线程数量
|
||||
"oa_confg": {
|
||||
"BaseUrl": "http://ip:port",
|
||||
"SystemKey": "M001", //OA系统key
|
||||
"ObjectClass": "ZSZQ_ZDNX", //OA文件类别
|
||||
"Urgent": 1, //紧急程度,1一般 2紧急 3加急
|
||||
"Issend": 1 //流程是否自动发送,0不发送,1自动发送下一步
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,16 @@ const colModelGrid = (new function () {
|
||||
return html;
|
||||
}
|
||||
},
|
||||
{ label: 'OA状态', name: 'OAStatus', width: 100, align: 'center' },
|
||||
{ label: 'OA-URL', name: 'OAURL', width: 150, align: 'center',
|
||||
formatter: function (cellValue, options, rowObject) {
|
||||
if (cellValue && cellValue.length > 0) {
|
||||
return '<a href="' + cellValue + '" target="_blank">查看</a>';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
},
|
||||
{ label: 'OA消息', name: 'OAMessage', width: 150, align: 'left' },
|
||||
{ label: '交易数量', name: 'tradeCount', width: 80, align: 'center' },
|
||||
{ label: 'tradeIds', name: 'tradeIds', hidden: true, optionHide: true }];
|
||||
this.upload = function (encryptId, sendMail) {
|
||||
@@ -156,6 +166,7 @@ $(function () {
|
||||
// $("#batchSendMailBtn").click(BatchSendMail);
|
||||
initJqGrid();
|
||||
SendEmailHub()
|
||||
SendOAHub(); // 初始化OA发送功能
|
||||
});
|
||||
|
||||
// 初始化jqGrid函数
|
||||
@@ -244,8 +255,12 @@ function showToolName(cellValue, options, rowObject) {
|
||||
html += "<input type=\"button\" class=\"wentiEdit\" title='交易确认书未生成或未找到制定确认书文件' disabled readonly=\"true\" value=\"{1}\" />"
|
||||
.template(rowObject.EncryptId, "发送Email");
|
||||
}
|
||||
var canUpload = page.canGenerate == true && rowObject.ContractDocUrl ? "" : "disabled";
|
||||
var canUpload = page.canGenerate == true && rowObject.ContractDocUrl ? "" : "disabled";
|
||||
html += "<input type=\"button\" class=\"wentiEdit\" value=\"上传\" onclick=\"colModelGrid.uploadNew('{0}')\" {1} />".template(rowObject.ContractCode, canUpload);
|
||||
|
||||
// 添加发送OA按钮
|
||||
html += "<input type=\"button\" class=\"wentiEdit\" title='发送交易确认书到OA系统' onclick=\"sendOA('{0}')\" value=\"发送OA\" />"
|
||||
.template(rowObject.id);
|
||||
return html;
|
||||
}
|
||||
|
||||
@@ -597,7 +612,147 @@ function SendEmailHub() {
|
||||
}, 3000); // 3秒
|
||||
});
|
||||
}
|
||||
function SendOAHub() {
|
||||
// 创建SignalR连接并连接到服务器上的Hub
|
||||
var connection = new signalR.HubConnectionBuilder()
|
||||
.withUrl('/tradeconfirm/sendoahub')
|
||||
.withAutomaticReconnect()
|
||||
.build();
|
||||
connection.start()
|
||||
.then(function () {
|
||||
$("#batchSendOA").click(function () {
|
||||
var jgrid = jQuery('#listGrid');
|
||||
var rowIds = jgrid.jqGrid('getGridParam', 'selarrrow');
|
||||
if (rowIds.length == 0) {
|
||||
main.alert("请至少选择一笔交易"); return;
|
||||
}
|
||||
|
||||
// 检查选中的行中是否有无确认书的情况
|
||||
var hasNoConfirmBook = false;
|
||||
var hasOAStatus = false;
|
||||
var ids = [];
|
||||
var contractCodes = [];
|
||||
|
||||
rowIds.forEach((v, i, arr) => {
|
||||
var rowId = v;
|
||||
var data = jgrid.jqGrid('getRowData', rowId);
|
||||
if (data.id) {
|
||||
ids.push(data.id);
|
||||
contractCodes.push(data.ContractCode);
|
||||
|
||||
// 检查是否有无确认书的情况
|
||||
if (!data.ContractCode) {
|
||||
hasNoConfirmBook = true;
|
||||
}
|
||||
|
||||
// 检查是否有已发送OA的情况
|
||||
if (data.OAStatus && data.OAStatus !== "") {
|
||||
hasOAStatus = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 根据不同情况显示不同提示
|
||||
if (hasNoConfirmBook) {
|
||||
main.confirm("选中的交易中有无确认书附件的情况,确定提交OA吗?", function() {
|
||||
batchSubmitOA(connection, ids);
|
||||
});
|
||||
} else if (hasOAStatus) {
|
||||
main.confirm("选中的交易中有已经提交过OA的情况,确定再次提交新的OA吗?", function() {
|
||||
batchSubmitOA(connection, ids);
|
||||
});
|
||||
} else {
|
||||
// 有确认书且OA状态为未发送过:无提示,直接在OA中起草内容
|
||||
batchSubmitOA(connection, ids);
|
||||
}
|
||||
});
|
||||
|
||||
// 批量提交OA的函数
|
||||
function batchSubmitOA(connection, ids) {
|
||||
var req = {
|
||||
ids: ids,
|
||||
}
|
||||
connection.invoke('StartProcessing', JSON.stringify(req));
|
||||
main.waitMe(true);
|
||||
}
|
||||
}).catch(function (error) {
|
||||
console.error(error);
|
||||
});
|
||||
// 监听服务器发送的消息。
|
||||
connection.on('UpdateProgress', function (msg) {
|
||||
if (msg != null && msg != '') {
|
||||
let jsonObject = JSON.parse(msg);
|
||||
SearchClick(true); // 刷新列表
|
||||
}
|
||||
});
|
||||
// 监听服务器发送的异常消息。
|
||||
connection.on('ExceptionMessage', function (msg) {
|
||||
if (msg.indexOf("正在发送OA") < 0) {
|
||||
main.waitMe(false);
|
||||
SearchClick(true);
|
||||
}
|
||||
main.alert(msg);
|
||||
});
|
||||
// 监听服务器发送的完成消息。
|
||||
connection.on('ProcessCompleted', function () {
|
||||
main.alert("OA发送处理完毕");
|
||||
main.waitMe(false);
|
||||
SearchClick(true);
|
||||
});
|
||||
// 监听连接关闭,启动重连
|
||||
connection.onclose(async (error) => {
|
||||
console.log("连接断开");
|
||||
// 等待3秒后尝试重新连接
|
||||
setTimeout(async () => {
|
||||
try {
|
||||
await connection.start();
|
||||
console.log("已重新连接");
|
||||
} catch (err) {
|
||||
console.error("重新连接失败: ", err);
|
||||
}
|
||||
}, 3000); // 3秒
|
||||
});
|
||||
}
|
||||
|
||||
// 单个发送OA函数
|
||||
function sendOA(id) {
|
||||
// 获取当前行数据
|
||||
var jgrid = jQuery('#listGrid');
|
||||
var rowData = jgrid.jqGrid('getRowData', id);
|
||||
|
||||
if (!rowData) return;
|
||||
|
||||
var tradeIdArray = rowData.tradeIds ? rowData.tradeIds.split(",") : [];
|
||||
if (tradeIdArray.length === 0) return;
|
||||
|
||||
// 根据不同情况显示不同提示
|
||||
if (!rowData.ContractCode) {
|
||||
// 无确认书:提示用户
|
||||
main.confirm("目前无确认书附件,确定提交OA吗?", function() {
|
||||
submitOA(id);
|
||||
});
|
||||
} else if (!rowData.OAStatus || rowData.OAStatus === "") {
|
||||
// 有确认书,OA状态为未发送过:无提示,直接在OA中起草内容
|
||||
submitOA(id);
|
||||
} else {
|
||||
// OA状态已经有值:提示用户是否再次提交
|
||||
main.confirm("已经提交过OA,确定再次提交一笔新的OA吗?", function() {
|
||||
submitOA(id);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 提交OA请求
|
||||
function submitOA(id) {
|
||||
var req = {
|
||||
id: id
|
||||
};
|
||||
main.post("/TradeConfirmBook/SendOA", req).done(function (res) {
|
||||
SearchClick(true);
|
||||
}).fail(function (xhr, status, error) {
|
||||
SearchClick(true);
|
||||
});
|
||||
}
|
||||
function openWindowWithPost(url, data) {
|
||||
var form = document.createElement("form");
|
||||
form.target = "_blank";
|
||||
|
||||
@@ -55,8 +55,6 @@ namespace RealTimeCalcPositionService
|
||||
{
|
||||
try
|
||||
{
|
||||
using var clientDb = new ClientDBContext();
|
||||
var clients= clientDb.client.ToList();
|
||||
//系统交易日
|
||||
var valuedate = valuedateBLL.ValueDate;
|
||||
var clientSettles = new RealTimeClientBanlanceService(new OptUserInfo(0, "实时客户资金服务", OptUserFrom.Service)).GetBalances();
|
||||
|
||||
@@ -6,6 +6,7 @@ using YLErp;
|
||||
using YLErp.Abstract;
|
||||
using YLErp.Helpers;
|
||||
using YLErp.Model;
|
||||
using static alglib;
|
||||
|
||||
internal class Program
|
||||
{
|
||||
@@ -28,6 +29,7 @@ internal class Program
|
||||
services.AddHostedService<ClientPosiTask>();
|
||||
services.AddHostedService<Worker>();
|
||||
services.AddHostedService<ClientNoDMABalanceTask>();
|
||||
|
||||
}).ConfigureLogging(logging =>
|
||||
{
|
||||
logging.ClearProviders();
|
||||
@@ -35,8 +37,7 @@ internal class Program
|
||||
})
|
||||
.UseNLog()
|
||||
.Build();
|
||||
|
||||
//YLServiceLocator.SetServiceProvider(host.Services);
|
||||
YLServiceLocator.SetServiceProvider(host.Services);
|
||||
|
||||
await host.RunAsync();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user