HEX
Server: Microsoft-IIS/8.5
System: Windows NT YDAWBH120 6.3 build 9600 (Windows Server 2012 R2 Standard Edition) AMD64
User: tentjecom_web (0)
PHP: 7.4.14
Disabled: NONE
Upload Files
File: D:/HostingSpaces/MdnDirecteur/hours.komma.cloud/app/Komma/Subprojects/SubprojectService.php
<?php

namespace App\Komma\Subprojects;


use App\Komma\Messages\MessageController;
use App\Komma\Projects\Project;
use App\Komma\Settings\Subprojecttemplates\SubprojectTemplate;
use App\Komma\Tasks\TaskService;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Pagination\Paginator;


class SubprojectService
{
    protected $messageController;
    protected $taskService;

    public function __construct(MessageController $messageController, TaskService $taskService)
    {
        $this->messageController = $messageController;
        $this->taskService = $taskService;
    }

    /**
     * Get the sum of all the hours in the subproject and divide them in the relevant groups
     *
     * @param $subproject
     * @return number
     */
    public function getSumSubprojectHours($subProject)
    {
        $totalBillWithBudget = [];
        $totalBillWithoutBudget = [];
        $totalNotBillWithBudget = [];
        $totalNotBillWithoutBudget = [];
        $totalExceedsSubProject = [];



        //loop trough each task of subproject
        foreach ($subProject->Tasks as $task) {

            $data = $this->getTaskHours($task, $subProject->budget);

            //get task hours sum
            $array[] = $data['billWithBudget'];
            $arrayNotBil[] = $data['billWithoutBudget'];
            $arrayNotBud[] = $data['notBillWithBudget'];
            $arrayExceeds[] = $data['notBillWithoutBudget'];
            $arrayBilled[] = $data['exceedsSubProject'];

            //sum task hours
            $totalBillWithBudget += [$task->TaskTemplate->name => array_sum($array)];
            $totalBillWithoutBudget += [$task->TaskTemplate->name => array_sum($arrayNotBil)];
            $totalNotBillWithBudget += [$task->TaskTemplate->name => array_sum($arrayNotBud)];
            $totalNotBillWithoutBudget += [$task->TaskTemplate->name => array_sum($arrayExceeds)];
            $totalExceedsSubProject += [$task->TaskTemplate->name => array_sum($arrayBilled)];

            //clear array
            $data = [];
            $array = [];
            $arrayNotBil = [];
            $arrayNotBud = [];
            $arrayExceeds = [];
            $arrayBilled = [];
        }

        //sum and return all task hours
        return compact('totalBillWithBudget', 'totalBillWithoutBudget', 'totalNotBillWithBudget', 'totalNotBillWithoutBudget', 'totalExceedsSubProject');
    }

    /**
     * Get all the hours in the subproject and divide them in the relevant groups
     *
     * @param  Subproject  $subProject
     * @return array
     */
    public function getSubProjectHours(Subproject $subProject)
    {
        $billWithBudget = [];
        $billWithoutBudget = [];
        $notBillWithBudget = [];
        $notBillWithoutBudget = [];
        $exceedsSubProject = [];

        $tasks = $subProject->Tasks;

        $tasks->loadMissing('Hours');

        //loop trough task of subproject
        foreach ($tasks as $task) {

            $data = $this->getTaskHours($task, $subProject->budget);
            $billWithBudget[] = $data['billWithBudget'];
            $billWithoutBudget[] = $data['billWithoutBudget'];
            $notBillWithBudget[] = $data['notBillWithBudget'];
            $notBillWithoutBudget[] = $data['notBillWithoutBudget'];
            $exceedsSubProject[] = $data['exceedsSubProject'];

        }

        $totalBillWithBudget = array_sum($billWithBudget);
        $totalBillWithoutBudget = array_sum($billWithoutBudget);
        $totalNotBillWithBudget = array_sum($notBillWithBudget);
        $totalNotBillWithoutBudget = array_sum($notBillWithoutBudget);
        $totalExceedsSubproject = array_sum($exceedsSubProject);

        return compact('totalBillWithBudget', 'totalBillWithoutBudget', 'totalNotBillWithBudget', 'totalNotBillWithoutBudget', 'totalExceedsSubproject');
    }

