# CƠ CHẾ TÍNH LƯƠNG CHI TIẾT

## 📊 TỔNG QUAN

Hệ thống tính lương tự động dựa trên:
- Cơ cấu lương nhân viên
- Dữ liệu chấm công thực tế
- Lịch làm việc công ty
- Nghỉ phép và OT
- Các quy định phạt có thể cấu hình

---

## 🔹 1. CẤU TRÚC LƯƠNG (Salary Structure)

Mỗi nhân viên có cơ cấu lương bao gồm:

### Các thành phần lương:
- **Lương cơ bản** (basic_salary)
- **Phụ cấp nhà ở** (housing_allowance)
- **Phụ cấp đi lại** (transport_allowance)
- **Phụ cấp khác** (other_allowances)

### Thông tin bổ sung:
- **Ngày hiệu lực** (effective_from) - cho phép thay đổi lương theo thời gian
- **Trạng thái nhân viên**: 
  - Thử việc (probation)
  - Thực tập (intern)
  - Chính thức (official)
- **Tỷ lệ lương thử việc** (probation_percent) - VD: 85% lương chính thức
- **Số ngày phép còn lại** (remaining_leave_days)

### Ví dụ cơ cấu lương:
```
Nhân viên: Nguyễn Văn A
- Lương cơ bản: 10,000,000 VNĐ
- Phụ cấp nhà ở: 1,000,000 VNĐ
- Phụ cấp đi lại: 500,000 VNĐ
- Phụ cấp khác: 500,000 VNĐ
- Trạng thái: Thử việc (85%)
- Ngày hiệu lực: 01/05/2025
- Ngày phép còn lại: 12 ngày
```

---

## 🔹 2. QUY TRÌNH TÍNH LƯƠNG (PayrollService)

### Bước 1: Kiểm tra điều kiện

✅ Kiểm tra nhân viên có cơ cấu lương chưa
✅ Kiểm tra đã đăng ký lịch làm việc chưa (WorkSchedule)
✅ Kiểm tra lịch làm việc công ty trong tháng (WorkCalendar)
✅ Kiểm tra bảng lương tháng này đã tính chưa (tránh trùng)

### Bước 2: Tính lương cơ bản theo giai đoạn

Hệ thống hỗ trợ **nhiều cơ cấu lương trong 1 tháng** (VD: tăng lương giữa tháng)

#### Ví dụ: Tháng 5/2025 (31 ngày)
```
Giai đoạn 1 (Ngày 1-15): 
- Lương: 10,000,000 VNĐ
- Trạng thái: Thử việc 85%
- Tính toán: 10,000,000 × 85% × (15/31) = 4,112,903 VNĐ

Giai đoạn 2 (Ngày 16-31):
- Lương: 12,000,000 VNĐ
- Trạng thái: Chính thức 100%
- Tính toán: 12,000,000 × 100% × (16/31) = 6,193,548 VNĐ

→ Tổng lương cơ bản: 10,306,451 VNĐ
```

#### Công thức:
```
Lương giai đoạn = Lương tháng × Tỷ lệ trạng thái × (Số ngày giai đoạn / Tổng ngày tháng)
```

### Bước 3: Tính phụ cấp

Tương tự lương cơ bản, phụ cấp cũng được tính theo tỷ lệ ngày và trạng thái nhân viên.

```
Phụ cấp giai đoạn = (Phụ cấp nhà ở + Phụ cấp đi lại + Phụ cấp khác) × Tỷ lệ × (Số ngày / Tổng ngày)
```

### Bước 4: Tính lương 1 ngày công

```
Lương 1 ngày = (Tổng lương cơ bản + Tổng phụ cấp) / Số ngày làm việc trong tháng
```

#### Ví dụ:
```
Tổng lương cơ bản: 10,000,000 VNĐ
Tổng phụ cấp: 2,000,000 VNĐ
Số ngày làm việc: 22 ngày (theo WorkCalendar)

→ Lương 1 ngày = 12,000,000 / 22 = 545,454 VNĐ
```

### Bước 5: Xử lý chấm công

