diff --git a/app/Http/Controllers/Api/v1/BasketController.php b/app/Http/Controllers/Api/v1/BasketController.php index 61661da..e808f4c 100644 --- a/app/Http/Controllers/Api/v1/BasketController.php +++ b/app/Http/Controllers/Api/v1/BasketController.php @@ -3,13 +3,10 @@ namespace App\Http\Controllers\Api\v1; use Illuminate\Http\Request; -use Illuminate\Support\Str; use App\Models\Campagne; -use App\Models\Coupon; use App\Enums\LogActions; use App\Http\Controllers\Controller; use App\Models\Basket; -use App\Models\BasketContent; use App\Models\Customers; use App\Traits\CouponTrait; use App\Traits\ThanksTrait; @@ -128,36 +125,7 @@ class BasketController extends Controller $customer = Customers::where('hashcode', $request->customer_hashcode)->first(); // Retrieve or create basket - $basket = Basket::where(['campagne_id' => $refcamp, 'customer_id' => $customer->id])->first(); - - if ($basket) { - $camp = Campagne::where('camp_id', $basket->campagne_id)->first(); - foreach ($coupons as $couponCode => $quantity) { - $cp = $camp->coupons()->where('coupon_code', $couponCode)->first(); - if ($cp) { - $basketContent = BasketContent::where(['basket_id' => $basket->id, 'coupon_id' => $cp->coupon_id])->first(); - if ($basketContent) { - $basketContent->quantity += $quantity; - $basketContent->save(); - } else { - $this->addContentToBasket($basket, $cp, $quantity); - } - } - } - } else { - $basket = new Basket(); - $basket->uuid = (string) Str::uuid(); - $basket->campagne()->associate($refcamp); - $basket->customer()->associate($customer); - $basket->save(); - - foreach ($coupons as $couponCode => $quantity) { - $cp = $campagne->coupons()->where('coupon_code', $couponCode)->first(); - if ($cp) { - $this->addContentToBasket($basket, $cp, $quantity); - } - } - } + $basket = Basket::updateContent($campagne, $coupons, $customer); // Log success $this->writeLogSuccessBasketCreated( @@ -173,15 +141,4 @@ class BasketController extends Controller 'Panier' => $basket ]); } - - private function addContentToBasket(Basket $basket, Coupon $coupon, int $quantity): void - { - if ($quantity > 0) { - $newBasketContent = new BasketContent(); - $newBasketContent->basket_id = $basket->id; - $newBasketContent->coupon_id = $coupon->coupon_id; - $newBasketContent->quantity = $quantity; - $newBasketContent->save(); - } - } } diff --git a/app/Http/Controllers/Api/v1/CouponsController.php b/app/Http/Controllers/Api/v1/CouponsController.php index 74c38f2..ad5fddf 100644 --- a/app/Http/Controllers/Api/v1/CouponsController.php +++ b/app/Http/Controllers/Api/v1/CouponsController.php @@ -9,8 +9,6 @@ use App\Http\Controllers\Controller; use App\Http\Requests\Coupons\PrintRequest; use App\Http\Resources\StatusResource; use App\Models\Customers; -use App\Models\PrintedCoupons; -use App\Models\Statistique; use App\Traits\CouponTrait; use App\Traits\GenerateBR; use PDF; diff --git a/app/Http/Controllers/Fo/BasketController.php b/app/Http/Controllers/Fo/BasketController.php index d322357..87f0078 100644 --- a/app/Http/Controllers/Fo/BasketController.php +++ b/app/Http/Controllers/Fo/BasketController.php @@ -22,6 +22,10 @@ class BasketController extends Controller return $content->quantity - $content->printed; }); + if (!$totalQuantity) { + return view('fo.basket.empty', compact('basket')); + } + return view('fo.basket.show', compact('basket', 'totalQuantity')); } @@ -78,6 +82,10 @@ class BasketController extends Controller } } + if (empty($coupons)) { + return redirect()->route('fo.basket.show', $basket); + } + // $coupons contains all printed coupons $pdf = PDF::loadView('pdf.coupons', ['coupons' => $coupons]); return $pdf->download(sprintf("coupons_%s_%s_%s.pdf", $crmInfos->firstname, $crmInfos->lastname, date('d-m-Y'))); diff --git a/app/Models/Basket.php b/app/Models/Basket.php index 283c36b..c4807c4 100644 --- a/app/Models/Basket.php +++ b/app/Models/Basket.php @@ -7,11 +7,16 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Support\Str; class Basket extends Model { use HasFactory; + protected $fillable = [ + 'campagne_id' + ]; + /** * Customer model relation * @return BelongsTo @@ -38,4 +43,40 @@ class Basket extends Model { return $this->hasMany(BasketContent::class); } + + public static function updateContent(Campagne $campagne, array $coupons, Customers $customer) + { + $basket = self::where(['campagne_id' => $campagne->camp_id, 'customer_id' => $customer->id])->first(); + + if (!$basket) { + $basket = new Basket(); + $basket->uuid = (string) Str::uuid(); + $basket->campagne()->associate($campagne); + $basket->customer()->associate($customer); + $basket->save(); + } + + foreach ($coupons as $couponCode => $quantity) { + $associatedCoupon = $campagne->coupons()->where('coupon_code', $couponCode)->first(); + + if ($associatedCoupon) { + $basketContent = BasketContent::where(['basket_id' => $basket->id, 'coupon_id' => $associatedCoupon->coupon_id])->first(); + if ($basketContent) { + $basketContent->quantity += $quantity; + $basketContent->save(); + } else { + if ($quantity > 0) { + $newBasketContent = new BasketContent(); + $newBasketContent->basket_id = $basket->id; + $newBasketContent->coupon_id = $associatedCoupon->coupon_id; + $newBasketContent->quantity = $quantity; + $newBasketContent->save(); + } + } + } + + } + + return $basket; + } } diff --git a/app/Models/Customers.php b/app/Models/Customers.php index 2e93077..a5c02bd 100644 --- a/app/Models/Customers.php +++ b/app/Models/Customers.php @@ -3,11 +3,14 @@ namespace App\Models; use App\Models\Panier; +use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; class Customers extends Model { + use HasFactory; + /** * @var string $primaryKey */ diff --git a/app/Traits/LogTrait.php b/app/Traits/LogTrait.php index ac0b659..1d6e5ec 100644 --- a/app/Traits/LogTrait.php +++ b/app/Traits/LogTrait.php @@ -26,26 +26,26 @@ trait LogTrait /** * Write error log when there's a wrong or missing parameter in the request. * - * @param string $refcamp - * @param string $refadherent - * @param string $refsite - * @param string $panier + * @param string|null $refcamp + * @param string|null $refadherent + * @param string|null $refsite + * @param string|null $panier * @return void */ public function writeLogErrorWrongRequestParameters( - string $refcamp, - string $refadherent, - string $refsite, - string $panier + $refcamp, + $refadherent, + $refsite, + $panier ) { $log = new Log(); $log->log_action = $this->logAction->value; $log->log_source = $this->logSource; $log->log_params = json_encode([ - 'refcamp' => $refcamp, - 'refadherent' => $refadherent, - 'refsite' => $refsite, - 'panier' => $panier + 'refcamp' => $refcamp ?? 'NO DATA', + 'refadherent' => $refadherent ?? 'NO DATA', + 'refsite' => $refsite ?? 'NO DATA', + 'panier' => $panier ?? 'NO DATA' ]); $log->log_statut = 'NOK'; $log->log_message = "Des paramètres de la requête sont mal renseignés ou non présents"; diff --git a/database/factories/CustomersFactory.php b/database/factories/CustomersFactory.php new file mode 100644 index 0000000..e80810f --- /dev/null +++ b/database/factories/CustomersFactory.php @@ -0,0 +1,25 @@ + $this->faker->randomDigit(), + 'hashcode' => $this->faker->uuid(), + 'email' => $this->faker->unique()->safeEmail(), + 'country' => $this->faker->randomElement([56,442, 250]), // ISO Country value for Belgium, Luxembourg and France + 'created_at' => now(), + 'updated_at' => now(), + ]; + } +} diff --git a/resources/views/fo/basket/empty.blade.php b/resources/views/fo/basket/empty.blade.php new file mode 100644 index 0000000..204c06a --- /dev/null +++ b/resources/views/fo/basket/empty.blade.php @@ -0,0 +1,12 @@ +@extends('fo.layout') +@section('title', $basket->campagne->site->site_libelle . ' - ' . __('Bons de Réduction')) + +@section('content') +
+
+ {{ $basket->campagne->site->site_libelle }} +

