Metadata-Version: 2.4
Name: orgm-bt
Version: 0.5.1
Summary: CLI for low-voltage electrical calculations, panel schedules, and HTML/PDF reports
Project-URL: Repository, https://github.com/osmargm1202/calc
Project-URL: Issues, https://github.com/osmargm1202/calc/issues
Keywords: electrical,low-voltage,NEC,panel-schedules,cli
Classifier: Environment :: Console
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Topic :: Scientific/Engineering
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Requires-Dist: jinja2>=3.1.0
Requires-Dist: weasyprint>=60.0
Requires-Dist: pillow>=11.0.0
Requires-Dist: reportlab>=4.4.4
Requires-Dist: sqlmodel>=0.0.14
Requires-Dist: alembic>=1.13.0
Requires-Dist: psycopg2-binary>=2.9.9
Requires-Dist: pydantic-settings>=2.0.0
Requires-Dist: fastapi>=0.109.0
Requires-Dist: uvicorn[standard]>=0.27.0
Requires-Dist: requests>=2.32.5
Requires-Dist: python-dotenv>=1.0.1
Requires-Dist: pandas>=2.0.0
Requires-Dist: boto3>=1.34.0
Requires-Dist: rich>=13.9.4
Requires-Dist: tabulate>=0.9.0
Requires-Dist: nocodb>=2.0.1
Requires-Dist: questionary>=2.0.1
Requires-Dist: coloraide>=5.1
Requires-Dist: hsluv>=5.0.4
Requires-Dist: python-multipart>=0.0.20
Requires-Dist: customtkinter>=5.2.2
Requires-Dist: webdav4==0.11.0

# orgm-bt: Electrical Calculation Library

A Python library for electrical load calculations and balancing according to NEC standards. This library provides tools for importing AutoCAD data, calculating load balances, and generating PDF reports.

## uv

uv venv --directory /home/osmar/Code/calc
export UV_PROJECT_ENVIRONMENT=/home/osmar/Code/calc/.venv
export VIRTUAL_ENV=/home/osmar/Code/calc/.venv


## Features

- **Data Import**: Parse AutoCAD TXT files for circuits, CSV files for panels, and DU files for diagramas unifilares
- **Load Balancing**: Greedy algorithm for optimal circuit-to-phase assignment
- **Code Validation**: Support for predefined load codes with automatic normalization
- **Custom Loads**: Handle custom format codes (M-208-3F-5HP, AC-480-3F-10KVA)
- **Load Calculation**: Complete electrical load calculations according to NEC standards
- **Panel Hierarchy**: Automatic detection and validation of panel hierarchies (TRF → MPM → Panels)
- **PDF Generation**: Generate professional reports using WeasyPrint with multiple document types:
  - Memoria de cálculo
  - Cuadros de distribución
  - Alimentadores
  - Módulos MPM
  - Transformadores (TRF)
  - Equipos especiales
- **DU Processing**: Process and enrich Diagrama Unifilar (DU) files with calculated feeder data
- **Circuit Enrichment**: Enrich circuit files with calculated breaker and cable information
- **Database Storage**: PostgreSQL with SQLModel for project and company data
- **Local Command Manager**: Interactive CLI tool (`local.py`) for managing and executing calculation commands
- **Cloud Storage**: Upload generated files to R2/S3 storage with automatic URL generation

## Installation

1. Clone the repository:
```bash
git clone <repository-url>
cd calc
```

2. Install dependencies using uv:
```bash
uv sync
```

3. Set up environment variables:
```bash
cp .env.example .env
# Edit .env with your database connection details
```

4. Set up the database:
```bash
uv run alembic upgrade head
```

## Quick Start

### 1. CLI local instalable

La CLI no usa una ruta por defecto: no ejecuta cálculos hasta que el operador
configure explícitamente los activos y la carpeta de proyectos. Instálela con `uv tool`:

```bash
# Cuando la versión esté publicada en PyPI:
pip install orgm-bt
#
# Alternativa desde el repositorio:
uv tool install --from git+https://github.com/osmargm1202/calc.git orgm-bt

# Estas rutas son ejemplos: cada PC decide las suyas.
orgm-bt config setup \
  --assets-dir ~/Documentos/ORGM-Calc/Activos \
  --projects-dir ~/Documentos/ORGM-Calc/Proyectos
```

