using GB5Shared.DTO.Framework.Login; using GB5Shared.EventLogPublish; using GB5Shared.Telemetry; using Microsoft.Extensions.Logging; using PERMBLL.Interfaces; using PERMDAL.DTOs; using PERMDAL.Interfaces; using System.Text.Json; using static GB5Shared.GB5Constant.Constant; namespace PERMBLL.Implementations; public class PIPBLL : IIPBLL { private readonly IPIPDAL _dal; private readonly EventLogPublish _eventLog; private readonly ILogger _logger; public PIPBLL(IPIPDAL dal, EventLogPublish eventLog, ILogger logger) { _dal = dal; _eventLog = eventLog; _logger = logger; } public async Task GetPIPPlanAsync(int pipPlanId, LoginDTO login, CancellationToken ct) { try { GB5Trace.Step("get-pipplan", new { pipPlanId }); var plan = await _dal.GetPIPPlanAsync(pipPlanId, login, ct).ConfigureAwait(false); if (plan is not null) plan.Actions = (await _dal.GetActionsByPlanAsync(pipPlanId, login, ct).ConfigureAwait(false)).ToList(); return JsonSerializer.Serialize(plan); } catch (Exception ex) { GB5Trace.MarkFailed("get-pipplan-failed", ex); _logger.LogError(ex, "GetPIPPlan failed for PIPPlanId {PIPPlanId}", pipPlanId); throw; } } public async Task GetPIPListAsync(int employeeId, short? status, int page, int pageSize, LoginDTO login, CancellationToken ct) { try { GB5Trace.Step("get-piplist", new { employeeId, status, page }); var list = await _dal.GetPIPListAsync(employeeId, status, page, pageSize, login, ct).ConfigureAwait(false); return JsonSerializer.Serialize(list); } catch (Exception ex) { GB5Trace.MarkFailed("get-piplist-failed", ex); _logger.LogError(ex, "GetPIPList failed"); throw; } } public async Task SavePIPPlanAsync(PIPPlanDTO dto, LoginDTO login, CancellationToken ct) { try { GB5Trace.Step("save-pipplan", new { dto.PIPPlanId, dto.EmployeeId }); var isNew = dto.PIPPlanId == 0; int savedId; if (isNew) { dto.TenantId = login.ClientId; dto.ManagerId = dto.ManagerId == 0 ? login.UserId : dto.ManagerId; savedId = await _dal.InsertPIPPlanAsync(dto, login, ct).ConfigureAwait(false); } else { await _dal.UpdatePIPPlanAsync(dto, login, ct).ConfigureAwait(false); savedId = dto.PIPPlanId; } GB5Trace.Step("event-publish", new { EventTypeId = EventTypeConstant.SAVEPERMPIPEVENTTYPEID }); await _eventLog.PublishEventLogAsync( isNew ? "PIP Plan Created" : "PIP Plan Updated", new { PIPPlanId = savedId, dto.EmployeeId }, EventTypeConstant.SAVEPERMPIPEVENTTYPEID, savedId, login, ct: ct).ConfigureAwait(false); return isNew ? $"{GB5Shared.Resource.Response.SuccessResponse.SaveSuccessMessage} {savedId}" : GB5Shared.Resource.Response.SuccessResponse.UpdateSuccess; } catch (Exception ex) { GB5Trace.MarkFailed("save-pipplan-failed", ex); _logger.LogError(ex, "SavePIPPlan failed for EmployeeId {EmployeeId}", dto.EmployeeId); throw; } } public async Task ActivatePIPPlanAsync(int pipPlanId, LoginDTO login, CancellationToken ct) { try { GB5Trace.Step("activate-pipplan", new { pipPlanId }); int rows = await _dal.ActivatePIPPlanAsync(pipPlanId, login, ct).ConfigureAwait(false); if (rows == 0) return "PIP plan not found or not in Draft status."; return GB5Shared.Resource.Response.SuccessResponse.UpdateSuccess; } catch (Exception ex) { GB5Trace.MarkFailed("activate-pipplan-failed", ex); _logger.LogError(ex, "ActivatePIPPlan failed for PIPPlanId {PIPPlanId}", pipPlanId); throw; } } public async Task ClosePIPPlanAsync(int pipPlanId, LoginDTO login, CancellationToken ct) { try { GB5Trace.Step("close-pipplan", new { pipPlanId }); int rows = await _dal.ClosePIPPlanAsync(pipPlanId, login, ct).ConfigureAwait(false); if (rows == 0) return "PIP plan not found or not in Active status."; GB5Trace.Step("event-publish", new { EventTypeId = EventTypeConstant.CLOSEPERMPIPEVENTTYPEID }); await _eventLog.PublishEventLogAsync( "PIP Plan Closed", new { PIPPlanId = pipPlanId }, EventTypeConstant.CLOSEPERMPIPEVENTTYPEID, pipPlanId, login, ct: ct).ConfigureAwait(false); return GB5Shared.Resource.Response.SuccessResponse.UpdateSuccess; } catch (Exception ex) { GB5Trace.MarkFailed("close-pipplan-failed", ex); _logger.LogError(ex, "ClosePIPPlan failed for PIPPlanId {PIPPlanId}", pipPlanId); throw; } } public async Task SavePIPActionAsync(PIPActionDTO dto, LoginDTO login, CancellationToken ct) { try { GB5Trace.Step("save-pipaction", new { dto.PIPActionId, dto.PIPPlanId }); var isNew = dto.PIPActionId == 0; int savedId; if (isNew) { dto.TenantId = login.ClientId; savedId = await _dal.InsertActionAsync(dto, login, ct).ConfigureAwait(false); } else { await _dal.UpdateActionAsync(dto, login, ct).ConfigureAwait(false); savedId = dto.PIPActionId; } return isNew ? $"{GB5Shared.Resource.Response.SuccessResponse.SaveSuccessMessage} {savedId}" : GB5Shared.Resource.Response.SuccessResponse.UpdateSuccess; } catch (Exception ex) { GB5Trace.MarkFailed("save-pipaction-failed", ex); _logger.LogError(ex, "SavePIPAction failed for PIPPlanId {PIPPlanId}", dto.PIPPlanId); throw; } } public async Task CompleteActionAsync(int pipActionId, LoginDTO login, CancellationToken ct) { try { GB5Trace.Step("complete-pipaction", new { pipActionId }); int rows = await _dal.CompleteActionAsync(pipActionId, login, ct).ConfigureAwait(false); if (rows == 0) return "Action not found or already completed."; return GB5Shared.Resource.Response.SuccessResponse.UpdateSuccess; } catch (Exception ex) { GB5Trace.MarkFailed("complete-pipaction-failed", ex); _logger.LogError(ex, "CompleteAction failed for PIPActionId {PIPActionId}", pipActionId); throw; } } }