using Meezi.API.Models.Taxes; using Meezi.Core.Entities; using Meezi.Infrastructure.Data; using Microsoft.EntityFrameworkCore; namespace Meezi.API.Services; public interface ITaxService { Task> GetAllAsync(string cafeId, CancellationToken cancellationToken = default); Task CreateAsync(string cafeId, CreateTaxRequest request, CancellationToken cancellationToken = default); Task UpdateAsync(string cafeId, string id, UpdateTaxRequest request, CancellationToken cancellationToken = default); Task DeleteAsync(string cafeId, string id, CancellationToken cancellationToken = default); } public class TaxService : ITaxService { private readonly AppDbContext _db; public TaxService(AppDbContext db) => _db = db; public async Task> GetAllAsync(string cafeId, CancellationToken cancellationToken = default) { return await _db.Taxes .Where(t => t.CafeId == cafeId) .OrderBy(t => t.Name) .Select(t => ToDto(t)) .ToListAsync(cancellationToken); } public async Task CreateAsync(string cafeId, CreateTaxRequest request, CancellationToken cancellationToken = default) { if (request.IsDefault) { var existing = await _db.Taxes.Where(t => t.CafeId == cafeId && t.IsDefault).ToListAsync(cancellationToken); foreach (var t in existing) t.IsDefault = false; } var entity = new Tax { CafeId = cafeId, Name = request.Name, Rate = request.Rate, IsDefault = request.IsDefault, IsRequired = request.IsRequired, IsCompound = request.IsCompound }; _db.Taxes.Add(entity); await _db.SaveChangesAsync(cancellationToken); return ToDto(entity); } public async Task UpdateAsync( string cafeId, string id, UpdateTaxRequest request, CancellationToken cancellationToken = default) { var entity = await _db.Taxes.FirstOrDefaultAsync(t => t.Id == id && t.CafeId == cafeId, cancellationToken); if (entity is null) return null; if (request.Name is not null) entity.Name = request.Name; if (request.Rate.HasValue) entity.Rate = request.Rate.Value; if (request.IsDefault == true) { var others = await _db.Taxes.Where(t => t.CafeId == cafeId && t.Id != id).ToListAsync(cancellationToken); foreach (var t in others) t.IsDefault = false; entity.IsDefault = true; } else if (request.IsDefault.HasValue) entity.IsDefault = request.IsDefault.Value; if (request.IsRequired.HasValue) entity.IsRequired = request.IsRequired.Value; if (request.IsCompound.HasValue) entity.IsCompound = request.IsCompound.Value; await _db.SaveChangesAsync(cancellationToken); return ToDto(entity); } public async Task DeleteAsync(string cafeId, string id, CancellationToken cancellationToken = default) { var entity = await _db.Taxes.FirstOrDefaultAsync(t => t.Id == id && t.CafeId == cafeId, cancellationToken); if (entity is null) return false; var wasDefault = entity.IsDefault; entity.DeletedAt = DateTime.UtcNow; entity.IsDefault = false; var categories = await _db.MenuCategories .Where(c => c.CafeId == cafeId && c.TaxId == id) .ToListAsync(cancellationToken); Tax? replacementDefault = null; if (wasDefault) { replacementDefault = await _db.Taxes .Where(t => t.CafeId == cafeId && t.Id != id) .OrderBy(t => t.Name) .FirstOrDefaultAsync(cancellationToken); if (replacementDefault is not null) replacementDefault.IsDefault = true; } foreach (var category in categories) category.TaxId = replacementDefault?.Id; await _db.SaveChangesAsync(cancellationToken); return true; } private static TaxDto ToDto(Tax t) => new(t.Id, t.Name, t.Rate, t.IsDefault, t.IsRequired, t.IsCompound); }