Added basic models and factories

This commit is contained in:
Constantin Graf
2024-01-21 18:35:29 +01:00
parent 28f7b43577
commit 6377df1f44
29 changed files with 1476 additions and 116 deletions

View File

@@ -1,6 +1,6 @@
APP_NAME=Laravel
APP_ENV=local
APP_KEY=
APP_KEY=base64:UNQNf1SXeASNkWux01Rj8EnHYx8FO0kAxWNDwktclkk=
APP_DEBUG=true
APP_URL=http://localhost

11
.github/workflows/pint.yml vendored Normal file
View File

@@ -0,0 +1,11 @@
name: PHP Linting
on: push
jobs:
pint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: "laravel-pint"
uses: aglipanci/laravel-pint-action@2.0.0
with:
configPath: "pint.json"

42
app/Models/Client.php Normal file
View File

@@ -0,0 +1,42 @@
<?php
declare(strict_types=1);
namespace App\Models;
use Database\Factories\ClientFactory;
use Illuminate\Database\Eloquent\Concerns\HasUuids;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
/**
* @property string $id
* @property string $name
* @property string $organization_id
* @property-read Team $organization
*
* @method static ClientFactory factory()
*/
class Client extends Model
{
use HasFactory;
use HasUuids;
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'name' => 'string',
];
/**
* @return BelongsTo<Team, Client>
*/
public function organization(): BelongsTo
{
return $this->belongsTo(Team::class, 'organization_id');
}
}

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

@@ -0,0 +1,63 @@
<?php
declare(strict_types=1);
namespace App\Models;
use Database\Factories\ProjectFactory;
use Illuminate\Database\Eloquent\Collection;
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\HasMany;
/**
* @property string $id
* @property string $name
* @property string $organization_id
* @property string $client_id
* @property-read Team $organization
* @property-read Client|null $client
* @property-read Collection<Task> $tasks
*
* @method static ProjectFactory factory()
*/
class Project extends Model
{
use HasFactory;
use HasUuids;
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'name' => 'string',
];
/**
* @return BelongsTo<Team, Project>
*/
public function organization(): BelongsTo
{
return $this->belongsTo(Team::class, 'organization_id');
}
/**
* @return BelongsTo<Client, Project>
*/
public function client(): BelongsTo
{
return $this->belongsTo(Client::class, 'client_id');
}
/**
* @return HasMany<Task>
*/
public function tasks(): HasMany
{
return $this->hasMany(Task::class);
}
}

42
app/Models/Tag.php Normal file
View File

@@ -0,0 +1,42 @@
<?php
declare(strict_types=1);
namespace App\Models;
use Database\Factories\TagFactory;
use Illuminate\Database\Eloquent\Concerns\HasUuids;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
/**
* @property string $id
* @property string $name
* @property string $organization_id
* @property-read Team $organization
*
* @method static TagFactory factory()
*/
class Tag extends Model
{
use HasFactory;
use HasUuids;
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'name' => 'string',
];
/**
* @return BelongsTo<Team, Tag>
*/
public function organization(): BelongsTo
{
return $this->belongsTo(Team::class, 'organization_id');
}
}

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

@@ -0,0 +1,52 @@
<?php
declare(strict_types=1);
namespace App\Models;
use Database\Factories\TaskFactory;
use Illuminate\Database\Eloquent\Concerns\HasUuids;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
/**
* @property string $id
* @property string $name
* @property string $project_id
* @property string $organization_id
* @property-read Project $project
* @property-read Team $organization
*
* @method static TaskFactory factory()
*/
class Task extends Model
{
use HasFactory;
use HasUuids;
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'name' => 'string',
];
/**
* @return BelongsTo<Project, Task>
*/
public function project(): BelongsTo
{
return $this->belongsTo(Project::class);
}
/**
* @return BelongsTo<Team, Task>
*/
public function organization(): BelongsTo
{
return $this->belongsTo(Team::class, 'organization_id');
}
}

77
app/Models/TimeEntry.php Normal file
View File

@@ -0,0 +1,77 @@
<?php
declare(strict_types=1);
namespace App\Models;
use Database\Factories\TimeEntryFactory;
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\Support\Carbon;
/**
* @property string $id
* @property string $description
* @property Carbon $start
* @property Carbon|null $end
* @property bool $billable
* @property array $tags
* @property-read User $user
* @property-read Team $organization
* @property-read Project|null $project
* @property-read Task|null $task
*
* @method static TimeEntryFactory factory()
*/
class TimeEntry extends Model
{
use HasFactory;
use HasUuids;
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'description' => 'string',
'start' => 'datetime',
'end' => 'datetime',
'billable' => 'bool',
'tags' => 'array',
];
/**
* @return BelongsTo<User, TimeEntry>
*/
public function user(): BelongsTo
{
return $this->belongsTo(User::class, 'user_id');
}
/**
* @return BelongsTo<Team, TimeEntry>
*/
public function organization(): BelongsTo
{
return $this->belongsTo(Team::class, 'organization_id');
}
/**
* @return BelongsTo<Project, TimeEntry>
*/
public function project(): BelongsTo
{
return $this->belongsTo(Project::class, 'project_id');
}
/**
* @return BelongsTo<Task, TimeEntry>
*/
public function task(): BelongsTo
{
return $this->belongsTo(Task::class, 'task_id');
}
}

View File

