Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/juadariasmar/inventory_project/llms.txt

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

Inventory System is a production-ready, multi-tenant SaaS application built for businesses that need to manage their stock, sales pipeline, and purchasing operations in one place. Each company that signs up gets its own isolated workspace — with its own products, users, categories, and transaction history — all living in the same Neon Postgres database, separated at the data layer by a strict empresaId tenant boundary. Whether you are a small retailer tracking shelf stock or a mid-size distributor coordinating purchase orders across multiple suppliers, Inventory System gives every team member the right level of access to keep operations moving.

Architecture Overview

Inventory System is built on a modern, serverless-first stack designed to scale on Vercel without managing infrastructure. Next.js App Router drives both the UI and the REST API. Every page is a React Server Component by default, with client components used only where interactivity is required. API routes under src/app/api/ handle all data mutations and follow a consistent pattern: parse the request body with Zod, resolve the authenticated session, enforce tenant isolation by scoping every query to empresaId, and return a typed JSON response. Multi-tenant data model — each company is represented by an Empresa record. When a new user completes sign-up, the system automatically creates an Empresa for them and links their Usuario record to it via empresaId. Every subsequent database query in the application is filtered by this ID, so one company can never read or write another company’s data. Neon Auth replaces NextAuth entirely. Authentication is handled by @neondatabase/auth, which provides session management, sign-in/sign-up flows, and webhook-based user sync. The middleware at src/middleware.ts uses auth.middleware() to protect all application routes, redirecting unauthenticated visitors to /auth/sign-in. Public routes (/auth/*, /invitacion) are excluded from the matcher. Prisma 5 + Neon Postgres — the Prisma client is configured with the driverAdapters preview feature and uses @prisma/adapter-neon with a WebSocket pool for production. This allows Prisma to run efficiently inside Vercel’s serverless environment without saturating the Postgres connection limit. Migrations are applied with the direct (unpooled) connection string; the pooled connection is used at runtime. Upstash Redis rate limitingsrc/middleware.ts applies a sliding-window rate limit (5 requests per minute per IP) to all mutating POST endpoints using @upstash/ratelimit. When Upstash credentials are not configured the middleware transparently falls back to an in-memory Map, which is sufficient for local development and single-instance deployments.

Key Capabilities

Products

Create, update, and categorize products with auto-generated SKU codes, stock levels, minimum stock thresholds, and a full price-change history log.

Inventory Movements

Record manual stock entries and exits, or let movements be generated automatically when sales are confirmed or purchase orders are received.

Sales & Quotes

Create quotes that soft-reserve stock until an expiry date, then convert them to confirmed sales in one click. Full cancellation workflow included.

Purchase Orders

Draft purchase orders against any configured supplier, then mark them as received to automatically post the corresponding stock-entry movements.

Analytics

Sales trends, top-selling products, low-stock alerts, slow-moving inventory reports, and revenue breakdowns — all scoped to the current company.

Notifications

In-app notifications for low stock, critical stock, expiring quotes, accepted invitations, and new user registrations — delivered per user or company-wide.

Data Model Summary

The following table lists the core Prisma models and their role in the system. Every model that stores business data carries an empresaId foreign key to enforce tenant isolation.
ModelDescription
EmpresaRepresents a tenant company. Root of the multi-tenant hierarchy; all other models cascade-delete when an Empresa is deleted.
UsuarioAn authenticated user linked to exactly one Empresa. Carries a Rol, a list of fine-grained Permiso[], and an EstadoUsuario (PENDIENTE / ACTIVO / SUSPENDIDO).
ProductoA stockable item belonging to a Categoria. Tracks current cantidad, stockMinimo, and precio.
CategoriaGroups products within a company. Each category has a short prefijo used to generate product codes.
MovimientoA single stock entry (entrada) or exit (salida) event. May be linked to a Venta or an OrdenCompra.
VentaA confirmed sale composed of ItemVenta line items. Automatically posts salida movements on creation.
CotizacionA quote with a validity date that reserves stock. Can be converted to a Venta or cancelled.
OrdenCompraA purchase order sent to a Proveedor. Receiving it posts entrada movements for each line item.
ProveedorA supplier linked to one or more OrdenCompra records within a company.
ClienteA customer record that can be associated with sales and quotes.
AuditoriaImmutable audit log recording every create, update, delete, login, and failed-login event with before/after JSON snapshots.
HistorialPrecioTracks every price change on a Producto, recording the previous and new price, the timestamp, and the user who made the change.
HistorialMovimientosSecondary audit trail scoped to stock-movement events, storing before/after JSON snapshots of the affected product record.
NotificacionIn-app notification delivered to a user or company-wide, covering low stock, expiring quotes, invitation acceptance, and new user registrations.
InvitacionA token-based invitation sent to an email address to join a specific Empresa with a pre-assigned role.
ConfiguracionEmpresaPer-company settings such as currency, tax rate, logo URL, and contact details. One record per Empresa.

Roles and Permissions

Inventory System uses a two-layer authorization model: a broad role that controls administrative capabilities, and a granular permissions list (Permiso[]) that controls individual feature access within that role.
RoleDescription
SUPER_ADMINPlatform-level administrator. Automatically assigned to the email address in SUPER_ADMIN_EMAIL. Can manage all companies and users across the platform.
ADMINCompany-level administrator. Can approve or suspend users, manage categories, invite new team members, and access all features of their own company.
USUARIOStandard operator. Access is restricted to the permissions explicitly granted by an ADMIN — for example, REGISTRAR_MOVIMIENTOS, REALIZAR_VENTAS, VER_ANALISIS, or EXPORTAR_REPORTES.
Users who sign up independently (without an invitation) are automatically created with role ADMIN and status ACTIVO, giving them immediate access to their own company workspace. Users invited by an existing ADMIN receive the role and status specified in the invitation, and may start with status PENDIENTE until the admin approves them.

Tech Stack

LayerTechnology
FrameworkNext.js 16 (App Router)
LanguageTypeScript 5
UIReact 19, Radix UI, Tailwind CSS 4, Lucide React
ORMPrisma 5 with @prisma/adapter-neon
DatabaseNeon Serverless Postgres
AuthenticationNeon Auth (@neondatabase/auth)
Rate LimitingUpstash Redis (@upstash/ratelimit)
ChartsRecharts 3
EmailResend via Nodemailer
ExportExcelJS, pdf-lib
TestingJest 30, Playwright
DeploymentVercel

Build docs developers (and LLMs) love