using AutoMapper; using PowderCoating.Application.DTOs.Catalog; using PowderCoating.Core.Entities; using System.Collections.Generic; using System.Linq; namespace PowderCoating.Application.Mappings { /// /// AutoMapper profile for product catalog entities. /// public class CatalogProfile : Profile { public CatalogProfile() { // ==================== Category Mappings ==================== // Category -> CategoryDto CreateMap() .ForMember(dest => dest.ParentCategoryName, opt => opt.MapFrom(src => src.ParentCategory != null ? src.ParentCategory.Name : null)) .ForMember(dest => dest.ItemCount, opt => opt.MapFrom(src => src.Items.Count(i => !i.IsDeleted))) .ForMember(dest => dest.SubCategoryCount, opt => opt.MapFrom(src => src.SubCategories.Count(c => !c.IsDeleted))); // CreateCategoryDto -> CatalogCategory CreateMap() .ForMember(dest => dest.Id, opt => opt.Ignore()) .ForMember(dest => dest.CompanyId, opt => opt.Ignore()) .ForMember(dest => dest.CreatedAt, opt => opt.Ignore()) .ForMember(dest => dest.UpdatedAt, opt => opt.Ignore()) .ForMember(dest => dest.CreatedBy, opt => opt.Ignore()) .ForMember(dest => dest.UpdatedBy, opt => opt.Ignore()) .ForMember(dest => dest.IsDeleted, opt => opt.Ignore()) .ForMember(dest => dest.ParentCategory, opt => opt.Ignore()) .ForMember(dest => dest.SubCategories, opt => opt.Ignore()) .ForMember(dest => dest.Items, opt => opt.Ignore()); // CatalogCategory -> UpdateCategoryDto (reverse mapping for Edit GET) CreateMap(); // UpdateCategoryDto -> CatalogCategory CreateMap() .ForMember(dest => dest.CompanyId, opt => opt.Ignore()) .ForMember(dest => dest.CreatedAt, opt => opt.Ignore()) .ForMember(dest => dest.UpdatedAt, opt => opt.Ignore()) .ForMember(dest => dest.CreatedBy, opt => opt.Ignore()) .ForMember(dest => dest.UpdatedBy, opt => opt.Ignore()) .ForMember(dest => dest.IsDeleted, opt => opt.Ignore()) .ForMember(dest => dest.ParentCategory, opt => opt.Ignore()) .ForMember(dest => dest.SubCategories, opt => opt.Ignore()) .ForMember(dest => dest.Items, opt => opt.Ignore()); // CatalogCategory -> CategoryTreeDto (recursive) CreateMap() .ForMember(dest => dest.ItemCount, opt => opt.MapFrom(src => src.Items.Count(i => !i.IsDeleted))) .ForMember(dest => dest.HasItems, opt => opt.MapFrom(src => src.Items.Any(i => !i.IsDeleted))) .ForMember(dest => dest.Children, opt => opt.MapFrom(src => src.SubCategories.Where(c => !c.IsDeleted).OrderBy(c => c.DisplayOrder))); // ==================== Item Mappings ==================== // CatalogItem -> CatalogItemDto CreateMap() .ForMember(dest => dest.CategoryName, opt => opt.MapFrom(src => src.Category.Name)) .ForMember(dest => dest.FullCategoryPath, opt => opt.MapFrom(src => GetCategoryPath(src.Category))) .ForMember(dest => dest.RevenueAccountName, opt => opt.MapFrom(src => src.RevenueAccount != null ? $"{src.RevenueAccount.AccountNumber} – {src.RevenueAccount.Name}" : null)) .ForMember(dest => dest.CogsAccountName, opt => opt.MapFrom(src => src.CogsAccount != null ? $"{src.CogsAccount.AccountNumber} – {src.CogsAccount.Name}" : null)); // CatalogItem -> CatalogItemListDto CreateMap() .ForMember(dest => dest.CategoryName, opt => opt.MapFrom(src => src.Category.Name)); // CreateCatalogItemDto -> CatalogItem CreateMap() .ForMember(dest => dest.Id, opt => opt.Ignore()) .ForMember(dest => dest.CompanyId, opt => opt.Ignore()) .ForMember(dest => dest.CreatedAt, opt => opt.Ignore()) .ForMember(dest => dest.UpdatedAt, opt => opt.Ignore()) .ForMember(dest => dest.CreatedBy, opt => opt.Ignore()) .ForMember(dest => dest.UpdatedBy, opt => opt.Ignore()) .ForMember(dest => dest.IsDeleted, opt => opt.Ignore()) .ForMember(dest => dest.Category, opt => opt.Ignore()) .ForMember(dest => dest.RevenueAccount, opt => opt.Ignore()) .ForMember(dest => dest.CogsAccount, opt => opt.Ignore()) // Image paths are set by CatalogImageService after the entity is saved, not from the DTO. .ForMember(dest => dest.ImagePath, opt => opt.Ignore()) .ForMember(dest => dest.ThumbnailPath, opt => opt.Ignore()); // UpdateCatalogItemDto -> CatalogItem CreateMap() .ForMember(dest => dest.CompanyId, opt => opt.Ignore()) .ForMember(dest => dest.CreatedAt, opt => opt.Ignore()) .ForMember(dest => dest.UpdatedAt, opt => opt.Ignore()) .ForMember(dest => dest.CreatedBy, opt => opt.Ignore()) .ForMember(dest => dest.UpdatedBy, opt => opt.Ignore()) .ForMember(dest => dest.IsDeleted, opt => opt.Ignore()) .ForMember(dest => dest.Category, opt => opt.Ignore()) .ForMember(dest => dest.RevenueAccount, opt => opt.Ignore()) .ForMember(dest => dest.CogsAccount, opt => opt.Ignore()) .ForMember(dest => dest.ImagePath, opt => opt.Ignore()) .ForMember(dest => dest.ThumbnailPath, opt => opt.Ignore()); // CatalogItem -> UpdateCatalogItemDto (reverse mapping for Edit) CreateMap(); } /// /// Builds the full category path by walking up the hierarchy. /// Example: "Wheels > 18 inch" /// private string GetCategoryPath(CatalogCategory category) { var path = new List(); var current = category; // Walk up the hierarchy while (current != null) { path.Insert(0, current.Name); current = current.ParentCategory; } return string.Join(" > ", path); } } }