fixes and tweaks
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
using Lutra.Domain.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Lutra.Application.Interfaces;
|
||||
|
||||
public interface ILutraDbContext
|
||||
@@ -8,6 +9,8 @@ public interface ILutraDbContext
|
||||
|
||||
DbSet<Beoordeling> Beoordelingen { get; }
|
||||
|
||||
DbSet<VerspakketFoto> VerspakketFotos { get; }
|
||||
|
||||
DbSet<Verspakket> Verspaketten { get; }
|
||||
|
||||
Task<int> SaveChangesAsync(CancellationToken cancellationToken);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Cortex.Mediator" Version="3.1.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.6" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.7" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
namespace Lutra.Application.Models.Supermarkten
|
||||
{
|
||||
public record Supermarkt
|
||||
{
|
||||
public required Guid Id { get; init; }
|
||||
namespace Lutra.Application.Models.Supermarkten;
|
||||
|
||||
public required string Naam { get; init; }
|
||||
}
|
||||
public record Supermarkt
|
||||
{
|
||||
public required Guid Id { get; init; }
|
||||
|
||||
public required string Naam { get; init; }
|
||||
}
|
||||
|
||||
@@ -1,17 +1,12 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
namespace Lutra.Application.Models.Verspakketten;
|
||||
|
||||
namespace Lutra.Application.Models.Verspakketten;
|
||||
|
||||
public class Beoordeling
|
||||
public record Beoordeling
|
||||
{
|
||||
[Range(1, 10)]
|
||||
public required int CijferSmaak { get; init; }
|
||||
|
||||
[Range(1, 10)]
|
||||
public required int CijferBereiden { get; init; }
|
||||
|
||||
public required bool Aanbevolen { get; init; }
|
||||
|
||||
[MaxLength(1024)]
|
||||
public string? Tekst { get; init; }
|
||||
}
|
||||
|
||||
@@ -1,23 +1,24 @@
|
||||
using Lutra.Application.Models.Supermarkten;
|
||||
|
||||
namespace Lutra.Application.Models.Verspakketten
|
||||
namespace Lutra.Application.Models.Verspakketten;
|
||||
|
||||
public record Verspakket
|
||||
{
|
||||
public record Verspakket
|
||||
{
|
||||
public required Guid Id { get; init; }
|
||||
public required Guid Id { get; init; }
|
||||
|
||||
public required string Naam { get; init; }
|
||||
public required string Naam { get; init; }
|
||||
|
||||
public int? PrijsInCenten { get; init; }
|
||||
public int? PrijsInCenten { get; init; }
|
||||
|
||||
public int AantalPersonen { get; init; }
|
||||
public int AantalPersonen { get; init; }
|
||||
|
||||
public double? AverageCijferSmaak { get; init; }
|
||||
|
||||
public double? AverageCijferBereiden { get; init; }
|
||||
|
||||
public Beoordeling[]? Beoordelingen { get; init; }
|
||||
public Beoordeling[]? Beoordelingen { get; init; }
|
||||
|
||||
public Supermarkt? Supermarkt { get; init; }
|
||||
}
|
||||
public VerspakketFotoResponse[]? Fotos { get; init; }
|
||||
|
||||
public Supermarkt? Supermarkt { get; init; }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Lutra.Application.Models.Verspakketten;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a foto to associate with a verspakket.
|
||||
/// </summary>
|
||||
public sealed record VerspakketFoto(
|
||||
/// <summary>Base64-encoded image data.</summary>
|
||||
string Base64Data,
|
||||
bool IsMainImage);
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Lutra.Application.Models.Verspakketten;
|
||||
|
||||
public sealed record VerspakketFotoResponse(
|
||||
Guid Id,
|
||||
/// <summary>Base64-encoded image data.</summary>
|
||||
string Base64Data,
|
||||
bool IsMainImage);
|
||||
@@ -0,0 +1,22 @@
|
||||
using Lutra.Application.Models.Supermarkten;
|
||||
|
||||
namespace Lutra.Application.Models.Verspakketten;
|
||||
|
||||
public record VerspakketSummary
|
||||
{
|
||||
public required Guid Id { get; init; }
|
||||
|
||||
public required string Naam { get; init; }
|
||||
|
||||
public int? PrijsInCenten { get; init; }
|
||||
|
||||
public int AantalPersonen { get; init; }
|
||||
|
||||
public double? AverageCijferSmaak { get; init; }
|
||||
|
||||
public double? AverageCijferBereiden { get; init; }
|
||||
|
||||
public VerspakketFotoResponse? Foto { get; init; }
|
||||
|
||||
public Supermarkt? Supermarkt { get; init; }
|
||||
}
|
||||
@@ -3,29 +3,28 @@ using Lutra.Application.Interfaces;
|
||||
using Lutra.Application.Models.Supermarkten;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Lutra.Application.Supermarkten
|
||||
{
|
||||
public sealed partial class GetSupermarkten
|
||||
{
|
||||
public sealed class Handler(ILutraDbContext context) : IQueryHandler<Query, Response>
|
||||
{
|
||||
public async Task<Response> Handle(Query request, CancellationToken cancellationToken)
|
||||
{
|
||||
var supermarkten = await context.Supermarkten
|
||||
.AsNoTracking()
|
||||
.Where(w => w.DeletedAt == null)
|
||||
.OrderBy(s => s.Naam)
|
||||
.Skip(request.Skip)
|
||||
.Take(request.Take)
|
||||
.Select(s => new Supermarkt
|
||||
{
|
||||
Id = s.Id,
|
||||
Naam = s.Naam
|
||||
})
|
||||
.ToListAsync(cancellationToken);
|
||||
namespace Lutra.Application.Supermarkten;
|
||||
|
||||
return new Response { Supermarkten = supermarkten };
|
||||
}
|
||||
public sealed partial class GetSupermarkten
|
||||
{
|
||||
public sealed class Handler(ILutraDbContext context) : IQueryHandler<Query, Response>
|
||||
{
|
||||
public async Task<Response> Handle(Query request, CancellationToken cancellationToken)
|
||||
{
|
||||
var supermarkten = await context.Supermarkten
|
||||
.AsNoTracking()
|
||||
.Where(w => w.DeletedAt == null)
|
||||
.OrderBy(s => s.Naam)
|
||||
.Skip(request.Skip)
|
||||
.Take(request.Take)
|
||||
.Select(s => new Supermarkt
|
||||
{
|
||||
Id = s.Id,
|
||||
Naam = s.Naam
|
||||
})
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
return new Response { Supermarkten = supermarkten };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
using Cortex.Mediator.Queries;
|
||||
|
||||
namespace Lutra.Application.Supermarkten
|
||||
namespace Lutra.Application.Supermarkten;
|
||||
|
||||
public sealed partial class GetSupermarkten
|
||||
{
|
||||
public sealed partial class GetSupermarkten
|
||||
{
|
||||
public record Query(int Skip, int Take) : IQuery<Response>;
|
||||
}
|
||||
public record Query(int Skip, int Take) : IQuery<Response>;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
using Lutra.Application.Models.Supermarkten;
|
||||
|
||||
namespace Lutra.Application.Supermarkten
|
||||
namespace Lutra.Application.Supermarkten;
|
||||
|
||||
public sealed partial class GetSupermarkten
|
||||
{
|
||||
public sealed partial class GetSupermarkten
|
||||
public sealed record Response
|
||||
{
|
||||
public sealed class Response
|
||||
{
|
||||
public required IEnumerable<Supermarkt> Supermarkten { get; set; }
|
||||
}
|
||||
public required IEnumerable<Supermarkt> Supermarkten { get; init; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
namespace Lutra.Application.Supermarkten
|
||||
{
|
||||
public sealed partial class GetSupermarkten { }
|
||||
}
|
||||
namespace Lutra.Application.Supermarkten;
|
||||
|
||||
public sealed partial class GetSupermarkten { }
|
||||
|
||||
@@ -2,8 +2,8 @@ namespace Lutra.Application.Verspakketten;
|
||||
|
||||
public sealed partial class AddBeoordeling
|
||||
{
|
||||
public sealed class Response
|
||||
public sealed record Response
|
||||
{
|
||||
public required Guid Id { get; set; }
|
||||
public required Guid Id { get; init; }
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
using Cortex.Mediator.Commands;
|
||||
using Lutra.Application.Models.Verspakketten;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Lutra.Application.Verspakketten;
|
||||
|
||||
@@ -9,7 +8,8 @@ public sealed partial class CreateVerspakket
|
||||
public sealed record Command(
|
||||
string Naam,
|
||||
int? PrijsInCenten,
|
||||
[Range(1, 10)] int AantalPersonen,
|
||||
int AantalPersonen,
|
||||
Guid SupermarktId,
|
||||
Beoordeling? Beoordeling) : ICommand<Response>;
|
||||
Beoordeling? Beoordeling,
|
||||
IReadOnlyList<VerspakketFoto>? Fotos = null) : ICommand<Response>;
|
||||
}
|
||||
|
||||
@@ -47,6 +47,22 @@ public sealed partial class CreateVerspakket
|
||||
});
|
||||
}
|
||||
|
||||
if (request.Fotos is { Count: > 0 })
|
||||
{
|
||||
foreach (var foto in request.Fotos)
|
||||
{
|
||||
verspakket.AddFoto(new Domain.Entities.VerspakketFoto
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Data = Convert.FromBase64String(foto.Base64Data),
|
||||
IsMainImage = foto.IsMainImage,
|
||||
VerspakketId = verspakket.Id,
|
||||
CreatedAt = now,
|
||||
ModifiedAt = now
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
await context.Verspaketten.AddAsync(verspakket, cancellationToken);
|
||||
await context.SaveChangesAsync(cancellationToken);
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ namespace Lutra.Application.Verspakketten;
|
||||
|
||||
public sealed partial class CreateVerspakket
|
||||
{
|
||||
public sealed class Response
|
||||
public sealed record Response
|
||||
{
|
||||
public required Guid Id { get; set; }
|
||||
public required Guid Id { get; init; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,44 +4,49 @@ using Lutra.Application.Models.Supermarkten;
|
||||
using Lutra.Application.Models.Verspakketten;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Lutra.Application.Verspakketten
|
||||
{
|
||||
namespace Lutra.Application.Verspakketten;
|
||||
|
||||
public sealed partial class GetVerspakket
|
||||
{
|
||||
public sealed class Handler(ILutraDbContext context) : IQueryHandler<Query, Response?>
|
||||
{
|
||||
public async Task<Response?> Handle(Query request, CancellationToken cancellationToken)
|
||||
{
|
||||
var verspakket = await context.Verspaketten
|
||||
.AsNoTracking()
|
||||
.Where(v => v.Id == request.Id)
|
||||
.Select(v => new Verspakket
|
||||
{
|
||||
Id = v.Id,
|
||||
Naam = v.Naam,
|
||||
PrijsInCenten = v.PrijsInCenten,
|
||||
AantalPersonen = v.AantalPersonen,
|
||||
AverageCijferSmaak = v.Beoordelingen.Any() ? v.Beoordelingen.Average(b => (double)b.CijferSmaak) : null,
|
||||
AverageCijferBereiden = v.Beoordelingen.Any() ? v.Beoordelingen.Average(b => (double)b.CijferBereiden) : null,
|
||||
Beoordelingen = v.Beoordelingen
|
||||
.Select(b => new Beoordeling
|
||||
{
|
||||
CijferSmaak = b.CijferSmaak,
|
||||
CijferBereiden = b.CijferBereiden,
|
||||
Aanbevolen = b.Aanbevolen,
|
||||
Tekst = b.Tekst
|
||||
})
|
||||
.ToArray(),
|
||||
Supermarkt = new Supermarkt
|
||||
{
|
||||
Id = v.Supermarkt.Id,
|
||||
Naam = v.Supermarkt.Naam
|
||||
}
|
||||
})
|
||||
.SingleOrDefaultAsync(cancellationToken);
|
||||
var verspakket = await context.Verspaketten
|
||||
.AsNoTracking()
|
||||
.Where(v => v.Id == request.Id)
|
||||
.Select(v => new Verspakket
|
||||
{
|
||||
Id = v.Id,
|
||||
Naam = v.Naam,
|
||||
PrijsInCenten = v.PrijsInCenten,
|
||||
AantalPersonen = v.AantalPersonen,
|
||||
AverageCijferSmaak = v.Beoordelingen.Any() ? v.Beoordelingen.Average(b => (double)b.CijferSmaak) : null,
|
||||
AverageCijferBereiden = v.Beoordelingen.Any() ? v.Beoordelingen.Average(b => (double)b.CijferBereiden) : null,
|
||||
Beoordelingen = v.Beoordelingen
|
||||
.Select(b => new Beoordeling
|
||||
{
|
||||
CijferSmaak = b.CijferSmaak,
|
||||
CijferBereiden = b.CijferBereiden,
|
||||
Aanbevolen = b.Aanbevolen,
|
||||
Tekst = b.Tekst
|
||||
})
|
||||
.ToArray(),
|
||||
Supermarkt = new Supermarkt
|
||||
{
|
||||
Id = v.Supermarkt.Id,
|
||||
Naam = v.Supermarkt.Naam
|
||||
},
|
||||
Fotos = v.Fotos
|
||||
.Select(f => new VerspakketFotoResponse(
|
||||
f.Id,
|
||||
Convert.ToBase64String(f.Data),
|
||||
f.IsMainImage))
|
||||
.ToArray()
|
||||
})
|
||||
.SingleOrDefaultAsync(cancellationToken);
|
||||
|
||||
return verspakket is null ? null : new Response { Verspakket = verspakket };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return verspakket is null ? null : new Response { Verspakket = verspakket };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
using Cortex.Mediator.Queries;
|
||||
|
||||
namespace Lutra.Application.Verspakketten
|
||||
namespace Lutra.Application.Verspakketten;
|
||||
|
||||
public sealed partial class GetVerspakket
|
||||
{
|
||||
public sealed partial class GetVerspakket
|
||||
{
|
||||
public record Query(Guid Id) : IQuery<Response?>;
|
||||
}
|
||||
public record Query(Guid Id) : IQuery<Response?>;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
using Lutra.Application.Models.Verspakketten;
|
||||
|
||||
namespace Lutra.Application.Verspakketten
|
||||
namespace Lutra.Application.Verspakketten;
|
||||
|
||||
public sealed partial class GetVerspakket
|
||||
{
|
||||
public sealed partial class GetVerspakket
|
||||
public sealed record Response
|
||||
{
|
||||
public sealed class Response
|
||||
{
|
||||
public required Verspakket Verspakket { get; set; }
|
||||
}
|
||||
public required Verspakket Verspakket { get; init; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
namespace Lutra.Application.Verspakketten
|
||||
{
|
||||
public sealed partial class GetVerspakket { }
|
||||
}
|
||||
namespace Lutra.Application.Verspakketten;
|
||||
|
||||
public sealed partial class GetVerspakket { }
|
||||
|
||||
@@ -4,69 +4,66 @@ using Lutra.Application.Models.Supermarkten;
|
||||
using Lutra.Application.Models.Verspakketten;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Lutra.Application.Verspakketten
|
||||
namespace Lutra.Application.Verspakketten;
|
||||
|
||||
public sealed partial class GetVerspakketten
|
||||
{
|
||||
public sealed partial class GetVerspakketten
|
||||
public sealed class Handler(ILutraDbContext context) : IQueryHandler<Query, Response>
|
||||
{
|
||||
public sealed class Handler(ILutraDbContext context) : IQueryHandler<Query, Response>
|
||||
public async Task<Response> Handle(Query request, CancellationToken cancellationToken)
|
||||
{
|
||||
public async Task<Response> Handle(Query request, CancellationToken cancellationToken)
|
||||
var query = context.Verspaketten
|
||||
.Where(w => w.DeletedAt == null)
|
||||
.AsNoTracking();
|
||||
|
||||
// Apply sort before pagination so the database handles ordering efficiently.
|
||||
IOrderedQueryable<Domain.Entities.Verspakket> sorted = request.SortField switch
|
||||
{
|
||||
var query = context.Verspaketten
|
||||
.Where(w => w.DeletedAt == null)
|
||||
.AsNoTracking();
|
||||
VerspakketSortField.AverageCijferSmaak =>
|
||||
request.SortDirection == SortDirection.Ascending
|
||||
? query.OrderBy(v => v.Beoordelingen.Average(b => (double)b.CijferSmaak))
|
||||
: query.OrderByDescending(v => v.Beoordelingen.Average(b => (double)b.CijferSmaak)),
|
||||
VerspakketSortField.AverageCijferBereiden =>
|
||||
request.SortDirection == SortDirection.Ascending
|
||||
? query.OrderBy(v => v.Beoordelingen.Average(b => (double)b.CijferBereiden))
|
||||
: query.OrderByDescending(v => v.Beoordelingen.Average(b => (double)b.CijferBereiden)),
|
||||
VerspakketSortField.PrijsInCenten =>
|
||||
request.SortDirection == SortDirection.Ascending
|
||||
? query.OrderBy(v => v.PrijsInCenten)
|
||||
: query.OrderByDescending(v => v.PrijsInCenten),
|
||||
VerspakketSortField.Naam or _ =>
|
||||
request.SortDirection == SortDirection.Ascending
|
||||
? query.OrderBy(v => v.Naam)
|
||||
: query.OrderByDescending(v => v.Naam),
|
||||
};
|
||||
|
||||
// Apply sort before pagination so the database handles ordering efficiently.
|
||||
IOrderedQueryable<Domain.Entities.Verspakket> sorted = request.SortField switch
|
||||
var verspakketten = await sorted
|
||||
.Skip(request.Skip)
|
||||
.Take(request.Take)
|
||||
.Select(v => new VerspakketSummary
|
||||
{
|
||||
VerspakketSortField.AverageCijferSmaak =>
|
||||
request.SortDirection == SortDirection.Ascending
|
||||
? query.OrderBy(v => v.Beoordelingen.Average(b => (double)b.CijferSmaak))
|
||||
: query.OrderByDescending(v => v.Beoordelingen.Average(b => (double)b.CijferSmaak)),
|
||||
VerspakketSortField.AverageCijferBereiden =>
|
||||
request.SortDirection == SortDirection.Ascending
|
||||
? query.OrderBy(v => v.Beoordelingen.Average(b => (double)b.CijferBereiden))
|
||||
: query.OrderByDescending(v => v.Beoordelingen.Average(b => (double)b.CijferBereiden)),
|
||||
VerspakketSortField.PrijsInCenten =>
|
||||
request.SortDirection == SortDirection.Ascending
|
||||
? query.OrderBy(v => v.PrijsInCenten)
|
||||
: query.OrderByDescending(v => v.PrijsInCenten),
|
||||
VerspakketSortField.Naam or _ =>
|
||||
request.SortDirection == SortDirection.Ascending
|
||||
? query.OrderBy(v => v.Naam)
|
||||
: query.OrderByDescending(v => v.Naam),
|
||||
};
|
||||
|
||||
var verspakketten = await sorted
|
||||
.Skip(request.Skip)
|
||||
.Take(request.Take)
|
||||
.Select(v => new Verspakket
|
||||
Id = v.Id,
|
||||
Naam = v.Naam,
|
||||
PrijsInCenten = v.PrijsInCenten,
|
||||
AantalPersonen = v.AantalPersonen,
|
||||
AverageCijferSmaak = v.Beoordelingen.Any() ? v.Beoordelingen.Average(b => (double)b.CijferSmaak) : null,
|
||||
AverageCijferBereiden = v.Beoordelingen.Any() ? v.Beoordelingen.Average(b => (double)b.CijferBereiden) : null,
|
||||
Supermarkt = new Supermarkt
|
||||
{
|
||||
Id = v.Id,
|
||||
Naam = v.Naam,
|
||||
PrijsInCenten = v.PrijsInCenten,
|
||||
AantalPersonen = v.AantalPersonen,
|
||||
AverageCijferSmaak = v.Beoordelingen.Any() ? v.Beoordelingen.Average(b => (double)b.CijferSmaak) : null,
|
||||
AverageCijferBereiden = v.Beoordelingen.Any() ? v.Beoordelingen.Average(b => (double)b.CijferBereiden) : null,
|
||||
Beoordelingen = v.Beoordelingen
|
||||
.Select(b => new Beoordeling
|
||||
{
|
||||
CijferSmaak = b.CijferSmaak,
|
||||
CijferBereiden = b.CijferBereiden,
|
||||
Aanbevolen = b.Aanbevolen,
|
||||
Tekst = b.Tekst
|
||||
})
|
||||
.ToArray(),
|
||||
Supermarkt = new Supermarkt
|
||||
{
|
||||
Id = v.Supermarkt.Id,
|
||||
Naam = v.Supermarkt.Naam
|
||||
}
|
||||
})
|
||||
.ToListAsync(cancellationToken);
|
||||
Id = v.Supermarkt.Id,
|
||||
Naam = v.Supermarkt.Naam
|
||||
},
|
||||
Foto = v.Fotos
|
||||
.Where(f => f.IsMainImage)
|
||||
.Select(f => new VerspakketFotoResponse(
|
||||
f.Id,
|
||||
Convert.ToBase64String(f.Data),
|
||||
f.IsMainImage))
|
||||
.SingleOrDefault()
|
||||
})
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
return new Response { Verspakketten = verspakketten };
|
||||
}
|
||||
return new Response { Verspakketten = verspakketten };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
using Cortex.Mediator.Queries;
|
||||
|
||||
namespace Lutra.Application.Verspakketten
|
||||
namespace Lutra.Application.Verspakketten;
|
||||
|
||||
public sealed partial class GetVerspakketten
|
||||
{
|
||||
public sealed partial class GetVerspakketten
|
||||
{
|
||||
public record Query(
|
||||
int Skip,
|
||||
int Take,
|
||||
VerspakketSortField SortField = VerspakketSortField.Naam,
|
||||
SortDirection SortDirection = SortDirection.Ascending) : IQuery<Response>;
|
||||
}
|
||||
public record Query(
|
||||
int Skip,
|
||||
int Take,
|
||||
VerspakketSortField SortField = VerspakketSortField.Naam,
|
||||
SortDirection SortDirection = SortDirection.Ascending) : IQuery<Response>;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
using Lutra.Application.Models.Verspakketten;
|
||||
|
||||
namespace Lutra.Application.Verspakketten
|
||||
namespace Lutra.Application.Verspakketten;
|
||||
|
||||
public sealed partial class GetVerspakketten
|
||||
{
|
||||
public sealed partial class GetVerspakketten
|
||||
public sealed record Response
|
||||
{
|
||||
public sealed class Response
|
||||
{
|
||||
public required IEnumerable<Verspakket> Verspakketten { get; set; }
|
||||
}
|
||||
public required IEnumerable<VerspakketSummary> Verspakketten { get; init; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
namespace Lutra.Application.Verspakketten
|
||||
{
|
||||
public sealed partial class GetVerspakketten { }
|
||||
}
|
||||
namespace Lutra.Application.Verspakketten;
|
||||
|
||||
public sealed partial class GetVerspakketten { }
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Cortex.Mediator.Commands;
|
||||
using Lutra.Application.Models.Verspakketten;
|
||||
|
||||
namespace Lutra.Application.Verspakketten;
|
||||
|
||||
@@ -7,5 +8,11 @@ public sealed partial class UpdateVerspakket
|
||||
/// <summary>
|
||||
/// Updates an existing verspakket.
|
||||
/// </summary>
|
||||
public sealed record Command(Guid Id, string Naam, int PrijsInCenten, int AantalPersonen, Guid SupermarktId) : ICommand<Response>;
|
||||
public sealed record Command(
|
||||
Guid Id,
|
||||
string Naam,
|
||||
int PrijsInCenten,
|
||||
int AantalPersonen,
|
||||
Guid SupermarktId,
|
||||
IReadOnlyList<VerspakketFoto>? Fotos = null) : ICommand<Response>;
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ public sealed partial class UpdateVerspakket
|
||||
throw new ArgumentException("AantalPersonen moet tussen 1 en 10 liggen.", nameof(request.AantalPersonen));
|
||||
|
||||
var verspakket = await context.Verspaketten
|
||||
.Include(v => v.Fotos)
|
||||
.FirstOrDefaultAsync(v => v.Id == request.Id && v.DeletedAt == null, cancellationToken);
|
||||
|
||||
if (verspakket is null)
|
||||
@@ -54,6 +55,32 @@ public sealed partial class UpdateVerspakket
|
||||
verspakket.SupermarktId = request.SupermarktId;
|
||||
verspakket.ModifiedAt = DateTime.UtcNow;
|
||||
|
||||
if (request.Fotos is not null)
|
||||
{
|
||||
// Replace all existing fotos
|
||||
foreach (var existing in verspakket.Fotos.ToList())
|
||||
verspakket.RemoveFoto(existing.Id);
|
||||
|
||||
context.VerspakketFotos.RemoveRange(
|
||||
await context.VerspakketFotos
|
||||
.Where(f => f.VerspakketId == request.Id)
|
||||
.ToListAsync(cancellationToken));
|
||||
|
||||
var now = DateTime.UtcNow;
|
||||
foreach (var foto in request.Fotos)
|
||||
{
|
||||
verspakket.AddFoto(new Domain.Entities.VerspakketFoto
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Data = Convert.FromBase64String(foto.Base64Data),
|
||||
IsMainImage = foto.IsMainImage,
|
||||
VerspakketId = verspakket.Id,
|
||||
CreatedAt = now,
|
||||
ModifiedAt = now
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
await context.SaveChangesAsync(cancellationToken);
|
||||
|
||||
return new Response();
|
||||
|
||||
Reference in New Issue
Block a user