using Fake.DependencyInjection; using Oms.Domain.OrdersAggregate; using Oms.Domain.OrdersAggregate.Consts; using Oms.Domain.OrdersAggregate.Entities; using Oms.Domain.OrdersAggregate.Repositories; using Oms.SqlSugarCore.Repositories; using SqlSugar; namespace Oms.SqlSugarCore.Orders; public class OrderRepository : OmsSqlSugarRepository, IOrderRepository, IScopedDependency { public async Task<(List Items, int Total)> GetFilteredPagedListAsync( int pageIndex, int pageSize, OrderListFilter filter, CancellationToken cancellationToken = default) { var db = await GetDbContextAsync(cancellationToken); var query = ApplyListFilter(db.Queryable(), filter); var total = await query.CountAsync(cancellationToken); var items = await query .OrderBy(x => x.UpdateTime, OrderByType.Desc) .OrderBy(x => x.Id, OrderByType.Desc) .ToPageListAsync(pageIndex, pageSize, cancellationToken); return (items, total); } public async Task> GetFilteredListAsync( OrderListFilter filter, CancellationToken cancellationToken = default) { var db = await GetDbContextAsync(cancellationToken); return await ApplyListFilter(db.Queryable(), filter) .OrderBy(x => x.UpdateTime, OrderByType.Desc) .OrderBy(x => x.Id, OrderByType.Desc) .ToListAsync(cancellationToken); } private static ISugarQueryable ApplyListFilter(ISugarQueryable query, OrderListFilter filter) { if (filter.CustomerId.HasValue) { var customerId = filter.CustomerId.Value; query = query.Where(x => x.CustomerId == customerId); } var status = filter.Status?.Trim(); if (!string.IsNullOrWhiteSpace(status) && !string.Equals(status, "all", StringComparison.OrdinalIgnoreCase)) { query = query.Where(x => x.OrderStatus == status); } var keyword = filter.Keyword?.Trim(); if (!string.IsNullOrWhiteSpace(keyword)) { query = query.Where(x => x.ServiceNo.Contains(keyword) || (x.ClientNo ?? string.Empty).Contains(keyword) || (x.TrackNo ?? string.Empty).Contains(keyword)); } if (filter.CreateTimeStart.HasValue) { var start = filter.CreateTimeStart.Value; query = query.Where(x => x.CreateTime >= start); } if (filter.CreateTimeEnd.HasValue) { var end = filter.CreateTimeEnd.Value; query = query.Where(x => x.CreateTime <= end); } query = OrderListScopeFilterApplier.Apply(query, filter); return query; } public Task GetByServiceNoAsync(string serviceNo, CancellationToken cancellationToken = default) { return FirstOrDefaultAsync(x => x.ServiceNo == serviceNo, cancellationToken); } public Task HasServiceNoAsync(string serviceNo, CancellationToken cancellationToken = default) { return AnyAsync(x => x.ServiceNo == serviceNo, cancellationToken); } public Task GetByTrackNoAsync(string trackNo, CancellationToken cancellationToken = default) { return FirstOrDefaultAsync(x => x.TrackNo == trackNo, cancellationToken); } public async Task GetByWaybillNoAsync(string waybillNo, CancellationToken cancellationToken = default) { var normalized = waybillNo.Trim(); if (string.IsNullOrWhiteSpace(normalized)) { return null; } var order = await GetByServiceNoAsync(normalized, cancellationToken); if (order != null) { return order; } order = await GetByTrackNoAsync(normalized, cancellationToken); if (order != null) { return order; } return await FirstOrDefaultAsync(x => x.ClientNo == normalized, cancellationToken); } public Task GetByCustomerAndClientNoAsync(int customerId, string clientNo, CancellationToken cancellationToken = default) { return FirstOrDefaultAsync(x => x.CustomerId == customerId && x.ClientNo == clientNo, cancellationToken); } public Task GetByRequestIdAsync(string requestId, CancellationToken cancellationToken = default) { return FirstOrDefaultAsync(x => x.RequestId == requestId, cancellationToken); } public async Task> GetSendersByOrderIdsAsync(IEnumerable orderIds, CancellationToken cancellationToken = default) { var ids = orderIds.Distinct().ToArray(); if (ids.Length == 0) { return []; } var db = await GetDbContextAsync(cancellationToken); return await db.Queryable() .Where(x => ids.Contains(x.OrderId)) .ToListAsync(cancellationToken); } public async Task> GetRecipientsByOrderIdsAsync(IEnumerable orderIds, CancellationToken cancellationToken = default) { var ids = orderIds.Distinct().ToArray(); if (ids.Length == 0) { return []; } var db = await GetDbContextAsync(cancellationToken); return await db.Queryable() .Where(x => ids.Contains(x.OrderId)) .ToListAsync(cancellationToken); } public async Task> GetDeclarationsByOrderIdsAsync(IEnumerable orderIds, CancellationToken cancellationToken = default) { var ids = orderIds.Distinct().ToArray(); if (ids.Length == 0) { return []; } var db = await GetDbContextAsync(cancellationToken); return await db.Queryable() .Where(x => ids.Contains(x.OrderId)) .ToListAsync(cancellationToken); } public async Task> GetWeightsByOrderIdsAsync(IEnumerable orderIds, CancellationToken cancellationToken = default) { var ids = orderIds.Distinct().ToArray(); if (ids.Length == 0) { return []; } var db = await GetDbContextAsync(cancellationToken); return await db.Queryable() .Where(x => ids.Contains(x.OrderId)) .ToListAsync(cancellationToken); } public async Task InsertSenderAsync(OrderSender sender, CancellationToken cancellationToken = default) { var db = await GetDbContextAsync(cancellationToken); return await db.Insertable(sender).ExecuteReturnEntityAsync(); } public async Task InsertRecipientAsync(OrderRecipient recipient, CancellationToken cancellationToken = default) { var db = await GetDbContextAsync(cancellationToken); return await db.Insertable(recipient).ExecuteReturnEntityAsync(); } public async Task InsertDeclarationsAsync(IEnumerable declarations, CancellationToken cancellationToken = default) { var items = declarations.ToArray(); if (items.Length == 0) { return; } var db = await GetDbContextAsync(cancellationToken); await db.Insertable(items).ExecuteCommandAsync(cancellationToken); } public async Task ReplaceDeclarationsAsync(int orderId, IEnumerable declarations, CancellationToken cancellationToken = default) { var items = declarations.ToArray(); var db = await GetDbContextAsync(cancellationToken); await db.Deleteable().Where(x => x.OrderId == orderId).ExecuteCommandAsync(cancellationToken); if (items.Length > 0) { await db.Insertable(items).ExecuteCommandAsync(cancellationToken); } } public async Task InsertWeightsAsync(IEnumerable weights, CancellationToken cancellationToken = default) { var items = weights.ToArray(); if (items.Length == 0) { return; } var db = await GetDbContextAsync(cancellationToken); await db.Insertable(items).ExecuteCommandAsync(cancellationToken); } public async Task ReplaceWeightsAsync(int orderId, IEnumerable weights, CancellationToken cancellationToken = default) { var items = weights.ToArray(); var db = await GetDbContextAsync(cancellationToken); await db.Deleteable().Where(x => x.OrderId == orderId).ExecuteCommandAsync(cancellationToken); if (items.Length > 0) { await db.Insertable(items).ExecuteCommandAsync(cancellationToken); } } public async Task UpsertFeesAsync(int orderId, IEnumerable fees, CancellationToken cancellationToken = default) { var items = fees.ToArray(); if (items.Length == 0) { return; } var db = await GetDbContextAsync(cancellationToken); foreach (var fee in items) { fee.OrderId = orderId; var existingList = await db.Queryable() .Where(x => x.OrderId == orderId && x.Type == fee.Type && x.CostItem == fee.CostItem && x.ChargingStage == fee.ChargingStage) .Take(1) .ToListAsync(cancellationToken); var existing = existingList.FirstOrDefault(); if (existing == null) { await db.Insertable(fee).ExecuteCommandAsync(cancellationToken); continue; } existing.Amount = fee.Amount; existing.Currency = fee.Currency; existing.PriceNo = fee.PriceNo; existing.PriceEffectiveTime = fee.PriceEffectiveTime; existing.DownstreamProvider = fee.DownstreamProvider; existing.UpdateTime = DateTime.Now; await db.Updateable(existing).ExecuteCommandAsync(cancellationToken); } } public async Task DeleteReceivableFeesAsync(int orderId, CancellationToken cancellationToken = default) { var db = await GetDbContextAsync(cancellationToken); await db.Deleteable() .Where(x => x.OrderId == orderId && x.Type == OrderFeeTypeCodes.Receivable) .ExecuteCommandAsync(cancellationToken); } public async Task DeleteReceivableFeesByStageAsync(int orderId, string chargingStage, CancellationToken cancellationToken = default) { var db = await GetDbContextAsync(cancellationToken); await db.Deleteable() .Where(x => x.OrderId == orderId && x.Type == OrderFeeTypeCodes.Receivable && x.ChargingStage == chargingStage) .ExecuteCommandAsync(cancellationToken); } public async Task DeletePayableFeesAsync(int orderId, CancellationToken cancellationToken = default) { var db = await GetDbContextAsync(cancellationToken); await db.Deleteable() .Where(x => x.OrderId == orderId && x.Type == OrderFeeTypeCodes.Payable) .ExecuteCommandAsync(cancellationToken); } public async Task DeletePayableFeesByStageAsync(int orderId, string chargingStage, CancellationToken cancellationToken = default) { var db = await GetDbContextAsync(cancellationToken); await db.Deleteable() .Where(x => x.OrderId == orderId && x.Type == OrderFeeTypeCodes.Payable && x.ChargingStage == chargingStage) .ExecuteCommandAsync(cancellationToken); } public async Task UpdateSenderAsync(OrderSender sender, CancellationToken cancellationToken = default) { var db = await GetDbContextAsync(cancellationToken); sender.UpdateTime = DateTime.Now; await db.Updateable(sender).ExecuteCommandAsync(cancellationToken); } public async Task UpdateRecipientAsync(OrderRecipient recipient, CancellationToken cancellationToken = default) { var db = await GetDbContextAsync(cancellationToken); recipient.UpdateTime = DateTime.Now; await db.Updateable(recipient).ExecuteCommandAsync(cancellationToken); } public async Task> GetFeesByOrderIdsAsync(IEnumerable orderIds, CancellationToken cancellationToken = default) { var ids = orderIds.Distinct().ToArray(); if (ids.Length == 0) { return []; } var db = await GetDbContextAsync(cancellationToken); return await db.Queryable() .Where(x => ids.Contains(x.OrderId)) .ToListAsync(cancellationToken); } public async Task<(List Items, int Total)> GetReceivablePayablePagedListAsync( int pageIndex, int pageSize, OrderReceivablePayableFilter filter, CancellationToken cancellationToken = default) { var db = await GetDbContextAsync(cancellationToken); var orderIdsQuery = ApplyListFilter(db.Queryable(), filter).Select(x => x.Id); var feeQuery = db.Queryable() .Where(fee => !fee.IsDeleted) .In(fee => fee.OrderId, orderIdsQuery); var feeType = filter.FeeType?.Trim(); if (!string.IsNullOrWhiteSpace(feeType) && !string.Equals(feeType, "all", StringComparison.OrdinalIgnoreCase)) { feeQuery = feeQuery.Where(fee => fee.Type == feeType); } var costItem = filter.CostItem?.Trim(); if (!string.IsNullOrWhiteSpace(costItem)) { feeQuery = feeQuery.Where(fee => fee.CostItem.Contains(costItem)); } var chargingStage = filter.ChargingStage?.Trim(); if (!string.IsNullOrWhiteSpace(chargingStage) && !string.Equals(chargingStage, "all", StringComparison.OrdinalIgnoreCase)) { feeQuery = feeQuery.Where(fee => fee.ChargingStage == chargingStage); } var total = await feeQuery.CountAsync(cancellationToken); var fees = await feeQuery .OrderBy(fee => fee.CreateTime, OrderByType.Desc) .OrderBy(fee => fee.Id, OrderByType.Desc) .ToPageListAsync(pageIndex, pageSize, cancellationToken); if (fees.Count == 0) { return ([], total); } var orderIds = fees.Select(x => x.OrderId).Distinct().ToArray(); var orders = await db.Queryable() .Where(x => orderIds.Contains(x.Id)) .ToListAsync(cancellationToken); var orderMap = orders.ToDictionary(x => x.Id); var items = fees .Where(fee => orderMap.ContainsKey(fee.OrderId)) .Select(fee => new OrderReceivablePayableRow { Fee = fee, Order = orderMap[fee.OrderId] }) .ToList(); return (items, total); } public async Task> GetStatusCountsAsync(int? customerId, CancellationToken cancellationToken = default) { var filter = new OrderListFilter { CustomerId = customerId }; return await GetStatusCountsByFilterAsync(filter, cancellationToken); } public async Task> GetStatusCountsByFilterAsync( OrderListFilter filter, CancellationToken cancellationToken = default) { var db = await GetDbContextAsync(cancellationToken); var query = ApplyListFilter(db.Queryable(), filter); return await query .GroupBy(x => x.OrderStatus) .Select(x => new OrderStatusCountRow { Status = x.OrderStatus, Count = SqlFunc.AggregateCount(x.Id) }) .ToListAsync(cancellationToken); } public async Task CountByFilterAndCreateTimeRangeAsync( OrderListFilter filter, DateTime startInclusive, DateTime endExclusive, CancellationToken cancellationToken = default) { var db = await GetDbContextAsync(cancellationToken); var query = ApplyListFilter(db.Queryable(), filter) .Where(x => x.CreateTime >= startInclusive && x.CreateTime < endExclusive) .Where(x => x.OrderStatus != OrderStatusCodes.Deleted); return await query.CountAsync(cancellationToken); } public async Task CountByFilterAndShipTimeRangeAsync( OrderListFilter filter, DateTime startInclusive, DateTime endExclusive, CancellationToken cancellationToken = default) { var db = await GetDbContextAsync(cancellationToken); var query = ApplyListFilter(db.Queryable(), filter) .Where(x => x.ShipTime != null && x.ShipTime >= startInclusive && x.ShipTime < endExclusive) .Where(x => x.OrderStatus != OrderStatusCodes.Deleted); return await query.CountAsync(cancellationToken); } public async Task SumFeeAmountByPayTimeRangeAsync( OrderListFilter filter, string feeType, DateTime startInclusive, DateTime endExclusive, CancellationToken cancellationToken = default) { var db = await GetDbContextAsync(cancellationToken); var orderQuery = ApplyListFilter(db.Queryable(), filter) .Where(x => x.PayTime != null && x.PayTime >= startInclusive && x.PayTime < endExclusive) .Where(x => x.OrderStatus != OrderStatusCodes.Deleted); var orderIds = await orderQuery.Select(x => x.Id).ToListAsync(cancellationToken); if (orderIds.Count == 0) { return 0m; } return await db.Queryable() .Where(x => orderIds.Contains(x.OrderId)) .Where(x => x.Type == feeType) .SumAsync(x => x.Amount); } public async Task> GetOrdersByFilterAndCreateTimeRangeAsync( OrderListFilter filter, DateTime startInclusive, DateTime endExclusive, CancellationToken cancellationToken = default) { var db = await GetDbContextAsync(cancellationToken); return await ApplyListFilter(db.Queryable(), filter) .Where(x => x.CreateTime >= startInclusive && x.CreateTime < endExclusive) .Where(x => x.OrderStatus != OrderStatusCodes.Deleted) .ToListAsync(cancellationToken); } }