La configuración se guarda en `~/.config/orgm-calc/config.json`. `config setup`
siembra explícitamente los catálogos actuales, `Assets/`, y los perfiles ORGM de
empresa e ingeniero; no se crea nada hasta proporcionar ambas rutas.

`init` no inicializa un workspace. Se ejecuta desde la carpeta donde el agente de
IA trabajará y crea allí un `AGENTS.md` con el flujo de revisión de CSV, datos
faltantes, cálculo HTML y PDF:

```bash
cd ~/Documentos/ORGM-Calc
orgm-bt init
```

Cada proyecto guarda solo `ruta`, relativa a `projects_dir`:

```bash
orgm-bt profile create client acme --name "ACME"
orgm-bt project create "Nave China" \
  --relative-path "Nave China/Calculos/ELEC" \
  --client acme
orgm-bt calculate "Nave China/Calculos/ELEC" --revision-description "Emisión inicial"
```

El ingeniero es obligatorio y, si se omite `--engineer`, se utiliza el perfil
configurado. Empresa y cliente son opcionales: sin cliente se muestra la empresa,
si existe; sin ambos, se dejan vacíos. Para quitar una asignación existente,
use `project edit RUTA --company "" --client ""`. En el menú de creación, ORGM
aparece preseleccionado como ingeniero y empresa; puede seleccionar «Ninguno»
para empresa/cliente. Por CLI, la empresa solo se asigna si se proporciona.

`project import-local` sirve para importar proyectos de una configuración anterior
(`local.json`) al catálogo central. No mueve los archivos de cálculo y no se
necesita para calcular proyectos ya registrados.

```bash
orgm-bt project import-local /ruta/anterior/datos/local.json
```

Sin argumentos, `orgm-bt` abre el menú Questionary: cálculo, DU, PDF, finalizar,
crear perfiles/proyectos, editar `PANELES.csv`, listar y reconfigurar rutas.
El cálculo genera HTML primero; PDF es explícito y posterior con WeasyPrint o
Chromium/Google Chrome headless.

#### Editar perfiles y proyectos

```bash
orgm-bt profile list engineer
orgm-bt profile edit engineer ingeniero-miguel-estevez \
  --name "Miguel Estevez" --codia 411690 --email "correo@ejemplo.com"
orgm-bt project edit "Nave China/Calculos/ELEC" --norma NEC
orgm-bt project edit --help
```

La ayuda distingue el objetivo requerido de los campos editables opcionales.
En el menú se seleccionan los campos que se quieren cambiar; los perfiles se
eligen por nombre, con tabla de CODIA, correo y teléfono, sin escribir IDs.
Los valores actuales quedan preseleccionados. Cancelar no guarda cambios.

**Título del informe** (`--calculation`, antes «Cálculo realizado») es el texto
que identifica la memoria impresa; por defecto es «Memoria de cálculo BT».
No es una fórmula ni el número del cálculo.

#### Revisiones y control del documento

La revisión corresponde a la carpeta numérica de cálculo en `RESULTADOS/`.
Un borrador se recalcula en el mismo número. Si la última revisión está
finalizada, el próximo cálculo crea la siguiente; también puede elegir
explícitamente «Siguiente revisión» sin sobrescribir la anterior.

```bash
orgm-bt calculate "Nave China/Calculos/ELEC" --revision-description "Emisión inicial"
# Continuar el borrador actual:
orgm-bt calculate "Nave China/Calculos/ELEC"
# Cerrar la revisión 1:
orgm-bt finalize "Nave China/Calculos/ELEC" 1
# Crear la revisión siguiente:
orgm-bt calculate "Nave China/Calculos/ELEC" \
  --revision next --revision-description "Ajuste de cargas y alimentadores"
```

En una terminal interactiva se solicita la descripción de cada revisión nueva.
En automatizaciones debe proporcionarse `--revision-description`; una ejecución
fallida no se incorpora al historial de cálculos terminados.

El menú de edición muestra la revisión actual y la siguiente. Elegir la
siguiente prepara la intención; la revisión real del catálogo se actualiza
solo tras un cálculo exitoso. Los documentos finalizados no se sobrescriben.

