using System; using System.Collections.Generic; using System.IO; using System.Linq; using AutoMapper; using ClosedXML.Excel; using CsvHelper; using CsvHelper.Configuration; using CsvHelper.Excel; using Heroic.AutoMapper; using InventoryTraker.Web.Models; namespace InventoryTraker.Web.Utilities { public class MovementReportWriter { public class MovementReportExportItem : IMapFrom, IHaveCustomMappings { public string Name { get; set; } public string UnitsPerCaseContainerType { get; set; } public string BeginningQuantity { get; set; } public string AddedQuantity { get; set; } public string TotalAvailableQuantity { get; set; } public string DistributedQuantity { get; set; } public string AdjustmentQuantity { get; set; } public string EndingQuantity { get; set; } public void CreateMappings(IMapperConfiguration configuration) { Func formatCases = (cases, unitsPerCase) => $"{cases * unitsPerCase} ({cases} cs)"; Func hideEmptyCases = (cases, unitsPerCase) => cases > 0 ? formatCases(cases, unitsPerCase) : ""; Func negative = (cases, unitsPerCase) => cases > 0 ? "- " + hideEmptyCases(cases, unitsPerCase) : ""; configuration.CreateMap() .ForMember(d => d.Name, opt => opt.MapFrom(i => i.InventoryType.Name)) .ForMember(d => d.UnitsPerCaseContainerType, opt => opt.MapFrom(i => i.InventoryType.UnitsPerCaseContainerType)) .ForMember(d => d.BeginningQuantity, opt => opt.MapFrom(i => formatCases(i.BeginningQuantity, i.InventoryType.UnitsPerCase))) .ForMember(d => d.AddedQuantity, opt => opt.MapFrom(i => hideEmptyCases(i.AddedQuantity, i.InventoryType.UnitsPerCase))) .ForMember(d => d.TotalAvailableQuantity, opt => opt.MapFrom(i => hideEmptyCases(i.TotalAvailableQuantity, i.InventoryType.UnitsPerCase))) .ForMember(d => d.AdjustmentQuantity, opt => opt.MapFrom(i => negative(i.AdjustmentQuantity, i.InventoryType.UnitsPerCase))) .ForMember(d => d.DistributedQuantity, opt => opt.MapFrom(i => hideEmptyCases(i.DistributedQuantity, i.InventoryType.UnitsPerCase))) .ForMember(d => d.EndingQuantity, opt => opt.MapFrom(i => formatCases(i.EndingQuantity, i.InventoryType.UnitsPerCase))); } } private sealed class MovementReportMap : CsvClassMap { public MovementReportMap() { Map(m => m.Name).Name("Name of Commodity"); Map(m => m.UnitsPerCaseContainerType).Name("Pack Size / Units per Case"); Map(m => m.BeginningQuantity).Name("Beginning Inventory"); Map(m => m.AddedQuantity).Name("Units Rec'd"); Map(m => m.TotalAvailableQuantity).Name("Total Units Available"); Map(m => m.AdjustmentQuantity).Name("Adjustments (show + or -)"); Map(m => m.DistributedQuantity).Name("Units Distributed"); Map(m => m.EndingQuantity).Name("Ending Inventory"); } } public byte[] Write(MovementReport report) { using (var stream = new MemoryStream()) { WriteStream(report, stream); return stream.ToArray(); } } public void WriteStream(MovementReport report, Stream stream) { var csvConfiguration = new CsvConfiguration(); csvConfiguration.RegisterClassMap(); using (var workbook = new XLWorkbook(XLEventTracking.Disabled)) { var worksheet = workbook.AddWorksheet("Monthly Inventory Report"); using (var writer = new CsvWriter(new ExcelSerializer(worksheet))) { writer.Configuration.RegisterClassMap(new MovementReportMap()); writer.WriteField("Monthly Inventory Report"); writer.NextRecord(); writer.WriteField($"Month: {report.Month:MMMM yyyy}"); writer.NextRecord(); var items = Mapper.Map, IEnumerable> (report.Items) .OrderBy(i => i.Name); writer.WriteRecords(items); workbook.SaveAs(stream); } } } } }