using GB5Shared.DTO.Framework.Criteria; using GB5Shared.DTO.Framework.Login; using GB5Shared.GenerateAutoNumber; using GB5Shared.Resource.Response; using SkillManagementBLL.Common; using SkillManagementDAL.CustomCode.EmployeeSkillProfile; using SkillManagementDAL.CustomCode.SkillAssessment; using SkillManagementDAL.DTO.EmployeeSkillProfile; using SkillManagementDAL.DTO.SkillAssessment; namespace SkillManagementBLL.SkillAssessment { public class SkillAssessmentBLL : ISkillAssessmentBLL { private readonly ISkillAssessmentDAL _assessmentDal; private readonly IEmployeeSkillProfileDAL _profileDal; private readonly AutoNumber _autoNumber; private readonly ISkillHubNotifier _hubNotifier; public SkillAssessmentBLL( ISkillAssessmentDAL assessmentDal, IEmployeeSkillProfileDAL profileDal, AutoNumber autoNumber, ISkillHubNotifier hubNotifier) { _assessmentDal = assessmentDal; _profileDal = profileDal; _autoNumber = autoNumber; _hubNotifier = hubNotifier; } public async Task GetHistory(int employeeId, LoginDTO login, CancellationToken ct) => await _assessmentDal.GetHistory(employeeId, login, ct); public async Task GetSkillAssessment(int AssessmentId, LoginDTO login, CancellationToken ct) => await _assessmentDal.GetSkillAssessment(AssessmentId, login, ct); public async Task GetSelectList(CriteriaDTO criteriaDTO, LoginDTO login, CancellationToken ct) => await _assessmentDal.GetSelectList(criteriaDTO, login, ct); public async Task Save(SkillAssessmentDTO dto, LoginDTO login, CancellationToken ct) { if (dto.EmployeeId == 0) throw new ArgumentException("EmployeeId is required."); var skillIds = (dto.SkillIds != null && dto.SkillIds.Count > 0) ? dto.SkillIds : (dto.SkillId != 0 ? new List { dto.SkillId } : new List()); if (skillIds.Count == 0) throw new ArgumentException("At least one SkillId is required."); var modelIds = (dto.ModelIds != null && dto.ModelIds.Count > 0) ? dto.ModelIds : new List { dto.ModelId }; if (dto.LevelAchieved < 1) throw new ArgumentException("LevelAchieved must be >= 1."); if (dto.AssessMethod > 5) throw new ArgumentException("AssessMethod must be 0-5."); if (dto.AssessedById == 0) dto.AssessedById = login.UserId; dto.CreatedById = login.UserId; dto.ModifiedById = login.UserId; dto.TenantId = login.ClientId; if (dto.AssessedDt == default) dto.AssessedDt = DateTime.UtcNow; dto.SourceType = 5; var assessmentCodes = new List(); // One TASSESSMENT (+ profile) row per selected skill x model foreach (var skillId in skillIds) { dto.SkillId = skillId; foreach (var modelId in modelIds) { dto.ModelId = modelId; // Get current level (for PreviousLevel) var currentLevel = await _profileDal.GetCurrentLevel( dto.EmployeeId, skillId, dto.ProductFamilyId, modelId, login, ct); dto.PreviousLevel = currentLevel ?? 0; // Generate IDs var an = await _autoNumber.GetNumberAsync(2, "TASSESSMENT", login); dto.AssessmentId = an.StartNumber; int profileId = an.StartNumber + 1; var codeAn = await _autoNumber.GetNumberAsync(1, "TASSESSMENTCODE", login); dto.AssessmentCode = $"AS-{codeAn.StartNumber - login.ServerConfigOffset}"; // Build profile (ONLY valid columns) var profile = new EmployeeSkillProfileDTO { ProfileId = profileId, ProfileName = $"EMP-{dto.EmployeeId}-SKL-{skillId}", EmployeeId = dto.EmployeeId, SkillId = skillId, ProductFamilyId = dto.ProductFamilyId, ModelId = modelId, CurrentLevNo = dto.LevelAchieved, ProfileStatus = 1, AssessedDt = dto.AssessedDt, TrainingPlanDate = dto.TrainingPlanDate, ActualTrainDt = dto.ActualTrainDt, NextReviewDt = dto.NextReviewDt, AssessedById = dto.AssessedById, Remarks = dto.Remarks, Status = 1, SortOrder = 9999, SourceType = dto.SourceType, CreatedById = login.UserId, ModifiedById = login.UserId, CreatedOn = DateTime.UtcNow, ModifiedOn = DateTime.UtcNow, TenantId = login.ClientId }; // 🔥 SINGLE CALL (handles both insert + upsert) await _assessmentDal.Insert(dto, profile, login, ct); await _hubNotifier.NotifyProfileChangedAsync(dto.EmployeeId, skillId, login.ClientId, ct).ConfigureAwait(false); assessmentCodes.Add(dto.AssessmentCode); } } return string.Format(SuccessResponse.SaveSuccessWithAssessmentNumber, string.Join(", ", assessmentCodes)); } } }