Cada versión incluye `control-documento.html` y `control-documento.json`.
El historial consolidado está en `RESULTADOS/control-documento.json`.
La hoja «Control del documento», accesible desde el menú de reportes e incluida
en la exportación PDF, muestra revisión, fecha, cambios, ingeniero y estado.
Las revisiones antiguas sin esos datos se conservan sin inventar descripciones.

### 2. Uso Directo con main.py

Ejecutar cálculos directamente con `main.py`:

```bash
# Ejemplo básico
uv run main.py --path /ruta/al/proyecto --output /ruta/salida

# Con parámetros adicionales
uv run main.py \
  --path /ruta/al/proyecto \
  --output /ruta/salida \
  --cliente "Nombre Cliente" \
  --empresa "Nombre Empresa" \
  --ing "Ing. Nombre" \
  --codia "12345" \
  --proyecto-id 1 \
  --url-logo-empresa "https://ejemplo.com/logo.png"

# Solo generar HTML (sin PDF)
uv run main.py --path /ruta/al/proyecto --html

# Modo blanco y negro
uv run main.py --path /ruta/al/proyecto --bn

# Especificar tamaños de página personalizados
uv run main.py \
  --path /ruta/al/proyecto \
  --alimentadores "11,17" \
  --cuadros "36,24" \
  --modulos-trf "24,18"
```

### 3. Importar Datos a Base de Datos

Create a project and import circuit/panel data:

```bash
# Create a new project
uv run python scripts/import_data.py --create-project "My Project"

# Import circuits from TXT file
uv run python scripts/import_data.py --project-id 1 --import-circuits proy/CIRCUITOS/D\ -\ BT.txt

# Import panels from CSV file
uv run python scripts/import_data.py --project-id 1 --import-panels proy/PANELES/PANELES.csv
```

### 4. Estructura de Directorios Requerida

El proyecto espera la siguiente estructura en el directorio base (`--path`):

```
proyecto/
├── CIRCUITOS/
│   └── D - BT.txt          # Archivo de circuitos (TXT tab-separated)
├── PANELES/
│   └── PANELES.csv         # Archivo de paneles (CSV)
└── DU/
    ├── TRF1.txt             # Diagrama del TRF (UTF-8 TSV)
    ├── MPM1.txt             # Diagrama de MPM o panel
    ├── TOTALIZADOR-TRF1.txt  # Totalizador (DU-facing TTL; interno TOTALIZADOR)
    ├── INV-01.txt           # Inversor (DU-facing INV; interno INVERSOR)
    └── ...                  # Un archivo por equipo (TXT UTF-8)
```

Los archivos generados se guardan en el directorio de salida especificado con `--output`.

## Scripts Reference

### `scripts/test_calculations.py`
Comprehensive test script that:
- Initializes the database
- Tests individual services (parser, validator, balanceador)
- Runs complete workflow: import → balance → PDF generation

### `scripts/import_data.py`
Data import utility with options:
- `--create-project NAME`: Create new project
- `--list-projects`: List all projects
- `--import-circuits FILE`: Import circuits from TXT
- `--import-panels FILE`: Import panels from CSV
- `--project-id ID`: Specify project ID
- `--clear-existing`: Clear existing data before import

### `scripts/generate_pdfs.py`
PDF generation utility with options:
- `--list-projects`: List all projects
- `--project-id ID`: Specify project ID
- `--output FILE`: Single PDF output file
- `--output-dir DIR`: Directory for multiple PDFs
- `--calculate-balance`: Calculate balance before PDF generation
- `--all-pdfs`: Generate all available PDF types

## Data Formats

### Circuit TXT Format
Tab-separated values (TSV) file con información de circuitos eléctricos. El archivo puede contener múltiples columnas:

**Columnas principales requeridas:**
- `HANDLE`: Identificador único del circuito
- `BLOCKNAME`: Nombre del bloque (generalmente "BT - CIRCUITO")
- `PANEL`: Nombre del panel al que pertenece el circuito
- `CANTIDAD`: Cantidad de elementos del circuito
- `CODIGO` o `CARGA`: Código de carga (TMC, IL, A/A, M-208-3F-5HP, etc.)
- `AREA`: Área o ubicación del circuito