@@ -13,9 +13,11 @@
"laravel/jetstream": "^4.2",
"laravel/passport": "*",
"laravel/tinker": "^2.8",
"tightenco/ziggy": "^1.0"
"tightenco/ziggy": "^1.0",
"tpetry/laravel-postgresql-enhanced": "^0.33.0"
},
"require-dev": {
"brianium/paratest": "^7.3",
"fakerphp/faker": "^1.9.1",
"larastan/larastan": "^2.0",
"laravel/pint": "^1.0",
@@ -54,6 +56,18 @@
],
"analyse": [
"@php ./vendor/bin/phpstan analyse --memory-limit=2G --configuration=phpstan.neon"
],
"ptest": [
"@php artisan test --parallel --colors=always --stop-on-failure"
],
"test": [
"@php artisan test --colors=always --stop-on-failure"
],
"test:coverage": [
"@php artisan test --coverage --colors=always --stop-on-failure"
],
"fix": [
"@php pint"
]
},
"extra": {

469
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "726e9483d9635413c31a43887a491b4e",
"content-hash": "34dbd2208afb93ce559614a5c014397e",
"packages": [
{
"name": "anourvalar/eloquent-serialize",
@@ -453,26 +453,26 @@
},
{
"name": "danharrin/livewire-rate-limiting",
"version": "v1.2.0",
"version": "v1.3.0",
"source": {
"type": "git",
"url": "https://github.com/danharrin/livewire-rate-limiting.git",
"reference": "bc2cc0a0b5b517fdc5bba8671013dd71081f70a8"
"reference": "bf16003f0d977b5a41071526d697eec94ac41735"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/danharrin/livewire-rate-limiting/zipball/bc2cc0a0b5b517fdc5bba8671013dd71081f70a8",
"reference": "bc2cc0a0b5b517fdc5bba8671013dd71081f70a8",
"url": "https://api.github.com/repos/danharrin/livewire-rate-limiting/zipball/bf16003f0d977b5a41071526d697eec94ac41735",
"reference": "bf16003f0d977b5a41071526d697eec94ac41735",
"shasum": ""
},
"require": {
"illuminate/support": "^9.0|^10.0",
"illuminate/support": "^9.0|^10.0|^11.0",
"php": "^8.0"
},
"require-dev": {
"livewire/livewire": "^3.0",
"livewire/volt": "^1.3",
"orchestra/testbench": "^7.0|^8.0",
"orchestra/testbench": "^7.0|^8.0|^9.0",
"phpunit/phpunit": "^9.0|^10.0"
},
"type": "library",
@@ -503,7 +503,7 @@
"type": "github"
}
],
"time": "2023-10-27T15:01:19+00:00"
"time": "2024-01-21T14:53:34+00:00"
},
{
"name": "dasprid/enum",
@@ -1339,16 +1339,16 @@
},
{
"name": "filament/actions",
"version": "v3.2.2",
"version": "v3.2.9",
"source": {
"type": "git",
"url": "https://github.com/filamentphp/actions.git",
"reference": "c47731ba370047d9440f1b43935b5d7242274dcc"
"reference": "465ef83a1c43b3b7fe122dde50eda2ee0f9138ea"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/filamentphp/actions/zipball/c47731ba370047d9440f1b43935b5d7242274dcc",
"reference": "c47731ba370047d9440f1b43935b5d7242274dcc",
"url": "https://api.github.com/repos/filamentphp/actions/zipball/465ef83a1c43b3b7fe122dde50eda2ee0f9138ea",
"reference": "465ef83a1c43b3b7fe122dde50eda2ee0f9138ea",
"shasum": ""
},
"require": {
@@ -1388,20 +1388,20 @@
"issues": "https://github.com/filamentphp/filament/issues",
"source": "https://github.com/filamentphp/filament"
},
"time": "2024-01-15T20:39:04+00:00"
"time": "2024-01-21T14:44:52+00:00"
},
{
"name": "filament/filament",
"version": "v3.2.2",
"version": "v3.2.9",
"source": {
"type": "git",
"url": "https://github.com/filamentphp/panels.git",
"reference": "baf5ac84b07d38216a4dd09dae9bedc836aa1d3e"
"reference": "a830f2d38073d3a4cdbe3798c957b69be50d39c3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/filamentphp/panels/zipball/baf5ac84b07d38216a4dd09dae9bedc836aa1d3e",
"reference": "baf5ac84b07d38216a4dd09dae9bedc836aa1d3e",
"url": "https://api.github.com/repos/filamentphp/panels/zipball/a830f2d38073d3a4cdbe3798c957b69be50d39c3",
"reference": "a830f2d38073d3a4cdbe3798c957b69be50d39c3",
"shasum": ""
},
"require": {
@@ -1453,20 +1453,20 @@
"issues": "https://github.com/filamentphp/filament/issues",
"source": "https://github.com/filamentphp/filament"
},
"time": "2024-01-15T20:39:17+00:00"
"time": "2024-01-21T14:44:57+00:00"
},
{
"name": "filament/forms",
"version": "v3.2.2",
"version": "v3.2.9",
"source": {
"type": "git",
"url": "https://github.com/filamentphp/forms.git",
"reference": "ed467134f77ca667ca02fdfa5c913d9e2fea9e2a"
"reference": "fc37c620f66a2e13e160b516cc4d0e5ad8ae9425"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/filamentphp/forms/zipball/ed467134f77ca667ca02fdfa5c913d9e2fea9e2a",
"reference": "ed467134f77ca667ca02fdfa5c913d9e2fea9e2a",
"url": "https://api.github.com/repos/filamentphp/forms/zipball/fc37c620f66a2e13e160b516cc4d0e5ad8ae9425",
"reference": "fc37c620f66a2e13e160b516cc4d0e5ad8ae9425",
"shasum": ""
},
"require": {
@@ -1509,20 +1509,20 @@
"issues": "https://github.com/filamentphp/filament/issues",
"source": "https://github.com/filamentphp/filament"
},
"time": "2024-01-15T20:39:04+00:00"
"time": "2024-01-21T14:44:57+00:00"
},
{
"name": "filament/infolists",
"version": "v3.2.2",
"version": "v3.2.9",
"source": {
"type": "git",
"url": "https://github.com/filamentphp/infolists.git",
"reference": "6d9e91514beca3a5932251f988c7ca3a62e2e9e8"
"reference": "b071063c45f0cd314c863947d1d841da09d40750"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/filamentphp/infolists/zipball/6d9e91514beca3a5932251f988c7ca3a62e2e9e8",
"reference": "6d9e91514beca3a5932251f988c7ca3a62e2e9e8",
"url": "https://api.github.com/repos/filamentphp/infolists/zipball/b071063c45f0cd314c863947d1d841da09d40750",
"reference": "b071063c45f0cd314c863947d1d841da09d40750",
"shasum": ""
},
"require": {
@@ -1560,20 +1560,20 @@
"issues": "https://github.com/filamentphp/filament/issues",
"source": "https://github.com/filamentphp/filament"
},
"time": "2024-01-15T20:39:02+00:00"
"time": "2024-01-21T14:44:53+00:00"
},
{
"name": "filament/notifications",
"version": "v3.2.2",
"version": "v3.2.9",
"source": {
"type": "git",
"url": "https://github.com/filamentphp/notifications.git",
"reference": "ce2daf3389cfff46fd0a15bd49264290d59b077c"
"reference": "c5f4f51d949fafc52643f2be654a4da92422836c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/filamentphp/notifications/zipball/ce2daf3389cfff46fd0a15bd49264290d59b077c",
"reference": "ce2daf3389cfff46fd0a15bd49264290d59b077c",
"url": "https://api.github.com/repos/filamentphp/notifications/zipball/c5f4f51d949fafc52643f2be654a4da92422836c",
"reference": "c5f4f51d949fafc52643f2be654a4da92422836c",
"shasum": ""
},
"require": {
@@ -1612,20 +1612,20 @@
"issues": "https://github.com/filamentphp/filament/issues",
"source": "https://github.com/filamentphp/filament"
},
"time": "2024-01-15T20:39:02+00:00"
"time": "2024-01-19T14:01:21+00:00"
},
{
"name": "filament/support",
"version": "v3.2.2",
"version": "v3.2.9",
"source": {
"type": "git",
"url": "https://github.com/filamentphp/support.git",
"reference": "cf74fe9e49042cc269cfdc3941aa9c9435f955e0"
"reference": "3b4d5d197c04e5a0b2a250d97c4761a07da9c85e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/filamentphp/support/zipball/cf74fe9e49042cc269cfdc3941aa9c9435f955e0",
"reference": "cf74fe9e49042cc269cfdc3941aa9c9435f955e0",
"url": "https://api.github.com/repos/filamentphp/support/zipball/3b4d5d197c04e5a0b2a250d97c4761a07da9c85e",
"reference": "3b4d5d197c04e5a0b2a250d97c4761a07da9c85e",
"shasum": ""
},
"require": {
@@ -1669,20 +1669,20 @@
"issues": "https://github.com/filamentphp/filament/issues",
"source": "https://github.com/filamentphp/filament"
},
"time": "2024-01-15T12:25:07+00:00"
"time": "2024-01-21T14:44:58+00:00"
},
{
"name": "filament/tables",
"version": "v3.2.2",
"version": "v3.2.9",
"source": {
"type": "git",
"url": "https://github.com/filamentphp/tables.git",
"reference": "ba7384fcbc2412f66f08310dd2786ec6602edcf0"
"reference": "87c55f6a1107d6d70b61a83f2cd7495343fdb19c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/filamentphp/tables/zipball/ba7384fcbc2412f66f08310dd2786ec6602edcf0",
"reference": "ba7384fcbc2412f66f08310dd2786ec6602edcf0",
"url": "https://api.github.com/repos/filamentphp/tables/zipball/87c55f6a1107d6d70b61a83f2cd7495343fdb19c",
"reference": "87c55f6a1107d6d70b61a83f2cd7495343fdb19c",
"shasum": ""
},
"require": {
@@ -1722,11 +1722,11 @@
"issues": "https://github.com/filamentphp/filament/issues",
"source": "https://github.com/filamentphp/filament"
},
"time": "2024-01-15T20:39:12+00:00"
"time": "2024-01-21T14:45:11+00:00"
},
{
"name": "filament/widgets",
"version": "v3.2.2",
"version": "v3.2.9",
"source": {
"type": "git",
"url": "https://github.com/filamentphp/widgets.git",
@@ -2511,30 +2511,30 @@
},
{
"name": "laravel/fortify",
"version": "v1.19.1",
"version": "v1.20.0",
"source": {
"type": "git",
"url": "https://github.com/laravel/fortify.git",
"reference": "1dde858a520f679b4a2f453fa68f8a0e98751875"
"reference": "587a55f906ae4f8448a19019a4b2ee7002d5c001"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/fortify/zipball/1dde858a520f679b4a2f453fa68f8a0e98751875",
"reference": "1dde858a520f679b4a2f453fa68f8a0e98751875",
"url": "https://api.github.com/repos/laravel/fortify/zipball/587a55f906ae4f8448a19019a4b2ee7002d5c001",
"reference": "587a55f906ae4f8448a19019a4b2ee7002d5c001",
"shasum": ""
},
"require": {
"bacon/bacon-qr-code": "^2.0",
"ext-json": "*",
"illuminate/support": "^8.82|^9.0|^10.0",
"php": "^7.3|^8.0",
"pragmarx/google2fa": "^7.0|^8.0"
"illuminate/support": "^10.0|^11.0",
"php": "^8.1",
"pragmarx/google2fa": "^8.0"
},
"require-dev": {
"mockery/mockery": "^1.0",
"orchestra/testbench": "^6.34|^7.31|^8.11",
"orchestra/testbench": "^8.16|^9.0",
"phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^9.3"
"phpunit/phpunit": "^10.4"
},
"type": "library",
"extra": {
@@ -2571,7 +2571,7 @@
"issues": "https://github.com/laravel/fortify/issues",
"source": "https://github.com/laravel/fortify"
},
"time": "2023-12-11T16:16:45+00:00"
"time": "2024-01-15T20:07:11+00:00"
},
{
"name": "laravel/framework",
@@ -2780,16 +2780,16 @@
},
{
"name": "laravel/jetstream",
"version": "v4.2.1",
"version": "v4.2.2",
"source": {
"type": "git",
"url": "https://github.com/laravel/jetstream.git",
"reference": "fb22f2d8acf10795ba8eb7672e5661722f998eca"
"reference": "7a11a4fb1426855b7132900af5c113a684b820cc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/jetstream/zipball/fb22f2d8acf10795ba8eb7672e5661722f998eca",
"reference": "fb22f2d8acf10795ba8eb7672e5661722f998eca",
"url": "https://api.github.com/repos/laravel/jetstream/zipball/7a11a4fb1426855b7132900af5c113a684b820cc",
"reference": "7a11a4fb1426855b7132900af5c113a684b820cc",
"shasum": ""
},
"require": {
@@ -2845,20 +2845,20 @@
"issues": "https://github.com/laravel/jetstream/issues",
"source": "https://github.com/laravel/jetstream"
},
"time": "2023-12-27T14:15:37+00:00"
"time": "2024-01-17T00:49:40+00:00"
},
{
"name": "laravel/passport",
"version": "v11.10.0",
"version": "v11.10.1",
"source": {
"type": "git",
"url": "https://github.com/laravel/passport.git",
"reference": "966bc8e477d08c86a11dc4c5a86f85fa0abdb89b"
"reference": "e1a651481cabff0ba174aaefbdc04a59e6a096ec"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/passport/zipball/966bc8e477d08c86a11dc4c5a86f85fa0abdb89b",
"reference": "966bc8e477d08c86a11dc4c5a86f85fa0abdb89b",
"url": "https://api.github.com/repos/laravel/passport/zipball/e1a651481cabff0ba174aaefbdc04a59e6a096ec",
"reference": "e1a651481cabff0ba174aaefbdc04a59e6a096ec",
"shasum": ""
},
"require": {
@@ -2923,7 +2923,7 @@
"issues": "https://github.com/laravel/passport/issues",
"source": "https://github.com/laravel/passport"
},
"time": "2023-11-02T17:16:12+00:00"
"time": "2024-01-10T14:44:24+00:00"
},
{
"name": "laravel/prompts",
@@ -4520,16 +4520,16 @@
},
{
"name": "nette/utils",
"version": "v4.0.3",
"version": "v4.0.4",
"source": {
"type": "git",
"url": "https://github.com/nette/utils.git",
"reference": "a9d127dd6a203ce6d255b2e2db49759f7506e015"
"reference": "d3ad0aa3b9f934602cb3e3902ebccf10be34d218"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nette/utils/zipball/a9d127dd6a203ce6d255b2e2db49759f7506e015",
"reference": "a9d127dd6a203ce6d255b2e2db49759f7506e015",
"url": "https://api.github.com/repos/nette/utils/zipball/d3ad0aa3b9f934602cb3e3902ebccf10be34d218",
"reference": "d3ad0aa3b9f934602cb3e3902ebccf10be34d218",
"shasum": ""
},
"require": {
@@ -4600,9 +4600,9 @@
],
"support": {
"issues": "https://github.com/nette/utils/issues",
"source": "https://github.com/nette/utils/tree/v4.0.3"
"source": "https://github.com/nette/utils/tree/v4.0.4"
},
"time": "2023-10-29T21:02:13+00:00"
"time": "2024-01-17T16:50:36+00:00"
},
{
"name": "nikic/php-parser",
@@ -8829,6 +8829,71 @@
},
"time": "2023-12-08T13:03:43+00:00"
},
{
"name": "tpetry/laravel-postgresql-enhanced",
"version": "0.33.0",
"source": {
"type": "git",
"url": "https://github.com/tpetry/laravel-postgresql-enhanced.git",
"reference": "a75749e45983ae548d4d85a9ef7c3240710a3384"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/tpetry/laravel-postgresql-enhanced/zipball/a75749e45983ae548d4d85a9ef7c3240710a3384",
"reference": "a75749e45983ae548d4d85a9ef7c3240710a3384",
"shasum": ""
},
"require": {
"doctrine/dbal": "^2.6|^3.5",
"illuminate/container": "^6.0|^7.0|^8.0|^9.0|^10.0",
"illuminate/database": "^6.0|^7.0|^8.79|^9.0|^10.0",
"illuminate/events": "^6.0|^7.0|^8.0|^9.0|^10.0",
"illuminate/support": "^6.0|^7.0|^8.0|^9.0|^10.0",
"php": "^8.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.19.3|^3.5.0",
"nunomaduro/larastan": "^1.0|^2.1",
"orchestra/testbench": "^4.0|^5.0|^6.0|^7.0|^8.0",
"phpstan/extension-installer": "^1.1",
"phpstan/phpstan": "^1.5",
"phpunit/phpunit": "^8.5.23|^9.5.13"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Tpetry\\PostgresqlEnhanced\\PostgresqlEnhancedServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Tpetry\\PostgresqlEnhanced\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "tpetry",
"email": "tobias@tpetry.me"
}
],
"description": "Support for many missing PostgreSQL specific features",
"homepage": "https://github.com/tpetry/laravel-postgresql-enhanced",
"keywords": [
"laravel",
"postgresql"
],
"support": {
"issues": "https://github.com/tpetry/laravel-postgresql-enhanced/issues",
"source": "https://github.com/tpetry/laravel-postgresql-enhanced/tree/0.33.0"
},
"time": "2023-10-23T15:36:21+00:00"
},
{
"name": "vlucas/phpdotenv",
"version": "v5.6.0",
@@ -9047,6 +9112,101 @@
}
],
"packages-dev": [
{
"name": "brianium/paratest",
"version": "v7.3.1",
"source": {
"type": "git",
"url": "https://github.com/paratestphp/paratest.git",
"reference": "551f46f52a93177d873f3be08a1649ae886b4a30"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/paratestphp/paratest/zipball/551f46f52a93177d873f3be08a1649ae886b4a30",
"reference": "551f46f52a93177d873f3be08a1649ae886b4a30",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-pcre": "*",
"ext-reflection": "*",
"ext-simplexml": "*",
"fidry/cpu-core-counter": "^0.5.1 || ^1.0.0",
"jean85/pretty-package-versions": "^2.0.5",
"php": "~8.1.0 || ~8.2.0 || ~8.3.0",
"phpunit/php-code-coverage": "^10.1.7",
"phpunit/php-file-iterator": "^4.1.0",
"phpunit/php-timer": "^6.0",
"phpunit/phpunit": "^10.4.2",
"sebastian/environment": "^6.0.1",
"symfony/console": "^6.3.4 || ^7.0.0",
"symfony/process": "^6.3.4 || ^7.0.0"
},
"require-dev": {
"doctrine/coding-standard": "^12.0.0",
"ext-pcov": "*",
"ext-posix": "*",
"infection/infection": "^0.27.6",
"phpstan/phpstan": "^1.10.40",
"phpstan/phpstan-deprecation-rules": "^1.1.4",
"phpstan/phpstan-phpunit": "^1.3.15",
"phpstan/phpstan-strict-rules": "^1.5.2",
"squizlabs/php_codesniffer": "^3.7.2",
"symfony/filesystem": "^6.3.1 || ^7.0.0"
},
"bin": [
"bin/paratest",
"bin/paratest.bat",
"bin/paratest_for_phpstorm"
],
"type": "library",
"autoload": {
"psr-4": {
"ParaTest\\": [
"src/"
]
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Brian Scaturro",
"email": "scaturrob@gmail.com",
"role": "Developer"
},
{
"name": "Filippo Tessarotto",
"email": "zoeslam@gmail.com",
"role": "Developer"
}
],
"description": "Parallel testing for PHP",
"homepage": "https://github.com/paratestphp/paratest",
"keywords": [
"concurrent",
"parallel",
"phpunit",
"testing"
],
"support": {
"issues": "https://github.com/paratestphp/paratest/issues",
"source": "https://github.com/paratestphp/paratest/tree/v7.3.1"
},
"funding": [
{
"url": "https://github.com/sponsors/Slamdunk",
"type": "github"
},
{
"url": "https://paypal.me/filippotessarotto",
"type": "paypal"
}
],
"time": "2023-10-31T09:24:17+00:00"
},
{
"name": "fakerphp/faker",
"version": "v1.23.1",
@@ -9110,6 +9270,67 @@
},
"time": "2024-01-02T13:46:09+00:00"
},
{
"name": "fidry/cpu-core-counter",
"version": "1.0.0",
"source": {
"type": "git",
"url": "https://github.com/theofidry/cpu-core-counter.git",
"reference": "85193c0b0cb5c47894b5eaec906e946f054e7077"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/85193c0b0cb5c47894b5eaec906e946f054e7077",
"reference": "85193c0b0cb5c47894b5eaec906e946f054e7077",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"require-dev": {
"fidry/makefile": "^0.2.0",
"fidry/php-cs-fixer-config": "^1.1.2",
"phpstan/extension-installer": "^1.2.0",
"phpstan/phpstan": "^1.9.2",
"phpstan/phpstan-deprecation-rules": "^1.0.0",
"phpstan/phpstan-phpunit": "^1.2.2",
"phpstan/phpstan-strict-rules": "^1.4.4",
"phpunit/phpunit": "^8.5.31 || ^9.5.26",
"webmozarts/strict-phpunit": "^7.5"
},
"type": "library",
"autoload": {
"psr-4": {
"Fidry\\CpuCoreCounter\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Théo FIDRY",
"email": "theo.fidry@gmail.com"
}
],
"description": "Tiny utility to get the number of CPU cores.",
"keywords": [
"CPU",
"core"
],
"support": {
"issues": "https://github.com/theofidry/cpu-core-counter/issues",
"source": "https://github.com/theofidry/cpu-core-counter/tree/1.0.0"
},
"funding": [
{
"url": "https://github.com/theofidry",
"type": "github"
}
],
"time": "2023-09-17T21:38:23+00:00"
},
{
"name": "filp/whoops",
"version": "2.15.4",
@@ -9232,6 +9453,65 @@
},
"time": "2020-07-09T08:09:16+00:00"
},
{
"name": "jean85/pretty-package-versions",
"version": "2.0.5",
"source": {
"type": "git",
"url": "https://github.com/Jean85/pretty-package-versions.git",
"reference": "ae547e455a3d8babd07b96966b17d7fd21d9c6af"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/ae547e455a3d8babd07b96966b17d7fd21d9c6af",
"reference": "ae547e455a3d8babd07b96966b17d7fd21d9c6af",
"shasum": ""
},
"require": {
"composer-runtime-api": "^2.0.0",
"php": "^7.1|^8.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.17",
"jean85/composer-provided-replaced-stub-package": "^1.0",
"phpstan/phpstan": "^0.12.66",
"phpunit/phpunit": "^7.5|^8.5|^9.4",
"vimeo/psalm": "^4.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"Jean85\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Alessandro Lai",
"email": "alessandro.lai85@gmail.com"
}
],
"description": "A library to get pretty versions strings of installed dependencies",
"keywords": [
"composer",
"package",
"release",
"versions"
],
"support": {
"issues": "https://github.com/Jean85/pretty-package-versions/issues",
"source": "https://github.com/Jean85/pretty-package-versions/tree/2.0.5"
},
"time": "2021-10-08T21:21:46+00:00"
},
{
"name": "larastan/larastan",
"version": "v2.8.1",
@@ -9335,16 +9615,16 @@
},
{
"name": "laravel/pint",
"version": "v1.13.8",
"version": "v1.13.9",
"source": {
"type": "git",
"url": "https://github.com/laravel/pint.git",
"reference": "69def89df9e0babc0f0a8bea184804a7d8a9c5c0"
"reference": "e3e269cc5d874c8efd2dc7962b1c7ff2585fe525"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/pint/zipball/69def89df9e0babc0f0a8bea184804a7d8a9c5c0",
"reference": "69def89df9e0babc0f0a8bea184804a7d8a9c5c0",
"url": "https://api.github.com/repos/laravel/pint/zipball/e3e269cc5d874c8efd2dc7962b1c7ff2585fe525",
"reference": "e3e269cc5d874c8efd2dc7962b1c7ff2585fe525",
"shasum": ""
},
"require": {
@@ -9355,13 +9635,13 @@
"php": "^8.1.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.46.0",
"illuminate/view": "^10.39.0",
"friendsofphp/php-cs-fixer": "^3.47.0",
"illuminate/view": "^10.40.0",
"larastan/larastan": "^2.8.1",
"laravel-zero/framework": "^10.3.0",
"mockery/mockery": "^1.6.7",
"nunomaduro/termwind": "^1.15.1",
"pestphp/pest": "^2.30.0"
"pestphp/pest": "^2.31.0"
},
"bin": [
"builds/pint"
@@ -9397,20 +9677,20 @@
"issues": "https://github.com/laravel/pint/issues",
"source": "https://github.com/laravel/pint"
},
"time": "2024-01-09T18:03:54+00:00"
"time": "2024-01-16T17:39:29+00:00"
},
{
"name": "laravel/sail",
"version": "v1.27.0",
"version": "v1.27.1",
"source": {
"type": "git",
"url": "https://github.com/laravel/sail.git",
"reference": "65a7764af5daadbd122e3b0d67be371d158a9b9a"
"reference": "9dc648978e4276f2bfd37a076a52e3bd9394777f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/sail/zipball/65a7764af5daadbd122e3b0d67be371d158a9b9a",
"reference": "65a7764af5daadbd122e3b0d67be371d158a9b9a",
"url": "https://api.github.com/repos/laravel/sail/zipball/9dc648978e4276f2bfd37a076a52e3bd9394777f",
"reference": "9dc648978e4276f2bfd37a076a52e3bd9394777f",
"shasum": ""
},
"require": {
@@ -9462,7 +9742,7 @@
"issues": "https://github.com/laravel/sail/issues",
"source": "https://github.com/laravel/sail"
},
"time": "2024-01-03T14:07:34+00:00"
"time": "2024-01-13T18:46:48+00:00"
},
{
"name": "mockery/mockery",
@@ -9815,16 +10095,16 @@
},
{
"name": "phpmyadmin/sql-parser",
"version": "5.8.2",
"version": "5.9.0",
"source": {
"type": "git",
"url": "https://github.com/phpmyadmin/sql-parser.git",
"reference": "f1720ae19abe6294cb5599594a8a57bc3c8cc287"
"reference": "011fa18a4e55591fac6545a821921dd1d61c6984"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpmyadmin/sql-parser/zipball/f1720ae19abe6294cb5599594a8a57bc3c8cc287",
"reference": "f1720ae19abe6294cb5599594a8a57bc3c8cc287",
"url": "https://api.github.com/repos/phpmyadmin/sql-parser/zipball/011fa18a4e55591fac6545a821921dd1d61c6984",
"reference": "011fa18a4e55591fac6545a821921dd1d61c6984",
"shasum": ""
},
"require": {
@@ -9855,6 +10135,7 @@
"bin": [
"bin/highlight-query",
"bin/lint-query",
"bin/sql-parser",
"bin/tokenize-query"
],
"type": "library",
@@ -9898,7 +10179,7 @@
"type": "other"
}
],
"time": "2023-09-19T12:34:29+00:00"
"time": "2024-01-20T20:34:02+00:00"
},
{
"name": "phpstan/phpstan",
@@ -10285,16 +10566,16 @@
},
{
"name": "phpunit/phpunit",
"version": "10.5.7",
"version": "10.5.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "e5c5b397a95cb0db013270a985726fcae93e61b8"
"reference": "08f4fa74d5fbfff1ef22abffee47aaedcaea227e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/e5c5b397a95cb0db013270a985726fcae93e61b8",
"reference": "e5c5b397a95cb0db013270a985726fcae93e61b8",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/08f4fa74d5fbfff1ef22abffee47aaedcaea227e",
"reference": "08f4fa74d5fbfff1ef22abffee47aaedcaea227e",
"shasum": ""
},
"require": {
@@ -10366,7 +10647,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
"source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.7"
"source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.8"
},
"funding": [
{
@@ -10382,7 +10663,7 @@
"type": "tidelift"
}
],
"time": "2024-01-14T16:40:30+00:00"
"time": "2024-01-19T07:07:27+00:00"
},
{
"name": "sebastian/cli-parser",

View File

@@ -0,0 +1,37 @@
<?php
declare(strict_types=1);
namespace Database\Factories;
use App\Models\Client;
use App\Models\Team;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends Factory<Client>
*/
class ClientFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'name' => $this->faker->company(),
'organization_id' => Team::factory(),
];
}
public function forOrganization(Team $organization): self
{
return $this->state(function (array $attributes) use ($organization) {
return [
'organization_id' => $organization->getKey(),
];
});
}
}

