@open3cl/engine 1.0.12 → 1.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/13.2_generateur_combustion_ch.js +1 -1
  2. package/features/dpe/domain/models/dpe.model.ts +9 -0
  3. package/features/dpe/domain/models/installation-chauffage.model.ts +26 -2
  4. package/features/dpe/domain/models/type-generateur.model.js +8 -0
  5. package/features/dpe/infrastructure/ch/chTv.store.js +94 -0
  6. package/features/dpe/infrastructure/ch/chTv.store.spec.js +99 -0
  7. package/features/dpe/infrastructure/ecs/ecsTv.store.js +5 -3
  8. package/features/dpe/infrastructure/ecs/ecsTv.store.spec.js +4 -0
  9. package/features/dpe/infrastructure/froid/frTv.store.js +4 -2
  10. package/features/dpe/infrastructure/tv.store.js +28 -0
  11. package/features/dpe/infrastructure/tv.store.spec.js +12 -0
  12. package/features/engine/domain/apport_et_besoin/apport-et-besoin.service.js +57 -3
  13. package/features/engine/domain/apport_et_besoin/apport-et-besoin.service.spec.js +117 -2
  14. package/features/engine/domain/apport_et_besoin/apport_gratuit/apport-gratuit.service.js +18 -2
  15. package/features/engine/domain/apport_et_besoin/apport_gratuit/apport-gratuit.service.spec.js +13 -2
  16. package/features/engine/domain/apport_et_besoin/ch/besoin-ch.service.js +150 -0
  17. package/features/engine/domain/apport_et_besoin/ch/besoin-ch.service.spec.js +145 -0
  18. package/features/engine/domain/apport_et_besoin/ch/perte-ch-recup.service.js +168 -0
  19. package/features/engine/domain/apport_et_besoin/ch/perte-ch-recup.service.spec.js +313 -0
  20. package/features/engine/domain/apport_et_besoin/ecs/perte-ecs-recup.service.js +12 -8
  21. package/features/engine/domain/apport_et_besoin/ecs/perte-ecs-recup.service.spec.js +28 -13
  22. package/features/engine/domain/ch/emetteur-ch.service.js +100 -0
  23. package/features/engine/domain/ch/emetteur-ch.service.spec.js +78 -0
  24. package/features/engine/domain/ch/generateur-ch.service.js +365 -0
  25. package/features/engine/domain/ch/generateur-ch.service.spec.js +734 -0
  26. package/features/engine/domain/ch/installation-ch.service.js +39 -0
  27. package/features/engine/domain/ch/installation-ch.service.spec.js +41 -0
  28. package/features/engine/domain/contexte.builder.js +1 -0
  29. package/features/engine/domain/contexte.builder.spec.js +2 -0
  30. package/features/engine/domain/ecs/generateur-ecs.service.js +2 -2
  31. package/features/engine/domain/ecs/installation-ecs.service.js +5 -5
  32. package/features/engine/domain/engine.service.js +13 -2
  33. package/features/engine/domain/models/contexte.model.ts +1 -0
  34. package/package.json +1 -1
