SET DEFINE OFF

DROP FUNCTION FN_TF_LOAN_INT_INFO;
DROP TYPE TFT_LOAN_INT_INFO;
DROP TYPE TFO_LOAN_INT_INFO;

CREATE TYPE TFO_LOAN_INT_INFO AS OBJECT 
(
	ACCT_PRD_ARG CHAR(6),
	ACCT_PRD_DATA CHAR(6),
	PRD_CODE__FR CHAR(6),
	PRD_CODE__TO CHAR(6),
	EMP_CODE CHAR(10),
	EMP_FULL_NAME VARCHAR2(120),
	PAY_SITE CHAR(5),
	FIN_ENTITY CHAR(10),
	CCTR_CODE__SAL CHAR(4),
	LOAN_NO CHAR(15),
	SCHEME_NO CHAR(10),
	SCHEME_TYPE CHAR(5),
	LOAN_AMT NUMBER(12,3),
	TERM NUMBER(3),
	INT_TERM CHAR(5),
	ISSUE_DATE DATE,
	LOAN_DISB_DATE DATE,
	LOAN_START_RECO_DATE DATE,
	LOAN_CLOUSRE_DATE DATE,
	MON_INST NUMBER(12,3),
	PRE_PAID_EMP_BENIFIT NUMBER(12,3),
	INTEREST NUMBER(6,2),
	ISA_EFF_INT_RATE NUMBER(6,2),
	APPR_DATE DATE,
	BALANCE_AMT NUMBER(12,3),
	DATE__BALANCE DATE,
	DATE__INTEREST DATE,
	LOAN_TYPE CHAR(1),
	EMI_NO NUMBER(10),
	EMI_PRD_CODE CHAR(6),
	EMI_PRD_DESCR VARCHAR2(10),
	OP_BALANCE_AMT NUMBER(12,3),
	INTEREST_AMT NUMBER(12,3),
	PRINC_CUM_INTEREST_AMT NUMBER(12,3),
	MON_DEDN NUMBER(12,3),
	RECOVER_AMT NUMBER(12,3),
	CL_BALANCE_AMT NUMBER(12,3),
	PRINC_DEDN NUMBER(12,3),
	PV_FACTOR NUMBER(10,4),
	PRESENT_VALUE NUMBER(12,3),
	AMORTISED_COST_OP_BAL NUMBER(12,3),
	INTEREST_AT_EFF_RATE NUMBER(12,3),
	REPAYMENT_INCL_INTEREST NUMBER(12,3),
	AMORTISED_COST_CL_BAL NUMBER(12,3),
	EMP_BENEFIT NUMBER(12,3),
	DIFF_PRINC_DEDN NUMBER(12,3),
	LOAN_INT_CALC_STR VARCHAR2(4000),
	REPAYMENT_INCL_INTEREST_1 NUMBER(12,3)
)
/
CREATE TYPE TFT_LOAN_INT_INFO AS TABLE OF TFO_LOAN_INT_INFO
/

CREATE OR REPLACE
FUNCTION FN_TF_LOAN_INT_INFO
	(
		FIN_ENTITY_CODE_FR FINENT.FIN_ENTITY%TYPE,
		FIN_ENTITY_CODE_TO FINENT.FIN_ENTITY%TYPE,
		ACCT_PRD ACCTPRD.CODE%TYPE,
		PRD_CODE__FR PERIOD.CODE%TYPE,
		PRD_CODE__TO PERIOD.CODE%TYPE,
		SITE_CODE__FR SITE.SITE_CODE%TYPE,
		SITE_CODE__TO SITE.SITE_CODE%TYPE,
		CCTR_CODE__FR EMPLOYEE.CCTR_CODE__SAL%TYPE,
		CCTR_CODE__TO EMPLOYEE.CCTR_CODE__SAL%TYPE,
		EMP_CODE__FR EMPLOYEE.EMP_CODE%TYPE, 
		EMP_CODE__TO EMPLOYEE.EMP_CODE%TYPE,
		EFF_INT_RATE LOANS.INTEREST%TYPE
	)
RETURN TFT_LOAN_INT_INFO 
PIPELINED IS 
OUT_REC TFO_LOAN_INT_INFO := TFO_LOAN_INT_INFO(	NULL,NULL,NULL,NULL,NULL,NULL,NULL,
		NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
		NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
		NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);