#### Tự động tạo bản ghi vắng mặt:
- Hệ thống kiểm tra tất cả ngày làm việc trong WorkCalendar
- Nếu ngày nào chưa có chấm công → Tự động tạo bản ghi "Absent"

#### Thống kê chấm công:
- **Đi làm** (present_days): Có check-in hoặc check-out
- **Vắng mặt** (absent_days): Không có chấm công
- **Nghỉ có phép** (approved_leave_days): Đã xin phép và được duyệt

### Bước 6: Tính giờ làm thực tế

```
Giờ làm thực = Giờ ra - Giờ vào - Thời gian nghỉ trưa
```

#### Ví dụ:
```
Check-in: 08:30
Check-out: 18:00
Nghỉ trưa: 12:00 - 13:30 (1.5 giờ)

Tính toán:
- Tổng giờ: 18:00 - 08:30 = 9.5 giờ
- Trừ nghỉ trưa: 9.5 - 1.5 = 8 giờ
→ Giờ làm thực: 8 giờ
```

#### Phân loại ngày công:
- **Đủ công**: Làm ≥ 8 giờ (có thể config trong `minimum_working_hours`)
- **Thiếu công**: Làm < 8 giờ

---

## 🔹 3. HỆ THỐNG PHẠT (Penalty System)

### A. Cấu hình phạt (AttendancePenaltyConfig)

Tất cả mức phạt được lưu trong database, có thể thay đổi:

| Loại vi phạm | Mức phạt mặc định | Key config |
|-------------|------------------|------------|
| Đi muộn/về sớm 5-15 phút | 20,000 VNĐ | `late_fine_5_15_minutes` |
| Đi muộn/về sớm 15-30 phút | 30,000 VNĐ | `late_fine_15_30_minutes` |
| Đi muộn/về sớm >30 phút | 100,000 VNĐ | `late_fine_30_plus_minutes` |
| Quên chấm công | 100,000 VNĐ | `forgot_punch_fine` |
| Thời gian ân hạn | 5 phút | `attendance_grace_time` |
| Miễn phạt quên chấm công | 3 lần | `max_forgot_free` |
| Miễn phạt đi muộn/về sớm | 3 lần | `max_late_early_free` |
| Ngưỡng trừ ngày công | 6 lần | `late_early_day_penalty_threshold` |
| Giờ làm tối thiểu | 8 giờ | `minimum_working_hours` |
| Hệ số OT | 1.5 | `ot_coefficient` |
| Giờ bắt đầu nghỉ trưa | 12:00:00 | `lunch_start_time` |
| Giờ kết thúc nghỉ trưa | 13:30:00 | `lunch_end_time` |

### B. Quy tắc phạt đi muộn/về sớm

#### Bước 1: Tính số phút vi phạm
```
Đi muộn = Giờ vào thực tế - Giờ vào quy định - Thời gian ân hạn
Về sớm = Giờ ra quy định - Giờ ra thực tế - Thời gian ân hạn
```

#### Ví dụ tính đi muộn:
```
Giờ vào quy định: 08:00
Giờ vào thực tế: 08:20
Thời gian ân hạn: 5 phút

→ Số phút đi muộn: 20 - 5 = 15 phút
→ Mức phạt: 20,000 VNĐ (theo bảng phạt 5-15 phút)
```

#### Bước 2: Miễn phạt 3 lần đầu
```
Ví dụ: Đi muộn 5 lần trong tháng (mỗi lần 10 phút)

Lần 1: Miễn phạt (0 VNĐ)
Lần 2: Miễn phạt (0 VNĐ)
Lần 3: Miễn phạt (0 VNĐ)
Lần 4: Phạt 20,000 VNĐ
Lần 5: Phạt 20,000 VNĐ

→ Tổng phạt tiền: 40,000 VNĐ
```

