add new url scraping data and create tab data lists

This commit is contained in:
arifal
2025-08-15 17:25:20 +07:00
parent 6896fd62a3
commit 209ef07f9c
18 changed files with 1220 additions and 424 deletions

View File

@@ -54,4 +54,86 @@ class PbgTask extends Model
public function attachments(){
return $this->hasMany(PbgTaskAttachment::class, 'pbg_task_id', 'id');
}
/**
* Get the data lists associated with this PBG task (One to Many)
* One pbg_task can have many data lists
*/
public function dataLists()
{
return $this->hasMany(PbgTaskDetailDataList::class, 'pbg_task_uuid', 'uuid');
}
/**
* Get only data lists with files
*/
public function dataListsWithFiles()
{
return $this->hasMany(PbgTaskDetailDataList::class, 'pbg_task_uuid', 'uuid')
->whereNotNull('file')
->where('file', '!=', '');
}
/**
* Get data lists by status
*/
public function dataListsByStatus($status)
{
return $this->hasMany(PbgTaskDetailDataList::class, 'pbg_task_uuid', 'uuid')
->where('status', $status);
}
/**
* Get data lists by data type
*/
public function dataListsByType($dataType)
{
return $this->hasMany(PbgTaskDetailDataList::class, 'pbg_task_uuid', 'uuid')
->where('data_type', $dataType);
}
/**
* Create or update data lists from API response
*/
public function syncDataLists(array $dataLists): void
{
foreach ($dataLists as $listData) {
PbgTaskDetailDataList::updateOrCreate(
['uid' => $listData['uid']],
[
'name' => $listData['name'] ?? null,
'description' => $listData['description'] ?? null,
'status' => $listData['status'] ?? null,
'status_name' => $listData['status_name'] ?? null,
'data_type' => $listData['data_type'] ?? null,
'data_type_name' => $listData['data_type_name'] ?? null,
'file' => $listData['file'] ?? null,
'note' => $listData['note'] ?? null,
'pbg_task_uuid' => $this->uuid,
]
);
}
}
/**
* Get data lists count by status
*/
public function getDataListsCountByStatusAttribute()
{
return $this->dataLists()
->selectRaw('status, COUNT(*) as count')
->groupBy('status')
->pluck('count', 'status');
}
/**
* Get data lists count by data type
*/
public function getDataListsCountByTypeAttribute()
{
return $this->dataLists()
->selectRaw('data_type, COUNT(*) as count')
->groupBy('data_type')
->pluck('count', 'data_type');
}
}

View File

@@ -141,6 +141,8 @@ class PbgTaskDetail extends Model
return $this->belongsTo(PbgTask::class, 'pbg_task_uid', 'uuid');
}
/**
* Create or update PbgTaskDetail from API response
*/
@@ -249,4 +251,6 @@ class PbgTaskDetail extends Model
$detailData
);
}
}

View File

@@ -0,0 +1,161 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class PbgTaskDetailDataList extends Model
{
use HasFactory;
protected $table = 'pbg_task_detail_data_lists';
protected $fillable = [
'uid',
'name',
'description',
'status',
'status_name',
'data_type',
'data_type_name',
'file',
'note',
'pbg_task_uuid',
];
protected $casts = [
'status' => 'integer',
'data_type' => 'integer',
'created_at' => 'datetime',
'updated_at' => 'datetime',
];
/**
* Relationship to PbgTask (Many to One)
* Many data lists belong to one pbg_task
*/
public function pbgTask()
{
return $this->belongsTo(PbgTask::class, 'pbg_task_uuid', 'uuid');
}
/**
* Get the full file path
*/
public function getFilePathAttribute()
{
return $this->file ? storage_path('app/public/' . $this->file) : null;
}
/**
* Get the file URL
*/
public function getFileUrlAttribute()
{
return $this->file ? asset('storage/' . $this->file) : null;
}
/**
* Check if file exists
*/
public function hasFile()
{
return !empty($this->file) && file_exists($this->getFilePathAttribute());
}
/**
* Get status badge color based on status
*/
public function getStatusBadgeAttribute()
{
return match($this->status) {
1 => 'success', // Sesuai
0 => 'danger', // Tidak Sesuai
default => 'secondary'
};
}
/**
* Scope: Filter by status
*/
public function scopeByStatus($query, $status)
{
return $query->where('status', $status);
}
/**
* Scope: Filter by data type
*/
public function scopeByDataType($query, $dataType)
{
return $query->where('data_type', $dataType);
}
/**
* Scope: With files only
*/
public function scopeWithFiles($query)
{
return $query->whereNotNull('file')->where('file', '!=', '');
}
/**
* Scope: Search by name or description
*/
public function scopeSearch($query, $search)
{
return $query->where(function ($q) use ($search) {
$q->where('name', 'LIKE', "%{$search}%")
->orWhere('description', 'LIKE', "%{$search}%")
->orWhere('status_name', 'LIKE', "%{$search}%")
->orWhere('data_type_name', 'LIKE', "%{$search}%");
});
}
/**
* Get file extension from file path
*/
public function getFileExtensionAttribute()
{
if (!$this->file) {
return null;
}
return strtoupper(pathinfo($this->file, PATHINFO_EXTENSION));
}
/**
* Get filename from file path
*/
public function getFileNameAttribute()
{
if (!$this->file) {
return null;
}
return basename($this->file);
}
/**
* Get formatted created date
*/
public function getFormattedCreatedAtAttribute()
{
return $this->created_at ? $this->created_at->format('d M Y, H:i') : '-';
}
/**
* Get truncated description
*/
public function getTruncatedDescriptionAttribute()
{
return $this->description ? \Str::limit($this->description, 80) : null;
}
/**
* Get truncated note
*/
public function getTruncatedNoteAttribute()
{
return $this->note ? \Str::limit($this->note, 100) : null;
}
}