using GB5Shared.DTO.Framework.AutoNumber; using GB5Shared.DTO.Framework.Criteria; using GB5Shared.DTO.Framework.Login; using GB5Shared.GenerateAutoNumber; using GB5Shared.Resource.Response; using GB5Shared.Validation; using MaintenanceDAL.CustomCode.Activity; using MaintenanceDAL.DTO.Activity; using MaintenanceDAL.DTO.ActivityType; namespace MaintenanceBLL.Activity { public class ActivityBLL : IActivityBLL { private readonly IActivityDAL _activityDAL; private readonly AutoNumber _autoNumber; private readonly IValidation _validation; public ActivityBLL(IActivityDAL activityDAL, AutoNumber autoNumber, IValidation validation) { _activityDAL = activityDAL; _autoNumber = autoNumber; _validation = validation; } // Activity-only success messages. Edit the wording HERE to change the Activity response text // without touching the shared GB5Shared SuccessResponse resource (which every module uses). private const string ActivitySaveSuccessMessage = "Details have been saved successfully with Code ="; private const string ActivityUpdateSuccessMessage = "Details have been updated successfully with Code ="; private const string ActivityDeleteSuccessMessage = "Activity deleted successfully."; private const string ActivityDeleteNotFoundMessage = "Activity not found or already deleted."; public async Task GetActivity(int activityId, LoginDTO loginDTO) { try { return await _activityDAL.GetActivity(activityId, loginDTO); } catch (Exception) { throw; } } public async Task GetSelectListActivity(CriteriaDTO criteriaDTO, LoginDTO loginDTO) { try { return await _activityDAL.GetSelectListActivity(criteriaDTO, loginDTO); } catch (Exception) { throw; } } public async Task SaveActivity(ActivityDTO activityDTO, LoginDTO loginDTO) { if(activityDTO == null) { throw new ArgumentNullException(nameof(activityDTO)); } // Field-level validation — surfaces " cannot be empty or whitespace." in the response. await _validation.NotEmpty(activityDTO.ActivityCode, nameof(activityDTO.ActivityCode)); await _validation.NotEmpty(activityDTO.ActivityName, nameof(activityDTO.ActivityName)); AutoNumberDTO? autoNumberDTO = null; activityDTO.ActivityModifiedById = loginDTO.UserId; activityDTO.ActivityModifiedOn = DateTime.UtcNow; bool IsNewData = activityDTO.ActivityId == 0; var count = 1; if(IsNewData) { try { autoNumberDTO = await _autoNumber.GetAutoNumber(count, "ACTIVITY", loginDTO); activityDTO.ActivityId = autoNumberDTO.StartNumber; activityDTO.ActivityCreatedById = loginDTO.UserId; activityDTO.ActivityCreatedOn = DateTime.UtcNow; await _activityDAL.SaveActivity(activityDTO, loginDTO); return $"{ActivitySaveSuccessMessage} {activityDTO.ActivityCode}"; } catch { // Roll back the allocated ACTIVITY number so a failed insert doesn't burn a code. // (IDs are negative here, so guard only on whether a number was actually allocated.) if (autoNumberDTO != null) await _autoNumber.RollbackAutoNumber("ACTIVITY", autoNumberDTO.StartNumber, loginDTO); throw; } } else { await _activityDAL.UpdateActivity(activityDTO, loginDTO); return $"{ActivityUpdateSuccessMessage} {activityDTO.ActivityCode}"; } } public async Task DeleteActivity(int activityId, LoginDTO loginDTO) { // 0 is the "new record" sentinel; GB5 AutoNumber issues negative PKs, which are valid. if (activityId == 0) { throw new ArgumentException("Invalid Activity Id."); } int rows = await _activityDAL.DeleteActivity(activityId, loginDTO); return rows > 0 ? ActivityDeleteSuccessMessage : ActivityDeleteNotFoundMessage; } } }