1 Commits

Author SHA1 Message Date
Daeng Deni Mardaeni
c1751169ac Add SQL seeders and queries for mig_debitures
- Created `mig_debitures_comms.sql` to insert communication records for debtors.
- Added `query_mig_debiturs.sql` to retrieve debtor information with address and communication details.
- Introduced `query_mig_debiturs_addrs.sql` to fetch unique addresses for debtors.
- Implemented `query_mig_debiturs_comms.sql` to select unique communication records for debtors.
2025-04-16 21:53:39 +07:00
381 changed files with 30287 additions and 35735 deletions

View File

@@ -1,228 +0,0 @@
<?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.');
}
}
}

View File

@@ -1,192 +0,0 @@
<?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()
);
}
}

View File

@@ -1,99 +0,0 @@
<?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;
}
}
}

View File

@@ -1,123 +0,0 @@
# 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`

View File

@@ -32,8 +32,6 @@ class LaporanAdminKreditExport implements WithColumnFormatting, WithHeadings, Fr
$row->nilai_pasar_wajar,
$row->nilai_likuidasi,
$row->nama_penilai,
$row->kolektibilitas,
$row->keterangan,
$row->created_at
];
}
@@ -54,8 +52,6 @@ class LaporanAdminKreditExport implements WithColumnFormatting, WithHeadings, Fr
'Nilai Pasar Wajar',
'Nilai Likuidasi',
'Nama Penilai',
'Kolektibilitas',
'Keterangan',
'Created At'
];
}
@@ -68,9 +64,7 @@ class LaporanAdminKreditExport implements WithColumnFormatting, WithHeadings, Fr
'J' => NumberFormat::FORMAT_DATE_DDMMYYYY,
'K' => NumberFormat::FORMAT_NUMBER_COMMA_SEPARATED1,
'L' => NumberFormat::FORMAT_NUMBER_COMMA_SEPARATED1,
'N' => NumberFormat::FORMAT_TEXT, // Kolektibilitas
'O' => NumberFormat::FORMAT_TEXT, // Keterangan
'P' => NumberFormat::FORMAT_DATE_DATETIME, // Created At (moved from M to P)
'M' => NumberFormat::FORMAT_DATE_DATETIME,
];
}
}

View File

@@ -1,288 +0,0 @@
<?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);
},
];
}
}

View File

@@ -1,245 +0,0 @@
<?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);
},
];
}
}

View File

@@ -19,7 +19,8 @@
public function collection()
{
$query = Permohonan::query();
$query = Permohonan::with(['user', 'branch', 'tujuanPenilaian', 'jenisFasilitasKredit', 'jenisPenilaian'])
->select('permohonan.*');
// Apply role-based filtering
if (!Auth::user()->hasAnyRole(['administrator'])) {

View File

@@ -1,117 +0,0 @@
<?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]],
];
}
}

View File

@@ -1,232 +0,0 @@
<?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);
},
];
}
}

View File

@@ -24,7 +24,6 @@
$row->id,
$row->code,
$row->name,
$row->biaya,
$row->created_at
];
}
@@ -36,7 +35,6 @@
'ID',
'Code',
'Name',
'Biaya',
'Created At'
];
}
@@ -46,8 +44,7 @@
{
return [
'A' => NumberFormat::FORMAT_NUMBER,
'D' => NumberFormat::FORMAT_NUMBER_00,
'E' => NumberFormat::FORMAT_DATE_DATETIME
'D' => NumberFormat::FORMAT_DATE_DATETIME
];
}
}

View File

@@ -1,185 +0,0 @@
<?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
];
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -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','penilai']))
->whereHas('user.roles', fn ($q) => $q->whereIn('name', ['surveyor', 'surveyor-penilai']))
->get();
$teamId = is_array($teamId) ? $teamId : [$teamId];
@@ -306,7 +306,6 @@ 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) {
@@ -325,9 +324,7 @@ class ActivityController extends Controller
});
}
// Apply sorting if provided
// Default sorting if no sort provided
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField');

View File

@@ -1,183 +0,0 @@
<?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);
}
}
}

View File

@@ -1,209 +0,0 @@
<?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());
}
}
}

View File

@@ -1,152 +0,0 @@
<?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,
]);
}
}

View File

@@ -1,129 +0,0 @@
<?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']);
}
}
}

View File

@@ -1,36 +0,0 @@
<?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'));
}
}

View File

@@ -129,7 +129,7 @@
// Retrieve data from the database
$query = Debiture::query();
if (!Auth::user()->hasAnyRole(['administrator','admin'])) {
if (!Auth::user()->hasAnyRole(['administrator'])) {
$query = $query->where('branch_id', Auth::user()->branch_id);
}

View File

@@ -406,9 +406,7 @@
// Remove values from $legalitasJaminan that are in $currentLegalitasJaminan
$legalitasJaminan = is_array($legalitasJaminan)
? array_diff($legalitasJaminan, $currentLegalitasJaminan->pluck('code')->toArray())
: [];
$legalitasJaminan = array_diff($legalitasJaminan, $currentLegalitasJaminan->pluck('code')->toArray());
$legalitas = JenisLegalitasJaminan::whereIn('code', $legalitasJaminan)->get();
}
@@ -443,7 +441,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);
@@ -453,8 +451,8 @@
}
// Periksa apakah dokumen jaminan terkait dengan permohonan aktif
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);
if ($jaminan->permohonan()->exists()) {
return response()->json(['success' => false, 'message' => 'Tidak dapat menghapus dokumen jaminan yang terkait dengan permohonan aktif'], 400);
}
DB::beginTransaction();

