Files
zszq-trs/YLErpDAL/Modules/SalesModule/SalesCommissionDetailDataService.cs
T
2024-05-09 14:06:26 +08:00

443 lines
19 KiB
C#

using BaseOUDAL;
using Qdp.Pricing.Library.Common.Interfaces;
using System.ComponentModel;
using YLErp.BLL;
using YLErp.DBModels.Helpers;
using YLErp.Model;
using YLErp.Modules.CalculationModule;
namespace YLErp.Modules.SalesModule
{
public class SalesCommissionDetailDataService : YLBaseService
{
public SalesCommissionDetailDataService(OptUserInfo userInfo) : base(userInfo)
{
}
public SalesCommissionDetailDataService(YLBaseService baseService) : base(baseService)
{
}
public SearchListResult<CommissionsDetailGroupByClient> FunDunCommissionDetailQueryByClient(BaseSearchReq req, List<int> salesmen, List<string> departments, List<int> clients)
{
// EF Core 不支持from group select g 用法
//var query = from s in DbContext.SalesCommissionDetail
// where s.IsValid && s.TradeCashID != 0
// group s by s.ClientID into g
// select g;
////根据客户查询
//if (clients != null && clients.Count > 0)
//{
// query = query.Where(o => clients.Contains(o.Key));
//}
//var temp = query.ToList();
var query = DbContext.SalesCommissionDetail.Where(b => b.IsValid && b.TradeCashID != 0);
if (clients != null && clients.Count > 0)
{
query = query.Where(o => clients.Contains(o.ClientID));
}
var temp = query?.ToList()?.GroupBy(g => g.ClientID)?.ToList();
var commissionGroups = new List<CommissionsDetailGroupByClient>();
foreach (var item in temp)
{
var commissionGroup = new CommissionsDetailGroupByClient
{
id = item.Key
};
item.OrderBy(o => o.TradeID);
foreach (var c in item)
{
double? tempCommission;
if (!c.CommissionFixed)
{
tempCommission = c.CommissionProportionAmount;
}
else
{
tempCommission = c.Commission;
}
commissionGroup.commissionCount++;
commissionGroup.commissionAmount = (commissionGroup.commissionAmount == null ? 0 : commissionGroup.commissionAmount) + tempCommission;
}
var tempSalesmen = new List<int>();
foreach (var com in item)
{
tempSalesmen.Add(com.SalesmanID);
}
//根据销售员查询
if (salesmen != null && salesmen.Count > 0)
{
if (tempSalesmen.Except(salesmen).Count() == tempSalesmen.Distinct().Count())
{
continue;
}
}
var men = new SalesmenDataService(OptUser).GetSalesmen(tempSalesmen);
//根据部门查询
if (departments != null && departments.Count > 0)
{
var departmentGroup = men.GroupBy(o => o.Department).Select(o => o.Key);
if (departmentGroup.Except(departments).Count() == (departmentGroup).Distinct().Count())
{
continue;
}
}
foreach (var man in men)
{
commissionGroup.salesman += man.Name + "、";
if (commissionGroup.department == null || !commissionGroup.department.Contains(man.Department))
{
commissionGroup.department += man.Department + "、";
}
}
commissionGroup.salesman = commissionGroup.salesman?.TrimEnd('、');
commissionGroup.department = commissionGroup.department?.TrimEnd('、');
commissionGroup.clientname = DataCacheProvider.GetClientDataSource().GetData(commissionGroup.id)?.Name;
commissionGroups.Add(commissionGroup);
}
var ret = commissionGroups.AsQueryable().ToSearchList(req);
ret.Sum = new
{
AmountSum = ret.rows.Sum(o => o.commissionAmount),
CountSum = ret.rows.Sum(o => o.commissionCount)
};
return ret;
}
public SearchListResult<CommissionDetailByTrade> CommissionDetailQuery(SalesCommissionDetailReq req)
{
var salesDic = new Lazy<Dictionary<int, string>>(() =>
{
return DbContext.salesmen.Select(n => new { n.id, n.Name }).ToDictionary(n => n.id, m => m.Name);
});
var fliterSalesNames = new List<string>();
var query = from s in DbContext.SalesCommissionDetail
where s.IsValid && s.TradeCashID != 0
join t in DbContext.trade
on s.TradeID equals t.id
select new CommissionDetailByTrade
{
id = s.id,
tradeid = t.id,
tradeNumber = t.TradeNumber,
tradeStatus = t.TradeStatus,
salesmanId = s.SalesmanID,
traderName = t.TraderName,
clientName = t.ClientName,
clientId = t.ClientId.ToString(),
buySell = t.BuySell,
tradeDate = t.TradeDate,
tradeType = t.TradeType,
structureType = t.StructureType,
StockEqvNotional = t.OriginalStockEqvNotional,
TradeSinglePrice = t.TradeType == "现金流交易" ? (t.TradePrice ?? 0) : (t.TradeSinglePrice ?? 0),
commissionAmout = s.CommissionFixed ? s.Commission : s.CommissionProportionAmount,
CommissionCalcu = s.CommissionFixed ? "" : s.CommissionCalcu
};
if (!string.IsNullOrWhiteSpace(req.salesmanIds))
{
var ids = req.salesmanIds.Split(',').Select(O => int.TryParse(O, out int id) ? id : 0).ToList();
query = query.Where(o => ids.Contains(o.salesmanId));
}
if (!string.IsNullOrWhiteSpace(req.clientIds))
{
var clients = req.clientIds.Split(',').ToList();
query = query.Where(o => clients.Contains(o.clientId));
}
if (!string.IsNullOrWhiteSpace(req.TradeNumber))
{
query = query.Where(o => o.tradeNumber.Contains(req.TradeNumber));
}
if (req.tradeDateStart != null)
{
query = query.Where(o => o.tradeDate >= req.tradeDateStart);
}
if (req.tradeDateEnd != null)
{
query = query.Where(o => o.tradeDate <= req.tradeDateEnd);
}
var temp = query.ToList().OrderBy(o => o.tradeid);
if (temp.Count() == 0)
{
return null;
}
var line = new CommissionDetailByTrade();
var result = new List<CommissionDetailByTrade>();
foreach (var item in temp)
{
line = new CommissionDetailByTrade()
{
id = item.id,
tradeid = item.tradeid,
buySell = item.buySell,
clientId = item.clientId,
clientName = item.clientName,
commissionAmout = item.commissionAmout,
StockEqvNotional = item.StockEqvNotional,
TradeSinglePrice = item.TradeSinglePrice,
structureType = item.structureType,
tradeDate = item.tradeDate,
tradeNumber = item.tradeNumber,
traderName = item.traderName,
tradeStatus = item.tradeStatus,
tradeType = item.tradeType,
CommissionCalcu = item.CommissionCalcu,
};
if (salesDic.Value.TryGetValue(item.salesmanId, out var name))
{
line.salesmanName = name;
}
result.Add(line);
//if (int.TryParse(item.salesmanName, out var id) && id > 0
// && salesDic.Value.TryGetValue(id, out var name) && !string.IsNullOrWhiteSpace(name))
//{
// line.salesmanName = name;
//}
}
//if (line != null && !string.IsNullOrWhiteSpace(line.salesmanName))
//{
// line.salesmanName = line.salesmanName.TrimEnd('、');
//}
//if (JudgeSalesmanName(line, fliterSalesNames))
//{
// result.Add(line);
//}
var ret = result.AsQueryable().ToSearchList(req);
return ret;
}
/// <summary>
/// 移除交易提成
/// </summary>
/// <param name="tradeId"></param>
/// <param name="useSave"></param>
public void RemoveTradeCommissionDetail(int tradeId, bool useSave = true)
{
//删除原来的数据
var oldCommissionsDetail = DbContext.SalesCommissionDetail.Where(o => o.TradeID == tradeId);
if (oldCommissionsDetail.Any())
oldCommissionsDetail.ToList().ForEach(l =>
{
l.IsValid = false;
l.TradeCashID = l.TradeCashID == 0 ? -1 : l.TradeCashID;//这个操作是防止计算提成的时候,查到这条记录;
});
if (useSave)
{
DbContext.SaveChanges();
}
}
/// <summary>
/// 保存交易提成明细
/// </summary>
public int SaveTradeCommissionDetail(int tradeId, int? ClientId, double? Commission, bool? CommissionFixed, IEnumerable<int> SalesIds, bool isValid, bool delOldData = true)
{
if (tradeId < 0)
{
throw new ServiceException("参数错误:" + nameof(tradeId));
}
if (ClientId < 1)
{
throw new ServiceException("参数错误:" + nameof(ClientId));
}
if (Commission < 0)
{
throw new ServiceException("提成金额 必须大于等于0");
}
if (delOldData)
{
//删除原来的数据
RemoveTradeCommissionDetail(tradeId, false);
}
//如果销售员,销售提成没了,那也没必要新增了
if (!SalesIds.Any())
{
DbContext.SaveChanges();
return 0;
}
if (!Commission.HasValue || Commission == 0)
{
DbContext.SaveChanges();
return 0;
}
var saleCount = SalesIds.Count();
var commissions = SalesIds.Select(n => new SalesCommissionDetail
{
ClientID = (int)ClientId,
Commission = Commission.Value / saleCount,
CommissionFixed = (bool)CommissionFixed,
OptDate = OptDate,
SalesmanID = n,
TradeID = tradeId,
IsValid = isValid
}).ToArray();
DbContext.SalesCommissionDetail.AddRange(commissions);
return DbContext.SaveChanges();
}
public void CalcuSalesCommissionDetail(trade_cash trade_Cash)
{
var trade = DbContext.trade.Where(l => l.id == trade_Cash.TradeId).FirstOrDefault();
if (trade == null) return;
var tradeClone = trade.Clone();
var salesCommissions = DbContext.SalesCommissionDetail.Where(x => x.TradeID == trade.id && x.TradeCashID == 0 && !x.CommissionFixed).ToList();
if (!salesCommissions.Any()) return;
if (!ConsTrade.TradeTypesForHedge.Contains(trade.TradeType))
{
double? nowPrice = tradeClone.SpotPrice;
//计算全额payoff
var notional = tradeClone.Notional;
tradeClone.Notional = tradeClone.OriginalNotional.Value;//原始份额不应该为Null
FangDunGetPayoff(tradeClone, Convert.ToDouble(nowPrice), out var amount);
tradeClone.Notional = notional;
//计算全额时间价值
var timePrice = (tradeClone.TradeSinglePrice.GetValueOrDefault() * tradeClone.OriginalNotional - (amount <= 0 ? 0 : amount));
//把全额时间价值换成当前了结部分的时间价值
timePrice = timePrice < 0 ? 0 : timePrice * trade_Cash.UnwindPercentRate;
//实际存续天数
var ActualExistenceDate = trade_Cash.ValueDate.Subtract(Convert.ToDateTime(trade.TradeDate)).TotalDays;
ActualExistenceDate = ActualExistenceDate < 1 ? 1 : ((int)ActualExistenceDate);
// var ActualExistenceDate = QdpModule.QdpCalendarHelper.AllBizDays(Convert.ToDateTime(trade.TradeDate), Convert.ToDateTime(tc.ValueDate)).Count;
//约定存续天数
var AgreedExistenceDate = Convert.ToDateTime(trade.ExerciseDate).Subtract(Convert.ToDateTime(trade.TradeDate)).TotalDays;
AgreedExistenceDate = AgreedExistenceDate < 1 ? 1 : ((int)AgreedExistenceDate);
// var AgreedExistenceDate = QdpModule.QdpCalendarHelper.AllBizDays(Convert.ToDateTime(trade.TradeDate), Convert.ToDateTime(trade.ExerciseDate)).Count;
foreach (var commission in salesCommissions)
{
//计算 提成金额 公式
var commissionProportionAmount = timePrice * ActualExistenceDate / AgreedExistenceDate * commission.Commission;
var commissionCalcu = $"{timePrice}*{ActualExistenceDate}/{AgreedExistenceDate}*{commission.Commission}";
commission.TradeCashID = trade_Cash.id;
commission.CommissionCalcu = commissionCalcu;
commission.CommissionProportionAmount = commissionProportionAmount;
commission.IsValid = true;
}
if (!trade_Cash.IsLastAction)
{
SaveTradeCommissionDetail(trade.id, trade.ClientId, salesCommissions.Sum(O => O.Commission), false, salesCommissions.Select(O => O.SalesmanID), false, false);
}
DbContext.SaveChanges();
}
}
public static void FangDunGetPayoff(trade trade, double price, out double amount)
{
amount = 0;
string fixings = null;
DateTime? finalPriceSettleDate = null;
tradeBLL.SetFieldsByTradeType(trade);
var isAsianOption = trade.TradeType == "亚式期权";
if (isAsianOption && trade.trade_asian_option == null)
{
throw new ServiceException("缺少亚式期权交易信息");
}
if (isAsianOption)
{
var startDate = trade.trade_asian_option.AveragingPeriodStartDate ?? trade.TradeDate.Value;
var settleDate = finalPriceSettleDate ?? valuedateBLL.ValueDate;
//亚式浮动行权价并且行权价有输入值的情况下
if (trade.trade_asian_option.StrikeType == "Floating")
{
//均价起算日大于结算日的情况下取计值日
if (startDate > settleDate)
{
startDate = settleDate;
}
fixings = $"{startDate:yyyy-MM-dd},{price}";
}
else
{
//均价起算日大于结算日的情况下取不到fixing则直接赋值
if (startDate > settleDate)
{
fixings = $"{settleDate:yyyy-MM-dd},{price}";
}
else
{
fixings = AsianOptionFixingService.GetFixingString(settleDate, trade);
if (string.IsNullOrEmpty(fixings))
{
//取不到fixing则直接赋值
fixings = $"{settleDate:yyyy-MM-dd},{price}";
}
}
}
}
var QdpTrade = TradeCalcHelper.GetQdpTrade(trade, finalPriceSettleDate, fixings);
if (QdpTrade != null && QdpTrade.Instrument != null && QdpTrade.Instrument is IOption opt)
{
var value = 1;
if (trade.BuySell == "卖出")
{
value = -1;
}
var cashFlows = opt.GetPayoff(new double[] { price });
if (cashFlows != null && (cashFlows[0].PaymentAmount == 0 || double.IsNaN(cashFlows[0].PaymentAmount)))
{
amount = TradeHelper.GetAmountByPaymentAmount(0, trade.PrincipalSum(), trade.BuySell) * value;
}
else
{
//cashFlows[0].PaymentAmount包含了买卖方向的处理了
amount = TradeHelper.GetAmountByPaymentAmount(cashFlows[0].PaymentAmount, trade.PrincipalSum(), trade.BuySell) * value;
}
}
}
}
public class SalesCommissionDetailReq : BaseSearchReq
{
/// <summary>
/// 销售员ID
/// </summary>
public string salesmanIds { get; set; }
/// <summary>
/// 客户ID
/// </summary>
public string clientIds { get; set; }
/// <summary>
/// 交易编号
/// </summary>
public string TradeNumber { get; set; }
/// <summary>
/// 交易日期始
/// </summary>
public DateTime? tradeDateStart { get; set; }
/// <summary>
/// 交易日期末
/// </summary>
public DateTime? tradeDateEnd { get; set; }
}
public class CommissionsDetailGroupByClient
{
public int id;
[DisplayName("销售员")]
public string salesman { get; set; }
[DisplayName("部门")]
public string department { get; set; }
[DisplayName("客户名称")]
public string clientname { get; set; }
[DisplayName("提成金额")]
public double? commissionAmount { get; set; }
[DisplayName("交易数目")]
public int commissionCount { get; set; }
}
}