# berprado/erpapi architecture

> Architecture diagram of the GitHub repository berprado/erpapi, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-18). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/berprado/erpapi
- Repository: https://github.com/berprado/erpapi

## Overview

1. This repository is a single-deployment backend-plus-frontend system for POS inventory auditing. The FastAPI application serves both the REST API and the built-in PWA frontend, so the main architectural boundary is not “frontend vs backend repo,” but “browser/PWA client vs API vs MySQL database.”

2. The backend core is organized around four Python modules:
   - `main.py` as the application entrypoint and route assembly point
   - `models.py` for SQLAlchemy ORM mappings
   - `schemas.py` for request/response validation via Pydantic
   - `database.py` and `config.py` for DB connectivity and environment-driven settings

3. The frontend is a static PWA under `static/` with `index.html`, `app.js`, `sw.js`, a manifest, and UI assets. It is not a separate SPA framework; it is vanilla JavaScript with service-worker caching and local autosave. The same backend process serves the UI and the API, which simplifies deployment and keeps the client/server contract tight.

4. Authentication and session control are centralized in the API using JWT. The login flow returns a token, and all business endpoints are protected by HTTP bearer auth. The repo also documents a SHA-256 password verification compatibility layer with the POS ecosystem, which is important because it constrains how user credentials are handled.

5. The operational gate is the “operativa” state in the database. Before inventory actions are allowed, the system validates that the active operation is in state `24` (`INICIO CIERRE`). This makes the operational state a key domain boundary: if the operation advances, paloteo editing and correction are blocked.

6. The main business subsystem is inventory paloteo. The frontend exposes PALOTEO 1, PALOTEO 2, PALOTEO 3, and REPORTE views, but they all write into one canonical inventory payload. The API endpoints support:
   - listing pending products
   - posting a full physical inventory
   - reading an existing inventory by operation
   - correcting selected items while preserving non-sent items

7. Product selection for paloteo is derived from operational data, not entered manually from scratch. The API combines products sold during the operation plus transfers from warehouse to bar, then applies per-product weighing configuration. This means the data flow is: operational transactions in MySQL → pending inventory list → captured physical counts → persisted inventory header/detail.

8. Weighable products have a dedicated subdomain and model layer. The API can create weighing profiles for bottle models, and the frontend validates bottle-related constraints before submission. The implementation stores both the exact raw ounce totals and the POS-facing rounded ounces, so the architecture explicitly separates audit precision from downstream POS compatibility.

9. The paloteo workflow also has a report/export subsystem. A request can generate a PDF report in memory, with variants for general, income, and salida views. The report export is tied to the filtered client-side view, so the UI state affects the generated document. Static PDF files in `static/pdfs/` appear to be examples or generated outputs used alongside this feature.

10. Local persistence is part of the client architecture. The PWA autosaves drafts by operation, bar, and user, which reduces data loss during multi-step inventory capture. The service worker uses cache-first behavior for static assets and network-first for `/api/*`, so the app is designed to remain usable even with intermittent connectivity while keeping business data fresh.

11. Configuration is environment-based and split between test and production databases. `APP_ENV` switches between local WAMP/MySQL and remote production credentials, while additional flags control the “operativa bar” resolution. This makes deployment behavior a first-class architectural concern rather than hardcoded logic.

12. The database schema is centered on a small set of business tables: users and access logs, operations, weighed-product configuration, physical inventory headers and details, and raw weigh audit records. That table set reflects the main domain boundaries: identity, operation control, inventory capture, and audit traceability.

13. The `documentos/` folder is not just documentation; it is architectural context. It contains implementation notes, comparative designs, and model discussions for paloteo, weighing, and report generation. For a diagram, this repository should be represented as a domain-specific operational system with a tightly coupled PWA client, a FastAPI service layer, and a MySQL-backed inventory/audit model.

