Delimiter $$
/**
 * compute BUSINESS_FI_ANA_TMP_ACCOUNTS_ACD_BPDSO
 * optimisation pour le calcul fiana
 * création de la table temporaire tmp_accouts_acd_bpdso
 * contient l'acd et le bpdso par client
 * appel la procédure  BUSINESS_FI_ANA_TMP_ENTRIES_LAST_MATCHING_CODES
 * REMARQUES : 
 *  l'ACD et le BPDSO se caclulent par rapport au dernier jour du mois (clos)
 *  - Il est donc inutilr de le calcculer tous les jours
 *  - il ne faut le calculer qu'en début de mois, pour le mois précédant
 *  - le caclu sur les 1er jour du mois (1-5) permet de prendre en compte les écriture fournis
 *    avec un légé décalage (ex ecriture du 25 fournis ou lettré dans le fichier du 3 du mois 
 *    suivant )
 */ 
Drop Procedure if Exists BUSINESS_FI_ANA_TMP_ACCOUNTS_ACD_BPDSO $$
Create Procedure BUSINESS_FI_ANA_TMP_ACCOUNTS_ACD_BPDSO(In refdate DateTime, In idaccounts Int unsigned, In identities Int unsigned)
Begin
    v_acc_acd_bpdso: begin


		set @bfataab_idaccounts = idaccounts;
		set @bfataab_identities = identities;
		set @bfataab_refdate = Coalesce(refdate, AMO_BAL_REFDATE());
-- 		set @bfataab_refdate = AMO_BAL_REFDATE(); -- test.debug
-- 		set @bfataab_accFilter = ifnull(idaccounts, '%');

        if idaccounts Is null Then
            Set @bftaab_accMinVal = 0;
            Set @bftaab_accMaxVal = 1000000;
        Else
            Set @bftaab_accMinVal = idaccounts;
            Set @bftaab_accMaxVal = idaccounts;
        End if;

        if identities Is null Then
            Set @bftaab_enttMinVal = 0;
            Set @bftaab_enttMaxVal = 1000;
        Else
            Set @bftaab_enttMinVal = identities;
            Set @bftaab_enttMaxVal = identities;
        End if;


        Drop Temporary Table if exists tmp_accouts_acd_bpdso;
        Create Temporary Table tmp_accouts_acd_bpdso (
                    ID_ACCOUNTS Int Unsigned not Null

                    , ADMIN_BASE_PERIOD SmallInt(10)    -- non utilisé dans les donnée, utilisé pour calcul et optimisation
                    , ENCOURS Decimal(19,4)             -- non utilisé dans les donnée, utilisé pour calcul et optimisation
                    , NON_ECHU Decimal(19,4)            -- non utilisé dans les donnée, utilisé pour calcul et optimisation
                    , CA Decimal(19,4)                  -- non utilisé dans les donnée, utilisé pour calcul et optimisation

                    , ACD Smallint(5)
                    , BPDSO Smallint(5)
                    
                    , Index (ID_ACCOUNTS)
                )
            ;

        -- determination de la date de reference
        -- la date de réference est le dernier jours du mois.
        -- - si la date de refenrence fourni (refdate) est égale à la date du jour, on utlise le 
        --   dernier jour du mois précédant (la date de reférence fournis)
        -- - si la date de refenrence fourni (refdate) est inférieur à la date du jour (retro  
        --   calcul) on utilise le dernier jour du mois de référence founis

        If @bfataab_refdate = curdate() Then
            -- utilisation du dernier jours du mois précédent
            Set @bfataab_refdate4Calc = date_sub(curdate(), interval DAYOFMONTH(curdate()) DAY);

        Else
            -- utilisation du dernier jours du mois de référence
            Set @bfataab_refdate4Calc = LAST_DAY(@bfataab_refdate);
        End If ;



--         Select @bfataab_idaccounts , @bfataab_refdate, @bftaab_accMinVal, @bftaab_accMaxVal, @bfataab_refdate4Calc;
-- 		leave v_acc_acd_bpdso;

		if idaccounts Is Not Null Then
			-- optimisation, si idaccount fourni, pas de recalcul du bpdso
