SET PATH *LIBL ; CREATE OR REPLACE FUNCTION RESTAPI.SFP_GET_OEE_TRENDS ( IN_PARM CLOB(2147483647) ) RETURNS CLOB(2147483647) LANGUAGE SQL SPECIFIC RESTAPI.SFP_GET_OEE_TRENDS NOT DETERMINISTIC MODIFIES SQL DATA CALLED ON NULL INPUT SET OPTION ALWBLK = *ALLREAD , ALWCPYDTA = *OPTIMIZE , COMMIT = *NONE , DECRESULT = (31, 31, 00) , DYNDFTCOL = *NO , DYNUSRPRF = *USER , SRTSEQ = *HEX BEGIN DECLARE ENV VARCHAR ( 20 ) DEFAULT '' ; DECLARE V_DAYS INTEGER DEFAULT 30 ; DECLARE V_PLANT VARCHAR ( 15 ) DEFAULT '' ; DECLARE V_DEPT VARCHAR ( 15 ) DEFAULT '' ; DECLARE V_WC VARCHAR ( 5 ) DEFAULT '' ; DECLARE V_SITE VARCHAR ( 3 ) DEFAULT '' ; DECLARE LL VARCHAR ( 1024 ) DEFAULT '' ; DECLARE V_IN_PARM CLOB ( 2 G ) DEFAULT '' ; -- Error handling variables DECLARE V_SQLSTATE CHAR ( 5 ) DEFAULT '00000' ; DECLARE V_SQLCODE INTEGER DEFAULT 0 ; DECLARE V_ERRMSG VARCHAR ( 500 ) DEFAULT '' ; DECLARE V_HTTP_STATUS INTEGER DEFAULT 200 ; DECLARE V_HAS_ERROR INTEGER DEFAULT 0 ; -- Continue handlers for error capture DECLARE CONTINUE HANDLER FOR SQLSTATE '22007' -- Invalid datetime BEGIN SET V_SQLSTATE = '22007' ; GET DIAGNOSTICS CONDITION 1 V_ERRMSG = MESSAGE_TEXT ; SET V_HTTP_STATUS = 400 ; SET V_HAS_ERROR = 1 ; END ; DECLARE CONTINUE HANDLER FOR SQLSTATE '22003' -- Numeric out of range BEGIN SET V_SQLSTATE = '22003' ; GET DIAGNOSTICS CONDITION 1 V_ERRMSG = MESSAGE_TEXT ; SET V_HTTP_STATUS = 400 ; SET V_HAS_ERROR = 1 ; END ; DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' -- No data found BEGIN SET V_SQLSTATE = '02000' ; SET V_ERRMSG = 'No data found for the specified criteria' ; SET V_HTTP_STATUS = 404 ; SET V_HAS_ERROR = 1 ; END ; DECLARE CONTINUE HANDLER FOR SQLSTATE '42501' -- Not authorized BEGIN SET V_SQLSTATE = '42501' ; GET DIAGNOSTICS CONDITION 1 V_ERRMSG = MESSAGE_TEXT ; SET V_HTTP_STATUS = 403 ; SET V_HAS_ERROR = 1 ; END ; DECLARE CONTINUE HANDLER FOR SQLSTATE '42704' -- Object not found BEGIN SET V_SQLSTATE = '42704' ; GET DIAGNOSTICS CONDITION 1 V_ERRMSG = MESSAGE_TEXT ; SET V_HTTP_STATUS = 404 ; SET V_HAS_ERROR = 1 ; END ; DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN GET DIAGNOSTICS CONDITION 1 V_SQLSTATE = RETURNED_SQLSTATE , V_SQLCODE = DB2_RETURNED_SQLCODE , V_ERRMSG = MESSAGE_TEXT ; SET V_HTTP_STATUS = 500 ; SET V_HAS_ERROR = 1 ; END ; -- Parse input parameters SET V_DAYS = COALESCE ( INT ( JSON_VALUE ( IN_PARM , '$.days' ) ) , 30 ) ; SET V_PLANT = COALESCE ( JSON_VALUE ( IN_PARM , '$.plant' ) , '' ) ; SET V_DEPT = COALESCE ( JSON_VALUE ( IN_PARM , '$.department' ) , '' ) ; SET V_WC = COALESCE ( JSON_VALUE ( IN_PARM , '$.workcenter' ) , '' ) ; SET V_SITE = COALESCE ( JSON_VALUE ( IN_PARM , '$.site' ) , '' ) ; -- Extract env handling all input formats (object, array, string) SET V_IN_PARM = IN_PARM ; WHILE CISTOOLS . JSON_TYPE ( V_IN_PARM ) IN ( 'object' , 'array' , 'string' ) DO SET V_IN_PARM = CASE CISTOOLS . JSON_TYPE ( V_IN_PARM ) WHEN 'object' THEN JSON_VALUE ( V_IN_PARM , '$.env' ) WHEN 'array' THEN JSON_VALUE ( V_IN_PARM , '$[0]' ) WHEN 'string' THEN REPLACE ( V_IN_PARM , '"' , '' ) ELSE TRIM ( V_IN_PARM ) END ; END WHILE ; SET ENV = V_IN_PARM ; SET LL = CISTOOLS . SET_LIBRARY_LIST ( ENV ) ; -- Validate environment was set IF ENV = '' OR ENV IS NULL THEN RETURN JSON_OBJECT ( 'error' : JSON_OBJECT ( 'http_status' : 400 , 'sqlstate' : '22001' , 'message' : 'Environment parameter is required' ) ) ; END IF ; -- Check for errors from library list setup IF V_HAS_ERROR = 1 THEN RETURN JSON_OBJECT ( 'error' : JSON_OBJECT ( 'http_status' : V_HTTP_STATUS , 'sqlstate' : V_SQLSTATE , 'message' : V_ERRMSG ) ) ; END IF ; RETURN WITH DATE_RANGE AS ( SELECT ( ZONED ( CURRENT_DATE - V_DAYS DAYS ) - 19000000 ) AS FROM_CY , ( ZONED ( CURRENT_DATE ) - 19000000 ) AS THRU_CY FROM SYSIBM . SYSDUMMY1 ) , -- Group by workcenter, site, and date from host file DAILY_WC_DATA AS ( SELECT TRIM ( P . KIWKCTR ) AS WKCTR , TRIM ( P . KISTID ) AS STID , TRIM ( P . KIGRP1 ) AS PLANT , TRIM ( P . KIGRP2 ) AS DEPT , P . KIDATE , SUM ( P . KIUP ) AS UP_SEC , SUM ( P . KIUDWN ) AS UDWN_SEC , SUM ( P . KIGAP ) AS GAP_SEC , SUM ( P . KIRCVD ) AS GOOD_QTY , SUM ( P . KISCRP ) AS BAD_QTY , SUM ( P . KIEXPT ) AS TARGET_QTY FROM SFCPERI P , DATE_RANGE R WHERE P . KIDATE BETWEEN R . FROM_CY AND R . THRU_CY AND TRIM ( P . KIGRP1 ) = COALESCE ( NULLIF ( V_PLANT , '' ) , TRIM ( P . KIGRP1 ) ) AND TRIM ( P . KIGRP2 ) = COALESCE ( NULLIF ( V_DEPT , '' ) , TRIM ( P . KIGRP2 ) ) AND TRIM ( P . KIWKCTR ) = COALESCE ( NULLIF ( V_WC , '' ) , TRIM ( P . KIWKCTR ) ) AND TRIM ( P . KISTID ) = COALESCE ( NULLIF ( V_SITE , '' ) , TRIM ( P . KISTID ) ) GROUP BY P . KIWKCTR , P . KISTID , P . KIGRP1 , P . KIGRP2 , P . KIDATE ) , DAILY_WC_OEE AS ( SELECT WKCTR , STID , PLANT , DEPT , KIDATE , DATE ( TIMESTAMP_FORMAT ( CHAR ( KIDATE + 19000000 ) , 'YYYYMMDD' ) ) AS OEE_DATE , INT ( ( COALESCE ( ( DECFLOAT ( UP_SEC - UDWN_SEC - GAP_SEC ) / NULLIF ( DECFLOAT ( UP_SEC ) , 0 ) ) , 0 ) * COALESCE ( ( DECFLOAT ( GOOD_QTY + BAD_QTY ) / NULLIF ( DECFLOAT ( TARGET_QTY ) , 0 ) ) , 0 ) * COALESCE ( ( DECFLOAT ( GOOD_QTY ) / NULLIF ( DECFLOAT ( GOOD_QTY + BAD_QTY ) , 0 ) ) , 0 ) * 100 ) + 0.5 ) AS OEE_PCT , INT ( ( COALESCE ( ( DECFLOAT ( UP_SEC - UDWN_SEC - GAP_SEC ) / NULLIF ( DECFLOAT ( UP_SEC ) , 0 ) ) , 0 ) * 100 ) + 0.5 ) AS AVAILABILITY_PCT , INT ( ( COALESCE ( ( DECFLOAT ( GOOD_QTY + BAD_QTY ) / NULLIF ( DECFLOAT ( TARGET_QTY ) , 0 ) ) , 0 ) * 100 ) + 0.5 ) AS PERFORMANCE_PCT , INT ( ( COALESCE ( ( DECFLOAT ( GOOD_QTY ) / NULLIF ( DECFLOAT ( GOOD_QTY + BAD_QTY ) , 0 ) ) , 0 ) * 100 ) + 0.5 ) AS QUALITY_PCT FROM DAILY_WC_DATA ) , -- Build daily trend JSON for each workcenter JSON_DAYS AS ( SELECT WKCTR , STID , PLANT , DEPT , JSON_OBJECT ( 'date' : TO_CHAR ( OEE_DATE , 'YYYY-MM-DD' ) , 'dayLabel' : TO_CHAR ( OEE_DATE , 'Dy' ) , 'oeePercentage' : OEE_PCT , 'availabilityPercentage' : AVAILABILITY_PCT , 'performancePercentage' : PERFORMANCE_PCT , 'qualityPercentage' : QUALITY_PCT ) AS DAY_OBJ , KIDATE FROM DAILY_WC_OEE ) , -- Aggregate trends by workcenter JSON_WORKCENTERS AS ( SELECT WKCTR , STID , PLANT , DEPT , JSON_OBJECT ( 'workcenter' : CAST ( WKCTR AS VARCHAR ( 5 ) CCSID 37 ) , 'site' : CAST ( STID AS VARCHAR ( 3 ) CCSID 37 ) , 'plant' : CAST ( PLANT AS VARCHAR ( 15 ) CCSID 37 ) , 'department' : CAST ( DEPT AS VARCHAR ( 15 ) CCSID 37 ) , 'trends' : JSON_ARRAYAGG ( DAY_OBJ FORMAT JSON ORDER BY KIDATE ) ) AS WC_OBJ FROM JSON_DAYS GROUP BY WKCTR , STID , PLANT , DEPT ORDER BY WKCTR , STID ) , -- Calculate overall daily totals for summary DAILY_TOTALS AS ( SELECT KIDATE , DATE ( TIMESTAMP_FORMAT ( CHAR ( KIDATE + 19000000 ) , 'YYYYMMDD' ) ) AS OEE_DATE , SUM ( UP_SEC ) AS UP_SEC , SUM ( UDWN_SEC ) AS UDWN_SEC , SUM ( GAP_SEC ) AS GAP_SEC , SUM ( GOOD_QTY ) AS GOOD_QTY , SUM ( BAD_QTY ) AS BAD_QTY , SUM ( TARGET_QTY ) AS TARGET_QTY FROM DAILY_WC_DATA GROUP BY KIDATE ) , DAILY_TOTAL_OEE AS ( SELECT KIDATE , OEE_DATE , INT ( ( COALESCE ( ( DECFLOAT ( UP_SEC - UDWN_SEC - GAP_SEC ) / NULLIF ( DECFLOAT ( UP_SEC ) , 0 ) ) , 0 ) * COALESCE ( ( DECFLOAT ( GOOD_QTY + BAD_QTY ) / NULLIF ( DECFLOAT ( TARGET_QTY ) , 0 ) ) , 0 ) * COALESCE ( ( DECFLOAT ( GOOD_QTY ) / NULLIF ( DECFLOAT ( GOOD_QTY + BAD_QTY ) , 0 ) ) , 0 ) * 100 ) + 0.5 ) AS OEE_PCT , INT ( ( COALESCE ( ( DECFLOAT ( UP_SEC - UDWN_SEC - GAP_SEC ) / NULLIF ( DECFLOAT ( UP_SEC ) , 0 ) ) , 0 ) * 100 ) + 0.5 ) AS AVAILABILITY_PCT , INT ( ( COALESCE ( ( DECFLOAT ( GOOD_QTY + BAD_QTY ) / NULLIF ( DECFLOAT ( TARGET_QTY ) , 0 ) ) , 0 ) * 100 ) + 0.5 ) AS PERFORMANCE_PCT , INT ( ( COALESCE ( ( DECFLOAT ( GOOD_QTY ) / NULLIF ( DECFLOAT ( GOOD_QTY + BAD_QTY ) , 0 ) ) , 0 ) * 100 ) + 0.5 ) AS QUALITY_PCT FROM DAILY_TOTALS ) , JSON_TOTAL_TRENDS AS ( SELECT JSON_OBJECT ( 'date' : TO_CHAR ( OEE_DATE , 'YYYY-MM-DD' ) , 'dayLabel' : TO_CHAR ( OEE_DATE , 'Dy' ) , 'oeePercentage' : OEE_PCT , 'availabilityPercentage' : AVAILABILITY_PCT , 'performancePercentage' : PERFORMANCE_PCT , 'qualityPercentage' : QUALITY_PCT ) AS DAY_OBJ , KIDATE FROM DAILY_TOTAL_OEE ) SELECT JSON_OBJECT ( 'workcenters' : ( SELECT JSON_ARRAYAGG ( WC_OBJ FORMAT JSON ) FROM JSON_WORKCENTERS ) FORMAT JSON , 'totals' : ( SELECT JSON_OBJECT ( 'trends' : JSON_ARRAYAGG ( DAY_OBJ FORMAT JSON ORDER BY KIDATE ) ) FROM JSON_TOTAL_TRENDS ) FORMAT JSON , 'periodDays' : V_DAYS , 'generatedAt' : TO_CHAR ( CURRENT_TIMESTAMP , 'YYYY-MM-DD HH24:MI:SS' ) ) FROM SYSIBM . SYSDUMMY1 ; END ; GRANT ALTER , EXECUTE ON SPECIFIC FUNCTION RESTAPI.SFP_GET_OEE_TRENDS TO AMAPICS WITH GRANT OPTION ; GRANT EXECUTE ON SPECIFIC FUNCTION RESTAPI.SFP_GET_OEE_TRENDS TO PUBLIC ;