Compare commits
143 Commits
lpj-db-mig
...
staging
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f934869e93 | ||
|
|
00be22fb17 | ||
|
|
22bc0bb802 | ||
|
|
9f0d6dc92c | ||
|
|
48cd479363 | ||
|
|
c5a52fa5dc | ||
|
|
27b5148ff1 | ||
|
|
d67f9908a4 | ||
|
|
adb373af89 | ||
|
|
cdf8268a6b | ||
|
|
daa121c8fa | ||
|
|
ee937f9fd6 | ||
|
|
58e0c04f4b | ||
|
|
5d47353f94 | ||
|
|
2cac6cf17c | ||
|
|
7d6e1845ad | ||
|
|
f6915cf9bc | ||
|
|
fb194bbb9a | ||
|
|
8fd7f91386 | ||
|
|
5d1dc7bf76 | ||
|
|
0129c57b0d | ||
|
|
2c56dd1d68 | ||
|
|
f402c0831a | ||
|
|
ceca0aa5e8 | ||
|
|
43361f81e7 | ||
|
|
58b53a0284 | ||
|
|
bb0da7626b | ||
|
|
8a6ab059f5 | ||
|
|
6cf4432642 | ||
|
|
7c5202021f | ||
|
|
e8a735e977 | ||
|
|
1c5b48ff1b | ||
|
|
6378ba0f98 | ||
|
|
2c8136dcf3 | ||
|
|
3315e1d4b6 | ||
|
|
37fb5c90d5 | ||
|
|
ff994a7c95 | ||
|
|
a2275758b1 | ||
|
|
783250d99a | ||
|
|
19057c7e81 | ||
|
|
9dfb8727dc | ||
|
|
bef7bcfa8f | ||
|
|
d9d8eaafcd | ||
|
|
f055cd5573 | ||
|
|
aee8fab832 | ||
|
|
a72cbe4bd9 | ||
|
|
ea09e8161c | ||
|
|
f051fa9507 | ||
|
|
04a657252f | ||
|
|
fc6f18fea9 | ||
|
|
8c60320532 | ||
|
|
34709b0f8f | ||
|
|
b2cfffc5d5 | ||
|
|
89329de198 | ||
|
|
70dda16699 | ||
|
|
db0b1f6cfc | ||
|
|
c153990c52 | ||
|
|
42d6e06a48 | ||
|
|
2db123a386 | ||
|
|
45f0d387fd | ||
|
|
7f9c58aabe | ||
|
|
3ce84b89b4 | ||
|
|
1dd4f8167e | ||
|
|
117b344857 | ||
|
|
0d5b6b1529 | ||
|
|
535be2cff3 | ||
|
|
1a67eb2000 | ||
|
|
e8ef9c0932 | ||
|
|
81f165c9d0 | ||
|
|
25011d1798 | ||
|
|
e773b82218 | ||
|
|
04ee3a0c48 | ||
|
|
10b5a6c96c | ||
|
|
3aca1d46c2 | ||
|
|
db55471111 | ||
|
|
112262d7d6 | ||
|
|
a1b9b7af86 | ||
|
|
e3540a1dd6 | ||
|
|
cd97d184ce | ||
|
|
929c56b079 | ||
|
|
388b65696f | ||
|
|
ba9089e2ac | ||
|
|
20d0061d42 | ||
|
|
4bef7cdafd | ||
|
|
bf728972b5 | ||
|
|
dfd2a82b42 | ||
|
|
c4bb3bea28 | ||
|
|
006dd44c64 | ||
|
|
698935d06f | ||
|
|
564c7ccac4 | ||
|
|
2b5556410d | ||
|
|
ee7c8ce97f | ||
|
|
17f7482080 | ||
|
|
6d137ad51c | ||
|
|
6c004812a9 | ||
|
|
d932559849 | ||
|
|
c3c40fdc27 | ||
|
|
41262e0317 | ||
|
|
2a1ecfd9e2 | ||
|
|
20833213b1 | ||
|
|
81159983cf | ||
|
|
bc35785c9c | ||
|
|
041ca943c9 | ||
|
|
312861a933 | ||
|
|
96657de512 | ||
|
|
4ad11593d5 | ||
|
|
d851ab58bc | ||
|
|
c08e050815 | ||
|
|
4aeecf6a97 | ||
|
|
1caa7ebfdd | ||
|
|
8666a0c58b | ||
|
|
99bc711954 | ||
|
|
627d7f9b40 | ||
|
|
8a5bf21982 | ||
|
|
2433aacfbc | ||
|
|
ba29f5ee8e | ||
|
|
eb784a982f | ||
|
|
2173a36564 | ||
|
|
ee079a8aa8 | ||
|
|
b4aba1a02a | ||
|
|
32baffe636 | ||
|
|
19fb39b02f | ||
|
|
bc7fef05f6 | ||
|
|
4d8b72e33a | ||
|
|
cf0059fe66 | ||
|
|
d7e5df569a | ||
|
|
cd46a3b0dc | ||
|
|
3486b97aee | ||
|
|
dc6e326122 | ||
|
|
4459b70271 | ||
|
|
57dece449c | ||
|
|
5e7368ebcf | ||
|
|
cbdd4bd99e | ||
|
|
d0cc62f8c0 | ||
|
|
0c2c0c9e20 | ||
|
|
274addb069 | ||
|
|
5c3a93c49b | ||
|
|
36ac1370d7 | ||
|
|
3eb402ae08 | ||
|
|
07589370df | ||
|
|
8220466f03 | ||
|
|
5c57b9cb58 | ||
|
|
a72515bc30 |
134
Helpers/PdfHelper.php
Normal file
134
Helpers/PdfHelper.php
Normal file
@@ -0,0 +1,134 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Helpers;
|
||||
|
||||
class PdfHelper
|
||||
{
|
||||
/**
|
||||
* Format text for PDF output to handle special characters
|
||||
*
|
||||
* @param string $text
|
||||
* @return string
|
||||
*/
|
||||
public static function formatText($text)
|
||||
{
|
||||
if (empty($text)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Common problematic characters and their safe replacements
|
||||
$replacements = [
|
||||
'<' => '<',
|
||||
'>' => '>',
|
||||
'&' => '&',
|
||||
'"' => '"',
|
||||
"'" => ''',
|
||||
'≤' => '≤',
|
||||
'≥' => '≥',
|
||||
'≠' => '!=',
|
||||
'≈' => '~',
|
||||
'×' => 'x',
|
||||
'÷' => '/',
|
||||
'–' => '-',
|
||||
'—' => '-',
|
||||
'' => '"',
|
||||
'' => '"',
|
||||
'' => "'",
|
||||
'' => "'",
|
||||
];
|
||||
|
||||
// First pass: replace with HTML entities
|
||||
$safeText = str_replace(array_keys($replacements), array_values($replacements), $text);
|
||||
|
||||
// Ensure UTF-8 encoding
|
||||
if (!mb_check_encoding($safeText, 'UTF-8')) {
|
||||
$safeText = mb_convert_encoding($safeText, 'UTF-8', 'auto');
|
||||
}
|
||||
|
||||
// Remove any remaining non-ASCII characters that could cause issues
|
||||
$safeText = preg_replace('/[^\x20-\x7E\xA0-\xFF]/', '', $safeText);
|
||||
|
||||
return $safeText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format mathematical symbols to text representation
|
||||
*
|
||||
* @param string $text
|
||||
* @return string
|
||||
*/
|
||||
public static function formatMathSymbols($text)
|
||||
{
|
||||
if (empty($text)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$mathReplacements = [
|
||||
'<' => 'kurang dari',
|
||||
'>' => 'lebih dari',
|
||||
'<=' => 'kurang dari sama dengan',
|
||||
'>=' => 'lebih dari sama dengan',
|
||||
'!=' => 'tidak sama dengan',
|
||||
'==' => 'sama dengan',
|
||||
'≤' => 'kurang dari sama dengan',
|
||||
'≥' => 'lebih dari sama dengan',
|
||||
'≠' => 'tidak sama dengan',
|
||||
'≈' => 'kira-kira',
|
||||
'≡' => 'identik dengan',
|
||||
'≅' => 'hampir sama dengan',
|
||||
];
|
||||
|
||||
return str_replace(array_keys($mathReplacements), array_values($mathReplacements), $text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape mathematical symbols for proper PDF rendering
|
||||
*
|
||||
* @param string $text
|
||||
* @return string
|
||||
*/
|
||||
public static function escapeMathSymbols($text)
|
||||
{
|
||||
if (empty($text)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Escape mathematical symbols for PDF rendering
|
||||
$mathEscapes = [
|
||||
'<' => '<',
|
||||
'>' => '>',
|
||||
'≤' => '≤',
|
||||
'≥' => '≥',
|
||||
'≠' => '!=',
|
||||
'≈' => '≈',
|
||||
'≡' => '≡',
|
||||
'≅' => '≅',
|
||||
];
|
||||
|
||||
return str_replace(array_keys($mathEscapes), array_values($mathEscapes), $text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap mathematical symbols with proper CSS class for PDF
|
||||
*
|
||||
* @param string $text
|
||||
* @return string
|
||||
*/
|
||||
public static function wrapMathSymbols($text)
|
||||
{
|
||||
if (empty($text)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// First escape the symbols
|
||||
$escapedText = self::escapeMathSymbols($text);
|
||||
|
||||
// Wrap mathematical expressions with proper class
|
||||
$patterns = [
|
||||
'/(<|>|≤|≥|!=)/' => '<span class="math-symbol">$1</span>',
|
||||
'/(\d+)\s*(<|>|≤|≥)\s*(\d+)/' => '<span class="math-symbol">$1 $2 $3</span>',
|
||||
];
|
||||
|
||||
return preg_replace(array_keys($patterns), array_values($patterns), $escapedText);
|
||||
}
|
||||
}
|
||||
27
Http/Controllers/ImageController.php
Normal file
27
Http/Controllers/ImageController.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Modules\Lpj\app\Services\ImageResizeService;
|
||||
|
||||
class ImageController extends Controller
|
||||
{
|
||||
protected $imageService;
|
||||
|
||||
public function __construct(ImageResizeService $imageService)
|
||||
{
|
||||
$this->imageService = $imageService;
|
||||
}
|
||||
|
||||
public function show(Request $request, $path)
|
||||
{
|
||||
$width = $request->query('w');
|
||||
$quality = $request->query('q', 80);
|
||||
|
||||
$resizedPath = $this->imageService->resize($path, $width, null, $quality);
|
||||
|
||||
return response()->file(storage_path('app/public/' . $resizedPath));
|
||||
}
|
||||
}
|
||||
228
app/Console/Commands/CleanupInspeksiDataCommand.php
Normal file
228
app/Console/Commands/CleanupInspeksiDataCommand.php
Normal file
@@ -0,0 +1,228 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Modules\Lpj\Jobs\CleanupInspeksiDataJob;
|
||||
use Modules\Lpj\Models\Inspeksi;
|
||||
use Modules\Lpj\Services\InspeksiCleanupService;
|
||||
|
||||
class CleanupInspeksiDataCommand extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'lpj:cleanup-inspeksi
|
||||
{--permohonan-id= : ID permohonan yang akan di-cleanup (opsional)}
|
||||
{--sync : Jalankan secara synchronous}
|
||||
{--dry-run : Tampilkan preview tanpa menjalankan cleanup}
|
||||
{--force : Jalankan tanpa konfirmasi}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Cleanup data inspeksi lama yang tidak memiliki dokument_id';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
Log::info('CleanupInspeksiDataCommand: Memulai proses cleanup data inspeksi', [
|
||||
'options' => $this->options()
|
||||
]);
|
||||
|
||||
try {
|
||||
$permohonanId = $this->option('permohonan-id');
|
||||
$sync = $this->option('sync');
|
||||
$dryRun = $this->option('dry-run');
|
||||
$force = $this->option('force');
|
||||
|
||||
// Validasi opsi
|
||||
if ($dryRun && $sync) {
|
||||
$this->error('Opsi --dry-run dan --sync tidak dapat digunakan bersamaan.');
|
||||
return Command::FAILURE;
|
||||
}
|
||||
|
||||
// Tampilkan header
|
||||
$this->info('=== Cleanup Data Inspeksi ===');
|
||||
$this->newLine();
|
||||
|
||||
// Ambil data yang akan di-cleanup
|
||||
$cleanupData = $this->getCleanupData($permohonanId);
|
||||
|
||||
if ($cleanupData->isEmpty()) {
|
||||
$this->info('Tidak ada data yang perlu di-cleanup.');
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
|
||||
// Tampilkan preview data
|
||||
$this->displayPreview($cleanupData);
|
||||
|
||||
if ($dryRun) {
|
||||
$this->info('Mode dry-run: Tidak ada perubahan yang dilakukan.');
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
|
||||
// Konfirmasi jika tidak force
|
||||
if (!$force && !$this->confirm('Lanjutkan dengan cleanup?')) {
|
||||
$this->info('Cleanup dibatalkan.');
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
|
||||
// Jalankan cleanup
|
||||
$this->runCleanup($cleanupData, $sync);
|
||||
|
||||
$this->info('Proses cleanup selesai.');
|
||||
return Command::SUCCESS;
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('CleanupInspeksiDataCommand: Terjadi error saat proses cleanup', [
|
||||
'error' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString()
|
||||
]);
|
||||
|
||||
$this->error('Terjadi kesalahan: ' . $e->getMessage());
|
||||
return Command::FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ambil data yang akan di-cleanup
|
||||
*/
|
||||
private function getCleanupData(?int $permohonanId = null)
|
||||
{
|
||||
$this->info('Mencari data yang akan di-cleanup...');
|
||||
|
||||
$query = DB::table('inspeksi as i')
|
||||
->select(
|
||||
'i.permohonan_id',
|
||||
'i.created_by',
|
||||
DB::raw('COUNT(CASE WHEN i.dokument_id IS NOT NULL AND i.deleted_at IS NULL THEN 1 END) as new_data_count'),
|
||||
DB::raw('COUNT(CASE WHEN i.dokument_id IS NULL AND i.deleted_at IS NULL THEN 1 END) as old_data_count')
|
||||
)
|
||||
->whereNull('i.deleted_at')
|
||||
->groupBy('i.permohonan_id', 'i.created_by');
|
||||
|
||||
if ($permohonanId) {
|
||||
$query->where('i.permohonan_id', $permohonanId);
|
||||
}
|
||||
|
||||
$results = $query->havingRaw('new_data_count > 0 AND old_data_count > 0')
|
||||
->get();
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tampilkan preview data
|
||||
*/
|
||||
private function displayPreview($cleanupData): void
|
||||
{
|
||||
$this->info('Data yang akan di-cleanup:');
|
||||
$this->table(
|
||||
['Permohonan ID', 'Created By', 'Data Baru', 'Data Lama'],
|
||||
$cleanupData->map(function ($item) {
|
||||
return [
|
||||
$item->permohonan_id,
|
||||
$item->created_by,
|
||||
$item->new_data_count,
|
||||
$item->old_data_count
|
||||
];
|
||||
})->toArray()
|
||||
);
|
||||
|
||||
$totalPermohonan = $cleanupData->count();
|
||||
$totalOldData = $cleanupData->sum('old_data_count');
|
||||
|
||||
$this->info("Total permohonan: {$totalPermohonan}");
|
||||
$this->info("Total data lama yang akan dihapus: {$totalOldData}");
|
||||
$this->newLine();
|
||||
}
|
||||
|
||||
/**
|
||||
* Jalankan cleanup
|
||||
*/
|
||||
private function runCleanup($cleanupData, bool $sync): void
|
||||
{
|
||||
$this->info('Memulai proses cleanup...');
|
||||
$this->newLine();
|
||||
|
||||
$progressBar = $this->output->createProgressBar($cleanupData->count());
|
||||
$progressBar->setFormat('Processing: %current%/%max% [%bar%] %percent:3s%% %message%');
|
||||
$progressBar->start();
|
||||
|
||||
$totalDeleted = 0;
|
||||
$totalErrors = 0;
|
||||
|
||||
foreach ($cleanupData as $data) {
|
||||
try {
|
||||
$progressBar->setMessage("Permohonan ID: {$data->permohonan_id}");
|
||||
|
||||
// Ambil data baru untuk mendapatkan dokument_id
|
||||
$newInspeksi = Inspeksi::where('permohonan_id', $data->permohonan_id)
|
||||
->where('created_by', $data->created_by)
|
||||
->whereNotNull('dokument_id')
|
||||
->whereNull('deleted_at')
|
||||
->first();
|
||||
|
||||
if (!$newInspeksi) {
|
||||
$this->warn("Tidak ditemukan data baru untuk permohonan {$data->permohonan_id}");
|
||||
$progressBar->advance();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Jalankan cleanup
|
||||
if ($sync) {
|
||||
// Jalankan sync
|
||||
$job = new CleanupInspeksiDataJob(
|
||||
$data->permohonan_id,
|
||||
$data->created_by,
|
||||
$newInspeksi->dokument_id
|
||||
);
|
||||
$job->handle();
|
||||
} else {
|
||||
// Dispatch ke queue
|
||||
CleanupInspeksiDataJob::dispatch(
|
||||
$data->permohonan_id,
|
||||
$data->created_by,
|
||||
$newInspeksi->dokument_id
|
||||
);
|
||||
}
|
||||
|
||||
$totalDeleted += $data->old_data_count;
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('CleanupInspeksiDataCommand: Error pada permohonan', [
|
||||
'permohonan_id' => $data->permohonan_id,
|
||||
'created_by' => $data->created_by,
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
|
||||
$this->error("Error pada permohonan {$data->permohonan_id}: {$e->getMessage()}");
|
||||
$totalErrors++;
|
||||
}
|
||||
|
||||
$progressBar->advance();
|
||||
}
|
||||
|
||||
$progressBar->finish();
|
||||
$this->newLine();
|
||||
$this->newLine();
|
||||
|
||||
// Tampilkan hasil
|
||||
$this->info('=== Hasil Cleanup ===');
|
||||
$this->info("Data lama yang dihapus: {$totalDeleted}");
|
||||
$this->info("Error: {$totalErrors}");
|
||||
|
||||
if (!$sync) {
|
||||
$this->info('Job telah di-dispatch ke queue. Monitor progress di log.');
|
||||
}
|
||||
}
|
||||
}
|
||||
192
app/Console/Commands/CleanupInspeksiStatusCommand.php
Normal file
192
app/Console/Commands/CleanupInspeksiStatusCommand.php
Normal file
@@ -0,0 +1,192 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Modules\Lpj\Models\Inspeksi;
|
||||
|
||||
class CleanupInspeksiStatusCommand extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'lpj:cleanup-inspeksi-status
|
||||
{--permohonan-id= : Filter berdasarkan permohonan ID}
|
||||
{--created-by= : Filter berdasarkan user ID}
|
||||
{--detailed : Tampilkan detail data}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Cek status data inspeksi yang memerlukan cleanup';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
try {
|
||||
$permohonanId = $this->option('permohonan-id');
|
||||
$createdBy = $this->option('created-by');
|
||||
$detailed = $this->option('detailed');
|
||||
|
||||
$this->info('=== Status Data Inspeksi ===');
|
||||
$this->newLine();
|
||||
|
||||
// Ambil statistik umum
|
||||
$this->showGeneralStats();
|
||||
|
||||
// Ambil data yang memerlukan cleanup
|
||||
$this->showCleanupStats($permohonanId, $createdBy);
|
||||
|
||||
if ($detailed) {
|
||||
$this->showDetailedData($permohonanId, $createdBy);
|
||||
}
|
||||
|
||||
return Command::SUCCESS;
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('CleanupInspeksiStatusCommand: Terjadi error', [
|
||||
'error' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString()
|
||||
]);
|
||||
|
||||
$this->error('Terjadi kesalahan: ' . $e->getMessage());
|
||||
return Command::FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tampilkan statistik umum
|
||||
*/
|
||||
private function showGeneralStats(): void
|
||||
{
|
||||
$this->info('Statistik Umum:');
|
||||
|
||||
$totalData = Inspeksi::count();
|
||||
$activeData = Inspeksi::whereNull('deleted_at')->count();
|
||||
$deletedData = Inspeksi::whereNotNull('deleted_at')->count();
|
||||
$dataWithDokument = Inspeksi::whereNotNull('dokument_id')->count();
|
||||
$dataWithoutDokument = Inspeksi::whereNull('dokument_id')->count();
|
||||
|
||||
$this->table(
|
||||
['Metrik', 'Jumlah'],
|
||||
[
|
||||
['Total Data', number_format($totalData)],
|
||||
['Data Aktif', number_format($activeData)],
|
||||
['Data Terhapus (Soft)', number_format($deletedData)],
|
||||
['Data dengan Dokument ID', number_format($dataWithDokument)],
|
||||
['Data tanpa Dokument ID', number_format($dataWithoutDokument)],
|
||||
]
|
||||
);
|
||||
|
||||
$this->newLine();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tampilkan statistik cleanup
|
||||
*/
|
||||
private function showCleanupStats(?int $permohonanId = null, ?int $createdBy = null): void
|
||||
{
|
||||
$this->info('Data yang Memerlukan Cleanup:');
|
||||
|
||||
$query = DB::table('inspeksi as i')
|
||||
->select(
|
||||
'i.permohonan_id',
|
||||
'i.created_by',
|
||||
DB::raw('COUNT(CASE WHEN i.dokument_id IS NOT NULL AND i.deleted_at IS NULL THEN 1 END) as new_data_count'),
|
||||
DB::raw('COUNT(CASE WHEN i.dokument_id IS NULL AND i.deleted_at IS NULL THEN 1 END) as old_data_count'),
|
||||
DB::raw('MIN(i.created_at) as oldest_data'),
|
||||
DB::raw('MAX(i.created_at) as newest_data')
|
||||
)
|
||||
->whereNull('i.deleted_at')
|
||||
->groupBy('i.permohonan_id', 'i.created_by');
|
||||
|
||||
if ($permohonanId) {
|
||||
$query->where('i.permohonan_id', $permohonanId);
|
||||
}
|
||||
|
||||
if ($createdBy) {
|
||||
$query->where('i.created_by', $createdBy);
|
||||
}
|
||||
|
||||
$results = $query->havingRaw('new_data_count > 0 AND old_data_count > 0')
|
||||
->orderBy('old_data_count', 'desc')
|
||||
->limit(20)
|
||||
->get();
|
||||
|
||||
if ($results->isEmpty()) {
|
||||
$this->info('Tidak ada data yang memerlukan cleanup.');
|
||||
return;
|
||||
}
|
||||
|
||||
$this->table(
|
||||
['Permohonan ID', 'Created By', 'Data Baru', 'Data Lama', 'Data Terlama', 'Data Terbaru'],
|
||||
$results->map(function ($item) {
|
||||
return [
|
||||
$item->permohonan_id,
|
||||
$item->created_by,
|
||||
$item->new_data_count,
|
||||
$item->old_data_count,
|
||||
$item->oldest_data,
|
||||
$item->newest_data,
|
||||
];
|
||||
})->toArray()
|
||||
);
|
||||
|
||||
$totalPermohonan = $results->count();
|
||||
$totalOldData = $results->sum('old_data_count');
|
||||
|
||||
$this->info("Total permohonan yang perlu cleanup: {$totalPermohonan}");
|
||||
$this->info("Total data lama yang akan dihapus: {$totalOldData}");
|
||||
$this->newLine();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tampilkan detail data
|
||||
*/
|
||||
private function showDetailedData(?int $permohonanId = null, ?int $createdBy = null): void
|
||||
{
|
||||
$this->info('Detail Data (20 data terbaru):');
|
||||
|
||||
$query = Inspeksi::with(['permohonan', 'dokument'])
|
||||
->whereNull('deleted_at');
|
||||
|
||||
if ($permohonanId) {
|
||||
$query->where('permohonan_id', $permohonanId);
|
||||
}
|
||||
|
||||
if ($createdBy) {
|
||||
$query->where('created_by', $createdBy);
|
||||
}
|
||||
|
||||
$data = $query->orderBy('created_at', 'desc')
|
||||
->limit(20)
|
||||
->get();
|
||||
|
||||
if ($data->isEmpty()) {
|
||||
$this->info('Tidak ada data untuk ditampilkan.');
|
||||
return;
|
||||
}
|
||||
|
||||
$this->table(
|
||||
['ID', 'Permohonan ID', 'Created By', 'Dokument ID', 'Status', 'Created At'],
|
||||
$data->map(function ($item) {
|
||||
return [
|
||||
$item->id,
|
||||
$item->permohonan_id,
|
||||
$item->created_by,
|
||||
$item->dokument_id ?? '-',
|
||||
$item->status,
|
||||
$item->created_at,
|
||||
];
|
||||
})->toArray()
|
||||
);
|
||||
}
|
||||
}
|
||||
99
app/Console/Commands/CleanupSingleInspeksiCommand.php
Normal file
99
app/Console/Commands/CleanupSingleInspeksiCommand.php
Normal file
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Modules\Lpj\Jobs\CleanupInspeksiDataJob;
|
||||
use Modules\Lpj\Services\InspeksiCleanupService;
|
||||
|
||||
class CleanupSingleInspeksiCommand extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'lpj:cleanup-single-inspeksi
|
||||
{permohonan-id : ID permohonan yang akan di-cleanup}
|
||||
{created-by : ID user yang membuat data}
|
||||
{--sync : Jalankan secara synchronous}
|
||||
{--force : Jalankan tanpa konfirmasi}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Cleanup data inspeksi untuk 1 permohonan dan user tertentu';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
Log::info('CleanupSingleInspeksiCommand: Memulai proses cleanup', [
|
||||
'permohonan_id' => $this->argument('permohonan-id'),
|
||||
'created_by' => $this->argument('created-by'),
|
||||
'sync' => $this->option('sync')
|
||||
]);
|
||||
|
||||
try {
|
||||
$permohonanId = (int) $this->argument('permohonan-id');
|
||||
$createdBy = (int) $this->argument('created-by');
|
||||
$sync = $this->option('sync');
|
||||
$force = $this->option('force');
|
||||
|
||||
// Validasi input
|
||||
if ($permohonanId <= 0) {
|
||||
$this->error('Permohonan ID harus angka positif.');
|
||||
return Command::FAILURE;
|
||||
}
|
||||
|
||||
if ($createdBy <= 0) {
|
||||
$this->error('Created By harus angka positif.');
|
||||
return Command::FAILURE;
|
||||
}
|
||||
|
||||
// Tampilkan info
|
||||
$this->info('=== Cleanup Single Inspeksi ===');
|
||||
$this->info("Permohonan ID: {$permohonanId}");
|
||||
$this->info("Created By: {$createdBy}");
|
||||
$this->info("Mode: " . ($sync ? 'Synchronous' : 'Queue'));
|
||||
$this->newLine();
|
||||
|
||||
// Konfirmasi jika tidak force
|
||||
if (!$force && !$this->confirm('Lanjutkan dengan cleanup?')) {
|
||||
$this->info('Cleanup dibatalkan.');
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
|
||||
// Jalankan cleanup
|
||||
$cleanupService = new InspeksiCleanupService();
|
||||
|
||||
if ($sync) {
|
||||
$this->info('Menjalankan cleanup secara synchronous...');
|
||||
$cleanupService->cleanupSync($permohonanId, $createdBy);
|
||||
$this->info('Cleanup selesai.');
|
||||
} else {
|
||||
$this->info('Mengirim job ke queue...');
|
||||
$cleanupService->cleanupAsync($permohonanId, $createdBy);
|
||||
$this->info('Job telah di-dispatch ke queue.');
|
||||
$this->info('Monitor progress di log.');
|
||||
}
|
||||
|
||||
return Command::SUCCESS;
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('CleanupSingleInspeksiCommand: Terjadi error saat proses cleanup', [
|
||||
'permohonan_id' => $this->argument('permohonan-id'),
|
||||
'created_by' => $this->argument('created-by'),
|
||||
'error' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString()
|
||||
]);
|
||||
|
||||
$this->error('Terjadi kesalahan: ' . $e->getMessage());
|
||||
return Command::FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
123
app/Console/README.md
Normal file
123
app/Console/README.md
Normal file
@@ -0,0 +1,123 @@
|
||||
# Console Commands untuk Cleanup Data Inspeksi
|
||||
|
||||
## Daftar Command
|
||||
|
||||
### 1. `lpj:cleanup-inspeksi`
|
||||
Command utama untuk cleanup data inspeksi secara batch.
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
php artisan lpj:cleanup-inspeksi [options]
|
||||
```
|
||||
|
||||
**Options:**
|
||||
- `--permohonan-id=ID` - Filter berdasarkan permohonan ID (opsional)
|
||||
- `--sync` - Jalankan secara synchronous
|
||||
- `--dry-run` - Tampilkan preview tanpa menjalankan cleanup
|
||||
- `--force` - Jalankan tanpa konfirmasi
|
||||
|
||||
**Contoh Penggunaan:**
|
||||
```bash
|
||||
# Preview data yang akan di-cleanup
|
||||
php artisan lpj:cleanup-inspeksi --dry-run
|
||||
|
||||
# Cleanup semua data (dengan konfirmasi)
|
||||
php artisan lpj:cleanup-inspeksi
|
||||
|
||||
# Cleanup untuk permohonan tertentu
|
||||
php artisan lpj:cleanup-inspeksi --permohonan-id=123 --force
|
||||
|
||||
# Jalankan secara sync
|
||||
php artisan lpj:cleanup-inspeksi --sync --force
|
||||
```
|
||||
|
||||
### 2. `lpj:cleanup-single-inspeksi`
|
||||
Command untuk cleanup 1 permohonan dan user tertentu.
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
php artisan lpj:cleanup-single-inspeksi <permohonan-id> <created-by> [options]
|
||||
```
|
||||
|
||||
**Arguments:**
|
||||
- `permohonan-id` - ID permohonan yang akan di-cleanup (required)
|
||||
- `created-by` - ID user yang membuat data (required)
|
||||
|
||||
**Options:**
|
||||
- `--sync` - Jalankan secara synchronous
|
||||
- `--force` - Jalankan tanpa konfirmasi
|
||||
|
||||
**Contoh Penggunaan:**
|
||||
```bash
|
||||
# Cleanup untuk permohonan 123 oleh user 456
|
||||
php artisan lpj:cleanup-single-inspeksi 123 456
|
||||
|
||||
# Jalankan secara sync tanpa konfirmasi
|
||||
php artisan lpj:cleanup-single-inspeksi 123 456 --sync --force
|
||||
```
|
||||
|
||||
### 3. `lpj:cleanup-inspeksi-status`
|
||||
Command untuk mengecek status data inspeksi dan melihat statistik cleanup.
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
php artisan lpj:cleanup-inspeksi-status [options]
|
||||
```
|
||||
|
||||
**Options:**
|
||||
- `--permohonan-id=ID` - Filter berdasarkan permohonan ID
|
||||
- `--created-by=ID` - Filter berdasarkan user ID
|
||||
- `--detailed` - Tampilkan detail data
|
||||
|
||||
**Contoh Penggunaan:**
|
||||
```bash
|
||||
# Lihat statistik umum
|
||||
php artisan lpj:cleanup-inspeksi-status
|
||||
|
||||
# Filter berdasarkan permohonan
|
||||
php artisan lpj:cleanup-inspeksi-status --permohonan-id=123
|
||||
|
||||
# Tampilkan detail data
|
||||
php artisan lpj:cleanup-inspeksi-status --detailed
|
||||
```
|
||||
|
||||
## Scheduling
|
||||
|
||||
Command cleanup otomatis dijalankan setiap hari jam 2 pagi dan setiap minggu. Konfigurasi scheduling ada di `LpjServiceProvider.php`.
|
||||
|
||||
## Monitoring
|
||||
|
||||
Semua aktivitas cleanup dicatat di log file:
|
||||
- `storage/logs/laravel.log` - Log umum
|
||||
- `storage/logs/cleanup-inspeksi.log` - Log cleanup harian
|
||||
- `storage/logs/cleanup-inspeksi-weekly.log` - Log cleanup mingguan
|
||||
|
||||
## Alur Kerja Cleanup
|
||||
|
||||
1. **Identifikasi**: Cari data inspeksi yang memiliki:
|
||||
- Data baru dengan `dokument_id` (tidak null)
|
||||
- Data lama tanpa `dokument_id` (null)
|
||||
- Sama `permohonan_id` dan `created_by`
|
||||
|
||||
2. **Proses**: Soft delete data lama menggunakan Laravel SoftDeletes
|
||||
|
||||
3. **Logging**: Catat setiap operasi untuk audit trail
|
||||
|
||||
4. **Transaction**: Gunakan DB transaction untuk konsistensi data
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Command tidak muncul
|
||||
Pastikan service provider sudah diregister dengan benar:
|
||||
```bash
|
||||
php artisan list | grep lpj
|
||||
```
|
||||
|
||||
### Data tidak ter-cleanup
|
||||
- Cek log untuk error
|
||||
- Pastikan ada data yang memenuhi kriteria
|
||||
- Gunakan `--dry-run` untuk preview
|
||||
- Gunakan `--detailed` untuk melihat detail data
|
||||
|
||||
### Performance
|
||||
Untuk data besar, gunakan mode queue (default) daripada `--sync`
|
||||
154
app/Emails/SendJadwalKunjunganEmailPHPMailer.php
Normal file
154
app/Emails/SendJadwalKunjunganEmailPHPMailer.php
Normal file
@@ -0,0 +1,154 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Emails;
|
||||
|
||||
use App\Services\PHPMailerService;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\PHPMailer\Exception;
|
||||
|
||||
class SendJadwalKunjunganEmailPHPMailer
|
||||
{
|
||||
/**
|
||||
* Data jadwal kunjungan
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* Waktu penilaian
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $waktu_penilaian;
|
||||
|
||||
/**
|
||||
* Deskripsi penilaian
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $deskripsi_penilaian;
|
||||
|
||||
protected $phpMailerService;
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*
|
||||
* @param array $emailData
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(array $emailData)
|
||||
{
|
||||
// Validasi data yang diterima
|
||||
if (!isset($emailData['emailData']['id']) ||
|
||||
!isset($emailData['emailData']['waktu_penilaian']) ||
|
||||
!isset($emailData['emailData']['deskripsi_penilaian'])) {
|
||||
throw new \InvalidArgumentException("Data email tidak lengkap.");
|
||||
}
|
||||
|
||||
$this->id = $emailData['emailData']['id'];
|
||||
$this->waktu_penilaian = $emailData['emailData']['waktu_penilaian'];
|
||||
$this->deskripsi_penilaian = $emailData['emailData']['deskripsi_penilaian'];
|
||||
|
||||
// Inisialisasi PHPMailerService
|
||||
$this->phpMailerService = new PHPMailerService([
|
||||
'host' => config('mail.mailers.phpmailer.host', 'mail.ag.co.id'),
|
||||
'port' => config('mail.mailers.phpmailer.port', 465),
|
||||
'username' => config('mail.mailers.phpmailer.username', 'BAGI@ag.co.id'),
|
||||
'password' => config('mail.mailers.phpmailer.password', 'BAG@202!'),
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Build the message.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function build(): self
|
||||
{
|
||||
return $this->view('lpj::emails.jadwal-kunjungan');
|
||||
}
|
||||
|
||||
/**
|
||||
* Kirim email menggunakan PHPMailer dengan dukungan attachment
|
||||
*
|
||||
* @param mixed $recipients
|
||||
* @param array $attachments
|
||||
* @return array
|
||||
*/
|
||||
public function sendWithPHPMailer($recipients, $attachments = [])
|
||||
{
|
||||
try {
|
||||
// Build HTML content
|
||||
$htmlContent = $this->buildHtml();
|
||||
|
||||
// Setup PHPMailer
|
||||
$mail = new PHPMailer(true);
|
||||
|
||||
// Server settings - menggunakan konfigurasi yang sama seperti EmailController
|
||||
$mail->isSMTP();
|
||||
$mail->Host = config('mail.mailers.smtp.host', 'mail.ag.co.id');
|
||||
$mail->SMTPAuth = true;
|
||||
$mail->Username = config('mail.mailers.smtp.username', 'BAGI@ag.co.id');
|
||||
$mail->Password = config('mail.mailers.smtp.password', 'BAG@202!');
|
||||
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
|
||||
$mail->Port = config('mail.mailers.smtp.port', 465);
|
||||
|
||||
// Bypass SSL Verification - sama seperti EmailController
|
||||
$mail->SMTPOptions = array(
|
||||
'ssl' => array(
|
||||
'verify_peer' => false,
|
||||
'verify_peer_name' => false,
|
||||
'allow_self_signed' => true
|
||||
)
|
||||
);
|
||||
|
||||
// Recipients
|
||||
if (is_array($recipients)) {
|
||||
foreach ($recipients as $recipient) {
|
||||
$mail->addAddress($recipient);
|
||||
}
|
||||
} else {
|
||||
$mail->addAddress($recipients);
|
||||
}
|
||||
|
||||
// Content
|
||||
$mail->isHTML(true);
|
||||
$mail->Subject = 'Jadwal Kunjungan Penilaian Resmi';
|
||||
$mail->Body = $htmlContent;
|
||||
$mail->AltBody = strip_tags($htmlContent);
|
||||
|
||||
// Add attachments if provided
|
||||
foreach ($attachments as $attachment) {
|
||||
if (file_exists($attachment)) {
|
||||
$mail->addAttachment($attachment);
|
||||
}
|
||||
}
|
||||
|
||||
$mail->send();
|
||||
|
||||
Log::info('Email jadwal kunjungan berhasil dikirim menggunakan PHPMailer', [
|
||||
'recipients' => $recipients,
|
||||
'attachments' => $attachments
|
||||
]);
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'message' => 'Email berhasil dikirim'
|
||||
];
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Gagal mengirim email jadwal kunjungan menggunakan PHPMailer', [
|
||||
'recipients' => $recipients,
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
|
||||
return [
|
||||
'success' => false,
|
||||
'error' => $e->getMessage()
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
144
app/Emails/SendPenawaranKJPPEmailPHPMailer.php
Normal file
144
app/Emails/SendPenawaranKJPPEmailPHPMailer.php
Normal file
@@ -0,0 +1,144 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Emails;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use App\Services\PHPMailerService;
|
||||
|
||||
class SendPenawaranKJPPEmailPHPMailer extends Mailable
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
// Tambahkan properti untuk data yang akan dikirimkan ke view
|
||||
public $dp1;
|
||||
public $penawaran;
|
||||
public $permohonan;
|
||||
public $villages;
|
||||
public $districts;
|
||||
public $cities;
|
||||
public $provinces;
|
||||
public $user; // Tambahkan user ke data yang dikirimkan ke view, sebagai cc dan bcc
|
||||
|
||||
protected $phpMailerService;
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*/
|
||||
public function __construct($dp1, $penawaran, $permohonan, $villages, $districts, $cities, $provinces, $user)
|
||||
{
|
||||
// Assign data yang diterima ke properti
|
||||
$this->dp1 = $dp1;
|
||||
$this->penawaran = $penawaran;
|
||||
$this->permohonan = $permohonan;
|
||||
$this->villages = $villages;
|
||||
$this->districts = $districts;
|
||||
$this->cities = $cities;
|
||||
$this->provinces = $provinces;
|
||||
$this->user = $user; // Tambahkan user ke data yang dikirimkan ke view, sebagai cc dan bcc
|
||||
|
||||
// Inisialisasi PHPMailerService
|
||||
$this->phpMailerService = new PHPMailerService([
|
||||
'host' => config('mail.mailers.phpmailer.host', 'mail.ag.co.id'),
|
||||
'port' => config('mail.mailers.phpmailer.port', 465),
|
||||
'username' => config('mail.mailers.phpmailer.username', 'BAGI@ag.co.id'),
|
||||
'password' => config('mail.mailers.phpmailer.password', 'BAG@202!'),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the message.
|
||||
*/
|
||||
public function build(): self
|
||||
{
|
||||
// Kirim data ke view
|
||||
return $this->view('lpj::penawaran.kirimEmailKJPP')
|
||||
->with([
|
||||
'dp1' => $this->dp1,
|
||||
'penawaran' => $this->penawaran,
|
||||
'permohonan' => $this->permohonan,
|
||||
'villages' => $this->villages,
|
||||
'districts' => $this->districts,
|
||||
'cities' => $this->cities,
|
||||
'provinces' => $this->provinces,
|
||||
'user' => $this->user // Tambahkan user ke data yang dikirimkan ke view, sebagai cc dan bcc
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Kirim email menggunakan PHPMailer
|
||||
*/
|
||||
public function sendWithPHPMailer($recipients)
|
||||
{
|
||||
// Gunakan view yang dapat diakses secara global untuk testing
|
||||
// Jika data adalah array (testing), gunakan view sederhana
|
||||
// Jika data adalah object (production), gunakan view asli
|
||||
if (is_array($this->dp1) || is_array($this->penawaran) || is_array($this->permohonan)) {
|
||||
// Mode testing - gunakan view sederhana
|
||||
$htmlContent = view('emails.test-kjpp-phpmailer', [
|
||||
'dp1' => $this->dp1,
|
||||
'penawaran' => $this->penawaran,
|
||||
'permohonan' => $this->permohonan,
|
||||
'villages' => $this->villages,
|
||||
'districts' => $this->districts,
|
||||
'cities' => $this->cities,
|
||||
'provinces' => $this->provinces,
|
||||
'user' => $this->user
|
||||
])->render();
|
||||
} else {
|
||||
// Mode production - gunakan view asli
|
||||
$htmlContent = view('lpj::penawaran.kirimEmailKJPP', [
|
||||
'dp1' => $this->dp1,
|
||||
'penawaran' => $this->penawaran,
|
||||
'permohonan' => $this->permohonan,
|
||||
'villages' => $this->villages,
|
||||
'districts' => $this->districts,
|
||||
'cities' => $this->cities,
|
||||
'provinces' => $this->provinces,
|
||||
'user' => $this->user
|
||||
])->render();
|
||||
}
|
||||
|
||||
// Siapkan data untuk PHPMailer
|
||||
$data = [
|
||||
'from' => [
|
||||
'address' => config('mail.from.address', 'BAGI@ag.co.id'),
|
||||
'name' => config('mail.from.name', 'Notifikasi Sistem Laravel')
|
||||
],
|
||||
'to' => [],
|
||||
'cc' => [],
|
||||
'bcc' => [],
|
||||
'subject' => 'Penawaran KJPP Tender',
|
||||
'html' => $htmlContent,
|
||||
'text' => strip_tags($htmlContent)
|
||||
];
|
||||
|
||||
// Proses recipients
|
||||
if (is_array($recipients)) {
|
||||
foreach ($recipients as $recipient) {
|
||||
if (is_string($recipient)) {
|
||||
$data['to'][] = ['address' => $recipient, 'name' => ''];
|
||||
} elseif (is_array($recipient)) {
|
||||
$data['to'][] = [
|
||||
'address' => $recipient['address'] ?? $recipient['email'] ?? '',
|
||||
'name' => $recipient['name'] ?? ''
|
||||
];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$data['to'][] = ['address' => $recipients, 'name' => ''];
|
||||
}
|
||||
|
||||
// Tambahkan CC dan BCC dari user jika ada
|
||||
if ($this->user && isset($this->user->email)) {
|
||||
$data['cc'][] = [
|
||||
'address' => $this->user->email,
|
||||
'name' => $this->user->name ?? 'User'
|
||||
];
|
||||
}
|
||||
|
||||
// Kirim email menggunakan PHPMailerService
|
||||
return $this->phpMailerService->sendEmail($data);
|
||||
}
|
||||
}
|
||||
@@ -2,28 +2,148 @@
|
||||
|
||||
namespace Modules\Lpj\Emails;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
// use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use App\Mail\PHPMailerMailable;
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class SendPenawaranTenderEmail extends Mailable
|
||||
class SendPenawaranTenderEmail extends PHPMailerMailable
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
protected $penawaran;
|
||||
protected $permohonan;
|
||||
protected $villages;
|
||||
protected $districts;
|
||||
protected $cities;
|
||||
protected $provinces;
|
||||
protected $user;
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*/
|
||||
public function __construct()
|
||||
public function __construct($penawaran, $permohonan, $villages, $districts, $cities, $provinces, $user)
|
||||
{
|
||||
//
|
||||
$this->penawaran = $penawaran;
|
||||
$this->permohonan = $permohonan;
|
||||
$this->villages = $villages;
|
||||
$this->districts = $districts;
|
||||
$this->cities = $cities;
|
||||
$this->provinces = $provinces;
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the message.
|
||||
*/
|
||||
public function build(): self
|
||||
public function buildHtml(): string
|
||||
{
|
||||
return $this->view('lpj::penawaran.kirimEmail');
|
||||
// Gunakan view test untuk testing atau view asli untuk produksi
|
||||
$viewName = 'emails.test-penawaran-tender-phpmailer';
|
||||
|
||||
// Cek apakah data berbentuk array atau object untuk menentukan view yang digunakan
|
||||
if (is_array($this->penawaran) || is_object($this->penawaran)) {
|
||||
// Gunakan view test untuk testing
|
||||
return view($viewName, [
|
||||
'penawaran' => $this->penawaran,
|
||||
'permohonan' => $this->permohonan,
|
||||
'villages' => $this->villages,
|
||||
'districts' => $this->districts,
|
||||
'cities' => $this->cities,
|
||||
'provinces' => $this->provinces,
|
||||
'user' => $this->user
|
||||
])->render();
|
||||
}
|
||||
|
||||
// Fallback ke view asli jika diperlukan
|
||||
return view('lpj::penawaran.kirimEmail', [
|
||||
'penawaran' => $this->penawaran,
|
||||
'permohonan' => $this->permohonan,
|
||||
'villages' => $this->villages,
|
||||
'districts' => $this->districts,
|
||||
'cities' => $this->cities,
|
||||
'provinces' => $this->provinces,
|
||||
'user' => $this->user
|
||||
])->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Send email using PHPMailer
|
||||
*/
|
||||
public function sendWithPHPMailer($recipients, $attachments = [])
|
||||
{
|
||||
try {
|
||||
$htmlContent = $this->buildHtml();
|
||||
|
||||
// Konfigurasi PHPMailer
|
||||
$mail = new PHPMailer(true);
|
||||
|
||||
// Server settings - menggunakan konfigurasi yang sudah terbukti berhasil
|
||||
$mail->isSMTP();
|
||||
$mail->Host = 'mail.ag.co.id';
|
||||
$mail->SMTPAuth = true;
|
||||
$mail->Username = 'BAGI@ag.co.id';
|
||||
$mail->Password = 'BAG@202!';
|
||||
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
|
||||
$mail->Port = 465;
|
||||
|
||||
// Bypass SSL Verification untuk menghindari certificate verify failed
|
||||
$mail->SMTPOptions = array(
|
||||
'ssl' => array(
|
||||
'verify_peer' => false,
|
||||
'verify_peer_name' => false,
|
||||
'allow_self_signed' => true
|
||||
)
|
||||
);
|
||||
|
||||
// Recipients
|
||||
if (is_array($recipients)) {
|
||||
foreach ($recipients as $recipient) {
|
||||
$mail->addAddress($recipient);
|
||||
}
|
||||
} else {
|
||||
$mail->addAddress($recipients);
|
||||
}
|
||||
|
||||
// Content
|
||||
$mail->isHTML(true);
|
||||
$mail->Subject = 'Penawaran Tender Baru';
|
||||
$mail->Body = $htmlContent;
|
||||
$mail->AltBody = strip_tags($htmlContent);
|
||||
|
||||
// Add attachments if provided
|
||||
foreach ($attachments as $attachment) {
|
||||
if (is_array($attachment) && isset($attachment['path'])) {
|
||||
// Format array dengan nama custom
|
||||
$attachmentName = $attachment['name'] ?? basename($attachment['path']);
|
||||
if (file_exists($attachment['path'])) {
|
||||
$mail->addAttachment($attachment['path'], $attachmentName);
|
||||
}
|
||||
} elseif (is_string($attachment) && file_exists($attachment)) {
|
||||
// Format string sederhana
|
||||
$mail->addAttachment($attachment);
|
||||
}
|
||||
}
|
||||
|
||||
$mail->send();
|
||||
|
||||
Log::info('Email penawaran tender berhasil dikirim menggunakan PHPMailer', [
|
||||
'recipients' => $recipients,
|
||||
'attachments' => $attachments
|
||||
]);
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'message' => 'Email berhasil dikirim'
|
||||
];
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Gagal mengirim email penawaran tender menggunakan PHPMailer', [
|
||||
'recipients' => $recipients,
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
|
||||
return [
|
||||
'success' => false,
|
||||
'error' => $e->getMessage()
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
132
app/Emails/SendPenawaranTenderEmailPHPMailer.php
Normal file
132
app/Emails/SendPenawaranTenderEmailPHPMailer.php
Normal file
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Emails;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use App\Services\PHPMailerService;
|
||||
|
||||
class SendPenawaranTenderEmailPHPMailer extends Mailable
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
public $penawaran;
|
||||
public $permohonan;
|
||||
public $villages;
|
||||
public $districts;
|
||||
public $cities;
|
||||
public $provinces;
|
||||
public $user;
|
||||
|
||||
protected $phpMailerService;
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*/
|
||||
public function __construct($penawaran = null, $permohonan = null, $villages = null, $districts = null, $cities = null, $provinces = null, $user = null)
|
||||
{
|
||||
$this->penawaran = $penawaran;
|
||||
$this->permohonan = $permohonan;
|
||||
$this->villages = $villages;
|
||||
$this->districts = $districts;
|
||||
$this->cities = $cities;
|
||||
$this->provinces = $provinces;
|
||||
$this->user = $user;
|
||||
|
||||
// Inisialisasi PHPMailerService
|
||||
$this->phpMailerService = new PHPMailerService([
|
||||
'host' => config('mail.mailers.phpmailer.host', 'mail.ag.co.id'),
|
||||
'port' => config('mail.mailers.phpmailer.port', 465),
|
||||
'username' => config('mail.mailers.phpmailer.username', 'BAGI@ag.co.id'),
|
||||
'password' => config('mail.mailers.phpmailer.password', 'BAG@202!'),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the message.
|
||||
*/
|
||||
public function build(): self
|
||||
{
|
||||
return $this->view('lpj::penawaran.kirimEmail');
|
||||
}
|
||||
|
||||
/**
|
||||
* Kirim email menggunakan PHPMailer dengan dukungan attachment
|
||||
*
|
||||
* @param mixed $recipients
|
||||
* @param array $attachments
|
||||
* @return array
|
||||
*/
|
||||
public function sendWithPHPMailer($recipients, $attachments = [])
|
||||
{
|
||||
// Gunakan view yang dapat diakses secara global untuk testing
|
||||
// Jika data adalah array (testing), gunakan view sederhana
|
||||
// Jika data adalah object (production), gunakan view asli
|
||||
if (is_array($this->penawaran) || is_array($this->permohonan) || is_array($this->villages)) {
|
||||
// Mode testing - gunakan view sederhana
|
||||
$htmlContent = view('emails.test-penawaran-tender-phpmailer', [
|
||||
'penawaran' => $this->penawaran,
|
||||
'permohonan' => $this->permohonan,
|
||||
'villages' => $this->villages,
|
||||
'districts' => $this->districts,
|
||||
'cities' => $this->cities,
|
||||
'provinces' => $this->provinces,
|
||||
'user' => $this->user
|
||||
])->render();
|
||||
} else {
|
||||
// Mode production - gunakan view asli
|
||||
$htmlContent = view('lpj::penawaran.kirimEmail', [
|
||||
'penawaran' => $this->penawaran,
|
||||
'permohonan' => $this->permohonan,
|
||||
'villages' => $this->villages,
|
||||
'districts' => $this->districts,
|
||||
'cities' => $this->cities,
|
||||
'provinces' => $this->provinces,
|
||||
'user' => $this->user
|
||||
])->render();
|
||||
}
|
||||
|
||||
// Siapkan data untuk PHPMailer
|
||||
$data = [
|
||||
'from' => [
|
||||
'address' => config('mail.from.address', 'BAGI@ag.co.id'),
|
||||
'name' => config('mail.from.name', 'Notifikasi Sistem Laravel')
|
||||
],
|
||||
'to' => [],
|
||||
'cc' => [],
|
||||
'bcc' => [],
|
||||
'subject' => 'Penawaran Tender',
|
||||
'html' => $htmlContent,
|
||||
'text' => strip_tags($htmlContent),
|
||||
'attachments' => $attachments
|
||||
];
|
||||
|
||||
// Proses recipients
|
||||
if (is_array($recipients)) {
|
||||
foreach ($recipients as $recipient) {
|
||||
if (is_string($recipient)) {
|
||||
$data['to'][] = ['address' => $recipient, 'name' => ''];
|
||||
} elseif (is_array($recipient)) {
|
||||
$data['to'][] = [
|
||||
'address' => $recipient['address'] ?? $recipient['email'] ?? '',
|
||||
'name' => $recipient['name'] ?? ''
|
||||
];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$data['to'][] = ['address' => $recipients, 'name' => ''];
|
||||
}
|
||||
|
||||
// Tambahkan CC dan BCC dari user jika ada
|
||||
if ($this->user && isset($this->user->email)) {
|
||||
$data['cc'][] = [
|
||||
'address' => $this->user->email,
|
||||
'name' => $this->user->name ?? 'User'
|
||||
];
|
||||
}
|
||||
|
||||
// Kirim email menggunakan PHPMailerService
|
||||
return $this->phpMailerService->sendEmail($data);
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,8 @@ class LaporanAdminKreditExport implements WithColumnFormatting, WithHeadings, Fr
|
||||
$row->nilai_pasar_wajar,
|
||||
$row->nilai_likuidasi,
|
||||
$row->nama_penilai,
|
||||
$row->kolektibilitas,
|
||||
$row->keterangan,
|
||||
$row->created_at
|
||||
];
|
||||
}
|
||||
@@ -52,6 +54,8 @@ class LaporanAdminKreditExport implements WithColumnFormatting, WithHeadings, Fr
|
||||
'Nilai Pasar Wajar',
|
||||
'Nilai Likuidasi',
|
||||
'Nama Penilai',
|
||||
'Kolektibilitas',
|
||||
'Keterangan',
|
||||
'Created At'
|
||||
];
|
||||
}
|
||||
@@ -64,7 +68,9 @@ class LaporanAdminKreditExport implements WithColumnFormatting, WithHeadings, Fr
|
||||
'J' => NumberFormat::FORMAT_DATE_DDMMYYYY,
|
||||
'K' => NumberFormat::FORMAT_NUMBER_COMMA_SEPARATED1,
|
||||
'L' => NumberFormat::FORMAT_NUMBER_COMMA_SEPARATED1,
|
||||
'M' => NumberFormat::FORMAT_DATE_DATETIME,
|
||||
'N' => NumberFormat::FORMAT_TEXT, // Kolektibilitas
|
||||
'O' => NumberFormat::FORMAT_TEXT, // Keterangan
|
||||
'P' => NumberFormat::FORMAT_DATE_DATETIME, // Created At (moved from M to P)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
117
app/Exports/LaporanSlikExport.php
Normal file
117
app/Exports/LaporanSlikExport.php
Normal file
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Exports;
|
||||
|
||||
use Maatwebsite\Excel\Concerns\FromQuery;
|
||||
use Maatwebsite\Excel\Concerns\WithHeadings;
|
||||
use Maatwebsite\Excel\Concerns\WithMapping;
|
||||
use Maatwebsite\Excel\Concerns\WithStyles;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||
|
||||
class LaporanSlikExport implements FromQuery, WithHeadings, WithMapping, WithStyles
|
||||
{
|
||||
protected $query;
|
||||
|
||||
public function __construct($query)
|
||||
{
|
||||
$this->query = $query;
|
||||
}
|
||||
|
||||
public function query()
|
||||
{
|
||||
return $this->query;
|
||||
}
|
||||
|
||||
public function headings(): array
|
||||
{
|
||||
return [
|
||||
'Sandi Bank',
|
||||
'Kode Kantor',
|
||||
'Kode Cabang',
|
||||
'Tahun',
|
||||
'Bulan',
|
||||
'No Rekening',
|
||||
'CIF',
|
||||
'Nama Debitur',
|
||||
'NPWP',
|
||||
'No KTP',
|
||||
'No Telp',
|
||||
'Alamat',
|
||||
'Kode Pos',
|
||||
'Kode Kab/Kota',
|
||||
'Kode Negara Domisili',
|
||||
'Kode Jenis',
|
||||
'Kode Sifat',
|
||||
'Kode Valuta',
|
||||
'Baki Debet',
|
||||
'Kolektibilitas',
|
||||
'Tanggal Mulai',
|
||||
'Tanggal Jatuh Tempo',
|
||||
'Tanggal Selesai',
|
||||
'Tanggal Restrukturisasi',
|
||||
'Kode Sebab Macet',
|
||||
'Tanggal Macet',
|
||||
'Kode Kondisi',
|
||||
'Tanggal Kondisi',
|
||||
'Nilai Agunan',
|
||||
'Jenis Agunan',
|
||||
'Kode Agunan',
|
||||
'Peringkat Agunan',
|
||||
'Fasilitas',
|
||||
'Status Agunan',
|
||||
'Tanggal Lapor',
|
||||
'Status',
|
||||
'Tanggal Dibuat',
|
||||
];
|
||||
}
|
||||
|
||||
public function map($laporanSlik): array
|
||||
{
|
||||
return [
|
||||
$laporanSlik->sandi_bank,
|
||||
$laporanSlik->kode_kantor,
|
||||
$laporanSlik->kode_cabang,
|
||||
$laporanSlik->tahun,
|
||||
$laporanSlik->bulan,
|
||||
$laporanSlik->no_rekening,
|
||||
$laporanSlik->cif,
|
||||
$laporanSlik->nama_debitur,
|
||||
$laporanSlik->npwp,
|
||||
$laporanSlik->no_ktp,
|
||||
$laporanSlik->no_telp,
|
||||
$laporanSlik->alamat,
|
||||
$laporanSlik->kode_pos,
|
||||
$laporanSlik->kode_kab_kota,
|
||||
$laporanSlik->kode_negara_domisili,
|
||||
$laporanSlik->kode_jenis,
|
||||
$laporanSlik->kode_sifat,
|
||||
$laporanSlik->kode_valuta,
|
||||
$laporanSlik->baki_debet,
|
||||
$laporanSlik->kolektibilitas,
|
||||
$laporanSlik->tanggal_mulai,
|
||||
$laporanSlik->tanggal_jatuh_tempo,
|
||||
$laporanSlik->tanggal_selesai,
|
||||
$laporanSlik->tanggal_restrukturisasi,
|
||||
$laporanSlik->kode_sebab_macet,
|
||||
$laporanSlik->tanggal_macet,
|
||||
$laporanSlik->kode_kondisi,
|
||||
$laporanSlik->tanggal_kondisi,
|
||||
$laporanSlik->nilai_agunan,
|
||||
$laporanSlik->jenis_agunan,
|
||||
$laporanSlik->kode_agunan,
|
||||
$laporanSlik->peringkat_agunan,
|
||||
$laporanSlik->fasilitas,
|
||||
$laporanSlik->status_agunan,
|
||||
$laporanSlik->tanggal_lapor,
|
||||
$laporanSlik->status,
|
||||
$laporanSlik->created_at->format('d/m/Y H:i'),
|
||||
];
|
||||
}
|
||||
|
||||
public function styles(Worksheet $sheet)
|
||||
{
|
||||
return [
|
||||
1 => ['font' => ['bold' => true]],
|
||||
];
|
||||
}
|
||||
}
|
||||
232
app/Exports/LaporanUserLimitExport.php
Normal file
232
app/Exports/LaporanUserLimitExport.php
Normal file
@@ -0,0 +1,232 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Exports;
|
||||
|
||||
use Maatwebsite\Excel\Concerns\FromCollection;
|
||||
use Maatwebsite\Excel\Concerns\WithHeadings;
|
||||
use Maatwebsite\Excel\Concerns\WithMapping;
|
||||
use Maatwebsite\Excel\Concerns\WithTitle;
|
||||
use Maatwebsite\Excel\Concerns\WithCustomStartCell;
|
||||
use Maatwebsite\Excel\Concerns\WithEvents;
|
||||
use Maatwebsite\Excel\Events\AfterSheet;
|
||||
use Modules\Lpj\Models\Permohonan;
|
||||
use Modules\Lpj\Models\Branch;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class LaporanUserLimitExport implements FromCollection, WithHeadings, WithMapping, WithTitle, WithCustomStartCell, WithEvents
|
||||
{
|
||||
protected $request;
|
||||
|
||||
public function __construct($request)
|
||||
{
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
public function collection()
|
||||
{
|
||||
$query = Permohonan::query();
|
||||
$query = $query->where('status', 'done');
|
||||
|
||||
// Apply date range filter if provided
|
||||
if ($this->request->has('start_date') || $this->request->has('end_date')) {
|
||||
$startDate = $this->request->start_date ?? '1900-01-01';
|
||||
$endDate = $this->request->end_date ?? now()->toDateString();
|
||||
|
||||
$query->where(function ($q) use ($startDate, $endDate) {
|
||||
|
||||
$q->whereHas('penilaian', function ($q2) use ($startDate, $endDate) {
|
||||
$q2->whereBetween('tanggal_kunjungan', [$startDate, $endDate]);
|
||||
});
|
||||
|
||||
// OR check if has penawaran with date in range
|
||||
$q->orWhereHas('penawaran', function ($q3) use ($startDate, $endDate) {
|
||||
$q3->whereBetween('tanggal_penilaian_sebelumnya', [$startDate, $endDate]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Apply branch filter if provided
|
||||
if ($this->request->has('branch_id') && !empty($this->request->branch_id)) {
|
||||
$query->where('branch_id', $this->request->branch_id);
|
||||
}
|
||||
|
||||
if ($this->request->has('penilai_id') && !empty($this->request->penilai_id)) {
|
||||
$request = $this->request; // Store in a local variable
|
||||
$query->whereHas('penilaian._user_penilai.userPenilaiTeam', function ($q) use ($request) {
|
||||
$q->where('user_id', $request->penilai_id);
|
||||
});
|
||||
}
|
||||
|
||||
// Apply search filter if provided
|
||||
if ($this->request->has('search') && !empty($this->request->search)) {
|
||||
$search = $this->request->search;
|
||||
$query->where(function ($q) use ($search) {
|
||||
$q->where('nomor_registrasi', 'LIKE', '%' . $search . '%');
|
||||
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search . '%');
|
||||
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $search . '%');
|
||||
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search . '%');
|
||||
$q->orWhereRelation('debiture', DB::raw('LOWER(name)'), 'LIKE', '%' . strtolower($search) . '%');
|
||||
|
||||
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search . '%');
|
||||
$q->orWhereRelation('jenisFasilitasKredit', 'name', 'LIKE', '%' . $search . '%');
|
||||
$q->orWhereRelation('jenisPenilaian', 'name', 'LIKE', '%' . $search . '%');
|
||||
$q->orWhere('status', 'LIKE', '%' . $search . '%');
|
||||
});
|
||||
}
|
||||
|
||||
// Default ordering
|
||||
$query->orderBy('nomor_registrasi', 'asc');
|
||||
|
||||
return $query->get();
|
||||
}
|
||||
|
||||
protected $rowNumber = 0;
|
||||
|
||||
public function map($permohonan): array
|
||||
{
|
||||
$this->rowNumber++;
|
||||
$npw = 0;
|
||||
|
||||
if (isset($permohonan->penilai->lpj)) {
|
||||
$lpj = json_decode($permohonan->penilai->lpj, true);
|
||||
$npw = str_replace('.', '', $lpj['total_nilai_pasar_wajar'] ?? 0);
|
||||
}
|
||||
|
||||
return [
|
||||
$this->rowNumber,
|
||||
$permohonan->nomor_registrasi,
|
||||
$permohonan->debiture->branch->name ?? '',
|
||||
$permohonan->debiture->name ?? '',
|
||||
$permohonan->user->name ?? $permohonan->mig_nama_ao ?? '',
|
||||
$permohonan->tanggal_permohonan ?? '',
|
||||
$permohonan->penilaian->_user_penilai->userPenilaiTeam->name ?? '',
|
||||
$permohonan->penilaian && $permohonan->penilaian->tanggal_kunjungan
|
||||
? formatTanggalIndonesia($permohonan->penilaian->tanggal_kunjungan)
|
||||
: '',
|
||||
formatRupiah($npw, 2),
|
||||
];
|
||||
}
|
||||
|
||||
public function headings(): array
|
||||
{
|
||||
return [
|
||||
'No',
|
||||
'Nomor Registrasi',
|
||||
'Cabang',
|
||||
'Nama Debitur',
|
||||
'Pemohon',
|
||||
'Tanggal Permohonan',
|
||||
'Nama Penilai',
|
||||
'Tanggal Laporan',
|
||||
'Nilai Pasar Wajar',
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function title(): string
|
||||
{
|
||||
return 'Laporan User Limit';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function startCell(): string
|
||||
{
|
||||
return 'A7';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function registerEvents(): array
|
||||
{
|
||||
return [
|
||||
AfterSheet::class => function (AfterSheet $event) {
|
||||
// Get the sheet
|
||||
$sheet = $event->sheet->getDelegate();
|
||||
|
||||
// Set the title
|
||||
$sheet->setCellValue('A1', 'LAPORAN PENILAIAN JAMINAN');
|
||||
$sheet->getStyle('A1')->getFont()->setBold(true)->setSize(16);
|
||||
|
||||
// Merge cells for title
|
||||
$sheet->mergeCells('A1:AH1');
|
||||
$sheet->getStyle('A1')->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
|
||||
|
||||
// Set the branch information if filtered
|
||||
$branchInfo = '';
|
||||
if ($this->request->has('branch_id') && !empty($this->request->branch_id)) {
|
||||
$branch = Branch::find($this->request->branch_id);
|
||||
if ($branch) {
|
||||
$branchInfo = 'Cabang: ' . $branch->name;
|
||||
$sheet->setCellValue('A2', $branchInfo);
|
||||
$sheet->mergeCells('A2:AH2');
|
||||
$sheet->getStyle('A2')->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
|
||||
$sheet->getStyle('A2')->getFont()->setBold(true);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the period
|
||||
$startDate = $this->request->start_date ?? '';
|
||||
$endDate = $this->request->end_date ?? '';
|
||||
|
||||
$rowIndex = $branchInfo ? 3 : 2;
|
||||
|
||||
if ($startDate && $endDate) {
|
||||
$startDateFormatted = Carbon::parse($startDate)->format('d F Y');
|
||||
$endDateFormatted = Carbon::parse($endDate)->format('d F Y');
|
||||
$sheet->setCellValue('A' . $rowIndex, 'Periode: ' . $startDateFormatted . ' - ' . $endDateFormatted);
|
||||
} else {
|
||||
$sheet->setCellValue('A' . $rowIndex, 'Periode: Semua Data');
|
||||
}
|
||||
$sheet->mergeCells('A' . $rowIndex . ':AH' . $rowIndex);
|
||||
$sheet->getStyle('A' . $rowIndex)->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
|
||||
|
||||
// Set the date of export
|
||||
$rowIndex++;
|
||||
$sheet->setCellValue('A' . $rowIndex, 'Tanggal Export: ' . Carbon::now()->format('d F Y H:i:s'));
|
||||
|
||||
// Set the user who exported
|
||||
$rowIndex++;
|
||||
$userName = Auth::user() ? Auth::user()->name : 'System';
|
||||
$sheet->setCellValue('A' . $rowIndex, 'Diexport oleh: ' . $userName);
|
||||
|
||||
// Add a blank line
|
||||
$rowIndex++;
|
||||
$sheet->setCellValue('A' . $rowIndex, '');
|
||||
|
||||
// Style the header row
|
||||
$headerRange = 'A7:' . $sheet->getHighestColumn() . '7';
|
||||
$sheet->getStyle($headerRange)->getFont()->setBold(true);
|
||||
$sheet->getStyle($headerRange)->getFill()
|
||||
->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)
|
||||
->getStartColor()->setARGB('FFCCCCCC');
|
||||
|
||||
// Auto-size columns - fixed to handle columns beyond Z
|
||||
$highestColumn = $sheet->getHighestColumn();
|
||||
$highestColumnIndex = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::columnIndexFromString($highestColumn);
|
||||
|
||||
for ($i = 1; $i <= $highestColumnIndex; $i++) {
|
||||
$currentColumn = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($i);
|
||||
$sheet->getColumnDimension($currentColumn)->setAutoSize(true);
|
||||
}
|
||||
|
||||
// Add borders to all cells with data
|
||||
$dataRange = 'A7:' . $sheet->getHighestColumn() . $sheet->getHighestRow();
|
||||
$sheet->getStyle($dataRange)->getBorders()->getAllBorders()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN);
|
||||
|
||||
// Center align the header row
|
||||
$sheet->getStyle($headerRange)->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
|
||||
|
||||
// Set text wrap for header cells
|
||||
$sheet->getStyle($headerRange)->getAlignment()->setWrapText(true);
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@
|
||||
$row->id,
|
||||
$row->code,
|
||||
$row->name,
|
||||
$row->biaya,
|
||||
$row->created_at
|
||||
];
|
||||
}
|
||||
@@ -35,6 +36,7 @@
|
||||
'ID',
|
||||
'Code',
|
||||
'Name',
|
||||
'Biaya',
|
||||
'Created At'
|
||||
];
|
||||
}
|
||||
@@ -44,7 +46,8 @@
|
||||
{
|
||||
return [
|
||||
'A' => NumberFormat::FORMAT_NUMBER,
|
||||
'D' => NumberFormat::FORMAT_DATE_DATETIME
|
||||
'D' => NumberFormat::FORMAT_NUMBER_00,
|
||||
'E' => NumberFormat::FORMAT_DATE_DATETIME
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
128
app/Exports/ReferensiLinkExport.php
Normal file
128
app/Exports/ReferensiLinkExport.php
Normal file
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Exports;
|
||||
|
||||
use Modules\Lpj\app\Models\ReferensiLink;
|
||||
use Maatwebsite\Excel\Concerns\FromQuery;
|
||||
use Maatwebsite\Excel\Concerns\WithHeadings;
|
||||
use Maatwebsite\Excel\Concerns\WithMapping;
|
||||
use Maatwebsite\Excel\Concerns\WithStyles;
|
||||
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
|
||||
use Maatwebsite\Excel\Concerns\WithColumnFormatting;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
|
||||
|
||||
class ReferensiLinkExport implements FromQuery, WithHeadings, WithMapping, WithStyles, ShouldAutoSize, WithColumnFormatting
|
||||
{
|
||||
protected $filters;
|
||||
|
||||
public function __construct($filters = [])
|
||||
{
|
||||
$this->filters = $filters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query data yang akan diexport
|
||||
*/
|
||||
public function query()
|
||||
{
|
||||
$query = ReferensiLink::with(['createdBy', 'updatedBy'])
|
||||
->select('referensi_link.*');
|
||||
|
||||
// Apply filters
|
||||
if (isset($this->filters['kategori']) && !empty($this->filters['kategori'])) {
|
||||
$query->where('kategori', $this->filters['kategori']);
|
||||
}
|
||||
|
||||
if (isset($this->filters['status']) && $this->filters['status'] !== '') {
|
||||
$query->where('is_active', $this->filters['status']);
|
||||
}
|
||||
|
||||
if (isset($this->filters['search']) && !empty($this->filters['search'])) {
|
||||
$query->search($this->filters['search']);
|
||||
}
|
||||
|
||||
return $query->ordered();
|
||||
}
|
||||
|
||||
/**
|
||||
* Header kolom
|
||||
*/
|
||||
public function headings(): array
|
||||
{
|
||||
return [
|
||||
'No',
|
||||
'Nama',
|
||||
'Link',
|
||||
'Kategori',
|
||||
'Deskripsi',
|
||||
'Status Aktif',
|
||||
'Urutan',
|
||||
'Dibuat Oleh',
|
||||
'Diupdate Oleh',
|
||||
'Tanggal Dibuat',
|
||||
'Tanggal Diupdate',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Mapping data untuk setiap baris
|
||||
*/
|
||||
public function map($referensiLink): array
|
||||
{
|
||||
static $rowNumber = 0;
|
||||
$rowNumber++;
|
||||
|
||||
return [
|
||||
$rowNumber,
|
||||
$referensiLink->name,
|
||||
$referensiLink->link,
|
||||
$referensiLink->kategori ?? '-',
|
||||
$referensiLink->deskripsi ?? '-',
|
||||
$referensiLink->is_active ? 'Aktif' : 'Tidak Aktif',
|
||||
$referensiLink->urutan,
|
||||
$referensiLink->createdBy ? $referensiLink->createdBy->name : '-',
|
||||
$referensiLink->updatedBy ? $referensiLink->updatedBy->name : '-',
|
||||
$referensiLink->created_at->format('d-m-Y H:i:s'),
|
||||
$referensiLink->updated_at->format('d-m-Y H:i:s'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Styling untuk worksheet
|
||||
*/
|
||||
public function styles(Worksheet $sheet)
|
||||
{
|
||||
return [
|
||||
// Header styling
|
||||
1 => [
|
||||
'font' => ['bold' => true, 'size' => 12],
|
||||
'fill' => ['fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID, 'startColor' => ['rgb' => 'E2EFDA']],
|
||||
'alignment' => ['horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER],
|
||||
],
|
||||
// Alternating row colors
|
||||
'A2:K1000' => [
|
||||
'fill' => ['fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID, 'startColor' => ['rgb' => 'F8F9FA']],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Format kolom
|
||||
*/
|
||||
public function columnFormats(): array
|
||||
{
|
||||
return [
|
||||
'F' => NumberFormat::FORMAT_DATE_DDMMYYYY, // Tanggal dibuat
|
||||
'G' => NumberFormat::FORMAT_DATE_DDMMYYYY, // Tanggal diupdate
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom title untuk sheet
|
||||
*/
|
||||
public function title(): string
|
||||
{
|
||||
return 'Referensi Link';
|
||||
}
|
||||
}
|
||||
185
app/Exports/SlikExport.php
Normal file
185
app/Exports/SlikExport.php
Normal file
@@ -0,0 +1,185 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Exports;
|
||||
|
||||
use Maatwebsite\Excel\Concerns\FromCollection;
|
||||
use Maatwebsite\Excel\Concerns\WithColumnFormatting;
|
||||
use Maatwebsite\Excel\Concerns\WithHeadings;
|
||||
use Maatwebsite\Excel\Concerns\WithMapping;
|
||||
use Modules\Lpj\Models\Slik;
|
||||
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
|
||||
|
||||
/**
|
||||
* Export class untuk data SLIK (Sistem Layanan Informasi Keuangan)
|
||||
*
|
||||
* Class ini menangani export data SLIK ke format Excel dengan:
|
||||
* - Mapping data sesuai struktur SLIK
|
||||
* - Format kolom yang sesuai (text, number, date)
|
||||
* - Header yang informatif
|
||||
*/
|
||||
class SlikExport implements WithColumnFormatting, WithHeadings, FromCollection, WithMapping
|
||||
{
|
||||
/**
|
||||
* Mengambil collection data SLIK untuk di-export
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function collection()
|
||||
{
|
||||
return Slik::orderBy('created_at', 'desc')->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Mapping data SLIK untuk setiap baris dalam Excel
|
||||
*
|
||||
* @param \Modules\Lpj\Models\Slik $row
|
||||
* @return array
|
||||
*/
|
||||
public function map($row): array
|
||||
{
|
||||
return [
|
||||
$row->id, // A - ID
|
||||
$row->sandi_bank, // B - Sandi Bank
|
||||
$row->tahun, // C - Tahun
|
||||
$row->bulan, // D - Bulan
|
||||
$row->flag_detail, // E - Flag Detail
|
||||
$row->kode_register_agunan, // F - Kode Register Agunan
|
||||
$row->no_rekening, // G - No Rekening
|
||||
$row->cif, // H - CIF
|
||||
$row->kolektibilitas, // I - Kolektibilitas
|
||||
$row->fasilitas, // J - Fasilitas
|
||||
$row->jenis_segmen_fasilitas, // K - Jenis Segmen Fasilitas
|
||||
$row->status_agunan, // L - Status Agunan
|
||||
$row->jenis_agunan, // M - Jenis Agunan
|
||||
$row->peringkat_agunan, // N - Peringkat Agunan
|
||||
$row->lembaga_pemeringkat, // O - Lembaga Pemeringkat
|
||||
$row->jenis_pengikatan, // P - Jenis Pengikatan
|
||||
$row->tanggal_pengikatan, // Q - Tanggal Pengikatan
|
||||
$row->nama_pemilik_agunan, // R - Nama Pemilik Agunan
|
||||
$row->bukti_kepemilikan, // S - Bukti Kepemilikan
|
||||
$row->alamat_agunan, // T - Alamat Agunan
|
||||
$row->lokasi_agunan, // U - Lokasi Agunan
|
||||
$row->nilai_agunan, // V - Nilai Agunan
|
||||
$row->nilai_agunan_menurut_ljk, // W - Nilai Agunan Menurut LJK
|
||||
$row->tanggal_penilaian_ljk, // X - Tanggal Penilaian LJK
|
||||
$row->nilai_agunan_penilai_independen, // Y - Nilai Agunan Penilai Independen
|
||||
$row->nama_penilai_independen, // Z - Nama Penilai Independen
|
||||
$row->tanggal_penilaian_penilai_independen, // AA - Tanggal Penilaian Penilai Independen
|
||||
$row->jumlah_hari_tunggakan, // AB - Jumlah Hari Tunggakan
|
||||
$row->status_paripasu, // AC - Status Paripasu
|
||||
$row->prosentase_paripasu, // AD - Prosentase Paripasu
|
||||
$row->status_kredit_join, // AE - Status Kredit Join
|
||||
$row->diasuransikan, // AF - Diasuransikan
|
||||
$row->keterangan, // AG - Keterangan
|
||||
$row->kantor_cabang, // AH - Kantor Cabang
|
||||
$row->operasi_data, // AI - Operasi Data
|
||||
$row->kode_cabang, // AJ - Kode Cabang
|
||||
$row->nama_debitur, // AK - Nama Debitur
|
||||
$row->nama_cabang, // AL - Nama Cabang
|
||||
$row->flag, // AM - Flag
|
||||
$row->created_at, // AN - Created At
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Header kolom untuk Excel
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function headings(): array
|
||||
{
|
||||
return [
|
||||
'ID',
|
||||
'Sandi Bank',
|
||||
'Tahun',
|
||||
'Bulan',
|
||||
'Flag Detail',
|
||||
'Kode Register Agunan',
|
||||
'No Rekening',
|
||||
'CIF',
|
||||
'Kolektibilitas',
|
||||
'Fasilitas',
|
||||
'Jenis Segmen Fasilitas',
|
||||
'Status Agunan',
|
||||
'Jenis Agunan',
|
||||
'Peringkat Agunan',
|
||||
'Lembaga Pemeringkat',
|
||||
'Jenis Pengikatan',
|
||||
'Tanggal Pengikatan',
|
||||
'Nama Pemilik Agunan',
|
||||
'Bukti Kepemilikan',
|
||||
'Alamat Agunan',
|
||||
'Lokasi Agunan',
|
||||
'Nilai Agunan',
|
||||
'Nilai Agunan Menurut LJK',
|
||||
'Tanggal Penilaian LJK',
|
||||
'Nilai Agunan Penilai Independen',
|
||||
'Nama Penilai Independen',
|
||||
'Tanggal Penilaian Penilai Independen',
|
||||
'Jumlah Hari Tunggakan',
|
||||
'Status Paripasu',
|
||||
'Prosentase Paripasu',
|
||||
'Status Kredit Join',
|
||||
'Diasuransikan',
|
||||
'Keterangan',
|
||||
'Kantor Cabang',
|
||||
'Operasi Data',
|
||||
'Kode Cabang',
|
||||
'Nama Debitur',
|
||||
'Nama Cabang',
|
||||
'Flag',
|
||||
'Created At',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Format kolom untuk Excel
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function columnFormats(): array
|
||||
{
|
||||
return [
|
||||
'A' => NumberFormat::FORMAT_NUMBER, // ID
|
||||
'B' => NumberFormat::FORMAT_TEXT, // Sandi Bank
|
||||
'C' => NumberFormat::FORMAT_TEXT, // Tahun
|
||||
'D' => NumberFormat::FORMAT_TEXT, // Bulan
|
||||
'E' => NumberFormat::FORMAT_TEXT, // Flag Detail
|
||||
'F' => NumberFormat::FORMAT_TEXT, // Kode Register Agunan
|
||||
'G' => NumberFormat::FORMAT_TEXT, // No Rekening
|
||||
'H' => NumberFormat::FORMAT_TEXT, // CIF
|
||||
'I' => NumberFormat::FORMAT_TEXT, // Kolektibilitas
|
||||
'J' => NumberFormat::FORMAT_TEXT, // Fasilitas
|
||||
'K' => NumberFormat::FORMAT_TEXT, // Jenis Segmen Fasilitas
|
||||
'L' => NumberFormat::FORMAT_TEXT, // Status Agunan
|
||||
'M' => NumberFormat::FORMAT_TEXT, // Jenis Agunan
|
||||
'N' => NumberFormat::FORMAT_TEXT, // Peringkat Agunan
|
||||
'O' => NumberFormat::FORMAT_TEXT, // Lembaga Pemeringkat
|
||||
'P' => NumberFormat::FORMAT_TEXT, // Jenis Pengikatan
|
||||
'Q' => NumberFormat::FORMAT_DATE_DDMMYYYY, // Tanggal Pengikatan
|
||||
'R' => NumberFormat::FORMAT_TEXT, // Nama Pemilik Agunan
|
||||
'S' => NumberFormat::FORMAT_TEXT, // Bukti Kepemilikan
|
||||
'T' => NumberFormat::FORMAT_TEXT, // Alamat Agunan
|
||||
'U' => NumberFormat::FORMAT_TEXT, // Lokasi Agunan
|
||||
'V' => NumberFormat::FORMAT_NUMBER_COMMA_SEPARATED1, // Nilai Agunan
|
||||
'W' => NumberFormat::FORMAT_NUMBER_COMMA_SEPARATED1, // Nilai Agunan Menurut LJK
|
||||
'X' => NumberFormat::FORMAT_DATE_DDMMYYYY, // Tanggal Penilaian LJK
|
||||
'Y' => NumberFormat::FORMAT_NUMBER_COMMA_SEPARATED1, // Nilai Agunan Penilai Independen
|
||||
'Z' => NumberFormat::FORMAT_TEXT, // Nama Penilai Independen
|
||||
'AA' => NumberFormat::FORMAT_DATE_DDMMYYYY, // Tanggal Penilaian Penilai Independen
|
||||
'AB' => NumberFormat::FORMAT_NUMBER, // Jumlah Hari Tunggakan
|
||||
'AC' => NumberFormat::FORMAT_TEXT, // Status Paripasu
|
||||
'AD' => NumberFormat::FORMAT_PERCENTAGE_00, // Prosentase Paripasu
|
||||
'AE' => NumberFormat::FORMAT_TEXT, // Status Kredit Join
|
||||
'AF' => NumberFormat::FORMAT_TEXT, // Diasuransikan
|
||||
'AG' => NumberFormat::FORMAT_TEXT, // Keterangan
|
||||
'AH' => NumberFormat::FORMAT_TEXT, // Kantor Cabang
|
||||
'AI' => NumberFormat::FORMAT_TEXT, // Operasi Data
|
||||
'AJ' => NumberFormat::FORMAT_TEXT, // Kode Cabang
|
||||
'AK' => NumberFormat::FORMAT_TEXT, // Nama Debitur
|
||||
'AL' => NumberFormat::FORMAT_TEXT, // Nama Cabang
|
||||
'AM' => NumberFormat::FORMAT_TEXT, // Flag
|
||||
'AN' => NumberFormat::FORMAT_DATE_DATETIME, // Created At
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,10 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Modules\Location\Models\City;
|
||||
use Modules\Location\Models\District;
|
||||
use Modules\Location\Models\Province;
|
||||
@@ -15,35 +18,144 @@
|
||||
use Modules\Lpj\Models\Penilaian;
|
||||
use Modules\Lpj\Models\TeamsUsers;
|
||||
use Modules\Usermanagement\Models\User;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Modules\Lpj\Services\ImageResizeService;
|
||||
|
||||
function formatTanggalIndonesia($date, $time = false)
|
||||
/**
|
||||
* Format tanggal ke dalam format Bahasa Indonesia
|
||||
*
|
||||
* Mengubah tanggal menjadi format yang lebih mudah dibaca dalam Bahasa Indonesia.
|
||||
* Contoh: "15 Januari 2024" atau "15 Januari 2024 pukul 14.30 WIB"
|
||||
*
|
||||
* @param string|mixed $date Tanggal yang akan diformat (string tanggal atau null)
|
||||
* @param bool $time Apakah akan menampilkan waktu juga (default: false)
|
||||
* @return string Tanggal yang sudah diformat dalam Bahasa Indonesia
|
||||
*
|
||||
* @example
|
||||
* formatTanggalIndonesia('2024-01-15') // "15 Januari 2024"
|
||||
* formatTanggalIndonesia('2024-01-15 14:30:00', true) // "15 Januari 2024 pukul 14.30 WIB"
|
||||
* formatTanggalIndonesia(null) // ""
|
||||
* formatTanggalIndonesia('invalid-date') // "invalid-date" (return as-is jika error)
|
||||
*/
|
||||
function formatTanggalIndonesia($date, $time = false): string
|
||||
{
|
||||
Carbon::setLocale('id');
|
||||
try {
|
||||
$waktu = Carbon::parse($date);
|
||||
if (!$time) {
|
||||
return $waktu->translatedFormat('d F Y');
|
||||
}
|
||||
return $waktu->translatedFormat('d F Y') . ' pukul ' . $waktu->format('H.i') . ' WIB';
|
||||
} catch (Throwable $e) {
|
||||
return $date;
|
||||
Log::debug('Memulai format tanggal Indonesia', [
|
||||
'date' => $date,
|
||||
'time' => $time
|
||||
]);
|
||||
|
||||
// Validasi input null atau kosong
|
||||
if (empty($date)) {
|
||||
Log::debug('Tanggal kosong, return empty string');
|
||||
return '';
|
||||
}
|
||||
|
||||
Carbon::setLocale('id');
|
||||
|
||||
try {
|
||||
$waktu = Carbon::parse($date);
|
||||
|
||||
if (!$time) {
|
||||
$result = $waktu->translatedFormat('d F Y');
|
||||
Log::debug('Format tanggal berhasil', ['result' => $result]);
|
||||
return $result;
|
||||
}
|
||||
|
||||
$result = $waktu->translatedFormat('d F Y') . ' pukul ' . $waktu->format('H.i') . ' WIB';
|
||||
Log::debug('Format tanggal dengan waktu berhasil', ['result' => $result]);
|
||||
return $result;
|
||||
|
||||
} catch (Throwable $e) {
|
||||
Log::warning('Gagal parse tanggal', [
|
||||
'date' => $date,
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
// Return input as-is jika gagal parse
|
||||
return (string) $date;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function formatRupiah($number, $decimals = 0)
|
||||
/**
|
||||
* Format angka ke dalam format mata uang Rupiah Indonesia
|
||||
*
|
||||
* Mengubah angka menjadi format mata uang Rupiah dengan pemisah ribuan
|
||||
* dan menggunakan koma sebagai pemisah desimal sesuai standar Indonesia.
|
||||
*
|
||||
* @param int|float|string $number Angka yang akan diformat (bisa negatif)
|
||||
* @param int $decimals Jumlah digit desimal (default: 0)
|
||||
* @return string Angka yang sudah diformat dalam format Rupiah
|
||||
*
|
||||
* @example
|
||||
* formatRupiah(1500000) // "Rp 1.500.000"
|
||||
* formatRupiah(1500000.50, 2) // "Rp 1.500.000,50"
|
||||
* formatRupiah(-500000) // "Rp -500.000"
|
||||
* formatRupiah(0) // "Rp 0"
|
||||
* formatRupiah(null) // "Rp 0"
|
||||
*/
|
||||
function formatRupiah($number, $decimals = 0, $withSymbol = true): string
|
||||
{
|
||||
$number = (float) $number;
|
||||
return 'Rp ' . number_format($number, $decimals, ',', '.');
|
||||
}
|
||||
Log::debug('Memulai format Rupiah', [
|
||||
'number' => $number,
|
||||
'decimals' => $decimals,
|
||||
'withSymbol' => $withSymbol
|
||||
]);
|
||||
|
||||
// Handle null atau kosong
|
||||
if ($number === null || $number === '') {
|
||||
Log::debug('Number null atau kosong, return Rp 0');
|
||||
return $withSymbol ? 'Rp 0' : '0';
|
||||
}
|
||||
|
||||
// Remove dots if present
|
||||
$number = str_replace('.', '', (string) $number);
|
||||
|
||||
// Konversi ke float dan handle error
|
||||
try {
|
||||
$number = (float) $number;
|
||||
} catch (Throwable $e) {
|
||||
Log::warning('Gagal konversi number ke float', [
|
||||
'number' => $number,
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
return $withSymbol ? 'Rp 0' : '0';
|
||||
}
|
||||
|
||||
// Validasi decimals
|
||||
$decimals = max(0, (int) $decimals);
|
||||
|
||||
$formatted = number_format($number, $decimals, ',', '.');
|
||||
$result = $withSymbol ? 'Rp ' . $formatted : $formatted;
|
||||
Log::debug('Format Rupiah berhasil', ['result' => $result]);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
function formatAlamat($alamat)
|
||||
{
|
||||
return ($alamat->address ? $alamat->address . ', ' : '') . (isset($alamat->village) ? $alamat->village->name . ', ' : '') . (isset($alamat->city) ? $alamat->city->name . ', ' : '') . (isset($alamat->province) ? $alamat->province->name . ', ' : '') . ($alamat->village->postal_code ?? '');
|
||||
}
|
||||
|
||||
function formatAlamatbyCode($alamat)
|
||||
{
|
||||
return ($alamat->address ? $alamat->address . ', ' : '') . (isset($alamat->village_code) ? getVillage($alamat->village_code)->name . ', ' : '') . (isset($alamat->city_code) ? getCity($alamat->city_code)->name . ', ' : '') . (isset($alamat->province_code) ? getProvince($alamat->province_code)->name . ', ' : '') . (getVillage($alamat->village_code)->postal_code ?? '');
|
||||
}
|
||||
|
||||
function getVillage($village)
|
||||
{
|
||||
return Village::where('code', $village)->first();
|
||||
}
|
||||
|
||||
function getCity($city)
|
||||
{
|
||||
return City::where('code', $city)->first();
|
||||
}
|
||||
|
||||
function getProvince($province)
|
||||
{
|
||||
return Province::where('code', $province)->first();
|
||||
}
|
||||
|
||||
// andy add
|
||||
function checkActiveDateRangePenawaran($id)
|
||||
{
|
||||
@@ -51,7 +163,7 @@
|
||||
|
||||
$start_date = strtotime($penawaran->start_date);
|
||||
$end_date = strtotime($penawaran->end_date);
|
||||
$todays_date = strtotime(now());
|
||||
$todays_date = Carbon::now()->getTimestamp();
|
||||
//$todays_date = strtotime("+1 day", strtotime(now()));
|
||||
|
||||
$allow = true;
|
||||
@@ -96,8 +208,6 @@
|
||||
$query->orWhereNull('dokumen_persetujuan');
|
||||
},
|
||||
)->get();
|
||||
// $sql = DB::getQueryLog();
|
||||
|
||||
|
||||
if (sizeof($query) > 0) {
|
||||
$allow = false;
|
||||
@@ -238,9 +348,6 @@
|
||||
return $hasil;
|
||||
}
|
||||
|
||||
// andy add
|
||||
|
||||
|
||||
function hitungHariKerja($tanggalMulai, $tanggalSelesai)
|
||||
{
|
||||
$tanggalMulai = Carbon::parse($tanggalMulai)->startOfDay();
|
||||
@@ -326,7 +433,8 @@
|
||||
$day = str_pad(date('d'), 2, '0', STR_PAD_LEFT);
|
||||
|
||||
// Generate random numbers
|
||||
$randomNumber = str_pad(mt_rand(0, pow(10, $randomLength) - 1), $randomLength, '0', STR_PAD_LEFT);
|
||||
//$randomNumber = str_pad(mt_rand(0, pow(10, $randomLength) - 1), $randomLength, '0', STR_PAD_LEFT);
|
||||
$randomNumber = sprintf('%0' . $randomLength . 'd', mt_rand(0, pow(10, $randomLength) - 1));
|
||||
|
||||
// Concatenate components to create the custom code
|
||||
return $year . $month . $day . $randomNumber;
|
||||
@@ -530,15 +638,178 @@
|
||||
}
|
||||
}
|
||||
|
||||
function formatNotifikasi($notifikasi)
|
||||
{
|
||||
$data = json_decode(json_encode($notifikasi->data));
|
||||
$message = $data->message;
|
||||
$data = $data->data;
|
||||
$notifikasi = [
|
||||
'title' => 'Permohonan : ' . $data->nomor_registrasi,
|
||||
'message' => $message,
|
||||
];
|
||||
return $notifikasi;
|
||||
function parsePembandingMigration($keterangan) {
|
||||
$keterangan = preg_replace('/[-]{5,}/', '',$keterangan); // Hapus ------
|
||||
$keterangan = preg_replace('/[.]{5,}/', '',$keterangan); // Hapus .....
|
||||
|
||||
$keterangan = preg_replace('/\s+/', ' ',$keterangan);
|
||||
$keterangan = preg_replace('/\s*\n\s*/', "\n",$keterangan);
|
||||
|
||||
// Pecah teks per baris untuk diproses
|
||||
$lines = explode("\n",$keterangan);
|
||||
$cleaned = [];
|
||||
|
||||
foreach ($lines as $line) {
|
||||
$line = trim($line);
|
||||
if (!empty($line)) {
|
||||
// Format angka dalam format Rp. 123.456.789
|
||||
$line = preg_replace_callback('/Rp\.\s*([\d.,]+)/', function($matches) {
|
||||
$angka = str_replace(['.', ','], '', $matches[1]);
|
||||
return 'Rp. ' . number_format((int)$angka, 0, ',', '.');
|
||||
}, $line);
|
||||
|
||||
// Jika ada tanda pagar (#), pisahkan menjadi baris baru
|
||||
$line = str_replace('#', "\n#", $line);
|
||||
|
||||
$cleaned[] = $line;
|
||||
}
|
||||
}
|
||||
|
||||
return implode("\n", $cleaned);
|
||||
}
|
||||
|
||||
/**
|
||||
* get full path to internal storage file or external storage file
|
||||
*
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
|
||||
function getFilePath($path)
|
||||
{
|
||||
// define base path external storage (use .env) example: 'F:\path\to\storage' in windows
|
||||
$externalBase = env('EXTERNAL_STORAGE_BASE_PATH', 'F:LPJ/lpj/LPJ Gambar/001/');
|
||||
|
||||
$segments = explode('/', $path);
|
||||
|
||||
if(strtoupper($segments[0]) === 'SURVEYOR'){
|
||||
$year = $segments[1];
|
||||
$month = ucfirst(strtolower($segments[2]));
|
||||
$date = $segments[3];
|
||||
$code = $segments[4];
|
||||
$file = $segments[5] ?? '';
|
||||
|
||||
$extenalFullpath = $externalBase . $year . '/' . $month . '/' . $date . '/' . $code . '/' . $file;
|
||||
|
||||
if(File::exists($extenalFullpath)){
|
||||
return $extenalFullpath;
|
||||
}
|
||||
}
|
||||
|
||||
// if not found in external storage, try to find in internal storage
|
||||
if (Storage::exists($path)) {
|
||||
return Storage::url('app/' . $path);
|
||||
}
|
||||
return $path;
|
||||
}
|
||||
|
||||
|
||||
function parseTimestamp(?string $timestamp): ?string
|
||||
{
|
||||
if (!$timestamp) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Trim whitespace dan normalize
|
||||
$timestamp = trim($timestamp);
|
||||
|
||||
// Log untuk debugging
|
||||
Log::info('Mencoba parsing timestamp: "' . $timestamp . '"');
|
||||
|
||||
// Parsing dengan DateTime native PHP untuk lebih robust
|
||||
try {
|
||||
// Pattern untuk format d/m/Y H:i:s
|
||||
if (preg_match('/^(\d{1,2})\/(\d{1,2})\/(\d{4})\s+(\d{1,2}):(\d{1,2}):(\d{1,2})$/', $timestamp, $matches)) {
|
||||
$day = (int) $matches[1];
|
||||
$month = (int) $matches[2];
|
||||
$year = (int) $matches[3];
|
||||
$hour = (int) $matches[4];
|
||||
$minute = (int) $matches[5];
|
||||
$second = (int) $matches[6];
|
||||
|
||||
// Validasi nilai
|
||||
if ($day >= 1 && $day <= 31 && $month >= 1 && $month <= 12 && $year >= 1900 && $year <= 2100 &&
|
||||
$hour >= 0 && $hour <= 23 && $minute >= 0 && $minute <= 59 && $second >= 0 && $second <= 59) {
|
||||
|
||||
// Buat DateTime object langsung
|
||||
$dateTime = new \DateTime();
|
||||
$dateTime->setDate($year, $month, $day);
|
||||
$dateTime->setTime($hour, $minute, $second);
|
||||
|
||||
$result = $dateTime->format('Y-m-d H:i:s');
|
||||
Log::info('Berhasil parsing dengan DateTime: ' . $timestamp . ' -> ' . $result);
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
// Pattern untuk format d/m/Y tanpa waktu
|
||||
if (preg_match('/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/', $timestamp, $matches)) {
|
||||
$day = (int) $matches[1];
|
||||
$month = (int) $matches[2];
|
||||
$year = (int) $matches[3];
|
||||
|
||||
// Validasi nilai
|
||||
if ($day >= 1 && $day <= 31 && $month >= 1 && $month <= 12 && $year >= 1900 && $year <= 2100) {
|
||||
|
||||
// Buat DateTime object langsung
|
||||
$dateTime = new \DateTime();
|
||||
$dateTime->setDate($year, $month, $day);
|
||||
$dateTime->setTime(0, 0, 0);
|
||||
|
||||
$result = $dateTime->format('Y-m-d H:i:s');
|
||||
Log::info('Berhasil parsing tanpa waktu dengan DateTime: ' . $timestamp . ' -> ' . $result);
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Gagal parsing dengan DateTime: ' . $timestamp . '. Error: ' . $e->getMessage());
|
||||
}
|
||||
|
||||
// Fallback ke format Carbon standar untuk format lainnya
|
||||
$formats = [
|
||||
'Y-m-d H:i:s',
|
||||
'Y-m-d',
|
||||
'd-m-Y H:i:s',
|
||||
'd-m-Y',
|
||||
'j-n-Y H:i:s',
|
||||
'j-n-Y',
|
||||
];
|
||||
|
||||
foreach ($formats as $format) {
|
||||
try {
|
||||
$carbon = \Carbon\Carbon::createFromFormat($format, $timestamp);
|
||||
|
||||
if ($carbon && $carbon->format($format) === $timestamp) {
|
||||
// Jika format tidak mengandung waktu, set ke awal hari
|
||||
if (!str_contains($format, 'H:i:s')) {
|
||||
$carbon = $carbon->startOfDay();
|
||||
}
|
||||
Log::info('Berhasil parsing dengan format ' . $format . ': ' . $timestamp . ' -> ' . $carbon->toDateTimeString());
|
||||
return $carbon->toDateTimeString();
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
// Lanjut ke format berikutnya
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
Log::error('Tidak dapat memparsing timestamp dengan format apapun: "' . $timestamp . '"');
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!function_exists('resize_image')) {
|
||||
/**
|
||||
* Merubah ukuran gambar secara on-the-fly dan mengembalikan path-nya.
|
||||
*
|
||||
* @param string $path Path asli gambar.
|
||||
* @param int|null $width Lebar yang diinginkan.
|
||||
* @param int|null $height Tinggi yang diinginkan (opsional, akan menjaga rasio aspek jika null).
|
||||
* @param int $quality Kualitas gambar (1-100).
|
||||
* @return string Path gambar yang sudah di-resize.
|
||||
*/
|
||||
function resize_image(string $path, ?int $width, ?int $height = null, int $quality = 80): string
|
||||
{
|
||||
|
||||
return app(ImageResizeService::class)->resize($path, $width, $height, $quality);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ class ActivityController extends Controller
|
||||
->when($teamId, fn ($q) => $q->where('id', $teamId));
|
||||
})
|
||||
->where('user_id', '!=', $user->id)
|
||||
->whereHas('user.roles', fn ($q) => $q->whereIn('name', ['surveyor', 'surveyor-penilai']))
|
||||
->whereHas('user.roles', fn ($q) => $q->whereIn('name', ['surveyor', 'surveyor-penilai','penilai']))
|
||||
->get();
|
||||
|
||||
$teamId = is_array($teamId) ? $teamId : [$teamId];
|
||||
@@ -306,6 +306,7 @@ class ActivityController extends Controller
|
||||
$query = Permohonan::query();
|
||||
|
||||
// Apply search filter if provided
|
||||
$query = $query->orderBy('nomor_registrasi', 'desc');
|
||||
if ($request->has('search') && !empty($request->get('search'))) {
|
||||
$search = $request->get('search');
|
||||
$query->where(function ($q) use ($search) {
|
||||
@@ -324,7 +325,9 @@ class ActivityController extends Controller
|
||||
});
|
||||
}
|
||||
|
||||
// Default sorting if no sort provided
|
||||
|
||||
|
||||
// Apply sorting if provided
|
||||
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
|
||||
$order = $request->get('sortOrder');
|
||||
$column = $request->get('sortField');
|
||||
|
||||
183
app/Http/Controllers/Api/DebiturController.php
Normal file
183
app/Http/Controllers/Api/DebiturController.php
Normal file
@@ -0,0 +1,183 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Exception;
|
||||
use Modules\Lpj\Models\Debiture;
|
||||
|
||||
/**
|
||||
* Controller untuk API pencarian debitur
|
||||
* Digunakan untuk autocomplete search pada form pembayaran
|
||||
*/
|
||||
class DebiturController extends Controller
|
||||
{
|
||||
/**
|
||||
* Pencarian debitur untuk autocomplete
|
||||
*
|
||||
* @param Request $request
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function search(Request $request): JsonResponse
|
||||
{
|
||||
try {
|
||||
// Log aktivitas pencarian
|
||||
Log::info('API Debitur Search - Request', [
|
||||
'query' => $request->get('q'),
|
||||
'user_id' => Auth::id()
|
||||
]);
|
||||
|
||||
$query = $request->get('q', '');
|
||||
|
||||
// Validasi minimal 2 karakter untuk pencarian
|
||||
if (strlen($query) < 2) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Minimal 2 karakter untuk pencarian',
|
||||
'data' => []
|
||||
], 400);
|
||||
}
|
||||
|
||||
// Mulai database transaction
|
||||
DB::beginTransaction();
|
||||
|
||||
try {
|
||||
// Query pencarian debitur
|
||||
// Asumsi tabel debitur dengan kolom: id, code, nama, alamat
|
||||
$debiturs = Debiture::query()
|
||||
->select('id', 'cif', 'name', 'address')
|
||||
->whereAny(['cif','name'], 'LIKE', "%{$query}%")
|
||||
->orderBy('name', 'asc')
|
||||
->limit(20) // Batasi hasil maksimal 20
|
||||
->get();
|
||||
|
||||
// Format data untuk TomSelect
|
||||
$formattedData = $debiturs->map(function($debitur) {
|
||||
return [
|
||||
'id' => $debitur->id,
|
||||
'kode_debitur' => $debitur->cif,
|
||||
'name' => $debitur->name,
|
||||
'address' => $debitur->address
|
||||
];
|
||||
});
|
||||
|
||||
DB::commit();
|
||||
|
||||
// Log hasil pencarian
|
||||
Log::info('API Debitur Search - Success', [
|
||||
'query' => $query,
|
||||
'results_count' => $formattedData->count(),
|
||||
'user_id' => Auth::id()
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Data debitur berhasil ditemukan',
|
||||
'data' => $formattedData
|
||||
]);
|
||||
|
||||
} catch (Exception $e) {
|
||||
DB::rollback();
|
||||
throw $e;
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
// Log error
|
||||
Log::error('API Debitur Search - Error', [
|
||||
'query' => $request->get('q'),
|
||||
'error' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString(),
|
||||
'user_id' => Auth::id()
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Terjadi kesalahan saat mencari data debitur',
|
||||
'error' => config('app.debug') ? $e->getMessage() : 'Internal Server Error'
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get detail debitur berdasarkan code
|
||||
*
|
||||
* @param Request $request
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function getByCode(Request $request): JsonResponse
|
||||
{
|
||||
try {
|
||||
$code = $request->get('code');
|
||||
|
||||
if (empty($code)) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Code debitur harus diisi',
|
||||
'data' => null
|
||||
], 400);
|
||||
}
|
||||
|
||||
// Log aktivitas get detail
|
||||
Log::info('API Debitur GetByCode - Request', [
|
||||
'code' => $code,
|
||||
'user_id' => Auth::id()
|
||||
]);
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
try {
|
||||
$debitur = DB::table('debitur')
|
||||
->select('id', 'code', 'nama', 'alamat', 'telepon', 'email')
|
||||
->where('code', $code)
|
||||
->where('status', 'aktif')
|
||||
->first();
|
||||
|
||||
if (!$debitur) {
|
||||
DB::rollback();
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Debitur tidak ditemukan',
|
||||
'data' => null
|
||||
], 404);
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
|
||||
Log::info('API Debitur GetByCode - Success', [
|
||||
'code' => $code,
|
||||
'debitur_id' => $debitur->id,
|
||||
'user_id' => Auth::id()
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Data debitur berhasil ditemukan',
|
||||
'data' => $debitur
|
||||
]);
|
||||
|
||||
} catch (Exception $e) {
|
||||
DB::rollback();
|
||||
throw $e;
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
Log::error('API Debitur GetByCode - Error', [
|
||||
'code' => $request->get('code'),
|
||||
'error' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString(),
|
||||
'user_id' => Auth::id()
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Terjadi kesalahan saat mengambil data debitur',
|
||||
'error' => config('app.debug') ? $e->getMessage() : 'Internal Server Error'
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,8 @@
|
||||
namespace Modules\Lpj\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Log;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Modules\Location\Models\Province;
|
||||
use Modules\Lpj\Http\Requests\BankDataRequest;
|
||||
use Modules\Lpj\Models\BankData;
|
||||
@@ -88,7 +88,8 @@
|
||||
}
|
||||
} else {
|
||||
// Invalid coordinates
|
||||
Log::warning("Invalid coordinates: Lat: $_lat, Lng: $_lng");// Do something to handle this situation, such as logging an error or skipping the record
|
||||
Log::warning("Invalid coordinates: Lat: $_lat, Lng: $_lng");
|
||||
// Do something to handle this situation, such as logging an error or skipping the record
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,7 +139,8 @@
|
||||
}
|
||||
} else {
|
||||
// Invalid coordinates
|
||||
Log::warning("Invalid coordinates: Lat: $lat, Lng: $lng");// Do something to handle this situation, such as logging an error or skipping the record
|
||||
Log::warning("Invalid coordinates: Lat: $lat, Lng: $lng");
|
||||
// Do something to handle this situation, such as logging an error or skipping the record
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -197,6 +199,24 @@
|
||||
// Retrieve data from the database
|
||||
$query = BankData::query();
|
||||
|
||||
// Check if show_all parameter is set
|
||||
$showAll = $request->has('show_all') && $request->get('show_all') === 'true';
|
||||
|
||||
// If show_all is true, we'll get all data without pagination
|
||||
if ($showAll) {
|
||||
// Get all records without pagination
|
||||
$data = $query->get();
|
||||
|
||||
return response()->json([
|
||||
'data' => $data,
|
||||
'recordsTotal' => $data->count(),
|
||||
'recordsFiltered' => $data->count(),
|
||||
'page' => 1,
|
||||
'pageSize' => $data->count(),
|
||||
'total' => 1
|
||||
]);
|
||||
}
|
||||
|
||||
// Apply search filter if provided
|
||||
if ($request->has('search') && !empty($request->get('search'))) {
|
||||
$search = $request->get('search');
|
||||
@@ -252,8 +272,10 @@
|
||||
// Get the total count of records
|
||||
$totalRecords = $query->count();
|
||||
|
||||
// Apply pagination if provided
|
||||
if ($request->has('page') && $request->has('size')) {
|
||||
// Apply pagination only if explicitly requested or not first load
|
||||
$shouldPaginate = $request->has('page') && $request->has('size') && !$request->has('show_all');
|
||||
|
||||
if ($shouldPaginate) {
|
||||
$page = $request->get('page');
|
||||
$size = $request->get('size');
|
||||
$offset = ($page - 1) * $size; // Calculate the offset
|
||||
@@ -287,11 +309,11 @@
|
||||
];
|
||||
});
|
||||
|
||||
// Calculate the page count
|
||||
$pageCount = ceil($totalRecords / $request->get('size'));
|
||||
// Calculate the page count (1 if showing all data)
|
||||
$pageCount = $shouldPaginate ? ceil($totalRecords / $request->get('size')) : 1;
|
||||
|
||||
// Calculate the current page number
|
||||
$currentPage = $request->get('page', 1);
|
||||
$currentPage = $shouldPaginate ? $request->get('page', 1) : 1;
|
||||
|
||||
// Ensure current page doesn't exceed page count
|
||||
$currentPage = min($currentPage, $pageCount);
|
||||
|
||||
209
app/Http/Controllers/BucokController.php
Normal file
209
app/Http/Controllers/BucokController.php
Normal file
@@ -0,0 +1,209 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Exception;
|
||||
use Illuminate\Http\Request;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
use Modules\Lpj\Imports\BucokImport;
|
||||
use Modules\Lpj\Models\Bucok;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Controller untuk mengelola data Bucok
|
||||
*
|
||||
* @package Modules\Lpj\Http\Controllers
|
||||
*/
|
||||
class BucokController extends Controller
|
||||
{
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* Menampilkan halaman index bucok
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return view('lpj::bucok.index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Menampilkan detail bucok
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function show($id)
|
||||
{
|
||||
$bucok = Bucok::findOrFail($id);
|
||||
return view('lpj::bucok.show', compact('bucok'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data untuk datatables dengan server-side processing
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function dataForDatatables(Request $request)
|
||||
{
|
||||
if (is_null($this->user) || !$this->user->can('bucok.view')) {
|
||||
// abort(403, 'Sorry! You are not allowed to view bucok.');
|
||||
}
|
||||
|
||||
// Retrieve data from the database
|
||||
$query = Bucok::query();
|
||||
|
||||
// Apply search filter if provided
|
||||
if ($request->has('search') && !empty($request->get('search'))) {
|
||||
$search = $request->get('search');
|
||||
$query->where(function ($q) use ($search) {
|
||||
$q->where('nomor_tiket', 'LIKE', "%$search%")
|
||||
->orWhere('deskripsi', 'LIKE', "%$search%")
|
||||
->orWhere('nomor_coa', 'LIKE', "%$search%")
|
||||
->orWhere('nama_coa', 'LIKE', "%$search%")
|
||||
->orWhere('cost_center', 'LIKE', "%$search%")
|
||||
->orWhere('nama_sub_direktorat', 'LIKE', "%$search%")
|
||||
->orWhere('nama_direktorat_cabang', 'LIKE', "%$search%")
|
||||
->orWhere('penyelesaian', 'LIKE', "%$search%")
|
||||
->orWhere('keterangan_gantung', 'LIKE', "%$search%");
|
||||
});
|
||||
}
|
||||
|
||||
// Apply date range filter
|
||||
if ($request->has('start_date') && !empty($request->get('start_date'))) {
|
||||
$query->whereDate('tanggal', '>=', $request->get('start_date'));
|
||||
}
|
||||
if ($request->has('end_date') && !empty($request->get('end_date'))) {
|
||||
$query->whereDate('tanggal', '<=', $request->get('end_date'));
|
||||
}
|
||||
|
||||
// Apply year filter
|
||||
if ($request->has('year') && !empty($request->get('year'))) {
|
||||
$query->byYear($request->get('year'));
|
||||
}
|
||||
|
||||
// Apply month filter
|
||||
if ($request->has('month') && !empty($request->get('month'))) {
|
||||
$query->byMonth($request->get('month'));
|
||||
}
|
||||
|
||||
// Apply cost center filter
|
||||
if ($request->has('cost_center') && !empty($request->get('cost_center'))) {
|
||||
$query->byCostCenter($request->get('cost_center'));
|
||||
}
|
||||
|
||||
// Apply completion status filter
|
||||
if ($request->has('completion_status') && $request->get('completion_status') !== '') {
|
||||
$isCompleted = $request->get('completion_status') == '1';
|
||||
$query->byCompletionStatus($isCompleted);
|
||||
}
|
||||
|
||||
// Apply sorting if provided
|
||||
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
|
||||
$order = $request->get('sortOrder');
|
||||
$column = $request->get('sortField', 'created_at');
|
||||
$query->orderBy($column, $order);
|
||||
} else {
|
||||
$query->orderBy('created_at', 'desc');
|
||||
}
|
||||
|
||||
// Get the total count of records
|
||||
$totalRecords = $query->count();
|
||||
|
||||
// Apply pagination if provided
|
||||
if ($request->has('page') && $request->has('size')) {
|
||||
$page = $request->get('page');
|
||||
$size = $request->get('size');
|
||||
$offset = ($page - 1) * $size; // Calculate the offset
|
||||
|
||||
$query->skip($offset)->take($size);
|
||||
}
|
||||
|
||||
// Get the filtered count of records
|
||||
$filteredRecords = $query->count();
|
||||
|
||||
// Get the data for the current page with relationships
|
||||
$data = $query->get();
|
||||
|
||||
// Transform data untuk datatables
|
||||
$transformedData = $data->map(function ($item) {
|
||||
return [
|
||||
'id' => $item->id,
|
||||
'no' => $item->no,
|
||||
'tanggal' => $item->tanggal ? dateFormat($item->tanggal,true) : '-',
|
||||
'bulan' => $item->bulan,
|
||||
'tahun' => $item->tahun,
|
||||
'nomor_tiket' => $item->nomor_tiket,
|
||||
'nomor_coa' => $item->nomor_coa,
|
||||
'nama_coa' => $item->nama_coa,
|
||||
'deskripsi' => $item->deskripsi,
|
||||
'nominal' => $item->nominal_formatted,
|
||||
'penyelesaian' => $item->penyelesaian,
|
||||
'umur_aging' => $item->umur_aging,
|
||||
'cost_center' => $item->cost_center,
|
||||
'nama_sub_direktorat' => $item->nama_sub_direktorat,
|
||||
'nama_direktorat_cabang' => $item->nama_direktorat_cabang,
|
||||
'tanggal_penyelesaian' => $item->tanggal_penyelesaian ? dateFormat($item->tanggal_penyelesaian,true) : '-',
|
||||
'nominal_penyelesaian' => $item->nominal_penyelesaian_formatted,
|
||||
'status_penyelesaian' => $item->status_penyelesaian,
|
||||
'status_badge' => $item->status_badge,
|
||||
'created_by' => $item->creator?->name ?? '-',
|
||||
'created_at' => dateFormat($item->created_at,true)
|
||||
];
|
||||
});
|
||||
|
||||
// Calculate the page count
|
||||
$pageCount = ceil($totalRecords / ($request->get('size', 10)));
|
||||
|
||||
// Calculate the current page number
|
||||
$currentPage = $request->get('page', 1);
|
||||
|
||||
// Return the response data as a JSON object
|
||||
return response()->json([
|
||||
'draw' => $request->get('draw'),
|
||||
'recordsTotal' => $totalRecords,
|
||||
'recordsFiltered' => $filteredRecords,
|
||||
'pageCount' => $pageCount,
|
||||
'page' => $currentPage,
|
||||
'totalCount' => $totalRecords,
|
||||
'data' => $transformedData,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Import data bucok dari Excel
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function import(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'file' => 'required|mimes:xlsx,xls,csv|max:10240' // Max 10MB
|
||||
]);
|
||||
|
||||
DB::beginTransaction();
|
||||
try {
|
||||
Log::info('Importing Bucok data', ['user_id' => Auth::id(), 'filename' => $request->file('file')->getClientOriginalName()]);
|
||||
|
||||
$import = new BucokImport();
|
||||
Excel::import($import, $request->file('file'));
|
||||
$statistics = $import->getImportStatistics();
|
||||
|
||||
DB::commit();
|
||||
Log::info('Bucok data imported successfully', ['user_id' => Auth::id()]);
|
||||
|
||||
return redirect()->back()->with('success', 'Data Bucok berhasil diimport. Total: ' . $statistics['total_processed'] . ', Created: ' . $statistics['created'] . ', Updated: ' . $statistics['updated'] . ', Skipped: ' . $statistics['skipped'] . ', Errors: ' . $statistics['errors']);
|
||||
} catch (Exception $e) {
|
||||
DB::rollback();
|
||||
Log::error('Failed to import Bucok data', ['error' => $e->getMessage(), 'user_id' => Auth::id()]);
|
||||
|
||||
return redirect()->back()->with('error', 'Gagal import data: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
152
app/Http/Controllers/CategoryDaftarPustakaController.php
Normal file
152
app/Http/Controllers/CategoryDaftarPustakaController.php
Normal file
@@ -0,0 +1,152 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Modules\Lpj\Models\CategoryDaftarPustaka;
|
||||
use Modules\Lpj\Http\Requests\CategoryDaftarPustakaRequest;
|
||||
|
||||
class CategoryDaftarPustakaController extends Controller
|
||||
{
|
||||
public $user;
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return view('lpj::category-daftar-pustaka.index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
return view('lpj::category-daftar-pustaka.create');
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*/
|
||||
public function store(CategoryDaftarPustakaRequest $request)
|
||||
{
|
||||
$validated = $request->validated();
|
||||
if ($validated) {
|
||||
try {
|
||||
CategoryDaftarPustaka::create($validated);
|
||||
return redirect()->route('category-daftar-pustaka.index')->with('success', 'Data Berhasil Disimpan');
|
||||
} catch (\Throwable $th) {
|
||||
return redirect()->route('category-daftar-pustaka.index')->with('error', $th->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the specified resource.
|
||||
*/
|
||||
public function show($id)
|
||||
{
|
||||
$category = CategoryDaftarPustaka::where('id', $id)->first();
|
||||
return view('lpj::category-daftar-pustaka.show', compact('category'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*/
|
||||
public function edit($id)
|
||||
{
|
||||
return view('lpj::category-daftar-pustaka.create', ['category' => CategoryDaftarPustaka::where('id', $id)->first()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*/
|
||||
public function update(CategoryDaftarPustakaRequest $request, $id)
|
||||
{
|
||||
$validated = $request->validated();
|
||||
if ($validated) {
|
||||
try {
|
||||
CategoryDaftarPustaka::where('id', $id)->update($validated);
|
||||
return redirect()->route('category-daftar-pustaka.index')->with('success', 'Data Berhasil Disimpan');
|
||||
} catch (\Throwable $th) {
|
||||
return redirect()->route('category-daftar-pustaka.index')->with('error', $th->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*/
|
||||
public function destroy($id)
|
||||
{
|
||||
try {
|
||||
CategoryDaftarPustaka::where('id', $id)->delete();
|
||||
return response()->json(['success' => true, 'message' => 'Data Berhasil Dihapus']);
|
||||
} catch (\Throwable $th) {
|
||||
return response()->json(['success' => false, 'message' => $th->getMessage()]);
|
||||
}
|
||||
}
|
||||
|
||||
public function dataForDatatables(Request $request)
|
||||
{
|
||||
if (is_null($this->user) || !$this->user->can('jenis_aset.view')) {
|
||||
//abort(403, 'Sorry! You are not allowed to view users.');
|
||||
}
|
||||
|
||||
// Retrieve data from the database
|
||||
$query = CategoryDaftarPustaka::query();
|
||||
|
||||
// Apply search filter if provided
|
||||
if ($request->has('search') && !empty($request->get('search'))) {
|
||||
$search = $request->get('search');
|
||||
$query->where(function ($q) use ($search) {
|
||||
$q->where('code', 'LIKE', "%$search%");
|
||||
$q->orWhere('name', 'LIKE', "%$search%");
|
||||
});
|
||||
}
|
||||
|
||||
// Apply sorting if provided
|
||||
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
|
||||
$order = $request->get('sortOrder');
|
||||
$column = $request->get('sortField');
|
||||
$query->orderBy($column, $order);
|
||||
}
|
||||
|
||||
// Get the total count of records
|
||||
$totalRecords = $query->count();
|
||||
|
||||
// Apply pagination if provided
|
||||
if ($request->has('page') && $request->has('size')) {
|
||||
$page = $request->get('page');
|
||||
$size = $request->get('size');
|
||||
$offset = ($page - 1) * $size; // Calculate the offset
|
||||
|
||||
$query->skip($offset)->take($size);
|
||||
}
|
||||
|
||||
// Get the filtered count of records
|
||||
$filteredRecords = $query->count();
|
||||
|
||||
// Get the data for the current page
|
||||
$data = $query->get();
|
||||
|
||||
// Calculate the page count
|
||||
$pageCount = ceil($totalRecords / $request->get('size'));
|
||||
|
||||
// Calculate the current page number
|
||||
$currentPage = 0 + 1;
|
||||
|
||||
// Return the response data as a JSON object
|
||||
return response()->json([
|
||||
'draw' => $request->get('draw'),
|
||||
'recordsTotal' => $totalRecords,
|
||||
'recordsFiltered' => $filteredRecords,
|
||||
'pageCount' => $pageCount,
|
||||
'page' => $currentPage,
|
||||
'totalCount' => $totalRecords,
|
||||
'data' => $data,
|
||||
]);
|
||||
}
|
||||
}
|
||||
139
app/Http/Controllers/DaftarPustakaController.php
Normal file
139
app/Http/Controllers/DaftarPustakaController.php
Normal file
@@ -0,0 +1,139 @@
|
||||
<?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;
|
||||
use Exception;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
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)
|
||||
{
|
||||
// Get categories with count of daftar pustaka
|
||||
try {
|
||||
$categories = CategoryDaftarPustaka::withCount('daftarPustaka')->get();
|
||||
} catch (\Exception $e) {
|
||||
// Handle jika tabel belum ada atau error lainnya
|
||||
Log::warning('Error loading categories with count: ' . $e->getMessage());
|
||||
$categories = CategoryDaftarPustaka::get(); // Fallback tanpa count
|
||||
}
|
||||
|
||||
$daftar_pustaka = $this->daftarPustaka->getAllDaftarPustaka($request);
|
||||
|
||||
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']);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -129,7 +129,7 @@
|
||||
// Retrieve data from the database
|
||||
$query = Debiture::query();
|
||||
|
||||
if (!Auth::user()->hasAnyRole(['administrator'])) {
|
||||
if (!Auth::user()->hasAnyRole(['administrator','admin'])) {
|
||||
$query = $query->where('branch_id', Auth::user()->branch_id);
|
||||
}
|
||||
|
||||
|
||||
@@ -406,7 +406,9 @@
|
||||
|
||||
|
||||
// Remove values from $legalitasJaminan that are in $currentLegalitasJaminan
|
||||
$legalitasJaminan = array_diff($legalitasJaminan, $currentLegalitasJaminan->pluck('code')->toArray());
|
||||
$legalitasJaminan = is_array($legalitasJaminan)
|
||||
? array_diff($legalitasJaminan, $currentLegalitasJaminan->pluck('code')->toArray())
|
||||
: [];
|
||||
|
||||
$legalitas = JenisLegalitasJaminan::whereIn('code', $legalitasJaminan)->get();
|
||||
}
|
||||
@@ -441,7 +443,7 @@
|
||||
try {
|
||||
// Periksa apakah pengguna adalah admin
|
||||
if (!auth()->user()->hasRole('administrator')) {
|
||||
return response()->json(['success' => false, 'message' => 'Hanya administrator yang dapat menghapus dokumen jaminan'], 403);
|
||||
//return response()->json(['success' => false, 'message' => 'Hanya administrator yang dapat menghapus dokumen jaminan'], 403);
|
||||
}
|
||||
|
||||
$jaminan = DokumenJaminan::find($jaminan_id);
|
||||
@@ -451,8 +453,8 @@
|
||||
}
|
||||
|
||||
// Periksa apakah dokumen jaminan terkait dengan permohonan aktif
|
||||
if ($jaminan->permohonan()->exists()) {
|
||||
return response()->json(['success' => false, 'message' => 'Tidak dapat menghapus dokumen jaminan yang terkait dengan permohonan aktif'], 400);
|
||||
if ($jaminan->permohonan()->exists() && !in_array($jaminan->permohonan->status,['order','revisi'])) {
|
||||
// return response()->json(['success' => false, 'message' => 'Tidak dapat menghapus dokumen jaminan yang terkait dengan permohonan aktif'], 400);
|
||||
}
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
239
app/Http/Controllers/InspeksiController.php
Normal file
239
app/Http/Controllers/InspeksiController.php
Normal file
@@ -0,0 +1,239 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Modules\Lpj\Models\Inspeksi;
|
||||
use Modules\Lpj\Services\InspeksiCleanupService;
|
||||
|
||||
/**
|
||||
* Controller contoh untuk menunjukkan penggunaan InspeksiCleanupService
|
||||
*
|
||||
* Controller ini berisi contoh method untuk membuat dan update data inspeksi
|
||||
* dengan otomatis menjalankan cleanup data lama yang tidak memiliki dokument_id
|
||||
*/
|
||||
class InspeksiController extends Controller
|
||||
{
|
||||
protected InspeksiCleanupService $cleanupService;
|
||||
|
||||
public function __construct(InspeksiCleanupService $cleanupService)
|
||||
{
|
||||
$this->cleanupService = $cleanupService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Contoh method untuk membuat data inspeksi baru
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'permohonan_id' => 'required|integer|exists:permohonan,id',
|
||||
'dokument_id' => 'nullable|integer|exists:dokumen_jaminan,id',
|
||||
'data_form' => 'required|json',
|
||||
'foto_form' => 'nullable|json',
|
||||
'denah_form' => 'nullable|json',
|
||||
'name' => 'required|string|max:255',
|
||||
'status' => 'required|string|max:50',
|
||||
]);
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
try {
|
||||
// Buat data inspeksi baru
|
||||
$inspeksi = Inspeksi::create(array_merge($validated, [
|
||||
'created_by' => Auth::id(),
|
||||
'updated_by' => Auth::id(),
|
||||
]));
|
||||
|
||||
Log::info('InspeksiController: Data inspeksi berhasil dibuat', [
|
||||
'inspeksi_id' => $inspeksi->id,
|
||||
'permohonan_id' => $inspeksi->permohonan_id,
|
||||
'dokument_id' => $inspeksi->dokument_id,
|
||||
'created_by' => $inspeksi->created_by
|
||||
]);
|
||||
|
||||
// Commit transaksi utama
|
||||
DB::commit();
|
||||
|
||||
// Jalankan cleanup secara async jika ada dokument_id
|
||||
// Ini akan menghapus data lama yang tidak memiliki dokument_id
|
||||
if ($inspeksi->dokument_id) {
|
||||
Log::info('InspeksiController: Memulai cleanup data lama', [
|
||||
'permohonan_id' => $inspeksi->permohonan_id,
|
||||
'created_by' => $inspeksi->created_by,
|
||||
'dokument_id' => $inspeksi->dokument_id
|
||||
]);
|
||||
|
||||
// Dispatch job cleanup secara async
|
||||
$this->cleanupService->cleanupAsync(
|
||||
$inspeksi->permohonan_id,
|
||||
$inspeksi->created_by,
|
||||
$inspeksi->dokument_id
|
||||
);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Data inspeksi berhasil dibuat',
|
||||
'data' => $inspeksi->load(['permohonan', 'dokument'])
|
||||
], 201);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
|
||||
Log::error('InspeksiController: Gagal membuat data inspeksi', [
|
||||
'error' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString()
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Gagal membuat data inspeksi: ' . $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Contoh method untuk update data inspeksi
|
||||
*
|
||||
* @param Request $request
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function update(Request $request, $id)
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'dokument_id' => 'nullable|integer|exists:dokumen_jaminan,id',
|
||||
'data_form' => 'required|json',
|
||||
'foto_form' => 'nullable|json',
|
||||
'denah_form' => 'nullable|json',
|
||||
'name' => 'required|string|max:255',
|
||||
'status' => 'required|string|max:50',
|
||||
]);
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
try {
|
||||
$inspeksi = Inspeksi::findOrFail($id);
|
||||
|
||||
// Simpan data lama untuk logging
|
||||
$oldDokumentId = $inspeksi->dokument_id;
|
||||
|
||||
// Update data
|
||||
$inspeksi->update(array_merge($validated, [
|
||||
'updated_by' => Auth::id(),
|
||||
]));
|
||||
|
||||
Log::info('InspeksiController: Data inspeksi berhasil diupdate', [
|
||||
'inspeksi_id' => $inspeksi->id,
|
||||
'permohonan_id' => $inspeksi->permohonan_id,
|
||||
'old_dokument_id' => $oldDokumentId,
|
||||
'new_dokument_id' => $inspeksi->dokument_id,
|
||||
'updated_by' => $inspeksi->updated_by
|
||||
]);
|
||||
|
||||
// Commit transaksi utama
|
||||
DB::commit();
|
||||
|
||||
// Jalankan cleanup jika dokument_id berubah dari null ke ada nilai
|
||||
if (!$oldDokumentId && $inspeksi->dokument_id) {
|
||||
Log::info('InspeksiController: Dokument ID berubah dari null, memulai cleanup', [
|
||||
'inspeksi_id' => $inspeksi->id,
|
||||
'permohonan_id' => $inspeksi->permohonan_id,
|
||||
'created_by' => $inspeksi->created_by,
|
||||
'new_dokument_id' => $inspeksi->dokument_id
|
||||
]);
|
||||
|
||||
// Dispatch job cleanup secara async
|
||||
$this->cleanupService->cleanupAsync(
|
||||
$inspeksi->permohonan_id,
|
||||
$inspeksi->created_by,
|
||||
$inspeksi->dokument_id
|
||||
);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Data inspeksi berhasil diupdate',
|
||||
'data' => $inspeksi->load(['permohonan', 'dokument'])
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
|
||||
Log::error('InspeksiController: Gagal update data inspeksi', [
|
||||
'inspeksi_id' => $id,
|
||||
'error' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString()
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Gagal update data inspeksi: ' . $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Contoh method untuk menjalankan cleanup secara manual
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function cleanup(Request $request)
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'permohonan_id' => 'required|integer|exists:permohonan,id',
|
||||
'created_by' => 'required|integer|exists:users,id',
|
||||
'sync' => 'boolean', // Opsional, default false (async)
|
||||
]);
|
||||
|
||||
try {
|
||||
$permohonanId = $validated['permohonan_id'];
|
||||
$createdBy = $validated['created_by'];
|
||||
$sync = $validated['sync'] ?? false;
|
||||
|
||||
Log::info('InspeksiController: Menjalankan cleanup manual', [
|
||||
'permohonan_id' => $permohonanId,
|
||||
'created_by' => $createdBy,
|
||||
'sync' => $sync
|
||||
]);
|
||||
|
||||
if ($sync) {
|
||||
// Jalankan secara sync
|
||||
$this->cleanupService->cleanupSync($permohonanId, $createdBy);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Cleanup selesai dijalankan secara synchronous'
|
||||
]);
|
||||
} else {
|
||||
// Dispatch ke queue
|
||||
$this->cleanupService->cleanupAsync($permohonanId, $createdBy);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Cleanup job berhasil di-dispatch ke queue'
|
||||
]);
|
||||
}
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('InspeksiController: Gagal menjalankan cleanup manual', [
|
||||
'error' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString()
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Gagal menjalankan cleanup: ' . $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ namespace Modules\Lpj\Http\Controllers;
|
||||
|
||||
use Throwable;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Modules\Lpj\Models\KJPP;
|
||||
use Modules\Location\Models\City;
|
||||
use Modules\Lpj\Models\IjinUsaha;
|
||||
@@ -20,6 +21,29 @@ use Modules\Lpj\Http\Requests\KJPPRequest;
|
||||
class KJPPController extends Controller
|
||||
{
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* Safely combine two arrays for array_map operation
|
||||
*
|
||||
* @param mixed $array1
|
||||
* @param mixed $array2
|
||||
* @return array
|
||||
*/
|
||||
private function safeArrayCombine($array1, $array2)
|
||||
{
|
||||
$arr1 = is_array($array1) ? $array1 : [];
|
||||
$arr2 = is_array($array2) ? $array2 : [];
|
||||
|
||||
// Ensure both arrays have the same length
|
||||
$maxLength = max(count($arr1), count($arr2));
|
||||
|
||||
// Pad shorter arrays with empty strings
|
||||
$arr1 = array_pad($arr1, $maxLength, '');
|
||||
$arr2 = array_pad($arr2, $maxLength, '');
|
||||
|
||||
return [$arr1, $arr2];
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
@@ -187,6 +211,15 @@ class KJPPController extends Controller
|
||||
public function show($id)
|
||||
{
|
||||
$kjpp = KJPP::find($id);
|
||||
|
||||
// Log untuk debugging data JSON
|
||||
Log::info('KJPP Data JSON Debug', [
|
||||
'id' => $id,
|
||||
'detail_nama_pimpinan' => $kjpp->detail_nama_pimpinan ?? 'null',
|
||||
'detail_nomor_hp_pimpinan' => $kjpp->detail_nomor_hp_pimpinan ?? 'null',
|
||||
'detail_email_kantor' => $kjpp->detail_email_kantor ?? 'null',
|
||||
]);
|
||||
|
||||
$ijin_usaha = IjinUsaha::where('code', $kjpp->nomor_ijin_usaha)->get();
|
||||
$ijin_usahas = IjinUsaha::all();
|
||||
$jenis_jaminan = JenisJaminan::all();
|
||||
@@ -208,36 +241,44 @@ class KJPPController extends Controller
|
||||
return [
|
||||
'email_kantor' => $email
|
||||
];
|
||||
}, $detailEmailKantor));
|
||||
}, $detailEmailKantor ?? []));
|
||||
|
||||
// Gunakan helper method untuk penggabungan array yang aman
|
||||
[$safeNamaPimpinan, $safeNomorPimpinan] = $this->safeArrayCombine($detailNamaPimpinan, $detailNomorHpPimpinan);
|
||||
$detailJoinPimpinan = json_encode(array_map(function ($nama, $nomor) {
|
||||
return [
|
||||
'nama_pimpinan' => $nama,
|
||||
'nomor_hp_pimpinan' => $nomor
|
||||
];
|
||||
}, $detailNamaPimpinan, $detailNomorHpPimpinan));
|
||||
}, $safeNamaPimpinan, $safeNomorPimpinan));
|
||||
|
||||
|
||||
// Gunakan helper method untuk penggabungan array yang aman
|
||||
[$safeNamaReviewer, $safeNomorReviewer] = $this->safeArrayCombine($detailNamaPicReviewer, $detailNomorHpPicReviewer);
|
||||
$detailJoinPicReviewer = json_encode(array_map(function ($nama, $nomor) {
|
||||
return [
|
||||
'nama_pic_reviewer' => $nama,
|
||||
'nomor_hp_pic_reviewer' => $nomor
|
||||
];
|
||||
}, $detailNamaPicReviewer, $detailNomorHpPicReviewer));
|
||||
}, $safeNamaReviewer, $safeNomorReviewer));
|
||||
|
||||
// Gunakan helper method untuk penggabungan array yang aman
|
||||
[$safeNamaAdmin, $safeNomorAdmin] = $this->safeArrayCombine($detailNamaPicAdmin, $detailNomorHpPicAdmin);
|
||||
$detailJoinPicAdmin = json_encode(array_map(function ($nama, $nomor) {
|
||||
return [
|
||||
'nama_pic_admin' => $nama,
|
||||
'nomor_hp_pic_admin' => $nomor
|
||||
];
|
||||
}, $detailNamaPicAdmin, $detailNomorHpPicAdmin));
|
||||
}, $safeNamaAdmin, $safeNomorAdmin));
|
||||
|
||||
// Gunakan helper method untuk penggabungan array yang aman
|
||||
[$safeNamaMarketing, $safeNomorMarketing] = $this->safeArrayCombine($detailNamaPicMarketing, $detailNomorHpPicMarketing);
|
||||
$detailJoinPicMarketing = json_encode(array_map(function ($nama, $nomor) {
|
||||
return [
|
||||
'nama_pic_marketing' => $nama,
|
||||
'nomor_hp_pic_marketing' => $nomor
|
||||
];
|
||||
}, $detailNamaPicMarketing, $detailNomorHpPicMarketing));
|
||||
}, $safeNamaMarketing, $safeNomorMarketing));
|
||||
|
||||
return view('lpj::kjpp.show', compact('jenis_jaminan', 'ijin_usahas', 'ijin_usaha', 'kjpp', 'provinces', 'cities', 'districts', 'villages', 'detailJoinEmailKantor', 'detailJoinPicReviewer', 'detailJoinPicAdmin', 'detailJoinPicMarketing', 'detailJoinPimpinan'));
|
||||
}
|
||||
@@ -248,6 +289,15 @@ class KJPPController extends Controller
|
||||
public function edit($id)
|
||||
{
|
||||
$kjpp = KJPP::find($id);
|
||||
|
||||
// Log untuk debugging data JSON di method edit
|
||||
Log::info('KJPP Edit Data JSON Debug', [
|
||||
'id' => $id,
|
||||
'detail_nama_pimpinan' => $kjpp->detail_nama_pimpinan ?? 'null',
|
||||
'detail_nomor_hp_pimpinan' => $kjpp->detail_nomor_hp_pimpinan ?? 'null',
|
||||
'detail_email_kantor' => $kjpp->detail_email_kantor ?? 'null',
|
||||
]);
|
||||
|
||||
$ijin_usaha = IjinUsaha::all();
|
||||
$jenis_aset = JenisJaminan::all();
|
||||
$provinces = Province::all();
|
||||
@@ -268,36 +318,44 @@ class KJPPController extends Controller
|
||||
return [
|
||||
'email_kantor' => $email
|
||||
];
|
||||
}, $detailEmailKantor));
|
||||
}, $detailEmailKantor ?? []));
|
||||
|
||||
// Gunakan helper method untuk penggabungan array yang aman
|
||||
[$safeNamaPimpinan, $safeNomorPimpinan] = $this->safeArrayCombine($detailNamaPimpinan, $detailNomorHpPimpinan);
|
||||
$detailJoinPimpinan = json_encode(array_map(function ($nama, $nomor) {
|
||||
return [
|
||||
'nama_pimpinan' => $nama,
|
||||
'nomor_hp_pimpinan' => $nomor
|
||||
];
|
||||
}, $detailNamaPimpinan, $detailNomorHpPimpinan));
|
||||
}, $safeNamaPimpinan, $safeNomorPimpinan));
|
||||
|
||||
|
||||
// Gunakan helper method untuk penggabungan array yang aman
|
||||
[$safeNamaReviewer, $safeNomorReviewer] = $this->safeArrayCombine($detailNamaPicReviewer, $detailNomorHpPicReviewer);
|
||||
$detailJoinPicReviewer = json_encode(array_map(function ($nama, $nomor) {
|
||||
return [
|
||||
'nama_pic_reviewer' => $nama,
|
||||
'nomor_hp_pic_reviewer' => $nomor
|
||||
];
|
||||
}, $detailNamaPicReviewer, $detailNomorHpPicReviewer));
|
||||
}, $safeNamaReviewer, $safeNomorReviewer));
|
||||
|
||||
// Gunakan helper method untuk penggabungan array yang aman
|
||||
[$safeNamaAdmin, $safeNomorAdmin] = $this->safeArrayCombine($detailNamaPicAdmin, $detailNomorHpPicAdmin);
|
||||
$detailJoinPicAdmin = json_encode(array_map(function ($nama, $nomor) {
|
||||
return [
|
||||
'nama_pic_admin' => $nama,
|
||||
'nomor_hp_pic_admin' => $nomor
|
||||
];
|
||||
}, $detailNamaPicAdmin, $detailNomorHpPicAdmin));
|
||||
}, $safeNamaAdmin, $safeNomorAdmin));
|
||||
|
||||
// Gunakan helper method untuk penggabungan array yang aman
|
||||
[$safeNamaMarketing, $safeNomorMarketing] = $this->safeArrayCombine($detailNamaPicMarketing, $detailNomorHpPicMarketing);
|
||||
$detailJoinPicMarketing = json_encode(array_map(function ($nama, $nomor) {
|
||||
return [
|
||||
'nama_pic_marketing' => $nama,
|
||||
'nomor_hp_pic_marketing' => $nomor
|
||||
];
|
||||
}, $detailNamaPicMarketing, $detailNomorHpPicMarketing));
|
||||
}, $safeNamaMarketing, $safeNomorMarketing));
|
||||
|
||||
return view('lpj::kjpp.create', compact('kjpp', 'ijin_usaha', 'jenis_aset', 'provinces', 'cities', 'districts', 'villages', 'detailJoinPicReviewer', 'detailJoinPicAdmin', 'detailJoinPicMarketing', 'detailJoinEmailKantor', 'detailJoinPimpinan'));
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Modules\Lpj\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Exception;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
@@ -149,6 +150,8 @@
|
||||
$request->validate([
|
||||
'kode_register_t24' => 'nullable',
|
||||
'cif' => 'required',
|
||||
'keterangan' => 'nullable|string',
|
||||
'kolektibilitas' => 'nullable|string|in:1,2,3,4,5',
|
||||
]);
|
||||
|
||||
try {
|
||||
@@ -157,6 +160,8 @@
|
||||
// Update only the editable fields
|
||||
$laporanAdminKredit->update([
|
||||
'kode_register_t24' => $request->kode_register_t24,
|
||||
'keterangan' => $request->keterangan,
|
||||
'kolektibilitas' => $request->kolektibilitas,
|
||||
'updated_by' => Auth::id(),
|
||||
]);
|
||||
|
||||
@@ -169,11 +174,11 @@
|
||||
}
|
||||
|
||||
return redirect()
|
||||
->route('laporan-admin-kredit.index')
|
||||
->route('admin-kredit.laporan.index')
|
||||
->with('success', 'Laporan Admin Kredit updated successfully');
|
||||
} catch (Exception $e) {
|
||||
return redirect()
|
||||
->route('laporan-admin-kredit.edit', $id)
|
||||
->route('admin-kredit.laporan.edit', $id)
|
||||
->with('error', 'Failed to update Laporan Admin Kredit');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
|
||||
namespace Modules\Lpj\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Modules\Lpj\Models\Permohonan;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Modules\Lpj\Http\Controllers\PenilaiController;
|
||||
|
||||
class LaporanController extends Controller
|
||||
@@ -15,7 +16,6 @@ class LaporanController extends Controller
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
|
||||
|
||||
public function __construct(PenilaiController $penilaiController){
|
||||
$this->penilaiController = $penilaiController;
|
||||
}
|
||||
@@ -75,11 +75,12 @@ class LaporanController extends Controller
|
||||
}
|
||||
|
||||
// Retrieve data from the database
|
||||
$query = Permohonan::query()->whereIn('status',['proses-laporan','done', 'paparan', 'proses-paparan'])->whereNotNull('approval_so_at')->whereNotNull('approval_eo_at')->where(function ($q) {
|
||||
$q->whereIn('nilai_plafond_id', [1,4])
|
||||
->whereNotNull('approval_dd_at')
|
||||
->orWhereIn('nilai_plafond_id', [2,3]);
|
||||
});
|
||||
$query = Permohonan::query()
|
||||
->whereIn('status',['proses-laporan','done', 'paparan', 'proses-paparan']);
|
||||
|
||||
if (Auth::user()->hasAnyRole(['pemohon-ao','pemohon-eo'])) {
|
||||
$query = $query->where('branch_id', Auth::user()->branch_id);
|
||||
}
|
||||
|
||||
$query = $query->orderBy('nomor_registrasi', 'desc');
|
||||
// Apply search filter if provided
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
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;
|
||||
@@ -60,6 +61,7 @@
|
||||
$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 . '%');
|
||||
@@ -69,7 +71,7 @@
|
||||
|
||||
// Apply sorting if provided
|
||||
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
|
||||
$order = $request->get('sortOrder');
|
||||
$order = $request->get('sortOrder');
|
||||
$column = $request->get('sortField');
|
||||
$query->orderBy($column, $order);
|
||||
}
|
||||
@@ -104,12 +106,12 @@
|
||||
$lpj = json_decode($permohonan->penilai->lpj, true);
|
||||
$npw = str_replace('.', '', $lpj['total_nilai_pasar_wajar'] ?? 0);
|
||||
|
||||
$luas_tanah = $lpj['luas_tanah'] ?? 0;
|
||||
$luas_tanah = $lpj['luas_tanah'] ?? 0;
|
||||
$luas_bangunan = $lpj['luas_bangunan'] ?? 0;
|
||||
// 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_bangunan = str_replace('.', '', $lpj['nilai_bangunan_2'] ?? 0);
|
||||
$nilai_liquidasi = str_replace('.', '', $lpj['likuidasi_nilai_2'] ?? 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,10 @@ use Modules\Lpj\Models\Permohonan;
|
||||
use Modules\Lpj\Models\StatusPermohonan;
|
||||
use Modules\Lpj\Exports\LaporanPenilaiJaminanExport;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
use Modules\Lpj\Models\Branch;
|
||||
use Modules\Lpj\Services\PreviewLaporanService;
|
||||
use Modules\Lpj\Models\Inspeksi;
|
||||
use Modules\Lpj\Models\Penilai;
|
||||
|
||||
class LaporanPenilaiJaminanController extends Controller
|
||||
{
|
||||
@@ -16,59 +20,31 @@ class LaporanPenilaiJaminanController extends Controller
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
|
||||
protected $previewLaporanService;
|
||||
|
||||
public function __construct(PreviewLaporanService $previewLaporanService)
|
||||
{
|
||||
$this->previewLaporanService = $previewLaporanService;
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
$status_permohonan = StatusPermohonan::all();
|
||||
return view('lpj::laporan-penilai-jaminan.index', compact('status_permohonan'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
return view('lpj::create');
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the specified resource.
|
||||
*/
|
||||
public function show($id)
|
||||
public function show($permohonan_id, $dokumen_id, $jaminan_id)
|
||||
{
|
||||
return view('lpj::laporan-penilai-jaminan.show');
|
||||
$back = route('laporan-penilai-jaminan.index');
|
||||
return $this->previewLaporanService->previewLaporan($permohonan_id, $dokumen_id, $jaminan_id, $back);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*/
|
||||
public function edit($id)
|
||||
{
|
||||
return view('lpj::edit');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*/
|
||||
public function update(Request $request, $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*/
|
||||
public function destroy($id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function dataForDatatables(Request $request)
|
||||
{
|
||||
@@ -93,91 +69,104 @@ class LaporanPenilaiJaminanController extends Controller
|
||||
// dd($startDate);
|
||||
// Retrieve data from the database
|
||||
$query = Permohonan::query();
|
||||
|
||||
$query = $query->where('status', 'done')->orderBy('tanggal_permohonan', 'desc');
|
||||
// Apply search filter if provided
|
||||
if ($request->has('search') && !empty($request->get('search'))) {
|
||||
$search = $request->get('search');
|
||||
$paramsSearch = json_decode($search);
|
||||
$search = json_decode($request->get('search'));
|
||||
|
||||
$query->where(function ($q) use ($search) {
|
||||
$q->where('nomor_registrasi', 'LIKE', '%' . $search . '%')
|
||||
->orWhere('tanggal_permohonan', 'LIKE', '%' . $search . '%')
|
||||
->orWhereRelation('user', 'name', 'LIKE', '%' . $search . '%')
|
||||
->orWhereRelation('debiture', 'name', 'LIKE', '%' . $search . '%')
|
||||
->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search . '%')
|
||||
->orWhereRelation('branch', 'name', 'LIKE', '%' . $search . '%');
|
||||
if (!empty($search->start_date) || !empty($search->end_date)) {
|
||||
$startDate = $search->start_date ?? '1900-01-01';
|
||||
$endDate = $search->end_date ?? now()->toDateString();
|
||||
|
||||
if (!empty($paramsSearch->tanggal_awal) && !empty($paramsSearch->tanggal_akhir)) {
|
||||
$q->whereBetween('tanggal_permohonan', [$paramsSearch->tanggal_awal, $paramsSearch->tanggal_akhir]);
|
||||
$query->where(function ($q) use ($startDate, $endDate) {
|
||||
|
||||
$q->whereHas('penilaian', function ($q2) use ($startDate, $endDate) {
|
||||
$q2->whereBetween('tanggal_kunjungan', [$startDate, $endDate]);
|
||||
});
|
||||
|
||||
// OR check if has penawaran with date in range
|
||||
$q->orWhereHas('penawaran', function ($q3) use ($startDate, $endDate) {
|
||||
$q3->whereBetween('tanggal_penilaian_sebelumnya', [$startDate, $endDate]);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (isset($search->branch_id) && !empty($search->branch_id)) {
|
||||
$query->where('branch_id', $search->branch_id);
|
||||
}
|
||||
|
||||
if (isset($search->laporan) && is_array($search->laporan) && !empty($search->laporan)) {
|
||||
foreach ($search->laporan as $type) {
|
||||
$query->whereHas('penilai', function ($q) use ($type) {
|
||||
$q->where('type_penilai', 'LIKE', '%' . $type . '%');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$statusKeywords = explode(',', $search);
|
||||
foreach ($statusKeywords as $keyword) {
|
||||
$q->orWhereRelation('penilai', 'type_penilai', 'LIKE', '%' . trim($keyword) . '%');
|
||||
}
|
||||
});
|
||||
// dd($search->search);
|
||||
|
||||
if (isset($search->search)) {
|
||||
|
||||
$query->where(function ($q) use ($search) {
|
||||
$q->where('nomor_registrasi', 'LIKE', '%' . $search->search . '%');
|
||||
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search->search . '%');
|
||||
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $search->search . '%');
|
||||
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search->search . '%');
|
||||
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search->search . '%');
|
||||
$q->orWhereRelation('debiture', DB::raw('LOWER(name)'), 'LIKE', '%' . strtolower($search->search) . '%');
|
||||
|
||||
$q->orWhereRelation('jenisFasilitasKredit', 'name', 'LIKE', '%' . $search->search . '%');
|
||||
$q->orWhereRelation('jenisPenilaian', 'name', 'LIKE', '%' . $search->search . '%');
|
||||
$q->orWhere('status', 'LIKE', '%' . $search->search . '%');
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
$query->where('status', 'done');
|
||||
|
||||
|
||||
|
||||
// Default sorting if no sort provided
|
||||
// Apply sorting if provided
|
||||
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
|
||||
$order = $request->get('sortOrder');
|
||||
$column = $request->get('sortField');
|
||||
$query->orderBy($column, $order);
|
||||
} else {
|
||||
$query->orderBy('nomor_registrasi', 'asc');
|
||||
}
|
||||
|
||||
// Get total count of records before pagination
|
||||
|
||||
// Get the total count of records
|
||||
$totalRecords = $query->count();
|
||||
|
||||
// Pagination
|
||||
// Apply pagination if provided
|
||||
if ($request->has('page') && $request->has('size')) {
|
||||
$page = (int) $request->get('page', 1);
|
||||
$size = (int) $request->get('size', 10);
|
||||
$offset = ($page - 1) * $size;
|
||||
$page = $request->get('page');
|
||||
$size = $request->get('size');
|
||||
$offset = ($page - 1) * $size; // Calculate the offset
|
||||
|
||||
$query->skip($offset)->take($size);
|
||||
}
|
||||
|
||||
// Get filtered count
|
||||
// Get the filtered count of records
|
||||
$filteredRecords = $query->count();
|
||||
|
||||
|
||||
|
||||
$totalRecords = $query->count();
|
||||
|
||||
// Pagination
|
||||
if ($request->has('page') && $request->has('size')) {
|
||||
$page = (int) $request->get('page', 1);
|
||||
$size = (int) $request->get('size', 10);
|
||||
$offset = ($page - 1) * $size;
|
||||
$query->skip($offset)->take($size);
|
||||
}
|
||||
|
||||
// Get filtered count
|
||||
$filteredRecords = $query->count();
|
||||
|
||||
// Get data with necessary relationships
|
||||
$data = $query->with(['user', 'debiture', 'branch', 'tujuanPenilaian', 'penilaian', 'dokumenjaminan.jenisJaminan','nilaiPlafond', 'penilai'])->get();
|
||||
$data = $query->with(['user', 'debiture', 'branch', 'tujuanPenilaian', 'penilaian', 'dokumenjaminan.jenisJaminan','nilaiPlafond', 'penilai', 'dokumenjaminan.inspeksi'])->get();
|
||||
|
||||
// Calculate total pages
|
||||
$pageCount = ceil($totalRecords / $request->get('size', 10));
|
||||
// Calculate the page count
|
||||
$pageCount = ceil($totalRecords / $size);
|
||||
|
||||
// Calculate the current page number
|
||||
$currentPage = max(1, $request->get('page', 1));
|
||||
|
||||
|
||||
|
||||
// Calculate total pages
|
||||
$pageCount = ceil($totalRecords / $request->get('size', 10));
|
||||
|
||||
// Return the response data as a JSON object
|
||||
return response()->json([
|
||||
'draw' => $request->get('draw'),
|
||||
'recordsTotal' => $totalRecords,
|
||||
'recordsFiltered' => $filteredRecords,
|
||||
'pageCount' => $pageCount,
|
||||
'page' => $request->get('page', 1),
|
||||
'page' => $currentPage,
|
||||
'totalCount' => $totalRecords,
|
||||
'data' => $data,
|
||||
]);
|
||||
@@ -185,15 +174,53 @@ class LaporanPenilaiJaminanController extends Controller
|
||||
|
||||
public function export(Request $request)
|
||||
{
|
||||
$tanggalAwal = $request->input('tanggal_awal');
|
||||
$tanggalAkhir = $request->input('tanggal_akhir');
|
||||
$status = $request->input('status');
|
||||
$selectedIds = $request->input('selected_ids');
|
||||
$startDate = $request->input('start_date');
|
||||
$endDate = $request->input('end_date');
|
||||
|
||||
// Validate the date format
|
||||
if (isset($startDate) && isset($endDate)) {
|
||||
$startDate = date('Y-m-d', strtotime($startDate));
|
||||
$endDate = date('Y-m-d', strtotime($endDate));
|
||||
|
||||
if ($startDate > $endDate) {
|
||||
return redirect()->back()->with('error', 'Tanggal awal tidak boleh lebih kecil dari tanggal akhir');
|
||||
}
|
||||
}
|
||||
// name the file
|
||||
$filename = $this->createNameLaporan($request);
|
||||
|
||||
$filename = 'laporan_penilai_jaminan_' . date('YmdHis') . '.xlsx';
|
||||
return Excel::download(
|
||||
new LaporanPenilaiJaminanExport($tanggalAwal, $tanggalAkhir, $status, $selectedIds),
|
||||
new LaporanPenilaiJaminanExport($request),
|
||||
$filename
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function createNameLaporan($request)
|
||||
{
|
||||
$startDate = $request->start_date ?? null;
|
||||
$endDate = $request->end_date ?? null;
|
||||
$branchId = $request->branch_id ?? null;
|
||||
$laporan = $request->laporan ?? null;
|
||||
|
||||
// Initialize filename parts
|
||||
$parts = ['Laporan Penilai Jaminan'];
|
||||
if ($startDate && $endDate) {
|
||||
$parts[] = "{$startDate}_{$endDate}";
|
||||
}
|
||||
if ($laporan) {
|
||||
$parts[] = $laporan;
|
||||
}
|
||||
if ($branchId) {
|
||||
$parts[] = $this->getBranchId($branchId);
|
||||
}
|
||||
// Return concatenated filename with extension
|
||||
return implode('_', $parts) . '.xlsx';
|
||||
}
|
||||
|
||||
public function getBranchId($branchId)
|
||||
{
|
||||
$branchesName = Branch::find($branchId)->name ?? null;
|
||||
return $branchesName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,161 +1,180 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Http\Controllers;
|
||||
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 Maatwebsite\Excel\Facades\Excel;
|
||||
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
|
||||
class LaporanPenilaianJaminanController extends Controller
|
||||
{
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
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 (isset($search->start_date) || isset($search->end_date)) {
|
||||
$query->whereBetween('tanggal_permohonan', [
|
||||
$search->start_date ?? '1900-01-01',
|
||||
$search->end_date ?? now()->toDateString()
|
||||
]);
|
||||
}
|
||||
|
||||
// Filter by branch if provided
|
||||
if (isset($search->branch_id) && !empty($search->branch_id)) {
|
||||
$query->where('branch_id', $search->branch_id);
|
||||
}
|
||||
|
||||
if (isset($search->penilai_id) && !empty($search->penilai_id)) {
|
||||
$query->whereHas('penilaian._user_penilai.userPenilaiTeam', function($q) use ($search) {
|
||||
$q->where('user_id', $search->penilai_id);
|
||||
});
|
||||
}
|
||||
|
||||
if (isset($search->search)) {
|
||||
|
||||
$query->where(function ($q) use ($search) {
|
||||
$q->where('nomor_registrasi', 'LIKE', '%' . $search->search . '%');
|
||||
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search->search . '%');
|
||||
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $search->search . '%');
|
||||
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search->search . '%');
|
||||
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search->search . '%');
|
||||
$q->orWhereRelation('jenisFasilitasKredit', 'name', 'LIKE', '%' . $search->search . '%');
|
||||
$q->orWhereRelation('jenisPenilaian', 'name', 'LIKE', '%' . $search->search . '%');
|
||||
$q->orWhere('status', 'LIKE', '%' . $search->search . '%');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Apply sorting if provided
|
||||
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
|
||||
$order = $request->get('sortOrder');
|
||||
$column = $request->get('sortField');
|
||||
$query->orderBy($column, $order);
|
||||
}
|
||||
|
||||
// Get the total count of records
|
||||
$totalRecords = $query->count();
|
||||
|
||||
// Apply pagination if provided
|
||||
if ($request->has('page') && $request->has('size')) {
|
||||
$page = $request->get('page');
|
||||
$size = $request->get('size');
|
||||
$offset = ($page - 1) * $size; // Calculate the offset
|
||||
|
||||
$query->skip($offset)->take($size);
|
||||
}
|
||||
|
||||
// Get the filtered count of records
|
||||
$filteredRecords = $query->count();
|
||||
|
||||
// Get the data for the current page
|
||||
$data = $query->with(['debiture.branch'])->get();
|
||||
|
||||
$data = $data->map(function ($permohonan) {
|
||||
$luas_tanah = 0;
|
||||
$luas_bangunan = 0;
|
||||
$nilai_tanah = 0;
|
||||
$nilai_bangunan = 0;
|
||||
$npw = 0;
|
||||
$nilai_liquidasi = 0;
|
||||
if (isset($permohonan->penilai->lpj)) {
|
||||
$lpj = json_decode($permohonan->penilai->lpj, true);
|
||||
$npw = str_replace('.', '', $lpj['total_nilai_pasar_wajar'] ?? 0);
|
||||
|
||||
$luas_tanah = $lpj['luas_tanah'] ?? 0;
|
||||
$luas_bangunan = $lpj['luas_bangunan'] ?? 0;
|
||||
// Calculate nilai_tanah dynamically by looking for all keys that start with 'nilai_tanah_'
|
||||
$nilai_tanah = str_replace('.', '', $lpj['nilai_tanah_2'] ?? 0);
|
||||
|
||||
$nilai_bangunan = str_replace('.', '', $lpj['nilai_bangunan_2'] ?? 0);
|
||||
$nilai_liquidasi = str_replace('.', '', $lpj['likuidasi_nilai_2'] ?? 0);
|
||||
}
|
||||
|
||||
return [
|
||||
'id' => $permohonan->id,
|
||||
'nomor_registrasi' => $permohonan->nomor_registrasi,
|
||||
'tanggal_permohonan' => $permohonan->tanggal_permohonan,
|
||||
'branch' => $permohonan->debiture?->branch?->name,
|
||||
'name' => $permohonan->debiture?->name,
|
||||
'pemohon' => $permohonan->creator?->name,
|
||||
'tujuan_penilaian' => $permohonan->tujuanPenilaian?->name,
|
||||
'jenis_agunan' => $permohonan->documents?->pluck('jenisJaminan.name')->unique()->implode(', '),
|
||||
'alamat_agunan' => $permohonan->documents?->map(function ($document) {
|
||||
return formatAlamat($document);
|
||||
})->unique()->implode(', '),
|
||||
'luas_tanah' => $luas_tanah . ' m²',
|
||||
'nilai_tanah' => formatRupiah($nilai_tanah,2),
|
||||
'luas_bangunan' => $luas_bangunan . ' m²',
|
||||
'nilai_bangunan' => formatRupiah($nilai_bangunan,2),
|
||||
'tanggal_laporan' => $permohonan->approval_dd_at ?? $permohonan->approval_eo_at ?? '',
|
||||
'tanggal_review' => $permohonan->penilaian?->tanggal_kunjungan ?? '',
|
||||
'nilai_pasar_wajar' => formatRupiah($npw,2),
|
||||
'nilai_likuidasi' => formatRupiah($nilai_liquidasi,2),
|
||||
'nama_penilai' => $permohonan->penilaian?->_user_penilai?->userPenilaiTeam?->name,
|
||||
];
|
||||
});
|
||||
|
||||
// Calculate the page count
|
||||
$pageCount = ceil($totalRecords / $request->get('size'));
|
||||
|
||||
// Calculate the current page number
|
||||
$currentPage = $request->get('page', 1);
|
||||
|
||||
// Return the response data as a JSON object
|
||||
return response()->json([
|
||||
'draw' => $request->get('draw'),
|
||||
'recordsTotal' => $totalRecords,
|
||||
'recordsFiltered' => $filteredRecords,
|
||||
'pageCount' => $pageCount,
|
||||
'page' => $currentPage,
|
||||
'totalCount' => $totalRecords,
|
||||
'data' => $data,
|
||||
]);
|
||||
}
|
||||
|
||||
public function export(Request $request)
|
||||
{
|
||||
return Excel::download(new LaporanPenilaianJaminanExport($request), 'laporan_penilaian_jaminan.xlsx');
|
||||
}
|
||||
return view('lpj::laporan_penilaian_jaminan.index');
|
||||
}
|
||||
|
||||
public function dataForDatatables(Request $request)
|
||||
{
|
||||
if (is_null($this->user) || !$this->user->can('laporan-admin-kredit.view')) {
|
||||
//abort(403, 'Sorry! You are not allowed to view laporan admin kredit.');
|
||||
}
|
||||
|
||||
// Retrieve data from the database
|
||||
$query = Permohonan::query();
|
||||
$query = $query->where('status', 'done');
|
||||
|
||||
// Apply search filter if provided
|
||||
if ($request->has('search') && !empty($request->get('search'))) {
|
||||
$search = json_decode($request->get('search'));
|
||||
|
||||
|
||||
if (!empty($search->start_date) || !empty($search->end_date)) {
|
||||
$startDate = $search->start_date ?? '1900-01-01';
|
||||
$endDate = $search->end_date ?? now()->toDateString();
|
||||
|
||||
$query->where(function ($q) use ($startDate, $endDate) {
|
||||
$q->whereHas('penilaian', function ($q2) use ($startDate, $endDate) {
|
||||
$q2->whereBetween('tanggal_kunjungan', [$startDate, $endDate]);
|
||||
})
|
||||
->orWhereHas('penawaran', function ($q3) use ($startDate, $endDate) {
|
||||
$q3->whereBetween('tanggal_penilaian_sebelumnya', [$startDate, $endDate]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Filter by branch if provided
|
||||
if (isset($search->branch_id) && !empty($search->branch_id)) {
|
||||
$query->where('branch_id', $search->branch_id);
|
||||
}
|
||||
|
||||
if (isset($search->penilai_id) && !empty($search->penilai_id)) {
|
||||
$query->whereHas('penilaian._user_penilai.userPenilaiTeam', function ($q) use ($search) {
|
||||
$q->where('user_id', $search->penilai_id);
|
||||
});
|
||||
}
|
||||
|
||||
if (isset($search->search)) {
|
||||
|
||||
$query->where(function ($q) use ($search) {
|
||||
$q->where('nomor_registrasi', 'LIKE', '%' . $search->search . '%');
|
||||
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search->search . '%');
|
||||
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $search->search . '%');
|
||||
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search->search . '%');
|
||||
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search->search . '%');
|
||||
$q->orWhereRelation('debiture', DB::raw('LOWER(name)'), 'LIKE', '%' . strtolower($search->search) . '%');
|
||||
|
||||
$q->orWhereRelation('jenisFasilitasKredit', 'name', 'LIKE', '%' . $search->search . '%');
|
||||
$q->orWhereRelation('jenisPenilaian', 'name', 'LIKE', '%' . $search->search . '%');
|
||||
$q->orWhere('status', 'LIKE', '%' . $search->search . '%');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Apply sorting if provided
|
||||
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
|
||||
$order = $request->get('sortOrder');
|
||||
$column = $request->get('sortField');
|
||||
$query->orderBy($column, $order);
|
||||
}
|
||||
|
||||
// Get the total count of records
|
||||
$totalRecords = $query->count();
|
||||
|
||||
// Apply pagination if provided
|
||||
if ($request->has('page') && $request->has('size')) {
|
||||
$page = $request->get('page');
|
||||
$size = $request->get('size');
|
||||
$offset = ($page - 1) * $size; // Calculate the offset
|
||||
|
||||
$query->skip($offset)->take($size);
|
||||
}
|
||||
|
||||
// Get the filtered count of records
|
||||
$filteredRecords = $query->count();
|
||||
|
||||
// Get the data for the current page
|
||||
$data = $query->with(['debiture.branch'])->get();
|
||||
|
||||
$data = $data->map(function ($permohonan) {
|
||||
$luas_tanah = 0;
|
||||
$luas_bangunan = 0;
|
||||
$nilai_tanah = 0;
|
||||
$nilai_bangunan = 0;
|
||||
$npw = 0;
|
||||
$nilai_liquidasi = 0;
|
||||
if (isset($permohonan->penilai->lpj)) {
|
||||
$lpj = json_decode($permohonan->penilai->lpj, true);
|
||||
$npw = str_replace('.', '', $lpj['total_nilai_pasar_wajar'] ?? 0);
|
||||
|
||||
$luas_tanah = $lpj['luas_tanah'] ?? 0;
|
||||
$luas_bangunan = $lpj['luas_bangunan'] ?? 0;
|
||||
// Calculate nilai_tanah dynamically by looking for all keys that start with 'nilai_tanah_'
|
||||
$nilai_tanah = str_replace('.', '', $lpj['nilai_tanah_2'] ?? 0);
|
||||
|
||||
$nilai_bangunan = str_replace('.', '', $lpj['nilai_bangunan_2'] ?? 0);
|
||||
$nilai_liquidasi = str_replace('.', '', $lpj['likuidasi_nilai_2'] ?? 0);
|
||||
}
|
||||
|
||||
return [
|
||||
'id' => $permohonan->id,
|
||||
'nomor_registrasi' => $permohonan->nomor_registrasi,
|
||||
'tanggal_permohonan' => $permohonan->tanggal_permohonan,
|
||||
'branch' => $permohonan->debiture?->branch?->name,
|
||||
'name' => $permohonan->debiture?->name,
|
||||
'pemohon' => $permohonan->creator?->name,
|
||||
'tujuan_penilaian' => $permohonan->tujuanPenilaian?->name,
|
||||
'jenis_agunan' => $permohonan->documents?->pluck('jenisJaminan.name')->unique()->implode(', '),
|
||||
'alamat_agunan' => $permohonan->documents?->map(function ($document) {
|
||||
return formatAlamat($document);
|
||||
})->unique()->implode(', '),
|
||||
'luas_tanah' => $luas_tanah . ' m²',
|
||||
'nilai_tanah' => formatRupiah($nilai_tanah, 2),
|
||||
'luas_bangunan' => $luas_bangunan . ' m²',
|
||||
'nilai_bangunan' => formatRupiah($nilai_bangunan, 2),
|
||||
'tanggal_laporan' => $permohonan->approval_dd_at ?? $permohonan->approval_eo_at ?? '',
|
||||
'tanggal_review' => $permohonan->penilaian?->tanggal_kunjungan ?? '',
|
||||
'nilai_pasar_wajar' => formatRupiah($npw, 2),
|
||||
'nilai_likuidasi' => formatRupiah($nilai_liquidasi, 2),
|
||||
'nama_penilai' => $permohonan->penilaian?->_user_penilai?->userPenilaiTeam?->name,
|
||||
];
|
||||
});
|
||||
|
||||
// Calculate the page count
|
||||
$pageCount = ceil($totalRecords / $request->get('size'));
|
||||
|
||||
// Calculate the current page number
|
||||
$currentPage = $request->get('page', 1);
|
||||
|
||||
// Return the response data as a JSON object
|
||||
return response()->json([
|
||||
'draw' => $request->get('draw'),
|
||||
'recordsTotal' => $totalRecords,
|
||||
'recordsFiltered' => $filteredRecords,
|
||||
'pageCount' => $pageCount,
|
||||
'page' => $currentPage,
|
||||
'totalCount' => $totalRecords,
|
||||
'data' => $data,
|
||||
]);
|
||||
}
|
||||
|
||||
public function export(Request $request)
|
||||
{
|
||||
$startDate = $request->start_date;
|
||||
$endDate = $request->end_date;
|
||||
// name of the file
|
||||
$fileName = 'laporan_penilaian_jaminan_' . $startDate . '_' . $endDate . '.xlsx';
|
||||
return Excel::download(new LaporanPenilaianJaminanExport($request), $fileName);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
// Retrieve data from the database
|
||||
$query = Permohonan::query();
|
||||
$query->where('status','done');
|
||||
|
||||
if (!Auth::user()->hasAnyRole(['administrator'])) {
|
||||
$query = $query->where('branch_id', Auth::user()->branch_id);
|
||||
|
||||
304
app/Http/Controllers/LaporanSlikController.php
Normal file
304
app/Http/Controllers/LaporanSlikController.php
Normal file
@@ -0,0 +1,304 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
use Modules\Lpj\Models\LaporanSlik;
|
||||
use Modules\Lpj\Models\Slik;
|
||||
use Modules\Lpj\Exports\LaporanSlikExport;
|
||||
|
||||
class LaporanSlikController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return view('lpj::laporan-slik.index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*/
|
||||
public function store(Request $request): JsonResponse
|
||||
{
|
||||
try {
|
||||
$request->validate([
|
||||
'slik_id' => 'required|exists:sliks,id'
|
||||
]);
|
||||
|
||||
$slik = Slik::findOrFail($request->slik_id);
|
||||
|
||||
// Cek apakah data sudah ada di laporan_slik
|
||||
$existing = LaporanSlik::where('slik_id', $slik->id)->first();
|
||||
if ($existing) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Data sudah ada di laporan SLIK'
|
||||
], 422);
|
||||
}
|
||||
|
||||
// Copy data dari tabel slik ke laporan_slik
|
||||
$laporanSlik = LaporanSlik::create([
|
||||
'slik_id' => $slik->id,
|
||||
'sandi_bank' => $slik->sandi_bank,
|
||||
'kode_kantor' => $slik->kode_kantor,
|
||||
'kode_cabang' => $slik->kode_cabang,
|
||||
'tahun' => $slik->tahun,
|
||||
'bulan' => $slik->bulan,
|
||||
'no_rekening' => $slik->no_rekening,
|
||||
'cif' => $slik->cif,
|
||||
'kode_jenis' => $slik->kode_jenis,
|
||||
'kode_jenis_ket' => $slik->kode_jenis_ket,
|
||||
'kode_sifat' => $slik->kode_sifat,
|
||||
'kode_sifat_ket' => $slik->kode_sifat_ket,
|
||||
'kode_valuta' => $slik->kode_valuta,
|
||||
'kode_valuta_ket' => $slik->kode_valuta_ket,
|
||||
'baki_debet' => $slik->baki_debet,
|
||||
'kolektibilitas' => $slik->kolektibilitas,
|
||||
'kolektibilitas_ket' => $slik->kolektibilitas_ket,
|
||||
'tanggal_mulai' => $slik->tanggal_mulai,
|
||||
'tanggal_jatuh_tempo' => $slik->tanggal_jatuh_tempo,
|
||||
'tanggal_selesai' => $slik->tanggal_selesai,
|
||||
'tanggal_restrukturisasi' => $slik->tanggal_restrukturisasi,
|
||||
'kode_sebab_macet' => $slik->kode_sebab_macet,
|
||||
'kode_sebab_macet_ket' => $slik->kode_sebab_macet_ket,
|
||||
'tanggal_macet' => $slik->tanggal_macet,
|
||||
'kode_kondisi' => $slik->kode_kondisi,
|
||||
'kode_kondisi_ket' => $slik->kode_kondisi_ket,
|
||||
'tanggal_kondisi' => $slik->tanggal_kondisi,
|
||||
'nilai_agunan' => $slik->nilai_agunan,
|
||||
'nilai_agunan_ket' => $slik->nilai_agunan_ket,
|
||||
'jenis_agunan' => $slik->jenis_agunan,
|
||||
'kode_agunan' => $slik->kode_agunan,
|
||||
'kode_agunan_ket' => $slik->kode_agunan_ket,
|
||||
'peringkat_agunan' => $slik->peringkat_agunan,
|
||||
'peringkat_agunan_ket' => $slik->peringkat_agunan_ket,
|
||||
'nama_debitur' => $slik->nama_debitur,
|
||||
'npwp' => $slik->npwp,
|
||||
'no_ktp' => $slik->no_ktp,
|
||||
'no_telp' => $slik->no_telp,
|
||||
'kode_kab_kota' => $slik->kode_kab_kota,
|
||||
'kode_kab_kota_ket' => $slik->kode_kab_kota_ket,
|
||||
'kode_negara_domisili' => $slik->kode_negara_domisili,
|
||||
'kode_negara_domisili_ket' => $slik->kode_negara_domisili_ket,
|
||||
'kode_pos' => $slik->kode_pos,
|
||||
'alamat' => $slik->alamat,
|
||||
'fasilitas' => $slik->fasilitas,
|
||||
'status_agunan' => $slik->status_agunan,
|
||||
'tanggal_lapor' => $slik->tanggal_lapor,
|
||||
'status' => 'active',
|
||||
'created_by' => auth()->id(),
|
||||
'updated_by' => auth()->id(),
|
||||
]);
|
||||
|
||||
// Hapus data dari tabel slik setelah berhasil dipindahkan
|
||||
$slik->delete();
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Data berhasil dipindahkan ke laporan SLIK',
|
||||
'data' => $laporanSlik
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Error moving SLIK to laporan: ' . $e->getMessage());
|
||||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Terjadi kesalahan saat memindahkan data'
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Data untuk datatables dengan server-side processing
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function dataForDatatables(Request $request)
|
||||
{
|
||||
try {
|
||||
// Retrieve data from the database
|
||||
$query = LaporanSlik::query();
|
||||
|
||||
// Apply search filter if provided
|
||||
if ($request->has('search') && !empty($request->get('search'))) {
|
||||
$search = $request->get('search');
|
||||
$query->where(function ($q) use ($search) {
|
||||
$q->where('sandi_bank', 'LIKE', "%$search%")
|
||||
->orWhere('no_rekening', 'LIKE', "%$search%")
|
||||
->orWhere('cif', 'LIKE', "%$search%")
|
||||
->orWhere('nama_debitur', 'LIKE', "%$search%")
|
||||
->orWhere('fasilitas', 'LIKE', "%$search%")
|
||||
->orWhere('status_agunan', 'LIKE', "%$search%");
|
||||
});
|
||||
}
|
||||
|
||||
// Apply year filter
|
||||
if ($request->has('year') && !empty($request->get('year'))) {
|
||||
$query->where('tahun', $request->get('year'));
|
||||
}
|
||||
|
||||
// Apply month filter
|
||||
if ($request->has('month') && !empty($request->get('month'))) {
|
||||
$query->where('bulan', $request->get('month'));
|
||||
}
|
||||
|
||||
// Apply sandi bank filter
|
||||
if ($request->has('sandi_bank') && !empty($request->get('sandi_bank'))) {
|
||||
$query->where('sandi_bank', $request->get('sandi_bank'));
|
||||
}
|
||||
|
||||
// Apply kolektibilitas filter
|
||||
if ($request->has('kolektibilitas') && !empty($request->get('kolektibilitas'))) {
|
||||
$query->where('kolektibilitas', $request->get('kolektibilitas'));
|
||||
}
|
||||
|
||||
// Apply status filter
|
||||
if ($request->has('status') && !empty($request->get('status'))) {
|
||||
$query->where('status', $request->get('status'));
|
||||
}
|
||||
|
||||
// Apply sorting if provided
|
||||
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
|
||||
$order = $request->get('sortOrder');
|
||||
$column = $request->get('sortField', 'created_at');
|
||||
$query->orderBy($column, $order);
|
||||
} else {
|
||||
$query->orderBy('created_at', 'desc');
|
||||
}
|
||||
|
||||
// Get the total count of records
|
||||
$totalRecords = $query->count();
|
||||
|
||||
// Apply pagination if provided
|
||||
if ($request->has('page') && $request->has('size')) {
|
||||
$page = $request->get('page');
|
||||
$size = $request->get('size');
|
||||
$offset = ($page - 1) * $size; // Calculate the offset
|
||||
|
||||
$query->skip($offset)->take($size);
|
||||
}
|
||||
|
||||
// Get the filtered count of records
|
||||
$filteredRecords = $query->count();
|
||||
|
||||
// Get the data for the current page
|
||||
$data = $query->get();
|
||||
|
||||
// Transform data untuk datatables
|
||||
$transformedData = $data->map(function ($item) {
|
||||
return [
|
||||
'id' => $item->id,
|
||||
'sandi_bank' => $item->sandi_bank,
|
||||
'tahun' => $item->tahun,
|
||||
'bulan' => $item->bulan,
|
||||
'no_rekening' => $item->no_rekening,
|
||||
'cif' => $item->cif,
|
||||
'nama_debitur' => $item->nama_debitur,
|
||||
'kolektibilitas' => $item->kolektibilitas,
|
||||
'kolektibilitas_badge' => $item->kolektibilitas_badge ?? '',
|
||||
'fasilitas' => $item->fasilitas,
|
||||
'nilai_agunan' => $item->nilai_agunan_formatted ?? '',
|
||||
'status_agunan' => $item->status_agunan,
|
||||
'status_badge' => $item->status_badge ?? '',
|
||||
'created_by' => $item->creator?->name ?? '-',
|
||||
'created_at' => dateFormat($item->created_at, true) ?? $item->created_at->format('d/m/Y H:i')
|
||||
];
|
||||
});
|
||||
|
||||
// Calculate the page count
|
||||
$pageCount = ceil($totalRecords / ($request->get('size', 10)));
|
||||
|
||||
// Calculate the current page number
|
||||
$currentPage = $request->get('page', 1);
|
||||
|
||||
// Return the response data as a JSON object
|
||||
return response()->json([
|
||||
'draw' => $request->get('draw'),
|
||||
'recordsTotal' => $totalRecords,
|
||||
'recordsFiltered' => $filteredRecords,
|
||||
'pageCount' => $pageCount,
|
||||
'page' => $currentPage,
|
||||
'totalCount' => $totalRecords,
|
||||
'data' => $transformedData,
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Error in laporan slik datatables: ' . $e->getMessage());
|
||||
|
||||
return response()->json([
|
||||
'draw' => $request->get('draw'),
|
||||
'recordsTotal' => 0,
|
||||
'recordsFiltered' => 0,
|
||||
'pageCount' => 0,
|
||||
'page' => 1,
|
||||
'totalCount' => 0,
|
||||
'data' => [],
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function show($id)
|
||||
{
|
||||
try {
|
||||
$laporanSlik = LaporanSlik::findOrFail($id);
|
||||
return view('lpj::laporan-slik.show', compact('laporanSlik'));
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Error showing laporan slik: ' . $e->getMessage());
|
||||
return back()->with('error', 'Data tidak ditemukan');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Export laporan SLIK to Excel
|
||||
*/
|
||||
public function export(Request $request)
|
||||
{
|
||||
try {
|
||||
$query = LaporanSlik::query();
|
||||
|
||||
// Apply filters
|
||||
if ($request->has('search') && $request->search) {
|
||||
$search = $request->search;
|
||||
$query->where(function($q) use ($search) {
|
||||
$q->where('nama_debitur', 'like', "%{$search}%")
|
||||
->orWhere('no_rekening', 'like', "%{$search}%")
|
||||
->orWhere('cif', 'like', "%{$search}%");
|
||||
});
|
||||
}
|
||||
|
||||
if ($request->has('year') && $request->year) {
|
||||
$query->where('tahun', $request->year);
|
||||
}
|
||||
|
||||
if ($request->has('month') && $request->month) {
|
||||
$query->where('bulan', $request->month);
|
||||
}
|
||||
|
||||
if ($request->has('status') && $request->status) {
|
||||
$query->where('status', $request->status);
|
||||
}
|
||||
|
||||
$filename = 'laporan-slik-' . now()->format('Y-m-d-His') . '.xlsx';
|
||||
|
||||
return Excel::download(new LaporanSlikExport($query), $filename);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Error exporting laporan slik: ' . $e->getMessage());
|
||||
return back()->with('error', 'Gagal export data: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,8 @@ 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
|
||||
@@ -38,4 +40,12 @@ class LaporanUserController extends Controller
|
||||
return $this->laporanUserService->dataForDatatables($request);
|
||||
}
|
||||
|
||||
public function export(Request $request)
|
||||
{
|
||||
$startDate = $request->start_date;
|
||||
$endDate = $request->end_date;
|
||||
// name of the file
|
||||
$fileName = 'laporan_user_limit' . $startDate . '_' . $endDate . '.xlsx';
|
||||
return Excel::download(new LaporanUserLimitExport($request), $fileName);
|
||||
}
|
||||
}
|
||||
|
||||
558
app/Http/Controllers/MemoController.php
Normal file
558
app/Http/Controllers/MemoController.php
Normal file
@@ -0,0 +1,558 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Http\Controllers;
|
||||
|
||||
use Exception;
|
||||
use Modules\Lpj\Models\Noc;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Modules\Lpj\Models\Permohonan;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Barryvdh\DomPDF\Facade\Pdf;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class MemoController extends Controller
|
||||
{
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* Menampilkan halaman index memo penyelesaian
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
Log::info('MemoController: Mengakses halaman index memo penyelesaian');
|
||||
return view('lpj::memo.index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Menampilkan form untuk membuat memo penyelesaian dengan data yang dipilih
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function create(Request $request)
|
||||
{
|
||||
Log::info('MemoController: Mengakses halaman create memo penyelesaian');
|
||||
|
||||
$selectedIds = $request->get('selected_ids', []);
|
||||
|
||||
// Pastikan $selectedIds selalu berupa array
|
||||
if (is_string($selectedIds)) {
|
||||
$selectedIds = explode(',', $selectedIds);
|
||||
}
|
||||
|
||||
// Filter array untuk menghilangkan nilai kosong
|
||||
$selectedIds = array_filter($selectedIds, function($id) {
|
||||
return !empty(trim($id));
|
||||
});
|
||||
|
||||
$permohonanList = [];
|
||||
$totalBiayaPJ = 0;
|
||||
|
||||
if (!empty($selectedIds) && count($selectedIds) > 0) {
|
||||
try {
|
||||
$permohonanList = Permohonan::with([
|
||||
'user',
|
||||
'debiture',
|
||||
'branch',
|
||||
'tujuanPenilaian',
|
||||
'penilaian',
|
||||
'jenisFasilitasKredit',
|
||||
'documents.inspeksi',
|
||||
'penilai',
|
||||
'documents.detail',
|
||||
'noc'
|
||||
])->whereIn('id', $selectedIds)->get();
|
||||
|
||||
// Hitung total biaya PJ dari nominal_bayar di tabel NOC
|
||||
$totalBiayaPJ = Noc::whereIn('permohonan_id', $selectedIds)
|
||||
->sum('nominal_bayar');
|
||||
|
||||
Log::info('MemoController: Total Biaya PJ dihitung: ' . $totalBiayaPJ);
|
||||
|
||||
} catch (Exception $e) {
|
||||
Log::error('MemoController: Error saat mengambil data permohonan - ' . $e->getMessage());
|
||||
return redirect()->back()->with('error', 'Terjadi kesalahan saat memuat data');
|
||||
}
|
||||
}
|
||||
|
||||
return view('lpj::memo.create', compact('permohonanList', 'totalBiayaPJ'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Menyimpan memo penyelesaian yang telah dibuat
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
Log::info('MemoController: Memulai proses penyimpanan memo penyelesaian');
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
try {
|
||||
// Validasi input
|
||||
$request->validate([
|
||||
'permohonan_ids' => 'required|array',
|
||||
'permohonan_ids.*' => 'exists:permohonan,id',
|
||||
'memo_number' => 'required|string|max:255',
|
||||
'payment_date' => 'required|date',
|
||||
'memo_date' => 'required|date'
|
||||
]);
|
||||
|
||||
$permohonanIds = $request->permohonan_ids;
|
||||
$memoNumber = $request->memo_number;
|
||||
$paymentDate = $request->payment_date;
|
||||
$memoDate = $request->memo_date;
|
||||
|
||||
// Update status permohonan yang dipilih
|
||||
foreach ($permohonanIds as $permohonanId) {
|
||||
$permohonan = Permohonan::find($permohonanId);
|
||||
if ($permohonan) {
|
||||
$permohonan->status = 'memo-penyelesaian';
|
||||
$permohonan->memo_penyelesaian_number = $memoNumber;
|
||||
$permohonan->memo_penyelesaian_date = $memoDate;
|
||||
$permohonan->memo_penyelesaian_payment_date = $paymentDate;
|
||||
$permohonan->memo_penyelesaian_created_at = now();
|
||||
//$permohonan->save();
|
||||
|
||||
Log::info('MemoController: Berhasil update permohonan ID: ' . $permohonanId);
|
||||
}
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
Log::info('MemoController: Berhasil menyimpan memo penyelesaian untuk ' . count($permohonanIds) . ' permohonan');
|
||||
|
||||
return redirect()->route('memo.index')
|
||||
->with('success', 'Memo penyelesaian berhasil dibuat untuk ' . count($permohonanIds) . ' permohonan');
|
||||
|
||||
} catch (Exception $e) {
|
||||
DB::rollback();
|
||||
Log::error('MemoController: Error saat menyimpan memo penyelesaian - ' . $e->getMessage());
|
||||
|
||||
return redirect()->back()
|
||||
->withInput()
|
||||
->with('error', 'Terjadi kesalahan saat menyimpan memo penyelesaian: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Menampilkan detail memo penyelesaian
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function show($id)
|
||||
{
|
||||
Log::info('MemoController: Mengakses detail memo penyelesaian ID: ' . $id);
|
||||
|
||||
$permohonan = Permohonan::with([
|
||||
'user',
|
||||
'debiture',
|
||||
'branch',
|
||||
'tujuanPenilaian',
|
||||
'penilaian',
|
||||
'jenisFasilitasKredit',
|
||||
'documents.inspeksi',
|
||||
'penilai',
|
||||
'documents.detail',
|
||||
'noc'
|
||||
])->findOrFail($id);
|
||||
|
||||
return view('lpj::memo.show', compact('permohonan'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Mengambil data untuk datatables pada halaman memo penyelesaian
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function dataForDatatables(Request $request)
|
||||
{
|
||||
Log::info('MemoController: Mengambil data untuk datatables');
|
||||
|
||||
if (is_null($this->user) || !$this->user->can('debitur.view')) {
|
||||
Log::warning('MemoController: User tidak memiliki permission untuk melihat data');
|
||||
// abort(403, 'Sorry! You are not allowed to view users.');
|
||||
}
|
||||
|
||||
// Mengambil data dari database dengan kondisi yang sama seperti LaporanController
|
||||
$query = Permohonan::query()
|
||||
->whereIn('status', ['proses-laporan', 'done', 'paparan', 'proses-paparan', 'memo-penyelesaian'])
|
||||
/*->whereNotNull('approval_so_at')
|
||||
->whereNotNull('approval_eo_at')
|
||||
->where(function ($q) {
|
||||
$q->whereIn('nilai_plafond_id', [1, 4])
|
||||
->whereNotNull('approval_dd_at')
|
||||
->orWhereIn('nilai_plafond_id', [2, 3]);
|
||||
})*/
|
||||
->whereHas('noc'); // Hanya tampilkan permohonan yang memiliki NOC
|
||||
|
||||
|
||||
$query = $query->orderBy('nomor_registrasi', 'desc');
|
||||
|
||||
// Apply search filter jika ada
|
||||
if ($request->has('search') && !empty($request->get('search'))) {
|
||||
$searchParams = explode('|', $request->get('search'));
|
||||
|
||||
$filterJenisPenilaian = $searchParams[0] ?? '';
|
||||
$searchTerm = $searchParams[1] ?? '';
|
||||
|
||||
// Filter berdasarkan jenis penilaian
|
||||
if (!empty($filterJenisPenilaian)) {
|
||||
$query->where('jenis_penilaian_id', $filterJenisPenilaian);
|
||||
Log::info('Applied jenis penilaian filter', ['filter' => $filterJenisPenilaian]);
|
||||
}
|
||||
|
||||
$query->where(function ($q) use ($searchTerm) {
|
||||
$q->where('nomor_registrasi', 'LIKE', '%' . $searchTerm . '%');
|
||||
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $searchTerm . '%');
|
||||
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $searchTerm . '%');
|
||||
$q->orWhereRelation('debiture', 'name', 'LIKE', '%' . $searchTerm . '%');
|
||||
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $searchTerm . '%');
|
||||
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $searchTerm . '%');
|
||||
$q->orWhere('status', 'LIKE', '%' . $searchTerm . '%');
|
||||
});
|
||||
}
|
||||
|
||||
// Apply sorting jika ada
|
||||
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
|
||||
$order = $request->get('sortOrder');
|
||||
$column = $request->get('sortField');
|
||||
$query->orderBy($column, $order);
|
||||
}
|
||||
|
||||
// Mendapatkan total count records
|
||||
$totalRecords = $query->count();
|
||||
$size = $request->get('size', 10);
|
||||
if ($size == 0) {
|
||||
$size = 10;
|
||||
}
|
||||
|
||||
// Apply pagination jika ada
|
||||
if ($request->has('page') && $request->has('size')) {
|
||||
$page = $request->get('page');
|
||||
$size = $request->get('size');
|
||||
$offset = ($page - 1) * $size;
|
||||
|
||||
$query->skip($offset)->take($size);
|
||||
}
|
||||
|
||||
// Mendapatkan filtered count records
|
||||
$filteredRecords = $query->count();
|
||||
|
||||
// Mendapatkan data untuk halaman saat ini
|
||||
$data = $query->with([
|
||||
'user',
|
||||
'debiture',
|
||||
'branch',
|
||||
'tujuanPenilaian',
|
||||
'jenisPenilaian',
|
||||
'penilaian',
|
||||
'jenisFasilitasKredit',
|
||||
'documents.inspeksi',
|
||||
'penilai',
|
||||
'documents.detail',
|
||||
'noc'
|
||||
])->get();
|
||||
|
||||
// Menghitung page count
|
||||
$pageCount = ceil($totalRecords / $size);
|
||||
|
||||
// Menghitung current page number
|
||||
$currentPage = max(1, $request->get('page', 1));
|
||||
|
||||
Log::info('MemoController: Berhasil mengambil data datatables - Total: ' . $totalRecords . ', Filtered: ' . $filteredRecords);
|
||||
|
||||
// Return response data sebagai JSON object
|
||||
return response()->json([
|
||||
'draw' => $request->get('draw'),
|
||||
'recordsTotal' => $totalRecords,
|
||||
'recordsFiltered' => $filteredRecords,
|
||||
'pageCount' => $pageCount,
|
||||
'page' => $currentPage,
|
||||
'totalCount' => $totalRecords,
|
||||
'data' => $data,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mengambil total biaya PJ berdasarkan permohonan yang dipilih
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function getTotalBiayaPJ(Request $request)
|
||||
{
|
||||
Log::info('MemoController: Mengambil total biaya PJ');
|
||||
|
||||
try {
|
||||
$permohonanIds = $request->get('permohonan_ids', []);
|
||||
|
||||
// Pastikan $permohonanIds selalu berupa array
|
||||
if (is_string($permohonanIds)) {
|
||||
$permohonanIds = explode(',', $permohonanIds);
|
||||
}
|
||||
|
||||
// Filter array untuk menghilangkan nilai kosong
|
||||
$permohonanIds = array_filter($permohonanIds, function($id) {
|
||||
return !empty(trim($id));
|
||||
});
|
||||
|
||||
$totalBiayaPJ = 0;
|
||||
|
||||
if (!empty($permohonanIds) && count($permohonanIds) > 0) {
|
||||
// Hitung total biaya PJ dari nominal_bayar di tabel NOC
|
||||
$totalBiayaPJ = \Modules\Lpj\Models\Noc::whereIn('permohonan_id', $permohonanIds)
|
||||
->sum('nominal_bayar');
|
||||
}
|
||||
|
||||
Log::info('MemoController: Total Biaya PJ berhasil dihitung: ' . $totalBiayaPJ);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'total_biaya_pj' => $totalBiayaPJ,
|
||||
'total_biaya_pj_formatted' => 'Rp ' . number_format($totalBiayaPJ, 0, ',', '.')
|
||||
]);
|
||||
|
||||
} catch (Exception $e) {
|
||||
Log::error('MemoController: Error saat menghitung total biaya PJ - ' . $e->getMessage());
|
||||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Terjadi kesalahan saat menghitung total biaya PJ'
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Menampilkan preview memo penyelesaian sebelum menyimpan
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function preview(Request $request)
|
||||
{
|
||||
Log::info('MemoController: Mengakses halaman preview memo penyelesaian');
|
||||
|
||||
|
||||
$permohonanIds = $request->permohonan_ids;
|
||||
$memoNumber = $request->memo_number;
|
||||
$paymentDate = $request->payment_date;
|
||||
$memoDate = $request->memo_date;
|
||||
|
||||
try {
|
||||
// Ambil data permohonan yang dipilih
|
||||
$permohonanList = Permohonan::with([
|
||||
'user',
|
||||
'debiture',
|
||||
'branch',
|
||||
'penilaian',
|
||||
'jenisPenilaian',
|
||||
'jenisFasilitasKredit',
|
||||
'documents.inspeksi',
|
||||
'penilai',
|
||||
'documents.detail',
|
||||
'noc'
|
||||
])->whereIn('id', $permohonanIds);
|
||||
|
||||
// Hitung total biaya PJ dari nominal_bayar di tabel NOC
|
||||
$totalBiayaPJ = Noc::whereIn('permohonan_id', $permohonanIds)
|
||||
->sum('nominal_bayar');
|
||||
|
||||
// Data untuk template memo
|
||||
$memoData = [
|
||||
'memo_number' => $memoNumber,
|
||||
'memo_date' => $memoDate,
|
||||
'payment_date' => $paymentDate,
|
||||
'total_biaya_pj' => $totalBiayaPJ,
|
||||
'permohonan_list' => $permohonanList->get(),
|
||||
'debitur_count' => $permohonanList->get()->count(),
|
||||
'jaminan_info' => $this->getJaminanInfo($permohonanList->get()),
|
||||
'jenisPenilaian' => $permohonanList->pluck('jenis_penilaian_id')->first()
|
||||
];
|
||||
|
||||
$permohonanList= $permohonanList->get();
|
||||
|
||||
Log::info('MemoController: Data preview memo berhasil disiapkan');
|
||||
|
||||
return view('lpj::memo.preview', compact('memoData', 'permohonanList', 'totalBiayaPJ'));
|
||||
|
||||
} catch (Exception $e) {
|
||||
Log::error('MemoController: Error saat menyiapkan preview memo - ' . $e->getMessage());
|
||||
return redirect()->back()
|
||||
->withInput()
|
||||
->with('error', 'Terjadi kesalahan saat menyiapkan preview memo: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate PDF memo penyelesaian dan simpan ke database
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function generatePdf(Request $request)
|
||||
{
|
||||
Log::info('MemoController: Memulai generate PDF memo penyelesaian');
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
try {
|
||||
// Validasi input
|
||||
|
||||
$permohonanIds = $request->permohonan_ids;
|
||||
$memoNumber = $request->memo_number;
|
||||
$paymentDate = $request->payment_date;
|
||||
$memoDate = $request->memo_date;
|
||||
|
||||
// Ambil data permohonan yang dipilih
|
||||
$permohonanList = Permohonan::with([
|
||||
'user',
|
||||
'debiture',
|
||||
'branch',
|
||||
'penilaian',
|
||||
'jenisPenilaian',
|
||||
'jenisFasilitasKredit',
|
||||
'documents.inspeksi',
|
||||
'penilai',
|
||||
'documents.detail',
|
||||
'noc'
|
||||
])->whereIn('id', $permohonanIds);
|
||||
|
||||
// Hitung total biaya PJ dari nominal_bayar di tabel NOC
|
||||
$totalBiayaPJ = Noc::whereIn('permohonan_id', $permohonanIds)
|
||||
->sum('nominal_bayar');
|
||||
|
||||
// Data untuk template memo
|
||||
$memoData = [
|
||||
'memo_number' => $memoNumber,
|
||||
'memo_date' => $memoDate,
|
||||
'payment_date' => $paymentDate,
|
||||
'total_biaya_pj' => $totalBiayaPJ,
|
||||
'permohonan_list' => $permohonanList->get(),
|
||||
'debitur_count' => $permohonanList->get()->count(),
|
||||
'jaminan_info' => $this->getJaminanInfo($permohonanList->get()),
|
||||
'jenisPenilaian' => $permohonanList->pluck('jenis_penilaian_id')->first()
|
||||
];
|
||||
|
||||
$permohonanList= $permohonanList->get();
|
||||
|
||||
// Generate PDF dari template
|
||||
$pdf = Pdf::loadView('lpj::memo.pdf-template', compact('memoData', 'permohonanList', 'totalBiayaPJ'))
|
||||
->setPaper('a4', 'portrait')
|
||||
->setOptions([
|
||||
'defaultFont' => 'Times-Roman',
|
||||
'isRemoteEnabled' => true,
|
||||
'isHtml5ParserEnabled' => true,
|
||||
'isPhpEnabled' => true,
|
||||
'dpi' => 150,
|
||||
'defaultPaperSize' => 'a4',
|
||||
'chroot' => public_path(),
|
||||
]);
|
||||
|
||||
// Nama file PDF
|
||||
$fileName = 'memo-penyelesaian-' . str_replace(['/', ' '], ['-', '-'], $memoNumber) . '-' . date('Y-m-d-H-i-s') . '.pdf';
|
||||
$filePath = 'memo-penyelesaian/' . $fileName;
|
||||
|
||||
// Simpan PDF ke storage
|
||||
Storage::disk('public')->put($filePath, $pdf->output());
|
||||
|
||||
// Update status permohonan yang dipilih
|
||||
// Update data di tabel NOC untuk setiap permohonan
|
||||
foreach ($permohonanIds as $permohonanId) {
|
||||
// Cari NOC berdasarkan permohonan_id
|
||||
$noc = Noc::where('permohonan_id', $permohonanId)->first();
|
||||
|
||||
if ($noc) {
|
||||
// Update field memo penyelesaian di tabel NOC
|
||||
$noc->memo_penyelesaian = $filePath;
|
||||
$noc->memo_penyelesaian_number = $memoNumber;
|
||||
$noc->memo_penyelesaian_date = $memoDate;
|
||||
$noc->memo_penyelesaian_payment_date = $paymentDate;
|
||||
$noc->memo_penyelesaian_created_at = now();
|
||||
$noc->save();
|
||||
|
||||
Log::info('MemoController: Berhasil update NOC untuk permohonan ID: ' . $permohonanId);
|
||||
} else {
|
||||
Log::warning('MemoController: NOC tidak ditemukan untuk permohonan ID: ' . $permohonanId);
|
||||
}
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
Log::info('MemoController: Berhasil generate PDF dan menyimpan memo penyelesaian untuk ' . count($permohonanIds) . ' permohonan');
|
||||
|
||||
// Return PDF untuk download
|
||||
return $pdf->download('memo-penyelesaian-' . $memoNumber . '.pdf');
|
||||
|
||||
} catch (Exception $e) {
|
||||
DB::rollback();
|
||||
Log::error('MemoController: Error saat generate PDF memo penyelesaian - ' . $e->getMessage());
|
||||
|
||||
return redirect()->back()
|
||||
->with('error', 'Terjadi kesalahan saat generate PDF memo penyelesaian: ' . $e->getMessage())
|
||||
->withInput();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function untuk mendapatkan informasi jaminan
|
||||
*
|
||||
* @param $permohonanList
|
||||
* @return string
|
||||
*/
|
||||
private function getJaminanInfo($permohonanList)
|
||||
{
|
||||
$jaminanTypes = [];
|
||||
foreach ($permohonanList as $permohonan) {
|
||||
if ($permohonan->tujuanPenilaian) {
|
||||
$jaminanTypes[] = $permohonan->tujuanPenilaian->name;
|
||||
}
|
||||
}
|
||||
|
||||
$uniqueJaminan = array_unique($jaminanTypes);
|
||||
return implode(' & ', $uniqueJaminan);
|
||||
}
|
||||
/**
|
||||
* Download PDF memo penyelesaian
|
||||
*
|
||||
* @param int $id - ID permohonan
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function downloadPdf($id)
|
||||
{
|
||||
Log::info('MemoController: Download PDF memo penyelesaian untuk permohonan ID: ' . $id);
|
||||
|
||||
try {
|
||||
// Cari NOC berdasarkan permohonan_id
|
||||
$noc = Noc::where('permohonan_id', $id)->first();
|
||||
|
||||
if (!$noc || !$noc->memo_penyelesaian) {
|
||||
Log::warning('MemoController: PDF memo penyelesaian tidak ditemukan untuk permohonan ID: ' . $id);
|
||||
return redirect()->back()->with('error', 'File PDF memo penyelesaian tidak ditemukan.');
|
||||
}
|
||||
|
||||
// Cek apakah file ada di storage
|
||||
if (!Storage::disk('public')->exists($noc->memo_penyelesaian)) {
|
||||
Log::warning('MemoController: File PDF tidak ada di storage: ' . $noc->memo_penyelesaian);
|
||||
return redirect()->back()->with('error', 'File PDF tidak ditemukan di server.');
|
||||
}
|
||||
|
||||
// Download file
|
||||
$fileName = 'memo-penyelesaian-' . $noc->memo_penyelesaian_number . '.pdf';
|
||||
|
||||
Log::info('MemoController: Berhasil download PDF memo penyelesaian: ' . $fileName);
|
||||
|
||||
return Storage::disk('public')->download($noc->memo_penyelesaian, $fileName);
|
||||
|
||||
} catch (Exception $e) {
|
||||
Log::error('MemoController: Error saat download PDF memo penyelesaian - ' . $e->getMessage());
|
||||
return redirect()->back()->with('error', 'Terjadi kesalahan saat mengunduh file PDF.');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,8 @@
|
||||
use App\Http\Controllers\Controller;
|
||||
use Exception;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
use Modules\Lpj\Exports\NilaiPlafondExport;
|
||||
use Modules\Lpj\Http\Requests\NilaiPlafondRequest;
|
||||
@@ -14,137 +16,239 @@
|
||||
{
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* Menampilkan halaman daftar Nilai Plafond.
|
||||
* Log setiap akses dan sebelum return view.
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return view('lpj::nilai_plafond.index');
|
||||
Log::info('NilaiPlafondController@index: akses halaman index');
|
||||
return \view('lpj::nilai_plafond.index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Menyimpan data Nilai Plafond baru termasuk field biaya.
|
||||
* Gunakan validasi dari NilaiPlafondRequest, log proses, dan bungkus dengan transaksi DB.
|
||||
*/
|
||||
public function store(NilaiPlafondRequest $request)
|
||||
{
|
||||
Log::info('NilaiPlafondController@store: mulai proses simpan');
|
||||
$validate = $request->validated();
|
||||
|
||||
if ($validate) {
|
||||
DB::beginTransaction();
|
||||
try {
|
||||
// Save to database
|
||||
NilaiPlafond::create($validate);
|
||||
return redirect()
|
||||
$record = NilaiPlafond::create($validate);
|
||||
DB::commit();
|
||||
|
||||
Log::info('NilaiPlafondController@store: simpan berhasil', ['id' => $record->id]);
|
||||
return \redirect()
|
||||
->route('basicdata.nilai-plafond.index')
|
||||
->with('success', 'Jenis Aset created successfully');
|
||||
->with('success', 'Nilai Plafond berhasil dibuat');
|
||||
} catch (Exception $e) {
|
||||
return redirect()
|
||||
DB::rollBack();
|
||||
Log::error('NilaiPlafondController@store: simpan gagal', ['error' => $e->getMessage()]);
|
||||
|
||||
return \redirect()
|
||||
->route('basicdata.nilai-plafond.create')
|
||||
->with('error', 'Failed to create nilai plafond');
|
||||
->with('error', 'Gagal membuat Nilai Plafond');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Menampilkan form pembuatan Nilai Plafond.
|
||||
* Log akses sebelum return view.
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
return view('lpj::nilai_plafond.create');
|
||||
Log::info('NilaiPlafondController@create: akses halaman create');
|
||||
return \view('lpj::nilai_plafond.create');
|
||||
}
|
||||
|
||||
/**
|
||||
* Menampilkan form edit Nilai Plafond berdasarkan ID.
|
||||
* Gunakan transaksi untuk pembacaan data dan logging.
|
||||
*/
|
||||
public function edit($id)
|
||||
{
|
||||
$nilaiPlafond = NilaiPlafond::find($id);
|
||||
return view('lpj::nilai_plafond.create', compact('nilaiPlafond'));
|
||||
Log::info('NilaiPlafondController@edit: mulai proses edit', ['id' => $id]);
|
||||
|
||||
DB::beginTransaction();
|
||||
try {
|
||||
$nilaiPlafond = NilaiPlafond::find($id);
|
||||
DB::commit();
|
||||
|
||||
Log::info('NilaiPlafondController@edit: data ditemukan', ['id' => $id]);
|
||||
return \view('lpj::nilai_plafond.create', compact('nilaiPlafond'));
|
||||
} catch (Exception $e) {
|
||||
DB::rollBack();
|
||||
Log::error('NilaiPlafondController@edit: gagal mengambil data', ['id' => $id, 'error' => $e->getMessage()]);
|
||||
return \redirect()
|
||||
->route('basicdata.nilai-plafond.index')
|
||||
->with('error', 'Gagal mengambil data Nilai Plafond');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Memperbarui data Nilai Plafond termasuk field biaya.
|
||||
* Validasi input, logging, dan gunakan transaksi DB.
|
||||
*/
|
||||
public function update(NilaiPlafondRequest $request, $id)
|
||||
{
|
||||
Log::info('NilaiPlafondController@update: mulai proses update', ['id' => $id]);
|
||||
$validate = $request->validated();
|
||||
|
||||
if ($validate) {
|
||||
DB::beginTransaction();
|
||||
try {
|
||||
// Update in database
|
||||
$nilaiPlafond = NilaiPlafond::find($id);
|
||||
if (!$nilaiPlafond) {
|
||||
Log::warning('NilaiPlafondController@update: data tidak ditemukan', ['id' => $id]);
|
||||
DB::rollBack();
|
||||
return \redirect()
|
||||
->route('basicdata.nilai-plafond.index')
|
||||
->with('error', 'Data Nilai Plafond tidak ditemukan');
|
||||
}
|
||||
|
||||
$nilaiPlafond->update($validate);
|
||||
return redirect()
|
||||
DB::commit();
|
||||
|
||||
Log::info('NilaiPlafondController@update: update berhasil', ['id' => $id]);
|
||||
return \redirect()
|
||||
->route('basicdata.nilai-plafond.index')
|
||||
->with('success', 'Jenis Aset updated successfully');
|
||||
->with('success', 'Nilai Plafond berhasil diperbarui');
|
||||
} catch (Exception $e) {
|
||||
return redirect()
|
||||
DB::rollBack();
|
||||
Log::error('NilaiPlafondController@update: update gagal', ['id' => $id, 'error' => $e->getMessage()]);
|
||||
|
||||
return \redirect()
|
||||
->route('basicdata.nilai-plafond.edit', $id)
|
||||
->with('error', 'Failed to update nilai plafond');
|
||||
->with('error', 'Gagal memperbarui Nilai Plafond');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Menghapus data Nilai Plafond berdasarkan ID.
|
||||
* Logging setiap langkah dan gunakan transaksi DB.
|
||||
*/
|
||||
public function destroy($id)
|
||||
{
|
||||
Log::info('NilaiPlafondController@destroy: mulai proses hapus', ['id' => $id]);
|
||||
DB::beginTransaction();
|
||||
try {
|
||||
// Delete from database
|
||||
$nilaiPlafond = NilaiPlafond::find($id);
|
||||
$nilaiPlafond->delete();
|
||||
if (!$nilaiPlafond) {
|
||||
DB::rollBack();
|
||||
Log::warning('NilaiPlafondController@destroy: data tidak ditemukan', ['id' => $id]);
|
||||
return \response()->json(['success' => false, 'message' => 'Data Nilai Plafond tidak ditemukan']);
|
||||
}
|
||||
|
||||
echo json_encode(['success' => true, 'message' => 'Jenis Aset deleted successfully']);
|
||||
$nilaiPlafond->delete();
|
||||
DB::commit();
|
||||
|
||||
Log::info('NilaiPlafondController@destroy: hapus berhasil', ['id' => $id]);
|
||||
return \response()->json(['success' => true, 'message' => 'Nilai Plafond berhasil dihapus']);
|
||||
} catch (Exception $e) {
|
||||
echo json_encode(['success' => false, 'message' => 'Failed to delete nilai plafond']);
|
||||
DB::rollBack();
|
||||
Log::error('NilaiPlafondController@destroy: hapus gagal', ['id' => $id, 'error' => $e->getMessage()]);
|
||||
return \response()->json(['success' => false, 'message' => 'Gagal menghapus Nilai Plafond']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Menyediakan data untuk datatables dengan pencarian, sortir, dan paginasi.
|
||||
* Logging proses dan gunakan transaksi DB untuk konsistensi pembacaan.
|
||||
*/
|
||||
public function dataForDatatables(Request $request)
|
||||
{
|
||||
Log::info('NilaiPlafondController@dataForDatatables: mulai proses');
|
||||
|
||||
if (is_null($this->user) || !$this->user->can('nilai_plafond.view')) {
|
||||
//abort(403, 'Sorry! You are not allowed to view users.');
|
||||
}
|
||||
|
||||
// Retrieve data from the database
|
||||
$query = NilaiPlafond::query();
|
||||
DB::beginTransaction();
|
||||
try {
|
||||
// Retrieve data from the database
|
||||
$query = NilaiPlafond::query();
|
||||
|
||||
// Apply search filter if provided
|
||||
if ($request->has('search') && !empty($request->get('search'))) {
|
||||
$search = $request->get('search');
|
||||
$query->where(function ($q) use ($search) {
|
||||
$q->where('code', 'LIKE', "%$search%");
|
||||
$q->orWhere('name', 'LIKE', "%$search%");
|
||||
});
|
||||
// Apply search filter if provided
|
||||
if ($request->has('search') && !empty($request->get('search'))) {
|
||||
$search = $request->get('search');
|
||||
$query->where(function ($q) use ($search) {
|
||||
$q->where('code', 'LIKE', "%$search%");
|
||||
$q->orWhere('name', 'LIKE', "%$search%");
|
||||
});
|
||||
}
|
||||
|
||||
// Apply sorting if provided
|
||||
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
|
||||
$order = $request->get('sortOrder');
|
||||
$column = $request->get('sortField');
|
||||
$query->orderBy($column, $order);
|
||||
}
|
||||
|
||||
// Get the total count of records
|
||||
$totalRecords = $query->count();
|
||||
|
||||
// Apply pagination if provided
|
||||
if ($request->has('page') && $request->has('size')) {
|
||||
$page = $request->get('page');
|
||||
$size = $request->get('size');
|
||||
$offset = ($page - 1) * $size; // Calculate the offset
|
||||
|
||||
$query->skip($offset)->take($size);
|
||||
}
|
||||
|
||||
// Get the filtered count of records
|
||||
$filteredRecords = $query->count();
|
||||
|
||||
// Get the data for the current page
|
||||
$data = $query->get();
|
||||
|
||||
// Calculate the page count
|
||||
$pageCount = ceil($totalRecords / $request->get('size'));
|
||||
|
||||
// Calculate the current page number
|
||||
$currentPage = 0 + 1;
|
||||
|
||||
DB::commit();
|
||||
Log::info('NilaiPlafondController@dataForDatatables: proses selesai, mengembalikan data');
|
||||
|
||||
// Return the response data as a JSON object
|
||||
return \response()->json([
|
||||
'draw' => $request->get('draw'),
|
||||
'recordsTotal' => $totalRecords,
|
||||
'recordsFiltered' => $filteredRecords,
|
||||
'pageCount' => $pageCount,
|
||||
'page' => $currentPage,
|
||||
'totalCount' => $totalRecords,
|
||||
'data' => $data,
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
DB::rollBack();
|
||||
Log::error('NilaiPlafondController@dataForDatatables: gagal memproses data', ['error' => $e->getMessage()]);
|
||||
return \response()->json([
|
||||
'draw' => $request->get('draw'),
|
||||
'recordsTotal' => 0,
|
||||
'recordsFiltered' => 0,
|
||||
'pageCount' => 0,
|
||||
'page' => 1,
|
||||
'totalCount' => 0,
|
||||
'data' => [],
|
||||
]);
|
||||
}
|
||||
|
||||
// Apply sorting if provided
|
||||
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
|
||||
$order = $request->get('sortOrder');
|
||||
$column = $request->get('sortField');
|
||||
$query->orderBy($column, $order);
|
||||
}
|
||||
|
||||
// Get the total count of records
|
||||
$totalRecords = $query->count();
|
||||
|
||||
// Apply pagination if provided
|
||||
if ($request->has('page') && $request->has('size')) {
|
||||
$page = $request->get('page');
|
||||
$size = $request->get('size');
|
||||
$offset = ($page - 1) * $size; // Calculate the offset
|
||||
|
||||
$query->skip($offset)->take($size);
|
||||
}
|
||||
|
||||
// Get the filtered count of records
|
||||
$filteredRecords = $query->count();
|
||||
|
||||
// Get the data for the current page
|
||||
$data = $query->get();
|
||||
|
||||
// Calculate the page count
|
||||
$pageCount = ceil($totalRecords / $request->get('size'));
|
||||
|
||||
// Calculate the current page number
|
||||
$currentPage = 0 + 1;
|
||||
|
||||
// Return the response data as a JSON object
|
||||
return response()->json([
|
||||
'draw' => $request->get('draw'),
|
||||
'recordsTotal' => $totalRecords,
|
||||
'recordsFiltered' => $filteredRecords,
|
||||
'pageCount' => $pageCount,
|
||||
'page' => $currentPage,
|
||||
'totalCount' => $totalRecords,
|
||||
'data' => $data,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mengekspor data Nilai Plafond ke Excel.
|
||||
* Log akses sebelum proses download.
|
||||
*/
|
||||
public function export()
|
||||
{
|
||||
Log::info('NilaiPlafondController@export: mulai proses export');
|
||||
return Excel::download(new NilaiPlafondExport, 'nilai_plafond.xlsx');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,10 +6,11 @@
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Modules\Lpj\Http\Requests\NocRequest;
|
||||
use Modules\Lpj\Models\Noc;
|
||||
use Modules\Lpj\Models\PenawaranTender;
|
||||
use Modules\Lpj\Models\Permohonan;
|
||||
use Modules\Lpj\Models\Permohonan;
|
||||
use Modules\Lpj\Models\Noc;
|
||||
use Modules\Lpj\Models\Bucok;
|
||||
use Modules\Lpj\Models\PersetujuanPenawaran;
|
||||
use Modules\Lpj\Models\JenisPenilaian;
|
||||
|
||||
class NocController extends Controller
|
||||
{
|
||||
@@ -26,13 +27,15 @@
|
||||
public function pembayaran()
|
||||
{
|
||||
$persetujuanPenawarans = PersetujuanPenawaran::all();
|
||||
return view('lpj::noc.pembayaran', compact('persetujuanPenawarans'));
|
||||
$jenisPenilaians = JenisPenilaian::get();
|
||||
return view('lpj::noc.pembayaran', compact('persetujuanPenawarans', 'jenisPenilaians'));
|
||||
}
|
||||
|
||||
public function penyelesaian()
|
||||
{
|
||||
$persetujuanPenawarans = PersetujuanPenawaran::all();
|
||||
return view('lpj::noc.penyelesaian', compact('persetujuanPenawarans'));
|
||||
$jenisPenilaians = JenisPenilaian::get();
|
||||
return view('lpj::noc.penyelesaian', compact('persetujuanPenawarans', 'jenisPenilaians'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -47,28 +50,47 @@
|
||||
public function store(NocRequest $request)
|
||||
{
|
||||
$validated = $request->validated();
|
||||
$validated['updated_by'] = Auth::id();
|
||||
if (request()->get('status_bayar') == "sudah_bayar") {
|
||||
$validated['status'] = '1';
|
||||
$status = "spk";
|
||||
} else {
|
||||
$status = "persetujuan-penawaran";
|
||||
}
|
||||
|
||||
|
||||
$validated['updated_by'] = Auth::id();
|
||||
if (request()->get('status_pembayar') == "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'],
|
||||
'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'] ?? '',
|
||||
];
|
||||
$noc = Noc::updateOrCreate(
|
||||
|
||||
if($validated['permohonan_id']){
|
||||
$noc = Noc::updateOrCreate(
|
||||
[
|
||||
'permohonan_id' => $validated['permohonan_id'],
|
||||
'persetujuan_penawaran_id' => $validated['persetujuan_penawaran_id'],
|
||||
],
|
||||
$dataNoc,
|
||||
);
|
||||
$dataNoc);
|
||||
|
||||
if($validated['status_pembayar'] == 'sudah_bayar'){
|
||||
$permohonan = Permohonan::find($validated['permohonan_id']);
|
||||
$permohonan->status_bayar = $validated['status_pembayar'];
|
||||
$permohonan->status = 'proses-laporan';
|
||||
$permohonan->save();
|
||||
}
|
||||
} else {
|
||||
$noc = Noc::updateOrCreate(
|
||||
[
|
||||
'persetujuan_penawaran_id' => $validated['persetujuan_penawaran_id'],
|
||||
],
|
||||
$dataNoc);
|
||||
}
|
||||
|
||||
$folderPath = 'noc/' . request()->get('persetujuan_penawaran_id') . '/bukti_ksl/';
|
||||
|
||||
@@ -80,26 +102,13 @@
|
||||
}
|
||||
$noc->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_pembayar');
|
||||
if ($permohonan->jenis_penilaian_id == 2) {
|
||||
$permohonan->status = $status;
|
||||
}
|
||||
$permohonan->save();
|
||||
|
||||
// andy add, update status penawaran.status='spk'
|
||||
// $penawaran = PenawaranTender::where('nomor_registrasi',$permohonan->nomor_registrasi)->first();
|
||||
if ($permohonan->jenis_penilaian_id == 2) {
|
||||
PenawaranTender::where('nomor_registrasi', $permohonan->nomor_registrasi)->update([
|
||||
'status' => $status,
|
||||
'updated_by' => Auth::id(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
}
|
||||
// andy add, update status penawaran.status='spk'
|
||||
}*/
|
||||
$bucok = Bucok::where('nomor_tiket', $noc->nomor_tiket)->orWhere('permohonan_id', $noc->permohonan_id)->first();
|
||||
if($bucok){
|
||||
$bucok->nominal_penyelesaian = $noc->total_pembukuan ?? '';
|
||||
$bucok->tanggal_penyelesaian = $noc->tanggal_pembayaran ?? date('Y-m-d');
|
||||
$bucok->penyelesaian = 'Selesai';
|
||||
$bucok->save();
|
||||
}
|
||||
|
||||
return redirect()
|
||||
->route('noc.index')->with('success', 'NOC berhasil disimpan.');
|
||||
@@ -133,6 +142,7 @@
|
||||
->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,
|
||||
@@ -142,13 +152,19 @@
|
||||
|
||||
$noc = Noc::updateOrCreate(
|
||||
[
|
||||
'permohonan_id' => $validated['permohonan_id'],
|
||||
'permohonan_id' => $validated['permohonan_id'],
|
||||
'persetujuan_penawaran_id' => $validated['persetujuan_penawaran_id'],
|
||||
],
|
||||
$dataNoc,
|
||||
);
|
||||
|
||||
if($validated['status_pembayar'] == 'sudah_bayar'){
|
||||
$permohonan = Permohonan::find($validated['permohonan_id']);
|
||||
$permohonan->status_bayar = $validated['status_pembayar'];
|
||||
$permohonan->status = 'proses-laporan';
|
||||
$permohonan->save();
|
||||
}
|
||||
|
||||
$folderPath = 'noc/' . request()->get('persetujuan_penawaran_id') . '/bukti_penyelesaian/';
|
||||
|
||||
if ($request->hasFile('bukti_penyelesaian')) {
|
||||
@@ -215,15 +231,19 @@
|
||||
$query = PersetujuanPenawaran::query();
|
||||
|
||||
// Filter for pembayaran (where memo_penyelesaian is null)
|
||||
$query->whereDoesntHave('noc', function($q) {
|
||||
/*$query->whereDoesntHave('noc', function($q) {
|
||||
$q->whereNotNull('memo_penyelesaian');
|
||||
});
|
||||
});*/
|
||||
|
||||
// Apply search filter if provided
|
||||
if ($request->has('search') && !empty($request->get('search'))) {
|
||||
$search = $request->get('search');
|
||||
$query->where(function ($q) use ($search) {
|
||||
$q->orWhereRelation('penawaran', 'nomor_registrasi', 'LIKE', '%' . $search . '%');
|
||||
$q->orWhereRelation('penawaran', 'nomor_registrasi', 'LIKE', '%' . $search . '%')
|
||||
->orWhereRelation('permohonan', 'nomor_registrasi', 'LIKE', '%' . $search . '%')
|
||||
->orWhereRelation('permohonan.debiture','name', 'LIKE', '%' . $search . '%')
|
||||
->orWhereRelation('permohonan.jenisPenilaian', 'name', 'LIKE', '%' . $search . '%')
|
||||
->orWhere('nomor_tiket', 'LIKE', '%' . $search . '%');
|
||||
});
|
||||
}
|
||||
|
||||
@@ -255,9 +275,11 @@
|
||||
$data = $data->map(function ($persetujuanPenawaran) {
|
||||
return [
|
||||
'id' => $persetujuanPenawaran->id,
|
||||
'nomor_registrasi' => $persetujuanPenawaran->permohonan->nomor_registrasi ?? $persetujuanPenawaran->penawaran->nomor_registrasi,
|
||||
'nama_debitur' => $persetujuanPenawaran->permohonan->debiture->name ?? $persetujuanPenawaran->penawaran->permohonan->debiture->name,
|
||||
'cabang' => $persetujuanPenawaran->permohonan->branch->name ?? $persetujuanPenawaran->penawaran->permohonan->branch->name,
|
||||
'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,
|
||||
@@ -267,11 +289,19 @@
|
||||
'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);
|
||||
})->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'));
|
||||
@@ -287,6 +317,7 @@
|
||||
'pageCount' => $pageCount,
|
||||
'page' => $currentPage,
|
||||
'totalCount' => $totalRecords,
|
||||
'totalNominalDiterima' => $totalNominalDiterima,
|
||||
'data' => $data,
|
||||
]);
|
||||
}
|
||||
@@ -301,7 +332,7 @@
|
||||
$query = PersetujuanPenawaran::query();
|
||||
|
||||
// Filter for penyelesaian (where memo_penyelesaian is not null)
|
||||
$query->whereHas('noc', function($q) {
|
||||
$query->whereDoesntHave('noc', function($q) {
|
||||
$q->whereNotNull('memo_penyelesaian');
|
||||
});
|
||||
|
||||
@@ -309,7 +340,15 @@
|
||||
if ($request->has('search') && !empty($request->get('search'))) {
|
||||
$search = $request->get('search');
|
||||
$query->where(function ($q) use ($search) {
|
||||
$q->orWhereRelation('penawaran', 'nomor_registrasi', 'LIKE', '%' . $search . '%');
|
||||
$q->orWhereRelation('penawaran', 'nomor_registrasi', 'LIKE', '%' . $search . '%')
|
||||
->orWhereRelation('permohonan', 'nomor_registrasi', 'LIKE', '%' . $search . '%')
|
||||
->orWhereRelation('permohonan.debiture','name', 'LIKE', '%' . $search . '%')
|
||||
->orWhereRelation('permohonan.jenisPenilaian', 'name', 'LIKE', '%' . $search . '%')
|
||||
->orWhere('nomor_tiket', 'LIKE', '%' . $search . '%'); $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 . '%');
|
||||
});
|
||||
}
|
||||
|
||||
@@ -341,9 +380,11 @@
|
||||
$data = $data->map(function ($persetujuanPenawaran) {
|
||||
return [
|
||||
'id' => $persetujuanPenawaran->id,
|
||||
'nomor_registrasi' => $persetujuanPenawaran->permohonan->nomor_registrasi ?? $persetujuanPenawaran->penawaran->nomor_registrasi,
|
||||
'nama_debitur' => $persetujuanPenawaran->permohonan->debiture->name ?? $persetujuanPenawaran->penawaran->permohonan->debiture->name,
|
||||
'cabang' => $persetujuanPenawaran->permohonan->branch->name ?? $persetujuanPenawaran->penawaran->permohonan->branch->name,
|
||||
'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,
|
||||
@@ -353,6 +394,7 @@
|
||||
'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,
|
||||
@@ -365,7 +407,15 @@
|
||||
true) : '-',
|
||||
'updated_at' => dateFormat($persetujuanPenawaran->updated_at, true),
|
||||
];
|
||||
})->sortBy('updated_at', 1);
|
||||
})->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'));
|
||||
@@ -381,6 +431,7 @@
|
||||
'pageCount' => $pageCount,
|
||||
'page' => $currentPage,
|
||||
'totalCount' => $totalRecords,
|
||||
'totalNominalDiterima' => $totalNominalDiterima,
|
||||
'data' => $data,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -3,26 +3,12 @@
|
||||
namespace Modules\Lpj\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Barryvdh\DomPDF\Facade\Pdf;
|
||||
use Exception;
|
||||
use Illuminate\Http\Request;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
use Modules\Location\Models\City;
|
||||
use Modules\Location\Models\District;
|
||||
use Modules\Location\Models\Province;
|
||||
use Modules\Location\Models\Village;
|
||||
use Modules\Lpj\Exports\PermohonanExport;
|
||||
use Modules\Lpj\Http\Requests\PermohonanRequest;
|
||||
use Modules\Lpj\Models\Branch;
|
||||
use Modules\Lpj\Models\Debiture;
|
||||
use Modules\Lpj\Models\DokumenJaminan;
|
||||
use Modules\Lpj\Models\JenisFasilitasKredit;
|
||||
use Modules\Lpj\Models\NilaiPlafond;
|
||||
use Modules\Lpj\Models\Permohonan;
|
||||
use Modules\Lpj\Models\PermohonanPembatalan;
|
||||
use Modules\Lpj\Models\StatusPermohonan;
|
||||
use Modules\Lpj\Models\TujuanPenilaian;
|
||||
use Modules\Lpj\Services\PermohonanHistoryService;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class PembatalanController extends Controller
|
||||
{
|
||||
@@ -92,6 +78,10 @@
|
||||
|
||||
// Retrieve data from the database
|
||||
$query = PermohonanPembatalan::query();
|
||||
if (Auth::user()->hasAnyRole(['pemohon-ao','pemohon-eo'])) {
|
||||
$query = $query->whereRelation('permohonan', 'branch_id', Auth::user()->branch_id);
|
||||
}
|
||||
|
||||
$query = $query->orderBy('created_at', 'desc');
|
||||
// Apply search filter if provided
|
||||
if ($request->has('search') && !empty($request->get('search'))) {
|
||||
|
||||
@@ -2,21 +2,17 @@
|
||||
|
||||
namespace Modules\Lpj\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Exception;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Modules\Lpj\Models\Noc;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
use Modules\Lpj\Http\Requests\PersetujuanPenawaranRequest;
|
||||
use Modules\Lpj\Models\PenawaranTender;
|
||||
use Modules\Lpj\Models\Bucok;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Modules\Lpj\Models\Permohonan;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Modules\Lpj\Models\PenawaranTender;
|
||||
use Modules\Lpj\Models\PersetujuanPenawaran;
|
||||
|
||||
// use Modules\Lpj\Models\JenisPenilaian;
|
||||
|
||||
// use Modules\Lpj\Models\Regions;
|
||||
use Modules\Lpj\Http\Requests\PersetujuanPenawaranRequest;
|
||||
|
||||
class PembayaranController extends Controller
|
||||
{
|
||||
@@ -27,6 +23,14 @@ class PembayaranController extends Controller
|
||||
return view('lpj::pembayaran.index');
|
||||
}
|
||||
|
||||
public function kurang(){
|
||||
return view('lpj::pembayaran.kurang');
|
||||
}
|
||||
|
||||
public function lebih(){
|
||||
return view('lpj::pembayaran.lebih');
|
||||
}
|
||||
|
||||
public function approval()
|
||||
{
|
||||
return view('lpj::pembayaran.approval');
|
||||
@@ -35,13 +39,16 @@ class PembayaranController extends Controller
|
||||
public function dataApprovalForDatatables(Request $request)
|
||||
{
|
||||
if (is_null($this->user) || !$this->user->can('noc.view')) {
|
||||
//abort(403, 'Sorry! You are not allowed to view persetujuan penawaran.');
|
||||
//abort(403, 'Sorry! You are not allowed to view persetujuan penawaran.');
|
||||
}
|
||||
|
||||
// Retrieve data from the database
|
||||
// Retrieve data from the database
|
||||
$query = PersetujuanPenawaran::query();
|
||||
if (Auth::user()->hasAnyRole(['pemohon-ao','pemohon-eo'])) {
|
||||
$query = $query->whereRelation('permohonan', 'branch_id', Auth::user()->branch_id);
|
||||
}
|
||||
|
||||
// Apply search filter if provided
|
||||
// Apply search filter if provided
|
||||
if ($request->has('search') && !empty($request->get('search'))) {
|
||||
$search = $request->get('search');
|
||||
$query->where(function ($q) use ($search) {
|
||||
@@ -49,29 +56,29 @@ class PembayaranController extends Controller
|
||||
});
|
||||
}
|
||||
|
||||
// Apply sorting if provided
|
||||
// Apply sorting if provided
|
||||
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
|
||||
$order = $request->get('sortOrder');
|
||||
$column = $request->get('sortField');
|
||||
$query->orderBy($column, $order);
|
||||
}
|
||||
|
||||
// Get the total count of records
|
||||
// Get the total count of records
|
||||
$totalRecords = $query->count();
|
||||
|
||||
// Apply pagination if provided
|
||||
// Apply pagination if provided
|
||||
if ($request->has('page') && $request->has('size')) {
|
||||
$page = $request->get('page');
|
||||
$size = $request->get('size');
|
||||
$offset = ($page - 1) * $size; // Calculate the offset
|
||||
$offset = ($page - 1) * $size; // Calculate the offset
|
||||
|
||||
$query->skip($offset)->take($size);
|
||||
}
|
||||
|
||||
// Get the filtered count of records
|
||||
// Get the filtered count of records
|
||||
$filteredRecords = $query->count();
|
||||
|
||||
// Get the data for the current page
|
||||
// Get the data for the current page
|
||||
$data = $query
|
||||
->with(
|
||||
[
|
||||
@@ -89,13 +96,13 @@ class PembayaranController extends Controller
|
||||
)->get();
|
||||
|
||||
|
||||
// Calculate the page count
|
||||
// Calculate the page count
|
||||
$pageCount = ceil($totalRecords / $request->get('size'));
|
||||
|
||||
// Calculate the current page number
|
||||
// Calculate the current page number
|
||||
$currentPage = $request->get('page', 1);
|
||||
|
||||
// Return the response data as a JSON object
|
||||
// Return the response data as a JSON object
|
||||
return response()->json([
|
||||
'draw' => $request->get('draw'),
|
||||
'recordsTotal' => $totalRecords,
|
||||
@@ -107,34 +114,130 @@ class PembayaranController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
public function create(){
|
||||
return view('lpj::pembayaran.create');
|
||||
}
|
||||
|
||||
public function edit($id)
|
||||
{
|
||||
$permohonan = Permohonan::find($id);
|
||||
|
||||
$persetujuanPenawaran = PersetujuanPenawaran::where('permohonan_id', $permohonan->id)->first();
|
||||
$req = request()->all();
|
||||
|
||||
if(isset($req['tiket'])){
|
||||
$persetujuanPenawaran = PersetujuanPenawaran::find($id);
|
||||
$permohonan = Permohonan::find($persetujuanPenawaran?->permohonan_id);
|
||||
} else {
|
||||
$permohonan = Permohonan::find($id);
|
||||
$persetujuanPenawaran = PersetujuanPenawaran::where('permohonan_id', $permohonan->id)->first();
|
||||
}
|
||||
|
||||
return view('lpj::pembayaran.form', compact('permohonan', 'persetujuanPenawaran'));
|
||||
}
|
||||
|
||||
public function editKurang($id){
|
||||
$noc = Noc::find($id);
|
||||
$permohonan = Permohonan::find($noc->permohonan_id);
|
||||
$persetujuanPenawaran = PersetujuanPenawaran::where('permohonan_id', $permohonan->id)->first();
|
||||
return view('lpj::pembayaran.form-kurang', compact('noc','permohonan','persetujuanPenawaran'));
|
||||
}
|
||||
|
||||
public function editLebih($id){
|
||||
$noc = Noc::find($id);
|
||||
$permohonan = Permohonan::find($noc->permohonan_id);
|
||||
$persetujuanPenawaran = PersetujuanPenawaran::where('permohonan_id', $permohonan->id)->first();
|
||||
return view('lpj::pembayaran.form-lebih', compact('noc','permohonan','persetujuanPenawaran'));
|
||||
}
|
||||
|
||||
public function store(PersetujuanPenawaranRequest $request)
|
||||
{
|
||||
$req = request()->all();
|
||||
|
||||
if(isset($req['type'])){
|
||||
if($req['type'] == 'create'){
|
||||
$data = [
|
||||
'nomor_tiket' => $req['nomor_tiket'] ?? '',
|
||||
'nominal_bayar' => $req['nominal_bayar'] ?? '',
|
||||
'catatan' => $req['catatan'] ?? ''
|
||||
];
|
||||
|
||||
if(request()->hasFile('bukti_bayar')){
|
||||
$folderPath = 'persetujuan_penawaran/bukti_bayar/' . $req['nomor_tiket'];
|
||||
$data['bukti_bayar'] = $request->file('bukti_bayar')->store($folderPath, 'public');
|
||||
}
|
||||
|
||||
$persetujuanPenawaran = PersetujuanPenawaran::create($data);
|
||||
$noc = [
|
||||
'persetujuan_penawaran_id' => $persetujuanPenawaran->id,
|
||||
'nomor_tiket' => $req['nomor_tiket'] ?? '',
|
||||
'debiture_id' => $req['debitur_id'] ?? '',
|
||||
'branch_id' => Auth::user()->branch_id,
|
||||
];
|
||||
$noc = Noc::create($noc);
|
||||
|
||||
$bucok = [
|
||||
'tanggal_penuh' => $persetujuanPenawaran->created_at ?? $noc->created_at,
|
||||
'tanggal' => $persetujuanPenawaran->created_at?->format('d') ?? $noc->created_at?->format('d'),
|
||||
'bulan' => $persetujuanPenawaran->created_at?->format('m') ?? $noc->created_at?->format('m'),
|
||||
'tahun' => $persetujuanPenawaran->created_at?->format('Y') ?? $noc->created_at?->format('Y'),
|
||||
'nomor_tiket' => $req['nomor_tiket'] ?? '',
|
||||
'nominal' => $req['nominal_bayar'] ?? '',
|
||||
'nominal_berjalan' => $req['nominal_bayar'] ?? '',
|
||||
'penyelesaian' => 'Belum Selesai',
|
||||
'nama_sub_direktorat' => $noc->branch?->name ?? '',
|
||||
'nama_direktorat_cabang' => $noc->branch?->name ?? '',
|
||||
];
|
||||
|
||||
Bucok::updateOrCreate([
|
||||
'nomor_tiket' => $req['nomor_tiket'] ?? '',
|
||||
], $bucok);
|
||||
|
||||
return redirect()
|
||||
->route('pembayaran.index')->with('success', 'Pembayaran berhasil disimpan.');
|
||||
}
|
||||
|
||||
if($req['type'] == 'kurang_bayar'){
|
||||
$noc = Noc::find($req['noc_id']);
|
||||
$noc->nominal_pelunasan = $req['nominal_pelunasan'];
|
||||
if (request()->hasFile('bukti_ksl_kurang_bayar')) {
|
||||
$folderPath = 'persetujuan_penawaran/bukti_ksl_kurang_bayar/' . $req['noc_id'];
|
||||
$noc->bukti_ksl_kurang_bayar = $request->file('bukti_ksl_kurang_bayar')->store($folderPath, 'public');
|
||||
}
|
||||
$noc->save();
|
||||
|
||||
$persetujuanPenawaran = PersetujuanPenawaran::find($noc->persetujuan_penawaran_id);
|
||||
$persetujuanPenawaran->bukti_ksl_kurang_bayar = $noc->bukti_ksl_kurang_bayar;
|
||||
$persetujuanPenawaran->nominal_kurang_bayar = $req['nominal_pelunasan'];
|
||||
$persetujuanPenawaran->save();
|
||||
return redirect()
|
||||
->route('pembayaran.kurang.index')->with('success', 'Pelunasan Kurang Bayar berhasil disimpan.');
|
||||
}
|
||||
|
||||
if($req['type'] == 'lebih_bayar'){
|
||||
$noc = Noc::find($req['noc_id']);
|
||||
if (request()->hasFile('bukti_ksl_lebih_bayar')) {
|
||||
$folderPath = 'persetujuan_penawaran/bukti_ksl_lebih_bayar/' . $req['noc_id'];
|
||||
$noc->bukti_ksl_lebih_bayar = $request->file('bukti_ksl_lebih_bayar')->store($folderPath, 'public');
|
||||
}
|
||||
$noc->save();
|
||||
|
||||
return redirect()
|
||||
->route('pembayaran.lebih.index')->with('success', 'Pengembalian Lebih Bayar berhasil disimpan.');
|
||||
}
|
||||
}
|
||||
|
||||
$validated = $request->validated();
|
||||
$validated['nominal_bayar'] = $req['nominal_bayar'] ?? 0;
|
||||
$validated['created_by'] = Auth::id();
|
||||
$validated['created_at'] = now();
|
||||
$validated['status'] = '0';
|
||||
|
||||
$persetujuanPenawaran = PersetujuanPenawaran::where('permohonan_id', $validated['permohonan_id'] ?? null)->first();
|
||||
$permohonan = Permohonan::find(request()->get('permohonan_id'));
|
||||
$permohonan = Permohonan::find(request()->get('permohonan_id'));
|
||||
if ($persetujuanPenawaran) {
|
||||
// if (isset($validated['penawaran_id'])) {
|
||||
|
||||
// $persetujuanPenawaran = PersetujuanPenawaran::create(
|
||||
// ['penawaran_id' => $validated['penawaran_id']],
|
||||
// $validated,
|
||||
// );
|
||||
|
||||
$persetujuanPenawaran->fill($validated);
|
||||
|
||||
if ($request->hasFile('bukti_bayar')) {
|
||||
$folderPath = 'persetujuan_penawaran/' . $validated['penawaran_id'];
|
||||
$folderPath = 'persetujuan_penawaran/' . $validated['penawaran_id'];
|
||||
$persetujuanPenawaran->bukti_bayar = $request->file('bukti_bayar')->store($folderPath, 'public');
|
||||
}
|
||||
|
||||
@@ -142,13 +245,22 @@ class PembayaranController extends Controller
|
||||
|
||||
$permohonan->approve_bayar_by = null;
|
||||
$permohonan->approve_bayar_at = null;
|
||||