using GB5Shared.DTO.Framework.AutoNumber; using GB5Shared.DTO.Framework.Criteria; using GB5Shared.DTO.Framework.Logging; using GB5Shared.DTO.Framework.Login; using GB5Shared.GenerateAutoNumber; using GB5Shared.QueryExecutor; using GB5Shared.Resource.Response; using GB5Shared.Validation; using MMBLL.MaterialGrade; using MMBLL.ParameterSet; using MMBLL.Standard; using MMDAL.CustomCode.Grade; using MMDAL.CustomCode.MaterialGrade; using MMDAL.DTO.Grade; using MMDAL.DTO.MaterialGrade; using MMDAL.Query.Grade; using MMDAL.Query.MaterialGrade; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Data.Common; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MMBLL.Grade { public class GradeBLL : IGradeBLL { private readonly IGradeDAL _GradeDAL; private readonly AutoNumber _AutoNumber; private readonly IValidation _Validation; private readonly IQueryExecutor _QueryExecutor; public GradeBLL(IGradeDAL GradeDAL, AutoNumber autoNumber, IValidation validation, IQueryExecutor QueryExecutor) { _GradeDAL = GradeDAL; _AutoNumber = autoNumber; _Validation = validation; _QueryExecutor = QueryExecutor; } public async Task GetGrade(int MaterialGradeId, LoginDTO loginDTO) { try { string sql = GradeQB.GET_GRADE; var parameters = new { GradeId = MaterialGradeId }; var result = await _GradeDAL.GetGrade(loginDTO, sql, parameters); return JsonConvert.SerializeObject(result); } catch (Exception) { throw; } } public async Task GetSelectListGrade(CriteriaDTO criteriaDTO, LoginDTO loginDTO) { try { return await _GradeDAL.GetSelectListGrade(criteriaDTO, loginDTO); } catch (Exception) { throw; } } public async Task SaveGrade(GradeDTO GradeDTO, LoginDTO LoginDTO) { if (GradeDTO == null) throw new ArgumentNullException(nameof(GradeDTO)); AutoNumberDTO? specAuto = null; AutoNumberDTO? matAuto = null; try { /* ================= VALIDATION ================= */ await _Validation.NotEmpty(GradeDTO.MaterialGrade.MaterialGradeCode, nameof(GradeDTO.MaterialGrade.MaterialGradeCode)); await _Validation.NotEmpty(GradeDTO.MaterialGrade.MaterialGradeName, nameof(GradeDTO.MaterialGrade.MaterialGradeName)); await _Validation.NotEmpty(GradeDTO.Specification.SpecificationName, nameof(GradeDTO.Specification.SpecificationName)); /* ================= MATERIAL GRADE ================= */ GradeDTO.MaterialGrade.MaterialGradeModifiedById = LoginDTO.UserId; GradeDTO.MaterialGrade.MaterialGradeModifiedOn = DateTime.UtcNow; int materialId = GradeDTO.MaterialGrade.MaterialGradeId; if (materialId == 0) { matAuto = await _AutoNumber.GetNumberAsync(1, "MATERIALGRADE", LoginDTO); GradeDTO.MaterialGrade.MaterialGradeId = matAuto.StartNumber; GradeDTO.MaterialGrade.MaterialGradeCreatedById = LoginDTO.UserId; GradeDTO.MaterialGrade.MaterialGradeCreatedOn = DateTime.UtcNow; } /* ================= SPECIFICATION ================= */ GradeDTO.Specification.ObjectId = GradeDTO.MaterialGrade.MaterialGradeId; GradeDTO.Specification.SpecificationModifiedById = LoginDTO.UserId; GradeDTO.Specification.SpecificationModifiedOn = DateTime.UtcNow; int specId = GradeDTO.Specification.SpecificationId; if (specId == 0) { int detailCount = GradeDTO.Specification.SpecificationDetailArray?.Count ?? 0; specAuto = await _AutoNumber.GetNumberAsync(1 + detailCount, "MATERIALGRADE", LoginDTO); int nextId = specAuto.StartNumber; GradeDTO.Specification.SpecificationId = nextId++; GradeDTO.Specification.SpecificationCreatedById = LoginDTO.UserId; GradeDTO.Specification.SpecificationCreatedOn = DateTime.UtcNow; if (GradeDTO.Specification.SpecificationDetailArray != null) { foreach (var d in GradeDTO.Specification.SpecificationDetailArray) { d.SpecificationDetailId = nextId++; d.SpecificationId = GradeDTO.Specification.SpecificationId; } } } else { // UPDATE case → assign SpecId to details if (GradeDTO.Specification.SpecificationDetailArray != null) { foreach (var d in GradeDTO.Specification.SpecificationDetailArray) { d.SpecificationId = specId; } } } /* ================= SAVE / UPDATE ================= */ if (materialId == 0 && specId == 0) { // BOTH NEW await _GradeDAL.SaveGrade(GradeDTO, LoginDTO); return $"{SuccessResponse.SaveSuccess}"; } else { // UPDATE FLOW await _GradeDAL.UpdateGrade(GradeDTO, LoginDTO); return $"{SuccessResponse.UpdateSuccess}"; } } catch (ValidationException vex) { throw new Exception(vex.Message); } catch (Exception) { if (specAuto != null && GradeDTO.Specification.SpecificationId > 0) await _AutoNumber.RollbackAutoNumber("MATERIALGRADE", specAuto.StartNumber, LoginDTO); if (matAuto != null && GradeDTO.MaterialGrade.MaterialGradeId > 0) await _AutoNumber.RollbackAutoNumber("MATERIALGRADE", matAuto.StartNumber, LoginDTO); throw; } } public async Task DeleteGrade(int MaterialGradeId, LoginDTO loginDTO) { try { // 🔹 1. Delete Details var detailResult = await _GradeDAL.DeleteSpecificationDetail(MaterialGradeId, loginDTO); // 🔹 2. Delete Specification var specResult = await _GradeDAL.DeleteSpecification(MaterialGradeId, loginDTO); // 🔹 3. Delete Parent var gradeResult = await _GradeDAL.DeleteGrade(MaterialGradeId, loginDTO); if (gradeResult <= 0) return $"{ErrorResponse.DeleteNotFoundMessage}"; return $"{SuccessResponse.DeleteSuccessMessage}"; } catch (Exception ex) { throw new Exception($"Error deleting Grade ID {MaterialGradeId}", ex); } } public async Task GetGradeList(LoginDTO loginDTO) { try { string sql = GradeQB.GET_LIST_GRADE; var result = await _GradeDAL.GetGradeList( loginDTO, sql ); return JsonConvert.SerializeObject(result); } catch (Exception) { throw; } } } }