View File

@@ -1,239 +0,0 @@
<?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);
}
}
}

View File

@@ -3,7 +3,6 @@
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;
@@ -20,7 +19,12 @@
*/
public function index()
{
$permohonan = Permohonan::where(['status' => 'done'])->get();
$permohonan = Permohonan::with([
'documents.jenisJaminan',
'penilaian._user_penilai',
'penilai',
'documents.detail.jenisLegalitasJaminan'
])->where(['status' => 'done'])->get();
foreach ($permohonan as $_permohonan) {
$npw = 0;
if (isset($_permohonan->penilai->lpj)) {
@@ -150,8 +154,6 @@
$request->validate([
'kode_register_t24' => 'nullable',
'cif' => 'required',
'keterangan' => 'nullable|string',
'kolektibilitas' => 'nullable|string|in:1,2,3,4,5',
]);
try {
@@ -160,8 +162,6 @@
// 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('admin-kredit.laporan.index')
->route('laporan-admin-kredit.index')
->with('success', 'Laporan Admin Kredit updated successfully');
} catch (Exception $e) {
return redirect()
->route('admin-kredit.laporan.edit', $id)
->route('laporan-admin-kredit.edit', $id)
->with('error', 'Failed to update Laporan Admin Kredit');
}
}

View File

@@ -1,23 +0,0 @@
<?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');
}
}

View File

@@ -2,10 +2,9 @@
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
@@ -16,6 +15,7 @@ class LaporanController extends Controller
* Display a listing of the resource.
*/
public function __construct(PenilaiController $penilaiController){
$this->penilaiController = $penilaiController;
}
@@ -75,12 +75,11 @@ class LaporanController extends Controller
}
// Retrieve data from the database
$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 = 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 = $query->orderBy('nomor_registrasi', 'desc');
// Apply search filter if provided
@@ -124,7 +123,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','noc'])->get();
$data = $query->with(['user', 'debiture', 'branch', 'tujuanPenilaian', 'penilaian','jenisFasilitasKredit', 'documents.inspeksi','penilai','documents.detail'])->get();
// Calculate the page count
$pageCount = ceil($totalRecords / $size);

View File

@@ -1,33 +0,0 @@
<?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);
}
}

View File

@@ -1,213 +0,0 @@
<?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');
}
}

View File

@@ -1,43 +0,0 @@
<?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);
}
}

View File

