@carbonbox/domain 0.51.0 → 0.52.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.
Files changed (38) hide show
  1. package/build/carbonbox/emission-calculation-formulas/emission-factors/domain/entity/EmissionFactor.js +44 -2
  2. package/build/carbonbox/emission-calculation-formulas/emission-factors/domain/enums/BiogenicContent.js +26 -0
  3. package/build/carbonbox/emission-calculation-formulas/emission-factors/domain/exceptions/InconsistentEmissionFactorBiogenicContentError.js +40 -0
  4. package/build/carbonbox/emission-calculation-formulas/emission-factors/domain/exceptions/InvalidBiogenicContentError.js +32 -0
  5. package/build/carbonbox/emission-calculation-formulas/emission-factors/domain/value-objects/EmissionFactorBiogenicContent.js +60 -0
  6. package/build/carbonbox/emission-calculation-formulas/emission-factors/domain/value-objects/EmissionFactorGreenhouseGasValues.js +2 -0
  7. package/build/carbonbox/emission-calculation-formulas/global-warming-potentials/domain/value-objects/GlobalWarmingPotentialGreenhouseGasPotentials.js +2 -0
  8. package/build/carbonbox/shared/domain/enums/ErrorCode.js +3 -1
  9. package/build/carbonbox/shared/domain/enums/StandardGreenhouseGasSpecies.js +36 -0
  10. package/build/carbonbox/shared/domain/value-objects/GreenhouseGasSpecies.js +67 -4
  11. package/build/main/index.js +26 -16
  12. package/build/types/carbonbox/emission-calculation-formulas/emission-factors/domain/entity/EmissionFactor.d.ts +12 -0
  13. package/build/types/carbonbox/emission-calculation-formulas/emission-factors/domain/entity/EmissionFactor.d.ts.map +1 -1
  14. package/build/types/carbonbox/emission-calculation-formulas/emission-factors/domain/entity/IEmissionFactor.d.ts +2 -0
  15. package/build/types/carbonbox/emission-calculation-formulas/emission-factors/domain/entity/IEmissionFactor.d.ts.map +1 -1
  16. package/build/types/carbonbox/emission-calculation-formulas/emission-factors/domain/enums/BiogenicContent.d.ts +23 -0
  17. package/build/types/carbonbox/emission-calculation-formulas/emission-factors/domain/enums/BiogenicContent.d.ts.map +1 -0
  18. package/build/types/carbonbox/emission-calculation-formulas/emission-factors/domain/exceptions/InconsistentEmissionFactorBiogenicContentError.d.ts +8 -0
  19. package/build/types/carbonbox/emission-calculation-formulas/emission-factors/domain/exceptions/InconsistentEmissionFactorBiogenicContentError.d.ts.map +1 -0
  20. package/build/types/carbonbox/emission-calculation-formulas/emission-factors/domain/exceptions/InvalidBiogenicContentError.d.ts +8 -0
  21. package/build/types/carbonbox/emission-calculation-formulas/emission-factors/domain/exceptions/InvalidBiogenicContentError.d.ts.map +1 -0
  22. package/build/types/carbonbox/emission-calculation-formulas/emission-factors/domain/types/EmissionFactorPrimitives.d.ts +2 -0
  23. package/build/types/carbonbox/emission-calculation-formulas/emission-factors/domain/types/EmissionFactorPrimitives.d.ts.map +1 -1
  24. package/build/types/carbonbox/emission-calculation-formulas/emission-factors/domain/types/EmissionFactorProps.d.ts +2 -0
  25. package/build/types/carbonbox/emission-calculation-formulas/emission-factors/domain/types/EmissionFactorProps.d.ts.map +1 -1
  26. package/build/types/carbonbox/emission-calculation-formulas/emission-factors/domain/value-objects/EmissionFactorBiogenicContent.d.ts +27 -0
  27. package/build/types/carbonbox/emission-calculation-formulas/emission-factors/domain/value-objects/EmissionFactorBiogenicContent.d.ts.map +1 -0
  28. package/build/types/carbonbox/emission-calculation-formulas/emission-factors/domain/value-objects/EmissionFactorGreenhouseGasValues.d.ts.map +1 -1
  29. package/build/types/carbonbox/emission-calculation-formulas/global-warming-potentials/domain/value-objects/GlobalWarmingPotentialGreenhouseGasPotentials.d.ts.map +1 -1
  30. package/build/types/carbonbox/shared/domain/enums/ErrorCode.d.ts +2 -0
  31. package/build/types/carbonbox/shared/domain/enums/ErrorCode.d.ts.map +1 -1
  32. package/build/types/carbonbox/shared/domain/enums/StandardGreenhouseGasSpecies.d.ts +33 -0
  33. package/build/types/carbonbox/shared/domain/enums/StandardGreenhouseGasSpecies.d.ts.map +1 -0
  34. package/build/types/carbonbox/shared/domain/value-objects/GreenhouseGasSpecies.d.ts +35 -4
  35. package/build/types/carbonbox/shared/domain/value-objects/GreenhouseGasSpecies.d.ts.map +1 -1
  36. package/build/types/main/index.d.ts +5 -0
  37. package/build/types/main/index.d.ts.map +1 -1
  38. package/package.json +1 -1
