diff --git a/src/main/java/io/gmss/fiscad/controllers/rfu/metier/DonneesImpositionTfuController.java b/src/main/java/io/gmss/fiscad/controllers/rfu/metier/DonneesImpositionTfuController.java index cc0bba0..daf0934 100644 --- a/src/main/java/io/gmss/fiscad/controllers/rfu/metier/DonneesImpositionTfuController.java +++ b/src/main/java/io/gmss/fiscad/controllers/rfu/metier/DonneesImpositionTfuController.java @@ -333,6 +333,59 @@ public class DonneesImpositionTfuController { } + @Operation( + summary = "Générer les données fiscales TFU pour une seule parcelle", + description = "Génère les impositions TFU pour une parcelle bâtie donnée" + ) + @PostMapping("/generer-batie/{parcelleId}") + public ResponseEntity genererDonneesFiscaleBatieUneParcelle(@CurrentUser UserPrincipal userPrincipal, @RequestBody ImpositionsTfuPaylaodWeb impositionsTfuPaylaodWeb,@PathVariable Long parcelleId) { + try { + Optional optionalImpositionsTfu =impositionsTfuRepository.findById(impositionsTfuPaylaodWeb.getId()); + + if(optionalImpositionsTfu.isEmpty()){ + return new ResponseEntity<>( + new ApiResponse<>(false, null, "L'instance d'imposition n'est pas trouvée."), + HttpStatus.OK + ); + } + +// if(!optionalImpositionsTfu.get().getStatusAvis().equals(StatusAvis.TFU_FNB_GENERE)){ +// return new ResponseEntity<>( +// new ApiResponse<>(false, null, "l'état actuel : "+optionalImpositionsTfu.get().getStatusAvis()+" ne permet pas cette opération."), +// HttpStatus.OK +// ); +// } + + if(userPrincipal==null){ + return new ResponseEntity<>( + new ApiResponse<>(false, null, "Vous n'êtes pas autorisé à accéder à cette ressource"), + HttpStatus.OK + ); + } + impositionsTfuPaylaodWeb=donneesImpositionTfuService.genererDonneesFiscalesParcelleBatieUneParcelle(impositionsTfuPaylaodWeb,userPrincipal.getUser().getId(),parcelleId); + + return new ResponseEntity<>( + new ApiResponse<>(true,impositionsTfuPaylaodWeb, "Données d'imposition des fonciers batis Générées avec succès."), + HttpStatus.OK + ); + + } catch (HttpClientErrorException.MethodNotAllowed e) { + logger.error(e.getLocalizedMessage()); + return new ResponseEntity<>(new ApiResponse(false, null, "Method POST/GET is required."), HttpStatus.OK); + } catch (NotFoundException | BadRequestException | MyFileNotFoundException | ResourceNotFoundException | + FileStorageException e) { + logger.error(e.getLocalizedMessage()); + return new ResponseEntity<>(new ApiResponse(false, null, e.getMessage()), HttpStatus.OK); + } catch (NullPointerException e) { + logger.error(e.getLocalizedMessage()); + return new ResponseEntity<>(new ApiResponse(false, null, "Null value has been detected {" + e.getMessage() + "}."), HttpStatus.OK); + } catch (Exception e) { + logger.error(e.getLocalizedMessage()); + return new ResponseEntity<>(new ApiResponse(false, null, "An error has been occur and the content is {" + e.getMessage() + "}."), HttpStatus.OK); + } + } + + @Operation(summary = "Générer les données fiscales TFU des parcelle baties") @@ -384,6 +437,59 @@ public class DonneesImpositionTfuController { } } + + @Operation( + summary = "Générer les données fiscales TFU pour une seule parcelle", + description = "Génère les impositions TFU pour une parcelle non bâtie donnée" + ) + @PostMapping("/generer-non-batie/{parcelleId}") + public ResponseEntity genererDonneesImpositionNonBatiesUneParcelle(@CurrentUser UserPrincipal userPrincipal, @RequestBody ImpositionsTfuPaylaodWeb impositionsTfuPaylaodWeb, @PathVariable Long parcelleId) { + try { + Optional optionalImpositionsTfu =impositionsTfuRepository.findById(impositionsTfuPaylaodWeb.getId()); + + if(optionalImpositionsTfu.isEmpty()){ + return new ResponseEntity<>( + new ApiResponse<>(false, null, "L'instance d'imposition n'est pas trouvée."), + HttpStatus.OK + ); + } + +// if(!optionalImpositionsTfu.get().getStatusAvis().equals(StatusAvis.GENERATION_AUTORISE)){ +// return new ResponseEntity<>( +// new ApiResponse<>(false, null, "l'état actuel : "+optionalImpositionsTfu.get().getStatusAvis()+" ne permet pas cette opération."), +// HttpStatus.OK +// ); +// } + + if(userPrincipal==null){ + return new ResponseEntity<>( + new ApiResponse<>(false, null, "Vous n'êtes pas autorisé à accéder à cette ressource"), + HttpStatus.OK + ); + } + impositionsTfuPaylaodWeb=donneesImpositionTfuService.genererDonneesFiscalesParcelleNonBatieUneParcelle(impositionsTfuPaylaodWeb,userPrincipal.getUser().getId(),parcelleId); + + return new ResponseEntity<>( + new ApiResponse<>(true,impositionsTfuPaylaodWeb, "Données d'imposition pour les fonciers non batis Générées avec succès."), + HttpStatus.OK + ); + + } catch (HttpClientErrorException.MethodNotAllowed e) { + logger.error(e.getLocalizedMessage()); + return new ResponseEntity<>(new ApiResponse(false, null, "Method POST/GET is required."), HttpStatus.OK); + } catch (NotFoundException | BadRequestException | MyFileNotFoundException | ResourceNotFoundException | + FileStorageException e) { + logger.error(e.getLocalizedMessage()); + return new ResponseEntity<>(new ApiResponse(false, null, e.getMessage()), HttpStatus.OK); + } catch (NullPointerException e) { + logger.error(e.getLocalizedMessage()); + return new ResponseEntity<>(new ApiResponse(false, null, "Null value has been detected {" + e.getMessage() + "}."), HttpStatus.OK); + } catch (Exception e) { + logger.error(e.getLocalizedMessage()); + return new ResponseEntity<>(new ApiResponse(false, null, "An error has been occur and the content is {" + e.getMessage() + "}."), HttpStatus.OK); + } + } + @Operation(summary = "Récuperer les avis d'id d'une imposition") @GetMapping("/by-impositions-id/{impositionsId}") public ResponseEntity getDonneesFiscale(@PathVariable Long impositionsId) { diff --git a/src/main/java/io/gmss/fiscad/entities/rfu/metier/DonneesImpositionTfu.java b/src/main/java/io/gmss/fiscad/entities/rfu/metier/DonneesImpositionTfu.java index c9a9459..a6caeb7 100644 --- a/src/main/java/io/gmss/fiscad/entities/rfu/metier/DonneesImpositionTfu.java +++ b/src/main/java/io/gmss/fiscad/entities/rfu/metier/DonneesImpositionTfu.java @@ -114,6 +114,7 @@ public class DonneesImpositionTfu extends BaseEntity implements Serializable { private Float tauxTfu; private Long tfuPiscine; private Float montantTaxe; + private Float montantTaxeBrut; //montant de la taxe calculée sans comparaisons avec TFU MINI private Float tfuCalculeTauxPropParc; private Float tfuSuperficieAuSolReel; private Long valeurAdminParcelleNbMetreCarre; @@ -146,5 +147,6 @@ public class DonneesImpositionTfu extends BaseEntity implements Serializable { @ManyToOne(fetch = FetchType.LAZY) private Personne personne ; + private Boolean parcelleContact; } diff --git a/src/main/java/io/gmss/fiscad/enums/NatureImpot.java b/src/main/java/io/gmss/fiscad/enums/NatureImpot.java index efd8735..ffb32bd 100755 --- a/src/main/java/io/gmss/fiscad/enums/NatureImpot.java +++ b/src/main/java/io/gmss/fiscad/enums/NatureImpot.java @@ -1,7 +1,8 @@ package io.gmss.fiscad.enums; public enum NatureImpot { - TFU, + FB, + FNB, IRF, SRTB } diff --git a/src/main/java/io/gmss/fiscad/implementations/rfu/metier/DonneesImpositionTfuServiceImpl.java b/src/main/java/io/gmss/fiscad/implementations/rfu/metier/DonneesImpositionTfuServiceImpl.java index 245ffdd..4bda8b7 100644 --- a/src/main/java/io/gmss/fiscad/implementations/rfu/metier/DonneesImpositionTfuServiceImpl.java +++ b/src/main/java/io/gmss/fiscad/implementations/rfu/metier/DonneesImpositionTfuServiceImpl.java @@ -109,21 +109,66 @@ public class DonneesImpositionTfuServiceImpl implements DonneesImpositionTfuServ return impositionsTfuRepository.findByIdToDto(impositionsTfu.getId()).orElse(null); } + @Override + @Transactional + public ImpositionsTfuPaylaodWeb genererDonneesFiscalesParcelleNonBatieUneParcelle(ImpositionsTfuPaylaodWeb impositionsTfuPaylaodWeb, Long userId,Long parcelleId) { + Integer nb= donneesImpositionTfuRepository.genererDonneesTfuNonBatie(impositionsTfuPaylaodWeb.getId(),userId,parcelleId); + + ImpositionsTfu impositionsTfu = entityFromPayLoadService.getImpositionsTfuFromPayLoadWeb(impositionsTfuPaylaodWeb); + impositionsTfu.setStatusAvis(StatusAvis.TFU_FNB_GENERE); + + impositionsTfu.setNombreAvisFnb(nb); + + impositionsTfuRepository.save(impositionsTfu); + + return impositionsTfuRepository.findByIdToDto(impositionsTfu.getId()).orElse(null); + } + @Override @Transactional public ImpositionsTfuPaylaodWeb genererDonneesFiscalesParcelleBatie(ImpositionsTfuPaylaodWeb impositionsTfuPaylaodWeb, Long userId) { Integer nbb= donneesImpositionTfuRepository.genererDonneesTfuBatie(impositionsTfuPaylaodWeb.getId(),userId); + Integer nbirfbtPlusieursBati = donneesImpositionTfuRepository.majDonneesTfuBatiePlusieursBatiment(impositionsTfuPaylaodWeb.getId()); + Integer nbulo= donneesImpositionTfuRepository.genererDonneesTfuBatieUniteLogement(impositionsTfuPaylaodWeb.getId(),userId); Integer nbirfbt= donneesImpositionTfuRepository.genererDonneesIrfBatie(impositionsTfuPaylaodWeb.getId(),userId); -// + Integer nbirfulo= donneesImpositionTfuRepository.genererDonneesIrfBatieUniteLogement(impositionsTfuPaylaodWeb.getId(),userId); -// + Integer nbsrtbbt= donneesImpositionTfuRepository.genererDonneesSrtbBatie(impositionsTfuPaylaodWeb.getId(),userId); -// - Integer nbsrtbulo= donneesImpositionTfuRepository.genererDonneesSrtbBatieUniteLogement(impositionsTfuPaylaodWeb.getId(),userId); + + + ImpositionsTfu impositionsTfu = entityFromPayLoadService.getImpositionsTfuFromPayLoadWeb(impositionsTfuPaylaodWeb); + impositionsTfu.setStatusAvis(StatusAvis.GENERE); + + impositionsTfu.setNombreAvis(nbb+nbulo+ (impositionsTfu.getNombreAvisFnb()==null?0:impositionsTfu.getNombreAvisFnb())); + impositionsTfu.setNombreAvisBatiment(nbb); + impositionsTfu.setNombreAvisUniteLog(nbulo); + + impositionsTfuRepository.save(impositionsTfu); + + return impositionsTfuRepository.findByIdToDto(impositionsTfu.getId()).orElse(null); + } + + + @Override + @Transactional + public ImpositionsTfuPaylaodWeb genererDonneesFiscalesParcelleBatieUneParcelle(ImpositionsTfuPaylaodWeb impositionsTfuPaylaodWeb, Long userId, Long parcelleId) { + + Integer nbb= donneesImpositionTfuRepository.genererDonneesTfuBatie(impositionsTfuPaylaodWeb.getId(),userId,parcelleId); + + Integer nbirfbtPlusieursBati = donneesImpositionTfuRepository.majDonneesTfuBatiePlusieursBatiment(impositionsTfuPaylaodWeb.getId(),parcelleId); + + Integer nbulo= donneesImpositionTfuRepository.genererDonneesTfuBatieUniteLogement(impositionsTfuPaylaodWeb.getId(),userId,parcelleId); + + Integer nbirfbt= donneesImpositionTfuRepository.genererDonneesIrfBatie(impositionsTfuPaylaodWeb.getId(),userId,parcelleId); + + Integer nbirfulo= donneesImpositionTfuRepository.genererDonneesIrfBatieUniteLogement(impositionsTfuPaylaodWeb.getId(),userId,parcelleId); + + Integer nbsrtbbt= donneesImpositionTfuRepository.genererDonneesSrtbBatie(impositionsTfuPaylaodWeb.getId(),userId,parcelleId); ImpositionsTfu impositionsTfu = entityFromPayLoadService.getImpositionsTfuFromPayLoadWeb(impositionsTfuPaylaodWeb); diff --git a/src/main/java/io/gmss/fiscad/interfaces/rfu/metier/DonneesImpositionTfuService.java b/src/main/java/io/gmss/fiscad/interfaces/rfu/metier/DonneesImpositionTfuService.java index 1d89b0f..9ca00af 100755 --- a/src/main/java/io/gmss/fiscad/interfaces/rfu/metier/DonneesImpositionTfuService.java +++ b/src/main/java/io/gmss/fiscad/interfaces/rfu/metier/DonneesImpositionTfuService.java @@ -27,6 +27,7 @@ public interface DonneesImpositionTfuService { ImpositionsTfuPaylaodWeb genererDonneesFiscalesParcelleBatie(ImpositionsTfuPaylaodWeb impositionsTfuPaylaodWeb,Long userId); ImpositionsTfuPaylaodWeb genererDonneesFiscalesParcelleNonBatie(ImpositionsTfuPaylaodWeb impositionsTfuPaylaodWeb,Long userId); + public ImpositionsTfuPaylaodWeb genererDonneesFiscalesParcelleNonBatieUneParcelle(ImpositionsTfuPaylaodWeb impositionsTfuPaylaodWeb, Long userId,Long parcelleId); List getDonneesFiscalesByImposition(Long impositionsId); List getDonneesFiscalesByImpositionArrondissement(Long impositionsId,Long arrondissementId); Page getDonneesFiscalesByImpositionTfuIdPageable(Long impositionsTfuId, Pageable pageable); @@ -47,5 +48,7 @@ public interface DonneesImpositionTfuService { List getDonneesFiscalesByPersonneId(Long personneId); + public ImpositionsTfuPaylaodWeb genererDonneesFiscalesParcelleBatieUneParcelle(ImpositionsTfuPaylaodWeb impositionsTfuPaylaodWeb, Long userId, Long parcelleId); + } diff --git a/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/archive_generate_old/generer_donnees_imposition_srtb_batie_old.sql b/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/archive_generate_old/generer_donnees_imposition_srtb_batie_old.sql new file mode 100644 index 0000000..b8cdcda --- /dev/null +++ b/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/archive_generate_old/generer_donnees_imposition_srtb_batie_old.sql @@ -0,0 +1,497 @@ +/*CREATE OR REPLACE FUNCTION public.generer_donnees_imposition_srtb_batie( + p_impositions_tfu_id BIGINT, + p_user_id BIGINT +) +RETURNS INTEGER +LANGUAGE plpgsql +AS +$$ +DECLARE +v_rows_inserted INTEGER; + v_annee BIGINT; + v_structure_id BIGINT; + v_montant_srtb NUMERIC; +BEGIN + +-- récupération de l'année +SELECT ex.annee, it.structure_id +INTO STRICT v_annee, v_structure_id +FROM impositions_tfu it + join exercice ex on ex.id =it.exercice_id +WHERE it.id = p_impositions_tfu_id; + + +select value +into STRICT v_montant_srtb +from parameters +where name ='TAXE_SRTB'; + + +INSERT INTO donnees_imposition_tfu( + annee, + code_departement, + nom_departement, + code_commune, + nom_commune, + code_arrondissement, + nom_arrondissement, + code_quartier_village, + nom_quartier_village, + q, + ilot, + parcelle, + nup, + titre_foncier, + num_batiment, + ifu, + npi, + tel_prop, + email_prop, + nom_prop, + prenom_prop, + raison_sociale, + adresse_prop, + tel_sc, + nom_sc, + prenom_sc, + longitude, + latitude, + batie, + exonere, + batiment_exonere, + standing_bat, + categorie_bat, + nombre_piscine, + date_enquete, + structure_id, + zone_rfu_id, + nature_impot, + superficie_parc, + superficie_au_sol_bat, + valeur_batiment, + valeur_locative_adm_metre_carre, + montant_loyer_annuel, + tfu_metre_carre, + tfu_minimum, + impositions_tfu_id, + deleted, + created_at , + created_by , + "source", + updated_at , + updated_by, + categorie_usage, + superficie_au_sol_taux_prop_parc, ---70% de la surperficie au sol de la parcelle + valeur_locative_adm_taux_prop_parc, + tfu_calcule_taux_prop_parc, ----tfu correspondant au 70% + valeur_locative_adm_sup_reel, + valeur_locative_adm, ----------valeur locative administrative + tfu_superficie_au_sol_reel, ----tfu correspondant à la superficie au sol reelle + tfu_piscine, + montant_taxe, ----tfu finale + taux_tfu, ----taux tfu batie + parcelle_id, + batiment_id, + unite_logement_id, + superficie_au_sol_loue +) +SELECT + v_annee, + d.code, + d.nom, + c.code, + c.nom, + a.code, + a.nom, + q.code, + q.nom, + p.q, + p.i, + p.p, + p.nup, + ep.numero_titre_foncier, + b.nub, + pers.ifu, + pers.npi, + pers.tel1, + pers.email, + pers.nom, + pers.prenom, + pers.raison_sociale, + pers.adresse, + ep.representant_tel, + ep.representant_nom, + ep.representant_prenom, + p.longitude, + p.latitude, + TRUE, + ( + CURRENT_DATE >= ep.date_debut_exemption + AND CURRENT_DATE <= COALESCE(ep.date_fin_exemption, CURRENT_DATE) + ), + ( + CURRENT_DATE >= eb.date_debut_excemption + AND CURRENT_DATE <= COALESCE(eb.date_fin_excemption, CURRENT_DATE) + ), + cb.standing, + cb.nom, + eb.nombre_piscine, + eb.date_enquete, + st.id, + ep.zone_rfu_id, + 'SRTB', + p.superficie, + eb.superficie_au_sol, + case -------valeur_batiment + WHEN eb.valeur_batiment_reel IS NOT NULL AND eb.valeur_batiment_reel <> 0 THEN eb.valeur_batiment_reel + WHEN eb.valeur_batiment_calcule IS NOT NULL AND eb.valeur_batiment_calcule <> 0 THEN eb.valeur_batiment_calcule + WHEN eb.valeur_batiment_estime IS NOT NULL AND eb.valeur_batiment_estime <> 0 THEN eb.valeur_batiment_estime + ELSE 0 + END, + brb.valeur_locative, + case ----- montant_loyer_annuel + WHEN eb.montant_locatif_annuel_declare IS NOT NULL AND eb.montant_locatif_annuel_declare <> 0 THEN eb.montant_locatif_annuel_declare + WHEN eb.montant_locatif_annuel_calcule IS NOT NULL AND eb.montant_locatif_annuel_calcule <> 0 THEN eb.montant_locatif_annuel_calcule + WHEN eb.montant_locatif_annuel_estime IS NOT NULL AND eb.montant_locatif_annuel_estime <> 0 THEN eb.montant_locatif_annuel_estime + ELSE 0 + END, + brb.tfu_metre_carre, + brb.tfu_minimum, + p_impositions_tfu_id, + false, + current_date , + p_user_id , + 'FISCAD', + current_date , + p_user_id, + eb.categorie_usage, + 0,---superficie_au_sol_70pour100 + 0, + 0, + eb.superficie_au_sol * brb.valeur_locative, + 0, ------ valeur_locative_adm : en attente de update + 0, + 0, + v_montant_srtb, + 0, + p.id, + b.id, + null, + eb.superficie_louee +FROM parcelle p + LEFT JOIN ( + SELECT DISTINCT ON (parcelle_id) + parcelle_id, + superficie, + personne_id, + numero_titre_foncier, + date_enquete, + representant_tel, + representant_nom, + representant_prenom, + representant_npi, + date_debut_exemption, + date_fin_exemption, + zone_rfu_id + FROM enquete + ORDER BY parcelle_id, date_enquete DESC, id DESC +) ep ON ep.parcelle_id = p.id + LEFT JOIN personne pers + ON pers.id = ep.personne_id + JOIN quartier q ON q.id = p.quartier_id + JOIN arrondissement a ON a.id = q.arrondissement_id + JOIN commune c ON c.id = a.commune_id + JOIN departement d ON d.id = c.departement_id + --JOIN secteur_decoupage sd ON sd.quartier_id = q.id + JOIN ( + SELECT DISTINCT ON (quartier_id) + quartier_id, + secteur_id + FROM secteur_decoupage + ORDER BY quartier_id + ) sd ON sd.quartier_id = q.id + JOIN secteur sect ON sect.id = sd.secteur_id + JOIN section ses ON ses.id = sect.section_id + JOIN "structure" st ON st.id = ses.structure_id + JOIN batiment b ON b.parcelle_id = p.id + JOIN ( + SELECT DISTINCT ON (batiment_id) + batiment_id, + superficie_au_sol, + nombre_piscine, + categorie_batiment_id, + date_enquete, + montant_locatif_annuel_declare, + montant_locatif_annuel_calcule, + montant_locatif_annuel_estime, + date_debut_excemption, + date_fin_excemption, + valeur_batiment_reel, + valeur_batiment_calcule, + valeur_batiment_estime, + u.categorie_usage, + superficie_louee + FROM enquete_batiment eb + join usage u on u.id=eb.usage_id + ORDER BY batiment_id, date_enquete DESC, eb.id DESC +) eb ON eb.batiment_id = b.id + JOIN categorie_batiment cb + ON cb.id = eb.categorie_batiment_id + JOIN LATERAL ( + SELECT * + FROM barem_rfu_bati br + WHERE br.categorie_batiment_id = cb.id + AND br.arrondissement_id = a.id + AND (br.quartier_id = q.id OR br.quartier_id IS NULL) + ORDER BY br.quartier_id DESC NULLS LAST + LIMIT 1 +) brb ON TRUE +WHERE p.batie = TRUE + AND NOT EXISTS ( + SELECT 1 + FROM unite_logement ul + WHERE ul.batiment_id = b.id + ) + AND st.id = v_structure_id +ON CONFLICT DO NOTHING; + +GET DIAGNOSTICS v_rows_inserted = ROW_COUNT; + +RETURN v_rows_inserted; +END; +$$; */ + +CREATE OR REPLACE FUNCTION public.generer_donnees_imposition_srtb_batie( + p_impositions_tfu_id BIGINT, + p_user_id BIGINT +) + RETURNS INTEGER + LANGUAGE plpgsql +AS $$ +DECLARE + v_rows_inserted INTEGER; + v_annee BIGINT; + v_structure_id BIGINT; + + v_montant_srtb NUMERIC; + v_today DATE; +BEGIN + + v_today := CURRENT_DATE; + + -- 1. année + structure + SELECT ex.annee, it.structure_id + INTO STRICT v_annee, v_structure_id + FROM impositions_tfu it + JOIN exercice ex ON ex.id = it.exercice_id + WHERE it.id = p_impositions_tfu_id; + + -- 2. paramètre (une seule requête) + SELECT value + INTO STRICT v_montant_srtb + FROM parameters + WHERE name = 'TAXE_SRTB'; + + -- 3. INSERT optimisé (SANS DISTINCT ON, SANS UPDATE) + INSERT INTO donnees_imposition_tfu ( + annee, + code_departement, nom_departement, + code_commune, nom_commune, + code_arrondissement, nom_arrondissement, + code_quartier_village, nom_quartier_village, + q, ilot, parcelle, nup, + titre_foncier, + num_batiment, + ifu, npi, tel_prop, email_prop, + nom_prop, prenom_prop, raison_sociale, adresse_prop, + tel_sc, nom_sc, prenom_sc, + longitude, latitude, + batie, + exonere, + batiment_exonere, + standing_bat, categorie_bat, + nombre_piscine, + date_enquete, + structure_id, + zone_rfu_id, + nature_impot, + superficie_parc, + superficie_au_sol_bat, + valeur_batiment, + valeur_locative_adm_metre_carre, + montant_loyer_annuel, + tfu_metre_carre, + tfu_minimum, + impositions_tfu_id, + deleted, + created_at, + created_by, + source, + updated_at, + updated_by, + categorie_usage, + superficie_au_sol_taux_prop_parc, + valeur_locative_adm_taux_prop_parc, + tfu_calcule_taux_prop_parc, + valeur_locative_adm_sup_reel, + valeur_locative_adm, + tfu_superficie_au_sol_reel, + tfu_piscine, + montant_taxe, + taux_tfu, + parcelle_id, + batiment_id, + unite_logement_id, + superficie_au_sol_loue, + personne_id + ) + SELECT + v_annee, + d.code, d.nom, + c.code, c.nom, + a.code, a.nom, + q.code, q.nom, + p.q, p.i, p.p, p.nup, + ep.numero_titre_foncier, + b.nub, + + pers.ifu, pers.npi, pers.tel1, pers.email, + pers.nom, pers.prenom, pers.raison_sociale, pers.adresse, + ep.representant_tel, ep.representant_nom, ep.representant_prenom, + + p.longitude, p.latitude, + TRUE, + + (v_today BETWEEN ep.date_debut_exemption AND COALESCE(ep.date_fin_exemption, v_today)), + (v_today BETWEEN eb.date_debut_excemption AND COALESCE(eb.date_fin_excemption, v_today)), + + cb.standing, + cb.nom, + + COALESCE(eb.nombre_piscine, 0), + eb.date_enquete, + + st.id, + ep.zone_rfu_id, + 'SRTB', + + p.superficie, + eb.superficie_au_sol, + + -- valeur bâtiment optimisée + COALESCE( + NULLIF(eb.valeur_batiment_reel,0), + NULLIF(eb.valeur_batiment_calcule,0), + NULLIF(eb.valeur_batiment_estime,0), + 0 + ), + + brb.valeur_locative, + + -- loyer optimisé + COALESCE( + NULLIF(eb.montant_locatif_annuel_declare,0), + NULLIF(eb.montant_locatif_annuel_calcule,0), + NULLIF(eb.montant_locatif_annuel_estime,0), + 0 + ), + + brb.tfu_metre_carre, + brb.tfu_minimum, + + p_impositions_tfu_id, + FALSE, + v_today, p_user_id, 'FISCAD', + v_today, p_user_id, + eb.categorie_usage, + + 0, 0, 0, + + eb.superficie_au_sol * brb.valeur_locative, + + 0, + 0, + 0, + + -- 🔥 SRTB = valeur directe (pas de calcul) + v_montant_srtb, + + 0, + + p.id, + b.id, + NULL, + eb.superficie_louee, + ep.personne_id + + FROM parcelle p + + -- dernière enquête parcelle + LEFT JOIN LATERAL ( + SELECT * + FROM enquete e + WHERE e.parcelle_id = p.id + ORDER BY date_enquete DESC, id DESC + LIMIT 1 + ) ep ON TRUE + + LEFT JOIN personne pers ON pers.id = ep.personne_id + + JOIN quartier q ON q.id = p.quartier_id + JOIN arrondissement a ON a.id = q.arrondissement_id + JOIN commune c ON c.id = a.commune_id + JOIN departement d ON d.id = c.departement_id + + -- structure via secteur + JOIN LATERAL ( + SELECT secteur_id + FROM secteur_decoupage + WHERE quartier_id = q.id + LIMIT 1 + ) sd ON TRUE + + JOIN secteur sect ON sect.id = sd.secteur_id + JOIN section ses ON ses.id = sect.section_id + JOIN structure st ON st.id = ses.structure_id + + JOIN batiment b ON b.parcelle_id = p.id + + -- 🔥 remplace DISTINCT ON + JOIN LATERAL ( + SELECT eb2.*,u.categorie_usage + FROM enquete_batiment eb2 + LEFT JOIN usage u ON u.id = eb2.usage_id + WHERE eb2.batiment_id = b.id + ORDER BY eb2.date_enquete DESC, eb2.id DESC + LIMIT 1 + ) eb ON TRUE + + JOIN categorie_batiment cb ON cb.id = eb.categorie_batiment_id + + JOIN LATERAL ( + SELECT * + FROM barem_rfu_bati br + WHERE br.categorie_batiment_id = cb.id + AND br.arrondissement_id = a.id + AND (br.quartier_id = q.id OR br.quartier_id IS NULL) + ORDER BY br.quartier_id DESC NULLS LAST + LIMIT 1 + ) brb ON TRUE + + WHERE p.batie = TRUE + AND NOT EXISTS ( + SELECT 1 + FROM unite_logement ul + WHERE ul.batiment_id = b.id + ) + AND st.id = v_structure_id + + ON CONFLICT DO NOTHING; + + GET DIAGNOSTICS v_rows_inserted = ROW_COUNT; + + RETURN v_rows_inserted; +END; +$$; + + diff --git a/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/generer_donnees_imposition_srtb_batie_unite_logement.sql b/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/archive_generate_old/generer_donnees_imposition_srtb_batie_unite_logement.sql similarity index 100% rename from src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/generer_donnees_imposition_srtb_batie_unite_logement.sql rename to src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/archive_generate_old/generer_donnees_imposition_srtb_batie_unite_logement.sql diff --git a/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/archive_generate_old/generer_donnees_imposition_tfu_batie_old.sql b/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/archive_generate_old/generer_donnees_imposition_tfu_batie_old.sql new file mode 100644 index 0000000..bb91e9a --- /dev/null +++ b/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/archive_generate_old/generer_donnees_imposition_tfu_batie_old.sql @@ -0,0 +1,754 @@ +/*CREATE OR REPLACE FUNCTION public.generer_donnees_imposition_tfu_batie( + p_impositions_tfu_id BIGINT, + p_user_id BIGINT +) +RETURNS INTEGER +LANGUAGE plpgsql +AS +$$ +DECLARE +v_rows_inserted INTEGER; + v_annee BIGINT; + v_structure_id BIGINT; + v_taux_defaut_sup_sol NUMERIC; + v_taux_tfu NUMERIC; + v_taux_valeur_locat_prof NUMERIC; + v_tfu_piscine_unitaire NUMERIC; +BEGIN + +-- récupération de l'année +SELECT ex.annee, it.structure_id +INTO STRICT v_annee, v_structure_id +FROM impositions_tfu it + join exercice ex on ex.id =it.exercice_id +WHERE it.id = p_impositions_tfu_id; + + +select value +into strict v_taux_defaut_sup_sol +from parameters +where name ='TAUX_DEFAUT_SUPERFICIE_AU_SOL'; + +select value +into STRICT v_taux_tfu +from parameters +where name ='TAUX_TFU'; + + +select value +into STRICT v_taux_valeur_locat_prof +from parameters +where name ='TAUX_VALEUR_LOCATIVE_PROFESSIONNELLE'; + +select value +into STRICT v_tfu_piscine_unitaire +from parameters +where name ='TFU_PAR_PISCINE'; + + +INSERT INTO donnees_imposition_tfu( + annee, + code_departement, + nom_departement, + code_commune, + nom_commune, + code_arrondissement, + nom_arrondissement, + code_quartier_village, + nom_quartier_village, + q, + ilot, + parcelle, + nup, + titre_foncier, + num_batiment, + ifu, + npi, + tel_prop, + email_prop, + nom_prop, + prenom_prop, + raison_sociale, + adresse_prop, + tel_sc, + nom_sc, + prenom_sc, + longitude, + latitude, + batie, + exonere, + batiment_exonere, + standing_bat, + categorie_bat, + nombre_piscine, + date_enquete, + structure_id, + zone_rfu_id, + nature_impot, + superficie_parc, + superficie_au_sol_bat, + valeur_batiment, + valeur_locative_adm_metre_carre, + montant_loyer_annuel, + tfu_metre_carre, + tfu_minimum, + impositions_tfu_id, + deleted, + created_at , + created_by , + "source", + updated_at , + updated_by, + categorie_usage, + superficie_au_sol_taux_prop_parc, ---70% de la surperficie au sol de la parcelle + valeur_locative_adm_taux_prop_parc, + tfu_calcule_taux_prop_parc, ----tfu correspondant au 70% + valeur_locative_adm_sup_reel, + valeur_locative_adm, ----------valeur locative administrative + tfu_superficie_au_sol_reel, ----tfu correspondant à la superficie au sol reelle + tfu_piscine, + montant_taxe, ----tfu finale + taux_tfu, ----taux tfu batie + parcelle_id, + batiment_id, + unite_logement_id +) +SELECT + v_annee, + d.code, + d.nom, + c.code, + c.nom, + a.code, + a.nom, + q.code, + q.nom, + p.q, + p.i, + p.p, + p.nup, + ep.numero_titre_foncier, + b.nub, + pers.ifu, + pers.npi, + pers.tel1, + pers.email, + pers.nom, + pers.prenom, + pers.raison_sociale, + pers.adresse, + ep.representant_tel, + ep.representant_nom, + ep.representant_prenom, + p.longitude, + p.latitude, + TRUE, + ( + CURRENT_DATE >= ep.date_debut_exemption + AND CURRENT_DATE <= COALESCE(ep.date_fin_exemption, CURRENT_DATE) + ), + ( + CURRENT_DATE >= eb.date_debut_excemption + AND CURRENT_DATE <= COALESCE(eb.date_fin_excemption, CURRENT_DATE) + ), + cb.standing, + cb.nom, + eb.nombre_piscine, + eb.date_enquete, + st.id, + ep.zone_rfu_id, + 'TFU', + p.superficie, + eb.superficie_au_sol, + COALESCE( + NULLIF(eb.valeur_batiment_reel, 0), + NULLIF(eb.valeur_batiment_calcule, 0), + NULLIF(eb.valeur_batiment_estime, 0), + 0 + ), + brb.valeur_locative, + COALESCE( + NULLIF(eb.montant_locatif_annuel_declare, 0), + NULLIF(eb.montant_locatif_annuel_calcule, 0), + NULLIF(eb.montant_locatif_annuel_estime, 0), + 0 + ), + brb.tfu_metre_carre, + brb.tfu_minimum, + p_impositions_tfu_id, + false, + current_date , + p_user_id , + 'FISCAD', + current_date , + p_user_id, + eb.categorie_usage, + p.superficie*v_taux_defaut_sup_sol/100,---superficie_au_sol_70pour100 + case ----valeur_locative_adm70pour100 + when eb.categorie_usage = 'HABITATION' then (p.superficie * v_taux_defaut_sup_sol/100) * brb.valeur_locative + else 0 + end, + case ----tfu calcule 70 pour 100 superficie parcelle + when eb.categorie_usage= 'HABITATION' then (p.superficie * v_taux_defaut_sup_sol/100) * brb.valeur_locative * v_taux_tfu/100 + else 0 + end, + case -----valeur_locative_adm_sup_reel + when eb.categorie_usage='HABITATION' then eb.superficie_au_sol * brb.valeur_locative + else 0 + end, + 0, ------ valeur_locative_adm : en attente de update + case -----tfu_superficie_au_sol_reel + when eb.categorie_usage='HABITATION' then eb.superficie_au_sol * brb.valeur_locative * v_taux_tfu/100 +eb.nombre_piscine * v_tfu_piscine_unitaire + else 0 + end, + eb.nombre_piscine * v_tfu_piscine_unitaire, + 0, + v_taux_tfu, + p.id, + b.id, + null +FROM parcelle p + LEFT JOIN ( + SELECT DISTINCT ON (parcelle_id) + parcelle_id, + superficie, + personne_id, + numero_titre_foncier, + date_enquete, + representant_tel, + representant_nom, + representant_prenom, + representant_npi, + date_debut_exemption, + date_fin_exemption, + zone_rfu_id + FROM enquete + ORDER BY parcelle_id, date_enquete DESC, id DESC +) ep ON ep.parcelle_id = p.id + LEFT JOIN personne pers + ON pers.id = ep.personne_id + JOIN quartier q ON q.id = p.quartier_id + JOIN arrondissement a ON a.id = q.arrondissement_id + JOIN commune c ON c.id = a.commune_id + JOIN departement d ON d.id = c.departement_id + --JOIN secteur_decoupage sd ON sd.quartier_id = q.id + JOIN ( + SELECT DISTINCT ON (quartier_id) + quartier_id, + secteur_id + FROM secteur_decoupage + ORDER BY quartier_id + ) sd ON sd.quartier_id = q.id + JOIN secteur sect ON sect.id = sd.secteur_id + JOIN section ses ON ses.id = sect.section_id + JOIN "structure" st ON st.id = ses.structure_id + JOIN batiment b ON b.parcelle_id = p.id + JOIN ( + SELECT DISTINCT ON (batiment_id) + batiment_id, + superficie_au_sol, + nombre_piscine, + categorie_batiment_id, + date_enquete, + montant_locatif_annuel_declare, + montant_locatif_annuel_calcule, + montant_locatif_annuel_estime, + date_debut_excemption, + date_fin_excemption, + valeur_batiment_reel, + valeur_batiment_calcule, + valeur_batiment_estime, + u.categorie_usage + FROM enquete_batiment eb + join usage u on u.id=eb.usage_id + ORDER BY batiment_id, date_enquete DESC, eb.id DESC +) eb ON eb.batiment_id = b.id + + JOIN categorie_batiment cb + ON cb.id = eb.categorie_batiment_id + JOIN LATERAL ( + SELECT * + FROM barem_rfu_bati br + WHERE br.categorie_batiment_id = cb.id + AND br.arrondissement_id = a.id + AND (br.quartier_id = q.id OR br.quartier_id IS NULL) + ORDER BY br.quartier_id DESC NULLS LAST + LIMIT 1 +) brb ON TRUE +WHERE p.batie = TRUE + AND NOT EXISTS ( + SELECT 1 + FROM unite_logement ul + WHERE ul.batiment_id = b.id + ) + AND st.id = v_structure_id +ON CONFLICT DO NOTHING; + +GET DIAGNOSTICS v_rows_inserted = ROW_COUNT; + +UPDATE donnees_imposition_tfu dtfu +SET + valeur_locative_adm = + CASE + WHEN categorie_usage = 'HABITATION' AND superficie_au_sol_bat <> 0 + THEN valeur_locative_adm_sup_reel + + WHEN categorie_usage = 'HABITATION' AND superficie_au_sol_bat = 0 + THEN valeur_locative_adm_taux_prop_parc + + WHEN categorie_usage IN ('PROFESSIONNELLE','MIXTE') AND valeur_batiment <> 0 + THEN valeur_batiment * (v_taux_valeur_locat_prof/100) + + WHEN categorie_usage IN ('PROFESSIONNELLE','MIXTE') AND valeur_batiment = 0 + THEN montant_loyer_annuel + END, + + montant_taxe = + CASE + WHEN categorie_usage = 'HABITATION' AND superficie_au_sol_bat <> 0 THEN + CASE + WHEN tfu_minimum < valeur_locative_adm_sup_reel * (v_taux_tfu/100) + tfu_piscine + THEN valeur_locative_adm_sup_reel * (v_taux_tfu/100) + tfu_piscine + ELSE tfu_minimum + END + + WHEN categorie_usage = 'HABITATION' AND superficie_au_sol_bat = 0 THEN + CASE + WHEN tfu_minimum < valeur_locative_adm_taux_prop_parc * (v_taux_tfu/100) + tfu_piscine + THEN valeur_locative_adm_taux_prop_parc * (v_taux_tfu/100) + tfu_piscine + ELSE tfu_minimum + END + + WHEN categorie_usage IN ('PROFESSIONNELLE','MIXTE') AND valeur_batiment <> 0 THEN + CASE + WHEN tfu_minimum < valeur_batiment * (v_taux_valeur_locat_prof/100) * (v_taux_tfu/100) + THEN valeur_batiment * (v_taux_valeur_locat_prof/100) * (v_taux_tfu/100) + ELSE tfu_minimum + END + + WHEN categorie_usage IN ('PROFESSIONNELLE','MIXTE') AND valeur_batiment = 0 THEN + CASE + WHEN tfu_minimum < montant_loyer_annuel * (v_taux_tfu/100) + THEN montant_loyer_annuel * (v_taux_tfu/100) + ELSE tfu_minimum + END + END +WHERE impositions_tfu_id = p_impositions_tfu_id + AND batie = TRUE + AND NOT EXISTS ( + SELECT 1 + FROM unite_logement ul + WHERE ul.batiment_id = dtfu.batiment_id +); +RETURN v_rows_inserted; +END; +$$;*/ + +CREATE OR REPLACE FUNCTION public.generer_donnees_imposition_tfu_batie( + p_impositions_tfu_id BIGINT, + p_user_id BIGINT +) + RETURNS INTEGER + LANGUAGE plpgsql +AS $$ +DECLARE + v_rows_inserted INTEGER; + v_annee BIGINT; + v_structure_id BIGINT; + v_taux_defaut_sup_sol NUMERIC; + v_taux_tfu NUMERIC; + v_taux_tfu_ratio NUMERIC; -- v_taux_tfu / 100 (pré-calculé) + v_taux_valeur_locat_prof NUMERIC; + v_taux_vlp_ratio NUMERIC; -- v_taux_valeur_locat_prof / 100 (pré-calculé) + v_tfu_piscine_unitaire NUMERIC; + v_today DATE; +BEGIN + + v_today := CURRENT_DATE; + + -- ------------------------------------------------------------------------- + -- 1. Récupération de l'année et de la structure (inchangée) + -- ------------------------------------------------------------------------- + SELECT ex.annee, it.structure_id + INTO STRICT v_annee, v_structure_id + FROM impositions_tfu it + JOIN exercice ex ON ex.id = it.exercice_id + WHERE it.id = p_impositions_tfu_id; + + -- ------------------------------------------------------------------------- + -- 2. Récupération des 4 paramètres en UNE seule requête + -- (évite 4 accès séquentiels à la table parameters) + -- ------------------------------------------------------------------------- + SELECT + MAX(value) FILTER (WHERE name = 'TAUX_DEFAUT_SUPERFICIE_AU_SOL'), + MAX(value) FILTER (WHERE name = 'TAUX_TFU'), + MAX(value) FILTER (WHERE name = 'TAUX_VALEUR_LOCATIVE_PROFESSIONNELLE'), + MAX(value) FILTER (WHERE name = 'TFU_PAR_PISCINE') + INTO STRICT + v_taux_defaut_sup_sol, + v_taux_tfu, + v_taux_valeur_locat_prof, + v_tfu_piscine_unitaire + FROM parameters + WHERE name IN ( + 'TAUX_DEFAUT_SUPERFICIE_AU_SOL', + 'TAUX_TFU', + 'TAUX_VALEUR_LOCATIVE_PROFESSIONNELLE', + 'TFU_PAR_PISCINE' + ); + + -- Ratios pré-calculés pour éviter la division répétée dans le SELECT + v_taux_tfu_ratio := v_taux_tfu / 100.0; + v_taux_vlp_ratio := v_taux_valeur_locat_prof / 100.0; + + -- ------------------------------------------------------------------------- + -- 3. INSERT avec calcul complet de valeur_locative_adm et montant_taxe + -- → supprime l'UPDATE post-INSERT (économie d'un second scan de table) + -- ------------------------------------------------------------------------- + INSERT INTO donnees_imposition_tfu ( + annee, + code_departement, + nom_departement, + code_commune, + nom_commune, + code_arrondissement, + nom_arrondissement, + code_quartier_village, + nom_quartier_village, + q, + ilot, + parcelle, + nup, + titre_foncier, + num_batiment, + ifu, + npi, + tel_prop, + email_prop, + nom_prop, + prenom_prop, + raison_sociale, + adresse_prop, + tel_sc, + nom_sc, + prenom_sc, + longitude, + latitude, + batie, + exonere, + batiment_exonere, + standing_bat, + categorie_bat, + nombre_piscine, + date_enquete, + structure_id, + zone_rfu_id, + nature_impot, + superficie_parc, + superficie_au_sol_bat, + valeur_batiment, + valeur_locative_adm_metre_carre, + montant_loyer_annuel, + tfu_metre_carre, + tfu_minimum, + impositions_tfu_id, + deleted, + created_at, + created_by, + "source", + updated_at, + updated_by, + categorie_usage, + superficie_au_sol_taux_prop_parc, -- 70 % superficie parcelle + valeur_locative_adm_taux_prop_parc, + tfu_calcule_taux_prop_parc, -- TFU à 70 % + valeur_locative_adm_sup_reel, + valeur_locative_adm, -- valeur locative administrative finale + tfu_superficie_au_sol_reel, + tfu_piscine, + montant_taxe, -- TFU finale + taux_tfu, + parcelle_id, + batiment_id, + unite_logement_id, + personne_id + ) + SELECT + v_annee, + d.code, + d.nom, + c.code, + c.nom, + a.code, + a.nom, + q.code, + q.nom, + p.q, + p.i, + p.p, + p.nup, + ep.numero_titre_foncier, + b.nub, + pers.ifu, + pers.npi, + pers.tel1, + pers.email, + pers.nom, + pers.prenom, + pers.raison_sociale, + pers.adresse, + ep.representant_tel, + ep.representant_nom, + ep.representant_prenom, + p.longitude, + p.latitude, + TRUE, + -- exonere parcelle + (v_today BETWEEN ep.date_debut_exemption + AND COALESCE(ep.date_fin_exemption, v_today)), + -- exonere batiment + (v_today BETWEEN eb.date_debut_excemption + AND COALESCE(eb.date_fin_excemption, v_today)), + cb.standing, + cb.nom, + eb.nombre_piscine, + eb.date_enquete, + st.id, + ep.zone_rfu_id, + 'TFU', + p.superficie, + eb.superficie_au_sol, + -- valeur_batiment : première valeur non nulle non zéro + COALESCE( + NULLIF(eb.valeur_batiment_reel, 0), + NULLIF(eb.valeur_batiment_calcule, 0), + NULLIF(eb.valeur_batiment_estime, 0), + 0 + ), + brb.valeur_locative, + -- montant_loyer_annuel + COALESCE( + NULLIF(eb.montant_locatif_annuel_declare, 0), + NULLIF(eb.montant_locatif_annuel_calcule, 0), + NULLIF(eb.montant_locatif_annuel_estime, 0), + 0 + ), + brb.tfu_metre_carre, + brb.tfu_minimum, + p_impositions_tfu_id, + FALSE, + v_today, + p_user_id, + 'FISCAD', + v_today, + p_user_id, + eb.categorie_usage, + + -- superficie_au_sol_taux_prop_parc (70 % parcelle) + p.superficie * v_taux_defaut_sup_sol / 100.0, + + -- valeur_locative_adm_taux_prop_parc + CASE WHEN eb.categorie_usage = 'HABITATION' + THEN (p.superficie * v_taux_defaut_sup_sol / 100.0) * brb.valeur_locative + ELSE 0 + END, + + -- tfu_calcule_taux_prop_parc + CASE WHEN eb.categorie_usage = 'HABITATION' + THEN (p.superficie * v_taux_defaut_sup_sol / 100.0) * brb.valeur_locative * v_taux_tfu_ratio + ELSE 0 + END, + + -- valeur_locative_adm_sup_reel + CASE WHEN eb.categorie_usage = 'HABITATION' + THEN eb.superficie_au_sol * brb.valeur_locative + ELSE 0 + END, + + -- --------------------------------------------------------------- + -- 🔧 CORRECTION : valeur_locative_adm avec tests explicites + -- --------------------------------------------------------------- + CASE + WHEN eb.categorie_usage = 'HABITATION' + AND eb.superficie_au_sol <> 0 + THEN eb.superficie_au_sol * brb.valeur_locative + + WHEN eb.categorie_usage = 'HABITATION' + AND eb.superficie_au_sol = 0 + THEN (p.superficie * v_taux_defaut_sup_sol / 100.0) * brb.valeur_locative + + -- ✅ Test explicite : valeur_batiment <> 0 + WHEN eb.categorie_usage IN ('PROFESSIONNELLE', 'MIXTE') + AND COALESCE(NULLIF(eb.valeur_batiment_reel, 0), + NULLIF(eb.valeur_batiment_calcule, 0), + NULLIF(eb.valeur_batiment_estime, 0), 0) <> 0 + THEN COALESCE(NULLIF(eb.valeur_batiment_reel, 0), + NULLIF(eb.valeur_batiment_calcule, 0), + NULLIF(eb.valeur_batiment_estime, 0), 0) + * v_taux_vlp_ratio + + -- ✅ Test explicite : valeur_batiment = 0 + WHEN eb.categorie_usage IN ('PROFESSIONNELLE', 'MIXTE') + AND COALESCE(NULLIF(eb.valeur_batiment_reel, 0), + NULLIF(eb.valeur_batiment_calcule, 0), + NULLIF(eb.valeur_batiment_estime, 0), 0) = 0 + THEN COALESCE(NULLIF(eb.montant_locatif_annuel_declare, 0), + NULLIF(eb.montant_locatif_annuel_calcule, 0), + NULLIF(eb.montant_locatif_annuel_estime, 0), 0) + + ELSE 0 + END, + + -- tfu_superficie_au_sol_reel + CASE WHEN eb.categorie_usage = 'HABITATION' + THEN eb.superficie_au_sol * brb.valeur_locative * v_taux_tfu_ratio * eb.nombre_piscine * v_tfu_piscine_unitaire + ELSE 0 + END, + + -- tfu_piscine + eb.nombre_piscine * v_tfu_piscine_unitaire, + + -- --------------------------------------------------------------- + -- montant_taxe ← calculé directement (plus d'UPDATE) + -- Utilise des CTE inline via expression pour éviter la redondance + -- --------------------------------------------------------------- + ( + -- On matérialise valeur_batiment et valeur_locative une seule fois + WITH calc AS ( + SELECT + COALESCE(NULLIF(eb.valeur_batiment_reel, 0), + NULLIF(eb.valeur_batiment_calcule, 0), + NULLIF(eb.valeur_batiment_estime, 0), 0) AS vb, + COALESCE(NULLIF(eb.montant_locatif_annuel_declare, 0), + NULLIF(eb.montant_locatif_annuel_calcule, 0), + NULLIF(eb.montant_locatif_annuel_estime, 0), 0) AS loyer, + eb.superficie_au_sol * brb.valeur_locative AS vla_reel, + (p.superficie * v_taux_defaut_sup_sol / 100.0) + * brb.valeur_locative AS vla_70 + ) + SELECT + CASE + WHEN eb.categorie_usage = 'HABITATION' + AND eb.superficie_au_sol <> 0 + THEN GREATEST(brb.tfu_minimum, + calc.vla_reel * v_taux_tfu_ratio + + eb.nombre_piscine * v_tfu_piscine_unitaire) + + WHEN eb.categorie_usage = 'HABITATION' + AND eb.superficie_au_sol = 0 + THEN GREATEST(brb.tfu_minimum, + calc.vla_70 * v_taux_tfu_ratio + + eb.nombre_piscine * v_tfu_piscine_unitaire) + + WHEN eb.categorie_usage IN ('PROFESSIONNELLE', 'MIXTE') + AND calc.vb <> 0 + THEN GREATEST(brb.tfu_minimum, + calc.vb * v_taux_vlp_ratio * v_taux_tfu_ratio) + + WHEN eb.categorie_usage IN ('PROFESSIONNELLE', 'MIXTE') + AND calc.vb = 0 + THEN GREATEST(brb.tfu_minimum, + calc.loyer * v_taux_tfu_ratio) + + ELSE brb.tfu_minimum + END + FROM calc + ), + v_taux_tfu, + p.id, + b.id, + NULL, + ep.personne_id + FROM parcelle p + -- Dernière enquête parcelle + LEFT JOIN LATERAL ( + SELECT + parcelle_id, + superficie, + personne_id, + numero_titre_foncier, + date_enquete, + representant_tel, + representant_nom, + representant_prenom, + representant_npi, + date_debut_exemption, + date_fin_exemption, + zone_rfu_id + FROM enquete + WHERE parcelle_id = p.id + ORDER BY date_enquete DESC, id DESC + LIMIT 1 + ) ep ON TRUE + + LEFT JOIN personne pers ON pers.id = ep.personne_id + + JOIN quartier q ON q.id = p.quartier_id + JOIN arrondissement a ON a.id = q.arrondissement_id + JOIN commune c ON c.id = a.commune_id + JOIN departement d ON d.id = c.departement_id + + -- Rattachement structure via secteur (DISTINCT ON → LATERAL plus lisible) + JOIN LATERAL ( + SELECT secteur_id + FROM secteur_decoupage + WHERE quartier_id = q.id + ORDER BY quartier_id + LIMIT 1 + ) sd ON TRUE + JOIN secteur sect ON sect.id = sd.secteur_id + JOIN section ses ON ses.id = sect.section_id + JOIN "structure" st ON st.id = ses.structure_id + + -- Bâtiments sans unités logement (anti-join via LEFT JOIN … IS NULL) + JOIN batiment b ON b.parcelle_id = p.id + LEFT JOIN unite_logement ul_filter ON ul_filter.batiment_id = b.id + + -- Dernière enquête bâtiment + JOIN LATERAL ( + SELECT + eb2.batiment_id, + eb2.superficie_au_sol, + eb2.nombre_piscine, + eb2.categorie_batiment_id, + eb2.date_enquete, + eb2.montant_locatif_annuel_declare, + eb2.montant_locatif_annuel_calcule, + eb2.montant_locatif_annuel_estime, + eb2.date_debut_excemption, + eb2.date_fin_excemption, + eb2.valeur_batiment_reel, + eb2.valeur_batiment_calcule, + eb2.valeur_batiment_estime, + u.categorie_usage + FROM enquete_batiment eb2 + JOIN usage u ON u.id = eb2.usage_id + WHERE eb2.batiment_id = b.id + ORDER BY eb2.date_enquete DESC, eb2.id DESC + LIMIT 1 + ) eb ON TRUE + + JOIN categorie_batiment cb ON cb.id = eb.categorie_batiment_id + + -- Barème RFU bâti (inchangé) + JOIN LATERAL ( + SELECT * + FROM barem_rfu_bati br + WHERE br.categorie_batiment_id = cb.id + AND br.arrondissement_id = a.id + AND (br.quartier_id = q.id OR br.quartier_id IS NULL) + ORDER BY br.quartier_id DESC NULLS LAST + LIMIT 1 + ) brb ON TRUE + + WHERE p.batie = TRUE + AND ul_filter.batiment_id IS NULL -- anti-join : pas d'unité logement + AND st.id = v_structure_id + + ON CONFLICT DO NOTHING; + + GET DIAGNOSTICS v_rows_inserted = ROW_COUNT; + + RETURN v_rows_inserted; +END; +$$; diff --git a/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/archive_generate_old/generer_donnees_imposition_tfu_batie_unite_logement_old.sql b/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/archive_generate_old/generer_donnees_imposition_tfu_batie_unite_logement_old.sql new file mode 100644 index 0000000..8bd6525 --- /dev/null +++ b/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/archive_generate_old/generer_donnees_imposition_tfu_batie_unite_logement_old.sql @@ -0,0 +1,855 @@ +/*CREATE OR REPLACE FUNCTION public.generer_donnees_imposition_tfu_batie_unite_logement( + p_impositions_tfu_id BIGINT, + p_user_id BIGINT +) +RETURNS INTEGER +LANGUAGE plpgsql +AS +$$ +DECLARE +v_rows_inserted INTEGER; + v_annee BIGINT; + v_structure_id BIGINT; + v_taux_defaut_sup_sol NUMERIC; + v_taux_tfu NUMERIC; + v_taux_valeur_locat_prof NUMERIC; + v_tfu_piscine_unitaire NUMERIC; +BEGIN + +-- récupération de l'année +SELECT ex.annee, it.structure_id +INTO STRICT v_annee, v_structure_id +FROM impositions_tfu it + join exercice ex on ex.id =it.exercice_id +WHERE it.id = p_impositions_tfu_id; + + +select value +into strict v_taux_defaut_sup_sol +from parameters +where name ='TAUX_DEFAUT_SUPERFICIE_AU_SOL'; + +select value +into STRICT v_taux_tfu +from parameters +where name ='TAUX_TFU'; + +RAISE NOTICE 'v_taux_tfu = %', v_taux_tfu; + +select value +into STRICT v_taux_valeur_locat_prof +from parameters +where name ='TAUX_VALEUR_LOCATIVE_PROFESSIONNELLE'; + +select value +into STRICT v_tfu_piscine_unitaire +from parameters +where name ='TFU_PAR_PISCINE'; + +INSERT INTO donnees_imposition_tfu( + annee, + code_departement, + nom_departement, + code_commune, + nom_commune, + code_arrondissement, + nom_arrondissement, + code_quartier_village, + nom_quartier_village, + q, + ilot, + parcelle, + nup, + titre_foncier, + num_batiment, + num_unite_logement, + ifu, + npi, + tel_prop, + email_prop, + nom_prop, + prenom_prop, + raison_sociale, + adresse_prop, + tel_sc, + nom_sc, + prenom_sc, + longitude, + latitude, + batie, + exonere, + batiment_exonere, + unite_logement_exonere, + standing_bat, + categorie_bat, + nombre_piscine, + date_enquete, + structure_id, + zone_rfu_id, + nature_impot, + superficie_parc, + superficie_au_sol_bat, + superficie_au_sol_ulog, + valeur_batiment, + valeur_locative_adm_metre_carre, + montant_loyer_annuel, + tfu_metre_carre, + tfu_minimum, + impositions_tfu_id, + deleted, + created_at , + created_by , + "source", + updated_at , + updated_by, + categorie_usage, + superficie_au_sol_taux_prop_parc, ---70% de la surperficie au sol de la parcelle + valeur_locative_adm_taux_prop_parc, + tfu_calcule_taux_prop_parc, ----tfu correspondant au 70% + valeur_locative_adm_sup_reel, + valeur_locative_adm, ----------valeur locative administrative + tfu_superficie_au_sol_reel, ----tfu correspondant à la superficie au sol reelle + tfu_piscine, + montant_taxe, ----tfu finale + taux_tfu, ----taux tfu batie + parcelle_id, + batiment_id, + unite_logement_id +) +SELECT + v_annee, + d.code, + d.nom, + c.code, + c.nom, + a.code, + a.nom, + q.code, + q.nom, + p.q, + p.i, + p.p, + p.nup, + ep.numero_titre_foncier, + b.nub, + ul.nul, + eul.ifu, + eul.npi, + eul.tel1, + eul.email, + eul.nom, + eul.prenom, + eul.raison_sociale, + eul.adresse, + eul.representant_tel, + eul.representant_nom, + eul.representant_prenom, + p.longitude, + p.latitude, + TRUE, + ( + CURRENT_DATE >= ep.date_debut_exemption + AND CURRENT_DATE <= COALESCE(ep.date_fin_exemption, CURRENT_DATE) + ), + ( + CURRENT_DATE >= eb.date_debut_excemption + AND CURRENT_DATE <= COALESCE(eb.date_fin_excemption, CURRENT_DATE) + ), + ( + CURRENT_DATE >= eul.date_debut_exemption + AND CURRENT_DATE <= COALESCE(eul.date_fin_exemption, CURRENT_DATE) + ), + cb.standing, + cb.nom, + CASE + WHEN eul.nombre_piscine is null then 0 + else eul.nombre_piscine + END, + eul.date_enquete, + st.id, + ep.zone_rfu_id, + 'TFU', + p.superficie, + eb.superficie_au_sol, + eul.superficie_au_sol, + CASE -------valeur_batiment + WHEN eul.valeur_unite_logement_reel IS NOT NULL AND eul.valeur_unite_logement_reel <> 0 THEN eul.valeur_unite_logement_reel + WHEN eul.valeur_unite_logement_calcule IS NOT NULL AND eul.valeur_unite_logement_calcule <> 0 THEN eul.valeur_unite_logement_calcule + WHEN eul.valeur_unite_logement_estime IS NOT NULL AND eul.valeur_unite_logement_estime <> 0 THEN eul.valeur_unite_logement_estime + ELSE 0 + END, + brb.valeur_locative, + CASE ----- montant_loyer_annuel + WHEN eul.montant_locatif_annuel_declare IS NOT NULL AND eul.montant_locatif_annuel_declare <> 0 THEN eul.montant_locatif_annuel_declare + WHEN eul.montant_locatif_annuel_calcule IS NOT NULL AND eul.montant_locatif_annuel_calcule <> 0 THEN eul.montant_locatif_annuel_calcule + WHEN eul.montant_locatif_annuel_estime IS NOT NULL AND eul.montant_locatif_annuel_estime <> 0 THEN eul.montant_locatif_annuel_estime + ELSE 0 + END, + brb.tfu_metre_carre, + brb.tfu_minimum, + p_impositions_tfu_id, + false, + current_date, + p_user_id, + 'FISCAD', + current_date, + p_user_id, + eul.categorie_usage, + p.superficie * v_taux_defaut_sup_sol/100,---superficie_au_sol_70pour100 + case ----valeur_locative_adm70pour100 + when eul.categorie_usage = 'HABITATION' then (p.superficie * v_taux_defaut_sup_sol/100) * brb.valeur_locative + else 0 + end, + case ----tfu calcule 70 pour 100 superficie parcelle + when eul.categorie_usage= 'HABITATION' then (p.superficie * v_taux_defaut_sup_sol/100) * brb.valeur_locative * v_taux_tfu/100 + else 0 + end, + case -----valeur_locative_adm_sup_reel + when eul.categorie_usage='HABITATION' then eul.superficie_au_sol * brb.valeur_locative + else 0 + end, + 0, ------ valeur_locative_adm : en attente de update + case -----tfu_superficie_au_sol_reel + when eul.categorie_usage='HABITATION' then eul.superficie_au_sol * brb.valeur_locative * 6/100 + else 0 + end, + CASE + WHEN eul.nombre_piscine is null then 0 + else eul.nombre_piscine * v_tfu_piscine_unitaire + END, + 0, + v_taux_tfu, + p.id, + b.id, + ul.id +FROM parcelle p + LEFT JOIN ( + SELECT DISTINCT ON (parcelle_id) + parcelle_id, + superficie, + personne_id, + numero_titre_foncier, + date_enquete, + representant_tel, + representant_nom, + representant_prenom, + representant_npi, + date_debut_exemption, + date_fin_exemption, + zone_rfu_id + FROM enquete + ORDER BY parcelle_id, date_enquete DESC, id DESC +) ep ON ep.parcelle_id = p.id + LEFT JOIN personne pers + ON pers.id = ep.personne_id + JOIN quartier q ON q.id = p.quartier_id + JOIN arrondissement a ON a.id = q.arrondissement_id + JOIN commune c ON c.id = a.commune_id + JOIN departement d ON d.id = c.departement_id + --JOIN secteur_decoupage sd ON sd.quartier_id = q.id + JOIN ( + SELECT DISTINCT ON (quartier_id) + quartier_id, + secteur_id + FROM secteur_decoupage + ORDER BY quartier_id + ) sd ON sd.quartier_id = q.id + JOIN secteur sect ON sect.id = sd.secteur_id + JOIN section ses ON ses.id = sect.section_id + JOIN "structure" st ON st.id = ses.structure_id + JOIN batiment b ON b.parcelle_id = p.id + JOIN ( + SELECT DISTINCT ON (batiment_id) + batiment_id, + superficie_au_sol, + nombre_piscine, + categorie_batiment_id, + date_enquete, + montant_locatif_annuel_declare, + montant_locatif_annuel_calcule, + montant_locatif_annuel_estime, + date_debut_excemption, + date_fin_excemption, + valeur_batiment_reel, + valeur_batiment_calcule, + valeur_batiment_estime, + u.categorie_usage + FROM enquete_batiment eb + join usage u on u.id=eb.usage_id + ORDER BY batiment_id, date_enquete DESC, eb.id DESC +) eb ON eb.batiment_id = b.id + JOIN unite_logement ul on ul.batiment_id = b.id + JOIN ( + SELECT DISTINCT ON (eult.unite_logement_id) + eult.unite_logement_id, + pers1.id, + pers1.ifu, + pers1.npi, + pers1.tel1, + pers1.email, + pers1.nom, + pers1.prenom, + pers1.raison_sociale, + pers1.adresse, + eult.nombre_piscine, + eult.categorie_batiment_id, + eult.superficie_au_sol, + eult.superficie_louee, + eult.nbre_piece, + eult.date_enquete, + eult.montant_locatif_annuel_calcule, + eult.montant_locatif_annuel_declare, + eult.montant_locatif_annuel_estime, + eult.date_debut_exemption, + eult.date_fin_exemption, + eult.representant_nom, + eult.representant_prenom, + eult.representant_tel, + eult.valeur_unite_logement_reel, + eult.valeur_unite_logement_calcule, + eult.valeur_unite_logement_estime, + u.categorie_usage + FROM enquete_unite_logement eult + join usage u on u.id=eult.usage_id + left join personne pers1 on pers1.id = eult.personne_id + ORDER BY unite_logement_id, date_enquete DESC, eult.id DESC +) eul ON eul.unite_logement_id = ul.id + JOIN categorie_batiment cb + ON cb.id = eul.categorie_batiment_id + JOIN LATERAL ( + SELECT * + FROM barem_rfu_bati br + WHERE br.categorie_batiment_id = cb.id + AND br.arrondissement_id = a.id + AND (br.quartier_id = q.id OR br.quartier_id IS NULL) + ORDER BY br.quartier_id DESC NULLS LAST + LIMIT 1 +) brb ON TRUE +WHERE p.batie = TRUE + AND EXISTS ( + SELECT 1 + FROM unite_logement ul + WHERE ul.batiment_id = b.id + ) + AND st.id = v_structure_id +ON CONFLICT DO NOTHING; + +GET DIAGNOSTICS v_rows_inserted = ROW_COUNT; + +UPDATE donnees_imposition_tfu dtfu +SET + valeur_locative_adm = + CASE + WHEN categorie_usage = 'HABITATION' AND superficie_au_sol_ulog <> 0 + THEN valeur_locative_adm_sup_reel + + WHEN categorie_usage = 'HABITATION' AND superficie_au_sol_ulog = 0 + THEN valeur_locative_adm_taux_prop_parc + + WHEN categorie_usage IN ('PROFESSIONNELLE','MIXTE') AND valeur_batiment <> 0 + THEN valeur_batiment * (v_taux_valeur_locat_prof/100) + + WHEN categorie_usage IN ('PROFESSIONNELLE','MIXTE') AND valeur_batiment = 0 + THEN montant_loyer_annuel + END, + + montant_taxe = + CASE + WHEN categorie_usage = 'HABITATION' AND superficie_au_sol_ulog <> 0 THEN + CASE + WHEN tfu_minimum < valeur_locative_adm_sup_reel * (v_taux_tfu/100) + tfu_piscine + THEN valeur_locative_adm_sup_reel * (v_taux_tfu/100) + tfu_piscine + ELSE tfu_minimum + END + + WHEN categorie_usage = 'HABITATION' AND superficie_au_sol_ulog = 0 THEN + CASE + WHEN tfu_minimum < valeur_locative_adm_taux_prop_parc * (v_taux_tfu/100) + tfu_piscine + THEN valeur_locative_adm_taux_prop_parc * (v_taux_tfu/100) + tfu_piscine + ELSE tfu_minimum + END + + WHEN categorie_usage IN ('PROFESSIONNELLE','MIXTE') AND valeur_batiment <> 0 THEN + CASE + WHEN tfu_minimum < valeur_batiment * (v_taux_valeur_locat_prof/100) * (v_taux_tfu/100) + THEN valeur_batiment * (v_taux_valeur_locat_prof/100) * (v_taux_tfu/100) + ELSE tfu_minimum + END + + WHEN categorie_usage IN ('PROFESSIONNELLE','MIXTE') AND valeur_batiment = 0 THEN + CASE + WHEN tfu_minimum < montant_loyer_annuel * (v_taux_tfu/100) + THEN montant_loyer_annuel * (v_taux_tfu/100) + ELSE tfu_minimum + END + END +WHERE impositions_tfu_id = p_impositions_tfu_id + AND batie = TRUE + AND EXISTS ( + SELECT 1 + FROM unite_logement ul + WHERE ul.batiment_id = dtfu.batiment_id +); +RETURN v_rows_inserted; +END; +$$;*/ +CREATE OR REPLACE FUNCTION public.generer_donnees_imposition_tfu_batie_unite_logement( + p_impositions_tfu_id BIGINT, + p_user_id BIGINT +) + RETURNS INTEGER + LANGUAGE plpgsql +AS $$ +DECLARE + v_rows_inserted INTEGER; + v_annee BIGINT; + v_structure_id BIGINT; + v_taux_defaut_sup_sol NUMERIC; + v_taux_tfu NUMERIC; + v_taux_tfu_ratio NUMERIC; -- v_taux_tfu / 100 (pré-calculé) + v_taux_valeur_locat_prof NUMERIC; + v_taux_vlp_ratio NUMERIC; -- v_taux_valeur_locat_prof / 100 (pré-calculé) + v_tfu_piscine_unitaire NUMERIC; + v_today DATE; +BEGIN + + v_today := CURRENT_DATE; + + -- ------------------------------------------------------------------------- + -- 1. Récupération de l'année et de la structure (inchangée) + -- ------------------------------------------------------------------------- + SELECT ex.annee, it.structure_id + INTO STRICT v_annee, v_structure_id + FROM impositions_tfu it + JOIN exercice ex ON ex.id = it.exercice_id + WHERE it.id = p_impositions_tfu_id; + + -- ------------------------------------------------------------------------- + -- 2. Récupération des 4 paramètres en UNE seule requête + -- (évite 4 accès séquentiels à la table parameters) + -- ------------------------------------------------------------------------- + SELECT + MAX(value) FILTER (WHERE name = 'TAUX_DEFAUT_SUPERFICIE_AU_SOL'), + MAX(value) FILTER (WHERE name = 'TAUX_TFU'), + MAX(value) FILTER (WHERE name = 'TAUX_VALEUR_LOCATIVE_PROFESSIONNELLE'), + MAX(value) FILTER (WHERE name = 'TFU_PAR_PISCINE') + INTO STRICT + v_taux_defaut_sup_sol, + v_taux_tfu, + v_taux_valeur_locat_prof, + v_tfu_piscine_unitaire + FROM parameters + WHERE name IN ( + 'TAUX_DEFAUT_SUPERFICIE_AU_SOL', + 'TAUX_TFU', + 'TAUX_VALEUR_LOCATIVE_PROFESSIONNELLE', + 'TFU_PAR_PISCINE' + ); + + -- Ratios pré-calculés pour éviter la division répétée dans le SELECT + v_taux_tfu_ratio := v_taux_tfu / 100.0; + v_taux_vlp_ratio := v_taux_valeur_locat_prof / 100.0; + + -- ------------------------------------------------------------------------- + -- 3. INSERT avec calcul complet de valeur_locative_adm et montant_taxe + -- → supprime l'UPDATE post-INSERT (économie d'un second scan de table) + -- ------------------------------------------------------------------------- + INSERT INTO donnees_imposition_tfu ( + annee, + code_departement, + nom_departement, + code_commune, + nom_commune, + code_arrondissement, + nom_arrondissement, + code_quartier_village, + nom_quartier_village, + q, + ilot, + parcelle, + nup, + titre_foncier, + num_batiment, + num_unite_logement, + ifu, + npi, + tel_prop, + email_prop, + nom_prop, + prenom_prop, + raison_sociale, + adresse_prop, + tel_sc, + nom_sc, + prenom_sc, + longitude, + latitude, + batie, + exonere, + batiment_exonere, + unite_logement_exonere, + standing_bat, + categorie_bat, + nombre_piscine, + date_enquete, + structure_id, + zone_rfu_id, + nature_impot, + superficie_parc, + superficie_au_sol_bat, + superficie_au_sol_ulog, + valeur_batiment, + valeur_locative_adm_metre_carre, + montant_loyer_annuel, + tfu_metre_carre, + tfu_minimum, + impositions_tfu_id, + deleted, + created_at, + created_by, + "source", + updated_at, + updated_by, + categorie_usage, + superficie_au_sol_taux_prop_parc, -- 70 % superficie parcelle + valeur_locative_adm_taux_prop_parc, + tfu_calcule_taux_prop_parc, -- TFU à 70 % + valeur_locative_adm_sup_reel, + valeur_locative_adm, -- valeur locative administrative finale + tfu_superficie_au_sol_reel, + tfu_piscine, + montant_taxe, -- TFU finale + taux_tfu, + parcelle_id, + batiment_id, + unite_logement_id + ) + SELECT + v_annee, + d.code, + d.nom, + c.code, + c.nom, + a.code, + a.nom, + q.code, + q.nom, + p.q, + p.i, + p.p, + p.nup, + ep.numero_titre_foncier, + b.nub, + ul.nul, + eul.ifu, + eul.npi, + eul.tel1, + eul.email, + eul.nom, + eul.prenom, + eul.raison_sociale, + eul.adresse, + eul.representant_tel, + eul.representant_nom, + eul.representant_prenom, + p.longitude, + p.latitude, + TRUE, + -- exonere parcelle + (v_today BETWEEN ep.date_debut_exemption + AND COALESCE(ep.date_fin_exemption, v_today)), + -- exonere batiment + (v_today BETWEEN eb.date_debut_excemption + AND COALESCE(eb.date_fin_excemption, v_today)), + -- exonere unite logement + (v_today BETWEEN eul.date_debut_exemption + AND COALESCE(eul.date_fin_exemption, v_today)), + cb.standing, + cb.nom, + COALESCE(eul.nombre_piscine, 0), + eul.date_enquete, + st.id, + ep.zone_rfu_id, + 'TFU', + p.superficie, + eb.superficie_au_sol, + eul.superficie_au_sol, + -- valeur_batiment (unité logement) : première valeur non nulle non zéro + COALESCE( + NULLIF(eul.valeur_unite_logement_reel, 0), + NULLIF(eul.valeur_unite_logement_calcule, 0), + NULLIF(eul.valeur_unite_logement_estime, 0), + 0 + ), + brb.valeur_locative, + -- montant_loyer_annuel + COALESCE( + NULLIF(eul.montant_locatif_annuel_declare, 0), + NULLIF(eul.montant_locatif_annuel_calcule, 0), + NULLIF(eul.montant_locatif_annuel_estime, 0), + 0 + ), + brb.tfu_metre_carre, + brb.tfu_minimum, + p_impositions_tfu_id, + FALSE, + v_today, + p_user_id, + 'FISCAD', + v_today, + p_user_id, + eul.categorie_usage, + + -- superficie_au_sol_taux_prop_parc (70 % parcelle) + p.superficie * v_taux_defaut_sup_sol / 100.0, + + -- valeur_locative_adm_taux_prop_parc + CASE WHEN eul.categorie_usage = 'HABITATION' + THEN (p.superficie * v_taux_defaut_sup_sol / 100.0) * brb.valeur_locative + ELSE 0 + END, + + -- tfu_calcule_taux_prop_parc + CASE WHEN eul.categorie_usage = 'HABITATION' + THEN (p.superficie * v_taux_defaut_sup_sol / 100.0) * brb.valeur_locative * v_taux_tfu_ratio + ELSE 0 + END, + + -- valeur_locative_adm_sup_reel + CASE WHEN eul.categorie_usage = 'HABITATION' + THEN eul.superficie_au_sol * brb.valeur_locative + ELSE 0 + END, + + -- --------------------------------------------------------------- + -- valeur_locative_adm avec tests explicites (corrigée) + -- --------------------------------------------------------------- + CASE + WHEN eul.categorie_usage = 'HABITATION' + AND eul.superficie_au_sol <> 0 + THEN eul.superficie_au_sol * brb.valeur_locative + + WHEN eul.categorie_usage = 'HABITATION' + AND eul.superficie_au_sol = 0 + THEN (p.superficie * v_taux_defaut_sup_sol / 100.0) * brb.valeur_locative + + -- ✅ Test explicite : valeur_unite_logement <> 0 + WHEN eul.categorie_usage IN ('PROFESSIONNELLE', 'MIXTE') + AND COALESCE(NULLIF(eul.valeur_unite_logement_reel, 0), + NULLIF(eul.valeur_unite_logement_calcule, 0), + NULLIF(eul.valeur_unite_logement_estime, 0), 0) <> 0 + THEN COALESCE(NULLIF(eul.valeur_unite_logement_reel, 0), + NULLIF(eul.valeur_unite_logement_calcule, 0), + NULLIF(eul.valeur_unite_logement_estime, 0), 0) + * v_taux_vlp_ratio + + -- ✅ Test explicite : valeur_unite_logement = 0 + WHEN eul.categorie_usage IN ('PROFESSIONNELLE', 'MIXTE') + AND COALESCE(NULLIF(eul.valeur_unite_logement_reel, 0), + NULLIF(eul.valeur_unite_logement_calcule, 0), + NULLIF(eul.valeur_unite_logement_estime, 0), 0) = 0 + THEN COALESCE(NULLIF(eul.montant_locatif_annuel_declare, 0), + NULLIF(eul.montant_locatif_annuel_calcule, 0), + NULLIF(eul.montant_locatif_annuel_estime, 0), 0) + + ELSE 0 + END, + + -- 🔧 CORRECTION : tfu_superficie_au_sol_reel (était hardcodé à 6/100) + CASE WHEN eul.categorie_usage = 'HABITATION' + THEN eul.superficie_au_sol * brb.valeur_locative * v_taux_tfu_ratio + ELSE 0 + END, + + -- tfu_piscine + COALESCE(eul.nombre_piscine, 0) * v_tfu_piscine_unitaire, + + -- --------------------------------------------------------------- + -- montant_taxe ← calculé directement (plus d'UPDATE) + -- --------------------------------------------------------------- + ( + WITH calc AS ( + SELECT + COALESCE(NULLIF(eul.valeur_unite_logement_reel, 0), + NULLIF(eul.valeur_unite_logement_calcule, 0), + NULLIF(eul.valeur_unite_logement_estime, 0), 0) AS valeur_ul, + COALESCE(NULLIF(eul.montant_locatif_annuel_declare, 0), + NULLIF(eul.montant_locatif_annuel_calcule, 0), + NULLIF(eul.montant_locatif_annuel_estime, 0), 0) AS loyer, + eul.superficie_au_sol * brb.valeur_locative AS vla_reel, + (p.superficie * v_taux_defaut_sup_sol / 100.0) + * brb.valeur_locative AS vla_70, + COALESCE(eul.nombre_piscine, 0) * v_tfu_piscine_unitaire AS piscine_montant + ) + SELECT + CASE + WHEN eul.categorie_usage = 'HABITATION' + AND eul.superficie_au_sol <> 0 + THEN GREATEST(brb.tfu_minimum, + calc.vla_reel * v_taux_tfu_ratio + + calc.piscine_montant) + + WHEN eul.categorie_usage = 'HABITATION' + AND eul.superficie_au_sol = 0 + THEN GREATEST(brb.tfu_minimum, + calc.vla_70 * v_taux_tfu_ratio + + calc.piscine_montant) + + WHEN eul.categorie_usage IN ('PROFESSIONNELLE', 'MIXTE') + AND calc.valeur_ul <> 0 + THEN GREATEST(brb.tfu_minimum, + calc.valeur_ul * v_taux_vlp_ratio * v_taux_tfu_ratio) + + WHEN eul.categorie_usage IN ('PROFESSIONNELLE', 'MIXTE') + AND calc.valeur_ul = 0 + THEN GREATEST(brb.tfu_minimum, + calc.loyer * v_taux_tfu_ratio) + + ELSE brb.tfu_minimum + END + FROM calc + ), + + v_taux_tfu, + p.id, + b.id, + ul.id + + FROM parcelle p + + -- Dernière enquête parcelle + LEFT JOIN LATERAL ( + SELECT + parcelle_id, + superficie, + personne_id, + numero_titre_foncier, + date_enquete, + representant_tel, + representant_nom, + representant_prenom, + representant_npi, + date_debut_exemption, + date_fin_exemption, + zone_rfu_id + FROM enquete + WHERE parcelle_id = p.id + ORDER BY date_enquete DESC, id DESC + LIMIT 1 + ) ep ON TRUE + + LEFT JOIN personne pers ON pers.id = ep.personne_id + + JOIN quartier q ON q.id = p.quartier_id + JOIN arrondissement a ON a.id = q.arrondissement_id + JOIN commune c ON c.id = a.commune_id + JOIN departement d ON d.id = c.departement_id + + -- Rattachement structure via secteur + JOIN LATERAL ( + SELECT secteur_id + FROM secteur_decoupage + WHERE quartier_id = q.id + ORDER BY quartier_id + LIMIT 1 + ) sd ON TRUE + JOIN secteur sect ON sect.id = sd.secteur_id + JOIN section ses ON ses.id = sect.section_id + JOIN "structure" st ON st.id = ses.structure_id + + JOIN batiment b ON b.parcelle_id = p.id + + -- Dernière enquête bâtiment + JOIN LATERAL ( + SELECT + eb2.batiment_id, + eb2.superficie_au_sol, + eb2.nombre_piscine, + eb2.categorie_batiment_id, + eb2.date_enquete, + eb2.montant_locatif_annuel_declare, + eb2.montant_locatif_annuel_calcule, + eb2.montant_locatif_annuel_estime, + eb2.date_debut_excemption, + eb2.date_fin_excemption, + eb2.valeur_batiment_reel, + eb2.valeur_batiment_calcule, + eb2.valeur_batiment_estime, + u.categorie_usage + FROM enquete_batiment eb2 + JOIN usage u ON u.id = eb2.usage_id + WHERE eb2.batiment_id = b.id + ORDER BY eb2.date_enquete DESC, eb2.id DESC + LIMIT 1 + ) eb ON TRUE + + JOIN unite_logement ul ON ul.batiment_id = b.id + + -- Dernière enquête unité logement + JOIN LATERAL ( + SELECT + eul2.unite_logement_id, + pers1.id, + pers1.ifu, + pers1.npi, + pers1.tel1, + pers1.email, + pers1.nom, + pers1.prenom, + pers1.raison_sociale, + pers1.adresse, + eul2.nombre_piscine, + eul2.categorie_batiment_id, + eul2.superficie_au_sol, + eul2.superficie_louee, + eul2.nbre_piece, + eul2.date_enquete, + eul2.montant_locatif_annuel_calcule, + eul2.montant_locatif_annuel_declare, + eul2.montant_locatif_annuel_estime, + eul2.date_debut_exemption, + eul2.date_fin_exemption, + eul2.representant_nom, + eul2.representant_prenom, + eul2.representant_tel, + eul2.valeur_unite_logement_reel, + eul2.valeur_unite_logement_calcule, + eul2.valeur_unite_logement_estime, + u.categorie_usage + FROM enquete_unite_logement eul2 + JOIN usage u ON u.id = eul2.usage_id + LEFT JOIN personne pers1 ON pers1.id = eul2.personne_id + WHERE eul2.unite_logement_id = ul.id + ORDER BY eul2.date_enquete DESC, eul2.id DESC + LIMIT 1 + ) eul ON TRUE + + JOIN categorie_batiment cb ON cb.id = eul.categorie_batiment_id + + -- Barème RFU bâti (inchangé) + JOIN LATERAL ( + SELECT * + FROM barem_rfu_bati br + WHERE br.categorie_batiment_id = cb.id + AND br.arrondissement_id = a.id + AND (br.quartier_id = q.id OR br.quartier_id IS NULL) + ORDER BY br.quartier_id DESC NULLS LAST + LIMIT 1 + ) brb ON TRUE + + WHERE p.batie = TRUE + AND EXISTS ( + SELECT 1 + FROM unite_logement ul2 + WHERE ul2.batiment_id = b.id + ) + AND st.id = v_structure_id + + ON CONFLICT DO NOTHING; + + GET DIAGNOSTICS v_rows_inserted = ROW_COUNT; + + RETURN v_rows_inserted; +END; +$$; + diff --git a/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/export_donnee_imposition_vers_sigibe.sql b/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/export_donnee_imposition_vers_sigibe.sql index 0ad54d8..21fa901 100644 --- a/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/export_donnee_imposition_vers_sigibe.sql +++ b/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/export_donnee_imposition_vers_sigibe.sql @@ -70,20 +70,20 @@ FROM impositions_tfu imp order by c.code,st.code,r_quartier_contact,i_contact,p_contact; -select * from e_avis_view; ---left join structure st2 on st2.id=imp.structure_id; +--left join structure st2 on st2.id=imp.structure_id; 8263 create or replace view e_avis_detail_view as WITH cca_unique AS ( SELECT DISTINCT ON (personne_id, commune_id) structure_id, personne_id, - commune_id + commune_id, + parcelle_id FROM commune_centre_assignation ORDER BY commune_id,personne_id,structure_id ) -SELECT +SELECT distinct on (exo.annee,dimp.parcelle_id,dimp.nature_impot) null as id_avis_detail, null as id_avis, dimp.id as id_externe_ligne_imposition, @@ -103,7 +103,11 @@ SELECT end as montant_base_imposition, dimp.valeur_locative_adm as montant_valeur_locative, dimp.taux_tfu as taux, - dimp.montant_taxe as montant_du + dimp.montant_taxe as montant_du, + case + when cca.parcelle_id is not null then true + else false + end as booleen_parcelle_contact FROM impositions_tfu imp INNER JOIN donnees_imposition_tfu dimp ON dimp.impositions_tfu_id = imp.id @@ -114,6 +118,13 @@ FROM impositions_tfu imp LEFT JOIN cca_unique cca ON cca.personne_id = dimp.personne_id AND cca.commune_id = imp.commune_id + AND cca.parcelle_id = dimp.parcelle_id LEFT JOIN structure st ON st.id = cca.structure_id where dimp.personne_id is not null ; + +select * from e_avis_detail_view +where qip_quartier='6431' and qip_ilot='1656' and qip_parcelle='C' ; + + +'6431', '1656', 'C' \ No newline at end of file diff --git a/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/generer_donnees_imposition_irf_batie.sql b/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/generer_donnees_imposition_irf_batie.sql index 668d400..ff9df6d 100644 --- a/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/generer_donnees_imposition_irf_batie.sql +++ b/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/generer_donnees_imposition_irf_batie.sql @@ -597,7 +597,7 @@ BEGIN JOIN usage u ON u.id = eb2.usage_id WHERE eb2.batiment_id = b.id -- 🔧 IRF : Filtre spécifique - AND eb2.superficie_louee * eb2.montant_locatif_annuel_declare > 0 + AND eb2.superficie_louee * eb2.montant_locatif_annuel_declare > 0 ---s'assurer que la superficie au sol loue est renseignée ORDER BY eb2.date_enquete DESC, eb2.id DESC LIMIT 1 ) eb ON TRUE diff --git a/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/generer_donnees_imposition_irf_batie_une_parcelle.sql b/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/generer_donnees_imposition_irf_batie_une_parcelle.sql new file mode 100644 index 0000000..cf0f1ff --- /dev/null +++ b/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/generer_donnees_imposition_irf_batie_une_parcelle.sql @@ -0,0 +1,350 @@ +CREATE OR REPLACE FUNCTION public.generer_donnees_imposition_irf_batie_une_parcelle( + p_impositions_tfu_id BIGINT, + p_user_id BIGINT, + p_parcelle_id BIGINT +) + RETURNS INTEGER + LANGUAGE plpgsql +AS $$ +DECLARE + v_rows_inserted INTEGER; + v_annee BIGINT; + v_structure_id BIGINT; + v_taux_defaut_sup_sol NUMERIC; + v_taux_valeur_locat_prof NUMERIC; + v_tfu_piscine_unitaire NUMERIC; + v_taux_irf NUMERIC; + v_taux_irf_ratio NUMERIC; -- v_taux_irf / 100 (pré-calculé) + v_today DATE; +BEGIN + + v_today := CURRENT_DATE; + + -- ------------------------------------------------------------------------- + -- 1. Récupération de l'année et de la structure (inchangée) + -- ------------------------------------------------------------------------- + SELECT ex.annee, it.structure_id + INTO STRICT v_annee, v_structure_id + FROM impositions_tfu it + JOIN exercice ex ON ex.id = it.exercice_id + WHERE it.id = p_impositions_tfu_id; + + -- ------------------------------------------------------------------------- + -- 2. Récupération des 4 paramètres en UNE seule requête + -- (évite 4 accès séquentiels à la table parameters) + -- ------------------------------------------------------------------------- + SELECT + MAX(value) FILTER (WHERE name = 'TAUX_DEFAUT_SUPERFICIE_AU_SOL'), + MAX(value) FILTER (WHERE name = 'TAUX_VALEUR_LOCATIVE_PROFESSIONNELLE'), + MAX(value) FILTER (WHERE name = 'TFU_PAR_PISCINE'), + MAX(value) FILTER (WHERE name = 'TAUX_IRF') + INTO STRICT + v_taux_defaut_sup_sol, + v_taux_valeur_locat_prof, + v_tfu_piscine_unitaire, + v_taux_irf + FROM parameters + WHERE name IN ( + 'TAUX_DEFAUT_SUPERFICIE_AU_SOL', + 'TAUX_VALEUR_LOCATIVE_PROFESSIONNELLE', + 'TFU_PAR_PISCINE', + 'TAUX_IRF' + ); + + -- Ratio pré-calculé pour éviter la division répétée dans le SELECT + v_taux_irf_ratio := v_taux_irf / 100.0; + + -- ------------------------------------------------------------------------- + -- 3. INSERT avec calcul direct de valeur_locative_adm et montant_taxe + -- → supprime l'UPDATE post-INSERT (économie d'un second scan de table) + -- ------------------------------------------------------------------------- + INSERT INTO donnees_imposition_tfu ( + annee, + code_departement, + nom_departement, + code_commune, + nom_commune, + code_arrondissement, + nom_arrondissement, + code_quartier_village, + nom_quartier_village, + q, + ilot, + parcelle, + nup, + titre_foncier, + num_batiment, + ifu, + npi, + tel_prop, + email_prop, + nom_prop, + prenom_prop, + raison_sociale, + adresse_prop, + tel_sc, + nom_sc, + prenom_sc, + longitude, + latitude, + batie, + exonere, + batiment_exonere, + standing_bat, + categorie_bat, + nombre_piscine, + date_enquete, + structure_id, + zone_rfu_id, + nature_impot, + superficie_parc, + superficie_au_sol_bat, + valeur_batiment, + valeur_locative_adm_metre_carre, + montant_loyer_annuel, + tfu_metre_carre, + tfu_minimum, + impositions_tfu_id, + deleted, + created_at, + created_by, + "source", + updated_at, + updated_by, + categorie_usage, + superficie_au_sol_taux_prop_parc, -- 70 % superficie parcelle + valeur_locative_adm_taux_prop_parc, + tfu_calcule_taux_prop_parc, -- 0 pour IRF + valeur_locative_adm_sup_reel, + valeur_locative_adm, -- = montant_loyer_annuel pour IRF + tfu_superficie_au_sol_reel, -- 0 pour IRF + tfu_piscine, -- 0 pour IRF + montant_taxe, -- IRF finale = loyer * taux_irf + taux_tfu, -- = taux_irf pour IRF + parcelle_id, + batiment_id, + unite_logement_id, + superficie_au_sol_loue, + personne_id + ) + SELECT + v_annee, + d.code, + d.nom, + c.code, + c.nom, + a.code, + a.nom, + q.code, + q.nom, + p.q, + p.i, + p.p, + p.nup, + ep.numero_titre_foncier, + b.nub, + pers.ifu, + pers.npi, + pers.tel1, + pers.email, + pers.nom, + pers.prenom, + pers.raison_sociale, + pers.adresse, + ep.representant_tel, + ep.representant_nom, + ep.representant_prenom, + p.longitude, + p.latitude, + TRUE, + -- exonere parcelle + (v_today BETWEEN ep.date_debut_exemption + AND COALESCE(ep.date_fin_exemption, v_today)), + -- exonere batiment + (v_today BETWEEN eb.date_debut_excemption + AND COALESCE(eb.date_fin_excemption, v_today)), + cb.standing, + cb.nom, + eb.nombre_piscine, + eb.date_enquete, + st.id, + ep.zone_rfu_id, + 'IRF', + p.superficie, + eb.superficie_au_sol, + -- valeur_batiment : première valeur non nulle non zéro + COALESCE( + NULLIF(eb.valeur_batiment_reel, 0), + NULLIF(eb.valeur_batiment_calcule, 0), + NULLIF(eb.valeur_batiment_estime, 0), + 0 + ), + brb.valeur_locative, + -- montant_loyer_annuel + COALESCE( + NULLIF(eb.montant_locatif_annuel_declare, 0), + NULLIF(eb.montant_locatif_annuel_calcule, 0), + NULLIF(eb.montant_locatif_annuel_estime, 0), + 0 + ), + -- 🔧 IRF : champs TFU mis à 0 + 0, -- tfu_metre_carre + 0, -- tfu_minimum + p_impositions_tfu_id, + FALSE, + v_today, + p_user_id, + 'FISCAD', + v_today, + p_user_id, + eb.categorie_usage, + + -- superficie_au_sol_taux_prop_parc (70 % parcelle) + p.superficie * v_taux_defaut_sup_sol / 100.0, + + -- valeur_locative_adm_taux_prop_parc + (p.superficie * v_taux_defaut_sup_sol / 100.0) * brb.valeur_locative, + + -- 🔧 IRF : tfu_calcule_taux_prop_parc → 0 + 0, + + -- valeur_locative_adm_sup_reel + eb.superficie_au_sol * brb.valeur_locative, + + -- --------------------------------------------------------------- + -- 🔧 IRF : valeur_locative_adm = montant_loyer_annuel (calculé directement) + -- --------------------------------------------------------------- + COALESCE( + NULLIF(eb.montant_locatif_annuel_declare, 0), + NULLIF(eb.montant_locatif_annuel_calcule, 0), + NULLIF(eb.montant_locatif_annuel_estime, 0), + 0 + ), + + -- 🔧 IRF : tfu_superficie_au_sol_reel → 0 + 0, + + -- 🔧 IRF : tfu_piscine → 0 + 0, + + -- --------------------------------------------------------------- + -- 🔧 IRF : montant_taxe = montant_loyer_annuel * taux_irf (calculé directement) + -- --------------------------------------------------------------- + COALESCE( + NULLIF(eb.montant_locatif_annuel_declare, 0), + NULLIF(eb.montant_locatif_annuel_calcule, 0), + NULLIF(eb.montant_locatif_annuel_estime, 0), + 0 + ) * v_taux_irf_ratio, + + -- 🔧 IRF : taux_tfu → taux_irf + v_taux_irf, + p.id, + b.id, + NULL, + eb.superficie_louee, + ep.personne_id + FROM parcelle p + + -- Dernière enquête parcelle + LEFT JOIN LATERAL ( + SELECT + parcelle_id, + superficie, + personne_id, + numero_titre_foncier, + date_enquete, + representant_tel, + representant_nom, + representant_prenom, + representant_npi, + date_debut_exemption, + date_fin_exemption, + zone_rfu_id + FROM enquete + WHERE parcelle_id = p.id + ORDER BY date_enquete DESC, id DESC + LIMIT 1 + ) ep ON TRUE + + LEFT JOIN personne pers ON pers.id = ep.personne_id + + JOIN quartier q ON q.id = p.quartier_id + JOIN arrondissement a ON a.id = q.arrondissement_id + JOIN commune c ON c.id = a.commune_id + JOIN departement d ON d.id = c.departement_id + + -- Rattachement structure via secteur (DISTINCT ON → LATERAL plus lisible) + JOIN LATERAL ( + SELECT secteur_id + FROM secteur_decoupage + WHERE quartier_id = q.id + ORDER BY quartier_id + LIMIT 1 + ) sd ON TRUE + JOIN secteur sect ON sect.id = sd.secteur_id + JOIN section ses ON ses.id = sect.section_id + JOIN "structure" st ON st.id = ses.structure_id + + -- Bâtiments sans unités logement (anti-join via LEFT JOIN … IS NULL) + JOIN batiment b ON b.parcelle_id = p.id + LEFT JOIN unite_logement ul_filter ON ul_filter.batiment_id = b.id + + -- 🔧 IRF : Dernière enquête bâtiment avec filtre spécifique IRF + JOIN LATERAL ( + SELECT + eb2.batiment_id, + eb2.superficie_au_sol, + eb2.nombre_piscine, + eb2.categorie_batiment_id, + eb2.date_enquete, + eb2.montant_locatif_annuel_declare, + eb2.montant_locatif_annuel_calcule, + eb2.montant_locatif_annuel_estime, + eb2.date_debut_excemption, + eb2.date_fin_excemption, + eb2.valeur_batiment_reel, + eb2.valeur_batiment_calcule, + eb2.valeur_batiment_estime, + u.categorie_usage, + eb2.superficie_louee + FROM enquete_batiment eb2 + JOIN usage u ON u.id = eb2.usage_id + WHERE eb2.batiment_id = b.id + -- 🔧 IRF : Filtre spécifique + AND eb2.superficie_louee * eb2.montant_locatif_annuel_declare > 0 ---s'assurer que la superficie au sol loue est renseignée + ORDER BY eb2.date_enquete DESC, eb2.id DESC + LIMIT 1 + ) eb ON TRUE + + JOIN categorie_batiment cb ON cb.id = eb.categorie_batiment_id + + -- Barème RFU bâti (inchangé) + JOIN LATERAL ( + SELECT * + FROM barem_rfu_bati br + WHERE br.categorie_batiment_id = cb.id + AND br.arrondissement_id = a.id + AND (br.quartier_id = q.id OR br.quartier_id IS NULL) + ORDER BY br.quartier_id DESC NULLS LAST + LIMIT 1 + ) brb ON TRUE + + WHERE p.batie = TRUE + AND ul_filter.batiment_id IS NULL -- anti-join : pas d'unité logement + AND st.id = v_structure_id + AND p.id=p_parcelle_id + AND NOT EXISTS(select 1 from donnees_imposition_tfu dimptfu + where dimptfu.parcelle_id=p_parcelle_id + AND dimptfu.annee=v_annee + AND dimptfu.nature_impot='IRF' + AND dimptfu.batiment_id=b.id) + + ON CONFLICT DO NOTHING; + + GET DIAGNOSTICS v_rows_inserted = ROW_COUNT; + + RETURN v_rows_inserted; +END; +$$; + diff --git a/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/generer_donnees_imposition_irf_batie_unite_logement_une_parcelle.sql b/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/generer_donnees_imposition_irf_batie_unite_logement_une_parcelle.sql new file mode 100644 index 0000000..b88b72a --- /dev/null +++ b/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/generer_donnees_imposition_irf_batie_unite_logement_une_parcelle.sql @@ -0,0 +1,305 @@ +CREATE OR REPLACE FUNCTION public.generer_donnees_imposition_irf_batie_ulo_une_parcelle( + p_impositions_tfu_id BIGINT, + p_user_id BIGINT, + p_parcelle_id BIGINT +) + RETURNS INTEGER + LANGUAGE plpgsql +AS $$ +DECLARE + v_rows_inserted INTEGER; + v_annee BIGINT; + v_structure_id BIGINT; + + v_taux_defaut_sup_sol NUMERIC; + v_taux_irf NUMERIC; + v_taux_irf_ratio NUMERIC; + + v_today DATE; +BEGIN + + v_today := CURRENT_DATE; + + -- 1. année + structure + SELECT ex.annee, it.structure_id + INTO STRICT v_annee, v_structure_id + FROM impositions_tfu it + JOIN exercice ex ON ex.id = it.exercice_id + WHERE it.id = p_impositions_tfu_id; + + -- 2. paramètres (UNE seule requête) + SELECT + MAX(value) FILTER (WHERE name = 'TAUX_DEFAUT_SUPERFICIE_AU_SOL'), + MAX(value) FILTER (WHERE name = 'TAUX_IRF') + INTO STRICT + v_taux_defaut_sup_sol, + v_taux_irf + FROM parameters + WHERE name IN ( + 'TAUX_DEFAUT_SUPERFICIE_AU_SOL', + 'TAUX_IRF' + ); + + v_taux_irf_ratio := v_taux_irf / 100.0; + + -- 3. INSERT optimisé + INSERT INTO donnees_imposition_tfu ( + annee, + code_departement, + nom_departement, + code_commune, + nom_commune, + code_arrondissement, + nom_arrondissement, + code_quartier_village, + nom_quartier_village, + q, + ilot, + parcelle, + nup, + titre_foncier, + num_batiment, + num_unite_logement, + ifu, + npi, + tel_prop, + email_prop, + nom_prop, prenom_prop, raison_sociale, adresse_prop, + tel_sc, nom_sc, prenom_sc, + longitude, latitude, + batie, + exonere, batiment_exonere, unite_logement_exonere, + standing_bat, categorie_bat, + nombre_piscine, + date_enquete, + structure_id, + zone_rfu_id, + nature_impot, + superficie_parc, + superficie_au_sol_bat, + superficie_au_sol_ulog, + valeur_batiment, + valeur_locative_adm_metre_carre, + montant_loyer_annuel, + tfu_metre_carre, + tfu_minimum, + impositions_tfu_id, + deleted, + created_at, + created_by, + source, + updated_at, + updated_by, + categorie_usage, + superficie_au_sol_taux_prop_parc, + valeur_locative_adm_taux_prop_parc, + tfu_calcule_taux_prop_parc, + valeur_locative_adm_sup_reel, + valeur_locative_adm, + tfu_superficie_au_sol_reel, + tfu_piscine, + montant_taxe, + taux_tfu, + parcelle_id, + batiment_id, + unite_logement_id, + superficie_au_sol_loue, + personne_id + ) + SELECT + v_annee, + d.code, d.nom, + c.code, c.nom, + a.code, a.nom, + q.code, q.nom, + p.q, p.i, p.p, p.nup, + ep.numero_titre_foncier, + b.nub, ul.nul, + + eul.ifu, eul.npi, eul.tel1, eul.email, + eul.nom, eul.prenom, eul.raison_sociale, eul.adresse, + eul.representant_tel, eul.representant_nom, eul.representant_prenom, + + p.longitude, p.latitude, + TRUE, + + (v_today BETWEEN ep.date_debut_exemption AND COALESCE(ep.date_fin_exemption, v_today)), + (v_today BETWEEN eb.date_debut_excemption AND COALESCE(eb.date_fin_excemption, v_today)), + (v_today BETWEEN eul.date_debut_exemption AND COALESCE(eul.date_fin_exemption, v_today)), + + cb.standing, + cb.nom, + + COALESCE(eul.nombre_piscine, 0), + eul.date_enquete, + st.id, + ep.zone_rfu_id, + 'IRF', + + p.superficie, + eb.superficie_au_sol, + eul.superficie_au_sol, + + -- valeur logement + COALESCE( + NULLIF(eul.valeur_unite_logement_reel,0), + NULLIF(eul.valeur_unite_logement_calcule,0), + NULLIF(eul.valeur_unite_logement_estime,0), + 0 + ), + + brb.valeur_locative, + + -- loyer + COALESCE( + NULLIF(eul.montant_locatif_annuel_declare,0), + NULLIF(eul.montant_locatif_annuel_calcule,0), + NULLIF(eul.montant_locatif_annuel_estime,0), + 0 + ), + + 0, 0, + p_impositions_tfu_id, + FALSE, + v_today, p_user_id, 'FISCAD', + v_today, p_user_id, + eul.categorie_usage, + + p.superficie * v_taux_defaut_sup_sol / 100.0, + + (p.superficie * v_taux_defaut_sup_sol / 100.0) * brb.valeur_locative, + + 0, + + eul.superficie_au_sol * brb.valeur_locative, + + -- valeur locative = loyer + COALESCE( + NULLIF(eul.montant_locatif_annuel_declare,0), + NULLIF(eul.montant_locatif_annuel_calcule,0), + NULLIF(eul.montant_locatif_annuel_estime,0), + 0 + ), + + 0, 0, + + -- montant taxe direct (PLUS D'UPDATE) + COALESCE( + NULLIF(eul.montant_locatif_annuel_declare,0), + NULLIF(eul.montant_locatif_annuel_calcule,0), + NULLIF(eul.montant_locatif_annuel_estime,0), + 0 + ) * v_taux_irf_ratio, + + v_taux_irf, + p.id, + b.id, + ul.id, + eul.superficie_louee, + eul.personne_id + + FROM parcelle p + + LEFT JOIN LATERAL ( + SELECT * + FROM enquete e + WHERE e.parcelle_id = p.id + ORDER BY date_enquete DESC, id DESC + LIMIT 1 + ) ep ON TRUE + + JOIN quartier q ON q.id = p.quartier_id + JOIN arrondissement a ON a.id = q.arrondissement_id + JOIN commune c ON c.id = a.commune_id + JOIN departement d ON d.id = c.departement_id + + JOIN LATERAL ( + SELECT secteur_id + FROM secteur_decoupage + WHERE quartier_id = q.id + LIMIT 1 + ) sd ON TRUE + + JOIN secteur sect ON sect.id = sd.secteur_id + JOIN section ses ON ses.id = sect.section_id + JOIN structure st ON st.id = ses.structure_id + + JOIN batiment b ON b.parcelle_id = p.id + JOIN unite_logement ul ON ul.batiment_id = b.id + + JOIN LATERAL ( + SELECT eult.unite_logement_id, + pers1.id, + pers1.ifu, + pers1.npi, + pers1.tel1, + pers1.email, + pers1.nom, + pers1.prenom, + pers1.raison_sociale, + pers1.adresse, + eult.nombre_piscine, + eult.categorie_batiment_id, + eult.superficie_au_sol, + eult.superficie_louee, + eult.nbre_piece, + eult.date_enquete, + eult.montant_locatif_annuel_calcule, + eult.montant_locatif_annuel_declare, + eult.montant_locatif_annuel_estime, + eult.date_debut_exemption, + eult.date_fin_exemption, + eult.representant_nom, + eult.representant_prenom, + eult.representant_tel, + eult.valeur_unite_logement_reel, + eult.valeur_unite_logement_calcule, + eult.valeur_unite_logement_estime, + u.categorie_usage, + pers1.id as personne_id + FROM enquete_unite_logement eult + LEFT JOIN personne pers1 ON pers1.id = eult.personne_id + join usage u on u.id=eult.usage_id + WHERE eult.unite_logement_id = ul.id + AND eult.superficie_louee * eult.montant_locatif_annuel_declare > 0 + ORDER BY date_enquete DESC, eult.id DESC + LIMIT 1 + ) eul ON TRUE + + JOIN LATERAL ( + SELECT * + FROM enquete_batiment eb2 + WHERE eb2.batiment_id = b.id + ORDER BY date_enquete DESC + LIMIT 1 + ) eb ON TRUE + + JOIN categorie_batiment cb ON cb.id = eul.categorie_batiment_id + + JOIN LATERAL ( + SELECT * + FROM barem_rfu_bati br + WHERE br.categorie_batiment_id = cb.id + AND br.arrondissement_id = a.id + AND (br.quartier_id = q.id OR br.quartier_id IS NULL) + ORDER BY br.quartier_id DESC NULLS LAST + LIMIT 1 + ) brb ON TRUE + + WHERE p.batie = TRUE + AND st.id = v_structure_id + AND p.id=p_parcelle_id + AND NOT EXISTS(select 1 from donnees_imposition_tfu dimptfu + where dimptfu.parcelle_id=p_parcelle_id + AND dimptfu.annee=v_annee + AND dimptfu.nature_impot='IRF' + AND dimptfu.batiment_id=b.id + AND dimptfu.unite_logement_id=ul.id) + + ON CONFLICT DO NOTHING; + + GET DIAGNOSTICS v_rows_inserted = ROW_COUNT; + + RETURN v_rows_inserted; +END; +$$; diff --git a/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/generer_donnees_imposition_srtb_batie.sql b/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/generer_donnees_imposition_srtb_batie.sql index b8cdcda..745d6ba 100644 --- a/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/generer_donnees_imposition_srtb_batie.sql +++ b/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/generer_donnees_imposition_srtb_batie.sql @@ -1,315 +1,69 @@ -/*CREATE OR REPLACE FUNCTION public.generer_donnees_imposition_srtb_batie( - p_impositions_tfu_id BIGINT, - p_user_id BIGINT -) -RETURNS INTEGER -LANGUAGE plpgsql -AS -$$ -DECLARE -v_rows_inserted INTEGER; - v_annee BIGINT; - v_structure_id BIGINT; - v_montant_srtb NUMERIC; -BEGIN - --- récupération de l'année -SELECT ex.annee, it.structure_id -INTO STRICT v_annee, v_structure_id -FROM impositions_tfu it - join exercice ex on ex.id =it.exercice_id -WHERE it.id = p_impositions_tfu_id; - - -select value -into STRICT v_montant_srtb -from parameters -where name ='TAXE_SRTB'; - - -INSERT INTO donnees_imposition_tfu( - annee, - code_departement, - nom_departement, - code_commune, - nom_commune, - code_arrondissement, - nom_arrondissement, - code_quartier_village, - nom_quartier_village, - q, - ilot, - parcelle, - nup, - titre_foncier, - num_batiment, - ifu, - npi, - tel_prop, - email_prop, - nom_prop, - prenom_prop, - raison_sociale, - adresse_prop, - tel_sc, - nom_sc, - prenom_sc, - longitude, - latitude, - batie, - exonere, - batiment_exonere, - standing_bat, - categorie_bat, - nombre_piscine, - date_enquete, - structure_id, - zone_rfu_id, - nature_impot, - superficie_parc, - superficie_au_sol_bat, - valeur_batiment, - valeur_locative_adm_metre_carre, - montant_loyer_annuel, - tfu_metre_carre, - tfu_minimum, - impositions_tfu_id, - deleted, - created_at , - created_by , - "source", - updated_at , - updated_by, - categorie_usage, - superficie_au_sol_taux_prop_parc, ---70% de la surperficie au sol de la parcelle - valeur_locative_adm_taux_prop_parc, - tfu_calcule_taux_prop_parc, ----tfu correspondant au 70% - valeur_locative_adm_sup_reel, - valeur_locative_adm, ----------valeur locative administrative - tfu_superficie_au_sol_reel, ----tfu correspondant à la superficie au sol reelle - tfu_piscine, - montant_taxe, ----tfu finale - taux_tfu, ----taux tfu batie - parcelle_id, - batiment_id, - unite_logement_id, - superficie_au_sol_loue -) -SELECT - v_annee, - d.code, - d.nom, - c.code, - c.nom, - a.code, - a.nom, - q.code, - q.nom, - p.q, - p.i, - p.p, - p.nup, - ep.numero_titre_foncier, - b.nub, - pers.ifu, - pers.npi, - pers.tel1, - pers.email, - pers.nom, - pers.prenom, - pers.raison_sociale, - pers.adresse, - ep.representant_tel, - ep.representant_nom, - ep.representant_prenom, - p.longitude, - p.latitude, - TRUE, - ( - CURRENT_DATE >= ep.date_debut_exemption - AND CURRENT_DATE <= COALESCE(ep.date_fin_exemption, CURRENT_DATE) - ), - ( - CURRENT_DATE >= eb.date_debut_excemption - AND CURRENT_DATE <= COALESCE(eb.date_fin_excemption, CURRENT_DATE) - ), - cb.standing, - cb.nom, - eb.nombre_piscine, - eb.date_enquete, - st.id, - ep.zone_rfu_id, - 'SRTB', - p.superficie, - eb.superficie_au_sol, - case -------valeur_batiment - WHEN eb.valeur_batiment_reel IS NOT NULL AND eb.valeur_batiment_reel <> 0 THEN eb.valeur_batiment_reel - WHEN eb.valeur_batiment_calcule IS NOT NULL AND eb.valeur_batiment_calcule <> 0 THEN eb.valeur_batiment_calcule - WHEN eb.valeur_batiment_estime IS NOT NULL AND eb.valeur_batiment_estime <> 0 THEN eb.valeur_batiment_estime - ELSE 0 - END, - brb.valeur_locative, - case ----- montant_loyer_annuel - WHEN eb.montant_locatif_annuel_declare IS NOT NULL AND eb.montant_locatif_annuel_declare <> 0 THEN eb.montant_locatif_annuel_declare - WHEN eb.montant_locatif_annuel_calcule IS NOT NULL AND eb.montant_locatif_annuel_calcule <> 0 THEN eb.montant_locatif_annuel_calcule - WHEN eb.montant_locatif_annuel_estime IS NOT NULL AND eb.montant_locatif_annuel_estime <> 0 THEN eb.montant_locatif_annuel_estime - ELSE 0 - END, - brb.tfu_metre_carre, - brb.tfu_minimum, - p_impositions_tfu_id, - false, - current_date , - p_user_id , - 'FISCAD', - current_date , - p_user_id, - eb.categorie_usage, - 0,---superficie_au_sol_70pour100 - 0, - 0, - eb.superficie_au_sol * brb.valeur_locative, - 0, ------ valeur_locative_adm : en attente de update - 0, - 0, - v_montant_srtb, - 0, - p.id, - b.id, - null, - eb.superficie_louee -FROM parcelle p - LEFT JOIN ( - SELECT DISTINCT ON (parcelle_id) - parcelle_id, - superficie, - personne_id, - numero_titre_foncier, - date_enquete, - representant_tel, - representant_nom, - representant_prenom, - representant_npi, - date_debut_exemption, - date_fin_exemption, - zone_rfu_id - FROM enquete - ORDER BY parcelle_id, date_enquete DESC, id DESC -) ep ON ep.parcelle_id = p.id - LEFT JOIN personne pers - ON pers.id = ep.personne_id - JOIN quartier q ON q.id = p.quartier_id - JOIN arrondissement a ON a.id = q.arrondissement_id - JOIN commune c ON c.id = a.commune_id - JOIN departement d ON d.id = c.departement_id - --JOIN secteur_decoupage sd ON sd.quartier_id = q.id - JOIN ( - SELECT DISTINCT ON (quartier_id) - quartier_id, - secteur_id - FROM secteur_decoupage - ORDER BY quartier_id - ) sd ON sd.quartier_id = q.id - JOIN secteur sect ON sect.id = sd.secteur_id - JOIN section ses ON ses.id = sect.section_id - JOIN "structure" st ON st.id = ses.structure_id - JOIN batiment b ON b.parcelle_id = p.id - JOIN ( - SELECT DISTINCT ON (batiment_id) - batiment_id, - superficie_au_sol, - nombre_piscine, - categorie_batiment_id, - date_enquete, - montant_locatif_annuel_declare, - montant_locatif_annuel_calcule, - montant_locatif_annuel_estime, - date_debut_excemption, - date_fin_excemption, - valeur_batiment_reel, - valeur_batiment_calcule, - valeur_batiment_estime, - u.categorie_usage, - superficie_louee - FROM enquete_batiment eb - join usage u on u.id=eb.usage_id - ORDER BY batiment_id, date_enquete DESC, eb.id DESC -) eb ON eb.batiment_id = b.id - JOIN categorie_batiment cb - ON cb.id = eb.categorie_batiment_id - JOIN LATERAL ( - SELECT * - FROM barem_rfu_bati br - WHERE br.categorie_batiment_id = cb.id - AND br.arrondissement_id = a.id - AND (br.quartier_id = q.id OR br.quartier_id IS NULL) - ORDER BY br.quartier_id DESC NULLS LAST - LIMIT 1 -) brb ON TRUE -WHERE p.batie = TRUE - AND NOT EXISTS ( - SELECT 1 - FROM unite_logement ul - WHERE ul.batiment_id = b.id - ) - AND st.id = v_structure_id -ON CONFLICT DO NOTHING; - -GET DIAGNOSTICS v_rows_inserted = ROW_COUNT; - -RETURN v_rows_inserted; -END; -$$; */ - CREATE OR REPLACE FUNCTION public.generer_donnees_imposition_srtb_batie( p_impositions_tfu_id BIGINT, - p_user_id BIGINT + p_user_id BIGINT ) RETURNS INTEGER LANGUAGE plpgsql AS $$ DECLARE - v_rows_inserted INTEGER; - v_annee BIGINT; - v_structure_id BIGINT; - - v_montant_srtb NUMERIC; - v_today DATE; + v_rows_inserted INTEGER; + v_annee BIGINT; + v_structure_id BIGINT; + v_taux_defaut_sup_sol NUMERIC; + v_montant_srtb NUMERIC; + v_today DATE; BEGIN v_today := CURRENT_DATE; - -- 1. année + structure + -- ------------------------------------------------------------------------- + -- 1. Récupération de l'année et de la structure (inchangée) + -- ------------------------------------------------------------------------- SELECT ex.annee, it.structure_id INTO STRICT v_annee, v_structure_id FROM impositions_tfu it JOIN exercice ex ON ex.id = it.exercice_id WHERE it.id = p_impositions_tfu_id; - -- 2. paramètre (une seule requête) SELECT value INTO STRICT v_montant_srtb FROM parameters WHERE name = 'TAXE_SRTB'; - -- 3. INSERT optimisé (SANS DISTINCT ON, SANS UPDATE) INSERT INTO donnees_imposition_tfu ( annee, - code_departement, nom_departement, - code_commune, nom_commune, - code_arrondissement, nom_arrondissement, - code_quartier_village, nom_quartier_village, - q, ilot, parcelle, nup, + code_departement, + nom_departement, + code_commune, + nom_commune, + code_arrondissement, + nom_arrondissement, + code_quartier_village, + nom_quartier_village, + q, + ilot, + parcelle, + nup, titre_foncier, num_batiment, - ifu, npi, tel_prop, email_prop, - nom_prop, prenom_prop, raison_sociale, adresse_prop, - tel_sc, nom_sc, prenom_sc, - longitude, latitude, + ifu, + npi, + tel_prop, + email_prop, + nom_prop, + prenom_prop, + raison_sociale, + adresse_prop, + tel_sc, + nom_sc, + prenom_sc, + longitude, + latitude, batie, exonere, batiment_exonere, - standing_bat, categorie_bat, + standing_bat, + categorie_bat, nombre_piscine, date_enquete, structure_id, @@ -326,19 +80,19 @@ BEGIN deleted, created_at, created_by, - source, + "source", updated_at, updated_by, categorie_usage, - superficie_au_sol_taux_prop_parc, + superficie_au_sol_taux_prop_parc, -- 70 % superficie parcelle valeur_locative_adm_taux_prop_parc, - tfu_calcule_taux_prop_parc, + tfu_calcule_taux_prop_parc, -- 0 pour IRF valeur_locative_adm_sup_reel, - valeur_locative_adm, - tfu_superficie_au_sol_reel, - tfu_piscine, - montant_taxe, - taux_tfu, + valeur_locative_adm, -- = montant_loyer_annuel pour IRF + tfu_superficie_au_sol_reel, -- 0 pour IRF + tfu_piscine, -- 0 pour IRF + montant_taxe, -- IRF finale = loyer * taux_irf + taux_tfu, -- = taux_irf pour IRF parcelle_id, batiment_id, unite_logement_id, @@ -346,146 +100,103 @@ BEGIN personne_id ) SELECT - v_annee, - d.code, d.nom, - c.code, c.nom, - a.code, a.nom, - q.code, q.nom, - p.q, p.i, p.p, p.nup, - ep.numero_titre_foncier, - b.nub, - - pers.ifu, pers.npi, pers.tel1, pers.email, - pers.nom, pers.prenom, pers.raison_sociale, pers.adresse, - ep.representant_tel, ep.representant_nom, ep.representant_prenom, - - p.longitude, p.latitude, + dimp.annee, + dimp.code_departement, + dimp.nom_departement, + dimp.code_commune, + dimp.nom_commune, + dimp.code_arrondissement, + dimp.nom_arrondissement, + dimp.code_quartier_village, + dimp.nom_quartier_village, + dimp.q, + dimp. ilot, + dimp.parcelle, + dimp.nup, + dimp.titre_foncier, + dimp. num_batiment, + dimp.ifu, + dimp. npi, + dimp.tel_prop, + dimp.email_prop, + dimp.nom_prop, + dimp.prenom_prop, + dimp.raison_sociale, + dimp.adresse_prop, + dimp.tel_sc, + dimp.nom_sc, + dimp.prenom_sc, + dimp.longitude, + dimp.latitude, TRUE, - - (v_today BETWEEN ep.date_debut_exemption AND COALESCE(ep.date_fin_exemption, v_today)), - (v_today BETWEEN eb.date_debut_excemption AND COALESCE(eb.date_fin_excemption, v_today)), - - cb.standing, - cb.nom, - - COALESCE(eb.nombre_piscine, 0), - eb.date_enquete, - - st.id, - ep.zone_rfu_id, + -- exonere parcelle + dimp.exonere, + -- exonere batiment + dimp.batiment_exonere, + dimp.standing_bat, + dimp.categorie_bat, + dimp.nombre_piscine, + dimp.date_enquete, + dimp.structure_id, + dimp.zone_rfu_id, 'SRTB', - - p.superficie, - eb.superficie_au_sol, - - -- valeur bâtiment optimisée - COALESCE( - NULLIF(eb.valeur_batiment_reel,0), - NULLIF(eb.valeur_batiment_calcule,0), - NULLIF(eb.valeur_batiment_estime,0), - 0 - ), - - brb.valeur_locative, - - -- loyer optimisé - COALESCE( - NULLIF(eb.montant_locatif_annuel_declare,0), - NULLIF(eb.montant_locatif_annuel_calcule,0), - NULLIF(eb.montant_locatif_annuel_estime,0), - 0 - ), - - brb.tfu_metre_carre, - brb.tfu_minimum, - + dimp.superficie_parc, + dimp.superficie_au_sol_bat, + dimp.valeur_batiment, + dimp.tfu_metre_carre, + -- montant_loyer_annuel + dimp.montant_loyer_annuel, + -- 🔧 IRF : champs TFU mis à 0 + 0, -- tfu_metre_carre + 0, -- tfu_minimum p_impositions_tfu_id, FALSE, - v_today, p_user_id, 'FISCAD', - v_today, p_user_id, - eb.categorie_usage, + v_today, + p_user_id, + 'FISCAD', + v_today, + p_user_id, + dimp.categorie_usage, - 0, 0, 0, + -- superficie_au_sol_taux_prop_parc (70 % parcelle) + dimp.superficie_au_sol_taux_prop_parc, - eb.superficie_au_sol * brb.valeur_locative, + -- valeur_locative_adm_taux_prop_parc + dimp.valeur_locative_adm_taux_prop_parc, - 0, - 0, + -- 🔧 IRF : tfu_calcule_taux_prop_parc → 0 0, - -- 🔥 SRTB = valeur directe (pas de calcul) + -- valeur_locative_adm_sup_reel + dimp.valeur_locative_adm_sup_reel, + + -- --------------------------------------------------------------- + -- 🔧 IRF : valeur_locative_adm = montant_loyer_annuel (calculé directement) + -- --------------------------------------------------------------- + dimp.valeur_locative_adm + , + + -- 🔧 IRF : tfu_superficie_au_sol_reel → 0 + 0, + + -- 🔧 IRF : tfu_piscine → 0 + 0, + + -- --------------------------------------------------------------- + -- 🔧 IRF : montant_taxe = montant_loyer_annuel * taux_irf (calculé directement) + -- --------------------------------------------------------------- v_montant_srtb, + -- 🔧 IRF : taux_tfu → taux_irf 0, - - p.id, - b.id, - NULL, - eb.superficie_louee, - ep.personne_id - - FROM parcelle p - - -- dernière enquête parcelle - LEFT JOIN LATERAL ( - SELECT * - FROM enquete e - WHERE e.parcelle_id = p.id - ORDER BY date_enquete DESC, id DESC - LIMIT 1 - ) ep ON TRUE - - LEFT JOIN personne pers ON pers.id = ep.personne_id - - JOIN quartier q ON q.id = p.quartier_id - JOIN arrondissement a ON a.id = q.arrondissement_id - JOIN commune c ON c.id = a.commune_id - JOIN departement d ON d.id = c.departement_id - - -- structure via secteur - JOIN LATERAL ( - SELECT secteur_id - FROM secteur_decoupage - WHERE quartier_id = q.id - LIMIT 1 - ) sd ON TRUE - - JOIN secteur sect ON sect.id = sd.secteur_id - JOIN section ses ON ses.id = sect.section_id - JOIN structure st ON st.id = ses.structure_id - - JOIN batiment b ON b.parcelle_id = p.id - - -- 🔥 remplace DISTINCT ON - JOIN LATERAL ( - SELECT eb2.*,u.categorie_usage - FROM enquete_batiment eb2 - LEFT JOIN usage u ON u.id = eb2.usage_id - WHERE eb2.batiment_id = b.id - ORDER BY eb2.date_enquete DESC, eb2.id DESC - LIMIT 1 - ) eb ON TRUE - - JOIN categorie_batiment cb ON cb.id = eb.categorie_batiment_id - - JOIN LATERAL ( - SELECT * - FROM barem_rfu_bati br - WHERE br.categorie_batiment_id = cb.id - AND br.arrondissement_id = a.id - AND (br.quartier_id = q.id OR br.quartier_id IS NULL) - ORDER BY br.quartier_id DESC NULLS LAST - LIMIT 1 - ) brb ON TRUE - - WHERE p.batie = TRUE - AND NOT EXISTS ( - SELECT 1 - FROM unite_logement ul - WHERE ul.batiment_id = b.id - ) - AND st.id = v_structure_id - + dimp.parcelle_id, + dimp.batiment_id, + dimp.unite_logement_id, + dimp.superficie_au_sol_loue, + dimp.personne_id + FROM donnees_imposition_tfu dimp + WHERE dimp.nature_impot= 'IRF' + AND dimp.impositions_tfu_id=p_impositions_tfu_id ON CONFLICT DO NOTHING; GET DIAGNOSTICS v_rows_inserted = ROW_COUNT; @@ -494,4 +205,3 @@ BEGIN END; $$; - diff --git a/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/generer_donnees_imposition_srtb_batie_une_parcelle.sql b/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/generer_donnees_imposition_srtb_batie_une_parcelle.sql new file mode 100644 index 0000000..947d23e --- /dev/null +++ b/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/generer_donnees_imposition_srtb_batie_une_parcelle.sql @@ -0,0 +1,213 @@ +CREATE OR REPLACE FUNCTION public.generer_donnees_imposition_srtb_batie_une_parcelle( + p_impositions_tfu_id BIGINT, + p_user_id BIGINT, + p_parcelle_id BIGINT +) + RETURNS INTEGER + LANGUAGE plpgsql +AS $$ +DECLARE + v_rows_inserted INTEGER; + v_annee BIGINT; + v_structure_id BIGINT; + v_taux_defaut_sup_sol NUMERIC; + v_montant_srtb NUMERIC; + v_today DATE; +BEGIN + + v_today := CURRENT_DATE; + + -- ------------------------------------------------------------------------- + -- 1. Récupération de l'année et de la structure (inchangée) + -- ------------------------------------------------------------------------- + SELECT ex.annee, it.structure_id + INTO STRICT v_annee, v_structure_id + FROM impositions_tfu it + JOIN exercice ex ON ex.id = it.exercice_id + WHERE it.id = p_impositions_tfu_id; + + SELECT value + INTO STRICT v_montant_srtb + FROM parameters + WHERE name = 'TAXE_SRTB'; + + INSERT INTO donnees_imposition_tfu ( + annee, + code_departement, + nom_departement, + code_commune, + nom_commune, + code_arrondissement, + nom_arrondissement, + code_quartier_village, + nom_quartier_village, + q, + ilot, + parcelle, + nup, + titre_foncier, + num_batiment, + ifu, + npi, + tel_prop, + email_prop, + nom_prop, + prenom_prop, + raison_sociale, + adresse_prop, + tel_sc, + nom_sc, + prenom_sc, + longitude, + latitude, + batie, + exonere, + batiment_exonere, + standing_bat, + categorie_bat, + nombre_piscine, + date_enquete, + structure_id, + zone_rfu_id, + nature_impot, + superficie_parc, + superficie_au_sol_bat, + valeur_batiment, + valeur_locative_adm_metre_carre, + montant_loyer_annuel, + tfu_metre_carre, + tfu_minimum, + impositions_tfu_id, + deleted, + created_at, + created_by, + "source", + updated_at, + updated_by, + categorie_usage, + superficie_au_sol_taux_prop_parc, -- 70 % superficie parcelle + valeur_locative_adm_taux_prop_parc, + tfu_calcule_taux_prop_parc, -- 0 pour IRF + valeur_locative_adm_sup_reel, + valeur_locative_adm, -- = montant_loyer_annuel pour IRF + tfu_superficie_au_sol_reel, -- 0 pour IRF + tfu_piscine, -- 0 pour IRF + montant_taxe, -- IRF finale = loyer * taux_irf + taux_tfu, -- = taux_irf pour IRF + parcelle_id, + batiment_id, + unite_logement_id, + superficie_au_sol_loue, + personne_id + ) + SELECT + dimp.annee, + dimp.code_departement, + dimp.nom_departement, + dimp.code_commune, + dimp.nom_commune, + dimp.code_arrondissement, + dimp.nom_arrondissement, + dimp.code_quartier_village, + dimp.nom_quartier_village, + dimp.q, + dimp. ilot, + dimp.parcelle, + dimp.nup, + dimp.titre_foncier, + dimp. num_batiment, + dimp.ifu, + dimp. npi, + dimp.tel_prop, + dimp.email_prop, + dimp.nom_prop, + dimp.prenom_prop, + dimp.raison_sociale, + dimp.adresse_prop, + dimp.tel_sc, + dimp.nom_sc, + dimp.prenom_sc, + dimp.longitude, + dimp.latitude, + TRUE, + -- exonere parcelle + dimp.exonere, + -- exonere batiment + dimp.batiment_exonere, + dimp.standing_bat, + dimp.categorie_bat, + dimp.nombre_piscine, + dimp.date_enquete, + dimp.structure_id, + dimp.zone_rfu_id, + 'SRTB', + dimp.superficie_parc, + dimp.superficie_au_sol_bat, + dimp.valeur_batiment, + dimp.tfu_metre_carre, + -- montant_loyer_annuel + dimp.montant_loyer_annuel, + -- 🔧 IRF : champs TFU mis à 0 + 0, -- tfu_metre_carre + 0, -- tfu_minimum + p_impositions_tfu_id, + FALSE, + v_today, + p_user_id, + 'FISCAD', + v_today, + p_user_id, + dimp.categorie_usage, + + -- superficie_au_sol_taux_prop_parc (70 % parcelle) + dimp.superficie_au_sol_taux_prop_parc, + + -- valeur_locative_adm_taux_prop_parc + dimp.valeur_locative_adm_taux_prop_parc, + + -- 🔧 IRF : tfu_calcule_taux_prop_parc → 0 + 0, + + -- valeur_locative_adm_sup_reel + dimp.valeur_locative_adm_sup_reel, + + -- --------------------------------------------------------------- + -- 🔧 IRF : valeur_locative_adm = montant_loyer_annuel (calculé directement) + -- --------------------------------------------------------------- + dimp.valeur_locative_adm + , + + -- 🔧 IRF : tfu_superficie_au_sol_reel → 0 + 0, + + -- 🔧 IRF : tfu_piscine → 0 + 0, + + -- --------------------------------------------------------------- + -- 🔧 IRF : montant_taxe = montant_loyer_annuel * taux_irf (calculé directement) + -- --------------------------------------------------------------- + v_montant_srtb, + + -- 🔧 IRF : taux_tfu → taux_irf + 0, + dimp.parcelle_id, + dimp.batiment_id, + dimp.unite_logement_id, + dimp.superficie_au_sol_loue, + dimp.personne_id + FROM donnees_imposition_tfu dimp + WHERE dimp.nature_impot= 'IRF' + AND dimp.impositions_tfu_id=p_impositions_tfu_id + AND dimp.parcelle_id=p_parcelle_id + AND NOT EXISTS(select 1 from donnees_imposition_tfu dimptfu + where dimptfu.parcelle_id=p_parcelle_id + AND dimptfu.nature_impot='SRTB' + AND dimptfu.batiment_id=dimp.batiment_id) + ON CONFLICT DO NOTHING; + + GET DIAGNOSTICS v_rows_inserted = ROW_COUNT; + + RETURN v_rows_inserted; +END; +$$; + diff --git a/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/generer_donnees_imposition_tfu_batie.sql b/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/generer_donnees_imposition_tfu_batie.sql index bb91e9a..8306221 100644 --- a/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/generer_donnees_imposition_tfu_batie.sql +++ b/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/generer_donnees_imposition_tfu_batie.sql @@ -1,349 +1,3 @@ -/*CREATE OR REPLACE FUNCTION public.generer_donnees_imposition_tfu_batie( - p_impositions_tfu_id BIGINT, - p_user_id BIGINT -) -RETURNS INTEGER -LANGUAGE plpgsql -AS -$$ -DECLARE -v_rows_inserted INTEGER; - v_annee BIGINT; - v_structure_id BIGINT; - v_taux_defaut_sup_sol NUMERIC; - v_taux_tfu NUMERIC; - v_taux_valeur_locat_prof NUMERIC; - v_tfu_piscine_unitaire NUMERIC; -BEGIN - --- récupération de l'année -SELECT ex.annee, it.structure_id -INTO STRICT v_annee, v_structure_id -FROM impositions_tfu it - join exercice ex on ex.id =it.exercice_id -WHERE it.id = p_impositions_tfu_id; - - -select value -into strict v_taux_defaut_sup_sol -from parameters -where name ='TAUX_DEFAUT_SUPERFICIE_AU_SOL'; - -select value -into STRICT v_taux_tfu -from parameters -where name ='TAUX_TFU'; - - -select value -into STRICT v_taux_valeur_locat_prof -from parameters -where name ='TAUX_VALEUR_LOCATIVE_PROFESSIONNELLE'; - -select value -into STRICT v_tfu_piscine_unitaire -from parameters -where name ='TFU_PAR_PISCINE'; - - -INSERT INTO donnees_imposition_tfu( - annee, - code_departement, - nom_departement, - code_commune, - nom_commune, - code_arrondissement, - nom_arrondissement, - code_quartier_village, - nom_quartier_village, - q, - ilot, - parcelle, - nup, - titre_foncier, - num_batiment, - ifu, - npi, - tel_prop, - email_prop, - nom_prop, - prenom_prop, - raison_sociale, - adresse_prop, - tel_sc, - nom_sc, - prenom_sc, - longitude, - latitude, - batie, - exonere, - batiment_exonere, - standing_bat, - categorie_bat, - nombre_piscine, - date_enquete, - structure_id, - zone_rfu_id, - nature_impot, - superficie_parc, - superficie_au_sol_bat, - valeur_batiment, - valeur_locative_adm_metre_carre, - montant_loyer_annuel, - tfu_metre_carre, - tfu_minimum, - impositions_tfu_id, - deleted, - created_at , - created_by , - "source", - updated_at , - updated_by, - categorie_usage, - superficie_au_sol_taux_prop_parc, ---70% de la surperficie au sol de la parcelle - valeur_locative_adm_taux_prop_parc, - tfu_calcule_taux_prop_parc, ----tfu correspondant au 70% - valeur_locative_adm_sup_reel, - valeur_locative_adm, ----------valeur locative administrative - tfu_superficie_au_sol_reel, ----tfu correspondant à la superficie au sol reelle - tfu_piscine, - montant_taxe, ----tfu finale - taux_tfu, ----taux tfu batie - parcelle_id, - batiment_id, - unite_logement_id -) -SELECT - v_annee, - d.code, - d.nom, - c.code, - c.nom, - a.code, - a.nom, - q.code, - q.nom, - p.q, - p.i, - p.p, - p.nup, - ep.numero_titre_foncier, - b.nub, - pers.ifu, - pers.npi, - pers.tel1, - pers.email, - pers.nom, - pers.prenom, - pers.raison_sociale, - pers.adresse, - ep.representant_tel, - ep.representant_nom, - ep.representant_prenom, - p.longitude, - p.latitude, - TRUE, - ( - CURRENT_DATE >= ep.date_debut_exemption - AND CURRENT_DATE <= COALESCE(ep.date_fin_exemption, CURRENT_DATE) - ), - ( - CURRENT_DATE >= eb.date_debut_excemption - AND CURRENT_DATE <= COALESCE(eb.date_fin_excemption, CURRENT_DATE) - ), - cb.standing, - cb.nom, - eb.nombre_piscine, - eb.date_enquete, - st.id, - ep.zone_rfu_id, - 'TFU', - p.superficie, - eb.superficie_au_sol, - COALESCE( - NULLIF(eb.valeur_batiment_reel, 0), - NULLIF(eb.valeur_batiment_calcule, 0), - NULLIF(eb.valeur_batiment_estime, 0), - 0 - ), - brb.valeur_locative, - COALESCE( - NULLIF(eb.montant_locatif_annuel_declare, 0), - NULLIF(eb.montant_locatif_annuel_calcule, 0), - NULLIF(eb.montant_locatif_annuel_estime, 0), - 0 - ), - brb.tfu_metre_carre, - brb.tfu_minimum, - p_impositions_tfu_id, - false, - current_date , - p_user_id , - 'FISCAD', - current_date , - p_user_id, - eb.categorie_usage, - p.superficie*v_taux_defaut_sup_sol/100,---superficie_au_sol_70pour100 - case ----valeur_locative_adm70pour100 - when eb.categorie_usage = 'HABITATION' then (p.superficie * v_taux_defaut_sup_sol/100) * brb.valeur_locative - else 0 - end, - case ----tfu calcule 70 pour 100 superficie parcelle - when eb.categorie_usage= 'HABITATION' then (p.superficie * v_taux_defaut_sup_sol/100) * brb.valeur_locative * v_taux_tfu/100 - else 0 - end, - case -----valeur_locative_adm_sup_reel - when eb.categorie_usage='HABITATION' then eb.superficie_au_sol * brb.valeur_locative - else 0 - end, - 0, ------ valeur_locative_adm : en attente de update - case -----tfu_superficie_au_sol_reel - when eb.categorie_usage='HABITATION' then eb.superficie_au_sol * brb.valeur_locative * v_taux_tfu/100 +eb.nombre_piscine * v_tfu_piscine_unitaire - else 0 - end, - eb.nombre_piscine * v_tfu_piscine_unitaire, - 0, - v_taux_tfu, - p.id, - b.id, - null -FROM parcelle p - LEFT JOIN ( - SELECT DISTINCT ON (parcelle_id) - parcelle_id, - superficie, - personne_id, - numero_titre_foncier, - date_enquete, - representant_tel, - representant_nom, - representant_prenom, - representant_npi, - date_debut_exemption, - date_fin_exemption, - zone_rfu_id - FROM enquete - ORDER BY parcelle_id, date_enquete DESC, id DESC -) ep ON ep.parcelle_id = p.id - LEFT JOIN personne pers - ON pers.id = ep.personne_id - JOIN quartier q ON q.id = p.quartier_id - JOIN arrondissement a ON a.id = q.arrondissement_id - JOIN commune c ON c.id = a.commune_id - JOIN departement d ON d.id = c.departement_id - --JOIN secteur_decoupage sd ON sd.quartier_id = q.id - JOIN ( - SELECT DISTINCT ON (quartier_id) - quartier_id, - secteur_id - FROM secteur_decoupage - ORDER BY quartier_id - ) sd ON sd.quartier_id = q.id - JOIN secteur sect ON sect.id = sd.secteur_id - JOIN section ses ON ses.id = sect.section_id - JOIN "structure" st ON st.id = ses.structure_id - JOIN batiment b ON b.parcelle_id = p.id - JOIN ( - SELECT DISTINCT ON (batiment_id) - batiment_id, - superficie_au_sol, - nombre_piscine, - categorie_batiment_id, - date_enquete, - montant_locatif_annuel_declare, - montant_locatif_annuel_calcule, - montant_locatif_annuel_estime, - date_debut_excemption, - date_fin_excemption, - valeur_batiment_reel, - valeur_batiment_calcule, - valeur_batiment_estime, - u.categorie_usage - FROM enquete_batiment eb - join usage u on u.id=eb.usage_id - ORDER BY batiment_id, date_enquete DESC, eb.id DESC -) eb ON eb.batiment_id = b.id - - JOIN categorie_batiment cb - ON cb.id = eb.categorie_batiment_id - JOIN LATERAL ( - SELECT * - FROM barem_rfu_bati br - WHERE br.categorie_batiment_id = cb.id - AND br.arrondissement_id = a.id - AND (br.quartier_id = q.id OR br.quartier_id IS NULL) - ORDER BY br.quartier_id DESC NULLS LAST - LIMIT 1 -) brb ON TRUE -WHERE p.batie = TRUE - AND NOT EXISTS ( - SELECT 1 - FROM unite_logement ul - WHERE ul.batiment_id = b.id - ) - AND st.id = v_structure_id -ON CONFLICT DO NOTHING; - -GET DIAGNOSTICS v_rows_inserted = ROW_COUNT; - -UPDATE donnees_imposition_tfu dtfu -SET - valeur_locative_adm = - CASE - WHEN categorie_usage = 'HABITATION' AND superficie_au_sol_bat <> 0 - THEN valeur_locative_adm_sup_reel - - WHEN categorie_usage = 'HABITATION' AND superficie_au_sol_bat = 0 - THEN valeur_locative_adm_taux_prop_parc - - WHEN categorie_usage IN ('PROFESSIONNELLE','MIXTE') AND valeur_batiment <> 0 - THEN valeur_batiment * (v_taux_valeur_locat_prof/100) - - WHEN categorie_usage IN ('PROFESSIONNELLE','MIXTE') AND valeur_batiment = 0 - THEN montant_loyer_annuel - END, - - montant_taxe = - CASE - WHEN categorie_usage = 'HABITATION' AND superficie_au_sol_bat <> 0 THEN - CASE - WHEN tfu_minimum < valeur_locative_adm_sup_reel * (v_taux_tfu/100) + tfu_piscine - THEN valeur_locative_adm_sup_reel * (v_taux_tfu/100) + tfu_piscine - ELSE tfu_minimum - END - - WHEN categorie_usage = 'HABITATION' AND superficie_au_sol_bat = 0 THEN - CASE - WHEN tfu_minimum < valeur_locative_adm_taux_prop_parc * (v_taux_tfu/100) + tfu_piscine - THEN valeur_locative_adm_taux_prop_parc * (v_taux_tfu/100) + tfu_piscine - ELSE tfu_minimum - END - - WHEN categorie_usage IN ('PROFESSIONNELLE','MIXTE') AND valeur_batiment <> 0 THEN - CASE - WHEN tfu_minimum < valeur_batiment * (v_taux_valeur_locat_prof/100) * (v_taux_tfu/100) - THEN valeur_batiment * (v_taux_valeur_locat_prof/100) * (v_taux_tfu/100) - ELSE tfu_minimum - END - - WHEN categorie_usage IN ('PROFESSIONNELLE','MIXTE') AND valeur_batiment = 0 THEN - CASE - WHEN tfu_minimum < montant_loyer_annuel * (v_taux_tfu/100) - THEN montant_loyer_annuel * (v_taux_tfu/100) - ELSE tfu_minimum - END - END -WHERE impositions_tfu_id = p_impositions_tfu_id - AND batie = TRUE - AND NOT EXISTS ( - SELECT 1 - FROM unite_logement ul - WHERE ul.batiment_id = dtfu.batiment_id -); -RETURN v_rows_inserted; -END; -$$;*/ - CREATE OR REPLACE FUNCTION public.generer_donnees_imposition_tfu_batie( p_impositions_tfu_id BIGINT, p_user_id BIGINT @@ -466,12 +120,15 @@ BEGIN valeur_locative_adm, -- valeur locative administrative finale tfu_superficie_au_sol_reel, tfu_piscine, + montant_taxe_brut, montant_taxe, -- TFU finale taux_tfu, parcelle_id, batiment_id, unite_logement_id, - personne_id + personne_id, + nombre_ulog, + nombre_bat ) SELECT v_annee, @@ -515,7 +172,7 @@ BEGIN eb.date_enquete, st.id, ep.zone_rfu_id, - 'TFU', + 'FB', p.superficie, eb.superficie_au_sol, -- valeur_batiment : première valeur non nulle non zéro @@ -607,7 +264,48 @@ BEGIN -- tfu_piscine eb.nombre_piscine * v_tfu_piscine_unitaire, + -- --------------------------------------------------------------- + -- montant_taxe_brut ← sans prise en compte du minimum + -- --------------------------------------------------------------- + ( + -- On matérialise valeur_batiment et valeur_locative une seule fois + WITH calc AS ( + SELECT + COALESCE(NULLIF(eb.valeur_batiment_reel, 0), + NULLIF(eb.valeur_batiment_calcule, 0), + NULLIF(eb.valeur_batiment_estime, 0), 0) AS vb, + COALESCE(NULLIF(eb.montant_locatif_annuel_declare, 0), + NULLIF(eb.montant_locatif_annuel_calcule, 0), + NULLIF(eb.montant_locatif_annuel_estime, 0), 0) AS loyer, + eb.superficie_au_sol * brb.valeur_locative AS vla_reel, + (p.superficie * v_taux_defaut_sup_sol / 100.0) + * brb.valeur_locative AS vla_70 + ) + SELECT + CASE + WHEN eb.categorie_usage = 'HABITATION' + AND eb.superficie_au_sol <> 0 + THEN calc.vla_reel * v_taux_tfu_ratio + + eb.nombre_piscine * v_tfu_piscine_unitaire + WHEN eb.categorie_usage = 'HABITATION' + AND eb.superficie_au_sol = 0 + THEN calc.vla_70 * v_taux_tfu_ratio + + eb.nombre_piscine * v_tfu_piscine_unitaire + + WHEN eb.categorie_usage IN ('PROFESSIONNELLE', 'MIXTE') + AND calc.vb <> 0 + THEN calc.vb * v_taux_vlp_ratio * v_taux_tfu_ratio + + WHEN eb.categorie_usage IN ('PROFESSIONNELLE', 'MIXTE') + AND calc.vb = 0 + THEN calc.loyer * v_taux_tfu_ratio + + ELSE brb.tfu_minimum + + END + FROM calc + ), -- --------------------------------------------------------------- -- montant_taxe ← calculé directement (plus d'UPDATE) -- Utilise des CTE inline via expression pour éviter la redondance @@ -658,7 +356,13 @@ BEGIN p.id, b.id, NULL, - ep.personne_id + ep.personne_id, + (select count(*) + from unite_logement ulog + where ulog.batiment_id= b.id), + (select count(*) + from batiment bat + where bat.parcelle_id= p.id) FROM parcelle p -- Dernière enquête parcelle LEFT JOIN LATERAL ( @@ -742,10 +446,10 @@ BEGIN ) brb ON TRUE WHERE p.batie = TRUE - AND ul_filter.batiment_id IS NULL -- anti-join : pas d'unité logement - AND st.id = v_structure_id + --AND ul_filter.batiment_id IS NULL -- anti-join : pas d'unité logement + AND st.id = v_structure_id ; - ON CONFLICT DO NOTHING; + -- ON CONFLICT DO NOTHING; GET DIAGNOSTICS v_rows_inserted = ROW_COUNT; diff --git a/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/generer_donnees_imposition_tfu_batie_une_parcelle.sql b/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/generer_donnees_imposition_tfu_batie_une_parcelle.sql new file mode 100644 index 0000000..a75c0c7 --- /dev/null +++ b/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/generer_donnees_imposition_tfu_batie_une_parcelle.sql @@ -0,0 +1,464 @@ +CREATE OR REPLACE FUNCTION public.generer_donnees_imposition_tfu_batie_une_parcelle( + p_impositions_tfu_id BIGINT, + p_user_id BIGINT, + p_parcelle_id BIGINT +) + RETURNS INTEGER + LANGUAGE plpgsql +AS $$ +DECLARE + v_rows_inserted INTEGER; + v_annee BIGINT; + v_structure_id BIGINT; + v_taux_defaut_sup_sol NUMERIC; + v_taux_tfu NUMERIC; + v_taux_tfu_ratio NUMERIC; -- v_taux_tfu / 100 (pré-calculé) + v_taux_valeur_locat_prof NUMERIC; + v_taux_vlp_ratio NUMERIC; -- v_taux_valeur_locat_prof / 100 (pré-calculé) + v_tfu_piscine_unitaire NUMERIC; + v_today DATE; +BEGIN + + v_today := CURRENT_DATE; + + -- ------------------------------------------------------------------------- + -- 1. Récupération de l'année et de la structure (inchangée) + -- ------------------------------------------------------------------------- + SELECT ex.annee, it.structure_id + INTO STRICT v_annee, v_structure_id + FROM impositions_tfu it + JOIN exercice ex ON ex.id = it.exercice_id + WHERE it.id = p_impositions_tfu_id; + + -- ------------------------------------------------------------------------- + -- 2. Récupération des 4 paramètres en UNE seule requête + -- (évite 4 accès séquentiels à la table parameters) + -- ------------------------------------------------------------------------- + SELECT + MAX(value) FILTER (WHERE name = 'TAUX_DEFAUT_SUPERFICIE_AU_SOL'), + MAX(value) FILTER (WHERE name = 'TAUX_TFU'), + MAX(value) FILTER (WHERE name = 'TAUX_VALEUR_LOCATIVE_PROFESSIONNELLE'), + MAX(value) FILTER (WHERE name = 'TFU_PAR_PISCINE') + INTO STRICT + v_taux_defaut_sup_sol, + v_taux_tfu, + v_taux_valeur_locat_prof, + v_tfu_piscine_unitaire + FROM parameters + WHERE name IN ( + 'TAUX_DEFAUT_SUPERFICIE_AU_SOL', + 'TAUX_TFU', + 'TAUX_VALEUR_LOCATIVE_PROFESSIONNELLE', + 'TFU_PAR_PISCINE' + ); + + -- Ratios pré-calculés pour éviter la division répétée dans le SELECT + v_taux_tfu_ratio := v_taux_tfu / 100.0; + v_taux_vlp_ratio := v_taux_valeur_locat_prof / 100.0; + + -- ------------------------------------------------------------------------- + -- 3. INSERT avec calcul complet de valeur_locative_adm et montant_taxe + -- → supprime l'UPDATE post-INSERT (économie d'un second scan de table) + -- ------------------------------------------------------------------------- + INSERT INTO donnees_imposition_tfu ( + annee, + code_departement, + nom_departement, + code_commune, + nom_commune, + code_arrondissement, + nom_arrondissement, + code_quartier_village, + nom_quartier_village, + q, + ilot, + parcelle, + nup, + titre_foncier, + num_batiment, + ifu, + npi, + tel_prop, + email_prop, + nom_prop, + prenom_prop, + raison_sociale, + adresse_prop, + tel_sc, + nom_sc, + prenom_sc, + longitude, + latitude, + batie, + exonere, + batiment_exonere, + standing_bat, + categorie_bat, + nombre_piscine, + date_enquete, + structure_id, + zone_rfu_id, + nature_impot, + superficie_parc, + superficie_au_sol_bat, + valeur_batiment, + valeur_locative_adm_metre_carre, + montant_loyer_annuel, + tfu_metre_carre, + tfu_minimum, + impositions_tfu_id, + deleted, + created_at, + created_by, + "source", + updated_at, + updated_by, + categorie_usage, + superficie_au_sol_taux_prop_parc, -- 70 % superficie parcelle + valeur_locative_adm_taux_prop_parc, + tfu_calcule_taux_prop_parc, -- TFU à 70 % + valeur_locative_adm_sup_reel, + valeur_locative_adm, -- valeur locative administrative finale + tfu_superficie_au_sol_reel, + tfu_piscine, + montant_taxe_brut, + montant_taxe, -- TFU finale + taux_tfu, + parcelle_id, + batiment_id, + unite_logement_id, + personne_id, + nombre_ulog, + nombre_bat + ) + SELECT + v_annee, + d.code, + d.nom, + c.code, + c.nom, + a.code, + a.nom, + q.code, + q.nom, + p.q, + p.i, + p.p, + p.nup, + ep.numero_titre_foncier, + b.nub, + pers.ifu, + pers.npi, + pers.tel1, + pers.email, + pers.nom, + pers.prenom, + pers.raison_sociale, + pers.adresse, + ep.representant_tel, + ep.representant_nom, + ep.representant_prenom, + p.longitude, + p.latitude, + TRUE, + -- exonere parcelle + (v_today BETWEEN ep.date_debut_exemption + AND COALESCE(ep.date_fin_exemption, v_today)), + -- exonere batiment + (v_today BETWEEN eb.date_debut_excemption + AND COALESCE(eb.date_fin_excemption, v_today)), + cb.standing, + cb.nom, + eb.nombre_piscine, + eb.date_enquete, + st.id, + ep.zone_rfu_id, + 'FB', + p.superficie, + eb.superficie_au_sol, + -- valeur_batiment : première valeur non nulle non zéro + COALESCE( + NULLIF(eb.valeur_batiment_reel, 0), + NULLIF(eb.valeur_batiment_calcule, 0), + NULLIF(eb.valeur_batiment_estime, 0), + 0 + ), + brb.valeur_locative, + -- montant_loyer_annuel + COALESCE( + NULLIF(eb.montant_locatif_annuel_declare, 0), + NULLIF(eb.montant_locatif_annuel_calcule, 0), + NULLIF(eb.montant_locatif_annuel_estime, 0), + 0 + ), + brb.tfu_metre_carre, + brb.tfu_minimum, + p_impositions_tfu_id, + FALSE, + v_today, + p_user_id, + 'FISCAD', + v_today, + p_user_id, + eb.categorie_usage, + + -- superficie_au_sol_taux_prop_parc (70 % parcelle) + p.superficie * v_taux_defaut_sup_sol / 100.0, + + -- valeur_locative_adm_taux_prop_parc + CASE WHEN eb.categorie_usage = 'HABITATION' + THEN (p.superficie * v_taux_defaut_sup_sol / 100.0) * brb.valeur_locative + ELSE 0 + END, + + -- tfu_calcule_taux_prop_parc + CASE WHEN eb.categorie_usage = 'HABITATION' + THEN (p.superficie * v_taux_defaut_sup_sol / 100.0) * brb.valeur_locative * v_taux_tfu_ratio + ELSE 0 + END, + + -- valeur_locative_adm_sup_reel + CASE WHEN eb.categorie_usage = 'HABITATION' + THEN eb.superficie_au_sol * brb.valeur_locative + ELSE 0 + END, + + -- --------------------------------------------------------------- + -- 🔧 CORRECTION : valeur_locative_adm avec tests explicites + -- --------------------------------------------------------------- + CASE + WHEN eb.categorie_usage = 'HABITATION' + AND eb.superficie_au_sol <> 0 + THEN eb.superficie_au_sol * brb.valeur_locative + + WHEN eb.categorie_usage = 'HABITATION' + AND eb.superficie_au_sol = 0 + THEN (p.superficie * v_taux_defaut_sup_sol / 100.0) * brb.valeur_locative + + -- ✅ Test explicite : valeur_batiment <> 0 + WHEN eb.categorie_usage IN ('PROFESSIONNELLE', 'MIXTE') + AND COALESCE(NULLIF(eb.valeur_batiment_reel, 0), + NULLIF(eb.valeur_batiment_calcule, 0), + NULLIF(eb.valeur_batiment_estime, 0), 0) <> 0 + THEN COALESCE(NULLIF(eb.valeur_batiment_reel, 0), + NULLIF(eb.valeur_batiment_calcule, 0), + NULLIF(eb.valeur_batiment_estime, 0), 0) + * v_taux_vlp_ratio + + -- ✅ Test explicite : valeur_batiment = 0 + WHEN eb.categorie_usage IN ('PROFESSIONNELLE', 'MIXTE') + AND COALESCE(NULLIF(eb.valeur_batiment_reel, 0), + NULLIF(eb.valeur_batiment_calcule, 0), + NULLIF(eb.valeur_batiment_estime, 0), 0) = 0 + THEN COALESCE(NULLIF(eb.montant_locatif_annuel_declare, 0), + NULLIF(eb.montant_locatif_annuel_calcule, 0), + NULLIF(eb.montant_locatif_annuel_estime, 0), 0) + + ELSE 0 + END, + + -- tfu_superficie_au_sol_reel + CASE WHEN eb.categorie_usage = 'HABITATION' + THEN eb.superficie_au_sol * brb.valeur_locative * v_taux_tfu_ratio * eb.nombre_piscine * v_tfu_piscine_unitaire + ELSE 0 + END, + + -- tfu_piscine + eb.nombre_piscine * v_tfu_piscine_unitaire, + -- --------------------------------------------------------------- + -- montant_taxe_brut ← sans prise en compte du minimum + -- --------------------------------------------------------------- + ( + -- On matérialise valeur_batiment et valeur_locative une seule fois + WITH calc AS ( + SELECT + COALESCE(NULLIF(eb.valeur_batiment_reel, 0), + NULLIF(eb.valeur_batiment_calcule, 0), + NULLIF(eb.valeur_batiment_estime, 0), 0) AS vb, + COALESCE(NULLIF(eb.montant_locatif_annuel_declare, 0), + NULLIF(eb.montant_locatif_annuel_calcule, 0), + NULLIF(eb.montant_locatif_annuel_estime, 0), 0) AS loyer, + eb.superficie_au_sol * brb.valeur_locative AS vla_reel, + (p.superficie * v_taux_defaut_sup_sol / 100.0) + * brb.valeur_locative AS vla_70 + ) + SELECT + CASE + WHEN eb.categorie_usage = 'HABITATION' + AND eb.superficie_au_sol <> 0 + THEN calc.vla_reel * v_taux_tfu_ratio + + eb.nombre_piscine * v_tfu_piscine_unitaire + + WHEN eb.categorie_usage = 'HABITATION' + AND eb.superficie_au_sol = 0 + THEN calc.vla_70 * v_taux_tfu_ratio + + eb.nombre_piscine * v_tfu_piscine_unitaire + + WHEN eb.categorie_usage IN ('PROFESSIONNELLE', 'MIXTE') + AND calc.vb <> 0 + THEN calc.vb * v_taux_vlp_ratio * v_taux_tfu_ratio + + WHEN eb.categorie_usage IN ('PROFESSIONNELLE', 'MIXTE') + AND calc.vb = 0 + THEN calc.loyer * v_taux_tfu_ratio + + ELSE brb.tfu_minimum + + END + FROM calc + ), + -- --------------------------------------------------------------- + -- montant_taxe ← calculé directement (plus d'UPDATE) + -- Utilise des CTE inline via expression pour éviter la redondance + -- --------------------------------------------------------------- + ( + -- On matérialise valeur_batiment et valeur_locative une seule fois + WITH calc AS ( + SELECT + COALESCE(NULLIF(eb.valeur_batiment_reel, 0), + NULLIF(eb.valeur_batiment_calcule, 0), + NULLIF(eb.valeur_batiment_estime, 0), 0) AS vb, + COALESCE(NULLIF(eb.montant_locatif_annuel_declare, 0), + NULLIF(eb.montant_locatif_annuel_calcule, 0), + NULLIF(eb.montant_locatif_annuel_estime, 0), 0) AS loyer, + eb.superficie_au_sol * brb.valeur_locative AS vla_reel, + (p.superficie * v_taux_defaut_sup_sol / 100.0) + * brb.valeur_locative AS vla_70 + ) + SELECT + CASE + WHEN eb.categorie_usage = 'HABITATION' + AND eb.superficie_au_sol <> 0 + THEN GREATEST(brb.tfu_minimum, + calc.vla_reel * v_taux_tfu_ratio + + eb.nombre_piscine * v_tfu_piscine_unitaire) + + WHEN eb.categorie_usage = 'HABITATION' + AND eb.superficie_au_sol = 0 + THEN GREATEST(brb.tfu_minimum, + calc.vla_70 * v_taux_tfu_ratio + + eb.nombre_piscine * v_tfu_piscine_unitaire) + + WHEN eb.categorie_usage IN ('PROFESSIONNELLE', 'MIXTE') + AND calc.vb <> 0 + THEN GREATEST(brb.tfu_minimum, + calc.vb * v_taux_vlp_ratio * v_taux_tfu_ratio) + + WHEN eb.categorie_usage IN ('PROFESSIONNELLE', 'MIXTE') + AND calc.vb = 0 + THEN GREATEST(brb.tfu_minimum, + calc.loyer * v_taux_tfu_ratio) + + ELSE brb.tfu_minimum + END + FROM calc + ), + v_taux_tfu, + p.id, + b.id, + NULL, + ep.personne_id, + (select count(*) + from unite_logement ulog + where ulog.batiment_id= b.id), + (select count(*) + from batiment bat + where bat.parcelle_id= p.id) + FROM parcelle p + -- Dernière enquête parcelle + LEFT JOIN LATERAL ( + SELECT + parcelle_id, + superficie, + personne_id, + numero_titre_foncier, + date_enquete, + representant_tel, + representant_nom, + representant_prenom, + representant_npi, + date_debut_exemption, + date_fin_exemption, + zone_rfu_id + FROM enquete + WHERE parcelle_id = p.id + ORDER BY date_enquete DESC, id DESC + LIMIT 1 + ) ep ON TRUE + + LEFT JOIN personne pers ON pers.id = ep.personne_id + + JOIN quartier q ON q.id = p.quartier_id + JOIN arrondissement a ON a.id = q.arrondissement_id + JOIN commune c ON c.id = a.commune_id + JOIN departement d ON d.id = c.departement_id + + -- Rattachement structure via secteur (DISTINCT ON → LATERAL plus lisible) + JOIN LATERAL ( + SELECT secteur_id + FROM secteur_decoupage + WHERE quartier_id = q.id + ORDER BY quartier_id + LIMIT 1 + ) sd ON TRUE + JOIN secteur sect ON sect.id = sd.secteur_id + JOIN section ses ON ses.id = sect.section_id + JOIN "structure" st ON st.id = ses.structure_id + + -- Bâtiments sans unités logement (anti-join via LEFT JOIN … IS NULL) + JOIN batiment b ON b.parcelle_id = p.id + LEFT JOIN unite_logement ul_filter ON ul_filter.batiment_id = b.id + + -- Dernière enquête bâtiment + JOIN LATERAL ( + SELECT + eb2.batiment_id, + eb2.superficie_au_sol, + eb2.nombre_piscine, + eb2.categorie_batiment_id, + eb2.date_enquete, + eb2.montant_locatif_annuel_declare, + eb2.montant_locatif_annuel_calcule, + eb2.montant_locatif_annuel_estime, + eb2.date_debut_excemption, + eb2.date_fin_excemption, + eb2.valeur_batiment_reel, + eb2.valeur_batiment_calcule, + eb2.valeur_batiment_estime, + u.categorie_usage + FROM enquete_batiment eb2 + JOIN usage u ON u.id = eb2.usage_id + WHERE eb2.batiment_id = b.id + ORDER BY eb2.date_enquete DESC, eb2.id DESC + LIMIT 1 + ) eb ON TRUE + + JOIN categorie_batiment cb ON cb.id = eb.categorie_batiment_id + + -- Barème RFU bâti (inchangé) + JOIN LATERAL ( + SELECT * + FROM barem_rfu_bati br + WHERE br.categorie_batiment_id = cb.id + AND br.arrondissement_id = a.id + AND (br.quartier_id = q.id OR br.quartier_id IS NULL) + ORDER BY br.quartier_id DESC NULLS LAST + LIMIT 1 + ) brb ON TRUE + + WHERE p.batie = TRUE + --AND ul_filter.batiment_id IS NULL -- anti-join : pas d'unité logement + AND st.id = v_structure_id + AND p.id = p_parcelle_id + AND NOT EXISTS(select 1 from donnees_imposition_tfu dimptfu + where dimptfu.batiment_id=b.id + and dimptfu.annee=v_annee + and dimptfu.nature_impot='FB'); + + -- ON CONFLICT DO NOTHING; + + GET DIAGNOSTICS v_rows_inserted = ROW_COUNT; + + RETURN v_rows_inserted; +END; +$$; diff --git a/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/generer_donnees_imposition_tfu_batie_unite_logement.sql b/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/generer_donnees_imposition_tfu_batie_unite_logement.sql index 8bd6525..954d133 100644 --- a/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/generer_donnees_imposition_tfu_batie_unite_logement.sql +++ b/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/generer_donnees_imposition_tfu_batie_unite_logement.sql @@ -1,398 +1,3 @@ -/*CREATE OR REPLACE FUNCTION public.generer_donnees_imposition_tfu_batie_unite_logement( - p_impositions_tfu_id BIGINT, - p_user_id BIGINT -) -RETURNS INTEGER -LANGUAGE plpgsql -AS -$$ -DECLARE -v_rows_inserted INTEGER; - v_annee BIGINT; - v_structure_id BIGINT; - v_taux_defaut_sup_sol NUMERIC; - v_taux_tfu NUMERIC; - v_taux_valeur_locat_prof NUMERIC; - v_tfu_piscine_unitaire NUMERIC; -BEGIN - --- récupération de l'année -SELECT ex.annee, it.structure_id -INTO STRICT v_annee, v_structure_id -FROM impositions_tfu it - join exercice ex on ex.id =it.exercice_id -WHERE it.id = p_impositions_tfu_id; - - -select value -into strict v_taux_defaut_sup_sol -from parameters -where name ='TAUX_DEFAUT_SUPERFICIE_AU_SOL'; - -select value -into STRICT v_taux_tfu -from parameters -where name ='TAUX_TFU'; - -RAISE NOTICE 'v_taux_tfu = %', v_taux_tfu; - -select value -into STRICT v_taux_valeur_locat_prof -from parameters -where name ='TAUX_VALEUR_LOCATIVE_PROFESSIONNELLE'; - -select value -into STRICT v_tfu_piscine_unitaire -from parameters -where name ='TFU_PAR_PISCINE'; - -INSERT INTO donnees_imposition_tfu( - annee, - code_departement, - nom_departement, - code_commune, - nom_commune, - code_arrondissement, - nom_arrondissement, - code_quartier_village, - nom_quartier_village, - q, - ilot, - parcelle, - nup, - titre_foncier, - num_batiment, - num_unite_logement, - ifu, - npi, - tel_prop, - email_prop, - nom_prop, - prenom_prop, - raison_sociale, - adresse_prop, - tel_sc, - nom_sc, - prenom_sc, - longitude, - latitude, - batie, - exonere, - batiment_exonere, - unite_logement_exonere, - standing_bat, - categorie_bat, - nombre_piscine, - date_enquete, - structure_id, - zone_rfu_id, - nature_impot, - superficie_parc, - superficie_au_sol_bat, - superficie_au_sol_ulog, - valeur_batiment, - valeur_locative_adm_metre_carre, - montant_loyer_annuel, - tfu_metre_carre, - tfu_minimum, - impositions_tfu_id, - deleted, - created_at , - created_by , - "source", - updated_at , - updated_by, - categorie_usage, - superficie_au_sol_taux_prop_parc, ---70% de la surperficie au sol de la parcelle - valeur_locative_adm_taux_prop_parc, - tfu_calcule_taux_prop_parc, ----tfu correspondant au 70% - valeur_locative_adm_sup_reel, - valeur_locative_adm, ----------valeur locative administrative - tfu_superficie_au_sol_reel, ----tfu correspondant à la superficie au sol reelle - tfu_piscine, - montant_taxe, ----tfu finale - taux_tfu, ----taux tfu batie - parcelle_id, - batiment_id, - unite_logement_id -) -SELECT - v_annee, - d.code, - d.nom, - c.code, - c.nom, - a.code, - a.nom, - q.code, - q.nom, - p.q, - p.i, - p.p, - p.nup, - ep.numero_titre_foncier, - b.nub, - ul.nul, - eul.ifu, - eul.npi, - eul.tel1, - eul.email, - eul.nom, - eul.prenom, - eul.raison_sociale, - eul.adresse, - eul.representant_tel, - eul.representant_nom, - eul.representant_prenom, - p.longitude, - p.latitude, - TRUE, - ( - CURRENT_DATE >= ep.date_debut_exemption - AND CURRENT_DATE <= COALESCE(ep.date_fin_exemption, CURRENT_DATE) - ), - ( - CURRENT_DATE >= eb.date_debut_excemption - AND CURRENT_DATE <= COALESCE(eb.date_fin_excemption, CURRENT_DATE) - ), - ( - CURRENT_DATE >= eul.date_debut_exemption - AND CURRENT_DATE <= COALESCE(eul.date_fin_exemption, CURRENT_DATE) - ), - cb.standing, - cb.nom, - CASE - WHEN eul.nombre_piscine is null then 0 - else eul.nombre_piscine - END, - eul.date_enquete, - st.id, - ep.zone_rfu_id, - 'TFU', - p.superficie, - eb.superficie_au_sol, - eul.superficie_au_sol, - CASE -------valeur_batiment - WHEN eul.valeur_unite_logement_reel IS NOT NULL AND eul.valeur_unite_logement_reel <> 0 THEN eul.valeur_unite_logement_reel - WHEN eul.valeur_unite_logement_calcule IS NOT NULL AND eul.valeur_unite_logement_calcule <> 0 THEN eul.valeur_unite_logement_calcule - WHEN eul.valeur_unite_logement_estime IS NOT NULL AND eul.valeur_unite_logement_estime <> 0 THEN eul.valeur_unite_logement_estime - ELSE 0 - END, - brb.valeur_locative, - CASE ----- montant_loyer_annuel - WHEN eul.montant_locatif_annuel_declare IS NOT NULL AND eul.montant_locatif_annuel_declare <> 0 THEN eul.montant_locatif_annuel_declare - WHEN eul.montant_locatif_annuel_calcule IS NOT NULL AND eul.montant_locatif_annuel_calcule <> 0 THEN eul.montant_locatif_annuel_calcule - WHEN eul.montant_locatif_annuel_estime IS NOT NULL AND eul.montant_locatif_annuel_estime <> 0 THEN eul.montant_locatif_annuel_estime - ELSE 0 - END, - brb.tfu_metre_carre, - brb.tfu_minimum, - p_impositions_tfu_id, - false, - current_date, - p_user_id, - 'FISCAD', - current_date, - p_user_id, - eul.categorie_usage, - p.superficie * v_taux_defaut_sup_sol/100,---superficie_au_sol_70pour100 - case ----valeur_locative_adm70pour100 - when eul.categorie_usage = 'HABITATION' then (p.superficie * v_taux_defaut_sup_sol/100) * brb.valeur_locative - else 0 - end, - case ----tfu calcule 70 pour 100 superficie parcelle - when eul.categorie_usage= 'HABITATION' then (p.superficie * v_taux_defaut_sup_sol/100) * brb.valeur_locative * v_taux_tfu/100 - else 0 - end, - case -----valeur_locative_adm_sup_reel - when eul.categorie_usage='HABITATION' then eul.superficie_au_sol * brb.valeur_locative - else 0 - end, - 0, ------ valeur_locative_adm : en attente de update - case -----tfu_superficie_au_sol_reel - when eul.categorie_usage='HABITATION' then eul.superficie_au_sol * brb.valeur_locative * 6/100 - else 0 - end, - CASE - WHEN eul.nombre_piscine is null then 0 - else eul.nombre_piscine * v_tfu_piscine_unitaire - END, - 0, - v_taux_tfu, - p.id, - b.id, - ul.id -FROM parcelle p - LEFT JOIN ( - SELECT DISTINCT ON (parcelle_id) - parcelle_id, - superficie, - personne_id, - numero_titre_foncier, - date_enquete, - representant_tel, - representant_nom, - representant_prenom, - representant_npi, - date_debut_exemption, - date_fin_exemption, - zone_rfu_id - FROM enquete - ORDER BY parcelle_id, date_enquete DESC, id DESC -) ep ON ep.parcelle_id = p.id - LEFT JOIN personne pers - ON pers.id = ep.personne_id - JOIN quartier q ON q.id = p.quartier_id - JOIN arrondissement a ON a.id = q.arrondissement_id - JOIN commune c ON c.id = a.commune_id - JOIN departement d ON d.id = c.departement_id - --JOIN secteur_decoupage sd ON sd.quartier_id = q.id - JOIN ( - SELECT DISTINCT ON (quartier_id) - quartier_id, - secteur_id - FROM secteur_decoupage - ORDER BY quartier_id - ) sd ON sd.quartier_id = q.id - JOIN secteur sect ON sect.id = sd.secteur_id - JOIN section ses ON ses.id = sect.section_id - JOIN "structure" st ON st.id = ses.structure_id - JOIN batiment b ON b.parcelle_id = p.id - JOIN ( - SELECT DISTINCT ON (batiment_id) - batiment_id, - superficie_au_sol, - nombre_piscine, - categorie_batiment_id, - date_enquete, - montant_locatif_annuel_declare, - montant_locatif_annuel_calcule, - montant_locatif_annuel_estime, - date_debut_excemption, - date_fin_excemption, - valeur_batiment_reel, - valeur_batiment_calcule, - valeur_batiment_estime, - u.categorie_usage - FROM enquete_batiment eb - join usage u on u.id=eb.usage_id - ORDER BY batiment_id, date_enquete DESC, eb.id DESC -) eb ON eb.batiment_id = b.id - JOIN unite_logement ul on ul.batiment_id = b.id - JOIN ( - SELECT DISTINCT ON (eult.unite_logement_id) - eult.unite_logement_id, - pers1.id, - pers1.ifu, - pers1.npi, - pers1.tel1, - pers1.email, - pers1.nom, - pers1.prenom, - pers1.raison_sociale, - pers1.adresse, - eult.nombre_piscine, - eult.categorie_batiment_id, - eult.superficie_au_sol, - eult.superficie_louee, - eult.nbre_piece, - eult.date_enquete, - eult.montant_locatif_annuel_calcule, - eult.montant_locatif_annuel_declare, - eult.montant_locatif_annuel_estime, - eult.date_debut_exemption, - eult.date_fin_exemption, - eult.representant_nom, - eult.representant_prenom, - eult.representant_tel, - eult.valeur_unite_logement_reel, - eult.valeur_unite_logement_calcule, - eult.valeur_unite_logement_estime, - u.categorie_usage - FROM enquete_unite_logement eult - join usage u on u.id=eult.usage_id - left join personne pers1 on pers1.id = eult.personne_id - ORDER BY unite_logement_id, date_enquete DESC, eult.id DESC -) eul ON eul.unite_logement_id = ul.id - JOIN categorie_batiment cb - ON cb.id = eul.categorie_batiment_id - JOIN LATERAL ( - SELECT * - FROM barem_rfu_bati br - WHERE br.categorie_batiment_id = cb.id - AND br.arrondissement_id = a.id - AND (br.quartier_id = q.id OR br.quartier_id IS NULL) - ORDER BY br.quartier_id DESC NULLS LAST - LIMIT 1 -) brb ON TRUE -WHERE p.batie = TRUE - AND EXISTS ( - SELECT 1 - FROM unite_logement ul - WHERE ul.batiment_id = b.id - ) - AND st.id = v_structure_id -ON CONFLICT DO NOTHING; - -GET DIAGNOSTICS v_rows_inserted = ROW_COUNT; - -UPDATE donnees_imposition_tfu dtfu -SET - valeur_locative_adm = - CASE - WHEN categorie_usage = 'HABITATION' AND superficie_au_sol_ulog <> 0 - THEN valeur_locative_adm_sup_reel - - WHEN categorie_usage = 'HABITATION' AND superficie_au_sol_ulog = 0 - THEN valeur_locative_adm_taux_prop_parc - - WHEN categorie_usage IN ('PROFESSIONNELLE','MIXTE') AND valeur_batiment <> 0 - THEN valeur_batiment * (v_taux_valeur_locat_prof/100) - - WHEN categorie_usage IN ('PROFESSIONNELLE','MIXTE') AND valeur_batiment = 0 - THEN montant_loyer_annuel - END, - - montant_taxe = - CASE - WHEN categorie_usage = 'HABITATION' AND superficie_au_sol_ulog <> 0 THEN - CASE - WHEN tfu_minimum < valeur_locative_adm_sup_reel * (v_taux_tfu/100) + tfu_piscine - THEN valeur_locative_adm_sup_reel * (v_taux_tfu/100) + tfu_piscine - ELSE tfu_minimum - END - - WHEN categorie_usage = 'HABITATION' AND superficie_au_sol_ulog = 0 THEN - CASE - WHEN tfu_minimum < valeur_locative_adm_taux_prop_parc * (v_taux_tfu/100) + tfu_piscine - THEN valeur_locative_adm_taux_prop_parc * (v_taux_tfu/100) + tfu_piscine - ELSE tfu_minimum - END - - WHEN categorie_usage IN ('PROFESSIONNELLE','MIXTE') AND valeur_batiment <> 0 THEN - CASE - WHEN tfu_minimum < valeur_batiment * (v_taux_valeur_locat_prof/100) * (v_taux_tfu/100) - THEN valeur_batiment * (v_taux_valeur_locat_prof/100) * (v_taux_tfu/100) - ELSE tfu_minimum - END - - WHEN categorie_usage IN ('PROFESSIONNELLE','MIXTE') AND valeur_batiment = 0 THEN - CASE - WHEN tfu_minimum < montant_loyer_annuel * (v_taux_tfu/100) - THEN montant_loyer_annuel * (v_taux_tfu/100) - ELSE tfu_minimum - END - END -WHERE impositions_tfu_id = p_impositions_tfu_id - AND batie = TRUE - AND EXISTS ( - SELECT 1 - FROM unite_logement ul - WHERE ul.batiment_id = dtfu.batiment_id -); -RETURN v_rows_inserted; -END; -$$;*/ CREATE OR REPLACE FUNCTION public.generer_donnees_imposition_tfu_batie_unite_logement( p_impositions_tfu_id BIGINT, p_user_id BIGINT @@ -446,6 +51,8 @@ BEGIN 'TFU_PAR_PISCINE' ); + + -- Ratios pré-calculés pour éviter la division répétée dans le SELECT v_taux_tfu_ratio := v_taux_tfu / 100.0; v_taux_vlp_ratio := v_taux_valeur_locat_prof / 100.0; @@ -454,6 +61,27 @@ BEGIN -- 3. INSERT avec calcul complet de valeur_locative_adm et montant_taxe -- → supprime l'UPDATE post-INSERT (économie d'un second scan de table) -- ------------------------------------------------------------------------- + WITH uniteLogementSupTotal as ( + WITH derniere_enquete_ulog AS ( + SELECT + eul.*, + ROW_NUMBER() OVER ( + PARTITION BY unite_logement_id + ORDER BY date_enquete DESC + ) AS rn + FROM enquete_unite_logement eul + ) + SELECT + ul.batiment_id, + dimp.montant_taxe, + SUM(ulog.superficie_au_sol) AS superficie_totale + FROM derniere_enquete_ulog ulog + inner join unite_logement ul on ul.id=ulog.unite_logement_id + inner join donnees_imposition_tfu dimp on dimp.batiment_id= ul.batiment_id + WHERE rn = 1 + AND dimp.impositions_tfu_id = p_impositions_tfu_id + GROUP BY ul.batiment_id,dimp.montant_taxe + ) INSERT INTO donnees_imposition_tfu ( annee, code_departement, @@ -570,7 +198,7 @@ BEGIN eul.date_enquete, st.id, ep.zone_rfu_id, - 'TFU', + 'FB', p.superficie, eb.superficie_au_sol, eul.superficie_au_sol, @@ -620,7 +248,6 @@ BEGIN THEN eul.superficie_au_sol * brb.valeur_locative ELSE 0 END, - -- --------------------------------------------------------------- -- valeur_locative_adm avec tests explicites (corrigée) -- --------------------------------------------------------------- @@ -654,7 +281,6 @@ BEGIN ELSE 0 END, - -- 🔧 CORRECTION : tfu_superficie_au_sol_reel (était hardcodé à 6/100) CASE WHEN eul.categorie_usage = 'HABITATION' THEN eul.superficie_au_sol * brb.valeur_locative * v_taux_tfu_ratio @@ -667,56 +293,16 @@ BEGIN -- --------------------------------------------------------------- -- montant_taxe ← calculé directement (plus d'UPDATE) -- --------------------------------------------------------------- - ( - WITH calc AS ( - SELECT - COALESCE(NULLIF(eul.valeur_unite_logement_reel, 0), - NULLIF(eul.valeur_unite_logement_calcule, 0), - NULLIF(eul.valeur_unite_logement_estime, 0), 0) AS valeur_ul, - COALESCE(NULLIF(eul.montant_locatif_annuel_declare, 0), - NULLIF(eul.montant_locatif_annuel_calcule, 0), - NULLIF(eul.montant_locatif_annuel_estime, 0), 0) AS loyer, - eul.superficie_au_sol * brb.valeur_locative AS vla_reel, - (p.superficie * v_taux_defaut_sup_sol / 100.0) - * brb.valeur_locative AS vla_70, - COALESCE(eul.nombre_piscine, 0) * v_tfu_piscine_unitaire AS piscine_montant - ) - SELECT - CASE - WHEN eul.categorie_usage = 'HABITATION' - AND eul.superficie_au_sol <> 0 - THEN GREATEST(brb.tfu_minimum, - calc.vla_reel * v_taux_tfu_ratio - + calc.piscine_montant) - - WHEN eul.categorie_usage = 'HABITATION' - AND eul.superficie_au_sol = 0 - THEN GREATEST(brb.tfu_minimum, - calc.vla_70 * v_taux_tfu_ratio - + calc.piscine_montant) - - WHEN eul.categorie_usage IN ('PROFESSIONNELLE', 'MIXTE') - AND calc.valeur_ul <> 0 - THEN GREATEST(brb.tfu_minimum, - calc.valeur_ul * v_taux_vlp_ratio * v_taux_tfu_ratio) - - WHEN eul.categorie_usage IN ('PROFESSIONNELLE', 'MIXTE') - AND calc.valeur_ul = 0 - THEN GREATEST(brb.tfu_minimum, - calc.loyer * v_taux_tfu_ratio) - - ELSE brb.tfu_minimum - END - FROM calc - ), - + case when ulost.superficie_totale > 0 + then eul.superficie_au_sol * ulost.montant_taxe / ulost.superficie_totale + else 0 + end, v_taux_tfu, p.id, b.id, ul.id FROM parcelle p - -- Dernière enquête parcelle LEFT JOIN LATERAL ( SELECT @@ -783,7 +369,8 @@ BEGIN LIMIT 1 ) eb ON TRUE - JOIN unite_logement ul ON ul.batiment_id = b.id + JOIN unite_logement ul ON ul.batiment_id = b.id + INNER JOIN uniteLogementSupTotal ulost on ulost.batiment_id=ul.batiment_id -- Dernière enquête unité logement JOIN LATERAL ( diff --git a/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/generer_donnees_imposition_tfu_batie_unite_logement_une_parcelle.sql b/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/generer_donnees_imposition_tfu_batie_unite_logement_une_parcelle.sql new file mode 100644 index 0000000..1680702 --- /dev/null +++ b/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/generer_donnees_imposition_tfu_batie_unite_logement_une_parcelle.sql @@ -0,0 +1,448 @@ +CREATE OR REPLACE FUNCTION public.generer_donnees_imposition_tfu_batie_ulo_une_parcelle( + p_impositions_tfu_id BIGINT, + p_user_id BIGINT, + p_parcelle_id BIGINT +) + RETURNS INTEGER + LANGUAGE plpgsql +AS $$ +DECLARE + v_rows_inserted INTEGER; + v_annee BIGINT; + v_structure_id BIGINT; + v_taux_defaut_sup_sol NUMERIC; + v_taux_tfu NUMERIC; + v_taux_tfu_ratio NUMERIC; -- v_taux_tfu / 100 (pré-calculé) + v_taux_valeur_locat_prof NUMERIC; + v_taux_vlp_ratio NUMERIC; -- v_taux_valeur_locat_prof / 100 (pré-calculé) + v_tfu_piscine_unitaire NUMERIC; + v_today DATE; +BEGIN + + v_today := CURRENT_DATE; + + -- ------------------------------------------------------------------------- + -- 1. Récupération de l'année et de la structure (inchangée) + -- ------------------------------------------------------------------------- + SELECT ex.annee, it.structure_id + INTO STRICT v_annee, v_structure_id + FROM impositions_tfu it + JOIN exercice ex ON ex.id = it.exercice_id + WHERE it.id = p_impositions_tfu_id; + + -- ------------------------------------------------------------------------- + -- 2. Récupération des 4 paramètres en UNE seule requête + -- (évite 4 accès séquentiels à la table parameters) + -- ------------------------------------------------------------------------- + SELECT + MAX(value) FILTER (WHERE name = 'TAUX_DEFAUT_SUPERFICIE_AU_SOL'), + MAX(value) FILTER (WHERE name = 'TAUX_TFU'), + MAX(value) FILTER (WHERE name = 'TAUX_VALEUR_LOCATIVE_PROFESSIONNELLE'), + MAX(value) FILTER (WHERE name = 'TFU_PAR_PISCINE') + INTO STRICT + v_taux_defaut_sup_sol, + v_taux_tfu, + v_taux_valeur_locat_prof, + v_tfu_piscine_unitaire + FROM parameters + WHERE name IN ( + 'TAUX_DEFAUT_SUPERFICIE_AU_SOL', + 'TAUX_TFU', + 'TAUX_VALEUR_LOCATIVE_PROFESSIONNELLE', + 'TFU_PAR_PISCINE' + ); + + + + -- Ratios pré-calculés pour éviter la division répétée dans le SELECT + v_taux_tfu_ratio := v_taux_tfu / 100.0; + v_taux_vlp_ratio := v_taux_valeur_locat_prof / 100.0; + + -- ------------------------------------------------------------------------- + -- 3. INSERT avec calcul complet de valeur_locative_adm et montant_taxe + -- → supprime l'UPDATE post-INSERT (économie d'un second scan de table) + -- ------------------------------------------------------------------------- + WITH uniteLogementSupTotal as ( + WITH derniere_enquete_ulog AS ( + SELECT + eul.*, + ROW_NUMBER() OVER ( + PARTITION BY unite_logement_id + ORDER BY date_enquete DESC + ) AS rn + FROM enquete_unite_logement eul + ) + SELECT + ul.batiment_id, + dimp.montant_taxe, + SUM(ulog.superficie_au_sol) AS superficie_totale + FROM derniere_enquete_ulog ulog + inner join unite_logement ul on ul.id=ulog.unite_logement_id + inner join donnees_imposition_tfu dimp on dimp.batiment_id= ul.batiment_id + WHERE rn = 1 + AND dimp.impositions_tfu_id = p_impositions_tfu_id + GROUP BY ul.batiment_id,dimp.montant_taxe + ) + INSERT INTO donnees_imposition_tfu ( + annee, + code_departement, + nom_departement, + code_commune, + nom_commune, + code_arrondissement, + nom_arrondissement, + code_quartier_village, + nom_quartier_village, + q, + ilot, + parcelle, + nup, + titre_foncier, + num_batiment, + num_unite_logement, + ifu, + npi, + tel_prop, + email_prop, + nom_prop, + prenom_prop, + raison_sociale, + adresse_prop, + tel_sc, + nom_sc, + prenom_sc, + longitude, + latitude, + batie, + exonere, + batiment_exonere, + unite_logement_exonere, + standing_bat, + categorie_bat, + nombre_piscine, + date_enquete, + structure_id, + zone_rfu_id, + nature_impot, + superficie_parc, + superficie_au_sol_bat, + superficie_au_sol_ulog, + valeur_batiment, + valeur_locative_adm_metre_carre, + montant_loyer_annuel, + tfu_metre_carre, + tfu_minimum, + impositions_tfu_id, + deleted, + created_at, + created_by, + "source", + updated_at, + updated_by, + categorie_usage, + superficie_au_sol_taux_prop_parc, -- 70 % superficie parcelle + valeur_locative_adm_taux_prop_parc, + tfu_calcule_taux_prop_parc, -- TFU à 70 % + valeur_locative_adm_sup_reel, + valeur_locative_adm, -- valeur locative administrative finale + tfu_superficie_au_sol_reel, + tfu_piscine, + montant_taxe, -- TFU finale + taux_tfu, + parcelle_id, + batiment_id, + unite_logement_id + ) + SELECT + v_annee, + d.code, + d.nom, + c.code, + c.nom, + a.code, + a.nom, + q.code, + q.nom, + p.q, + p.i, + p.p, + p.nup, + ep.numero_titre_foncier, + b.nub, + ul.nul, + eul.ifu, + eul.npi, + eul.tel1, + eul.email, + eul.nom, + eul.prenom, + eul.raison_sociale, + eul.adresse, + eul.representant_tel, + eul.representant_nom, + eul.representant_prenom, + p.longitude, + p.latitude, + TRUE, + -- exonere parcelle + (v_today BETWEEN ep.date_debut_exemption + AND COALESCE(ep.date_fin_exemption, v_today)), + -- exonere batiment + (v_today BETWEEN eb.date_debut_excemption + AND COALESCE(eb.date_fin_excemption, v_today)), + -- exonere unite logement + (v_today BETWEEN eul.date_debut_exemption + AND COALESCE(eul.date_fin_exemption, v_today)), + cb.standing, + cb.nom, + COALESCE(eul.nombre_piscine, 0), + eul.date_enquete, + st.id, + ep.zone_rfu_id, + 'FB', + p.superficie, + eb.superficie_au_sol, + eul.superficie_au_sol, + -- valeur_batiment (unité logement) : première valeur non nulle non zéro + COALESCE( + NULLIF(eul.valeur_unite_logement_reel, 0), + NULLIF(eul.valeur_unite_logement_calcule, 0), + NULLIF(eul.valeur_unite_logement_estime, 0), + 0 + ), + brb.valeur_locative, + -- montant_loyer_annuel + COALESCE( + NULLIF(eul.montant_locatif_annuel_declare, 0), + NULLIF(eul.montant_locatif_annuel_calcule, 0), + NULLIF(eul.montant_locatif_annuel_estime, 0), + 0 + ), + brb.tfu_metre_carre, + brb.tfu_minimum, + p_impositions_tfu_id, + FALSE, + v_today, + p_user_id, + 'FISCAD', + v_today, + p_user_id, + eul.categorie_usage, + + -- superficie_au_sol_taux_prop_parc (70 % parcelle) + p.superficie * v_taux_defaut_sup_sol / 100.0, + + -- valeur_locative_adm_taux_prop_parc + CASE WHEN eul.categorie_usage = 'HABITATION' + THEN (p.superficie * v_taux_defaut_sup_sol / 100.0) * brb.valeur_locative + ELSE 0 + END, + + -- tfu_calcule_taux_prop_parc + CASE WHEN eul.categorie_usage = 'HABITATION' + THEN (p.superficie * v_taux_defaut_sup_sol / 100.0) * brb.valeur_locative * v_taux_tfu_ratio + ELSE 0 + END, + + -- valeur_locative_adm_sup_reel + CASE WHEN eul.categorie_usage = 'HABITATION' + THEN eul.superficie_au_sol * brb.valeur_locative + ELSE 0 + END, + -- --------------------------------------------------------------- + -- valeur_locative_adm avec tests explicites (corrigée) + -- --------------------------------------------------------------- + CASE + WHEN eul.categorie_usage = 'HABITATION' + AND eul.superficie_au_sol <> 0 + THEN eul.superficie_au_sol * brb.valeur_locative + + WHEN eul.categorie_usage = 'HABITATION' + AND eul.superficie_au_sol = 0 + THEN (p.superficie * v_taux_defaut_sup_sol / 100.0) * brb.valeur_locative + + -- ✅ Test explicite : valeur_unite_logement <> 0 + WHEN eul.categorie_usage IN ('PROFESSIONNELLE', 'MIXTE') + AND COALESCE(NULLIF(eul.valeur_unite_logement_reel, 0), + NULLIF(eul.valeur_unite_logement_calcule, 0), + NULLIF(eul.valeur_unite_logement_estime, 0), 0) <> 0 + THEN COALESCE(NULLIF(eul.valeur_unite_logement_reel, 0), + NULLIF(eul.valeur_unite_logement_calcule, 0), + NULLIF(eul.valeur_unite_logement_estime, 0), 0) + * v_taux_vlp_ratio + + -- ✅ Test explicite : valeur_unite_logement = 0 + WHEN eul.categorie_usage IN ('PROFESSIONNELLE', 'MIXTE') + AND COALESCE(NULLIF(eul.valeur_unite_logement_reel, 0), + NULLIF(eul.valeur_unite_logement_calcule, 0), + NULLIF(eul.valeur_unite_logement_estime, 0), 0) = 0 + THEN COALESCE(NULLIF(eul.montant_locatif_annuel_declare, 0), + NULLIF(eul.montant_locatif_annuel_calcule, 0), + NULLIF(eul.montant_locatif_annuel_estime, 0), 0) + + ELSE 0 + END, + -- 🔧 CORRECTION : tfu_superficie_au_sol_reel (était hardcodé à 6/100) + CASE WHEN eul.categorie_usage = 'HABITATION' + THEN eul.superficie_au_sol * brb.valeur_locative * v_taux_tfu_ratio + ELSE 0 + END, + + -- tfu_piscine + COALESCE(eul.nombre_piscine, 0) * v_tfu_piscine_unitaire, + + -- --------------------------------------------------------------- + -- montant_taxe ← calculé directement (plus d'UPDATE) + -- --------------------------------------------------------------- + case when ulost.superficie_totale > 0 + then eul.superficie_au_sol * ulost.montant_taxe / ulost.superficie_totale + else 0 + end, + v_taux_tfu, + p.id, + b.id, + ul.id + + FROM parcelle p + -- Dernière enquête parcelle + LEFT JOIN LATERAL ( + SELECT + parcelle_id, + superficie, + personne_id, + numero_titre_foncier, + date_enquete, + representant_tel, + representant_nom, + representant_prenom, + representant_npi, + date_debut_exemption, + date_fin_exemption, + zone_rfu_id + FROM enquete + WHERE parcelle_id = p.id + ORDER BY date_enquete DESC, id DESC + LIMIT 1 + ) ep ON TRUE + + LEFT JOIN personne pers ON pers.id = ep.personne_id + + JOIN quartier q ON q.id = p.quartier_id + JOIN arrondissement a ON a.id = q.arrondissement_id + JOIN commune c ON c.id = a.commune_id + JOIN departement d ON d.id = c.departement_id + + -- Rattachement structure via secteur + JOIN LATERAL ( + SELECT secteur_id + FROM secteur_decoupage + WHERE quartier_id = q.id + ORDER BY quartier_id + LIMIT 1 + ) sd ON TRUE + JOIN secteur sect ON sect.id = sd.secteur_id + JOIN section ses ON ses.id = sect.section_id + JOIN "structure" st ON st.id = ses.structure_id + + JOIN batiment b ON b.parcelle_id = p.id + + -- Dernière enquête bâtiment + JOIN LATERAL ( + SELECT + eb2.batiment_id, + eb2.superficie_au_sol, + eb2.nombre_piscine, + eb2.categorie_batiment_id, + eb2.date_enquete, + eb2.montant_locatif_annuel_declare, + eb2.montant_locatif_annuel_calcule, + eb2.montant_locatif_annuel_estime, + eb2.date_debut_excemption, + eb2.date_fin_excemption, + eb2.valeur_batiment_reel, + eb2.valeur_batiment_calcule, + eb2.valeur_batiment_estime, + u.categorie_usage + FROM enquete_batiment eb2 + JOIN usage u ON u.id = eb2.usage_id + WHERE eb2.batiment_id = b.id + ORDER BY eb2.date_enquete DESC, eb2.id DESC + LIMIT 1 + ) eb ON TRUE + + JOIN unite_logement ul ON ul.batiment_id = b.id + INNER JOIN uniteLogementSupTotal ulost on ulost.batiment_id=ul.batiment_id + + -- Dernière enquête unité logement + JOIN LATERAL ( + SELECT + eul2.unite_logement_id, + pers1.id, + pers1.ifu, + pers1.npi, + pers1.tel1, + pers1.email, + pers1.nom, + pers1.prenom, + pers1.raison_sociale, + pers1.adresse, + eul2.nombre_piscine, + eul2.categorie_batiment_id, + eul2.superficie_au_sol, + eul2.superficie_louee, + eul2.nbre_piece, + eul2.date_enquete, + eul2.montant_locatif_annuel_calcule, + eul2.montant_locatif_annuel_declare, + eul2.montant_locatif_annuel_estime, + eul2.date_debut_exemption, + eul2.date_fin_exemption, + eul2.representant_nom, + eul2.representant_prenom, + eul2.representant_tel, + eul2.valeur_unite_logement_reel, + eul2.valeur_unite_logement_calcule, + eul2.valeur_unite_logement_estime, + u.categorie_usage + FROM enquete_unite_logement eul2 + JOIN usage u ON u.id = eul2.usage_id + LEFT JOIN personne pers1 ON pers1.id = eul2.personne_id + WHERE eul2.unite_logement_id = ul.id + ORDER BY eul2.date_enquete DESC, eul2.id DESC + LIMIT 1 + ) eul ON TRUE + + JOIN categorie_batiment cb ON cb.id = eul.categorie_batiment_id + + -- Barème RFU bâti (inchangé) + JOIN LATERAL ( + SELECT * + FROM barem_rfu_bati br + WHERE br.categorie_batiment_id = cb.id + AND br.arrondissement_id = a.id + AND (br.quartier_id = q.id OR br.quartier_id IS NULL) + ORDER BY br.quartier_id DESC NULLS LAST + LIMIT 1 + ) brb ON TRUE + + WHERE p.batie = TRUE + AND EXISTS ( + SELECT 1 + FROM unite_logement ul2 + WHERE ul2.batiment_id = b.id + ) + AND st.id = v_structure_id + AND p.id = p_parcelle_id + AND NOT exists(select 1 from donnees_imposition_tfu dimptfu + where dimptfu.annee=v_annee + and dimptfu.batiment_id=b.id + and dimptfu.unite_logement_id=ul.id + and dimptfu.nature_impot='FB') + ON CONFLICT DO NOTHING; + + GET DIAGNOSTICS v_rows_inserted = ROW_COUNT; + + RETURN v_rows_inserted; +END; +$$; + diff --git a/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/generer_donnees_imposition_tfu_non_batie.sql b/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/generer_donnees_imposition_tfu_non_batie.sql index db38c46..ba2f582 100644 --- a/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/generer_donnees_imposition_tfu_non_batie.sql +++ b/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/generer_donnees_imposition_tfu_non_batie.sql @@ -268,7 +268,7 @@ BEGIN ep.date_enquete, st.id, ep.zone_rfu_id, - 'TFU', + 'FNB', p.superficie, p_impositions_tfu_id, false, diff --git a/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/generer_donnees_imposition_tfu_non_batie_une_parcelle.sql b/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/generer_donnees_imposition_tfu_non_batie_une_parcelle.sql new file mode 100644 index 0000000..103b474 --- /dev/null +++ b/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/generer_donnees_imposition_tfu_non_batie_une_parcelle.sql @@ -0,0 +1,190 @@ +CREATE OR REPLACE FUNCTION public.generer_donnees_imposition_tfu_non_batie_une_parcelle( + p_impositions_tfu_id BIGINT, + p_user_id BIGINT, + p_parcelle_id BIGINT +) + RETURNS INTEGER + LANGUAGE plpgsql +AS +$$ +DECLARE + v_rows_inserted INTEGER; + v_annee BIGINT; + v_structure_id BIGINT; +BEGIN + + -- récupération de l'année + SELECT ex.annee, it.structure_id + INTO STRICT v_annee, v_structure_id + FROM impositions_tfu it + JOIN exercice ex ON ex.id = it.exercice_id + WHERE it.id = p_impositions_tfu_id; + + + INSERT INTO donnees_imposition_tfu( + annee, + code_departement, + nom_departement, + code_commune, + nom_commune, + code_arrondissement, + nom_arrondissement, + code_quartier_village, + nom_quartier_village, + q, + ilot, + parcelle, + nup, + titre_foncier, + ifu, + npi, + tel_prop, + email_prop, + nom_prop, + prenom_prop, + raison_sociale, + adresse_prop, + tel_sc, + nom_sc, + prenom_sc, + longitude, + latitude, + batie, + exonere, + date_enquete, + structure_id, + zone_rfu_id, + nature_impot, + superficie_parc, + impositions_tfu_id, + deleted, + created_at, + created_by, + "source", + updated_at, + updated_by, + taux_tfu, + valeur_admin_parcelle_nb, + valeur_admin_parcelle_nb_metre_carre, + montant_taxe, + parcelle_id, + personne_id + ) + SELECT + v_annee, + d.code, + d.nom, + c.code, + c.nom, + a.code, + a.nom, + q.code, + q.nom, + p.q, + p.i, + p.p, + p.nup, + ep.numero_titre_foncier, + pers.ifu, + pers.npi, + pers.tel1, + pers.email, + pers.nom, + pers.prenom, + pers.raison_sociale, + pers.adresse, + ep.representant_tel, + ep.representant_nom, + ep.representant_prenom, + p.longitude, + p.latitude, + false, + ( + CURRENT_DATE >= ep.date_debut_exemption + AND CURRENT_DATE <= COALESCE(ep.date_fin_exemption, CURRENT_DATE) + ), + ep.date_enquete, + st.id, + ep.zone_rfu_id, + 'FNB', + p.superficie, + p_impositions_tfu_id, + false, + current_date, + p_user_id, + 'FISCAD', + current_date, + p_user_id, + brnb.taux, + CASE + WHEN brnb.au_metre_carre = true + THEN brnb.valeur_administrative_metre_carre * ep.superficie + ELSE brnb.valeur_administrative + END, + brnb.valeur_administrative_metre_carre, + CASE + WHEN brnb.au_metre_carre = true + THEN brnb.valeur_administrative_metre_carre * ep.superficie * brnb.taux / 100 + ELSE brnb.valeur_administrative * brnb.taux / 100 + END, + p.id, + ep.personne_id + FROM parcelle p + LEFT JOIN ( + SELECT DISTINCT ON (parcelle_id) + parcelle_id, + superficie, + personne_id, + numero_titre_foncier, + date_enquete, + representant_tel, + representant_nom, + representant_prenom, + representant_npi, + date_debut_exemption, + date_fin_exemption, + zone_rfu_id + FROM enquete + ORDER BY parcelle_id, date_enquete DESC + ) ep ON ep.parcelle_id = p.id + + LEFT JOIN personne pers ON pers.id = ep.personne_id + + JOIN quartier q ON q.id = p.quartier_id + JOIN arrondissement a ON a.id = q.arrondissement_id + JOIN commune c ON c.id = a.commune_id + JOIN departement d ON d.id = c.departement_id + +-- ✅ CORRECTION ICI + JOIN ( + SELECT DISTINCT ON (quartier_id) + quartier_id, + secteur_id + FROM secteur_decoupage + ORDER BY quartier_id + ) sd ON sd.quartier_id = q.id + + JOIN secteur sect ON sect.id = sd.secteur_id + JOIN section ses ON ses.id = sect.section_id + JOIN "structure" st ON st.id = ses.structure_id + + LEFT JOIN barem_rfu_non_bati brnb + ON (brnb.commune_id = c.id AND brnb.zone_rfu_id = ep.zone_rfu_id) + + WHERE p.batie = false + AND st.id = v_structure_id + AND p.id=p_parcelle_id + AND NOT EXISTS( select 1 from donnees_imposition_tfu dimptfu + where dimptfu.nature_impot='FNB' + and dimptfu.parcelle_id=p_parcelle_id + and dimptfu.annee=v_annee) + + ON CONFLICT DO NOTHING; + + GET DIAGNOSTICS v_rows_inserted = ROW_COUNT; + + RETURN v_rows_inserted; + +END; +$$; + diff --git a/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/maj_donnees_imposition_tfu_batie_plusieurs_batiment.sql b/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/maj_donnees_imposition_tfu_batie_plusieurs_batiment.sql new file mode 100644 index 0000000..ce0253b --- /dev/null +++ b/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/maj_donnees_imposition_tfu_batie_plusieurs_batiment.sql @@ -0,0 +1,51 @@ +/** + - consider les parcelles avec plusieurs batiment + - faire la somme (som_tfu_calcule) des TFU calculées + - on recupere la tfu minimum (max_tfu_min) de la catégorie la plus élévée des batiment + - si montant_tfu= Max(som_tfu_calcule, max_tfu_min) + */ + +CREATE OR REPLACE FUNCTION public.maj_donnees_imposition_tfu_batie_plusBati( + p_impositions_tfu_id BIGINT +) + RETURNS INTEGER + LANGUAGE plpgsql +AS $$ +DECLARE + v_rows_inserted INTEGER; +BEGIN + + ------MAJ pour les parcelles ayants plusieurs batiment + WITH donnees_imposition_plusieurs_bat AS ( + SELECT + dimp.parcelle_id, + GREATEST( + MAX(dimp.tfu_minimum), + SUM(dimp.montant_taxe_brut) + ) AS montant_tfu_parcelle, + COUNT(*) AS nombre_bat + FROM donnees_imposition_tfu dimp + LEFT JOIN unite_logement ul_filter on dimp.unite_logement_id = ul_filter.id + where impositions_tfu_id=p_impositions_tfu_id + AND batie=true and ul_filter.id is null + AND nature_impot='FB' + GROUP BY dimp.parcelle_id + HAVING COUNT(*) > 1 + ) + UPDATE donnees_imposition_tfu dimp + SET + montant_taxe = dippb.montant_tfu_parcelle, + nombre_bat = dippb.nombre_bat + FROM donnees_imposition_plusieurs_bat dippb + WHERE dimp.parcelle_id = dippb.parcelle_id + AND dimp.impositions_tfu_id=p_impositions_tfu_id; + + ------FIN MAJ pour les parcelles ayants plusieurs batiment + + GET DIAGNOSTICS v_rows_inserted = ROW_COUNT; + + RETURN v_rows_inserted; +END; +$$; + + diff --git a/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/maj_donnees_imposition_tfu_batie_plusieurs_batiment_une_parcelle.sql b/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/maj_donnees_imposition_tfu_batie_plusieurs_batiment_une_parcelle.sql new file mode 100644 index 0000000..1d0fd3b --- /dev/null +++ b/src/main/java/io/gmss/fiscad/persistence/procedure_fonction_stocke/maj_donnees_imposition_tfu_batie_plusieurs_batiment_une_parcelle.sql @@ -0,0 +1,53 @@ +/** + - consider les parcelles avec plusieurs batiment + - faire la somme (som_tfu_calcule) des TFU calculées + - on recupere la tfu minimum (max_tfu_min) de la catégorie la plus élévée des batiment + - si montant_tfu= Max(som_tfu_calcule, max_tfu_min) + */ + +CREATE OR REPLACE FUNCTION public.maj_donnees_imposition_tfu_batie_plusBati_une_parcelle( + p_impositions_tfu_id BIGINT, + p_parcelle_id BIGINT +) + RETURNS INTEGER + LANGUAGE plpgsql +AS $$ +DECLARE + v_rows_inserted INTEGER; +BEGIN + + ------MAJ pour les parcelles ayants plusieurs batiment + WITH donnees_imposition_plusieurs_bat AS ( + SELECT + dimp.parcelle_id, + GREATEST( + MAX(dimp.tfu_minimum), + SUM(dimp.montant_taxe_brut) + ) AS montant_tfu_parcelle, + COUNT(*) AS nombre_bat + FROM donnees_imposition_tfu dimp + LEFT JOIN unite_logement ul_filter on dimp.unite_logement_id = ul_filter.id + where impositions_tfu_id=p_impositions_tfu_id + AND batie=true and ul_filter.id is null + AND nature_impot='FB' + AND dimp.parcelle_id=p_parcelle_id + GROUP BY dimp.parcelle_id + HAVING COUNT(*) > 1 + ) + UPDATE donnees_imposition_tfu dimp + SET + montant_taxe = dippb.montant_tfu_parcelle, + nombre_bat = dippb.nombre_bat + FROM donnees_imposition_plusieurs_bat dippb + WHERE dimp.parcelle_id = dippb.parcelle_id + AND dimp.impositions_tfu_id=p_impositions_tfu_id; + + ------FIN MAJ pour les parcelles ayants plusieurs batiment + + GET DIAGNOSTICS v_rows_inserted = ROW_COUNT; + + RETURN v_rows_inserted; +END; +$$; + + diff --git a/src/main/java/io/gmss/fiscad/persistence/repositories/rfu/metier/DonneesImpositionTfuRepository.java b/src/main/java/io/gmss/fiscad/persistence/repositories/rfu/metier/DonneesImpositionTfuRepository.java index 373f8f0..9296476 100755 --- a/src/main/java/io/gmss/fiscad/persistence/repositories/rfu/metier/DonneesImpositionTfuRepository.java +++ b/src/main/java/io/gmss/fiscad/persistence/repositories/rfu/metier/DonneesImpositionTfuRepository.java @@ -508,53 +508,115 @@ SELECT new io.gmss.fiscad.paylaods.request.crudweb.DonneesImpositionPaylaodWeb( Pageable pageable ); - @Query(value = "SELECT generer_donnees_imposition_tfu_batie(:structureId, :impositionId)", nativeQuery = true) + @Query(value = "SELECT generer_donnees_imposition_tfu_batie(:impositionId, :userId)", nativeQuery = true) Integer genererDonneesTfuBatie( - @Param("structureId") Long structureId, - @Param("impositionId") Long impositionId + @Param("impositionId") Long impositionId, + @Param("userId") Long userId + ); + + @Query(value = "SELECT generer_donnees_imposition_tfu_batie_une_parcelle(:impositionId, :userId,:parcelleId)", nativeQuery = true) + Integer genererDonneesTfuBatie( + @Param("impositionId") Long impositionId, + @Param("userId") Long userId, + @Param("parcelleId") Long parcelleId ); - @Query(value = "SELECT generer_donnees_imposition_tfu_batie_unite_logement(:structureId, :impositionId)", nativeQuery = true) + @Query(value = "SELECT generer_donnees_imposition_tfu_batie_unite_logement(:impositionId, :userId)", nativeQuery = true) Integer genererDonneesTfuBatieUniteLogement( - @Param("structureId") Long structureId, - @Param("impositionId") Long impositionId + @Param("impositionId") Long impositionId, + @Param("userId") Long userId + ); + + @Query(value = "SELECT generer_donnees_imposition_tfu_batie_ulo_une_parcelle(:impositionId, :userId,:parcelleId)", nativeQuery = true) + Integer genererDonneesTfuBatieUniteLogement( + @Param("impositionId") Long impositionId, + @Param("userId") Long userId, + @Param("parcelleId") Long parcelleId ); - @Query(value = "SELECT generer_donnees_imposition_tfu_non_batie(:structureId, :impositionId)", nativeQuery = true) + @Query(value = "SELECT generer_donnees_imposition_tfu_non_batie(:impositionId, :userId)", nativeQuery = true) Integer genererDonneesTfuNonBatie( - @Param("structureId") Long structureId, - @Param("impositionId") Long impositionId + @Param("impositionId") Long impositionId, + @Param("userId") Long userId ); - @Query(value = "SELECT generer_donnees_imposition_irf_batie(:structureId, :impositionId)", nativeQuery = true) + @Query(value = "SELECT generer_donnees_imposition_tfu_non_batie_une_parcelle(:impositionId, :userId, :parcelleId)", nativeQuery = true) + Integer genererDonneesTfuNonBatie( + @Param("impositionId") Long impositionId, + @Param("userId") Long userId, + @Param("parcelleId") Long parcelleId + ); + + @Query(value = "SELECT generer_donnees_imposition_irf_batie(:impositionId, :userId)", nativeQuery = true) Integer genererDonneesIrfBatie( - @Param("structureId") Long structureId, - @Param("impositionId") Long impositionId + @Param("impositionId") Long impositionId, + @Param("userId") Long userId ); - @Query(value = "SELECT generer_donnees_imposition_srtb_batie(:structureId, :impositionId)", nativeQuery = true) + @Query(value = "SELECT generer_donnees_imposition_irf_batie_une_parcelle(:impositionId, :userId, :parcelleId)", nativeQuery = true) + Integer genererDonneesIrfBatie( + @Param("impositionId") Long impositionId, + @Param("userId") Long userId, + @Param("parcelleId") Long parcelleId + ); + + @Query(value = "SELECT generer_donnees_imposition_srtb_batie(:impositionId, :userId)", nativeQuery = true) Integer genererDonneesSrtbBatie( - @Param("structureId") Long structureId, - @Param("impositionId") Long impositionId + @Param("impositionId") Long impositionId, + @Param("userId") Long userId ); - @Query(value = "SELECT generer_donnees_imposition_irf_batie_unite_logement(:structureId, :impositionId)", nativeQuery = true) + @Query(value = "SELECT generer_donnees_imposition_srtb_batie_une_parcelle(:impositionId, :userId, :parcelleId)", nativeQuery = true) + Integer genererDonneesSrtbBatie( + @Param("impositionId") Long impositionId, + @Param("userId") Long userId, + @Param("parcelleId") Long parcelleId + ); + + @Query(value = "SELECT generer_donnees_imposition_irf_batie_unite_logement(:impositionId, :userId)", nativeQuery = true) Integer genererDonneesIrfBatieUniteLogement( - @Param("structureId") Long structureId, + @Param("impositionId") Long impositionId, + @Param("userId") Long userId + ); + + + @Query(value = "SELECT generer_donnees_imposition_irf_batie_ulo_une_parcelle(:impositionId, :userId, :parcelleId)", nativeQuery = true) + Integer genererDonneesIrfBatieUniteLogement( + @Param("impositionId") Long impositionId, + @Param("userId") Long userId, + @Param("parcelleId") Long parcelleId + ); + +// @Query(value = "SELECT generer_donnees_imposition_srtb_batie_unite_logement(:impositionId, :userId)", nativeQuery = true) +// Integer genererDonneesSrtbBatieUniteLogement( +// @Param("impositionId") Long impositionId, +// @Param("userId") Long userId +// ); + +// @Query(value = "SELECT generer_donnees_imposition_srtb_batie_u(:impositionId, :userId)", nativeQuery = true) +// Integer genererDonneesSrtbBatieUniteLogement( +// @Param("impositionId") Long impositionId, +// @Param("userId") Long userId +// ); + + + + + @Query(value = "SELECT maj_donnees_imposition_tfu_batie_plusBati(:impositionId)", nativeQuery = true) + Integer majDonneesTfuBatiePlusieursBatiment( @Param("impositionId") Long impositionId ); - @Query(value = "SELECT generer_donnees_imposition_srtb_batie_unite_logement(:structureId, :impositionId)", nativeQuery = true) - Integer genererDonneesSrtbBatieUniteLogement( - @Param("structureId") Long structureId, - @Param("impositionId") Long impositionId + @Query(value = "SELECT maj_donnees_imposition_tfu_batie_plusbati_une_parcelle(:impositionId,:parcelleId)", nativeQuery = true) + Integer majDonneesTfuBatiePlusieursBatiment( + @Param("impositionId") Long impositionId, + @Param("parcelleId") Long parcelleId ); - @Query(value = """ SELECT new io.gmss.fiscad.paylaods.request.crudweb.DonneesImpositionPaylaodWeb( d.id, diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 7a2dd25..17ab386 100755 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,6 +1,6 @@ -spring.profiles.active=${SPRING_PROFILES_ACTIVE} +#spring.profiles.active=${SPRING_PROFILES_ACTIVE} #spring.profiles.active=abomey -#spring.profiles.active=test +spring.profiles.active=test spring.jpa.properties.hibernate.id.new_generator_mappings=false spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true spring.jpa.open-in-view=false