Compare commits
190 Commits
e28da750c7
...
staging
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
112262d7d6 | ||
|
|
a1b9b7af86 | ||
|
|
e3540a1dd6 | ||
|
|
cd97d184ce | ||
|
|
929c56b079 | ||
|
|
388b65696f | ||
|
|
ba9089e2ac | ||
|
|
20d0061d42 | ||
|
|
4bef7cdafd | ||
|
|
bf728972b5 | ||
|
|
dfd2a82b42 | ||
|
|
c4bb3bea28 | ||
|
|
006dd44c64 | ||
|
|
698935d06f | ||
|
|
564c7ccac4 | ||
|
|
2b5556410d | ||
|
|
ee7c8ce97f | ||
|
|
17f7482080 | ||
|
|
6d137ad51c | ||
|
|
6c004812a9 | ||
|
|
d932559849 | ||
|
|
c3c40fdc27 | ||
|
|
41262e0317 | ||
|
|
2a1ecfd9e2 | ||
|
|
20833213b1 | ||
|
|
81159983cf | ||
|
|
bc35785c9c | ||
|
|
041ca943c9 | ||
|
|
312861a933 | ||
|
|
96657de512 | ||
|
|
4ad11593d5 | ||
|
|
d851ab58bc | ||
|
|
c08e050815 | ||
|
|
4aeecf6a97 | ||
|
|
1caa7ebfdd | ||
|
|
8666a0c58b | ||
|
|
99bc711954 | ||
|
|
627d7f9b40 | ||
|
|
8a5bf21982 | ||
|
|
2433aacfbc | ||
|
|
ba29f5ee8e | ||
|
|
eb784a982f | ||
|
|
2173a36564 | ||
|
|
ee079a8aa8 | ||
|
|
b4aba1a02a | ||
|
|
32baffe636 | ||
|
|
19fb39b02f | ||
|
|
bc7fef05f6 | ||
|
|
4d8b72e33a | ||
|
|
cf0059fe66 | ||
|
|
d7e5df569a | ||
|
|
cd46a3b0dc | ||
|
|
3486b97aee | ||
|
|
dc6e326122 | ||
|
|
4459b70271 | ||
|
|
57dece449c | ||
|
|
5e7368ebcf | ||
|
|
cbdd4bd99e | ||
|
|
d0cc62f8c0 | ||
|
|
0c2c0c9e20 | ||
|
|
274addb069 | ||
|
|
5c3a93c49b | ||
|
|
36ac1370d7 | ||
|
|
3eb402ae08 | ||
|
|
07589370df | ||
|
|
8220466f03 | ||
|
|
5c57b9cb58 | ||
|
|
a72515bc30 | ||
|
|
e79b8c6449 | ||
|
|
e63f9e7359 | ||
|
|
d0f3ffa93a | ||
|
|
37874aff3a | ||
|
|
44ff9d4ac6 | ||
|
|
5e8f979d05 | ||
|
|
ae15e1983f | ||
|
|
28513100f4 | ||
|
|
e72e82ea55 | ||
|
|
47bf7ab59b | ||
|
|
4ee42f38b9 | ||
|
|
60dd90a9ed | ||
|
|
3f979aef05 | ||
|
|
4bb808b341 | ||
|
|
887478c751 | ||
|
|
2708dead53 | ||
|
|
644f1da871 | ||
|
|
e32c73cdb2 | ||
|
|
40c3d84efc | ||
|
|
760a0cb85d | ||
|
|
0f8774a37c | ||
|
|
fa659ff115 | ||
|
|
fdfe591c39 | ||
|
|
7aae88ce85 | ||
|
|
8fbc02bfff | ||
|
|
0e4c8760f8 | ||
|
|
320dba9d9c | ||
|
|
6ddf78d2b0 | ||
|
|
79e66226b0 | ||
|
|
500118d787 | ||
|
|
ade4ffcad4 | ||
|
|
08b71604ec | ||
|
|
e731e9cea0 | ||
|
|
980b4e8e9f | ||
|
|
8158f3058f | ||
|
|
eea49b7943 | ||
|
|
5e8067ad72 | ||
|
|
e85ed55598 | ||
|
|
7f6c702683 | ||
|
|
e6d05cc4aa | ||
|
|
4ebc700283 | ||
|
|
121d099402 | ||
|
|
54668820b1 | ||
|
|
d63108dea1 | ||
|
|
5cdc4b08b3 | ||
|
|
dd11f467fa | ||
|
|
49b13e6689 | ||
|
|
b9d0d9f03b | ||
|
|
0972f3fcff | ||
|
|
d251c7655d | ||
|
|
afbdad43db | ||
|
|
886a382f57 | ||
|
|
c1c37f5716 | ||
|
|
89957190c7 | ||
|
|
0167919542 | ||
|
|
b3ccf3bb8f | ||
|
|
d434680f0e | ||
|
|
53c86a79d0 | ||
|
|
f7b851d295 | ||
|
|
baf0000a3f | ||
|
|
5b50a36a60 | ||
|
|
45f911cef9 | ||
|
|
aa3efd6015 | ||
|
|
fd21a5b86f | ||
|
|
d1744b07ec | ||
|
|
10aa59d65d | ||
|
|
2506b6115c | ||
|
|
acfc282e25 | ||
|
|
ffb24b8cd6 | ||
|
|
d4c70fba00 | ||
|
|
7b14c16af1 | ||
|
|
fc466f6087 | ||
|
|
1e8ce1d6d9 | ||
|
|
589e06dc00 | ||
|
|
7936c3e275 | ||
|
|
5e946cdfa7 | ||
|
|
b53b94e27d | ||
|
|
6f8db74159 | ||
|
|
43b086f3ea |
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`
|
||||
@@ -32,6 +32,8 @@ class LaporanAdminKreditExport implements WithColumnFormatting, WithHeadings, Fr
|
||||
$row->nilai_pasar_wajar,
|
||||
$row->nilai_likuidasi,
|
||||
$row->nama_penilai,
|
||||
$row->kolektibilitas,
|
||||
$row->keterangan,
|
||||
$row->created_at
|
||||
];
|
||||
}
|
||||
@@ -52,6 +54,8 @@ class LaporanAdminKreditExport implements WithColumnFormatting, WithHeadings, Fr
|
||||
'Nilai Pasar Wajar',
|
||||
'Nilai Likuidasi',
|
||||
'Nama Penilai',
|
||||
'Kolektibilitas',
|
||||
'Keterangan',
|
||||
'Created At'
|
||||
];
|
||||
}
|
||||
@@ -64,7 +68,9 @@ class LaporanAdminKreditExport implements WithColumnFormatting, WithHeadings, Fr
|
||||
'J' => NumberFormat::FORMAT_DATE_DDMMYYYY,
|
||||
'K' => NumberFormat::FORMAT_NUMBER_COMMA_SEPARATED1,
|
||||
'L' => NumberFormat::FORMAT_NUMBER_COMMA_SEPARATED1,
|
||||
'M' => NumberFormat::FORMAT_DATE_DATETIME,
|
||||
'N' => NumberFormat::FORMAT_TEXT, // Kolektibilitas
|
||||
'O' => NumberFormat::FORMAT_TEXT, // Keterangan
|
||||
'P' => NumberFormat::FORMAT_DATE_DATETIME, // Created At (moved from M to P)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,288 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Exports;
|
||||
|
||||
use Maatwebsite\Excel\Concerns\FromCollection;
|
||||
use Maatwebsite\Excel\Concerns\WithHeadings;
|
||||
use Maatwebsite\Excel\Concerns\WithMapping;
|
||||
use Maatwebsite\Excel\Concerns\WithTitle;
|
||||
use Maatwebsite\Excel\Concerns\WithCustomStartCell;
|
||||
use Maatwebsite\Excel\Concerns\WithEvents;
|
||||
use Maatwebsite\Excel\Events\AfterSheet;
|
||||
use Modules\Lpj\Models\Permohonan;
|
||||
use Modules\Lpj\Models\Branch;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class LaporanHasilPenilaianJaminanInternalExternalExport implements FromCollection, WithHeadings, WithMapping, WithTitle, WithCustomStartCell, WithEvents
|
||||
{
|
||||
protected $request;
|
||||
|
||||
public function __construct($request)
|
||||
{
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
public function collection()
|
||||
{
|
||||
$query = Permohonan::query();
|
||||
$query = $query->where('status', 'done');
|
||||
|
||||
// Apply date range filter if provided
|
||||
if ($this->request->has('start_date') || $this->request->has('end_date')) {
|
||||
$query->whereBetween('tanggal_permohonan', [
|
||||
$this->request->start_date ?? '1900-01-01',
|
||||
$this->request->end_date ?? now()->toDateString()
|
||||
]);
|
||||
}
|
||||
|
||||
// Apply branch filter if provided
|
||||
if ($this->request->has('branch_id') && !empty($this->request->branch_id)) {
|
||||
$query->where('branch_id', $this->request->branch_id);
|
||||
}
|
||||
|
||||
if ($this->request->has('penilai_id') && !empty($this->request->penilai_id)) {
|
||||
$request = $this->request; // Store in a local variable
|
||||
$query->whereHas('penilaian._user_penilai.userPenilaiTeam', function($q) use ($request) {
|
||||
$q->where('user_id', $request->penilai_id);
|
||||
});
|
||||
}
|
||||
|
||||
// Apply search filter if provided
|
||||
if ($this->request->has('search') && !empty($this->request->search)) {
|
||||
$search = $this->request->search;
|
||||
$query->where(function ($q) use ($search) {
|
||||
$q->where('nomor_registrasi', 'LIKE', '%' . $search . '%');
|
||||
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search . '%');
|
||||
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $search . '%');
|
||||
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search . '%');
|
||||
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search . '%');
|
||||
$q->orWhereRelation('jenisFasilitasKredit', 'name', 'LIKE', '%' . $search . '%');
|
||||
$q->orWhereRelation('jenisPenilaian', 'name', 'LIKE', '%' . $search . '%');
|
||||
$q->orWhere('status', 'LIKE', '%' . $search . '%');
|
||||
});
|
||||
}
|
||||
|
||||
// Default ordering
|
||||
$query->orderBy('nomor_registrasi', 'asc');
|
||||
|
||||
return $query->get();
|
||||
}
|
||||
|
||||
protected $rowNumber = 0;
|
||||
|
||||
public function map($permohonan): array
|
||||
{
|
||||
$this->rowNumber++;
|
||||
$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;
|
||||
$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 [
|
||||
$this->rowNumber,
|
||||
$permohonan->nomor_registrasi,
|
||||
$permohonan->tanggal_permohonan,
|
||||
$permohonan->debiture->branch->name,
|
||||
$permohonan->creator->name,
|
||||
$permohonan->debiture->cif,
|
||||
$permohonan->debiture->name,
|
||||
$permohonan->jenisPenilaian->name,
|
||||
$permohonan->tujuanPenilaian->name,
|
||||
$permohonan->jenisFasilitasKredit->name,
|
||||
$permohonan->documents->pluck('jenisJaminan.name')->unique()->implode(', '),
|
||||
$permohonan->documents->map(function ($document) {
|
||||
return formatAlamat($document);
|
||||
})->unique()->implode(', '),
|
||||
$permohonan->documents->flatMap(function ($document) {
|
||||
return $document->detail->map(function ($detail) {
|
||||
return (!empty($detail->dokumen_nomor) && is_array($detail->dokumen_nomor))
|
||||
? ($detail->jenisLegalitasJaminan->name ?? '') . "\n" . implode(', ', $detail->dokumen_nomor)
|
||||
: null;
|
||||
});
|
||||
})->filter()->unique()->implode(', '),
|
||||
$permohonan->documents->pluck('pemilik.name')->unique()->implode(', '),
|
||||
$luas_tanah . ' m²',
|
||||
formatRupiah($nilai_tanah, 2),
|
||||
$luas_bangunan . ' m²',
|
||||
formatRupiah($nilai_bangunan, 2),
|
||||
formatRupiah($permohonan->nilai_njop ?? 0, 2),
|
||||
formatRupiah($npw, 2),
|
||||
formatRupiah($nilai_liquidasi, 2),
|
||||
$permohonan->documents->map(function ($document) {
|
||||
return formatTanggalIndonesia($document->created_at);
|
||||
})->first(),
|
||||
'', // tanggal_spk
|
||||
'', // nomor_spk
|
||||
'', // tanggal_rencana_kunjungan
|
||||
$permohonan->penilaian->tanggal_kunjungan ? formatTanggalIndonesia($permohonan->penilaian->tanggal_kunjungan) : '',
|
||||
'', // tanggal_delivered
|
||||
'', // jangka_waktu_sla
|
||||
($permohonan->approval_dd_at || $permohonan->approval_eo_at) ?
|
||||
formatTanggalIndonesia($permohonan->approval_dd_at ?? $permohonan->approval_eo_at) : '',
|
||||
$permohonan->penilaian->tanggal_kunjungan ? formatTanggalIndonesia($permohonan->penilaian->tanggal_kunjungan) : '',
|
||||
$permohonan->penilaian->_user_penilai->userPenilaiTeam->name ?? '',
|
||||
$permohonan->penilaian->teams ?? '',
|
||||
'', // saran
|
||||
'' // catatan
|
||||
];
|
||||
}
|
||||
|
||||
public function headings(): array
|
||||
{
|
||||
return [
|
||||
'No',
|
||||
'Nomor Registrasi',
|
||||
'Tanggal Permohonan',
|
||||
'Cabang',
|
||||
'Pemohon',
|
||||
'CIF',
|
||||
'Nama Debitur',
|
||||
'Jenis Penilaian',
|
||||
'Tujuan Penilaian',
|
||||
'Jenis Fasilitas Kredit',
|
||||
'Jenis Agunan',
|
||||
'Alamat Agunan',
|
||||
'Bukti Kepemilikan',
|
||||
'Nama Pemilik',
|
||||
'Luas Tanah',
|
||||
'Nilai Tanah',
|
||||
'Luas Bangunan',
|
||||
'Nilai Bangunan',
|
||||
'Nilai NJOP',
|
||||
'Nilai Pasar Wajar',
|
||||
'Nilai Likuidasi',
|
||||
'Tanggal Dokumen Diterima',
|
||||
'Tanggal SPK',
|
||||
'Nomor SPK',
|
||||
'Tanggal Rencana Kunjungan',
|
||||
'Tanggal Kunjungan',
|
||||
'Tanggal Delivered',
|
||||
'Jangka Waktu SLA',
|
||||
'Tanggal Laporan',
|
||||
'Tanggal Review',
|
||||
'Nama Penilai',
|
||||
'Nama Team Leader',
|
||||
'Saran',
|
||||
'Catatan'
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function title(): string
|
||||
{
|
||||
return 'Laporan Hasil Penilaian Jaminan Internal & External';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function startCell(): string
|
||||
{
|
||||
return 'A7';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function registerEvents(): array
|
||||
{
|
||||
return [
|
||||
AfterSheet::class => function(AfterSheet $event) {
|
||||
// Get the sheet
|
||||
$sheet = $event->sheet->getDelegate();
|
||||
|
||||
// Set the title
|
||||
$sheet->setCellValue('A1', 'LAPORAN PENILAIAN JAMINAN');
|
||||
$sheet->getStyle('A1')->getFont()->setBold(true)->setSize(16);
|
||||
|
||||
// Merge cells for title
|
||||
$sheet->mergeCells('A1:AH1');
|
||||
$sheet->getStyle('A1')->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
|
||||
|
||||
// Set the branch information if filtered
|
||||
$branchInfo = '';
|
||||
if ($this->request->has('branch_id') && !empty($this->request->branch_id)) {
|
||||
$branch = Branch::find($this->request->branch_id);
|
||||
if ($branch) {
|
||||
$branchInfo = 'Cabang: ' . $branch->name;
|
||||
$sheet->setCellValue('A2', $branchInfo);
|
||||
$sheet->mergeCells('A2:AH2');
|
||||
$sheet->getStyle('A2')->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
|
||||
$sheet->getStyle('A2')->getFont()->setBold(true);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the period
|
||||
$startDate = $this->request->start_date ?? '';
|
||||
$endDate = $this->request->end_date ?? '';
|
||||
|
||||
$rowIndex = $branchInfo ? 3 : 2;
|
||||
|
||||
if ($startDate && $endDate) {
|
||||
$startDateFormatted = Carbon::parse($startDate)->format('d F Y');
|
||||
$endDateFormatted = Carbon::parse($endDate)->format('d F Y');
|
||||
$sheet->setCellValue('A' . $rowIndex, 'Periode: ' . $startDateFormatted . ' - ' . $endDateFormatted);
|
||||
} else {
|
||||
$sheet->setCellValue('A' . $rowIndex, 'Periode: Semua Data');
|
||||
}
|
||||
$sheet->mergeCells('A' . $rowIndex . ':AH' . $rowIndex);
|
||||
$sheet->getStyle('A' . $rowIndex)->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
|
||||
|
||||
// Set the date of export
|
||||
$rowIndex++;
|
||||
$sheet->setCellValue('A' . $rowIndex, 'Tanggal Export: ' . Carbon::now()->format('d F Y H:i:s'));
|
||||
|
||||
// Set the user who exported
|
||||
$rowIndex++;
|
||||
$userName = Auth::user() ? Auth::user()->name : 'System';
|
||||
$sheet->setCellValue('A' . $rowIndex, 'Diexport oleh: ' . $userName);
|
||||
|
||||
// Add a blank line
|
||||
$rowIndex++;
|
||||
$sheet->setCellValue('A' . $rowIndex, '');
|
||||
|
||||
// Style the header row
|
||||
$headerRange = 'A7:' . $sheet->getHighestColumn() . '7';
|
||||
$sheet->getStyle($headerRange)->getFont()->setBold(true);
|
||||
$sheet->getStyle($headerRange)->getFill()
|
||||
->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)
|
||||
->getStartColor()->setARGB('FFCCCCCC');
|
||||
|
||||
// Auto-size columns - fixed to handle columns beyond Z
|
||||
$highestColumn = $sheet->getHighestColumn();
|
||||
$highestColumnIndex = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::columnIndexFromString($highestColumn);
|
||||
|
||||
for ($i = 1; $i <= $highestColumnIndex; $i++) {
|
||||
$currentColumn = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($i);
|
||||
$sheet->getColumnDimension($currentColumn)->setAutoSize(true);
|
||||
}
|
||||
|
||||
// Add borders to all cells with data
|
||||
$dataRange = 'A7:' . $sheet->getHighestColumn() . $sheet->getHighestRow();
|
||||
$sheet->getStyle($dataRange)->getBorders()->getAllBorders()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN);
|
||||
|
||||
// Center align the header row
|
||||
$sheet->getStyle($headerRange)->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
|
||||
|
||||
// Set text wrap for header cells
|
||||
$sheet->getStyle($headerRange)->getAlignment()->setWrapText(true);
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
245
app/Exports/LaporanPenilaianJaminanExport.php
Normal file
245
app/Exports/LaporanPenilaianJaminanExport.php
Normal file
@@ -0,0 +1,245 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Exports;
|
||||
|
||||
use Maatwebsite\Excel\Concerns\FromCollection;
|
||||
use Maatwebsite\Excel\Concerns\WithHeadings;
|
||||
use Maatwebsite\Excel\Concerns\WithMapping;
|
||||
use Maatwebsite\Excel\Concerns\WithTitle;
|
||||
use Maatwebsite\Excel\Concerns\WithCustomStartCell;
|
||||
use Maatwebsite\Excel\Concerns\WithEvents;
|
||||
use Maatwebsite\Excel\Events\AfterSheet;
|
||||
use Modules\Lpj\Models\Permohonan;
|
||||
use Modules\Lpj\Models\Branch;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class LaporanPenilaianJaminanExport implements FromCollection, WithHeadings, WithMapping, WithTitle, WithCustomStartCell, WithEvents
|
||||
{
|
||||
protected $request;
|
||||
|
||||
public function __construct($request)
|
||||
{
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
public function collection()
|
||||
{
|
||||
$query = Permohonan::query();
|
||||
$query = $query->where('status', 'done');
|
||||
|
||||
// Apply date range filter if provided
|
||||
if ($this->request->has('start_date') || $this->request->has('end_date')) {
|
||||
$query->whereBetween('tanggal_permohonan', [
|
||||
$this->request->start_date ?? '1900-01-01',
|
||||
$this->request->end_date ?? now()->toDateString()
|
||||
]);
|
||||
}
|
||||
|
||||
// Apply branch filter if provided
|
||||
if ($this->request->has('branch_id') && !empty($this->request->branch_id)) {
|
||||
$query->where('branch_id', $this->request->branch_id);
|
||||
}
|
||||
|
||||
if ($this->request->has('penilai_id') && !empty($this->request->penilai_id)) {
|
||||
$request = $this->request; // Store in a local variable
|
||||
$query->whereHas('penilaian._user_penilai.userPenilaiTeam', function($q) use ($request) {
|
||||
$q->where('user_id', $request->penilai_id);
|
||||
});
|
||||
}
|
||||
|
||||
// Apply search filter if provided
|
||||
if ($this->request->has('search') && !empty($this->request->search)) {
|
||||
$search = $this->request->search;
|
||||
$query->where(function ($q) use ($search) {
|
||||
$q->where('nomor_registrasi', 'LIKE', '%' . $search . '%');
|
||||
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search . '%');
|
||||
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $search . '%');
|
||||
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search . '%');
|
||||
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search . '%');
|
||||
$q->orWhereRelation('jenisFasilitasKredit', 'name', 'LIKE', '%' . $search . '%');
|
||||
$q->orWhereRelation('jenisPenilaian', 'name', 'LIKE', '%' . $search . '%');
|
||||
$q->orWhere('status', 'LIKE', '%' . $search . '%');
|
||||
});
|
||||
}
|
||||
|
||||
// Default ordering
|
||||
$query->orderBy('nomor_registrasi', 'asc');
|
||||
|
||||
return $query->with(['debiture.branch'])->get();
|
||||
}
|
||||
|
||||
protected $rowNumber = 0;
|
||||
|
||||
public function map($permohonan): array
|
||||
{
|
||||
$this->rowNumber++;
|
||||
$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;
|
||||
$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 [
|
||||
$this->rowNumber,
|
||||
$permohonan->nomor_registrasi,
|
||||
$permohonan->tanggal_permohonan,
|
||||
$permohonan->debiture->branch->name,
|
||||
$permohonan->debiture->name,
|
||||
$permohonan->creator->name,
|
||||
$permohonan->tujuanPenilaian->name,
|
||||
$permohonan->documents->pluck('jenisJaminan.name')->unique()->implode(', '),
|
||||
$permohonan->documents->map(function ($document) {
|
||||
return formatAlamat($document);
|
||||
})->unique()->implode(', '),
|
||||
$luas_tanah . ' m²',
|
||||
formatRupiah($nilai_tanah, 2),
|
||||
$luas_bangunan . ' m²',
|
||||
formatRupiah($nilai_bangunan, 2),
|
||||
($permohonan->approval_dd_at || $permohonan->approval_eo_at) ?
|
||||
formatTanggalIndonesia($permohonan->approval_dd_at ?? $permohonan->approval_eo_at) : '',
|
||||
$permohonan->penilaian->tanggal_kunjungan ?
|
||||
formatTanggalIndonesia($permohonan->penilaian->tanggal_kunjungan) : '',
|
||||
formatRupiah($npw, 2),
|
||||
formatRupiah($nilai_liquidasi, 2),
|
||||
$permohonan->penilaian->_user_penilai->userPenilaiTeam->name,
|
||||
];
|
||||
}
|
||||
|
||||
public function headings(): array
|
||||
{
|
||||
return [
|
||||
'No',
|
||||
'Nomor Registrasi',
|
||||
'Tanggal Permohonan',
|
||||
'Cabang',
|
||||
'Nama Debitur',
|
||||
'Pemohon',
|
||||
'Tujuan Penilaian',
|
||||
'Jenis Agunan',
|
||||
'Alamat Agunan',
|
||||
'Luas Tanah',
|
||||
'Nilai Tanah',
|
||||
'Luas Bangunan',
|
||||
'Nilai Bangunan',
|
||||
'Tanggal Laporan',
|
||||
'Tanggal Review',
|
||||
'Nilai Pasar Wajar',
|
||||
'Nilai Likuidasi',
|
||||
'Nama Penilai',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function title(): string
|
||||
{
|
||||
return 'Laporan Penilaian Jaminan';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function startCell(): string
|
||||
{
|
||||
return 'A7';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function registerEvents(): array
|
||||
{
|
||||
return [
|
||||
AfterSheet::class => function(AfterSheet $event) {
|
||||
// Get the sheet
|
||||
$sheet = $event->sheet->getDelegate();
|
||||
|
||||
// Set the title
|
||||
$sheet->setCellValue('A1', 'LAPORAN PENILAIAN JAMINAN');
|
||||
$sheet->getStyle('A1')->getFont()->setBold(true)->setSize(16);
|
||||
|
||||
// Merge cells for title
|
||||
$sheet->mergeCells('A1:R1');
|
||||
$sheet->getStyle('A1')->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
|
||||
|
||||
// Set the branch information if filtered
|
||||
$branchInfo = '';
|
||||
if ($this->request->has('branch_id') && !empty($this->request->branch_id)) {
|
||||
$branch = Branch::find($this->request->branch_id);
|
||||
if ($branch) {
|
||||
$branchInfo = 'Cabang: ' . $branch->name;
|
||||
$sheet->setCellValue('A2', $branchInfo);
|
||||
$sheet->mergeCells('A2:R2');
|
||||
$sheet->getStyle('A2')->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
|
||||
$sheet->getStyle('A2')->getFont()->setBold(true);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the period
|
||||
$startDate = $this->request->start_date ?? '';
|
||||
$endDate = $this->request->end_date ?? '';
|
||||
|
||||
$rowIndex = $branchInfo ? 3 : 2;
|
||||
|
||||
if ($startDate && $endDate) {
|
||||
$startDateFormatted = Carbon::parse($startDate)->format('d F Y');
|
||||
$endDateFormatted = Carbon::parse($endDate)->format('d F Y');
|
||||
$sheet->setCellValue('A' . $rowIndex, 'Periode: ' . $startDateFormatted . ' - ' . $endDateFormatted);
|
||||
} else {
|
||||
$sheet->setCellValue('A' . $rowIndex, 'Periode: Semua Data');
|
||||
}
|
||||
$sheet->mergeCells('A' . $rowIndex . ':R' . $rowIndex);
|
||||
$sheet->getStyle('A' . $rowIndex)->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
|
||||
|
||||
// Set the date of export
|
||||
$rowIndex++;
|
||||
$sheet->setCellValue('A' . $rowIndex, 'Tanggal Export: ' . Carbon::now()->format('d F Y H:i:s'));
|
||||
|
||||
// Set the user who exported
|
||||
$rowIndex++;
|
||||
$userName = Auth::user() ? Auth::user()->name : 'System';
|
||||
$sheet->setCellValue('A' . $rowIndex, 'Diexport oleh: ' . $userName);
|
||||
|
||||
// Add a blank line
|
||||
$rowIndex++;
|
||||
$sheet->setCellValue('A' . $rowIndex, '');
|
||||
|
||||
// Style the header row
|
||||
$headerRange = 'A7:' . $sheet->getHighestColumn() . '7';
|
||||
$sheet->getStyle($headerRange)->getFont()->setBold(true);
|
||||
$sheet->getStyle($headerRange)->getFill()
|
||||
->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)
|
||||
->getStartColor()->setARGB('FFCCCCCC');
|
||||
|
||||
// Auto-size columns
|
||||
foreach(range('A', $sheet->getHighestColumn()) as $column) {
|
||||
$sheet->getColumnDimension($column)->setAutoSize(true);
|
||||
}
|
||||
|
||||
// Add borders to all cells with data
|
||||
$dataRange = 'A7:' . $sheet->getHighestColumn() . $sheet->getHighestRow();
|
||||
$sheet->getStyle($dataRange)->getBorders()->getAllBorders()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN);
|
||||
|
||||
// Center align the header row
|
||||
$sheet->getStyle($headerRange)->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
|
||||
|
||||
// Set text wrap for header cells
|
||||
$sheet->getStyle($headerRange)->getAlignment()->setWrapText(true);
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -19,8 +19,7 @@
|
||||
|
||||
public function collection()
|
||||
{
|
||||
$query = Permohonan::with(['user', 'branch', 'tujuanPenilaian', 'jenisFasilitasKredit', 'jenisPenilaian'])
|
||||
->select('permohonan.*');
|
||||
$query = Permohonan::query();
|
||||
|
||||
// Apply role-based filtering
|
||||
if (!Auth::user()->hasAnyRole(['administrator'])) {
|
||||
|
||||
117
app/Exports/LaporanSlikExport.php
Normal file
117
app/Exports/LaporanSlikExport.php
Normal file
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Exports;
|
||||
|
||||
use Maatwebsite\Excel\Concerns\FromQuery;
|
||||
use Maatwebsite\Excel\Concerns\WithHeadings;
|
||||
use Maatwebsite\Excel\Concerns\WithMapping;
|
||||
use Maatwebsite\Excel\Concerns\WithStyles;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||
|
||||
class LaporanSlikExport implements FromQuery, WithHeadings, WithMapping, WithStyles
|
||||
{
|
||||
protected $query;
|
||||
|
||||
public function __construct($query)
|
||||
{
|
||||
$this->query = $query;
|
||||
}
|
||||
|
||||
public function query()
|
||||
{
|
||||
return $this->query;
|
||||
}
|
||||
|
||||
public function headings(): array
|
||||
{
|
||||
return [
|
||||
'Sandi Bank',
|
||||
'Kode Kantor',
|
||||
'Kode Cabang',
|
||||
'Tahun',
|
||||
'Bulan',
|
||||
'No Rekening',
|
||||
'CIF',
|
||||
'Nama Debitur',
|
||||
'NPWP',
|
||||
'No KTP',
|
||||
'No Telp',
|
||||
'Alamat',
|
||||
'Kode Pos',
|
||||
'Kode Kab/Kota',
|
||||
'Kode Negara Domisili',
|
||||
'Kode Jenis',
|
||||
'Kode Sifat',
|
||||
'Kode Valuta',
|
||||
'Baki Debet',
|
||||
'Kolektibilitas',
|
||||
'Tanggal Mulai',
|
||||
'Tanggal Jatuh Tempo',
|
||||
'Tanggal Selesai',
|
||||
'Tanggal Restrukturisasi',
|
||||
'Kode Sebab Macet',
|
||||
'Tanggal Macet',
|
||||
'Kode Kondisi',
|
||||
'Tanggal Kondisi',
|
||||
'Nilai Agunan',
|
||||
'Jenis Agunan',
|
||||
'Kode Agunan',
|
||||
'Peringkat Agunan',
|
||||
'Fasilitas',
|
||||
'Status Agunan',
|
||||
'Tanggal Lapor',
|
||||
'Status',
|
||||
'Tanggal Dibuat',
|
||||
];
|
||||
}
|
||||
|
||||
public function map($laporanSlik): array
|
||||
{
|
||||
return [
|
||||
$laporanSlik->sandi_bank,
|
||||
$laporanSlik->kode_kantor,
|
||||
$laporanSlik->kode_cabang,
|
||||
$laporanSlik->tahun,
|
||||
$laporanSlik->bulan,
|
||||
$laporanSlik->no_rekening,
|
||||
$laporanSlik->cif,
|
||||
$laporanSlik->nama_debitur,
|
||||
$laporanSlik->npwp,
|
||||
$laporanSlik->no_ktp,
|
||||
$laporanSlik->no_telp,
|
||||
$laporanSlik->alamat,
|
||||
$laporanSlik->kode_pos,
|
||||
$laporanSlik->kode_kab_kota,
|
||||
$laporanSlik->kode_negara_domisili,
|
||||
$laporanSlik->kode_jenis,
|
||||
$laporanSlik->kode_sifat,
|
||||
$laporanSlik->kode_valuta,
|
||||
$laporanSlik->baki_debet,
|
||||
$laporanSlik->kolektibilitas,
|
||||
$laporanSlik->tanggal_mulai,
|
||||
$laporanSlik->tanggal_jatuh_tempo,
|
||||
$laporanSlik->tanggal_selesai,
|
||||
$laporanSlik->tanggal_restrukturisasi,
|
||||
$laporanSlik->kode_sebab_macet,
|
||||
$laporanSlik->tanggal_macet,
|
||||
$laporanSlik->kode_kondisi,
|
||||
$laporanSlik->tanggal_kondisi,
|
||||
$laporanSlik->nilai_agunan,
|
||||
$laporanSlik->jenis_agunan,
|
||||
$laporanSlik->kode_agunan,
|
||||
$laporanSlik->peringkat_agunan,
|
||||
$laporanSlik->fasilitas,
|
||||
$laporanSlik->status_agunan,
|
||||
$laporanSlik->tanggal_lapor,
|
||||
$laporanSlik->status,
|
||||
$laporanSlik->created_at->format('d/m/Y H:i'),
|
||||
];
|
||||
}
|
||||
|
||||
public function styles(Worksheet $sheet)
|
||||
{
|
||||
return [
|
||||
1 => ['font' => ['bold' => true]],
|
||||
];
|
||||
}
|
||||
}
|
||||
232
app/Exports/LaporanUserLimitExport.php
Normal file
232
app/Exports/LaporanUserLimitExport.php
Normal file
@@ -0,0 +1,232 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Exports;
|
||||
|
||||
use Maatwebsite\Excel\Concerns\FromCollection;
|
||||
use Maatwebsite\Excel\Concerns\WithHeadings;
|
||||
use Maatwebsite\Excel\Concerns\WithMapping;
|
||||
use Maatwebsite\Excel\Concerns\WithTitle;
|
||||
use Maatwebsite\Excel\Concerns\WithCustomStartCell;
|
||||
use Maatwebsite\Excel\Concerns\WithEvents;
|
||||
use Maatwebsite\Excel\Events\AfterSheet;
|
||||
use Modules\Lpj\Models\Permohonan;
|
||||
use Modules\Lpj\Models\Branch;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class LaporanUserLimitExport implements FromCollection, WithHeadings, WithMapping, WithTitle, WithCustomStartCell, WithEvents
|
||||
{
|
||||
protected $request;
|
||||
|
||||
public function __construct($request)
|
||||
{
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
public function collection()
|
||||
{
|
||||
$query = Permohonan::query();
|
||||
$query = $query->where('status', 'done');
|
||||
|
||||
// Apply date range filter if provided
|
||||
if ($this->request->has('start_date') || $this->request->has('end_date')) {
|
||||
$startDate = $this->request->start_date ?? '1900-01-01';
|
||||
$endDate = $this->request->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]);
|
||||
});
|
||||
|
||||
// OR check if has penawaran with date in range
|
||||
$q->orWhereHas('penawaran', function ($q3) use ($startDate, $endDate) {
|
||||
$q3->whereBetween('tanggal_penilaian_sebelumnya', [$startDate, $endDate]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Apply branch filter if provided
|
||||
if ($this->request->has('branch_id') && !empty($this->request->branch_id)) {
|
||||
$query->where('branch_id', $this->request->branch_id);
|
||||
}
|
||||
|
||||
if ($this->request->has('penilai_id') && !empty($this->request->penilai_id)) {
|
||||
$request = $this->request; // Store in a local variable
|
||||
$query->whereHas('penilaian._user_penilai.userPenilaiTeam', function ($q) use ($request) {
|
||||
$q->where('user_id', $request->penilai_id);
|
||||
});
|
||||
}
|
||||
|
||||
// Apply search filter if provided
|
||||
if ($this->request->has('search') && !empty($this->request->search)) {
|
||||
$search = $this->request->search;
|
||||
$query->where(function ($q) use ($search) {
|
||||
$q->where('nomor_registrasi', 'LIKE', '%' . $search . '%');
|
||||
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search . '%');
|
||||
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $search . '%');
|
||||
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search . '%');
|
||||
$q->orWhereRelation('debiture', DB::raw('LOWER(name)'), 'LIKE', '%' . strtolower($search) . '%');
|
||||
|
||||
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search . '%');
|
||||
$q->orWhereRelation('jenisFasilitasKredit', 'name', 'LIKE', '%' . $search . '%');
|
||||
$q->orWhereRelation('jenisPenilaian', 'name', 'LIKE', '%' . $search . '%');
|
||||
$q->orWhere('status', 'LIKE', '%' . $search . '%');
|
||||
});
|
||||
}
|
||||
|
||||
// Default ordering
|
||||
$query->orderBy('nomor_registrasi', 'asc');
|
||||
|
||||
return $query->get();
|
||||
}
|
||||
|
||||
protected $rowNumber = 0;
|
||||
|
||||
public function map($permohonan): array
|
||||
{
|
||||
$this->rowNumber++;
|
||||
$npw = 0;
|
||||
|
||||
if (isset($permohonan->penilai->lpj)) {
|
||||
$lpj = json_decode($permohonan->penilai->lpj, true);
|
||||
$npw = str_replace('.', '', $lpj['total_nilai_pasar_wajar'] ?? 0);
|
||||
}
|
||||
|
||||
return [
|
||||
$this->rowNumber,
|
||||
$permohonan->nomor_registrasi,
|
||||
$permohonan->debiture->branch->name ?? '',
|
||||
$permohonan->debiture->name ?? '',
|
||||
$permohonan->user->name ?? $permohonan->mig_nama_ao ?? '',
|
||||
$permohonan->tanggal_permohonan ?? '',
|
||||
$permohonan->penilaian->_user_penilai->userPenilaiTeam->name ?? '',
|
||||
$permohonan->penilaian && $permohonan->penilaian->tanggal_kunjungan
|
||||
? formatTanggalIndonesia($permohonan->penilaian->tanggal_kunjungan)
|
||||
: '',
|
||||
formatRupiah($npw, 2),
|
||||
];
|
||||
}
|
||||
|
||||
public function headings(): array
|
||||
{
|
||||
return [
|
||||
'No',
|
||||
'Nomor Registrasi',
|
||||
'Cabang',
|
||||
'Nama Debitur',
|
||||
'Pemohon',
|
||||
'Tanggal Permohonan',
|
||||
'Nama Penilai',
|
||||
'Tanggal Laporan',
|
||||
'Nilai Pasar Wajar',
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function title(): string
|
||||
{
|
||||
return 'Laporan User Limit';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function startCell(): string
|
||||
{
|
||||
return 'A7';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function registerEvents(): array
|
||||
{
|
||||
return [
|
||||
AfterSheet::class => function (AfterSheet $event) {
|
||||
// Get the sheet
|
||||
$sheet = $event->sheet->getDelegate();
|
||||
|
||||
// Set the title
|
||||
$sheet->setCellValue('A1', 'LAPORAN PENILAIAN JAMINAN');
|
||||
$sheet->getStyle('A1')->getFont()->setBold(true)->setSize(16);
|
||||
|
||||
// Merge cells for title
|
||||
$sheet->mergeCells('A1:AH1');
|
||||
$sheet->getStyle('A1')->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
|
||||
|
||||
// Set the branch information if filtered
|
||||
$branchInfo = '';
|
||||
if ($this->request->has('branch_id') && !empty($this->request->branch_id)) {
|
||||
$branch = Branch::find($this->request->branch_id);
|
||||
if ($branch) {
|
||||
$branchInfo = 'Cabang: ' . $branch->name;
|
||||
$sheet->setCellValue('A2', $branchInfo);
|
||||
$sheet->mergeCells('A2:AH2');
|
||||
$sheet->getStyle('A2')->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
|
||||
$sheet->getStyle('A2')->getFont()->setBold(true);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the period
|
||||
$startDate = $this->request->start_date ?? '';
|
||||
$endDate = $this->request->end_date ?? '';
|
||||
|
||||
$rowIndex = $branchInfo ? 3 : 2;
|
||||
|
||||
if ($startDate && $endDate) {
|
||||
$startDateFormatted = Carbon::parse($startDate)->format('d F Y');
|
||||
$endDateFormatted = Carbon::parse($endDate)->format('d F Y');
|
||||
$sheet->setCellValue('A' . $rowIndex, 'Periode: ' . $startDateFormatted . ' - ' . $endDateFormatted);
|
||||
} else {
|
||||
$sheet->setCellValue('A' . $rowIndex, 'Periode: Semua Data');
|
||||
}
|
||||
$sheet->mergeCells('A' . $rowIndex . ':AH' . $rowIndex);
|
||||
$sheet->getStyle('A' . $rowIndex)->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
|
||||
|
||||
// Set the date of export
|
||||
$rowIndex++;
|
||||
$sheet->setCellValue('A' . $rowIndex, 'Tanggal Export: ' . Carbon::now()->format('d F Y H:i:s'));
|
||||
|
||||
// Set the user who exported
|
||||
$rowIndex++;
|
||||
$userName = Auth::user() ? Auth::user()->name : 'System';
|
||||
$sheet->setCellValue('A' . $rowIndex, 'Diexport oleh: ' . $userName);
|
||||
|
||||
// Add a blank line
|
||||
$rowIndex++;
|
||||
$sheet->setCellValue('A' . $rowIndex, '');
|
||||
|
||||
// Style the header row
|
||||
$headerRange = 'A7:' . $sheet->getHighestColumn() . '7';
|
||||
$sheet->getStyle($headerRange)->getFont()->setBold(true);
|
||||
$sheet->getStyle($headerRange)->getFill()
|
||||
->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)
|
||||
->getStartColor()->setARGB('FFCCCCCC');
|
||||
|
||||
// Auto-size columns - fixed to handle columns beyond Z
|
||||
$highestColumn = $sheet->getHighestColumn();
|
||||
$highestColumnIndex = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::columnIndexFromString($highestColumn);
|
||||
|
||||
for ($i = 1; $i <= $highestColumnIndex; $i++) {
|
||||
$currentColumn = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($i);
|
||||
$sheet->getColumnDimension($currentColumn)->setAutoSize(true);
|
||||
}
|
||||
|
||||
// Add borders to all cells with data
|
||||
$dataRange = 'A7:' . $sheet->getHighestColumn() . $sheet->getHighestRow();
|
||||
$sheet->getStyle($dataRange)->getBorders()->getAllBorders()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN);
|
||||
|
||||
// Center align the header row
|
||||
$sheet->getStyle($headerRange)->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
|
||||
|
||||
// Set text wrap for header cells
|
||||
$sheet->getStyle($headerRange)->getAlignment()->setWrapText(true);
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@
|
||||
$row->id,
|
||||
$row->code,
|
||||
$row->name,
|
||||
$row->biaya,
|
||||
$row->created_at
|
||||
];
|
||||
}
|
||||
@@ -35,6 +36,7 @@
|
||||
'ID',
|
||||
'Code',
|
||||
'Name',
|
||||
'Biaya',
|
||||
'Created At'
|
||||
];
|
||||
}
|
||||
@@ -44,7 +46,8 @@
|
||||
{
|
||||
return [
|
||||
'A' => NumberFormat::FORMAT_NUMBER,
|
||||
'D' => NumberFormat::FORMAT_DATE_DATETIME
|
||||
'D' => NumberFormat::FORMAT_NUMBER_00,
|
||||
'E' => NumberFormat::FORMAT_DATE_DATETIME
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
185
app/Exports/SlikExport.php
Normal file
185
app/Exports/SlikExport.php
Normal file
@@ -0,0 +1,185 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Exports;
|
||||
|
||||
use Maatwebsite\Excel\Concerns\FromCollection;
|
||||
use Maatwebsite\Excel\Concerns\WithColumnFormatting;
|
||||
use Maatwebsite\Excel\Concerns\WithHeadings;
|
||||
use Maatwebsite\Excel\Concerns\WithMapping;
|
||||
use Modules\Lpj\Models\Slik;
|
||||
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
|
||||
|
||||
/**
|
||||
* Export class untuk data SLIK (Sistem Layanan Informasi Keuangan)
|
||||
*
|
||||
* Class ini menangani export data SLIK ke format Excel dengan:
|
||||
* - Mapping data sesuai struktur SLIK
|
||||
* - Format kolom yang sesuai (text, number, date)
|
||||
* - Header yang informatif
|
||||
*/
|
||||
class SlikExport implements WithColumnFormatting, WithHeadings, FromCollection, WithMapping
|
||||
{
|
||||
/**
|
||||
* Mengambil collection data SLIK untuk di-export
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function collection()
|
||||
{
|
||||
return Slik::orderBy('created_at', 'desc')->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Mapping data SLIK untuk setiap baris dalam Excel
|
||||
*
|
||||
* @param \Modules\Lpj\Models\Slik $row
|
||||
* @return array
|
||||
*/
|
||||
public function map($row): array
|
||||
{
|
||||
return [
|
||||
$row->id, // A - ID
|
||||
$row->sandi_bank, // B - Sandi Bank
|
||||
$row->tahun, // C - Tahun
|
||||
$row->bulan, // D - Bulan
|
||||
$row->flag_detail, // E - Flag Detail
|
||||
$row->kode_register_agunan, // F - Kode Register Agunan
|
||||
$row->no_rekening, // G - No Rekening
|
||||
$row->cif, // H - CIF
|
||||
$row->kolektibilitas, // I - Kolektibilitas
|
||||
$row->fasilitas, // J - Fasilitas
|
||||
$row->jenis_segmen_fasilitas, // K - Jenis Segmen Fasilitas
|
||||
$row->status_agunan, // L - Status Agunan
|
||||
$row->jenis_agunan, // M - Jenis Agunan
|
||||
$row->peringkat_agunan, // N - Peringkat Agunan
|
||||
$row->lembaga_pemeringkat, // O - Lembaga Pemeringkat
|
||||
$row->jenis_pengikatan, // P - Jenis Pengikatan
|
||||
$row->tanggal_pengikatan, // Q - Tanggal Pengikatan
|
||||
$row->nama_pemilik_agunan, // R - Nama Pemilik Agunan
|
||||
$row->bukti_kepemilikan, // S - Bukti Kepemilikan
|
||||
$row->alamat_agunan, // T - Alamat Agunan
|
||||
$row->lokasi_agunan, // U - Lokasi Agunan
|
||||
$row->nilai_agunan, // V - Nilai Agunan
|
||||
$row->nilai_agunan_menurut_ljk, // W - Nilai Agunan Menurut LJK
|
||||
$row->tanggal_penilaian_ljk, // X - Tanggal Penilaian LJK
|
||||
$row->nilai_agunan_penilai_independen, // Y - Nilai Agunan Penilai Independen
|
||||
$row->nama_penilai_independen, // Z - Nama Penilai Independen
|
||||
$row->tanggal_penilaian_penilai_independen, // AA - Tanggal Penilaian Penilai Independen
|
||||
$row->jumlah_hari_tunggakan, // AB - Jumlah Hari Tunggakan
|
||||
$row->status_paripasu, // AC - Status Paripasu
|
||||
$row->prosentase_paripasu, // AD - Prosentase Paripasu
|
||||
$row->status_kredit_join, // AE - Status Kredit Join
|
||||
$row->diasuransikan, // AF - Diasuransikan
|
||||
$row->keterangan, // AG - Keterangan
|
||||
$row->kantor_cabang, // AH - Kantor Cabang
|
||||
$row->operasi_data, // AI - Operasi Data
|
||||
$row->kode_cabang, // AJ - Kode Cabang
|
||||
$row->nama_debitur, // AK - Nama Debitur
|
||||
$row->nama_cabang, // AL - Nama Cabang
|
||||
$row->flag, // AM - Flag
|
||||
$row->created_at, // AN - Created At
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Header kolom untuk Excel
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function headings(): array
|
||||
{
|
||||
return [
|
||||
'ID',
|
||||
'Sandi Bank',
|
||||
'Tahun',
|
||||
'Bulan',
|
||||
'Flag Detail',
|
||||
'Kode Register Agunan',
|
||||
'No Rekening',
|
||||
'CIF',
|
||||
'Kolektibilitas',
|
||||
'Fasilitas',
|
||||
'Jenis Segmen Fasilitas',
|
||||
'Status Agunan',
|
||||
'Jenis Agunan',
|
||||
'Peringkat Agunan',
|
||||
'Lembaga Pemeringkat',
|
||||
'Jenis Pengikatan',
|
||||
'Tanggal Pengikatan',
|
||||
'Nama Pemilik Agunan',
|
||||
'Bukti Kepemilikan',
|
||||
'Alamat Agunan',
|
||||
'Lokasi Agunan',
|
||||
'Nilai Agunan',
|
||||
'Nilai Agunan Menurut LJK',
|
||||
'Tanggal Penilaian LJK',
|
||||
'Nilai Agunan Penilai Independen',
|
||||
'Nama Penilai Independen',
|
||||
'Tanggal Penilaian Penilai Independen',
|
||||
'Jumlah Hari Tunggakan',
|
||||
'Status Paripasu',
|
||||
'Prosentase Paripasu',
|
||||
'Status Kredit Join',
|
||||
'Diasuransikan',
|
||||
'Keterangan',
|
||||
'Kantor Cabang',
|
||||
'Operasi Data',
|
||||
'Kode Cabang',
|
||||
'Nama Debitur',
|
||||
'Nama Cabang',
|
||||
'Flag',
|
||||
'Created At',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Format kolom untuk Excel
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function columnFormats(): array
|
||||
{
|
||||
return [
|
||||
'A' => NumberFormat::FORMAT_NUMBER, // ID
|
||||
'B' => NumberFormat::FORMAT_TEXT, // Sandi Bank
|
||||
'C' => NumberFormat::FORMAT_TEXT, // Tahun
|
||||
'D' => NumberFormat::FORMAT_TEXT, // Bulan
|
||||
'E' => NumberFormat::FORMAT_TEXT, // Flag Detail
|
||||
'F' => NumberFormat::FORMAT_TEXT, // Kode Register Agunan
|
||||
'G' => NumberFormat::FORMAT_TEXT, // No Rekening
|
||||
'H' => NumberFormat::FORMAT_TEXT, // CIF
|
||||
'I' => NumberFormat::FORMAT_TEXT, // Kolektibilitas
|
||||
'J' => NumberFormat::FORMAT_TEXT, // Fasilitas
|
||||
'K' => NumberFormat::FORMAT_TEXT, // Jenis Segmen Fasilitas
|
||||
'L' => NumberFormat::FORMAT_TEXT, // Status Agunan
|
||||
'M' => NumberFormat::FORMAT_TEXT, // Jenis Agunan
|
||||
'N' => NumberFormat::FORMAT_TEXT, // Peringkat Agunan
|
||||
'O' => NumberFormat::FORMAT_TEXT, // Lembaga Pemeringkat
|
||||
'P' => NumberFormat::FORMAT_TEXT, // Jenis Pengikatan
|
||||
'Q' => NumberFormat::FORMAT_DATE_DDMMYYYY, // Tanggal Pengikatan
|
||||
'R' => NumberFormat::FORMAT_TEXT, // Nama Pemilik Agunan
|
||||
'S' => NumberFormat::FORMAT_TEXT, // Bukti Kepemilikan
|
||||
'T' => NumberFormat::FORMAT_TEXT, // Alamat Agunan
|
||||
'U' => NumberFormat::FORMAT_TEXT, // Lokasi Agunan
|
||||
'V' => NumberFormat::FORMAT_NUMBER_COMMA_SEPARATED1, // Nilai Agunan
|
||||
'W' => NumberFormat::FORMAT_NUMBER_COMMA_SEPARATED1, // Nilai Agunan Menurut LJK
|
||||
'X' => NumberFormat::FORMAT_DATE_DDMMYYYY, // Tanggal Penilaian LJK
|
||||
'Y' => NumberFormat::FORMAT_NUMBER_COMMA_SEPARATED1, // Nilai Agunan Penilai Independen
|
||||
'Z' => NumberFormat::FORMAT_TEXT, // Nama Penilai Independen
|
||||
'AA' => NumberFormat::FORMAT_DATE_DDMMYYYY, // Tanggal Penilaian Penilai Independen
|
||||
'AB' => NumberFormat::FORMAT_NUMBER, // Jumlah Hari Tunggakan
|
||||
'AC' => NumberFormat::FORMAT_TEXT, // Status Paripasu
|
||||
'AD' => NumberFormat::FORMAT_PERCENTAGE_00, // Prosentase Paripasu
|
||||
'AE' => NumberFormat::FORMAT_TEXT, // Status Kredit Join
|
||||
'AF' => NumberFormat::FORMAT_TEXT, // Diasuransikan
|
||||
'AG' => NumberFormat::FORMAT_TEXT, // Keterangan
|
||||
'AH' => NumberFormat::FORMAT_TEXT, // Kantor Cabang
|
||||
'AI' => NumberFormat::FORMAT_TEXT, // Operasi Data
|
||||
'AJ' => NumberFormat::FORMAT_TEXT, // Kode Cabang
|
||||
'AK' => NumberFormat::FORMAT_TEXT, // Nama Debitur
|
||||
'AL' => NumberFormat::FORMAT_TEXT, // Nama Cabang
|
||||
'AM' => NumberFormat::FORMAT_TEXT, // Flag
|
||||
'AN' => NumberFormat::FORMAT_DATE_DATETIME, // Created At
|
||||
];
|
||||
}
|
||||
}
|
||||
1161
app/Helpers/Lpj.php
1161
app/Helpers/Lpj.php
File diff suppressed because it is too large
Load Diff
@@ -55,7 +55,7 @@ class ActivityController extends Controller
|
||||
->when($teamId, fn ($q) => $q->where('id', $teamId));
|
||||
})
|
||||
->where('user_id', '!=', $user->id)
|
||||
->whereHas('user.roles', fn ($q) => $q->whereIn('name', ['surveyor', 'surveyor-penilai']))
|
||||
->whereHas('user.roles', fn ($q) => $q->whereIn('name', ['surveyor', 'surveyor-penilai','penilai']))
|
||||
->get();
|
||||
|
||||
$teamId = is_array($teamId) ? $teamId : [$teamId];
|
||||
@@ -306,6 +306,7 @@ class ActivityController extends Controller
|
||||
$query = Permohonan::query();
|
||||
|
||||
// Apply search filter if provided
|
||||
$query = $query->orderBy('nomor_registrasi', 'desc');
|
||||
if ($request->has('search') && !empty($request->get('search'))) {
|
||||
$search = $request->get('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'))) {
|
||||
$order = $request->get('sortOrder');
|
||||
$column = $request->get('sortField');
|
||||
|
||||
183
app/Http/Controllers/Api/DebiturController.php
Normal file
183
app/Http/Controllers/Api/DebiturController.php
Normal file
@@ -0,0 +1,183 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Exception;
|
||||
use Modules\Lpj\Models\Debiture;
|
||||
|
||||
/**
|
||||
* Controller untuk API pencarian debitur
|
||||
* Digunakan untuk autocomplete search pada form pembayaran
|
||||
*/
|
||||
class DebiturController extends Controller
|
||||
{
|
||||
/**
|
||||
* Pencarian debitur untuk autocomplete
|
||||
*
|
||||
* @param Request $request
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function search(Request $request): JsonResponse
|
||||
{
|
||||
try {
|
||||
// Log aktivitas pencarian
|
||||
Log::info('API Debitur Search - Request', [
|
||||
'query' => $request->get('q'),
|
||||
'user_id' => Auth::id()
|
||||
]);
|
||||
|
||||
$query = $request->get('q', '');
|
||||
|
||||
// Validasi minimal 2 karakter untuk pencarian
|
||||
if (strlen($query) < 2) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Minimal 2 karakter untuk pencarian',
|
||||
'data' => []
|
||||
], 400);
|
||||
}
|
||||
|
||||
// Mulai database transaction
|
||||
DB::beginTransaction();
|
||||
|
||||
try {
|
||||
// Query pencarian debitur
|
||||
// Asumsi tabel debitur dengan kolom: id, code, nama, alamat
|
||||
$debiturs = Debiture::query()
|
||||
->select('id', 'cif', 'name', 'address')
|
||||
->whereAny(['cif','name'], 'LIKE', "%{$query}%")
|
||||
->orderBy('name', 'asc')
|
||||
->limit(20) // Batasi hasil maksimal 20
|
||||
->get();
|
||||
|
||||
// Format data untuk TomSelect
|
||||
$formattedData = $debiturs->map(function($debitur) {
|
||||
return [
|
||||
'id' => $debitur->id,
|
||||
'kode_debitur' => $debitur->cif,
|
||||
'name' => $debitur->name,
|
||||
'address' => $debitur->address
|
||||
];
|
||||
});
|
||||
|
||||
DB::commit();
|
||||
|
||||
// Log hasil pencarian
|
||||
Log::info('API Debitur Search - Success', [
|
||||
'query' => $query,
|
||||
'results_count' => $formattedData->count(),
|
||||
'user_id' => Auth::id()
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Data debitur berhasil ditemukan',
|
||||
'data' => $formattedData
|
||||
]);
|
||||
|
||||
} catch (Exception $e) {
|
||||
DB::rollback();
|
||||
throw $e;
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
// Log error
|
||||
Log::error('API Debitur Search - Error', [
|
||||
'query' => $request->get('q'),
|
||||
'error' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString(),
|
||||
'user_id' => Auth::id()
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Terjadi kesalahan saat mencari data debitur',
|
||||
'error' => config('app.debug') ? $e->getMessage() : 'Internal Server Error'
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get detail debitur berdasarkan code
|
||||
*
|
||||
* @param Request $request
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function getByCode(Request $request): JsonResponse
|
||||
{
|
||||
try {
|
||||
$code = $request->get('code');
|
||||
|
||||
if (empty($code)) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Code debitur harus diisi',
|
||||
'data' => null
|
||||
], 400);
|
||||
}
|
||||
|
||||
// Log aktivitas get detail
|
||||
Log::info('API Debitur GetByCode - Request', [
|
||||
'code' => $code,
|
||||
'user_id' => Auth::id()
|
||||
]);
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
try {
|
||||
$debitur = DB::table('debitur')
|
||||
->select('id', 'code', 'nama', 'alamat', 'telepon', 'email')
|
||||
->where('code', $code)
|
||||
->where('status', 'aktif')
|
||||
->first();
|
||||
|
||||
if (!$debitur) {
|
||||
DB::rollback();
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Debitur tidak ditemukan',
|
||||
'data' => null
|
||||
], 404);
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
|
||||
Log::info('API Debitur GetByCode - Success', [
|
||||
'code' => $code,
|
||||
'debitur_id' => $debitur->id,
|
||||
'user_id' => Auth::id()
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Data debitur berhasil ditemukan',
|
||||
'data' => $debitur
|
||||
]);
|
||||
|
||||
} catch (Exception $e) {
|
||||
DB::rollback();
|
||||
throw $e;
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
Log::error('API Debitur GetByCode - Error', [
|
||||
'code' => $request->get('code'),
|
||||
'error' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString(),
|
||||
'user_id' => Auth::id()
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Terjadi kesalahan saat mengambil data debitur',
|
||||
'error' => config('app.debug') ? $e->getMessage() : 'Internal Server Error'
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
209
app/Http/Controllers/BucokController.php
Normal file
209
app/Http/Controllers/BucokController.php
Normal file
@@ -0,0 +1,209 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Exception;
|
||||
use Illuminate\Http\Request;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
use Modules\Lpj\Imports\BucokImport;
|
||||
use Modules\Lpj\Models\Bucok;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Controller untuk mengelola data Bucok
|
||||
*
|
||||
* @package Modules\Lpj\Http\Controllers
|
||||
*/
|
||||
class BucokController extends Controller
|
||||
{
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* Menampilkan halaman index bucok
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return view('lpj::bucok.index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Menampilkan detail bucok
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function show($id)
|
||||
{
|
||||
$bucok = Bucok::findOrFail($id);
|
||||
return view('lpj::bucok.show', compact('bucok'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data untuk datatables dengan server-side processing
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function dataForDatatables(Request $request)
|
||||
{
|
||||
if (is_null($this->user) || !$this->user->can('bucok.view')) {
|
||||
// abort(403, 'Sorry! You are not allowed to view bucok.');
|
||||
}
|
||||
|
||||
// Retrieve data from the database
|
||||
$query = Bucok::query();
|
||||
|
||||
// Apply search filter if provided
|
||||
if ($request->has('search') && !empty($request->get('search'))) {
|
||||
$search = $request->get('search');
|
||||
$query->where(function ($q) use ($search) {
|
||||
$q->where('nomor_tiket', 'LIKE', "%$search%")
|
||||
->orWhere('deskripsi', 'LIKE', "%$search%")
|
||||
->orWhere('nomor_coa', 'LIKE', "%$search%")
|
||||
->orWhere('nama_coa', 'LIKE', "%$search%")
|
||||
->orWhere('cost_center', 'LIKE', "%$search%")
|
||||
->orWhere('nama_sub_direktorat', 'LIKE', "%$search%")
|
||||
->orWhere('nama_direktorat_cabang', 'LIKE', "%$search%")
|
||||
->orWhere('penyelesaian', 'LIKE', "%$search%")
|
||||
->orWhere('keterangan_gantung', 'LIKE', "%$search%");
|
||||
});
|
||||
}
|
||||
|
||||
// Apply date range filter
|
||||
if ($request->has('start_date') && !empty($request->get('start_date'))) {
|
||||
$query->whereDate('tanggal', '>=', $request->get('start_date'));
|
||||
}
|
||||
if ($request->has('end_date') && !empty($request->get('end_date'))) {
|
||||
$query->whereDate('tanggal', '<=', $request->get('end_date'));
|
||||
}
|
||||
|
||||
// Apply year filter
|
||||
if ($request->has('year') && !empty($request->get('year'))) {
|
||||
$query->byYear($request->get('year'));
|
||||
}
|
||||
|
||||
// Apply month filter
|
||||
if ($request->has('month') && !empty($request->get('month'))) {
|
||||
$query->byMonth($request->get('month'));
|
||||
}
|
||||
|
||||
// Apply cost center filter
|
||||
if ($request->has('cost_center') && !empty($request->get('cost_center'))) {
|
||||
$query->byCostCenter($request->get('cost_center'));
|
||||
}
|
||||
|
||||
// Apply completion status filter
|
||||
if ($request->has('completion_status') && $request->get('completion_status') !== '') {
|
||||
$isCompleted = $request->get('completion_status') == '1';
|
||||
$query->byCompletionStatus($isCompleted);
|
||||
}
|
||||
|
||||
// Apply sorting if provided
|
||||
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
|
||||
$order = $request->get('sortOrder');
|
||||
$column = $request->get('sortField', 'created_at');
|
||||
$query->orderBy($column, $order);
|
||||
} else {
|
||||
$query->orderBy('created_at', 'desc');
|
||||
}
|
||||
|
||||
// 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 with relationships
|
||||
$data = $query->get();
|
||||
|
||||
// Transform data untuk datatables
|
||||
$transformedData = $data->map(function ($item) {
|
||||
return [
|
||||
'id' => $item->id,
|
||||
'no' => $item->no,
|
||||
'tanggal' => $item->tanggal ? dateFormat($item->tanggal,true) : '-',
|
||||
'bulan' => $item->bulan,
|
||||
'tahun' => $item->tahun,
|
||||
'nomor_tiket' => $item->nomor_tiket,
|
||||
'nomor_coa' => $item->nomor_coa,
|
||||
'nama_coa' => $item->nama_coa,
|
||||
'deskripsi' => $item->deskripsi,
|
||||
'nominal' => $item->nominal_formatted,
|
||||
'penyelesaian' => $item->penyelesaian,
|
||||
'umur_aging' => $item->umur_aging,
|
||||
'cost_center' => $item->cost_center,
|
||||
'nama_sub_direktorat' => $item->nama_sub_direktorat,
|
||||
'nama_direktorat_cabang' => $item->nama_direktorat_cabang,
|
||||
'tanggal_penyelesaian' => $item->tanggal_penyelesaian ? dateFormat($item->tanggal_penyelesaian,true) : '-',
|
||||
'nominal_penyelesaian' => $item->nominal_penyelesaian_formatted,
|
||||
'status_penyelesaian' => $item->status_penyelesaian,
|
||||
'status_badge' => $item->status_badge,
|
||||
'created_by' => $item->creator?->name ?? '-',
|
||||
'created_at' => dateFormat($item->created_at,true)
|
||||
];
|
||||
});
|
||||
|
||||
// Calculate the page count
|
||||
$pageCount = ceil($totalRecords / ($request->get('size', 10)));
|
||||
|
||||
// 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' => $transformedData,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Import data bucok dari Excel
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function import(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'file' => 'required|mimes:xlsx,xls,csv|max:10240' // Max 10MB
|
||||
]);
|
||||
|
||||
DB::beginTransaction();
|
||||
try {
|
||||
Log::info('Importing Bucok data', ['user_id' => Auth::id(), 'filename' => $request->file('file')->getClientOriginalName()]);
|
||||
|
||||
$import = new BucokImport();
|
||||
Excel::import($import, $request->file('file'));
|
||||
$statistics = $import->getImportStatistics();
|
||||
|
||||
DB::commit();
|
||||
Log::info('Bucok data imported successfully', ['user_id' => Auth::id()]);
|
||||
|
||||
return redirect()->back()->with('success', 'Data Bucok berhasil diimport. Total: ' . $statistics['total_processed'] . ', Created: ' . $statistics['created'] . ', Updated: ' . $statistics['updated'] . ', Skipped: ' . $statistics['skipped'] . ', Errors: ' . $statistics['errors']);
|
||||
} catch (Exception $e) {
|
||||
DB::rollback();
|
||||
Log::error('Failed to import Bucok data', ['error' => $e->getMessage(), 'user_id' => Auth::id()]);
|
||||
|
||||
return redirect()->back()->with('error', 'Gagal import data: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
152
app/Http/Controllers/CategoryDaftarPustakaController.php
Normal file
152
app/Http/Controllers/CategoryDaftarPustakaController.php
Normal file
@@ -0,0 +1,152 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Modules\Lpj\Models\CategoryDaftarPustaka;
|
||||
use Modules\Lpj\Http\Requests\CategoryDaftarPustakaRequest;
|
||||
|
||||
class CategoryDaftarPustakaController extends Controller
|
||||
{
|
||||
public $user;
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return view('lpj::category-daftar-pustaka.index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
return view('lpj::category-daftar-pustaka.create');
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*/
|
||||
public function store(CategoryDaftarPustakaRequest $request)
|
||||
{
|
||||
$validated = $request->validated();
|
||||
if ($validated) {
|
||||
try {
|
||||
CategoryDaftarPustaka::create($validated);
|
||||
return redirect()->route('category-daftar-pustaka.index')->with('success', 'Data Berhasil Disimpan');
|
||||
} catch (\Throwable $th) {
|
||||
return redirect()->route('category-daftar-pustaka.index')->with('error', $th->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the specified resource.
|
||||
*/
|
||||
public function show($id)
|
||||
{
|
||||
$category = CategoryDaftarPustaka::where('id', $id)->first();
|
||||
return view('lpj::category-daftar-pustaka.show', compact('category'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*/
|
||||
public function edit($id)
|
||||
{
|
||||
return view('lpj::category-daftar-pustaka.create', ['category' => CategoryDaftarPustaka::where('id', $id)->first()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*/
|
||||
public function update(CategoryDaftarPustakaRequest $request, $id)
|
||||
{
|
||||
$validated = $request->validated();
|
||||
if ($validated) {
|
||||
try {
|
||||
CategoryDaftarPustaka::where('id', $id)->update($validated);
|
||||
return redirect()->route('category-daftar-pustaka.index')->with('success', 'Data Berhasil Disimpan');
|
||||
} catch (\Throwable $th) {
|
||||
return redirect()->route('category-daftar-pustaka.index')->with('error', $th->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*/
|
||||
public function destroy($id)
|
||||
{
|
||||
try {
|
||||
CategoryDaftarPustaka::where('id', $id)->delete();
|
||||
return response()->json(['success' => true, 'message' => 'Data Berhasil Dihapus']);
|
||||
} catch (\Throwable $th) {
|
||||
return response()->json(['success' => false, 'message' => $th->getMessage()]);
|
||||
}
|
||||
}
|
||||
|
||||
public function dataForDatatables(Request $request)
|
||||
{
|
||||
if (is_null($this->user) || !$this->user->can('jenis_aset.view')) {
|
||||
//abort(403, 'Sorry! You are not allowed to view users.');
|
||||
}
|
||||
|
||||
// Retrieve data from the database
|
||||
$query = CategoryDaftarPustaka::query();
|
||||
|
||||
// Apply search filter if provided
|
||||
if ($request->has('search') && !empty($request->get('search'))) {
|
||||
$search = $request->get('search');
|
||||
$query->where(function ($q) use ($search) {
|
||||
$q->where('code', '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;
|
||||
|
||||
// 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,
|
||||
]);
|
||||
}
|
||||
}
|
||||
129
app/Http/Controllers/DaftarPustakaController.php
Normal file
129
app/Http/Controllers/DaftarPustakaController.php
Normal file
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Modules\Lpj\Models\CategoryDaftarPustaka;
|
||||
use Modules\Lpj\Services\DaftarPustakaService;
|
||||
use Modules\Lpj\Http\Requests\DaftarPustakaRequest;
|
||||
|
||||
class DaftarPustakaController extends Controller
|
||||
{
|
||||
private $daftarPustaka;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->daftarPustaka = app(DaftarPustakaService::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$categories = CategoryDaftarPustaka::all();
|
||||
$daftar_pustaka = $this->daftarPustaka->getAllDaftarPustaka($request);
|
||||
|
||||
return view('lpj::daftar-pustaka.index', [
|
||||
'categories' => $categories,
|
||||
'daftar_pustaka' => $daftar_pustaka,
|
||||
'page' => $daftar_pustaka->currentPage(),
|
||||
'pageCount' => $daftar_pustaka->lastPage(),
|
||||
'limit' => $daftar_pustaka->perPage(),
|
||||
'total' => $daftar_pustaka->total(),
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
$categories = CategoryDaftarPustaka::all();
|
||||
// dd($categories);
|
||||
return view('lpj::daftar-pustaka.create', compact('categories'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*/
|
||||
public function store(DaftarPustakaRequest $request)
|
||||
{
|
||||
|
||||
$validate = $request->validated();
|
||||
// dd($validate);
|
||||
$file = $request->file('attachment');
|
||||
if ($validate) {
|
||||
try {
|
||||
// Save to database
|
||||
$this->daftarPustaka->storeDaftarPustaka($validate, $file);
|
||||
return redirect()
|
||||
->route('daftar-pustaka.index')
|
||||
->with('success', 'Daftar Pustaka created successfully');
|
||||
} catch (Exception $e) {
|
||||
return redirect()
|
||||
->route('daftar-pustaka.create')
|
||||
->with('error', 'Failed to create daftar pustaka');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the specified resource.
|
||||
*/
|
||||
public function show($id)
|
||||
{
|
||||
$daftarPustaka = $this->daftarPustaka->getDaftarPustakaById($id);
|
||||
$categories = CategoryDaftarPustaka::all();
|
||||
|
||||
return view('lpj::daftar-pustaka.show', compact('daftarPustaka', 'categories'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*/
|
||||
public function edit($id)
|
||||
{
|
||||
$daftarPustaka = $this->daftarPustaka->getDaftarPustakaById($id);
|
||||
$categories = CategoryDaftarPustaka::all();
|
||||
return view('lpj::daftar-pustaka.create', compact('daftarPustaka', 'categories'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*/
|
||||
public function update(DaftarPustakaRequest $request, $id)
|
||||
{
|
||||
$validate = $request->validated();
|
||||
if ($validate) {
|
||||
try {
|
||||
// Save to database
|
||||
$file = $request->file('attachment');
|
||||
$this->daftarPustaka->updateDaftarPustaka($validate, $file, $id);
|
||||
return redirect()
|
||||
->route('daftar-pustaka.index')
|
||||
->with('success', 'Daftar Pustaka updated successfully');
|
||||
} catch (Exception $e) {
|
||||
return redirect()
|
||||
->route('daftar-pustaka.create')
|
||||
->with('error', 'Failed to update daftar pustaka');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*/
|
||||
public function destroy($id)
|
||||
{
|
||||
try {
|
||||
$this->daftarPustaka->deleteDaftarPustaka($id);
|
||||
return response()->json(['success' => true, 'message' => 'Daftar Pustaka deleted successfully']);
|
||||
} catch (Exception $e) {
|
||||
return response()->json(['success' => false, 'message' => 'Failed to delete daftar pustaka']);
|
||||
}
|
||||
}
|
||||
}
|
||||
36
app/Http/Controllers/DashboardController.php
Normal file
36
app/Http/Controllers/DashboardController.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Modules\Lpj\Services\DashboardService;
|
||||
|
||||
class DashboardController extends Controller
|
||||
{
|
||||
public $dashboardService;
|
||||
public function __construct(DashboardService $dashboardService)
|
||||
{
|
||||
$this->dashboardService = $dashboardService;
|
||||
}
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
// nilai default
|
||||
$start_date = $request->input('start_date', now()->startOfYear()->format('Y-m-d'));
|
||||
$end_date = $request->input('end_date', now()->format('Y-m-d'));
|
||||
|
||||
$validate = $request->validate([
|
||||
'start_date' => 'nullable|date_format:Y-m-d',
|
||||
'end_date' => 'nullable|date_format:Y-m-d',
|
||||
]);
|
||||
|
||||
$dashboard = $this->dashboardService->getDashboardData($start_date, $end_date);
|
||||
|
||||
// dd($dashboard);
|
||||
return view('lpj::dashboard.index', compact('dashboard'));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -129,7 +129,7 @@
|
||||
// Retrieve data from the database
|
||||
$query = Debiture::query();
|
||||
|
||||
if (!Auth::user()->hasAnyRole(['administrator'])) {
|
||||
if (!Auth::user()->hasAnyRole(['administrator','admin'])) {
|
||||
$query = $query->where('branch_id', Auth::user()->branch_id);
|
||||
}
|
||||
|
||||
|
||||
@@ -406,7 +406,9 @@
|
||||
|
||||
|
||||
// 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();
|
||||
}
|
||||
@@ -441,7 +443,7 @@
|
||||
try {
|
||||
// Periksa apakah pengguna adalah admin
|
||||
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);
|
||||
@@ -451,8 +453,8 @@
|
||||
}
|
||||
|
||||
// Periksa apakah dokumen jaminan terkait dengan permohonan aktif
|
||||
if ($jaminan->permohonan()->exists()) {
|
||||
return response()->json(['success' => false, 'message' => 'Tidak dapat menghapus dokumen jaminan yang terkait dengan permohonan aktif'], 400);
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Modules\Lpj\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Exception;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
@@ -19,12 +20,7 @@
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$permohonan = Permohonan::with([
|
||||
'documents.jenisJaminan',
|
||||
'penilaian._user_penilai',
|
||||
'penilai',
|
||||
'documents.detail.jenisLegalitasJaminan'
|
||||
])->where(['status' => 'done'])->get();
|
||||
$permohonan = Permohonan::where(['status' => 'done'])->get();
|
||||
foreach ($permohonan as $_permohonan) {
|
||||
$npw = 0;
|
||||
if (isset($_permohonan->penilai->lpj)) {
|
||||
@@ -154,6 +150,8 @@
|
||||
$request->validate([
|
||||
'kode_register_t24' => 'nullable',
|
||||
'cif' => 'required',
|
||||
'keterangan' => 'nullable|string',
|
||||
'kolektibilitas' => 'nullable|string|in:1,2,3,4,5',
|
||||
]);
|
||||
|
||||
try {
|
||||
@@ -162,6 +160,8 @@
|
||||
// Update only the editable fields
|
||||
$laporanAdminKredit->update([
|
||||
'kode_register_t24' => $request->kode_register_t24,
|
||||
'keterangan' => $request->keterangan,
|
||||
'kolektibilitas' => $request->kolektibilitas,
|
||||
'updated_by' => Auth::id(),
|
||||
]);
|
||||
|
||||
@@ -174,11 +174,11 @@
|
||||
}
|
||||
|
||||
return redirect()
|
||||
->route('laporan-admin-kredit.index')
|
||||
->route('admin-kredit.laporan.index')
|
||||
->with('success', 'Laporan Admin Kredit updated successfully');
|
||||
} catch (Exception $e) {
|
||||
return redirect()
|
||||
->route('laporan-admin-kredit.edit', $id)
|
||||
->route('admin-kredit.laporan.edit', $id)
|
||||
->with('error', 'Failed to update Laporan Admin Kredit');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class LaporanBiayaInternalExternalController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function showLaporanBiayaInternal()
|
||||
{
|
||||
return view('lpj::laporan-biaya.internal');
|
||||
}
|
||||
|
||||
public function showLaporanBiayaExternal()
|
||||
{
|
||||
return view('lpj::laporan-biaya.external');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,9 +2,10 @@
|
||||
|
||||
namespace Modules\Lpj\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Modules\Lpj\Models\Permohonan;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Modules\Lpj\Http\Controllers\PenilaiController;
|
||||
|
||||
class LaporanController extends Controller
|
||||
@@ -15,7 +16,6 @@ class LaporanController extends Controller
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
|
||||
|
||||
public function __construct(PenilaiController $penilaiController){
|
||||
$this->penilaiController = $penilaiController;
|
||||
}
|
||||
@@ -75,11 +75,12 @@ class LaporanController extends Controller
|
||||
}
|
||||
|
||||
// Retrieve data from the database
|
||||
$query = Permohonan::query()->whereIn('status',['proses-laporan','done', 'paparan', 'proses-paparan'])->whereNotNull('approval_so_at')->whereNotNull('approval_eo_at')->where(function ($q) {
|
||||
$q->whereIn('nilai_plafond_id', [1,4])
|
||||
->whereNotNull('approval_dd_at')
|
||||
->orWhereIn('nilai_plafond_id', [2,3]);
|
||||
});
|
||||
$query = Permohonan::query()
|
||||
->whereIn('status',['proses-laporan','done', 'paparan', 'proses-paparan']);
|
||||
|
||||
if (Auth::user()->hasAnyRole(['pemohon-ao','pemohon-eo'])) {
|
||||
$query = $query->where('branch_id', Auth::user()->branch_id);
|
||||
}
|
||||
|
||||
$query = $query->orderBy('nomor_registrasi', 'desc');
|
||||
// Apply search filter if provided
|
||||
@@ -123,7 +124,7 @@ class LaporanController extends Controller
|
||||
$filteredRecords = $query->count();
|
||||
|
||||
// Get the data for the current page
|
||||
$data = $query->with(['user', 'debiture', 'branch', 'tujuanPenilaian', 'penilaian','jenisFasilitasKredit', 'documents.inspeksi','penilai','documents.detail'])->get();
|
||||
$data = $query->with(['user', 'debiture', 'branch', 'tujuanPenilaian', 'penilaian','jenisFasilitasKredit', 'documents.inspeksi','penilai','documents.detail','noc'])->get();
|
||||
|
||||
// Calculate the page count
|
||||
$pageCount = ceil($totalRecords / $size);
|
||||
|
||||
33
app/Http/Controllers/LaporanDebitureController.php
Normal file
33
app/Http/Controllers/LaporanDebitureController.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Modules\Lpj\Models\Debiture;
|
||||
use Modules\Lpj\Services\LaporanDebitureService;
|
||||
|
||||
class LaporanDebitureController extends Controller
|
||||
{
|
||||
private $laporanDebitureService;
|
||||
public function __construct()
|
||||
{
|
||||
$this->laporanDebitureService = app(LaporanDebitureService::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$debiture = Debiture::all();
|
||||
return view('lpj::laporan-debiture.index', compact('debiture'));
|
||||
}
|
||||
|
||||
|
||||
public function dataTableForDebiture(Request $request)
|
||||
{
|
||||
return $this->laporanDebitureService->dataForDatatables($request);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
use Modules\Lpj\Exports\LaporanHasilPenilaianJaminanInternalExternalExport;
|
||||
use Modules\Lpj\Models\Permohonan;
|
||||
|
||||
class LaporanHasilPenilaianJaminanInternalExternalController extends Controller
|
||||
{
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return view('lpj::laporan_hasil_penilaian_jaminan_internal_external.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('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,
|
||||
'jenis_penilaian' => $permohonan->jenisPenilaian?->name,
|
||||
'tujuan_penilaian' => $permohonan->tujuanPenilaian?->name,
|
||||
'jenis_fasilitas_kredit' => $permohonan->jenisFasilitasKredit?->name,
|
||||
'branch' => $permohonan->debiture->branch?->name,
|
||||
'pemohon' => $permohonan->creator?->name,
|
||||
'cif' => $permohonan->debiture->cif,
|
||||
'name' => $permohonan->debiture?->name,
|
||||
'jenis_agunan' => $permohonan->documents?->pluck('jenisJaminan.name')
|
||||
->unique()
|
||||
->implode(', '),
|
||||
'alamat_agunan' => $permohonan->documents?->map(function ($document) {
|
||||
return formatAlamat($document);
|
||||
})->unique()->implode(', '),
|
||||
'bukti_kepemilikan' => (function() use ($permohonan) {
|
||||
$legalitasItems = $permohonan->documents?->flatMap(function ($document) {
|
||||
return $document->detail->map(function ($detail) {
|
||||
// Jika tidak ada jenis legalitas jaminan, lewati
|
||||
if (empty($detail->jenisLegalitasJaminan)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Hanya tampilkan detail yang memiliki dokumen_jaminan
|
||||
if (empty($detail->dokumen_jaminan)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Tampilkan nama legalitas jaminan saja
|
||||
return $detail->jenisLegalitasJaminan->name ?? '';
|
||||
});
|
||||
})->filter()->unique()->values()->toArray();
|
||||
|
||||
// Buat daftar bernomor
|
||||
$result = '';
|
||||
foreach ($legalitasItems as $index => $item) {
|
||||
$result .= ($index + 1) . '. ' . $item . "\n";
|
||||
}
|
||||
|
||||
return $result;
|
||||
})(),
|
||||
'nama_pemilik' => $permohonan->documents?->pluck('pemilik.name')
|
||||
->unique()
|
||||
->implode(', '),
|
||||
'luas_tanah' => $luas_tanah . ' m²',
|
||||
'nilai_tanah' => formatRupiah($nilai_tanah, 2),
|
||||
'luas_bangunan' => $luas_bangunan . ' m²',
|
||||
'nilai_bangunan' => formatRupiah($nilai_bangunan, 2),
|
||||
'nilai_njop' => formatRupiah($permohonan->nilai_njop, 2),
|
||||
'nilai_pasar_wajar' => formatRupiah($npw, 2),
|
||||
'nilai_likuidasi' => formatRupiah($nilai_liquidasi, 2),
|
||||
'tanggal_documen_diterima' => $permohonan->documents?->map(function ($document) {
|
||||
return $document->created_at->format('d-m-Y');
|
||||
}),
|
||||
'tanggal_spk' => '',
|
||||
'nomor_spk' => '',
|
||||
'tanggal_rencana_kunjunagn' => '',
|
||||
'tanggal_kunjungan' => '',
|
||||
'taggal_delivered' => '',
|
||||
'jangka_waktu_sla' => '',
|
||||
'nama_penilai' => $permohonan->penilaian?->_user_penilai?->userPenilaiTeam?->name,
|
||||
'nama_team_leader' => $permohonan->penilaian?->teams,
|
||||
'saran' => '',
|
||||
'catatan' => '',
|
||||
|
||||
|
||||
'tanggal_permohonan' => $permohonan->tanggal_permohonan,
|
||||
'tanggal_laporan' => $permohonan->approval_dd_at ?? $permohonan->approval_eo_at ?? '',
|
||||
'tanggal_review' => $permohonan->penilaian?->tanggal_kunjungan ?? '',
|
||||
];
|
||||
});
|
||||
|
||||
// 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 LaporanHasilPenilaianJaminanInternalExternalExport($request), 'laporan_hasil_penilaian_jaminan_internal_external.xlsx');
|
||||
}
|
||||
}
|
||||
43
app/Http/Controllers/LaporanMonitoringSoController.php
Normal file
43
app/Http/Controllers/LaporanMonitoringSoController.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Modules\Lpj\Services\LaporanMonitoringSoService;
|
||||
|
||||
class LaporanMonitoringSoController extends Controller
|
||||
{
|
||||
|
||||
private $laporanMonitoringSoService;
|
||||
|
||||
public function __construct(LaporanMonitoringSoService $laporanMonitoringSoService)
|
||||
{
|
||||
$this->laporanMonitoringSoService = $laporanMonitoringSoService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$user = auth()->user()->load('roles');
|
||||
$result = $this->laporanMonitoringSoService->progresPengerjaanLaporan($user);
|
||||
return view('lpj::laporan-monitoring.index', compact('result'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show details data.
|
||||
* @return Response
|
||||
*/
|
||||
|
||||
public function show($id){
|
||||
return view('lpj::laporan-monitoring.show', compact('id'));
|
||||
}
|
||||
|
||||
|
||||
public function dataForDatatablePenilai(Request $request, $id){
|
||||
return $this->laporanMonitoringSoService->showDetailsPermohonan($request, $id);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,6 +9,10 @@ use Modules\Lpj\Models\Permohonan;
|
||||
use Modules\Lpj\Models\StatusPermohonan;
|
||||
use Modules\Lpj\Exports\LaporanPenilaiJaminanExport;
|
||||
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
|
||||
{
|
||||
@@ -16,59 +20,31 @@ class LaporanPenilaiJaminanController extends Controller
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
|
||||
protected $previewLaporanService;
|
||||
|
||||
public function __construct(PreviewLaporanService $previewLaporanService)
|
||||
{
|
||||
$this->previewLaporanService = $previewLaporanService;
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
$status_permohonan = StatusPermohonan::all();
|
||||
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.
|
||||
*/
|
||||
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)
|
||||
{
|
||||
@@ -93,91 +69,104 @@ class LaporanPenilaiJaminanController extends Controller
|
||||
// dd($startDate);
|
||||
// Retrieve data from the database
|
||||
$query = Permohonan::query();
|
||||
|
||||
$query = $query->where('status', 'done')->orderBy('tanggal_permohonan', 'desc');
|
||||
// Apply search filter if provided
|
||||
if ($request->has('search') && !empty($request->get('search'))) {
|
||||
$search = $request->get('search');
|
||||
$paramsSearch = json_decode($search);
|
||||
$search = json_decode($request->get('search'));
|
||||
|
||||
$query->where(function ($q) use ($search) {
|
||||
$q->where('nomor_registrasi', 'LIKE', '%' . $search . '%')
|
||||
->orWhere('tanggal_permohonan', 'LIKE', '%' . $search . '%')
|
||||
->orWhereRelation('user', 'name', 'LIKE', '%' . $search . '%')
|
||||
->orWhereRelation('debiture', 'name', 'LIKE', '%' . $search . '%')
|
||||
->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search . '%')
|
||||
->orWhereRelation('branch', 'name', 'LIKE', '%' . $search . '%');
|
||||
if (!empty($search->start_date) || !empty($search->end_date)) {
|
||||
$startDate = $search->start_date ?? '1900-01-01';
|
||||
$endDate = $search->end_date ?? now()->toDateString();
|
||||
|
||||
if (!empty($paramsSearch->tanggal_awal) && !empty($paramsSearch->tanggal_akhir)) {
|
||||
$q->whereBetween('tanggal_permohonan', [$paramsSearch->tanggal_awal, $paramsSearch->tanggal_akhir]);
|
||||
$query->where(function ($q) use ($startDate, $endDate) {
|
||||
|
||||
$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);
|
||||
foreach ($statusKeywords as $keyword) {
|
||||
$q->orWhereRelation('penilai', 'type_penilai', 'LIKE', '%' . trim($keyword) . '%');
|
||||
}
|
||||
});
|
||||
// dd($search->search);
|
||||
|
||||
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');
|
||||
|
||||
|
||||
|
||||
// Default sorting if no sort provided
|
||||
// Apply sorting if provided
|
||||
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
|
||||
$order = $request->get('sortOrder');
|
||||
$column = $request->get('sortField');
|
||||
$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();
|
||||
|
||||
// Pagination
|
||||
// Apply pagination if provided
|
||||
if ($request->has('page') && $request->has('size')) {
|
||||
$page = (int) $request->get('page', 1);
|
||||
$size = (int) $request->get('size', 10);
|
||||
$offset = ($page - 1) * $size;
|
||||
$page = $request->get('page');
|
||||
$size = $request->get('size');
|
||||
$offset = ($page - 1) * $size; // Calculate the offset
|
||||
|
||||
$query->skip($offset)->take($size);
|
||||
}
|
||||
|
||||
// Get filtered count
|
||||
// Get the filtered count of records
|
||||
$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
|
||||
$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
|
||||
$pageCount = ceil($totalRecords / $request->get('size', 10));
|
||||
// Calculate the page count
|
||||
$pageCount = ceil($totalRecords / $size);
|
||||
|
||||
// Calculate the current page number
|
||||
$currentPage = max(1, $request->get('page', 1));
|
||||
|
||||
|
||||
|
||||
// Calculate total pages
|
||||
$pageCount = ceil($totalRecords / $request->get('size', 10));
|
||||
|
||||
// Return the response data as a JSON object
|
||||
return response()->json([
|
||||
'draw' => $request->get('draw'),
|
||||
'recordsTotal' => $totalRecords,
|
||||
'recordsFiltered' => $filteredRecords,
|
||||
'pageCount' => $pageCount,
|
||||
'page' => $request->get('page', 1),
|
||||
'page' => $currentPage,
|
||||
'totalCount' => $totalRecords,
|
||||
'data' => $data,
|
||||
]);
|
||||
@@ -185,15 +174,53 @@ class LaporanPenilaiJaminanController extends Controller
|
||||
|
||||
public function export(Request $request)
|
||||
{
|
||||
$tanggalAwal = $request->input('tanggal_awal');
|
||||
$tanggalAkhir = $request->input('tanggal_akhir');
|
||||
$status = $request->input('status');
|
||||
$selectedIds = $request->input('selected_ids');
|
||||
$startDate = $request->input('start_date');
|
||||
$endDate = $request->input('end_date');
|
||||
|
||||
// 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(
|
||||
new LaporanPenilaiJaminanExport($tanggalAwal, $tanggalAkhir, $status, $selectedIds),
|
||||
new LaporanPenilaiJaminanExport($request),
|
||||
$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;
|
||||
}
|
||||
}
|
||||
|
||||
180
app/Http/Controllers/LaporanPenilaianJaminanController.php
Normal file
180
app/Http/Controllers/LaporanPenilaianJaminanController.php
Normal file
@@ -0,0 +1,180 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Modules\Lpj\Exports\LaporanPenilaianJaminanExport;
|
||||
use Modules\Lpj\Models\Permohonan;
|
||||
use Modules\Lpj\Models\Penilaian;
|
||||
use Modules\Lpj\Models\PenawaranTender;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class LaporanPenilaianJaminanController extends Controller
|
||||
{
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* 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 (!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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
// Retrieve data from the database
|
||||
$query = Permohonan::query();
|
||||
$query->where('status','done');
|
||||
|
||||
if (!Auth::user()->hasAnyRole(['administrator'])) {
|
||||
$query = $query->where('branch_id', Auth::user()->branch_id);
|
||||
|
||||
32
app/Http/Controllers/LaporanSLAPenilaiController.php
Normal file
32
app/Http/Controllers/LaporanSLAPenilaiController.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Modules\Lpj\Services\LaporanSLAPenilaiService;
|
||||
|
||||
class LaporanSLAPenilaiController extends Controller
|
||||
{
|
||||
private $laporanSLAPenilaiService;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->laporanSLAPenilaiService = app(LaporanSLAPenilaiService::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return view('lpj::laporan-sla-penilai.index');
|
||||
}
|
||||
|
||||
public function dataForDatatableSLaPenilai(Request $request)
|
||||
{
|
||||
return $this->laporanSLAPenilaiService->dataForDatatables($request);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
304
app/Http/Controllers/LaporanSlikController.php
Normal file
304
app/Http/Controllers/LaporanSlikController.php
Normal file
@@ -0,0 +1,304 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
use Modules\Lpj\Models\LaporanSlik;
|
||||
use Modules\Lpj\Models\Slik;
|
||||
use Modules\Lpj\Exports\LaporanSlikExport;
|
||||
|
||||
class LaporanSlikController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return view('lpj::laporan-slik.index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*/
|
||||
public function store(Request $request): JsonResponse
|
||||
{
|
||||
try {
|
||||
$request->validate([
|
||||
'slik_id' => 'required|exists:sliks,id'
|
||||
]);
|
||||
|
||||
$slik = Slik::findOrFail($request->slik_id);
|
||||
|
||||
// Cek apakah data sudah ada di laporan_slik
|
||||
$existing = LaporanSlik::where('slik_id', $slik->id)->first();
|
||||
if ($existing) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Data sudah ada di laporan SLIK'
|
||||
], 422);
|
||||
}
|
||||
|
||||
// Copy data dari tabel slik ke laporan_slik
|
||||
$laporanSlik = LaporanSlik::create([
|
||||
'slik_id' => $slik->id,
|
||||
'sandi_bank' => $slik->sandi_bank,
|
||||
'kode_kantor' => $slik->kode_kantor,
|
||||
'kode_cabang' => $slik->kode_cabang,
|
||||
'tahun' => $slik->tahun,
|
||||
'bulan' => $slik->bulan,
|
||||
'no_rekening' => $slik->no_rekening,
|
||||
'cif' => $slik->cif,
|
||||
'kode_jenis' => $slik->kode_jenis,
|
||||
'kode_jenis_ket' => $slik->kode_jenis_ket,
|
||||
'kode_sifat' => $slik->kode_sifat,
|
||||
'kode_sifat_ket' => $slik->kode_sifat_ket,
|
||||
'kode_valuta' => $slik->kode_valuta,
|
||||
'kode_valuta_ket' => $slik->kode_valuta_ket,
|
||||
'baki_debet' => $slik->baki_debet,
|
||||
'kolektibilitas' => $slik->kolektibilitas,
|
||||
'kolektibilitas_ket' => $slik->kolektibilitas_ket,
|
||||
'tanggal_mulai' => $slik->tanggal_mulai,
|
||||
'tanggal_jatuh_tempo' => $slik->tanggal_jatuh_tempo,
|
||||
'tanggal_selesai' => $slik->tanggal_selesai,
|
||||
'tanggal_restrukturisasi' => $slik->tanggal_restrukturisasi,
|
||||
'kode_sebab_macet' => $slik->kode_sebab_macet,
|
||||
'kode_sebab_macet_ket' => $slik->kode_sebab_macet_ket,
|
||||
'tanggal_macet' => $slik->tanggal_macet,
|
||||
'kode_kondisi' => $slik->kode_kondisi,
|
||||
'kode_kondisi_ket' => $slik->kode_kondisi_ket,
|
||||
'tanggal_kondisi' => $slik->tanggal_kondisi,
|
||||
'nilai_agunan' => $slik->nilai_agunan,
|
||||
'nilai_agunan_ket' => $slik->nilai_agunan_ket,
|
||||
'jenis_agunan' => $slik->jenis_agunan,
|
||||
'kode_agunan' => $slik->kode_agunan,
|
||||
'kode_agunan_ket' => $slik->kode_agunan_ket,
|
||||
'peringkat_agunan' => $slik->peringkat_agunan,
|
||||
'peringkat_agunan_ket' => $slik->peringkat_agunan_ket,
|
||||
'nama_debitur' => $slik->nama_debitur,
|
||||
'npwp' => $slik->npwp,
|
||||
'no_ktp' => $slik->no_ktp,
|
||||
'no_telp' => $slik->no_telp,
|
||||
'kode_kab_kota' => $slik->kode_kab_kota,
|
||||
'kode_kab_kota_ket' => $slik->kode_kab_kota_ket,
|
||||
'kode_negara_domisili' => $slik->kode_negara_domisili,
|
||||
'kode_negara_domisili_ket' => $slik->kode_negara_domisili_ket,
|
||||
'kode_pos' => $slik->kode_pos,
|
||||
'alamat' => $slik->alamat,
|
||||
'fasilitas' => $slik->fasilitas,
|
||||
'status_agunan' => $slik->status_agunan,
|
||||
'tanggal_lapor' => $slik->tanggal_lapor,
|
||||
'status' => 'active',
|
||||
'created_by' => auth()->id(),
|
||||
'updated_by' => auth()->id(),
|
||||
]);
|
||||
|
||||
// Hapus data dari tabel slik setelah berhasil dipindahkan
|
||||
$slik->delete();
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Data berhasil dipindahkan ke laporan SLIK',
|
||||
'data' => $laporanSlik
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Error moving SLIK to laporan: ' . $e->getMessage());
|
||||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Terjadi kesalahan saat memindahkan data'
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Data untuk datatables dengan server-side processing
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function dataForDatatables(Request $request)
|
||||
{
|
||||
try {
|
||||
// Retrieve data from the database
|
||||
$query = LaporanSlik::query();
|
||||
|
||||
// Apply search filter if provided
|
||||
if ($request->has('search') && !empty($request->get('search'))) {
|
||||
$search = $request->get('search');
|
||||
$query->where(function ($q) use ($search) {
|
||||
$q->where('sandi_bank', 'LIKE', "%$search%")
|
||||
->orWhere('no_rekening', 'LIKE', "%$search%")
|
||||
->orWhere('cif', 'LIKE', "%$search%")
|
||||
->orWhere('nama_debitur', 'LIKE', "%$search%")
|
||||
->orWhere('fasilitas', 'LIKE', "%$search%")
|
||||
->orWhere('status_agunan', 'LIKE', "%$search%");
|
||||
});
|
||||
}
|
||||
|
||||
// Apply year filter
|
||||
if ($request->has('year') && !empty($request->get('year'))) {
|
||||
$query->where('tahun', $request->get('year'));
|
||||
}
|
||||
|
||||
// Apply month filter
|
||||
if ($request->has('month') && !empty($request->get('month'))) {
|
||||
$query->where('bulan', $request->get('month'));
|
||||
}
|
||||
|
||||
// Apply sandi bank filter
|
||||
if ($request->has('sandi_bank') && !empty($request->get('sandi_bank'))) {
|
||||
$query->where('sandi_bank', $request->get('sandi_bank'));
|
||||
}
|
||||
|
||||
// Apply kolektibilitas filter
|
||||
if ($request->has('kolektibilitas') && !empty($request->get('kolektibilitas'))) {
|
||||
$query->where('kolektibilitas', $request->get('kolektibilitas'));
|
||||
}
|
||||
|
||||
// Apply status filter
|
||||
if ($request->has('status') && !empty($request->get('status'))) {
|
||||
$query->where('status', $request->get('status'));
|
||||
}
|
||||
|
||||
// Apply sorting if provided
|
||||
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
|
||||
$order = $request->get('sortOrder');
|
||||
$column = $request->get('sortField', 'created_at');
|
||||
$query->orderBy($column, $order);
|
||||
} else {
|
||||
$query->orderBy('created_at', 'desc');
|
||||
}
|
||||
|
||||
// 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();
|
||||
|
||||
// Transform data untuk datatables
|
||||
$transformedData = $data->map(function ($item) {
|
||||
return [
|
||||
'id' => $item->id,
|
||||
'sandi_bank' => $item->sandi_bank,
|
||||
'tahun' => $item->tahun,
|
||||
'bulan' => $item->bulan,
|
||||
'no_rekening' => $item->no_rekening,
|
||||
'cif' => $item->cif,
|
||||
'nama_debitur' => $item->nama_debitur,
|
||||
'kolektibilitas' => $item->kolektibilitas,
|
||||
'kolektibilitas_badge' => $item->kolektibilitas_badge ?? '',
|
||||
'fasilitas' => $item->fasilitas,
|
||||
'nilai_agunan' => $item->nilai_agunan_formatted ?? '',
|
||||
'status_agunan' => $item->status_agunan,
|
||||
'status_badge' => $item->status_badge ?? '',
|
||||
'created_by' => $item->creator?->name ?? '-',
|
||||
'created_at' => dateFormat($item->created_at, true) ?? $item->created_at->format('d/m/Y H:i')
|
||||
];
|
||||
});
|
||||
|
||||
// Calculate the page count
|
||||
$pageCount = ceil($totalRecords / ($request->get('size', 10)));
|
||||
|
||||
// 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' => $transformedData,
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Error in laporan slik datatables: ' . $e->getMessage());
|
||||
|
||||
return response()->json([
|
||||
'draw' => $request->get('draw'),
|
||||
'recordsTotal' => 0,
|
||||
'recordsFiltered' => 0,
|
||||
'pageCount' => 0,
|
||||
'page' => 1,
|
||||
'totalCount' => 0,
|
||||
'data' => [],
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function show($id)
|
||||
{
|
||||
try {
|
||||
$laporanSlik = LaporanSlik::findOrFail($id);
|
||||
return view('lpj::laporan-slik.show', compact('laporanSlik'));
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Error showing laporan slik: ' . $e->getMessage());
|
||||
return back()->with('error', 'Data tidak ditemukan');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Export laporan SLIK to Excel
|
||||
*/
|
||||
public function export(Request $request)
|
||||
{
|
||||
try {
|
||||
$query = LaporanSlik::query();
|
||||
|
||||
// Apply filters
|
||||
if ($request->has('search') && $request->search) {
|
||||
$search = $request->search;
|
||||
$query->where(function($q) use ($search) {
|
||||
$q->where('nama_debitur', 'like', "%{$search}%")
|
||||
->orWhere('no_rekening', 'like', "%{$search}%")
|
||||
->orWhere('cif', 'like', "%{$search}%");
|
||||
});
|
||||
}
|
||||
|
||||
if ($request->has('year') && $request->year) {
|
||||
$query->where('tahun', $request->year);
|
||||
}
|
||||
|
||||
if ($request->has('month') && $request->month) {
|
||||
$query->where('bulan', $request->month);
|
||||
}
|
||||
|
||||
if ($request->has('status') && $request->status) {
|
||||
$query->where('status', $request->status);
|
||||
}
|
||||
|
||||
$filename = 'laporan-slik-' . now()->format('Y-m-d-His') . '.xlsx';
|
||||
|
||||
return Excel::download(new LaporanSlikExport($query), $filename);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Error exporting laporan slik: ' . $e->getMessage());
|
||||
return back()->with('error', 'Gagal export data: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
51
app/Http/Controllers/LaporanUserController.php
Normal file
51
app/Http/Controllers/LaporanUserController.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
use Modules\Lpj\Exports\LaporanUserLimitExport;
|
||||
use Modules\Lpj\Services\LaporanUserService;
|
||||
|
||||
class LaporanUserController extends Controller
|
||||
{
|
||||
|
||||
|
||||
private $laporanUserService;
|
||||
|
||||
public function __construct(LaporanUserService $laporanUserService)
|
||||
{
|
||||
$this->laporanUserService = $laporanUserService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
// $user = $this->laporanUserService->getUserPemohon();
|
||||
return view('lpj::laporan-user.index');
|
||||
}
|
||||
|
||||
public function searchUserPemohon(Request $request)
|
||||
{
|
||||
$search = $request->get('search');
|
||||
$user = $this->laporanUserService->getUserPemohon($search);
|
||||
return response()->json($user);
|
||||
}
|
||||
|
||||
public function dataTableForUserPemohon(Request $request)
|
||||
{
|
||||
return $this->laporanUserService->dataForDatatables($request);
|
||||
}
|
||||
|
||||
public function export(Request $request)
|
||||
{
|
||||
$startDate = $request->start_date;
|
||||
$endDate = $request->end_date;
|
||||
// name of the file
|
||||
$fileName = 'laporan_user_limit' . $startDate . '_' . $endDate . '.xlsx';
|
||||
return Excel::download(new LaporanUserLimitExport($request), $fileName);
|
||||
}
|
||||
}
|
||||
558
app/Http/Controllers/MemoController.php
Normal file
558
app/Http/Controllers/MemoController.php
Normal file
@@ -0,0 +1,558 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Http\Controllers;
|
||||
|
||||
use Exception;
|
||||
use Modules\Lpj\Models\Noc;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Modules\Lpj\Models\Permohonan;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Barryvdh\DomPDF\Facade\Pdf;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class MemoController extends Controller
|
||||
{
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* Menampilkan halaman index memo penyelesaian
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
Log::info('MemoController: Mengakses halaman index memo penyelesaian');
|
||||
return view('lpj::memo.index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Menampilkan form untuk membuat memo penyelesaian dengan data yang dipilih
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function create(Request $request)
|
||||
{
|
||||
Log::info('MemoController: Mengakses halaman create memo penyelesaian');
|
||||
|
||||
$selectedIds = $request->get('selected_ids', []);
|
||||
|
||||
// Pastikan $selectedIds selalu berupa array
|
||||
if (is_string($selectedIds)) {
|
||||
$selectedIds = explode(',', $selectedIds);
|
||||
}
|
||||
|
||||
// Filter array untuk menghilangkan nilai kosong
|
||||
$selectedIds = array_filter($selectedIds, function($id) {
|
||||
return !empty(trim($id));
|
||||
});
|
||||
|
||||
$permohonanList = [];
|
||||
$totalBiayaPJ = 0;
|
||||
|
||||
if (!empty($selectedIds) && count($selectedIds) > 0) {
|
||||
try {
|
||||
$permohonanList = Permohonan::with([
|
||||
'user',
|
||||
'debiture',
|
||||
'branch',
|
||||
'tujuanPenilaian',
|
||||
'penilaian',
|
||||
'jenisFasilitasKredit',
|
||||
'documents.inspeksi',
|
||||
'penilai',
|
||||
'documents.detail',
|
||||
'noc'
|
||||
])->whereIn('id', $selectedIds)->get();
|
||||
|
||||
// Hitung total biaya PJ dari nominal_bayar di tabel NOC
|
||||
$totalBiayaPJ = Noc::whereIn('permohonan_id', $selectedIds)
|
||||
->sum('nominal_bayar');
|
||||
|
||||
Log::info('MemoController: Total Biaya PJ dihitung: ' . $totalBiayaPJ);
|
||||
|
||||
} catch (Exception $e) {
|
||||
Log::error('MemoController: Error saat mengambil data permohonan - ' . $e->getMessage());
|
||||
return redirect()->back()->with('error', 'Terjadi kesalahan saat memuat data');
|
||||
}
|
||||
}
|
||||
|
||||
return view('lpj::memo.create', compact('permohonanList', 'totalBiayaPJ'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Menyimpan memo penyelesaian yang telah dibuat
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
Log::info('MemoController: Memulai proses penyimpanan memo penyelesaian');
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
try {
|
||||
// Validasi input
|
||||
$request->validate([
|
||||
'permohonan_ids' => 'required|array',
|
||||
'permohonan_ids.*' => 'exists:permohonan,id',
|
||||
'memo_number' => 'required|string|max:255',
|
||||
'payment_date' => 'required|date',
|
||||
'memo_date' => 'required|date'
|
||||
]);
|
||||
|
||||
$permohonanIds = $request->permohonan_ids;
|
||||
$memoNumber = $request->memo_number;
|
||||
$paymentDate = $request->payment_date;
|
||||
$memoDate = $request->memo_date;
|
||||
|
||||
// Update status permohonan yang dipilih
|
||||
foreach ($permohonanIds as $permohonanId) {
|
||||
$permohonan = Permohonan::find($permohonanId);
|
||||
if ($permohonan) {
|
||||
$permohonan->status = 'memo-penyelesaian';
|
||||
$permohonan->memo_penyelesaian_number = $memoNumber;
|
||||
$permohonan->memo_penyelesaian_date = $memoDate;
|
||||
$permohonan->memo_penyelesaian_payment_date = $paymentDate;
|
||||
$permohonan->memo_penyelesaian_created_at = now();
|
||||
//$permohonan->save();
|
||||
|
||||
Log::info('MemoController: Berhasil update permohonan ID: ' . $permohonanId);
|
||||
}
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
Log::info('MemoController: Berhasil menyimpan memo penyelesaian untuk ' . count($permohonanIds) . ' permohonan');
|
||||
|
||||
return redirect()->route('memo.index')
|
||||
->with('success', 'Memo penyelesaian berhasil dibuat untuk ' . count($permohonanIds) . ' permohonan');
|
||||
|
||||
} catch (Exception $e) {
|
||||
DB::rollback();
|
||||
Log::error('MemoController: Error saat menyimpan memo penyelesaian - ' . $e->getMessage());
|
||||
|
||||
return redirect()->back()
|
||||
->withInput()
|
||||
->with('error', 'Terjadi kesalahan saat menyimpan memo penyelesaian: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Menampilkan detail memo penyelesaian
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function show($id)
|
||||
{
|
||||
Log::info('MemoController: Mengakses detail memo penyelesaian ID: ' . $id);
|
||||
|
||||
$permohonan = Permohonan::with([
|
||||
'user',
|
||||
'debiture',
|
||||
'branch',
|
||||
'tujuanPenilaian',
|
||||
'penilaian',
|
||||
'jenisFasilitasKredit',
|
||||
'documents.inspeksi',
|
||||
'penilai',
|
||||
'documents.detail',
|
||||
'noc'
|
||||
])->findOrFail($id);
|
||||
|
||||
return view('lpj::memo.show', compact('permohonan'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Mengambil data untuk datatables pada halaman memo penyelesaian
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function dataForDatatables(Request $request)
|
||||
{
|
||||
Log::info('MemoController: Mengambil data untuk datatables');
|
||||
|
||||
if (is_null($this->user) || !$this->user->can('debitur.view')) {
|
||||
Log::warning('MemoController: User tidak memiliki permission untuk melihat data');
|
||||
// abort(403, 'Sorry! You are not allowed to view users.');
|
||||
}
|
||||
|
||||
// Mengambil data dari database dengan kondisi yang sama seperti LaporanController
|
||||
$query = Permohonan::query()
|
||||
->whereIn('status', ['proses-laporan', 'done', 'paparan', 'proses-paparan', 'memo-penyelesaian'])
|
||||
/*->whereNotNull('approval_so_at')
|
||||
->whereNotNull('approval_eo_at')
|
||||
->where(function ($q) {
|
||||
$q->whereIn('nilai_plafond_id', [1, 4])
|
||||
->whereNotNull('approval_dd_at')
|
||||
->orWhereIn('nilai_plafond_id', [2, 3]);
|
||||
})*/
|
||||
->whereHas('noc'); // Hanya tampilkan permohonan yang memiliki NOC
|
||||
|
||||
|
||||
$query = $query->orderBy('nomor_registrasi', 'desc');
|
||||
|
||||
// Apply search filter jika ada
|
||||
if ($request->has('search') && !empty($request->get('search'))) {
|
||||
$searchParams = explode('|', $request->get('search'));
|
||||
|
||||
$filterJenisPenilaian = $searchParams[0] ?? '';
|
||||
$searchTerm = $searchParams[1] ?? '';
|
||||
|
||||
// Filter berdasarkan jenis penilaian
|
||||
if (!empty($filterJenisPenilaian)) {
|
||||
$query->where('jenis_penilaian_id', $filterJenisPenilaian);
|
||||
Log::info('Applied jenis penilaian filter', ['filter' => $filterJenisPenilaian]);
|
||||
}
|
||||
|
||||
$query->where(function ($q) use ($searchTerm) {
|
||||
$q->where('nomor_registrasi', 'LIKE', '%' . $searchTerm . '%');
|
||||
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $searchTerm . '%');
|
||||
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $searchTerm . '%');
|
||||
$q->orWhereRelation('debiture', 'name', 'LIKE', '%' . $searchTerm . '%');
|
||||
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $searchTerm . '%');
|
||||
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $searchTerm . '%');
|
||||
$q->orWhere('status', 'LIKE', '%' . $searchTerm . '%');
|
||||
});
|
||||
}
|
||||
|
||||
// Apply sorting jika ada
|
||||
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
|
||||
$order = $request->get('sortOrder');
|
||||
$column = $request->get('sortField');
|
||||
$query->orderBy($column, $order);
|
||||
}
|
||||
|
||||
// Mendapatkan total count records
|
||||
$totalRecords = $query->count();
|
||||
$size = $request->get('size', 10);
|
||||
if ($size == 0) {
|
||||
$size = 10;
|
||||
}
|
||||
|
||||
// Apply pagination jika ada
|
||||
if ($request->has('page') && $request->has('size')) {
|
||||
$page = $request->get('page');
|
||||
$size = $request->get('size');
|
||||
$offset = ($page - 1) * $size;
|
||||
|
||||
$query->skip($offset)->take($size);
|
||||
}
|
||||
|
||||
// Mendapatkan filtered count records
|
||||
$filteredRecords = $query->count();
|
||||
|
||||
// Mendapatkan data untuk halaman saat ini
|
||||
$data = $query->with([
|
||||
'user',
|
||||
'debiture',
|
||||
'branch',
|
||||
'tujuanPenilaian',
|
||||
'jenisPenilaian',
|
||||
'penilaian',
|
||||
'jenisFasilitasKredit',
|
||||
'documents.inspeksi',
|
||||
'penilai',
|
||||
'documents.detail',
|
||||
'noc'
|
||||
])->get();
|
||||
|
||||
// Menghitung page count
|
||||
$pageCount = ceil($totalRecords / $size);
|
||||
|
||||
// Menghitung current page number
|
||||
$currentPage = max(1, $request->get('page', 1));
|
||||
|
||||
Log::info('MemoController: Berhasil mengambil data datatables - Total: ' . $totalRecords . ', Filtered: ' . $filteredRecords);
|
||||
|
||||
// Return response data sebagai JSON object
|
||||
return response()->json([
|
||||
'draw' => $request->get('draw'),
|
||||
'recordsTotal' => $totalRecords,
|
||||
'recordsFiltered' => $filteredRecords,
|
||||
'pageCount' => $pageCount,
|
||||
'page' => $currentPage,
|
||||
'totalCount' => $totalRecords,
|
||||
'data' => $data,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mengambil total biaya PJ berdasarkan permohonan yang dipilih
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function getTotalBiayaPJ(Request $request)
|
||||
{
|
||||
Log::info('MemoController: Mengambil total biaya PJ');
|
||||
|
||||
try {
|
||||
$permohonanIds = $request->get('permohonan_ids', []);
|
||||
|
||||
// Pastikan $permohonanIds selalu berupa array
|
||||
if (is_string($permohonanIds)) {
|
||||
$permohonanIds = explode(',', $permohonanIds);
|
||||
}
|
||||
|
||||
// Filter array untuk menghilangkan nilai kosong
|
||||
$permohonanIds = array_filter($permohonanIds, function($id) {
|
||||
return !empty(trim($id));
|
||||
});
|
||||
|
||||
$totalBiayaPJ = 0;
|
||||
|
||||
if (!empty($permohonanIds) && count($permohonanIds) > 0) {
|
||||
// Hitung total biaya PJ dari nominal_bayar di tabel NOC
|
||||
$totalBiayaPJ = \Modules\Lpj\Models\Noc::whereIn('permohonan_id', $permohonanIds)
|
||||
->sum('nominal_bayar');
|
||||
}
|
||||
|
||||
Log::info('MemoController: Total Biaya PJ berhasil dihitung: ' . $totalBiayaPJ);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'total_biaya_pj' => $totalBiayaPJ,
|
||||
'total_biaya_pj_formatted' => 'Rp ' . number_format($totalBiayaPJ, 0, ',', '.')
|
||||
]);
|
||||
|
||||
} catch (Exception $e) {
|
||||
Log::error('MemoController: Error saat menghitung total biaya PJ - ' . $e->getMessage());
|
||||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Terjadi kesalahan saat menghitung total biaya PJ'
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Menampilkan preview memo penyelesaian sebelum menyimpan
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function preview(Request $request)
|
||||
{
|
||||
Log::info('MemoController: Mengakses halaman preview memo penyelesaian');
|
||||
|
||||
|
||||
$permohonanIds = $request->permohonan_ids;
|
||||
$memoNumber = $request->memo_number;
|
||||
$paymentDate = $request->payment_date;
|
||||
$memoDate = $request->memo_date;
|
||||
|
||||
try {
|
||||
// Ambil data permohonan yang dipilih
|
||||
$permohonanList = Permohonan::with([
|
||||
'user',
|
||||
'debiture',
|
||||
'branch',
|
||||
'penilaian',
|
||||
'jenisPenilaian',
|
||||
'jenisFasilitasKredit',
|
||||
'documents.inspeksi',
|
||||
'penilai',
|
||||
'documents.detail',
|
||||
'noc'
|
||||
])->whereIn('id', $permohonanIds);
|
||||
|
||||
// Hitung total biaya PJ dari nominal_bayar di tabel NOC
|
||||
$totalBiayaPJ = Noc::whereIn('permohonan_id', $permohonanIds)
|
||||
->sum('nominal_bayar');
|
||||
|
||||
// Data untuk template memo
|
||||
$memoData = [
|
||||
'memo_number' => $memoNumber,
|
||||
'memo_date' => $memoDate,
|
||||
'payment_date' => $paymentDate,
|
||||
'total_biaya_pj' => $totalBiayaPJ,
|
||||
'permohonan_list' => $permohonanList->get(),
|
||||
'debitur_count' => $permohonanList->get()->count(),
|
||||
'jaminan_info' => $this->getJaminanInfo($permohonanList->get()),
|
||||
'jenisPenilaian' => $permohonanList->pluck('jenis_penilaian_id')->first()
|
||||
];
|
||||
|
||||
$permohonanList= $permohonanList->get();
|
||||
|
||||
Log::info('MemoController: Data preview memo berhasil disiapkan');
|
||||
|
||||
return view('lpj::memo.preview', compact('memoData', 'permohonanList', 'totalBiayaPJ'));
|
||||
|
||||
} catch (Exception $e) {
|
||||
Log::error('MemoController: Error saat menyiapkan preview memo - ' . $e->getMessage());
|
||||
return redirect()->back()
|
||||
->withInput()
|
||||
->with('error', 'Terjadi kesalahan saat menyiapkan preview memo: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate PDF memo penyelesaian dan simpan ke database
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function generatePdf(Request $request)
|
||||
{
|
||||
Log::info('MemoController: Memulai generate PDF memo penyelesaian');
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
try {
|
||||
// Validasi input
|
||||
|
||||
$permohonanIds = $request->permohonan_ids;
|
||||
$memoNumber = $request->memo_number;
|
||||
$paymentDate = $request->payment_date;
|
||||
$memoDate = $request->memo_date;
|
||||
|
||||
// Ambil data permohonan yang dipilih
|
||||
$permohonanList = Permohonan::with([
|
||||
'user',
|
||||
'debiture',
|
||||
'branch',
|
||||
'penilaian',
|
||||
'jenisPenilaian',
|
||||
'jenisFasilitasKredit',
|
||||
'documents.inspeksi',
|
||||
'penilai',
|
||||
'documents.detail',
|
||||
'noc'
|
||||
])->whereIn('id', $permohonanIds);
|
||||
|
||||
// Hitung total biaya PJ dari nominal_bayar di tabel NOC
|
||||
$totalBiayaPJ = Noc::whereIn('permohonan_id', $permohonanIds)
|
||||
->sum('nominal_bayar');
|
||||
|
||||
// Data untuk template memo
|
||||
$memoData = [
|
||||
'memo_number' => $memoNumber,
|
||||
'memo_date' => $memoDate,
|
||||
'payment_date' => $paymentDate,
|
||||
'total_biaya_pj' => $totalBiayaPJ,
|
||||
'permohonan_list' => $permohonanList->get(),
|
||||
'debitur_count' => $permohonanList->get()->count(),
|
||||
'jaminan_info' => $this->getJaminanInfo($permohonanList->get()),
|
||||
'jenisPenilaian' => $permohonanList->pluck('jenis_penilaian_id')->first()
|
||||
];
|
||||
|
||||
$permohonanList= $permohonanList->get();
|
||||
|
||||
// Generate PDF dari template
|
||||
$pdf = Pdf::loadView('lpj::memo.pdf-template', compact('memoData', 'permohonanList', 'totalBiayaPJ'))
|
||||
->setPaper('a4', 'portrait')
|
||||
->setOptions([
|
||||
'defaultFont' => 'Times-Roman',
|
||||
'isRemoteEnabled' => true,
|
||||
'isHtml5ParserEnabled' => true,
|
||||
'isPhpEnabled' => true,
|
||||
'dpi' => 150,
|
||||
'defaultPaperSize' => 'a4',
|
||||
'chroot' => public_path(),
|
||||
]);
|
||||
|
||||
// Nama file PDF
|
||||
$fileName = 'memo-penyelesaian-' . str_replace(['/', ' '], ['-', '-'], $memoNumber) . '-' . date('Y-m-d-H-i-s') . '.pdf';
|
||||
$filePath = 'memo-penyelesaian/' . $fileName;
|
||||
|
||||
// Simpan PDF ke storage
|
||||
Storage::disk('public')->put($filePath, $pdf->output());
|
||||
|
||||
// Update status permohonan yang dipilih
|
||||
// Update data di tabel NOC untuk setiap permohonan
|
||||
foreach ($permohonanIds as $permohonanId) {
|
||||
// Cari NOC berdasarkan permohonan_id
|
||||
$noc = Noc::where('permohonan_id', $permohonanId)->first();
|
||||
|
||||
if ($noc) {
|
||||
// Update field memo penyelesaian di tabel NOC
|
||||
$noc->memo_penyelesaian = $filePath;
|
||||
$noc->memo_penyelesaian_number = $memoNumber;
|
||||
$noc->memo_penyelesaian_date = $memoDate;
|
||||
$noc->memo_penyelesaian_payment_date = $paymentDate;
|
||||
$noc->memo_penyelesaian_created_at = now();
|
||||
$noc->save();
|
||||
|
||||
Log::info('MemoController: Berhasil update NOC untuk permohonan ID: ' . $permohonanId);
|
||||
} else {
|
||||
Log::warning('MemoController: NOC tidak ditemukan untuk permohonan ID: ' . $permohonanId);
|
||||
}
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
Log::info('MemoController: Berhasil generate PDF dan menyimpan memo penyelesaian untuk ' . count($permohonanIds) . ' permohonan');
|
||||
|
||||
// Return PDF untuk download
|
||||
return $pdf->download('memo-penyelesaian-' . $memoNumber . '.pdf');
|
||||
|
||||
} catch (Exception $e) {
|
||||
DB::rollback();
|
||||
Log::error('MemoController: Error saat generate PDF memo penyelesaian - ' . $e->getMessage());
|
||||
|
||||
return redirect()->back()
|
||||
->with('error', 'Terjadi kesalahan saat generate PDF memo penyelesaian: ' . $e->getMessage())
|
||||
->withInput();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function untuk mendapatkan informasi jaminan
|
||||
*
|
||||
* @param $permohonanList
|
||||
* @return string
|
||||
*/
|
||||
private function getJaminanInfo($permohonanList)
|
||||
{
|
||||
$jaminanTypes = [];
|
||||
foreach ($permohonanList as $permohonan) {
|
||||
if ($permohonan->tujuanPenilaian) {
|
||||
$jaminanTypes[] = $permohonan->tujuanPenilaian->name;
|
||||
}
|
||||
}
|
||||
|
||||
$uniqueJaminan = array_unique($jaminanTypes);
|
||||
return implode(' & ', $uniqueJaminan);
|
||||
}
|
||||
/**
|
||||
* Download PDF memo penyelesaian
|
||||
*
|
||||
* @param int $id - ID permohonan
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function downloadPdf($id)
|
||||
{
|
||||
Log::info('MemoController: Download PDF memo penyelesaian untuk permohonan ID: ' . $id);
|
||||
|
||||
try {
|
||||
// Cari NOC berdasarkan permohonan_id
|
||||
$noc = Noc::where('permohonan_id', $id)->first();
|
||||
|
||||
if (!$noc || !$noc->memo_penyelesaian) {
|
||||
Log::warning('MemoController: PDF memo penyelesaian tidak ditemukan untuk permohonan ID: ' . $id);
|
||||
return redirect()->back()->with('error', 'File PDF memo penyelesaian tidak ditemukan.');
|
||||
}
|
||||
|
||||
// Cek apakah file ada di storage
|
||||
if (!Storage::disk('public')->exists($noc->memo_penyelesaian)) {
|
||||
Log::warning('MemoController: File PDF tidak ada di storage: ' . $noc->memo_penyelesaian);
|
||||
return redirect()->back()->with('error', 'File PDF tidak ditemukan di server.');
|
||||
}
|
||||
|
||||
// Download file
|
||||
$fileName = 'memo-penyelesaian-' . $noc->memo_penyelesaian_number . '.pdf';
|
||||
|
||||
Log::info('MemoController: Berhasil download PDF memo penyelesaian: ' . $fileName);
|
||||
|
||||
return Storage::disk('public')->download($noc->memo_penyelesaian, $fileName);
|
||||
|
||||
} catch (Exception $e) {
|
||||
Log::error('MemoController: Error saat download PDF memo penyelesaian - ' . $e->getMessage());
|
||||
return redirect()->back()->with('error', 'Terjadi kesalahan saat mengunduh file PDF.');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,8 @@
|
||||
use App\Http\Controllers\Controller;
|
||||
use Exception;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
use Modules\Lpj\Exports\NilaiPlafondExport;
|
||||
use Modules\Lpj\Http\Requests\NilaiPlafondRequest;
|
||||
@@ -14,137 +16,239 @@
|
||||
{
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* Menampilkan halaman daftar Nilai Plafond.
|
||||
* Log setiap akses dan sebelum return view.
|
||||
*/
|
||||
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)
|
||||
{
|
||||
Log::info('NilaiPlafondController@store: mulai proses simpan');
|
||||
$validate = $request->validated();
|
||||
|
||||
if ($validate) {
|
||||
DB::beginTransaction();
|
||||
try {
|
||||
// Save to database
|
||||
NilaiPlafond::create($validate);
|
||||
return redirect()
|
||||
$record = NilaiPlafond::create($validate);
|
||||
DB::commit();
|
||||
|
||||
Log::info('NilaiPlafondController@store: simpan berhasil', ['id' => $record->id]);
|
||||
return \redirect()
|
||||
->route('basicdata.nilai-plafond.index')
|
||||
->with('success', 'Jenis Aset created successfully');
|
||||
->with('success', 'Nilai Plafond berhasil dibuat');
|
||||
} catch (Exception $e) {
|
||||
return redirect()
|
||||
DB::rollBack();
|
||||
Log::error('NilaiPlafondController@store: simpan gagal', ['error' => $e->getMessage()]);
|
||||
|
||||
return \redirect()
|
||||
->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()
|
||||
{
|
||||
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)
|
||||
{
|
||||
$nilaiPlafond = NilaiPlafond::find($id);
|
||||
return view('lpj::nilai_plafond.create', compact('nilaiPlafond'));
|
||||
Log::info('NilaiPlafondController@edit: mulai proses edit', ['id' => $id]);
|
||||
|
||||
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)
|
||||
{
|
||||
Log::info('NilaiPlafondController@update: mulai proses update', ['id' => $id]);
|
||||
$validate = $request->validated();
|
||||
|
||||
if ($validate) {
|
||||
DB::beginTransaction();
|
||||
try {
|
||||
// Update in database
|
||||
$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);
|
||||
return redirect()
|
||||
DB::commit();
|
||||
|
||||
Log::info('NilaiPlafondController@update: update berhasil', ['id' => $id]);
|
||||
return \redirect()
|
||||
->route('basicdata.nilai-plafond.index')
|
||||
->with('success', 'Jenis Aset updated successfully');
|
||||
->with('success', 'Nilai Plafond berhasil diperbarui');
|
||||
} 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)
|
||||
->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)
|
||||
{
|
||||
Log::info('NilaiPlafondController@destroy: mulai proses hapus', ['id' => $id]);
|
||||
DB::beginTransaction();
|
||||
try {
|
||||
// Delete from database
|
||||
$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) {
|
||||
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)
|
||||
{
|
||||
Log::info('NilaiPlafondController@dataForDatatables: mulai proses');
|
||||
|
||||
if (is_null($this->user) || !$this->user->can('nilai_plafond.view')) {
|
||||
//abort(403, 'Sorry! You are not allowed to view users.');
|
||||
}
|
||||
|
||||
// Retrieve data from the database
|
||||
$query = NilaiPlafond::query();
|
||||
DB::beginTransaction();
|
||||
try {
|
||||
// Retrieve data from the database
|
||||
$query = NilaiPlafond::query();
|
||||
|
||||
// Apply search filter if provided
|
||||
if ($request->has('search') && !empty($request->get('search'))) {
|
||||
$search = $request->get('search');
|
||||
$query->where(function ($q) use ($search) {
|
||||
$q->where('code', 'LIKE', "%$search%");
|
||||
$q->orWhere('name', 'LIKE', "%$search%");
|
||||
});
|
||||
// Apply search filter if provided
|
||||
if ($request->has('search') && !empty($request->get('search'))) {
|
||||
$search = $request->get('search');
|
||||
$query->where(function ($q) use ($search) {
|
||||
$q->where('code', '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()
|
||||
{
|
||||
Log::info('NilaiPlafondController@export: mulai proses export');
|
||||
return Excel::download(new NilaiPlafondExport, 'nilai_plafond.xlsx');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,9 +6,10 @@
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Modules\Lpj\Http\Requests\NocRequest;
|
||||
use Modules\Lpj\Models\PenawaranTender;
|
||||
use Modules\Lpj\Models\Permohonan;
|
||||
use Modules\Lpj\Models\Bucok;
|
||||
use Modules\Lpj\Models\Noc;
|
||||
use Modules\Lpj\Models\PersetujuanPenawaran;
|
||||
use Modules\Lpj\Models\JenisPenilaian;
|
||||
|
||||
class NocController extends Controller
|
||||
{
|
||||
@@ -18,9 +19,22 @@
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return redirect()->route('noc.pembayaran.index');
|
||||
}
|
||||
|
||||
public function pembayaran()
|
||||
{
|
||||
$persetujuanPenawarans = PersetujuanPenawaran::all();
|
||||
return view('lpj::noc.index', compact('persetujuanPenawarans'));
|
||||
$jenisPenilaians = JenisPenilaian::get();
|
||||
return view('lpj::noc.pembayaran', compact('persetujuanPenawarans', 'jenisPenilaians'));
|
||||
}
|
||||
|
||||
public function penyelesaian()
|
||||
{
|
||||
$persetujuanPenawarans = PersetujuanPenawaran::all();
|
||||
$jenisPenilaians = JenisPenilaian::get();
|
||||
return view('lpj::noc.penyelesaian', compact('persetujuanPenawarans', 'jenisPenilaians'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -35,53 +49,63 @@
|
||||
public function store(NocRequest $request)
|
||||
{
|
||||
$validated = $request->validated();
|
||||
|
||||
|
||||
$validated['updated_by'] = Auth::id();
|
||||
if (request()->get('status_bayar') == "sudah_bayar") {
|
||||
$validated['status'] = '1';
|
||||
$status = "spk";
|
||||
} else {
|
||||
$status = "persetujuan-penawaran";
|
||||
}
|
||||
|
||||
$persetujuanPenawaran = PersetujuanPenawaran::updateOrCreate(
|
||||
['penawaran_id' => $validated['penawaran_id']],
|
||||
$validated,
|
||||
);
|
||||
$dataNoc = [
|
||||
'nominal_bayar' => $validated['nominal_bayar'],
|
||||
'total_pembukuan' => $validated['total_pembukuan'],
|
||||
'tanggal_pembayaran' => $validated['tanggal_pembayaran'] ?? date('Y-m-d'),
|
||||
'status_bayar' => $validated['nominal_bayar'] < $validated['total_harus_bayar'] ? false : true,
|
||||
'catatan_noc' => $validated['catatan_noc'] ?? '',
|
||||
'status_kurang_bayar' => $validated['status_kurang_bayar'] ?? '0',
|
||||
'status_lebih_bayar' => $validated['status_lebih_bayar'] ?? '0',
|
||||
'nominal_kurang_bayar' => $validated['nominal_kurang_bayar'] ?? '0',
|
||||
'nominal_lebih_bayar' => $validated['nominal_lebih_bayar'] ?? '0',
|
||||
'bukti_pengembalian' => $validated['bukti_pengembalian'] ?? '',
|
||||
];
|
||||
|
||||
$folderPath = 'noc/' . $validated['penawaran_id'];
|
||||
if($validated['permohonan_id']){
|
||||
$noc = Noc::updateOrCreate(
|
||||
[
|
||||
'permohonan_id' => $validated['permohonan_id'],
|
||||
'persetujuan_penawaran_id' => $validated['persetujuan_penawaran_id'],
|
||||
],
|
||||
$dataNoc,
|
||||
);
|
||||
} else {
|
||||
$noc = Noc::updateOrCreate(
|
||||
[
|
||||
'persetujuan_penawaran_id' => $validated['persetujuan_penawaran_id'],
|
||||
],
|
||||
$dataNoc,
|
||||
);
|
||||
}
|
||||
|
||||
$folderPath = 'noc/' . request()->get('persetujuan_penawaran_id') . '/bukti_ksl/';
|
||||
|
||||
if ($request->hasFile('bukti_ksl')) {
|
||||
$persetujuanPenawaran->bukti_ksl = $request->file('bukti_ksl')->store(
|
||||
$noc->bukti_ksl = $request->file('bukti_ksl')->store(
|
||||
$folderPath,
|
||||
'public',
|
||||
);
|
||||
}
|
||||
$noc->save();
|
||||
|
||||
$persetujuanPenawaran->save();
|
||||
|
||||
// Update the status of the related permohonan to 'spk'
|
||||
$permohonan = Permohonan::find(request()->get('permohonan_id'));
|
||||
if ($permohonan) {
|
||||
$permohonan->status_bayar = request()->get('status_bayar');
|
||||
if($permohonan->jenis_penilaian_id==2) {
|
||||
$permohonan->status = $status;
|
||||
}
|
||||
$permohonan->save();
|
||||
|
||||
// andy add, update status penawaran.status='spk'
|
||||
// $penawaran = PenawaranTender::where('nomor_registrasi',$permohonan->nomor_registrasi)->first();
|
||||
if($permohonan->jenis_penilaian_id==2) {
|
||||
PenawaranTender::where('nomor_registrasi', $permohonan->nomor_registrasi)->update([
|
||||
'status' => $status,
|
||||
'updated_by' => Auth::id(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
}
|
||||
// andy add, update status penawaran.status='spk'
|
||||
$bucok = Bucok::where('nomor_tiket', $noc->nomor_tiket)->orWhere('permohonan_id', $noc->permohonan_id)->first();
|
||||
if($bucok){
|
||||
$bucok->nominal_penyelesaian = $noc->total_pembukuan ?? '';
|
||||
$bucok->tanggal_penyelesaian = $noc->tanggal_pembayaran ?? date('Y-m-d');
|
||||
$bucok->penyelesaian = 'Selesai';
|
||||
$bucok->save();
|
||||
}
|
||||
|
||||
return redirect()
|
||||
->route('noc.index')->with('success', 'Penyelesaian KSL berhasil disimpan.');
|
||||
->route('noc.index')->with('success', 'NOC berhasil disimpan.');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,13 +113,60 @@
|
||||
*/
|
||||
public function update(NocRequest $request, PersetujuanPenawaran $persetujuanPenawaran)
|
||||
{
|
||||
$validated = $request->validated();
|
||||
$validated['updated_by'] = Auth::id();
|
||||
$validated = $request->validated();
|
||||
|
||||
|
||||
if($request->get('is_memo')){
|
||||
|
||||
$memo = Noc::find($request->get('is_memo'));
|
||||
|
||||
$folderPath = 'noc/' . request()->get('persetujuan_penawaran_id') . '/memo_penyelesaian/';
|
||||
|
||||
if ($request->hasFile('memo_penyelesaian')) {
|
||||
$memo->memo_penyelesaian = $request->file('memo_penyelesaian')->store(
|
||||
$folderPath,
|
||||
'public',
|
||||
);
|
||||
}
|
||||
|
||||
$memo->catatan_noc = $validated['catatan_noc'];
|
||||
$memo->save();
|
||||
|
||||
|
||||
return redirect()
|
||||
->route('laporan.index')->with('success', 'Memo Penyelesaian updated successfully');
|
||||
}
|
||||
$dataNoc = [
|
||||
'total_pembukuan' => $validated['total_pembukuan'],
|
||||
'nominal_penyelesaian' => $validated['nominal_penyelesaian'],
|
||||
'tanggal_penyelesaian' => $validated['tanggal_penyelesaian'] ?? date('Y-m-d'),
|
||||
'status_pelunasan' => ((int)$validated['nominal_bayar'] + (int)$validated['nominal_penyelesaian']) === (int)$validated['total_harus_bayar'] ? true : false,
|
||||
'catatan_noc' => $validated['catatan_noc'],
|
||||
];
|
||||
|
||||
|
||||
$noc = Noc::updateOrCreate(
|
||||
[
|
||||
'permohonan_id' => $validated['permohonan_id'],
|
||||
'permohonan_id' => $validated['permohonan_id'],
|
||||
'persetujuan_penawaran_id' => $validated['persetujuan_penawaran_id'],
|
||||
],
|
||||
$dataNoc,
|
||||
);
|
||||
|
||||
$folderPath = 'noc/' . request()->get('persetujuan_penawaran_id') . '/bukti_penyelesaian/';
|
||||
|
||||
if ($request->hasFile('bukti_penyelesaian')) {
|
||||
$noc->bukti_penyelesaian = $request->file('bukti_penyelesaian')->store(
|
||||
$folderPath,
|
||||
'public',
|
||||
);
|
||||
}
|
||||
$noc->save();
|
||||
|
||||
$persetujuanPenawaran->update($validated);
|
||||
|
||||
return redirect()
|
||||
->route('noc.index')->with('success', 'Persetujuan Penawaran updated successfully');
|
||||
->route('noc.index')->with('success', 'NOC updated successfully');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -109,16 +180,16 @@
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*/
|
||||
public function show($id) {}
|
||||
public function show(Noc $noc) {
|
||||
return view('lpj::noc.memo', compact('noc'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*/
|
||||
public function edit($id)
|
||||
{
|
||||
$persetujuanPenawaran = PersetujuanPenawaran::where('id', $id)->with(
|
||||
['penawaran.detail', 'penawaran.permohonan.debiture','permohonan'],
|
||||
)->first();
|
||||
$persetujuanPenawaran = PersetujuanPenawaran::where('id', $id)->first();
|
||||
return view('lpj::noc.form', compact('persetujuanPenawaran'));
|
||||
}
|
||||
|
||||
@@ -134,6 +205,12 @@
|
||||
}
|
||||
|
||||
public function dataForDatatables(Request $request)
|
||||
{
|
||||
// Redirect to pembayaran datatables by default
|
||||
return $this->dataForDatatablesPembayaran($request);
|
||||
}
|
||||
|
||||
public function dataForDatatablesPembayaran(Request $request)
|
||||
{
|
||||
if (is_null($this->user) || !$this->user->can('noc.view')) {
|
||||
//abort(403, 'Sorry! You are not allowed to view persetujuan penawaran.');
|
||||
@@ -142,11 +219,20 @@
|
||||
// Retrieve data from the database
|
||||
$query = PersetujuanPenawaran::query();
|
||||
|
||||
// Filter for pembayaran (where memo_penyelesaian is null)
|
||||
/*$query->whereDoesntHave('noc', function($q) {
|
||||
$q->whereNotNull('memo_penyelesaian');
|
||||
});*/
|
||||
|
||||
// Apply search filter if provided
|
||||
if ($request->has('search') && !empty($request->get('search'))) {
|
||||
$search = $request->get('search');
|
||||
$query->where(function ($q) use ($search) {
|
||||
$q->orWhereRelation('penawaran', 'nomor_registrasi', '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 . '%');
|
||||
});
|
||||
}
|
||||
|
||||
@@ -173,18 +259,38 @@
|
||||
$filteredRecords = $query->count();
|
||||
|
||||
// Get the data for the current page
|
||||
$data = $query
|
||||
->with(
|
||||
[
|
||||
'penawaran.permohonan.debiture',
|
||||
'penawaran.permohonan.branch',
|
||||
'permohonan.debiture',
|
||||
'permohonan.branch',
|
||||
'penawaran.detail',
|
||||
'penawaran.persetujuan',
|
||||
],
|
||||
)->get();
|
||||
$data = $query->get();
|
||||
|
||||
$data = $data->map(function ($persetujuanPenawaran) {
|
||||
return [
|
||||
'id' => $persetujuanPenawaran->id,
|
||||
'nomor_registrasi' => $persetujuanPenawaran->permohonan?->nomor_registrasi ?? $persetujuanPenawaran->penawaran?->nomor_registrasi,
|
||||
'nomor_tiket' => $persetujuanPenawaran->nomor_tiket ?? '',
|
||||
'nama_debitur' => $persetujuanPenawaran?->permohonan?->debiture->name ?? $persetujuanPenawaran->penawaran?->permohonan?->debiture->name ?? $persetujuanPenawaran->noc?->debiture->name,
|
||||
'kode_cabang' => $persetujuanPenawaran?->permohonan?->branch->code ?? $persetujuanPenawaran->penawaran?->permohonan?->branch->code ?? $persetujuanPenawaran->noc?->branch->code,
|
||||
'cabang' => $persetujuanPenawaran?->permohonan?->branch->name ?? $persetujuanPenawaran->penawaran?->permohonan?->branch->name ?? $persetujuanPenawaran->noc?->branch->name,
|
||||
'tanggal_pembayaran' => dateFormat(
|
||||
$persetujuanPenawaran->noc->tanggal_pembayaran ?? $persetujuanPenawaran->noc?->created_at,
|
||||
true,
|
||||
),
|
||||
'nominal_bayar' => currencyFormat($persetujuanPenawaran->nominal_bayar ?? 0,
|
||||
),
|
||||
'nominal_diterima' => currencyFormat(
|
||||
$persetujuanPenawaran->noc->nominal_bayar ?? 0,
|
||||
),
|
||||
'jenis_penilaian' => $persetujuanPenawaran->permohonan?->jenisPenilaian?->name ?? "",
|
||||
'bukti_ksl' => $persetujuanPenawaran->noc->bukti_ksl ?? $persetujuanPenawaran->bukti_ksl ?? null,
|
||||
'bukti_bayar' => $persetujuanPenawaran->bukti_bayar ?? null,
|
||||
'updated_at' => dateFormat($persetujuanPenawaran->updated_at, true),
|
||||
];
|
||||
})->sortBy('updated_at', 1)->values();
|
||||
|
||||
// Calculate total nominal diterima from all filtered data (not just current page)
|
||||
$totalNominalDiterima = $data->sum(function ($item) {
|
||||
// Extract numeric value from formatted currency string
|
||||
$nominal = str_replace(['Rp', '.', ',00'], '', $item['nominal_diterima']);
|
||||
return (float) $nominal;
|
||||
});
|
||||
|
||||
// Calculate the page count
|
||||
$pageCount = ceil($totalRecords / $request->get('size'));
|
||||
@@ -200,6 +306,121 @@
|
||||
'pageCount' => $pageCount,
|
||||
'page' => $currentPage,
|
||||
'totalCount' => $totalRecords,
|
||||
'totalNominalDiterima' => $totalNominalDiterima,
|
||||
'data' => $data,
|
||||
]);
|
||||
}
|
||||
|
||||
public function dataForDatatablesPenyelesaian(Request $request)
|
||||
{
|
||||
if (is_null($this->user) || !$this->user->can('noc.view')) {
|
||||
//abort(403, 'Sorry! You are not allowed to view persetujuan penawaran.');
|
||||
}
|
||||
|
||||
// Retrieve data from the database
|
||||
$query = PersetujuanPenawaran::query();
|
||||
|
||||
// Filter for penyelesaian (where memo_penyelesaian is not null)
|
||||
$query->whereDoesntHave('noc', function($q) {
|
||||
$q->whereNotNull('memo_penyelesaian');
|
||||
});
|
||||
|
||||
// Apply search filter if provided
|
||||
if ($request->has('search') && !empty($request->get('search'))) {
|
||||
$search = $request->get('search');
|
||||
$query->where(function ($q) use ($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 . '%'); $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 . '%');
|
||||
});
|
||||
}
|
||||
|
||||
// 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();
|
||||
|
||||
$data = $data->map(function ($persetujuanPenawaran) {
|
||||
return [
|
||||
'id' => $persetujuanPenawaran->id,
|
||||
'nomor_registrasi' => $persetujuanPenawaran->permohonan?->nomor_registrasi ?? $persetujuanPenawaran->penawaran?->nomor_registrasi ?? '',
|
||||
'nomor_tiket' => $persetujuanPenawaran->nomor_tiket ?? '',
|
||||
'nama_debitur' => $persetujuanPenawaran->permohonan?->debiture?->name ?? $persetujuanPenawaran->penawaran?->permohonan?->debiture?->name ?? $persetujuanPenawaran->noc?->debiture?->name,
|
||||
'kode_cabang' => $persetujuanPenawaran?->permohonan?->branch?->code ?? $persetujuanPenawaran->penawaran?->permohonan?->branch?->code ?? $persetujuanPenawaran->noc?->branch?->code ?? '',
|
||||
'cabang' => $persetujuanPenawaran->permohonan?->branch?->name ?? $persetujuanPenawaran->penawaran?->permohonan?->branch?->name ?? $persetujuanPenawaran->noc?->branch?->name ?? '',
|
||||
'tanggal_pembayaran' => dateFormat(
|
||||
$persetujuanPenawaran->noc->tanggal_pembayaran ?? $persetujuanPenawaran->noc?->created_at,
|
||||
true,
|
||||
),
|
||||
'nominal_bayar' => currencyFormat($persetujuanPenawaran->nominal_bayar ?? 0,
|
||||
),
|
||||
'nominal_diterima' => currencyFormat(
|
||||
$persetujuanPenawaran->noc->nominal_bayar ?? 0,
|
||||
),
|
||||
'jenis_penilaian' => $persetujuanPenawaran->permohonan?->jenisPenilaian?->name ?? "",
|
||||
'bukti_ksl' => $persetujuanPenawaran->noc->bukti_ksl ?? $persetujuanPenawaran->bukti_ksl ?? null,
|
||||
'bukti_bayar' => $persetujuanPenawaran->bukti_bayar ?? null,
|
||||
'memo_penyelesaian' => $persetujuanPenawaran->noc->memo_penyelesaian ?? $persetujuanPenawaran->memo_penyelesaian ?? null,
|
||||
'nominal_penyelesaian' => currencyFormat(
|
||||
$persetujuanPenawaran->noc->nominal_penyelesaian ?? $persetujuanPenawaran->nominal_penyelesaian ?? 0,
|
||||
),
|
||||
'bukti_penyelesaian' => $persetujuanPenawaran->noc->bukti_penyelesaian ?? $persetujuanPenawaran->bukti_penyelesaian ?? null,
|
||||
'tanggal_penyelesaian' => $persetujuanPenawaran->noc?->tanggal_penyelesaian ? dateFormat(
|
||||
$persetujuanPenawaran->noc?->tanggal_penyelesaian,
|
||||
true) : '-',
|
||||
'updated_at' => dateFormat($persetujuanPenawaran->updated_at, true),
|
||||
];
|
||||
})->sortBy('updated_at', 1)->values();
|
||||
|
||||
|
||||
// Calculate total nominal diterima from all filtered data (not just current page)
|
||||
$totalNominalDiterima = $data->sum(function ($item) {
|
||||
// Extract numeric value from formatted currency string
|
||||
$nominal = str_replace(['Rp', '.', ',00'], '', $item['nominal_diterima']);
|
||||
return (float) $nominal;
|
||||
});
|
||||
|
||||
// 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,
|
||||
'totalNominalDiterima' => $totalNominalDiterima,
|
||||
'data' => $data,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -3,26 +3,12 @@
|
||||
namespace Modules\Lpj\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Barryvdh\DomPDF\Facade\Pdf;
|
||||
use Exception;
|
||||
use Illuminate\Http\Request;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
use Modules\Location\Models\City;
|
||||
use Modules\Location\Models\District;
|
||||
use Modules\Location\Models\Province;
|
||||
use Modules\Location\Models\Village;
|
||||
use Modules\Lpj\Exports\PermohonanExport;
|
||||
use Modules\Lpj\Http\Requests\PermohonanRequest;
|
||||
use Modules\Lpj\Models\Branch;
|
||||
use Modules\Lpj\Models\Debiture;
|
||||
use Modules\Lpj\Models\DokumenJaminan;
|
||||
use Modules\Lpj\Models\JenisFasilitasKredit;
|
||||
use Modules\Lpj\Models\NilaiPlafond;
|
||||
use Modules\Lpj\Models\Permohonan;
|
||||
use Modules\Lpj\Models\PermohonanPembatalan;
|
||||
use Modules\Lpj\Models\StatusPermohonan;
|
||||
use Modules\Lpj\Models\TujuanPenilaian;
|
||||
use Modules\Lpj\Services\PermohonanHistoryService;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class PembatalanController extends Controller
|
||||
{
|
||||
@@ -92,6 +78,10 @@
|
||||
|
||||
// Retrieve data from the database
|
||||
$query = PermohonanPembatalan::query();
|
||||
if (Auth::user()->hasAnyRole(['pemohon-ao','pemohon-eo'])) {
|
||||
$query = $query->whereRelation('permohonan', 'branch_id', Auth::user()->branch_id);
|
||||
}
|
||||
|
||||
$query = $query->orderBy('created_at', 'desc');
|
||||
// Apply search filter if provided
|
||||
if ($request->has('search') && !empty($request->get('search'))) {
|
||||
|
||||
@@ -2,21 +2,17 @@
|
||||
|
||||
namespace Modules\Lpj\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Exception;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Modules\Lpj\Models\Noc;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
use Modules\Lpj\Http\Requests\PersetujuanPenawaranRequest;
|
||||
use Modules\Lpj\Models\PenawaranTender;
|
||||
use Modules\Lpj\Models\Bucok;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Modules\Lpj\Models\Permohonan;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Modules\Lpj\Models\PenawaranTender;
|
||||
use Modules\Lpj\Models\PersetujuanPenawaran;
|
||||
|
||||
// use Modules\Lpj\Models\JenisPenilaian;
|
||||
|
||||
// use Modules\Lpj\Models\Regions;
|
||||
use Modules\Lpj\Http\Requests\PersetujuanPenawaranRequest;
|
||||
|
||||
class PembayaranController extends Controller
|
||||
{
|
||||
@@ -27,6 +23,14 @@ class PembayaranController extends Controller
|
||||
return view('lpj::pembayaran.index');
|
||||
}
|
||||
|
||||
public function kurang(){
|
||||
return view('lpj::pembayaran.kurang');
|
||||
}
|
||||
|
||||
public function lebih(){
|
||||
return view('lpj::pembayaran.lebih');
|
||||
}
|
||||
|
||||
public function approval()
|
||||
{
|
||||
return view('lpj::pembayaran.approval');
|
||||
@@ -35,13 +39,16 @@ class PembayaranController extends Controller
|
||||
public function dataApprovalForDatatables(Request $request)
|
||||
{
|
||||
if (is_null($this->user) || !$this->user->can('noc.view')) {
|
||||
//abort(403, 'Sorry! You are not allowed to view persetujuan penawaran.');
|
||||
//abort(403, 'Sorry! You are not allowed to view persetujuan penawaran.');
|
||||
}
|
||||
|
||||
// Retrieve data from the database
|
||||
// Retrieve data from the database
|
||||
$query = PersetujuanPenawaran::query();
|
||||
if (Auth::user()->hasAnyRole(['pemohon-ao','pemohon-eo'])) {
|
||||
$query = $query->whereRelation('permohonan', 'branch_id', Auth::user()->branch_id);
|
||||
}
|
||||
|
||||
// Apply search filter if provided
|
||||
// Apply search filter if provided
|
||||
if ($request->has('search') && !empty($request->get('search'))) {
|
||||
$search = $request->get('search');
|
||||
$query->where(function ($q) use ($search) {
|
||||
@@ -49,29 +56,29 @@ class PembayaranController extends Controller
|
||||
});
|
||||
}
|
||||
|
||||
// Apply sorting if provided
|
||||
// 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
|
||||
// Get the total count of records
|
||||
$totalRecords = $query->count();
|
||||
|
||||
// Apply pagination if provided
|
||||
// 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
|
||||
$offset = ($page - 1) * $size; // Calculate the offset
|
||||
|
||||
$query->skip($offset)->take($size);
|
||||
}
|
||||
|
||||
// Get the filtered count of records
|
||||
// Get the filtered count of records
|
||||
$filteredRecords = $query->count();
|
||||
|
||||
// Get the data for the current page
|
||||
// Get the data for the current page
|
||||
$data = $query
|
||||
->with(
|
||||
[
|
||||
@@ -89,13 +96,13 @@ class PembayaranController extends Controller
|
||||
)->get();
|
||||
|
||||
|
||||
// Calculate the page count
|
||||
// Calculate the page count
|
||||
$pageCount = ceil($totalRecords / $request->get('size'));
|
||||
|
||||
// Calculate the current page number
|
||||
// Calculate the current page number
|
||||
$currentPage = $request->get('page', 1);
|
||||
|
||||
// Return the response data as a JSON object
|
||||
// Return the response data as a JSON object
|
||||
return response()->json([
|
||||
'draw' => $request->get('draw'),
|
||||
'recordsTotal' => $totalRecords,
|
||||
@@ -107,34 +114,130 @@ class PembayaranController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
public function create(){
|
||||
return view('lpj::pembayaran.create');
|
||||
}
|
||||
|
||||
public function edit($id)
|
||||
{
|
||||
$permohonan = Permohonan::find($id);
|
||||
|
||||
$persetujuanPenawaran = PersetujuanPenawaran::where('permohonan_id', $permohonan->id)->first();
|
||||
$req = request()->all();
|
||||
|
||||
if(isset($req['tiket'])){
|
||||
$persetujuanPenawaran = PersetujuanPenawaran::find($id);
|
||||
$permohonan = Permohonan::find($persetujuanPenawaran?->permohonan_id);
|
||||
} else {
|
||||
$permohonan = Permohonan::find($id);
|
||||
$persetujuanPenawaran = PersetujuanPenawaran::where('permohonan_id', $permohonan->id)->first();
|
||||
}
|
||||
|
||||
return view('lpj::pembayaran.form', compact('permohonan', 'persetujuanPenawaran'));
|
||||
}
|
||||
|
||||
public function editKurang($id){
|
||||
$noc = Noc::find($id);
|
||||
$permohonan = Permohonan::find($noc->permohonan_id);
|
||||
$persetujuanPenawaran = PersetujuanPenawaran::where('permohonan_id', $permohonan->id)->first();
|
||||
return view('lpj::pembayaran.form-kurang', compact('noc','permohonan','persetujuanPenawaran'));
|
||||
}
|
||||
|
||||
public function editLebih($id){
|
||||
$noc = Noc::find($id);
|
||||
$permohonan = Permohonan::find($noc->permohonan_id);
|
||||
$persetujuanPenawaran = PersetujuanPenawaran::where('permohonan_id', $permohonan->id)->first();
|
||||
return view('lpj::pembayaran.form-lebih', compact('noc','permohonan','persetujuanPenawaran'));
|
||||
}
|
||||
|
||||
public function store(PersetujuanPenawaranRequest $request)
|
||||
{
|
||||
$req = request()->all();
|
||||
|
||||
if(isset($req['type'])){
|
||||
if($req['type'] == 'create'){
|
||||
$data = [
|
||||
'nomor_tiket' => $req['nomor_tiket'] ?? '',
|
||||
'nominal_bayar' => $req['nominal_bayar'] ?? '',
|
||||
'catatan' => $req['catatan'] ?? ''
|
||||
];
|
||||
|
||||
if(request()->hasFile('bukti_bayar')){
|
||||
$folderPath = 'persetujuan_penawaran/bukti_bayar/' . $req['nomor_tiket'];
|
||||
$data['bukti_bayar'] = $request->file('bukti_bayar')->store($folderPath, 'public');
|
||||
}
|
||||
|
||||
$persetujuanPenawaran = PersetujuanPenawaran::create($data);
|
||||
$noc = [
|
||||
'persetujuan_penawaran_id' => $persetujuanPenawaran->id,
|
||||
'nomor_tiket' => $req['nomor_tiket'] ?? '',
|
||||
'debiture_id' => $req['debitur_id'] ?? '',
|
||||
'branch_id' => Auth::user()->branch_id,
|
||||
];
|
||||
$noc = Noc::create($noc);
|
||||
|
||||
$bucok = [
|
||||
'tanggal_penuh' => $persetujuanPenawaran->created_at ?? $noc->created_at,
|
||||
'tanggal' => $persetujuanPenawaran->created_at?->format('d') ?? $noc->created_at?->format('d'),
|
||||
'bulan' => $persetujuanPenawaran->created_at?->format('m') ?? $noc->created_at?->format('m'),
|
||||
'tahun' => $persetujuanPenawaran->created_at?->format('Y') ?? $noc->created_at?->format('Y'),
|
||||
'nomor_tiket' => $req['nomor_tiket'] ?? '',
|
||||
'nominal' => $req['nominal_bayar'] ?? '',
|
||||
'nominal_berjalan' => $req['nominal_bayar'] ?? '',
|
||||
'penyelesaian' => 'Belum Selesai',
|
||||
'nama_sub_direktorat' => $noc->branch?->name ?? '',
|
||||
'nama_direktorat_cabang' => $noc->branch?->name ?? '',
|
||||
];
|
||||
|
||||
Bucok::updateOrCreate([
|
||||
'nomor_tiket' => $req['nomor_tiket'] ?? '',
|
||||
], $bucok);
|
||||
|
||||
return redirect()
|
||||
->route('pembayaran.index')->with('success', 'Pembayaran berhasil disimpan.');
|
||||
}
|
||||
|
||||
if($req['type'] == 'kurang_bayar'){
|
||||
$noc = Noc::find($req['noc_id']);
|
||||
$noc->nominal_pelunasan = $req['nominal_pelunasan'];
|
||||
if (request()->hasFile('bukti_ksl_kurang_bayar')) {
|
||||
$folderPath = 'persetujuan_penawaran/bukti_ksl_kurang_bayar/' . $req['noc_id'];
|
||||
$noc->bukti_ksl_kurang_bayar = $request->file('bukti_ksl_kurang_bayar')->store($folderPath, 'public');
|
||||
}
|
||||
$noc->save();
|
||||
|
||||
$persetujuanPenawaran = PersetujuanPenawaran::find($noc->persetujuan_penawaran_id);
|
||||
$persetujuanPenawaran->bukti_ksl_kurang_bayar = $noc->bukti_ksl_kurang_bayar;
|
||||
$persetujuanPenawaran->nominal_kurang_bayar = $req['nominal_pelunasan'];
|
||||
$persetujuanPenawaran->save();
|
||||
return redirect()
|
||||
->route('pembayaran.kurang.index')->with('success', 'Pelunasan Kurang Bayar berhasil disimpan.');
|
||||
}
|
||||
|
||||
if($req['type'] == 'lebih_bayar'){
|
||||
$noc = Noc::find($req['noc_id']);
|
||||
if (request()->hasFile('bukti_ksl_lebih_bayar')) {
|
||||
$folderPath = 'persetujuan_penawaran/bukti_ksl_lebih_bayar/' . $req['noc_id'];
|
||||
$noc->bukti_ksl_lebih_bayar = $request->file('bukti_ksl_lebih_bayar')->store($folderPath, 'public');
|
||||
}
|
||||
$noc->save();
|
||||
|
||||
return redirect()
|
||||
->route('pembayaran.lebih.index')->with('success', 'Pengembalian Lebih Bayar berhasil disimpan.');
|
||||
}
|
||||
}
|
||||
|
||||
$validated = $request->validated();
|
||||
$validated['nominal_bayar'] = $req['nominal_bayar'] ?? 0;
|
||||
$validated['created_by'] = Auth::id();
|
||||
$validated['created_at'] = now();
|
||||
$validated['status'] = '0';
|
||||
|
||||
$persetujuanPenawaran = PersetujuanPenawaran::where('permohonan_id', $validated['permohonan_id'] ?? null)->first();
|
||||
$permohonan = Permohonan::find(request()->get('permohonan_id'));
|
||||
$permohonan = Permohonan::find(request()->get('permohonan_id'));
|
||||
if ($persetujuanPenawaran) {
|
||||
// if (isset($validated['penawaran_id'])) {
|
||||
|
||||
// $persetujuanPenawaran = PersetujuanPenawaran::create(
|
||||
// ['penawaran_id' => $validated['penawaran_id']],
|
||||
// $validated,
|
||||
// );
|
||||
|
||||
$persetujuanPenawaran->fill($validated);
|
||||
|
||||
if ($request->hasFile('bukti_bayar')) {
|
||||
$folderPath = 'persetujuan_penawaran/' . $validated['penawaran_id'];
|
||||
$folderPath = 'persetujuan_penawaran/' . $validated['penawaran_id'];
|
||||
$persetujuanPenawaran->bukti_bayar = $request->file('bukti_bayar')->store($folderPath, 'public');
|
||||
}
|
||||
|
||||
@@ -142,13 +245,22 @@ class PembayaranController extends Controller
|
||||
|
||||
$permohonan->approve_bayar_by = null;
|
||||
$permohonan->approve_bayar_at = null;
|
||||
$permohonan->status = 'done';
|
||||
$permohonan->status = 'proses-laporan';
|
||||
$permohonan->save();
|
||||
} else {
|
||||
$persetujuanPenawaran = PersetujuanPenawaran::create(
|
||||
$validated
|
||||
);
|
||||
|
||||
if(isset($validated['nomor_tiket'])){
|
||||
$noc = Noc::where('nomor_tiket',$validated['nomor_tiket'])->first();
|
||||
if($noc){
|
||||
$noc->persetujuan_penawaran_id = $persetujuanPenawaran->id;
|
||||
$noc->permohonan_id = $validated['permohonan_id'];
|
||||
$noc->save();
|
||||
}
|
||||
}
|
||||
|
||||
$folderPath = 'persetujuan_penawaran/' . $validated['penawaran_id'];
|
||||
|
||||
if ($request->hasFile('bukti_bayar')) {
|
||||
@@ -157,20 +269,47 @@ class PembayaranController extends Controller
|
||||
$persetujuanPenawaran->save();
|
||||
}
|
||||
|
||||
// Update the status of the related permohonan to 'spk'
|
||||
$bucok = [
|
||||
'tanggal_penuh' => $persetujuanPenawaran->created_at ?? $validated['created_at'],
|
||||
'tanggal' => $persetujuanPenawaran->created_at?->format('d') ?? $validated['created_at']?->format('d'),
|
||||
'bulan' => $persetujuanPenawaran->created_at?->format('m') ?? $validated['created_at']?->format('m'),
|
||||
'tahun' => $persetujuanPenawaran->created_at?->format('Y') ?? $validated['created_at']?->format('Y'),
|
||||
'nomor_tiket' => $req['nomor_tiket'] ?? '',
|
||||
'nominal' => $req['nominal_bayar'] ?? '',
|
||||
'nominal_berjalan' => $req['nominal_bayar'] ?? '',
|
||||
'penyelesaian' => 'Belum Selesai',
|
||||
'nama_sub_direktorat' => $noc->branch?->name ?? '',
|
||||
'nama_direktorat_cabang' => $noc->branch?->name ?? '',
|
||||
'permohonan_id' => $permohonan->id,
|
||||
'nomor_registrasi' => $permohonan->nomor_registrasi,
|
||||
];
|
||||
|
||||
|
||||
if(isset($req['nomor_tiket']) && $req['nomor_tiket'] !=''){
|
||||
Bucok::updateOrCreate([
|
||||
'nomor_registrasi' => $permohonan->nomor_registrasi,
|
||||
'nomor_tiket' => $req['nomor_tiket'],
|
||||
], $bucok);
|
||||
} else {
|
||||
Bucok::updateOrCreate([
|
||||
'nomor_registrasi' => $permohonan->nomor_registrasi
|
||||
], $bucok);
|
||||
}
|
||||
|
||||
// Update the status of the related permohonan to 'spk'
|
||||
|
||||
if ($permohonan) {
|
||||
$permohonan->status_bayar = request()->get('status_bayar');
|
||||
$permohonan->save();
|
||||
|
||||
// andy add, update status penawaran.status='spk'
|
||||
// $penawaran = PenawaranTender::where('nomor_registrasi',$permohonan->nomor_registrasi)->first();
|
||||
// andy add, update status penawaran.status='spk'
|
||||
// $penawaran = PenawaranTender::where('nomor_registrasi',$permohonan->nomor_registrasi)->first();
|
||||
PenawaranTender::where('nomor_registrasi', $permohonan->nomor_registrasi)->update([
|
||||
'status' => 'noc',
|
||||
'updated_by' => Auth::id(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
// andy add, update status penawaran.status='spk'
|
||||
// andy add, update status penawaran.status='spk'
|
||||
|
||||
}
|
||||
|
||||
@@ -180,7 +319,7 @@ class PembayaranController extends Controller
|
||||
|
||||
public function update(Request $request, $id): JsonResponse
|
||||
{
|
||||
// init
|
||||
// init
|
||||
$data = [];
|
||||
$output = [];
|
||||
$tindakan = null;
|
||||
@@ -196,22 +335,22 @@ class PembayaranController extends Controller
|
||||
}
|
||||
$output['data'] = $data;
|
||||
|
||||
// Update the status of the related permohonan to 'spk'
|
||||
// Update the status of the related permohonan to 'spk'
|
||||
$permohonan = Permohonan::find($id);
|
||||
|
||||
if ($permohonan) {
|
||||
|
||||
if ($request->type === 'revisi') {
|
||||
$data['status'] = 'revisi-pembayaran';
|
||||
$data['status'] = 'revisi-pembayaran';
|
||||
$data['status_bayar'] = 'belum_bayar';
|
||||
} else {
|
||||
$data['status_bayar'] = 'sudah_bayar';
|
||||
$data['status'] = 'proses-laporan';
|
||||
}
|
||||
$data['status'] = 'proses-laporan';
|
||||
|
||||
if ($permohonan->jenis_penilaian_id == 2) {
|
||||
$data['status_bayar'] = 'sudah_bayar';
|
||||
$data['status'] = 'spk';
|
||||
if ($permohonan->jenis_penilaian_id == 2) {
|
||||
$data['status_bayar'] = 'sudah_bayar';
|
||||
$data['status'] = 'spk';
|
||||
}
|
||||
}
|
||||
|
||||
if ($permohonan->jenis_penilaian_id == 1) {
|
||||
@@ -251,48 +390,43 @@ class PembayaranController extends Controller
|
||||
public function dataForDatatables(Request $request)
|
||||
{
|
||||
if (is_null($this->user) || !$this->user->can('debitur.view')) {
|
||||
// abort(403, 'Sorry! You are not allowed to view users.');
|
||||
// abort(403, 'Sorry! You are not allowed to view users.');
|
||||
}
|
||||
|
||||
$query = Permohonan::query()->where(function ($query) {
|
||||
$query->where(['status_bayar' => 'belum_bayar', 'jenis_penilaian_id' => 1])
|
||||
->orWhere('status', 'revisi-pembayaran');
|
||||
})
|
||||
->where(function ($query) {
|
||||
$query->whereNotIn('id', function ($subquery) {
|
||||
$subquery->select('permohonan_id')
|
||||
->from('persetujuan_penawaran')
|
||||
->whereNotNull('permohonan_id');
|
||||
})
|
||||
->orWhere('status', 'revisi-pembayaran');
|
||||
});
|
||||
$query = PersetujuanPenawaran::query();
|
||||
|
||||
if (Auth::user()->hasAnyRole(['pemohon-ao','pemohon-eo'])) {
|
||||
$query = $query->whereRelation('permohonan', 'branch_id', Auth::user()->branch_id);
|
||||
}
|
||||
|
||||
/*$query->where(function($q) {
|
||||
$q->whereRelation('permohonan', function($query) {
|
||||
$query->where('status_bayar', 'belum_bayar')
|
||||
->where('jenis_penilaian_id', 1);
|
||||
});
|
||||
});*/
|
||||
$query->orWhereRelation('permohonan','status_bayar','revisi-pembayaran');
|
||||
$query->orWhere(function($q) {
|
||||
$q->where('permohonan_id',null);
|
||||
$q->where('nomor_tiket','!=',null);
|
||||
});
|
||||
|
||||
// Pencarian berdasarkan parameter search
|
||||
if ($request->has('search') && !empty($request->get('search'))) {
|
||||
$search = $request->get('search');
|
||||
$query->where(function ($q) use ($search) {
|
||||
$q->where('nomor_registrasi', 'LIKE', '%' . $search . '%');
|
||||
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search . '%');
|
||||
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $search . '%');
|
||||
$q->orWhereRelation('debiture', 'name', 'LIKE', '%' . $search . '%');
|
||||
$q->orWhereRelation('jenisPenilaian', 'name', 'LIKE', '%' . $search . '%');
|
||||
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search . '%');
|
||||
$q->orWhere('status', 'LIKE', '%' . $search . '%');
|
||||
});
|
||||
}
|
||||
|
||||
// Sorting berdasarkan sortField dan sortOrder
|
||||
// Sorting berdasarkan sortField dan sortOrder
|
||||
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
|
||||
$order = $request->get('sortOrder');
|
||||
$column = $request->get('sortField');
|
||||
$query->orderBy($column, $order);
|
||||
}
|
||||
|
||||
// Hitung total records
|
||||
// Hitung total records
|
||||
$totalRecords = $query->count();
|
||||
|
||||
// Pagination (default page size 10)
|
||||
// Pagination (default page size 10)
|
||||
$size = $request->get('size', 10);
|
||||
if ($size == 0) {
|
||||
$size = 10;
|
||||
@@ -305,20 +439,172 @@ class PembayaranController extends Controller
|
||||
$query->skip($offset)->take($size);
|
||||
}
|
||||
|
||||
// Filtered records
|
||||
// Filtered records
|
||||
$filteredRecords = $query->count();
|
||||
|
||||
// Ambil data dengan relasi
|
||||
$data = $query->with(['user', 'debiture', 'branch', 'jenisPenilaian'])->get();
|
||||
// Ambil data dengan relasi
|
||||
$data = $query->get();
|
||||
|
||||
$data = $data->map(function ($item) {
|
||||
return [
|
||||
'id' => $item->permohonan?->id ?? $item->id,
|
||||
'nomor_registrasi' => $item->permohonan?->nomor_registrasi,
|
||||
'nomor_tiket' => $item->nomor_tiket ?? '',
|
||||
'debiture' => $item->permohonan?->debiture ?? $item->noc?->debiture,
|
||||
'user' => $item->permohonan?->user ?? $item->creator,
|
||||
'status_bayar' => $item->permohonan?->status_bayar ?? ($item->nomor_tiket ? 'Sudah Bayar' : ''),
|
||||
'tanggal_permohonan' => $item->permohonan?->tanggal_permohonan ?? '',
|
||||
'branch' => $item->permohonan?->branch ?? $item->noc?->branch,
|
||||
'is_permohonan' => $item->permohonan ?? ''
|
||||
];
|
||||
});
|
||||
|
||||
|
||||
// Hitung jumlah halaman
|
||||
// Hitung jumlah halaman
|
||||
$pageCount = ceil($totalRecords / $size);
|
||||
|
||||
// Ambil current page
|
||||
// Ambil current page
|
||||
$currentPage = max(1, $request->get('page', 1));
|
||||
|
||||
// Return JSON response
|
||||
// Return JSON response
|
||||
return response()->json([
|
||||
'draw' => $request->get('draw'),
|
||||
'recordsTotal' => $totalRecords,
|
||||
'recordsFiltered' => $filteredRecords,
|
||||
'pageCount' => $pageCount,
|
||||
'page' => $currentPage,
|
||||
'totalCount' => $totalRecords,
|
||||
'data' => $data,
|
||||
]);
|
||||
}
|
||||
|
||||
public function dataForDatatablesKurang(Request $request)
|
||||
{
|
||||
if (is_null($this->user) || !$this->user->can('debitur.view')) {
|
||||
// abort(403, 'Sorry! You are not allowed to view users.');
|
||||
}
|
||||
|
||||
$query = Noc::query()->where(function ($query) {
|
||||
$query->where(['status_kurang_bayar' => '1'])
|
||||
->where('bukti_ksl_kurang_bayar',null);
|
||||
});
|
||||
|
||||
// Sorting berdasarkan sortField dan sortOrder
|
||||
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
|
||||
$order = $request->get('sortOrder');
|
||||
$column = $request->get('sortField');
|
||||
$query->orderBy($column, $order);
|
||||
}
|
||||
|
||||
// Hitung total records
|
||||
$totalRecords = $query->count();
|
||||
|
||||
// Pagination (default page size 10)
|
||||
$size = $request->get('size', 10);
|
||||
if ($size == 0) {
|
||||
$size = 10;
|
||||
}
|
||||
|
||||
if ($request->has('page') && $request->has('size')) {
|
||||
$page = $request->get('page', 1);
|
||||
$offset = ($page - 1) * $size;
|
||||
|
||||
$query->skip($offset)->take($size);
|
||||
}
|
||||
|
||||
// Filtered records
|
||||
$filteredRecords = $query->count();
|
||||
|
||||
// Ambil data dengan relasi
|
||||
$data = $query->get();
|
||||
|
||||
$data = $data->map(function ($item) {
|
||||
return [
|
||||
'id' => $item->id,
|
||||
'permohonan' => $item->permohonan,
|
||||
'pemohon' => $item->permohonan->user,
|
||||
'branch' => $item->permohonan->branch,
|
||||
'debiture' => $item->permohonan->debiture,
|
||||
'nominal_kurang_bayar' => formatRupiah($item->nominal_kurang_bayar,2)
|
||||
];
|
||||
});
|
||||
|
||||
// Hitung jumlah halaman
|
||||
$pageCount = ceil($totalRecords / $size);
|
||||
|
||||
// Ambil current page
|
||||
$currentPage = max(1, $request->get('page', 1));
|
||||
|
||||
// Return JSON response
|
||||
return response()->json([
|
||||
'draw' => $request->get('draw'),
|
||||
'recordsTotal' => $totalRecords,
|
||||
'recordsFiltered' => $filteredRecords,
|
||||
'pageCount' => $pageCount,
|
||||
'page' => $currentPage,
|
||||
'totalCount' => $totalRecords,
|
||||
'data' => $data,
|
||||
]);
|
||||
}
|
||||
|
||||
public function dataForDatatablesLebih(Request $request)
|
||||
{
|
||||
if (is_null($this->user) || !$this->user->can('debitur.view')) {
|
||||
// abort(403, 'Sorry! You are not allowed to view users.');
|
||||
}
|
||||
|
||||
$query = Noc::query()->where(function ($query) {
|
||||
$query->where(['status_lebih_bayar' => '1'])
|
||||
->where('bukti_ksl_lebih_bayar',null);
|
||||
});
|
||||
|
||||
// Sorting berdasarkan sortField dan sortOrder
|
||||
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
|
||||
$order = $request->get('sortOrder');
|
||||
$column = $request->get('sortField');
|
||||
$query->orderBy($column, $order);
|
||||
}
|
||||
|
||||
// Hitung total records
|
||||
$totalRecords = $query->count();
|
||||
|
||||
// Pagination (default page size 10)
|
||||
$size = $request->get('size', 10);
|
||||
if ($size == 0) {
|
||||
$size = 10;
|
||||
}
|
||||
|
||||
if ($request->has('page') && $request->has('size')) {
|
||||
$page = $request->get('page', 1);
|
||||
$offset = ($page - 1) * $size;
|
||||
|
||||
$query->skip($offset)->take($size);
|
||||
}
|
||||
|
||||
// Filtered records
|
||||
$filteredRecords = $query->count();
|
||||
|
||||
// Ambil data dengan relasi
|
||||
$data = $query->get();
|
||||
|
||||
$data = $data->map(function ($item) {
|
||||
return [
|
||||
'id' => $item->id,
|
||||
'permohonan' => $item->permohonan,
|
||||
'pemohon' => $item->permohonan->user,
|
||||
'branch' => $item->permohonan->branch,
|
||||
'debiture' => $item->permohonan->debiture,
|
||||
'nominal_lebih_bayar' => formatRupiah($item->nominal_lebih_bayar,2)
|
||||
];
|
||||
});
|
||||
|
||||
// Hitung jumlah halaman
|
||||
$pageCount = ceil($totalRecords / $size);
|
||||
|
||||
// Ambil current page
|
||||
$currentPage = max(1, $request->get('page', 1));
|
||||
|
||||
// Return JSON response
|
||||
return response()->json([
|
||||
'draw' => $request->get('draw'),
|
||||
'recordsTotal' => $totalRecords,
|
||||
|
||||
@@ -26,18 +26,21 @@ use Modules\Lpj\Http\Requests\FormSurveyorRequest;
|
||||
use Modules\Lpj\Models\Authorization;
|
||||
use Modules\Lpj\Models\Debiture;
|
||||
use Modules\Lpj\Services\SaveFormInspesksiService;
|
||||
use Modules\Lpj\Services\PreviewLaporanService;
|
||||
|
||||
class PenilaiController extends Controller
|
||||
{
|
||||
public $user;
|
||||
protected $surveyorController;
|
||||
protected $inspeksiService;
|
||||
protected $previewLaporanService;
|
||||
|
||||
|
||||
public function __construct(SurveyorController $surveyorController, SaveFormInspesksiService $inspeksiService)
|
||||
public function __construct(SurveyorController $surveyorController, SaveFormInspesksiService $inspeksiService, PreviewLaporanService $previewLaporanService)
|
||||
{
|
||||
$this->surveyorController = $surveyorController;
|
||||
$this->inspeksiService = $inspeksiService;
|
||||
$this->previewLaporanService = $previewLaporanService;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -152,6 +155,11 @@ class PenilaiController extends Controller
|
||||
$jaminanId = $request->query('jaminanId');
|
||||
|
||||
$permohonan = $this->surveyorController->getPermohonanJaminanId($id, $documentId, $jaminanId);
|
||||
|
||||
if ($permohonan->status == 'proses-laporan') {
|
||||
//return redirect()->back()->with('error', 'Masih dalam proses laporan');
|
||||
}
|
||||
|
||||
$basicData = $this->surveyorController->getCommonData();
|
||||
$noLpSederhana = $this->generateNoLaporan($permohonan, $documentId, 'lpj');
|
||||
|
||||
@@ -218,6 +226,11 @@ class PenilaiController extends Controller
|
||||
$jaminanId = $request->query('jaminanId');
|
||||
|
||||
$permohonan = $this->surveyorController->getPermohonanJaminanId($permohonanId, $documentId, $jaminanId);
|
||||
|
||||
if ($permohonan->status == 'proses-laporan') {
|
||||
return redirect()->back()->with('error', 'Masih dalam proses laporan');
|
||||
}
|
||||
|
||||
$nomorLaporan = $this->generateNoLaporan($permohonan, $documentId, 'resume');
|
||||
$inspeksi = Inspeksi::where('permohonan_id', $permohonanId)->where('dokument_id', $documentId)->first();
|
||||
$noLpresume = $this->generateNoLaporan($permohonan, $documentId, 'resume');
|
||||
@@ -253,6 +266,9 @@ class PenilaiController extends Controller
|
||||
|
||||
$data = $this->getDataPermohonanWithPenilaiAndInspeksi($req['permohonanId'], $req['documentId'], $req['jaminanId']);
|
||||
$permohonan = $data['permohonan'];
|
||||
if ($permohonan->status == 'proses-laporan') {
|
||||
return redirect()->back()->with('error', 'Masih dalam proses laporan');
|
||||
}
|
||||
|
||||
$nomorLaporan = $this->generateNoLaporan($permohonan, $req['documentId'], 'memo');
|
||||
$inspeksi = Inspeksi::where('permohonan_id', $req['permohonanId'])->where('dokument_id', $req['documentId'])->first();
|
||||
@@ -392,6 +408,11 @@ class PenilaiController extends Controller
|
||||
$jaminanId = $request->query('jaminanId');
|
||||
$provinces = Province::all();
|
||||
$permohonan = $this->surveyorController->getPermohonanJaminanId($permohonanId, $documentId, $jaminanId);
|
||||
|
||||
if ($permohonan->status == 'proses-laporan') {
|
||||
return redirect()->back()->with('error', 'Masih dalam proses laporan');
|
||||
}
|
||||
|
||||
$nomorLaporan = $this->generateNoLaporan($permohonan, $documentId, 'rap');
|
||||
$basicData = $this->surveyorController->getCommonData();
|
||||
$inspeksi = Inspeksi::where('permohonan_id', $permohonanId)->where('dokument_id', $documentId)->first();
|
||||
@@ -470,6 +491,9 @@ class PenilaiController extends Controller
|
||||
$jaminanId = $request->query('jaminanId');
|
||||
$provinces = Province::all();
|
||||
$permohonan = $this->surveyorController->getPermohonanJaminanId($permohonanId, $documentId, $jaminanId);
|
||||
if ($permohonan->status == 'proses-laporan') {
|
||||
return redirect()->back()->with('error', 'Masih dalam proses laporan');
|
||||
}
|
||||
$nomorLaporan = $this->generateNoLaporan($permohonan, $documentId, 'call-report');
|
||||
$basicData = $this->surveyorController->getCommonData();
|
||||
$inspeksi = Inspeksi::where('permohonan_id', $permohonanId)->where('dokument_id', $documentId)->first();
|
||||
@@ -527,13 +551,7 @@ class PenilaiController extends Controller
|
||||
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)
|
||||
{
|
||||
@@ -601,7 +619,8 @@ class PenilaiController extends Controller
|
||||
'jenisfasilitasKredit',
|
||||
'penilaian.userPenilai',
|
||||
'penilai',
|
||||
'nilaiPlafond'
|
||||
'nilaiPlafond',
|
||||
'penawaran'
|
||||
])->get();
|
||||
|
||||
// Calculate the page count
|
||||
@@ -679,15 +698,17 @@ class PenilaiController extends Controller
|
||||
'lokasi_lengkap' => $data->lokasi_lengkap ?? '',
|
||||
];
|
||||
|
||||
// Extract data pembanding
|
||||
if (isset($dataPembanding['data_pembanding'])) {
|
||||
foreach ($dataPembanding['data_pembanding'] as $index => $pembanding) {
|
||||
if ($index == 0) {
|
||||
$exportData['pembanding1'] = $pembanding;
|
||||
} elseif ($index == 1) {
|
||||
$exportData['pembanding2'] = $pembanding;
|
||||
} elseif ($index == 2) {
|
||||
$exportData['pembanding3'] = $pembanding;
|
||||
if(isset($dataPembanding)){
|
||||
// Extract data pembanding
|
||||
if (isset($dataPembanding['data_pembanding'])) {
|
||||
foreach ($dataPembanding['data_pembanding'] as $index => $pembanding) {
|
||||
if ($index == 0) {
|
||||
$exportData['pembanding1'] = $pembanding;
|
||||
} elseif ($index == 1) {
|
||||
$exportData['pembanding2'] = $pembanding;
|
||||
} elseif ($index == 2) {
|
||||
$exportData['pembanding3'] = $pembanding;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -820,10 +841,10 @@ class PenilaiController extends Controller
|
||||
$permohonan = Permohonan::findOrFail($id);
|
||||
|
||||
if ($permohonan->status === 'proses-laporan') {
|
||||
return response()->json([
|
||||
/*return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Masih proses laporan',
|
||||
], 400);
|
||||
], 400);*/
|
||||
}
|
||||
|
||||
if ($permohonan->status === 'proses-paparan') {
|
||||
@@ -985,11 +1006,10 @@ class PenilaiController extends Controller
|
||||
],
|
||||
];
|
||||
|
||||
|
||||
|
||||
Inspeksi::create([
|
||||
Inspeksi::updateOrCreate([
|
||||
'permohonan_id' => $validatedData['permohonan_id'],
|
||||
'dokument_id' => $validatedData['dokument_id'],
|
||||
'dokument_id' => $validatedData['dokument_id']
|
||||
],[
|
||||
'data_form' => json_encode($newData),
|
||||
'name' => $validatedData['type']
|
||||
]);
|
||||
@@ -1056,14 +1076,14 @@ class PenilaiController extends Controller
|
||||
|
||||
$data = [];
|
||||
|
||||
$kategoriUnik = ['tanah', 'bangunan', 'apartemen-kantor', 'alat-berat', 'mesin', 'kendaraan', 'pesawat', 'kapal', 'sarana_pelengkap_penilai'];
|
||||
$kategoriUnik = ['tanah', 'bangunan', 'apartemen-kantor', 'alat-berat', 'mesin', 'kendaraan', 'pesawat', 'kapal', 'sarana_pelengkap_penilai'];
|
||||
|
||||
foreach ($kategoriUnik as $kategori) {
|
||||
// Dynamically generate keys
|
||||
$luasKey = 'luas_' . $kategori;
|
||||
$nilaiKey1 = 'nilai_' . $kategori . '_1';
|
||||
$nilaiKey2 = 'nilai_' . $kategori . '_2';
|
||||
|
||||
|
||||
// Collect data if exists
|
||||
if ($request->has($luasKey)) {
|
||||
$data[$luasKey] = $request->input($luasKey);
|
||||
@@ -1075,7 +1095,7 @@ class PenilaiController extends Controller
|
||||
$data[$nilaiKey2] = $request->input($nilaiKey2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$data['total_nilai_pasar_wajar'] = $request->input('total_nilai_pasar_wajar');
|
||||
$data['likuidasi'] = $request->input('likuidasi');
|
||||
$data['likuidasi_nilai_1'] = $request->input('likuidasi_nilai_1');
|
||||
@@ -1104,8 +1124,7 @@ class PenilaiController extends Controller
|
||||
$penilai = Penilai::updateOrCreate(
|
||||
[
|
||||
'permohonan_id' => $request->permohonanId,
|
||||
'dokument_id' => $request->documentId,
|
||||
|
||||
'dokument_id' => $request->input('dokument_id'),
|
||||
],
|
||||
[
|
||||
'lpj' => json_encode($data),
|
||||
@@ -1132,20 +1151,9 @@ class PenilaiController extends Controller
|
||||
{
|
||||
DB::beginTransaction();
|
||||
try {
|
||||
$formRequest = new FormSurveyorRequest();
|
||||
$formRequest->setContainer(app());
|
||||
$formRequest->initialize(
|
||||
$request->all(),
|
||||
$request->query->all(),
|
||||
$request->attributes->all(),
|
||||
$request->cookies->all(),
|
||||
$request->files->all(),
|
||||
$request->server->all(),
|
||||
$request->getContent()
|
||||
);
|
||||
|
||||
$validated = $formRequest->validateResolved();
|
||||
$result = $this->surveyorController->store($formRequest);
|
||||
$validatedData = $request->all();
|
||||
$result = $this->inspeksiService->storeInspeksi($validatedData, $request->input('type'), $request);
|
||||
|
||||
$data = [
|
||||
'kepada' => $request->input('kepada'),
|
||||
@@ -1243,9 +1251,10 @@ class PenilaiController extends Controller
|
||||
|
||||
|
||||
|
||||
Inspeksi::create([
|
||||
Inspeksi::updateOrCreate([
|
||||
'permohonan_id' => $validated['permohonan_id'],
|
||||
'dokument_id' => $validated['dokument_id'],
|
||||
'dokument_id' => $validated['dokument_id']
|
||||
],[
|
||||
'data_form' => json_encode($newData),
|
||||
'name' => $validated['type']
|
||||
]);
|
||||
@@ -1266,8 +1275,6 @@ class PenilaiController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function print_out(Request $request)
|
||||
{
|
||||
$documentId = $request->query('documentId');
|
||||
@@ -1383,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)
|
||||
{
|
||||
$viewMap = [
|
||||
@@ -1410,7 +1426,7 @@ class PenilaiController extends Controller
|
||||
}
|
||||
|
||||
|
||||
// pengunaan request query by id permohonan, dokument, jaminan , inspeksi
|
||||
// pengunaan request query by id permohonan, documentId, jaminan , inspeksi
|
||||
protected function getRequestQueryId(Request $request)
|
||||
{
|
||||
return [
|
||||
@@ -1762,4 +1778,24 @@ class PenilaiController extends Controller
|
||||
'message' => 'Berhasil Revisi Ke surveyor',
|
||||
], 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;
|
||||
$status = 'done';
|
||||
$approvalField = null;
|
||||
|
||||
$lpj_ = optional(json_decode($permohonan->penilai->lpj));
|
||||
$npw = $lpj_->total_nilai_pasar_wajar ?? 0;
|
||||
$npw = str_replace('.', '', $npw);
|
||||
|
||||
|
||||
if ($role === 'senior-officer') {
|
||||
$approvalField = 'approval_so';
|
||||
$status = in_array($permohonan->nilai_plafond_id, [3]) ? 'done' : 'proses-laporan';
|
||||
$status = $npw <=1000000000 ? 'done' : 'proses-laporan';
|
||||
} elseif ($role === 'EO Appraisal') {
|
||||
$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') {
|
||||
$approvalField = 'approval_dd';
|
||||
$status = 'done';
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,6 +6,7 @@
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Modules\Lpj\Http\Requests\PersetujuanPenawaranRequest;
|
||||
use Modules\Lpj\Models\Noc;
|
||||
use Modules\Lpj\Models\PenawaranDetailTender;
|
||||
use Modules\Lpj\Models\PenawaranDetailTenderLog;
|
||||
use Modules\Lpj\Models\PenawaranTender;
|
||||
@@ -39,6 +40,7 @@
|
||||
$validated = $request->validated();
|
||||
$validated['created_by'] = Auth::id();
|
||||
$validated['status'] = '0';
|
||||
$validated['nominal_bayar'] = $validated['biaya_final'];
|
||||
|
||||
$persetujuanPenawaran = PersetujuanPenawaran::updateOrCreate(
|
||||
['penawaran_id' => $validated['penawaran_id']],
|
||||
@@ -67,6 +69,22 @@
|
||||
|
||||
$persetujuanPenawaran->save();
|
||||
|
||||
|
||||
// Save NOC
|
||||
try {
|
||||
$noc = 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());
|
||||
}
|
||||
|
||||
return redirect()
|
||||
->route('persetujuan-penawaran.index')->with('success', 'Persetujuan Penawaran berhasil disimpan.');
|
||||
}
|
||||
@@ -162,8 +180,8 @@
|
||||
public function edit($id)
|
||||
{
|
||||
$permohonan = Permohonan::with(['debiture', 'penawaranTender.detail'])->find($id);
|
||||
|
||||
return view('lpj::persetujuan_penawaran.form', compact('permohonan'));
|
||||
$persetujuanPenawaran = PersetujuanPenawaran::where('permohonan_id', $id)->first();
|
||||
return view('lpj::persetujuan_penawaran.form', compact('permohonan', 'persetujuanPenawaran'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -184,8 +202,12 @@
|
||||
}
|
||||
|
||||
// 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
|
||||
if ($request->has('search') && !empty($request->get('search'))) {
|
||||
$search = $request->get('search');
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
$query =PenawaranTender::query()
|
||||
->select('penawaran.*', 'tujuan_penilaian_kjpp.name as tujuan_penilaian_kjpp_name')
|
||||
->leftJoin('tujuan_penilaian_kjpp', 'tujuan_penilaian_kjpp.id','=','penawaran.tujuan_penilaian_kjpp_id')
|
||||
->where('penawaran.status','=','spk')
|
||||
->where('penawaran.status','=','registrasi-final')
|
||||
->withCount('penawarandetails');
|
||||
|
||||
// Apply search filter if provided
|
||||
|
||||
22
app/Http/Controllers/RekapHarianSoController.php
Normal file
22
app/Http/Controllers/RekapHarianSoController.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Modules\Lpj\Models\TujuanPenilaian;
|
||||
|
||||
class RekapHarianSoController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$total_laporan_debitur = 0;
|
||||
$tujuan_penilaian = TujuanPenilaian::all();
|
||||
return view('lpj::rekap-harian-so.index', compact('tujuan_penilaian', 'total_laporan_debitur'));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
548
app/Http/Controllers/SlikController.php
Normal file
548
app/Http/Controllers/SlikController.php
Normal file
@@ -0,0 +1,548 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Exception;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
use Modules\Lpj\Exports\SlikExport;
|
||||
use Modules\Lpj\Imports\SlikImport;
|
||||
use Modules\Lpj\Models\Slik;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Controller untuk mengelola data Slik
|
||||
*
|
||||
* Menangani operasi CRUD dan import data Slik dari file Excel
|
||||
* dengan fitur server-side processing untuk datatables
|
||||
*
|
||||
* @package Modules\Lpj\Http\Controllers
|
||||
*/
|
||||
class SlikController extends Controller
|
||||
{
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->user = Auth::user();
|
||||
}
|
||||
|
||||
/**
|
||||
* Menampilkan halaman index slik
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return view('lpj::slik.index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Menampilkan detail slik
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function show($id)
|
||||
{
|
||||
$slik = Slik::findOrFail($id);
|
||||
return view('lpj::slik.show', compact('slik'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data untuk datatables dengan server-side processing
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function dataForDatatables(Request $request)
|
||||
{
|
||||
// Authorization check dapat ditambahkan sesuai kebutuhan
|
||||
// if (is_null($this->user)) {
|
||||
// abort(403, 'Unauthorized access.');
|
||||
// }
|
||||
|
||||
// Retrieve data from the database
|
||||
$query = Slik::query();
|
||||
|
||||
// Apply search filter if provided
|
||||
if ($request->has('search') && !empty($request->get('search'))) {
|
||||
$search = $request->get('search');
|
||||
$query->where(function ($q) use ($search) {
|
||||
$q->where('sandi_bank', 'LIKE', "%$search%")
|
||||
->orWhere('no_rekening', 'LIKE', "%$search%")
|
||||
->orWhere('cif', 'LIKE', "%$search%")
|
||||
->orWhere('nama_debitur', 'LIKE', "%$search%")
|
||||
->orWhere('nama_cabang', 'LIKE', "%$search%")
|
||||
->orWhere('jenis_agunan', 'LIKE', "%$search%")
|
||||
->orWhere('nama_pemilik_agunan', 'LIKE', "%$search%")
|
||||
->orWhere('alamat_agunan', 'LIKE', "%$search%")
|
||||
->orWhere('lokasi_agunan', 'LIKE', "%$search%");
|
||||
});
|
||||
}
|
||||
|
||||
// Apply year filter
|
||||
if ($request->has('year') && !empty($request->get('year'))) {
|
||||
$query->byYear($request->get('year'));
|
||||
}
|
||||
|
||||
// Apply month filter
|
||||
if ($request->has('month') && !empty($request->get('month'))) {
|
||||
$query->byMonth($request->get('month'));
|
||||
}
|
||||
|
||||
// Apply sandi bank filter
|
||||
if ($request->has('sandi_bank') && !empty($request->get('sandi_bank'))) {
|
||||
$query->where('sandi_bank', $request->get('sandi_bank'));
|
||||
}
|
||||
|
||||
// Apply kolektibilitas filter
|
||||
if ($request->has('kolektibilitas') && !empty($request->get('kolektibilitas'))) {
|
||||
$query->where('kolektibilitas', $request->get('kolektibilitas'));
|
||||
}
|
||||
|
||||
// Apply jenis agunan filter
|
||||
if ($request->has('jenis_agunan') && !empty($request->get('jenis_agunan'))) {
|
||||
$query->where('jenis_agunan', $request->get('jenis_agunan'));
|
||||
}
|
||||
|
||||
// Apply sorting if provided
|
||||
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
|
||||
$order = $request->get('sortOrder');
|
||||
$column = $request->get('sortField', 'created_at');
|
||||
$query->orderBy($column, $order);
|
||||
} else {
|
||||
$query->orderBy('created_at', 'desc');
|
||||
}
|
||||
|
||||
// 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 with relationships
|
||||
$data = $query->get();
|
||||
|
||||
// Transform data untuk datatables
|
||||
$transformedData = $data->map(function ($item) {
|
||||
return [
|
||||
'id' => $item->id,
|
||||
'sandi_bank' => $item->sandi_bank,
|
||||
'tahun' => $item->tahun,
|
||||
'bulan' => $item->bulan,
|
||||
'no_rekening' => $item->no_rekening,
|
||||
'cif' => $item->cif,
|
||||
'nama_debitur' => $item->nama_debitur,
|
||||
'kolektibilitas' => $item->kolektibilitas,
|
||||
'kolektibilitas_badge' => $item->kolektibilitas_badge,
|
||||
'fasilitas' => $item->fasilitas,
|
||||
'jenis_agunan' => $item->jenis_agunan,
|
||||
'nama_pemilik_agunan' => $item->nama_pemilik_agunan,
|
||||
'nilai_agunan' => $item->nilai_agunan_formatted,
|
||||
'nilai_agunan_ljk' => $item->nilai_agunan_ljk_formatted,
|
||||
'alamat_agunan' => $item->alamat_agunan,
|
||||
'lokasi_agunan' => $item->lokasi_agunan,
|
||||
'nama_cabang' => $item->nama_cabang,
|
||||
'kode_cabang' => $item->kode_cabang,
|
||||
'created_by' => $item->creator?->name ?? '-',
|
||||
'created_at' => dateFormat($item->created_at, true)
|
||||
];
|
||||
});
|
||||
|
||||
// Calculate the page count
|
||||
$pageCount = ceil($totalRecords / ($request->get('size', 10)));
|
||||
|
||||
// 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' => $transformedData,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Import data slik dari Excel dengan optimasi memory dan progress tracking
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function import(Request $request)
|
||||
{
|
||||
Log::info('SlikController: Starting import process with optimizations', [
|
||||
'user_id' => Auth::id(),
|
||||
'request_size' => $request->header('Content-Length'),
|
||||
'has_file' => $request->hasFile('file'),
|
||||
'memory_limit' => ini_get('memory_limit'),
|
||||
'max_execution_time' => ini_get('max_execution_time')
|
||||
]);
|
||||
|
||||
// Validasi file upload dengan logging detail dan error handling komprehensif
|
||||
try {
|
||||
// Cek apakah ada file yang diupload
|
||||
if (!$request->hasFile('file')) {
|
||||
Log::error('SlikController: Tidak ada file yang diupload', [
|
||||
'user_id' => Auth::id(),
|
||||
'files_count' => count($request->allFiles()),
|
||||
'request_data' => $request->all()
|
||||
]);
|
||||
throw ValidationException::withMessages(['file' => 'Tidak ada file yang diupload.']);
|
||||
}
|
||||
|
||||
$file = $request->file('file');
|
||||
|
||||
// Cek apakah file valid
|
||||
if (!$file->isValid()) {
|
||||
$error = $file->getError();
|
||||
$errorMessage = match($error) {
|
||||
UPLOAD_ERR_INI_SIZE => 'File terlalu besar (melebihi upload_max_filesize).',
|
||||
UPLOAD_ERR_FORM_SIZE => 'File terlalu besar (melebihi MAX_FILE_SIZE).',
|
||||
UPLOAD_ERR_PARTIAL => 'File hanya terupload sebagian.',
|
||||
UPLOAD_ERR_NO_FILE => 'Tidak ada file yang diupload.',
|
||||
UPLOAD_ERR_NO_TMP_DIR => 'Direktori temp tidak tersedia.',
|
||||
UPLOAD_ERR_CANT_WRITE => 'Gagal menulis file ke disk.',
|
||||
UPLOAD_ERR_EXTENSION => 'Upload dibatalkan oleh ekstensi PHP.',
|
||||
default => 'Error upload tidak diketahui: ' . $error
|
||||
};
|
||||
|
||||
Log::error('SlikController: File upload tidak valid', [
|
||||
'error' => $error,
|
||||
'error_message' => $errorMessage,
|
||||
'user_id' => Auth::id(),
|
||||
'file_info' => [
|
||||
'name' => $file->getClientOriginalName(),
|
||||
'size' => $file->getSize(),
|
||||
'mime' => $file->getMimeType()
|
||||
]
|
||||
]);
|
||||
throw ValidationException::withMessages(['file' => $errorMessage]);
|
||||
}
|
||||
|
||||
$maxFileSize = config('import.slik.max_file_size', 50) * 1024; // dalam KB
|
||||
$request->validate([
|
||||
'file' => 'required|file|mimes:xlsx,xls|max:' . $maxFileSize
|
||||
]);
|
||||
Log::info('SlikController: Validasi file berhasil');
|
||||
} catch (\Illuminate\Validation\ValidationException $e) {
|
||||
Log::error('SlikController: Validasi file gagal', [
|
||||
'errors' => $e->errors(),
|
||||
'user_id' => Auth::id(),
|
||||
'request_size' => $request->header('Content-Length')
|
||||
]);
|
||||
throw $e;
|
||||
}
|
||||
|
||||
try {
|
||||
$uploadedFile = $request->file('file');
|
||||
$originalName = $uploadedFile->getClientOriginalName();
|
||||
$fileSize = $uploadedFile->getSize();
|
||||
|
||||
Log::info('SlikController: Memulai import data Slik', [
|
||||
'user_id' => Auth::id(),
|
||||
'filename' => $originalName,
|
||||
'filesize' => $fileSize,
|
||||
'filesize_mb' => round($fileSize / 1024 / 1024, 2),
|
||||
'mime_type' => $uploadedFile->getMimeType(),
|
||||
'extension' => $uploadedFile->getClientOriginalExtension()
|
||||
]);
|
||||
|
||||
// Generate unique import ID
|
||||
$importId = uniqid('slik_import_');
|
||||
$userId = Auth::id() ?? 1;
|
||||
|
||||
// Cek apakah menggunakan queue processing untuk file besar
|
||||
$useQueue = config('import.slik.queue.enabled', false) && $fileSize > (5 * 1024 * 1024); // > 5MB
|
||||
|
||||
// Pastikan direktori temp ada
|
||||
$tempDir = storage_path('app/temp');
|
||||
if (!file_exists($tempDir)) {
|
||||
mkdir($tempDir, 0755, true);
|
||||
Log::info('SlikController: Direktori temp dibuat', ['path' => $tempDir]);
|
||||
}
|
||||
|
||||
// Simpan file sementara dengan nama unik
|
||||
$tempFileName = 'slik_import_' . time() . '_' . uniqid() . '.' . $uploadedFile->getClientOriginalExtension();
|
||||
$tempFilePath = $tempDir . '/' . $tempFileName;
|
||||
|
||||
Log::info('SlikController: Memindahkan file ke temp', [
|
||||
'temp_path' => $tempFilePath,
|
||||
'use_queue' => $useQueue
|
||||
]);
|
||||
|
||||
// Pindahkan file ke direktori temp
|
||||
$uploadedFile->move($tempDir, $tempFilePath);
|
||||
|
||||
// Verifikasi file berhasil dipindahkan
|
||||
if (!file_exists($tempFilePath)) {
|
||||
throw new Exception('File gagal dipindahkan ke direktori temp');
|
||||
}
|
||||
|
||||
Log::info('SlikController: File berhasil dipindahkan', [
|
||||
'file_size' => filesize($tempFilePath)
|
||||
]);
|
||||
|
||||
if ($useQueue) {
|
||||
Log::info('SlikController: Menggunakan queue processing untuk file besar', [
|
||||
'import_id' => $importId,
|
||||
'file_size_mb' => round($fileSize / 1024 / 1024, 2)
|
||||
]);
|
||||
|
||||
// Dispatch job ke queue
|
||||
\Modules\Lpj\Jobs\ProcessSlikImport::dispatch($tempFilePath, $userId, $importId);
|
||||
|
||||
return redirect()->back()->with('success', 'Import sedang diproses di background. ID: ' . $importId);
|
||||
}
|
||||
|
||||
// Import langsung untuk file kecil
|
||||
Log::info('SlikController: Processing file directly', [
|
||||
'import_id' => $importId,
|
||||
'file_size_mb' => round($fileSize / 1024 / 1024, 2)
|
||||
]);
|
||||
|
||||
// Set optimasi memory untuk import langsung
|
||||
$memoryLimit = config('import.slik.memory_limit', 256);
|
||||
ini_set('memory_limit', $memoryLimit . 'M');
|
||||
ini_set('max_execution_time', config('import.slik.timeout', 30000));
|
||||
|
||||
// Enable garbage collection jika diizinkan
|
||||
if (config('import.slik.enable_gc', true)) {
|
||||
gc_enable();
|
||||
}
|
||||
|
||||
// Proses import menggunakan SlikImport class
|
||||
Log::info('SlikController: Memulai proses Excel import');
|
||||
$import = new SlikImport();
|
||||
Excel::import($import, $tempFilePath);
|
||||
Log::info('SlikController: Excel import selesai');
|
||||
|
||||
// Force garbage collection setelah selesai
|
||||
if (config('import.slik.enable_gc', true)) {
|
||||
gc_collect_cycles();
|
||||
}
|
||||
|
||||
// Hapus file temporary setelah import
|
||||
if (file_exists($tempFilePath)) {
|
||||
unlink($tempFilePath);
|
||||
Log::info('SlikController: File temp berhasil dihapus');
|
||||
}
|
||||
|
||||
Log::info('SlikController: Data Slik berhasil diimport', [
|
||||
'user_id' => Auth::id(),
|
||||
'import_id' => $importId
|
||||
]);
|
||||
|
||||
return redirect()->back()->with('success', 'Data Slik berhasil diimport dari file Excel.');
|
||||
|
||||
} catch (Exception $e) {
|
||||
// Hapus file temporary jika ada error
|
||||
if (isset($tempFilePath) && file_exists($tempFilePath)) {
|
||||
unlink($tempFilePath);
|
||||
Log::info('SlikController: File temp dihapus karena error');
|
||||
}
|
||||
|
||||
Log::error('SlikController: Gagal import data Slik', [
|
||||
'error' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString(),
|
||||
'user_id' => Auth::id(),
|
||||
'file' => $e->getFile(),
|
||||
'line' => $e->getLine(),
|
||||
'memory_usage' => memory_get_usage(true)
|
||||
]);
|
||||
|
||||
return redirect()->back()->with('error', 'Gagal import data Slik: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Menampilkan halaman form import
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function importForm()
|
||||
{
|
||||
return view('lpj::slik.import');
|
||||
}
|
||||
|
||||
/**
|
||||
* Download template Excel untuk import
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\BinaryFileResponse
|
||||
*/
|
||||
public function downloadTemplate()
|
||||
{
|
||||
$templatePath = resource_path('metronic/slik.xlsx');
|
||||
|
||||
if (!file_exists($templatePath)) {
|
||||
return redirect()->back()->with('error', 'Template file tidak ditemukan.');
|
||||
}
|
||||
|
||||
return response()->download($templatePath, 'template_slik.xlsx');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get import progress
|
||||
*
|
||||
* @param string $importId
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function progress(string $importId)
|
||||
{
|
||||
try {
|
||||
$progressService = new \Modules\Lpj\Services\ImportProgressService();
|
||||
$progress = $progressService->getProgress($importId);
|
||||
|
||||
if (!$progress) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Progress import tidak ditemukan'
|
||||
], 404);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'progress' => $progress
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('SlikController: Error getting progress', [
|
||||
'import_id' => $importId,
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Gagal mendapatkan progress: ' . $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Export data SLIK ke Excel
|
||||
*
|
||||
* Method ini menangani export data SLIK ke format Excel dengan:
|
||||
* - Logging aktivitas export
|
||||
* - Error handling yang proper
|
||||
* - Format Excel yang sesuai dengan struktur SLIK
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\BinaryFileResponse
|
||||
*/
|
||||
public function export()
|
||||
{
|
||||
try {
|
||||
Log::info('SLIK Export: Memulai proses export data SLIK', [
|
||||
'user_id' => Auth::id(),
|
||||
'timestamp' => now(),
|
||||
'memory_usage' => memory_get_usage(true) / 1024 / 1024 . ' MB'
|
||||
]);
|
||||
|
||||
// Hitung total data yang akan di-export
|
||||
$totalData = Slik::count();
|
||||
|
||||
Log::info('SLIK Export: Informasi data export', [
|
||||
'total_records' => $totalData,
|
||||
'user_id' => Auth::id(),
|
||||
'timestamp' => now()
|
||||
]);
|
||||
|
||||
// Generate nama file dengan timestamp
|
||||
$filename = 'slik_export_' . date('Y-m-d_H-i-s') . '.xlsx';
|
||||
|
||||
// Proses export menggunakan SlikExport class
|
||||
$export = Excel::download(new SlikExport(), $filename);
|
||||
|
||||
Log::info('SLIK Export: Berhasil generate file export', [
|
||||
'filename' => $filename,
|
||||
'total_records' => $totalData,
|
||||
'user_id' => Auth::id(),
|
||||
'timestamp' => now(),
|
||||
'memory_peak' => memory_get_peak_usage(true) / 1024 / 1024 . ' MB'
|
||||
]);
|
||||
|
||||
return $export;
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('SLIK Export: Gagal melakukan export data SLIK', [
|
||||
'error' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString(),
|
||||
'user_id' => Auth::id(),
|
||||
'timestamp' => now(),
|
||||
'memory_usage' => memory_get_usage(true) / 1024 / 1024 . ' MB'
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Gagal melakukan export data SLIK: ' . $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncate all SLIK data
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function truncate()
|
||||
{
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
|
||||
Log::info('SLIK Truncate: Memulai proses truncate data SLIK', [
|
||||
'user_id' => Auth::id(),
|
||||
'timestamp' => now()
|
||||
]);
|
||||
|
||||
// Truncate tabel SLIK
|
||||
Slik::truncate();
|
||||
|
||||
DB::commit();
|
||||
|
||||
Log::info('SLIK Truncate: Berhasil menghapus semua data SLIK', [
|
||||
'user_id' => Auth::id(),
|
||||
'timestamp' => now()
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Semua data SLIK berhasil dihapus'
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
DB::rollback();
|
||||
|
||||
Log::error('SLIK Truncate: Gagal menghapus data SLIK', [
|
||||
'error' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString(),
|
||||
'user_id' => Auth::id(),
|
||||
'timestamp' => now()
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Gagal menghapus data SLIK: ' . $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -345,6 +345,19 @@ use Illuminate\Support\Facades\Auth;
|
||||
$content = $pdf->download()->getOriginalContent();
|
||||
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['spkpenawaran_path'] = $spkpenawaran_path;
|
||||
$data1['message']['message_success'] = array('Generate SPK PDF successfully');
|
||||
|
||||
@@ -3,25 +3,21 @@
|
||||
namespace Modules\Lpj\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
use Modules\Lpj\Exports\BasicDataSurveyorExport;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Barryvdh\DomPDF\Facade\Pdf;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Http\Response;
|
||||
use Exception;
|
||||
use Modules\Lpj\Models\Debiture;
|
||||
use Modules\Lpj\Models\LaporanExternal;
|
||||
use Modules\Lpj\Models\Permohonan;
|
||||
use Modules\Lpj\Models\Branch;
|
||||
use Modules\Lpj\Models\Surveyor;
|
||||
use Modules\Lpj\Models\BentukTanah;
|
||||
use Modules\Lpj\Models\KonturTanah;
|
||||
use Modules\Location\Models\Province;
|
||||
@@ -41,17 +37,8 @@ use Modules\Lpj\Models\SpekBangunan;
|
||||
use Modules\Lpj\Models\SpekKategoritBangunan;
|
||||
use Modules\Lpj\Models\SaranaPelengkap;
|
||||
use Modules\Lpj\Models\ArahMataAngin;
|
||||
use Modules\Lpj\Models\Analisa;
|
||||
use Modules\Lpj\Models\Penilaian;
|
||||
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\Lantai;
|
||||
use Modules\Lpj\Models\Inspeksi;
|
||||
@@ -62,29 +49,24 @@ use Modules\Lpj\Models\PosisiUnit;
|
||||
use Modules\Lpj\Models\TerletakArea;
|
||||
use Modules\Lpj\Models\FasilitasObjek;
|
||||
use Modules\Lpj\Models\MerupakanDaerah;
|
||||
use Modules\Lpj\Models\ObjekJaminan;
|
||||
use Modules\Lpj\Models\ModelAlatBerat;
|
||||
use Modules\Lpj\Models\JenisPesawat;
|
||||
use Modules\Lpj\Models\DokumenJaminan;
|
||||
use Modules\Lpj\Models\DetailDokumenJaminan;
|
||||
use Modules\Lpj\Models\JenisKapal;
|
||||
use Modules\Lpj\Models\JenisKendaraan;
|
||||
use Modules\Lpj\Models\RuteJaminan;
|
||||
use Modules\Lpj\Models\HubunganPemilikJaminan;
|
||||
use Modules\Lpj\Models\HubunganPenghuniJaminan;
|
||||
use Modules\Lpj\Models\AnalisaUnit;
|
||||
use Modules\Lpj\Models\GolonganMasySekitar;
|
||||
use Modules\Lpj\Models\TingkatKeramaian;
|
||||
use Modules\Lpj\Models\TujuanPenilaian;
|
||||
use Modules\Lpj\Models\LaluLintasLokasi;
|
||||
use Modules\Lpj\Models\SpekBagunanAnalisaDetail;
|
||||
use Modules\Lpj\Http\Requests\SurveyorRequest;
|
||||
use Modules\Lpj\Http\Requests\FormSurveyorRequest;
|
||||
use Modules\Lpj\Jobs\SendJadwalKunjunganEmailJob;
|
||||
use App\Helpers\Lpj;
|
||||
use Modules\Lpj\Models\Authorization;
|
||||
use Modules\Lpj\Services\SurveyorValidateService;
|
||||
use Modules\Lpj\Services\SaveFormInspesksiService;
|
||||
use Modules\Lpj\Models\PermohonanHistory;
|
||||
|
||||
class SurveyorController extends Controller
|
||||
{
|
||||
@@ -126,6 +108,9 @@ class SurveyorController extends Controller
|
||||
$provinces = Province::all();
|
||||
$bentukTanah = BentukTanah::all();
|
||||
|
||||
// Jalankan cleanup inspeksi otomatis untuk permohonan ini
|
||||
$this->cleanupInspeksiData($id);
|
||||
|
||||
// Get all inspeksi data for this permohonan
|
||||
if (strtolower($permohonan->tujuanPenilaian->name) == 'rap') {
|
||||
$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(
|
||||
'permohonan',
|
||||
'surveyor',
|
||||
'branches',
|
||||
'provinces',
|
||||
'bentukTanah',
|
||||
'inspeksiData'
|
||||
'inspeksiData',
|
||||
'catatan_revisi_survey',
|
||||
));
|
||||
}
|
||||
|
||||
@@ -253,7 +242,7 @@ class SurveyorController extends Controller
|
||||
], 200);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
\Log::error('Denah Store Error: ' . $e->getMessage());
|
||||
Log::error('Denah Store Error: ' . $e->getMessage());
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Gagal menyimpan data: ' . $e->getMessage()
|
||||
@@ -794,12 +783,12 @@ class SurveyorController extends Controller
|
||||
]);
|
||||
|
||||
|
||||
if ($permohonan->jenisPenilaian->name == "External") {
|
||||
if (in_array(strtolower($permohonan->jenisPenilaian->name), ['external', 'eksternal'])) {
|
||||
LaporanExternal::updateOrCreate(
|
||||
['permohonan_id' => $permohonan->id],
|
||||
[
|
||||
'nomor_laporan' => $permohonan->nomor_registrasi,
|
||||
'tanggal_laporan' => now(),
|
||||
'tgl_final_laporan' => now(),
|
||||
'created_by' => Auth::id(),
|
||||
]
|
||||
);
|
||||
@@ -1079,7 +1068,7 @@ class SurveyorController extends Controller
|
||||
return null;
|
||||
|
||||
} 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());
|
||||
}
|
||||
}
|
||||
@@ -1396,6 +1385,11 @@ class SurveyorController extends Controller
|
||||
}
|
||||
public function storeDataPembanding(Request $request)
|
||||
{
|
||||
$request->merge([
|
||||
'kordinat_lat' => $request->get('kordinat_lat') ? str_replace(',', '', $request->get('kordinat_lat')) : null,
|
||||
'kordinat_lng' => $request->get('kordinat_lng') ? str_replace(',', '', $request->get('kordinat_lng')) : null,
|
||||
]);
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
|
||||
@@ -1556,11 +1550,11 @@ class SurveyorController extends Controller
|
||||
{
|
||||
|
||||
$validated = $request->validate([
|
||||
'dokument' => 'required',
|
||||
'documentId' => 'required',
|
||||
'jenis_jaminan' => 'required'
|
||||
]);
|
||||
|
||||
$dokumentId = $validated['dokument'];
|
||||
$dokumentId = $validated['documentId'];
|
||||
$jaminanId = $validated['jenis_jaminan'];
|
||||
|
||||
$permohonan = $this->getPermohonanJaminanId($id, $dokumentId, $jaminanId);
|
||||
@@ -1644,11 +1638,11 @@ class SurveyorController extends Controller
|
||||
public function denah(Request $request, $id)
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'dokument' => 'required',
|
||||
'documentId' => 'required',
|
||||
'jenis_jaminan' => 'required'
|
||||
]);
|
||||
|
||||
$dokumentId = $validated['dokument'];
|
||||
$dokumentId = $validated['documentId'];
|
||||
$jaminanId = $validated['jenis_jaminan'];
|
||||
|
||||
$permohonan = $this->getPermohonanJaminanId($id, $dokumentId, $jaminanId);
|
||||
@@ -1672,11 +1666,11 @@ class SurveyorController extends Controller
|
||||
public function foto(Request $request, $id)
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'dokument' => 'required',
|
||||
'documentId' => 'required',
|
||||
'jenis_jaminan' => 'required'
|
||||
]);
|
||||
|
||||
$dokumentId = $validated['dokument'];
|
||||
$dokumentId = $validated['documentId'];
|
||||
$jaminanId = $validated['jenis_jaminan'];
|
||||
$fotoObjekJaminan = FotoObjekJaminan::all();
|
||||
|
||||
@@ -1707,11 +1701,11 @@ class SurveyorController extends Controller
|
||||
// Ambil data permohonan dengan eager loading
|
||||
|
||||
$validated = $request->validate([
|
||||
'dokument' => 'required',
|
||||
'documentId' => 'required',
|
||||
'jenis_jaminan' => 'required'
|
||||
]);
|
||||
|
||||
$dokumentId = $validated['dokument'];
|
||||
$dokumentId = $validated['documentId'];
|
||||
$jaminanId = $validated['jenis_jaminan'];
|
||||
|
||||
$permohonan = $this->getPermohonanJaminanId($id, $dokumentId, $jaminanId);
|
||||
@@ -1847,10 +1841,10 @@ class SurveyorController extends Controller
|
||||
return redirect()
|
||||
->route('basicdata.' . $type . '.index')
|
||||
->with('success', 'created successfully');
|
||||
} catch (Exeception $e) {
|
||||
} catch (\Exception $e) {
|
||||
return redirect()
|
||||
->route('basicdata.' . $type . '.index')
|
||||
->with('error', $th->getMessage());
|
||||
->with('error', $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2116,7 +2110,7 @@ class SurveyorController extends Controller
|
||||
|
||||
public function dataForDatatablesData(Request $request, $type)
|
||||
{
|
||||
if (is_null(auth()->user()) || !$this->user->can('jenis_aset.view')) {
|
||||
if (is_null(Auth::user()) || !$this->user->can('jenis_aset.view')) {
|
||||
//abort(403, 'Sorry! You are not allowed to view users.');
|
||||
}
|
||||
|
||||
@@ -2156,7 +2150,7 @@ class SurveyorController extends Controller
|
||||
if (array_key_exists($type, $models)) {
|
||||
$query = $models[$type]::query();
|
||||
} else {
|
||||
throw new InvalidArgumentException("Invalid type: $type");
|
||||
throw new \InvalidArgumentException("Invalid type: $type");
|
||||
}
|
||||
|
||||
if ($request->has('search') && !empty($request->get('search'))) {
|
||||
@@ -2229,9 +2223,9 @@ class SurveyorController extends Controller
|
||||
$model = $modelClass::findOrFail($id);
|
||||
$model->delete();
|
||||
return response()->json(['success' => true, 'message' => 'deleted successfully']);
|
||||
} catch (ModelNotFoundException $e) {
|
||||
} catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
|
||||
return response()->json(['success' => false, 'message' => 'not found.'], 404);
|
||||
} catch (Exception $e) {
|
||||
} catch (\Exception $e) {
|
||||
return response()->json(['success' => false, 'message' => 'Failed to delete.'], 500);
|
||||
}
|
||||
}
|
||||
@@ -2387,14 +2381,14 @@ class SurveyorController extends Controller
|
||||
$path = $file->storeAs("public/surveyor/{$request->type}", $fileName);
|
||||
|
||||
if ($path === false) {
|
||||
throw new Exception("Failed to store file for {$fileKey}");
|
||||
throw new \Exception("Failed to store file for {$fileKey}");
|
||||
}
|
||||
if (isset($data[$fileKey]) && $data[$fileKey]) {
|
||||
$this->deleteFile($data[$fileKey]);
|
||||
}
|
||||
return str_replace('public/', '', $path);
|
||||
} else {
|
||||
throw new Exception("Invalid file upload for {$fileKey}");
|
||||
throw new \Exception("Invalid file upload for {$fileKey}");
|
||||
}
|
||||
} elseif (isset($data[$fileKey]) && $data[$fileKey]) {
|
||||
return $data[$fileKey];
|
||||
@@ -2423,14 +2417,14 @@ class SurveyorController extends Controller
|
||||
public function uploadFile($file, $type)
|
||||
{
|
||||
if (!$file->isValid()) {
|
||||
throw new Exception("Invalid file upload for {$type}");
|
||||
throw new \Exception("Invalid file upload for {$type}");
|
||||
}
|
||||
|
||||
$fileName = time() . '_' . $file->getClientOriginalName();
|
||||
$path = $file->storeAs("public/surveyor/{$type}", $fileName);
|
||||
|
||||
if ($path === false) {
|
||||
throw new Exception("Failed to store file for {$type}");
|
||||
throw new \Exception("Failed to store file for {$type}");
|
||||
}
|
||||
|
||||
return str_replace('public/', '', $path);
|
||||
@@ -2880,9 +2874,10 @@ class SurveyorController extends Controller
|
||||
$inspeksi->data_form = json_encode($existingData);
|
||||
$inspeksi->save();
|
||||
} else {
|
||||
Inspeksi::create([
|
||||
Inspeksi::updateOrCreate([
|
||||
'permohonan_id' => $request->input('permohonan_id'),
|
||||
'dokument_id' => $request->input('document_id'),
|
||||
'dokument_id' => $request->input('document_id')
|
||||
],[
|
||||
'data_form' => json_encode($existingData),
|
||||
]);
|
||||
}
|
||||
@@ -2903,5 +2898,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()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
33
app/Http/Requests/CategoryDaftarPustakaRequest.php
Normal file
33
app/Http/Requests/CategoryDaftarPustakaRequest.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class CategoryDaftarPustakaRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
$rules = [
|
||||
'name' => 'required|max:255',
|
||||
];
|
||||
|
||||
if ($this->method() == 'PUT') {
|
||||
$rules['code'] = 'required|max:50|unique:category_daftar_pustaka,code,' . $this->id;
|
||||
} else {
|
||||
$rules['code'] = 'required|max:50|unique:category_daftar_pustaka,code';
|
||||
}
|
||||
return $rules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
38
app/Http/Requests/DaftarPustakaRequest.php
Normal file
38
app/Http/Requests/DaftarPustakaRequest.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class DaftarPustakaRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
|
||||
$rules = [
|
||||
'judul' => 'required|max:255',
|
||||
'category_id' => 'required',
|
||||
'deskripsi' => 'nullable',
|
||||
];
|
||||
|
||||
if ($this->method() == 'PUT') {
|
||||
$rules['attachment'] = 'nullable|mimes:pdf,jpg,jpeg,png,gif';
|
||||
} else {
|
||||
$rules['attachment'] = 'required|mimes:pdf,jpg,jpeg,png,gif';
|
||||
}
|
||||
|
||||
return $rules;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@
|
||||
{
|
||||
$rules = [
|
||||
'name' => 'required|max:255',
|
||||
'biaya' => 'nullable|numeric|min:0',
|
||||
];
|
||||
|
||||
if ($this->method() == 'PUT') {
|
||||
|
||||
@@ -4,20 +4,164 @@
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
/**
|
||||
* Form Request untuk validasi data NOC (Notice of Completion)
|
||||
*/
|
||||
class NocRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Konstanta untuk jenis file yang diizinkan
|
||||
*/
|
||||
private const ALLOWED_FILE_TYPES = 'pdf,jpg,jpeg,png';
|
||||
|
||||
/**
|
||||
* Konstanta untuk ukuran file maksimum (dalam KB)
|
||||
*/
|
||||
private const MAX_FILE_SIZE = 10240;
|
||||
|
||||
/**
|
||||
* Menentukan apakah pengguna berwenang untuk melakukan request ini
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mengumpulkan semua aturan validasi
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return array_merge(
|
||||
$this->getBasicInfoRules(),
|
||||
$this->getPaymentRules(),
|
||||
$this->getSettlementRules(),
|
||||
$this->getAuthorizationRules(),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Aturan validasi untuk informasi dasar
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getBasicInfoRules()
|
||||
{
|
||||
return [
|
||||
'penawaran_id' => 'nullable|exists:penawaran,id',
|
||||
'nominal_bayar' => 'nullable|numeric|min:0',
|
||||
'bukti_ksl' => 'nullable|file|mimes:pdf,jpg,jpeg,png|max:10240',
|
||||
'status' => 'nullable|boolean',
|
||||
'permohonan_id' => 'nullable|exists:permohonan,id',
|
||||
'persetujuan_penawaran_id' => 'required|exists:persetujuan_penawaran,id',
|
||||
'status' => 'nullable|boolean',
|
||||
'created_by' => 'nullable|exists:users,id',
|
||||
'updated_by' => 'nullable|exists:users,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Aturan validasi untuk data pembayaran
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getPaymentRules()
|
||||
{
|
||||
$fileRule = 'nullable|file|mimes:' . self::ALLOWED_FILE_TYPES . '|max:' . self::MAX_FILE_SIZE;
|
||||
|
||||
return [
|
||||
'total_harus_bayar' => 'nullable|numeric|min:0',
|
||||
'nominal_bayar' => 'nullable|numeric|min:0',
|
||||
'total_pembukuan' => 'nullable|numeric|min:0',
|
||||
'bukti_ksl' => $fileRule,
|
||||
'bukti_bayar' => $fileRule,
|
||||
'status_bayar' => 'nullable|boolean',
|
||||
'tanggal_pembayaran' => 'nullable|date',
|
||||
'status_kurang_bayar' => 'nullable|boolean',
|
||||
'status_lebih_bayar' => 'nullable|boolean',
|
||||
'nominal_kurang_bayar' => 'nullable|numeric|min:0',
|
||||
'nominal_lebih_bayar' => 'nullable|numeric|min:0',
|
||||
'bukti_pengembalian' => 'nullable|file|mimes:pdf,jpg,jpeg,png|max:2048',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Aturan validasi untuk data penyelesaian
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getSettlementRules()
|
||||
{
|
||||
$fileRule = 'nullable|file|mimes:' . self::ALLOWED_FILE_TYPES . '|max:' . self::MAX_FILE_SIZE;
|
||||
|
||||
return [
|
||||
'nominal_penyelesaian' => 'nullable|numeric|min:0',
|
||||
'status_penyelesaian' => 'nullable|boolean',
|
||||
'tanggal_penyelesaian' => 'nullable|date',
|
||||
'bukti_penyelesaian' => $fileRule,
|
||||
'memo_penyelesaian' => $fileRule,
|
||||
'catatan_noc' => 'nullable|string',
|
||||
'nomor_tiket' => 'nullable|string',
|
||||
'nomor_rekening_lebih_bayar' => 'nullable|string',
|
||||
'bukti_ksl_lebih_bayar' => 'nullable|string',
|
||||
'bukti_ksl_kurang_bayar' => 'nullable|string'
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Aturan validasi untuk otorisasi
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getAuthorizationRules()
|
||||
{
|
||||
return [
|
||||
'authorized_status' => 'nullable|boolean',
|
||||
'authorized_at' => 'nullable|date',
|
||||
'authorized_by' => 'nullable|exists:users,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Pesan khusus untuk validasi
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function messages()
|
||||
{
|
||||
return [
|
||||
'permohonan_id.exists' => 'ID Permohonan tidak valid',
|
||||
'persetujuan_penawaran_id.required' => 'ID Persetujuan Penawaran harus diisi',
|
||||
'persetujuan_penawaran_id.exists' => 'ID Persetujuan Penawaran tidak valid',
|
||||
'nominal_bayar.numeric' => 'Nominal Bayar harus berupa angka',
|
||||
'nominal_bayar.min' => 'Nominal Bayar minimal 0',
|
||||
'bukti_ksl.file' => 'Bukti KSL harus berupa file',
|
||||
'bukti_ksl.mimes' => 'Bukti KSL harus berformat pdf, jpg, jpeg, atau png',
|
||||
'bukti_ksl.max' => 'Ukuran Bukti KSL maksimal 10MB',
|
||||
'bukti_bayar.file' => 'Bukti Bayar harus berupa file',
|
||||
'bukti_bayar.mimes' => 'Bukti Bayar harus berformat pdf, jpg, jpeg, atau png',
|
||||
'bukti_bayar.max' => 'Ukuran Bukti Bayar maksimal 10MB',
|
||||
'status.boolean' => 'Status harus berupa boolean',
|
||||
'status_bayar.boolean' => 'Status Bayar harus berupa boolean',
|
||||
'tanggal_pembayaran.date' => 'Format Tanggal Pembayaran tidak valid',
|
||||
'nominal_penyelesaian.numeric' => 'Nominal Penyelesaian harus berupa angka',
|
||||
'nominal_penyelesaian.min' => 'Nominal Penyelesaian minimal 0',
|
||||
'status_penyelesaian.boolean' => 'Status Penyelesaian harus berupa boolean',
|
||||
'tanggal_penyelesaian.date' => 'Format Tanggal Penyelesaian tidak valid',
|
||||
'bukti_penyelesaian.file' => 'Bukti Penyelesaian harus berupa file',
|
||||
'bukti_penyelesaian.mimes' => 'Bukti Penyelesaian harus berformat pdf, jpg, jpeg, atau png',
|
||||
'bukti_penyelesaian.max' => 'Ukuran Bukti Penyelesaian maksimal 10MB',
|
||||
'memo_penyelesaian.file' => 'Memo Penyelesaian harus berupa file',
|
||||
'memo_penyelesaian.mimes' => 'Memo Penyelesaian harus berformat pdf, jpg, jpeg, atau png',
|
||||
'memo_penyelesaian.max' => 'Ukuran Memo Penyelesaian maksimal 10MB',
|
||||
'authorized_status.boolean' => 'Status Otorisasi harus berupa boolean',
|
||||
'authorized_at.date' => 'Format Tanggal Otorisasi tidak valid',
|
||||
'authorized_by.exists' => 'User Otorisasi tidak valid',
|
||||
'status_kurang_bayar.boolean' => 'Status Kurang Bayar harus berupa boolean',
|
||||
'status_lebih_bayar.boolean' => 'Status Lebih Bayar harus berupa boolean',
|
||||
'nominal_kurang_bayar.numeric' => 'Nominal Kurang Bayar harus berupa angka',
|
||||
'nominal_kurang_bayar.min' => 'Nominal Kurang Bayar minimal 0',
|
||||
'nominal_lebih_bayar.numeric' => 'Nominal Lebih Bayar harus berupa angka',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,6 @@
|
||||
),
|
||||
'tanggal_permohonan' => date('Y-m-d'),
|
||||
'user_id' => auth()->user()->id,
|
||||
'branch_id' => auth()->user()->branch_id,
|
||||
'status' => 'order'
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -14,56 +14,54 @@
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'permohonan_id' => 'nullable|exists:permohonan,id',
|
||||
'penawaran_id' => 'nullable|exists:penawaran,id',
|
||||
'nomor_proposal_penawaran' => 'nullable|string|max:255',
|
||||
'tanggal_proposal_penawaran' => 'nullable|date',
|
||||
'biaya_final' => 'nullable|numeric|min:0',
|
||||
'sla_resume' => 'nullable|numeric|min:0',
|
||||
'sla_final' => 'nullable|numeric|min:0',
|
||||
'file_persetujuan_penawaran' => 'nullable|file|mimes:pdf,doc,docx|max:10240',
|
||||
'surat_representasi' => 'nullable|file|mimes:pdf,doc,docx|max:10240',
|
||||
'bukti_bayar' => 'nullable|file|mimes:pdf,jpg,jpeg,png|max:10240',
|
||||
'nominal_bayar' => 'nullable|numeric|min:0',
|
||||
'status' => 'nullable|boolean',
|
||||
'authorized_status' => 'boolean',
|
||||
'authorized_at' => 'nullable|date',
|
||||
'authorized_by' => 'nullable|exists:users,id',
|
||||
'catatan' => 'nullable|string',
|
||||
];
|
||||
'permohonan_id' => 'nullable|exists:permohonan,id',
|
||||
'penawaran_id' => 'nullable|exists:penawaran,id',
|
||||
'nomor_proposal_penawaran' => 'nullable|string|max:255',
|
||||
'nomor_tiket' => 'nullable|string|max:100',
|
||||
'nominal_kurang_bayar' => 'nullable|string|max:100',
|
||||
'bukti_ksl_kurang_bayar' => 'nullable|file|mimes:pdf,doc,docx|max:10240',
|
||||
'tanggal_proposal_penawaran' => 'nullable|date',
|
||||
'biaya_final' => 'nullable|numeric|min:0',
|
||||
'sla_resume' => 'nullable|numeric|min:0',
|
||||
'sla_final' => 'nullable|numeric|min:0',
|
||||
'file_persetujuan_penawaran' => 'nullable|file|mimes:pdf,doc,docx|max:10240',
|
||||
'surat_representasi' => 'nullable|file|mimes:pdf,doc,docx|max:10240',
|
||||
'status' => 'nullable|boolean',
|
||||
'authorized_status' => 'boolean',
|
||||
'authorized_at' => 'nullable|date',
|
||||
'authorized_by' => 'nullable|exists:users,id',
|
||||
'catatan' => 'nullable|string',
|
||||
];
|
||||
}
|
||||
|
||||
public function messages()
|
||||
{
|
||||
return [
|
||||
'penawaran_id.required' => 'Penawaran ID wajib diisi.',
|
||||
'penawaran_id.exists' => 'Penawaran ID tidak valid.',
|
||||
'nomor_proposal_penawaran.required' => 'Nomor proposal penawaran wajib diisi.',
|
||||
'tanggal_proposal_penawaran.required' => 'Tanggal proposal penawaran wajib diisi.',
|
||||
'tanggal_proposal_penawaran.date' => 'Tanggal proposal penawaran harus berupa tanggal yang valid.',
|
||||
'biaya_final.required' => 'Biaya final wajib diisi.',
|
||||
'biaya_final.numeric' => 'Biaya final harus berupa angka.',
|
||||
'biaya_final.min' => 'Biaya final tidak boleh kurang dari 0.',
|
||||
'sla_resume.required' => 'SLA Resume wajib diisi.',
|
||||
'sla_final.required' => 'SLA Final wajib diisi.',
|
||||
'file_persetujuan_penawaran.file' => 'File Persetujuan Penawaran harus berupa file.',
|
||||
'file_persetujuan_penawaran.mimes' => 'File Persetujuan Penawaran harus berupa file PDF, DOC, atau DOCX.',
|
||||
'file_persetujuan_penawaran.max' => 'Ukuran File Persetujuan Penawaran tidak boleh lebih dari 10MB.',
|
||||
'surat_representasi.file' => 'Surat Representasi harus berupa file.',
|
||||
'surat_representasi.mimes' => 'Surat Representasi harus berupa file PDF, DOC, atau DOCX.',
|
||||
'surat_representasi.max' => 'Ukuran Surat Representasi tidak boleh lebih dari 10MB.',
|
||||
'bukti_bayar.file' => 'Bukti Bayar harus berupa file.',
|
||||
'bukti_bayar.mimes' => 'Bukti Bayar harus berupa file PDF, JPG, JPEG, atau PNG.',
|
||||
'bukti_bayar.max' => 'Ukuran Bukti Bayar tidak boleh lebih dari 10MB.',
|
||||
'region_id.required' => 'Region ID wajib diisi.',
|
||||
'region_id.exists' => 'Region ID tidak valid.',
|
||||
'status.required' => 'Status wajib diisi.',
|
||||
'status.boolean' => 'Status harus berupa nilai boolean.',
|
||||
'authorized_status.boolean' => 'Status otorisasi harus berupa nilai boolean.',
|
||||
'authorized_at.date' => 'Tanggal otorisasi harus berupa tanggal yang valid.',
|
||||
'authorized_by.exists' => 'ID pengguna yang mengotorisasi tidak valid.',
|
||||
'status_bayar.required' => 'Status bayar wajib diisi.',
|
||||
'status_bayar.in' => 'Status bayar harus berupa "sudah_bayar", "belum_bayar" atau "tidak bayar".',
|
||||
];
|
||||
'penawaran_id.required' => 'Penawaran ID wajib diisi.',
|
||||
'penawaran_id.exists' => 'Penawaran ID tidak valid.',
|
||||
'nomor_proposal_penawaran.required' => 'Nomor proposal penawaran wajib diisi.',
|
||||
'nomor_tiket.string' => 'Nomor tiket harus berupa teks.',
|
||||
'nomor_tiket.max' => 'Nomor tiket tidak boleh lebih dari 100 karakter.',
|
||||
'tanggal_proposal_penawaran.required' => 'Tanggal proposal penawaran wajib diisi.',
|
||||
'tanggal_proposal_penawaran.date' => 'Tanggal proposal penawaran harus berupa tanggal yang valid.',
|
||||
'biaya_final.required' => 'Biaya final wajib diisi.',
|
||||
'biaya_final.numeric' => 'Biaya final harus berupa angka.',
|
||||
'biaya_final.min' => 'Biaya final tidak boleh kurang dari 0.',
|
||||
'sla_resume.required' => 'SLA Resume wajib diisi.',
|
||||
'sla_final.required' => 'SLA Final wajib diisi.',
|
||||
'file_persetujuan_penawaran.file' => 'File Persetujuan Penawaran harus berupa file.',
|
||||
'file_persetujuan_penawaran.mimes' => 'File Persetujuan Penawaran harus berupa file PDF, DOC, atau DOCX.',
|
||||
'file_persetujuan_penawaran.max' => 'Ukuran File Persetujuan Penawaran tidak boleh lebih dari 10MB.',
|
||||
'surat_representasi.file' => 'Surat Representasi harus berupa file.',
|
||||
'surat_representasi.mimes' => 'Surat Representasi harus berupa file PDF, DOC, atau DOCX.',
|
||||
'surat_representasi.max' => 'Ukuran Surat Representasi tidak boleh lebih dari 10MB.',
|
||||
'region_id.required' => 'Region ID wajib diisi.',
|
||||
'region_id.exists' => 'Region ID tidak valid.',
|
||||
'status.required' => 'Status wajib diisi.',
|
||||
'status.boolean' => 'Status harus berupa nilai boolean.',
|
||||
'authorized_status.boolean' => 'Status otorisasi harus berupa nilai boolean.',
|
||||
'authorized_at.date' => 'Tanggal otorisasi harus berupa tanggal yang valid.',
|
||||
'authorized_by.exists' => 'ID pengguna yang mengotorisasi tidak valid.',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
341
app/Imports/BucokImport.php
Normal file
341
app/Imports/BucokImport.php
Normal file
@@ -0,0 +1,341 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Imports;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Maatwebsite\Excel\Concerns\ToCollection;
|
||||
use Maatwebsite\Excel\Concerns\WithStartRow;
|
||||
use Maatwebsite\Excel\Concerns\WithValidation;
|
||||
use Maatwebsite\Excel\Concerns\WithBatchInserts;
|
||||
use Maatwebsite\Excel\Concerns\WithChunkReading;
|
||||
use Modules\Lpj\Models\Bucok;
|
||||
use Carbon\Carbon;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Kelas untuk mengimpor data Excel ke tabel bucoks
|
||||
* Menggunakan Laravel Excel dengan validasi dan batch processing
|
||||
* Data dimulai dari baris ke-5 tanpa header
|
||||
*/
|
||||
class BucokImport implements ToCollection, WithStartRow, WithValidation, WithBatchInserts, WithChunkReading
|
||||
{
|
||||
private $importedCount = 0;
|
||||
private $skippedCount = 0;
|
||||
private $createdCount = 0;
|
||||
private $updatedCount = 0;
|
||||
private $errors = [];
|
||||
|
||||
/**
|
||||
* Menentukan baris mulai membaca data (baris ke-5)
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function startRow(): int
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
|
||||
/**
|
||||
* Memproses koleksi data dari Excel
|
||||
*
|
||||
* @param Collection $collection
|
||||
* @return void
|
||||
*/
|
||||
public function collection(Collection $collection)
|
||||
{
|
||||
DB::beginTransaction();
|
||||
|
||||
try {
|
||||
foreach ($collection as $rowIndex => $row) {
|
||||
// Log setiap baris yang diproses
|
||||
Log::info('Processing Bucok import row', [
|
||||
'row_number' => $rowIndex + 5, // +5 karena mulai dari baris 5
|
||||
'row_data' => $row->toArray()
|
||||
]);
|
||||
|
||||
// Konversi row ke array dengan indeks numerik
|
||||
$rowArray = $row->toArray();
|
||||
|
||||
// Skip baris kosong
|
||||
if (empty(array_filter($rowArray))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Validasi data baris
|
||||
$mappedData = $this->mapRowToBucok($rowArray, $rowIndex + 5);
|
||||
|
||||
// Update atau create berdasarkan nomor_tiket
|
||||
if (!empty($mappedData['nomor_tiket'])) {
|
||||
// Update atau create berdasarkan nomor_tiket
|
||||
$bucok = Bucok::updateOrCreate(
|
||||
['nomor_tiket' => $mappedData['nomor_tiket']], // Kondisi pencarian
|
||||
array_merge($mappedData, ['updated_by' => auth()->id()]) // Data yang akan diupdate/create
|
||||
);
|
||||
|
||||
// Log dan tracking apakah data di-update atau di-create
|
||||
if ($bucok->wasRecentlyCreated) {
|
||||
$this->createdCount++;
|
||||
Log::info('Bucok created successfully', [
|
||||
'row_number' => $rowIndex + 5,
|
||||
'nomor_tiket' => $mappedData['nomor_tiket'],
|
||||
'action' => 'created'
|
||||
]);
|
||||
} else {
|
||||
$this->updatedCount++;
|
||||
Log::info('Bucok updated successfully', [
|
||||
'row_number' => $rowIndex + 5,
|
||||
'nomor_tiket' => $mappedData['nomor_tiket'],
|
||||
'action' => 'updated'
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
$this->importedCount++;
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
|
||||
// Log summary
|
||||
Log::info('Bucok import completed', [
|
||||
'imported' => $this->importedCount,
|
||||
'skipped' => $this->skippedCount,
|
||||
'total_errors' => count($this->errors)
|
||||
]);
|
||||
|
||||
} catch (Exception $e) {
|
||||
DB::rollback();
|
||||
Log::error('Bucok import failed', ['error' => $e->getMessage()]);
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mapping data Excel berdasarkan indeks kolom ke struktur model Bucok
|
||||
* Kolom dimulai dari indeks 0 (A=0, B=1, C=2, dst.)
|
||||
*
|
||||
* @param array $row
|
||||
* @param int $rowNumber
|
||||
* @return array
|
||||
*/
|
||||
private function mapRowToBucok(array $row, int $rowNumber): array
|
||||
{
|
||||
return [
|
||||
'no' => $row[0] ?? null, // Kolom A
|
||||
'tanggal' => !empty($row[1]) ? $this->parseDate($row[1]) : null, // Kolom B
|
||||
'bulan' => $row[2] ?? null, // Kolom C
|
||||
'tahun' => $row[3] ?? null, // Kolom D
|
||||
'tanggal_penuh' => !empty($row[4]) ? $this->parseDate($row[4]) : null, // Kolom E
|
||||
'nomor_categ' => $row[5] ?? null, // Kolom F
|
||||
'coa_summary' => $row[6] ?? null, // Kolom G
|
||||
'nomor_coa' => $row[7] ?? null, // Kolom H
|
||||
'nama_coa' => $row[8] ?? null, // Kolom I
|
||||
'nomor_tiket' => $row[9] ?? null, // Kolom J - Auto-generate jika kosong
|
||||
'deskripsi' => $row[10] ?? null, // Kolom K
|
||||
'nominal' => $this->parseNumeric($row[11] ?? 0), // Kolom L
|
||||
'penyelesaian' => $row[12] ?? 'Belum Selesai', // Kolom M
|
||||
'umur_aging' => $this->parseNumeric($row[13] ?? 0), // Kolom N
|
||||
'cost_center' => $row[14] ?? null, // Kolom O
|
||||
'nama_sub_direktorat' => $row[15] ?? null, // Kolom P
|
||||
'nama_direktorat_cabang' => $row[16] ?? null, // Kolom Q
|
||||
'tanggal_penyelesaian' => !empty($row[17]) ? $this->parseDate($row[17]) : null, // Kolom R
|
||||
'nominal_penyelesaian' => $this->parseNumeric($row[18] ?? 0), // Kolom S
|
||||
'nominal_berjalan' => $this->parseNumeric($row[19] ?? 0), // Kolom T
|
||||
'amortisasi_berjalan' => $this->parseNumeric($row[20] ?? 0), // Kolom U
|
||||
'sistem_berjalan' => $this->parseNumeric($row[21] ?? 0), // Kolom V
|
||||
'lainnya_berjalan' => $this->parseNumeric($row[22] ?? 0), // Kolom W
|
||||
'nominal_gantung' => $this->parseNumeric($row[23] ?? 0), // Kolom X
|
||||
'aset_gantung' => $this->parseNumeric($row[24] ?? 0), // Kolom Y
|
||||
'keterangan_gantung' => $row[25] ?? null, // Kolom Z
|
||||
'lainnya_satu' => $row[26] ?? null, // Kolom AA
|
||||
'lainnya_dua' => $row[27] ?? null, // Kolom AB
|
||||
'created_by' => auth()->id(),
|
||||
'updated_by' => auth()->id()
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse tanggal dari berbagai format
|
||||
*
|
||||
* @param mixed $dateValue
|
||||
* @return Carbon|null
|
||||
*/
|
||||
private function parseDate($dateValue)
|
||||
{
|
||||
if (empty($dateValue)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
// Jika berupa angka Excel date serial
|
||||
if (is_numeric($dateValue)) {
|
||||
return Carbon::createFromFormat('Y-m-d', \PhpOffice\PhpSpreadsheet\Shared\Date::excelToDateTimeObject($dateValue)->format('Y-m-d'));
|
||||
}
|
||||
|
||||
// Jika berupa string tanggal
|
||||
return Carbon::parse($dateValue);
|
||||
} catch (Exception $e) {
|
||||
Log::warning('Failed to parse date', ['value' => $dateValue, 'error' => $e->getMessage()]);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse nilai numerik dari berbagai format
|
||||
*
|
||||
* @param mixed $numericValue
|
||||
* @return float
|
||||
*/
|
||||
private function parseNumeric($numericValue): float
|
||||
{
|
||||
if (empty($numericValue)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Hapus karakter non-numerik kecuali titik dan koma
|
||||
$cleaned = preg_replace('/[^0-9.,\-]/', '', $numericValue);
|
||||
|
||||
// Ganti koma dengan titik untuk decimal
|
||||
$cleaned = str_replace(',', '.', $cleaned);
|
||||
|
||||
return (float) $cleaned;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validasi data yang sudah dimapping
|
||||
*
|
||||
* @param array $data
|
||||
* @return \Illuminate\Validation\Validator
|
||||
*/
|
||||
private function validateMappedData(array $data)
|
||||
{
|
||||
return Validator::make($data, [
|
||||
'no' => 'nullable|integer',
|
||||
'tanggal' => 'nullable|date',
|
||||
'bulan' => 'nullable|integer|between:1,12',
|
||||
'tahun' => 'nullable|integer|min:2000|max:2099',
|
||||
'tanggal_penuh' => 'nullable|date',
|
||||
'nomor_categ' => 'nullable|string|max:50',
|
||||
'coa_summary' => 'nullable|string|max:255',
|
||||
'nomor_coa' => 'nullable|string|max:50',
|
||||
'nama_coa' => 'nullable|string|max:255',
|
||||
'nomor_tiket' => 'nullable|string|max:50',
|
||||
'deskripsi' => 'nullable|string',
|
||||
'nominal' => 'nullable|numeric|min:0',
|
||||
'penyelesaian' => 'nullable|in:Selesai,Belum Selesai,Dalam Proses',
|
||||
'umur_aging' => 'nullable|integer|min:0',
|
||||
'cost_center' => 'nullable|string|max:100',
|
||||
'nama_sub_direktorat' => 'nullable|string|max:255',
|
||||
'nama_direktorat_cabang' => 'nullable|string|max:255',
|
||||
'tanggal_penyelesaian' => 'nullable|date',
|
||||
'nominal_penyelesaian' => 'nullable|numeric|min:0',
|
||||
'nominal_berjalan' => 'nullable|numeric|min:0',
|
||||
'amortisasi_berjalan' => 'nullable|numeric|min:0',
|
||||
'sistem_berjalan' => 'nullable|numeric|min:0',
|
||||
'lainnya_berjalan' => 'nullable|numeric|min:0',
|
||||
'nominal_gantung' => 'nullable|numeric|min:0',
|
||||
'aset_gantung' => 'nullable|numeric|min:0',
|
||||
'keterangan_gantung' => 'nullable|string',
|
||||
'lainnya_satu' => 'nullable|string',
|
||||
'lainnya_dua' => 'nullable|string'
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Aturan validasi untuk seluruh file Excel (tidak digunakan karena tanpa header)
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Ukuran batch untuk insert
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function batchSize(): int
|
||||
{
|
||||
return 100;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ukuran chunk untuk membaca file
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function chunkSize(): int
|
||||
{
|
||||
return 100;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mendapatkan jumlah data yang berhasil diimpor
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getImportedCount(): int
|
||||
{
|
||||
return $this->importedCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mendapatkan jumlah data yang berhasil dibuat
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getCreatedCount(): int
|
||||
{
|
||||
return $this->createdCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mendapatkan jumlah data yang berhasil diupdate
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getUpdatedCount(): int
|
||||
{
|
||||
return $this->updatedCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mendapatkan statistik lengkap import
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getImportStatistics(): array
|
||||
{
|
||||
return [
|
||||
'total_processed' => $this->importedCount,
|
||||
'created' => $this->createdCount,
|
||||
'updated' => $this->updatedCount,
|
||||
'skipped' => $this->skippedCount,
|
||||
'errors' => count($this->errors)
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Mendapatkan jumlah data yang dilewati
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getSkippedCount(): int
|
||||
{
|
||||
return $this->skippedCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mendapatkan daftar error yang terjadi
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getErrors(): array
|
||||
{
|
||||
return $this->errors;
|
||||
}
|
||||
}
|
||||
415
app/Imports/SlikImport.php
Normal file
415
app/Imports/SlikImport.php
Normal file
@@ -0,0 +1,415 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Imports;
|
||||
|
||||
use Modules\Lpj\Models\Slik;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Maatwebsite\Excel\Concerns\ToCollection;
|
||||
use Maatwebsite\Excel\Concerns\WithStartRow;
|
||||
use Maatwebsite\Excel\Concerns\WithChunkReading;
|
||||
use Maatwebsite\Excel\Concerns\WithBatchInserts;
|
||||
use Maatwebsite\Excel\Concerns\WithCustomCsvSettings;
|
||||
|
||||
|
||||
/**
|
||||
* Class SlikImport
|
||||
*
|
||||
* Handle import data Excel untuk modul Slik
|
||||
* Menggunakan Laravel Excel package untuk membaca file Excel
|
||||
* dengan optimasi memory dan chunk processing
|
||||
*
|
||||
* @package Modules\Lpj\app\Imports
|
||||
*/
|
||||
class SlikImport implements ToCollection, WithStartRow, WithBatchInserts, WithChunkReading, WithCustomCsvSettings
|
||||
{
|
||||
/**
|
||||
* Mulai membaca dari baris ke-5 (skip header)
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function startRow(): int
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch size untuk insert data dari konfigurasi
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function batchSize(): int
|
||||
{
|
||||
return config('import.slik.batch_size', 50);
|
||||
}
|
||||
|
||||
/**
|
||||
* Chunk size untuk membaca file dari konfigurasi
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function chunkSize(): int
|
||||
{
|
||||
return config('import.slik.chunk_size', 50);
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom CSV settings untuk optimasi pembacaan file
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getCsvSettings(): array
|
||||
{
|
||||
return [
|
||||
'input_encoding' => 'UTF-8',
|
||||
'delimiter' => ',',
|
||||
'enclosure' => '"',
|
||||
'escape_character' => '\\',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Process collection data dari Excel dengan optimasi memory
|
||||
*
|
||||
* @param Collection $collection
|
||||
* @return void
|
||||
*/
|
||||
public function collection(Collection $collection)
|
||||
{
|
||||
// Set memory limit dari konfigurasi
|
||||
$memoryLimit = config('import.slik.memory_limit', 1024);
|
||||
$currentMemoryLimit = ini_get('memory_limit');
|
||||
|
||||
if ($currentMemoryLimit !== '-1' && $this->convertToBytes($currentMemoryLimit) < $memoryLimit * 1024 * 1024) {
|
||||
ini_set('memory_limit', $memoryLimit . 'M');
|
||||
}
|
||||
|
||||
// Set timeout handler
|
||||
$timeout = config('import.slik.timeout', 1800);
|
||||
set_time_limit($timeout);
|
||||
|
||||
// Force garbage collection sebelum memulai
|
||||
if (config('import.slik.enable_gc', true)) {
|
||||
gc_collect_cycles();
|
||||
}
|
||||
|
||||
Log::info('SlikImport: Memulai import data', [
|
||||
'total_rows' => $collection->count(),
|
||||
'memory_usage' => memory_get_usage(true),
|
||||
'memory_peak' => memory_get_peak_usage(true),
|
||||
'memory_limit' => ini_get('memory_limit'),
|
||||
'php_version' => PHP_VERSION,
|
||||
'memory_limit_before' => $currentMemoryLimit,
|
||||
'config' => [
|
||||
'memory_limit' => $memoryLimit,
|
||||
'chunk_size' => $this->chunkSize(),
|
||||
'batch_size' => $this->batchSize()
|
||||
]
|
||||
]);
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
try {
|
||||
$processedRows = 0;
|
||||
$skippedRows = 0;
|
||||
$errorRows = 0;
|
||||
$totalRows = $collection->count();
|
||||
|
||||
foreach ($collection as $index => $row) {
|
||||
// Log progress setiap 25 baris untuk chunk lebih kecil
|
||||
if ($index % 25 === 0) {
|
||||
Log::info('SlikImport: Processing chunk', [
|
||||
'current_row' => $index + 5,
|
||||
'progress' => round(($index / max($totalRows, 1)) * 100, 2) . '%',
|
||||
'processed' => $processedRows,
|
||||
'skipped' => $skippedRows,
|
||||
'errors' => $errorRows,
|
||||
'memory_usage' => memory_get_usage(true),
|
||||
'memory_peak' => memory_get_peak_usage(true),
|
||||
'memory_diff' => memory_get_peak_usage(true) - memory_get_usage(true)
|
||||
]);
|
||||
}
|
||||
|
||||
// Skip baris kosong
|
||||
if ($this->isEmptyRow($row)) {
|
||||
$skippedRows++;
|
||||
Log::debug('SlikImport: Skipping empty row', ['row_number' => $index + 5]);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Validasi data
|
||||
if (!$this->validateRow($row)) {
|
||||
$errorRows++;
|
||||
Log::warning('SlikImport: Invalid row data', [
|
||||
'row_number' => $index + 5,
|
||||
'data' => $row->toArray()
|
||||
]);
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
// Map data dari Excel ke model
|
||||
$slikData = $this->mapRowToSlik($row);
|
||||
|
||||
// Update atau create berdasarkan no_rekening dan cif
|
||||
$slik = Slik::updateOrCreate(
|
||||
[
|
||||
'no_rekening' => $slikData['no_rekening'],
|
||||
'cif' => $slikData['cif']
|
||||
],
|
||||
$slikData
|
||||
);
|
||||
|
||||
$processedRows++;
|
||||
|
||||
// Log detail untuk baris pertama sebagai sample
|
||||
if ($index === 0) {
|
||||
Log::info('SlikImport: Sample data processed', [
|
||||
'slik_id' => $slik->id,
|
||||
'no_rekening' => $slik->no_rekening,
|
||||
'cif' => $slik->cif,
|
||||
'was_recently_created' => $slik->wasRecentlyCreated
|
||||
]);
|
||||
}
|
||||
|
||||
// Force garbage collection setiap 25 baris untuk mengurangi memory
|
||||
if (config('import.slik.enable_gc', true) && $index > 0 && $index % 25 === 0) {
|
||||
gc_collect_cycles();
|
||||
}
|
||||
|
||||
// Unset data yang sudah tidak digunakan untuk mengurangi memory
|
||||
if ($index > 0 && $index % 25 === 0) {
|
||||
unset($slikData, $slik);
|
||||
}
|
||||
|
||||
// Reset collection internal untuk mengurangi memory
|
||||
if ($index > 0 && $index % 100 === 0) {
|
||||
$collection = collect($collection->slice($index + 1)->values());
|
||||
}
|
||||
|
||||
} catch (\Exception $e) {
|
||||
$errorRows++;
|
||||
Log::error('SlikImport: Error processing row', [
|
||||
'row_number' => $index + 5,
|
||||
'error' => $e->getMessage(),
|
||||
'data' => $row->toArray(),
|
||||
'memory_usage' => memory_get_usage(true)
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
|
||||
// Force garbage collection setelah selesai
|
||||
if (config('import.slik.enable_gc', true)) {
|
||||
gc_collect_cycles();
|
||||
}
|
||||
|
||||
// Cleanup variables
|
||||
unset($collection);
|
||||
|
||||
Log::info('SlikImport: Import berhasil diselesaikan', [
|
||||
'total_rows' => $totalRows,
|
||||
'processed_rows' => $processedRows,
|
||||
'skipped_rows' => $skippedRows,
|
||||
'error_rows' => $errorRows,
|
||||
'final_memory_usage' => memory_get_usage(true),
|
||||
'peak_memory_usage' => memory_get_peak_usage(true),
|
||||
'memory_saved' => memory_get_peak_usage(true) - memory_get_usage(true),
|
||||
'memory_efficiency' => ($processedRows > 0) ? round(memory_get_peak_usage(true) / $processedRows, 2) : 0
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
|
||||
// Force garbage collection jika error
|
||||
if (config('import.slik.enable_gc', true)) {
|
||||
gc_collect_cycles();
|
||||
}
|
||||
|
||||
$errorType = 'general';
|
||||
if (str_contains(strtolower($e->getMessage()), 'memory')) {
|
||||
$errorType = 'memory';
|
||||
} elseif (str_contains(strtolower($e->getMessage()), 'timeout') || str_contains(strtolower($e->getMessage()), 'maximum execution time')) {
|
||||
$errorType = 'timeout';
|
||||
}
|
||||
|
||||
Log::error('SlikImport: Error during import', [
|
||||
'error' => $e->getMessage(),
|
||||
'error_type' => $errorType,
|
||||
'exception_type' => get_class($e),
|
||||
'trace' => $e->getTraceAsString(),
|
||||
'file' => $e->getFile(),
|
||||
'line' => $e->getLine(),
|
||||
'memory_usage' => memory_get_usage(true),
|
||||
'memory_peak' => memory_get_peak_usage(true),
|
||||
'memory_limit' => ini_get('memory_limit'),
|
||||
'timeout_limit' => ini_get('max_execution_time'),
|
||||
'is_memory_error' => str_contains(strtolower($e->getMessage()), 'memory'),
|
||||
'is_timeout_error' => str_contains(strtolower($e->getMessage()), 'timeout') || str_contains(strtolower($e->getMessage()), 'maximum execution time')
|
||||
]);
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert memory limit string ke bytes
|
||||
*
|
||||
* @param string $memoryLimit
|
||||
* @return int
|
||||
*/
|
||||
private function convertToBytes(string $memoryLimit): int
|
||||
{
|
||||
$memoryLimit = trim($memoryLimit);
|
||||
$lastChar = strtolower(substr($memoryLimit, -1));
|
||||
$number = (int) substr($memoryLimit, 0, -1);
|
||||
|
||||
switch ($lastChar) {
|
||||
case 'g':
|
||||
return $number * 1024 * 1024 * 1024;
|
||||
case 'm':
|
||||
return $number * 1024 * 1024;
|
||||
case 'k':
|
||||
return $number * 1024;
|
||||
default:
|
||||
return (int) $memoryLimit;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cek apakah baris kosong
|
||||
*
|
||||
* @param Collection $row
|
||||
* @return bool
|
||||
*/
|
||||
private function isEmptyRow(Collection $row): bool
|
||||
{
|
||||
return $row->filter(function ($value) {
|
||||
return !empty(trim($value));
|
||||
})->isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validasi data baris
|
||||
*
|
||||
* @param Collection $row
|
||||
* @return bool
|
||||
*/
|
||||
private function validateRow(Collection $row): bool
|
||||
{
|
||||
// Validasi minimal: sandi_bank, no_rekening, dan cif harus ada
|
||||
return !empty(trim($row[0])) && // sandi_bank
|
||||
!empty(trim($row[5])) && // no_rekening
|
||||
!empty(trim($row[6])); // cif
|
||||
}
|
||||
|
||||
/**
|
||||
* Map data dari baris Excel ke array untuk model Slik
|
||||
*
|
||||
* @param Collection $row
|
||||
* @return array
|
||||
*/
|
||||
private function mapRowToSlik(Collection $row): array
|
||||
{
|
||||
return [
|
||||
'sandi_bank' => trim($row[0]) ?: null,
|
||||
'tahun' => $this->parseInteger($row[1]),
|
||||
'bulan' => $this->parseInteger($row[2]),
|
||||
'flag_detail' => trim($row[3]) ?: null,
|
||||
'kode_register_agunan' => trim($row[4]) ?: null,
|
||||
'no_rekening' => trim($row[5]) ?: null,
|
||||
'cif' => trim($row[6]) ?: null,
|
||||
'kolektibilitas' => trim($row[7]) ?: null,
|
||||
'fasilitas' => trim($row[8]) ?: null,
|
||||
'jenis_segmen_fasilitas' => trim($row[9]) ?: null,
|
||||
'status_agunan' => trim($row[10]) ?: null,
|
||||
'jenis_agunan' => trim($row[11]) ?: null,
|
||||
'peringkat_agunan' => trim($row[12]) ?: null,
|
||||
'lembaga_pemeringkat' => trim($row[13]) ?: null,
|
||||
'jenis_pengikatan' => trim($row[14]) ?: null,
|
||||
'tanggal_pengikatan' => $this->parseDate($row[15]),
|
||||
'nama_pemilik_agunan' => trim($row[16]) ?: null,
|
||||
'bukti_kepemilikan' => trim($row[17]) ?: null,
|
||||
'alamat_agunan' => trim($row[18]) ?: null,
|
||||
'lokasi_agunan' => trim($row[19]) ?: null,
|
||||
'nilai_agunan' => $this->parseDecimal($row[20]),
|
||||
'nilai_agunan_menurut_ljk' => $this->parseDecimal($row[21]),
|
||||
'tanggal_penilaian_ljk' => $this->parseDate($row[22]),
|
||||
'nilai_agunan_penilai_independen' => $this->parseDecimal($row[23]),
|
||||
'nama_penilai_independen' => trim($row[24]) ?: null,
|
||||
'tanggal_penilaian_penilai_independen' => $this->parseDate($row[25]),
|
||||
'jumlah_hari_tunggakan' => $this->parseInteger($row[26]),
|
||||
'status_paripasu' => trim($row[27]) ?: null,
|
||||
'prosentase_paripasu' => $this->parseDecimal($row[28]),
|
||||
'status_kredit_join' => trim($row[29]) ?: null,
|
||||
'diasuransikan' => trim($row[30]) ?: null,
|
||||
'keterangan' => trim($row[31]) ?: null,
|
||||
'kantor_cabang' => trim($row[32]) ?: null,
|
||||
'operasi_data' => trim($row[33]) ?: null,
|
||||
'kode_cabang' => trim($row[34]) ?: null,
|
||||
'nama_debitur' => trim($row[35]) ?: null,
|
||||
'nama_cabang' => trim($row[36]) ?: null,
|
||||
'flag' => trim($row[37]) ?: null,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse integer value
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return int|null
|
||||
*/
|
||||
private function parseInteger($value): ?int
|
||||
{
|
||||
if (empty(trim($value))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (int) $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse decimal value
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return float|null
|
||||
*/
|
||||
private function parseDecimal($value): ?float
|
||||
{
|
||||
if (empty(trim($value))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Remove currency formatting
|
||||
$cleaned = str_replace([',', '.'], ['', '.'], $value);
|
||||
$cleaned = preg_replace('/[^0-9.]/', '', $cleaned);
|
||||
|
||||
return (float) $cleaned;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse date value
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return string|null
|
||||
*/
|
||||
private function parseDate($value): ?string
|
||||
{
|
||||
if (empty(trim($value))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
// Try to parse various date formats
|
||||
$date = \Carbon\Carbon::parse($value);
|
||||
return $date->format('Y-m-d');
|
||||
} catch (\Exception $e) {
|
||||
Log::warning('SlikImport: Invalid date format', [
|
||||
'value' => $value,
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
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()
|
||||
]);
|
||||
}
|
||||
}
|
||||
179
app/Jobs/ProcessSlikImport.php
Normal file
179
app/Jobs/ProcessSlikImport.php
Normal file
@@ -0,0 +1,179 @@
|
||||
<?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\Log;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Modules\Lpj\Imports\SlikImport;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
|
||||
class ProcessSlikImport implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
public $timeout = 1800; // 30 menit untuk file besar
|
||||
public $tries = 5; // Tambah retry untuk file sangat besar
|
||||
public $maxExceptions = 5;
|
||||
public $backoff = [60, 300, 900, 1800, 3600]; // Exponential backoff dalam detik
|
||||
|
||||
protected string $filePath;
|
||||
protected int $userId;
|
||||
protected string $importId;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @param string $filePath
|
||||
* @param int $userId
|
||||
* @param string $importId
|
||||
*/
|
||||
public function __construct(string $filePath, int $userId, string $importId)
|
||||
{
|
||||
$this->filePath = $filePath;
|
||||
$this->userId = $userId;
|
||||
$this->importId = $importId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle(): void
|
||||
{
|
||||
Log::info('ProcessSlikImport: Memulai proses import via queue', [
|
||||
'file_path' => $this->filePath,
|
||||
'user_id' => $this->userId,
|
||||
'import_id' => $this->importId,
|
||||
'memory_limit' => ini_get('memory_limit'),
|
||||
'max_execution_time' => ini_get('max_execution_time')
|
||||
]);
|
||||
|
||||
try {
|
||||
// Cek file size terlebih dahulu
|
||||
$fileSize = filesize($this->filePath);
|
||||
$maxFileSize = config('import.slik.max_file_size', 50) * 1024 * 1024; // Convert MB to bytes
|
||||
|
||||
if ($fileSize > $maxFileSize) {
|
||||
throw new \Exception('File terlalu besar: ' . number_format($fileSize / 1024 / 1024, 2) . ' MB. Maksimum: ' . config('import.slik.max_file_size', 50) . ' MB');
|
||||
}
|
||||
|
||||
// Set optimasi memory untuk queue processing
|
||||
$memoryLimit = config('import.slik.memory_limit', 1024);
|
||||
ini_set('memory_limit', $memoryLimit . 'M');
|
||||
ini_set('max_execution_time', config('import.slik.timeout', 1800));
|
||||
|
||||
// Set timeout untuk XML Scanner
|
||||
$xmlScannerTimeout = config('import.slik.xml_scanner.timeout', 1800);
|
||||
$xmlScannerMemory = config('import.slik.xml_scanner.memory_limit', 1024);
|
||||
|
||||
// Enable garbage collection jika diizinkan
|
||||
if (config('import.slik.enable_gc', true)) {
|
||||
gc_enable();
|
||||
}
|
||||
|
||||
// Update progress status
|
||||
$this->updateProgress('processing', 0, 'Memproses file Excel...');
|
||||
|
||||
Log::info('SlikImport: Processing file', [
|
||||
'file' => basename($this->filePath),
|
||||
'file_size' => number_format(filesize($this->filePath) / 1024 / 1024, 2) . ' MB',
|
||||
'memory_limit' => $memoryLimit . 'M',
|
||||
'timeout' => config('import.slik.timeout', 1800),
|
||||
'enable_gc' => config('import.slik.enable_gc', true),
|
||||
'xml_scanner_timeout' => config('import.slik.xml_scanner.timeout', 1800),
|
||||
'chunk_size' => config('import.slik.chunk_size', 50),
|
||||
'batch_size' => config('import.slik.batch_size', 50),
|
||||
]);
|
||||
|
||||
// Import file menggunakan SlikImport
|
||||
$import = new SlikImport();
|
||||
Excel::import($import, $this->filePath);
|
||||
|
||||
// Update progress selesai
|
||||
$this->updateProgress('completed', 100, 'Import berhasil diselesaikan');
|
||||
|
||||
Log::info('ProcessSlikImport: Import berhasil diselesaikan', [
|
||||
'import_id' => $this->importId,
|
||||
'file_path' => $this->filePath,
|
||||
'memory_usage' => memory_get_usage(true),
|
||||
'memory_peak' => memory_get_peak_usage(true)
|
||||
]);
|
||||
|
||||
// Hapus file temporary setelah selesai
|
||||
if (config('import.general.cleanup_temp_files', true)) {
|
||||
Storage::delete($this->filePath);
|
||||
Log::info('ProcessSlikImport: File temporary dihapus', ['file_path' => $this->filePath]);
|
||||
}
|
||||
|
||||
} catch (\Exception $e) {
|
||||
// Update progress error
|
||||
$this->updateProgress('failed', 0, 'Error: ' . $e->getMessage());
|
||||
|
||||
Log::error('ProcessSlikImport: Error saat proses import', [
|
||||
'import_id' => $this->importId,
|
||||
'error' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString(),
|
||||
'file' => $e->getFile(),
|
||||
'line' => $e->getLine(),
|
||||
'memory_usage' => memory_get_usage(true)
|
||||
]);
|
||||
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update progress import
|
||||
*
|
||||
* @param string $status
|
||||
* @param int $percentage
|
||||
* @param string $message
|
||||
* @return void
|
||||
*/
|
||||
private function updateProgress(string $status, int $percentage, string $message): void
|
||||
{
|
||||
if (config('import.slik.progress.enabled', true)) {
|
||||
$cacheKey = config('import.slik.progress.cache_key', 'slik_import_progress') . '_' . $this->importId;
|
||||
$cacheTtl = config('import.slik.progress.cache_ttl', 3600);
|
||||
|
||||
$progressData = [
|
||||
'status' => $status,
|
||||
'percentage' => $percentage,
|
||||
'message' => $message,
|
||||
'timestamp' => now(),
|
||||
'user_id' => $this->userId
|
||||
];
|
||||
|
||||
cache()->put($cacheKey, $progressData, $cacheTtl);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle job failure
|
||||
*
|
||||
* @param \Throwable $exception
|
||||
* @return void
|
||||
*/
|
||||
public function failed(\Throwable $exception): void
|
||||
{
|
||||
Log::error('ProcessSlikImport: Job failed', [
|
||||
'import_id' => $this->importId,
|
||||
'error' => $exception->getMessage(),
|
||||
'trace' => $exception->getTraceAsString()
|
||||
]);
|
||||
|
||||
// Update progress ke failed
|
||||
$this->updateProgress('failed', 0, 'Import gagal: ' . $exception->getMessage());
|
||||
|
||||
// Cleanup file temporary
|
||||
if (Storage::exists($this->filePath)) {
|
||||
Storage::delete($this->filePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Modules\Lpj\Database\Factories\AnalisaFactory;
|
||||
|
||||
class Analisa extends Model
|
||||
class Analisa extends Base
|
||||
{
|
||||
use HasFactory;
|
||||
protected $table = 'analisa';
|
||||
|
||||
@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Modules\Lpj\Database\Factories\AnalisaFaktaFactory;
|
||||
|
||||
class AnalisaFakta extends Model
|
||||
class AnalisaFakta extends Base
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Modules\Lpj\Database\Factories\AnalisaLingkunganFactory;
|
||||
|
||||
class AnalisaLingkungan extends Model
|
||||
class AnalisaLingkungan extends Base
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Modules\Lpj\Database\Factories\AnalisaTanahBagunanFactory;
|
||||
|
||||
class AnalisaTanahBagunan extends Model
|
||||
class AnalisaTanahBagunan extends Base
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Modules\Lpj\Database\Factories\AnalisaUnitFactory;
|
||||
|
||||
class AnalisaUnit extends Model
|
||||
class AnalisaUnit extends Base
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Spatie\Activitylog\LogOptions;
|
||||
use Spatie\Activitylog\Traits\LogsActivity;
|
||||
use Wildside\Userstamps\Userstamps;
|
||||
use Mattiverse\Userstamps\Traits\Userstamps;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
|
||||
|
||||
/**
|
||||
@@ -14,7 +15,7 @@
|
||||
*/
|
||||
class Base extends Model
|
||||
{
|
||||
use LogsActivity, SoftDeletes, Userstamps;
|
||||
use LogsActivity, SoftDeletes, Userstamps, Notifiable;
|
||||
|
||||
protected $connection;
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Modules\Lpj\Database\Factories\BentukTanahFactory;
|
||||
|
||||
class BentukTanah extends Model
|
||||
class BentukTanah extends Base
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
// use Modules\Lpj\Database\Factories\BentukUnitFactory;
|
||||
|
||||
class BentukUnit extends Model
|
||||
class BentukUnit extends Base
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
|
||||
115
app/Models/Bucok.php
Normal file
115
app/Models/Bucok.php
Normal file
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Models;
|
||||
|
||||
use Illuminate\Foundation\Auth\User;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* Model Bucok untuk mengelola data bucok
|
||||
*
|
||||
* @property int $id
|
||||
* @property int|null $no
|
||||
* @property string|null $tanggal
|
||||
* @property string|null $bulan
|
||||
* @property int|null $tahun
|
||||
* @property string|null $tanggal_penuh
|
||||
* @property string|null $nomor_categ
|
||||
* @property string|null $coa_summary
|
||||
* @property string|null $nomor_coa
|
||||
* @property string|null $nama_coa
|
||||
* @property string $nomor_tiket
|
||||
* @property string|null $deskripsi
|
||||
* @property float|null $nominal
|
||||
* @property string|null $penyelesaian
|
||||
* @property int|null $umur_aging
|
||||
* @property string|null $cost_center
|
||||
* @property string|null $nama_sub_direktorat
|
||||
* @property string|null $nama_direktorat_cabang
|
||||
* @property string|null $tanggal_penyelesaian
|
||||
* @property float|null $nominal_penyelesaian
|
||||
* @property float|null $nominal_berjalan
|
||||
* @property float|null $amortisasi_berjalan
|
||||
* @property float|null $sistem_berjalan
|
||||
* @property float|null $lainnya_berjalan
|
||||
* @property float|null $nominal_gantung
|
||||
* @property float|null $aset_gantung
|
||||
* @property string|null $keterangan_gantung
|
||||
* @property string|null $lainnya_satu
|
||||
* @property string|null $lainnya_dua
|
||||
*/
|
||||
class Bucok extends Base
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
/**
|
||||
* Nama tabel yang digunakan oleh model
|
||||
*/
|
||||
protected $table = 'bucoks';
|
||||
|
||||
/**
|
||||
* Field yang dapat diisi secara mass assignment
|
||||
*/
|
||||
protected $fillable = [
|
||||
'no',
|
||||
'tanggal',
|
||||
'bulan',
|
||||
'tahun',
|
||||
'tanggal_penuh',
|
||||
'nomor_categ',
|
||||
'coa_summary',
|
||||
'nomor_coa',
|
||||
'nama_coa',
|
||||
'nomor_tiket',
|
||||
'deskripsi',
|
||||
'nominal',
|
||||
'penyelesaian',
|
||||
'umur_aging',
|
||||
'cost_center',
|
||||
'nama_sub_direktorat',
|
||||
'nama_direktorat_cabang',
|
||||
'tanggal_penyelesaian',
|
||||
'nominal_penyelesaian',
|
||||
'nominal_berjalan',
|
||||
'amortisasi_berjalan',
|
||||
'sistem_berjalan',
|
||||
'lainnya_berjalan',
|
||||
'nominal_gantung',
|
||||
'aset_gantung',
|
||||
'keterangan_gantung',
|
||||
'lainnya_satu',
|
||||
'lainnya_dua',
|
||||
'nomor_registrasi',
|
||||
'permohonan_id',
|
||||
];
|
||||
|
||||
/**
|
||||
* Casting tipe data untuk field tertentu
|
||||
*/
|
||||
protected $casts = [
|
||||
'no' => 'integer',
|
||||
'tanggal' => 'date',
|
||||
'tahun' => 'integer',
|
||||
'tanggal_penuh' => 'date',
|
||||
'nominal' => 'decimal:2',
|
||||
'umur_aging' => 'integer',
|
||||
'tanggal_penyelesaian' => 'date',
|
||||
'nominal_penyelesaian' => 'decimal:2',
|
||||
'nominal_berjalan' => 'decimal:2',
|
||||
'amortisasi_berjalan' => 'decimal:2',
|
||||
'sistem_berjalan' => 'decimal:2',
|
||||
'lainnya_berjalan' => 'decimal:2',
|
||||
'nominal_gantung' => 'decimal:2',
|
||||
'aset_gantung' => 'decimal:2',
|
||||
];
|
||||
|
||||
/**
|
||||
* Field yang akan di-hidden saat serialization
|
||||
*/
|
||||
protected $hidden = [
|
||||
'created_by',
|
||||
'updated_by',
|
||||
'deleted_by',
|
||||
];
|
||||
}
|
||||
27
app/Models/CategoryDaftarPustaka.php
Normal file
27
app/Models/CategoryDaftarPustaka.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
// use Modules\Lpj\Database\Factories\CategoryDaftarPustakaFactory;
|
||||
|
||||
class CategoryDaftarPustaka extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $table = 'category_daftar_pustaka';
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*/
|
||||
protected $fillable = [
|
||||
'id',
|
||||
'name',
|
||||
'code',
|
||||
];
|
||||
|
||||
public function daftarPustaka(){
|
||||
return $this->hasMany(DaftarPustaka::class);
|
||||
}
|
||||
|
||||
}
|
||||
29
app/Models/DaftarPustaka.php
Normal file
29
app/Models/DaftarPustaka.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
// use Modules\Lpj\Database\Factories\DaftarPustakaFactory;
|
||||
|
||||
class DaftarPustaka extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $table = 'daftar_pustaka';
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*/
|
||||
protected $fillable = [
|
||||
'id',
|
||||
'category_id',
|
||||
'judul',
|
||||
'attachment',
|
||||
'deskripsi',
|
||||
];
|
||||
|
||||
public function category(){
|
||||
return $this->belongsTo(CategoryDaftarPustaka::class);
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Modules\Lpj\Database\Factories\DenahFactory;
|
||||
|
||||
class Denah extends Model
|
||||
class Denah extends Base
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
// use Modules\Lpj\Database\Factories\FasilitasObjekFactory;
|
||||
|
||||
class FasilitasObjek extends Model
|
||||
class FasilitasObjek extends Base
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Modules\Lpj\Database\Factories\FotoJaminanFactory;
|
||||
|
||||
class FotoJaminan extends Model
|
||||
class FotoJaminan extends Base
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
// use Modules\Lpj\Database\Factories\FotoObjekJaminanFactory;
|
||||
|
||||
class FotoObjekJaminan extends Model
|
||||
class FotoObjekJaminan extends Base
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Modules\Lpj\Database\Factories\GolonganMasySekitarFactory;
|
||||
|
||||
class GolonganMasySekitar extends Model
|
||||
class GolonganMasySekitar extends Base
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
// use Modules\Lpj\Database\Factories\InspeksiFactory;
|
||||
|
||||
class Inspeksi extends Model
|
||||
class Inspeksi extends Base
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
@@ -14,7 +14,7 @@ class Inspeksi extends Model
|
||||
/**
|
||||
* 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()
|
||||
{
|
||||
|
||||
@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Modules\Lpj\Database\Factories\JenisBangunanFactory;
|
||||
|
||||
class JenisBangunan extends Model
|
||||
class JenisBangunan extends Base
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
// use Modules\Lpj\Database\Factories\JenisKapalFactory;
|
||||
|
||||
class JenisKapal extends Model
|
||||
class JenisKapal extends Base
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
// use Modules\Lpj\Database\Factories\JenisKendaraanFactory;
|
||||
|
||||
class JenisKendaraan extends Model
|
||||
class JenisKendaraan extends Base
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Modules\Lpj\Models;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Modules\Lpj\Database\Factories\JenisPenilaianFactory;
|
||||
use Modules\Lpj\Models\Penilaian;
|
||||
class JenisPenilaian extends Model
|
||||
class JenisPenilaian extends Base
|
||||
{
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
// use Modules\Lpj\Database\Factories\JenisPesawatFactory;
|
||||
|
||||
class JenisPesawat extends Model
|
||||
class JenisPesawat extends Base
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
|
||||
// use Modules\Lpj\Database\Factories\JenisUnitFactory;
|
||||
|
||||
class JenisUnit extends Model
|
||||
class JenisUnit extends Base
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Modules\Lpj\Database\Factories\KetinggianTanahFactory;
|
||||
|
||||
class KetinggianTanah extends Model
|
||||
class KetinggianTanah extends Base
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Modules\Lpj\Database\Factories\KondisiBangunanFactory;
|
||||
|
||||
class KondisiBangunan extends Model
|
||||
class KondisiBangunan extends Base
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Modules\Lpj\Database\Factories\KondisiFisikTanahFactory;
|
||||
|
||||
class KondisiFisikTanah extends Model
|
||||
class KondisiFisikTanah extends Base
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Modules\Lpj\Database\Factories\KonturTanahFactory;
|
||||
|
||||
class KonturTanah extends Model
|
||||
class KonturTanah extends Base
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Modules\Lpj\Database\Factories\LaluLintasLokasiFactory;
|
||||
|
||||
class LaluLintasLokasi extends Model
|
||||
class LaluLintasLokasi extends Base
|
||||
{
|
||||
use HasFactory;
|
||||
protected $table = 'lalu_lintas_lokasi';
|
||||
|
||||
@@ -27,7 +27,7 @@ class LampiranDokumen extends Base
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
||||
if ($user && $user->hasAnyRole(['penilai', 'administrator', 'Penilai', 'admin','surveyor'])) {
|
||||
if ($user && $user->hasAnyRole(['penilai', 'administrator', 'Penilai', 'admin','surveyor','pemohon-ao','pemohon-eo'])) {
|
||||
$file = $fileData['file'];
|
||||
$fileName = $fileData['nama_file'] ?? time() . '_' . $file->getClientOriginalName();
|
||||
$filePath = $file->storeAs('lampiran_dokumen', $fileName, 'public');
|
||||
|
||||
@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Modules\Lpj\Database\Factories\LokasiUnitFactory;
|
||||
|
||||
class Lantai extends Model
|
||||
class Lantai extends Base
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Modules\Lpj\Database\Factories\LantaiUnitFactory;
|
||||
|
||||
class LantaiUnit extends Model
|
||||
class LantaiUnit extends Base
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
// use Modules\Lpj\Database\Factories\LaporanFactory;
|
||||
|
||||
class Laporan extends Model
|
||||
class Laporan extends Base
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
|
||||
@@ -18,7 +18,9 @@ class LaporanAdminKredit extends Base
|
||||
'tanggal_kunjungan',
|
||||
'nilai_pasar_wajar',
|
||||
'nilai_likuidasi',
|
||||
'nama_penilai'
|
||||
'nama_penilai',
|
||||
'keterangan',
|
||||
'kolektibilitas'
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
|
||||
114
app/Models/LaporanSlik.php
Normal file
114
app/Models/LaporanSlik.php
Normal file
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Modules\Usermanagement\Models\User;
|
||||
|
||||
class LaporanSlik extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $table = 'laporan_slik';
|
||||
|
||||
protected $fillable = [
|
||||
'slik_id',
|
||||
'sandi_bank',
|
||||
'kode_kantor',
|
||||
'kode_cabang',
|
||||
'tahun',
|
||||
'bulan',
|
||||
'no_rekening',
|
||||
'cif',
|
||||
'kode_jenis',
|
||||
'kode_jenis_ket',
|
||||
'kode_sifat',
|
||||
'kode_sifat_ket',
|
||||
'kode_valuta',
|
||||
'kode_valuta_ket',
|
||||
'baki_debet',
|
||||
'kolektibilitas',
|
||||
'kolektibilitas_ket',
|
||||
'tanggal_mulai',
|
||||
'tanggal_jatuh_tempo',
|
||||
'tanggal_selesai',
|
||||
'tanggal_restrukturisasi',
|
||||
'kode_sebab_macet',
|
||||
'kode_sebab_macet_ket',
|
||||
'tanggal_macet',
|
||||
'kode_kondisi',
|
||||
'kode_kondisi_ket',
|
||||
'tanggal_kondisi',
|
||||
'nilai_agunan',
|
||||
'nilai_agunan_ket',
|
||||
'jenis_agunan',
|
||||
'kode_agunan',
|
||||
'kode_agunan_ket',
|
||||
'peringkat_agunan',
|
||||
'peringkat_agunan_ket',
|
||||
'nama_debitur',
|
||||
'npwp',
|
||||
'no_ktp',
|
||||
'no_telp',
|
||||
'kode_kab_kota',
|
||||
'kode_kab_kota_ket',
|
||||
'kode_negara_domisili',
|
||||
'kode_negara_domisili_ket',
|
||||
'kode_pos',
|
||||
'alamat',
|
||||
'fasilitas',
|
||||
'status_agunan',
|
||||
'tanggal_lapor',
|
||||
'status',
|
||||
'created_by',
|
||||
'updated_by',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
];
|
||||
|
||||
public function slik()
|
||||
{
|
||||
return $this->belongsTo(Slik::class, 'slik_id');
|
||||
}
|
||||
|
||||
public function creator()
|
||||
{
|
||||
return $this->belongsTo(User::class, 'created_by');
|
||||
}
|
||||
|
||||
public function updater()
|
||||
{
|
||||
return $this->belongsTo(User::class, 'updated_by');
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope untuk filter berdasarkan status
|
||||
*/
|
||||
public function scopeActive($query)
|
||||
{
|
||||
return $query->where('status', 'aktif');
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor untuk nilai agunan yang diformat
|
||||
*/
|
||||
public function getNilaiAgunanFormattedAttribute()
|
||||
{
|
||||
return number_format($this->nilai_agunan ?? 0, 0, ',', '.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor untuk status badge
|
||||
*/
|
||||
public function getStatusBadgeAttribute()
|
||||
{
|
||||
$status = $this->status ?? 'aktif';
|
||||
$class = $status == 'aktif' ? 'success' : 'danger';
|
||||
|
||||
return '<span class="badge badge-light-' . $class . '">' . ucfirst($status) . '</span>';
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Modules\Lpj\Database\Factories\LingkunganFactory;
|
||||
|
||||
class Lingkungan extends Model
|
||||
class Lingkungan extends Base
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
|
||||
// use Modules\Lpj\Database\Factories\MerupakanDaerahFactory;
|
||||
|
||||
class MerupakanDaerah extends Model
|
||||
class MerupakanDaerah extends Base
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
// use Modules\Lpj\Database\Factories\ModelAlatBeratFactory;
|
||||
|
||||
class ModelAlatBerat extends Model
|
||||
class ModelAlatBerat extends Base
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
|
||||
@@ -6,5 +6,5 @@
|
||||
class NilaiPlafond extends Base
|
||||
{
|
||||
protected $table = 'nilai_plafond';
|
||||
protected $fillable = ['code', 'name'];
|
||||
protected $fillable = ['code', 'name', 'biaya'];
|
||||
}
|
||||
|
||||
57
app/Models/Noc.php
Normal file
57
app/Models/Noc.php
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Models;
|
||||
|
||||
use Illuminate\Foundation\Auth\User;
|
||||
|
||||
class Noc extends Base
|
||||
{
|
||||
protected $table = 'noc';
|
||||
|
||||
protected $guarded = ['id'];
|
||||
|
||||
protected $casts = [
|
||||
'nominal_bayar' => 'decimal:2',
|
||||
'status_bayar' => 'boolean',
|
||||
'status_kurang_bayar' => 'boolean',
|
||||
'nominal_kurang_bayar' => 'decimal:2',
|
||||
'status_lebih_bayar' => 'boolean',
|
||||
'nominal_lebih_bayar' => 'decimal:2',
|
||||
'tanggal_pembayaran' => 'date',
|
||||
'nominal_penyelesaian' => 'decimal:2',
|
||||
'status_penyelesaiaan' => 'boolean',
|
||||
'tanggal_penyelesaian' => 'date',
|
||||
'memo_penyelesaian_date' => 'date',
|
||||
'memo_penyelesaian_payment_date' => 'date',
|
||||
'memo_penyelesaian_created_at' => 'datetime',
|
||||
'status' => 'boolean',
|
||||
'authorized_status' => 'boolean',
|
||||
'authorized_at' => 'datetime',
|
||||
];
|
||||
|
||||
// Relationship with Permohonan
|
||||
public function permohonan()
|
||||
{
|
||||
return $this->belongsTo(Permohonan::class, 'permohonan_id');
|
||||
}
|
||||
|
||||
// Relationship with PersetujuanPenawaran
|
||||
public function persetujuanPenawaran()
|
||||
{
|
||||
return $this->belongsTo(PersetujuanPenawaran::class, 'persetujuan_penawaran_id');
|
||||
}
|
||||
|
||||
// Relationship with User (for authorized_by)
|
||||
public function authorizedBy()
|
||||
{
|
||||
return $this->belongsTo(User::class, 'authorized_by');
|
||||
}
|
||||
|
||||
public function debiture(){
|
||||
return $this->belongsTo(Debiture::class,'debiture_id');
|
||||
}
|
||||
|
||||
public function branch(){
|
||||
return $this->belongsTo(Branch::class,'branch_id');
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Modules\Lpj\Database\Factories\ObjekJaminanFactory;
|
||||
|
||||
class ObjekJaminan extends Model
|
||||
class ObjekJaminan extends Base
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
// use Modules\Lpj\Database\Factories\PenawaranDetailTenderFactory;
|
||||
|
||||
class PenawaranDetailTenderLog extends Model
|
||||
class PenawaranDetailTenderLog extends Base
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
@@ -22,7 +22,7 @@ class PenawaranDetailTenderLog extends Model
|
||||
{
|
||||
return $this->belongsTo(PenawaranTender::class, 'penawaran_id', 'id');
|
||||
}
|
||||
|
||||
|
||||
public function penawarandetail(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(PenawaranDetailTender::class, 'detail_penawaran_id', 'id');
|
||||
|
||||
@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
// use Modules\Lpj\Database\Factories\PenilaiFactory;
|
||||
|
||||
class Penilai extends Model
|
||||
class Penilai extends Base
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user