From 3b042182e8df58beaba9b2662743f1770e4f0117 Mon Sep 17 00:00:00 2001
From: jorplaz <429-jorplaz@users.noreply.gitlab.inf.uva.es>
Date: Sat, 2 Jul 2022 12:52:04 +0200
Subject: [PATCH] Updated models and seeders

---
 app/Http/Controllers/AuthController.php       | 12 +++-
 app/Models/Bike.php                           | 12 ++++
 app/Models/ElectricBike.php                   |  4 ++
 app/Models/Reward.php                         |  7 +++
 app/Models/Route.php                          |  7 +++
 app/Models/Stop.php                           | 30 +++++++++
 app/Models/User.php                           |  7 +++
 app/Providers/AppServiceProvider.php          |  5 +-
 composer.json                                 |  3 +-
 composer.lock                                 | 63 ++++++++++++++++++-
 .../2022_06_13_151027_create_bikes_table.php  |  3 +
 ..._13_153838_create_electric_bikes_table.php |  3 +-
 .../2022_06_14_151011_create_routes_table.php |  2 +
 ...2022_06_15_144408_create_rewards_table.php |  1 +
 database/seeders/BikeSeeder.php               | 19 ++++--
 database/seeders/RewardSeeder.php             | 15 +++--
 database/seeders/UserSeeder.php               |  3 +-
 routes/api.php                                | 30 ++++++++-
 18 files changed, 203 insertions(+), 23 deletions(-)

diff --git a/app/Http/Controllers/AuthController.php b/app/Http/Controllers/AuthController.php
index 87a0349..1c4a337 100644
--- a/app/Http/Controllers/AuthController.php
+++ b/app/Http/Controllers/AuthController.php
@@ -2,8 +2,11 @@
 
 namespace App\Http\Controllers;
 
+use App\Models\User;
 use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Log;
 use Illuminate\Support\Facades\Validator;
+use Laravel\Sanctum\PersonalAccessToken;
 
 class AuthController extends Controller
 {
@@ -24,9 +27,12 @@ class AuthController extends Controller
         ]);
     }
 
-    public function logout()
+    public function logout(Request $request)
     {
-        auth()->user()->tokens()->delete();
-        return  response()->json(['Token revoked']);
+        $user = UserController::getUserByToken($request);
+        if(1 != $user->tokens()->delete()){
+            return "false";
+        }
+        return "true";
     }
 }
\ No newline at end of file
diff --git a/app/Models/Bike.php b/app/Models/Bike.php
index 05c406f..75a3e69 100644
--- a/app/Models/Bike.php
+++ b/app/Models/Bike.php
@@ -6,17 +6,25 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
 use Illuminate\Database\Eloquent\Model;
 use Illuminate\Database\Eloquent\Relations\BelongsTo;
 use Illuminate\Database\Eloquent\Relations\HasMany;
+use Nanigans\SingleTableInheritance\SingleTableInheritanceTrait;
 
 /**
  * @method static create(array $array)
+ * @method static find(int $int)
+ * @property mixed $id
+ * @property mixed $bikeable_type
+ * @property mixed|null $stop_id
  */
 class Bike extends Model
 {
     use HasFactory;
 
+    protected $table = "bikes";
+
     protected $fillable = [
         'stop_id',
         'unlocked',
+        'type'
     ];
 
     public function stop(): BelongsTo{
@@ -26,4 +34,8 @@ class Bike extends Model
     public function routes(): HasMany{
         return $this->hasMany(Route::class);
     }
+
+    public function bikeable(){
+        return $this->morphTo();
+    }
 }
diff --git a/app/Models/ElectricBike.php b/app/Models/ElectricBike.php
index 8991516..de5833e 100644
--- a/app/Models/ElectricBike.php
+++ b/app/Models/ElectricBike.php
@@ -14,4 +14,8 @@ class ElectricBike extends Bike
         'id',
         'battery',
     ];
+
+    public function bike(){
+        return $this->morphOne(Bike::class, 'bikeable');
+    }
 }
