Files
StoreWeb/Store.KJDWebService/Services/WXShopRevenueStatisticsService.cs
T

307 lines
11 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using StoreHub.KJDWebService.Models;
using StoreHub.Framework.Repositorys;
using Microsoft.Extensions.Configuration;
using StoreHub.KJDWebService.Models.WxModel;
using StoreHub.KJDWebService.Commons;
using StoreHub.KJDWebService.Commons;
using MySql.Data.MySqlClient;
using NaiBa.Util.Extension;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text;
using System.Threading;
namespace StoreHub.KJDWebService.Services
{
public class WXShopRevenueStatisticsService : ServiceBase
{
private readonly WXOrderService _wxOrderService;
public WXShopRevenueStatisticsService(SqlRepository sqlRepository, IConfiguration configuration, WXOrderService wxOrderService) : base(sqlRepository, configuration)
{
_wxOrderService = wxOrderService;
}
public string GetShopOrderAmountRange(string inputData)
{
Result ret = Result.ArgumentNull();
if (!string.IsNullOrEmpty(inputData))
{
try
{
// todo 获取当前用户微信店铺,或指定某一个店铺,某一段时间
// 获取店铺下时间范围内的所有订单涉及到的金额
// 直接返回
if (!WXUserService.GetSign(inputData))
throw new ArgumentException("校验失败");
var timeCalc = DateTime.Now;
string shop_ids = RegexUtils.GetStringQuery(ref inputData, "shop_ids")?.Replace("'", "");//所有店铺信息
if (string.IsNullOrEmpty(shop_ids))
throw new ArgumentException("请选择店铺");
List<string> shopIdLst = shop_ids.Split(',').ToList();
if (shopIdLst.Count > 0)
shop_ids = "'" + string.Join("','", shopIdLst) + "'";
string start_Time = RegexUtils.GetStringQuery(ref inputData, "start_time")?.Replace("'", "");
string end_Time = RegexUtils.GetStringQuery(ref inputData, "end_time")?.Replace("'", "");
DateTime startTime = DateTime.Now.AddDays(-7);
DateTime endTime = DateTime.Now;
if (!string.IsNullOrEmpty(start_Time))
startTime = TimeUtils.StampMillisecondsToDateTime(start_Time.ParseToLong());
if (!string.IsNullOrEmpty(end_Time))
endTime = TimeUtils.StampMillisecondsToDateTime(end_Time.ParseToLong());
if (endTime <= startTime)
throw new ArgumentException("结束时间必须大于开始时间");
if (endTime > startTime.AddMonths(3))
throw new ArgumentException("时间范围不能超过3个月");
int startTimestamp = TimeUtils.DateTimeToTimestampSeconds(startTime);
int endTimestamp = TimeUtils.DateTimeToTimestampSeconds(endTime);
StringBuilder sb = new StringBuilder();
sb.Append("SELECT ");
sb.Append("A.shop_name, ");
sb.Append("A.create_time, ");
sb.Append("A.order_id, ");
sb.Append("A.`status`, ");
sb.Append("A.product_price, ");
sb.Append("A.order_price, ");
sb.Append("A.purchase_price, ");
sb.Append("A.freight, ");
sb.Append("A.predict_commission_fee, ");
sb.Append("A.commission_amount, ");
sb.Append("A.discounted_price, ");
sb.Append("A.profit, ");
sb.Append("A.purchase_status, ");
sb.Append("A.out_amount, ");
sb.Append("B.refund_status, ");
sb.Append("c.`status` as refund_status_string, ");
sb.Append("IFNULL(C.refund_amount, 0) AS refund_amount ");
sb.Append("FROM erp.oms_wei_order AS A ");
sb.Append("INNER JOIN erp.`oms_wei_order_item` AS B ON A.`order_id` = B.`order_id` ");
sb.Append("LEFT JOIN ( SELECT order_id,`status`,refund_amount,id FROM erp.`oms_wei_refund` WHERE id IN ( SELECT MAX(id) FROM erp.`oms_wei_refund` GROUP BY order_id)) AS C ON A.order_id = C.order_id ");
sb.Append("WHERE A.create_time BETWEEN " + startTimestamp + " AND " + endTimestamp + " ");
sb.Append("AND A.`status` > 10 ");
sb.Append("AND A.shop_id IN (" + shop_ids + ") ");
sb.Append("ORDER BY A.create_time asc");
string conn = "ConnKJD";
MysqlUtils mySql = new MysqlUtils(conn);
DataTable dt = mySql.ExecuteDataTable(sb.ToString());
mySql.Close();
if (!string.IsNullOrEmpty(mySql.Message))
throw new Exception(mySql.Message);
// out_amount 为空或为0的订单,从中转仓订单表(GetTransitOrderTable)补全外采金额
// external_procurement:0=未查到,1=从 GetTransitOrderTable 查询到
Dictionary<string, int> transitOutAmountMap = new Dictionary<string, int>();
if (dt != null && dt.Rows.Count > 0)
{
HashSet<string> needLookupOrderIds = new HashSet<string>();
foreach (DataRow row in dt.Rows)
{
int? rowOutAmount = row["out_amount"].ParseToInt();
if (rowOutAmount == null || rowOutAmount.Value == 0)
{
string orderId = row["order_id"].ParseToString();
if (!string.IsNullOrEmpty(orderId))
needLookupOrderIds.Add(orderId);
}
}
if (needLookupOrderIds.Count > 0)
{
const int chunkSize = 100;
const int transitPageSize = 500;
List<string> needLookupList = needLookupOrderIds.ToList();
for (int i = 0; i < needLookupList.Count; i += chunkSize)
{
int takeCount = Math.Min(chunkSize, needLookupList.Count - i);
string chunkOrderIds = string.Join(",", needLookupList.GetRange(i, takeCount));
int pageIndex = 1;
while (true)
{
int count = -1;
var transitList = _wxOrderService.GetTransitOrderTable(pageIndex, transitPageSize, chunkOrderIds, null, null, null, null, "true", out count);
if (transitList == null || transitList.Count == 0)
break;
foreach (var transit in transitList)
{
if (transit != null && !string.IsNullOrEmpty(transit.order_no) && needLookupOrderIds.Contains(transit.order_no))
{
if (!transitOutAmountMap.ContainsKey(transit.order_no))
transitOutAmountMap[transit.order_no] = transit.out_amount ?? 0;
}
}
if (transitList.Count < transitPageSize)
break;
pageIndex++;
}
}
}
}
List<WXOrderAmountInfo> orderList = new List<WXOrderAmountInfo>();
if (dt != null)
{
foreach (DataRow row in dt.Rows)
orderList.Add(BuildOrderAmountInfo(row, transitOutAmountMap));
}
// 买手号退款金额:退款订单(refund_status>1)且非外采时,从买手售后表补全退款金额
FillBuyerRefundAmount(orderList, conn);
ret.Code = 200;
ret.Msg = "success";
ret.Data = orderList;
}
catch (Exception ex)
{
ret.Code = 500;
ret.Msg = ex.Message;
}
}
return JsonUtils.SerializeObjectToString(ret, new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore
});
}
/// <summary>
/// 将订单行转换为金额详情:out_amount 为空或0时从中转仓订单表补全,并计算利润
/// </summary>
private WXOrderAmountInfo BuildOrderAmountInfo(DataRow row, Dictionary<string, int> transitOutAmountMap)
{
string orderId = row["order_id"].ParseToString();
int outAmount = row["out_amount"].ParseToInt();
int externalProcurement = 0;
if (outAmount == 0)
{
int transitAmount;
if (transitOutAmountMap.TryGetValue(orderId, out transitAmount))
{
externalProcurement = 1;
outAmount = transitAmount;
}
}
int orderPrice = row["order_price"].ParseToInt();
int predictCommissionFee = row["predict_commission_fee"].ParseToInt();
int commissionAmount = row["commission_amount"].ParseToInt();
int refund_amount = row["refund_amount"].ParseToInt();
// 利润 = 订单金额 - 外采金额 - 平台服务费 - 达人佣金(为空按0处理)
int profit = orderPrice - outAmount - predictCommissionFee - commissionAmount;
if (refund_amount > 0) //退款利润计算
{
profit = orderPrice - refund_amount;
}
return new WXOrderAmountInfo
{
shop_name = row["shop_name"].ParseToString(),
create_time = row["create_time"].ParseToInt(),
order_id = orderId,
status = row["status"].ParseToInt(),
product_price = row["product_price"].ParseToInt(),
order_price = orderPrice,
purchase_price = row["purchase_price"].ParseToInt(),
freight = row["freight"].ParseToInt(),
predict_commission_fee = predictCommissionFee,
commission_amount = commissionAmount,
discounted_price = row["discounted_price"].ParseToInt(),
profit = profit,
purchase_status = row["purchase_status"].ParseToInt(),
out_amount = outAmount,
refund_status = row["refund_status"].ParseToInt(),
refund_status_string = row["refund_status_string"].ParseToString(),
refund_amount = row["refund_amount"].ParseToInt(),
external_procurement = externalProcurement
};
}
/// <summary>
/// 买手号退款金额:退款订单(refund_status>1)且非外采时,从买手售后表(wxxd.order_pdd_buyer_after_sale)查询退款金额(refundAmount)填入
/// </summary>
private void FillBuyerRefundAmount(List<WXOrderAmountInfo> orderList, string conn)
{
if (orderList == null || orderList.Count == 0)
return;
// 退款订单(refund_status>1)且非外采(out_amount、external_procurement都为0)的订单才查询买手号退款金额
HashSet<string> needLookupOrderIds = new HashSet<string>();
foreach (WXOrderAmountInfo order in orderList)
{
if (order.refund_status > 1 && order.external_procurement == 1 && order.out_amount > 0)
{
if (!string.IsNullOrEmpty(order.order_id))
needLookupOrderIds.Add(order.order_id);
}
}
if (needLookupOrderIds.Count == 0)
return;
Dictionary<string, Tuple<int, string>> buyerRefundAmountMap = new Dictionary<string, Tuple<int, string>>();
MysqlUtils mySql = new MysqlUtils(conn);
try
{
const int chunkSize = 100;
List<string> needLookupList = needLookupOrderIds.ToList();
for (int i = 0; i < needLookupList.Count; i += chunkSize)
{
int takeCount = Math.Min(chunkSize, needLookupList.Count - i);
string chunkOrderIds = string.Join("','", needLookupList.GetRange(i, takeCount));
string sql = "SELECT WX_ORDER_ID,refundAmount,statusText FROM wxxd.order_pdd_buyer_after_sale a " +
"WHERE a.WX_ORDER_ID IN ('" + chunkOrderIds + "') AND a.id = ( SELECT MAX(b.id) FROM wxxd.order_pdd_buyer_after_sale b WHERE b.WX_ORDER_ID = a.WX_ORDER_ID) ORDER BY a.WX_ORDER_ID;";
DataTable buyerDt = mySql.ExecuteDataTable(sql);
if (buyerDt != null)
{
foreach (DataRow row in buyerDt.Rows)
{
string wxOrderId = row["WX_ORDER_ID"].ParseToString();
int refundAmount = row["refundAmount"].ParseToInt();
string statusText = row["statusText"].ParseToString();
if (!string.IsNullOrEmpty(wxOrderId) && !buyerRefundAmountMap.ContainsKey(wxOrderId))
buyerRefundAmountMap[wxOrderId] = new Tuple<int, string>(refundAmount, statusText);
}
}
}
}
finally
{
mySql.Close();
}
if (!string.IsNullOrEmpty(mySql.Message))
throw new Exception(mySql.Message);
foreach (WXOrderAmountInfo order in orderList)
{
Tuple<int, string> buyerRefundAmount;
if (buyerRefundAmountMap.TryGetValue(order.order_id, out buyerRefundAmount))
{
order.buyer_refund_amount = buyerRefundAmount.Item1;
order.buyer_refund_status = buyerRefundAmount.Item2;
}
}
}
}
}