using System.Data;
using YLErp.Commons;
using YLErp.Model;
namespace YLErp.Modules.EodModule
{
///
/// 结算价导入服务
///
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;
}
///
/// 导入xlsx数据
///
public ImportResultModel ImportxlsxDatas(Stream stream)
{
var importModels = Enumerable.Empty();
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();
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();
var uniqSet = new HashSet(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; }
}
}
}