Skip to content

Commit 399fcaa

Browse files
authored
Feat: Add product variant reviews relation to productrs (#72)
* fix reviews * add images relation to reviews * remove redundant relationship definition (already in Lunar Product model) * update product policy * add and test product variant reviews relation to products --------- Co-authored-by: Jakub Theimer <5587309+theimerj@users.noreply.github.com>
1 parent 014926d commit 399fcaa

File tree

8 files changed

+74
-45
lines changed

8 files changed

+74
-45
lines changed

packages/api/src/Domain/Products/Concerns/HasRelationships.php

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -51,25 +51,6 @@ public function attributes(): MorphToMany
5151
return $relation->withTimestamps();
5252
}
5353

54-
/**
55-
* Get prices through variants.
56-
*/
57-
public function prices(): HasManyThrough
58-
{
59-
/** @var Product $this */
60-
return $this
61-
->hasManyThrough(
62-
Price::modelClass(),
63-
ProductVariant::modelClass(),
64-
'product_id',
65-
'priceable_id'
66-
)
67-
->where(
68-
'priceable_type',
69-
(new (ProductVariant::modelClass()))->getMorphClass()
70-
);
71-
}
72-
7354
/**
7455
* Get base prices through variants.
7556
*/

packages/api/src/Domain/Products/Policies/ProductPolicy.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,4 +141,9 @@ public function viewReviews(?Authenticatable $user, ProductContract $product): b
141141
{
142142
return true;
143143
}
144+
145+
public function viewProductVariantReviews(?Authenticatable $user, ProductContract $product): bool
146+
{
147+
return true;
148+
}
144149
}

packages/reviews/src/Domain/Reviews/Http/Routing/ReviewRouteGroup.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ public function routes(): void
4242
->resource(ProductSchema::type(), ProductsController::class)
4343
->relationships(function (Relationships $relationships) {
4444
$relationships->hasMany('reviews')->readOnly();
45+
$relationships->hasMany('product_variant_reviews')->readOnly();
4546
})->only();
4647

4748
$server

packages/reviews/src/Domain/Reviews/Policies/ReviewPolicy.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,9 @@ public function unpublish(?Authenticatable $user, Review $review): bool
6565
{
6666
return true;
6767
}
68+
69+
public function viewImages(?Authenticatable $user, Review $review): bool
70+
{
71+
return true;
72+
}
6873
}

packages/reviews/src/ReviewsServiceProvider.php

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use Dystore\Api\Domain\ProductVariants\JsonApi\V1\ProductVariantResource;
1313
use Dystore\Api\Domain\ProductVariants\JsonApi\V1\ProductVariantSchema;
1414
use Dystore\Api\Support\Config\Collections\DomainConfigCollection;
15+
use Dystore\Api\Support\Models\Actions\SchemaType;
1516
use Dystore\Reviews\Domain\Reviews\JsonApi\V1\ReviewSchema;
1617
use Dystore\Reviews\Domain\Reviews\Models\Review;
1718
use Illuminate\Database\Eloquent\Relations\Relation;
@@ -20,6 +21,7 @@
2021
use Illuminate\Support\ServiceProvider;
2122
use LaravelJsonApi\Eloquent\Fields\Number;
2223
use LaravelJsonApi\Eloquent\Fields\Relations\HasMany;
24+
use LaravelJsonApi\Eloquent\Fields\Relations\HasManyThrough;
2325
use Lunar\Facades\ModelManifest;
2426
use Lunar\Models\Product;
2527
use Lunar\Models\ProductVariant;
@@ -158,6 +160,17 @@ protected function registerDynamicRelations(): void
158160
return $model->morphMany(Review::class, 'purchasable');
159161
});
160162

163+
Product::resolveRelationUsing('productVariantReviews', function (Product $model) {
164+
return $model
165+
->hasManyThrough(
166+
Review::modelClass(),
167+
ProductVariant::modelClass(),
168+
'product_id',
169+
'purchasable_id'
170+
)
171+
->where('purchasable_type', 'product_variant');
172+
});
173+
161174
ProductVariant::resolveRelationUsing('reviews', function (ProductVariant $model) {
162175
return $model->morphMany(Review::class, 'purchasable');
163176
});
@@ -178,35 +191,43 @@ protected function extendSchemas(): void
178191
$productSchemaExtenstion = $schemaManifest::extend(ProductSchema::class);
179192

180193
$productSchemaExtenstion
181-
->setWith([
182-
'reviews',
183-
])
184194
->setIncludePaths([
185195
'reviews',
186196
'reviews.user',
187197
'reviews.user.customers',
188198
'variants.reviews',
189199
'variants.reviews.user',
190200
'variants.reviews.user.customers',
201+
'product_variant_reviews',
202+
'product_variant_reviews.user',
203+
'product_variant_reviews.user.customers',
191204
])
192205
->setFields([
193206
fn () => Number::make('rating', 'review_rating'),
194207
fn () => Number::make('review_count')
195208
->extractUsing(
196209
static fn ($model) => $model->relationLoaded('reviews')
197210
? $model->reviews->count()
198-
: $model->reviews()->count(),
211+
: null,
199212
),
200213
fn () => HasMany::make('reviews', 'reviews')
201214
->serializeUsing(
202215
static fn ($relation) => $relation->withoutLinks(),
203216
),
217+
fn () => HasManyThrough::make('product_variant_reviews', 'productVariantReviews')
218+
->type(SchemaType::get(Review::class))
219+
->retainFieldName()
220+
->serializeUsing(
221+
static fn ($relation) => $relation->withoutLinks(),
222+
),
204223
])
205224
->setShowRelated([
206225
'reviews',
226+
'product_variant_reviews',
207227
])
208228
->setShowRelationship([
209229
'reviews',
230+
'product_variant_reviews',
210231
]);
211232

