@carbonbox/domain
Una librería de capa de dominio pura y completa para Sistema de Gestión de Huella de Carbono siguiendo principios de Domain-Driven Design (DDD) y patrones de Arquitectura Limpia.
🌱 Descripción General
Esta librería proporciona la lógica de dominio central para un sistema completo de gestión de huella de carbono con 644 archivos TypeScript organizados en 8 contextos de dominio principales:
Tipos de Huella de Carbono
- 🏢 Huellas de Carbono Corporativas - Seguimiento de emisiones organizacionales
- 📦 Huellas de Carbono de Productos - Análisis de emisiones del ciclo de vida del producto
- 🎪 Huellas de Carbono de Eventos - Gestión de emisiones específicas de eventos
Módulos Principales del Dominio
- 📋 Activity Data Collection - Sistema de recopilación dinámica de datos con formularios configurables
- ⚙️ Carbon Footprint Configurations - Gestión de configuraciones para los tres tipos de huella
- 🏭 Company Resources - Recursos organizacionales (eventos, instalaciones, productos)
- 🧮 Emission Calculation Formulas - Motor matemático de fórmulas con variables y factores
- 🔄 Emission Calculation Process - Orquestación de flujos de trabajo y gestión de trabajos
- 📊 Emission Calculation Results - Sistema de almacenamiento y agregación de resultados
- 👥 Stakeholders - Gestión integral de stakeholders basada en roles
- 🔧 Shared Domain - Componentes transversales y fundacionales
🏗️ Arquitectura
Principios Fundamentales
- Domain-Driven Design (DDD) - Modelos de dominio ricos con reglas de negocio
- Arquitectura Limpia - Capa de dominio pura sin dependencias externas
- Programación Funcional - Patrón Either/Result para manejo de errores
- Principios SOLID - Segregación de interfaces e inversión de dependencias
- Seguridad de Tipos - TypeScript estricto con verificación de tipos integral
Patrones Arquitectónicos Clave
- Aggregate Roots - Todas las entidades extienden
AggregateRoot<T> - Value Objects - Objetos inmutables con validación
- Factory Methods - Métodos estáticos
create()yfromPrimitives() - Patrón Either - Manejo funcional de errores con
Either<L,R> - Conversión de Primitivos - Soporte de serialización bidireccional
� Estructura de Carpetas
El proyecto está organizado siguiendo los principios de Domain-Driven Design con una separación clara entre código fuente y archivos compilados:
carbonbox-domain/
├── src/ # Código fuente TypeScript
│ ├── carbonbox/ # Contextos de dominio principales
│ │ ├── activity-data-collection/ # Sistema de recopilación de datos
│ │ ├── carbon-footprint-configurations/ # Configuraciones de huella de carbono
│ │ ├── company-resources/ # Recursos organizacionales
│ │ ├── emission-calculation-formulas/ # Fórmulas y factores de emisión
│ │ ├── emission-calculation-process/ # Procesos de cálculo
│ │ ├── emission-calculation-results/ # Resultados y agregaciones
│ │ ├── purchase-management-system/ # Sistema de gestión de compras
│ │ ├── shared/ # Componentes compartidos
│ │ └── stakeholders/ # Gestión de stakeholders
│ └── main/
│ └── index.ts # Punto de entrada principal
├── build/ # Archivos JavaScript compilados
│ ├── carbonbox/ # Estructura compilada
│ │ ├── activity-data-collection/
│ │ │ ├── activity-data-submissions/
│ │ │ ├── collection-fields/
│ │ │ ├── conditional-logic/
│ │ │ ├── contextual-labels/
│ │ │ ├── dynamic-forms/
│ │ │ └── stakeholder-adaptations/
│ │ ├── calculation-engine/
│ │ │ ├── GreenhouseGasEnum.js
│ │ │ ├── IPCCMethodologyEnum.js
│ │ │ ├── IPCCTierEnum.js
│ │ │ ├── VariableTypeEnum.js
│ │ │ ├── calculation-method/
│ │ │ ├── emission-factor/
│ │ │ ├── equation/
│ │ │ ├── equation-variable/
│ │ │ └── shared/
│ │ ├── carbon-footprint/
│ │ │ └── corporate/
│ │ ├── carbon-footprint-configurations/
│ │ │ ├── corporate/
│ │ │ ├── corporate-config/
│ │ │ ├── corporate-configuration/
│ │ │ ├── corporate-configurations/
│ │ │ ├── event/
│ │ │ ├── event-config/
│ │ │ ├── event-configuration/
│ │ │ ├── event-configurations/
│ │ │ ├── product/
│ │ │ ├── product-config/
│ │ │ ├── product-configuration/
│ │ │ ├── product-configurations/
│ │ │ └── shared/
│ │ ├── company-resources/
│ │ │ ├── event/
│ │ │ ├── events/
│ │ │ ├── facilities/
│ │ │ ├── facility/
│ │ │ ├── product/
│ │ │ └── products/
│ │ ├── data-collection/
│ │ │ ├── domain/
│ │ │ ├── emission-calculation/
│ │ │ ├── input-field-template/
│ │ │ └── shared/
│ │ ├── emission-calculation-engine/
│ │ │ └── domain/
│ │ ├── emission-calculation-formulas/
│ │ │ ├── calculation-variables/
│ │ │ ├── domain/
│ │ │ ├── emission-factors/
│ │ │ ├── global-warming-potentials/
│ │ │ └── shared/
│ │ ├── emission-calculation-process/
│ │ │ ├── calculation-jobs/
│ │ │ ├── calculation-processes/
│ │ │ └── calculation-workflows/
│ │ ├── emission-calculation-results/
│ │ │ ├── emission-aggregations/
│ │ │ ├── emission-calculations/
│ │ │ └── ghg-emission-results/
│ │ ├── emission-formula-engine/
│ │ │ ├── domain/
│ │ │ ├── emission-factor/
│ │ │ ├── formula-variable/
│ │ │ ├── global-warming-potential/
│ │ │ └── shared/
│ │ ├── plan/
│ │ │ ├── discount/
│ │ │ └── domain/
│ │ ├── plugins/
│ │ │ ├── IPluginPrimitives.js
│ │ │ ├── Plugin.js
│ │ │ └── users/
│ │ ├── pricing/
│ │ ├── purchase-management-system/
│ │ ├── purchasing/
│ │ ├── services/
│ │ ├── shared/
│ │ ├── stakeholders/
│ │ └── users/
│ ├── main/
│ │ └── index.js
│ └── types/ # Definiciones de tipos TypeScript
│ ├── carbonbox/
│ └── main/
├── package.json # Configuración del paquete
├── tsconfig.json # Configuración de TypeScript
├── tsconfig.prod.json # Configuración de producción
└── README.md # Documentación del proyecto
Organización por Contextos de Dominio
Cada contexto de dominio sigue una estructura DDD consistente:
domain/- Entidades, Value Objects, agregados y reglas de negocioentities/- Entidades del dominio con lógica de negociovalue-objects/- Objetos de valor inmutablesshared/- Componentes compartidos dentro del contextotypes/- Definiciones de tipos específicos del contexto
Convenciones de Nomenclatura
- Archivos de Interfaz: Prefijo
I(ej.IPurchaseContract.ts) - Value Objects: Nombre descriptivo del concepto (ej.
PurchaseContractCode.ts) - Entidades: Nombre del agregado (ej.
PurchaseContract.ts) - Enums: Sufijo
Enum(ej.GreenhouseGasEnum.ts)
�📦 Instalación
npm install @carbonbox/domain
🚀 Inicio Rápido
import {
CorporateCarbonFootprintConfiguration,
Either,
DomainError
} from '@carbonbox/domain';
// Crear una configuración de huella de carbono corporativa
const result: Either<DomainError, CorporateCarbonFootprintConfiguration> =
CorporateCarbonFootprintConfiguration.create({
configurationCode: 'CORP-001',
configurationName: 'Evaluación Corporativa Anual 2024',
carbonFootprintObjective: 'CARBON_NEUTRALITY',
reportingStandard: 'GHG_PROTOCOL',
collectionPeriod: 'ANNUAL',
// ... otras propiedades requeridas
});
// Manejar el resultado funcionalmente
result.fold(
(error) => console.error('Error al crear configuración:', error.message),
(config) => console.log('Configuración creada:', config.toPrimitives())
);
🏛️ Estructura Detallada del Dominio
📋 1. Activity Data Collection
Propósito: Sistema completo de recopilación dinámica de datos con formularios configurables.
// Crear un formulario dinámico con lógica condicional
const form = DynamicForm.create({
formCode: 'SCOPE1_EMISSIONS',
fields: [
CollectionField.create({
fieldType: 'NUMERIC_INPUT',
isRequired: true,
validationRules: ['POSITIVE_NUMBER']
})
],
conditionalRules: [
ConditionalFieldRule.create({
triggerField: 'emissionSource',
action: 'SHOW_FIELD',
targetField: 'fuelType'
})
]
});
⚙️ 2. Carbon Footprint Configurations
Propósito: Configuración y gestión de los tres tipos principales de huella de carbono.
Configuración Corporativa
const corporateConfig = CorporateCarbonFootprintConfiguration.create({
configurationCode: 'CORP-2024',
reportingStandard: 'ISO_14064_1',
corporateSegmentConfigurations: [
CorporateSegmentConfiguration.create({
segment: CorporateSegment.create({
segmentCode: 'SCOPE_1',
segmentName: 'Emisiones Directas'
})
})
]
});
🏭 3. Company Resources
Propósito: Gestión de recursos organizacionales.
// Gestión de instalaciones con alcance operacional
const facility = Facility.create({
facilityCode: 'FAC-001',
commercialBranchName: 'Oficina Principal',
operationalScope: 'OPERATIONAL_CONTROL',
address: Address.create({
street: 'Carrera 7 #100-50',
city: 'Bogotá',
countryCode: 'CO'
})
});
🧮 4. Emission Calculation Formulas
Propósito: Motor matemático de fórmulas con variables y factores de emisión.
const formula = EmissionCalculationFormula.create({
formulaCode: 'COMBUSTION_CO2',
expression: 'activityData * emissionFactor * oxidationFactor',
applicableGreenhouseGases: ['CO2'],
variables: [
CalculationVariable.create({
variableName: 'activityData',
unit: 'LITERS',
dataType: 'NUMERIC'
})
],
emissionFactor: EmissionFactor.create({
value: 2.31,
unit: 'KG_CO2_PER_LITER'
})
});
🔄 5. Emission Calculation Process
Propósito: Orquestación de flujos de trabajo y gestión de trabajos de cálculo.
const workflow = CalculationWorkflow.create({
workflowCode: 'ANNUAL_CALCULATION',
trigger: 'SCHEDULED',
status: 'ACTIVE',
processes: [
CalculationProcess.create({
processCode: 'SCOPE1_CALC',
priority: 'HIGH',
jobs: [
CalculationJob.create({
jobType: 'EMISSION_CALCULATION',
status: 'PENDING'
})
]
})
]
});
📊 6. Emission Calculation Results
Propósito: Almacenamiento y agregación de resultados de cálculos.
const result = EmissionCalculation.create({
calculationId: 'CALC-001',
emissionValue: 1500.25,
unit: 'KG_CO2_EQ',
uncertaintyRange: UncertaintyRange.create({
lowerBound: 1425.24,
upperBound: 1575.26
}),
ghgBreakdown: GHGBreakdown.create({
co2: 1450.0,
ch4: 50.25,
n2o: 0.0
})
});
👥 7. Stakeholders
Propósito: Sistema integral de gestión de stakeholders con jerarquía de roles.
// Jerarquía: Host → Manager → Coordinator → Client
const client = CarbonClient.create({
stakeholderCode: 'CLI-001',
businessName: 'Empresa Sostenible S.A.S.',
taxIdentification: ColombiaNIT.create('900123456-7'),
businessScale: 'LARGE_ENTERPRISE',
supervisionHierarchy: {
coordinator: 'COORD-001',
manager: 'MGR-001'
}
});
🔧 8. Shared Domain
Propósito: Componentes transversales y fundacionales.
// Manejo funcional de errores con Either
const operation = Either.fromTryCatch(
() => processEmissionData(data),
(error) => new InvalidDataError(error.message)
);
operation
.map(result => result.toPrimitives())
.fold(
error => handleError(error),
success => processSuccess(success)
);
🌍 Características del Dominio de Negocio
Cumplimiento de Estándares Internacionales
- ✅ Protocolo GHG - Soporte completo para emisiones Alcance 1, 2 y 3
- ✅ ISO 14064-1 - Estándares internacionales de huella de carbono
- ✅ 7 Gases de Efecto Invernadero - CO2, CH4, N2O, HFCs, PFCs, SF6, NF3
- ✅ Reportes Híbridos - Combinación de estándares según necesidades
Regulaciones Colombianas
- 🇨🇴 Validación de NIT - Validación completa con dígito de verificación
- 🇨🇴 Formatos Tributarios - Soporte para identificación tributaria colombiana
- 🇨🇴 Escalas de Negocio - Clasificación según normativa colombiana
Arquitectura Multi-tenant
- 👑 Jerarquía de Roles - Host → Manager → Coordinator → Client
- 🔐 Control de Permisos - Sistema granular de permisos por rol
- 🏢 Supervisión - Líneas claras de reporte y supervisión
- ⚖️ Segregación de Datos - Aislamiento por cliente de carbono
Sistema de Recopilación Dinámica
- 📝 Formularios Configurables - Generación dinámica de formularios
- 🔀 Lógica Condicional - Campos que aparecen según condiciones
- 🎯 Adaptaciones por Stakeholder - Formularios personalizados por rol
- 📈 Seguimiento de Incertidumbre - Manejo de calidad y incertidumbre de datos
🛠️ Desarrollo
Prerrequisitos
- Node.js 18.x o 20.x
- TypeScript 5.x
- npm
Configuración del Entorno
# Clonar el repositorio
git clone https://github.com/CarbonBoxTech/carbonbox-domain.git
cd carbonbox-domain
# Instalar dependencias
npm ci
# Construir el proyecto
npm run build
# Ejecutar linting
npm run lint
# Corregir problemas de linting automáticamente
npm run lint:fix
# Modo desarrollo con observación
npm run tsc
Scripts Disponibles
| Script | Descripción |
|---|---|
npm run build | Compilar TypeScript a JavaScript |
npm run tsc | Iniciar compilador TypeScript en modo observación |
npm run lint | Ejecutar ESLint en archivos fuente |
npm run lint:fix | Auto-corregir problemas de ESLint |
🧪 Testing
La infraestructura de pruebas está configurada para:
- Jest - Framework de testing principal
- Cypress - Pruebas end-to-end (configuradas pero no implementadas)
- Estructura de pruebas - Directorios preparados para implementación
# Estructura preparada para testing
__test__/ # Pruebas unitarias
cypress/ # Pruebas E2E
jest.config.ts # Configuración Jest
cypress.config.ts # Configuración Cypress
📐 Estándares de Código
Configuración ESLint
- Airbnb TypeScript - Configuración estricta de código
- Import Organization - Organización automática de imports
- No Unused Variables - Política estricta de variables no utilizadas
- Consistent Formatting - Formato consistente en todo el código
Configuración TypeScript
{
"target": "ES2021",
"module": "commonjs",
"strict": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"declaration": true,
"declarationMap": true,
"outDir": "./build"
}
🔄 CI/CD y Automatización
Flujos de Trabajo Automatizados
Pipeline de Integración Continua
# .github/workflows/ci.yml
- ESLint validation
- TypeScript compilation
- Build verification
- Matrix testing (Node.js 18.x, 20.x)
Pipeline de Release Automatizado
# .github/workflows/release.yml
- Full CI pipeline execution
- GitHub release creation
- NPM package publication
Proceso de Release
# 1. Actualizar versión
npm version patch|minor|major
# 2. Push cambios y tags
git push origin main --tags
# 3. GitHub Actions se encarga del resto automáticamente
# - Ejecuta CI completo
# - Crea release en GitHub
# - Publica a NPM
🤝 Contribuir
Flujo de Trabajo
- Fork del repositorio
- Crear rama de característica:
git checkout -b feature/nueva-caracteristica - Seguir estándares de código y ejecutar linting
- Commit de cambios:
git commit -m 'Agregar nueva característica' - Push a la rama:
git push origin feature/nueva-caracteristica - Abrir Pull Request
Guías de Desarrollo
Principios de DDD
- Usar Factory Methods para creación de entidades
- Mantener Value Objects inmutables
- Implementar Aggregate Roots correctamente
- Seguir patrón Either para manejo de errores
Estándares de Código
// ✅ Correcto - Usar factory methods
const entity = MyEntity.create(props);
// ❌ Incorrecto - Constructor directo
const entity = new MyEntity(props);
// ✅ Correcto - Manejo de errores con Either
const result: Either<DomainError, Success> = operation();
// ❌ Incorrecto - Lanzar excepciones
throw new Error('Something went wrong');
📊 Métricas del Proyecto
- 📁 644 Archivos TypeScript - Cobertura completa del dominio
- 🏗️ 8 Contextos de Dominio - Separación clara por responsabilidades
- 🔍 0 Dependencias Externas - Capa de dominio pura
- ⚡ TypeScript Estricto - Máxima seguridad de tipos
- 🎯 Patrón DDD - Implementación completa de Domain-Driven Design
📄 Licencia
Este proyecto está licenciado bajo la Licencia ISC - ver el archivo LICENSE para detalles.
👥 Autores
- Manuel Rivera - Desarrollo inicial - [email protected]
🔗 Enlaces
Hecho con ❤️ para la gestión sostenible de huella de carbono 🌱