#### Bước 3: Trừ ngày công nếu vi phạm >6 lần
```
Ví dụ: Đi muộn 8 lần trong tháng

Lần 1-3: Miễn phạt (0 VNĐ)
Lần 4-6: Phạt tiền (3 × 20,000 = 60,000 VNĐ)
Lần 7-8: Trừ ngày công (2 × lương 1 ngày)

Nếu lương 1 ngày = 545,454 VNĐ
→ Phạt tiền: 60,000 VNĐ
→ Trừ ngày công: 2 × 545,454 = 1,090,908 VNĐ
→ Tổng phạt: 1,150,908 VNĐ
```

### C. Quy tắc phạt quên chấm công

#### Định nghĩa quên chấm công:
- Thiếu check-in HOẶC thiếu check-out (không phải cả 2)
- Nếu thiếu cả 2 → Tính là nghỉ không phép

#### Quy tắc phạt:
```
Ví dụ: Quên chấm công 5 lần trong tháng

Lần 1: Miễn phạt (0 VNĐ)
Lần 2: Miễn phạt (0 VNĐ)
Lần 3: Miễn phạt (0 VNĐ)
Lần 4: Phạt 100,000 VNĐ
Lần 5: Phạt 100,000 VNĐ

→ Tổng phạt: 200,000 VNĐ
```

### D. Phạt vắng mặt không phép

```
Nghỉ không phép = Trừ lương 1 ngày công

Ví dụ:
- Vắng mặt 2 ngày không xin phép
- Lương 1 ngày: 545,454 VNĐ
→ Tổng phạt: 2 × 545,454 = 1,090,908 VNĐ
```

### E. Chi tiết vi phạm được lưu vào bảng AttendancePenalty

Mỗi lần vi phạm được ghi nhận chi tiết:
```
- employee_id: ID nhân viên
- date: Ngày vi phạm
- type: late / early_leave / missing_punch / leave_unpaid
- minutes: Số phút vi phạm
- amount: Số tiền phạt
- note: Ghi chú chi tiết (VD: "Đi muộn 15 phút")
```

---

## 🔹 4. NGHỈ PHÉP (Leave Management)

### Quy tắc nghỉ phép có lương:

#### Điều kiện:
1. Chỉ tính loại nghỉ **"Casual"** (nghỉ phép thường)
2. Phải được **phê duyệt** (status = 'Approved')
3. Mỗi tháng được nghỉ **tối đa 1 ngày có lương**
4. Trừ vào số ngày phép còn lại trong cơ cấu lương

#### Ví dụ:
```
Nhân viên có 12 ngày phép/năm còn lại
Tháng này xin nghỉ 2 ngày Casual (đã duyệt)

Hệ thống tính:
- Ngày 1: Được hưởng lương (paid_leave_days_taken = 1)
- Ngày 2: Trừ lương 1 ngày công (545,454 VNĐ)
- Số ngày phép còn lại: 12 - 1 = 11 ngày

→ Tổng trừ lương: 545,454 VNĐ
```

### Các loại nghỉ phép:

| Loại nghỉ | Tên | Xử lý |
|-----------|-----|-------|
| Casual | Nghỉ phép thường | Tối đa 1 ngày/tháng có lương |
| Sick Leave | Nghỉ ốm | Trừ lương |
| Unpaid Leave | Nghỉ không lương | Trừ lương |
| Late | Xin đi muộn | KHÔNG trừ ngày công, chỉ ghi nhận |

### Nghỉ nửa ngày (Half-Day Leave):

Hệ thống hỗ trợ **nghỉ nửa ngày** bằng cách tích checkbox "Nghỉ nửa ngày" khi xin phép.

#### Cách tính:
```
Nghỉ nửa ngày = 0.5 ngày công

Ví dụ:
- Nhân viên xin nghỉ 1 ngày (is_half_day = true)
- Lương 1 ngày: 545,454 VNĐ
→ Chỉ trừ: 545,454 × 0.5 = 272,727 VNĐ
```

#### Lưu ý:
- Nếu chọn "Nghỉ nửa ngày" nhưng nghỉ nhiều ngày (VD: 3 ngày)
- Hệ thống sẽ tính: 3 × 0.5 = 1.5 ngày công
- Khuyến nghị: Chỉ chọn "Nghỉ nửa ngày" khi nghỉ 1 ngày duy nhất