**Columnas opcionales:**
- `ALIMENTADOR`: Identificador del alimentador
- `CIRCUITO`: Número de circuito
- `DISTANCIA`: Distancia en metros
- `FASE`: Número de fases
- `POTENCIA`: Potencia en VA/W
- `FACTOR`: Factor de potencia
- `TIPO`: Tipo de carga. Use `SERVICIOS_AUXIALIARES` para calcular esa carga a FD=1.
- `TENSIÓN`: Tensión nominal
- `CANALIZACION`: Tipo de canalización (`PVC`, `PVC SCH40`, `EMT`, `IMC`, `RMC`, `ENT`)
- `BREAKER_MINIMO`: Breaker mínimo requerido
- `CABLE_MINIMO`: Cable mínimo requerido

**Columnas custom** (para especificar valores personalizados):
- `VA_CUSTOM`: Potencia custom en VA
- `TENSION_CUSTOM`: Tensión custom
- `FP_CUSTOM`: Factor de potencia custom
- `FASES_CUSTOM`: Número de fases custom

**Ejemplo:**
```
HANDLE	BLOCKNAME	PANEL	CANTIDAD	CODIGO	AREA	ALIMENTADOR	CIRCUITO
'1583E	BT - CIRCUITO	PBA	6	IL	GENERAL		
'158C5	BT - CIRCUITO	PBB	5	IL	GENERAL		
```

### Panel CSV Format
Archivo CSV con información de la jerarquía de paneles y sus características. Define la estructura de alimentación desde transformadores hasta paneles finales.

**Columnas requeridas:**
- `FUENTE`: Panel o transformador origen (TRF, MPM1, MPM2, etc.)
- `PANEL`: Identificador del panel destino
- `FASE`: Número de fases (1, 2, 3)
- `TENSION`: Tensión nominal (120, 208, 240, 277, 480)

**Columnas opcionales:**
- `DISTANCIA`: Distancia en metros desde la fuente
- `NUMERO`: Número del panel (puede ser rango como "101-102")
- `AREA`: Área o ubicación del panel
- `PROPOSITO`: Propósito del panel (residencial, comercial, etc.)
- `CANALIZACION`: Tipo de canalización (`PVC`, `PVC SCH40`, `EMT`, `IMC`, `RMC`, `ENT`)
- `TIPO`: Tipo de panel

Si la norma del proyecto es **CEPM**, importación desde `PANELES.csv` fuerza `CANALIZACION = PVC SCH40` para todos los alimentadores.
Importación de `CIRCUITOS`/cargas no aplica ese forzado y preserva el valor proporcionado.
- `POTENCIA`: Potencia nominal
- `POTENCIAL`: Potencial eléctrico
- `NEUTRO`: Configuración de neutro
- `TIERRA`: Configuración de tierra

**Ejemplo:**
```
FUENTE,PANEL,DISTANCIA,NUMERO,FASE,TENSION,AREA,PROPOSITO,CANALIZACION
MPM3,PBAC,20,1,2,208,AREA COMUN,area comun,EMT
MPM3,PBS,20,1,2,208,SOTANO,area comun,
MPM3,PBF,39,101,2,208,BLOQUE A NIVEL 1,residencial,
```

**Nota:** La jerarquía debe ser válida: TRF → MPM → Paneles. El sistema valida automáticamente que no haya ciclos y que todos los paneles tengan una fuente válida.

### DU (Diagrama Unifilar) TXT Format
Archivo tab-separated (TSV) UTF-8 para diagramas unifilares.

La carpeta `DU/` puede contener **múltiples** archivos `*.txt`. Cada archivo representa un equipo lógico y se procesa de forma independiente al ejecutar `main.py`.

**Semántica de nombre de archivo (sin extensión):**
- `TRF*` → tipo `TRF` (salida tipo resumen/export).
- `TRFS*`, `MB*`, `MPM*`, `INV*`/`INVERSOR*` → tipo `equipo` (llenado tabular).
- `TOTALIZADOR*` y `TTL*` → tipo `TTL` (DU-facing; alias interno `TOTALIZADOR*`).
- cualquier otro prefijo no reconocido → fallback tabular (si existe origen de alimentadores), o `DISPONIBLE` si no.

