using System.Data; using System.Text; using YLErp.Commons; using YLErp.Models; namespace YLErp.Modules.MarginModule { /// /// 标的预付金计算参数导入服务 /// public class MarginParamsImportService : YLBaseService { public MarginParamsImportService(OptUserInfo userInfo) : base(userInfo) { } public MarginParamsImportService(YLBaseService baseService) : base(baseService) { } /// /// 导入标的数据(Excel) /// public MarginParamsImportResult ImportUnderlying(Stream streamIn) { var readResult = ReadData(streamIn, false); if (readResult.hasError) { return new MarginParamsImportResult { ResultSet = readResult.dataSet, ResultMsg = "读取导入数据失败,请检查修改后重新导入" }; } var lists = new[] { readResult.marginHis, readResult.volRateHis, readResult.updownHis }; if (!lists.Any(n => n.Count > 0)) { return new MarginParamsImportResult { ResultSet = readResult.dataSet, ResultMsg = "未读取到任何导入数据" }; } var sqlBuilderList = new List(10) { new StringBuilder(5200) }; var tableName = DbContext.GetTableName(); var result = new MarginParamsImportResult { ResultSet = readResult.dataSet }; foreach (var list in lists) { if (!list.Any()) { continue; } string valueType = null; string sheetName = list[0].dataRow.Table.TableName; switch (sheetName) { case "预付金比例": valueType = nameof(MarginParamModel.MarginRate); break; case "Span波动率变动": valueType = nameof(MarginParamModel.VolatilityRate); break; case "Span涨跌幅度": valueType = nameof(MarginParamModel.UpDownLimit); break; } var groups = list.GroupBy(n => n.code); foreach (var grp in groups) { var items = grp.OrderBy(n => n.date).ToArray(); var minDate = items[0].date; var maxDate = items[items.Length - 1].date; var sqlBuilder = sqlBuilderList.Last(); if (sqlBuilder.Length > 5000) { sqlBuilderList.Add(sqlBuilder = new StringBuilder(5200)); } sqlBuilder.AppendFormat("delete from {0} where UnderlyingCode='{1}' and ValueDate>='{2}' and ValueDate<='{3}' and ValueType='{4}';" , tableName, grp.Key, minDate.ToShortDateString(), maxDate.ToShortDateString(), valueType).AppendLine(); foreach (var item in items) { DbContext.UnderlyingHisData.Add(new UnderlyingHisData { UnderlyingCode = grp.Key, ValueType = valueType, ValueDate = item.date, Value = item.dvalue, OptId = UserId, OptName = UserName, OptDate = OptDate, ValueFlag = sheetName != "Span涨跌幅度" || item.isPercent ? "%" : "F" }); } } } using (var trans = BeginTransaction()) { foreach (var sb in sqlBuilderList) { var sql = sb.ToString(); if (sql.Length > 0) { var changes1 = DbContext.Database.ExecuteSqlRaw(sql); } } result.SuccessSum = DbContext.SaveChanges(); UpdateUnderlyingMaringParams(SystemValueDate); trans.Commit(); } return result.SetMsg($"成功处理{result.SuccessSum}条"); } /// /// 使用mysql语句执行underlying_manager表中预付金参数的更新 /// private int UpdateUnderlyingMaringParams(DateTime maxDate) { var maxDateStr = maxDate.ToString("yyyy-MM-dd"); var sql = $@" update underlying_manager set MarginRate= (select `Value` end from underlying_hisdata uh where uh.UnderlyingCode = underlying_manager.UnderlyingCode and uh.ValueDate <= '{maxDateStr}' && uh.ValueType = 'MarginRate' order by ValueDate desc limit 1), VolatilityRate= (select case ValueFlag when '%' then CONCAT(TRUNCATE(`Value`*100,2),'%') else TRUNCATE(`Value`,4) end from underlying_hisdata uh where uh.UnderlyingCode = underlying_manager.UnderlyingCode and uh.ValueDate <= '{maxDateStr}' && uh.ValueType = 'VolatilityRate' order by ValueDate desc limit 1), UpDownLimit= (select case ValueFlag when '%' then CONCAT(TRUNCATE(`Value`*100,2),'%') else TRUNCATE(`Value`,4) end from underlying_hisdata uh where uh.UnderlyingCode = underlying_manager.UnderlyingCode and uh.ValueDate <= '{maxDateStr}' && uh.ValueType = 'UpDownLimit' order by ValueDate desc limit 1)"; return DbContext.Database.ExecuteSqlRaw(sql); } /// /// 导入品种数据(Excel) /// public MarginParamsImportResult ImportVariety(Stream streamIn) { var readResult = ReadData(streamIn, true); if (readResult.hasError) { return new MarginParamsImportResult { ResultSet = readResult.dataSet, ResultMsg = "读取导入数据失败,请检查修改后重新导入" }; } var lists = new[] { readResult.marginHis, readResult.volRateHis, readResult.updownHis }; if (!lists.Any(n => n.Count > 0)) { return new MarginParamsImportResult { ResultSet = readResult.dataSet, ResultMsg = "未读取到任何导入数据" }; } var sysDate = SystemValueDate; var vaDic = DbContext.variety.ToDictionary(n => n.VarietyCode); var sqlBuilder = new StringBuilder(); var tableName = DbContext.GetTableName(); var result = new MarginParamsImportResult { ResultSet = readResult.dataSet }; foreach (var list in lists) { if (!list.Any()) { continue; } string valueType = null; string sheetName = list[0].dataRow.Table.TableName; switch (sheetName) { case "预付金比例": valueType = nameof(MarginParamModel.MarginRate); break; case "Span波动率变动": valueType = nameof(MarginParamModel.VolatilityRate); break; case "Span涨跌幅度": valueType = nameof(MarginParamModel.UpDownLimit); break; } var groups = list.GroupBy(n => n.code); foreach (var grp in groups) { var items = grp.OrderBy(n => n.date).ToArray(); if (!vaDic.TryGetValue(grp.Key, out var va)) { foreach (var item in items) { result.FailSum++; item.dataRow["处理结果"] = "品种信息不存在"; } continue; } result.SuccessSum++; var minDate = items[0].date; var maxDate = items[items.Length - 1].date; sqlBuilder.AppendFormat("delete from {0} where VarietyId={1} and ValueDate>='{2}' and ValueDate<='{3}' and ValueType='{4}';" , tableName, va.id, minDate.ToShortDateString(), maxDate.ToShortDateString(), valueType).AppendLine(); var index = 0; foreach (var item in items) { if (item.date <= sysDate) { index++; } DbContext.VarietyHisData.Add(new VarietyHisData { VarietyId = va.id, ValueType = valueType, ValueDate = item.date, Value = item.dvalue, OptId = UserId, OptName = UserName, OptDate = OptDate }); } //更新品种数据 if (index > 0) { ReadModel rm = null; if (index < items.Length) { rm = items[index - 1]; } else if (!DbContext.VarietyHisData.Any(n => n.VarietyId == va.id && n.ValueDate > maxDate && n.ValueDate <= sysDate && n.ValueType == valueType)) { rm = items[items.Length - 1]; } if (rm != null) { switch (sheetName) { case "预付金比例": va.Margin = rm.dvalue; break; case "Span波动率变动": va.VolatilityRate = rm.dvalue.ToString("P2"); break; case "Span涨跌幅度": va.UpLimit = va.DownLimit = rm.dvalue.ToString("P2"); break; } } } } } if (result.SuccessSum < 1) { return result.SetMsg("所有导入数据都未能成功处理"); } using (var trans = BeginTransaction()) { var sql = sqlBuilder.ToString(); var changes = DbContext.Database.ExecuteSqlRaw(sql); changes = DbContext.SaveChanges(); trans.Commit(); } return result.SetMsg($"成功处理{result.SuccessSum}条,失败{result.FailSum}条"); } private ReadResult ReadData(Stream streamIn, bool isVariety) { streamIn.Position = 0; var codePropName = isVariety ? "品种代码" : "标的代码"; var ds = Office.ExcelHelper.ReadExcelAsDataSet(streamIn); var readResult = new ReadResult { dataSet = ds }; var uniqSet = new HashSet(StringComparer.OrdinalIgnoreCase); foreach (DataTable dt in ds.Tables) { List list = null; switch (dt.TableName) { case "预付金比例": list = readResult.marginHis; break; case "Span波动率变动": list = readResult.volRateHis; break; case "Span涨跌幅度": list = readResult.updownHis; break; default: continue; } var reader = new DataRowReader(dt); dt.Columns.Add("处理结果"); var colCount = dt.Columns.Count; uniqSet.Clear(); foreach (DataRow row in dt.Rows.Cast()) { if (row.ItemArray.All(n => string.IsNullOrWhiteSpace(n?.ToString()))) { continue; } reader.SetDataRow(row); try { var model = new ReadModel { dataRow = row, code = reader.GetString(codePropName, true).ToUpperInvariant(), date = reader.GetDate("变动日期", true).Value, dvalue = reader.GetPercent(dt.TableName, false) ?? 0 }; if (!uniqSet.Add(model.code + "^" + model.date.ToShortDateString())) { throw new ServiceException("重复设置"); } model.dvalue = Math.Abs(model.dvalue); model.isPercent = reader.GetString("绝对值方式", false) != "是"; list.Add(model); } catch (ServiceException sex) { readResult.hasError = true; row[colCount - 1] = sex.Message; } } } return readResult; } class ReadModel { public string code; public DateTime date; public double dvalue; public bool isPercent; public DataRow dataRow; } class ReadResult { public bool hasError; public DataSet dataSet; public List marginHis { get; private set; } public List volRateHis { get; private set; } public List updownHis { get; private set; } public ReadResult() { marginHis = new List(); volRateHis = new List(); updownHis = new List(); } } } /// /// /// public class MarginParamsImportResult { public int FailSum { get; set; } public int SuccessSum { get; set; } public string ResultMsg { get; set; } public DataSet ResultSet { get; set; } internal MarginParamsImportResult SetMsg(string msg) { ResultMsg = msg; return this; } } }