Fix e-payment settings payload, cart race, and media/content helpers.

Stop returning passwordSet (forbidNonWhitelisted), upsert carts safely, and harden related media/product/workshop flows.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Alireza Hassani
2026-08-25 16:41:00 +03:30
co-authored by Cursor
parent ad6f9dcf1d
commit 20cc0bbd78
12 changed files with 220 additions and 42 deletions
+54 -1
View File
@@ -5,7 +5,7 @@ import {
NotFoundException,
} from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { MediaType } from '@prisma/client';
import { MediaEntityType, MediaType } from '@prisma/client';
import { randomUUID } from 'crypto';
import * as path from 'path';
import sharp from 'sharp';
@@ -209,6 +209,7 @@ export class MediaService {
blogs,
videos,
instructions,
workshops,
brands,
userProducts,
sliders,
@@ -235,6 +236,10 @@ export class MediaService {
where: { business_id: businessId, featured_media_id: { in: uniqueIds } },
select: { featured_media_id: true },
}),
this.prisma.workshops.findMany({
where: { business_id: businessId, featured_media_id: { in: uniqueIds } },
select: { featured_media_id: true },
}),
this.prisma.brand.findMany({
where: { businessId, imageMediaId: { in: uniqueIds } },
select: { imageMediaId: true },
@@ -274,6 +279,7 @@ export class MediaService {
for (const row of blogs) addId(row.featured_media_id);
for (const row of videos) addId(row.featured_media_id);
for (const row of instructions) addId(row.featured_media_id);
for (const row of workshops) addId(row.featured_media_id);
for (const row of brands) addId(row.imageMediaId);
for (const row of userProducts) addId(row.featuredMediaId);
for (const row of sliders) addId(row.image_media_id);
@@ -304,6 +310,53 @@ export class MediaService {
return mediaRows.length;
}
async galleryMediaIds(
businessId: bigint,
entityType: MediaEntityType,
entityId: bigint,
): Promise<bigint[]> {
const rows = await this.prisma.mediaAttachment.findMany({
where: { businessId, entityType, entityId, isFeatured: false },
select: { mediaId: true },
});
return rows.map((row) => row.mediaId);
}
async allLinkedMediaIds(
businessId: bigint,
entityType: MediaEntityType,
entityId: bigint,
featuredMediaId?: bigint | null,
): Promise<bigint[]> {
const rows = await this.prisma.mediaAttachment.findMany({
where: { businessId, entityType, entityId },
select: { mediaId: true },
});
const ids = rows.map((row) => row.mediaId);
if (featuredMediaId != null) ids.push(featuredMediaId);
return ids;
}
idsNotIn(
previous: bigint[],
next: Array<bigint | null | undefined>,
): bigint[] {
const keep = new Set(
next
.filter((id): id is bigint => id != null)
.map((id) => id.toString()),
);
const seen = new Set<string>();
const dropped: bigint[] = [];
for (const id of previous) {
const key = id.toString();
if (keep.has(key) || seen.has(key)) continue;
seen.add(key);
dropped.push(id);
}
return dropped;
}
private async uploadOne(
businessId: bigint,
file: Express.Multer.File,