@@ -10,7 +10,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
10
10
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
11
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
12
  };
13
- var _EmissionFactor_code, _EmissionFactor_name, _EmissionFactor_description, _EmissionFactor_greenhouseGasValues, _EmissionFactor_informationSource, _EmissionFactor_ipccCode, _EmissionFactor_ipccSubcategory, _EmissionFactor_methodologicalTier;
13
+ var _EmissionFactor_code, _EmissionFactor_name, _EmissionFactor_description, _EmissionFactor_greenhouseGasValues, _EmissionFactor_informationSource, _EmissionFactor_ipccCode, _EmissionFactor_ipccSubcategory, _EmissionFactor_methodologicalTier, _EmissionFactor_biogenicContent;
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.EmissionFactor = void 0;
16
16
  const AggregateRoot_1 = require("../../../../shared/domain/entities/AggregateRoot");
@@ -23,6 +23,9 @@ const EmissionFactorIpccCode_1 = require("../value-objects/EmissionFactorIpccCod
23
23
  const EmissionFactorIpccSubcategory_1 = require("../value-objects/EmissionFactorIpccSubcategory");
24
24
  const EmissionFactorMethodologicalTier_1 = require("../value-objects/EmissionFactorMethodologicalTier");
25
25
  const EmissionFactorName_1 = require("../value-objects/EmissionFactorName");
26
+ const EmissionFactorBiogenicContent_1 = require("../value-objects/EmissionFactorBiogenicContent");
27
+ const InconsistentEmissionFactorBiogenicContentError_1 = require("../exceptions/InconsistentEmissionFactorBiogenicContentError");
28
+ const StandardGreenhouseGasSpecies_1 = require("../../../../shared/domain/enums/StandardGreenhouseGasSpecies");
26
29
  class EmissionFactor extends AggregateRoot_1.AggregateRoot {
27
30
  constructor(props, skipDomainValidation) {
28
31
  const id = skipDomainValidation
@@ -37,6 +40,7 @@ class EmissionFactor extends AggregateRoot_1.AggregateRoot {
37
40
  _EmissionFactor_ipccCode.set(this, void 0);
38
41
  _EmissionFactor_ipccSubcategory.set(this, void 0);
39
42
  _EmissionFactor_methodologicalTier.set(this, void 0);
43
+ _EmissionFactor_biogenicContent.set(this, void 0);
40
44
  if (skipDomainValidation === false) {
41
45
  // Initialize with domain validation
42
46
  __classPrivateFieldSet(this, _EmissionFactor_code, EmissionFactorCode_1.EmissionFactorCode.create(props.code), "f");
@@ -47,6 +51,8 @@ class EmissionFactor extends AggregateRoot_1.AggregateRoot {
47
51
  __classPrivateFieldSet(this, _EmissionFactor_ipccCode, EmissionFactorIpccCode_1.EmissionFactorIpccCode.create(props.ipccCode), "f");
48
52
  __classPrivateFieldSet(this, _EmissionFactor_ipccSubcategory, EmissionFactorIpccSubcategory_1.EmissionFactorIpccSubcategory.create(props.ipccSubcategory), "f");
49
53
  __classPrivateFieldSet(this, _EmissionFactor_methodologicalTier, EmissionFactorMethodologicalTier_1.EmissionFactorMethodologicalTier.create(props.methodologicalTier), "f");
54
+ __classPrivateFieldSet(this, _EmissionFactor_biogenicContent, EmissionFactorBiogenicContent_1.EmissionFactorBiogenicContent.create(props.biogenicContent), "f");
55
+ EmissionFactor.guardAgainstInconsistentBiogenicContent(__classPrivateFieldGet(this, _EmissionFactor_biogenicContent, "f"), __classPrivateFieldGet(this, _EmissionFactor_greenhouseGasValues, "f"));
50
56
  }
51
57
  else {
52
58
  // Initialize from primitives (no domain validation)
@@ -58,6 +64,7 @@ class EmissionFactor extends AggregateRoot_1.AggregateRoot {
58
64
  __classPrivateFieldSet(this, _EmissionFactor_ipccCode, EmissionFactorIpccCode_1.EmissionFactorIpccCode.fromPrimitives(props.ipccCode), "f");
59
65
  __classPrivateFieldSet(this, _EmissionFactor_ipccSubcategory, EmissionFactorIpccSubcategory_1.EmissionFactorIpccSubcategory.fromPrimitives(props.ipccSubcategory), "f");
60
66
  __classPrivateFieldSet(this, _EmissionFactor_methodologicalTier, EmissionFactorMethodologicalTier_1.EmissionFactorMethodologicalTier.fromPrimitives(props.methodologicalTier), "f");
67
+ __classPrivateFieldSet(this, _EmissionFactor_biogenicContent, EmissionFactorBiogenicContent_1.EmissionFactorBiogenicContent.fromPrimitives(props.biogenicContent), "f");
61
68
  }
62
69
  }
63
70
  static create(props) {
@@ -74,6 +81,7 @@ class EmissionFactor extends AggregateRoot_1.AggregateRoot {
74
81
  ipccCode: primitives.ipccCode,
75
82
  ipccSubcategory: primitives.ipccSubcategory,
76
83
  methodologicalTier: primitives.methodologicalTier,
84
+ biogenicContent: primitives.biogenicContent,
77
85
  };
78
86
  return new EmissionFactor(props, true);
79
87
  }
@@ -88,6 +96,7 @@ class EmissionFactor extends AggregateRoot_1.AggregateRoot {
88
96
  ipccCode: __classPrivateFieldGet(this, _EmissionFactor_ipccCode, "f").toPrimitives(),
89
97
  ipccSubcategory: __classPrivateFieldGet(this, _EmissionFactor_ipccSubcategory, "f").toPrimitives(),
90
98
  methodologicalTier: __classPrivateFieldGet(this, _EmissionFactor_methodologicalTier, "f").toEnum(),
99
+ biogenicContent: __classPrivateFieldGet(this, _EmissionFactor_biogenicContent, "f").toEnum(),
91
100
  };
92
101
  }
93
102
  get code() {
@@ -114,6 +123,39 @@ class EmissionFactor extends AggregateRoot_1.AggregateRoot {
114
123
  get methodologicalTier() {
115
124
  return __classPrivateFieldGet(this, _EmissionFactor_methodologicalTier, "f");
116
125
  }
126
+ get biogenicContent() {
127
+ return __classPrivateFieldGet(this, _EmissionFactor_biogenicContent, "f");
128
+ }
129
+ /**
130
+ * Coherencia entre el contenido biogénico declarado y las especies del factor
131
+ * (GHG Protocol cap. 9 / ISO 14064-1 §9.3.1): evita, p.ej., una leña cargada con `CO2` fósil
132
+ * (se sumaría al inventario) o una mezcla con biocombustible sin su `CO2-BIOGENIC`.
133
+ * - NONE: no declara `CO2-BIOGENIC` ni `CH4-NON-FOSSIL`.
134
+ * - FULL: no declara `CO2` ni `CH4-FOSSIL`, y declara `CO2-BIOGENIC` o `CH4-NON-FOSSIL`.
135
+ * - PARTIAL: declara `CO2` y `CO2-BIOGENIC`.
136
+ * N2O y las especies de texto libre se aceptan con cualquier contenido.
137
+ */
138
+ static guardAgainstInconsistentBiogenicContent(biogenicContent, greenhouseGasValues) {
139
+ const declaredSpecies = greenhouseGasValues.toPrimitives().map((value) => value.greenhouseGasSpecies);
140
+ const declares = (species) => declaredSpecies.includes(species);
141
+ const forbiddenSpecies = [];
142
+ const missingSpecies = [];
143
+ if (biogenicContent.isNone()) {
144
+ forbiddenSpecies.push(...[StandardGreenhouseGasSpecies_1.StandardGreenhouseGasSpecies.CO2_BIOGENIC, StandardGreenhouseGasSpecies_1.StandardGreenhouseGasSpecies.CH4_NON_FOSSIL].filter(declares));
145
+ }
146
+ if (biogenicContent.isFull()) {
147
+ forbiddenSpecies.push(...[StandardGreenhouseGasSpecies_1.StandardGreenhouseGasSpecies.CO2, StandardGreenhouseGasSpecies_1.StandardGreenhouseGasSpecies.CH4_FOSSIL].filter(declares));
148
+ if (!declares(StandardGreenhouseGasSpecies_1.StandardGreenhouseGasSpecies.CO2_BIOGENIC) && !declares(StandardGreenhouseGasSpecies_1.StandardGreenhouseGasSpecies.CH4_NON_FOSSIL)) {
149
+ missingSpecies.push(`${StandardGreenhouseGasSpecies_1.StandardGreenhouseGasSpecies.CO2_BIOGENIC} or ${StandardGreenhouseGasSpecies_1.StandardGreenhouseGasSpecies.CH4_NON_FOSSIL}`);
150
+ }
151
+ }
152
+ if (biogenicContent.isPartial()) {
153
+ missingSpecies.push(...[StandardGreenhouseGasSpecies_1.StandardGreenhouseGasSpecies.CO2, StandardGreenhouseGasSpecies_1.StandardGreenhouseGasSpecies.CO2_BIOGENIC].filter((species) => !declares(species)));
154
+ }
155
+ if (forbiddenSpecies.length > 0 || missingSpecies.length > 0) {
156
+ throw InconsistentEmissionFactorBiogenicContentError_1.InconsistentEmissionFactorBiogenicContentError.create(biogenicContent.toEnum(), declaredSpecies, forbiddenSpecies, missingSpecies);
157
+ }
158
+ }
117
159
  }
118
160
  exports.EmissionFactor = EmissionFactor;
119
- _EmissionFactor_code = new WeakMap(), _EmissionFactor_name = new WeakMap(), _EmissionFactor_description = new WeakMap(), _EmissionFactor_greenhouseGasValues = new WeakMap(), _EmissionFactor_informationSource = new WeakMap(), _EmissionFactor_ipccCode = new WeakMap(), _EmissionFactor_ipccSubcategory = new WeakMap(), _EmissionFactor_methodologicalTier = new WeakMap();
161
+ _EmissionFactor_code = new WeakMap(), _EmissionFactor_name = new WeakMap(), _EmissionFactor_description = new WeakMap(), _EmissionFactor_greenhouseGasValues = new WeakMap(), _EmissionFactor_informationSource = new WeakMap(), _EmissionFactor_ipccCode = new WeakMap(), _EmissionFactor_ipccSubcategory = new WeakMap(), _EmissionFactor_methodologicalTier = new WeakMap(), _EmissionFactor_biogenicContent = new WeakMap();
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BiogenicContent = void 0;
4
+ /**
5
+ * Biogenic carbon content of an emission factor
6
+ * Declares the carbon origin of the activity so the greenhouse gas species of the factor can be
7
+ * checked for coherence (GHG Protocol Corporate Standard cap. 9; ISO 14064-1:2018 §9.3.1)
8
+ */
9
+ var BiogenicContent;
10
+ (function (BiogenicContent) {
11
+ /**
12
+ * No biogenic carbon - fossil fuels, grid electricity, refrigerants, industrial processes.
13
+ * Must not declare `CO2-BIOGENIC` nor `CH4-NON-FOSSIL`
14
+ */
15
+ BiogenicContent["NONE"] = "NONE";
16
+ /**
17
+ * Fully biogenic carbon - biomass, organic waste, wastewater.
18
+ * Must not declare `CO2` nor `CH4-FOSSIL`, and must declare `CO2-BIOGENIC` or `CH4-NON-FOSSIL`
19
+ */
20
+ BiogenicContent["FULL"] = "FULL";
21
+ /**
22
+ * Fossil and biogenic carbon - fuels blended with biofuels.
23
+ * Must declare both `CO2` and `CO2-BIOGENIC`
24
+ */
25
+ BiogenicContent["PARTIAL"] = "PARTIAL";
26
+ })(BiogenicContent || (exports.BiogenicContent = BiogenicContent = {}));
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.InconsistentEmissionFactorBiogenicContentError = void 0;
4
+ const CodedRootError_1 = require("../../../../shared/domain/exceptions/CodedRootError");
5
+ const ErrorCode_1 = require("../../../../shared/domain/enums/ErrorCode");
6
+ class InconsistentEmissionFactorBiogenicContentError extends CodedRootError_1.CodedRootError {
7
+ constructor(biogenicContent, declaredSpecies, forbiddenSpecies, missingSpecies) {
8
+ const problems = [];
9
+ if (forbiddenSpecies.length > 0) {
10
+ problems.push(`must not declare [${forbiddenSpecies.join(', ')}]`);
11
+ }
12
+ if (missingSpecies.length > 0) {
13
+ problems.push(`must declare [${missingSpecies.join(', ')}]`);
14
+ }
15
+ const technicalMessage = `Emission factor with biogenic content '${biogenicContent}' ${problems.join(' and ')} `
16
+ + `(declared species: [${declaredSpecies.join(', ')}]).`;
17
+ const context = {
18
+ biogenicContent,
19
+ declaredSpecies,
20
+ forbiddenSpecies,
21
+ missingSpecies,
22
+ timestamp: new Date().toISOString(),
23
+ };
24
+ const suggestions = [
25
+ 'NONE (fossil fuels, grid electricity, refrigerants): use CO2 and CH4-FOSSIL, never CO2-BIOGENIC nor CH4-NON-FOSSIL',
26
+ 'FULL (biomass, organic waste, wastewater): use CO2-BIOGENIC and/or CH4-NON-FOSSIL, never CO2 nor CH4-FOSSIL',
27
+ 'PARTIAL (fuels blended with biofuels): split the carbon dioxide into CO2 (fossil share) and CO2-BIOGENIC (biofuel share)',
28
+ 'N2O and non-standard species are allowed with any biogenic content',
29
+ ];
30
+ super(ErrorCode_1.ErrorCode.INCONSISTENT_EMISSION_FACTOR_BIOGENIC_CONTENT, technicalMessage, context, suggestions);
31
+ this.name = 'InconsistentEmissionFactorBiogenicContentError';
32
+ }
33
+ static create(biogenicContent, declaredSpecies, forbiddenSpecies, missingSpecies) {
34
+ return new InconsistentEmissionFactorBiogenicContentError(biogenicContent, declaredSpecies, forbiddenSpecies, missingSpecies);
35
+ }
36
+ logError() {
37
+ return `${this.name}: ${this.technicalMessage}`;
38
+ }
39
+ }
40
+ exports.InconsistentEmissionFactorBiogenicContentError = InconsistentEmissionFactorBiogenicContentError;
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.InvalidBiogenicContentError = void 0;
4
+ const CodedRootError_1 = require("../../../../shared/domain/exceptions/CodedRootError");
5
+ const ErrorCode_1 = require("../../../../shared/domain/enums/ErrorCode");
6
+ class InvalidBiogenicContentError extends CodedRootError_1.CodedRootError {
7
+ constructor(receivedValue, validValues) {
8
+ const validValuesList = validValues.join(', ');
9
+ const technicalMessage = `Invalid biogenic content value '${receivedValue}': must be one of ${validValuesList}.`;
10
+ const context = {
11
+ receivedValue,
12
+ validValues,
13
+ validValuesList,
14
+ timestamp: new Date().toISOString(),
15
+ };
16
+ const suggestions = [
17
+ `Use one of the valid biogenic content values: ${validValuesList}`,
18
+ 'Use NONE for fossil fuels, grid electricity, refrigerants and industrial processes',
19
+ 'Use FULL for biomass, organic waste and wastewater',
20
+ 'Use PARTIAL for fuels blended with biofuels',
21
+ ];
22
+ super(ErrorCode_1.ErrorCode.INVALID_BIOGENIC_CONTENT, technicalMessage, context, suggestions);
23
+ this.name = 'InvalidBiogenicContentError';
24
+ }
25
+ static create(receivedValue, validValues) {
26
+ return new InvalidBiogenicContentError(receivedValue, validValues);
27
+ }
28
+ logError() {
29
+ return `${this.name}: ${this.technicalMessage}`;
30
+ }
31
+ }
32
+ exports.InvalidBiogenicContentError = InvalidBiogenicContentError;
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EmissionFactorBiogenicContent = void 0;
4
+ const String_1 = require("../../../../shared/domain/value-objects/String");
5
+ const BiogenicContent_1 = require("../enums/BiogenicContent");
6
+ const InvalidBiogenicContentError_1 = require("../exceptions/InvalidBiogenicContentError");
7
+ class EmissionFactorBiogenicContent extends String_1.String {
8
+ constructor(value, skipDomainValidation) {
9
+ super(value, skipDomainValidation, EmissionFactorBiogenicContent.PROPERTY_NAME);
10
+ if (skipDomainValidation === false) {
11
+ EmissionFactorBiogenicContent.validateBiogenicContent(value);
12
+ }
13
+ }
14
+ static create(value) {
15
+ String_1.String.guardAgainstEmptyValue(value, EmissionFactorBiogenicContent.PROPERTY_NAME);
16
+ String_1.String.guardAgainstInvalidType(value, EmissionFactorBiogenicContent.PROPERTY_NAME);
17
+ return new EmissionFactorBiogenicContent(value, false);
18
+ }
19
+ static fromPrimitives(primitive) {
20
+ return new EmissionFactorBiogenicContent(primitive, true);
21
+ }
22
+ /**
23
+ * Valida que el valor sea un contenido biogénico soportado.
24
+ */
25
+ static validateBiogenicContent(value) {
26
+ if (!EmissionFactorBiogenicContent.VALID_BIOGENIC_CONTENTS.includes(value)) {
27
+ throw InvalidBiogenicContentError_1.InvalidBiogenicContentError.create(value, EmissionFactorBiogenicContent.VALID_BIOGENIC_CONTENTS);
28
+ }
29
+ }
30
+ /**
31
+ * Obtiene los contenidos biogénicos válidos.
32
+ */
33
+ static getValidBiogenicContents() {
34
+ return Object.freeze([...EmissionFactorBiogenicContent.VALID_BIOGENIC_CONTENTS]);
35
+ }
36
+ /**
37
+ * Verifica si un valor es un contenido biogénico válido.
38
+ */
39
+ static isValidBiogenicContent(value) {
40
+ return EmissionFactorBiogenicContent.VALID_BIOGENIC_CONTENTS.includes(value);
41
+ }
42
+ isNone() {
43
+ return this.value === BiogenicContent_1.BiogenicContent.NONE;
44
+ }
45
+ isFull() {
46
+ return this.value === BiogenicContent_1.BiogenicContent.FULL;
47
+ }
48
+ isPartial() {
49
+ return this.value === BiogenicContent_1.BiogenicContent.PARTIAL;
50
+ }
51
+ toPrimitives() {
52
+ return this.value;
53
+ }
54
+ toEnum() {
55
+ return this.value;
56
+ }
57
+ }
58
+ exports.EmissionFactorBiogenicContent = EmissionFactorBiogenicContent;
59
+ EmissionFactorBiogenicContent.PROPERTY_NAME = 'biogenicContent';
60
+ EmissionFactorBiogenicContent.VALID_BIOGENIC_CONTENTS = Object.values(BiogenicContent_1.BiogenicContent);
@@ -50,6 +50,8 @@ class EmissionFactorGreenhouseGasValues extends ValueObject_1.ValueObject {
50
50
  EmissionFactorGreenhouseGasValues.guardAgainstInvalidCategory(value.greenhouseGasCategory, `${propertyName}.greenhouseGasCategory`);
51
51
  // Normaliza + valida el código de especie (lanza si el formato es inválido).
52
52
  GreenhouseGasSpecies_1.GreenhouseGasSpecies.create(value.greenhouseGasSpecies);
53
+ // CO2 / CH4 / N2O solo aceptan sus especies estándar (p.ej. nada de `CH4` a secas).
54
+ GreenhouseGasSpecies_1.GreenhouseGasSpecies.guardAgainstCategoryMismatch(value.greenhouseGasCategory, value.greenhouseGasSpecies, `${propertyName}.greenhouseGasSpecies`);
53
55
  EmissionFactorGreenhouseGasValues.guardAgainstInvalidCountryValues(value.countryValues, `${propertyName}.countryValues`);
54
56
  EmissionFactorGreenhouseGasValues.guardAgainstInvalidUnit(value.unit, `${propertyName}.unit`);
55
57
  EmissionFactorGreenhouseGasValues.guardAgainstInvalidDataSource(value.dataSource, `${propertyName}.dataSource`);
@@ -46,6 +46,8 @@ class GlobalWarmingPotentialGreenhouseGasPotentials extends ValueObject_1.ValueO
46
46
  GlobalWarmingPotentialGreenhouseGasPotentials.guardAgainstInvalidCategory(value.greenhouseGasCategory, `${propertyName}.greenhouseGasCategory`);
47
47
  // Normaliza + valida el código de especie (lanza si el formato es inválido).
48
48
  GreenhouseGasSpecies_1.GreenhouseGasSpecies.create(value.greenhouseGasSpecies);
49
+ // CO2 / CH4 / N2O solo aceptan sus especies estándar (p.ej. nada de `CH4` a secas).
50
+ GreenhouseGasSpecies_1.GreenhouseGasSpecies.guardAgainstCategoryMismatch(value.greenhouseGasCategory, value.greenhouseGasSpecies, `${propertyName}.greenhouseGasSpecies`);
49
51
  GlobalWarmingPotentialGreenhouseGasPotentials.guardAgainstInvalidPotentialValue(value.potentialValue, `${propertyName}.potentialValue`);
50
52
  }
51
53
  static guardAgainstInvalidCategory(category, propertyName) {
@@ -136,7 +136,7 @@ var ErrorCode;
136
136
  ErrorCode["INVALID_FORMULA"] = "CBX-EMC-003";
137
137
  ErrorCode["JOB_NOT_FOUND"] = "CBX-EMC-004";
138
138
  ErrorCode["JOB_ALREADY_RUNNING"] = "CBX-EMC-005";
139
- // Emission Calculation Formulas Errors (CBX-EMC-006 to CBX-EMC-013)
139
+ // Emission Calculation Formulas Errors (CBX-EMC-006 to CBX-EMC-015)
140
140
  ErrorCode["INVALID_CALCULATION_VARIABLE_ACTIVITY_DATA_CONDITIONS_FOR_STRATEGY"] = "CBX-EMC-006";
141
141
  ErrorCode["INVALID_CALCULATION_VARIABLE_RESOLUTION_STRATEGY"] = "CBX-EMC-007";
142
142
  ErrorCode["DUPLICATE_GREENHOUSE_GAS"] = "CBX-EMC-008";
@@ -145,6 +145,8 @@ var ErrorCode;
145
145
  ErrorCode["UNAUTHORIZED_FORMULA_CREATION_ROLE"] = "CBX-EMC-011";
146
146
  ErrorCode["INVALID_IPCC_CODE"] = "CBX-EMC-012";
147
147
  ErrorCode["INVALID_METHODOLOGICAL_TIER"] = "CBX-EMC-013";
148
+ ErrorCode["INVALID_BIOGENIC_CONTENT"] = "CBX-EMC-014";
149
+ ErrorCode["INCONSISTENT_EMISSION_FACTOR_BIOGENIC_CONTENT"] = "CBX-EMC-015";
148
150
  // Emission Calculation Results Errors (CBX-ECR-XXX)
149
151
  ErrorCode["UNKNOWN_GREENHOUSE_GAS_CATEGORY"] = "CBX-ECR-001";
150
152
  // Reporting Errors (CBX-RPT-XXX)
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StandardGreenhouseGasSpecies = void 0;
4
+ /**
5
+ * Standard greenhouse gas species: the codes the system knows and gives meaning to.
6
+ * Any other species (refrigerants, blends, SF6, NF3...) is still accepted as free text
7
+ * by `GreenhouseGasSpecies`, but only under a category that has no standard species
8
+ * (HFC, PFC, SF6, NF3, HCFC, OTHER).
9
+ *
10
+ * Biogenic accounting (GHG Protocol Corporate Standard cap. 9; ISO 14064-1:2018 §9.3.1):
11
+ * only `CO2-BIOGENIC` stays outside the inventory total; `CH4-NON-FOSSIL` counts with its
12
+ * own potential (IPCC AR6: 27.0 vs 29.8 for fossil methane).
13
+ */
14
+ var StandardGreenhouseGasSpecies;
15
+ (function (StandardGreenhouseGasSpecies) {
16
+ /**
17
+ * Fossil carbon dioxide
18
+ */
19
+ StandardGreenhouseGasSpecies["CO2"] = "CO2";
20
+ /**
21
+ * Carbon dioxide from biomass / biofuel combustion: informational item outside the total
22
+ */
23
+ StandardGreenhouseGasSpecies["CO2_BIOGENIC"] = "CO2-BIOGENIC";
24
+ /**
25
+ * Methane of fossil origin
26
+ */
27
+ StandardGreenhouseGasSpecies["CH4_FOSSIL"] = "CH4-FOSSIL";
28
+ /**
29
+ * Methane of non-fossil origin (biomass, waste, wastewater): counts towards the total
30
+ */
31
+ StandardGreenhouseGasSpecies["CH4_NON_FOSSIL"] = "CH4-NON-FOSSIL";
32
+ /**
33
+ * Nitrous oxide
34
+ */
35
+ StandardGreenhouseGasSpecies["N2O"] = "N2O";
36
+ })(StandardGreenhouseGasSpecies || (exports.StandardGreenhouseGasSpecies = StandardGreenhouseGasSpecies = {}));
@@ -3,18 +3,23 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.GreenhouseGasSpecies = void 0;
4
4
  const String_1 = require("./String");
5
5
  const InvalidPropertyValueError_1 = require("../exceptions/InvalidPropertyValueError");
6
+ const GreenhouseGasCategory_1 = require("../enums/GreenhouseGasCategory");
7
+ const StandardGreenhouseGasSpecies_1 = require("../enums/StandardGreenhouseGasSpecies");
6
8
  /**
7
9
  * Código canónico de la especie de gas de efecto invernadero (p.ej. `CO2`, `CH4-FOSSIL`,
8
10
  * `R-410A`, `HFC-134A`). La especie es la llave real con la que se cruzan EmissionFactor y
9
11
  * GlobalWarmingPotential: por eso se normaliza al ingresar (trim + colapsar espacios + UPPERCASE)
10
12
  * para que un mismo refrigerante escrito con espacios/casing distintos matchee siempre igual.
11
- * La categoría (GreenhouseGasCategory) viaja al lado; aquí no se valida coherencia química
12
- * especie↔categoría (decisión de diseño: validación permisiva, match por especie).
13
+ *
14
+ * Especies estándar (`StandardGreenhouseGasSpecies`): `CO2`, `CO2-BIOGENIC`, `CH4-FOSSIL`,
15
+ * `CH4-NON-FOSSIL`, `N2O`. Las categorías CO2, CH4 y N2O SOLO aceptan sus especies estándar
16
+ * (`guardAgainstCategoryMismatch`); el resto de categorías (HFC, PFC, SF6, NF3, HCFC, OTHER)
17
+ * acepta texto libre (refrigerantes, mezclas).
13
18
  *
14
19
  * CO₂ biogénico: el CO₂ liberado al quemar biomasa o biocombustibles se reporta por separado,
15
20
  * fuera de los alcances y del total del inventario (GHG Protocol Corporate Standard cap. 9;
16
21
  * ISO 14064-1:2018 §9.3.1). Se modela como la especie `CO2-BIOGENIC` de la categoría CO2
17
- * (paralela a `CH4-BIOGENIC`, que SÍ cuenta en el total con su PCG). Este VO es el único lugar
22
+ * (paralela a `CH4-NON-FOSSIL`, que SÍ cuenta en el total con su PCG). Este VO es el único lugar
18
23
  * que conoce esa convención: toda suma de inventario pregunta `isBiogenicCarbonDioxide`.
19
24
  */
20
25
  class GreenhouseGasSpecies extends String_1.String {
@@ -39,6 +44,19 @@ class GreenhouseGasSpecies extends String_1.String {
39
44
  String_1.String.guardAgainstInvalidType(value, GreenhouseGasSpecies.PROPERTY_NAME);
40
45
  return value.trim().replace(/\s+/g, ' ').toUpperCase();
41
46
  }
47
+ /**
48
+ * True si la especie es una de las estándar (`StandardGreenhouseGasSpecies`).
49
+ */
50
+ static isStandard(value) {
51
+ return GreenhouseGasSpecies.STANDARD_SPECIES_CATEGORIES.has(GreenhouseGasSpecies.normalize(value));
52
+ }
53
+ /**
54
+ * Especies estándar de una categoría (vacío si la categoría acepta texto libre).
55
+ */
56
+ static standardSpeciesOf(category) {
57
+ return Object.values(StandardGreenhouseGasSpecies_1.StandardGreenhouseGasSpecies)
58
+ .filter((species) => GreenhouseGasSpecies.STANDARD_SPECIES_CATEGORIES.get(species) === category);
59
+ }
42
60
  /**
43
61
  * True para la especie `CO2-BIOGENIC` (en cualquier casing/espaciado): CO₂ que NO cuenta en
44
62
  * el total del inventario y se reporta como partida informativa.
@@ -46,9 +64,46 @@ class GreenhouseGasSpecies extends String_1.String {
46
64
  static isBiogenicCarbonDioxide(value) {
47
65
  return GreenhouseGasSpecies.normalize(value) === GreenhouseGasSpecies.BIOGENIC_CARBON_DIOXIDE;
48
66
  }
67
+ /**
68
+ * True para la especie `CH4-NON-FOSSIL`: metano de origen biogénico que SÍ cuenta en el total.
69
+ */
70
+ static isNonFossilMethane(value) {
71
+ return GreenhouseGasSpecies.normalize(value) === StandardGreenhouseGasSpecies_1.StandardGreenhouseGasSpecies.CH4_NON_FOSSIL;
72
+ }
73
+ /**
74
+ * True para las especies de carbono biogénico (`CO2-BIOGENIC`, `CH4-NON-FOSSIL`): las que un
75
+ * factor con contenido biogénico declara y una fórmula sobre ese factor no puede omitir.
76
+ */
77
+ static isBiogenic(value) {
78
+ return GreenhouseGasSpecies.isBiogenicCarbonDioxide(value) || GreenhouseGasSpecies.isNonFossilMethane(value);
79
+ }
80
+ /**
81
+ * Las categorías con especies estándar (CO2, CH4, N2O) solo aceptan esas especies, y cada
82
+ * especie estándar solo su propia categoría. Evita, p.ej., un `CH4` a secas (¿fósil o no fósil?).
83
+ */
84
+ static guardAgainstCategoryMismatch(category, species, propertyName) {
85
+ const normalizedSpecies = GreenhouseGasSpecies.normalize(species);
86
+ const standardCategory = GreenhouseGasSpecies.STANDARD_SPECIES_CATEGORIES.get(normalizedSpecies);
87
+ if (standardCategory !== undefined && standardCategory !== category) {
88
+ throw InvalidPropertyValueError_1.InvalidPropertyValueError.create(propertyName, `category ${standardCategory} for standard species ${normalizedSpecies}`, `"${category}"`);
89
+ }
90
+ const standardSpecies = GreenhouseGasSpecies.standardSpeciesOf(category);
91
+ if (standardSpecies.length > 0 && standardCategory === undefined) {
92
+ throw InvalidPropertyValueError_1.InvalidPropertyValueError.create(propertyName, `one of the standard species of category ${category} (${standardSpecies.join(', ')})`, `"${normalizedSpecies}"`);
93
+ }
94
+ }
49
95
  isBiogenicCarbonDioxide() {
50
96
  return GreenhouseGasSpecies.isBiogenicCarbonDioxide(this.value);
51
97
  }
98
+ isNonFossilMethane() {
99
+ return GreenhouseGasSpecies.isNonFossilMethane(this.value);
100
+ }
101
+ isBiogenic() {
102
+ return GreenhouseGasSpecies.isBiogenic(this.value);
103
+ }
104
+ isStandard() {
105
+ return GreenhouseGasSpecies.isStandard(this.value);
106
+ }
52
107
  static guardAgainstInvalidSpecies(value) {
53
108
  String_1.String.guardAgainstEmptyValue(value, GreenhouseGasSpecies.PROPERTY_NAME);
54
109
  if (!GreenhouseGasSpecies.SPECIES_REGEX.test(value)) {
@@ -61,7 +116,15 @@ class GreenhouseGasSpecies extends String_1.String {
61
116
  }
62
117
  exports.GreenhouseGasSpecies = GreenhouseGasSpecies;
63
118
  GreenhouseGasSpecies.PROPERTY_NAME = 'greenhouseGasSpecies';
64
- GreenhouseGasSpecies.BIOGENIC_CARBON_DIOXIDE = 'CO2-BIOGENIC';
119
+ GreenhouseGasSpecies.BIOGENIC_CARBON_DIOXIDE = StandardGreenhouseGasSpecies_1.StandardGreenhouseGasSpecies.CO2_BIOGENIC;
65
120
  // Letras, dígitos, espacio, guion y barra: cubre ASHRAE (R-410A) y químicos/mezclas
66
121
  // (HFC-134A, MEZCLA HFC 365MFC/HFC 227EA, POLYCOLD 1102HC).
67
122
  GreenhouseGasSpecies.SPECIES_REGEX = /^[A-Z0-9][A-Z0-9 /-]*$/;
123
+ // Categoría de cada especie estándar. Una categoría presente aquí solo acepta sus especies estándar.
124
+ GreenhouseGasSpecies.STANDARD_SPECIES_CATEGORIES = new Map([
125
+ [StandardGreenhouseGasSpecies_1.StandardGreenhouseGasSpecies.CO2, GreenhouseGasCategory_1.GreenhouseGasCategory.CO2],
126
+ [StandardGreenhouseGasSpecies_1.StandardGreenhouseGasSpecies.CO2_BIOGENIC, GreenhouseGasCategory_1.GreenhouseGasCategory.CO2],
127
+ [StandardGreenhouseGasSpecies_1.StandardGreenhouseGasSpecies.CH4_FOSSIL, GreenhouseGasCategory_1.GreenhouseGasCategory.CH4],
128
+ [StandardGreenhouseGasSpecies_1.StandardGreenhouseGasSpecies.CH4_NON_FOSSIL, GreenhouseGasCategory_1.GreenhouseGasCategory.CH4],
129
+ [StandardGreenhouseGasSpecies_1.StandardGreenhouseGasSpecies.N2O, GreenhouseGasCategory_1.GreenhouseGasCategory.N2O],
130
+ ]);