131 lines
6.9 KiB
C#
131 lines
6.9 KiB
C#
using Distribution.Data;
|
|
using Distribution.Models;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace Distribution.Features.Vehicle;
|
|
|
|
public class VehicleDashboardRepository(AppDBContext db) : IVehicleDashboardRepository
|
|
{
|
|
public Task<List<VehicleBalanceRow>> GetStockOnBoardAsync(Guid vehicleId) =>
|
|
db.StockBalances.AsNoTracking()
|
|
.Where(b => b.LocationType == LocationType.Vehicle && b.LocationId == vehicleId && b.Quantity > 0)
|
|
.Select(b => new VehicleBalanceRow(
|
|
b.FK_ItemId, b.Item.Sku, b.Item.Name, b.Item.Category.Name, b.Item.BaseUom.Name,
|
|
b.Item.SalePrice, b.Quantity, b.UpdatedAt))
|
|
.ToListAsync();
|
|
|
|
public Task<List<VehicleMovementRow>> GetMovementsAsync(Guid vehicleId, DateTime from, DateTime toExclusive) =>
|
|
db.StockMovements.AsNoTracking()
|
|
.Where(m => (m.FromLocationId == vehicleId || m.ToLocationId == vehicleId)
|
|
&& m.CreatedAt >= from && m.CreatedAt < toExclusive)
|
|
.OrderByDescending(m => m.CreatedAt)
|
|
.Select(m => new VehicleMovementRow(
|
|
m.Id, m.FK_ItemId, m.Item.Name, m.Item.Sku,
|
|
m.FromLocationId, m.FromLocationType, m.ToLocationId, m.ToLocationType,
|
|
m.Quantity, m.Type, m.ReasonCode, m.ReferenceId, m.CreatedAt, m.CreatedBy))
|
|
.ToListAsync();
|
|
|
|
public Task<List<VehicleRideRow>> GetRidesAsync(Guid vehicleId, DateTime from, DateTime toExclusive) =>
|
|
db.DeliveryRuns.AsNoTracking()
|
|
.Where(r => r.FK_VehicleId == vehicleId
|
|
&& (r.StartedAt ?? r.CreatedAt) >= from && (r.StartedAt ?? r.CreatedAt) < toExclusive)
|
|
.OrderByDescending(r => r.StartedAt ?? r.CreatedAt)
|
|
.Select(r => new VehicleRideRow(
|
|
r.Id, r.Status, r.FK_DriverProfileId, r.DriverProfile.User.FullName,
|
|
r.Meterstart, r.Meterend, r.StartedAt, r.ClosedAt, r.CreatedAt,
|
|
r.CancelTypeCode, r.CancelReason,
|
|
db.DeliveryTasks.Count(t => t.FK_RideId == r.Id),
|
|
db.DeliveryTasks.Count(t => t.FK_RideId == r.Id
|
|
&& (t.Status == DeliveryTaskStatus.Delivered || t.Status == DeliveryTaskStatus.PartiallyDelivered)),
|
|
db.DeliveryTasks.Count(t => t.FK_RideId == r.Id && t.Status == DeliveryTaskStatus.Failed)))
|
|
.ToListAsync();
|
|
|
|
public Task<VehicleRideRow?> GetOpenRideAsync(Guid vehicleId) =>
|
|
db.DeliveryRuns.AsNoTracking()
|
|
.Where(r => r.FK_VehicleId == vehicleId && r.Status == RideStatus.Open)
|
|
.Select(r => new VehicleRideRow(
|
|
r.Id, r.Status, r.FK_DriverProfileId, r.DriverProfile.User.FullName,
|
|
r.Meterstart, r.Meterend, r.StartedAt, r.ClosedAt, r.CreatedAt,
|
|
r.CancelTypeCode, r.CancelReason,
|
|
db.DeliveryTasks.Count(t => t.FK_RideId == r.Id),
|
|
db.DeliveryTasks.Count(t => t.FK_RideId == r.Id
|
|
&& (t.Status == DeliveryTaskStatus.Delivered || t.Status == DeliveryTaskStatus.PartiallyDelivered)),
|
|
db.DeliveryTasks.Count(t => t.FK_RideId == r.Id && t.Status == DeliveryTaskStatus.Failed)))
|
|
.FirstOrDefaultAsync();
|
|
|
|
public Task<List<VehicleTaskRow>> GetTasksAsync(Guid vehicleId, DateTime from, DateTime toExclusive) =>
|
|
db.DeliveryTasks.AsNoTracking()
|
|
.Where(t => t.Ride.FK_VehicleId == vehicleId
|
|
&& (t.Ride.StartedAt ?? t.Ride.CreatedAt) >= from && (t.Ride.StartedAt ?? t.Ride.CreatedAt) < toExclusive)
|
|
.Select(t => new VehicleTaskRow(
|
|
t.FK_RideId, t.Status, t.ShopPO.FK_StoreId, t.ShopPO.Store.StoreName,
|
|
t.ShopPO.Items.Sum(i => i.QuantityFulfilled * i.UnitPrice),
|
|
t.Ride.StartedAt ?? t.Ride.CreatedAt))
|
|
.ToListAsync();
|
|
|
|
public Task<List<VehicleCollectionRow>> GetCollectionsAsync(Guid vehicleId, DateTime from, DateTime toExclusive) =>
|
|
db.Payments.AsNoTracking()
|
|
.Where(p => p.CollectedAt >= from && p.CollectedAt < toExclusive
|
|
&& db.DeliveryTasks.Any(t => t.Ride.FK_VehicleId == vehicleId && t.FK_ShopPOId == p.Invoice.FK_ShopPOId))
|
|
.GroupBy(p => p.Method)
|
|
.Select(g => new VehicleCollectionRow(g.Key, g.Sum(p => p.Amount), g.Count()))
|
|
.ToListAsync();
|
|
|
|
public async Task<VehicleReturnTotals> GetReturnTotalsAsync(Guid vehicleId, DateTime from, DateTime toExclusive)
|
|
{
|
|
var returns = db.SaleReturns.AsNoTracking()
|
|
.Where(r => r.CreatedAt >= from && r.CreatedAt < toExclusive
|
|
&& db.DeliveryTasks.Any(t => t.Ride.FK_VehicleId == vehicleId && t.FK_ShopPOId == r.FK_ShopPOId));
|
|
var count = await returns.CountAsync();
|
|
var credit = await returns.SumAsync(r => (decimal?)r.TotalCreditAmount) ?? 0m;
|
|
var units = await returns.SelectMany(r => r.Items).SumAsync(i => (decimal?)i.Quantity) ?? 0m;
|
|
return new VehicleReturnTotals(count, credit, units);
|
|
}
|
|
|
|
public Task<List<VehicleDriverRow>> GetDriversAsync(IEnumerable<Guid> driverProfileIds)
|
|
{
|
|
var ids = driverProfileIds.Distinct().ToList();
|
|
return db.DriverProfiles.AsNoTracking()
|
|
.Where(d => ids.Contains(d.Id))
|
|
.Select(d => new VehicleDriverRow(
|
|
d.Id, d.User.FullName, d.LicenseNumber, d.LicenseExpiry, d.MedicalClearanceExpiry, d.IsActive))
|
|
.ToListAsync();
|
|
}
|
|
|
|
public Task<VehicleNamedRef?> GetWarehouseRefAsync(Guid? warehouseId) =>
|
|
warehouseId is null
|
|
? Task.FromResult<VehicleNamedRef?>(null)
|
|
: db.Warehouses.AsNoTracking()
|
|
.Where(w => w.Id == warehouseId)
|
|
.Select(w => new VehicleNamedRef(w.Id, w.Name))
|
|
.FirstOrDefaultAsync();
|
|
|
|
public Task<VehicleNamedRef?> GetMobileWarehouseAsync(Guid vehicleId) =>
|
|
db.Warehouses.AsNoTracking()
|
|
.Where(w => w.VehicleId == vehicleId)
|
|
.Select(w => new VehicleNamedRef(w.Id, w.Name))
|
|
.FirstOrDefaultAsync();
|
|
|
|
public async Task<Dictionary<Guid, string>> GetLocationNamesAsync(IEnumerable<Guid> ids)
|
|
{
|
|
var idList = ids.Distinct().ToList();
|
|
var names = new Dictionary<Guid, string>();
|
|
if (idList.Count == 0) return names;
|
|
|
|
foreach (var w in await db.Warehouses.AsNoTracking().Where(w => idList.Contains(w.Id)).Select(w => new { w.Id, w.Name }).ToListAsync())
|
|
names[w.Id] = w.Name;
|
|
foreach (var v in await db.Vehicles.AsNoTracking().Where(v => idList.Contains(v.Id)).Select(v => new { v.Id, v.RegNumber }).ToListAsync())
|
|
names[v.Id] = v.RegNumber;
|
|
return names;
|
|
}
|
|
|
|
public async Task<Dictionary<Guid, string>> GetUserNamesAsync(IEnumerable<Guid> ids)
|
|
{
|
|
var idList = ids.Distinct().ToList();
|
|
if (idList.Count == 0) return [];
|
|
return await db.Users.AsNoTracking()
|
|
.Where(u => idList.Contains(u.Id))
|
|
.ToDictionaryAsync(u => u.Id, u => u.FullName);
|
|
}
|
|
}
|