LI_CNT NUMBER(6);
LI_CNT1 NUMBER(6);
LI_CNT2 NUMBER(6);
EMI_NO NUMBER(6);
TOT_INST_DEDN NUMBER(6);
TOT_INST_NO NUMBER(6);
LC_LOAN_OP_BAL LOANS.LOAN_AMT%TYPE;
LC_LOAN_RECO LOANS.LOAN_AMT%TYPE;
LD_LOAN_CLOUSRE_DATE DATE;
LD_INT_FIRST_DATE DATE;
LD_INT_LAST_DATE DATE;
EMI_PRD_CODE PERIOD.CODE%TYPE;
EMI_PRD_DESCR PERIOD.DESCR%TYPE;
PV_FACTOR NUMBER(12,4);
PRESENT_VALUE LOANS.LOAN_AMT%TYPE;
TOT_PRESENT_VALUE LOANS.LOAN_AMT%TYPE;
AMORTISED_COST_OP_BAL LOANS.LOAN_AMT%TYPE;
INTEREST_AT_EFF_RATE LOANS.LOAN_AMT%TYPE;
AMORTISED_COST_CL_BAL LOANS.LOAN_AMT%TYPE;
EMP_BENEFIT LOANS.LOAN_AMT%TYPE;
DIFF_PRINC_DEDN LOANS.LOAN_AMT%TYPE;
LC_PRINC_DEDN LOANS.LOAN_AMT%TYPE;
LC_INT_DEDN LOANS.LOAN_AMT%TYPE;
LC_OTH_RECOVERY LOANS.LOAN_AMT%TYPE;
LC_EFF_INT_RATE LOANS.INTEREST%TYPE;
LS_EXCLUDE_SCHEME_TYPE VARCHAR2(1024);
LOAN_INT_CALC_STR VARCHAR2(4000);
ARG_ACCT_PRD_CODE ACCTPRD.CODE%TYPE;
LD_CAL_FDATE ACCTPRD.FR_DATE%TYPE;
LD_CAL_TDATE ACCTPRD.TO_DATE%TYPE;
LI_NO_DAYS_IN_CAL_YR NUMBER(3);

CURSOR LOAN_INFO(AS_EXCLUDE_SCHEME_TYPE VARCHAR2) IS 
	SELECT 
	LN.EMP_CODE AS EMP_CODE ,
	TRIM(EM.EMP_FNAME) || ' ' || TRIM(EM.EMP_MNAME) || TRIM(EM.EMP_LNAME) AS EMP_FULL_NAME,
	EM.PAY_SITE AS PAY_SITE,
	EM.CCTR_CODE__SAL AS CCTR_CODE__SAL,
	LN.LOAN_NO AS LOAN_NO,
	LN.SCHEME_NO SCHEME_NO,
	LN.ISSUE_DATE AS ISSUE_DATE,
	LN.START_RECO AS START_RECO,
	LN.TERM AS TERM,
	LN.LOAN_AMT AS LOAN_AMT,
	LN.INTEREST AS INTEREST,
	LN.MON_INST AS MON_INST,
	LN.INT_TERM AS INT_TERM,
	LN.INTEREST_AMT AS INTEREST_AMT,
	LN.RECOVER_AMT AS RECOVER_AMT,
	LN.APPR_DATE AS APPR_DATE,
	LN.BALANCE_AMT AS BALANCE_AMT,
	LN.DATE__BALANCE AS DATE__BALANCE,
	LN.DATE__INTEREST AS DATE__INTEREST,
	LN.LOAN_TYPE AS LOAN_TYPE,
	LN.ACT_TERM AS ACT_TERM,
	AP.FR_DATE AS FY_FROM_DATE,
	AP.TO_DATE AS FY_TO_DATE,
	LS.AD_CODE__INT AS AD_CODE__INT,
	LS.AD_CODE__DED AS AD_CODE__DED,
	LS.SCHEME_TYPE AS SCHEME_TYPE,
	SM.FIN_ENTITY AS FIN_ENTITY
	FROM LOANS LN, EMPLOYEE EM, SITE SM, ACCTPRD AP, LOAN_SCHEME LS 
	WHERE EM.EMP_CODE = LN.EMP_CODE 
	AND LN.EMP_CODE >= EMP_CODE__FR 
	AND LN.EMP_CODE <= EMP_CODE__TO 
	AND EM.PAY_SITE >= SITE_CODE__FR 
	AND EM.PAY_SITE <= SITE_CODE__TO 
	AND SM.SITE_CODE = EM.PAY_SITE 
	--AND SM.FIN_ENTITY = FIN_ENTITY_CODE_FR 
	AND SM.FIN_ENTITY BETWEEN FIN_ENTITY_CODE_FR AND FIN_ENTITY_CODE_TO 
	AND LN.ISSUE_DATE <= AP.TO_DATE 
	AND AP.CODE = ACCT_PRD 
	AND LN.STATUS IN ('A','E')
	AND LS.SCHEME_NO = LN.SCHEME_NO 
	--AND LS.SCHEME_TYPE NOT IN ('A','B') 
	-- AND LS.SCHEME_TYPE NOT IN (AS_EXCLUDE_SCHEME_TYPE) 
	AND LS.SCHEME_TYPE NOT IN ( SELECT regexp_substr(AS_EXCLUDE_SCHEME_TYPE, '[^,]+', 1, LEVEL) 
		token FROM dual CONNECT BY LEVEL <= length(AS_EXCLUDE_SCHEME_TYPE) - 
			length(REPLACE(AS_EXCLUDE_SCHEME_TYPE, ',', '')) + 1) 
	ORDER BY SM.FIN_ENTITY,LN.EMP_CODE,LN.ISSUE_DATE;