View File

@@ -0,0 +1,49 @@
<?php
declare(strict_types=1);
namespace Database\Factories;
use App\Models\Client;
use App\Models\Project;
use App\Models\Team;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends Factory<Project>
*/
class ProjectFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'name' => $this->faker->company(),
'color' => $this->faker->hexColor(),
'organization_id' => Team::factory(),
'client_id' => null,
];
}
public function forOrganization(Team $organization): self
{
return $this->state(function (array $attributes) use ($organization) {
return [
'organization_id' => $organization->getKey(),
];
});
}
public function forClient(?Client $client): self
{
return $this->state(function (array $attributes) use ($client) {
return [
'client_id' => $client?->getKey(),
];
});
}
}

View File

@@ -0,0 +1,37 @@
<?php
declare(strict_types=1);
namespace Database\Factories;
use App\Models\Tag;
use App\Models\Team;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends Factory<Tag>
*/
class TagFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'name' => $this->faker->name,
'organization_id' => Team::factory(),
];
}
public function forOrganization(Team $organization): self
{
return $this->state(function (array $attributes) use ($organization) {
return [
'organization_id' => $organization->getKey(),
];
});
}
}

View File

@@ -0,0 +1,48 @@
<?php
declare(strict_types=1);
namespace Database\Factories;
use App\Models\Project;
use App\Models\Task;
use App\Models\Team;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends Factory<Task>
*/
class TaskFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'name' => $this->faker->word(),
'project_id' => Project::factory(),
'organization_id' => Team::factory(),
];
}
public function forProject(Project $project): self
{
return $this->state(function (array $attributes) use ($project) {
return [
'project_id' => $project->getKey(),
];
});
}
public function forOrganization(Team $organization): self
{
return $this->state(function (array $attributes) use ($organization) {
return [
'organization_id' => $organization->getKey(),
];
});
}
}

