using AccountsDAL.CustomCode.AccountGroup; using AccountsDAL.DTO.AccountGroup; using Dapr.Client; using GB5Shared.DaprCache; using GB5Shared.DTO.Framework.Criteria; using GB5Shared.DTO.Framework.HybridCache; using GB5Shared.DTO.Framework.Login; using GB5Shared.EntityHandler; using GB5Shared.GenerateAutoNumber; using GB5Shared.PubSub.OutBox; using GB5Shared.QueryExecutor; using GB5Shared.Resource.Response; using GB5Shared.WorkFlow.WorkFlowEngine; using Newtonsoft.Json; using System.Data.Common; using static GB5Shared.GB5Constant.Constant; namespace AccountsBLL.AccountGroup { public class AccountGroupBLL : IAccountGroupBLL { private readonly IAccountGroupDAL _AccountGroupDAL; private readonly AutoNumber _AutoNumber; private readonly IWorkFlowEngine _WorkFlowEngine; private readonly IQueryExecutor _QueryExecutor; private readonly IOutBox _OutBox; private readonly KeyInvalidate _KeyInvalidate; private readonly DaprClient _DaprClient; private readonly BaseEntityAppService _BaseEntityAppService; public AccountGroupBLL( IAccountGroupDAL accountGroupDAL, AutoNumber autoNumber, IWorkFlowEngine workFlowEngine, IQueryExecutor queryExecutor, IOutBox outBox, KeyInvalidate keyInvalidate, DaprClient daprClient, BaseEntityAppService baseEntityAppService) { _AccountGroupDAL = accountGroupDAL; _AutoNumber = autoNumber; _WorkFlowEngine = workFlowEngine; _QueryExecutor = queryExecutor; _OutBox = outBox; _KeyInvalidate = keyInvalidate; _DaprClient = daprClient; _BaseEntityAppService = baseEntityAppService; } // ── Read ───────────────────────────────────────────────────────────── public async Task GetAccountGroup(int accountGroupId, LoginDTO loginDTO) { try { var dto = await _AccountGroupDAL.GetAccountGroup(accountGroupId, loginDTO).ConfigureAwait(false); return JsonConvert.SerializeObject(dto); } catch (Exception) { throw; } } public async Task GetSelectListAccountGroup(CriteriaDTO criteriaDTO, LoginDTO loginDTO) { try { return await _AccountGroupDAL.GetSelectListAccountGroup(criteriaDTO, loginDTO).ConfigureAwait(false); } catch (Exception) { throw; } } public async Task GetAccountGroupList(CriteriaDTO criteriaDTO, LoginDTO loginDTO) { try { return await _AccountGroupDAL.GetAccountGroupList(criteriaDTO, loginDTO).ConfigureAwait(false); } catch (Exception) { throw; } } public async Task GetAccountGroupTree(LoginDTO loginDTO, CriteriaDTO CriteriaDTO) { try { string flatListJson = await _AccountGroupDAL.GetAccountGroupTree(loginDTO, CriteriaDTO).ConfigureAwait(false); var flatList = JsonConvert.DeserializeObject>(flatListJson) ?? new List(); List accountGroupTreeDTOs = new List(); foreach (var item in flatList) { var node = new AccountGroupTreeDTO { Id = item.Id, Code = item.Code, data = item.Name, attr = new AccountGroupTreeAttributeDTO { Id = item.Id, Code = item.Code } }; // Set Parent property if item has a parent (ParentId != -1) if (item.ParentId != -1) { node.Parent = new AccountGroupTreeDTO { Id = item.ParentId }; } accountGroupTreeDTOs.Add(node); } var tree = BuildAccountGroupTree(accountGroupTreeDTOs); return JsonConvert.SerializeObject(tree); } catch (Exception) { throw; } } private static List BuildAccountGroupTree(List nodes) { var lookup = nodes.ToDictionary(node => node.Id); var roots = new List(); foreach (var node in nodes) { var parentId = node.Parent?.Id; node.Parent = null; if (!parentId.HasValue || !lookup.TryGetValue(parentId.Value, out var parent)) { roots.Add(node); continue; } parent.children.Add(node); } return roots; } // ── Save (insert or update) ─────────────────────────────────────────── public async Task SaveAccountGroup(AccountGroupDTO dto, LoginDTO loginDTO) { if (dto == null) throw new ArgumentNullException(nameof(dto)); if (string.IsNullOrWhiteSpace(dto.AccountGroupCode)) throw new ArgumentException("Account group code is required."); if (string.IsNullOrWhiteSpace(dto.AccountGroupName)) throw new ArgumentException("Account group name is required."); if (dto.AccountGroupAccountScheduleId == 0 || dto.AccountGroupAccountScheduleId == -1) throw new ArgumentException("Account schedule is required."); var Trans = await _QueryExecutor.BeginTransactionAsync(loginDTO); try { bool isNew = dto.AccountGroupId == 0; if (isNew) { var auto = await _AutoNumber.GetNumberAsync(1, AUTONUMBERCONSTANT.ACCOUNTGROUP, loginDTO) .ConfigureAwait(false); dto.AccountGroupId = auto.StartNumber; } //var definitions = new List(); //var executors = new List(); //var engine = new QualifierEngine((IQualifierDefinitionLoader)definitions, executors); //var facade = new QualifierFacade(engine); //var baseSvc = new BaseEntityAppService( // ✅ correct generic // facade, _WorkFlowEngine, _OutBox, _QueryExecutor, _DaprClient); await _BaseEntityAppService.ExecuteSaveAsync( EntityConstant.OBJECTACCOUNTGROUP, EventTypeConstant.SAVEACCOUNTGROUPEVENTTYPEID, dto, // ✅ instance not type loginDTO, async tx => { if (isNew) await _AccountGroupDAL.SaveAccountGroup(dto, loginDTO, tx).ConfigureAwait(false); else await _AccountGroupDAL.UpdateAccountGroup(dto, loginDTO, tx).ConfigureAwait(false); return dto.AccountGroupId; }, null, -1, -1, Trans); await _QueryExecutor.CommitAsync(Trans); var cacheKey = CacheKeyGenerator.KeyGeneration( dto.AccountGroupId, // int ObjectId EntityConstant.OBJECTACCOUNT, // int ObjectTypeId CacheKeyLevel.CLIENT_LEVEL, // int CachingKeyLevel string.Empty, // string SourceData ← this was missing! loginDTO); // LoginDTO await _KeyInvalidate.AllInvalidateCache(cacheKey); return isNew ? SuccessResponse.SaveSuccess : SuccessResponse.UpdateSuccess; } catch (Exception) { await _QueryExecutor.RollbackAsync(Trans); throw; } } // ── Delete ──────────────────────────────────────────────────────────── public async Task DeleteAccountGroup(int accountGroupId, LoginDTO loginDTO) { var Trans = await _QueryExecutor.BeginTransactionAsync(loginDTO); try { //var definitions = new List(); //var executors = new List(); //var engine = new QualifierEngine((IQualifierDefinitionLoader)definitions, executors); //var facade = new QualifierFacade(engine); //var baseSvc = new BaseEntityAppService( // ✅ correct generic // facade, _WorkFlowEngine, _OutBox, _QueryExecutor, _DaprClient); await _BaseEntityAppService.ExecuteSaveAsync( EntityConstant.OBJECTACCOUNTGROUP, EventTypeConstant.DELETEACCOUNTGROUPEVENTTYPEID, new AccountGroupDTO { AccountGroupId = accountGroupId }, loginDTO, async tx => { await _AccountGroupDAL.DeleteAccountGroup(accountGroupId, loginDTO, tx) .ConfigureAwait(false); return accountGroupId; }, null, -1, -1, Trans); await _QueryExecutor.CommitAsync(Trans); var cacheKey = CacheKeyGenerator.KeyGeneration( accountGroupId, // ✅ int parameter from method signature EntityConstant.OBJECTACCOUNT, CacheKeyLevel.CLIENT_LEVEL, string.Empty, loginDTO); await _KeyInvalidate.AllInvalidateCache(cacheKey); return SuccessResponse.DeleteSuccessMessage; } catch (Exception) { await _QueryExecutor.RollbackAsync(Trans); throw; } } } }