using System.ComponentModel.DataAnnotations; using GB5Shared.DTO.Framework.AutoNumber; using GB5Shared.DTO.Framework.Criteria; using GB5Shared.DTO.Framework.Login; using GB5Shared.GenerateAutoNumber; using GB5Shared.Resource.Response; using GB5Shared.Validation; using Newtonsoft.Json; using TMSBLL.TxSkillUpgrade; using TMSDAL.CustomCode.TrainingCompletion; using TMSDAL.DTO.TrainingCompletion; using TMSDAL.Enums; namespace TMSBLL.TrainingCompletion { public class TrainingCompletionBLL : ITrainingCompletionBLL { private readonly ITrainingCompletionDAL _TrainingCompletionDAL; private readonly ITxSkillUpgradeBLL _TxSkillUpgradeBLL; private readonly AutoNumber _AutoNumber; private readonly IValidation _Validation; public TrainingCompletionBLL(ITrainingCompletionDAL trainingCompletionDAL, ITxSkillUpgradeBLL txSkillUpgradeBLL, AutoNumber autoNumber, IValidation validation) { _TrainingCompletionDAL = trainingCompletionDAL; _TxSkillUpgradeBLL = txSkillUpgradeBLL; _AutoNumber = autoNumber; _Validation = validation; } public async Task GetTrainingCompletion(int completionId, LoginDTO loginDTO) { try { var result = await _TrainingCompletionDAL.GetTrainingCompletion(completionId, loginDTO); return JsonConvert.SerializeObject(result); } catch (Exception) { throw; } } public async Task GetCompletionByEnrollment(int enrollmentId, LoginDTO loginDTO) { try { var result = await _TrainingCompletionDAL.GetCompletionByEnrollment(enrollmentId, loginDTO); return JsonConvert.SerializeObject(result); } catch (Exception) { throw; } } public async Task GetSelectList(CriteriaDTO criteriaDTO, LoginDTO login, CancellationToken ct) { try { return await _TrainingCompletionDAL.GetSelectList(criteriaDTO, login, ct); } catch (Exception) { throw; } } public async Task SaveTrainingCompletion(TrainingCompletionDTO dto, LoginDTO loginDTO) { if (dto == null) throw new ArgumentNullException(nameof(dto)); AutoNumberDTO? autoNumberDTO = null; try { if (dto.EnrollmentId == 0) throw new ValidationException("EnrollmentId is required."); if (dto.InstanceId == 0) throw new ValidationException("InstanceId is required."); if (dto.ProgrammeId == 0) throw new ValidationException("ProgrammeId is required."); if (dto.EmployeeId == 0) throw new ValidationException("EmployeeId is required."); if (!Enum.IsDefined(typeof(CompletionStatus), dto.CompletionStatus)) throw new ValidationException($"Invalid CompletionStatus value: {dto.CompletionStatus}."); dto.TenantId = loginDTO.ClientId; dto.ModifiedById = loginDTO.UserId; dto.ModifiedOn = DateTime.UtcNow; if (dto.TrainingCompletionId == 0) { autoNumberDTO = await _AutoNumber.GetAutoNumber(1, "TRAININGCOMPLETION", loginDTO); dto.TrainingCompletionId = autoNumberDTO.StartNumber; dto.CreatedById = loginDTO.UserId; dto.CreatedOn = DateTime.UtcNow; await _TrainingCompletionDAL.SaveTrainingCompletion(dto, loginDTO); if (dto.CompletionStatus == (byte)CompletionStatus.Completed && dto.IsPassed == 1) await _TxSkillUpgradeBLL.ApplySkillMappingAsync(dto.ProgrammeId, -1, dto.EnrollmentId, loginDTO, default); return string.Format(SuccessResponse.SaveSuccessWithCodeAndName, dto.TrainingCompletionCode, dto.TrainingCompletionName); } else { await _TrainingCompletionDAL.UpdateTrainingCompletion(dto, loginDTO); if (dto.CompletionStatus == (byte)CompletionStatus.Completed && dto.IsPassed == 1) await _TxSkillUpgradeBLL.ApplySkillMappingAsync(dto.ProgrammeId, -1, dto.EnrollmentId, loginDTO, default); return string.Format(SuccessResponse.UpdateSuccessWithCodeAndName, dto.TrainingCompletionCode, dto.TrainingCompletionName); } } catch (ValidationException vex) { throw new Exception(vex.Message); } catch (Exception) { if (autoNumberDTO != null && dto.TrainingCompletionId > 0) await _AutoNumber.RollbackAutoNumber("TRAININGCOMPLETION", dto.TrainingCompletionId, loginDTO); throw; } } public async Task GetTrainingCompletionList(LoginDTO loginDTO) { try { return await _TrainingCompletionDAL.GetTrainingCompletionList(loginDTO); } catch (Exception) { throw; } } public async Task SaveCompletionBulk(CompletionBulkDTO dto, LoginDTO loginDTO) { if (dto == null) throw new ArgumentNullException(nameof(dto)); if (dto.Records == null || dto.Records.Count == 0) throw new Exception("Records list cannot be empty."); AutoNumberDTO? autoNumberDTO = null; var toInsert = dto.Records.Where(r => r.TrainingCompletionId == 0).ToList(); var toUpdate = dto.Records.Where(r => r.TrainingCompletionId != 0).ToList(); try { if (toInsert.Count > 0) { autoNumberDTO = await _AutoNumber.GetAutoNumber(toInsert.Count, "TRAININGCOMPLETION", loginDTO); int nextId = autoNumberDTO.StartNumber; foreach (var record in toInsert) { record.TrainingCompletionId = nextId++; record.TenantId = loginDTO.ClientId; record.CreatedById = loginDTO.UserId; record.CreatedOn = DateTime.UtcNow; record.ModifiedById = loginDTO.UserId; record.ModifiedOn = DateTime.UtcNow; } await _TrainingCompletionDAL.SaveCompletionBulk(toInsert, loginDTO); } if (toUpdate.Count > 0) { foreach (var record in toUpdate) { record.TenantId = loginDTO.ClientId; record.ModifiedById = loginDTO.UserId; record.ModifiedOn = DateTime.UtcNow; } await _TrainingCompletionDAL.UpdateCompletionBulk(toUpdate, loginDTO); } return $"Bulk operation completed. Saved: {toInsert.Count}, Updated: {toUpdate.Count}."; } catch (Exception) { if (autoNumberDTO != null && toInsert.Count > 0) await _AutoNumber.RollbackAutoNumber("TRAININGCOMPLETION", autoNumberDTO.StartNumber, loginDTO); throw; } } } }