400 lines
12 KiB
C#
400 lines
12 KiB
C#
using Newtonsoft.Json;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
|
||
namespace _29WxOrderWpf.Ctrls.Statistics.Models
|
||
{
|
||
/// <summary>
|
||
/// 店铺营收统计 - 查询参数
|
||
/// </summary>
|
||
public class ShopRevenueStatisticsQuery
|
||
{
|
||
/// <summary>开始时间</summary>
|
||
public DateTime StartDate { get; set; }
|
||
|
||
/// <summary>结束时间</summary>
|
||
public DateTime EndDate { get; set; }
|
||
|
||
/// <summary>选中的店铺 app_key 列表;空/Null 表示全部店铺</summary>
|
||
public List<string> ShopKeys { get; set; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// 店铺营收统计 - 接口返回的原始明细行。
|
||
/// 与后端 WXOrderAmountInfo 保持一致(camelCase JSON):
|
||
/// shopName, createTime, orderId, status, productPrice, orderPrice, purchasePrice, freight,
|
||
/// predictCommissionFee, commissionAmount, discountedPrice, profit, purchaseStatus,
|
||
/// outAmount, refundStatus, refundStatusString, refundAmount, externalProcurement
|
||
/// 金额字段单位均为分(显示时需除以 100)。
|
||
/// </summary>
|
||
public class ShopRevenueStatisticsRow
|
||
{
|
||
/// <summary>
|
||
/// 店铺名称
|
||
/// </summary>
|
||
[JsonProperty("shop_name")]
|
||
public string ShopName { get; set; }
|
||
|
||
/// <summary>
|
||
/// 下单时间(秒级时间戳)
|
||
/// </summary>
|
||
[JsonProperty("create_time")]
|
||
[JsonConverter(typeof(UnixDateTimeConverter))]
|
||
public DateTime CreateTime { get; set; }
|
||
|
||
/// <summary>
|
||
/// 订单号
|
||
/// </summary>
|
||
[JsonProperty("order_id")]
|
||
public string OrderId { get; set; }
|
||
|
||
/// <summary>
|
||
/// 订单状态
|
||
/// </summary>
|
||
[JsonProperty("status")]
|
||
public int Status { get; set; }
|
||
|
||
/// <summary>
|
||
/// 商品总价(分)
|
||
/// </summary>
|
||
[JsonProperty("product_price")]
|
||
public int ProductPrice { get; set; }
|
||
|
||
/// <summary>
|
||
/// 订单金额(分)
|
||
/// </summary>
|
||
[JsonProperty("order_price")]
|
||
public int OrderPrice { get; set; }
|
||
|
||
/// <summary>
|
||
/// 采购价(分)
|
||
/// </summary>
|
||
[JsonProperty("purchase_price")]
|
||
public int PurchasePrice { get; set; }
|
||
|
||
/// <summary>
|
||
/// 运费(分)
|
||
/// </summary>
|
||
[JsonProperty("freight")]
|
||
public int Freight { get; set; }
|
||
|
||
/// <summary>
|
||
/// 平台服务费(预计技术服务费,分)
|
||
/// </summary>
|
||
[JsonProperty("predict_commission_fee")]
|
||
public int PredictCommissionFee { get; set; }
|
||
|
||
/// <summary>
|
||
/// 达人佣金(分)
|
||
/// </summary>
|
||
[JsonProperty("commission_amount")]
|
||
public int CommissionAmount { get; set; }
|
||
|
||
/// <summary>
|
||
/// 优惠金额(分)
|
||
/// </summary>
|
||
[JsonProperty("discounted_price")]
|
||
public int DiscountedPrice { get; set; }
|
||
|
||
/// <summary>
|
||
/// 利润(分)
|
||
/// </summary>
|
||
[JsonProperty("profit")]
|
||
public int Profit { get; set; }
|
||
|
||
/// <summary>
|
||
/// 采购状态
|
||
/// </summary>
|
||
[JsonProperty("purchase_status")]
|
||
public int PurchaseStatus { get; set; }
|
||
|
||
/// <summary>
|
||
/// 外采金额(分),out_amount为空或0时从中转仓订单表补全
|
||
/// </summary>
|
||
[JsonProperty("out_amount")]
|
||
public int OutAmount { get; set; }
|
||
|
||
/// <summary>
|
||
/// 售后状态(订单明细 refund_status)
|
||
/// </summary>
|
||
[JsonProperty("refund_status")]
|
||
public int RefundStatus { get; set; }
|
||
|
||
/// <summary>
|
||
/// 售后状态(退款单 status)
|
||
/// </summary>
|
||
[JsonProperty("refund_status_string")]
|
||
public string RefundStatusString { get; set; }
|
||
|
||
/// <summary>
|
||
/// 售后退款金额(分)
|
||
/// </summary>
|
||
[JsonProperty("refund_amount")]
|
||
public int RefundAmount { get; set; }
|
||
|
||
/// <summary>
|
||
/// 是否外采:0=未从中转仓订单表查到,1=查到
|
||
/// </summary>
|
||
[JsonProperty("external_procurement")]
|
||
public int ExternalProcurement { get; set; }
|
||
|
||
|
||
/// <summary>
|
||
/// 买手退款金额
|
||
/// </summary>
|
||
[JsonProperty("buyer_refund_amount")]
|
||
public int BuyerRefundAmount { get; set; }
|
||
|
||
/// <summary>
|
||
/// 买手退款状态
|
||
/// </summary>
|
||
[JsonProperty("buyer_refund_status")]
|
||
public string BuyerRefundStatus { get; set; }
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 顶部汇总卡片数据(金额单位:元)
|
||
/// </summary>
|
||
public class ShopRevenueSummary
|
||
{
|
||
/// <summary>销售额(最终有效销售额)</summary>
|
||
public decimal SalesAmount { get; set; }
|
||
/// <summary>有效订单数(已扣除退款订单)</summary>
|
||
public int ValidOrderCount { get; set; }
|
||
|
||
/// <summary>利润(实际利润)</summary>
|
||
public decimal Profit { get; set; }
|
||
|
||
/// <summary>退款金额(统计期间退款)</summary>
|
||
public decimal RefundAmount { get; set; }
|
||
|
||
/// <summary>退款订单数</summary>
|
||
public int RefundOrderCount { get; set; }
|
||
|
||
/// <summary>平台服务费总额(元)</summary>
|
||
public decimal PlatformFeeTotal { get; set; }
|
||
|
||
/// <summary>达人佣金(元)</summary>
|
||
public decimal Commission { get; set; }
|
||
|
||
/// <summary>客单价(平均每单金额)</summary>
|
||
public decimal AvgOrderAmount { get; set; }
|
||
|
||
/// <summary>退款率(退款订单占比,百分数,如 2.31 表示 2.31%)</summary>
|
||
public decimal RefundRate { get; set; }
|
||
|
||
/// <summary>平均利润率(利润 / 采购金额,百分数,如 12.34 表示 12.34%)</summary>
|
||
public decimal AverageProfitRate { get; set; }
|
||
/// <summary>买手号付款金额(采购金额,元)</summary>
|
||
public decimal BuyerPaymentAmount { get; set; }
|
||
|
||
/// <summary>买手号退款金额(采购退款金额,元)</summary>
|
||
public decimal BuyerRefundAmount { get; set; }
|
||
/// <summary>买手号退款成功金额(采购退款金额,元)</summary>
|
||
public decimal BuyerRefundSuccessedAmount { get; set; }
|
||
/// <summary>买手号剩余退款金额(尚未成功退款的金额,元)</summary>
|
||
public decimal BuyerRefundRemainingAmount => BuyerRefundAmount - BuyerRefundSuccessedAmount;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 销售趋势数据点(金额单位:元)
|
||
/// </summary>
|
||
public class RevenueTrendPoint
|
||
{
|
||
/// <summary>日期</summary>
|
||
public DateTime Date { get; set; }
|
||
|
||
/// <summary>日期文本(MM-dd)</summary>
|
||
public string DateText { get { return Date.ToString("MM-dd"); } }
|
||
|
||
/// <summary>当日销售额(元)</summary>
|
||
public decimal SalesAmount { get; set; }
|
||
|
||
/// <summary>当日有效订单数</summary>
|
||
public int OrderCount { get; set; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// 店铺销售占比数据(金额单位:元)
|
||
/// </summary>
|
||
public class ShopSalesProportionItem
|
||
{
|
||
/// <summary>店铺名称</summary>
|
||
public string ShopName { get; set; }
|
||
|
||
/// <summary>销售额(元)</summary>
|
||
public decimal SalesAmount { get; set; }
|
||
|
||
/// <summary>占比(0~100)</summary>
|
||
public double Percentage { get; set; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// 店铺统计表格行(金额单位:元)
|
||
/// </summary>
|
||
public class ShopStatisticsItem
|
||
{
|
||
/// <summary>店铺名称</summary>
|
||
public string ShopName { get; set; }
|
||
|
||
/// <summary>订单数</summary>
|
||
public int OrderCount { get; set; }
|
||
|
||
/// <summary>销售额(元)</summary>
|
||
public decimal SalesAmount { get; set; }
|
||
/// <summary>采购金额(元)</summary>
|
||
public decimal BuyerPaymentAmount { get; set; }
|
||
/// <summary>利润(元)</summary>
|
||
public decimal Profit { get; set; }
|
||
|
||
/// <summary>退款金额(元)</summary>
|
||
public decimal RefundAmount { get; set; }
|
||
|
||
/// <summary>平台服务费总额(元)</summary>
|
||
public decimal PlatformFeeTotal { get; set; }
|
||
|
||
/// <summary>达人佣金(元)</summary>
|
||
public decimal Commission { get; set; }
|
||
|
||
/// <summary>客单价(元)</summary>
|
||
public decimal AvgOrderAmount { get; set; }
|
||
|
||
/// <summary>平均利润率(利润 / 采购金额,百分数,如 12.34 表示 12.34%)</summary>
|
||
public decimal AverageProfitRate { get; set; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// 统计周期类型:天 / 周 / 月
|
||
/// </summary>
|
||
public enum PeriodStatisticType
|
||
{
|
||
/// <summary>按天统计</summary>
|
||
Day = 0,
|
||
|
||
/// <summary>按周统计(周一起始)</summary>
|
||
Week = 1,
|
||
|
||
/// <summary>按月统计</summary>
|
||
Month = 2
|
||
}
|
||
|
||
/// <summary>
|
||
/// 天/周/月周期统计表格行(金额单位:元)。
|
||
/// 按所选店铺(或全部店铺)统计:天统计每天一行;周统计每周一行;月统计每月一行。
|
||
/// </summary>
|
||
public class ShopPeriodStatisticsItem
|
||
{
|
||
/// <summary>周期开始日期(用于排序)</summary>
|
||
public DateTime PeriodStart { get; set; }
|
||
|
||
/// <summary>周期显示文本(天:yyyy-MM-dd;周:yyyy-MM-dd ~ yyyy-MM-dd;月:yyyy-MM)</summary>
|
||
public string Period { get; set; }
|
||
|
||
/// <summary>订单数</summary>
|
||
public int OrderCount { get; set; }
|
||
|
||
/// <summary>销售额(元)</summary>
|
||
public decimal SalesAmount { get; set; }
|
||
/// <summary>买手号付款金额(采购金额,元)</summary>
|
||
public decimal BuyerPaymentAmount { get; set; }
|
||
|
||
/// <summary>利润(元)</summary>
|
||
public decimal Profit { get; set; }
|
||
|
||
/// <summary>退款金额(元)</summary>
|
||
public decimal RefundAmount { get; set; }
|
||
|
||
/// <summary>平台服务费总额(元)</summary>
|
||
public decimal PlatformFeeTotal { get; set; }
|
||
|
||
/// <summary>达人佣金(元)</summary>
|
||
public decimal Commission { get; set; }
|
||
|
||
/// <summary>平均利润率(利润 / 采购金额,百分数,如 12.34 表示 12.34%)</summary>
|
||
public decimal AverageProfitRate { get; set; }
|
||
|
||
/// <summary>客户数</summary>
|
||
public int CustomerCount { get; set; }
|
||
|
||
/// <summary>客单价(元)</summary>
|
||
public decimal AvgOrderAmount { get; set; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// 店铺下拉选项
|
||
/// </summary>
|
||
public class ShopOption
|
||
{
|
||
/// <summary>店铺 app_key(A.app_key)</summary>
|
||
public string AppKey { get; set; }
|
||
public string ShopId { get; set; }
|
||
/// <summary>店铺名称</summary>
|
||
public string ShopName { get; set; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// 时间范围下拉选项
|
||
/// </summary>
|
||
public class TimeRangeOption
|
||
{
|
||
/// <summary>显示文本(如:今天、昨天、本周、本月、最近10天、自定义)</summary>
|
||
public string Text { get; set; }
|
||
|
||
/// <summary>值(today / yesterday / week / month / last10 / custom)</summary>
|
||
public string Value { get; set; }
|
||
}
|
||
|
||
class UnixDateTimeConverter : JsonConverter
|
||
{
|
||
public override bool CanConvert(Type objectType)
|
||
{
|
||
return objectType == typeof(DateTime);
|
||
}
|
||
|
||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||
{
|
||
// 读取数值(支持 long 和 int 类型)
|
||
if (reader.TokenType == JsonToken.Integer)
|
||
{
|
||
long milliseconds = (long)reader.Value;
|
||
// Unix 纪元:1970-01-01 UTC
|
||
//DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
||
DateTime epoch = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
|
||
if (milliseconds.ToString().Length == 13)
|
||
{
|
||
return epoch.AddMilliseconds(milliseconds);
|
||
}
|
||
return epoch.AddSeconds(milliseconds);
|
||
|
||
|
||
}
|
||
// 如果传入的是字符串(如 "1700000000000"),也支持
|
||
else if (reader.TokenType == JsonToken.String)
|
||
{
|
||
if (long.TryParse((string)reader.Value, out long milliseconds))
|
||
{
|
||
//DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
||
DateTime epoch = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
|
||
if (milliseconds.ToString().Length == 13)
|
||
{
|
||
return epoch.AddMilliseconds(milliseconds);
|
||
}
|
||
return epoch.AddSeconds(milliseconds);
|
||
}
|
||
}
|
||
throw new JsonSerializationException($"无法将 {reader.Value} 转换为 DateTime");
|
||
}
|
||
|
||
|
||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||
{
|
||
// 序列化时转回时间戳
|
||
//DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
||
DateTime epoch = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
|
||
long milliseconds = (long)((DateTime)value - epoch).TotalMilliseconds;
|
||
writer.WriteValue(milliseconds);
|
||
}
|
||
}
|
||
}
|