using GB5Shared.DaprCache; using GB5Shared.DTO.Framework.Criteria; using GB5Shared.DTO.Framework.Login; using GB5Shared.DTO.Qualifier; using GB5Shared.EntityHandler; using GB5Shared.GB5Library.Qualifier; using GB5Shared.GenerateAutoNumber; using GB5Shared.QueryExecutor; using GB5Shared.UnixEpochDate; using Newtonsoft.Json; using QMSDAL.CustomCode.Checklist; using QMSDAL.CustomCode.ChecklistDetail; using QMSDAL.DTO; using QMSDAL.Query.Checklist; using System.Text.Json; using static GB5Shared.GB5Constant.Constant; namespace QMSBLL.Checklist { // ───────────────────────────────────────────────────────────────────────── // ChecklistBLL // // Save pipeline: // 1. BeginTransaction // 2. (if new) GetAutoNumber — batch = 1 header + detail count // 3. ExecuteSaveAsync with DAL callback (SaveChecklist/UpdateChecklist + SaveAllDetail) // 4. CommitTransaction // 5. KeyInvalidate.AllInvalidateCache // // Delete guard: if USAGECOUNT > 0, return validation error string (do NOT throw). // ───────────────────────────────────────────────────────────────────────── public class ChecklistBLL : IChecklistBLL { private readonly IChecklistDAL _ChecklistDAL; private readonly IChecklistDetailDAL _ChecklistDetailDAL; private readonly AutoNumber _AutoNumber; private readonly IQueryExecutor _QueryExecutor; private readonly KeyInvalidate _KeyInvalidate; private readonly BaseEntityAppService _BaseEntityAppService; public ChecklistBLL( IChecklistDAL checklistDAL, IChecklistDetailDAL checklistDetailDAL, AutoNumber autoNumber, IQueryExecutor queryExecutor, KeyInvalidate keyInvalidate, BaseEntityAppService baseEntityAppService) { _ChecklistDAL = checklistDAL; _ChecklistDetailDAL = checklistDetailDAL; _AutoNumber = autoNumber; _QueryExecutor = queryExecutor; _KeyInvalidate = keyInvalidate; _BaseEntityAppService = baseEntityAppService; } // ── Get single checklist ────────────────────────────────────────────── public async Task GetChecklistAsync( int checklistId, LoginDTO loginDTO, CancellationToken ct = default) { try { var result = await _ChecklistDAL.GetChecklistAsync( checklistId, loginDTO, ct); return JsonConvert.SerializeObject(result); } catch { throw; } } public async Task GetChecklistDetailAsync( int checklistId, LoginDTO loginDTO, CancellationToken ct = default) { try { return await _ChecklistDetailDAL.GetChecklistDetailAsync( checklistId, loginDTO, ct); } catch { throw; } } // ── Get active checklist list ───────────────────────────────────────── public async Task GetChecklistListAsync(int FirstNumber, int MaxResult, LoginDTO login, CriteriaDTO CriteriaDTO, CancellationToken ct = default) { try { return await _ChecklistDAL.GetChecklistListAsync(FirstNumber, MaxResult, CriteriaDTO, login, false, ct).ConfigureAwait(false); } catch (Exception) { throw; } } // ── Save (insert or update) ─────────────────────────────────────────── public async Task SaveChecklistAsync( ChecklistDTO dto, LoginDTO login, CancellationToken ct = default) { if (dto == null) throw new ArgumentNullException( nameof(dto), "Checklist data is required and cannot be empty."); if (login == null) throw new ArgumentNullException( nameof(login), "Login information is required."); bool isNew = dto.ChecklistId == 0; DateOnly currentDate = DateOnly.FromDateTime(DateTime.UtcNow); // --------------------------------------------- // HEADER AUDIT FIELDS // --------------------------------------------- dto.ChecklistModifiedById = login.UserId; dto.ChecklistModifiedOn = currentDate; if (isNew) { dto.ChecklistCreatedById = login.UserId; dto.ChecklistCreatedOn = currentDate; } // --------------------------------------------- // DETAIL AUDIT FIELDS // --------------------------------------------- if (dto.ChecklistDetailArray != null) { foreach (var detail in dto.ChecklistDetailArray) { detail.ModifiedById = login.UserId; detail.ModifiedOn = currentDate; // Only new detail records get Created fields if (detail.ChecklistDetailId == 0) { detail.CreatedById = login.UserId; detail.CreatedOn = currentDate; } } } // --------------------------------------------- // NEW CHECKLIST // --------------------------------------------- if (isNew) { int newChecklistId = await _ChecklistDAL.SaveChecklistAsync( dto, login); if (newChecklistId <= 0) { throw new Exception( "Checklist insert failed. " + "No valid Checklist ID was returned."); } dto.ChecklistId = newChecklistId; return $"Checklist saved successfully with Id {newChecklistId}"; } // --------------------------------------------- // EXISTING CHECKLIST // --------------------------------------------- await _ChecklistDAL.UpdateChecklistFullAsync( dto, login); return $"Checklist updated successfully with Id {dto.ChecklistId}"; } public async Task DeleteChecklist(int checklistId, LoginDTO loginDTO) { try { var statements = new List<(string sql, object param)> { (ChecklistQB.DELETE_CHECKLISTDETAIL, new { checklistid = checklistId }), (ChecklistQB.DELETE_CHECKLIST, new { checklistid = checklistId }) }; await _QueryExecutor.ExecuteInTransactionAsync(loginDTO, statements); return "Checklist AND Checklistdetails deleted successfully."; } catch (Exception ex) { throw new Exception($"ERROR DELETING CHECKLIST ID {checklistId}", ex); } } public async Task GetSelectListChecklistFull(int FirstNumber, int MaxResult, CriteriaDTO CriteriaDTO, LoginDTO LoginDTO) { try { var data = await _ChecklistDAL.GetSelectListChecklistFull(FirstNumber, MaxResult, CriteriaDTO, LoginDTO); string json = System.Text.Json.JsonSerializer.Serialize(data); return json; } catch (Exception) { throw; } } } }