598 lines
14 KiB
PHP
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'
|
|
]);
|
|
}
|
|
} |