302 lines
11 KiB
PHP
302 lines
11 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use Illuminate\Http\Request;
|
|
use App\Models\InformasiKegiatan;
|
|
use App\Models\Kabupaten;
|
|
use App\Models\Kecamatan;
|
|
use App\Models\Kelurahan;
|
|
use Carbon\Carbon;
|
|
|
|
class PengumumanController extends Controller
|
|
{
|
|
public function index()
|
|
{
|
|
$pengumuman = InformasiKegiatan::with('saranTanggapan')
|
|
->active()
|
|
->orderBy('TanggalMulaiPeriode', 'desc')
|
|
->get()
|
|
->map(function ($item, $index) {
|
|
return [
|
|
'no' => $index + 1,
|
|
'no_registrasi' => $item->NoRegistrasi,
|
|
'nama_perusahaan' => $item->Pemrakarsa,
|
|
'nama_kegiatan' => $item->NamaKegiatan,
|
|
'jenis_dokumen' => $item->JenisDokumen,
|
|
'periode' => $this->formatBusinessDayPeriod($item->TanggalMulaiPeriode, 10),
|
|
'status' => 'Menunggu Tanggapan',
|
|
'detail_url' => route('pengumuman.detail', $item->KegiatanID)
|
|
];
|
|
});
|
|
|
|
return view('pengumuman.index', compact('pengumuman'));
|
|
}
|
|
|
|
/**
|
|
* Generate business day period (10 working days excluding weekends and holidays)
|
|
*/
|
|
private function formatBusinessDayPeriod($startDate, $workingDays = 10)
|
|
{
|
|
$start = Carbon::parse($startDate);
|
|
$current = $start->copy();
|
|
$daysAdded = 0;
|
|
|
|
// Indonesian public holidays 2025 (tanggal merah)
|
|
$holidays = [
|
|
'2025-01-01', // Tahun Baru
|
|
'2025-01-29', // Tahun Baru Imlek
|
|
'2025-03-29', // Hari Raya Nyepi
|
|
'2025-03-30', // Wafat Isa Almasih
|
|
'2025-04-09', // Isra Miraj
|
|
'2025-05-01', // Hari Buruh
|
|
'2025-05-12', // Hari Raya Waisak
|
|
'2025-05-29', // Kenaikan Isa Almasih
|
|
'2025-06-01', // Hari Lahir Pancasila
|
|
'2025-06-06', // Idul Fitri 1446 H
|
|
'2025-06-07', // Idul Fitri 1446 H
|
|
'2025-08-17', // Hari Kemerdekaan RI
|
|
'2025-08-31', // Idul Adha 1446 H
|
|
'2025-09-21', // Tahun Baru Islam 1447 H
|
|
'2025-11-30', // Maulid Nabi Muhammad SAW
|
|
'2025-12-25', // Hari Raya Natal
|
|
];
|
|
|
|
while ($daysAdded < $workingDays) {
|
|
$current->addDay();
|
|
|
|
// Skip weekends (Saturday = 6, Sunday = 0)
|
|
if ($current->dayOfWeek == Carbon::SATURDAY || $current->dayOfWeek == Carbon::SUNDAY) {
|
|
continue;
|
|
}
|
|
|
|
// Skip public holidays
|
|
if (in_array($current->format('Y-m-d'), $holidays)) {
|
|
continue;
|
|
}
|
|
|
|
$daysAdded++;
|
|
}
|
|
|
|
return $start->format('d M') . ' - ' . $current->format('d M Y');
|
|
}
|
|
|
|
public function detail($id)
|
|
{
|
|
$kegiatan = InformasiKegiatan::with('saranTanggapanApproved')->findOrFail($id);
|
|
return view('pengumuman.detail', compact('kegiatan'));
|
|
}
|
|
|
|
public function create()
|
|
{
|
|
$kabupaten = Kabupaten::orderBy('NamaKabupaten', 'asc')->get();
|
|
return view('pengumuman.create', compact('kabupaten'));
|
|
}
|
|
|
|
/**
|
|
* Generate unique 12-digit registration number with enhanced security
|
|
* Format: Mixed alphanumeric with timestamp hash to prevent easy guessing
|
|
* Example: ENV4B7X9K2M
|
|
*/
|
|
private function generateRegistrationNumber()
|
|
{
|
|
do {
|
|
// Create a unique seed from current time, microtime, and random data
|
|
$seed = now()->timestamp . microtime(true) . random_int(100000, 999999);
|
|
|
|
// Generate hash and extract alphanumeric characters
|
|
$hash = hash('sha256', $seed);
|
|
|
|
// Create character pool (excluding similar looking characters)
|
|
$chars = '23456789ABCDEFGHJKLMNPQRSTUVWXYZ';
|
|
|
|
// Start with prefix
|
|
$prefix = 'REG';
|
|
|
|
// Generate 9 additional characters from hash
|
|
$remaining = '';
|
|
$hashPos = 0;
|
|
|
|
while (strlen($remaining) < 9 && $hashPos < strlen($hash)) {
|
|
$hexChar = strtoupper($hash[$hashPos]);
|
|
|
|
// Convert hex to index in our character pool
|
|
$index = hexdec($hexChar) % strlen($chars);
|
|
$remaining .= $chars[$index];
|
|
|
|
$hashPos++;
|
|
}
|
|
|
|
// If we need more characters, use additional random generation
|
|
while (strlen($remaining) < 9) {
|
|
$remaining .= $chars[random_int(0, strlen($chars) - 1)];
|
|
}
|
|
|
|
$registrationNumber = $prefix . $remaining;
|
|
|
|
// Check if this number already exists
|
|
$exists = InformasiKegiatan::where('NoRegistrasi', $registrationNumber)->exists();
|
|
|
|
} while ($exists); // Keep generating until we get a unique number
|
|
|
|
return $registrationNumber;
|
|
}
|
|
|
|
public function store(Request $request)
|
|
{
|
|
$validated = $request->validate([
|
|
'jenis_dokumen' => 'required|string|max:50',
|
|
'nama_kegiatan' => 'required|string|max:255',
|
|
'pemrakarsa' => 'required|string|max:100',
|
|
'bidang_usaha' => 'required|string|max:100',
|
|
'deskripsi_kegiatan' => 'required|string',
|
|
'dampak_potensial' => 'required|string',
|
|
'kabupaten' => 'required|string|max:100',
|
|
'kecamatan' => 'required|string|max:100',
|
|
'kelurahan' => 'required|string|max:100',
|
|
'lokasi_kegiatan' => 'nullable|string|max:100',
|
|
'deskripsi_lokasi' => 'required|string',
|
|
'latitude' => 'nullable|numeric|between:-90,90',
|
|
'longitude' => 'nullable|numeric|between:-180,180',
|
|
'tanggal_mulai' => 'required|date|after_or_equal:today',
|
|
'skala_besaran' => 'nullable|string|max:50',
|
|
'kewenangan' => 'required|string|max:50',
|
|
'status' => 'required|in:aktif,nonaktif'
|
|
], [
|
|
'jenis_dokumen.required' => 'Jenis dokumen wajib dipilih',
|
|
'nama_kegiatan.required' => 'Nama kegiatan wajib diisi',
|
|
'pemrakarsa.required' => 'Pemrakarsa wajib diisi',
|
|
'bidang_usaha.required' => 'Bidang usaha wajib diisi',
|
|
'deskripsi_kegiatan.required' => 'Deskripsi kegiatan wajib diisi',
|
|
'dampak_potensial.required' => 'Dampak potensial wajib diisi',
|
|
'kabupaten.required' => 'Kabupaten wajib dipilih',
|
|
'kecamatan.required' => 'Kecamatan wajib dipilih',
|
|
'kelurahan.required' => 'Kelurahan wajib dipilih',
|
|
'deskripsi_lokasi.required' => 'Deskripsi lokasi wajib diisi',
|
|
'tanggal_mulai.required' => 'Tanggal mulai periode wajib diisi',
|
|
'tanggal_mulai.after_or_equal' => 'Tanggal mulai tidak boleh kurang dari hari ini',
|
|
'kewenangan.required' => 'Kewenangan wajib dipilih',
|
|
'status.required' => 'Status wajib dipilih',
|
|
'latitude.between' => 'Latitude harus antara -90 sampai 90',
|
|
'longitude.between' => 'Longitude harus antara -180 sampai 180'
|
|
]);
|
|
|
|
try {
|
|
// Generate unique registration number
|
|
$noRegistrasi = $this->generateRegistrationNumber();
|
|
|
|
// Calculate end date (10 business days from start date)
|
|
$startDate = Carbon::parse($validated['tanggal_mulai']);
|
|
$endDate = $this->calculateBusinessDayEnd($startDate, 10);
|
|
|
|
// Get location names from database
|
|
$kabupaten = Kabupaten::find($validated['kabupaten']);
|
|
$kecamatan = Kecamatan::find($validated['kecamatan']);
|
|
$kelurahan = Kelurahan::find($validated['kelurahan']);
|
|
|
|
$kombinasiLokasi = $kabupaten->NamaKabupaten . ', ' . $kecamatan->NamaKecamatan . ', ' . $kelurahan->NamaKelurahan;
|
|
|
|
InformasiKegiatan::create([
|
|
'NoRegistrasi' => $noRegistrasi,
|
|
'JenisDokumen' => $validated['jenis_dokumen'],
|
|
'NamaKegiatan' => $validated['nama_kegiatan'],
|
|
'Pemrakarsa' => $validated['pemrakarsa'],
|
|
'BidangUsaha' => $validated['bidang_usaha'],
|
|
'DeskripsiKegiatan' => $validated['deskripsi_kegiatan'],
|
|
'DampakPotensial' => $validated['dampak_potensial'],
|
|
'ProvinsiKota' => $kombinasiLokasi,
|
|
'LokasiKegiatan' => $validated['lokasi_kegiatan'],
|
|
'DeskripsiLokasi' => $validated['deskripsi_lokasi'],
|
|
'Latitude' => $validated['latitude'],
|
|
'Longitude' => $validated['longitude'],
|
|
'TanggalMulaiPeriode' => $startDate,
|
|
'TanggalSelesaiPeriode' => $endDate,
|
|
'SkalaBesaran' => $validated['skala_besaran'],
|
|
'Kewenangan' => $validated['kewenangan'],
|
|
'Status' => $validated['status']
|
|
]);
|
|
|
|
return redirect()->route('pengumuman.index')
|
|
->with('success', 'Pengumuman kegiatan berhasil ditambahkan dengan nomor registrasi: ' . $noRegistrasi);
|
|
|
|
} catch (\Exception $e) {
|
|
return back()
|
|
->withInput()
|
|
->with('error', 'Terjadi kesalahan saat menyimpan data: ' . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
public function calculatePeriod(Request $request)
|
|
{
|
|
$startDate = Carbon::parse($request->start_date);
|
|
$endDate = $this->calculateBusinessDayEnd($startDate, 10);
|
|
|
|
$periode = $startDate->format('d M') . ' - ' . $endDate->format('d M Y');
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'periode' => $periode,
|
|
'start_date' => $startDate->format('Y-m-d'),
|
|
'end_date' => $endDate->format('Y-m-d')
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Calculate business day end date (excludes weekends and holidays)
|
|
*/
|
|
private function calculateBusinessDayEnd($startDate, $workingDays = 10)
|
|
{
|
|
$current = $startDate->copy();
|
|
$daysAdded = 0;
|
|
|
|
// Indonesian public holidays 2025 (tanggal merah)
|
|
$holidays = [
|
|
'2025-01-01', '2025-01-29', '2025-03-29', '2025-03-30', '2025-04-09',
|
|
'2025-05-01', '2025-05-12', '2025-05-29', '2025-06-01', '2025-06-06',
|
|
'2025-06-07', '2025-08-17', '2025-08-31', '2025-09-21', '2025-11-30',
|
|
'2025-12-25'
|
|
];
|
|
|
|
while ($daysAdded < $workingDays) {
|
|
$current->addDay();
|
|
|
|
// Skip weekends and holidays
|
|
if ($current->dayOfWeek == Carbon::SATURDAY ||
|
|
$current->dayOfWeek == Carbon::SUNDAY ||
|
|
in_array($current->format('Y-m-d'), $holidays)) {
|
|
continue;
|
|
}
|
|
|
|
$daysAdded++;
|
|
}
|
|
|
|
return $current;
|
|
}
|
|
|
|
/**
|
|
* Get kecamatan by kabupaten ID
|
|
*/
|
|
public function getKecamatan(Request $request)
|
|
{
|
|
$kabupatenId = $request->kabupaten_id;
|
|
$kecamatan = Kecamatan::where('KabupatenId', $kabupatenId)
|
|
->orderBy('NamaKecamatan', 'asc')
|
|
->get(['KecamatanId', 'NamaKecamatan']);
|
|
|
|
return response()->json($kecamatan);
|
|
}
|
|
|
|
/**
|
|
* Get kelurahan by kecamatan ID
|
|
*/
|
|
public function getKelurahan(Request $request)
|
|
{
|
|
$kecamatanId = $request->kecamatan_id;
|
|
$kelurahan = Kelurahan::where('KecamatanId', $kecamatanId)
|
|
->orderBy('NamaKelurahan', 'asc')
|
|
->get(['KelurahanId', 'NamaKelurahan']);
|
|
|
|
return response()->json($kelurahan);
|
|
}
|
|
}
|