Files
hr/README.md

199 lines
7.3 KiB
Markdown

# HR Management System
Internal admin application for managing employee records, leave requests, disciplinary reports, bonuses, gifts, and document storage. Built on Laravel with a Filament admin panel.
**Stack:** Laravel 13, PHP 8.3+, Filament 5, SQLite (default) or MySQL, Vite + Tailwind 4.
**Key packages:** Filament Shield (RBAC), Language Switch, Spatie Activity Log, Maatwebsite Excel, DomPDF.
## Requirements
- PHP 8.3+, Composer, Node.js/npm
- SQLite extension (default) or MySQL/PostgreSQL if configured in `.env`
- Queue worker required for Excel imports (`ProcessImportJob`)
## Installation
### Quick setup (recommended)
```bash
composer setup
php artisan db:seed
```
`composer setup` runs: `composer install`, copies `.env`, `key:generate`, `migrate`, `npm install`, and `npm run build`.
### Manual setup
1. `composer install`
2. `cp .env.example .env` and configure the database if not using SQLite
3. `touch database/database.sqlite` (SQLite only)
4. `php artisan key:generate`
5. `php artisan migrate`
6. `php artisan db:seed`
7. `npm install && npm run build`
### Development
```bash
composer dev
```
Runs the HTTP server, queue listener, log tail (Pail), and Vite concurrently. The queue worker is required for Excel imports and full local development.
### Default admin credentials
- URL: `http://localhost:8000/admin`
- Email: `admin@company.com`
- Password: `password`
### Optional configuration
Set these in `.env` or see [`config/hr.php`](config/hr.php):
| Variable | Default | Description |
|----------|---------|-------------|
| `HR_COMPANY_NAME` | HR Management System | Company name shown in the panel |
| `HR_ANNUAL_LEAVE_DAYS` | 24 | Annual paid leave allowance per employee |
| `HR_LEAVE_CALCULATION` | `calendar` | Day counting mode: `calendar` or `business` |
## Application Structure
```
app/
├── Filament/ # Admin UI: Resources, Pages, Widgets, Concerns
│ ├── Resources/ # One resource per entity (Employee, Vacation, etc.)
│ ├── Pages/ # Dashboard, ImportWizard
│ └── Widgets/ # Stats, charts, upcoming birthdays/leaves
├── Models/ # Eloquent models + LogsHrActivity concern
├── Policies/ # Authorization (ScopedByDepartment concern)
├── Services/ # Business logic (leave calc, import, export, vacation balance)
├── Observers/ # Side effects on leave/report/document save
├── Imports/Exports/ # Excel import/export
└── Jobs/ # Async import processing
config/hr.php # Company settings, locales, file upload paths
lang/{en,tk,ru}/ # App translations (hr.php, enums.php, etc.)
database/seeders/ # Org data, roles, admin user, demo data
```
### Filament resource pattern
Each resource splits into dedicated subdirectories:
- `Schemas/` — form and infolist configuration
- `Tables/` — table columns, filters, actions
- `Pages/` — list, create, edit, view pages
- `RelationManagers/` — optional nested CRUD (e.g. Employee has 8 relation managers for vacations, leave, reports, bonuses, gifts, and documents)
### Navigation groups
| Group | Resources |
|-------|-----------|
| Organization | Departments, Positions, Shifts |
| Employees | Employee (central hub record) |
| Leave Management | Vacations, Sick Leave, Unpaid Leave |
| Records | Disciplinary Reports, Explanations, Bonuses, Gifts, Documents |
| System | Users, Activity Log, Shield roles |
## Domain Model and Relationships
**Employee** is the central entity — most HR records belong to an employee. **Department** scopes both employees and admin users. **User** (admin login) is separate from **Employee** (HR record); they are linked only by department for authorization scoping.
Organization tables (Department, Position, Shift) use soft deletes. Department auto-generates a unique `code` from its name on save.
```mermaid
erDiagram
Department ||--o{ Employee : has
Department ||--o{ User : has
Position ||--o{ Employee : has
Shift ||--o{ Employee : has
Employee ||--o{ Vacation : has
Employee ||--o{ SickLeave : has
Employee ||--o{ UnpaidLeave : has
Employee ||--o{ DisciplinaryReport : has
Employee ||--o{ Explanation : has
Employee ||--o{ Bonus : has
Employee ||--o{ Gift : has
Employee ||--o{ EmployeeDocument : has
User ||--o{ Vacation : approves
```
## Application Logic
### Entry points
- `/` — public welcome page only
- `/admin` — all HR functionality lives in the Filament admin panel
### Request and authorization flow
```mermaid
flowchart LR
UserLogin[Admin login] --> FilamentPanel[Filament /admin]
FilamentPanel --> Shield[Filament Shield roles]
Shield --> Policy[Model Policy]
Policy --> ScopedByDept[ScopedByDepartment]
ScopedByDept --> Resource[Filament Resource CRUD]
Resource --> Service[Service layer]
Service --> Model[Eloquent Model]
Model --> Observer[Observer hooks]
Model --> ActivityLog[Spatie Activity Log]
```
### Authorization
Three layers work together:
1. **Filament Shield** — role and permission management UI; `super_admin` bypasses all checks
2. **Policies** — 13 model policies registered in [`AppServiceProvider`](app/Providers/AppServiceProvider.php) enforce per-model CRUD rules
3. **`ScopedByDepartment`** — shared policy concern that scopes access by role:
- `administrator` / `hr_manager` — full access
- `supervisor` — read all records
- `department_manager` — scoped to own `department_id`
- `viewer` — read-only
Seeded roles: `super_admin`, `administrator`, `hr_manager`, `supervisor`, `department_manager`, `viewer`, `panel_user`.
### Leave workflow
- Vacations, sick leave, and unpaid leave use the `ApprovalStatus` enum (pending → approved/rejected)
- [`LeaveDaysCalculator`](app/Services/Leave/LeaveDaysCalculator.php) computes leave days using calendar or business-day mode from `config/hr.php`
- Observers on leave models handle status transitions and day calculations on save
- [`VacationBalanceService`](app/Services/Vacation/VacationBalanceService.php) tracks remaining annual leave against `HR_ANNUAL_LEAVE_DAYS`
### Import pipeline
1. **Import Wizard** (Filament page) accepts an Excel upload
2. Dispatches `ProcessImportJob` to the queue
3. Type-specific transformers in `app/Services/Import/` process employees, vacations, bonuses, or reports
4. Requires a running queue worker (`composer dev` starts one automatically)
### Audit trail
- The `LogsHrActivity` concern on HR models logs changes to fillable fields via Spatie Activity Log
- The **Activity Log** resource provides a read-only audit viewer in the admin panel
### Localization
- Supported locales: `en`, `tk`, `ru` ([`config/hr.php`](config/hr.php))
- User preference stored on `users.locale`; Language Switch persists the choice on change
- Labels come from `lang/*/hr.php`, `enums.php`, and the `HasHrResourceLabels` trait on Filament resources
### File uploads
Employee documents are stored on the `local` disk under `storage/app/hr/` (configurable in `config/hr.php`).
## Testing
```bash
composer test
# or: php artisan test
```
Tests live under `tests/Feature/` and include localization, model behavior (e.g. Department), and other feature coverage.
## License
Open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT).