using GB5Shared.DTO.Framework.Login; using GB5Shared.QueryExecutor; using PERMDAL.DTOs; using PERMDAL.Interfaces; using PERMDAL.QueryBuilders; namespace PERMDAL.Implementations; public class FinalizeAppraisalDAL : IFinalizeAppraisalDAL { private readonly IQueryExecutor _qe; public FinalizeAppraisalDAL(IQueryExecutor queryExecutor) => _qe = queryExecutor; public async Task ActivePIPExistsAsync(int employeeId, LoginDTO login, CancellationToken ct) { int count = await _qe.ExecuteScalarAsync(login, PIPQB.EXISTS_ACTIVE_PIP, new { EmployeeId = employeeId, TenantId = login.ClientId }, cancellationToken: ct) .ConfigureAwait(false); return count > 0; } public async Task FinalizeAppraisalTransactionAsync(FinalizeDataDTO data, LoginDTO login, CancellationToken ct) { await using var tx = await _qe.BeginTransactionAsync(login).ConfigureAwait(false); try { // 1. Update appraisal scores + finalize status await _qe.ExecuteAsync(login, AppraisalQB.FINALIZE_SCORES, new { data.AppraisalId, data.OverallMeasureScore, data.OverallGoalScore, data.FinalPercentage, TenantId = login.ClientId, ModifiedBy = login.UserId }, tx, ct).ConfigureAwait(false); // 2. Auto-create PIP if flagged if (data.ShouldCreatePIP) { await _qe.ExecuteScalarAsync(login, PIPQB.INSERT_PIPPLAN, new { data.AppraisalId, data.EmployeeId, ManagerId = data.ManagerId, EndDate = data.PIPEndDate, Reason = data.PIPReason, TenantId = login.ClientId, CreatedBy = login.UserId }, cancellationToken: ct).ConfigureAwait(false); } // 3. Insert TNA requests for each gap KRA foreach (var tna in data.TNAItems ?? Enumerable.Empty()) { await _qe.ExecuteAsync(login, TNAQB.INSERT_TNAREQUEST, new { data.AppraisalId, data.EmployeeId, tna.KRAId, tna.GapScore, TenantId = login.ClientId, CreatedBy = login.UserId }, tx, ct).ConfigureAwait(false); } await tx.CommitAsync(ct).ConfigureAwait(false); } catch { await tx.RollbackAsync(ct).ConfigureAwait(false); throw; } } }