using System; using System.Linq; using AutoMapper; using Kavita.Models.DTOs; using Kavita.Models.Entities; using Kavita.Models.Entities.Enums; namespace Kavita.Models.AutoMapper; /// /// Maps Chapter entities to ChapterDto with user progress attached at the DB level via JOIN. /// public class AutoMapperChapterProfile : Profile { public AutoMapperChapterProfile() { int userId = 0; // Placeholder will be replaced at runtime CreateMap() .MapChapterBase(userId); CreateMap() .MapChapterBase(userId) .ForMember(dest => dest.SeriesId, opt => opt.MapFrom(src => src.Volume.SeriesId)) .ForMember(dest => dest.VolumeTitle, opt => opt.MapFrom(src => src.Volume.Name)) .ForMember(dest => dest.LibraryId, opt => opt.MapFrom(src => src.Volume.Series.LibraryId)) .ForMember(dest => dest.LibraryType, opt => opt.MapFrom(src => src.Volume.Series.Library.Type)); } } internal static class AutoMapperChapterProfileBaseExtensions { public static IMappingExpression MapChapterBase(this IMappingExpression mapping, int userId) where TDest: ChapterDto { return mapping .ForMember(dest => dest.PagesRead, opt => opt.MapFrom(src => src.UserProgress .Where(p => p.AppUserId == userId) .Select(p => (int?)p.PagesRead) .FirstOrDefault() ?? 0)) .ForMember(dest => dest.LastReadingProgressUtc, opt => opt.MapFrom(src => src.UserProgress .Where(p => p.AppUserId == userId) .Select(p => (DateTime?)p.LastModifiedUtc) .FirstOrDefault() ?? DateTime.MinValue)) .ForMember(dest => dest.LastReadingProgress, opt => opt.MapFrom(src => src.UserProgress .Where(p => p.AppUserId == userId) .Select(p => (DateTime?)p.LastModified) .FirstOrDefault() ?? DateTime.MinValue)) .ForMember(dest => dest.TotalReads, opt => opt.MapFrom(src => src.UserProgress .Where(p => p.AppUserId == userId) .Select(p => (int?)p.TotalReads) .FirstOrDefault() ?? 0)) // People mappings by role .ForMember(dest => dest.Writers, opt => opt.MapFrom(src => src.People .Where(cp => cp.Role == PersonRole.Writer) .Select(cp => cp.Person) .OrderBy(p => p.NormalizedName))) .ForMember(dest => dest.CoverArtists, opt => opt.MapFrom(src => src.People .Where(cp => cp.Role == PersonRole.CoverArtist) .Select(cp => cp.Person) .OrderBy(p => p.NormalizedName))) .ForMember(dest => dest.Publishers, opt => opt.MapFrom(src => src.People .Where(cp => cp.Role == PersonRole.Publisher) .Select(cp => cp.Person) .OrderBy(p => p.NormalizedName))) .ForMember(dest => dest.Characters, opt => opt.MapFrom(src => src.People .Where(cp => cp.Role == PersonRole.Character) .Select(cp => cp.Person) .OrderBy(p => p.NormalizedName))) .ForMember(dest => dest.Pencillers, opt => opt.MapFrom(src => src.People .Where(cp => cp.Role == PersonRole.Penciller) .Select(cp => cp.Person) .OrderBy(p => p.NormalizedName))) .ForMember(dest => dest.Inkers, opt => opt.MapFrom(src => src.People .Where(cp => cp.Role == PersonRole.Inker) .Select(cp => cp.Person) .OrderBy(p => p.NormalizedName))) .ForMember(dest => dest.Imprints, opt => opt.MapFrom(src => src.People .Where(cp => cp.Role == PersonRole.Imprint) .Select(cp => cp.Person) .OrderBy(p => p.NormalizedName))) .ForMember(dest => dest.Colorists, opt => opt.MapFrom(src => src.People .Where(cp => cp.Role == PersonRole.Colorist) .Select(cp => cp.Person) .OrderBy(p => p.NormalizedName))) .ForMember(dest => dest.Letterers, opt => opt.MapFrom(src => src.People .Where(cp => cp.Role == PersonRole.Letterer) .Select(cp => cp.Person) .OrderBy(p => p.NormalizedName))) .ForMember(dest => dest.Editors, opt => opt.MapFrom(src => src.People .Where(cp => cp.Role == PersonRole.Editor) .Select(cp => cp.Person) .OrderBy(p => p.NormalizedName))) .ForMember(dest => dest.Translators, opt => opt.MapFrom(src => src.People .Where(cp => cp.Role == PersonRole.Translator) .Select(cp => cp.Person) .OrderBy(p => p.NormalizedName))) .ForMember(dest => dest.Teams, opt => opt.MapFrom(src => src.People .Where(cp => cp.Role == PersonRole.Team) .Select(cp => cp.Person) .OrderBy(p => p.NormalizedName))) .ForMember(dest => dest.Locations, opt => opt.MapFrom(src => src.People .Where(cp => cp.Role == PersonRole.Location) .Select(cp => cp.Person) .OrderBy(p => p.NormalizedName))); } }