Backend Architecture¶
The Stratpoint Timesheet Application backend is built on Laravel 8.x, following modern PHP development practices and architectural patterns. This section provides detailed information about the backend structure, design patterns, and implementation details.
Application Structure¶
Directory Organization¶
app/
├── Console/ # Artisan commands
├── Exceptions/ # Exception handlers
├── Http/ # HTTP layer components
│ ├── Controllers/ # Request controllers
│ ├── Middleware/ # HTTP middleware
│ ├── Requests/ # Form request validation
│ ├── Resources/ # API resource transformers
│ ├── Services/ # Business logic services
│ └── Traits/ # Reusable traits
├── Jobs/ # Queue jobs
├── Mail/ # Mail classes
├── Models/ # Eloquent models
├── Providers/ # Service providers
├── helpers.php # Global helper functions
└── validators.php # Custom validators
Core Components¶
- Controllers
- Handle HTTP requests and coordinate between services and models
- Models
- Eloquent ORM models representing database entities and business logic
- Services
- Encapsulate complex business logic and external integrations
- Middleware
- Process HTTP requests and responses with cross-cutting concerns
- Jobs
- Asynchronous background tasks for heavy operations
Design Patterns¶
Model-View-Controller (MVC)¶
The application strictly follows the MVC pattern:
graph LR
A[HTTP Request] --> B[Route]
B --> C[Middleware]
C --> D[Controller]
D --> E[Service Layer]
E --> F[Model]
F --> G[Database]
D --> H[Response]
H --> I[JSON/View]
Active Record Pattern¶
The application uses Laravel's Active Record pattern via Eloquent ORM, with static methods for complex queries:
// Example: User model with static query methods
class User extends BaseModel
{
public static function getFilters($options = [])
{
// Static query methods for complex filtering
return self::select(['id', 'firstname', 'lastname', 'email'])
->where('isActive', 1)
->when($options['role_id'] ?? null, function($query, $roleId) {
return $query->where('role_id', $roleId);
})
->get();
}
}
Note: No repository pattern is implemented - the application follows Laravel's Active Record approach.
Service Layer Pattern¶
Business logic is encapsulated in service classes:
graph TB
A[Controller] --> B[Service Class]
B --> C[Model 1]
B --> D[Model 2]
B --> E[External API]
B --> F[Cache]
C --> G[Database]
D --> G
Actual Service Classes: - AuthService: JWT authentication and app source validation - BrewerySsoService: SSO infrastructure (not active) - ProjectService: Project-related business logic - UtilizationService: Resource utilization calculations - ProjectResourceService: Project resource management - PaymentMilestoneService: Payment milestone processing - FileUploadService: File upload operations - FileExportService: Report export functionality - UserService: User management operations
Database Layer¶
Eloquent ORM¶
The application uses Laravel's Eloquent ORM for database interactions:
- Base Model
- All models extend BaseModel with audit logging and authentication context
class BaseModel extends Model
{
protected $casts = [
'created_at' => 'datetime:Y-m-d H:i:s',
'updated_at' => 'datetime:Y-m-d H:i:s',
];
public static function getAuthUser()
{
// Get authenticated user from request context
}
// Automatic audit logging on delete
public static function boot()
{
parent::boot();
static::deleting(function($model) {
// Audit log implementation
});
}
}
- Model Relationships
- Comprehensive relationship definitions between entities
class Project extends BaseModel
{
public function client()
{
return $this->belongsTo(Client::class);
}
public function projectUsers()
{
return $this->hasMany(ProjectUser::class);
}
public function timelogs()
{
return $this->hasManyThrough(Timelog::class, ProjectUser::class);
}
}
Database Migrations¶
Comprehensive migration system for database schema management:
// Example migration structure
class CreateTimelogsTable extends Migration
{
public function up()
{
Schema::create('timelogs', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained();
$table->foreignId('project_user_id')->nullable()->constrained();
$table->foreignId('tasktype_id')->constrained();
$table->datetime('startTime');
$table->datetime('stopTime');
$table->decimal('spentHours', 8, 2);
$table->text('description');
$table->string('status')->default('pending');
$table->timestamps();
$table->softDeletes();
$table->index(['user_id', 'startTime']);
$table->index(['status', 'created_at']);
});
}
}
HTTP Layer¶
Routing Structure¶
The application uses a structured routing approach:
// API routes with versioning
Route::group(['prefix' => 'v2', 'middleware' => ['throttle:100,1']], function () {
// Authentication routes
Route::resource('authenticate', 'TokenAuthController');
// Protected routes
Route::group(['middleware' => ['my.jwt.auth']], function () {
Route::resource('timelogs', 'TimelogController');
Route::resource('projects', 'ProjectController');
// ... other resources
});
});
// Specialized module routes
include('sinop.php');
include('csat.php');
include('f1.php');
// ... other modules
Middleware Stack¶
Custom middleware handles cross-cutting concerns:
graph TB
A[HTTP Request] --> B[Throttle Middleware]
B --> C[CORS Middleware]
C --> D[Authentication Middleware]
D --> E[Authorization Middleware]
E --> F[Validation Middleware]
F --> G[Logging Middleware]
G --> H[Controller]
Key Middleware Components:
MyGetUserFromToken: Custom JWT authenticationAllowedAppSource: Application source validationValidateAllUserInputs: Input sanitizationLogAccess: Request logging and monitoring
Request Validation¶
Comprehensive input validation using Laravel's validation system:
class TimelogRequest extends FormRequest
{
public function rules()
{
return [
'startTime' => 'required|date',
'stopTime' => 'required|date|after:startTime',
'project_user_id' => 'required|exists:project_users,id',
'description' => 'required|string|max:1000',
'spentHours' => 'required|numeric|min:0.25|max:24'
];
}
}
Business Logic Layer¶
Service Classes¶
Business logic is organized into focused service classes:
class AuthService
{
public function authenticate($credentials)
{
// Authentication logic
}
public function checkAppAccessSource($request)
{
// App source validation
}
public function getNewToken($request)
{
// Token refresh logic
}
}
Event System¶
Laravel's event system handles business events:
// Event definition
class TimelogApproved
{
public $timelog;
public function __construct(Timelog $timelog)
{
$this->timelog = $timelog;
}
}
// Event listener
class SendApprovalNotification
{
public function handle(TimelogApproved $event)
{
// Send notification logic
}
}
Background Processing¶
Queue System¶
Asynchronous processing using Laravel Queues:
graph LR
A[Web Request] --> B[Dispatch Job]
B --> C[Queue]
C --> D[Worker Process]
D --> E[Job Execution]
E --> F[Database Update]
E --> G[Email Notification]
E --> H[External API Call]
Job Types:
- Email notifications
- Report generation
- Data synchronization
- File processing
- Cleanup tasks
Scheduled Tasks¶
Automated tasks using Laravel Scheduler:
protected function schedule(Schedule $schedule)
{
$schedule->command('timesheet:emailDeficiencyLevel1')
->monthlyOn(20, '07:00')
->onOneServer();
$schedule->command('timesheet:notifyProjectsNearDeadline')
->dailyAt('08:00')
->onOneServer();
$schedule->command('timesheet:emailOffsetSummaryForTheMonth')
->weekly()
->mondays()
->at('20:00')
->onOneServer();
}
Security Implementation¶
Authentication System¶
JWT-based authentication implementation:
sequenceDiagram
participant C as Client
participant M as JWT Middleware
participant A as Auth Service
participant D as Database
C->>M: Request with JWT Token
M->>A: Validate JWT Token
A->>D: Get User by Token Subject
D->>A: User Data
A->>M: Authentication Result
M->>C: Allow/Deny Request
Note: SSO authentication infrastructure exists but is not currently active.
Authorization System¶
Role-based access control implementation:
class User extends BaseModel
{
public function hasPermission($permissionId)
{
$permissions = explode(',', $this->permission_ids);
return in_array($permissionId, $permissions);
}
public function isApproverFor($userId)
{
// Check approval hierarchy
}
}
Data Encryption¶
Sensitive data encryption using Laravel's encryption:
use App\Http\Traits\EncryptableTrait;
class ProjectUser extends BaseModel
{
use EncryptableTrait;
protected $encryptable = [
'hourlySalary',
'sensitiveField'
];
}
API Design¶
RESTful API Structure¶
Consistent API design following REST principles:
GET /api/v2/timelogs # List timelogs
POST /api/v2/timelogs # Create timelog
GET /api/v2/timelogs/{id} # Show timelog
PUT /api/v2/timelogs/{id} # Update timelog
DELETE /api/v2/timelogs/{id} # Delete timelog
Response Format¶
Actual response format used in the application:
{
"header": {
"status": 200,
"title": "Resource Name",
"description": "Operation completed successfully"
},
"body": {
"data": [...]
}
}
Simple Response (Common):
{
"data": [...],
"pagination": {
"current_page": 1,
"last_page": 10,
"per_page": 50,
"total": 500
}
}
Performance Optimization¶
Caching Strategy¶
Multi-level caching implementation:
// Model-level caching
public static function getFilters()
{
$cacheName = 'users.filters';
return Cache::remember($cacheName, 3600, function () {
return self::select(['id', 'name', 'email'])
->where('is_active', 1)
->get();
});
}
Database Optimization¶
- Proper indexing on frequently queried columns
- Query optimization using Eloquent relationships
- Database connection pooling
- Read replica usage for reporting queries
Memory Management¶
- Efficient data loading with pagination
- Lazy loading of relationships
- Memory-conscious batch processing
- Garbage collection optimization
This backend architecture provides a solid foundation for the Stratpoint Timesheet Application, ensuring scalability, maintainability, and performance while supporting complex business requirements.