Files
accounting_dev/application/controllers/Payroll.php
T
2026-05-26 08:07:45 +00:00

598 lines
14 KiB
PHP

<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Payroll extends CI_Controller {
public function __construct()
{
parent::__construct();
$this->load->database();
date_default_timezone_set('Asia/Jakarta');
}
// =====================================================
// INDEX
// =====================================================
public function index()
{
$data = [
'active_menu' => 'payroll'
];
$this->load->view('partials/header',$data);
$this->load->view('employees/payroll');
$this->load->view('partials/footer');
}
// =====================================================
// GET DATA
// =====================================================
public function get_data()
{
$month = $this->input->post('month');
$this->db->select("
p.*,
e.full_name,
pp.period_name,
pp.start_date,
pp.end_date
");
$this->db->from('k_payrolls p');
$this->db->join(
'k_employees e',
'e.id = p.employee_id'
);
$this->db->join(
'k_payroll_periods pp',
'pp.id = p.payroll_period_id'
);
if($month){
$this->db->where(
'DATE_FORMAT(pp.start_date,"%Y-%m")',
$month
);
}
$this->db->order_by(
'e.full_name',
'ASC'
);
$rows = $this->db->get()->result();
$data = [];
$no = 1;
foreach($rows as $row){
$pendapatan =
(
$row->allowance_amount
+
$row->bonus_amount
+
$row->overtime_amount
);
$potongan =
(
$row->deduction_amount
+
$row->bpjs_kesehatan_amount
+
$row->bpjs_ketenagakerjaan_amount
+
$row->tax_amount
+
$row->attendance_cut_amount
);
$status = '';
if($row->payment_status == 'paid'){
$status = '
<span class="badge bg-success">
Paid
</span>
';
} else {
$status = '
<span class="badge bg-warning text-dark">
Draft
</span>
';
}
$data[] = [
$no++,
$row->full_name,
'Rp '.number_format(
$row->basic_salary,
0,
',',
'.'
),
'Rp '.number_format(
$pendapatan,
0,
',',
'.'
),
'Rp '.number_format(
$potongan,
0,
',',
'.'
),
'Rp '.number_format(
$row->total_salary,
0,
',',
'.'
),
$status,
'
<button
class="btn btn-sm btn-warning btn-edit"
data-id="'.$row->id.'">
<i class="fa fa-edit"></i>
Edit
</button>
'
];
}
echo json_encode([
'data' => $data
]);
}
// =====================================================
// DETAIL
// =====================================================
public function detail($id)
{
$this->db->select("
p.*,
e.full_name
");
$this->db->from('k_payrolls p');
$this->db->join(
'k_employees e',
'e.id = p.employee_id'
);
$this->db->where(
'p.id',
$id
);
$payroll = $this->db->get()->row();
if(!$payroll){
echo json_encode([
'status' => false,
'message' => 'Payroll tidak ditemukan'
]);
return;
}
$items = $this->db
->where('payroll_id',$id)
->order_by('id','ASC')
->get('k_payroll_items')
->result();
echo json_encode([
'status' => true,
'payroll' => $payroll,
'employee' => [
'full_name' => $payroll->full_name
],
'items' => $items
]);
}
// =====================================================
// SAVE ITEMS
// =====================================================
public function save_items()
{
$payrollId = $this->input->post('payroll_id');
$items = $this->input->post('items');
$payroll = $this->db
->where('id',$payrollId)
->get('k_payrolls')
->row();
if(!$payroll){
echo json_encode([
'status' => false,
'message' => 'Payroll tidak ditemukan'
]);
return;
}
// =========================================
// DELETE OLD ITEMS
// =========================================
$this->db
->where('payroll_id',$payrollId)
->delete('k_payroll_items');
$allowance = 0;
$bonus = 0;
$overtime = 0;
$deduction = 0;
$bpjs = 0;
$tax = 0;
if($items){
foreach($items as $item){
$amount = (float)$item['amount'];
$insert = [
'payroll_id' => $payrollId,
'item_type' => $item['item_type'],
'item_name' => $item['item_name'],
'amount' => $amount
];
$this->db->insert(
'k_payroll_items',
$insert
);
switch($item['item_type']){
case 'allowance':
$allowance += $amount;
break;
case 'bonus':
$bonus += $amount;
break;
case 'overtime':
$overtime += $amount;
break;
case 'deduction':
$deduction += $amount;
break;
case 'bpjs':
$bpjs += $amount;
break;
case 'tax':
$tax += $amount;
break;
}
}
}
// =========================================
// TOTAL
// =========================================
$totalSalary =
(
$payroll->basic_salary
+
$allowance
+
$bonus
+
$overtime
)
-
(
$deduction
+
$bpjs
+
$tax
+
$payroll->attendance_cut_amount
);
// =========================================
// UPDATE PAYROLL
// =========================================
$this->db
->where('id',$payrollId)
->update(
'k_payrolls',
[
'allowance_amount' => $allowance,
'bonus_amount' => $bonus,
'overtime_amount' => $overtime,
'deduction_amount' => $deduction,
'bpjs_kesehatan_amount' => $bpjs,
'tax_amount' => $tax,
'total_salary' => $totalSalary
]
);
echo json_encode([
'status' => true,
'message' => 'Payroll berhasil disimpan'
]);
}
// =====================================================
// GENERATE PAYROLL
// =====================================================
public function generate_payroll()
{
$month = $this->input->post('month');
if(!$month){
echo json_encode([
'status' => false,
'message' => 'Bulan wajib dipilih'
]);
return;
}
$startDate = date(
'Y-m-01',
strtotime($month)
);
$endDate = date(
'Y-m-t',
strtotime($month)
);
// =========================================
// PERIOD
// =========================================
$period = $this->db
->where('start_date',$startDate)
->where('end_date',$endDate)
->get('k_payroll_periods')
->row();
if(!$period){
$this->db->insert(
'k_payroll_periods',
[
'period_name' => date(
'F Y',
strtotime($startDate)
),
'start_date' => $startDate,
'end_date' => $endDate,
'status' => 'draft',
'generated_at' => date('Y-m-d H:i:s')
]
);
$periodId = $this->db->insert_id();
} else {
$periodId = $period->id;
}
// =========================================
// EMPLOYEES
// =========================================
$employees = $this->db
->where('is_active',1)
->get('k_employees')
->result();
foreach($employees as $employee){
// =====================================
// ATTENDANCE
// =====================================
$attendance = $this->db
->select("
COUNT(*) as total_work_days,
SUM(attendance_status='present')
as total_present,
SUM(attendance_status='alpha')
as total_alpha,
SUM(overtime_hours)
as total_overtime_hours
")
->where('employee_id',$employee->id)
->where('attendance_date >=',$startDate)
->where('attendance_date <=',$endDate)
->get('k_attendances')
->row();
$dailySalary =
$employee->basic_salary / 30;
$alphaCut =
(
$attendance->total_alpha
* $dailySalary
);
$overtimeRate = 25000;
$overtimeAmount =
(
$attendance->total_overtime_hours
* $overtimeRate
);
$totalSalary =
(
$employee->basic_salary
+ $overtimeAmount
)
- $alphaCut;
$exist = $this->db
->where(
'payroll_period_id',
$periodId
)
->where(
'employee_id',
$employee->id
)
->get('k_payrolls')
->row();
$data = [
'payroll_period_id' => $periodId,
'employee_id' => $employee->id,
'basic_salary' => $employee->basic_salary,
'total_work_days' => (
$attendance->total_work_days ?? 0
),
'total_present' => (
$attendance->total_present ?? 0
),
'total_alpha' => (
$attendance->total_alpha ?? 0
),
'total_overtime_hours' => (
$attendance->total_overtime_hours ?? 0
),
'attendance_cut_amount' => $alphaCut,
'overtime_amount' => $overtimeAmount,
'total_salary' => $totalSalary
];
if($exist){
$this->db
->where('id',$exist->id)
->update(
'k_payrolls',
$data
);
} else {
$this->db->insert(
'k_payrolls',
$data
);
$payrollId = $this->db->insert_id();
// =================================
// AUTO ITEM OVERTIME
// =================================
if($overtimeAmount > 0){
$this->db->insert(
'k_payroll_items',
[
'payroll_id' => $payrollId,
'item_type' => 'overtime',
'item_name' => 'Lembur',
'amount' => $overtimeAmount
]
);
}
// =================================
// AUTO ITEM ALPHA
// =================================
if($alphaCut > 0){
$this->db->insert(
'k_payroll_items',
[
'payroll_id' => $payrollId,
'item_type' => 'deduction',
'item_name' => 'Potongan Alpha',
'amount' => $alphaCut
]
);
}
}
}
echo json_encode([
'status' => true,
'message' => 'Payroll berhasil digenerate'
]);
}
}