更新 商铺统计利润算法
增加买手售后订单 增加备注
This commit is contained in:
1 parent
87e13e6544
commit
31b78e12b5
12 files changed
+208
-40
No files matched your search
@@ -1,4 +1,5 @@
|
||||
using KJD_Web.Services.Buyer;
|
||||
using KJD_Web.Requests.Buyers;
|
||||
using KJD_Web.Services.Buyer;
|
||||
using Store.Framework.Base;
|
||||
using Store.Framework.Dtos;
|
||||
using Store.Framework.Models;
|
||||
@@ -36,5 +37,25 @@ public class BuyerController : ApiControllerBase
|
||||
}
|
||||
return Ok(ret);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新买手订单售后备注
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public IHttpActionResult UpdateBuyerAfterRemark(BuyerAfterOrderRequest request)
|
||||
{
|
||||
ApiResultBase ret;
|
||||
try
|
||||
{
|
||||
var v = _buyerService.UpdateBuyerAfterRemark(request.UserName, request.id, request.Remark);
|
||||
ret = ApiResult.Success(v);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ret = ApiResult.Fail("更新失败");
|
||||
}
|
||||
return Ok(ret);
|
||||
}
|
||||
}
|
||||
@@ -220,6 +220,7 @@
|
||||
<Compile Include="Model\WxModel\oms_wei_transfer_extra_package.cs" />
|
||||
<Compile Include="Model\WxModel\ShopRevenueStatistics.cs" />
|
||||
<Compile Include="Model\WxModel\yh_sync_logistics.cs" />
|
||||
<Compile Include="Requests\Buyers\BuyerAfterOrderRequest.cs" />
|
||||
<Compile Include="Requests\RequestBase.cs" />
|
||||
<Compile Include="Requests\ShopRequest.cs" />
|
||||
<Compile Include="Requests\Shops\ShopOrderDetailType.cs" />
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using KJD_Web.Utils;
|
||||
using KJD_Web.Services.Shops;
|
||||
using KJD_Web.Utils;
|
||||
using MySqlX.XDevAPI.Relational;
|
||||
using Store.Contracts.Order.Entitys;
|
||||
using System;
|
||||
@@ -24,9 +25,16 @@ public class ShopRevenueStatistics
|
||||
public string ShopName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 外采金额(单位:分,整数存储)
|
||||
/// 外采金额(单位:分,整数存储) 最后一次购买的商品金额
|
||||
/// </summary>
|
||||
public int OutAmount => BuyerOrders.Sum(a => a.OutAmount);
|
||||
public int OutAmount
|
||||
{
|
||||
get
|
||||
{
|
||||
if (BuyerOrders == null || BuyerOrders.Count == 0) return 0;
|
||||
return BuyerOrders.Last().OutAmount;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 订单金额,单位为分,
|
||||
/// </summary>
|
||||
@@ -178,6 +186,8 @@ public class ShopRevenueStatistics
|
||||
/// </summary>
|
||||
public string RefundStatusText { get; set; }
|
||||
|
||||
public string Remark { get; set; }
|
||||
public DateTime CreateTime { get; set; }
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
using Store.Framework.Dtos;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
|
||||
namespace KJD_Web.Requests.Buyers;
|
||||
|
||||
public class BuyerAfterOrderRequest : SignRequestBase
|
||||
{
|
||||
public int id { get; set; }
|
||||
public string Remark { get; set; }
|
||||
}
|
||||
@@ -24,4 +24,8 @@ public enum ShopOrderDetailType
|
||||
/// 买手未退回金额的订单:退款订单中买手款项还没退回的(对应统计里的未退回金额口径)
|
||||
/// </summary>
|
||||
BuyerUnrefunded = 3,
|
||||
/// <summary>
|
||||
/// 利润订单 有效订单+退款订单利润>0
|
||||
/// </summary>
|
||||
Profit = 4,
|
||||
}
|
||||
@@ -45,7 +45,17 @@ public class ShopOrderDetailResponse
|
||||
public int OrderRefundAmount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 外采金额(分),即该订单下所有买手订单的购买金额之和
|
||||
/// 利润
|
||||
/// </summary>
|
||||
public long ProfitAmount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 平台佣金
|
||||
/// </summary>
|
||||
public long PlatformFee { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 外采金额(分),即该订单下所有买手订单的最后一单的商品金额
|
||||
/// </summary>
|
||||
public int OutAmount { get; set; }
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ using Store.Contracts.User.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
|
||||
namespace KJD_Web.Services.Buyer;
|
||||
@@ -49,4 +50,30 @@ public class BuyerService : ITransientDependency
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/// <summary>
|
||||
/// 更新买手售后订单备注
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="remark"></param>
|
||||
public bool UpdateBuyerAfterRemark(string userName, long id, string remark)
|
||||
{
|
||||
var item = _freeSql.Select<OrderPddBuyerAfterSaleEntity>()
|
||||
.Where(a => a.Id == id)
|
||||
.First();
|
||||
if (item == null) return false;
|
||||
|
||||
var shopId = _freeSql.Select<WeiOrderEntity>()
|
||||
.Where(a => a.OrderId == item.WxOrderId)
|
||||
.ToOne(a => a.ShopId);
|
||||
var ret = _shopService.IsShopOwnedByUser(shopId, userName);
|
||||
if (ret == true)
|
||||
{
|
||||
var affrows = _freeSql.Update<OrderPddBuyerAfterSaleEntity>()
|
||||
.Set(a => a.Remark, remark)
|
||||
.Where(a => a.Id == id)
|
||||
.ExecuteAffrows();
|
||||
return affrows == 1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -169,7 +169,11 @@ public class ShopRevenueStatisticsService : ITransientDependency
|
||||
public List<ShopOrderDetailResponse> GetShopOrderDetails(DateTime startTime, DateTime endTime, ShopOrderDetailType orderType = ShopOrderDetailType.All, string userName = null, List<string> shopIds = null)
|
||||
{
|
||||
var result = new List<ShopOrderDetailResponse>();
|
||||
startTime = startTime.Date;
|
||||
endTime = endTime.Date.AddDays(1).AddSeconds(-1);
|
||||
if (endTime < startTime) return result;
|
||||
if (endTime > startTime.AddMonths(3))
|
||||
throw new ArgumentException("时间范围不能超过3个月");
|
||||
|
||||
var ids = shopIds != null && shopIds.Count > 0 ? shopIds : getShopIdsByUserName(userName);
|
||||
if (ids == null || ids.Count == 0) return result;
|
||||
@@ -194,6 +198,7 @@ public class ShopRevenueStatisticsService : ITransientDependency
|
||||
// 加载买手订单(直拍和中转仓都要查),并回填商铺订单的退款金额
|
||||
LoadBuyerOrder(orders);
|
||||
FillRefunds(orders);
|
||||
CalcProfit(orders);
|
||||
|
||||
foreach (var order in orders)
|
||||
{
|
||||
@@ -215,6 +220,12 @@ public class ShopRevenueStatisticsService : ITransientDependency
|
||||
case ShopOrderDetailType.BuyerUnrefunded: // 买手未退回金额的订单
|
||||
if (!hasRefund || unrefundedAmount <= 0) continue;
|
||||
break;
|
||||
case ShopOrderDetailType.Profit: //利润订单 有效订单+ 退款订单利润大于>0
|
||||
if (hasRefund)
|
||||
{
|
||||
if (order.Profit <= 0) continue;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
@@ -226,6 +237,8 @@ public class ShopRevenueStatisticsService : ITransientDependency
|
||||
CreateTime = order.CreateTime,
|
||||
OrderPrice = order.OrderPrice,
|
||||
OrderRefundAmount = order.Items.Sum(a => a.RefundAmount),
|
||||
ProfitAmount = order.Profit,
|
||||
PlatformFee = order.HasRefund ? 0 : order.PredictCommissionFee,
|
||||
OutAmount = order.OutAmount,
|
||||
UnrefundedAmount = unrefundedAmount,
|
||||
BuyerOrders = buyerOrders,
|
||||
@@ -427,11 +440,12 @@ public class ShopRevenueStatisticsService : ITransientDependency
|
||||
{
|
||||
ShopDailyStats(item.Key, item.Value);
|
||||
}
|
||||
string log = $"更新统计:{item.Key.ToString("yyyy/MM/dd")} {item.Value.Count}条商铺";
|
||||
_logger.Info(log);
|
||||
Debug.WriteLine(log);
|
||||
}
|
||||
|
||||
string log = $"更新统计:{dict.Count}天数据";
|
||||
_logger.Info(log);
|
||||
Debug.WriteLine(log);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -541,6 +555,7 @@ public class ShopRevenueStatisticsService : ITransientDependency
|
||||
SkuId = a.OrderSkuId,
|
||||
OutOrderSn = a.OutOrderNo,
|
||||
OutAmount = a.OutAmount ?? 0,
|
||||
CreateTime = a.CreatedTime ?? DateTime.MinValue
|
||||
}));
|
||||
}
|
||||
}
|
||||
@@ -564,6 +579,7 @@ public class ShopRevenueStatisticsService : ITransientDependency
|
||||
SkuId = a.WxSkuId,
|
||||
OutOrderSn = a.OrderSn,
|
||||
OutAmount = a.OrderAmount ?? 0,
|
||||
CreateTime = a.AddTime,
|
||||
}));
|
||||
|
||||
}
|
||||
@@ -600,7 +616,8 @@ public class ShopRevenueStatisticsService : ITransientDependency
|
||||
OutOrderSn = a.OrderSn,
|
||||
OutAmount = a.OrderAmount ?? 0,
|
||||
RefundAmount = a.RefundAmount ?? (a.OrderAmount ?? 0),
|
||||
RefundStatusText = a.StatusText
|
||||
RefundStatusText = a.StatusText,
|
||||
Remark = a.Remark
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -616,6 +633,7 @@ public class ShopRevenueStatisticsService : ITransientDependency
|
||||
buyerOrder.RefundId = r.RefundId;
|
||||
buyerOrder.RefundAmount = r.RefundAmount;
|
||||
buyerOrder.RefundStatusText = r.RefundStatusText;
|
||||
buyerOrder.Remark = r.Remark;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -624,7 +642,7 @@ public class ShopRevenueStatisticsService : ITransientDependency
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
orders.Sort((a, b) => a.CreateTime.CompareTo(b.CreateTime));
|
||||
//移除未购买的订单
|
||||
for (int i = orders.Count - 1; i >= 0; i--)
|
||||
{
|
||||
@@ -680,11 +698,26 @@ public class ShopRevenueStatisticsService : ITransientDependency
|
||||
/// <param name="orders"></param>
|
||||
private static void CalcProfit(List<OrderInfo> orders)
|
||||
{
|
||||
long count = 0;
|
||||
foreach (var order in orders)
|
||||
{
|
||||
order.Profit = order.HasRefund
|
||||
? order.OrderPrice - order.Items.Sum(a => a.RefundAmount)
|
||||
: order.OrderPrice - order.OutAmount - order.PredictCommissionFee - order.CommissionAmount;
|
||||
if (order.HasRefund)
|
||||
{
|
||||
order.Profit = order.OrderPrice - order.Items.Sum(a => a.RefundAmount);
|
||||
count += order.Profit;
|
||||
if (order.Profit != 0)
|
||||
{
|
||||
Debug.WriteLine($"运费利润 :{order.OrderId} {order.Profit}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
order.Profit = order.OrderPrice - order.OutAmount - order.PredictCommissionFee - order.CommissionAmount;
|
||||
if (order.Profit < 0)
|
||||
{
|
||||
Debug.WriteLine($"正常单负利润 :{order.OrderId} {order.Profit}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -704,7 +737,7 @@ public class ShopRevenueStatisticsService : ITransientDependency
|
||||
StatDate = statDate,
|
||||
OrderCount = valid.Count,
|
||||
SalesAmount = valid.Sum(o => (long)o.OrderPrice),
|
||||
ProfitAmount = valid.Sum(o => (long)o.Profit),
|
||||
ProfitAmount = shopGroup.Sum(o => (long)o.Profit),//利润 包括 正常订单和退款订单所有的利润
|
||||
PlatformFee = valid.Sum(o => (long)o.PredictCommissionFee),
|
||||
RefundOrderCount = afterSale.Count,
|
||||
RefundDone = afterSaleItems.Where(i => i.IsRefundSuccessed)
|
||||
@@ -805,7 +838,7 @@ public class ShopRevenueStatisticsService : ITransientDependency
|
||||
yield return source.Skip(i).Take(size).ToArray();
|
||||
}
|
||||
|
||||
private static bool IsRefundDone(string statusText)
|
||||
internal static bool IsRefundDone(string statusText)
|
||||
{
|
||||
return !string.IsNullOrEmpty(statusText) && statusText == "退款成功";
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using MAX.Core.DependencyInjection;
|
||||
using MAX.Core.Logger;
|
||||
using Store.Framework.Jobs;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -15,14 +16,20 @@ namespace KJD_Web.Services.Shops;
|
||||
public class ShopStatsJob : IScheduledJobs, ITransientDependency
|
||||
{
|
||||
private readonly ShopRevenueStatisticsService _shopRevenueStatisticsService;
|
||||
private readonly ILoggerFacade _logger;
|
||||
|
||||
public ShopStatsJob(ShopRevenueStatisticsService shopRevenueStatisticsService)
|
||||
public ShopStatsJob(ShopRevenueStatisticsService shopRevenueStatisticsService, ILoggerFacade logger)
|
||||
{
|
||||
_shopRevenueStatisticsService = shopRevenueStatisticsService;
|
||||
_logger = logger;
|
||||
}
|
||||
public Task RunAsync()
|
||||
{
|
||||
_shopRevenueStatisticsService.UpdateStats(DateTime.Now.AddDays(-1).Date);
|
||||
var data = DateTime.Now.AddDays(-1).Date;
|
||||
_logger.Info($">>> 执行商铺统计更新:{data.ToString("yyyy-MM-dd")}");
|
||||
_shopRevenueStatisticsService.UpdateStats(data);
|
||||
_logger.Info($"<<< 执行商铺更新:{data.ToString("yyyy-MM-dd")}");
|
||||
return Task.CompletedTask;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -120,4 +120,7 @@ public class OrderPddBuyerAfterSaleEntity
|
||||
/// </summary>
|
||||
[Column(Name = "mdy_time")]
|
||||
public DateTime MdyTime { get; set; }
|
||||
|
||||
[Column(Name = "remark")]
|
||||
public string Remark { get; set; }
|
||||
}
|
||||
@@ -259,7 +259,7 @@ public class VirtualLogisticsApi : ISingletonDependency
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, $"VirtualLogisticsApi:{item.URL}\n{item.Postdata}");
|
||||
//_logger.Error(ex, $"VirtualLogisticsApi:{item.URL}\n{item.Postdata}");
|
||||
return new Result<T>
|
||||
{
|
||||
Code = -1,
|
||||
|
||||
@@ -101,36 +101,59 @@ internal class ShopTest
|
||||
//shopService.GetShopOrderAmountRange(id, DateTime.Now.AddDays(-10));
|
||||
}
|
||||
|
||||
private static IEnumerable<DateTime> CaseArray
|
||||
{
|
||||
get
|
||||
{
|
||||
DateTime startDate = DateTime.Parse("2026/08/01");
|
||||
DateTime endDate = DateTime.Parse("2026/10/08");
|
||||
|
||||
for (DateTime d = startDate; d <= endDate; d = d.AddDays(1))
|
||||
{
|
||||
yield return d;
|
||||
}
|
||||
}
|
||||
}
|
||||
[Test]
|
||||
[TestCaseSource(nameof(CaseArray))]
|
||||
public void StatsDataRangeShopSalesOrderTest(DateTime date)
|
||||
{
|
||||
var shopService = _container.Resolve<ShopRevenueStatisticsService>();
|
||||
|
||||
Console.WriteLine($"开始:{date.ToLongDateString()}");
|
||||
try
|
||||
{
|
||||
shopService.ShopDailyStats(date);
|
||||
}
|
||||
catch
|
||||
{
|
||||
Console.WriteLine($"错误:{date.ToLongDateString()}");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void GetShopSalesOrderTest()
|
||||
{
|
||||
var shopService = _container.Resolve<ShopRevenueStatisticsService>();
|
||||
DateTime startDate = DateTime.Parse("2026/08/01");
|
||||
DateTime endDate = DateTime.Parse("2026/10/07");
|
||||
DateTime date = startDate;
|
||||
while (date <= endDate)
|
||||
DateTime date = DateTime.Parse("2026/10/01");
|
||||
|
||||
Console.WriteLine($"开始:{date.ToLongDateString()}");
|
||||
try
|
||||
{
|
||||
Console.WriteLine($"开始:{date.ToLongDateString()}");
|
||||
try
|
||||
{
|
||||
shopService.ShopDailyStats(date);
|
||||
}
|
||||
catch
|
||||
{
|
||||
Console.WriteLine($"错误:{date.ToLongDateString()}");
|
||||
}
|
||||
date = date.AddDays(1);
|
||||
shopService.ShopDailyStats(date, [
|
||||
1960967267443626508,
|
||||
]);
|
||||
}
|
||||
catch
|
||||
{
|
||||
Console.WriteLine($"错误:{date.ToLongDateString()}");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
[Test]
|
||||
public void GetBuyerDailyStatsTest()
|
||||
{
|
||||
var shopService = _container.Resolve<ShopRevenueStatisticsService>();
|
||||
shopService.BuyerDailyStats(DateTime.Parse("2026/10/02"), [1960967267443620449]);
|
||||
}
|
||||
[Test]
|
||||
public void UpdateStatsTest()
|
||||
{
|
||||
@@ -177,4 +200,20 @@ internal class ShopTest
|
||||
}
|
||||
Console.WriteLine(sb.ToString());
|
||||
}
|
||||
|
||||
|
||||
|
||||
[Test]
|
||||
public void GetShopOrderDetailsTest()
|
||||
{
|
||||
var shopService = _container.Resolve<ShopRevenueStatisticsService>();
|
||||
var ret = shopService.GetShopOrderDetails(DateTime.Parse("2026/10/01"), DateTime.Parse("2026/10/01"), shopIds: [
|
||||
"1960967267443626517",
|
||||
|
||||
]);
|
||||
foreach (var item in ret)
|
||||
{
|
||||
Console.WriteLine($"{item.OrderId} {item.OutAmount}");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user