BuildTracking es un backend en Java (Spring Boot) para gestionar el seguimiento de obra en proyectos de construcción: empleados, asistencias, participaciones, proyectos, ítems y contabilidad por proyecto.
Este repositorio contiene la implementación de las entidades principales con una arquitectura modular completa (models, dto, repositories, services, controllers) siguiendo las mejores prácticas de desarrollo empresarial.
Proveer una API REST robusta para llevar control de recursos humanos con jerarquías organizacionales, participación en proyectos, registro de asistencias, gestión de ítems, contabilidad de facturas por proyecto y consultas personalizadas. La arquitectura está diseñada con manejo de excepciones centralizado, respuestas estandarizadas y separación completa entre DTOs y entidades JPA.
- src/main/java/com/construmedicis/buildtracking
- attendance (asistencias)
- employee (empleados con jerarquía)
- participation (participaciones empleado-proyecto)
- project (proyectos de construcción)
- item (ítems de proyecto)
- invoice (facturas con contabilidad)
- assignment (reglas de asignación automática)
- util (excepciones, response handler, etc.)
Cada módulo incluye:
models: entidades JPA con relaciones (ManyToOne, OneToMany, ManyToMany)dto: DTOs para entrada y salida (evitan exponer entidades directamente y previenen referencias circulares)repository: interfaces JpaRepository con métodos de consulta personalizadosservices: interfaces yimplcon lógica de negocio y validacionescontroller: endpoints REST que usan DTOs y devuelvenResponse<T>
- Java 25
- Maven (el proyecto incluye mvnw como wrapper)
- PostgreSQL (configurado en
application.propertiesparabuild_tracking_bd)
- Compilar/ejecutar con el wrapper (Windows PowerShell):
cd c:\path\to\buildtracking
.\mvnw.cmd -DskipTests spring-boot:run- Compilar empaquetado (jar):
.\mvnw.cmd -DskipTests packageNota: todos los controladores devuelven un objeto Response<T> (status, userMessage, moreInfo, data).
- GET /api/employees
- GET /api/employees/{id}
- POST /api/employees (body: EmployeeDTO)
- DELETE /api/employees/{id}
Características especiales:
- Los empleados soportan jerarquía organizacional (manager/subordinates)
- Relación ManyToMany con proyectos
- GET /api/projects
- GET /api/projects/{id}
- POST /api/projects (body: ProjectDTO)
- DELETE /api/projects/{id}
- GET /api/participations
- GET /api/participations/{id}
- GET /api/participations/project/{projectId} (consulta todas las participaciones de un proyecto)
- POST /api/participations (body: ParticipationDTO)
- DELETE /api/participations/{id}
- GET /api/attendances
- GET /api/attendances/{id}
- GET /api/attendances/participation/{participationId} (consulta todas las asistencias de una participación)
- POST /api/attendances (body: AttendanceDTO)
- DELETE /api/attendances/{id}
- GET /api/items
- GET /api/items/{id}
- GET /api/items/project/{projectId} (ítems de un proyecto - catálogo específico) 🆕
- POST /api/items (body: ItemDTO)
- PUT /api/items/{id} (body: ItemDTO) (actualizar nombre, descripción, precio, cantidad) 🆕
- DELETE /api/items/{id}
Características especiales:
- Catálogo dinámico: Los ítems se crean automáticamente al importar facturas desde Gmail si no existen
- Vinculación inteligente: Sistema de matching que busca ítems existentes por descripción exacta o código
- Multi-proyecto: Un ítem puede asociarse a múltiples proyectos mediante relación ManyToMany
- Sincronización con facturas: Cada
InvoiceItemse vincula a unItemdel catálogo medianteitemId
- GET /api/invoices
- GET /api/invoices/{id}
- GET /api/invoices/project/{projectId} (facturas de un proyecto)
- GET /api/invoices/supplier/{supplierId} (facturas de un proveedor)
- GET /api/invoices/date-range?startDate=yyyy-MM-dd&endDate=yyyy-MM-dd (por rango de fechas)
- GET /api/invoices/pending-review?maxConfidence=70 (facturas con baja confianza en asignación)
- POST /api/invoices (body: InvoiceDTO)
- POST /api/invoices/sync-gmail?gmailLabel=Facturas/Proyecto1&after=2025/11/01&before=2025/11/30 🎯 (sincronización automática desde Gmail con rango de fechas opcional) 🆕
- PUT /api/invoices/{id}/assign-project?projectId=X (asignar proyecto manualmente)
- DELETE /api/invoices/{id}
Flujo de sincronización desde Gmail:
- Llama
POST /api/invoices/sync-gmail?gmailLabel=Facturas&after=2025/11/01&before=2025/11/30(especifica etiqueta y opcionalmente rango de fechas en formato yyyy/MM/dd) - Sistema autentica con Gmail usando OAuth 2.0 (credentials.json en src/main/resources/)
- Busca correos con esa etiqueta que tengan adjuntos en el rango de fechas especificado (si se provee)
- Descarga adjuntos:
- XMLs directos: Procesa inmediatamente
- ZIPs: Descomprime y extrae XMLs contenidos (las facturas suelen enviarse comprimidas con PDF+XML)
- Parsea cada XML (formato DIAN - facturas electrónicas Colombia) y verifica si ya existe en BD por número de factura (evita duplicados)
- Para facturas nuevas:
- Crea
Invoicecon:source=EMAIL_AUTO(todas las facturas de correo ya están pagadas)withholdingTaxywithholdingICA: BigDecimal.ZERO si no existen en XML (nunca null)
- Para cada ítem del XML:
- Busca/crea
Itemen catálogo (matching por código o descripción, sin precio - el precio está en la factura) - Crea
InvoiceItemvinculado alItemdel catálogo (aquí se guarda el precio de compra)
- Busca/crea
- Evalúa reglas de asignación automática:
- Si confianza ≥ 70%: asigna factura al proyecto y asocia items al proyecto
- Si confianza < 70%: marca para revisión manual
- Crea
- Elimina archivos temporales (ZIPs, XMLs extraídos después de procesarlos)
- Retorna estadísticas: emails procesados, facturas creadas, auto-asignadas, pendientes revisión
- GET /api/invoice-items
- GET /api/invoice-items/{id}
- GET /api/invoice-items/invoice/{invoiceId} (líneas de una factura)
- GET /api/invoice-items/item/{itemId} (facturas donde se compró un ítem)
- POST /api/invoice-items (body: InvoiceItemDTO)
- DELETE /api/invoice-items/{id}
Características especiales:
- Precios en facturas, no en catálogo: El catálogo de
ItemNO tiene precio. Los precios están enInvoiceItem(cada compra puede tener precio diferente) - Cálculo automático de totales: El servicio calcula automáticamente el total considerando subtotal, IVA y retenciones
- Asignación de confianza: Sistema de confianza (0-100%) para asignaciones automáticas de proyecto
- Todas pagadas: Las facturas en el sistema ya están pagadas (no hay estados pendientes)
- GET /api/assignment-rules
- GET /api/assignment-rules/{id}
- GET /api/assignment-rules/project/{projectId} (reglas de un proyecto)
- GET /api/assignment-rules/active (solo reglas activas ordenadas por prioridad)
- GET /api/assignment-rules/type/{ruleType} (filtrar por tipo de regla)
- POST /api/assignment-rules (body: ProjectAssignmentRuleDTO)
- POST /api/assignment-rules/evaluate (evaluar reglas para una factura)
- PUT /api/assignment-rules/{id}/toggle?isActive=true (activar/desactivar regla)
- DELETE /api/assignment-rules/{id}
Tipos de reglas disponibles:
- SUPPLIER_NIT: Asigna por NIT del proveedor (confianza: 95%)
- DATE_RANGE: Asigna por rango de fechas (confianza: 70%)
- KEYWORDS: Asigna por palabras clave en descripciones (confianza: 60-85%)
- EMPLOYEE_PARTICIPATION: Asigna si hay empleados participando en el proyecto (confianza: 75%)
- MANUAL: Siempre requiere confirmación manual
Flujo de evaluación:
- Se ordenan las reglas activas por prioridad (menor número = mayor prioridad)
- Se evalúa cada regla en orden hasta encontrar una coincidencia
- Retorna projectId, nombre, confianza y razón de la coincidencia
- Si confianza < 70%, la factura queda pendiente de revisión manual
Para que la sincronización automática funcione, necesitas configurar credenciales OAuth 2.0:
- credentials.json: Archivo de credenciales de Google Cloud Console
- Ubicación:
src/main/resources/credentials.json - Obtener en: https://console.cloud.google.com/apis/credentials
- Habilitar Gmail API en Google Cloud Console
- Ubicación:
- tokens/: Directorio para tokens de acceso (se crea automáticamente en
src/main/resources/tokens/) - Primera autenticación: Al llamar por primera vez
POST /api/invoices/sync-gmailse abrirá el navegador para autorizar - Parámetros opcionales:
after: Fecha desde (formato yyyy/MM/dd) - Ej:2025/11/01before: Fecha hasta (formato yyyy/MM/dd) - Ej:2025/11/30- Ejemplo completo:
POST /api/invoices/sync-gmail?gmailLabel=Facturas&after=2025/11/01&before=2025/11/30
NOTA: El módulo EmailConfig está deprecado. Usa directamente POST /api/invoices/sync-gmail?gmailLabel=TuEtiqueta&after=yyyy/MM/dd&before=yyyy/MM/dd
Los endpoints de EmailConfig aún funcionan pero ya no son necesarios:
- GET /api/email-config
- GET /api/email-config/{id}
- GET /api/email-config/project/{projectId}
- GET /api/email-config/auto-sync
- POST /api/email-config (body: EmailConfigDTO)
- PUT /api/email-config/{id} (body: EmailConfigDTO)
- DELETE /api/email-config/{id}
POST /api/email-config/{id}/sync(usarPOST /api/invoices/sync-gmailen su lugar)
El proyecto implementa un sistema robusto de manejo de errores y respuestas estandarizadas:
Response<T>yResponseHandler: Wrapper uniforme para todas las respuestas con estructura{status, userMessage, moreInfo, data}BusinessRuleExceptionyActionBusinessRuleException: Excepciones personalizadas para reglas de negocioCustomExceptionHandler: Manejador global de excepciones con mensajes i18n desdeexceptions.properties- Validaciones: Los servicios validan la existencia de entidades relacionadas antes de operaciones (throw exception si no existen)
El proyecto usa versionado semántico (SemVer) y está configurado con automatización de releases mediante GitHub Actions.
Versión actual: 0.0.3-SNAPSHOT (ver archivo VERSION)
Formato: MAJOR.MINOR.PATCH
- MAJOR: cambios incompatibles con versiones anteriores
- MINOR: nuevas funcionalidades retrocompatibles
- PATCH: correcciones y mejoras pequeñas
El proyecto incluye un workflow de GitHub Actions (.github/workflows/release.yml) que se activa automáticamente al crear tags con formato v*.*.* (ej: v1.0.0).
Pasos para crear un release:
- Actualizar versión en
VERSIONypom.xml:
# Editar VERSION manualmente (ej: 1.0.0)
.\mvnw.cmd versions:set -DnewVersion=1.0.0
.\mvnw.cmd -DskipTests package- Commit y crear tag:
git add VERSION pom.xml
git commit -m "chore(release): 1.0.0"
git tag -a v1.0.0 -m "Release 1.0.0"
git push origin main
git push origin v1.0.0- El workflow de GitHub Actions automáticamente:
- Compila el proyecto
- Crea el release en GitHub
- Adjunta el JAR al release
Hay una clase de prueba base; añade más tests para cubrir servicios y controladores. Puedes ejecutar:
.\mvnw.cmd testPara colaborar en el proyecto:
- Usa commits descriptivos siguiendo convenciones (ej:
feat:,fix:,chore:) - Crea PRs con descripción clara de los cambios
- Mantén la consistencia con la arquitectura existente (DTOs, Response wrapper, manejo de excepciones)
- Agrega tests para nuevas funcionalidades
- Separación de capas: Controllers → Services → Repositories
- DTOs: Evitan exponer entidades JPA y previenen referencias circulares JSON
- Response wrapper: Todas las respuestas REST usan
Response<T>para uniformidad - Validación: Los servicios validan existencia de entidades relacionadas
- i18n: Mensajes de error centralizados en
exceptions.properties - Jerarquías: Employee soporta estructura árbol (manager/subordinates)
- Consultas personalizadas: Métodos repository adicionales para queries específicas (ej:
findByProjectId)
Versión: 0.0.2-SNAPSHOT
Tecnologías: Java 25 • Spring Boot 4.0.1-SNAPSHOT • PostgreSQL • JPA/Hibernate • Lombok • Maven