-- 			Create Temporary Table tmp_accouts_acd_bpdso AS
            Insert Into tmp_accouts_acd_bpdso (
                    ID_ACCOUNTS, ACD, BPDSO
                )
			Select
# 				ACCOUNTS_ID_ACCOUNTS ID_ACCOUNTS
			       acc.ID_ACCOUNTS
				, FI_ANA_ACD ACD
				, FI_ANA_BPDSO BPDSO
			From FI_ANA
                Inner Join ACCOUNTS acc
                           On FI_ANA.ACCOUNTS_ID_ACCOUNTS = acc.ID_ACCOUNTS
                    
			Where 
#                 ACCOUNTS_ID_ACCOUNTS between @bftaab_accMinVal and @bftaab_accMaxVal
                acc.ID_ACCOUNTS between @bftaab_accMinVal and @bftaab_accMaxVal
                And acc.ENTITIES_ID_ENTITIES between @bftaab_enttMinVal and @bftaab_enttMaxVal
			;
		Else
			call BUSINESS_FI_ANA_TMP_ENTRIES_LAST_MATCHING_CODES(@bfataab_refdate, @bfataab_idaccounts, @bfataab_identities );
            Set @bfataab_lastDayRefdate = LAST_DAY(DATE_SUB(@bfataab_refdate4Calc, INTERVAL 1 MONTH));
-- 			Create Temporary Table tmp_accouts_acd_bpdso AS
            Insert Into tmp_accouts_acd_bpdso (
                    ID_ACCOUNTS

                    , ADMIN_BASE_PERIOD    -- non utilisé dans les donnée, utilisé pour calcul et optimisation
                    , ENCOURS              -- non utilisé dans les donnée, utilisé pour calcul et optimisation
                    , NON_ECHU             -- non utilisé dans les donnée, utilisé pour calcul et optimisation
                    , CA                   -- non utilisé dans les donnée, utilisé pour calcul et optimisation

--                     , ACD, BPDSO
                )
