@open3cl/engine 1.0.7 → 1.0.9

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 (24) hide show
  1. package/features/dpe/domain/models/baie-vitree.model.ts +8 -6
  2. package/features/dpe/domain/models/dpe.model.ts +7 -3
  3. package/features/dpe/domain/models/{plancher-bas.model.ts → plancher.model.ts} +31 -7
  4. package/features/dpe/infrastructure/baieVitreeTv.store.js +292 -0
  5. package/features/dpe/infrastructure/baieVitreeTv.store.spec.js +352 -0
  6. package/features/dpe/infrastructure/pontThermiqueTv.store.js +112 -0
  7. package/features/dpe/infrastructure/pontThermiqueTv.store.spec.js +134 -0
  8. package/features/dpe/infrastructure/tv.store.js +0 -33
  9. package/features/dpe/infrastructure/tv.store.spec.js +0 -83
  10. package/features/engine/domain/engine.service.js +2 -1
  11. package/features/engine/domain/enveloppe/baie_vitree/deperdition-baie-vitree.service.js +292 -0
  12. package/features/engine/domain/enveloppe/baie_vitree/deperdition-baie-vitree.service.spec.js +484 -0
  13. package/features/engine/domain/enveloppe/deperdition-enveloppe.service.js +38 -0
  14. package/features/engine/domain/enveloppe/mur/deperdition-mur.service.js +28 -0
  15. package/features/engine/domain/enveloppe/mur/deperdition-mur.service.spec.js +61 -0
  16. package/features/engine/domain/enveloppe/plancher_bas/deperdition-plancher-bas.service.js +46 -0
  17. package/features/engine/domain/enveloppe/plancher_bas/deperdition-plancher-bas.service.spec.js +85 -0
  18. package/features/engine/domain/enveloppe/plancher_haut/deperdition-plancher-haut.service.js +33 -0
  19. package/features/engine/domain/enveloppe/plancher_haut/deperdition-plancher-haut.service.spec.js +61 -0
  20. package/features/engine/domain/enveloppe/pont_thermique/deperdition-pont-thermique.service.js +439 -0
  21. package/features/engine/domain/enveloppe/pont_thermique/deperdition-pont-thermique.service.spec.js +636 -0
  22. package/features/engine/domain/enveloppe/ventilation/deperdition-ventilation.service.spec.js +49 -0
  23. package/package.json +1 -1
  24. package/features/dpe/domain/models/plancher-haut.model.ts +0 -33