### Lưu ý quan trọng:
- Nghỉ phép **"Late"** (xin đi muộn) KHÔNG tính vào tổng số ngày nghỉ
- Tránh trường hợp xin đi muộn 30 phút nhưng bị trừ cả ngày lương
- **Nghỉ nửa ngày** giúp nhân viên linh hoạt hơn khi chỉ cần nghỉ buổi sáng/chiều

---

## 🔹 5. TĂNG CA (Overtime)

### Công thức tính tiền OT:
```
Tiền OT = Số giờ OT × Lương 1 giờ × Hệ số OT
```

### Trong đó:
```
Lương 1 giờ = Lương 1 ngày / Giờ làm tối thiểu
Hệ số OT = 1.5 (mặc định, có thể config)
```

### Ví dụ chi tiết:
```
Lương 1 ngày: 545,454 VNĐ
Giờ làm tối thiểu: 8 giờ
→ Lương 1 giờ: 545,454 / 8 = 68,181 VNĐ

OT trong tháng: 4 giờ
Hệ số OT: 1.5

→ Tiền OT: 4 × 68,181 × 1.5 = 409,086 VNĐ
```

### Điều kiện tính OT:
- Phải có bản ghi trong bảng `overtimes`
- Trạng thái: **Approved** (đã duyệt)
- Thuộc tháng tính lương

---

## 🔹 6. THU NHẬP BỔ SUNG (Additional Income)

### Các loại thu nhập bổ sung:
- Thưởng dự án
- Hoa hồng bán hàng
- Phụ cấp đặc biệt
- Thưởng hiệu suất
- Các khoản khác

### Cách tính:
```
Tổng thu nhập bổ sung = SUM(amount) từ bảng additional_incomes
```

### Ví dụ:
```
Tháng 5/2025:
- Thưởng dự án: 2,000,000 VNĐ
- Hoa hồng: 1,500,000 VNĐ
- Phụ cấp đặc biệt: 500,000 VNĐ

→ Tổng thu nhập bổ sung: 4,000,000 VNĐ
```

---

## 🔹 7. KHẤU TRỪ (Deductions)

### Các khoản khấu trừ thủ công:
- BHXH (Bảo hiểm xã hội): 8% lương cơ bản
- BHYT (Bảo hiểm y tế): 1.5% lương cơ bản
- BHTN (Bảo hiểm thất nghiệp): 1% lương cơ bản
- Thuế TNCN (Thuế thu nhập cá nhân)
- Tạm ứng
- Các khoản khác

### Ví dụ:
```
Lương cơ bản: 10,000,000 VNĐ

BHXH: 10,000,000 × 8% = 800,000 VNĐ
BHYT: 10,000,000 × 1.5% = 150,000 VNĐ
BHTN: 10,000,000 × 1% = 100,000 VNĐ
Tạm ứng: 2,000,000 VNĐ

→ Tổng khấu trừ: 3,050,000 VNĐ
```

### Lưu ý:
- Khấu trừ được nhập thủ công vào bảng `deductions`
- Mỗi nhân viên mỗi tháng có 1 bản ghi khấu trừ

---

## 🔹 8. CÔNG THỨC TÍNH LƯƠNG CUỐI CÙNG

### Công thức tổng quát:
```
LƯƠNG THỰC NHẬN = 
  Lương cơ bản
  + Phụ cấp
  + Tiền OT
  + Thu nhập bổ sung
  - Khấu trừ thủ công
  - Phạt đi muộn/về sớm (sau 3 lần miễn phí)
  - Phạt trừ ngày công (nếu vi phạm >6 lần)
  - Phạt quên chấm công (sau 3 lần miễn phí)
  - Phạt vắng mặt không phép
  - Phạt nghỉ phép vượt hạn mức
```

### Ví dụ tính lương đầy đủ:

#### Thông tin nhân viên:
```
Tên: Nguyễn Văn A
Tháng: 05/2025
Số ngày làm việc: 22 ngày
```