diff --git a/app/Models/Reward.php b/app/Models/Reward.php
index 3b40b19..e108eb0 100644
--- a/app/Models/Reward.php
+++ b/app/Models/Reward.php
@@ -8,6 +8,9 @@ use Illuminate\Database\Eloquent\Relations\BelongsToMany;
 
 /**
  * @method static create(array $array)
+ * @property mixed $redeemed
+ * @property mixed $total_available
+ * @property mixed $points
  */
 class Reward extends Model
 {
@@ -18,6 +21,10 @@ class Reward extends Model
         'description',
         'user_id',
         'reward_id',
+        'points',
+        'total_available',
+        'image',
+        'redeemed',
     ];
 
     public function users(): BelongsToMany{
diff --git a/app/Models/Route.php b/app/Models/Route.php
index 987300d..d33714c 100644
--- a/app/Models/Route.php
+++ b/app/Models/Route.php
@@ -6,6 +6,12 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
 use Illuminate\Database\Eloquent\Model;
 use Illuminate\Database\Eloquent\Relations\BelongsTo;
 
+/**
+ * @property mixed $user_id
+ * @property \Illuminate\Database\Eloquent\HigherOrderBuilderProxy|mixed $initial_stop_id
+ * @property mixed $bike_id
+ * @method static find(mixed $id)
+ */
 class Route extends Model
 {
     use HasFactory;
@@ -17,6 +23,7 @@ class Route extends Model
         "bike_id",
         "distance",
         "duration",
+        "estimated_duration",
         "points",
     ];
 
diff --git a/app/Models/Stop.php b/app/Models/Stop.php
index 2a25676..0b74cb9 100644
--- a/app/Models/Stop.php
+++ b/app/Models/Stop.php
@@ -5,9 +5,16 @@ namespace App\Models;
 use Illuminate\Database\Eloquent\Factories\HasFactory;
 use Illuminate\Database\Eloquent\Model;
 use Illuminate\Database\Eloquent\Relations\HasMany;
+use phpDocumentor\Reflection\Types\Boolean;
+use PhpParser\Node\Expr\Cast\Int_;
 
 /**
  * @method static create(array $array)
+ * @method static find($initial_stop_id)
+ * @property mixed $lng
+ * @property mixed $lat
+ * @property mixed $total_spaces
+ * @property mixed $id
  */
 class Stop extends Model
 {
@@ -34,4 +41,27 @@ class Stop extends Model
     public function routesEnd(): HasMany{
         return $this->hasMany(Route::class, "final_stop_id");
     }
+
+    public function reservations(): HasMany{
+        return $this->hasMany(Reservation::class);
+    }
+
+    public function reserved_pedal_bikes(): int{
+        return $this->reservations()->where('bike_type', '=', 'pedal')->count();
+    }
+    public function reserved_electric_bikes(): int{
+        return $this->reservations()->where('bike_type', '=', 'electric')->count();
+    }
+
+    public function check_availability_bikes(String $type): bool{
+        $available = false;
+        if ($type=="pedal" || $type=="App\Models\Bike"){
+            $bikeCount = $this->bikes()->where('bikeable_type', '=', 'App\Models\Bike')->count();
+            $available = $bikeCount > $this->reserved_pedal_bikes();
+        }else if ($type=="electric" || $type=="App\Models\ElectricBike"){
+            $bikeCount = $this->bikes()->where('bikeable_type', '=', 'App\Models\ElectricBike')->count();
+            $available = $bikeCount > $this->reserved_electric_bikes();
+        }
+        return $available;
+    }
 }
diff --git a/app/Models/User.php b/app/Models/User.php
index b9cb8ba..4bb40e9 100644
--- a/app/Models/User.php
+++ b/app/Models/User.php
@@ -13,6 +13,9 @@ use Laravel\Sanctum\HasApiTokens;
 /**
  * @method static create(string[] $array)
  * @method static find(int $id)
+ * @method static where(string $string, mixed $email)
+ * @property mixed $points
+ * @property mixed $id
  */
 class User extends Authenticatable
 {
@@ -55,4 +58,8 @@ class User extends Authenticatable
     public function rewards(): BelongsToMany{
         return $this->belongsToMany(Reward::class, 'user_reward')->withTimestamps();
     }
+
+    public function reservations(): HasMany{
+        return $this->hasMany(Reservation::class);
+    }
 }
diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php
index 88da5b6..c29e182 100644
--- a/app/Providers/AppServiceProvider.php
+++ b/app/Providers/AppServiceProvider.php
@@ -22,8 +22,11 @@ class AppServiceProvider extends ServiceProvider
      *
      * @return void
      */
-    public function boot()
+    public function boot(\Illuminate\Http\Request $request)
     {
+        if (!empty( env('NGROK_URL') ) && $request->server->has('HTTP_X_ORIGINAL_HOST')) {
+            $this->app['url']->forceRootUrl(env('NGROK_URL'));
+        }
         JsonResource::withoutWrapping();
     }
 }
