@ -2,33 +2,39 @@
namespace App\Http\Controllers;
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use DateTime;
use App\Models\Link;
use App\Models\User;
use App\Models\Image;
use App\Models\Holiday;
use App\Models\Project;
use App\Models\Project;
use App\Models\UserToProyek;
use App\Models\Activity;
use App\Models\Activity;
use App\Models\UserToActivity;
use App\Jobs\ProcessSCurve;
use App\Models\User;
use App\Models\OfficeHours;
use App\Models\ProjectType;
use App\Models\ProjectPhase;
use App\Models\UserToProyek;
use App\Models\VersionGantt;
use Illuminate\Http\Request;
use App\Models\ProjectIssues;
use App\Models\AssignMaterial;
use App\Models\AssignMaterial;
use App\Models\DokumenProject;
use App\Models\DokumenProject;
use App\Models\FolderDocumentProyek;
use App\Models\ProjectCharter;
use App\Models\ProjectCharter;
use App\Models\ProjectApproval;
use App\Models\ReportActivity;
use App\Models\ProjectPhase;
use App\Models\ProjectType;
use App\Models\ProjectMileStone;
use App\Models\ProjectParticipants;
use App\Models\ShowHideColumn;
use App\Models\ShowHideColumn;
use App\Models\VersionGantt;
use App\Models\UserToActivity;
use App\Models\Image;
use App\Models\CommentActivity;
use App\Models\Link;
use App\Models\ActivityDokumen;
use App\Models\ActivityDokumen;
use App\Models\Holiday;
use App\Models\CommentActivity;
use App\Models\ReportActivity;
use App\Models\ProjectApproval;
use App\Models\OfficeHours;
use App\Models\ProjectMileStone;
use App\Models\ProjectChecklists;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\DB;
use App\Models\ProjectParticipants;
use App\Models\FolderDocumentProyek;
use App\Helpers\MasterFunctionsHelper;
use App\Helpers\MasterFunctionsHelper;
use App\Models\ProjectRisks;
use App\Models\ReportActivityMaterial;
use App\Models\ReportActivityMaterial;
use Illuminate\Support\Facades\Artisan;
const API_GEOLOCATION = "https://nominatim.oslogdev.com/search/ADDR?format=json&addressdetails=1&limit=1";
const API_GEOLOCATION = "https://nominatim.oslogdev.com/search/ADDR?format=json&addressdetails=1&limit=1";
@ -63,11 +69,22 @@ class ProjectController extends Controller
return response()->json(['status'=>'success','message'=>'Data added!', 'data_result' =>$dataResultInsert, 'code'=> 200], 200);
return response()->json(['status'=>'success','message'=>'Data added!', 'data_result' =>$dataResultInsert, 'code'=> 200], 200);
}
}
public function edit($id){
public function edit($id)
if(empty($id) || !is_int((int)$id))
{
return response()->json(['status'=>'failed','message'=>'id is required!','code'=>400], 400);
if (empty($id) || !is_int((int)$id))
return response()->json(['status' => 'failed', 'message' => 'id is required!', 'code' => 400], 400);
$result = Project::find($id);
$result = Project::query()
->from('m_proyek AS mp')
->where('mp.id', $id)
->selectRaw('value_proyek,scoupe_of_work,kode_sortname,jumlah_stakeholder,nama,mulai_proyek,akhir_proyek,area_kerja,rencana_biaya,biaya_actual,company,pm_id,type_proyek_id,divisi_id,persentase_progress,keterangan,durasi_proyek,progress_by_worklog,currency_symbol,late_consequence,assumtion,currency_code,currency_name,project_objectives,considered_success_when,potential_risk,testing_environment,budget_health,phase_id,calculation_status');
if (!is_null($result->first()['divisi_id'])) {
$result->leftJoin('m_divisi', 'mp.divisi_id', '=', 'm_divisi.id')
->addSelect(DB::raw('m_divisi.name AS nama_divisi'));
}
$result = $result->first();
if(!$result)
if(!$result)
return response()->json(['status'=>'failed','message'=> 'Data not found!','code'=> 404], 404);
return response()->json(['status'=>'failed','message'=> 'Data not found!','code'=> 404], 404);
@ -143,6 +160,9 @@ class ProjectController extends Controller
ProjectApproval::where('proyek_id', $project_id)->delete();
ProjectApproval::where('proyek_id', $project_id)->delete();
ProjectMileStone::where('proyek_id', $project_id)->delete();
ProjectMileStone::where('proyek_id', $project_id)->delete();
ProjectParticipants::where('proyek_id', $project_id)->delete();
ProjectParticipants::where('proyek_id', $project_id)->delete();
ProjectChecklists::where('proyek_id', $project_id)->delete();
ProjectIssues::where('proyek_id', $project_id)->delete();
ProjectRisks::where('proyek_id', $project_id)->delete();
$this->deleteVersionGantt($project_id);
$this->deleteVersionGantt($project_id);
$this->deleteDokumenProject($project_id);
$this->deleteDokumenProject($project_id);
}
}
@ -217,64 +237,53 @@ class ProjectController extends Controller
public function list()
public function list()
{
{
$data = Project::orderBy('id', 'desc')->get();
$data = Project::select(
'id',
'kode_sortname',
'jumlah_stakeholder',
'nama',
'mulai_proyek',
'akhir_proyek',
'area_kerja',
'lokasi_kantor',
'rencana_biaya',
'biaya_actual',
'company',
'pm_id',
'type_proyek_id',
'divisi_id',
'persentase_progress',
'keterangan',
'durasi_proyek',
'progress_by_worklog',
'status',
'currency_symbol',
'currency_code',
'currency_name',
'project_objectives',
'considered_success_when',
'potential_risk',
'testing_environment',
'currency_code',
'currency_symbol',
'currency_name',
'budget_health',
'phase_id',
'calculation_status',
'created_at',
'created_by',
'updated_at',
'updated_by'
)->orderBy('id', 'desc')->get();
$countData = $data->count();
$countData = $data->count();
if(!$data)
if(!$data)
return response()->json(['status'=>'failed','message'=>'Data not found!','code'=> 404], 404);
return response()->json(['status'=>'failed','message'=>'Data not found!','code'=> 404], 404);
$scheduleWarningThreshold = 10;
$scheduleDangerThreshold = 5;
foreach($data as $d){
$progress = $costVariance = $actualCost = 0;
$lastActivity = null;
$scheduleHealth = "on-track";
$rootActivity = Activity::whereNull('parent_id')->where('proyek_id', $d->id)->orderBy('version_gantt_id', 'desc')->first();
if($rootActivity){
$costVariance = (int)$d->rencana_biaya - (int)$rootActivity->biaya_actual;
$actualCost = $rootActivity->biaya_actual ?? 0;
$progress = $rootActivity->persentase_progress ?? 0;
$timeleft = strtotime($d->mulai_proyek) - strtotime($rootActivity->end_date);
$date1 = new \DateTime(date("Y-m-d", strtotime($d->mulai_proyek)));
$date2 = new \DateTime(date("Y-m-d", strtotime($rootActivity->end_date)));
$daysRemaining = $date2->diff($date1);
$daysRemaining = $daysRemaining->d;
if($daysRemaining < = $scheduleDangerThreshold) {
$scheduleHealth = "danger";
} elseif ($daysRemaining < = $scheduleWarningThreshold) {
$scheduleHealth = "warning";
}
$lastActivity = date("d/m/Y", strtotime($rootActivity->end_date));
}
$d->plannedInterval = date("d/m/Y", strtotime($d->mulai_proyek)) . " - " . date("d/m/Y", strtotime($d->akhir_proyek));
$d->plannedCost = $d->rencana_biaya;
$d->actualCost = $actualCost;
$d->lastActivity = $lastActivity ?? "-";
$d->costVariance = $costVariance;
$d->costHealth = $d->budget_health;
$d->scheduleHealth = $scheduleHealth;
$d->progress = $progress;
$d->lastGanttId = VersionGantt::where("proyek_id", $d->id)->orderBy('id', 'desc')->first()->id ?? null;
$d->manpower = UserToProyek::where("proyek_id", $d->id)->count() ?? 0;
$d->projectManager = DB::table('m_proyek')
->join('m_users', 'm_users.id', '=', 'm_proyek.pm_id')
->where('m_proyek.id', $d->id)
->pluck('m_users.name')
->first();
if($d->area_kerja != ''){
$d->geolocation = $this->httpReq($d->area_kerja);
$d->geolocation = [];
} else {
$d->geolocation = [];
}
}
$totalPlannedCost = array_sum(array_map('intval', array_column($data->toArray(), 'plannedCost')));
$totalPlannedCost = array_sum(array_map('intval', array_column($data->toArray(), 'plannedCost')));
$totalActualCost = $data->sum('actualCost');
$totalActualCost = $data->sum('actualCost');
$manpowers = User::count();
$manpowers = User::count();
$projectsOnDanger = Project::where('budget_health', 'danger ')->count();
$projectsOnDanger = Project::where('budget_health', 'overrun')->count();
$projectPhases = ProjectPhase::orderBy('order', 'asc')->pluck('name');
$projectPhases = ProjectPhase::orderBy('order', 'asc')->pluck('name');
$projectTypes = ProjectType::orderBy('id', 'asc')->pluck('name');
$projectTypes = ProjectType::orderBy('id', 'asc')->pluck('name');
try {
try {
@ -288,7 +297,7 @@ class ProjectController extends Controller
}
}
try {
try {
$projectsByType = DB::table('m_proyek')
$projectsByType = DB::table('m_proyek')
->select('m_type_proyek.name', DB::raw('count(* ) as total'))
->select('m_type_proyek.name', DB::raw('count(m_type_proyek.id ) as total'))
->join('m_type_proyek', 'm_type_proyek.id', '=', 'm_proyek.type_proyek_id')
->join('m_type_proyek', 'm_type_proyek.id', '=', 'm_proyek.type_proyek_id')
->groupBy('m_type_proyek.name')
->groupBy('m_type_proyek.name')
->get();
->get();
@ -332,6 +341,63 @@ class ProjectController extends Controller
return response()->json(['status'=>'success','code'=>200, 'data' => $data], 200);
return response()->json(['status'=>'success','code'=>200, 'data' => $data], 200);
}
}
public function calculateSCurve(Request $request){
$sCurve = Project::select('scurve')->where('id', $request->project_id)->first();
return response()->json(['status'=>'success','code'=>200, 'data' => json_decode($sCurve->scurve)], 200);
}
public function sCurveCommand(Request $request){
Artisan::call('calculate:scurve', [
'project_id' => $request->project_id
]);
// $project = Project::find($request->project_id);
// if ($project) {
// dispatch(new ProcessSCurve($project));
// return response()->json(['message' => 'S Curve calculation queued']);
// }
// return response()->json(['message' => 'Project not found'], 404);
}
public function getLinearSCurve(Request $request){
$data = MasterFunctionsHelper::getLinearSCurve($request);
return response()->json(['status'=>'success','code'=>200, 'data' => $data], 200);
}
public static function setSyncDate($activity_id, $activity, $report) {
$status = AssignMaterial::where('activity_id', $activity_id)->first();
if (!isset($status)) {
$reports = array(
'activity_id' => $activity_id,
'min_date' => new DateTime($activity->start_date),
'max_date' => new DateTime($activity->end_date),
'status' => 'open'
);
return $reports;
}
if (!isset($status->status_activity)) {
$status->status_activity = 'open';
}
if ($status->status_activity != 'done') {
$minDate = date_create($report->report_date);
$maxDate = date_create($report->report_date);
date_add($maxDate, date_interval_create_from_date_string($activity->duration . " days"));
} else {
$material = AssignMaterial::where('activity_id', $activity_id)->first();
$minDate = date_create($material->start_activity);
$maxDate = date_create($material->finish_activity);
}
$reports = array(
'activity_id' => $activity_id,
'min_date' => $minDate,
'max_date' => $maxDate,
'status' => $status->status_activity
);
return $reports;
}
public function synchronizeReport($gantt_id)
public function synchronizeReport($gantt_id)
{
{
$activities = Activity::where("version_gantt_id", $gantt_id)->get();
$activities = Activity::where("version_gantt_id", $gantt_id)->get();
@ -343,31 +409,40 @@ class ProjectController extends Controller
if ($countReports === 1) {
if ($countReports === 1) {
$dataReports = ReportActivityMaterial::where('activity_id', $activity_id)->orderBy('report_date')->get();
$dataReports = ReportActivityMaterial::where('activity_id', $activity_id)->orderBy('report_date')->get();
foreach($dataReports as $dr) {
foreach($dataReports as $dr) {
$reports[] = array(
$reports[] = ProjectController::setSyncDate($activity_id, $activity, $dr);
'activity_id'=>$activity_id,
'min_date'=>$dr->report_date,
'max_date'=>date_modify(date_create($dr->report_date), "1 days")
);
}
}
}
}
if ($countReports > 1) {
if ($countReports > 1) {
$firstReport = ReportActivityMaterial::where('activity_id', $activity_id)->orderBy('report_date')->first();
$firstReport = ReportActivityMaterial::where('activity_id', $activity_id)->orderBy('report_date')->first();
$lastReport = ReportActivityMaterial::where('activity_id', $activity_id)->orderByDesc('report_date')->first();
$reports[] = ProjectController::setSyncDate($activity_id, $activity, $firstReport);
$reports[] = array(
}
'activity_id'=>$activity_id,
$successor = Link::where('t_activity_id', $activity->id)->first();
'min_date'=>$firstReport->report_date,
if ($successor) {
'max_date'=>date_modify(date_create($lastReport->report_date), "1 days")
$predecessor = Activity::find($successor->s_activity_id);
);
$activity->start_date = $predecessor->end_date;
$end_date = new DateTime($activity->start_date);
$end_date->modify("+" . $activity->duration . " days");
$activity->end_date = $end_date->format("Y-m-d H:i:sO");
}
}
$activity->reports = $reports;
$activity->save() ;
}
}
/* return response()->json(['status'=>'success','data'=> $reports,'code'=>200], 200); */
/* return response()->json(['status'=>'success','data'=> $reports,'code'=>200], 200); */
/* return response()->json(['status'=>'success','data'=> $activities,'code'=>200], 200); */
/* return response()->json(['status'=>'success','data'=> $activities,'code'=>200], 200); */
for ($i=0; $i < count ( $ reports ) ; $ i + + ) {
for ($i=0; $i < count ( $ reports ) ; $ i + + ) {
$activity = Activity::find($reports[$i]['activity_id']);
$activity = Activity::find($reports[$i]['activity_id']);
$activity->start_date = $reports[$i]['min_date'];
if($reports[$i]['status'] != 'done'){
$activity->end_date = $reports[$i]['max_date'];
$reports[$i]['max_date']->modify('-1 day');
}else if($reports[$i]['status'] == 'done'){
$activity->actual_end = $reports[$i]['max_date']->setTime(23,59,59);
}
$activity->start_date = $reports[$i]['min_date']; //same early
$activity->end_date = $reports[$i]['max_date']->setTime(23,59,59); // same early
$startDate = new DateTime($activity->start_date);
$endDate = new DateTime($activity->end_date);
$duration = MasterFunctionsHelper::countDays($activity->version_gantt_id, $startDate, $endDate);
$activity->duration = $duration;
$activity->actual_start = $reports[$i]['min_date'];
$activity->save();
$activity->save();
}
}
@ -382,6 +457,8 @@ class ProjectController extends Controller
$activity->update([
$activity->update([
"planned_start"=>$activity->start_date,
"planned_start"=>$activity->start_date,
"planned_end"=>$activity->end_date,
"planned_end"=>$activity->end_date,
"early_start"=>$activity->start_date,
"early_end"=>$activity->end_date,
]);
]);
}
}
@ -389,18 +466,38 @@ class ProjectController extends Controller
}
}
public function getInvoiceIntegration(Request $request) {
public function getInvoiceIntegration(Request $request) {
// $search = urlencode($request->search);
$ganttCount = VersionGantt::where('proyek_id', $request->id)->count();
// if(empty($search))
$search = urlencode($request->search);
// return response()->json(['status'=>'error', 'message'=>'Empty query string!'], 400);
if(empty($search))
// $url = str_replace("SEARCH", $search, config('api.adw').'/project_cost?project_no=SEARCH');
return response()->json(['status'=>'error', 'message'=>'Empty query string!'], 400);
$url = str_replace("SEARCH", $search, config('api.adw').'/project_cost?project_no=SEARCH');
$response = null;
$response = MasterFunctionsHelper::curlReq($url);
if (isset($request->gantt_id)) {
$response->data->total_cost = $response->data->total_cost / $ganttCount;
}
return response()->json(['status'=>'success', 'data'=> $response, 'code'=>200], 200);
return response()->json(['status'=>'success', 'data'=> $response, 'code'=>200], 200);
}
}
public function getByUser($id)
{
$alias = "utp";
$userProyek = UserToProyek::query()
->from('assign_hr_to_proyek AS ' . $alias)
->where([
['is_customer', true],
['user_id', $id]
])
->leftJoin('m_users', $alias.'.user_id', '=', 'm_users.id')
->leftJoin('m_proyek', $alias.'.proyek_id', '=', 'm_proyek.id')
->leftJoin('m_type_proyek', 'm_proyek.type_proyek_id', '=', 'm_type_proyek.id')
->select('m_proyek.*', 'm_type_proyek.name AS join_second_name','m_users.name AS join_first_name')
->get();
$totalRecord = $userProyek->count();
public function detail($id){
return response()->json(['status' => 'success', 'code' => 200, 'data' => $userProyek, 'totalRecord' => $totalRecord], 200);
}
public function detail(Request $request, $id, $gantt_id = null, $s_curve = null){
if(empty($id) || !is_int((int)$id))
if(empty($id) || !is_int((int)$id))
return response()->json(['status'=>'failed','message'=>'id is required!','code'=>400], 400);
return response()->json(['status'=>'failed','message'=>'id is required!','code'=>400], 400);
@ -408,11 +505,49 @@ class ProjectController extends Controller
if(!$result)
if(!$result)
return response()->json(['status'=>'failed','message'=> 'Data not found!','code'=> 404], 404);
return response()->json(['status'=>'failed','message'=> 'Data not found!','code'=> 404], 404);
if (!isset($gantt_id)) {
$gantt = MasterFunctionsHelper::getLatestGantt($id);
$gantt = MasterFunctionsHelper::getLatestGantt($id);
$ganttId = $gantt['last_gantt_id'];
} else {
$ganttId = $gantt_id;
}
$result->projectManager = User::where('id', $result->pm_id)->value('name');
$result->projectManager = User::where('id', $result->pm_id)->value('name');
$result->header = Activity::whereNull('parent_id')->where("proyek_id", $id)->where("version_gantt_id", $gantt['last_gantt_id'])->first();
return response()->json(['status'=>'success','code'=> 200,'data'=>$result], 200);
if (isset($s_curve)) {
$result->header = Activity::whereNull('parent_id')->where("proyek_id", $id)->first();
$actualStartExist = Activity::where('proyek_id', $id)->whereNotNull('actual_start')->exists();
$actualEndExist = Activity::where('proyek_id', $id)->whereNotNull('actual_end')->exists();
$query = Activity::where('proyek_id', $id);
} else {
$result->header = Activity::whereNull('parent_id')->where("proyek_id", $id)->where("version_gantt_id", $ganttId)->first();
$actualStartExist = Activity::where('version_gantt_id', $ganttId)->whereNotNull('actual_start')->exists();
$actualEndExist = Activity::where('version_gantt_id', $ganttId)->whereNotNull('actual_end')->exists();
$query = Activity::where('version_gantt_id', $ganttId);
}
if ($actualStartExist) {
$startDate = $query->orderBy('actual_start')->value('start_date');
} else {
$startDate = $query->orderBy('start_date')->value('start_date');
}
if ($actualEndExist) {
$endDate = $query->orderByDesc('actual_end')->value('end_date');
} else {
$endDate = $query->orderByDesc('end_date')->value('end_date');
}
$plannedStart = Activity::where('version_gantt_id', $ganttId)
->orderBy('planned_start')
->value('planned_start');
$plannedEnd = Activity::where('version_gantt_id', $ganttId)
->orderByDesc('planned_end')
->value('planned_end');
$result->header->start_date = $startDate;
$result->header->end_date = $endDate;
$result->header->planned_start = $plannedStart;
$result->header->planned_end = $plannedEnd;
return response()->json(['status'=>'success','code'=> 200,'data'=>$result, 'gantt'=>$ganttId], 200);
}
}
public function getOverdueActivities(Request $request){
public function getOverdueActivities(Request $request){
@ -425,11 +560,23 @@ class ProjectController extends Controller
if(!$result)
if(!$result)
return response()->json(['status'=>'failed','message'=> 'Project not found!','code'=> 404], 404);
return response()->json(['status'=>'failed','message'=> 'Project not found!','code'=> 404], 404);
//TODO possible overdue bug
//TODO possible overdue bug
if(isset($payload['till_date']))
$endDate = Activity::where('proyek_id', $payload['id'])
$overdueActivities = Activity::where('proyek_id', $payload['id'])->whereNotNull('parent_id')->where('persentase_progress', '!=', 100)->whereDate('end_date','< =',$payload['till_date'])->orderBy('end_date', 'asc')->get();
->orderByDesc('end_date')
else
->value('end_date');
if(isset($payload['till_date'])) {
if (isset($payload['scurve'])) {
$overdueActivities = Activity::where('proyek_id', $payload['id'])->whereNotNull('parent_id')->where('persentase_progress', '!=', 100)->whereDate('end_date','< =',$endDate)->orderBy('end_date', 'asc')->get();
} else {
$overdueActivities = Activity::where('version_gantt_id', $payload['gantt'])->whereNotNull('parent_id')->where('persentase_progress', '!=', 100)->whereDate('end_date','< =',$endDate)->orderBy('end_date', 'asc')->get();
}
}
else {
if (isset($payload['scurve'])) {
$overdueActivities = Activity::where('proyek_id', $payload['id'])->whereNotNull('parent_id')->where('persentase_progress', '!=', 100)->orderBy('end_date', 'asc')->get();
$overdueActivities = Activity::where('proyek_id', $payload['id'])->whereNotNull('parent_id')->where('persentase_progress', '!=', 100)->orderBy('end_date', 'asc')->get();
} else {
$overdueActivities = Activity::where('version_gantt_id', $payload['gantt'])->whereNotNull('parent_id')->where('persentase_progress', '!=', 100)->orderBy('end_date', 'asc')->get();
}
}
$result->overdueActivities = $overdueActivities;
$result->overdueActivities = $overdueActivities;
return response()->json(['status'=>'success','code'=> 200,'data'=>$result], 200);
return response()->json(['status'=>'success','code'=> 200,'data'=>$result], 200);
@ -456,9 +603,8 @@ class ProjectController extends Controller
}
}
public function getManpower($proyek_id){
public function getManpower($proyek_id){
$manPower = UserToProyek::where('proyek_id', $proyek_id)->get();
$manCount = UserToProyek::where('proyek_id', $proyek_id)->count();
$manCount = $manPower->count();
return response()->json(['totalRecord'=>$manCount]);
return response()->json(['data'=>$manPower, 'totalRecord'=>$manCount]);
}
}
public function getAssignedHR($gantt_id){
public function getAssignedHR($gantt_id){