Wrote tests for most services, applied EF core optimisations
This commit is contained in:
@@ -49,6 +49,17 @@ public sealed class OrderService(IDbContextFactory<MidrandBooksDbContext> contex
|
||||
if (!await context.Prices.AnyAsync(pp => pp.Id == request.ProductPriceId, cancellationToken))
|
||||
return Result.Fail<long>("Product price not found.");
|
||||
|
||||
var existingItem = await context.OrderItems.FirstOrDefaultAsync(i => i.ProductPriceId == request.ProductPriceId && i.OrderId == orderId, cancellationToken);
|
||||
|
||||
if(existingItem is not null)
|
||||
{
|
||||
existingItem.Quantity += request.Quantity;
|
||||
|
||||
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||
? Result.Ok(existingItem.Id)
|
||||
: Result.Fail<long>("Update existing order item.");
|
||||
}
|
||||
|
||||
var orderItem = context.OrderItems.Add(new Entities.OrderItem
|
||||
{
|
||||
OrderId = orderId,
|
||||
@@ -78,9 +89,6 @@ public sealed class OrderService(IDbContextFactory<MidrandBooksDbContext> contex
|
||||
|
||||
if (!await context.Orders.AnyAsync(o => o.Id == orderId, cancellationToken))
|
||||
return Result.Fail("Order not found.");
|
||||
|
||||
var existingItems = context.OrderItems.Where(oi => oi.OrderId == orderId);
|
||||
context.OrderItems.RemoveRange(existingItems);
|
||||
|
||||
foreach (var item in items)
|
||||
{
|
||||
@@ -90,18 +98,23 @@ public sealed class OrderService(IDbContextFactory<MidrandBooksDbContext> contex
|
||||
if (!await context.Prices.AnyAsync(pp => pp.Id == item.ProductPriceId, cancellationToken))
|
||||
return Result.Fail($"Product price with ID {item.ProductPriceId} not found.");
|
||||
|
||||
context.OrderItems.Add(new Entities.OrderItem
|
||||
{
|
||||
OrderId = orderId,
|
||||
AuthorBookId = item.AuthorBookId,
|
||||
ProductPriceId = item.ProductPriceId,
|
||||
Quantity = item.Quantity
|
||||
});
|
||||
var existingItem = await context.OrderItems.FirstOrDefaultAsync(i => i.ProductPriceId == item.ProductPriceId && i.OrderId == orderId, cancellationToken);
|
||||
|
||||
if (existingItem is not null)
|
||||
existingItem.Quantity += item.Quantity;
|
||||
else
|
||||
context.OrderItems.Add(new Entities.OrderItem
|
||||
{
|
||||
OrderId = orderId,
|
||||
AuthorBookId = item.AuthorBookId,
|
||||
ProductPriceId = item.ProductPriceId,
|
||||
Quantity = item.Quantity
|
||||
});
|
||||
|
||||
await context.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||
? Result.Ok()
|
||||
: Result.Fail("Failed to add items to order.");
|
||||
return Result.Ok();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -115,16 +128,13 @@ public sealed class OrderService(IDbContextFactory<MidrandBooksDbContext> contex
|
||||
{
|
||||
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||
|
||||
var orderItem = await context.OrderItems.FirstOrDefaultAsync(oi => oi.Id == orderItemId && oi.OrderId == orderId, cancellationToken);
|
||||
var rowsDeleted = await context.OrderItems
|
||||
.Where(oi => oi.Id == orderItemId && oi.OrderId == orderId)
|
||||
.ExecuteDeleteAsync(cancellationToken);
|
||||
|
||||
if (orderItem is null)
|
||||
return Result.Fail("Order item not found.");
|
||||
|
||||
context.OrderItems.Remove(orderItem);
|
||||
|
||||
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||
return rowsDeleted > 0
|
||||
? Result.Ok()
|
||||
: Result.Fail("Failed to remove item from order.");
|
||||
: Result.Fail("Order item not found or failed to remove.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -132,15 +142,14 @@ public sealed class OrderService(IDbContextFactory<MidrandBooksDbContext> contex
|
||||
}
|
||||
}
|
||||
|
||||
public async ValueTask<Result> ClearOrderItemasAsync(long orderId, CancellationToken cancellationToken = default)
|
||||
public async ValueTask<Result> ClearOrderItemsAsync(long orderId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||
|
||||
var orderItems = context.OrderItems.Where(oi => oi.OrderId == orderId);
|
||||
|
||||
context.OrderItems.RemoveRange(orderItems);
|
||||
var deletedItems = await context.OrderItems.Where(oi => oi.OrderId == orderId)
|
||||
.ExecuteDeleteAsync(cancellationToken);
|
||||
|
||||
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||
? Result.Ok()
|
||||
@@ -199,12 +208,15 @@ public sealed class OrderService(IDbContextFactory<MidrandBooksDbContext> contex
|
||||
{
|
||||
try
|
||||
{
|
||||
var fromDate = range.From.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc);
|
||||
var toDate = range.To.ToDateTime(TimeOnly.MaxValue, DateTimeKind.Utc);
|
||||
|
||||
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||
|
||||
var orders = await context.Orders
|
||||
.AsNoTracking()
|
||||
.Where(o => o.CreatedAt >= range.From.ToDateTime(TimeOnly.MinValue) && o.CreatedAt <= range.To.ToDateTime(TimeOnly.MaxValue))
|
||||
.Skip(index * range.MaxRecords)
|
||||
.Where(o => o.CreatedAt >= fromDate && o.CreatedAt <= toDate)
|
||||
.Skip(index).Take(range.MaxRecords)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
return Result.Ok(orders.Select(o => o.ToModel()).ToArray());
|
||||
@@ -221,17 +233,15 @@ public sealed class OrderService(IDbContextFactory<MidrandBooksDbContext> contex
|
||||
{
|
||||
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||
|
||||
var order = await context.Orders.FirstOrDefaultAsync(o => o.Id == orderId, cancellationToken);
|
||||
var rowsUpdated = await context.Orders
|
||||
.Where(o => o.Id == orderId)
|
||||
.ExecuteUpdateAsync(setters => setters
|
||||
.SetProperty(o => o.Status, newStatus)
|
||||
.SetProperty(o => o.UpdatedAt, DateTime.UtcNow), cancellationToken);
|
||||
|
||||
if (order is null)
|
||||
return Result.Fail("Order not found.");
|
||||
|
||||
order.UpdatedAt = DateTime.UtcNow;
|
||||
order.Status = newStatus;
|
||||
|
||||
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||
return rowsUpdated > 0
|
||||
? Result.Ok()
|
||||
: Result.Fail("Failed to update order status.");
|
||||
: Result.Fail("Order not found or status update failed.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -282,17 +292,16 @@ public sealed class OrderService(IDbContextFactory<MidrandBooksDbContext> contex
|
||||
{
|
||||
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||
|
||||
var shipping = await context.Shippings.FirstOrDefaultAsync(s => s.OrderId == orderId, cancellationToken);
|
||||
var rowsUpdated = await context.Shippings
|
||||
.Where(s => s.OrderId == orderId)
|
||||
.ExecuteUpdateAsync(setters => setters
|
||||
.SetProperty(s => s.Status, newStatus)
|
||||
.SetProperty(s => s.UpdatedAt, DateTime.UtcNow),
|
||||
cancellationToken);
|
||||
|
||||
if (shipping is null)
|
||||
return Result.Fail("Shipping not found for this order.");
|
||||
|
||||
shipping.UpdatedAt = DateTime.UtcNow;
|
||||
shipping.Status = newStatus;
|
||||
|
||||
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||
return rowsUpdated > 0
|
||||
? Result.Ok()
|
||||
: Result.Fail("Failed to update shipping status.");
|
||||
: Result.Fail("Shipping not found for this order or status update failed.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -325,21 +334,14 @@ public sealed class OrderService(IDbContextFactory<MidrandBooksDbContext> contex
|
||||
try
|
||||
{
|
||||
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||
|
||||
var rowsDeleted = await context.Shippings
|
||||
.Where(s => s.Id == shippingId && s.OrderId == orderId)
|
||||
.ExecuteDeleteAsync(cancellationToken);
|
||||
|
||||
if(!await context.Orders.AnyAsync(o => o.Id == orderId, cancellationToken))
|
||||
return Result.Fail("Order not found.");
|
||||
|
||||
var shipping = await context.Shippings.AsNoTracking()
|
||||
.FirstOrDefaultAsync(s => s.OrderId == orderId && s.Id == shippingId, cancellationToken);
|
||||
|
||||
if (shipping is null)
|
||||
return Result.Fail("Shipping not found for this order.");
|
||||
|
||||
context.Shippings.Remove(shipping);
|
||||
|
||||
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||
return rowsDeleted > 0
|
||||
? Result.Ok()
|
||||
: Result.Fail("Failed to remove shipping from order.");
|
||||
: Result.Fail("Shipping record not found for this order.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -353,17 +355,15 @@ public sealed class OrderService(IDbContextFactory<MidrandBooksDbContext> contex
|
||||
{
|
||||
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||
|
||||
var shipping = await context.Shippings.FirstOrDefaultAsync(s => s.OrderId == orderId && s.Id == shippingId, cancellationToken);
|
||||
var rowsUpdated = await context.Shippings
|
||||
.Where(s => s.Id == shippingId && s.OrderId == orderId)
|
||||
.ExecuteUpdateAsync(setters => setters
|
||||
.SetProperty(s => s.TrackingNumber, trackingNumber)
|
||||
.SetProperty(s => s.UpdatedAt, DateTime.UtcNow), cancellationToken);
|
||||
|
||||
if (shipping is null)
|
||||
return Result.Fail("Shipping not found for this order.");
|
||||
|
||||
shipping.UpdatedAt = DateTime.UtcNow;
|
||||
shipping.TrackingNumber = trackingNumber;
|
||||
|
||||
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||
return rowsUpdated > 0
|
||||
? Result.Ok()
|
||||
: Result.Fail("Failed to update shipping tracking number.");
|
||||
: Result.Fail("Shipping record not found for this order.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -440,24 +440,22 @@ public sealed class OrderService(IDbContextFactory<MidrandBooksDbContext> contex
|
||||
{
|
||||
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||
|
||||
var provider = await context.ShippingProviders.FirstOrDefaultAsync(sp => sp.Id == request.ProviderId, cancellationToken);
|
||||
var rowsUpdated = await context.ShippingProviders
|
||||
.Where(sp => sp.Id == request.ProviderId)
|
||||
.ExecuteUpdateAsync(setters => setters
|
||||
.SetProperty(sp => sp.Name, request.Name)
|
||||
.SetProperty(sp => sp.Price, request.Price)
|
||||
.SetProperty(sp => sp.TrackingUrl, request.TrackingUrl)
|
||||
.SetProperty(sp => sp.Enabled, request.Enabled)
|
||||
.SetProperty(sp => sp.UpdatedAt, DateTime.UtcNow), cancellationToken);
|
||||
|
||||
if (provider is null)
|
||||
return Result.Fail("Shipping provider not found.");
|
||||
|
||||
provider.UpdatedAt = DateTime.UtcNow;
|
||||
provider.Enabled = request.Enabled;
|
||||
provider.Name = request.Name;
|
||||
provider.Price = request.Price;
|
||||
provider.TrackingUrl = request.TrackingUrl;
|
||||
|
||||
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||
return rowsUpdated > 0
|
||||
? Result.Ok()
|
||||
: Result.Fail("Failed to update shipping provider status.");
|
||||
: Result.Fail("Shipping provider not found.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Result.Fail(new Error(ex.Message).CausedBy(ex));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user