build: include production build artifacts in repo
This commit is contained in:
+214
@@ -0,0 +1,214 @@
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
||||
return function (target, key) { decorator(target, key, paramIndex); }
|
||||
};
|
||||
import { Body, Controller, Delete, Get, HttpCode, Module, Param, Patch, Post, Put, Query, } from "@nestjs/common";
|
||||
import { categoryInputSchema, productInputSchema, productListQuerySchema, reorderSchema, } from "@imen/shared";
|
||||
import { z } from "zod";
|
||||
import { AdminAuth, CurrentUser, Roles } from "../common/auth.js";
|
||||
import { IdPipe, ZodPipe } from "../common/zod.pipe.js";
|
||||
import { MediaModule } from "../media/media.controller.js";
|
||||
import { CategoriesService } from "./categories.service.js";
|
||||
import { ProductsService } from "./products.service.js";
|
||||
const publishSchema = z.object({ isPublished: z.boolean() });
|
||||
let CategoriesController = class CategoriesController {
|
||||
categories;
|
||||
constructor(categories) {
|
||||
this.categories = categories;
|
||||
}
|
||||
list() {
|
||||
return this.categories.list();
|
||||
}
|
||||
get(id) {
|
||||
return this.categories.get(id);
|
||||
}
|
||||
create(body, user) {
|
||||
return this.categories.create(body, user.id);
|
||||
}
|
||||
async reorder(body, user) {
|
||||
await this.categories.reorder(body.ids, user.id);
|
||||
}
|
||||
update(id, body, user) {
|
||||
return this.categories.update(id, body, user.id);
|
||||
}
|
||||
async remove(id, user) {
|
||||
await this.categories.remove(id, user.id);
|
||||
}
|
||||
};
|
||||
__decorate([
|
||||
Get(),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", []),
|
||||
__metadata("design:returntype", void 0)
|
||||
], CategoriesController.prototype, "list", null);
|
||||
__decorate([
|
||||
Get(":id"),
|
||||
__param(0, Param("id", IdPipe)),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Number]),
|
||||
__metadata("design:returntype", void 0)
|
||||
], CategoriesController.prototype, "get", null);
|
||||
__decorate([
|
||||
Post(),
|
||||
__param(0, Body(new ZodPipe(categoryInputSchema))),
|
||||
__param(1, CurrentUser()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Object, Object]),
|
||||
__metadata("design:returntype", void 0)
|
||||
], CategoriesController.prototype, "create", null);
|
||||
__decorate([
|
||||
Post("reorder"),
|
||||
HttpCode(204),
|
||||
__param(0, Body(new ZodPipe(reorderSchema))),
|
||||
__param(1, CurrentUser()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Object, Object]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], CategoriesController.prototype, "reorder", null);
|
||||
__decorate([
|
||||
Put(":id"),
|
||||
__param(0, Param("id", IdPipe)),
|
||||
__param(1, Body(new ZodPipe(categoryInputSchema))),
|
||||
__param(2, CurrentUser()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Number, Object, Object]),
|
||||
__metadata("design:returntype", void 0)
|
||||
], CategoriesController.prototype, "update", null);
|
||||
__decorate([
|
||||
Roles("ADMIN"),
|
||||
Delete(":id"),
|
||||
HttpCode(204),
|
||||
__param(0, Param("id", IdPipe)),
|
||||
__param(1, CurrentUser()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Number, Object]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], CategoriesController.prototype, "remove", null);
|
||||
CategoriesController = __decorate([
|
||||
AdminAuth(),
|
||||
Controller("admin/categories"),
|
||||
__metadata("design:paramtypes", [CategoriesService])
|
||||
], CategoriesController);
|
||||
export { CategoriesController };
|
||||
let ProductsController = class ProductsController {
|
||||
products;
|
||||
constructor(products) {
|
||||
this.products = products;
|
||||
}
|
||||
list(q) {
|
||||
return this.products.list(q);
|
||||
}
|
||||
get(id) {
|
||||
return this.products.get(id);
|
||||
}
|
||||
create(body, user) {
|
||||
return this.products.create(body, user.id);
|
||||
}
|
||||
async reorder(body, user) {
|
||||
await this.products.reorder(body.ids, user.id);
|
||||
}
|
||||
duplicate(id, user) {
|
||||
return this.products.duplicate(id, user.id);
|
||||
}
|
||||
publish(id, body, user) {
|
||||
return this.products.setPublished(id, body.isPublished, user.id);
|
||||
}
|
||||
update(id, body, user) {
|
||||
return this.products.update(id, body, user.id);
|
||||
}
|
||||
async remove(id, user) {
|
||||
await this.products.remove(id, user.id);
|
||||
}
|
||||
};
|
||||
__decorate([
|
||||
Get(),
|
||||
__param(0, Query(new ZodPipe(productListQuerySchema))),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Object]),
|
||||
__metadata("design:returntype", void 0)
|
||||
], ProductsController.prototype, "list", null);
|
||||
__decorate([
|
||||
Get(":id"),
|
||||
__param(0, Param("id", IdPipe)),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Number]),
|
||||
__metadata("design:returntype", void 0)
|
||||
], ProductsController.prototype, "get", null);
|
||||
__decorate([
|
||||
Post(),
|
||||
__param(0, Body(new ZodPipe(productInputSchema))),
|
||||
__param(1, CurrentUser()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Object, Object]),
|
||||
__metadata("design:returntype", void 0)
|
||||
], ProductsController.prototype, "create", null);
|
||||
__decorate([
|
||||
Post("reorder"),
|
||||
HttpCode(204),
|
||||
__param(0, Body(new ZodPipe(reorderSchema))),
|
||||
__param(1, CurrentUser()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Object, Object]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], ProductsController.prototype, "reorder", null);
|
||||
__decorate([
|
||||
Post(":id/duplicate"),
|
||||
__param(0, Param("id", IdPipe)),
|
||||
__param(1, CurrentUser()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Number, Object]),
|
||||
__metadata("design:returntype", void 0)
|
||||
], ProductsController.prototype, "duplicate", null);
|
||||
__decorate([
|
||||
Patch(":id/publish"),
|
||||
__param(0, Param("id", IdPipe)),
|
||||
__param(1, Body(new ZodPipe(publishSchema))),
|
||||
__param(2, CurrentUser()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Number, Object, Object]),
|
||||
__metadata("design:returntype", void 0)
|
||||
], ProductsController.prototype, "publish", null);
|
||||
__decorate([
|
||||
Put(":id"),
|
||||
__param(0, Param("id", IdPipe)),
|
||||
__param(1, Body(new ZodPipe(productInputSchema))),
|
||||
__param(2, CurrentUser()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Number, Object, Object]),
|
||||
__metadata("design:returntype", void 0)
|
||||
], ProductsController.prototype, "update", null);
|
||||
__decorate([
|
||||
Roles("ADMIN"),
|
||||
Delete(":id"),
|
||||
HttpCode(204),
|
||||
__param(0, Param("id", IdPipe)),
|
||||
__param(1, CurrentUser()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Number, Object]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], ProductsController.prototype, "remove", null);
|
||||
ProductsController = __decorate([
|
||||
AdminAuth(),
|
||||
Controller("admin/products"),
|
||||
__metadata("design:paramtypes", [ProductsService])
|
||||
], ProductsController);
|
||||
export { ProductsController };
|
||||
let CatalogModule = class CatalogModule {
|
||||
};
|
||||
CatalogModule = __decorate([
|
||||
Module({
|
||||
imports: [MediaModule],
|
||||
controllers: [CategoriesController, ProductsController],
|
||||
providers: [CategoriesService, ProductsService],
|
||||
})
|
||||
], CatalogModule);
|
||||
export { CatalogModule };
|
||||
//# sourceMappingURL=catalog.module.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"catalog.module.js","sourceRoot":"","sources":["../../src/catalog/catalog.module.ts"],"names":[],"mappings":"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"}
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
import { ConflictException, Injectable } from "@nestjs/common";
|
||||
import { AuditService, RevalidateService } from "../common/common.module.js";
|
||||
import { MediaService } from "../media/media.service.js";
|
||||
import { PrismaService } from "../prisma/prisma.service.js";
|
||||
const withCover = { coverImage: true };
|
||||
let CategoriesService = class CategoriesService {
|
||||
prisma;
|
||||
media;
|
||||
audit;
|
||||
revalidate;
|
||||
constructor(prisma, media, audit, revalidate) {
|
||||
this.prisma = prisma;
|
||||
this.media = media;
|
||||
this.audit = audit;
|
||||
this.revalidate = revalidate;
|
||||
}
|
||||
async list() {
|
||||
const rows = await this.prisma.category.findMany({
|
||||
orderBy: [{ sortOrder: "asc" }, { id: "asc" }],
|
||||
include: { ...withCover, _count: { select: { products: true, groups: true } } },
|
||||
});
|
||||
return rows.map(({ coverImage, _count, ...c }) => ({
|
||||
...c,
|
||||
coverImage: coverImage && this.media.toDto(coverImage),
|
||||
productCount: _count.products,
|
||||
groupCount: _count.groups,
|
||||
}));
|
||||
}
|
||||
async get(id) {
|
||||
const { coverImage, ...c } = await this.prisma.category.findUniqueOrThrow({
|
||||
where: { id },
|
||||
include: {
|
||||
...withCover,
|
||||
groups: {
|
||||
orderBy: { sortOrder: "asc" },
|
||||
include: { _count: { select: { products: true } } },
|
||||
},
|
||||
},
|
||||
});
|
||||
return {
|
||||
...c,
|
||||
coverImage: coverImage && this.media.toDto(coverImage),
|
||||
groups: c.groups.map(({ _count, ...g }) => ({ ...g, productCount: _count.products })),
|
||||
};
|
||||
}
|
||||
async create(input, userId) {
|
||||
this.assertUniqueGroupSlugs(input);
|
||||
const { groups, ...data } = input;
|
||||
const last = await this.prisma.category.aggregate({ _max: { sortOrder: true } });
|
||||
const category = await this.prisma.category.create({
|
||||
data: {
|
||||
...data,
|
||||
sortOrder: (last._max.sortOrder ?? -1) + 1,
|
||||
groups: {
|
||||
create: groups.map((g, i) => ({ slug: g.slug, name: g.name, desc: g.desc, sortOrder: i })),
|
||||
},
|
||||
},
|
||||
});
|
||||
this.audit.log(userId, "create", "category", category.id, category.name);
|
||||
this.revalidate.trigger();
|
||||
return this.get(category.id);
|
||||
}
|
||||
async update(id, input, userId) {
|
||||
this.assertUniqueGroupSlugs(input);
|
||||
const { groups, ...data } = input;
|
||||
await this.prisma.$transaction(async (tx) => {
|
||||
const category = await tx.category.update({ where: { id }, data });
|
||||
const keepIds = groups.flatMap((g) => (g.id ? [g.id] : []));
|
||||
await tx.productGroup.deleteMany({ where: { categoryId: id, id: { notIn: keepIds } } });
|
||||
for (const g of groups) {
|
||||
if (g.id) {
|
||||
await tx.productGroup.update({
|
||||
where: { id: g.id, categoryId: id },
|
||||
data: { slug: `__tmp-${g.id}` },
|
||||
});
|
||||
}
|
||||
}
|
||||
for (const [i, g] of groups.entries()) {
|
||||
const fields = { slug: g.slug, name: g.name, desc: g.desc, sortOrder: i };
|
||||
if (g.id) {
|
||||
await tx.productGroup.update({ where: { id: g.id, categoryId: id }, data: fields });
|
||||
}
|
||||
else {
|
||||
await tx.productGroup.create({ data: { ...fields, categoryId: id } });
|
||||
}
|
||||
}
|
||||
this.audit.log(userId, "update", "category", id, category.name);
|
||||
});
|
||||
this.revalidate.trigger();
|
||||
return this.get(id);
|
||||
}
|
||||
async remove(id, userId) {
|
||||
const category = await this.prisma.category.findUniqueOrThrow({
|
||||
where: { id },
|
||||
include: { _count: { select: { products: true } } },
|
||||
});
|
||||
if (category._count.products > 0) {
|
||||
throw new ConflictException(`این دسته ${category._count.products} محصول دارد؛ ابتدا محصولات را حذف یا جابهجا کنید`);
|
||||
}
|
||||
await this.prisma.category.delete({ where: { id } });
|
||||
this.audit.log(userId, "delete", "category", id, category.name);
|
||||
this.revalidate.trigger();
|
||||
}
|
||||
async reorder(ids, userId) {
|
||||
await this.prisma.$transaction(ids.map((id, i) => this.prisma.category.update({ where: { id }, data: { sortOrder: i } })));
|
||||
this.audit.log(userId, "reorder", "category", "", `${ids.length} دسته`);
|
||||
this.revalidate.trigger();
|
||||
}
|
||||
assertUniqueGroupSlugs(input) {
|
||||
const slugs = input.groups.map((g) => g.slug);
|
||||
if (new Set(slugs).size !== slugs.length) {
|
||||
throw new ConflictException("اسلاگ زیرگروهها باید یکتا باشد");
|
||||
}
|
||||
}
|
||||
};
|
||||
CategoriesService = __decorate([
|
||||
Injectable(),
|
||||
__metadata("design:paramtypes", [PrismaService,
|
||||
MediaService,
|
||||
AuditService,
|
||||
RevalidateService])
|
||||
], CategoriesService);
|
||||
export { CategoriesService };
|
||||
//# sourceMappingURL=categories.service.js.map
|
||||
File diff suppressed because one or more lines are too long
+182
@@ -0,0 +1,182 @@
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
import { BadRequestException, Injectable } from "@nestjs/common";
|
||||
import { AuditService, RevalidateService } from "../common/common.module.js";
|
||||
import { MediaService } from "../media/media.service.js";
|
||||
import { PrismaService } from "../prisma/prisma.service.js";
|
||||
let ProductsService = class ProductsService {
|
||||
prisma;
|
||||
media;
|
||||
audit;
|
||||
revalidate;
|
||||
constructor(prisma, media, audit, revalidate) {
|
||||
this.prisma = prisma;
|
||||
this.media = media;
|
||||
this.audit = audit;
|
||||
this.revalidate = revalidate;
|
||||
}
|
||||
async list(q) {
|
||||
const where = {
|
||||
...(q.categoryId && { categoryId: q.categoryId }),
|
||||
...(q.groupId && { groupId: q.groupId }),
|
||||
...(q.status && { isPublished: q.status === "published" }),
|
||||
...(q.q && {
|
||||
OR: [
|
||||
{ name: { contains: q.q, mode: "insensitive" } },
|
||||
{ nameEn: { contains: q.q, mode: "insensitive" } },
|
||||
{ code: { contains: q.q, mode: "insensitive" } },
|
||||
],
|
||||
}),
|
||||
};
|
||||
const [rows, total] = await this.prisma.$transaction([
|
||||
this.prisma.product.findMany({
|
||||
where,
|
||||
orderBy: [{ category: { sortOrder: "asc" } }, { sortOrder: "asc" }, { id: "asc" }],
|
||||
skip: (q.page - 1) * q.pageSize,
|
||||
take: q.pageSize,
|
||||
include: {
|
||||
image: true,
|
||||
category: { select: { id: true, name: true } },
|
||||
group: { select: { id: true, name: true } },
|
||||
},
|
||||
}),
|
||||
this.prisma.product.count({ where }),
|
||||
]);
|
||||
return {
|
||||
items: rows.map(({ image, ...p }) => ({ ...p, image: image && this.media.toDto(image) })),
|
||||
total,
|
||||
page: q.page,
|
||||
pageSize: q.pageSize,
|
||||
};
|
||||
}
|
||||
async get(id) {
|
||||
const { image, gallery, ...p } = await this.prisma.product.findUniqueOrThrow({
|
||||
where: { id },
|
||||
include: { image: true, gallery: { orderBy: { sortOrder: "asc" }, include: { media: true } } },
|
||||
});
|
||||
return {
|
||||
...p,
|
||||
image: image && this.media.toDto(image),
|
||||
gallery: gallery.map((g) => this.media.toDto(g.media)),
|
||||
};
|
||||
}
|
||||
async create(input, userId) {
|
||||
await this.assertGroup(input);
|
||||
const { galleryIds, ...data } = input;
|
||||
const last = await this.prisma.product.aggregate({
|
||||
where: { categoryId: input.categoryId },
|
||||
_max: { sortOrder: true },
|
||||
});
|
||||
const product = await this.prisma.product.create({
|
||||
data: {
|
||||
...data,
|
||||
sortOrder: (last._max.sortOrder ?? -1) + 1,
|
||||
gallery: { create: unique(galleryIds).map((mediaId, i) => ({ mediaId, sortOrder: i })) },
|
||||
},
|
||||
});
|
||||
this.audit.log(userId, "create", "product", product.id, product.name);
|
||||
this.revalidate.trigger();
|
||||
return this.get(product.id);
|
||||
}
|
||||
async update(id, input, userId) {
|
||||
await this.assertGroup(input);
|
||||
const { galleryIds, ...data } = input;
|
||||
const product = await this.prisma.product.update({
|
||||
where: { id },
|
||||
data: {
|
||||
...data,
|
||||
gallery: {
|
||||
deleteMany: {},
|
||||
create: unique(galleryIds).map((mediaId, i) => ({ mediaId, sortOrder: i })),
|
||||
},
|
||||
},
|
||||
});
|
||||
this.audit.log(userId, "update", "product", id, product.name);
|
||||
this.revalidate.trigger();
|
||||
return this.get(id);
|
||||
}
|
||||
async setPublished(id, isPublished, userId) {
|
||||
const product = await this.prisma.product.update({ where: { id }, data: { isPublished } });
|
||||
this.audit.log(userId, isPublished ? "publish" : "unpublish", "product", id, product.name);
|
||||
this.revalidate.trigger();
|
||||
return { id, isPublished };
|
||||
}
|
||||
async duplicate(id, userId) {
|
||||
const src = await this.prisma.product.findUniqueOrThrow({
|
||||
where: { id },
|
||||
include: { gallery: true },
|
||||
});
|
||||
let n = 1;
|
||||
const taken = async (code, slug) => (await this.prisma.product.count({ where: { OR: [{ code }, { slug }] } })) > 0;
|
||||
while (await taken(`${src.code}-${n}`, `${src.slug}-copy-${n}`))
|
||||
n++;
|
||||
const copy = await this.prisma.product.create({
|
||||
data: {
|
||||
categoryId: src.categoryId,
|
||||
groupId: src.groupId,
|
||||
code: `${src.code}-${n}`,
|
||||
slug: `${src.slug}-copy-${n}`,
|
||||
name: `${src.name} (کپی)`,
|
||||
nameEn: src.nameEn,
|
||||
desc: src.desc,
|
||||
specs: src.specs,
|
||||
variants: src.variants,
|
||||
details: src.details,
|
||||
brand: src.brand,
|
||||
origin: src.origin,
|
||||
sizes: src.sizes,
|
||||
standards: src.standards,
|
||||
features: src.features,
|
||||
applications: src.applications,
|
||||
attributes: (src.attributes ?? []),
|
||||
packaging: src.packaging,
|
||||
minOrder: src.minOrder,
|
||||
seoTitle: src.seoTitle,
|
||||
seoDescription: src.seoDescription,
|
||||
imageId: src.imageId,
|
||||
sortOrder: src.sortOrder + 1,
|
||||
isPublished: false,
|
||||
gallery: {
|
||||
create: src.gallery.map((g) => ({ mediaId: g.mediaId, sortOrder: g.sortOrder })),
|
||||
},
|
||||
},
|
||||
});
|
||||
this.audit.log(userId, "duplicate", "product", copy.id, copy.name);
|
||||
return this.get(copy.id);
|
||||
}
|
||||
async remove(id, userId) {
|
||||
const product = await this.prisma.product.delete({ where: { id } });
|
||||
this.audit.log(userId, "delete", "product", id, product.name);
|
||||
this.revalidate.trigger();
|
||||
}
|
||||
async reorder(ids, userId) {
|
||||
await this.prisma.$transaction(ids.map((id, i) => this.prisma.product.update({ where: { id }, data: { sortOrder: i } })));
|
||||
this.audit.log(userId, "reorder", "product", "", `${ids.length} محصول`);
|
||||
this.revalidate.trigger();
|
||||
}
|
||||
async assertGroup(input) {
|
||||
if (!input.groupId)
|
||||
return;
|
||||
const group = await this.prisma.productGroup.findUnique({ where: { id: input.groupId } });
|
||||
if (group?.categoryId !== input.categoryId) {
|
||||
throw new BadRequestException("زیرگروه انتخابشده متعلق به این دسته نیست");
|
||||
}
|
||||
}
|
||||
};
|
||||
ProductsService = __decorate([
|
||||
Injectable(),
|
||||
__metadata("design:paramtypes", [PrismaService,
|
||||
MediaService,
|
||||
AuditService,
|
||||
RevalidateService])
|
||||
], ProductsService);
|
||||
export { ProductsService };
|
||||
const unique = (ids) => [...new Set(ids)];
|
||||
//# sourceMappingURL=products.service.js.map
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user