feat(products): port missing variant fields from henza and redesign variant modal
This commit is contained in:
@@ -73,6 +73,12 @@ export class AdminProductsController {
|
||||
return this.products.createVariant(body);
|
||||
}
|
||||
|
||||
@Get('colors')
|
||||
@RequirePermission('product.list')
|
||||
colors() {
|
||||
return this.products.colors();
|
||||
}
|
||||
|
||||
@Get('show-type-options')
|
||||
@RequirePermission('product.list')
|
||||
showTypeOptions() {
|
||||
|
||||
@@ -20,6 +20,13 @@ const SHOW_TYPE_LABELS: Record<number, string> = {
|
||||
3: 'سایت و گوشی',
|
||||
};
|
||||
|
||||
export const VARIANT_COLORS: Record<number, string> = {
|
||||
0: 'سفید',
|
||||
1: 'زرد',
|
||||
2: 'شکلاتی',
|
||||
3: 'رزگلد',
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
export class AdminProductsService {
|
||||
constructor(
|
||||
@@ -201,6 +208,7 @@ export class AdminProductsService {
|
||||
}
|
||||
|
||||
private variantRow(v: Prisma.ProductVariantGetPayload<object> & { image?: { id: string; url: string } | null }) {
|
||||
const colorNum = v.color != null ? Number(v.color) : null;
|
||||
return {
|
||||
id: v.id,
|
||||
product_id_id: v.productId,
|
||||
@@ -216,13 +224,22 @@ export class AdminProductsService {
|
||||
// without a second lookup. Only populated where the query included it.
|
||||
image_id: v.imageId,
|
||||
image: v.image ? { id: v.image.id, url: v.image.url } : null,
|
||||
// Legacy had a separate rial making-charge column; the schema models wage
|
||||
// as a percentage only. Returned as null rather than faked.
|
||||
rial_pay: null,
|
||||
color_str: null,
|
||||
color: colorNum,
|
||||
color_str: colorNum != null ? (VARIANT_COLORS[colorNum] ?? null) : null,
|
||||
rial_pay: v.rialWage != null ? Number(v.rialWage) : null,
|
||||
details: v.details ?? null,
|
||||
description: v.description ?? null,
|
||||
};
|
||||
}
|
||||
|
||||
/** Legacy `GET product/color` — options for variant color dropdown. */
|
||||
colors() {
|
||||
return Object.entries(VARIANT_COLORS).map(([id, title]) => ({
|
||||
id: Number(id),
|
||||
title,
|
||||
}));
|
||||
}
|
||||
|
||||
/** Legacy `POST get/variants` — a POST that reads, per legacy's own routing. */
|
||||
async listVariants(query: TableQueryDto & { product_id?: string }) {
|
||||
this.table.assertNotExport(query);
|
||||
@@ -339,6 +356,13 @@ export class AdminProductsService {
|
||||
qty: Number(v.qty ?? 0),
|
||||
isPreOrder: Boolean(v.is_pre_order),
|
||||
isActive: v.is_active !== undefined ? Boolean(v.is_active) : true,
|
||||
color: v.color !== undefined && v.color !== null && v.color !== '' ? Number(v.color) : null,
|
||||
rialWage:
|
||||
v.rial_pay !== undefined && v.rial_pay !== null && v.rial_pay !== ''
|
||||
? new Prisma.Decimal(String(v.rial_pay))
|
||||
: null,
|
||||
details: v.details ? String(v.details) : null,
|
||||
description: v.description ? String(v.description) : null,
|
||||
imageId,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -225,6 +225,8 @@ export class CatalogService {
|
||||
|
||||
const stockBlocked = await this.accounting.stockBlocker();
|
||||
const out = [];
|
||||
const colorNames: Record<number, string> = { 0: 'سفید', 1: 'زرد', 2: 'شکلاتی', 3: 'رزگلد' };
|
||||
|
||||
for (const p of products) {
|
||||
const { accountingStockWeight, accountingStockCount, accountingStockAt, ...product } = p;
|
||||
// D27 — out of stock in the accounting software: every variant reads as
|
||||
@@ -232,7 +234,22 @@ export class CatalogService {
|
||||
// the cart unless it is a pre-order variant. The stock figures themselves
|
||||
// stay server-side; this endpoint is public.
|
||||
const blocked = stockBlocked({ accountingStockWeight, accountingStockCount, accountingStockAt });
|
||||
out.push(blocked ? { ...product, variants: product.variants.map((v) => (v.isPreOrder ? v : { ...v, qty: 0 })) } : product);
|
||||
const mappedVariants = product.variants.map((v) => {
|
||||
const cNum = v.color != null ? Number(v.color) : null;
|
||||
const color_str = cNum != null ? (colorNames[cNum] ?? null) : null;
|
||||
const base = {
|
||||
...v,
|
||||
color: cNum,
|
||||
color_str,
|
||||
rial_pay: v.rialWage != null ? Number(v.rialWage) : null,
|
||||
};
|
||||
return blocked && !v.isPreOrder ? { ...base, qty: 0 } : base;
|
||||
});
|
||||
|
||||
out.push({
|
||||
...product,
|
||||
variants: mappedVariants,
|
||||
});
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user