IFinance_CustomerDeliveryBillRepository.cs 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795
  1. using System;
  2. using System.Collections.Concurrent;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading;
  7. using System.Threading.Tasks;
  8. using Dapper;
  9. using Microsoft.Extensions.Caching.Distributed;
  10. using NPOI.SS.Formula.Functions;
  11. using XYY.Common.Standard;
  12. using XYY.Core.Standard.Data.Infrastructure;
  13. using XYY.Model.Standard;
  14. using XYY.Model.Standard.Enums;
  15. using XYY.Model.Standard.Finance;
  16. using XYY.Model.Standard.Task;
  17. using XYY.Service.Standard.Finance.Charging.Base;
  18. using XYY.TaskTrack.Standard;
  19. namespace XYY.Data.Standard.Finance
  20. {
  21. public interface IFinance_CustomerDeliveryBillRepository : IBaseRepository<Finance_CustomerDeliveryBill>
  22. {
  23. Task<Finance_CustomerDeliveryBill> GetDeliveryBillById(int id);
  24. Task AddDeliveryBill(Finance_CustomerDeliveryBill bill, bool ss);
  25. Task UpdateCustomerDeliveryBillState(int id, BillState billState, bool notran);
  26. Task<IEnumerable<Finance_CustomerDeliveryBill>> AddDeliveryBillBatch(List<Finance_CustomerDeliveryBill> finance_CustomerDeliveryBills);
  27. Task<AddDeliveryBillResult> AddDeliveryBillAsFile(Finance_CustomerDeliveryBill bill, List<Finance_CustomerDeliveryBillDetailInput2> list);
  28. [NonTrans]
  29. Task InputSupplementOrDeduction(int billId, List<Finance_CustomerDeliveryBillDetailInput> details, int type, bool isClear = true);
  30. [NonTrans]
  31. Task InputClaim(int billId, List<Finance_CustomerDeliveryBillClaimInput> details);
  32. [NonTrans]
  33. Task UpdateConfirmed(int billId, List<Finance_CustomerDeliveryBillDetailInput> details);
  34. Task<List<Finance_CustomerDeliveryBillDetail>> GetDetail(int billId, int type, bool? confirmed);
  35. Task<List<Finance_CustomerDeliveryBill>> GetDataAsStatus(FiannceCustomerDeliveryBillParam param);
  36. Task<Dictionary<int, int>> GetGroupCounts();
  37. [NonTrans]
  38. Task Pass(int billId, bool isRealTime, bool fromDirectImport = false);
  39. Task Rereject(int billId);
  40. Task<List<Finance_Logistics_LadingBillLogDto>> GetPaymentLog(int billId);
  41. Task DeleteDetails(int billId);
  42. void BatchAddDetails(int billId, List<Finance_CustomerDeliveryBillDetail> list);
  43. [NonTrans]
  44. Task UpdatetWeightAndFee(List<Finance_CustomerDeliveryBillDetail> list, int taskQty, int batchQty, string guidId, int oriBillId);
  45. Task<PageResult<Finance_CustomerDeliveryBill>> GetRemittancePageResult(QueryModel queryModel);
  46. Task<IEnumerable<WaitCreateBillCustomer>> GetWaitCreateBill(int billType);
  47. Task<CustomerDeliveryPanel> GetCustomerDeliveryPanelAsync();
  48. Task<CustomerDeliveryPanelDetail> GetCustomerDeliveryPanelDetail();
  49. Task<List<CustomerRemittance>> GetRemittance(QueryModel queryModel);
  50. Tuple<decimal, decimal> GetUSDAndEURToCny(DateTime start, DateTime end);
  51. Task<IEnumerable<Finance_ChargesDetail>> GetChargesDetails(int customerId, DateTime start, DateTime end);
  52. Task<IEnumerable<OP_FirstBillInfo>> GetCustomerDeliveryBillByNew(IEnumerable<int> customerIds);
  53. /// <summary>
  54. /// 退件费用
  55. /// </summary>
  56. /// <param name="customerId">客户Id</param>
  57. /// <param name="start">开始日期</param>
  58. /// <param name="end">结束日期</param>
  59. /// <returns></returns>
  60. Task<List<Finance_CustomerDeliveryBillDetail>> Load_Return_Fee(int customerId, DateTime start, DateTime end);
  61. Task<List<Finance_CustomerDeliveryBillDetail>> Get_Repeat_Fee(int billId);
  62. }
  63. public class Finance_CustomerDeliveryBillRepository : BaseRepository<Finance_CustomerDeliveryBill>, IFinance_CustomerDeliveryBillRepository
  64. {
  65. private readonly IDistributedCache _cache;
  66. private readonly IFinance_Customer_AccountRepository _accountRepository;
  67. public Finance_CustomerDeliveryBillRepository(IUnitOfWork unitOfWork, IDistributedCache cache, IFinance_Customer_AccountRepository accountRepository) : base(unitOfWork)
  68. {
  69. _cache = cache;
  70. _accountRepository = accountRepository;
  71. }
  72. public async Task<List<Finance_CustomerDeliveryBillDetail>> Load_Return_Fee(int customerId, DateTime start, DateTime end)
  73. {
  74. string sql = $@"select b.*
  75. from Order_Return(nolock) a join Finance_CustomerDeliveryBillDetail(nolock)b on a.OrderId=b.OrderId
  76. and b.FeeType = 0
  77. join Order_Order(nolock)c on c.id=b.OrderId
  78. join User_Customer(nolock)d on d.id=c.CustomerId
  79. left join Finance_CustomerDeliveryBillDetail(nolock)e on e.OrderId = a.OrderId and e.FeeType = 9
  80. where c.CustomerId= {customerId} and a.createtime between '{start}' and '{end.AddDays(1)}'
  81. and e.Id is null";
  82. return (await _unitOfWork.QueryBySqlAsync<Finance_CustomerDeliveryBillDetail>(sql)).ToList();
  83. }
  84. public async Task<AddDeliveryBillResult> AddDeliveryBillAsFile(Finance_CustomerDeliveryBill bill, List<Finance_CustomerDeliveryBillDetailInput2> list)
  85. {
  86. await _unitOfWork.ExecuteScalarAsync<Finance_CustomerDeliveryBillDetailInput>("delete Finance_CustomerDeliveryBillDetailInput2");
  87. await _unitOfWork.BulkToDBAsync(list);
  88. await _unitOfWork.ExecuteStoredProcedureAsync("createCustomerBillAsFile", new
  89. {
  90. BillName = bill.Name,
  91. CustomerId = bill.CustomerId,
  92. StartTime = bill.StartTime,
  93. EndTime = bill.EndTime,
  94. ServiceBillUrl = bill.ServiceBillUrl
  95. }, 180);
  96. return null;
  97. }
  98. [NonTrans]
  99. public async Task UpdateConfirmed(int billId, List<Finance_CustomerDeliveryBillDetailInput> details)
  100. {
  101. await _unitOfWork.ExecuteScalarAsync<Finance_CustomerDeliveryBillDetailInput>("delete Finance_CustomerDeliveryBillDetailInput where BillId=" + billId);
  102. details.ForEach(x => { x.BillId = billId; x.CreateTime = DateTime.Now; });
  103. await _unitOfWork.BulkToDBAsync(details);
  104. await _unitOfWork.ExecuteStoredProcedureAsync("UpdateCustomerConfirmed", new
  105. {
  106. billId = billId
  107. }, 180);
  108. await _unitOfWork.ExecuteStoredProcedureAsync("UpdateCustomerBill", new { billId = billId }, 180);
  109. }
  110. public async Task<List<Finance_CustomerDeliveryBillDetail>> GetDetail(int billId, int type, bool? confirmed)
  111. {
  112. string sql = @" select * from Finance_CustomerDeliveryBillDetail(nolock) where [FeeType]=" + type + " and billId= " + billId;
  113. if (confirmed.HasValue)
  114. sql += " and confirmed = " + (confirmed.Value ? 1 : 0);
  115. var t = await _unitOfWork.QueryBySqlAsync<Finance_CustomerDeliveryBillDetail>(sql);
  116. return t.ToList();
  117. }
  118. public async Task<List<Finance_CustomerDeliveryBill>> GetDataAsStatus(FiannceCustomerDeliveryBillParam param)
  119. {
  120. StringBuilder sqlBuilder = new StringBuilder();
  121. sqlBuilder.Append($@"select b.BillingCycle,a.* from Finance_CustomerDeliveryBill(nolock)a join User_Customer(nolock)b on a.CustomerId=b.Id where b.Type = 0 and Status=" + param.status + " and StartTime>='2021-10-01'");
  122. if (0 != (int)param.BillingCycle)
  123. sqlBuilder.Append($@" and b.BillingCycle = " + (int)param.BillingCycle + "");
  124. if (0 != param.customerId)
  125. sqlBuilder.Append($@" and b.Id = " + param.customerId + "");
  126. if (param.IsInterceptCustomers.HasValue)
  127. sqlBuilder.Append($@" and b.IsInterceptCustomers = " + (param.IsInterceptCustomers.Value ? 1 : 0));
  128. sqlBuilder.Append(" order by a.CreateTime desc");
  129. var t = await _unitOfWork.QueryBySqlAsync<Finance_CustomerDeliveryBill>(sqlBuilder.ToString());
  130. return t.ToList();
  131. }
  132. public async Task<Dictionary<int, int>> GetGroupCounts()
  133. {
  134. string sql = @"select Status as [Key],count(0) as [Value] from Finance_CustomerDeliveryBill(nolock)a join User_Customer(nolock)b on a.CustomerId=b.Id where b.Type = 0 and StartTime>='2021-10-01' group by Status";
  135. var t = await _unitOfWork.QueryBySqlAsync<dynamic>(sql);
  136. return t.ToDictionary(x => (int)x.Key, x => (int)x.Value);
  137. }
  138. [NonTrans]
  139. public async Task InputSupplementOrDeduction(int billId, List<Finance_CustomerDeliveryBillDetailInput> details, int type, bool isClear = true)
  140. {
  141. if (isClear)
  142. await _unitOfWork.ExecuteScalarAsync<Finance_CustomerDeliveryBillDetailInput>("delete Finance_CustomerDeliveryBillDetailInput where BillId=" + billId);
  143. details.ForEach(x => { x.BillId = billId; x.CreateTime = DateTime.Now; });
  144. if (details.Count > 0)
  145. await _unitOfWork.BulkToDBAsync(details);
  146. await _unitOfWork.ExecuteStoredProcedureAsync("InputCustomerSupplementOrDeduction", new
  147. {
  148. billId = billId,
  149. type = type
  150. });
  151. await _unitOfWork.ExecuteStoredProcedureAsync("updateCustomerBill", new { billId = billId });
  152. }
  153. [NonTrans]
  154. public async Task InputClaim(int billId, List<Finance_CustomerDeliveryBillClaimInput> details)
  155. {
  156. await _unitOfWork.ExecuteScalarAsync<Finance_CustomerDeliveryBillClaimInput>("delete Finance_CustomerDeliveryBillClaimInput where BillId=" + billId);
  157. details.ForEach(x => { x.BillId = billId; x.CreateTime = DateTime.Now; });
  158. await _unitOfWork.BulkToDBAsync(details);
  159. await _unitOfWork.ExecuteStoredProcedureAsync("InputCustomerClaim", new
  160. {
  161. billId = billId
  162. });
  163. await _unitOfWork.ExecuteStoredProcedureAsync("updateCustomerBill", new { billId = billId });
  164. }
  165. public async Task<CustomerDeliveryPanel> GetCustomerDeliveryPanelAsync()
  166. {
  167. string sql =
  168. @"
  169. --当天未核对帐单
  170. select * from (
  171. select count(0) as TodayNotPassQty from Finance_CustomerDeliveryBill(nolock)
  172. where Status=0 and CreateTime
  173. between convert(nvarchar(10), GETDATE(),120) and convert(nvarchar(10),DATEADD( DAY,1,getdate()),120))t1
  174. left join
  175. --总计未核对帐单
  176. (select count(0) as NotPassQty from Finance_CustomerDeliveryBill(nolock)
  177. where Status=0 and StartTime>='2022-01-01')t2 on 1=1
  178. left join
  179. --当前欠款帐单总额
  180. (select count(0)ArrearsQty,SUM(Finance_CustomerDeliveryBill.Receivables-Payment) ArrearsTotal
  181. from Finance_CustomerDeliveryBill(nolock)
  182. where Status=3 and StartTime>='2022-01-01')t3 on 1=1
  183. left join
  184. --当前逾期欠款帐单
  185. (select count(0)OverdueQty,SUM(Finance_CustomerDeliveryBill.Receivables-Payment) OverdueTotal,AVG(CurrentOverdueDays) CurrentOverdueDay
  186. from Finance_CustomerDeliveryBill(nolock)
  187. where Status=3 and StartTime>='2022-01-01' and CurrentOverdueDays>0)t5 on 1=1
  188. left join(
  189. --当前收款完成帐单总额
  190. select count(0)PaymentQty,SUM(Payment) PaymentTotalc
  191. from Finance_CustomerDeliveryBill(nolock)
  192. where (Status=5 or Status=4) and StartTime>='2022-01-01')t6 on 1=1
  193. ";
  194. return await _unitOfWork.Connection.QuerySingleAsync<CustomerDeliveryPanel>(sql, null, _unitOfWork.Transaction);
  195. }
  196. public async Task AddDeliveryBill(Finance_CustomerDeliveryBill bill, bool ss)
  197. {
  198. int billId = bill.Id;
  199. if (billId <= 0)
  200. {
  201. billId = (int)(await _unitOfWork.InsertAsync(bill));
  202. bill.Id = billId;
  203. }
  204. if (ss)
  205. await _unitOfWork.ExecuteStoredProcedureAsync("createCustomerBillAsCharges", new { billId = billId }, 120);
  206. else
  207. await _unitOfWork.ExecuteStoredProcedureAsync("createCustomerBill", new { billId = billId }, 120);
  208. await _unitOfWork.ExecuteStoredProcedureAsync("updateCustomerBill", new { billId = billId }, 120);
  209. }
  210. [NonTrans]
  211. public async Task Pass(int billId, bool isRealTime = false, bool fromDirectImport = false)
  212. {
  213. var model = await GetAsync(billId);
  214. if (model.Status == FiannceServiceBillStatus.结算中)
  215. throw new Exception("帐单已完结,无须再审核");
  216. model.Status = (FiannceServiceBillStatus)(model.Status.GetValue() + 1);
  217. if (model.Status == FiannceServiceBillStatus.财务确认)
  218. {
  219. if (fromDirectImport)
  220. {
  221. model.Status = FiannceServiceBillStatus.结算中;
  222. }
  223. else
  224. {
  225. model.Status = FiannceServiceBillStatus.最终确认;
  226. }
  227. }
  228. if (model.Status == FiannceServiceBillStatus.结算中)
  229. {
  230. //最终确认通过时,更新应付款金额
  231. await _unitOfWork.ExecuteStoredProcedureAsync("passCustomerConfirmed", new { billId = billId }, 120);
  232. var response = await _unitOfWork.Connection.ExecuteAsync(" exec UpdateCustomerBill @billid=" + billId, null, _unitOfWork.Transaction, 180);
  233. model = await GetAsync(billId);
  234. model.Status = FiannceServiceBillStatus.结算中;
  235. model.Receivables =
  236. model.ConfirmedFreigh + model.Supplement - Math.Abs(model.Deduction) - Math.Abs(model.ClaimAmount.HasValue ? model.ClaimAmount.Value : 0);
  237. model.CustomerRevenue = Math.Abs(model.Deduction) + Math.Abs(model.ClaimAmount.HasValue ? model.ClaimAmount.Value : 0);
  238. model.CustomerExpenditure = model.ConfirmedFreigh + model.Supplement;
  239. //收入还款
  240. if (model.CustomerRevenue > 0)
  241. {
  242. //查找当前客户有欠款的帐单
  243. var bills = await _unitOfWork.QueryBySqlAsync<Finance_CustomerDeliveryBill>(
  244. "select * from Finance_CustomerDeliveryBill(nolock) where CustomerId=@CustomerId and Status = @Status", null, new
  245. {
  246. CustomerId = model.CustomerId,
  247. Status = FiannceServiceBillStatus.结算中
  248. });
  249. foreach (var item in bills)
  250. {
  251. if (item.AmountToBeRepaid < model.CustomerRevenue)
  252. {
  253. item.Status = FiannceServiceBillStatus.已还清;
  254. item.AmountToBeRepaid = 0;
  255. item.Repayment = item.Arrears;
  256. }
  257. else
  258. {
  259. item.AmountToBeRepaid -= model.CustomerRevenue;
  260. item.Repayment += model.CustomerRevenue;
  261. }
  262. await _unitOfWork.UpdateAsync(item);
  263. }
  264. }
  265. var account = (await _unitOfWork.QueryAsync<Finance_Customer_Account>(x => x.CustomerId == model.CustomerId)).FirstOrDefault();
  266. if (account == null)
  267. {
  268. //为客户创建帐户
  269. account = new Finance_Customer_Account() { CustomerId = model.CustomerId };
  270. account.Id = (int)await _unitOfWork.InsertAsync<Finance_Customer_Account>(account);
  271. }
  272. //查找上期帐单
  273. var lastBill = (await QueryAsync(x => x.EndTime < model.StartTime && x.CustomerId == model.CustomerId)).OrderByDescending(x => x.EndTime)
  274. .FirstOrDefault();
  275. if (lastBill == null)
  276. lastBill = new Finance_CustomerDeliveryBill();
  277. //上期余额
  278. model.BalanceOfPreviousPeriod = lastBill.ClosingBalance; //帐期内付款金额
  279. decimal? CurrentPeriod =
  280. _unitOfWork.Connection.QuerySingle<decimal?>("select sum(PaymentCNY) from Finance_Customer_Remittance(nolock) " +
  281. "where CustomerId=@CustomerId and convert(nvarchar(10),PassDate,120) between @StartTime and @EndTime",
  282. new { CustomerId = model.CustomerId, StartTime = model.StartTime, EndTime = model.EndTime }, _unitOfWork.Transaction);
  283. model.CurrentPeriod = CurrentPeriod ?? 0;
  284. //期末余额等于帐户余额减去本期应收
  285. if (!isRealTime)
  286. model.ClosingBalance = account.Balance - model.Receivables;
  287. else
  288. model.ClosingBalance
  289. = model.BalanceOfPreviousPeriod + model.CurrentPeriod + model.CustomerRevenue - model.CustomerExpenditure;
  290. //期末余额大于0的设置待还款金额
  291. if (model.ClosingBalance < 0)
  292. {
  293. model.AmountToBeRepaid = Math.Abs(model.ClosingBalance);
  294. model.Arrears = Math.Abs(model.ClosingBalance);
  295. }
  296. if (account.RepaymentTermDay == 0)
  297. throw new Exception("未找到当前客户的付款限制天数设置");
  298. else
  299. model.LastRepaymentDate = model.EndTime.AddDays(account.RepaymentTermDay);
  300. if (!isRealTime)
  301. {
  302. //更新帐户余额
  303. account.Balance = account.Balance - model.Receivables;
  304. if (account.Balance > 0)
  305. {
  306. //帐户还有余额的话更新为无欠款
  307. model.Status = FiannceServiceBillStatus.无欠款;
  308. }
  309. else
  310. {
  311. model.Status = FiannceServiceBillStatus.结算中;
  312. }
  313. //int[] testCustomerIds = new int[] { 146, 221, 250, 362, 227 };
  314. int[] testCustomerIds = new int[] { };
  315. if (testCustomerIds.Contains(account.CustomerId))
  316. {
  317. //非实时计算帐单,在核帐后,判断是否有超额
  318. if (account.Quota + account.BaseQuota + account.Balance < 0)
  319. {
  320. account.Arrears = true;
  321. //超额时发送消息给李素
  322. var customer = (await _unitOfWork.QueryAsync<User_Customer>(x => x.Id == account.CustomerId)).FirstOrDefault();
  323. if (customer != null)
  324. {
  325. RestSharp.RestClient client = new RestSharp.RestClient("http://120.24.149.148:9505");
  326. RestSharp.RestRequest request = new RestSharp.RestRequest("/WarningNotice/NoticeCard", RestSharp.Method.POST);
  327. string noticeText = $"# 欠费通知,客户**{(string.IsNullOrEmpty(customer.Abbreviation) ? customer.CompanyName : customer.Abbreviation)}** 客户编码**{customer.CustomerNumber}**" +
  328. $" \n 当前余额:**{account.Balance.ToString("0.00")}** \n 基础授信额度:**{account.BaseQuota.ToString("0.00")}** \n 临时授信额度:**{account.Quota.ToString("0.00")}** \n 可用余额:**{(account.Quota + account.BaseQuota + account.Balance).ToString("0.00")}** \n 已产生**欠费**,仓库**停止收件**。 \n 请及时回款,或在 **钉钉OA审批** **财务** **额度调整** 中申请临时额度 避免**发货延误**。";
  329. var body = new
  330. {
  331. ServiceType = "钉钉",
  332. ButtonOrient = "0",
  333. Text = noticeText,
  334. Title = $"客户{(string.IsNullOrEmpty(customer.Abbreviation) ? customer.CompanyName : customer.Abbreviation)}欠费",
  335. ToAllUser = false,
  336. UserIds = new List<int>
  337. {
  338. 200,
  339. 1
  340. },
  341. Buttons = new List<dynamic>
  342. {
  343. new
  344. {
  345. Text = "已知悉",
  346. Link = "http://wms.xingyunyi.cn"
  347. }
  348. }
  349. };
  350. request.AddJsonBody(body);
  351. var restResponse = client.Execute(request);
  352. if (restResponse.StatusCode == System.Net.HttpStatusCode.OK)
  353. {
  354. NotailResult notailResult = null;
  355. try
  356. {
  357. notailResult = Newtonsoft.Json.JsonConvert.DeserializeObject<NotailResult>(restResponse.Content);
  358. }
  359. catch (Exception ex)
  360. {
  361. throw new Exception("钉钉推送信息反解析失败,请联系立航" + ex.Message);
  362. }
  363. if (!notailResult.IsSuccess)
  364. {
  365. throw new Exception("钉钉推送信息api失败,请联系立航" + notailResult.ErrMsg);
  366. }
  367. }
  368. else
  369. {
  370. throw new Exception("钉钉推送信息http失败,请联系立航" + restResponse.Content);
  371. }
  372. }
  373. }
  374. }
  375. await _unitOfWork.UpdateAsync(account);
  376. }
  377. else
  378. {
  379. if (model.ClosingBalance > 0)
  380. model.Status = FiannceServiceBillStatus.无欠款;
  381. }
  382. }
  383. else
  384. {
  385. var response = await _unitOfWork.Connection.ExecuteAsync(" exec UpdateCustomerBill @billid=" + billId, null, _unitOfWork.Transaction, 180);
  386. }
  387. await _unitOfWork.UpdateAsync(model);
  388. }
  389. public class NotailResult
  390. {
  391. public bool IsSuccess
  392. {
  393. get; set;
  394. }
  395. public string ErrMsg
  396. {
  397. get; set;
  398. }
  399. }
  400. public async Task Rereject(int billId)
  401. {
  402. var model = await GetAsync(billId);
  403. if (model.Status == FiannceServiceBillStatus.待对帐)
  404. throw new Exception("帐单刚开始对帐,无法驳回");
  405. if (model.Status == FiannceServiceBillStatus.最终确认)
  406. model.Status = FiannceServiceBillStatus.财务确认;
  407. model.Status = (FiannceServiceBillStatus)(model.Status.GetValue() - 1);
  408. await _unitOfWork.UpdateAsync(model);
  409. }
  410. public async Task<List<Finance_Logistics_LadingBillLogDto>> GetPaymentLog(int billId)
  411. {
  412. var list = (await _unitOfWork.QueryAsync<Finance_CustomerDeliveryBillLog>(x => x.Id == billId)).ToList();
  413. List<Finance_Logistics_LadingBillLogDto> dtos = new List<Finance_Logistics_LadingBillLogDto>();
  414. foreach (var item in list)
  415. {
  416. dtos.Add(new Finance_Logistics_LadingBillLogDto
  417. {
  418. OldPayment = item.OldValue,
  419. NewPayment = item.NewValue,
  420. Payment = (decimal.Parse(item.NewValue) - decimal.Parse(item.OldValue)).ToString(),
  421. CreateTime = item.CreateTime.Value
  422. });
  423. }
  424. return dtos;
  425. }
  426. public async Task DeleteDetails(int billId)
  427. {
  428. await _unitOfWork.ExecuteScalarAsync<object>($"delete Finance_CustomerDeliveryBillDetail where billId={billId}");
  429. }
  430. /// <summary>
  431. /// 批量更新数据
  432. /// </summary>
  433. /// <param name="list">导入重量列表</param>
  434. /// <param name="taskQty">并发数</param>
  435. /// <param name="batchQty">并发每次执行记录数</param>
  436. /// <param name="guidId">任务的GUID,方便对象跟踪</param>
  437. /// <returns></returns>
  438. [NonTrans]
  439. public async Task UpdatetWeightAndFee(List<Finance_CustomerDeliveryBillDetail> list, int taskQty, int batchQty, string guidId, int oriBillId)
  440. {
  441. if (this._unitOfWork.Connection.State == System.Data.ConnectionState.Closed)
  442. this._unitOfWork.Connection.Open();
  443. try
  444. {
  445. await _unitOfWork.ExecuteAsync($"delete Finance_CustomerDeliveryBillDetailInput where BillId={oriBillId}");
  446. list = list.Where(x => x.Weight != x.SysWeight).ToList();
  447. var inputs = list.Select(x => new Finance_CustomerDeliveryBillDetailInput
  448. {
  449. BillId = oriBillId,
  450. Weight = x.Weight,
  451. CreateTime = DateTime.Now,
  452. TrackingNumber = x.TrackingNumber,
  453. Remark = x.Remark
  454. }
  455. ).ToList();
  456. await _unitOfWork.BulkToDBAsync(inputs);
  457. TaskTrackModel taskTrackModel = new TaskTrackModel();
  458. taskTrackModel.Summary = list.Count;
  459. taskTrackModel.WaitQty = list.Count;
  460. taskTrackModel.Name = guidId;
  461. taskTrackModel.StartTime = DateTime.Now;
  462. taskTrackModel.EndTime = DateTime.Now;
  463. int taskId = (int)(await _unitOfWork.InsertAsync(taskTrackModel));
  464. ConcurrentBag<List<Finance_CustomerDeliveryBillDetail>> waitList = new ConcurrentBag<List<Finance_CustomerDeliveryBillDetail>>(); ///取大概有多少个任务
  465. int batchCounts = (int)Math.Ceiling(list.Count / (decimal)batchQty);
  466. for (int i = 0; i < batchCounts; i++)
  467. {
  468. waitList.Add(list.Skip(i * batchQty).Take(batchQty).ToList());
  469. }
  470. List<Task> taskList = new List<Task>();
  471. int q = 0;
  472. //生成队列任务
  473. for (var i = 0; i < taskQty; i++)
  474. {
  475. taskList.Add(Task.Run(async () =>
  476. {
  477. while (waitList.TryTake(out var data))
  478. {
  479. await _unitOfWork.ExecuteStoredProcedureAsync("UpdateCustomerConfirmedAsWeight", new
  480. {
  481. billId = oriBillId,
  482. index = q,
  483. size = batchQty
  484. }, 3600);
  485. q++;
  486. //排他锁Update 数据库
  487. await _unitOfWork.ExecuteAsync($"update taskTrackModel set SuccessQty += {batchQty} ,WaitQty -= {batchQty} where id = {taskId}");
  488. }
  489. }));
  490. }
  491. Task.WaitAll(taskList.ToArray());
  492. await _unitOfWork.ExecuteAsync($"update Finance_CustomerDeliveryBillDetail set Confirmed =1 ,Amount= SysAmount,Weight=SysWeight where BillId={oriBillId} and Weight =0 ");
  493. await _unitOfWork.ExecuteStoredProcedureAsync("UpdateCustomerBill", new { billId = oriBillId }, 3600);
  494. }
  495. catch (Exception ex)
  496. {
  497. throw ex;
  498. }
  499. finally
  500. {
  501. if (this._unitOfWork.Connection.State == System.Data.ConnectionState.Open)
  502. this._unitOfWork.Connection.Close();
  503. }
  504. }
  505. public void BatchAddDetails(int billId, List<Finance_CustomerDeliveryBillDetail> list)
  506. {
  507. _unitOfWork.InsertBatch<Finance_CustomerDeliveryBillDetail>(list);
  508. }
  509. public async Task<Finance_CustomerDeliveryBill> GetDeliveryBillById(int id)
  510. {
  511. var result = await _unitOfWork.QueryAsync<Finance_CustomerDeliveryBill>(i => i.Id == id);
  512. return result.FirstOrDefault();
  513. }
  514. public async Task<PageResult<Finance_CustomerDeliveryBill>> GetRemittancePageResult(QueryModel queryModel)
  515. {
  516. return await _unitOfWork.GetPagingListAsync<Finance_CustomerDeliveryBill>(queryModel);
  517. }
  518. public async Task<IEnumerable<WaitCreateBillCustomer>> GetWaitCreateBill(int billType)
  519. {
  520. DateTime endTime = DateTime.Now;
  521. DateTime endDay = new DateTime(endTime.Year, endTime.Month, endTime.Day);
  522. int year = endDay.Year;
  523. int month = endDay.Month;
  524. int day = endDay.Day;
  525. DateTime startTime = endTime;
  526. if (billType == 2)
  527. {
  528. //日结
  529. startTime = endDay.AddDays(-1);
  530. }
  531. else if (billType == 3)
  532. {
  533. //周结
  534. startTime = endDay.AddDays(-7);
  535. }
  536. else if (billType == 4)
  537. {
  538. //半月结
  539. //如果是1号的话,出16号至月尾
  540. if (endDay.Day == 1)
  541. {
  542. if (endDay.Month == 1)
  543. {
  544. //1月份出12月份的并且年份减1
  545. year--;
  546. month = 12;
  547. }
  548. else
  549. {
  550. month--;
  551. }
  552. day = 16;
  553. startTime = new DateTime(year, month, day);
  554. }
  555. else if (endDay.Day == 16)
  556. {
  557. //16号的话,我们出1-15号的帐单
  558. startTime = new DateTime(year, month, 1);
  559. }
  560. //startTime = endDay.AddDays(-15);
  561. }
  562. else if (billType == 5)
  563. {
  564. //月结算上个月帐单
  565. startTime = endDay.AddMonths(-1);
  566. }
  567. //endDay = endDay.AddDays(-1);
  568. /*有帐单数据的*/
  569. string sql = $@"select isnull( a.Abbreviation,a.CompanyName) as CustomerName, a.Id as CustomerId,'{startTime.ToString_yyyyMMdd()}' [start],'{endDay.AddDays(-1).ToString_yyyyMMdd()}' [end] from User_Customer(nolock)a
  570. join
  571. Order_Order(nolock)b on a.id=b.CustomerId
  572. where b.ReceiveTime between @start and @end
  573. and BillingCycle = @BillingCycle
  574. group by a.Id,a.CompanyName,a.Abbreviation
  575. union
  576. select isnull( a.Abbreviation,a.CompanyName) as CustomerName, a.Id as CustomerId,'{startTime.ToString_yyyyMMdd()}' [start],'{endDay.AddDays(-1).ToString_yyyyMMdd()}' [end] from User_Customer(nolock)a
  577. join Finance_Customer_Supplement(nolock)b on a.Id = b.CustomerId
  578. where b.createtime between @start and @end
  579. and BillingCycle = @BillingCycle
  580. group by a.Id,a.CompanyName,a.Abbreviation
  581. union
  582. select isnull( d.Abbreviation,d.CompanyName) as CustomerName, d.Id as CustomerId,'{startTime.ToString_yyyyMMdd()}' [start],'{endDay.AddDays(-1).ToString_yyyyMMdd()}' [end]
  583. from Order_Return(nolock) a join Finance_CustomerDeliveryBillDetail(nolock)b on a.OrderId=b.OrderId
  584. and b.FeeType = 0
  585. join Order_Order(nolock)c on c.id=b.OrderId
  586. join User_Customer(nolock)d on d.id=c.CustomerId
  587. left join Finance_CustomerDeliveryBillDetail(nolock)e on e.OrderId = a.OrderId and e.FeeType = 9
  588. where a.createtime between @start and @end and BillingCycle = @BillingCycle
  589. and e.Id is null
  590. group by d.Id,d.CompanyName,d.Abbreviation
  591. union
  592. select isnull( a.Abbreviation,a.CompanyName) as CustomerName, a.Id as CustomerId,'{startTime.ToString_yyyyMMdd()}' [start],'{endDay.AddDays(-1).ToString_yyyyMMdd()}' [end] from User_Customer(nolock)a
  593. join
  594. Logistics_ClaimRecord(nolock)l on a.id=l.CustomerId
  595. where l.CreateTime between @start and @end
  596. and isnull(l.Solution,0) !=0 and l.ClaimStatus=0 and BillingCycle = @BillingCycle
  597. group by a.Id,a.CompanyName,a.Abbreviation
  598. ";
  599. return await _unitOfWork.QueryBySqlAsync<WaitCreateBillCustomer>(sql, null, new { BillingCycle = billType, start = startTime, end = endDay });
  600. }
  601. public async Task<CustomerDeliveryPanelDetail> GetCustomerDeliveryPanelDetail()
  602. {
  603. string sql = @"
  604. select b.Abbreviation as CustomerName, convert(nvarchar(10), a.CreateTime,120) as AccountingPeriod,
  605. case when convert(nvarchar(10), a.CreateTime,120) = convert(nvarchar(10),getdate(),120) then 1 else 0 end as Hot,
  606. a.SysFreigh as Total
  607. from Finance_CustomerDeliveryBill(nolock)a join User_Customer(nolock)b on a.CustomerId=b.Id
  608. where Status=0 and
  609. StartTime>='2022-01-01'
  610. order by a.CreateTime desc
  611. select a.CustomerId,b.Abbreviation as CustomerName, convert(nvarchar(10), min( a.EndTime),120) as AccountingPeriod,
  612. sum(a.Receivables - a.Payment ) as Total
  613. from Finance_CustomerDeliveryBill(nolock)a join User_Customer(nolock)b on a.CustomerId=b.Id
  614. where Status=3 and StartTime>='2022-01-01'
  615. group by b.Abbreviation,a.CustomerId
  616. order by sum(a.Receivables - a.Payment ) desc
  617. select a.CustomerId,b.Abbreviation as CustomerName, convert(nvarchar(10), min( a.EndTime),120) as AccountingPeriod,
  618. sum(a.Receivables - a.Payment ) as Total
  619. from Finance_CustomerDeliveryBill(nolock)a join User_Customer(nolock)b on a.CustomerId=b.Id
  620. where Status=3 and StartTime>='2022-01-01'
  621. and CurrentOverdueDays>0
  622. group by b.Abbreviation,a.CustomerId
  623. order by sum(a.Receivables - a.Payment ) desc
  624. select a.CustomerId,b.Abbreviation as CustomerName, convert(nvarchar(10), max( a.EndTime),120) as AccountingPeriod,
  625. sum(a.Payment ) as Total
  626. from Finance_CustomerDeliveryBill(nolock)a join User_Customer(nolock)b on a.CustomerId=b.Id
  627. where Status=5 and StartTime>='2022-01-01'
  628. and CurrentOverdueDays>0
  629. group by b.Abbreviation,a.CustomerId
  630. order by sum(a.Receivables - a.Payment ) desc
  631. ";
  632. var dr = await _unitOfWork.Connection.QueryMultipleAsync(sql);
  633. CustomerDeliveryPanelDetail detail = new CustomerDeliveryPanelDetail
  634. {
  635. NotPass = await dr.ReadAsync<CustomerDeliveryPanelDetailItem>(),
  636. Arrears = await dr.ReadAsync<CustomerDeliveryPanelDetailItem>(),
  637. Overdue = await dr.ReadAsync<CustomerDeliveryPanelDetailItem>(),
  638. Payment = await dr.ReadAsync<CustomerDeliveryPanelDetailItem>()
  639. };
  640. return detail;
  641. }
  642. public async Task<List<CustomerRemittance>> GetRemittance(QueryModel queryModel)
  643. {
  644. return (await _unitOfWork.QueryBySqlAsync<CustomerRemittance>(
  645. "select a.*,b.Abbreviation from Finance_CustomerDeliveryBill(nolock)a join user_customer(nolock)b on a.CustomerId=b.Id where 1=1 " + GetWhere(queryModel.QueryParamer))).ToList();
  646. }
  647. public Tuple<decimal, decimal> GetUSDAndEURToCny(DateTime start, DateTime end)
  648. {
  649. //USD
  650. string sql = "select ToCNY from Finance_CustomerRate(nolock) where @start between startDate and endDate and @end between startDate and endDate and Currency='USD'";
  651. var usd = _unitOfWork.Connection.QuerySingle<decimal>(sql, new { start = start, end = start });
  652. sql = "select ToCNY from Finance_CustomerRate(nolock) where @start between startDate and endDate and @end between startDate and endDate and Currency='EUR'";
  653. var eur = _unitOfWork.Connection.QuerySingle<decimal>(sql, new { start = start, end = start });
  654. return new Tuple<decimal, decimal>(usd, eur);
  655. }
  656. public async Task<IEnumerable<Finance_ChargesDetail>> GetChargesDetails(int customerId, DateTime start, DateTime end)
  657. {
  658. string sql = "select * from Finance_ChargesDetail(nolock) where CustomerId=@customerId and AccountingDate>=@start and AccountingDate<@end and Offset=0 ";//时间全用大于等于、小于
  659. return await _unitOfWork.QueryBySqlAsync<Finance_ChargesDetail>(sql, null, new { customerId = customerId, start = start, end = end });
  660. }
  661. public async Task<IEnumerable<OP_FirstBillInfo>> GetCustomerDeliveryBillByNew(IEnumerable<int> customerIds)
  662. {
  663. string sql = @"select a.CompanyName,b.*,c.Balance,c.RepaymentTermDay,c.CustomerId CustomerInfoId from User_Customer a
  664. left join Finance_Customer_Account c on c.CustomerId=a.Id
  665. outer apply (select top 1 * from Finance_CustomerDeliveryBill where CustomerId=a.Id order by id desc) b
  666. where a.Id in @Ids";
  667. return await _unitOfWork.QueryBySqlAsync<OP_FirstBillInfo>(sql, null, new { Ids = customerIds });
  668. }
  669. public async Task<List<Finance_CustomerDeliveryBillDetail>> Get_Repeat_Fee(int billId)
  670. {
  671. string sql = @"select OrderId from Finance_CustomerDeliveryBillDetail where OrderId in (
  672. select OrderId from Finance_CustomerDeliveryBillDetail(nolock)
  673. where BillId = @billId and FeeType=0)
  674. and BillId <>@billId and FeeType=0";
  675. return (await _unitOfWork.QueryBySqlAsync<Finance_CustomerDeliveryBillDetail>(sql, null, new { billId = billId })).ToList();
  676. }
  677. public async Task<IEnumerable<Finance_CustomerDeliveryBill>> AddDeliveryBillBatch(List<Finance_CustomerDeliveryBill> finance_CustomerDeliveryBills)
  678. {
  679. _unitOfWork.InsertBatch(finance_CustomerDeliveryBills);
  680. var sql = @$"select * from Finance_CustomerDeliveryBill where BillTmpId = @BillTmpId";
  681. var dbFinance_CustomerDeliveryBills = await _unitOfWork.QueryBySqlAsync<Finance_CustomerDeliveryBill>(sql, null, new { BillTmpId = finance_CustomerDeliveryBills.FirstOrDefault()?.BillTmpId });
  682. return dbFinance_CustomerDeliveryBills;
  683. }
  684. /// <summary>
  685. /// 更新账单状态
  686. /// </summary>
  687. /// <param name="id"></param>
  688. /// <param name="billState"></param>
  689. /// <returns></returns>
  690. /// <exception cref="NotImplementedException"></exception>
  691. public async Task UpdateCustomerDeliveryBillState(int id, BillState billState, bool notran)
  692. {
  693. if (notran)
  694. await _unitOfWork.UpdateByConditionNoTransferAsync<Finance_CustomerDeliveryBill, bool>(x => x.Id == id, new { BillState = (int)billState });
  695. else
  696. await _unitOfWork.UpdateByConditionAsync<Finance_CustomerDeliveryBill, bool>(x => x.Id == id, new { BillState = (int)billState });
  697. }
  698. }
  699. }