max("id"); if(!$maxGanttId){ $data = array( "proyek_id" => $id ); } else { $data = array( "last_gantt_id" => $maxGanttId, "proyek_id" => $id ); } return $data; } // dipake di dashboard project & bod public function getSCurve($request){ $allGantt = []; if(!is_int($request)){ $dataPayload = $request->all(); if(isset($dataPayload['gantt_id'])){ $allGantt[] = $dataPayload['gantt_id']; }else{ $allGantt[] = MasterFunctionsHelper::getLatestGantt($dataPayload['project_id']); } } else { $allGantt[] = MasterFunctionsHelper::getLatestGantt($request); } foreach($allGantt as $gantt){ if (!isset($gantt['last_gantt_id'])) { $ganttId = $gantt; } else { $ganttId = $gantt['last_gantt_id']; } $gantt = VersionGantt::find($ganttId)->toArray(); // foreach ($gantt as $key => $value) { // Log::info('gantt '.$value.' index '.$key); // } if (isset($gantt['calculation_type'])) { if($gantt['calculation_type'] == 'simple') { // to do return MasterFunctionsHelper::calculateProgressBasedOnSimple($gantt); } else { return MasterFunctionsHelper::calculateProgressBasedOnReportMaterial($gantt); } } } } public function calculateProgressBasedOnReportMaterial($keyGantt) { DB::enableQueryLog(); $dataFinal=[]; $dataPayload = []; $dataPayload['period'] = 'week'; $totalACWP = 0; $totalBCWP = 0; $tempPercentage = []; $dataProject = Project::find($keyGantt['proyek_id']); $dataHeader = Activity::where('type_activity', 'header')->where("proyek_id", $keyGantt['proyek_id'])->where("version_gantt_id", $keyGantt['id'])->first(); if(isset($dataPayload['end_date']) && $dataPayload['end_date'] > $dataProject->akhir_proyek){ $dataPayload['end_date'] = $dataProject->akhir_proyek; } if($dataHeader){ $totalRencanaBudget = Activity::where('parent_id', $dataHeader->id)->where("proyek_id", $keyGantt['proyek_id'])->where("version_gantt_id", $keyGantt['id'])->sum("rencana_biaya"); }else{ $totalRencanaBudget = Activity::whereNull('parent_id')->where("proyek_id", $keyGantt['proyek_id'])->where("version_gantt_id", $keyGantt['id'])->sum("rencana_biaya"); } if(!Activity::where("version_gantt_id", $keyGantt['id'])->first()) return $dataFinal; $alreadyHasReport = DB::table('report_activity_material as a') ->select('a.id') ->join('m_activity as b', 'b.id', '=', 'a.activity_id') ->where('b.version_gantt_id', '=', $keyGantt['id']) ->exists(); // note : delete this // if(!$alreadyHasReport) // return $dataFinal; $minDate = Activity::where('version_gantt_id', $keyGantt['id'])->whereNull('parent_id')->pluck('start_date')->first(); $begin = new \DateTime($minDate.' Monday'); if(isset($dataPayload['end_date'])){ $maxDate = $dataPayload['end_date']; $end = new \DateTime($maxDate. ' Friday'); $end->modify('next Friday'); /* $interval = \DateInterval::createFromDateString('1 day'); */ // should be using this but its bugged $interval = new \DateInterval('P7D'); } else { $maxDate = DB::table('assign_material_to_activity as ama') ->where("ama.proyek_id", $keyGantt['proyek_id']) ->join('m_activity as a', 'a.id', '=', 'ama.activity_id') ->where('a.version_gantt_id', '=', $keyGantt['id']) ->max("plan_date"); // plan date overlapped with assign_material_to_activity's, it should be m_activity's $end = new \DateTime($maxDate. ' Friday'); $end->modify('next Friday'); $interval = new \DateInterval('P7D'); } $period = new \DatePeriod($begin, $interval, $end); $arr_ActualM = []; $tempDate = []; $tempPercentagePlan = []; $tempPercentagePlanWhr = []; $tempPercentageReal = []; $tempTtlPercentPlan=0; $tempTtlPercentActual=0; $currentACWP = 0; $currentBCWP = 0; foreach ($period as $dt) { $minSevenDays = new \Datetime($dt->format("Y-m-d")); $minSevenDays = $minSevenDays->modify('-7 day')->format("Y-m-d"); $dataPlanM = DB::table('assign_material_to_activity as ama') ->select('ama.activity_id', 'ama.qty_planning', 'ama.plan_date', 'ama.start_activity', 'a.bobot_planning', 'a.biaya_actual', 'a.duration', 'a.persentase_progress') ->join('m_activity as a', 'a.id', '=', 'ama.activity_id') ->where('ama.proyek_id', '=', $keyGantt['proyek_id']) ->where('a.version_gantt_id', '=', $keyGantt['id']) ->whereDate('ama.plan_date', '<=',$dt->format("Y-m-d")) ->whereDate('ama.plan_date', '>', $minSevenDays) ->get(); $dataActualM = DB::table('report_activity_material as ram') ->select('ram.activity_id', 'ram.qty', 'ram.report_date', 'a.bobot_planning', 'a.biaya_actual', 'a.duration', 'a.persentase_progress') ->join('m_activity as a', 'a.id', '=', 'ram.activity_id') ->where('a.version_gantt_id', '=', $keyGantt['id']) ->where('a.proyek_id', '=', $keyGantt['proyek_id']) ->whereDate('ram.report_date', '<=',$dt->format("Y-m-d")) ->whereDate('ram.report_date', '>',$minSevenDays) ->get(); $dataTempPlan = []; $x = 0; $sumPercentagePlan=0; $totalACWP = isset($totalACWP) ? $totalACWP : 0; $totalBCWP = isset($totalBCWP) ? $totalBCWP : 0; foreach ($dataPlanM as $keyPlanM) { $sumVolPlan = DB::table('assign_material_to_activity') ->select('activity_id', DB::raw('SUM(qty_planning) as ttl_qty_plan')) ->where('activity_id', '=', $keyPlanM->activity_id) ->groupBy('activity_id') ->first(); $dataTempPlan [$x]['activity_id'] = $keyPlanM->activity_id; $dataTempPlan [$x]['qty_plan'] = $keyPlanM->qty_planning; $dataTempPlan [$x]['plan_date'] = $keyPlanM->plan_date; $dataTempPlan [$x]['start_activity'] = $keyPlanM->start_activity; $dataTempPlan [$x]['bobot_planning'] = $keyPlanM->bobot_planning; $dataTempPlan [$x]['ttl_plan'] = $sumVolPlan->ttl_qty_plan; $dataTempPlan [$x]['biaya_actual'] = $keyPlanM->biaya_actual; $dataTempPlan [$x]['duration'] = $keyPlanM->duration; $dataTempPlan [$x]['persentase_progress'] = $keyPlanM->persentase_progress; try { $dataTempPlan [$x]['percentage'] = ($keyPlanM->qty_planning/$sumVolPlan->ttl_qty_plan)*$keyPlanM->bobot_planning; $sumPercentagePlan+=($keyPlanM->qty_planning/$sumVolPlan->ttl_qty_plan)*$keyPlanM->bobot_planning; if(isset($keyPlanM->duration) && $keyPlanM->duration > 0) $totalBCWP += (((($keyPlanM->persentase_progress*$keyPlanM->bobot_planning)/100)/$keyPlanM->duration)* $totalRencanaBudget)/100; else $totalBCWP = 0; $dataTempPlan [$x]['totalBCWP'] = $totalBCWP; } catch (\DivisionByZeroError $e) { return response()->json(['message' => $e->getMessage()]); } $x++; } $w = 0; $dataTempReport = []; $sumPercentageActual=0; foreach ($dataActualM as $keyActualM) { $sumVolActual = DB::table('assign_material_to_activity') ->select('activity_id', DB::raw('SUM(qty_planning) as ttl_qty_plan')) ->where('activity_id', '=', $keyActualM->activity_id) ->groupBy('activity_id') ->first(); $dataTempReport [$w]['activity_id'] = $keyActualM->activity_id; $dataTempReport [$w]['qty'] = $keyActualM->qty; $dataTempReport [$w]['report_date'] = $keyActualM->report_date; $dataTempReport [$w]['bobot_planning'] = $keyActualM->bobot_planning; $dataTempReport [$w]['ttl_plan'] = $sumVolActual->ttl_qty_plan; $dataTempReport [$w]['biaya_actual'] = $keyActualM->biaya_actual; $dataTempReport [$w]['duration'] = $keyActualM->duration; $dataTempReport [$w]['persentase_progress'] = $keyActualM->persentase_progress; try { // assign_material_to_activity $checkStatusActivity = DB::table('assign_material_to_activity') ->select('activity_id', 'status_activity') ->where('activity_id', '=', $keyActualM->activity_id) ->orderBy('status_activity', 'ASC') ->first(); $dataTempReport [$w]['percentage'] = ($keyActualM->qty/$sumVolActual->ttl_qty_plan)*$keyActualM->bobot_planning; // $sumPercentageActual+=($keyActualM->qty/$sumVolActual->ttl_qty_plan)*$keyActualM->bobot_planning; // if($keyActualM->qty/$sumVolActual->ttl_qty_plan >= 1){ if($checkStatusActivity->status_activity == 'done'){ $sumPercentageActual+=$keyActualM->bobot_planning; // $sumPercentageActual = $sumPercentageActual > $keyGantt['progress'] ? $keyGantt['progress'] : $sumPercentageActual; }else{ if($keyActualM->qty/$sumVolActual->ttl_qty_plan >= 1){ $sumPercentageActual+=(($keyActualM->qty/$sumVolActual->ttl_qty_plan)*$keyActualM->bobot_planning)*(95/100); // $sumPercentageActual = $sumPercentageActual > $keyGantt['progress'] ? $keyGantt['progress'] : $sumPercentageActual; }else{ $sumPercentageActual+=($keyActualM->qty/$sumVolActual->ttl_qty_plan)*$keyActualM->bobot_planning; // $sumPercentageActual = $sumPercentageActual > $keyGantt['progress'] ? $keyGantt['progress'] : $sumPercentageActual; } } // }else { // if($checkStatusActivity->status_activity == 'done'){ // $sumPercentageActual+=($keyActualM->qty/$keyActualM->qty)*$keyActualM->bobot_planning; // }else{ // $sumPercentageActual+=($keyActualM->qty/$sumVolActual->ttl_qty_plan)*$keyActualM->bobot_planning; // } // } $totalACWP += $keyActualM->biaya_actual/$keyActualM->duration; } catch (\DivisionByZeroError $e) { return response()->json(['message' => $e->getMessage()]); } $dataTempReport [$w]['totalacwp'] = $totalACWP; $w++; } $arr_ActualM[] = array( 'date'=>$dt->format("Y-m-d"), 'percentPlan'=>$sumPercentagePlan, 'percentActual'=> $sumPercentageActual, 'plan'=>$dataTempPlan, 'actual'=>$dataTempReport, ); if(isset($dataPayload['period']) && $dataPayload['period'] == 'week'){ $tempTtlPercentPlan+= $sumPercentagePlan; $tempTtlPercentActual+= $sumPercentageActual; // if($tempTtlPercentPlan >= 100 || $tempTtlPercentActual >= $keyGantt['progress'];){ // if($tempTtlPercentActual >= 100) // $tempTtlPercentActual = 100; // if($tempTtlPercentPlan >= 100) // $tempTtlPercentPlan = 100; // if($tempTtlPercentActual >= $keyGantt['progress']) // $tempTtlPercentActual = $keyGantt['progress']; if($tempTtlPercentPlan >= 100) $tempTtlPercentPlan = 100; // $sumPercentageActual > $keyGantt['progress'] ? $keyGantt['progress'] : $sumPercentageActual // } $currentACWP += $totalACWP; $currentBCWP += $totalBCWP; $tempPercentage[] = array(round($tempTtlPercentPlan,2), round($tempTtlPercentActual,2)); $tempPercentagePlan[] = round($tempTtlPercentPlan, 2); $tempPercentagePlanWhr[] = ["weekly period", $tempPercentagePlan]; $tempPercentageReal[] = round($tempTtlPercentActual, 2); if($tempTtlPercentPlan >= 100 && $tempTtlPercentActual >= 100){ break; } }else{ $tempPercentage[] = array(round($sumPercentagePlan,2), round($sumPercentageActual,2)); $tempPercentagePlan[] = round($sumPercentagePlan, 2); $tempPercentageReal[] = round($sumPercentageActual, 2); } $tempDate[] = array($dt->format("Y-m-d")); } try { if(round($totalACWP,0) > $totalRencanaBudget){ $estimatedCost = round($totalACWP,0)+0; }else{ $estimatedCost = ($totalRencanaBudget+0); } } catch (\DivisionByZeroError $e) { return response()->json([ 'message' => $e->getMessage(), "line" => 566, 'gantt' => $keyGantt, ]); } $estimatedCost = $totalACWP > $totalRencanaBudget ? $totalACWP : $totalRencanaBudget; $costDeviation = $totalRencanaBudget - $estimatedCost; if($costDeviation > 0){ $potential = "SAVING"; } else { $potential = $costDeviation == 0 ? "ON BUDGET" : "OVERRUN"; } $dataResponse = array( "date" =>$tempDate, "percentage" =>$tempPercentage, "percentagePlan" => $tempPercentagePlan, "percentageReal" => $tempPercentageReal, "data_details" =>$arr_ActualM, "budget_control" =>array("current_budget"=> $totalRencanaBudget, "acwp" => round($totalACWP,0), "bcwp" => round($totalBCWP,0), "rem_to_complete" => ($totalRencanaBudget - round($totalACWP,0)), "add_cost_to_complete" => 0, "estimated_at_completion" => $estimatedCost, "cost_deviation" => $costDeviation, "potential" => $potential, ) ); $dataFinal[] = array( "proyek_name"=> $dataProject->nama, "data"=>$dataResponse, "gantt"=>$keyGantt ); return $dataFinal; } public function calculateProgressBasedOnSimple($keyGantt){ DB::enableQueryLog(); $dataFinal=[]; $dataPayload = []; $dataPayload['period'] = 'week'; $dataProject = Project::find($keyGantt['proyek_id']); $dataHeader = Activity::where('type_activity', 'header')->where("proyek_id", $keyGantt['proyek_id'])->where("version_gantt_id", $keyGantt['id'])->first(); if(isset($dataPayload['end_date']) && $dataPayload['end_date'] > $dataProject->akhir_proyek){ $dataPayload['end_date'] = $dataProject->akhir_proyek; } if($dataHeader){ $totalRencanaBudget = Activity::where('parent_id', $dataHeader->id)->where("proyek_id", $keyGantt['proyek_id'])->where("version_gantt_id", $keyGantt['id'])->sum("rencana_biaya"); }else{ $totalRencanaBudget = Activity::whereNull('parent_id')->where("proyek_id", $keyGantt['proyek_id'])->where("version_gantt_id", $keyGantt['id'])->sum("rencana_biaya"); } if(!Activity::where("version_gantt_id", $keyGantt['id'])->first()) return $dataFinal; // $alreadyHasReport = DB::table('report_activity_material as a') // ->select('a.id') // ->join('m_activity as b', 'b.id', '=', 'a.activity_id') // ->where('b.version_gantt_id', '=', $keyGantt['id']) // ->exists(); // if(!$alreadyHasReport) // return $dataFinal; $minDate = Activity::where('version_gantt_id', $keyGantt['id'])->whereNull('parent_id')->pluck('start_date')->first(); $begin = new \DateTime($minDate.' Monday'); if(isset($dataPayload['end_date'])){ $maxDate = $dataPayload['end_date']; $end = new \DateTime($maxDate); /* $interval = \DateInterval::createFromDateString('1 day'); */ // should be using this but its bugged $interval = new \DateInterval('P7D'); } else { // $maxDate = DB::table('assign_material_to_activity as ama') // ->where("ama.proyek_id", $keyGantt['proyek_id']) // ->join('m_activity as a', 'a.id', '=', 'ama.activity_id') // ->where('a.version_gantt_id', '=', $keyGantt['id']) // ->max("plan_date"); // plan date overlapped with assign_material_to_activity's, it should be m_activity's $maxDate = Activity::where('version_gantt_id', $keyGantt['id'])->whereNull('parent_id')->pluck('end_date')->first(); $end = new \DateTime($maxDate. ' Friday'); $interval = new \DateInterval('P7D'); } $period = new \DatePeriod($begin, $interval, $end); $arr_ActualM = []; $tempDate = []; $tempPercentagePlan = []; $tempPercentagePlanWhr = []; $tempPercentageReal = []; $tempTtlPercentPlan=0; $tempTtlPercentActual=0; $currentACWP = 0; $currentBCWP = 0; foreach ($period as $dt) { $minSevenDays = new \Datetime($dt->format("Y-m-d")); $minSevenDays = $minSevenDays->modify('-7 day')->format("Y-m-d"); $dataPlanM = DB::table('m_activity') ->select('id as activity_id', 'bobot_planning', 'start_date', 'biaya_actual', 'duration', 'persentase_progress') // ->join('m_activity as a', 'a.id', '=', 'activity_id') ->where('proyek_id', '=', $keyGantt['proyek_id']) ->where('type_activity', '=', 'task') ->where('version_gantt_id', '=', $keyGantt['id']) ->whereDate('start_date', '<=',$dt->format("Y-m-d")) ->whereDate('start_date', '>', $minSevenDays) ->get(); $dataActualM = DB::table('m_activity as a') ->select('mapl.id as id_progress_log', 'mapl.activity_id', 'mapl.variance', 'mapl.created_at', 'a.bobot_planning', 'a.biaya_actual', 'a.duration', 'a.persentase_progress') ->join('m_activity_progress_log as mapl', 'a.id', '=', 'mapl.activity_id') ->where('a.version_gantt_id', '=', $keyGantt['id']) ->where('a.type_activity', '=', 'task') ->where('mapl.variance', '>', 0) ->where('a.proyek_id', '=', $keyGantt['proyek_id']) ->whereDate('mapl.created_at', '<=',$dt->format("Y-m-d")) ->whereDate('mapl.created_at', '>',$minSevenDays) ->get(); $dataTempPlan = []; $x = 0; $sumPercentagePlan=0; $totalACWP = isset($totalACWP) ? $totalACWP : 0; $totalBCWP = isset($totalBCWP) ? $totalBCWP : 0; foreach ($dataPlanM as $keyPlanM) { $dataTempPlan [$x]['activity_id'] = $keyPlanM->activity_id; $dataTempPlan [$x]['qty_plan'] = $keyPlanM->bobot_planning; $dataTempPlan [$x]['plan_date'] = $keyPlanM->start_date; $dataTempPlan [$x]['start_activity'] = $keyPlanM->start_date; $dataTempPlan [$x]['bobot_planning'] = $keyPlanM->bobot_planning; $dataTempPlan [$x]['ttl_plan'] = $keyPlanM->bobot_planning; $dataTempPlan [$x]['biaya_actual'] = $keyPlanM->biaya_actual; $dataTempPlan [$x]['duration'] = $keyPlanM->duration; $dataTempPlan [$x]['persentase_progress'] = $keyPlanM->persentase_progress; try { $dataTempPlan [$x]['percentage'] = $keyPlanM->bobot_planning; $sumPercentagePlan+=$keyPlanM->bobot_planning; $totalBCWP += 0; $dataTempPlan [$x]['totalBCWP'] = $totalBCWP; } catch (\DivisionByZeroError $e) { return response()->json(['message' => $e->getMessage()]); } $x++; } $w = 0; $dataTempReport = []; $sumPercentageActual=0; foreach ($dataActualM as $keyActualM) { $sumVolActual = DB::table('m_activity_progress_log') ->select('id', DB::raw('SUM(variance) as ttl_percen_act')) ->where('id', '=', $keyActualM->id_progress_log) ->groupBy('id') ->first(); $dataTempReport [$w]['id_progress_log'] = $keyActualM->id_progress_log; // $dataTempReport [$w]['qty'] = $keyActualM->qty; $dataTempReport [$w]['report_date'] = $keyActualM->created_at; $dataTempReport [$w]['bobot_planning'] = $keyActualM->bobot_planning; // $dataTempReport [$w]['ttl_plan'] = $sumVolActual->ttl_percen_act ? $sumVolActual->ttl_percen_act : 0; $dataTempReport [$w]['biaya_actual'] = $keyActualM->biaya_actual; $dataTempReport [$w]['duration'] = $keyActualM->duration; $dataTempReport [$w]['persentase_progress'] = $keyActualM->persentase_progress; try { $dataTempReport [$w]['percentage'] = $sumVolActual->ttl_percen_act ? ($sumVolActual->ttl_percen_act/100)*$keyActualM->bobot_planning : 0; $sumPercentageActual+=$sumVolActual->ttl_percen_act ? ($sumVolActual->ttl_percen_act/100)*$keyActualM->bobot_planning : 0; $totalACWP += $keyActualM->biaya_actual/$keyActualM->duration; } catch (\DivisionByZeroError $e) { return response()->json(['message' => $e->getMessage()]); } $dataTempReport [$w]['totalacwp'] = $totalACWP; $w++; } $arr_ActualM[] = array( 'date'=>$dt->format("Y-m-d"), 'percentPlan'=>$sumPercentagePlan, 'percentActual'=>$sumPercentageActual, 'plan'=>$dataTempPlan, 'actual'=>$dataTempReport, ); if(isset($dataPayload['period']) && $dataPayload['period'] == 'week'){ $tempTtlPercentPlan+= $sumPercentagePlan; $tempTtlPercentActual+= $sumPercentageActual; if($tempTtlPercentPlan >= 100 || $tempTtlPercentActual >= 100){ if($tempTtlPercentActual >= 100) $tempTtlPercentActual = 100; if($tempTtlPercentPlan >= 100) $tempTtlPercentPlan = 100; } $currentACWP += $totalACWP; $currentBCWP += $totalBCWP; $tempPercentage[] = array(round($tempTtlPercentPlan,2), round($tempTtlPercentActual,2)); $tempPercentagePlan[] = round($tempTtlPercentPlan, 2); $tempPercentagePlanWhr[] = ["weekly period", $tempPercentagePlan]; $tempPercentageReal[] = round($tempTtlPercentActual, 2); if($tempTtlPercentPlan >= 100 && $tempTtlPercentActual >= 100){ break; } }else{ $tempPercentage[] = array(round($sumPercentagePlan,2), round($sumPercentageActual,2)); $tempPercentagePlan[] = round($sumPercentagePlan, 2); $tempPercentageReal[] = round($sumPercentageActual, 2); } $tempDate[] = array($dt->format("Y-m-d")); } try { if(round($totalACWP,0) > $totalRencanaBudget){ $estimatedCost = round($totalACWP,0)+0; }else{ $estimatedCost = ($totalRencanaBudget+0); } } catch (\DivisionByZeroError $e) { return response()->json([ 'message' => $e->getMessage(), "line" => 566, 'gantt' => $keyGantt, ]); } $estimatedCost = $totalACWP > $totalRencanaBudget ? $totalACWP : $totalRencanaBudget; $costDeviation = $totalRencanaBudget - $estimatedCost; if($costDeviation > 0){ $potential = "SAVING"; } else { $potential = $costDeviation == 0 ? "ON BUDGET" : "OVERRUN"; } $dataResponse = array( "date" =>$tempDate, "percentage" =>$tempPercentage, "percentagePlan" => $tempPercentagePlan, "percentageReal" => $tempPercentageReal, "data_details" =>$arr_ActualM, "budget_control" =>array("current_budget"=> $totalRencanaBudget, "acwp" => round($totalACWP,0), "bcwp" => round($totalBCWP,0), "rem_to_complete" => ($totalRencanaBudget - round($totalACWP,0)), "add_cost_to_complete" => 0, "estimated_at_completion" => $estimatedCost, "cost_deviation" => $costDeviation, "potential" => $potential, ) ); $dataFinal[] = array( "proyek_name"=> $dataProject->nama, "data"=>$dataResponse, "gantt"=>$keyGantt, ); return $dataFinal; } }