You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

701 lines
31 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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<CardSale> 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;
}
/// <summary>
/// 关闭窗口
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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();
}
/// <summary>
/// 最小化
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnControlBoxMinClick(object sender, EventArgs e)
{
this.WindowState = FormWindowState.Minimized;
}
private void BtnExitClick(object sender, EventArgs e)
{
OnCloseTouchClick(sender, e);
}
/// <summary>
/// 时间选择
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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<CardSale> 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<CardSalePay> pays = getOrderPayListByTradeNo(ticketId);
payListTable.PrimaryGrid.DataSource = pays;
}
else
{
payListTable.PrimaryGrid.Rows.Clear();
}
}
/// <summary>
/// 退销售单
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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<CardSalePay> 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<bool, string> result = CardHelper.PrinterTicket("礼品卡销售", vars, true, openCashbox, 1, 0);
this.ShowToastNotify(this, string.Format("{0}", result.Item2));
}
}
});
}
}
private Tuple<bool, string,string> DoRefund(string busNo,string ticketId)
{
//获取主单数据
CardSale cardSale = GetOrderById(ticketId);
//获取明细单数据
List<CardSalePay> salePay = getOrderPayListByTradeNo(ticketId);
if (cardSale.PayStatus ==2 || !string.IsNullOrEmpty(cardSale.OrgBusNo) )
{
return new Tuple<bool, string,string>(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<bool, string, string>(false, response.Item2, null);
}
}
catch (Exception ex)
{
LOGGER.Error(ex, "礼品卡退单异常");
return new Tuple<bool, string, string>(false, "礼品卡退单异常", null);
}
//第二步组装支付方式
List<CardSalePay> backPay = new List<CardSalePay>();
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<bool, string, string>(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<bool, string, string>(false, upayPayment.Item2, null);
}
else
{
pay.Memo = "扫呗支付:该订单已全额退款,";
}
}
else
{
return new Tuple<bool, string, string>(false, res.Item2, null);
}
}
break;
default:
{
return new Tuple<bool, string, string>(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<bool, string, string>(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<bool, string, string>(false, upayPayment.Item2, null);
}
else
{
pay.Memo = "扫呗支付:该订单已全额退款,";
}
}
else
{
return new Tuple<bool, string, string>(false, res.Item2, null);
}
}
break;
default:
{
return new Tuple<bool, string, string>(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<CardSale>(_BackCardSale);
// 保存支付明细
List<CardSalePay> detail = _BackCardSale.Pay;
if (detail != null && detail.Count > 0)
{
foreach (CardSalePay detailEntity in detail)
{
db.Save<CardSalePay>(detailEntity);
}
}
transaction.Complete();
LOGGER.Info("单号:[{0}]保存礼品卡销售退单......成功", _BackCardSale.BusNo);
}
}
}
return new Tuple<bool, string, string>(true, "礼品卡退单成功", _BackCardSale.Id);
}
catch (Exception ex)
{
LOGGER.Error(ex);
return new Tuple<bool, string, string>(false, "礼品卡销售退单保存失败", null);
}
}
private void BtnQueryClick(object sender, EventArgs e)
{
QueryTicket();
}
public void QueryTicket()
{
//获取选择的订单
List<CardSale> 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<CardSale> getBusTicketList(string startTime, string endTime)
{
List<CardSale> 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<CardSale>(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<CardSale>();
}
return list;
}
public List<CardSalePay> getOrderPayListByTradeNo(string ticketId)
{
List<CardSalePay> 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<CardSalePay>(sql).ToList();
}
}
catch (Exception ex)
{
LOGGER.Error(ex);
}
if (list == null)
{
list = new List<CardSalePay>();
}
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<CardSale>(sql, null);
}
}
catch (Exception ex)
{
LOGGER.Error(ex);
}
return cardSale;
}
/// <summary>
/// 数据源绑定
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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;
}
}
}
/// <summary>
/// 读卡
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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();
}
}
/// <summary>
/// 输入是否验证通过
/// </summary>
private bool InputVerify()
{
if (string.IsNullOrEmpty(this.txtInput.Text.Trim()))
{
this.ShowToastNotify(this, "请输入卡号信息");
return false;
}
return true;
}
/// <summary>
/// 订单补打
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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<CardSalePay> 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<bool, string> result = CardHelper.PrinterTicket("礼品卡销售", vars, true, openCashbox, 1, 0);
this.ShowToastNotify(this, string.Format("{0}", result.Item2));
}
}
}