diff --git a/composer.json b/composer.json
index 0ab4cf7..e112bb1 100644
--- a/composer.json
+++ b/composer.json
@@ -9,7 +9,8 @@
         "guzzlehttp/guzzle": "^7.2",
         "laravel/framework": "^9.11",
         "laravel/sanctum": "^2.15",
-        "laravel/tinker": "^2.7"
+        "laravel/tinker": "^2.7",
+        "nanigans/single-table-inheritance": "~1.0"
     },
     "require-dev": {
         "fakerphp/faker": "^1.9.1",
diff --git a/composer.lock b/composer.lock
index 292c550..9ba8178 100644
--- a/composer.lock
+++ b/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": "58fa573d0eb02b0bca9c8679dea764c0",
+    "content-hash": "a6074d6cbd7b2a35b7d18370d948483f",
     "packages": [
         {
             "name": "brick/math",
@@ -1702,6 +1702,67 @@
             ],
             "time": "2022-05-10T09:36:00+00:00"
         },
+        {
+            "name": "nanigans/single-table-inheritance",
+            "version": "v1.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/jonspalmer/single-table-inheritance.git",
+                "reference": "5fd1dd86ddc5ab66bf9d1260b8de1e58ac5826ff"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/jonspalmer/single-table-inheritance/zipball/5fd1dd86ddc5ab66bf9d1260b8de1e58ac5826ff",
+                "reference": "5fd1dd86ddc5ab66bf9d1260b8de1e58ac5826ff",
+                "shasum": ""
+            },
+            "require": {
+                "illuminate/database": ">= 5.2",
+                "illuminate/support": ">= 5.2",
+                "php": ">= 7.2"
+            },
+            "require-dev": {
+                "mockery/mockery": "~1.0",
+                "orchestra/database": "3.8.*|4.*|5.*|6.*",
+                "orchestra/testbench": "3.8.*|4.*|5.*|6.*",
+                "phpunit/phpunit": "~8.0|~9.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-main": "1.1.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Nanigans\\SingleTableInheritance\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Jon Palmer",
+                    "email": "328224+jonspalmer@users.noreply.github.com"
+                }
+            ],
+            "description": "Single Table Inheritance Trait",
+            "keywords": [
+                "eloquent",
+                "inheritance",
+                "laravel",
+                "model",
+                "single",
+                "table"
+            ],
+            "support": {
+                "issues": "https://github.com/jonspalmer/single-table-inheritance/issues",
+                "source": "https://github.com/jonspalmer/single-table-inheritance/tree/v1.0.0"
+            },
+            "time": "2021-04-17T13:10:00+00:00"
+        },
         {
             "name": "nesbot/carbon",
             "version": "2.58.0",
diff --git a/database/migrations/2022_06_13_151027_create_bikes_table.php b/database/migrations/2022_06_13_151027_create_bikes_table.php
index 705aadf..6e16720 100644
--- a/database/migrations/2022_06_13_151027_create_bikes_table.php
+++ b/database/migrations/2022_06_13_151027_create_bikes_table.php
@@ -16,10 +16,13 @@ return new class extends Migration
         Schema::create('bikes', function (Blueprint $table) {
             $table->id();
             $table->foreignId('stop_id')
+                ->nullable()
                 ->index()
                 ->constrained()
                 ->cascadeOnUpdate();
             $table->boolean('unlocked');
+            $table->unsignedBigInteger('bikeable_id');
+            $table->string('bikeable_type');
             $table->timestamps();
         });
     }