Main entry points: [`main.py`](https://github.com/berprado/erpapi/blob/main/main.py) (App entry), [`models.py`](https://github.com/berprado/erpapi/blob/main/models.py) (ORM models), [`documentos`](https://github.com/berprado/erpapi/tree/main/documentos) (Domain notes), [`static/app.js`](https://github.com/berprado/erpapi/blob/main/static/app.js) (Client logic)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_client["PWA client"]
  node_static_index["UI shell<br/>static PWA<br/>[index.html]"]
  node_static_app["Client logic<br/>vanilla JS<br/>[app.js]"]
  node_static_sw["Service worker<br/>offline cache<br/>[sw.js]"]
  node_static_manifest["Manifest<br/>PWA config<br/>[manifest.json]"]
end

subgraph group_api["FastAPI service"]
  node_main_py["App entry<br/>FastAPI bootstrap<br/>[main.py]"]
  node_auth_layer["Auth gate<br/>JWT bearer<br/>[main.py]"]
  node_inventory_flow["Paloteo flow<br/>inventory API<br/>[main.py]"]
  node_weighing_flow["Weighing<br/>weigh profile API<br/>[main.py]"]
  node_report_flow["Reports<br/>PDF export<br/>[main.py]"]
end

subgraph group_data["Data model"]
  node_config_py["Settings<br/>env config<br/>[config.py]"]
  node_database_py["DB session<br/>SQLAlchemy setup<br/>[database.py]"]
  node_models_py[("ORM models<br/>SQLAlchemy ORM<br/>[models.py]")]
  node_schemas_py["API schemas<br/>Pydantic models<br/>[schemas.py]"]
  node_mysql_db[("MySQL<br/>relational DB")]
end

subgraph group_docs["Docs"]
  node_docs_notes["Domain notes<br/>design docs"]
end

node_static_index -->|"loads"| node_static_app
node_static_app -->|"registers"| node_static_sw
node_static_app -->|"calls API"| node_main_py
node_static_sw -->|"network-first /api"| node_main_py
node_main_py -->|"mounts"| node_auth_layer
node_main_py -->|"mounts"| node_inventory_flow
node_main_py -->|"mounts"| node_weighing_flow
node_main_py -->|"mounts"| node_report_flow
node_main_py -->|"uses"| node_database_py
node_database_py -->|"reads settings"| node_config_py
node_database_py -->|"connects to"| node_mysql_db
node_models_py -->|"maps to"| node_mysql_db
node_schemas_py -->|"validates"| node_main_py
node_inventory_flow -->|"writes/reads"| node_models_py
node_inventory_flow -->|"uses"| node_schemas_py
node_weighing_flow -->|"writes/reads"| node_models_py
node_report_flow -->|"renders from"| node_inventory_flow
node_auth_layer -->|"checks users"| node_models_py
node_docs_notes -.->|"documents"| node_inventory_flow
node_docs_notes -.->|"documents"| node_weighing_flow
node_docs_notes -.->|"documents"| node_report_flow

click node_static_index "https://github.com/berprado/erpapi/blob/main/static/index.html"
click node_static_app "https://github.com/berprado/erpapi/blob/main/static/app.js"
click node_static_sw "https://github.com/berprado/erpapi/blob/main/static/sw.js"
click node_static_manifest "https://github.com/berprado/erpapi/blob/main/static/manifest.json"
click node_main_py "https://github.com/berprado/erpapi/blob/main/main.py"
click node_auth_layer "https://github.com/berprado/erpapi/blob/main/main.py"
click node_inventory_flow "https://github.com/berprado/erpapi/blob/main/main.py"
click node_weighing_flow "https://github.com/berprado/erpapi/blob/main/main.py"
click node_report_flow "https://github.com/berprado/erpapi/blob/main/main.py"
click node_config_py "https://github.com/berprado/erpapi/blob/main/config.py"
click node_database_py "https://github.com/berprado/erpapi/blob/main/database.py"
click node_models_py "https://github.com/berprado/erpapi/blob/main/models.py"
click node_schemas_py "https://github.com/berprado/erpapi/blob/main/schemas.py"
click node_docs_notes "https://github.com/berprado/erpapi/tree/main/documentos"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_static_index,node_static_app,node_static_sw,node_static_manifest toneBlue
class node_main_py,node_auth_layer,node_inventory_flow,node_weighing_flow,node_report_flow toneAmber
class node_config_py,node_database_py,node_models_py,node_schemas_py,node_mysql_db toneMint
class node_docs_notes toneRose
```

## Components

### PWA client

Browser-facing static app and offline behavior.

- [UI shell](https://github.com/berprado/erpapi/blob/main/static/index.html): static PWA · Served HTML entrypoint for the built-in inventory app. · `static/index.html`
- [Client logic](https://github.com/berprado/erpapi/blob/main/static/app.js): vanilla JS · PWA screens, forms, local autosave, and API calls. · `static/app.js`
- [Service worker](https://github.com/berprado/erpapi/blob/main/static/sw.js): offline cache · Cache-first static assets with network-first API handling. · `static/sw.js`
- [Manifest](https://github.com/berprado/erpapi/blob/main/static/manifest.json): PWA config · Web app metadata for installable PWA behavior. · `static/manifest.json`

### FastAPI service

Application entrypoint, auth, and business endpoints.

- [App entry](https://github.com/berprado/erpapi/blob/main/main.py): FastAPI bootstrap · Creates the application, assembles routes, and serves the UI/API. · `main.py`
- [Auth gate](https://github.com/berprado/erpapi/blob/main/main.py): JWT bearer · Login, token issuance, password verification, and protected endpoints. · `main.py`
- [Paloteo flow](https://github.com/berprado/erpapi/blob/main/main.py): inventory API · Pending products, full counts, correction, and operation-bound inventory reads. · `main.py`
- [Weighing](https://github.com/berprado/erpapi/blob/main/main.py): weigh profile API · Bottle and weighable-product handling with precision and POS rounding. · `main.py`
- [Reports](https://github.com/berprado/erpapi/blob/main/main.py): PDF export · Generates in-memory paloteo PDFs for general, income, and salida views. · `main.py`

### Data model

Configuration, ORM, schemas, and MySQL persistence.

- [Settings](https://github.com/berprado/erpapi/blob/main/config.py): env config · Environment-driven database and deployment switches. · `config.py`
- [DB session](https://github.com/berprado/erpapi/blob/main/database.py): SQLAlchemy setup · Database engine, connection, and session wiring. · `database.py`
- [ORM models](https://github.com/berprado/erpapi/blob/main/models.py): SQLAlchemy ORM · Users, operations, inventory headers/details, weights, and audit records. · `models.py`
- [API schemas](https://github.com/berprado/erpapi/blob/main/schemas.py): Pydantic models · Request and response validation for the REST contract. · `schemas.py`
- **MySQL**: relational DB · Operational source of truth for users, operations, inventory, and auditability.

### Docs

Repository documentation and implementation notes.

- [Domain notes](https://github.com/berprado/erpapi/tree/main/documentos): design docs · Implementation context for paloteo, weighing, and report workflows. · `documentos`

## Connections

- UI shell → Client logic: loads · The HTML shell bootstraps the client logic.
- Client logic → Service worker: registers · Client enables offline behavior through the service worker.
- Client logic → App entry: calls API · Browser actions post and fetch inventory data from the backend.
- Service worker → App entry: network-first /api · Business requests are refreshed from the API when possible.
- App entry → Auth gate: mounts · Application includes JWT login and bearer-protected routes.
- App entry → Paloteo flow: mounts · Application exposes the paloteo and correction endpoints.
- App entry → Weighing: mounts · Application exposes weighable-product configuration and validation flows.
- App entry → Reports: mounts · Application exposes PDF report generation.
- App entry → DB session: uses · Routes operate through the shared database session layer.
- DB session → Settings: reads settings · Connection setup depends on environment configuration.
- DB session → MySQL: connects to · Persistent state lives in MySQL.
- ORM models → MySQL: maps to · ORM models define the business tables in the database.
- API schemas → App entry: validates · Pydantic schemas shape incoming and outgoing API payloads.
- Paloteo flow → ORM models: writes/reads · Inventory operations persist headers, details, and corrections.
- Paloteo flow → API schemas: uses · Inventory endpoints exchange typed payloads.
- Weighing → ORM models: writes/reads · Weighing profiles and audit traces are persisted through ORM models.
- Reports → Paloteo flow: renders from · Reports are derived from the current paloteo data and filters.
- Auth gate → ORM models: checks users · Authentication depends on stored credentials and access logs.
- Domain notes → Paloteo flow: documents · Notes describe paloteo, correction, and operational state rules.
- Domain notes → Weighing: documents · Notes describe weighable-product behavior and bottle constraints.
- Domain notes → Reports: documents · Notes describe PDF export variants and view coupling.
