FeeAuditRepository.cs 42 KB

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