diff --git a/FaKrosnoApi/Controllers/ExcelGeneratorController.cs b/FaKrosnoApi/Controllers/ExcelGeneratorController.cs new file mode 100644 index 0000000..d4bebfe --- /dev/null +++ b/FaKrosnoApi/Controllers/ExcelGeneratorController.cs @@ -0,0 +1,136 @@ +using System.Net; +using System.Net.Mail; +using Microsoft.AspNetCore.Mvc; +using Syncfusion.Drawing; +using Syncfusion.XlsIO; +using SytelineSaAppEfDataModel.Dtos; +using SytelineSaAppEfDataModel.Services; + +namespace FaKrosnoApi.Controllers; + +[ApiController] +[Route("api/[controller]")] +public class ExcelGeneratorController(IWzHeaderService wzHeaderService, IMaterialTransactionService materialTransactionService, IConfiguration configuration) : Controller +{ + [HttpGet("generate-meyle")] + public async Task GeneratePackListForMeyle(Guid packListId) + { + WzHeaderDto wzHeader = await wzHeaderService.GetById(packListId); + MaterialTransactionDto? materialTransaction = await materialTransactionService.GetByWzNumber(wzHeader.WzRowsMeyle.First().WzNumber); + + using ExcelEngine excelEngine = new ExcelEngine(); + IApplication application = excelEngine.Excel; + application.DefaultVersion = ExcelVersion.Xlsx; + + IWorkbook workbook = application.Workbooks.Create(1); + IWorksheet worksheet = workbook.Worksheets[0]; + + IStyle boldFontStyle = workbook.Styles.Add("BoldFontStyle"); + boldFontStyle.Font.Bold = true; + + var mainHeaders = new List + { "Numer zamówienia Meyle", "Meyle Numer", "Ilość w dostawie", "Numer Palety", "Nr Wz", "Nr Partii" }; + + worksheet["B1"].Value = "Packing List"; + worksheet["B1"].CellStyle = boldFontStyle; + + worksheet["B3"].Value = "Supplier Name"; + worksheet["B3"].CellStyle = boldFontStyle; + + worksheet["D3"].Value = "FA KROSNO"; + worksheet["D3"].CellStyle = boldFontStyle; + + worksheet["B4"].Value = "Packing List nr"; + worksheet["B4"].CellStyle = boldFontStyle; + + worksheet["B6"].Value = "Related delivery note"; + worksheet["B6"].CellStyle = boldFontStyle; + + worksheet["D6"].Value = string.Join(", ", wzHeader.WzRowsMeyle.Select(x => x.WzNumber).Distinct()); + worksheet["D6"].CellStyle = boldFontStyle; + + worksheet["B9"].Value = "Forwarder"; + worksheet["B9"].CellStyle = boldFontStyle; + + worksheet["B10"].Value = "Date"; + worksheet["B10"].CellStyle = boldFontStyle; + + worksheet["D10"].DateTime = materialTransaction?.CreateDate ?? DateTime.Now; + + int currentRow = 12; + + for (int i = 0; i < mainHeaders.Count; i++) + { + string columnLetter = GetColumnLetter(i); + worksheet.Range[$"{columnLetter}{currentRow}"].Text = mainHeaders[i]; + worksheet.Range[$"{columnLetter}{currentRow}"].CellStyle = boldFontStyle; + } + + currentRow++; + + foreach (var wzRow in wzHeader.WzRowsMeyle) + { + worksheet.Range[$"A{currentRow}"].Text = wzRow.OrderNumber; + worksheet.Range[$"B{currentRow}"].Text = wzRow.ItemNumber; + worksheet.Range[$"C{currentRow}"].Number = (double)wzRow.Quantity!; + worksheet.Range[$"D{currentRow}"].Number = (double)wzRow.PalletNumber!; + worksheet.Range[$"E{currentRow}"].Text = wzRow.WzNumber; + worksheet.Range[$"F{currentRow}"].Text = wzRow.PartNumber; + + currentRow++; + } + + for (int i = 0; i < 6; i++) + { + worksheet.AutofitColumn(i + 1); + } + + using MemoryStream stream = new MemoryStream(); + workbook.SaveAs(stream); + stream.Position = 0; + + SendEmail(stream); + } + + private static string GetColumnLetter(int columnIndex) + { + string columnName = string.Empty; + while (columnIndex >= 0) + { + columnName = (char)('A' + (columnIndex % 26)) + columnName; + columnIndex = (columnIndex / 26) - 1; + } + + return columnName; + } + + private void SendEmail(MemoryStream stream) + { + IConfigurationSection smtpSettings = configuration.GetSection("EmailSettings"); + string smtpHost = smtpSettings["SmtpServer"] ?? string.Empty; + int smtpPort = int.Parse(smtpSettings["Port"] ?? "0"); + string smtpUsername = smtpSettings["SenderEmail"] ?? string.Empty; + string smtpPassword = smtpSettings["SenderPassword"] ?? string.Empty; + string fromEmail = smtpSettings["SenderEmail"] ?? string.Empty; + List toEmail = (smtpSettings["RecipientEmail"] ?? string.Empty).Split(',').ToList(); + string subject = "MEYLE: Packing List"; + string body = + $"W załączeniu znajduje się Packing List dla klienta MEYLE wygenerowany {DateTime.Now:dd.MM.yyyy HH:mm:ss}"; + + using var mailMessage = new MailMessage(); + mailMessage.From = new MailAddress(fromEmail); + mailMessage.Subject = subject; + mailMessage.Body = body; + mailMessage.IsBodyHtml = false; + + mailMessage.Attachments.Add(new Attachment(stream, $"PackingList_Meyle_{DateTime.Now:yyyyMMddHHmmss}.xlsx", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")); + + toEmail.ForEach(x => mailMessage.To.Add(x)); + + using var smtpClient = new SmtpClient(smtpHost, smtpPort); + smtpClient.EnableSsl = true; + smtpClient.Credentials = new NetworkCredential(smtpUsername, smtpPassword); + smtpClient.Send(mailMessage); + } +} \ No newline at end of file diff --git a/FaKrosnoApi/Controllers/WzHeaderController.cs b/FaKrosnoApi/Controllers/WzHeaderController.cs index b1035a8..13155dc 100644 --- a/FaKrosnoApi/Controllers/WzHeaderController.cs +++ b/FaKrosnoApi/Controllers/WzHeaderController.cs @@ -35,4 +35,11 @@ public class WzHeaderController(IWzHeaderService service, IMaterialTransactionSe await service.CreateHeader(wzHeader); return CreatedAtAction(nameof(CreateHeader), wzHeader); } + + [HttpGet("by-id")] + public async Task> GetById([FromQuery] Guid id) + { + WzHeaderDto? wzHeader = await service.GetById(id); + return wzHeader != null ? Ok(wzHeader) : NotFound(); + } } \ No newline at end of file diff --git a/FaKrosnoApi/FaKrosnoApi.csproj b/FaKrosnoApi/FaKrosnoApi.csproj index 595a074..736fd0f 100644 --- a/FaKrosnoApi/FaKrosnoApi.csproj +++ b/FaKrosnoApi/FaKrosnoApi.csproj @@ -18,6 +18,7 @@ + diff --git a/FaKrosnoApi/Program.cs b/FaKrosnoApi/Program.cs index b7288ad..ce45794 100644 --- a/FaKrosnoApi/Program.cs +++ b/FaKrosnoApi/Program.cs @@ -108,6 +108,8 @@ builder.Services.AddScoped(); builder.Services.AddHostedService(); +Syncfusion.Licensing.SyncfusionLicenseProvider.RegisterLicense("NRAiBiAaIQQuGjN/V09+XU9HdVRDX3xKf0x/TGpQb19xflBPallYVBYiSV9jS3tTckVgWHldc3ZUR2lfVE90Vg=="); + var app = builder.Build(); app.UseOpenApi(); diff --git a/OrdersManagement/Components/Pages/WarehousePackList.razor b/OrdersManagement/Components/Pages/WarehousePackList.razor index b0b72a5..587a72f 100644 --- a/OrdersManagement/Components/Pages/WarehousePackList.razor +++ b/OrdersManagement/Components/Pages/WarehousePackList.razor @@ -24,8 +24,8 @@ - + @@ -99,6 +99,6 @@ private async Task ExportXls() { - await _grid.ExportToExcelAsync(); + await WarehouseService.GenerateXlsForMeyleAsync(WzHeader); } } \ No newline at end of file diff --git a/OrdersManagement/Services/WarehouseService.cs b/OrdersManagement/Services/WarehouseService.cs index 0998fe8..2d2f8e0 100644 --- a/OrdersManagement/Services/WarehouseService.cs +++ b/OrdersManagement/Services/WarehouseService.cs @@ -80,4 +80,14 @@ public class WarehouseService(IHttpClientFactory httpClientFactory) var response = await _httpClient.PutAsJsonAsync("api/WzRowMeyle", wzRowsMeyle); response.EnsureSuccessStatusCode(); } + + public async Task GenerateXlsForMeyleAsync(Guid wzHeaderId) + { + var response = await _httpClient.GetAsync($"api/ExcelGenerator/generate-meyle?packListId={wzHeaderId}"); + response.EnsureSuccessStatusCode(); + if (response.StatusCode != System.Net.HttpStatusCode.OK) + { + throw new Exception("Failed to generate XLS for Mayle"); + } + } } \ No newline at end of file diff --git a/SytelineSaAppEfDataModel/Dtos/WzHeaderDto.cs b/SytelineSaAppEfDataModel/Dtos/WzHeaderDto.cs index b45c435..ffbe71c 100644 --- a/SytelineSaAppEfDataModel/Dtos/WzHeaderDto.cs +++ b/SytelineSaAppEfDataModel/Dtos/WzHeaderDto.cs @@ -5,4 +5,6 @@ public class WzHeaderDto public Guid ID { get; set; } public Guid? FK_Client { get; set; } public DateTime CreatedDate { get; set; } + + public IEnumerable WzRowsMeyle { get; set; } = new List(); } \ No newline at end of file diff --git a/SytelineSaAppEfDataModel/Services/IWzHeaderService.cs b/SytelineSaAppEfDataModel/Services/IWzHeaderService.cs index d4c5630..6235e2b 100644 --- a/SytelineSaAppEfDataModel/Services/IWzHeaderService.cs +++ b/SytelineSaAppEfDataModel/Services/IWzHeaderService.cs @@ -6,4 +6,5 @@ public interface IWzHeaderService { Task> GetAll(); Task CreateHeader(WzHeaderDto wzHeader); + Task GetById(Guid id); } \ No newline at end of file diff --git a/SytelineSaAppEfDataModel/Services/WzHeaderService.cs b/SytelineSaAppEfDataModel/Services/WzHeaderService.cs index 79f96a5..2b4461c 100644 --- a/SytelineSaAppEfDataModel/Services/WzHeaderService.cs +++ b/SytelineSaAppEfDataModel/Services/WzHeaderService.cs @@ -18,4 +18,16 @@ public class WzHeaderService(SytelineSaAppDbContext context, IMapper mapper) : I await context.WzHeaders.AddAsync(entity); await context.SaveChangesAsync(); } + + public async Task GetById(Guid id) + { + var entity = await context.WzHeaders.FindAsync(id); + var items = await context.WzRowsMeyle.Where(x => x.FK_Header == id).Select(x => mapper.Map(x)) + .ToListAsync(); + + WzHeaderDto wzHeader = mapper.Map(entity); + wzHeader.WzRowsMeyle = items; + + return wzHeader; + } } \ No newline at end of file