View File

@@ -0,0 +1,74 @@
<?php
declare(strict_types=1);
namespace Database\Factories;
use App\Models\Project;
use App\Models\Task;
use App\Models\Team;
use App\Models\TimeEntry;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends Factory<TimeEntry>
*/
class TimeEntryFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
$start = $this->faker->dateTimeBetween('-1 year', '-1 hour');
return [
'description' => $this->faker->sentence(),
'start' => $start,
'end' => $this->faker->dateTimeBetween($start, 'now'),
'billable' => $this->faker->boolean(),
'tags' => [],
'user_id' => User::factory(),
'organization_id' => Team::factory(),
];
}
public function forUser(User $user): self
{
return $this->state(function (array $attributes) use ($user) {
return [
'user_id' => $user->getKey(),
];
});
}
public function forOrganization(Team $organization): self
{
return $this->state(function (array $attributes) use ($organization) {
return [
'organization_id' => $organization->getKey(),
];
});
}
public function forProject(?Project $project): self
{
return $this->state(function (array $attributes) use ($project) {
return [
'project_id' => $project?->getKey(),
];
});
}
public function forTask(?Task $task): self
{
return $this->state(function (array $attributes) use ($task) {
return [
'task_id' => $task?->getKey(),
];
});
}
}

View File

