Initial commit
This commit is contained in:
@@ -0,0 +1,598 @@
|
||||
<?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'
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user