@@ -9,10 +9,6 @@ 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
{
@@ -20,31 +16,59 @@ 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($permohonan_id, $dokumen_id, $jaminan_id)
public function show($id)
{
$back = route('laporan-penilai-jaminan.index');
return $this->previewLaporanService->previewLaporan($permohonan_id, $dokumen_id, $jaminan_id, $back);
return view('lpj::laporan-penilai-jaminan.show');
}
/**
* 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)
{
@@ -69,104 +93,91 @@ 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 = json_decode($request->get('search'));
$search = $request->get('search');
$paramsSearch = json_decode($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 ($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 . '%');
$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 . '%');
});
if (!empty($paramsSearch->tanggal_awal) && !empty($paramsSearch->tanggal_akhir)) {
$q->whereBetween('tanggal_permohonan', [$paramsSearch->tanggal_awal, $paramsSearch->tanggal_akhir]);
}
}
// 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 . '%');
});
}
$statusKeywords = explode(',', $search);
foreach ($statusKeywords as $keyword) {
$q->orWhereRelation('penilai', 'type_penilai', 'LIKE', '%' . trim($keyword) . '%');
}
});
}
$query->where('status', 'done');
// Apply sorting if provided
// Default sorting if no sort 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 the total count of records
// Get total count of records before pagination
$totalRecords = $query->count();
// Apply pagination if provided
// Pagination
if ($request->has('page') && $request->has('size')) {
$page = $request->get('page');
$size = $request->get('size');
$offset = ($page - 1) * $size; // Calculate the offset
$page = (int) $request->get('page', 1);
$size = (int) $request->get('size', 10);
$offset = ($page - 1) * $size;
$query->skip($offset)->take($size);
}
// Get the filtered count of records
// Get filtered count
$filteredRecords = $query->count();
$totalRecords = $query->count();
// Pagination
if ($request->has('page') && $request->has('size')) {
$page = (int) $request->get('page', 1);
$size = (int) $request->get('size', 10);
$offset = ($page - 1) * $size;
$query->skip($offset)->take($size);
}
// Get filtered count
$filteredRecords = $query->count();
// Get data with necessary relationships
$data = $query->with(['user', 'debiture', 'branch', 'tujuanPenilaian', 'penilaian', 'dokumenjaminan.jenisJaminan','nilaiPlafond', 'penilai', 'dokumenjaminan.inspeksi'])->get();
$data = $query->with(['user', 'debiture', 'branch', 'tujuanPenilaian', 'penilaian', 'dokumenjaminan.jenisJaminan','nilaiPlafond', 'penilai'])->get();
// Calculate the page count
$pageCount = ceil($totalRecords / $size);
// Calculate total pages
$pageCount = ceil($totalRecords / $request->get('size', 10));
// Calculate the current page number
$currentPage = max(1, $request->get('page', 1));
// Return the response data as a JSON object
// Calculate total pages
$pageCount = ceil($totalRecords / $request->get('size', 10));
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $currentPage,
'page' => $request->get('page', 1),
'totalCount' => $totalRecords,
'data' => $data,
]);
@@ -174,53 +185,15 @@ class LaporanPenilaiJaminanController extends Controller
public function export(Request $request)
{
$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);
$tanggalAwal = $request->input('tanggal_awal');
$tanggalAkhir = $request->input('tanggal_akhir');
$status = $request->input('status');
$selectedIds = $request->input('selected_ids');
$filename = 'laporan_penilai_jaminan_' . date('YmdHis') . '.xlsx';
return Excel::download(
new LaporanPenilaiJaminanExport($request),
new LaporanPenilaiJaminanExport($tanggalAwal, $tanggalAkhir, $status, $selectedIds),
$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;
}
}

View File

@@ -1,180 +0,0 @@
<?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);
}
}

View File

@@ -32,7 +32,6 @@
// 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);

View File

@@ -1,32 +0,0 @@
<?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);
}
}

View File

@@ -1,304 +0,0 @@
<?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());
}
}
}

View File

@@ -1,51 +0,0 @@
<?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);
}
}

View File

@@ -1,558 +0,0 @@
<?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.');
}
}
}

View File

@@ -5,8 +5,6 @@
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;
@@ -16,239 +14,137 @@
{
public $user;
/**
* Menampilkan halaman daftar Nilai Plafond.
* Log setiap akses dan sebelum return view.
*/
public function index()
{
Log::info('NilaiPlafondController@index: akses halaman index');
return \view('lpj::nilai_plafond.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 {
$record = NilaiPlafond::create($validate);
DB::commit();
Log::info('NilaiPlafondController@store: simpan berhasil', ['id' => $record->id]);
return \redirect()
// Save to database
NilaiPlafond::create($validate);
return redirect()
->route('basicdata.nilai-plafond.index')
->with('success', 'Nilai Plafond berhasil dibuat');
->with('success', 'Jenis Aset created successfully');
} catch (Exception $e) {
DB::rollBack();
Log::error('NilaiPlafondController@store: simpan gagal', ['error' => $e->getMessage()]);
return \redirect()
return redirect()
->route('basicdata.nilai-plafond.create')
->with('error', 'Gagal membuat Nilai Plafond');
->with('error', 'Failed to create nilai plafond');
}
}
}
/**
* Menampilkan form pembuatan Nilai Plafond.
* Log akses sebelum return view.
*/
public function create()
{
Log::info('NilaiPlafondController@create: akses halaman create');
return \view('lpj::nilai_plafond.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)
{
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');
}
$nilaiPlafond = NilaiPlafond::find($id);
return view('lpj::nilai_plafond.create', compact('nilaiPlafond'));
}
/**
* 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);
DB::commit();
Log::info('NilaiPlafondController@update: update berhasil', ['id' => $id]);
return \redirect()
return redirect()
->route('basicdata.nilai-plafond.index')
->with('success', 'Nilai Plafond berhasil diperbarui');
->with('success', 'Jenis Aset updated successfully');
} catch (Exception $e) {
DB::rollBack();
Log::error('NilaiPlafondController@update: update gagal', ['id' => $id, 'error' => $e->getMessage()]);
return \redirect()
return redirect()
->route('basicdata.nilai-plafond.edit', $id)
->with('error', 'Gagal memperbarui Nilai Plafond');
->with('error', 'Failed to update 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);
if (!$nilaiPlafond) {
DB::rollBack();
Log::warning('NilaiPlafondController@destroy: data tidak ditemukan', ['id' => $id]);
return \response()->json(['success' => false, 'message' => 'Data Nilai Plafond tidak ditemukan']);
}
$nilaiPlafond->delete();
DB::commit();
Log::info('NilaiPlafondController@destroy: hapus berhasil', ['id' => $id]);
return \response()->json(['success' => true, 'message' => 'Nilai Plafond berhasil dihapus']);
echo json_encode(['success' => true, 'message' => 'Jenis Aset deleted successfully']);
} catch (Exception $e) {
DB::rollBack();
Log::error('NilaiPlafondController@destroy: hapus gagal', ['id' => $id, 'error' => $e->getMessage()]);
return \response()->json(['success' => false, 'message' => 'Gagal menghapus Nilai Plafond']);
echo json_encode(['success' => false, 'message' => 'Failed to delete 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.');
}
DB::beginTransaction();
try {
// Retrieve data from the database
$query = NilaiPlafond::query();
// 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 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 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,
]);
}
/**
* 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');
}
}

View File

@@ -6,10 +6,9 @@
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Modules\Lpj\Http\Requests\NocRequest;
use Modules\Lpj\Models\Bucok;
use Modules\Lpj\Models\Noc;
use Modules\Lpj\Models\PenawaranTender;
use Modules\Lpj\Models\Permohonan;
use Modules\Lpj\Models\PersetujuanPenawaran;
use Modules\Lpj\Models\JenisPenilaian;
class NocController extends Controller
{
@@ -19,22 +18,9 @@ use Modules\Lpj\Models\Noc;
* Display a listing of the resource.
*/
public function index()
{
return redirect()->route('noc.pembayaran.index');
}
public function pembayaran()
{
$persetujuanPenawarans = PersetujuanPenawaran::all();
$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'));
return view('lpj::noc.index', compact('persetujuanPenawarans'));
}
/**
@@ -49,63 +35,53 @@ use Modules\Lpj\Models\Noc;
public function store(NocRequest $request)
{
$validated = $request->validated();
$validated['updated_by'] = Auth::id();
if (request()->get('status_bayar') == "sudah_bayar") {
$validated['status'] = '1';
}
$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'] ?? '',
];
if($validated['permohonan_id']){
$noc = Noc::updateOrCreate(
[
'permohonan_id' => $validated['permohonan_id'],
'persetujuan_penawaran_id' => $validated['persetujuan_penawaran_id'],
],
$dataNoc,
);
$status = "spk";
} else {
$noc = Noc::updateOrCreate(
[
'persetujuan_penawaran_id' => $validated['persetujuan_penawaran_id'],
],
$dataNoc,
);
$status = "persetujuan-penawaran";
}
$folderPath = 'noc/' . request()->get('persetujuan_penawaran_id') . '/bukti_ksl/';
$persetujuanPenawaran = PersetujuanPenawaran::updateOrCreate(
['penawaran_id' => $validated['penawaran_id']],
$validated,
);
$folderPath = 'noc/' . $validated['penawaran_id'];
if ($request->hasFile('bukti_ksl')) {
$noc->bukti_ksl = $request->file('bukti_ksl')->store(
$persetujuanPenawaran->bukti_ksl = $request->file('bukti_ksl')->store(
$folderPath,
'public',
);
}
$noc->save();
$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();
$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'
}
return redirect()
->route('noc.index')->with('success', 'NOC berhasil disimpan.');
->route('noc.index')->with('success', 'Penyelesaian KSL berhasil disimpan.');
}
/**
@@ -113,60 +89,13 @@ use Modules\Lpj\Models\Noc;
*/
public function update(NocRequest $request, PersetujuanPenawaran $persetujuanPenawaran)
{
$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();
$validated = $request->validated();
$validated['updated_by'] = Auth::id();
$persetujuanPenawaran->update($validated);
return redirect()
->route('noc.index')->with('success', 'NOC updated successfully');
->route('noc.index')->with('success', 'Persetujuan Penawaran updated successfully');
}
/**
@@ -180,16 +109,16 @@ use Modules\Lpj\Models\Noc;
/**
* Display the specified resource.
*/
public function show(Noc $noc) {
return view('lpj::noc.memo', compact('noc'));
}
public function show($id) {}
/**
* Show the form for editing the specified resource.
*/
public function edit($id)
{
$persetujuanPenawaran = PersetujuanPenawaran::where('id', $id)->first();
$persetujuanPenawaran = PersetujuanPenawaran::where('id', $id)->with(
['penawaran.detail', 'penawaran.permohonan.debiture','permohonan'],
)->first();
return view('lpj::noc.form', compact('persetujuanPenawaran'));
}
@@ -205,12 +134,6 @@ use Modules\Lpj\Models\Noc;
}
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.');
@@ -219,20 +142,11 @@ use Modules\Lpj\Models\Noc;
// 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 . '%')
->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 . '%');
});
}
@@ -259,38 +173,18 @@ use Modules\Lpj\Models\Noc;
$filteredRecords = $query->count();
// Get the data for the current page
$data = $query->get();
$data = $query
->with(
[
'penawaran.permohonan.debiture',
'penawaran.permohonan.branch',
'permohonan.debiture',
'permohonan.branch',
'penawaran.detail',
'penawaran.persetujuan',
],
)->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'));
@@ -306,121 +200,6 @@ use Modules\Lpj\Models\Noc;
'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,
]);
}

