Files
zszq-trs/YLErpDAL/Modules/EodModule/SettlementPriceImportService.cs
T
张名锐 2eba4ce2a9 feat(settlement): 添加标的类型判断逻辑支持价格表分流
- 在ConsGlobal中为所有标的类型常量添加中文注释说明
- 新增UseStockPriceTable方法用于判断标的类型是否使用股票价格表
- 修改SettlementPriceImportService中的价格表分流逻辑
- 添加单元测试验证股指期货、基金等进入股票价格表的逻辑
- 确保Shibor、利率收益率和债券指数进入正确的商品期货价格表
2026-07-31 16:57:49 +08:00

251 lines
9.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Data;
using YLErp.Commons;
using YLErp.Model;
namespace YLErp.Modules.EodModule
{
/// <summary>
/// 结算价导入服务
/// </summary>
public class SettlementPriceImportService : YLBaseService
{
public SettlementPriceImportService(OptUserInfo userInfo) : base(userInfo)
{
}
public static bool UseStockPriceTable(string instrumentType)
{
return ConsGlobal.InstrumentType.EquityTypes().Contains(instrumentType)
|| instrumentType == ConsGlobal.InstrumentType.Fund;
}
/// <summary>
/// 导入xlsx数据
/// </summary>
public ImportResultModel ImportxlsxDatas(Stream stream)
{
var importModels = Enumerable.Empty<ImportModel>();
var rowIndex = 0;
try
{
var ds = Office.ExcelHelper.ReadExcelAsDataSet(stream);
if (ds.Tables.Count < 1 || ds.Tables[0].Rows.Count < 1)
{
throw new ServiceException("读取导入数据失败:数据为空") { Tag = "111" };
}
var table = ds.Tables[0];
var reader = new DataRowReader(table);
var list = new List<ImportModel>();
rowIndex = 1;
foreach (DataRow row in table.Rows)
{
rowIndex++;
if (row.ItemArray.All(n => string.IsNullOrWhiteSpace(n?.ToString())))
{
continue;
}
reader.SetDataRow(row);
var model = new ImportModel
{
date = reader.GetDate("日期", true).Value,
code = reader.GetString("代码", true),
closePrice = reader.GetDouble("收盘价", false),
settlePrice = reader.GetDouble("结算价", false),
ReferencePrice = reader.GetDouble("参考价", false)
};
model.underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(model.code);
if (model.underlying == null)
{
throw new ServiceException("标的代码不存在:" + model.code) { Tag = "111" };
}
list.Add(model);
}
importModels = list.ToArray();
}
catch (ServiceException se)
{
if (se.Tag != null) throw;
throw new ServiceException($"第{rowIndex}行,发生错误:{se.Message}");
}
catch (Exception ex)
{
LogFactory.GetLogger("导入场内交易").Error(ex);
throw new ServiceException($"第{rowIndex}行,发生错误:{ex.Message}", ex);
}
if (!importModels.Any())
{
throw new ServiceException("没有可导入的数据");
}
var result = new ImportResultModel
{
TotalCount = importModels.Count()
};
var dates = new HashSet<DateTime>();
var uniqSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
foreach (var item in importModels)
{
var underlying = item.underlying;
if (underlying.IsBond())
{
var eodPrice = DbContext.china_bond_valuation
.FirstOrDefault(p => p.valuation_date == item.date && p.bond_id == underlying.UnderlyingCode);
if (eodPrice == null)
{
var datestr = item.date.ToString("yyyyMMdd");
if (uniqSet.Add(datestr + "^" + item.code))
{
eodPrice = new ChinaBondValuation();
eodPrice.credibility = 1;
DbContext.china_bond_valuation.Add(eodPrice);
}
else
{
result.Errors.Add($"重复数据,忽略: {datestr},{item.code}");
continue;
}
}
eodPrice.valuation_date = item.date;
eodPrice.bond_id = underlying.UnderlyingCode;
if (item.closePrice.HasValue)
eodPrice.dirty_price_close =Convert.ToDecimal(item.closePrice ?? 0);
if (item.settlePrice.HasValue)
eodPrice.net_price = Convert.ToDecimal(item.settlePrice ?? 0);
if (item.ReferencePrice.HasValue)
eodPrice.yield = Convert.ToDecimal(item.ReferencePrice);
eodPrice.update_time = DateTime.Now;
// 手工上传也是登录用户的人工动作,戳操作人到已有列(create_user/update_user)
// 使列表来源列显示上传人姓名(与 SaveBondPrice 口径一致);聚源/中债自动同步(外部ETL)不写这两列。
// eodPrice.id==0 表示本次新增(尚未落库),非0为命中已有行的更新。
EodPriceService.StampBondOperator(eodPrice, UserId, eodPrice.id == 0);
result.SuccessCount++;
}
else if (!UseStockPriceTable(underlying.UnderlyingInstrumentType))
{
var eodPrice = DbContext.eod_commodity_future_price
.FirstOrDefault(p => p.ValueDate == item.date && p.UnderlyingCode == underlying.UnderlyingCode);
if (eodPrice == null)
{
var datestr = item.date.ToString("yyyyMMdd");
if (uniqSet.Add(datestr + "^" + item.code))
{
eodPrice = new eod_commodity_future_price();
DbContext.eod_commodity_future_price.Add(eodPrice);
}
else
{
result.Errors.Add($"重复数据,忽略: {datestr},{item.code}");
continue;
}
}
eodPrice.ValueDate = item.date;
eodPrice.UnderlyingCode = underlying.UnderlyingCode;
eodPrice.UnderlyingId = underlying.id;
// 入库前强制 UnderlyingId 与 UnderlyingCode(FutureContractId) 一致,避免网页/结算两套 JOIN 失同步。
EodPriceService.SyncUnderlyingIdFromCode(DbContext, eodPrice);
if (item.closePrice.HasValue)
eodPrice.ClosePrice = item.closePrice ?? 0;
if (item.settlePrice.HasValue)
eodPrice.SettlePrice = item.settlePrice ?? 0;
if (item.ReferencePrice.HasValue)
eodPrice.ReferencePrice = item.ReferencePrice;
eodPrice.OptId = UserId;
eodPrice.OptName = UserName;
eodPrice.OptDate = DateTime.Now;
eodPrice.DataSource = EodPriceBase.人工;
result.SuccessCount++;
}
else
{
var stockPrice = DbContext.eod_stock_price
.FirstOrDefault(p => p.ValueDate == item.date && p.UnderlyingCode == underlying.UnderlyingCode);
if (stockPrice == null)
{
var datestr = item.date.ToString("yyyyMMdd");
if (uniqSet.Add(datestr + "^" + item.code))
{
stockPrice = new eod_stock_price();
DbContext.eod_stock_price.Add(stockPrice);
}
else
{
result.Errors.Add($"重复数据,忽略: {datestr},{item.code}");
continue;
}
}
stockPrice.ValueDate = item.date;
stockPrice.UnderlyingCode = underlying.UnderlyingCode;
if (item.closePrice.HasValue)
stockPrice.ClosePrice = item.closePrice ?? 0;
if (item.ReferencePrice.HasValue)
stockPrice.ReferencePrice = item.ReferencePrice;
stockPrice.OptDate = DateTime.Now;
stockPrice.DataSource = EodPriceBase.人工;
result.SuccessCount++;
}
//else
//{
// result.Errors.Add("未导入,标的不属于商品或股票:" + item.code);
//}
dates.Add(item.date.Date);
}
DbContext.SaveChanges();
if (dates.Contains(BLL.valuedateBLL.ValueDate))
{
var sql = $@"
update underlying_manager um join eod_commodity_future_price eod on um.UnderlyingCode = eod.FutureContractId
set um.Price = eod.ClosePrice where eod.ValueDate='{BLL.valuedateBLL.ValueDate:yyyy-MM-dd}';
update underlying_manager um join eod_stock_price eod on um.UnderlyingCode = eod.StockId
set um.Price = eod.ClosePrice where eod.ValueDate='{BLL.valuedateBLL.ValueDate:yyyy-MM-dd}';";
DbContext.Database.ExecuteSqlRaw(sql);
}
return result;
}
class ImportModel
{
public DateTime date { get; set; }
public string code { get; set; }
public double? closePrice { get; set; }
public double? settlePrice { get; set; }
public double? ReferencePrice { get; set; }
public underlying_manager underlying { get; set; }
}
}
}