From 168eb9cae9a30db4f76f26e7a1e54218c6954baa Mon Sep 17 00:00:00 2001 From: Muhammad Sulaiman Yusuf Date: Fri, 22 Jul 2022 15:47:36 +0700 Subject: [PATCH] refactor, move calculations to model --- app/Http/Controllers/ActivityController.php | 301 +------------------- app/Models/Activity.php | 150 +++++++++- 2 files changed, 155 insertions(+), 296 deletions(-) diff --git a/app/Http/Controllers/ActivityController.php b/app/Http/Controllers/ActivityController.php index 5a133dd..9c384c8 100644 --- a/app/Http/Controllers/ActivityController.php +++ b/app/Http/Controllers/ActivityController.php @@ -3,29 +3,25 @@ namespace App\Http\Controllers; use App\Models\Activity; -use App\Models\AssignMaterial; -use App\Models\AssignTools; use App\Models\CommentActivity; use App\Models\Holiday; use App\Models\Link; use App\Models\Project; use App\Models\ReportActivity; -use App\Models\ReportActivityMaterial; use App\Models\TemplateGantt; use App\Models\UserToActivity; use App\Models\VersionGantt; use Illuminate\Support\Facades\DB; use Illuminate\Http\Request; -use Illuminate\Support\Arr; class ActivityController extends Controller { public function getByGanttId($id, $proyek_id) { - if(Activity::where("version_gantt_id", $id)->count() == 0) - $dataGantt = $this->getDataActivity($id); + if(Activity::where("version_gantt_id", $id)->count() == 0) { + $this->cloneTemplate($id, $proyek_id); + } - $this->templateToActivity($id, $proyek_id); $dataGantt = $this->getDataActivity($id); return response()->json(['status'=>'success','data'=> $dataGantt,'code'=>200], 200); @@ -33,7 +29,6 @@ class ActivityController extends Controller private function getDataActivity($id) { - $dataHeader = Activity::where('version_gantt_id', $id)->where('type_activity', 'header')->first(); $startDate = date_create($dataHeader->start_date); $endDate = date_create($dataHeader->end_date); @@ -53,20 +48,15 @@ class ActivityController extends Controller $type = $objRow->type_activity; if(empty($dataChildren)) $type = "task"; - $objRow->text = $objRow->name; $objRow->parent = $objRow->parent_id ? $objRow->parent_id : null; $startDate = date_create($objRow->start_date); $endDate = date_create($objRow->end_date); - $objRow->jobs_done = $this->sumVolumeActualMaterial($objRow->id); - $objRow->assign_hr = $this->getUserActivity($objRow->id); - $objRow->assign_tools = $this->getToolsActivity($objRow->id); - $objRow->assign_material = $this->getMaterialActivity($objRow->id); $objRow->start_date = date_format($startDate,"Y-m-d H:i:s"); $objRow->end_date = date_format($endDate,"Y-m-d H:i:s"); $objRow->planned_start = isset($objRow->planned_start) ? date_format(date_create($objRow->planned_start),"Y-m-d H:i:s") : NULL; $objRow->planned_end = isset($objRow->planned_end) ? date_format(date_create($objRow->planned_end),"Y-m-d H:i:s") : NULL; - $objRow->progress = (int)$objRow->persentase_progress/100; + $objRow->progress = (int) $objRow->persentase_progress / 100; $dataChildren = $this->getChildren($id, $objRow->id); $objRow->type = $type; $finalData[] = $objRow; @@ -104,10 +94,6 @@ class ActivityController extends Controller foreach($data as $objRow){ $objRow->parent = $parent_id; $objRow->text = $objRow->name; - $objRow->jobs_done = $this->sumVolumeActualMaterial($objRow->id); - $objRow->assign_hr = $this->getUserActivity($objRow->id); - $objRow->assign_tools = $this->getToolsActivity($objRow->id); - $objRow->assign_material = $this->getMaterialActivity($objRow->id); $objRow->progress = (int)$objRow->persentase_progress/100; $startDate = date_create($objRow->start_date); $endDate = date_create($objRow->end_date); @@ -129,54 +115,7 @@ class ActivityController extends Controller return $finalData; } - private function sumVolumeActualMaterial($id) - { - $tmpPercentage = []; - - $dataPlan = AssignMaterial::where('activity_id', $id)->get(); - if($dataPlan->isEmpty()) - return 0; - - foreach ($dataPlan as $value) { - $tmpPercentage[] = 100; - $getDataVolActual = ReportActivityMaterial::where('assign_material_id', '=', $value->id)->sum("qty"); - $percentage = ($getDataVolActual * 100) / $value->qty_planning; - if($value->status_activity != 'done'){ - $tmpPercentage[] = $percentage >= 100 ? 90 : $percentage; - } - } - - return array_sum($tmpPercentage) > 0 ? array_sum($tmpPercentage) / count($tmpPercentage) : 0; - } - - private function getUserActivity($id) - { - 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', $id) - ->get() - ->toArray()); - } - - private function getMaterialActivity($id) - { - 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', $id) - ->get() - ->toArray()); - } - - private function getToolsActivity($id) - { - 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', $id) - ->get() - ->toArray()); - } - - private function templateToActivity($id, $proyek_id) + private function cloneTemplate($id, $proyek_id) { $project = Project::findOrFail($proyek_id); @@ -248,6 +187,7 @@ class ActivityController extends Controller $parent = $data['parent_id'] ?? null; if($parent){ $this->updateTypeProject($parent); + Activity::find($parent)->update(["type_activity"=>"project"]); CommentActivity::where('activity_id', $parent)->delete(); UserToActivity::where('activity_id', $parent)->delete(); } @@ -258,11 +198,6 @@ class ActivityController extends Controller return response()->json(['status'=>'success','action'=>'inserted', 'tid'=>$result->id,'code'=>200], 200); } - private function updateTypeProject($id) - { - Activity::find($id)->update(["type_activity"=>"project"]); - } - public function edit($id){ if(empty($id) || !is_int((int)$id)) return response()->json(['status'=>'failed','message'=>'id is required!','code'=>400], 400); @@ -279,10 +214,8 @@ class ActivityController extends Controller return response()->json(['status'=>'failed', 'action'=>'error','message'=>'id is required!','code'=>400], 400); $updateBobot = false; - $data = Activity::findOrFail($id); if(!$data = Activity::find($id)) return response()->json(['status'=>'failed', 'action'=>'error','message'=>'Data not found!','code'=> 404], 404); - $parent = $data->parent_id; $dataUpdate = $request->all(); $oldRencanaBiaya = $data->rencana_biaya; @@ -299,14 +232,6 @@ class ActivityController extends Controller if(!$data->update($dataUpdate)) return response()->json(['status'=>'failed', 'action'=>'error','message'=>'data activity failed updated!','code'=>400], 400); - if($parent){ - $this->updateCostPlanning($parent); - $this->updatePersentaseProgress($parent); - $this->updateCostActual($parent); - } - - $this->calculateAllBobot($data->proyek_id, $data->version_gantt_id); - return response()->json(['status'=>'success','update_bobot'=> $updateBobot, 'data'=>$dataUpdate, 'action'=>'updated','message'=>'Activity updated!','code'=>200], 200); } @@ -325,66 +250,17 @@ class ActivityController extends Controller return response()->json(['status'=>'success','message'=>'Activity Updated!','code'=> 200], 200); } - private function calculateAllBobot($proyek, $gantt) - { - if(Activity::where('version_gantt_id', $gantt)->where("proyek_id", $proyek)->where('type_activity', 'header')->count() == 0) - $totalCost = Activity::select( - DB::raw('sum(cast(rencana_biaya as double precision))') - ) - ->where("proyek_id", $proyek) - ->where("version_gantt_id", $gantt) - ->whereNull("parent_id") - ->first(); - - $rootActivity = Activity::where('version_gantt_id', $gantt) - ->where("proyek_id", $proyek) - ->where('type_activity', 'header') - ->first(); - - $totalCost = Activity::select(DB::raw('sum(cast(rencana_biaya as double precision))')) - ->where("proyek_id", $proyek) - ->where("version_gantt_id", $gantt) - ->where("parent_id", $rootActivity->id) - ->first(); - - if($totalCost->sum > 0){ - $activities = Activity::where("proyek_id", $proyek)->where("version_gantt_id", $gantt)->get(); - foreach ($activities as $activity) { - $activity->update([ - "bobot_planning" => ( (int)$activity->rencana_biaya / $totalCost->sum ) * 100, - "updated_by" => $this->currentName - ]); - } - } - return true; - } - public function delete($id) { - $data = Activity::findOrFail($id); - if(!$data = Activity::find($id)) return response()->json(['status'=>'failed', 'action'=>'error','message'=> 'Data not found!','code'=> 404], 404); - if($data->parent_id){ - $this->checkForUpdateParent($data->parent_id); - $this->updateCostPlanning($data->parent_id); - $this->updatePersentaseProgress($data->parent_id); - $this->updateCostActual($data->parent_id); - } - if(!$data->delete()) return response()->json(['status'=>'failed', 'action'=>'error','message'=>'data activity failed deleted!','code'=> 500], 500); return response()->json(['status'=>'success', "action"=>"deleted",'message'=>'data activity successfully deleted!','code'=>200], 200); } - private function checkForUpdateParent($id) - { - if(Activity::where("parent_id", $id)->count() == 0) - Activity::find($id)->update(["type_activity"=>"task"]); - } - public function getUpdate($id) { if(!$data = Activity::find($id)) @@ -392,56 +268,9 @@ class ActivityController extends Controller $data->progress = (int) $data->persentase_progress / 100; $data->rencana_biaya = str_replace(".", ",", $data->rencana_biaya); - $data->jobs_done = $this->sumVolumeActualMaterial($data->id); - $data->assign_hr = $this->getUserActivity($data->id); - $data->assign_tools = $this->getToolsActivity($data->id); - $data->assign_material = $this->getMaterialActivity($data->id); return response()->json(['status'=>'success', "data"=> $data,'code'=>200], 200); } - private function updateCostPlanning($id) - { - $sumBiaya = Activity::select(DB::raw('sum(cast(rencana_biaya as double precision))')) - ->where("parent_id", $id) - ->first(); - - $activity = Activity::find($id); - $data= array( - "rencana_biaya" => $sumBiaya->sum, - "updated_by" => $this->currentName - ); - - if($activity->update($data) && $activity->parent_id) - $this->updateCostPlanning($activity->parent_id); - } - - private function updatePersentaseProgress($id) - { - $siblings = Activity::where("parent_id", $id); - $sumProgress = $siblings->sum("persentase_progress"); - $totalChild = $siblings->count(); - $activity = Activity::find($id); - - $activity->update([ - "persentase_progress" => $sumProgress / $totalChild, - "updated_by" => $this->currentName - ]); - if($activity->parent_id) - $this->updatePersentaseProgress($activity->parent_id); - } - - private function updateCostActual($id) - { - $activity = Activity::find($id); - - $activity->update([ - "biaya_actual" => Activity::where("parent_id", $id)->sum("biaya_actual"), - "updated_by" => $this->currentName - ]); - if($activity->parent_id) - $this->updateCostActual($activity->parent_id); - } - public function search(Request $request) { $dataBuilder = $this->setUpPayload($request->all(), 'm_activity'); @@ -756,124 +585,6 @@ class ActivityController extends Controller } - public function getCalculateCurvaSDays(Request $request) - { - $dataPayload = $request->all(); - $allGantt = []; - foreach ($dataPayload['project_id'] as $val) { - $allGantt[] = $this->getLatestGantt($val); - } - - $dataFinal=[]; - foreach ($allGantt as $val) { - $dataProject = Project::find($val['proyek_id']); - $holidays = Holiday::where("version_gantt_id", $val['last_gantt_id'])->where("proyek_id", $val['proyek_id'])->get(); - $dateHoliday = []; //$holiday->all(); - foreach ($holidays as $holiday) { - $startH = new \DateTime($holiday->date); - $endH = clone $startH; - $endH->modify('+'.$holiday->duration.' day'); - $intervalH = \DateInterval::createFromDateString('1 day'); - $periodH = new \DatePeriod($startH, $intervalH, $endH); - foreach ($periodH as $dt) { - $dateHoliday[] = $dt->format("Y-m-d"); - } - } - $verGantt = VersionGantt::find($val['last_gantt_id']); - $configOff = $verGantt->config_dayoff; - if($configOff && $configOff!= ""){ - $dayOff = explode(",", $verGantt->config_dayoff); - $dayOff = array_map( - function($value) { return (int)$value; }, - $dayOff - ); - }else{ - $dayOff = []; - } - $dataHeader = Activity::where('type_activity', 'header')->where("proyek_id", $val['proyek_id'])->where("version_gantt_id", $val['last_gantt_id'])->first(); - if($dataHeader){ - $minDate = Activity::where('parent_id', $dataHeader->id)->where("proyek_id", $val['proyek_id'])->where("version_gantt_id", $val['last_gantt_id'])->min("start_date"); - $maxDate = Activity::where('parent_id', $dataHeader->id)->where("proyek_id", $val['proyek_id'])->where("version_gantt_id", $val['last_gantt_id'])->max("end_date"); - }else{ - $minDate = Activity::whereNull('parent_id')->where("proyek_id", $val['proyek_id'])->where("version_gantt_id", $val['last_gantt_id'])->min("start_date"); - $maxDate = Activity::whereNull('parent_id')->where("proyek_id", $val['proyek_id'])->where("version_gantt_id", $val['last_gantt_id'])->max("end_date"); - } - - $begin = new \DateTime($minDate); - $end = new \DateTime($maxDate); - $interval = \DateInterval::createFromDateString('1 day'); - $period = new \DatePeriod($begin, $interval, $end); - $dataHeader = Activity::where('type_activity', 'header')->where("proyek_id", $val['proyek_id'])->where("version_gantt_id", $val['last_gantt_id'])->first(); - if($dataHeader){ - $totalRencanaBudget = Activity::select(DB::raw('sum(cast(rencana_biaya as integer))'))->where('parent_id', $dataHeader->id)->where("proyek_id", $val['proyek_id'])->where("version_gantt_id", $val['last_gantt_id'])->first(); - }else{ - $totalRencanaBudget = Activity::select(DB::raw('sum(cast(rencana_biaya as integer))'))->whereNull('parent_id')->where("proyek_id", $val['proyek_id'])->where("version_gantt_id", $val['last_gantt_id'])->first(); - } - - $totalRencanaBudget = $totalRencanaBudget->sum; - $currentPercentage = 0; - $currentACWP = 0; - $currentProgressActivity = 0; - $currentBCWP = 0; - $dataDate = []; - $dataPercen = []; - $testdata = []; - foreach ($period as $dt) { - $weekDay = $dt->format("w"); - $currentDate = $dt->format("Y-m-d"); - $testdata[] = array('weekday' => $weekDay, 'date' =>$currentDate); - if(!in_array($weekDay, $dayOff) && !in_array($currentDate, $dateHoliday)) - { - $totalPercentage = 0; - $totalACWP = 0; - $totalProgressActivity = 0; - $totalBCWP = 0; - $dataActivity = Activity::whereRaw("'".$currentDate."' BETWEEN DATE(m_activity.start_date) AND DATE(m_activity.end_date) - INTERVAL '1 DAY'")->where('type_activity', 'task')->where("proyek_id", $val['proyek_id'])->where("version_gantt_id", $val['last_gantt_id'])->get(); - foreach ($dataActivity as $activity) { - - $duration = $activity->duration; - if($totalRencanaBudget > 0 && $duration > 0){ - $totalPercentage += $activity->bobot_planning/$duration; - if($activity->biaya_actual > 0 && $activity->persentase_progress){ - $totalACWP += $activity->biaya_actual/$duration; - $totalProgressActivity += (($activity->persentase_progress*$activity->bobot_planning)/100)/$duration; - $totalBCWP += (((($activity->persentase_progress*$activity->bobot_planning)/100)/$duration)* $totalRencanaBudget)/100; - } - } - } - - $currentPercentage = round(($currentPercentage + $totalPercentage), 0); - $currentACWP = $totalACWP == 0 ? null : $currentACWP + $totalACWP; - $currentProgressActivity = $totalProgressActivity == 0 ? null : round(($currentProgressActivity + $totalProgressActivity),0); - $currentBCWP = $totalBCWP == 0 ? null :$currentBCWP + $totalBCWP; - $currentPercentage = $currentPercentage > 100 ? 100 : $currentPercentage; - $currentProgressActivity = $currentProgressActivity > 100 ? 100 : $currentProgressActivity; - - - $dataDate[] = array($currentDate, $currentBCWP, $currentACWP); - $dataPercen[] = array($currentPercentage, $currentProgressActivity); - }else{ - $dataDate[] = $currentDate; - $dataPercen[] = array($currentPercentage,$currentProgressActivity); - } - } - $dataPercentage = array( - "date"=>$dataDate, - "percentage"=>$dataPercen - ); - $dataFinal[] = array( - "proyek_name"=> $dataProject->nama, - "data"=>$dataPercentage - ); - } - - if($dataFinal){ - return response()->json(['status'=>'success','code'=>200,'data'=>$dataFinal, 'testdata' => $testdata, '$period' => $period, 'totalRecord'=>1], 200); - }else{ - return response()->json(['status'=>'failed','message'=>'failed get list percentage day, please try again later!','code'=>400], 400); - } - } - private function getLatestGantt($id){ return array( "last_gantt_id" => VersionGantt::where("proyek_id", $id)->latest(), diff --git a/app/Models/Activity.php b/app/Models/Activity.php index 94f2ae4..f7dc9a8 100644 --- a/app/Models/Activity.php +++ b/app/Models/Activity.php @@ -2,7 +2,12 @@ namespace App\Models; +use App\Models\AssignMaterial; +use App\Models\AssignTools; +use App\Models\ReportActivityMaterial; use Illuminate\Database\Eloquent\Model; +use Illuminate\Support\Arr; +use Illuminate\Support\Facades\DB; class Activity extends Model { @@ -15,9 +20,152 @@ class Activity extends Model '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', + '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', 'created_at', 'created_by', 'updated_at', 'updated_by' ]; + + protected $attributes = [ + 'jobs_done', 'assign_hr', 'assign_material', 'assign_tools' + ]; + + protected $appends = [ + 'jobs_done', 'assign_hr', 'assign_material', 'assign_tools' + ]; + + public static function boot() { + parent::boot(); + + static::updated(function($data) { + + // update bobot + if(Activity::where('version_gantt_id', $data->version_gantt_id)->where("proyek_id", $data->proyek_id)->where('type_activity', 'header')->count() == 0) + $totalCost = Activity::select( + DB::raw('sum(cast(rencana_biaya as double precision))') + ) + ->where("proyek_id", $data->proyek_id) + ->where("version_gantt_id", $data->version_gantt_id) + ->whereNull("parent_id") + ->first(); + + $rootActivity = Activity::where('version_gantt_id', $data->version_gantt_id) + ->where("proyek_id", $data->proyek_id) + ->where('type_activity', 'header') + ->first(); + + $totalCost = Activity::select(DB::raw('sum(cast(rencana_biaya as double precision))')) + ->where("proyek_id", $data->proyek_id) + ->where("version_gantt_id", $data->version_gantt_id) + ->where("parent_id", $rootActivity->id) + ->first(); + + if($totalCost->sum > 0){ + $activities = Activity::where("proyek_id", $data->proyek_id)->where("version_gantt_id", $data->version_gantt_id)->get(); + foreach ($activities as $activity) { + $activity->update([ + "bobot_planning" => ( (int)$activity->rencana_biaya / $totalCost->sum ) * 100, + "updated_by" => auth()->user() ? auth()->user()->name : "system", + ]); + $activity->save(); + } + } + + $data->updateCostPlanning(); + $data->updatePersentaseProgress(); + $data->updateCostActual(); + }); + + static::deleted(function($data) { + if(Activity::where("parent_id", $data->parent_id)->count() == 0) + Activity::find($data->parent_id)->update(["type_activity"=>"task"]); + + $data->updateCostPlanning(); + $data->updatePersentaseProgress(); + $data->updateCostActual(); + }); + + } + + 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() + { + $siblings = Activity::where("parent_id", $this->parent_id); + $sumProgress = $siblings->sum("persentase_progress"); + $totalChild = $siblings->count(); + + $this->persentage_progress = $sumProgress / $totalChild; + if($parent = Activity::find($this->parent_id)){ + $parent->update([ + "persentase_progress" => $sumProgress / $totalChild, + ]); + } + } + + 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, + ]); + } + } + + public function getJobsDoneAttribute() + { + $tmpPercentage = []; + $dataPlan = AssignMaterial::where('activity_id', $this->id)->get(); + if($dataPlan->isEmpty()) + return 0; + foreach ($dataPlan as $value) { + $tmpPercentage[] = 100; + $getDataVolActual = ReportActivityMaterial::where('assign_material_id', '=', $value->id)->sum("qty"); + $percentage = ($getDataVolActual * 100) / $value->qty_planning; + if($value->status_activity != 'done'){ + $tmpPercentage[] = $percentage >= 100 ? 90 : $percentage; + } + } + return array_sum($tmpPercentage) > 0 ? array_sum($tmpPercentage) / count($tmpPercentage) : 0; + } + + 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) + ->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()); + } + }