first commit

This commit is contained in:
Noor E Ilahi
2026-01-09 12:54:53 +05:30
commit 7ccf44f7da
1070 changed files with 113036 additions and 0 deletions

102
app/Models/Attachment.php Normal file
View File

@@ -0,0 +1,102 @@
<?php
namespace App\Models;
use App\Enums\AttachmentStatus;
use Illuminate\Database\Eloquent\Concerns\HasUuids;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Eloquent as EloquentIdeHelper;
/**
* App\Models\Attachment
*
* @property string $id
* @property int $attachmentable_id
* @property string $attachmentable_type
* @property string $original_name
* @property string $mime_type
* @property string $extension
* @property int $size
* @property string $hash
* @property int $project_id
* @property int $user_id
* @property AttachmentStatus $status
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property-read Model|\Eloquent $attachmentAbleRelation
* @property-read \App\Models\Project|null $project
* @property-read \App\Models\User $user
* @method static EloquentBuilder|Attachment newModelQuery()
* @method static EloquentBuilder|Attachment newQuery()
* @method static EloquentBuilder|Attachment query()
* @method static EloquentBuilder|Attachment whereAttachmentableId($value)
* @method static EloquentBuilder|Attachment whereAttachmentableType($value)
* @method static EloquentBuilder|Attachment whereCreatedAt($value)
* @method static EloquentBuilder|Attachment whereHash($value)
* @method static EloquentBuilder|Attachment whereId($value)
* @method static EloquentBuilder|Attachment whereMimeType($value)
* @method static EloquentBuilder|Attachment whereOriginalName($value)
* @method static EloquentBuilder|Attachment whereProjectId($value)
* @method static EloquentBuilder|Attachment whereSize($value)
* @method static EloquentBuilder|Attachment whereStatus($value)
* @method static EloquentBuilder|Attachment whereUpdatedAt($value)
* @method static EloquentBuilder|Attachment whereUserId($value)
* @mixin EloquentIdeHelper
*/
class Attachment extends Model
{
use HasFactory;
use HasUuids;
protected $fillable = [
'attachmentable_id',
'attachmentable_type',
'original_name',
'mime_type',
'extension',
'size',
'hash',
'project_id',
'user_id',
'status',
];
protected $casts = [
'attachmentable_id' => 'integer',
'attachmentable_type' => 'string',
'original_name' => 'string',
'mime_type' => 'string',
'extension' => 'string',
'size' => 'integer',
'hash' => 'string',
'project_id' => 'integer',
'user_id' => 'integer',
'status' => AttachmentStatus::class,
];
/**
* It's important to name the relationship the same as the method because otherwise
* eager loading of the polymorphic relationship will fail on queued jobs.
*
* @see https://github.com/laravelio/laravel.io/issues/350
*/
public function attachmentAbleRelation(): MorphTo
{
return $this->morphTo('attachmentAbleRelation', 'attachmentable_type', 'attachmentable_id');
}
public function user(): BelongsTo
{
return $this->belongsTo(User::class, 'user_id');
}
public function project(): BelongsTo
{
return $this->belongsTo(Project::class, 'project_id');
}
}

View File

@@ -0,0 +1,58 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Database\Eloquent\Model;
use Eloquent as EloquentIdeHelper;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
/**
* Class CronTaskWorkers
*
* @property int $user_id
* @property int $task_id
* @property int $duration
* @property int $offset,
* @property bool $created_by_cron
* @method static EloquentBuilder|Task whereTaskId($value)
* @mixin EloquentIdeHelper
*/
class CronTaskWorkers extends Model
{
public $table = "cron_task_workers";
public $timestamps = false;
/**
* @var array
*/
protected $fillable = [
'user_id' => 'integer',
'task_id' => 'integer',
'duration' => 'integer',
'offset' => 'integer',
'created_by_cron' => 'boolean'
];
/**
* @var array
*/
protected $casts = [
'user_id' => 'integer',
'task_id' => 'integer',
'duration' => 'integer',
'offset' => 'integer',
'created_by_cron' => 'boolean'
];
public function task(): BelongsTo
{
return $this->belongsTo(Task::class, 'task_id')->withoutGlobalScopes();
}
public function user(): BelongsTo
{
return $this->belongsTo(User::class, 'user_id')->withoutGlobalScopes();
}
}

67
app/Models/Invitation.php Normal file
View File

@@ -0,0 +1,67 @@
<?php
namespace App\Models;
use App\Events\InvitationCreated;
use Eloquent as EloquentIdeHelper;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Carbon;
/**
* App\Models\Invitation
*
* @property int $id
* @property string $key
* @property string $email
* @property Carbon $expires_at
* @property int|null $role_id
* @method static EloquentBuilder|Invitation newModelQuery()
* @method static EloquentBuilder|Invitation newQuery()
* @method static EloquentBuilder|Invitation query()
* @method static EloquentBuilder|Invitation whereEmail($value)
* @method static EloquentBuilder|Invitation whereExpiresAt($value)
* @method static EloquentBuilder|Invitation whereId($value)
* @method static EloquentBuilder|Invitation whereKey($value)
* @method static EloquentBuilder|Invitation whereRoleId($value)
* @mixin EloquentIdeHelper
*/
class Invitation extends Model
{
/**
* @var bool
*/
public $timestamps = false;
/**
* @var array
*/
protected $fillable = [
'key',
'email',
'expires_at',
'role_id',
];
/**
* @var array
*/
protected $casts = [
'key' => 'string',
'email' => 'string',
'role_id' => 'int',
];
/**
* @var array
*/
protected $dates = [
'expires_at',
];
protected $dispatchesEvents = [
'created' => InvitationCreated::class,
'updated' => InvitationCreated::class,
];
}

49
app/Models/Module.php Normal file
View File

@@ -0,0 +1,49 @@
<?php
namespace App\Models;
use Eloquent;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Carbon;
/**
* App\Models\Module
*
* @property int $id
* @property string $name
* @property bool $enabled
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
* @method static Builder|Module newModelQuery()
* @method static Builder|Module newQuery()
* @method static Builder|Module query()
* @method static Builder|Module whereCreatedAt($value)
* @method static Builder|Module whereEnabled($value)
* @method static Builder|Module whereId($value)
* @method static Builder|Module whereName($value)
* @method static Builder|Module whereUpdatedAt($value)
* @mixin Eloquent
*/
class Module extends Model
{
/**
* @var array
*/
protected $fillable = ['name', 'enabled'];
/**
* @var array
*/
protected $casts = ['name' => 'string', 'enabled' => 'boolean'];
/**
* @var array
*/
protected $dates = ['created_at', 'updated_at'];
/**
* @var array
*/
protected $visible = ['name', 'enabled'];
}

60
app/Models/Priority.php Normal file
View File

