Multi-tenant humanitarian aid inventory management system
Sistema multi-tenant de gestión de inventario para ayuda humanitaria
Acopio is a web-based management platform designed to support humanitarian aid collection centers (e.g. Cruz Roja chapters, disaster relief organizations). It allows multiple independent organizations — each as a tenant — to manage their aid collection operations in complete isolation: donations received, transfers between centers, shipments to destinations, and real-time inventory with reporting.
| Feature | Description |
|---|---|
| 🏢 Multi-Tenancy | Complete data isolation between organizations. Each tenant has its own users, inventory, roles, and catalog. |
| 🔐 Role-Based Access Control | Powered by spatie/laravel-permission with Filament Shield. Roles and permissions are scoped per tenant. |
| 📥 Aid Reception | Log incoming donations per supply item across multiple collection centers. |
| 🔄 Internal Transfers | Track transfers of supplies between collection centers within the same organization. |
| 📤 Shipments / Dispatches | Register outgoing dispatches to final destinations. |
| 📊 Statistics Dashboard | Real-time KPI widgets, charts, and filterable data tables with date-range and center filters. |
| 📄 Export to PDF & Excel | Generate and download reception reports in PDF (DomPDF) and Excel (PhpSpreadsheet) formats. |
| 🗂️ Base Catalog | 10 categories, 42 subcategories, and 71 supply items pre-loaded as a reusable seed. |
| ⚡ Quick Reception Form | Streamlined Filament page for rapid donation entry without navigating CRUD tables. |
| 🧭 Inventory Overview | Cross-center inventory visibility with aggregated widgets and charts. |
Laravel 15 (PHP 8.3)
├── Filament v5 — Admin panel, CRUD resources, pages & widgets
├── spatie/laravel-permission — Role & Permission management (team-scoped per tenant)
├── filament-shield — Auto-generated Filament policies from permissions
├── DomPDF — PDF report generation
├── PhpSpreadsheet — Excel report generation
├── Laravel Sail + Docker — Local development (PHP, MySQL 8.4, Redis)
└── Vite — Frontend asset compilation
Multi-tenancy is implemented via a lightweight custom solution:
- A
tenantstable groups users and data under an organization. - A
HasTenanttrait automatically scopes all Eloquent queries to the current tenant using a Global Scope, preventing any data leakage between organizations. - A
SetTenantPermissionsContextmiddleware configures Spatie's team ID on every request so permissions are evaluated in the correct tenant context.
Tenant
└── Users (with roles scoped to tenant)
└── CentroAcopio (Collection Center)
├── Recepcions → RecepcionDetalles → Insumo
├── Transferencias (origin / destination centers)
└── Envios → EnvioDetalles → Destino
Catalog (isolated per tenant):
Categoria → Subcategoria → Insumo
Requirements: Docker Desktop, Git
# 1. Clone the repository
git clone https://github.com/Gusthere/acopio.git acopio && cd acopio
# 2. Copy environment file
cp .env.example .env
# 3. Install PHP dependencies (via temporary container)
docker run --rm -u "$(id -u):$(id -g)" \
-v "$(pwd):/var/www/html" -w /var/www/html \
laravelsail/php83-composer:latest \
composer install --no-interaction
# 4. Start the development environment
./vendor/bin/sail up -d
# 5. Generate application key and run migrations
./vendor/bin/sail artisan key:generate
./vendor/bin/sail artisan migrate
# 6. Create your first tenant (with base catalog)
./vendor/bin/sail artisan tenants:create "My Organization" \
--owner_email=admin@example.com \
--owner_password=secret \
--with-catalogo
# 7. Open the panel at http://localhost/admin| Command | Description |
|---|---|
tenants:create {name} |
Creates a new tenant with optional owner and base catalog |
tenants:seed-catalogo {id} |
Seeds the base catalog into an existing tenant |
db:seed |
Loads the global catalog (no tenant association) |
# Full tenant setup in one command
php artisan tenants:create "Cruz Roja Bogotá" \
--owner_email=admin@bogota.org \
--owner_password=secret123 \
--with-catalogo
# Seed catalog into an existing tenant (non-interactive)
php artisan tenants:seed-catalogo 3 --forceThe project ships a production Dockerfile based on serversideup/php:8.3-fpm-nginx.
On container start, an entrypoint script automatically runs:
config:cache → route:cache → view:cache → storage:link → filament:optimize → migrate
docker build -t acopio:latest .
docker run -p 80:80 --env-file .env acopio:latestapp/
├── Console/Commands/ # tenants:create, tenants:seed-catalogo
├── Filament/
│ ├── Pages/ # Dashboard, EstadisticasAcopio, InventarioCentros, RegistroRapidoRecepcion
│ ├── Resources/ # CRUD: CentroAcopio, Insumo, Recepcion, Envio, Transferencia, User…
│ └── Widgets/ # KPI stat cards, bar/donut charts, report data tables
├── Http/Middleware/ # SetTenantPermissionsContext
├── Models/
│ ├── Traits/HasTenant # Global Scope for automatic tenant isolation
│ └── Scopes/ # Eloquent query scopes
└── Support/
├── ReportDataCollector.php # Centralized report data aggregation logic
└── UnidadMedidaFormatter.php # Unit-of-measure display formatting
database/
├── migrations/ # 17 migration files
└── seeders/
└── CatalogoComunSeeder.php # Reusable base catalog seeder (10 cats / 42 subcats / 71 items)
Acopio es una plataforma de gestión web diseñada para apoyar centros de acopio de ayuda humanitaria (ej. seccionales de Cruz Roja, organizaciones de respuesta a desastres). Permite que múltiples organizaciones independientes — cada una como un tenant — gestionen sus operaciones de acopio en completo aislamiento: donaciones recibidas, transferencias entre centros, despachos a destinos e inventario en tiempo real con reportes exportables.
| Funcionalidad | Descripción |
|---|---|
| 🏢 Multi-tenancy | Aislamiento total de datos entre organizaciones. Cada tenant tiene sus propios usuarios, inventario, roles y catálogo. |
| 🔐 Control de Acceso por Roles | Usando spatie/laravel-permission con Filament Shield. Roles y permisos aislados por tenant. |
| 📥 Recepción de Donaciones | Registro de insumos recibidos por centro de acopio, con detalle por ítem. |
| 🔄 Transferencias Internas | Seguimiento de movimientos de insumos entre centros de la misma organización. |
| 📤 Envíos / Despachos | Registro de salidas hacia destinos finales. |
| 📊 Dashboard de Estadísticas | KPIs en tiempo real, gráficos y tablas filtrables por rango de fechas y centro. |
| 📄 Exportar PDF y Excel | Reportes de recepción descargables en PDF (DomPDF) y Excel con tabla nativa (PhpSpreadsheet). |
| 🗂️ Catálogo Base | 10 categorías, 42 subcategorías y 71 insumos pre-cargados como seed reutilizable. |
| ⚡ Registro Rápido de Recepción | Página Filament optimizada para el ingreso ágil de donaciones. |
| 🧭 Vista de Inventario | Visibilidad consolidada del inventario por centro con widgets y gráficos. |
Laravel 15 (PHP 8.3)
├── Filament v5 — Panel administrativo, CRUD, páginas y widgets personalizados
├── spatie/laravel-permission — Roles y Permisos con soporte de equipos (teams) por tenant
├── filament-shield — Políticas de Filament generadas automáticamente
├── DomPDF — Generación de reportes PDF
├── PhpSpreadsheet — Generación de reportes Excel con tablas nativas
├── Laravel Sail + Docker — Entorno de desarrollo (PHP 8.3, MySQL 8.4, Redis Alpine)
└── Vite — Compilación de assets frontend
La multi-tenancy está implementada con una solución liviana y personalizada:
- La tabla
tenantsagrupa usuarios y datos bajo una organización. - El trait
HasTenantaplica automáticamente un Global Scope de Eloquent en todos los modelos, garantizando el filtrado por tenant y evitando filtraciones de datos entre organizaciones. - El middleware
SetTenantPermissionsContextconfigura el Team ID de Spatie en cada request, asegurando que los permisos se evalúen en el contexto del tenant correcto.
Tenant
└── Usuarios (con roles aislados por tenant)
└── CentroAcopio
├── Recepciones → RecepciónDetalles → Insumo
├── Transferencias (origen / destino entre centros)
└── Envíos → EnvíoDetalles → Destino
Catálogo (aislado por tenant):
Categoría → Subcategoría → Insumo
Requisitos: Docker Desktop, Git
# 1. Clonar el repositorio
git clone https://github.com/Gusthere/acopio.git acopio && cd acopio
# 2. Copiar el archivo de entorno
cp .env.example .env
# 3. Instalar dependencias PHP (contenedor temporal)
docker run --rm -u "$(id -u):$(id -g)" \
-v "$(pwd):/var/www/html" -w /var/www/html \
laravelsail/php83-composer:latest \
composer install --no-interaction
# 4. Levantar el entorno de desarrollo
./vendor/bin/sail up -d
# 5. Generar clave de aplicación y ejecutar migraciones
./vendor/bin/sail artisan key:generate
./vendor/bin/sail artisan migrate
# 6. Crear el primer tenant con catálogo base
./vendor/bin/sail artisan tenants:create "Mi Organización" \
--owner_email=admin@example.com \
--owner_password=secret \
--with-catalogo
# 7. Acceder al panel en http://localhost/admin| Comando | Descripción |
|---|---|
tenants:create {name} |
Crea un nuevo tenant con owner y catálogo opcionales |
tenants:seed-catalogo {id} |
Inyecta el catálogo base en un tenant existente |
db:seed |
Carga el catálogo global (sin asociar a ningún tenant) |
# Configuración completa de un tenant en un solo comando
php artisan tenants:create "Cruz Roja Bogotá" \
--owner_email=admin@bogota.org \
--owner_password=secret123 \
--with-catalogo
# Inyectar catálogo en tenant existente (sin confirmación interactiva)
php artisan tenants:seed-catalogo 3 --forceEl proyecto incluye un Dockerfile de producción basado en serversideup/php:8.3-fpm-nginx.
Al iniciar el contenedor, un script de entrypoint ejecuta automáticamente:
config:cache → route:cache → view:cache → storage:link → filament:optimize → migrate
docker build -t acopio:latest .
docker run -p 80:80 --env-file .env acopio:latestapp/
├── Console/Commands/ # tenants:create, tenants:seed-catalogo
├── Filament/
│ ├── Pages/ # Dashboard, EstadisticasAcopio, InventarioCentros, RegistroRapidoRecepcion
│ ├── Resources/ # CRUD: CentroAcopio, Insumo, Recepcion, Envio, Transferencia, Usuario…
│ └── Widgets/ # Tarjetas KPI, gráficos de barras/dona, tablas de reporte
├── Http/Middleware/ # SetTenantPermissionsContext
├── Models/
│ ├── Traits/HasTenant # Global Scope para aislamiento automático por tenant
│ └── Scopes/ # Query Scopes de Eloquent
└── Support/
├── ReportDataCollector.php # Lógica centralizada de agregación de datos para reportes
└── UnidadMedidaFormatter.php # Formateo de unidades de medida
database/
├── migrations/ # 17 archivos de migración
└── seeders/
└── CatalogoComunSeeder.php # Seeder reutilizable del catálogo base (10 cat / 42 subcat / 71 insumos)
| # | Categoría | Subcategorías | Insumos |
|---|---|---|---|
| 1 | Insumos médicos | 4 | 11 |
| 2 | Alimentos no perecederos | 6 | 12 |
| 3 | Ropa de niños | 5 | 7 |
| 4 | Ropa de adultos | 5 | 7 |
| 5 | Higiene personal | 5 | 9 |
| 6 | Limpieza y desinfección | 3 | 5 |
| 7 | Dormitorio y abrigo | 4 | 5 |
| 8 | Utensilios y cocina | 3 | 6 |
| 9 | Agua y saneamiento | 3 | 3 |
| 10 | Protección y emergencia | 4 | 7 |
| Total | 42 | 71 |
This project is open-sourced software licensed under the MIT license.
Este proyecto es software de código abierto licenciado bajo la licencia MIT.