diff --git a/be/app/Http/Resources/ClientResource.php b/be/app/Http/Resources/ClientResource.php new file mode 100644 index 0000000..edb146a --- /dev/null +++ b/be/app/Http/Resources/ClientResource.php @@ -0,0 +1,26 @@ + $this->id, + 'name' => $this->name, + 'code' => $this->code, + 'client' => ClientResource::collection($this->users), + 'updated_at' => $this->updated_at, + ]; + } +} diff --git a/be/app/Http/Resources/ProjectCollection.php b/be/app/Http/Resources/ProjectCollection.php new file mode 100644 index 0000000..da2153f --- /dev/null +++ b/be/app/Http/Resources/ProjectCollection.php @@ -0,0 +1,25 @@ + $this->collection, + 'status' => 200, + ]; + } + +} diff --git a/be/app/Http/Resources/ProjectResource.php b/be/app/Http/Resources/ProjectResource.php new file mode 100644 index 0000000..e46c124 --- /dev/null +++ b/be/app/Http/Resources/ProjectResource.php @@ -0,0 +1,25 @@ + $this->id, + 'name' => $this->name, + 'code' => $this->code, + 'client' => $this->client, + ]; + } +} diff --git a/be/app/Models/Attachment.php b/be/app/Models/Attachment.php new file mode 100644 index 0000000..5ad608d --- /dev/null +++ b/be/app/Models/Attachment.php @@ -0,0 +1,18 @@ +belongsTo(SubTask::class); + } +} diff --git a/be/app/Models/Client.php b/be/app/Models/Client.php new file mode 100644 index 0000000..cee0082 --- /dev/null +++ b/be/app/Models/Client.php @@ -0,0 +1,18 @@ +hasMany(Project::class); + } +} diff --git a/be/app/Models/MasterTask.php b/be/app/Models/MasterTask.php new file mode 100644 index 0000000..68fa209 --- /dev/null +++ b/be/app/Models/MasterTask.php @@ -0,0 +1,28 @@ +hasMany(SubTask::class); + } + + public function project() + { + return $this->belongsTo(Project::class); + } + + public function attachments() + { + return $this->hasMany(Attachment::class); + } +} diff --git a/be/app/Models/Project.php b/be/app/Models/Project.php new file mode 100644 index 0000000..2b76a5e --- /dev/null +++ b/be/app/Models/Project.php @@ -0,0 +1,23 @@ +belongsTo(Client::class); + } + + public function mastertasks() + { + return $this->hasMany(MasterTask::class); + } +} diff --git a/be/app/Models/SubTask.php b/be/app/Models/SubTask.php new file mode 100644 index 0000000..4736f8a --- /dev/null +++ b/be/app/Models/SubTask.php @@ -0,0 +1,35 @@ +belongsTo(MasterTask::class); + } + + public function user() + { + return $this->belongsTo(MasterTask::class); + } + + public function timeblocks() + { + return $this->hasMany(Timeblock::class); + } + + public function timesheets() + { + return $this->hasMany(Timesheet::class); + } +} + + diff --git a/be/app/Models/Team.php b/be/app/Models/Team.php index aa26518..ace6c1a 100644 --- a/be/app/Models/Team.php +++ b/be/app/Models/Team.php @@ -10,9 +10,8 @@ class Team extends Model use HasFactory; public $timestamps = true; - protected $guarded = ['id', 'name']; - protected $table = 'teams'; + protected $guarded = ['id', 'name']; public function users() { diff --git a/be/app/Models/Timeblock.php b/be/app/Models/Timeblock.php new file mode 100644 index 0000000..fe0cc3c --- /dev/null +++ b/be/app/Models/Timeblock.php @@ -0,0 +1,18 @@ +belongsTo(SubTask::class); + } +} diff --git a/be/app/Models/Timesheet.php b/be/app/Models/Timesheet.php new file mode 100644 index 0000000..b61a4fc --- /dev/null +++ b/be/app/Models/Timesheet.php @@ -0,0 +1,23 @@ +belongsTo(SubTask::class); + } + + public function user() + { + return $this->belongsTo(User::class); + } +} diff --git a/be/app/Models/User.php b/be/app/Models/User.php index a13a05a..8640624 100644 --- a/be/app/Models/User.php +++ b/be/app/Models/User.php @@ -37,4 +37,14 @@ class User extends Authenticatable return $this->belongsToMany(Team::class); } + public function timesheets() + { + return $this->hasMany(Timesheet::class); + } + + public function subtasks() + { + return $this->hasMany(SubTask::class); + } + } diff --git a/be/database/factories/AttachmentFactory.php b/be/database/factories/AttachmentFactory.php new file mode 100644 index 0000000..9ff64ec --- /dev/null +++ b/be/database/factories/AttachmentFactory.php @@ -0,0 +1,32 @@ + + */ +class AttachmentFactory extends Factory +{ + /** + * Define the model's default state. + * + * @return array + */ + public function definition() + { + $extension = fake()->fileExtension(); + + return [ + 'original_name' => fake()->words(2, true) . '.' . $extension, + 'disk_name' => Str::random(15) . '.' . $extension, + 'path' => fake()->imageUrl(), + 'extension' => $extension, + 'content_type' => fake()->mimeType(), + 'file_size' => fake()->numberBetween(1323,992385), + ]; + } + +} diff --git a/be/database/factories/ClientFactory.php b/be/database/factories/ClientFactory.php new file mode 100644 index 0000000..8603289 --- /dev/null +++ b/be/database/factories/ClientFactory.php @@ -0,0 +1,27 @@ + + */ +class ClientFactory extends Factory +{ + /** + * Define the model's default state. + * + * @return array + */ + public function definition() + { + $company = fake()->company(); + + return [ + 'name' => $company, + 'code' => strtoupper(substr($company, 0, 5)), + ]; + } +} diff --git a/be/database/factories/MasterTaskFactory.php b/be/database/factories/MasterTaskFactory.php new file mode 100644 index 0000000..62a5a42 --- /dev/null +++ b/be/database/factories/MasterTaskFactory.php @@ -0,0 +1,32 @@ + + */ +class MasterTaskFactory extends Factory +{ + /** + * Define the model's default state. + * + * @return array + */ + public function definition() + { + $project = Project::factory()->create(); + + return [ + 'project_id' => $project->id, + 'title' => 'Master task ' . fake()->words(2, true), + 'estimated_time' => fake()->numberBetween(20,100), + 'tracked_time' => fake()->numberBetween(4,20), + 'deadline' => fake()->date(), + 'is_finished' => 0, + ]; + } +} diff --git a/be/database/factories/ProjectFactory.php b/be/database/factories/ProjectFactory.php new file mode 100644 index 0000000..133e953 --- /dev/null +++ b/be/database/factories/ProjectFactory.php @@ -0,0 +1,33 @@ + + */ +class ProjectFactory extends Factory +{ + /** + * Define the model's default state. + * + * @return array + */ + + public function definition() + { + $name = fake()->country(); + + $client = Client::factory('App\Models\Client')->create(); + + return [ + 'client_id' => $client->id, + 'name' => 'Project ' . $name, + 'code' => strtoupper(substr($name, 0, 3)) . '-2023-' . rand(1, 9), + ]; + + + } +} diff --git a/be/database/factories/SubTaskFactory.php b/be/database/factories/SubTaskFactory.php new file mode 100644 index 0000000..b72de59 --- /dev/null +++ b/be/database/factories/SubTaskFactory.php @@ -0,0 +1,33 @@ + + */ +class SubTaskFactory extends Factory +{ + /** + * Define the model's default state. + * + * @return array + */ + public function definition() + { +// $user = User::factory()->create(); +// $mastertask = MasterTask::factory()->hasAttachments(random_int(0 , 3))->create(); + + return [ + 'user_id' => 1, +// 'master_task_id' => $mastertask->id, + 'estimated_time' => fake()->numberBetween(1,16), + 'tracked_time' => fake()->numberBetween(4,20), + 'is_finished' => 0, + ]; + } +} diff --git a/be/database/factories/TeamFactory.php b/be/database/factories/TeamFactory.php index 4ae446c..740ae13 100644 --- a/be/database/factories/TeamFactory.php +++ b/be/database/factories/TeamFactory.php @@ -18,7 +18,7 @@ class TeamFactory extends Factory public function definition() { return [ - 'name' => fake()->company(), + 'name' => 'Team ' . fake()->colorName(), ]; } } diff --git a/be/database/factories/TimeblockFactory.php b/be/database/factories/TimeblockFactory.php new file mode 100644 index 0000000..e7557c4 --- /dev/null +++ b/be/database/factories/TimeblockFactory.php @@ -0,0 +1,28 @@ + + */ +class TimeblockFactory extends Factory +{ + /** + * Define the model's default state. + * + * @return array + */ + public function definition() + { + $start = fake()->dateTimeBetween('now', '+3 weeks'); + $end = Carbon::instance($start)->addHours(fake()->numberBetween(3, 5)); + + return [ + 'start' => $start, + 'end' => fake()->dateTimeBetween($start, $end), + ]; + } +} diff --git a/be/database/factories/TimesheetFactory.php b/be/database/factories/TimesheetFactory.php new file mode 100644 index 0000000..b811132 --- /dev/null +++ b/be/database/factories/TimesheetFactory.php @@ -0,0 +1,28 @@ + + */ +class TimesheetFactory extends Factory +{ + /** + * Define the model's default state. + * + * @return array + */ + public function definition() + { + $user = User::factory()->create(); + + return [ + 'user_id' => $user->id, + 'time' => fake()->numberBetween(1,8), + 'synced_to_karat' => null, + ]; + } +} diff --git a/be/database/factories/UserFactory.php b/be/database/factories/UserFactory.php index 8b200c5..de67ac5 100644 --- a/be/database/factories/UserFactory.php +++ b/be/database/factories/UserFactory.php @@ -17,15 +17,18 @@ class UserFactory extends Factory */ public function definition() { + $firstname = fake()->firstname(); + $lastname = fake()->lastname(); + return [ - 'email' => fake()->unique()->safeEmail(), + 'email' => strtolower($firstname . '.' . $lastname . '@jandl.sk'), 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password 'remember_token' => Str::random(10), - 'firstname' => fake()->firstname(), - 'lastname' => fake()->lastname(), - 'code' => strtoupper(Str::random(3)), - 'work_start' => '9.0', - 'work_end' => '17.0', + 'firstname' => $firstname, + 'lastname' => $lastname, + 'code' => strtoupper(substr($firstname, 0, 1) . substr($lastname, 0, 2)), + 'work_start' => rand(7, 10) . '.0', + 'work_end' => rand(15, 18) . '.0', ]; } diff --git a/be/database/migrations/2023_01_19_091424_create_clients_table.php b/be/database/migrations/2023_01_19_091424_create_clients_table.php new file mode 100644 index 0000000..8fca634 --- /dev/null +++ b/be/database/migrations/2023_01_19_091424_create_clients_table.php @@ -0,0 +1,33 @@ +id(); + $table->string('name'); + $table->string('code'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('clients'); + } +}; diff --git a/be/database/migrations/2023_01_19_091939_create_projects_table.php b/be/database/migrations/2023_01_19_091939_create_projects_table.php new file mode 100644 index 0000000..d55491a --- /dev/null +++ b/be/database/migrations/2023_01_19_091939_create_projects_table.php @@ -0,0 +1,34 @@ +id(); + $table->foreignIdFor(\App\Models\Client::class); + $table->string('name'); + $table->string('code'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('projects'); + } +}; diff --git a/be/database/migrations/2023_01_19_100036_update_clients_table_for_unique_code.php b/be/database/migrations/2023_01_19_100036_update_clients_table_for_unique_code.php new file mode 100644 index 0000000..b4e0930 --- /dev/null +++ b/be/database/migrations/2023_01_19_100036_update_clients_table_for_unique_code.php @@ -0,0 +1,30 @@ +unique('code'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + // + } +}; diff --git a/be/database/migrations/2023_01_19_100047_update_projects_table_for_unique_code.php b/be/database/migrations/2023_01_19_100047_update_projects_table_for_unique_code.php new file mode 100644 index 0000000..2cc88cf --- /dev/null +++ b/be/database/migrations/2023_01_19_100047_update_projects_table_for_unique_code.php @@ -0,0 +1,30 @@ +unique('code'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + // + } +}; diff --git a/be/database/migrations/2023_01_20_080241_create_master_task_table.php b/be/database/migrations/2023_01_20_080241_create_master_task_table.php new file mode 100644 index 0000000..b1ed22b --- /dev/null +++ b/be/database/migrations/2023_01_20_080241_create_master_task_table.php @@ -0,0 +1,40 @@ +id(); + $table->foreignIdFor( Project::class); + $table->foreignIdFor( Team::class)->nullable(); + $table->string('title'); + $table->float('estimated_time')->comment('tento field sa updatuje automaticky na zaklade subtaskov'); + $table->float('tracked_time')->default(0)->comment('tento field sa updatuje automaticky na zaklade vykazov subtaskov'); + $table->timestamp('deadline'); + $table->boolean('is_finished')->default(false); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('master_task'); + } +}; diff --git a/be/database/migrations/2023_01_20_085651_create_subtasks_table.php b/be/database/migrations/2023_01_20_085651_create_subtasks_table.php new file mode 100644 index 0000000..62ec150 --- /dev/null +++ b/be/database/migrations/2023_01_20_085651_create_subtasks_table.php @@ -0,0 +1,40 @@ +id(); + $table->foreignIdFor( MasterTask::class); + $table->foreignIdFor( User::class); + $table->float('estimated_time'); + $table->float('tracked_time')->default(0)->comment('tento field sa updatuje automaticky na zaklade vykazov'); + $table->boolean('is_finished')->default(false); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('sub_tasks'); + } +}; diff --git a/be/database/migrations/2023_01_20_094052_create_attachments_table.php b/be/database/migrations/2023_01_20_094052_create_attachments_table.php new file mode 100644 index 0000000..6ce5e2e --- /dev/null +++ b/be/database/migrations/2023_01_20_094052_create_attachments_table.php @@ -0,0 +1,39 @@ +id(); + $table->foreignIdFor( MasterTask::class); + $table->string('original_name'); + $table->string('disk_name'); + $table->string('path'); + $table->string('extension'); + $table->string('content_type'); + $table->bigInteger('file_size'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('attachments'); + } +}; diff --git a/be/database/migrations/2023_01_20_094959_create_timesheets_table.php b/be/database/migrations/2023_01_20_094959_create_timesheets_table.php new file mode 100644 index 0000000..b716925 --- /dev/null +++ b/be/database/migrations/2023_01_20_094959_create_timesheets_table.php @@ -0,0 +1,37 @@ +id(); + $table->foreignIdFor( SubTask::class); + $table->foreignIdFor( User::class); + $table->float('time', 4); + $table->timestamp( 'synced_to_karat')->nullable()->default(null); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('timesheets'); + } +}; diff --git a/be/database/migrations/2023_01_23_082423_create_timeblocks_table.php b/be/database/migrations/2023_01_23_082423_create_timeblocks_table.php new file mode 100644 index 0000000..e41bf3a --- /dev/null +++ b/be/database/migrations/2023_01_23_082423_create_timeblocks_table.php @@ -0,0 +1,35 @@ +id(); + $table->foreignIdFor( SubTask::class); + $table->timestamp( 'start'); + $table->timestamp( 'end'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('timeblocks'); + } +}; diff --git a/be/database/seeders/ClientSeeder.php b/be/database/seeders/ClientSeeder.php new file mode 100644 index 0000000..68faf1a --- /dev/null +++ b/be/database/seeders/ClientSeeder.php @@ -0,0 +1,23 @@ +count(10) + ->hasProjects(3) + ->create(); + } +} diff --git a/be/database/seeders/DatabaseSeeder.php b/be/database/seeders/DatabaseSeeder.php index 76d96dc..ad6b5a9 100644 --- a/be/database/seeders/DatabaseSeeder.php +++ b/be/database/seeders/DatabaseSeeder.php @@ -3,6 +3,10 @@ namespace Database\Seeders; // use Illuminate\Database\Console\Seeds\WithoutModelEvents; +use App\Models\MasterTask; +use App\Models\Project; +use App\Models\Team; +use App\Models\User; use Illuminate\Database\Seeder; class DatabaseSeeder extends Seeder @@ -14,11 +18,25 @@ class DatabaseSeeder extends Seeder */ public function run() { - // \App\Models\User::factory(10)->create(); + for ($i=0; $i < 5; $i++) { + Team::factory() + ->hasUsers(random_int(2, 5)) + ->create(); + } - // \App\Models\User::factory()->create([ - // 'name' => 'Test User', - // 'email' => 'test@example.com', - // ]); + for ($i=0; $i < 3; $i++) { + MasterTask::factory() + ->hasAttachments(random_int(0, 3)) + ->hasSubTasks(random_int(3, 5)) + ->create(); + } + +// for ($i=0; $i < 3; $i++) { +// User::factory() +// ->hasSubTasks(3) +//// ->hasAttachments(random_int(0, 3)) +//// ->hasSubTasks(random_int(3, 5)) +// ->create(); +// } } } diff --git a/be/database/seeders/MasterTaskSeeder.php b/be/database/seeders/MasterTaskSeeder.php new file mode 100644 index 0000000..da7f115 --- /dev/null +++ b/be/database/seeders/MasterTaskSeeder.php @@ -0,0 +1,23 @@ +hasAttachments(2) + ->hasSubTasks(2) + ->create(); + } +} diff --git a/be/database/seeders/ProjectSeeder.php b/be/database/seeders/ProjectSeeder.php new file mode 100644 index 0000000..d1520dc --- /dev/null +++ b/be/database/seeders/ProjectSeeder.php @@ -0,0 +1,26 @@ +hasMastertasks(2) + ->create(); + } + } +} diff --git a/be/database/seeders/SubTaskSeeder.php b/be/database/seeders/SubTaskSeeder.php new file mode 100644 index 0000000..76a06a2 --- /dev/null +++ b/be/database/seeders/SubTaskSeeder.php @@ -0,0 +1,24 @@ +count(10) + ->hasTimeblocks(2) + ->hasTimesheets(2) + ->create(); + } +}