Custom Backend OSPRO Surveyor Indonesia
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

258 lines
8.3 KiB

<?php
namespace App\Models;
use App\Models\AssignMaterial;
use App\Models\ActivityProgressLog;
use App\Models\AssignTools;
use App\Models\ReportActivityMaterial;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;
class Activity extends Model
{
protected $table = 'm_activity';
const CREATED_AT = 'created_at';
const UPDATED_AT = 'updated_at';
// persentase bobot gak kepake yg dipakenya bobot_planning
protected $fillable = [
'proyek_id', 'parent_id', 'kode_sortname', 'name', 'rencana_biaya', 'start_date',
'end_date', 'area_kerja', 'biaya_actual', 'persentase_bobot', 'persentase_progress',
'buffer_radius', 'duration', 'color_progress', 'jumlah_pekerjaan', 'satuan',
'description', 'priority', 'bobot_planning', 'type_activity', 'open', 'geom',
'version_gantt_id', 'budget_plan', 'biaya_material_plan', 'biaya_human_plan', 'biaya_tools_plan',
'planned_start', 'planned_end', 'satuan_id', 'actual_start', 'actual_end',
'created_at', 'created_by', 'updated_at', 'updated_by', 'sortorder'
];
protected $appends = [
'jobs_done', 'assign_hr', 'assign_material', 'assign_tools', 'assign_expense'
];
protected $casts = [
'rencana_biaya' => 'double'
];
public function getStartDateAttribute($value)
{
if ($value instanceof \DateTime) {
return Carbon::instance($value)
->timezone(env('APP_TIMEZONE'))
->toDateTimeString();
}
return Carbon::createFromTimestamp(strtotime($value))
->timezone(env('APP_TIMEZONE'))
->toDateTimeString();
}
public function getEndDateAttribute($value)
{
if ($value instanceof \DateTime) {
return Carbon::instance($value)
->timezone(env('APP_TIMEZONE'))
->toDateTimeString();
}
return Carbon::createFromTimestamp(strtotime($value))
->timezone(env('APP_TIMEZONE'))
->toDateTimeString();
}
public static function boot() {
parent::boot();
DB::transaction(function() {
static::updating(function($data) {
$data->logPersentaseProgress();
});
static::updated(function($data) {
$data->updateBobot();
$data->updateCostPlanning();
if($data->bobot_planning){
$data->updatePersentaseProgress();
}
$data->updateCostActual();
// if($data->start_date != request()->start_date || $data->end_date != request()->end_date) {
// $data->updateStartEndDateHeader();
// }
});
static::deleted(function($data) {
if (isset($data->parent_id)) {
if(Activity::where("parent_id", $data->parent_id)->count() == 0) {
$activity = Activity::find($data->parent_id);
if ($activity) {
$activity->update(["type_activity"=>"task"]);
}
}
}
$data->updateBobot(true);
$data->updateCostPlanning();
if($data->bobot_planning){
$data->updatePersentaseProgress();
}
$data->updateCostActual();
$data->updateStartEndDateHeader();
});
},5);
}
private function updateBobot($isDelete = false)
{
$root = Activity::where([
['version_gantt_id', $this->version_gantt_id],
['proyek_id', $this->proyek_id]
])
->whereNull('parent_id')
->first();
if(isset($root) && doubleval($root->rencana_biaya) > 0){
$activities = Activity::where([['proyek_id', $this->proyek_id],['version_gantt_id', $this->version_gantt_id]])->get();
foreach ($activities as $activity) {
if($isDelete && $activity->id == $this->id)
continue;
$activity->bobot_planning = ( doubleval($activity->rencana_biaya) / doubleval($root->rencana_biaya)) * 100;
$activity->updated_by = auth()->user() ? auth()->user()->name : "system";
$activity->saveQuietly();
}
} else {
if($parent = Activity::find($this->parent_id)){
$totalChildWeight = Activity::where("parent_id", $this->parent_id)->sum('bobot_planning');
$parent->update([
"bobot_planning" => $totalChildWeight
]);
}
}
}
private function updateCostActual()
{
$actualCost = Activity::where("parent_id", $this->parent_id)->sum("biaya_actual");
$this->biaya_actual = $actualCost;
if($parent = Activity::find($this->parent_id)){
$parent->update([
"biaya_actual" => $actualCost
]);
}
}
private function updatePersentaseProgress()
{
if($parent = Activity::find($this->parent_id)){
$parentActWeight = $parent->bobot_planning;
if ($parentActWeight == 0) {
$parent->update([
"persentase_progress" => 0
]);
return;
}
$totalChildProportionalProgress = 0;
$childs = Activity::where("parent_id", $parent->id)->get();
foreach($childs as $child){
$currentActWeight = $child->bobot_planning;
$currentActProportionalProgress = ($currentActWeight / $parentActWeight) * $child->persentase_progress;
$totalChildProportionalProgress += $currentActProportionalProgress;
}
$parent->update([
"persentase_progress" => $totalChildProportionalProgress
]);
}
}
private function updateCostPlanning() {
$sumBiaya = Activity::select(DB::raw('sum(cast(rencana_biaya as double precision))'))
->where("parent_id", $this->parent_id)
->first();
$this->rencana_biaya = $sumBiaya->sum;
if($parent = Activity::find($this->parent_id)){
$parent->update([
"rencana_biaya" => $sumBiaya->sum,
]);
}
}
private function logPersentaseProgress()
{
ActivityProgressLog::create([
'version_gantt_id' => $this->version_gantt_id,
'activity_id' => request()->id,
'old_percentage' => $this->persentase_progress,
'new_percentage' => request()->persentase_progress,
'variance' => $this->persentase_progress - request()->persentase_progress,
'created_by'=> "system"
]);
}
private function updateStartEndDateHeader()
{
$earliestStartDate = Activity::where('version_gantt_id', $this->version_gantt_id)->whereNotNull('parent_id')->oldest('start_date')->pluck('start_date')->first();
$latestEndDate = Activity::where('version_gantt_id', $this->version_gantt_id)->whereNotNull('parent_id')->latest('end_date')->pluck('end_date')->first();
if($header = Activity::where('version_gantt_id', $this->version_gantt_id)->whereNull('parent_id')->first()) {
$header->start_date = $earliestStartDate;
$header->end_date = $latestEndDate;
$header->saveQuietly();
}
}
public function getJobsDoneAttribute()
{
if(!ReportActivityMaterial::where('activity_id', $this->id)->first())
return 0;
if(!$dataPlan = AssignMaterial::where('activity_id', $this->id)->get())
return 0;
if($dataPlan->isEmpty())
return 0;
if($dataPlan[0]->status_activity == 'done')
return 100;
return $this->persentase_progress;
}
public function getAssignHrAttribute()
{
return Arr::flatten(UserToActivity::select("u.name as name")
->join("m_users as u", "u.id", "=", "assign_hr_to_activity.user_id")
->where('assign_hr_to_activity.activity_id', $this->id)
->get()
->toArray());
}
public function getAssignMaterialAttribute()
{
return Arr::flatten(AssignMaterial::select("m.description as name")
->join("m_req_material as m", "m.id", "=", "assign_material_to_activity.material_id")
->where('assign_material_to_activity.activity_id', $this->id)
->where('assign_material_to_activity.type', "material")
->get()
->toArray());
}
public function getAssignExpenseAttribute()
{
return Arr::flatten(AssignMaterial::select("m.description as name")
->join("m_req_material as m", "m.id", "=", "assign_material_to_activity.material_id")
->where('assign_material_to_activity.activity_id', $this->id)
->where('assign_material_to_activity.type', "expense")
->get()
->toArray());
}
public function getAssignToolsAttribute()
{
return Arr::flatten(AssignTools::select("m.name as name")
->join("m_tools_resource as m", "m.id", "=", "assign_tools_to_activity.tools_id")
->where('assign_tools_to_activity.activity_id', $this->id)
->get()
->toArray());
}
}