CREATE OR REPLACE PROCEDURE public."Hr_S_PerformanceReviewAfterSave"( p_ReviewId uuid, p_UserId uuid, p_Actor varchar(16) ) LANGUAGE plpgsql AS $$ DECLARE v_Status varchar(16); v_Last varchar(16); v_EmployeeId uuid; v_ManagerId uuid; v_TenantId uuid; v_Valid boolean; BEGIN SELECT "Status", COALESCE("LastStatus", 'GoalSetting'), "EmployeeId", "ManagerId", "TenantId" INTO v_Status, v_Last, v_EmployeeId, v_ManagerId, v_TenantId FROM "Hr_T_PerformanceReview" WHERE "Id" = p_ReviewId AND "IsDeleted" = FALSE; IF v_Status IS NULL THEN RETURN; END IF; -- Elle açılan değerlendirmede organizasyon bilgisi çalışandan, yetkinlikler dönemin setinden gelir. -- Ad, pano kartının başlığı olduğu için kayıtta metin olarak tutulur. UPDATE "Hr_T_PerformanceReview" rv SET "EmployeeName" = LEFT(LTRIM(COALESCE(u."Name", '') || ' ' || COALESCE(u."Surname", '')), 128), "DepartmentId" = COALESCE(rv."DepartmentId", u."DepartmentId"), "JobPositionId" = COALESCE(rv."JobPositionId", u."JobPositionId") FROM "AbpUsers" u WHERE u."Id" = rv."EmployeeId" AND rv."Id" = p_ReviewId; INSERT INTO "Hr_T_PerformanceCompetency" ("Id", "TenantId", "ReviewId", "SkillId", "ExpectedLevelId", "IsActive", "CreationTime", "CreatorId", "IsDeleted") SELECT gen_random_uuid(), rv."TenantId", rv."Id", ps."SkillId", ps."ExpectedLevelId", TRUE, NOW() AT TIME ZONE 'UTC', p_UserId, FALSE FROM "Hr_T_PerformanceReview" rv INNER JOIN "Hr_T_PerformancePeriodSkill" ps ON ps."PeriodId" = rv."PeriodId" AND ps."IsDeleted" = FALSE AND ps."IsActive" = TRUE WHERE rv."Id" = p_ReviewId AND rv."Status" <> 'Completed' AND NOT EXISTS ( SELECT 1 FROM "Hr_T_PerformanceCompetency" c WHERE c."ReviewId" = rv."Id" AND c."SkillId" = ps."SkillId" AND c."IsDeleted" = FALSE); IF v_Status <> v_Last THEN -- İK her geçişi yapar; çalışan öz değerlendirmeyi gönderir; yönetici hedefleri onaylar, -- değerlendirmesini kalibrasyona gönderir ya da kaydı bir önceki aşamaya iade eder. v_Valid := CASE WHEN p_Actor = 'Hr' THEN TRUE WHEN p_Actor = 'Employee' AND v_Last = 'SelfReview' AND v_Status = 'ManagerReview' THEN TRUE WHEN p_Actor = 'Manager' AND v_Last = 'GoalSetting' AND v_Status = 'SelfReview' THEN TRUE WHEN p_Actor = 'Manager' AND v_Last = 'SelfReview' AND v_Status = 'GoalSetting' THEN TRUE WHEN p_Actor = 'Manager' AND v_Last = 'ManagerReview' AND v_Status IN ('SelfReview', 'Calibration') THEN TRUE ELSE FALSE END; -- Hedef belirleme ancak ağırlıkları toplamı 100 olan en az bir hedefle kapanır. IF v_Valid AND v_Last = 'GoalSetting' AND v_Status <> 'GoalSetting' AND NOT EXISTS ( SELECT 1 FROM "Hr_T_PerformanceGoal" g WHERE g."ReviewId" = p_ReviewId AND g."IsDeleted" = FALSE HAVING SUM(g."Weight") = 100) THEN v_Valid := FALSE; END IF; IF NOT v_Valid THEN UPDATE "Hr_T_PerformanceReview" SET "Status" = v_Last WHERE "Id" = p_ReviewId; v_Status := v_Last; ELSE UPDATE "Hr_T_PerformanceReview" SET "LastStatus" = v_Status, "SelfSubmittedDate" = CASE WHEN v_Status = 'ManagerReview' THEN NOW() AT TIME ZONE 'UTC' ELSE "SelfSubmittedDate" END, "ManagerSubmittedDate" = CASE WHEN v_Status = 'Calibration' THEN NOW() AT TIME ZONE 'UTC' ELSE "ManagerSubmittedDate" END, "CompletedDate" = CASE WHEN v_Status = 'Completed' THEN NOW() AT TIME ZONE 'UTC' ELSE NULL END WHERE "Id" = p_ReviewId; IF v_Status IN ('GoalSetting', 'SelfReview', 'Completed') THEN CALL public."Hr_S_PerformanceNotify"(p_ReviewId, v_EmployeeId, 'PerformansDurumDegisti', 'Hr.Performance.Notification.Status.Subject', 'Hr.Performance.Notification.Status.Message', p_UserId); END IF; IF v_Status IN ('ManagerReview', 'Completed') THEN CALL public."Hr_S_PerformanceNotify"(p_ReviewId, v_ManagerId, 'PerformansDurumDegisti', 'Hr.Performance.Notification.Status.Subject', 'Hr.Performance.Notification.Status.Message', p_UserId); END IF; -- Tamamlanan değerlendirmenin yönetici seviyeleri çalışanın yetkinlik profiline yazılır -- (Progress 0–100 → UserSkill.Level 1–5). IF v_Status = 'Completed' THEN UPDATE "Adm_T_UserSkill" us SET "Level" = x.lvl, "Note" = LEFT('Performans: ' || p."Name", 512), "LastModificationTime" = NOW() AT TIME ZONE 'UTC', "LastModifierId" = p_UserId FROM "Hr_T_PerformanceCompetency" c INNER JOIN "Hr_T_SkillLevel" l ON l."Id" = c."ManagerLevelId" INNER JOIN "Hr_T_PerformanceReview" rv ON rv."Id" = c."ReviewId" INNER JOIN "Hr_T_PerformancePeriod" p ON p."Id" = rv."PeriodId" CROSS JOIN LATERAL (SELECT CASE WHEN l."Progress" <= 20 THEN 1 WHEN l."Progress" >= 100 THEN 5 ELSE CAST(CEILING(l."Progress" / 20.0) AS integer) END AS lvl) x WHERE c."SkillId" = us."SkillId" AND c."ReviewId" = p_ReviewId AND c."IsDeleted" = FALSE AND us."UserId" = v_EmployeeId AND us."IsDeleted" = FALSE AND (us."TenantId" = v_TenantId OR (us."TenantId" IS NULL AND v_TenantId IS NULL)); INSERT INTO "Adm_T_UserSkill" ("Id", "TenantId", "UserId", "SkillId", "Level", "Note", "CreationTime", "CreatorId", "IsDeleted") SELECT gen_random_uuid(), v_TenantId, v_EmployeeId, c."SkillId", x.lvl, LEFT('Performans: ' || p."Name", 512), NOW() AT TIME ZONE 'UTC', p_UserId, FALSE FROM "Hr_T_PerformanceCompetency" c INNER JOIN "Hr_T_SkillLevel" l ON l."Id" = c."ManagerLevelId" INNER JOIN "Hr_T_PerformanceReview" rv ON rv."Id" = c."ReviewId" INNER JOIN "Hr_T_PerformancePeriod" p ON p."Id" = rv."PeriodId" CROSS JOIN LATERAL (SELECT CASE WHEN l."Progress" <= 20 THEN 1 WHEN l."Progress" >= 100 THEN 5 ELSE CAST(CEILING(l."Progress" / 20.0) AS integer) END AS lvl) x WHERE c."ReviewId" = p_ReviewId AND c."IsDeleted" = FALSE AND NOT EXISTS ( SELECT 1 FROM "Adm_T_UserSkill" us WHERE us."UserId" = v_EmployeeId AND us."SkillId" = c."SkillId" AND us."IsDeleted" = FALSE AND (us."TenantId" = v_TenantId OR (us."TenantId" IS NULL AND v_TenantId IS NULL))); END IF; END IF; END IF; CALL public."Hr_S_PerformanceReviewRecalc"(p_ReviewId); END $$;