**Columnas requeridas:**
- `HANDLE`: Identificador único
- `BLOCKNAME`: Nombre del bloque
- `DESCRIPCION`: Descripción del elemento
- `AREA`: Área o ubicación
- `BREAKER`: Información del breaker (se llena automáticamente)
- `ALIMENTADOR`: ID del alimentador (se llena automáticamente)
- `FASE`: Número de fases (se llena automáticamente)
- `POTENCIAL`: Potencial eléctrico (se llena automáticamente)
- `PANEL`: Nombre del panel asociado

**Ejemplo:**
```
HANDLE	BLOCKNAME	DESCRIPCION	AREA	BREAKER	ALIMENTADOR	FASE	POTENCIAL	PANEL
'228AF	*U92			-	-	-		TRF1
'23117	*U93			-	-	-		PBA
```

**Nota:** Cada archivo generado conserva el nombre original del archivo de entrada bajo el directorio de salida `.../DU/`.

## Load Code Support

### Predefined Codes
- **TMC**: Tomacorrientes (120V, 1F)
- **IL**: Iluminación (120V, 1F)
- **A/A**: Aire acondicionado (208V, 3F)
- **M2F1**: Motor 2HP (208V, 3F)

### Custom Format Codes
- **M-208-3F-5HP**: Motor 5HP, 208V, 3-phase
- **AC-480-3F-10KVA**: AC unit 10KVA, 480V, 3-phase

### Code Normalization
Automatic normalization with warnings:
- TMCC → TMC
- LED → IL
- LED-P → IL

## Database Schema

### Core Tables
- `proyectos`: Project information
- `circuitos`: Circuit data with load information
- `paneles`: Panel specifications
- `jerarquia_alimentacion`: Panel hierarchy relationships

### Custom Fields
- `va_custom`: Custom VA rating
- `tension_custom`: Custom voltage
- `fp_custom`: Custom power factor
- `fases_custom`: Custom phase count

## Configuration Files

### `datos/cargas_predeterminadas.json`
Predefined load codes with electrical characteristics:
```json
{
  "TMC": {
    "descripcion": "TOMACORRIENTE",
    "potencia": 1800,
    "tension": 120,
    "fase": 1,
    "factor": 1.0,
    "tipo": "tc"
  }
}
```

### `datos/categorias.json`
Load categories for organization:
```json
{
  "tc": {"nombre": "Tomacorriente", "descripcion": "Tomacorrientes de uso general"},
  "il": {"nombre": "Iluminación", "descripcion": "Iluminación de uso general"},
  "aa": {"nombre": "Aire Acondicionado", "descripcion": "Sistemas de aire acondicionado"}
}
```

## Development

### Project Structure
```
calc/
├── app/
│   ├── utils/              # Utilidades de cálculo
│   │   ├── carga.py        # Conversión y cálculo de cargas
│   │   ├── circuitos.py    # Procesamiento de circuitos
│   │   ├── panel.py        # Gestión de paneles y jerarquías
│   │   ├── mpm.py          # Módulos MPM (Media Power Module)
│   │   ├── trf.py          # Transformadores
│   │   ├── equipos.py      # Equipos especiales (GEN, UPS, etc.)
│   │   ├── cables.py       # Cálculo de cables
│   │   ├── factores_demanda.py  # Factores de demanda
│   │   └── ...             # Otras utilidades
│   ├── services/           # Servicios principales
│   │   ├── generador_pdf.py    # Generación de PDFs
│   │   └── validator.py        # Validación de datos
│   ├── du/                 # Procesamiento de Diagramas Unifilares
│   │   ├── du.py           # Procesador principal de DU
│   │   ├── alimentador.py  # Lógica de alimentadores
│   │   └── dibujante.py    # Generación de diagramas
│   ├── db/                 # Base de datos
│   │   ├── models.py       # Modelos SQLModel
│   │   ├── database.py     # Conexión a base de datos
│   │   └── alembic/        # Migraciones Alembic
│   ├── templates/          # Templates HTML para PDFs
│   │   ├── template-memoria.html
│   │   ├── template-cuadro-distribucion.html
│   │   ├── template-alimentadores.html
│   │   ├── template-mpm.html
│   │   ├── template-trf.html
│   │   ├── template-modulos-mpm-trf.html
│   │   ├── template-equipos.html
│   │   └── template-guia-cargas.html
│   ├── config.py           # Configuración de la aplicación
│   └── __init__.py
├── storage/                # Integración con almacenamiento cloud
│   └── s3.py              # Cliente S3/R2
├── datos/                  # Archivos JSON de configuración
│   ├── cargas_predeterminadas.json    # Códigos de carga
│   ├── motores_predeterminados.json   # Especificaciones de motores
│   ├── categorias.json                # Categorías de cargas
│   ├── factores_demanda.json          # Factores de demanda
│   ├── nema.json                      # Estándares NEMA
│   └── ...                            # Otros archivos de configuración
├── proy/                   # Datos de ejemplo
│   ├── CIRCUITOS/          # Archivos de circuitos
│   ├── PANELES/            # Archivos de paneles
│   └── DU/                 # Archivos de diagramas unifilares
├── temp/                   # Directorio temporal para archivos generados
├── main.py                 # Punto de entrada principal
├── local.py                # Gestor de comandos para uso local
├── api.py                  # API FastAPI (pendiente implementación)
├── alembic.ini             # Configuración de Alembic
├── pyproject.toml          # Dependencias y configuración del proyecto
└── README.md               # Este archivo
```

