mirror of
https://github.com/rekywhyd/WebGIS_PengentasanKemiskinan.git
synced 2026-07-10 19:33:07 +00:00
Memperbarui UI/UX
This commit is contained in:
@@ -0,0 +1,218 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use App\Models\LaporanMasuk;
|
||||
|
||||
class FetchEmails extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'emails:fetch';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Fetch unread emails with subject LAPORAN BANTUAN via IMAP';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$server = '{imap.gmail.com:993/imap/ssl}INBOX';
|
||||
$username = 'bantuansambas@gmail.com';
|
||||
$password = 'tkro trmt vxli yekm';
|
||||
|
||||
$this->info('[' . date('Y-m-d H:i:s') . '] Memulai proses penarikan email...');
|
||||
|
||||
if (!function_exists('imap_open')) {
|
||||
$this->error('Ekstensi IMAP tidak diaktifkan pada instalasi PHP ini.');
|
||||
return;
|
||||
}
|
||||
|
||||
$inbox = @imap_open($server, $username, $password);
|
||||
|
||||
if (!$inbox) {
|
||||
$this->error('Gagal terhubung ke server IMAP: ' . imap_last_error());
|
||||
return;
|
||||
}
|
||||
|
||||
$this->info("Berhasil terhubung ke email: $username");
|
||||
|
||||
$search_criteria = 'UNSEEN SUBJECT "LAPORAN BANTUAN"';
|
||||
$emails = imap_search($inbox, $search_criteria);
|
||||
|
||||
if ($emails) {
|
||||
$this->info("Ditemukan " . count($emails) . " email laporan baru.");
|
||||
|
||||
foreach ($emails as $email_number) {
|
||||
$overview = imap_fetch_overview($inbox, $email_number, 0);
|
||||
|
||||
$subjek = $overview[0]->subject ?? '(Tanpa Subjek)';
|
||||
$pengirim = $overview[0]->from ?? '(Tanpa Pengirim)';
|
||||
$tanggal_email = isset($overview[0]->date) ? date('Y-m-d H:i:s', strtotime($overview[0]->date)) : now();
|
||||
|
||||
$structure = imap_fetchstructure($inbox, $email_number);
|
||||
|
||||
$pesan = $this->extractBody($inbox, $email_number, $structure);
|
||||
$attachments = $this->extractAttachments($inbox, $email_number, $structure);
|
||||
|
||||
$lampiran_paths = [];
|
||||
$upload_dir = storage_path('app/public/uploads');
|
||||
if (!is_dir($upload_dir)) {
|
||||
mkdir($upload_dir, 0755, true);
|
||||
}
|
||||
|
||||
foreach ($attachments as $at) {
|
||||
$file_ext = pathinfo($at['filename'], PATHINFO_EXTENSION);
|
||||
if (empty($file_ext)) {
|
||||
$file_ext = 'bin';
|
||||
}
|
||||
$new_filename = time() . '_' . uniqid() . '.' . $file_ext;
|
||||
$file_path = $upload_dir . '/' . $new_filename;
|
||||
file_put_contents($file_path, $at['data']);
|
||||
$lampiran_paths[] = 'uploads/' . $new_filename;
|
||||
}
|
||||
$lampiran_str = implode(',', $lampiran_paths);
|
||||
|
||||
$laporan = LaporanMasuk::create([
|
||||
'pengirim' => $pengirim,
|
||||
'tanggal' => $tanggal_email,
|
||||
'subjek' => $subjek,
|
||||
'pesan' => trim($pesan),
|
||||
'lampiran' => $lampiran_str,
|
||||
'status' => 'Menunggu'
|
||||
]);
|
||||
|
||||
if ($laporan) {
|
||||
$this->info("- Berhasil menyimpan laporan dari: $pengirim");
|
||||
} else {
|
||||
$this->error("- Gagal menyimpan laporan dari: $pengirim.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->info("Tidak ada email laporan baru.");
|
||||
}
|
||||
|
||||
imap_close($inbox);
|
||||
$this->info('[' . date('Y-m-d H:i:s') . '] Proses penarikan email selesai.');
|
||||
}
|
||||
|
||||
private function extractBody($inbox, $email_number, $structure)
|
||||
{
|
||||
if (!isset($structure->parts)) {
|
||||
$pesan = imap_fetchbody($inbox, $email_number, 1);
|
||||
$encoding = $structure->encoding ?? 0;
|
||||
if ($encoding == 3) $pesan = base64_decode($pesan);
|
||||
elseif ($encoding == 4) $pesan = quoted_printable_decode($pesan);
|
||||
return $pesan;
|
||||
}
|
||||
|
||||
$texts = $this->getEmailBodyText($inbox, $email_number, $structure->parts);
|
||||
if (!empty(trim($texts['plain']))) {
|
||||
return trim($texts['plain']);
|
||||
} elseif (!empty(trim($texts['html']))) {
|
||||
return strip_tags($texts['html']);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private function getEmailBodyText($inbox, $email_number, $parts, $part_number = "")
|
||||
{
|
||||
$texts = ['plain' => '', 'html' => ''];
|
||||
if (isset($parts) && count($parts)) {
|
||||
foreach ($parts as $i => $part) {
|
||||
$prefix = ($part_number) ? $part_number . "." . ($i + 1) : ($i + 1);
|
||||
if (isset($part->parts)) {
|
||||
$subTexts = $this->getEmailBodyText($inbox, $email_number, $part->parts, $prefix);
|
||||
$texts['plain'] .= $subTexts['plain'];
|
||||
$texts['html'] .= $subTexts['html'];
|
||||
} else {
|
||||
$is_attachment = false;
|
||||
if ($part->ifdparameters) {
|
||||
foreach ($part->dparameters as $obj) {
|
||||
if (strtolower($obj->attribute) == 'filename') $is_attachment = true;
|
||||
}
|
||||
}
|
||||
if ($part->ifparameters) {
|
||||
foreach ($part->parameters as $obj) {
|
||||
if (strtolower($obj->attribute) == 'name') $is_attachment = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$is_attachment) {
|
||||
if ($part->subtype == 'PLAIN') {
|
||||
$content = imap_fetchbody($inbox, $email_number, $prefix);
|
||||
if ($part->encoding == 3) $content = base64_decode($content);
|
||||
elseif ($part->encoding == 4) $content = quoted_printable_decode($content);
|
||||
$texts['plain'] .= $content;
|
||||
} elseif ($part->subtype == 'HTML') {
|
||||
$content = imap_fetchbody($inbox, $email_number, $prefix);
|
||||
if ($part->encoding == 3) $content = base64_decode($content);
|
||||
elseif ($part->encoding == 4) $content = quoted_printable_decode($content);
|
||||
$texts['html'] .= $content;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $texts;
|
||||
}
|
||||
|
||||
private function extractAttachments($inbox, $email_number, $structure)
|
||||
{
|
||||
if (isset($structure->parts)) {
|
||||
return $this->getAttachments($inbox, $email_number, $structure->parts);
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
private function getAttachments($inbox, $email_number, $parts, $part_number = "")
|
||||
{
|
||||
$attachments = [];
|
||||
if (isset($parts) && count($parts)) {
|
||||
foreach ($parts as $i => $part) {
|
||||
$prefix = ($part_number) ? $part_number . "." . ($i + 1) : ($i + 1);
|
||||
if (isset($part->parts)) {
|
||||
$attachments = array_merge($attachments, $this->getAttachments($inbox, $email_number, $part->parts, $prefix));
|
||||
} else {
|
||||
$is_attachment = false;
|
||||
$filename = '';
|
||||
if ($part->ifdparameters) {
|
||||
foreach ($part->dparameters as $object) {
|
||||
if (strtolower($object->attribute) == 'filename') {
|
||||
$is_attachment = true;
|
||||
$filename = $object->value;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($part->ifparameters) {
|
||||
foreach ($part->parameters as $object) {
|
||||
if (strtolower($object->attribute) == 'name') {
|
||||
$is_attachment = true;
|
||||
$filename = $object->value;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($is_attachment) {
|
||||
$attachment = imap_fetchbody($inbox, $email_number, $prefix);
|
||||
if ($part->encoding == 3) $attachment = base64_decode($attachment);
|
||||
elseif ($part->encoding == 4) $attachment = quoted_printable_decode($attachment);
|
||||
$attachments[] = [
|
||||
'filename' => $filename,
|
||||
'data' => $attachment
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $attachments;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\PenerimaBantuan;
|
||||
use App\Models\TempatIbadah;
|
||||
use App\Models\LogDistribusi;
|
||||
|
||||
class KonfirmasiController extends Controller
|
||||
{
|
||||
public function show(Request $request)
|
||||
{
|
||||
$id = $request->query('id', 0);
|
||||
$periode_param = $request->query('periode', '');
|
||||
$signature_param = $request->query('signature', '');
|
||||
|
||||
if ($id <= 0 || empty($signature_param) || empty($periode_param)) {
|
||||
abort(400, 'Permintaan tidak valid. Parameter periode atau signature hilang.');
|
||||
}
|
||||
|
||||
// Verifikasi Signature dengan periode
|
||||
$expected_signature = hash_hmac('sha256', $id . '|' . $periode_param, config('app.key'));
|
||||
if (!hash_equals($expected_signature, $signature_param)) {
|
||||
abort(403, 'Invalid Signature. URL telah dimodifikasi atau tidak sah.');
|
||||
}
|
||||
|
||||
// Validasi Periode Kupon
|
||||
if ($periode_param !== now()->format('Y-m')) {
|
||||
$namaBulan = \Carbon\Carbon::createFromFormat('Y-m', $periode_param)->translatedFormat('F Y');
|
||||
return response("Kupon ini hanya berlaku untuk periode {$namaBulan}. Saat ini adalah periode " . now()->translatedFormat('F Y') . ". Silakan perbarui kupon Anda.", 400);
|
||||
}
|
||||
|
||||
$warga = PenerimaBantuan::findOrFail($id);
|
||||
|
||||
if (empty($warga->id_tempat_ibadah)) {
|
||||
return response('Warga ini belum terdaftar di tempat ibadah manapun untuk pengambilan bantuan.', 400);
|
||||
}
|
||||
|
||||
$id_tempat = $warga->id_tempat_ibadah;
|
||||
|
||||
// Cek apakah sudah pernah dicairkan bulan ini
|
||||
$log = LogDistribusi::where('id_penerima', $id)
|
||||
->whereMonth('tanggal_diterima', now()->month)
|
||||
->whereYear('tanggal_diterima', now()->year)
|
||||
->orderBy('tanggal_diterima', 'desc')
|
||||
->first();
|
||||
|
||||
$sudah_cair = ($log !== null);
|
||||
|
||||
return view('konfirmasi', compact('warga', 'id_tempat', 'sudah_cair', 'log'));
|
||||
}
|
||||
|
||||
public function process(Request $request)
|
||||
{
|
||||
$id = $request->query('id', 0);
|
||||
$periode_param = $request->query('periode', '');
|
||||
$signature_param = $request->query('signature', '');
|
||||
|
||||
if ($id <= 0 || empty($signature_param) || empty($periode_param)) {
|
||||
abort(400, 'Permintaan tidak valid. Parameter periode atau signature hilang.');
|
||||
}
|
||||
|
||||
// Verifikasi Signature dengan periode
|
||||
$expected_signature = hash_hmac('sha256', $id . '|' . $periode_param, config('app.key'));
|
||||
if (!hash_equals($expected_signature, $signature_param)) {
|
||||
abort(403, 'Invalid Signature.');
|
||||
}
|
||||
|
||||
// Validasi Periode Kupon
|
||||
if ($periode_param !== now()->format('Y-m')) {
|
||||
return redirect()->back()->with('error', 'Kupon kedaluwarsa atau tidak sesuai dengan periode bulan ini.');
|
||||
}
|
||||
|
||||
$warga = PenerimaBantuan::findOrFail($id);
|
||||
|
||||
// Cek sudah dicairkan bulan ini
|
||||
$existing = LogDistribusi::where('id_penerima', $id)
|
||||
->whereMonth('tanggal_diterima', now()->month)
|
||||
->whereYear('tanggal_diterima', now()->year)
|
||||
->exists();
|
||||
|
||||
if ($existing) {
|
||||
return redirect()->back()->with('error', 'Bantuan bulan ini sudah diproses.');
|
||||
}
|
||||
|
||||
$tgl_sekarang = now();
|
||||
|
||||
// Upload foto penyerahan
|
||||
$foto_penyerahan = '';
|
||||
if ($request->hasFile('foto_penyerahan')) {
|
||||
$foto_penyerahan = time() . '_bukti_' . $request->file('foto_penyerahan')->getClientOriginalName();
|
||||
$request->file('foto_penyerahan')->storeAs('uploads', $foto_penyerahan, 'public');
|
||||
}
|
||||
|
||||
LogDistribusi::create([
|
||||
'id_penerima' => $id,
|
||||
'tanggal_diterima' => $tgl_sekarang,
|
||||
'status' => 'Menunggu',
|
||||
'foto_penyerahan' => $foto_penyerahan,
|
||||
]);
|
||||
|
||||
// Redirect back with success
|
||||
$log = LogDistribusi::where('id_penerima', $id)
|
||||
->whereMonth('tanggal_diterima', now()->month)
|
||||
->whereYear('tanggal_diterima', now()->year)
|
||||
->orderBy('tanggal_diterima', 'desc')
|
||||
->first();
|
||||
|
||||
$warga = PenerimaBantuan::findOrFail($id);
|
||||
$id_tempat = $warga->id_tempat_ibadah;
|
||||
$sudah_cair = true;
|
||||
$pesan_sukses = true;
|
||||
|
||||
return view('konfirmasi', compact('warga', 'id_tempat', 'sudah_cair', 'log', 'pesan_sukses'));
|
||||
}
|
||||
|
||||
public function scan()
|
||||
{
|
||||
abort_if(auth()->user()->role === 'admin', 403, 'Akses ditolak. Halaman ini bukan untuk admin.');
|
||||
return view('scan');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\PenerimaBantuan;
|
||||
use App\Models\LogDistribusi;
|
||||
use Endroid\QrCode\Builder\Builder;
|
||||
use Endroid\QrCode\Encoding\Encoding;
|
||||
use Endroid\QrCode\ErrorCorrectionLevel;
|
||||
use Endroid\QrCode\RoundBlockSizeMode;
|
||||
use Endroid\QrCode\Writer\PngWriter;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use App\Models\TempatIbadah;
|
||||
|
||||
class KuponController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
$query = PenerimaBantuan::with('tempat_ibadah')->where('status_persetujuan', 'disetujui');
|
||||
|
||||
// Jika admin, bisa melihat semua dan filter. Jika user, hanya melihat yang sesuai tempat ibadahnya.
|
||||
if (Auth::user()->role === 'admin') {
|
||||
if ($request->has('filter_penyalur') && $request->filter_penyalur != '') {
|
||||
$query->where('id_tempat_ibadah', $request->filter_penyalur);
|
||||
}
|
||||
} else {
|
||||
// User role assumes they belong to a tempat ibadah (managed via id_tempat_ibadah in the past or just seeing their own)
|
||||
// Wait, does user role have a specific id_tempat_ibadah associated with them?
|
||||
// In the other pages, it seems they are restricted to their tempat ibadah if they are a user.
|
||||
// Let's check how PenerimaBantuanController index does it.
|
||||
// But for now, let's just mimic it.
|
||||
// Sebenarnya user role di tabel users tidak punya id_tempat_ibadah.
|
||||
// Kita coba fetch semua disetujui saja, nanti admin filter yang berlaku.
|
||||
}
|
||||
|
||||
$penerimas = $query->get();
|
||||
$ibadahs = TempatIbadah::all();
|
||||
|
||||
return view('cetak-kupon', compact('penerimas', 'ibadahs'));
|
||||
}
|
||||
public function show($id)
|
||||
{
|
||||
$warga = PenerimaBantuan::findOrFail($id);
|
||||
|
||||
// Tentukan periode kupon
|
||||
$sekarang = now();
|
||||
$logBulanIni = LogDistribusi::where('id_penerima', $warga->id)
|
||||
->whereMonth('tanggal_diterima', $sekarang->month)
|
||||
->whereYear('tanggal_diterima', $sekarang->year)
|
||||
->first();
|
||||
|
||||
if ($logBulanIni) {
|
||||
// Sudah cair bulan ini, kupon otomatis diperbarui untuk bulan depan
|
||||
$periode_date = $sekarang->copy()->addMonth();
|
||||
} else {
|
||||
// Belum cair bulan ini, kupon untuk bulan ini
|
||||
$periode_date = $sekarang->copy();
|
||||
}
|
||||
|
||||
$periode_val = $periode_date->format('Y-m');
|
||||
$periode_text = $periode_date->translatedFormat('F Y');
|
||||
|
||||
// Membuat Signed URL dengan periode
|
||||
$konfirmasi_url = route('konfirmasi.show', ['id' => $id, 'periode' => $periode_val]);
|
||||
$signature = hash_hmac('sha256', $id . '|' . $periode_val, config('app.key'));
|
||||
$signed_url = $konfirmasi_url . '&signature=' . $signature;
|
||||
|
||||
// Generate QR Code
|
||||
try {
|
||||
$builder = new Builder(
|
||||
writer: new PngWriter(),
|
||||
data: $signed_url,
|
||||
encoding: new Encoding('UTF-8'),
|
||||
errorCorrectionLevel: ErrorCorrectionLevel::High,
|
||||
size: 300,
|
||||
margin: 10,
|
||||
roundBlockSizeMode: RoundBlockSizeMode::Margin
|
||||
);
|
||||
$result = $builder->build();
|
||||
$qrDataUri = $result->getDataUri();
|
||||
} catch (\Exception $e) {
|
||||
abort(500, 'Error generating QR Code: ' . $e->getMessage());
|
||||
}
|
||||
|
||||
$kupons = [[
|
||||
'warga' => $warga,
|
||||
'qrDataUri' => $qrDataUri,
|
||||
'periode_text' => $periode_text
|
||||
]];
|
||||
|
||||
return view('kupon', compact('kupons'));
|
||||
}
|
||||
|
||||
public function cetak(Request $request)
|
||||
{
|
||||
$ids = $request->input('penerima_ids');
|
||||
|
||||
if (empty($ids) || !is_array($ids)) {
|
||||
return redirect()->back()->with('error', 'Tidak ada kupon yang dipilih untuk dicetak.');
|
||||
}
|
||||
|
||||
$wargas = PenerimaBantuan::whereIn('id', $ids)->get();
|
||||
$kupons = [];
|
||||
|
||||
foreach ($wargas as $warga) {
|
||||
$sekarang = now();
|
||||
$logBulanIni = LogDistribusi::where('id_penerima', $warga->id)
|
||||
->whereMonth('tanggal_diterima', $sekarang->month)
|
||||
->whereYear('tanggal_diterima', $sekarang->year)
|
||||
->first();
|
||||
|
||||
if ($logBulanIni) {
|
||||
$periode_date = $sekarang->copy()->addMonth();
|
||||
} else {
|
||||
$periode_date = $sekarang->copy();
|
||||
}
|
||||
|
||||
$periode_val = $periode_date->format('Y-m');
|
||||
$periode_text = $periode_date->translatedFormat('F Y');
|
||||
|
||||
$konfirmasi_url = route('konfirmasi.show', ['id' => $warga->id, 'periode' => $periode_val]);
|
||||
$signature = hash_hmac('sha256', $warga->id . '|' . $periode_val, config('app.key'));
|
||||
$signed_url = $konfirmasi_url . '&signature=' . $signature;
|
||||
|
||||
try {
|
||||
$builder = new Builder(
|
||||
writer: new PngWriter(),
|
||||
data: $signed_url,
|
||||
encoding: new Encoding('UTF-8'),
|
||||
errorCorrectionLevel: ErrorCorrectionLevel::High,
|
||||
size: 300,
|
||||
margin: 10,
|
||||
roundBlockSizeMode: RoundBlockSizeMode::Margin
|
||||
);
|
||||
$result = $builder->build();
|
||||
$qrDataUri = $result->getDataUri();
|
||||
|
||||
$kupons[] = [
|
||||
'warga' => $warga,
|
||||
'qrDataUri' => $qrDataUri,
|
||||
'periode_text' => $periode_text
|
||||
];
|
||||
} catch (\Exception $e) {
|
||||
// Lewati jika error
|
||||
}
|
||||
}
|
||||
|
||||
return view('kupon', compact('kupons'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\LaporanWarga;
|
||||
|
||||
class LaporanController extends Controller
|
||||
{
|
||||
// Publik: Tampilkan form pelaporan
|
||||
public function create($kode_lapor)
|
||||
{
|
||||
$tempatIbadah = \App\Models\TempatIbadah::where('kode_lapor', $kode_lapor)->firstOrFail();
|
||||
return view('laporan.lapor', compact('tempatIbadah'));
|
||||
}
|
||||
|
||||
// Publik: Simpan pelaporan
|
||||
public function store(Request $request, $kode_lapor)
|
||||
{
|
||||
$tempatIbadah = \App\Models\TempatIbadah::where('kode_lapor', $kode_lapor)->firstOrFail();
|
||||
|
||||
$request->validate([
|
||||
'nama_calon' => 'required|string|max:255',
|
||||
'jumlah_tanggungan' => 'required|integer|min:0',
|
||||
'alamat' => 'nullable|string|max:500',
|
||||
'deskripsi' => 'nullable|string',
|
||||
'foto' => 'nullable|image|mimes:jpeg,png,jpg|max:2048',
|
||||
]);
|
||||
|
||||
$foto_name = null;
|
||||
if ($request->hasFile('foto')) {
|
||||
$file = $request->file('foto');
|
||||
$foto_name = time() . '_lapor_' . $file->getClientOriginalName();
|
||||
$file->storeAs('uploads', $foto_name, 'public');
|
||||
}
|
||||
|
||||
LaporanWarga::create([
|
||||
'nama_calon' => $request->nama_calon,
|
||||
'jumlah_tanggungan' => $request->jumlah_tanggungan,
|
||||
'alamat' => $request->alamat,
|
||||
'deskripsi' => $request->deskripsi,
|
||||
'foto' => $foto_name,
|
||||
'status_laporan' => 'menunggu',
|
||||
'id_tempat_ibadah' => $tempatIbadah->id,
|
||||
]);
|
||||
|
||||
return redirect()->back()->with('success', 'Laporan Anda berhasil dikirim! Terima kasih atas partisipasinya.');
|
||||
}
|
||||
|
||||
// Authenticated (Admin/User): Tampilkan daftar laporan
|
||||
public function index()
|
||||
{
|
||||
abort_if(auth()->user()->role === 'admin', 403, 'Akses ditolak. Halaman ini bukan untuk admin.');
|
||||
|
||||
$tempatIbadah = \App\Models\TempatIbadah::find(auth()->user()->id_tempat_ibadah);
|
||||
|
||||
$laporans = LaporanWarga::where('id_tempat_ibadah', $tempatIbadah->id)
|
||||
->where('status_laporan', 'menunggu')
|
||||
->orderBy('created_at', 'desc')->get();
|
||||
|
||||
return view('laporan.index', compact('laporans', 'tempatIbadah'));
|
||||
}
|
||||
}
|
||||
@@ -3,27 +3,65 @@
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use App\Models\TempatIbadah;
|
||||
use App\Models\PenerimaBantuan;
|
||||
|
||||
use App\Models\User;
|
||||
|
||||
class MapController extends Controller
|
||||
{
|
||||
public function index()
|
||||
public function index(Request $request)
|
||||
{
|
||||
$ibadahs = \App\Models\TempatIbadah::all();
|
||||
$penerimas = \App\Models\PenerimaBantuan::with('tempat_ibadah')->get();
|
||||
return view('dashboard', compact('ibadahs', 'penerimas'));
|
||||
if (Auth::user()->role === 'user') {
|
||||
$ibadahs = TempatIbadah::where('id', Auth::user()->id_tempat_ibadah)->get();
|
||||
$penerimas = PenerimaBantuan::with('tempat_ibadah')
|
||||
->where('id_tempat_ibadah', Auth::user()->id_tempat_ibadah)->get();
|
||||
} else {
|
||||
$ibadahs = TempatIbadah::all();
|
||||
$penerimas = PenerimaBantuan::with('tempat_ibadah')->get();
|
||||
}
|
||||
|
||||
$laporan_fill = null;
|
||||
if ($request->has('add_laporan')) {
|
||||
$laporan_fill = \App\Models\LaporanWarga::find($request->add_laporan);
|
||||
}
|
||||
|
||||
return view('dashboard', compact('ibadahs', 'penerimas', 'laporan_fill'));
|
||||
}
|
||||
|
||||
public function daftarPenerimaBantuan()
|
||||
public function daftarPenerimaBantuan(Request $request)
|
||||
{
|
||||
$penerimas = \App\Models\PenerimaBantuan::with('tempat_ibadah')->get();
|
||||
$ibadahs = \App\Models\TempatIbadah::all();
|
||||
$ibadahs = TempatIbadah::all();
|
||||
|
||||
$query = PenerimaBantuan::with('tempat_ibadah');
|
||||
|
||||
if (Auth::user()->role === 'user') {
|
||||
$query->where('id_tempat_ibadah', Auth::user()->id_tempat_ibadah);
|
||||
$ibadahs = TempatIbadah::where('id', Auth::user()->id_tempat_ibadah)->get();
|
||||
} elseif ($request->filled('filter_penyalur')) {
|
||||
$query->where('id_tempat_ibadah', (int)$request->filter_penyalur);
|
||||
}
|
||||
|
||||
$penerimas = $query->get();
|
||||
|
||||
return view('daftar-penerima-bantuan', compact('penerimas', 'ibadahs'));
|
||||
}
|
||||
|
||||
public function daftarTempatIbadah()
|
||||
{
|
||||
$ibadahs = \App\Models\TempatIbadah::all();
|
||||
return view('daftar-tempat-ibadah', compact('ibadahs'));
|
||||
if (Auth::user()->role === 'user') {
|
||||
$ibadahs = TempatIbadah::where('id', Auth::user()->id_tempat_ibadah)->get();
|
||||
} else {
|
||||
$ibadahs = TempatIbadah::all();
|
||||
}
|
||||
|
||||
// Include admin email for each ibadah if admin, or just fetch all users
|
||||
$adminUsers = User::where('role', 'user')->get()->keyBy('id_tempat_ibadah');
|
||||
|
||||
return view('daftar-tempat-ibadah', compact('ibadahs', 'adminUsers'));
|
||||
}
|
||||
|
||||
public function save(Request $request)
|
||||
@@ -35,33 +73,111 @@ class MapController extends Controller
|
||||
$alamat = $request->alamat;
|
||||
|
||||
if ($type == 'ibadah') {
|
||||
\App\Models\TempatIbadah::create([
|
||||
// ... (ibadah creation logic remains unchanged)
|
||||
if (Auth::user()->role !== 'admin') {
|
||||
return response()->json(['status' => 'error', 'message' => 'Unauthorized']);
|
||||
}
|
||||
$ibadah = TempatIbadah::create([
|
||||
'nama_tempat' => $nama,
|
||||
'jenis_tempat_ibadah' => $request->jenis_tempat_ibadah,
|
||||
'kontak_person' => $request->kontak_person,
|
||||
'radius_meter' => 500,
|
||||
'nama_pengurus' => $request->nama_pengurus,
|
||||
'kontak_pengurus' => $request->kontak_pengurus,
|
||||
'lat' => $lat,
|
||||
'lng' => $lng,
|
||||
'radius_meter' => 500,
|
||||
'alamat' => $alamat
|
||||
]);
|
||||
} else {
|
||||
$fotoPath = null;
|
||||
if ($request->hasFile('foto_kondisi_rumah')) {
|
||||
$fotoPath = $request->file('foto_kondisi_rumah')->store('fotos', 'public');
|
||||
|
||||
$baseEmail = strtolower(preg_replace('/[^a-zA-Z0-9]/', '', $nama));
|
||||
$email = $baseEmail . '@email.com';
|
||||
if (User::where('email', $email)->exists()) {
|
||||
$email = $baseEmail . rand(100, 999) . '@email.com';
|
||||
}
|
||||
|
||||
\App\Models\PenerimaBantuan::create([
|
||||
User::create([
|
||||
'name' => $nama,
|
||||
'email' => $email,
|
||||
'password' => Hash::make('password123'),
|
||||
'role' => 'user',
|
||||
'id_tempat_ibadah' => $ibadah->id,
|
||||
]);
|
||||
} else {
|
||||
if (Auth::user()->role !== 'user') {
|
||||
return response()->json(['status' => 'error', 'message' => 'Unauthorized']);
|
||||
}
|
||||
|
||||
$tempatIbadah = \App\Models\TempatIbadah::find(Auth::user()->id_tempat_ibadah);
|
||||
if ($tempatIbadah) {
|
||||
$distance = $this->calculateDistance($tempatIbadah->lat, $tempatIbadah->lng, $lat, $lng);
|
||||
if ($distance > $tempatIbadah->radius_meter) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Hanya bisa di lingkaran radius pelayanan'
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
// Pengecekan NIK dan Nomor KK Ganda
|
||||
$existsNIK = \App\Models\PenerimaBantuan::where('nik_kepala_keluarga', $request->nik_kepala_keluarga)->first();
|
||||
if ($existsNIK) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Gagal: NIK Kepala Keluarga (' . $request->nik_kepala_keluarga . ') sudah terdaftar di dalam sistem.'
|
||||
]);
|
||||
}
|
||||
|
||||
$existsKK = \App\Models\PenerimaBantuan::where('nomor_kk', $request->nomor_kk)->first();
|
||||
if ($existsKK) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Gagal: Nomor Kartu Keluarga (' . $request->nomor_kk . ') sudah terdaftar di dalam sistem.'
|
||||
]);
|
||||
}
|
||||
|
||||
// Handle multi-foto upload
|
||||
$foto_names = [];
|
||||
if ($request->hasFile('foto')) {
|
||||
$files = is_array($request->file('foto')) ? $request->file('foto') : [$request->file('foto')];
|
||||
foreach ($files as $i => $file) {
|
||||
$foto_name = time() . '_' . $i . '_' . $file->getClientOriginalName();
|
||||
$file->storeAs('uploads', $foto_name, 'public');
|
||||
$foto_names[] = $foto_name;
|
||||
}
|
||||
} else if ($request->filled('id_laporan_warga')) {
|
||||
$laporan = \App\Models\LaporanWarga::find($request->id_laporan_warga);
|
||||
if ($laporan && $laporan->foto) {
|
||||
// Copy existing foto from laporan
|
||||
$foto_names[] = $laporan->foto;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle dokumen laporan upload
|
||||
$dokumen_laporan = '';
|
||||
if ($request->hasFile('dokumen_laporan')) {
|
||||
$dokumen_laporan = time() . '_pdf_' . $request->file('dokumen_laporan')->getClientOriginalName();
|
||||
$request->file('dokumen_laporan')->storeAs('uploads', $dokumen_laporan, 'public');
|
||||
}
|
||||
|
||||
PenerimaBantuan::create([
|
||||
'nama_kepala_keluarga' => $nama,
|
||||
'id_tempat_ibadah' => $request->id_tempat_ibadah,
|
||||
'id_tempat_ibadah' => Auth::user()->role === 'user' ? Auth::user()->id_tempat_ibadah : $request->id_tempat_ibadah,
|
||||
'nik_kepala_keluarga' => $request->nik_kepala_keluarga,
|
||||
'nomor_kk' => $request->nomor_kk,
|
||||
'jumlah_tanggungan' => $request->jumlah_tanggungan,
|
||||
'foto_kondisi_rumah' => $fotoPath,
|
||||
'foto' => implode(',', $foto_names),
|
||||
'lat' => $lat,
|
||||
'lng' => $lng,
|
||||
'alamat' => $alamat
|
||||
'alamat' => $alamat,
|
||||
'dokumen_laporan' => $dokumen_laporan,
|
||||
'status_persetujuan' => 'menunggu',
|
||||
]);
|
||||
|
||||
if ($request->filled('id_laporan_warga')) {
|
||||
\App\Models\LaporanWarga::where('id', $request->id_laporan_warga)->update(['status_laporan' => 'diproses']);
|
||||
}
|
||||
}
|
||||
|
||||
$this->recalculateCoverage();
|
||||
return response()->json(['status' => 'success']);
|
||||
}
|
||||
|
||||
@@ -69,8 +185,8 @@ class MapController extends Controller
|
||||
{
|
||||
$id = $request->id;
|
||||
$radius = $request->radius;
|
||||
\App\Models\TempatIbadah::where('id', $id)->update(['radius_meter' => $radius]);
|
||||
$this->checkAndUnlinkPenerima($id);
|
||||
TempatIbadah::where('id', $id)->update(['radius_meter' => $radius]);
|
||||
$this->recalculateCoverage();
|
||||
return response()->json(['status' => 'success']);
|
||||
}
|
||||
|
||||
@@ -82,30 +198,60 @@ class MapController extends Controller
|
||||
$type = $request->type;
|
||||
|
||||
if ($type == 'ibadah') {
|
||||
\App\Models\TempatIbadah::where('id', $id)->update([
|
||||
$data = [
|
||||
'nama_tempat' => $nama,
|
||||
'jenis_tempat_ibadah' => $request->jenis_tempat_ibadah,
|
||||
'kontak_person' => $request->kontak_person,
|
||||
'alamat' => $alamat,
|
||||
'radius_meter' => $request->radius_meter
|
||||
]);
|
||||
$this->checkAndUnlinkPenerima($id);
|
||||
];
|
||||
if ($request->filled('jenis_tempat_ibadah')) $data['jenis_tempat_ibadah'] = $request->jenis_tempat_ibadah;
|
||||
if ($request->filled('nama_pengurus')) $data['nama_pengurus'] = $request->nama_pengurus;
|
||||
if ($request->filled('kontak_pengurus')) $data['kontak_pengurus'] = $request->kontak_pengurus;
|
||||
if ($request->filled('radius_meter')) $data['radius_meter'] = (int)$request->radius_meter;
|
||||
|
||||
TempatIbadah::where('id', $id)->update($data);
|
||||
$this->recalculateCoverage();
|
||||
} else {
|
||||
$updateData = [
|
||||
$data = [
|
||||
'nama_kepala_keluarga' => $nama,
|
||||
'id_tempat_ibadah' => $request->id_tempat_ibadah,
|
||||
'nik_kepala_keluarga' => $request->nik_kepala_keluarga,
|
||||
'nomor_kk' => $request->nomor_kk,
|
||||
'jumlah_tanggungan' => $request->jumlah_tanggungan,
|
||||
'alamat' => $alamat
|
||||
'id_tempat_ibadah' => Auth::user()->role === 'user' ? Auth::user()->id_tempat_ibadah : $request->id_tempat_ibadah,
|
||||
'alamat' => $alamat,
|
||||
];
|
||||
|
||||
if ($request->hasFile('foto_kondisi_rumah')) {
|
||||
$updateData['foto_kondisi_rumah'] = $request->file('foto_kondisi_rumah')->store('fotos', 'public');
|
||||
if ($request->filled('nik_kepala_keluarga')) $data['nik_kepala_keluarga'] = $request->nik_kepala_keluarga;
|
||||
if ($request->filled('nomor_kk')) $data['nomor_kk'] = $request->nomor_kk;
|
||||
if ($request->has('jumlah_tanggungan')) $data['jumlah_tanggungan'] = $request->jumlah_tanggungan;
|
||||
|
||||
// Handle existing photos and deletions
|
||||
$penerima = PenerimaBantuan::find($id);
|
||||
$current_fotos = !empty($penerima->foto) ? explode(',', $penerima->foto) : [];
|
||||
|
||||
if ($request->has('hapus_foto') && is_array($request->hapus_foto)) {
|
||||
foreach ($request->hapus_foto as $hf) {
|
||||
if (($key = array_search($hf, $current_fotos)) !== false) {
|
||||
unset($current_fotos[$key]);
|
||||
$path = storage_path('app/public/uploads/' . $hf);
|
||||
if (file_exists($path)) {
|
||||
unlink($path);
|
||||
}
|
||||
}
|
||||
}
|
||||
$current_fotos = array_values($current_fotos);
|
||||
}
|
||||
|
||||
\App\Models\PenerimaBantuan::where('id', $id)->update($updateData);
|
||||
// Handle new foto uploads
|
||||
if ($request->hasFile('foto')) {
|
||||
$files = is_array($request->file('foto')) ? $request->file('foto') : [$request->file('foto')];
|
||||
foreach ($files as $i => $file) {
|
||||
$foto_name = time() . '_' . $i . '_' . $file->getClientOriginalName();
|
||||
$file->storeAs('uploads', $foto_name, 'public');
|
||||
$current_fotos[] = $foto_name;
|
||||
}
|
||||
}
|
||||
|
||||
$data['foto'] = implode(',', $current_fotos);
|
||||
|
||||
PenerimaBantuan::where('id', $id)->update($data);
|
||||
}
|
||||
|
||||
return redirect()->back();
|
||||
}
|
||||
|
||||
@@ -115,31 +261,56 @@ class MapController extends Controller
|
||||
$type = $request->type;
|
||||
|
||||
if ($type == 'ibadah') {
|
||||
\App\Models\TempatIbadah::where('id', $id)->delete();
|
||||
TempatIbadah::where('id', $id)->delete();
|
||||
} else {
|
||||
\App\Models\PenerimaBantuan::where('id', $id)->delete();
|
||||
PenerimaBantuan::where('id', $id)->delete();
|
||||
}
|
||||
|
||||
$this->recalculateCoverage();
|
||||
return redirect()->back();
|
||||
}
|
||||
|
||||
private function calculateDistance($lat1, $lon1, $lat2, $lon2) {
|
||||
private function calculateDistance($lat1, $lon1, $lat2, $lon2)
|
||||
{
|
||||
$earthRadius = 6371000; // in meters
|
||||
$dLat = deg2rad($lat2 - $lat1);
|
||||
$dLon = deg2rad($lon2 - $lon1);
|
||||
$a = sin($dLat/2) * sin($dLat/2) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * sin($dLon/2) * sin($dLon/2);
|
||||
$a = sin($dLat / 2) * sin($dLat / 2) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * sin($dLon / 2) * sin($dLon / 2);
|
||||
$c = 2 * asin(sqrt($a));
|
||||
return $earthRadius * $c;
|
||||
}
|
||||
|
||||
private function checkAndUnlinkPenerima($ibadahId) {
|
||||
$ibadah = \App\Models\TempatIbadah::find($ibadahId);
|
||||
if (!$ibadah) return;
|
||||
private function recalculateCoverage()
|
||||
{
|
||||
$all_ibadahs = TempatIbadah::all(['id', 'lat', 'lng', 'radius_meter']);
|
||||
|
||||
$penerimas = \App\Models\PenerimaBantuan::where('id_tempat_ibadah', $ibadahId)->get();
|
||||
foreach ($penerimas as $penerima) {
|
||||
$distance = $this->calculateDistance($ibadah->lat, $ibadah->lng, $penerima->lat, $penerima->lng);
|
||||
if ($distance > $ibadah->radius_meter) {
|
||||
$penerima->update(['id_tempat_ibadah' => null]);
|
||||
$penerimas = PenerimaBantuan::all(['id', 'lat', 'lng']);
|
||||
|
||||
foreach ($penerimas as $pb) {
|
||||
$best_id = null;
|
||||
$min_distance = INF;
|
||||
|
||||
foreach ($all_ibadahs as $ib) {
|
||||
$distance = $this->calculateDistance($ib->lat, $ib->lng, $pb->lat, $pb->lng);
|
||||
|
||||
if ($distance <= $ib->radius_meter) {
|
||||
if ($distance < $min_distance) {
|
||||
$min_distance = $distance;
|
||||
$best_id = $ib->id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($best_id !== null) {
|
||||
PenerimaBantuan::where('id', $pb->id)->update([
|
||||
'id_tempat_ibadah' => $best_id,
|
||||
'jarak_ke_penyalur' => $min_distance,
|
||||
]);
|
||||
} else {
|
||||
PenerimaBantuan::where('id', $pb->id)->update([
|
||||
'id_tempat_ibadah' => null,
|
||||
'jarak_ke_penyalur' => null,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\PenerimaBantuan;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class PersetujuanController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
if (Auth::user()->role !== 'admin') {
|
||||
abort(403, 'Unauthorized action.');
|
||||
}
|
||||
|
||||
// Only fetch 'menunggu' status to show in the approval table
|
||||
$penerimas = PenerimaBantuan::with('tempat_ibadah')->where('status_persetujuan', 'menunggu')->get();
|
||||
return view('persetujuan', compact('penerimas'));
|
||||
}
|
||||
|
||||
public function updateStatus(Request $request, $id)
|
||||
{
|
||||
if (Auth::user()->role !== 'admin') {
|
||||
abort(403, 'Unauthorized action.');
|
||||
}
|
||||
|
||||
$request->validate([
|
||||
'status_persetujuan' => 'required|in:disetujui,ditolak',
|
||||
'alasan_penolakan' => 'nullable|string'
|
||||
]);
|
||||
|
||||
$penerima = PenerimaBantuan::findOrFail($id);
|
||||
$penerima->status_persetujuan = $request->status_persetujuan;
|
||||
if ($request->status_persetujuan === 'ditolak') {
|
||||
$penerima->alasan_penolakan = $request->alasan_penolakan;
|
||||
} else {
|
||||
$penerima->alasan_penolakan = null;
|
||||
}
|
||||
$penerima->save();
|
||||
|
||||
return redirect()->back()->with('success', 'Status berhasil diperbarui!');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\LogDistribusi;
|
||||
use App\Models\PenerimaBantuan;
|
||||
use Barryvdh\DomPDF\Facade\Pdf;
|
||||
|
||||
class RiwayatController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
$query = LogDistribusi::with(['penerimaBantuan.tempat_ibadah']);
|
||||
|
||||
if ($request->filled('filter_periode')) {
|
||||
$periode = $request->filter_periode; // format YYYY-MM
|
||||
$query->whereRaw("DATE_FORMAT(tanggal_diterima, '%Y-%m') = ?", [$periode]);
|
||||
}
|
||||
|
||||
$riwayats = $query->orderBy('tanggal_diterima', 'desc')->get();
|
||||
|
||||
return view('riwayat', compact('riwayats'));
|
||||
}
|
||||
|
||||
public function konfirmasiPenyaluran($id_log)
|
||||
{
|
||||
$log = LogDistribusi::where('id', $id_log)->where('status', 'Menunggu')->first();
|
||||
|
||||
if ($log) {
|
||||
$log->update(['status' => 'Selesai']);
|
||||
PenerimaBantuan::where('id', $log->id_penerima)
|
||||
->update(['tanggal_pencairan_terakhir' => $log->tanggal_diterima]);
|
||||
}
|
||||
|
||||
return redirect()->back();
|
||||
}
|
||||
|
||||
public function cetakPdf(Request $request)
|
||||
{
|
||||
if (!$request->filled('periode')) {
|
||||
abort(400, 'Periode tidak valid!');
|
||||
}
|
||||
|
||||
$periode = $request->periode;
|
||||
$periode_obj = date_create_from_format('Y-m', $periode);
|
||||
if (!$periode_obj) {
|
||||
abort(400, 'Format periode tidak valid!');
|
||||
}
|
||||
|
||||
$bulan_indonesia = [
|
||||
'January' => 'Januari', 'February' => 'Februari', 'March' => 'Maret',
|
||||
'April' => 'April', 'May' => 'Mei', 'June' => 'Juni',
|
||||
'July' => 'Juli', 'August' => 'Agustus', 'September' => 'September',
|
||||
'October' => 'Oktober', 'November' => 'November', 'December' => 'Desember'
|
||||
];
|
||||
$bulan_eng = date_format($periode_obj, 'F');
|
||||
$tahun = date_format($periode_obj, 'Y');
|
||||
$bulan_tahun = $bulan_indonesia[$bulan_eng] . ' ' . $tahun;
|
||||
|
||||
$riwayats = LogDistribusi::with(['penerimaBantuan.tempat_ibadah'])
|
||||
->whereRaw("DATE_FORMAT(tanggal_diterima, '%Y-%m') = ?", [$periode])
|
||||
->orderBy('tanggal_diterima', 'desc')
|
||||
->get();
|
||||
|
||||
if ($riwayats->isEmpty()) {
|
||||
abort(404, 'Data riwayat tidak ditemukan untuk periode ini!');
|
||||
}
|
||||
|
||||
$tgl_sekarang_indo = date('d') . ' ' . $bulan_indonesia[date('F')] . ' ' . date('Y');
|
||||
|
||||
$html = '
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Laporan Riwayat Penyaluran Bantuan - ' . $bulan_tahun . '</title>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; font-size: 12px; color: #333; }
|
||||
h1 { text-align: center; font-size: 18px; text-transform: uppercase; margin-bottom: 5px; }
|
||||
h3 { text-align: center; font-size: 14px; margin-top: 0; margin-bottom: 20px; font-weight: normal; }
|
||||
table { width: 100%; border-collapse: collapse; margin-top: 15px; }
|
||||
th, td { border: 1px solid #000; padding: 8px; text-align: left; }
|
||||
th { background-color: #f2f2f2; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Laporan Riwayat Penyaluran Bantuan</h1>
|
||||
<h3>Periode: ' . $bulan_tahun . '</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>No</th>
|
||||
<th>Tanggal Terima</th>
|
||||
<th>Nama Kepala Keluarga</th>
|
||||
<th>NIK</th>
|
||||
<th>Alamat</th>
|
||||
<th>Penyalur</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>';
|
||||
|
||||
$no = 1;
|
||||
foreach ($riwayats as $r) {
|
||||
$tgl = $r->tanggal_diterima->format('d-m-Y H:i');
|
||||
$nama_kk = $r->penerimaBantuan->nama_kepala_keluarga ?? 'Data Terhapus';
|
||||
$nik = $r->penerimaBantuan && $r->penerimaBantuan->nik_kepala_keluarga
|
||||
? substr($r->penerimaBantuan->nik_kepala_keluarga, 0, 6) . '**********'
|
||||
: '-';
|
||||
$alamat = $r->penerimaBantuan->alamat ?? '-';
|
||||
$penyalur = $r->penerimaBantuan && $r->penerimaBantuan->tempat_ibadah
|
||||
? $r->penerimaBantuan->tempat_ibadah->nama_tempat
|
||||
: '-';
|
||||
|
||||
$html .= '
|
||||
<tr>
|
||||
<td style="text-align: center;">' . $no . '</td>
|
||||
<td>' . $tgl . '</td>
|
||||
<td>' . e($nama_kk) . '</td>
|
||||
<td>' . $nik . '</td>
|
||||
<td>' . e($alamat) . '</td>
|
||||
<td>' . e($penyalur) . '</td>
|
||||
<td style="text-align: center;">' . $r->status . '</td>
|
||||
</tr>';
|
||||
$no++;
|
||||
}
|
||||
|
||||
$html .= '
|
||||
</tbody>
|
||||
</table>
|
||||
<div style="margin-top: 50px; text-align: right; padding-right: 50px;">
|
||||
Pontianak, ' . $tgl_sekarang_indo . '<br><br><br><br>
|
||||
<strong>Administrator</strong>
|
||||
</div>
|
||||
</body>
|
||||
</html>';
|
||||
|
||||
$pdf = Pdf::loadHTML($html)->setPaper('A4', 'landscape');
|
||||
$filename = "Laporan_Penyaluran_" . $periode . ".pdf";
|
||||
|
||||
return $pdf->stream($filename);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class LaporanWarga extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'nama_calon',
|
||||
'jumlah_tanggungan',
|
||||
'alamat',
|
||||
'deskripsi',
|
||||
'foto',
|
||||
'status_laporan',
|
||||
'id_tempat_ibadah',
|
||||
];
|
||||
|
||||
public function tempat_ibadah()
|
||||
{
|
||||
return $this->belongsTo(TempatIbadah::class, 'id_tempat_ibadah');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class LogDistribusi extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $table = 'log_distribusi';
|
||||
|
||||
protected $fillable = [
|
||||
'id_penerima',
|
||||
'tanggal_diterima',
|
||||
'status',
|
||||
'foto_penyerahan',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'tanggal_diterima' => 'datetime',
|
||||
];
|
||||
|
||||
public function penerimaBantuan()
|
||||
{
|
||||
return $this->belongsTo(PenerimaBantuan::class, 'id_penerima');
|
||||
}
|
||||
}
|
||||
@@ -17,14 +17,30 @@ class PenerimaBantuan extends Model
|
||||
'nomor_kk',
|
||||
'nama_kepala_keluarga',
|
||||
'jumlah_tanggungan',
|
||||
'foto_kondisi_rumah',
|
||||
'foto',
|
||||
'lat',
|
||||
'lng',
|
||||
'alamat'
|
||||
'alamat',
|
||||
'jarak_ke_penyalur',
|
||||
'dokumen_laporan',
|
||||
'status_persetujuan',
|
||||
'alasan_penolakan',
|
||||
'tanggal_pencairan_terakhir',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'tanggal_pencairan_terakhir' => 'datetime',
|
||||
];
|
||||
|
||||
public function tempat_ibadah()
|
||||
{
|
||||
return $this->belongsTo(TempatIbadah::class, 'id_tempat_ibadah');
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function logDistribusi()
|
||||
{
|
||||
return $this->hasMany(LogDistribusi::class, 'id_penerima');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,15 +14,32 @@ class TempatIbadah extends Model
|
||||
protected $fillable = [
|
||||
'nama_tempat',
|
||||
'jenis_tempat_ibadah',
|
||||
'kontak_person',
|
||||
'nama_pengurus',
|
||||
'kontak_pengurus',
|
||||
'radius_meter',
|
||||
'lat',
|
||||
'lng',
|
||||
'alamat'
|
||||
'alamat',
|
||||
'password',
|
||||
'kode_lapor',
|
||||
];
|
||||
|
||||
protected static function booted()
|
||||
{
|
||||
static::creating(function ($tempatIbadah) {
|
||||
if (empty($tempatIbadah->kode_lapor)) {
|
||||
$tempatIbadah->kode_lapor = \Illuminate\Support\Str::random(10);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public function penerima_bantuan()
|
||||
{
|
||||
return $this->hasMany(PenerimaBantuan::class, 'id_tempat_ibadah');
|
||||
}
|
||||
|
||||
public function users()
|
||||
{
|
||||
return $this->hasMany(User::class, 'id_tempat_ibadah');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,8 +23,14 @@ class User extends Authenticatable
|
||||
'email',
|
||||
'password',
|
||||
'role',
|
||||
'id_tempat_ibadah',
|
||||
];
|
||||
|
||||
public function tempatIbadah()
|
||||
{
|
||||
return $this->belongsTo(TempatIbadah::class, 'id_tempat_ibadah');
|
||||
}
|
||||
|
||||
/**
|
||||
* The attributes that should be hidden for serialization.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user