using GB5Shared.DTO.Framework.Criteria; using GB5Shared.DTO.Framework.Login; using GB5Shared.GenerateAutoNumber; using GB5Shared.Resource.Response; using GB5Shared.Validation; using SkillManagementDAL.CustomCode.SkillGroup; using SkillManagementDAL.DTO.SkillGroup; using System.Text.Json; namespace SkillManagementBLL.SkillGroup { public class SkillGroupBLL : ISkillGroupBLL { private readonly ISkillGroupDAL _dal; private readonly AutoNumber _autoNumber; private readonly IValidation _validation; public SkillGroupBLL(ISkillGroupDAL dal, AutoNumber autoNumber, IValidation validation) { _dal = dal; _autoNumber = autoNumber; _validation = validation; } public async Task GetList(int domainId, LoginDTO login, CancellationToken ct) => await _dal.GetList(domainId, login, ct); public async Task GetById(int groupId, LoginDTO login, CancellationToken ct) => await _dal.GetById(groupId, login, ct); public async Task GetSelectList(CriteriaDTO criteriaDTO, LoginDTO login, CancellationToken ct) => await _dal.GetSelectList(criteriaDTO, login, ct); public async Task GetSkillGroupList(int firstNumber, int maxResult, CriteriaDTO criteriaDTO, LoginDTO login, CancellationToken ct = default) { // ── VALIDATION ─────────────────────────────────────────── if (firstNumber == -1 && maxResult != -1) throw new ArgumentException("MaxResult must also be -1 when FirstNumber is -1."); if (firstNumber != -1 && maxResult == -1) throw new ArgumentException("FirstNumber must also be -1 when MaxResult is -1."); if (firstNumber != -1 && firstNumber < 1) throw new ArgumentException($"FirstNumber must be >= 1 or -1. Got: {firstNumber}"); if (maxResult != -1 && maxResult < 1) throw new ArgumentException($"MaxResult must be >= 1 or -1. Got: {maxResult}"); // ── FETCH DATA ─────────────────────────────────────────── bool isAllData = firstNumber == -1 && maxResult == -1; List data = isAllData ? await _dal.GetAllList(login, ct) : await _dal.GetPagedList(firstNumber, maxResult, login, ct); // ── SERIALIZE (KEY CHANGE) ──────────────────────────────── var json = JsonSerializer.Serialize(data); return json; } public async Task Save(SkillGroupDTO dto, LoginDTO login, CancellationToken ct) { await _validation.NotEmpty(dto.GroupCode, nameof(dto.GroupCode)); await _validation.NotEmpty(dto.GroupName, nameof(dto.GroupName)); if (dto.DomainId == 0) throw new ArgumentException("DomainId is required."); if (dto.DisplayOrder <= 0) throw new ArgumentException("DisplayOrder must be greater than 0."); var now = DateTime.UtcNow; // ✅ FK VALIDATION VIA DAL //var exists = await _dal.DomainExists(dto.DomainId, login.ClientId, login); //if (!exists) // throw new Exception("Invalid DomainId"); dto.TenantId = login.ClientId; dto.ModifiedById = login.UserId; dto.ModifiedOn = now; bool isNew = dto.GroupId == 0; GB5Shared.DTO.Framework.AutoNumber.AutoNumberDTO? an = null; try { if (isNew) { an = await _autoNumber.GetNumberAsync(1, "MSKILLGROUP", login); dto.GroupId = an.StartNumber; dto.CreatedById = login.UserId; dto.CreatedOn = now; var rows = await _dal.Insert(dto, login, ct); if (rows == 0) throw new Exception("Insert failed"); return string.Format(SuccessResponse.SaveSuccessWithCodeAndName, dto.GroupCode, dto.GroupName); } else { var rows = await _dal.Update(dto, login, ct); if (rows == 0) throw new Exception("Update failed"); return string.Format(SuccessResponse.UpdateSuccessWithCodeAndName, dto.GroupCode, dto.GroupName); } } catch { if (an != null && isNew) await _autoNumber.RollbackAutoNumber("MSKILLGROUP", an.StartNumber, login); throw; } } public async Task DeleteSkillGroup(int groupId, LoginDTO loginDTO) { var result = await _dal.DeleteSkillGroup(groupId, loginDTO); if (result == ErrorResponse.DeleteNotFoundMessage) throw new Exception(result); return result; } } }