refactor(catalog): Complete catalog refactor to simplify its data model and its querying.
source commits: refactor/catalog
This commit is contained in:
@@ -1,68 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Catalog\Controllers;
|
||||
|
||||
use App\Domains\Catalog\Models\Attribute;
|
||||
use App\Domains\Catalog\Requests\StoreAttributeRequest;
|
||||
use App\Domains\Catalog\Requests\UpdateAttributeRequest;
|
||||
use App\Domains\Catalog\Resources\AttributeResource;
|
||||
use App\Domains\Catalog\Services\ProductService;
|
||||
use App\Domains\Shared\Enums\FieldType;
|
||||
use App\Domains\Tenant\Models\Tenant;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
class AttributeController extends Controller
|
||||
{
|
||||
public function index(Tenant $tenant): JsonResponse
|
||||
{
|
||||
$query = Attribute::query()
|
||||
->where('tenant_codigo', $tenant->codigo)
|
||||
->with('options')
|
||||
->latest();
|
||||
|
||||
return AttributeResource::collection($query->paginateFromRequest())->response();
|
||||
}
|
||||
|
||||
public function store(StoreAttributeRequest $request, Tenant $tenant): JsonResponse
|
||||
{
|
||||
$attribute = ProductService::createAttribute($tenant, $request->validated());
|
||||
|
||||
return AttributeResource::make($attribute)->response()->setStatusCode(201);
|
||||
}
|
||||
|
||||
public function show(Tenant $tenant, Attribute $attribute): AttributeResource
|
||||
{
|
||||
$attribute = $this->resolveScopedAttribute($tenant, $attribute);
|
||||
|
||||
return AttributeResource::make($attribute->load('options'));
|
||||
}
|
||||
|
||||
public function update(UpdateAttributeRequest $request, Tenant $tenant, Attribute $attribute): AttributeResource
|
||||
{
|
||||
$attribute = $this->resolveScopedAttribute($tenant, $attribute);
|
||||
$attribute = ProductService::updateAttribute($attribute, $request->validated());
|
||||
|
||||
return AttributeResource::make($attribute);
|
||||
}
|
||||
|
||||
public function destroy(Tenant $tenant, Attribute $attribute): Response
|
||||
{
|
||||
$attribute = $this->resolveScopedAttribute($tenant, $attribute);
|
||||
ProductService::deleteAttribute($attribute);
|
||||
|
||||
return response()->noContent();
|
||||
}
|
||||
|
||||
protected function resolveScopedAttribute(Tenant $tenant, Attribute $attribute): Attribute
|
||||
{
|
||||
if ($attribute->tenant_codigo !== $tenant->codigo) {
|
||||
throw new NotFoundHttpException('Attribute not found for tenant.');
|
||||
}
|
||||
|
||||
return $attribute;
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Catalog\Controllers;
|
||||
|
||||
use App\Domains\Catalog\Models\Brand;
|
||||
use App\Domains\Catalog\Requests\StoreBrandRequest;
|
||||
use App\Domains\Catalog\Requests\UpdateBrandRequest;
|
||||
use App\Domains\Catalog\Resources\BrandResource;
|
||||
use App\Domains\Tenant\Models\Tenant;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
class BrandController extends Controller
|
||||
{
|
||||
public function index(Tenant $tenant): JsonResponse
|
||||
{
|
||||
return BrandResource::collection(
|
||||
Brand::query()->where('tenant_codigo', $tenant->codigo)->orderByDesc('id')->paginateFromRequest()
|
||||
)->response();
|
||||
}
|
||||
|
||||
public function store(StoreBrandRequest $request, Tenant $tenant): JsonResponse
|
||||
{
|
||||
$brand = Brand::query()->create([
|
||||
...$request->validated(),
|
||||
'tenant_codigo' => $tenant->codigo,
|
||||
]);
|
||||
|
||||
return BrandResource::make($brand)->response()->setStatusCode(201);
|
||||
}
|
||||
|
||||
public function show(Tenant $tenant, Brand $marca): BrandResource
|
||||
{
|
||||
$marca = $this->resolveScopedBrand($tenant, $marca);
|
||||
|
||||
return BrandResource::make($marca);
|
||||
}
|
||||
|
||||
public function update(UpdateBrandRequest $request, Tenant $tenant, Brand $marca): BrandResource
|
||||
{
|
||||
$marca = $this->resolveScopedBrand($tenant, $marca);
|
||||
$marca->update($request->validated());
|
||||
|
||||
return BrandResource::make($marca);
|
||||
}
|
||||
|
||||
public function destroy(Tenant $tenant, Brand $marca): Response
|
||||
{
|
||||
$marca = $this->resolveScopedBrand($tenant, $marca);
|
||||
$marca->delete();
|
||||
|
||||
return response()->noContent();
|
||||
}
|
||||
|
||||
protected function resolveScopedBrand(Tenant $tenant, Brand $brand): Brand
|
||||
{
|
||||
if ($brand->tenant_codigo !== $tenant->codigo) {
|
||||
throw new NotFoundHttpException('Brand not found for tenant.');
|
||||
}
|
||||
|
||||
return $brand;
|
||||
}
|
||||
}
|
||||
@@ -2,31 +2,122 @@
|
||||
|
||||
namespace App\Domains\Catalog\Controllers;
|
||||
|
||||
use App\Domains\Bundle\Models\Bundle;
|
||||
use App\Domains\Catalog\Models\CatalogItem;
|
||||
use App\Domains\Catalog\Models\FeaturedGroup;
|
||||
use App\Domains\Catalog\Models\ProductVariant;
|
||||
use App\Domains\Catalog\Requests\CatalogItemDetailRequest;
|
||||
use App\Domains\Catalog\Requests\FeaturedGroupPageRequest;
|
||||
use App\Domains\Catalog\Requests\StoreCatalogItemRequest;
|
||||
use App\Domains\Catalog\Resources\CatalogFeaturedGroupResource;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphTo;
|
||||
use App\Domains\Catalog\Resources\CatalogFeaturedItemResource;
|
||||
use App\Domains\Catalog\Resources\CatalogItemDetailResource;
|
||||
use App\Domains\Catalog\Resources\CatalogItemResource;
|
||||
use App\Domains\Catalog\Services\CatalogService;
|
||||
use App\Domains\Tenant\Models\Tenant;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
|
||||
class CatalogController extends Controller
|
||||
{
|
||||
public function index(string $tenant): JsonResponse
|
||||
private const ITEMS_PER_PAGE = 12;
|
||||
|
||||
public function index(Tenant $tenant): JsonResponse
|
||||
{
|
||||
$featuredGroups = FeaturedGroup::where('tenant_codigo', $tenant)
|
||||
->with([
|
||||
'groupItems' => fn ($query) => $query->orderBy('order'),
|
||||
'groupItems.groupable' => function (MorphTo $morphTo): void {
|
||||
$morphTo->morphWith([
|
||||
ProductVariant::class => ['product', 'attachments', 'product.attachments'],
|
||||
Bundle::class => ['items.variant.product', 'items.variant.attachments', 'items.variant.product.attachments'],
|
||||
]);
|
||||
},
|
||||
])
|
||||
$featuredGroups = FeaturedGroup::query()
|
||||
->where('tenant_code', $tenant->codigo)
|
||||
->orderBy('group_order')
|
||||
->get();
|
||||
|
||||
return response()->json(CatalogFeaturedGroupResource::collection($featuredGroups)->resolve());
|
||||
return response()->json($featuredGroups->map(
|
||||
fn (FeaturedGroup $featuredGroup): array => (new CatalogFeaturedGroupResource(
|
||||
$featuredGroup,
|
||||
$this->featuredItemsResponse($featuredGroup, 1),
|
||||
))->resolve()
|
||||
));
|
||||
}
|
||||
|
||||
public function featuredGroupItems(
|
||||
FeaturedGroupPageRequest $request,
|
||||
Tenant $tenant,
|
||||
FeaturedGroup $featuredGroup,
|
||||
): JsonResponse {
|
||||
abort_unless($featuredGroup->tenant_code === $tenant->codigo, 404);
|
||||
|
||||
$page = (int) $request->validated('page', 1);
|
||||
|
||||
return response()->json($this->featuredItemsResponse($featuredGroup, $page));
|
||||
}
|
||||
|
||||
public function show(
|
||||
CatalogItemDetailRequest $request,
|
||||
Tenant $tenant,
|
||||
CatalogItem $catalogItem,
|
||||
CatalogService $catalogService,
|
||||
): CatalogItemDetailResource {
|
||||
abort_unless($catalogItem->tenant_code === $tenant->codigo, 404);
|
||||
|
||||
$variantId = $request->validated('variant_id');
|
||||
|
||||
return CatalogItemDetailResource::make(
|
||||
$catalogService->getDetail(
|
||||
$catalogItem,
|
||||
$variantId === null ? null : (int) $variantId,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function store(
|
||||
StoreCatalogItemRequest $request,
|
||||
Tenant $tenant,
|
||||
CatalogService $catalogService,
|
||||
): JsonResponse {
|
||||
$catalogItem = $catalogService->create([
|
||||
...$request->validated(),
|
||||
'tenant_code' => $tenant->codigo,
|
||||
]);
|
||||
|
||||
return CatalogItemResource::make($catalogItem)
|
||||
->response()
|
||||
->setStatusCode(201);
|
||||
}
|
||||
|
||||
/** @return array<string, mixed> */
|
||||
private function featuredItemsResponse(FeaturedGroup $featuredGroup, int $page): array
|
||||
{
|
||||
$paginator = $this->paginateFeaturedItems($featuredGroup, $page);
|
||||
|
||||
$paginator->getCollection()->each(
|
||||
fn ($featuredItem) => $featuredItem->setRelation('featuredGroup', $featuredGroup)
|
||||
);
|
||||
|
||||
return CatalogFeaturedItemResource::collection($paginator)
|
||||
->response()
|
||||
->getData(true);
|
||||
}
|
||||
|
||||
private function paginateFeaturedItems(
|
||||
FeaturedGroup $featuredGroup,
|
||||
int $page,
|
||||
): LengthAwarePaginator {
|
||||
$paginator = $featuredGroup->featuredItems()
|
||||
->with([
|
||||
'catalogItem.inventory',
|
||||
'catalogItem.attachments',
|
||||
'catalogItem.variants.inventory',
|
||||
'catalogItem.variants.attachments',
|
||||
'catalogItem.variants.definitions.itemAttribute.attribute',
|
||||
'catalogItem.bundleComponents.catalogItem',
|
||||
'catalogItem.bundleComponents.variant.catalogItem',
|
||||
])
|
||||
->paginate(
|
||||
perPage: self::ITEMS_PER_PAGE,
|
||||
pageName: 'page',
|
||||
page: $page,
|
||||
);
|
||||
|
||||
return $paginator->withPath(route('catalog.featured-groups.items.index', [
|
||||
'tenant' => $featuredGroup->tenant_code,
|
||||
'featuredGroup' => $featuredGroup->id,
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Catalog\Controllers;
|
||||
|
||||
use App\Domains\Catalog\Models\Category;
|
||||
use App\Domains\Catalog\Requests\StoreCategoryRequest;
|
||||
use App\Domains\Catalog\Requests\UpdateCategoryRequest;
|
||||
use App\Domains\Catalog\Resources\CategoryResource;
|
||||
use App\Domains\Tenant\Models\Tenant;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
class CategoryController extends Controller
|
||||
{
|
||||
public function index(Tenant $tenant): JsonResponse
|
||||
{
|
||||
return CategoryResource::collection(
|
||||
Category::query()
|
||||
->where(function ($query) use ($tenant): void {
|
||||
$query
|
||||
->where('tenant_code', $tenant->codigo)
|
||||
->orWhereNull('tenant_code');
|
||||
})
|
||||
->with(['parent', 'subCategories', 'tenant'])
|
||||
->orderByDesc('id')
|
||||
->get()
|
||||
)->response();
|
||||
}
|
||||
|
||||
public function store(StoreCategoryRequest $request, Tenant $tenant): JsonResponse
|
||||
{
|
||||
$category = Category::query()->create([
|
||||
...$request->validated(),
|
||||
'tenant_code' => $tenant->codigo,
|
||||
]);
|
||||
|
||||
return CategoryResource::make($category->load(['parent', 'subCategories', 'tenant']))
|
||||
->response()
|
||||
->setStatusCode(201);
|
||||
}
|
||||
|
||||
public function show(Tenant $tenant, Category $categoria): CategoryResource
|
||||
{
|
||||
$categoria = $this->resolveScopedCategory($tenant, $categoria);
|
||||
|
||||
return CategoryResource::make($categoria->load(['parent', 'subCategories', 'tenant']));
|
||||
}
|
||||
|
||||
public function update(UpdateCategoryRequest $request, Tenant $tenant, Category $categoria): CategoryResource
|
||||
{
|
||||
$categoria = $this->resolveScopedCategory($tenant, $categoria);
|
||||
$this->ensureCategoryIsMutable($categoria);
|
||||
$categoria->update($request->validated());
|
||||
|
||||
return CategoryResource::make($categoria->load(['parent', 'subCategories', 'tenant']));
|
||||
}
|
||||
|
||||
public function destroy(Tenant $tenant, Category $categoria): Response
|
||||
{
|
||||
$categoria = $this->resolveScopedCategory($tenant, $categoria);
|
||||
$this->ensureCategoryIsMutable($categoria);
|
||||
$categoria->delete();
|
||||
|
||||
return response()->noContent();
|
||||
}
|
||||
|
||||
protected function resolveScopedCategory(Tenant $tenant, Category $category): Category
|
||||
{
|
||||
if ($category->tenant_code !== null && $category->tenant_code !== $tenant->codigo) {
|
||||
throw new NotFoundHttpException('Category not found for tenant.');
|
||||
}
|
||||
|
||||
return $category;
|
||||
}
|
||||
|
||||
protected function ensureCategoryIsMutable(Category $category): void
|
||||
{
|
||||
if ($category->isGlobal()) {
|
||||
throw new AccessDeniedHttpException('Global categories are read-only.');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Catalog\Controllers;
|
||||
|
||||
use App\Domains\Catalog\Models\FeaturedGroup;
|
||||
use App\Domains\Catalog\Requests\StoreFeaturedGroupRequest;
|
||||
use App\Domains\Catalog\Requests\UpdateFeaturedGroupRequest;
|
||||
use App\Domains\Catalog\Resources\FeaturedGroupResource;
|
||||
use App\Domains\Catalog\Services\FeaturedGroupService;
|
||||
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
class FeaturedGroupController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
private readonly FeaturedGroupService $featuredGroupService
|
||||
) {}
|
||||
|
||||
public function index(string $tenant): AnonymousResourceCollection
|
||||
{
|
||||
$groups = FeaturedGroup::where('tenant_codigo', $tenant)->get();
|
||||
return FeaturedGroupResource::collection($groups);
|
||||
}
|
||||
|
||||
public function store(StoreFeaturedGroupRequest $request, string $tenant): FeaturedGroupResource
|
||||
{
|
||||
$group = $this->featuredGroupService->createGroup($tenant, $request->validated());
|
||||
return new FeaturedGroupResource($group);
|
||||
}
|
||||
|
||||
public function show(string $tenant, FeaturedGroup $featuredGroup): FeaturedGroupResource
|
||||
{
|
||||
abort_if($featuredGroup->tenant_codigo !== $tenant, 404);
|
||||
return new FeaturedGroupResource($featuredGroup->load('groupItems'));
|
||||
}
|
||||
|
||||
public function update(UpdateFeaturedGroupRequest $request, string $tenant, FeaturedGroup $featuredGroup): FeaturedGroupResource
|
||||
{
|
||||
abort_if($featuredGroup->tenant_codigo !== $tenant, 404);
|
||||
$group = $this->featuredGroupService->updateGroup($featuredGroup, $request->validated());
|
||||
return new FeaturedGroupResource($group);
|
||||
}
|
||||
|
||||
public function destroy(string $tenant, FeaturedGroup $featuredGroup): JsonResponse
|
||||
{
|
||||
abort_if($featuredGroup->tenant_codigo !== $tenant, 404);
|
||||
$this->featuredGroupService->deleteGroup($featuredGroup);
|
||||
return response()->json(null, 204);
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Catalog\Controllers;
|
||||
|
||||
use App\Domains\Bundle\Models\Bundle;
|
||||
use App\Domains\Catalog\Models\FeaturedGroup;
|
||||
use App\Domains\Catalog\Models\GroupItem;
|
||||
use App\Domains\Catalog\Models\ProductVariant;
|
||||
use App\Domains\Catalog\Requests\StoreGroupItemRequest;
|
||||
use App\Domains\Catalog\Requests\UpdateGroupItemRequest;
|
||||
use App\Domains\Catalog\Resources\GroupItemResource;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
|
||||
use Illuminate\Routing\Controller;
|
||||
|
||||
class GroupItemController extends Controller
|
||||
{
|
||||
public function index(string $tenant, FeaturedGroup $featuredGroup): AnonymousResourceCollection
|
||||
{
|
||||
abort_if($featuredGroup->tenant_codigo !== $tenant, 404);
|
||||
|
||||
return GroupItemResource::collection($featuredGroup->groupItems);
|
||||
}
|
||||
|
||||
public function store(StoreGroupItemRequest $request, string $tenant, FeaturedGroup $featuredGroup): GroupItemResource
|
||||
{
|
||||
abort_if($featuredGroup->tenant_codigo !== $tenant, 404);
|
||||
|
||||
$groupableType = $request->mappedGroupableType();
|
||||
$groupable = $groupableType::query()->findOrFail($request->integer('groupable_id'));
|
||||
|
||||
abort_if(
|
||||
($groupable instanceof ProductVariant && $groupable->product()->where('tenant_codigo', $tenant)->doesntExist())
|
||||
|| ($groupable instanceof Bundle && $groupable->tenant_codigo !== $tenant),
|
||||
404
|
||||
);
|
||||
|
||||
$groupItem = $featuredGroup->groupItems()->create([
|
||||
'groupable_type' => $groupableType,
|
||||
'groupable_id' => $groupable->getKey(),
|
||||
'order' => $request->validated('order'),
|
||||
]);
|
||||
|
||||
return new GroupItemResource($groupItem);
|
||||
}
|
||||
|
||||
public function update(UpdateGroupItemRequest $request, string $tenant, FeaturedGroup $featuredGroup, GroupItem $groupItem): GroupItemResource
|
||||
{
|
||||
abort_if($featuredGroup->tenant_codigo !== $tenant || $groupItem->featured_group_id !== $featuredGroup->id, 404);
|
||||
$groupItem->update($request->validated());
|
||||
|
||||
return new GroupItemResource($groupItem);
|
||||
}
|
||||
|
||||
public function destroy(string $tenant, FeaturedGroup $featuredGroup, GroupItem $groupItem): JsonResponse
|
||||
{
|
||||
abort_if($featuredGroup->tenant_codigo !== $tenant || $groupItem->featured_group_id !== $featuredGroup->id, 404);
|
||||
$groupItem->delete();
|
||||
|
||||
return response()->json(null, 204);
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Catalog\Controllers;
|
||||
|
||||
use App\Domains\Catalog\Models\Product;
|
||||
use App\Domains\Catalog\Requests\ProductDetailRequest;
|
||||
use App\Domains\Catalog\Requests\StoreProductRequest;
|
||||
use App\Domains\Catalog\Requests\UpdateProductRequest;
|
||||
use App\Domains\Catalog\Resources\ProductResource;
|
||||
use App\Domains\Catalog\Services\ProductService;
|
||||
use App\Domains\Tenant\Models\Tenant;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
class ProductController extends Controller
|
||||
{
|
||||
public function index(Tenant $tenant, ProductService $productService): JsonResponse
|
||||
{
|
||||
return ProductResource::collection(
|
||||
$productService->getProductos($tenant)
|
||||
)->response();
|
||||
}
|
||||
|
||||
public function store(StoreProductRequest $request, Tenant $tenant, ProductService $productService): JsonResponse
|
||||
{
|
||||
$product = $productService->create($tenant, $request->validated());
|
||||
|
||||
return ProductResource::make($product)->response()->setStatusCode(201);
|
||||
}
|
||||
|
||||
public function show(ProductDetailRequest $request, Tenant $tenant, Product $producto, ProductService $productService): ProductResource
|
||||
{
|
||||
$producto = $this->resolveScopedProduct($tenant, $producto);
|
||||
$variantId = $request->query('variant_id');
|
||||
$variantId = $variantId !== null ? (int) $variantId : null;
|
||||
$producto = $productService->getProductDetail($tenant, $producto, $variantId);
|
||||
|
||||
return ProductResource::make($producto);
|
||||
}
|
||||
|
||||
public function update(UpdateProductRequest $request, Tenant $tenant, Product $producto, ProductService $productService): ProductResource
|
||||
{
|
||||
$producto = $this->resolveScopedProduct($tenant, $producto);
|
||||
$producto = $productService->update($producto, $request->validated());
|
||||
|
||||
return ProductResource::make($producto);
|
||||
}
|
||||
|
||||
public function destroy(Tenant $tenant, Product $producto, ProductService $productService): Response
|
||||
{
|
||||
$producto = $this->resolveScopedProduct($tenant, $producto);
|
||||
$productService->delete($producto);
|
||||
|
||||
return response()->noContent();
|
||||
}
|
||||
|
||||
protected function resolveScopedProduct(Tenant $tenant, Product $product): Product
|
||||
{
|
||||
if ($product->tenant_codigo !== $tenant->codigo) {
|
||||
throw new NotFoundHttpException('Product not found.');
|
||||
}
|
||||
|
||||
return $product;
|
||||
}
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Catalog\Controllers;
|
||||
|
||||
use App\Domains\Catalog\Models\Product;
|
||||
use App\Domains\Catalog\Models\ProductVariant;
|
||||
use App\Domains\Catalog\Requests\StoreProductVariantRequest;
|
||||
use App\Domains\Catalog\Requests\UpdateProductVariantRequest;
|
||||
use App\Domains\Catalog\Resources\ProductVariantResource;
|
||||
use App\Domains\Catalog\Services\ProductService;
|
||||
use App\Domains\Tenant\Models\Tenant;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
class ProductVariantController extends Controller
|
||||
{
|
||||
public function index(Tenant $tenant, Product $producto): JsonResponse
|
||||
{
|
||||
|
||||
$query = ProductVariant::query()
|
||||
->where('producto_id', $producto->id)
|
||||
->with(['product', 'definitions.productAttribute.attribute.options', 'attachments'])
|
||||
->latest();
|
||||
|
||||
return ProductVariantResource::collection($query->paginateFromRequest())->response();
|
||||
}
|
||||
|
||||
public function store(StoreProductVariantRequest $request, Tenant $tenant, Product $producto, ProductService $productService): JsonResponse
|
||||
{
|
||||
$producto = $this->resolveScopedProduct($tenant, $producto);
|
||||
|
||||
$variant = $productService->createVariant($producto, $request->validated());
|
||||
|
||||
return ProductVariantResource::make($variant)->response()->setStatusCode(201);
|
||||
}
|
||||
|
||||
public function show(Tenant $tenant, Product $producto, ProductVariant $productVariant): ProductVariantResource
|
||||
{
|
||||
$producto = $this->resolveScopedProduct($tenant, $producto);
|
||||
$productVariant = $this->resolveScopedVariant($producto, $productVariant);
|
||||
|
||||
return ProductVariantResource::make($productVariant->load([
|
||||
'attachments' => fn ($query) => $query->orderBy('attachments.id'),
|
||||
'definitions.productAttribute.attribute.options',
|
||||
'product.attachments' => fn ($query) => $query->orderBy('attachments.id'),
|
||||
]));
|
||||
}
|
||||
|
||||
public function update(UpdateProductVariantRequest $request, Tenant $tenant, Product $producto, ProductVariant $productVariant, ProductService $productService): ProductVariantResource
|
||||
{
|
||||
$producto = $this->resolveScopedProduct($tenant, $producto);
|
||||
$productVariant = $this->resolveScopedVariant($producto, $productVariant);
|
||||
|
||||
$productVariant = $productService->updateVariant($productVariant, $request->validated());
|
||||
|
||||
return ProductVariantResource::make($productVariant);
|
||||
}
|
||||
|
||||
public function destroy(Tenant $tenant, Product $producto, ProductVariant $productVariant, ProductService $productService): Response
|
||||
{
|
||||
$producto = $this->resolveScopedProduct($tenant, $producto);
|
||||
$productVariant = $this->resolveScopedVariant($producto, $productVariant);
|
||||
$productService->deleteVariant($productVariant);
|
||||
|
||||
return response()->noContent();
|
||||
}
|
||||
|
||||
protected function resolveScopedProduct(Tenant $tenant, Product $product): Product
|
||||
{
|
||||
if ($product->tenant_codigo !== $tenant->codigo) {
|
||||
throw new NotFoundHttpException('Product not found for tenant.');
|
||||
}
|
||||
|
||||
return $product;
|
||||
}
|
||||
|
||||
protected function resolveScopedVariant(Product $product, ProductVariant $variant): ProductVariant
|
||||
{
|
||||
if ($variant->producto_id !== $product->id) {
|
||||
throw new NotFoundHttpException('Product variant not found for product.');
|
||||
}
|
||||
|
||||
return $variant;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user