768 lines
20 KiB
PHP
768 lines
20 KiB
PHP
<?php
|
|
defined('BASEPATH') OR exit('No direct script access allowed');
|
|
|
|
class Generateschedule extends CI_Controller {
|
|
|
|
public function __construct()
|
|
{
|
|
parent::__construct();
|
|
|
|
$this->load->database();
|
|
|
|
date_default_timezone_set('Asia/Jakarta');
|
|
}
|
|
|
|
// =====================================================
|
|
// INDEX
|
|
// =====================================================
|
|
public function index()
|
|
{
|
|
$data = [
|
|
"active_menu" => "generate_schedule"
|
|
];
|
|
|
|
// ============================================
|
|
// POSITIONS
|
|
// ============================================
|
|
$data['positions'] = $this->db
|
|
->where('is_active',1)
|
|
->order_by('position_name','ASC')
|
|
->get('k_positions')
|
|
->result();
|
|
|
|
// ============================================
|
|
// SHIFTS
|
|
// ============================================
|
|
$data['shifts'] = $this->db
|
|
->order_by('shift_code','ASC')
|
|
->get('k_shifts')
|
|
->result();
|
|
|
|
$this->load->view('partials/header', $data);
|
|
$this->load->view('employees/generate_schedule', $data);
|
|
$this->load->view('partials/footer');
|
|
}
|
|
|
|
// =====================================================
|
|
// CALENDAR DATA
|
|
// =====================================================
|
|
public function calendar_data()
|
|
{
|
|
$month = (int)$this->input->get('month');
|
|
$year = (int)$this->input->get('year');
|
|
|
|
if(empty($month)){
|
|
$month = date('n');
|
|
}
|
|
|
|
if(empty($year)){
|
|
$year = date('Y');
|
|
}
|
|
|
|
$firstDate = $year . '-'
|
|
. str_pad($month,2,'0',STR_PAD_LEFT)
|
|
. '-01';
|
|
|
|
// ============================================
|
|
// START MONDAY
|
|
// ============================================
|
|
$startDate = date(
|
|
'Y-m-d',
|
|
strtotime('monday this week', strtotime($firstDate))
|
|
);
|
|
|
|
if(date('N', strtotime($firstDate)) == 1){
|
|
$startDate = $firstDate;
|
|
}
|
|
|
|
// ============================================
|
|
// END SUNDAY
|
|
// ============================================
|
|
$lastDate = date(
|
|
'Y-m-t',
|
|
strtotime($firstDate)
|
|
);
|
|
|
|
$endDate = date(
|
|
'Y-m-d',
|
|
strtotime('sunday this week', strtotime($lastDate))
|
|
);
|
|
|
|
$days = [];
|
|
|
|
$current = strtotime($startDate);
|
|
$end = strtotime($endDate);
|
|
|
|
while($current <= $end){
|
|
|
|
$date = date('Y-m-d', $current);
|
|
|
|
// ========================================
|
|
// GET SCHEDULE GROUP BY SHIFT
|
|
// ========================================
|
|
$this->db->select('
|
|
sh.id as shift_id,
|
|
sh.shift_name,
|
|
|
|
p.position_name,
|
|
|
|
COUNT(s.id) as total_employee
|
|
');
|
|
|
|
$this->db->from('k_employee_shift_schedules s');
|
|
|
|
$this->db->join(
|
|
'k_employees e',
|
|
'e.id = s.employee_id',
|
|
'left'
|
|
);
|
|
|
|
$this->db->join(
|
|
'k_positions p',
|
|
'p.id = e.position_id',
|
|
'left'
|
|
);
|
|
|
|
$this->db->join(
|
|
'k_shifts sh',
|
|
'sh.id = s.shift_id',
|
|
'left'
|
|
);
|
|
|
|
$this->db->where('DATE(s.start_datetime)', $date);
|
|
|
|
// ========================================
|
|
// GROUPING
|
|
// ========================================
|
|
$this->db->group_by('sh.id');
|
|
$this->db->group_by('p.id');
|
|
|
|
$this->db->order_by('sh.checkin_time','ASC');
|
|
$this->db->order_by('p.position_name','ASC');
|
|
|
|
$rows = $this->db->get()->result();
|
|
|
|
// ========================================
|
|
// FORMAT GROUPED
|
|
// ========================================
|
|
$grouped = [];
|
|
|
|
if($rows){
|
|
|
|
foreach($rows as $r){
|
|
|
|
$shiftId = $r->shift_id ?: 0;
|
|
|
|
if(!isset($grouped[$shiftId])){
|
|
|
|
$grouped[$shiftId] = [
|
|
|
|
'shift_id' => $r->shift_id,
|
|
|
|
'shift_name' => $r->shift_name ?: '-',
|
|
|
|
'positions' => []
|
|
];
|
|
}
|
|
|
|
$grouped[$shiftId]['positions'][] = [
|
|
|
|
'position_name' => $r->position_name ?: '-',
|
|
|
|
'total' => (int)$r->total_employee
|
|
];
|
|
}
|
|
}
|
|
|
|
$days[] = [
|
|
|
|
'date' => date('d', strtotime($date)),
|
|
|
|
'month' => date('M', strtotime($date)),
|
|
|
|
'day_name' => $this->translateDay(
|
|
date('l', strtotime($date))
|
|
),
|
|
|
|
'full_date' => tanggal_indo($date),
|
|
|
|
'full_date_raw' => $date,
|
|
|
|
'is_current_month' => (
|
|
date('m', strtotime($date))
|
|
==
|
|
str_pad($month,2,'0',STR_PAD_LEFT)
|
|
),
|
|
|
|
'shifts' => array_values($grouped)
|
|
];
|
|
|
|
$current = strtotime('+1 day', $current);
|
|
}
|
|
|
|
echo json_encode([
|
|
'days' => $days
|
|
]);
|
|
}
|
|
|
|
// =====================================================
|
|
// GET EMPLOYEE
|
|
// =====================================================
|
|
public function get_employees()
|
|
{
|
|
$position_id = $this->input->get('position_id');
|
|
|
|
$this->db->select('
|
|
e.id,
|
|
e.full_name,
|
|
e.fingerprint_user_id,
|
|
|
|
p.position_name
|
|
');
|
|
|
|
$this->db->from('k_employees e');
|
|
|
|
$this->db->join(
|
|
'k_positions p',
|
|
'p.id=e.position_id',
|
|
'left'
|
|
);
|
|
|
|
$this->db->where('e.is_active',1);
|
|
|
|
if(!empty($position_id)){
|
|
$this->db->where('e.position_id',$position_id);
|
|
}
|
|
|
|
$this->db->order_by('e.full_name','ASC');
|
|
|
|
$employees = $this->db->get()->result();
|
|
|
|
echo json_encode([
|
|
'data' => $employees
|
|
]);
|
|
}
|
|
|
|
// =====================================================
|
|
// SAVE MANUAL SCHEDULE
|
|
// =====================================================
|
|
public function save_manual_schedule()
|
|
{
|
|
try{
|
|
|
|
$employee_ids = $this->input->post('employee_ids');
|
|
|
|
$schedule_date = $this->input->post('schedule_date');
|
|
|
|
$shift_id = $this->input->post('shift_id');
|
|
|
|
// ============================================
|
|
// VALIDASI
|
|
// ============================================
|
|
if(empty($employee_ids)){
|
|
throw new Exception('Employee belum dipilih');
|
|
}
|
|
|
|
if(empty($schedule_date)){
|
|
throw new Exception('Tanggal wajib diisi');
|
|
}
|
|
|
|
if(empty($shift_id)){
|
|
throw new Exception('Shift wajib dipilih');
|
|
}
|
|
|
|
// ============================================
|
|
// GET SHIFT
|
|
// ============================================
|
|
$shift = $this->db
|
|
->where('id', $shift_id)
|
|
->get('k_shifts')
|
|
->row();
|
|
|
|
if(!$shift){
|
|
throw new Exception('Shift tidak ditemukan');
|
|
}
|
|
|
|
// ============================================
|
|
// BUILD START DATETIME
|
|
// ============================================
|
|
$start_datetime = date(
|
|
'Y-m-d H:i:s',
|
|
strtotime(
|
|
$schedule_date . ' ' . $shift->checkin_time
|
|
)
|
|
);
|
|
|
|
// ============================================
|
|
// BUILD END DATETIME
|
|
// ============================================
|
|
$end_datetime = date(
|
|
'Y-m-d H:i:s',
|
|
strtotime(
|
|
$schedule_date . ' ' . $shift->checkout_time
|
|
)
|
|
);
|
|
|
|
// ============================================
|
|
// JIKA SHIFT NYEBRANG HARI
|
|
// ============================================
|
|
$is_cross_day = 0;
|
|
|
|
if(
|
|
strtotime($shift->checkout_time)
|
|
<=
|
|
strtotime($shift->checkin_time)
|
|
){
|
|
|
|
$end_datetime = date(
|
|
'Y-m-d H:i:s',
|
|
strtotime('+1 day', strtotime($end_datetime))
|
|
);
|
|
|
|
$is_cross_day = 1;
|
|
}
|
|
|
|
// ============================================
|
|
// HITUNG TOTAL JAM KERJA
|
|
// ============================================
|
|
$work_hours = (
|
|
strtotime($end_datetime)
|
|
-
|
|
strtotime($start_datetime)
|
|
) / 3600;
|
|
|
|
// ============================================
|
|
// LOOP EMPLOYEE
|
|
// ============================================
|
|
foreach($employee_ids as $employee_id){
|
|
|
|
// ========================================
|
|
// CHECK EXIST
|
|
// ========================================
|
|
$exists = $this->db
|
|
->where('employee_id', $employee_id)
|
|
->where('schedule_date', $schedule_date)
|
|
->get('k_employee_shift_schedules')
|
|
->row();
|
|
|
|
// ========================================
|
|
// DATA SAVE
|
|
// ========================================
|
|
$saveData = [
|
|
|
|
'employee_id' => $employee_id,
|
|
|
|
'shift_id' => $shift_id,
|
|
|
|
'start_datetime' => $start_datetime,
|
|
|
|
'end_datetime' => $end_datetime,
|
|
|
|
'work_hours' => $work_hours,
|
|
|
|
'is_cross_day' => $is_cross_day,
|
|
|
|
'schedule_source' => 'manual',
|
|
|
|
'notes' => 'manual planner',
|
|
|
|
'updated_at' => date('Y-m-d H:i:s')
|
|
];
|
|
|
|
// ========================================
|
|
// UPDATE
|
|
// ========================================
|
|
if($exists){
|
|
|
|
$this->db
|
|
->where('id', $exists->id)
|
|
->update(
|
|
'k_employee_shift_schedules',
|
|
$saveData
|
|
);
|
|
|
|
// ========================================
|
|
// INSERT
|
|
// ========================================
|
|
} else {
|
|
|
|
$saveData['created_at'] = date('Y-m-d H:i:s');
|
|
|
|
$this->db->insert(
|
|
'k_employee_shift_schedules',
|
|
$saveData
|
|
);
|
|
}
|
|
}
|
|
|
|
echo json_encode([
|
|
'status' => true,
|
|
'message' => 'Jadwal berhasil disimpan'
|
|
]);
|
|
|
|
} catch(Exception $e){
|
|
|
|
echo json_encode([
|
|
'status' => false,
|
|
'message' => $e->getMessage()
|
|
]);
|
|
}
|
|
}
|
|
|
|
// =====================================================
|
|
// TRANSLATE DAY
|
|
// =====================================================
|
|
private function translateDay($day)
|
|
{
|
|
$days = [
|
|
'Sunday' => 'Minggu',
|
|
'Monday' => 'Senin',
|
|
'Tuesday' => 'Selasa',
|
|
'Wednesday' => 'Rabu',
|
|
'Thursday' => 'Kamis',
|
|
'Friday' => 'Jumat',
|
|
'Saturday' => 'Sabtu'
|
|
];
|
|
|
|
return isset($days[$day])
|
|
? $days[$day]
|
|
: $day;
|
|
}
|
|
|
|
// =====================================================
|
|
// DETAIL SCHEDULE
|
|
// =====================================================
|
|
public function detail_schedule()
|
|
{
|
|
$schedule_date = $this->input->get('schedule_date');
|
|
|
|
if(empty($schedule_date)){
|
|
|
|
echo json_encode([
|
|
'status' => false,
|
|
'message'=> 'Tanggal wajib diisi',
|
|
'data' => []
|
|
]);
|
|
|
|
return;
|
|
}
|
|
|
|
// ============================================
|
|
// GET DATA
|
|
// ============================================
|
|
$this->db->select('
|
|
s.id as schedule_id,
|
|
|
|
s.employee_id,
|
|
s.shift_id,
|
|
|
|
s.start_datetime,
|
|
s.end_datetime,
|
|
|
|
e.employee_code,
|
|
e.full_name,
|
|
e.fingerprint_user_id,
|
|
|
|
p.id as position_id,
|
|
p.position_name,
|
|
|
|
sh.shift_name,
|
|
sh.checkin_time,
|
|
sh.checkout_time,
|
|
sh.color
|
|
');
|
|
|
|
$this->db->from('k_employee_shift_schedules s');
|
|
|
|
$this->db->join(
|
|
'k_employees e',
|
|
'e.id=s.employee_id',
|
|
'left'
|
|
);
|
|
|
|
$this->db->join(
|
|
'k_positions p',
|
|
'p.id=e.position_id',
|
|
'left'
|
|
);
|
|
|
|
$this->db->join(
|
|
'k_shifts sh',
|
|
'sh.id=s.shift_id',
|
|
'left'
|
|
);
|
|
|
|
// ============================================
|
|
// FILTER DATE
|
|
// ============================================
|
|
$this->db->where(
|
|
'DATE(s.start_datetime)',
|
|
$schedule_date
|
|
);
|
|
|
|
$this->db->order_by('p.position_name','ASC');
|
|
|
|
$this->db->order_by('e.full_name','ASC');
|
|
|
|
$rows = $this->db->get()->result();
|
|
|
|
// ============================================
|
|
// GROUP POSITION
|
|
// ============================================
|
|
$grouped = [];
|
|
|
|
if($rows){
|
|
|
|
foreach($rows as $r){
|
|
|
|
$position_id = $r->position_id ?: 0;
|
|
|
|
// ====================================
|
|
// CREATE GROUP
|
|
// ====================================
|
|
if(!isset($grouped[$position_id])){
|
|
|
|
$grouped[$position_id] = [
|
|
|
|
'position_id' => $r->position_id,
|
|
|
|
'position_name' => $r->position_name ?: '-',
|
|
|
|
'employees' => []
|
|
];
|
|
}
|
|
|
|
// ====================================
|
|
// EMPLOYEE
|
|
// ====================================
|
|
$grouped[$position_id]['employees'][] = [
|
|
|
|
'schedule_id' => $r->schedule_id,
|
|
|
|
'employee_id' => $r->employee_id,
|
|
|
|
'full_name' => $r->full_name,
|
|
|
|
'employee_code' => $r->employee_code,
|
|
|
|
'fingerprint_user_id' => $r->fingerprint_user_id,
|
|
|
|
'shift_id' => $r->shift_id,
|
|
|
|
'shift_name' => $r->shift_name,
|
|
|
|
'checkin' => $r->checkin_time
|
|
? date(
|
|
'H:i',
|
|
strtotime($r->checkin_time)
|
|
)
|
|
: '-',
|
|
|
|
'checkout' => $r->checkout_time
|
|
? date(
|
|
'H:i',
|
|
strtotime($r->checkout_time)
|
|
)
|
|
: '-',
|
|
|
|
'start_datetime' => $r->start_datetime,
|
|
|
|
'end_datetime' => $r->end_datetime,
|
|
|
|
'color' => $r->color
|
|
];
|
|
}
|
|
}
|
|
|
|
echo json_encode([
|
|
'status' => true,
|
|
'data' => array_values($grouped)
|
|
]);
|
|
}
|
|
|
|
// =====================================================
|
|
// UPDATE SCHEDULE SHIFT
|
|
// =====================================================
|
|
public function update_schedule_shift()
|
|
{
|
|
try{
|
|
|
|
$schedule_id = $this->input->post('schedule_id');
|
|
|
|
$shift_id = $this->input->post('shift_id');
|
|
|
|
// ============================================
|
|
// VALIDASI
|
|
// ============================================
|
|
if(empty($schedule_id)){
|
|
throw new Exception('Schedule ID kosong');
|
|
}
|
|
|
|
if(empty($shift_id)){
|
|
throw new Exception('Shift wajib dipilih');
|
|
}
|
|
|
|
// ============================================
|
|
// CHECK SCHEDULE
|
|
// ============================================
|
|
$schedule = $this->db
|
|
->where('id', $schedule_id)
|
|
->get('k_employee_shift_schedules')
|
|
->row();
|
|
|
|
if(!$schedule){
|
|
throw new Exception('Schedule tidak ditemukan');
|
|
}
|
|
|
|
// ============================================
|
|
// CHECK SHIFT
|
|
// ============================================
|
|
$shift = $this->db
|
|
->where('id', $shift_id)
|
|
->get('k_shifts')
|
|
->row();
|
|
|
|
if(!$shift){
|
|
throw new Exception('Shift tidak ditemukan');
|
|
}
|
|
|
|
// ============================================
|
|
// AMBIL TANGGAL
|
|
// ============================================
|
|
$schedule_date = date(
|
|
'Y-m-d',
|
|
strtotime($schedule->start_datetime)
|
|
);
|
|
|
|
// ============================================
|
|
// BUILD START DATETIME
|
|
// ============================================
|
|
$start_datetime = date(
|
|
'Y-m-d H:i:s',
|
|
strtotime(
|
|
$schedule_date . ' ' . $shift->checkin_time
|
|
)
|
|
);
|
|
|
|
// ============================================
|
|
// BUILD END DATETIME
|
|
// ============================================
|
|
$end_datetime = date(
|
|
'Y-m-d H:i:s',
|
|
strtotime(
|
|
$schedule_date . ' ' . $shift->checkout_time
|
|
)
|
|
);
|
|
|
|
// ============================================
|
|
// CROSS DAY
|
|
// ============================================
|
|
$is_cross_day = 0;
|
|
|
|
if(
|
|
strtotime($shift->checkout_time)
|
|
<=
|
|
strtotime($shift->checkin_time)
|
|
){
|
|
|
|
$end_datetime = date(
|
|
'Y-m-d H:i:s',
|
|
strtotime('+1 day', strtotime($end_datetime))
|
|
);
|
|
|
|
$is_cross_day = 1;
|
|
}
|
|
|
|
// ============================================
|
|
// WORK HOURS
|
|
// ============================================
|
|
$work_hours = $shift->work_hours;
|
|
|
|
// ============================================
|
|
// UPDATE
|
|
// ============================================
|
|
$this->db
|
|
->where('id', $schedule_id)
|
|
->update(
|
|
'k_employee_shift_schedules',
|
|
[
|
|
|
|
'shift_id' => $shift_id,
|
|
|
|
'start_datetime' => $start_datetime,
|
|
|
|
'end_datetime' => $end_datetime,
|
|
|
|
'work_hours' => $work_hours,
|
|
|
|
'is_cross_day' => $is_cross_day,
|
|
|
|
'updated_at' => date('Y-m-d H:i:s')
|
|
]
|
|
);
|
|
|
|
echo json_encode([
|
|
'status' => true,
|
|
'message' => 'Shift berhasil diupdate'
|
|
]);
|
|
|
|
} catch(Exception $e){
|
|
|
|
echo json_encode([
|
|
'status' => false,
|
|
'message' => $e->getMessage()
|
|
]);
|
|
}
|
|
}
|
|
|
|
|
|
// =====================================================
|
|
// DELETE SCHEDULE
|
|
// =====================================================
|
|
public function delete_schedule()
|
|
{
|
|
try{
|
|
|
|
$schedule_id = $this->input->post('schedule_id');
|
|
|
|
// ============================================
|
|
// VALIDASI
|
|
// ============================================
|
|
if(empty($schedule_id)){
|
|
throw new Exception('Schedule ID kosong');
|
|
}
|
|
|
|
// ============================================
|
|
// CHECK DATA
|
|
// ============================================
|
|
$schedule = $this->db
|
|
->where('id', $schedule_id)
|
|
->get('k_employee_shift_schedules')
|
|
->row();
|
|
|
|
if(!$schedule){
|
|
throw new Exception('Schedule tidak ditemukan');
|
|
}
|
|
|
|
// ============================================
|
|
// DELETE
|
|
// ============================================
|
|
$this->db
|
|
->where('id', $schedule_id)
|
|
->delete('k_employee_shift_schedules');
|
|
|
|
echo json_encode([
|
|
'status' => true,
|
|
'message' => 'Schedule berhasil dihapus'
|
|
]);
|
|
|
|
} catch(Exception $e){
|
|
|
|
echo json_encode([
|
|
'status' => false,
|
|
'message' => $e->getMessage()
|
|
]);
|
|
}
|
|
}
|
|
|
|
} |