+

{{ __('Coupon(s) non disponible') }}

+
+
+@endsection \ No newline at end of file diff --git a/resources/views/fo/basket/show.blade.php b/resources/views/fo/basket/show.blade.php index d83cdc0..bec0302 100644 --- a/resources/views/fo/basket/show.blade.php +++ b/resources/views/fo/basket/show.blade.php @@ -1,28 +1,22 @@ - - - - - {{ $basket->campagne->site->site_libelle }} - {{ __('Bons de Réduction') }} - - - - - -
-
- {{ $basket->campagne->site->site_libelle }} -
+@extends('fo.layout') +@section('title', $basket->campagne->site->site_libelle . ' - ' . __('Bons de Réduction')) -
-
-
Nombre de coupons :
-

{{ $totalQuantity }}

-
+@section('content') +
+
+ {{ $basket->campagne->site->site_libelle }} +
+ +
+
+
Nombre de coupons :
+

{{ $totalQuantity }}

- @if($totalQuantity) -
-

Liste des coupons :

-
    +
+ @if($totalQuantity) +
+

Liste des coupons :

+
    @foreach ($basket->contents as $content) @php $remain = $content->quantity - $content->printed; @@ -34,16 +28,13 @@ @endif @endforeach -
-
- - - @endif - +
- - - - + + + @endif + +
+@endsection \ No newline at end of file diff --git a/resources/views/fo/layout.blade.php b/resources/views/fo/layout.blade.php new file mode 100644 index 0000000..2a5b863 --- /dev/null +++ b/resources/views/fo/layout.blade.php @@ -0,0 +1,15 @@ + + + + + @yield('title') + + + + + + @yield('content') + + + + diff --git a/routes/api.php b/routes/api.php index 4dfa3da..008f3ed 100644 --- a/routes/api.php +++ b/routes/api.php @@ -11,11 +11,14 @@ | */ +use Illuminate\Support\Facades\Route; + Route::prefix('v1') + ->name('api.v1.') ->group(function () { Route::get('/customer/mur', 'Api\v1\CustomerController@mur'); Route::get('/customer/basket', 'Api\v1\CustomerController@basket'); - Route::get('/customer/basket/update', 'Api\v1\BasketController@updateBasket'); + Route::get('/customer/basket/update', 'Api\v1\BasketController@updateBasket')->name('basket.update'); Route::resource('customer', 'Api\v1\CustomerController'); Route::get('/mur', 'Api\v1\MurController@show'); Route::get('/coupons/print', 'Api\v1\CouponsController@print'); diff --git a/tests/Feature/Api/V1/BasketTest.php b/tests/Feature/Api/V1/BasketTest.php new file mode 100644 index 0000000..f9c3afd --- /dev/null +++ b/tests/Feature/Api/V1/BasketTest.php @@ -0,0 +1,153 @@ +json('GET', $enpoint, [ + // missing required params intentionally + ]); + + $response->assertStatus(200) + ->assertJson([ + 'Statut' => 'KO', + 'Code' => 101, + 'Message' => 'Des paramètres de la requête sont mal renseignés ou non présents', + ]); + } + + public function test_updateBasket_invalidCampaign_returnsError() + { + $enpoint = route('api.v1.basket.update'); + + $response = $this->json('GET', $enpoint, [ + 'customer_hashcode' => 'hash123', + 'refcamp' => 999999, // non existent campaign id + 'refsite' => 1, + 'panier' => '1)1000', + ]); + + $response->assertStatus(200) + ->assertJson([ + 'Statut' => 'KO', + 'Code' => 103, + 'Message' => "La campagne n'existe pas ou n'est pas un panier", + ]); + } + + public function test_updateBasket_successfulBasketCreation_returnsSuccess() + { + $enpoint = route('api.v1.basket.update'); + + // Create a fake campaign + $campaign = Campagne::factory()->create([ + 'camp_published' => 1, + 'camp_type' => 1, + 'camp_siteId' => 1, + ]); + + // Create a fake customer + $customer = Customers::factory()->create([ + 'hashcode' => 'hash123', + ]); + + // Create a coupon in the campaign + $coupon = Coupon::factory()->create(); + $campaign->coupons()->attach($coupon); + + $response = $this->json('GET', $enpoint, [ + 'customer_hashcode' => 'hash123', + 'refcamp' => $campaign->camp_id, + 'refsite' => $campaign->camp_siteId, + 'panier' => sprintf("(%d)%s", 2, $coupon->coupon_code), + ]); + + $response->assertStatus(200) + ->assertJson([ + 'Statut' => 'OK', + ]); + + // Assert basket created for the customer and campaign + $this->assertDatabaseHas('baskets', [ + 'campagne_id' => $campaign->camp_id, + 'customer_id' => $customer->id, + ]); + + $basket = Basket::where(['campagne_id' => $campaign->camp_id, 'customer_id' => $customer->id])->first(); + + $this->assertDatabaseHas('basket_contents', [ + 'quantity' => 2, + 'printed' => 0, + 'basket_id' => $basket->id, + 'coupon_id' => $coupon->coupon_id + ]); + } + + public function test_updateBasket_successfulBasketUpdate_returnsSuccess() + { + $enpoint = route('api.v1.basket.update'); + + // Create a fake campaign + $campaign = Campagne::factory()->create([ + 'camp_published' => 1, + 'camp_type' => 1, + 'camp_siteId' => 1, + ]); + + // Create a fake customer + $customer = Customers::factory()->create([ + 'hashcode' => 'hash123', + ]); + + // Create a coupon in the campaign + $coupon = Coupon::factory()->create(); + $campaign->coupons()->attach($coupon); + + // Create a basket + $basket = new Basket(); + $basket->uuid = (string) Str::uuid(); + $basket->campagne()->associate($campaign); + $basket->customer()->associate($customer); + $basket->save(); + + $response = $this->json('GET', $enpoint, [ + 'customer_hashcode' => 'hash123', + 'refcamp' => $campaign->camp_id, + 'refsite' => $campaign->camp_siteId, + 'panier' => sprintf("(%d)%s", 2, $coupon->coupon_code), + ]); + + $response->assertStatus(200) + ->assertJson([ + 'Statut' => 'OK', + ]); + + // Assert basket created for the customer and campaign + $this->assertDatabaseHas('baskets', [ + 'campagne_id' => $campaign->camp_id, + 'customer_id' => $customer->id, + ]); + + $this->assertDatabaseHas('basket_contents', [ + 'quantity' => 2, + 'printed' => 0, + 'basket_id' => $basket->id, + 'coupon_id' => $coupon->coupon_id + ]); + } +}