1497 lines
61 KiB
PHP
1497 lines
61 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Validator;
|
|
use Symfony\Component\HttpFoundation\StreamedResponse;
|
|
use PhpOffice\PhpSpreadsheet\Cell\DataType;
|
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
|
use App\Models\MasterPitStopPraAkre;
|
|
use App\Models\PraAkre;
|
|
use App\Models\KaryawanLuar;
|
|
use Barryvdh\DomPDF\Facade\Pdf;
|
|
|
|
class PitStopController extends Controller
|
|
{
|
|
private function dtInt($value, $default = 0)
|
|
{
|
|
$n = is_numeric($value) ? (int) $value : (int) $default;
|
|
return $n < 0 ? (int) $default : $n;
|
|
}
|
|
|
|
private function streamXlsx(string $filename, callable $buildSpreadsheet): StreamedResponse
|
|
{
|
|
$response = new StreamedResponse(function () use ($buildSpreadsheet) {
|
|
$spreadsheet = new Spreadsheet();
|
|
$buildSpreadsheet($spreadsheet);
|
|
$writer = new Xlsx($spreadsheet);
|
|
$writer->save('php://output');
|
|
});
|
|
|
|
$response->headers->set('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
|
$response->headers->set('Content-Disposition', 'attachment; filename="' . $filename . '"');
|
|
return $response;
|
|
}
|
|
|
|
public function pitstop(){
|
|
$masterPitStop = MasterPitStopPraAkre::where('statusenabled', true)->get();
|
|
$data = [
|
|
'title' => 'Pit Stop',
|
|
'masterPitStop' => $masterPitStop
|
|
];
|
|
return view('pitstop.index', $data);
|
|
}
|
|
|
|
public function progressUnit()
|
|
{
|
|
$totalSteps = (int) MasterPitStopPraAkre::where('statusenabled', true)->count();
|
|
|
|
return view('pitstop.progress_unit', [
|
|
'title' => 'Monitoring Pra Akreditasi',
|
|
'totalSteps' => $totalSteps,
|
|
]);
|
|
}
|
|
|
|
public function progressUnitDetail(Request $request, $unit_id)
|
|
{
|
|
$unitId = (int) $unit_id;
|
|
$unit = DB::connection('pgsql')
|
|
->table('public.unitkerjapegawai_m as ukp')
|
|
->where('ukp.statusenabled', true)
|
|
->where('ukp.id', $unitId)
|
|
->select(['ukp.id', 'ukp.name'])
|
|
->first();
|
|
|
|
abort_if(!$unit, 404);
|
|
|
|
$totalSteps = (int) MasterPitStopPraAkre::where('statusenabled', true)->count();
|
|
|
|
return view('pitstop.progress_unit_detail', [
|
|
'title' => 'Monitoring Pra Akreditasi - ' . ($unit->name ?? 'Unit'),
|
|
'unit' => $unit,
|
|
'totalSteps' => $totalSteps,
|
|
]);
|
|
}
|
|
|
|
public function progressExternalDetail(Request $request, $tipe)
|
|
{
|
|
$tipe = urldecode((string) $tipe);
|
|
$tipe = trim($tipe);
|
|
abort_if($tipe === '', 404);
|
|
|
|
$totalSteps = (int) MasterPitStopPraAkre::where('statusenabled', true)->count();
|
|
$masterPitStop = MasterPitStopPraAkre::where('statusenabled', true)->get();
|
|
|
|
return view('pitstop.progress_external_detail', [
|
|
'title' => 'Monitoring Karyawan Luar - ' . $tipe,
|
|
'tipe' => $tipe,
|
|
'totalSteps' => $totalSteps,
|
|
'masterPitStop' => $masterPitStop,
|
|
]);
|
|
}
|
|
|
|
public function dataProgress(Request $request)
|
|
{
|
|
$draw = $this->dtInt($request->input('draw'), 1);
|
|
$start = $this->dtInt($request->input('start'), 0);
|
|
$length = $this->dtInt($request->input('length'), 10);
|
|
if ($length < 1) $length = 10;
|
|
if ($length > 200) $length = 200;
|
|
|
|
$search = trim((string) data_get($request->all(), 'search.value', ''));
|
|
|
|
$totalSteps = (int) MasterPitStopPraAkre::where('statusenabled', true)->count();
|
|
|
|
$perPegawai = DB::connection('pgsql')
|
|
->table('public.mappegawaijabatantounitkerja_m as mp')
|
|
->join('public.pegawai_m as pg', 'pg.id', '=', 'mp.objectpegawaifk')
|
|
->join('public.unitkerjapegawai_m as ukp', 'ukp.id', '=', 'mp.objectunitkerjapegawaifk')
|
|
->leftJoin('public.praakre as p', 'p.pegawai_id', '=', 'pg.id')
|
|
->leftJoin('public.masterpitstop as m', function ($join) {
|
|
$join->on(DB::raw('m.id::text'), '=', 'p.masterpitstop_id')
|
|
->where('m.statusenabled', true);
|
|
})
|
|
->where('mp.statusenabled', true)
|
|
->where('mp.isprimary', true)
|
|
->where('pg.statusenabled', true)
|
|
->where('ukp.statusenabled', true)
|
|
->select([
|
|
DB::raw('ukp.id as unit_id'),
|
|
DB::raw("coalesce(ukp.name, '-') as unit_name"),
|
|
DB::raw('pg.id as pegawai_id'),
|
|
DB::raw("count(distinct m.id) filter (where p.status='lulus') as lulus_count"),
|
|
])
|
|
->groupBy('ukp.id', 'ukp.name', 'pg.id');
|
|
|
|
$unitAgg = DB::connection('pgsql')
|
|
->query()
|
|
->fromSub($perPegawai, 't')
|
|
->select([
|
|
't.unit_id',
|
|
't.unit_name',
|
|
DB::raw('count(*) as total_pegawai'),
|
|
DB::raw('sum(case when t.lulus_count >= ' . $totalSteps . ' then 1 else 0 end) as pegawai_selesai'),
|
|
DB::raw('sum(t.lulus_count) as total_step_lulus'),
|
|
DB::raw('avg(t.lulus_count) as avg_step_lulus'),
|
|
])
|
|
->groupBy('t.unit_id', 't.unit_name');
|
|
|
|
$recordsTotal = DB::connection('pgsql')
|
|
->query()
|
|
->fromSub($unitAgg, 'u')
|
|
->count();
|
|
|
|
$filteredQuery = DB::connection('pgsql')->query()->fromSub($unitAgg, 'u');
|
|
if ($search !== '') {
|
|
$filteredQuery->where('u.unit_name', 'ILIKE', '%' . $search . '%');
|
|
}
|
|
|
|
$recordsFiltered = (clone $filteredQuery)->count();
|
|
|
|
$rows = $filteredQuery
|
|
->orderByDesc('pegawai_selesai')
|
|
->orderByDesc('avg_step_lulus')
|
|
->orderBy('unit_name')
|
|
->offset($start)
|
|
->limit($length)
|
|
->get();
|
|
|
|
$data = $rows->map(function ($r) use ($totalSteps) {
|
|
$totalPegawai = (int) ($r->total_pegawai ?? 0);
|
|
$pegawaiSelesai = (int) ($r->pegawai_selesai ?? 0);
|
|
$selesaiPct = $totalPegawai > 0 ? round(($pegawaiSelesai / $totalPegawai) * 100, 1) : 0;
|
|
|
|
return [
|
|
'unit_id' => (int) $r->unit_id,
|
|
'unit_name' => (string) ($r->unit_name ?? '-'),
|
|
'total_pegawai' => $totalPegawai,
|
|
'pegawai_selesai' => $pegawaiSelesai,
|
|
'selesai_pct' => $selesaiPct,
|
|
'total_step_lulus' => (int) ($r->total_step_lulus ?? 0),
|
|
];
|
|
})->values();
|
|
|
|
return response()->json([
|
|
'draw' => $draw,
|
|
'recordsTotal' => $recordsTotal,
|
|
'recordsFiltered' => $recordsFiltered,
|
|
'data' => $data,
|
|
]);
|
|
}
|
|
|
|
public function dataProgressExternal(Request $request){
|
|
$draw = $this->dtInt($request->input('draw'), 1);
|
|
$start = $this->dtInt($request->input('start'), 0);
|
|
$length = $this->dtInt($request->input('length'), 10);
|
|
if ($length < 1) $length = 10;
|
|
if ($length > 200) $length = 200;
|
|
|
|
$search = trim((string) data_get($request->all(), 'search.value', ''));
|
|
|
|
$totalSteps = (int) MasterPitStopPraAkre::where('statusenabled', true)->count();
|
|
|
|
$perPegawai = DB::connection('pgsql')
|
|
->table('public.pegawai_luar_pl as pl')
|
|
->leftJoin('public.praakre as p', function ($join) {
|
|
$join->on('p.pegawai_id', '=', 'pl.id')
|
|
->where('p.tipe_karyawan', 'luar');
|
|
})
|
|
->leftJoin('public.masterpitstop as m', function ($join) {
|
|
$join->on(DB::raw('m.id::text'), '=', 'p.masterpitstop_id')
|
|
->where('m.statusenabled', true);
|
|
})
|
|
->select([
|
|
DB::raw("coalesce(nullif(pl.tipe, ''), '-') as tipe"),
|
|
DB::raw('pl.id as pegawai_id'),
|
|
DB::raw("count(distinct m.id) filter (where p.status='lulus') as lulus_count"),
|
|
])
|
|
->groupBy(DB::raw("coalesce(nullif(pl.tipe, ''), '-')"), 'pl.id');
|
|
|
|
$tipeAgg = DB::connection('pgsql')
|
|
->query()
|
|
->fromSub($perPegawai, 't')
|
|
->select([
|
|
't.tipe',
|
|
DB::raw('count(*) as total_pegawai'),
|
|
DB::raw('sum(case when t.lulus_count >= ' . $totalSteps . ' then 1 else 0 end) as pegawai_selesai'),
|
|
DB::raw('sum(t.lulus_count) as total_step_lulus'),
|
|
DB::raw('avg(t.lulus_count) as avg_step_lulus'),
|
|
])
|
|
->groupBy('t.tipe');
|
|
|
|
$recordsTotal = DB::connection('pgsql')
|
|
->query()
|
|
->fromSub($tipeAgg, 'u')
|
|
->count();
|
|
|
|
$filteredQuery = DB::connection('pgsql')->query()->fromSub($tipeAgg, 'u');
|
|
if ($search !== '') {
|
|
$filteredQuery->where('u.tipe', 'ILIKE', '%' . $search . '%');
|
|
}
|
|
|
|
$recordsFiltered = (clone $filteredQuery)->count();
|
|
|
|
$rows = $filteredQuery
|
|
->orderByDesc('pegawai_selesai')
|
|
->orderByDesc('avg_step_lulus')
|
|
->orderBy('tipe')
|
|
->offset($start)
|
|
->limit($length)
|
|
->get();
|
|
|
|
$data = $rows->map(function ($r) use ($totalSteps) {
|
|
$totalPegawai = (int) ($r->total_pegawai ?? 0);
|
|
$pegawaiSelesai = (int) ($r->pegawai_selesai ?? 0);
|
|
$selesaiPct = $totalPegawai > 0 ? round(($pegawaiSelesai / $totalPegawai) * 100, 1) : 0;
|
|
|
|
return [
|
|
'tipe' => (string) ($r->tipe ?? '-'),
|
|
'total_pegawai' => $totalPegawai,
|
|
'pegawai_selesai' => $pegawaiSelesai,
|
|
'selesai_pct' => $selesaiPct,
|
|
'total_step_lulus' => (int) ($r->total_step_lulus ?? 0),
|
|
'avg_step_lulus' => $totalSteps > 0 ? round((float) ($r->avg_step_lulus ?? 0), 2) : 0,
|
|
];
|
|
})->values();
|
|
|
|
return response()->json([
|
|
'draw' => $draw,
|
|
'recordsTotal' => $recordsTotal,
|
|
'recordsFiltered' => $recordsFiltered,
|
|
'data' => $data,
|
|
]);
|
|
}
|
|
|
|
public function dataProgressExternalDetail(Request $request)
|
|
{
|
|
$validator = Validator::make($request->all(), [
|
|
'tipe' => 'required|string|max:100',
|
|
'limit' => 'nullable|integer|min:1|max:500',
|
|
]);
|
|
|
|
if ($validator->fails()) {
|
|
return response()->json([
|
|
'error' => 1,
|
|
'message' => 'Validasi gagal.',
|
|
'errors' => $validator->errors(),
|
|
], 422);
|
|
}
|
|
|
|
$tipe = trim((string) $validator->validated()['tipe']);
|
|
$limit = (int) ($validator->validated()['limit'] ?? 200);
|
|
|
|
$totalSteps = (int) MasterPitStopPraAkre::where('statusenabled', true)->count();
|
|
|
|
$rows = DB::connection('pgsql')
|
|
->table('public.pegawai_luar_pl as pl')
|
|
->leftJoin('public.praakre as p', function ($join) {
|
|
$join->on('p.pegawai_id', '=', 'pl.id')
|
|
->where('p.tipe_karyawan', 'luar');
|
|
})
|
|
->leftJoin('public.masterpitstop as m', function ($join) {
|
|
$join->on(DB::raw('m.id::text'), '=', 'p.masterpitstop_id')
|
|
->where('m.statusenabled', true);
|
|
})
|
|
->where(DB::raw("coalesce(nullif(pl.tipe, ''), '-')"), '=', $tipe)
|
|
->select([
|
|
'pl.id',
|
|
'pl.nama',
|
|
'pl.nik',
|
|
DB::raw("coalesce(nullif(pl.tipe, ''), '-') as tipe"),
|
|
DB::raw("count(distinct m.id) filter (where p.status='lulus') as lulus_count"),
|
|
])
|
|
->groupBy('pl.id', 'pl.nama', 'pl.nik', DB::raw("coalesce(nullif(pl.tipe, ''), '-')"))
|
|
->orderBy('pl.nama')
|
|
->limit($limit)
|
|
->get();
|
|
|
|
$data = $rows->map(function ($r) use ($totalSteps) {
|
|
$lulus = (int) ($r->lulus_count ?? 0);
|
|
$selesai = $totalSteps > 0 ? ($lulus >= $totalSteps ? 1 : 0) : 0;
|
|
$pct = $totalSteps > 0 ? round(($lulus / $totalSteps) * 100, 1) : 0;
|
|
return [
|
|
'id' => (int) $r->id,
|
|
'nama' => (string) ($r->nama ?? '-'),
|
|
'nik' => (string) ($r->nik ?? '-'),
|
|
'tipe' => (string) ($r->tipe ?? '-'),
|
|
'lulus_count' => $lulus,
|
|
'pct' => $pct,
|
|
'selesai' => $selesai,
|
|
];
|
|
})->values();
|
|
|
|
return response()->json([
|
|
'error' => 0,
|
|
'data' => $data,
|
|
'meta' => [
|
|
'tipe' => $tipe,
|
|
'total_steps' => $totalSteps,
|
|
'count' => $data->count(),
|
|
],
|
|
]);
|
|
}
|
|
|
|
public function monitoringPdf(Request $request)
|
|
{
|
|
$unitId = $request->query('unit_id');
|
|
$unitId = is_null($unitId) || $unitId === '' ? null : (int) $unitId;
|
|
|
|
$totalSteps = (int) MasterPitStopPraAkre::where('statusenabled', true)->count();
|
|
$generatedAt = now();
|
|
|
|
// Default: ringkasan per unit (tanpa list pegawai) supaya tidak memakan memory besar.
|
|
if (is_null($unitId)) {
|
|
$perPegawai = DB::connection('pgsql')
|
|
->table('public.mappegawaijabatantounitkerja_m as mp')
|
|
->join('public.pegawai_m as pg', 'pg.id', '=', 'mp.objectpegawaifk')
|
|
->join('public.unitkerjapegawai_m as ukp', 'ukp.id', '=', 'mp.objectunitkerjapegawaifk')
|
|
->leftJoin('public.praakre as p', 'p.pegawai_id', '=', 'pg.id')
|
|
->leftJoin('public.masterpitstop as m', function ($join) {
|
|
$join->on(DB::raw('m.id::text'), '=', 'p.masterpitstop_id')
|
|
->where('m.statusenabled', true);
|
|
})
|
|
->where('mp.statusenabled', true)
|
|
->where('mp.isprimary', true)
|
|
->where('pg.statusenabled', true)
|
|
->where('pg.kedudukanfk', 1)
|
|
->where('ukp.statusenabled', true)
|
|
->select([
|
|
DB::raw('ukp.id as unit_id'),
|
|
DB::raw("coalesce(ukp.name, '-') as unit_name"),
|
|
DB::raw('pg.id as pegawai_id'),
|
|
DB::raw("count(distinct m.id) filter (where p.status='lulus') as lulus_count"),
|
|
])
|
|
->groupBy('ukp.id', 'ukp.name', 'pg.id');
|
|
|
|
$unitAgg = DB::connection('pgsql')
|
|
->query()
|
|
->fromSub($perPegawai, 't')
|
|
->select([
|
|
't.unit_id',
|
|
't.unit_name',
|
|
DB::raw('count(*) as total_pegawai'),
|
|
DB::raw('sum(case when t.lulus_count >= ' . $totalSteps . ' then 1 else 0 end) as pegawai_selesai'),
|
|
])
|
|
->groupBy('t.unit_id', 't.unit_name');
|
|
|
|
$rows = DB::connection('pgsql')
|
|
->query()
|
|
->fromSub($unitAgg, 'u')
|
|
->orderByDesc('pegawai_selesai')
|
|
->orderByDesc('total_pegawai')
|
|
->orderBy('unit_name')
|
|
->get();
|
|
|
|
$units = $rows->map(function ($r) {
|
|
$totalPegawai = (int) ($r->total_pegawai ?? 0);
|
|
$pegawaiSelesai = (int) ($r->pegawai_selesai ?? 0);
|
|
$pct = $totalPegawai > 0 ? round(($pegawaiSelesai / $totalPegawai) * 100, 1) : 0;
|
|
return (object) [
|
|
'unit_id' => (int) $r->unit_id,
|
|
'unit_name' => (string) ($r->unit_name ?? '-'),
|
|
'total_pegawai' => $totalPegawai,
|
|
'pegawai_selesai' => $pegawaiSelesai,
|
|
'pct' => $pct,
|
|
'pegawai' => collect(),
|
|
];
|
|
});
|
|
|
|
$pdf = Pdf::loadView('pitstop.monitoring_pdf', [
|
|
'title' => 'Monitoring Pra Akreditasi',
|
|
'generatedAt' => $generatedAt,
|
|
'totalSteps' => $totalSteps,
|
|
'units' => $units,
|
|
'isSummaryOnly' => true,
|
|
])->setPaper('a4', 'landscape');
|
|
|
|
$filename = 'monitoring-pra-akreditasi-ringkasan-' . $generatedAt->format('Ymd-Hi') . '.pdf';
|
|
return $pdf->download($filename);
|
|
}
|
|
|
|
// Mode detail: PDF per unit (lebih aman untuk memory).
|
|
$unit = DB::connection('pgsql')
|
|
->table('public.unitkerjapegawai_m as ukp')
|
|
->where('ukp.statusenabled', true)
|
|
->where('ukp.id', $unitId)
|
|
->select(['ukp.id', 'ukp.name'])
|
|
->first();
|
|
|
|
abort_if(!$unit, 404);
|
|
|
|
$perPegawai = DB::connection('pgsql')
|
|
->table('public.mappegawaijabatantounitkerja_m as mp')
|
|
->join('public.pegawai_m as pg', 'pg.id', '=', 'mp.objectpegawaifk')
|
|
->join('public.unitkerjapegawai_m as ukp', 'ukp.id', '=', 'mp.objectunitkerjapegawaifk')
|
|
->leftJoin('public.praakre as p', 'p.pegawai_id', '=', 'pg.id')
|
|
->leftJoin('public.masterpitstop as m', function ($join) {
|
|
$join->on(DB::raw('m.id::text'), '=', 'p.masterpitstop_id')
|
|
->where('m.statusenabled', true);
|
|
})
|
|
->where('mp.statusenabled', true)
|
|
->where('mp.isprimary', true)
|
|
->where('pg.statusenabled', true)
|
|
->where('pg.kedudukanfk', 1)
|
|
->where('ukp.statusenabled', true)
|
|
->where('ukp.id', $unitId)
|
|
->select([
|
|
DB::raw('ukp.id as unit_id'),
|
|
DB::raw("coalesce(ukp.name, '-') as unit_name"),
|
|
DB::raw('pg.id as pegawai_id'),
|
|
DB::raw("coalesce(pg.namalengkap, '-') as nama"),
|
|
DB::raw("coalesce(pg.nip_pns, '-') as nip_pns"),
|
|
DB::raw("count(distinct m.id) filter (where p.status='lulus') as lulus_count"),
|
|
DB::raw("coalesce((
|
|
select string_agg(ms.nama, ', ' order by ms.id)
|
|
from public.masterpitstop ms
|
|
left join public.praakre px
|
|
on px.pegawai_id = pg.id
|
|
and px.status = 'lulus'
|
|
and px.masterpitstop_id = ms.id::text
|
|
where ms.statusenabled = true
|
|
and px.id is null
|
|
), '') as belum_selesai_steps"),
|
|
])
|
|
->groupBy('ukp.id', 'ukp.name', 'pg.id', 'pg.namalengkap', 'pg.nip_pns');
|
|
|
|
$rows = DB::connection('pgsql')
|
|
->query()
|
|
->fromSub($perPegawai, 't')
|
|
->orderBy('t.nama')
|
|
->get();
|
|
|
|
$totalPegawai = $rows->count();
|
|
$pegawaiSelesai = $rows->filter(function ($r) use ($totalSteps) {
|
|
return (int) ($r->lulus_count ?? 0) >= $totalSteps && $totalSteps > 0;
|
|
})->count();
|
|
$pct = $totalPegawai > 0 ? round(($pegawaiSelesai / $totalPegawai) * 100, 1) : 0;
|
|
|
|
$pegawai = $rows->map(function ($r) use ($totalSteps) {
|
|
$lulus = (int) ($r->lulus_count ?? 0);
|
|
$pctPegawai = $totalSteps > 0 ? round(($lulus / $totalSteps) * 100, 1) : 0;
|
|
$belum = trim((string) ($r->belum_selesai_steps ?? ''));
|
|
return (object) [
|
|
'pegawai_id' => (int) $r->pegawai_id,
|
|
'nama' => (string) ($r->nama ?? '-'),
|
|
'nip_pns' => (string) ($r->nip_pns ?? '-'),
|
|
'total_steps' => $totalSteps,
|
|
'lulus_steps' => $lulus,
|
|
'pct' => $pctPegawai,
|
|
'belum_selesai_steps' => $belum,
|
|
];
|
|
})->values();
|
|
|
|
$units = collect([
|
|
(object) [
|
|
'unit_id' => (int) $unit->id,
|
|
'unit_name' => (string) ($unit->name ?? '-'),
|
|
'total_pegawai' => $totalPegawai,
|
|
'pegawai_selesai' => $pegawaiSelesai,
|
|
'pct' => $pct,
|
|
'pegawai' => $pegawai,
|
|
],
|
|
]);
|
|
|
|
$pdf = Pdf::loadView('pitstop.monitoring_pdf', [
|
|
'title' => 'Monitoring Pra Akreditasi',
|
|
'generatedAt' => $generatedAt,
|
|
'totalSteps' => $totalSteps,
|
|
'units' => $units,
|
|
'isSummaryOnly' => false,
|
|
])->setPaper('a4', 'landscape');
|
|
|
|
$filename = 'monitoring-pra-akreditasi-unit-' . $unitId . '-' . $generatedAt->format('Ymd-Hi') . '.pdf';
|
|
return $pdf->download($filename);
|
|
}
|
|
|
|
public function monitoringPdfExternal(Request $request)
|
|
{
|
|
$tipe = $request->query('tipe');
|
|
$tipe = is_null($tipe) ? null : trim((string) $tipe);
|
|
if ($tipe === '') $tipe = null;
|
|
|
|
$totalSteps = (int) MasterPitStopPraAkre::where('statusenabled', true)->count();
|
|
$generatedAt = now();
|
|
|
|
// Summary: per tipe (tanpa list pegawai)
|
|
if (is_null($tipe)) {
|
|
$perPegawai = DB::connection('pgsql')
|
|
->table('public.pegawai_luar_pl as pl')
|
|
->leftJoin('public.praakre as p', function ($join) {
|
|
$join->on('p.pegawai_id', '=', 'pl.id')
|
|
->where('p.tipe_karyawan', 'luar');
|
|
})
|
|
->leftJoin('public.masterpitstop as m', function ($join) {
|
|
$join->on(DB::raw('m.id::text'), '=', 'p.masterpitstop_id')
|
|
->where('m.statusenabled', true);
|
|
})
|
|
->select([
|
|
DB::raw("coalesce(nullif(pl.tipe, ''), '-') as tipe"),
|
|
DB::raw('pl.id as pegawai_id'),
|
|
DB::raw("count(distinct m.id) filter (where p.status='lulus') as lulus_count"),
|
|
])
|
|
->groupBy(DB::raw("coalesce(nullif(pl.tipe, ''), '-')"), 'pl.id');
|
|
|
|
$tipeAgg = DB::connection('pgsql')
|
|
->query()
|
|
->fromSub($perPegawai, 't')
|
|
->select([
|
|
't.tipe',
|
|
DB::raw('count(*) as total_pegawai'),
|
|
DB::raw('sum(case when t.lulus_count >= ' . $totalSteps . ' then 1 else 0 end) as pegawai_selesai'),
|
|
])
|
|
->groupBy('t.tipe')
|
|
->orderByDesc('pegawai_selesai')
|
|
->orderByDesc('total_pegawai')
|
|
->orderBy('tipe')
|
|
->get();
|
|
|
|
$types = $tipeAgg->map(function ($r) {
|
|
return (object) [
|
|
'tipe' => (string) ($r->tipe ?? '-'),
|
|
'total_pegawai' => (int) ($r->total_pegawai ?? 0),
|
|
'pegawai_selesai' => (int) ($r->pegawai_selesai ?? 0),
|
|
'pegawai' => collect(),
|
|
];
|
|
});
|
|
|
|
$pdf = Pdf::loadView('pitstop.monitoring_pdf_external', [
|
|
'title' => 'Monitoring Karyawan Luar',
|
|
'generatedAt' => $generatedAt,
|
|
'totalSteps' => $totalSteps,
|
|
'types' => $types,
|
|
'isSummaryOnly' => true,
|
|
])->setPaper('a4', 'landscape');
|
|
|
|
$filename = 'monitoring-karyawan-luar-ringkasan-' . $generatedAt->format('Ymd-Hi') . '.pdf';
|
|
return $pdf->download($filename);
|
|
}
|
|
|
|
// Detail per tipe
|
|
$perPegawai = DB::connection('pgsql')
|
|
->table('public.pegawai_luar_pl as pl')
|
|
->leftJoin('public.praakre as p', function ($join) {
|
|
$join->on('p.pegawai_id', '=', 'pl.id')
|
|
->where('p.tipe_karyawan', 'luar');
|
|
})
|
|
->leftJoin('public.masterpitstop as m', function ($join) {
|
|
$join->on(DB::raw('m.id::text'), '=', 'p.masterpitstop_id')
|
|
->where('m.statusenabled', true);
|
|
})
|
|
->where(DB::raw("coalesce(nullif(pl.tipe, ''), '-')"), '=', $tipe)
|
|
->select([
|
|
'pl.id',
|
|
DB::raw("coalesce(pl.nama, '-') as nama"),
|
|
DB::raw("coalesce(pl.nik, '-') as nik"),
|
|
DB::raw("count(distinct m.id) filter (where p.status='lulus') as lulus_count"),
|
|
DB::raw("coalesce((
|
|
select string_agg(ms.nama, ', ' order by ms.id)
|
|
from public.masterpitstop ms
|
|
left join public.praakre px
|
|
on px.pegawai_id = pl.id
|
|
and px.tipe_karyawan = 'luar'
|
|
and px.status = 'lulus'
|
|
and px.masterpitstop_id = ms.id::text
|
|
where ms.statusenabled = true
|
|
and px.id is null
|
|
), '') as belum_steps"),
|
|
])
|
|
->groupBy('pl.id', 'pl.nama', 'pl.nik')
|
|
->orderBy('pl.nama')
|
|
->get();
|
|
|
|
$pegawai = $perPegawai->map(function ($r) use ($totalSteps) {
|
|
return (object) [
|
|
'nama' => (string) ($r->nama ?? '-'),
|
|
'nik' => (string) ($r->nik ?? '-'),
|
|
'lulus_steps' => (int) ($r->lulus_count ?? 0),
|
|
'total_steps' => $totalSteps,
|
|
'belum_selesai_steps' => (string) ($r->belum_steps ?? ''),
|
|
];
|
|
});
|
|
|
|
$totalPegawai = (int) $pegawai->count();
|
|
$pegawaiSelesai = $pegawai->filter(function ($p) {
|
|
return ((int) ($p->total_steps ?? 0)) > 0 && ((int) ($p->lulus_steps ?? 0)) >= ((int) ($p->total_steps ?? 0));
|
|
})->count();
|
|
|
|
$types = collect([
|
|
(object) [
|
|
'tipe' => $tipe,
|
|
'total_pegawai' => $totalPegawai,
|
|
'pegawai_selesai' => $pegawaiSelesai,
|
|
'pegawai' => $pegawai,
|
|
],
|
|
]);
|
|
|
|
$pdf = Pdf::loadView('pitstop.monitoring_pdf_external', [
|
|
'title' => 'Monitoring Karyawan Luar - ' . $tipe,
|
|
'generatedAt' => $generatedAt,
|
|
'totalSteps' => $totalSteps,
|
|
'types' => $types,
|
|
'isSummaryOnly' => false,
|
|
])->setPaper('a4', 'landscape');
|
|
|
|
$filename = 'monitoring-karyawan-luar-' . preg_replace('/[^a-zA-Z0-9_-]+/', '-', $tipe) . '-' . $generatedAt->format('Ymd-Hi') . '.pdf';
|
|
return $pdf->download($filename);
|
|
}
|
|
|
|
public function monitoringExcel(Request $request)
|
|
{
|
|
$unitId = $request->query('unit_id');
|
|
$unitId = is_null($unitId) || $unitId === '' ? null : (int) $unitId;
|
|
|
|
$totalSteps = (int) MasterPitStopPraAkre::where('statusenabled', true)->count();
|
|
$generatedAt = now();
|
|
|
|
// Summary per unit
|
|
if (is_null($unitId)) {
|
|
$perPegawai = DB::connection('pgsql')
|
|
->table('public.mappegawaijabatantounitkerja_m as mp')
|
|
->join('public.pegawai_m as pg', 'pg.id', '=', 'mp.objectpegawaifk')
|
|
->join('public.unitkerjapegawai_m as ukp', 'ukp.id', '=', 'mp.objectunitkerjapegawaifk')
|
|
->leftJoin('public.praakre as p', 'p.pegawai_id', '=', 'pg.id')
|
|
->leftJoin('public.masterpitstop as m', function ($join) {
|
|
$join->on(DB::raw('m.id::text'), '=', 'p.masterpitstop_id')
|
|
->where('m.statusenabled', true);
|
|
})
|
|
->where('mp.statusenabled', true)
|
|
->where('mp.isprimary', true)
|
|
->where('pg.statusenabled', true)
|
|
->where('pg.kedudukanfk', 1)
|
|
->where('ukp.statusenabled', true)
|
|
->select([
|
|
DB::raw('ukp.id as unit_id'),
|
|
DB::raw("coalesce(ukp.name, '-') as unit_name"),
|
|
DB::raw('pg.id as pegawai_id'),
|
|
DB::raw("count(distinct m.id) filter (where p.status='lulus') as lulus_count"),
|
|
])
|
|
->groupBy('ukp.id', 'ukp.name', 'pg.id');
|
|
|
|
$unitAgg = DB::connection('pgsql')
|
|
->query()
|
|
->fromSub($perPegawai, 't')
|
|
->select([
|
|
't.unit_id',
|
|
't.unit_name',
|
|
DB::raw('count(*) as total_pegawai'),
|
|
DB::raw('sum(case when t.lulus_count >= ' . $totalSteps . ' then 1 else 0 end) as pegawai_selesai'),
|
|
])
|
|
->groupBy('t.unit_id', 't.unit_name')
|
|
->orderBy('t.unit_name')
|
|
->get();
|
|
|
|
$filename = 'monitoring-pra-akreditasi-ringkasan-' . $generatedAt->format('Ymd-Hi') . '.xlsx';
|
|
return $this->streamXlsx($filename, function (Spreadsheet $spreadsheet) use ($unitAgg, $totalSteps) {
|
|
$sheet = $spreadsheet->getActiveSheet();
|
|
$sheet->setTitle('Internal (Summary)');
|
|
|
|
$headers = ['Nama Unit', 'Total Pitstop', 'Total Karyawan', 'Karyawan Selesai'];
|
|
foreach ($headers as $i => $h) {
|
|
$sheet->setCellValueByColumnAndRow($i + 1, 1, $h);
|
|
}
|
|
$sheet->getStyle('A1:E1')->getFont()->setBold(true);
|
|
|
|
$row = 2;
|
|
foreach ($unitAgg as $r) {
|
|
$sheet->setCellValueByColumnAndRow(1, $row, (string) ($r->unit_name ?? '-'));
|
|
$sheet->setCellValueByColumnAndRow(2, $row, (int) $totalSteps);
|
|
$sheet->setCellValueByColumnAndRow(3, $row, (int) ($r->total_pegawai ?? 0));
|
|
$sheet->setCellValueByColumnAndRow(4, $row, (int) ($r->pegawai_selesai ?? 0));
|
|
$row++;
|
|
}
|
|
foreach(range('A', 'E') as $col){
|
|
$sheet->getColumnDimension($col)->setAutoSize(true);
|
|
}
|
|
});
|
|
}
|
|
|
|
// Detail per unit
|
|
$unit = DB::connection('pgsql')
|
|
->table('public.unitkerjapegawai_m as ukp')
|
|
->where('ukp.statusenabled', true)
|
|
->where('ukp.id', $unitId)
|
|
->select(['ukp.id', 'ukp.name'])
|
|
->first();
|
|
|
|
abort_if(!$unit, 404);
|
|
|
|
$rows = DB::connection('pgsql')
|
|
->table('public.mappegawaijabatantounitkerja_m as mp')
|
|
->join('public.pegawai_m as pg', 'pg.id', '=', 'mp.objectpegawaifk')
|
|
->join('public.unitkerjapegawai_m as ukp', 'ukp.id', '=', 'mp.objectunitkerjapegawaifk')
|
|
->leftJoin('public.praakre as p', 'p.pegawai_id', '=', 'pg.id')
|
|
->leftJoin('public.masterpitstop as m', function ($join) {
|
|
$join->on(DB::raw('m.id::text'), '=', 'p.masterpitstop_id')
|
|
->where('m.statusenabled', true);
|
|
})
|
|
->where('mp.statusenabled', true)
|
|
->where('mp.isprimary', true)
|
|
->where('pg.statusenabled', true)
|
|
->where('pg.kedudukanfk', 1)
|
|
->where('ukp.statusenabled', true)
|
|
->where('ukp.id', $unitId)
|
|
->select([
|
|
'pg.id',
|
|
DB::raw("coalesce(pg.namalengkap, '-') as nama"),
|
|
DB::raw("coalesce(pg.nip_pns, '-') as nip_pns"),
|
|
DB::raw("count(distinct m.id) filter (where p.status='lulus') as lulus_count"),
|
|
DB::raw("coalesce((
|
|
select string_agg(ms.nama, ', ' order by ms.id)
|
|
from public.masterpitstop ms
|
|
left join public.praakre px
|
|
on px.pegawai_id = pg.id
|
|
and px.status = 'lulus'
|
|
and px.masterpitstop_id = ms.id::text
|
|
where ms.statusenabled = true
|
|
and px.id is null
|
|
), '') as belum_steps"),
|
|
])
|
|
->groupBy('pg.id', 'pg.namalengkap', 'pg.nip_pns')
|
|
->orderBy('pg.namalengkap')
|
|
->get();
|
|
|
|
$filename = 'monitoring-pra-akreditasi-unit-' . (int) $unitId . '-' . $generatedAt->format('Ymd-Hi') . '.xlsx';
|
|
return $this->streamXlsx($filename, function (Spreadsheet $spreadsheet) use ($rows, $unit, $totalSteps) {
|
|
$sheet = $spreadsheet->getActiveSheet();
|
|
$sheet->setTitle('Internal (Detail)');
|
|
|
|
$headers = ['Nama Unit', 'Nama Karyawan', 'NIP', 'Lulus Pitstop', 'Total Pitstop', 'Belum Dikerjakan'];
|
|
foreach ($headers as $i => $h) {
|
|
$sheet->setCellValueByColumnAndRow($i + 1, 1, $h);
|
|
}
|
|
$sheet->getStyle('A1:I1')->getFont()->setBold(true);
|
|
|
|
$row = 2;
|
|
foreach ($rows as $r) {
|
|
$lulus = (int) ($r->lulus_count ?? 0);
|
|
$selesai = $totalSteps > 0 && $lulus >= $totalSteps ? 1 : 0;
|
|
|
|
$sheet->setCellValueByColumnAndRow(1, $row, (string) ($unit->name ?? '-'));
|
|
$sheet->setCellValueByColumnAndRow(2, $row, (string) ($r->nama ?? '-'));
|
|
$sheet->setCellValueExplicitByColumnAndRow(3, $row, (string) ($r->nip_pns ?? '-'), DataType::TYPE_STRING);
|
|
$sheet->setCellValueByColumnAndRow(4, $row, $lulus);
|
|
$sheet->setCellValueByColumnAndRow(5, $row, (int) $totalSteps);
|
|
$sheet->setCellValueByColumnAndRow(6, $row, (string) ($r->belum_steps ?? ''));
|
|
$row++;
|
|
}
|
|
foreach(range('A', 'I') as $col){
|
|
$sheet->getColumnDimension($col)->setAutoSize(true);
|
|
}
|
|
});
|
|
}
|
|
|
|
public function monitoringExcelExternal(Request $request)
|
|
{
|
|
$tipe = $request->query('tipe');
|
|
$tipe = is_null($tipe) ? null : trim((string) $tipe);
|
|
if ($tipe === '') $tipe = null;
|
|
|
|
$totalSteps = (int) MasterPitStopPraAkre::where('statusenabled', true)->count();
|
|
$generatedAt = now();
|
|
|
|
// Summary per tipe
|
|
if (is_null($tipe)) {
|
|
$perPegawai = DB::connection('pgsql')
|
|
->table('public.pegawai_luar_pl as pl')
|
|
->leftJoin('public.praakre as p', function ($join) {
|
|
$join->on('p.pegawai_id', '=', 'pl.id')
|
|
->where('p.tipe_karyawan', 'luar');
|
|
})
|
|
->leftJoin('public.masterpitstop as m', function ($join) {
|
|
$join->on(DB::raw('m.id::text'), '=', 'p.masterpitstop_id')
|
|
->where('m.statusenabled', true);
|
|
})
|
|
->select([
|
|
DB::raw("coalesce(nullif(pl.tipe, ''), '-') as tipe"),
|
|
DB::raw('pl.id as pegawai_id'),
|
|
DB::raw("count(distinct m.id) filter (where p.status='lulus') as lulus_count"),
|
|
])
|
|
->groupBy(DB::raw("coalesce(nullif(pl.tipe, ''), '-')"), 'pl.id');
|
|
|
|
$tipeAgg = DB::connection('pgsql')
|
|
->query()
|
|
->fromSub($perPegawai, 't')
|
|
->select([
|
|
't.tipe',
|
|
DB::raw('count(*) as total_pegawai'),
|
|
DB::raw('sum(case when t.lulus_count >= ' . $totalSteps . ' then 1 else 0 end) as pegawai_selesai'),
|
|
])
|
|
->groupBy('t.tipe')
|
|
->orderBy('t.tipe')
|
|
->get();
|
|
|
|
$filename = 'monitoring-karyawan-luar-ringkasan-' . $generatedAt->format('Ymd-Hi') . '.xlsx';
|
|
return $this->streamXlsx($filename, function (Spreadsheet $spreadsheet) use ($tipeAgg, $totalSteps) {
|
|
$sheet = $spreadsheet->getActiveSheet();
|
|
$sheet->setTitle('External (Summary)');
|
|
|
|
$headers = ['Unit', 'Total Pitstop', 'Total Karyawan External', 'Karyawan External Selesai'];
|
|
foreach ($headers as $i => $h) {
|
|
$sheet->setCellValueByColumnAndRow($i + 1, 1, $h);
|
|
}
|
|
$sheet->getStyle('A1:D1')->getFont()->setBold(true);
|
|
$row = 2;
|
|
foreach ($tipeAgg as $r) {
|
|
$sheet->setCellValueByColumnAndRow(1, $row, (string) ($r->tipe ?? '-'));
|
|
$sheet->setCellValueByColumnAndRow(2, $row, (int) $totalSteps);
|
|
$sheet->setCellValueByColumnAndRow(3, $row, (int) ($r->total_pegawai ?? 0));
|
|
$sheet->setCellValueByColumnAndRow(4, $row, (int) ($r->pegawai_selesai ?? 0));
|
|
$row++;
|
|
}
|
|
|
|
foreach(range('A', 'D') as $col){
|
|
$sheet->getColumnDimension($col)->setAutoSize(true);
|
|
}
|
|
});
|
|
}
|
|
|
|
// Detail per tipe
|
|
$rows = DB::connection('pgsql')
|
|
->table('public.pegawai_luar_pl as pl')
|
|
->leftJoin('public.praakre as p', function ($join) {
|
|
$join->on('p.pegawai_id', '=', 'pl.id')
|
|
->where('p.tipe_karyawan', 'luar');
|
|
})
|
|
->leftJoin('public.masterpitstop as m', function ($join) {
|
|
$join->on(DB::raw('m.id::text'), '=', 'p.masterpitstop_id')
|
|
->where('m.statusenabled', true);
|
|
})
|
|
->where(DB::raw("coalesce(nullif(pl.tipe, ''), '-')"), '=', $tipe)
|
|
->select([
|
|
'pl.id',
|
|
DB::raw("coalesce(pl.nama, '-') as nama"),
|
|
DB::raw("coalesce(pl.nik, '-') as nik"),
|
|
DB::raw("count(distinct m.id) filter (where p.status='lulus') as lulus_count"),
|
|
DB::raw("coalesce((
|
|
select string_agg(ms.nama, ', ' order by ms.id)
|
|
from public.masterpitstop ms
|
|
left join public.praakre px
|
|
on px.pegawai_id = pl.id
|
|
and px.tipe_karyawan = 'luar'
|
|
and px.status = 'lulus'
|
|
and px.masterpitstop_id = ms.id::text
|
|
where ms.statusenabled = true
|
|
and px.id is null
|
|
), '') as belum_steps"),
|
|
])
|
|
->groupBy('pl.id', 'pl.nama', 'pl.nik')
|
|
->orderBy('pl.nama')
|
|
->get();
|
|
|
|
$filename = 'monitoring-karyawan-luar-' . preg_replace('/[^a-zA-Z0-9_-]+/', '-', (string) $tipe) . '-' . $generatedAt->format('Ymd-Hi') . '.xlsx';
|
|
return $this->streamXlsx($filename, function (Spreadsheet $spreadsheet) use ($rows, $tipe, $totalSteps) {
|
|
$sheet = $spreadsheet->getActiveSheet();
|
|
$sheet->setTitle('External (Detail)');
|
|
|
|
$headers = ['Unit', 'Nama', 'NIK', 'Lulus Pitstop', 'Total Pitstop', 'Belum Dikerjakan'];
|
|
foreach ($headers as $i => $h) {
|
|
$sheet->setCellValueByColumnAndRow($i + 1, 1, $h);
|
|
}
|
|
$sheet->getStyle('A1:H1')->getFont()->setBold(true);
|
|
|
|
$row = 2;
|
|
foreach ($rows as $r) {
|
|
$lulus = (int) ($r->lulus_count ?? 0);
|
|
$selesai = $totalSteps > 0 && $lulus >= $totalSteps ? 1 : 0;
|
|
|
|
$sheet->setCellValueByColumnAndRow(1, $row, (string) $tipe);
|
|
$sheet->setCellValueByColumnAndRow(2, $row, (string) ($r->nama ?? '-'));
|
|
$sheet->setCellValueExplicitByColumnAndRow(3, $row, (string) ($r->nik ?? '-'), DataType::TYPE_STRING);
|
|
$sheet->setCellValueByColumnAndRow(4, $row, $lulus);
|
|
$sheet->setCellValueByColumnAndRow(5, $row, (int) $totalSteps);
|
|
$sheet->setCellValueByColumnAndRow(6, $row, (string) ($r->belum_steps ?? ''));
|
|
$row++;
|
|
}
|
|
|
|
foreach(range('A', 'H') as $col){
|
|
$sheet->getColumnDimension($col)->setAutoSize(true);
|
|
}
|
|
});
|
|
}
|
|
|
|
public function dataProgressUnit(Request $request, $unit_id)
|
|
{
|
|
$unitId = (int) $unit_id;
|
|
|
|
$draw = $this->dtInt($request->input('draw'), 1);
|
|
$start = $this->dtInt($request->input('start'), 0);
|
|
$length = $this->dtInt($request->input('length'), 10);
|
|
if ($length < 1) $length = 10;
|
|
if ($length > 200) $length = 200;
|
|
|
|
$search = trim((string) data_get($request->all(), 'search.value', ''));
|
|
|
|
$totalSteps = (int) MasterPitStopPraAkre::where('statusenabled', true)->count();
|
|
|
|
$baseNoSearch = DB::connection('pgsql')
|
|
->table('public.mappegawaijabatantounitkerja_m as mp')
|
|
->join('public.pegawai_m as pg', 'pg.id', '=', 'mp.objectpegawaifk')
|
|
->join('public.unitkerjapegawai_m as ukp', 'ukp.id', '=', 'mp.objectunitkerjapegawaifk')
|
|
->leftJoin('public.praakre as p', 'p.pegawai_id', '=', 'pg.id')
|
|
->leftJoin('public.masterpitstop as m', function ($join) {
|
|
$join->on(DB::raw('m.id::text'), '=', 'p.masterpitstop_id')
|
|
->where('m.statusenabled', true);
|
|
})
|
|
->where('mp.statusenabled', true)
|
|
->where('mp.isprimary', true)
|
|
->where('pg.statusenabled', true)
|
|
->where('pg.kedudukanfk', 1)
|
|
->where('ukp.statusenabled', true)
|
|
->where('ukp.id', $unitId)
|
|
->select([
|
|
'pg.id',
|
|
DB::raw("coalesce(pg.namalengkap, '-') as nama"),
|
|
DB::raw("coalesce(pg.nip_pns, '-') as nip_pns"),
|
|
DB::raw("count(distinct m.id) filter (where p.status='lulus') as lulus_count"),
|
|
DB::raw("coalesce((
|
|
select count(*)
|
|
from public.masterpitstop ms
|
|
left join public.praakre px
|
|
on px.pegawai_id = pg.id
|
|
and px.status = 'lulus'
|
|
and px.masterpitstop_id = ms.id::text
|
|
where ms.statusenabled = true
|
|
and px.id is null
|
|
), 0) as belum_count"),
|
|
DB::raw("coalesce((
|
|
select string_agg(ms.nama, ', ' order by ms.id)
|
|
from public.masterpitstop ms
|
|
left join public.praakre px
|
|
on px.pegawai_id = pg.id
|
|
and px.status = 'lulus'
|
|
and px.masterpitstop_id = ms.id::text
|
|
where ms.statusenabled = true
|
|
and px.id is null
|
|
), '') as belum_steps"),
|
|
])
|
|
->groupBy('pg.id', 'pg.namalengkap', 'pg.nip_pns');
|
|
|
|
$base = clone $baseNoSearch;
|
|
if ($search !== '') {
|
|
$base->where('pg.namalengkap', 'ILIKE', '%' . $search . '%');
|
|
}
|
|
|
|
$recordsTotal = DB::connection('pgsql')->query()->fromSub($baseNoSearch, 't')->count();
|
|
$recordsFiltered = $search === ''
|
|
? $recordsTotal
|
|
: DB::connection('pgsql')->query()->fromSub($base, 't')->count();
|
|
|
|
$rows = $base
|
|
->orderByDesc('lulus_count')
|
|
->orderBy('pg.namalengkap')
|
|
->offset($start)
|
|
->limit($length)
|
|
->get();
|
|
|
|
$data = $rows->map(function ($r) use ($totalSteps) {
|
|
$lulus = (int) ($r->lulus_count ?? 0);
|
|
$pct = $totalSteps > 0 ? round(($lulus / $totalSteps) * 100, 1) : 0;
|
|
return [
|
|
'id' => (int) $r->id,
|
|
'nama' => (string) ($r->nama ?? '-'),
|
|
'nip_pns' => (string) ($r->nip_pns ?? '-'),
|
|
'lulus_count' => $lulus,
|
|
'pct' => $pct,
|
|
'selesai' => $totalSteps > 0 ? ($lulus >= $totalSteps ? 1 : 0) : 0,
|
|
'belum_count' => (int) ($r->belum_count ?? 0),
|
|
'belum_steps' => (string) ($r->belum_steps ?? ''),
|
|
];
|
|
})->values();
|
|
|
|
return response()->json([
|
|
'draw' => $draw,
|
|
'recordsTotal' => $recordsTotal,
|
|
'recordsFiltered' => $recordsFiltered,
|
|
'data' => $data,
|
|
]);
|
|
}
|
|
|
|
public function dataProgressExternalByTipe(Request $request, $tipe)
|
|
{
|
|
$tipe = urldecode((string) $tipe);
|
|
$tipe = trim($tipe);
|
|
abort_if($tipe === '', 404);
|
|
|
|
$draw = $this->dtInt($request->input('draw'), 1);
|
|
$start = $this->dtInt($request->input('start'), 0);
|
|
$length = $this->dtInt($request->input('length'), 10);
|
|
if ($length < 1) $length = 10;
|
|
if ($length > 200) $length = 200;
|
|
|
|
$search = trim((string) data_get($request->all(), 'search.value', ''));
|
|
|
|
$totalSteps = (int) MasterPitStopPraAkre::where('statusenabled', true)->count();
|
|
|
|
$baseNoSearch = DB::connection('pgsql')
|
|
->table('public.pegawai_luar_pl as pl')
|
|
->leftJoin('public.praakre as p', function ($join) {
|
|
$join->on('p.pegawai_id', '=', 'pl.id')
|
|
->where('p.tipe_karyawan', 'luar');
|
|
})
|
|
->leftJoin('public.masterpitstop as m', function ($join) {
|
|
$join->on(DB::raw('m.id::text'), '=', 'p.masterpitstop_id')
|
|
->where('m.statusenabled', true);
|
|
})
|
|
->where(DB::raw("coalesce(nullif(pl.tipe, ''), '-')"), '=', $tipe)
|
|
->select([
|
|
'pl.id',
|
|
DB::raw("coalesce(pl.nama, '-') as nama"),
|
|
DB::raw("coalesce(pl.nik, '-') as nik"),
|
|
DB::raw("count(distinct m.id) filter (where p.status='lulus') as lulus_count"),
|
|
DB::raw("coalesce((
|
|
select count(*)
|
|
from public.masterpitstop ms
|
|
left join public.praakre px
|
|
on px.pegawai_id = pl.id
|
|
and px.tipe_karyawan = 'luar'
|
|
and px.status = 'lulus'
|
|
and px.masterpitstop_id = ms.id::text
|
|
where ms.statusenabled = true
|
|
and px.id is null
|
|
), 0) as belum_count"),
|
|
DB::raw("coalesce((
|
|
select string_agg(ms.nama, ', ' order by ms.id)
|
|
from public.masterpitstop ms
|
|
left join public.praakre px
|
|
on px.pegawai_id = pl.id
|
|
and px.tipe_karyawan = 'luar'
|
|
and px.status = 'lulus'
|
|
and px.masterpitstop_id = ms.id::text
|
|
where ms.statusenabled = true
|
|
and px.id is null
|
|
), '') as belum_steps"),
|
|
])
|
|
->groupBy('pl.id', 'pl.nama', 'pl.nik');
|
|
|
|
$base = clone $baseNoSearch;
|
|
if ($search !== '') {
|
|
$base->where(function ($q) use ($search) {
|
|
$q->where('pl.nama', 'ILIKE', '%' . $search . '%')
|
|
->orWhere('pl.nik', 'ILIKE', '%' . $search . '%');
|
|
});
|
|
}
|
|
|
|
$recordsTotal = DB::connection('pgsql')->query()->fromSub($baseNoSearch, 't')->count();
|
|
$recordsFiltered = $search === ''
|
|
? $recordsTotal
|
|
: DB::connection('pgsql')->query()->fromSub($base, 't')->count();
|
|
|
|
$rows = $base
|
|
->orderByDesc('lulus_count')
|
|
->orderBy('pl.nama')
|
|
->offset($start)
|
|
->limit($length)
|
|
->get();
|
|
|
|
$data = $rows->map(function ($r) use ($totalSteps) {
|
|
$lulus = (int) ($r->lulus_count ?? 0);
|
|
$pct = $totalSteps > 0 ? round(($lulus / $totalSteps) * 100, 1) : 0;
|
|
return [
|
|
'id' => (int) $r->id,
|
|
'nama' => (string) ($r->nama ?? '-'),
|
|
'nik' => (string) ($r->nik ?? '-'),
|
|
'lulus_count' => $lulus,
|
|
'pct' => $pct,
|
|
'selesai' => $totalSteps > 0 ? ($lulus >= $totalSteps ? 1 : 0) : 0,
|
|
'belum_count' => (int) ($r->belum_count ?? 0),
|
|
'belum_steps' => (string) ($r->belum_steps ?? ''),
|
|
];
|
|
})->values();
|
|
|
|
return response()->json([
|
|
'draw' => $draw,
|
|
'recordsTotal' => $recordsTotal,
|
|
'recordsFiltered' => $recordsFiltered,
|
|
'data' => $data,
|
|
]);
|
|
}
|
|
|
|
public function dataProgressAllKaryawan(Request $request)
|
|
{
|
|
$draw = $this->dtInt($request->input('draw'), 1);
|
|
$start = $this->dtInt($request->input('start'), 0);
|
|
$length = $this->dtInt($request->input('length'), 10);
|
|
if ($length < 1) $length = 10;
|
|
if ($length > 200) $length = 200;
|
|
|
|
$search = trim((string) data_get($request->all(), 'search.value', ''));
|
|
|
|
$totalSteps = (int) MasterPitStopPraAkre::where('statusenabled', true)->count();
|
|
|
|
// Internal
|
|
$internal = DB::connection('pgsql')
|
|
->table('public.mappegawaijabatantounitkerja_m as mp')
|
|
->join('public.pegawai_m as pg', 'pg.id', '=', 'mp.objectpegawaifk')
|
|
->join('public.unitkerjapegawai_m as ukp', 'ukp.id', '=', 'mp.objectunitkerjapegawaifk')
|
|
->leftJoin('public.praakre as p', 'p.pegawai_id', '=', 'pg.id')
|
|
->leftJoin('public.masterpitstop as m', function ($join) {
|
|
$join->on(DB::raw('m.id::text'), '=', 'p.masterpitstop_id')
|
|
->where('m.statusenabled', true);
|
|
})
|
|
->where('mp.statusenabled', true)
|
|
->where('mp.isprimary', true)
|
|
->where('pg.statusenabled', true)
|
|
->where('pg.kedudukanfk', 1)
|
|
->where('ukp.statusenabled', true)
|
|
->select([
|
|
DB::raw("'internal' as tipe_karyawan"),
|
|
'pg.id',
|
|
DB::raw("coalesce(pg.namalengkap, '-') as nama"),
|
|
DB::raw("coalesce(pg.nip_pns, '-') as identitas"),
|
|
DB::raw("coalesce(ukp.name, '-') as unit_name"),
|
|
DB::raw("count(distinct m.id) filter (where p.status='lulus') as lulus_count"),
|
|
DB::raw("coalesce((
|
|
select count(*)
|
|
from public.masterpitstop ms
|
|
left join public.praakre px
|
|
on px.pegawai_id = pg.id
|
|
and px.status = 'lulus'
|
|
and px.masterpitstop_id = ms.id::text
|
|
where ms.statusenabled = true
|
|
and px.id is null
|
|
), 0) as belum_count"),
|
|
DB::raw("coalesce((
|
|
select string_agg(ms.nama, ', ' order by ms.id)
|
|
from public.masterpitstop ms
|
|
left join public.praakre px
|
|
on px.pegawai_id = pg.id
|
|
and px.status = 'lulus'
|
|
and px.masterpitstop_id = ms.id::text
|
|
where ms.statusenabled = true
|
|
and px.id is null
|
|
), '') as belum_steps"),
|
|
])
|
|
->groupBy('pg.id', 'pg.namalengkap', 'pg.nip_pns', 'ukp.name');
|
|
|
|
// External
|
|
$external = DB::connection('pgsql')
|
|
->table('public.pegawai_luar_pl as pl')
|
|
->leftJoin('public.praakre as p', function ($join) {
|
|
$join->on('p.pegawai_id', '=', 'pl.id')
|
|
->where('p.tipe_karyawan', 'luar');
|
|
})
|
|
->leftJoin('public.masterpitstop as m', function ($join) {
|
|
$join->on(DB::raw('m.id::text'), '=', 'p.masterpitstop_id')
|
|
->where('m.statusenabled', true);
|
|
})
|
|
->select([
|
|
DB::raw("'luar' as tipe_karyawan"),
|
|
'pl.id',
|
|
DB::raw("coalesce(pl.nama, '-') as nama"),
|
|
DB::raw("coalesce(pl.nik, '-') as identitas"),
|
|
DB::raw("coalesce(nullif(pl.tipe, ''), '-') as unit_name"),
|
|
DB::raw("count(distinct m.id) filter (where p.status='lulus') as lulus_count"),
|
|
DB::raw("coalesce((
|
|
select count(*)
|
|
from public.masterpitstop ms
|
|
left join public.praakre px
|
|
on px.pegawai_id = pl.id
|
|
and px.tipe_karyawan = 'luar'
|
|
and px.status = 'lulus'
|
|
and px.masterpitstop_id = ms.id::text
|
|
where ms.statusenabled = true
|
|
and px.id is null
|
|
), 0) as belum_count"),
|
|
DB::raw("coalesce((
|
|
select string_agg(ms.nama, ', ' order by ms.id)
|
|
from public.masterpitstop ms
|
|
left join public.praakre px
|
|
on px.pegawai_id = pl.id
|
|
and px.tipe_karyawan = 'luar'
|
|
and px.status = 'lulus'
|
|
and px.masterpitstop_id = ms.id::text
|
|
where ms.statusenabled = true
|
|
and px.id is null
|
|
), '') as belum_steps"),
|
|
])
|
|
->groupBy('pl.id', 'pl.nama', 'pl.nik', DB::raw("coalesce(nullif(pl.tipe, ''), '-')"));
|
|
|
|
$union = $internal->unionAll($external);
|
|
|
|
$baseNoSearch = DB::connection('pgsql')->query()->fromSub($union, 'u');
|
|
$base = DB::connection('pgsql')->query()->fromSub($union, 'u');
|
|
|
|
if ($search !== '') {
|
|
$base->where(function ($q) use ($search) {
|
|
$q->where('u.nama', 'ILIKE', '%' . $search . '%')
|
|
->orWhere('u.identitas', 'ILIKE', '%' . $search . '%')
|
|
->orWhere('u.unit_name', 'ILIKE', '%' . $search . '%')
|
|
->orWhere('u.tipe_karyawan', 'ILIKE', '%' . $search . '%');
|
|
});
|
|
}
|
|
|
|
$recordsTotal = DB::connection('pgsql')->query()->fromSub($baseNoSearch, 't')->count();
|
|
$recordsFiltered = $search === ''
|
|
? $recordsTotal
|
|
: DB::connection('pgsql')->query()->fromSub($base, 't')->count();
|
|
|
|
$rows = $base
|
|
->orderByDesc('lulus_count')
|
|
->orderBy('nama')
|
|
->offset($start)
|
|
->limit($length)
|
|
->get();
|
|
|
|
$data = $rows->map(function ($r) use ($totalSteps) {
|
|
$lulus = (int) ($r->lulus_count ?? 0);
|
|
$pct = $totalSteps > 0 ? round(($lulus / $totalSteps) * 100, 1) : 0;
|
|
return [
|
|
'tipe_karyawan' => (string) ($r->tipe_karyawan ?? 'internal'),
|
|
'id' => (int) ($r->id ?? 0),
|
|
'nama' => (string) ($r->nama ?? '-'),
|
|
'identitas' => (string) ($r->identitas ?? '-'),
|
|
'unit_name' => (string) ($r->unit_name ?? '-'),
|
|
'lulus_count' => $lulus,
|
|
'pct' => $pct,
|
|
'selesai' => $totalSteps > 0 ? ($lulus >= $totalSteps ? 1 : 0) : 0,
|
|
'belum_count' => (int) ($r->belum_count ?? 0),
|
|
'belum_steps' => (string) ($r->belum_steps ?? ''),
|
|
];
|
|
})->values();
|
|
|
|
return response()->json([
|
|
'draw' => $draw,
|
|
'recordsTotal' => $recordsTotal,
|
|
'recordsFiltered' => $recordsFiltered,
|
|
'data' => $data,
|
|
]);
|
|
}
|
|
|
|
|
|
|
|
public function progressDetail(Request $request)
|
|
{
|
|
$validator = Validator::make($request->all(), [
|
|
'pegawai_id' => 'required|integer|exists:pgsql.public.pegawai_m,id',
|
|
]);
|
|
|
|
if ($validator->fails()) {
|
|
return response()->json([
|
|
'error' => 1,
|
|
'message' => 'Validasi gagal.',
|
|
'errors' => $validator->errors(),
|
|
], 422);
|
|
}
|
|
|
|
$pegawaiId = (int) $validator->validated()['pegawai_id'];
|
|
|
|
$rows = DB::connection('pgsql')
|
|
->table('public.praakre as p')
|
|
->leftJoin('public.masterpitstop as m', function ($join) {
|
|
$join->on(DB::raw('m.id::text'), '=', 'p.masterpitstop_id')
|
|
->where('m.statusenabled', true);
|
|
})
|
|
->where('p.pegawai_id', $pegawaiId)
|
|
->where('p.status', 'lulus')
|
|
->whereNotNull('m.id')
|
|
->select([
|
|
'p.id',
|
|
'p.masterpitstop_id',
|
|
DB::raw("coalesce(m.nama, '-') as step_nama"),
|
|
'p.status',
|
|
DB::raw("to_char(p.created_at, 'DD-MM-YYYY HH24:MI') as created_at"),
|
|
])
|
|
->orderByDesc('p.id')
|
|
->limit(500)
|
|
->get();
|
|
|
|
return response()->json([
|
|
'error' => 0,
|
|
'data' => $rows,
|
|
]);
|
|
}
|
|
|
|
public function progressDetailExternal(Request $request)
|
|
{
|
|
$validator = Validator::make($request->all(), [
|
|
'pegawai_id' => 'required|integer|exists:pgsql.public.pegawai_luar_pl,id',
|
|
]);
|
|
|
|
if ($validator->fails()) {
|
|
return response()->json([
|
|
'error' => 1,
|
|
'message' => 'Validasi gagal.',
|
|
'errors' => $validator->errors(),
|
|
], 422);
|
|
}
|
|
|
|
$pegawaiId = (int) $validator->validated()['pegawai_id'];
|
|
|
|
$rows = DB::connection('pgsql')
|
|
->table('public.praakre as p')
|
|
->leftJoin('public.masterpitstop as m', function ($join) {
|
|
$join->on(DB::raw('m.id::text'), '=', 'p.masterpitstop_id')
|
|
->where('m.statusenabled', true);
|
|
})
|
|
->where('p.tipe_karyawan', 'luar')
|
|
->where('p.status', 'lulus')
|
|
->where('p.pegawai_id', $pegawaiId)
|
|
->whereNotNull('m.id')
|
|
->select([
|
|
'p.id',
|
|
'p.masterpitstop_id',
|
|
DB::raw("coalesce(m.nama, '-') as step_nama"),
|
|
'p.status',
|
|
DB::raw("to_char(p.created_at, 'DD-MM-YYYY HH24:MI') as created_at"),
|
|
])
|
|
->orderByDesc('p.id')
|
|
->limit(500)
|
|
->get();
|
|
|
|
return response()->json([
|
|
'error' => 0,
|
|
'data' => $rows,
|
|
]);
|
|
}
|
|
|
|
public function pegawaiSteps(Request $request)
|
|
{
|
|
$validator = Validator::make($request->all(), [
|
|
'pegawai_id' => 'required|integer|exists:pgsql.public.pegawai_m,id',
|
|
]);
|
|
|
|
if ($validator->fails()) {
|
|
return response()->json([
|
|
'error' => 1,
|
|
'message' => 'Validasi gagal.',
|
|
'errors' => $validator->errors(),
|
|
], 422);
|
|
}
|
|
|
|
$pegawaiId = (int) $validator->validated()['pegawai_id'];
|
|
|
|
$lockedSteps = PraAkre::where('pegawai_id', $pegawaiId)
|
|
->where('status', 'lulus')
|
|
->distinct()
|
|
->pluck('masterpitstop_id');
|
|
|
|
return response()->json([
|
|
'error' => 0,
|
|
'data' => [
|
|
'locked_steps' => $lockedSteps,
|
|
],
|
|
]);
|
|
}
|
|
|
|
public function pegawaiStepsExternal(Request $request)
|
|
{
|
|
$validator = Validator::make($request->all(), [
|
|
'pegawai_id' => 'required|integer|exists:pgsql.public.pegawai_luar_pl,id',
|
|
]);
|
|
|
|
if ($validator->fails()) {
|
|
return response()->json([
|
|
'error' => 1,
|
|
'message' => 'Validasi gagal.',
|
|
'errors' => $validator->errors(),
|
|
], 422);
|
|
}
|
|
|
|
$pegawaiId = (int) $validator->validated()['pegawai_id'];
|
|
|
|
$lockedSteps = PraAkre::where('pegawai_id', $pegawaiId)
|
|
->where('tipe_karyawan', 'luar')
|
|
->where('status', 'lulus')
|
|
->distinct()
|
|
->pluck('masterpitstop_id');
|
|
|
|
return response()->json([
|
|
'error' => 0,
|
|
'data' => [
|
|
'locked_steps' => $lockedSteps,
|
|
],
|
|
]);
|
|
}
|
|
|
|
public function submit(Request $request)
|
|
{
|
|
$tipeKaryawan = (string) $request->input('tipe_karyawan', 'internal');
|
|
$tipeKaryawan = $tipeKaryawan === 'luar' ? 'luar' : 'internal';
|
|
|
|
$validator = Validator::make($request->all(), [
|
|
'karyawan_id' => ['required', 'integer'],
|
|
'step' => 'required',
|
|
'status' => 'required|in:lulus,tidak_lulus',
|
|
'unit_id' => 'nullable|string|max:15',
|
|
'tipe_karyawan' => 'nullable|in:internal,luar',
|
|
]);
|
|
|
|
if ($validator->fails()) {
|
|
return response()->json([
|
|
'error' => 1,
|
|
'message' => 'Validasi gagal.',
|
|
'errors' => $validator->errors(),
|
|
], 422);
|
|
}
|
|
|
|
$payload = $validator->validated();
|
|
$payload['tipe_karyawan'] = $tipeKaryawan;
|
|
|
|
$pegawaiId = (int) $payload['karyawan_id'];
|
|
$masterPitstopId = (string) $payload['step'];
|
|
|
|
if ($tipeKaryawan === 'luar') {
|
|
$exists = DB::connection('pgsql')
|
|
->table('public.pegawai_luar_pl')
|
|
->where('id', $pegawaiId)
|
|
->exists();
|
|
if (!$exists) {
|
|
return response()->json([
|
|
'error' => 1,
|
|
'message' => 'Karyawan luar tidak ditemukan.',
|
|
], 422);
|
|
}
|
|
} else {
|
|
$exists = DB::connection('pgsql')
|
|
->table('public.pegawai_m')
|
|
->where('id', $pegawaiId)
|
|
->exists();
|
|
if (!$exists) {
|
|
return response()->json([
|
|
'error' => 1,
|
|
'message' => 'Karyawan tidak ditemukan.',
|
|
], 422);
|
|
}
|
|
}
|
|
|
|
$alreadyPassed = PraAkre::where('pegawai_id', $pegawaiId)
|
|
->where('tipe_karyawan', $tipeKaryawan)
|
|
->where('masterpitstop_id', $masterPitstopId)
|
|
->where('status', 'lulus')
|
|
->exists();
|
|
|
|
if ($alreadyPassed) {
|
|
return response()->json([
|
|
'error' => 1,
|
|
'message' => 'Step ini sudah lulus dan terkunci.',
|
|
], 409);
|
|
}
|
|
|
|
$row = PraAkre::create([
|
|
'pegawai_id' => $pegawaiId,
|
|
'masterpitstop_id' => $masterPitstopId,
|
|
'unit_id' => $tipeKaryawan === 'luar' ? null : ($payload['unit_id'] ?? null),
|
|
'status' => $payload['status'],
|
|
'tipe_karyawan' => $payload['tipe_karyawan'],
|
|
'action_at' => auth()->user()->objectpegawaifk
|
|
,
|
|
'created_at' => now(),
|
|
]);
|
|
|
|
return response()->json([
|
|
'error' => 0,
|
|
'message' => 'Data berhasil disimpan.',
|
|
'data' => [
|
|
'id' => $row->id,
|
|
'pegawai_id' => $row->pegawai_id,
|
|
'masterpitstop_id' => $row->masterpitstop_id,
|
|
'status' => $row->status,
|
|
],
|
|
]);
|
|
}
|
|
|
|
}
|