diff --git a/src/3.2.1_mur.js b/src/3.2.1_mur.js index 525bf58..a490a5a 100644 --- a/src/3.2.1_mur.js +++ b/src/3.2.1_mur.js @@ -166,8 +166,17 @@ function calc_umur0(di, de, du) { } } - // Si présence d'un doublage - if (type_doublage > 2) { + /** + * Le doublage NE doit PAS être cumulé à une isolation ITE ou ITI. + * Il doit uniquement être pris en compte en l'absence d'isolation ITE/ITI (ex: ITR seule, non isolé, inconnu). + * Types avec ITE ou ITI : 3 (iti), 4 (ite), 6 (iti+ite), 7 (iti+itr), 8 (ite+itr) + * @see https://github.com/Open3CL/engine/issues/146 + */ + const type_isolation = parseInt(de.enum_type_isolation_id) || 1; + const hasIteOrIti = [3, 4, 6, 7, 8].includes(type_isolation); + + // Si présence d'un doublage et pas d'isolation ITE/ITI + if (type_doublage > 2 && !hasIteOrIti) { let umur0Doublage; // 3 - doublage indéterminé ou lame d'air inf 15 mm diff --git a/src/3.2.1_mur.spec.js b/src/3.2.1_mur.spec.js index 2452d18..253a8d8 100644 --- a/src/3.2.1_mur.spec.js +++ b/src/3.2.1_mur.spec.js @@ -44,4 +44,102 @@ describe('Recherche de bugs dans le calcul de déperdition des murs', () => { expect(mur.donnee_intermediaire.umur).toBe(2.5); expect(mur.donnee_intermediaire.umur0).toBe(2.5); }); + + /** + * @see https://github.com/Open3CL/engine/issues/146 + * Le doublage NE doit PAS être cumulé à une isolation ITE ou ITI. + */ + describe('[MURS] Doublage non cumulé à une isolation ITE/ITI (#146)', () => { + const baseDE = { + enum_type_adjacence_id: '1', // Paroi sur l'extérieur (b=1) + enum_materiaux_structure_mur_id: '11', // Béton ≤20 cm + epaisseur_structure: 20, + enum_methode_saisie_u0_id: '2', + paroi_ancienne: 0 + }; + + test('doublage avec ITI : le doublage ne doit pas être pris en compte dans Umur0', () => { + const zc = 3; // H2a + const pc_id = 6; + const ej = 0; + // Mur béton 20 cm (umur0 ~ 2.5), avec doublage connu (type 5) ET isolation ITI (type 3) + const mur = { + donnee_entree: { + ...baseDE, + description: 'Mur béton avec doublage et ITI', + enum_methode_saisie_u_id: '3', // épaisseur isolation saisie + epaisseur_isolation: 10, // 10 cm + enum_type_doublage_id: '5', // doublage connu (plâtre brique bois) + enum_type_isolation_id: '3' // ITI + }, + donnee_intermediaire: {} + }; + calc_mur(mur, zc, pc_id, ej); + + // Sans doublage cumulé, umur0 = 2.5 (valeur brute du mur béton ≤20cm) + // Avec doublage cumulé à tort : umur0 = 1 / (1/2.5 + 0.21) ≈ 1.724 + expect(mur.donnee_intermediaire.umur0).toBeCloseTo(2.5, 2); + }); + + test('doublage avec ITE : le doublage ne doit pas être pris en compte dans Umur0', () => { + const zc = 3; + const pc_id = 6; + const ej = 0; + const mur = { + donnee_entree: { + ...baseDE, + description: 'Mur béton avec doublage et ITE', + enum_methode_saisie_u_id: '3', + epaisseur_isolation: 8, + enum_type_doublage_id: '4', // doublage indéterminé lame d'air sup 15mm + enum_type_isolation_id: '4' // ITE + }, + donnee_intermediaire: {} + }; + calc_mur(mur, zc, pc_id, ej); + + // umur0 = 2.5 (béton ≤20cm, doublage ignoré car ITE présent) + expect(mur.donnee_intermediaire.umur0).toBeCloseTo(2.5, 2); + }); + + test('doublage avec ITR seule : le doublage DOIT être pris en compte dans Umur0', () => { + const zc = 3; + const pc_id = 6; + const ej = 0; + const mur = { + donnee_entree: { + ...baseDE, + description: 'Mur béton avec doublage et ITR', + enum_methode_saisie_u_id: '1', // non isolé + enum_type_doublage_id: '5', // doublage connu + enum_type_isolation_id: '5' // ITR + }, + donnee_intermediaire: {} + }; + calc_mur(mur, zc, pc_id, ej); + + // ITR seule → le doublage est pris en compte : umur0 < 2.5 + expect(mur.donnee_intermediaire.umur0).toBeLessThan(2.5); + }); + + test('doublage sans isolation : le doublage DOIT être pris en compte dans Umur0', () => { + const zc = 3; + const pc_id = 6; + const ej = 0; + const mur = { + donnee_entree: { + ...baseDE, + description: 'Mur béton avec doublage sans isolation', + enum_methode_saisie_u_id: '1', // non isolé + enum_type_doublage_id: '5', + enum_type_isolation_id: '2' // non isolé + }, + donnee_intermediaire: {} + }; + calc_mur(mur, zc, pc_id, ej); + + // Non isolé → doublage pris en compte : umur0 < umur0_nu_brut (le doublage réduit bien la valeur) + expect(mur.donnee_intermediaire.umur0).toBeLessThan(2.5); + }); + }); }); diff --git a/src/features/engine/domain/enveloppe/mur/deperdition-mur.service.js b/src/features/engine/domain/enveloppe/mur/deperdition-mur.service.js index a03a1d3..61c1716 100755 --- a/src/features/engine/domain/enveloppe/mur/deperdition-mur.service.js +++ b/src/features/engine/domain/enveloppe/mur/deperdition-mur.service.js @@ -129,20 +129,29 @@ export class DeperditionMurService extends DeperditionService { } /** - * Pour l’ensemble des parois, la présence d’un doublage apporte une résistance thermique supplémentaire + * Pour l’ensemble des parois, la présence d’un doublage apporte une résistance thermique supplémentaire. + * Cependant, lorsqu'une isolation ITE ou ITI est présente, le doublage NE doit PAS être cumulé. + * Le doublage n'est pris en compte que si aucune isolation ITE/ITI n'est appliquée. + * Types d'isolation avec ITE ou ITI : 3 (iti), 4 (ite), 6 (iti+ite), 7 (iti+itr), 8 (ite+itr) + * @see https://github.com/Open3CL/engine/issues/146 */ - switch (murDE.enum_type_doublage_id) { - case '3': - // doublage indéterminé ou lame d'air inf 15 mm - umur0 = 1 / (1 / umur0 + 0.1); - break; - case '4': // doublage indéterminé ou lame d'air sup 15 mm - case '5': // doublage connu (plâtre brique bois) - umur0 = 1 / (1 / umur0 + 0.21); - break; - default: - // absence de doublage ou inconnu - break; + const typeIsolation = parseInt(murDE.enum_type_isolation_id) || 1; + const hasIteOrIti = [3, 4, 6, 7, 8].includes(typeIsolation); + + if (!hasIteOrIti) { + switch (murDE.enum_type_doublage_id) { + case '3': + // doublage indéterminé ou lame d'air inf 15 mm + umur0 = 1 / (1 / umur0 + 0.1); + break; + case '4': // doublage indéterminé ou lame d'air sup 15 mm + case '5': // doublage connu (plâtre brique bois) + umur0 = 1 / (1 / umur0 + 0.21); + break; + default: + // absence de doublage ou inconnu + break; + } } /**