View File

@@ -3,12 +3,26 @@
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
{
@@ -78,10 +92,6 @@
// 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'))) {

View File

@@ -2,17 +2,21 @@
namespace Modules\Lpj\Http\Controllers;
use Exception;
use Modules\Lpj\Models\Noc;
use Illuminate\Http\Request;
use Modules\Lpj\Models\Bucok;
use Illuminate\Http\JsonResponse;
use Modules\Lpj\Models\Permohonan;
use App\Http\Controllers\Controller;
use Exception;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Modules\Lpj\Models\PenawaranTender;
use Modules\Lpj\Models\PersetujuanPenawaran;
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\Permohonan;
use Modules\Lpj\Models\PersetujuanPenawaran;
// use Modules\Lpj\Models\JenisPenilaian;
// use Modules\Lpj\Models\Regions;
class PembayaranController extends Controller
{
@@ -23,14 +27,6 @@ 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');
@@ -39,16 +35,13 @@ 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) {
@@ -56,29 +49,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(
[
@@ -96,13 +89,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,
@@ -114,130 +107,34 @@ class PembayaranController extends Controller
]);
}
public function create(){
return view('lpj::pembayaran.create');
}
public function edit($id)
{
$permohonan = Permohonan::find($id);
$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();
}
$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');
}
@@ -245,22 +142,13 @@ class PembayaranController extends Controller
$permohonan->approve_bayar_by = null;
$permohonan->approve_bayar_at = null;
$permohonan->status = 'proses-laporan';
$permohonan->status = 'done';
$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')) {
@@ -269,47 +157,20 @@ class PembayaranController extends Controller
$persetujuanPenawaran->save();
}
$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'
// 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'
}
@@ -319,7 +180,7 @@ class PembayaranController extends Controller
public function update(Request $request, $id): JsonResponse
{
// init
// init
$data = [];
$output = [];
$tindakan = null;
@@ -335,22 +196,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) {
@@ -390,43 +251,48 @@ 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 = 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);
$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');
});
// 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;
@@ -439,172 +305,20 @@ class PembayaranController extends Controller
$query->skip($offset)->take($size);
}
// Filtered records
// Filtered records
$filteredRecords = $query->count();
// 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 ?? ''
];
});
// Ambil data dengan relasi
$data = $query->with(['user', 'debiture', 'branch', 'jenisPenilaian'])->get();
// 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 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 JSON response
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,

