Clarify invalid-product errors and resolve order company from product records.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-15 08:04:09 +02:00
co-authored by Cursor
parent 507fc99065
commit 183476708d
2 changed files with 58 additions and 23 deletions
+8 -1
View File
@@ -113,9 +113,16 @@ export class CartsService {
if (!item) throw new NotFoundException('آیتم سبد یافت نشد');
await this.prisma.cartItem.delete({ where: { id: itemId } });
const remaining = await this.prisma.cartItem.findMany({
where: { cartId: cart.id },
take: 1,
});
await this.prisma.cart.update({
where: { id: cart.id },
data: { updatedAt: new Date() },
data: {
companyId: remaining[0]?.companyId ?? null,
updatedAt: new Date(),
},
});
return this.getCart(userId);
+50 -22
View File
@@ -135,31 +135,59 @@ export class OrdersService {
}
async submitOrder(userId: string, dto: SubmitOrderDto) {
const [company, settings] = await Promise.all([
this.prisma.company.findUnique({ where: { id: dto.companyId } }),
this.prisma.systemSettings.findUnique({
where: { id: 'default' },
select: { maxMeteragePerInvoice: true },
}),
]);
if (!company || !company.isActive) {
throw new NotFoundException('شرکت یافت نشد یا غیرفعال است');
}
const maxMeterage = resolveMaxMeterage(
company.maxMeteragePerInvoice,
settings?.maxMeteragePerInvoice,
);
const settings = await this.prisma.systemSettings.findUnique({
where: { id: 'default' },
select: { maxMeteragePerInvoice: true },
});
const productIds = dto.items.map((i) => i.productId);
const uniqueProductIds = [...new Set(productIds)];
if (uniqueProductIds.length !== productIds.length) {
throw new BadRequestException('محصول تکراری در سفارش مجاز نیست');
}
const products = await this.prisma.product.findMany({
where: { id: { in: productIds }, companyId: company.id, isActive: true },
where: { id: { in: uniqueProductIds } },
include: { catalog: true },
});
if (products.length !== productIds.length) {
throw new BadRequestException('یک یا چند محصول نامعتبر است');
}
const productMap = new Map(products.map((p) => [p.id, p]));
for (const item of dto.items) {
const product = productMap.get(item.productId);
if (!product) {
throw new BadRequestException(
'یک یا چند محصول نامعتبر است یا دیگر در سیستم وجود ندارد. سبد را خالی کنید و دوباره اضافه کنید.',
);
}
if (!product.isActive) {
throw new BadRequestException(
`محصول «${product.name}» غیرفعال است و قابل سفارش نیست`,
);
}
}
const productCompanyIds = [
...new Set(products.map((p) => p.companyId)),
];
if (productCompanyIds.length !== 1) {
throw new BadRequestException(
'اقلام سفارش باید همه از یک شرکت باشند',
);
}
// شرکت را از خود محصولات resolve کن تا companyId کهنه/ناسازگار سبد خطا ندهد
const orderCompany = await this.prisma.company.findUnique({
where: { id: productCompanyIds[0]! },
});
if (!orderCompany || !orderCompany.isActive) {
throw new NotFoundException('شرکت محصولات یافت نشد یا غیرفعال است');
}
const maxMeterageResolved = resolveMaxMeterage(
orderCompany.maxMeteragePerInvoice,
settings?.maxMeteragePerInvoice,
);
let totalMeterage = 0;
const itemsData = dto.items.map((item) => {
const product = productMap.get(item.productId)!;
@@ -187,9 +215,9 @@ export class OrdersService {
};
});
if (totalMeterage > maxMeterage) {
if (totalMeterage > maxMeterageResolved) {
throw new BadRequestException(
`حداکثر متراژ مجاز هر فاکتور ${maxMeterage} متر است`,
`حداکثر متراژ مجاز هر فاکتور ${maxMeterageResolved} متر است`,
);
}
@@ -200,8 +228,8 @@ export class OrdersService {
data: {
orderNumber,
userId,
companyId: company.id,
companyName: company.name,
companyId: orderCompany.id,
companyName: orderCompany.name,
settlementType: null,
checkMode: null,
status: OrderStatus.awaiting_review,