From f21aba50155f825edba397d0c3cd13f9cb8c82ea Mon Sep 17 00:00:00 2001
From: etiti <emmanueltiti370@gmail.com>
Date: Mon, 11 Nov 2024 23:20:49 +0300
Subject: [PATCH 1/5] creting review model, test for repository, adding types

---
 .../app/Contract/RepositoryInterface.php      |  21 ++++
 .../AssessmentReviewData.php                  |  32 +++++
 application/app/Models/AssessmentReview.php   |  13 ++
 application/app/Models/IdeascaleProfile.php   |   3 +-
 application/app/Policies/ReviewPolicy.php     |  66 ++++++++++
 .../AssessmentReviewRepository.php            |  15 +++
 application/app/Repositories/Repository.php   |  32 ++---
 .../app/Repositories/RepositoryInterface.php  |  18 ---
 application/composer.json                     |   1 +
 application/composer.lock                     |  56 ++++++++-
 application/config/database.php               |   6 +-
 .../factories/AssessmentReviewFactory.php     |  28 +++++
 .../factories/IdeascaleProfileFactory.php     |   3 +-
 ...151958_create_ideascale_profiles_table.php |   2 +-
 ...2024_11_11_153139_create_reviews_table.php |  33 +++++
 .../seeders/AssessmentReviewSeeder.php        |  18 +++
 .../database/seeders/DatabaseSeeder.php       |   1 +
 application/phpunit.xml                       |  12 +-
 application/resources/types/generated.d.ts    | 114 +++++++++++-------
 application/tests/Feature/RepositoryTest.php  |  99 +++++++++++++++
 20 files changed, 477 insertions(+), 96 deletions(-)
 create mode 100644 application/app/Contract/RepositoryInterface.php
 create mode 100644 application/app/DataTransferObjects/AssessmentReviewData.php
 create mode 100644 application/app/Models/AssessmentReview.php
 create mode 100644 application/app/Policies/ReviewPolicy.php
 create mode 100644 application/app/Repositories/AssessmentReviewRepository.php
 delete mode 100644 application/app/Repositories/RepositoryInterface.php
 create mode 100644 application/database/factories/AssessmentReviewFactory.php
 create mode 100644 application/database/migrations/2024_11_11_153139_create_reviews_table.php
 create mode 100644 application/database/seeders/AssessmentReviewSeeder.php
 create mode 100644 application/tests/Feature/RepositoryTest.php

diff --git a/application/app/Contract/RepositoryInterface.php b/application/app/Contract/RepositoryInterface.php
new file mode 100644
index 00000000..9f644315
--- /dev/null
+++ b/application/app/Contract/RepositoryInterface.php
@@ -0,0 +1,21 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Contract;
+
+use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\Collection;
+
+interface RepositoryInterface
+{
+    public function all(): array|Collection;
+
+    public function find(int|string $id): Model;
+
+    public function create(array $data): Model;
+
+    public function update(array $data, $id): bool;
+
+    public function delete(int|string $id): int;
+}
diff --git a/application/app/DataTransferObjects/AssessmentReviewData.php b/application/app/DataTransferObjects/AssessmentReviewData.php
new file mode 100644
index 00000000..4f147694
--- /dev/null
+++ b/application/app/DataTransferObjects/AssessmentReviewData.php
@@ -0,0 +1,32 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\DataTransferObjects;
+
+use Spatie\LaravelData\Data;
+use Spatie\TypeScriptTransformer\Attributes\Optional as TypeScriptOptional;
+use Spatie\TypeScriptTransformer\Attributes\TypeScript;
+
+#[TypeScript]
+final class AssessmentReviewData extends Data
+{
+    public function __construct(
+        public ?int $id,
+
+        #[TypeScriptOptional]
+        public ?int $assessor_id,
+
+        public int $excellent_count,
+
+        public int $good_count,
+
+        public int $filtered_out_count,
+
+        public bool $flagged,
+
+        #[TypeScriptOptional]
+        public ?array $qa_rationale,
+
+    ) {}
+}
diff --git a/application/app/Models/AssessmentReview.php b/application/app/Models/AssessmentReview.php
new file mode 100644
index 00000000..eea64d7f
--- /dev/null
+++ b/application/app/Models/AssessmentReview.php
@@ -0,0 +1,13 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+class AssessmentReview extends Model
+{
+    use HasFactory;
+}
diff --git a/application/app/Models/IdeascaleProfile.php b/application/app/Models/IdeascaleProfile.php
index be1a8f28..a21110e6 100755
--- a/application/app/Models/IdeascaleProfile.php
+++ b/application/app/Models/IdeascaleProfile.php
@@ -4,8 +4,9 @@
 
 namespace App\Models;
 
-use App\Casts\DateFormatCast;
 use App\Models\Model;