View File

@@ -26,21 +26,18 @@ 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, PreviewLaporanService $previewLaporanService)
public function __construct(SurveyorController $surveyorController, SaveFormInspesksiService $inspeksiService)
{
$this->surveyorController = $surveyorController;
$this->inspeksiService = $inspeksiService;
$this->previewLaporanService = $previewLaporanService;
}
/**
@@ -155,11 +152,6 @@ 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');
@@ -226,11 +218,6 @@ 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');
@@ -266,9 +253,6 @@ 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();
@@ -408,11 +392,6 @@ 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();
@@ -491,9 +470,6 @@ 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();
@@ -551,7 +527,13 @@ 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)
{
@@ -619,8 +601,7 @@ class PenilaiController extends Controller
'jenisfasilitasKredit',
'penilaian.userPenilai',
'penilai',
'nilaiPlafond',
'penawaran'
'nilaiPlafond'
])->get();
// Calculate the page count
@@ -698,17 +679,15 @@ class PenilaiController extends Controller
'lokasi_lengkap' => $data->lokasi_lengkap ?? '',
];
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;
}
// 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;
}
}
}
@@ -841,10 +820,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') {
@@ -1006,10 +985,11 @@ class PenilaiController extends Controller
],
];
Inspeksi::updateOrCreate([
Inspeksi::create([
'permohonan_id' => $validatedData['permohonan_id'],
'dokument_id' => $validatedData['dokument_id']
],[
'dokument_id' => $validatedData['dokument_id'],
'data_form' => json_encode($newData),
'name' => $validatedData['type']
]);
@@ -1076,14 +1056,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);
@@ -1095,7 +1075,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');
@@ -1124,7 +1104,8 @@ class PenilaiController extends Controller
$penilai = Penilai::updateOrCreate(
[
'permohonan_id' => $request->permohonanId,
'dokument_id' => $request->input('dokument_id'),
'dokument_id' => $request->documentId,
],
[
'lpj' => json_encode($data),
@@ -1151,9 +1132,20 @@ 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()
);
$validatedData = $request->all();
$result = $this->inspeksiService->storeInspeksi($validatedData, $request->input('type'), $request);
$validated = $formRequest->validateResolved();
$result = $this->surveyorController->store($formRequest);
$data = [
'kepada' => $request->input('kepada'),
@@ -1251,10 +1243,9 @@ class PenilaiController extends Controller
Inspeksi::updateOrCreate([
Inspeksi::create([
'permohonan_id' => $validated['permohonan_id'],
'dokument_id' => $validated['dokument_id']
],[
'dokument_id' => $validated['dokument_id'],
'data_form' => json_encode($newData),
'name' => $validated['type']
]);
@@ -1275,6 +1266,8 @@ class PenilaiController extends Controller
}
}
public function print_out(Request $request)
{
$documentId = $request->query('documentId');
@@ -1390,15 +1383,6 @@ 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 = [
@@ -1426,7 +1410,7 @@ class PenilaiController extends Controller
}
// pengunaan request query by id permohonan, documentId, jaminan , inspeksi
// pengunaan request query by id permohonan, dokument, jaminan , inspeksi
protected function getRequestQueryId(Request $request)
{
return [
@@ -1778,24 +1762,4 @@ 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)
{
}
}

View File

@@ -517,18 +517,12 @@ 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 = $npw <=1000000000 ? 'done' : 'proses-laporan';
$status = in_array($permohonan->nilai_plafond_id, [3]) ? 'done' : 'proses-laporan';
} elseif ($role === 'EO Appraisal') {
$approvalField = 'approval_eo';
$status = $npw <=5000000000 ? 'done' : 'proses-laporan';
$status = in_array($permohonan->nilai_plafond_id, [2, 1]) ? 'done' : 'proses-laporan';
} elseif ($role === 'DD Appraisal') {
$approvalField = 'approval_dd';
$status = 'done';
@@ -609,15 +603,8 @@ class PenilaianController extends Controller
break;
case 'paparan':
if (Auth::user()->roles[0]->name === 'senior-officer' || Auth::user()->roles[0]->name === 'administrator' && $authorization->approve_so === null) {
$status = '3';
if (in_array($permohonan->nilai_plafond_id, [3])) {
$status = '1';
$permohonan->update([
'status' => $authorization->request
]);
}
$authorization->update([
'status' => $status,
'status' => '3',
'status_so' => '1',
'approve_so' => Auth::user()->id,
'approve_so_at' => now(),
@@ -628,10 +615,9 @@ class PenilaianController extends Controller
'tanggal_paparan' => $request->tanggalPaparan,
'keterangan' => $request->keterangan
]);
} elseif (Auth::user()->roles[0]->name === 'EO Appraisal') {
$status = '2';
if (in_array($permohonan->nilai_plafond_id, [1,2, 3])) {
if (in_array($permohonan->nilai_plafond_id, [1,2])) {
$status = '1';
$permohonan->update([
'status' => $authorization->request

File diff suppressed because it is too large Load Diff

View File

@@ -6,7 +6,6 @@
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;
@@ -40,7 +39,6 @@
$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']],
@@ -69,22 +67,6 @@
$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.');
}
@@ -180,8 +162,8 @@
public function edit($id)
{
$permohonan = Permohonan::with(['debiture', 'penawaranTender.detail'])->find($id);
$persetujuanPenawaran = PersetujuanPenawaran::where('permohonan_id', $id)->first();
return view('lpj::persetujuan_penawaran.form', compact('permohonan', 'persetujuanPenawaran'));
return view('lpj::persetujuan_penawaran.form', compact('permohonan'));
}
/**
@@ -202,12 +184,8 @@
}
// Retrieve data from the database
//$query = Permohonan::query()->where(['status' => 'persetujuan-penawaran']);
$query = Permohonan::query()
->where(['status' => 'persetujuan-penawaran'])
->whereHas('penawaranTender', function ($q) {
$q->where('status', 'persetujuan-penawaran');
});
$query = Permohonan::query()->where(['status' => 'persetujuan-penawaran']);
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = $request->get('search');

View File

@@ -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','=','registrasi-final')
->where('penawaran.status','=','spk')
->withCount('penawarandetails');
// Apply search filter if provided

View File

@@ -1,22 +0,0 @@
<?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'));
}
}

View File

@@ -1,548 +0,0 @@
<?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);
}
}
}

View File

@@ -345,19 +345,6 @@ 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');

View File

@@ -3,21 +3,25 @@
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\Facades\Log;
use Illuminate\Support\Str;
use Barryvdh\DomPDF\Facade\Pdf;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Carbon;
use Exception;
use Illuminate\Support\Facades\Mail;
use Illuminate\Http\Response;
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;
@@ -37,8 +41,17 @@ 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;
@@ -49,24 +62,29 @@ 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
{
@@ -108,9 +126,6 @@ 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)
@@ -136,17 +151,13 @@ 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',
'catatan_revisi_survey',
'inspeksiData'
));
}
@@ -242,7 +253,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()
@@ -783,12 +794,12 @@ class SurveyorController extends Controller
]);
if (in_array(strtolower($permohonan->jenisPenilaian->name), ['external', 'eksternal'])) {
if ($permohonan->jenisPenilaian->name == "External") {
LaporanExternal::updateOrCreate(
['permohonan_id' => $permohonan->id],
[
'nomor_laporan' => $permohonan->nomor_registrasi,
'tgl_final_laporan' => now(),
'tanggal_laporan' => now(),
'created_by' => Auth::id(),
]
);
@@ -1068,7 +1079,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());
}
}
@@ -1385,11 +1396,6 @@ 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();
@@ -1550,11 +1556,11 @@ class SurveyorController extends Controller
{
$validated = $request->validate([
'documentId' => 'required',
'dokument' => 'required',
'jenis_jaminan' => 'required'
]);
$dokumentId = $validated['documentId'];
$dokumentId = $validated['dokument'];
$jaminanId = $validated['jenis_jaminan'];
$permohonan = $this->getPermohonanJaminanId($id, $dokumentId, $jaminanId);
@@ -1638,11 +1644,11 @@ class SurveyorController extends Controller
public function denah(Request $request, $id)
{
$validated = $request->validate([
'documentId' => 'required',
'dokument' => 'required',
'jenis_jaminan' => 'required'
]);
$dokumentId = $validated['documentId'];
$dokumentId = $validated['dokument'];
$jaminanId = $validated['jenis_jaminan'];
$permohonan = $this->getPermohonanJaminanId($id, $dokumentId, $jaminanId);
@@ -1666,11 +1672,11 @@ class SurveyorController extends Controller
public function foto(Request $request, $id)
{
$validated = $request->validate([
'documentId' => 'required',
'dokument' => 'required',
'jenis_jaminan' => 'required'
]);
$dokumentId = $validated['documentId'];
$dokumentId = $validated['dokument'];
$jaminanId = $validated['jenis_jaminan'];
$fotoObjekJaminan = FotoObjekJaminan::all();
@@ -1701,11 +1707,11 @@ class SurveyorController extends Controller
// Ambil data permohonan dengan eager loading
$validated = $request->validate([
'documentId' => 'required',
'dokument' => 'required',
'jenis_jaminan' => 'required'
]);
$dokumentId = $validated['documentId'];
$dokumentId = $validated['dokument'];
$jaminanId = $validated['jenis_jaminan'];
$permohonan = $this->getPermohonanJaminanId($id, $dokumentId, $jaminanId);
@@ -1841,10 +1847,10 @@ class SurveyorController extends Controller
return redirect()
->route('basicdata.' . $type . '.index')
->with('success', 'created successfully');
} catch (\Exception $e) {
} catch (Exeception $e) {
return redirect()
->route('basicdata.' . $type . '.index')
->with('error', $e->getMessage());
->with('error', $th->getMessage());
}
}
}
@@ -2110,7 +2116,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.');
}
@@ -2150,7 +2156,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'))) {
@@ -2223,9 +2229,9 @@ class SurveyorController extends Controller
$model = $modelClass::findOrFail($id);
$model->delete();
return response()->json(['success' => true, 'message' => 'deleted successfully']);
} catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
} catch (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);
}
}
@@ -2381,14 +2387,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];
@@ -2417,14 +2423,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);
@@ -2874,10 +2880,9 @@ class SurveyorController extends Controller
$inspeksi->data_form = json_encode($existingData);
$inspeksi->save();
} else {
Inspeksi::updateOrCreate([
Inspeksi::create([
'permohonan_id' => $request->input('permohonan_id'),
'dokument_id' => $request->input('document_id')
],[
'dokument_id' => $request->input('document_id'),
'data_form' => json_encode($existingData),
]);
}
@@ -2898,99 +2903,5 @@ 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()
]);
}
}
}

View File

@@ -1,33 +0,0 @@
<?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;
}
}

View File

@@ -1,38 +0,0 @@
<?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;
}
}

View File

@@ -14,7 +14,6 @@
{
$rules = [
'name' => 'required|max:255',
'biaya' => 'nullable|numeric|min:0',
];
if ($this->method() == 'PUT') {

View File

@@ -4,164 +4,20 @@
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 [
'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',
'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',
];
}
}

View File

@@ -48,6 +48,7 @@
),
'tanggal_permohonan' => date('Y-m-d'),
'user_id' => auth()->user()->id,
'branch_id' => auth()->user()->branch_id,
'status' => 'order'
]);
}

View File

@@ -14,54 +14,56 @@
public function rules()
{
return [
'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',
];
'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',
];
}
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.',
'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.',
];
'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".',
];
}
}

View File

@@ -1,341 +0,0 @@
<?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;
}
}

View File

@@ -1,415 +0,0 @@
<?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;
}
}
}

View File

@@ -1,156 +0,0 @@
<?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()
]);
}
}

View File

@@ -1,179 +0,0 @@
<?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);
}
}
}

View File

@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Modules\Lpj\Database\Factories\AnalisaFactory;
class Analisa extends Base
class Analisa extends Model
{
use HasFactory;
protected $table = 'analisa';

View File

@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Modules\Lpj\Database\Factories\AnalisaFaktaFactory;
class AnalisaFakta extends Base
class AnalisaFakta extends Model
{
use HasFactory;

View File

@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Modules\Lpj\Database\Factories\AnalisaLingkunganFactory;
class AnalisaLingkungan extends Base
class AnalisaLingkungan extends Model
{
use HasFactory;

View File

@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Modules\Lpj\Database\Factories\AnalisaTanahBagunanFactory;
class AnalisaTanahBagunan extends Base
class AnalisaTanahBagunan extends Model
{
use HasFactory;

View File

@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Modules\Lpj\Database\Factories\AnalisaUnitFactory;
class AnalisaUnit extends Base
class AnalisaUnit extends Model
{
use HasFactory;

View File

@@ -6,8 +6,7 @@
use Illuminate\Database\Eloquent\SoftDeletes;
use Spatie\Activitylog\LogOptions;
use Spatie\Activitylog\Traits\LogsActivity;
use Mattiverse\Userstamps\Traits\Userstamps;
use Illuminate\Notifications\Notifiable;
use Wildside\Userstamps\Userstamps;
/**
@@ -15,7 +14,7 @@
*/
class Base extends Model
{
use LogsActivity, SoftDeletes, Userstamps, Notifiable;
use LogsActivity, SoftDeletes, Userstamps;
protected $connection;

View File

@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Modules\Lpj\Database\Factories\BentukTanahFactory;
class BentukTanah extends Base
class BentukTanah extends Model
{
use HasFactory;

View File

@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
// use Modules\Lpj\Database\Factories\BentukUnitFactory;
class BentukUnit extends Base
class BentukUnit extends Model
{
use HasFactory;

View File

@@ -1,115 +0,0 @@
<?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',
];
}

View File

@@ -1,27 +0,0 @@
<?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);
}
}

