Initial commit
This commit is contained in:
@@ -0,0 +1,644 @@
|
||||
<?php
|
||||
defined('BASEPATH') OR exit('No direct script access allowed');
|
||||
|
||||
class Scheduler extends CI_Controller {
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->load->database();
|
||||
|
||||
date_default_timezone_set('Asia/Jakarta');
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// PROCESS ATTENDANCE LOG
|
||||
// =====================================================
|
||||
public function process_attendance()
|
||||
{
|
||||
echo "PROCESS ATTENDANCE START\n";
|
||||
|
||||
// =============================================
|
||||
// GET PENDING LOG
|
||||
// =============================================
|
||||
$logs = $this->db
|
||||
->where('process_status','pending')
|
||||
->order_by('check_time','ASC')
|
||||
->limit(1000)
|
||||
->get('k_attendance_logs')
|
||||
->result();
|
||||
|
||||
foreach($logs as $log){
|
||||
|
||||
try{
|
||||
|
||||
// =====================================
|
||||
// GET EMPLOYEE
|
||||
// =====================================
|
||||
$employee = $this->db
|
||||
->where(
|
||||
'fingerprint_user_id',
|
||||
$log->user_id
|
||||
)
|
||||
->where('is_active',1)
|
||||
->get('k_employees')
|
||||
->row();
|
||||
|
||||
if(!$employee){
|
||||
|
||||
$this->updateLogStatus(
|
||||
$log->id,
|
||||
'failed'
|
||||
);
|
||||
|
||||
echo "FAILED EMPLOYEE : {$log->user_id}\n";
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// =====================================
|
||||
// UPDATE EMPLOYEE ID
|
||||
// =====================================
|
||||
$this->db
|
||||
->where('id',$log->id)
|
||||
->update(
|
||||
'k_attendance_logs',
|
||||
[
|
||||
'employee_id' => $employee->id
|
||||
]
|
||||
);
|
||||
|
||||
$logDateTime = date(
|
||||
'Y-m-d H:i:s',
|
||||
strtotime($log->check_time)
|
||||
);
|
||||
|
||||
// =====================================
|
||||
// FIND SCHEDULE
|
||||
// SUPPORT SHIFT MALAM
|
||||
// =====================================
|
||||
$this->db->from(
|
||||
'k_employee_shift_schedules'
|
||||
);
|
||||
|
||||
$this->db->where(
|
||||
'employee_id',
|
||||
$employee->id
|
||||
);
|
||||
|
||||
$this->db->where(
|
||||
'status',
|
||||
'published'
|
||||
);
|
||||
|
||||
// =====================================
|
||||
// RANGE SHIFT
|
||||
// =====================================
|
||||
$this->db->where("
|
||||
'{$logDateTime}' BETWEEN
|
||||
DATE_SUB(start_datetime, INTERVAL 3 HOUR)
|
||||
AND
|
||||
DATE_ADD(end_datetime, INTERVAL 6 HOUR)
|
||||
", null, false);
|
||||
|
||||
$this->db->order_by(
|
||||
'start_datetime',
|
||||
'DESC'
|
||||
);
|
||||
|
||||
$schedule = $this->db->get()->row();
|
||||
|
||||
// =====================================
|
||||
// SCHEDULE NOT FOUND
|
||||
// =====================================
|
||||
if(!$schedule){
|
||||
|
||||
$this->updateLogStatus(
|
||||
$log->id,
|
||||
'failed'
|
||||
);
|
||||
|
||||
echo "FAILED SCHEDULE : {$logDateTime}\n";
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// =====================================
|
||||
// GET SHIFT
|
||||
// =====================================
|
||||
$shift = $this->db
|
||||
->where('id',$schedule->shift_id)
|
||||
->get('k_shifts')
|
||||
->row();
|
||||
|
||||
if(!$shift){
|
||||
|
||||
$this->updateLogStatus(
|
||||
$log->id,
|
||||
'failed'
|
||||
);
|
||||
|
||||
echo "FAILED SHIFT : {$schedule->shift_id}\n";
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// =====================================
|
||||
// ATTENDANCE DATE
|
||||
// =====================================
|
||||
$attendance_date = date(
|
||||
'Y-m-d',
|
||||
strtotime($schedule->start_datetime)
|
||||
);
|
||||
|
||||
// =====================================
|
||||
// GET ATTENDANCE
|
||||
// =====================================
|
||||
$attendance = $this->db
|
||||
->where(
|
||||
'employee_id',
|
||||
$employee->id
|
||||
)
|
||||
->where(
|
||||
'attendance_date',
|
||||
$attendance_date
|
||||
)
|
||||
->get('k_attendances')
|
||||
->row();
|
||||
|
||||
// =====================================
|
||||
// CHECK LATE
|
||||
// =====================================
|
||||
$late_minutes = 0;
|
||||
|
||||
$maxCheckin = strtotime(
|
||||
$schedule->start_datetime
|
||||
) + (
|
||||
$shift->late_tolerance_minutes * 60
|
||||
);
|
||||
|
||||
if(
|
||||
strtotime($logDateTime)
|
||||
>
|
||||
$maxCheckin
|
||||
){
|
||||
|
||||
$late_minutes = floor(
|
||||
(
|
||||
strtotime($logDateTime)
|
||||
-
|
||||
strtotime($schedule->start_datetime)
|
||||
) / 60
|
||||
);
|
||||
|
||||
if($late_minutes < 0){
|
||||
$late_minutes = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// =====================================
|
||||
// INSERT CHECKIN
|
||||
// =====================================
|
||||
if(!$attendance){
|
||||
|
||||
$this->db->insert(
|
||||
'k_attendances',
|
||||
[
|
||||
|
||||
'employee_id' => $employee->id,
|
||||
|
||||
'attendance_date' => $attendance_date,
|
||||
|
||||
'checkin_time' => $logDateTime,
|
||||
|
||||
'late_minutes' => $late_minutes,
|
||||
|
||||
'attendance_status' => (
|
||||
$late_minutes > 0
|
||||
? 'late'
|
||||
: 'present'
|
||||
),
|
||||
|
||||
'shift_id' => $shift->id,
|
||||
|
||||
'attendance_log_in_id' => $log->id,
|
||||
|
||||
'created_at' => date('Y-m-d H:i:s')
|
||||
]
|
||||
);
|
||||
|
||||
echo "CHECKIN : {$employee->full_name}\n";
|
||||
|
||||
} else {
|
||||
|
||||
// =================================
|
||||
// SUDAH ADA CHECKOUT
|
||||
// =================================
|
||||
if(!empty($attendance->checkout_time)){
|
||||
|
||||
$this->updateLogStatus(
|
||||
$log->id,
|
||||
'processed'
|
||||
);
|
||||
|
||||
echo "SKIP LOG (SUDAH CHECKOUT)\n";
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// =================================
|
||||
// CEK SELISIH JAM
|
||||
// =================================
|
||||
$diffMinutes = floor(
|
||||
(
|
||||
strtotime($logDateTime)
|
||||
-
|
||||
strtotime($attendance->checkin_time)
|
||||
) / 60
|
||||
);
|
||||
|
||||
// =================================
|
||||
// MINIMAL 2 JAM
|
||||
// BARU DIANGGAP CHECKOUT
|
||||
// =================================
|
||||
if($diffMinutes < 120){
|
||||
|
||||
$this->updateLogStatus(
|
||||
$log->id,
|
||||
'processed'
|
||||
);
|
||||
|
||||
echo "SKIP DUPLICATE LOG : {$employee->full_name}\n";
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// =================================
|
||||
// WORK HOURS
|
||||
// =================================
|
||||
$workHours = (
|
||||
strtotime($logDateTime)
|
||||
-
|
||||
strtotime($attendance->checkin_time)
|
||||
) / 3600;
|
||||
|
||||
if($workHours < 0){
|
||||
$workHours = 0;
|
||||
}
|
||||
|
||||
// =================================
|
||||
// EARLY LEAVE
|
||||
// =================================
|
||||
$early_leave_minutes = 0;
|
||||
|
||||
if(
|
||||
strtotime($logDateTime)
|
||||
<
|
||||
strtotime($schedule->end_datetime)
|
||||
){
|
||||
|
||||
$early_leave_minutes = floor(
|
||||
(
|
||||
strtotime($schedule->end_datetime)
|
||||
-
|
||||
strtotime($logDateTime)
|
||||
) / 60
|
||||
);
|
||||
|
||||
if($early_leave_minutes < 0){
|
||||
$early_leave_minutes = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// =================================
|
||||
// OVERTIME
|
||||
// =================================
|
||||
$overtime_hours = 0;
|
||||
|
||||
if(
|
||||
strtotime($logDateTime)
|
||||
>
|
||||
strtotime($schedule->end_datetime)
|
||||
){
|
||||
|
||||
$overtime_hours = round(
|
||||
(
|
||||
strtotime($logDateTime)
|
||||
-
|
||||
strtotime($schedule->end_datetime)
|
||||
) / 3600,
|
||||
2
|
||||
);
|
||||
|
||||
if($overtime_hours < 0){
|
||||
$overtime_hours = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// =================================
|
||||
// UPDATE CHECKOUT
|
||||
// =================================
|
||||
$this->db
|
||||
->where(
|
||||
'id',
|
||||
$attendance->id
|
||||
)
|
||||
->update(
|
||||
'k_attendances',
|
||||
[
|
||||
|
||||
'checkout_time' => $logDateTime,
|
||||
|
||||
'attendance_log_out_id' => $log->id,
|
||||
|
||||
'work_hours' => round($workHours,2),
|
||||
|
||||
'early_leave_minutes' => $early_leave_minutes,
|
||||
|
||||
'overtime_hours' => $overtime_hours
|
||||
]
|
||||
);
|
||||
|
||||
echo "CHECKOUT : {$employee->full_name}\n";
|
||||
}
|
||||
|
||||
// =====================================
|
||||
// UPDATE LOG STATUS
|
||||
// =====================================
|
||||
$this->updateLogStatus(
|
||||
$log->id,
|
||||
'processed'
|
||||
);
|
||||
|
||||
echo "SUCCESS LOG ID : {$log->id}\n";
|
||||
|
||||
} catch(Exception $e){
|
||||
|
||||
$this->updateLogStatus(
|
||||
$log->id,
|
||||
'failed'
|
||||
);
|
||||
|
||||
echo "ERROR : " . $e->getMessage() . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
echo "PROCESS ATTENDANCE DONE\n";
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// AUTO CLOSE ATTENDANCE
|
||||
// =====================================================
|
||||
public function auto_close_attendance()
|
||||
{
|
||||
echo "AUTO CLOSE START\n";
|
||||
|
||||
// =============================================
|
||||
// AMBIL ATTENDANCE BELUM CHECKOUT
|
||||
// =============================================
|
||||
$attendances = $this->db
|
||||
->where('checkout_time IS NULL', null, false)
|
||||
->get('k_attendances')
|
||||
->result();
|
||||
|
||||
foreach($attendances as $attendance){
|
||||
|
||||
// =========================================
|
||||
// GET SCHEDULE
|
||||
// =========================================
|
||||
$schedule = $this->db
|
||||
->where(
|
||||
'employee_id',
|
||||
$attendance->employee_id
|
||||
)
|
||||
->where(
|
||||
'shift_id',
|
||||
$attendance->shift_id
|
||||
)
|
||||
->where(
|
||||
'DATE(start_datetime)',
|
||||
$attendance->attendance_date
|
||||
)
|
||||
->get('k_employee_shift_schedules')
|
||||
->row();
|
||||
|
||||
if(!$schedule){
|
||||
continue;
|
||||
}
|
||||
|
||||
// =========================================
|
||||
// AUTO CLOSE
|
||||
// END SHIFT + 4 JAM
|
||||
// =========================================
|
||||
$autoCloseTime = date(
|
||||
'Y-m-d H:i:s',
|
||||
strtotime(
|
||||
$schedule->end_datetime . ' +4 hours'
|
||||
)
|
||||
);
|
||||
|
||||
// =========================================
|
||||
// BELUM WAKTUNYA
|
||||
// =========================================
|
||||
if(
|
||||
strtotime(date('Y-m-d H:i:s'))
|
||||
<
|
||||
strtotime($autoCloseTime)
|
||||
){
|
||||
continue;
|
||||
}
|
||||
|
||||
// =========================================
|
||||
// WORK HOURS
|
||||
// =========================================
|
||||
$workHours = (
|
||||
strtotime($schedule->end_datetime)
|
||||
-
|
||||
strtotime($attendance->checkin_time)
|
||||
) / 3600;
|
||||
|
||||
if($workHours < 0){
|
||||
$workHours = 0;
|
||||
}
|
||||
|
||||
// =========================================
|
||||
// AUTO CHECKOUT
|
||||
// =========================================
|
||||
$this->db
|
||||
->where('id',$attendance->id)
|
||||
->update(
|
||||
'k_attendances',
|
||||
[
|
||||
|
||||
'checkout_time' => $schedule->end_datetime,
|
||||
|
||||
'work_hours' => round($workHours,2),
|
||||
|
||||
'notes' => 'Auto checkout by system'
|
||||
]
|
||||
);
|
||||
|
||||
echo "AUTO CLOSE EMPLOYEE : {$attendance->employee_id}\n";
|
||||
}
|
||||
|
||||
echo "AUTO CLOSE DONE\n";
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// GENERATE DAILY ATTENDANCE
|
||||
// =====================================================
|
||||
public function generate_daily_attendance()
|
||||
{
|
||||
echo "GENERATE DAILY START\n";
|
||||
|
||||
// =============================================
|
||||
// GENERATE HARI KEMARIN
|
||||
// =============================================
|
||||
$date = date(
|
||||
'Y-m-d',
|
||||
strtotime('-1 day')
|
||||
);
|
||||
|
||||
// =============================================
|
||||
// GET ALL SCHEDULE
|
||||
// =============================================
|
||||
$schedules = $this->db
|
||||
->where('schedule_date', $date)
|
||||
->where('status','published')
|
||||
->get('k_employee_shift_schedules')
|
||||
->result();
|
||||
|
||||
foreach($schedules as $schedule){
|
||||
|
||||
// =========================================
|
||||
// CHECK ATTENDANCE EXIST
|
||||
// =========================================
|
||||
$attendance = $this->db
|
||||
->where(
|
||||
'employee_id',
|
||||
$schedule->employee_id
|
||||
)
|
||||
->where(
|
||||
'attendance_date',
|
||||
$date
|
||||
)
|
||||
->get('k_attendances')
|
||||
->row();
|
||||
|
||||
if($attendance){
|
||||
continue;
|
||||
}
|
||||
|
||||
// =========================================
|
||||
// CHECK HOLIDAY
|
||||
// =========================================
|
||||
$holiday = $this->db
|
||||
->where('holiday_date',$date)
|
||||
->get('k_holidays')
|
||||
->row();
|
||||
|
||||
if($holiday){
|
||||
|
||||
$this->db->insert(
|
||||
'k_attendances',
|
||||
[
|
||||
|
||||
'employee_id' => $schedule->employee_id,
|
||||
|
||||
'attendance_date' => $date,
|
||||
|
||||
'attendance_status' => 'holiday',
|
||||
|
||||
'is_holiday' => 1,
|
||||
|
||||
'shift_id' => $schedule->shift_id,
|
||||
|
||||
'notes' => $holiday->holiday_name
|
||||
]
|
||||
);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// =========================================
|
||||
// CHECK LEAVE
|
||||
// =========================================
|
||||
$leave = $this->db
|
||||
->where(
|
||||
'employee_id',
|
||||
$schedule->employee_id
|
||||
)
|
||||
->where(
|
||||
'approval_status',
|
||||
'approved'
|
||||
)
|
||||
->where('start_date <=',$date)
|
||||
->where('end_date >=',$date)
|
||||
->get('k_leave_requests')
|
||||
->row();
|
||||
|
||||
if($leave){
|
||||
|
||||
$this->db->insert(
|
||||
'k_attendances',
|
||||
[
|
||||
|
||||
'employee_id' => $schedule->employee_id,
|
||||
|
||||
'attendance_date' => $date,
|
||||
|
||||
'attendance_status' => $leave->leave_type,
|
||||
|
||||
'shift_id' => $schedule->shift_id,
|
||||
|
||||
'notes' => $leave->reason
|
||||
]
|
||||
);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// =========================================
|
||||
// DEFAULT ALPHA
|
||||
// =========================================
|
||||
$this->db->insert(
|
||||
'k_attendances',
|
||||
[
|
||||
|
||||
'employee_id' => $schedule->employee_id,
|
||||
|
||||
'attendance_date' => $date,
|
||||
|
||||
'attendance_status' => 'alpha',
|
||||
|
||||
'shift_id' => $schedule->shift_id,
|
||||
|
||||
'notes' => 'Tidak hadir'
|
||||
]
|
||||
);
|
||||
|
||||
echo "GENERATE EMPLOYEE : {$schedule->employee_id}\n";
|
||||
}
|
||||
|
||||
echo "GENERATE DAILY DONE\n";
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// UPDATE LOG STATUS
|
||||
// =====================================================
|
||||
private function updateLogStatus(
|
||||
$id,
|
||||
$status
|
||||
){
|
||||
|
||||
$this->db
|
||||
->where('id',$id)
|
||||
->update(
|
||||
'k_attendance_logs',
|
||||
[
|
||||
'process_status' => $status
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user