+use App\Casts\DateFormatCast;
+use Illuminate\Database\Eloquent\Factories\HasFactory;
 
 class IdeascaleProfile extends Model
 {
diff --git a/application/app/Policies/ReviewPolicy.php b/application/app/Policies/ReviewPolicy.php
new file mode 100644
index 00000000..6eacd68a
--- /dev/null
+++ b/application/app/Policies/ReviewPolicy.php
@@ -0,0 +1,66 @@
+<?php
+
+namespace App\Policies;
+
+use App\Models\Review;
+use App\Models\User;
+use Illuminate\Auth\Access\Response;
+
+class ReviewPolicy
+{
+    /**
+     * Determine whether the user can view any models.
+     */
+    public function viewAny(User $user): bool
+    {
+        //
+    }
+
+    /**
+     * Determine whether the user can view the model.
+     */
+    public function view(User $user, Review $review): bool
+    {
+        //
+    }
+
+    /**
+     * Determine whether the user can create models.
+     */
+    public function create(User $user): bool
+    {
+        //
+    }
+
+    /**
+     * Determine whether the user can update the model.
+     */
+    public function update(User $user, Review $review): bool
+    {
+        //
+    }
+
+    /**
+     * Determine whether the user can delete the model.
+     */
+    public function delete(User $user, Review $review): bool
+    {
+        //
+    }
+
+    /**
+     * Determine whether the user can restore the model.
+     */
+    public function restore(User $user, Review $review): bool
+    {
+        //
+    }
+
+    /**
+     * Determine whether the user can permanently delete the model.
+     */
+    public function forceDelete(User $user, Review $review): bool
+    {
+        //
+    }
+}
diff --git a/application/app/Repositories/AssessmentReviewRepository.php b/application/app/Repositories/AssessmentReviewRepository.php
new file mode 100644
index 00000000..a56fc6f3
--- /dev/null
+++ b/application/app/Repositories/AssessmentReviewRepository.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Repositories;
+
+use App\Models\AssessmentReview;
+
+class AssessmentReviewRepository extends Repository
+{
+    public function __construct(AssessmentReview $model)
+    {
+        parent::__construct($model);
+    }
+}
diff --git a/application/app/Repositories/Repository.php b/application/app/Repositories/Repository.php
index babc578d..0306c0a1 100644
--- a/application/app/Repositories/Repository.php
+++ b/application/app/Repositories/Repository.php
@@ -5,21 +5,21 @@
 namespace App\Repositories;
 
 use App\Scopes\LimitScope;
-use Illuminate\Contracts\Pagination\LengthAwarePaginator;
-use Illuminate\Database\Eloquent\Collection;
+use App\Contract\RepositoryInterface;
 use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\Collection;
+use Illuminate\Database\Eloquent\Builder;
+use Illuminate\Contracts\Pagination\LengthAwarePaginator;
 
 class Repository implements RepositoryInterface
 {
     protected $query;
 
-    // Constructor to bind model to repo
     public function __construct(protected Model $model)
     {
         $this->setModel($model);
     }
 
-    // Get all instances of model
     public function all(): array|Collection
     {
         if ($this->query) {
@@ -29,8 +29,7 @@ public function all(): array|Collection
         return $this->model->all();
     }
 
-    // Get all instances of model
-    public function count()
+    public function count(): int
     {
         if ($this->query) {
             return $this->query->count();
@@ -39,8 +38,7 @@ public function count()
         return $this->model->count();
     }
 
-    // get the record with the given id
-    public function find($idOrSlug, ...$params)
+    public function find(int|string $idOrSlug, ...$params): Model
     {
         if (is_int($idOrSlug)) {
             return $this->model->findOrFail($idOrSlug);
@@ -49,22 +47,19 @@ public function find($idOrSlug, ...$params)
         return $this->model->where('slug', '=', $idOrSlug)->first();
     }
 
-    // create a new record in the database
-    public function create(array $data)
+    public function create(array $data): Model
     {
         return $this->model->create($data);
     }
 
-    // update record in the database
-    public function update(array $data, $id)
+    public function update(array $data, $id): bool
     {
         $record = $this->model->find($id);
 
         return $record->update($data);
     }
 
-    // remove record from the database
-    public function delete($id)
+    public function delete($id): int
     {
         return $this->model->destroy($id);
     }
@@ -87,17 +82,15 @@ public function paginate($perPage = null): LengthAwarePaginator
         return $this->getQuery()?->fastPaginate($perPage);
     }
 
-    // Get the associated model
     public function getModel(): Model
     {
         return $this->model;
     }
 
-    // Set the associated model
     public function setModel($model): static
     {
         $this->model = $model;
-        $this->query = $this->getModel()::query();
+        $this->query = $this->model::query();
 
         return $this;
     }
@@ -109,13 +102,12 @@ public function setQuery($query): static
         return $this;
     }
 
-    public function getQuery()
+    public function getQuery(): Builder
     {
         return $this->query ?? $this->model::query();
     }
 
-    // Eager load database relationships
-    public function with($relations)
+    public function with($relations): Builder
     {
         return $this->model->with($relations);
     }
diff --git a/application/app/Repositories/RepositoryInterface.php b/application/app/Repositories/RepositoryInterface.php
deleted file mode 100644
index 2aabd293..00000000
--- a/application/app/Repositories/RepositoryInterface.php
+++ /dev/null
@@ -1,18 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace App\Repositories;
-
-interface RepositoryInterface
-{
-    public function all();
-
-    public function find($id);
-
-    public function create(array $data);
-
-    public function update(array $data, $id);
-
-    public function delete($id);
-}
diff --git a/application/composer.json b/application/composer.json
index 6cfecd21..e8b3f4f8 100644
--- a/application/composer.json
+++ b/application/composer.json
@@ -6,6 +6,7 @@
     "license": "MIT",
     "require": {
         "php": "^8.2",
+        "hammerstone/fast-paginate": "^1.1",
         "inertiajs/inertia-laravel": "2.x-dev",
         "laravel/framework": "^11.9",
         "laravel/horizon": "^5.29",
diff --git a/application/composer.lock b/application/composer.lock
index d5744224..55545509 100644
--- a/application/composer.lock
+++ b/application/composer.lock
@@ -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": "4fdd26c781ec96df3d4a35da294ccbe1",
+    "content-hash": "ed4af2f793d87a04968ad8068f2887a9",
     "packages": [
         {
             "name": "amphp/amp",
@@ -2085,6 +2085,60 @@
             ],
             "time": "2023-12-03T19:50:20+00:00"
         },
+        {
+            "name": "hammerstone/fast-paginate",
+            "version": "v1.1.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/hammerstonedev/fast-paginate.git",
+                "reference": "6a1fb26c860d04176d00761ae8a93f04da14c81c"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/hammerstonedev/fast-paginate/zipball/6a1fb26c860d04176d00761ae8a93f04da14c81c",
+                "reference": "6a1fb26c860d04176d00761ae8a93f04da14c81c",
+                "shasum": ""
+            },
+            "require": {
+                "illuminate/database": "^8.37|^9.0|^10.0|^11.0",
+                "php": "^7.4|^8.0"
+            },
+            "require-dev": {
+                "laravel/scout": "^9.4|^10.8",
+                "mockery/mockery": "^1.3.3",
+                "orchestra/testbench": "^6|^7|^8.0|^9.0",
+                "phpunit/phpunit": ">=8.5.23|^9"
+            },
+            "type": "library",
+            "extra": {
+                "laravel": {
+                    "providers": [
+                        "Hammerstone\\FastPaginate\\FastPaginateProvider"
+                    ]
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Hammerstone\\FastPaginate\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Aaron Francis",
+                    "email": "aaron@hammerstone.dev"
+                }
+            ],
+            "description": "Fast paginate for Laravel",
+            "support": {
+                "issues": "https://github.com/hammerstonedev/fast-paginate/issues",
+                "source": "https://github.com/hammerstonedev/fast-paginate/tree/v1.1.1"
+            },
+            "time": "2024-05-16T15:45:29+00:00"
+        },
         {
             "name": "inertiajs/inertia-laravel",
             "version": "2.x-dev",
diff --git a/application/config/database.php b/application/config/database.php
index 206cde66..730cd0b0 100644
--- a/application/config/database.php
+++ b/application/config/database.php
@@ -33,15 +33,13 @@
 
         'sqlite' => [
             'driver' => 'sqlite',
-            'url' => env('DB_URL'),
+            'url' => env('DATABASE_URL'),
             'database' => env('DB_DATABASE', database_path('database.sqlite')),
             'prefix' => '',
             'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),
-            'busy_timeout' => null,
-            'journal_mode' => null,
-            'synchronous' => null,
         ],
 
+
         'mysql' => [
             'driver' => 'mysql',
             'url' => env('DB_URL'),
diff --git a/application/database/factories/AssessmentReviewFactory.php b/application/database/factories/AssessmentReviewFactory.php
new file mode 100644
index 00000000..ff0b7323
--- /dev/null
+++ b/application/database/factories/AssessmentReviewFactory.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace Database\Factories;
+
+use Illuminate\Database\Eloquent\Factories\Factory;
+
+/**
+ * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Review>
+ */
+class AssessmentReviewFactory extends Factory
+{
+    /**
+     * Define the model's default state.
+     *
+     * @return array<string, mixed>
+     */
+    public function definition(): array
+    {
+        return [
+            'assessor_id' => 1,
+            'excellent_count' => rand(0,100),
+            'good_count' => rand(0, 100),
+            'filtered_out_count' => rand(0, 100),
+            'flagged' => $this->faker->randomElement([true,false]),
+            'qa_rationale' => json_encode(['en',$this->faker->sentences(500,true)])
+        ];
+    }
+}
diff --git a/application/database/factories/IdeascaleProfileFactory.php b/application/database/factories/IdeascaleProfileFactory.php
index 39d8b3f4..627a1d1f 100755
--- a/application/database/factories/IdeascaleProfileFactory.php
+++ b/application/database/factories/IdeascaleProfileFactory.php
@@ -4,6 +4,7 @@
 
 namespace Database\Factories;
 
+use App\Models\User;
 use Illuminate\Database\Eloquent\Factories\Factory;
 
 class IdeascaleProfileFactory extends Factory
@@ -34,7 +35,7 @@ public function definition()
             'linkedin' => $this->faker->userName,
             'discord' => $this->faker->userName,
             'ideascale' => $this->faker->word,
-            'claimed_by' => $this->faker->randomElement([null, $this->faker->numberBetween(1, 100)]),
+            'claimed_by' => User::factory(),
             'telegram' => $this->faker->userName,
             'title' => $this->faker->jobTitle,
         ];
diff --git a/application/database/migrations/2024_11_06_151958_create_ideascale_profiles_table.php b/application/database/migrations/2024_11_06_151958_create_ideascale_profiles_table.php
index 08393fc0..14681373 100755
--- a/application/database/migrations/2024_11_06_151958_create_ideascale_profiles_table.php
+++ b/application/database/migrations/2024_11_06_151958_create_ideascale_profiles_table.php
@@ -26,7 +26,7 @@ public function up()
             $table->string('linkedin')->nullable();
             $table->string('discord')->nullable();
             $table->string('ideascale')->nullable();
-            $table->bigInteger('claimed_by')->nullable();
+            $table->foreignId('claimed_by')->constrained('users')->nullable();
             $table->string('telegram')->nullable();
             $table->string('title', 255)->nullable();
         });
diff --git a/application/database/migrations/2024_11_11_153139_create_reviews_table.php b/application/database/migrations/2024_11_11_153139_create_reviews_table.php
new file mode 100644
index 00000000..476f8095
--- /dev/null
+++ b/application/database/migrations/2024_11_11_153139_create_reviews_table.php
@@ -0,0 +1,33 @@
+<?php
+
+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('assessment_reviews', function (Blueprint $table) {
+            $table->id();
+            $table->timestamps();
+            $table->foreignId('assessor_id');
+            $table->integer('excellent_count')->default(0);
+            $table->integer('good_count')->default(0);
+            $table->integer('filtered_out_count')->default(0);
+            $table->json('qa_rationale')->nullable();
+            $table->boolean('flagged')->default(false);
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     */
+    public function down(): void
+    {
+        Schema::dropIfExists('assesment_reviews');
+    }
+};
diff --git a/application/database/seeders/AssessmentReviewSeeder.php b/application/database/seeders/AssessmentReviewSeeder.php
new file mode 100644
index 00000000..8360998e
--- /dev/null
+++ b/application/database/seeders/AssessmentReviewSeeder.php
@@ -0,0 +1,18 @@
+<?php
+
+namespace Database\Seeders;
+
+use App\Models\AssessmentReview;
+use Illuminate\Database\Console\Seeds\WithoutModelEvents;
+use Illuminate\Database\Seeder;
+
+class AssessmentReviewSeeder extends Seeder
+{
+    /**
+     * Run the database seeds.
+     */
+    public function run(): void
+    {
+        AssessmentReview::factory(10)->create();
+    }
+}
diff --git a/application/database/seeders/DatabaseSeeder.php b/application/database/seeders/DatabaseSeeder.php
index 475986ff..9bbbb157 100644
--- a/application/database/seeders/DatabaseSeeder.php
+++ b/application/database/seeders/DatabaseSeeder.php
@@ -18,6 +18,7 @@ public function run(): void
         $this->call([
             UserSeeder::class,
             ProposalSeeder::class,
+            RoleSeeder::class
         ]);
 
         $this->call(
diff --git a/application/phpunit.xml b/application/phpunit.xml
index c09b5bcf..81ab12ee 100644
--- a/application/phpunit.xml
+++ b/application/phpunit.xml
@@ -1,9 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
-         bootstrap="vendor/autoload.php"
-         colors="true"
->
+<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd" bootstrap="vendor/autoload.php" colors="true">
     <testsuites>
         <testsuite name="Unit">
             <directory>tests/Unit</directory>
@@ -22,7 +18,11 @@
         <env name="APP_MAINTENANCE_DRIVER" value="file"/>
         <env name="BCRYPT_ROUNDS" value="4"/>
         <env name="CACHE_STORE" value="array"/>
-        <env name="DB_DATABASE" value="testing"/>
+
+        <!-- Database Configuration for SQLite In-Memory Testing -->
+        <env name="DB_CONNECTION" value="sqlite"/>
+        <env name="DB_DATABASE" value=":memory:"/>
+
         <env name="MAIL_MAILER" value="array"/>
         <env name="PULSE_ENABLED" value="false"/>
         <env name="QUEUE_CONNECTION" value="sync"/>
diff --git a/application/resources/types/generated.d.ts b/application/resources/types/generated.d.ts
index 9ffa96fc..252b2277 100644
--- a/application/resources/types/generated.d.ts
+++ b/application/resources/types/generated.d.ts
@@ -1,46 +1,72 @@
 declare namespace App.DataTransferObjects {
-export type ProposalData = {
-id: number | null;
-user_id: number | null;
-campaign_id: number | null;
-fund_id: number | null;
-title: Array<any> | null;
-slug: string;
-website: string | null;
-excerpt?: string;
-amount_requested: number;
-amount_received: number | null;
-definition_of_success?: string;
-status?: string;
-funding_status?: string;
-meta_data?: Array<any>;
-funded_at?: string;
-deleted_at?: string;
-funding_updated_at?: string;
-yes_votes_count: number | null;
-no_votes_count: number | null;
-abstain_votes_count: number | null;
-comment_prompt?: string;
-social_excerpt?: string;
-team_id?: number;
-ideascale_link?: string;
-type?: string;
-meta_title?: Array<any>;
-problem?: Array<any>;
-solution?: Array<any>;
-experience?: Array<any>;
-content?: Array<any>;
-currency?: string;
-opensource: boolean;
-ranking_total?: number;
-quickpitch?: string;
-quickpitch_length?: number;
-};
-export type UserData = {
-id: number;
-name: string;
-email: string;
-profile_photo_url: string;
-email_verified_at: string;
-};
+    export type AssessmentReviewData = {
+        id: number | null;
+        assessor_id?: number;
+        excellent_count: number;
+        good_count: number;
+        filtered_out_count: number;
+        flagged: boolean;
+        qa_rationale?: Array<any>;
+    };
+    export type IdeascaleProfileData = {
+        id: number | null;
+        ideascaleId?: number;
+        username?: string;
+        email?: string;
+        name?: string;
+        bio?: string;
+        createdAt?: string;
+        updatedAt?: string;
+        twitter?: string;
+        linkedin?: string;
+        discord?: string;
+        ideascale?: string;
+        claimedBy?: number;
+        telegram?: string;
+        title?: string;
+    };
+    export type ProposalData = {
+        id: number | null;
+        user_id: number | null;
+        campaign_id: number | null;
+        fund_id: number | null;
+        title: Array<any> | null;
+        slug: string;
+        website: string | null;
+        excerpt?: string;
+        amount_requested: number;
+        amount_received: number | null;
+        definition_of_success?: string;
+        status?: string;
+        funding_status?: string;
+        meta_data?: Array<any>;
+        funded_at?: string;
+        deleted_at?: string;
+        funding_updated_at?: string;
+        yes_votes_count: number | null;
+        no_votes_count: number | null;
+        abstain_votes_count: number | null;
+        comment_prompt?: string;
+        social_excerpt?: string;
+        team_id?: number;
+        ideascale_link?: string;
+        type?: string;
+        meta_title?: Array<any>;
+        problem?: Array<any>;
+        solution?: Array<any>;
+        experience?: Array<any>;
+        content?: Array<any>;
+        currency?: string;
+        opensource: boolean;
+        ranking_total?: number;
+        quickpitch?: string;
+        quickpitch_length?: number;
+    };
+    export type UserData = {
+        id: number;
+        name: string;
+        email: string;
+        profile_photo_url: string;
+        email_verified_at: string;
+    };
 }
diff --git a/application/tests/Feature/RepositoryTest.php b/application/tests/Feature/RepositoryTest.php
new file mode 100644
index 00000000..91b4b126
--- /dev/null
+++ b/application/tests/Feature/RepositoryTest.php
@@ -0,0 +1,99 @@
+<?php
+
+declare(strict_types=1);
+
+use App\Models\Proposal;
+use App\Models\User;
+use App\Repositories\Repository;
+use Illuminate\Database\Eloquent\Collection;
+use Illuminate\Foundation\Testing\RefreshDatabase;
+use Illuminate\Contracts\Pagination\LengthAwarePaginator;
+
+uses(RefreshDatabase::class);
+
+beforeEach(function () {
+    // Initialize repository with the User model
+    $this->repository = new Repository(new User());
+});
+
+it('returns all records with all method', function () {
+    User::factory()->count(3)->create();
+    $records = $this->repository->all();
+
+    expect($records)->toBeInstanceOf(Collection::class)
+        ->and($records)->toHaveCount(3);
+});
+
+it('returns correct record count with count method', function () {
+    User::factory()->count(5)->create();
+    $count = $this->repository->count();
+
+    expect($count)->toBeInt()->toEqual(5);
+});
+
+it('retrieves by id  with find method', function () {
+    $user = User::factory()->create([
+        'name' => 'Sample User',
+    ]);
+
+    $foundById = $this->repository->find($user->id);
+    expect($foundById)->toBeInstanceOf(User::class)
+        ->and($foundById->id)->toEqual($user->id);
+});
+
+it('retrieves by id or slug with find method', function () {
+
+    $this->repository = new Repository(new Proposal());
+
+    $proposal = Proposal::factory(state: [
+        'title' => json_encode(['en' => 'Nice proposal']),
+        'slug' => 'nice-proposal'
+    ])->create();
+
+    $foundById = $this->repository->find($proposal->id);
+    expect($foundById)->toBeInstanceOf(Proposal::class)
+        ->and($foundById->id)->toEqual($proposal->id);
+
+    $foundBySlug = $this->repository->find('nice-proposal');
+    expect($foundBySlug)->toBeInstanceOf(Proposal::class)
+        ->and($foundBySlug->slug)->toEqual('nice-proposal');
+});
+
+it('creates a new record with create method', function () {
+    $data = ['name' => 'New User', 'email' => 'newuser@example.com', 'password' => bcrypt('password')];
+    $user = $this->repository->create($data);
+
+    expect($user)->toBeInstanceOf(User::class)
+        ->and($user->name)->toEqual('New User');
+});
+
+it('updates existing record with update method', function () {
+    $user = User::factory()->create(['name' => 'Old Name']);
+    $updated = $this->repository->update(['name' => 'Updated Name'], $user->id);
+
+    expect($updated)->toBeTrue()
+        ->and($user->refresh()->name)->toEqual('Updated Name');
+});
+
+it('deletes a record by id with delete method', function () {
+    $user = User::factory()->create();
+    $deleted = $this->repository->delete($user->id);
+
+    expect($deleted)->toEqual(1)
+        ->and(User::find($user->id))->toBeNull();
+});
+
+it('applies limit to query with limit method', function () {
+    User::factory()->count(10)->create();
+    $records = $this->repository->limit(5)->all();
+
+    expect($records)->toHaveCount(5);
+});
+
+it('returns paginated result with paginate method', function () {
+    User::factory()->count(15)->create();
+    $paginator = $this->repository->paginate(5);
+
+    expect($paginator)->toBeInstanceOf(LengthAwarePaginator::class)
+        ->and($paginator->perPage())->toEqual(5);
+});
-- 
GitLab


From fad3ebb55742d9db11366c0892eab14aadad0232 Mon Sep 17 00:00:00 2001
From: etiti <emmanueltiti370@gmail.com>
Date: Mon, 11 Nov 2024 23:33:50 +0300
Subject: [PATCH 2/5] deprecate assesment nomenclature

---
 .../DataTransferObjects/AssessmentReviewData.php  |  4 ++--
 .../Models/{AssessmentReview.php => Review.php}   |  2 +-
 .../Repositories/AssessmentReviewRepository.php   | 15 ---------------
 application/app/Repositories/ReviewRepository.php | 15 +++++++++++++++
 ...essmentReviewFactory.php => ReviewFactory.php} |  2 +-
 .../2024_11_11_153139_create_reviews_table.php    |  4 ++--
 ...ssessmentReviewSeeder.php => ReviewSeeder.php} |  6 +++---
 7 files changed, 24 insertions(+), 24 deletions(-)
 rename application/app/Models/{AssessmentReview.php => Review.php} (82%)
 delete mode 100644 application/app/Repositories/AssessmentReviewRepository.php
 create mode 100644 application/app/Repositories/ReviewRepository.php
 rename application/database/factories/{AssessmentReviewFactory.php => ReviewFactory.php} (93%)
 rename application/database/seeders/{AssessmentReviewSeeder.php => ReviewSeeder.php} (63%)

diff --git a/application/app/DataTransferObjects/AssessmentReviewData.php b/application/app/DataTransferObjects/AssessmentReviewData.php
index 4f147694..45d6a8a6 100644
--- a/application/app/DataTransferObjects/AssessmentReviewData.php
+++ b/application/app/DataTransferObjects/AssessmentReviewData.php
@@ -9,13 +9,13 @@
 use Spatie\TypeScriptTransformer\Attributes\TypeScript;
 
 #[TypeScript]
-final class AssessmentReviewData extends Data
+final class ReviewData extends Data
 {
     public function __construct(
         public ?int $id,
 
         #[TypeScriptOptional]
-        public ?int $assessor_id,
+        public ?int $reviewer_id,
 
         public int $excellent_count,
 
diff --git a/application/app/Models/AssessmentReview.php b/application/app/Models/Review.php
similarity index 82%
rename from application/app/Models/AssessmentReview.php
rename to application/app/Models/Review.php
index eea64d7f..12cad7d1 100644
--- a/application/app/Models/AssessmentReview.php
+++ b/application/app/Models/Review.php
@@ -7,7 +7,7 @@
 use Illuminate\Database\Eloquent\Factories\HasFactory;
 use Illuminate\Database\Eloquent\Model;
 
-class AssessmentReview extends Model
+class Review extends Model
 {
     use HasFactory;
 }
diff --git a/application/app/Repositories/AssessmentReviewRepository.php b/application/app/Repositories/AssessmentReviewRepository.php
deleted file mode 100644
index a56fc6f3..00000000
--- a/application/app/Repositories/AssessmentReviewRepository.php
+++ /dev/null
@@ -1,15 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace App\Repositories;
-
-use App\Models\AssessmentReview;
-
-class AssessmentReviewRepository extends Repository
-{
-    public function __construct(AssessmentReview $model)
-    {
-        parent::__construct($model);
-    }
-}
diff --git a/application/app/Repositories/ReviewRepository.php b/application/app/Repositories/ReviewRepository.php
new file mode 100644
index 00000000..134991a9
--- /dev/null
+++ b/application/app/Repositories/ReviewRepository.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Repositories;
+
+use App\Models\Review;
+
+class ReviewRepository extends Repository
+{
+    public function __construct(Review $model)
+    {
+        parent::__construct($model);
+    }
+}
diff --git a/application/database/factories/AssessmentReviewFactory.php b/application/database/factories/ReviewFactory.php
similarity index 93%
rename from application/database/factories/AssessmentReviewFactory.php
rename to application/database/factories/ReviewFactory.php
index ff0b7323..d7455379 100644
--- a/application/database/factories/AssessmentReviewFactory.php
+++ b/application/database/factories/ReviewFactory.php
@@ -7,7 +7,7 @@
 /**
  * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Review>
  */
-class AssessmentReviewFactory extends Factory
+class ReviewFactory extends Factory
 {
     /**
      * Define the model's default state.
diff --git a/application/database/migrations/2024_11_11_153139_create_reviews_table.php b/application/database/migrations/2024_11_11_153139_create_reviews_table.php
index 476f8095..f8324011 100644
--- a/application/database/migrations/2024_11_11_153139_create_reviews_table.php
+++ b/application/database/migrations/2024_11_11_153139_create_reviews_table.php
@@ -11,7 +11,7 @@
      */
     public function up(): void
     {
-        Schema::create('assessment_reviews', function (Blueprint $table) {
+        Schema::create('reviews', function (Blueprint $table) {
             $table->id();
             $table->timestamps();
             $table->foreignId('assessor_id');
@@ -28,6 +28,6 @@ public function up(): void
      */
     public function down(): void
     {
-        Schema::dropIfExists('assesment_reviews');
+        Schema::dropIfExists('reviews');
     }
 };
diff --git a/application/database/seeders/AssessmentReviewSeeder.php b/application/database/seeders/ReviewSeeder.php
similarity index 63%
rename from application/database/seeders/AssessmentReviewSeeder.php
rename to application/database/seeders/ReviewSeeder.php
index 8360998e..6e51eb83 100644
--- a/application/database/seeders/AssessmentReviewSeeder.php
+++ b/application/database/seeders/ReviewSeeder.php
@@ -2,17 +2,17 @@
 
 namespace Database\Seeders;
 
-use App\Models\AssessmentReview;
+use App\Models\Review;
 use Illuminate\Database\Console\Seeds\WithoutModelEvents;
 use Illuminate\Database\Seeder;
 
-class AssessmentReviewSeeder extends Seeder
+class ReviewSeeder extends Seeder
 {
     /**
      * Run the database seeds.
      */
     public function run(): void
     {
-        AssessmentReview::factory(10)->create();
+        Review::factory(10)->create();
     }
 }
-- 
GitLab


From f37ebe302c6db6934c2b39aa6af423e405cab3ca Mon Sep 17 00:00:00 2001
From: etiti <emmanueltiti370@gmail.com>
Date: Mon, 11 Nov 2024 23:37:57 +0300
Subject: [PATCH 3/5] update review policy

---
 application/app/Policies/ReviewPolicy.php | 39 ++++++++---------------
 1 file changed, 13 insertions(+), 26 deletions(-)

diff --git a/application/app/Policies/ReviewPolicy.php b/application/app/Policies/ReviewPolicy.php
index 6eacd68a..be0115f4 100644
--- a/application/app/Policies/ReviewPolicy.php
+++ b/application/app/Policies/ReviewPolicy.php
@@ -1,27 +1,30 @@
 <?php
 
+declare(strict_types=1);
+
 namespace App\Policies;
 
-use App\Models\Review;
 use App\Models\User;
+use App\Enums\RoleEnum;
+use App\Enums\PermissionEnum;
 use Illuminate\Auth\Access\Response;
 
-class ReviewPolicy
+class ReviewPolicy extends AppPolicy
 {
     /**
      * Determine whether the user can view any models.
      */
     public function viewAny(User $user): bool
     {
-        //
+        return parent::canViewAny($user) || $user->hasAnyPermission([PermissionEnum::read_users()->value]);
     }
 
     /**
      * Determine whether the user can view the model.
      */
-    public function view(User $user, Review $review): bool
+    public function view(User $user, User $model): bool
     {
-        //
+        return parent::canView($user, $model) || $user->hasAnyPermission([PermissionEnum::read_users()->value]);
     }
 
     /**
@@ -29,38 +32,22 @@ public function view(User $user, Review $review): bool
      */
     public function create(User $user): bool
     {
-        //
+        return parent::canCreate($user) || $user->hasAnyPermission([PermissionEnum::create_users()->value]);
     }
 
     /**
      * Determine whether the user can update the model.
      */
-    public function update(User $user, Review $review): bool
+    public function update(User $user, User $model): bool
     {
-        //
+        return parent::canUpdate($user, $model) || $user->hasAnyPermission([PermissionEnum::update_users()->value]);
     }
 
     /**
      * Determine whether the user can delete the model.
      */
-    public function delete(User $user, Review $review): bool
-    {
-        //
-    }
-
-    /**
-     * Determine whether the user can restore the model.
-     */
-    public function restore(User $user, Review $review): bool
-    {
-        //
-    }
-
-    /**
-     * Determine whether the user can permanently delete the model.
-     */
-    public function forceDelete(User $user, Review $review): bool
+    public function delete(User $user, User $model): bool
     {
-        //
+        return parent::canDelete($user, $model) || $user->hasAnyPermission([PermissionEnum::delete_users()->value]);
     }
 }
-- 
GitLab


From c557820434700010dc92009213aa8207def61833 Mon Sep 17 00:00:00 2001
From: etiti <emmanueltiti370@gmail.com>
Date: Mon, 11 Nov 2024 23:45:30 +0300
Subject: [PATCH 4/5] update review model name to ReviewModeration

---
 application/app/Models/{Review.php => ReviewModeration.php} | 2 +-
 .../{ReviewPolicy.php => ReviewModerationPolicy.php}        | 2 +-
 application/app/Repositories/ReviewRepository.php           | 4 ++--
 .../{ReviewFactory.php => ReviewModerationFactory.php}      | 4 ++--
 .../migrations/2024_11_11_153139_create_reviews_table.php   | 6 +++---
 .../{ReviewSeeder.php => ReviewModerationSeeder.php}        | 6 +++---
 6 files changed, 12 insertions(+), 12 deletions(-)
 rename application/app/Models/{Review.php => ReviewModeration.php} (82%)
 rename application/app/Policies/{ReviewPolicy.php => ReviewModerationPolicy.php} (96%)
 rename application/database/factories/{ReviewFactory.php => ReviewModerationFactory.php} (89%)
 rename application/database/seeders/{ReviewSeeder.php => ReviewModerationSeeder.php} (63%)

diff --git a/application/app/Models/Review.php b/application/app/Models/ReviewModeration.php
similarity index 82%
rename from application/app/Models/Review.php
rename to application/app/Models/ReviewModeration.php
index 12cad7d1..5243f8cb 100644
--- a/application/app/Models/Review.php
+++ b/application/app/Models/ReviewModeration.php
@@ -7,7 +7,7 @@
 use Illuminate\Database\Eloquent\Factories\HasFactory;
 use Illuminate\Database\Eloquent\Model;
 
-class Review extends Model
+class ReviewModeration extends Model
 {
     use HasFactory;
 }
diff --git a/application/app/Policies/ReviewPolicy.php b/application/app/Policies/ReviewModerationPolicy.php
similarity index 96%
rename from application/app/Policies/ReviewPolicy.php
rename to application/app/Policies/ReviewModerationPolicy.php
index be0115f4..bfbd3451 100644
--- a/application/app/Policies/ReviewPolicy.php
+++ b/application/app/Policies/ReviewModerationPolicy.php
@@ -9,7 +9,7 @@
 use App\Enums\PermissionEnum;
 use Illuminate\Auth\Access\Response;
 
-class ReviewPolicy extends AppPolicy
+class ReviewModerationPolicy extends AppPolicy
 {
     /**
      * Determine whether the user can view any models.
diff --git a/application/app/Repositories/ReviewRepository.php b/application/app/Repositories/ReviewRepository.php
index 134991a9..6bb287b2 100644
--- a/application/app/Repositories/ReviewRepository.php
+++ b/application/app/Repositories/ReviewRepository.php
@@ -4,11 +4,11 @@
 
 namespace App\Repositories;
 
-use App\Models\Review;
+use App\Models\ReviewModeration;
 
 class ReviewRepository extends Repository
 {
-    public function __construct(Review $model)
+    public function __construct(ReviewModeration $model)
     {
         parent::__construct($model);
     }
diff --git a/application/database/factories/ReviewFactory.php b/application/database/factories/ReviewModerationFactory.php
similarity index 89%
rename from application/database/factories/ReviewFactory.php
rename to application/database/factories/ReviewModerationFactory.php
index d7455379..07e277ee 100644
--- a/application/database/factories/ReviewFactory.php
+++ b/application/database/factories/ReviewModerationFactory.php
@@ -7,7 +7,7 @@
 /**
  * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Review>
  */
-class ReviewFactory extends Factory
+class ReviewModerationFactory extends Factory
 {
     /**
      * Define the model's default state.
@@ -17,7 +17,7 @@ class ReviewFactory extends Factory
     public function definition(): array
     {
         return [
-            'assessor_id' => 1,
+            'reviewer_id' => 1,
             'excellent_count' => rand(0,100),
             'good_count' => rand(0, 100),
             'filtered_out_count' => rand(0, 100),
diff --git a/application/database/migrations/2024_11_11_153139_create_reviews_table.php b/application/database/migrations/2024_11_11_153139_create_reviews_table.php
index f8324011..c360ce48 100644
--- a/application/database/migrations/2024_11_11_153139_create_reviews_table.php
+++ b/application/database/migrations/2024_11_11_153139_create_reviews_table.php
@@ -11,10 +11,10 @@
      */
     public function up(): void
     {
-        Schema::create('reviews', function (Blueprint $table) {
+        Schema::create('review_moderations', function (Blueprint $table) {
             $table->id();
             $table->timestamps();
-            $table->foreignId('assessor_id');
+            $table->foreignId('reviewer_id');
             $table->integer('excellent_count')->default(0);
             $table->integer('good_count')->default(0);
             $table->integer('filtered_out_count')->default(0);
@@ -28,6 +28,6 @@ public function up(): void
      */
     public function down(): void
     {
-        Schema::dropIfExists('reviews');
+        Schema::dropIfExists('review_moderations');
     }
 };
diff --git a/application/database/seeders/ReviewSeeder.php b/application/database/seeders/ReviewModerationSeeder.php
similarity index 63%
rename from application/database/seeders/ReviewSeeder.php
rename to application/database/seeders/ReviewModerationSeeder.php
index 6e51eb83..935ed183 100644
--- a/application/database/seeders/ReviewSeeder.php
+++ b/application/database/seeders/ReviewModerationSeeder.php
@@ -2,17 +2,17 @@
 
 namespace Database\Seeders;
 
-use App\Models\Review;
+use App\Models\ReviewModeration;
 use Illuminate\Database\Console\Seeds\WithoutModelEvents;
 use Illuminate\Database\Seeder;
 
-class ReviewSeeder extends Seeder
+class ReviewModerationSeeder extends Seeder
 {
     /**
      * Run the database seeds.
      */
     public function run(): void
     {
-        Review::factory(10)->create();
+        ReviewModeration::factory(10)->create();
     }
 }
-- 
GitLab


From 04c1bb1e628c7436f2142203bb9d8f602495f1b0 Mon Sep 17 00:00:00 2001
From: etiti <emmanueltiti370@gmail.com>
Date: Mon, 11 Nov 2024 23:48:42 +0300
Subject: [PATCH 5/5] update ReviewModeration DTO

---
 ...ReviewData.php => ReviewModerationData.php} |  2 +-
 application/resources/types/generated.d.ts     | 18 +++++++++---------
 2 files changed, 10 insertions(+), 10 deletions(-)
 rename application/app/DataTransferObjects/{AssessmentReviewData.php => ReviewModerationData.php} (92%)

diff --git a/application/app/DataTransferObjects/AssessmentReviewData.php b/application/app/DataTransferObjects/ReviewModerationData.php
similarity index 92%
rename from application/app/DataTransferObjects/AssessmentReviewData.php
rename to application/app/DataTransferObjects/ReviewModerationData.php
index 45d6a8a6..3ac74ba3 100644
--- a/application/app/DataTransferObjects/AssessmentReviewData.php
+++ b/application/app/DataTransferObjects/ReviewModerationData.php
@@ -9,7 +9,7 @@
 use Spatie\TypeScriptTransformer\Attributes\TypeScript;
 
 #[TypeScript]
-final class ReviewData extends Data
+final class ReviewModerationData extends Data
 {
     public function __construct(
         public ?int $id,
diff --git a/application/resources/types/generated.d.ts b/application/resources/types/generated.d.ts
index 252b2277..97576335 100644
--- a/application/resources/types/generated.d.ts
+++ b/application/resources/types/generated.d.ts
@@ -1,13 +1,4 @@
 declare namespace App.DataTransferObjects {
-    export type AssessmentReviewData = {
-        id: number | null;
-        assessor_id?: number;
-        excellent_count: number;
-        good_count: number;
-        filtered_out_count: number;
-        flagged: boolean;
-        qa_rationale?: Array<any>;
-    };
     export type IdeascaleProfileData = {
         id: number | null;
         ideascaleId?: number;
@@ -62,6 +53,15 @@ declare namespace App.DataTransferObjects {
         quickpitch?: string;
         quickpitch_length?: number;
     };
+    export type ReviewModerationData = {
+        id: number | null;
+        reviewer_id?: number;
+        excellent_count: number;
+        good_count: number;
+        filtered_out_count: number;
+        flagged: boolean;
+        qa_rationale?: Array<any>;
+    };
     export type UserData = {
         id: number;
         name: string;
-- 
GitLab