212233
/** @var ResourceExtension $productResourceExtension */
Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
<?php
22

3+
use Carbon\Carbon;
34
use Dystore\Api\Base\Enums\PublishedStatus;
45
use Dystore\Api\Domain\Products\Models\Product;
56
use Dystore\Api\Domain\ProductVariants\Models\ProductVariant;
67
use Dystore\Reviews\Domain\Reviews\Models\Review;
7-
use Dystore\Tests\Reviews\Stubs\Users\User;
88
use Dystore\Tests\Reviews\TestCase;
99
use Illuminate\Foundation\Testing\RefreshDatabase;
1010

@@ -13,42 +13,62 @@
1313

1414
it('can list product reviews', function () {
1515
/** @var TestCase $this */
16-
$user = User::factory()->create();
17-
1816
$review = Review::factory()
1917
->for(Product::factory(), 'purchasable')
2018
->state([
2119
'status' => PublishedStatus::PUBLISHED,
22-
'published_at' => now(),
20+
'published_at' => Carbon::now(),
2321
])
2422
->create();
2523

2624
$response = $this
27-
->actingAs($user)
2825
->jsonApi()
2926
->expects('reviews')
3027
->get(serverUrl("/products/{$review->purchasable->getRouteKey()}/reviews"));
3128

32-
$response->assertFetchedMany([$review]);
29+
$response
30+
->assertSuccessful()
31+
->assertFetchedMany([$review]);
3332
});
3433

35-
it('can list product variant reviews', function () {
34+
it('can list product variant reviews through a product', function () {
3635
/** @var TestCase $this */
37-
$user = User::factory()->create();
36+
$reviews = Review::factory()
37+
->for(ProductVariant::factory(), 'purchasable')
38+
->count(5)
39+
->create([
40+
'status' => PublishedStatus::PUBLISHED,
41+
'published_at' => Carbon::now(),
42+
]);
3843

44+
$product = $reviews->first()->purchasable->product;
45+
46+
$response = $this
47+
->jsonApi()
48+
->expects('reviews')
49+
->get(serverUrl("/products/{$product->getRouteKey()}/product_variant_reviews"));
50+
51+
$response
52+
->assertSuccessful()
53+
->assertFetchedMany($reviews);
54+
});
55+
56+
it('can list product variant reviews', function () {
57+
/** @var TestCase $this */
3958
$review = Review::factory()
4059
->for(ProductVariant::factory(), 'purchasable')
4160
->state([
4261
'status' => PublishedStatus::PUBLISHED,
43-
'published_at' => now(),
62+
'published_at' => Carbon::now(),
4463
])
4564
->create();
4665

4766
$response = $this
48-
->actingAs($user)
4967
->jsonApi()
5068
->expects('reviews')
5169
->get(serverUrl("/product_variants/{$review->purchasable->getRouteKey()}/reviews"));
5270

53-
$response->assertFetchedMany([$review]);
71+
$response
72+
->assertSuccessful()
73+
->assertFetchedMany([$review]);
5474
});

tests/reviews/TestCase.php

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
namespace Dystore\Tests\Reviews;
44

5-
use Dystore\Reviews\Domain\Reviews\Models\Review;
65
use Dystore\Tests\Reviews\Stubs\Lunar\TestUrlGenerator;
76
use Illuminate\Contracts\Config\Repository;
87
use Illuminate\Contracts\Debug\ExceptionHandler;
@@ -11,8 +10,6 @@
1110
use Illuminate\Support\Facades\Config;
1211
use LaravelJsonApi\Testing\MakesJsonApiRequests;
1312
use LaravelJsonApi\Testing\TestExceptionHandler;
14-
use Lunar\Models\Product;
15-
use Lunar\Models\ProductVariant;
1613
use Orchestra\Testbench\Concerns\WithWorkbench;
1714
use Orchestra\Testbench\TestCase as Orchestra;
1815

@@ -93,14 +90,6 @@ protected function defineEnvironment($app): void
9390
'prefix' => '',
9491
]);
9592
});
96-
97-
ProductVariant::resolveRelationUsing('reviews', function ($model) {
98-
return $model->morphMany(Review::class, 'purchasable');
99-
});
100-
101-
Product::resolveRelationUsing('reviews', function ($model) {
102-
return $model->morphMany(Review::class, 'purchasable');
103-
});
10493
}
10594

10695
/**

tests/reviews/Unit/RegistersDynamicRelastionsTest.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use Dystore\Api\Domain\Products\Models\Product;
44
use Dystore\Api\Domain\ProductVariants\Models\ProductVariant;
55
use Dystore\Tests\Reviews\TestCase;
6+
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
67
use Illuminate\Database\Eloquent\Relations\MorphMany;
78
use Illuminate\Foundation\Testing\RefreshDatabase;
89

@@ -14,6 +15,12 @@
1415
expect($model->reviews())->toBeInstanceOf(MorphMany::class);
1516
});
1617

18+
test('product has productVariantReviews relation', function () {
19+
$model = new Product;
20+
21+
expect($model->productVariantReviews())->toBeInstanceOf(HasManyThrough::class);
22+
});
23+
1724
test('product variant has reviews relation', function () {
1825
$model = new ProductVariant;
1926

0 commit comments

Comments
 (0)