%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /var/www/html/hr/api/app/Models/
Upload File :
Create Path :
Current File : /var/www/html/hr/api/app/Models/Timecard.php

<?php

namespace App\Models;

use App\Exceptions\AppException;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\DB;
use Throwable;

/**
 * @property integer id
 * @property mixed date
 * @property mixed start_time
 * @property mixed end_time
 * @property string notes
 * @property string status
 * @property float hours
 * @property float approved_hours
 * @property integer user_id
 * @property integer approved_by
 * @property integer project_id
 * @property User user
 * @property User approvedBy
 * @property Project project
 */
class Timecard extends BaseModel
{
    const TO_APPROVE = 'TO_APPROVE';
    const APPROVED = 'APPROVED';

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'date',
        'start_time',
        'end_time',
        'notes',
        'status',
        'hours',
        'approved_hours',
    ];

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'id'             => 'integer',
        'date'           => 'date',
        'start_time'     => 'time',
        'end_time'       => 'time',
        'notes'          => 'string',
        'status'         => 'string',
        'hours'          => 'float',
        'approved_hours' => 'float',
        'user_id'        => 'integer',
        'project_id'     => 'integer',
    ];

    /**
     * @param $data
     * @return self
     * @throws Throwable
     */
    public static function createItem($data)
    {
        try {
            $user = self::getLoggedInUser();
            $timecardsOnDate = self::query()
                                   ->where('user_id', $user->id)
                                   ->where('date', Carbon::parse($data['date']))
                                   ->where('start_time', '<', Carbon::parse($data['end_time']))
                                   ->where('end_time', '>', Carbon::parse($data['start_time']))
                                   ->exists();
            if ($timecardsOnDate) {
                throw new AppException('This timecard entry overlaps with other timecards on the same date, please check start and end time.');
            }
            /** @var Project $project */
            $project = Project::query()
                              ->find($data['project_id']);
            if (!$project->canLogTimecard($user->id)) {
                throw new AppException('You are not allowed to log hours into this project');
            }
            DB::beginTransaction();
            /** @var self $item */
            $item = self::query()
                        ->make([
                            'date'       => $data['date'],
                            'start_time' => $data['start_time'],
                            'end_time'   => $data['end_time'],
                            'notes'      => $data['notes'],
                            'hours'      => self::diffInHours($data['end_time'], $data['start_time']),
                        ]);
            $item->user()
                 ->associate($user);
            $item->project()
                 ->associate($data['project_id']);
            $item->save();
            DB::commit();
            return $item;
        } catch (Throwable $e) {
            DB::rollBack();
            throw $e;
        }
    }

    public function user()
    {
        return $this->belongsTo(User::class);
    }

    public function project()
    {
        return $this->belongsTo(Project::class);
    }

    public static function bulkApprove($timecards)
    {
        forEach ($timecards as $t) {
            /** @var Timecard $timecard */
            $timecard = Timecard::query()
                                ->find($t['id']);
            $timecard->approve($t['approved_hours']);
        }
    }

    public function approve($approved_hours)
    {
        $this->status = self::APPROVED;
        $this->approved_hours = $approved_hours;
        $this->approvedBy()
             ->associate(self::getLoggedInUser());
        $this->save();
        $this->save();
    }

    public function approvedBy()
    {
        return $this->belongsTo(User::class, 'approved_by');
    }

    public static function bulkUnApprove($timecards)
    {
        self::query()
            ->whereIn('id', $timecards)
            ->update([
                'status'         => self::TO_APPROVE,
                'approved_hours' => null,
            ]);
    }

    public static function approveAll()
    {
        $user = BaseModel::getLoggedInUser();
        $timecards = Timecard::query()
                             ->where('status', self::TO_APPROVE)
                             ->private($user);

        if ($user->isManager()) {
            $timecards = $timecards->whereHas('project', function (Builder $p) use ($user) {
                $p->where('manager_id', $user->id);
            });
        }

        $timecards->update([
            'status'         => self::APPROVED,
            'approved_hours' => DB::raw("`hours`"),
            'approved_by'    => $user->id,
        ]);
    }

    /**
     * @param $data
     * @return self
     * @throws Throwable
     */
    public function updateItem($data)
    {
        try {
            if (!$this->isEditable()) {
                throw new AppException(trans('timecards.cant_edit_due_approval'));
            }
            $timecardsOnDate = self::query()
                                   ->where('id', '!=', $this->id)
                                   ->where('date', Carbon::parse($data['date']))
                                   ->where('start_time', '<', Carbon::parse($data['end_time']))
                                   ->where('end_time', '>', Carbon::parse($data['start_time']))
                                   ->exists();
            if ($timecardsOnDate) {
                throw new AppException(trans('timecards.overlapping'));
            }
            DB::beginTransaction();
            $this->date = $data['date'];
            $this->start_time = $data['start_time'];
            $this->end_time = $data['end_time'];
            $this->notes = $data['notes'];
            $this->hours = self::diffInHours($data['end_time'], $data['start_time']);
            $this->project()
                 ->associate($data['project_id']);
            $this->save();
            DB::commit();
            return $this;
        } catch (Throwable $e) {
            DB::rollBack();
            throw $e;
        }
    }

    public function isEditable()
    {
        return $this->status !== self::APPROVED;
    }

    /**
     * @throws Throwable
     */
    public function deleteItem()
    {
        try {
            if (!$this->isDeletable()) {
                throw new AppException(trans('timecards.cant_delete_due_approval'));
            }
            $this->delete();
        } catch (Throwable $e) {
            throw $e;
        }
    }

    public function isDeletable()
    {
        return $this->status !== self::APPROVED;
    }

    public function scopePrivate(Builder $query, $user)
    {
        return $query->whereHas('project', 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);
            });
        });
    }

}

Zerion Mini Shell 1.0