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 ; 