-- 			SELECT
-- 				ID_ACCOUNTS
-- 				-- expression pour rendre null les valeur négative
-- 				-- et limiter a une valeur maximal
-- 				-- Nullif(GREATEST(Least(xxxxx, MAXVALUE), 0, 0)
-- 				, Nullif(GREATEST(Least(round((ENCOURS * ADMIN_BASE_PERIOD)/CA), 32000), 0), 0) as ACD
-- 				, Nullif(GREATEST(Least(round((NON_ECHU * ADMIN_BASE_PERIOD)/CA), 32000), 0),0) as BPDSO
-- 			FROM (
					SELECT
						ACCOUNTS.ID_ACCOUNTS
						-- ADMIN_PARAMS.ADMIN_BASE_PERIOD
                        , Min(ADMIN_PARAMS.ADMIN_BASE_PERIOD) ADMIN_BASE_PERIOD
-- 						, sum(Case When ENTRIES.ENTRIES_DUE_DATE <= DATE_SUB(LAST_DAY(DATE_SUB(@bfataab_refdate4Calc, INTERVAL 1 MONTH)), INTERVAL ADMIN_PARAMS.ADMIN_BASE_PERIOD DAY)
						, sum(
                            Case When ENTRIES.ENTRIES_DUE_DATE <= DATE_SUB(@bfataab_lastDayRefdate, INTERVAL ADMIN_PARAMS.ADMIN_BASE_PERIOD DAY)
                                    AND (DF_ENTRIES_TYPE.DF_ENTRIES_TYPE_ACCOUNTANT = 1)
                                    AND (
                                            @bfataab_isOpenAtDate := (
                                                (
        -- 												V_ENTRIES_MATCHINGCODES_LAST.MATCHINGCODES_DATE > LAST_DAY(DATE_SUB(@bfataab_refdate4Calc, INTERVAL 1 MONTH))
    --                                                 AND
    --                                                     V_ENTRIES_MATCHING_CODE_STATE.DF_MATCHINGCODE_STATE_CLOSED = 1
                                                    V_ENTRIES_MATCHINGCODES_LAST.MATCHINGCODES_DATE > @bfataab_lastDayRefdate
                                                    And ENTRIES.DF_MATCH_STAT_ID_DF_MATCH_STAT  = 3
                                                )
                                                Or ENTRIES.DF_MATCH_STAT_ID_DF_MATCH_STAT In (1, 2)
    --                                             OR
    --                                                 V_ENTRIES_MATCHING_CODE_STATE.DF_MATCHINGCODE_STATE_PARTIAL = 1
    --                                             OR
    --                                                 V_ENTRIES_MATCHING_CODE_STATE.DF_MATCHINGCODE_STATE_OPEN = 1
                                            )
                                    )
                                Then
                                    ENTRIES.ENTRIES_ENT_DEBIT - ENTRIES.ENTRIES_ENT_CREDIT
                                Else
                                    0
                                End 
                            ) as ENCOURS
-- 						, sum(Case When ENTRIES.ENTRIES_DUE_DATE > LAST_DAY(DATE_SUB(@bfataab_refdate4Calc, INTERVAL 1 MONTH))
						, sum(
                                Case When ENTRIES.ENTRIES_DUE_DATE > @bfataab_lastDayRefdate
        -- 							AND ENTRIES.ENTRIES_DATE <= LAST_DAY(DATE_SUB(@bfataab_refdate4Calc, INTERVAL 1 MONTH))
                                    AND ENTRIES.ENTRIES_DATE <= @bfataab_lastDayRefdate
                        			AND (DF_ENTRIES_TYPE.DF_ENTRIES_TYPE_ACCOUNTANT = 1)
                                	AND (
                                            @bfataab_isOpenAtDate
--                                                 (
--                                                         V_ENTRIES_MATCHINGCODES_LAST.MATCHINGCODES_DATE > LAST_DAY(DATE_SUB(@bfataab_refdate4Calc, INTERVAL 1 MONTH))
--                                                     AND
--                                                         V_ENTRIES_MATCHING_CODE_STATE.DF_MATCHINGCODE_STATE_CLOSED = 1
--                                                 )
--                                             OR
--                                                 V_ENTRIES_MATCHING_CODE_STATE.DF_MATCHINGCODE_STATE_PARTIAL = 1
--                                             OR
--                                                 V_ENTRIES_MATCHING_CODE_STATE.DF_MATCHINGCODE_STATE_OPEN = 1
                                        )
                                Then
                                    ENTRIES.ENTRIES_ENT_DEBIT - ENTRIES.ENTRIES_ENT_CREDIT
                                Else
                                    0
                                End 
                            ) as NON_ECHU
-- 						, sum(Case When ENTRIES.ENTRIES_DATE <= DATE_SUB(LAST_DAY(DATE_SUB(@bfataab_refdate4Calc, INTERVAL 1 MONTH)), INTERVAL ADMIN_PARAMS.ADMIN_BASE_PERIOD DAY)
						, sum(
                            Case When ENTRIES.ENTRIES_DATE <= DATE_SUB(@bfataab_lastDayRefdate, INTERVAL ADMIN_PARAMS.ADMIN_BASE_PERIOD DAY)
                                	AND (DF_ENTRIES_TYPE.DF_ENTRIES_TYPE_CODE = 'INV' OR DF_ENTRIES_TYPE.DF_ENTRIES_TYPE_CODE = 'CRN')
                                    AND (
                                        @bfataab_isOpenAtDate
--                                                 (
--                                                         V_ENTRIES_MATCHINGCODES_LAST.MATCHINGCODES_DATE > LAST_DAY(DATE_SUB(@bfataab_refdate4Calc, INTERVAL 1 MONTH))
--                                                     AND
--                                                         V_ENTRIES_MATCHING_CODE_STATE.DF_MATCHINGCODE_STATE_CLOSED = 1
--                                                 )
--                                             OR
--                                                 V_ENTRIES_MATCHING_CODE_STATE.DF_MATCHINGCODE_STATE_PARTIAL = 1
--                                             OR
--                                                 V_ENTRIES_MATCHING_CODE_STATE.DF_MATCHINGCODE_STATE_OPEN = 1
                                        )
                                Then
                                    ENTRIES.ENTRIES_ENT_DEBIT - ENTRIES.ENTRIES_ENT_CREDIT
                                Else
                                    0
                                End 
                        ) as CA
					FROM ADMIN_PARAMS
					Inner JOIN ENTITIES
						ON ADMIN_PARAMS.ID_ADMIN_PARAMS = ENTITIES.ADMIN_ID_ADMIN
					Inner JOIN ACCOUNTS
						ON ENTITIES.ID_ENTITIES = ACCOUNTS.ENTITIES_ID_ENTITIES
					LEFT JOIN (
                            ENTRIES
                            Inner JOIN DF_ENTRIES_TYPE
                                ON ENTRIES.DF_ENTR_TYPE_ID_DF_ENTR_TYPE = DF_ENTRIES_TYPE.ID_DF_ENTRIES_TYPE
                            Inner Join ENTRIES_has_ACCOUNTS
                                ON ENTRIES_has_ACCOUNTS.ENTRIES_ID_ENTRIES = ENTRIES.ID_ENTRIES
                            LEFT JOIN tmp_ent_last_match V_ENTRIES_MATCHINGCODES_LAST
                                ON ENTRIES.ID_ENTRIES = V_ENTRIES_MATCHINGCODES_LAST.ID_ENTRIES
    -- 						LEFT JOIN V_ENTRIES_MATCHING_CODE_STATE
    -- 							ON ENTRIES.ID_ENTRIES = V_ENTRIES_MATCHING_CODE_STATE.ID_ENTRIES
                        ) ON ACCOUNTS.ID_ACCOUNTS = ENTRIES_has_ACCOUNTS.ACCOUNTS_ID_ACCOUNTS
	--                 LEFT JOIN ENTRIES
	--                     ON ENTRIES_has_ACCOUNTS.ENTRIES_ID_ENTRIES = ENTRIES.ID_ENTRIES
	--                 LEFT JOIN tmp_ent_last_match V_ENTRIES_MATCHINGCODES_LAST
	--                     ON ENTRIES.ID_ENTRIES = V_ENTRIES_MATCHINGCODES_LAST.ID_ENTRIES
	--                 LEFT JOIN V_ENTRIES_MATCHING_CODE_STATE
	--                     ON ENTRIES.ID_ENTRIES = V_ENTRIES_MATCHING_CODE_STATE.ID_ENTRIES
	--                 LEFT JOIN DF_ENTRIES_TYPE
	--                     ON ENTRIES.DF_ENTR_TYPE_ID_DF_ENTR_TYPE = DF_ENTRIES_TYPE.ID_DF_ENTRIES_TYPE
					Where
						ACCOUNTS.ID_ACCOUNTS between @bftaab_accMinVal And @bftaab_accMaxVal
# 						And ACCOUNTS.ENTITIES_ID_ENTITIES between @bftaab_enttMinVal And @bftaab_enttMaxVal
						And ENTITIES.ID_ENTITIES between @bftaab_enttMinVal And @bftaab_enttMaxVal

					GROUP BY ACCOUNTS.ID_ACCOUNTS
-- 				) tmp_use_for_acd_bpdso
			;

            Update tmp_accouts_acd_bpdso
            Set
                ACD = Case
                        When CA Is Null Then null
                        When CA = 0 Then null
                        Else
                            Nullif(GREATEST(Least(round((ENCOURS * ADMIN_BASE_PERIOD)/CA), 32000), 0), 0)
                    End
                , BPDSO =
                    Case
                        When CA Is Null Then null
                        When CA = 0 Then null
                        Else
                            Nullif(GREATEST(Least(round((NON_ECHU * ADMIN_BASE_PERIOD)/CA), 32000), 0),0)
			        End
            ;

		end if;
--         Create Index ix_tmp_accouts_acd_bpdso On tmp_accouts_acd_bpdso(ID_ACCOUNTS);

#         Drop temporary table if exists tmp_v_acc_aging_bal_bas_det;


    end;
end $$
Delimiter ;