using FrameworkDAL.CustomCode.Module; using FrameworkDAL.DTO.Project; using GB5Shared.QueryExecutor; using GB5Shared.DTO.Framework.Criteria; using GB5Shared.DTO.Framework.Login; using GB5Shared.EntityHandler; using GB5Shared.GenerateAutoNumber; using GB5Shared.ResponseStandard; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using static GB5Shared.GB5Constant.Constant; namespace FrameworkBLL.Module { public class ModuleBLL : IModuleBLL { private readonly IModuleDAL _ModuleDAL; private readonly IQueryExecutor _queryExecutor; private readonly AutoNumber _autoNumber; private readonly BaseEntityAppService _baseEntityAppService; public ModuleBLL(IModuleDAL ModuleDAL, IQueryExecutor queryExecutor, AutoNumber autoNumber, BaseEntityAppService baseEntityAppService) { _ModuleDAL = ModuleDAL; _queryExecutor = queryExecutor; _autoNumber = autoNumber; _baseEntityAppService = baseEntityAppService; } public async Task GetModuleList(LoginDTO LoginDTO, string? module = null) { try { return await _ModuleDAL.GetModuleList(LoginDTO, module); } catch (Exception) { throw; } finally { } } public async Task GetSelectListModule(CriteriaDTO criteriaDTO, LoginDTO loginDTO) { try { return await _ModuleDAL.GetSelectListModule(criteriaDTO, loginDTO); } catch (Exception) { throw; } } public async Task GetModule(int ModuleId, LoginDTO LoginDTO) { try { return await _ModuleDAL.GetModule(ModuleId, LoginDTO); } catch (Exception) { throw; } } // Create-only. Confirmed live against USCIMPSYS (2026-07-24): MAUTONUMBER already has a // real, actively-consumed 'MODULE' row, and every recently-created MMODULE row (GBSTUDIO, // CMS, HELPDESK, FOUNDRY, DMS, ...) sits in that same sequential counter range — modules // DO get created via autonumber in the real system. A handful of legacy/system modules // (ADMIN at -1900000000, FRAMEWORK at -2147483637, etc.) carry older, hand-picked fixed // IDs from before this convention — so an explicit non-zero ModuleId is still honored if // the caller supplies one (e.g. re-seeding a known legacy module), but ModuleId == 0 // autonumbers via AUTONUMBERCONSTANT.MODULE, mirroring RoleBLL.SaveRole exactly. public async Task SaveModule(ModuleDTO moduleDto, LoginDTO login) { if (moduleDto.ModuleId == 0) { var auto = await _autoNumber.GetNumberAsync(1, AUTONUMBERCONSTANT.MODULE, login); moduleDto.ModuleId = auto.StartNumber; } var transaction = await _queryExecutor.BeginTransactionAsync(login); try { await _baseEntityAppService.ExecuteSaveAsync( EntityConstant.OBJECTMODULE, EventTypeConstant.SAVEMODULEEVENTTYPEID, moduleDto, login, async tx => { await _ModuleDAL.SaveModule(moduleDto, login, tx); return moduleDto.ModuleId; }, null, -1, -1, transaction); await _queryExecutor.CommitAsync(transaction); return "Details saved successfully."; } catch (Exception) { await _queryExecutor.RollbackAsync(transaction); throw; } } public async Task UpdateModule(ModuleDTO moduleDto, LoginDTO login) { if (moduleDto.ModuleId == 0) throw new ArgumentException("ModuleId is required.", nameof(moduleDto)); var transaction = await _queryExecutor.BeginTransactionAsync(login); try { await _baseEntityAppService.ExecuteSaveAsync( EntityConstant.OBJECTMODULE, EventTypeConstant.SAVEMODULEEVENTTYPEID, moduleDto, login, async tx => { await _ModuleDAL.UpdateModule(moduleDto, login, tx); return moduleDto.ModuleId; }, null, -1, -1, transaction); await _queryExecutor.CommitAsync(transaction); return "Details updated successfully."; } catch (Exception) { await _queryExecutor.RollbackAsync(transaction); throw; } } public async Task> DeleteModule(int ModuleId, LoginDTO LoginDTO) { try { return await _ModuleDAL.DeleteModule(ModuleId, LoginDTO); } catch (Exception) { throw; } } } }