HaniBlindBox/server/HoneyBox/src/HoneyBox.Admin.Business/Services/OrderService.cs
2026-01-17 22:28:51 +08:00

1142 lines
40 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 HoneyBox.Admin.Business.Models;
using HoneyBox.Admin.Business.Models.Order;
using HoneyBox.Admin.Business.Services.Interfaces;
using HoneyBox.Model.Data;
using HoneyBox.Model.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
namespace HoneyBox.Admin.Business.Services;
/// <summary>
/// 订单管理服务实现
/// </summary>
public class OrderService : IOrderService
{
private readonly HoneyBoxDbContext _dbContext;
private readonly ILogger<OrderService> _logger;
// 订单状态名称映射
private static readonly Dictionary<int, string> OrderStatusNames = new()
{
{ 0, "待支付" },
{ 1, "已支付" },
{ 2, "已取消" }
};
// 支付方式名称映射
private static readonly Dictionary<int, string> PayTypeNames = new()
{
{ 0, "未支付" },
{ 1, "微信支付" },
{ 2, "支付宝" }
};
// 发货状态名称映射
private static readonly Dictionary<int, string> ShippingStatusNames = new()
{
{ 0, "待支付" },
{ 1, "待发货" },
{ 2, "已发货" },
{ 3, "已签收" },
{ 4, "已取消" }
};
// 物流状态名称映射
private static readonly Dictionary<int, string> DeliveryStatusNames = new()
{
{ -1, "未查询" },
{ 0, "在途" },
{ 1, "揽收" },
{ 2, "疑难" },
{ 3, "签收" },
{ 4, "退签" },
{ 5, "派件" },
{ 6, "退回" }
};
// 订单项状态名称映射
private static readonly Dictionary<int, string> OrderItemStatusNames = new()
{
{ 0, "待处理" },
{ 1, "已回收" },
{ 2, "已发货" }
};
public OrderService(
HoneyBoxDbContext dbContext,
ILogger<OrderService> logger)
{
_dbContext = dbContext;
_logger = logger;
}
#region
/// <inheritdoc />
public async Task<PagedResult<OrderListResponse>> GetOrderListAsync(OrderListRequest request)
{
var query = _dbContext.Orders.AsNoTracking();
// 应用过滤条件(包含手机号过滤)
query = await ApplyOrderFiltersWithMobileAsync(query, request);
// 获取总数
var total = await query.CountAsync();
// 获取订单列表
var orders = await query
.OrderByDescending(o => o.Id)
.Skip(request.Skip)
.Take(request.PageSize)
.ToListAsync();
// 获取用户信息
var userIds = orders.Select(o => o.UserId).Distinct().ToList();
var users = await _dbContext.Users
.AsNoTracking()
.Where(u => userIds.Contains(u.Id))
.ToDictionaryAsync(u => u.Id);
// 映射结果
var list = orders.Select(o => MapToOrderListResponse(o, users)).ToList();
return PagedResult<OrderListResponse>.Create(list, total, request.Page, request.PageSize);
}
/// <inheritdoc />
public async Task<OrderDetailResponse?> GetOrderDetailAsync(int orderId)
{
var order = await _dbContext.Orders
.AsNoTracking()
.FirstOrDefaultAsync(o => o.Id == orderId);
if (order == null)
{
return null;
}
// 获取用户信息
var user = await _dbContext.Users
.AsNoTracking()
.FirstOrDefaultAsync(u => u.Id == order.UserId);
// 获取订单项
var orderItems = await _dbContext.OrderItems
.AsNoTracking()
.Where(oi => oi.OrderId == orderId)
.ToListAsync();
// 映射基本信息
var response = MapToOrderDetailResponse(order, user);
// 按prize_code分组
response.PrizeGroups = GroupOrderItemsByPrizeCode(orderItems);
return response;
}
/// <inheritdoc />
public async Task<PagedResult<OrderListResponse>> GetStuckOrdersAsync(OrderListRequest request)
{
// 卡单:有订单项但状态为待处理的订单
var query = _dbContext.Orders
.AsNoTracking()
.Where(o => o.Status == 1); // 已支付的订单
// 应用过滤条件
query = ApplyOrderFilters(query, request);
// 按手机号过滤需要关联用户表
if (!string.IsNullOrWhiteSpace(request.Mobile))
{
var mobileUserIds = await _dbContext.Users
.AsNoTracking()
.Where(u => u.Mobile != null && u.Mobile.Contains(request.Mobile))
.Select(u => u.Id)
.ToListAsync();
query = query.Where(o => mobileUserIds.Contains(o.UserId));
}
// 只获取有待处理订单项的订单
var ordersWithStuckItems = query
.Where(o => _dbContext.OrderItems.Any(oi => oi.OrderId == o.Id && oi.Status == 0));
// 获取总数
var total = await ordersWithStuckItems.CountAsync();
// 获取订单列表
var orders = await ordersWithStuckItems
.OrderByDescending(o => o.Id)
.Skip(request.Skip)
.Take(request.PageSize)
.ToListAsync();
// 获取用户信息
var userIds = orders.Select(o => o.UserId).Distinct().ToList();
var users = await _dbContext.Users
.AsNoTracking()
.Where(u => userIds.Contains(u.Id))
.ToDictionaryAsync(u => u.Id);
// 映射结果
var list = orders.Select(o => MapToOrderListResponse(o, users)).ToList();
return PagedResult<OrderListResponse>.Create(list, total, request.Page, request.PageSize);
}
/// <inheritdoc />
public async Task<PagedResult<RecoveryOrderResponse>> GetRecoveryOrdersAsync(OrderListRequest request)
{
var query = _dbContext.OrderItemsRecoveries.AsNoTracking();
// 应用过滤条件
if (request.UserId.HasValue)
{
query = query.Where(r => r.UserId == request.UserId.Value);
}
if (request.StartDate.HasValue)
{
var startTimestamp = (int)((DateTimeOffset)request.StartDate.Value).ToUnixTimeSeconds();
query = query.Where(r => r.Addtime >= startTimestamp);
}
if (request.EndDate.HasValue)
{
var endTimestamp = (int)((DateTimeOffset)request.EndDate.Value.AddDays(1)).ToUnixTimeSeconds();
query = query.Where(r => r.Addtime < endTimestamp);
}
// 按手机号过滤需要关联用户表
if (!string.IsNullOrWhiteSpace(request.Mobile))
{
var mobileUserIds = await _dbContext.Users
.AsNoTracking()
.Where(u => u.Mobile != null && u.Mobile.Contains(request.Mobile))
.Select(u => u.Id)
.ToListAsync();
query = query.Where(r => mobileUserIds.Contains(r.UserId));
}
// 获取总数
var total = await query.CountAsync();
// 获取回收订单列表
var recoveries = await query
.OrderByDescending(r => r.Id)
.Skip(request.Skip)
.Take(request.PageSize)
.ToListAsync();
// 获取用户信息
var userIds = recoveries.Select(r => r.UserId).Distinct().ToList();
var users = await _dbContext.Users
.AsNoTracking()
.Where(u => userIds.Contains(u.Id))
.ToDictionaryAsync(u => u.Id);
// 获取回收的奖品信息
var recoveryNums = recoveries.Select(r => r.RecoveryNum).ToList();
var recoveryItems = await _dbContext.OrderItems
.AsNoTracking()
.Where(oi => oi.RecoveryNum != null && recoveryNums.Contains(oi.RecoveryNum))
.ToListAsync();
// 映射结果
var list = recoveries.Select(r => MapToRecoveryOrderResponse(r, users, recoveryItems)).ToList();
return PagedResult<RecoveryOrderResponse>.Create(list, total, request.Page, request.PageSize);
}
#endregion
#region
/// <inheritdoc />
public async Task<PagedResult<ShippingOrderResponse>> GetShippingOrdersAsync(ShippingOrderListRequest request)
{
var query = _dbContext.OrderItemsSends.AsNoTracking();
// 应用过滤条件(包含手机号过滤)
query = await ApplyShippingFiltersWithMobileAsync(query, request);
// 获取总数
var total = await query.CountAsync();
// 获取发货订单列表
var shippingOrders = await query
.OrderByDescending(s => s.Id)
.Skip(request.Skip)
.Take(request.PageSize)
.ToListAsync();
// 获取用户信息
var userIds = shippingOrders.Select(s => s.UserId).Distinct().ToList();
var users = await _dbContext.Users
.AsNoTracking()
.Where(u => userIds.Contains(u.Id))
.ToDictionaryAsync(u => u.Id);
// 映射结果(不包含奖品详情)
var list = shippingOrders.Select(s => MapToShippingOrderResponse(s, users, null)).ToList();
return PagedResult<ShippingOrderResponse>.Create(list, total, request.Page, request.PageSize);
}
/// <inheritdoc />
public async Task<ShippingOrderResponse?> GetShippingOrderDetailAsync(int sendId)
{
var shippingOrder = await _dbContext.OrderItemsSends
.AsNoTracking()
.FirstOrDefaultAsync(s => s.Id == sendId);
if (shippingOrder == null)
{
return null;
}
// 获取用户信息
var user = await _dbContext.Users
.AsNoTracking()
.FirstOrDefaultAsync(u => u.Id == shippingOrder.UserId);
// 获取发货的奖品信息
var shippingItems = await _dbContext.OrderItems
.AsNoTracking()
.Where(oi => oi.SendNum == shippingOrder.SendNum)
.ToListAsync();
var users = user != null ? new Dictionary<int, User> { { user.Id, user } } : new Dictionary<int, User>();
return MapToShippingOrderResponse(shippingOrder, users, shippingItems);
}
/// <inheritdoc />
public async Task<bool> ShipOrderAsync(int sendId, ShipOrderRequest request, int operatorId)
{
var shippingOrder = await _dbContext.OrderItemsSends
.FirstOrDefaultAsync(s => s.Id == sendId);
if (shippingOrder == null)
{
throw new BusinessException(BusinessErrorCodes.NotFound, "发货订单不存在");
}
if (shippingOrder.Status != 1)
{
throw new BusinessException(BusinessErrorCodes.ValidationFailed, "只有待发货状态的订单才能发货");
}
// 更新发货信息
shippingOrder.CourierName = request.CourierName;
shippingOrder.CourierNumber = request.CourierNumber;
shippingOrder.CourierCode = request.CourierCode;
shippingOrder.Status = 2; // 已发货
shippingOrder.SendTime = (int)DateTimeOffset.Now.ToUnixTimeSeconds();
shippingOrder.AdminId = operatorId;
shippingOrder.UpdatedAt = DateTime.Now;
var result = await _dbContext.SaveChangesAsync() > 0;
// 记录操作日志
await LogOrderOperationAsync(sendId, "ship", $"发货处理: SendNum={shippingOrder.SendNum}, Courier={request.CourierName}, Number={request.CourierNumber}", operatorId);
_logger.LogInformation("发货处理成功: SendId={SendId}, SendNum={SendNum}, Operator={Operator}",
sendId, shippingOrder.SendNum, operatorId);
return result;
}
/// <inheritdoc />
public async Task<bool> CancelShippingOrderAsync(int sendId, int operatorId)
{
var shippingOrder = await _dbContext.OrderItemsSends
.FirstOrDefaultAsync(s => s.Id == sendId);
if (shippingOrder == null)
{
throw new BusinessException(BusinessErrorCodes.NotFound, "发货订单不存在");
}
if (shippingOrder.Status != 1 && shippingOrder.Status != 2)
{
throw new BusinessException(BusinessErrorCodes.ValidationFailed, "只有待发货或已发货状态的订单才能取消");
}
// 获取发货的奖品
var shippingItems = await _dbContext.OrderItems
.Where(oi => oi.SendNum == shippingOrder.SendNum)
.ToListAsync();
// 恢复奖品到用户盒柜(将状态改回待处理)
foreach (var item in shippingItems)
{
item.Status = 0; // 待处理
item.SendNum = null;
item.FhStatus = 0;
item.UpdatedAt = DateTime.Now;
}
// 更新发货订单状态
shippingOrder.Status = 4; // 已取消
shippingOrder.CancelTime = (int)DateTimeOffset.Now.ToUnixTimeSeconds();
shippingOrder.AdminId = operatorId;
shippingOrder.UpdatedAt = DateTime.Now;
var result = await _dbContext.SaveChangesAsync() > 0;
// 记录操作日志
await LogOrderOperationAsync(sendId, "cancel_ship", $"取消发货: SendNum={shippingOrder.SendNum}, 恢复奖品数量={shippingItems.Count}", operatorId);
_logger.LogInformation("取消发货成功: SendId={SendId}, SendNum={SendNum}, RestoredItems={RestoredItems}, Operator={Operator}",
sendId, shippingOrder.SendNum, shippingItems.Count, operatorId);
return result;
}
#endregion
#region
/// <inheritdoc />
public async Task<byte[]> ExportOrdersAsync(OrderExportRequest request)
{
var query = _dbContext.Orders.AsNoTracking();
// 应用过滤条件
if (request.UserId.HasValue)
{
query = query.Where(o => o.UserId == request.UserId.Value);
}
if (!string.IsNullOrWhiteSpace(request.OrderNum))
{
query = query.Where(o => o.OrderNum.Contains(request.OrderNum));
}
if (request.StartDate.HasValue)
{
query = query.Where(o => o.CreatedAt >= request.StartDate.Value);
}
if (request.EndDate.HasValue)
{
var endDate = request.EndDate.Value.AddDays(1);
query = query.Where(o => o.CreatedAt < endDate);
}
if (request.Status.HasValue)
{
query = query.Where(o => o.Status == request.Status.Value);
}
if (request.OrderType.HasValue)
{
query = query.Where(o => o.OrderType == request.OrderType.Value);
}
// 按手机号过滤需要关联用户表
if (!string.IsNullOrWhiteSpace(request.Mobile))
{
var mobileUserIds = await _dbContext.Users
.AsNoTracking()
.Where(u => u.Mobile != null && u.Mobile.Contains(request.Mobile))
.Select(u => u.Id)
.ToListAsync();
query = query.Where(o => mobileUserIds.Contains(o.UserId));
}
// 获取订单数据
var orders = await query
.OrderByDescending(o => o.Id)
.Take(10000) // 限制导出数量
.ToListAsync();
// 获取用户信息
var userIds = orders.Select(o => o.UserId).Distinct().ToList();
var users = await _dbContext.Users
.AsNoTracking()
.Where(u => userIds.Contains(u.Id))
.ToDictionaryAsync(u => u.Id);
// 映射导出数据
var exportData = orders.Select(o => MapToOrderExportDto(o, users)).ToList();
// 生成CSV格式简单实现可以替换为Excel库
return GenerateCsvBytes(exportData);
}
/// <inheritdoc />
public async Task<byte[]> ExportShippingOrdersAsync(ShippingExportRequest request)
{
var query = _dbContext.OrderItemsSends.AsNoTracking();
// 应用过滤条件
if (request.UserId.HasValue)
{
query = query.Where(s => s.UserId == request.UserId.Value);
}
if (!string.IsNullOrWhiteSpace(request.SendNum))
{
query = query.Where(s => s.SendNum.Contains(request.SendNum));
}
if (request.StartDate.HasValue)
{
var startTimestamp = (int)((DateTimeOffset)request.StartDate.Value).ToUnixTimeSeconds();
query = query.Where(s => s.Addtime >= startTimestamp);
}
if (request.EndDate.HasValue)
{
var endTimestamp = (int)((DateTimeOffset)request.EndDate.Value.AddDays(1)).ToUnixTimeSeconds();
query = query.Where(s => s.Addtime < endTimestamp);
}
if (request.Status.HasValue)
{
query = query.Where(s => s.Status == request.Status.Value);
}
// 按手机号过滤需要关联用户表
if (!string.IsNullOrWhiteSpace(request.Mobile))
{
var mobileUserIds = await _dbContext.Users
.AsNoTracking()
.Where(u => u.Mobile != null && u.Mobile.Contains(request.Mobile))
.Select(u => u.Id)
.ToListAsync();
query = query.Where(s => mobileUserIds.Contains(s.UserId));
}
// 获取发货订单数据
var shippingOrders = await query
.OrderByDescending(s => s.Id)
.Take(10000) // 限制导出数量
.ToListAsync();
// 获取用户信息
var userIds = shippingOrders.Select(s => s.UserId).Distinct().ToList();
var users = await _dbContext.Users
.AsNoTracking()
.Where(u => userIds.Contains(u.Id))
.ToDictionaryAsync(u => u.Id);
// 映射导出数据
var exportData = shippingOrders.Select(s => MapToShippingExportDto(s, users)).ToList();
// 生成CSV格式
return GenerateShippingCsvBytes(exportData);
}
/// <inheritdoc />
public async Task<byte[]> ExportRecoveryOrdersAsync(RecoveryExportRequest request)
{
var query = _dbContext.OrderItemsRecoveries.AsNoTracking();
// 应用过滤条件
if (request.UserId.HasValue)
{
query = query.Where(r => r.UserId == request.UserId.Value);
}
if (request.StartDate.HasValue)
{
var startTimestamp = (int)((DateTimeOffset)request.StartDate.Value).ToUnixTimeSeconds();
query = query.Where(r => r.Addtime >= startTimestamp);
}
if (request.EndDate.HasValue)
{
var endTimestamp = (int)((DateTimeOffset)request.EndDate.Value.AddDays(1)).ToUnixTimeSeconds();
query = query.Where(r => r.Addtime < endTimestamp);
}
// 按手机号过滤需要关联用户表
if (!string.IsNullOrWhiteSpace(request.Mobile))
{
var mobileUserIds = await _dbContext.Users
.AsNoTracking()
.Where(u => u.Mobile != null && u.Mobile.Contains(request.Mobile))
.Select(u => u.Id)
.ToListAsync();
query = query.Where(r => mobileUserIds.Contains(r.UserId));
}
// 获取回收订单数据
var recoveryOrders = await query
.OrderByDescending(r => r.Id)
.Take(10000) // 限制导出数量
.ToListAsync();
// 获取用户信息
var userIds = recoveryOrders.Select(r => r.UserId).Distinct().ToList();
var users = await _dbContext.Users
.AsNoTracking()
.Where(u => userIds.Contains(u.Id))
.ToDictionaryAsync(u => u.Id);
// 映射导出数据
var exportData = recoveryOrders.Select(r => MapToRecoveryExportDto(r, users)).ToList();
// 生成CSV格式
return GenerateRecoveryCsvBytes(exportData);
}
/// <inheritdoc />
public async Task<ShippingStatsResponse> GetShippingStatsAsync(ShippingOrderListRequest request)
{
var query = _dbContext.OrderItemsSends.AsNoTracking();
// 应用过滤条件
query = ApplyShippingFilters(query, request);
// 按手机号过滤需要关联用户表
if (!string.IsNullOrWhiteSpace(request.Mobile))
{
var mobileUserIds = await _dbContext.Users
.AsNoTracking()
.Where(u => u.Mobile != null && u.Mobile.Contains(request.Mobile))
.Select(u => u.Id)
.ToListAsync();
query = query.Where(s => mobileUserIds.Contains(s.UserId));
}
// 获取总条数
var totalCount = await query.CountAsync();
// 获取所有发货单号
var sendNums = await query.Select(s => s.SendNum).ToListAsync();
// 计算总价值(所有发货奖品的价值总和)
var totalValue = await _dbContext.OrderItems
.AsNoTracking()
.Where(oi => oi.SendNum != null && sendNums.Contains(oi.SendNum))
.SumAsync(oi => oi.GoodslistPrice);
// 获取当前页的发货单号
var pageShippingOrders = await query
.OrderByDescending(s => s.Id)
.Skip(request.Skip)
.Take(request.PageSize)
.Select(s => s.SendNum)
.ToListAsync();
// 计算本页总价值
var pageValue = await _dbContext.OrderItems
.AsNoTracking()
.Where(oi => oi.SendNum != null && pageShippingOrders.Contains(oi.SendNum))
.SumAsync(oi => oi.GoodslistPrice);
return new ShippingStatsResponse
{
TotalCount = totalCount,
TotalValue = totalValue,
PageValue = pageValue
};
}
#endregion
#region Private Helper Methods
/// <summary>
/// 应用订单过滤条件
/// </summary>
private IQueryable<Order> ApplyOrderFilters(IQueryable<Order> query, OrderListRequest request)
{
if (request.UserId.HasValue)
{
query = query.Where(o => o.UserId == request.UserId.Value);
}
if (!string.IsNullOrWhiteSpace(request.OrderNum))
{
query = query.Where(o => o.OrderNum.Contains(request.OrderNum));
}
if (request.StartDate.HasValue)
{
query = query.Where(o => o.CreatedAt >= request.StartDate.Value);
}
if (request.EndDate.HasValue)
{
var endDate = request.EndDate.Value.AddDays(1);
query = query.Where(o => o.CreatedAt < endDate);
}
if (request.Status.HasValue)
{
query = query.Where(o => o.Status == request.Status.Value);
}
if (request.OrderType.HasValue)
{
query = query.Where(o => o.OrderType == request.OrderType.Value);
}
return query;
}
/// <summary>
/// 应用订单过滤条件(包含手机号过滤,异步版本)
/// </summary>
private async Task<IQueryable<Order>> ApplyOrderFiltersWithMobileAsync(IQueryable<Order> query, OrderListRequest request)
{
query = ApplyOrderFilters(query, request);
// 按手机号过滤需要关联用户表
if (!string.IsNullOrWhiteSpace(request.Mobile))
{
var mobileUserIds = await _dbContext.Users
.AsNoTracking()
.Where(u => u.Mobile != null && u.Mobile.Contains(request.Mobile))
.Select(u => u.Id)
.ToListAsync();
query = query.Where(o => mobileUserIds.Contains(o.UserId));
}
return query;
}
/// <summary>
/// 应用发货订单过滤条件
/// </summary>
private IQueryable<OrderItemsSend> ApplyShippingFilters(IQueryable<OrderItemsSend> query, ShippingOrderListRequest request)
{
if (request.UserId.HasValue)
{
query = query.Where(s => s.UserId == request.UserId.Value);
}
if (!string.IsNullOrWhiteSpace(request.SendNum))
{
query = query.Where(s => s.SendNum.Contains(request.SendNum));
}
if (request.StartDate.HasValue)
{
var startTimestamp = (int)((DateTimeOffset)request.StartDate.Value).ToUnixTimeSeconds();
query = query.Where(s => s.Addtime >= startTimestamp);
}
if (request.EndDate.HasValue)
{
var endTimestamp = (int)((DateTimeOffset)request.EndDate.Value.AddDays(1)).ToUnixTimeSeconds();
query = query.Where(s => s.Addtime < endTimestamp);
}
if (request.Status.HasValue)
{
query = query.Where(s => s.Status == request.Status.Value);
}
return query;
}
/// <summary>
/// 应用发货订单过滤条件(包含手机号过滤,异步版本)
/// </summary>
private async Task<IQueryable<OrderItemsSend>> ApplyShippingFiltersWithMobileAsync(IQueryable<OrderItemsSend> query, ShippingOrderListRequest request)
{
query = ApplyShippingFilters(query, request);
// 按手机号过滤需要关联用户表
if (!string.IsNullOrWhiteSpace(request.Mobile))
{
var mobileUserIds = await _dbContext.Users
.AsNoTracking()
.Where(u => u.Mobile != null && u.Mobile.Contains(request.Mobile))
.Select(u => u.Id)
.ToListAsync();
query = query.Where(s => mobileUserIds.Contains(s.UserId));
}
return query;
}
/// <summary>
/// 映射订单到列表响应
/// </summary>
private OrderListResponse MapToOrderListResponse(Order order, Dictionary<int, User> users)
{
users.TryGetValue(order.UserId, out var user);
return new OrderListResponse
{
Id = order.Id,
OrderNum = order.OrderNum,
UserId = order.UserId,
UserNickname = user?.Nickname,
UserMobile = user?.Mobile,
UserUid = user?.Uid,
GoodsId = order.GoodsId,
GoodsTitle = order.GoodsTitle,
GoodsImgUrl = order.GoodsImgurl,
OrderType = order.OrderType,
OrderTotal = order.OrderTotal,
Discount = order.Zhe,
DiscountTotal = order.OrderZheTotal,
WeChatPayment = order.Price,
BalancePayment = order.UseMoney,
IntegralPayment = order.UseIntegral,
ScorePayment = order.UseScore,
CouponPayment = order.UseCoupon,
Num = order.Num,
PrizeNum = order.PrizeNum,
Status = order.Status,
StatusName = OrderStatusNames.GetValueOrDefault(order.Status, "未知"),
PayType = order.PayType,
PayTypeName = PayTypeNames.GetValueOrDefault(order.PayType, "未知"),
CreatedAt = order.CreatedAt,
PayTime = order.PayTime > 0 ? DateTimeOffset.FromUnixTimeSeconds(order.PayTime).LocalDateTime : null
};
}
/// <summary>
/// 映射订单到详情响应
/// </summary>
private OrderDetailResponse MapToOrderDetailResponse(Order order, User? user)
{
return new OrderDetailResponse
{
Id = order.Id,
OrderNum = order.OrderNum,
UserId = order.UserId,
UserNickname = user?.Nickname,
UserMobile = user?.Mobile,
UserUid = user?.Uid,
GoodsId = order.GoodsId,
GoodsTitle = order.GoodsTitle,
GoodsImgUrl = order.GoodsImgurl,
OrderType = order.OrderType,
OrderTotal = order.OrderTotal,
Discount = order.Zhe,
DiscountTotal = order.OrderZheTotal,
WeChatPayment = order.Price,
BalancePayment = order.UseMoney,
IntegralPayment = order.UseIntegral,
ScorePayment = order.UseScore,
CouponPayment = order.UseCoupon,
Num = order.Num,
PrizeNum = order.PrizeNum,
Status = order.Status,
StatusName = OrderStatusNames.GetValueOrDefault(order.Status, "未知"),
PayType = order.PayType,
PayTypeName = PayTypeNames.GetValueOrDefault(order.PayType, "未知"),
CreatedAt = order.CreatedAt,
PayTime = order.PayTime > 0 ? DateTimeOffset.FromUnixTimeSeconds(order.PayTime).LocalDateTime : null,
PrizeGroups = new List<OrderPrizeGroupDto>()
};
}
/// <summary>
/// 按prize_code分组订单项
/// </summary>
private List<OrderPrizeGroupDto> GroupOrderItemsByPrizeCode(List<OrderItem> orderItems)
{
return orderItems
.GroupBy(oi => oi.PrizeCode ?? "UNKNOWN")
.Select(g => new OrderPrizeGroupDto
{
PrizeCode = g.Key == "UNKNOWN" ? null : g.Key,
Title = g.First().GoodslistTitle,
ImgUrl = g.First().GoodslistImgurl,
Price = g.First().GoodslistPrice,
RecoveryMoney = g.First().GoodslistMoney,
Count = g.Count(),
GoodsType = g.First().GoodslistType,
ShangId = g.First().ShangId,
Items = g.Select(oi => new OrderPrizeItemDto
{
Id = oi.Id,
Status = oi.Status,
StatusName = OrderItemStatusNames.GetValueOrDefault(oi.Status, "未知"),
RecoveryNum = oi.RecoveryNum,
SendNum = oi.SendNum,
LuckNo = oi.LuckNo,
CreatedAt = oi.CreatedAt
}).ToList()
})
.ToList();
}
/// <summary>
/// 映射回收订单响应
/// </summary>
private RecoveryOrderResponse MapToRecoveryOrderResponse(OrderItemsRecovery recovery, Dictionary<int, User> users, List<OrderItem> allRecoveryItems)
{
users.TryGetValue(recovery.UserId, out var user);
var items = allRecoveryItems
.Where(oi => oi.RecoveryNum == recovery.RecoveryNum)
.Select(oi => new RecoveryPrizeDto
{
Id = oi.Id,
PrizeCode = oi.PrizeCode,
Title = oi.GoodslistTitle,
ImgUrl = oi.GoodslistImgurl,
Price = oi.GoodslistPrice,
RecoveryMoney = oi.GoodslistMoney,
GoodsType = oi.GoodslistType
})
.ToList();
return new RecoveryOrderResponse
{
Id = recovery.Id,
UserId = recovery.UserId,
UserNickname = user?.Nickname,
UserMobile = user?.Mobile,
UserUid = user?.Uid,
RecoveryNum = recovery.RecoveryNum,
Money = recovery.Money,
Count = recovery.Count,
CreatedAt = recovery.CreatedAt,
Prizes = items
};
}
/// <summary>
/// 映射发货订单响应
/// </summary>
private ShippingOrderResponse MapToShippingOrderResponse(OrderItemsSend shippingOrder, Dictionary<int, User> users, List<OrderItem>? shippingItems)
{
users.TryGetValue(shippingOrder.UserId, out var user);
var prizes = shippingItems?.Select(oi => new ShippingPrizeDto
{
Id = oi.Id,
PrizeCode = oi.PrizeCode,
Title = oi.GoodslistTitle,
ImgUrl = oi.GoodslistImgurl,
Price = oi.GoodslistPrice,
GoodsType = oi.GoodslistType
}).ToList() ?? new List<ShippingPrizeDto>();
return new ShippingOrderResponse
{
Id = shippingOrder.Id,
UserId = shippingOrder.UserId,
UserNickname = user?.Nickname,
UserMobile = user?.Mobile,
UserUid = user?.Uid,
SendNum = shippingOrder.SendNum,
Freight = shippingOrder.Freight,
Status = shippingOrder.Status,
StatusName = ShippingStatusNames.GetValueOrDefault(shippingOrder.Status, "未知"),
Count = shippingOrder.Count,
Name = shippingOrder.Name,
ReceiverMobile = shippingOrder.Mobile,
Address = shippingOrder.Address,
Message = shippingOrder.Message,
CourierNumber = shippingOrder.CourierNumber,
CourierName = shippingOrder.CourierName,
CourierCode = shippingOrder.CourierCode,
DeliveryStatus = shippingOrder.DeliveryStatus,
DeliveryStatusName = DeliveryStatusNames.GetValueOrDefault(shippingOrder.DeliveryStatus, "未知"),
CreatedAt = shippingOrder.CreatedAt,
PayTime = shippingOrder.PayTime > 0 ? DateTimeOffset.FromUnixTimeSeconds(shippingOrder.PayTime).LocalDateTime : null,
SendTime = shippingOrder.SendTime > 0 ? DateTimeOffset.FromUnixTimeSeconds(shippingOrder.SendTime).LocalDateTime : null,
ReceiveTime = shippingOrder.ShouTime > 0 ? DateTimeOffset.FromUnixTimeSeconds(shippingOrder.ShouTime).LocalDateTime : null,
Prizes = prizes
};
}
/// <summary>
/// 映射订单导出数据
/// </summary>
private OrderExportDto MapToOrderExportDto(Order order, Dictionary<int, User> users)
{
users.TryGetValue(order.UserId, out var user);
return new OrderExportDto
{
OrderNum = order.OrderNum,
UserId = order.UserId,
UserNickname = user?.Nickname,
UserMobile = user?.Mobile,
GoodsTitle = order.GoodsTitle,
OrderTotal = order.OrderTotal,
DiscountTotal = order.OrderZheTotal,
WeChatPayment = order.Price,
BalancePayment = order.UseMoney,
IntegralPayment = order.UseIntegral,
ScorePayment = order.UseScore,
CouponPayment = order.UseCoupon,
Num = order.Num,
PrizeNum = order.PrizeNum,
StatusName = OrderStatusNames.GetValueOrDefault(order.Status, "未知"),
PayTypeName = PayTypeNames.GetValueOrDefault(order.PayType, "未知"),
CreatedAt = order.CreatedAt,
PayTime = order.PayTime > 0 ? DateTimeOffset.FromUnixTimeSeconds(order.PayTime).LocalDateTime : null
};
}
/// <summary>
/// 生成CSV字节数组
/// </summary>
private byte[] GenerateCsvBytes(List<OrderExportDto> data)
{
var sb = new System.Text.StringBuilder();
// 添加表头
sb.AppendLine("订单编号,用户ID,用户昵称,用户手机号,商品标题,订单总金额,折后金额,微信支付,余额支付,积分支付,钻石支付,优惠券抵扣,购买数量,中奖数量,订单状态,支付方式,创建时间,支付时间");
// 添加数据行
foreach (var item in data)
{
sb.AppendLine($"{item.OrderNum},{item.UserId},{EscapeCsvField(item.UserNickname)},{item.UserMobile},{EscapeCsvField(item.GoodsTitle)},{item.OrderTotal},{item.DiscountTotal},{item.WeChatPayment},{item.BalancePayment},{item.IntegralPayment},{item.ScorePayment},{item.CouponPayment ?? 0},{item.Num},{item.PrizeNum},{item.StatusName},{item.PayTypeName},{item.CreatedAt:yyyy-MM-dd HH:mm:ss},{item.PayTime?.ToString("yyyy-MM-dd HH:mm:ss") ?? ""}");
}
// 使用UTF-8 BOM以支持中文
var preamble = System.Text.Encoding.UTF8.GetPreamble();
var content = System.Text.Encoding.UTF8.GetBytes(sb.ToString());
var result = new byte[preamble.Length + content.Length];
preamble.CopyTo(result, 0);
content.CopyTo(result, preamble.Length);
return result;
}
/// <summary>
/// 转义CSV字段
/// </summary>
private string EscapeCsvField(string? field)
{
if (string.IsNullOrEmpty(field))
return "";
if (field.Contains(',') || field.Contains('"') || field.Contains('\n'))
{
return $"\"{field.Replace("\"", "\"\"")}\"";
}
return field;
}
/// <summary>
/// 映射发货订单导出数据
/// </summary>
private ShippingExportDto MapToShippingExportDto(OrderItemsSend shippingOrder, Dictionary<int, User> users)
{
users.TryGetValue(shippingOrder.UserId, out var user);
return new ShippingExportDto
{
SendNum = shippingOrder.SendNum,
UserId = shippingOrder.UserId,
UserNickname = user?.Nickname,
UserMobile = user?.Mobile,
Name = shippingOrder.Name,
ReceiverMobile = shippingOrder.Mobile,
Address = shippingOrder.Address,
Count = shippingOrder.Count,
Freight = shippingOrder.Freight,
StatusName = ShippingStatusNames.GetValueOrDefault(shippingOrder.Status, "未知"),
CourierName = shippingOrder.CourierName,
CourierNumber = shippingOrder.CourierNumber,
Message = shippingOrder.Message,
CreatedAt = shippingOrder.CreatedAt,
SendTime = shippingOrder.SendTime > 0 ? DateTimeOffset.FromUnixTimeSeconds(shippingOrder.SendTime).LocalDateTime : null
};
}
/// <summary>
/// 映射回收订单导出数据
/// </summary>
private RecoveryExportDto MapToRecoveryExportDto(OrderItemsRecovery recovery, Dictionary<int, User> users)
{
users.TryGetValue(recovery.UserId, out var user);
return new RecoveryExportDto
{
RecoveryNum = recovery.RecoveryNum,
UserId = recovery.UserId,
UserNickname = user?.Nickname,
UserMobile = user?.Mobile,
Money = recovery.Money,
Count = recovery.Count,
CreatedAt = recovery.CreatedAt
};
}
/// <summary>
/// 生成发货订单CSV字节数组
/// </summary>
private byte[] GenerateShippingCsvBytes(List<ShippingExportDto> data)
{
var sb = new System.Text.StringBuilder();
// 添加表头
sb.AppendLine("发货单号,用户ID,用户昵称,用户手机号,收货人,收货手机号,收货地址,发货数量,运费,状态,快递公司,快递单号,备注,创建时间,发货时间");
// 添加数据行
foreach (var item in data)
{
sb.AppendLine($"{item.SendNum},{item.UserId},{EscapeCsvField(item.UserNickname)},{item.UserMobile},{EscapeCsvField(item.Name)},{item.ReceiverMobile},{EscapeCsvField(item.Address)},{item.Count},{item.Freight},{item.StatusName},{EscapeCsvField(item.CourierName)},{item.CourierNumber},{EscapeCsvField(item.Message)},{item.CreatedAt:yyyy-MM-dd HH:mm:ss},{item.SendTime?.ToString("yyyy-MM-dd HH:mm:ss") ?? ""}");
}
// 使用UTF-8 BOM以支持中文
var preamble = System.Text.Encoding.UTF8.GetPreamble();
var content = System.Text.Encoding.UTF8.GetBytes(sb.ToString());
var result = new byte[preamble.Length + content.Length];
preamble.CopyTo(result, 0);
content.CopyTo(result, preamble.Length);
return result;
}
/// <summary>
/// 生成回收订单CSV字节数组
/// </summary>
private byte[] GenerateRecoveryCsvBytes(List<RecoveryExportDto> data)
{
var sb = new System.Text.StringBuilder();
// 添加表头
sb.AppendLine("回收单号,用户ID,用户昵称,用户手机号,回收金额,回收数量,创建时间");
// 添加数据行
foreach (var item in data)
{
sb.AppendLine($"{item.RecoveryNum},{item.UserId},{EscapeCsvField(item.UserNickname)},{item.UserMobile},{item.Money},{item.Count},{item.CreatedAt:yyyy-MM-dd HH:mm:ss}");
}
// 使用UTF-8 BOM以支持中文
var preamble = System.Text.Encoding.UTF8.GetPreamble();
var content = System.Text.Encoding.UTF8.GetBytes(sb.ToString());
var result = new byte[preamble.Length + content.Length];
preamble.CopyTo(result, 0);
content.CopyTo(result, preamble.Length);
return result;
}
/// <summary>
/// 记录订单操作日志
/// </summary>
private async Task LogOrderOperationAsync(int orderId, string operation, string content, int operatorId)
{
var log = new AdminOperationLog
{
AdminId = operatorId,
Operation = $"order:{operation}",
Content = $"OrderId={orderId}, {content}",
Ip = string.Empty,
CreatedAt = DateTime.Now
};
_dbContext.AdminOperationLogs.Add(log);
await _dbContext.SaveChangesAsync();
}
#endregion
}