View File

@@ -1,29 +0,0 @@
<?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);
}
}

View File

@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Modules\Lpj\Database\Factories\DenahFactory;
class Denah extends Base
class Denah extends Model
{
use HasFactory;

View File

@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
// use Modules\Lpj\Database\Factories\FasilitasObjekFactory;
class FasilitasObjek extends Base
class FasilitasObjek extends Model
{
use HasFactory;

View File

@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Modules\Lpj\Database\Factories\FotoJaminanFactory;
class FotoJaminan extends Base
class FotoJaminan extends Model
{
use HasFactory;

View File

@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
// use Modules\Lpj\Database\Factories\FotoObjekJaminanFactory;
class FotoObjekJaminan extends Base
class FotoObjekJaminan extends Model
{
use HasFactory;

View File

@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Modules\Lpj\Database\Factories\GolonganMasySekitarFactory;
class GolonganMasySekitar extends Base
class GolonganMasySekitar extends Model
{
use HasFactory;

View File

@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
// use Modules\Lpj\Database\Factories\InspeksiFactory;
class Inspeksi extends Base
class Inspeksi extends Model
{
use HasFactory;
@@ -14,7 +14,7 @@ class Inspeksi extends Base
/**
* 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','mig_detail_data_jaminan'];
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'];
public function permohonan()
{

View File

@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Modules\Lpj\Database\Factories\JenisBangunanFactory;
class JenisBangunan extends Base
class JenisBangunan extends Model
{
use HasFactory;

View File

@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
// use Modules\Lpj\Database\Factories\JenisKapalFactory;
class JenisKapal extends Base
class JenisKapal extends Model
{
use HasFactory;

View File

@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
// use Modules\Lpj\Database\Factories\JenisKendaraanFactory;
class JenisKendaraan extends Base
class JenisKendaraan extends Model
{
use HasFactory;

View File

@@ -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 Base
class JenisPenilaian extends Model
{
/**

View File

@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
// use Modules\Lpj\Database\Factories\JenisPesawatFactory;
class JenisPesawat extends Base
class JenisPesawat extends Model
{
use HasFactory;

View File

@@ -7,7 +7,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
// use Modules\Lpj\Database\Factories\JenisUnitFactory;
class JenisUnit extends Base
class JenisUnit extends Model
{
use HasFactory;

View File

@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Modules\Lpj\Database\Factories\KetinggianTanahFactory;
class KetinggianTanah extends Base
class KetinggianTanah extends Model
{
use HasFactory;

View File

@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Modules\Lpj\Database\Factories\KondisiBangunanFactory;
class KondisiBangunan extends Base
class KondisiBangunan extends Model
{
use HasFactory;

View File

@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Modules\Lpj\Database\Factories\KondisiFisikTanahFactory;
class KondisiFisikTanah extends Base
class KondisiFisikTanah extends Model
{
use HasFactory;

View File

@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Modules\Lpj\Database\Factories\KonturTanahFactory;
class KonturTanah extends Base
class KonturTanah extends Model
{
use HasFactory;

View File

@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Modules\Lpj\Database\Factories\LaluLintasLokasiFactory;
class LaluLintasLokasi extends Base
class LaluLintasLokasi extends Model
{
use HasFactory;
protected $table = 'lalu_lintas_lokasi';

View File

@@ -27,7 +27,7 @@ class LampiranDokumen extends Base
{
$user = Auth::user();
if ($user && $user->hasAnyRole(['penilai', 'administrator', 'Penilai', 'admin','surveyor','pemohon-ao','pemohon-eo'])) {
if ($user && $user->hasAnyRole(['penilai', 'administrator', 'Penilai', 'admin','surveyor'])) {
$file = $fileData['file'];
$fileName = $fileData['nama_file'] ?? time() . '_' . $file->getClientOriginalName();
$filePath = $file->storeAs('lampiran_dokumen', $fileName, 'public');

View File

@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Modules\Lpj\Database\Factories\LokasiUnitFactory;
class Lantai extends Base
class Lantai extends Model
{
use HasFactory;

View File

@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Modules\Lpj\Database\Factories\LantaiUnitFactory;
class LantaiUnit extends Base
class LantaiUnit extends Model
{
use HasFactory;

View File

@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
// use Modules\Lpj\Database\Factories\LaporanFactory;
class Laporan extends Base
class Laporan extends Model
{
use HasFactory;

View File

@@ -18,9 +18,7 @@ class LaporanAdminKredit extends Base
'tanggal_kunjungan',
'nilai_pasar_wajar',
'nilai_likuidasi',
'nama_penilai',
'keterangan',
'kolektibilitas'
'nama_penilai'
];
protected $casts = [

View File

@@ -1,114 +0,0 @@
<?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>';
}
}

View File

@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Modules\Lpj\Database\Factories\LingkunganFactory;
class Lingkungan extends Base
class Lingkungan extends Model
{
use HasFactory;

View File

@@ -7,7 +7,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
// use Modules\Lpj\Database\Factories\MerupakanDaerahFactory;
class MerupakanDaerah extends Base
class MerupakanDaerah extends Model
{
use HasFactory;

View File

@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
// use Modules\Lpj\Database\Factories\ModelAlatBeratFactory;
class ModelAlatBerat extends Base
class ModelAlatBerat extends Model
{
use HasFactory;

View File

@@ -6,5 +6,5 @@
class NilaiPlafond extends Base
{
protected $table = 'nilai_plafond';
protected $fillable = ['code', 'name', 'biaya'];
protected $fillable = ['code', 'name'];
}

View File

@@ -1,57 +0,0 @@
<?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');
}
}

View File

@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Modules\Lpj\Database\Factories\ObjekJaminanFactory;
class ObjekJaminan extends Base
class ObjekJaminan extends Model
{
use HasFactory;

View File

@@ -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 Base
class PenawaranDetailTenderLog extends Model
{
use HasFactory;
@@ -22,7 +22,7 @@ class PenawaranDetailTenderLog extends Base
{
return $this->belongsTo(PenawaranTender::class, 'penawaran_id', 'id');
}
public function penawarandetail(): BelongsTo
{
return $this->belongsTo(PenawaranDetailTender::class, 'detail_penawaran_id', 'id');

View File

@@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
// use Modules\Lpj\Database\Factories\PenilaiFactory;
class Penilai extends Base
class Penilai extends Model
{
use HasFactory;

Some files were not shown because too many files have changed in this diff Show More