using GB5Shared.DaprCache; using GB5Shared.DTO.Framework.Criteria; using GB5Shared.DTO.Framework.Login; using GB5Shared.DTO.Qualifier; using GB5Shared.EntityHandler; using GB5Shared.GB5Library.Qualifier; using GB5Shared.GenerateAutoNumber; using GB5Shared.ListQuery; using GB5Shared.QueryExecutor; using GB5Shared.Resource.Response; using Newtonsoft.Json; using SwDAL.CustomCode.ScriptBranch; using SwDAL.DTO.ScriptBranch; using static GB5Shared.GB5Constant.Constant; namespace SwBLL.ScriptBranch; public class ScriptBranchBLL : IScriptBranchBLL { private readonly IScriptBranchDAL _ScriptBranchDAL; private readonly AutoNumber _AutoNumber; private readonly IQueryExecutor _QueryExecutor; private readonly KeyInvalidate _KeyInvalidate; private readonly IListHandler _ListHandler; private readonly BaseEntityAppService _BaseEntityAppService; public ScriptBranchBLL( IScriptBranchDAL scriptBranchDAL, AutoNumber autoNumber, IQueryExecutor queryExecutor, KeyInvalidate keyInvalidate, IListHandler listHandler, BaseEntityAppService baseEntityAppService) { _ScriptBranchDAL = scriptBranchDAL; _AutoNumber = autoNumber; _QueryExecutor = queryExecutor; _KeyInvalidate = keyInvalidate; _ListHandler = listHandler; _BaseEntityAppService = baseEntityAppService; } // ── Read — typed pass-through ───────────────────────────────────────── public async Task GetById(int branchId, LoginDTO loginDTO, CancellationToken ct) => await _ScriptBranchDAL.GetById(branchId, loginDTO, ct).ConfigureAwait(false); public async Task GetList( CriteriaDTO criteria, string? searchText, int pageOffset, int pageSize, LoginDTO loginDTO, CancellationToken ct = default) { var merged = CriteriaRouterHelper.WithSearchAndPaging(criteria, searchText, pageOffset, pageSize); var c = CriteriaBinder.Bind(merged); var result = await _ListHandler .HandleAsync(new ScriptBranchListQuery(c), loginDTO, ct) .ConfigureAwait(false); return JsonConvert.SerializeObject(result); } public async Task GetSelectListScriptBranch( int firstNumber, int maxResult, CriteriaDTO criteriaDTO, LoginDTO loginDTO) => await _ScriptBranchDAL.GetSelectListScriptBranch(firstNumber, maxResult, loginDTO) .ConfigureAwait(false); // ── Save (insert or update) ─────────────────────────────────────────── public async Task Save(ScriptBranchDTO dto, LoginDTO loginDTO, CancellationToken ct) { if (dto == null) throw new ArgumentNullException(nameof(dto)); if (dto.DbModelId <= 0) throw new ArgumentException("DbModelId is required.", nameof(dto)); dto.TenantId = loginDTO.ClientId; var Trans = await _QueryExecutor.BeginTransactionAsync(loginDTO); try { bool isNew = dto.BranchId == 0; if (isNew) { // Was AUTONUMBERCONSTANT.SWDBSERVER — a copy-paste bug (same class already // found and fixed in 7 sibling BLLs, §31.10.1) that had this entity allocating // BranchIds from DbServer's own counter. Never caught before because the one // real branch row ("MAIN", BranchId=1) was seeded via direct SQL, not this path. var auto = await _AutoNumber.GetNumberAsync(1, AUTONUMBERCONSTANT.SWSCRIPTBRANCH, loginDTO, Trans); dto.BranchId = auto.StartNumber; } await _BaseEntityAppService.ExecuteSaveAsync( EntityConstant.OBJECTSWSCRIPTBRANCH, EventTypeConstant.SAVESCRIPTBRANCHEVENTTYPEID, dto, loginDTO, async tx => { _ = isNew ? await _ScriptBranchDAL.SaveScriptBranch(dto, loginDTO, tx, ct) : await _ScriptBranchDAL.UpdateScriptBranch(dto, loginDTO, tx, ct); return dto.BranchId; }, null, -1, -1, Trans); await _QueryExecutor.CommitAsync(Trans); var keyGen = new CacheKeyGeneration(); var cacheKey = keyGen.KeyGeneration( dto.BranchId, EntityConstant.OBJECTSWSCRIPTBRANCH, CacheKeyLevel.CLIENT_LEVEL, loginDTO); await _KeyInvalidate.AllInvalidateCache(cacheKey); return isNew ? $"{SuccessResponse.SaveSuccessMessage} {dto.BranchId}" : $"{SuccessResponse.UpdateSuccessMessage} {dto.BranchId}"; } catch (Exception) { await _QueryExecutor.RollbackAsync(Trans); throw; } } // ── Delete ──────────────────────────────────────────────────────────── public async Task Delete(int branchId, LoginDTO loginDTO, CancellationToken ct) { var Trans = await _QueryExecutor.BeginTransactionAsync(loginDTO); try { await _BaseEntityAppService.ExecuteSaveAsync( EntityConstant.OBJECTSWSCRIPTBRANCH, EventTypeConstant.DELETESCRIPTBRANCHEVENTTYPEID, new ScriptBranchDTO { BranchId = branchId, TenantId = loginDTO.ClientId }, loginDTO, async tx => { await _ScriptBranchDAL.DeleteScriptBranch(branchId, loginDTO, tx, ct); return branchId; }, null, -1, -1, Trans); await _QueryExecutor.CommitAsync(Trans); var keyGen = new CacheKeyGeneration(); var cacheKey = keyGen.KeyGeneration( branchId, EntityConstant.OBJECTSWSCRIPTBRANCH, CacheKeyLevel.CLIENT_LEVEL, loginDTO); await _KeyInvalidate.AllInvalidateCache(cacheKey); return SuccessResponse.DeleteSuccessMessage; } catch (Exception) { await _QueryExecutor.RollbackAsync(Trans); throw; } } }