#### Thu nhập:
```
1. Lương cơ bản: 10,000,000 VNĐ
2. Phụ cấp nhà ở: 1,000,000 VNĐ
3. Phụ cấp đi lại: 500,000 VNĐ
4. Phụ cấp khác: 500,000 VNĐ
5. Tiền OT (4 giờ): 409,086 VNĐ
6. Thưởng dự án: 2,000,000 VNĐ

→ Tổng thu nhập: 14,409,086 VNĐ
```

#### Khấu trừ:
```
1. BHXH + BHYT + BHTN: 1,050,000 VNĐ
2. Tạm ứng: 2,000,000 VNĐ
3. Đi muộn 5 lần (sau miễn 3 lần): 40,000 VNĐ
4. Quên chấm công 4 lần (sau miễn 3 lần): 100,000 VNĐ
5. Nghỉ phép vượt hạn mức (1 ngày): 545,454 VNĐ

→ Tổng khấu trừ: 3,735,454 VNĐ
```

#### Lương thực nhận:
```
14,409,086 - 3,735,454 = 10,673,632 VNĐ
```

---

## 🔹 9. DỮ LIỆU LƯU TRONG BẢNG PAYROLL

### Cấu trúc bảng payrolls:
```php
- id: ID bảng lương
- employee_id: ID nhân viên
- month: Tháng tính lương (2025-05-01)
- basic_salary: Tổng lương cơ bản
- allowances: Tổng phụ cấp
- deductions: Khấu trừ thủ công (BHXH, thuế, tạm ứng...)
- other_income: Thu nhập bổ sung (thưởng, hoa hồng...)
- penalty_amount: Tổng tiền phạt chấm công
- ot_amount: Tiền OT
- net_salary: Lương thực nhận
- intern_days: Số ngày làm với trạng thái thực tập
- probation_days: Số ngày làm với trạng thái thử việc
- official_days: Số ngày làm với trạng thái chính thức
- present_days: Số ngày đi làm
- absent_days: Số ngày vắng mặt
- approved_leave_days: Số ngày nghỉ có phép (Casual)
- paid_leave_days_taken: Số ngày phép được hưởng lương
- status: Processed / Paid
- processed_by: ID người xử lý
- created_at: Ngày tạo
- updated_at: Ngày cập nhật
```

### Ví dụ dữ liệu:
```json
{
  "id": 1,
  "employee_id": 5,
  "month": "2025-05-01",
  "basic_salary": 10000000,
  "allowances": 2000000,
  "deductions": 3050000,
  "other_income": 2000000,
  "penalty_amount": 685454,
  "ot_amount": 409086,
  "net_salary": 10673632,
  "intern_days": 0,
  "probation_days": 0,
  "official_days": 22,
  "present_days": 20,
  "absent_days": 2,
  "approved_leave_days": 2,
  "paid_leave_days_taken": 1,
  "status": "Processed",
  "processed_by": 1
}
```

---

## 🔹 10. CHI TIẾT VI PHẠM (AttendancePenalty)

### Cấu trúc bảng attendance_penalties:
```php
- id: ID vi phạm
- employee_id: ID nhân viên
- date: Ngày vi phạm
- type: Loại vi phạm
  + late: Đi muộn
  + early_leave: Về sớm
  + missing_punch: Quên chấm công
  + leave_unpaid: Nghỉ không phép
- minutes: Số phút vi phạm (null nếu không áp dụng)
- amount: Số tiền phạt
- note: Ghi chú chi tiết
- created_at: Ngày tạo
```

### Ví dụ dữ liệu:
```json
[
  {
    "id": 1,
    "employee_id": 5,
    "date": "2025-05-10",
    "type": "late",
    "minutes": 15,
    "amount": 20000,
    "note": "Đi muộn 15 phút"
  },
  {
    "id": 2,
    "employee_id": 5,
    "date": "2025-05-15",
    "type": "early_leave",
    "minutes": 20,
    "amount": 20000,
    "note": "Về sớm 20 phút"
  },
  {
    "id": 3,
    "employee_id": 5,
    "date": "2025-05-20",
    "type": "missing_punch",
    "minutes": null,
    "amount": 100000,
    "note": "Quên chấm công (thiếu vào/ra)"
  }
]
```

