-- ==================================================================== -- Fix GetProfileSalaryPosition to use calendar arithmetic -- This changes the years/months/days calculation from fixed formulas -- to actual calendar arithmetic, matching calculateGovAge behavior -- ==================================================================== DELIMITER $$ DROP PROCEDURE IF EXISTS `GetProfileSalaryPosition`$$ CREATE DEFINER=`root`@`%` PROCEDURE `GetProfileSalaryPosition`( IN personId VARCHAR(36), IN _date DATE ) BEGIN WITH ordered AS ( SELECT * FROM profileSalary WHERE profileId = personId AND commandCode IN ('0','1','2','3','4','8','9','10','11','12','13','14','15','16','20') ), work_session AS ( SELECT *, COALESCE( SUM(CASE WHEN commandCode IN (12,15,16) THEN 1 ELSE 0 END) OVER (ORDER BY commandDateAffect, commandDateSign ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING), 0) AS sessionId FROM ordered ), session_end AS ( SELECT sessionId, MAX(commandDateAffect) AS sessionEndDate FROM work_session GROUP BY sessionId ), position_change AS ( SELECT *, CASE WHEN LAG(positionName) OVER (ORDER BY commandDateAffect, commandDateSign) = positionName AND LAG(sessionId) OVER (ORDER BY commandDateAffect, commandDateSign) = sessionId THEN 0 ELSE 1 END AS isNewPosition FROM work_session ), position_group AS ( SELECT *, SUM(isNewPosition) OVER (ORDER BY commandDateAffect, commandDateSign) AS posGroup FROM position_change ), first_rows AS ( SELECT * FROM ( SELECT *, ROW_NUMBER() OVER (PARTITION BY posGroup ORDER BY commandDateAffect, commandDateSign) AS rnPos FROM position_group ) t WHERE rnPos = 1 ), rows_with_duration AS ( SELECT fr.*, LEAD(fr.sessionId) OVER (ORDER BY fr.commandDateAffect, fr.commandDateSign) AS nextSessionId, CASE WHEN LEAD(fr.commandDateAffect) OVER (ORDER BY fr.commandDateAffect, fr.commandDateSign) IS NULL THEN NULL WHEN LEAD(fr.sessionId) OVER (ORDER BY fr.commandDateAffect, fr.commandDateSign) <> fr.sessionId THEN TIMESTAMPDIFF(DAY, fr.commandDateAffect, se.sessionEndDate) + 1 ELSE TIMESTAMPDIFF(DAY, fr.commandDateAffect, LEAD(fr.commandDateAffect) OVER (ORDER BY fr.commandDateAffect, fr.commandDateSign)) END AS duration_days FROM first_rows fr LEFT JOIN session_end se ON se.sessionId = fr.sessionId ), resultWithDiff AS ( SELECT *, LAG(duration_days) OVER (ORDER BY commandDateAffect, commandDateSign) AS days_diff FROM rows_with_duration ) -- ✅ NEW: Use calendar arithmetic for years/months/days calculation SELECT r.commandDateAffect, r.positionName, r.positionCee, r.days_diff, CASE WHEN LAG(r.commandDateAffect) OVER (ORDER BY r.commandDateAffect, r.commandDateSign) IS NOT NULL THEN TIMESTAMPDIFF(YEAR, LAG(r.commandDateAffect) OVER (ORDER BY r.commandDateAffect, r.commandDateSign), r.commandDateAffect) ELSE 0 END AS Years, CASE WHEN LAG(r.commandDateAffect) OVER (ORDER BY r.commandDateAffect, r.commandDateSign) IS NOT NULL THEN TIMESTAMPDIFF(MONTH, LAG(r.commandDateAffect) OVER (ORDER BY r.commandDateAffect, r.commandDateSign), r.commandDateAffect) % 12 ELSE 0 END AS Months, CASE WHEN LAG(r.commandDateAffect) OVER (ORDER BY r.commandDateAffect, r.commandDateSign) IS NOT NULL THEN TIMESTAMPDIFF(DAY, DATE_ADD( DATE_ADD(LAG(r.commandDateAffect) OVER (ORDER BY r.commandDateAffect, r.commandDateSign), INTERVAL TIMESTAMPDIFF(YEAR, LAG(r.commandDateAffect) OVER (ORDER BY r.commandDateAffect, r.commandDateSign), r.commandDateAffect) YEAR), INTERVAL TIMESTAMPDIFF(MONTH, LAG(r.commandDateAffect) OVER (ORDER BY r.commandDateAffect, r.commandDateSign), r.commandDateAffect) % 12 MONTH), r.commandDateAffect) ELSE 0 END AS Days, r.posNo, r.positionExecutive, r.positionType, r.positionLevel, r.orgRoot, r.orgChild1, r.orgChild2, r.orgChild3, r.orgChild4, r.commandCode, r.commandName, r.commandNo, r.commandYear, r.remark FROM resultWithDiff r UNION ALL -- ✅ NEW: Use calendar arithmetic for the final row too SELECT _date, NULL, NULL, TIMESTAMPDIFF(DAY, MAX(commandDateAffect), _date) + 1, TIMESTAMPDIFF(YEAR, MAX(commandDateAffect), _date), TIMESTAMPDIFF(MONTH, MAX(commandDateAffect), _date) % 12, DATEDIFF(_date, DATE_ADD( DATE_ADD(MAX(commandDateAffect), INTERVAL TIMESTAMPDIFF(YEAR, MAX(commandDateAffect), _date) YEAR), INTERVAL TIMESTAMPDIFF(MONTH, MAX(commandDateAffect), _date) % 12 MONTH) ), NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,NULL FROM resultWithDiff; END$$ DELIMITER ; -- ==================================================================== -- Verification query (optional) -- ==================================================================== -- CALL GetProfileSalaryPosition('your-profile-id', '2024-06-14');