    private function getTaskHours($task, $budget){
        $bWB = [];
        $bWoB = [];

        $nBWB = [];
        $nBWoB = [];

        $eS = [];

        $hours = $task->Hours;
        //loop though hours
        foreach ($hours as $hour) {
            if($hour->exceed_subproject == 0) {

                if ($hour->billable == 1) {

                    if($budget > 0) {
                        $bWB[] = floatval($hour->value);
                    } else {
                        $bWoB[] = floatval($hour->value);
                    }

                } else {

                    if($budget > 0) {
                        $nBWB[] = floatval($hour->value);
                    } else {
                        $nBWoB[] = floatval($hour->value);
                    }

                }

            } else {
                $eS[] = floatval($hour->value);
            }
        }

        $billWithBudget = array_sum($bWB);
        $billWithoutBudget = array_sum($bWoB);
        $notBillWithBudget = array_sum($nBWB);
        $notBillWithoutBudget = array_sum($nBWoB);
        $exceedsSubProject = array_sum($eS);

        return compact('billWithBudget', 'billWithoutBudget', 'notBillWithBudget', 'notBillWithoutBudget', 'exceedsSubProject');
    }


    /**
     * @param $request
     */
    public function checkIfExist(Request $request)
    {
        //find project
        $project = Project::find($request->project);

        //if the chosen subproject exist
        if (!empty($project->Subprojects->where('name', $request->name)->first())) {
            //message
            $this->messageController->exist("Deelproject", "project");

            // Find redirect route
            $redirectRoute = 'projecten';
            //if ref exist
            if ($request->filled('ref')) {
                //get ref
                $ref = $request->get('ref');
                //replace - with / if - exist
                $redirectRoute = str_replace('-', '/', $ref);
            }

            //return redirect route string
            return $redirectRoute;
        }

    }


    /**
     * @param $request
     * @return mixed
     */
    public function storeSubproject(Request $request)
    {
        $subproject = $this->store($request);

        //message + activity
        $this->messageController->create("Nieuw deelproject", Subproject::find($subproject->id));

        return $subproject;
    }


    /**
     * @param $request
     * @return mixed
     */
    public function store(Request $request)
    {
        //store subproject
        $subprojectTemplate = SubprojectTemplate::find($request->subproject);

        $subproject = \DB::transaction(function () use ($request, $subprojectTemplate) {
            //store new sub project
            $subproject = new Subproject();
            $subproject->subproject_template_id = $request->subproject;
            $subproject->project_id = $request->project;
            $subproject->name = $request->name;
            $subproject->budget = !empty($request->budget) ? $request->budget : 0;
            $subproject->billable = $request->billable;
            $subproject->hourly_rate = $request->hourly_rate;
            $subproject->save();

            if($request->has('tasks')) {
                $subproject->TaskTemplates()->sync($request->tasks);
            } else {
                //loop trough related task templates
                foreach ($subprojectTemplate->TaskTemplates as $taskTemplate) {
                    //make $request array to store task
                    $taskRequest = ['subproject' => $subproject->id];
                    $taskRequest += ['task' => $taskTemplate->id];
                    //make object of array
                    $taskRequest = (object)$taskRequest;

                    //go to store task
                    $this->taskService->store($taskRequest);
                }
            }
            return $subproject;
        });

        //return subproject
        return $subproject;
    }


    /**
     * @param $items
     * @param $perPage
     * @param null $page
     * @return LengthAwarePaginator
     */
    public function paginate($items, $perPage, $page = null)
    {
        $page = $page ?: (Paginator::resolveCurrentPath() ? 1 : 1);
        $items = $items instanceof Collection ? $items : Collection::make($items);
        return new LengthAwarePaginator($items->forPage($page, $perPage), $items->count(), $perPage, $page, ['path' => Paginator::resolveCurrentPath()]);
    }