diff --git a/database/migrations/2022_06_13_153838_create_electric_bikes_table.php b/database/migrations/2022_06_13_153838_create_electric_bikes_table.php
index db6b5b7..0946573 100644
--- a/database/migrations/2022_06_13_153838_create_electric_bikes_table.php
+++ b/database/migrations/2022_06_13_153838_create_electric_bikes_table.php
@@ -17,8 +17,7 @@ return new class extends Migration
             $table->id();
             $table->integer('battery');
             $table->timestamps();
-
-            $table->foreign('id')->references('id')->on('bikes');
+            //$table->foreign('id')->references('id')->on('bikes');
         });
     }
 
diff --git a/database/migrations/2022_06_14_151011_create_routes_table.php b/database/migrations/2022_06_14_151011_create_routes_table.php
index 51d6e35..f73d946 100644
--- a/database/migrations/2022_06_14_151011_create_routes_table.php
+++ b/database/migrations/2022_06_14_151011_create_routes_table.php
@@ -48,6 +48,8 @@ return new class extends Migration
                 ->nullable();
             $table->integer('duration')
                 ->nullable();
+            $table->integer('estimated_duration')
+                ->nullable();
             $table->integer('points')
                 ->nullable();
 
diff --git a/database/migrations/2022_06_15_144408_create_rewards_table.php b/database/migrations/2022_06_15_144408_create_rewards_table.php
index deebdc1..485b82c 100644
--- a/database/migrations/2022_06_15_144408_create_rewards_table.php
+++ b/database/migrations/2022_06_15_144408_create_rewards_table.php
@@ -19,6 +19,7 @@ return new class extends Migration
             $table->string('description');
             $table->integer('points');
             $table->integer('total_available');
+            $table->integer('redeemed')->default(0);
             $table->string('image')->nullable();
             $table->timestamps();
         });
diff --git a/database/seeders/BikeSeeder.php b/database/seeders/BikeSeeder.php
index 22543e8..b638f24 100644
--- a/database/seeders/BikeSeeder.php
+++ b/database/seeders/BikeSeeder.php
@@ -18,29 +18,36 @@ class BikeSeeder extends Seeder
     {
         $bike = Bike::create([
             'stop_id' => 1,
-            'unlocked' => false
+            'unlocked' => false,
+            'bikeable_id' => 1,
+            'bikeable_type' => 'App\Models\ElectricBike',
         ]);
         ElectricBike::create([
-            'id' => $bike->id,
             'battery' => 60
         ]);
         Bike::create([
             'stop_id' => 1,
-            'unlocked' => false
+            'unlocked' => false,
+            'bikeable_id' => 2,
+            'bikeable_type' => 'App\Models\Bike',
         ]);
 
         $bike = Bike::create([
             'stop_id' => 2,
-            'unlocked' => false
+            'unlocked' => false,
+            'bikeable_id' => 2,
+            'bikeable_type' => 'App\Models\ElectricBike',
         ]);
         ElectricBike::create([
-            'id' => $bike->id,
             'battery' => 70
         ]);
 
         Bike::create([
             'stop_id' => 3,
-            'unlocked' => false
+            'unlocked' => false,
+            'bikeable_id' => 4,
+            'bikeable_type' => 'App\Models\Bike',
         ]);
+
     }
 }
diff --git a/database/seeders/RewardSeeder.php b/database/seeders/RewardSeeder.php
index 5472789..e98dbed 100644
--- a/database/seeders/RewardSeeder.php
+++ b/database/seeders/RewardSeeder.php
@@ -19,33 +19,38 @@ class RewardSeeder extends Seeder
             'name' => 'Reward 1',
             'description' => 'A short description',
             'points' => 100,
