%PDF- %PDF-
Direktori : /var/www/html/hr/api/app/Models/ |
Current File : /var/www/html/hr/api/app/Models/Project.php |
<?php namespace App\Models; use Carbon\Carbon; use Illuminate\Database\Eloquent\Builder; use Illuminate\Support\Facades\DB; use Throwable; /** * @property integer id * @property string code * @property string name * @property mixed start_date * @property mixed end_date * @property integer estimation * @property integer price * @property string currency * @property string notes * @property integer client_id * @property integer manager_id * @property Client client * @property User manager * @property mixed users * @property boolean is_private */ class Project extends BaseModel { const EURO = 'EURO'; const ALL = 'ALBANIAN_LEK'; const USD = 'USD'; /** * The attributes that are mass assignable. * * @var array */ protected $fillable = [ 'code', 'name', 'start_date', 'end_date', 'estimation', 'price', 'currency', 'notes', 'is_private', ]; protected $guarded = [ 'client_id', 'manager_id', ]; protected $dates = [ 'start_date', 'end_date', ]; /** * The attributes that should be cast to native types. * * @var array */ protected $casts = [ 'id' => 'integer', 'code' => 'string', 'name' => 'string', 'start_date' => 'date', 'end_date' => 'date', 'estimation' => 'integer', 'price' => 'integer', 'currency' => 'string', 'notes' => 'string', 'client_id' => 'integer', 'manager_id' => 'integer', ]; /** * @param $data * @return Project * @throws Throwable */ public static function createItem($data) { try { DB::beginTransaction(); /** @var Project $project */ $project = self::query() ->make([ 'code' => $data['code'], 'name' => $data['name'], 'start_date' => $data['start_date'], 'end_date' => $data['end_date'], 'estimation' => $data['estimation'], 'price' => $data['price'], 'currency' => array_key_exists('currency', $data) ? $data['currency'] : self::EURO, 'notes' => array_key_exists('notes', $data) ? $data['notes'] : null, ]); $project->client() ->associate($data['client_id']); $project->manager() ->associate($data['manager_id']); $project->save(); DB::commit(); return $project; } catch (Throwable $e) { DB::rollBack(); throw $e; } } public function client() { return $this->belongsTo(Client::class); } public function manager() { return $this->belongsTo(User::class, 'manager_id'); } /** * @param Carbon $date * @return array */ public static function getWorkDone(Carbon $date) { return self::query() ->join('timecards', 'timecards.project_id', '=', 'projects.id') ->where('timecards.date', '=', $date->format('Y-m-d')) ->groupBy('name') ->get([ 'name', DB::raw('sum(timecards.hours) as total'), ]); } public function scopePrivate(Builder $query, $user) { return $query->where(function (Builder $q) use ($user) { $q->where('is_private', false); $q->orWhere(function (Builder $u) use ($user) { $u->where('is_private', true); $u->where('manager_id', $user->id); }); }); } /** * @param $data * @return Project * @throws Throwable */ public function updateItem($data) { try { DB::beginTransaction(); $this->update([ 'code' => $data['code'], 'name' => $data['name'], 'start_date' => $data['start_date'], 'end_date' => $data['end_date'], 'estimation' => $data['estimation'], 'price' => $data['price'], 'currency' => array_key_exists('currency', $data) ? $data['currency'] : self::EURO, 'notes' => array_key_exists('notes', $data) ? $data['notes'] : null, ]); $this->client() ->associate($data['client_id']); $this->manager() ->associate($data['manager_id']); $this->save(); DB::commit(); return $this; } catch (Throwable $e) { DB::rollBack(); throw $e; } } public function timecards() { return $this->hasMany(Timecard::class); } public function users() { return $this->belongsToMany(User::class, 'user_project'); } public function canLogTimecard($userId) { return self::query() ->where('manager_id', $userId) ->orWhereHas('users', function (Builder $q) use ($userId) { $q->where('user_id', $userId); }) ->exists(); } public function performance() { $totalHours = Timecard::query() ->where('project_id', $this->id) ->get([ DB::raw('SUM(hours) as hours'), ]); $approvedTimecard = Timecard::query() ->where('project_id', $this->id) ->where('status', Timecard::APPROVED) ->get([ DB::raw('SUM(hours) as hours'), DB::raw('SUM(approved_hours) as approved_hours'), ]); $totalWorked = head(head($totalHours))->hours; $toApprove = head(head($totalHours))->hours - head(head($approvedTimecard))->hours; $approvedHours = head(head($approvedTimecard))->approved_hours; $users = Timecard::query() ->where('project_id', $this->id) ->groupBy('user_id') ->get('user_id') ->pluck('user_id'); $usersPerformance = collect(); foreach ($users as $user) { /** @var User $user */ $user = User::query() ->find($user); $usersPerformance->push($this->getUserPerformance($user)); } return [ 'total_worked' => $totalWorked, 'to_approve' => $toApprove, 'approved_hours' => $approvedHours, 'performance' => round(100 * $approvedHours / max($totalWorked, 1), 0) . "%", 'users_performance' => $usersPerformance, ]; } public function getUserPerformance(User $user) { $hoursWorked = Timecard::query() ->where('project_id', $this->id) ->where('user_id', $user->id) ->get([ DB::raw('SUM(hours) as hours'), DB::raw('SUM(approved_hours) as approved_hours'), ]); $toApprove = Timecard::query() ->where('project_id', $this->id) ->where('user_id', $user->id) ->where('status', Timecard::TO_APPROVE) ->get([ DB::raw('SUM(hours) as hours'), ]); $totalWorked = head(head($hoursWorked))->hours; $toApprove = head(head($toApprove))->hours; $approvedHours = head(head($hoursWorked))->approved_hours; $performance = round(100 * $approvedHours / max($totalWorked, 1), 0) . "%"; return [ 'name' => $user->getFullName(), 'total_worked' => $totalWorked, 'to_approve' => $toApprove, 'approved_hours' => $approvedHours, 'performance' => $performance, ]; } public function getPaymentInfo() { $approvedTimecard = Timecard::query() ->where('project_id', $this->id) ->where('status', Timecard::APPROVED) ->get([ DB::raw('SUM(approved_hours) as approved_hours'), ]); $payments = $this->payments() ->where('status', Payment::PAID) ->get(DB::raw('SUM(amount) as amount')); $approvedHours = head(head($approvedTimecard))->approved_hours; $estimatedPayment = $this->estimation * $this->price; $approvedPayment = $approvedHours * $this->price; $paid = head(head($payments))->amount; return [ 'estimation' => $this->estimation, 'estimated_payment' => $estimatedPayment, 'approved_payment' => $approvedPayment, 'paid' => $paid, 'to_pay' => max($approvedPayment - $paid, 0), 'currency' => $this->currency, ]; } public function payments() { return $this->hasMany(Payment::class); } }