using DevComponents.DotNetBar; using DevComponents.DotNetBar.SuperGrid; using POSV.Card; using POSV.Entity; using POSV.Helper; using POSV.PayApi; using POSV.Payment.Saobei; using POSV.Payment.Saobei.Parameter; using POSV.ShoppingCart; using POSV.Utils; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace POSV.Member { public partial class GiftCardFormTicket : BusinessForm { public GiftCardFormTicket() { InitializeComponent(); this.controlBox1.Text = "礼品卡销售记录"; this.controlBox1.ShowApplicationVersion = false; } protected override void OnLoad(EventArgs e) { base.OnLoad(e); if (this.DesignMode) return; this.startPicker.Value = DateTime.Parse(Global.Instance.BusinessPlan.StartTimeSimple); this.endPicker.Value = DateTime.Parse(Global.Instance.BusinessPlan.EndTimeSimple); this.Focus(); this.txtTradeNo.Focus(); this.txtTradeNo.SelectAll(); this.ActiveControl = this.txtTradeNo; //第一步获取订单列表 List detail = getBusTicketList(this.startPicker.Value.ToString("yyyy-MM-dd HH:mm:ss"), this.endPicker.Value.ToString("yyyy-MM-dd HH:mm:ss")); CardSaleTable.PrimaryGrid.DataSource = detail; } /// /// 关闭窗口 /// /// /// private void OnControlBoxCloseClick(object sender, EventArgs e) { OnCloseTouchClick(sender, e); } private void OnCloseTouchClick(object sender, EventArgs e) { //先关闭父窗体 if (this.Owner != null) { this.Owner.Close(); } //再关闭当前窗体 this.Close(); } /// /// 最小化 /// /// /// private void OnControlBoxMinClick(object sender, EventArgs e) { this.WindowState = FormWindowState.Minimized; } private void BtnExitClick(object sender, EventArgs e) { OnCloseTouchClick(sender, e); } /// /// 时间选择 /// /// /// private void BtnTimeClick(object sender, EventArgs e) { var obj = sender as ButtonX; var typeStr = obj.Tag as string; var type = (ReportQuickDate)Enum.Parse(typeof(ReportQuickDate), typeStr); var res = DateTimeUtils.CalculateBusinessPlanDate(type, this.startPicker.Value, this.endPicker.Value); this.startPicker.Value = res.Item1; this.endPicker.Value = res.Item2; List detail = getBusTicketList(this.startPicker.Value.ToString("yyyy-MM-dd HH:mm:ss"), this.endPicker.Value.ToString("yyyy-MM-dd HH:mm:ss")); CardSaleTable.PrimaryGrid.DataSource = detail; } private void OnTicketRowActivated(object sender, DevComponents.DotNetBar.SuperGrid.GridRowActivatedEventArgs e) { GridPanel grid = e.GridPanel; if (e.NewActiveRow != null) { payListTable.PrimaryGrid.Rows.Clear(); //先清除其他表数据 GridRow row = e.NewActiveRow as GridRow; grid.SetSelected(e.NewActiveRow, false); grid.SetActiveRow(e.NewActiveRow); var ticketId = row.Cells["id"].Value.ToString(); List pays = getOrderPayListByTradeNo(ticketId); payListTable.PrimaryGrid.DataSource = pays; } else { payListTable.PrimaryGrid.Rows.Clear(); } } /// /// 退销售单 /// /// /// private void BtnBackTicketClick(object sender, EventArgs e) { this.RefundOrderCheck(); } private void RefundOrderCheck() { var panel = CardSaleTable.PrimaryGrid; if (panel.ActiveRow == null) { this.ShowToastNotify(this, "请选择要操作的单据"); return; } //提示 var row = panel.ActiveRow as GridRow; var ticketId = row.Cells["id"].Value.ToString(); var busNo = row.Cells["busNo"].Value.ToString(); bool allowBackPayHistory = Global.Instance.GlobalConfigBoolValue(ConfigConstant.CASHIER_ALLOW_BACKPAY_HISTORY, true); //不允许退历史单据 if (!allowBackPayHistory) { //判断是否是隔天的单据 var createDate = row.Cells["createDate"].Value.ToString(); string ticketDate = DateTime.Parse(createDate).ToString("yyyy-MM-dd"); if (!ticketDate.Equals(DateTime.Now.ToString("yyyy-MM-dd"))) { //不是同一天,查询设置 this.ShowToastNotify(this, "只能退款当日单据!"); return; } } //有销售流水不允许退单 var dialog = new DialogForm("礼品卡退单确认提醒", string.Format("确定退<{0}>单?", busNo), MessageBoxIcon.Question, MessageBoxButtons.OKCancel); if (dialog.ShowDialog(this) == DialogResult.OK) { LOGGER.Info("礼品卡销售记录<{0}>确定退单", busNo); Task.Factory.StartNew(() => { return DoRefund(busNo, ticketId); ; }).ContinueWith(task => { if (task.IsFaulted) { LOGGER.Error(task.Exception.GetBaseException()); } else { if (!task.Result.Item1) { this.ShowToastNotify(this, "退款失败!"); LOGGER.Info("退单失败![{0}]", task.Result.Item2); if (this.IsDisposed || !this.IsHandleCreated) return; this.Invoke(new Action(() => { dialog = new DialogForm("退款提醒", "退款失败!" + task.Result.Item2, MessageBoxIcon.Warning, MessageBoxButtons.OK); dialog.TopLevel = true; dialog.ShowDialog(this); })); } else { this.ShowToastNotify(this, "退单成功!"); LOGGER.Info("退单交易完成"); if (this.IsDisposed || !this.IsHandleCreated) return; this.Invoke(new Action(() => { dialog = new DialogForm("退款提醒", "退款成功(金额原路退回)!", MessageBoxIcon.Warning, MessageBoxButtons.OK); dialog.TopLevel = true; dialog.ShowDialog(this); QueryTicket(); })); //退单打印 List salePay = getOrderPayListByTradeNo(task.Result.Item3); CardSale cardSale = GetOrderById(task.Result.Item3); SaleGiftCardRecordRequest request = new SaleGiftCardRecordRequest(); if (salePay != null && salePay.Count > 0) { CardSalePay cardSalePay = salePay[0]; request.SaleAmount = cardSalePay.Amount; request.PayType = cardSalePay.PayName; } SaleGiftCardRecordResponse response = new SaleGiftCardRecordResponse(); if (cardSale != null) { response.TicketNo = cardSale.TicketNo; response.CardNo = cardSale.CardNo; response.SchemeName = cardSale.PlanName; response.RetailPrice = cardSale.RetailPrice; response.RealAmount = cardSale.RealAmount; } //退款成功打单 this.ShowToastNotify(this, "开始打印"); //构建收银小票模版参数打印 var vars = CardHelper.BuilderGiftCardVariable(request, response, false,true); bool openCashbox = false; //充值打印份数 int ticketCount = Global.Instance.GlobalConfigIntValue(ConfigConstant.PERIPHERAL_CASHIER_RECHARGE_COUNT, 1); //打印延迟 int delaySecond = Global.Instance.GlobalConfigIntValue(ConfigConstant.PERIPHERAL_CASHIER_CARD_PRINT_DELAY, 1); //执行收银小票打印 Tuple result = CardHelper.PrinterTicket("礼品卡销售", vars, true, openCashbox, 1, 0); this.ShowToastNotify(this, string.Format("{0}", result.Item2)); } } }); } } private Tuple DoRefund(string busNo,string ticketId) { //获取主单数据 CardSale cardSale = GetOrderById(ticketId); //获取明细单数据 List salePay = getOrderPayListByTradeNo(ticketId); if (cardSale.PayStatus ==2 || !string.IsNullOrEmpty(cardSale.OrgBusNo) ) { return new Tuple(false, "订单已完全退单",null); } string backTradeNo = string.Format("{0}_{1}{2}", Global.Instance.Authc.StoreNo, Global.Instance.Authc.PosNo, DateTime.Now.ToString("yyyyMMddHHmmss")); //生成新单 CardSale _BackCardSale = ObjectUtils.Copy(cardSale); _BackCardSale.Id = IdWorkerUtils.Instance.NextId(); _BackCardSale.PayStatus = 2; _BackCardSale.BusNo = backTradeNo.Split('_')[1]; _BackCardSale.CreateDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); _BackCardSale.Money = 0-cardSale.Money; _BackCardSale.OrgBusNo = cardSale.BusNo; //第一步先发起退单请求 try { var request = new RefundGiftCardRecordRequest(); request.CardNo = cardSale.CardNo; request.PayVoucherNo = string.Format("{0}_{1}", Global.Instance.Authc.StoreNo, cardSale.BusNo); request.ShopNo = Global.Instance.Authc.StoreNo; request.PosNo = Global.Instance.Authc.PosNo; request.WorkerNo = Global.Instance.Worker.No; var response = CardUtils.RefundGiftCardRecord(request); //成功 if (response.Item1) { RefundGiftCardRecordResponse saleGiftCardRecordResponse = response.Item3.Data; _BackCardSale.TicketNo = saleGiftCardRecordResponse.TicketNo; _BackCardSale.ShiftName = Global.Instance.BusinessPlanLog.Name; _BackCardSale.ShiftNo = Global.Instance.BusinessPlanLog.No; _BackCardSale.WorkerId = Global.Instance.BusinessPlanLog.WorkerId; _BackCardSale.WorkerName = Global.Instance.BusinessPlanLog.WorkerName; _BackCardSale.WorkerNo = Global.Instance.BusinessPlanLog.WorkerNo; } else { return new Tuple(false, response.Item2, null); } } catch (Exception ex) { LOGGER.Error(ex, "礼品卡退单异常"); return new Tuple(false, "礼品卡退单异常", null); } //第二步组装支付方式 List backPay = new List(); foreach (CardSalePay pay in salePay) { switch (pay.PayNo) { case "04"://支付宝 { this.ShowToastNotify(this, "正在进行支付宝退款...请勿关闭!", 30000); switch (pay.PayChannel) { case PayChannelEnum.原生支付: { var result = AlipayApi.RefundAndQuery(AccountTypeEnum.门店, pay.VoucherNo, pay.Amount, backTradeNo, "正常退款"); if (!result.Item1) { return new Tuple(false, result.Item2,null); } } break; case PayChannelEnum.扫呗支付: { var res = SaobeiApi.GetSaobeiParameter(AccountTypeEnum.门店); if (res.Item1) { var parameter = res.Item3; //银联商务支付参数 string merchant_no = parameter.ContainsKey("merchant_no") ? parameter["merchant_no"].ToString() : ""; string terminal_id = parameter.ContainsKey("terminal_id") ? parameter["terminal_id"].ToString() : ""; string signKey = parameter.ContainsKey("signKey") ? parameter["signKey"].ToString() : ""; string gatewayUrl = parameter.ContainsKey("gatewayUrl") ? parameter["gatewayUrl"].ToString() : ""; string requestNum = string.Format("{0}_{1}", Global.Instance.Authc.StoreNo, backTradeNo); SaobeiRefundParam request = new SaobeiRefundParam(); request.Pay_type = "020"; request.Terminal_trace = pay.VoucherNo; request.Refund_fee = string.Format("{0}", Convert.ToInt32(Math.Abs(pay.Amount) * 100)); request.Out_trade_no = pay.Memo; var upayPayment = SaobeiUtils.SaobeiRefund(merchant_no, terminal_id, signKey, gatewayUrl, request); if (!upayPayment.Item1) { return new Tuple(false, upayPayment.Item2, null); } else { pay.Memo = "扫呗支付:该订单已全额退款,"; } } else { return new Tuple(false, res.Item2, null); } } break; default: { return new Tuple(false, "暂未开放该渠道退款",null); } } } break; case "05"://微信支付 { this.ShowToastNotify(this, "正在进行微信退款...时间很长,预计1-2分钟,请勿关闭!", 100000); switch (pay.PayChannel) { case PayChannelEnum.原生支付: { var result = WeixinApi.RefundAndQuery(AccountTypeEnum.门店, pay.VoucherNo, pay.Amount, pay.Amount, backTradeNo, "正常退款", 100); if (!result.Item1) { return new Tuple(false, result.Item2,null); } } break; case PayChannelEnum.扫呗支付: { var res = SaobeiApi.GetSaobeiParameter(AccountTypeEnum.门店); if (res.Item1) { var parameter = res.Item3; //银联商务支付参数 string merchant_no = parameter.ContainsKey("merchant_no") ? parameter["merchant_no"].ToString() : ""; string terminal_id = parameter.ContainsKey("terminal_id") ? parameter["terminal_id"].ToString() : ""; string signKey = parameter.ContainsKey("signKey") ? parameter["signKey"].ToString() : ""; string gatewayUrl = parameter.ContainsKey("gatewayUrl") ? parameter["gatewayUrl"].ToString() : ""; string requestNum = string.Format("{0}_{1}", Global.Instance.Authc.StoreNo, backTradeNo); SaobeiRefundParam request = new SaobeiRefundParam(); request.Pay_type = "010"; request.Terminal_trace = pay.VoucherNo; request.Refund_fee = string.Format("{0}", Convert.ToInt32(Math.Abs(pay.Amount) * 100)); request.Out_trade_no = pay.Memo; var upayPayment = SaobeiUtils.SaobeiRefund(merchant_no, terminal_id, signKey, gatewayUrl, request); if (!upayPayment.Item1) { return new Tuple(false, upayPayment.Item2, null); } else { pay.Memo = "扫呗支付:该订单已全额退款,"; } } else { return new Tuple(false, res.Item2, null); } } break; default: { return new Tuple(false, "暂未开放该渠道退款" , null); } break; } } break; } //组装支付方式 pay.Id = IdWorkerUtils.Instance.NextId(); pay.TicketId = _BackCardSale.Id; pay.Amount = 0 - pay.Amount; pay.CreateDate = _BackCardSale.CreateDate; backPay.Add(pay); } _BackCardSale.Pay = backPay; //第三部保存单据 try { lock (Global.Instance.SyncLock) { using (var db = Global.Instance.OpenDataBase) { using (var transaction = db.GetTransaction()) { //更新主单的退单状态 string updateSql = string.Format("update pos_card_sale set orgBusNo='{0}' where id = '{1}';", _BackCardSale.BusNo, cardSale.Id); LOGGER.Info("单号:[{0}]更新主单状态......开始", cardSale.BusNo); db.Execute(updateSql); LOGGER.Info("单号:[{0}]保存礼品卡销售退单......开始", _BackCardSale.BusNo); // 保存主单数据 db.Save(_BackCardSale); // 保存支付明细 List detail = _BackCardSale.Pay; if (detail != null && detail.Count > 0) { foreach (CardSalePay detailEntity in detail) { db.Save(detailEntity); } } transaction.Complete(); LOGGER.Info("单号:[{0}]保存礼品卡销售退单......成功", _BackCardSale.BusNo); } } } return new Tuple(true, "礼品卡退单成功", _BackCardSale.Id); } catch (Exception ex) { LOGGER.Error(ex); return new Tuple(false, "礼品卡销售退单保存失败", null); } } private void BtnQueryClick(object sender, EventArgs e) { QueryTicket(); } public void QueryTicket() { //获取选择的订单 List detail = getBusTicketList(this.startPicker.Value.ToString("yyyy-MM-dd HH:mm:ss"), this.endPicker.Value.ToString("yyyy-MM-dd HH:mm:ss")); CardSaleTable.PrimaryGrid.DataSource = detail; } public List getBusTicketList(string startTime, string endTime) { List list = null; string busNo = StringUtils.GetString(this.txtTradeNo.Text); string cardNo = StringUtils.GetString(this.txtInput.Text); try { using (var db = Global.Instance.OpenDataBase) { StringBuilder sqlBuld = new StringBuilder(); sqlBuld.Append(" select * "); sqlBuld.Append(" from pos_card_sale "); sqlBuld.Append(" where createDate >= '{0}' and createDate <= '{1}'"); if (busNo != null && !"".Equals(busNo)) { sqlBuld.Append(" and busNo like '%" + busNo + "%' "); } if (cardNo != null && !"".Equals(cardNo)) { sqlBuld.Append(" and cardNo like '%" + cardNo + "%' "); } sqlBuld.Append(" order by createDate desc"); string sql = string.Format(sqlBuld.ToString(), startTime, endTime); list = db.Query(sql).ToList(); foreach (CardSale cardSaleEntity in list) { if (cardSaleEntity.PayStatus == 2 || !string.IsNullOrEmpty(cardSaleEntity.OrgBusNo)) { cardSaleEntity.StatusDesc = "已退单"; } else { cardSaleEntity.StatusDesc = "已支付"; } } } } catch (Exception ex) { LOGGER.Error(ex); } if (list == null) { list = new List(); } return list; } public List getOrderPayListByTradeNo(string ticketId) { List list = null; try { using (var db = Global.Instance.OpenDataBase) { StringBuilder sqlBuld = new StringBuilder(); sqlBuld.Append(" select * "); sqlBuld.Append(" from pos_card_sale_pay "); sqlBuld.Append(" where ticketId = '{0}' "); string sql = string.Format(sqlBuld.ToString(), ticketId); list = db.Query(sql).ToList(); } } catch (Exception ex) { LOGGER.Error(ex); } if (list == null) { list = new List(); } return list; } public CardSale GetOrderById(string ticketId) { CardSale cardSale = null; try { using (var db = Global.Instance.OpenDataBase) { StringBuilder sqlBuld = new StringBuilder(); sqlBuld.Append(" select * "); sqlBuld.Append(" from pos_card_sale "); sqlBuld.Append(" where id = '{0}' "); string sql = string.Format(sqlBuld.ToString(), ticketId); cardSale = db.FirstOrDefault(sql, null); } } catch (Exception ex) { LOGGER.Error(ex); } return cardSale; } /// /// 数据源绑定 /// /// /// private void OnBind(object sender, GridDataBindingCompleteEventArgs e) { var panel = e.GridPanel; foreach (var r in panel.Rows) { var row = r as GridRow; //设置单据内容字体颜色 if ("已退单".Equals(row.Cells["statusDesc"].Value.ToString())) { row.CellStyles.Default.TextColor = Color.Red; } else { row.CellStyles.Default.TextColor = Color.Black; } } } /// /// 读卡 /// /// /// private void OnReadCardClick(object sender, EventArgs e) { var result = CardOperateUtils.Instance.ReadCardNo(); if (result.Item1) { this.txtInput.Text = result.Item2; //读卡成功,模拟回车事件 InputSimulatorUtils.SendKey(KeyCodes.Map["return"]); } else { result = CardOperateUtilsOther.Instance.ReadCardNo(); if (result.Item1) { this.txtInput.Text = result.Item2; //读卡成功,模拟回车事件 InputSimulatorUtils.SendKey(KeyCodes.Map["return"]); } else { this.ShowToastNotify(this, result.Item2); } } } private void OnFinishedClick(object sender, Component.EnterEventArg e) { var isVerify = InputVerify(); if (isVerify) { QueryTicket(); } } /// /// 输入是否验证通过 /// private bool InputVerify() { if (string.IsNullOrEmpty(this.txtInput.Text.Trim())) { this.ShowToastNotify(this, "请输入卡号信息"); return false; } return true; } /// /// 订单补打 /// /// /// private void BtnPrintClick(object sender, EventArgs e) { var panel = CardSaleTable.PrimaryGrid; if (panel.ActiveRow == null) { this.ShowToastNotify(this, "请选择要操作的单据"); return; } //提示 var row = panel.ActiveRow as GridRow; var ticketId = row.Cells["id"].Value.ToString(); var busNo = row.Cells["busNo"].Value.ToString(); List salePay = getOrderPayListByTradeNo(ticketId); CardSale cardSale = GetOrderById(ticketId); SaleGiftCardRecordRequest request = new SaleGiftCardRecordRequest(); if (salePay!=null && salePay.Count>0) { CardSalePay cardSalePay = salePay[0]; request.SaleAmount = cardSalePay.Amount; request.PayType = cardSalePay.PayName; } SaleGiftCardRecordResponse response = new SaleGiftCardRecordResponse(); if (cardSale!=null) { response.TicketNo = cardSale.TicketNo; response.CardNo = cardSale.CardNo; response.SchemeName = cardSale.PlanName; response.RetailPrice = cardSale.RetailPrice; response.RealAmount = cardSale.RealAmount; } bool isBack = false; if (cardSale.PayStatus==2) { isBack = true; } //成功以后打印 this.ShowToastNotify(this, "开始打印"); //构建收银小票模版参数打印 var vars = CardHelper.BuilderGiftCardVariable(request, response, true, isBack); bool openCashbox = false; //充值打印份数 int ticketCount = Global.Instance.GlobalConfigIntValue(ConfigConstant.PERIPHERAL_CASHIER_RECHARGE_COUNT, 1); //打印延迟 int delaySecond = Global.Instance.GlobalConfigIntValue(ConfigConstant.PERIPHERAL_CASHIER_CARD_PRINT_DELAY, 1); //执行收银小票打印 Tuple result = CardHelper.PrinterTicket("礼品卡销售", vars, true, openCashbox, 1, 0); this.ShowToastNotify(this, string.Format("{0}", result.Item2)); } } }