using GB5Shared.DTO.Framework.Login; using GB5Shared.Telemetry; using Newtonsoft.Json; using SkillManagementBLL.EmployeeSkillProfile; using SkillManagementDAL.CustomCode.EmployeeSkillProfile; using SkillManagementDAL.DTO.EmployeeSkillProfile; namespace SkillManagementBLL.SkillGrant { public class SkillGrantBLL : ISkillGrantBLL { private readonly IEmployeeSkillProfileDAL _EmployeeSkillProfileDAL; private readonly IEmployeeSkillProfileBLL _EmployeeSkillProfileBLL; public SkillGrantBLL(IEmployeeSkillProfileDAL employeeSkillProfileDAL, IEmployeeSkillProfileBLL employeeSkillProfileBLL) { _EmployeeSkillProfileDAL = employeeSkillProfileDAL; _EmployeeSkillProfileBLL = employeeSkillProfileBLL; } public async Task ApplySkillGrantAsync(int employeeId, int skillId, int productFamilyId, int modelId, byte levelNo, LoginDTO loginDTO, CancellationToken ct) { GB5Trace.Step("apply-skill-grant", new { employeeId, skillId, productFamilyId, modelId, levelNo }); var existingJson = await _EmployeeSkillProfileDAL.GetByEmployee(employeeId, 0, skillId, loginDTO, ct).ConfigureAwait(false); var existing = JsonConvert.DeserializeObject>(existingJson) ?? new List(); var match = existing.FirstOrDefault(p => p.ProductFamilyId == productFamilyId && p.ModelId == modelId); // Never auto-downgrade an existing higher level. if (match != null && match.CurrentLevNo >= levelNo) { GB5Trace.Step("skill-grant-no-op-not-higher", new { employeeId, skillId, existingLevel = match.CurrentLevNo, grantedLevel = levelNo }); return; } var dto = match ?? new EmployeeSkillProfileDTO { EmployeeId = employeeId, SkillId = skillId, ProductFamilyId = productFamilyId, ModelId = modelId, CreatedById = loginDTO.UserId, CreatedOn = DateTime.UtcNow, Status = 1, SourceType = 5, SortOrder = 9999 }; dto.CurrentLevNo = levelNo; dto.ProfileStatus = 1; // Current dto.AssessedDt = DateTime.UtcNow; dto.AssessedById = -1; // system/auto — granted via training completion, not a human assessor await _EmployeeSkillProfileBLL.Save(dto, loginDTO, ct).ConfigureAwait(false); } } }