    /**
     * @param  Subproject  $subproject
     * @return array
     */
    public function getBudget(Subproject $subproject)
    {
        //$values = (object)['totalHoursBil' => 0, 'totalHoursNotBil' => 0, 'totalHours' => 0, 'totalExceedHours' => 0];

        $subproject->loadMissing('Tasks');

        $values = (object)$this->getSubProjectHours($subproject);
        $totalHours = $values->totalBillWithBudget+$values->totalBillWithoutBudget+$values->totalNotBillWithBudget+$values->totalNotBillWithoutBudget+$values->totalExceedsSubproject;
        $totalHoursInBudget = $values->totalBillWithBudget+$values->totalNotBillWithBudget+$values->totalExceedsSubproject;

        $actualRate = (object)$this->ActualHourlyRate($subproject->Project, $totalHours, $subproject->budget + $values->totalBillWithoutBudget);

        $array = [
            'totalBillWithBudget' => $values->totalBillWithBudget,
            'totalBillWithoutBudget' => $values->totalBillWithoutBudget,
            'totalNotBillWithBudget' => $values->totalNotBillWithBudget,
            'totalNotBillWithoutBudget' => $values->totalNotBillWithoutBudget,
            'totalExceedsSubproject' => $values->totalExceedsSubproject,
            'totalHours' => $totalHours,
            'totalHoursInBudget' => $totalHoursInBudget,
            'actualRate' => $actualRate->actualRate,
            'count' => $actualRate->i
        ];

        return $array;
    }

    /**
     * Calculate the actual hourly rate based on the budget and the written hours
     *
     * So projects that stay in budget, will have a positive ActualHourlyRate
     * Example:
     * $project->hourly_rate = €85
     * $totalBudget = 10
     * $totalHours = 5
     * 85*10 = 850 / 5 =  €170
     *
     * So projects that go over the budget, will have a negative ActualHourlyRate
     * Example:
     * $project->hourly_rate = €85
     * $totalBudget = 5
     * $totalHours = 10
     * 85*10 = 425 / 10 =  €42.50
     *
     * @param $subproject
     * @param $totalHours
     * @param $totalBudget
     * @return float
     */
    public function ActualHourlyRate($project, $totalHours, $totalBudget)
    {
        $i = 0;
        //calculate actual hourly rate of subproject
        if (empty($totalHours) || $project->hourly_rate == 0) {
            $actualRate = 0;
        } else {
            $actualRate = ($project->hourly_rate * $totalBudget) / $totalHours;
            $i = 1;
        }
        //return
        return compact('actualRate', 'i');
    }


    /**
     *  API call urls for the hour write form
     */

    public function getSubProjectWithTasksByID($id) {
        $subproject = Subproject::with(['Tasks', 'TaskTemplates', 'SubprojectTemplate'])->where('id', $id)->first();
        return !empty($subproject) ? $subproject : null;
    }

    public function getSubProjectByID($id) {
        $subproject = Subproject::where('id', $id)->first();
        return !empty($subproject) ? $subproject : null;
    }

    public function getProjectSubProgressBarByID($id){
        $getSubProject = $this->getSubProjectByID($id);
        $budgets = $this->getBudget($getSubProject);

        return view('partials.generalElements.progressBar',[
            'hoursNoBudget' => $budgets['totalBillWithoutBudget']+$budgets['totalNotBillWithoutBudget'],
            'budget' => $getSubProject->budget,
            'hoursLeftInBudget' => $getSubProject->budget - ($budgets['totalBillWithBudget']+$budgets['totalNotBillWithBudget']+$budgets['totalExceedsSubproject']),
            'barWidth' => $getSubProject->budget > 0 ? (100 / $getSubProject->budget) *  ($budgets['totalBillWithBudget']+$budgets['totalNotBillWithBudget']+$budgets['totalExceedsSubproject']) : 100,
        ]);

    }
}