@open3cl/engine 1.0.0
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.js +76 -0
- package/10_clim.js +45 -0
- package/11_besoin_ecs.js +25 -0
- package/11_ecs.js +95 -0
- package/11_nadeq.js +87 -0
- package/11_nadeq.spec.js +55 -0
- package/12.4_pac.js +54 -0
- package/13.2_generateur_combustion.js +295 -0
- package/13.2_generateur_combustion_bouilleur.js +173 -0
- package/13.2_generateur_combustion_ch.js +195 -0
- package/13.2_generateur_combustion_chaudiere.js +151 -0
- package/13.2_generateur_pac.js +36 -0
- package/13_rendement_distribution_ecs.js +12 -0
- package/14_generateur_ecs.js +388 -0
- package/15_conso_aux.js +257 -0
- package/16.2_production_enr.js +328 -0
- package/16.2_production_enr.spec.js +251 -0
- package/16_conso_eclairage.js +37 -0
- package/2021_04_13_confort_ete.js +61 -0
- package/2021_04_13_qualite_isolation.js +174 -0
- package/3.1_b.js +141 -0
- package/3.2.1_mur.js +331 -0
- package/3.2.1_mur.spec.js +46 -0
- package/3.2.2_plancher_bas.js +259 -0
- package/3.2.2_plancher_bas.spec.js +88 -0
- package/3.2.3_plancher_haut.js +158 -0
- package/3.3.1.4_porte.js +32 -0
- package/3.3_baie_vitree.js +308 -0
- package/3.3_baie_vitree.spec.js +333 -0
- package/3.4_pont_thermique.js +463 -0
- package/3_deperdition.js +258 -0
- package/4_ventilation.js +197 -0
- package/5_conso_ventilation.js +127 -0
- package/6.1_apport_gratuit.js +61 -0
- package/6.1_apport_gratuit.spec.js +181 -0
- package/6.2_surface_sud_equivalente.js +109 -0
- package/7_inertie.js +178 -0
- package/7_inertie.spec.js +263 -0
- package/8_intermittence.js +5 -0
- package/9_besoin_ch.js +198 -0
- package/9_chauffage.js +291 -0
- package/9_chauffage.spec.js +101 -0
- package/9_conso_ch.js +95 -0
- package/9_conso_ch.spec.js +255 -0
- package/9_emetteur_ch.js +122 -0
- package/9_generateur_ch.js +230 -0
- package/9_generateur_ch.spec.js +87 -0
- package/README.md +43 -0
- package/apport_et_besoin.js +55 -0
- package/conso.js +529 -0
- package/conso.spec.js +90 -0
- package/core/assets/domain/add-additionnal-ue-values-tables.js +57 -0
- package/core/assets/domain/synchronize-assets.js +29 -0
- package/core/assets/domain/synchronize-assets.spec.js +37 -0
- package/core/assets/domain/synchronize-c1-tables.js +61 -0
- package/core/assets/domain/synchronize-c1-tables.spec.js +35 -0
- package/core/assets/domain/synchronize-dpe-ges-limit-values-tables.js +73 -0
- package/core/assets/domain/synchronize-dpe-ges-limit-values-tables.spec.js +72 -0
- package/core/assets/domain/synchronize-enum-tables.js +77 -0
- package/core/assets/domain/synchronize-enum-tables.spec.js +31 -0
- package/core/assets/domain/synchronize-solicitations-tables.js +72 -0
- package/core/assets/domain/synchronize-solicitations-tables.spec.js +47 -0
- package/core/assets/domain/synchronize-valeur-tables.js +146 -0
- package/core/assets/domain/synchronize-valeur-tables.spec.js +54 -0
- package/core/conf/infrastructure/application.config.js +33 -0
- package/core/file/infrastructure/adapter/file.store.js +75 -0
- package/core/file/infrastructure/adapter/file.store.spec.js +30 -0
- package/core/tv/infrastructure/assets/additional-ue-values.js +69 -0
- package/core/tv/infrastructure/tvs.store.js +40 -0
- package/core/tv/infrastructure/tvs.store.spec.js +34 -0
- package/core/util/infrastructure/object-util.js +23 -0
- package/core/util/infrastructure/object-util.spec.js +25 -0
- package/engine.js +503 -0
- package/enums.js +1155 -0
- package/ficheTechnique.js +86 -0
- package/ficheTechnique.spec.js +181 -0
- package/index.js +4 -0
- package/package.json +87 -0
- package/tv/18.2_sollicitations_ext.ods +0 -0
- package/tv/18.5_c1.ods +0 -0
- package/tv/dpe_ges_limit_values.ods +0 -0
- package/tv.js +80811 -0
- package/tvs.d.ts +7 -0
- package/utils.js +500 -0
- package/utils.spec.js +36 -0
package/conso.spec.js
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import calc_conso from './conso.js';
|
|
2
|
+
|
|
3
|
+
describe('Recherche de bugs dans le calcul de la consommation', () => {
|
|
4
|
+
test('calcul de la consommation de chauffage pour 2475E2510509B', () => {
|
|
5
|
+
const Sh = 22.76; // Surface habitable
|
|
6
|
+
const zc_id = 1; // Zone climatique
|
|
7
|
+
const ca_id = 1; // Classe d'altitude
|
|
8
|
+
const vt = [];
|
|
9
|
+
const ch = [
|
|
10
|
+
{
|
|
11
|
+
donnee_entree: {
|
|
12
|
+
description:
|
|
13
|
+
'Convecteur électrique NFC, NF** et NF*** avec programmateur pièce par pièce (système individuel)',
|
|
14
|
+
reference: '2024_07_11_09_30_44_722898200737262',
|
|
15
|
+
surface_chauffee: 22.76,
|
|
16
|
+
rdim: 1,
|
|
17
|
+
nombre_niveau_installation_ch: 1,
|
|
18
|
+
enum_cfg_installation_ch_id: '1',
|
|
19
|
+
enum_type_installation_id: '1',
|
|
20
|
+
enum_methode_calcul_conso_id: '1'
|
|
21
|
+
},
|
|
22
|
+
emetteur_chauffage_collection: {
|
|
23
|
+
emetteur_chauffage: [
|
|
24
|
+
{
|
|
25
|
+
donnee_entree: {
|
|
26
|
+
description: '',
|
|
27
|
+
reference: 'Emetteur:2024_07_11_09_30_44_722898200737262#1',
|
|
28
|
+
surface_chauffee: 22.76,
|
|
29
|
+
tv_rendement_emission_id: 1,
|
|
30
|
+
tv_rendement_distribution_ch_id: 1,
|
|
31
|
+
tv_rendement_regulation_id: 1,
|
|
32
|
+
enum_type_emission_distribution_id: '1',
|
|
33
|
+
tv_intermittence_id: 138,
|
|
34
|
+
reseau_distribution_isole: 0,
|
|
35
|
+
enum_equipement_intermittence_id: '4',
|
|
36
|
+
enum_type_regulation_id: '2',
|
|
37
|
+
enum_periode_installation_emetteur_id: '1',
|
|
38
|
+
enum_type_chauffage_id: '1',
|
|
39
|
+
enum_temp_distribution_ch_id: '1',
|
|
40
|
+
enum_lien_generateur_emetteur_id: '1'
|
|
41
|
+
},
|
|
42
|
+
donnee_intermediaire: {
|
|
43
|
+
rendement_distribution: 1,
|
|
44
|
+
rendement_emission: 0.95,
|
|
45
|
+
rendement_regulation: 0.99,
|
|
46
|
+
i0: 0.86
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
]
|
|
50
|
+
},
|
|
51
|
+
generateur_chauffage_collection: {
|
|
52
|
+
generateur_chauffage: [
|
|
53
|
+
{
|
|
54
|
+
donnee_entree: {
|
|
55
|
+
description: 'Electrique - Convecteur électrique NFC, NF** et NF***',
|
|
56
|
+
reference: 'Generateur:2024_07_11_09_30_44_722898200737262#1',
|
|
57
|
+
reference_generateur_mixte: '',
|
|
58
|
+
ref_produit_generateur_ch: 'Sans Objet',
|
|
59
|
+
enum_type_generateur_ch_id: '98',
|
|
60
|
+
enum_usage_generateur_id: '1',
|
|
61
|
+
enum_type_energie_id: '1',
|
|
62
|
+
position_volume_chauffe: 1,
|
|
63
|
+
tv_rendement_generation_id: 29,
|
|
64
|
+
identifiant_reseau_chaleur: '',
|
|
65
|
+
enum_methode_saisie_carac_sys_id: '1',
|
|
66
|
+
enum_lien_generateur_emetteur_id: '1'
|
|
67
|
+
},
|
|
68
|
+
donnee_intermediaire: {
|
|
69
|
+
rendement_generation: 1,
|
|
70
|
+
conso_ch: 6322.706407855126,
|
|
71
|
+
conso_ch_depensier: 7679.56883918009,
|
|
72
|
+
rg: 1,
|
|
73
|
+
rg_dep: 1,
|
|
74
|
+
conso_auxiliaire_generation_ch: 0,
|
|
75
|
+
conso_auxiliaire_generation_ch_depensier: 0
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
]
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
];
|
|
82
|
+
const ecs = [];
|
|
83
|
+
const fr = [];
|
|
84
|
+
|
|
85
|
+
const result = calc_conso(Sh, zc_id, ca_id, vt, ch, ecs, fr);
|
|
86
|
+
|
|
87
|
+
expect(result.ef_conso.conso_ch).toBe(6322.706407855126);
|
|
88
|
+
expect(result.ef_conso.conso_ch_depensier).toBe(7679.56883918009);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { UPB_ADDITIONAL_VALUES } from '../../tv/infrastructure/assets/additional-ue-values.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Add additional values for ue
|
|
5
|
+
*/
|
|
6
|
+
export class AddAdditionnalUeValuesTables {
|
|
7
|
+
/**
|
|
8
|
+
* @type {FileStore}
|
|
9
|
+
*/
|
|
10
|
+
#fileStore;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @type {ApplicationConfig}
|
|
14
|
+
*/
|
|
15
|
+
#appConfig;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @param fileStore {FileStore}
|
|
19
|
+
* @param appConfig {ApplicationConfig}
|
|
20
|
+
*/
|
|
21
|
+
constructor(fileStore, appConfig) {
|
|
22
|
+
this.#fileStore = fileStore;
|
|
23
|
+
this.#appConfig = appConfig;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Ajout de valeurs supplémentaires pour le calcul du facteur Ue pour les déperditions plancher_bas
|
|
28
|
+
* @param tableValues
|
|
29
|
+
* @returns {*}
|
|
30
|
+
*/
|
|
31
|
+
execute(tableValues) {
|
|
32
|
+
UPB_ADDITIONAL_VALUES.forEach(
|
|
33
|
+
({
|
|
34
|
+
type_adjacence_plancher,
|
|
35
|
+
enum_type_adjacence_id,
|
|
36
|
+
type_adjacence,
|
|
37
|
+
enum_periode_construction_id,
|
|
38
|
+
periode_construction,
|
|
39
|
+
values
|
|
40
|
+
}) => {
|
|
41
|
+
const baseData = {
|
|
42
|
+
type_adjacence_plancher,
|
|
43
|
+
enum_type_adjacence_id,
|
|
44
|
+
type_adjacence,
|
|
45
|
+
enum_periode_construction_id,
|
|
46
|
+
periode_construction
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
values.forEach(({ ue, '2s_p': key2SP, upb }) => {
|
|
50
|
+
tableValues['ue'].push({ ...baseData, '2s_p': key2SP, upb, ue });
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
return tableValues;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export class SynchronizeAssets {
|
|
2
|
+
/**
|
|
3
|
+
* @type {SynchronizeEnumTables}
|
|
4
|
+
*/
|
|
5
|
+
#synchronizeEnumTables;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @type {SynchronizeValeurTables}
|
|
9
|
+
*/
|
|
10
|
+
#synchronizeValeurTables;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @param synchronizeEnumTables {SynchronizeEnumTables}
|
|
14
|
+
* @param synchronizeValeurTables {SynchronizeValeurTables}
|
|
15
|
+
*/
|
|
16
|
+
constructor(synchronizeEnumTables, synchronizeValeurTables) {
|
|
17
|
+
this.#synchronizeEnumTables = synchronizeEnumTables;
|
|
18
|
+
this.#synchronizeValeurTables = synchronizeValeurTables;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
execute() {
|
|
22
|
+
return Promise.all([
|
|
23
|
+
this.#synchronizeEnumTables.execute(),
|
|
24
|
+
this.#synchronizeValeurTables.execute()
|
|
25
|
+
])
|
|
26
|
+
.then(() => console.log('enum and valeur tables are synchronized successfully'))
|
|
27
|
+
.catch((error) => console.error('Could not synchronize files', error));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { SynchronizeAssets } from './synchronize-assets.js';
|
|
2
|
+
import { SynchronizeEnumTables } from './synchronize-enum-tables.js';
|
|
3
|
+
import { SynchronizeValeurTables } from './synchronize-valeur-tables.js';
|
|
4
|
+
import { jest } from '@jest/globals';
|
|
5
|
+
|
|
6
|
+
describe('SynchronizeAssets unit tests', () => {
|
|
7
|
+
it('should synchronize xlsx and ods files', () => {
|
|
8
|
+
const synchronizeEnumTables = new SynchronizeEnumTables(null, null);
|
|
9
|
+
const synchronizeValeurTables = new SynchronizeValeurTables(null, null, null);
|
|
10
|
+
const synchronizeAssets = new SynchronizeAssets(synchronizeEnumTables, synchronizeValeurTables);
|
|
11
|
+
|
|
12
|
+
jest.spyOn(console, 'log').mockReturnValue(null);
|
|
13
|
+
jest.spyOn(synchronizeEnumTables, 'execute').mockResolvedValue({});
|
|
14
|
+
jest.spyOn(synchronizeValeurTables, 'execute').mockResolvedValue({});
|
|
15
|
+
|
|
16
|
+
return synchronizeAssets.execute().then(() => {
|
|
17
|
+
expect(synchronizeEnumTables.execute).toHaveBeenCalled();
|
|
18
|
+
expect(synchronizeValeurTables.execute).toHaveBeenCalled();
|
|
19
|
+
expect(console.log).toHaveBeenCalled();
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('should log errors if synchronization has failed', () => {
|
|
24
|
+
const synchronizeEnumTables = new SynchronizeEnumTables(null, null);
|
|
25
|
+
const synchronizeValeurTables = new SynchronizeValeurTables(null, null, null);
|
|
26
|
+
const synchronizeAssets = new SynchronizeAssets(synchronizeEnumTables, synchronizeValeurTables);
|
|
27
|
+
|
|
28
|
+
jest.spyOn(console, 'error').mockReturnValue(null);
|
|
29
|
+
jest.spyOn(synchronizeEnumTables, 'execute').mockResolvedValue({});
|
|
30
|
+
jest.spyOn(synchronizeValeurTables, 'execute').mockRejectedValue(null);
|
|
31
|
+
|
|
32
|
+
return synchronizeAssets.execute().catch((error) => {
|
|
33
|
+
expect(error).toBeDefined();
|
|
34
|
+
expect(console.error).toHaveBeenCalled();
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
});
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { set } from 'lodash-es';
|
|
2
|
+
|
|
3
|
+
const ZONE_CLIMATIQUE_PROPERTY = 'zc';
|
|
4
|
+
const MOIS_PROPERTY = 'mois';
|
|
5
|
+
const EXCLUDED_PROPERTIES = [ZONE_CLIMATIQUE_PROPERTY, MOIS_PROPERTY];
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Read the `18.5_c1.ods` local file
|
|
9
|
+
* - Convert the file into a json object
|
|
10
|
+
* - Extract, format data and return data
|
|
11
|
+
*
|
|
12
|
+
* The file content is merged in the `tv.js` file generated in the {@link SynchronizeValeurTables} use case.
|
|
13
|
+
*/
|
|
14
|
+
export class SynchronizeC1Tables {
|
|
15
|
+
/**
|
|
16
|
+
* @type {FileStore}
|
|
17
|
+
*/
|
|
18
|
+
#fileStore;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @type {ApplicationConfig}
|
|
22
|
+
*/
|
|
23
|
+
#appConfig;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @param fileStore {FileStore}
|
|
27
|
+
* @param appConfig {ApplicationConfig}
|
|
28
|
+
*/
|
|
29
|
+
constructor(fileStore, appConfig) {
|
|
30
|
+
this.#fileStore = fileStore;
|
|
31
|
+
this.#appConfig = appConfig;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
*
|
|
36
|
+
* @return {Promise<any>}
|
|
37
|
+
*/
|
|
38
|
+
execute() {
|
|
39
|
+
return this.#fileStore.readLocalOdsFileAndConvertToJson(this.#appConfig.c1FilePath).then(
|
|
40
|
+
/** @param excelSheets {{[key: string]: {zc: string, mois: string}[]}} **/ (excelSheets) => {
|
|
41
|
+
const output = {};
|
|
42
|
+
|
|
43
|
+
// For each tab in Excel file
|
|
44
|
+
for (const sheetName in excelSheets) {
|
|
45
|
+
output[sheetName] = {};
|
|
46
|
+
|
|
47
|
+
excelSheets[sheetName].forEach((sheetValue) => {
|
|
48
|
+
for (const sheetValueKey in sheetValue) {
|
|
49
|
+
if (!EXCLUDED_PROPERTIES.includes(sheetValueKey)) {
|
|
50
|
+
const path = `${sheetName}.${sheetValue.zc}.${sheetValue.mois}.${sheetValueKey}`;
|
|
51
|
+
set(output, path, parseFloat(sheetValue[sheetValueKey]));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return output;
|
|
58
|
+
}
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { SynchronizeC1Tables } from './synchronize-c1-tables.js';
|
|
2
|
+
import { FileStore } from '../../file/infrastructure/adapter/file.store.js';
|
|
3
|
+
import { ApplicationConfig } from '../../conf/infrastructure/application.config.js';
|
|
4
|
+
import { C1TablesFixture } from '../../../../test/fixtures/core/assets/c1-tables.fixture.js';
|
|
5
|
+
import { jest } from '@jest/globals';
|
|
6
|
+
|
|
7
|
+
describe('SynchronizeC1Tables unit tests', () => {
|
|
8
|
+
it('should read and parse 18.5_c1.ods file', () => {
|
|
9
|
+
const fileStore = new FileStore();
|
|
10
|
+
const appConfig = new ApplicationConfig();
|
|
11
|
+
const synchronizeC1Tables = new SynchronizeC1Tables(fileStore, appConfig);
|
|
12
|
+
|
|
13
|
+
const c1Data = C1TablesFixture.aC1Example();
|
|
14
|
+
jest.spyOn(fileStore, 'readLocalOdsFileAndConvertToJson').mockResolvedValue(c1Data);
|
|
15
|
+
jest.spyOn(ApplicationConfig.prototype, 'c1FilePath', 'get').mockReturnValue('src/file.ods');
|
|
16
|
+
|
|
17
|
+
return synchronizeC1Tables.execute().then((output) => {
|
|
18
|
+
expect(fileStore.readLocalOdsFileAndConvertToJson).toHaveBeenCalled();
|
|
19
|
+
expect(output).toMatchObject({
|
|
20
|
+
c1: {
|
|
21
|
+
h1a: {
|
|
22
|
+
Janvier: {
|
|
23
|
+
'sud sup75°': 1.0,
|
|
24
|
+
'sud 25°-75°': 1.67
|
|
25
|
+
},
|
|
26
|
+
Février: {
|
|
27
|
+
'sud sup75°': 1.0,
|
|
28
|
+
'sud 25°-75°': 1.78
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
});
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { set } from 'lodash-es';
|
|
2
|
+
|
|
3
|
+
const CLASSE_ALTITUDE_PROPERTY = 'classe_altitude';
|
|
4
|
+
const SURFACE_PROPERTY = 'surface';
|
|
5
|
+
const EXCLUDED_PROPERTIES = [CLASSE_ALTITUDE_PROPERTY, SURFACE_PROPERTY];
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Read the `dpe_ges_limit_values.ods` local file
|
|
9
|
+
* - Convert the file into a json object
|
|
10
|
+
* - Extract, format data and return data
|
|
11
|
+
*
|
|
12
|
+
* The file content is merged in the `tv.js` file generated in the {@link SynchronizeValeurTables} use case.
|
|
13
|
+
*/
|
|
14
|
+
export class SynchronizeDpeGesLimitValuesTables {
|
|
15
|
+
/**
|
|
16
|
+
* @type {FileStore}
|
|
17
|
+
*/
|
|
18
|
+
#fileStore;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @type {ApplicationConfig}
|
|
22
|
+
*/
|
|
23
|
+
#appConfig;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @param fileStore {FileStore}
|
|
27
|
+
* @param appConfig {ApplicationConfig}
|
|
28
|
+
*/
|
|
29
|
+
constructor(fileStore, appConfig) {
|
|
30
|
+
this.#fileStore = fileStore;
|
|
31
|
+
this.#appConfig = appConfig;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @return {Promise<any>}
|
|
36
|
+
*/
|
|
37
|
+
execute() {
|
|
38
|
+
return this.#fileStore
|
|
39
|
+
.readLocalOdsFileAndConvertToJson(this.#appConfig.dpeGesLimitValuesFilePath)
|
|
40
|
+
.then(
|
|
41
|
+
/** @param excelSheets {{[key: string]: {classe_altitude: string, surface: string}[]}} **/ (
|
|
42
|
+
excelSheets
|
|
43
|
+
) => {
|
|
44
|
+
const output = {};
|
|
45
|
+
|
|
46
|
+
// For each tab in Excel file
|
|
47
|
+
for (const sheetName in excelSheets) {
|
|
48
|
+
output[sheetName] = {};
|
|
49
|
+
|
|
50
|
+
excelSheets[sheetName].forEach((sheetValue) => {
|
|
51
|
+
// Group by "classe_altitude" an "surface"
|
|
52
|
+
let groupKey = sheetValue.classe_altitude;
|
|
53
|
+
|
|
54
|
+
if (!output[sheetName][groupKey]) {
|
|
55
|
+
output[sheetName][groupKey] = {};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
output[sheetName][groupKey][parseFloat(sheetValue.surface)] = {};
|
|
59
|
+
|
|
60
|
+
for (const sheetValueKey in sheetValue) {
|
|
61
|
+
if (!EXCLUDED_PROPERTIES.includes(sheetValueKey)) {
|
|
62
|
+
const path = `${sheetName}.${groupKey}.${sheetValue.surface}.${sheetValueKey}`;
|
|
63
|
+
set(output, path, parseFloat(sheetValue[sheetValueKey]));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return output;
|
|
70
|
+
}
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { FileStore } from '../../file/infrastructure/adapter/file.store.js';
|
|
2
|
+
import { ApplicationConfig } from '../../conf/infrastructure/application.config.js';
|
|
3
|
+
import { DpeGesLimitValuesTablesFixture } from '../../../../test/fixtures/core/assets/dpe-ges-limit-values-tables.fixture.js';
|
|
4
|
+
import { SynchronizeDpeGesLimitValuesTables } from './synchronize-dpe-ges-limit-values-tables.js';
|
|
5
|
+
import { jest } from '@jest/globals';
|
|
6
|
+
|
|
7
|
+
describe('SynchronizeDpeGesLimitValuesTables unit tests', () => {
|
|
8
|
+
it('should read and parse dpe_ges_limit_values file', () => {
|
|
9
|
+
const fileStore = new FileStore();
|
|
10
|
+
const appConfig = new ApplicationConfig();
|
|
11
|
+
const synchronizeDpeGesLimitValuesTables = new SynchronizeDpeGesLimitValuesTables(
|
|
12
|
+
fileStore,
|
|
13
|
+
appConfig
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
const dpeGesLimitData = DpeGesLimitValuesTablesFixture.aDpeGesLimitExample();
|
|
17
|
+
jest.spyOn(fileStore, 'readLocalOdsFileAndConvertToJson').mockResolvedValue(dpeGesLimitData);
|
|
18
|
+
jest
|
|
19
|
+
.spyOn(ApplicationConfig.prototype, 'solicitationsExtFilePath', 'get')
|
|
20
|
+
.mockReturnValue('src/file.ods');
|
|
21
|
+
|
|
22
|
+
return synchronizeDpeGesLimitValuesTables.execute().then((output) => {
|
|
23
|
+
expect(fileStore.readLocalOdsFileAndConvertToJson).toHaveBeenCalled();
|
|
24
|
+
expect(output).toStrictEqual({
|
|
25
|
+
dpe_class_limit: {
|
|
26
|
+
'inférieur à 400m': {
|
|
27
|
+
3: {
|
|
28
|
+
A: 146,
|
|
29
|
+
B: 186,
|
|
30
|
+
C: 386,
|
|
31
|
+
D: 505,
|
|
32
|
+
E: 622,
|
|
33
|
+
F: 739
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
'400-800m': {
|
|
37
|
+
10: {
|
|
38
|
+
A: 124,
|
|
39
|
+
B: 164,
|
|
40
|
+
C: 329,
|
|
41
|
+
D: 428,
|
|
42
|
+
E: 533,
|
|
43
|
+
F: 640
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
ges_class_limit: {
|
|
48
|
+
'400-800m': {
|
|
49
|
+
10: {
|
|
50
|
+
A: 10,
|
|
51
|
+
B: 15,
|
|
52
|
+
C: 40,
|
|
53
|
+
D: 62,
|
|
54
|
+
E: 84,
|
|
55
|
+
F: 115
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
'inférieur à 400m': {
|
|
59
|
+
3: {
|
|
60
|
+
A: 11,
|
|
61
|
+
B: 16,
|
|
62
|
+
C: 44,
|
|
63
|
+
D: 68,
|
|
64
|
+
E: 90,
|
|
65
|
+
F: 122
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
});
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Download the `enum_tables.xlsx` file from the official ademe repository and generates a new `enums.js` file
|
|
3
|
+
* Please see @link https://gitlab.com/observatoire-dpe/observatoire-dpe/-/tree/master
|
|
4
|
+
* - Convert the file into a json object
|
|
5
|
+
* - Extract, format data and then generate a new enums.js file
|
|
6
|
+
*/
|
|
7
|
+
export class SynchronizeEnumTables {
|
|
8
|
+
/**
|
|
9
|
+
* @type {FileStore}
|
|
10
|
+
*/
|
|
11
|
+
#fileStore;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @type {ApplicationConfig}
|
|
15
|
+
*/
|
|
16
|
+
#appConfig;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @param fileStore {FileStore}
|
|
20
|
+
* @param appConfig {ApplicationConfig}
|
|
21
|
+
*/
|
|
22
|
+
constructor(fileStore, appConfig) {
|
|
23
|
+
this.#fileStore = fileStore;
|
|
24
|
+
this.#appConfig = appConfig;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @return {Promise<void>}
|
|
29
|
+
*/
|
|
30
|
+
execute() {
|
|
31
|
+
return this.#fileStore
|
|
32
|
+
.downloadXlsxFileAndConvertToJson(this.#appConfig.ademeEnumTablesFileUrl)
|
|
33
|
+
.then(
|
|
34
|
+
/** @param excelSheets {{[tabName: string]: {id: string, lib: string}[]}} xlsx content file grouped by tab */
|
|
35
|
+
(excelSheets) => {
|
|
36
|
+
const enumsOutput = {};
|
|
37
|
+
|
|
38
|
+
// for each tab in xlsx file
|
|
39
|
+
Object.keys(excelSheets)
|
|
40
|
+
.filter((sheetName) => sheetName !== 'index') // Exclude first tab called "index"
|
|
41
|
+
.forEach((sheetName) => {
|
|
42
|
+
/**
|
|
43
|
+
* Each Excel sheet has a list of columns
|
|
44
|
+
* Keep only the two first columns for now for compatibility with the legacy `enums.js` file
|
|
45
|
+
* @type {{id: string, lib: string}[]}
|
|
46
|
+
*/
|
|
47
|
+
const excelSheetValues = excelSheets[sheetName];
|
|
48
|
+
|
|
49
|
+
const outputTabValues = {};
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Convert object in the form of [{id: 1, lib: "test"}, {id: 2, lib: "test 2"}]
|
|
53
|
+
* to {1: "test", 2: "test 2"}
|
|
54
|
+
*/
|
|
55
|
+
excelSheetValues.forEach((excelSheetValue) => {
|
|
56
|
+
outputTabValues[excelSheetValue.id] = excelSheetValue.lib.replace(/ :/g, ' :');
|
|
57
|
+
|
|
58
|
+
// For compatibility with the legacy `enums.js` file, force the lowercase for
|
|
59
|
+
// each value except the `classe_etiquette`
|
|
60
|
+
if (sheetName !== 'classe_etiquette') {
|
|
61
|
+
outputTabValues[excelSheetValue.id] =
|
|
62
|
+
outputTabValues[excelSheetValue.id].toLowerCase();
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
enumsOutput[sheetName] = outputTabValues;
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// Overwrite the enums.js file in filesystem
|
|
70
|
+
return this.#fileStore.writeFileToLocalSystem(
|
|
71
|
+
`${this.#appConfig.assetsOutputFolder}/enums.js`,
|
|
72
|
+
`/** @type {TableEnum} **/\nconst enums = ${JSON.stringify(enumsOutput, null, 2)};\n export default enums;`
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { FileStore } from '../../file/infrastructure/adapter/file.store.js';
|
|
2
|
+
import { ApplicationConfig } from '../../conf/infrastructure/application.config.js';
|
|
3
|
+
import { EnumTablesFixture } from '../../../../test/fixtures/core/assets/enum-tables.fixture.js';
|
|
4
|
+
import { SynchronizeEnumTables } from './synchronize-enum-tables.js';
|
|
5
|
+
import { jest } from '@jest/globals';
|
|
6
|
+
|
|
7
|
+
describe('SynchronizeEnumTables', () => {
|
|
8
|
+
it('should download, parse and convert enum_tables.xlsx file', () => {
|
|
9
|
+
const fileStore = new FileStore();
|
|
10
|
+
const appConfig = new ApplicationConfig();
|
|
11
|
+
const synchronizeEnumTables = new SynchronizeEnumTables(fileStore, appConfig);
|
|
12
|
+
|
|
13
|
+
const enumTablesData = EnumTablesFixture.anEnumTableExample();
|
|
14
|
+
jest
|
|
15
|
+
.spyOn(ApplicationConfig.prototype, 'ademeEnumTablesFileUrl', 'get')
|
|
16
|
+
.mockReturnValue('http://localhost/file.xlsx');
|
|
17
|
+
jest
|
|
18
|
+
.spyOn(ApplicationConfig.prototype, 'assetsOutputFolder', 'get')
|
|
19
|
+
.mockReturnValue('src/assets');
|
|
20
|
+
jest.spyOn(fileStore, 'downloadXlsxFileAndConvertToJson').mockResolvedValue(enumTablesData);
|
|
21
|
+
jest.spyOn(fileStore, 'writeFileToLocalSystem').mockResolvedValue(null);
|
|
22
|
+
|
|
23
|
+
return synchronizeEnumTables.execute().then(() => {
|
|
24
|
+
expect(fileStore.downloadXlsxFileAndConvertToJson).toHaveBeenCalled();
|
|
25
|
+
expect(fileStore.writeFileToLocalSystem).toHaveBeenCalledWith(
|
|
26
|
+
'src/assets/enums.js',
|
|
27
|
+
expect.any(String)
|
|
28
|
+
);
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
});
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { set } from 'lodash-es';
|
|
2
|
+
|
|
3
|
+
const ILPA_PROPERTY = 'ilpa';
|
|
4
|
+
const CLASSE_ALTITUDE_PROPERTY = 'classe_altitude';
|
|
5
|
+
const MOIS_PROPERTY = 'mois';
|
|
6
|
+
const EXCLUDED_PROPERTIES = [ILPA_PROPERTY, CLASSE_ALTITUDE_PROPERTY, MOIS_PROPERTY];
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Read the `18.2_sollicitations_ext.ods` local file
|
|
10
|
+
* - Convert the file into a json object
|
|
11
|
+
* - Extract, format data and return data
|
|
12
|
+
*
|
|
13
|
+
* The file content is merged in the `tv.js` file generated in the {@link SynchronizeValeurTables} use case.
|
|
14
|
+
*/
|
|
15
|
+
export class SynchronizeSolicitationsTables {
|
|
16
|
+
/**
|
|
17
|
+
* @type {FileStore}
|
|
18
|
+
*/
|
|
19
|
+
#fileStore;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @type {ApplicationConfig}
|
|
23
|
+
*/
|
|
24
|
+
#appConfig;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @param fileStore {FileStore}
|
|
28
|
+
* @param appConfig {ApplicationConfig}
|
|
29
|
+
*/
|
|
30
|
+
constructor(fileStore, appConfig) {
|
|
31
|
+
this.#fileStore = fileStore;
|
|
32
|
+
this.#appConfig = appConfig;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @return {Promise<any>}
|
|
37
|
+
*/
|
|
38
|
+
execute() {
|
|
39
|
+
return this.#fileStore
|
|
40
|
+
.readLocalOdsFileAndConvertToJson(this.#appConfig.solicitationsExtFilePath)
|
|
41
|
+
.then(
|
|
42
|
+
/** @param excelSheets {{[key: string]: {ilpa?: number, classe_altitude: string, mois: string}[]}} **/ (
|
|
43
|
+
excelSheets
|
|
44
|
+
) => {
|
|
45
|
+
const output = {};
|
|
46
|
+
|
|
47
|
+
// For each tab in Excel file
|
|
48
|
+
for (const sheetName in excelSheets) {
|
|
49
|
+
output[sheetName] = {};
|
|
50
|
+
|
|
51
|
+
excelSheets[sheetName].forEach((sheetValue) => {
|
|
52
|
+
// Group by "ilpa" property if it exists or "classe_altitude" otherwise
|
|
53
|
+
let groupKey = sheetValue.hasOwnProperty(ILPA_PROPERTY)
|
|
54
|
+
? '.' + sheetValue.ilpa
|
|
55
|
+
: sheetValue.hasOwnProperty(CLASSE_ALTITUDE_PROPERTY)
|
|
56
|
+
? '.' + sheetValue.classe_altitude
|
|
57
|
+
: '';
|
|
58
|
+
|
|
59
|
+
for (const sheetValueKey in sheetValue) {
|
|
60
|
+
if (!EXCLUDED_PROPERTIES.includes(sheetValueKey)) {
|
|
61
|
+
const path = `${sheetName}${groupKey}${sheetValue.hasOwnProperty(ILPA_PROPERTY) ? '.' + sheetValue.classe_altitude : ''}.${sheetValue.mois}.${sheetValueKey}`;
|
|
62
|
+
set(output, path, parseFloat(sheetValue[sheetValueKey]));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return output;
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { FileStore } from '../../file/infrastructure/adapter/file.store.js';
|
|
2
|
+
import { ApplicationConfig } from '../../conf/infrastructure/application.config.js';
|
|
3
|
+
import { SynchronizeSolicitationsTables } from './synchronize-solicitations-tables.js';
|
|
4
|
+
import { SolicitationsTablesFixture } from '../../../../test/fixtures/core/assets/solicitations-tables.fixture.js';
|
|
5
|
+
import { jest } from '@jest/globals';
|
|
6
|
+
|
|
7
|
+
describe('SynchronizeSolicitationsTables unit tests', () => {
|
|
8
|
+
it('should read and parse 18.2_sollicitations_ext.ods file', () => {
|
|
9
|
+
const fileStore = new FileStore();
|
|
10
|
+
const appConfig = new ApplicationConfig();
|
|
11
|
+
const synchronizeSolicitationsTables = new SynchronizeSolicitationsTables(fileStore, appConfig);
|
|
12
|
+
|
|
13
|
+
const solicitationsData = SolicitationsTablesFixture.aSolicitationExample();
|
|
14
|
+
jest.spyOn(fileStore, 'readLocalOdsFileAndConvertToJson').mockResolvedValue(solicitationsData);
|
|
15
|
+
jest
|
|
16
|
+
.spyOn(ApplicationConfig.prototype, 'solicitationsExtFilePath', 'get')
|
|
17
|
+
.mockReturnValue('src/file.ods');
|
|
18
|
+
|
|
19
|
+
return synchronizeSolicitationsTables.execute().then((output) => {
|
|
20
|
+
expect(fileStore.readLocalOdsFileAndConvertToJson).toHaveBeenCalled();
|
|
21
|
+
expect(output).toMatchObject({
|
|
22
|
+
e: {
|
|
23
|
+
0: {
|
|
24
|
+
'inférieur à 400m': {
|
|
25
|
+
Janvier: {
|
|
26
|
+
h1a: 38.36
|
|
27
|
+
},
|
|
28
|
+
Février: {
|
|
29
|
+
h1a: 37.47
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
e_fr_26: {
|
|
35
|
+
'inférieur à 400m': {
|
|
36
|
+
Janvier: {
|
|
37
|
+
h1a: 0
|
|
38
|
+
},
|
|
39
|
+
Février: {
|
|
40
|
+
h1a: 0
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
});
|