using BBWY.Client.APIServices; using BBWY.Client.Extensions; using BBWY.Client.Models; using BBWY.Common.Models; using GalaSoft.MvvmLight.Command; using Microsoft.Win32; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Data; using System.IO; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Input; using BBWY.Common.Extensions; using BBWY.Client.Views.FinancialTerminal; using Newtonsoft.Json; namespace BBWY.Client.ViewModels { public class ProcurementAuditViewModel : BaseVM, IDenpendency { private GlobalContext globalContext; private AuditFile selectAuditFile; private bool isLoading; private bool isAudited; private bool isShowPayBillPanel; private bool onlyException; private PurchaseOrderService purchaseOrderService; private FinancialTerminalService financialTerminalService; private DateTime startDate; private DateTime endDate; private Shop selectResultShop; private bool noMatchPurchaseOrder; private bool noChooseFundType; private string searchResultPurchaseOrder; private Platform? selectPurchasePlatform; public DateTime StartDate { get => startDate; set { Set(ref startDate, value); } } public DateTime EndDate { get => endDate; set { Set(ref endDate, value); } } public IList AuditFileList { get; set; } public IList AuditPayBillList { get; set; } public IList DepartmentList { get; set; } public IList ShopList { get; set; } public IList ShowAuditPayBillList { get; set; } public AuditFile SelectAuditFile { get => selectAuditFile; set { if (Set(ref selectAuditFile, value)) SearchLocal(); } } public bool IsLoading { get => isLoading; set { Set(ref isLoading, value); } } public bool IsAudited { get => isAudited; set { Set(ref isAudited, value); } } public bool IsShowPayBillPanel { get => isShowPayBillPanel; set { Set(ref isShowPayBillPanel, value); } } public bool OnlyException { get => onlyException; set { Set(ref onlyException, value); } } public ICommand AuditCommand { get; set; } public ICommand ClearAuditCommand { get; set; } public ICommand ImportAliPayBillCommand { get; set; } public ICommand Import1688PurchaseOrderCommand { get; set; } public ICommand ImportJDShopOrderCommand { get; set; } public ICommand SearchHistoryCommand { get; set; } public ICommand SearchLocalCommand { get; set; } public ICommand ClearLocalConditionCommand { get; set; } public ICommand SaveCommand { get; set; } public ICommand ExportCommand { get; set; } public ICommand ShowAuditCapitalTypeInputModeCommand { get; set; } public ICommand HideAuditCapitalTypeInputModeCommand { get; set; } public Shop SelectResultShop { get => selectResultShop; set { Set(ref selectResultShop, value); } } public bool NoMatchPurchaseOrder { get => noMatchPurchaseOrder; set { Set(ref noMatchPurchaseOrder, value); } } public bool NoChooseFundType { get => noChooseFundType; set { Set(ref noChooseFundType, value); } } public string SearchResultPurchaseOrder { get => searchResultPurchaseOrder; set { Set(ref searchResultPurchaseOrder, value); } } public Platform? SelectPurchasePlatform { get => selectPurchasePlatform; set { Set(ref selectPurchasePlatform, value); } } public ProcurementAuditViewModel(PurchaseOrderService purchaseOrderService, FinancialTerminalService financialTerminalService, GlobalContext globalContext) { this.globalContext = globalContext; AuditFileList = new ObservableCollection(); AuditCommand = new RelayCommand(Audit); ClearAuditCommand = new RelayCommand(ClearAudit); ImportAliPayBillCommand = new RelayCommand(ImportAliPayBill); SearchHistoryCommand = new RelayCommand(SearchHistory); SearchLocalCommand = new RelayCommand(SearchLocal); ClearLocalConditionCommand = new RelayCommand(() => ClearLocalCondition()); SaveCommand = new RelayCommand(Save); ExportCommand = new RelayCommand(Export); ShowAuditCapitalTypeInputModeCommand = new RelayCommand(ShowAuditCapitalTypeInputMode); HideAuditCapitalTypeInputModeCommand = new RelayCommand(HideAuditCapitalTypeInputMode); this.purchaseOrderService = purchaseOrderService; this.financialTerminalService = financialTerminalService; DepartmentList = new ObservableCollection(); ShopList = new ObservableCollection(); AuditFileList = new ObservableCollection(); AuditPayBillList = new List(); ShowAuditPayBillList = new ObservableCollection(); LoadDepartment(); StartDate = DateTime.Now.Date; EndDate = DateTime.Now.Date; } private void OnDeparmentSelectionChanged() { ShopList.Clear(); foreach (var d in DepartmentList) { if (!d.IsSelected) continue; foreach (var s in d.ShopList) { s.IsSelected = false; ShopList.Add(s); } } } private void LoadDepartment() { var dlist = JsonConvert.DeserializeObject>(JsonConvert.SerializeObject(globalContext.User.DepartmentList)); foreach (var d in dlist) { d.IsSelected = false; DepartmentList.Add(d); d.OnIsSelectedChanged = OnDeparmentSelectionChanged; } ShopList.Clear(); } private void SearchHistory() { if (IsLoading) return; ClearAudit(); IsLoading = true; var importShopIds = string.Join(',', ShopList.Where(s => s.IsSelected).Select(s => s.ShopId)); Task.Factory.StartNew(() => financialTerminalService.GetAuditPayBillList(importShopIds, StartDate, EndDate)).ContinueWith(t => { IsLoading = false; var response = t.Result; if (!response.Success) { MessageBox.Show(response.Msg, "查询账单"); return; } var list = response.Data.Map>(); App.Current.Dispatcher.Invoke(() => { foreach (var b in list) { b.Init(ShopList); AuditPayBillList.Add(b); } SearchLocal(); }); }); } private void Audit() { if (IsLoading) return; if (AuditPayBillList.Count() == 0 || !ShopList.Any(s => s.IsSelected)) { MessageBox.Show("审核数据不全", "提示"); return; } var waitList = new List() { new ManualResetEvent(false) }; IsLoading = true; var shopList = ShopList.Where(s => s.IsSelected).ToList(); var sDate = StartDate.AddDays(-5); var eDate = EndDate; Task.Factory.StartNew(() => { AuditByPayBill(waitList[0], shopList, sDate, eDate); //AuditByPurchaseOrder(waitList[1]); }).ContinueWith(t => { WaitHandle.WaitAll(waitList.ToArray(), -1); IsLoading = false; IsAudited = true; App.Current.Dispatcher.BeginInvoke((Action)delegate { SelectAuditFile = AuditFileList.FirstOrDefault(f => f.AuditFileType == AuditFileType.账单); }); }); } private void AuditByPayBill(EventWaitHandle ewh, IList shopList, DateTime startDate, DateTime endDate) { try { var auditPurchaseOrderResponse = purchaseOrderService.GetAuditPurchaseOrderList(shopList.Select(s => s.ShopId).ToList(), startDate, endDate); if (!auditPurchaseOrderResponse.Success) throw new Exception($"获取采购单失败,{auditPurchaseOrderResponse.Msg}"); //按日分组的pdd账单集合, key=日期 value=当日账单总额 var pddPayBillDayDictionary = new Dictionary(); foreach (var payBill in AuditPayBillList) { payBill.IsChanged = true; payBill.ErrorMessage = string.Empty; #region 按日累计拼多多账单金额 if (payBill.MerchantOrderNo.StartsWith("XP")) { if (!pddPayBillDayDictionary.TryGetValue(payBill.PayTime.Value.Date, out decimal pddTotalPurchaseAmount)) pddPayBillDayDictionary.Add(payBill.PayTime.Value.Date, 0); pddTotalPurchaseAmount += Math.Abs(payBill.ExpenditureAmount); pddPayBillDayDictionary[payBill.PayTime.Value.Date] = pddTotalPurchaseAmount; } #endregion #region 匹配采购单 if (string.IsNullOrEmpty(payBill.SourceMerchantOrderNo)) { payBill.ErrorMessage = "未选资金类型"; continue; } var relationPurchaseOrder = auditPurchaseOrderResponse.Data.FirstOrDefault(p => p.PurchaseOrderId == payBill.MerchantOrderNo || p.MerchantOrderId == payBill.MerchantOrderNo); if (relationPurchaseOrder == null) { //if (payBill.IncomeAmount > 0 && StartDate.Day == 1) //{ // payBill.AuditCapitalType = AuditCapitalType.上月商品退款; // continue; //} if (payBill.IsSupportMerchantOrderNo) { //if (payBill.MerchantOrderNo.StartsWith("XP")) // payBill.AuditCapitalType = AuditCapitalType.商品采购; //else payBill.ErrorMessage = "未匹配采购单"; } else payBill.ErrorMessage = "未选资金类型"; continue; } payBill.RelationPurchaseOrderId = relationPurchaseOrder.PurchaseOrderId; payBill.RelationShopOrderId = relationPurchaseOrder.OrderId; var belongShop = shopList.FirstOrDefault(s => s.ShopId == relationPurchaseOrder.ShopId); if (belongShop != null) { //payBill.BelongShopId = relationPurchaseOrder.ShopId; //payBill.BelongShop = belongShop?.ShopName; payBill.BelongShopModel = belongShop; } payBill.PurchasePlatform = relationPurchaseOrder.PurchasePlatform; payBill.OrderStartTime = relationPurchaseOrder.OrderStartTime; if (payBill.IncomeAmount > 0) { if (payBill.PayTime.Value.Month == relationPurchaseOrder.OrderStartTime.Value.Month) payBill.AuditCapitalType = AuditCapitalType.当月商品退款; else payBill.AuditCapitalType = AuditCapitalType.上月商品退款; } else { if (payBill.PayTime.Value.Month == relationPurchaseOrder.OrderStartTime.Value.Month) payBill.AuditCapitalType = AuditCapitalType.当月商品采购; else payBill.AuditCapitalType = AuditCapitalType.上月商品采购; } #endregion } #region 按日比较拼多多账单金额和采购单金额 foreach (var key in pddPayBillDayDictionary) { var purchaseAmount = auditPurchaseOrderResponse.Data.Where(p => p.PurchaseTime.Value.Date == key.Key && p.PurchasePlatform == Platform.拼多多).Sum(p => p.PurchaseAmount); if (key.Value != purchaseAmount) { var currentDayPddPayBillList = AuditPayBillList.Where(p => p.PayTime.Value.Date == key.Key.Date && p.MerchantOrderNo.StartsWith("XP") && string.IsNullOrEmpty(p.RelationPurchaseOrderId)); foreach (var payBill in currentDayPddPayBillList) payBill.ErrorMessage = $"{key.Key:yyyy-MM-dd}账单金额与采购单不匹配"; } } #endregion } catch (Exception ex) { App.Current.Dispatcher.Invoke(() => MessageBox.Show(ex.Message, "账单匹配")); } finally { ewh.Set(); } } private void ClearAudit() { SelectAuditFile = null; AuditFileList.Clear(); AuditPayBillList.Clear(); //AuditPurchaseOrderList.Clear(); //AuditShopOrderList.Clear(); ShowAuditPayBillList.Clear(); //ShowAuditPurchaseOrderList.Clear(); //ShowAuditShopOrderList.Clear(); IsAudited = false; IsShowPayBillPanel = false; //IsShowPurchaseOrderPanel = false; //IsShowShopOrderPanel = false; OnlyException = false; SelectResultShop = null; NoChooseFundType = false; NoMatchPurchaseOrder = false; SearchResultPurchaseOrder = string.Empty; SelectPurchasePlatform = null; } private (string ErrorMessage, string FileName, List Lines) ImportAuditFile(AuditFileType auditFileType) { var ofd = new OpenFileDialog() { Filter = "CSV Files (*.csv)|*.csv" }; if (ofd.ShowDialog() != true) return (string.Empty, string.Empty, null); var fileName = ofd.FileName.Substring(ofd.FileName.LastIndexOf("\\") + 1); var filePath = ofd.FileName; if (AuditFileList.Any(f => f.FileName == fileName)) return ("文件已存在", string.Empty, null); try { var lines = File.ReadAllLines(filePath, Encoding.GetEncoding("GB2312")).ToList(); AuditFileList.Add(new AuditFile() { FileName = fileName, AuditFileType = auditFileType }); return (string.Empty, fileName, lines); } catch (Exception ex) { return (ex.Message, string.Empty, null); } } /// /// 导入支付宝账单 /// private void ImportAliPayBill() { //AuditPayBillList.Clear(); var importResult = ImportAuditFile(AuditFileType.账单); if (!string.IsNullOrEmpty(importResult.ErrorMessage)) { MessageBox.Show(importResult.ErrorMessage, "导入支付宝账单"); return; } if (importResult.Lines == null || importResult.Lines.Count == 0) return; //忽略前5行 /* #支付宝账务明细查询 #账号:[20883422054731100156] #起始日期:[2022年04月01日 00:00:00] 终止日期:[2022年05月01日 00:00:00] #-----------------------------------------账务明细列表---------------------------------------- 账务流水号 业务流水号 商户订单号 商品名称 发生时间 对方账号 收入金额(+元) 支出金额(-元) 账户余额(元) 交易渠道 业务类型 备注 */ for (var i = 0; i < 5; i++) importResult.Lines.RemoveAt(0); //忽略后4行 /* #-----------------------------------------账务明细列表结束------------------------------------ #支出合计:681笔,共-39623.27元 #收入合计:85笔,共43889.26元 #导出时间:[2022年05月01日 10:13:45] */ for (var i = 0; i < 4; i++) { importResult.Lines.RemoveAt(importResult.Lines.Count() - 1); } var payBillNo = ""; var list = new List(); try { foreach (var line in importResult.Lines) { var array = line.CSVstrToArry(); var sourceMerchantOrderNo = array[2].FormatString(); var incomeAmount = decimal.Parse(array[6].FormatString()); var expenditureAmount = decimal.Parse(array[7].FormatString()); payBillNo = array[0].FormatString(); if (list.Any(p => p.PayBillNo == payBillNo)) continue; var payBill = new AuditPayBill() { BelongFileName = importResult.FileName, PayBillNo = payBillNo, PayBillType = PayBillType.支付宝, SourceMerchantOrderNo = sourceMerchantOrderNo, ProductName = array[3].FormatString(), PayTime = DateTime.Parse(array[4].FormatString()), OppositeAccount = array[5].FormatString(), ExpenditureAmount = expenditureAmount, IncomeAmount = incomeAmount, Remark = array[11] }; payBill.MerchantOrderNo = payBill.SourceMerchantOrderNo; if (payBill.MerchantOrderNo == null) payBill.MerchantOrderNo = ""; if (payBill.SourceMerchantOrderNo.StartsWith("T50060NP")) { payBill.MerchantOrderNo = payBill.SourceMerchantOrderNo.Substring(8); payBill.IsSupportMerchantOrderNo = true; } if (payBill.SourceMerchantOrderNo.StartsWith("T200P")) { payBill.MerchantOrderNo = payBill.SourceMerchantOrderNo.Substring(5); payBill.IsSupportMerchantOrderNo = true; } if (payBill.SourceMerchantOrderNo.StartsWith("XP")) { payBill.IsSupportMerchantOrderNo = true; } list.Add(payBill); } //list = list.OrderByDescending(p => p.PayTime).ToList(); foreach (var p in list) AuditPayBillList.Add(p); } catch (Exception ex) { MessageBox.Show($"问题账单号{payBillNo} {ex.Message}", "导入支付宝账单"); } } private void ClearLocalCondition(bool isSearch = true) { OnlyException = false; NoMatchPurchaseOrder = false; NoChooseFundType = false; SelectResultShop = null; SelectPurchasePlatform = null; SearchResultPurchaseOrder = string.Empty; if (isSearch) SearchLocal(); } /// /// 采购审计文件对象改变事件 /// private void SearchLocal() { //if (SelectAuditFile == null) // return; //if (SelectAuditFile.AuditFileType == AuditFileType.账单) //{ IsShowPayBillPanel = true; ShowAuditPayBillList.Clear(); var where = AuditPayBillList.Where(b => true); if (SelectAuditFile != null) where = where.Where(b => b.BelongFileName == SelectAuditFile.FileName); if (OnlyException) where = where.Where(b => !string.IsNullOrEmpty(b.ErrorMessage)); if (NoMatchPurchaseOrder) where = where.Where(b => !string.IsNullOrEmpty(b.ErrorMessage) && b.ErrorMessage == "未匹配采购单"); if (NoChooseFundType) where = where.Where(b => !string.IsNullOrEmpty(b.ErrorMessage) && b.ErrorMessage == "未选资金类型"); if (SelectResultShop != null) where = where.Where(b => b.BelongShopId != null && b.BelongShopId.Value == SelectResultShop.ShopId); if (!string.IsNullOrEmpty(SearchResultPurchaseOrder)) where = where.Where(b => !string.IsNullOrEmpty(b.RelationPurchaseOrderId) && b.RelationPurchaseOrderId.Contains(SearchResultPurchaseOrder)); if (SelectPurchasePlatform != null) where = where.Where(b => b.PurchasePlatform == SelectPurchasePlatform); var list = where.ToList(); foreach (var b in list) ShowAuditPayBillList.Add(b); //} } private void Save() { if (ShowAuditPayBillList.Count == 0) { MessageBox.Show("没有需要保存的数据", "提示"); return; } var saveList = ShowAuditPayBillList.Where(p => p.IsChanged).ToList(); if (saveList.Count == 0) { MessageBox.Show("没有需要保存的账单"); return; } var importShopIds = string.Join(',', ShopList.Where(s => s.IsSelected).Select(s => s.ShopId)); var replaceResponse = financialTerminalService.IsExistAuditPayBill(importShopIds, StartDate, EndDate); if (!replaceResponse.Success) { MessageBox.Show("检查重复账单失败", "提示"); return; } if (replaceResponse.Data) if (MessageBox.Show("存在重复账单数据,是否覆盖", "确认", MessageBoxButton.OKCancel) != MessageBoxResult.OK) return; IsLoading = true; foreach (var bill in ShowAuditPayBillList) bill.ImportShopIds = importShopIds; Task.Factory.StartNew(() => financialTerminalService.BatchInsertAuditPayBill(saveList)).ContinueWith(t => { IsLoading = false; var insertResponse = t.Result; App.Current.Dispatcher.Invoke(() => { if (insertResponse.Success) { foreach (var p in saveList) p.IsChanged = false; MessageBox.Show("保存成功", "提示"); } else MessageBox.Show(insertResponse.Msg, "提示"); }); }); } private void Export() { if (ShowAuditPayBillList.Count == 0) return; var shopNames = string.Join(',', ShopList.Where(s => s.IsSelected).Select(s => s.ShopName)); var ew = new ProcurementAuditExcelExport(); if (ew.ShowDialog() != true) return; var fileName = string.Empty; var saveList = new List(); if (ew.Type == 0) { fileName = $"{StartDate:yyyy-MM-dd}_{EndDate:yyyy-MM-dd}_{shopNames}_审计结果.csv"; saveList.AddRange(ShowAuditPayBillList.Select(p => p.ToString()).ToList()); saveList.Insert(0, AuditPayBill.ExportTitle); } else { fileName = $"{StartDate:yyyy-MM-dd}_{EndDate:yyyy-MM-dd}_{shopNames}_资金类型汇总.csv"; saveList.Add($"序号,资金类型,{string.Join(',', ShopList)},汇总"); var capitalGroups = ShowAuditPayBillList.Where(p => p.AuditCapitalType != null).GroupBy(p => p.AuditCapitalType); var index = 1; var rowBuilder = new StringBuilder(); foreach (var capitalGroup in capitalGroups) { var sum = 0M; rowBuilder.Append($"{index},{capitalGroup.Key},"); foreach (var shop in ShopList) { var currentShopCapitalGroup = capitalGroup.Where(p => p.BelongShopId == shop.ShopId); var amount = 0M; if (currentShopCapitalGroup.Count() > 0) { if (capitalGroup.Key == AuditCapitalType.当月商品退款 || capitalGroup.Key == AuditCapitalType.上月商品退款) amount = currentShopCapitalGroup.Sum(p => p.IncomeAmount); else amount = currentShopCapitalGroup.Sum(p => p.ExpenditureAmount); } sum += amount; rowBuilder.Append($"{amount},"); } rowBuilder.Append($"{sum}"); index++; saveList.Add(rowBuilder.ToString()); rowBuilder.Clear(); } } var sfd = new SaveFileDialog() { FileName = fileName }; if (sfd.ShowDialog() != true) return; var path = sfd.FileName; try { File.WriteAllLines(path, saveList, Encoding.UTF8); MessageBox.Show("导出成功", "提示"); } catch (Exception ex) { MessageBox.Show(ex.Message, "导出审计结果"); } } private void ShowAuditCapitalTypeInputMode(AuditPayBill auditPayBill) { auditPayBill.AuditCapitalTypeInputMode = 1; } private void HideAuditCapitalTypeInputMode(AuditPayBill auditPayBill) { auditPayBill.AuditCapitalTypeInputMode = 0; } } }