| @@ -0,0 +1,202 @@ | |||
| WebUI / Pages : | |||
| =============== | |||
| private async Task Export() | |||
| { | |||
| item.DT_WORK_FORCE_ID_WORK_FORCE = listDT_WORK_FORCE_ID_WORK_FORCE!.Where(e => e.ID_WORK_FORCE == item.ID_WORK_FORCE).FirstOrDefault(); | |||
| if(item.DATE_START>item.DATE_END) | |||
| { | |||
| var dtFin = item.DATE_START; | |||
| var dtDebut = item.DATE_END; | |||
| item.DATE_START = dtDebut; | |||
| item.DATE_END = dtFin; | |||
| } | |||
| try | |||
| { | |||
| var resultat = await ApiService.GetExportByFiltersAsync($"api/DT_TIME_SHEET/export", item); | |||
| if (resultat == null || resultat.Length == 0) | |||
| { | |||
| // Gérer le cas d'erreur ou pas de données | |||
| ToastService.ShowInfo($"Il n'y a pas de données disponibles.", settings => { settings.Timeout = 2000; settings.IconType = IconType.None; settings.Position = ToastPosition.BottomCenter; }); | |||
| return; | |||
| } | |||
| // Nom de fichier avec timestamp | |||
| var now = DateTime.Now; | |||
| var fileName = $"reportings_{now:yyyyMMdd_HHmmss}.xlsx"; | |||
| // Convertir en base64 | |||
| var base64 = Convert.ToBase64String(resultat); | |||
| // Appel JS pour lancer le téléchargement | |||
| await JS!.InvokeVoidAsync("downloadFileFromByteArray", fileName, base64); | |||
| } | |||
| catch (Exception ex) | |||
| { | |||
| ToastService.ShowError($"Erreur dans les exports. Faites CTRL + F5 et recommencez... Si le soucis persiste, voir avec l'administrateur.", settings => { settings.Timeout = 2000; settings.IconType = IconType.None; settings.Position = ToastPosition.BottomCenter; }); | |||
| } | |||
| } | |||
| WebUI / Services : | |||
| ================== | |||
| public async Task<byte[]?> GetExportByFiltersAsync<T>(string url, T data) | |||
| { | |||
| var response = await _httpClient.PostAsJsonAsync<T>(url, data); | |||
| if (!response.IsSuccessStatusCode) | |||
| return null; | |||
| return await response.Content.ReadAsByteArrayAsync(); | |||
| } | |||
| API / CONTROLLER | |||
| ================ | |||
| using Microsoft.AspNetCore.Authorization; | |||
| using Microsoft.AspNetCore.Mvc; | |||
| using Temporis.Domain; | |||
| namespace Temporis.Api.Controllers | |||
| { | |||
| public partial class DT_TIME_SHEETController | |||
| { | |||
| [HttpPost("export")] | |||
| [Authorize(Roles = "Admin,Manager")] | |||
| public async Task<ActionResult> Export([FromBody] DT_TIME_SHEET dt_time_sheet) | |||
| { | |||
| var bytes = await dt_time_sheetService.ExportReportings(dt_time_sheet); | |||
| if (bytes == null || bytes.Length == 0) | |||
| return NotFound("Aucune donnée à exporter."); | |||
| return File(bytes, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", $"reportings.xlsx"); | |||
| } | |||
| } | |||
| } | |||
| APPLICATION / Service : | |||
| ======================= | |||
| >>> D'abord : Installer le nuget ClosedXML sur le projet "Application" | |||
| #region Exports | |||
| public async Task<byte[]?> ExportReportings(DT_TIME_SHEET filters) | |||
| { | |||
| if (filters == null) | |||
| return null; | |||
| var lst = await dt_time_sheetRepository.GetAll_by_filters_Async(filters); | |||
| var lstItems = lst.ToList(); | |||
| if (lstItems == null || lstItems.Count == 0) | |||
| return null; | |||
| using (var workbook = new XLWorkbook()) | |||
| { | |||
| // Grouper les lignes par ID_TIME_SHEET | |||
| var groupByTimeSheet = lstItems | |||
| .GroupBy(l => l.ID_TIME_SHEET) | |||
| .ToList(); | |||
| foreach (var group in groupByTimeSheet) | |||
| { | |||
| var timeSheet = group.First().DT_TIME_SHEET; | |||
| string nomOnglet = timeSheet?.LIBELLE ?? $"TimeSheet_{group.Key.ToString().Substring(0, 8)}"; | |||
| // Crée l'onglet | |||
| var worksheet = workbook.Worksheets.Add(nomOnglet); | |||
| int row = 0; | |||
| // Identification | |||
| worksheet.Cell(row + 1, 1).Value = "Nom"; | |||
| worksheet.Cell(row + 2, 1).Value = "Prénom"; | |||
| worksheet.Cell(row + 3, 1).Value = "Début Période"; | |||
| worksheet.Cell(row + 4, 1).Value = "Fin Période"; | |||
| worksheet.Cell(row + 5, 1).Value = "Validation manager ?"; | |||
| worksheet.Cell(row + 1, 1).Style.Font.Bold = true; | |||
| worksheet.Cell(row + 2, 1).Style.Font.Bold = true; | |||
| worksheet.Cell(row + 3, 1).Style.Font.Bold = true; | |||
| worksheet.Cell(row + 4, 1).Style.Font.Bold = true; | |||
| worksheet.Cell(row + 5, 1).Style.Font.Bold = true; | |||
| worksheet.Cell(row + 1, 2).Value = timeSheet!.DT_WORK_FORCE_ID_WORK_FORCE!.LAST_NAME; | |||
| worksheet.Cell(row + 2, 2).Value = timeSheet!.DT_WORK_FORCE_ID_WORK_FORCE!.FIRST_NAME; | |||
| worksheet.Cell(row + 3, 2).Value = timeSheet!.DATE_START.ToString("dd-MM-yyyy"); | |||
| worksheet.Cell(row + 4, 2).Value = timeSheet!.DATE_END.ToString("dd-MM-yyyy"); | |||
| worksheet.Cell(row + 5, 2).Value = timeSheet!.IsValidat ? "Oui" : "Non"; | |||
| row = row + 7; | |||
| // Entêtes de lignes | |||
| worksheet.Cell(row, 1).Value = "Date"; | |||
| worksheet.Cell(row, 2).Value = "Projet"; | |||
| worksheet.Cell(row, 3).Value = "Quantité (j)"; | |||
| worksheet.Cell(row, 4).Value = "Télétravail"; | |||
| worksheet.Row(row).Style.Font.Bold = true; | |||
| // Remplir les lignes | |||
| row = row + 1; | |||
| double nbrTeleTravail = 0; | |||
| var lstAlternance = group.Where(e=>e.DT_PROJECT?.ID_PROJECT_TYPE == ToolsRepo.ID_PROJECT_TYPE_ALTERNANCE).ToList(); | |||
| foreach (var line in group) | |||
| { | |||
| worksheet.Cell(row, 1).Value = line.DAY.ToString("dd-MM-yyyy"); | |||
| worksheet.Cell(row, 2).Value = line.DT_PROJECT?.LIBELLE_PROJECT ?? ""; | |||
| worksheet.Cell(row, 3).Value = line.QUANTITY; | |||
| worksheet.Cell(row, 4).Value = line.TELETRAVAIL ? "Oui" : "Non"; | |||
| if(line.TELETRAVAIL) | |||
| { | |||
| nbrTeleTravail = nbrTeleTravail + line.QUANTITY; | |||
| } | |||
| row++; | |||
| } | |||
| row = row + 2; | |||
| worksheet.Cell(row, 1).Value = "Total télétravail (j)"; | |||
| worksheet.Cell(row, 1).Style.Font.Bold = true; | |||
| worksheet.Cell(row, 2).Value = nbrTeleTravail; | |||
| var lstAbs = await dt_day_offRepository.GetAll_By_ID_WORK_FORCE_And_Dates_Async(timeSheet!.ID_WORK_FORCE, timeSheet!.DATE_START, timeSheet!.DATE_END); | |||
| var lstAbsences = lstAbs.ToList(); | |||
| var nbrJoursOuvres = Infrastructure.Tools.NbrJoursOuvres(timeSheet!.DATE_START, timeSheet!.DATE_END); | |||
| row = row + 2; | |||
| worksheet.Cell(row, 1).Value = "Nbre de Tickets Restaurant"; | |||
| worksheet.Cell(row, 1).Style.Font.Bold = true; | |||
| worksheet.Cell(row, 2).Value = nbrJoursOuvres - lstAbsences.Count - lstAlternance.Count; | |||
| row = row + 2; | |||
| if (lstAbsences != null && lstAbsences.Count() > 0) | |||
| { | |||
| worksheet.Cell(row, 1).Value = "Absences"; | |||
| worksheet.Cell(row, 1).Style.Font.Bold = true; | |||
| row = row + 1; | |||
| foreach (var item in lstAbsences) | |||
| { | |||
| worksheet.Cell(row, 1).Value = item.DATE_DAY_OFF.ToString("dd-MM-yyyy"); | |||
| worksheet.Cell(row, 2).Value = item.DT_DAY_OFF!.DT_REF_DAY_OFF_TYPE!.LIBELLE_DAY_OFF_TYPE; | |||
| row++; | |||
| } | |||
| } | |||
| // Ajustement automatique des colonnes | |||
| worksheet.Columns().AdjustToContents(); | |||
| } | |||
| using var stream = new MemoryStream(); | |||
| workbook.SaveAs(stream); | |||
| return stream.ToArray(); | |||
| } | |||
| } | |||
| #endregion | |||