@@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('clients', function (Blueprint $table) {
$table->uuid('id')->primary();
$table->string('name', 255);
$table->uuid('organization_id');
$table->foreign('organization_id')
->references('id')
->on('teams')
->cascadeOnUpdate()
->restrictOnDelete();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('clients');
}
};

View File

@@ -0,0 +1,43 @@
<?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('projects', function (Blueprint $table) {
$table->uuid('id')->primary();
$table->string('name', 255);
$table->string('color', 16);
$table->uuid('client_id')->nullable();
$table->foreign('client_id')
->references('id')
->on('clients')
->cascadeOnUpdate()
->restrictOnDelete();
$table->uuid('organization_id');
$table->foreign('organization_id')
->references('id')
->on('teams')
->cascadeOnUpdate()
->restrictOnDelete();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('projects');
}
};

View File

@@ -0,0 +1,42 @@
<?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('tasks', function (Blueprint $table) {
$table->uuid('id')->primary();
$table->string('name', 255);
$table->uuid('project_id');
$table->foreign('project_id')
->references('id')
->on('projects')
->cascadeOnUpdate()
->restrictOnDelete();
$table->uuid('organization_id');
$table->foreign('organization_id')
->references('id')
->on('teams')
->cascadeOnUpdate()
->restrictOnDelete();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('tasks');
}
};