-            'total_available' => 5
+            'total_available' => 5,
+            "image"=> "https://images.unsplash.com/photo-1591544940847-e8c860a9464e?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1974&q=80"
         ]);
         $reward->users()->sync([1,2]);
         $reward = Reward::create([
             'name' => 'Reward 2',
             'description' => 'A short description 2',
             'points' => 200,
-            'total_available' => 2
+            'total_available' => 2,
+            "image"=> "https://images.unsplash.com/photo-1621841957884-1210fe19d66d?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2340&q=80"
         ]);
         $reward->users()->sync([1]);
         Reward::create([
             'name' => 'Reward 3',
             'description' => 'A short description 3',
             'points' => 1000,
-            'total_available' => 1
+            'total_available' => 1,
+            "image" => "https://images.unsplash.com/photo-1565599837634-134bc3aadce8?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1335&q=80"
         ]);
         Reward::create([
             'name' => 'Reward 4',
             'description' => 'A short description 4',
             'points' => 4,
-            'total_available' => 10
+            'total_available' => 10,
+            'image' => 'https://images.unsplash.com/photo-1617257118084-339d30c49b02?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2340&q=80'
         ]);
         Reward::create([
             'name' => 'Reward 5',
             'description' => 'A short description 5',
             'points' => 500,
-            'total_available' => 5
+            'total_available' => 5,
+            "image"=> "https://images.unsplash.com/photo-1655219282218-6a4a8d91a699?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2340&q=80"
         ]);
     }
 }
diff --git a/database/seeders/UserSeeder.php b/database/seeders/UserSeeder.php
index 53bc219..81d01bf 100644
--- a/database/seeders/UserSeeder.php
+++ b/database/seeders/UserSeeder.php
@@ -18,7 +18,8 @@ class UserSeeder extends Seeder
         User::create([
             'name' => 'Jorge',
             'email' => 'jorge@uva.es',
-            'password' => '12345678'
+            'password' => bcrypt('123456'),
+            'points' => 1000
         ]);
         User::create([
             'name' => 'Mario',
diff --git a/routes/api.php b/routes/api.php
index fd621db..0276c00 100644
--- a/routes/api.php
+++ b/routes/api.php
@@ -2,8 +2,12 @@
 
 use App\Http\Controllers\AuthController;
 use App\Http\Controllers\BikeController;
+use App\Http\Controllers\RewardController;
 use App\Http\Controllers\RouteController;
 use App\Http\Controllers\StopController;
+use App\Http\Resources\BikeResource;
+use App\Http\Resources\RewardColletion;
+use App\Models\Bike;
 use Illuminate\Http\Request;
 use Illuminate\Support\Facades\Route;
 
@@ -23,10 +27,30 @@ Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
 });
 
 Route::post('/login', [AuthController::class, 'login']);
-Route::get('/retobici/stops', [StopController::class, 'getAllStops']);
+Route::get('/stops', [StopController::class, 'getAllStops']);
+Route::get('/rewards', [RewardController::class, 'getAllRewards']);
 
 Route::middleware('auth:sanctum')->group(function (){
-    Route::post('/retobici/bikes/unlock/{bike}', [BikeController::class, 'unlockBike']);
-    Route::put('/retobici/routes', [RouteController::class, 'createRoute']);
+
+    Route::post('/stops/{bike}/unlock', [StopController::class, 'unlockBike']);
+    Route::post('/stops/{stop}/reserve/{type}', [StopController::class, 'reserveBike']);
+    Route::post('/stops/{stop}/lock', [StopController::class, 'lockBike']);
+
+    Route::put('/routes/{bike}', [RouteController::class, 'createRoute']);
+    Route::post('/routes/finish', [RouteController::class, 'finishRoute']);
+
+    Route::post('/rewards/{reward}', [RewardController::class, 'obtainReward']);
+    Route::get('/rewards/redeemed', [RewardController::class, 'getUserRewards']);
+    Route::get('/rewards/not/redeemed', [RewardController::class, 'getNotRedeemedRewards']);
+
+    Route::post('/logout', [AuthController::class, 'logout']);
+});
+
+Route::get('/test', function (){
+    $stops = \App\Models\Stop::all();
+    $remove = $stops->first();
+    return $stops->filter(function ($value) use ($remove){
+        return $value!=$remove;
+    });
 });
 
-- 
GitLab