### Running Tests
```bash
# Test individual services
uv run python scripts/test_calculations.py

# Test with sample data
uv run python scripts/import_data.py --create-project "Test" --import-circuits proy/CIRCUITOS/D\ -\ BT.txt
```

### Database Migrations
```bash
# Create new migration
uv run alembic revision --autogenerate -m "Description"

# Apply migrations
uv run alembic upgrade head
```

## Requirements

- Python 3.11+
- PostgreSQL 12+
- uv (package manager)

### Dependencies
- **PDF Generation**: WeasyPrint, Pillow, ReportLab, svglib
- **Database**: SQLModel, Alembic, psycopg2-binary, pydantic-settings
- **API**: FastAPI, uvicorn (pendiente implementación)
- **Templates**: Jinja2
- **Cloud Storage**: boto3 (S3/R2)
- **Utilities**: rich, tabulate, pandas, python-dotenv
- **Interactive CLI**: questionary
- **NocoDB**: nocodb (integración opcional)

## License

No se ha declarado una licencia de distribución. El titular debe definirla antes
de anunciar el proyecto como software libre; publicar en PyPI no concede por sí
solo permisos de reutilización.

## Publicación en PyPI

Requiere Python 3.11 o posterior. El editor gráfico necesita Tk/Tcl y una sesión
gráfica; el PDF con WeasyPrint necesita sus bibliotecas nativas del sistema
(incluido Pango). Chromium/Chrome es una alternativa externa para PDF.

El paquete incluye catálogos de cálculo, plantillas y CSS/JS. No incluye los
proyectos locales, `.env`, la firma personal ni el carnet CODIA. Cada instalación
debe aportar esos activos a sus perfiles; los archivos locales existentes no
se eliminan al instalar o actualizar.

Desde la raíz del repositorio, para la versión 0.5.1:

```bash
uv build
uvx twine check --strict dist/orgm_bt-0.5.1.tar.gz dist/orgm_bt-0.5.1-py3-none-any.whl

# Prueba local del paquete, sin instalar desde el código fuente:
uv tool install --from ./dist/orgm_bt-0.5.1-py3-none-any.whl orgm-bt
orgm-bt --help

# Publicar solo estos dos artefactos. Requiere autenticación de PyPI.
# Use UV_PUBLISH_TOKEN desde el entorno; nunca guarde el token en el repositorio.
sops-shared-env --with UV_PUBLISH_TOKEN -- uv publish dist/orgm_bt-0.5.1.tar.gz dist/orgm_bt-0.5.1-py3-none-any.whl
```

Antes de publicar, confirme la licencia y la titularidad del nombre `orgm-bt`
en PyPI. Para una nueva entrega, incremente `project.version` en `pyproject.toml`,
ejecute `uv lock` y use los nombres de artefacto de esa versión. PyPI no permite
reemplazar un archivo ya publicado con el mismo nombre.

## Contributing

[Add contribution guidelines here]


## Workspace local

