Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/AndresLopezCorrales/Goods-Inventory/llms.txt

Use this file to discover all available pages before exploring further.

Goods Inventory follows a classic three-tier architecture — a React SPA (single-page application) in the browser, a Flask REST API as the middle tier, and a MySQL database as persistent storage. Each tier has a clearly defined responsibility: the frontend handles user interaction and state, the API enforces business logic and authentication, and the database provides durable, relational storage for all inventory data.

High-level flow

The diagram below traces the path of a typical public lookup — a user searching for a responsible party by name:
1

User enters a name in the browser

The React SPA renders the BuscadorResponsables component. As the user types, the frontend fires a request to the Flask API.
2

GET /api/responsables/buscar

The request hits the Home blueprint. No authentication is required. The query string carries the search term, e.g. ?name=Martinez.
3

MySQL query executes

SQLAlchemy translates the lookup into a SELECT against the responsible table, filtering rows whose name column matches the search term.
4

JSON response returned

The API serialises the matching rows using each model’s to_dict() method and returns a JSON array to the browser.
5

UI renders locations

React receives the response, updates component state, and renders the list of matching responsibles along with their associated locations.

Backend structure

The Flask application is bootstrapped inside a create_app() factory in main.py. On startup it:
  1. Loads .env variables — database credentials, server host, JWT secret, and token expiry are all read from environment variables, keeping secrets out of source control.
  2. Creates the MySQL database if it doesn’t already exist, using a server-level connection before the app database URI is configured.
  3. Initialises SQLAlchemy by binding the db instance to the app and calling db.create_all() to materialise any missing tables.
  4. Imports Excel dataload_excel_data() seeds the areas and articulos tables from bundled .xls files on the first run.
  5. Registers blueprints — route modules are attached via register_blueprints(), keeping the factory function clean.
  6. Configures CORS and JWT — all origins are permitted for API routes, and JWT access tokens are issued with a configurable expiry window.
main.py
def create_app():
    server_uri = f"mysql+pymysql://{name}:{password}@{server}"
    engine = create_engine(server_uri)
    with engine.connect() as conn:
        conn.execute(text(f"CREATE DATABASE IF NOT EXISTS {database}"))
        conn.commit()

    app = Flask(__name__)
    CORS(app, supports_credentials=True, resources={r"/*": {"origins": "*"}},
         allow_headers=["Content-Type", "Authorization"],
         expose_headers=["Authorization"])
    app.config['SQLALCHEMY_DATABASE_URI'] = f"mysql+pymysql://{name}:{password}@{server}/{database}"
    app.config['JWT_SECRET_KEY'] = jwt_secret_key
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
    app.config["JWT_ACCESS_TOKEN_EXPIRES"] = timedelta(days=jwt_expires_days)

    jwt = JWTManager(app)
    db.init_app(app)

    with app.app_context():
        db.create_all()
        load_excel_data("app/data/areas.xls", "app/data/articulos.xls")

    register_blueprints(app)
    return app

Blueprint organization

Routes are split into two blueprints based on whether they require authentication.

Home blueprint (public)

These endpoints are accessible without a JWT token and power the read-only public interface:
MethodEndpointDescription
GET/api/responsables/buscarSearch for responsible parties by name
GET/api/ubicaciones/{id}Retrieve locations for a given responsible
GET/api/items/{id}Retrieve items assigned to a location
POST/api/revisionesSubmit a new revision record

Admin blueprint (JWT-protected)

These endpoints require a valid Authorization: Bearer <token> header and are used exclusively by the admin dashboard:
MethodEndpointDescription
POST/api/loginAuthenticate and receive a JWT access token
GET/api/admin/responsables/buscarAdmin-scoped responsible search
GET/api/admin/ubicaciones/buscarAdmin-scoped location search
GET/api/admin/responsables/{id}/ubicacionesList locations for a specific responsible (admin view)
GET/api/admin/items/{id}Retrieve items assigned to a location (admin view)
GET/api/admin/locations/{id}/revisionsList all revisions for a location (admin view)

Frontend routing

The React application uses React Router v6 and defines the following client-side routes in App.jsx:
PathComponentAccess
/BuscadorResponsablesPublic — the main search landing page
/ubicaciones/:responsableIdUbicacionesPublic — lists locations for a responsible
/items/:ubicacionIdItemsPublic — lists items within a location
/adminAdminPagePublic — login form for administrators
/dashboardDashboardProtected — admin home after login
/admin/responsable/:idAdminResponsablesUbicacionProtected — manage a responsible’s locations
/admin/ubicacion/:id_locationAdminUbicacionRevisionesProtected — manage revisions for a location
All admin routes (such as /dashboard, /admin/responsable/:id, and /admin/ubicacion/:id_location) check for a JWT token in localStorage on mount. If no token is found, the router immediately redirects the user to /admin to log in.

Build docs developers (and LLMs) love