CURSOR PRD_INFO(START_DATE DATE) IS SELECT A.CODE,A.FR_DATE,A.TO_DATE,
	A.ACCT_PRD AS P_ACCT_PRD,B.FR_DATE AS FY_FROM_DATE,B.TO_DATE AS FY_TO_DATE 
	FROM PERIOD A,ACCTPRD B
	WHERE B.CODE = A.ACCT_PRD AND A.TO_DATE >= START_DATE ORDER BY TO_DATE;

CURSOR LOAN_INST_INFO(ARG_LOAN_NO CHAR) IS SELECT * FROM LOANS_SCHEDULE 
	WHERE LOAN_NO = ARG_LOAN_NO  
	AND (NO_INST <> NO_INST_DED OR (NO_INST IS NULL AND PRD_CODE IS NULL)) ORDER BY LINE_NO ;

CURSOR LOAN_RECO_INFO(ARG_LOAN_NO CHAR , ARG_FR_DATE DATE , ARG_TO_DATE DATE) 
	IS SELECT * FROM LOAN_REG WHERE LOAN_NO = ARG_LOAN_NO 
	AND TRAN_DATE BETWEEN ARG_FR_DATE AND ARG_TO_DATE 
	AND AMOUNT <> 0 AND TRAN_TYPE NOT IN ('P') AND 
	CASE WHEN INT_CALCULATED IS NULL THEN 'N' ELSE INT_CALCULATED END = 'N' 
	ORDER BY TRAN_DATE;

CURSOR LOAN_INT_CALC_INFO(ARG_LOAN_NO CHAR , ARG_PRD_CODE CHAR) 
	IS SELECT * FROM LOANS_INTEREST_DET WHERE LOAN_NO = ARG_LOAN_NO 
	AND PRD_CODE = ARG_PRD_CODE ORDER BY PRD_CODE,LINE_NO;

