@open3cl/engine 1.7.0 → 1.7.1
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.
- package/10_besoin_fr.spec.js +1 -0
- package/10_clim.spec.js +1 -0
- package/11_besoin_ecs.spec.js +1 -0
- package/11_ecs.spec.js +1 -0
- package/12.4_pac.spec.js +1 -0
- package/13.2_generateur_combustion.spec.js +3 -3
- package/13.2_generateur_combustion_ch.spec.js +3 -3
- package/14_generateur_ecs.spec.js +1 -0
- package/15_conso_aux.spec.js +3 -3
- package/2021_04_13_confort_ete.spec.js +1 -0
- package/3.1_b.spec.js +1 -0
- package/3.2.1_mur.spec.js +1 -0
- package/3.2.2_plancher_bas.spec.js +1 -0
- package/3.2.3_plancher_haut.spec.js +1 -0
- package/3.3.1.4_porte.spec.js +1 -0
- package/3.3_baie_vitree.spec.js +1 -0
- package/3.4_pont_thermique.spec.js +1 -0
- package/4_ventilation.spec.js +1 -0
- package/5_conso_ventilation.spec.js +1 -0
- package/6.2_surface_sud_equivalente.spec.js +1 -0
- package/9_besoin_ch.spec.js +1 -0
- package/9_chauffage.spec.js +3 -3
- package/9_conso_ch.spec.js +1 -0
- package/9_emetteur_ch.spec.js +1 -0
- package/9_generateur_ch.spec.js +1 -0
- package/README.md +412 -291
- package/conso.spec.js +1 -0
- package/engine.js +3 -1
- package/engine.spec.js +1 -0
- package/package.json +15 -14
- package/features/engine/domain/apport_et_besoin/apport-et-besoin.service.spec.js +0 -222
- package/features/engine/domain/apport_et_besoin/ch/perte-ch-recup.service.spec.js +0 -345
- package/features/engine/domain/apport_et_besoin/ecs/besoin-ecs.service.spec.js +0 -87
- package/features/engine/domain/apport_et_besoin/ecs/perte-ecs-recup.service.spec.js +0 -260
- package/features/engine/domain/apport_et_besoin/froid/besoin-froid.service.spec.js +0 -272
- package/features/engine/domain/apport_et_besoin/surface-sud-equivalente.service.spec.js +0 -231
- package/features/engine/domain/ch/generateur-ch.service.spec.js +0 -849
- package/features/engine/domain/conso/froid/conso-froid.service.spec.js +0 -233
- package/features/engine/domain/ecs/installation-ecs.service.spec.js +0 -337
- package/features/engine/domain/enveloppe/baie_vitree/deperdition-baie-vitree.service.spec.js +0 -607
- package/features/engine/domain/enveloppe/deperdition-enveloppe.service.spec.js +0 -550
- package/features/engine/domain/enveloppe/espace_tampon/espace-tampon.service.spec.js +0 -82
- package/features/engine/domain/enveloppe/mur/deperdition-mur.service.spec.js +0 -542
- package/features/engine/domain/enveloppe/plancher_bas/deperdition-plancher-bas.service.spec.js +0 -430
- package/features/engine/domain/enveloppe/plancher_haut/deperdition-plancher-haut.service.spec.js +0 -411
- package/features/engine/domain/enveloppe/pont_thermique/deperdition-pont-thermique.service.spec.js +0 -653
- package/features/engine/domain/enveloppe/porte/deperdition-porte.service.spec.js +0 -117
- package/features/engine/domain/enveloppe/ventilation/deperdition-ventilation.service.spec.js +0 -508
|
@@ -1,233 +0,0 @@
|
|
|
1
|
-
import { beforeEach, describe, expect, test, vi } from 'vitest';
|
|
2
|
-
import { DpeNormalizerService } from '../../../../normalizer/domain/dpe-normalizer.service.js';
|
|
3
|
-
import { ContexteBuilder } from '../../contexte.builder.js';
|
|
4
|
-
import corpus from '../../../../../../test/corpus-sano.json';
|
|
5
|
-
import { getAdemeFileJson } from '../../../../../../test/test-helpers.js';
|
|
6
|
-
import { FrTvStore } from '../../../../dpe/infrastructure/froid/frTv.store.js';
|
|
7
|
-
import { ConsoFroidService } from './conso-froid.service.js';
|
|
8
|
-
import { describeIntegration } from '../../../../../../test/helpers/integration-test.js';
|
|
9
|
-
|
|
10
|
-
/** @type {ConsoFroidService} **/
|
|
11
|
-
let service;
|
|
12
|
-
|
|
13
|
-
/** @type {DpeNormalizerService} **/
|
|
14
|
-
let normalizerService;
|
|
15
|
-
|
|
16
|
-
/** @type {ContexteBuilder} **/
|
|
17
|
-
let contexteBuilder;
|
|
18
|
-
|
|
19
|
-
/** @type {FrTvStore} **/
|
|
20
|
-
let tvStore;
|
|
21
|
-
|
|
22
|
-
describe('Calcul des consos en froid du logement', () => {
|
|
23
|
-
beforeEach(() => {
|
|
24
|
-
tvStore = new FrTvStore();
|
|
25
|
-
service = new ConsoFroidService(tvStore);
|
|
26
|
-
normalizerService = new DpeNormalizerService();
|
|
27
|
-
contexteBuilder = new ContexteBuilder();
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
test.each([
|
|
31
|
-
{
|
|
32
|
-
label: 'Climatisation avec méthode de saisie 6, sans surface clim',
|
|
33
|
-
enumMethodeSaisieCaracSysId: 6,
|
|
34
|
-
eerInitial: 125,
|
|
35
|
-
expected: { conso_fr: 7.2, conso_fr_depensier: 10.8 }
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
label: 'Climatisation avec méthode de saisie 7, sans surface clim',
|
|
39
|
-
enumMethodeSaisieCaracSysId: 7,
|
|
40
|
-
eerInitial: 125,
|
|
41
|
-
expected: { conso_fr: 7.2, conso_fr_depensier: 10.8 }
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
label: 'Climatisation avec méthode de saisie 8, sans surface clim',
|
|
45
|
-
enumMethodeSaisieCaracSysId: 8,
|
|
46
|
-
eerInitial: 125,
|
|
47
|
-
expected: { conso_fr: 7.2, conso_fr_depensier: 10.8 }
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
label: 'Climatisation avec méthode de saisie 6, avec surface clim',
|
|
51
|
-
enumMethodeSaisieCaracSysId: 6,
|
|
52
|
-
eerInitial: 125,
|
|
53
|
-
surfaceClim: 80,
|
|
54
|
-
expected: { conso_fr: 5.76, conso_fr_depensier: 8.64 }
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
label: 'Climatisation avec méthode de saisie 7, avec surface clim',
|
|
58
|
-
enumMethodeSaisieCaracSysId: 7,
|
|
59
|
-
eerInitial: 125,
|
|
60
|
-
surfaceClim: 80,
|
|
61
|
-
expected: { conso_fr: 5.76, conso_fr_depensier: 8.64 }
|
|
62
|
-
},
|
|
63
|
-
{
|
|
64
|
-
label: 'Climatisation avec méthode de saisie 8, avec surface clim',
|
|
65
|
-
enumMethodeSaisieCaracSysId: 8,
|
|
66
|
-
eerInitial: 125,
|
|
67
|
-
surfaceClim: 80,
|
|
68
|
-
expected: { conso_fr: 5.76, conso_fr_depensier: 8.64 }
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
label: 'Climatisation avec méthode de saisie 5, sans surface clim',
|
|
72
|
-
enumMethodeSaisieCaracSysId: 5,
|
|
73
|
-
eer: 90,
|
|
74
|
-
expected: { conso_fr: 10, conso_fr_depensier: 15 }
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
label: 'Climatisation avec méthode de saisie 5, avec surface clim',
|
|
78
|
-
enumMethodeSaisieCaracSysId: 5,
|
|
79
|
-
eer: 90,
|
|
80
|
-
surfaceClim: 80,
|
|
81
|
-
expected: { conso_fr: 8, conso_fr_depensier: 12 }
|
|
82
|
-
}
|
|
83
|
-
])(
|
|
84
|
-
'Détermination des consommations des systèmes de refroidissement pour $label',
|
|
85
|
-
({
|
|
86
|
-
enumMethodeSaisieCaracSysId,
|
|
87
|
-
surfaceClim = undefined,
|
|
88
|
-
eer = undefined,
|
|
89
|
-
eerInitial,
|
|
90
|
-
expected
|
|
91
|
-
}) => {
|
|
92
|
-
vi.spyOn(tvStore, 'getEer').mockReturnValue(eer);
|
|
93
|
-
|
|
94
|
-
/** @type {Contexte} */
|
|
95
|
-
const contexte = {
|
|
96
|
-
zoneClimatique: { id: 1 },
|
|
97
|
-
surfaceHabitable: 100
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
/** @type {Climatisation} */
|
|
101
|
-
const climatisation = {
|
|
102
|
-
donnee_entree: {
|
|
103
|
-
enum_methode_saisie_carac_sys_id: enumMethodeSaisieCaracSysId,
|
|
104
|
-
surface_clim: surfaceClim
|
|
105
|
-
},
|
|
106
|
-
donnee_intermediaire: { eer: eerInitial }
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
/** @type {ApportEtBesoin} */
|
|
110
|
-
const apportEtBesoin = {
|
|
111
|
-
besoin_fr: 1000,
|
|
112
|
-
besoin_fr_depensier: 1500
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
const consoFroid = service.consoFroid(contexte, apportEtBesoin, climatisation);
|
|
116
|
-
expect(consoFroid.conso_fr).toBeCloseTo(expected.conso_fr, 2);
|
|
117
|
-
expect(consoFroid.conso_fr_depensier).toBeCloseTo(expected.conso_fr_depensier, 2);
|
|
118
|
-
}
|
|
119
|
-
);
|
|
120
|
-
|
|
121
|
-
test('consoFroid : données intermédiaires absentes -> EER lu dans la table (repli {})', () => {
|
|
122
|
-
// climatisation.donnee_intermediaire absente : repli sur {} puis lecture de l'EER forfaitaire.
|
|
123
|
-
vi.spyOn(tvStore, 'getEer').mockReturnValue(90);
|
|
124
|
-
|
|
125
|
-
/** @type {Contexte} */
|
|
126
|
-
const contexte = { zoneClimatique: { id: 1 }, surfaceHabitable: 100 };
|
|
127
|
-
|
|
128
|
-
/** @type {Climatisation} */
|
|
129
|
-
const climatisation = {
|
|
130
|
-
donnee_entree: { enum_methode_saisie_carac_sys_id: 6, enum_periode_installation_fr_id: 2 }
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
/** @type {ApportEtBesoin} */
|
|
134
|
-
const apportEtBesoin = { besoin_fr: 1000, besoin_fr_depensier: 1500 };
|
|
135
|
-
|
|
136
|
-
const consoFroid = service.consoFroid(contexte, apportEtBesoin, climatisation);
|
|
137
|
-
|
|
138
|
-
expect(tvStore.getEer).toHaveBeenCalledWith(1, 2);
|
|
139
|
-
// conso = 0.9 * besoin / eer
|
|
140
|
-
expect(consoFroid.conso_fr).toBeCloseTo((0.9 * 1000) / 90, 5);
|
|
141
|
-
expect(consoFroid.conso_fr_depensier).toBeCloseTo((0.9 * 1500) / 90, 5);
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
test('execute : renseigne les données intermédiaires de chaque climatisation', () => {
|
|
145
|
-
// On isole execute du calcul détaillé : consoFroid est doublée pour ne vérifier que
|
|
146
|
-
// l'itération sur les climatisations et l'affectation des champs (dont l'initialisation ??=).
|
|
147
|
-
vi.spyOn(service, 'consoFroid').mockReturnValue({
|
|
148
|
-
besoin_fr: 10,
|
|
149
|
-
besoin_fr_depensier: 15,
|
|
150
|
-
conso_fr: 2,
|
|
151
|
-
conso_fr_depensier: 3
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
/** @type {Contexte} */
|
|
155
|
-
const ctx = { zoneClimatique: { id: 1 }, surfaceHabitable: 100 };
|
|
156
|
-
|
|
157
|
-
// Première climatisation sans donnee_intermediaire (branche ??= {}),
|
|
158
|
-
// seconde avec un objet préexistant (branche ??= conservée).
|
|
159
|
-
const climSansDI = { donnee_entree: {} };
|
|
160
|
-
const climAvecDI = { donnee_entree: {}, donnee_intermediaire: { eer: 42 } };
|
|
161
|
-
|
|
162
|
-
/** @type {Logement} */
|
|
163
|
-
const logement = {
|
|
164
|
-
sortie: { apport_et_besoin: { besoin_fr: 1000, besoin_fr_depensier: 1500 } },
|
|
165
|
-
climatisation_collection: { climatisation: [climSansDI, climAvecDI] }
|
|
166
|
-
};
|
|
167
|
-
|
|
168
|
-
service.execute(ctx, logement);
|
|
169
|
-
|
|
170
|
-
expect(service.consoFroid).toHaveBeenCalledTimes(2);
|
|
171
|
-
expect(service.consoFroid).toHaveBeenCalledWith(
|
|
172
|
-
ctx,
|
|
173
|
-
logement.sortie.apport_et_besoin,
|
|
174
|
-
climSansDI
|
|
175
|
-
);
|
|
176
|
-
|
|
177
|
-
for (const clim of [climSansDI, climAvecDI]) {
|
|
178
|
-
expect(clim.donnee_intermediaire).toMatchObject({
|
|
179
|
-
besoin_fr: 10,
|
|
180
|
-
besoin_fr_depensier: 15,
|
|
181
|
-
conso_fr: 2,
|
|
182
|
-
conso_fr_depensier: 3
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
// L'objet préexistant a été conservé (eer non écrasé par ??=)
|
|
186
|
-
expect(climAvecDI.donnee_intermediaire.eer).toBe(42);
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
test("execute : aucune conso calculée en l'absence de climatisation", () => {
|
|
190
|
-
// Valeur de repli [] quand climatisation_collection est absente.
|
|
191
|
-
vi.spyOn(service, 'consoFroid');
|
|
192
|
-
|
|
193
|
-
/** @type {Contexte} */
|
|
194
|
-
const ctx = { zoneClimatique: { id: 1 }, surfaceHabitable: 100 };
|
|
195
|
-
|
|
196
|
-
service.execute(ctx, { sortie: { apport_et_besoin: {} } });
|
|
197
|
-
|
|
198
|
-
expect(service.consoFroid).not.toHaveBeenCalled();
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
describeIntegration("Test d'intégration pour le besoin en froid", () => {
|
|
202
|
-
test.each(corpus)('vérification des sorties besoin_fr et conso_fr pour dpe %s', (ademeId) => {
|
|
203
|
-
/**
|
|
204
|
-
* @type {Dpe}
|
|
205
|
-
*/
|
|
206
|
-
let dpeRequest = getAdemeFileJson(ademeId);
|
|
207
|
-
dpeRequest = normalizerService.normalize(dpeRequest);
|
|
208
|
-
|
|
209
|
-
/** @type {Contexte} */
|
|
210
|
-
const ctx = contexteBuilder.fromDpe(dpeRequest);
|
|
211
|
-
|
|
212
|
-
const climatisations = structuredClone(
|
|
213
|
-
dpeRequest.logement.climatisation_collection?.climatisation || []
|
|
214
|
-
);
|
|
215
|
-
service.execute(ctx, dpeRequest.logement);
|
|
216
|
-
|
|
217
|
-
climatisations.forEach((climatisation, i) => {
|
|
218
|
-
console.log('climatisation.donnee_intermediaire.besoin_fr');
|
|
219
|
-
expect(climatisation.donnee_intermediaire.besoin_fr).toBeCloseTo(
|
|
220
|
-
dpeRequest.logement.climatisation_collection.climatisation[i].donnee_intermediaire
|
|
221
|
-
.besoin_fr,
|
|
222
|
-
2
|
|
223
|
-
);
|
|
224
|
-
console.log(climatisation.donnee_intermediaire.conso_fr);
|
|
225
|
-
expect(climatisation.donnee_intermediaire.conso_fr).toBeCloseTo(
|
|
226
|
-
dpeRequest.logement.climatisation_collection.climatisation[i].donnee_intermediaire
|
|
227
|
-
.conso_fr,
|
|
228
|
-
2
|
|
229
|
-
);
|
|
230
|
-
});
|
|
231
|
-
});
|
|
232
|
-
});
|
|
233
|
-
});
|
|
@@ -1,337 +0,0 @@
|
|
|
1
|
-
import { beforeEach, describe, expect, test, vi } from 'vitest';
|
|
2
|
-
import { GenerateurEcsService } from './generateur-ecs.service.js';
|
|
3
|
-
import { InstallationEcsService } from './installation-ecs.service.js';
|
|
4
|
-
import corpus from '../../../../../test/corpus-sano.json';
|
|
5
|
-
import { expect_or, getAdemeFileJson } from '../../../../../test/test-helpers.js';
|
|
6
|
-
import { DpeNormalizerService } from '../../../normalizer/domain/dpe-normalizer.service.js';
|
|
7
|
-
import { ContexteBuilder } from '../contexte.builder.js';
|
|
8
|
-
import { describeIntegration } from '../../../../../test/helpers/integration-test.js';
|
|
9
|
-
|
|
10
|
-
/** @type {InstallationEcsService} **/
|
|
11
|
-
let service;
|
|
12
|
-
|
|
13
|
-
/** @type {GenerateurEcsService} **/
|
|
14
|
-
let generateurEcsService;
|
|
15
|
-
|
|
16
|
-
/** @type {DpeNormalizerService} **/
|
|
17
|
-
let normalizerService;
|
|
18
|
-
|
|
19
|
-
/** @type {ContexteBuilder} **/
|
|
20
|
-
let contexteBuilder;
|
|
21
|
-
|
|
22
|
-
describe('Calcul des besoins et des pertes des installations ECS', () => {
|
|
23
|
-
beforeEach(() => {
|
|
24
|
-
generateurEcsService = new GenerateurEcsService();
|
|
25
|
-
service = new InstallationEcsService(generateurEcsService);
|
|
26
|
-
normalizerService = new DpeNormalizerService();
|
|
27
|
-
contexteBuilder = new ContexteBuilder();
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
test.each([
|
|
31
|
-
{
|
|
32
|
-
label: "Installation ECS sans surface habitable pour l'installation",
|
|
33
|
-
surfaceHabitableLogement: 40,
|
|
34
|
-
besoin_ecs: 850,
|
|
35
|
-
besoin_ecs_depensier: 1050,
|
|
36
|
-
expected: { besoinEcsDepensierInstallation: 1050, besoinEcsInstallation: 850 }
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
label: "Installation ECS avec surface habitable pour l'installation",
|
|
40
|
-
surfaceHabitableLogement: 40,
|
|
41
|
-
surfaceHabitableInstallation: 50,
|
|
42
|
-
besoin_ecs: 850,
|
|
43
|
-
besoin_ecs_depensier: 1050,
|
|
44
|
-
expected: { besoinEcsDepensierInstallation: 1312.5, besoinEcsInstallation: 1062.5 }
|
|
45
|
-
}
|
|
46
|
-
])(
|
|
47
|
-
'Calcul des besoins proratisés pour $label',
|
|
48
|
-
({
|
|
49
|
-
surfaceHabitableLogement,
|
|
50
|
-
surfaceHabitableInstallation = undefined,
|
|
51
|
-
besoin_ecs,
|
|
52
|
-
besoin_ecs_depensier,
|
|
53
|
-
expected
|
|
54
|
-
}) => {
|
|
55
|
-
/** @type {Contexte} */
|
|
56
|
-
const ctx = { surfaceHabitable: surfaceHabitableLogement };
|
|
57
|
-
|
|
58
|
-
/** @type {{besoin_ecs: number, besoin_ecs_depensier: number}} */
|
|
59
|
-
const besoinEcs = { besoin_ecs, besoin_ecs_depensier };
|
|
60
|
-
|
|
61
|
-
/** @type {InstallationEcs} */
|
|
62
|
-
const installationEcs = {
|
|
63
|
-
donnee_entree: { surface_habitable: surfaceHabitableInstallation }
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
const besoinEcsInstallation = service.besoinEcsInstallation(ctx, installationEcs, besoinEcs);
|
|
67
|
-
|
|
68
|
-
expect(besoinEcsInstallation).toStrictEqual(expected);
|
|
69
|
-
}
|
|
70
|
-
);
|
|
71
|
-
|
|
72
|
-
test.each([
|
|
73
|
-
{
|
|
74
|
-
label: 'Installation individuelle avec générateur hors volume chauffé',
|
|
75
|
-
enumTypeInstallationId: 1,
|
|
76
|
-
positionVolumeChauffeStockage1: 0,
|
|
77
|
-
positionVolumeChauffeStockage2: 0,
|
|
78
|
-
positionVolumeChauffeStockage3: 0,
|
|
79
|
-
expected: {
|
|
80
|
-
QdwIndVc: { conventionnel: 15, depensier: 27 },
|
|
81
|
-
QdwColVc: { conventionnel: 0, depensier: 0 },
|
|
82
|
-
QdwColHVc: { conventionnel: 0, depensier: 0 },
|
|
83
|
-
QgwRecuperable: 0
|
|
84
|
-
}
|
|
85
|
-
},
|
|
86
|
-
{
|
|
87
|
-
label: 'Installation individuelle avec générateur hors volume chauffé',
|
|
88
|
-
enumTypeInstallationId: 1,
|
|
89
|
-
positionVolumeChauffeStockage2: 0,
|
|
90
|
-
positionVolumeChauffe2: 0,
|
|
91
|
-
positionVolumeChauffeStockage3: 0,
|
|
92
|
-
expected: {
|
|
93
|
-
QdwIndVc: { conventionnel: 15, depensier: 27 },
|
|
94
|
-
QdwColVc: { conventionnel: 0, depensier: 0 },
|
|
95
|
-
QdwColHVc: { conventionnel: 0, depensier: 0 },
|
|
96
|
-
QgwRecuperable: 0
|
|
97
|
-
}
|
|
98
|
-
},
|
|
99
|
-
{
|
|
100
|
-
label: 'Installation individuelle avec 1 générateur en volume chauffé',
|
|
101
|
-
enumTypeInstallationId: 1,
|
|
102
|
-
positionVolumeChauffeStockage1: 0,
|
|
103
|
-
positionVolumeChauffeStockage2: 1,
|
|
104
|
-
positionVolumeChauffeStockage3: 0,
|
|
105
|
-
expected: {
|
|
106
|
-
QdwIndVc: { conventionnel: 15, depensier: 27 },
|
|
107
|
-
QdwColVc: { conventionnel: 0, depensier: 0 },
|
|
108
|
-
QdwColHVc: { conventionnel: 0, depensier: 0 },
|
|
109
|
-
QgwRecuperable: 120
|
|
110
|
-
}
|
|
111
|
-
},
|
|
112
|
-
{
|
|
113
|
-
label: 'Installation individuelle avec 1 générateur en volume chauffé',
|
|
114
|
-
enumTypeInstallationId: 1,
|
|
115
|
-
positionVolumeChauffeStockage1: 0,
|
|
116
|
-
positionVolumeChauffe2: 1,
|
|
117
|
-
positionVolumeChauffeStockage3: 0,
|
|
118
|
-
expected: {
|
|
119
|
-
QdwIndVc: { conventionnel: 15, depensier: 27 },
|
|
120
|
-
QdwColVc: { conventionnel: 0, depensier: 0 },
|
|
121
|
-
QdwColHVc: { conventionnel: 0, depensier: 0 },
|
|
122
|
-
QgwRecuperable: 120
|
|
123
|
-
}
|
|
124
|
-
},
|
|
125
|
-
{
|
|
126
|
-
label: 'Installation individuelle avec 2 générateurs en volume chauffé',
|
|
127
|
-
enumTypeInstallationId: 1,
|
|
128
|
-
positionVolumeChauffeStockage1: 0,
|
|
129
|
-
positionVolumeChauffeStockage2: 1,
|
|
130
|
-
positionVolumeChauffeStockage3: 1,
|
|
131
|
-
expected: {
|
|
132
|
-
QdwIndVc: { conventionnel: 15, depensier: 27 },
|
|
133
|
-
QdwColVc: { conventionnel: 0, depensier: 0 },
|
|
134
|
-
QdwColHVc: { conventionnel: 0, depensier: 0 },
|
|
135
|
-
QgwRecuperable: 260
|
|
136
|
-
}
|
|
137
|
-
},
|
|
138
|
-
{
|
|
139
|
-
label: 'Installation collective avec générateur hors volume chauffé',
|
|
140
|
-
enumTypeInstallationId: 2,
|
|
141
|
-
positionVolumeChauffeStockage1: 0,
|
|
142
|
-
positionVolumeChauffeStockage2: 0,
|
|
143
|
-
positionVolumeChauffeStockage3: 0,
|
|
144
|
-
expected: {
|
|
145
|
-
QdwIndVc: { conventionnel: 15, depensier: 27 },
|
|
146
|
-
QdwColVc: { conventionnel: 16.8, depensier: 30.24 },
|
|
147
|
-
QdwColHVc: { conventionnel: 4.2, depensier: 7.56 },
|
|
148
|
-
QgwRecuperable: 0
|
|
149
|
-
}
|
|
150
|
-
},
|
|
151
|
-
{
|
|
152
|
-
label: 'Installation collective avec 1 générateur en volume chauffé',
|
|
153
|
-
enumTypeInstallationId: 2,
|
|
154
|
-
positionVolumeChauffeStockage1: 0,
|
|
155
|
-
positionVolumeChauffeStockage2: 0,
|
|
156
|
-
positionVolumeChauffeStockage3: 1,
|
|
157
|
-
expected: {
|
|
158
|
-
QdwIndVc: { conventionnel: 15, depensier: 27 },
|
|
159
|
-
QdwColVc: { conventionnel: 16.8, depensier: 30.24 },
|
|
160
|
-
QdwColHVc: { conventionnel: 4.2, depensier: 7.56 },
|
|
161
|
-
QgwRecuperable: 0
|
|
162
|
-
}
|
|
163
|
-
},
|
|
164
|
-
{
|
|
165
|
-
label: 'Installation collective avec 2 générateurs en volume chauffé',
|
|
166
|
-
enumTypeInstallationId: 2,
|
|
167
|
-
positionVolumeChauffeStockage1: 1,
|
|
168
|
-
positionVolumeChauffeStockage2: 1,
|
|
169
|
-
positionVolumeChauffeStockage3: 0,
|
|
170
|
-
expected: {
|
|
171
|
-
QdwIndVc: { conventionnel: 15, depensier: 27 },
|
|
172
|
-
QdwColVc: { conventionnel: 16.8, depensier: 30.24 },
|
|
173
|
-
QdwColHVc: { conventionnel: 4.2, depensier: 7.56 },
|
|
174
|
-
QgwRecuperable: 0
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
])(
|
|
178
|
-
'Calcul des pertes de distribution et de stockage $label',
|
|
179
|
-
({
|
|
180
|
-
enumTypeInstallationId,
|
|
181
|
-
positionVolumeChauffeStockage1,
|
|
182
|
-
positionVolumeChauffeStockage2,
|
|
183
|
-
positionVolumeChauffe2 = undefined,
|
|
184
|
-
positionVolumeChauffeStockage3,
|
|
185
|
-
expected
|
|
186
|
-
}) => {
|
|
187
|
-
/** @type {InstallationEcs} */
|
|
188
|
-
const installationEcs = {
|
|
189
|
-
donnee_entree: { enum_type_installation_id: enumTypeInstallationId },
|
|
190
|
-
generateur_ecs_collection: {
|
|
191
|
-
generateur_ecs: [
|
|
192
|
-
{
|
|
193
|
-
donnee_entree: { position_volume_chauffe_stockage: positionVolumeChauffeStockage1 },
|
|
194
|
-
donnee_utilisateur: { Qgw: 100 }
|
|
195
|
-
},
|
|
196
|
-
{
|
|
197
|
-
donnee_entree: {
|
|
198
|
-
position_volume_chauffe_stockage: positionVolumeChauffeStockage2,
|
|
199
|
-
position_volume_chauffe: positionVolumeChauffe2
|
|
200
|
-
},
|
|
201
|
-
donnee_utilisateur: { Qgw: 120 }
|
|
202
|
-
},
|
|
203
|
-
{
|
|
204
|
-
donnee_entree: { position_volume_chauffe_stockage: positionVolumeChauffeStockage3 },
|
|
205
|
-
donnee_utilisateur: { Qgw: 140 }
|
|
206
|
-
}
|
|
207
|
-
]
|
|
208
|
-
}
|
|
209
|
-
};
|
|
210
|
-
|
|
211
|
-
service.pertesDistributionStockageEcsInstallation(installationEcs, 150, 270);
|
|
212
|
-
|
|
213
|
-
expect(installationEcs.donnee_utilisateur.QdwIndVc.conventionnel).toBeCloseTo(
|
|
214
|
-
expected.QdwIndVc.conventionnel,
|
|
215
|
-
5
|
|
216
|
-
);
|
|
217
|
-
expect(installationEcs.donnee_utilisateur.QdwIndVc.depensier).toBeCloseTo(
|
|
218
|
-
expected.QdwIndVc.depensier,
|
|
219
|
-
5
|
|
220
|
-
);
|
|
221
|
-
expect(installationEcs.donnee_utilisateur.QdwColVc.conventionnel).toBeCloseTo(
|
|
222
|
-
expected.QdwColVc.conventionnel,
|
|
223
|
-
5
|
|
224
|
-
);
|
|
225
|
-
expect(installationEcs.donnee_utilisateur.QdwColVc.depensier).toBeCloseTo(
|
|
226
|
-
expected.QdwColVc.depensier,
|
|
227
|
-
5
|
|
228
|
-
);
|
|
229
|
-
expect(installationEcs.donnee_utilisateur.QdwColHVc.conventionnel).toBeCloseTo(
|
|
230
|
-
expected.QdwColHVc.conventionnel,
|
|
231
|
-
5
|
|
232
|
-
);
|
|
233
|
-
expect(installationEcs.donnee_utilisateur.QdwColHVc.depensier).toBeCloseTo(
|
|
234
|
-
expected.QdwColHVc.depensier,
|
|
235
|
-
5
|
|
236
|
-
);
|
|
237
|
-
expect(installationEcs.donnee_utilisateur.QgwRecuperable).toBeCloseTo(
|
|
238
|
-
expected.QgwRecuperable,
|
|
239
|
-
5
|
|
240
|
-
);
|
|
241
|
-
}
|
|
242
|
-
);
|
|
243
|
-
|
|
244
|
-
test("Determination du caractère individuelle de l'installation", () => {
|
|
245
|
-
expect(service.isInstallationIndividuelle({ enum_type_installation_id: 1 })).toBeTruthy();
|
|
246
|
-
expect(service.isInstallationIndividuelle({ enum_type_installation_id: 2 })).toBeFalsy();
|
|
247
|
-
expect(service.isInstallationIndividuelle({ enum_type_installation_id: 3 })).toBeFalsy();
|
|
248
|
-
expect(service.isInstallationIndividuelle({ enum_type_installation_id: 4 })).toBeFalsy();
|
|
249
|
-
});
|
|
250
|
-
|
|
251
|
-
test('execute : parcourt les installations ECS et renseigne besoins et pertes', () => {
|
|
252
|
-
// Le calcul des Qgw par générateur est délégué au GenerateurEcsService : on le double
|
|
253
|
-
// pour isoler la logique d'orchestration de l'installation.
|
|
254
|
-
vi.spyOn(generateurEcsService, 'execute').mockReturnValue(undefined);
|
|
255
|
-
|
|
256
|
-
/** @type {Contexte} */
|
|
257
|
-
const ctx = { surfaceHabitable: 100 };
|
|
258
|
-
|
|
259
|
-
/** @type {InstallationEcs} */
|
|
260
|
-
const installationEcs = {
|
|
261
|
-
donnee_entree: { enum_type_installation_id: 1, surface_habitable: 100 },
|
|
262
|
-
generateur_ecs_collection: {
|
|
263
|
-
generateur_ecs: [
|
|
264
|
-
{
|
|
265
|
-
donnee_entree: { position_volume_chauffe_stockage: 1 },
|
|
266
|
-
donnee_utilisateur: { Qgw: 500 }
|
|
267
|
-
}
|
|
268
|
-
]
|
|
269
|
-
}
|
|
270
|
-
};
|
|
271
|
-
|
|
272
|
-
/** @type {Logement} */
|
|
273
|
-
const logement = { installation_ecs_collection: { installation_ecs: [installationEcs] } };
|
|
274
|
-
|
|
275
|
-
service.execute(ctx, logement, { besoin_ecs: 1000, besoin_ecs_depensier: 1500 });
|
|
276
|
-
|
|
277
|
-
// Délégation du calcul par générateur
|
|
278
|
-
expect(generateurEcsService.execute).toHaveBeenCalledWith(installationEcs);
|
|
279
|
-
|
|
280
|
-
// Besoins proratisés (surface installation === surface logement -> ratio 1)
|
|
281
|
-
expect(installationEcs.donnee_intermediaire).toStrictEqual({
|
|
282
|
-
besoin_ecs: 1000,
|
|
283
|
-
besoin_ecs_depensier: 1500
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
// Pertes de distribution individuelle : 0.1 * besoin (en Wh) ; installation individuelle -> QdwCol* = 0
|
|
287
|
-
expect(installationEcs.donnee_utilisateur.QdwIndVc.conventionnel).toBeCloseTo(100000, 5);
|
|
288
|
-
expect(installationEcs.donnee_utilisateur.QdwIndVc.depensier).toBeCloseTo(150000, 5);
|
|
289
|
-
expect(installationEcs.donnee_utilisateur.QdwColVc.conventionnel).toBe(0);
|
|
290
|
-
// Générateur en volume chauffé -> stockage récupérable = Qgw
|
|
291
|
-
expect(installationEcs.donnee_utilisateur.QgwRecuperable).toBe(500);
|
|
292
|
-
});
|
|
293
|
-
|
|
294
|
-
test('execute : aucune installation traitée quand la collection ECS est absente', () => {
|
|
295
|
-
// Valeur de repli [] quand installation_ecs_collection est absente.
|
|
296
|
-
const generateurSpy = vi.spyOn(generateurEcsService, 'execute');
|
|
297
|
-
|
|
298
|
-
service.execute({ surfaceHabitable: 100 }, {}, { besoin_ecs: 0, besoin_ecs_depensier: 0 });
|
|
299
|
-
|
|
300
|
-
expect(generateurSpy).not.toHaveBeenCalled();
|
|
301
|
-
});
|
|
302
|
-
|
|
303
|
-
describeIntegration("Test d'intégration des installations ECS", () => {
|
|
304
|
-
test.each(corpus)('vérification des DI des installations ECS pour dpe %s', (ademeId) => {
|
|
305
|
-
let dpeRequest = getAdemeFileJson(ademeId);
|
|
306
|
-
dpeRequest = normalizerService.normalize(dpeRequest);
|
|
307
|
-
|
|
308
|
-
/** @type {Contexte} */
|
|
309
|
-
const ctx = contexteBuilder.fromDpe(dpeRequest);
|
|
310
|
-
|
|
311
|
-
const installationsECS = structuredClone(
|
|
312
|
-
dpeRequest.logement.installation_ecs_collection?.installation_ecs || []
|
|
313
|
-
);
|
|
314
|
-
service.execute(ctx, dpeRequest.logement, {
|
|
315
|
-
besoin_ecs: dpeRequest.logement.sortie.apport_et_besoin.besoin_ecs,
|
|
316
|
-
besoin_ecs_depensier: dpeRequest.logement.sortie.apport_et_besoin.besoin_ecs_depensier
|
|
317
|
-
});
|
|
318
|
-
|
|
319
|
-
installationsECS.forEach((installationECS, i) => {
|
|
320
|
-
expect_or(
|
|
321
|
-
() =>
|
|
322
|
-
expect(installationECS.donnee_intermediaire.besoin_ecs).toBeCloseTo(
|
|
323
|
-
dpeRequest.logement.installation_ecs_collection.installation_ecs[i]
|
|
324
|
-
.donnee_intermediaire.besoin_ecs,
|
|
325
|
-
2
|
|
326
|
-
),
|
|
327
|
-
() =>
|
|
328
|
-
expect(installationECS.donnee_intermediaire.besoin_ecs).toBeCloseTo(
|
|
329
|
-
dpeRequest.logement.installation_ecs_collection.installation_ecs[i]
|
|
330
|
-
.donnee_intermediaire.besoin_ecs * 1000,
|
|
331
|
-
2
|
|
332
|
-
)
|
|
333
|
-
);
|
|
334
|
-
});
|
|
335
|
-
});
|
|
336
|
-
});
|
|
337
|
-
});
|