@@ -37,7 +37,7 @@ export function tv_temp_fonc_30_100(di, de, du, em_ch, ac) {
37
37
  const em_ch_de = em.donnee_entree;
38
38
  const em_ch_du = em.donnee_utilisateur;
39
39
  const matcher = {
40
- type_generateur_ch_id: de.enum_type_generateur_ch_id,
40
+ enum_type_generateur_ch_id: de.enum_type_generateur_ch_id,
41
41
  enum_temp_distribution_ch_id: requestInputID(em_ch_de, em_ch_du, 'temp_distribution_ch'),
42
42
  periode_emetteurs: requestInput(em_ch_de, em_ch_du, 'periode_installation_emetteur')
43
43
  };
@@ -159,6 +159,15 @@ export interface Logement {
159
159
  installation_ecs_collection: { installation_ecs: InstallationEcs[] };
160
160
  installation_chauffage_collection: { installation_chauffage: InstallationChauffage[] };
161
161
  sortie: Sortie;
162
+ donnees_de_calcul: LogementDonneesCalcul;
163
+ }
164
+
165
+ export interface LogementDonneesCalcul {
166
+ apportsInterneCh: { [key: string]: number };
167
+ apportsInterneDepensier: { [key: string]: number };
168
+ apportsSolaire: { [key: string]: number };
169
+ besoinChauffageHP: { [key: string]: number };
170
+ besoinChauffageDepensierHP: { [key: string]: number };
162
171
  }
163
172
 
164
173
  export interface Tertiaire extends Logement {}
@@ -1,4 +1,5 @@
1
1
  import { DE } from './dpe.model';
2
+ import { GenerateurEcsDU } from './installation-ecs.model';
2
3
 
3
4
  export interface InstallationChauffage {
4
5
  donnee_entree?: InstallationChauffageDE;
@@ -62,6 +63,7 @@ export interface EmetteurChauffageDI {
62
63
 
63
64
  export interface GenerateurChauffage {
64
65
  donnee_entree?: GenerateurChauffageDE;
66
+ donnee_utilisateur?: GenerateurChauffageDU;
65
67
  donnee_intermediaire?: GenerateurChauffageDI;
66
68
  }
67
69
 
@@ -71,7 +73,7 @@ export interface GenerateurChauffageDE extends DE {
71
73
  enum_type_generateur_ch_id: number;
72
74
  enum_usage_generateur_id: number;
73
75
  enum_type_energie_id: number;
74
- position_volume_chauffe: boolean;
76
+ position_volume_chauffe: number;
75
77
  tv_rendement_generation_id?: number;
76
78
  tv_scop_id?: number;
77
79
  tv_temp_fonc_100_id?: number;
@@ -81,7 +83,7 @@ export interface GenerateurChauffageDE extends DE {
81
83
  identifiant_reseau_chaleur?: string;
82
84
  date_arrete_reseau_chaleur?: string;
83
85
  priorite_generateur_cascade?: number;
84
- presence_ventouse?: boolean;
86
+ presence_ventouse?: number;
85
87
  presence_regulation_combustion?: boolean;
86
88
  enum_methode_saisie_carac_sys_id: number;
87
89
  enum_lien_generateur_emetteur_id: number;
@@ -99,3 +101,25 @@ export interface GenerateurChauffageDI {
99
101
  conso_ch: number;
100
102
  conso_ch_depensier: number;
101
103
  }
104
+
105
+ export interface GenerateurChauffageDU {
106
+ ratio_virtualisation?: number;
107
+ typeGenerateur?: TypeGenerateur;
108
+ combustion: boolean;
109
+ pac: boolean;
110
+ generateur?: {
111
+ tv_generateur_combustion_id: string;
112
+ enum_type_generateur_ch_id: string;
113
+ type_generateur: string;
114
+ critere_pn: string;
115
+ pveil: string;
116
+ qp0_perc: string;
117
+ rpint: string;
118
+ rpn: string;
119
+ };
120
+ }
121
+
122
+ export enum TypeGenerateur {
123
+ CHAUDIERE = 'CHAUDIERE',
124
+ OTHER = 'OTHER'
125
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @type {{[key: string]: string}}
3
+ */
4
+ export const TypeGenerateur = {
5
+ COMBUSTION: 'COMBUSTION',
6
+ PAC: 'PAC',
7
+ OTHER: 'OTHER'
8
+ };
@@ -0,0 +1,94 @@
1
+ import { tvs as tv } from '../../../../tv-v2.js';
2
+ import { TvStore } from './../tv.store.js';
3
+ import { convertExpression } from '../../../../utils.js';
4
+ import enums from '../../../../enums.js';
5
+ import { logger } from '../../../../core/util/logger/log-service.js';
6
+
7
+ /**
8
+ * Accès aux données des tables de valeurs pour le chauffage
9
+ */
10
+ export class ChTvStore extends TvStore {
11
+ /**
12
+ * Récupération des ids des générateurs de chauffage à combustion
13
+ * @return {[number]}
14
+ */
15
+ getCombustionGenerateurs() {
16
+ return this.#getTypeGenerateurChId('generateur_combustion');
17
+ }
18
+ /**
19
+ * Récupération des ids des générateurs de chauffage pompes à chaleur
20
+ * @return {[number]}
21
+ */
22
+ getPacGenerateurs() {
23
+ return this.#getTypeGenerateurChId('scop');
24
+ }
25
+
26
+ /**
27
+ * @param tv {string}
28
+ * @returns {any[]}
29
+ */
30
+ #getTypeGenerateurChId(tv) {
31
+ return [
32
+ ...new Set(
33
+ tv[tv].flatMap((v) =>
34
+ (v.enum_type_generateur_ch_id
35
+ ? v.enum_type_generateur_ch_id.split('|').map(Number)
36
+ : []
37
+ ).filter(Number.isFinite)
38
+ )
39
+ )
40
+ ].sort((a, b) => a - b);
41
+ }
42
+
43
+ /**
44
+ * Récupération des informations du générateur à combustion
45
+ * @param enumTypeGenerateurId
46
+ * @param pn
47
+ * @return {{tv_generateur_combustion_id: string, enum_type_generateur_ch_id: string, type_generateur: string, critere_pn: string, pveil: string, qp0_perc: string, rpint: string, rpn: string}}
48
+ */
49
+ getGenerateurCombustion(enumTypeGenerateurId, pn) {
50
+ return tv['generateur_combustion'].find(
51
+ (v) =>
52
+ v.enum_type_generateur_ch_id &&
53
+ v.enum_type_generateur_ch_id.split('|').includes(enumTypeGenerateurId) &&
54
+ (!v.critere_pn ||
55
+ eval(`let Pn=${pn} ;${convertExpression(v.critere_pn.replace('≤', '<='))}`))
56
+ );
57
+ }
58
+
59
+ /**
60
+ * Récupération de la température de fonctionnement
61
+ *
62
+ * @param pourcentageFonctionnement pourcentage de fonctionnement du générateur (30% ou 100%)
63
+ * @param enumTypeGenerateurId
64
+ * @param enumTemperatureDistribution
65
+ * @param enumPeriodeEmetteurs
66
+ * @return {number}
67
+ */
68
+ temperatureFonctionnement(
69
+ pourcentageFonctionnement,
70
+ enumTypeGenerateurId,
71
+ enumTemperatureDistribution,
72
+ enumPeriodeEmetteurs
73
+ ) {
74
+ const temperatureDistribution = enums.temp_distribution_ch[enumTemperatureDistribution];
75
+ const periodeEmetteur = enums.periode_installation_emetteur[enumPeriodeEmetteurs];
76
+
77
+ const temperature = tv[`temp_fonc_${pourcentageFonctionnement}`].find(
78
+ (v) =>
79
+ (!v.enum_type_generateur_ch_id ||
80
+ v.enum_type_generateur_ch_id.split('|').includes(enumTypeGenerateurId)) &&
81
+ v.temp_distribution_ch.toLowerCase() === temperatureDistribution?.toLowerCase() &&
82
+ v.periode_emetteurs.toLowerCase() === periodeEmetteur?.toLowerCase()
83
+ );
84
+
85
+ if (!temperature) {
86
+ logger.error(
87
+ `Pas de valeur forfaitaire temp_fonc_${pourcentageFonctionnement} pour enumTypeGenerateurId:${enumTypeGenerateurId}, enumTemperatureDistribution:${enumTemperatureDistribution}, enumPeriodeEmetteurs:${enumPeriodeEmetteurs}`
88
+ );
89
+ return;
90
+ }
91
+
92
+ return parseFloat(temperature[`temp_fonc_${pourcentageFonctionnement}`]);
93
+ }
94
+ }
@@ -0,0 +1,99 @@
1
+ import { beforeEach, describe, expect, test } from 'vitest';
2
+ import { ChTvStore } from './chTv.store.js';
3
+
4
+ /** @type {ChTvStore} **/
5
+ let chTvStore;
6
+
7
+ describe('Lecture des tables de valeurs', () => {
8
+ beforeEach(() => {
9
+ chTvStore = new ChTvStore();
10
+ });
11
+
12
+ test('ids des générateurs de chauffage à combustion', () => {
13
+ expect(chTvStore.getCombustionGenerateurs()).toStrictEqual([
14
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
15
+ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
16
+ 94, 95, 96, 97, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133,
17
+ 134, 135, 136, 137, 138, 139, 140, 141, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158,
18
+ 159, 160, 161
19
+ ]);
20
+ });
21
+
22
+ test('ids des générateurs de chauffage pompe à chaleur', () => {
23
+ expect(chTvStore.getPacGenerateurs()).toStrictEqual([
24
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 143, 145, 146, 147, 162,
25
+ 163, 164, 165, 166, 167, 168, 169, 170
26
+ ]);
27
+ });
28
+
29
+ test('Caractéristique du générateur à combustion', () => {
30
+ expect(chTvStore.getGenerateurCombustion('128', 125)).toStrictEqual({
31
+ tv_generateur_combustion_id: '2',
32
+ enum_type_generateur_ch_id: '86|128',
33
+ enum_type_generateur_ecs_id: '46|93',
34
+ type_generateur: 'Chaudière gaz classique 1981-1985',
35
+ pn: 'Pn',
36
+ rpn: '84 + 2 logPn',
37
+ rpint: '80 + 3 logPn',
38
+ qp0_perc: '2%',
39
+ pveil: '150'
40
+ });
41
+
42
+ expect(chTvStore.getGenerateurCombustion('84', 125)).toStrictEqual({
43
+ tv_generateur_combustion_id: '26',
44
+ enum_type_generateur_ch_id: '84',
45
+ enum_type_generateur_ecs_id: '44',
46
+ type_generateur: 'Chaudière fioul à condensation après 2015',
47
+ critere_pn: '70<Pn≤400',
48
+ pn: 'Pn',
49
+ rpn: '94 + logPn',
50
+ rpint: '100 + logPn',
51
+ qp0_perc: '0.60%'
52
+ });
53
+ });
54
+
55
+ describe('Lecture des valeurs de temp_fonc_30 ou temp_fonc_100', () => {
56
+ test.each([
57
+ {
58
+ label:
59
+ "Chaudière standard après 1990, emetteurs entre 1981 et 2000, basse température d'émission",
60
+ pourcentageFonctionnement: 30,
61
+ enumTypeGenerateurId: '89',
62
+ enumTemperatureDistribution: 2,
63
+ enumPeriodeEmetteurs: 2,
64
+ expected: 45
65
+ },
66
+ {
67
+ label: "Emetteurs entre 1981 et 2000, basse température d'émission",
68
+ pourcentageFonctionnement: 100,
69
+ enumTypeGenerateurId: '89',
70
+ enumTemperatureDistribution: 2,
71
+ enumPeriodeEmetteurs: 2,
72
+ expected: 35
73
+ }
74
+ ])(
75
+ `$label`,
76
+ ({
77
+ pourcentageFonctionnement,
78
+ enumTypeGenerateurId,
79
+ enumTemperatureDistribution,
80
+ enumPeriodeEmetteurs,
81
+ expected
82
+ }) => {
83
+ expect(
84
+ chTvStore.temperatureFonctionnement(
85
+ pourcentageFonctionnement,
86
+ enumTypeGenerateurId,
87
+ enumTemperatureDistribution,
88
+ enumPeriodeEmetteurs
89
+ )
90
+ ).toBe(expected);
91
+ }
92
+ );
93
+
94
+ test('pas de valeur de temp_fonc_30 ou temp_fonc_100', () => {
95
+ const pertes_stockage = chTvStore.temperatureFonctionnement(100, 600, 600, 600);
96
+ expect(pertes_stockage).toBeUndefined();
97
+ });
98
+ });
99
+ });
@@ -58,8 +58,10 @@ export class EcsTvStore extends TvStore {
58
58
  * @return {[number]}
59
59
  */
60
60
  getElectriqueEcsGenerateurs() {
61
- return tv['pertes_stockage'].flatMap((v) =>
62
- v.enum_type_generateur_ecs_id.split('|').map(Number)
63
- );
61
+ return [
62
+ ...new Set(
63
+ tv['pertes_stockage'].flatMap((v) => v.enum_type_generateur_ecs_id.split('|').map(Number))
64
+ )
65
+ ];
64
66
  }
65
67
  }
@@ -66,4 +66,8 @@ describe('Lecture des tables de valeurs', () => {
66
66
  expect(pertes_stockage).toBeUndefined();
67
67
  });
68
68
  });
69
+
70
+ test('ids des générateurs électriques ECS', () => {
71
+ expect(ecsTvStore.getElectriqueEcsGenerateurs()).toStrictEqual([68, 118, 69, 70, 71]);
72
+ });
69
73
  });
@@ -15,8 +15,10 @@ export class FrTvStore extends TvStore {
15
15
  * — e_fr_28 : ensoleillement reçu en période de refroidissement pour un mois donné et une consigne de refroidissement à 28°C (comportement conventionnel).
16
16
  * — textmoy_clim_26 : Température extérieure moyenne pour un mois donné et une consigne de refroidissement à 26°C (comportement conventionnel).
17
17
  * — textmoy_clim_28 : nombre d’heures de chauffage pour un mois donné et une consigne de refroidissement à 28°C (comportement conventionnel).
18
+ * — dh19 : degrés heures de chauffage pour un mois donné à 19°C (comportement conventionnel).
19
+ * — dh21 : degrés heures de chauffage pour un mois donné à 21°C (comportement dépensier).
18
20
  *
19
- * @param type {'e', nref26' | 'nref28' | 'e_fr_26' | 'e_fr_28' | 'textmoy_clim_26' | 'textmoy_clim_28'}
21
+ * @param type {'e', nref26' | 'nref28' | 'e_fr_26' | 'e_fr_28' | 'textmoy_clim_26' | 'textmoy_clim_28'| 'dh19'| 'dh21'}
20
22
  * @param classeAltitude {string}
21
23
  * @param zoneClimatique {string}
22
24
  * @param mois {string}
@@ -31,6 +33,6 @@ export class FrTvStore extends TvStore {
31
33
  values = values[ilpa];
32
34
  }
33
35
 
34
- return values[classeAltitude][mois][zoneClimatique];
36
+ return parseFloat(values[classeAltitude][mois][zoneClimatique]);
35
37
  }
36
38
  }
@@ -353,4 +353,32 @@ export class TvStore {
353
353
 
354
354
  return q4paConv;
355
355
  }
356
+
357
+ /**
358
+ * Température extérieure de base(°C)
359
+ *
360
+ * @param classeAltitude {string}
361
+ * @param zoneClimatique {string}
362
+ */
363
+ getTempBase(classeAltitude, zoneClimatique) {
364
+ const Tbase = {
365
+ 1: {
366
+ h1: -9.5,
367
+ h2: -6.5,
368
+ h3: -3.5
369
+ },
370
+ 2: {
371
+ h1: -11.5,
372
+ h2: -8.5,
373
+ h3: -5.5
374
+ },
375
+ 3: {
376
+ h1: -13.5,
377
+ h2: -10.5,
378
+ h3: -7.5
379
+ }
380
+ };
381
+
382
+ return Tbase[classeAltitude][zoneClimatique];
383
+ }
356
384
  }
@@ -565,6 +565,18 @@ describe('Lecture des tables de valeurs', () => {
565
565
  });
566
566
  });
