📋 Domain Overview
The Supply Domain is a core bounded context within the application responsible for managing supply chain operations, including agents, customers, suppliers, supply orders, quotations, purchase orders, and goods receipts. This domain follows Domain-Driven Design (DDD) principles to ensure clean architecture, maintainability, and scalability.
Purpose & Scope
The Supply Domain handles all operations related to procurement, distribution, and inventory management across the organization. It manages relationships between multiple stakeholders (agents, customers, suppliers) and coordinates complex business processes including order creation, quotation management, and goods receipt tracking.
🎯 Core Responsibility
Managing end-to-end supply chain operations and stakeholder interactions
📦 Primary Artifacts
Orders, Quotations, Purchase Orders, Goods Receipts, and Agent Management
🔄 Integration Points
Multiple subdomains working as bounded contexts with clear interfaces
🏗️ Architecture Overview
The Supply Domain follows a layered DDD architecture with clear separation of concerns:
Architectural Layers
| Layer | Responsibility | Key Components |
|---|---|---|
| HTTP Layer | Handle incoming requests and format responses | Controllers, Resources, Requests |
| Application Layer | Orchestrate business logic and coordinate operations | Services, DTOs, Transformers |
| Domain Layer | Define core business concepts and rules | Models, Entities, Value Objects, Events |
| Persistence Layer | Abstract data storage and retrieval | Repositories, Migrations, Seeders |
📁 Complete Project Structure
Overview of the entire Supply Domain project structure including all layers, configurations, and resources:
Root Structure
- app/
- Domains/Supply/
- SubDomains/ (7 Bounded Contexts)
- Agents/
- Customers/
- Suppliers/
- SupplyOrders/
- Quotations/
- PurchaseOrders/
- GoodsReceipts/
- Shared/ (Shared DTOs, Traits, Helpers)
- SubDomains/ (7 Bounded Contexts)
- Domains/Supply/
- routes/
- apis/
- v1/supply.php
- v1/agents.php
- v1/customers.php
- v1/suppliers.php
- v1/supply-orders.php
- v1/quotations.php
- v1/purchase-orders.php
- v1/goods-receipts.php
- apis/
- database/
- migrations/ (All supply domain migrations)
- seeders/
- SupplySeeder.php
- AgentSeeder.php
- CustomerSeeder.php
- SupplierSeeder.php
- config/
- supply.php (Supply domain configuration)
- app/Providers/
- SupplyDomainServiceProvider.php
Subdomain Detailed Structure
Each of the 7 subdomains follows this consistent structure:
- SubDomains/{SubdomainName}/
- Models/
- Entity1.php
- Entity2.php
- DTOs/
- Entity1DTO.php
- CreateEntity1DTO.php
- UpdateEntity1DTO.php
- Services/
- Entity1Service.php
- Entity2Service.php
- Http/
- Controllers/V1/
- Entity1Controller.php
- Entity2Controller.php
- Requests/V1/
- StoreEntity1Request.php
- UpdateEntity1Request.php
- Resources/V1/
- Entity1Resource.php
- Entity2Resource.php
- Controllers/V1/
- Events/ (Domain Events)
- Exceptions/ (Domain Exceptions)
- Traits/ (Shared Behaviors)
- Repositories/ (Data Access)
- Models/
🗄️ Database Schema & Migrations
The Supply Domain uses a comprehensive relational database schema with support for all 7 subdomains:
Core Tables
| Table | Purpose | Key Fields |
|---|---|---|
| agents | Sales agents managing customer relationships | id, user_id, name, commission, is_active, created_at, updated_at, deleted_at |
| customers | Business customers purchasing goods | id, code, name, credit_limit, is_active, created_at, updated_at, deleted_at |
| customer_locations | Multiple delivery/billing locations per customer | id, customer_id, name, address, phone, created_at, updated_at |
| suppliers | External vendors providing goods | id, code, name, contact_email, payment_terms, created_at, updated_at, deleted_at |
| supply_orders | Orders created by agents for customers | id, order_number, customer_id, agent_id, total_amount, status, created_at, updated_at, deleted_at |
| supply_order_items | Individual items in supply orders | id, order_id, description, quantity, unit_price, total_price, created_at |
| quotations | Price quotes for customer requests | id, quotation_number, customer_id, total_amount, status, valid_until, created_at, updated_at, deleted_at |
| quotation_items | Items included in quotations | id, quotation_id, description, quantity, unit_price, total_price, created_at |
| purchase_orders | Internal orders to suppliers | id, po_number, supplier_id, total_amount, status, delivery_date, created_at, updated_at, deleted_at |
| purchase_order_items | Items in purchase orders | id, po_id, description, quantity, unit_price, total_price, created_at |
| goods_receipts | Record of received goods from suppliers | id, receipt_number, po_id, total_items, received_date, status, created_at, updated_at, deleted_at |
| goods_receipt_items | Individual items received | id, receipt_id, po_item_id, quantity_received, quality_status, created_at |
Database Relationships
// Entity Relationships
agents.user_id → users.id (Has One User)
customers.id ← supply_orders.customer_id (Has Many Orders)
customers.id ← quotations.customer_id (Has Many Quotations)
agents.id ← supply_orders.agent_id (Created By)
suppliers.id ← purchase_orders.supplier_id (Has Many POs)
supply_orders.id ← supply_order_items.order_id (Has Many Items)
quotations.id ← quotation_items.quotation_id (Has Many Items)
purchase_orders.id ← purchase_order_items.po_id (Has Many Items)
purchase_orders.id ← goods_receipts.po_id (Has One Receipt)
goods_receipts.id ← goods_receipt_items.receipt_id (Has Many Items)
Soft Delete Support
The following tables support soft deletes (recovery from deletion):
- agents - deleted_at column
- customers - deleted_at column
- suppliers - deleted_at column
- supply_orders - deleted_at column
- quotations - deleted_at column
- purchase_orders - deleted_at column
- goods_receipts - deleted_at column
Indexing Strategy
All tables include strategic indexes for optimal query performance:
- Primary keys on id columns
- Foreign key indexes for relationships
- Composite indexes on frequently filtered columns (status, is_active, created_at)
- Full-text search indexes on name/description fields
- Unique indexes on business identifiers (order_number, po_number, etc.)
Migrations Organization
- database/migrations/
- 2024_01_15_create_agents_table.php
- 2024_01_16_create_customers_table.php
- 2024_01_16_create_customer_locations_table.php
- 2024_01_17_create_suppliers_table.php
- 2024_01_18_create_supply_orders_table.php
- 2024_01_18_create_supply_order_items_table.php
- 2024_01_19_create_quotations_table.php
- 2024_01_19_create_quotation_items_table.php
- 2024_01_20_create_purchase_orders_table.php
- 2024_01_20_create_purchase_order_items_table.php
- 2024_01_21_create_goods_receipts_table.php
- 2024_01_21_create_goods_receipt_items_table.php
Example Migration Structure
// database/migrations/2024_01_15_create_agents_table.php
Schema::create('agents', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained('users');
$table->string('name');
$table->decimal('commission', 5, 2)->default(0);
$table->boolean('is_active')->default(true);
$table->timestamps();
$table->softDeletes();
// Indexes
$table->index('user_id');
$table->index('is_active');
$table->index('created_at');
});
🛣️ API Routes & Routing
RESTful API routes organized by subdomain with V1 versioning:
Routes File Organization
- routes/apis/
- v1/
- agents.php
- customers.php
- suppliers.php
- supply-orders.php
- quotations.php
- purchase-orders.php
- goods-receipts.php
- v1/
Route Grouping Pattern
// routes/apis/v1/agents.php
Route::middleware(['api', 'auth:sanctum'])
->prefix('agents')
->name('agents.')
->group(function () {
Route::get('/', [AgentController::class, 'index'])->name('index');
Route::post('/', [AgentController::class, 'store'])->name('store');
Route::get('{agent}', [AgentController::class, 'show'])->name('show');
Route::put('{agent}', [AgentController::class, 'update'])->name('update');
Route::delete('{agent}', [AgentController::class, 'destroy'])->name('destroy');
Route::post('{agent}/restore', [AgentController::class, 'restore'])->name('restore');
Route::get('active', [AgentController::class, 'active'])->name('active');
});
// All routes follow the same RESTful pattern for other subdomains
Route Features
- RESTful resource routes for CRUD operations
- Soft delete restore endpoints
- Additional action routes (active, search, filter)
- API authentication via Sanctum tokens
- V1 versioning for backward compatibility
- Route naming conventions for easy reference
- Middleware protection on all endpoints
Main API Routes File
// routes/web.php - Main entry point for API routes
Route::prefix('api')
->group(function () {
require __DIR__ . '/apis/v1/agents.php';
require __DIR__ . '/apis/v1/customers.php';
require __DIR__ . '/apis/v1/suppliers.php';
require __DIR__ . '/apis/v1/supply-orders.php';
require __DIR__ . '/apis/v1/quotations.php';
require __DIR__ . '/apis/v1/purchase-orders.php';
require __DIR__ . '/apis/v1/goods-receipts.php';
});
Endpoint Summary
| Subdomain | Base Endpoint | Standard Methods | Special Endpoints |
|---|---|---|---|
| Agents | /api/agents | GET, POST, PUT, DELETE | restore, active |
| Customers | /api/customers | GET, POST, PUT, DELETE | restore, locations |
| Suppliers | /api/suppliers | GET, POST, PUT, DELETE | restore, contacts |
| Supply Orders | /api/supply-orders | GET, POST, PUT, DELETE | restore, status |
| Quotations | /api/quotations | GET, POST, PUT, DELETE | restore, approve, reject |
| Purchase Orders | /api/purchase-orders | GET, POST, PUT, DELETE | restore, confirm, track |
| Goods Receipts | /api/goods-receipts | GET, POST, PUT, DELETE | restore, verify, quality-check |
Route Model Binding
Implicit route model binding with soft delete support:
// Automatically resolves {agent} route parameter to Agent model
Route::get('agents/{agent}', function (Agent $agent) {
return $agent;
});
// For soft-deleted models, use:
Route::get('agents/{agent}', function (Agent $agent) {
return $agent; // Includes soft-deleted records
})->withTrashed();
// To only show non-soft-deleted:
Route::get('agents/{agent}', function (Agent $agent) {
return $agent; // Excludes soft-deleted records
});
⚙️ Service Providers & Configuration
Service providers register and bootstrap the Supply Domain components:
SupplyDomainServiceProvider
The main service provider for the entire Supply Domain:
class SupplyDomainServiceProvider extends ServiceProvider {
/**
* Register services
*/
public function register(): void {
// Register all service classes
$this->app->singleton(AgentService::class);
$this->app->singleton(CustomerService::class);
$this->app->singleton(SupplierService::class);
$this->app->singleton(SupplyOrderService::class);
$this->app->singleton(QuotationService::class);
$this->app->singleton(PurchaseOrderService::class);
$this->app->singleton(GoodsReceiptService::class);
}
/**
* Bootstrap services
*/
public function boot(): void {
// Load routes
$this->loadRoutesFrom(__DIR__ . '/../../routes/apis');
// Load migrations
$this->loadMigrationsFrom(__DIR__ . '/../../database/migrations');
// Register event listeners
$this->registerEventListeners();
// Publish configuration
$this->publishes([
__DIR__ . '/../../config/supply.php' => config_path('supply.php'),
]);
}
/**
* Register domain event listeners
*/
protected function registerEventListeners(): void {
// Event listeners for domain events
}
}
Provider Responsibilities
- Register service classes as singletons for dependency injection
- Load route files from the domain
- Load database migrations automatically
- Register event listeners for domain events
- Publish configuration files to application config
- Bootstrap domain-specific functionality
Configuration File (config/supply.php)
return [
'name' => 'Supply Domain',
'version' => '1.0.0',
// Feature flags
'features' => [
'enable_quotations' => true,
'enable_purchase_orders' => true,
'enable_goods_receipts' => true,
'enable_soft_deletes' => true,
],
// Pagination defaults
'pagination' => [
'per_page' => 15,
'max_per_page' => 100,
],
// Business rules
'business_rules' => [
'commission_min' => 0,
'commission_max' => 100,
'default_payment_terms_days' => 30,
'default_quotation_validity_days' => 30,
],
// Event handling
'events' => [
'queue' => 'default',
'retry' => 3,
],
// API versioning
'api' => [
'current_version' => 'v1',
'versions' => ['v1'],
],
];
Bootstrap Process
1. Application loads providers from config/app.php
2. SupplyDomainServiceProvider::register() is called
- All 7 service classes are registered as singletons
3. SupplyDomainServiceProvider::boot() is called
- Routes are loaded from routes/apis/
- Migrations are registered from database/migrations
- Event listeners are registered
- Configuration files are published
4. Domain is ready for HTTP requests
5. Routes dispatch to Controllers
6. Controllers inject Services via dependency injection
7. Services manage domain logic and events
Integration with Application
The Supply Domain integrates seamlessly with the Laravel application:
- Automatic service resolution through Laravel's container
- Database migrations run with
php artisan migrate - Seeders available via
php artisan db:seed - Routes accessible immediately after provider boot
- Configuration accessible via
config('supply') - Events automatically dispatched through Laravel's event system
- Middleware automatically applied to all domain routes
Service Registration & Dependency Injection
// In controller - service is automatically injected
class AgentController {
public function __construct(
private AgentService $service
) {}
public function index(Request $request): JsonResponse {
// Service instance automatically provided
$agents = $this->service->getAll(['per_page' => 15]);
return response()->json($agents);
}
}
// Laravel's service container resolves AgentService:
// 1. Checks if AgentService is registered (it is)
// 2. Creates or retrieves singleton instance
// 3. Injects into controller constructor
🔀 Bounded Contexts (Subdomains)
The Supply Domain is divided into 7 specialized bounded contexts, each managing a specific aspect of the supply chain. Each subdomain operates independently with its own models, services, and API endpoints.
👤 1. Agents Subdomain
Manages sales agents responsible for client relationships and order management
Models
Agent, User
DTOs
AgentDTO, CreateAgentDTO, UpdateAgentDTO
Service
AgentService
Controller
AgentController
🏪 2. Customers Subdomain
Manages customer information, locations, and credit settings
Models
Customer, Location
DTOs
CustomerDTO, CreateCustomerDTO, UpdateCustomerDTO
Service
CustomerService
Controller
CustomerController
🏭 3. Suppliers Subdomain
Manages supplier information, contact details, and payment terms
Models
Supplier, Contact
DTOs
SupplierDTO, CreateSupplierDTO, UpdateSupplierDTO
Service
SupplierService
Controller
SupplierController
📦 4. Supply Orders Subdomain
Manages orders created by agents for customers, including items and quantities
Models
SupplyOrder, OrderItem
DTOs
SupplyOrderDTO, CreateSupplyOrderDTO
Service
SupplyOrderService
Controller
SupplyOrderController
💬 5. Quotations Subdomain
Manages quotations for customer requests with pricing and terms
Models
Quotation, QuotationItem
DTOs
QuotationDTO, CreateQuotationDTO, UpdateQuotationDTO
Service
QuotationService
Controller
QuotationController
🛒 6. Purchase Orders Subdomain
Manages purchase orders created from approved quotations
Models
PurchaseOrder, POItem
DTOs
PurchaseOrderDTO, CreatePurchaseOrderDTO
Service
PurchaseOrderService
Controller
PurchaseOrderController
📥 7. Goods Receipts Subdomain
Manages received goods from suppliers and inventory updates
Models
GoodsReceipt, ReceiptItem
DTOs
GoodsReceiptDTO, CreateGoodsReceiptDTO
Service
GoodsReceiptService
Controller
GoodsReceiptController
🏛️ Domain-Driven Design Layers
Each subdomain follows the complete DDD layered architecture pattern:
📁 Folder Structure
app/Domains/Supply/SubDomains/{Subdomain}/
📊 Layers
Models, DTOs, Services, Http, Events, Exceptions, Traits
🔗 Integration
Clear boundaries with explicit interfaces between subdomains
Typical Subdomain Structure
- app/Domains/Supply/SubDomains/{SubdomainName}/
- Models/ (Entities, Aggregates)
- Agent.php
- ...
- DTOs/ (Data Transfer Objects)
- AgentDTO.php
- CreateAgentDTO.php
- UpdateAgentDTO.php
- Services/ (Application/Domain Services)
- AgentService.php
- Http/
- Controllers/V1/
- AgentController.php
- Requests/V1/
- StoreAgentRequest.php
- UpdateAgentRequest.php
- Resources/V1/
- AgentResource.php
- Controllers/V1/
- Events/ (Domain Events)
- Exceptions/ (Domain Exceptions)
- Traits/ (Shared Behaviors)
- Models/ (Entities, Aggregates)
🏛️ Domain Entities
Entities are core domain objects with unique identities and lifecycle management:
Core Entities
| Entity | Description | Key Attributes |
|---|---|---|
| Agent | Sales representative managing customer relationships | name, user_id, commission, is_active |
| Customer | Business entity purchasing goods/services | name, code, locations, credit_limit, is_active |
| Supplier | External vendor providing goods to organization | name, code, contact_info, payment_terms |
| SupplyOrder | Order created by agent for customer | order_number, customer_id, agent_id, total_amount, status |
| Quotation | Price quote for customer request | quotation_number, customer_id, total_amount, status, valid_until |
| PurchaseOrder | Internal order to supplier | po_number, supplier_id, total_amount, status, delivery_date |
| GoodsReceipt | Record of received goods from supplier | receipt_number, po_id, total_items, received_date, status |
Aggregate Roots
The following entities serve as aggregate roots, managing their own aggregates:
- Agent - manages agent data and commissions
- Customer - manages customer profile and locations
- Supplier - manages supplier information and contacts
- SupplyOrder - manages order items and status lifecycle
- Quotation - manages quotation items and approval workflow
- PurchaseOrder - manages PO items and delivery tracking
- GoodsReceipt - manages received items and quality checks
📤 Data Transfer Objects (DTOs)
DTOs provide type-safe data transformation between HTTP requests, domain models, and API responses:
DTO Pattern
Each entity typically has three DTOs:
EntityDTO
Represents the complete entity data for responses and internal operations
CreateEntityDTO
Represents required data for creating new entities
UpdateEntityDTO
Represents optional data for updating existing entities
Available DTOs
| DTO | Purpose | Location |
|---|---|---|
| AgentDTO | Complete agent data representation | Agents/DTOs/ |
| CreateAgentDTO | Data required to create new agent | Agents/DTOs/ |
| UpdateAgentDTO | Optional data for agent updates | Agents/DTOs/ |
| Same pattern applies to all 7 subdomains... | ||
DTO Data Flow
HTTP Request
↓
Request Validation (StoreAgentRequest)
↓
DTO Creation (CreateAgentDTO::fromArray())
↓
Service Layer (AgentService::create())
↓
Model Creation (Agent::create())
↓
Model to DTO (AgentDTO::fromModel())
↓
DTO to Resource (AgentResource)
↓
JSON Response
DTO Features
- Type-safe data transformation
- Validation contracts at HTTP boundary
- Clear separation between internal and external representations
- Support for partial updates with null-safe handling
- Automatic conversion between models and API responses
- Easy testing and mocking of business logic
⚙️ Application Services
Services orchestrate business logic and coordinate between HTTP layer and domain models:
Service Responsibilities
CRUD Operations
Create, read, update, and delete entity instances
Business Logic
Execute domain-specific rules and calculations
Event Publishing
Emit domain events for cross-domain communication
Query Operations
Search, filter, and retrieve entities with pagination
Service Methods (AgentService as Example)
| Method | Parameters | Returns | Purpose |
|---|---|---|---|
| create() | array $data | Agent | Create new agent |
| update() | Agent $agent, array $data | Agent | Update existing agent |
| delete() | Agent $agent | bool | Soft-delete agent |
| restore() | Agent $agent | Agent | Restore soft-deleted agent |
| getById() | int $id | Agent|null | Retrieve single agent by ID |
| getAll() | array $params | Paginated Collection | Retrieve all agents with pagination |
| search() | string $query, int $perPage | Paginated Collection | Search agents by name |
| filter() | array $filters, int $perPage | Paginated Collection | Filter agents by criteria |
| getActive() | int $perPage | Paginated Collection | Retrieve only active agents |
Service Pattern (All Services Follow This)
class AgentService {
public function __construct(
private AgentRepository $repository
) {}
public function create(array $data): Agent {
$agent = $this->repository->create($data);
event(new AgentCreated($agent));
return $agent;
}
public function update(Agent $agent, array $data): Agent {
$updated = $this->repository->update($agent, $data);
event(new AgentUpdated($updated));
return $updated;
}
public function delete(Agent $agent): bool {
$deleted = $this->repository->delete($agent);
event(new AgentDeleted($agent));
return $deleted;
}
public function getAll(array $params): Paginator {
return $this->repository->paginate(
$params['per_page'] ?? 15
);
}
public function search(string $query, int $perPage = 15): Paginator {
return $this->repository->search($query, $perPage);
}
}
🔌 API Endpoints
RESTful API endpoints following HTTP standards with consistent response formats:
Agent Controller Endpoints (V1)
| Method | Endpoint | Description | Status Code |
|---|---|---|---|
| GET | /api/v1/agents | List all agents with pagination and filtering | 200 |
| GET | /api/v1/agents/{id} | Retrieve single agent | 200 |
| POST | /api/v1/agents | Create new agent | 201 |
| PUT | /api/v1/agents/{id} | Update agent | 200 |
| DELETE | /api/v1/agents/{id} | Soft-delete agent | 200 |
| POST | /api/v1/agents/{id}/restore | Restore deleted agent | 200 |
| GET | /api/v1/agents/active | List active agents only | 200 |
HTTP Status Codes
✅ 200 OK
Successful GET, PUT, DELETE operations
✨ 201 Created
Successful resource creation (POST)
⚠️ 404 Not Found
Requested resource doesn't exist
❌ 422 Unprocessable Entity
Validation errors in request data
💥 500 Internal Server Error
Unexpected server-side errors
Request/Response Example
// GET /api/v1/agents
Response:
{
"success": true,
"message": "Agents retrieved successfully",
"data": [
{
"id": 1,
"name": "John Doe",
"commission": 5.5,
"is_active": true,
"user_id": 1,
"created_at": "2024-01-15T10:30:00Z"
}
],
"pagination": {
"total": 50,
"per_page": 15,
"current_page": 1,
"last_page": 4
}
}
// POST /api/v1/agents
Request:
{
"name": "Jane Smith",
"user_id": 2,
"commission": 6.0,
"is_active": true
}
Response: 201 Created
{
"success": true,
"message": "Agent created successfully",
"data": {
"id": 2,
"name": "Jane Smith",
"commission": 6.0,
"is_active": true,
"user_id": 2,
"created_at": "2024-01-15T11:30:00Z"
}
}
Query Parameters
| Parameter | Type | Example | Description |
|---|---|---|---|
| per_page | integer | ?per_page=25 | Items per page (default: 15) |
| search | string | ?search=john | Search by name |
| is_active | boolean | ?is_active=true | Filter by active status |
| min_commission | float | ?min_commission=5 | Filter by minimum commission |
| max_commission | float | ?max_commission=10 | Filter by maximum commission |
| user_id | integer | ?user_id=5 | Filter by user ID |
🎯 Domain Events
Domain Events enable asynchronous communication between bounded contexts and decoupled business process handling:
Event Architecture Benefits
- Decouples subdomains through publish-subscribe pattern
- Enables audit trails and historical tracking
- Supports async processing and notifications
- Facilitates saga pattern for distributed transactions
- Provides event sourcing capabilities for future enhancements
Implemented Domain Events
The Supply Domain uses Domain Events to communicate important occurrences:
AgentCreated
Fired when new agent is created
AgentUpdated
Fired when agent information is updated
AgentDeleted
Fired when agent is soft-deleted
AgentRestored
Fired when deleted agent is restored
Event Publishing Pattern
// In Service Layer
public function create(array $data): Agent {
$agent = $this->repository->create($data);
// Publish domain event
event(new AgentCreated($agent));
return $agent;
}
// Event Definition
class AgentCreated {
public function __construct(
public Agent $agent
) {}
}
// Event Listener
class SendAgentCreationNotification {
public function handle(AgentCreated $event) {
// Send email notification
Mail::to($event->agent->user->email)
->send(new AgentWelcomeMail($event->agent));
}
}
Planned Events (30+ events across all subdomains)
| Entity | Events |
|---|---|
| Agent | Created, Updated, Deleted, Restored, CommissionChanged |
| Customer | Created, Updated, Deleted, CreditLimitModified, StatusChanged |
| Supplier | Created, Updated, Deleted, PaymentTermsChanged, ContactUpdated |
| SupplyOrder | Created, Confirmed, Shipped, Delivered, Cancelled, StatusChanged |
| Quotation | Created, Sent, Accepted, Rejected, Expired, Converted |
| PurchaseOrder | Created, Confirmed, PartiallyReceived, Completed, Cancelled |
| GoodsReceipt | Created, Verified, QualityChecked, Accepted, Rejected |
Event Handlers
Events are handled through Laravel's event-listener pattern:
- Send notifications to stakeholders
- Update related entities in other bounded contexts
- Trigger workflow transitions
- Log audit trails
- Execute async jobs (queue processing)
- Integrate with external systems
🎁 Additional Features & Best Practices
Soft Deletes
All entities support soft deletes for data integrity and audit compliance. Deleted records
are marked with deleted_at timestamp rather than permanently removed.
Timestamps
Automatic tracking of creation and modification times:
created_at- When the record was createdupdated_at- Last modification timestampdeleted_at- Soft delete timestamp (if applicable)
Relationships
Well-defined Eloquent relationships between entities:
- Agents belong to Users
- Customers have many Locations
- SupplyOrders contain multiple OrderItems
- Quotations contain multiple QuotationItems
- PurchaseOrders contain multiple POItems
- GoodsReceipts contain multiple ReceiptItems
Pagination & Filtering
All index endpoints support:
- Pagination with customizable page size
- Full-text search capabilities
- Advanced filtering by multiple criteria
- Sorting options for results
Error Handling
Consistent error response format:
{
"success": false,
"message": "Agent not found",
"errors": null,
"data": null,
"code": "404"
}
Validation
Form Request classes provide validation at HTTP boundary:
- StoreAgentRequest - validates creation data
- UpdateAgentRequest - validates update data
- Custom validation rules for domain constraints
- Multilingual error messages (en, ar, tr, ur)
Logging
Comprehensive logging throughout the application:
- Log all CRUD operations with entity IDs
- Track exceptions with full context
- Audit trail for compliance requirements
- Performance metrics for slow queries
📚 Conclusion & Next Steps
The Supply Domain represents a well-structured, scalable implementation of Domain-Driven Design principles within a Laravel application. The layered architecture, clear domain boundaries, and comprehensive API documentation provide a solid foundation for:
- Maintainable and testable code
- Clear separation of concerns
- Easy onboarding of new developers
- Reduced coupling between subdomains
- Scalable async operations through events
- Comprehensive audit and compliance tracking
Future Enhancements
🎯 Value Objects
Implement domain-specific value objects like Money, CommissionRate, OrderNumber
📋 Specifications
Encapsulate complex query logic through Specification pattern
🔄 Event Sourcing
Implement event sourcing for immutable audit trails
📊 CQRS
Separate read and write models for optimal performance
Documentation & Resources
- API Documentation: See AGENTS_API.md for endpoint details
- Postman Collection: Available for API testing with all endpoints
- Database Migrations: Create and seed development data
- Unit Tests: Comprehensive test coverage for business logic