Compare commits
54 Commits
112262d7d6
...
sementara
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aceff4f006 | ||
|
|
f402c0831a | ||
|
|
ceca0aa5e8 | ||
|
|
43361f81e7 | ||
|
|
58b53a0284 | ||
|
|
bb0da7626b | ||
|
|
8a6ab059f5 | ||
|
|
6cf4432642 | ||
|
|
7c5202021f | ||
|
|
e8a735e977 | ||
|
|
1c5b48ff1b | ||
|
|
6378ba0f98 | ||
|
|
2c8136dcf3 | ||
|
|
3315e1d4b6 | ||
|
|
37fb5c90d5 | ||
|
|
ff994a7c95 | ||
|
|
a2275758b1 | ||
|
|
783250d99a | ||
|
|
19057c7e81 | ||
|
|
9dfb8727dc | ||
|
|
bef7bcfa8f | ||
|
|
d9d8eaafcd | ||
|
|
f055cd5573 | ||
|
|
aee8fab832 | ||
|
|
a72cbe4bd9 | ||
|
|
ea09e8161c | ||
|
|
f051fa9507 | ||
|
|
04a657252f | ||
|
|
fc6f18fea9 | ||
|
|
8c60320532 | ||
|
|
34709b0f8f | ||
|
|
b2cfffc5d5 | ||
|
|
89329de198 | ||
|
|
70dda16699 | ||
|
|
db0b1f6cfc | ||
|
|
c153990c52 | ||
|
|
42d6e06a48 | ||
|
|
2db123a386 | ||
|
|
45f0d387fd | ||
|
|
7f9c58aabe | ||
|
|
3ce84b89b4 | ||
|
|
1dd4f8167e | ||
|
|
117b344857 | ||
|
|
0d5b6b1529 | ||
|
|
535be2cff3 | ||
|
|
1a67eb2000 | ||
|
|
e8ef9c0932 | ||
|
|
81f165c9d0 | ||
|
|
25011d1798 | ||
|
|
e773b82218 | ||
|
|
04ee3a0c48 | ||
|
|
10b5a6c96c | ||
|
|
3aca1d46c2 | ||
|
|
db55471111 |
83
Helpers/PdfHelper.php
Normal file
83
Helpers/PdfHelper.php
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Lpj\Helpers;
|
||||||
|
|
||||||
|
class PdfHelper
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Format text for PDF output to handle special characters
|
||||||
|
*
|
||||||
|
* @param string $text
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function formatText($text)
|
||||||
|
{
|
||||||
|
if (empty($text)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Common problematic characters and their safe replacements
|
||||||
|
$replacements = [
|
||||||
|
'<' => '<',
|
||||||
|
'>' => '>',
|
||||||
|
'&' => '&',
|
||||||
|
'"' => '"',
|
||||||
|
"'" => ''',
|
||||||
|
'≤' => '≤',
|
||||||
|
'≥' => '≥',
|
||||||
|
'≠' => '!=',
|
||||||
|
'≈' => '~',
|
||||||
|
'×' => 'x',
|
||||||
|
'÷' => '/',
|
||||||
|
'–' => '-',
|
||||||
|
'—' => '-',
|
||||||
|
'' => '"',
|
||||||
|
'' => '"',
|
||||||
|
'' => "'",
|
||||||
|
'' => "'",
|
||||||
|
];
|
||||||
|
|
||||||
|
// First pass: replace with HTML entities
|
||||||
|
$safeText = str_replace(array_keys($replacements), array_values($replacements), $text);
|
||||||
|
|
||||||
|
// Ensure UTF-8 encoding
|
||||||
|
if (!mb_check_encoding($safeText, 'UTF-8')) {
|
||||||
|
$safeText = mb_convert_encoding($safeText, 'UTF-8', 'auto');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove any remaining non-ASCII characters that could cause issues
|
||||||
|
$safeText = preg_replace('/[^\x20-\x7E\xA0-\xFF]/', '', $safeText);
|
||||||
|
|
||||||
|
return $safeText;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format mathematical symbols to text representation
|
||||||
|
*
|
||||||
|
* @param string $text
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function formatMathSymbols($text)
|
||||||
|
{
|
||||||
|
if (empty($text)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$mathReplacements = [
|
||||||
|
'<' => 'kurang dari',
|
||||||
|
'>' => 'lebih dari',
|
||||||
|
'<=' => 'kurang dari sama dengan',
|
||||||
|
'>=' => 'lebih dari sama dengan',
|
||||||
|
'!=' => 'tidak sama dengan',
|
||||||
|
'==' => 'sama dengan',
|
||||||
|
'≤' => 'kurang dari sama dengan',
|
||||||
|
'≥' => 'lebih dari sama dengan',
|
||||||
|
'≠' => 'tidak sama dengan',
|
||||||
|
'≈' => 'kira-kira',
|
||||||
|
'≡' => 'identik dengan',
|
||||||
|
'≅' => 'hampir sama dengan',
|
||||||
|
];
|
||||||
|
|
||||||
|
return str_replace(array_keys($mathReplacements), array_values($mathReplacements), $text);
|
||||||
|
}
|
||||||
|
}
|
||||||
27
Http/Controllers/ImageController.php
Normal file
27
Http/Controllers/ImageController.php
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Lpj\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Routing\Controller;
|
||||||
|
use Modules\Lpj\app\Services\ImageResizeService;
|
||||||
|
|
||||||
|
class ImageController extends Controller
|
||||||
|
{
|
||||||
|
protected $imageService;
|
||||||
|
|
||||||
|
public function __construct(ImageResizeService $imageService)
|
||||||
|
{
|
||||||
|
$this->imageService = $imageService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function show(Request $request, $path)
|
||||||
|
{
|
||||||
|
$width = $request->query('w');
|
||||||
|
$quality = $request->query('q', 80);
|
||||||
|
|
||||||
|
$resizedPath = $this->imageService->resize($path, $width, null, $quality);
|
||||||
|
|
||||||
|
return response()->file(storage_path('app/public/' . $resizedPath));
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
app/.DS_Store
vendored
Normal file
BIN
app/.DS_Store
vendored
Normal file
Binary file not shown.
228
app/Console/Commands/CleanupInspeksiDataCommand.php
Normal file
228
app/Console/Commands/CleanupInspeksiDataCommand.php
Normal file
@@ -0,0 +1,228 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Lpj\Console\Commands;
|
||||||
|
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Modules\Lpj\Jobs\CleanupInspeksiDataJob;
|
||||||
|
use Modules\Lpj\Models\Inspeksi;
|
||||||
|
use Modules\Lpj\Services\InspeksiCleanupService;
|
||||||
|
|
||||||
|
class CleanupInspeksiDataCommand extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'lpj:cleanup-inspeksi
|
||||||
|
{--permohonan-id= : ID permohonan yang akan di-cleanup (opsional)}
|
||||||
|
{--sync : Jalankan secara synchronous}
|
||||||
|
{--dry-run : Tampilkan preview tanpa menjalankan cleanup}
|
||||||
|
{--force : Jalankan tanpa konfirmasi}';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'Cleanup data inspeksi lama yang tidak memiliki dokument_id';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*/
|
||||||
|
public function handle(): int
|
||||||
|
{
|
||||||
|
Log::info('CleanupInspeksiDataCommand: Memulai proses cleanup data inspeksi', [
|
||||||
|
'options' => $this->options()
|
||||||
|
]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$permohonanId = $this->option('permohonan-id');
|
||||||
|
$sync = $this->option('sync');
|
||||||
|
$dryRun = $this->option('dry-run');
|
||||||
|
$force = $this->option('force');
|
||||||
|
|
||||||
|
// Validasi opsi
|
||||||
|
if ($dryRun && $sync) {
|
||||||
|
$this->error('Opsi --dry-run dan --sync tidak dapat digunakan bersamaan.');
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tampilkan header
|
||||||
|
$this->info('=== Cleanup Data Inspeksi ===');
|
||||||
|
$this->newLine();
|
||||||
|
|
||||||
|
// Ambil data yang akan di-cleanup
|
||||||
|
$cleanupData = $this->getCleanupData($permohonanId);
|
||||||
|
|
||||||
|
if ($cleanupData->isEmpty()) {
|
||||||
|
$this->info('Tidak ada data yang perlu di-cleanup.');
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tampilkan preview data
|
||||||
|
$this->displayPreview($cleanupData);
|
||||||
|
|
||||||
|
if ($dryRun) {
|
||||||
|
$this->info('Mode dry-run: Tidak ada perubahan yang dilakukan.');
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Konfirmasi jika tidak force
|
||||||
|
if (!$force && !$this->confirm('Lanjutkan dengan cleanup?')) {
|
||||||
|
$this->info('Cleanup dibatalkan.');
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Jalankan cleanup
|
||||||
|
$this->runCleanup($cleanupData, $sync);
|
||||||
|
|
||||||
|
$this->info('Proses cleanup selesai.');
|
||||||
|
return Command::SUCCESS;
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::error('CleanupInspeksiDataCommand: Terjadi error saat proses cleanup', [
|
||||||
|
'error' => $e->getMessage(),
|
||||||
|
'trace' => $e->getTraceAsString()
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->error('Terjadi kesalahan: ' . $e->getMessage());
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ambil data yang akan di-cleanup
|
||||||
|
*/
|
||||||
|
private function getCleanupData(?int $permohonanId = null)
|
||||||
|
{
|
||||||
|
$this->info('Mencari data yang akan di-cleanup...');
|
||||||
|
|
||||||
|
$query = DB::table('inspeksi as i')
|
||||||
|
->select(
|
||||||
|
'i.permohonan_id',
|
||||||
|
'i.created_by',
|
||||||
|
DB::raw('COUNT(CASE WHEN i.dokument_id IS NOT NULL AND i.deleted_at IS NULL THEN 1 END) as new_data_count'),
|
||||||
|
DB::raw('COUNT(CASE WHEN i.dokument_id IS NULL AND i.deleted_at IS NULL THEN 1 END) as old_data_count')
|
||||||
|
)
|
||||||
|
->whereNull('i.deleted_at')
|
||||||
|
->groupBy('i.permohonan_id', 'i.created_by');
|
||||||
|
|
||||||
|
if ($permohonanId) {
|
||||||
|
$query->where('i.permohonan_id', $permohonanId);
|
||||||
|
}
|
||||||
|
|
||||||
|
$results = $query->havingRaw('new_data_count > 0 AND old_data_count > 0')
|
||||||
|
->get();
|
||||||
|
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tampilkan preview data
|
||||||
|
*/
|
||||||
|
private function displayPreview($cleanupData): void
|
||||||
|
{
|
||||||
|
$this->info('Data yang akan di-cleanup:');
|
||||||
|
$this->table(
|
||||||
|
['Permohonan ID', 'Created By', 'Data Baru', 'Data Lama'],
|
||||||
|
$cleanupData->map(function ($item) {
|
||||||
|
return [
|
||||||
|
$item->permohonan_id,
|
||||||
|
$item->created_by,
|
||||||
|
$item->new_data_count,
|
||||||
|
$item->old_data_count
|
||||||
|
];
|
||||||
|
})->toArray()
|
||||||
|
);
|
||||||
|
|
||||||
|
$totalPermohonan = $cleanupData->count();
|
||||||
|
$totalOldData = $cleanupData->sum('old_data_count');
|
||||||
|
|
||||||
|
$this->info("Total permohonan: {$totalPermohonan}");
|
||||||
|
$this->info("Total data lama yang akan dihapus: {$totalOldData}");
|
||||||
|
$this->newLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Jalankan cleanup
|
||||||
|
*/
|
||||||
|
private function runCleanup($cleanupData, bool $sync): void
|
||||||
|
{
|
||||||
|
$this->info('Memulai proses cleanup...');
|
||||||
|
$this->newLine();
|
||||||
|
|
||||||
|
$progressBar = $this->output->createProgressBar($cleanupData->count());
|
||||||
|
$progressBar->setFormat('Processing: %current%/%max% [%bar%] %percent:3s%% %message%');
|
||||||
|
$progressBar->start();
|
||||||
|
|
||||||
|
$totalDeleted = 0;
|
||||||
|
$totalErrors = 0;
|
||||||
|
|
||||||
|
foreach ($cleanupData as $data) {
|
||||||
|
try {
|
||||||
|
$progressBar->setMessage("Permohonan ID: {$data->permohonan_id}");
|
||||||
|
|
||||||
|
// Ambil data baru untuk mendapatkan dokument_id
|
||||||
|
$newInspeksi = Inspeksi::where('permohonan_id', $data->permohonan_id)
|
||||||
|
->where('created_by', $data->created_by)
|
||||||
|
->whereNotNull('dokument_id')
|
||||||
|
->whereNull('deleted_at')
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if (!$newInspeksi) {
|
||||||
|
$this->warn("Tidak ditemukan data baru untuk permohonan {$data->permohonan_id}");
|
||||||
|
$progressBar->advance();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Jalankan cleanup
|
||||||
|
if ($sync) {
|
||||||
|
// Jalankan sync
|
||||||
|
$job = new CleanupInspeksiDataJob(
|
||||||
|
$data->permohonan_id,
|
||||||
|
$data->created_by,
|
||||||
|
$newInspeksi->dokument_id
|
||||||
|
);
|
||||||
|
$job->handle();
|
||||||
|
} else {
|
||||||
|
// Dispatch ke queue
|
||||||
|
CleanupInspeksiDataJob::dispatch(
|
||||||
|
$data->permohonan_id,
|
||||||
|
$data->created_by,
|
||||||
|
$newInspeksi->dokument_id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$totalDeleted += $data->old_data_count;
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::error('CleanupInspeksiDataCommand: Error pada permohonan', [
|
||||||
|
'permohonan_id' => $data->permohonan_id,
|
||||||
|
'created_by' => $data->created_by,
|
||||||
|
'error' => $e->getMessage()
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->error("Error pada permohonan {$data->permohonan_id}: {$e->getMessage()}");
|
||||||
|
$totalErrors++;
|
||||||
|
}
|
||||||
|
|
||||||
|
$progressBar->advance();
|
||||||
|
}
|
||||||
|
|
||||||
|
$progressBar->finish();
|
||||||
|
$this->newLine();
|
||||||
|
$this->newLine();
|
||||||
|
|
||||||
|
// Tampilkan hasil
|
||||||
|
$this->info('=== Hasil Cleanup ===');
|
||||||
|
$this->info("Data lama yang dihapus: {$totalDeleted}");
|
||||||
|
$this->info("Error: {$totalErrors}");
|
||||||
|
|
||||||
|
if (!$sync) {
|
||||||
|
$this->info('Job telah di-dispatch ke queue. Monitor progress di log.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
192
app/Console/Commands/CleanupInspeksiStatusCommand.php
Normal file
192
app/Console/Commands/CleanupInspeksiStatusCommand.php
Normal file
@@ -0,0 +1,192 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Lpj\Console\Commands;
|
||||||
|
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Modules\Lpj\Models\Inspeksi;
|
||||||
|
|
||||||
|
class CleanupInspeksiStatusCommand extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'lpj:cleanup-inspeksi-status
|
||||||
|
{--permohonan-id= : Filter berdasarkan permohonan ID}
|
||||||
|
{--created-by= : Filter berdasarkan user ID}
|
||||||
|
{--detailed : Tampilkan detail data}';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'Cek status data inspeksi yang memerlukan cleanup';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*/
|
||||||
|
public function handle(): int
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$permohonanId = $this->option('permohonan-id');
|
||||||
|
$createdBy = $this->option('created-by');
|
||||||
|
$detailed = $this->option('detailed');
|
||||||
|
|
||||||
|
$this->info('=== Status Data Inspeksi ===');
|
||||||
|
$this->newLine();
|
||||||
|
|
||||||
|
// Ambil statistik umum
|
||||||
|
$this->showGeneralStats();
|
||||||
|
|
||||||
|
// Ambil data yang memerlukan cleanup
|
||||||
|
$this->showCleanupStats($permohonanId, $createdBy);
|
||||||
|
|
||||||
|
if ($detailed) {
|
||||||
|
$this->showDetailedData($permohonanId, $createdBy);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::error('CleanupInspeksiStatusCommand: Terjadi error', [
|
||||||
|
'error' => $e->getMessage(),
|
||||||
|
'trace' => $e->getTraceAsString()
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->error('Terjadi kesalahan: ' . $e->getMessage());
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tampilkan statistik umum
|
||||||
|
*/
|
||||||
|
private function showGeneralStats(): void
|
||||||
|
{
|
||||||
|
$this->info('Statistik Umum:');
|
||||||
|
|
||||||
|
$totalData = Inspeksi::count();
|
||||||
|
$activeData = Inspeksi::whereNull('deleted_at')->count();
|
||||||
|
$deletedData = Inspeksi::whereNotNull('deleted_at')->count();
|
||||||
|
$dataWithDokument = Inspeksi::whereNotNull('dokument_id')->count();
|
||||||
|
$dataWithoutDokument = Inspeksi::whereNull('dokument_id')->count();
|
||||||
|
|
||||||
|
$this->table(
|
||||||
|
['Metrik', 'Jumlah'],
|
||||||
|
[
|
||||||
|
['Total Data', number_format($totalData)],
|
||||||
|
['Data Aktif', number_format($activeData)],
|
||||||
|
['Data Terhapus (Soft)', number_format($deletedData)],
|
||||||
|
['Data dengan Dokument ID', number_format($dataWithDokument)],
|
||||||
|
['Data tanpa Dokument ID', number_format($dataWithoutDokument)],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->newLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tampilkan statistik cleanup
|
||||||
|
*/
|
||||||
|
private function showCleanupStats(?int $permohonanId = null, ?int $createdBy = null): void
|
||||||
|
{
|
||||||
|
$this->info('Data yang Memerlukan Cleanup:');
|
||||||
|
|
||||||
|
$query = DB::table('inspeksi as i')
|
||||||
|
->select(
|
||||||
|
'i.permohonan_id',
|
||||||
|
'i.created_by',
|
||||||
|
DB::raw('COUNT(CASE WHEN i.dokument_id IS NOT NULL AND i.deleted_at IS NULL THEN 1 END) as new_data_count'),
|
||||||
|
DB::raw('COUNT(CASE WHEN i.dokument_id IS NULL AND i.deleted_at IS NULL THEN 1 END) as old_data_count'),
|
||||||
|
DB::raw('MIN(i.created_at) as oldest_data'),
|
||||||
|
DB::raw('MAX(i.created_at) as newest_data')
|
||||||
|
)
|
||||||
|
->whereNull('i.deleted_at')
|
||||||
|
->groupBy('i.permohonan_id', 'i.created_by');
|
||||||
|
|
||||||
|
if ($permohonanId) {
|
||||||
|
$query->where('i.permohonan_id', $permohonanId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($createdBy) {
|
||||||
|
$query->where('i.created_by', $createdBy);
|
||||||
|
}
|
||||||
|
|
||||||
|
$results = $query->havingRaw('new_data_count > 0 AND old_data_count > 0')
|
||||||
|
->orderBy('old_data_count', 'desc')
|
||||||
|
->limit(20)
|
||||||
|
->get();
|
||||||
|
|
||||||
|
if ($results->isEmpty()) {
|
||||||
|
$this->info('Tidak ada data yang memerlukan cleanup.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->table(
|
||||||
|
['Permohonan ID', 'Created By', 'Data Baru', 'Data Lama', 'Data Terlama', 'Data Terbaru'],
|
||||||
|
$results->map(function ($item) {
|
||||||
|
return [
|
||||||
|
$item->permohonan_id,
|
||||||
|
$item->created_by,
|
||||||
|
$item->new_data_count,
|
||||||
|
$item->old_data_count,
|
||||||
|
$item->oldest_data,
|
||||||
|
$item->newest_data,
|
||||||
|
];
|
||||||
|
})->toArray()
|
||||||
|
);
|
||||||
|
|
||||||
|
$totalPermohonan = $results->count();
|
||||||
|
$totalOldData = $results->sum('old_data_count');
|
||||||
|
|
||||||
|
$this->info("Total permohonan yang perlu cleanup: {$totalPermohonan}");
|
||||||
|
$this->info("Total data lama yang akan dihapus: {$totalOldData}");
|
||||||
|
$this->newLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tampilkan detail data
|
||||||
|
*/
|
||||||
|
private function showDetailedData(?int $permohonanId = null, ?int $createdBy = null): void
|
||||||
|
{
|
||||||
|
$this->info('Detail Data (20 data terbaru):');
|
||||||
|
|
||||||
|
$query = Inspeksi::with(['permohonan', 'dokument'])
|
||||||
|
->whereNull('deleted_at');
|
||||||
|
|
||||||
|
if ($permohonanId) {
|
||||||
|
$query->where('permohonan_id', $permohonanId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($createdBy) {
|
||||||
|
$query->where('created_by', $createdBy);
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = $query->orderBy('created_at', 'desc')
|
||||||
|
->limit(20)
|
||||||
|
->get();
|
||||||
|
|
||||||
|
if ($data->isEmpty()) {
|
||||||
|
$this->info('Tidak ada data untuk ditampilkan.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->table(
|
||||||
|
['ID', 'Permohonan ID', 'Created By', 'Dokument ID', 'Status', 'Created At'],
|
||||||
|
$data->map(function ($item) {
|
||||||
|
return [
|
||||||
|
$item->id,
|
||||||
|
$item->permohonan_id,
|
||||||
|
$item->created_by,
|
||||||
|
$item->dokument_id ?? '-',
|
||||||
|
$item->status,
|
||||||
|
$item->created_at,
|
||||||
|
];
|
||||||
|
})->toArray()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
99
app/Console/Commands/CleanupSingleInspeksiCommand.php
Normal file
99
app/Console/Commands/CleanupSingleInspeksiCommand.php
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Lpj\Console\Commands;
|
||||||
|
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Modules\Lpj\Jobs\CleanupInspeksiDataJob;
|
||||||
|
use Modules\Lpj\Services\InspeksiCleanupService;
|
||||||
|
|
||||||
|
class CleanupSingleInspeksiCommand extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'lpj:cleanup-single-inspeksi
|
||||||
|
{permohonan-id : ID permohonan yang akan di-cleanup}
|
||||||
|
{created-by : ID user yang membuat data}
|
||||||
|
{--sync : Jalankan secara synchronous}
|
||||||
|
{--force : Jalankan tanpa konfirmasi}';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'Cleanup data inspeksi untuk 1 permohonan dan user tertentu';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*/
|
||||||
|
public function handle(): int
|
||||||
|
{
|
||||||
|
Log::info('CleanupSingleInspeksiCommand: Memulai proses cleanup', [
|
||||||
|
'permohonan_id' => $this->argument('permohonan-id'),
|
||||||
|
'created_by' => $this->argument('created-by'),
|
||||||
|
'sync' => $this->option('sync')
|
||||||
|
]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$permohonanId = (int) $this->argument('permohonan-id');
|
||||||
|
$createdBy = (int) $this->argument('created-by');
|
||||||
|
$sync = $this->option('sync');
|
||||||
|
$force = $this->option('force');
|
||||||
|
|
||||||
|
// Validasi input
|
||||||
|
if ($permohonanId <= 0) {
|
||||||
|
$this->error('Permohonan ID harus angka positif.');
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($createdBy <= 0) {
|
||||||
|
$this->error('Created By harus angka positif.');
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tampilkan info
|
||||||
|
$this->info('=== Cleanup Single Inspeksi ===');
|
||||||
|
$this->info("Permohonan ID: {$permohonanId}");
|
||||||
|
$this->info("Created By: {$createdBy}");
|
||||||
|
$this->info("Mode: " . ($sync ? 'Synchronous' : 'Queue'));
|
||||||
|
$this->newLine();
|
||||||
|
|
||||||
|
// Konfirmasi jika tidak force
|
||||||
|
if (!$force && !$this->confirm('Lanjutkan dengan cleanup?')) {
|
||||||
|
$this->info('Cleanup dibatalkan.');
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Jalankan cleanup
|
||||||
|
$cleanupService = new InspeksiCleanupService();
|
||||||
|
|
||||||
|
if ($sync) {
|
||||||
|
$this->info('Menjalankan cleanup secara synchronous...');
|
||||||
|
$cleanupService->cleanupSync($permohonanId, $createdBy);
|
||||||
|
$this->info('Cleanup selesai.');
|
||||||
|
} else {
|
||||||
|
$this->info('Mengirim job ke queue...');
|
||||||
|
$cleanupService->cleanupAsync($permohonanId, $createdBy);
|
||||||
|
$this->info('Job telah di-dispatch ke queue.');
|
||||||
|
$this->info('Monitor progress di log.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::error('CleanupSingleInspeksiCommand: Terjadi error saat proses cleanup', [
|
||||||
|
'permohonan_id' => $this->argument('permohonan-id'),
|
||||||
|
'created_by' => $this->argument('created-by'),
|
||||||
|
'error' => $e->getMessage(),
|
||||||
|
'trace' => $e->getTraceAsString()
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->error('Terjadi kesalahan: ' . $e->getMessage());
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
123
app/Console/README.md
Normal file
123
app/Console/README.md
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
# Console Commands untuk Cleanup Data Inspeksi
|
||||||
|
|
||||||
|
## Daftar Command
|
||||||
|
|
||||||
|
### 1. `lpj:cleanup-inspeksi`
|
||||||
|
Command utama untuk cleanup data inspeksi secara batch.
|
||||||
|
|
||||||
|
**Usage:**
|
||||||
|
```bash
|
||||||
|
php artisan lpj:cleanup-inspeksi [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Options:**
|
||||||
|
- `--permohonan-id=ID` - Filter berdasarkan permohonan ID (opsional)
|
||||||
|
- `--sync` - Jalankan secara synchronous
|
||||||
|
- `--dry-run` - Tampilkan preview tanpa menjalankan cleanup
|
||||||
|
- `--force` - Jalankan tanpa konfirmasi
|
||||||
|
|
||||||
|
**Contoh Penggunaan:**
|
||||||
|
```bash
|
||||||
|
# Preview data yang akan di-cleanup
|
||||||
|
php artisan lpj:cleanup-inspeksi --dry-run
|
||||||
|
|
||||||
|
# Cleanup semua data (dengan konfirmasi)
|
||||||
|
php artisan lpj:cleanup-inspeksi
|
||||||
|
|
||||||
|
# Cleanup untuk permohonan tertentu
|
||||||
|
php artisan lpj:cleanup-inspeksi --permohonan-id=123 --force
|
||||||
|
|
||||||
|
# Jalankan secara sync
|
||||||
|
php artisan lpj:cleanup-inspeksi --sync --force
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. `lpj:cleanup-single-inspeksi`
|
||||||
|
Command untuk cleanup 1 permohonan dan user tertentu.
|
||||||
|
|
||||||
|
**Usage:**
|
||||||
|
```bash
|
||||||
|
php artisan lpj:cleanup-single-inspeksi <permohonan-id> <created-by> [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Arguments:**
|
||||||
|
- `permohonan-id` - ID permohonan yang akan di-cleanup (required)
|
||||||
|
- `created-by` - ID user yang membuat data (required)
|
||||||
|
|
||||||
|
**Options:**
|
||||||
|
- `--sync` - Jalankan secara synchronous
|
||||||
|
- `--force` - Jalankan tanpa konfirmasi
|
||||||
|
|
||||||
|
**Contoh Penggunaan:**
|
||||||
|
```bash
|
||||||
|
# Cleanup untuk permohonan 123 oleh user 456
|
||||||
|
php artisan lpj:cleanup-single-inspeksi 123 456
|
||||||
|
|
||||||
|
# Jalankan secara sync tanpa konfirmasi
|
||||||
|
php artisan lpj:cleanup-single-inspeksi 123 456 --sync --force
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. `lpj:cleanup-inspeksi-status`
|
||||||
|
Command untuk mengecek status data inspeksi dan melihat statistik cleanup.
|
||||||
|
|
||||||
|
**Usage:**
|
||||||
|
```bash
|
||||||
|
php artisan lpj:cleanup-inspeksi-status [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Options:**
|
||||||
|
- `--permohonan-id=ID` - Filter berdasarkan permohonan ID
|
||||||
|
- `--created-by=ID` - Filter berdasarkan user ID
|
||||||
|
- `--detailed` - Tampilkan detail data
|
||||||
|
|
||||||
|
**Contoh Penggunaan:**
|
||||||
|
```bash
|
||||||
|
# Lihat statistik umum
|
||||||
|
php artisan lpj:cleanup-inspeksi-status
|
||||||
|
|
||||||
|
# Filter berdasarkan permohonan
|
||||||
|
php artisan lpj:cleanup-inspeksi-status --permohonan-id=123
|
||||||
|
|
||||||
|
# Tampilkan detail data
|
||||||
|
php artisan lpj:cleanup-inspeksi-status --detailed
|
||||||
|
```
|
||||||
|
|
||||||
|
## Scheduling
|
||||||
|
|
||||||
|
Command cleanup otomatis dijalankan setiap hari jam 2 pagi dan setiap minggu. Konfigurasi scheduling ada di `LpjServiceProvider.php`.
|
||||||
|
|
||||||
|
## Monitoring
|
||||||
|
|
||||||
|
Semua aktivitas cleanup dicatat di log file:
|
||||||
|
- `storage/logs/laravel.log` - Log umum
|
||||||
|
- `storage/logs/cleanup-inspeksi.log` - Log cleanup harian
|
||||||
|
- `storage/logs/cleanup-inspeksi-weekly.log` - Log cleanup mingguan
|
||||||
|
|
||||||
|
## Alur Kerja Cleanup
|
||||||
|
|
||||||
|
1. **Identifikasi**: Cari data inspeksi yang memiliki:
|
||||||
|
- Data baru dengan `dokument_id` (tidak null)
|
||||||
|
- Data lama tanpa `dokument_id` (null)
|
||||||
|
- Sama `permohonan_id` dan `created_by`
|
||||||
|
|
||||||
|
2. **Proses**: Soft delete data lama menggunakan Laravel SoftDeletes
|
||||||
|
|
||||||
|
3. **Logging**: Catat setiap operasi untuk audit trail
|
||||||
|
|
||||||
|
4. **Transaction**: Gunakan DB transaction untuk konsistensi data
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Command tidak muncul
|
||||||
|
Pastikan service provider sudah diregister dengan benar:
|
||||||
|
```bash
|
||||||
|
php artisan list | grep lpj
|
||||||
|
```
|
||||||
|
|
||||||
|
### Data tidak ter-cleanup
|
||||||
|
- Cek log untuk error
|
||||||
|
- Pastikan ada data yang memenuhi kriteria
|
||||||
|
- Gunakan `--dry-run` untuk preview
|
||||||
|
- Gunakan `--detailed` untuk melihat detail data
|
||||||
|
|
||||||
|
### Performance
|
||||||
|
Untuk data besar, gunakan mode queue (default) daripada `--sync`
|
||||||
@@ -24,6 +24,7 @@
|
|||||||
$row->id,
|
$row->id,
|
||||||
$row->code,
|
$row->code,
|
||||||
$row->name,
|
$row->name,
|
||||||
|
$row->biaya,
|
||||||
$row->created_at
|
$row->created_at
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -35,6 +36,7 @@
|
|||||||
'ID',
|
'ID',
|
||||||
'Code',
|
'Code',
|
||||||
'Name',
|
'Name',
|
||||||
|
'Biaya',
|
||||||
'Created At'
|
'Created At'
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -44,7 +46,8 @@
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'A' => NumberFormat::FORMAT_NUMBER,
|
'A' => NumberFormat::FORMAT_NUMBER,
|
||||||
'D' => NumberFormat::FORMAT_DATE_DATETIME
|
'D' => NumberFormat::FORMAT_NUMBER_00,
|
||||||
|
'E' => NumberFormat::FORMAT_DATE_DATETIME
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
128
app/Exports/ReferensiLinkExport.php
Normal file
128
app/Exports/ReferensiLinkExport.php
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Lpj\Exports;
|
||||||
|
|
||||||
|
use Modules\Lpj\app\Models\ReferensiLink;
|
||||||
|
use Maatwebsite\Excel\Concerns\FromQuery;
|
||||||
|
use Maatwebsite\Excel\Concerns\WithHeadings;
|
||||||
|
use Maatwebsite\Excel\Concerns\WithMapping;
|
||||||
|
use Maatwebsite\Excel\Concerns\WithStyles;
|
||||||
|
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
|
||||||
|
use Maatwebsite\Excel\Concerns\WithColumnFormatting;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
|
||||||
|
|
||||||
|
class ReferensiLinkExport implements FromQuery, WithHeadings, WithMapping, WithStyles, ShouldAutoSize, WithColumnFormatting
|
||||||
|
{
|
||||||
|
protected $filters;
|
||||||
|
|
||||||
|
public function __construct($filters = [])
|
||||||
|
{
|
||||||
|
$this->filters = $filters;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query data yang akan diexport
|
||||||
|
*/
|
||||||
|
public function query()
|
||||||
|
{
|
||||||
|
$query = ReferensiLink::with(['createdBy', 'updatedBy'])
|
||||||
|
->select('referensi_link.*');
|
||||||
|
|
||||||
|
// Apply filters
|
||||||
|
if (isset($this->filters['kategori']) && !empty($this->filters['kategori'])) {
|
||||||
|
$query->where('kategori', $this->filters['kategori']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($this->filters['status']) && $this->filters['status'] !== '') {
|
||||||
|
$query->where('is_active', $this->filters['status']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($this->filters['search']) && !empty($this->filters['search'])) {
|
||||||
|
$query->search($this->filters['search']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $query->ordered();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Header kolom
|
||||||
|
*/
|
||||||
|
public function headings(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'No',
|
||||||
|
'Nama',
|
||||||
|
'Link',
|
||||||
|
'Kategori',
|
||||||
|
'Deskripsi',
|
||||||
|
'Status Aktif',
|
||||||
|
'Urutan',
|
||||||
|
'Dibuat Oleh',
|
||||||
|
'Diupdate Oleh',
|
||||||
|
'Tanggal Dibuat',
|
||||||
|
'Tanggal Diupdate',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mapping data untuk setiap baris
|
||||||
|
*/
|
||||||
|
public function map($referensiLink): array
|
||||||
|
{
|
||||||
|
static $rowNumber = 0;
|
||||||
|
$rowNumber++;
|
||||||
|
|
||||||
|
return [
|
||||||
|
$rowNumber,
|
||||||
|
$referensiLink->name,
|
||||||
|
$referensiLink->link,
|
||||||
|
$referensiLink->kategori ?? '-',
|
||||||
|
$referensiLink->deskripsi ?? '-',
|
||||||
|
$referensiLink->is_active ? 'Aktif' : 'Tidak Aktif',
|
||||||
|
$referensiLink->urutan,
|
||||||
|
$referensiLink->createdBy ? $referensiLink->createdBy->name : '-',
|
||||||
|
$referensiLink->updatedBy ? $referensiLink->updatedBy->name : '-',
|
||||||
|
$referensiLink->created_at->format('d-m-Y H:i:s'),
|
||||||
|
$referensiLink->updated_at->format('d-m-Y H:i:s'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Styling untuk worksheet
|
||||||
|
*/
|
||||||
|
public function styles(Worksheet $sheet)
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
// Header styling
|
||||||
|
1 => [
|
||||||
|
'font' => ['bold' => true, 'size' => 12],
|
||||||
|
'fill' => ['fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID, 'startColor' => ['rgb' => 'E2EFDA']],
|
||||||
|
'alignment' => ['horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER],
|
||||||
|
],
|
||||||
|
// Alternating row colors
|
||||||
|
'A2:K1000' => [
|
||||||
|
'fill' => ['fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID, 'startColor' => ['rgb' => 'F8F9FA']],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format kolom
|
||||||
|
*/
|
||||||
|
public function columnFormats(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'F' => NumberFormat::FORMAT_DATE_DDMMYYYY, // Tanggal dibuat
|
||||||
|
'G' => NumberFormat::FORMAT_DATE_DDMMYYYY, // Tanggal diupdate
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom title untuk sheet
|
||||||
|
*/
|
||||||
|
public function title(): string
|
||||||
|
{
|
||||||
|
return 'Referensi Link';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
use Modules\Location\Models\City;
|
use Modules\Location\Models\City;
|
||||||
use Modules\Location\Models\District;
|
use Modules\Location\Models\District;
|
||||||
use Modules\Location\Models\Province;
|
use Modules\Location\Models\Province;
|
||||||
@@ -15,29 +18,118 @@
|
|||||||
use Modules\Lpj\Models\Penilaian;
|
use Modules\Lpj\Models\Penilaian;
|
||||||
use Modules\Lpj\Models\TeamsUsers;
|
use Modules\Lpj\Models\TeamsUsers;
|
||||||
use Modules\Usermanagement\Models\User;
|
use Modules\Usermanagement\Models\User;
|
||||||
|
use Illuminate\Support\Facades\File;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use Modules\Lpj\Services\ImageResizeService;
|
||||||
|
|
||||||
function formatTanggalIndonesia($date, $time = false)
|
/**
|
||||||
|
* Format tanggal ke dalam format Bahasa Indonesia
|
||||||
|
*
|
||||||
|
* Mengubah tanggal menjadi format yang lebih mudah dibaca dalam Bahasa Indonesia.
|
||||||
|
* Contoh: "15 Januari 2024" atau "15 Januari 2024 pukul 14.30 WIB"
|
||||||
|
*
|
||||||
|
* @param string|mixed $date Tanggal yang akan diformat (string tanggal atau null)
|
||||||
|
* @param bool $time Apakah akan menampilkan waktu juga (default: false)
|
||||||
|
* @return string Tanggal yang sudah diformat dalam Bahasa Indonesia
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* formatTanggalIndonesia('2024-01-15') // "15 Januari 2024"
|
||||||
|
* formatTanggalIndonesia('2024-01-15 14:30:00', true) // "15 Januari 2024 pukul 14.30 WIB"
|
||||||
|
* formatTanggalIndonesia(null) // ""
|
||||||
|
* formatTanggalIndonesia('invalid-date') // "invalid-date" (return as-is jika error)
|
||||||
|
*/
|
||||||
|
function formatTanggalIndonesia($date, $time = false): string
|
||||||
{
|
{
|
||||||
Carbon::setLocale('id');
|
Log::debug('Memulai format tanggal Indonesia', [
|
||||||
try {
|
'date' => $date,
|
||||||
$waktu = Carbon::parse($date);
|
'time' => $time
|
||||||
if (!$time) {
|
]);
|
||||||
return $waktu->translatedFormat('d F Y');
|
|
||||||
}
|
// Validasi input null atau kosong
|
||||||
return $waktu->translatedFormat('d F Y') . ' pukul ' . $waktu->format('H.i') . ' WIB';
|
if (empty($date)) {
|
||||||
} catch (Throwable $e) {
|
Log::debug('Tanggal kosong, return empty string');
|
||||||
return $date;
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Carbon::setLocale('id');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$waktu = Carbon::parse($date);
|
||||||
|
|
||||||
|
if (!$time) {
|
||||||
|
$result = $waktu->translatedFormat('d F Y');
|
||||||
|
Log::debug('Format tanggal berhasil', ['result' => $result]);
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = $waktu->translatedFormat('d F Y') . ' pukul ' . $waktu->format('H.i') . ' WIB';
|
||||||
|
Log::debug('Format tanggal dengan waktu berhasil', ['result' => $result]);
|
||||||
|
return $result;
|
||||||
|
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
Log::warning('Gagal parse tanggal', [
|
||||||
|
'date' => $date,
|
||||||
|
'error' => $e->getMessage()
|
||||||
|
]);
|
||||||
|
// Return input as-is jika gagal parse
|
||||||
|
return (string) $date;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
function formatRupiah($number, $decimals = 0)
|
* Format angka ke dalam format mata uang Rupiah Indonesia
|
||||||
|
*
|
||||||
|
* Mengubah angka menjadi format mata uang Rupiah dengan pemisah ribuan
|
||||||
|
* dan menggunakan koma sebagai pemisah desimal sesuai standar Indonesia.
|
||||||
|
*
|
||||||
|
* @param int|float|string $number Angka yang akan diformat (bisa negatif)
|
||||||
|
* @param int $decimals Jumlah digit desimal (default: 0)
|
||||||
|
* @return string Angka yang sudah diformat dalam format Rupiah
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* formatRupiah(1500000) // "Rp 1.500.000"
|
||||||
|
* formatRupiah(1500000.50, 2) // "Rp 1.500.000,50"
|
||||||
|
* formatRupiah(-500000) // "Rp -500.000"
|
||||||
|
* formatRupiah(0) // "Rp 0"
|
||||||
|
* formatRupiah(null) // "Rp 0"
|
||||||
|
*/
|
||||||
|
function formatRupiah($number, $decimals = 0, $withSymbol = true): string
|
||||||
{
|
{
|
||||||
$number = (float) $number;
|
Log::debug('Memulai format Rupiah', [
|
||||||
return 'Rp ' . number_format($number, $decimals, ',', '.');
|
'number' => $number,
|
||||||
}
|
'decimals' => $decimals,
|
||||||
|
'withSymbol' => $withSymbol
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Handle null atau kosong
|
||||||
|
if ($number === null || $number === '') {
|
||||||
|
Log::debug('Number null atau kosong, return Rp 0');
|
||||||
|
return $withSymbol ? 'Rp 0' : '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove dots if present
|
||||||
|
$number = str_replace('.', '', (string) $number);
|
||||||
|
|
||||||
|
// Konversi ke float dan handle error
|
||||||
|
try {
|
||||||
|
$number = (float) $number;
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
Log::warning('Gagal konversi number ke float', [
|
||||||
|
'number' => $number,
|
||||||
|
'error' => $e->getMessage()
|
||||||
|
]);
|
||||||
|
return $withSymbol ? 'Rp 0' : '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validasi decimals
|
||||||
|
$decimals = max(0, (int) $decimals);
|
||||||
|
|
||||||
|
$formatted = number_format($number, $decimals, ',', '.');
|
||||||
|
$result = $withSymbol ? 'Rp ' . $formatted : $formatted;
|
||||||
|
Log::debug('Format Rupiah berhasil', ['result' => $result]);
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
function formatAlamat($alamat)
|
function formatAlamat($alamat)
|
||||||
{
|
{
|
||||||
@@ -96,8 +188,6 @@
|
|||||||
$query->orWhereNull('dokumen_persetujuan');
|
$query->orWhereNull('dokumen_persetujuan');
|
||||||
},
|
},
|
||||||
)->get();
|
)->get();
|
||||||
// $sql = DB::getQueryLog();
|
|
||||||
|
|
||||||
|
|
||||||
if (sizeof($query) > 0) {
|
if (sizeof($query) > 0) {
|
||||||
$allow = false;
|
$allow = false;
|
||||||
@@ -238,9 +328,6 @@
|
|||||||
return $hasil;
|
return $hasil;
|
||||||
}
|
}
|
||||||
|
|
||||||
// andy add
|
|
||||||
|
|
||||||
|
|
||||||
function hitungHariKerja($tanggalMulai, $tanggalSelesai)
|
function hitungHariKerja($tanggalMulai, $tanggalSelesai)
|
||||||
{
|
{
|
||||||
$tanggalMulai = Carbon::parse($tanggalMulai)->startOfDay();
|
$tanggalMulai = Carbon::parse($tanggalMulai)->startOfDay();
|
||||||
@@ -326,7 +413,8 @@
|
|||||||
$day = str_pad(date('d'), 2, '0', STR_PAD_LEFT);
|
$day = str_pad(date('d'), 2, '0', STR_PAD_LEFT);
|
||||||
|
|
||||||
// Generate random numbers
|
// Generate random numbers
|
||||||
$randomNumber = str_pad(mt_rand(0, pow(10, $randomLength) - 1), $randomLength, '0', STR_PAD_LEFT);
|
//$randomNumber = str_pad(mt_rand(0, pow(10, $randomLength) - 1), $randomLength, '0', STR_PAD_LEFT);
|
||||||
|
$randomNumber = sprintf('%0' . $randomLength . 'd', mt_rand(0, pow(10, $randomLength) - 1));
|
||||||
|
|
||||||
// Concatenate components to create the custom code
|
// Concatenate components to create the custom code
|
||||||
return $year . $month . $day . $randomNumber;
|
return $year . $month . $day . $randomNumber;
|
||||||
@@ -530,15 +618,178 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatNotifikasi($notifikasi)
|
function parsePembandingMigration($keterangan) {
|
||||||
{
|
$keterangan = preg_replace('/[-]{5,}/', '',$keterangan); // Hapus ------
|
||||||
$data = json_decode(json_encode($notifikasi->data));
|
$keterangan = preg_replace('/[.]{5,}/', '',$keterangan); // Hapus .....
|
||||||
$message = $data->message;
|
|
||||||
$data = $data->data;
|
$keterangan = preg_replace('/\s+/', ' ',$keterangan);
|
||||||
$notifikasi = [
|
$keterangan = preg_replace('/\s*\n\s*/', "\n",$keterangan);
|
||||||
'title' => 'Permohonan : ' . $data->nomor_registrasi,
|
|
||||||
'message' => $message,
|
// Pecah teks per baris untuk diproses
|
||||||
];
|
$lines = explode("\n",$keterangan);
|
||||||
return $notifikasi;
|
$cleaned = [];
|
||||||
|
|
||||||
|
foreach ($lines as $line) {
|
||||||
|
$line = trim($line);
|
||||||
|
if (!empty($line)) {
|
||||||
|
// Format angka dalam format Rp. 123.456.789
|
||||||
|
$line = preg_replace_callback('/Rp\.\s*([\d.,]+)/', function($matches) {
|
||||||
|
$angka = str_replace(['.', ','], '', $matches[1]);
|
||||||
|
return 'Rp. ' . number_format((int)$angka, 0, ',', '.');
|
||||||
|
}, $line);
|
||||||
|
|
||||||
|
// Jika ada tanda pagar (#), pisahkan menjadi baris baru
|
||||||
|
$line = str_replace('#', "\n#", $line);
|
||||||
|
|
||||||
|
$cleaned[] = $line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return implode("\n", $cleaned);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get full path to internal storage file or external storage file
|
||||||
|
*
|
||||||
|
* @param string $path
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
|
||||||
|
function getFilePath($path)
|
||||||
|
{
|
||||||
|
// define base path external storage (use .env) example: 'F:\path\to\storage' in windows
|
||||||
|
$externalBase = env('EXTERNAL_STORAGE_BASE_PATH', 'F:LPJ/lpj/LPJ Gambar/001/');
|
||||||
|
|
||||||
|
$segments = explode('/', $path);
|
||||||
|
|
||||||
|
if(strtoupper($segments[0]) === 'SURVEYOR'){
|
||||||
|
$year = $segments[1];
|
||||||
|
$month = ucfirst(strtolower($segments[2]));
|
||||||
|
$date = $segments[3];
|
||||||
|
$code = $segments[4];
|
||||||
|
$file = $segments[5] ?? '';
|
||||||
|
|
||||||
|
$extenalFullpath = $externalBase . $year . '/' . $month . '/' . $date . '/' . $code . '/' . $file;
|
||||||
|
|
||||||
|
if(File::exists($extenalFullpath)){
|
||||||
|
return $extenalFullpath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if not found in external storage, try to find in internal storage
|
||||||
|
if (Storage::exists($path)) {
|
||||||
|
return Storage::url('app/' . $path);
|
||||||
|
}
|
||||||
|
return $path;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function parseTimestamp(?string $timestamp): ?string
|
||||||
|
{
|
||||||
|
if (!$timestamp) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trim whitespace dan normalize
|
||||||
|
$timestamp = trim($timestamp);
|
||||||
|
|
||||||
|
// Log untuk debugging
|
||||||
|
Log::info('Mencoba parsing timestamp: "' . $timestamp . '"');
|
||||||
|
|
||||||
|
// Parsing dengan DateTime native PHP untuk lebih robust
|
||||||
|
try {
|
||||||
|
// Pattern untuk format d/m/Y H:i:s
|
||||||
|
if (preg_match('/^(\d{1,2})\/(\d{1,2})\/(\d{4})\s+(\d{1,2}):(\d{1,2}):(\d{1,2})$/', $timestamp, $matches)) {
|
||||||
|
$day = (int) $matches[1];
|
||||||
|
$month = (int) $matches[2];
|
||||||
|
$year = (int) $matches[3];
|
||||||
|
$hour = (int) $matches[4];
|
||||||
|
$minute = (int) $matches[5];
|
||||||
|
$second = (int) $matches[6];
|
||||||
|
|
||||||
|
// Validasi nilai
|
||||||
|
if ($day >= 1 && $day <= 31 && $month >= 1 && $month <= 12 && $year >= 1900 && $year <= 2100 &&
|
||||||
|
$hour >= 0 && $hour <= 23 && $minute >= 0 && $minute <= 59 && $second >= 0 && $second <= 59) {
|
||||||
|
|
||||||
|
// Buat DateTime object langsung
|
||||||
|
$dateTime = new \DateTime();
|
||||||
|
$dateTime->setDate($year, $month, $day);
|
||||||
|
$dateTime->setTime($hour, $minute, $second);
|
||||||
|
|
||||||
|
$result = $dateTime->format('Y-m-d H:i:s');
|
||||||
|
Log::info('Berhasil parsing dengan DateTime: ' . $timestamp . ' -> ' . $result);
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pattern untuk format d/m/Y tanpa waktu
|
||||||
|
if (preg_match('/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/', $timestamp, $matches)) {
|
||||||
|
$day = (int) $matches[1];
|
||||||
|
$month = (int) $matches[2];
|
||||||
|
$year = (int) $matches[3];
|
||||||
|
|
||||||
|
// Validasi nilai
|
||||||
|
if ($day >= 1 && $day <= 31 && $month >= 1 && $month <= 12 && $year >= 1900 && $year <= 2100) {
|
||||||
|
|
||||||
|
// Buat DateTime object langsung
|
||||||
|
$dateTime = new \DateTime();
|
||||||
|
$dateTime->setDate($year, $month, $day);
|
||||||
|
$dateTime->setTime(0, 0, 0);
|
||||||
|
|
||||||
|
$result = $dateTime->format('Y-m-d H:i:s');
|
||||||
|
Log::info('Berhasil parsing tanpa waktu dengan DateTime: ' . $timestamp . ' -> ' . $result);
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::error('Gagal parsing dengan DateTime: ' . $timestamp . '. Error: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback ke format Carbon standar untuk format lainnya
|
||||||
|
$formats = [
|
||||||
|
'Y-m-d H:i:s',
|
||||||
|
'Y-m-d',
|
||||||
|
'd-m-Y H:i:s',
|
||||||
|
'd-m-Y',
|
||||||
|
'j-n-Y H:i:s',
|
||||||
|
'j-n-Y',
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($formats as $format) {
|
||||||
|
try {
|
||||||
|
$carbon = \Carbon\Carbon::createFromFormat($format, $timestamp);
|
||||||
|
|
||||||
|
if ($carbon && $carbon->format($format) === $timestamp) {
|
||||||
|
// Jika format tidak mengandung waktu, set ke awal hari
|
||||||
|
if (!str_contains($format, 'H:i:s')) {
|
||||||
|
$carbon = $carbon->startOfDay();
|
||||||
|
}
|
||||||
|
Log::info('Berhasil parsing dengan format ' . $format . ': ' . $timestamp . ' -> ' . $carbon->toDateTimeString());
|
||||||
|
return $carbon->toDateTimeString();
|
||||||
|
}
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
// Lanjut ke format berikutnya
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::error('Tidak dapat memparsing timestamp dengan format apapun: "' . $timestamp . '"');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!function_exists('resize_image')) {
|
||||||
|
/**
|
||||||
|
* Merubah ukuran gambar secara on-the-fly dan mengembalikan path-nya.
|
||||||
|
*
|
||||||
|
* @param string $path Path asli gambar.
|
||||||
|
* @param int|null $width Lebar yang diinginkan.
|
||||||
|
* @param int|null $height Tinggi yang diinginkan (opsional, akan menjaga rasio aspek jika null).
|
||||||
|
* @param int $quality Kualitas gambar (1-100).
|
||||||
|
* @return string Path gambar yang sudah di-resize.
|
||||||
|
*/
|
||||||
|
function resize_image(string $path, ?int $width, ?int $height = null, int $quality = 80): string
|
||||||
|
{
|
||||||
|
|
||||||
|
return app(ImageResizeService::class)->resize($path, $width, $height, $quality);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
32
app/Http/Controllers/# Run on VM.sh
Normal file
32
app/Http/Controllers/# Run on VM.sh
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
# Run on VM
|
||||||
|
rclone hashsum MD5 "gdrive:01_Data Mentah/itdel/bawang_putih/BPM1" --drive-shared-with-me --output-file itdel_bawang_putih_gdrive.txt
|
||||||
|
rclone hashsum MD5 "gcs:transit_bucket_ysds/itdel/BPM1" --output-file itdel_bawang_putih_gcs.txt
|
||||||
|
rclone check --checksum "gcs:transit_bucket_ysds/itdel/BPM1" "gdrive:01_Data Mentah/itdel/bawang_putih/BPM1" --drive-shared-with-me --combined="itdel_bawang_putih_cheksum_bucket_drive.txt" --log-file="itdel_bawang_putih_count_checksum_bucket_drive.txt"
|
||||||
|
# Run on Local Machine
|
||||||
|
rclone hashsum MD5 "/data/storageserver/0.RAW/WGS/revio call/Raw/itdel/bawang_putih/BPM1" --output-file itdel_bawang_putih_local.txt
|
||||||
|
rclone check --checksum "/data/storageserver/0.RAW/WGS/revio call/Raw/itdel/bawang_putih/BPM1" "gdrive:01_Data Mentah/itdel/bawang_putih/BPM1" --drive-shared-with-me --combined="itdel_bawang_putih_checksum_local_gdrive.txt" --log-file="itdel_bawang_putih_count_checksum_local_gdrive.txt"
|
||||||
|
|
||||||
|
# Run on VM
|
||||||
|
rclone hashsum MD5 "gdrive:01_Data Mentah/itdel/kemenyan" --drive-shared-with-me --output-file itdel_kemenyan_gdrive.txt
|
||||||
|
rclone hashsum MD5 "gcs:transit_bucket_ysds/itdel/kemenyan" --output-file itdel_kemenyan_gcs.txt
|
||||||
|
rclone check --checksum "gcs:transit_bucket_ysds/itdel/kemenyan" "gdrive:01_Data Mentah/itdel/kemenyan" --drive-shared-with-me --combined="itdel_kemenyan_checksum_bucket_drive.txt" --log-file="itdel_kemenyan_count_checksum_bucket_drive.txt"
|
||||||
|
# Run on Local Machine
|
||||||
|
rclone hashsum MD5 "/data/storageserver/0.RAW/WGS/revio call/Raw/itdel/kemenyan" --output-file itdel_kemenyan_local.txt
|
||||||
|
rclone check --checksum "/data/storageserver/0.RAW/WGS/revio call/Raw/itdel/kemenyan" "gdrive:01_Data Mentah/itdel/kemenyan" --drive-shared-with-me --combined="itdel_kemenyan_checksum_local_gdrive.txt" --log-file="itdel_kemenyan_count_checksum_local_gdrive.txt"
|
||||||
|
|
||||||
|
# Run on VM
|
||||||
|
rclone hashsum MD5 "gdrive:01_Data Mentah/ugm/prima/bawang_putih" --drive-shared-with-me --output-file ugm_prima_bawang_putih_gdrive.txt
|
||||||
|
rclone hashsum MD5 "gcs:transit_bucket_ysds/bawang_putih_prima_UGM" --output-file ugm_prima_bawang_putih_gcs.txt
|
||||||
|
rclone check --checksum "gcs:transit_bucket_ysds/bawang_putih_prima_UGM" "gdrive:01_Data Mentah/ugm/prima/bawang_putih" --drive-shared-with-me --combined="ugm_prima_bawang_putih_checksum_bucket_drive.txt" --log-file="ugm_prima_bawang_putih_count_checksum_bucket_drive.txt"
|
||||||
|
# Run on Local Machine
|
||||||
|
rclone hashsum MD5 "/data/storageserver/0.RAW/WGS/revio call/Raw/bawang_putih" --output-file ugm_prima_bawang_putih_local.txt
|
||||||
|
rclone check --checksum "/data/storageserver/0.RAW/WGS/revio call/Raw/bawang_putih" "gdrive:01_Data Mentah/ugm/prima/bawang_putih" --drive-shared-with-me --combined="ugm_prima_bawang_putih_checksum_local_gdrive.txt" --log-file="ugm_prima_bawang_putih_count_checksum_local_gdrive.txt"
|
||||||
|
|
||||||
|
|
||||||
|
# Run on VM
|
||||||
|
rclone hashsum MD5 "gdrive:01_Data Mentah/polije/netty/bawang_merah" --drive-shared-with-me --output-file polije_netty_bawang_merah_gdrive.txt
|
||||||
|
rclone hashsum MD5 "gcs:transit_bucket_ysds/bawang_merah_netty_polije" --output-file polije_netty_bawang_merah_gcs.txt
|
||||||
|
rclone check --checksum "gcs:transit_bucket_ysds/bawang_merah_netty_polije" "gdrive:01_Data Mentah/polije/netty/bawang_merah" --drive-shared-with-me --combined="polije_netty_bawang_merah_checksum_bucket_drive.txt" --log-file="polije_netty_bawang_merah_count_checksum_bucket_drive.txt"
|
||||||
|
# Run on Local Machine
|
||||||
|
rclone hashsum MD5 "/data/storageserver/0.RAW/WGS/revio call/Raw/bawang_merah" --output-file polije_netty_bawang_merah_local.txt
|
||||||
|
rclone check --checksum "/data/storageserver/0.RAW/WGS/revio call/Raw/bawang_merah" "gdrive:01_Data Mentah/polije/netty/bawang_merah" --drive-shared-with-me --combined="polije_netty_bawang_merah_checksum_local_gdrive.txt" --log-file="polije_netty_bawang_merah_count_checksum_local_gdrive.txt"
|
||||||
@@ -306,6 +306,7 @@ class ActivityController extends Controller
|
|||||||
$query = Permohonan::query();
|
$query = Permohonan::query();
|
||||||
|
|
||||||
// Apply search filter if provided
|
// Apply search filter if provided
|
||||||
|
$query = $query->orderBy('nomor_registrasi', 'desc');
|
||||||
if ($request->has('search') && !empty($request->get('search'))) {
|
if ($request->has('search') && !empty($request->get('search'))) {
|
||||||
$search = $request->get('search');
|
$search = $request->get('search');
|
||||||
$query->where(function ($q) use ($search) {
|
$query->where(function ($q) use ($search) {
|
||||||
@@ -324,7 +325,9 @@ class ActivityController extends Controller
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default sorting if no sort provided
|
|
||||||
|
|
||||||
|
// Apply sorting if provided
|
||||||
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
|
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
|
||||||
$order = $request->get('sortOrder');
|
$order = $request->get('sortOrder');
|
||||||
$column = $request->get('sortField');
|
$column = $request->get('sortField');
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
namespace Modules\Lpj\Http\Controllers;
|
namespace Modules\Lpj\Http\Controllers;
|
||||||
|
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Routing\Controller;
|
use Illuminate\Routing\Controller;
|
||||||
use Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use Modules\Location\Models\Province;
|
use Modules\Location\Models\Province;
|
||||||
use Modules\Lpj\Http\Requests\BankDataRequest;
|
use Modules\Lpj\Http\Requests\BankDataRequest;
|
||||||
use Modules\Lpj\Models\BankData;
|
use Modules\Lpj\Models\BankData;
|
||||||
@@ -88,7 +88,8 @@
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Invalid coordinates
|
// Invalid coordinates
|
||||||
Log::warning("Invalid coordinates: Lat: $_lat, Lng: $_lng");// Do something to handle this situation, such as logging an error or skipping the record
|
Log::warning("Invalid coordinates: Lat: $_lat, Lng: $_lng");
|
||||||
|
// Do something to handle this situation, such as logging an error or skipping the record
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,7 +139,8 @@
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Invalid coordinates
|
// Invalid coordinates
|
||||||
Log::warning("Invalid coordinates: Lat: $lat, Lng: $lng");// Do something to handle this situation, such as logging an error or skipping the record
|
Log::warning("Invalid coordinates: Lat: $lat, Lng: $lng");
|
||||||
|
// Do something to handle this situation, such as logging an error or skipping the record
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -197,6 +199,24 @@
|
|||||||
// Retrieve data from the database
|
// Retrieve data from the database
|
||||||
$query = BankData::query();
|
$query = BankData::query();
|
||||||
|
|
||||||
|
// Check if show_all parameter is set
|
||||||
|
$showAll = $request->has('show_all') && $request->get('show_all') === 'true';
|
||||||
|
|
||||||
|
// If show_all is true, we'll get all data without pagination
|
||||||
|
if ($showAll) {
|
||||||
|
// Get all records without pagination
|
||||||
|
$data = $query->get();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'data' => $data,
|
||||||
|
'recordsTotal' => $data->count(),
|
||||||
|
'recordsFiltered' => $data->count(),
|
||||||
|
'page' => 1,
|
||||||
|
'pageSize' => $data->count(),
|
||||||
|
'total' => 1
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
// Apply search filter if provided
|
// Apply search filter if provided
|
||||||
if ($request->has('search') && !empty($request->get('search'))) {
|
if ($request->has('search') && !empty($request->get('search'))) {
|
||||||
$search = $request->get('search');
|
$search = $request->get('search');
|
||||||
@@ -252,8 +272,10 @@
|
|||||||
// Get the total count of records
|
// Get the total count of records
|
||||||
$totalRecords = $query->count();
|
$totalRecords = $query->count();
|
||||||
|
|
||||||
// Apply pagination if provided
|
// Apply pagination only if explicitly requested or not first load
|
||||||
if ($request->has('page') && $request->has('size')) {
|
$shouldPaginate = $request->has('page') && $request->has('size') && !$request->has('show_all');
|
||||||
|
|
||||||
|
if ($shouldPaginate) {
|
||||||
$page = $request->get('page');
|
$page = $request->get('page');
|
||||||
$size = $request->get('size');
|
$size = $request->get('size');
|
||||||
$offset = ($page - 1) * $size; // Calculate the offset
|
$offset = ($page - 1) * $size; // Calculate the offset
|
||||||
@@ -287,11 +309,11 @@
|
|||||||
];
|
];
|
||||||
});
|
});
|
||||||
|
|
||||||
// Calculate the page count
|
// Calculate the page count (1 if showing all data)
|
||||||
$pageCount = ceil($totalRecords / $request->get('size'));
|
$pageCount = $shouldPaginate ? ceil($totalRecords / $request->get('size')) : 1;
|
||||||
|
|
||||||
// Calculate the current page number
|
// Calculate the current page number
|
||||||
$currentPage = $request->get('page', 1);
|
$currentPage = $shouldPaginate ? $request->get('page', 1) : 1;
|
||||||
|
|
||||||
// Ensure current page doesn't exceed page count
|
// Ensure current page doesn't exceed page count
|
||||||
$currentPage = min($currentPage, $pageCount);
|
$currentPage = min($currentPage, $pageCount);
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ use Illuminate\Http\Request;
|
|||||||
use Modules\Lpj\Models\CategoryDaftarPustaka;
|
use Modules\Lpj\Models\CategoryDaftarPustaka;
|
||||||
use Modules\Lpj\Services\DaftarPustakaService;
|
use Modules\Lpj\Services\DaftarPustakaService;
|
||||||
use Modules\Lpj\Http\Requests\DaftarPustakaRequest;
|
use Modules\Lpj\Http\Requests\DaftarPustakaRequest;
|
||||||
|
use Exception;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
class DaftarPustakaController extends Controller
|
class DaftarPustakaController extends Controller
|
||||||
{
|
{
|
||||||
@@ -22,7 +24,15 @@ class DaftarPustakaController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function index(Request $request)
|
public function index(Request $request)
|
||||||
{
|
{
|
||||||
$categories = CategoryDaftarPustaka::all();
|
// Get categories with count of daftar pustaka
|
||||||
|
try {
|
||||||
|
$categories = CategoryDaftarPustaka::withCount('daftarPustaka')->get();
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
// Handle jika tabel belum ada atau error lainnya
|
||||||
|
Log::warning('Error loading categories with count: ' . $e->getMessage());
|
||||||
|
$categories = CategoryDaftarPustaka::get(); // Fallback tanpa count
|
||||||
|
}
|
||||||
|
|
||||||
$daftar_pustaka = $this->daftarPustaka->getAllDaftarPustaka($request);
|
$daftar_pustaka = $this->daftarPustaka->getAllDaftarPustaka($request);
|
||||||
|
|
||||||
return view('lpj::daftar-pustaka.index', [
|
return view('lpj::daftar-pustaka.index', [
|
||||||
|
|||||||
@@ -129,7 +129,7 @@
|
|||||||
// Retrieve data from the database
|
// Retrieve data from the database
|
||||||
$query = Debiture::query();
|
$query = Debiture::query();
|
||||||
|
|
||||||
if (!Auth::user()->hasAnyRole(['administrator'])) {
|
if (!Auth::user()->hasAnyRole(['administrator','admin'])) {
|
||||||
$query = $query->where('branch_id', Auth::user()->branch_id);
|
$query = $query->where('branch_id', Auth::user()->branch_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -406,7 +406,9 @@
|
|||||||
|
|
||||||
|
|
||||||
// Remove values from $legalitasJaminan that are in $currentLegalitasJaminan
|
// Remove values from $legalitasJaminan that are in $currentLegalitasJaminan
|
||||||
$legalitasJaminan = array_diff($legalitasJaminan, $currentLegalitasJaminan->pluck('code')->toArray());
|
$legalitasJaminan = is_array($legalitasJaminan)
|
||||||
|
? array_diff($legalitasJaminan, $currentLegalitasJaminan->pluck('code')->toArray())
|
||||||
|
: [];
|
||||||
|
|
||||||
$legalitas = JenisLegalitasJaminan::whereIn('code', $legalitasJaminan)->get();
|
$legalitas = JenisLegalitasJaminan::whereIn('code', $legalitasJaminan)->get();
|
||||||
}
|
}
|
||||||
@@ -441,7 +443,7 @@
|
|||||||
try {
|
try {
|
||||||
// Periksa apakah pengguna adalah admin
|
// Periksa apakah pengguna adalah admin
|
||||||
if (!auth()->user()->hasRole('administrator')) {
|
if (!auth()->user()->hasRole('administrator')) {
|
||||||
return response()->json(['success' => false, 'message' => 'Hanya administrator yang dapat menghapus dokumen jaminan'], 403);
|
//return response()->json(['success' => false, 'message' => 'Hanya administrator yang dapat menghapus dokumen jaminan'], 403);
|
||||||
}
|
}
|
||||||
|
|
||||||
$jaminan = DokumenJaminan::find($jaminan_id);
|
$jaminan = DokumenJaminan::find($jaminan_id);
|
||||||
@@ -451,8 +453,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Periksa apakah dokumen jaminan terkait dengan permohonan aktif
|
// Periksa apakah dokumen jaminan terkait dengan permohonan aktif
|
||||||
if ($jaminan->permohonan()->exists()) {
|
if ($jaminan->permohonan()->exists() && !in_array($jaminan->permohonan->status,['order','revisi'])) {
|
||||||
return response()->json(['success' => false, 'message' => 'Tidak dapat menghapus dokumen jaminan yang terkait dengan permohonan aktif'], 400);
|
// return response()->json(['success' => false, 'message' => 'Tidak dapat menghapus dokumen jaminan yang terkait dengan permohonan aktif'], 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
DB::beginTransaction();
|
DB::beginTransaction();
|
||||||
|
|||||||
239
app/Http/Controllers/InspeksiController.php
Normal file
239
app/Http/Controllers/InspeksiController.php
Normal file
@@ -0,0 +1,239 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Lpj\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Modules\Lpj\Models\Inspeksi;
|
||||||
|
use Modules\Lpj\Services\InspeksiCleanupService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controller contoh untuk menunjukkan penggunaan InspeksiCleanupService
|
||||||
|
*
|
||||||
|
* Controller ini berisi contoh method untuk membuat dan update data inspeksi
|
||||||
|
* dengan otomatis menjalankan cleanup data lama yang tidak memiliki dokument_id
|
||||||
|
*/
|
||||||
|
class InspeksiController extends Controller
|
||||||
|
{
|
||||||
|
protected InspeksiCleanupService $cleanupService;
|
||||||
|
|
||||||
|
public function __construct(InspeksiCleanupService $cleanupService)
|
||||||
|
{
|
||||||
|
$this->cleanupService = $cleanupService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contoh method untuk membuat data inspeksi baru
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @return \Illuminate\Http\JsonResponse
|
||||||
|
*/
|
||||||
|
public function store(Request $request)
|
||||||
|
{
|
||||||
|
$validated = $request->validate([
|
||||||
|
'permohonan_id' => 'required|integer|exists:permohonan,id',
|
||||||
|
'dokument_id' => 'nullable|integer|exists:dokumen_jaminan,id',
|
||||||
|
'data_form' => 'required|json',
|
||||||
|
'foto_form' => 'nullable|json',
|
||||||
|
'denah_form' => 'nullable|json',
|
||||||
|
'name' => 'required|string|max:255',
|
||||||
|
'status' => 'required|string|max:50',
|
||||||
|
]);
|
||||||
|
|
||||||
|
DB::beginTransaction();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Buat data inspeksi baru
|
||||||
|
$inspeksi = Inspeksi::create(array_merge($validated, [
|
||||||
|
'created_by' => Auth::id(),
|
||||||
|
'updated_by' => Auth::id(),
|
||||||
|
]));
|
||||||
|
|
||||||
|
Log::info('InspeksiController: Data inspeksi berhasil dibuat', [
|
||||||
|
'inspeksi_id' => $inspeksi->id,
|
||||||
|
'permohonan_id' => $inspeksi->permohonan_id,
|
||||||
|
'dokument_id' => $inspeksi->dokument_id,
|
||||||
|
'created_by' => $inspeksi->created_by
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Commit transaksi utama
|
||||||
|
DB::commit();
|
||||||
|
|
||||||
|
// Jalankan cleanup secara async jika ada dokument_id
|
||||||
|
// Ini akan menghapus data lama yang tidak memiliki dokument_id
|
||||||
|
if ($inspeksi->dokument_id) {
|
||||||
|
Log::info('InspeksiController: Memulai cleanup data lama', [
|
||||||
|
'permohonan_id' => $inspeksi->permohonan_id,
|
||||||
|
'created_by' => $inspeksi->created_by,
|
||||||
|
'dokument_id' => $inspeksi->dokument_id
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Dispatch job cleanup secara async
|
||||||
|
$this->cleanupService->cleanupAsync(
|
||||||
|
$inspeksi->permohonan_id,
|
||||||
|
$inspeksi->created_by,
|
||||||
|
$inspeksi->dokument_id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true,
|
||||||
|
'message' => 'Data inspeksi berhasil dibuat',
|
||||||
|
'data' => $inspeksi->load(['permohonan', 'dokument'])
|
||||||
|
], 201);
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
DB::rollBack();
|
||||||
|
|
||||||
|
Log::error('InspeksiController: Gagal membuat data inspeksi', [
|
||||||
|
'error' => $e->getMessage(),
|
||||||
|
'trace' => $e->getTraceAsString()
|
||||||
|
]);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => false,
|
||||||
|
'message' => 'Gagal membuat data inspeksi: ' . $e->getMessage()
|
||||||
|
], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contoh method untuk update data inspeksi
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @param int $id
|
||||||
|
* @return \Illuminate\Http\JsonResponse
|
||||||
|
*/
|
||||||
|
public function update(Request $request, $id)
|
||||||
|
{
|
||||||
|
$validated = $request->validate([
|
||||||
|
'dokument_id' => 'nullable|integer|exists:dokumen_jaminan,id',
|
||||||
|
'data_form' => 'required|json',
|
||||||
|
'foto_form' => 'nullable|json',
|
||||||
|
'denah_form' => 'nullable|json',
|
||||||
|
'name' => 'required|string|max:255',
|
||||||
|
'status' => 'required|string|max:50',
|
||||||
|
]);
|
||||||
|
|
||||||
|
DB::beginTransaction();
|
||||||
|
|
||||||
|
try {
|
||||||
|
$inspeksi = Inspeksi::findOrFail($id);
|
||||||
|
|
||||||
|
// Simpan data lama untuk logging
|
||||||
|
$oldDokumentId = $inspeksi->dokument_id;
|
||||||
|
|
||||||
|
// Update data
|
||||||
|
$inspeksi->update(array_merge($validated, [
|
||||||
|
'updated_by' => Auth::id(),
|
||||||
|
]));
|
||||||
|
|
||||||
|
Log::info('InspeksiController: Data inspeksi berhasil diupdate', [
|
||||||
|
'inspeksi_id' => $inspeksi->id,
|
||||||
|
'permohonan_id' => $inspeksi->permohonan_id,
|
||||||
|
'old_dokument_id' => $oldDokumentId,
|
||||||
|
'new_dokument_id' => $inspeksi->dokument_id,
|
||||||
|
'updated_by' => $inspeksi->updated_by
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Commit transaksi utama
|
||||||
|
DB::commit();
|
||||||
|
|
||||||
|
// Jalankan cleanup jika dokument_id berubah dari null ke ada nilai
|
||||||
|
if (!$oldDokumentId && $inspeksi->dokument_id) {
|
||||||
|
Log::info('InspeksiController: Dokument ID berubah dari null, memulai cleanup', [
|
||||||
|
'inspeksi_id' => $inspeksi->id,
|
||||||
|
'permohonan_id' => $inspeksi->permohonan_id,
|
||||||
|
'created_by' => $inspeksi->created_by,
|
||||||
|
'new_dokument_id' => $inspeksi->dokument_id
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Dispatch job cleanup secara async
|
||||||
|
$this->cleanupService->cleanupAsync(
|
||||||
|
$inspeksi->permohonan_id,
|
||||||
|
$inspeksi->created_by,
|
||||||
|
$inspeksi->dokument_id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true,
|
||||||
|
'message' => 'Data inspeksi berhasil diupdate',
|
||||||
|
'data' => $inspeksi->load(['permohonan', 'dokument'])
|
||||||
|
]);
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
DB::rollBack();
|
||||||
|
|
||||||
|
Log::error('InspeksiController: Gagal update data inspeksi', [
|
||||||
|
'inspeksi_id' => $id,
|
||||||
|
'error' => $e->getMessage(),
|
||||||
|
'trace' => $e->getTraceAsString()
|
||||||
|
]);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => false,
|
||||||
|
'message' => 'Gagal update data inspeksi: ' . $e->getMessage()
|
||||||
|
], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contoh method untuk menjalankan cleanup secara manual
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @return \Illuminate\Http\JsonResponse
|
||||||
|
*/
|
||||||
|
public function cleanup(Request $request)
|
||||||
|
{
|
||||||
|
$validated = $request->validate([
|
||||||
|
'permohonan_id' => 'required|integer|exists:permohonan,id',
|
||||||
|
'created_by' => 'required|integer|exists:users,id',
|
||||||
|
'sync' => 'boolean', // Opsional, default false (async)
|
||||||
|
]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$permohonanId = $validated['permohonan_id'];
|
||||||
|
$createdBy = $validated['created_by'];
|
||||||
|
$sync = $validated['sync'] ?? false;
|
||||||
|
|
||||||
|
Log::info('InspeksiController: Menjalankan cleanup manual', [
|
||||||
|
'permohonan_id' => $permohonanId,
|
||||||
|
'created_by' => $createdBy,
|
||||||
|
'sync' => $sync
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($sync) {
|
||||||
|
// Jalankan secara sync
|
||||||
|
$this->cleanupService->cleanupSync($permohonanId, $createdBy);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true,
|
||||||
|
'message' => 'Cleanup selesai dijalankan secara synchronous'
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
// Dispatch ke queue
|
||||||
|
$this->cleanupService->cleanupAsync($permohonanId, $createdBy);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true,
|
||||||
|
'message' => 'Cleanup job berhasil di-dispatch ke queue'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::error('InspeksiController: Gagal menjalankan cleanup manual', [
|
||||||
|
'error' => $e->getMessage(),
|
||||||
|
'trace' => $e->getTraceAsString()
|
||||||
|
]);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => false,
|
||||||
|
'message' => 'Gagal menjalankan cleanup: ' . $e->getMessage()
|
||||||
|
], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,7 +16,6 @@ class LaporanController extends Controller
|
|||||||
* Display a listing of the resource.
|
* Display a listing of the resource.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
public function __construct(PenilaiController $penilaiController){
|
public function __construct(PenilaiController $penilaiController){
|
||||||
$this->penilaiController = $penilaiController;
|
$this->penilaiController = $penilaiController;
|
||||||
}
|
}
|
||||||
@@ -76,14 +75,8 @@ class LaporanController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve data from the database
|
// Retrieve data from the database
|
||||||
$query = Permohonan::query()->whereIn('status',['proses-laporan','done', 'paparan', 'proses-paparan'])
|
$query = Permohonan::query()
|
||||||
->whereNotNull('approval_so_at');
|
->whereIn('status',['proses-laporan','done', 'paparan', 'proses-paparan']);
|
||||||
/*->whereNotNull('approval_eo_at')
|
|
||||||
->where(function ($q) {
|
|
||||||
$q->whereIn('nilai_plafond_id', [1,4])
|
|
||||||
->whereNotNull('approval_dd_at')
|
|
||||||
->orWhereIn('nilai_plafond_id', [2,3]);
|
|
||||||
});*/
|
|
||||||
|
|
||||||
if (Auth::user()->hasAnyRole(['pemohon-ao','pemohon-eo'])) {
|
if (Auth::user()->hasAnyRole(['pemohon-ao','pemohon-eo'])) {
|
||||||
$query = $query->where('branch_id', Auth::user()->branch_id);
|
$query = $query->where('branch_id', Auth::user()->branch_id);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
use Maatwebsite\Excel\Facades\Excel;
|
use Maatwebsite\Excel\Facades\Excel;
|
||||||
use Modules\Lpj\Exports\LaporanHasilPenilaianJaminanInternalExternalExport;
|
use Modules\Lpj\Exports\LaporanHasilPenilaianJaminanInternalExternalExport;
|
||||||
use Modules\Lpj\Models\Permohonan;
|
use Modules\Lpj\Models\Permohonan;
|
||||||
@@ -60,6 +61,7 @@
|
|||||||
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $search->search . '%');
|
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $search->search . '%');
|
||||||
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search->search . '%');
|
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search->search . '%');
|
||||||
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search->search . '%');
|
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search->search . '%');
|
||||||
|
$q->orWhereRelation('debiture', DB::raw('LOWER(name)'), 'LIKE', '%' . strtolower($search->search) . '%');
|
||||||
$q->orWhereRelation('jenisFasilitasKredit', 'name', 'LIKE', '%' . $search->search . '%');
|
$q->orWhereRelation('jenisFasilitasKredit', 'name', 'LIKE', '%' . $search->search . '%');
|
||||||
$q->orWhereRelation('jenisPenilaian', 'name', 'LIKE', '%' . $search->search . '%');
|
$q->orWhereRelation('jenisPenilaian', 'name', 'LIKE', '%' . $search->search . '%');
|
||||||
$q->orWhere('status', 'LIKE', '%' . $search->search . '%');
|
$q->orWhere('status', 'LIKE', '%' . $search->search . '%');
|
||||||
@@ -69,7 +71,7 @@
|
|||||||
|
|
||||||
// Apply sorting if provided
|
// Apply sorting if provided
|
||||||
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
|
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
|
||||||
$order = $request->get('sortOrder');
|
$order = $request->get('sortOrder');
|
||||||
$column = $request->get('sortField');
|
$column = $request->get('sortField');
|
||||||
$query->orderBy($column, $order);
|
$query->orderBy($column, $order);
|
||||||
}
|
}
|
||||||
@@ -104,12 +106,12 @@
|
|||||||
$lpj = json_decode($permohonan->penilai->lpj, true);
|
$lpj = json_decode($permohonan->penilai->lpj, true);
|
||||||
$npw = str_replace('.', '', $lpj['total_nilai_pasar_wajar'] ?? 0);
|
$npw = str_replace('.', '', $lpj['total_nilai_pasar_wajar'] ?? 0);
|
||||||
|
|
||||||
$luas_tanah = $lpj['luas_tanah'] ?? 0;
|
$luas_tanah = $lpj['luas_tanah'] ?? 0;
|
||||||
$luas_bangunan = $lpj['luas_bangunan'] ?? 0;
|
$luas_bangunan = $lpj['luas_bangunan'] ?? 0;
|
||||||
// Calculate nilai_tanah dynamically by looking for all keys that start with 'nilai_tanah_'
|
// Calculate nilai_tanah dynamically by looking for all keys that start with 'nilai_tanah_'
|
||||||
$nilai_tanah = str_replace('.', '', $lpj['nilai_tanah_2'] ?? 0);
|
$nilai_tanah = str_replace('.', '', $lpj['nilai_tanah_2'] ?? 0);
|
||||||
|
|
||||||
$nilai_bangunan = str_replace('.', '', $lpj['nilai_bangunan_2'] ?? 0);
|
$nilai_bangunan = str_replace('.', '', $lpj['nilai_bangunan_2'] ?? 0);
|
||||||
$nilai_liquidasi = str_replace('.', '', $lpj['likuidasi_nilai_2'] ?? 0);
|
$nilai_liquidasi = str_replace('.', '', $lpj['likuidasi_nilai_2'] ?? 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,10 @@ use Modules\Lpj\Models\Permohonan;
|
|||||||
use Modules\Lpj\Models\StatusPermohonan;
|
use Modules\Lpj\Models\StatusPermohonan;
|
||||||
use Modules\Lpj\Exports\LaporanPenilaiJaminanExport;
|
use Modules\Lpj\Exports\LaporanPenilaiJaminanExport;
|
||||||
use Maatwebsite\Excel\Facades\Excel;
|
use Maatwebsite\Excel\Facades\Excel;
|
||||||
|
use Modules\Lpj\Models\Branch;
|
||||||
|
use Modules\Lpj\Services\PreviewLaporanService;
|
||||||
|
use Modules\Lpj\Models\Inspeksi;
|
||||||
|
use Modules\Lpj\Models\Penilai;
|
||||||
|
|
||||||
class LaporanPenilaiJaminanController extends Controller
|
class LaporanPenilaiJaminanController extends Controller
|
||||||
{
|
{
|
||||||
@@ -16,59 +20,31 @@ class LaporanPenilaiJaminanController extends Controller
|
|||||||
/**
|
/**
|
||||||
* Display a listing of the resource.
|
* Display a listing of the resource.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
protected $previewLaporanService;
|
||||||
|
|
||||||
|
public function __construct(PreviewLaporanService $previewLaporanService)
|
||||||
|
{
|
||||||
|
$this->previewLaporanService = $previewLaporanService;
|
||||||
|
}
|
||||||
|
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
$status_permohonan = StatusPermohonan::all();
|
$status_permohonan = StatusPermohonan::all();
|
||||||
return view('lpj::laporan-penilai-jaminan.index', compact('status_permohonan'));
|
return view('lpj::laporan-penilai-jaminan.index', compact('status_permohonan'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the form for creating a new resource.
|
|
||||||
*/
|
|
||||||
public function create()
|
|
||||||
{
|
|
||||||
return view('lpj::create');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Store a newly created resource in storage.
|
|
||||||
*/
|
|
||||||
public function store(Request $request)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show the specified resource.
|
* Show the specified resource.
|
||||||
*/
|
*/
|
||||||
public function show($id)
|
public function show($permohonan_id, $dokumen_id, $jaminan_id)
|
||||||
{
|
{
|
||||||
return view('lpj::laporan-penilai-jaminan.show');
|
$back = route('laporan-penilai-jaminan.index');
|
||||||
|
return $this->previewLaporanService->previewLaporan($permohonan_id, $dokumen_id, $jaminan_id, $back);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the form for editing the specified resource.
|
|
||||||
*/
|
|
||||||
public function edit($id)
|
|
||||||
{
|
|
||||||
return view('lpj::edit');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the specified resource in storage.
|
|
||||||
*/
|
|
||||||
public function update(Request $request, $id)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the specified resource from storage.
|
|
||||||
*/
|
|
||||||
public function destroy($id)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
public function dataForDatatables(Request $request)
|
public function dataForDatatables(Request $request)
|
||||||
{
|
{
|
||||||
@@ -93,91 +69,104 @@ class LaporanPenilaiJaminanController extends Controller
|
|||||||
// dd($startDate);
|
// dd($startDate);
|
||||||
// Retrieve data from the database
|
// Retrieve data from the database
|
||||||
$query = Permohonan::query();
|
$query = Permohonan::query();
|
||||||
|
$query = $query->where('status', 'done')->orderBy('tanggal_permohonan', 'desc');
|
||||||
// Apply search filter if provided
|
// Apply search filter if provided
|
||||||
if ($request->has('search') && !empty($request->get('search'))) {
|
if ($request->has('search') && !empty($request->get('search'))) {
|
||||||
$search = $request->get('search');
|
$search = json_decode($request->get('search'));
|
||||||
$paramsSearch = json_decode($search);
|
|
||||||
|
|
||||||
$query->where(function ($q) use ($search) {
|
if (!empty($search->start_date) || !empty($search->end_date)) {
|
||||||
$q->where('nomor_registrasi', 'LIKE', '%' . $search . '%')
|
$startDate = $search->start_date ?? '1900-01-01';
|
||||||
->orWhere('tanggal_permohonan', 'LIKE', '%' . $search . '%')
|
$endDate = $search->end_date ?? now()->toDateString();
|
||||||
->orWhereRelation('user', 'name', 'LIKE', '%' . $search . '%')
|
|
||||||
->orWhereRelation('debiture', 'name', 'LIKE', '%' . $search . '%')
|
|
||||||
->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search . '%')
|
|
||||||
->orWhereRelation('branch', 'name', 'LIKE', '%' . $search . '%');
|
|
||||||
|
|
||||||
if (!empty($paramsSearch->tanggal_awal) && !empty($paramsSearch->tanggal_akhir)) {
|
$query->where(function ($q) use ($startDate, $endDate) {
|
||||||
$q->whereBetween('tanggal_permohonan', [$paramsSearch->tanggal_awal, $paramsSearch->tanggal_akhir]);
|
|
||||||
|
$q->whereHas('penilaian', function ($q2) use ($startDate, $endDate) {
|
||||||
|
$q2->whereBetween('tanggal_kunjungan', [$startDate, $endDate]);
|
||||||
|
});
|
||||||
|
|
||||||
|
// OR check if has penawaran with date in range
|
||||||
|
$q->orWhereHas('penawaran', function ($q3) use ($startDate, $endDate) {
|
||||||
|
$q3->whereBetween('tanggal_penilaian_sebelumnya', [$startDate, $endDate]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (isset($search->branch_id) && !empty($search->branch_id)) {
|
||||||
|
$query->where('branch_id', $search->branch_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($search->laporan) && is_array($search->laporan) && !empty($search->laporan)) {
|
||||||
|
foreach ($search->laporan as $type) {
|
||||||
|
$query->whereHas('penilai', function ($q) use ($type) {
|
||||||
|
$q->where('type_penilai', 'LIKE', '%' . $type . '%');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
$statusKeywords = explode(',', $search);
|
// dd($search->search);
|
||||||
foreach ($statusKeywords as $keyword) {
|
|
||||||
$q->orWhereRelation('penilai', 'type_penilai', 'LIKE', '%' . trim($keyword) . '%');
|
if (isset($search->search)) {
|
||||||
}
|
|
||||||
});
|
$query->where(function ($q) use ($search) {
|
||||||
|
$q->where('nomor_registrasi', 'LIKE', '%' . $search->search . '%');
|
||||||
|
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search->search . '%');
|
||||||
|
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $search->search . '%');
|
||||||
|
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search->search . '%');
|
||||||
|
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search->search . '%');
|
||||||
|
$q->orWhereRelation('debiture', DB::raw('LOWER(name)'), 'LIKE', '%' . strtolower($search->search) . '%');
|
||||||
|
|
||||||
|
$q->orWhereRelation('jenisFasilitasKredit', 'name', 'LIKE', '%' . $search->search . '%');
|
||||||
|
$q->orWhereRelation('jenisPenilaian', 'name', 'LIKE', '%' . $search->search . '%');
|
||||||
|
$q->orWhere('status', 'LIKE', '%' . $search->search . '%');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
$query->where('status', 'done');
|
|
||||||
|
|
||||||
|
// Apply sorting if provided
|
||||||
|
|
||||||
// Default sorting if no sort provided
|
|
||||||
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
|
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
|
||||||
$order = $request->get('sortOrder');
|
$order = $request->get('sortOrder');
|
||||||
$column = $request->get('sortField');
|
$column = $request->get('sortField');
|
||||||
$query->orderBy($column, $order);
|
$query->orderBy($column, $order);
|
||||||
} else {
|
|
||||||
$query->orderBy('nomor_registrasi', 'asc');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get total count of records before pagination
|
|
||||||
|
// Get the total count of records
|
||||||
$totalRecords = $query->count();
|
$totalRecords = $query->count();
|
||||||
|
|
||||||
// Pagination
|
// Apply pagination if provided
|
||||||
if ($request->has('page') && $request->has('size')) {
|
if ($request->has('page') && $request->has('size')) {
|
||||||
$page = (int) $request->get('page', 1);
|
$page = $request->get('page');
|
||||||
$size = (int) $request->get('size', 10);
|
$size = $request->get('size');
|
||||||
$offset = ($page - 1) * $size;
|
$offset = ($page - 1) * $size; // Calculate the offset
|
||||||
|
|
||||||
$query->skip($offset)->take($size);
|
$query->skip($offset)->take($size);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get filtered count
|
// Get the filtered count of records
|
||||||
$filteredRecords = $query->count();
|
$filteredRecords = $query->count();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$totalRecords = $query->count();
|
|
||||||
|
|
||||||
// Pagination
|
|
||||||
if ($request->has('page') && $request->has('size')) {
|
|
||||||
$page = (int) $request->get('page', 1);
|
|
||||||
$size = (int) $request->get('size', 10);
|
|
||||||
$offset = ($page - 1) * $size;
|
|
||||||
$query->skip($offset)->take($size);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get filtered count
|
|
||||||
$filteredRecords = $query->count();
|
|
||||||
|
|
||||||
// Get data with necessary relationships
|
// Get data with necessary relationships
|
||||||
$data = $query->with(['user', 'debiture', 'branch', 'tujuanPenilaian', 'penilaian', 'dokumenjaminan.jenisJaminan','nilaiPlafond', 'penilai'])->get();
|
$data = $query->with(['user', 'debiture', 'branch', 'tujuanPenilaian', 'penilaian', 'dokumenjaminan.jenisJaminan','nilaiPlafond', 'penilai', 'dokumenjaminan.inspeksi'])->get();
|
||||||
|
|
||||||
// Calculate total pages
|
// Calculate the page count
|
||||||
$pageCount = ceil($totalRecords / $request->get('size', 10));
|
$pageCount = ceil($totalRecords / $size);
|
||||||
|
|
||||||
|
// Calculate the current page number
|
||||||
|
$currentPage = max(1, $request->get('page', 1));
|
||||||
|
|
||||||
|
// Return the response data as a JSON object
|
||||||
|
|
||||||
// Calculate total pages
|
|
||||||
$pageCount = ceil($totalRecords / $request->get('size', 10));
|
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'draw' => $request->get('draw'),
|
'draw' => $request->get('draw'),
|
||||||
'recordsTotal' => $totalRecords,
|
'recordsTotal' => $totalRecords,
|
||||||
'recordsFiltered' => $filteredRecords,
|
'recordsFiltered' => $filteredRecords,
|
||||||
'pageCount' => $pageCount,
|
'pageCount' => $pageCount,
|
||||||
'page' => $request->get('page', 1),
|
'page' => $currentPage,
|
||||||
'totalCount' => $totalRecords,
|
'totalCount' => $totalRecords,
|
||||||
'data' => $data,
|
'data' => $data,
|
||||||
]);
|
]);
|
||||||
@@ -185,15 +174,53 @@ class LaporanPenilaiJaminanController extends Controller
|
|||||||
|
|
||||||
public function export(Request $request)
|
public function export(Request $request)
|
||||||
{
|
{
|
||||||
$tanggalAwal = $request->input('tanggal_awal');
|
$startDate = $request->input('start_date');
|
||||||
$tanggalAkhir = $request->input('tanggal_akhir');
|
$endDate = $request->input('end_date');
|
||||||
$status = $request->input('status');
|
|
||||||
$selectedIds = $request->input('selected_ids');
|
// Validate the date format
|
||||||
|
if (isset($startDate) && isset($endDate)) {
|
||||||
|
$startDate = date('Y-m-d', strtotime($startDate));
|
||||||
|
$endDate = date('Y-m-d', strtotime($endDate));
|
||||||
|
|
||||||
|
if ($startDate > $endDate) {
|
||||||
|
return redirect()->back()->with('error', 'Tanggal awal tidak boleh lebih kecil dari tanggal akhir');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// name the file
|
||||||
|
$filename = $this->createNameLaporan($request);
|
||||||
|
|
||||||
$filename = 'laporan_penilai_jaminan_' . date('YmdHis') . '.xlsx';
|
|
||||||
return Excel::download(
|
return Excel::download(
|
||||||
new LaporanPenilaiJaminanExport($tanggalAwal, $tanggalAkhir, $status, $selectedIds),
|
new LaporanPenilaiJaminanExport($request),
|
||||||
$filename
|
$filename
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function createNameLaporan($request)
|
||||||
|
{
|
||||||
|
$startDate = $request->start_date ?? null;
|
||||||
|
$endDate = $request->end_date ?? null;
|
||||||
|
$branchId = $request->branch_id ?? null;
|
||||||
|
$laporan = $request->laporan ?? null;
|
||||||
|
|
||||||
|
// Initialize filename parts
|
||||||
|
$parts = ['Laporan Penilai Jaminan'];
|
||||||
|
if ($startDate && $endDate) {
|
||||||
|
$parts[] = "{$startDate}_{$endDate}";
|
||||||
|
}
|
||||||
|
if ($laporan) {
|
||||||
|
$parts[] = $laporan;
|
||||||
|
}
|
||||||
|
if ($branchId) {
|
||||||
|
$parts[] = $this->getBranchId($branchId);
|
||||||
|
}
|
||||||
|
// Return concatenated filename with extension
|
||||||
|
return implode('_', $parts) . '.xlsx';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBranchId($branchId)
|
||||||
|
{
|
||||||
|
$branchesName = Branch::find($branchId)->name ?? null;
|
||||||
|
return $branchesName;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,161 +1,180 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Modules\Lpj\Http\Controllers;
|
namespace Modules\Lpj\Http\Controllers;
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Modules\Lpj\Exports\LaporanPenilaianJaminanExport;
|
use Modules\Lpj\Exports\LaporanPenilaianJaminanExport;
|
||||||
use Modules\Lpj\Models\Permohonan;
|
use Modules\Lpj\Models\Permohonan;
|
||||||
use Maatwebsite\Excel\Facades\Excel;
|
use Modules\Lpj\Models\Penilaian;
|
||||||
|
use Modules\Lpj\Models\PenawaranTender;
|
||||||
|
use Maatwebsite\Excel\Facades\Excel;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
class LaporanPenilaianJaminanController extends Controller
|
class LaporanPenilaianJaminanController extends Controller
|
||||||
|
{
|
||||||
|
public $user;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
{
|
{
|
||||||
public $user;
|
return view('lpj::laporan_penilaian_jaminan.index');
|
||||||
|
|
||||||
/**
|
|
||||||
* Display a listing of the resource.
|
|
||||||
*/
|
|
||||||
public function index()
|
|
||||||
{
|
|
||||||
return view('lpj::laporan_penilaian_jaminan.index');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function dataForDatatables(Request $request)
|
|
||||||
{
|
|
||||||
if (is_null($this->user) || !$this->user->can('laporan-admin-kredit.view')) {
|
|
||||||
//abort(403, 'Sorry! You are not allowed to view laporan admin kredit.');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieve data from the database
|
|
||||||
$query = Permohonan::query();
|
|
||||||
$query = $query->where('status', 'done');
|
|
||||||
|
|
||||||
// Apply search filter if provided
|
|
||||||
if ($request->has('search') && !empty($request->get('search'))) {
|
|
||||||
$search = json_decode($request->get('search'));
|
|
||||||
|
|
||||||
if (isset($search->start_date) || isset($search->end_date)) {
|
|
||||||
$query->whereBetween('tanggal_permohonan', [
|
|
||||||
$search->start_date ?? '1900-01-01',
|
|
||||||
$search->end_date ?? now()->toDateString()
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter by branch if provided
|
|
||||||
if (isset($search->branch_id) && !empty($search->branch_id)) {
|
|
||||||
$query->where('branch_id', $search->branch_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($search->penilai_id) && !empty($search->penilai_id)) {
|
|
||||||
$query->whereHas('penilaian._user_penilai.userPenilaiTeam', function($q) use ($search) {
|
|
||||||
$q->where('user_id', $search->penilai_id);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($search->search)) {
|
|
||||||
|
|
||||||
$query->where(function ($q) use ($search) {
|
|
||||||
$q->where('nomor_registrasi', 'LIKE', '%' . $search->search . '%');
|
|
||||||
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search->search . '%');
|
|
||||||
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $search->search . '%');
|
|
||||||
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search->search . '%');
|
|
||||||
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search->search . '%');
|
|
||||||
$q->orWhereRelation('jenisFasilitasKredit', 'name', 'LIKE', '%' . $search->search . '%');
|
|
||||||
$q->orWhereRelation('jenisPenilaian', 'name', 'LIKE', '%' . $search->search . '%');
|
|
||||||
$q->orWhere('status', 'LIKE', '%' . $search->search . '%');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply sorting if provided
|
|
||||||
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
|
|
||||||
$order = $request->get('sortOrder');
|
|
||||||
$column = $request->get('sortField');
|
|
||||||
$query->orderBy($column, $order);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the total count of records
|
|
||||||
$totalRecords = $query->count();
|
|
||||||
|
|
||||||
// Apply pagination if provided
|
|
||||||
if ($request->has('page') && $request->has('size')) {
|
|
||||||
$page = $request->get('page');
|
|
||||||
$size = $request->get('size');
|
|
||||||
$offset = ($page - 1) * $size; // Calculate the offset
|
|
||||||
|
|
||||||
$query->skip($offset)->take($size);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the filtered count of records
|
|
||||||
$filteredRecords = $query->count();
|
|
||||||
|
|
||||||
// Get the data for the current page
|
|
||||||
$data = $query->with(['debiture.branch'])->get();
|
|
||||||
|
|
||||||
$data = $data->map(function ($permohonan) {
|
|
||||||
$luas_tanah = 0;
|
|
||||||
$luas_bangunan = 0;
|
|
||||||
$nilai_tanah = 0;
|
|
||||||
$nilai_bangunan = 0;
|
|
||||||
$npw = 0;
|
|
||||||
$nilai_liquidasi = 0;
|
|
||||||
if (isset($permohonan->penilai->lpj)) {
|
|
||||||
$lpj = json_decode($permohonan->penilai->lpj, true);
|
|
||||||
$npw = str_replace('.', '', $lpj['total_nilai_pasar_wajar'] ?? 0);
|
|
||||||
|
|
||||||
$luas_tanah = $lpj['luas_tanah'] ?? 0;
|
|
||||||
$luas_bangunan = $lpj['luas_bangunan'] ?? 0;
|
|
||||||
// Calculate nilai_tanah dynamically by looking for all keys that start with 'nilai_tanah_'
|
|
||||||
$nilai_tanah = str_replace('.', '', $lpj['nilai_tanah_2'] ?? 0);
|
|
||||||
|
|
||||||
$nilai_bangunan = str_replace('.', '', $lpj['nilai_bangunan_2'] ?? 0);
|
|
||||||
$nilai_liquidasi = str_replace('.', '', $lpj['likuidasi_nilai_2'] ?? 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [
|
|
||||||
'id' => $permohonan->id,
|
|
||||||
'nomor_registrasi' => $permohonan->nomor_registrasi,
|
|
||||||
'tanggal_permohonan' => $permohonan->tanggal_permohonan,
|
|
||||||
'branch' => $permohonan->debiture?->branch?->name,
|
|
||||||
'name' => $permohonan->debiture?->name,
|
|
||||||
'pemohon' => $permohonan->creator?->name,
|
|
||||||
'tujuan_penilaian' => $permohonan->tujuanPenilaian?->name,
|
|
||||||
'jenis_agunan' => $permohonan->documents?->pluck('jenisJaminan.name')->unique()->implode(', '),
|
|
||||||
'alamat_agunan' => $permohonan->documents?->map(function ($document) {
|
|
||||||
return formatAlamat($document);
|
|
||||||
})->unique()->implode(', '),
|
|
||||||
'luas_tanah' => $luas_tanah . ' m²',
|
|
||||||
'nilai_tanah' => formatRupiah($nilai_tanah,2),
|
|
||||||
'luas_bangunan' => $luas_bangunan . ' m²',
|
|
||||||
'nilai_bangunan' => formatRupiah($nilai_bangunan,2),
|
|
||||||
'tanggal_laporan' => $permohonan->approval_dd_at ?? $permohonan->approval_eo_at ?? '',
|
|
||||||
'tanggal_review' => $permohonan->penilaian?->tanggal_kunjungan ?? '',
|
|
||||||
'nilai_pasar_wajar' => formatRupiah($npw,2),
|
|
||||||
'nilai_likuidasi' => formatRupiah($nilai_liquidasi,2),
|
|
||||||
'nama_penilai' => $permohonan->penilaian?->_user_penilai?->userPenilaiTeam?->name,
|
|
||||||
];
|
|
||||||
});
|
|
||||||
|
|
||||||
// Calculate the page count
|
|
||||||
$pageCount = ceil($totalRecords / $request->get('size'));
|
|
||||||
|
|
||||||
// Calculate the current page number
|
|
||||||
$currentPage = $request->get('page', 1);
|
|
||||||
|
|
||||||
// Return the response data as a JSON object
|
|
||||||
return response()->json([
|
|
||||||
'draw' => $request->get('draw'),
|
|
||||||
'recordsTotal' => $totalRecords,
|
|
||||||
'recordsFiltered' => $filteredRecords,
|
|
||||||
'pageCount' => $pageCount,
|
|
||||||
'page' => $currentPage,
|
|
||||||
'totalCount' => $totalRecords,
|
|
||||||
'data' => $data,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function export(Request $request)
|
|
||||||
{
|
|
||||||
return Excel::download(new LaporanPenilaianJaminanExport($request), 'laporan_penilaian_jaminan.xlsx');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function dataForDatatables(Request $request)
|
||||||
|
{
|
||||||
|
if (is_null($this->user) || !$this->user->can('laporan-admin-kredit.view')) {
|
||||||
|
//abort(403, 'Sorry! You are not allowed to view laporan admin kredit.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve data from the database
|
||||||
|
$query = Permohonan::query();
|
||||||
|
$query = $query->where('status', 'done');
|
||||||
|
|
||||||
|
// Apply search filter if provided
|
||||||
|
if ($request->has('search') && !empty($request->get('search'))) {
|
||||||
|
$search = json_decode($request->get('search'));
|
||||||
|
|
||||||
|
|
||||||
|
if (!empty($search->start_date) || !empty($search->end_date)) {
|
||||||
|
$startDate = $search->start_date ?? '1900-01-01';
|
||||||
|
$endDate = $search->end_date ?? now()->toDateString();
|
||||||
|
|
||||||
|
$query->where(function ($q) use ($startDate, $endDate) {
|
||||||
|
$q->whereHas('penilaian', function ($q2) use ($startDate, $endDate) {
|
||||||
|
$q2->whereBetween('tanggal_kunjungan', [$startDate, $endDate]);
|
||||||
|
})
|
||||||
|
->orWhereHas('penawaran', function ($q3) use ($startDate, $endDate) {
|
||||||
|
$q3->whereBetween('tanggal_penilaian_sebelumnya', [$startDate, $endDate]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter by branch if provided
|
||||||
|
if (isset($search->branch_id) && !empty($search->branch_id)) {
|
||||||
|
$query->where('branch_id', $search->branch_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($search->penilai_id) && !empty($search->penilai_id)) {
|
||||||
|
$query->whereHas('penilaian._user_penilai.userPenilaiTeam', function ($q) use ($search) {
|
||||||
|
$q->where('user_id', $search->penilai_id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($search->search)) {
|
||||||
|
|
||||||
|
$query->where(function ($q) use ($search) {
|
||||||
|
$q->where('nomor_registrasi', 'LIKE', '%' . $search->search . '%');
|
||||||
|
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search->search . '%');
|
||||||
|
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $search->search . '%');
|
||||||
|
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search->search . '%');
|
||||||
|
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search->search . '%');
|
||||||
|
$q->orWhereRelation('debiture', DB::raw('LOWER(name)'), 'LIKE', '%' . strtolower($search->search) . '%');
|
||||||
|
|
||||||
|
$q->orWhereRelation('jenisFasilitasKredit', 'name', 'LIKE', '%' . $search->search . '%');
|
||||||
|
$q->orWhereRelation('jenisPenilaian', 'name', 'LIKE', '%' . $search->search . '%');
|
||||||
|
$q->orWhere('status', 'LIKE', '%' . $search->search . '%');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply sorting if provided
|
||||||
|
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
|
||||||
|
$order = $request->get('sortOrder');
|
||||||
|
$column = $request->get('sortField');
|
||||||
|
$query->orderBy($column, $order);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the total count of records
|
||||||
|
$totalRecords = $query->count();
|
||||||
|
|
||||||
|
// Apply pagination if provided
|
||||||
|
if ($request->has('page') && $request->has('size')) {
|
||||||
|
$page = $request->get('page');
|
||||||
|
$size = $request->get('size');
|
||||||
|
$offset = ($page - 1) * $size; // Calculate the offset
|
||||||
|
|
||||||
|
$query->skip($offset)->take($size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the filtered count of records
|
||||||
|
$filteredRecords = $query->count();
|
||||||
|
|
||||||
|
// Get the data for the current page
|
||||||
|
$data = $query->with(['debiture.branch'])->get();
|
||||||
|
|
||||||
|
$data = $data->map(function ($permohonan) {
|
||||||
|
$luas_tanah = 0;
|
||||||
|
$luas_bangunan = 0;
|
||||||
|
$nilai_tanah = 0;
|
||||||
|
$nilai_bangunan = 0;
|
||||||
|
$npw = 0;
|
||||||
|
$nilai_liquidasi = 0;
|
||||||
|
if (isset($permohonan->penilai->lpj)) {
|
||||||
|
$lpj = json_decode($permohonan->penilai->lpj, true);
|
||||||
|
$npw = str_replace('.', '', $lpj['total_nilai_pasar_wajar'] ?? 0);
|
||||||
|
|
||||||
|
$luas_tanah = $lpj['luas_tanah'] ?? 0;
|
||||||
|
$luas_bangunan = $lpj['luas_bangunan'] ?? 0;
|
||||||
|
// Calculate nilai_tanah dynamically by looking for all keys that start with 'nilai_tanah_'
|
||||||
|
$nilai_tanah = str_replace('.', '', $lpj['nilai_tanah_2'] ?? 0);
|
||||||
|
|
||||||
|
$nilai_bangunan = str_replace('.', '', $lpj['nilai_bangunan_2'] ?? 0);
|
||||||
|
$nilai_liquidasi = str_replace('.', '', $lpj['likuidasi_nilai_2'] ?? 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'id' => $permohonan->id,
|
||||||
|
'nomor_registrasi' => $permohonan->nomor_registrasi,
|
||||||
|
'tanggal_permohonan' => $permohonan->tanggal_permohonan,
|
||||||
|
'branch' => $permohonan->debiture?->branch?->name,
|
||||||
|
'name' => $permohonan->debiture?->name,
|
||||||
|
'pemohon' => $permohonan->creator?->name,
|
||||||
|
'tujuan_penilaian' => $permohonan->tujuanPenilaian?->name,
|
||||||
|
'jenis_agunan' => $permohonan->documents?->pluck('jenisJaminan.name')->unique()->implode(', '),
|
||||||
|
'alamat_agunan' => $permohonan->documents?->map(function ($document) {
|
||||||
|
return formatAlamat($document);
|
||||||
|
})->unique()->implode(', '),
|
||||||
|
'luas_tanah' => $luas_tanah . ' m²',
|
||||||
|
'nilai_tanah' => formatRupiah($nilai_tanah, 2),
|
||||||
|
'luas_bangunan' => $luas_bangunan . ' m²',
|
||||||
|
'nilai_bangunan' => formatRupiah($nilai_bangunan, 2),
|
||||||
|
'tanggal_laporan' => $permohonan->approval_dd_at ?? $permohonan->approval_eo_at ?? '',
|
||||||
|
'tanggal_review' => $permohonan->penilaian?->tanggal_kunjungan ?? '',
|
||||||
|
'nilai_pasar_wajar' => formatRupiah($npw, 2),
|
||||||
|
'nilai_likuidasi' => formatRupiah($nilai_liquidasi, 2),
|
||||||
|
'nama_penilai' => $permohonan->penilaian?->_user_penilai?->userPenilaiTeam?->name,
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
// Calculate the page count
|
||||||
|
$pageCount = ceil($totalRecords / $request->get('size'));
|
||||||
|
|
||||||
|
// Calculate the current page number
|
||||||
|
$currentPage = $request->get('page', 1);
|
||||||
|
|
||||||
|
// Return the response data as a JSON object
|
||||||
|
return response()->json([
|
||||||
|
'draw' => $request->get('draw'),
|
||||||
|
'recordsTotal' => $totalRecords,
|
||||||
|
'recordsFiltered' => $filteredRecords,
|
||||||
|
'pageCount' => $pageCount,
|
||||||
|
'page' => $currentPage,
|
||||||
|
'totalCount' => $totalRecords,
|
||||||
|
'data' => $data,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function export(Request $request)
|
||||||
|
{
|
||||||
|
$startDate = $request->start_date;
|
||||||
|
$endDate = $request->end_date;
|
||||||
|
// name of the file
|
||||||
|
$fileName = 'laporan_penilaian_jaminan_' . $startDate . '_' . $endDate . '.xlsx';
|
||||||
|
return Excel::download(new LaporanPenilaianJaminanExport($request), $fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use Exception;
|
use Exception;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
use Maatwebsite\Excel\Facades\Excel;
|
use Maatwebsite\Excel\Facades\Excel;
|
||||||
use Modules\Lpj\Exports\NilaiPlafondExport;
|
use Modules\Lpj\Exports\NilaiPlafondExport;
|
||||||
use Modules\Lpj\Http\Requests\NilaiPlafondRequest;
|
use Modules\Lpj\Http\Requests\NilaiPlafondRequest;
|
||||||
@@ -14,137 +16,239 @@
|
|||||||
{
|
{
|
||||||
public $user;
|
public $user;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Menampilkan halaman daftar Nilai Plafond.
|
||||||
|
* Log setiap akses dan sebelum return view.
|
||||||
|
*/
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
return view('lpj::nilai_plafond.index');
|
Log::info('NilaiPlafondController@index: akses halaman index');
|
||||||
|
return \view('lpj::nilai_plafond.index');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Menyimpan data Nilai Plafond baru termasuk field biaya.
|
||||||
|
* Gunakan validasi dari NilaiPlafondRequest, log proses, dan bungkus dengan transaksi DB.
|
||||||
|
*/
|
||||||
public function store(NilaiPlafondRequest $request)
|
public function store(NilaiPlafondRequest $request)
|
||||||
{
|
{
|
||||||
|
Log::info('NilaiPlafondController@store: mulai proses simpan');
|
||||||
$validate = $request->validated();
|
$validate = $request->validated();
|
||||||
|
|
||||||
if ($validate) {
|
if ($validate) {
|
||||||
|
DB::beginTransaction();
|
||||||
try {
|
try {
|
||||||
// Save to database
|
$record = NilaiPlafond::create($validate);
|
||||||
NilaiPlafond::create($validate);
|
DB::commit();
|
||||||
return redirect()
|
|
||||||
|
Log::info('NilaiPlafondController@store: simpan berhasil', ['id' => $record->id]);
|
||||||
|
return \redirect()
|
||||||
->route('basicdata.nilai-plafond.index')
|
->route('basicdata.nilai-plafond.index')
|
||||||
->with('success', 'Jenis Aset created successfully');
|
->with('success', 'Nilai Plafond berhasil dibuat');
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
return redirect()
|
DB::rollBack();
|
||||||
|
Log::error('NilaiPlafondController@store: simpan gagal', ['error' => $e->getMessage()]);
|
||||||
|
|
||||||
|
return \redirect()
|
||||||
->route('basicdata.nilai-plafond.create')
|
->route('basicdata.nilai-plafond.create')
|
||||||
->with('error', 'Failed to create nilai plafond');
|
->with('error', 'Gagal membuat Nilai Plafond');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Menampilkan form pembuatan Nilai Plafond.
|
||||||
|
* Log akses sebelum return view.
|
||||||
|
*/
|
||||||
public function create()
|
public function create()
|
||||||
{
|
{
|
||||||
return view('lpj::nilai_plafond.create');
|
Log::info('NilaiPlafondController@create: akses halaman create');
|
||||||
|
return \view('lpj::nilai_plafond.create');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Menampilkan form edit Nilai Plafond berdasarkan ID.
|
||||||
|
* Gunakan transaksi untuk pembacaan data dan logging.
|
||||||
|
*/
|
||||||
public function edit($id)
|
public function edit($id)
|
||||||
{
|
{
|
||||||
$nilaiPlafond = NilaiPlafond::find($id);
|
Log::info('NilaiPlafondController@edit: mulai proses edit', ['id' => $id]);
|
||||||
return view('lpj::nilai_plafond.create', compact('nilaiPlafond'));
|
|
||||||
|
DB::beginTransaction();
|
||||||
|
try {
|
||||||
|
$nilaiPlafond = NilaiPlafond::find($id);
|
||||||
|
DB::commit();
|
||||||
|
|
||||||
|
Log::info('NilaiPlafondController@edit: data ditemukan', ['id' => $id]);
|
||||||
|
return \view('lpj::nilai_plafond.create', compact('nilaiPlafond'));
|
||||||
|
} catch (Exception $e) {
|
||||||
|
DB::rollBack();
|
||||||
|
Log::error('NilaiPlafondController@edit: gagal mengambil data', ['id' => $id, 'error' => $e->getMessage()]);
|
||||||
|
return \redirect()
|
||||||
|
->route('basicdata.nilai-plafond.index')
|
||||||
|
->with('error', 'Gagal mengambil data Nilai Plafond');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Memperbarui data Nilai Plafond termasuk field biaya.
|
||||||
|
* Validasi input, logging, dan gunakan transaksi DB.
|
||||||
|
*/
|
||||||
public function update(NilaiPlafondRequest $request, $id)
|
public function update(NilaiPlafondRequest $request, $id)
|
||||||
{
|
{
|
||||||
|
Log::info('NilaiPlafondController@update: mulai proses update', ['id' => $id]);
|
||||||
$validate = $request->validated();
|
$validate = $request->validated();
|
||||||
|
|
||||||
if ($validate) {
|
if ($validate) {
|
||||||
|
DB::beginTransaction();
|
||||||
try {
|
try {
|
||||||
// Update in database
|
|
||||||
$nilaiPlafond = NilaiPlafond::find($id);
|
$nilaiPlafond = NilaiPlafond::find($id);
|
||||||
|
if (!$nilaiPlafond) {
|
||||||
|
Log::warning('NilaiPlafondController@update: data tidak ditemukan', ['id' => $id]);
|
||||||
|
DB::rollBack();
|
||||||
|
return \redirect()
|
||||||
|
->route('basicdata.nilai-plafond.index')
|
||||||
|
->with('error', 'Data Nilai Plafond tidak ditemukan');
|
||||||
|
}
|
||||||
|
|
||||||
$nilaiPlafond->update($validate);
|
$nilaiPlafond->update($validate);
|
||||||
return redirect()
|
DB::commit();
|
||||||
|
|
||||||
|
Log::info('NilaiPlafondController@update: update berhasil', ['id' => $id]);
|
||||||
|
return \redirect()
|
||||||
->route('basicdata.nilai-plafond.index')
|
->route('basicdata.nilai-plafond.index')
|
||||||
->with('success', 'Jenis Aset updated successfully');
|
->with('success', 'Nilai Plafond berhasil diperbarui');
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
return redirect()
|
DB::rollBack();
|
||||||
|
Log::error('NilaiPlafondController@update: update gagal', ['id' => $id, 'error' => $e->getMessage()]);
|
||||||
|
|
||||||
|
return \redirect()
|
||||||
->route('basicdata.nilai-plafond.edit', $id)
|
->route('basicdata.nilai-plafond.edit', $id)
|
||||||
->with('error', 'Failed to update nilai plafond');
|
->with('error', 'Gagal memperbarui Nilai Plafond');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Menghapus data Nilai Plafond berdasarkan ID.
|
||||||
|
* Logging setiap langkah dan gunakan transaksi DB.
|
||||||
|
*/
|
||||||
public function destroy($id)
|
public function destroy($id)
|
||||||
{
|
{
|
||||||
|
Log::info('NilaiPlafondController@destroy: mulai proses hapus', ['id' => $id]);
|
||||||
|
DB::beginTransaction();
|
||||||
try {
|
try {
|
||||||
// Delete from database
|
|
||||||
$nilaiPlafond = NilaiPlafond::find($id);
|
$nilaiPlafond = NilaiPlafond::find($id);
|
||||||
$nilaiPlafond->delete();
|
if (!$nilaiPlafond) {
|
||||||
|
DB::rollBack();
|
||||||
|
Log::warning('NilaiPlafondController@destroy: data tidak ditemukan', ['id' => $id]);
|
||||||
|
return \response()->json(['success' => false, 'message' => 'Data Nilai Plafond tidak ditemukan']);
|
||||||
|
}
|
||||||
|
|
||||||
echo json_encode(['success' => true, 'message' => 'Jenis Aset deleted successfully']);
|
$nilaiPlafond->delete();
|
||||||
|
DB::commit();
|
||||||
|
|
||||||
|
Log::info('NilaiPlafondController@destroy: hapus berhasil', ['id' => $id]);
|
||||||
|
return \response()->json(['success' => true, 'message' => 'Nilai Plafond berhasil dihapus']);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
echo json_encode(['success' => false, 'message' => 'Failed to delete nilai plafond']);
|
DB::rollBack();
|
||||||
|
Log::error('NilaiPlafondController@destroy: hapus gagal', ['id' => $id, 'error' => $e->getMessage()]);
|
||||||
|
return \response()->json(['success' => false, 'message' => 'Gagal menghapus Nilai Plafond']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Menyediakan data untuk datatables dengan pencarian, sortir, dan paginasi.
|
||||||
|
* Logging proses dan gunakan transaksi DB untuk konsistensi pembacaan.
|
||||||
|
*/
|
||||||
public function dataForDatatables(Request $request)
|
public function dataForDatatables(Request $request)
|
||||||
{
|
{
|
||||||
|
Log::info('NilaiPlafondController@dataForDatatables: mulai proses');
|
||||||
|
|
||||||
if (is_null($this->user) || !$this->user->can('nilai_plafond.view')) {
|
if (is_null($this->user) || !$this->user->can('nilai_plafond.view')) {
|
||||||
//abort(403, 'Sorry! You are not allowed to view users.');
|
//abort(403, 'Sorry! You are not allowed to view users.');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve data from the database
|
DB::beginTransaction();
|
||||||
$query = NilaiPlafond::query();
|
try {
|
||||||
|
// Retrieve data from the database
|
||||||
|
$query = NilaiPlafond::query();
|
||||||
|
|
||||||
// Apply search filter if provided
|
// Apply search filter if provided
|
||||||
if ($request->has('search') && !empty($request->get('search'))) {
|
if ($request->has('search') && !empty($request->get('search'))) {
|
||||||
$search = $request->get('search');
|
$search = $request->get('search');
|
||||||
$query->where(function ($q) use ($search) {
|
$query->where(function ($q) use ($search) {
|
||||||
$q->where('code', 'LIKE', "%$search%");
|
$q->where('code', 'LIKE', "%$search%");
|
||||||
$q->orWhere('name', 'LIKE', "%$search%");
|
$q->orWhere('name', 'LIKE', "%$search%");
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply sorting if provided
|
||||||
|
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
|
||||||
|
$order = $request->get('sortOrder');
|
||||||
|
$column = $request->get('sortField');
|
||||||
|
$query->orderBy($column, $order);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the total count of records
|
||||||
|
$totalRecords = $query->count();
|
||||||
|
|
||||||
|
// Apply pagination if provided
|
||||||
|
if ($request->has('page') && $request->has('size')) {
|
||||||
|
$page = $request->get('page');
|
||||||
|
$size = $request->get('size');
|
||||||
|
$offset = ($page - 1) * $size; // Calculate the offset
|
||||||
|
|
||||||
|
$query->skip($offset)->take($size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the filtered count of records
|
||||||
|
$filteredRecords = $query->count();
|
||||||
|
|
||||||
|
// Get the data for the current page
|
||||||
|
$data = $query->get();
|
||||||
|
|
||||||
|
// Calculate the page count
|
||||||
|
$pageCount = ceil($totalRecords / $request->get('size'));
|
||||||
|
|
||||||
|
// Calculate the current page number
|
||||||
|
$currentPage = 0 + 1;
|
||||||
|
|
||||||
|
DB::commit();
|
||||||
|
Log::info('NilaiPlafondController@dataForDatatables: proses selesai, mengembalikan data');
|
||||||
|
|
||||||
|
// Return the response data as a JSON object
|
||||||
|
return \response()->json([
|
||||||
|
'draw' => $request->get('draw'),
|
||||||
|
'recordsTotal' => $totalRecords,
|
||||||
|
'recordsFiltered' => $filteredRecords,
|
||||||
|
'pageCount' => $pageCount,
|
||||||
|
'page' => $currentPage,
|
||||||
|
'totalCount' => $totalRecords,
|
||||||
|
'data' => $data,
|
||||||
|
]);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
DB::rollBack();
|
||||||
|
Log::error('NilaiPlafondController@dataForDatatables: gagal memproses data', ['error' => $e->getMessage()]);
|
||||||
|
return \response()->json([
|
||||||
|
'draw' => $request->get('draw'),
|
||||||
|
'recordsTotal' => 0,
|
||||||
|
'recordsFiltered' => 0,
|
||||||
|
'pageCount' => 0,
|
||||||
|
'page' => 1,
|
||||||
|
'totalCount' => 0,
|
||||||
|
'data' => [],
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply sorting if provided
|
|
||||||
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
|
|
||||||
$order = $request->get('sortOrder');
|
|
||||||
$column = $request->get('sortField');
|
|
||||||
$query->orderBy($column, $order);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the total count of records
|
|
||||||
$totalRecords = $query->count();
|
|
||||||
|
|
||||||
// Apply pagination if provided
|
|
||||||
if ($request->has('page') && $request->has('size')) {
|
|
||||||
$page = $request->get('page');
|
|
||||||
$size = $request->get('size');
|
|
||||||
$offset = ($page - 1) * $size; // Calculate the offset
|
|
||||||
|
|
||||||
$query->skip($offset)->take($size);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the filtered count of records
|
|
||||||
$filteredRecords = $query->count();
|
|
||||||
|
|
||||||
// Get the data for the current page
|
|
||||||
$data = $query->get();
|
|
||||||
|
|
||||||
// Calculate the page count
|
|
||||||
$pageCount = ceil($totalRecords / $request->get('size'));
|
|
||||||
|
|
||||||
// Calculate the current page number
|
|
||||||
$currentPage = 0 + 1;
|
|
||||||
|
|
||||||
// Return the response data as a JSON object
|
|
||||||
return response()->json([
|
|
||||||
'draw' => $request->get('draw'),
|
|
||||||
'recordsTotal' => $totalRecords,
|
|
||||||
'recordsFiltered' => $filteredRecords,
|
|
||||||
'pageCount' => $pageCount,
|
|
||||||
'page' => $currentPage,
|
|
||||||
'totalCount' => $totalRecords,
|
|
||||||
'data' => $data,
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mengekspor data Nilai Plafond ke Excel.
|
||||||
|
* Log akses sebelum proses download.
|
||||||
|
*/
|
||||||
public function export()
|
public function export()
|
||||||
{
|
{
|
||||||
|
Log::info('NilaiPlafondController@export: mulai proses export');
|
||||||
return Excel::download(new NilaiPlafondExport, 'nilai_plafond.xlsx');
|
return Excel::download(new NilaiPlafondExport, 'nilai_plafond.xlsx');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -229,7 +229,10 @@ use Modules\Lpj\Models\Noc;
|
|||||||
$search = $request->get('search');
|
$search = $request->get('search');
|
||||||
$query->where(function ($q) use ($search) {
|
$query->where(function ($q) use ($search) {
|
||||||
$q->orWhereRelation('penawaran', 'nomor_registrasi', 'LIKE', '%' . $search . '%')
|
$q->orWhereRelation('penawaran', 'nomor_registrasi', 'LIKE', '%' . $search . '%')
|
||||||
->orWhereRelation('permohonan.jenisPenilaian', 'name', 'LIKE', '%' . $search . '%');
|
->orWhereRelation('permohonan', 'nomor_registrasi', 'LIKE', '%' . $search . '%')
|
||||||
|
->orWhereRelation('permohonan.debiture','name', 'LIKE', '%' . $search . '%')
|
||||||
|
->orWhereRelation('permohonan.jenisPenilaian', 'name', 'LIKE', '%' . $search . '%')
|
||||||
|
->orWhere('nomor_tiket', 'LIKE', '%' . $search . '%');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -326,8 +329,15 @@ use Modules\Lpj\Models\Noc;
|
|||||||
if ($request->has('search') && !empty($request->get('search'))) {
|
if ($request->has('search') && !empty($request->get('search'))) {
|
||||||
$search = $request->get('search');
|
$search = $request->get('search');
|
||||||
$query->where(function ($q) use ($search) {
|
$query->where(function ($q) use ($search) {
|
||||||
$q->orWhereRelation('penawaran', 'nomor_registrasi', 'LIKE', '%' . $search . '%')
|
$q->orWhereRelation('penawaran', 'nomor_registrasi', 'LIKE', '%' . $search . '%')
|
||||||
->orWhereRelation('permohonan.jenisPenilaian', 'name', 'LIKE', '%' . $search . '%');
|
->orWhereRelation('permohonan', 'nomor_registrasi', 'LIKE', '%' . $search . '%')
|
||||||
|
->orWhereRelation('permohonan.debiture','name', 'LIKE', '%' . $search . '%')
|
||||||
|
->orWhereRelation('permohonan.jenisPenilaian', 'name', 'LIKE', '%' . $search . '%')
|
||||||
|
->orWhere('nomor_tiket', 'LIKE', '%' . $search . '%'); $q->orWhereRelation('penawaran', 'nomor_registrasi', 'LIKE', '%' . $search . '%')
|
||||||
|
->orWhereRelation('permohonan', 'nomor_registrasi', 'LIKE', '%' . $search . '%')
|
||||||
|
->orWhereRelation('permohonan.debiture','name', 'LIKE', '%' . $search . '%')
|
||||||
|
->orWhereRelation('permohonan.jenisPenilaian', 'name', 'LIKE', '%' . $search . '%')
|
||||||
|
->orWhere('nomor_tiket', 'LIKE', '%' . $search . '%');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -245,7 +245,7 @@ class PembayaranController extends Controller
|
|||||||
|
|
||||||
$permohonan->approve_bayar_by = null;
|
$permohonan->approve_bayar_by = null;
|
||||||
$permohonan->approve_bayar_at = null;
|
$permohonan->approve_bayar_at = null;
|
||||||
$permohonan->status = 'done';
|
$permohonan->status = 'proses-laporan';
|
||||||
$permohonan->save();
|
$permohonan->save();
|
||||||
} else {
|
} else {
|
||||||
$persetujuanPenawaran = PersetujuanPenawaran::create(
|
$persetujuanPenawaran = PersetujuanPenawaran::create(
|
||||||
@@ -346,11 +346,11 @@ class PembayaranController extends Controller
|
|||||||
} else {
|
} else {
|
||||||
$data['status_bayar'] = 'sudah_bayar';
|
$data['status_bayar'] = 'sudah_bayar';
|
||||||
$data['status'] = 'proses-laporan';
|
$data['status'] = 'proses-laporan';
|
||||||
}
|
|
||||||
|
|
||||||
if ($permohonan->jenis_penilaian_id == 2) {
|
if ($permohonan->jenis_penilaian_id == 2) {
|
||||||
$data['status_bayar'] = 'sudah_bayar';
|
$data['status_bayar'] = 'sudah_bayar';
|
||||||
$data['status'] = 'spk';
|
$data['status'] = 'spk';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($permohonan->jenis_penilaian_id == 1) {
|
if ($permohonan->jenis_penilaian_id == 1) {
|
||||||
@@ -399,12 +399,12 @@ class PembayaranController extends Controller
|
|||||||
$query = $query->whereRelation('permohonan', 'branch_id', Auth::user()->branch_id);
|
$query = $query->whereRelation('permohonan', 'branch_id', Auth::user()->branch_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
$query->where(function($q) {
|
/*$query->where(function($q) {
|
||||||
$q->whereRelation('permohonan', function($query) {
|
$q->whereRelation('permohonan', function($query) {
|
||||||
$query->where('status_bayar', 'belum_bayar')
|
$query->where('status_bayar', 'belum_bayar')
|
||||||
->where('jenis_penilaian_id', 1);
|
->where('jenis_penilaian_id', 1);
|
||||||
});
|
});
|
||||||
});
|
});*/
|
||||||
$query->orWhereRelation('permohonan','status_bayar','revisi-pembayaran');
|
$query->orWhereRelation('permohonan','status_bayar','revisi-pembayaran');
|
||||||
$query->orWhere(function($q) {
|
$query->orWhere(function($q) {
|
||||||
$q->where('permohonan_id',null);
|
$q->where('permohonan_id',null);
|
||||||
|
|||||||
@@ -26,18 +26,21 @@ use Modules\Lpj\Http\Requests\FormSurveyorRequest;
|
|||||||
use Modules\Lpj\Models\Authorization;
|
use Modules\Lpj\Models\Authorization;
|
||||||
use Modules\Lpj\Models\Debiture;
|
use Modules\Lpj\Models\Debiture;
|
||||||
use Modules\Lpj\Services\SaveFormInspesksiService;
|
use Modules\Lpj\Services\SaveFormInspesksiService;
|
||||||
|
use Modules\Lpj\Services\PreviewLaporanService;
|
||||||
|
|
||||||
class PenilaiController extends Controller
|
class PenilaiController extends Controller
|
||||||
{
|
{
|
||||||
public $user;
|
public $user;
|
||||||
protected $surveyorController;
|
protected $surveyorController;
|
||||||
protected $inspeksiService;
|
protected $inspeksiService;
|
||||||
|
protected $previewLaporanService;
|
||||||
|
|
||||||
|
|
||||||
public function __construct(SurveyorController $surveyorController, SaveFormInspesksiService $inspeksiService)
|
public function __construct(SurveyorController $surveyorController, SaveFormInspesksiService $inspeksiService, PreviewLaporanService $previewLaporanService)
|
||||||
{
|
{
|
||||||
$this->surveyorController = $surveyorController;
|
$this->surveyorController = $surveyorController;
|
||||||
$this->inspeksiService = $inspeksiService;
|
$this->inspeksiService = $inspeksiService;
|
||||||
|
$this->previewLaporanService = $previewLaporanService;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -154,7 +157,7 @@ class PenilaiController extends Controller
|
|||||||
$permohonan = $this->surveyorController->getPermohonanJaminanId($id, $documentId, $jaminanId);
|
$permohonan = $this->surveyorController->getPermohonanJaminanId($id, $documentId, $jaminanId);
|
||||||
|
|
||||||
if ($permohonan->status == 'proses-laporan') {
|
if ($permohonan->status == 'proses-laporan') {
|
||||||
return redirect()->back()->with('error', 'Masih dalam proses laporan');
|
//return redirect()->back()->with('error', 'Masih dalam proses laporan');
|
||||||
}
|
}
|
||||||
|
|
||||||
$basicData = $this->surveyorController->getCommonData();
|
$basicData = $this->surveyorController->getCommonData();
|
||||||
@@ -548,13 +551,7 @@ class PenilaiController extends Controller
|
|||||||
return view('lpj::penilai.components.call-report', compact('permohonan', 'basicData', 'nomorLaporan', 'forminspeksi', 'cities', 'districts', 'villages', 'cekAlamat', 'callReport'));
|
return view('lpj::penilai.components.call-report', compact('permohonan', 'basicData', 'nomorLaporan', 'forminspeksi', 'cities', 'districts', 'villages', 'cekAlamat', 'callReport'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the specified resource from storage.
|
|
||||||
*/
|
|
||||||
public function destroy($id)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
public function dataForDatatables(Request $request)
|
public function dataForDatatables(Request $request)
|
||||||
{
|
{
|
||||||
@@ -701,15 +698,17 @@ class PenilaiController extends Controller
|
|||||||
'lokasi_lengkap' => $data->lokasi_lengkap ?? '',
|
'lokasi_lengkap' => $data->lokasi_lengkap ?? '',
|
||||||
];
|
];
|
||||||
|
|
||||||
// Extract data pembanding
|
if(isset($dataPembanding)){
|
||||||
if (isset($dataPembanding['data_pembanding'])) {
|
// Extract data pembanding
|
||||||
foreach ($dataPembanding['data_pembanding'] as $index => $pembanding) {
|
if (isset($dataPembanding['data_pembanding'])) {
|
||||||
if ($index == 0) {
|
foreach ($dataPembanding['data_pembanding'] as $index => $pembanding) {
|
||||||
$exportData['pembanding1'] = $pembanding;
|
if ($index == 0) {
|
||||||
} elseif ($index == 1) {
|
$exportData['pembanding1'] = $pembanding;
|
||||||
$exportData['pembanding2'] = $pembanding;
|
} elseif ($index == 1) {
|
||||||
} elseif ($index == 2) {
|
$exportData['pembanding2'] = $pembanding;
|
||||||
$exportData['pembanding3'] = $pembanding;
|
} elseif ($index == 2) {
|
||||||
|
$exportData['pembanding3'] = $pembanding;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -842,10 +841,10 @@ class PenilaiController extends Controller
|
|||||||
$permohonan = Permohonan::findOrFail($id);
|
$permohonan = Permohonan::findOrFail($id);
|
||||||
|
|
||||||
if ($permohonan->status === 'proses-laporan') {
|
if ($permohonan->status === 'proses-laporan') {
|
||||||
return response()->json([
|
/*return response()->json([
|
||||||
'success' => false,
|
'success' => false,
|
||||||
'message' => 'Masih proses laporan',
|
'message' => 'Masih proses laporan',
|
||||||
], 400);
|
], 400);*/
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($permohonan->status === 'proses-paparan') {
|
if ($permohonan->status === 'proses-paparan') {
|
||||||
@@ -1276,8 +1275,6 @@ class PenilaiController extends Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public function print_out(Request $request)
|
public function print_out(Request $request)
|
||||||
{
|
{
|
||||||
$documentId = $request->query('documentId');
|
$documentId = $request->query('documentId');
|
||||||
@@ -1393,6 +1390,15 @@ class PenilaiController extends Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function print_out_laporan($permohonan_id, $document_id, $jaminan_id)
|
||||||
|
{
|
||||||
|
// jika tidak ada id kembalikan ke halaman sebelumnya
|
||||||
|
if (!$permohonan_id || !$document_id || !$jaminan_id) {
|
||||||
|
return redirect()->back()->with('error', 'Laporan tidak valid');
|
||||||
|
}
|
||||||
|
return $this->previewLaporanService->printOutLaporan($permohonan_id, $document_id, $jaminan_id);
|
||||||
|
}
|
||||||
|
|
||||||
private function getViewLaporan($tipe)
|
private function getViewLaporan($tipe)
|
||||||
{
|
{
|
||||||
$viewMap = [
|
$viewMap = [
|
||||||
@@ -1772,4 +1778,24 @@ class PenilaiController extends Controller
|
|||||||
'message' => 'Berhasil Revisi Ke surveyor',
|
'message' => 'Berhasil Revisi Ke surveyor',
|
||||||
], 200);
|
], 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function showLaporanInspeksi(
|
||||||
|
$permohonan_id,
|
||||||
|
$dokumen_id,
|
||||||
|
$jaminan_id,
|
||||||
|
Request $request)
|
||||||
|
{
|
||||||
|
if ($request->type == 'penilai') {
|
||||||
|
$back = route('penilai.show', $permohonan_id);
|
||||||
|
}else{
|
||||||
|
$back = route('surveyor.show', $permohonan_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->previewLaporanService->previewLaporan($permohonan_id, $dokumen_id, $jaminan_id, $back);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function showInspectionReportReview($permohonan_id, $dokumen_id, $jaminan_id)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -517,12 +517,18 @@ class PenilaianController extends Controller
|
|||||||
$role = Auth::user()->roles[0]->name;
|
$role = Auth::user()->roles[0]->name;
|
||||||
$status = 'done';
|
$status = 'done';
|
||||||
$approvalField = null;
|
$approvalField = null;
|
||||||
|
|
||||||
|
$lpj_ = optional(json_decode($permohonan->penilai->lpj));
|
||||||
|
$npw = $lpj_->total_nilai_pasar_wajar ?? 0;
|
||||||
|
$npw = str_replace('.', '', $npw);
|
||||||
|
|
||||||
|
|
||||||
if ($role === 'senior-officer') {
|
if ($role === 'senior-officer') {
|
||||||
$approvalField = 'approval_so';
|
$approvalField = 'approval_so';
|
||||||
$status = in_array($permohonan->nilai_plafond_id, [3]) ? 'done' : 'proses-laporan';
|
$status = $npw <=1000000000 ? 'done' : 'proses-laporan';
|
||||||
} elseif ($role === 'EO Appraisal') {
|
} elseif ($role === 'EO Appraisal') {
|
||||||
$approvalField = 'approval_eo';
|
$approvalField = 'approval_eo';
|
||||||
$status = in_array($permohonan->nilai_plafond_id, [2, 1]) ? 'done' : 'proses-laporan';
|
$status = $npw <=5000000000 ? 'done' : 'proses-laporan';
|
||||||
} elseif ($role === 'DD Appraisal') {
|
} elseif ($role === 'DD Appraisal') {
|
||||||
$approvalField = 'approval_dd';
|
$approvalField = 'approval_dd';
|
||||||
$status = 'done';
|
$status = 'done';
|
||||||
|
|||||||
@@ -27,6 +27,9 @@
|
|||||||
use Modules\Lpj\Models\StatusPermohonan;
|
use Modules\Lpj\Models\StatusPermohonan;
|
||||||
use Modules\Lpj\Models\TujuanPenilaian;
|
use Modules\Lpj\Models\TujuanPenilaian;
|
||||||
use Modules\Lpj\Services\PermohonanHistoryService;
|
use Modules\Lpj\Services\PermohonanHistoryService;
|
||||||
|
use Modules\Lpj\Models\Noc;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class PermohonanController extends Controller
|
class PermohonanController extends Controller
|
||||||
{
|
{
|
||||||
@@ -47,6 +50,9 @@
|
|||||||
{
|
{
|
||||||
$validate = $request->validated();
|
$validate = $request->validated();
|
||||||
if ($validate) {
|
if ($validate) {
|
||||||
|
if(auth()->user()->hasRole('admin')){
|
||||||
|
$validate['status'] = "preregister";
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
// Process file upload
|
// Process file upload
|
||||||
$filePath = null;
|
$filePath = null;
|
||||||
@@ -169,7 +175,7 @@
|
|||||||
// Retrieve data from the database
|
// Retrieve data from the database
|
||||||
$query = Permohonan::query();
|
$query = Permohonan::query();
|
||||||
|
|
||||||
if (!Auth::user()->hasAnyRole(['administrator'])) {
|
if (!Auth::user()->hasAnyRole(['administrator','admin'])) {
|
||||||
$query = $query->where('branch_id', Auth::user()->branch_id);
|
$query = $query->where('branch_id', Auth::user()->branch_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -360,14 +366,54 @@
|
|||||||
$permohonan->keterangan = $request->keterangan;
|
$permohonan->keterangan = $request->keterangan;
|
||||||
$permohonan->save();
|
$permohonan->save();
|
||||||
|
|
||||||
$persetujuanPenawaran = PersetujuanPenawaran::where('permohonan_id', $id)->first();
|
if ($permohonan->status_bayar == 'belum_bayar') {
|
||||||
if(!$persetujuanPenawaran){
|
PersetujuanPenawaran::firstOrCreate(
|
||||||
$persetujuanPenawaran = PersetujuanPenawaran::create([
|
['permohonan_id' => $id],
|
||||||
'permohonan_id' => $id,
|
['created_by' => Auth::id()]
|
||||||
'created_by' => Auth::id(),
|
);
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($permohonan->status == 'sudah_dibayar') {
|
||||||
|
|
||||||
|
$documents = $permohonan->dokumenjaminan->first(function ($doc) {
|
||||||
|
return $doc->detail && $doc->detail->contains('name', 'Bukti Bayar');
|
||||||
|
});
|
||||||
|
|
||||||
|
$buktiBayar = $documents->detail->filter(function ($detail) {
|
||||||
|
return $detail->name == 'Bukti Bayar';
|
||||||
|
})->first() ?? null;
|
||||||
|
|
||||||
|
if ($buktiBayar->isEmpty()) {
|
||||||
|
return redirect()->route('authorization.show', $id)->with('error', 'Bukti Bayar harus diunggah');
|
||||||
|
}
|
||||||
|
|
||||||
|
$dokumenJaminan = json_decode($buktiBayar->dokumen_jaminan);
|
||||||
|
|
||||||
|
$persetujuanPenawaran = PersetujuanPenawaran::firstOrCreate(
|
||||||
|
['permohonan_id' => $id],
|
||||||
|
[
|
||||||
|
'created_by' => Auth::id(),
|
||||||
|
'bukti_bayar' => $buktiBayar->first()->dokumen_jaminan[0],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
Noc::updateOrCreate([
|
||||||
|
'permohonan_id' => $persetujuanPenawaran->permohonan_id,
|
||||||
|
'persetujuan_penawaran_id' => $persetujuanPenawaran->id
|
||||||
|
],[
|
||||||
|
'bukti_bayar' => $persetujuanPenawaran->bukti_bayar,
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
\Log::error('Failed to create or update NOC: ' . $e->getMessage());
|
||||||
|
return redirect()
|
||||||
|
->route('persetujuan-penawaran.index')
|
||||||
|
->with('error', 'Persetujuan Penawaran berhasil disimpan tetapi gagal membuat NOC: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
return redirect()->route('authorization.show', $id)->with('error', 'Failed to update permohonan');
|
return redirect()->route('authorization.show', $id)->with('error', 'Failed to update permohonan');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,6 +40,7 @@
|
|||||||
$validated = $request->validated();
|
$validated = $request->validated();
|
||||||
$validated['created_by'] = Auth::id();
|
$validated['created_by'] = Auth::id();
|
||||||
$validated['status'] = '0';
|
$validated['status'] = '0';
|
||||||
|
$validated['nominal_bayar'] = $validated['biaya_final'];
|
||||||
|
|
||||||
$persetujuanPenawaran = PersetujuanPenawaran::updateOrCreate(
|
$persetujuanPenawaran = PersetujuanPenawaran::updateOrCreate(
|
||||||
['penawaran_id' => $validated['penawaran_id']],
|
['penawaran_id' => $validated['penawaran_id']],
|
||||||
@@ -179,8 +180,8 @@
|
|||||||
public function edit($id)
|
public function edit($id)
|
||||||
{
|
{
|
||||||
$permohonan = Permohonan::with(['debiture', 'penawaranTender.detail'])->find($id);
|
$permohonan = Permohonan::with(['debiture', 'penawaranTender.detail'])->find($id);
|
||||||
|
$persetujuanPenawaran = PersetujuanPenawaran::where('permohonan_id', $id)->first();
|
||||||
return view('lpj::persetujuan_penawaran.form', compact('permohonan'));
|
return view('lpj::persetujuan_penawaran.form', compact('permohonan', 'persetujuanPenawaran'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -201,8 +202,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve data from the database
|
// Retrieve data from the database
|
||||||
$query = Permohonan::query()->where(['status' => 'persetujuan-penawaran']);
|
//$query = Permohonan::query()->where(['status' => 'persetujuan-penawaran']);
|
||||||
|
$query = Permohonan::query()
|
||||||
|
->where(['status' => 'persetujuan-penawaran'])
|
||||||
|
->whereHas('penawaranTender', function ($q) {
|
||||||
|
$q->where('status', 'persetujuan-penawaran');
|
||||||
|
});
|
||||||
// Apply search filter if provided
|
// Apply search filter if provided
|
||||||
if ($request->has('search') && !empty($request->get('search'))) {
|
if ($request->has('search') && !empty($request->get('search'))) {
|
||||||
$search = $request->get('search');
|
$search = $request->get('search');
|
||||||
|
|||||||
441
app/Http/Controllers/ReferensiLinkController.php
Normal file
441
app/Http/Controllers/ReferensiLinkController.php
Normal file
@@ -0,0 +1,441 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Lpj\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use Exception;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Maatwebsite\Excel\Facades\Excel;
|
||||||
|
use Modules\Lpj\Models\ReferensiLink;
|
||||||
|
use Modules\Lpj\Http\Requests\ReferensiLinkRequest;
|
||||||
|
use Modules\Lpj\Exports\ReferensiLinkExport;
|
||||||
|
use Modules\Lpj\Imports\ReferensiLinkImport;
|
||||||
|
|
||||||
|
class ReferensiLinkController extends Controller
|
||||||
|
{
|
||||||
|
public $user;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->middleware('auth');
|
||||||
|
$this->middleware(function ($request, $next) {
|
||||||
|
$this->user = auth()->user();
|
||||||
|
return $next($request);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
//$this->authorize('referensi-link.view', $this->user);
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'title' => 'Referensi Link',
|
||||||
|
'subtitle' => 'Daftar Referensi Link',
|
||||||
|
'breadcrumb' => [
|
||||||
|
['url' => route('dashboard'), 'text' => 'Dashboard'],
|
||||||
|
['text' => 'Referensi Link']
|
||||||
|
],
|
||||||
|
'kategoriOptions' => $this->getKategoriOptions(),
|
||||||
|
];
|
||||||
|
|
||||||
|
return view('lpj::referensi_link.index', $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for creating a new resource.
|
||||||
|
*/
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
//$this->authorize('referensi-link.create', $this->user);
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'title' => 'Tambah Referensi Link',
|
||||||
|
'subtitle' => 'Form Tambah Referensi Link Baru',
|
||||||
|
'breadcrumb' => [
|
||||||
|
['url' => route('dashboard'), 'text' => 'Dashboard'],
|
||||||
|
['url' => route('basicdata.referensi-link.index'), 'text' => 'Referensi Link'],
|
||||||
|
['text' => 'Tambah']
|
||||||
|
],
|
||||||
|
'kategoriOptions' => $this->getKategoriOptions(),
|
||||||
|
];
|
||||||
|
|
||||||
|
return view('lpj::referensi_link.create', $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a newly created resource in storage.
|
||||||
|
*/
|
||||||
|
public function store(ReferensiLinkRequest $request)
|
||||||
|
{
|
||||||
|
//$this->authorize('referensi-link.create', $this->user);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$validated = $request->validated();
|
||||||
|
|
||||||
|
// Set urutan otomatis jika belum diisi
|
||||||
|
if (empty($validated['urutan'])) {
|
||||||
|
$validated['urutan'] = ReferensiLink::max('urutan') + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$referensiLink = ReferensiLink::create($validated);
|
||||||
|
|
||||||
|
return redirect()
|
||||||
|
->route('basicdata.referensi-link.index')
|
||||||
|
->with('success', 'Referensi Link berhasil ditambahkan');
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return redirect()
|
||||||
|
->back()
|
||||||
|
->withInput()
|
||||||
|
->with('error', 'Gagal menambahkan Referensi Link: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for editing the specified resource.
|
||||||
|
*/
|
||||||
|
public function edit($id)
|
||||||
|
{
|
||||||
|
//$this->authorize('referensi-link.update', $this->user);
|
||||||
|
|
||||||
|
$referensiLink = ReferensiLink::findOrFail($id);
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'title' => 'Edit Referensi Link',
|
||||||
|
'subtitle' => 'Form Edit Referensi Link',
|
||||||
|
'breadcrumb' => [
|
||||||
|
['url' => route('dashboard'), 'text' => 'Dashboard'],
|
||||||
|
['url' => route('basicdata.referensi-link.index'), 'text' => 'Referensi Link'],
|
||||||
|
['text' => 'Edit']
|
||||||
|
],
|
||||||
|
'referensiLink' => $referensiLink,
|
||||||
|
'kategoriOptions' => $this->getKategoriOptions(),
|
||||||
|
];
|
||||||
|
|
||||||
|
return view('lpj::referensi_link.create', $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the specified resource in storage.
|
||||||
|
*/
|
||||||
|
public function update(ReferensiLinkRequest $request, $id)
|
||||||
|
{
|
||||||
|
//$this->authorize('referensi-link.update', $this->user);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$referensiLink = ReferensiLink::findOrFail($id);
|
||||||
|
$validated = $request->validated();
|
||||||
|
|
||||||
|
$referensiLink->update($validated);
|
||||||
|
|
||||||
|
return redirect()
|
||||||
|
->route('basicdata.referensi-link.index')
|
||||||
|
->with('success', 'Referensi Link berhasil diperbarui');
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return redirect()
|
||||||
|
->back()
|
||||||
|
->withInput()
|
||||||
|
->with('error', 'Gagal memperbarui Referensi Link: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified resource from storage.
|
||||||
|
*/
|
||||||
|
public function destroy($id)
|
||||||
|
{
|
||||||
|
//$this->authorize('referensi-link.delete', $this->user);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$referensiLink = ReferensiLink::findOrFail($id);
|
||||||
|
$referensiLink->delete();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true,
|
||||||
|
'message' => 'Referensi Link berhasil dihapus'
|
||||||
|
]);
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return response()->json([
|
||||||
|
'success' => false,
|
||||||
|
'message' => 'Gagal menghapus Referensi Link: ' . $e->getMessage()
|
||||||
|
], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Datatable API for KTDataTable
|
||||||
|
*/
|
||||||
|
public function dataTable(Request $request)
|
||||||
|
{
|
||||||
|
//$this->authorize('referensi-link.view', $this->user);
|
||||||
|
|
||||||
|
$query = ReferensiLink::with(['createdBy', 'updatedBy'])
|
||||||
|
->select('referensi_link.*');
|
||||||
|
|
||||||
|
// Search
|
||||||
|
$search = $request->input('search');
|
||||||
|
if (!empty($search)) {
|
||||||
|
$query->where(function ($q) use ($search) {
|
||||||
|
$q->where('name', 'LIKE', "%{$search}%")
|
||||||
|
->orWhere('link', 'LIKE', "%{$search}%")
|
||||||
|
->orWhere('kategori', 'LIKE', "%{$search}%");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optional filters (support multiple request shapes)
|
||||||
|
$filters = $request->input('filters', []);
|
||||||
|
$kategori = $request->input('kategori', $filters['kategori'] ?? null);
|
||||||
|
if (!empty($kategori)) {
|
||||||
|
if (is_array($kategori)) {
|
||||||
|
$query->whereIn('kategori', $kategori);
|
||||||
|
} else {
|
||||||
|
$values = preg_split('/[,|]/', (string) $kategori, -1, PREG_SPLIT_NO_EMPTY);
|
||||||
|
if (count($values) > 1) {
|
||||||
|
$query->whereIn('kategori', $values);
|
||||||
|
} else {
|
||||||
|
$query->where('kategori', $kategori);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$statusRaw = $request->input('status', $filters['status'] ?? $request->input('is_active'));
|
||||||
|
$statusParsed = $this->parseActiveFilter($statusRaw);
|
||||||
|
if ($statusParsed !== null) {
|
||||||
|
$query->where('is_active', $statusParsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sorting
|
||||||
|
$allowedSortFields = ['id', 'name', 'link', 'kategori', 'urutan', 'is_active', 'created_at', 'updated_at'];
|
||||||
|
$sortField = in_array($request->input('sortField', 'urutan'), $allowedSortFields, true)
|
||||||
|
? $request->input('sortField', 'urutan')
|
||||||
|
: 'urutan';
|
||||||
|
$sortOrder = strtolower($request->input('sortOrder', 'asc'));
|
||||||
|
if (in_array($sortOrder, ['asc', 'desc'], true)) {
|
||||||
|
$query->orderBy($sortField, $sortOrder);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pagination
|
||||||
|
$page = max((int) $request->input('page', 1), 1);
|
||||||
|
$size = max((int) $request->input('size', 10), 1);
|
||||||
|
$totalRecords = (clone $query)->count();
|
||||||
|
$offset = ($page - 1) * $size;
|
||||||
|
$items = $query->skip($offset)->take($size)->get();
|
||||||
|
|
||||||
|
// Map data rows
|
||||||
|
$data = $items->map(function ($row) {
|
||||||
|
return [
|
||||||
|
'id' => $row->id,
|
||||||
|
'name' => $row->name,
|
||||||
|
'link' => '<a href="' . $row->link . '" target="_blank" class="text-primary">' . Str::limit($row->link, 50) . ' <i class="fas fa-external-link-alt"></i></a>',
|
||||||
|
'kategori' => $row->kategori,
|
||||||
|
'status_badge' => $row->status_badge,
|
||||||
|
'urutan' => $row->urutan,
|
||||||
|
'actions' => (
|
||||||
|
(auth()->user()->can('referensi-link.update') ? '<a class="dropdown-item" href="' . route('basicdata.referensi-link.edit', $row->id) . '"><i class="fas fa-edit"></i> Edit</a>' : '') .
|
||||||
|
(auth()->user()->can('referensi-link.delete') ? '<a class="dropdown-item text-danger" href="javascript:void(0)" onclick="deleteData(' . $row->id . ')"><i class="fas fa-trash"></i> Hapus</a>' : '')
|
||||||
|
),
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'draw' => (int) $request->input('draw'),
|
||||||
|
'recordsTotal' => $totalRecords,
|
||||||
|
'recordsFiltered' => $totalRecords,
|
||||||
|
'pageCount' => (int) ceil($totalRecords / $size),
|
||||||
|
'page' => $page,
|
||||||
|
'totalCount' => $totalRecords,
|
||||||
|
'data' => $data,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Export data to Excel
|
||||||
|
*/
|
||||||
|
public function export(Request $request)
|
||||||
|
{
|
||||||
|
//$this->authorize('referensi-link.export', $this->user);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$filename = 'referensi_link_' . date('YmdHis') . '.xlsx';
|
||||||
|
|
||||||
|
return Excel::download(new ReferensiLinkExport($request->all()), $filename);
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return redirect()
|
||||||
|
->back()
|
||||||
|
->with('error', 'Gagal export data: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show import form
|
||||||
|
*/
|
||||||
|
public function import()
|
||||||
|
{
|
||||||
|
//$this->authorize('referensi-link.import', $this->user);
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'title' => 'Import Referensi Link',
|
||||||
|
'subtitle' => 'Import data Referensi Link dari Excel',
|
||||||
|
'breadcrumb' => [
|
||||||
|
['url' => route('dashboard'), 'text' => 'Dashboard'],
|
||||||
|
['url' => route('basicdata.referensi-link.index'), 'text' => 'Referensi Link'],
|
||||||
|
['text' => 'Import']
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
return view('lpj::referensi_link.import', $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process import
|
||||||
|
*/
|
||||||
|
public function importProcess(Request $request)
|
||||||
|
{
|
||||||
|
//$this->authorize('referensi-link.import', $this->user);
|
||||||
|
|
||||||
|
$request->validate([
|
||||||
|
'file' => 'required|mimes:xlsx,xls|max:10240', // max 10MB
|
||||||
|
]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$import = new ReferensiLinkImport();
|
||||||
|
Excel::import($import, $request->file('file'));
|
||||||
|
|
||||||
|
$stats = $import->getImportStats();
|
||||||
|
|
||||||
|
$message = "Import berhasil! {$stats['success']} data berhasil diimport";
|
||||||
|
if ($stats['failed'] > 0) {
|
||||||
|
$message .= ", {$stats['failed']} data gagal diimport";
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()
|
||||||
|
->route('basicdata.referensi-link.index')
|
||||||
|
->with('success', $message);
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
Log::error('ReferensiLink import error: ' . $e->getMessage());
|
||||||
|
return redirect()
|
||||||
|
->back()
|
||||||
|
->with('error', 'Gagal import data: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggle status (active/inactive)
|
||||||
|
*/
|
||||||
|
public function toggleStatus($id)
|
||||||
|
{
|
||||||
|
//$this->authorize('referensi-link.update', $this->user);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$referensiLink = ReferensiLink::findOrFail($id);
|
||||||
|
$referensiLink->is_active = !$referensiLink->is_active;
|
||||||
|
$referensiLink->save();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true,
|
||||||
|
'message' => 'Status berhasil diubah',
|
||||||
|
'status' => $referensiLink->is_active
|
||||||
|
]);
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return response()->json([
|
||||||
|
'success' => false,
|
||||||
|
'message' => 'Gagal mengubah status: ' . $e->getMessage()
|
||||||
|
], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get kategori options for dropdown
|
||||||
|
*/
|
||||||
|
private function getKategoriOptions()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'regulasi' => 'Regulasi',
|
||||||
|
'panduan' => 'Panduan',
|
||||||
|
'prosedur' => 'Prosedur',
|
||||||
|
'formulir' => 'Formulir',
|
||||||
|
'laporan' => 'Laporan',
|
||||||
|
'lainnya' => 'Lainnya'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function parseActiveFilter($value): ?bool
|
||||||
|
{
|
||||||
|
if ($value === null || $value === '') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_bool($value)) {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
$val = strtolower(trim((string) $value));
|
||||||
|
|
||||||
|
if (in_array($val, ['1', 'true', 'aktif', 'active', 'yes', 'y'], true)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (in_array($val, ['0', 'false', 'tidak', 'inactive', 'nonaktif', 'no', 'n'], true)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Download import template
|
||||||
|
*/
|
||||||
|
public function downloadTemplate()
|
||||||
|
{
|
||||||
|
//$this->authorize('referensi-link.import', $this->user);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$headers = [
|
||||||
|
'Nama',
|
||||||
|
'Link',
|
||||||
|
'Kategori',
|
||||||
|
'Deskripsi',
|
||||||
|
'Status Aktif',
|
||||||
|
'Urutan'
|
||||||
|
];
|
||||||
|
|
||||||
|
$filename = 'template_referensi_link_' . date('YmdHis') . '.xlsx';
|
||||||
|
|
||||||
|
return Excel::download(new class($headers) implements \Maatwebsite\Excel\Concerns\FromArray, \Maatwebsite\Excel\Concerns\WithHeadings {
|
||||||
|
private $headers;
|
||||||
|
|
||||||
|
public function __construct($headers)
|
||||||
|
{
|
||||||
|
$this->headers = $headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function array(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
['Contoh Referensi', 'https://example.com', 'panduan', 'Deskripsi contoh referensi link', 'aktif', 1],
|
||||||
|
['Contoh Regulasi', 'https://regulasi.example.com', 'regulasi', 'Deskripsi regulasi', 'aktif', 2],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function headings(): array
|
||||||
|
{
|
||||||
|
return $this->headers;
|
||||||
|
}
|
||||||
|
}, $filename);
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return redirect()
|
||||||
|
->back()
|
||||||
|
->with('error', 'Gagal download template: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -345,6 +345,19 @@ use Illuminate\Support\Facades\Auth;
|
|||||||
$content = $pdf->download()->getOriginalContent();
|
$content = $pdf->download()->getOriginalContent();
|
||||||
Storage::put('public/'.$newFileNameWithPath,$content);
|
Storage::put('public/'.$newFileNameWithPath,$content);
|
||||||
|
|
||||||
|
$permohonanModel = Permohonan::where('nomor_registrasi', $penawaran->nomor_registrasi)->first();
|
||||||
|
if ($permohonanModel) {
|
||||||
|
$permohonanModel->status = 'registrasi-final';
|
||||||
|
$permohonanModel->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
$persetujuanPenawaran = PenawaranTender::where('id', $penawaran->id)->first();
|
||||||
|
if ($persetujuanPenawaran) {
|
||||||
|
$persetujuanPenawaran->status = 'registrasi-final';
|
||||||
|
$persetujuanPenawaran->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
$data1['status'] = 'success';
|
$data1['status'] = 'success';
|
||||||
$data1['spkpenawaran_path'] = $spkpenawaran_path;
|
$data1['spkpenawaran_path'] = $spkpenawaran_path;
|
||||||
$data1['message']['message_success'] = array('Generate SPK PDF successfully');
|
$data1['message']['message_success'] = array('Generate SPK PDF successfully');
|
||||||
|
|||||||
@@ -3,25 +3,21 @@
|
|||||||
namespace Modules\Lpj\Http\Controllers;
|
namespace Modules\Lpj\Http\Controllers;
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use Illuminate\Http\RedirectResponse;
|
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Http\JsonResponse;
|
|
||||||
use Illuminate\Support\Facades\Validator;
|
use Illuminate\Support\Facades\Validator;
|
||||||
use Maatwebsite\Excel\Facades\Excel;
|
use Maatwebsite\Excel\Facades\Excel;
|
||||||
use Modules\Lpj\Exports\BasicDataSurveyorExport;
|
use Modules\Lpj\Exports\BasicDataSurveyorExport;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Facades\Log;
|
||||||
use Barryvdh\DomPDF\Facade\Pdf;
|
use Barryvdh\DomPDF\Facade\Pdf;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
use Illuminate\Support\Carbon;
|
use Illuminate\Support\Carbon;
|
||||||
use Illuminate\Support\Facades\Mail;
|
use Exception;
|
||||||
use Illuminate\Http\Response;
|
|
||||||
use Modules\Lpj\Models\Debiture;
|
use Modules\Lpj\Models\Debiture;
|
||||||
use Modules\Lpj\Models\LaporanExternal;
|
use Modules\Lpj\Models\LaporanExternal;
|
||||||
use Modules\Lpj\Models\Permohonan;
|
use Modules\Lpj\Models\Permohonan;
|
||||||
use Modules\Lpj\Models\Branch;
|
use Modules\Lpj\Models\Branch;
|
||||||
use Modules\Lpj\Models\Surveyor;
|
|
||||||
use Modules\Lpj\Models\BentukTanah;
|
use Modules\Lpj\Models\BentukTanah;
|
||||||
use Modules\Lpj\Models\KonturTanah;
|
use Modules\Lpj\Models\KonturTanah;
|
||||||
use Modules\Location\Models\Province;
|
use Modules\Location\Models\Province;
|
||||||
@@ -41,17 +37,8 @@ use Modules\Lpj\Models\SpekBangunan;
|
|||||||
use Modules\Lpj\Models\SpekKategoritBangunan;
|
use Modules\Lpj\Models\SpekKategoritBangunan;
|
||||||
use Modules\Lpj\Models\SaranaPelengkap;
|
use Modules\Lpj\Models\SaranaPelengkap;
|
||||||
use Modules\Lpj\Models\ArahMataAngin;
|
use Modules\Lpj\Models\ArahMataAngin;
|
||||||
use Modules\Lpj\Models\Analisa;
|
|
||||||
use Modules\Lpj\Models\Penilaian;
|
use Modules\Lpj\Models\Penilaian;
|
||||||
use Modules\Lpj\Models\PerkerasanJalan;
|
use Modules\Lpj\Models\PerkerasanJalan;
|
||||||
use Modules\Lpj\Models\AnalisaFakta;
|
|
||||||
use Modules\Lpj\Models\AnalisaLingkungan;
|
|
||||||
use Modules\Lpj\Models\AnalisaTanahBagunan;
|
|
||||||
use Modules\Lpj\Models\SpekBangunanAnalisa;
|
|
||||||
use Modules\Lpj\Models\Denah;
|
|
||||||
use Modules\Lpj\Models\FotoJaminan;
|
|
||||||
use Modules\Lpj\Models\Lingkungan;
|
|
||||||
use Modules\Lpj\Models\LantaiUnit;
|
|
||||||
use Modules\Lpj\Models\Teams;
|
use Modules\Lpj\Models\Teams;
|
||||||
use Modules\Lpj\Models\Lantai;
|
use Modules\Lpj\Models\Lantai;
|
||||||
use Modules\Lpj\Models\Inspeksi;
|
use Modules\Lpj\Models\Inspeksi;
|
||||||
@@ -62,29 +49,24 @@ use Modules\Lpj\Models\PosisiUnit;
|
|||||||
use Modules\Lpj\Models\TerletakArea;
|
use Modules\Lpj\Models\TerletakArea;
|
||||||
use Modules\Lpj\Models\FasilitasObjek;
|
use Modules\Lpj\Models\FasilitasObjek;
|
||||||
use Modules\Lpj\Models\MerupakanDaerah;
|
use Modules\Lpj\Models\MerupakanDaerah;
|
||||||
use Modules\Lpj\Models\ObjekJaminan;
|
|
||||||
use Modules\Lpj\Models\ModelAlatBerat;
|
use Modules\Lpj\Models\ModelAlatBerat;
|
||||||
use Modules\Lpj\Models\JenisPesawat;
|
use Modules\Lpj\Models\JenisPesawat;
|
||||||
use Modules\Lpj\Models\DokumenJaminan;
|
use Modules\Lpj\Models\DokumenJaminan;
|
||||||
use Modules\Lpj\Models\DetailDokumenJaminan;
|
use Modules\Lpj\Models\DetailDokumenJaminan;
|
||||||
use Modules\Lpj\Models\JenisKapal;
|
use Modules\Lpj\Models\JenisKapal;
|
||||||
use Modules\Lpj\Models\JenisKendaraan;
|
use Modules\Lpj\Models\JenisKendaraan;
|
||||||
use Modules\Lpj\Models\RuteJaminan;
|
|
||||||
use Modules\Lpj\Models\HubunganPemilikJaminan;
|
use Modules\Lpj\Models\HubunganPemilikJaminan;
|
||||||
use Modules\Lpj\Models\HubunganPenghuniJaminan;
|
use Modules\Lpj\Models\HubunganPenghuniJaminan;
|
||||||
use Modules\Lpj\Models\AnalisaUnit;
|
|
||||||
use Modules\Lpj\Models\GolonganMasySekitar;
|
use Modules\Lpj\Models\GolonganMasySekitar;
|
||||||
use Modules\Lpj\Models\TingkatKeramaian;
|
use Modules\Lpj\Models\TingkatKeramaian;
|
||||||
use Modules\Lpj\Models\TujuanPenilaian;
|
use Modules\Lpj\Models\TujuanPenilaian;
|
||||||
use Modules\Lpj\Models\LaluLintasLokasi;
|
use Modules\Lpj\Models\LaluLintasLokasi;
|
||||||
use Modules\Lpj\Models\SpekBagunanAnalisaDetail;
|
|
||||||
use Modules\Lpj\Http\Requests\SurveyorRequest;
|
use Modules\Lpj\Http\Requests\SurveyorRequest;
|
||||||
use Modules\Lpj\Http\Requests\FormSurveyorRequest;
|
|
||||||
use Modules\Lpj\Jobs\SendJadwalKunjunganEmailJob;
|
use Modules\Lpj\Jobs\SendJadwalKunjunganEmailJob;
|
||||||
use App\Helpers\Lpj;
|
|
||||||
use Modules\Lpj\Models\Authorization;
|
use Modules\Lpj\Models\Authorization;
|
||||||
use Modules\Lpj\Services\SurveyorValidateService;
|
use Modules\Lpj\Services\SurveyorValidateService;
|
||||||
use Modules\Lpj\Services\SaveFormInspesksiService;
|
use Modules\Lpj\Services\SaveFormInspesksiService;
|
||||||
|
use Modules\Lpj\Models\PermohonanHistory;
|
||||||
|
|
||||||
class SurveyorController extends Controller
|
class SurveyorController extends Controller
|
||||||
{
|
{
|
||||||
@@ -126,6 +108,9 @@ class SurveyorController extends Controller
|
|||||||
$provinces = Province::all();
|
$provinces = Province::all();
|
||||||
$bentukTanah = BentukTanah::all();
|
$bentukTanah = BentukTanah::all();
|
||||||
|
|
||||||
|
// Jalankan cleanup inspeksi otomatis untuk permohonan ini
|
||||||
|
$this->cleanupInspeksiData($id);
|
||||||
|
|
||||||
// Get all inspeksi data for this permohonan
|
// Get all inspeksi data for this permohonan
|
||||||
if (strtolower($permohonan->tujuanPenilaian->name) == 'rap') {
|
if (strtolower($permohonan->tujuanPenilaian->name) == 'rap') {
|
||||||
$inspeksiData = Inspeksi::where('permohonan_id', $id)
|
$inspeksiData = Inspeksi::where('permohonan_id', $id)
|
||||||
@@ -151,13 +136,17 @@ class SurveyorController extends Controller
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$catatan_revisi_survey = PermohonanHistory::where('permohonan_id', $id)
|
||||||
|
->where('status', 'revisi-survey')->latest()->first();
|
||||||
|
|
||||||
return view('lpj::surveyor.detail', compact(
|
return view('lpj::surveyor.detail', compact(
|
||||||
'permohonan',
|
'permohonan',
|
||||||
'surveyor',
|
'surveyor',
|
||||||
'branches',
|
'branches',
|
||||||
'provinces',
|
'provinces',
|
||||||
'bentukTanah',
|
'bentukTanah',
|
||||||
'inspeksiData'
|
'inspeksiData',
|
||||||
|
'catatan_revisi_survey',
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,7 +242,7 @@ class SurveyorController extends Controller
|
|||||||
], 200);
|
], 200);
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
\Log::error('Denah Store Error: ' . $e->getMessage());
|
Log::error('Denah Store Error: ' . $e->getMessage());
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'success' => false,
|
'success' => false,
|
||||||
'message' => 'Gagal menyimpan data: ' . $e->getMessage()
|
'message' => 'Gagal menyimpan data: ' . $e->getMessage()
|
||||||
@@ -894,11 +883,10 @@ class SurveyorController extends Controller
|
|||||||
$penilaian = Penilaian::findOrFail($id);
|
$penilaian = Penilaian::findOrFail($id);
|
||||||
|
|
||||||
$permohonan = Permohonan::where('nomor_registrasi', $penilaian->nomor_registrasi)->first();
|
$permohonan = Permohonan::where('nomor_registrasi', $penilaian->nomor_registrasi)->first();
|
||||||
;
|
|
||||||
if (Carbon::parse($validate['waktu_penilaian']) <= Carbon::parse($penilaian->tanggal_kunjungan)) {
|
if (Carbon::parse($validate['waktu_penilaian']) <= Carbon::parse($penilaian->tanggal_kunjungan)) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'success' => false,
|
'success' => false,
|
||||||
'message' => 'Waktu penilaian harus lebih besar dari tanggal assign.'
|
'message' => 'Waktu penilaian harus lebih besar dari tanggal assign.'.$penilaian->tanggal_kunjungan.' '.$validate['waktu_penilaian']
|
||||||
], 422);
|
], 422);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1079,7 +1067,7 @@ class SurveyorController extends Controller
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
\Log::error('File upload error: ' . $e->getMessage());
|
Log::error('File upload error: ' . $e->getMessage());
|
||||||
throw new \Exception("Gagal mengupload file: " . $e->getMessage());
|
throw new \Exception("Gagal mengupload file: " . $e->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2909,5 +2897,99 @@ class SurveyorController extends Controller
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fungsi untuk cleanup data inspeksi otomatis
|
||||||
|
* Menghapus data inspeksi tanpa dokument_id jika ada data lain dengan dokument_id yang sama
|
||||||
|
*/
|
||||||
|
private function cleanupInspeksiData($permohonanId)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
Log::info('SurveyorController: Memulai cleanup inspeksi otomatis', [
|
||||||
|
'permohonan_id' => $permohonanId,
|
||||||
|
'user_id' => Auth::id()
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Ambil data inspeksi yang memiliki dokument_id (data lengkap)
|
||||||
|
$dataWithDokument = Inspeksi::where('permohonan_id', $permohonanId)
|
||||||
|
->whereNotNull('dokument_id')
|
||||||
|
->whereNull('deleted_at')
|
||||||
|
->get();
|
||||||
|
|
||||||
|
// Ambil data inspeksi yang tidak memiliki dokument_id (data yang akan di-cleanup)
|
||||||
|
$dataWithoutDokument = Inspeksi::where('permohonan_id', $permohonanId)
|
||||||
|
->whereNull('dokument_id')
|
||||||
|
->whereNull('deleted_at')
|
||||||
|
->get();
|
||||||
|
|
||||||
|
// Jika ada data tanpa dokument_id, cek apakah ada data dengan dokument_id yang sama
|
||||||
|
if ($dataWithoutDokument->isNotEmpty() && $dataWithDokument->isNotEmpty()) {
|
||||||
|
|
||||||
|
// Group data dengan dokument_id by created_by
|
||||||
|
$groupedDataWithDokument = $dataWithDokument->groupBy('created_by');
|
||||||
|
|
||||||
|
// Group data tanpa dokument_id by created_by
|
||||||
|
$groupedDataWithoutDokument = $dataWithoutDokument->groupBy('created_by');
|
||||||
|
|
||||||
|
// Proses cleanup untuk setiap user
|
||||||
|
foreach ($groupedDataWithDokument as $userId => $userDataWithDokument) {
|
||||||
|
|
||||||
|
// Cek apakah user ini juga memiliki data tanpa dokument_id
|
||||||
|
if (isset($groupedDataWithoutDokument[$userId])) {
|
||||||
|
|
||||||
|
// Ambil salah satu data dengan dokument_id sebagai referensi untuk logging
|
||||||
|
$referenceData = $userDataWithDokument->first();
|
||||||
|
|
||||||
|
Log::info('SurveyorController: Menemukan data lengkap untuk user, akan menghapus data tidak lengkap', [
|
||||||
|
'user_id' => $userId,
|
||||||
|
'permohonan_id' => $permohonanId,
|
||||||
|
'reference_dokument_id' => $referenceData->dokument_id,
|
||||||
|
'data_count_to_delete' => $groupedDataWithoutDokument[$userId]->count()
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Ambil semua data tanpa dokument_id untuk user ini
|
||||||
|
$userDataWithoutDokument = $groupedDataWithoutDokument[$userId];
|
||||||
|
|
||||||
|
// Soft delete data tanpa dokument_id
|
||||||
|
foreach ($userDataWithoutDokument as $dataToDelete) {
|
||||||
|
DB::beginTransaction();
|
||||||
|
try {
|
||||||
|
// Soft delete data
|
||||||
|
$dataToDelete->delete();
|
||||||
|
|
||||||
|
Log::info('SurveyorController: Data inspeksi berhasil di-soft delete', [
|
||||||
|
'id' => $dataToDelete->id,
|
||||||
|
'permohonan_id' => $dataToDelete->permohonan_id,
|
||||||
|
'dokument_id' => $dataToDelete->dokument_id,
|
||||||
|
'created_by' => $dataToDelete->created_by,
|
||||||
|
'deleted_at' => now()
|
||||||
|
]);
|
||||||
|
|
||||||
|
DB::commit();
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
DB::rollback();
|
||||||
|
Log::error('SurveyorController: Gagal menghapus data inspeksi', [
|
||||||
|
'id' => $dataToDelete->id,
|
||||||
|
'error' => $e->getMessage()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::info('SurveyorController: Cleanup inspeksi otomatis selesai', [
|
||||||
|
'permohonan_id' => $permohonanId,
|
||||||
|
'data_with_dokument' => $dataWithDokument->count(),
|
||||||
|
'data_without_dokument' => $dataWithoutDokument->count()
|
||||||
|
]);
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::error('SurveyorController: Error saat cleanup inspeksi otomatis', [
|
||||||
|
'permohonan_id' => $permohonanId,
|
||||||
|
'error' => $e->getMessage(),
|
||||||
|
'trace' => $e->getTraceAsString()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
'city_code' => 'nullable|exists:cities,code',
|
'city_code' => 'nullable|exists:cities,code',
|
||||||
'district_code' => 'nullable|exists:districts,code',
|
'district_code' => 'nullable|exists:districts,code',
|
||||||
'village_code' => 'nullable|exists:villages,code',
|
'village_code' => 'nullable|exists:villages,code',
|
||||||
'nomor_rekening' => 'nullable|string|max:10',
|
'nomor_rekening' => 'nullable|string|max:50',
|
||||||
'name' => 'required',
|
'name' => 'required',
|
||||||
'registered_at' => 'nullable|date',
|
'registered_at' => 'nullable|date',
|
||||||
'npwp' => 'nullable|string|min:15|max:16',
|
'npwp' => 'nullable|string|min:15|max:16',
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
{
|
{
|
||||||
$rules = [
|
$rules = [
|
||||||
'name' => 'required|max:255',
|
'name' => 'required|max:255',
|
||||||
|
'biaya' => 'nullable|numeric|min:0',
|
||||||
];
|
];
|
||||||
|
|
||||||
if ($this->method() == 'PUT') {
|
if ($this->method() == 'PUT') {
|
||||||
|
|||||||
@@ -48,7 +48,6 @@
|
|||||||
),
|
),
|
||||||
'tanggal_permohonan' => date('Y-m-d'),
|
'tanggal_permohonan' => date('Y-m-d'),
|
||||||
'user_id' => auth()->user()->id,
|
'user_id' => auth()->user()->id,
|
||||||
'branch_id' => auth()->user()->branch_id,
|
|
||||||
'status' => 'order'
|
'status' => 'order'
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|||||||
114
app/Http/Requests/ReferensiLinkRequest.php
Normal file
114
app/Http/Requests/ReferensiLinkRequest.php
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Lpj\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class ReferensiLinkRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
$rules = [
|
||||||
|
'name' => 'required|string|max:255',
|
||||||
|
'link' => 'required|string|max:500',
|
||||||
|
'kategori' => 'nullable|string|max:100',
|
||||||
|
'deskripsi' => 'nullable|string|max:2000',
|
||||||
|
'is_active' => 'boolean',
|
||||||
|
'urutan' => 'nullable|integer|min:0',
|
||||||
|
];
|
||||||
|
|
||||||
|
// Validasi tambahan untuk link
|
||||||
|
$rules['link'] .= '|url';
|
||||||
|
|
||||||
|
return $rules;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get custom messages for validator errors.
|
||||||
|
*
|
||||||
|
* @return array<string, string>
|
||||||
|
*/
|
||||||
|
public function messages(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name.required' => 'Nama referensi link wajib diisi',
|
||||||
|
'name.string' => 'Nama referensi link harus berupa teks',
|
||||||
|
'name.max' => 'Nama referensi link maksimal 255 karakter',
|
||||||
|
'link.required' => 'Link wajib diisi',
|
||||||
|
'link.string' => 'Link harus berupa teks',
|
||||||
|
'link.max' => 'Link maksimal 500 karakter',
|
||||||
|
'link.url' => 'Link harus berupa URL yang valid',
|
||||||
|
'kategori.string' => 'Kategori harus berupa teks',
|
||||||
|
'kategori.max' => 'Kategori maksimal 100 karakter',
|
||||||
|
'deskripsi.string' => 'Deskripsi harus berupa teks',
|
||||||
|
'deskripsi.max' => 'Deskripsi maksimal 2000 karakter',
|
||||||
|
'is_active.boolean' => 'Status aktif harus berupa ya/tidak',
|
||||||
|
'urutan.integer' => 'Urutan harus berupa angka',
|
||||||
|
'urutan.min' => 'Urutan minimal 0',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get custom attributes for validator errors.
|
||||||
|
*
|
||||||
|
* @return array<string, string>
|
||||||
|
*/
|
||||||
|
public function attributes(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name' => 'Nama Referensi Link',
|
||||||
|
'link' => 'Link',
|
||||||
|
'kategori' => 'Kategori',
|
||||||
|
'deskripsi' => 'Deskripsi',
|
||||||
|
'is_active' => 'Status Aktif',
|
||||||
|
'urutan' => 'Urutan',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare the data for validation.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function prepareForValidation(): void
|
||||||
|
{
|
||||||
|
// Format link jika belum memiliki protocol
|
||||||
|
if ($this->has('link')) {
|
||||||
|
$link = $this->input('link');
|
||||||
|
if ($link && !preg_match('/^(https?:\/\/)/i', $link)) {
|
||||||
|
$this->merge([
|
||||||
|
'link' => 'https://' . $link
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set default is_active jika tidak diset
|
||||||
|
if (!$this->has('is_active')) {
|
||||||
|
$this->merge([
|
||||||
|
'is_active' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set default urutan jika tidak diset atau 0
|
||||||
|
if (!$this->has('urutan') || empty($this->input('urutan'))) {
|
||||||
|
$this->merge([
|
||||||
|
'urutan' => 0
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
166
app/Imports/ReferensiLinkImport.php
Normal file
166
app/Imports/ReferensiLinkImport.php
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Lpj\Imports;
|
||||||
|
|
||||||
|
use Modules\Lpj\app\Models\ReferensiLink;
|
||||||
|
use Maatwebsite\Excel\Concerns\ToModel;
|
||||||
|
use Maatwebsite\Excel\Concerns\WithHeadingRow;
|
||||||
|
use Maatwebsite\Excel\Concerns\WithValidation;
|
||||||
|
use Maatwebsite\Excel\Concerns\Importable;
|
||||||
|
use Maatwebsite\Excel\Concerns\SkipsFailures;
|
||||||
|
use Maatwebsite\Excel\Concerns\SkipsOnFailure;
|
||||||
|
use Maatwebsite\Excel\Concerns\WithBatchInserts;
|
||||||
|
use Maatwebsite\Excel\Concerns\WithChunkReading;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
|
class ReferensiLinkImport implements ToModel, WithHeadingRow, WithValidation, SkipsOnFailure, WithBatchInserts, WithChunkReading
|
||||||
|
{
|
||||||
|
use Importable, SkipsFailures;
|
||||||
|
|
||||||
|
protected $importedCount = 0;
|
||||||
|
protected $failedCount = 0;
|
||||||
|
protected $errors = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert row to model
|
||||||
|
*/
|
||||||
|
public function model(array $row)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$this->importedCount++;
|
||||||
|
|
||||||
|
return new ReferensiLink([
|
||||||
|
'name' => $row['nama'] ?? $row['name'],
|
||||||
|
'link' => $this->formatLink($row['link'] ?? $row['url'] ?? ''),
|
||||||
|
'kategori' => $row['kategori'] ?? $row['category'] ?? 'lainnya',
|
||||||
|
'deskripsi' => $row['deskripsi'] ?? $row['description'] ?? null,
|
||||||
|
'is_active' => $this->parseStatus($row['status_aktif'] ?? $row['is_active'] ?? 'aktif'),
|
||||||
|
'urutan' => $this->parseUrutan($row['urutan'] ?? $row['order'] ?? 0),
|
||||||
|
'created_by' => Auth::id(),
|
||||||
|
'updated_by' => Auth::id(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->failedCount++;
|
||||||
|
$this->errors[] = "Baris {$row['row_number']}: " . $e->getMessage();
|
||||||
|
Log::error('Import ReferensiLink Error: ' . $e->getMessage(), ['row' => $row]);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validation rules
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'nama' => 'required|string|max:255',
|
||||||
|
'name' => 'required|string|max:255',
|
||||||
|
'link' => 'required|string|max:500',
|
||||||
|
'url' => 'required|string|max:500',
|
||||||
|
'kategori' => 'nullable|string|max:100',
|
||||||
|
'category' => 'nullable|string|max:100',
|
||||||
|
'deskripsi' => 'nullable|string|max:2000',
|
||||||
|
'description' => 'nullable|string|max:2000',
|
||||||
|
'status_aktif' => 'nullable|string|in:aktif,tidak aktif,1,0,true,false',
|
||||||
|
'is_active' => 'nullable|string|in:aktif,tidak aktif,1,0,true,false',
|
||||||
|
'urutan' => 'nullable|integer|min:0',
|
||||||
|
'order' => 'nullable|integer|min:0',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom validation messages
|
||||||
|
*/
|
||||||
|
public function customValidationMessages()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'nama.required' => 'Nama wajib diisi',
|
||||||
|
'name.required' => 'Nama wajib diisi',
|
||||||
|
'link.required' => 'Link wajib diisi',
|
||||||
|
'url.required' => 'Link wajib diisi',
|
||||||
|
'link.url' => 'Link harus berupa URL yang valid',
|
||||||
|
'url.url' => 'Link harus berupa URL yang valid',
|
||||||
|
'kategori.max' => 'Kategori maksimal 100 karakter',
|
||||||
|
'category.max' => 'Kategori maksimal 100 karakter',
|
||||||
|
'deskripsi.max' => 'Deskripsi maksimal 2000 karakter',
|
||||||
|
'description.max' => 'Deskripsi maksimal 2000 karakter',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Batch size for inserts
|
||||||
|
*/
|
||||||
|
public function batchSize(): int
|
||||||
|
{
|
||||||
|
return 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Chunk size for reading
|
||||||
|
*/
|
||||||
|
public function chunkSize(): int
|
||||||
|
{
|
||||||
|
return 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format link to ensure it has protocol
|
||||||
|
*/
|
||||||
|
private function formatLink($link)
|
||||||
|
{
|
||||||
|
if (empty($link)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove any whitespace
|
||||||
|
$link = trim($link);
|
||||||
|
|
||||||
|
// Add protocol if not present
|
||||||
|
if (!preg_match('/^(https?:\/\/)/i', $link)) {
|
||||||
|
$link = 'https://' . $link;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $link;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse status value
|
||||||
|
*/
|
||||||
|
private function parseStatus($status)
|
||||||
|
{
|
||||||
|
if (empty($status)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$status = strtolower(trim($status));
|
||||||
|
|
||||||
|
return in_array($status, ['aktif', '1', 'true', 'yes', 'ya']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse order value
|
||||||
|
*/
|
||||||
|
private function parseUrutan($urutan)
|
||||||
|
{
|
||||||
|
if (empty($urutan)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int) $urutan;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get import statistics
|
||||||
|
*/
|
||||||
|
public function getImportStats(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'imported' => $this->importedCount,
|
||||||
|
'failed' => $this->failedCount,
|
||||||
|
'errors' => $this->errors,
|
||||||
|
'success' => $this->importedCount - $this->failedCount,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
156
app/Jobs/CleanupInspeksiDataJob.php
Normal file
156
app/Jobs/CleanupInspeksiDataJob.php
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Lpj\Jobs;
|
||||||
|
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Modules\Lpj\Models\Inspeksi;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Job untuk membersihkan data inspeksi yang tidak memiliki dokument_id
|
||||||
|
*
|
||||||
|
* Case: Jika ada data inspeksi yang masuk dengan permohonan_id yang sama
|
||||||
|
* tetapi memiliki dokument_id dan user created_by yang sama, maka
|
||||||
|
* data lama (tanpa dokument_id) akan di-soft delete
|
||||||
|
*/
|
||||||
|
class CleanupInspeksiDataJob implements ShouldQueue
|
||||||
|
{
|
||||||
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
||||||
|
public $timeout = 300; // 5 menit
|
||||||
|
public $tries = 3;
|
||||||
|
public $maxExceptions = 3;
|
||||||
|
public $backoff = [60, 120, 300]; // Exponential backoff dalam detik
|
||||||
|
|
||||||
|
protected int $permohonanId;
|
||||||
|
protected int $createdBy;
|
||||||
|
protected ?int $dokumentId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new job instance.
|
||||||
|
*
|
||||||
|
* @param int $permohonanId
|
||||||
|
* @param int $createdBy
|
||||||
|
* @param int|null $dokumentId
|
||||||
|
*/
|
||||||
|
public function __construct(int $permohonanId, int $createdBy, ?int $dokumentId = null)
|
||||||
|
{
|
||||||
|
$this->permohonanId = $permohonanId;
|
||||||
|
$this->createdBy = $createdBy;
|
||||||
|
$this->dokumentId = $dokumentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the job.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
public function handle(): void
|
||||||
|
{
|
||||||
|
Log::info('CleanupInspeksiDataJob: Memulai proses cleanup data inspeksi', [
|
||||||
|
'permohonan_id' => $this->permohonanId,
|
||||||
|
'created_by' => $this->createdBy,
|
||||||
|
'dokument_id' => $this->dokumentId
|
||||||
|
]);
|
||||||
|
|
||||||
|
DB::beginTransaction();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Cari data inspeksi yang memiliki dokument_id (data baru)
|
||||||
|
$newInspeksi = Inspeksi::where('permohonan_id', $this->permohonanId)
|
||||||
|
->where('created_by', $this->createdBy)
|
||||||
|
->whereNotNull('dokument_id')
|
||||||
|
->whereNull('deleted_at')
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if (!$newInspeksi) {
|
||||||
|
Log::warning('CleanupInspeksiDataJob: Tidak ditemukan data inspeksi baru dengan dokument_id', [
|
||||||
|
'permohonan_id' => $this->permohonanId,
|
||||||
|
'created_by' => $this->createdBy
|
||||||
|
]);
|
||||||
|
DB::rollBack();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::info('CleanupInspeksiDataJob: Data inspeksi baru ditemukan', [
|
||||||
|
'inspeksi_id' => $newInspeksi->id,
|
||||||
|
'dokument_id' => $newInspeksi->dokument_id
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Cari data inspeksi lama yang tidak memiliki dokument_id
|
||||||
|
$oldInspeksiList = Inspeksi::where('permohonan_id', $this->permohonanId)
|
||||||
|
->where('created_by', $this->createdBy)
|
||||||
|
->whereNull('dokument_id')
|
||||||
|
->whereNull('deleted_at')
|
||||||
|
->where('id', '!=', $newInspeksi->id) // Jangan hapus data yang baru saja ditemukan
|
||||||
|
->get();
|
||||||
|
|
||||||
|
if ($oldInspeksiList->isEmpty()) {
|
||||||
|
Log::info('CleanupInspeksiDataJob: Tidak ditemukan data inspeksi lama tanpa dokument_id', [
|
||||||
|
'permohonan_id' => $this->permohonanId,
|
||||||
|
'created_by' => $this->createdBy
|
||||||
|
]);
|
||||||
|
DB::commit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$deletedCount = 0;
|
||||||
|
foreach ($oldInspeksiList as $oldInspeksi) {
|
||||||
|
// Soft delete data lama
|
||||||
|
$oldInspeksi->delete(); // Menggunakan soft delete karena model menggunakan SoftDeletes trait
|
||||||
|
|
||||||
|
Log::info('CleanupInspeksiDataJob: Data inspeksi lama berhasil di-soft delete', [
|
||||||
|
'old_inspeksi_id' => $oldInspeksi->id,
|
||||||
|
'permohonan_id' => $oldInspeksi->permohonan_id,
|
||||||
|
'created_by' => $oldInspeksi->created_by,
|
||||||
|
'deleted_at' => now()->toDateTimeString()
|
||||||
|
]);
|
||||||
|
|
||||||
|
$deletedCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
DB::commit();
|
||||||
|
|
||||||
|
Log::info('CleanupInspeksiDataJob: Proses cleanup selesai', [
|
||||||
|
'permohonan_id' => $this->permohonanId,
|
||||||
|
'created_by' => $this->createdBy,
|
||||||
|
'deleted_count' => $deletedCount,
|
||||||
|
'new_inspeksi_id' => $newInspeksi->id
|
||||||
|
]);
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
DB::rollBack();
|
||||||
|
|
||||||
|
Log::error('CleanupInspeksiDataJob: Terjadi error saat proses cleanup', [
|
||||||
|
'permohonan_id' => $this->permohonanId,
|
||||||
|
'created_by' => $this->createdBy,
|
||||||
|
'error' => $e->getMessage(),
|
||||||
|
'trace' => $e->getTraceAsString()
|
||||||
|
]);
|
||||||
|
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle a job failure.
|
||||||
|
*
|
||||||
|
* @param \Throwable $exception
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function failed(\Throwable $exception): void
|
||||||
|
{
|
||||||
|
Log::error('CleanupInspeksiDataJob: Job gagal dieksekusi', [
|
||||||
|
'permohonan_id' => $this->permohonanId,
|
||||||
|
'created_by' => $this->createdBy,
|
||||||
|
'error' => $exception->getMessage(),
|
||||||
|
'trace' => $exception->getTraceAsString()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,7 +21,7 @@ class CategoryDaftarPustaka extends Model
|
|||||||
];
|
];
|
||||||
|
|
||||||
public function daftarPustaka(){
|
public function daftarPustaka(){
|
||||||
return $this->hasMany(DaftarPustaka::class);
|
return $this->hasMany(DaftarPustaka::class, 'category_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ class Inspeksi extends Base
|
|||||||
/**
|
/**
|
||||||
* The attributes that are mass assignable.
|
* The attributes that are mass assignable.
|
||||||
*/
|
*/
|
||||||
protected $fillable = ['data_form', 'foto_form', 'denah_form','permohonan_id', 'name', 'status', 'authorized_status', 'authorized_at', 'authorized_by', 'created_by', 'updated_by', 'deleted_by','dokument_id','data_pembanding'];
|
protected $fillable = ['data_form', 'foto_form', 'denah_form','permohonan_id', 'name', 'status', 'authorized_status', 'authorized_at', 'authorized_by', 'created_by', 'updated_by', 'deleted_by','dokument_id','data_pembanding','mig_detail_data_jaminan'];
|
||||||
|
|
||||||
public function permohonan()
|
public function permohonan()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,5 +6,5 @@
|
|||||||
class NilaiPlafond extends Base
|
class NilaiPlafond extends Base
|
||||||
{
|
{
|
||||||
protected $table = 'nilai_plafond';
|
protected $table = 'nilai_plafond';
|
||||||
protected $fillable = ['code', 'name'];
|
protected $fillable = ['code', 'name', 'biaya'];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace Modules\Lpj\Models;
|
namespace Modules\Lpj\Models;
|
||||||
|
|
||||||
use Modules\Usermanagement\Models\User;
|
use Modules\Usermanagemenet\Models\User;
|
||||||
|
|
||||||
class PersetujuanPenawaran extends Base
|
class PersetujuanPenawaran extends Base
|
||||||
{
|
{
|
||||||
@@ -13,9 +13,6 @@
|
|||||||
'permohonan_id',
|
'permohonan_id',
|
||||||
'penawaran_id',
|
'penawaran_id',
|
||||||
'nomor_proposal_penawaran',
|
'nomor_proposal_penawaran',
|
||||||
'nomor_tiket',
|
|
||||||
'nominal_kurang_bayar',
|
|
||||||
'bukti_ksl_kurang_bayar',
|
|
||||||
'tanggal_proposal_penawaran',
|
'tanggal_proposal_penawaran',
|
||||||
'biaya_final',
|
'biaya_final',
|
||||||
'sla_resume',
|
'sla_resume',
|
||||||
@@ -49,6 +46,12 @@
|
|||||||
return $this->belongsTo(Permohonan::class, 'permohonan_id');
|
return $this->belongsTo(Permohonan::class, 'permohonan_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Relationship with Region
|
||||||
|
public function region()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Region::class);
|
||||||
|
}
|
||||||
|
|
||||||
// Relationship with User (for authorized_by)
|
// Relationship with User (for authorized_by)
|
||||||
public function authorizedBy()
|
public function authorizedBy()
|
||||||
{
|
{
|
||||||
|
|||||||
152
app/Models/ReferensiLink.php
Normal file
152
app/Models/ReferensiLink.php
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Lpj\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Modules\Usermanagement\Models\User;
|
||||||
|
|
||||||
|
class ReferensiLink extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The table associated with the model.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $table = 'referensi_link';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes that are mass assignable.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $fillable = [
|
||||||
|
'name',
|
||||||
|
'link',
|
||||||
|
'kategori',
|
||||||
|
'deskripsi',
|
||||||
|
'is_active',
|
||||||
|
'urutan',
|
||||||
|
'created_by',
|
||||||
|
'updated_by',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes that should be cast.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $casts = [
|
||||||
|
'is_active' => 'boolean',
|
||||||
|
'urutan' => 'integer',
|
||||||
|
'created_at' => 'datetime',
|
||||||
|
'updated_at' => 'datetime',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Boot the model.
|
||||||
|
*/
|
||||||
|
protected static function boot()
|
||||||
|
{
|
||||||
|
parent::boot();
|
||||||
|
|
||||||
|
static::creating(function ($model) {
|
||||||
|
if (Auth::check()) {
|
||||||
|
$model->created_by = Auth::id();
|
||||||
|
$model->updated_by = Auth::id();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
static::updating(function ($model) {
|
||||||
|
if (Auth::check()) {
|
||||||
|
$model->updated_by = Auth::id();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scope untuk filter data aktif
|
||||||
|
*/
|
||||||
|
public function scopeActive($query)
|
||||||
|
{
|
||||||
|
return $query->where('is_active', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scope untuk filter berdasarkan kategori
|
||||||
|
*/
|
||||||
|
public function scopeByKategori($query, $kategori)
|
||||||
|
{
|
||||||
|
return $query->where('kategori', $kategori);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scope untuk urutkan berdasarkan urutan
|
||||||
|
*/
|
||||||
|
public function scopeOrdered($query)
|
||||||
|
{
|
||||||
|
return $query->orderBy('urutan', 'asc')->orderBy('name', 'asc');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scope untuk pencarian
|
||||||
|
*/
|
||||||
|
public function scopeSearch($query, $search)
|
||||||
|
{
|
||||||
|
return $query->where(function ($q) use ($search) {
|
||||||
|
$q->where('name', 'like', "%{$search}%")
|
||||||
|
->orWhere('link', 'like', "%{$search}%")
|
||||||
|
->orWhere('kategori', 'like', "%{$search}%")
|
||||||
|
->orWhere('deskripsi', 'like', "%{$search}%");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Relasi ke user yang membuat
|
||||||
|
*/
|
||||||
|
public function createdBy()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class, 'created_by');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Relasi ke user yang update
|
||||||
|
*/
|
||||||
|
public function updatedBy()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class, 'updated_by');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accessor untuk status badge
|
||||||
|
*/
|
||||||
|
public function getStatusBadgeAttribute()
|
||||||
|
{
|
||||||
|
return $this->is_active
|
||||||
|
? '<span class="badge bg-success">Aktif</span>'
|
||||||
|
: '<span class="badge bg-danger">Tidak Aktif</span>';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accessor untuk link yang diformat
|
||||||
|
*/
|
||||||
|
public function getFormattedLinkAttribute()
|
||||||
|
{
|
||||||
|
return $this->link ? url($this->link) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mutator untuk memastikan link valid
|
||||||
|
*/
|
||||||
|
public function setLinkAttribute($value)
|
||||||
|
{
|
||||||
|
// Validasi dan format link
|
||||||
|
if ($value && !preg_match('/^(https?:\/\/)/i', $value)) {
|
||||||
|
$value = 'https://' . $value;
|
||||||
|
}
|
||||||
|
$this->attributes['link'] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -32,25 +32,46 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register commands in the format of Command::class
|
* Register commands in the format of Command::class
|
||||||
*/
|
*/
|
||||||
protected function registerCommands()
|
protected function registerCommands()
|
||||||
: void
|
: void
|
||||||
{
|
{
|
||||||
// $this->commands([]);
|
$this->commands([
|
||||||
}
|
\Modules\Lpj\Console\Commands\CleanupInspeksiDataCommand::class,
|
||||||
|
\Modules\Lpj\Console\Commands\CleanupSingleInspeksiCommand::class,
|
||||||
|
\Modules\Lpj\Console\Commands\CleanupInspeksiStatusCommand::class,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register command Schedules.
|
* Register command Schedules.
|
||||||
*/
|
*/
|
||||||
protected function registerCommandSchedules()
|
protected function registerCommandSchedules()
|
||||||
: void
|
: void
|
||||||
{
|
{
|
||||||
// $this->app->booted(function () {
|
$this->app->booted(function () {
|
||||||
// $schedule = $this->app->make(Schedule::class);
|
$schedule = $this->app->make(\Illuminate\Console\Scheduling\Schedule::class);
|
||||||
// $schedule->command('inspire')->hourly();
|
|
||||||
// });
|
// Jalankan cleanup inspeksi setiap hari jam 2 pagi
|
||||||
}
|
$schedule->command('lpj:cleanup-inspeksi --force')
|
||||||
|
->dailyAt('02:00')
|
||||||
|
->withoutOverlapping()
|
||||||
|
->onOneServer()
|
||||||
|
->runInBackground()
|
||||||
|
->appendOutputTo(storage_path('logs/cleanup-inspeksi.log'));
|
||||||
|
|
||||||
|
// Backup cleanup setiap minggu
|
||||||
|
$schedule->command('lpj:cleanup-inspeksi --force')
|
||||||
|
->weekly()
|
||||||
|
->sundays()
|
||||||
|
->at('03:00')
|
||||||
|
->withoutOverlapping()
|
||||||
|
->onOneServer()
|
||||||
|
->runInBackground()
|
||||||
|
->appendOutputTo(storage_path('logs/cleanup-inspeksi-weekly.log'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register translations.
|
* Register translations.
|
||||||
|
|||||||
@@ -50,44 +50,40 @@ class DaftarPustakaService
|
|||||||
|
|
||||||
// get all with pagination
|
// get all with pagination
|
||||||
public function getAllDaftarPustaka($request)
|
public function getAllDaftarPustaka($request)
|
||||||
{
|
{
|
||||||
$query = DaftarPustaka::query();
|
$query = DaftarPustaka::query();
|
||||||
|
|
||||||
// Filter pencarian
|
// Filter pencarian
|
||||||
if (!empty($request->get('search'))) {
|
if (!empty($request->get('search'))) {
|
||||||
$search = $request->get('search');
|
$search = $request->get('search');
|
||||||
$query->where(function ($q) use ($search) {
|
$query->where(function ($q) use ($search) {
|
||||||
$q->orWhere('judul', 'LIKE', "%$search%");
|
$q->orWhere('judul', 'LIKE', "%$search%");
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter kategori
|
||||||
|
if (!empty($request->get('category'))) {
|
||||||
|
$category = explode(',', $request->input('category'));
|
||||||
|
$query->whereIn('category_id', $category);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default pagination
|
||||||
|
$page = (int) $request->get('page', 1);
|
||||||
|
$size = (int) $request->get('size', 10);
|
||||||
|
|
||||||
|
return $query->paginate($size, ['*'], 'page', $page);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter kategori
|
|
||||||
if (!empty($request->get('category'))) {
|
|
||||||
$category = explode(',', $request->input('category'));
|
|
||||||
$query->whereIn('category_id', $category);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Default pagination
|
|
||||||
$page = (int) $request->get('page', 1);
|
|
||||||
$size = (int) $request->get('size', 10);
|
|
||||||
|
|
||||||
return $query->paginate($size, ['*'], 'page', $page);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private function handleUpload($file)
|
private function handleUpload($file)
|
||||||
{
|
{
|
||||||
$today = now();
|
$today = now();
|
||||||
$folderPath = 'daftar_pustaka/' . $today->format('Y/m/d');
|
$folderPath = 'daftar_pustaka/' . $today->format('Y/m/d');
|
||||||
|
|
||||||
if (!file_exists(public_path($folderPath))) {
|
|
||||||
mkdir(public_path($folderPath), 0755, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
$fileName = $file->getClientOriginalName();
|
$fileName = $file->getClientOriginalName();
|
||||||
$file->move(public_path($folderPath), $fileName);
|
$filePath = $file->storeAs($folderPath, $fileName, 'public');
|
||||||
|
|
||||||
return $folderPath . '/' . $fileName;
|
return $filePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
73
app/Services/ImageResizeService.php
Normal file
73
app/Services/ImageResizeService.php
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Lpj\Services;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use Intervention\Image\Laravel\Facades\Image;
|
||||||
|
|
||||||
|
class ImageResizeService
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Resize an image and store it.
|
||||||
|
*
|
||||||
|
* @param string $originalPath
|
||||||
|
* @param int $width
|
||||||
|
* @param int|null $height
|
||||||
|
* @param int $quality
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function resize(string $originalPath, ?int $width, ?int $height = null, int $quality = 80): string
|
||||||
|
{
|
||||||
|
if (empty($originalPath) || !Storage::disk('public')->exists($originalPath)) {
|
||||||
|
Log::warning("Image Service: Original path is empty or does not exist: {$originalPath}");
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$height = null;
|
||||||
|
|
||||||
|
$pathinfo = pathinfo($originalPath);
|
||||||
|
|
||||||
|
// Kembali menggunakan direktori 'resized' dan menyertakan dimensi di nama file
|
||||||
|
$resizedPath = "{$pathinfo['dirname']}/resized/{$pathinfo['filename']}_{$width}x{$height}_{$quality}.{$pathinfo['extension']}";
|
||||||
|
|
||||||
|
if (Storage::disk('public')->exists($resizedPath)) {
|
||||||
|
return $resizedPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$originalFullPath = Storage::disk('public')->path($originalPath);
|
||||||
|
$newFullPath = Storage::disk('public')->path($resizedPath);
|
||||||
|
|
||||||
|
$image = Image::read($originalFullPath);
|
||||||
|
|
||||||
|
// Resize dengan menjaga aspek rasio jika height null
|
||||||
|
if ($width && $height) {
|
||||||
|
// Paksa resize ke dimensi yang ditentukan, abaikan aspek rasio
|
||||||
|
$image->resize($width, $height);
|
||||||
|
} elseif ($width && !$height) {
|
||||||
|
// Resize hanya berdasarkan width, tinggi menyesuaikan aspek rasio
|
||||||
|
$image->scale(width: $width);
|
||||||
|
} elseif (!$width && $height) {
|
||||||
|
// Resize hanya berdasarkan height, lebar menyesuaikan aspek rasio
|
||||||
|
$image->scale(height: $height);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (!Storage::disk('public')->exists(dirname($resizedPath))) {
|
||||||
|
Storage::disk('public')->makeDirectory(dirname($resizedPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simpan dengan kualitas yang ditentukan
|
||||||
|
$image->save($newFullPath, $quality);
|
||||||
|
|
||||||
|
Log::info("Image Service: Successfully resized {$originalPath} to {$resizedPath} with quality {$quality}%.");
|
||||||
|
|
||||||
|
return $resizedPath;
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::error("Image Service: Resize failed for {$originalPath}. Error: " . $e->getMessage());
|
||||||
|
return $originalPath; // Fallback ke gambar asli jika gagal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
83
app/Services/InspeksiCleanupService.php
Normal file
83
app/Services/InspeksiCleanupService.php
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Lpj\Services;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Modules\Lpj\Jobs\CleanupInspeksiDataJob;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service untuk membersihkan data inspeksi yang tidak memiliki dokument_id
|
||||||
|
*
|
||||||
|
* Class ini menyediakan method untuk menjalankan cleanup data inspeksi
|
||||||
|
* ketika ada data baru dengan dokument_id yang sama
|
||||||
|
*/
|
||||||
|
class InspeksiCleanupService
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Dispatch job untuk cleanup data inspeksi
|
||||||
|
*
|
||||||
|
* @param int $permohonanId
|
||||||
|
* @param int $createdBy
|
||||||
|
* @param int|null $dokumentId
|
||||||
|
* @param bool $sync
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function cleanupInspeksiData(int $permohonanId, int $createdBy, ?int $dokumentId = null, bool $sync = false): void
|
||||||
|
{
|
||||||
|
Log::info('InspeksiCleanupService: Memulai cleanup data inspeksi', [
|
||||||
|
'permohonan_id' => $permohonanId,
|
||||||
|
'created_by' => $createdBy,
|
||||||
|
'dokument_id' => $dokumentId,
|
||||||
|
'sync' => $sync
|
||||||
|
]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$job = new CleanupInspeksiDataJob($permohonanId, $createdBy, $dokumentId);
|
||||||
|
|
||||||
|
if ($sync) {
|
||||||
|
// Jalankan secara synchronous (langsung)
|
||||||
|
$job->handle();
|
||||||
|
Log::info('InspeksiCleanupService: Cleanup selesai dijalankan secara sync');
|
||||||
|
} else {
|
||||||
|
// Dispatch ke queue
|
||||||
|
dispatch($job);
|
||||||
|
Log::info('InspeksiCleanupService: Cleanup job berhasil di-dispatch ke queue');
|
||||||
|
}
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::error('InspeksiCleanupService: Gagal menjalankan cleanup', [
|
||||||
|
'permohonan_id' => $permohonanId,
|
||||||
|
'created_by' => $createdBy,
|
||||||
|
'error' => $e->getMessage(),
|
||||||
|
'trace' => $e->getTraceAsString()
|
||||||
|
]);
|
||||||
|
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatch job untuk cleanup data inspeksi secara async (default)
|
||||||
|
*
|
||||||
|
* @param int $permohonanId
|
||||||
|
* @param int $createdBy
|
||||||
|
* @param int|null $dokumentId
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function cleanupAsync(int $permohonanId, int $createdBy, ?int $dokumentId = null): void
|
||||||
|
{
|
||||||
|
$this->cleanupInspeksiData($permohonanId, $createdBy, $dokumentId, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Jalankan cleanup data inspeksi secara sync
|
||||||
|
*
|
||||||
|
* @param int $permohonanId
|
||||||
|
* @param int $createdBy
|
||||||
|
* @param int|null $dokumentId
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function cleanupSync(int $permohonanId, int $createdBy, ?int $dokumentId = null): void
|
||||||
|
{
|
||||||
|
$this->cleanupInspeksiData($permohonanId, $createdBy, $dokumentId, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
736
app/Services/PreviewLaporanService.php
Normal file
736
app/Services/PreviewLaporanService.php
Normal file
@@ -0,0 +1,736 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Lpj\Services;
|
||||||
|
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use App\Helpers\Lpj;
|
||||||
|
use Modules\Lpj\Models\Denah;
|
||||||
|
use Modules\Lpj\Models\Teams;
|
||||||
|
use Modules\Lpj\Models\Branch;
|
||||||
|
use Modules\Lpj\Models\Lantai;
|
||||||
|
use Barryvdh\DomPDF\Facade\Pdf;
|
||||||
|
use Modules\Lpj\Models\Analisa;
|
||||||
|
use Modules\Lpj\Models\Penilai;
|
||||||
|
use Modules\Lpj\Models\Debiture;
|
||||||
|
use Modules\Lpj\Models\Inspeksi;
|
||||||
|
use Modules\Lpj\Models\Surveyor;
|
||||||
|
use Modules\Lpj\Models\ViewUnit;
|
||||||
|
use Modules\Location\Models\City;
|
||||||
|
use Modules\Lpj\Models\JenisUnit;
|
||||||
|
use Modules\Lpj\Models\Penilaian;
|
||||||
|
use Modules\Lpj\Models\Perizinan;
|
||||||
|
use Modules\Lpj\Models\BentukUnit;
|
||||||
|
use Modules\Lpj\Models\JenisKapal;
|
||||||
|
use Modules\Lpj\Models\LantaiUnit;
|
||||||
|
use Modules\Lpj\Models\Lingkungan;
|
||||||
|
use Modules\Lpj\Models\Permohonan;
|
||||||
|
use Modules\Lpj\Models\PosisiUnit;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Modules\Lpj\Models\AnalisaUnit;
|
||||||
|
use Modules\Lpj\Models\BentukTanah;
|
||||||
|
use Modules\Lpj\Models\FotoJaminan;
|
||||||
|
use Modules\Lpj\Models\KonturTanah;
|
||||||
|
use Modules\Lpj\Models\RuteJaminan;
|
||||||
|
use Modules\Location\Models\Village;
|
||||||
|
use Modules\Lpj\Models\AnalisaFakta;
|
||||||
|
use Modules\Lpj\Models\JenisJaminan;
|
||||||
|
use Modules\Lpj\Models\JenisPesawat;
|
||||||
|
use Modules\Lpj\Models\ObjekJaminan;
|
||||||
|
use Modules\Lpj\Models\SpekBangunan;
|
||||||
|
use Modules\Lpj\Models\TerletakArea;
|
||||||
|
use Modules\Location\Models\District;
|
||||||
|
use Modules\Location\Models\Province;
|
||||||
|
use Modules\Lpj\Models\ArahMataAngin;
|
||||||
|
use Modules\Lpj\Models\JenisBangunan;
|
||||||
|
use Modules\Lpj\Models\PosisiKavling;
|
||||||
|
use Modules\Lpj\Models\SifatBangunan;
|
||||||
|
use Modules\Lpj\Models\DokumenJaminan;
|
||||||
|
use Modules\Lpj\Models\FasilitasObjek;
|
||||||
|
use Modules\Lpj\Models\JenisKendaraan;
|
||||||
|
use Modules\Lpj\Models\ModelAlatBerat;
|
||||||
|
use Modules\Lpj\Models\KetinggianTanah;
|
||||||
|
use Modules\Lpj\Models\KondisiBangunan;
|
||||||
|
use Modules\Lpj\Models\LaporanExternal;
|
||||||
|
use Modules\Lpj\Models\MerupakanDaerah;
|
||||||
|
use Modules\Lpj\Models\PerkerasanJalan;
|
||||||
|
use Modules\Lpj\Models\SaranaPelengkap;
|
||||||
|
use Modules\Lpj\Models\TujuanPenilaian;
|
||||||
|
use Modules\Lpj\Models\FotoObjekJaminan;
|
||||||
|
use Modules\Lpj\Models\LaluLintasLokasi;
|
||||||
|
use Modules\Lpj\Models\TingkatKeramaian;
|
||||||
|
use Modules\Lpj\Models\AnalisaLingkungan;
|
||||||
|
use Modules\Lpj\Models\KondisiFisikTanah;
|
||||||
|
use Modules\Lpj\Models\AnalisaTanahBagunan;
|
||||||
|
use Modules\Lpj\Models\GolonganMasySekitar;
|
||||||
|
use Modules\Lpj\Models\SpekBangunanAnalisa;
|
||||||
|
use Modules\Lpj\Models\DetailDokumenJaminan;
|
||||||
|
use Modules\Lpj\Models\SpekKategoritBangunan;
|
||||||
|
use Modules\Lpj\Http\Requests\SurveyorRequest;
|
||||||
|
use Modules\Lpj\Models\HubunganPemilikJaminan;
|
||||||
|
use Modules\Lpj\Models\HubunganPenghuniJaminan;
|
||||||
|
use Modules\Lpj\Models\SpekBagunanAnalisaDetail;
|
||||||
|
use Modules\Lpj\Jobs\SendJadwalKunjunganEmailJob;
|
||||||
|
use Modules\Lpj\Http\Requests\FormSurveyorRequest;
|
||||||
|
|
||||||
|
class PreviewLaporanService
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Preview Laporan dan unduh foto terkait dengan logika fallback path.
|
||||||
|
*
|
||||||
|
* Menghasilkan PDF atau paket unduhan foto berdasarkan status laporan.
|
||||||
|
* Jika file foto asli tidak ditemukan dan status LPJ adalah 1, maka
|
||||||
|
* sistem akan mencoba menggunakan fallback path dengan pola
|
||||||
|
* `surveyor/001/{lastTwoParts}` untuk meminimalisir gambar hilang.
|
||||||
|
*
|
||||||
|
* @param int $permohonan_id ID Permohonan
|
||||||
|
* @param int $dokumen_id ID Dokumen
|
||||||
|
* @param int $jaminan_id ID Jaminan
|
||||||
|
* @param string $back URL atau rute kembali
|
||||||
|
* @return \Symfony\Component\HttpFoundation\Response
|
||||||
|
*/
|
||||||
|
public function previewLaporan($permohonan_id, $dokumen_id, $jaminan_id, $back)
|
||||||
|
{
|
||||||
|
$permohonan = $this->getPermohonanJaminanId(
|
||||||
|
$permohonan_id,
|
||||||
|
$dokumen_id,
|
||||||
|
$jaminan_id
|
||||||
|
);
|
||||||
|
// $tipeLaporanResponse = $this->checkPrintOutLaporan($permohonan_id, $document_id);
|
||||||
|
// $tipeLaporan = $tipeLaporanResponse->getData();
|
||||||
|
|
||||||
|
// if (!$tipeLaporan->status) {
|
||||||
|
// return redirect()->back()->with('error', 'Laporan tidak valid');
|
||||||
|
// }
|
||||||
|
$basicData = $this->getCommonData();
|
||||||
|
|
||||||
|
$inspeksi = Inspeksi::where('permohonan_id', $permohonan_id)->where('dokument_id', $dokumen_id)->first();
|
||||||
|
$lpj = Penilai::where('permohonan_id', $permohonan_id)->where('dokument_id', $dokumen_id)->first();
|
||||||
|
|
||||||
|
$mig_permohonan = json_decode($permohonan->mig_permohonan);
|
||||||
|
|
||||||
|
$nomorLaporan = getNomorLaporan($permohonan_id, $dokumen_id);
|
||||||
|
$tanggalLaporan = $permohonan->is_mig
|
||||||
|
? ($mig_permohonan->mig_mst_jaminan_tgl_laporan ?? $mig_permohonan->mig_mst_jaminan_tgl_create ?? null)
|
||||||
|
: ($lpj->created_at ?? null);
|
||||||
|
$forminspeksi = null;
|
||||||
|
$lpjData = null;
|
||||||
|
$formFoto = null;
|
||||||
|
|
||||||
|
// if ($inspeksi) {
|
||||||
|
$forminspeksi = json_decode($inspeksi?->data_form, true) ?? null;
|
||||||
|
|
||||||
|
$formFoto = json_decode($inspeksi?->foto_form, true) ?? null;
|
||||||
|
// $denahForm = json_decode($data->denah_form, true);
|
||||||
|
$dataPembanding = json_decode($inspeksi?->data_pembanding, true) ?? null;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if ($lpj) {
|
||||||
|
$lpjData = json_decode($lpj?->lpj, true) ?? null;
|
||||||
|
$memo = json_decode($lpj?->memo, true) ?? null;
|
||||||
|
$resumeData = json_decode($lpj?->resume, true) ?? null;
|
||||||
|
$rap = json_decode($lpj?->rap, true);
|
||||||
|
$report = json_decode($lpj?->call_report, true) ?? null;
|
||||||
|
// }
|
||||||
|
|
||||||
|
$inputAddress = $forminspeksi['asset']['alamat']['sesuai'] ?? $forminspeksi['asset']['alamat']['tidak sesuai'] ?? [];
|
||||||
|
|
||||||
|
$alamat = [
|
||||||
|
'address' => $inputAddress['address'] ?? null,
|
||||||
|
'village_code' => getWilayahName($inputAddress['village_code'] ?? null, 'village'),
|
||||||
|
'district_code' => getWilayahName($inputAddress['district_code'] ?? null, 'district'),
|
||||||
|
'city_code' => getWilayahName($inputAddress['city_code'] ?? null, 'city'),
|
||||||
|
'province_code' => getWilayahName($inputAddress['province_code'] ?? null, 'province')
|
||||||
|
];
|
||||||
|
|
||||||
|
$statusLpj = 0;
|
||||||
|
|
||||||
|
// $viewLaporan = $this->getViewLaporan($tipeLaporan);
|
||||||
|
return view('lpj::component.show-laporan-inspeksi', compact('permohonan', 'basicData', 'forminspeksi', 'alamat', 'lpjData', 'memo', 'resumeData', 'rap', 'report', 'lpj', 'formFoto', 'nomorLaporan', 'tanggalLaporan', 'dataPembanding', 'inspeksi', 'statusLpj', 'permohonan_id', 'back', ));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function printOutLaporan($permohonan_id, $document_id, $jaminan_id)
|
||||||
|
{
|
||||||
|
$tipeLaporanResponse = $this->checkPrintOutLaporan($permohonan_id, $document_id);
|
||||||
|
$tipeLaporan = $tipeLaporanResponse->getData();
|
||||||
|
|
||||||
|
//dd($permohonan_id, $document_id, $tipeLaporan);
|
||||||
|
|
||||||
|
if (!$tipeLaporan->status) {
|
||||||
|
//return redirect()->back()->with('error', 'Laporan tidak valid');
|
||||||
|
}
|
||||||
|
$permohonan = $this->getPermohonanJaminanId(
|
||||||
|
$permohonan_id,
|
||||||
|
$document_id,
|
||||||
|
$jaminan_id
|
||||||
|
);
|
||||||
|
|
||||||
|
$basicData = $this->getCommonData();
|
||||||
|
|
||||||
|
$inspeksi = Inspeksi::where('permohonan_id', $permohonan_id)->where('dokument_id', $document_id)->first();
|
||||||
|
$lpj = Penilai::where('permohonan_id', $permohonan_id)->first(); //->where('dokument_id', $document_id)->first();
|
||||||
|
|
||||||
|
$mig_permohonan = json_decode($permohonan->mig_permohonan);
|
||||||
|
$nomorLaporan = getNomorLaporan($permohonan_id, $document_id);
|
||||||
|
|
||||||
|
//Carbon::createFromFormat('d/m/Y H:i:s', $mig_permohonan->mig_mst_jaminan_tgl_laporan)->format('Y-m-d H:i:s');
|
||||||
|
|
||||||
|
$tanggalLaporan = $permohonan->is_mig
|
||||||
|
? ($mig_permohonan->mig_mst_jaminan_tgl_laporan
|
||||||
|
? Carbon::createFromFormat('d/m/Y H:i:s', $mig_permohonan->mig_mst_jaminan_tgl_laporan)->format('Y-m-d H:i:s')
|
||||||
|
: ($mig_permohonan->mig_mst_jaminan_tgl_oto
|
||||||
|
? Carbon::createFromFormat('d/m/Y H:i:s', $mig_permohonan->mig_mst_jaminan_tgl_oto)->format('Y-m-d H:i:s')
|
||||||
|
: null))
|
||||||
|
: ($lpj->created_at ?? null);
|
||||||
|
|
||||||
|
|
||||||
|
$forminspeksi = null;
|
||||||
|
$lpjData = null;
|
||||||
|
$formFoto = null;
|
||||||
|
|
||||||
|
$dataPembanding ='';
|
||||||
|
if ($inspeksi) {
|
||||||
|
$forminspeksi = json_decode($inspeksi->data_form, true);
|
||||||
|
$formFoto = json_decode($inspeksi->foto_form, true);
|
||||||
|
// $denahForm = json_decode($data->denah_form, true);
|
||||||
|
$dataPembanding = json_decode($inspeksi->data_pembanding, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if ($lpj) {
|
||||||
|
$lpjData = json_decode($lpj->lpj, true);
|
||||||
|
$memo = json_decode($lpj->memo, true);
|
||||||
|
$resumeData = json_decode($lpj->resume, true);
|
||||||
|
$rap = json_decode($lpj->rap, true);
|
||||||
|
$report = json_decode($lpj->call_report, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$inputAddress = $forminspeksi['asset']['alamat']['sesuai'] ?? $forminspeksi['asset']['alamat']['tidak sesuai'] ?? [];
|
||||||
|
|
||||||
|
$inputAddress = $forminspeksi['asset']['alamat']['sesuai'] ?? $forminspeksi['asset']['alamat']['tidak sesuai'] ?? [];
|
||||||
|
$alamat = [
|
||||||
|
'address' => $inputAddress['address'] ?? null,
|
||||||
|
'village_code' => getWilayahName($inputAddress['village_code'] ?? null, 'village'),
|
||||||
|
'district_code' => getWilayahName($inputAddress['district_code'] ?? null, 'district'),
|
||||||
|
'city_code' => getWilayahName($inputAddress['city_code'] ?? null, 'city'),
|
||||||
|
'province_code' => getWilayahName($inputAddress['province_code'] ?? null, 'province')
|
||||||
|
];
|
||||||
|
|
||||||
|
$viewLaporan = $this->getViewLaporan($tipeLaporan->status);
|
||||||
|
|
||||||
|
$statusLpj = 1;
|
||||||
|
|
||||||
|
$mig_permohonan = json_decode($permohonan->mig_permohonan);
|
||||||
|
$nilaiPasar = $mig_permohonan->mig_mst_lpj_tot_nilai_pasar ?? null;
|
||||||
|
|
||||||
|
if(($tipeLaporan->status === 'memo' && $permohonan->mig_permohonan && $permohonan->is_mig) || ($nilaiPasar !== null && $nilaiPasar < 1 && $permohonan->is_mig)){
|
||||||
|
$paths = $formFoto['upload_foto'] ?? null;
|
||||||
|
|
||||||
|
if (!is_array($paths) || empty($paths)) {
|
||||||
|
return response()->json(['error' => 'No files to download'], 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
$files = [];
|
||||||
|
foreach ($paths as $path) {
|
||||||
|
if (!$path['path']) {
|
||||||
|
Log::warning('PreviewLaporanService: Path kosong terdeteksi dalam daftar paths.');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Logika fallback untuk path file
|
||||||
|
$originalPath = $path['path'];
|
||||||
|
$fallbackPath = null;
|
||||||
|
|
||||||
|
// Jika file asli tidak ditemukan, buat fallback path
|
||||||
|
if ($statusLpj == 1) {
|
||||||
|
$fullOriginalPath = storage_path('app/public/' . $originalPath);
|
||||||
|
|
||||||
|
if (!file_exists($fullOriginalPath)) {
|
||||||
|
// Ekstrak bagian akhir path (contoh: 251051/251051_2_2.png)
|
||||||
|
$pathParts = explode('/', $originalPath);
|
||||||
|
if (count($pathParts) >= 2) {
|
||||||
|
$lastTwoParts = array_slice($pathParts, -2);
|
||||||
|
$fallbackPath = 'surveyor/001/' . implode('/', $lastTwoParts);
|
||||||
|
Log::info('PreviewLaporanService: Menggunakan fallback path kandidat.', [
|
||||||
|
'original' => $originalPath,
|
||||||
|
'fallback' => $fallbackPath,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tentukan path yang akan digunakan
|
||||||
|
$pathToUse = ($fallbackPath && $statusLpj == 1 && file_exists(storage_path('app/public/' . $fallbackPath)))
|
||||||
|
? $fallbackPath
|
||||||
|
: $originalPath;
|
||||||
|
|
||||||
|
$fullPath = storage_path('app/public/' . $pathToUse);
|
||||||
|
if (!file_exists($fullPath)) {
|
||||||
|
Log::warning('PreviewLaporanService: File tidak ditemukan untuk original maupun fallback.', [
|
||||||
|
'original' => $originalPath,
|
||||||
|
'fallback' => $fallbackPath,
|
||||||
|
'resolved' => $pathToUse,
|
||||||
|
]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::info('PreviewLaporanService: Menambahkan file untuk diunduh.', [
|
||||||
|
'resolved' => $pathToUse,
|
||||||
|
'fullPath' => $fullPath,
|
||||||
|
]);
|
||||||
|
$files[] = $fullPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($files)) {
|
||||||
|
Log::warning('PreviewLaporanService: Tidak ada file valid ditemukan setelah resolusi path.');
|
||||||
|
return response()->json(['error' => 'No valid files found'], 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
// For single file, download directly
|
||||||
|
if (count($files) === 1) {
|
||||||
|
Log::info('PreviewLaporanService: Mengunduh single file.', ['file' => $files[0]]);
|
||||||
|
return response()->download($files[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// For multiple files, create zip and download
|
||||||
|
$zipName = 'photos_' . time() . '.zip';
|
||||||
|
$zipPath = storage_path('app/public/' . $zipName);
|
||||||
|
|
||||||
|
$zip = new \ZipArchive();
|
||||||
|
if ($zip->open($zipPath, \ZipArchive::CREATE) === true) {
|
||||||
|
foreach ($files as $file) {
|
||||||
|
$zip->addFile($file, basename($file));
|
||||||
|
}
|
||||||
|
$zip->close();
|
||||||
|
Log::info('PreviewLaporanService: Zip file berhasil dibuat.', ['zip' => $zipPath, 'count' => count($files)]);
|
||||||
|
return response()->download($zipPath)->deleteFileAfterSend(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::error('PreviewLaporanService: Gagal membuat zip file.');
|
||||||
|
return response()->json(['error' => 'Failed to create zip file'], 500);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$pdf = $this->generatePDF($viewLaporan, compact(
|
||||||
|
'permohonan',
|
||||||
|
'forminspeksi',
|
||||||
|
'lpjData',
|
||||||
|
'formFoto',
|
||||||
|
'basicData',
|
||||||
|
'inspeksi',
|
||||||
|
'lpj',
|
||||||
|
'statusLpj',
|
||||||
|
'alamat',
|
||||||
|
'dataPembanding',
|
||||||
|
'nomorLaporan',
|
||||||
|
'memo',
|
||||||
|
'resumeData',
|
||||||
|
'tanggalLaporan',
|
||||||
|
'rap',
|
||||||
|
'report'
|
||||||
|
));
|
||||||
|
|
||||||
|
$cleanNomorLaporan = str_replace(['/', '\\'], '-', $nomorLaporan);
|
||||||
|
$filename = 'Laporan_' . $tipeLaporan->status . '_' . $permohonan->debiture->name . '_' . $cleanNomorLaporan;
|
||||||
|
|
||||||
|
return $pdf->download($filename . '_data.pdf');
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::error('PDF generation failed: ' . $e->getMessage());
|
||||||
|
return response()->json(['error' => 'Failed to generate PDF. Please check the log for details.'], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function generatePDF(string $viewLaporan, array $data)
|
||||||
|
{
|
||||||
|
//return view('lpj::' . $viewLaporan, $data);
|
||||||
|
|
||||||
|
$pdf = PDF::loadView('lpj::' . $viewLaporan, $data);
|
||||||
|
$pdf->setPaper('A4', 'portrait');
|
||||||
|
$pdf->set_option('isHtml5ParserEnabled', true);
|
||||||
|
$pdf->set_option('isPhpEnabled', true);
|
||||||
|
$pdf->set_option('dpi', '96');
|
||||||
|
|
||||||
|
return $pdf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private function getViewLaporan($tipe)
|
||||||
|
{
|
||||||
|
$viewMap = [
|
||||||
|
'sederhana' => 'penilai.components.print-out-sederhana',
|
||||||
|
'standar' => 'penilai.components.print-out-standar',
|
||||||
|
'resume' => 'penilai.components.print-resume',
|
||||||
|
'memo' => 'penilai.components.print-memo',
|
||||||
|
'rap' => 'penilai.components.print-out-rap',
|
||||||
|
'call-report' => 'penilai.components.print-out-call-report'
|
||||||
|
];
|
||||||
|
return $viewMap[$tipe] ?? 'penilai.components.print-resume';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function checkPrintOutLaporan($permohonan_id, $dokumen_id)
|
||||||
|
{
|
||||||
|
|
||||||
|
// Ambil data berdasarkan ID
|
||||||
|
$statusLpj = Penilai::where('permohonan_id', $permohonan_id)
|
||||||
|
//->where('dokument_id', $dokumen_id)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
|
||||||
|
$permohonan = Permohonan::where('id', $permohonan_id)->first();
|
||||||
|
|
||||||
|
// Jika data tidak ditemukan, kembalikan status null
|
||||||
|
if (!$statusLpj) {
|
||||||
|
return response()->json(['status' => null]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tentukan tipe berdasarkan kondisi
|
||||||
|
$type = $statusLpj->type_penilai ?? null;
|
||||||
|
|
||||||
|
if ($type === 'memo' && $permohonan->is_mig!=1) {
|
||||||
|
return $this->checkDataMemo($type, $statusLpj);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($type === 'resume') {
|
||||||
|
return $this->checkDataResume($type, $statusLpj);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if ($type === 'standar' || $type === 'sederhana') {
|
||||||
|
return $this->checkDataLpj($type, $statusLpj);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($type === 'rap') {
|
||||||
|
return $this->checkDataRap($type, $statusLpj);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Kembalikan respons dengan tipe yang sesuai
|
||||||
|
return response()->json(['status' => $type]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function checkDataMemo($type, $statusLpj)
|
||||||
|
{
|
||||||
|
// Ambil data JSON dari statusLpj
|
||||||
|
$data = json_decode($statusLpj->memo, true) ?? [];
|
||||||
|
|
||||||
|
|
||||||
|
$validationRules = [
|
||||||
|
'memo' => [
|
||||||
|
'kepada',
|
||||||
|
'dari',
|
||||||
|
'nomor_memo',
|
||||||
|
'tanggal',
|
||||||
|
'perihal',
|
||||||
|
'jenis_asset_tidak_sesuai',
|
||||||
|
'lokasi.lokasi',
|
||||||
|
'lokasi.province_code',
|
||||||
|
'lokasi.city_code',
|
||||||
|
'lokasi.district_code',
|
||||||
|
'lokasi.village_code',
|
||||||
|
'lokasi.penilai',
|
||||||
|
'terlampir',
|
||||||
|
'hasil_survey',
|
||||||
|
'kesimpulan_saran',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
// Validasi data JSON
|
||||||
|
if (isset($validationRules[$type])) {
|
||||||
|
$missingFields = [];
|
||||||
|
|
||||||
|
foreach ($validationRules[$type] as $field) {
|
||||||
|
$keys = explode('.', $field);
|
||||||
|
$value = $data;
|
||||||
|
|
||||||
|
foreach ($keys as $key) {
|
||||||
|
if (!isset($value[$key])) {
|
||||||
|
$missingFields[] = $field;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$value = $value[$key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Jika ada field yang kosong, kembalikan error
|
||||||
|
if (!empty($missingFields)) {
|
||||||
|
return response()->json([
|
||||||
|
'status' => null,
|
||||||
|
'message' => "Silahkan lengkapi data memo terlebih dahulu.",
|
||||||
|
'missing_fields' => $missingFields,
|
||||||
|
], 400);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Jika data valid
|
||||||
|
return response()->json([
|
||||||
|
'status' => $type,
|
||||||
|
'message' => "Data memo valid.",
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function checkDataResume($type, $statusLpj)
|
||||||
|
{
|
||||||
|
// Ambil data JSON dari statusLpj
|
||||||
|
$data = json_decode($statusLpj->resume, true) ?? [];
|
||||||
|
|
||||||
|
$validationRules = [
|
||||||
|
'resume' => [
|
||||||
|
'fisik'
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
// Validasi data JSON
|
||||||
|
if (isset($validationRules[$type])) {
|
||||||
|
$missingFields = [];
|
||||||
|
|
||||||
|
foreach ($validationRules[$type] as $field) {
|
||||||
|
$keys = explode('.', $field);
|
||||||
|
$value = $data;
|
||||||
|
|
||||||
|
foreach ($keys as $key) {
|
||||||
|
if (!isset($value[$key])) {
|
||||||
|
$missingFields[] = $field;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$value = $value[$key];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validasi khusus untuk array fisik dan sesuai_imb
|
||||||
|
if ($field === 'fisik' || $field === 'sesuai_imb') {
|
||||||
|
if (empty($value) || !is_array($value)) {
|
||||||
|
$missingFields[] = $field;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validasi struktur data di dalam array
|
||||||
|
foreach ($value as $item) {
|
||||||
|
$requiredKeys = ['sertifikat', 'luas_tanah', 'nilai'];
|
||||||
|
foreach ($requiredKeys as $requiredKey) {
|
||||||
|
if (!isset($item[$requiredKey])) {
|
||||||
|
$missingFields[] = $field . '.' . $requiredKey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Jika ada field yang kosong, kembalikan error
|
||||||
|
if (!empty($missingFields)) {
|
||||||
|
return response()->json([
|
||||||
|
'status' => null,
|
||||||
|
'message' => "Silahkan lengkapi data resume terlebih dahulu.",
|
||||||
|
'missing_fields' => $missingFields,
|
||||||
|
], 400);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Jika data valid
|
||||||
|
return response()->json([
|
||||||
|
'status' => $type,
|
||||||
|
'message' => "Data resume valid.",
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function checkDataLpj($type, $statusLpj)
|
||||||
|
{
|
||||||
|
// Ambil data JSON dari statusLpj
|
||||||
|
$data = json_decode($statusLpj->lpj, true) ?? [];
|
||||||
|
|
||||||
|
$validationRules = [
|
||||||
|
'lpj' => [
|
||||||
|
'luas_tanah',
|
||||||
|
'nilai_tanah_1',
|
||||||
|
'nilai_tanah_2',
|
||||||
|
'luas_bangunan',
|
||||||
|
'nilai_bangunan_1',
|
||||||
|
'nilai_bangunan_2',
|
||||||
|
'total_nilai_pasar_wajar',
|
||||||
|
'likuidasi',
|
||||||
|
'likuidasi_nilai_1',
|
||||||
|
'likuidasi_nilai_2',
|
||||||
|
'asuransi_luas_bangunan',
|
||||||
|
'asuransi_nilai_1',
|
||||||
|
'asuransi_nilai_2',
|
||||||
|
'npw_tambahan'
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
// Validasi data JSON
|
||||||
|
if (isset($validationRules[$type])) {
|
||||||
|
$missingFields = [];
|
||||||
|
|
||||||
|
foreach ($validationRules[$type] as $field) {
|
||||||
|
// Penanganan khusus untuk field yang boleh null
|
||||||
|
if (in_array($field, ['sarana_pelengkap_penilai', 'nilai_sarana_pelengkap_1', 'nilai_sarana_pelengkap_2'])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($data[$field])) {
|
||||||
|
$missingFields[] = $field;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validasi khusus untuk npw_tambahan
|
||||||
|
if ($field === 'npw_tambahan' && is_array($data[$field])) {
|
||||||
|
foreach ($data[$field] as $index => $item) {
|
||||||
|
$requiredKeys = ['name', 'luas', 'nilai_1', 'nilai_2'];
|
||||||
|
foreach ($requiredKeys as $key) {
|
||||||
|
if (!isset($item[$key])) {
|
||||||
|
$missingFields[] = "npw_tambahan[$index].$key";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Jika ada field yang kosong, kembalikan error
|
||||||
|
if (!empty($missingFields)) {
|
||||||
|
return response()->json([
|
||||||
|
'status' => null,
|
||||||
|
'message' => "Silahkan lengkapi data LPJ terlebih dahulu.",
|
||||||
|
'missing_fields' => $missingFields,
|
||||||
|
], 400);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Jika data valid
|
||||||
|
return response()->json([
|
||||||
|
'status' => $type,
|
||||||
|
'message' => "Data LPJ valid.",
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function checkDataRap($type, $statusLpj)
|
||||||
|
{
|
||||||
|
// Ambil data JSON dari statusLpj
|
||||||
|
$data = json_decode($statusLpj->rap, true) ?? [];
|
||||||
|
|
||||||
|
$requiredFields = [
|
||||||
|
'dari',
|
||||||
|
'kepada',
|
||||||
|
'perihal',
|
||||||
|
'tanggal',
|
||||||
|
'nomor_rap'
|
||||||
|
];
|
||||||
|
|
||||||
|
// Cek apakah ada field yang kosong
|
||||||
|
$missingFields = [];
|
||||||
|
foreach ($requiredFields as $field) {
|
||||||
|
if (!isset($data[$field]) || empty($data[$field])) {
|
||||||
|
$missingFields[] = $field;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Jika ada field yang kosong, kembalikan error
|
||||||
|
if (!empty($missingFields)) {
|
||||||
|
return response()->json([
|
||||||
|
'status' => null,
|
||||||
|
'message' => "Silahkan lengkapi data RAP terlebih dahulu.",
|
||||||
|
'missing_fields' => $missingFields
|
||||||
|
], 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Jika semua data terisi
|
||||||
|
return response()->json([
|
||||||
|
'status' => $type,
|
||||||
|
'message' => "Data RAP valid."
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
private function getPermohonanJaminanId($id, $dokumentId, $jaminanId)
|
||||||
|
{
|
||||||
|
return Permohonan::with([
|
||||||
|
'user',
|
||||||
|
'debiture.province',
|
||||||
|
'debiture.city',
|
||||||
|
'debiture.district',
|
||||||
|
'debiture.village',
|
||||||
|
'branch',
|
||||||
|
'tujuanPenilaian',
|
||||||
|
'penilaian',
|
||||||
|
'penawaran',
|
||||||
|
'debiture.documents' => function ($query) use ($dokumentId, $jaminanId) {
|
||||||
|
$query->where('id', $dokumentId)
|
||||||
|
->where('jenis_jaminan_id', $jaminanId);
|
||||||
|
}
|
||||||
|
])->findOrFail($id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCommonData()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'branches' => Branch::all(),
|
||||||
|
'bentukTanah' => BentukTanah::all(),
|
||||||
|
'konturTanah' => KonturTanah::all(),
|
||||||
|
'posisiKavling' => PosisiKavling::all(),
|
||||||
|
'ketinggianTanah' => KetinggianTanah::all(),
|
||||||
|
'kondisiFisikTanah' => KondisiFisikTanah::all(),
|
||||||
|
'jenisBangunan' => JenisBangunan::all(),
|
||||||
|
'kondisiBangunan' => KondisiBangunan::all(),
|
||||||
|
'sifatBangunan' => SifatBangunan::all(),
|
||||||
|
'spekKategoriBangunan' => SpekKategoritBangunan::all(),
|
||||||
|
'spekBangunan' => SpekBangunan::all(),
|
||||||
|
'saranaPelengkap' => SaranaPelengkap::all(),
|
||||||
|
'arahMataAngin' => ArahMataAngin::all(),
|
||||||
|
'lantai' => Lantai::all(),
|
||||||
|
'viewUnit' => ViewUnit::all(),
|
||||||
|
'golMasySekitar' => GolonganMasySekitar::all(),
|
||||||
|
'tingkatKeramaian' => TingkatKeramaian::all(),
|
||||||
|
'laluLintasLokasi' => LaluLintasLokasi::all(),
|
||||||
|
'jenisPesawat' => JenisPesawat::all(),
|
||||||
|
'modelAlatBerat' => ModelAlatBerat::all(),
|
||||||
|
'jenisKapal' => JenisKapal::all(),
|
||||||
|
'jenisKendaraan' => JenisKendaraan::all(),
|
||||||
|
'terletakArea' => TerletakArea::all(),
|
||||||
|
'posisiUnit' => PosisiUnit::all(),
|
||||||
|
'bentukUnit' => BentukUnit::all(),
|
||||||
|
'fasilitasObjek' => FasilitasObjek::all(),
|
||||||
|
'merupakanDaerah' => MerupakanDaerah::all(),
|
||||||
|
'jenisUnit' => JenisUnit::all(),
|
||||||
|
'jenisJaminan' => JenisJaminan::all(),
|
||||||
|
'hubCadeb' => HubunganPemilikJaminan::all(),
|
||||||
|
'hubPenghuni' => HubunganPenghuniJaminan::all(),
|
||||||
|
'perkerasanJalan' => PerkerasanJalan::all(),
|
||||||
|
'terletakDiArea' => TerletakArea::all(),
|
||||||
|
'tujuanPenilaian' => TujuanPenilaian::all(),
|
||||||
|
'perizinan' => Perizinan::all(),
|
||||||
|
'foto' => FotoObjekJaminan::all()
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
private const HEADERS = [
|
||||||
|
'bentuk-tanah' => ['Bentuk Tanah', 'bentuk-tanah'],
|
||||||
|
'kontur-tanah' => ['Kontur Tanah', 'kontur-tanah'],
|
||||||
|
'posisi-kavling' => ['Posisi Kavling', 'posisi-kavling'],
|
||||||
|
'ketinggian-tanah' => ['Ketinggian Tanah', 'ketinggian-tanah'],
|
||||||
|
'kondisi-fisik-tanah' => ['Kondisi Fisik Tanah', 'kondisi-fisik-tanah'],
|
||||||
|
'jenis-bangunan' => ['Jenis Bangunan', 'jenis-bangunan'],
|
||||||
|
'kondisi-bangunan' => ['Kondisi Bangunan', 'kondisi-bangunan'],
|
||||||
|
'sifat-bangunan' => ['Sifat Bangunan', 'sifat-bangunan'],
|
||||||
|
'sarana-pelengkap' => ['Sarana Pelengkap', 'sarana-pelengkap'],
|
||||||
|
'lalu-lintas-lokasi' => ['Lalu Lintas Depan Lokasi', 'lalu-lintas-lokasi'],
|
||||||
|
'tingkat-keramaian' => ['Tingkat Keramaian', 'tingkat-keramaian'],
|
||||||
|
'gol-mas-sekitar' => ['Golongan Masyarakat Sekitar', 'gol-mas-sekitar'],
|
||||||
|
'spek-kategori-bangunan' => ['Spek Kategori Bangunan', 'spek-kategori-bangunan'],
|
||||||
|
'spek-bangunan' => ['Spek Bangunan', 'spek-bangunan'],
|
||||||
|
'lantai-unit' => ['Lantai Unit', 'lantai-unit'],
|
||||||
|
'view-unit' => ['View Unit', 'view-unit'],
|
||||||
|
'perkerasan-jalan' => ['Perkerasan jalan', 'perkerasan-jalan'],
|
||||||
|
'jenis-pesawat' => ['Jenis pesawat', 'jenis-pesawat'],
|
||||||
|
'model-alat-berat' => ['Model alat berat', 'model-alat-berat'],
|
||||||
|
'jenis-kapal' => ['Jenis kapal', 'jenis-kapal'],
|
||||||
|
'jenis-kendaraan' => ['Jenis kendaraan', 'jenis-kendaraan'],
|
||||||
|
'jenis-unit' => ['Jenis unit', 'jenis-unit'],
|
||||||
|
'terletak-area' => ['Terletak di Area', 'terletak-area'],
|
||||||
|
'merupakan-daerah' => ['Merupakan Daerah', 'merupakan-daerah'],
|
||||||
|
'posisi-unit' => ['Posisi unit', 'posisi-unit'],
|
||||||
|
'bentuk-unit' => ['Bentuk unit', 'bentuk-unit'],
|
||||||
|
'fasilitas-objek' => ['Fasilitas Umum Dekat Objek', 'fasilitas-objek'],
|
||||||
|
'foto-objek-jaminan' => ['Foto Objek Jaminan', 'foto-objek-jaminan'],
|
||||||
|
'perizinan' => ['Perizinan', 'perizinan'],
|
||||||
|
];
|
||||||
|
|
||||||
|
}
|
||||||
@@ -4,7 +4,6 @@ namespace Modules\Lpj\Services;
|
|||||||
|
|
||||||
use Modules\Lpj\Models\Inspeksi;
|
use Modules\Lpj\Models\Inspeksi;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use \Illuminate\Support\Facades\Log;
|
|
||||||
|
|
||||||
class SaveFormInspesksiService
|
class SaveFormInspesksiService
|
||||||
{
|
{
|
||||||
@@ -21,7 +20,6 @@ class SaveFormInspesksiService
|
|||||||
$inspeksi->name = $request->input('type');
|
$inspeksi->name = $request->input('type');
|
||||||
|
|
||||||
$processedData = $this->getActionSpecificRules($validatedData, $type, $request, $inspeksi);
|
$processedData = $this->getActionSpecificRules($validatedData, $type, $request, $inspeksi);
|
||||||
Log::info($processedData);
|
|
||||||
|
|
||||||
// Merge data lama dengan data baru
|
// Merge data lama dengan data baru
|
||||||
$existingData = json_decode($inspeksi->data_form, true) ?: [];
|
$existingData = json_decode($inspeksi->data_form, true) ?: [];
|
||||||
@@ -35,7 +33,6 @@ class SaveFormInspesksiService
|
|||||||
'upload_gs'
|
'upload_gs'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
foreach ($fotoTypes as $fotoType) {
|
foreach ($fotoTypes as $fotoType) {
|
||||||
if (isset($existingData[$fotoType])) {
|
if (isset($existingData[$fotoType])) {
|
||||||
$processedData[$fotoType] = $existingData[$fotoType];
|
$processedData[$fotoType] = $existingData[$fotoType];
|
||||||
@@ -60,7 +57,7 @@ class SaveFormInspesksiService
|
|||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
return [
|
return [
|
||||||
'success' => false,
|
'success' => false,
|
||||||
'message' => 'Gagal menyimpan data : '.$e->getMessage(),
|
'message' => 'Gagal menyimpan data',
|
||||||
'error' => $e->getMessage()
|
'error' => $e->getMessage()
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -88,31 +85,36 @@ class SaveFormInspesksiService
|
|||||||
$hasAssetDescriptionRules = false;
|
$hasAssetDescriptionRules = false;
|
||||||
$hasFactaData = false;
|
$hasFactaData = false;
|
||||||
|
|
||||||
$actions = array_map('trim', explode(',', $action));
|
|
||||||
$pisah = array_filter($actions, function($act) use ($allowedActions) {
|
|
||||||
return isset($allowedActions[$act]);
|
$pisah = array_filter(
|
||||||
});
|
explode(',', $action),
|
||||||
|
function ($act) use ($allowedActions) {
|
||||||
|
return isset($allowedActions[trim($act)]);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// dd($pisah);
|
||||||
|
|
||||||
foreach ($pisah as $act) {
|
foreach ($pisah as $act) {
|
||||||
$act = trim($act); // Bersihkan spasi
|
$act = trim($act); // Bersihkan spasi
|
||||||
if($act){
|
if (isset($allowedActions[$act])) {
|
||||||
if (isset($allowedActions[$act])) {
|
$method = $allowedActions[$act];
|
||||||
$method = $allowedActions[$act];
|
|
||||||
|
|
||||||
$actionRules = $this->$method($data, $request, $inspeksi);
|
$actionRules = $this->$method($data, $request, $inspeksi);
|
||||||
$rules = array_merge($rules, $actionRules);
|
$rules = array_merge($rules, $actionRules);
|
||||||
// Cek apakah act memerlukan asset description rules
|
|
||||||
if($act){
|
|
||||||
if (in_array($act, ['apartemen-kantor', 'tanah', 'bangunan', 'rap'])) {
|
|
||||||
$hasAssetDescriptionRules = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (in_array($act, ['rap'])) {
|
// Cek apakah act memerlukan asset description rules
|
||||||
$hasFactaData = true;
|
if (in_array($act, ['apartemen-kantor', 'tanah', 'bangunan', 'rap'])) {
|
||||||
}
|
$hasAssetDescriptionRules = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cek apakah act memerlukan fakta data
|
||||||
|
if (in_array($act, ['rap'])) {
|
||||||
|
$hasFactaData = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($hasAssetDescriptionRules) {
|
if ($hasAssetDescriptionRules) {
|
||||||
|
|||||||
107
app/Services/TypeLaporanService.php
Normal file
107
app/Services/TypeLaporanService.php
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Lpj\Services;
|
||||||
|
|
||||||
|
class TypeLaporanService
|
||||||
|
{
|
||||||
|
public function handleRequest($type, $permohonanId, $documentId, $jaminanId, $surveyorController)
|
||||||
|
{
|
||||||
|
$permohonan = $this->getPermohonanData($surveyorController, $permohonanId, $documentId, $jaminanId);
|
||||||
|
|
||||||
|
if ($permohonan->status == 'proses-laporan') {
|
||||||
|
throw new \Exception('Masih dalam proses laporan');
|
||||||
|
}
|
||||||
|
|
||||||
|
$nomorLaporan = $this->generateNomorLaporan($surveyorController, $permohonan, $documentId, $type);
|
||||||
|
$inspeksi = $this->getInspeksi($permohonanId, $documentId);
|
||||||
|
$this->updatePenilai($permohonanId, $documentId, $type);
|
||||||
|
|
||||||
|
$debitur = Debiture::find($permohonan->debiture_id);
|
||||||
|
$forminspeksi = $inspeksi ? json_decode($inspeksi->data_form, true) : null;
|
||||||
|
|
||||||
|
$locationCodes = $this->getAlamatData($debitur, $forminspeksi);
|
||||||
|
$locationData = $this->getLocationData(
|
||||||
|
$locationCodes['provinceCode'],
|
||||||
|
$locationCodes['cityCode'],
|
||||||
|
$locationCodes['districtCode'],
|
||||||
|
$forminspeksi
|
||||||
|
);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'permohonan' => $permohonan,
|
||||||
|
'nomorLaporan' => $nomorLaporan,
|
||||||
|
'basicData' => $surveyorController->getCommonData(),
|
||||||
|
'cities' => $locationData['cities'],
|
||||||
|
'districts' => $locationData['districts'],
|
||||||
|
'villages' => $locationData['villages'],
|
||||||
|
'forminspeksi' => $forminspeksi,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getPermohonanData($surveyorController, $permohonanId, $documentId, $jaminanId)
|
||||||
|
{
|
||||||
|
return $surveyorController->getPermohonanData($permohonanId, $documentId, $jaminanId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function generateNomorLaporan($surveyorController, $permohonan, $documentId, $type)
|
||||||
|
{
|
||||||
|
return $surveyorController->generateNomorLaporan($permohonan, $documentId, $type);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getInspeksi($permohonanId, $documentId)
|
||||||
|
{
|
||||||
|
return Inspeksi::where('permohonan_id', $permohonanId)
|
||||||
|
->where('document_id', $documentId)
|
||||||
|
->first();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function updatePenilai($permohonanId, $documentId, $type)
|
||||||
|
{
|
||||||
|
// Logika untuk memperbarui data berdasarkan tipe laporan
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getAlamatData($debitur, $forminspeksi)
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'provinceCode' => $debitur->province_id ?? $forminspeksi['province'],
|
||||||
|
'cityCode' => $debitur->city_id ?? $forminspeksi['city'],
|
||||||
|
'districtCode' => $debitur->district_id ?? $forminspeksi['district'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getLocationData($provinceCode, $cityCode, $districtCode, $forminspeksi)
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'cities' => $this->fetchCityData($provinceCode),
|
||||||
|
'districts' => $this->fetchDistrictData($cityCode),
|
||||||
|
'villages' => $this->fetchVillageData($districtCode),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function fetchCityData($provinceCode)
|
||||||
|
{
|
||||||
|
return City::where('province_code', $provinceCode)->get();
|
||||||
|
}
|
||||||
|
private function fetchDistrictData($cityCode)
|
||||||
|
{
|
||||||
|
return District::where('city_code', $cityCode)->get();
|
||||||
|
}
|
||||||
|
private function fetchVillageData($districtCode)
|
||||||
|
{
|
||||||
|
return Village::where('district_code', $districtCode)->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function updateOrCreatePenilai($permohonan_id, $document_id, $type, $data)
|
||||||
|
{
|
||||||
|
return Penilai::updateOrCreate(
|
||||||
|
[
|
||||||
|
'permohonan_id' => $permohonan_id,
|
||||||
|
'dokument_id' => $document_id,
|
||||||
|
|
||||||
|
],
|
||||||
|
[
|
||||||
|
$type => json_encode($data),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
75
commit-message-staged.txt
Normal file
75
commit-message-staged.txt
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
🐛 fix(lpj): Perbaikan format Rupiah, role access, dan validasi data
|
||||||
|
|
||||||
|
## Ringkasan
|
||||||
|
Melakukan perbaikan pada helper format Rupiah, akses role user, validasi data MIG, serta penyesuaian tampilan laporan dan dokumentasi.
|
||||||
|
|
||||||
|
## Perubahan Detail
|
||||||
|
|
||||||
|
### 🔧 Helper Function
|
||||||
|
**app/Helpers/Lpj.php**:
|
||||||
|
- Menambahkan parameter opsional `withSymbol` pada fungsi `formatRupiah()` untuk kontrol simbol Rp
|
||||||
|
- Menambahkan handling untuk menghapus titik (.) dari input number sebelum proses
|
||||||
|
- Memperbaiki return value untuk null/empty string sesuai parameter `withSymbol`
|
||||||
|
- Mengganti `str_pad()` dengan `sprintf()` untuk generate random number (lebih efisien)
|
||||||
|
|
||||||
|
### 🛠️ Service Layer
|
||||||
|
**app/Services/PreviewLaporanService.php**:
|
||||||
|
- Memperbaiki validasi data MIG dengan menambahkan pengecekan `is_mig` flag
|
||||||
|
- Menambahkan null safety pada property `mig_mst_lpj_tot_nilai_pasar`
|
||||||
|
- Memperbaiki kondisi logic untuk memo dan validasi nilai pasar
|
||||||
|
|
||||||
|
### 🎨 View Components
|
||||||
|
**resources/views/component/print-out-dokument.blade.php**:
|
||||||
|
- Memperbaiki syntax Blade dari `@isset` menjadi `isset()` yang lebih proper
|
||||||
|
|
||||||
|
**resources/views/debitur/components/debitur.blade.php**:
|
||||||
|
- Memperbaiki role checking dari `hasRole()` menjadi `hasAnyRole()` untuk multiple roles
|
||||||
|
|
||||||
|
**resources/views/debitur/index.blade.php**:
|
||||||
|
- Menambahkan role 'admin' pada kondisi edit dan delete actions
|
||||||
|
- Memperbaiki permission checking untuk administrator dan admin
|
||||||
|
|
||||||
|
**resources/views/laporan/index.blade.php**:
|
||||||
|
- Menyederhanakan logic tombol laporan dan resume
|
||||||
|
- Menghapus logic role-based yang kompleks untuk tombol laporan
|
||||||
|
- Memperbaiki route URL untuk print-out laporan
|
||||||
|
- Menghapus function `generateLaporanButton()` yang tidak digunakan
|
||||||
|
|
||||||
|
**resources/views/penilai/components/lpj-sederhana-standar.blade.php**:
|
||||||
|
- Menambahkan role 'penilai' pada permission tombol simpan
|
||||||
|
|
||||||
|
**resources/views/penilai/components/print-out-sederhana.blade.php**:
|
||||||
|
- Memperbaiki tampilan data dokumen dengan menambahkan kolom nomor dokumen
|
||||||
|
- Mengganti `number_format()` dengan `formatRupiah()` untuk konsistensi format
|
||||||
|
- Menambahkan fallback untuk data tanah dan bangunan ketika `npw_tambahan` tidak tersedia
|
||||||
|
- Memperbaiki perhitungan total nilai pasar wajar dengan proper parsing
|
||||||
|
- Memperbaiki format tampilan nilai likuidasi
|
||||||
|
- Memperbaiki struktur HTML tabel untuk dokumentasi
|
||||||
|
|
||||||
|
**resources/views/penilai/components/signature-approval.blade.php**:
|
||||||
|
- Memperbaiki route dan parameter untuk approval signature
|
||||||
|
|
||||||
|
**resources/views/permohonan/index.blade.php**:
|
||||||
|
- Menambahkan role 'admin' pada permission actions
|
||||||
|
|
||||||
|
## Alasan Perubahan
|
||||||
|
1. **Format Rupiah**: Menambahkan fleksibilitas untuk menampilkan nominal dengan atau tanpa simbol Rp sesuai kebutuhan tampilan
|
||||||
|
2. **Validasi Data**: Memperkuat validasi data MIG untuk mencegah error pada data yang tidak lengkap
|
||||||
|
3. **Role Access**: Memperbaiki permission checking untuk mencakup role admin yang sebelumnya terlewat
|
||||||
|
4. **Tampilan Laporan**: Menyederhanakan UI dan memperbaiki format tampilan nilai untuk konsistensi
|
||||||
|
5. **Fallback Data**: Menambahkan handling untuk kasus data tidak lengkap pada laporan penilaian
|
||||||
|
|
||||||
|
## Dampak
|
||||||
|
- ✅ Format Rupiah lebih fleksibel dengan opsi simbol
|
||||||
|
- ✅ Validasi data MIG lebih kuat dan aman
|
||||||
|
- ✅ Role admin sekarang memiliki akses yang sesuai
|
||||||
|
- ✅ Tampilan laporan lebih konsisten dan rapi
|
||||||
|
- ✅ Penanganan error untuk data tidak lengkap lebih baik
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
Pastikan untuk:
|
||||||
|
1. Test format Rupiah dengan berbagai skenario (dengan/ tanpa simbol)
|
||||||
|
2. Test akses role admin pada semua fitur yang diperbarui
|
||||||
|
3. Test validasi data MIG dengan data lengkap dan tidak lengkap
|
||||||
|
4. Test tampilan laporan dengan data npw_tambahan kosong
|
||||||
|
5. Verifikasi perhitungan total nilai pasar wajar tetap akurat
|
||||||
BIN
database/.DS_Store
vendored
Normal file
BIN
database/.DS_Store
vendored
Normal file
Binary file not shown.
@@ -0,0 +1,52 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class () extends Migration {
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('debitures', function (Blueprint $table) {
|
||||||
|
// nullable
|
||||||
|
$table->string('cif', 16)
|
||||||
|
->nullable()
|
||||||
|
->default('0000000000')
|
||||||
|
->comment('asal data LPJ.PRM_DEBITUR.KODE_CIF. Pada KODE_CIF ada yang digitnya 16 => 3372040405810002')
|
||||||
|
->change();
|
||||||
|
$table->unsignedBigInteger('branch_id')->nullable()->change();
|
||||||
|
$table->string('nomor_id', 50)->nullable()->change();
|
||||||
|
|
||||||
|
$table->unsignedBigInteger('mig_kd_debitur_seq')->nullable()->comment('asal data LPJ.PRM_DEBITUR.KD_DEBITUR_SEQ. Berguna untuk update debitur_id menggunakan KD_DEBITUR_SEQ nya');
|
||||||
|
$table->timestamp('processed_at')->nullable();
|
||||||
|
$table->char('is_mig', 1)->nullable()->comment('untuk menandakan row ini dari LPJ OLD');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('debitures', function (Blueprint $table) {
|
||||||
|
// Kembalikan kolom branch_id agar tidak nullable (asumsi awal NOT NULL)
|
||||||
|
$table->unsignedBigInteger('branch_id')->nullable(false)->change();
|
||||||
|
|
||||||
|
// Kembalikan kolom yang diubah nullable menjadi NOT NULL
|
||||||
|
$table->string('cif', 10)->nullable(false)->change();
|
||||||
|
$table->string('nomor_id', 50)->nullable(false)->change();
|
||||||
|
|
||||||
|
// Hapus kolom tambahan yang dibuat di up()
|
||||||
|
$table->dropColumn([
|
||||||
|
'mig_kd_debitur_seq',
|
||||||
|
'mig_urut_seq_addr',
|
||||||
|
'mig_urut_seq_comm',
|
||||||
|
'processed_at',
|
||||||
|
'is_mig'
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class () extends Migration {
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('permohonan', function (Blueprint $table) {
|
||||||
|
// nullable
|
||||||
|
$table->unsignedBigInteger('branch_id')->nullable()->change();
|
||||||
|
$table->unsignedBigInteger('user_id')->nullable()->change();
|
||||||
|
|
||||||
|
|
||||||
|
$table->unsignedBigInteger('mig_kd_debitur_seq')->nullable()->comment('asal data LPJ.PRM_DEBITUR.KD_DEBITUR_SEQ. Berguna untuk update debitur_id menggunakan KD_DEBITUR_SEQ nya');
|
||||||
|
$table->unsignedBigInteger('nomor_lpj')->nullable();
|
||||||
|
$table->string('mig_nama_ao')->nullable();
|
||||||
|
$table->char('is_mig', 1)->nullable()->comment('untuk menandakan row ini dari LPJ OLD');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('permohonan', function (Blueprint $table) {
|
||||||
|
// Kembalikan kolom branch_id agar tidak nullable (asumsi awal NOT NULL)
|
||||||
|
$table->unsignedBigInteger('branch_id')->nullable(false)->change();
|
||||||
|
$table->unsignedBigInteger('user_id')->nullable(false)->change();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Hapus kolom tambahan yang dibuat di up()
|
||||||
|
$table->dropColumn([
|
||||||
|
'mig_kd_debitur_seq',
|
||||||
|
'nomor_lpj',
|
||||||
|
'mig_nama_ao',
|
||||||
|
'is_mig'
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class () extends Migration {
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('dokumen_jaminan', function (Blueprint $table) {
|
||||||
|
// nullable
|
||||||
|
|
||||||
|
$table->unsignedBigInteger('mig_kd_debitur_seq')->nullable()->comment('asal data LPJ.PRM_DEBITUR.KD_DEBITUR_SEQ. Berguna untuk update debitur_id menggunakan KD_DEBITUR_SEQ nya');
|
||||||
|
$table->unsignedBigInteger('nomor_lpj')->nullable();
|
||||||
|
$table->timestamp('processed_at')->nullable();
|
||||||
|
$table->char('is_mig', 1)->nullable()->comment('untuk menandakan row ini dari LPJ OLD');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('dokumen_jaminan', function (Blueprint $table) {
|
||||||
|
|
||||||
|
|
||||||
|
// Hapus kolom tambahan yang dibuat di up()
|
||||||
|
$table->dropColumn([
|
||||||
|
'nomor_lpj',
|
||||||
|
'mig_kd_debitur_seq',
|
||||||
|
'processed_at',
|
||||||
|
'is_mig'
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class () extends Migration {
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('pemilik_jaminan', function (Blueprint $table) {
|
||||||
|
// nullable
|
||||||
|
|
||||||
|
$table->unsignedBigInteger('mig_kd_debitur_seq')->nullable()->comment('asal data LPJ.PRM_DEBITUR.KD_DEBITUR_SEQ. Berguna untuk update debitur_id menggunakan KD_DEBITUR_SEQ nya');
|
||||||
|
$table->timestamp('processed_at')->nullable();
|
||||||
|
$table->char('is_mig', 1)->nullable()->comment('untuk menandakan row ini dari LPJ OLD');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('pemilik_jaminan', function (Blueprint $table) {
|
||||||
|
|
||||||
|
|
||||||
|
// Hapus kolom tambahan yang dibuat di up()
|
||||||
|
$table->dropColumn([
|
||||||
|
'mig_kd_debitur_seq',
|
||||||
|
'processed_at',
|
||||||
|
'is_mig'
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('inspeksi', function (Blueprint $table) {
|
||||||
|
$table->unsignedBigInteger('nomor_lpj')->nullable();
|
||||||
|
$table->timestamp('processed_at')->nullable();
|
||||||
|
$table->char('is_mig', 1)->nullable()->comment('untuk menandakan row ini dari LPJ OLD');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('inspeksi', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('nomor_lpj');
|
||||||
|
$table->dropColumn('processed_at');
|
||||||
|
$table->dropColumn('is_mig');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('penilai', function (Blueprint $table) {
|
||||||
|
$table->unsignedBigInteger('nomor_lpj')->nullable();
|
||||||
|
$table->timestamp('processed_at')->nullable();
|
||||||
|
$table->char('is_mig', 1)->nullable()->comment('untuk menandakan row ini dari LPJ OLD');
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('penilai', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('nomor_lpj');
|
||||||
|
$table->dropColumn('processed_at');
|
||||||
|
$table->dropColumn('is_mig');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return new class extends \Illuminate\Database\Migrations\Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Tambah kolom biaya pada tabel nilai_plafond.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
\Illuminate\Support\Facades\Schema::table('nilai_plafond', function (\Illuminate\Database\Schema\Blueprint $table) {
|
||||||
|
// PostgreSQL akan memetakan decimal ke numeric
|
||||||
|
$table->decimal('biaya', 15, 2)->default(0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Menghapus kolom biaya jika dilakukan rollback.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
\Illuminate\Support\Facades\Schema::table('nilai_plafond', function (\Illuminate\Database\Schema\Blueprint $table) {
|
||||||
|
$table->dropColumn('biaya');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Tambahkan kolom biaya pada tabel nilai_plafond
|
||||||
|
*
|
||||||
|
* Catatan:
|
||||||
|
* - Menggunakan tipe decimal(15,2) agar kompatibel dengan PostgreSQL (numeric)
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('nilai_plafond', function (Blueprint $table) {
|
||||||
|
// Tambahkan kolom biaya sebagai decimal dengan 2 pecahan
|
||||||
|
$table->decimal('biaya', 15, 2)->nullable();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rollback perubahan: hapus kolom biaya dari tabel nilai_plafond
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
if (Schema::hasColumn('nilai_plafond', 'biaya')) {
|
||||||
|
Schema::table('nilai_plafond', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('biaya');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('referensi_link', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('name', 255)->nullable(false)->comment('Nama referensi link');
|
||||||
|
$table->text('link')->nullable(false)->comment('URL link referensi');
|
||||||
|
$table->string('kategori', 100)->nullable()->comment('Kategori referensi (misal: regulasi, panduan, dll)');
|
||||||
|
$table->text('deskripsi')->nullable()->comment('Deskripsi lengkap referensi');
|
||||||
|
$table->boolean('is_active')->default(true)->comment('Status aktif referensi');
|
||||||
|
$table->integer('urutan')->default(0)->comment('Urutan tampil referensi');
|
||||||
|
$table->unsignedBigInteger('created_by')->nullable()->comment('ID user yang membuat');
|
||||||
|
$table->unsignedBigInteger('updated_by')->nullable()->comment('ID user yang update terakhir');
|
||||||
|
$table->timestamps();
|
||||||
|
|
||||||
|
// Indexes
|
||||||
|
$table->index('kategori');
|
||||||
|
$table->index('is_active');
|
||||||
|
$table->index('urutan');
|
||||||
|
$table->index('created_by');
|
||||||
|
|
||||||
|
// Foreign keys
|
||||||
|
$table->foreign('created_by')->references('id')->on('users')->onDelete('set null');
|
||||||
|
$table->foreign('updated_by')->references('id')->on('users')->onDelete('set null');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('referensi_link');
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -13,24 +13,25 @@ class HubunganPemilikJaminanSeeder extends Seeder
|
|||||||
public function run(): void
|
public function run(): void
|
||||||
{
|
{
|
||||||
$hubungan_pemilik_jaminan = [
|
$hubungan_pemilik_jaminan = [
|
||||||
[
|
['name' => 'Milik Pribadi'],
|
||||||
'name' => 'Milik Pribadi'
|
['name' => 'Suami'],
|
||||||
],
|
['name' => 'Anak'],
|
||||||
[
|
['name' => 'Saudara'],
|
||||||
'name' => 'Suami/Istri'
|
['name' => 'Ayah'],
|
||||||
],
|
['name' => 'Ibu'],
|
||||||
[
|
['name' => 'Nenek'],
|
||||||
'name' => 'Anak'
|
['name' => 'Penjual/Developer'],
|
||||||
],
|
[ 'name' => 'Kakak/adik kandung'],
|
||||||
[
|
[ 'name' => 'Orang tua'],
|
||||||
'name' => 'Saudara Kandung'
|
[ 'name' => 'Mitra Usaha'],
|
||||||
],
|
[ 'name' => 'Pihak lain'],
|
||||||
[
|
[ 'name' => 'Negara'],
|
||||||
'name' => 'Ayah'
|
[ 'name' => 'Nenek/kakek'],
|
||||||
],
|
[ 'name' => 'Milik Keluarga'],
|
||||||
[
|
[ 'name' => 'Kakak/adik Orangtua'],
|
||||||
'name' => 'Ibu'
|
[ 'name' => 'Istri'],
|
||||||
]
|
[ 'name' => 'Pengurus'],
|
||||||
|
[ 'name' => 'Lain - lain'],
|
||||||
];
|
];
|
||||||
|
|
||||||
foreach ($hubungan_pemilik_jaminan as $hpj) {
|
foreach ($hubungan_pemilik_jaminan as $hpj) {
|
||||||
|
|||||||
@@ -69,6 +69,49 @@ class JenisFasilitasKreditSeeder extends Seeder
|
|||||||
'created_at' => now(),
|
'created_at' => now(),
|
||||||
'updated_at' => now()
|
'updated_at' => now()
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'code' => 'JFK009',
|
||||||
|
'name' => 'UMKM',
|
||||||
|
'status' => 1,
|
||||||
|
'created_at' => now(),
|
||||||
|
'updated_at' => now()
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'code' => 'JFK010',
|
||||||
|
'name' => 'KORPORASI',
|
||||||
|
'status' => 1,
|
||||||
|
'created_at' => now(),
|
||||||
|
'updated_at' => now()
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'code' => 'JFK011',
|
||||||
|
'name' => 'KPR 2',
|
||||||
|
'status' => 1,
|
||||||
|
'created_at' => now(),
|
||||||
|
'updated_at' => now()
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'code' => 'JFK012',
|
||||||
|
'name' => 'KONSUMER',
|
||||||
|
'status' => 1,
|
||||||
|
'created_at' => now(),
|
||||||
|
'updated_at' => now()
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'code' => 'JFK013',
|
||||||
|
'name' => 'KOMERSIL',
|
||||||
|
'status' => 1,
|
||||||
|
'created_at' => now(),
|
||||||
|
'updated_at' => now()
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'code' => 'JFK014',
|
||||||
|
'name' => 'KPR REGULER',
|
||||||
|
'status' => 1,
|
||||||
|
'created_at' => now(),
|
||||||
|
'updated_at' => now()
|
||||||
|
],
|
||||||
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,36 +12,50 @@ class LpjDatabaseSeeder extends Seeder
|
|||||||
public function run(): void
|
public function run(): void
|
||||||
{
|
{
|
||||||
$this->call([
|
$this->call([
|
||||||
BranchSeeder::class,
|
|
||||||
CurrencySeeder::class,
|
// BranchSeeder::class,
|
||||||
HolidayCalendarSeeder::class,
|
// CurrencySeeder::class,
|
||||||
JenisFasilitasKreditSeeder::class,
|
// HolidayCalendarSeeder::class,
|
||||||
JenisLegalitasJaminanSeeder::class,
|
// JenisFasilitasKreditSeeder::class,
|
||||||
JenisJaminanSeeder::class,
|
// JenisLegalitasJaminanSeeder::class,
|
||||||
JenisDokumenSeeder::class,
|
// JenisJaminanSeeder::class,
|
||||||
TujuanPenilaianSeeder::class,
|
// JenisDokumenSeeder::class,
|
||||||
NilaiPlatformSeeder::class,
|
// TujuanPenilaianSeeder::class,
|
||||||
HubunganPemilikJaminanSeeder::class,
|
// NilaiPlatformSeeder::class,
|
||||||
HubunganPenghuniJaminanSeeder::class,
|
// HubunganPemilikJaminanSeeder::class,
|
||||||
ArahMataAnginSeeder::class,
|
// HubunganPenghuniJaminanSeeder::class,
|
||||||
StatusPermohonanSeeder::class,
|
// ArahMataAnginSeeder::class,
|
||||||
RegionSeeder::class,
|
// StatusPermohonanSeeder::class,
|
||||||
TeamsSeeder::class,
|
// RegionSeeder::class,
|
||||||
TeamUsersSeeder::class,
|
// TeamsSeeder::class,
|
||||||
JenisPenilaianSeeder::class,
|
// TeamUsersSeeder::class,
|
||||||
IjinUsahaSeeder::class,
|
// MasterDataSurveyorSeeder::class
|
||||||
TujuanPenilaianKJPPSeeder::class,
|
// JenisPenilaianSeeder::class,
|
||||||
KJPPSeeder::class,
|
// IjinUsahaSeeder::class,
|
||||||
JenisLaporanSeeder::class,
|
// TujuanPenilaianKJPPSeeder::class,
|
||||||
DebitureSeeder::class,
|
// KJPPSeeder::class,
|
||||||
PemilikJaminanSeeder::class,
|
// JenisLaporanSeeder::class,
|
||||||
DokumenJaminanSeeder::class,
|
// DebitureSeeder::class,
|
||||||
DetailDokumenJaminanSeeder::class,
|
// PemilikJaminanSeeder::class,
|
||||||
PermohonanSeeder::class,
|
// DokumenJaminanSeeder::class,
|
||||||
FotoObjekJaminanSeeder::class,
|
// DetailDokumenJaminanSeeder::class,
|
||||||
|
// PermohonanSeeder::class,
|
||||||
|
// FotoObjekJaminanSeeder::class,
|
||||||
// PenawaranSeeder::class,
|
// PenawaranSeeder::class,
|
||||||
// DetailPenawaranSeeder::class,
|
// DetailPenawaranSeeder::class,
|
||||||
// PenilaianSeeder::class,
|
// PenilaianSeeder::class,
|
||||||
|
// MigrationDebitureSeeder::class,
|
||||||
|
// MigrationPermohonanSeeder::class,
|
||||||
|
// MigrationDokumentJaminanSeeder::class,
|
||||||
|
// MigrationDetailDokumenJaminanSeeder::class,
|
||||||
|
// MigPenilaianAndPenilainTeamSeeder::class,
|
||||||
|
// MigrationInpseksiSeeder::class,
|
||||||
|
MigrationGambarInspeksiSeeder::class,
|
||||||
|
// MigrationPembandingSeeder::class,
|
||||||
|
// MigrationPenilaiSeeder::class
|
||||||
|
|
||||||
|
// ini untuk penilaian external
|
||||||
|
// MigExternalPenawaranSeeder::class,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
45
database/seeders/MasterDataSurveyorSeeder.php
Normal file
45
database/seeders/MasterDataSurveyorSeeder.php
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Lpj\Database\Seeders;
|
||||||
|
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
|
||||||
|
class MasterDataSurveyorSeeder extends Seeder
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the database seeds.
|
||||||
|
*/
|
||||||
|
public function run(): void
|
||||||
|
{
|
||||||
|
|
||||||
|
$nameTable = [
|
||||||
|
'fasilitas_objek',
|
||||||
|
'gol_mas_sekitar',
|
||||||
|
'jenis_bangunan',
|
||||||
|
'jenis_kapal',
|
||||||
|
'jenis_kendaraan',
|
||||||
|
'jenis_pesawat',
|
||||||
|
'kondisi_bangunan',
|
||||||
|
'kondisi_fisik_tanah',
|
||||||
|
'kontur_tanah',
|
||||||
|
'lalu_lintas_lokasi',
|
||||||
|
'lantai',
|
||||||
|
'merupakan_daerah',
|
||||||
|
'perkerasan_jalan',
|
||||||
|
'sifat_bangunan',
|
||||||
|
'model_alat_berat',
|
||||||
|
'posisi_kavling',
|
||||||
|
'posisi_unit',
|
||||||
|
'tingkat_keramaian',
|
||||||
|
'sarana_pelengkap',
|
||||||
|
'spek_kategori_bangunan',
|
||||||
|
'spek_bangunan',
|
||||||
|
'terletak_diarea',
|
||||||
|
'view_unit'
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($nameTable as $table) {
|
||||||
|
DB::unprepared(file_get_contents(__DIR__ . '/sql/' . $table . '.sql'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
306
database/seeders/MigExternalPenawaranSeeder.php
Normal file
306
database/seeders/MigExternalPenawaranSeeder.php
Normal file
@@ -0,0 +1,306 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Lpj\Database\Seeders;
|
||||||
|
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Modules\Lpj\Models\Permohonan;
|
||||||
|
use Modules\Lpj\Models\PenawaranTender;
|
||||||
|
use Modules\Usermanagement\Models\User;
|
||||||
|
use Modules\Lpj\Models\Penilaian;
|
||||||
|
use Modules\Lpj\Models\PenilaianTeam;
|
||||||
|
|
||||||
|
class MigExternalPenawaranSeeder extends Seeder
|
||||||
|
{
|
||||||
|
protected $errorLogFile = __DIR__ . '/csv/penawaran/mig_penawaran_external_error.csv';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the database seeds.
|
||||||
|
*/
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
// Bersihkan/Inisialisasi file error log
|
||||||
|
$this->initializeErrorLog();
|
||||||
|
// Path ke file csv
|
||||||
|
$filePath = realpath(__DIR__ . '/csv/penawaran/mig_penawaran_external.csv');
|
||||||
|
|
||||||
|
if (!$filePath) {
|
||||||
|
Log::error('File csv tidak ditemukan: ' . __DIR__ . '/csv/permohonan/mig_penawaran_external.csv');
|
||||||
|
$this->command->error('File csv tidak ditemukan.');
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($handle = fopen($filePath, 'r')) === false) {
|
||||||
|
Log::error('Gagal membuka file CSV: ' . $filePath);
|
||||||
|
$this->command->error('Gagal membuka file CSV.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$header = fgetcsv($handle, 0, '~');
|
||||||
|
$rows = [];
|
||||||
|
$batchSize = 500; // Ukuran batch
|
||||||
|
$userDataChace = [];
|
||||||
|
$nomorRegisCahce = [];
|
||||||
|
$errorCount = 0; // Inisialisasi variabel errorCount
|
||||||
|
$errorDebitureIds = []; // Inisialisasi array errorDebitureIds
|
||||||
|
$totalData = 0;
|
||||||
|
|
||||||
|
// Menghitung total data di file CSV
|
||||||
|
while (($data = fgetcsv($handle, 0, '~')) !== false) {
|
||||||
|
$totalData++;
|
||||||
|
}
|
||||||
|
|
||||||
|
rewind($handle); // Reset pointer ke awal file
|
||||||
|
fgetcsv($handle, 0, '~'); // Skip header
|
||||||
|
|
||||||
|
$batchCount = 0;
|
||||||
|
$currentRow = 0;
|
||||||
|
|
||||||
|
while (($data = fgetcsv($handle, 0, '~')) !== false) {
|
||||||
|
if (count($data) != count($header)) {
|
||||||
|
Log::warning('Baris CSV memiliki jumlah kolom yang tidak sesuai: ' . json_encode($data));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$rows[] = array_combine($header, $data);
|
||||||
|
$currentRow++;
|
||||||
|
|
||||||
|
// Jika sudah mencapai batch size, proses batch
|
||||||
|
if (count($rows) >= $batchSize) {
|
||||||
|
$batchCount++;
|
||||||
|
$this->command->info("Memproses batch ke-{$batchCount} ({$currentRow}/{$totalData})");
|
||||||
|
$this->processBatch($rows, $nomorRegisCahce, $userDataChace, $errorCount, $errorDebitureIds, $totalData, $batchCount, $currentRow);
|
||||||
|
$rows = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Proses sisa data jika ada
|
||||||
|
// print_r($rows[0]);
|
||||||
|
if (!empty($rows)) {
|
||||||
|
$batchCount++;
|
||||||
|
$this->command->info("Memproses batch ke-{$batchCount} ({$currentRow}/{$totalData})");
|
||||||
|
$this->processBatch($rows, $nomorRegisCahce, $userDataChace, $errorCount, $errorDebitureIds, $totalData, $batchCount, $currentRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose($handle);
|
||||||
|
|
||||||
|
$this->command->info("Data debiture berhasil dimigrasikan. Total data: {$totalData}, Total batch: {$batchCount}, Total error: {$errorCount}");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private function processBatch(
|
||||||
|
array $rows,
|
||||||
|
array &$userDataChace,
|
||||||
|
array &$nomorRegisCahce,
|
||||||
|
int &$errorCount,
|
||||||
|
array &$errorDebitureIds,
|
||||||
|
int $totalData,
|
||||||
|
int $batchCount,
|
||||||
|
int $currentRow
|
||||||
|
) {
|
||||||
|
$userData = [];
|
||||||
|
foreach ($rows as $index => $row) {
|
||||||
|
try {
|
||||||
|
// Jalankan setiap baris dengan transaksi sendiri
|
||||||
|
DB::beginTransaction();
|
||||||
|
|
||||||
|
// Cek apakah sudah diproses
|
||||||
|
$existingRecord = PenawaranTender::where('nomor_registrasi', $row['mig_nomor_jaminan'])->first();
|
||||||
|
if ($existingRecord && $existingRecord->created_at) {
|
||||||
|
$this->command->info('Data sudah diproses sebelumnya: ' . $row['mig_nomor_jaminan']);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ambil nomor registrasi
|
||||||
|
$nomor_registrasi = $this->getNomorRegistrasiPermohonan($row['mig_nomor_jaminan'], $nomorRegisCahce);
|
||||||
|
if (!$nomor_registrasi) {
|
||||||
|
throw new \Exception("Nomor registrasi tidak valid");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$userIdUpdate = $this->getUserIdData($row['mig_created_by'] ?? null, $userData)['id'];
|
||||||
|
$userIdOtorisasi = $this->getUserIdData($row['mig_authorized_by'] ?? null, $userData)['id'];
|
||||||
|
|
||||||
|
if (!$userIdUpdate || !$userIdOtorisasi) {
|
||||||
|
// $this->logError($userIdUpdate, 'Salah satu user tidak ditemukan');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mapping field user
|
||||||
|
$mapUser = [
|
||||||
|
'created_by' => $userIdUpdate,
|
||||||
|
'updated_by' => $userIdUpdate,
|
||||||
|
'authorized_by' => $userIdOtorisasi,
|
||||||
|
];
|
||||||
|
|
||||||
|
// create random code
|
||||||
|
|
||||||
|
$tgl = $this->parseTimestamp($row['mig_tgl_penyerahan']);
|
||||||
|
|
||||||
|
// ambil nilai tahun terakhir contoh 2023 maka ambil 23
|
||||||
|
$year = date('y', strtotime($tgl));
|
||||||
|
|
||||||
|
// random code berdasarkan tgl contoh NP2300001
|
||||||
|
|
||||||
|
$code = 'NP' . $year . str_pad(rand(1, 99999), 5, '0', STR_PAD_LEFT); // outputnya NP2300001:
|
||||||
|
// Cek apakah kode sudah ada
|
||||||
|
$existingCode = PenawaranTender::where('code', $code)->first();
|
||||||
|
if ($existingCode) {
|
||||||
|
$code = 'NP' . $year . str_pad(rand(1, 99999), 5, '0', STR_PAD_LEFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Buat penilaian
|
||||||
|
$penilaian = PenawaranTender::create([
|
||||||
|
'code' => $code,
|
||||||
|
'nama_kjpp_sebelumnya' => $row['mig_nama_kjpp'],
|
||||||
|
'biaya_kjpp_sebelumnya' => $row['mig_tot_jasa'],
|
||||||
|
'tanggal_penilaian_sebelumnya' => $this->parseTimestamp($row['mig_tgl_penyerahan']),
|
||||||
|
'nomor_registrasi' => $nomor_registrasi,
|
||||||
|
'tujuan_penilaian_kjpp_id' => $this->checkTujuanPenilaian($row['mig_mst_jaminan_kd_tujuan_seq']),
|
||||||
|
'jenis_laporan_id' => 1,
|
||||||
|
'start_date' => $this->parseTimestamp($row['mig_tgl_penyerahan']),
|
||||||
|
'end_date' => $this->parseTimestamp($row['mig_terima_laporan']),
|
||||||
|
'catatan' => $row['mig_catatan'],
|
||||||
|
'status' => 'spk',
|
||||||
|
'created_at' => $this->parseTimestamp($row['mig_created_at']),
|
||||||
|
'updated_at' => $this->parseTimestamp($row['mig_updated_at']),
|
||||||
|
'authorized_by' => $mapUser['authorized_by'],
|
||||||
|
'created_by' => $mapUser['created_by'],
|
||||||
|
'updated_by' => $mapUser['updated_by'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Commit transaksi
|
||||||
|
DB::commit();
|
||||||
|
$this->command->info('Proses data penilaian ' . $row['mig_nomor_jaminan'] . ' (' . ($index + 1) . '/' . count($rows) . ')');
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
// Rollback jika ada error
|
||||||
|
DB::rollBack();
|
||||||
|
|
||||||
|
Log::error('Error pada baris: ' . json_encode($row) . '. Pesan: ' . $e->getMessage());
|
||||||
|
$errorCount++;
|
||||||
|
$errorDebitureIds[] = $row['mig_team_id'] ?? '-';
|
||||||
|
$this->logError($row['mig_team_id'] ?? '-', $e->getMessage());
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->command->info("Batch {$batchCount} selesai. Total error: " . count($errorDebitureIds));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private function getNomorRegistrasiPermohonan($nomor_registrasi_id, $nomorRegisCahce)
|
||||||
|
{
|
||||||
|
if (isset($nomorRegisCahce[$nomor_registrasi_id])) {
|
||||||
|
return $nomorRegisCahce[$nomor_registrasi_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
$nomorRegis = Permohonan::where('nomor_registrasi', $nomor_registrasi_id)->first();
|
||||||
|
|
||||||
|
if (!$nomorRegis) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$nomorRegisCahce[$nomor_registrasi_id] = $nomorRegis->nomor_registrasi;
|
||||||
|
return $nomorRegis->nomor_registrasi;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getUserIdData(?string $code, array &$cache): array
|
||||||
|
{
|
||||||
|
if (!$code) {
|
||||||
|
return ['id' => null, 'branch_id' => null];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($cache[$code])) {
|
||||||
|
return $cache[$code];
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = User::where('nik', $code)->first();
|
||||||
|
|
||||||
|
if ($user) {
|
||||||
|
$cache[$code] = ['id' => $user->id, 'branch_id' => $user->branch_id];
|
||||||
|
return $cache[$code];
|
||||||
|
}
|
||||||
|
|
||||||
|
return ['id' => null, 'branch_id' => null];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getUserId($mig_user_id, $userDataChace)
|
||||||
|
{
|
||||||
|
if (isset($userDataChace[$mig_user_id])) {
|
||||||
|
return $userDataChace[$mig_user_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
$userId = User::where('nik', $mig_user_id)->first();
|
||||||
|
|
||||||
|
if (!$userId) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$userDataChace[$mig_user_id] = $userId->id;
|
||||||
|
return $userId->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function parseTimestamp(?string $timestamp): ?string
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
if ($timestamp) {
|
||||||
|
// Cek jika format hanya tanggal (Y-m-d)
|
||||||
|
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $timestamp)) {
|
||||||
|
return \Carbon\Carbon::createFromFormat('Y-m-d', $timestamp)
|
||||||
|
->startOfDay()
|
||||||
|
->toDateTimeString();
|
||||||
|
}
|
||||||
|
// Format lengkap (Y-m-d H:i:s)
|
||||||
|
return \Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $timestamp)->toDateTimeString();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::error('Gagal memparsing timestamp: ' . $timestamp . '. Pesan: ' . $e->getMessage());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private function initializeErrorLog()
|
||||||
|
{
|
||||||
|
// Jika file lama ada, hapus
|
||||||
|
if (file_exists($this->errorLogFile)) {
|
||||||
|
unlink($this->errorLogFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Buat file baru dengan header
|
||||||
|
$handle = fopen($this->errorLogFile, 'w');
|
||||||
|
fputcsv($handle, ['mig_kd_debitur_seq', 'Error']);
|
||||||
|
fclose($handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function logError(string $kode, string $message)
|
||||||
|
{
|
||||||
|
// Catat ke log
|
||||||
|
Log::error("Error migrasi debiture [$kode]: $message");
|
||||||
|
|
||||||
|
// Tulis ke file error
|
||||||
|
$handle = fopen($this->errorLogFile, 'a');
|
||||||
|
fputcsv($handle, [$kode, $message]);
|
||||||
|
fclose($handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function checkTujuanPenilaian($code): int
|
||||||
|
{
|
||||||
|
$mapping = [
|
||||||
|
1 => 7,
|
||||||
|
2 => 5,
|
||||||
|
3 => 8,
|
||||||
|
6 => 6,
|
||||||
|
];
|
||||||
|
|
||||||
|
return $mapping[$code] ?? 7;
|
||||||
|
}
|
||||||
|
}
|
||||||
1036
database/seeders/MigInspeksiHelper.php
Normal file
1036
database/seeders/MigInspeksiHelper.php
Normal file
File diff suppressed because it is too large
Load Diff
350
database/seeders/MigPenilaianAndPenilainTeamSeeder.php
Normal file
350
database/seeders/MigPenilaianAndPenilainTeamSeeder.php
Normal file
@@ -0,0 +1,350 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Lpj\Database\Seeders;
|
||||||
|
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Modules\Basicdata\Models\Branch;
|
||||||
|
use Modules\Lpj\Models\Penilaian;
|
||||||
|
use Modules\Usermanagement\Models\User;
|
||||||
|
use Modules\Lpj\Models\PenilaianTeam;
|
||||||
|
use Modules\Lpj\Models\Permohonan;
|
||||||
|
|
||||||
|
class MigPenilaianAndPenilainTeamSeeder extends Seeder
|
||||||
|
{
|
||||||
|
protected $errorLogFile = __DIR__ . '/csv/penilaian/penilaian.team.fix.new_20251012_error.csv';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the database seeds.
|
||||||
|
*/
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
// Bersihkan/Inisialisasi file error log
|
||||||
|
$this->initializeErrorLog();
|
||||||
|
// Path ke file csv
|
||||||
|
$filePath = realpath(__DIR__ . '/csv/penilaian/penilaian.team.fix.new_20251012.csv');
|
||||||
|
|
||||||
|
if (!$filePath) {
|
||||||
|
Log::error('File csv tidak ditemukan: ' . __DIR__ . '/csv/penilaian/penilaian.team.fix.new_20251012.csv');
|
||||||
|
$this->command->error('File csv tidak ditemukan.');
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($handle = fopen($filePath, 'r')) === false) {
|
||||||
|
Log::error('Gagal membuka file CSV: ' . $filePath);
|
||||||
|
$this->command->error('Gagal membuka file CSV.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$header = fgetcsv($handle, 0, ',');
|
||||||
|
$rows = [];
|
||||||
|
$batchSize = 500; // Ukuran batch
|
||||||
|
$userDataChace = [];
|
||||||
|
$nomorRegisCahce = [];
|
||||||
|
$errorCount = 0; // Inisialisasi variabel errorCount
|
||||||
|
$errorDebitureIds = []; // Inisialisasi array errorDebitureIds
|
||||||
|
$totalData = 0;
|
||||||
|
|
||||||
|
// Menghitung total data di file CSV
|
||||||
|
while (($data = fgetcsv($handle, 0, ',')) !== false) {
|
||||||
|
$totalData++;
|
||||||
|
}
|
||||||
|
|
||||||
|
rewind($handle); // Reset pointer ke awal file
|
||||||
|
fgetcsv($handle, 0, ','); // Skip header
|
||||||
|
|
||||||
|
$batchCount = 0;
|
||||||
|
$currentRow = 0;
|
||||||
|
|
||||||
|
while (($data = fgetcsv($handle, 0, ',')) !== false) {
|
||||||
|
if (count($data) != count($header)) {
|
||||||
|
Log::warning('Baris CSV memiliki jumlah kolom yang tidak sesuai: ' . json_encode($data));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$rows[] = array_combine($header, $data);
|
||||||
|
$currentRow++;
|
||||||
|
|
||||||
|
// Jika sudah mencapai batch size, proses batch
|
||||||
|
if (count($rows) >= $batchSize) {
|
||||||
|
$batchCount++;
|
||||||
|
$this->command->info("Memproses batch ke-{$batchCount} ({$currentRow}/{$totalData})");
|
||||||
|
$this->processBatch($rows, $nomorRegisCahce, $userDataChace, $errorCount, $errorDebitureIds, $totalData, $batchCount, $currentRow);
|
||||||
|
$rows = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Proses sisa data jika ada
|
||||||
|
// print_r($rows[0]);
|
||||||
|
if (!empty($rows)) {
|
||||||
|
$batchCount++;
|
||||||
|
$this->command->info("Memproses batch ke-{$batchCount} ({$currentRow}/{$totalData})");
|
||||||
|
$this->processBatch($rows, $nomorRegisCahce, $userDataChace, $errorCount, $errorDebitureIds, $totalData, $batchCount, $currentRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose($handle);
|
||||||
|
|
||||||
|
$this->command->info("Data debiture berhasil dimigrasikan. Total data: {$totalData}, Total batch: {$batchCount}, Total error: {$errorCount}");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private function processBatch(
|
||||||
|
array $rows,
|
||||||
|
array &$userDataChace,
|
||||||
|
array &$nomorRegisCahce,
|
||||||
|
int &$errorCount,
|
||||||
|
array &$errorDebitureIds,
|
||||||
|
int $totalData,
|
||||||
|
int $batchCount,
|
||||||
|
int $currentRow
|
||||||
|
) {
|
||||||
|
$userData = [];
|
||||||
|
foreach ($rows as $index => $row) {
|
||||||
|
try {
|
||||||
|
// Jalankan setiap baris dengan transaksi sendiri
|
||||||
|
//DB::beginTransaction();
|
||||||
|
|
||||||
|
// Cek apakah sudah diproses
|
||||||
|
$existingRecord = Penilaian::where('nomor_registrasi', $row['mig_nomor_registrasi'])->first();
|
||||||
|
if ($existingRecord && $existingRecord->created_at) {
|
||||||
|
$this->command->info('Data sudah diproses sebelumnya: ' . $row['mig_nomor_registrasi']);
|
||||||
|
//continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ambil nomor registrasi
|
||||||
|
$nomor_registrasi = $this->getNomorRegistrasiPermohonan($row['mig_nomor_registrasi'], $nomorRegisCahce);
|
||||||
|
if (!$nomor_registrasi) {
|
||||||
|
throw new \Exception($row['mig_nomor_registrasi']."Nomor registrasi tidak valid");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ambil user ID
|
||||||
|
$userId = $this->getUserId($row['mig_user_id'], $userDataChace);
|
||||||
|
if (!$userId) {
|
||||||
|
// $this->logError($row['mig_user_id'], 'Salah satu user tidak ditemukan');
|
||||||
|
throw new \Exception($row['mig_user_id'] . " User tidak ditemukan");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$userIdUpdate = $this->getUserIdData($row['mig_created_by'] ?? null, $userData)['id'];
|
||||||
|
$userIdOtorisasi = $this->getUserIdData($row['mig_authorized_by'] ?? null, $userData)['id'];
|
||||||
|
|
||||||
|
if (!$userIdUpdate || !$userIdOtorisasi) {
|
||||||
|
// $this->logError($userIdUpdate, 'Salah satu user tidak ditemukan');
|
||||||
|
//continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mapping field user
|
||||||
|
$mapUser = [
|
||||||
|
'created_by' => $userIdUpdate,
|
||||||
|
'updated_by' => $userIdUpdate,
|
||||||
|
'authorized_by' => $userIdOtorisasi,
|
||||||
|
];
|
||||||
|
|
||||||
|
// Ambil team ID
|
||||||
|
$teamId = $this->checkTeams($row['mig_team_id']);
|
||||||
|
if (!$teamId) {
|
||||||
|
throw new \Exception("Team tidak ditemukan");
|
||||||
|
}
|
||||||
|
|
||||||
|
$idPenilaian = Penilaian::orderBy('id', 'desc')->first()->id;
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'id' => $idPenilaian+1,
|
||||||
|
'nomor_registrasi' => $nomor_registrasi,
|
||||||
|
'jenis_penilaian_id' => 1,
|
||||||
|
'tanggal_kunjungan' => $this->parseTimestamp($row['mig_tanggal_kunjungan']) ?? now(),
|
||||||
|
'waktu_penilaian' => $this->parseTimestamp($row['mig_waktu_penilaian']),
|
||||||
|
'status' => 'done',
|
||||||
|
'keterangan' => null,
|
||||||
|
'created_at' => $this->parseTimestamp($row['mig_created_at']),
|
||||||
|
'updated_at' => $this->parseTimestamp($row['mig_updated_at']),
|
||||||
|
'authorized_by' => $mapUser['authorized_by'],
|
||||||
|
'created_by' => $mapUser['created_by'],
|
||||||
|
'updated_by' => $mapUser['updated_by']
|
||||||
|
];
|
||||||
|
|
||||||
|
if($nomor_registrasi=='251722'){
|
||||||
|
Log::info("Data penilaian 251722 : ",$data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Buat penilaian
|
||||||
|
$penilaian = Penilaian::updateOrCreate([
|
||||||
|
'nomor_registrasi' => $nomor_registrasi
|
||||||
|
],[
|
||||||
|
'id' => $idPenilaian+1,
|
||||||
|
'nomor_registrasi' => $nomor_registrasi,
|
||||||
|
'jenis_penilaian_id' => 1,
|
||||||
|
'tanggal_kunjungan' => $this->parseTimestamp($row['mig_tanggal_kunjungan']) ?? now(),
|
||||||
|
'waktu_penilaian' => $this->parseTimestamp($row['mig_waktu_penilaian']),
|
||||||
|
'status' => 'done',
|
||||||
|
'keterangan' => null,
|
||||||
|
'created_at' => $this->parseTimestamp($row['mig_created_at']),
|
||||||
|
'updated_at' => $this->parseTimestamp($row['mig_updated_at']),
|
||||||
|
'authorized_by' => $mapUser['authorized_by'],
|
||||||
|
'created_by' => $mapUser['created_by'],
|
||||||
|
'updated_by' => $mapUser['updated_by'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
//DB::commit();
|
||||||
|
|
||||||
|
// Buat tim penilaian
|
||||||
|
$roles = ['surveyor', 'penilai'];
|
||||||
|
foreach ($roles as $role) {
|
||||||
|
$idPenilaianTeam = PenilaianTeam::orderBy('id', 'desc')->first()->id;
|
||||||
|
|
||||||
|
PenilaianTeam::updateOrCreate([
|
||||||
|
'penilaian_id' => $penilaian->id
|
||||||
|
],[
|
||||||
|
'id' => $idPenilaianTeam+1,
|
||||||
|
'penilaian_id' => $penilaian->id,
|
||||||
|
'user_id' => $userId,
|
||||||
|
'role' => $role,
|
||||||
|
'team_id' => $teamId,
|
||||||
|
'created_at' => $this->parseTimestamp($row['mig_created_at']),
|
||||||
|
'updated_at' => $this->parseTimestamp($row['mig_updated_at']),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Commit transaksi
|
||||||
|
//DB::commit();
|
||||||
|
$this->command->info('Proses data penilaian ' . $row['mig_nomor_lpj'] . ' (' . ($index + 1) . '/' . count($rows) . ')');
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
// Rollback jika ada error
|
||||||
|
//DB::rollBack();
|
||||||
|
|
||||||
|
Log::error('Error pada baris: ' . json_encode($row) . '. Pesan: ' . $e->getMessage());
|
||||||
|
$errorCount++;
|
||||||
|
$errorDebitureIds[] = $row['mig_team_id'] ?? '-';
|
||||||
|
$this->logError($row['mig_team_id'] ?? '-', $e->getMessage());
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->command->info("Batch {$batchCount} selesai. Total error: " . count($errorDebitureIds));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private function getNomorRegistrasiPermohonan($nomor_registrasi_id, $nomorRegisCahce)
|
||||||
|
{
|
||||||
|
if (isset($nomorRegisCahce[$nomor_registrasi_id])) {
|
||||||
|
return $nomorRegisCahce[$nomor_registrasi_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
$nomorRegis = Permohonan::where('nomor_registrasi', $nomor_registrasi_id)->first();
|
||||||
|
|
||||||
|
if (!$nomorRegis) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$nomorRegisCahce[$nomor_registrasi_id] = $nomorRegis->nomor_registrasi;
|
||||||
|
return $nomorRegis->nomor_registrasi;
|
||||||
|
}
|
||||||
|
private function getUserIdData(?string $code, array &$cache): array
|
||||||
|
{
|
||||||
|
if (!$code) {
|
||||||
|
return ['id' => null, 'branch_id' => null];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($cache[$code])) {
|
||||||
|
return $cache[$code];
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = User::where('nik', $code)->first();
|
||||||
|
|
||||||
|
if ($user) {
|
||||||
|
$cache[$code] = ['id' => $user->id, 'branch_id' => $user->branch_id];
|
||||||
|
return $cache[$code];
|
||||||
|
}
|
||||||
|
|
||||||
|
return ['id' => null, 'branch_id' => null];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getUserId($mig_user_id, $userDataChace)
|
||||||
|
{
|
||||||
|
if (isset($userDataChace[$mig_user_id])) {
|
||||||
|
return $userDataChace[$mig_user_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
$userId = User::where('nik', $mig_user_id)->first();
|
||||||
|
|
||||||
|
if (!$userId) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$userDataChace[$mig_user_id] = $userId->id;
|
||||||
|
return $userId->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function checkTeams($code): int
|
||||||
|
{
|
||||||
|
$mapping = [
|
||||||
|
'01' => 1,
|
||||||
|
'02' => 2,
|
||||||
|
'04' => 4,
|
||||||
|
'07' => 5,
|
||||||
|
'06' => 3,
|
||||||
|
];
|
||||||
|
return $mapping[(string)$code] ?? 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private function parseTimestamp(?string $timestamp): ?string
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
if ($timestamp) {
|
||||||
|
// Cek jika format hanya tanggal (Y-m-d)
|
||||||
|
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $timestamp)) {
|
||||||
|
return \Carbon\Carbon::createFromFormat('Y-m-d', $timestamp)
|
||||||
|
->startOfDay()
|
||||||
|
->toDateTimeString();
|
||||||
|
}
|
||||||
|
// Format lengkap (Y-m-d H:i:s)
|
||||||
|
if (preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/', $timestamp)) {
|
||||||
|
return \Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $timestamp)->toDateTimeString();
|
||||||
|
}
|
||||||
|
// Format d/m/Y H:i:s (contoh: 28/4/2017 14:43:43)
|
||||||
|
if (preg_match('/^\d{1,2}\/\d{1,2}\/\d{4} \d{2}:\d{2}:\d{2}$/', $timestamp)) {
|
||||||
|
return \Carbon\Carbon::createFromFormat('d/m/Y H:i:s', $timestamp)->toDateTimeString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::error('Gagal memparsing timestamp: ' . $timestamp . '. Pesan: ' . $e->getMessage());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private function initializeErrorLog()
|
||||||
|
{
|
||||||
|
// Jika file lama ada, hapus
|
||||||
|
if (file_exists($this->errorLogFile)) {
|
||||||
|
unlink($this->errorLogFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Buat file baru dengan header
|
||||||
|
$handle = fopen($this->errorLogFile, 'w');
|
||||||
|
fputcsv($handle, ['mig_kd_debitur_seq', 'Error']);
|
||||||
|
fclose($handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function logError(string $kode, string $message)
|
||||||
|
{
|
||||||
|
// Catat ke log
|
||||||
|
Log::error("Error migrasi debiture [$kode]: $message");
|
||||||
|
|
||||||
|
// Tulis ke file error
|
||||||
|
$handle = fopen($this->errorLogFile, 'a');
|
||||||
|
fputcsv($handle, [$kode, $message]);
|
||||||
|
fclose($handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
255
database/seeders/MigrationDebitureSeeder.php
Normal file
255
database/seeders/MigrationDebitureSeeder.php
Normal file
@@ -0,0 +1,255 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Lpj\Database\Seeders;
|
||||||
|
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Modules\Basicdata\Models\Branch;
|
||||||
|
use Modules\Lpj\Models\Debiture;
|
||||||
|
use Modules\Usermanagement\Models\User;
|
||||||
|
|
||||||
|
|
||||||
|
class MigrationDebitureSeeder extends Seeder
|
||||||
|
{
|
||||||
|
protected $errorLogFile = __DIR__ . '/csv/debitures/error_migration.csv';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the database seeds.
|
||||||
|
*/
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
// Bersihkan/Inisialisasi file error log
|
||||||
|
$this->initializeErrorLog();
|
||||||
|
|
||||||
|
// Path ke file csv
|
||||||
|
$filePath = realpath(__DIR__ . '/csv/debitures/debitur.latest.csv');
|
||||||
|
|
||||||
|
if (!$filePath) {
|
||||||
|
Log::error('File csv tidak ditemukan: ' . __DIR__ . '/csv/debitures/debitur.latest.csv');
|
||||||
|
$this->command->error('File csv tidak ditemukan.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($handle = fopen($filePath, 'r')) === false) {
|
||||||
|
Log::error('Gagal membuka file CSV: ' . $filePath);
|
||||||
|
$this->command->error('Gagal membuka file CSV.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$header = fgetcsv($handle, 0, '|');
|
||||||
|
$rows = [];
|
||||||
|
$batchSize = 500;
|
||||||
|
$userData = [];
|
||||||
|
$branchCache = [];
|
||||||
|
$totalData = 0;
|
||||||
|
|
||||||
|
// Hitung total baris
|
||||||
|
while (($data = fgetcsv($handle, 0, '|')) !== false) {
|
||||||
|
$totalData++;
|
||||||
|
}
|
||||||
|
|
||||||
|
rewind($handle);
|
||||||
|
fgetcsv($handle, 0, '|'); // Lewati header
|
||||||
|
|
||||||
|
$currentRow = 0;
|
||||||
|
$batchCount = 0;
|
||||||
|
|
||||||
|
while (($data = fgetcsv($handle, 0, '|')) !== false) {
|
||||||
|
if (count($data) != count($header)) {
|
||||||
|
$this->logError($data[0] ?? '-', 'Jumlah kolom tidak sesuai');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$rows[] = array_combine($header, $data);
|
||||||
|
$currentRow++;
|
||||||
|
|
||||||
|
if (count($rows) >= $batchSize) {
|
||||||
|
$batchCount++;
|
||||||
|
$this->command->info("Memproses batch ke-{$batchCount} ({$currentRow}/{$totalData})");
|
||||||
|
$this->processBatch($rows, $branchCache, $userData);
|
||||||
|
$rows = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// print_r($rows);
|
||||||
|
if (!empty($rows)) {
|
||||||
|
$batchCount++;
|
||||||
|
$this->command->info("Memproses batch ke-{$batchCount} ({$currentRow}/{$totalData})");
|
||||||
|
$this->processBatch($rows, $branchCache, $userData);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose($handle);
|
||||||
|
|
||||||
|
$this->command->info("Data debiture berhasil dimigrasikan. Total data: {$totalData}, Total batch: {$batchCount}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private function processBatch(array $rows, array &$branchCache, array &$userData)
|
||||||
|
{
|
||||||
|
foreach ($rows as $index => $row) {
|
||||||
|
try {
|
||||||
|
$kode = $row['mig_kd_debitur_seq'] ?? '-';
|
||||||
|
|
||||||
|
// Cek apakah sudah diproses sebelumnya
|
||||||
|
$existingRecord = Debiture::where('mig_kd_debitur_seq', $kode)->first();
|
||||||
|
if ($existingRecord && $existingRecord->processed_at) {
|
||||||
|
$this->command->info("Data sudah diproses sebelumnya: $kode");
|
||||||
|
//continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ambil branch_id
|
||||||
|
$branchId = $this->getBranchId($row['mig_kd_cabang'] ?? null, $branchCache);
|
||||||
|
if (!$branchId) {
|
||||||
|
$this->logError($row['mig_kd_cabang'], 'Cabang tidak ditemukan');
|
||||||
|
//continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ambil user IDs berdasarkan NIK
|
||||||
|
$userIdUpdate = $this->getUserId($row['mig_user_update'] ?? null, $userData)['id'];
|
||||||
|
$userIdOtorisasi = $this->getUserId($row['mig_user_oto'] ?? null, $userData)['id'];
|
||||||
|
|
||||||
|
// if (!$userIdUpdate || !$userIdOtorisasi) {
|
||||||
|
// $this->logError($kode, 'Salah satu user tidak ditemukan');
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Mapping field user
|
||||||
|
$mapUser = [
|
||||||
|
'created_by' => $userIdUpdate,
|
||||||
|
'updated_by' => $userIdUpdate,
|
||||||
|
'authorized_by' => $userIdOtorisasi,
|
||||||
|
];
|
||||||
|
|
||||||
|
// Parsing nomor HP
|
||||||
|
$nomorHp = !empty($row['mig_phone']) ? preg_replace('/[^0-9]/', '', $row['mig_phone']) : null;
|
||||||
|
$email = !empty($row['email']) ? $row['email'] : null;
|
||||||
|
$nomorId = !empty($row['nomor_id']) ? $row['nomor_id'] : null;
|
||||||
|
|
||||||
|
// Parsing waktu
|
||||||
|
$authorizedAt = $this->parseTimestamp($row['mig_tgl_oto'] ?? null);
|
||||||
|
$createdAt = $this->parseTimestamp($row['created_at'] ?? null);
|
||||||
|
$updatedAt = $this->parseTimestamp($row['updated_at'] ?? null);
|
||||||
|
|
||||||
|
if (!$createdAt || !$updatedAt) {
|
||||||
|
$this->logError($kode, 'Gagal parsing created_at / updated_at');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simpan data
|
||||||
|
Debiture::updateOrCreate([
|
||||||
|
'mig_kd_debitur_seq' => (int) strtok($row['mig_kd_debitur_seq'], '.'),
|
||||||
|
], [
|
||||||
|
'branch_id' => $branchId,
|
||||||
|
'name' => $row['name'] ?? '',
|
||||||
|
'cif' => (int) strtok($row['cif'],'.') ?: '0000000000',
|
||||||
|
'phone' => $nomorHp,
|
||||||
|
'nomor_id' => $nomorId,
|
||||||
|
'email' => $email,
|
||||||
|
'npwp' => null,
|
||||||
|
'address' => $row['address'] ?? null,
|
||||||
|
'authorized_at' => $authorizedAt,
|
||||||
|
'authorized_by' => $mapUser['authorized_by'],
|
||||||
|
'created_by' => $mapUser['created_by'] ?? null,
|
||||||
|
'updated_by' => $mapUser['updated_by'] ?? null,
|
||||||
|
'created_at' => $createdAt,
|
||||||
|
'updated_at' => $updatedAt,
|
||||||
|
'mig_kd_debitur_seq' => (int) strtok($row['mig_kd_debitur_seq'], '.'),
|
||||||
|
'processed_at' => now(),
|
||||||
|
'mig_debitur' => json_encode($row),
|
||||||
|
'is_mig' => 1
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->command->info("Proses data debiture $kode (" . ($index + 1) . '/' . count($rows) . ')');
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->logError($row['mig_kd_debitur_seq'] ?? '-', "Error eksepsi: " . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getBranchId(?string $code, array &$cache): ?int
|
||||||
|
{
|
||||||
|
if (!$code) return null;
|
||||||
|
|
||||||
|
if (isset($cache[$code])) {
|
||||||
|
return $cache[$code];
|
||||||
|
}
|
||||||
|
|
||||||
|
$branch = Branch::where('code', $code)->first();
|
||||||
|
|
||||||
|
if ($branch) {
|
||||||
|
$cache[$code] = $branch->id;
|
||||||
|
return $branch->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getUserId(?string $code, array &$cache): array
|
||||||
|
{
|
||||||
|
if (!$code) return ['id' => null, 'branch_id' => null];
|
||||||
|
|
||||||
|
if (isset($cache[$code])) {
|
||||||
|
return $cache[$code];
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = User::where('nik', $code)->first();
|
||||||
|
|
||||||
|
if ($user) {
|
||||||
|
$cache[$code] = ['id' => $user->id, 'branch_id' => $user->branch_id];
|
||||||
|
return $cache[$code];
|
||||||
|
}
|
||||||
|
|
||||||
|
return ['id' => null, 'branch_id' => null];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function parseTimestamp(?string $timestamp): ?string
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
if ($timestamp) {
|
||||||
|
// Cek jika format hanya tanggal (Y-m-d)
|
||||||
|
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $timestamp)) {
|
||||||
|
return \Carbon\Carbon::createFromFormat('Y-m-d', $timestamp)
|
||||||
|
->startOfDay()
|
||||||
|
->toDateTimeString();
|
||||||
|
}
|
||||||
|
// Format lengkap (Y-m-d H:i:s)
|
||||||
|
if (preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/', $timestamp)) {
|
||||||
|
return \Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $timestamp)->toDateTimeString();
|
||||||
|
}
|
||||||
|
// Format d/m/Y H:i:s (contoh: 28/4/2017 14:43:43)
|
||||||
|
if (preg_match('/^\d{1,2}\/\d{1,2}\/\d{4} \d{2}:\d{2}:\d{2}$/', $timestamp)) {
|
||||||
|
return \Carbon\Carbon::createFromFormat('d/m/Y H:i:s', $timestamp)->toDateTimeString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::error('Gagal memparsing timestamp: ' . $timestamp . '. Pesan: ' . $e->getMessage());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function initializeErrorLog()
|
||||||
|
{
|
||||||
|
// Jika file lama ada, hapus
|
||||||
|
if (file_exists($this->errorLogFile)) {
|
||||||
|
unlink($this->errorLogFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Buat file baru dengan header
|
||||||
|
$handle = fopen($this->errorLogFile, 'w');
|
||||||
|
fputcsv($handle, ['mig_kd_debitur_seq', 'Error']);
|
||||||
|
fclose($handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function logError(string $kode, string $message)
|
||||||
|
{
|
||||||
|
// Catat ke log
|
||||||
|
Log::error("Error migrasi debiture [$kode]: $message");
|
||||||
|
|
||||||
|
// Tulis ke file error
|
||||||
|
$handle = fopen($this->errorLogFile, 'a');
|
||||||
|
fputcsv($handle, [$kode, $message]);
|
||||||
|
fclose($handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
356
database/seeders/MigrationDetailDokumenJaminanSeeder.php
Normal file
356
database/seeders/MigrationDetailDokumenJaminanSeeder.php
Normal file
@@ -0,0 +1,356 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Lpj\Database\Seeders;
|
||||||
|
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Modules\Lpj\Models\Debiture;
|
||||||
|
use Modules\Location\Models\City;
|
||||||
|
use Modules\Location\Models\District;
|
||||||
|
use Modules\Location\Models\Province;
|
||||||
|
use Modules\Location\Models\Village;
|
||||||
|
use Modules\Lpj\Models\DokumenJaminan;
|
||||||
|
use Modules\Lpj\Models\Permohonan;
|
||||||
|
use Modules\Lpj\Models\JenisJaminan;
|
||||||
|
use Modules\Lpj\Models\JenisLegalitasJaminan;
|
||||||
|
use Modules\Lpj\Models\PemilikJaminan;
|
||||||
|
use Modules\Lpj\Models\DetailDokumenJaminan;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
|
class MigrationDetailDokumenJaminanSeeder extends Seeder
|
||||||
|
{
|
||||||
|
protected $errorLogFile = __DIR__ . '/csv/detail.dokumen.jaminan_20251016_error.csv';
|
||||||
|
/**
|
||||||
|
* Run the database seeds.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
$this->initializeErrorLog();
|
||||||
|
// Path ke file csv
|
||||||
|
$filePath = realpath(__DIR__ . '/csv/detail.dokumen.jaminan_20251016.csv');
|
||||||
|
|
||||||
|
if (!$filePath) {
|
||||||
|
Log::error('File csv tidak ditemukan: ' . __DIR__ . '/csv/detail.dokumen.jaminan_20251016.csv');
|
||||||
|
$this->command->error('File csv tidak ditemukan.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($handle = fopen($filePath, 'r')) === false) {
|
||||||
|
Log::error('Gagal membuka file CSV: ' . $filePath);
|
||||||
|
$this->command->error('Gagal membuka file CSV.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$header = fgetcsv($handle, 0, ',');
|
||||||
|
$rows = [];
|
||||||
|
$batchSize = 1000; // Ukuran batch
|
||||||
|
$permohonanCache = [];
|
||||||
|
$jenisJaminanCache = [];
|
||||||
|
$dokumenJaminanCache = [];
|
||||||
|
$provinceCache = [];
|
||||||
|
$cityCache = [];
|
||||||
|
$districtCache = [];
|
||||||
|
$subdistrictCache = [];
|
||||||
|
$totalData = 0;
|
||||||
|
$errorCount = 0;
|
||||||
|
$errorDebitureIds = [];
|
||||||
|
$hubunganPemilikCache = [];
|
||||||
|
|
||||||
|
// Menghitung total data di file CSV
|
||||||
|
while (($data = fgetcsv($handle, 0, ',')) !== false) {
|
||||||
|
$totalData++;
|
||||||
|
}
|
||||||
|
|
||||||
|
rewind($handle); // Reset pointer ke awal file
|
||||||
|
fgetcsv($handle, 0, ','); // Skip header
|
||||||
|
|
||||||
|
$batchCount = 0;
|
||||||
|
$currentRow = 0;
|
||||||
|
|
||||||
|
|
||||||
|
// Membaca setiap baris dalam CSV
|
||||||
|
while (($data = fgetcsv($handle, 0, ',')) !== false) {
|
||||||
|
if (count($data) != count($header)) {
|
||||||
|
Log::warning('Baris CSV memiliki jumlah kolom yang tidak sesuai: ' . json_encode($data));
|
||||||
|
$errorCount++;
|
||||||
|
$errorDebitureIds[] = $data[0] ?? 'ID tidak valid'; // Menyimpan ID yang error
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$rows[] = array_combine($header, $data);
|
||||||
|
$currentRow++;
|
||||||
|
|
||||||
|
// print_r($rows);
|
||||||
|
|
||||||
|
|
||||||
|
if (count($rows) >= $batchSize) {
|
||||||
|
$errorDebitureIds[] = $data[0] ?? 'ID tidak valid'; // Menyimpan ID yang error
|
||||||
|
$this->processBatch($rows, $permohonanCache, $jenisJaminanCache, $dokumenJaminanCache, $batchCount, $currentRow, $totalData, $errorCount, $errorDebitureIds);
|
||||||
|
$rows = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// print_r($rows[0]);
|
||||||
|
if (!empty($rows)) {
|
||||||
|
$this->processBatch($rows, $permohonanCache, $jenisJaminanCache, $dokumenJaminanCache, $batchCount, $currentRow, $totalData, $errorCount, $errorDebitureIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose($handle);
|
||||||
|
|
||||||
|
$this->command->info('Data debiture berhasil dimigrasikan.');
|
||||||
|
}
|
||||||
|
|
||||||
|
private function processBatch(
|
||||||
|
array $rows,
|
||||||
|
array &$permohonanCache,
|
||||||
|
array &$jenisJaminanCache,
|
||||||
|
array &$dokumenJaminanCache,
|
||||||
|
int $batchCount,
|
||||||
|
int $currentRow,
|
||||||
|
int $totalData,
|
||||||
|
int &$errorCount,
|
||||||
|
array &$errorDebitureIds
|
||||||
|
) {
|
||||||
|
$groupedRows = $this->groupRowsByNomorLaporanAndKeterangan($rows);
|
||||||
|
|
||||||
|
// print_r($groupedRows);
|
||||||
|
|
||||||
|
foreach ($groupedRows as $nomorLaporan => $dataPerGrup) {
|
||||||
|
|
||||||
|
// print_r($dataPerGrup);
|
||||||
|
try {
|
||||||
|
// Ambil salah satu baris untuk referensi (misal baris pertama dari grup)
|
||||||
|
$firstRow = reset($dataPerGrup)['details'] ? reset($dataPerGrup) : reset($dataPerGrup);
|
||||||
|
$debiturId = null;
|
||||||
|
$nomorJaminan = null;
|
||||||
|
|
||||||
|
|
||||||
|
// Cari debitur ID dari salah satu field
|
||||||
|
foreach ($rows as $row) {
|
||||||
|
if ($row['mig_nomor_laporan'] == $nomorLaporan) {
|
||||||
|
$debiturId = $row['mig_kd_debitur_seq'] ?? null;
|
||||||
|
$nomorJaminan = $row['mig_nomor_jaminan'] ?? null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$debiturId) {
|
||||||
|
throw new \Exception('Debitur ID tidak ditemukan');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Ambil ID dokumen jaminan
|
||||||
|
$dokumenJaminanId = $this->getDokumenJaminanId($debiturId,$nomorJaminan, $dokumenJaminanCache);
|
||||||
|
if (!$dokumenJaminanId) {
|
||||||
|
throw new \Exception('Dokumen jaminan tidak ditemukan');
|
||||||
|
}
|
||||||
|
|
||||||
|
//dd($debiturId,$nomorJaminan);
|
||||||
|
|
||||||
|
foreach ($dataPerGrup as $groupKey => $rowData) {
|
||||||
|
// Ambil legalitas jaminan ID berdasarkan grup keterangan
|
||||||
|
$legalitasJaminanId = $this->getLegalitasJaminanId($groupKey, $jenisJaminanCache);
|
||||||
|
|
||||||
|
if (!$legalitasJaminanId) {
|
||||||
|
throw new \Exception("Legalitas jaminan tidak ditemukan untuk grup: {$groupKey}");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Simpan ke database
|
||||||
|
$detail =DetailDokumenJaminan::updateOrCreate(
|
||||||
|
[
|
||||||
|
'name' => $groupKey,
|
||||||
|
'dokumen_jaminan_id' => $dokumenJaminanId,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'details' => json_encode($rowData['details']),
|
||||||
|
'jenis_legalitas_jaminan_id' => $legalitasJaminanId,
|
||||||
|
'dokumen_jaminan' => !empty($rowData['documents']) ? json_encode($rowData['documents']) : null,
|
||||||
|
'dokumen_nomor' => $nomorLaporan,
|
||||||
|
'keterangan' => $groupKey,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
if($nomorJaminan=='253339'){
|
||||||
|
//dd($debiturId,$nomorJaminan,$legalitasJaminanId, $detail, $dokumenJaminanId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Info progress
|
||||||
|
$this->command->info("Proses data detail dokumen (Nomor Laporan: {$nomorLaporan}, batch ke: {$batchCount}, total dari: {$currentRow}/{$totalData})");
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::error("Error pada nomor laporan {$nomorLaporan}: " . $e->getMessage());
|
||||||
|
$this->logError($debiturId ?? '-', $e->getMessage());
|
||||||
|
$errorDebitureIds[] = $debiturId ?? '-';
|
||||||
|
$errorCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private function groupRowsByNomorLaporann(array $rows): array
|
||||||
|
{
|
||||||
|
$grouped = [];
|
||||||
|
|
||||||
|
foreach ($rows as $row) {
|
||||||
|
$nomorJaminan = $row['mig_nomor_laporan'] ?? null;
|
||||||
|
if (!empty($nomorJaminan)) {
|
||||||
|
$grouped[$nomorJaminan][] = $row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $grouped;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// private function groupRowsByNomorLaporanAndKeterangan(array $rows): array
|
||||||
|
// {
|
||||||
|
// $groupedByNomorLaporan = $this->groupRowsByNomorLaporann($rows);
|
||||||
|
// $finalGrouped = [];
|
||||||
|
|
||||||
|
// foreach ($groupedByNomorLaporan as $nomorLaporan => $rowList) {
|
||||||
|
// $groupedByGrpKeterangan = [];
|
||||||
|
|
||||||
|
// // Urutkan berdasarkan mig_urutan_sub (ascending)
|
||||||
|
// usort($rowList, function ($a, $b) {
|
||||||
|
// return $a['mig_urutan_sub'] <=> $b['mig_urutan_sub'];
|
||||||
|
// });
|
||||||
|
|
||||||
|
// foreach ($rowList as $row) {
|
||||||
|
// $grpKeterangan = $row['mig_grp_keterangan'] ?? 'UNKNOWN_GROUP';
|
||||||
|
|
||||||
|
// if (!isset($groupedByGrpKeterangan[$grpKeterangan])) {
|
||||||
|
// $groupedByGrpKeterangan[$grpKeterangan] = [
|
||||||
|
// 'details' => [],
|
||||||
|
// 'documents' => []
|
||||||
|
// ];
|
||||||
|
// }
|
||||||
|
|
||||||
|
// $keyKeterangan = $row['mig_key_keterangan'] ?? 'UNKNOWN_KEY';
|
||||||
|
// $value = $row['mig_nilai'] ?? null;
|
||||||
|
|
||||||
|
// // Jika belum ada detail, inisialisasi sebagai array asosiatif
|
||||||
|
// if (empty($groupedByGrpKeterangan[$grpKeterangan]['details'])) {
|
||||||
|
// $groupedByGrpKeterangan[$grpKeterangan]['details'][] = [];
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Masukkan ke dalam object tunggal (bukan item baru)
|
||||||
|
// if ($value !== null) {
|
||||||
|
// $lastIndex = count($groupedByGrpKeterangan[$grpKeterangan]['details']) - 1;
|
||||||
|
// $groupedByGrpKeterangan[$grpKeterangan]['details'][$lastIndex][$keyKeterangan] = $value;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Tambahkan dokumen jika ada
|
||||||
|
// $urlFile = $row['mig_url_file'] ?? null;
|
||||||
|
// if (!empty($urlFile)) {
|
||||||
|
// $groupedByGrpKeterangan[$grpKeterangan]['documents'][] = $urlFile;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// $finalGrouped[$nomorLaporan] = $groupedByGrpKeterangan;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // print_r($finalGrouped);
|
||||||
|
// return $finalGrouped;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
private function groupRowsByNomorLaporanAndKeterangan(array $rows): array
|
||||||
|
{
|
||||||
|
$groupedByNomorLaporan = $this->groupRowsByNomorLaporann($rows);
|
||||||
|
$finalGrouped = [];
|
||||||
|
|
||||||
|
foreach ($groupedByNomorLaporan as $nomorLaporan => $rowList) {
|
||||||
|
$groupedByGrpKeterangan = [];
|
||||||
|
|
||||||
|
// Urutkan berdasarkan mig_urutan_sub
|
||||||
|
usort($rowList, function ($a, $b) {
|
||||||
|
return $a['mig_urutan_sub'] <=> $b['mig_urutan_sub'];
|
||||||
|
});
|
||||||
|
|
||||||
|
foreach ($rowList as $row) {
|
||||||
|
$grpKeterangan = $row['mig_grp_keterangan'] ?? 'UNKNOWN_GROUP';
|
||||||
|
$keyKeterangan = $row['mig_key_keterangan'] ?? 'UNKNOWN_KEY';
|
||||||
|
$value = $row['mig_nilai'] ?? null;
|
||||||
|
|
||||||
|
if (!isset($groupedByGrpKeterangan[$grpKeterangan])) {
|
||||||
|
$groupedByGrpKeterangan[$grpKeterangan] = [
|
||||||
|
'details' => [],
|
||||||
|
'documents' => []
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Masukkan sebagai object baru ke dalam details
|
||||||
|
if ($value !== null) {
|
||||||
|
$groupedByGrpKeterangan[$grpKeterangan]['details'][] = [
|
||||||
|
$keyKeterangan => $value
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dokumen tetap masuk sebagai array string
|
||||||
|
$urlFile = $row['mig_url_file'] ?? null;
|
||||||
|
if (!empty($urlFile)) {
|
||||||
|
$groupedByGrpKeterangan[$grpKeterangan]['documents'][] = $urlFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$finalGrouped[$nomorLaporan] = $groupedByGrpKeterangan;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $finalGrouped;
|
||||||
|
}
|
||||||
|
private function getDokumenJaminanId(string $code,string $nomorLaporan, array &$dokumenJaminanCache)
|
||||||
|
{
|
||||||
|
$dokumen = DokumenJaminan::where('mig_kd_debitur_seq', $code)
|
||||||
|
->where('nomor_lpj', $nomorLaporan)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if ($dokumen) {
|
||||||
|
$dokumenJaminanCache[$code] = $dokumen->id;
|
||||||
|
return $dokumen->id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getLegalitasJaminanId(string $code, array &$legalitasJaminanCache)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (isset($legalitasJaminanCache[$code])) {
|
||||||
|
return $legalitasJaminanCache[$code];
|
||||||
|
}
|
||||||
|
|
||||||
|
$legalitas = JenisLegalitasJaminan::whereRaw('LOWER(name) = ?', [strtolower($code)])->first();
|
||||||
|
|
||||||
|
if ($legalitas) {
|
||||||
|
$legalitasJaminanCache[$code] = $legalitas->id;
|
||||||
|
return $legalitas->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function initializeErrorLog()
|
||||||
|
{
|
||||||
|
$file = $this->errorLogFile;
|
||||||
|
|
||||||
|
if (file_exists($file)) {
|
||||||
|
unlink($file); // Hapus file lama
|
||||||
|
}
|
||||||
|
|
||||||
|
$handle = fopen($file, 'w');
|
||||||
|
fputcsv($handle, ['mig_kd_debitur_seq', 'Error']);
|
||||||
|
fclose($handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function logError(string $kode, string $message)
|
||||||
|
{
|
||||||
|
Log::error("Error migrasi dokumen jaminan [$kode]: $message");
|
||||||
|
|
||||||
|
$handle = fopen($this->errorLogFile, 'a');
|
||||||
|
fputcsv($handle, [$kode, $message]);
|
||||||
|
fclose($handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
508
database/seeders/MigrationDokumentJaminanSeeder.php
Normal file
508
database/seeders/MigrationDokumentJaminanSeeder.php
Normal file
@@ -0,0 +1,508 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Lpj\Database\Seeders;
|
||||||
|
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Modules\Lpj\Models\Debiture;
|
||||||
|
use Modules\Location\Models\City;
|
||||||
|
use Modules\Location\Models\District;
|
||||||
|
use Modules\Location\Models\Province;
|
||||||
|
use Modules\Location\Models\Village;
|
||||||
|
use Modules\Lpj\Models\DokumenJaminan;
|
||||||
|
use Modules\Lpj\Models\Permohonan;
|
||||||
|
use Modules\Lpj\Models\JenisJaminan;
|
||||||
|
use Modules\Lpj\Models\PemilikJaminan;
|
||||||
|
use Modules\Lpj\Models\HubunganPemilikJaminan;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
|
|
||||||
|
class MigrationDokumentJaminanSeeder extends Seeder
|
||||||
|
{
|
||||||
|
protected $errorLogFile = __DIR__ . '/csv/dokumen_20251022_error_log.csv';
|
||||||
|
/**
|
||||||
|
* Run the database seeds.
|
||||||
|
*/
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
$this->initializeErrorLog();
|
||||||
|
// Path ke file csv
|
||||||
|
$filePath = realpath(__DIR__ . '/csv/dokumen_20251022.csv');
|
||||||
|
|
||||||
|
if (!$filePath) {
|
||||||
|
Log::error('File csv tidak ditemukan: ' . __DIR__ . '/csv/dokumen_20251022.csv');
|
||||||
|
$this->command->error('File csv tidak ditemukan.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($handle = fopen($filePath, 'r')) === false) {
|
||||||
|
Log::error('Gagal membuka file CSV: ' . $filePath);
|
||||||
|
$this->command->error('Gagal membuka file CSV.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$header = fgetcsv($handle, 0, ',');
|
||||||
|
$rows = [];
|
||||||
|
$batchSize = 1000; // Ukuran batch
|
||||||
|
$permohonanCache = [];
|
||||||
|
$jenisJaminanCache = [];
|
||||||
|
$pemilikJaminanCache = [];
|
||||||
|
$provinceCache = [];
|
||||||
|
$cityCache = [];
|
||||||
|
$districtCache = [];
|
||||||
|
$subdistrictCache = [];
|
||||||
|
$totalData = 0;
|
||||||
|
$errorCount = 0;
|
||||||
|
$errorDebitureIds = [];
|
||||||
|
$hubunganPemilikCache = [];
|
||||||
|
// Menghitung total data di file CSV
|
||||||
|
while (($data = fgetcsv($handle, 0, ',')) !== false) {
|
||||||
|
$totalData++;
|
||||||
|
}
|
||||||
|
|
||||||
|
rewind($handle); // Reset pointer ke awal file
|
||||||
|
fgetcsv($handle, 0, ','); // Skip header
|
||||||
|
|
||||||
|
$batchCount = 0;
|
||||||
|
$currentRow = 0;
|
||||||
|
|
||||||
|
|
||||||
|
// Membaca setiap baris dalam CSV
|
||||||
|
while (($data = fgetcsv($handle, 0, ',')) !== false) {
|
||||||
|
if (count($data) != count($header)) {
|
||||||
|
Log::warning('Baris CSV memiliki jumlah kolom yang tidak sesuai: ' . json_encode($data));
|
||||||
|
$errorCount++;
|
||||||
|
$errorDebitureIds[] = $data[0] ?? 'ID tidak valid'; // Menyimpan ID yang error
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$rows[] = array_combine($header, $data);
|
||||||
|
$currentRow++;
|
||||||
|
|
||||||
|
// print_r($rows);
|
||||||
|
|
||||||
|
|
||||||
|
if (count($rows) >= $batchSize) {
|
||||||
|
$errorDebitureIds[] = $data[0] ?? 'ID tidak valid'; // Menyimpan ID yang error
|
||||||
|
$this->processBatch($rows, $permohonanCache, $jenisJaminanCache, $pemilikJaminanCache, $provinceCache, $cityCache, $districtCache, $subdistrictCache, $batchCount, $currentRow, $totalData, $errorCount, $errorDebitureIds, $hubunganPemilikCache);
|
||||||
|
$rows = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// print_r($rows[0]);
|
||||||
|
if (!empty($rows)) {
|
||||||
|
$this->processBatch($rows, $permohonanCache, $jenisJaminanCache, $pemilikJaminanCache, $provinceCache, $cityCache, $districtCache, $subdistrictCache, $batchCount, $currentRow, $totalData, $errorCount, $errorDebitureIds, $hubunganPemilikCache);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose($handle);
|
||||||
|
|
||||||
|
$this->command->info('Data debiture berhasil dimigrasikan.');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Proses batch data.
|
||||||
|
*/
|
||||||
|
|
||||||
|
private function processBatch(
|
||||||
|
array $rows,
|
||||||
|
array &$permohonanCache,
|
||||||
|
array &$jenisJaminanCache,
|
||||||
|
array &$pemilikJaminanCache,
|
||||||
|
array &$provinceCache,
|
||||||
|
array &$cityCache,
|
||||||
|
array &$districtCache,
|
||||||
|
array &$subdistrictCache,
|
||||||
|
int $batchCount,
|
||||||
|
int $currentRow,
|
||||||
|
int $totalData,
|
||||||
|
int &$errorCount,
|
||||||
|
array &$errorDebitureIds,
|
||||||
|
array &$hubunganPemilikCache
|
||||||
|
) {
|
||||||
|
foreach ($rows as $index => $row) {
|
||||||
|
try {
|
||||||
|
// Jalankan transaksi per-baris
|
||||||
|
// DB::beginTransaction();
|
||||||
|
|
||||||
|
// Cari permohonan
|
||||||
|
|
||||||
|
$permohonan = Permohonan::where('nomor_registrasi', $row['mig_nomor_jaminan'])->first();
|
||||||
|
|
||||||
|
if (empty($permohonan)) {
|
||||||
|
throw new \Exception('Missing debiture_id' . $row['mig_nomor_jaminan']);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pastikan permohonan_id belum digunakan di dokumen_jaminan
|
||||||
|
$existingDokumen = DokumenJaminan::where('permohonan_id', $permohonan->id)->first();
|
||||||
|
if ($existingDokumen) {
|
||||||
|
//throw new \Exception("permohonan_id {$permohonan->id} sudah digunakan di dokumen_jaminan");
|
||||||
|
//continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ambil lokasi
|
||||||
|
|
||||||
|
// jika external silahkan matikan ini
|
||||||
|
|
||||||
|
$proviceCode = $this->getProvinceCode($row['mig_province_name'], $provinceCache);
|
||||||
|
$cityCode = $this->getCityCode($row['mig_city_name'], $cityCache);
|
||||||
|
$districtCode = $this->getDistrictCode($row['mig_district_name'], $districtCache);
|
||||||
|
$subdistrict = $this->getSubdistrictCode($row['mig_village_name'], $subdistrictCache, $districtCache);
|
||||||
|
// $hubunganPemilik = $this->getHubunganPemilikJaminanId($row['mig_hubungan_pemilik_jaminan'], $hubunganPemilikCache);
|
||||||
|
|
||||||
|
|
||||||
|
$pemilik_jaminan_name = $this->getDebitureId($row['mig_kd_debitur_seq'], $pemilikJaminanCache);
|
||||||
|
// Buat Pemilik Jaminan
|
||||||
|
$pemilik_jaminan = PemilikJaminan::updateOrCreate([
|
||||||
|
'debiture_id' => $permohonan->debiture_id,
|
||||||
|
'hubungan_pemilik_jaminan_id' => 1,
|
||||||
|
// 'name' => $row['name'],
|
||||||
|
'name' => $pemilik_jaminan_name,
|
||||||
|
'detail_sertifikat' => null,
|
||||||
|
'npwp' => null,
|
||||||
|
'nomor_id' => null,
|
||||||
|
'email' => null,
|
||||||
|
'phone' => null,
|
||||||
|
// jika external silahkan matikan ini
|
||||||
|
'province_code' => $proviceCode,
|
||||||
|
'city_code' => $cityCode,
|
||||||
|
'district_code' => $districtCode,
|
||||||
|
'village_code' => $subdistrict['code'],
|
||||||
|
'postal_code' => $subdistrict['postal_code'],
|
||||||
|
'address' => $row['address'],
|
||||||
|
'created_at' => $this->parseTimestamp($row['created_at']),
|
||||||
|
'updated_at' => $this->parseTimestamp($row['updated_at']),
|
||||||
|
'mig_kd_debitur_seq' => $row['mig_kd_debitur_seq'],
|
||||||
|
'processed_at' => now(),
|
||||||
|
'is_mig' => 1
|
||||||
|
]);
|
||||||
|
|
||||||
|
|
||||||
|
// Buat Dokumen Jaminan
|
||||||
|
$dokumenJaminan = DokumenJaminan::updateOrCreate([
|
||||||
|
'permohonan_id' => $permohonan->id,
|
||||||
|
'mig_kd_debitur_seq' => $row['mig_kd_debitur_seq'],
|
||||||
|
'nomor_lpj' => $row['mig_nomor_jaminan']
|
||||||
|
],[
|
||||||
|
'debiture_id' => $permohonan->debiture_id,
|
||||||
|
'permohonan_id' => $permohonan->id,
|
||||||
|
'jenis_jaminan_id' => $this->getJaminanId($row['mig_jenis_seq']) ?? '',
|
||||||
|
'pemilik_jaminan_id' => $pemilik_jaminan->id,
|
||||||
|
// jika external silahkan matikan ini
|
||||||
|
'province_code' => $proviceCode ?? '',
|
||||||
|
'city_code' => $cityCode ?? '',
|
||||||
|
'district_code' => $districtCode ?? '',
|
||||||
|
'village_code' => $subdistrict['code'] ?? '',
|
||||||
|
'postal_code' => $subdistrict['postal_code'] ?? '',
|
||||||
|
'address' => $row['address'],
|
||||||
|
'created_at' => $this->parseTimestamp($row['created_at']),
|
||||||
|
'updated_at' => $this->parseTimestamp($row['updated_at']),
|
||||||
|
'mig_kd_debitur_seq' => $row['mig_kd_debitur_seq'],
|
||||||
|
'processed_at' => now(),
|
||||||
|
'nomor_lpj' => $row['mig_nomor_jaminan'],
|
||||||
|
'is_mig' => 1
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Commit jika semua sukses
|
||||||
|
// DB::commit();
|
||||||
|
$this->command->info("Proses dokumen jaminan: " . $row['mig_kd_debitur_seq'] . "Batch: {$batchCount} Baris: {$currentRow} Total: {$totalData} Error: {$errorCount}");
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
// Rollback hanya untuk baris ini
|
||||||
|
Log::error("Error pada baris: " . json_encode($row) . ". Pesan: " . $e->getMessage());
|
||||||
|
$this->logError($row['mig_kd_debitur_seq'] ?? '-', $e->getMessage());
|
||||||
|
$errorDebitureIds[] = $row['mig_kd_debitur_seq'] ?? '-';
|
||||||
|
// DB::rollBack();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->command->info("Batch {$batchCount} selesai. Total error: " . count($errorDebitureIds));
|
||||||
|
}
|
||||||
|
// private function getPermohonanId($code,$cache)
|
||||||
|
// {
|
||||||
|
// if (isset($cache[$code])) {
|
||||||
|
// return $cache[$code];
|
||||||
|
// }
|
||||||
|
|
||||||
|
// $permohonan = Permohonan::where('mig_kd_debitur_seq', $code)->where('nomor_registrasi', $mig_nomor_jaminan)->first();
|
||||||
|
|
||||||
|
// if ($permohonan) {
|
||||||
|
// $cache[$code] = $permohonan;
|
||||||
|
// return $permohonan;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
private function getJaminanId($code): ?int
|
||||||
|
{
|
||||||
|
/*$mapping = [
|
||||||
|
7 => 17,
|
||||||
|
8 => 13,
|
||||||
|
6 => 32,
|
||||||
|
1 => 17,
|
||||||
|
2 => 26,
|
||||||
|
3 => 27,
|
||||||
|
4 => 50,
|
||||||
|
5 => 21,
|
||||||
|
138051314724 => 23,
|
||||||
|
138027243057 => 34,
|
||||||
|
138027664224 => 35,
|
||||||
|
138027738489 => 10,
|
||||||
|
138051485796 => 48,
|
||||||
|
138051492883 => 47,
|
||||||
|
138051515419 => 40,
|
||||||
|
138051753311 => 41,
|
||||||
|
138051754843 => 46,
|
||||||
|
138051759078 => 42,
|
||||||
|
138051480538 => 45,
|
||||||
|
123382184742 => 18,
|
||||||
|
138051483711 => 44,
|
||||||
|
991 => 52
|
||||||
|
];*/
|
||||||
|
|
||||||
|
$mapping = [
|
||||||
|
1 => 1,
|
||||||
|
2 => 17,
|
||||||
|
3 => 19,
|
||||||
|
4 => 15,
|
||||||
|
5 => 18,
|
||||||
|
6 => 26,
|
||||||
|
7 => 26,
|
||||||
|
8 => 26,
|
||||||
|
9 => 26,
|
||||||
|
10 => 24,
|
||||||
|
11 => 28,
|
||||||
|
12 => 29,
|
||||||
|
13 => 32,
|
||||||
|
991001 => 17,
|
||||||
|
121965631354 => 17,
|
||||||
|
122267387302 => 13,
|
||||||
|
122267391891 => 27,
|
||||||
|
123242566528 => 1,
|
||||||
|
123391628912 => 18,
|
||||||
|
123779076991 => 26,
|
||||||
|
123779092232 => 26,
|
||||||
|
123837866231 => 19,
|
||||||
|
124159228236 => 14,
|
||||||
|
124280447242 => 32,
|
||||||
|
124385048902 => 30,
|
||||||
|
124539856281 => 22,
|
||||||
|
124635294016 => 13,
|
||||||
|
124963468687 => 18,
|
||||||
|
125178371127 => 31,
|
||||||
|
125228814911 => 17,
|
||||||
|
125749523699 => 27,
|
||||||
|
126156105725 => 15,
|
||||||
|
127407367039 => 15,
|
||||||
|
132065123922 => 32,
|
||||||
|
138027244724 => 33,
|
||||||
|
138027246193 => 34,
|
||||||
|
138027693348 => 35,
|
||||||
|
138027764236 => 10,
|
||||||
|
138050882693 => 15,
|
||||||
|
138050910670 => 20,
|
||||||
|
138051316169 => 23,
|
||||||
|
138051517359 => 36,
|
||||||
|
138051519318 => 37,
|
||||||
|
138051522331 => 38,
|
||||||
|
138051601738 => 39,
|
||||||
|
138051602831 => 40,
|
||||||
|
138051773783 => 41,
|
||||||
|
138051776693 => 46,
|
||||||
|
138051780489 => 42,
|
||||||
|
164921358499 => 32,
|
||||||
|
165216289979 => 49,
|
||||||
|
165216294371 => 49,
|
||||||
|
173035895092 => 24
|
||||||
|
];
|
||||||
|
|
||||||
|
return $mapping[$code] ?? 17;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getPemilikJaminanId(string $code, array &$cache): ?int
|
||||||
|
{
|
||||||
|
if (isset($cache[$code])) {
|
||||||
|
return $cache[$code];
|
||||||
|
}
|
||||||
|
|
||||||
|
$jaminan = PemilikJaminan::where('mig_kd_debitur_seq', $code)->first();
|
||||||
|
|
||||||
|
if ($jaminan) {
|
||||||
|
$cache[$code] = $jaminan->id;
|
||||||
|
return $jaminan->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getDebitureId(string $code, array &$cache): ?string
|
||||||
|
{
|
||||||
|
if (isset($cache[$code])) {
|
||||||
|
return $cache[$code];
|
||||||
|
}
|
||||||
|
|
||||||
|
$debiture = Debiture::where('mig_kd_debitur_seq', $code)->first();
|
||||||
|
|
||||||
|
if ($debiture) {
|
||||||
|
$cache[$code] = $debiture->name;
|
||||||
|
return $debiture->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private function getProvinceCode(string $name, array &$cache): ?string
|
||||||
|
{
|
||||||
|
|
||||||
|
$normalizedName = strtolower($name);
|
||||||
|
if (isset($cache[$normalizedName])) {
|
||||||
|
return $cache[$normalizedName];
|
||||||
|
}
|
||||||
|
|
||||||
|
$province = Province::whereRaw('LOWER(name) = ?', [strtolower($name)])->first();
|
||||||
|
|
||||||
|
if ($province) {
|
||||||
|
$cache[$normalizedName] = $province->code;
|
||||||
|
return $province->code;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getCityCode(string $name, array &$cache): ?string
|
||||||
|
{
|
||||||
|
$normalizedName = strtolower($name);
|
||||||
|
if (isset($cache[$normalizedName])) {
|
||||||
|
return $cache[$normalizedName];
|
||||||
|
}
|
||||||
|
|
||||||
|
$city = City::whereRaw('LOWER(name) = ?', [strtolower($name)])->first();
|
||||||
|
|
||||||
|
if ($city) {
|
||||||
|
$cache[$normalizedName] = $city->code;
|
||||||
|
return $city->code;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getDistrictCode(string $name, array &$cache): ?string
|
||||||
|
{
|
||||||
|
$normalizedName = strtolower($name);
|
||||||
|
if (isset($cache[$normalizedName])) {
|
||||||
|
return $cache[$normalizedName];
|
||||||
|
}
|
||||||
|
|
||||||
|
$district = District::whereRaw('LOWER(name) = ?', [strtolower($name)])->first();
|
||||||
|
|
||||||
|
if ($district) {
|
||||||
|
$cache[$normalizedName] = $district->code;
|
||||||
|
return $district->code;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getSubdistrictCode(string $name, array &$cache, array &$districtCache): ?array
|
||||||
|
{
|
||||||
|
$normalizedName = strtolower($name);
|
||||||
|
|
||||||
|
// Pastikan cache menyimpan array, bukan hanya kode
|
||||||
|
if (isset($cache[$normalizedName])) {
|
||||||
|
return $cache[$normalizedName];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ambil subdistrict dari database
|
||||||
|
$subdistrict = Village::whereRaw('LOWER(name) = ?', [$normalizedName])->first();
|
||||||
|
|
||||||
|
// Jika ditemukan, simpan ke dalam cache sebagai array lengkap
|
||||||
|
if ($subdistrict) {
|
||||||
|
$cache[$normalizedName] = [
|
||||||
|
'code' => $subdistrict->code,
|
||||||
|
'postal_code' => $subdistrict->postal_code
|
||||||
|
];
|
||||||
|
return $cache[$normalizedName];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Jika tidak ditemukan, kembalikan null
|
||||||
|
return [
|
||||||
|
'code' => null,
|
||||||
|
'postal_code' => null
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private function getHubunganPemilikJaminanId(string $code, array &$cache): ?int
|
||||||
|
{
|
||||||
|
if (isset($cache[$code])) {
|
||||||
|
return $cache[$code];
|
||||||
|
}
|
||||||
|
|
||||||
|
$jaminan = HubunganPemilikJaminan::whereRaw('LOWER(name) = ?', [strtolower($code)])->first();
|
||||||
|
|
||||||
|
if ($jaminan) {
|
||||||
|
$cache[$code] = $jaminan->id;
|
||||||
|
return $jaminan->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mengonversi nilai TIMESTAMP menjadi format datetime yang valid.
|
||||||
|
*/
|
||||||
|
private function parseTimestamp(?string $timestamp): ?string
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
if ($timestamp) {
|
||||||
|
// Cek jika format hanya tanggal (Y-m-d)
|
||||||
|
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $timestamp)) {
|
||||||
|
return \Carbon\Carbon::createFromFormat('Y-m-d', $timestamp)
|
||||||
|
->startOfDay()
|
||||||
|
->toDateTimeString();
|
||||||
|
}
|
||||||
|
// Format lengkap (Y-m-d H:i:s)
|
||||||
|
if (preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/', $timestamp)) {
|
||||||
|
return \Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $timestamp)->toDateTimeString();
|
||||||
|
}
|
||||||
|
// Format d/m/Y H:i:s (contoh: 28/4/2017 14:43:43)
|
||||||
|
if (preg_match('/^\d{1,2}\/\d{1,2}\/\d{4} \d{2}:\d{2}:\d{2}$/', $timestamp)) {
|
||||||
|
return \Carbon\Carbon::createFromFormat('d/m/Y H:i:s', $timestamp)->toDateTimeString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::error('Gagal memparsing timestamp: ' . $timestamp . '. Pesan: ' . $e->getMessage());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function initializeErrorLog()
|
||||||
|
{
|
||||||
|
$file = $this->errorLogFile;
|
||||||
|
|
||||||
|
if (file_exists($file)) {
|
||||||
|
unlink($file); // Hapus file lama
|
||||||
|
}
|
||||||
|
|
||||||
|
$handle = fopen($file, 'w');
|
||||||
|
fputcsv($handle, ['mig_kd_debitur_seq', 'Error']);
|
||||||
|
fclose($handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function logError(string $kode, string $message)
|
||||||
|
{
|
||||||
|
Log::error("Error migrasi dokumen jaminan [$kode]: $message");
|
||||||
|
|
||||||
|
$handle = fopen($this->errorLogFile, 'a');
|
||||||
|
fputcsv($handle, [$kode, $message]);
|
||||||
|
fclose($handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
297
database/seeders/MigrationGambarInspeksiSeeder.php
Normal file
297
database/seeders/MigrationGambarInspeksiSeeder.php
Normal file
@@ -0,0 +1,297 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Lpj\Database\Seeders;
|
||||||
|
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Modules\Lpj\Models\Inspeksi;
|
||||||
|
use Modules\Basicdata\Models\Branch;
|
||||||
|
use Modules\Lpj\Models\DokumenJaminan;
|
||||||
|
use Modules\Lpj\Models\Permohonan;
|
||||||
|
use DateTime;
|
||||||
|
|
||||||
|
class MigrationGambarInspeksiSeeder extends Seeder
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the database seeds.
|
||||||
|
*/
|
||||||
|
protected $errorLogFile = __DIR__ . '/csv/inspeksi/foto_20251014-error.csv';
|
||||||
|
/**
|
||||||
|
* Migrasi data gambar inspeksi dari file csv ke tabel inspeksi_gambar
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
$this->initializeErrorLog();
|
||||||
|
// Path ke file csv
|
||||||
|
$filePath = realpath(__DIR__ . '/csv/inspeksi/foto_20251014.csv');
|
||||||
|
|
||||||
|
if (!$filePath) {
|
||||||
|
Log::error('File csv tidak ditemukan: ' . __DIR__ . '/csv/inspeksi/foto_20251014.csv');
|
||||||
|
$this->command->error('File csv tidak ditemukan.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($handle = fopen($filePath, 'r')) === false) {
|
||||||
|
Log::error('Gagal membuka file CSV: ' . $filePath);
|
||||||
|
$this->command->error('Gagal membuka file CSV.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$header = fgetcsv($handle, 0, ',');
|
||||||
|
$rows = [];
|
||||||
|
$batchSize = 500;
|
||||||
|
$userData = [];
|
||||||
|
$branchCache = []; // <-- Gunakan sebagai cache
|
||||||
|
$totalData = 0;
|
||||||
|
|
||||||
|
while (($data = fgetcsv($handle, 0, ',')) !== false) {
|
||||||
|
$totalData++;
|
||||||
|
}
|
||||||
|
|
||||||
|
rewind($handle);
|
||||||
|
fgetcsv($handle, 0, ','); // Skip header
|
||||||
|
|
||||||
|
$batchCount = 0;
|
||||||
|
$currentRow = 0;
|
||||||
|
$errorCount = 0;
|
||||||
|
$errorDebitureIds = [];
|
||||||
|
|
||||||
|
while (($data = fgetcsv($handle, 0, ',')) !== false) {
|
||||||
|
if (count($data) != count($header)) {
|
||||||
|
Log::warning('Baris CSV memiliki jumlah kolom yang tidak sesuai: ' . json_encode($data));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$rows[] = array_combine($header, $data);
|
||||||
|
$currentRow++;
|
||||||
|
|
||||||
|
if (count($rows) >= $batchSize) {
|
||||||
|
$batchCount++;
|
||||||
|
$this->command->info("Memproses batch ke-{$batchCount} ({$currentRow}/{$totalData})");
|
||||||
|
$this->processBatch($rows, $branchCache, $userData, $errorCount, $errorDebitureIds, $totalData, $batchCount, $currentRow);
|
||||||
|
$rows = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// info_harga_laporan_202505021522.csv
|
||||||
|
// print_r($rows[0]);
|
||||||
|
if (!empty($rows)) {
|
||||||
|
$batchCount++;
|
||||||
|
$this->command->info("Memproses batch ke-{$batchCount} ({$currentRow}/{$totalData})");
|
||||||
|
$this->processBatch($rows, $branchCache, $userData, $errorCount, $errorDebitureIds, $totalData, $batchCount, $currentRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose($handle);
|
||||||
|
$this->command->info("Data debiture berhasil dimigrasikan. Total data: {$totalData}, Total batch: {$batchCount}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private function processBatch(array $rows, array &$branchCache, array &$userData, int &$errorCount, array &$errorDebitureIds, int $totalData, int $batchCount, int $currentRow)
|
||||||
|
{
|
||||||
|
// Kelompokkan berdasarkan mig_nomor_jaminan
|
||||||
|
$groupedRows = $this->groupRowsByJaminan($rows);
|
||||||
|
|
||||||
|
foreach ($groupedRows as $nomorJaminan => $groupRows) {
|
||||||
|
try {
|
||||||
|
// Ambil informasi permohonan dan dokument_id
|
||||||
|
$nomorRegis = $this->getNomorRegistrasiPermohonan($nomorJaminan, $branchCache);
|
||||||
|
if (!$nomorRegis) {
|
||||||
|
Log::warning("Nomor registrasi tidak ditemukan untuk nomor jaminan: {$nomorJaminan}");
|
||||||
|
$errorCount++;
|
||||||
|
$errorDebitureIds[] = $nomorJaminan;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bangun JSON foto_form
|
||||||
|
$fotoJson = $this->checkFoto($groupRows);
|
||||||
|
|
||||||
|
|
||||||
|
Inspeksi::updateOrCreate(
|
||||||
|
[
|
||||||
|
'permohonan_id' => $nomorRegis['id'],
|
||||||
|
'dokument_id' => $nomorRegis['dokument_id']
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'foto_form' => $fotoJson,
|
||||||
|
'updated_at' => now()
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->command->info("Berhasil update foto_form untuk nomor jaminan: {$nomorJaminan}");
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::error("Error pada nomor jaminan {$nomorJaminan}: " . $e->getMessage());
|
||||||
|
$errorCount++;
|
||||||
|
$errorDebitureIds[] = $nomorJaminan;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private function groupRowsByJaminan(array $rows): array
|
||||||
|
{
|
||||||
|
$grouped = [];
|
||||||
|
|
||||||
|
foreach ($rows as $row) {
|
||||||
|
$nomorJaminan = $row['mig_nomor_jaminan'] ?? null;
|
||||||
|
|
||||||
|
if (!empty($nomorJaminan)) {
|
||||||
|
$grouped[$nomorJaminan][] = $row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $grouped;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private function checkFoto(array $rows)
|
||||||
|
{
|
||||||
|
// Inisialisasi kelompok untuk tiap kategori
|
||||||
|
$kategoriPrioritas = [
|
||||||
|
'PETA LOKASI' => [],
|
||||||
|
'GAMBAR SITUASI / SURAT UKUR' => [],
|
||||||
|
'FOTO JAMINAN' => [],
|
||||||
|
'MAK' => [],
|
||||||
|
'lainnya' => []
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($rows as $row) {
|
||||||
|
// Ambil kolom penting
|
||||||
|
$namaFoto = trim($row['mig_nama_gambar'] ?? '');
|
||||||
|
$pathFoto = trim($row['mig_url_gambar'] ?? '');
|
||||||
|
$kategori = trim($row['mig_kategori'] ?? 'lainnya');
|
||||||
|
$urutan = (int)($row['mig_urutan_gambar'] ?? 999);
|
||||||
|
$tgl = trim($row['mig_tgl'] ?? '');
|
||||||
|
$nomorLpj = trim($row['mig_nomor_laporan'] ?? '');
|
||||||
|
|
||||||
|
if (empty($pathFoto) || empty($tgl)) {
|
||||||
|
continue; // Lewati jika tidak lengkap
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$tanggal = \Carbon\Carbon::createFromFormat('d/m/Y H:i:s', $tgl)->startOfDay();
|
||||||
|
if (!$tanggal) {
|
||||||
|
throw new \Exception("Tanggal tidak valid");
|
||||||
|
}
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
continue; // Lewati jika tanggal tidak valid
|
||||||
|
}
|
||||||
|
|
||||||
|
$tahun = $tanggal->format('Y');
|
||||||
|
$bulanAngka = $tanggal->format('n');
|
||||||
|
$bulanNama = [
|
||||||
|
1 => 'JANUARI', 2 => 'FEBRUARI', 3 => 'MARET',
|
||||||
|
4 => 'APRIL', 5 => 'MEI', 6 => 'JUNI',
|
||||||
|
7 => 'JULI', 8 => 'AGUSTUS', 9 => 'SEPTEMBER',
|
||||||
|
10 => 'OKTOBER', 11 => 'NOVEMBER', 12 => 'DESEMBER'
|
||||||
|
][(int)$bulanAngka] ?? 'UNKNOWN';
|
||||||
|
|
||||||
|
$tanggalFormat = $tanggal->format('dmY');
|
||||||
|
|
||||||
|
if (empty($namaFoto)) {
|
||||||
|
$namaFoto = basename($pathFoto) ?: 'image.jpg';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gunakan '/' sebagai separator path
|
||||||
|
$finalPath = "surveyor/{$tahun}/{$bulanNama}/{$tanggalFormat}/{$nomorLpj}/{$pathFoto}";
|
||||||
|
|
||||||
|
$fotoItem = [
|
||||||
|
'urutan' => $urutan,
|
||||||
|
'name' => $namaFoto,
|
||||||
|
'path' => $finalPath,
|
||||||
|
'category' => $kategori,
|
||||||
|
'sub' => null,
|
||||||
|
'description' => '',
|
||||||
|
'created_by' => null,
|
||||||
|
'created_at' => null
|
||||||
|
];
|
||||||
|
|
||||||
|
// Masukkan ke dalam kelompok kategori
|
||||||
|
if (isset($kategoriPrioritas[$kategori])) {
|
||||||
|
$kategoriPrioritas[$kategori][] = $fotoItem;
|
||||||
|
} else {
|
||||||
|
$kategoriPrioritas['lainnya'][] = $fotoItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Urutkan masing-masing kategori berdasarkan urutan
|
||||||
|
foreach ($kategoriPrioritas as &$kelompok) {
|
||||||
|
usort($kelompok, function ($a, $b) {
|
||||||
|
return $a['urutan'] <=> $b['urutan'];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gabungkan dengan urutan prioritas: PETA LOKASI -> GAMBAR SITUASI -> FOTO JAMINAN -> lainnya
|
||||||
|
$finalFotos = array_merge(
|
||||||
|
$kategoriPrioritas['PETA LOKASI'],
|
||||||
|
$kategoriPrioritas['GAMBAR SITUASI / SURAT UKUR'],
|
||||||
|
$kategoriPrioritas['FOTO JAMINAN'],
|
||||||
|
$kategoriPrioritas['lainnya']
|
||||||
|
);
|
||||||
|
|
||||||
|
// Hapus indeks 'urutan'
|
||||||
|
$finalFotos = array_map(function ($foto) {
|
||||||
|
unset($foto['urutan']);
|
||||||
|
return $foto;
|
||||||
|
}, $finalFotos);
|
||||||
|
|
||||||
|
return json_encode([
|
||||||
|
'upload_foto' => $finalFotos
|
||||||
|
], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
|
||||||
|
}
|
||||||
|
private function getNomorRegistrasiPermohonan($nomor_jaminan_id, array &$cache)
|
||||||
|
{
|
||||||
|
// Cek apakah sudah ada di cache
|
||||||
|
if (isset($cache[$nomor_jaminan_id])) {
|
||||||
|
return $cache[$nomor_jaminan_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cari di tabel Permohonan berdasarkan nomor registrasi
|
||||||
|
$permohonan = Permohonan::where('nomor_registrasi', $nomor_jaminan_id)->first();
|
||||||
|
|
||||||
|
if (!$permohonan) {
|
||||||
|
// Tidak ditemukan
|
||||||
|
$cache[$nomor_jaminan_id] = null;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cari dokument jaminan terkait
|
||||||
|
$dokumenJaminan = DokumenJaminan::where('permohonan_id', $permohonan->id)->first();
|
||||||
|
|
||||||
|
// Simpan hasil ke cache
|
||||||
|
$result = [
|
||||||
|
'id' => $permohonan->id,
|
||||||
|
'dokument_id' => $dokumenJaminan ? $dokumenJaminan->id : null
|
||||||
|
];
|
||||||
|
|
||||||
|
$cache[$nomor_jaminan_id] = $result;
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private function initializeErrorLog()
|
||||||
|
{
|
||||||
|
$file = $this->errorLogFile;
|
||||||
|
|
||||||
|
if (file_exists($file)) {
|
||||||
|
unlink($file); // Hapus file lama
|
||||||
|
}
|
||||||
|
|
||||||
|
$handle = fopen($file, 'w');
|
||||||
|
fputcsv($handle, ['mig_kd_debitur_seq', 'Error']);
|
||||||
|
fclose($handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function logError(string $kode, string $message)
|
||||||
|
{
|
||||||
|
Log::error("Error migrasi dokumen jaminan [$kode]: $message");
|
||||||
|
|
||||||
|
$handle = fopen($this->errorLogFile, 'a');
|
||||||
|
fputcsv($handle, [$kode, $message]);
|
||||||
|
fclose($handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
1001
database/seeders/MigrationInpseksiSeeder.php
Normal file
1001
database/seeders/MigrationInpseksiSeeder.php
Normal file
File diff suppressed because it is too large
Load Diff
16
database/seeders/MigrationLaporanSeeder.php
Normal file
16
database/seeders/MigrationLaporanSeeder.php
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Lpj\Database\Seeders;
|
||||||
|
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
|
||||||
|
class MigrationLaporanSeeder extends Seeder
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the database seeds.
|
||||||
|
*/
|
||||||
|
public function run(): void
|
||||||
|
{
|
||||||
|
// $this->call([]);
|
||||||
|
}
|
||||||
|
}
|
||||||
225
database/seeders/MigrationPembandingSeeder.php
Normal file
225
database/seeders/MigrationPembandingSeeder.php
Normal file
@@ -0,0 +1,225 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Lpj\Database\Seeders;
|
||||||
|
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Modules\Lpj\Models\Inspeksi;
|
||||||
|
use Modules\Basicdata\Models\Branch;
|
||||||
|
use Modules\Lpj\Models\DokumenJaminan;
|
||||||
|
use Modules\Lpj\Models\Permohonan;
|
||||||
|
|
||||||
|
class MigrationPembandingSeeder extends Seeder
|
||||||
|
{
|
||||||
|
protected $errorLogFile = __DIR__ . '/csv/inspeksi/pembanding_20251016_error.csv';
|
||||||
|
/**
|
||||||
|
* Run the database seeds.
|
||||||
|
*/
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
// Path ke file csv
|
||||||
|
$filePath = realpath(__DIR__ . '/csv/inspeksi/pembanding_20251016.csv');
|
||||||
|
|
||||||
|
if (!$filePath) {
|
||||||
|
Log::error('File csv tidak ditemukan: ' . __DIR__ . '/csv/inspeksi/pembanding_20251016.csv');
|
||||||
|
$this->command->error('File csv tidak ditemukan.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($handle = fopen($filePath, 'r')) === false) {
|
||||||
|
Log::error('Gagal membuka file CSV: ' . $filePath);
|
||||||
|
$this->command->error('Gagal membuka file CSV.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$header = fgetcsv($handle, 0, ',');
|
||||||
|
$rows = [];
|
||||||
|
$batchSize = 300;
|
||||||
|
$userData = [];
|
||||||
|
$branchCache = []; // <-- Gunakan sebagai cache
|
||||||
|
$totalData = 0;
|
||||||
|
|
||||||
|
while (($data = fgetcsv($handle, 0, ',')) !== false) {
|
||||||
|
$totalData++;
|
||||||
|
}
|
||||||
|
|
||||||
|
rewind($handle);
|
||||||
|
fgetcsv($handle, 0, ','); // Skip header
|
||||||
|
|
||||||
|
$batchCount = 0;
|
||||||
|
$currentRow = 0;
|
||||||
|
$errorCount = 0;
|
||||||
|
$errorDebitureIds = [];
|
||||||
|
|
||||||
|
while (($data = fgetcsv($handle, 0, ',')) !== false) {
|
||||||
|
if (count($data) != count($header)) {
|
||||||
|
Log::warning('Baris CSV memiliki jumlah kolom yang tidak sesuai: ' . json_encode($data));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$rows[] = array_combine($header, $data);
|
||||||
|
$currentRow++;
|
||||||
|
|
||||||
|
if (count($rows) >= $batchSize) {
|
||||||
|
$batchCount++;
|
||||||
|
$this->command->info("Memproses batch ke-{$batchCount} ({$currentRow}/{$totalData})");
|
||||||
|
$this->processBatch($rows, $branchCache, $userData, $errorCount, $errorDebitureIds, $totalData, $batchCount, $currentRow);
|
||||||
|
$rows = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// info_harga_laporan_202505021522.csv
|
||||||
|
// print_r($rows[0]);
|
||||||
|
if (!empty($rows)) {
|
||||||
|
$batchCount++;
|
||||||
|
$this->command->info("Memproses batch ke-{$batchCount} ({$currentRow}/{$totalData})");
|
||||||
|
$this->processBatch($rows, $branchCache, $userData, $errorCount, $errorDebitureIds, $totalData, $batchCount, $currentRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose($handle);
|
||||||
|
$this->command->info("Data debiture berhasil dimigrasikan. Total data: {$totalData}, Total batch: {$batchCount}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private function processBatch(array $rows, array &$branchCache, array &$userData, int &$errorCount, array &$errorDebitureIds, int $totalData, int $batchCount, int $currentRow)
|
||||||
|
{
|
||||||
|
// Kelompokkan berdasarkan mig_nomor_lpj
|
||||||
|
$groupedRows = $this->groupRowsByJaminan($rows);
|
||||||
|
|
||||||
|
foreach ($groupedRows as $nomorLpj => $groupRows) {
|
||||||
|
try {
|
||||||
|
// Dapatkan info permohonan untuk update inspeksi
|
||||||
|
$nomorRegis = $this->getNomorRegistrasiPermohonan($nomorLpj, $branchCache);
|
||||||
|
if (!$nomorRegis) {
|
||||||
|
Log::warning("Nomor registrasi tidak ditemukan untuk nomor LPJ: {$nomorLpj}");
|
||||||
|
$errorCount++;
|
||||||
|
$errorDebitureIds[] = $nomorLpj;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bangun JSON data pembanding
|
||||||
|
$pembandingJson = $this->checkPembanding($groupRows);
|
||||||
|
|
||||||
|
// Update ke tabel inspeksi
|
||||||
|
|
||||||
|
// print_r($pembandingJson);
|
||||||
|
$inspeksi = Inspeksi::where('permohonan_id', $nomorRegis['id'])
|
||||||
|
->where('dokument_id', $nomorRegis['dokument_id'])
|
||||||
|
->update([
|
||||||
|
'data_pembanding' => $pembandingJson,
|
||||||
|
'updated_at' => now()
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->command->info("Berhasil update data_pembanding untuk nomor LPJ: {$nomorLpj}");
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::error("Error pada nomor LPJ {$nomorLpj}: " . $e->getMessage());
|
||||||
|
$errorCount++;
|
||||||
|
$errorDebitureIds[] = $nomorLpj;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private function groupRowsByJaminan(array $rows): array
|
||||||
|
{
|
||||||
|
$grouped = [];
|
||||||
|
|
||||||
|
foreach ($rows as $row) {
|
||||||
|
$nomorJaminan = $row['mig_nomor_lpj'] ?? null;
|
||||||
|
|
||||||
|
if (!empty($nomorJaminan)) {
|
||||||
|
$grouped[$nomorJaminan][] = $row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if($row['mig_nomor_lpj']=='251936'){
|
||||||
|
dd($grouped);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $grouped;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function checkPembanding(array $rows)
|
||||||
|
{
|
||||||
|
$pembandingList = [];
|
||||||
|
|
||||||
|
foreach ($rows as $row) {
|
||||||
|
// Pastikan kolom penting tersedia
|
||||||
|
$urutan = (int)($row['mig_urutan'] ?? 999);
|
||||||
|
$pembanding = trim($row['mig_pembanding'] ?? '');
|
||||||
|
|
||||||
|
// CUKUP VALIDASI PEMBANDING SAJA
|
||||||
|
if (empty($pembanding)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$pembandingList[] = [
|
||||||
|
'urutan' => $urutan,
|
||||||
|
'keterangan' => $pembanding,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Urutkan berdasarkan urutan
|
||||||
|
usort($pembandingList, function ($a, $b) {
|
||||||
|
return $a['urutan'] <=> $b['urutan'];
|
||||||
|
});
|
||||||
|
|
||||||
|
// Hapus indeks 'urutan'
|
||||||
|
$finalPembanding = array_map(function ($item) {
|
||||||
|
unset($item['urutan']);
|
||||||
|
return $item;
|
||||||
|
}, $pembandingList);
|
||||||
|
|
||||||
|
return json_encode([
|
||||||
|
'data_pembanding' => $finalPembanding
|
||||||
|
], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
|
||||||
|
}
|
||||||
|
private function getNomorRegistrasiPermohonan($nomor_jaminan_id, array &$cache)
|
||||||
|
{
|
||||||
|
if (isset($cache[$nomor_jaminan_id])) {
|
||||||
|
return $cache[$nomor_jaminan_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
$permohonan = Permohonan::where('nomor_lpj', $nomor_jaminan_id)->first();
|
||||||
|
|
||||||
|
if (!$permohonan) {
|
||||||
|
$cache[$nomor_jaminan_id] = null;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$dokumenJaminan = DokumenJaminan::where('permohonan_id', $permohonan->id)->first();
|
||||||
|
|
||||||
|
$result = [
|
||||||
|
'id' => $permohonan->id,
|
||||||
|
'dokument_id' => $dokumenJaminan ? $dokumenJaminan->id : null
|
||||||
|
];
|
||||||
|
|
||||||
|
$cache[$nomor_jaminan_id] = $result;
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function initializeErrorLog()
|
||||||
|
{
|
||||||
|
$file = $this->errorLogFile;
|
||||||
|
|
||||||
|
// Hapus file lama jika ada
|
||||||
|
if (file_exists($file)) {
|
||||||
|
unlink($file);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Buat file baru dengan header
|
||||||
|
$handle = fopen($file, 'w');
|
||||||
|
fputcsv($handle, ['mig_mst_jaminan_nomor_jaminan', 'Error']);
|
||||||
|
fclose($handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function logError($nomorJaminan, string $message)
|
||||||
|
{
|
||||||
|
Log::error("Error migrasi permohonan [$nomorJaminan]: $message");
|
||||||
|
|
||||||
|
// Tulis ke file error
|
||||||
|
$handle = fopen($this->errorLogFile, 'a');
|
||||||
|
fputcsv($handle, [$nomorJaminan, $message]);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
282
database/seeders/MigrationPemilikJaminanSeeder.php
Normal file
282
database/seeders/MigrationPemilikJaminanSeeder.php
Normal file
@@ -0,0 +1,282 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Lpj\Database\Seeders;
|
||||||
|
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Modules\Lpj\Models\HubunganPemilikJaminan;
|
||||||
|
use Modules\Lpj\Models\Debiture;
|
||||||
|
use Modules\Lpj\Models\PemilikJaminan;
|
||||||
|
use Modules\Basicdata\Models\Branch;
|
||||||
|
use Modules\Usermanagement\Models\User;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Modules\Location\Models\Province;
|
||||||
|
use Modules\Location\Models\City;
|
||||||
|
use Modules\Location\Models\District;
|
||||||
|
use Modules\Location\Models\Village;
|
||||||
|
|
||||||
|
class MigrationPemilikJaminanSeeder extends Seeder
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the database seeds.
|
||||||
|
*/
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
$filePath = realpath(__DIR__ . '/csv/pemilik_20251002.csv');
|
||||||
|
|
||||||
|
if (!$filePath) {
|
||||||
|
Log::error('File CSV tidak ditemukan: ' . __DIR__ . '/csv/pemilik_20251002.csv');
|
||||||
|
$this->command->error('File CSV tidak ditemukan.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($handle = fopen($filePath, 'r')) === false) {
|
||||||
|
Log::error('Gagal membuka file CSV: ' . $filePath);
|
||||||
|
$this->command->error('Gagal membuka file CSV.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$header = fgetcsv($handle, 0, ',');
|
||||||
|
$rows = [];
|
||||||
|
$batchSize = 100; // Ukuran batch
|
||||||
|
$branchCache = [];
|
||||||
|
$debitureCache = [];
|
||||||
|
$hubunganPemilikCache = [];
|
||||||
|
$provinceCache = [];
|
||||||
|
$cityCache = [];
|
||||||
|
$districtCache = [];
|
||||||
|
$subdistrictCache = [];
|
||||||
|
|
||||||
|
while (($data = fgetcsv($handle, 0, ',')) !== false) {
|
||||||
|
if (count($data) != count($header)) {
|
||||||
|
Log::warning('Baris CSV memiliki jumlah kolom yang tidak sesuai: ' . json_encode($data));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$rows[] = array_combine($header, $data);
|
||||||
|
|
||||||
|
if (count($rows) >= $batchSize) {
|
||||||
|
$this->processBatch($rows, $branchCache, $debitureCache, $hubunganPemilikCache, $provinceCache, $cityCache, $districtCache, $subdistrictCache);
|
||||||
|
$rows = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// print_r($rows);
|
||||||
|
if (!empty($rows)) {
|
||||||
|
$this->processBatch($rows, $branchCache, $debitureCache, $hubunganPemilikCache, $provinceCache, $cityCache, $districtCache, $subdistrictCache);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose($handle);
|
||||||
|
|
||||||
|
$this->command->info('Data permohonan berhasil dimigrasikan.');
|
||||||
|
}
|
||||||
|
|
||||||
|
private function processBatch(array $rows, array &$branchCache, array &$debitureCache, array &$hubunganPemilikCache, array &$provinceCache, array &$cityCache, array &$districtCache, array &$subdistrictCache)
|
||||||
|
{
|
||||||
|
foreach ($rows as $index => $row) {
|
||||||
|
$debitureId = $this->getDebiturId($row['mig_kd_debitur_seq'], $debitureCache);
|
||||||
|
|
||||||
|
if (!$debitureId) {
|
||||||
|
Log::warning('Debitur tidak ditemukan untuk kode: ' . $row['mig_kd_debitur_seq']);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$hubunganPemilik = $this->getHubunganPemilikId($row['mig_hubungan_pemilik_jaminan'], $hubunganPemilikCache);
|
||||||
|
|
||||||
|
|
||||||
|
$proviceCode = $this->getProvinceCode($row['mig_province_name'], $provinceCache);
|
||||||
|
$cityCode = $this->getCityCode($row['mig_city_name'], $cityCache);
|
||||||
|
$districtCode = $this->getDistrictCode($row['mig_district_name'], $districtCache);
|
||||||
|
|
||||||
|
$subdistrictCode = $this->getSubdistrictCode($row['mig_village_name'], $subdistrictCache, $districtCache);
|
||||||
|
|
||||||
|
|
||||||
|
PemilikJaminan::updateOrCreate([
|
||||||
|
'mig_kd_debitur_seq' => $row['mig_kd_debitur_seq'],
|
||||||
|
],[
|
||||||
|
'debiture_id' => $debitureId,
|
||||||
|
'hubungan_pemilik_jaminan_id' => $hubunganPemilik,
|
||||||
|
'name' => $row['name'],
|
||||||
|
'detail_sertifikat' => null,
|
||||||
|
'npwp' => null,
|
||||||
|
'nomor_id' => null,
|
||||||
|
'email' => null,
|
||||||
|
'phone' => null,
|
||||||
|
'province_code' => $proviceCode,
|
||||||
|
'city_code' => $cityCode,
|
||||||
|
'district_code' => $districtCode,
|
||||||
|
'village_code' => $subdistrictCode['code'],
|
||||||
|
'postal_code' => $subdistrictCode['postal_code'],
|
||||||
|
'address' => $row['address'],
|
||||||
|
'created_at' => $this->parseTimestamp($row['created_at']),
|
||||||
|
'updated_at' => $this->parseTimestamp($row['updated_at']),
|
||||||
|
'mig_kd_debitur_seq' => $row['mig_kd_debitur_seq'],
|
||||||
|
'processed_at' => now(),
|
||||||
|
'is_mig' => 1
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->command->info('Proses data Pemilik Jaminan ' . $row['name'] . ' (' . ($index + 1) . '/' . count($rows) . ')');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getDebiturId(string $code, array &$cache): ?int
|
||||||
|
{
|
||||||
|
if (isset($cache[$code])) {
|
||||||
|
return $cache[$code];
|
||||||
|
}
|
||||||
|
|
||||||
|
$debitur = Debiture::where('mig_kd_debitur_seq', $code)->first();
|
||||||
|
|
||||||
|
if ($debitur) {
|
||||||
|
$cache[$code] = $debitur->id;
|
||||||
|
return $debitur->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getHubunganPemilikId(string $name, array &$cache): ?int
|
||||||
|
{
|
||||||
|
// Normalisasi nama
|
||||||
|
$normalizedName = strtolower(trim($name));
|
||||||
|
|
||||||
|
// Cek cache untuk menghindari query berulang
|
||||||
|
if (isset($cache[$normalizedName])) {
|
||||||
|
return $cache[$normalizedName];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query database dengan pengamanan tambahan
|
||||||
|
$hubunganPemilik = HubunganPemilikJaminan::whereRaw('LOWER(name) = ?', [$normalizedName])
|
||||||
|
->whereNull('deleted_at') // Tambahkan ini jika Anda menggunakan soft deletes
|
||||||
|
->first();
|
||||||
|
|
||||||
|
// Jika data ditemukan, simpan dalam cache
|
||||||
|
if ($hubunganPemilik) {
|
||||||
|
$cache[$normalizedName] = $hubunganPemilik->id;
|
||||||
|
return $hubunganPemilik->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default jika data tidak ditemukan
|
||||||
|
$cache[$normalizedName] = 1; // Cache nilai default untuk menghindari query berulang
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private function getProvinceCode(string $name, array &$cache): ?string
|
||||||
|
{
|
||||||
|
|
||||||
|
$normalizedName = strtolower($name);
|
||||||
|
if (isset($cache[$normalizedName])) {
|
||||||
|
return $cache[$normalizedName];
|
||||||
|
}
|
||||||
|
|
||||||
|
$province = Province::whereRaw('LOWER(name) = ?', [strtolower($name)])->first();
|
||||||
|
|
||||||
|
if ($province) {
|
||||||
|
$cache[$normalizedName] = $province->code;
|
||||||
|
return $province->code;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getCityCode(string $name, array &$cache): ?string
|
||||||
|
{
|
||||||
|
$normalizedName = strtolower($name);
|
||||||
|
if (isset($cache[$normalizedName])) {
|
||||||
|
return $cache[$normalizedName];
|
||||||
|
}
|
||||||
|
|
||||||
|
$city = City::whereRaw('LOWER(name) = ?', [strtolower($name)])->first();
|
||||||
|
|
||||||
|
if ($city) {
|
||||||
|
$cache[$normalizedName] = $city->code;
|
||||||
|
return $city->code;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getDistrictCode(string $name, array &$cache): ?string
|
||||||
|
{
|
||||||
|
$normalizedName = strtolower($name);
|
||||||
|
if (isset($cache[$normalizedName])) {
|
||||||
|
return $cache[$normalizedName];
|
||||||
|
}
|
||||||
|
|
||||||
|
$district = District::whereRaw('LOWER(name) = ?', [strtolower($name)])->first();
|
||||||
|
|
||||||
|
if ($district) {
|
||||||
|
$cache[$normalizedName] = $district->code;
|
||||||
|
return $district->code;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getSubdistrictCode(string $name, array &$cache, array &$districtCache): ?array
|
||||||
|
{
|
||||||
|
$normalizedName = strtolower($name);
|
||||||
|
|
||||||
|
// Pastikan cache menyimpan array, bukan hanya kode
|
||||||
|
if (isset($cache[$normalizedName])) {
|
||||||
|
return $cache[$normalizedName];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ambil subdistrict dari database
|
||||||
|
$subdistrict = Village::whereRaw('LOWER(name) = ?', [$normalizedName])->first();
|
||||||
|
|
||||||
|
// Jika ditemukan, simpan ke dalam cache sebagai array lengkap
|
||||||
|
if ($subdistrict) {
|
||||||
|
$cache[$normalizedName] = [
|
||||||
|
'code' => $subdistrict->code,
|
||||||
|
'postal_code' => $subdistrict->postal_code
|
||||||
|
];
|
||||||
|
return $cache[$normalizedName];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Jika tidak ditemukan, kembalikan null
|
||||||
|
return [
|
||||||
|
'code' => null,
|
||||||
|
'postal_code' => null
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private function parseDate(?string $date): ?string
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return $date ? \Carbon\Carbon::createFromFormat('Y-m-d', $date)->toDateString() : null;
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::error('Gagal memparsing tanggal: ' . $date);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function parseTimestamp(?string $timestamp): ?string
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
if ($timestamp) {
|
||||||
|
// Cek jika format hanya tanggal (Y-m-d)
|
||||||
|
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $timestamp)) {
|
||||||
|
return \Carbon\Carbon::createFromFormat('Y-m-d', $timestamp)
|
||||||
|
->startOfDay()
|
||||||
|
->toDateTimeString();
|
||||||
|
}
|
||||||
|
// Format lengkap (Y-m-d H:i:s)
|
||||||
|
if (preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/', $timestamp)) {
|
||||||
|
return \Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $timestamp)->toDateTimeString();
|
||||||
|
}
|
||||||
|
// Format d/m/Y H:i:s (contoh: 28/4/2017 14:43:43)
|
||||||
|
if (preg_match('/^\d{1,2}\/\d{1,2}\/\d{4} \d{2}:\d{2}:\d{2}$/', $timestamp)) {
|
||||||
|
return \Carbon\Carbon::createFromFormat('d/m/Y H:i:s', $timestamp)->toDateTimeString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::error('Gagal memparsing timestamp: ' . $timestamp . '. Pesan: ' . $e->getMessage());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
505
database/seeders/MigrationPenilaiSeeder.php
Normal file
505
database/seeders/MigrationPenilaiSeeder.php
Normal file
@@ -0,0 +1,505 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Lpj\Database\Seeders;
|
||||||
|
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
use Modules\Lpj\Models\DokumenJaminan;
|
||||||
|
use Modules\Lpj\Models\Permohonan;
|
||||||
|
use Modules\Lpj\Models\Penilai;
|
||||||
|
use Modules\Lpj\Models\Laporan;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
|
class MigrationPenilaiSeeder extends Seeder
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the database seeds.
|
||||||
|
*/
|
||||||
|
protected $errorLogFile = __DIR__ . '/csv/penilaian/penilai.fix.latest_error.csv';
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
$this->initializeErrorLog();
|
||||||
|
// Path ke file csv
|
||||||
|
$filePath = realpath(__DIR__ . '/csv/penilaian/penilai.fix.latest_20251011.csv');
|
||||||
|
|
||||||
|
if (!$filePath) {
|
||||||
|
Log::error('File csv tidak ditemukan: ' . __DIR__ . '/csv/penilaian/penilai.fix.latest_20251011.csv');
|
||||||
|
$this->command->error('File csv tidak ditemukan.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($handle = fopen($filePath, 'r')) === false) {
|
||||||
|
Log::error('Gagal membuka file CSV: ' . $filePath);
|
||||||
|
$this->command->error('Gagal membuka file CSV.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$header = fgetcsv($handle, 0, ',');
|
||||||
|
$rows = [];
|
||||||
|
$batchSize = 500;
|
||||||
|
$userData = [];
|
||||||
|
$branchCache = []; // <-- Gunakan sebagai cache
|
||||||
|
$totalData = 0;
|
||||||
|
|
||||||
|
while (($data = fgetcsv($handle, 0, ',')) !== false) {
|
||||||
|
$totalData++;
|
||||||
|
}
|
||||||
|
|
||||||
|
rewind($handle);
|
||||||
|
fgetcsv($handle, 0, ','); // Skip header
|
||||||
|
|
||||||
|
$batchCount = 0;
|
||||||
|
$currentRow = 0;
|
||||||
|
$errorCount = 0;
|
||||||
|
$errorDebitureIds = [];
|
||||||
|
|
||||||
|
while (($data = fgetcsv($handle, 0, ',')) !== false) {
|
||||||
|
if (count($data) != count($header)) {
|
||||||
|
Log::warning('Baris CSV memiliki jumlah kolom yang tidak sesuai: ' . json_encode($data));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$rows[] = array_combine($header, $data);
|
||||||
|
$currentRow++;
|
||||||
|
|
||||||
|
if (count($rows) >= $batchSize) {
|
||||||
|
$batchCount++;
|
||||||
|
$this->command->info("Memproses batch ke-{$batchCount} ({$currentRow}/{$totalData})");
|
||||||
|
$this->processBatch($rows, $branchCache, $userData, $errorCount, $errorDebitureIds, $totalData, $batchCount, $currentRow);
|
||||||
|
$rows = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// info_harga_laporan_202505021522.csv
|
||||||
|
// print_r($rows);
|
||||||
|
if (!empty($rows)) {
|
||||||
|
$batchCount++;
|
||||||
|
$this->command->info("Memproses batch ke-{$batchCount} ({$currentRow}/{$totalData})");
|
||||||
|
$this->processBatch($rows, $branchCache, $userData, $errorCount, $errorDebitureIds, $totalData, $batchCount, $currentRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose($handle);
|
||||||
|
$this->command->info("Data debiture berhasil dimigrasikan. Total data: {$totalData}, Total batch: {$batchCount}");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private function processBatch(array $rows, array &$branchCache, array &$userData, int &$errorCount, array &$errorDebitureIds, int $totalData, int $batchCount, int $currentRow)
|
||||||
|
{
|
||||||
|
// Kelompokkan berdasarkan mig_nomor_lpj
|
||||||
|
$groupedRows = $this->groupRowsByLpj($rows);
|
||||||
|
|
||||||
|
foreach ($groupedRows as $nomorLpj => $groupRows) {
|
||||||
|
try {
|
||||||
|
// Ambil informasi permohonan dan dokument_id
|
||||||
|
$nomorRegis = $this->getNomorRegistrasiPermohonan($nomorLpj, $branchCache);
|
||||||
|
if (!$nomorRegis) {
|
||||||
|
Log::warning("Nomor registrasi tidak ditemukan untuk nomor LPJ: {$nomorLpj}");
|
||||||
|
$errorCount++;
|
||||||
|
$errorDebitureIds[] = $nomorLpj;
|
||||||
|
//continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dapatkan type_penilai (misal: standar, sederhana)
|
||||||
|
$firstRow = reset($groupRows);
|
||||||
|
|
||||||
|
$typePenilai = $this->checkTypePenilai($firstRow['mig_kode_jenis_laporan'] ?? '');
|
||||||
|
|
||||||
|
if (!$typePenilai) {
|
||||||
|
Log::warning("Tidak ada jenis laporan valid untuk nomor LPJ: {$nomorLpj}");
|
||||||
|
$errorCount++;
|
||||||
|
$errorDebitureIds[] = $nomorLpj;
|
||||||
|
//continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bangun JSON type_penilai
|
||||||
|
$penilaiJson = $this->cekJenisPenilai($groupRows);
|
||||||
|
|
||||||
|
// Simpan ke tabel Penilai
|
||||||
|
|
||||||
|
// print_r(json_decode($penilaiJson, true));
|
||||||
|
|
||||||
|
// Mapping field JSON berdasarkan tipe penilaian
|
||||||
|
$fillableFieldMap = [
|
||||||
|
'memo' => 'memo',
|
||||||
|
'standar' => 'lpj',
|
||||||
|
'sederhana' => 'lpj',
|
||||||
|
'call_report' => 'call_report',
|
||||||
|
'rap' => 'rap',
|
||||||
|
'resume' => 'resume'
|
||||||
|
];
|
||||||
|
|
||||||
|
$fieldToUpdate = $fillableFieldMap[$typePenilai] ?? null;
|
||||||
|
|
||||||
|
if (!$fieldToUpdate) {
|
||||||
|
Log::warning("Field tidak dikenali untuk tipe: {$typePenilai}");
|
||||||
|
$errorCount++;
|
||||||
|
$errorDebitureIds[] = $nomorLpj;
|
||||||
|
//continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NO: 001/241917/LPJ/PJ-2251/VII/24
|
||||||
|
// 001 => kode cabang
|
||||||
|
// 241917 => nomor lpj
|
||||||
|
// LPJ => jenis laporan
|
||||||
|
// PJ-2251 => nomor registrasi ambil nilai akhirnnya 242251
|
||||||
|
// VII => bulan
|
||||||
|
// 24 => tahun
|
||||||
|
|
||||||
|
// Generate nomor_laporan
|
||||||
|
$mig_permohonan = json_decode($nomorRegis['mig_permohonan'],true) ?? '';
|
||||||
|
$tanggal = $mig_permohonan['mig_mst_lpj_tgl_laporan'] ?? $mig_permohonan['mig_mst_lpj_tgl_oto'] ?? $firstRow['mig_created_at'];
|
||||||
|
|
||||||
|
//$tanggal = $firstRow['mig_created_at'];
|
||||||
|
$nomorD = $nomorRegis['nomor_registrasi'];
|
||||||
|
$nomorRegistrasi = "PJ-{$nomorD}";
|
||||||
|
$nomorLaporan = $this->generateNomorLaporan($typePenilai, $nomorLpj, $nomorRegistrasi, $tanggal, $nomorRegis['id']);
|
||||||
|
// Simpan atau update ke tabel Penilai
|
||||||
|
$penilaiLP = Penilai::updateOrCreate(
|
||||||
|
[
|
||||||
|
'permohonan_id' => $nomorRegis['id'],
|
||||||
|
'dokument_id' => $nomorRegis['dokument_id']
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'type' => $typePenilai,
|
||||||
|
$fieldToUpdate => $penilaiJson,
|
||||||
|
'type_penilai' => $typePenilai,
|
||||||
|
'created_at' => $this->parseTimestamp($tanggal),
|
||||||
|
'updated_at' => $this->parseTimestamp($tanggal),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Simpan ke tabel Laporan
|
||||||
|
Laporan::updateOrCreate(
|
||||||
|
[
|
||||||
|
'permohonan_id' => $penilaiLP->permohonan_id,
|
||||||
|
'dokumen_jaminan_id' => $penilaiLP->dokument_id
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'nomor_laporan' => $nomorLaporan,
|
||||||
|
'created_at' => $this->parseTimestamp($tanggal),
|
||||||
|
'updated_at' => $this->parseTimestamp($tanggal)
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
$this->command->info("Berhasil simpan data penilai untuk nomor LPJ: {$nomorLpj}");
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::error("Error pada nomor LPJ {$nomorLpj}: " . $e->getMessage());
|
||||||
|
$errorCount++;
|
||||||
|
$errorDebitureIds[] = $nomorLpj;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private function getNomorRegistrasiPermohonan($nomorLpj, array &$cache)
|
||||||
|
{
|
||||||
|
if (isset($cache[$nomorLpj])) {
|
||||||
|
return $cache[$nomorLpj];
|
||||||
|
}
|
||||||
|
|
||||||
|
$permohonan = Permohonan::where('nomor_lpj', $nomorLpj)->first();
|
||||||
|
|
||||||
|
if (!$permohonan) {
|
||||||
|
$cache[$nomorLpj] = null;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$dokumenJaminan = DokumenJaminan::where('permohonan_id', $permohonan->id)->first();
|
||||||
|
|
||||||
|
$result = [
|
||||||
|
'id' => $permohonan->id,
|
||||||
|
'dokument_id' => $dokumenJaminan ? $dokumenJaminan->id : null,
|
||||||
|
'nomor_registrasi' => $permohonan->nomor_registrasi,
|
||||||
|
'mig_permohonan' => $permohonan->mig_permohonan
|
||||||
|
];
|
||||||
|
|
||||||
|
$cache[$nomorLpj] = $result;
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
private function groupRowsByLpj(array $rows): array
|
||||||
|
{
|
||||||
|
$grouped = [];
|
||||||
|
|
||||||
|
foreach ($rows as $row) {
|
||||||
|
$nomorLpj = $row['mig_nomor_lpj'] ?? null;
|
||||||
|
|
||||||
|
if (!empty($nomorLpj)) {
|
||||||
|
$grouped[$nomorLpj][] = $row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $grouped;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function checkTypePenilai($type)
|
||||||
|
{
|
||||||
|
$data = [
|
||||||
|
'MAK' => 'memo',
|
||||||
|
'STD' => 'standar',
|
||||||
|
'SPL' => 'sederhana',
|
||||||
|
'RHP' => 'call-report',
|
||||||
|
'RAP' => 'rap',
|
||||||
|
'PRG' => 'resume',
|
||||||
|
];
|
||||||
|
|
||||||
|
return $data[$type];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private function cekJenisPenilai(array $groupRows)
|
||||||
|
{
|
||||||
|
// Urutkan grup berdasarkan mig_urutan_seq
|
||||||
|
usort($groupRows, function ($a, $b) {
|
||||||
|
return ($a['mig_urutan_seq'] ?? 999) <=> ($b['mig_urutan_seq'] ?? 999);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Inisialisasi struktur JSON
|
||||||
|
$penilaiJson = [
|
||||||
|
'luas_bangunan' => null,
|
||||||
|
'luas_tanah' => null,
|
||||||
|
'nilai_tanah_1' => null,
|
||||||
|
'nilai_tanah_2' => null,
|
||||||
|
'sarana_pelengkap_penilai' => null,
|
||||||
|
'nilai_sarana_pelengkap_1' => null,
|
||||||
|
'nilai_sarana_pelengkap_2' => null,
|
||||||
|
'total_nilai_pasar_wajar' => null,
|
||||||
|
'likuidasi' => null,
|
||||||
|
'likuidasi_nilai_1' => null,
|
||||||
|
'likuidasi_nilai_2' => null,
|
||||||
|
'asuransi_luas_bangunan' => null,
|
||||||
|
'asuransi_nilai_1' => null,
|
||||||
|
'asuransi_nilai_2' => "0",
|
||||||
|
'npw_tambahan' => []
|
||||||
|
];
|
||||||
|
|
||||||
|
// Ambil mainRow (urutan pertama)
|
||||||
|
$mainRow = null;
|
||||||
|
foreach ($groupRows as $row) {
|
||||||
|
if (($row['mig_urutan_seq'] ?? '') == 1) {
|
||||||
|
$mainRow = $row;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Jika tidak ada mainRow, ambil baris pertama sebagai fallback
|
||||||
|
if (!$mainRow && !empty($groupRows[0])) {
|
||||||
|
$mainRow = $groupRows[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($mainRow) {
|
||||||
|
$penilaiJson['total_nilai_pasar_wajar'] = $mainRow['mig_nilai_total_nilai_pasar'] ?? null;
|
||||||
|
$penilaiJson['likuidasi'] = $mainRow['mig_nilai_likudasi'] ?? null;
|
||||||
|
|
||||||
|
// Hitung likuidasi nilai 2 jika ada total dan persen likuidasi
|
||||||
|
$totalPasarWajar = (int)str_replace('.', '', $mainRow['mig_nilai_total_nilai_pasar'] ?? 0);
|
||||||
|
$persenLikuidasi = (int)($mainRow['mig_nilai_likudasi'] ?? 0);
|
||||||
|
$penilaiJson['likuidasi_nilai_1'] = $mainRow['mig_nilai_total_nilai_pasar'] ?? null;
|
||||||
|
$penilaiJson['likuidasi_nilai_2'] = number_format(
|
||||||
|
$totalPasarWajar * ($persenLikuidasi / 100),
|
||||||
|
0,
|
||||||
|
'',
|
||||||
|
''
|
||||||
|
);
|
||||||
|
|
||||||
|
// Isi data utama hanya untuk urutan 1
|
||||||
|
$penilaiJson['luas_tanah'] = $mainRow['mig_nilai_satuan'] ?? null;
|
||||||
|
$penilaiJson['nilai_tanah_1'] = $mainRow['mig_harga_satuan'] ?? null;
|
||||||
|
$penilaiJson['nilai_tanah_2'] = number_format(
|
||||||
|
(int)str_replace('.', '', $mainRow['mig_nilai_satuan'] ?? 0) *
|
||||||
|
(int)str_replace('.', '', $mainRow['mig_harga_satuan'] ?? 0),
|
||||||
|
0,
|
||||||
|
'',
|
||||||
|
''
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Proses tambahan (urutan > 1)
|
||||||
|
foreach ($groupRows as $row) {
|
||||||
|
// Hanya proses jika mig_urutan_seq ada
|
||||||
|
$urutan = $row['mig_urutan_seq'] ?? '';
|
||||||
|
if (empty($urutan)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tambahkan ke npw_tambahan
|
||||||
|
$penilaiJson['npw_tambahan'][] = [
|
||||||
|
'name' => $row['mig_keterangan'] ?? 'Luas Bangunan Tambahan',
|
||||||
|
'luas' => $row['mig_nilai_satuan'] ?? null,
|
||||||
|
'nilai_1' => $row['mig_harga_satuan'] ?? null,
|
||||||
|
'nilai_2' => number_format(
|
||||||
|
(int)str_replace('.', '', $row['mig_nilai_satuan'] ?? 0) *
|
||||||
|
(int)str_replace('.', '', $row['mig_harga_satuan'] ?? 0),
|
||||||
|
0,
|
||||||
|
'',
|
||||||
|
''
|
||||||
|
)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kosongkan npw_tambahan jika kosong
|
||||||
|
if (empty($penilaiJson['npw_tambahan'])) {
|
||||||
|
$penilaiJson['npw_tambahan'] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return json_encode($penilaiJson, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function convertToRoman($month)
|
||||||
|
{
|
||||||
|
$roman = ['I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX', 'X', 'XI', 'XII'];
|
||||||
|
return $month >= 1 && $month <= 12 ? $roman[$month - 1] : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
private function generateNomorLaporan($typePenilai, $nomorLpj, $nomorRegistrasi, $tanggal)
|
||||||
|
{
|
||||||
|
// Mapping type_penilai ke singkatan laporan
|
||||||
|
$laporanMap = [
|
||||||
|
'memo' => 'MEMO',
|
||||||
|
'standar' => 'LPJ',
|
||||||
|
'sederhana' => 'LPJ',
|
||||||
|
'call_report' => 'CALL',
|
||||||
|
'rap' => 'RAP',
|
||||||
|
'resume' => 'RESUME'
|
||||||
|
];
|
||||||
|
|
||||||
|
// Dapatkan tahun dan bulan dari tanggal
|
||||||
|
$tanggal_ = $this->parseTimestamp($tanggal);
|
||||||
|
$date = \Carbon\Carbon::parse($tanggal_);
|
||||||
|
$kodeCabang = '001'; // bisa diambil dari user atau parameter lain jika dinamis
|
||||||
|
$tahun = substr($date->year, -2); // 2024 → 24
|
||||||
|
$bulan = $this->convertToRoman($date->month); // 7 → VII
|
||||||
|
|
||||||
|
// Format akhir nomor registrasi (PJ-XXX)
|
||||||
|
$nomorDebiturAkhir = substr($nomorRegistrasi, -4); // PJ-2251 → 2251
|
||||||
|
|
||||||
|
return sprintf(
|
||||||
|
"%s/%s/%s/%s/%s/%s",
|
||||||
|
$kodeCabang,
|
||||||
|
$nomorLpj,
|
||||||
|
$laporanMap[$typePenilai] ?? strtoupper($typePenilai),
|
||||||
|
"PJ-" . $nomorDebiturAkhir,
|
||||||
|
$bulan,
|
||||||
|
$tahun
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function parseTimestamp(?string $timestamp): ?string
|
||||||
|
{
|
||||||
|
if (!$timestamp) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trim whitespace dan normalize
|
||||||
|
$timestamp = trim($timestamp);
|
||||||
|
|
||||||
|
// Log untuk debugging
|
||||||
|
Log::info('Mencoba parsing timestamp: "' . $timestamp . '"');
|
||||||
|
|
||||||
|
// Parsing dengan DateTime native PHP untuk lebih robust
|
||||||
|
try {
|
||||||
|
// Pattern untuk format d/m/Y H:i:s
|
||||||
|
if (preg_match('/^(\d{1,2})\/(\d{1,2})\/(\d{4})\s+(\d{1,2}):(\d{1,2}):(\d{1,2})$/', $timestamp, $matches)) {
|
||||||
|
$day = (int) $matches[1];
|
||||||
|
$month = (int) $matches[2];
|
||||||
|
$year = (int) $matches[3];
|
||||||
|
$hour = (int) $matches[4];
|
||||||
|
$minute = (int) $matches[5];
|
||||||
|
$second = (int) $matches[6];
|
||||||
|
|
||||||
|
// Validasi nilai
|
||||||
|
if ($day >= 1 && $day <= 31 && $month >= 1 && $month <= 12 && $year >= 1900 && $year <= 2100 &&
|
||||||
|
$hour >= 0 && $hour <= 23 && $minute >= 0 && $minute <= 59 && $second >= 0 && $second <= 59) {
|
||||||
|
|
||||||
|
// Buat DateTime object langsung
|
||||||
|
$dateTime = new \DateTime();
|
||||||
|
$dateTime->setDate($year, $month, $day);
|
||||||
|
$dateTime->setTime($hour, $minute, $second);
|
||||||
|
|
||||||
|
$result = $dateTime->format('Y-m-d H:i:s');
|
||||||
|
Log::info('Berhasil parsing dengan DateTime: ' . $timestamp . ' -> ' . $result);
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pattern untuk format d/m/Y tanpa waktu
|
||||||
|
if (preg_match('/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/', $timestamp, $matches)) {
|
||||||
|
$day = (int) $matches[1];
|
||||||
|
$month = (int) $matches[2];
|
||||||
|
$year = (int) $matches[3];
|
||||||
|
|
||||||
|
// Validasi nilai
|
||||||
|
if ($day >= 1 && $day <= 31 && $month >= 1 && $month <= 12 && $year >= 1900 && $year <= 2100) {
|
||||||
|
|
||||||
|
// Buat DateTime object langsung
|
||||||
|
$dateTime = new \DateTime();
|
||||||
|
$dateTime->setDate($year, $month, $day);
|
||||||
|
$dateTime->setTime(0, 0, 0);
|
||||||
|
|
||||||
|
$result = $dateTime->format('Y-m-d H:i:s');
|
||||||
|
Log::info('Berhasil parsing tanpa waktu dengan DateTime: ' . $timestamp . ' -> ' . $result);
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::error('Gagal parsing dengan DateTime: ' . $timestamp . '. Error: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback ke format Carbon standar untuk format lainnya
|
||||||
|
$formats = [
|
||||||
|
'Y-m-d H:i:s',
|
||||||
|
'Y-m-d',
|
||||||
|
'd-m-Y H:i:s',
|
||||||
|
'd-m-Y',
|
||||||
|
'j-n-Y H:i:s',
|
||||||
|
'j-n-Y',
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($formats as $format) {
|
||||||
|
try {
|
||||||
|
$carbon = \Carbon\Carbon::createFromFormat($format, $timestamp);
|
||||||
|
|
||||||
|
if ($carbon && $carbon->format($format) === $timestamp) {
|
||||||
|
// Jika format tidak mengandung waktu, set ke awal hari
|
||||||
|
if (!str_contains($format, 'H:i:s')) {
|
||||||
|
$carbon = $carbon->startOfDay();
|
||||||
|
}
|
||||||
|
Log::info('Berhasil parsing dengan format ' . $format . ': ' . $timestamp . ' -> ' . $carbon->toDateTimeString());
|
||||||
|
return $carbon->toDateTimeString();
|
||||||
|
}
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
// Lanjut ke format berikutnya
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::error('Tidak dapat memparsing timestamp dengan format apapun: "' . $timestamp . '"');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function initializeErrorLog()
|
||||||
|
{
|
||||||
|
$file = $this->errorLogFile;
|
||||||
|
|
||||||
|
if (file_exists($file)) {
|
||||||
|
unlink($file); // Hapus file lama
|
||||||
|
}
|
||||||
|
|
||||||
|
$handle = fopen($file, 'w');
|
||||||
|
fputcsv($handle, ['mig_kd_debitur_seq', 'Error']);
|
||||||
|
fclose($handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function logError(string $kode, string $message)
|
||||||
|
{
|
||||||
|
Log::error("Error migrasi dokumen jaminan [$kode]: $message");
|
||||||
|
|
||||||
|
$handle = fopen($this->errorLogFile, 'a');
|
||||||
|
fputcsv($handle, [$kode, $message]);
|
||||||
|
fclose($handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
414
database/seeders/MigrationPermohonanSeeder.php
Normal file
414
database/seeders/MigrationPermohonanSeeder.php
Normal file
@@ -0,0 +1,414 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Lpj\Database\Seeders;
|
||||||
|
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Modules\Lpj\Models\Permohonan;
|
||||||
|
use Modules\Lpj\Models\Debiture;
|
||||||
|
use Modules\Basicdata\Models\Branch;
|
||||||
|
use Modules\Usermanagement\Models\User;
|
||||||
|
|
||||||
|
class MigrationPermohonanSeeder extends Seeder
|
||||||
|
{
|
||||||
|
protected $errorLogFile = __DIR__ . '/csv/permohonan/permohonan.2024.2025_error.csv';
|
||||||
|
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
// Bersihkan file error sebelum mulai
|
||||||
|
$this->initializeErrorLog();
|
||||||
|
|
||||||
|
$filePath = realpath(__DIR__ . '/csv/permohonan/permohonan.2024.2025.csv');
|
||||||
|
|
||||||
|
if (!$filePath) {
|
||||||
|
Log::error('File CSV tidak ditemukan: ' . __DIR__ . '/csv/permohonan/permohonan.2024.2025.csv');
|
||||||
|
$this->command->error('File CSV tidak ditemukan.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($handle = fopen($filePath, 'r')) === false) {
|
||||||
|
Log::error('Gagal membuka file CSV: ' . $filePath);
|
||||||
|
$this->command->error('Gagal membuka file CSV.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$header = fgetcsv($handle, 0, ',');
|
||||||
|
$rows = [];
|
||||||
|
$batchSize = 1000;
|
||||||
|
$branchCache = [];
|
||||||
|
$debitureCache = [];
|
||||||
|
$totalData = 0;
|
||||||
|
$currentRow = 0;
|
||||||
|
$batchCount = 0;
|
||||||
|
|
||||||
|
// Hitung total data
|
||||||
|
while (fgetcsv($handle, 0, ',') !== false) {
|
||||||
|
$totalData++;
|
||||||
|
}
|
||||||
|
|
||||||
|
rewind($handle);
|
||||||
|
fgetcsv($handle, 0, ','); // Lewati header
|
||||||
|
|
||||||
|
while (($data = fgetcsv($handle, 0, ',')) !== false) {
|
||||||
|
if (count($data) != count($header)) {
|
||||||
|
$nomorJaminan = $data[array_search('mig_mst_jaminan_nomor_jaminan', $header)] ?? '-';
|
||||||
|
$this->logError($nomorJaminan, count($data).' Jumlah kolom tidak sesuai dengan header. Header: '.count($header));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$rows[] = array_combine($header, $data);
|
||||||
|
$currentRow++;
|
||||||
|
// print_r($rows);
|
||||||
|
if (count($rows) >= $batchSize) {
|
||||||
|
$batchCount++;
|
||||||
|
$this->command->info("Memproses batch ke-{$batchCount} ({$currentRow}/{$totalData})");
|
||||||
|
$this->processBatch($rows, $branchCache, $debitureCache, $totalData, $batchCount);
|
||||||
|
$rows = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// print_r($rows);
|
||||||
|
|
||||||
|
if (!empty($rows)) {
|
||||||
|
$batchCount++;
|
||||||
|
$this->command->info("Memproses batch ke-{$batchCount} ({$currentRow}/{$totalData})");
|
||||||
|
$this->processBatch($rows, $branchCache, $debitureCache, $totalData, $batchCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose($handle);
|
||||||
|
|
||||||
|
$this->command->info("Migrasi selesai. Total data diproses: $totalData.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private function processBatch(array $rows, array &$branchCache, array &$debitureCache, int $totalData, int $batchCount)
|
||||||
|
{
|
||||||
|
$userData = [];
|
||||||
|
foreach ($rows as $index => $row) {
|
||||||
|
try {
|
||||||
|
$nomorJaminan = $row['mig_mst_jaminan_nomor_jaminan'] ?? '-';
|
||||||
|
|
||||||
|
// Cek apakah sudah diproses
|
||||||
|
$existingRecord = Permohonan::where('nomor_registrasi', $row['mig_mst_jaminan_nomor_jaminan'])->first();
|
||||||
|
if ($existingRecord && $existingRecord->processed_at) {
|
||||||
|
$this->command->info("Data sudah diproses: $nomorJaminan");
|
||||||
|
//continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ambil branch_id
|
||||||
|
$branchId = $this->getBranchId($row['mig_mst_jaminan_kd_cabang'] ?? null, $branchCache);
|
||||||
|
// if (!$branchId) {
|
||||||
|
// $this->logError($branchId, 'Cabang tidak ditemukan');
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Ambil Debitur ID
|
||||||
|
$debitureId = $this->getDebiturId($row['mig_mst_jaminan_kd_debitur_seq'], $debitureCache);
|
||||||
|
if (!$debitureId) {
|
||||||
|
$this->logError($nomorJaminan, 'Debitur tidak ditemukan');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ambil User IDs
|
||||||
|
$userId = $this->getUserId($row['mig_mst_jaminan_nama_ao'], $branchCache, true);
|
||||||
|
|
||||||
|
// jika external matikan
|
||||||
|
$approved1Id = $this->getUserId($row['mig_mst_lpj_user_approved_1'], $branchCache, false);
|
||||||
|
$approved2Id = $this->getUserId($row['mig_mst_lpj_user_approved_2'], $branchCache, false);
|
||||||
|
$periksaId = $this->getUserId($row['mig_mst_lpj_user_periksa'], $branchCache, false);
|
||||||
|
|
||||||
|
// // Ambil user IDs berdasarkan NIK
|
||||||
|
$userIdUpdate = $this->getUserIdData($row['mig_mst_jaminan_user_create'] ?? null, $userData)['id'];
|
||||||
|
$userIdOtorisasi = $this->getUserIdData($row['mig_mst_jaminan_user_oto'] ?? null, $userData)['id'];
|
||||||
|
|
||||||
|
// jika external matikan
|
||||||
|
// if (!$userIdUpdate || !$userIdOtorisasi) {
|
||||||
|
// $this->logError($userIdUpdate, 'Salah satu user tidak ditemukan');
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Mapping field user
|
||||||
|
$mapUser = [
|
||||||
|
'created_by' => $userIdUpdate,
|
||||||
|
'updated_by' => $userIdUpdate,
|
||||||
|
'authorized_by' => $userIdOtorisasi,
|
||||||
|
];
|
||||||
|
|
||||||
|
// jika external matikan
|
||||||
|
// if (!$userId || !$approved1Id || !$approved2Id) {
|
||||||
|
// $this->logError($userId, 'Salah satu user tidak ditemukan');
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Mapping data
|
||||||
|
$jenisFasilitas = $this->checkJenisFasilitas($row['mig_mst_jaminan_kd_jenis_fas_seq']);
|
||||||
|
$tujuanPenilaian = $this->checkTujuanPenilaian($row['mig_mst_jaminan_kd_tujuan_seq']);
|
||||||
|
$regionId = $this->checkRegion($row['mig_mst_kode_kelompok_region']);
|
||||||
|
|
||||||
|
|
||||||
|
$nomor_lpj = isset($row['mig_mst_lpj_nomor_lpj']) ? $row['mig_mst_lpj_nomor_lpj'] : '';
|
||||||
|
$nomor_lpj = is_numeric($nomor_lpj) ? (int)$nomor_lpj : 0;
|
||||||
|
|
||||||
|
$jenisPenilaian = $row['mig_internal_or_external'] == 1 ? 2 : 1;
|
||||||
|
|
||||||
|
// Simpan data
|
||||||
|
$permohonan = Permohonan::updateOrCreate([
|
||||||
|
'nomor_registrasi' => $nomorJaminan,
|
||||||
|
],[
|
||||||
|
'nomor_registrasi' => $nomorJaminan,
|
||||||
|
'tanggal_permohonan' => $this->parseDate($row['tanggal_permohonan']),
|
||||||
|
'user_id' => $userId['id'],
|
||||||
|
'branch_id' => $branchId,
|
||||||
|
'tujuan_penilaian_id' => $tujuanPenilaian,
|
||||||
|
'debiture_id' => $debitureId,
|
||||||
|
'jenis_fasilitas_kredit_id' => $jenisFasilitas,
|
||||||
|
'nilai_plafond_id' => 2,
|
||||||
|
'status' => 'done',
|
||||||
|
// jika external matikan
|
||||||
|
'approval_eo' => $approved1Id['id'] ?? 0,
|
||||||
|
'approval_eo_at' => $this->parseTimestamp($row['mig_mst_lpj_tgl_approved_1']),
|
||||||
|
'approval_dd' => $approved2Id['id'] ?? 0,
|
||||||
|
'approval_dd_at' => $this->parseTimestamp($row['mig_mst_lpj_tgl_approved_2']),
|
||||||
|
'approval_so' => $periksaId['id'] ?? 0,
|
||||||
|
'approval_so_at' => $this->parseTimestamp($row['mig_mst_lpj_tgl_periksa']),
|
||||||
|
// end external matikan
|
||||||
|
'keterangan' => $row['mig_mst_jaminan_catatan'] ?? null,
|
||||||
|
'status_bayar' => 'sudah_bayar',
|
||||||
|
'created_at' => $this->parseTimestamp($row['mig_mst_jaminan_tgl_create']),
|
||||||
|
'updated_at' => $this->parseTimestamp($row['mig_mst_jaminan_tgl_update']),
|
||||||
|
'mig_kd_debitur_seq' => $row['mig_mst_jaminan_kd_debitur_seq'],
|
||||||
|
'nomor_lpj' => $nomor_lpj,
|
||||||
|
'region_id' => $regionId,
|
||||||
|
'jenis_penilaian_id' => $jenisPenilaian,
|
||||||
|
'authorized_by' => $mapUser['authorized_by'],
|
||||||
|
'created_by' => $mapUser['created_by'],
|
||||||
|
'updated_by' => $mapUser['updated_by'],
|
||||||
|
'mig_nama_ao' => $row['mig_mst_jaminan_nama_ao'],
|
||||||
|
'mig_permohonan' => json_encode($row),
|
||||||
|
'is_mig' => 1
|
||||||
|
]);
|
||||||
|
|
||||||
|
if($permohonan && $nomorJaminan=='253122'){
|
||||||
|
Log::info($permohonan);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->command->info("Proses data permohonan $nomorJaminan (" . ($index + 1) . '/' . count($rows) . " pada batch ke-$batchCount)");
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$nomorJaminan = $row['mig_mst_jaminan_nomor_jaminan'] ?? '-';
|
||||||
|
$this->logError($nomorJaminan, "Error eksepsi: " . $e->getMessage());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getUserIdData(?string $code, array &$cache): array
|
||||||
|
{
|
||||||
|
if (!$code) {
|
||||||
|
return ['id' => null, 'branch_id' => null];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($cache[$code])) {
|
||||||
|
return $cache[$code];
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = User::where('nik', $code)->first();
|
||||||
|
|
||||||
|
if ($user) {
|
||||||
|
$cache[$code] = ['id' => $user->id, 'branch_id' => $user->branch_id];
|
||||||
|
return $cache[$code];
|
||||||
|
}
|
||||||
|
|
||||||
|
return ['id' => null, 'branch_id' => null];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getUserId(string $value, array &$cache, bool $includeBranch = false): ?array
|
||||||
|
{
|
||||||
|
if (isset($cache[$value])) {
|
||||||
|
return $cache[$value];
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = null;
|
||||||
|
|
||||||
|
if ($includeBranch) {
|
||||||
|
$user = User::whereRaw('LOWER(name) = ?', [strtolower($value)])->first();
|
||||||
|
} else {
|
||||||
|
$user = User::where('nik', $value)->first();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($user) {
|
||||||
|
$result = ['id' => $user->id];
|
||||||
|
if ($includeBranch) {
|
||||||
|
$result['branch_id'] = $user->branch_id;
|
||||||
|
}
|
||||||
|
$cache[$value] = $result;
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ['id' => null, 'branch_id' => null];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getDebiturId(string $code, array &$cache): ?int
|
||||||
|
{
|
||||||
|
if (isset($cache[$code])) {
|
||||||
|
return $cache[$code];
|
||||||
|
}
|
||||||
|
|
||||||
|
$debitur = Debiture::where('mig_kd_debitur_seq', $code)->first();
|
||||||
|
|
||||||
|
if ($debitur) {
|
||||||
|
$cache[$code] = $debitur->id;
|
||||||
|
return $debitur->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
private function getBranchId(?string $code, array &$cache): ?int
|
||||||
|
{
|
||||||
|
if (!$code) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($cache[$code])) {
|
||||||
|
return $cache[$code];
|
||||||
|
}
|
||||||
|
|
||||||
|
$branch = Branch::where('code', $code)->first();
|
||||||
|
|
||||||
|
if ($branch) {
|
||||||
|
$cache[$code] = $branch->id;
|
||||||
|
return $branch->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
private function checkJenisFasilitas($code): int
|
||||||
|
{
|
||||||
|
// Extract the integer part before the decimal
|
||||||
|
$intCode = (int) $code;
|
||||||
|
|
||||||
|
$mapping = [
|
||||||
|
161337594516 => 1,
|
||||||
|
161337598118 => 14,
|
||||||
|
155739382483 => 7,
|
||||||
|
2 => 9,
|
||||||
|
153568936592 => 10,
|
||||||
|
155737674431 => 11,
|
||||||
|
161337561199 => 12,
|
||||||
|
1 => 13,
|
||||||
|
];
|
||||||
|
|
||||||
|
return $mapping[$intCode] ?? 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function checkTujuanPenilaian($code): int
|
||||||
|
{
|
||||||
|
$code = (int) $code;
|
||||||
|
$mapping = [
|
||||||
|
1 => 1,
|
||||||
|
2 => 2,
|
||||||
|
3 => 9,
|
||||||
|
4 => 10,
|
||||||
|
5 => 8,
|
||||||
|
6 => 3,
|
||||||
|
];
|
||||||
|
|
||||||
|
return $mapping[$code] ?? 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function checkRegion($code): int
|
||||||
|
{
|
||||||
|
$mapping = [
|
||||||
|
'01' => 1,
|
||||||
|
'02' => 2,
|
||||||
|
'04' => 3,
|
||||||
|
'07' => 4,
|
||||||
|
'06' => 5,
|
||||||
|
];
|
||||||
|
|
||||||
|
return $mapping[$code] ?? 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function parseDate(?string $date): ?string
|
||||||
|
{
|
||||||
|
if (!$date) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Coba format d/m/Y terlebih dahulu (contoh: 30/1/2025)
|
||||||
|
return \Carbon\Carbon::createFromFormat('d/m/Y', $date)->toDateString();
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
try {
|
||||||
|
// Fallback ke format Y-m-d jika gagal
|
||||||
|
return \Carbon\Carbon::createFromFormat('Y-m-d', $date)->toDateString();
|
||||||
|
} catch (\Exception $e2) {
|
||||||
|
// If both formats fail, try to parse with Carbon::parse as last resort
|
||||||
|
try {
|
||||||
|
return \Carbon\Carbon::parse($date)->toDateString();
|
||||||
|
} catch (\Exception $e3) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function parseTimestamp(?string $timestamp): ?string
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
if (!$timestamp) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cek format d/m/Y H:i:s (contoh: 29/9/2025 17:20:36)
|
||||||
|
if (preg_match('/^\d{1,2}\/\d{1,2}\/\d{4} \d{1,2}:\d{2}:\d{2}$/', $timestamp)) {
|
||||||
|
return \Carbon\Carbon::createFromFormat('d/m/Y H:i:s', $timestamp)->toDateTimeString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cek jika format hanya tanggal (Y-m-d)
|
||||||
|
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $timestamp)) {
|
||||||
|
return \Carbon\Carbon::createFromFormat('Y-m-d', $timestamp)
|
||||||
|
->startOfDay()
|
||||||
|
->toDateTimeString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format lengkap (Y-m-d H:i:s)
|
||||||
|
if (preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/', $timestamp)) {
|
||||||
|
return \Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $timestamp)->toDateTimeString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback: coba parsing dengan createFromFormat tambahan atau gunakan parse
|
||||||
|
return \Carbon\Carbon::parse($timestamp)->toDateTimeString();
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::error('Gagal memparsing timestamp: ' . $timestamp . '. Pesan: ' . $e->getMessage());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private function initializeErrorLog()
|
||||||
|
{
|
||||||
|
$file = $this->errorLogFile;
|
||||||
|
|
||||||
|
// Hapus file lama jika ada
|
||||||
|
if (file_exists($file)) {
|
||||||
|
unlink($file);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Buat file baru dengan header
|
||||||
|
$handle = fopen($file, 'w');
|
||||||
|
fputcsv($handle, ['mig_mst_jaminan_nomor_jaminan', 'Error']);
|
||||||
|
fclose($handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function logError($nomorJaminan, string $message)
|
||||||
|
{
|
||||||
|
Log::error("Error migrasi permohonan [$nomorJaminan]: $message");
|
||||||
|
|
||||||
|
// Tulis ke file error
|
||||||
|
$handle = fopen($this->errorLogFile, 'a');
|
||||||
|
fputcsv($handle, [$nomorJaminan, $message]);
|
||||||
|
fclose($handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@ namespace Modules\Lpj\Database\Seeders;
|
|||||||
|
|
||||||
use Illuminate\Database\Seeder;
|
use Illuminate\Database\Seeder;
|
||||||
use Modules\Lpj\Models\Teams;
|
use Modules\Lpj\Models\Teams;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
class TeamsSeeder extends Seeder
|
class TeamsSeeder extends Seeder
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
@@ -12,14 +12,6 @@ class TeamsSeeder extends Seeder
|
|||||||
*/
|
*/
|
||||||
public function run(): void
|
public function run(): void
|
||||||
{
|
{
|
||||||
Teams::insert([
|
DB::unprepared(file_get_contents(__DIR__ . '/sql/teams.sql'));
|
||||||
[
|
|
||||||
'regions_id' => 1,
|
|
||||||
'code' => 'T01',
|
|
||||||
'name' => 'Team 1',
|
|
||||||
'created_at' => now(),
|
|
||||||
'updated_at' => now()
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,36 @@ class TujuanPenilaianKJPPSeeder extends Seeder
|
|||||||
'status' => 1,
|
'status' => 1,
|
||||||
'created_at' => now(),
|
'created_at' => now(),
|
||||||
'updated_at' => now()
|
'updated_at' => now()
|
||||||
]
|
],
|
||||||
|
[
|
||||||
|
'code' => 'TPK05',
|
||||||
|
'name' => 'Penilaian Ulang Jaminan / Review Tahunan',
|
||||||
|
'status' => 1,
|
||||||
|
'created_at' => now(),
|
||||||
|
'updated_at' => now()
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'code' => 'TPK06',
|
||||||
|
'name' => 'Lelang',
|
||||||
|
'status' => 1,
|
||||||
|
'created_at' => now(),
|
||||||
|
'updated_at' => now()
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'code' => 'TPK07',
|
||||||
|
'name' => 'Permohonan Baru',
|
||||||
|
'status' => 1,
|
||||||
|
'created_at' => now(),
|
||||||
|
'updated_at' => now()
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'code' => 'TPK08',
|
||||||
|
'name' => 'Penambahan Fasilitas / Jaminan',
|
||||||
|
'status' => 1,
|
||||||
|
'created_at' => now(),
|
||||||
|
'updated_at' => now()
|
||||||
|
],
|
||||||
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,7 +60,38 @@ class TujuanPenilaianSeeder extends Seeder
|
|||||||
'created_at' => now(),
|
'created_at' => now(),
|
||||||
'updated_at' => now(),
|
'updated_at' => now(),
|
||||||
'deleted_at' => null,
|
'deleted_at' => null,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'code' => 'TP0007',
|
||||||
|
'name' => 'Jual Beli',
|
||||||
|
'status' => 1,
|
||||||
|
'created_at' => now(),
|
||||||
|
'updated_at' => now(),
|
||||||
|
'deleted_at' => null,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'code' => 'TP0008',
|
||||||
|
'name' => 'KPR eks BPPN',
|
||||||
|
'status' => 1,
|
||||||
|
'created_at' => now(),
|
||||||
|
'updated_at' => now(),
|
||||||
|
'deleted_at' => null,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'code' => 'TP0009',
|
||||||
|
'name' => 'Penambahan Fasilitas / Jaminan',
|
||||||
|
'status' => 1,
|
||||||
|
'created_at' => now(),
|
||||||
|
'updated_at' => now()
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'code' => 'TP00010',
|
||||||
|
'name' => 'Penukaran Jaminan',
|
||||||
|
'status' => 1,
|
||||||
|
'created_at' => now(),
|
||||||
|
'updated_at' => now()
|
||||||
]
|
]
|
||||||
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
10
database/seeders/sql/fasilitas_objek.sql
Normal file
10
database/seeders/sql/fasilitas_objek.sql
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
INSERT INTO `fasilitas_objek` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
|
||||||
|
(1, 'FU001', 'Tempat Ibadah', 1, NULL, '2024-11-28 18:57:35', '2024-11-28 18:57:35', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(2, 'FU002', 'Rumah Sakit', 1, NULL, '2024-11-28 18:57:50', '2024-11-28 18:57:50', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(3, 'FU003', 'Sekolah', 1, NULL, '2024-11-28 18:58:05', '2024-11-28 18:58:05', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(4, 'FU004', 'Kantor Pemerintahan', 1, NULL, '2024-11-28 18:58:27', '2024-11-28 18:58:27', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(5, 'FU005', 'Stasiun Kereta', 1, NULL, '2024-11-28 18:58:49', '2024-11-28 18:58:49', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(6, 'FU006', 'Terminal Bus', 1, NULL, '2024-11-28 18:59:09', '2024-11-28 18:59:09', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(7, 'FU007', 'Bandara', 1, NULL, '2024-11-28 18:59:26', '2024-11-28 18:59:26', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(8, 'FU009', 'Pos Polisi', 1, NULL, '2024-11-28 18:59:50', '2024-11-28 18:59:50', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(9, 'FU010', 'Lainnya', 1, NULL, '2024-11-28 19:00:07', '2024-11-28 19:00:07', NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
4
database/seeders/sql/gol_mas_sekitar.sql
Normal file
4
database/seeders/sql/gol_mas_sekitar.sql
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
INSERT INTO `gol_mas_sekitar` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
|
||||||
|
(1, 'GMS001', 'Menengah', 1, NULL, '2024-11-05 00:36:23', '2024-11-05 00:36:23', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(2, 'GMS002', 'Menengah Bawah', 1, NULL, '2024-11-05 00:36:35', '2024-11-05 00:36:35', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(3, 'GMS003', 'Menengah Atas', 1, NULL, '2024-11-05 00:36:48', '2024-11-05 00:36:48', NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
6
database/seeders/sql/jenis_bangunan.sql
Normal file
6
database/seeders/sql/jenis_bangunan.sql
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
INSERT INTO `jenis_bangunan` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
|
||||||
|
(1, 'JB001', 'Rumah', 1, NULL, '2024-11-04 21:43:16', '2024-11-04 21:43:16', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(2, 'JB002', 'Ruko', 1, NULL, '2024-11-04 21:43:28', '2024-11-04 21:43:28', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(3, 'JB003', 'Gudang', 1, NULL, '2024-11-04 21:43:41', '2024-11-04 21:43:41', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(4, 'JB004', 'Pabrik', 1, NULL, '2024-11-04 21:43:53', '2024-11-04 21:43:53', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(5, 'JB005', 'Lainnya', 1, NULL, '2024-11-04 21:44:08', '2024-11-04 21:44:08', NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
@@ -1,29 +1,44 @@
|
|||||||
INSERT INTO jenis_jaminan VALUES
|
|
||||||
(1, 'JJ001', 'Tanah', 'tanah', '[\"tanah\", \"lingkungan\", \"fakta\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ004\",\"JLJ005\",\"JLJ006\",\"JLJ022\"]', 1, '2024-12-06 09:16:02', '2024-12-06 09:16:02', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
|
||||||
(2, 'JJ002', 'Unit Apartemen', 'unit-apartemen', '[\"apartemen-kantor\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ004\",\"JLJ006\",\"JLJ007\",\"JLJ022\",\"JLJ024\"]', 1, '2024-12-06 09:16:02', '2024-12-06 09:16:02', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
INSERT INTO `jenis_jaminan` (`id`, `code`, `name`, `slug`, `form_kategori`, `jenis_legalitas_jaminan_id`, `status`, `created_at`, `updated_at`, `authorized_at`, `authorized_status`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`, `authorized_by`) VALUES
|
||||||
(3, 'JJ003', 'Kawasan Industrial / Komersil / Residensial - Perumahan', 'kawasan-industrial-komersil-residensial-perumahan', '[\"tanah\", \"bangunan\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ004\",\"JLJ006\",\"JLJ007\",\"JLJ008\",\"JLJ022\"]', 1, '2024-12-06 09:16:02', '2024-12-06 09:16:02', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
(1, 'JJ001', 'Tanah kosong', 'tanah-kosong', '[\"tanah\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ004\",\"JLJ005\",\"JLJ006\",\"JLJ022\"]', NULL, NULL, '2024-12-20 00:15:07', NULL, 't', NULL, NULL, 1, NULL, NULL),
|
||||||
(4, 'JJ004', 'Mall', 'mall', 'null', '[\"JLJ001\",\"JLJ003\",\"JLJ004\",\"JLJ006\",\"JLJ007\",\"JLJ009\",\"JLJ012\",\"JLJ013\",\"JLJ014\",\"JLJ015\",\"JLJ021\",\"JLJ022\"]', 1, '2024-12-06 09:16:02', '2024-12-06 09:16:02', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
(2, 'JJ002', 'Unit Apartemen', 'unit-apartemen', '[\"apartemen-kantor\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ004\",\"JLJ006\",\"JLJ007\",\"JLJ022\",\"JLJ024\"]', NULL, NULL, '2024-12-03 03:38:02', NULL, 'r', NULL, NULL, 1, NULL, NULL),
|
||||||
(5, 'JJ005', 'Pabrik', 'pabrik', 'null', '[\"JLJ001\",\"JLJ003\",\"JLJ004\",\"JLJ006\",\"JLJ007\",\"JLJ009\",\"JLJ011\"]', 1, '2024-12-06 09:16:02', '2024-12-06 09:16:02', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
(3, 'JJ003', 'Kawasan Industrial / Komersil / Residensial - Perumahan', 'kawasan-industrial-komersil-residensial-perumahan', '[\"tanah\", \"bangunan\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ004\",\"JLJ005\",\"JLJ007\",\"JLJ008\",\"JLJ009\",\"JLJ022\",\"JLJ024\",\"JLJ039\",\"JLJ040\"]', NULL, NULL, '2025-03-10 19:34:58', NULL, 'k', NULL, NULL, 1, NULL, NULL),
|
||||||
(6, 'JJ006', 'Emas dan Perak', 'emas-dan-perak', 'null', '[\"JLJ001\",\"JLJ007\",\"JLJ014\",\"JLJ022\"]', 1, '2024-12-06 09:16:02', '2024-12-06 09:16:02', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
(4, 'JJ004', 'Unit Kios', 'unit-kios', '[\"tanah\", \"bangunan\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ004\",\"JLJ006\",\"JLJ007\",\"JLJ009\",\"JLJ010\",\"JLJ022\"]', NULL, NULL, '2024-12-03 01:57:55', NULL, 'g', '2024-12-03 01:57:55', NULL, 1, 1, NULL),
|
||||||
(7, 'JJ007', 'Alat Berat', 'alat-berat', 'null', '[\"JLJ004\"]', 1, '2024-12-06 09:16:02', '2024-12-06 09:16:02', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
(6, 'JJ005', 'Mall', 'mall', '[\"tanah\", \"bangunan\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ004\",\"JLJ006\",\"JLJ007\",\"JLJ009\",\"JLJ012\",\"JLJ013\",\"JLJ014\",\"JLJ015\",\"JLJ021\",\"JLJ022\"]', 1, '2024-09-11 00:51:36', '2024-12-16 19:48:40', NULL, NULL, NULL, 1, 1, NULL, NULL),
|
||||||
(8, 'JJ008', 'Rumah Tinggal', 'rumah-tinggal', '[\"tanah\", \"bangunan\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ004\",\"JLJ006\",\"JLJ007\",\"JLJ009\",\"JLJ024\"]', 1, '2024-12-06 09:16:02', '2024-12-06 09:16:02', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
(7, 'JJ006', 'Pabrik', 'pabrik', '[\"tanah\", \"bangunan\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ004\",\"JLJ006\",\"JLJ007\",\"JLJ009\",\"JLJ011\"]', 1, '2024-10-23 22:27:56', '2024-12-16 19:48:54', NULL, NULL, NULL, 1, 1, NULL, NULL),
|
||||||
(9, 'JJ009', 'Full Properti', 'full-properti', '[\"tanah\", \"bangunan\", \"informasi\"]', '[\"JLJ001\",\"JLJ006\",\"JLJ007\",\"JLJ009\"]', 1, '2024-12-06 09:16:02', '2024-12-10 22:07:46', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
(8, 'JJ007', 'Emas dan Perak', 'emas-dan-perak', NULL, '[\"JLJ008\",\"JLJ014\",\"JLJ022\"]', 1, '2024-12-02 02:40:42', '2024-12-02 02:40:58', NULL, NULL, '2024-12-02 02:40:58', 4, 4, 4, NULL),
|
||||||
(10, 'JJ010', 'Gudang', 'gudang', '[\"tanah\", \"bangunan\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ007\",\"JLJ009\",\"JLJ024\"]', 1, '2024-12-06 09:16:02', '2024-12-06 09:16:02', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
(9, 'JJ008', 'Emas dan Perak', 'emas-dan-perak', NULL, '[\"JLJ008\",\"JLJ014\",\"JLJ022\"]', 1, '2024-12-02 02:41:39', '2024-12-02 02:47:44', NULL, NULL, '2024-12-02 02:47:44', 4, 4, 4, NULL),
|
||||||
(11, 'JJ011', 'Unit Kios', 'unit-kios', '[\"apartemen-kantor\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ007\",\"JLJ009\",\"JLJ024\"]', 1, '2024-12-06 09:16:02', '2024-12-06 09:16:02', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
(10, 'JJ009', 'Emas dan Perak', 'emas-dan-perak', NULL, '[\"JLJ001\",\"JLJ007\",\"JLJ014\",\"JLJ022\"]', 1, '2024-12-02 02:49:32', '2024-12-02 02:49:32', NULL, NULL, NULL, 4, 4, NULL, NULL),
|
||||||
(12, 'JJ012', 'Gedung Mall', 'gedung-mall', '[\"tanah\", \"bangunan\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ007\",\"JLJ009\"]', 1, '2024-12-06 09:16:02', '2024-12-06 09:16:02', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
(11, 'JJ010', 'Alat Berat', 'alat-berat', 'null', '[\"JLJ004\",\"JLJ011\"]', 1, '2024-12-03 00:59:14', '2024-12-30 23:36:25', NULL, NULL, '2024-12-30 23:36:25', 1, 1, 1, NULL),
|
||||||
(13, 'JJ013', 'Tanah Bangunan', 'tanah-bangunan', '[\"tanah\", \"bangunan\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ005\",\"JLJ007\",\"JLJ009\",\"JLJ022\",\"JLJ024\"]', 1, '2024-12-06 09:16:02', '2024-12-06 09:16:02', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
(12, 'JJ011', 'Rumah Tinggal', 'rumah-tinggal', '[\"tanah\", \"bangunan\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ004\",\"JLJ006\",\"JLJ007\",\"JLJ009\",\"JLJ022\",\"JLJ024\"]', 1, '2024-12-03 01:12:23', '2024-12-19 00:11:01', NULL, NULL, NULL, 1, 1, NULL, NULL),
|
||||||
(14, 'JJ014', 'Apartemen', 'apartemen', '[\"apartemen-kantor\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ022\",\"JLJ024\"]', 1, '2024-12-06 09:16:02', '2024-12-06 09:16:02', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
(13, 'JJ012', 'Pabrik', 'pabrik', '[\"tanah\", \"bangunan\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ006\",\"JLJ007\",\"JLJ009\"]', 1, '2024-12-03 01:55:14', '2024-12-03 01:55:14', NULL, NULL, NULL, 1, 1, NULL, NULL),
|
||||||
(15, 'JJ015', 'Ruko', 'ruko', '[\"tanah\", \"bangunan\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ007\",\"JLJ022\"]', 1, '2024-12-06 09:16:02', '2024-12-06 09:16:02', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
(14, 'JJ013', 'Gudang', 'gudang', '[\"tanah\", \"bangunan\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ007\",\"JLJ009\",\"JLJ022\",\"JLJ024\"]', 1, '2024-12-03 01:56:09', '2025-01-22 02:13:30', NULL, NULL, NULL, 1, 1, NULL, NULL),
|
||||||
(16, 'JJ016', 'Mesin Tekstil', 'mesin-tekstil', '[\"mesin\"]', '[\"JLJ011\",\"JLJ022\"]', 1, '2024-12-06 09:16:02', '2024-12-06 09:16:02', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
(15, 'JJ014', 'Unit Kios', 'unit-kios', '[\"apartemen-kantor\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ007\",\"JLJ009\",\"JLJ024\"]', 1, '2024-12-03 01:58:32', '2024-12-03 04:20:22', NULL, NULL, NULL, 1, 1, NULL, NULL),
|
||||||
(17, 'JJ017', 'Mesin', 'mesin', '[\"mesin\"]', '[\"JLJ011\",\"JLJ022\"]', 1, '2024-12-06 09:16:02', '2024-12-06 09:16:02', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
(16, 'JJ015', 'Gedung Mall', 'gedung-mall', '[\"tanah\", \"bangunan\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ007\",\"JLJ009\"]', 1, '2024-12-03 01:59:41', '2024-12-03 01:59:41', NULL, NULL, NULL, 1, 1, NULL, NULL),
|
||||||
(18, 'JJ018', 'Mesin Tenun Tekstil', 'mesin-tenun-tekstil', '[\"mesin\"]', '[\"JLJ011\",\"JLJ022\"]', 1, '2024-12-06 09:16:02', '2024-12-06 09:16:02', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
(17, 'JJ016', 'Tanah Bangunan', 'tanah-bangunan', '[\"tanah\", \"bangunan\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ005\",\"JLJ007\",\"JLJ009\",\"JLJ022\",\"JLJ024\",\"JLJ039\",\"JLJ040\"]', 1, '2024-12-03 02:01:20', '2025-03-10 19:35:15', NULL, NULL, NULL, 1, 1, NULL, NULL),
|
||||||
(19, 'JJ019', 'Penilaian Bisnis', 'penilaian-bisnis', '[\"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ007\",\"JLJ014\"]', 1, '2024-12-10 02:34:01', '2024-12-10 02:34:01', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
(18, 'JJ017', 'Apartemen', 'apartemen', '[\"apartemen-kantor\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ022\",\"JLJ024\"]', 1, '2024-12-03 04:24:14', '2024-12-03 22:35:05', NULL, NULL, NULL, 1, 1, NULL, NULL),
|
||||||
(20, 'JJ020', 'Penilaian Tanah dan Bangunan', 'penilaian-tanah-dan-bangunan', '[\"tanah\", \"bangunan\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ007\"]', 1, '2024-12-10 02:34:54', '2024-12-10 02:34:54', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
(19, 'JJ018', 'Ruko/Rukan', 'rukorukan', '[\"tanah\", \"bangunan\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ007\",\"JLJ022\"]', 1, '2024-12-03 19:33:17', '2024-12-16 01:54:36', NULL, NULL, NULL, 1, 1, NULL, NULL),
|
||||||
(21, 'JJ021', 'Penilaian Mesin', 'penilaian-mesin', '[\"mesin\"]', '[\"JLJ011\",\"JLJ022\"]', 1, '2024-12-10 03:00:13', '2024-12-10 03:00:13', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
(20, 'JJ019', 'Unit Kantor', 'unit-kantor', '[\"apartemen-kantor\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ005\"]', 1, '2024-12-16 01:56:38', '2024-12-16 19:51:00', NULL, NULL, NULL, 1, 1, NULL, NULL),
|
||||||
(22, 'JJ022', 'Penilian Kapal dan Pesawat', 'penilian-kapal-dan-pesawat', '[\"kapal\", \"pesawat\"]', '[\"JLJ011\",\"JLJ022\"]', 1, '2024-12-10 03:01:00', '2024-12-10 03:01:00', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
(21, 'JJ020', 'Pesawat', 'pesawat', '[\"pesawat\"]', '[\"JLJ001\",\"JLJ004\"]', 1, '2024-12-16 01:58:21', '2024-12-16 01:58:21', NULL, NULL, NULL, 1, 1, NULL, NULL),
|
||||||
(23, 'JJ023', 'Tanah Kosong', 'tanah-kosong', '[\"tanah\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ007\",\"JLJ022\"]', 1, '2024-12-10 03:18:24', '2024-12-10 03:18:24', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
(22, 'JJ021', 'SPBU', 'spbu', '[\"tanah\", \"bangunan\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ005\"]', 1, '2024-12-16 01:59:22', '2024-12-16 01:59:22', NULL, NULL, NULL, 1, 1, NULL, NULL),
|
||||||
(24, 'JJ024', 'Tanah Kosong untuk dikembangkan', 'tanah-kosong-untuk-dikembangkan', '[\"tanah\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ007\",\"JLJ022\"]', 1, '2024-12-10 03:19:03', '2024-12-10 03:19:03', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
(23, 'JJ022', 'Alat Berat', 'alat-berat', '[\"alat-berat\"]', '[\"JLJ004\",\"JLJ006\",\"JLJ011\"]', 1, '2024-12-30 23:37:10', '2024-12-30 23:45:54', NULL, NULL, NULL, 1, 1, NULL, NULL),
|
||||||
(25, 'JJ025', 'Bisnis', 'bisnis', '[\"informasi\", \"lingkungan\"]', '[\"JLJ001\",\"JLJ007\"]', 1, '2024-12-10 22:09:26', '2024-12-10 22:09:26', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
(24, 'JJ023', 'Lainnya', 'lainnya', '[\"tanah\", \"bangunan\"]', '[\"JLJ001\",\"JLJ007\"]', 1, '2025-03-05 21:30:11', '2025-03-05 21:30:11', NULL, NULL, NULL, 1, 1, NULL, NULL),
|
||||||
(26, 'JJ026', 'Properti Sederhana', 'properti-sederhana', '[\"lingkungan\", \"tanah\"]', '[\"JLJ001\",\"JLJ007\"]', 1, '2024-12-10 22:10:01', '2024-12-10 22:10:01', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
(25, 'JJ024', 'Hotel', 'hotel', '[\"bangunan\", \"tanah\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ006\",\"JLJ007\",\"JLJ008\",\"JLJ009\",\"JLJ011\",\"JLJ013\",\"JLJ014\",\"JLJ015\",\"JLJ016\",\"JLJ017\",\"JLJ020\",\"JLJ021\",\"JLJ022\",\"JLJ024\",\"JLJ028\",\"JLJ036\"]', 1, '2025-03-09 02:01:45', '2025-03-09 02:01:45', NULL, NULL, NULL, 1, 1, NULL, NULL),
|
||||||
(27, 'JJ027', 'Bangunan', 'bangunan', '[\"bangunan\"]', '[\"JLJ003\",\"JLJ007\"]', 1, '2024-12-12 08:13:41', '2024-12-12 08:13:41', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
(26, 'JJ025', 'Kendaraan', 'kendaraan', '[\"kendaraan\"]', 'null', 1, '2025-04-18 05:42:13', '2025-04-18 05:42:13', NULL, NULL, NULL, 1, 1, NULL, NULL),
|
||||||
(28, 'JJ028', 'Kendaraan Bermotor', 'kendaraan-bermotor', '[\"kendaraan\"]', '[\"JLJ022\"]', 1, '2024-12-12 08:15:51', '2024-12-12 08:15:51', NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
(27, 'JJ026', 'Mesin', 'mesin', 'null', 'null', 1, '2025-04-18 05:45:21', '2025-04-18 05:45:21', NULL, NULL, NULL, 1, 1, NULL, NULL),
|
||||||
|
(28, 'JJ027', 'Barang Elektronik', 'barang-elektronik', 'null', 'null', 1, '2025-04-18 05:47:28', '2025-04-18 05:47:28', NULL, NULL, NULL, 1, 1, NULL, NULL),
|
||||||
|
(29, 'JJ028', 'Furniture', 'furniture', 'null', 'null', 1, '2025-04-18 05:49:22', '2025-04-18 05:49:22', NULL, NULL, NULL, 1, 1, NULL, NULL),
|
||||||
|
(30, 'JJ029', 'Perlengkapan', 'perlengkapan', 'null', 'null', 1, '2025-04-18 05:51:00', '2025-04-18 05:51:00', NULL, NULL, NULL, 1, 1, NULL, NULL),
|
||||||
|
(31, 'JJ030', 'Persediaan Barang', 'persediaan-barang', 'null', 'null', 1, '2025-04-18 05:52:08', '2025-04-18 05:52:08', NULL, NULL, NULL, 1, 1, NULL, NULL),
|
||||||
|
(32, 'JJ031', 'Kapal', 'kapal', 'null', 'null', 1, '2025-04-18 05:53:26', '2025-04-18 05:53:26', NULL, NULL, NULL, 1, 1, NULL, NULL),
|
||||||
|
(33, 'JJ032', 'Deposito Berjangka', 'deposito-berjangka', 'null', 'null', 1, '2025-04-18 05:57:44', '2025-04-18 05:57:44', NULL, NULL, NULL, 1, 1, NULL, NULL),
|
||||||
|
(34, 'JJ033', 'Sertifikat Deposito', 'sertifikat-deposito', 'null', 'null', 1, '2025-04-18 05:58:57', '2025-04-18 05:58:57', NULL, NULL, NULL, 1, 1, NULL, NULL),
|
||||||
|
(35, 'JJ034', 'Rekening Giro / Tabungan', 'rekening-giro-tabungan', 'null', 'null', 1, '2025-04-18 05:59:56', '2025-04-18 05:59:56', NULL, NULL, NULL, 1, 1, NULL, NULL),
|
||||||
|
(36, 'JJ035', 'Barang Dagangan', 'barang-dagangan', 'null', 'null', 1, '2025-04-18 06:03:51', '2025-04-18 06:03:51', NULL, NULL, NULL, 1, 1, NULL, NULL),
|
||||||
|
(37, 'JJ036', 'Piutang Dagang', 'piutang-dagang', 'null', 'null', 1, '2025-04-18 06:04:59', '2025-04-18 06:04:59', NULL, NULL, NULL, 1, 1, NULL, NULL),
|
||||||
|
(38, 'JJ037', 'Jaminan Pribadi', 'jaminan-pribadi', 'null', 'null', 1, '2025-04-18 06:05:57', '2025-04-18 06:05:57', NULL, NULL, NULL, 1, 1, NULL, NULL),
|
||||||
|
(39, 'JJ038', 'Jaminan Perusahaan', 'jaminan-perusahaan', 'null', 'null', 1, '2025-04-18 06:06:53', '2025-04-18 06:06:53', NULL, NULL, NULL, 1, 1, NULL, NULL),
|
||||||
|
(40, 'JJ039', 'Resi Gudang', 'resi-gudang', 'null', 'null', 1, '2025-04-18 06:07:41', '2025-04-18 06:07:41', NULL, NULL, NULL, 1, 1, NULL, NULL),
|
||||||
|
(41, 'JJ040', 'Surat Berharga dan Saham', 'surat-berharga-dan-saham', 'null', 'null', 1, '2025-04-18 06:08:32', '2025-04-18 06:08:32', NULL, NULL, NULL, 1, 1, NULL, NULL),
|
||||||
|
(42, 'JJ041', 'Tanah Kavling (Kerjasama)', 'tanah-kavling-kerjasama', 'null', 'null', 1, '2025-04-18 06:09:31', '2025-04-18 06:09:31', NULL, NULL, NULL, 1, 1, NULL, NULL);
|
||||||
|
|||||||
10
database/seeders/sql/jenis_kapal.sql
Normal file
10
database/seeders/sql/jenis_kapal.sql
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
INSERT INTO `jenis_kapal` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
|
||||||
|
(1, 'JK001', 'Fishing Boat', 1, NULL, '2024-11-28 18:33:01', '2024-11-28 18:33:01', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(2, 'JK002', 'Tugboat', 1, NULL, '2024-11-28 18:33:55', '2024-11-28 18:33:55', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(3, 'JK003', 'Tongkang', 1, NULL, '2024-11-28 18:34:15', '2024-11-28 18:34:15', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(4, 'JK004', 'Self Propelled Oil Barge', 1, NULL, '2024-11-28 18:34:30', '2024-11-28 18:34:30', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(5, 'JK005', 'Dredger', 1, NULL, '2024-11-28 18:34:49', '2024-11-28 18:34:49', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(6, 'JK006', 'General Cargo', 1, NULL, '2024-11-28 18:35:09', '2024-11-28 18:35:09', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(7, 'JK007', 'Container Ship', 1, NULL, '2024-11-28 18:35:35', '2024-11-28 18:35:35', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(8, 'JK008', 'Oli Tangker', 1, NULL, '2024-11-28 18:36:04', '2024-11-28 18:36:04', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(9, 'JK009', 'Passenger Ship', 1, NULL, '2024-11-28 18:36:40', '2024-11-28 18:36:40', NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
7
database/seeders/sql/jenis_kendaraan.sql
Normal file
7
database/seeders/sql/jenis_kendaraan.sql
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
INSERT INTO `jenis_kendaraan` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
|
||||||
|
(1, 'JK001', 'Mobil Penumpang', 1, NULL, '2024-11-28 02:18:01', '2024-11-28 02:18:01', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(2, 'JK002', 'Mobil Bus', 1, NULL, '2024-11-28 02:18:15', '2024-11-28 02:18:15', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(3, 'JK003', 'Mobil Barang', 1, NULL, '2024-11-28 02:18:36', '2024-11-28 02:18:36', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(4, 'JK004', 'Sepeda Motor', 1, NULL, '2024-11-28 02:18:51', '2024-11-28 02:18:51', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(5, 'JK005', 'Kendaraan Khusus', 1, NULL, '2024-11-28 02:19:18', '2024-11-28 02:19:18', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(6, 'JK006', 'Truk', 1, NULL, '2024-11-28 02:19:34', '2024-11-28 02:19:34', NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
@@ -21,4 +21,33 @@ INSERT INTO `jenis_legalitas_jaminan` (`code`, `created_at`, `custom_field`, `cu
|
|||||||
('JLJ020', '2024-12-06 09:04:50', NULL, NULL, NULL, 'Rate Kamar pertipe, Jumlah Kamar, Luas Kamar Pertipe', 'rate-kamar-pertipe-jumlah-kamar-luas-kamar-pertipe', 1, '2024-12-06 09:04:50'),
|
('JLJ020', '2024-12-06 09:04:50', NULL, NULL, NULL, 'Rate Kamar pertipe, Jumlah Kamar, Luas Kamar Pertipe', 'rate-kamar-pertipe-jumlah-kamar-luas-kamar-pertipe', 1, '2024-12-06 09:04:50'),
|
||||||
('JLJ021', '2024-12-06 09:04:50', NULL, NULL, NULL, 'Analisis Kompetitor', 'analisis-kompetitor', 1, '2024-12-06 09:04:50'),
|
('JLJ021', '2024-12-06 09:04:50', NULL, NULL, NULL, 'Analisis Kompetitor', 'analisis-kompetitor', 1, '2024-12-06 09:04:50'),
|
||||||
('JLJ022', '2024-12-06 09:04:50', NULL, NULL, NULL, 'Bukti Bayar', 'bukti-bayar', 1, '2024-12-06 09:04:50'),
|
('JLJ022', '2024-12-06 09:04:50', NULL, NULL, NULL, 'Bukti Bayar', 'bukti-bayar', 1, '2024-12-06 09:04:50'),
|
||||||
('JLJ024', '2024-12-06 09:04:50', NULL, NULL, NULL, 'PPJB', 'ppjb', 1, '2024-12-06 09:04:50');
|
('JLJ024', '2024-12-06 09:04:50', NULL, NULL, NULL, 'PPJB', 'ppjb', 1, '2024-12-06 09:04:50'),
|
||||||
|
('JLJ025', '2024-12-06 09:04:50', NULL, NULL, NULL, 'LOKASI JAMINAN', 'lokasi-jaminan', 1, '2024-12-06 09:04:50'),
|
||||||
|
('JLJ026', '2024-12-06 09:04:50', NULL, NULL, NULL, 'KEPEMILIKAN', 'kepemilikan', 1, '2024-12-06 09:04:50'),
|
||||||
|
('JLJ027', '2024-12-06 09:04:50', NULL, NULL, NULL, 'STATUS KEPEMILIKAN, HUBUNGAN DAN PENGHUNI', 'status-kepemilikan-hubungan-dan-penghuni', 1, '2024-12-06 09:04:50'),
|
||||||
|
('JLJ028', '2024-12-06 09:04:50', NULL, NULL, NULL, 'ANALISA TANAH DAN BANGUNAN', 'analisa-tanah-dan-bangunan', 1, '2024-12-06 09:04:50'),
|
||||||
|
('JLJ029', '2024-12-06 09:04:50', NULL, NULL, NULL, 'SARANA PELENGKAP DAN LINGKUNGAN', 'sarana-pelengkap-dan-lingkungan', 1, '2024-12-06 09:04:50'),
|
||||||
|
('JLJ030', '2024-12-06 09:04:50', NULL, NULL, NULL, 'STATUS PEMILIKAN', 'status-pemilikan', 1, '2024-12-06 09:04:50'),
|
||||||
|
('JLJ031', '2024-12-06 09:04:50', NULL, NULL, NULL, 'KONDISI DAN SARANA PELENGKAP KENDARAAN', 'kondisi-dan-sarana-pelengkap-kendaraan', 1, '2024-12-06 09:04:50'),
|
||||||
|
('JLJ032', '2024-12-06 09:04:50', NULL, NULL, NULL, 'BARANG YANG DIPERIKSA', 'barang-yang-diperiksa', 1, '2024-12-06 09:04:50'),
|
||||||
|
('JLJ033', '2024-12-06 09:04:50', NULL, NULL, NULL, 'LOKASI, TEMPAT DAN STATUS TEMPAT PENYIMPANAN BARANG', 'lokasi-tempat-dan-status-tempat-penyimpanan-barang', 1, '2024-12-06 09:04:50'),
|
||||||
|
('JLJ034', '2024-12-06 09:04:50', NULL, NULL, NULL, 'KONDISI DAN DOKUMENTASI PENYIMPANAN BARANG', 'kondisi-dan-dokumentasi-penyimpanan-barang', 1, '2024-12-06 09:04:50'),
|
||||||
|
('JLJ035', '2024-12-06 09:04:50', NULL, NULL, NULL, 'KONDISI / SISTEM PENGAMANAN DAN LINGKUNGAN TEMPAT PENYIMPANAN BARANG', 'kondisi-sistem-pengamanan-dan-lingkungan-tempat-penyimpanan-barang', 1, '2024-12-06 09:04:50'),
|
||||||
|
('JLJ036', '2024-12-06 09:04:50', NULL, NULL, NULL, 'KONDISI MESIN', 'kondisi-mesin', 1, '2024-12-06 09:04:50'),
|
||||||
|
('JLJ037', '2024-12-06 09:04:50', NULL, NULL, NULL, 'CATATAN', 'catatan', 1, '2024-12-06 09:04:50'),
|
||||||
|
('JLJ038', '2024-12-06 09:04:50', NULL, NULL, NULL, 'EMAS', 'emas', 1, '2024-12-06 09:04:50'),
|
||||||
|
('JLJ039', '2024-12-06 09:04:50', NULL, NULL, NULL, 'ALAT BERAT', 'alat-berat', 1, '2024-12-06 09:04:50'),
|
||||||
|
('JLJ040', '2024-12-06 09:04:50', NULL, NULL, NULL, 'DEPOSITO', 'deposito', 1, '2024-12-06 09:04:50'),
|
||||||
|
('JLJ041', '2024-12-06 09:04:50', NULL, NULL, NULL, 'BARANG DAGANGAN', 'barang-dagangan', 1, '2024-12-06 09:04:50'),
|
||||||
|
('JLJ042', '2024-12-06 09:04:50', NULL, NULL, NULL, 'PIUTANG DAGANG', 'piutang-dagang', 1, '2024-12-06 09:04:50'),
|
||||||
|
('JLJ043', '2024-12-06 09:04:50', NULL, NULL, NULL, 'JAMINAN PRIBADI', 'jaminan-pribadi', 1, '2024-12-06 09:04:50'),
|
||||||
|
('JLJ044', '2024-12-06 09:04:50', NULL, NULL, NULL, 'JAMINAN PERUSAHAAN', 'jaminan-perusahaan', 1, '2024-12-06 09:04:50'),
|
||||||
|
('JLJ045', '2024-12-06 09:04:50', NULL, NULL, NULL, 'RESI GUDANG', 'resi-gudang', 1, '2024-12-06 09:04:50'),
|
||||||
|
('JLJ046', '2024-12-06 09:04:50', NULL, NULL, NULL, 'Surat Berharga dan Saham', 'surat-berharga-dan-saham', 1, '2024-12-06 09:04:50'),
|
||||||
|
('JLJ047', '2024-12-06 09:04:50', NULL, NULL, NULL, 'Tanah dan Bangunan (Kerjasama)', 'tanah-dan-bangunan-kerjasama', 1, '2024-12-06 09:04:50'),
|
||||||
|
('JLJ048', '2024-12-06 09:04:50', NULL, NULL, NULL, 'Tanah Kavling (Kerjasama)', 'tanah-kavling-kerjasama', 1, '2024-12-06 09:04:50'),
|
||||||
|
('JLJ049', '2024-12-06 09:04:50', NULL, NULL, NULL, 'JENIS KAPAL DAN STATUS KEPEMILIKAN', 'jenis-kapal-dan-status-kepemilikan', 1, '2024-12-06 09:04:50'),
|
||||||
|
('JLJ050', '2024-12-06 09:04:50', NULL, NULL, NULL, 'KONDISI DAN SARANA PELENGKAP KAPAL', 'kondisi-dan-sarana-pelengkap-kapal', 1, '2024-12-06 09:04:50'),
|
||||||
|
('JLJ051', '2024-12-06 09:04:50', NULL, NULL, NULL, 'REKENING GIRO / TABUNGAN', 'rekening-giro-tabungan', 1, '2024-12-06 09:04:50'),
|
||||||
|
('JLJ052', '2024-12-06 09:04:50', NULL, NULL, NULL, 'DATA TANAH', 'data-tanah', 1, '2024-12-06 09:04:50'),
|
||||||
|
('JLJ053', '2024-12-06 09:04:50', NULL, NULL, NULL, 'DATA BANGUNAN', 'data-bangunan', 1, '2024-12-06 09:04:50');
|
||||||
|
|||||||
7
database/seeders/sql/jenis_pesawat.sql
Normal file
7
database/seeders/sql/jenis_pesawat.sql
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
INSERT INTO `jenis_pesawat` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
|
||||||
|
(1, 'JP001', 'Penumpang Komersil', 1, NULL, '2024-11-28 18:37:59', '2024-11-28 18:37:59', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(2, 'JP002', 'Milliter', 1, NULL, '2024-11-28 18:38:13', '2024-11-28 18:38:13', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(3, 'JP003', 'Cargo', 1, NULL, '2024-11-28 18:38:26', '2024-11-28 18:38:26', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(4, 'JP004', 'Helikopter', 1, NULL, '2024-11-28 18:38:39', '2024-11-28 18:38:39', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(5, 'JP005', 'Pribadi', 1, NULL, '2024-11-28 18:38:56', '2024-11-28 18:38:56', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(6, 'JP006', 'Lainnya', 1, NULL, '2024-11-28 18:39:13', '2024-11-28 18:39:13', NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
2
database/seeders/sql/jenis_unit.sql
Normal file
2
database/seeders/sql/jenis_unit.sql
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
INSERT INTO `jenis_unit` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
|
||||||
|
(1, 'JU001', 'H', 1, NULL, '2024-11-28 18:54:44', '2024-11-28 18:54:44', NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
5
database/seeders/sql/ketinggian_tanah.sql
Normal file
5
database/seeders/sql/ketinggian_tanah.sql
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
INSERT INTO `ketinggian_tanah` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
|
||||||
|
(2, 'KT001', 'Sama Dengan Jalan', 1, NULL, '2024-11-05 00:28:23', '2024-11-05 00:28:23', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(3, 'KT002', 'Lebih Tinggi', 1, NULL, '2024-11-05 00:28:50', '2024-11-25 21:20:57', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(4, 'KT004', 'Lebih Rendah', 1, NULL, '2024-11-05 00:31:20', '2024-11-25 21:21:05', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(5, 'KT005', 'Bervariasi', 1, NULL, '2024-11-05 00:31:48', '2024-11-05 00:31:48', NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
7
database/seeders/sql/kondisi_bangunan.sql
Normal file
7
database/seeders/sql/kondisi_bangunan.sql
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
INSERT INTO `kondisi_bangunan` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
|
||||||
|
(2, 'KB001', 'Cukup Terawat', 1, NULL, '2024-11-05 00:32:53', '2024-11-05 00:32:53', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(3, 'KB002', 'Kurang Terawat', 1, NULL, '2024-11-05 00:33:08', '2024-11-05 00:33:08', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(4, 'KB003', 'Tidak Terawat', 1, NULL, '2024-11-05 00:33:24', '2024-11-05 00:33:24', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(5, 'KB004', 'Hancur/Tidak Layak Ditinggali', 1, NULL, '2024-11-05 00:33:55', '2024-11-05 00:33:55', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(6, 'KB005', 'Terawat', 1, NULL, '2025-03-07 02:47:03', '2025-03-07 02:47:03', NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
5
database/seeders/sql/kondisi_fisik_tanah.sql
Normal file
5
database/seeders/sql/kondisi_fisik_tanah.sql
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
INSERT INTO `kondisi_fisik_tanah` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
|
||||||
|
(1, 'KFT001', 'Tanah Darat', 1, NULL, '2024-11-04 21:41:58', '2024-11-04 21:41:58', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(2, 'KFT002', 'Sawah', 1, NULL, '2024-11-04 21:42:11', '2024-11-04 21:42:11', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(3, 'KFT003', 'Urukan', 1, NULL, '2024-11-04 21:42:24', '2024-11-04 21:42:24', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(4, 'KFT004', 'Bukit', 1, NULL, '2024-11-04 21:42:38', '2024-11-04 21:42:38', NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
5
database/seeders/sql/kontur_tanah.sql
Normal file
5
database/seeders/sql/kontur_tanah.sql
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
INSERT INTO `kontur_tanah` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
|
||||||
|
(1, 'KT001', 'Rata', 1, NULL, '2024-11-04 21:31:11', '2024-11-04 21:31:11', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(2, 'KT002', 'Tidak Rata', 1, NULL, '2024-11-04 21:31:25', '2024-11-04 21:31:25', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(3, 'KT003', 'Berbukit', 1, NULL, '2024-11-04 21:37:07', '2024-11-04 21:37:07', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(4, 'KT004', 'Bergelombang', 1, NULL, '2024-11-04 21:37:27', '2024-11-04 21:37:27', NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
4
database/seeders/sql/lalu_lintas_lokasi.sql
Normal file
4
database/seeders/sql/lalu_lintas_lokasi.sql
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
INSERT INTO `lalu_lintas_lokasi` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
|
||||||
|
(1, 'LD001', 'Satu Arah', 1, NULL, '2025-01-22 23:23:31', '2025-01-22 23:23:31', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(2, 'LD002', 'Dua Arah - Satu Jalur', 1, NULL, '2025-01-22 23:23:46', '2025-01-22 23:23:46', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(3, 'LD003', 'Dua Arah - Dua Jalur', 1, NULL, '2025-01-22 23:24:04', '2025-01-22 23:24:04', NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
4
database/seeders/sql/lantai.sql
Normal file
4
database/seeders/sql/lantai.sql
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
INSERT INTO `lantai` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
|
||||||
|
(1, 'LU001', 'Rendah', 1, NULL, '2024-11-05 02:06:00', '2024-11-05 02:06:00', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(3, 'LU003', 'Tinggi', 1, NULL, '2024-11-05 02:06:35', '2024-11-05 02:06:35', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(4, 'LU002', 'Menengah', 1, NULL, '2024-11-05 02:07:02', '2024-11-05 02:07:02', NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
4
database/seeders/sql/merupakan_daerah.sql
Normal file
4
database/seeders/sql/merupakan_daerah.sql
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
INSERT INTO `merupakan_daerah` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
|
||||||
|
(1, 'MD001', 'Bebas Banjir', 1, NULL, '2024-11-28 18:56:17', '2024-11-28 18:56:17', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(2, 'MD002', 'Rawan Banjir', 1, NULL, '2024-11-28 18:56:37', '2024-11-28 18:56:37', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(3, 'MD003', 'Sering Banjir', 1, NULL, '2024-11-28 18:56:56', '2024-11-28 18:56:56', NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
3
database/seeders/sql/model_alat_berat.sql
Normal file
3
database/seeders/sql/model_alat_berat.sql
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
INSERT INTO `model_alat_berat` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
|
||||||
|
(1, 'MA001', 'Excavator', 1, NULL, '2024-11-28 02:13:48', '2024-11-28 02:13:48', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(2, 'MA002', 'Grader', 1, NULL, '2024-11-28 02:14:02', '2024-11-28 02:14:02', NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
8
database/seeders/sql/perkerasan_jalan.sql
Normal file
8
database/seeders/sql/perkerasan_jalan.sql
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
INSERT INTO `perkerasan_jalan` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
|
||||||
|
(1, 'PJ001', 'Aspal', 1, NULL, '2024-12-09 02:25:15', '2024-12-09 02:25:15', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(2, 'PJ002', 'Beton', 1, NULL, '2024-12-09 02:25:28', '2024-12-09 02:25:28', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(3, 'PJ003', 'Conblock', 1, NULL, '2024-12-09 02:25:44', '2024-12-09 02:25:44', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(4, 'PJ004', 'Sirtu', 1, NULL, '2024-12-09 02:25:56', '2024-12-09 02:25:56', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(5, 'PJ006', 'Belum ada perkerasan', 1, NULL, '2024-12-09 02:26:13', '2024-12-09 02:26:13', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(6, 'PJ007', 'Semen', 1, NULL, '2024-12-20 00:23:31', '2024-12-20 00:23:31', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(7, 'PJ008', 'Lainnya', 1, NULL, '2024-12-20 00:23:45', '2024-12-20 00:23:45', NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
6
database/seeders/sql/posisi_kavling.sql
Normal file
6
database/seeders/sql/posisi_kavling.sql
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
INSERT INTO `posisi_kavling` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
|
||||||
|
(1, 'PK001', 'Badan', 1, NULL, '2024-11-04 21:38:18', '2024-11-04 21:38:18', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(2, 'PK002', 'Pojok', 1, NULL, '2024-11-04 21:38:29', '2024-11-04 21:38:29', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(3, 'PK003', 'Hook', 1, NULL, '2024-11-04 21:38:38', '2024-11-04 21:38:38', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(4, 'PK004', 'Kuldesak', 1, NULL, '2024-11-04 21:38:59', '2024-11-04 21:38:59', NULL, NULL, NULL, NULL, NULL, NULL),
|
||||||
|
(5, 'PK005', 'Lainnya', 1, NULL, '2024-11-04 21:39:47', '2024-11-04 21:39:47', NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user