`orgm-bt config setup` prepara los activos y el catálogo central. `orgm-bt init`
solo escribe la guía del agente en el directorio actual.

```text
BT/
├── Assets/
├── Ing/<id>/datos.json, codia.png, firma.png (opcional)
├── Empresas/<id>/datos.json, logo.png
├── Cliente/<id>/datos.json, logo.png
├── Proyectos/<ruta-legible>-<hash>.json
└── BD/*.json
```

`BD/` se inicializa con los catálogos incluidos; después es la única base usada por
los cálculos de ese workspace. Modificar un JSON allí no modifica el programa.

Perfiles de ingeniero, empresa y cliente contienen `datos.json`. Campos admitidos:
`nombre`, `representante`, `correo`, `telefono`, `ubicacion`; el ingeniero añade
`codia`. Los logos locales se copian al resultado HTML, sin descargarlos de red.

Cada JSON de `BT/Proyectos/` persiste la ruta relativa a `projects_dir`.
CSV, circuitos y resultados permanecen en esa carpeta de cálculo; el CLI no usa
su `datos.json`, que puede pertenecer a una integración de API. Editar o borrar
un proyecto afecta al catálogo central, no a sus archivos de cálculo.

```json
{
  "nombre": "Nave de los Chinos",
  "ruta": "608 - NAVE DE LOS CHINOS/Calculo/ELEC",
  "ingeniero": "osmar",
  "empresa": "",
  "cliente": "cliente-bohc-projects-srl",
  "calculo_realizado": "Memoria de cálculo BT",
  "revision": 1,
  "descripcion_revision": "Emisión inicial",
  "ubicacion": "Santo Domingo",
  "norma": "MOPC"
}
```

### Flujo terminal

```bash
# Crear perfiles; copie después logo.png, codia.png o firma.png a sus carpetas.
orgm-bt profile create engineer osmar --name "Ing. Osmar Garcia" --codia 36467
orgm-bt profile create client cliente-bohc-projects-srl --name "BOHC PROJECTS SRL"

# Crear proyecto y la plantilla PANELES/PANELES.csv.
orgm-bt project create "Nave de los Chinos" \
  --relative-path "608 - NAVE DE LOS CHINOS/Calculo/ELEC" \
  --engineer osmar --client cliente-bohc-projects-srl

# La lista nunca se imprime al iniciar. Solicítela explícitamente.
orgm-bt project list --limit all
orgm-bt project list --limit 10
orgm-bt project list --search chinos --limit all

# Generar HTML, editar paneles con Tkinter y gestionar resultados.
orgm-bt calculate "Nave de los Chinos" --revision-description "Emisión inicial"
orgm-bt panels "Nave de los Chinos"
orgm-bt du "Nave de los Chinos" 1
orgm-bt finalize "Nave de los Chinos" 1
orgm-bt pdf "Nave de los Chinos" 1 --renderer chromium
```

Sin subcomando, `orgm-bt` y `uv run local.py` muestran un menú corto: calcular,
ver proyectos (todos, cantidad o búsqueda), crear o editar paneles. No imprime una
tabla de proyectos antes de que el usuario la pida. Los switches legacy de
`local.py` siguen disponibles para instalaciones que aún usan `datos/local.json`.

## Pendiente

- **Diagrama Unifilar**: Procesamiento básico implementado (archivo DU), pendiente visualización completa y generación automática del diagrama
- **Feed Lugs**: Alimentación a través de terminal (no va en un breaker). Pendiente implementar en cálculos y documentos.
- **FastAPI simple de uso interno**: Implementar API REST simple para uso interno del equipo, permitiendo:
  - Crear y gestionar proyectos
  - Ejecutar cálculos via API
  - Obtener resultados y documentos generados
  - Subir archivos de entrada
- **Actualizar Alembic con datos de local.json**: Crear migraciones de Alembic para almacenar en base de datos todos los campos de configuración que actualmente se guardan en `local.json`, excepto:
  - `path`: Ruta local (no se almacena en BD)
  - `output`: Ruta local de salida (no se almacena en BD)
  - `fecha_creacion` y `fecha_calculo`: Se pueden usar timestamps de BD

Esto permitirá centralizar la gestión de proyectos y configuraciones en la base de datos en lugar de archivos JSON locales.
