# Penggajian

- Module key: `Penggajian`
- Category: `Payroll/Finance`
- Path: `app/Modules/Penggajian`

## Ringkasan

Penggajian berada di kategori Payroll/Finance. Modul ini memiliki 44 definisi route, 3 controller, 8 model, dan 13 view. Database module terdeteksi pada tabel: `payroll_payment_histories`, `payroll_reimbursement_requests`, `payroll_slip_profiles`, `thr_requests`, `thr_request_details`, `thr_payment_histories`, `payroll_payment_bpjs_details`.

## Flowchart

```mermaid
flowchart TD
    A[User / Operator] --> B[Menu Penggajian]
    B --> C[Routes: 44]
    C --> D[Controllers: 3]
    D --> E[Views: 13]
    D --> F[(Tables: 7<br/>payroll_payment_histories<br/>payroll_reimbursement_requests<br/>payroll_slip_profiles<br/>thr_requests<br/>thr_request_details)]
    D --> G[Validation / Business Rules]
    G --> F
    F --> H[Report / Export / Audit]
```


## Routes

- `Route::middleware(['auth', 'ip.block', 'menu.access'])->group(function () {`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::prefix('penggajian')->name('penggajian.')->group(function () {`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::get('/', [PenggajianController::class, 'index'])->name('index');`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::get('refs', [PenggajianController::class, 'refs'])->name('refs');`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::get('data', [PenggajianController::class, 'data'])->name('data');`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::post('process', [PenggajianController::class, 'startProcess'])->name('process.start');`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::get('process/{id}/status', [PenggajianController::class, 'processStatus'])->name('process.status');`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::get('process/{id}/result', [PenggajianController::class, 'processResult'])->name('process.result');`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::get('export-excel', [PenggajianController::class, 'exportExcel'])->name('export_excel');`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::get('export-slip-excel', [PenggajianController::class, 'exportSlipExcel'])->name('export_slip_excel');`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::get('export-pdf', [PenggajianController::class, 'exportPdf'])->name('export_pdf');`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::get('detail', [PenggajianController::class, 'detail'])->name('detail');`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::get('detail-pdf', [PenggajianController::class, 'detailPdf'])->name('detail_pdf');`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::get('report-bulanan', [PenggajianMonthlyReportController::class, 'index'])->name('report_bulanan');`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::get('report-bulanan-data', [PenggajianMonthlyReportController::class, 'data'])->name('report_bulanan_data');`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::get('report-template', [PenggajianController::class, 'reportTemplate'])->name('report_template');`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::get('report-thr-progresif', [PenggajianController::class, 'thrProgressiveReport'])->name('report_thr_progresif');`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::get('tax-proof', [PenggajianController::class, 'taxProof'])->name('tax_proof');`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::get('slip-print', [PenggajianController::class, 'slipPrint'])->name('slip_print');`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::get('slip-profiles/{id}/builder', [PenggajianController::class, 'slipBuilder'])->name('slip_profiles.builder');`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::post('slip-profiles/{id}/builder', [PenggajianController::class, 'slipBuilderSave'])->name('slip_profiles.builder_save');`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::get('slip-profiles', [PenggajianController::class, 'slipProfileIndex'])->name('slip_profiles.index');`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::get('slip-profiles/data', [PenggajianController::class, 'slipProfileData'])->name('slip_profiles.data');`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::post('slip-profiles', [PenggajianController::class, 'slipProfileStore'])->name('slip_profiles.store');`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::put('slip-profiles/{id}', [PenggajianController::class, 'slipProfileUpdate'])->name('slip_profiles.update');`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::delete('slip-profiles/{id}', [PenggajianController::class, 'slipProfileDestroy'])->name('slip_profiles.destroy');`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::post('mark-paid', [PenggajianController::class, 'markPaid'])->name('mark_paid');`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::post('unmark-paid', [PenggajianController::class, 'unmarkPaid'])->name('unmark_paid');`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::post('mark-paid-bulk', [PenggajianController::class, 'markPaidBulk'])->name('mark_paid.bulk');`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::post('unmark-paid-bulk', [PenggajianController::class, 'unmarkPaidBulk'])->name('unmark_paid.bulk');`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::put('cycle/{assignmentId}', [PenggajianController::class, 'updateCycle'])->name('cycle.update');`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::put('cycle-bulk', [PenggajianController::class, 'updateCycleBulk'])->name('cycle.bulk');`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::prefix('thr')->name('thr.')->group(function () {`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::get('/', [ThrController::class, 'index'])->name('index');`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::get('refs', [ThrController::class, 'refs'])->name('refs');`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::get('data', [ThrController::class, 'data'])->name('data');`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::get('details', [ThrController::class, 'details'])->name('details');`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::post('generate', [ThrController::class, 'generate'])->name('generate');`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::post('{id}/submit', [ThrController::class, 'submit'])->name('submit');`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::post('{id}/approve', [ThrController::class, 'approve'])->name('approve');`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::post('{id}/reject', [ThrController::class, 'reject'])->name('reject');`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::delete('{id}', [ThrController::class, 'destroy'])->name('destroy');`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::post('pay-detail', [ThrController::class, 'payDetail'])->name('pay_detail');`  
  File: `app/Modules/Penggajian/routes/web.php`
- `Route::get('report-year', [ThrController::class, 'reportYear'])->name('report_year');`  
  File: `app/Modules/Penggajian/routes/web.php`

## Controllers

- `app/Modules/Penggajian/Http/Controllers/PenggajianController.php`
- `app/Modules/Penggajian/Http/Controllers/PenggajianMonthlyReportController.php`
- `app/Modules/Penggajian/Http/Controllers/ThrController.php`

## Models

- `app/Modules/Penggajian/Models/PayrollPaymentBpjsDetailModel.php`
- `app/Modules/Penggajian/Models/PayrollPaymentHistoryModel.php`
- `app/Modules/Penggajian/Models/PayrollProcessJobModel.php`
- `app/Modules/Penggajian/Models/PayrollSlipProfileModel.php`
- `app/Modules/Penggajian/Models/ReimbursementRequestModel.php`
- `app/Modules/Penggajian/Models/ThrPaymentHistoryModel.php`
- `app/Modules/Penggajian/Models/ThrRequestDetailModel.php`
- `app/Modules/Penggajian/Models/ThrRequestModel.php`

## Views

- `app/Modules/Penggajian/Resources/views/detail.blade.php`
- `app/Modules/Penggajian/Resources/views/exports/payroll_detail_pdf.blade.php`
- `app/Modules/Penggajian/Resources/views/exports/payroll_export_pdf.blade.php`
- `app/Modules/Penggajian/Resources/views/index.blade.php`
- `app/Modules/Penggajian/Resources/views/report_bulanan.blade.php`
- `app/Modules/Penggajian/Resources/views/report_template.blade.php`
- `app/Modules/Penggajian/Resources/views/report_thr_progresif.blade.php`
- `app/Modules/Penggajian/Resources/views/slip_builder.blade.php`
- `app/Modules/Penggajian/Resources/views/slip_print.blade.php`
- `app/Modules/Penggajian/Resources/views/slip_profiles.blade.php`
- `app/Modules/Penggajian/Resources/views/tax_proof_pdf.blade.php`
- `app/Modules/Penggajian/Resources/views/thr_index.blade.php`
- `app/Modules/Penggajian/Resources/views/thr_report_year.blade.php`

## Database / Migration

### `payroll_payment_histories`
- Actions: `create`, `table`
- Columns: 37
  - `profil_bulan_karyawan_id:unsignedBigInteger`
  - `profil_bulan_id:unsignedBigInteger`
  - `karyawan_id:unsignedBigInteger`
  - `pay_date:date`
  - `period_start:date`
  - `period_end:date`
  - `nominal:decimal`
  - `status:string`
  - `marked_by:unsignedBigInteger`
  - `marked_at:dateTime`
  - `notes:text`
  - `profil_bulan_karyawan_id:foreign`
  - `profil_bulan_id:foreign`
  - `karyawan_id:foreign`
  - `marked_by:foreign`
  - `profil_bulan_id:index`
  - `profil_bulan_karyawan_id:index`
  - `gross_nominal:decimal`
  - `pph21_nominal:decimal`
  - `bpjs_nominal:decimal`
  - `reimburse_nominal:decimal`
  - `net_nominal:decimal`
  - `pph21_rate:decimal`
  - `bpjs_rate_total:decimal`
  - `bank_account_id:unsignedBigInteger`
  - `bank_account_id:foreign`
  - `tax_proof_no:string`
  - `tax_proof_no:dropColumn`
  - `pay_hist_bank_account_fk:dropForeign`
  - `bank_account_id:dropColumn`
  - `bpjs_rate_total:dropColumn`
  - `pph21_rate:dropColumn`
  - `net_nominal:dropColumn`
  - `reimburse_nominal:dropColumn`
  - `bpjs_nominal:dropColumn`
  - `pph21_nominal:dropColumn`
  - `gross_nominal:dropColumn`
- Migrations:
  - `app/Modules/Penggajian/Database/migrations/2026_02_26_150000_create_payroll_payment_histories_table.php`
  - `app/Modules/Penggajian/Database/migrations/2026_03_03_100200_add_payroll_components_to_payment_histories_table.php`
### `payroll_reimbursement_requests`
- Actions: `create`
- Columns: 18
  - `request_no:string`
  - `karyawan_id:foreignId`
  - `request_date:date`
  - `claim_date:date`
  - `category:string`
  - `description:text`
  - `amount:decimal`
  - `attachment_path:string`
  - `status:string`
  - `approved_by:unsignedBigInteger`
  - `approved_at:dateTime`
  - `rejected_reason:text`
  - `created_by:unsignedBigInteger`
  - `is_active:boolean`
  - `approved_by:foreign`
  - `created_by:foreign`
  - `karyawan_id:index`
  - `status:index`
- Migrations:
  - `app/Modules/Penggajian/Database/migrations/2026_03_03_100100_create_payroll_reimbursement_requests_table.php`
### `payroll_slip_profiles`
- Actions: `create`, `table`
- Columns: 16
  - `code:string`
  - `name:string`
  - `company_name:string`
  - `company_address:string`
  - `header_note:text`
  - `footer_note:text`
  - `show_logo:boolean`
  - `show_signature:boolean`
  - `show_npwp:boolean`
  - `show_bank_account:boolean`
  - `paper_size:string`
  - `orientation:string`
  - `is_default:boolean`
  - `is_active:boolean`
  - `layout_json:longText`
  - `layout_json:dropColumn`
- Migrations:
  - `app/Modules/Penggajian/Database/migrations/2026_03_03_130000_create_payroll_slip_profiles_table.php`
  - `app/Modules/Penggajian/Database/migrations/2026_03_03_140000_add_layout_json_to_payroll_slip_profiles_table.php`
### `thr_requests`
- Actions: `create`
- Columns: 18
  - `request_no:string`
  - `year:unsignedSmallInteger`
  - `profil_bulan_id:unsignedBigInteger`
  - `status:string`
  - `total_nominal:decimal`
  - `approved_nominal:decimal`
  - `paid_nominal:decimal`
  - `outstanding_nominal:decimal`
  - `submitted_by:unsignedBigInteger`
  - `submitted_at:dateTime`
  - `approved_by:unsignedBigInteger`
  - `approved_at:dateTime`
  - `notes:text`
  - `is_active:boolean`
  - `profil_bulan_id:foreign`
  - `submitted_by:foreign`
  - `approved_by:foreign`
  - `year:index`
- Migrations:
  - `app/Modules/Penggajian/Database/migrations/2026_03_03_150000_create_thr_requests_table.php`
### `thr_request_details`
- Actions: `create`
- Columns: 19
  - `thr_request_id:unsignedBigInteger`
  - `profil_bulan_karyawan_id:unsignedBigInteger`
  - `karyawan_id:unsignedBigInteger`
  - `employment_status:string`
  - `base_salary_monthly:decimal`
  - `prorate_months:decimal`
  - `prorate_factor:decimal`
  - `thr_nominal:decimal`
  - `approved_nominal:decimal`
  - `paid_nominal:decimal`
  - `outstanding_nominal:decimal`
  - `status:string`
  - `last_paid_at:dateTime`
  - `notes:text`
  - `thr_request_id:foreign`
  - `profil_bulan_karyawan_id:foreign`
  - `karyawan_id:foreign`
  - `thr_request_id:unique`
  - `status:index`
- Migrations:
  - `app/Modules/Penggajian/Database/migrations/2026_03_03_150100_create_thr_request_details_table.php`
### `thr_payment_histories`
- Actions: `create`
- Columns: 18
  - `thr_request_id:unsignedBigInteger`
  - `thr_request_detail_id:unsignedBigInteger`
  - `karyawan_id:unsignedBigInteger`
  - `pay_date:date`
  - `amount:decimal`
  - `payment_method:string`
  - `reference_no:string`
  - `bank_account_id:unsignedBigInteger`
  - `tax_no:string`
  - `status:string`
  - `paid_by:unsignedBigInteger`
  - `notes:text`
  - `thr_request_id:foreign`
  - `thr_request_detail_id:foreign`
  - `karyawan_id:foreign`
  - `paid_by:foreign`
  - `pay_date:index`
  - `karyawan_id:index`
- Migrations:
  - `app/Modules/Penggajian/Database/migrations/2026_03_03_150200_create_thr_payment_histories_table.php`
### `payroll_payment_bpjs_details`
- Actions: `create`, `table`
- Columns: 21
  - `payment_history_id:foreignId`
  - `karyawan_id:foreignId`
  - `bpjs_id:foreignId`
  - `component_code:string`
  - `component_name:string`
  - `basis_type:enum`
  - `basis_source_nominal:decimal`
  - `ceiling_nominal:decimal`
  - `basis_nominal:decimal`
  - `rate_company_percent:decimal`
  - `rate_employee_percent:decimal`
  - `company_nominal:decimal`
  - `employee_nominal:decimal`
  - `is_enrolled:boolean`
  - `deduct_to_payroll:boolean`
  - `notes:text`
  - `payment_history_id:index`
  - `ceiling_min_nominal:decimal`
  - `ceiling_max_nominal:decimal`
  - `ceiling_max_nominal:dropColumn`
  - `ceiling_min_nominal:dropColumn`
- Migrations:
  - `app/Modules/Penggajian/Database/migrations/2026_04_21_165000_create_payroll_payment_bpjs_details_table.php`
  - `app/Modules/Penggajian/Database/migrations/2026_04_24_150100_add_min_max_to_payroll_payment_bpjs_details_table.php`