BEGIN
	ARG_ACCT_PRD_CODE := ACCT_PRD;
	LI_CNT2 := 0;
	SELECT COUNT(1) INTO LI_CNT2 FROM PERIOD WHERE CODE BETWEEN PRD_CODE__FR AND PRD_CODE__TO 
		AND ACCT_PRD = ARG_ACCT_PRD_CODE;
	IF LI_CNT2 = 0 THEN
		RETURN;
	END IF;
	LI_CNT2 := 0;
	SELECT COUNT(1) INTO LI_CNT2 FROM PAYRPARM 
		WHERE PRD_CODE = '999999' AND VAR_NAME = 'IAS_LNREPO_EXCL_SCHM';
	IF LI_CNT2 > 0 THEN
		SELECT TRIM(VAR_VALUE) INTO LS_EXCLUDE_SCHEME_TYPE FROM PAYRPARM 
			WHERE PRD_CODE = '999999' AND VAR_NAME = 'IAS_LNREPO_EXCL_SCHM';
	ELSE
		LS_EXCLUDE_SCHEME_TYPE := '';
	END IF;
	IF LS_EXCLUDE_SCHEME_TYPE IS NULL OR LENGTH(TRIM(LS_EXCLUDE_SCHEME_TYPE)) = 0 THEN
		LS_EXCLUDE_SCHEME_TYPE := '**********';
	END IF;
	DBMS_OUTPUT.PUT_LINE(LS_EXCLUDE_SCHEME_TYPE);
	LI_CNT2 := 0;
	FOR I IN LOAN_INFO(LS_EXCLUDE_SCHEME_TYPE)
	LOOP
		LI_CNT2 := LI_CNT2 + 1;
		LI_CNT := 0;
		LC_LOAN_OP_BAL := I.LOAN_AMT;
		SELECT SUM(AMOUNT) INTO LC_LOAN_RECO FROM LOAN_REG WHERE LOAN_NO = I.LOAN_NO 
		AND TRAN_DATE < I.FY_FROM_DATE;
		IF LC_LOAN_RECO IS NOT NULL THEN 
			LC_LOAN_OP_BAL := LC_LOAN_OP_BAL - LC_LOAN_RECO;
		END IF;
		LI_CNT1 := 0;
		SELECT COUNT(1), MIN(FROM_DATE) INTO LI_CNT1, LD_INT_FIRST_DATE FROM LOAN_INT_REG WHERE LOAN_NO=I.LOAN_NO ;
		IF LI_CNT1 > 0 THEN
			LD_INT_LAST_DATE := I.DATE__INTEREST + 1;
		ELSE
			LD_INT_LAST_DATE := I.DATE__INTEREST;
			LD_INT_FIRST_DATE := I.DATE__INTEREST;
		END IF;
		LI_CNT1 := 0;
		SELECT CASE WHEN LD_INT_FIRST_DATE > (SELECT TO_DATE FROM PERIOD 
			WHERE CODE = PRD_CODE__TO) THEN 0 ELSE LC_LOAN_OP_BAL END INTO LC_LOAN_OP_BAL 
			FROM DUAL;
		SELECT SUM(INT_RATE) INTO LC_EFF_INT_RATE FROM LOANSCHEME_INT_RATE 
		WHERE SCHEME_TYPE = I.SCHEME_TYPE AND LD_INT_FIRST_DATE BETWEEN EFF_FROM AND VALID_UPTO;
		IF LC_EFF_INT_RATE IS NULL THEN 
			LC_EFF_INT_RATE := CASE WHEN EFF_INT_RATE IS NULL OR EFF_INT_RATE <= 0 THEN 
			I.INTEREST ELSE EFF_INT_RATE END;
		END IF;
		IF LC_EFF_INT_RATE <= I.INTEREST THEN 
			LC_LOAN_OP_BAL := 0;
		END IF;
		IF LC_LOAN_OP_BAL > 0 THEN
			EMI_NO := 0;
			TOT_PRESENT_VALUE := 0;
			LC_LOAN_OP_BAL := I.LOAN_AMT;

			FOR J IN PRD_INFO(LD_INT_FIRST_DATE)
			LOOP
				LD_CAL_FDATE := TO_DATE('01/01/' || TO_CHAR(J.FR_DATE , 'YYYY') , 'DD/MM/YYYY');
				LD_CAL_TDATE := TO_DATE('31/12/' || TO_CHAR(J.FR_DATE , 'YYYY') , 'DD/MM/YYYY');
				LI_NO_DAYS_IN_CAL_YR := LD_CAL_TDATE - LD_CAL_FDATE + 1;
				LI_NO_DAYS_IN_CAL_YR := 365; -- Modified by Piyush on 17/06/2016 as per ERP
				IF LC_LOAN_OP_BAL > 0 THEN
					EMI_NO := EMI_NO + 1;
					LI_CNT1 := 0;
					LC_PRINC_DEDN := 0;
					SELECT COUNT(1) INTO LI_CNT1 FROM LOAN_REG WHERE LOAN_NO = I.LOAN_NO 
					AND TRAN_TYPE = 'P' AND TRAN_DATE BETWEEN J.FR_DATE AND J.TO_DATE;
					IF LI_CNT1 > 0 THEN
						SELECT SUM(CASE WHEN AMOUNT IS NULL THEN 0 ELSE AMOUNT END) 
						INTO LC_PRINC_DEDN FROM LOAN_REG WHERE LOAN_NO = I.LOAN_NO 
						AND TRAN_TYPE = 'P' AND TRAN_DATE BETWEEN J.FR_DATE AND J.TO_DATE;
					ELSE
						LI_CNT1 := 0;
						SELECT COUNT(1) INTO LI_CNT1 FROM PAYROLL WHERE EMP_CODE = I.EMP_CODE 
						AND PRD_CODE = J.CODE;
						IF LI_CNT1 > 0 THEN
							SELECT AMOUNT INTO LC_PRINC_DEDN FROM PAYROLLDET 
							WHERE EMP_CODE = I.EMP_CODE AND PRD_CODE = J.CODE AND 
							((REF_TYPE = 'L' AND REF_NO = I.LOAN_NO) OR AD_CODE = I.AD_CODE__DED);
						ELSE
							IF I.START_RECO <= J.FR_DATE THEN
								TOT_INST_DEDN := 0;
								TOT_INST_NO := 0;
								FOR K IN LOAN_INST_INFO(I.LOAN_NO)
								LOOP
									TOT_INST_NO := TOT_INST_NO + CASE WHEN K.NO_INST IS NULL THEN 9999 
										ELSE K.NO_INST END;
									IF TOT_INST_NO >= EMI_NO THEN
										LC_PRINC_DEDN := CASE WHEN LC_LOAN_OP_BAL > K.AMOUNT THEN K.AMOUNT ELSE LC_LOAN_OP_BAL END;
										EXIT;
									END IF;
								END LOOP;
							END IF;
						END IF;
					END IF;
					PV_FACTOR := 0;
					PRESENT_VALUE := 0;
					LC_OTH_RECOVERY := 0;
					LC_INT_DEDN := 0;
					IF LI_CNT1 > 0 THEN
						SELECT AMOUNT INTO LC_INT_DEDN FROM PAYROLLDET WHERE EMP_CODE = I.EMP_CODE AND PRD_CODE = J.CODE AND ((REF_TYPE = 'N' AND REF_NO = I.LOAN_NO) OR AD_CODE = I.AD_CODE__INT);
					ELSE
						LC_INT_DEDN := ROUND((LC_LOAN_OP_BAL * I.INTEREST / 100) / (LI_NO_DAYS_IN_CAL_YR) * ((J.TO_DATE - CASE WHEN LD_INT_FIRST_DATE > J.FR_DATE THEN LD_INT_FIRST_DATE ELSE J.FR_DATE END) + 1),2);
						FOR L IN LOAN_RECO_INFO(I.LOAN_NO, J.FR_DATE, J.TO_DATE)
						LOOP
							LC_INT_DEDN := LC_INT_DEDN - (ROUND((L.AMOUNT * I.INTEREST / 100) / (LI_NO_DAYS_IN_CAL_YR) * ((J.TO_DATE - L.TRAN_DATE) + 1),2));
						END LOOP;
						LC_INT_DEDN := CASE WHEN LC_INT_DEDN >= 0 THEN LC_INT_DEDN ELSE 0 END;
						IF TRIM(I.INT_TERM) = 'EMI' THEN
							LC_PRINC_DEDN := I.MON_INST - LC_INT_DEDN;
						ELSE
							LC_PRINC_DEDN := I.MON_INST;
						END IF;
					END IF;
					IF LC_PRINC_DEDN > LC_LOAN_OP_BAL THEN
						LC_PRINC_DEDN := LC_LOAN_OP_BAL;
					END IF;

					SELECT SUM(AMOUNT) INTO LC_OTH_RECOVERY FROM LOAN_REG WHERE LOAN_NO = I.LOAN_NO AND TRAN_DATE BETWEEN J.FR_DATE AND J.TO_DATE AND TRAN_TYPE NOT IN ('P');
					IF LC_OTH_RECOVERY IS NULL THEN 
						LC_OTH_RECOVERY := 0;
					END IF;
					PV_FACTOR := ROUND(1 / POWER((1 + ROUND(LC_EFF_INT_RATE / 1200 , 4)),EMI_NO),4);
					PRESENT_VALUE := ROUND((LC_PRINC_DEDN + LC_INT_DEDN + LC_OTH_RECOVERY) * PV_FACTOR , 2);
					TOT_PRESENT_VALUE := TOT_PRESENT_VALUE + PRESENT_VALUE;
					LC_LOAN_OP_BAL := LC_LOAN_OP_BAL - LC_PRINC_DEDN - LC_OTH_RECOVERY;
					LD_LOAN_CLOUSRE_DATE := J.TO_DATE;
				ELSE
					EXIT;
				END IF;
			END LOOP;

			IF LD_LOAN_CLOUSRE_DATE >= I.FY_FROM_DATE THEN
				LC_LOAN_OP_BAL := I.LOAN_AMT;
				LI_CNT1 := 0;
				SELECT CASE WHEN LD_INT_FIRST_DATE > (SELECT TO_DATE FROM PERIOD 
					WHERE CODE = PRD_CODE__TO) THEN 0 ELSE LC_LOAN_OP_BAL END INTO LC_LOAN_OP_BAL 
					FROM DUAL;
				PV_FACTOR := 0;
				PRESENT_VALUE := 0;
				LC_OTH_RECOVERY := 0;
				LC_INT_DEDN := 0;
				LC_PRINC_DEDN := 0;
				EMI_NO := 0;

				FOR J IN PRD_INFO(LD_INT_FIRST_DATE)
				LOOP
					LD_CAL_FDATE := TO_DATE('01/01/' || TO_CHAR(J.FR_DATE , 'YYYY') , 'DD/MM/YYYY');
					LD_CAL_TDATE := TO_DATE('31/12/' || TO_CHAR(J.FR_DATE , 'YYYY') , 'DD/MM/YYYY');
					LI_NO_DAYS_IN_CAL_YR := LD_CAL_TDATE - LD_CAL_FDATE + 1;
					LI_NO_DAYS_IN_CAL_YR := 365;  -- Modified by Piyush on 17/06/2016 as per ERP
					IF LC_LOAN_OP_BAL > 0 THEN
						LC_OTH_RECOVERY := 0;
						EMI_NO := EMI_NO + 1;
						LI_CNT1 := 0;
						LC_PRINC_DEDN := 0;
						LC_OTH_RECOVERY := 0;
						LC_INT_DEDN := 0;
						SELECT COUNT(1) INTO LI_CNT1 FROM LOAN_REG WHERE LOAN_NO = I.LOAN_NO 
						AND TRAN_TYPE = 'P' AND TRAN_DATE BETWEEN J.FR_DATE AND J.TO_DATE;
						IF LI_CNT1 > 0 THEN
							SELECT SUM(CASE WHEN AMOUNT IS NULL THEN 0 ELSE AMOUNT END) 
							INTO LC_PRINC_DEDN FROM LOAN_REG WHERE LOAN_NO = I.LOAN_NO 
							AND TRAN_TYPE = 'P' AND TRAN_DATE BETWEEN J.FR_DATE AND J.TO_DATE;
						ELSE
							LI_CNT1 := 0;
							SELECT COUNT(1) INTO LI_CNT1 FROM PAYROLL WHERE EMP_CODE = I.EMP_CODE 
							AND PRD_CODE = J.CODE;
							IF LI_CNT1 > 0 THEN
								SELECT AMOUNT INTO LC_PRINC_DEDN FROM PAYROLLDET 
								WHERE EMP_CODE = I.EMP_CODE AND PRD_CODE = J.CODE AND 
								((REF_TYPE = 'L' AND REF_NO = I.LOAN_NO) OR AD_CODE = I.AD_CODE__DED);
							ELSE
								IF I.START_RECO <= J.FR_DATE THEN
									TOT_INST_DEDN := 0;
									TOT_INST_NO := 0;
									FOR K IN LOAN_INST_INFO(I.LOAN_NO)
									LOOP
										TOT_INST_NO := TOT_INST_NO + CASE WHEN K.NO_INST IS NULL THEN 999999 
											ELSE K.NO_INST END;
										IF TOT_INST_NO >= EMI_NO THEN
											LC_PRINC_DEDN := CASE WHEN LC_LOAN_OP_BAL > K.AMOUNT THEN K.AMOUNT ELSE LC_LOAN_OP_BAL END;
											EXIT;
										END IF;
									END LOOP;
								END IF;
							END IF;
						END IF;
						PV_FACTOR := 0;
						PRESENT_VALUE := 0;
						LC_OTH_RECOVERY := 0;
						LC_INT_DEDN := 0;
						LOAN_INT_CALC_STR := '';
						-- Modified to calculate interest as per ERP.Start
						INTEREST_AT_EFF_RATE := 0.00;
						-- Modified to calculate interest as per ERP.End

						IF LI_CNT1 > 0 THEN
							SELECT AMOUNT INTO LC_INT_DEDN FROM PAYROLLDET WHERE EMP_CODE = I.EMP_CODE AND PRD_CODE = J.CODE AND ((REF_TYPE = 'N' AND REF_NO = I.LOAN_NO) OR AD_CODE = I.AD_CODE__INT);
							FOR M IN LOAN_INT_CALC_INFO(I.LOAN_NO , J.CODE) 
							LOOP
								LOAN_INT_CALC_STR := LOAN_INT_CALC_STR || '[AI-' || M.REF_TYPE || '-' || 
									TRIM(TO_CHAR(M.AMOUNT)) || 
									'-' || TO_CHAR(M.DATE__FROM , 'DD-MON-YY') || '-' || 
									'-' || TO_CHAR(M.DATE__TO , 'DD-MON-YY') || '-' || 
									'-' || TRIM(TO_CHAR(M.NO_DAYS)) || '-' || 
									TRIM(TO_CHAR(M.INT_PERC)) || '-' || 
									TRIM(TO_CHAR(M.INTEREST_AMT__DIFF)) || ']';
							END LOOP;
						ELSE
							LC_INT_DEDN := ROUND((LC_LOAN_OP_BAL * I.INTEREST / 100) / (LI_NO_DAYS_IN_CAL_YR) * ((J.TO_DATE - CASE WHEN LD_INT_FIRST_DATE > J.FR_DATE THEN LD_INT_FIRST_DATE ELSE J.FR_DATE END) + 1),2);
							LOAN_INT_CALC_STR := LOAN_INT_CALC_STR || '[PI-LOANBL-' || 
								TRIM(TO_CHAR(LC_LOAN_OP_BAL)) || '-' || 
								TO_CHAR(CASE WHEN LD_INT_FIRST_DATE > J.FR_DATE THEN LD_INT_FIRST_DATE ELSE J.FR_DATE END , 'DD-MON-YY') || '-' ||
								TO_CHAR(J.TO_DATE , 'DD-MON-YY') || '-' ||
								TRIM(TO_CHAR(((J.TO_DATE - CASE WHEN LD_INT_FIRST_DATE > J.FR_DATE THEN LD_INT_FIRST_DATE ELSE J.FR_DATE END) + 1))) || '-' || 
								TRIM(TO_CHAR(I.INTEREST)) || '-' || 
								TRIM(TO_CHAR(LC_INT_DEDN)) || ']' ;
							
							FOR L IN LOAN_RECO_INFO(I.LOAN_NO, J.FR_DATE, J.TO_DATE)
							LOOP
								LC_INT_DEDN := LC_INT_DEDN - (ROUND((L.AMOUNT * I.INTEREST / 100) / (LI_NO_DAYS_IN_CAL_YR) * ((J.TO_DATE - L.TRAN_DATE) + 1),2));
								LOAN_INT_CALC_STR := LOAN_INT_CALC_STR || '[PI-LNRECO-' || 
									TRIM(TO_CHAR(L.AMOUNT)) || '-' || 
									TO_CHAR(L.TRAN_DATE , 'DD-MON-YY') || '-' ||
									TO_CHAR(J.TO_DATE , 'DD-MON-YY') || '-' ||
									TRIM(TO_CHAR(((J.TO_DATE - L.TRAN_DATE) + 1))) || '-' || 
									TRIM(TO_CHAR(I.INTEREST)) || '-' || 
									TRIM(TO_CHAR((ROUND((L.AMOUNT * I.INTEREST / 100) / (LI_NO_DAYS_IN_CAL_YR) * ((J.TO_DATE - L.TRAN_DATE) + 1),2)))) || ']' ;
								-- Modified to calculate interest as per ERP.Start
								INTEREST_AT_EFF_RATE := INTEREST_AT_EFF_RATE - (ROUND((L.AMOUNT * LC_EFF_INT_RATE / 100) / (LI_NO_DAYS_IN_CAL_YR) * ((J.TO_DATE - L.TRAN_DATE) + 1),2));
								-- Modified to calculate interest as per ERP.End
							END LOOP;
							LC_INT_DEDN := CASE WHEN LC_INT_DEDN >= 0 THEN LC_INT_DEDN ELSE 0 END;
							IF TRIM(I.INT_TERM) = 'EMI' THEN
								LC_PRINC_DEDN := I.MON_INST - LC_INT_DEDN;
							ELSE
								LC_PRINC_DEDN := I.MON_INST;
							END IF;
						END IF;
						IF LC_PRINC_DEDN > LC_LOAN_OP_BAL THEN
							LC_PRINC_DEDN := LC_LOAN_OP_BAL;
						END IF;

						SELECT SUM(AMOUNT) INTO LC_OTH_RECOVERY FROM LOAN_REG WHERE LOAN_NO = I.LOAN_NO AND TRAN_DATE BETWEEN J.FR_DATE AND J.TO_DATE AND TRAN_TYPE NOT IN ('P');
						IF LC_OTH_RECOVERY IS NULL THEN 
							LC_OTH_RECOVERY := 0;
						END IF;

						AMORTISED_COST_OP_BAL := CASE WHEN EMI_NO = 1 THEN TOT_PRESENT_VALUE ELSE AMORTISED_COST_CL_BAL END;

						-- Commented and shofted above to calculate interest as per ERP logic
						-- INTEREST_AT_EFF_RATE := ROUND((AMORTISED_COST_OP_BAL * LC_EFF_INT_RATE / 100) / (LI_NO_DAYS_IN_CAL_YR) * ((J.TO_DATE - CASE WHEN LD_INT_FIRST_DATE > J.FR_DATE THEN LD_INT_FIRST_DATE ELSE J.FR_DATE END) + 1),2);

						INTEREST_AT_EFF_RATE := INTEREST_AT_EFF_RATE + (ROUND((AMORTISED_COST_OP_BAL * LC_EFF_INT_RATE / 100) / (LI_NO_DAYS_IN_CAL_YR) * ((J.TO_DATE - CASE WHEN LD_INT_FIRST_DATE > J.FR_DATE THEN LD_INT_FIRST_DATE ELSE J.FR_DATE END) + 1),2));

						-- Commented and modified bellow to set cl bal 0 on clauser of loan.Start
						--AMORTISED_COST_CL_BAL := AMORTISED_COST_OP_BAL + INTEREST_AT_EFF_RATE - (LC_PRINC_DEDN + LC_OTH_RECOVERY + LC_INT_DEDN);

						if LC_LOAN_OP_BAL - LC_PRINC_DEDN - LC_OTH_RECOVERY > 0 then
							AMORTISED_COST_CL_BAL := AMORTISED_COST_OP_BAL + INTEREST_AT_EFF_RATE - (LC_PRINC_DEDN + LC_OTH_RECOVERY + LC_INT_DEDN);
						else
							AMORTISED_COST_CL_BAL := 0;
						end if;
						-- Commented and modified bellow to set cl bal 0 on clauser of loan.End

						PV_FACTOR := ROUND(1 / POWER((1 + ROUND(LC_EFF_INT_RATE / 1200 , 4)),EMI_NO),4);
						PRESENT_VALUE := ROUND((LC_PRINC_DEDN + LC_INT_DEDN + LC_OTH_RECOVERY) * PV_FACTOR , 2);

						EMP_BENEFIT := INTEREST_AT_EFF_RATE - LC_INT_DEDN;

						DIFF_PRINC_DEDN := (LC_LOAN_OP_BAL - (LC_PRINC_DEDN + LC_OTH_RECOVERY)) - AMORTISED_COST_CL_BAL;

						OUT_REC.ACCT_PRD_ARG := ACCT_PRD; 
						OUT_REC.ACCT_PRD_DATA := J.P_ACCT_PRD; 
						OUT_REC.PRD_CODE__FR := PRD_CODE__FR; 
						OUT_REC.PRD_CODE__TO := PRD_CODE__TO; 
						OUT_REC.FIN_ENTITY := I.FIN_ENTITY; 
						OUT_REC.EMP_CODE := I.EMP_CODE; 
						OUT_REC.EMP_FULL_NAME := I.EMP_FULL_NAME; 
						OUT_REC.PAY_SITE := I.PAY_SITE; 
						OUT_REC.CCTR_CODE__SAL := I.CCTR_CODE__SAL; 
						OUT_REC.LOAN_NO := I.LOAN_NO; 
						OUT_REC.SCHEME_NO := I.SCHEME_NO; 
						OUT_REC.SCHEME_TYPE := I.SCHEME_TYPE; 
						OUT_REC.ISSUE_DATE := I.ISSUE_DATE; 
						OUT_REC.LOAN_DISB_DATE := LD_INT_FIRST_DATE;
						OUT_REC.TERM := I.TERM; 
						OUT_REC.LOAN_AMT := I.LOAN_AMT; 
						OUT_REC.INTEREST := I.INTEREST; 
						OUT_REC.MON_INST := I.MON_INST; 
						OUT_REC.INT_TERM := I.INT_TERM; 
						OUT_REC.APPR_DATE := I.APPR_DATE; 
						OUT_REC.DATE__BALANCE := I.DATE__BALANCE; 
						OUT_REC.DATE__INTEREST := I.DATE__INTEREST; 
						OUT_REC.LOAN_TYPE := I.LOAN_TYPE; 
						OUT_REC.LOAN_CLOUSRE_DATE := LD_LOAN_CLOUSRE_DATE; 
						OUT_REC.ISA_EFF_INT_RATE := LC_EFF_INT_RATE; 
						OUT_REC.BALANCE_AMT := LC_LOAN_OP_BAL; 
						OUT_REC.LOAN_START_RECO_DATE := I.START_RECO; 

						OUT_REC.EMI_NO := EMI_NO; 
						OUT_REC.EMI_PRD_CODE := J.CODE; 
						OUT_REC.EMI_PRD_DESCR := TO_CHAR(J.FR_DATE , 'MON-YY'); 
						OUT_REC.OP_BALANCE_AMT := LC_LOAN_OP_BAL; 
						OUT_REC.INTEREST_AMT := LC_INT_DEDN; 
						OUT_REC.PRINC_CUM_INTEREST_AMT := (LC_LOAN_OP_BAL + LC_INT_DEDN); 
						OUT_REC.MON_DEDN := (LC_PRINC_DEDN + LC_INT_DEDN); 
						OUT_REC.PRINC_DEDN := LC_PRINC_DEDN; 
						OUT_REC.RECOVER_AMT := LC_OTH_RECOVERY; 
						OUT_REC.CL_BALANCE_AMT := LC_LOAN_OP_BAL - LC_PRINC_DEDN - LC_OTH_RECOVERY; 

						OUT_REC.PV_FACTOR := PV_FACTOR; 
						OUT_REC.PRESENT_VALUE := PRESENT_VALUE; 
						OUT_REC.AMORTISED_COST_OP_BAL := AMORTISED_COST_OP_BAL; 
						OUT_REC.INTEREST_AT_EFF_RATE := INTEREST_AT_EFF_RATE; 
						OUT_REC.REPAYMENT_INCL_INTEREST := (LC_PRINC_DEDN + LC_INT_DEDN + LC_OTH_RECOVERY) ; 
						OUT_REC.AMORTISED_COST_CL_BAL := AMORTISED_COST_CL_BAL; 
						OUT_REC.EMP_BENEFIT := EMP_BENEFIT; 
						OUT_REC.DIFF_PRINC_DEDN := DIFF_PRINC_DEDN; 
						OUT_REC.PRINC_DEDN := LC_PRINC_DEDN; 
						OUT_REC.LOAN_INT_CALC_STR := LOAN_INT_CALC_STR; 
						OUT_REC.REPAYMENT_INCL_INTEREST_1 := CASE WHEN LC_LOAN_OP_BAL - LC_PRINC_DEDN - LC_OTH_RECOVERY > 0 THEN (LC_PRINC_DEDN + LC_INT_DEDN + LC_OTH_RECOVERY) ELSE AMORTISED_COST_OP_BAL + INTEREST_AT_EFF_RATE END; 
						LC_LOAN_OP_BAL := LC_LOAN_OP_BAL - LC_PRINC_DEDN - LC_OTH_RECOVERY;
						pipe row ( out_rec ); 
					ELSE
						EXIT;
					END IF;
				END LOOP;
			END IF;
		END IF;
	END LOOP;

	RETURN ;
END;
/
