Files
accounting_dev/application/controllers/Cronjob.php
T
Wian Drs 275652f7f7 Update Cronjob
update cronjob attendance monthly
2026-05-30 16:15:40 +07:00

356 lines
13 KiB
PHP

<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Cronjob extends CI_Controller {
public function __construct()
{
parent::__construct();
$this->load->database();
// ONLY CLI ACCESS
if (!$this->input->is_cli_request()) {
exit('No direct access allowed');
}
}
public function generate_insight()
{
$period = date('Y-m');
// =====================================================
// 🔥 REPLACE MODE (hapus data lama dulu)
// =====================================================
$this->db->where('period', $period);
$this->db->delete('ai_insights');
// =====================================================
// 1. FINANCE - OVERDUE INVOICE
// =====================================================
$overdue = $this->db->query("
SELECT COUNT(*) as total
FROM invoices
WHERE status != 'paid'
AND jatuh_tempo < CURDATE()
AND deleted_at IS NULL
")->row()->total;
if ($overdue > 0) {
$this->db->insert('ai_insights', [
'type' => 'finance',
'severity' => 'warning',
'message' => "$overdue invoice sudah melewati jatuh tempo",
'meta' => json_encode([
'overdue_count' => (int)$overdue
]),
'period' => $period
]);
}
// =====================================================
// 2. FINANCE - CASHFLOW BULAN INI
// =====================================================
$cash = $this->db->query("
SELECT COALESCE(SUM(jd.debit),0) as cash_in
FROM journal_details jd
JOIN journals j ON j.id = jd.journal_id
WHERE MONTH(j.tanggal) = MONTH(CURDATE())
AND YEAR(j.tanggal) = YEAR(CURDATE())
")->row()->cash_in;
if ($cash > 0) {
$this->db->insert('ai_insights', [
'type' => 'finance',
'severity' => ($cash > 10000000) ? 'info' : 'warning',
'message' => "Cashflow bulan ini Rp " . number_format($cash),
'meta' => json_encode([
'cash_in' => (float)$cash
]),
'period' => $period
]);
}
// =====================================================
// 3. STOCK - KRITIS
// =====================================================
$stocks = $this->db->query("
SELECT
i.kode_id,
k.nama_barang,
SUM(i.stok) as total_stok,
k.limit_stock
FROM items i
JOIN kode_barang k ON k.id = i.kode_id
GROUP BY i.kode_id, k.nama_barang, k.limit_stock
HAVING total_stok <= k.limit_stock
")->result();
foreach ($stocks as $s) {
$this->db->insert('ai_insights', [
'type' => 'stock',
'severity' => 'critical',
'message' => "Stok {$s->nama_barang} kritis ({$s->total_stok})",
'meta' => json_encode([
'kode_id' => $s->kode_id,
'item' => $s->nama_barang,
'stok' => (int)$s->total_stok,
'limit' => (int)$s->limit_stock
]),
'period' => $period
]);
}
// =====================================================
// 4. CUSTOMER - PAYMENT RISK
// =====================================================
$lateCustomers = $this->db->query("
SELECT
c.nama,
COUNT(i.id) as total_invoice
FROM invoices i
JOIN customers c ON c.id = i.customer_id
WHERE i.status != 'paid'
AND i.jatuh_tempo < CURDATE()
GROUP BY i.customer_id
HAVING total_invoice > 2
")->result();
foreach ($lateCustomers as $c) {
$this->db->insert('ai_insights', [
'type' => 'customer',
'severity' => 'warning',
'message' => "Customer {$c->nama} memiliki {$c->total_invoice} invoice overdue",
'meta' => json_encode([
'customer' => $c->nama,
'overdue_invoice' => (int)$c->total_invoice
]),
'period' => $period
]);
}
// =====================================================
// RESPONSE
// =====================================================
echo json_encode([
'status' => true,
'message' => 'AI Insight generated (REPLACE MODE)',
'period' => $period
]);
}
// =====================================================
// CRONJOB UNTUK LIHAT KEHADIRAN SELAMA 1 BULAN
// =====================================================
// | Kriteria | Pengurangan |
// | ---------------------- | ------------------: |
// | Alpha | -20 poin / hari |
// | Terlambat | -2 poin / kejadian |
// | Izin (permit) | -1 poin / hari |
// | Akumulasi telat | -1 poin / 60 menit |
// | Akumulasi pulang cepat | -1 poin / 120 menit |
public function generateMonthlyAttendance()
{
$month = date('Y-m-01');
$startDate = date('Y-m-01', strtotime($month));
$endDate = date('Y-m-t', strtotime($month));
$employees = $this->db
->where('is_active', 1)
->get('k_employees')
->result();
$processed = 0;
$this->db->trans_begin();
try {
foreach ($employees as $employee) {
// Total Hari Kerja
$schedule = $this->db->query("
SELECT
COUNT(*) AS total_hari_kerja
FROM k_employee_shift_schedules
WHERE employee_id = ?
AND status IN ('published','done')
AND schedule_date BETWEEN ? AND ?
", array(
$employee->id,
$startDate,
$endDate
))->row();
$total_hari_kerja = (int) $schedule->total_hari_kerja;
// Rekap Absensi
$attendance = $this->db->query("
SELECT
COALESCE(SUM(attendance_status='present'),0) AS total_present,
COALESCE(SUM(attendance_status='late'),0) AS total_late,
COALESCE(SUM(attendance_status='alpha'),0) AS total_alpha,
COALESCE(SUM(attendance_status='sick'),0) AS total_sick,
COALESCE(SUM(attendance_status='permit'),0) AS total_permit,
COALESCE(SUM(attendance_status='annual'),0) AS total_annual,
COALESCE(SUM(late_minutes),0) AS total_late_minutes,
COALESCE(SUM(early_leave_minutes),0) AS total_early_leave_minutes,
COALESCE(SUM(work_hours),0) AS total_work_hours,
COALESCE(SUM(overtime_hours),0) AS total_overtime_hours
FROM k_attendances
WHERE employee_id = ?
AND attendance_date BETWEEN ? AND ?
", array(
$employee->id,
$startDate,
$endDate
))->row();
$total_present = (int) $attendance->total_present;
$total_late = (int) $attendance->total_late;
$total_alpha = (int) $attendance->total_alpha;
$total_sick = (int) $attendance->total_sick;
$total_permit = (int) $attendance->total_permit;
$total_annual = (int) $attendance->total_annual;
// Kehadiran
$total_hadir = $total_present + $total_late;
$attendance_percentage = 0;
if ($total_hari_kerja > 0) {
$attendance_percentage = round(
($total_hadir / $total_hari_kerja) * 100,
2
);
}
// SCOR
$score = 100;
// Alpha
$score -= ($total_alpha * 20);
// Telat
$score -= ($total_late * 2);
// Izin
$score -= ($total_permit * 1);
// Total menit telat
$score -= floor(
((int) $attendance->total_late_minutes) / 60
);
// Total menit pulang cepat
$score -= floor(
((int) $attendance->total_early_leave_minutes) / 120
);
if ($score < 0) {
$score = 0;
}
// LOGIKA STATUS
if ($score >= 90) {
$status = 'baik sekali';
} elseif ($score >= 75) {
$status = 'baik';
} elseif ($score >= 60) {
$status = 'kurang baik';
} else {
$status = 'buruk';
}
// INSERT OR UPDATE TO k_attendance_monthly
$sql = "
INSERT INTO k_attendance_monthly (
employee_id, month,
total_present, total_late, total_alpha, total_sick, total_permit, total_annual,
total_late_minutes, total_early_leave_minutes,
total_work_hours, total_overtime_hours,
total_hari_kerja, total_hadir, attendance_percentage,
score, status
)
VALUES (
?, ?,
?, ?, ?, ?, ?, ?,
?, ?,
?, ?,
?, ?, ?,
?, ?
)
ON DUPLICATE KEY UPDATE
total_present = VALUES(total_present),
total_late = VALUES(total_late),
total_alpha = VALUES(total_alpha),
total_sick = VALUES(total_sick),
total_permit = VALUES(total_permit),
total_annual = VALUES(total_annual),
total_late_minutes = VALUES(total_late_minutes),
total_early_leave_minutes = VALUES(total_early_leave_minutes),
total_work_hours = VALUES(total_work_hours),
total_overtime_hours = VALUES(total_overtime_hours),
total_hari_kerja = VALUES(total_hari_kerja),
total_hadir = VALUES(total_hadir),
attendance_percentage = VALUES(attendance_percentage),
score = VALUES(score),
status = VALUES(status),
updated_at = CURRENT_TIMESTAMP
";
$this->db->query($sql, array(
$employee->id,
$month,
$total_present,
$total_late,
$total_alpha,
$total_sick,
$total_permit,
$total_annual,
(int)$attendance->total_late_minutes,
(int)$attendance->total_early_leave_minutes,
(float)$attendance->total_work_hours,
(float)$attendance->total_overtime_hours,
$total_hari_kerja,
$total_hadir,
$attendance_percentage,
$score,
$status
));
$processed++;
}
if ($this->db->trans_status() === FALSE) {
throw new Exception('Transaction failed');
}
$this->db->trans_commit();
echo json_encode(array(
'status' => true,
'month' => $month,
'processed' => $processed,
'message' => 'Monthly attendance generated successfully'
));
} catch (Exception $e) {
$this->db->trans_rollback();
echo json_encode(array(
'status' => false,
'month' => $month,
'message' => $e->getMessage()
));
}
}
}