Initial commit

This commit is contained in:
root
2026-05-26 08:07:45 +00:00
commit a234e55e64
4263 changed files with 855927 additions and 0 deletions
@@ -0,0 +1,768 @@
<?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()
]);
}
}
}