2026-09-09 06:46:27 +03:30
|
|
|
import { Injectable, NotFoundException } from '@nestjs/common';
|
|
|
|
|
import { PrismaService } from '../../prisma/prisma.service';
|
|
|
|
|
|
|
|
|
|
@Injectable()
|
|
|
|
|
export class CatalogService {
|
|
|
|
|
constructor(private readonly prisma: PrismaService) {}
|
|
|
|
|
|
|
|
|
|
listProducts() {
|
|
|
|
|
return this.prisma.product.findMany({
|
|
|
|
|
where: { isActive: true },
|
|
|
|
|
include: {
|
2026-09-21 08:32:31 +03:30
|
|
|
// Only orderable variants reach the storefront. An inactive one used to
|
|
|
|
|
// be listed and then rejected by getVariantOrThrow at checkout, so the
|
|
|
|
|
// customer could pick a chip and get a 404 on the order.
|
|
|
|
|
variants: {
|
|
|
|
|
where: { isActive: true },
|
|
|
|
|
// Each variant carries its own gallery picture, so the app can render
|
|
|
|
|
// the chip without a second request per variant.
|
|
|
|
|
include: { image: true },
|
|
|
|
|
},
|
|
|
|
|
// Explicit order: the UI treats images[0] as the product's main photo,
|
|
|
|
|
// which is only meaningful if the rows come back sorted.
|
|
|
|
|
images: { orderBy: { sortOrder: 'asc' } },
|
2026-09-09 06:46:27 +03:30
|
|
|
category: true,
|
|
|
|
|
brand: true,
|
|
|
|
|
collections: { include: { collection: true } },
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async getVariantOrThrow(variantId: string) {
|
|
|
|
|
const variant = await this.prisma.productVariant.findUnique({ where: { id: variantId } });
|
|
|
|
|
if (!variant || !variant.isActive) {
|
|
|
|
|
throw new NotFoundException(`Product variant ${variantId} not found or inactive`);
|
|
|
|
|
}
|
|
|
|
|
return variant;
|
|
|
|
|
}
|
|
|
|
|
}
|