@@ -0,0 +1,60 @@
<?php
namespace App\Models;
use Eloquent;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Carbon;
/**
* App\Models\Priority
*
* @property int $id
* @property string $name
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
* @property string|null $color
* @property-read Collection|Task[] $tasks
* @property-read int|null $tasks_count
* @method static EloquentBuilder|Priority newModelQuery()
* @method static EloquentBuilder|Priority newQuery()
* @method static EloquentBuilder|Priority query()
* @method static EloquentBuilder|Priority whereColor($value)
* @method static EloquentBuilder|Priority whereCreatedAt($value)
* @method static EloquentBuilder|Priority whereId($value)
* @method static EloquentBuilder|Priority whereName($value)
* @method static EloquentBuilder|Priority whereUpdatedAt($value)
* @mixin Eloquent
*/
class Priority extends Model
{
/**
* table name from database
* @var string
*/
protected $table = 'priorities';
/**
* @var array
*/
protected $fillable = [
'name',
'color',
];
/**
* @var array
*/
protected $casts = [
'name' => 'string',
'color' => 'string',
];
public function tasks(): HasMany
{
return $this->hasMany(Task::class, 'priority_id');
}
}

205
app/Models/Project.php Normal file
View File

@@ -0,0 +1,205 @@
<?php
namespace App\Models;
use App\Enums\ScreenshotsState;
use App\Scopes\ProjectAccessScope;
use App\Traits\ExposePermissions;
use Database\Factories\ProjectFactory;
use DB;
use Eloquent as EloquentIdeHelper;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Query\Builder as QueryBuilder;
use Illuminate\Support\Carbon;
/**
* App\Models\Project
*
* @property int $id
* @property int|null $company_id
* @property string $name
* @property string $description
* @property Carbon|null $deleted_at
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
* @property int $important
* @property string $source
* @property int|null $default_priority_id
* @property ScreenshotsState $screenshots_state
* @property-read Priority|null $defaultPriority
* @property-read array $can
* @property-read int|null $roles_count
* @property-read Collection|Status[] $statuses
* @property-read int|null $statuses_count
* @property-read Collection|Task[] $tasks
* @property-read ProjectPhase[] $phases
* @property-read int|null $tasks_count
* @property-read Collection|User[] $users
* @property-read int|null $users_count
* @method static ProjectFactory factory(...$parameters)
* @method static EloquentBuilder|Project newModelQuery()
* @method static EloquentBuilder|Project newQuery()
* @method static QueryBuilder|Project onlyTrashed()
* @method static EloquentBuilder|Project query()
* @method static EloquentBuilder|Project whereCompanyId($value)
* @method static EloquentBuilder|Project whereCreatedAt($value)
* @method static EloquentBuilder|Project whereDefaultPriorityId($value)
* @method static EloquentBuilder|Project whereDeletedAt($value)
* @method static EloquentBuilder|Project whereDescription($value)
* @method static EloquentBuilder|Project whereId($value)
* @method static EloquentBuilder|Project whereImportant($value)
* @method static EloquentBuilder|Project whereName($value)
* @method static EloquentBuilder|Project whereSource($value)
* @method static EloquentBuilder|Project whereUpdatedAt($value)
* @method static QueryBuilder|Project withTrashed()
* @method static QueryBuilder|Project withoutTrashed()
* @mixin EloquentIdeHelper
* @property-read Collection|Property[] $properties
* @property-read int|null $properties_count
*/
class Project extends Model
{
use SoftDeletes;
use ExposePermissions;
use HasFactory;
/**
* @var array
*/
protected $fillable = [
'company_id',
'name',
'description',
'important',
'source',
'default_priority_id',
'screenshots_state',
'group',
];
/**
* @var array
*/
protected $casts = [
'company_id' => 'integer',
'name' => 'string',
'description' => 'string',
'important' => 'integer',
'source' => 'string',
'default_priority_id' => 'integer',
];
/**
* @var array
*/
protected $dates = [
'deleted_at',
'created_at',
'updated_at',
];
protected const PERMISSIONS = ['update', 'update_members', 'destroy'];
protected static function boot(): void
{
parent::boot();
static::addGlobalScope(new ProjectAccessScope);
static::deleting(static function (Project $project) {
CronTaskWorkers::whereHas(
'task',
static fn(EloquentBuilder $query) => $query
->where('project_id', '=', $project->id)
)->delete();
$project->tasks()->delete();
});
}
public function tasks(): HasMany
{
return $this->hasMany(Task::class, 'project_id');
}
public function phases(): HasMany
{
return $this->hasMany(ProjectPhase::class);
}
public function users(): BelongsToMany
{
return $this->belongsToMany(User::class, 'projects_users')
->withPivot('role_id')
->using(ProjectUserPivot::class)
->withoutGlobalScopes();
}
public function group(): BelongsTo
{
return $this->belongsTo(ProjectGroup::class, 'group');
}
public function defaultPriority(): HasOne
{
return $this->hasOne(Priority::class, 'id', 'default_priority_id');
}
public function statuses(): BelongsToMany
{
return $this->belongsToMany(Status::class, 'projects_statuses', 'project_id', 'status_id')->withPivot('color');
}
public function getNameAttribute(): string
{
return empty($this->attributes['source']) || $this->attributes['source'] === 'internal'
? $this->attributes['name']
: ucfirst($this->attributes['source']) . ": {$this->attributes['name']}";
}
public function properties(): MorphMany
{
return $this->morphMany(Property::class, 'entity');
}
public function workers(): HasManyThrough
{
return $this->hasManyThrough(CronTaskWorkers::class, Task::class);
}
public function tasksRelations(): Attribute
{
$tasksIdsQuery = $this->tasks()->select('id');
return Attribute::make(get: fn() => DB::table('tasks_relations')
->whereIn('parent_id', $tasksIdsQuery)
->orWhereIn('child_id', $tasksIdsQuery)
->get(['parent_id', 'child_id']))->shouldCache();
}
protected function screenshotsState(): Attribute
{
return Attribute::make(
get: static function ($value): ScreenshotsState {
$projectState = ScreenshotsState::withGlobalOverrides($value);
return match ($projectState) {
null => ScreenshotsState::REQUIRED,
ScreenshotsState::ANY => ScreenshotsState::OPTIONAL,
default => $projectState,
};
},
set: static fn ($value) => (string)ScreenshotsState::getNormalizedValue($value),
)->shouldCache();
}
}

View File