@@ -0,0 +1,636 @@
1
+ import corpus from '../../../../../../test/corpus-sano.json';
2
+ import { getAdemeFileJson } from '../../../../../../test/test-helpers.js';
3
+ import { ContexteBuilder } from '../../contexte.builder.js';
4
+ import { DpeNormalizerService } from '../../../../normalizer/domain/dpe-normalizer.service.js';
5
+ import { beforeEach, describe, expect, test, vi } from 'vitest';
6
+ import { DeperditionPontThermiqueService } from './deperdition-pont-thermique.service.js';
7
+ import { PontThermiqueTvStore } from '../../../../dpe/infrastructure/pontThermiqueTv.store.js';
8
+ import { DeperditionMurService } from '../mur/deperdition-mur.service.js';
9
+ import { DeperditionPlancherHautService } from '../plancher_haut/deperdition-plancher-haut.service.js';
10
+ import { DeperditionPlancherBasService } from '../plancher_bas/deperdition-plancher-bas.service.js';
11
+
12
+ /** @type {DeperditionPontThermiqueService} **/
13
+ let service;
14
+
15
+ /** @type {DeperditionMurService} **/
16
+ let deperditionMurService;
17
+
18
+ /** @type {DeperditionPlancherBasService} **/
19
+ let deperditionPlancherBasService;
20
+
21
+ /** @type {DeperditionPlancherHautService} **/
22
+ let deperditionPlancherHautService;
23
+
24
+ /** @type {DpeNormalizerService} **/
25
+ let normalizerService;
26
+
27
+ /** @type {PontThermiqueTvStore} **/
28
+ let tvStore;
29
+
30
+ /** @type {ContexteBuilder} **/
31
+ let contexteBuilder;
32
+
33
+ describe('Calcul de déperdition des ponts thermiques', () => {
34
+ beforeEach(() => {
35
+ tvStore = new PontThermiqueTvStore();
36
+ deperditionMurService = new DeperditionMurService();
37
+ deperditionPlancherBasService = new DeperditionPlancherBasService();
38
+ deperditionPlancherHautService = new DeperditionPlancherHautService();
39
+ service = new DeperditionPontThermiqueService(
40
+ tvStore,
41
+ deperditionMurService,
42
+ deperditionPlancherHautService,
43
+ deperditionPlancherBasService
44
+ );
45
+ normalizerService = new DpeNormalizerService();
46
+ contexteBuilder = new ContexteBuilder();
47
+ });
48
+
49
+ describe("Determination si un élément de l'enveloppe est concerné par un pont thermique", () => {
50
+ test.each([
51
+ {
52
+ label: 'Les Planchers hauts en structure légère sont négligés',
53
+ enumTypePlancherHaut: [9, 10],
54
+ expected: false
55
+ },
56
+ {
57
+ label: 'Les Planchers hauts en structure lourde sont impactés',
58
+ enumTypePlancherHaut: [1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 13, 14, 15, 16],
59
+ expected: true
60
+ }
61
+ ])('$label', ({ enumTypePlancherHaut, expected }) => {
62
+ enumTypePlancherHaut.forEach((typePlancherHaut) => {
63
+ expect(
64
+ service.plancherHautHasPontThermique({ enum_type_plancher_haut_id: typePlancherHaut })
65
+ ).toBe(expected);
66
+ });
67
+ });
68
+
69
+ test.each([
70
+ {
71
+ label: 'Les Planchers bas en structure légère sont négligés',
72
+ enumTypePlancherBas: [4, 10],
73
+ expected: false
74
+ },
75
+ {
76
+ label: 'Les Planchers bas en structure lourde sont impactés',
77
+ enumTypePlancherBas: [1, 2, 3, 5, 6, 7, 8, 9, 11, 12, 13],
78
+ expected: true
79
+ }
80
+ ])('$label', ({ enumTypePlancherBas, expected }) => {
81
+ enumTypePlancherBas.forEach((typePlancherBas) => {
82
+ expect(
83
+ service.plancherBasHasPontThermique({ enum_type_plancher_bas_id: typePlancherBas })
84
+ ).toBe(expected);
85
+ });
86
+ });
87
+
88
+ test.each([
89
+ {
90
+ label: 'Les murs avec adjacence sur une circulation sont négligés',
91
+ enumTypeAdjacenceId: [14, 15, 16, 17, 18, 22],
92
+ expected: false
93
+ },
94
+ {
95
+ label: 'Les murs avec adjacence autre que sur une circulation sont impactés',
96
+ enumTypeAdjacenceId: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 19, 20, 21],
97
+ expected: true
98
+ },
99
+ {
100
+ label: 'Les murs en matériaux léger pour les liaisons avec les planchers bas sont négligés',
101
+ typeLiaison: 1,
102
+ enumMateriauxStructureMurId: [5, 6, 7, 16, 18, 24, 25, 26, 27],
103
+ expected: false
104
+ },
105
+ {
106
+ label: 'Les murs en matériaux léger pour les liaisons avec les planchers bas sont impactés',
107
+ typeLiaison: 1,
108
+ enumMateriauxStructureMurId: [
109
+ 1, 2, 3, 4, 8, 9, 10, 11, 12, 13, 14, 15, 17, 19, 20, 21, 22, 23
110
+ ],
111
+ expected: true
112
+ },
113
+ {
114
+ label:
115
+ 'Les murs en matériaux léger pour les liaisons avec les planchers haut sont négligés',
116
+ typeLiaison: 3,
117
+ enumMateriauxStructureMurId: [5, 6, 7, 16, 18, 24, 25, 26, 27],
118
+ expected: false
119
+ },
120
+ {
121
+ label:
122
+ 'Les murs en matériaux léger pour les liaisons avec les planchers haut sont impactés',
123
+ typeLiaison: 3,
124
+ enumMateriauxStructureMurId: [
125
+ 1, 2, 3, 4, 8, 9, 10, 11, 12, 13, 14, 15, 17, 19, 20, 21, 22, 23
126
+ ],
127
+ expected: true
128
+ },
129
+ {
130
+ label: 'Les murs en structure bois pour les liaisons avec les menuiseries sont négligés',
131
+ typeLiaison: 4,
132
+ enumMateriauxStructureMurId: [5, 6, 7, 18, 24, 25, 26, 27],
133
+ expected: false
134
+ },
135
+ {
136
+ label:
137
+ 'Les murs en matériaux autres que structure bois pour les liaisons avec les menuiseries sont impactés',
138
+ typeLiaison: 4,
139
+ enumMateriauxStructureMurId: [
140
+ 1, 2, 3, 4, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 19, 20, 21, 22, 23
141
+ ],
142
+ expected: true
143
+ }
144
+ ])(
145
+ '$label',
146
+ ({
147
+ enumTypeAdjacenceId = undefined,
148
+ typeLiaison = undefined,
149
+ enumMateriauxStructureMurId = undefined,
150
+ expected
151
+ }) => {
152
+ if (enumTypeAdjacenceId) {
153
+ enumTypeAdjacenceId.forEach((typeAdjacenceId) => {
154
+ expect(
155
+ service.murHasPontThermique(
156
+ {
157
+ enum_type_adjacence_id: typeAdjacenceId,
158
+ enum_materiaux_structure_mur_id: enumMateriauxStructureMurId
159
+ },
160
+ typeLiaison
161
+ )
162
+ ).toBe(expected);
163
+ });
164
+ }
165
+ if (enumMateriauxStructureMurId) {
166
+ enumMateriauxStructureMurId.forEach((materiauxStructureMurId) => {
167
+ expect(
168
+ service.murHasPontThermique(
169
+ {
170
+ enum_type_adjacence_id: enumTypeAdjacenceId,
171
+ enum_materiaux_structure_mur_id: materiauxStructureMurId
172
+ },
173
+ typeLiaison
174
+ )
175
+ ).toBe(expected);
176
+ });
177
+ }
178
+ }
179
+ );
180
+ });
181
+
182
+ describe("Récupération des élements de l'enveloppe à partir des références", () => {
183
+ test('Cas des murs', () => {
184
+ let enveloppe = { mur_collection: {} };
185
+ expect(service.mur({}, enveloppe)).toBeUndefined();
186
+
187
+ enveloppe.mur_collection.mur = [];
188
+ expect(service.mur({}, enveloppe)).toBeUndefined();
189
+
190
+ const murDE = { reference: 'reference' };
191
+ enveloppe.mur_collection.mur = [{ donnee_entree: murDE }];
192
+
193
+ expect(service.mur({}, enveloppe)).toBeUndefined();
194
+ expect(service.mur({ reference_1: 'reference_1' }, enveloppe)).toBeUndefined();
195
+ expect(service.mur({ reference_1: 'reference' }, enveloppe)).toStrictEqual(murDE);
196
+ expect(service.mur({ reference_2: 'reference' }, enveloppe)).toStrictEqual(murDE);
197
+ });
198
+
199
+ test('Cas des plancher bas', () => {
200
+ let enveloppe = { plancher_bas_collection: {} };
201
+ expect(service.plancherBas({}, enveloppe)).toBeUndefined();
202
+
203
+ enveloppe.plancher_bas_collection.plancher_bas = [];
204
+ expect(service.plancherBas({}, enveloppe)).toBeUndefined();
205
+
206
+ const plancherBasDE = { reference: 'reference' };
207
+ enveloppe.plancher_bas_collection.plancher_bas = [{ donnee_entree: plancherBasDE }];
208
+
209
+ expect(service.plancherBas({}, enveloppe)).toBeUndefined();
210
+ expect(service.plancherBas({ reference_1: 'reference_1' }, enveloppe)).toBeUndefined();
211
+ expect(service.plancherBas({ reference_1: 'reference' }, enveloppe)).toStrictEqual(
212
+ plancherBasDE
213
+ );
214
+ expect(service.plancherBas({ reference_2: 'reference' }, enveloppe)).toStrictEqual(
215
+ plancherBasDE
216
+ );
217
+ });
218
+
219
+ test('Cas des plancher haut', () => {
220
+ let enveloppe = { plancher_haut_collection: {} };
221
+ expect(service.plancherHaut({}, enveloppe)).toBeUndefined();
222
+
223
+ enveloppe.plancher_haut_collection.plancher_haut = [];
224
+ expect(service.plancherHaut({}, enveloppe)).toBeUndefined();
225
+
226
+ const plancherHautDE = { reference: 'reference' };
227
+ enveloppe.plancher_haut_collection.plancher_haut = [{ donnee_entree: plancherHautDE }];
228
+
229
+ expect(service.plancherHaut({}, enveloppe)).toBeUndefined();
230
+ expect(service.plancherHaut({ reference_1: 'reference_1' }, enveloppe)).toBeUndefined();
231
+ expect(service.plancherHaut({ reference_1: 'reference' }, enveloppe)).toStrictEqual(
232
+ plancherHautDE
233
+ );
234
+ expect(service.plancherHaut({ reference_2: 'reference' }, enveloppe)).toStrictEqual(
235
+ plancherHautDE
236
+ );
237
+ });
238
+
239
+ test('Cas des plancher menuiseries', () => {
240
+ let enveloppe = { baie_vitree_collection: {}, porte_collection: {} };
241
+ expect(service.menuiserie({}, enveloppe)).toBeUndefined();
242
+
243
+ enveloppe.baie_vitree_collection.baie_vitree = [];
244
+ enveloppe.porte_collection.porte = [];
245
+ expect(service.menuiserie({}, enveloppe)).toBeUndefined();
246
+
247
+ const menuiserieDE = { reference: 'reference' };
248
+ enveloppe.baie_vitree_collection.baie_vitree = [{ donnee_entree: menuiserieDE }];
249
+
250
+ expect(service.menuiserie({}, enveloppe)).toBeUndefined();
251
+ expect(service.menuiserie({ reference_1: 'reference_1' }, enveloppe)).toBeUndefined();
252
+ expect(service.menuiserie({ reference_1: 'reference' }, enveloppe)).toStrictEqual(
253
+ menuiserieDE
254
+ );
255
+ expect(service.menuiserie({ reference_2: 'reference' }, enveloppe)).toStrictEqual(
256
+ menuiserieDE
257
+ );
258
+
259
+ enveloppe.baie_vitree_collection.baie_vitree = [];
260
+ enveloppe.porte_collection.porte = [{ donnee_entree: menuiserieDE }];
261
+
262
+ expect(service.menuiserie({}, enveloppe)).toBeUndefined();
263
+ expect(service.menuiserie({ reference_1: 'reference_1' }, enveloppe)).toBeUndefined();
264
+ expect(service.menuiserie({ reference_1: 'reference' }, enveloppe)).toStrictEqual(
265
+ menuiserieDE
266
+ );
267
+ expect(service.menuiserie({ reference_2: 'reference' }, enveloppe)).toStrictEqual(
268
+ menuiserieDE
269
+ );
270
+
271
+ enveloppe.baie_vitree_collection.baie_vitree = [{ donnee_entree: menuiserieDE }];
272
+ expect(service.menuiserie({ reference_2: 'reference' }, enveloppe)).toStrictEqual(
273
+ menuiserieDE
274
+ );
275
+ });
276
+ });
277
+
278
+ describe('Calcul du pont thermique de type plancher bas / mur', () => {
279
+ test('Aucun plancher bas trouvé, valeur par défaut issue de tv_pont_thermique_id', () => {
280
+ vi.spyOn(tvStore, 'getKForMurById').mockReturnValue(0.75);
281
+ vi.spyOn(tvStore, 'getKForPlancher').mockReturnValue(0.25);
282
+
283
+ expect(service.pontThermiquePlancherBasMur({}, { tv_pont_thermique_id: 1 }, {}, 3)).toBe(
284
+ 0.75
285
+ );
286
+ expect(tvStore.getKForMurById).toHaveBeenCalledWith(1);
287
+ expect(tvStore.getKForPlancher).not.toHaveBeenCalled();
288
+ });
289
+
290
+ test('Plancher bas non concerné par le pont thermique', () => {
291
+ vi.spyOn(tvStore, 'getKForMurById').mockReturnValue(0.75);
292
+ vi.spyOn(tvStore, 'getKForPlancher').mockReturnValue(0.25);
293
+
294
+ const pontThermiqueDE = { reference_1: 'reference' };
295
+ const enveloppe = {
296
+ plancher_bas_collection: {
297
+ plancher_bas: [
298
+ { donnee_entree: { enum_type_plancher_bas_id: 4, reference: 'reference' } }
299
+ ]
300
+ }
301
+ };
302
+ expect(service.pontThermiquePlancherBasMur({}, pontThermiqueDE, enveloppe, 3)).toBe(0);
303
+ expect(tvStore.getKForMurById).not.toHaveBeenCalled();
304
+ expect(tvStore.getKForPlancher).not.toHaveBeenCalled();
305
+ });
306
+
307
+ test('Utilisation des tables de valeurs pour calculer le pont thermique', () => {
308
+ vi.spyOn(tvStore, 'getKForMurById').mockReturnValue(0.75);
309
+ vi.spyOn(tvStore, 'getKForPlancher').mockReturnValue(0.25);
310
+
311
+ const pontThermiqueDE = { reference_1: 'reference' };
312
+ const enveloppe = {
313
+ plancher_bas_collection: {
314
+ plancher_bas: [{ donnee_entree: { reference: 'reference', enum_type_isolation_id: 5 } }]
315
+ }
316
+ };
317
+ expect(service.pontThermiquePlancherBasMur({}, pontThermiqueDE, enveloppe, 3)).toBe(0.25);
318
+ expect(tvStore.getKForMurById).not.toHaveBeenCalled();
319
+ expect(tvStore.getKForPlancher).toHaveBeenCalledWith(1, 'iti', 'itr');
320
+ });
321
+ });
322
+
323
+ describe('Calcul du pont thermique de type plancher haut / mur', () => {
324
+ test('Aucun plancher haut trouvé, valeur par défaut issue de tv_pont_thermique_id', () => {
325
+ vi.spyOn(tvStore, 'getKForMurById').mockReturnValue(0.75);
326
+ vi.spyOn(tvStore, 'getKForPlancher').mockReturnValue(0.25);
327
+
328
+ expect(service.pontThermiquePlancherHautMur({}, { tv_pont_thermique_id: 1 }, {}, 3)).toBe(
329
+ 0.75
330
+ );
331
+ expect(tvStore.getKForMurById).toHaveBeenCalledWith(1);
332
+ expect(tvStore.getKForPlancher).not.toHaveBeenCalled();
333
+ });
334
+
335
+ test('Plancher haut non concerné par le pont thermique', () => {
336
+ vi.spyOn(tvStore, 'getKForMurById').mockReturnValue(0.75);
337
+ vi.spyOn(tvStore, 'getKForPlancher').mockReturnValue(0.25);
338
+
339
+ const pontThermiqueDE = { reference_1: 'reference' };
340
+ const enveloppe = {
341
+ plancher_haut_collection: {
342
+ plancher_haut: [
343
+ { donnee_entree: { enum_type_plancher_haut_id: 9, reference: 'reference' } }
344
+ ]
345
+ }
346
+ };
347
+ expect(service.pontThermiquePlancherHautMur({}, pontThermiqueDE, enveloppe, 3)).toBe(0);
348
+ expect(tvStore.getKForMurById).not.toHaveBeenCalled();
349
+ expect(tvStore.getKForPlancher).not.toHaveBeenCalled();
350
+ });
351
+
352
+ test('Utilisation des tables de valeurs pour calculer le pont thermique', () => {
353
+ vi.spyOn(tvStore, 'getKForMurById').mockReturnValue(0.75);
354
+ vi.spyOn(tvStore, 'getKForPlancher').mockReturnValue(0.25);
355
+
356
+ const pontThermiqueDE = { reference_1: 'reference' };
357
+ const enveloppe = {
358
+ plancher_haut_collection: {
359
+ plancher_haut: [{ donnee_entree: { reference: 'reference', enum_type_isolation_id: 5 } }]
360
+ }
361
+ };
362
+ expect(service.pontThermiquePlancherHautMur({}, pontThermiqueDE, enveloppe, 3)).toBe(0.25);
363
+ expect(tvStore.getKForMurById).not.toHaveBeenCalled();
364
+ expect(tvStore.getKForPlancher).toHaveBeenCalledWith(3, 'iti', 'itr');
365
+ });
366
+ });
367
+
368
+ describe('Calcul du pont thermique de type menuiserie / mur', () => {
369
+ test('Aucune menuiserie trouvée, valeur par défaut issue de tv_pont_thermique_id', () => {
370
+ vi.spyOn(tvStore, 'getKForMurById').mockReturnValue(0.75);
371
+ vi.spyOn(tvStore, 'getKForMenuiserie').mockReturnValue(0.25);
372
+
373
+ expect(service.pontThermiqueMenuiserieMur({ tv_pont_thermique_id: 1 }, {}, 3)).toBe(0.75);
374
+ expect(tvStore.getKForMurById).toHaveBeenCalledWith(1);
375
+ expect(tvStore.getKForMenuiserie).not.toHaveBeenCalled();
376
+ });
377
+
378
+ test('Utilisation des tables de valeurs pour calculer le pont thermique', () => {
379
+ vi.spyOn(tvStore, 'getKForMurById').mockReturnValue(0.75);
380
+ vi.spyOn(tvStore, 'getKForMenuiserie').mockReturnValue(0.25);
381
+
382
+ const pontThermiqueDE = { reference_1: 'reference' };
383
+ const enveloppe = {
384
+ baie_vitree_collection: {
385
+ baie_vitree: [
386
+ {
387
+ donnee_entree: {
388
+ reference: 'reference',
389
+ enum_type_pose_id: 5,
390
+ largeur_dormant: 5,
391
+ presence_retour_isolation: 0
392
+ }
393
+ }
394
+ ]
395
+ }
396
+ };
397
+ expect(service.pontThermiqueMenuiserieMur(pontThermiqueDE, enveloppe, 3)).toBe(0.25);
398
+ expect(tvStore.getKForMurById).not.toHaveBeenCalled();
399
+ expect(tvStore.getKForMenuiserie).toHaveBeenCalledWith(5, 'iti', 5, 0, 5);
400
+ });
401
+
402
+ test("Utilisation du type de pose par défaut 'tunnel' pour calculer le pont thermique", () => {
403
+ vi.spyOn(tvStore, 'getKForMurById').mockReturnValue(0.75);
404
+ vi.spyOn(tvStore, 'getKForMenuiserie').mockReturnValue(0.25);
405
+
406
+ const pontThermiqueDE = { reference_1: 'reference' };
407
+ const enveloppe = {
408
+ baie_vitree_collection: {
409
+ baie_vitree: [
410
+ {
411
+ donnee_entree: {
412
+ reference: 'reference',
413
+ largeur_dormant: 5,
414
+ presence_retour_isolation: 0
415
+ }
416
+ }
417
+ ]
418
+ }
419
+ };
420
+ expect(service.pontThermiqueMenuiserieMur(pontThermiqueDE, enveloppe, 3)).toBe(0.25);
421
+ expect(tvStore.getKForMurById).not.toHaveBeenCalled();
422
+ expect(tvStore.getKForMenuiserie).toHaveBeenCalledWith(5, 'iti', 3, 0, 5);
423
+ });
424
+ });
425
+
426
+ describe("Calcul de l'isolation du mur", () => {
427
+ test('Utilisation du service deperditionMurService', () => {
428
+ vi.spyOn(deperditionMurService, 'typeIsolation').mockReturnValue(6);
429
+
430
+ /**
431
+ * @type {Contexte}
432
+ */
433
+ const ctx = {
434
+ enumPeriodeConstructionId: 1
435
+ };
436
+ /**
437
+ * @type {MurDE}
438
+ */
439
+ const murDE = {
440
+ enum_type_adjacence_id: 1
441
+ };
442
+
443
+ expect(service.isolationMur(ctx, murDE)).toBe(6);
444
+ expect(deperditionMurService.typeIsolation).toHaveBeenCalledWith(ctx, murDE);
445
+ });
446
+
447
+ test('Isolation ITI si pas possible de définir le mur', () => {
448
+ vi.spyOn(deperditionMurService, 'typeIsolation').mockReturnValue(6);
449
+
450
+ expect(service.isolationMur({}, undefined)).toBe(3);
451
+ expect(deperditionMurService.typeIsolation).not.toHaveBeenCalled();
452
+ });
453
+ });
454
+
455
+ describe('Calcul du facteur k du pont thermique', () => {
456
+ test('Utilisation de k_saisi', () => {
457
+ vi.spyOn(tvStore, 'getKForMurById').mockReturnValue(0.75);
458
+
459
+ expect(
460
+ service.execute({}, {}, { k_saisi: 0.6, enum_methode_saisie_pont_thermique_id: 2 }, 3)
461
+ ).toStrictEqual({ k: 0.6 });
462
+ expect(
463
+ service.execute({}, {}, { k_saisi: 0.6, enum_methode_saisie_pont_thermique_id: 3 }, 3)
464
+ ).toStrictEqual({ k: 0.6 });
465
+ expect(tvStore.getKForMurById).not.toHaveBeenCalled();
466
+ });
467
+
468
+ test('Utilisation de la valeur par défaut si pas de reference_1', () => {
469
+ vi.spyOn(tvStore, 'getKForMurById').mockReturnValue(0.75);
470
+
471
+ const pontThermiqueDE = { tv_pont_thermique_id: 1, enum_methode_saisie_pont_thermique_id: 4 };
472
+ expect(service.execute({}, {}, pontThermiqueDE)).toStrictEqual({ k: 0.75 });
473
+ expect(tvStore.getKForMurById).toHaveBeenCalledWith(1);
474
+ });
475
+
476
+ test("Utilisation de la valeur par défaut si la valeur k n'est pas trouvée", () => {
477
+ vi.spyOn(tvStore, 'getKForMurById').mockReturnValue(0.75);
478
+
479
+ expect(
480
+ service.execute(
481
+ {},
482
+ {},
483
+ { k_saisi: undefined, enum_methode_saisie_pont_thermique_id: 2, tv_pont_thermique_id: 1 },
484
+ 3
485
+ )
486
+ ).toStrictEqual({ k: 0.75 });
487
+
488
+ expect(tvStore.getKForMurById).toHaveBeenCalledWith(1);
489
+ });
490
+
491
+ test("0 si le mur n'est pas concerné par les déperditions pont thermique", () => {
492
+ vi.spyOn(tvStore, 'getKForMurById').mockReturnValue(0.75);
493
+
494
+ const pontThermiqueDE = {
495
+ reference_1: 'reference',
496
+ tv_pont_thermique_id: 1,
497
+ enum_methode_saisie_pont_thermique_id: 4
498
+ };
499
+ const enveloppe = {
500
+ mur_collection: {
501
+ mur: [{ donnee_entree: { reference: 'reference', enum_type_adjacence_id: 14 } }]
502
+ }
503
+ };
504
+
505
+ expect(service.execute({}, enveloppe, pontThermiqueDE)).toStrictEqual({ k: 0 });
506
+ expect(tvStore.getKForMurById).not.toHaveBeenCalled();
507
+ });
508
+
509
+ test('Utilisation de getKForMur pour les refend ou plancher intermédiaire', () => {
510
+ vi.spyOn(tvStore, 'getKForMur').mockReturnValue(0.75);
511
+
512
+ const pontThermiqueDE = {
513
+ reference_1: 'reference',
514
+ tv_pont_thermique_id: 1,
515
+ enum_type_liaison_id: 2,
516
+ enum_type_adjacence_id: 8,
517
+ enum_methode_saisie_pont_thermique_id: 4
518
+ };
519
+ expect(service.execute({}, {}, pontThermiqueDE)).toStrictEqual({ k: 0.75 });
520
+ expect(tvStore.getKForMur).toHaveBeenCalledWith(2, 'iti');
521
+
522
+ pontThermiqueDE.enum_type_liaison_id = 4;
523
+ expect(service.execute({}, {}, pontThermiqueDE)).toStrictEqual({ k: 0.75 });
524
+ expect(tvStore.getKForMur).toHaveBeenCalledWith(2, 'iti');
525
+ });
526
+
527
+ test('Utilisation de getKForPlancher pour un plancher bas', () => {
528
+ vi.spyOn(tvStore, 'getKForPlancher').mockReturnValue(0.35);
529
+ vi.spyOn(deperditionPlancherBasService, 'typeIsolation').mockReturnValue(3);
530
+
531
+ const pontThermiqueDE = {
532
+ reference_1: 'reference',
533
+ tv_pont_thermique_id: 1,
534
+ enum_type_liaison_id: 1,
535
+ enum_materiaux_structure_mur_id: 3,
536
+ enum_methode_saisie_pont_thermique_id: 4
537
+ };
538
+
539
+ const plancherBasDE = { reference: 'reference', enum_type_plancher_bas_id: 1 };
540
+
541
+ const enveloppe = {
542
+ plancher_bas_collection: { plancher_bas: [{ donnee_entree: plancherBasDE }] }
543
+ };
544
+ expect(service.execute({}, enveloppe, pontThermiqueDE)).toStrictEqual({ k: 0.35 });
545
+ expect(deperditionPlancherBasService.typeIsolation).toHaveBeenCalledWith({}, plancherBasDE);
546
+ expect(tvStore.getKForPlancher).toHaveBeenCalledWith(1, 'iti', 'iti');
547
+ });
548
+
549
+ test('Utilisation de getKForPlancher pour un plancher haut', () => {
550
+ vi.spyOn(tvStore, 'getKForPlancher').mockReturnValue(0.35);
551
+ vi.spyOn(deperditionPlancherHautService, 'typeIsolation').mockReturnValue(3);
552
+
553
+ const pontThermiqueDE = {
554
+ reference_1: 'reference',
555
+ tv_pont_thermique_id: 1,
556
+ enum_type_liaison_id: 3,
557
+ enum_materiaux_structure_mur_id: 3,
558
+ enum_methode_saisie_pont_thermique_id: 4
559
+ };
560
+
561
+ const plancherHautDE = { reference: 'reference', enum_type_plancher_haut_id: 1 };
562
+
563
+ const enveloppe = {
564
+ plancher_haut_collection: { plancher_haut: [{ donnee_entree: plancherHautDE }] }
565
+ };
566
+ expect(service.execute({}, enveloppe, pontThermiqueDE)).toStrictEqual({ k: 0.35 });
567
+ expect(deperditionPlancherHautService.typeIsolation).toHaveBeenCalledWith({}, plancherHautDE);
568
+ expect(tvStore.getKForPlancher).toHaveBeenCalledWith(3, 'iti', 'iti');
569
+ });
570
+
571
+ test('Utilisation de getKForMenuiserie pour une menuiserie', () => {
572
+ vi.spyOn(tvStore, 'getKForMenuiserie').mockReturnValue(0.35);
573
+
574
+ const pontThermiqueDE = {
575
+ reference_1: 'reference',
576
+ tv_pont_thermique_id: 1,
577
+ enum_type_liaison_id: 5,
578
+ enum_materiaux_structure_mur_id: 3,
579
+ enum_methode_saisie_pont_thermique_id: 4
580
+ };
581
+
582
+ const porteDE = {
583
+ reference: 'reference',
584
+ enum_type_plancher_haut_id: 1,
585
+ largeur_dormant: 5,
586
+ presence_retour_isolation: 0
587
+ };
588
+
589
+ const enveloppe = { porte_collection: { porte: [{ donnee_entree: porteDE }] } };
590
+ expect(service.execute({}, enveloppe, pontThermiqueDE)).toStrictEqual({ k: 0.35 });
591
+ expect(tvStore.getKForMenuiserie).toHaveBeenCalledWith(5, 'iti', 3, 0, 5);
592
+ });
593
+
594
+ test("Utilisation de getKForMenuiserie avec type de pose 3 pour une menuiserie avec une pose 'sans objet'", () => {
595
+ vi.spyOn(tvStore, 'getKForMenuiserie').mockReturnValue(0.35);
596
+
597
+ const pontThermiqueDE = {
598
+ reference_1: 'reference',
599
+ tv_pont_thermique_id: 1,
600
+ enum_type_liaison_id: 5,
601
+ enum_materiaux_structure_mur_id: 3,
602
+ enum_methode_saisie_pont_thermique_id: 4
603
+ };
604
+
605
+ const porteDE = {
606
+ reference: 'reference',
607
+ enum_type_plancher_haut_id: 1,
608
+ enum_type_pose_id: 4,
609
+ largeur_dormant: 5,
610
+ presence_retour_isolation: 0
611
+ };
612
+
613
+ const enveloppe = { porte_collection: { porte: [{ donnee_entree: porteDE }] } };
614
+ expect(service.execute({}, enveloppe, pontThermiqueDE)).toStrictEqual({ k: 0.35 });
615
+ expect(tvStore.getKForMenuiserie).toHaveBeenCalledWith(5, 'iti', 3, 0, 5);
616
+ });
617
+ });
618
+
619
+ describe("Test d'intégration des ponts thermiques", () => {
620
+ test.each(corpus)('vérification des DI des ponts thermiques pour dpe %s', (ademeId) => {
621
+ let dpeRequest = getAdemeFileJson(ademeId);
622
+ dpeRequest = normalizerService.normalize(dpeRequest);
623
+
624
+ /** @type {Contexte} */
625
+ const ctx = contexteBuilder.fromDpe(dpeRequest);
626
+
627
+ const pontsThermiques =
628
+ dpeRequest.logement.enveloppe.pont_thermique_collection?.pont_thermique || [];
629
+
630
+ pontsThermiques.forEach((pontThermique) => {
631
+ const di = service.execute(ctx, dpeRequest.logement.enveloppe, pontThermique.donnee_entree);
632
+ expect(di.k).toBeCloseTo(pontThermique.donnee_intermediaire.k, 2);
633
+ });
634
+ });
635
+ });
636
+ });