FeeAuditRepository.cs 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850
  1. using EyeSoft.Logging;
  2. using NPOI.SS.Formula.Functions;
  3. using OASystem.Domain;
  4. using OASystem.Domain.Entities.Groups;
  5. using OASystem.Domain.Entities.Resource;
  6. using OASystem.Domain.ViewModels.Groups;
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Linq;
  10. using System.Text;
  11. using System.Threading.Tasks;
  12. namespace OASystem.Infrastructure.Repositories.Groups
  13. {
  14. /// <summary>
  15. /// 费用审核仓储
  16. /// </summary>
  17. public class FeeAuditRepository:BaseRepository<EntityBase,ViewBase>
  18. {
  19. public FeeAuditRepository(SqlSugarClient sqlSugar) : base(sqlSugar)
  20. {
  21. }
  22. /// <summary>
  23. /// 费用自动审核
  24. /// </summary>
  25. /// <param name="feeType">
  26. /// 1.酒店 76
  27. /// 2.op 79
  28. /// 3.其他费用-出行物资 98
  29. /// 4.保险 82
  30. /// </param>
  31. /// <param name="diId">团组Id</param>
  32. /// <param name="dataId">数据Id(模块类型主表Id)</param>
  33. /// <returns></returns>
  34. public async Task<JsonView> FeeAutomaticAudit(int feeType, int diId, int dataId)
  35. {
  36. var _view = new JsonView() { Code = 201, Msg = "自动审核操作失败" };
  37. if (diId < 1) { _view.Msg = MsgTips.DiId; return _view; }
  38. if (dataId < 1) { _view.Msg = MsgTips.Id; return _view; }
  39. var stids = new List<int>() { 17, 66, 91 };
  40. var setData = _sqlSugar.Queryable<Sys_SetData>().Where(x => x.IsDel == 0 && stids.Contains(x.STid)).ToList();
  41. string _teamCurrency = string.Empty;
  42. var groupInfo = _sqlSugar.Queryable<Grp_GroupCostParameter>().Where(x => x.IsDel == 0 && x.DiId == diId).First();
  43. if (groupInfo == null) { _view.Msg = $"团组成本信息未填写!"; return _view; }
  44. _teamCurrency = groupInfo.Currency;
  45. decimal _teamRate = groupInfo.Rate;
  46. //币种验证 统一为currencycode三字码
  47. if (int.TryParse(_teamCurrency,out int currency)) _teamCurrency = setData.Find(x => x.Id == currency)?.Name ?? "";
  48. string costContentSql = $"Select * From Grp_GroupCost";
  49. var costContents = _sqlSugar.SqlQueryable<GroupCostAuditView>(costContentSql).Where(x => x.IsDel == 0 && x.Diid == diId).ToList();
  50. if (costContents.Count < 1) { _view.Msg = $"团组成本信息未填写!"; return _view; }
  51. //处理 成本详细信息 日期为空
  52. for (int i = 0; i < costContents.Count; i++)
  53. {
  54. if (string.IsNullOrEmpty( costContents[i].Date))
  55. {
  56. int index = i - 1;
  57. if (index >= 0)
  58. {
  59. costContents[i].Date = costContents[index].Date;
  60. var dtBool = DateTime.TryParse(costContents[i].Date, out DateTime _dateTime);
  61. if (dtBool)
  62. {
  63. costContents[i].CurrTime = _dateTime;
  64. }
  65. }
  66. }
  67. else
  68. {
  69. var dtBool = DateTime.TryParse(costContents[i].Date, out DateTime _dateTime);
  70. if (dtBool)
  71. {
  72. costContents[i].CurrTime = _dateTime;
  73. }
  74. }
  75. }
  76. if (feeType == 1)
  77. {
  78. //1089 对冲账或其他 不在审核范围
  79. var hotelCostInfo = _sqlSugar.Queryable<Grp_HotelReservations>().Where(x => x.IsDel == 0 && x.DiId == diId && x.Id == dataId && x.CheckType != 1089).First();
  80. var hotelCostDetails = _sqlSugar.Queryable<Grp_HotelReservationsContent>().Where(x => x.IsDel == 0 && x.DiId == diId && x.HrId == dataId).ToList();
  81. if (hotelCostInfo == null)
  82. {
  83. _view.Msg = $"酒店费用数据未填写";
  84. QuashAudit(76, diId, dataId);
  85. return _view;
  86. }
  87. //酒店费用金额 == 0 不自动审核
  88. if (hotelCostInfo.CardPrice == 0.0000M)
  89. {
  90. _view.Msg = $"酒店费用金额 == 0 不自动审核";
  91. QuashAudit(76, diId, dataId);
  92. return _view;
  93. }
  94. //获取C表汇率
  95. decimal _rate = 1.0000M;
  96. var roomFeeInfo = hotelCostDetails.Where(x => x.PriceType == 1).First();
  97. if (roomFeeInfo == null)
  98. {
  99. _view.Msg = $"酒店房间费用付款数据未填写";
  100. return _view;
  101. }
  102. _rate = roomFeeInfo.Rate == 0.0000M ? 1.0000M : roomFeeInfo.Rate;
  103. bool isAutoAudit = true; //是否自动审核
  104. DateTime checkIn = Convert.ToDateTime(hotelCostInfo.CheckInDate),
  105. checkOut = Convert.ToDateTime(hotelCostInfo.CheckOutDate);
  106. if (checkOut > checkIn) checkOut = checkOut.AddDays(-1); //房费计算,结束日期为前一天
  107. var hotelCostInfos = costContents.Where(x => x.CurrTime >= checkIn && x.CurrTime <= checkOut).ToList();
  108. if (hotelCostInfos.Count < 1) isAutoAudit = false;
  109. decimal otherFee = hotelCostDetails.Where(x => x.PriceType != 1).Sum(x => x.Price * (x.Rate == 0.0000M ? 1.0000M : x.Rate));
  110. if (otherFee > 0) { otherFee /= (checkOut - checkIn).Days; }
  111. var hotelCostInfosGroup = hotelCostInfos.GroupBy(x => x.Date);
  112. foreach (var item in hotelCostInfosGroup)
  113. {
  114. var hotelSingleRoomFee = item.Sum(x => x.HotelSingleRoomFee) * _teamRate; //成本单间费用
  115. var hotelDoubleRoomFee = item.Sum(x => x.HotelDoubleRoomFee) * _teamRate; //成本双人间费用
  116. var hotelSuiteFee = item.Sum(x => x.HotelSuiteFee) * _teamRate; //成本套房费用
  117. var hotelSuiteRoomFee = item.Sum(x => x.HotelSuiteRoomFee) * _teamRate; //成本其他房型间费用
  118. //1.判断费用是否 <= 成本费用
  119. //1.1 判断单间费用
  120. decimal singleRoomPrice = (hotelCostInfo.SingleRoomPrice + otherFee) * _rate; //酒店录入费用
  121. if (singleRoomPrice > 0) if (singleRoomPrice > hotelSingleRoomFee) isAutoAudit = false;
  122. //1.2 判断双人间费用
  123. decimal doubleRoomPrice = (hotelCostInfo.DoubleRoomPrice + otherFee) * _rate;//酒店录入费用
  124. if (doubleRoomPrice > 0) if (doubleRoomPrice > hotelDoubleRoomFee) isAutoAudit = false;
  125. //1.3 判断套房费用
  126. decimal suiteRoomPrice = (hotelCostInfo.SuiteRoomPrice + otherFee) * _rate;//酒店录入费用
  127. if (suiteRoomPrice > 0) if (suiteRoomPrice > hotelSuiteFee) isAutoAudit = false;
  128. //1.4 判断其他房型费用
  129. decimal otherRoomPrice = (hotelCostInfo.OtherRoomPrice + otherFee) * _rate;//酒店录入费用
  130. if (otherRoomPrice > 0) if (otherRoomPrice > hotelSuiteRoomFee) isAutoAudit = false;
  131. }
  132. //2.判断是否自动审核
  133. if (isAutoAudit)
  134. {
  135. var ccpUpdate = _sqlSugar.Updateable<Grp_CreditCardPayment>()
  136. .SetColumns(it => it.IsAuditGM == 3)
  137. .SetColumns(it => it.AuditGMOperate == 4)
  138. .SetColumns(it => it.AuditGMDate == DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"))
  139. .Where(s => s.DIId == diId && s.CTable == 76 && s.CId == dataId)
  140. .ExecuteCommand();
  141. if (ccpUpdate > 0)
  142. {
  143. _view.Code = 200;
  144. _view.Msg = "自动审核执行成功";
  145. return _view;
  146. }
  147. }
  148. else
  149. {
  150. //撤销该条数据的自动审核 --> 该条数据的审核状态是自动审核 3 --> 0
  151. var quashStatus = QuashAudit(76, diId, dataId);
  152. if (quashStatus)
  153. {
  154. _view.Code = 200;
  155. _view.Msg = "费用超团组成本,自动审核撤销成功!";
  156. return _view;
  157. }
  158. }
  159. }
  160. else if (feeType == 2)
  161. {
  162. //1.基础数据参数验证
  163. var priceType = new List<int>() {
  164. 1062 //1062 尾款
  165. };
  166. var opinfos = _sqlSugar.Queryable<Grp_CarTouristGuideGroundReservations>()
  167. .Where(x => x.IsDel == 0 && x.DiId == diId && x.Id == dataId && !priceType.Contains(x.PriceType))
  168. .First();
  169. //var opinfos = _sqlSugar.Queryable<Grp_CarTouristGuideGroundReservations>()
  170. // .Where(x => x.IsDel == 0 && x.DiId == diId && x.Id == dataId )
  171. // .First();
  172. if (opinfos == null)
  173. {
  174. _view.Msg = $"OP费用费用类型属于“尾款”或者 内容未填写";
  175. return _view;
  176. }
  177. //1.含超时费用/超支费用 手动审核
  178. if (opinfos.SelectCheck.Contains("超时") || opinfos.SelectCheck.Contains("超支") || opinfos.SelectCheck.Contains("尾款"))
  179. {
  180. _view.Msg = @$"OP费用含尾款/超支/超时费用,请手动审核";
  181. return _view;
  182. }
  183. //1.参数验证
  184. var opCheckPriceTyeps = opinfos.SelectCheck.Split(',');
  185. var opCheckPriceTyepIds = setData.Where(x => opinfos.SelectCheck.Split(',').Contains(x.Name)).Select(x => x.Id).ToList();
  186. var opContents = _sqlSugar.Queryable<Grp_CarTouristGuideGroundReservationsContent>()
  187. .Where(x => x.IsDel == 0 && x.DiId == diId && x.CTGGRId == dataId && opCheckPriceTyepIds.Contains(x.SId))
  188. .OrderBy(x => x.DatePrice, OrderByType.Asc)
  189. .ToList();
  190. if (opContents.Count < 1)
  191. {
  192. _view.Msg = $"OP费用费用内容未填写";
  193. return _view;
  194. }
  195. //获取C表汇率
  196. decimal _opRate = 1.0000M;
  197. var payInfo = _sqlSugar.Queryable<Grp_CreditCardPayment>().Where(x => x.IsDel == 0 && x.DIId == diId && x.CTable == 79 && x.CId == dataId).First();
  198. if (payInfo == null)
  199. {
  200. _view.Msg = $"OP费用付款数据未填写";
  201. return _view;
  202. }
  203. _opRate = payInfo.DayRate;
  204. string opCurrencyName = setData.Find(x => x.Id == opContents[0].Currency)?.Name ?? "";
  205. //团组、OP币种 验证是否一致
  206. if (opCurrencyName.Equals(_teamCurrency))
  207. {
  208. _opRate = payInfo.DayRate;
  209. _teamRate = payInfo.DayRate;
  210. }
  211. var opBasicDatas = setData.Where(x => x.STid == 17).ToList(); //费用类型基础数据
  212. bool isAutoAudit = true;
  213. if (!DateTime.TryParse(opinfos.ServiceStartTime, out DateTime startDt1) || !DateTime.TryParse(opinfos.ServiceEndTime, out DateTime endDt1))
  214. {
  215. _view.Msg = $"OP费用服务起止日期格式不正确!";
  216. return _view;
  217. }
  218. DateTime startDt = startDt1;
  219. DateTime endDt = endDt1;
  220. var opCostDatas = costContents.Where(it => Convert.ToDateTime(it.Date) >= startDt && Convert.ToDateTime(it.Date) <= endDt).ToList();
  221. if (opCostDatas.Count < 1)
  222. {
  223. _view.Msg = $"该时间段内团组成本未填写!";
  224. return _view;
  225. }
  226. var noAuditFeeTypeIds = new List<int> {
  227. 982 ,//982 车超时费 -- 暂无
  228. 96 ,//96 接送机费 -- 暂无
  229. 97 ,//97 其他费用 -- 暂无
  230. 992 ,//992 住补费用 -- 暂无
  231. 1059,//1059 导游超时费用 -- 暂无
  232. 1070,//1070 尾款金额 -- 暂无
  233. 1071,//1071 其他额外费用 -- 暂无
  234. 1073,//1073 翻译超时费 -- 暂无
  235. 1074,//1074 早餐超支费用 -- 暂无
  236. 1075,//1075 午餐超支费用 -- 暂无
  237. 1076,//1076 晚餐超支费用 -- 暂无
  238. };
  239. //费用类型筛选 包含 feeTypeIds && 包含这些类型费用大于0
  240. var noAuditFeeContents = opContents.Where(x => x.Price > 0 && noAuditFeeTypeIds.Contains(x.SId)).ToList();
  241. if (noAuditFeeContents.Count > 0)
  242. {
  243. _view.Msg = @$"OP费用含尾款/超支/超时费用,请手动审核";
  244. return _view;
  245. }
  246. //2.按天按项 检查费用是否超过预算
  247. var opDayContent = opContents.GroupBy(x => x.DatePrice);
  248. foreach (var item in opDayContent)
  249. {
  250. var opCostInfo = opCostDatas.Where(x => Convert.ToDateTime(x.Date) == item.Key).ToList();
  251. if (opCostInfo.Count < 1) continue;
  252. //车费 91
  253. var opCarCost = item.FirstOrDefault(x => x.SId == 91);
  254. if (opCarCost != null) if (opCarCost.Price * _opRate > _teamRate * opCostInfo.Sum(x => x.CarFee)) isAutoAudit = false;
  255. //982 车超时费 -- 暂无
  256. //92 导游费
  257. var opGuideCost = item.FirstOrDefault(x => x.SId == 92);
  258. if (opGuideCost != null) if (opGuideCost.Price * _opRate > _teamRate * opCostInfo.Sum(x => x.GuideFee)) isAutoAudit = false;
  259. //94 导游景点费
  260. var opGuideScenicCost = item.FirstOrDefault(x => x.SId == 94);
  261. if (opGuideScenicCost != null) if (opGuideScenicCost.Price * _opRate > _teamRate * opCostInfo.Sum(x => x.GuideScenicFee)) isAutoAudit = false;
  262. //95 导游小费
  263. var opGuideTipCost = item.FirstOrDefault(x => x.SId == 95);
  264. if (opGuideTipCost != null) if (opGuideTipCost.Price * _opRate > _teamRate * opCostInfo.Sum(x => x.GuideTipFee)) isAutoAudit = false;
  265. //983 导游餐补
  266. var opGuideMealCost = item.FirstOrDefault(x => x.SId == 983);
  267. if (opGuideMealCost != null) if (opGuideMealCost.Price * _opRate > _teamRate * opCostInfo.Sum(x => x.GuideMealFee)) isAutoAudit = false;
  268. //984 导游房补
  269. var opGuideRoomCost = item.FirstOrDefault(x => x.SId == 984);
  270. if (opGuideRoomCost != null) if (opGuideRoomCost.Price * _opRate > _teamRate * opCostInfo.Sum(x => x.GuideRoomFee)) isAutoAudit = false;
  271. //985 导游交通
  272. var opGuideTrafficCost = item.FirstOrDefault(x => x.SId == 985);
  273. if (opGuideTrafficCost != null) if (opGuideTrafficCost.Price * _opRate > _teamRate * opCostInfo.Sum(x => x.GuideTrafficFee)) isAutoAudit = false;
  274. //96 接送机费 -- 暂无
  275. //97 其他费用 -- 暂无
  276. //979 司机工资
  277. var opDriverCost = item.FirstOrDefault(x => x.SId == 979);
  278. if (opDriverCost != null) if (opDriverCost.Price * _opRate > _teamRate * opCostInfo.Sum(x => x.DriverFee)) isAutoAudit = false;
  279. //980 司机小费
  280. var opDriverTipCost = item.FirstOrDefault(x => x.SId == 980);
  281. if (opDriverTipCost != null) if (opDriverTipCost.Price * _opRate > _teamRate * opCostInfo.Sum(x => x.DriverTipFee)) isAutoAudit = false;
  282. //981 司机餐补
  283. var opDriverMealCost = item.FirstOrDefault(x => x.SId == 981);
  284. if (opDriverMealCost != null) if (opDriverMealCost.Price * _opRate > _teamRate * opCostInfo.Sum(x => x.DriverMealFee)) isAutoAudit = false;
  285. //988 客户早餐费用
  286. var opClientBreakfastCost = item.FirstOrDefault(x => x.SId == 988);
  287. if (opClientBreakfastCost != null) if (opClientBreakfastCost.Price * _opRate > _teamRate * opCostInfo.Sum(x => x.ClientBreakfastFee)) isAutoAudit = false;
  288. //93 客户午餐费用
  289. var opClientLunchCost = item.FirstOrDefault(x => x.SId == 93);
  290. if (opClientLunchCost != null) if (opClientLunchCost.Price * _opRate > _teamRate * opCostInfo.Sum(x => x.ClientLunchFee)) isAutoAudit = false;
  291. //989 客户晚餐费用
  292. var opClientDinnerCost = item.FirstOrDefault(x => x.SId == 989);
  293. if (opClientDinnerCost != null) if (opClientDinnerCost.Price * _opRate > _teamRate * opCostInfo.Sum(x => x.ClientDinnerFee)) isAutoAudit = false;
  294. //990 景点门票费
  295. var opScenicTicketCost = item.FirstOrDefault(x => x.SId == 990);
  296. if (opScenicTicketCost != null) if (opScenicTicketCost.Price * _opRate > _teamRate * opCostInfo.Sum(x => x.ScenicTicketFee)) isAutoAudit = false;
  297. //991 饮料/零食/水果
  298. var opDrinkSnackFruitCost = item.FirstOrDefault(x => x.SId == 991);
  299. if (opDrinkSnackFruitCost != null) if (opDrinkSnackFruitCost.Price * _opRate > _teamRate * opCostInfo.Sum(x => x.DrinkSnackFruitFee)) isAutoAudit = false;
  300. //992 住补费用 -- 暂无
  301. //994 翻译费
  302. var opTranslatorCost = item.FirstOrDefault(x => x.SId == 994);
  303. if (opTranslatorCost != null) if (opTranslatorCost.Price * _opRate > _teamRate * opCostInfo.Sum(x => x.TranslatorFee)) isAutoAudit = false;
  304. //1059 导游超时费用 -- 暂无
  305. //1070 尾款金额 -- 暂无
  306. //1071 其他额外费用 -- 暂无
  307. //1073 翻译超时费 -- 暂无
  308. //1074 早餐超支费用 -- 暂无
  309. //1075 午餐超支费用 -- 暂无
  310. //1076 晚餐超支费用 -- 暂无
  311. }
  312. //更改审核状态
  313. if (isAutoAudit)
  314. {
  315. var ccpUpdate = _sqlSugar.Updateable<Grp_CreditCardPayment>()
  316. .SetColumns(it => it.IsAuditGM == 3)
  317. .SetColumns(it => it.AuditGMOperate == 4)
  318. .SetColumns(it => it.AuditGMDate == DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"))
  319. .Where(s => s.DIId == diId && s.CTable == 79 && s.CId == dataId)
  320. .ExecuteCommand();
  321. if (ccpUpdate > 0)
  322. {
  323. _view.Code = 200;
  324. _view.Msg = "自动审核执行成功!";
  325. return _view;
  326. }
  327. }
  328. else
  329. {
  330. //撤销该条数据的自动审核 --> 该条数据的审核状态是自动审核 3 --> 0
  331. if (QuashAudit(79, diId, dataId))
  332. {
  333. _view.Code = 200;
  334. _view.Msg = "费用超团组成本,自动审核撤销成功!";
  335. return _view;
  336. }
  337. }
  338. }
  339. else if (feeType == 3)
  340. {
  341. #region 出行物资的功能及相关费用自动审核
  342. var isAutoAudit = false;
  343. var currModule = 98; //其他款项
  344. int groupSize = 0; // 团组人数
  345. var groupDetails = await _sqlSugar.Queryable<Grp_DelegationInfo>().Where(x => x.IsDel == 0 && x.Id == diId).FirstAsync();
  346. if (groupInfo != null) groupSize = groupDetails.VisitPNumber;
  347. decimal groupCostCNYTotal = costContents.Sum(x => x.TeFee) * _teamRate * groupSize; //团组成本出行物资总金额
  348. if (groupCostCNYTotal <= 0.00M)
  349. {
  350. _view.Msg = $"团组成本出行物资费用数据未填写";
  351. QuashAudit(currModule, diId, dataId);
  352. return _view;
  353. }
  354. var teNames = setData.Where(x => x.STid == 91).Select(x => x.Name).ToList();
  355. var otherFeeDatas = _sqlSugar.Queryable<Grp_DecreasePayments>()
  356. .InnerJoin<Grp_CreditCardPayment>((dp, ccp) => dp.Id == ccp.CId && ccp.CTable == 98 && ccp.IsDel == 0)
  357. .Where((dp, ccp) => dp.IsDel == 0 && dp.DiId == diId)
  358. .ToList();
  359. var ids = new List<int>();
  360. foreach (var item in otherFeeDatas)
  361. {
  362. if (item.PriceName.Contains("、"))
  363. {
  364. var priceNames = item.PriceName.Split('、');
  365. foreach (var priceName in priceNames)
  366. {
  367. if (teNames.Contains(priceName))
  368. {
  369. ids.Add(item.Id);
  370. continue;
  371. }
  372. }
  373. }
  374. else if (teNames.Contains(item.PriceName))
  375. {
  376. ids.Add(item.Id);
  377. }
  378. }
  379. ids = ids.Distinct().ToList();
  380. decimal otherFeeCNYTotal = otherFeeDatas.Where(x => ids.Contains(x.Id)).Sum(x => x.FeeTotal); //其他费用出行物资总金额
  381. if (otherFeeCNYTotal <= 0.00M)
  382. {
  383. _view.Msg = $"其他款项出行物资费用数据未填写";
  384. QuashAudit(currModule, diId, dataId);
  385. return _view;
  386. }
  387. if (otherFeeCNYTotal > groupCostCNYTotal)
  388. {
  389. _view.Msg = $"其他款项出行物资费用超出团组成本物资费用";
  390. QuashAudit(currModule, diId, dataId);
  391. return _view;
  392. }
  393. isAutoAudit = true;
  394. //2.判断是否自动审核
  395. if (isAutoAudit)
  396. {
  397. var ccpUpdate = _sqlSugar.Updateable<Grp_CreditCardPayment>()
  398. .SetColumns(it => it.IsAuditGM == 3)
  399. .SetColumns(it => it.AuditGMOperate == 4)
  400. .SetColumns(it => it.AuditGMDate == DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"))
  401. .Where(s => s.DIId == diId && s.CTable == currModule && s.CId == dataId)
  402. .ExecuteCommand();
  403. if (ccpUpdate > 0)
  404. {
  405. _view.Code = 200;
  406. _view.Msg = "自动审核执行成功";
  407. return _view;
  408. }
  409. }
  410. else
  411. {
  412. //撤销该条数据的自动审核 --> 该条数据的审核状态是自动审核 3 --> 0
  413. var quashStatus = QuashAudit(currModule, diId, dataId);
  414. if (quashStatus)
  415. {
  416. _view.Code = 200;
  417. _view.Msg = "费用超团组成本,自动审核撤销成功!";
  418. return _view;
  419. }
  420. }
  421. #endregion
  422. }
  423. else if (feeType == 4)
  424. {
  425. #region 保险费用录入自动审核
  426. var currModule = 82;
  427. var groupDetails = _sqlSugar.Queryable<Grp_DelegationInfo>().Where(x => x.IsDel == 0 && x.Id == diId).First();
  428. if (groupDetails == null)
  429. {
  430. _view.Msg = $"团组信息为空,不可自动审核!";
  431. return _view;
  432. }
  433. var insuranceCountryCostData = _sqlSugar.Queryable<Res_BasicInsuranceCost>().Where(x => x.IsDel == 0).ToList();
  434. if (!insuranceCountryCostData.Any())
  435. {
  436. _view.Msg = $"保险国家费用信息为空,不可自动审核!";
  437. return _view;
  438. }
  439. var insuranceType = _sqlSugar.Queryable<Grp_InsuranceCost>().Where(x => x.IsDel == 0 && x.Id != 2).Select(x => x.Id).ToList();
  440. var insuranceCostData1 = _sqlSugar.Queryable<Grp_Customers>()
  441. .LeftJoin<Grp_CreditCardPayment>((c, ccp) => c.Id == ccp.CId && ccp.CTable == 82)
  442. .Where((c, ccp) => c.IsDel == 0 && c.DiId == diId)
  443. .Select((c, ccp) => new
  444. {
  445. c.Id,
  446. c.Iid,
  447. ccpId = ccp.Id,
  448. CNYPrice = ccp.PayMoney * ccp.DayRate
  449. })
  450. .ToList();
  451. if (!insuranceCostData1.Any())
  452. {
  453. _view.Msg = $"暂无保险数据,不可自动审核!";
  454. return _view;
  455. }
  456. #region 处理已审核的 “新数据请不要选此项” 数据
  457. var insuranceCostData2 = insuranceCostData1.Where(x => x.Iid == 2).ToList();
  458. if (insuranceCostData2.Any())
  459. {
  460. var ccpIds = insuranceCostData2.Select(x => x.ccpId).ToList();
  461. var auditCcpIds = _sqlSugar.Queryable<Grp_CreditCardPayment>().Where(x => x.IsDel == 0 && ccpIds.Contains(x.Id) && x.IsAuditGM == 3).Select(x => x.Id).ToList();
  462. if (auditCcpIds.Any())
  463. {
  464. var ccpUpd = _sqlSugar.Updateable<Grp_CreditCardPayment>()
  465. .SetColumns(it => it.IsAuditGM == 0)
  466. .SetColumns(it => it.AuditGMOperate == 0)
  467. .SetColumns(it => it.AuditGMDate == "")
  468. .Where(s => auditCcpIds.Contains(s.Id))
  469. .ExecuteCommand();
  470. }
  471. }
  472. #endregion
  473. var insuranceCostData = insuranceCostData1.Where(x => insuranceType.Contains(x.Iid)).ToList();
  474. var currInsuranceInfo = insuranceCostData.Where(x => x.Id == dataId).FirstOrDefault();
  475. if (!insuranceCostData.Any() && currInsuranceInfo == null)
  476. {
  477. _view.Msg = $"暂无保险数据,不可自动审核!";
  478. return _view;
  479. }
  480. if (currInsuranceInfo.CNYPrice == 0.00M)
  481. {
  482. _view.Msg = $"保险数据未录入费用信息,不可自动审核!";
  483. QuashAudit(currModule, diId, dataId);
  484. return _view;
  485. }
  486. var groupPeopleNum = groupDetails.VisitPNumber;
  487. var visitCountrys = groupDetails.VisitCountry.Split("|").ToList();
  488. if (!visitCountrys.Any())
  489. {
  490. _view.Msg = $"出访国家为空,不可自动审核!";
  491. return _view;
  492. }
  493. var basicCountrys = insuranceCountryCostData.Select(x => x.CountryName).ToList();
  494. var schengenCountry = visitCountrys.Intersect(basicCountrys); //申根国
  495. var unSchengenCountry = visitCountrys.Except(basicCountrys); //非申根国
  496. var schengenCost = insuranceCountryCostData.Where(x => schengenCountry.Contains(x.CountryName)).Sum(x => x.Cost); // 申根国费用
  497. var unSchengenCost = unSchengenCountry.Count() * 35; // 非申根国费用
  498. var groupBudgetCost = (schengenCost + unSchengenCost) * groupPeopleNum;
  499. var groupActialCost = insuranceCostData.Sum(x => x.CNYPrice);
  500. if (groupActialCost > groupBudgetCost)
  501. {
  502. _view.Msg = $"保险费用超出团组成本费用";
  503. QuashAudit(currModule, diId, dataId);
  504. return _view;
  505. }
  506. //自动审核
  507. var ccpUpdate = _sqlSugar.Updateable<Grp_CreditCardPayment>()
  508. .SetColumns(it => it.IsAuditGM == 3)
  509. .SetColumns(it => it.AuditGMOperate == 4)
  510. .SetColumns(it => it.AuditGMDate == DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"))
  511. .Where(s => s.DIId == diId && s.CTable == currModule && s.CId == dataId)
  512. .ExecuteCommand();
  513. if (ccpUpdate > 0)
  514. {
  515. _view.Code = 200;
  516. _view.Msg = "自动审核执行成功";
  517. }
  518. else _view.Msg = "自动审核执行失败";
  519. return _view;
  520. #endregion
  521. }
  522. else _view.Msg = $"请传入有效的feeType参数";
  523. return _view;
  524. }
  525. /// <summary>
  526. /// hotel、op 撤销自动审核的数据
  527. /// </summary>
  528. /// <param name="type">
  529. /// 酒店 76
  530. /// op 79
  531. /// </param>
  532. /// <param name="diId"></param>
  533. /// <param name="dataId"></param>
  534. /// <returns></returns>
  535. private bool QuashAudit(int type, int diId, int dataId)
  536. {
  537. //撤销该条数据的自动审核 --> 该条数据的审核状态是自动审核 3 --> 0
  538. var ccpInfo = _sqlSugar.Queryable<Grp_CreditCardPayment>()
  539. .Where(s => s.DIId == diId && s.CTable == type && s.CId == dataId && s.IsAuditGM == 3)
  540. .First();
  541. if (ccpInfo != null)
  542. {
  543. var ccpUpdate = _sqlSugar.Updateable<Grp_CreditCardPayment>()
  544. .SetColumns(it => it.IsAuditGM == 0)
  545. .SetColumns(it => it.AuditGMOperate == 0)
  546. .SetColumns(it => it.AuditGMDate == string.Empty)
  547. .Where(s => s.Id == ccpInfo.Id)
  548. .ExecuteCommand();
  549. if (ccpUpdate > 0)
  550. {
  551. return true;
  552. }
  553. }
  554. return false;
  555. }
  556. //
  557. /// <summary>
  558. /// 费用自动审核
  559. /// </summary>
  560. /// <param name="feeType">
  561. /// 1.酒店 76
  562. /// 2.op 79
  563. /// </param>
  564. /// <param name="diId">团组Id</param>
  565. /// <param name="dataId">数据Id(模块类型主表Id)</param>
  566. /// <returns></returns>
  567. public string IsOverBudget(int feeType, int diId, int dataId)
  568. {
  569. string _view ="-";
  570. if (diId < 1) { return _view; }
  571. if (dataId < 1) { return _view; }
  572. List<int> stids = new List<int>() { 17, 66 };
  573. var setData = _sqlSugar.Queryable<Sys_SetData>().Where(x => x.IsDel == 0 && stids.Contains(x.STid)).ToList();
  574. string _teamCurrency = string.Empty;
  575. var groupInfo = _sqlSugar.Queryable<Grp_GroupCostParameter>().Where(x => x.IsDel == 0 && x.DiId == diId).First();
  576. if (groupInfo == null) { return _view; }
  577. _teamCurrency = groupInfo.Currency;
  578. //币种验证 统一为currencycode三字码
  579. if (int.TryParse(_teamCurrency, out int currency)) _teamCurrency = setData.Find(x => x.Id == currency)?.Name ?? "";
  580. string costContentSql = $"Select * From Grp_GroupCost";
  581. var costContents = _sqlSugar.SqlQueryable<GroupCostAuditView>(costContentSql).Where(x => x.IsDel == 0 && x.Diid == diId).ToList();
  582. if (costContents.Count < 1) { return _view; }
  583. //处理 成本详细信息 日期为空
  584. for (int i = 0; i < costContents.Count; i++)
  585. {
  586. if (string.IsNullOrEmpty(costContents[i].Date))
  587. {
  588. int index = i - 1;
  589. if (index >= 0)
  590. {
  591. costContents[i].Date = costContents[index].Date;
  592. }
  593. }
  594. }
  595. if (feeType == 1)
  596. {
  597. var hotelCostInfo = _sqlSugar.Queryable<Grp_HotelReservations>().Where(x => x.IsDel == 0 && x.DiId == diId && x.Id == dataId).First();
  598. var hotelCostDetails = _sqlSugar.Queryable<Grp_HotelReservationsContent>().Where(x => x.IsDel == 0 && x.DiId == diId && x.HrId == dataId).ToList();
  599. if (hotelCostInfo == null) return _view;
  600. //获取C表汇率
  601. decimal _rate = 1.0000M;
  602. var roomFeeInfo = hotelCostDetails.Where(x => x.PriceType == 1).First();
  603. if (roomFeeInfo == null) return _view;
  604. _rate = roomFeeInfo.Rate == 0.0000M ? 1.0000M : roomFeeInfo.Rate;
  605. bool isAutoAudit = true; //是否自动审核
  606. DateTime checkIn = Convert.ToDateTime(hotelCostInfo.CheckInDate),
  607. checkOut = Convert.ToDateTime(hotelCostInfo.CheckOutDate);
  608. if (checkOut > checkIn) checkOut = checkOut.AddDays(-1); //房费计算,结束日期为前一天
  609. var hotelCostInfos = costContents.Where(x => Convert.ToDateTime(x.Date) >= checkIn && Convert.ToDateTime(x.Date) <= checkOut).ToList();
  610. if (hotelCostInfos.Count < 1) isAutoAudit = false;
  611. decimal otherFee = hotelCostDetails.Where(x => x.PriceType != 1).Sum(x => x.Price * (x.Rate == 0.0000M ? 1.0000M : x.Rate));
  612. if (otherFee > 0) { otherFee /= (checkOut - checkIn).Days; }
  613. var hotelCostInfosGroup = hotelCostInfos.GroupBy(x => x.Date);
  614. foreach (var item in hotelCostInfosGroup)
  615. {
  616. decimal hotelSingleRoomFee = item.Sum(x => x.HotelSingleRoomFee);
  617. decimal hotelDoubleRoomFee = item.Sum(x => x.HotelDoubleRoomFee);
  618. decimal hotelSuiteFee = item.Sum(x => x.HotelSuiteFee);
  619. decimal hotelSuiteRoomFee = item.Sum(x => x.HotelSuiteRoomFee);
  620. //1.判断费用是否 <= 成本费用
  621. //1.1 判断单间费用
  622. decimal singleRoomPrice = (hotelCostInfo.SingleRoomPrice + otherFee) * _rate;
  623. if (singleRoomPrice > 0) if (singleRoomPrice > hotelSingleRoomFee * _rate) isAutoAudit = false;
  624. //1.2 判断双人间费用
  625. decimal doubleRoomPrice = (hotelCostInfo.DoubleRoomPrice + otherFee) * _rate;
  626. if (doubleRoomPrice > 0) if (doubleRoomPrice > hotelDoubleRoomFee * _rate) isAutoAudit = false;
  627. //1.3 判断套房费用
  628. decimal suiteRoomPrice = (hotelCostInfo.SuiteRoomPrice + otherFee) * _rate;
  629. if (suiteRoomPrice > 0) if (suiteRoomPrice > hotelSuiteFee * _rate) isAutoAudit = false;
  630. //1.4 判断其他房型费用
  631. decimal otherRoomPrice = (hotelCostInfo.OtherRoomPrice + otherFee) * _rate;
  632. if (otherRoomPrice > 0) if (otherRoomPrice > hotelSuiteRoomFee * _rate) isAutoAudit = false;
  633. }
  634. //2.判断是否自动审核
  635. if (isAutoAudit)
  636. {
  637. return $"未超预算";
  638. }
  639. }
  640. else if (feeType == 2)
  641. {
  642. //1.基础数据参数验证
  643. var priceType = new List<int>() { 1062 };
  644. var opinfos = _sqlSugar.Queryable<Grp_CarTouristGuideGroundReservations>()
  645. .Where(x => x.IsDel == 0 && x.DiId == diId && x.Id == dataId && !priceType.Contains(x.PriceType))
  646. .First();
  647. //var opinfos = _sqlSugar.Queryable<Grp_CarTouristGuideGroundReservations>()
  648. // .Where(x => x.IsDel == 0 && x.DiId == diId && x.Id == dataId )
  649. // .First();
  650. if (opinfos == null) return _view;
  651. //1.含超时费用/超支费用 手动审核
  652. if (opinfos.SelectCheck.Contains("超时") || opinfos.SelectCheck.Contains("超支") || opinfos.SelectCheck.Contains("尾款")) return _view;
  653. //1.参数验证
  654. var opCheckPriceTyeps = opinfos.SelectCheck.Split(',');
  655. var opCheckPriceTyepIds = setData.Where(x => opinfos.SelectCheck.Split(',').Contains(x.Name)).Select(x => x.Id).ToList();
  656. var opContents = _sqlSugar.Queryable<Grp_CarTouristGuideGroundReservationsContent>()
  657. .Where(x => x.IsDel == 0 && x.DiId == diId && x.CTGGRId == dataId && opCheckPriceTyepIds.Contains(x.SId))
  658. .OrderBy(x => x.DatePrice, OrderByType.Asc)
  659. .ToList();
  660. if (opContents.Count < 1) return _view;
  661. //获取C表汇率
  662. decimal _rate = 1.0000M;
  663. var payInfo = _sqlSugar.Queryable<Grp_CreditCardPayment>().Where(x => x.IsDel == 0 && x.DIId == diId && x.CTable == 79 && x.Id == dataId).First();
  664. if (payInfo == null) return _view;
  665. _rate = payInfo.DayRate;
  666. string opCurrencyName = setData.Find(x => x.Id == opContents[0].Currency)?.Name ?? "";
  667. var opBasicDatas = setData.Where(x => x.STid == 17).ToList(); //费用类型基础数据
  668. bool isAutoAudit = true;
  669. if (!DateTime.TryParse(opinfos.ServiceStartTime, out DateTime startDt1) || !DateTime.TryParse(opinfos.ServiceEndTime, out DateTime endDt1)) return _view;
  670. DateTime startDt = startDt1;
  671. DateTime endDt = endDt1;
  672. var opCostDatas = costContents.Where(it => Convert.ToDateTime(it.Date) >= startDt && Convert.ToDateTime(it.Date) <= endDt).ToList();
  673. if (opCostDatas.Count < 1) return _view;
  674. var noAuditFeeTypeIds = new List<int> {
  675. 982 ,//982 车超时费 -- 暂无
  676. 96 ,//96 接送机费 -- 暂无
  677. 97 ,//97 其他费用 -- 暂无
  678. 992 ,//992 住补费用 -- 暂无
  679. 1059,//1059 导游超时费用 -- 暂无
  680. 1070,//1070 尾款金额 -- 暂无
  681. 1071,//1071 其他额外费用 -- 暂无
  682. 1073,//1073 翻译超时费 -- 暂无
  683. 1074,//1074 早餐超支费用 -- 暂无
  684. 1075,//1075 午餐超支费用 -- 暂无
  685. 1076,//1076 晚餐超支费用 -- 暂无
  686. };
  687. //费用类型筛选 包含 feeTypeIds && 包含这些类型费用大于0
  688. var noAuditFeeContents = opContents.Where(x => x.Price > 0 && noAuditFeeTypeIds.Contains(x.SId)).ToList();
  689. if (noAuditFeeContents.Count > 0) return _view;
  690. //2.按天按项 检查费用是否超过预算
  691. var opDayContent = opContents.GroupBy(x => x.DatePrice);
  692. foreach (var item in opDayContent)
  693. {
  694. var opCostInfo = opCostDatas.Where(x => Convert.ToDateTime(x.Date) == item.Key).ToList();
  695. if (opCostInfo.Count < 1) continue;
  696. //车费 91
  697. var opCarCost = item.FirstOrDefault(x => x.SId == 91);
  698. if (opCarCost != null) if (opCarCost.Price * _rate > _rate * opCostInfo.Sum(x => x.CarFee)) isAutoAudit = false;
  699. //982 车超时费 -- 暂无
  700. //92 导游费
  701. var opGuideCost = item.FirstOrDefault(x => x.SId == 92);
  702. if (opGuideCost != null) if (opGuideCost.Price * _rate > _rate * opCostInfo.Sum(x => x.GuideFee)) isAutoAudit = false;
  703. //94 导游景点费
  704. var opGuideScenicCost = item.FirstOrDefault(x => x.SId == 94);
  705. if (opGuideScenicCost != null) if (opGuideScenicCost.Price * _rate > _rate * opCostInfo.Sum(x => x.GuideScenicFee)) isAutoAudit = false;
  706. //95 导游小费
  707. var opGuideTipCost = item.FirstOrDefault(x => x.SId == 95);
  708. if (opGuideTipCost != null) if (opGuideTipCost.Price * _rate > _rate * opCostInfo.Sum(x => x.GuideTipFee)) isAutoAudit = false;
  709. //983 导游餐补
  710. var opGuideMealCost = item.FirstOrDefault(x => x.SId == 983);
  711. if (opGuideMealCost != null) if (opGuideMealCost.Price * _rate > _rate * opCostInfo.Sum(x => x.GuideMealFee)) isAutoAudit = false;
  712. //984 导游房补
  713. var opGuideRoomCost = item.FirstOrDefault(x => x.SId == 984);
  714. if (opGuideRoomCost != null) if (opGuideRoomCost.Price * _rate > _rate * opCostInfo.Sum(x => x.GuideRoomFee)) isAutoAudit = false;
  715. //985 导游交通
  716. var opGuideTrafficCost = item.FirstOrDefault(x => x.SId == 985);
  717. if (opGuideTrafficCost != null) if (opGuideTrafficCost.Price * _rate > _rate * opCostInfo.Sum(x => x.GuideTrafficFee)) isAutoAudit = false;
  718. //96 接送机费 -- 暂无
  719. //97 其他费用 -- 暂无
  720. //979 司机工资
  721. var opDriverCost = item.FirstOrDefault(x => x.SId == 979);
  722. if (opDriverCost != null) if (opDriverCost.Price * _rate > _rate * opCostInfo.Sum(x => x.DriverFee)) isAutoAudit = false;
  723. //980 司机小费
  724. var opDriverTipCost = item.FirstOrDefault(x => x.SId == 980);
  725. if (opDriverTipCost != null) if (opDriverTipCost.Price * _rate > _rate * opCostInfo.Sum(x => x.DriverTipFee)) isAutoAudit = false;
  726. //981 司机餐补
  727. var opDriverMealCost = item.FirstOrDefault(x => x.SId == 981);
  728. if (opDriverMealCost != null) if (opDriverMealCost.Price * _rate > _rate * opCostInfo.Sum(x => x.DriverMealFee)) isAutoAudit = false;
  729. //988 客户早餐费用
  730. var opClientBreakfastCost = item.FirstOrDefault(x => x.SId == 988);
  731. if (opClientBreakfastCost != null) if (opClientBreakfastCost.Price * _rate > _rate * opCostInfo.Sum(x => x.ClientBreakfastFee)) isAutoAudit = false;
  732. //93 客户午餐费用
  733. var opClientLunchCost = item.FirstOrDefault(x => x.SId == 93);
  734. if (opClientLunchCost != null) if (opClientLunchCost.Price * _rate > _rate * opCostInfo.Sum(x => x.ClientLunchFee)) isAutoAudit = false;
  735. //989 客户晚餐费用
  736. var opClientDinnerCost = item.FirstOrDefault(x => x.SId == 989);
  737. if (opClientDinnerCost != null) if (opClientDinnerCost.Price * _rate > _rate * opCostInfo.Sum(x => x.ClientDinnerFee)) isAutoAudit = false;
  738. //990 景点门票费
  739. var opScenicTicketCost = item.FirstOrDefault(x => x.SId == 990);
  740. if (opScenicTicketCost != null) if (opScenicTicketCost.Price * _rate > _rate * opCostInfo.Sum(x => x.ScenicTicketFee)) isAutoAudit = false;
  741. //991 饮料/零食/水果
  742. var opDrinkSnackFruitCost = item.FirstOrDefault(x => x.SId == 991);
  743. if (opDrinkSnackFruitCost != null) if (opDrinkSnackFruitCost.Price * _rate > _rate * opCostInfo.Sum(x => x.DrinkSnackFruitFee)) isAutoAudit = false;
  744. //992 住补费用 -- 暂无
  745. //994 翻译费
  746. var opTranslatorCost = item.FirstOrDefault(x => x.SId == 994);
  747. if (opTranslatorCost != null) if (opTranslatorCost.Price * _rate > _rate * opCostInfo.Sum(x => x.TranslatorFee)) isAutoAudit = false;
  748. //1059 导游超时费用 -- 暂无
  749. //1070 尾款金额 -- 暂无
  750. //1071 其他额外费用 -- 暂无
  751. //1073 翻译超时费 -- 暂无
  752. //1074 早餐超支费用 -- 暂无
  753. //1075 午餐超支费用 -- 暂无
  754. //1076 晚餐超支费用 -- 暂无
  755. }
  756. //更改审核状态
  757. if (isAutoAudit) return _view;
  758. }
  759. else return _view;
  760. return _view;
  761. }
  762. }
  763. }