|
- using CartWise.Application.Interfaces;
- using CartWise.Application.Results;
- using CartWise.Domain.Entities;
- using CartWise.Domain.Enums;
- using Microsoft.EntityFrameworkCore;
-
- namespace CartWise.Application.Services;
-
- public class ShoppingListService : IShoppingListService
- {
- private readonly IApplicationDbContext _db;
- private readonly TimeProvider _timeProvider;
-
- public ShoppingListService(IApplicationDbContext db, TimeProvider timeProvider)
- {
- _db = db;
- _timeProvider = timeProvider;
- }
-
- public async Task<ShoppingList?> GetActiveListAsync(Guid householdId, CancellationToken cancellationToken = default)
- {
- return await _db.ShoppingLists
- .Include(l => l.Items)
- .AsNoTracking()
- .Where(l => l.HouseholdId == householdId && l.Status == ShoppingListStatus.Active)
- .FirstOrDefaultAsync(cancellationToken);
- }
-
- public async Task<Result<ShoppingList>> CreateListAsync(Guid householdId, string name, string createdByUserId, CancellationToken cancellationToken = default)
- {
- var hasActiveList = await _db.ShoppingLists
- .AsNoTracking()
- .AnyAsync(l => l.HouseholdId == householdId && l.Status == ShoppingListStatus.Active, cancellationToken);
-
- if (hasActiveList)
- {
- return Result<ShoppingList>.Failure("This household already has an active shopping list.");
- }
-
- ShoppingList list;
- try
- {
- list = new ShoppingList(householdId, name, createdByUserId, _timeProvider.GetUtcNow().UtcDateTime);
- }
- catch (ArgumentException ex)
- {
- return Result<ShoppingList>.Failure(ex.Message);
- }
-
- _db.ShoppingLists.Add(list);
- await _db.SaveChangesAsync(cancellationToken);
-
- return Result<ShoppingList>.Success(list);
- }
-
- public async Task<Result<ShoppingListItem>> AddItemAsync(
- Guid shoppingListId,
- string displayName,
- decimal? quantity,
- string? unit,
- string addedByUserId,
- CancellationToken cancellationToken = default)
- {
- var list = await _db.ShoppingLists
- .Include(l => l.Items)
- .FirstOrDefaultAsync(l => l.ShoppingListId == shoppingListId, cancellationToken);
-
- if (list is null)
- {
- return Result<ShoppingListItem>.Failure("Shopping list not found.");
- }
-
- ShoppingListItem item;
- try
- {
- item = list.AddItem(displayName, quantity, unit, addedByUserId, _timeProvider.GetUtcNow().UtcDateTime);
- }
- catch (Exception ex) when (ex is ArgumentException or InvalidOperationException)
- {
- return Result<ShoppingListItem>.Failure(ex.Message);
- }
-
- // EF Core can't reliably infer Added state for a new child discovered only via a mutated
- // navigation collection on an already-tracked parent, since ShoppingListItemId is a
- // client-generated Guid rather than a store-generated key. Mark it explicitly.
- _db.ShoppingListItems.Add(item);
- await _db.SaveChangesAsync(cancellationToken);
-
- return Result<ShoppingListItem>.Success(item);
- }
- }
|