@@ -0,0 +1,63 @@
<?php
namespace App\Models;
use App\Scopes\ProjectAccessScope;
use App\Traits\ExposePermissions;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\SoftDeletes;
use Kalnoy\Nestedset\AncestorsRelation;
use Kalnoy\Nestedset\DescendantsRelation;
use Kalnoy\Nestedset\NodeTrait;
use Kalnoy\Nestedset\QueryBuilder;
/**
* @method static QueryBuilder withDepth()
*/
class ProjectGroup extends Model
{
use SoftDeletes;
use HasFactory;
use ExposePermissions;
use NodeTrait;
protected $fillable = [
'name',
];
protected $dates = [
'deleted_at',
'created_at',
'updated_at',
];
protected const PERMISSIONS = ['update', 'destroy'];
public function groupParentsWithProjectsCount(): AncestorsRelation
{
return $this->ancestors()->withCount('projects')->defaultOrder();
}
public function groupParent(): HasOne
{
return $this->hasOne(ProjectGroup::class, 'id', 'parent_id');
}
public function descendantsWithDepthAndProjectsCount(): DescendantsRelation
{
return $this->descendants()->withCount('projects')->withDepth()->defaultOrder();
}
protected static function boot(): void
{
parent::boot();
}
public function projects(): HasMany
{
return $this->hasMany(Project::class, 'group');
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
class ProjectPhase extends Model
{
use HasFactory;
protected $fillable = [
'project_id',
'name'
];
public function project(): BelongsTo
{
return $this->belongsTo(Project::class);
}
public function tasks(): HasMany
{
return $this->hasMany(Task::class);
}
}

View File

@@ -0,0 +1,56 @@
<?php
namespace App\Models;
use Eloquent as EloquentIdeHelper;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
/**
* App\Models\ProjectReport
*
* @deprecated
* @property int $user_id
* @property string $user_name
* @property int $task_id
* @property int $project_id
* @property string $task_name
* @property string $project_name
* @property string $date
* @property string|null $duration
* @property-read Project $project
* @property-read Task $task
* @property-read User $user
* @method static Builder|ProjectReport newModelQuery()
* @method static Builder|ProjectReport newQuery()
* @method static Builder|ProjectReport query()
* @method static Builder|ProjectReport whereDate($value)
* @method static Builder|ProjectReport whereDuration($value)
* @method static Builder|ProjectReport whereProjectId($value)
* @method static Builder|ProjectReport whereProjectName($value)
* @method static Builder|ProjectReport whereTaskId($value)
* @method static Builder|ProjectReport whereTaskName($value)
* @method static Builder|ProjectReport whereUserId($value)
* @method static Builder|ProjectReport whereUserName($value)
* @mixin EloquentIdeHelper
*/
class ProjectReport extends Model
{
protected $table = 'project_report';
public function user(): BelongsTo
{
return $this->belongsTo(User::class, 'user_id');
}
public function task(): BelongsTo
{
return $this->belongsTo(Task::class, 'task_id');
}
public function project(): BelongsTo
{
return $this->belongsTo(Project::class, 'project_id');
}
}

View File

@@ -0,0 +1,27 @@
<?php
namespace App\Models;
use Eloquent;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\Pivot;
/**
* App\Models\ProjectUserPivot
*
* @method static Builder|ProjectUserPivot newModelQuery()
* @method static Builder|ProjectUserPivot newQuery()
* @method static Builder|ProjectUserPivot query()
* @mixin Eloquent
*/
class ProjectUserPivot extends Pivot
{
/**
* @var array
*/
protected $casts = [
'project_id' => 'int',
'user_id' => 'int',
'role_id' => 'int',
];
}

View File

@@ -0,0 +1,83 @@
<?php
namespace App\Models;
use Eloquent as EloquentIdeHelper;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Support\Carbon;
/**
* App\Models\ProjectsUsers
*
* @property int $project_id
* @property int $user_id
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
* @property int $role_id
* @property-read Project $project
* @property-read User $user
* @method static EloquentBuilder|ProjectsUsers newModelQuery()
* @method static EloquentBuilder|ProjectsUsers newQuery()
* @method static EloquentBuilder|ProjectsUsers query()
* @method static EloquentBuilder|ProjectsUsers whereCreatedAt($value)
* @method static EloquentBuilder|ProjectsUsers whereProjectId($value)
* @method static EloquentBuilder|ProjectsUsers whereRoleId($value)
* @method static EloquentBuilder|ProjectsUsers whereUpdatedAt($value)
* @method static EloquentBuilder|ProjectsUsers whereUserId($value)
* @mixin EloquentIdeHelper
*/
class ProjectsUsers extends Model
{
/**
* table name from database
*
* @var string
*/
protected $table = 'projects_users';
/**
* @var array
*/
protected $fillable = [
'project_id',
'user_id',
'role_id',
];
/**
* @var array
*/
protected $casts = [
'project_id' => 'integer',
'user_id' => 'integer',
'role_id' => 'integer',
];
/**
* @var array
*/
protected $dates = [
'created_at',
'updated_at',
];
public function user(): BelongsTo
{
return $this->belongsTo(User::class, 'user_id');
}
public function project(): BelongsTo
{
return $this->belongsTo(Project::class, 'project_id');
}
protected function setKeysForSaveQuery($query): EloquentBuilder
{
$query->where('project_id', '=', $this->getAttribute('project_id'))
->where('user_id', '=', $this->getAttribute('user_id'));
return $query;
}
}

95
app/Models/Property.php Normal file
View File

@@ -0,0 +1,95 @@
<?php
namespace App\Models;
use Eloquent as EloquentIdeHelper;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Query\Builder as QueryBuilder;
use Illuminate\Support\Carbon;
/**
* App\Models\Property
*
* @property int $id
* @property int $entity_id
* @property string $entity_type
* @property string $name
* @property string $value
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
* @property Carbon|null $deleted_at
* @method static EloquentBuilder|Property newModelQuery()
* @method static EloquentBuilder|Property newQuery()
* @method static QueryBuilder|Property onlyTrashed()
* @method static EloquentBuilder|Property query()
* @method static EloquentBuilder|Property whereCreatedAt($value)
* @method static EloquentBuilder|Property whereDeletedAt($value)
* @method static EloquentBuilder|Property whereEntityId($value)
* @method static EloquentBuilder|Property whereEntityType($value)
* @method static EloquentBuilder|Property whereId($value)
* @method static EloquentBuilder|Property whereName($value)
* @method static EloquentBuilder|Property whereUpdatedAt($value)
* @method static EloquentBuilder|Property whereValue($value)
* @method static QueryBuilder|Property withTrashed()
* @method static QueryBuilder|Property withoutTrashed()
* @mixin EloquentIdeHelper
* @property-read Model|EloquentIdeHelper $entity
*/
class Property extends Model
{
use SoftDeletes;
public const PROJECT_CODE = 'project';
public const TASK_CODE = 'task';
public const TIME_INTERVAL_CODE = 'time_interval';
public const USER_CODE = 'user';
public const TASK_COMMENT_CODE = 'task_comment';
protected $table = 'properties';
protected $fillable = [
'entity_id',
'entity_type',
'name',
'value',
];
protected $casts = [
'entity_id' => 'integer',
'entity_type' => 'string',
'name' => 'string',
'value' => 'string',
];
protected $dates = [
'created_at',
'updated_at',
'deleted_at',
];
public function entity(): MorphTo
{
return $this->morphTo();
}
public static function getTableName(): string
{
return with(new static())->getTable();
}
public static function loadMorphMap(): void
{
Relation::enforceMorphMap([
self::PROJECT_CODE => Project::class,
self::TASK_CODE => Task::class,
self::TIME_INTERVAL_CODE => TimeInterval::class,
self::USER_CODE => User::class,
self::TASK_COMMENT_CODE => TaskComment::class,
]);
}
}

101
app/Models/Role.php Normal file
View File

@@ -0,0 +1,101 @@
<?php
namespace App\Models;
use Cache;
use Eloquent as EloquentIdeHelper;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Query\Builder as QueryBuilder;
use Illuminate\Support\Carbon;
/**
* App\Models\Role
*
* @todo Find a way to delete this module. Currently used in many migrations =(
*
* @deprecated Since 4.0.0, but still can be used in some old migrations
* @property int $id
* @property string $name
* @property Carbon|null $deleted_at
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
* @property-read Collection|Project[] $projects
* @property-read int|null $projects_count
* @property-read Collection|User[] $users
* @property-read int|null $users_count
* @method static EloquentBuilder|Role newModelQuery()
* @method static EloquentBuilder|Role newQuery()
* @method static QueryBuilder|Role onlyTrashed()
* @method static EloquentBuilder|Role query()
* @method static EloquentBuilder|Role whereCreatedAt($value)
* @method static EloquentBuilder|Role whereDeletedAt($value)
* @method static EloquentBuilder|Role whereId($value)
* @method static EloquentBuilder|Role whereName($value)
* @method static EloquentBuilder|Role whereUpdatedAt($value)
* @method static QueryBuilder|Role withTrashed()
* @method static QueryBuilder|Role withoutTrashed()
* @mixin EloquentIdeHelper
*/
class Role extends Model
{
use SoftDeletes, HasFactory;
/**
* table name from database
*
* @var string
*/
protected $table = 'role';
/**
* @var array
*/
protected $fillable = ['name'];
/**
* @var array
*/
protected $casts = [
'name' => 'string'
];
/**
* @var array
*/
protected $dates = [
'created_at',
'updated_at',
'deleted_at',
];
/**
* @return HasMany
*/
public function users(): HasMany
{
return $this->hasMany(User::class, 'role_id', 'id');
}
/**
* @return BelongsToMany
*/
public function projects(): BelongsToMany
{
return $this->belongsToMany(Project::class, 'projects_roles', 'role_id', 'project_id');
}
public static function getIdByName(string $name): ?int
{
return Cache::store('octane')->rememberForever(
"role_id.$name",
static fn() => optional(self::firstWhere('name', $name))->id,
);
}
}

40
app/Models/Setting.php Normal file
View File

@@ -0,0 +1,40 @@
<?php
namespace App\Models;
use Eloquent;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Carbon;
/**
* App\Models\Setting
*
* @property int $id
* @property string $module_name
* @property string $key
* @property string $value
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
* @method static Builder|Setting newModelQuery()
* @method static Builder|Setting newQuery()
* @method static Builder|Setting query()
* @method static Builder|Setting whereCreatedAt($value)
* @method static Builder|Setting whereId($value)
* @method static Builder|Setting whereKey($value)
* @method static Builder|Setting whereModuleName($value)
* @method static Builder|Setting whereUpdatedAt($value)
* @method static Builder|Setting whereValue($value)
* @mixin Eloquent
*/
class Setting extends Model
{
/**
* @var array
*/
protected $fillable = [
'module_name',
'key',
'value'
];
}

82
app/Models/Status.php Normal file
View File

@@ -0,0 +1,82 @@
<?php
namespace App\Models;
use Eloquent as EloquentIdeHelper;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Carbon;
/**
* App\Models\Status
*
* @property int $id
* @property string $name
* @property bool $active
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
* @property string|null $color
* @property-read Collection|\App\Models\Project[] $projects
* @property-read int|null $projects_count
* @property-read Collection|\App\Models\Task[] $tasks
* @property-read int|null $tasks_count
* @method static EloquentBuilder|Status newModelQuery()
* @method static EloquentBuilder|Status newQuery()
* @method static EloquentBuilder|Status query()
* @method static EloquentBuilder|Status whereActive($value)
* @method static EloquentBuilder|Status whereColor($value)
* @method static EloquentBuilder|Status whereCreatedAt($value)
* @method static EloquentBuilder|Status whereId($value)
* @method static EloquentBuilder|Status whereName($value)
* @method static EloquentBuilder|Status whereUpdatedAt($value)
* @mixin EloquentIdeHelper
*/
class Status extends Model
{
/**
* table name from database
* @var string
*/
protected $table = 'statuses';
/**
* @var array
*/
protected $fillable = [
'name',
'active',
'color',
'order',
];
/**
* @var array
*/
protected $casts = [
'name' => 'string',
'active' => 'boolean',
'color' => 'string',
'order' => 'integer',
];
public static function getTableName(): string
{
return with(new static())->getTable();
}
public function tasks(): HasMany
{
return $this->hasMany(Task::class, 'status_id');
}
/**
* @return BelongsToMany
*/
public function projects(): BelongsToMany
{
return $this->belongsToMany(Project::class, 'projects_statuses', 'status_id', 'project_id')->withPivot('color');
}
}

46
app/Models/SusFiles.php Normal file
View File

@@ -0,0 +1,46 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Concerns\HasUuids;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Eloquent as EloquentIdeHelper;
/**
* App\Models\SusFiles
*
* @property string $id
* @property string $path
* @property string $mime_type
* @property string $hash
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @method static EloquentBuilder|Attachment newModelQuery()
* @method static EloquentBuilder|Attachment newQuery()
* @method static EloquentBuilder|Attachment query()
* @method static EloquentBuilder|Attachment whereCreatedAt($value)
* @method static EloquentBuilder|Attachment whereHash($value)
* @method static EloquentBuilder|Attachment whereId($value)
* @method static EloquentBuilder|Attachment whereMimeType($value)
* @method static EloquentBuilder|Attachment whereUpdatedAt($value)
* @mixin EloquentIdeHelper
*/
class SusFiles extends Model
{
use HasFactory;
use HasUuids;
protected $fillable = [
'path',
'mime_type',
'hash',
];
protected $casts = [
'path' => 'string',
'mime_type' => 'string',
'hash' => 'string',
];
}

274
app/Models/Task.php Normal file
View File

@@ -0,0 +1,274 @@
<?php
namespace App\Models;
use App\Contracts\AttachmentAble;
use App\Scopes\TaskAccessScope;
use App\Traits\ExposePermissions;
use App\Traits\HasAttachments;
use Database\Factories\TaskFactory;
use Eloquent as EloquentIdeHelper;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Query\Builder as QueryBuilder;
use Illuminate\Support\Carbon;
use Parsedown;
use Staudenmeir\LaravelAdjacencyList\Eloquent\HasGraphRelationships;
/**
* Class Task
*
* @property int $id
* @property int $project_id
* @property int $project_phase_id
* @property string $phase
* @property string $task_name
* @property string|null $description
* @property int $assigned_by
* @property string|null $url
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
* @property Carbon|null $deleted_at
* @property int $priority_id
* @property int $important
* @property int|null $status_id
* @property float $relative_position
* @property Carbon|null $due_date
* @property Carbon|null $start_date
* @property int|null $estimate
* @property-read User $assigned
* @property-read Collection|TaskHistory[] $changes
* @property-read int|null $changes_count
* @property-read Collection|TaskComment[] $comments
* @property-read int|null $comments_count
* @property-read array $can
* @property-read Priority $priority
* @property-read Project $project
* @property-read Status|null $status
* @property-read Collection|TimeInterval[] $timeIntervals
* @property-read int|null $time_intervals_count
* @property-read Collection|User[] $users
* @property-read Collection|CronTaskWorkers[] $workers
* @property-read int|null $users_count
* @method static TaskFactory factory(...$parameters)
* @method static EloquentBuilder|Task newModelQuery()
* @method static EloquentBuilder|Task newQuery()
* @method static QueryBuilder|Task onlyTrashed()
* @method static EloquentBuilder|Task query()
* @method static EloquentBuilder|Task whereAssignedBy($value)
* @method static EloquentBuilder|Task whereCreatedAt($value)
* @method static EloquentBuilder|Task whereDeletedAt($value)
* @method static EloquentBuilder|Task whereDescription($value)
* @method static EloquentBuilder|Task whereDueDate($value)
* @method static EloquentBuilder|Task whereId($value)
* @method static EloquentBuilder|Task whereImportant($value)
* @method static EloquentBuilder|Task wherePriorityId($value)
* @method static EloquentBuilder|Task whereProjectId($value)
* @method static EloquentBuilder|Task whereRelativePosition($value)
* @method static EloquentBuilder|Task whereStatusId($value)
* @method static EloquentBuilder|Task whereTaskName($value)
* @method static EloquentBuilder|Task whereUpdatedAt($value)
* @method static EloquentBuilder|Task whereUrl($value)
* @method static QueryBuilder|Task withTrashed()
* @method static QueryBuilder|Task withoutTrashed()
* @mixin EloquentIdeHelper
* @property-read Collection|Property[] $properties
* @property-read int|null $properties_count
*/
class Task extends Model implements AttachmentAble
{
use SoftDeletes;
use ExposePermissions;
use HasFactory;
use HasGraphRelationships;
use HasAttachments;
public const TYPE = 'tasks';
/**
* table name from database
* @var string
*/
protected $table = 'tasks';
/**
* @var array
*/
protected $fillable = [
'project_id',
'project_phase_id',
'task_name',
'description',
'assigned_by',
'url',
'priority_id',
'status_id',
'important',
'relative_position',
'start_date',
'due_date',
'estimate',
];
/**
* @var array
*/
protected $casts = [
'project_id' => 'integer',
'project_phase_id' => 'integer',
'task_name' => 'string',
'description' => 'string',
'assigned_by' => 'integer',
'url' => 'string',
'priority_id' => 'integer',
'status_id' => 'integer',
'important' => 'integer',
'relative_position' => 'float',
'estimate' => 'integer',
'start_date' => 'date',
'due_date' => 'date',
];
/**
* @var array
*/
protected $dates = [
'created_at',
'updated_at',
'deleted_at',
];
protected const PERMISSIONS = ['update', 'destroy'];
protected static function boot(): void
{
parent::boot();
static::addGlobalScope(new TaskAccessScope);
static::deleting(static function (Task $task) {
$task->timeIntervals()->delete();
$task->parents()->detach();
$task->children()->detach();
CronTaskWorkers::whereTaskId($task->id)->delete();
});
static::updated(static function (Task $task) {
if ($task->getOriginal('project_id') !== $task->project_id) {
$task->parents()->detach();
$task->children()->detach();
}
});
static::created(static function (Task $task) {
dispatch(static function () use ($task) {
foreach ($task->users as $user) {
$task->project->users()->firstOrCreate(
['id' => $user->id],
['role_id' => \App\Enums\Role::USER]
);
}
});
});
static::updated(static function (Task $task) {
dispatch(static function () use ($task) {
foreach ($task->users as $user) {
$task->project->users()->firstOrCreate(
['id' => $user->id],
['role_id' => \App\Enums\Role::USER]
);
}
});
});
}
public function timeIntervals(): HasMany
{
return $this->hasMany(TimeInterval::class, 'task_id');
}
public function users(): BelongsToMany
{
return $this->belongsToMany(User::class, 'tasks_users', 'task_id', 'user_id')->withoutGlobalScopes();
}
public function comments(): HasMany
{
return $this->hasMany(TaskComment::class, 'task_id');
}
public function project(): BelongsTo
{
return $this->belongsTo(Project::class, 'project_id')->withoutGlobalScopes();
}
public function assigned(): BelongsTo
{
return $this->belongsTo(User::class, 'assigned_by');
}
public function priority(): BelongsTo
{
return $this->belongsTo(Priority::class, 'priority_id');
}
public function status(): BelongsTo
{
return $this->belongsTo(Status::class, 'status_id');
}
public function getDescription(): string
{
return tap(new Parsedown())->text($this->description);
}
public function changes(): HasMany
{
return $this->hasMany(TaskHistory::class, 'task_id');
}
public function properties(): MorphMany
{
return $this->morphMany(Property::class, 'entity');
}
public function workers(): HasMany
{
return $this->hasMany(CronTaskWorkers::class, 'task_id', 'id');
}
public function phase(): BelongsTo
{
return $this->belongsTo(ProjectPhase::class, 'project_phase_id');
}
// related to attachments
public function getProjectId(): int
{
return $this->project_id;
}
// Below methods are related to Cattr gantt functionality and LaravelAdjacencyList package
public function getPivotTableName(): string
{
return 'tasks_relations';
}
public function enableCycleDetection(): bool
{
return true;
}
public function includeCycleStart(): bool
{
return true;
}
}

105
app/Models/TaskComment.php Normal file
View File

@@ -0,0 +1,105 @@
<?php
namespace App\Models;
use App\Contracts\AttachmentAble;
use App\Traits\HasAttachments;
use Eloquent as EloquentIdeHelper;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Query\Builder as QueryBuilder;
use Illuminate\Support\Carbon;
/**
* Class TaskComment
*
* @property int $id
* @property int $task_id
* @property int $user_id
* @property string $content
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
* @property Carbon|null $deleted_at
* @property-read Collection|Property[] $properties
* @property-read int|null $properties_count
* @property-read Task $task
* @property-read User $user
* @method static EloquentBuilder|TaskComment newModelQuery()
* @method static EloquentBuilder|TaskComment newQuery()
* @method static QueryBuilder|TaskComment onlyTrashed()
* @method static EloquentBuilder|TaskComment query()
* @method static EloquentBuilder|TaskComment whereContent($value)
* @method static EloquentBuilder|TaskComment whereCreatedAt($value)
* @method static EloquentBuilder|TaskComment whereDeletedAt($value)
* @method static EloquentBuilder|TaskComment whereId($value)
* @method static EloquentBuilder|TaskComment whereTaskId($value)
* @method static EloquentBuilder|TaskComment whereUpdatedAt($value)
* @method static EloquentBuilder|TaskComment whereUserId($value)
* @method static QueryBuilder|TaskComment withTrashed()
* @method static QueryBuilder|TaskComment withoutTrashed()
* @mixin EloquentIdeHelper
*/
class TaskComment extends Model implements AttachmentAble
{
use SoftDeletes;
use HasAttachments;
public const TYPE = 'task_comments';
/**
* table name from database
* @var string
*/
protected $table = 'task_comment';
/**
* @var array
*/
protected $fillable = [
'task_id',
'user_id',
'content',
];
/**
* @var array
*/
protected $casts = [
'task_id' => 'integer',
'user_id' => 'integer',
'content' => 'string',
];
/**
* @var array
*/
protected $dates = [
'created_at',
'updated_at',
'deleted_at',
];
public function task(): BelongsTo
{
return $this->belongsTo(Task::class, 'task_id');
}
public function user(): BelongsTo
{
return $this->belongsTo(User::class, 'user_id');
}
public function properties(): MorphMany
{
return $this->morphMany(Property::class, 'entity');
}
// related to attachments
public function getProjectId(): int
{
return $this->task->project_id;
}
}

View File

@@ -0,0 +1,97 @@
<?php
namespace App\Models;
use Eloquent;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Support\Carbon;
/**
* App\Models\TaskHistory
*
* @property int $id
* @property int $task_id
* @property int $user_id
* @property string $field
* @property string $new_value
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
* @property-read Task $task
* @property-read User $user
* @method static Builder|TaskHistory newModelQuery()
* @method static Builder|TaskHistory newQuery()
* @method static Builder|TaskHistory query()
* @method static Builder|TaskHistory whereCreatedAt($value)
* @method static Builder|TaskHistory whereField($value)
* @method static Builder|TaskHistory whereId($value)
* @method static Builder|TaskHistory whereNewValue($value)
* @method static Builder|TaskHistory whereTaskId($value)
* @method static Builder|TaskHistory whereUpdatedAt($value)
* @method static Builder|TaskHistory whereUserId($value)
* @mixin Eloquent
* @property string|null $old_value
* @method static Builder|TaskHistory whereOldValue($value)
*/
class TaskHistory extends Model
{
/**
* @var string
*/
protected $table = 'task_history';
/**
* @var array
*/
protected $fillable = [
'task_id',
'user_id',
'field',
'old_value',
'new_value',
];
/**
* @var array
*/
protected $casts
= [
'task_id' => 'integer',
'user_id' => 'integer',
'field' => 'string',
];
/**
* @var array
*/
protected $dates
= [
'created_at',
'updated_at',
];
/**
* @return string
*/
public static function getTableName(): string
{
return with(new static())->getTable();
}
/**
* @return BelongsTo
*/
public function task(): BelongsTo
{
return $this->belongsTo(Task::class, 'task_id');
}
/**
* @return BelongsTo
*/
public function user(): BelongsTo
{
return $this->belongsTo(User::class, 'user_id');
}
}

192
app/Models/TimeInterval.php Normal file
View File

@@ -0,0 +1,192 @@
<?php
namespace App\Models;
use App\Contracts\ScreenshotService;
use App\Scopes\TimeIntervalAccessScope;
use Database\Factories\TimeIntervalFactory;
use Eloquent as EloquentIdeHelper;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Query\Builder as QueryBuilder;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Carbon;
use Storage;
use MatanYadaev\EloquentSpatial\SpatialBuilder as Builder;
use MatanYadaev\EloquentSpatial\Objects\Point;
use MatanYadaev\EloquentSpatial\Traits\HasSpatial;
/**
* App\Models\TimeInterval
*
* @property int $id
* @property int $task_id
* @property string|null $screenshot_id
* @property Carbon $start_at
* @property Carbon $end_at
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
* @property Carbon|null $deleted_at
* @property int $user_id
* @property bool $is_manual
* @property int|null $activity_fill
* @property int|null $mouse_fill
* @property int|null $keyboard_fill
* @property array|null $location
* @property-read Collection|TrackedApplication[] $apps
* @property-read int|null $apps_count
* @property-read bool $has_screenshot
* @property-read Collection|Property[] $properties
* @property-read int|null $properties_count
* @property-read Task $task
* @property-read User $user
* @method static Builder|TimeInterval comparison($geometryColumn, $geometry, $relationship)
* @method static Builder|TimeInterval contains($geometryColumn, $geometry)
* @method static Builder|TimeInterval crosses($geometryColumn, $geometry)
* @method static Builder|TimeInterval disjoint($geometryColumn, $geometry)
* @method static Builder|TimeInterval distance($geometryColumn, $geometry, $distance)
* @method static Builder|TimeInterval distanceExcludingSelf($geometryColumn, $geometry, $distance)
* @method static Builder|TimeInterval distanceSphere($geometryColumn, $geometry, $distance)
* @method static Builder|TimeInterval distanceSphereExcludingSelf($geometryColumn, $geometry, $distance)
* @method static Builder|TimeInterval distanceSphereValue($geometryColumn, $geometry)
* @method static Builder|TimeInterval distanceValue($geometryColumn, $geometry)
* @method static Builder|TimeInterval doesTouch($geometryColumn, $geometry)
* @method static Builder|TimeInterval equals($geometryColumn, $geometry)
* @method static TimeIntervalFactory factory(...$parameters)
* @method static Builder|TimeInterval intersects($geometryColumn, $geometry)
* @method static Builder|TimeInterval newModelQuery()
* @method static Builder|TimeInterval newQuery()
* @method static QueryBuilder|TimeInterval onlyTrashed()
* @method static Builder|TimeInterval orderByDistance($geometryColumn, $geometry, $direction = 'asc')
* @method static Builder|TimeInterval orderByDistanceSphere($geometryColumn, $geometry, $direction = 'asc')
* @method static Builder|TimeInterval orderBySpatial($geometryColumn, $geometry, $orderFunction, $direction = 'asc')
* @method static Builder|TimeInterval overlaps($geometryColumn, $geometry)
* @method static Builder|TimeInterval query()
* @method static Builder|TimeInterval whereActivityFill($value)
* @method static Builder|TimeInterval whereCreatedAt($value)
* @method static Builder|TimeInterval whereDeletedAt($value)
* @method static Builder|TimeInterval whereEndAt($value)
* @method static Builder|TimeInterval whereId($value)
* @method static Builder|TimeInterval whereIsManual($value)
* @method static Builder|TimeInterval whereKeyboardFill($value)
* @method static Builder|TimeInterval whereLocation($value)
* @method static Builder|TimeInterval whereMouseFill($value)
* @method static Builder|TimeInterval whereStartAt($value)
* @method static Builder|TimeInterval whereTaskId($value)
* @method static Builder|TimeInterval whereUpdatedAt($value)
* @method static Builder|TimeInterval whereUserId($value)
* @method static QueryBuilder|TimeInterval withTrashed()
* @method static Builder|TimeInterval within($geometryColumn, $polygon)
* @method static QueryBuilder|TimeInterval withoutTrashed()
* @mixin EloquentIdeHelper
*/
class TimeInterval extends Model
{
use SoftDeletes;
use HasFactory;
use HasSpatial;
use Notifiable;
/**
* table name from database
* @var string
*/
protected $table = 'time_intervals';
/**
* @var array
*/
protected $fillable = [
'task_id',
'screenshot_id',
'start_at',
'user_id',
'end_at',
'activity_fill',
'mouse_fill',
'keyboard_fill',
'is_manual',
'location',
];
/**
* @var array
*/
protected $casts = [
'task_id' => 'integer',
'user_id' => 'integer',
'activity_fill' => 'integer',
'mouse_fill' => 'integer',
'keyboard_fill' => 'integer',
'is_manual' => 'boolean',
'location' => Point::class,
];
/**
* @var array
*/
protected $dates = [
'start_at',
'end_at',
'created_at',
'updated_at',
'deleted_at',
];
protected $appends = ['has_screenshot'];
/**
* Override parent boot and Call deleting event
*
* @return void
*/
protected static function boot(): void
{
parent::boot();
static::addGlobalScope(new TimeIntervalAccessScope);
}
public function task(): BelongsTo
{
return $this->belongsTo(Task::class, 'task_id')->withoutGlobalScopes();
}
public function user(): BelongsTo
{
return $this->belongsTo(User::class, 'user_id');
}
public function properties(): MorphMany
{
return $this->morphMany(Property::class, 'entity');
}
public function hasScreenshot(): Attribute
{
return Attribute::make(
get: static fn ($value) => !$value || Storage::exists(
app(ScreenshotService::class)->getScreenshotPath($value['id'])
)
)->shouldCache();
}
public function location(): Attribute
{
return Attribute::make(
get: static fn ($value) => $value ? ['lat' => $value->latitude, 'lng' => $value->longitude] : null,
set: static fn ($value) => $value ? new Point($value['lat'], $value['lng']) : null,
)->shouldCache();
}
public function apps(): HasMany
{
return $this->hasMany(TrackedApplication::class, 'time_interval_id');
}
}

View File

@@ -0,0 +1,76 @@
<?php
namespace App\Models;
use App\Scopes\TimeIntervalAccessScope;
use Eloquent;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Carbon;
/**
* App\Models\TrackedApplication
*
* @property int $id
* @property string $title
* @property string $executable
* @property int|null $time_interval_id
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
* @property Carbon|null $deleted_at
* @property int|null $user_id
* @property-read TimeInterval|null $timeInterval
* @property-read User|null $user
* @method static Builder|TrackedApplication newModelQuery()
* @method static Builder|TrackedApplication newQuery()
* @method static \Illuminate\Database\Query\Builder|TrackedApplication onlyTrashed()
* @method static Builder|TrackedApplication query()
* @method static Builder|TrackedApplication whereCreatedAt($value)
* @method static Builder|TrackedApplication whereDeletedAt($value)
* @method static Builder|TrackedApplication whereExecutable($value)
* @method static Builder|TrackedApplication whereId($value)
* @method static Builder|TrackedApplication whereTimeIntervalId($value)
* @method static Builder|TrackedApplication whereTitle($value)
* @method static Builder|TrackedApplication whereUpdatedAt($value)
* @method static Builder|TrackedApplication whereUserId($value)
* @method static \Illuminate\Database\Query\Builder|TrackedApplication withTrashed()
* @method static \Illuminate\Database\Query\Builder|TrackedApplication withoutTrashed()
* @mixin Eloquent
*/
class TrackedApplication extends Model
{
use SoftDeletes;
protected $table = 'tracked_applications';
protected $fillable = [
'title',
'executable',
'user_id',
];
protected $dates = [
'created_at',
'updated_at',
'deleted_at',
];
protected static function boot(): void
{
parent::boot();
static::addGlobalScope(new TimeIntervalAccessScope);
}
public function timeInterval(): BelongsTo
{
return $this->belongsTo(TimeInterval::class, 'time_interval_id');
}
public function user(): BelongsTo
{
return $this->belongsTo(User::class, 'user_id');
}
}

View File

@@ -0,0 +1,36 @@
<?php
namespace App\Models;
use App\Enums\UniversalReportType;
use App\Enums\UniversalReportBase;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class UniversalReport extends Model
{
use HasFactory;
protected $fillable = [
'name',
'type',
'base',
'data_objects',
'fields',
'charts',
];
protected $casts = [
'type' => UniversalReportType::class,
'base' => UniversalReportBase::class,
'data_objects' => 'array',
'fields' => 'array',
'charts' => 'array',
];
public function user(): BelongsTo
{
return $this->belongsTo(User::class, 'user_id');
}
}

341
app/Models/User.php Normal file
View File

@@ -0,0 +1,341 @@
<?php
namespace App\Models;
use App\Enums\Role;
use App\Enums\ScreenshotsState;
use App\Mail\ResetPassword;
use App\Scopes\UserAccessScope;
use App\Traits\HasRole;
use Auth;
use Carbon\Carbon;
use Database\Factories\UserFactory;
use Eloquent as EloquentIdeHelper;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Query\Builder as QueryBuilder;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\DatabaseNotification;
use Illuminate\Notifications\DatabaseNotificationCollection;
use Illuminate\Notifications\Notifiable;
use Hash;
use Laravel\Sanctum\HasApiTokens;
use Laravel\Sanctum\PersonalAccessToken;
/**
* App\Models\User
*
* @property int $id
* @property string $full_name
* @property string $email
* @property string|null $url
* @property int|null $company_id
* @property string|null $avatar
* @property ScreenshotsState $screenshots_state
* @property bool $screenshots_state_locked
* @property int|null $manual_time
* @property int|null $computer_time_popup
* @property bool|null $blur_screenshots
* @property bool|null $web_and_app_monitoring
* @property int|null $screenshots_interval
* @property int $active
* @property string $password
* @property \Illuminate\Support\Carbon|null $deleted_at
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property string|null $timezone
* @property int $important
* @property int $change_password
* @property int $is_admin
* @property int $role_id
* @property string $user_language
* @property string $type
* @property bool $invitation_sent
* @property int $nonce
* @property int $client_installed
* @property int $permanent_screenshots
* @property \Illuminate\Support\Carbon $last_activity
* @property-read bool $online
* @property-read bool $can_view_team_tab
* @property-read bool $can_create_task
* @property-read DatabaseNotificationCollection|DatabaseNotification[] $notifications
* @property-read int|null $notifications_count
* @property-read Collection|Project[] $projects
* @property-read int|null $projects_count
* @property-read Collection|ProjectsUsers[] $projectsRelation
* @property-read int|null $projects_relation_count
* @property-read Collection|Property[] $properties
* @property-read int|null $properties_count
* @property-read Collection|Task[] $tasks
* @property-read int|null $tasks_count
* @property-read Collection|TimeInterval[] $timeIntervals
* @property-read int|null $time_intervals_count
* @property-read Collection|PersonalAccessToken[] $tokens
* @property-read int|null $tokens_count
* @method static EloquentBuilder|User active()
* @method static EloquentBuilder|User admin()
* @method static UserFactory factory(...$parameters)
* @method static EloquentBuilder|User newModelQuery()
* @method static EloquentBuilder|User newQuery()
* @method static QueryBuilder|User onlyTrashed()
* @method static EloquentBuilder|User query()
* @method static EloquentBuilder|User whereActive($value)
* @method static EloquentBuilder|User whereAvatar($value)
* @method static EloquentBuilder|User whereBlurScreenshots($value)
* @method static EloquentBuilder|User whereChangePassword($value)
* @method static EloquentBuilder|User whereClientInstalled($value)
* @method static EloquentBuilder|User whereCompanyId($value)
* @method static EloquentBuilder|User whereComputerTimePopup($value)
* @method static EloquentBuilder|User whereCreatedAt($value)
* @method static EloquentBuilder|User whereDeletedAt($value)
* @method static EloquentBuilder|User whereEmail($value)
* @method static EloquentBuilder|User whereFullName($value)
* @method static EloquentBuilder|User whereId($value)
* @method static EloquentBuilder|User whereImportant($value)
* @method static EloquentBuilder|User whereInvitationSent($value)
* @method static EloquentBuilder|User whereIsAdmin($value)
* @method static EloquentBuilder|User whereLastActivity($value)
* @method static EloquentBuilder|User whereManualTime($value)
* @method static EloquentBuilder|User whereNonce($value)
* @method static EloquentBuilder|User wherePassword($value)
* @method static EloquentBuilder|User wherePermanentScreenshots($value)
* @method static EloquentBuilder|User whereRoleId($value)
* @method static EloquentBuilder|User whereScreenshotsActive($value)
* @method static EloquentBuilder|User whereScreenshotsInterval($value)
* @method static EloquentBuilder|User whereTimezone($value)
* @method static EloquentBuilder|User whereType($value)
* @method static EloquentBuilder|User whereUpdatedAt($value)
* @method static EloquentBuilder|User whereUrl($value)
* @method static EloquentBuilder|User whereUserLanguage($value)
* @method static EloquentBuilder|User whereWebAndAppMonitoring($value)
* @method static QueryBuilder|User withTrashed()
* @method static QueryBuilder|User withoutTrashed()
* @mixin EloquentIdeHelper
*/
class User extends Authenticatable
{
use Notifiable;
use SoftDeletes;
use HasRole;
use HasFactory;
use HasApiTokens;
/**
* table name from database
* @var string
*/
protected $table = 'users';
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'full_name',
'email',
'url',
'company_id',
'avatar',
'screenshots_state',
'screenshots_state_locked',
'manual_time',
'computer_time_popup',
'blur_screenshots',
'web_and_app_monitoring',
'screenshots_interval',
'active',
'password',
'timezone',
'important',
'change_password',
'role_id',
'user_language',
'type',
'invitation_sent',
'nonce',
'client_installed',
'last_activity',
'efficiency',
];
/**
* @var array
*/
protected $casts = [
'full_name' => 'string',
'email' => 'string',
'url' => 'string',
'company_id' => 'integer',
'avatar' => 'string',
'screenshots_state_locked' => 'boolean',
'manual_time' => 'integer',
'computer_time_popup' => 'integer',
'blur_screenshots' => 'boolean',
'web_and_app_monitoring' => 'boolean',
'screenshots_interval' => 'integer',
'active' => 'integer',
'password' => 'string',
'timezone' => 'string',
'important' => 'integer',
'change_password' => 'int',
'user_language' => 'string',
'type' => 'string',
'invitation_sent' => 'boolean',
'nonce' => 'integer',
'client_installed' => 'integer',
'efficiency' => 'float',
];
/**
* The attributes that should be mutated to dates.
*
* @var array
*/
protected $dates = [
'created_at',
'updated_at',
'deleted_at',
'last_activity',
];
protected $hidden = [
'password',
];
protected static function boot(): void
{
parent::boot();
static::addGlobalScope(new UserAccessScope);
}
protected $appends = [
'online',
'can_view_team_tab',
'can_create_task',
];
public function projects(): BelongsToMany
{
return $this->belongsToMany(Project::class, 'projects_users', 'user_id', 'project_id')
->withPivot('role_id');
}
public function projectsRelation(): HasMany
{
return $this->hasMany(ProjectsUsers::class, 'user_id', 'id');
}
public function tasks(): BelongsToMany
{
return $this->belongsToMany(Task::class, 'tasks_users', 'user_id', 'task_id');
}
public function timeIntervals(): HasMany
{
return $this->hasMany(TimeInterval::class, 'user_id');
}
public function properties(): MorphMany
{
return $this->morphMany(Property::class, 'entity');
}
public function universalReports(): HasMany
{
return $this->hasMany(UniversalReport::class, 'user_id');
}
/**
* Send the password reset notification.
*
* @param string $token
* @return void
*/
public function sendPasswordResetNotification($token): void
{
$this->notify(new ResetPassword($this->email, $token));
}
protected function online(): Attribute
{
return Attribute::make(
get: static fn($value, $attributes) => ($attributes['last_activity'] ?? false) &&
Carbon::parse($attributes['last_activity'])->diffInSeconds(Carbon::now())
< config('app.user_activity.online_status_time'),
);
}
protected function password(): Attribute
{
return Attribute::make(
set: static fn($value) => Hash::needsRehash($value) ? Hash::make($value) : $value,
);
}
protected function canViewTeamTab(): Attribute
{
$self = $this;
return Attribute::make(
get: static fn() => $self->hasRole([Role::ADMIN, Role::MANAGER, Role::AUDITOR])
|| $self->hasRoleInAnyProject([Role::MANAGER, Role::AUDITOR]),
);
}
protected function canCreateTask(): Attribute
{
$self = $this;
return Attribute::make(
get: static fn() => $self->hasRole([Role::ADMIN, Role::MANAGER])
|| $self->hasRoleInAnyProject(Role::MANAGER, Role::USER),
);
}
/**
* Always returns correct state in case env or app settings should override it.
*/
protected function screenshotsState(): Attribute
{
return Attribute::make(
get: static function (mixed $value, array $attributes): ScreenshotsState {
$userState = ScreenshotsState::withGlobalOverrides($value);
$showOriginalValues = Auth::user() !== null && Auth::user()->hasRole(Role::ADMIN) && (int)Auth::id() !== (int)$attributes['id'];
if ($showOriginalValues) {
return match ($userState) {
null => ScreenshotsState::REQUIRED,
ScreenshotsState::ANY => ScreenshotsState::OPTIONAL,
default => $userState,
};
}
return match ($userState) {
null, ScreenshotsState::ANY, ScreenshotsState::OPTIONAL => ScreenshotsState::REQUIRED,
default => $userState,
};
},
set: static fn ($value) => (string)ScreenshotsState::getNormalizedValue($value),
)->shouldCache();
}
public function scopeAdmin(EloquentBuilder $query): EloquentBuilder
{
return $query->where('role_id', '=', Role::ADMIN->value, 'or');
}
public function scopeManager(EloquentBuilder $query): EloquentBuilder
{
return $query->where('role_id', '=', Role::MANAGER->value, 'or');
}
public function scopeActive(EloquentBuilder $query): EloquentBuilder
{
return $query->where('active', true);
}
}