View File

@@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('tags', function (Blueprint $table) {
$table->uuid('id')->primary();
$table->string('name', 255);
$table->uuid('organization_id');
$table->foreign('organization_id')
->references('id')
->on('teams')
->cascadeOnUpdate()
->restrictOnDelete();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('tags');
}
};

View File

@@ -0,0 +1,58 @@
<?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('time_entries', function (Blueprint $table) {
$table->uuid('id')->primary();
$table->string('description', 255);
$table->dateTime('start');
$table->dateTime('end')->nullable();
$table->boolean('billable')->default(false);
$table->uuid('user_id');
$table->foreign('user_id')
->references('id')
->on('users')
->cascadeOnUpdate()
->restrictOnDelete();
$table->uuid('organization_id');
$table->foreign('organization_id')
->references('id')
->on('teams')
->cascadeOnUpdate()
->restrictOnDelete();
$table->uuid('project_id')->nullable();
$table->foreign('project_id')
->references('id')
->on('projects')
->cascadeOnUpdate()
->restrictOnDelete();
$table->uuid('task_id')->nullable();
$table->foreign('task_id')
->references('id')
->on('tasks')
->cascadeOnUpdate()
->restrictOnDelete();
$table->jsonb('tags')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('time_entries');
}
};

View File

@@ -5,8 +5,14 @@ declare(strict_types=1);
namespace Database\Seeders;
// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use App\Models\Client;
use App\Models\Project;
use App\Models\Task;
use App\Models\Team;
use App\Models\TimeEntry;
use App\Models\User;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class DatabaseSeeder extends Seeder
{
@@ -15,9 +21,35 @@ class DatabaseSeeder extends Seeder
*/
public function run(): void
{
User::factory()->withPersonalTeam()->create([
$this->deleteAll();
$organization = Team::factory()->create([
'name' => 'ACME Corp',
]);
$user1 = User::factory()->withPersonalTeam()->create([
'name' => 'Test User',
'email' => 'test@example.com',
]);
$user1->teams()->attach($organization);
$client = Client::factory()->create([
'name' => 'Big Company',
]);
$bigCompanyProject = Project::factory()->forClient($client)->create([
'name' => 'Big Company Project',
]);
Task::factory()->forProject($bigCompanyProject)->create();
$internalProject = Project::factory()->create([
'name' => 'Internal Project',
]);
}
private function deleteAll(): void
{
DB::table((new TimeEntry())->getTable())->delete();
DB::table((new Task())->getTable())->delete();
DB::table((new Project())->getTable())->delete();
DB::table((new Client())->getTable())->delete();
DB::table((new User())->getTable())->delete();
DB::table((new Team())->getTable())->delete();
}
}

View File

@@ -18,7 +18,6 @@ services:
extra_hosts:
- 'host.docker.internal:host-gateway'
ports:
- '${APP_PORT:-80}:80'
- '${VITE_PORT:-5173}:${VITE_PORT:-5173}'
environment:
WWWUSER: '${WWWUSER}'

View File

@@ -1,18 +0,0 @@
<?php
declare(strict_types=1);
namespace Tests\Unit;
use PHPUnit\Framework\TestCase;
class ExampleTest extends TestCase
{
/**
* A basic test example.
*/
public function test_that_true_is_true(): void
{
$this->assertTrue(true);
}
}

View File

@@ -0,0 +1,26 @@
<?php
declare(strict_types=1);
namespace Tests\Unit\Model;
use App\Models\Client;
use App\Models\Team;
class ClientModelTest extends ModelTestAbstract
{
public function test_it_belongs_to_a_organization(): void
{
// Arrange
$organization = Team::factory()->create();
$client = Client::factory()->forOrganization($organization)->create();
// Act
$client->refresh();
$organizationRel = $client->organization;
// Assert
$this->assertNotNull($organizationRel);
$this->assertTrue($organizationRel->is($organization));
}
}

View File

@@ -0,0 +1,13 @@
<?php
declare(strict_types=1);
namespace Tests\Unit\Model;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
abstract class ModelTestAbstract extends TestCase
{
use RefreshDatabase;
}

View File

@@ -0,0 +1,72 @@
<?php
declare(strict_types=1);
namespace Tests\Unit\Model;
use App\Models\Client;
use App\Models\Project;
use App\Models\Task;
use App\Models\Team;
class ProjectModelTest extends ModelTestAbstract
{
public function test_it_belongs_to_a_organization(): void
{
// Arrange
$organization = Team::factory()->create();
$project = Project::factory()->forOrganization($organization)->create();
// Act
$project->refresh();
$organizationRel = $project->organization;
// Assert
$this->assertNotNull($organizationRel);
$this->assertTrue($organizationRel->is($organization));
}
public function test_it_can_belong_to_a_client(): void
{
// Arrange
$client = Client::factory()->create();
$project = Project::factory()->forClient($client)->create();
// Act
$project->refresh();
$clientRel = $project->client;
// Assert
$this->assertNotNull($clientRel);
$this->assertTrue($clientRel->is($client));
}
public function test_it_can_belong_to_no_client(): void
{
// Arrange
$project = Project::factory()->forClient(null)->create();
// Act
$project->refresh();
$clientRel = $project->client;
// Assert
$this->assertNull($clientRel);
}
public function test_it_has_many_tasks(): void
{
// Arrange
$project = Project::factory()->create();
$tasks = Task::factory()->forProject($project)->createMany(3);
// Act
$project->refresh();
$tasksRel = $project->tasks;
// Assert
$this->assertNotNull($tasksRel);
$this->assertCount(3, $tasksRel);
$this->assertTrue($tasksRel->first()->is($tasks->first()));
}
}

View File

@@ -0,0 +1,26 @@
<?php
declare(strict_types=1);
namespace Tests\Unit\Model;
use App\Models\Tag;
use App\Models\Team;
class TagModelTest extends ModelTestAbstract
{
public function test_it_belongs_to_a_organization(): void
{
// Arrange
$organization = Team::factory()->create();
$task = Tag::factory()->forOrganization($organization)->create();
// Act
$task->refresh();
$organizationRel = $task->organization;
// Assert
$this->assertNotNull($organizationRel);
$this->assertTrue($organizationRel->is($organization));
}
}

View File

@@ -0,0 +1,42 @@
<?php
declare(strict_types=1);
namespace Tests\Unit\Model;
use App\Models\Project;
use App\Models\Task;
use App\Models\Team;
class TaskModelTest extends ModelTestAbstract
{
public function test_it_belongs_to_a_organization(): void
{
// Arrange
$organization = Team::factory()->create();
$task = Task::factory()->forOrganization($organization)->create();
// Act
$task->refresh();
$organizationRel = $task->organization;
// Assert
$this->assertNotNull($organizationRel);
$this->assertTrue($organizationRel->is($organization));
}
public function test_it_belongs_to_a_project(): void
{
// Arrange
$project = Project::factory()->create();
$task = Task::factory()->forProject($project)->create();
// Act
$task->refresh();
$projectRel = $task->project;
// Assert
$this->assertNotNull($projectRel);
$this->assertTrue($projectRel->is($project));
}
}

View File

@@ -0,0 +1,100 @@
<?php
declare(strict_types=1);
namespace Tests\Unit\Model;
use App\Models\Project;
use App\Models\Task;
use App\Models\Team;
use App\Models\TimeEntry;
use App\Models\User;
class TimeEntryModelTest extends ModelTestAbstract
{
public function test_it_belongs_to_a_user(): void
{
// Arrange
$user = User::factory()->create();
$timeEntry = TimeEntry::factory()->forUser($user)->create();
// Act
$timeEntry->refresh();
$userRel = $timeEntry->user;
// Assert
$this->assertNotNull($userRel);
$this->assertTrue($userRel->is($user));
}
public function test_it_belongs_to_a_organization(): void
{
// Arrange
$organization = Team::factory()->create();
$timeEntry = TimeEntry::factory()->forOrganization($organization)->create();
// Act
$timeEntry->refresh();
$organizationRel = $timeEntry->organization;
// Assert
$this->assertNotNull($organizationRel);
$this->assertTrue($organizationRel->is($organization));
}
public function test_it_can_belong_to_a_project(): void
{
// Arrange
$project = Project::factory()->create();
$timeEntry = TimeEntry::factory()->forProject($project)->create();
// Act
$timeEntry->refresh();
$projectRel = $timeEntry->project;
// Assert
$this->assertNotNull($projectRel);
$this->assertTrue($projectRel->is($project));
}
public function test_it_can_belong_to_no_project(): void
{
// Arrange
$timeEntry = TimeEntry::factory()->forProject(null)->create();
// Act
$timeEntry->refresh();
$project = $timeEntry->project;
// Assert
$this->assertNull($project);
}
public function test_it_can_belong_to_a_task(): void
{
// Arrange
$task = Task::factory()->create();
$timeEntry = TimeEntry::factory()->forTask($task)->create();
// Act
$timeEntry->refresh();
$taskRel = $timeEntry->task;
// Assert
$this->assertNotNull($taskRel);
$this->assertTrue($taskRel->is($task));
}
public function test_it_can_belong_to_no_task(): void
{
// Arrange
$timeEntry = TimeEntry::factory()->forTask(null)->create();
// Act
$timeEntry->refresh();
$taskRel = $timeEntry->task;
// Assert
$this->assertNull($taskRel);
}
}

View File

@@ -0,0 +1,26 @@
<?php
declare(strict_types=1);
namespace Tests\Unit\Model;
use App\Models\User;
use App\Providers\Filament\AdminPanelProvider;
use Filament\Panel;
class UserModelTest extends ModelTestAbstract
{
public function test_normal_user_can_not_access_admin_panel(): void
{
// Arrange
$user = User::factory()->create();
$panelProvider = new AdminPanelProvider(app());
$mainPanel = $panelProvider->panel(Panel::make());
// Act
$canAccess = $user->canAccessPanel($mainPanel);
// Assert
$this->assertFalse($canAccess);
}
}