GWM : items master joined

This commit is contained in:
Gowtham M 2026-07-10 15:32:28 +05:30
parent 28d38bc695
commit 382111f7b9
2 changed files with 104 additions and 9 deletions

View File

@ -154,7 +154,52 @@ components:
id: { type: string, example: '1' }
item_code: { type: string, example: 'ITM-00006', description: Auto-generated on create via ITEM document series; read-only }
item_name: { type: string, example: 'LABSA' }
hsn_code_id: { type: integer, nullable: true, example: 1 }
item_category_id: { type: string, example: '38' }
item_subcategory_id: { type: string, nullable: true, example: '30' }
hsn_code_id: { type: string, nullable: true, example: '1' }
item_category:
type: object
nullable: true
properties:
id: { type: string, example: '38' }
code: { type: string, example: 'RAW' }
name: { type: string, example: 'Raw Material' }
item_subcategory:
type: object
nullable: true
properties:
id: { type: string, example: '30' }
code: { type: string, example: 'CHEM' }
name: { type: string, example: 'Chemicals' }
item_category_id: { type: string, example: '38' }
hsn_code:
type: object
nullable: true
properties:
id: { type: string, example: '1' }
code: { type: string, example: '34029099' }
description: { type: string, example: 'Organic surface-active agents' }
uom:
type: object
nullable: true
properties:
id: { type: string }
code: { type: string }
name: { type: string }
gst_rate:
type: object
nullable: true
properties:
id: { type: string }
rate_pct: { type: number }
description: { type: string, nullable: true }
brand:
type: object
nullable: true
properties:
id: { type: string }
code: { type: string }
name: { type: string }
BrandsCreateBody:
type: object
required: [code, name, brand_type]

View File

@ -15,6 +15,50 @@ const SOFT_DELETE_TABLES = new Set([
'brands',
]);
const itemInclude = {
item_categories: { select: { id: true, code: true, name: true } },
item_subcategories: { select: { id: true, code: true, name: true, item_category_id: true } },
hsn_codes: { select: { id: true, code: true, description: true } },
uom: { select: { id: true, code: true, name: true } },
gst_rates: { select: { id: true, rate_pct: true, description: true } },
brands: { select: { id: true, code: true, name: true } },
};
const toDecimal = (value) =>
value !== null && value !== undefined ? Number(value) : value;
const sanitizeItem = (row) => {
if (!row) return null;
const {
item_categories,
item_subcategories,
hsn_codes,
uom,
gst_rates,
brands,
...rest
} = row;
return {
...rest,
min_order_qty: toDecimal(rest.min_order_qty),
reorder_level: toDecimal(rest.reorder_level),
item_category: item_categories || null,
item_subcategory: item_subcategories || null,
hsn_code: hsn_codes || null,
uom: uom || null,
gst_rate: gst_rates
? { ...gst_rates, rate_pct: toDecimal(gst_rates.rate_pct) }
: null,
brand: brands || null,
item_categories: undefined,
item_subcategories: undefined,
hsn_codes: undefined,
gst_rates: undefined,
brands: undefined,
};
};
const normalizeString = (value) => {
if (value === undefined || value === null) return value;
const str = String(value).trim();
@ -138,19 +182,22 @@ const createItems = async (payload, userId, requestId) => {
if (data.is_asset_item === undefined) data.is_asset_item = false;
if (data.is_active === undefined) data.is_active = true;
const created = await prisma.items.create({ data });
const created = await prisma.items.create({
data,
include: itemInclude,
});
await auditLog({
tableName: 'items',
recordId: created.id,
action: 'CREATE',
oldValue: null,
newValue: created,
newValue: sanitizeItem(created),
userId,
requestId,
});
return created;
return sanitizeItem(created);
};
const listItems = async (query) => {
@ -169,9 +216,10 @@ const listItems = async (query) => {
: {}),
};
const [data, total] = await Promise.all([
const [rows, total] = await Promise.all([
prisma.items.findMany({
where,
include: itemInclude,
orderBy: { created_at: 'desc' },
skip,
take: limit,
@ -179,15 +227,16 @@ const listItems = async (query) => {
prisma.items.count({ where }),
]);
return { data, meta: { page, limit, total } };
return { data: rows.map(sanitizeItem), meta: { page, limit, total } };
};
const getItemsById = async (id) => {
const one = await prisma.items.findFirst({
where: { id: BigInt(id), deleted_at: null },
include: itemInclude,
});
if (!one) throw new ApiError(404, 'items not found');
return one;
return sanitizeItem(one);
};
const updateItems = async (id, payload, userId, requestId) => {
@ -204,6 +253,7 @@ const updateItems = async (id, payload, userId, requestId) => {
const updated = await prisma.items.update({
where: { id: BigInt(id) },
data,
include: itemInclude,
});
await auditLog({
@ -211,12 +261,12 @@ const updateItems = async (id, payload, userId, requestId) => {
recordId: id,
action: 'UPDATE',
oldValue: existing,
newValue: updated,
newValue: sanitizeItem(updated),
userId,
requestId,
});
return updated;
return sanitizeItem(updated);
};
const deleteItems = async (id, userId, requestId) => {