using System.Data; using YieldChain.Helpers; using YLErp.BLL; using YLErp.Commons; using YLErp.Models; namespace YLErp.Modules.UnderlyingModule { /// /// 标的品种数据操作服务 /// public class VarietyDalService : YLBaseService { public VarietyDalService(OptUserInfo userInfo) : base(userInfo) { } public void ImportExcel(Stream streamIn, out int totalNum, out int successNum) { totalNum = 0; successNum = 0; int rowIndex = 0; try { var ds = Office.ExcelHelper.ReadExcelAsDataSet(streamIn, new[] { 0 }, 1); 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); totalNum = table.Rows.Count - rowIndex; foreach (var row in table.Rows.Cast()) { if (row.ItemArray.All(n => string.IsNullOrWhiteSpace(n?.ToString()))) { totalNum--; continue; } reader.SetDataRow(row); //映射导入数据 var variety = MapVariety(reader, row); //保存数据 SaveData(variety); successNum++; rowIndex++; } } catch (ServiceException se) { if (se.Tag != null) throw; throw new ServiceException($"第{rowIndex + 2}行,发生错误:{se.Message}"); } } private Variety MapVariety(DataRowReader reader, DataRow row) { var variety = new Variety(); var VarietyCode = reader.GetString("品种代码", true); variety.VarietyCode = VarietyCode; bool isnull = VarietyCode != "篮子标的" && VarietyCode != "组合标的"; bool isadd = true; if (DbContext.variety.FirstOrDefault(o => o.VarietyCode == variety.VarietyCode) != null) { variety = DbContext.variety.FirstOrDefault(o => o.VarietyCode == variety.VarietyCode); isadd = false; } string marketCode = null; string mainCategoryCn = null; string contractSize = null; string unit = null; string VarietyName = null; string AssetType = null; string VarietyEnName = null; string EnUnit = null; string BBGTicker = null; string CommissionType = null; string TradedOptionCommissionType = null; string CloseTodayCommissionType = null; string commissionExchange = null; string commissionDeviation = null; string tradedOptionCommissionExchange = null; string tradedOptionCommissionDeviation = null; string closeTodayCommissionExchange = null; string closeTodayCommissionDeviation = null; DataColumnCollection rowx = row.Table.Columns; foreach (DataColumn col in rowx) { switch (col.ColumnName) { case "交易所代码": marketCode = reader.GetString("交易所代码", false); break; case "主类型": mainCategoryCn = reader.GetString("主类型", PS.Config.Company == Configuration.CompanyEnum.中金); break; case "合约乘数": contractSize = reader.GetString("合约乘数", false); break; case "单位": unit = reader.GetString("单位", false); break; case "品种名": VarietyName = reader.GetString("品种名", false); break; case "品种类型": AssetType = reader.GetString("品种类型", false); break; case "品种英文名": VarietyEnName = reader.GetString("品种英文名", false); break; case "单位英文描述": EnUnit = reader.GetString("单位英文描述", false); break; case "BBG Ticker": BBGTicker = reader.GetString("BBG Ticker", false); break; case "交易所手续费类型": CommissionType = reader.GetString("交易所手续费类型", false); break; case "场内手续费类型": TradedOptionCommissionType = reader.GetString("场内手续费类型", false); break; case "平今仓手续费类型": CloseTodayCommissionType = reader.GetString("平今仓手续费类型", false); break; case "交易所手续费": commissionExchange = reader.GetString("交易所手续费", false); break; case "手续费偏离值": commissionDeviation = reader.GetString("手续费偏离值", false); break; case "交易所场内手续费": tradedOptionCommissionExchange = reader.GetString("交易所场内手续费", false); break; case "场内手续费偏离值": tradedOptionCommissionDeviation = reader.GetString("场内手续费偏离值", false); break; case "交易所平今仓手续费": closeTodayCommissionExchange = reader.GetString("交易所平今仓手续费", false); break; case "平今仓手续费偏离值": closeTodayCommissionDeviation = reader.GetString("平今仓手续费偏离值", false); break; } } var market = DataCacheProvider.GetMarketDataSource().AsQueryable().FirstOrDefault(o => o.ExchangeNo == marketCode); if (isadd) { if (market == null && isnull) { throw new ServiceException("未找到交易所代码对应的交易所"); } if (contractSize == null) { throw new ServiceException("未找到合约乘数"); } if (unit == null) { throw new ServiceException("未找到单位"); } if (VarietyName == null) { throw new ServiceException("未找到品种名"); } if (AssetType == null && PS.Config.Company == Configuration.CompanyEnum.中金) { throw new ServiceException("未找到品种类型"); } if (CommissionType == null) { throw new ServiceException("未找到交易所手续费类型"); } if (TradedOptionCommissionType == null) { throw new ServiceException("未找到场内手续费类型"); } if (CloseTodayCommissionType == null) { throw new ServiceException("未找到平今仓手续费类型"); } } variety.VarietyName = VarietyName == null ? variety.VarietyName : VarietyName; variety.AssetType = AssetType == null ? variety.AssetType : AssetType; variety.VarietyEnName = VarietyEnName == null ? variety.VarietyEnName : VarietyEnName; variety.TradingMarket = market == null ? variety.TradingMarket : market.MarketName; variety.TradingMarketId = market == null ? variety.TradingMarketId : market.id; if (contractSize != null && unit != null) { if (double.TryParse(contractSize, out var contractsize)) { variety.TradeUnit = contractsize + unit + "/手"; } } variety.EnUnit = EnUnit == null ? variety.EnUnit : EnUnit; variety.BBGTicker = BBGTicker == null ? variety.BBGTicker : BBGTicker; variety.QuoteUnit = unit == null ? variety.QuoteUnit : "元(人民币)/" + unit; if (mainCategoryCn != null) { variety.MainCategory = string.IsNullOrWhiteSpace(mainCategoryCn) ? null : ConsGlobal.MainCategory.GetFromDesc(mainCategoryCn); } variety.CommissionType = CommissionType == null ? variety.CommissionType : CommissionType; variety.TradedOptionCommissionType = VarietyName == null ? variety.TradedOptionCommissionType : TradedOptionCommissionType; variety.CloseTodayCommissionType = VarietyName == null ? variety.CloseTodayCommissionType : CloseTodayCommissionType; if (commissionExchange != null) { if (double.TryParse(commissionExchange, out var CommissionExchange)) { variety.CommissionExchange = CommissionExchange; } } if (commissionDeviation != null) { if (double.TryParse(commissionDeviation, out var CommissionDeviation)) { variety.CommissionDeviation = CommissionDeviation; } } if (tradedOptionCommissionExchange != null) { if (double.TryParse(tradedOptionCommissionExchange, out var TradedOptionCommissionExchange)) { variety.TradedOptionCommissionExchange = TradedOptionCommissionExchange; } } if (tradedOptionCommissionDeviation != null) { if (double.TryParse(tradedOptionCommissionDeviation, out var TradedOptionCommissionDeviation)) { variety.TradedOptionCommissionDeviation = TradedOptionCommissionDeviation; } } if (closeTodayCommissionExchange != null) { if (double.TryParse(closeTodayCommissionExchange, out var CloseTodayCommissionExchange)) { variety.CloseTodayCommissionExchange = CloseTodayCommissionExchange; } } if (closeTodayCommissionDeviation != null) { if (double.TryParse(closeTodayCommissionDeviation, out var CloseTodayCommissionDeviation)) { variety.CloseTodayCommissionDeviation = CloseTodayCommissionDeviation; } } using (var db = DbContextFactory.GetErpBaseContext()) { var dicId = db.Dictionaries.FirstOrDefault(o => o.Name == "品种类型").Id; if (!db.DictionaryItems.Any(x => x.Name == variety.AssetType && x.DictId == dicId) && AssetType != null) { throw new ServiceException("未找到品种类型" + variety.AssetType); } } var currency = DbContext.currency.FirstOrDefault(o => o.CurrencyCode == variety.QuoteCurrency); if (currency == null && !string.IsNullOrEmpty(variety.QuoteCurrency)) { throw new ServiceException("计价币种不存在,请先维护货币" + variety.QuoteCurrency); } else if (!string.IsNullOrEmpty(variety.QuoteCurrency)) { if (variety.QuoteCurrency != "CNH" && variety.QuoteCurrency != "CNY") { variety.QuoteUnit = currency.CurrencyUnit + "/" + unit; } } return variety; } public VarietyDto GetDetail(int id) { Variety va = DbContext.variety.AsNoTracking().FirstOrDefault(n => n.id == id); if (va == null) { return null; } var dto = new VarietyDto(); ObjectHelper.MapValues(dto, va); dto.HisDataList = DbContext.VarietyHisData.Where(n => n.VarietyId == id).OrderBy(n => n.ValueDate) .Select(n => new HistoryData { Value = n.Value, ValueDate = n.ValueDate, ValueType = n.ValueType }).ToArray(); return dto; } /// /// 保存数据 /// public Variety SaveData(Variety reqModel) { Variety dbModel; var isNew = reqModel.id == 0; if (isNew) { dbModel = reqModel; if (DbContext.variety.Any(o => o.VarietyName == reqModel.VarietyName)) { throw new ServiceException("保存失败,已存在名为" + reqModel.VarietyName + "的品种"); } DbContext.variety.Add(dbModel); } else { dbModel = DbContext.variety.Find(reqModel.id); if (dbModel == null) { throw new ServiceException("保存失败,数据不存在"); } UpdateChanges(dbModel, reqModel, "id"); } var currency = DbContext.currency.FirstOrDefault(o => o.CurrencyCode == dbModel.QuoteCurrency); if (currency == null && !string.IsNullOrEmpty(dbModel.QuoteCurrency)) { throw new ServiceException("计价币种不存在,请先维护货币" + dbModel.QuoteCurrency); } dbModel.VarietyCode = dbModel.VarietyCode; if (dbModel.CommissionType == ConsCommissionType.Ratio && dbModel.CommissionExchange.HasValue) { dbModel.CommissionExchange = Convert.ToDouble(OtcFormatExtensions.OtcFormatValue(dbModel.CommissionExchange.Value / 10000, 8)); } if (dbModel.CommissionType == ConsCommissionType.Ratio && dbModel.CommissionDeviation.HasValue) { dbModel.CommissionDeviation = Convert.ToDouble(OtcFormatExtensions.OtcFormatValue(dbModel.CommissionDeviation.Value / 10000, 8)); } if (dbModel.TradedOptionCommissionType == ConsCommissionType.Ratio && dbModel.TradedOptionCommissionExchange.HasValue) { dbModel.TradedOptionCommissionExchange = Convert.ToDouble(OtcFormatExtensions.OtcFormatValue(dbModel.TradedOptionCommissionExchange.Value / 10000, 8)); } if (dbModel.TradedOptionCommissionType == ConsCommissionType.Ratio && dbModel.TradedOptionCommissionDeviation.HasValue) { dbModel.TradedOptionCommissionDeviation = Convert.ToDouble(OtcFormatExtensions.OtcFormatValue(dbModel.TradedOptionCommissionDeviation.Value / 10000, 8)); } if (dbModel.CloseTodayCommissionType == ConsCommissionType.Ratio && dbModel.CloseTodayCommissionExchange.HasValue) { dbModel.CloseTodayCommissionExchange = Convert.ToDouble(OtcFormatExtensions.OtcFormatValue(dbModel.CloseTodayCommissionExchange.Value / 10000, 8)); } if (dbModel.CloseTodayCommissionType == ConsCommissionType.Ratio && dbModel.CloseTodayCommissionDeviation.HasValue) { dbModel.CloseTodayCommissionDeviation = Convert.ToDouble(OtcFormatExtensions.OtcFormatValue(dbModel.CloseTodayCommissionDeviation.Value / 10000, 8)); } if (dbModel.CommissionExchange.HasValue || dbModel.CommissionDeviation.HasValue) { dbModel.Commission = Convert.ToDouble(OtcFormatExtensions.OtcFormatValue((dbModel.CommissionExchange ?? 0) + (dbModel.CommissionDeviation ?? 0), 8)); } else { dbModel.Commission = null; } if (dbModel.TradedOptionCommissionExchange.HasValue || dbModel.TradedOptionCommissionDeviation.HasValue) { dbModel.TradedOptionCommission = Convert.ToDouble(OtcFormatExtensions.OtcFormatValue((dbModel.TradedOptionCommissionExchange ?? 0) + (dbModel.TradedOptionCommissionDeviation ?? 0), 8)); } else { dbModel.TradedOptionCommission = null; } if (dbModel.CloseTodayCommissionExchange.HasValue || dbModel.CloseTodayCommissionDeviation.HasValue) { dbModel.CloseTodayCommission = Convert.ToDouble(OtcFormatExtensions.OtcFormatValue((dbModel.CloseTodayCommissionExchange ?? 0) + (dbModel.CloseTodayCommissionDeviation ?? 0), 8)); } else { dbModel.CloseTodayCommission = null; } dbModel.OptId = UserId; dbModel.OptName = UserName; dbModel.OptDate = DateTime.Now; dbModel.DownLimit = dbModel.UpLimit; //1.修改underlying的单位 var Underlyings = DbContext.underlying_manager.Where(o => o.CommodityCode == dbModel.VarietyCode); if (Underlyings != null) { foreach (var item in Underlyings) { item.UnderlyingType = dbModel.VarietyName; item.QuoteUnit = dbModel.QuoteUnitSingleOriginal; item.TradeUnit = dbModel.TradeUnitSingle; } } using (var trans = BeginTransaction()) { DbContext.SaveChanges(); UpdateHisData(reqModel, isNew); DbContext.SaveChanges(); trans.Commit(); } new DicForTranslationModule.DicForTranslationService(OptUser).SetWordDictionary(dbModel); return dbModel; } /// /// 删除数据 /// public void RemoveData(int id) { if (DbContext.client_variety_config.Any(x => x.VarietyId == id)) { throw new ServiceException("收费配置包含该品种信息,不能被删除"); } if (DbContext.client_variety_marginrate.Any(x => x.VarietyId == id)) { throw new ServiceException("预付金维护包含该品种信息,不能被删除"); } var va = DbContext.variety.Find(id); if (va == null) { throw new ServiceException("找不到品种信息"); } DbContext.variety.Remove(va); var vvols = DbContext.variety_vol.Where(n => n.VarietyId == id).ToArray(); DbContext.variety_vol.RemoveRange(vvols); var vhis = DbContext.VarietyHisData.Where(n => n.VarietyId == id).ToArray(); DbContext.VarietyHisData.RemoveRange(vhis); DbContext.SaveChanges(); } /// /// 保存历史数据 /// private void UpdateHisData(Variety newData, bool isNew) { var sysDate = valuedateBLL.ValueDate; var newPara = MarginParamModel.Create(newData.Margin, newData.VolatilityRate, newData.UpLimit, false); if (!string.IsNullOrWhiteSpace(newData.VolatilityRate) && !newPara.VolatilityRate.HasValue) { throw new ServiceException("解析Span波动率变动失败:" + newData.VolatilityRate); } if (!string.IsNullOrWhiteSpace(newData.UpLimit) && !newPara.UpDownLimit.HasValue) { throw new ServiceException("解析Span涨跌幅度失败:" + newData.UpLimit); } if (isNew) { DbContext.BulkDelete($"{nameof(VarietyHisData.VarietyId)}='{newData.id}'"); } var hisdataService = new VarietyHisDataService(this); var valdate = isNew ? new DateTime(2000, 1, 1) : valuedateBLL.ValueDate; hisdataService.AddOrUpdateHisData(new VarietyHisDataAddOrUpdateRequest { VarietyId = newData.id, ValueType = nameof(MarginParamModel.MarginRate), Value = newPara.MarginRate, ValueDate = valdate }, false); hisdataService.AddOrUpdateHisData(new VarietyHisDataAddOrUpdateRequest { VarietyId = newData.id, ValueType = nameof(MarginParamModel.VolatilityRate), Value = newPara.VolatilityRate, ValueDate = valdate }, false); hisdataService.AddOrUpdateHisData(new VarietyHisDataAddOrUpdateRequest { VarietyId = newData.id, ValueType = nameof(MarginParamModel.UpDownLimit), Value = newPara.UpDownLimit, ValueDate = valdate }, false); } } }