---

## 🔹 11. TÍNH NĂNG ĐẶC BIỆT

### A. Hỗ trợ nhiều cơ cấu lương trong 1 tháng
- Nhân viên được tăng lương giữa tháng
- Chuyển từ thử việc sang chính thức
- Hệ thống tự động tính tỷ lệ theo số ngày

### B. Tự động tạo bản ghi chấm công
- Dựa trên WorkCalendar (lịch làm việc công ty)
- Tự động đánh dấu "Absent" nếu không chấm công
- Tránh thiếu sót dữ liệu

### C. Miễn phạt 3 lần đầu (Nhân văn)
- Đi muộn/về sớm: Miễn 3 lần
- Quên chấm công: Miễn 3 lần
- Khuyến khích nhân viên cải thiện

### D. Trừ ngày công nếu vi phạm nhiều
- Đi muộn/về sớm >6 lần: Từ lần 7 trừ 1 ngày công/lần
- Răn đe vi phạm thường xuyên

### E. Lưu chi tiết từng vi phạm
- Tra cứu lịch sử vi phạm
- Minh bạch trong tính lương
- Giải quyết khiếu nại

### F. Tích hợp máy chấm công ZKTeco
- Lấy dữ liệu tự động từ máy chấm công
- Đồng bộ real-time
- Giảm thiểu sai sót thủ công

---

## 🔹 12. LƯU Ý QUAN TRỌNG

### ⚠️ Điều kiện bắt buộc trước khi tính lương:
1. ✅ Nhân viên phải có cơ cấu lương (SalaryStructure)
2. ✅ Nhân viên phải đăng ký lịch làm việc (WorkSchedule)
3. ✅ Công ty phải có lịch làm việc tháng đó (WorkCalendar)
4. ✅ Chưa tính lương tháng này (tránh trùng)

### ⚠️ Thứ tự ưu tiên khi tính lương:
1. Lương cơ bản + Phụ cấp (theo cơ cấu)
2. Thu nhập bổ sung (OT, thưởng)
3. Khấu trừ thủ công (BHXH, thuế)
4. Phạt chấm công (đi muộn, quên chấm công)
5. Phạt nghỉ phép vượt hạn

### ⚠️ Xử lý nghỉ phép:
- Nghỉ phép "Late" (xin đi muộn) KHÔNG trừ ngày công
- Chỉ nghỉ phép "Casual" mới được tính vào quỹ phép có lương
- Tối đa 1 ngày/tháng được hưởng lương khi nghỉ phép

### ⚠️ Xử lý chấm công:
- Thiếu check-in HOẶC check-out: Quên chấm công (phạt 100k sau 3 lần)
- Thiếu CẢ check-in VÀ check-out: Nghỉ không phép (trừ 1 ngày công)

---

## 🔹 13. CÁCH SỬ DỤNG

### Tính lương cho 1 nhân viên:
```php
POST /payrolls/store
{
  "employee_id": 5,
  "month": "2025-05"
}
```

### Tính lương cho tất cả nhân viên:
```php
POST /payrolls/calculate-all
{
  "month": "2025-05"
}
```

### Xuất phiếu lương PDF:
```php
GET /payrolls/{id}/payslip
```

### Xuất báo cáo Excel:
```php
GET /payrolls/export
```

---

## 🔹 14. KẾT LUẬN

Hệ thống tính lương này được thiết kế:

✅ **Tự động hóa cao**: Giảm thiểu thao tác thủ công
✅ **Linh hoạt**: Hỗ trợ nhiều cơ cấu lương, thay đổi giữa tháng
✅ **Minh bạch**: Lưu chi tiết từng vi phạm, dễ tra cứu
✅ **Nhân văn**: Miễn phạt 3 lần đầu, khuyến khích cải thiện
✅ **Công bằng**: Tính toán chính xác theo quy định
✅ **Dễ cấu hình**: Tất cả mức phạt có thể thay đổi trong database

---

**Tài liệu này được tạo tự động từ source code**
**Phiên bản: 1.0**
**Ngày cập nhật: 04/12/2025**
