litepie / masters
Laravel package for managing master data with multi-tenancy support
Requires
- php: ^8.1
- laravel/framework: ^10.0|^11.0
- spatie/laravel-multitenancy: ^3.0
- spatie/laravel-permission: ^6.0
Requires (Dev)
- orchestra/testbench: ^8.0|^9.0
- phpunit/phpunit: ^10.0
This package is auto-updated.
Last update: 2025-08-22 16:06:17 UTC
README
A comprehensive Laravel package for managing master data with advanced multi-tenancy support. This package provides a robust foundation for handling reference data like countries, states, cities, categories, currencies, languages, and custom master data types in multi-tenant Laravel applications.
Table of Contents
- Features
- Requirements
- Installation
- Configuration
- Quick Start
- Multi-Tenancy
- Master Data Types
- Usage Examples
- API Documentation
- Console Commands
- Admin Interface
- Advanced Features
- Testing
- Contributing
- License
Features
🏢 Multi-Tenant Architecture
- Flexible Tenancy Strategies: Single database, multi-database, or schema-based isolation
- Global vs Tenant Data: Share common data globally while maintaining tenant-specific customizations
- Automatic Tenant Scoping: Built-in query scoping for seamless tenant isolation
- Tenant Context Management: Easy tenant switching with context preservation
📊 Comprehensive Master Data Management
- Pre-built Data Types: Countries, states, cities, categories, currencies, languages
- Custom Master Types: Create unlimited custom master data types with validation rules
- Hierarchical Support: Unlimited parent-child relationships with tree traversal
- Rich Metadata: Store additional data and metadata for each master record
🚀 Performance & Scalability
- Smart Caching: Automatic caching with configurable TTL and cache invalidation
- Optimized Queries: Efficient database queries with eager loading support
- Bulk Operations: High-performance import/export capabilities
- Database Indexing: Optimized database indexes for fast lookups
🔧 Developer Experience
- Eloquent Integration: Seamless integration with Laravel's Eloquent ORM
- Facade Support: Clean, expressive API through Laravel facades
- Validation Framework: Built-in validation with customizable rules
- Event System: Hook into create, update, delete events
🌐 API & Web Interface
- RESTful API: Complete REST API with filtering, searching, and pagination
- Admin Panel: Web-based administration interface
- Import/Export: Support for CSV, JSON, and Excel formats
- Rate Limiting: Built-in API rate limiting and throttling
🔒 Security & Reliability
- Soft Deletes: Safe data deletion with recovery options
- Audit Trail: Track all changes with comprehensive logging
- Data Validation: Multi-layer validation for data integrity
- Permission Integration: Works with Laravel's authorization system
Requirements
- PHP 8.1 or higher
- Laravel 10.0 or 11.0
- MySQL 8.0+ / PostgreSQL 13+ / SQLite 3.8+
- Redis (optional, for caching)
Installation
Step 1: Install via Composer
composer require litepie/masters
Step 2: Publish Package Assets
# Publish everything php artisan vendor:publish --provider="Litepie\Masters\MastersServiceProvider" # Or publish selectively php artisan vendor:publish --provider="Litepie\Masters\MastersServiceProvider" --tag="config" php artisan vendor:publish --provider="Litepie\Masters\MastersServiceProvider" --tag="migrations" php artisan vendor:publish --provider="Litepie\Masters\MastersServiceProvider" --tag="views" php artisan vendor:publish --provider="Litepie\Masters\MastersServiceProvider" --tag="assets"
Step 3: Run Database Migrations
php artisan migrate
Step 4: Install and Setup Package
# Install package and create default master types php artisan masters:install # Seed sample data (optional) php artisan masters:seed
Configuration
The package configuration file config/masters.php
provides extensive customization options:
Multi-Tenancy Strategy
// Single database with tenant_id column (default) 'tenancy_strategy' => 'single_db', // Multiple databases per tenant 'tenancy_strategy' => 'multi_db', // Schema-based separation 'tenancy_strategy' => 'schema',
Cache Configuration
'cache' => [ 'enabled' => true, 'ttl' => 3600, // 1 hour 'prefix' => 'masters', ],
API Settings
'api' => [ 'enabled' => true, 'prefix' => 'api/masters', 'middleware' => ['api', 'throttle:60,1'], 'rate_limit' => '60,1', ],
Quick Start
Basic Usage with Facade
use Litepie\Masters\Facades\Masters; // Set tenant context Masters::setTenant('tenant_123'); // Get all countries $countries = Masters::get('countries'); // Create new master data $country = Masters::create('countries', [ 'name' => 'United States', 'code' => 'US', 'iso_code' => 'USA', 'is_active' => true ]); // Update master data Masters::update('countries', $country->id, [ 'name' => 'United States of America' ]); // Search master data $results = Masters::search('countries', 'United');
Using Eloquent Models Directly
use Litepie\Masters\Models\MasterData; use Litepie\Masters\Models\MasterType; // Get countries with states $countries = MasterData::ofType('countries') ->with('children') ->active() ->get(); // Create hierarchical data $usa = MasterData::ofType('countries')->where('code', 'US')->first(); $california = MasterData::create([ 'master_type_id' => MasterType::where('slug', 'states')->first()->id, 'name' => 'California', 'code' => 'CA', 'parent_id' => $usa->id, 'is_active' => true ]);
Multi-Tenancy
Tenant Context Management
use Litepie\Masters\Facades\Masters; // Set current tenant Masters::setTenant('tenant_123'); // Get current tenant $currentTenant = Masters::getCurrentTenant(); // Execute in tenant context Masters::runForTenant('tenant_456', function() { $data = Masters::get('categories'); // This will only get categories for tenant_456 }); // Clear tenant context Masters::setTenant(null);
Global vs Tenant-Specific Data
// Global data (available to all tenants) $countries = MasterData::ofType('countries')->global()->get(); // Tenant-specific data $categories = MasterData::ofType('categories')->tenant('tenant_123')->get(); // Both global and tenant data $currencies = MasterData::ofType('currencies')->tenantOrGlobal()->get();
Master Data Types
Default Master Types
The package comes with these pre-configured master types:
- Countries (Global): ISO countries with codes
- States/Provinces (Global): Hierarchical under countries
- Cities (Global): Hierarchical under states
- Categories (Tenant-specific): Product/service categories
- Currencies (Global): ISO currencies with codes
- Languages (Global): ISO languages with codes
Creating Custom Master Types
use Litepie\Masters\Models\MasterType; $departmentType = MasterType::create([ 'name' => 'Departments', 'slug' => 'departments', 'description' => 'Organizational departments', 'is_hierarchical' => true, 'is_global' => false, // Tenant-specific 'validation_rules' => [ 'name' => 'required|string|max:255', 'code' => 'required|string|max:10|unique:master_data,code', 'manager_email' => 'nullable|email' ], 'additional_fields' => [ 'manager_email' => 'string', 'budget' => 'decimal', 'location' => 'string' ] ]); // Add data to custom type $hr = Masters::create('departments', [ 'name' => 'Human Resources', 'code' => 'HR', 'additional_data' => [ 'manager_email' => 'hr.manager@company.com', 'budget' => 50000, 'location' => 'Building A, Floor 2' ] ]);
Usage Examples
Hierarchical Data Operations
// Get full tree structure $categoryTree = Masters::getHierarchical('categories'); // Get children of specific parent $subCategories = Masters::getHierarchical('categories', $parentId); // Get path of an item $category = MasterData::find(123); echo $category->getPath(); // "Electronics > Computers > Laptops" echo $category->getPath(' / '); // "Electronics / Computers / Laptops" // Check relationships if ($category->hasChildren()) { $subcategories = $category->children; } if (!$category->isRoot()) { $parent = $category->parent; } // Get all ancestors $ancestors = $category->ancestors(); // Get all descendants $descendants = $category->descendants;
Advanced Querying
// Complex filtering $data = Masters::get('countries', [ 'search' => 'United', 'is_active' => true, 'parent_id' => null ]); // Using Eloquent scopes $activeCountries = MasterData::ofType('countries') ->active() ->rootLevel() ->orderBy('name') ->get(); // Search with relationships $countriesWithStates = MasterData::ofType('countries') ->whereHas('children', function($query) { $query->where('is_active', true); }) ->with(['children' => function($query) { $query->active()->orderBy('name'); }]) ->get();
Bulk Operations
// Import from array $countries = [ ['name' => 'India', 'code' => 'IN', 'iso_code' => 'IND'], ['name' => 'China', 'code' => 'CN', 'iso_code' => 'CHN'], ['name' => 'Japan', 'code' => 'JP', 'iso_code' => 'JPN'], ]; $results = Masters::import('countries', $countries); // Returns: ['success' => 3, 'failed' => 0, 'errors' => []] // Export to array $exportData = Masters::export('countries', [ 'is_active' => true ]); // Export specific fields $exportData = MasterData::ofType('countries') ->select(['name', 'code', 'iso_code']) ->active() ->get() ->toArray();
API Documentation
Authentication
All API endpoints support standard Laravel authentication and can be protected with middleware:
// In config/masters.php 'api' => [ 'middleware' => ['api', 'auth:sanctum', 'throttle:60,1'], ],
Endpoints
Master Types
GET /api/masters/types # List all master types POST /api/masters/types # Create new master type GET /api/masters/types/{id} # Get specific master type PUT /api/masters/types/{id} # Update master type DELETE /api/masters/types/{id} # Delete master type
Master Data
GET /api/masters/{type} # List data for type POST /api/masters/{type} # Create new data GET /api/masters/{type}/{id} # Get specific data PUT /api/masters/{type}/{id} # Update data DELETE /api/masters/{type}/{id} # Delete data # Specialized endpoints GET /api/masters/{type}/tree # Get hierarchical tree GET /api/masters/{type}/children/{parentId} # Get children GET /api/masters/{type}/search/{query} # Search data POST /api/masters/{type}/import # Bulk import GET /api/masters/{type}/export # Export data
Convenience Endpoints
GET /api/masters/countries # List countries GET /api/masters/states/{countryId} # List states by country GET /api/masters/cities/{stateId} # List cities by state GET /api/masters/currencies # List currencies GET /api/masters/languages # List languages
Request/Response Examples
Create Master Data
POST /api/masters/categories Content-Type: application/json { "name": "Electronics", "code": "ELEC", "description": "Electronic products and devices", "parent_id": null, "is_active": true, "additional_data": { "icon": "fas fa-laptop", "color": "#3498db" } }
Response:
{ "data": { "id": 123, "name": "Electronics", "code": "ELEC", "slug": "electronics", "description": "Electronic products and devices", "parent_id": null, "is_active": true, "additional_data": { "icon": "fas fa-laptop", "color": "#3498db" }, "created_at": "2025-08-21T10:30:00Z", "updated_at": "2025-08-21T10:30:00Z" }, "message": "Master data created successfully" }
Get Hierarchical Data
GET /api/masters/categories/tree
Response:
{ "data": [ { "id": 1, "name": "Electronics", "children": [ { "id": 2, "name": "Computers", "children": [ { "id": 3, "name": "Laptops", "children": [] } ] } ] } ], "type": "categories" }
Console Commands
Installation & Setup
# Install package and create default types php artisan masters:install # Force reinstall php artisan masters:install --force # Seed all sample data php artisan masters:seed # Seed specific type php artisan masters:seed countries
Data Import
# Import from CSV php artisan masters:import countries /path/to/countries.csv # Import from JSON php artisan masters:import currencies /path/to/currencies.json
Maintenance
# Clear all masters cache php artisan cache:clear --tags=masters # Validate data integrity php artisan masters:validate # Generate master data report php artisan masters:report
Admin Interface
Accessing the Admin Panel
The package provides a web-based admin interface accessible at /admin/masters
(configurable):
- Dashboard: Overview of all master types and data counts
- Master Types Management: Create, edit, delete master types
- Master Data Management: CRUD operations for all master data
- Import/Export Interface: Web-based bulk operations
- Search & Filter: Advanced search across all data types
Customizing Admin Routes
// In config/masters.php 'admin' => [ 'enabled' => true, 'prefix' => 'admin/masters', 'middleware' => ['web', 'auth', 'can:manage-masters'], ],
Advanced Features
Custom Validation Rules
// In MasterType creation $type = MasterType::create([ 'name' => 'Products', 'slug' => 'products', 'validation_rules' => [ 'name' => 'required|string|max:255', 'sku' => 'required|string|unique:master_data,code', 'price' => 'required|numeric|min:0', 'category_id' => 'required|exists:master_data,id' ] ]);
Event Hooks
use Litepie\Masters\Models\MasterData; // Listen for master data events MasterData::creating(function ($masterData) { // Auto-generate slug if (empty($masterData->slug)) { $masterData->slug = Str::slug($masterData->name); } }); MasterData::created(function ($masterData) { // Clear cache, send notifications, etc. Log::info("Master data created: {$masterData->name}"); });
Custom Cache Strategies
// Custom cache key generation class CustomMasterData extends MasterData { public function getCacheKey(): string { return "custom:master:{$this->masterType->slug}:{$this->id}:{$this->tenant_id}"; } }
Database Optimization
// Add custom indexes in migration Schema::table('master_data', function (Blueprint $table) { $table->index(['tenant_id', 'master_type_id', 'is_active']); $table->index(['parent_id', 'sort_order']); $table->fullText(['name', 'description']); // For advanced search });
Testing
Unit Tests
use Litepie\Masters\Facades\Masters; use Litepie\Masters\Models\MasterType; class MasterDataTest extends TestCase { public function test_can_create_master_data() { // Create master type $type = MasterType::create([ 'name' => 'Test Categories', 'slug' => 'test-categories', 'is_global' => false ]); // Set tenant Masters::setTenant('test_tenant'); // Create master data $category = Masters::create('test-categories', [ 'name' => 'Test Category', 'code' => 'TEST' ]); $this->assertNotNull($category); $this->assertEquals('Test Category', $category->name); $this->assertEquals('test_tenant', $category->tenant_id); } public function test_hierarchical_relationships() { $parent = Masters::create('categories', [ 'name' => 'Parent Category', 'code' => 'PARENT' ]); $child = Masters::create('categories', [ 'name' => 'Child Category', 'code' => 'CHILD', 'parent_id' => $parent->id ]); $this->assertTrue($parent->hasChildren()); $this->assertFalse($child->isRoot()); $this->assertEquals($parent->id, $child->parent->id); } }
API Tests
public function test_api_endpoints() { $response = $this->getJson('/api/masters/countries'); $response->assertStatus(200) ->assertJsonStructure(['data', 'count']); $response = $this->postJson('/api/masters/countries', [ 'name' => 'Test Country', 'code' => 'TC', 'is_active' => true ]); $response->assertStatus(201); }
Contributing
We welcome contributions! Please see CONTRIBUTING.md for details.
Development Setup
# Clone the repository git clone https://github.com/litepie/masters.git # Install dependencies composer install # Run tests composer test # Check code style composer cs-check # Fix code style composer cs-fix
Changelog
Please see CHANGELOG.md for recent changes.
Security
If you discover any security-related issues, please email security@litepie.com instead of using the issue tracker.
Credits
License
The MIT License (MIT). Please see License File for more information.