using System.Collections.Generic; using System.Data.Common; using System.Linq; using System.Threading; using System.Threading.Tasks; using FrameworkDAL.DTO.MenuGroup; using FrameworkDAL.Query.MenuGroup; using GB5Shared.DTO.Framework.Login; using GB5Shared.QueryExecutor; namespace FrameworkDAL.CustomCode.MenuGroup { public class MenuGroupDAL : IMenuGroupDAL { private readonly IQueryExecutor _queryExecutor; public MenuGroupDAL(IQueryExecutor queryExecutor) { _queryExecutor = queryExecutor; } public async Task GetMenuSetPresentationInfo(int menuSetId, LoginDTO loginDTO, CancellationToken ct) => await _queryExecutor.QuerySingleAsync( loginDTO, MenuGroupQB.GET_MENUSET_PRESENTATION_INFO, new { MenuSetId = menuSetId }, cancellationToken: ct) .ConfigureAwait(false); public async Task> GetMenuGroupFlatList(int menuSetId, LoginDTO loginDTO, CancellationToken ct) => (await _queryExecutor.QueryAsync( loginDTO, MenuGroupQB.GET_MENUGROUP_FLAT_LIST, new { MenuSetId = menuSetId }, cancellationToken: ct) .ConfigureAwait(false)).ToList(); public async Task GetMenuGroupById(int menuGroupId, LoginDTO loginDTO, CancellationToken ct) => await _queryExecutor.QuerySingleAsync( loginDTO, MenuGroupQB.GET_MENUGROUP_BY_ID, new { MenuGroupId = menuGroupId }, cancellationToken: ct) .ConfigureAwait(false); public async Task> GetResolvedLeavesByGroupIds( IEnumerable groupIds, int menuSetId, int? roleId, LoginDTO loginDTO, CancellationToken ct) { var ids = groupIds.ToList(); if (ids.Count == 0) return new List(); return (await _queryExecutor.QueryAsync( loginDTO, MenuGroupQB.GET_RESOLVED_LEAVES_BY_GROUPIDS, new { GroupIds = ids, MenuSetId = menuSetId, RoleId = roleId }, cancellationToken: ct) .ConfigureAwait(false)).ToList(); } public async Task GetMenuSetIdForModule(int clientId, int moduleId, LoginDTO loginDTO, CancellationToken ct) => await _queryExecutor.QuerySingleAsync( loginDTO, MenuGroupQB.GET_MENUSETID_FOR_MODULE, new { ClientId = clientId, ModuleId = moduleId }, cancellationToken: ct) .ConfigureAwait(false); public async Task SaveMenuGroup(MenuGroupDTO dto, LoginDTO loginDTO, DbTransaction tx, CancellationToken ct) => await _queryExecutor.ExecuteAsync(loginDTO, MenuGroupQB.INSERT_MENUGROUP, dto, tx, cancellationToken: ct) .ConfigureAwait(false); public async Task UpdateMenuGroup(MenuGroupDTO dto, LoginDTO loginDTO, DbTransaction tx, CancellationToken ct) => await _queryExecutor.ExecuteAsync(loginDTO, MenuGroupQB.UPDATE_MENUGROUP, dto, tx, cancellationToken: ct) .ConfigureAwait(false); public async Task DeleteMenuGroup(int menuGroupId, LoginDTO loginDTO, DbTransaction tx, CancellationToken ct) => await _queryExecutor.ExecuteAsync(loginDTO, MenuGroupQB.DELETE_MENUGROUP, new { MenuGroupId = menuGroupId }, tx, cancellationToken: ct) .ConfigureAwait(false); public async Task SaveMenuGroupDetail(int menuGroupId, IEnumerable leaves, LoginDTO loginDTO, CancellationToken ct) { // Unlike SkillProcessStageMapDAL.Save, an empty incoming list is NOT a no-op here — // it means "this group now has zero leaves," which must actually clear the group // (a legitimate admin action), not silently skip the delete. var leafList = leaves.ToList(); var statements = new List<(string sql, object param)>(); var survivingIds = leafList.Where(l => l.MenuGroupDetailId > 0).Select(l => l.MenuGroupDetailId).ToList(); statements.Add(survivingIds.Count > 0 ? (MenuGroupQB.DELETE_MENUGROUPDETAIL_NOT_IN, new { MenuGroupId = menuGroupId, SurvivingIds = survivingIds }) : (MenuGroupQB.DELETE_MENUGROUPDETAIL_BY_GROUP, new { MenuGroupId = menuGroupId })); foreach (var leaf in leafList) { leaf.MenuGroupId = menuGroupId; statements.Add(leaf.MenuGroupDetailId > 0 ? (MenuGroupQB.UPDATE_MENUGROUPDETAIL, (object)leaf) : (MenuGroupQB.INSERT_MENUGROUPDETAIL, (object)leaf)); } await _queryExecutor.ExecuteInTransactionAsync(loginDTO, statements).ConfigureAwait(false); } } }