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.

1311 lines
61 KiB
C#

9 months ago
using com.azkoss.excellite;
using DevComponents.DotNetBar;
using DevComponents.DotNetBar.Controls;
using POS.Language.Language;
using POSV.Component;
using POSV.Entity;
using POSV.Helper;
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.Windows.Forms;
namespace POSV.Report
{
public partial class DaySaleReport : BusinessForm
{
public DaySaleReport()
{
InitializeComponent();
this.controlBox1.Text = LangProxy.ToLang( "营业日报");
this.controlBox1.ShowApplicationVersion = false;
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
DefaultGridStyle.setSmallGridStyle(this.overDetailGrid);
DefaultGridStyle.setSmallGridStyle(this.nonoperatingGrid);
DefaultGridStyle.setSmallGridStyle(this.promotionGrid);
DefaultGridStyle.setSmallGridStyle(this.orderTypeGrid);
DefaultGridStyle.setSmallGridStyle(this.payWayGrid);
DefaultGridStyle.setSmallGridStyle(this.categoryGrid);
DefaultGridStyle.setSmallGridStyle(this.categorySeqGrid);
//DefaultGridStyle.setDefaultGridStyle(this.productListTable);
//DefaultGridStyle.setDefaultGridStyle(this.productMakeListTable);
//DefaultGridStyle.setDefaultGridStyle(this.payListTable);
this.startPicker.Value = DateTime.Parse(Global.Instance.BusinessPlan.StartTimeSimple);
this.endPicker.Value = DateTime.Parse(Global.Instance.BusinessPlan.EndTimeSimple);
InitPrintChk();
}
private void InitPageData()
{
this.lblKl.Text = string.Empty;
this.lblOrderNum.Text = string.Empty;
this.lblAmount.Text = string.Empty;
this.lblPromotion.Text = string.Empty;
this.lblMaling.Text = string.Empty;
this.lblPaid.Text = string.Empty;
this.lblAveragePerson.Text = string.Empty;
this.lblAverageOrder.Text = string.Empty;
this.lblRefund.Text = string.Empty;
this.lblOverAmount.Text = string.Empty;
promotionGrid.PrimaryGrid.Rows.Clear();
nonoperatingGrid.PrimaryGrid.Rows.Clear();
overDetailGrid.PrimaryGrid.Rows.Clear();
payWayGrid.PrimaryGrid.Rows.Clear();
orderTypeGrid.PrimaryGrid.Rows.Clear();
categoryGrid.PrimaryGrid.Rows.Clear();
categorySeqGrid.PrimaryGrid.Rows.Clear();
}
private void InitPrintChk()
{
this.printOverChk.Checked = true;
this.printNonoperatingChk.Checked = true;
this.printCategoryChk.Checked = true;
this.printCategorySeqChk.Checked = true;
this.printOrderTypeChk.Checked = true;
this.printPayWayChk.Checked = true;
this.printPromotionChk.Checked = true;
var printChkStr = Global.Instance.GlobalConfigStringValue(ConfigConstant.CONFIG_CASHIER_DAYSALEREPORT_PRINT);
if (!string.IsNullOrEmpty(printChkStr))
{
var printChk = JsonUtils.Deserialize<Dictionary<string, string>>(printChkStr);
if(printChk != null)
{
foreach(var chk in printChk.Keys)
{
switch (chk)
{
case "打印溢收明细":
this.printOverChk.Checked = printChk["打印溢收明细"] == "true";
break;
case "打印非营业收支":
this.printNonoperatingChk.Checked = printChk["打印非营业收支"] == "true"; ;
break;
case "打印优惠统计":
this.printPromotionChk.Checked = printChk["打印优惠统计"] == "true"; ;
break;
case "打印订单类型":
this.printOrderTypeChk.Checked = printChk["打印订单类型"] == "true"; ;
break;
case "打印收银方式":
this.printPayWayChk.Checked = printChk["打印收银方式"] == "true"; ;
break;
case "打印商品分类":
this.printCategoryChk.Checked = printChk["打印商品分类"] == "true"; ;
break;
case "打印分类排行":
this.printCategorySeqChk.Checked = printChk["打印分类排行"] == "true"; ;
break;
}
}
}
}
this.printOverChk.CheckedChanged += OnPrintCheckChanged;
this.printNonoperatingChk.CheckedChanged += OnPrintCheckChanged;
this.printCategoryChk.CheckedChanged += OnPrintCheckChanged;
this.printCategorySeqChk.CheckedChanged += OnPrintCheckChanged;
this.printOrderTypeChk.CheckedChanged += OnPrintCheckChanged;
this.printPayWayChk.CheckedChanged += OnPrintCheckChanged;
this.printPromotionChk.CheckedChanged += OnPrintCheckChanged;
}
private void OnPrintCheckChanged(object sender, EventArgs e)
{
//保存更新打印设置
Dictionary<string, string> chkDic = new Dictionary<string, string>();
chkDic["打印溢收明细"] = this.printOverChk.Checked.ToString().ToLower();
chkDic["打印非营业收支"] = this.printNonoperatingChk.Checked.ToString().ToLower();
chkDic["打印优惠统计"] = this.printPromotionChk.Checked.ToString().ToLower();
chkDic["打印订单类型"] = this.printOrderTypeChk.Checked.ToString().ToLower();
chkDic["打印收银方式"] = this.printPayWayChk.Checked.ToString().ToLower();
chkDic["打印商品分类"] = this.printCategoryChk.Checked.ToString().ToLower();
chkDic["打印分类排行"] = this.printCategorySeqChk.Checked.ToString().ToLower();
var config = new Config();
config.Id = IdWorkerUtils.Instance.NextId();
config.Group = ConfigConstant.CASHIER_GROUP;
config.TenantId = Global.Instance.Authc.TenantId;
config.Keys = ConfigConstant.CONFIG_CASHIER_DAYSALEREPORT_PRINT;
config.Values = JsonUtils.Serialize(chkDic);
bool isSuccess = true;
string message = "参数更新成功";
try
{
lock (Global.Instance.SyncLock)
{
using (var db = Global.Instance.OpenDataBase)
{
using (var trans = db.GetTransaction())
{
db.Save(config);
trans.Complete();
}
}
}
}
catch (Exception ex)
{
isSuccess = false;
message = "日营业报表打印参数更新异常";
LOGGER.Error(ex, message);
}
finally
{
if (isSuccess)
{
Global.Instance.ReloadConfig(ConfigConstant.CASHIER_GROUP);
}
}
}
private Dictionary<string, string> businessDic = new Dictionary<string, string>();
private List<Tuple<string, string, string, string>> promotionList = new List<Tuple<string, string, string, string>>();
private List<Tuple<string, string, string>> nonoperatingList = new List<Tuple<string, string, string>>();
private List<Tuple<string, string>> overAmountList = new List<Tuple<string, string>>();
private List<Tuple<string, string, string, string>> payWayList = new List<Tuple<string, string, string, string>>();
private List<Tuple<string, string, string, string, string>> orderTypeList = new List<Tuple<string, string, string, string, string>>();
private List<Tuple<string, string, string, string, string>> categoryList = new List<Tuple<string, string, string, string, string>>();
private List<Tuple<string, string, string, string, string>> categorySeqList = new List<Tuple<string, string, string, string, string>>();
string startTime = string.Empty;
string endTime = string.Empty;
private void OnQueryClick(object sender, EventArgs e)
{
try
{
InitPageData();
businessDic = new Dictionary<string, string>();
promotionList = new List<Tuple<string, string, string, string>>();
nonoperatingList = new List<Tuple<string, string, string>>();
overAmountList = new List<Tuple<string, string>>();
payWayList = new List<Tuple<string, string, string, string>>();
orderTypeList = new List<Tuple<string, string, string, string, string>>();
categoryList = new List<Tuple<string, string, string, string, string>>();
categorySeqList = new List<Tuple<string, string, string, string, string>>();
startTime = this.startPicker.Value.ToString("yyyy-MM-dd HH:mm:ss");
endTime = this.endPicker.Value.ToString("yyyy-MM-dd HH:mm:ss");
//**********营业统计
#region 营业统计
var sql = @"select cast(sum(p.people) as text) as peopleNum, count(1) as orderNum, cast(round(sum(p.amount),2) as text) as amount, cast(round(sum(p.discountAmount),2) as text) as discountAmount,
cast(round(sum(p.malingAmount),2) as text) as malingAmount, cast(round(sum(p.paidAmount),2) as text) as paidAmount
from pos_order p
where p.orderStatus in (0,4) and orgTradeNo = '' and p.finishDate >= '{0}' and p.finishDate <= '{1}';";
var ds = SqliteUtils.Query(string.Format(sql, startTime, endTime), "data");
var dt = ds.Tables["data"];
if(dt.Rows.Count > 0)
{
var data = dt.Rows[0];
var peopleNum = StringUtils.GetDecimal(data["peopleNum"]);
businessDic.Add("peopleNum", peopleNum + "");
this.lblKl.Text = peopleNum.ToString();
var orderNum = StringUtils.GetDecimal(data["orderNum"]);
businessDic.Add("orderNum", orderNum + "");
this.lblOrderNum.Text = orderNum.ToString();
var amount = StringUtils.GetDecimal(data["amount"]);
businessDic.Add("amount", amount + "");
this.lblAmount.Text = amount.ToString();
var discountAmount = StringUtils.GetString(data["discountAmount"]);
this.lblPromotion.Text = discountAmount;
businessDic.Add("discountAmount", discountAmount + "");
var malingAmount = StringUtils.GetString(data["malingAmount"]);
this.lblMaling.Text = StringUtils.GetString(data["malingAmount"]);
businessDic.Add("malingAmount", malingAmount + "");
var paidAmount = StringUtils.GetDecimal(data["paidAmount"]);
businessDic.Add("paidAmount", paidAmount + "");
this.lblPaid.Text = paidAmount.ToString();
string peopleAverage = "0", orderAverage = "0";
//人均
if(peopleNum != 0)
{
peopleAverage = StringUtils.FormatDataTwoDigit(paidAmount / peopleNum);
}
this.lblAveragePerson.Text = peopleAverage;
businessDic.Add("peopleAverage", peopleAverage + "");
//单均
if (orderNum != 0)
{
orderAverage = StringUtils.FormatDataTwoDigit(paidAmount / orderNum);
}
this.lblAverageOrder.Text = orderAverage;
businessDic.Add("orderAverage", orderAverage + "");
}
#endregion
//**********退款
#region 退款
decimal refundCount = 0, refundPeopleNum = 0;//退款订单数、退款人数
sql = @"select cast(sum(p.paidAmount) as text) as refundAmount, count(1) as refundCount, cast(sum(p.people) as text) as peopleNum
from pos_order p
where p.orderStatus = 2 and p.orgTradeNo != '' and p.finishDate >= '{0}' and p.finishDate <= '{1}';";
ds = SqliteUtils.Query(string.Format(sql, startTime, endTime), "data");
dt = ds.Tables["data"];
if (dt.Rows.Count > 0)
{
var data = dt.Rows[0];
var refundAmount = StringUtils.GetDecimal(data["refundAmount"]);
this.lblRefund.Text = refundAmount + "";
businessDic.Add("refundAmount", refundAmount + "");
refundCount = StringUtils.GetDecimal(data["refundCount"]);
refundPeopleNum = StringUtils.GetDecimal(data["peopleNum"]);
}
else
{
this.lblRefund.Text = "0";
businessDic.Add("refundAmount", "0");
}
#endregion
//**********溢收
#region 溢收
sql = @"select cast(sum(p.overAmount) as text) as overAmount from pos_order_pay p
inner join pos_order r on p.tradeNo = r.tradeNo
where r.orderStatus in (0,2,4) and p.finishDate >= '{0}' and p.finishDate <= '{1}';";
ds = SqliteUtils.Query(string.Format(sql, startTime, endTime), "data");
dt = ds.Tables["data"];
if (dt.Rows.Count > 0)
{
var data = dt.Rows[0];
var overAmount = StringUtils.GetString(data["overAmount"]);
this.lblOverAmount.Text = overAmount;
businessDic.Add("overAmount", overAmount + "");
}
else
{
this.lblOverAmount.Text = "0";
businessDic.Add("overAmount", "0");
}
#endregion
//**********优惠统计
#region 优惠统计
decimal totalNum = 0.00M;
decimal totalAmount = 0.00M;
//单品优惠统计,排除道菜分摊优惠
sql = @"select d.promotionType, d.planName,cast(round(sum(d.discountAmount),2) as text) as discountAmount ,count(1) as num from
(select a.promotionType, a.planName,cast(round(sum(a.discountAmount),2) as text) as discountAmount ,a.tradeNo
from pos_order_item_promotion a
left join pos_order_item b on a.itemId = b.id
left join pos_order c on b.orderId = c.id
where c.orderStatus in (0, 4)
and c.orgTradeNo = ''
and c.finishDate >= '{0}' and c.finishDate <= '{1}'
and a.promotionType <> '50'
group by a.tradeNo, a.planNo, a.promotionType, a.planName) d
group by d.promotionType, d.planName; ";
var ds2 = SqliteUtils.Query(string.Format(sql, startTime, endTime), "data");
var dt2 = ds2.Tables["data"];
//增加优惠名称
dt2.Columns.Add(new DataColumn("promotionTypeName"));
foreach (DataRow row in dt2.Rows)
{
var promotionType = StringUtils.GetString(row["promotionType"]);
var planName = StringUtils.GetString(row["planName"]);
//这里这样做是为了兼容历史数据因为新增了planName 优惠方案名称
if (!string.IsNullOrEmpty(planName))
{
row["promotionTypeName"] = planName;
}
else
{
var type = (PromotionType)Enum.Parse(typeof(PromotionType), promotionType);
row["promotionTypeName"] = type.ToString();
}
totalNum += StringUtils.GetDecimal(row["num"]);
totalAmount += StringUtils.GetDecimal(row["discountAmount"]);
}
//增加占比
dt2.Columns.Add(new DataColumn("amountRatio"));
foreach (DataRow row in dt2.Rows)
{
if (totalAmount > 0)
{
row["amountRatio"] = StringUtils.FormatDataTwoDigit(StringUtils.GetDecimal(row["discountAmount"]) / totalAmount * 100) + "%";
}
else
{
row["amountRatio"] = "0%";
}
promotionList.Add(new Tuple<string, string, string, string>(row["promotionTypeName"] + "", row["num"] + "", row["discountAmount"] + "", row["amountRatio"] + ""));
}
//添加小计行
var totalRow = dt2.NewRow();
totalRow["promotionTypeName"] = LangProxy.ToLang("小计");
totalRow["num"] = totalNum;
totalRow["discountAmount"] = StringUtils.FormatDataNoDigit(totalAmount);
dt2.Rows.Add(totalRow);
promotionList.Add(new Tuple<string, string, string, string>(totalRow["promotionTypeName"] + "", totalRow["num"] + "", totalRow["discountAmount"] + "", string.Empty));
promotionGrid.PrimaryGrid.DataSource = dt2;
#endregion
//**********营业外收支
#region 营业外收支
sql = @"select cast(sum(p.money) as text) as money, p.type from pos_store_cost_revenue p where p.inputDate >= '{0}' and p.inputDate <= '{1}' group by p.type;";
ds = SqliteUtils.Query(string.Format(sql, startTime, endTime), "data");
dt = ds.Tables["data"];
if (dt.Rows.Count > 0)
{
foreach(DataRow row in dt.Rows)
{
var type = StringUtils.GetInt(row["type"]);
switch (type)
{
case 1://支出
{
var money = StringUtils.GetString(row["money"]);
this.lblNonoperatingOut.Text = money;
businessDic.Add("nonoperatingOut", money + "");
}
break;
case 2://收入
{
var money = StringUtils.GetString(row["money"]);
this.lblNonoperatingIn.Text = money;
businessDic.Add("nonoperatingIn", money + "");
}
break;
}
}
}
//**********营业外收支明细列表
totalAmount = 0.00M;
sql = @"select p.money, p.type, p.description, p.inputDate from pos_store_cost_revenue p where p.inputDate >= '{0}' and p.inputDate <= '{1}' order by p.inputDate;";
ds = SqliteUtils.Query(string.Format(sql, startTime, endTime), "data");
dt = ds.Tables["data"];
foreach(DataRow row in dt.Rows)
{
var money = StringUtils.GetDecimal(row["money"]);
totalAmount += StringUtils.GetInt(row["type"]) == 1 ? money * -1 : money;
nonoperatingList.Add(new Tuple<string, string, string>(row["description"] + "", row["money"] + "", row["inputDate"] + ""));
}
totalRow = dt.NewRow();
totalRow["description"] = LangProxy.ToLang("小计");
totalRow["money"] = StringUtils.FormatDataNoDigit(totalAmount);
nonoperatingList.Add(new Tuple<string, string, string>(totalRow["description"] + "", totalRow["money"] + "", string.Empty));
dt.Rows.Add(totalRow);
nonoperatingGrid.PrimaryGrid.DataSource = dt;
#endregion
#region 卡务统计
decimal cardChargeMoney = 0.00M;
int cardChargeCount = 0;
//充值统计
sql = @"select round(sum(money),2) as cardRealMoney ,count(1) as cardCount from pos_card_recharge where rechargeStatus = 2 and createDate >= '{0}' and createDate <= '{1}';";
ds = SqliteUtils.Query(string.Format(sql, startTime, endTime), "data");
dt = ds.Tables["data"];
if (dt.Rows.Count > 0)
{
var data = dt.Rows[0];
var money = StringUtils.GetDecimal(data["cardRealMoney"]);
cardChargeMoney += money;
var cardCount = StringUtils.GetInt(data["cardCount"]);
cardChargeCount += cardCount;
}
sql = @"select round(sum(money),2) as cardRealMoney ,count(1) as cardCount from pos_card_sale where payStatus = 1 and createDate >= '{0}' and createDate <= '{1}';";
ds = SqliteUtils.Query(string.Format(sql, startTime, endTime), "data");
dt = ds.Tables["data"];
if (dt.Rows.Count > 0)
{
var data = dt.Rows[0];
var money = StringUtils.GetDecimal(data["cardRealMoney"]);
cardChargeMoney += money;
var cardCount = StringUtils.GetInt(data["cardCount"]);
cardChargeCount += cardCount;
}
businessDic.Add("cardRealMoney",string.Format("{0}", cardChargeMoney));
businessDic.Add("cardCount", string.Format("{0}", cardChargeCount));
this.lblCardChargeMoney.Text = string.Format("{0}", cardChargeMoney);
this.lblCardChargeCount.Text = string.Format("{0}", cardChargeCount);
//退卡统计
decimal cardDestroyMoney = 0.00M;
int cardDestroyCount = 0;
sql = @"select round(sum(refundMoney),2) as cardRefundMoney ,count(id) as cardRefundCount from pos_card_account_destroy where createDate >= '{0}' and createDate <= '{1}';";
ds = SqliteUtils.Query(string.Format(sql, startTime, endTime), "data");
dt = ds.Tables["data"];
if (dt.Rows.Count > 0)
{
var data = dt.Rows[0];
var money = StringUtils.GetDecimal(data["cardRefundMoney"]);
cardDestroyMoney += money;
var cardCount = StringUtils.GetInt(data["cardRefundCount"]);
cardDestroyCount += cardCount;
}
sql = @"select round(sum(money),2) as cardRefundMoney ,count(1) as cardRefundCount from pos_card_sale where payStatus = 2 and createDate >= '{0}' and createDate <= '{1}';";
ds = SqliteUtils.Query(string.Format(sql, startTime, endTime), "data");
dt = ds.Tables["data"];
if (dt.Rows.Count > 0)
{
var data = dt.Rows[0];
var money = StringUtils.GetDecimal(data["cardRefundMoney"]);
cardDestroyMoney += money;
var cardCount = StringUtils.GetInt(data["cardRefundCount"]);
cardDestroyCount += cardCount;
}
businessDic.Add("cardRefundMoney", string.Format("{0}", cardDestroyMoney));
businessDic.Add("cardRefundCount", string.Format("{0}", cardDestroyCount));
this.lblCardDestroyMoney.Text = string.Format("{0}", cardDestroyMoney);
this.lblCardDestroyCount.Text = string.Format("{0}", cardDestroyCount);
#endregion
//溢收明细
#region 溢收明细
totalAmount = 0.00M;
sql = @"select p.overAmount, p.tradeNo, p.finishDate from pos_order_pay p
inner join pos_order r on p.tradeNo = r.tradeNo
where r.orderStatus in (0,2,4) and p.overAmount != 0 and p.finishDate >= '{0}' and p.finishDate <= '{1}' order by p.finishDate;";
ds = SqliteUtils.Query(string.Format(sql, startTime, endTime), "data");
dt = ds.Tables["data"];
foreach (DataRow row in dt.Rows)
{
totalAmount += StringUtils.GetDecimal(row["overAmount"]);
overAmountList.Add(new Tuple<string, string>(row["tradeNo"] + "", row["overAmount"] + ""));
}
totalRow = dt.NewRow();
totalRow["tradeNo"] = LangProxy.ToLang("小计");
totalRow["overAmount"] = StringUtils.FormatDataNoDigit(totalAmount);
overAmountList.Add(new Tuple<string, string>(totalRow["tradeNo"] + "", totalRow["overAmount"] + ""));
dt.Rows.Add(totalRow);
overDetailGrid.PrimaryGrid.DataSource = dt;
#endregion
//**********收银方式汇总
#region 收银方式汇总
totalAmount = 0.00M;
totalNum = 0.00M;
sql = @"select p.[no], p.name, sum(case when r.orderStatus == 2 then -1 else 1 end) as orderNum, cast(round(sum(p.amount),2) as text) as amount from pos_order_pay p
inner join pos_order r on p.tradeNo = r.tradeNo
where r.orderStatus in (0,2,4) and p.finishDate >= '{0}' and p.finishDate <= '{1}' group by p.[no];";
ds = SqliteUtils.Query(string.Format(sql, startTime, endTime), "data");
dt = ds.Tables["data"];
foreach (DataRow row in dt.Rows)
{
totalAmount += StringUtils.GetDecimal(row["amount"]);
totalNum += StringUtils.GetDecimal(row["orderNum"]);
}
//增加占比
dt.Columns.Add(new DataColumn("amountRatio"));
foreach(DataRow row in dt.Rows)
{
if(totalAmount > 0)
{
row["amountRatio"] = StringUtils.FormatDataTwoDigit(StringUtils.GetDecimal(row["amount"]) / totalAmount * 100) + "%";
}
else
{
row["amountRatio"] = "0%";
}
payWayList.Add(new Tuple<string, string, string, string>(row["name"] + "", row["orderNum"] + "", row["amount"] + "", row["amountRatio"] + ""));
}
totalRow = dt.NewRow();
totalRow["name"] = LangProxy.ToLang("小计");
totalRow["amount"] = StringUtils.FormatDataNoDigit(totalAmount);
totalRow["orderNum"] = StringUtils.FormatDataNoDigit(totalNum);
payWayList.Add(new Tuple<string, string, string, string>(totalRow["name"] + "", totalRow["orderNum"] + "", totalRow["amount"] + "", string.Empty));
dt.Rows.Add(totalRow);
payWayGrid.PrimaryGrid.DataSource = dt;
#endregion
//**********订单营业模式汇总统计
#region 营业模式汇总统计
totalAmount = 0.00M;
totalNum = 0.00M;
sql = @"select p.orderType, sum(case when p.orderStatus == 2 then -1 else 1 end) as orderNum, cast(sum(p.paidAmount) as text) as paidAmount from pos_order p
where p.orderStatus in (0,2,4) and p.finishDate >= '{0}' and p.finishDate <= '{1}' group by p.orderType;";
ds = SqliteUtils.Query(string.Format(sql, startTime, endTime), "data");
dt = ds.Tables["data"];
//转换营业模式名称
dt.Columns.Add(new DataColumn("typeName"));
foreach (DataRow row in dt.Rows)
{
var orderType = StringUtils.GetString(row["orderType"]);
var type = (OrderType)Enum.Parse(typeof(OrderType), orderType);
row["typeName"] = type.ToString();
totalAmount += StringUtils.GetDecimal(row["paidAmount"]);
totalNum += StringUtils.GetDecimal(row["orderNum"]);
}
//增加单均、占比
dt.Columns.Add(new DataColumn("averageOrder"));
dt.Columns.Add(new DataColumn("amountRatio"));
foreach (DataRow row in dt.Rows)
{
var orderNum = StringUtils.GetDecimal(row["orderNum"]);
var paidAmount = StringUtils.GetDecimal(row["paidAmount"]);
if (orderNum != 0.00M)
{
row["averageOrder"] = StringUtils.FormatDataNoDigit(paidAmount / orderNum);
}
if (totalAmount > 0)
{
row["amountRatio"] = StringUtils.FormatDataTwoDigit(StringUtils.GetDecimal(row["paidAmount"]) / totalAmount * 100) + "%";
}
else
{
row["amountRatio"] = "0%";
}
orderTypeList.Add(new Tuple<string, string, string, string, string>(row["typeName"] + "", row["orderNum"] + "", row["averageOrder"] + "", row["paidAmount"] + "", row["amountRatio"] + ""));
}
totalRow = dt.NewRow();
totalRow["typeName"] = LangProxy.ToLang("小计");
totalRow["paidAmount"] = StringUtils.FormatDataNoDigit(totalAmount);
totalRow["orderNum"] = StringUtils.FormatDataNoDigit(totalNum);
if (totalNum != 0.00M)
{
totalRow["averageOrder"] = StringUtils.FormatDataTwoDigit(totalAmount / totalNum);
}
orderTypeList.Add(new Tuple<string, string, string, string, string>(totalRow["typeName"] + "", totalRow["orderNum"] + "", totalRow["averageOrder"] + "", totalRow["paidAmount"] + "",string.Empty));
dt.Rows.Add(totalRow);
orderTypeGrid.PrimaryGrid.DataSource = dt;
#endregion
//*********分类汇总
#region 分类汇总
totalAmount = 0.00M;
var totalReceivableAmount = 0.00M;
var totalCount = 0.00M;
//2020-06-03 修改left join on 的条件原条件p.tradeNo = r.tradeNo
sql = @"select p.typeId, p.typeName, cast(sum(p.totalAmount) as text) as totalAmount, cast(sum(p.quantity - p.rquantity) as text) as quantity, cast(sum(p.totalReceivableAmount) as text) as totalReceivableAmount
from pos_order_item p
left join pos_order r on p.orderId = r.id
where r.orderStatus in (0,2,4) and p.isSuit != 3 and r.finishDate >= '{0}' and r.finishDate <= '{1}'
group by p.typeId order by sum(p.quantity - p.rquantity) desc;";
ds = SqliteUtils.Query(string.Format(sql, startTime, endTime), "data");
dt = ds.Tables["data"];
foreach (DataRow row in dt.Rows)
{
totalCount += StringUtils.GetDecimal(row["quantity"]);
totalAmount += StringUtils.GetDecimal(row["totalAmount"]);
totalReceivableAmount += StringUtils.GetDecimal(row["totalReceivableAmount"]);
}
//增加占比
dt.Columns.Add(new DataColumn("amountRatio"));
foreach (DataRow row in dt.Rows)
{
if (totalAmount > 0)
{
row["amountRatio"] = StringUtils.FormatDataTwoDigit(StringUtils.GetDecimal(row["totalReceivableAmount"]) / totalReceivableAmount * 100) + "%";
}
else
{
row["amountRatio"] = "0%";
}
categoryList.Add(new Tuple<string, string, string, string, string>(row["typeName"] + "", row["quantity"] + "", row["totalAmount"] + "", row["totalReceivableAmount"] + "", row["amountRatio"] + ""));
}
totalRow = dt.NewRow();
totalRow["typeName"] = LangProxy.ToLang("小计");
totalRow["quantity"] = StringUtils.FormatDataNoDigit(totalCount);
totalRow["totalAmount"] = StringUtils.FormatDataNoDigit(totalAmount);
totalRow["totalReceivableAmount"] = StringUtils.FormatDataNoDigit(totalReceivableAmount);
categoryList.Add(new Tuple<string, string, string, string, string>(totalRow["typeName"] + "", totalRow["quantity"] + "", totalRow["totalAmount"] + "", totalRow["totalReceivableAmount"] + "", string.Empty));
dt.Rows.Add(totalRow);
categoryGrid.PrimaryGrid.DataSource = dt;
#endregion
//分类排行
#region 分类排行
decimal finialtotalNum = 0.00M;
decimal finialtotalAmount = 0.00M;
decimal finialSuitQuantity = 0.00M;
decimal totalSuitQuantity = 0.00M;
totalNum = 0.00M;
totalAmount = 0.00M;
//2020-06-03 修改left join on 的条件原条件p.tradeNo = r.tradeNo
sql = @"select p.typeId, p.typeName, p.productName, p.specName, cast(sum(p.quantity - p.rquantity) as text) as quantity,
cast(sum(case when isSuit = 3 then p.quantity else 0 end) as text) as suitQuantity,
cast(round(sum(case when isSuit != 3 then p.totalReceivableAmount else 0 end),2) as text) as totalReceivableAmount
from pos_order_item p
left join pos_order r on p.orderId = r.id
where r.orderStatus in (0,2,4) and r.finishDate >= '{0}' and r.finishDate <= '{1}'
group by p.productId, p.specId
order by p.typeId, sum(p.quantity - p.rquantity) desc;";
ds = SqliteUtils.Query(string.Format(sql, startTime, endTime), "data");
dt = ds.Tables["data"];
dt.Columns.Add(new DataColumn("seq"));
string typeId = null;
int seq = 1;
DataTable newDt = dt.Clone();
foreach (DataRow row in dt.Rows)
{
var currentTypeId = StringUtils.GetString(row["typeId"]);
if (currentTypeId != typeId)
{
if(newDt.Rows.Count > 0)
{
//上一行的合计
totalRow = dt.NewRow();
totalRow["productName"] = LangProxy.ToLang("小计");
totalRow["quantity"] = StringUtils.FormatDataNoDigit(totalNum);
totalRow["totalReceivableAmount"] = StringUtils.FormatDataNoDigit(totalAmount);
totalRow["suitQuantity"] = StringUtils.FormatDataNoDigit(totalSuitQuantity);
categorySeqList.Add(new Tuple<string, string, string, string, string>(string.Empty, totalRow["productName"] + "", totalRow["quantity"] + "", totalRow["suitQuantity"] + "", totalRow["totalReceivableAmount"] + ""));
totalSuitQuantity = 0;
totalNum = 0;
totalAmount = 0;
newDt.Rows.Add(totalRow.ItemArray);
}
DataRow newRow = dt.NewRow();
newRow["productName"] = "★★" + StringUtils.GetString(row["typeName"]);
categorySeqList.Add(new Tuple<string, string, string, string, string>(string.Empty, newRow["productName"] + "", string.Empty, string.Empty, string.Empty));
newDt.Rows.Add(newRow.ItemArray);
seq = 1;
}
typeId = currentTypeId;
var quantity = StringUtils.GetDecimal(row["quantity"]);
totalNum += quantity;
finialtotalNum += quantity;
var suitQuantity = StringUtils.GetDecimal(row["suitQuantity"]);
totalSuitQuantity += suitQuantity;
finialSuitQuantity += suitQuantity;
var tempReceiveAmount = StringUtils.GetDecimal(row["totalReceivableAmount"]);
totalAmount += tempReceiveAmount;
finialtotalAmount += tempReceiveAmount;
row["seq"] = seq + "";
row["productName"] = Convert.ToString(row["productName"]) + (string.IsNullOrEmpty(Convert.ToString(row["specName"])) ? "" : string.Format("({0})", Convert.ToString(row["specName"])));
newDt.Rows.Add(row.ItemArray);
seq++;
categorySeqList.Add(new Tuple<string, string, string, string, string>(row["seq"] + "", row["productName"] + "", row["quantity"] + "", row["suitQuantity"] + "", row["totalReceivableAmount"] + ""));
}
totalRow = dt.NewRow();
totalRow["productName"] = LangProxy.ToLang("小计");
totalRow["quantity"] = StringUtils.FormatDataNoDigit(totalNum);
totalRow["totalReceivableAmount"] = StringUtils.FormatDataNoDigit(totalAmount);
totalRow["suitQuantity"] = StringUtils.FormatDataNoDigit(totalSuitQuantity);
categorySeqList.Add(new Tuple<string, string, string, string, string>(string.Empty, totalRow["productName"] + "", totalRow["quantity"] + "", totalRow["suitQuantity"] + "", totalRow["totalReceivableAmount"] + ""));
newDt.Rows.Add(totalRow.ItemArray);
totalRow = dt.NewRow();
totalRow["productName"] = "Σ合计";
totalRow["quantity"] = StringUtils.FormatDataNoDigit(finialtotalNum);
totalRow["totalReceivableAmount"] = StringUtils.FormatDataNoDigit(finialtotalAmount);
totalRow["suitQuantity"] = StringUtils.FormatDataNoDigit(finialSuitQuantity);
categorySeqList.Add(new Tuple<string, string, string, string, string>(string.Empty, totalRow["productName"] + "", totalRow["quantity"] + "", totalRow["suitQuantity"] + "", totalRow["totalReceivableAmount"] + ""));
newDt.Rows.Add(totalRow.ItemArray);
categorySeqGrid.PrimaryGrid.DataSource = newDt;
#endregion
}
catch (Exception ex)
{
LOGGER.Error(ex, "日营业报表查询异常");
}
}
private void OnDateClick(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;
OnQueryClick(sender, e);
}
private void OnPrintClick(object sender, EventArgs e)
{
var vars = new List<Printer.VariableValue>();
//系统变量
var data = new Dictionary<string, string>();
data.Add("@门店名称@", Global.Instance.Worker.StoreInfo.PrintName);
data.Add("@门店编码@", Global.Instance.Worker.StoreInfo.No);
data.Add("@收银员编码@", Global.Instance.Worker.No);
data.Add("@收银员名称@", Global.Instance.Worker.Name);
data.Add("@打印时间@", DateTimeUtils.GetNowFormat());
data.Add("@开始时间@", startTime);
data.Add("@结束时间@", endTime);
//综合数据
List<Dictionary<string, string>> dataList = new List<Dictionary<string, string>>();
foreach(var temp in businessDic.Keys)
{
var dic = new Dictionary<string, string>();
dic.Add("@数值@", businessDic[temp]);
switch (temp)
{
case "peopleNum":
{
dic.Add("@名称@", "客流");
}
break;
case "orderNum":
{
dic.Add("@名称@", "单数");
}
break;
case "amount":
{
dic.Add("@名称@", "流水");
}
break;
case "discountAmount":
{
dic.Add("@名称@", "优惠");
}
break;
case "malingAmount":
{
dic.Add("@名称@", "抹零");
}
break;
case "paidAmount":
{
dic.Add("@名称@", "实收");
}
break;
case "peopleAverage":
{
dic.Add("@名称@", "人均");
}
break;
case "orderAverage":
{
dic.Add("@名称@", "单均");
}
break;
case "refundAmount":
{
dic.Add("@名称@", "退款金额");
}
break;
case "overAmount":
{
dic.Add("@名称@", "溢收合计");
}
break;
case "nonoperatingOut":
{
dic.Add("@名称@", "营业外支");
}
break;
case "nonoperatingIn":
{
dic.Add("@名称@", "营业外收");
}
break;
case "cardCount":
{
dic.Add("@名称@", "充值笔数");
}
break;
case "cardRealMoney":
{
dic.Add("@名称@", "卡充金额");
}
break;
case "cardRefundCount":
{
dic.Add("@名称@", "退卡次数");
}
break;
case "cardRefundMoney":
{
dic.Add("@名称@", "退卡金额");
}
break;
}
if(dic.ContainsKey("@名称@"))
{
dataList.Add(dic);
}
}
vars.Add(new Printer.VariableValue() { Key = "综合数据", DataType = Printer.DataType.List, Value = JsonUtils.Serialize(dataList) });
//营业外收支明细
if (this.printNonoperatingChk.Checked)
{
dataList = new List<Dictionary<string, string>>();
foreach (var temp in nonoperatingList)
{
var dic = new Dictionary<string, string>();
dic.Add("@名称@", temp.Item1);
dic.Add("@金额@", temp.Item2);
dic.Add("@时间@", temp.Item3);
dataList.Add(dic);
}
vars.Add(new Printer.VariableValue() { Key = "营业外收支明细", DataType = Printer.DataType.List, Value = JsonUtils.Serialize(dataList) });
}
else
{
data.Add("@是否打印非营业收支@", "false");
}
//溢收数据
if (this.printOverChk.Checked)
{
dataList = new List<Dictionary<string, string>>();
foreach (var temp in overAmountList)
{
var dic = new Dictionary<string, string>();
dic.Add("@订单@", temp.Item1);
dic.Add("@金额@", temp.Item2);
dataList.Add(dic);
}
vars.Add(new Printer.VariableValue() { Key = "溢收数据", DataType = Printer.DataType.List, Value = JsonUtils.Serialize(dataList) });
}
else
{
data.Add("@是否打印溢收明细@", "false");
}
//优惠数据
if (this.printPromotionChk.Checked)
{
dataList = new List<Dictionary<string, string>>();
foreach (var temp in promotionList)
{
var dic = new Dictionary<string, string>();
dic.Add("@名称@", temp.Item1);
dic.Add("@数量@", temp.Item2);
dic.Add("@金额@", temp.Item3);
dic.Add("@占比@", temp.Item4);
dataList.Add(dic);
}
vars.Add(new Printer.VariableValue() { Key = "优惠数据", DataType = Printer.DataType.List, Value = JsonUtils.Serialize(dataList) });
}
else
{
data.Add("@是否打印优惠统计@", "false");
}
//订单类型数据
if (this.printOrderTypeChk.Checked)
{
dataList = new List<Dictionary<string, string>>();
foreach (var temp in orderTypeList)
{
var dic = new Dictionary<string, string>();
dic.Add("@名称@", temp.Item1);
dic.Add("@单数@", temp.Item2);
dic.Add("@单均@", temp.Item3);
dic.Add("@实收金额@", temp.Item4);
dic.Add("@占比@", temp.Item5);
dataList.Add(dic);
}
vars.Add(new Printer.VariableValue() { Key = "订单类型数据", DataType = Printer.DataType.List, Value = JsonUtils.Serialize(dataList) });
}
else
{
data.Add("@是否打印订单类型@", "false");
}
//收银方式数据
if (this.printPayWayChk.Checked)
{
dataList = new List<Dictionary<string, string>>();
foreach (var temp in payWayList)
{
var dic = new Dictionary<string, string>();
dic.Add("@名称@", temp.Item1);
dic.Add("@数量@", temp.Item2);
dic.Add("@金额@", temp.Item3);
dic.Add("@占比@", temp.Item4);
dataList.Add(dic);
}
vars.Add(new Printer.VariableValue() { Key = "收银方式数据", DataType = Printer.DataType.List, Value = JsonUtils.Serialize(dataList) });
}
else
{
data.Add("@是否打印收银方式@", "false");
}
//分类排行数据
if (this.printCategorySeqChk.Checked)
{
dataList = new List<Dictionary<string, string>>();
foreach (var temp in categorySeqList)
{
var dic = new Dictionary<string, string>();
dic.Add("@序号@", temp.Item1);
dic.Add("@名称@", temp.Item2);
dic.Add("@总销量@", temp.Item3);
dic.Add("@套餐量@", temp.Item4);
dic.Add("@金额@", temp.Item5);
dataList.Add(dic);
if (temp.Item2 == LangProxy.ToLang("小计") && temp != categorySeqList[categorySeqList.Count - 2])
{
var emptyDic = new Dictionary<string, string>();
emptyDic.Add("@序号@", "");
emptyDic.Add("@名称@", "");
emptyDic.Add("@总销量@", "");
emptyDic.Add("@套餐量@", "");
emptyDic.Add("@金额@", "");
dataList.Add(emptyDic);
}
}
vars.Add(new Printer.VariableValue() { Key = "分类排行数据", DataType = Printer.DataType.List, Value = JsonUtils.Serialize(dataList) });
}
else
{
data.Add("@是否打印分类排行@", "false");
}
//分类汇总列表
if (this.printCategoryChk.Checked)
{
dataList = new List<Dictionary<string, string>>();
foreach (var temp in categoryList)
{
var dic = new Dictionary<string, string>();
dic.Add("@名称@", temp.Item1);
dic.Add("@数量@", temp.Item2);
dic.Add("@销售金额@", temp.Item3);
dic.Add("@实收金额@", temp.Item4);
dic.Add("@占比@", temp.Item5);
dataList.Add(dic);
}
vars.Add(new Printer.VariableValue() { Key = "分类汇总列表", DataType = Printer.DataType.List, Value = JsonUtils.Serialize(dataList) });
}
else
{
data.Add("@是否打印商品分类@", "false");
}
vars.Add(new Printer.VariableValue() { Key = "默认数据源", DataType = Printer.DataType.Simple, Value = JsonUtils.Serialize(data) });
this.ShowToastNotify(this, "开始打印");
//构建收银小票模版参数
Tuple<bool, string> result = ReportHelper.PrinterTicket("营业日报", vars, true, false);
this.ShowToastNotify(this, string.Format("{0}", result.Item2));
}
private void OnExitClick(object sender, EventArgs e)
{
OnCloseClick(sender, e);
}
private void OnControlBoxMinClick(object sender, EventArgs e)
{
this.WindowState = FormWindowState.Minimized;
}
private void OnCloseClick(object sender, EventArgs e)
{
//先关闭父窗体
if (this.Owner != null)
{
this.Owner.Close();
}
//再关闭当前窗体
this.Close();
}
private void OnExportClick(object sender, EventArgs e)
{
SaveFileDialog fileDialog = new SaveFileDialog();
fileDialog.Title = "请选择文件保存位置";
fileDialog.FileName = "营业报告.xls";
fileDialog.Filter = "Excel文件|*.xls";
fileDialog.FilterIndex = 1;
fileDialog.RestoreDirectory = true;
if (fileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
string path = fileDialog.FileName;
WaitWindow.Show(this.ExcelExportMethod, "数据导出中....", new object[] { path, false });
}
}
private void ExcelExportMethod(object sender, WaitWindowEventArgs e)
{
try
{
string filePath = e.Arguments[0].ToString();
com.azkoss.excellite.CellStyle headStyle = new com.azkoss.excellite.CellStyle();
headStyle.VerticalAlignment = com.azkoss.excellite.VerticalAlignmentStyle.Center;
headStyle.HorizontalAlignment = com.azkoss.excellite.HorizontalAlignmentStyle.Center;
headStyle.FillPattern.SetSolid(Color.LightGray);
headStyle.Font.Weight = ExcelFont.BoldWeight;
headStyle.Font.Color = Color.Black;
com.azkoss.excellite.CellStyle cellStyle = new com.azkoss.excellite.CellStyle();
cellStyle.VerticalAlignment = com.azkoss.excellite.VerticalAlignmentStyle.Center;
cellStyle.HorizontalAlignment = com.azkoss.excellite.HorizontalAlignmentStyle.Center;
cellStyle.Font.Color = Color.Black;
ExcelFile excelFile = new ExcelFile();
ExcelWorksheet sheet = excelFile.Worksheets.Add("营业总报表");
int row = 0;
//销售总计
sheet.Rows[row].Height = 18 * 20;
sheet.Cells[row, 0].Style = headStyle;
sheet.Cells[row, 0].Value = "销售总计";
sheet.Cells[row, 1].Style = headStyle;
sheet.Cells[row, 1].Value = "";
foreach (var key in businessDic.Keys)
{
row = row + 1;
sheet.Rows[row].Height = 18 * 20;
string val = businessDic[key];
switch (key)
{
case "peopleNum":
{
sheet.Cells[row, 0].Style = cellStyle;
sheet.Cells[row, 0].Value = "客流";
}
break;
case "orderNum":
{
sheet.Cells[row, 0].Style = cellStyle;
sheet.Cells[row, 0].Value = "单数";
}
break;
case "amount":
{
sheet.Cells[row, 0].Style = cellStyle;
sheet.Cells[row, 0].Value = "流水";
}
break;
case "discountAmount":
{
sheet.Cells[row, 0].Style = cellStyle;
sheet.Cells[row, 0].Value = "优惠";
}
break;
case "malingAmount":
{
sheet.Cells[row, 0].Style = cellStyle;
sheet.Cells[row, 0].Value = "抹零";
}
break;
case "paidAmount":
{
sheet.Cells[row, 0].Style = cellStyle;
sheet.Cells[row, 0].Value = "实收";
}
break;
case "peopleAverage":
{
sheet.Cells[row, 0].Style = cellStyle;
sheet.Cells[row, 0].Value = "人均";
}
break;
case "orderAverage":
{
sheet.Cells[row, 0].Style = cellStyle;
sheet.Cells[row, 0].Value = "单均";
}
break;
case "refundAmount":
{
sheet.Cells[row, 0].Style = cellStyle;
sheet.Cells[row, 0].Value = "退款金额";
}
break;
case "overAmount":
{
sheet.Cells[row, 0].Style = cellStyle;
sheet.Cells[row, 0].Value = "溢收合计";
}
break;
case "nonoperatingOut":
{
sheet.Cells[row, 0].Style = cellStyle;
sheet.Cells[row, 0].Value = "营业外支";
}
break;
case "nonoperatingIn":
{
sheet.Cells[row, 0].Style = cellStyle;
sheet.Cells[row, 0].Value = "营业外收";
}
break;
case "cardCount":
{
sheet.Cells[row, 0].Style = cellStyle;
sheet.Cells[row, 0].Value = "充值笔数";
}
break;
case "cardRealMoney":
{
sheet.Cells[row, 0].Style = cellStyle;
sheet.Cells[row, 0].Value = "卡充金额";
}
break;
case "cardRefundCount":
{
sheet.Cells[row, 0].Style = cellStyle;
sheet.Cells[row, 0].Value = "退卡次数";
}
break;
case "cardRefundMoney":
{
sheet.Cells[row, 0].Style = cellStyle;
sheet.Cells[row, 0].Value = "退卡金额";
}
break;
}
sheet.Cells[row, 1].Style = cellStyle;
sheet.Cells[row, 1].Value = val;
}
row = row + 2;
//付款列表
if (payWayList != null)
{
sheet.Rows[row].Height = 18 * 20;
sheet.Cells[row, 0].Style = headStyle;
sheet.Cells[row, 0].Value = "名称";
sheet.Cells[row, 1].Style = headStyle;
sheet.Cells[row, 1].Value = "订单数";
sheet.Cells[row, 2].Style = headStyle;
sheet.Cells[row, 2].Value = "销售额";
sheet.Cells[row, 3].Style = headStyle;
sheet.Cells[row, 3].Value = "占比";
foreach (var pay in payWayList)
{
row = row + 1;
sheet.Rows[row].Height = 18 * 20;
sheet.Cells[row, 0].Style = cellStyle;
sheet.Cells[row, 0].Value = pay.Item1;
sheet.Cells[row, 1].Style = cellStyle;
sheet.Cells[row, 1].Value = pay.Item2;
sheet.Cells[row, 2].Style = cellStyle;
sheet.Cells[row, 2].Value = pay.Item3;
sheet.Cells[row, 3].Style = cellStyle;
sheet.Cells[row, 3].Value = pay.Item4;
}
//空白行
if(payWayList.Count > 0)
{
row = row + 2;
}
}
//类别排行
if (categorySeqList != null)
{
sheet.Rows[row].Height = 18 * 20;
sheet.Cells[row, 0].Style = headStyle;
sheet.Cells[row, 0].Value = "名称";
sheet.Cells[row, 1].Style = headStyle;
sheet.Cells[row, 1].Value = "数量";
sheet.Cells[row, 2].Style = headStyle;
sheet.Cells[row, 2].Value = "毛销售额";
foreach (var category in categorySeqList)
{
row = row + 1;
sheet.Rows[row].Height = 18 * 20;
sheet.Cells[row, 0].Style = cellStyle;
sheet.Cells[row, 0].Value = category.Item2;
sheet.Cells[row, 1].Style = cellStyle;
sheet.Cells[row, 1].Value = category.Item3;
sheet.Cells[row, 2].Style = cellStyle;
sheet.Cells[row, 2].Value = category.Item5;
}
}
excelFile.SaveXls(filePath);
LOGGER.Info("导出数据到Excel文件成功");
}
catch (Exception ex)
{
LOGGER.Error(ex, "导出到Excel发生异常");
}
finally
{
}
}
}
}