update 2025-06-02

This commit is contained in:
arifal
2025-02-06 04:55:30 +07:00
parent 4eac6ab83d
commit d54edb7783
23 changed files with 1354 additions and 684 deletions

View File

@@ -12,42 +12,47 @@ class DashboardController extends Controller
use GlobalApiResponse;
public function businnessDocument(Request $request){
$businessData = DB::table('pbg_task')
->leftJoin('pbg_task_retributions', 'pbg_task.uuid', '=', 'pbg_task_retributions.pbg_task_uid')
->select(
DB::raw('COUNT(DISTINCT pbg_task.id) as task_count'),
DB::raw('SUM(pbg_task_retributions.nilai_retribusi_bangunan) as total_retribution')
)
$query = DB::table('pbg_task AS pt')
->leftJoin('pbg_task_google_sheet AS ptgs', 'pt.registration_number', '=', 'ptgs.no_registrasi')
->leftJoin('pbg_task_retributions AS ptr', 'pt.uuid', '=', 'ptr.pbg_task_uid') // Join ke pbg_task_retributions
->where(function ($query) {
$query->where("pbg_task.function_type", "LIKE", "sebagai tempat usaha%");
$query->whereRaw('LOWER(TRIM(ptgs.status_verifikasi)) != ?', [strtolower(trim('Selesai Verifikasi'))])
->orWhereNull('ptgs.status_verifikasi');
})
->where(function ($query) {
$query->whereRaw('LOWER(TRIM(pt.function_type)) = ?', [strtolower(trim('Sebagai Tempat Usaha'))]);
})
->selectRaw('COUNT(pt.id) AS total_data,
SUM(ptr.nilai_retribusi_bangunan) AS total_retribution') // Menambahkan SUM dari pbg_task_retributions
->first();
$taskCount = $businessData->task_count;
$taskTotal = $businessData->total_retribution;
$taskCount = $query->total_data;
$taskTotal = $query->total_retribution ?? 0;
$result = [
"count" => $taskCount,
"series" => [$taskCount],
"total" => $taskTotal
];
return $this->resSuccess($result);
}
public function nonBusinnessDocument(Request $request){
$businessData = DB::table('pbg_task')
->leftJoin('pbg_task_retributions', 'pbg_task.uuid', '=', 'pbg_task_retributions.pbg_task_uid')
->select(
DB::raw('COUNT(DISTINCT pbg_task.id) as task_count'),
DB::raw('SUM(pbg_task_retributions.nilai_retribusi_bangunan) as total_retribution')
)
$query = DB::table('pbg_task AS pt')
->leftJoin('pbg_task_google_sheet AS ptgs', 'pt.registration_number', '=', 'ptgs.no_registrasi')
->leftJoin('pbg_task_retributions AS ptr', 'pt.uuid', '=', 'ptr.pbg_task_uid') // Join ke pbg_task_retributions
->where(function ($query) {
$query->where("pbg_task.function_type", "NOT LIKE", "sebagai tempat usaha%")
->orWhereNull("pbg_task.function_type");
$query->whereRaw('LOWER(TRIM(ptgs.status_verifikasi)) != ?', [strtolower(trim('Selesai Verifikasi'))])
->orWhereNull('ptgs.status_verifikasi'); // Include NULL values
})
->where(function ($query) {
$query->whereRaw('LOWER(TRIM(pt.function_type)) != ?', [strtolower(trim('Sebagai Tempat Usaha'))])
->orWhereNull('pt.function_type'); // Include NULL values
})
->selectRaw('COUNT(pt.id) AS total_data,
SUM(ptr.nilai_retribusi_bangunan) AS total_retribution') // Menambahkan SUM dari pbg_task_retributions
->first();
$taskCount = $businessData->task_count;
$taskTotal = $businessData->total_retribution;
$taskCount = $query->total_data;
$taskTotal = $query->total_retribution ?? 0;
$result = [
"count" => $taskCount,
"series" => [$taskCount],
"total" => $taskTotal
];
return $this->resSuccess($result);
@@ -64,12 +69,54 @@ class DashboardController extends Controller
$taskTotal = $query->total_retribution;
$result = [
"count" => $taskCount,
"series" => [$taskCount],
"total" => $taskTotal
];
return $this->resSuccess($result);
}
public function verificationDocuments(){
$query = DB::table('pbg_task AS pt')
->leftJoin('pbg_task_google_sheet AS ptgs', 'pt.registration_number', '=', 'ptgs.no_registrasi')
->leftJoin('pbg_task_retributions AS ptr', 'pt.uuid', '=', 'ptr.pbg_task_uid') // Menambahkan join ke pbg_task_retributions
->whereRaw('LOWER(TRIM(ptgs.status_verifikasi)) = ?', [strtolower(trim('Selesai Verifikasi'))])
->selectRaw('COUNT(pt.id) AS total_data,
SUM(ptr.nilai_retribusi_bangunan) AS total_retribution')
->first();
$taskCount = $query->total_data;
$taskTotal = $query->total_retribution;
$result = [
"count"=> $taskCount,
"total"=> $taskTotal
];
return $this->resSuccess($result);
}
public function nonVerificationDocuments(){
$query = DB::table('pbg_task AS pt')
->leftJoin('pbg_task_google_sheet AS ptgs', 'pt.registration_number', '=', 'ptgs.no_registrasi')
->leftJoin('pbg_task_retributions AS ptr', 'pt.uuid', '=', 'ptr.pbg_task_uid') // Join tabel pbg_task_retributions
->where(function ($query) {
$query->whereRaw('LOWER(TRIM(ptgs.status_verifikasi)) != ?', [strtolower(trim('Selesai Verifikasi'))])
->orWhereNull('ptgs.status_verifikasi'); // Include NULL values
})
->selectRaw('COUNT(pt.id) AS total_data,
SUM(ptr.nilai_retribusi_bangunan) AS total_retribution') // Menambahkan SUM dari pbg_task_retributions
->first();
$taskCount = $query->total_data;
$taskTotal = $query->total_retribution ?? 0;
$result = [
"count"=> $taskCount,
"total"=> $taskTotal
];
return $this->resSuccess($result);
}
public function pbgTaskDocuments(Request $request){
$request->validate([
'status' => 'required|string'

View File

@@ -17,12 +17,12 @@ class GoogleSheetController extends Controller
*/
public function index()
{
$data = $this->googleSheetService->getSheetData("Sheet1!A2:BB2");
$dataCollection = $this->googleSheetService->getSheetDataCollection();
$result = [
"data" => $data,
"last_row" => $this->googleSheetService->getLastRow("Sheet1"),
"header" => $this->googleSheetService->getHeader("Sheet1"),
"last_column" => $this->googleSheetService->getLastColumn("Sheet1")
"last_row" => $this->googleSheetService->getLastRowByColumn("C"),
"last_column" => $this->googleSheetService->getLastColumn(),
"header" => $this->googleSheetService->getHeader(),
"data_collection" => $dataCollection
];
return response()->json($result);
}

View File

@@ -5,13 +5,18 @@ namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Http\Requests\PbgTaskMultiStepRequest;
use App\Models\PbgTask;
use App\Models\PbgTaskGoogleSheet;
use App\Services\GoogleSheetService;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class PbgTaskController extends Controller
{
/**
* Display a listing of the resource.
*/
protected $googleSheetService;
public function __construct(GoogleSheetService $googleSheetService){
$this->googleSheetService = $googleSheetService;
}
public function index()
{
//
@@ -87,4 +92,200 @@ class PbgTaskController extends Controller
"uuid" => $request->input("step1Form.uuid"),
]);
}
public function syncPbgFromGoogleSheet(){
try{
$totalRowCount = $this->googleSheetService->getLastRowByColumn("C");
$sheetData = $this->googleSheetService->getSheetDataCollection($totalRowCount);
$mapToUpsert = [];
$count = 0;
foreach($sheetData as $data){
$mapToUpsert[] =
[
'no_registrasi' => $data['no__registrasi'] ?? null,
'jenis_konsultasi' => $data['jenis_konsultasi'] ?? null,
'fungsi_bg' => $data['fungsi_bg'] ?? null,
'tgl_permohonan' => $this->convertToDate($data['tgl_permohonan']),
'status_verifikasi' => $data['status_verifikasi'] ?? null,
'status_permohonan' => $this->convertToDate($data['status_permohonan']),
'alamat_pemilik' => $data['alamat_pemilik'] ?? null,
'no_hp' => $data['no__hp'] ?? null,
'email' => $data['e_mail'] ?? null,
'tanggal_catatan' => $this->convertToDate($data['tanggal_catatan']),
'catatan_kekurangan_dokumen' => $data['catatan_kekurangan_dokumen'] ?? null,
'gambar' => $data['gambar'] ?? null,
'krk_kkpr' => $data['krk_kkpr'] ?? null,
'no_krk' => $data['no__krk'] ?? null,
'lh' => $data['lh'] ?? null,
'ska' => $data['ska'] ?? null,
'keterangan' => $data['keterangan'] ?? null,
'helpdesk' => $data['helpdesk'] ?? null,
'pj' => $data['pj'] ?? null,
'kepemilikan' => $data['kepemilikan'] ?? null,
'potensi_taru' => $data['potensi_taru'] ?? null,
'validasi_dinas' => $data['validasi_dinas'] ?? null,
'kategori_retribusi' => $data['kategori_retribusi'] ?? null,
'no_urut_ba_tpt' => $data['no__urut_ba_tpt__2024_0001_'] ?? null,
'tanggal_ba_tpt' => $this->convertToDate($data['tanggal_ba_tpt']),
'no_urut_ba_tpa' => $data['no__urut_ba_tpa'] ?? null,
'tanggal_ba_tpa' => $this->convertToDate($data['tanggal_ba_tpa']),
'no_urut_skrd' => $data['no__urut_skrd__2024_0001_'] ?? null,
'tanggal_skrd' => $this->convertToDate($data['tanggal_skrd']),
'ptsp' => $data['ptsp'] ?? null,
'selesai_terbit' => $data['selesai_terbit'] ?? null,
'tanggal_pembayaran' => $this->convertToDate($data['tanggal_pembayaran__yyyy_mm_dd_']),
'format_sts' => $data['format_sts'] ?? null,
'tahun_terbit' => (int) $data['tahun_terbit'] ?? null,
'tahun_berjalan' => (int) $data['tahun_berjalan'] ?? null,
'kelurahan' => $data['kelurahan'] ?? null,
'kecamatan' => $data['kecamatan'] ?? null,
'lb' => $this->convertToDecimal($data['lb']) ?? null,
'tb' => $this->convertToDecimal($data['tb']) ?? null,
'jlb' => (int) $data['jlb'] ?? null,
'unit' => (int) $data['unit'] ?? null,
'usulan_retribusi' => (int) $data['usulan_retribusi'] ?? null,
'nilai_retribusi_keseluruhan_simbg' => $this->convertToDecimal($data['nilai_retribusi_keseluruhan__simbg_']) ?? null,
'nilai_retribusi_keseluruhan_pad' => $this->convertToDecimal($data['nilai_retribusi_keseluruhan__pad_']) ?? null,
'denda' => $this->convertToDecimal($data['denda']) ?? null,
'latitude' => $data['latitude'] ?? null,
'longitude' => $data['longitude'] ?? null,
'nik_nib' => $data['nik_nib'] ?? null,
'dok_tanah' => $data['dok__tanah'] ?? null,
'temuan' => $data['temuan'] ?? null,
];
}
DB::beginTransaction();
$batchSize = 1000;
$chunks = array_chunk($mapToUpsert, $batchSize);
foreach($chunks as $chunk){
PbgTaskGoogleSheet::upsert($chunk, ["no_registrasi"],[
'jenis_konsultasi',
'nama_pemilik',
'lokasi_bg',
'fungsi_bg',
'nama_bangunan',
'tgl_permohonan',
'status_verifikasi',
'status_permohonan',
'alamat_pemilik',
'no_hp',
'email',
'tanggal_catatan',
'catatan_kekurangan_dokumen',
'gambar',
'krk_kkpr',
'no_krk',
'lh',
'ska',
'keterangan',
'helpdesk',
'pj',
'kepemilikan',
'potensi_taru',
'validasi_dinas',
'kategori_retribusi',
'no_urut_ba_tpt',
'tanggal_ba_tpt',
'no_urut_ba_tpa',
'tanggal_ba_tpa',
'no_urut_skrd',
'tanggal_skrd',
'ptsp',
'selesai_terbit',
'tanggal_pembayaran',
'format_sts',
'tahun_terbit',
'tahun_berjalan',
'kelurahan',
'kecamatan',
'lb',
'tb',
'jlb',
'unit',
'usulan_retribusi',
'nilai_retribusi_keseluruhan_simbg',
'nilai_retribusi_keseluruhan_pad',
'denda',
'latitude',
'longitude',
'nik_nib',
'dok_tanah',
'temuan',
]);
}
DB::commit();
return response()->json([
"success" => true,
"message" => "Data berhasil disimpan ke database"
], 200);
}catch(\Exception $ex){
DB::rollBack();
return response()->json([
"success" => false,
"message" => "Gagal menyimpan data",
"error" => $ex->getMessage()
], 500);
}
}
protected function convertToDecimal(?string $value): ?float
{
if (empty($value)) {
return null; // Return null if the input is empty
}
// Remove all non-numeric characters except comma and dot
$value = preg_replace('/[^0-9,\.]/', '', $value);
// If the number contains both dot (.) and comma (,)
if (strpos($value, '.') !== false && strpos($value, ',') !== false) {
$value = str_replace('.', '', $value); // Remove thousands separator
$value = str_replace(',', '.', $value); // Convert decimal separator to dot
}
// If only a dot is present (assumed as thousands separator)
elseif (strpos($value, '.') !== false) {
$value = str_replace('.', '', $value); // Remove all dots (treat as thousands separators)
}
// If only a comma is present (assumed as decimal separator)
elseif (strpos($value, ',') !== false) {
$value = str_replace(',', '.', $value); // Convert comma to dot (decimal separator)
}
// Ensure the value is numeric before returning
return is_numeric($value) ? (float) number_format((float) $value, 2, '.', '') : null;
}
protected function convertToInteger($value) {
// Check if the value is an empty string, and return null if true
if (trim($value) === "") {
return null;
}
// Otherwise, cast to integer
return (int) $value;
}
protected function convertToDate($dateString)
{
try {
// Check if the string is empty
if (empty($dateString)) {
return null;
}
// Try to parse the date string
$date = Carbon::parse($dateString);
// Return the Carbon instance
return $date->format('Y-m-d');
} catch (\Exception $e) {
// Return null if an error occurs during parsing
return null;
}
}
}

View File

@@ -16,7 +16,8 @@ class RequestAssignmentController extends Controller
{
$query = PbgTask::query()->orderBy('id', 'desc');
if($request->has('search') && !empty($request->get("search"))){
$query->where('name', 'LIKE', '%'.$request->get('search').'%');
$query->where('name', 'LIKE', '%'.$request->get('search').'%')
->orWhere('registration_number', 'LIKE', '%'.$request->get('search').'%');
}
return RequestAssignmentResouce::collection($query->paginate());
}

View File

@@ -7,6 +7,7 @@ use App\Models\DataSetting;
use Exception;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Request;
class DataSettingController extends Controller
{
@@ -103,4 +104,17 @@ class DataSettingController extends Controller
return response()->json(['success' => false, 'message' => 'Failed to delete item.'], 500);
}
}
public function getValueSetting(Request $request){
try{
$data = DataSetting::where('key', $request->key_name)->first();
return response()->json([
'success' => true,
'message' => "Successfully retrieved data",
"data"=> $data
]);
}catch(Exception $e){
return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
}
}
}

View File

@@ -0,0 +1,68 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class PbgTaskGoogleSheet extends Model
{
protected $table = "pbg_task_google_sheet";
protected $fillable = [
'jenis_konsultasi',
'no_registrasi',
'nama_pemilik',
'lokasi_bg',
'fungsi_bg',
'nama_bangunan',
'tgl_permohonan',
'status_verifikasi',
'status_permohonan',
'alamat_pemilik',
'no_hp',
'email',
'tanggal_catatan',
'catatan_kekurangan_dokumen',
'gambar',
'krk_kkpr',
'no_krk',
'lh',
'ska',
'keterangan',
'helpdesk',
'pj',
'kepemilikan',
'potensi_taru',
'validasi_dinas',
'kategori_retribusi',
'no_urut_ba_tpt',
'tanggal_ba_tpt',
'no_urut_ba_tpa',
'tanggal_ba_tpa',
'no_urut_skrd',
'tanggal_skrd',
'ptsp',
'selesai_terbit',
'tanggal_pembayaran',
'format_sts',
'tahun_terbit',
'tahun_berjalan',
'kelurahan',
'kecamatan',
'lb',
'tb',
'jlb',
'unit',
'usulan_retribusi',
'nilai_retribusi_keseluruhan_simbg',
'nilai_retribusi_keseluruhan_pad',
'denda',
'latitude',
'longitude',
'nik_nib',
'dok_tanah',
'temuan',
];
}

View File

@@ -59,6 +59,8 @@ class ServiceSIMBG
$res = $clientHelper->get($url, $headers);
Log::info("response index integration", ['res' => $res]);
if (empty($res->original['success']) || !$res->original['success']) {
// Log error
Log::error("API response indicates failure", ['url' => $url, 'uuid' => $uuid]);
@@ -128,9 +130,10 @@ class ServiceSIMBG
$savedCount = $failedCount = 0;
for ($currentPage = 1; $currentPage <= $totalPage; $currentPage++) {
for ($currentPage = 50; $currentPage <= $totalPage; $currentPage++) {
$pageUrl = "/api/pbg/v1/list/?page={$currentPage}&size={$this->fetch_per_page}&sort=ASC";
$getToken = $this->getToken();
Log::info("response index integration", ['currentPage' => $currentPage]);
if (empty($getToken->original['data']['token']['access'])) {
$importDatasource->update([
'status' => ImportDatasourceStatus::Failed->value,
@@ -227,6 +230,8 @@ class ServiceSIMBG
$res = $clientHelper->get($url, $headers);
Log::info("response task detail submit", ['res' => $res]);
if (empty($res->original['success']) || !$res->original['success']) {
// Log error
Log::error("API response indicates failure", ['url' => $url, 'uuid' => $uuid]);

View File

@@ -4,7 +4,6 @@ namespace App\Services;
use Google_Client;
use Google_Service_Sheets;
use Google_Service_Sheets_Sheet;
class GoogleSheetService
{
@@ -33,35 +32,100 @@ class GoogleSheetService
return $response->getValues();
}
public function getLastRow($sheetName = "Sheet1"){
public function getLastRowByColumn($column = "A")
{
// Ambil spreadsheet
$spreadsheet = $this->service->spreadsheets->get($this->spreadsheetID);
$sheets = $spreadsheet->getSheets();
foreach ($sheets as $sheet) {
if ($sheet->getProperties()->getTitle() === $sheetName) {
return [
'rowCount' => $sheet->getProperties()->getGridProperties()->getRowCount(),
'columnCount' => $sheet->getProperties()->getGridProperties()->getColumnCount(),
];
}
}
}
public function getHeader($sheetName = "Sheet1", $range = "Sheet1!1:1"){
$response = $this->service->spreadsheets_values->get($this->spreadsheetID, $range);
$values = $response->getValues();
return !empty($values) && isset($values[0]) ? $values[0] : [];
}
if (!empty($sheets)) {
// Ambil nama sheet pertama dengan benar
$firstSheetTitle = $sheets[0]->getProperties()->getTitle();
public function getLastColumn($sheetName = 'Sheet1')
{
$range = "{$sheetName}!1:1";
// ✅ Format range harus benar!
$range = "{$firstSheetTitle}!{$column}:{$column}";
// Ambil data dari kolom yang diminta
$response = $this->service->spreadsheets_values->get($this->spreadsheetID, $range);
$values = $response->getValues();
if (!empty($values) && isset($values[0])) {
return count($values[0]);
// Cek nilai terakhir yang tidak kosong
$lastRow = 0;
if (!empty($values)) {
foreach ($values as $index => $row) {
if (!empty($row[0])) { // Jika ada data, update lastRow
$lastRow = $index + 1;
}
}
}
return $lastRow;
}
return 0;
}
public function getHeader()
{
$spreadsheet = $this->service->spreadsheets->get($this->spreadsheetID);
$sheets = $spreadsheet->getSheets();
// Ambil nama sheet pertama
$firstSheetTitle = $sheets[0]->getProperties()->getTitle();
// Ambil data dari baris pertama (header)
$range = "{$firstSheetTitle}!1:1";
$response = $this->service->spreadsheets_values->get($this->spreadsheetID, $range);
$values = $response->getValues();
// Kembalikan header (baris pertama)
return !empty($values) ? $values[0] : [];
}
public function getLastColumn()
{
$spreadsheet = $this->service->spreadsheets->get($this->spreadsheetID);
$sheets = $spreadsheet->getSheets();
// Ambil nama sheet pertama
$firstSheetTitle = $sheets[0]->getProperties()->getTitle();
// Ambil baris pertama untuk mendapatkan jumlah kolom yang terisi
$range = "{$firstSheetTitle}!1:1";
$response = $this->service->spreadsheets_values->get($this->spreadsheetID, $range);
$values = $response->getValues();
// Hitung jumlah kolom yang memiliki nilai
return !empty($values) ? count(array_filter($values[0], fn($value) => $value !== "")) : 0;
}
public function getSheetDataCollection($totalRow = 10){
$spreadsheet = $this->service->spreadsheets->get($this->spreadsheetID);
$sheets = $spreadsheet->getSheets();
$firstSheetTitle = $sheets[0]->getProperties()->getTitle();
$header = $this->getHeader();
$header = array_map(function($columnHeader) {
// Trim spaces first, then replace non-alphanumeric characters with underscores
$columnHeader = trim($columnHeader);
return strtolower(preg_replace('/[^A-Za-z0-9_]/', '_', $columnHeader));
}, $header);
$range = "{$firstSheetTitle}!2:{$totalRow}";
$response = $this->service->spreadsheets_values->get($this->spreadsheetID, $range);
$values = $response->getValues();
$mappedData = [];
if (!empty($values)) {
foreach ($values as $row) {
$rowData = [];
foreach ($header as $index => $columnHeader) {
// Map header to the corresponding value from the row
$rowData[$columnHeader] = isset($row[$index]) ? $row[$index] : null;
}
$mappedData[] = $rowData;
}
}
return $mappedData;
}
}

View File

@@ -0,0 +1,80 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('pbg_task_google_sheet', function (Blueprint $table) {
$table->id();
$table->string('jenis_konsultasi')->nullable();
$table->string('no_registrasi')->nullable()->unique();
$table->string('nama_pemilik')->nullable();
$table->text('lokasi_bg')->nullable();
$table->string('fungsi_bg')->nullable();
$table->string('nama_bangunan')->nullable();
$table->date('tgl_permohonan')->nullable();
$table->string('status_verifikasi')->nullable();
$table->string('status_permohonan')->nullable();
$table->text('alamat_pemilik')->nullable();
$table->string('no_hp')->nullable();
$table->string('email')->nullable();
$table->date('tanggal_catatan')->nullable();
$table->text('catatan_kekurangan_dokumen')->nullable();
$table->string('gambar')->nullable();
$table->string('krk_kkpr')->nullable();
$table->string('no_krk')->nullable();
$table->string('lh')->nullable();
$table->string('ska')->nullable();
$table->text('keterangan')->nullable();
$table->string('helpdesk')->nullable();
$table->string('pj')->nullable();
$table->string('kepemilikan')->nullable();
$table->string('potensi_taru')->nullable();
$table->string('validasi_dinas')->nullable();
$table->string('kategori_retribusi')->nullable();
$table->string('no_urut_ba_tpt')->nullable();
$table->date('tanggal_ba_tpt')->nullable();
$table->string('no_urut_ba_tpa')->nullable();
$table->date('tanggal_ba_tpa')->nullable();
$table->string('no_urut_skrd')->nullable();
$table->date('tanggal_skrd')->nullable();
$table->string('ptsp')->nullable();
$table->string('selesai_terbit')->nullable();
$table->date('tanggal_pembayaran')->nullable();
$table->string('format_sts')->nullable();
$table->integer('tahun_terbit')->nullable();
$table->integer('tahun_berjalan')->nullable();
$table->string('kelurahan')->nullable();
$table->string('kecamatan')->nullable();
$table->decimal('lb', 20,2)->nullable();
$table->decimal('tb', 20, 2)->nullable();
$table->integer('jlb')->nullable();
$table->integer('unit')->nullable();
$table->integer('usulan_retribusi')->nullable();
$table->decimal('nilai_retribusi_keseluruhan_simbg', 20, 2)->nullable();
$table->decimal('nilai_retribusi_keseluruhan_pad', 20, 2)->nullable();
$table->decimal('denda', 20, 2)->nullable();
$table->string('latitude')->nullable();
$table->string('longitude')->nullable();
$table->string('nik_nib')->nullable();
$table->string('dok_tanah')->nullable();
$table->text('temuan')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('pbg_task_google_sheet');
}
};

View File

@@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('pbg_task', function (Blueprint $table) {
$table->string('uuid')->nullable()->unique()->change();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('pbg_task', function (Blueprint $table) {
$table->string('uuid')->nullable()->change();
});
}
};

View File

@@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('pbg_task_index_integrations', function (Blueprint $table) {
$table->string('pbg_task_uid')->unique()->change();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('pbg_task_index_integrations', function (Blueprint $table) {
$table->string('pbg_task_uid')->unique()->change();
});
}
};

View File

@@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('pbg_task_retributions', function (Blueprint $table) {
$table->string('detail_id')->unique()->change();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('pbg_task_retributions', function (Blueprint $table) {
$table->string('detail_id')->unique()->change();
});
}
};

14
package-lock.json generated
View File

@@ -6,6 +6,7 @@
"": {
"dependencies": {
"apexcharts": "^3.44.2",
"big.js": "^6.2.2",
"bootstrap": "^5.3.3",
"countup.js": "^2.3.2",
"dropzone": "^5.9.0",
@@ -477,6 +478,19 @@
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true
},
"node_modules/big.js": {
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/big.js/-/big.js-6.2.2.tgz",
"integrity": "sha512-y/ie+Faknx7sZA5MfGA2xKlu0GDv8RWrXGsmlteyJQ2lvoKv9GBK/fpRMc2qlSoBAgNxrixICFCBefIq8WCQpQ==",
"license": "MIT",
"engines": {
"node": "*"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/bigjs"
}
},
"node_modules/binary-extensions": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",

View File

@@ -17,6 +17,7 @@
},
"dependencies": {
"apexcharts": "^3.44.2",
"big.js": "^6.2.2",
"bootstrap": "^5.3.3",
"countup.js": "^2.3.2",
"dropzone": "^5.9.0",

View File

@@ -4,6 +4,8 @@ use Illuminate\Http\Request;
define('LARAVEL_START', microtime(true));
ini_set('max_execution_time',14400);
// Determine if the application is in maintenance mode...
if (file_exists($maintenance = __DIR__.'/../storage/framework/maintenance.php')) {
require $maintenance;

View File

@@ -1,13 +1,83 @@
import ApexCharts from "apexcharts";
import Big from "big.js";
import GlobalConfig, { addThousandSeparators } from "../global-config.js";
class BigData {
async init() {
try{
this.resultDataTotal = await this.getTotalAllTask();
try {
this.totalTargetPAD = await this.getTargetPAD();
this.resultDataTotal = await this.getDataTotalPotensi();
this.dataVerification = await this.getDataVerfication();
this.dataNonVerification = await this.getDataNonVerfication();
this.dataBusiness = await this.getDataBusiness();
this.dataNonBusiness = await this.getDataNonBusiness();
if (!this.resultDataTotal) {
// total potensi
this.bigTargetPAD = new Big(this.totalTargetPAD ?? 0);
this.bigTotalPotensi = new Big(this.resultDataTotal.totalData ?? 0);
this.resultPercentage = 0;
if (this.bigTotalPotensi > 0 && this.bigTargetPAD > 0) {
this.resultPercentage = this.bigTotalPotensi
.div(this.bigTargetPAD)
.times(100)
.toFixed(2);
if (this.resultPercentage > 100) {
this.resultPercentage = 100;
}
}
// kekurangan potensi
this.totalKekuranganPotensi = new Big(
this.totalTargetPAD - this.bigTotalPotensi
);
this.percentageKekuranganPotensi =
this.totalKekuranganPotensi <= 0 || this.totalTargetPAD <= 0
? 0
: this.totalKekuranganPotensi
.div(this.bigTargetPAD)
.times(100)
.toFixed(2);
// non-verification documents
this.bigTotalNonVerification = new Big(
this.dataNonVerification.total
);
this.percentageResultNonVerification = this.bigTotalNonVerification
.div(this.bigTotalPotensi)
.times(100)
.toFixed(2);
// verification documents
this.bigTotalVerification = new Big(this.dataVerification.total);
this.percetageResultVerification =
this.bigTotalVerification <= 0 || this.bigTotalPotensi <= 0
? 0
: this.bigTotalVerification
.div(this.bigTargetPAD)
.times(100)
.toFixed(2);
// business documents
this.bigTotalBusiness = new Big(this.dataBusiness.total);
this.percentageResultBusiness =
this.bigTotalNonVerification <= 0
? 0
: this.bigTotalBusiness
.div(this.bigTotalNonVerification)
.times(100)
.toFixed(2);
// non-business documents
this.bigTotalNonBusiness = new Big(this.dataNonBusiness.total);
this.percentageResultNonBusiness =
this.bigTotalNonBusiness <= 0
? 0
: this.bigTotalNonBusiness
.div(this.bigTotalNonVerification)
.times(100)
.toFixed(2);
if (!this.totalTargetPAD) {
console.error("Failed to load chart data");
return;
}
@@ -15,29 +85,34 @@ class BigData {
this.initChartTargetPAD();
this.initChartUsaha();
this.initChartNonUsaha();
this.initChartStatus1();
this.initChartStatus2();
this.initChartStatus3();
this.initChartStatus4();
this.initChartStatus5();
this.initChartStatus6();
this.initChartStatus7();
this.initChartStatus20();
this.initChartStatus24();
}catch(e){
this.initChartTotalPotensi();
this.initChartVerificationDocuments();
this.initChartNonVerificationDocuments();
this.initChartKekuranganPotensi();
this.initChartRealisasiTerbitPBG();
this.initChartMenungguKlikDPMPTSP();
this.initChartProsesDinasTeknis();
this.initChartPotensiTataRuang();
} catch (e) {
console.error(e);
}
}
async getTotalAllTask() {
async getDataTotalPotensi() {
try {
const response = await fetch(`${GlobalConfig.apiHost}/api/all-task-documents`, {
const response = await fetch(
`${GlobalConfig.apiHost}/api/all-task-documents`,
{
credentials: "include",
headers: {
Authorization: `Bearer ${document.querySelector("meta[name='api-token']").content}`,
Authorization: `Bearer ${
document.querySelector("meta[name='api-token']")
.content
}`,
"Content-Type": "application/json",
},
});
}
);
if (!response.ok) {
console.error("Network response was not ok", response);
@@ -47,398 +122,407 @@ class BigData {
return {
seriesData: data.data.series,
countData: data.data.count,
totalData: data.data.total
totalData: data.data.total,
};
} catch (error) {
console.error("Error fetching chart data:", error);
return null; // Mengembalikan null jika terjadi error
return null;
}
}
async getTargetPAD() {
try {
const response = await fetch(
`${GlobalConfig.apiHost}/api/api-data-settings?search=target_pad`,
{
credentials: "include",
headers: {
Authorization: `Bearer ${
document.querySelector("meta[name='api-token']")
.content
}`,
"Content-Type": "application/json",
},
}
);
if (!response.ok) {
console.error("Network response was not ok", response);
}
const data = await response.json();
return data.data[0].value;
} catch (error) {
console.error("Error fetching chart data:", error);
return null;
}
}
async getDataVerfication() {
try {
const response = await fetch(
`${GlobalConfig.apiHost}/api/verification-documents`,
{
credentials: "include",
headers: {
Authorization: `Bearer ${
document.querySelector("meta[name='api-token']")
.content
}`,
"Content-Type": "application/json",
},
}
);
if (!response.ok) {
console.error("Network response was not ok", response);
}
const data = await response.json();
return {
count: data.data.count,
total: data.data.total,
};
} catch (error) {
console.error("Error fetching chart data:", error);
return null;
}
}
async getDataNonVerfication() {
try {
const response = await fetch(
`${GlobalConfig.apiHost}/api/non-verification-documents`,
{
credentials: "include",
headers: {
Authorization: `Bearer ${
document.querySelector("meta[name='api-token']")
.content
}`,
"Content-Type": "application/json",
},
}
);
if (!response.ok) {
console.error("Network response was not ok", response);
}
const data = await response.json();
return {
count: data.data.count,
total: data.data.total,
};
} catch (error) {
console.error("Error fetching chart data:", error);
return null;
}
}
async getDataBusiness() {
try {
const response = await fetch(
`${GlobalConfig.apiHost}/api/business-documents`,
{
credentials: "include",
headers: {
Authorization: `Bearer ${
document.querySelector("meta[name='api-token']")
.content
}`,
"Content-Type": "application/json",
},
}
);
if (!response.ok) {
console.error("Network response was not ok", response);
}
const data = await response.json();
return {
count: data.data.count,
total: data.data.total,
};
} catch (error) {
console.error("Error fetching chart data:", error);
return null;
}
}
async getDataNonBusiness() {
try {
const response = await fetch(
`${GlobalConfig.apiHost}/api/non-business-documents`,
{
credentials: "include",
headers: {
Authorization: `Bearer ${
document.querySelector("meta[name='api-token']")
.content
}`,
"Content-Type": "application/json",
},
}
);
if (!response.ok) {
console.error("Network response was not ok", response);
}
const data = await response.json();
return {
count: data.data.count,
total: data.data.total,
};
} catch (error) {
console.error("Error fetching chart data:", error);
return null;
}
}
initChartTargetPAD() {
const total = this.resultDataTotal.totalData;
const count = this.resultDataTotal.countData;
document.querySelectorAll('.document-count.chart-all-task').forEach((element) => {
element.innerText = `${count}`;
let totalPad = 0;
fetch(
`${GlobalConfig.apiHost}/api/api-data-settings?search=target_pad`,
{
credentials: "include",
headers: {
Authorization: `Bearer ${
document.querySelector("meta[name='api-token']").content
}`,
"Content-Type": "application/json",
},
}
)
.then((response) => {
if (!response.ok) {
throw new Error("Network response was not ok");
}
return response.json();
})
.then((data) => {
totalPad = data.data[0].value;
document
.querySelectorAll(".document-count.chart-target-pad")
.forEach((element) => {
element.innerText = ``;
});
document.querySelectorAll('.document-total.chart-all-task').forEach((element) => {
element.innerText = `Rp.${addThousandSeparators(total)}`;
document
.querySelectorAll(".document-total.chart-target-pad")
.forEach((element) => {
element.innerText = `Rp.${addThousandSeparators(
totalPad
)}`;
});
document.querySelectorAll('.small-percentage.chart-all-task').forEach((element) => {
document
.querySelectorAll(".small-percentage.chart-target-pad")
.forEach((element) => {
element.innerText = `${100}%`;
});
})
.catch((error) => {
console.error("Error fetching target_pad:", error);
});
}
initChartTotalPotensi() {
const countAll = this.resultDataTotal.countData ?? 0;
document
.querySelectorAll(".document-count.chart-total-potensi")
.forEach((element) => {
element.innerText = `${countAll}`;
});
document
.querySelectorAll(".document-total.chart-total-potensi")
.forEach((element) => {
element.innerText = `Rp.${addThousandSeparators(
this.bigTotalPotensi.toString()
)}`;
});
document
.querySelectorAll(".small-percentage.chart-total-potensi")
.forEach((element) => {
element.innerText = `${this.resultPercentage}%`;
});
}
initChartVerificationDocuments() {
document
.querySelectorAll(".document-count.chart-berkas-terverifikasi")
.forEach((element) => {
element.innerText = `${this.dataVerification.count}`;
});
document
.querySelectorAll(".document-total.chart-berkas-terverifikasi")
.forEach((element) => {
element.innerText = `Rp.${addThousandSeparators(
this.bigTotalVerification.toString()
)}`;
});
document
.querySelectorAll(".small-percentage.chart-berkas-terverifikasi")
.forEach((element) => {
element.innerText = `${this.percetageResultVerification}%`;
});
}
initChartNonVerificationDocuments() {
document
.querySelectorAll(
".document-count.chart-berkas-belum-terverifikasi"
)
.forEach((element) => {
element.innerText = `${this.dataNonVerification.count}`;
});
document
.querySelectorAll(
".document-total.chart-berkas-belum-terverifikasi"
)
.forEach((element) => {
element.innerText = `Rp.${addThousandSeparators(
this.bigTotalNonVerification.toString()
)}`;
});
document
.querySelectorAll(
".small-percentage.chart-berkas-belum-terverifikasi"
)
.forEach((element) => {
element.innerText = `${this.percentageResultNonVerification}%`;
});
}
initChartUsaha() {
fetch(`${GlobalConfig.apiHost}/api/business-documents`,{
credentials: "include",
headers: {
Authorization: `Bearer ${document.querySelector("meta[name='api-token']").content}`,
"Content-Type": "application/json",
},
})
.then((response) => {
if (!response.ok) {
throw new Error("Network response was not ok");
}
return response.json();
})
.then((data) => {
// Pastikan this.resultDataTotal sudah ada
if (!this.resultDataTotal) {
console.error("Error: resultDataTotal is undefined");
return;
}
const totalAll = this.resultDataTotal.totalData ?? 0;
const countAll = this.resultDataTotal.countData ?? 0;
const countUsaha = data?.data?.count ?? 0;
const totalUsaha = data?.data?.total ?? 0;
// Perbaikan perhitungan persentase
let resultPercentage = 0;
if (countUsaha > 0) {
resultPercentage = (countUsaha / countAll) * 100;
if (resultPercentage > 100) {
resultPercentage = 100; // Batasi maksimum 100%
}
}
document.querySelectorAll('.document-count.chart-business').forEach((element) => {
element.innerText = `${countUsaha}`;
document
.querySelectorAll(".document-count.chart-business")
.forEach((element) => {
element.innerText = `${this.dataBusiness.count}`;
});
document.querySelectorAll('.document-total.chart-business').forEach((element) => {
element.innerText = `Rp.${addThousandSeparators(totalUsaha)}`;
document
.querySelectorAll(".document-total.chart-business")
.forEach((element) => {
element.innerText = `Rp.${addThousandSeparators(
this.bigTotalBusiness.toString()
)}`;
});
document.querySelectorAll('.small-percentage.chart-business').forEach((element) => {
element.innerText = `${resultPercentage.toFixed(2)}%`;
});
})
.catch((error) => {
console.error("error fetching chart dara : ", error);
document
.querySelectorAll(".small-percentage.chart-business")
.forEach((element) => {
element.innerText = `${this.percentageResultBusiness}%`;
});
}
initChartNonUsaha() {
fetch(`${GlobalConfig.apiHost}/api/non-business-documents`, {
credentials: "include",
headers: {
Authorization: `Bearer ${document.querySelector("meta[name='api-token']").content}`,
"Content-Type": "application/json",
},
})
.then((response) => {
if (!response.ok) {
throw new Error("Network response was not ok");
}
return response.json();
})
.then((data) => {
// Pastikan this.resultDataTotal sudah ada
if (!this.resultDataTotal) {
console.error("Error: resultDataTotal is undefined");
return;
}
const totalAll = this.resultDataTotal.totalData ?? 0;
const countAll = this.resultDataTotal.countData ?? 0;
const countUsaha = data?.data?.count ?? 0;
const totalUsaha = data?.data?.total ?? 0;
// Perbaikan perhitungan persentase
let resultPercentage = 0;
if (countUsaha > 0) {
resultPercentage = (countUsaha / countAll) * 100;
if (resultPercentage > 100) {
resultPercentage = 100; // Batasi maksimum 100%
}
}
document.querySelectorAll('.document-count.chart-non-business').forEach((element) => {
element.innerText = `${data.data.count}`;
document
.querySelectorAll(".document-count.chart-non-business")
.forEach((element) => {
element.innerText = `${this.dataNonBusiness.count}`;
});
document.querySelectorAll('.document-total.chart-non-business').forEach((element) => {
element.innerText = `Rp.${addThousandSeparators(data.data.total)}`;
document
.querySelectorAll(".document-total.chart-non-business")
.forEach((element) => {
element.innerText = `Rp.${addThousandSeparators(
this.bigTotalNonBusiness.toString()
)}`;
});
document.querySelectorAll('.small-percentage.chart-non-business').forEach((element) => {
element.innerText = `${resultPercentage.toFixed(2)}%`;
});
})
.catch((error) => {
console.error("error fetching chart dara : ", error);
document
.querySelectorAll(".small-percentage.chart-non-business")
.forEach((element) => {
element.innerText = `${this.percentageResultNonBusiness}%`;
});
}
initChartStatus1(){
fetch(`${GlobalConfig.apiHost}/api/pbg-task-documents?status=1`, {
credentials: "include",
headers: {
Authorization: `Bearer ${document.querySelector("meta[name='api-token']").content}`,
"Content-Type": "application/json",
}
})
.then((response) => {
if (!response.ok) {
throw new Error("Network response was not ok");
}
return response.json();
})
.then((data) => {
const seriesData = data.data.series;
// document.getElementById(
// "countStatus1"
// ).innerText = `${data.data.count} Berkas`;
// document.getElementById(
// "totalStatus1"
// ).innerText = `Rp.${addThousandSeparators(data.data.total)}`;
})
.catch((error) => {
console.error("error fetching chart dara : ", error);
initChartKekuranganPotensi() {
document
.querySelectorAll(".document-count.chart-kekurangan-potensi")
.forEach((element) => {
element.innerText = ``;
});
document
.querySelectorAll(".document-total.chart-kekurangan-potensi")
.forEach((element) => {
element.innerText = `Rp.${addThousandSeparators(
this.totalKekuranganPotensi.toString()
)}`;
});
document
.querySelectorAll(".small-percentage.chart-kekurangan-potensi")
.forEach((element) => {
element.innerText = `${this.percentageKekuranganPotensi}%`;
});
}
initChartStatus2(){
fetch(`${GlobalConfig.apiHost}/api/pbg-task-documents?status=2`, {
credentials: "include",
headers: {
Authorization: `Bearer ${document.querySelector("meta[name='api-token']").content}`,
"Content-Type": "application/json",
}
})
.then((response) => {
if (!response.ok) {
throw new Error("Network response was not ok");
}
return response.json();
})
.then((data) => {
const seriesData = data.data.series;
// document.getElementById(
// "countStatus2"
// ).innerText = `${data.data.count} Berkas`;
// document.getElementById(
// "totalStatus2"
// ).innerText = `Rp.${addThousandSeparators(data.data.total)}`;
})
.catch((error) => {
console.error("error fetching chart dara : ", error);
initChartRealisasiTerbitPBG() {
document
.querySelectorAll(".document-count.chart-realisasi-tebit-pbg")
.forEach((element) => {
element.innerText = `0`;
});
document
.querySelectorAll(".document-total.chart-realisasi-tebit-pbg")
.forEach((element) => {
element.innerText = `Rp.${addThousandSeparators("0.00")}`;
});
document
.querySelectorAll(".small-percentage.chart-realisasi-tebit-pbg")
.forEach((element) => {
element.innerText = `0.00%`;
});
}
initChartStatus3(){
fetch(`${GlobalConfig.apiHost}/api/pbg-task-documents?status=3`, {
credentials: "include",
headers: {
Authorization: `Bearer ${document.querySelector("meta[name='api-token']").content}`,
"Content-Type": "application/json",
}
})
.then((response) => {
if (!response.ok) {
throw new Error("Network response was not ok");
}
return response.json();
})
.then((data) => {
const seriesData = data.data.series;
// document.getElementById(
// "countStatus3"
// ).innerText = `${data.data.count} Berkas`;
// document.getElementById(
// "totalStatus3"
// ).innerText = `Rp.${addThousandSeparators(data.data.total)}`;
})
.catch((error) => {
console.error("error fetching chart dara : ", error);
initChartMenungguKlikDPMPTSP() {
document
.querySelectorAll(".document-count.chart-menunggu-klik-dpmptsp")
.forEach((element) => {
element.innerText = `${0}`;
});
document
.querySelectorAll(".document-total.chart-menunggu-klik-dpmptsp")
.forEach((element) => {
element.innerText = `Rp.${addThousandSeparators("0.00")}`;
});
document
.querySelectorAll(".small-percentage.chart-menunggu-klik-dpmptsp")
.forEach((element) => {
element.innerText = `0.00%`;
});
}
initChartStatus4(){
fetch(`${GlobalConfig.apiHost}/api/pbg-task-documents?status=4`, {
credentials: "include",
headers: {
Authorization: `Bearer ${document.querySelector("meta[name='api-token']").content}`,
"Content-Type": "application/json",
}
})
.then((response) => {
if (!response.ok) {
throw new Error("Network response was not ok");
}
return response.json();
})
.then((data) => {
const seriesData = data.data.series;
// document.getElementById(
// "countStatus4"
// ).innerText = `${data.data.count} Berkas`;
// document.getElementById(
// "totalStatus4"
// ).innerText = `Rp.${addThousandSeparators(data.data.total)}`;
})
.catch((error) => {
console.error("error fetching chart dara : ", error);
initChartProsesDinasTeknis() {
document
.querySelectorAll(".document-count.chart-proses-dinas-teknis")
.forEach((element) => {
element.innerText = `${0}`;
});
document
.querySelectorAll(".document-total.chart-proses-dinas-teknis")
.forEach((element) => {
element.innerText = `Rp.${addThousandSeparators("0.00")}`;
});
document
.querySelectorAll(".small-percentage.chart-proses-dinas-teknis")
.forEach((element) => {
element.innerText = `0.00%`;
});
}
initChartStatus5(){
fetch(`${GlobalConfig.apiHost}/api/pbg-task-documents?status=5`, {
credentials: "include",
headers: {
Authorization: `Bearer ${document.querySelector("meta[name='api-token']").content}`,
"Content-Type": "application/json",
}
})
.then((response) => {
if (!response.ok) {
throw new Error("Network response was not ok");
}
return response.json();
})
.then((data) => {
const seriesData = data.data.series;
// document.getElementById(
// "countStatus5"
// ).innerText = `${data.data.count} Berkas`;
// document.getElementById(
// "totalStatus5"
// ).innerText = `Rp.${addThousandSeparators(data.data.total)}`;
})
.catch((error) => {
console.error("error fetching chart dara : ", error);
initChartPotensiTataRuang() {
document
.querySelectorAll(".document-count.chart-potensi-tata-ruang")
.forEach((element) => {
element.innerText = `${0}`;
});
}
initChartStatus6(){
fetch(`${GlobalConfig.apiHost}/api/pbg-task-documents?status=6`, {
credentials: "include",
headers: {
Authorization: `Bearer ${document.querySelector("meta[name='api-token']").content}`,
"Content-Type": "application/json",
}
})
.then((response) => {
if (!response.ok) {
throw new Error("Network response was not ok");
}
return response.json();
})
.then((data) => {
const seriesData = data.data.series;
// document.getElementById(
// "countStatus6"
// ).innerText = `${data.data.count} Berkas`;
// document.getElementById(
// "totalStatus6"
// ).innerText = `Rp.${addThousandSeparators(data.data.total)}`;
})
.catch((error) => {
console.error("error fetching chart dara : ", error);
document
.querySelectorAll(".document-total.chart-potensi-tata-ruang")
.forEach((element) => {
element.innerText = `Rp.${addThousandSeparators("0.00")}`;
});
}
initChartStatus7(){
fetch(`${GlobalConfig.apiHost}/api/pbg-task-documents?status=7`, {
credentials: "include",
headers: {
Authorization: `Bearer ${document.querySelector("meta[name='api-token']").content}`,
"Content-Type": "application/json",
}
})
.then((response) => {
if (!response.ok) {
throw new Error("Network response was not ok");
}
return response.json();
})
.then((data) => {
const seriesData = data.data.series;
// document.getElementById(
// "countStatus7"
// ).innerText = `${data.data.count} Berkas`;
// document.getElementById(
// "totalStatus7"
// ).innerText = `Rp.${addThousandSeparators(data.data.total)}`;
})
.catch((error) => {
console.error("error fetching chart dara : ", error);
document
.querySelectorAll(".small-percentage.chart-potensi-tata-ruang")
.forEach((element) => {
element.innerText = `0.00%`;
});
}
initChartStatus20(){
fetch(`${GlobalConfig.apiHost}/api/pbg-task-documents?status=20`, {
credentials: "include",
headers: {
Authorization: `Bearer ${document.querySelector("meta[name='api-token']").content}`,
"Content-Type": "application/json",
}
})
.then((response) => {
if (!response.ok) {
throw new Error("Network response was not ok");
}
return response.json();
})
.then((data) => {
const seriesData = data.data.series;
// document.getElementById(
// "countStatus20"
// ).innerText = `${data.data.count} Berkas`;
// document.getElementById(
// "totalStatus20"
// ).innerText = `Rp.${addThousandSeparators(data.data.total)}`;
})
.catch((error) => {
console.error("error fetching chart dara : ", error);
});
}
initChartStatus24(){
fetch(`${GlobalConfig.apiHost}/api/pbg-task-documents?status=24`, {
credentials: "include",
headers: {
Authorization: `Bearer ${document.querySelector("meta[name='api-token']").content}`,
"Content-Type": "application/json",
}
})
.then((response) => {
if (!response.ok) {
throw new Error("Network response was not ok");
}
return response.json();
})
.then((data) => {
const seriesData = data.data.series;
// document.getElementById(
// "countStatus24"
// ).innerText = `${data.data.count} Berkas`;
// document.getElementById(
// "totalStatus24"
// ).innerText = `Rp.${addThousandSeparators(data.data.total)}`;
})
.catch((error) => {
console.error("error fetching chart dara : ", error);
});
}
}
class ArrowConnectorCircles {
init(){
// Memanggil fungsi saat halaman dimuat dan ketika layar diubah ukurannya
document.addEventListener("resize", this.updateLine());
document.addEventListener("load", this.updateLine());
}
updateLine() {
const circle1 = document.getElementById("chart-all-task-1").getBoundingClientRect();
const circle2 = document.getElementById("chart-all-task-2").getBoundingClientRect();
const line = document.getElementById("connector-line");
console.log(circle1);
console.log(circle2);
line.setAttribute("x1", circle1.left + circle1.width / 2);
line.setAttribute("y1", circle1.top + circle1.height / 2);
line.setAttribute("x2", circle2.left + circle2.width / 2);
line.setAttribute("y2", circle2.top + circle2.height / 2);
}
}
document.addEventListener("DOMContentLoaded", async function (e) {
await new BigData().init();
// new ArrowConnectorCircles().init();
});
function resizeDashboard(){
function resizeDashboard() {
//Target Width
let targetElement = document.getElementById("dashboard-fixed-wrapper");
let targetWidth = targetElement.offsetWidth;
@@ -449,15 +533,16 @@ function resizeDashboard(){
let dashboardWidth = 1110; //dashboardElement.offsetWidth;
//console.log("CURRENT ",dashboardWidth);
if(targetWidth> dashboardWidth){
if (targetWidth > dashboardWidth) {
targetWidth = dashboardWidth;
}
dashboardElement.style.transformOrigin = "left top";
dashboardElement.style.transition = "transform 0.2s ease-in-out";
dashboardElement.style.transform = "scale(" + (targetWidth/dashboardWidth).toFixed(2) + ")";
dashboardElement.style.transform =
"scale(" + (targetWidth / dashboardWidth).toFixed(2) + ")";
//console.log("SCALE ", (targetWidth/dashboardWidth).toFixed(2));
}
}
window.addEventListener("load", function () {
resizeDashboard();
@@ -465,5 +550,4 @@ window.addEventListener("load", function () {
window.addEventListener("resize", function () {
resizeDashboard();
});

View File

@@ -1,11 +1,27 @@
const GlobalConfig = {
apiHost: 'http://localhost:8000'
apiHost: "http://localhost:8000",
};
export default GlobalConfig;
export function addThousandSeparators(number, fractionDigits = 2) {
return new Intl.NumberFormat('en-US', {
export function addThousandSeparators(value, fractionDigits = 2) {
if (!value) return null; // Handle empty or null values
// Remove any non-numeric characters except commas and dots
value = value.replace(/[^0-9,.]/g, "");
// If the value contains multiple dots, assume dots are thousand separators
if ((value.match(/\./g) || []).length > 1) {
value = value.replace(/\./g, "");
}
// Convert to a proper decimal number
let number = parseFloat(value.replace(",", "."));
if (isNaN(number)) return null; // Return null if conversion fails
// Format the number with thousand separators
return new Intl.NumberFormat("en-US", {
minimumFractionDigits: fractionDigits,
maximumFractionDigits: fractionDigits,
}).format(number);

View File

@@ -7,6 +7,7 @@ class SyncronizeTask {
init() {
this.initTableImportDatasources();
this.handleSubmitSync();
this.handleSubmitSnycGoogleSheet();
}
initTableImportDatasources() {
new Grid({
@@ -50,28 +51,31 @@ class SyncronizeTask {
const button = document.getElementById("btn-sync-submit");
// Check if the button should be enabled or disabled based on the status
fetch(`${GlobalConfig.apiHost}/api/import-datasource/check-datasource`, {
fetch(
`${GlobalConfig.apiHost}/api/import-datasource/check-datasource`,
{
method: "GET",
headers: {
Authorization: `Bearer ${document
.querySelector('meta[name="api-token"]')
.getAttribute("content")}`,
"Content-Type": "application/json",
},
}
})
.then(response => {
)
.then((response) => {
if (!response.ok) {
throw new Error("Network response was not ok");
}
return response.json();
})
.then(data => {
.then((data) => {
console.log("data check button sync", data.can_execute);
button.disabled = !data.can_execute;
// If the button is enabled, add click event to trigger sync
if (!button.disabled) {
button.addEventListener("click", function(e) {
button.addEventListener("click", function (e) {
button.disabled = true; // Disable button to prevent multiple clicks
button.textContent = "Syncing..."; // Change button text to show syncing
@@ -83,22 +87,26 @@ class SyncronizeTask {
.querySelector('meta[name="api-token"]')
.getAttribute("content")}`,
"Content-Type": "application/json",
}
},
})
.then(response => {
.then((response) => {
if (!response.ok) {
throw new Error("Network response was not ok");
throw new Error(
"Network response was not ok"
);
}
return response.json();
})
.then(data => {
.then((data) => {
console.log("data sync button", data);
alert("Synchronization executed successfully");
window.location.reload();
})
.catch(err => {
.catch((err) => {
console.error("Fetch error:", err);
alert("An error occurred during synchronization");
alert(
"An error occurred during synchronization"
);
})
.finally(() => {
button.disabled = false; // Re-enable the button after the request is complete
@@ -107,11 +115,48 @@ class SyncronizeTask {
});
}
})
.catch(err => {
.catch((err) => {
console.error("Fetch error:", err);
alert("An error occurred while checking the datasource");
});
}
handleSubmitSnycGoogleSheet() {
const button = document.getElementById("btn-sync-submit-google-sheet");
button.addEventListener("click", function (e) {
button.disabled = true; // Disable button to prevent multiple clicks
button.textContent = "Syncing..."; // Change button text to show syncing
// Trigger the scraping API call
fetch(`${GlobalConfig.apiHost}/api/sync-pbg-task-google-sheet`, {
method: "GET",
headers: {
Authorization: `Bearer ${document
.querySelector('meta[name="api-token"]')
.getAttribute("content")}`,
"Content-Type": "application/json",
},
})
.then((response) => {
if (!response.ok) {
throw new Error("Network response was not ok");
}
return response.json();
})
.then((data) => {
console.log("data sync button", data);
alert("Synchronization executed successfully");
window.location.reload();
})
.catch((err) => {
console.error("Fetch error:", err);
alert("An error occurred during synchronization");
})
.finally(() => {
button.disabled = false; // Re-enable the button after the request is complete
button.textContent = "Sync Google Sheet"; // Reset button text
});
});
}
}
document.addEventListener("DOMContentLoaded", function (e) {
new SyncronizeTask().init();

View File

@@ -8,7 +8,7 @@
display: flex;
align-items: center;
justify-content: center;
background-color: var(--circle-color);; /* Warna lingkaran utama */
background-color: var(--circle-color); /* Warna lingkaran utama */
border-radius: 50%; /* Membuat lingkaran */
border: 6px solid white; /* Border putih */
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* Efek bayangan */
@@ -72,7 +72,7 @@
justify-content: center;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* Efek bayangan */
.small-circle-content{
.small-circle-content {
width: 45px;
height: 45px;
background-color: #2d4f90; /* Warna lingkaran kecil */
@@ -89,22 +89,9 @@
margin: 0;
}
}
}
}
.arrow-container {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none; /* Agar SVG tidak menghalangi interaksi */
}
// .circle-container {
// width: 20vw; /* Responsif menggunakan unit viewport */
// height: 20vw; /* Pastikan tinggi sama dengan lebar */

View File

@@ -39,8 +39,8 @@
@component('components.circle', [
'document_title' => 'Kekurangan Potensi',
'document_color' => '#911701',
'document_type' => 'Pemohon',
'document_id' => 'chart-all-task',
'document_type' => '',
'document_id' => 'chart-kekurangan-potensi',
'visible_small_circle' => true,
'style' => 'top:150px;'
])
@@ -49,8 +49,8 @@
@component('components.circle', [
'document_title' => 'Target PAD 2024',
'document_color' => '#020e42',
'document_type' => 'Pemohon',
'document_id' => 'chart-all-task',
'document_type' => '',
'document_id' => 'chart-target-pad',
'visible_small_circle' => true,
'style' => 'left:200px;'
])
@@ -68,7 +68,7 @@
'document_title' => 'Total Potensi Berkas',
'document_color' => '#02acfa',
'document_type' => 'Pemohon',
'document_id' => 'chart-all-task',
'document_id' => 'chart-total-potensi',
'visible_small_circle' => true,
'style' => 'left:400px;top:150px;'
])
@@ -83,8 +83,8 @@
@component('components.circle', [
'document_title' => 'Perkiraan Potensi PBG Dari Tata Ruang',
'document_color' => '#bf04bc',
'document_type' => 'Pemohon',
'document_id' => 'chart-all-task',
'document_type' => 'Berkas',
'document_id' => 'chart-potensi-tata-ruang',
'visible_small_circle' => true,
'style' => 'left:600px;'
])
@@ -117,7 +117,7 @@
'document_title' => 'Berkas Terverifikasi',
'document_color' => '#0561f5',
'document_type' => 'Berkas',
'document_id' => 'chart-business',
'document_id' => 'chart-berkas-terverifikasi',
'visible_small_circle' => true,
'style' => 'top:300px;left:200px;'
])
@@ -133,7 +133,7 @@
'document_title' => 'Berkas Belum Terverifikasi',
'document_color' => '#b973ff',
'document_type' => 'Berkas',
'document_id' => 'chart-business',
'document_id' => 'chart-berkas-belum-terverifikasi',
'visible_small_circle' => true,
'style' => 'top:300px;left:600px;'
])
@@ -150,7 +150,7 @@
'document_title' => 'Realisasi Terbit PBG',
'document_color' => '#09ab5a',
'document_type' => 'Berkas',
'document_id' => 'chart-business',
'document_id' => 'chart-realisasi-tebit-pbg',
'visible_small_circle' => true,
'style' => 'top:550px;left:100px;'
])
@@ -163,7 +163,7 @@
'document_title' => 'Menunggu Klik DPMPTSP',
'document_color' => '#0294ad',
'document_type' => 'Berkas',
'document_id' => 'chart-business',
'document_id' => 'chart-menunggu-klik-dpmptsp',
'visible_small_circle' => true,
'style' => 'top:550px;left:400px'
])
@@ -176,57 +176,12 @@
'document_title' => 'Berproses Di Dinas Teknis',
'document_color' => '#422519',
'document_type' => 'Berkas',
'document_id' => 'chart-business',
'document_id' => 'chart-proses-dinas-teknis',
'visible_small_circle' => true,
'style' => 'top:550px;left:700px'
])
@endcomponent
</div>
<div class="row d-flex justify-content-center">
<!-- <div id="circle1" class="absolute w-16 h-16 bg-blue-500 rounded-full flex items-center justify-center text-white text-lg font-bold top-40 left-40">
1
</div>
<div id="circle2" class="absolute w-16 h-16 bg-red-500 rounded-full flex items-center justify-center text-white text-lg font-bold top-80 left-80">
2
</div>
<svg id="svg-container" class="absolute inset-0 w-full h-full pointer-events-none">
<defs>
<marker id="arrowhead" markerWidth="10" markerHeight="7" refX="10" refY="3.5" orient="auto">
<polygon points="0 0, 10 3.5, 0 7" fill="red"></polygon>
</marker>
</defs>
<line id="connector-line" stroke="red" stroke-width="2" marker-end="url(#arrowhead)" />
</svg> -->
</div>
<div class="row d-flex justify-content-center">
</div>
<div class="row d-flex justify-content-center">
</div>
<div class="row d-flex justify-content-center">
</div>
<div class="row d-flex justify-content-center">
</div>
<div class="row d-flex justify-content-center">
</div>
</div>
@endsection

View File

@@ -68,7 +68,7 @@
</a>
<div class="collapse" id="sidebarSettings">
<ul class="nav sub-navbar-nav">
<li class="sub-nav-item">
<li class="sub-nav-item d-none">
<a class="sub-nav-link" href="{{ route ('general.index' ) }}">General</a>
</li>
<li class="sub-nav-item">

View File

@@ -10,11 +10,8 @@
<div class="row">
<div class="col-md-12 col-xl-12 d-flex justify-content-end">
<!-- <form action="{{route('settings.sync')}}" method="post" id="sync-form">
@csrf
<button type="button" class="btn btn-success width-lg" id="btn-sync-submit">Sync SIMBG</button>
</form> -->
<button type="button" class="btn btn-success width-lg" id="btn-sync-submit">Sync SIMBG</button>
<button type="button" class="btn btn-success" style="margin-right: 20px;" id="btn-sync-submit-google-sheet">Sync Google Sheet</button>
<button type="button" class="btn btn-success" id="btn-sync-submit">Sync SIMBG</button>
</div>
<div>
<div id="table-import-datasources"></div>

View File

@@ -38,6 +38,8 @@ Route::group(['middleware' => 'auth:sanctum'], function (){
Route::get('/non-business-documents','nonBusinnessDocument');
Route::get('/all-task-documents', 'allTaskDocuments');
Route::get('/pbg-task-documents', 'pbgTaskDocuments');
Route::get('/verification-documents','verificationDocuments');
Route::get('/non-verification-documents','nonVerificationDocuments');
});
// scraping
@@ -47,6 +49,9 @@ Route::group(['middleware' => 'auth:sanctum'], function (){
Route::apiResource('/api-data-settings', DataSettingController::class);
Route::apiResource('/api-pbg-task', PbgTaskController::class);
// sync pbg google sheet
Route::get('/sync-pbg-task-google-sheet', [PbgTaskController::class, 'syncPbgFromGoogleSheet'])->name('pbg-task.sync-google-sheet');
});
Route::apiResource('/api-google-sheet', GoogleSheetController::class);