567
567
 
568
+ test('lecture des valeurs de tempBase', () => {
569
+ expect(tvStore.getTempBase('1', 'h1')).toBe(-9.5);
570
+ expect(tvStore.getTempBase('1', 'h2')).toBe(-6.5);
571
+ expect(tvStore.getTempBase('1', 'h3')).toBe(-3.5);
572
+ expect(tvStore.getTempBase('2', 'h1')).toBe(-11.5);
573
+ expect(tvStore.getTempBase('2', 'h2')).toBe(-8.5);
574
+ expect(tvStore.getTempBase('2', 'h3')).toBe(-5.5);
575
+ expect(tvStore.getTempBase('3', 'h1')).toBe(-13.5);
576
+ expect(tvStore.getTempBase('3', 'h2')).toBe(-10.5);
577
+ expect(tvStore.getTempBase('3', 'h3')).toBe(-7.5);
578
+ });
579
+
568
580
  describe.skip('Benchmark b', () => {
569
581
  test('reworked', () => {
570
582
  for (let i = 0; i < 1000; i++) {
@@ -5,6 +5,9 @@ import { BesoinFroidService } from './froid/besoin-froid.service.js';
5
5
  import { ApportGratuitService } from './apport_gratuit/apport-gratuit.service.js';
6
6
  import { InstallationEcsService } from '../ecs/installation-ecs.service.js';
7
7
  import { PerteEcsRecupService } from './ecs/perte-ecs-recup.service.js';
8
+ import { BesoinChService } from './ch/besoin-ch.service.js';
9
+ import { PerteChRecupService } from './ch/perte-ch-recup.service.js';
10
+ import { InstallationChService } from '../ch/installation-ch.service.js';
8
11
 
9
12
  /**
10
13
  * Calcul des déperditions de l’enveloppe GV
@@ -21,11 +24,21 @@ export class ApportEtBesoinService {
21
24
  */
22
25
  #besoinEcsService;
23
26
 
27
+ /**
28
+ * @type {BesoinChService}
29
+ */
30
+ #besoinChService;
31
+
24
32
  /**
25
33
  * @type {InstallationEcsService}
26
34
  */
27
35
  #installationEcsService;
28
36
 
37
+ /**
38
+ * @type {InstallationChService}
39
+ */
40
+ #installationChService;
41
+
29
42
  /**
30
43
  * @type {PerteEcsRecupService}
31
44
  */
@@ -36,6 +49,11 @@ export class ApportEtBesoinService {
36
49
  */
37
50
  #besoinFroidService;
38
51
 
52
+ /**
53
+ * @type {PerteChRecupService}
54
+ */
55
+ #perteChRecupService;
56
+
39
57
  /**
40
58
  * @type {ApportGratuitService}
41
59
  */
@@ -43,25 +61,34 @@ export class ApportEtBesoinService {
43
61
 
44
62
  /**
45
63
  * @param besoinEcsService {BesoinEcsService}
64
+ * @param besoinChService {BesoinChService}
46
65
  * @param installationEcsService {InstallationEcsService}
66
+ * @param installationChService {InstallationChService}
47
67
  * @param perteEcsRecupService {PerteEcsRecupService}
48
68
  * @param besoinFroidService {BesoinFroidService}
49
69
  * @param surfaceSudEquivalenteService {SurfaceSudEquivalenteService}
70
+ * @param perteChRecupService {PerteChRecupService}
50
71
  * @param apportGratuitService {ApportGratuitService}
51
72
  */
52
73
  constructor(
53
74
  besoinEcsService = inject(BesoinEcsService),
75
+ besoinChService = inject(BesoinChService),
54
76
  installationEcsService = inject(InstallationEcsService),
77
+ installationChService = inject(InstallationChService),
55
78
  perteEcsRecupService = inject(PerteEcsRecupService),
56
79
  besoinFroidService = inject(BesoinFroidService),
57
80
  surfaceSudEquivalenteService = inject(SurfaceSudEquivalenteService),
81
+ perteChRecupService = inject(PerteChRecupService),
58
82
  apportGratuitService = inject(ApportGratuitService)
59
83
  ) {
60
84
  this.#besoinEcsService = besoinEcsService;
85
+ this.#besoinChService = besoinChService;
61
86
  this.#installationEcsService = installationEcsService;
87
+ this.#installationChService = installationChService;
62
88
  this.#perteEcsRecupService = perteEcsRecupService;
63
89
  this.#besoinFroidService = besoinFroidService;
64
90
  this.#surfaceSudEquivalenteService = surfaceSudEquivalenteService;
91
+ this.#perteChRecupService = perteChRecupService;
65
92
  this.#apportGratuitService = apportGratuitService;
66
93
  }
67
94
 
@@ -80,6 +107,31 @@ export class ApportEtBesoinService {
80
107
  */
81
108
  this.#installationEcsService.execute(ctx, logement, besoinEcs);
82
109
 
110
+ /**
111
+ * Détermination des données des installations de chauffage
112
+ */
113
+ this.#installationChService.execute(ctx, logement);
114
+
115
+ const apportsInternes = this.#apportGratuitService.apportInterne(ctx, logement);
116
+ const apportsSolaires = this.#apportGratuitService.apportSolaire(ctx, logement);
117
+
118
+ const pertesEcsRecup = this.#perteEcsRecupService.execute(ctx, logement);
119
+ // Besoin de chauffage hors pertes récupérées
120
+ const besoinChHP = this.#besoinChService.execute(ctx, logement);
121
+ const pertesChauffageRecup = this.#perteChRecupService.execute(ctx, logement);
122
+
123
+ const besoinCh = {
124
+ besoin_ch: besoinChHP.besoin_ch_hp,
125
+ besoin_ch_depensier: besoinChHP.besoin_ch_depensier_hp
126
+ };
127
+ besoinCh.besoin_ch -= pertesEcsRecup.pertes_distribution_ecs_recup;
128
+ besoinCh.besoin_ch -= pertesEcsRecup.pertes_stockage_ecs_recup;
129
+ besoinCh.besoin_ch -= pertesChauffageRecup.pertes_generateur_ch_recup;
130
+
131
+ besoinCh.besoin_ch_depensier -= pertesEcsRecup.pertes_distribution_ecs_recup_depensier;
132
+ besoinCh.besoin_ch_depensier -= pertesEcsRecup.pertes_stockage_ecs_recup_depensier;
133
+ besoinCh.besoin_ch_depensier -= pertesChauffageRecup.pertes_generateur_ch_recup_depensier;
134
+
83
135
  return {
84
136
  ...besoinEcs,
85
137
  ...{
@@ -92,9 +144,11 @@ export class ApportEtBesoinService {
92
144
  v40_ecs_journalier_depensier: ctx.nadeq * 79
93
145
  },
94
146
  ...this.#besoinFroidService.execute(ctx, logement),
95
- ...this.#apportGratuitService.apportInterne(ctx, logement),
96
- ...this.#apportGratuitService.apportSolaire(ctx, logement),
97
- ...this.#perteEcsRecupService.execute(ctx, logement)
147
+ ...apportsInternes,
148
+ ...apportsSolaires,
149
+ ...pertesEcsRecup,
150
+ ...pertesChauffageRecup,
151
+ ...besoinCh
98
152
  };
99
153
  }
100
154
  }