GWM : locatin api parent id removed
This commit is contained in:
parent
67b2c32884
commit
8de3afedb3
@ -182,9 +182,11 @@ Each sub-master supports: `GET /` (list), `GET /:id`, `POST /`, `PUT /:id`, `DEL
|
|||||||
| [~] | Asset Subcategories | removed — use Item Subcategories |
|
| [~] | Asset Subcategories | removed — use Item Subcategories |
|
||||||
| [x] | Departments | `/masters/departments` |
|
| [x] | Departments | `/masters/departments` |
|
||||||
| [x] | Designations | `/masters/designations` |
|
| [x] | Designations | `/masters/designations` |
|
||||||
| [x] | Locations | `/masters/locations` | Unified plants + warehouses (`type`: `plant` \| `warehouse`) |
|
| [x] | Locations | `/masters/locations` | Unified plants + warehouses (`type`: `plant` \| `warehouse`); no plant↔warehouse hierarchy |
|
||||||
| [x] | Plants | `/masters/plants` | Alias — plant locations only |
|
| [x] | Plants | `/masters/plants` | Alias — plant locations only |
|
||||||
| [x] | Warehouses | `/masters/warehouses` | Alias — warehouse locations only |
|
| [x] | Warehouses | `/masters/warehouses` | Alias — warehouse locations only |
|
||||||
|
|
||||||
|
**DB patch:** `scripts/patch-locations-drop-parent-id.sql` — drops `locations.parent_id` (flat locations).
|
||||||
| [x] | Document Series | `/masters/document-series` |
|
| [x] | Document Series | `/masters/document-series` |
|
||||||
|
|
||||||
**Masters total:** 13 modules × 5 endpoints (+ plants/warehouses aliases)
|
**Masters total:** 13 modules × 5 endpoints (+ plants/warehouses aliases)
|
||||||
|
|||||||
@ -592,7 +592,6 @@ model locations {
|
|||||||
type String @db.VarChar(20)
|
type String @db.VarChar(20)
|
||||||
code String @db.VarChar(30)
|
code String @db.VarChar(30)
|
||||||
name String @db.VarChar(150)
|
name String @db.VarChar(150)
|
||||||
parent_id BigInt?
|
|
||||||
gstin String? @db.VarChar(15)
|
gstin String? @db.VarChar(15)
|
||||||
address String?
|
address String?
|
||||||
city String? @db.VarChar(100)
|
city String? @db.VarChar(100)
|
||||||
@ -610,8 +609,6 @@ model locations {
|
|||||||
transfers_to asset_transfers[] @relation("TransferToLocation")
|
transfers_to asset_transfers[] @relation("TransferToLocation")
|
||||||
assets_location assets[] @relation("AssetLocation")
|
assets_location assets[] @relation("AssetLocation")
|
||||||
grn_location grn[] @relation("GRNLocation")
|
grn_location grn[] @relation("GRNLocation")
|
||||||
parent locations? @relation("LocationHierarchy", fields: [parent_id], references: [id], onUpdate: NoAction)
|
|
||||||
children locations[] @relation("LocationHierarchy")
|
|
||||||
po_billing purchase_orders[] @relation("POBillingLocation")
|
po_billing purchase_orders[] @relation("POBillingLocation")
|
||||||
po_shipping purchase_orders[] @relation("POShippingLocation")
|
po_shipping purchase_orders[] @relation("POShippingLocation")
|
||||||
users_plant users[] @relation("UserPlantLocation")
|
users_plant users[] @relation("UserPlantLocation")
|
||||||
@ -619,7 +616,6 @@ model locations {
|
|||||||
users_updated users? @relation("locations_updated_byTousers", fields: [updated_by], references: [id], onUpdate: NoAction, map: "fk_locations_updated_by")
|
users_updated users? @relation("locations_updated_byTousers", fields: [updated_by], references: [id], onUpdate: NoAction, map: "fk_locations_updated_by")
|
||||||
|
|
||||||
@@index([type], map: "idx_locations_type")
|
@@index([type], map: "idx_locations_type")
|
||||||
@@index([parent_id], map: "idx_locations_parent_id")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This table contains check constraints and requires additional setup for migrations. Visit https://pris.ly/d/check-constraints for more info.
|
/// This table contains check constraints and requires additional setup for migrations. Visit https://pris.ly/d/check-constraints for more info.
|
||||||
|
|||||||
5
scripts/patch-locations-drop-parent-id.sql
Normal file
5
scripts/patch-locations-drop-parent-id.sql
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
-- Remove location hierarchy (parent_id). Plants and warehouses are flat locations.
|
||||||
|
|
||||||
|
ALTER TABLE locations DROP CONSTRAINT IF EXISTS locations_parent_id_fkey;
|
||||||
|
DROP INDEX IF EXISTS idx_locations_parent_id;
|
||||||
|
ALTER TABLE locations DROP COLUMN IF EXISTS parent_id;
|
||||||
@ -358,7 +358,6 @@ components:
|
|||||||
type: { type: string, enum: [plant, warehouse], example: plant }
|
type: { type: string, enum: [plant, warehouse], example: plant }
|
||||||
code: { type: string, example: 'PLT01' }
|
code: { type: string, example: 'PLT01' }
|
||||||
name: { type: string, example: 'Bharat Plant 1' }
|
name: { type: string, example: 'Bharat Plant 1' }
|
||||||
parent_id: { type: integer, nullable: true, example: 1, description: Required when type is warehouse (plant id) }
|
|
||||||
gstin: { type: string, example: '27ABCDE1234F1Z5' }
|
gstin: { type: string, example: '27ABCDE1234F1Z5' }
|
||||||
address: { type: string, example: 'MIDC, Nashik' }
|
address: { type: string, example: 'MIDC, Nashik' }
|
||||||
city: { type: string, example: 'Nashik' }
|
city: { type: string, example: 'Nashik' }
|
||||||
@ -373,7 +372,6 @@ components:
|
|||||||
properties:
|
properties:
|
||||||
code: { type: string, example: 'PLT01' }
|
code: { type: string, example: 'PLT01' }
|
||||||
name: { type: string, example: 'Bharat Plant 1' }
|
name: { type: string, example: 'Bharat Plant 1' }
|
||||||
parent_id: { type: integer, nullable: true, example: 1 }
|
|
||||||
gstin: { type: string, example: '27ABCDE1234F1Z5' }
|
gstin: { type: string, example: '27ABCDE1234F1Z5' }
|
||||||
address: { type: string, example: 'MIDC, Nashik' }
|
address: { type: string, example: 'MIDC, Nashik' }
|
||||||
city: { type: string, example: 'Nashik' }
|
city: { type: string, example: 'Nashik' }
|
||||||
@ -384,11 +382,10 @@ components:
|
|||||||
is_active: { type: boolean, example: true }
|
is_active: { type: boolean, example: true }
|
||||||
WarehousesCreateBody:
|
WarehousesCreateBody:
|
||||||
type: object
|
type: object
|
||||||
required: [code, name, plant_id]
|
required: [code, name]
|
||||||
properties:
|
properties:
|
||||||
code: { type: string, example: 'WH01' }
|
code: { type: string, example: 'WH01' }
|
||||||
name: { type: string, example: 'Main Warehouse' }
|
name: { type: string, example: 'Main Warehouse' }
|
||||||
plant_id: { type: integer, example: 1 }
|
|
||||||
location: { type: string, example: 'Ground Floor' }
|
location: { type: string, example: 'Ground Floor' }
|
||||||
is_active: { type: boolean, example: true }
|
is_active: { type: boolean, example: true }
|
||||||
WarehousesUpdateBody:
|
WarehousesUpdateBody:
|
||||||
@ -397,7 +394,6 @@ components:
|
|||||||
properties:
|
properties:
|
||||||
code: { type: string, example: 'WH01' }
|
code: { type: string, example: 'WH01' }
|
||||||
name: { type: string, example: 'Main Warehouse' }
|
name: { type: string, example: 'Main Warehouse' }
|
||||||
plant_id: { type: integer, example: 1 }
|
|
||||||
location: { type: string, example: 'Ground Floor' }
|
location: { type: string, example: 'Ground Floor' }
|
||||||
is_active: { type: boolean, example: true }
|
is_active: { type: boolean, example: true }
|
||||||
PlantsCreateBody:
|
PlantsCreateBody:
|
||||||
@ -1527,10 +1523,6 @@ paths:
|
|||||||
- in: query
|
- in: query
|
||||||
name: type
|
name: type
|
||||||
schema: { type: string, enum: [plant, warehouse] }
|
schema: { type: string, enum: [plant, warehouse] }
|
||||||
- in: query
|
|
||||||
name: parent_id
|
|
||||||
schema: { type: integer }
|
|
||||||
description: Filter warehouses by plant id
|
|
||||||
responses:
|
responses:
|
||||||
"200":
|
"200":
|
||||||
description: List fetched
|
description: List fetched
|
||||||
|
|||||||
@ -6,7 +6,6 @@ const { parseId } = require('../../../utils/parseId');
|
|||||||
const { rowsToCsv } = require('../../../utils/csv');
|
const { rowsToCsv } = require('../../../utils/csv');
|
||||||
const {
|
const {
|
||||||
LOCATION_TYPES,
|
LOCATION_TYPES,
|
||||||
assertPlant,
|
|
||||||
toPlantResponse,
|
toPlantResponse,
|
||||||
toWarehouseResponse,
|
toWarehouseResponse,
|
||||||
toLocationResponse,
|
toLocationResponse,
|
||||||
@ -31,7 +30,6 @@ const buildPlantData = (payload) => ({
|
|||||||
pincode: normalizeString(payload.pincode),
|
pincode: normalizeString(payload.pincode),
|
||||||
phone: normalizeString(payload.phone),
|
phone: normalizeString(payload.phone),
|
||||||
is_active: payload.is_active,
|
is_active: payload.is_active,
|
||||||
parent_id: null,
|
|
||||||
location: null,
|
location: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -39,7 +37,6 @@ const buildWarehouseData = (payload) => ({
|
|||||||
type: LOCATION_TYPES.WAREHOUSE,
|
type: LOCATION_TYPES.WAREHOUSE,
|
||||||
code: payload.code ? String(payload.code).trim().toUpperCase() : undefined,
|
code: payload.code ? String(payload.code).trim().toUpperCase() : undefined,
|
||||||
name: normalizeString(payload.name),
|
name: normalizeString(payload.name),
|
||||||
parent_id: payload.parent_id ?? payload.plant_id ?? null,
|
|
||||||
location: normalizeString(payload.location),
|
location: normalizeString(payload.location),
|
||||||
is_active: payload.is_active,
|
is_active: payload.is_active,
|
||||||
gstin: null,
|
gstin: null,
|
||||||
@ -50,8 +47,6 @@ const buildWarehouseData = (payload) => ({
|
|||||||
phone: null,
|
phone: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
const warehouseInclude = { parent: { select: { id: true, code: true, name: true } } };
|
|
||||||
|
|
||||||
const assertUniqueCode = async (code, excludeId = null) => {
|
const assertUniqueCode = async (code, excludeId = null) => {
|
||||||
if (!code) return;
|
if (!code) return;
|
||||||
const existing = await prisma.locations.findFirst({
|
const existing = await prisma.locations.findFirst({
|
||||||
@ -71,19 +66,10 @@ const createLocation = async (type, payload, userId, requestId) => {
|
|||||||
if (!data.code || !data.name) throw new ApiError(422, 'code and name are required');
|
if (!data.code || !data.name) throw new ApiError(422, 'code and name are required');
|
||||||
await assertUniqueCode(data.code);
|
await assertUniqueCode(data.code);
|
||||||
|
|
||||||
if (type === LOCATION_TYPES.WAREHOUSE) {
|
|
||||||
if (!data.parent_id) throw new ApiError(422, 'parent_id (plant) is required for warehouse');
|
|
||||||
await assertPlant(data.parent_id, 'parent_id');
|
|
||||||
data.parent_id = BigInt(data.parent_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
data.created_by = userId ? BigInt(userId) : null;
|
data.created_by = userId ? BigInt(userId) : null;
|
||||||
data.updated_by = userId ? BigInt(userId) : null;
|
data.updated_by = userId ? BigInt(userId) : null;
|
||||||
|
|
||||||
const created = await prisma.locations.create({
|
const created = await prisma.locations.create({ data });
|
||||||
data,
|
|
||||||
include: type === LOCATION_TYPES.WAREHOUSE ? warehouseInclude : undefined,
|
|
||||||
});
|
|
||||||
|
|
||||||
const response =
|
const response =
|
||||||
type === LOCATION_TYPES.PLANT ? toPlantResponse(created) : toWarehouseResponse(created);
|
type === LOCATION_TYPES.PLANT ? toPlantResponse(created) : toWarehouseResponse(created);
|
||||||
@ -106,7 +92,6 @@ const buildLocationsWhere = (query, type = null) => {
|
|||||||
const where = {
|
const where = {
|
||||||
deleted_at: null,
|
deleted_at: null,
|
||||||
...(effectiveType ? { type: effectiveType } : {}),
|
...(effectiveType ? { type: effectiveType } : {}),
|
||||||
...(query.parent_id ? { parent_id: BigInt(query.parent_id) } : {}),
|
|
||||||
...(query.is_active !== undefined ? { is_active: query.is_active } : {}),
|
...(query.is_active !== undefined ? { is_active: query.is_active } : {}),
|
||||||
...(query.search
|
...(query.search
|
||||||
? {
|
? {
|
||||||
@ -123,9 +108,6 @@ const buildLocationsWhere = (query, type = null) => {
|
|||||||
const listLocations = async (query, type = null) => {
|
const listLocations = async (query, type = null) => {
|
||||||
const { where, effectiveType } = buildLocationsWhere(query, type);
|
const { where, effectiveType } = buildLocationsWhere(query, type);
|
||||||
|
|
||||||
const locationsInclude =
|
|
||||||
effectiveType === LOCATION_TYPES.WAREHOUSE || !effectiveType ? warehouseInclude : undefined;
|
|
||||||
|
|
||||||
const mapRow = (row) => {
|
const mapRow = (row) => {
|
||||||
if (effectiveType === LOCATION_TYPES.PLANT) return toPlantResponse(row);
|
if (effectiveType === LOCATION_TYPES.PLANT) return toPlantResponse(row);
|
||||||
if (effectiveType === LOCATION_TYPES.WAREHOUSE) return toWarehouseResponse(row);
|
if (effectiveType === LOCATION_TYPES.WAREHOUSE) return toWarehouseResponse(row);
|
||||||
@ -136,7 +118,6 @@ const listLocations = async (query, type = null) => {
|
|||||||
where.is_active = true;
|
where.is_active = true;
|
||||||
const rows = await prisma.locations.findMany({
|
const rows = await prisma.locations.findMany({
|
||||||
where,
|
where,
|
||||||
include: locationsInclude,
|
|
||||||
orderBy: { created_at: 'desc' },
|
orderBy: { created_at: 'desc' },
|
||||||
});
|
});
|
||||||
const data = rows.map(mapRow);
|
const data = rows.map(mapRow);
|
||||||
@ -148,7 +129,6 @@ const listLocations = async (query, type = null) => {
|
|||||||
const [rows, total] = await Promise.all([
|
const [rows, total] = await Promise.all([
|
||||||
prisma.locations.findMany({
|
prisma.locations.findMany({
|
||||||
where,
|
where,
|
||||||
include: locationsInclude,
|
|
||||||
orderBy: { created_at: 'desc' },
|
orderBy: { created_at: 'desc' },
|
||||||
skip,
|
skip,
|
||||||
take: limit,
|
take: limit,
|
||||||
@ -163,10 +143,6 @@ const exportLocations = async (query, type = null) => {
|
|||||||
const { where, effectiveType } = buildLocationsWhere(query, type);
|
const { where, effectiveType } = buildLocationsWhere(query, type);
|
||||||
const rows = await prisma.locations.findMany({
|
const rows = await prisma.locations.findMany({
|
||||||
where,
|
where,
|
||||||
include:
|
|
||||||
effectiveType === LOCATION_TYPES.WAREHOUSE || !effectiveType
|
|
||||||
? warehouseInclude
|
|
||||||
: undefined,
|
|
||||||
orderBy: { created_at: 'desc' },
|
orderBy: { created_at: 'desc' },
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -181,8 +157,6 @@ const exportLocations = async (query, type = null) => {
|
|||||||
? [
|
? [
|
||||||
{ key: 'code', header: 'Code' },
|
{ key: 'code', header: 'Code' },
|
||||||
{ key: 'name', header: 'Name' },
|
{ key: 'name', header: 'Name' },
|
||||||
{ key: (row) => row.parent?.code || row.plant?.code || '', header: 'Plant Code' },
|
|
||||||
{ key: (row) => row.parent?.name || row.plant?.name || '', header: 'Plant Name' },
|
|
||||||
{ key: 'location', header: 'Location' },
|
{ key: 'location', header: 'Location' },
|
||||||
{ key: 'is_active', header: 'Is Active' },
|
{ key: 'is_active', header: 'Is Active' },
|
||||||
{ key: 'created_at', header: 'Created At', type: 'datetime' },
|
{ key: 'created_at', header: 'Created At', type: 'datetime' },
|
||||||
@ -215,7 +189,6 @@ const getLocationById = async (id, type = null) => {
|
|||||||
deleted_at: null,
|
deleted_at: null,
|
||||||
...(type ? { type } : {}),
|
...(type ? { type } : {}),
|
||||||
},
|
},
|
||||||
include: warehouseInclude,
|
|
||||||
});
|
});
|
||||||
if (!row) throw new ApiError(404, type ? `${type} not found` : 'Location not found');
|
if (!row) throw new ApiError(404, type ? `${type} not found` : 'Location not found');
|
||||||
|
|
||||||
@ -228,7 +201,6 @@ const updateLocation = async (id, type, payload, userId, requestId) => {
|
|||||||
const idBigInt = parseId(id);
|
const idBigInt = parseId(id);
|
||||||
const existing = await prisma.locations.findFirst({
|
const existing = await prisma.locations.findFirst({
|
||||||
where: { id: idBigInt, deleted_at: null, type },
|
where: { id: idBigInt, deleted_at: null, type },
|
||||||
include: warehouseInclude,
|
|
||||||
});
|
});
|
||||||
if (!existing) throw new ApiError(404, `${type} not found`);
|
if (!existing) throw new ApiError(404, `${type} not found`);
|
||||||
|
|
||||||
@ -240,18 +212,11 @@ const updateLocation = async (id, type, payload, userId, requestId) => {
|
|||||||
|
|
||||||
if (data.code) await assertUniqueCode(data.code, id);
|
if (data.code) await assertUniqueCode(data.code, id);
|
||||||
|
|
||||||
if (type === LOCATION_TYPES.WAREHOUSE && data.parent_id !== undefined) {
|
|
||||||
if (!data.parent_id) throw new ApiError(422, 'parent_id (plant) is required for warehouse');
|
|
||||||
await assertPlant(data.parent_id, 'parent_id');
|
|
||||||
data.parent_id = BigInt(data.parent_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
data.updated_by = userId ? BigInt(userId) : null;
|
data.updated_by = userId ? BigInt(userId) : null;
|
||||||
|
|
||||||
const updated = await prisma.locations.update({
|
const updated = await prisma.locations.update({
|
||||||
where: { id: idBigInt },
|
where: { id: idBigInt },
|
||||||
data,
|
data,
|
||||||
include: type === LOCATION_TYPES.WAREHOUSE ? warehouseInclude : undefined,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const oldValue =
|
const oldValue =
|
||||||
@ -276,7 +241,6 @@ const deleteLocation = async (id, type, userId, requestId) => {
|
|||||||
const idBigInt = parseId(id);
|
const idBigInt = parseId(id);
|
||||||
const existing = await prisma.locations.findFirst({
|
const existing = await prisma.locations.findFirst({
|
||||||
where: { id: idBigInt, deleted_at: null, type },
|
where: { id: idBigInt, deleted_at: null, type },
|
||||||
include: warehouseInclude,
|
|
||||||
});
|
});
|
||||||
if (!existing) throw new ApiError(404, `${type} not found`);
|
if (!existing) throw new ApiError(404, `${type} not found`);
|
||||||
|
|
||||||
@ -302,7 +266,6 @@ const deleteLocation = async (id, type, userId, requestId) => {
|
|||||||
const deleteLocationById = async (id, userId, requestId) => {
|
const deleteLocationById = async (id, userId, requestId) => {
|
||||||
const existing = await prisma.locations.findFirst({
|
const existing = await prisma.locations.findFirst({
|
||||||
where: { id: parseId(id), deleted_at: null },
|
where: { id: parseId(id), deleted_at: null },
|
||||||
include: warehouseInclude,
|
|
||||||
});
|
});
|
||||||
if (!existing) throw new ApiError(404, 'Location not found');
|
if (!existing) throw new ApiError(404, 'Location not found');
|
||||||
return deleteLocation(id, existing.type, userId, requestId);
|
return deleteLocation(id, existing.type, userId, requestId);
|
||||||
|
|||||||
@ -13,8 +13,6 @@ const locationFields = {
|
|||||||
pincode: Joi.string().max(10).allow(null, '').optional(),
|
pincode: Joi.string().max(10).allow(null, '').optional(),
|
||||||
phone: Joi.string().max(15).allow(null, '').optional(),
|
phone: Joi.string().max(15).allow(null, '').optional(),
|
||||||
location: Joi.string().max(200).allow(null, '').optional(),
|
location: Joi.string().max(200).allow(null, '').optional(),
|
||||||
parent_id: Joi.number().integer().positive().optional(),
|
|
||||||
plant_id: Joi.number().integer().positive().optional(),
|
|
||||||
is_active: Joi.boolean().optional(),
|
is_active: Joi.boolean().optional(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -45,7 +43,6 @@ const updatePlantSchema = Joi.object({
|
|||||||
const createWarehouseSchema = Joi.object({
|
const createWarehouseSchema = Joi.object({
|
||||||
code: masterCode({ max: 30, required: true }),
|
code: masterCode({ max: 30, required: true }),
|
||||||
name: masterName({ max: 150, required: true }),
|
name: masterName({ max: 150, required: true }),
|
||||||
plant_id: Joi.number().integer().positive().required(),
|
|
||||||
location: locationFields.location,
|
location: locationFields.location,
|
||||||
is_active: Joi.boolean().default(true),
|
is_active: Joi.boolean().default(true),
|
||||||
});
|
});
|
||||||
@ -53,7 +50,6 @@ const createWarehouseSchema = Joi.object({
|
|||||||
const updateWarehouseSchema = Joi.object({
|
const updateWarehouseSchema = Joi.object({
|
||||||
code: masterCode({ max: 30 }),
|
code: masterCode({ max: 30 }),
|
||||||
name: masterName({ max: 150 }),
|
name: masterName({ max: 150 }),
|
||||||
plant_id: Joi.number().integer().positive().optional(),
|
|
||||||
location: locationFields.location,
|
location: locationFields.location,
|
||||||
is_active: Joi.boolean().optional(),
|
is_active: Joi.boolean().optional(),
|
||||||
}).min(1);
|
}).min(1);
|
||||||
@ -62,11 +58,6 @@ const createLocationSchema = Joi.object({
|
|||||||
type: Joi.string().valid('plant', 'warehouse').required(),
|
type: Joi.string().valid('plant', 'warehouse').required(),
|
||||||
code: masterCode({ max: 30, required: true }),
|
code: masterCode({ max: 30, required: true }),
|
||||||
name: masterName({ max: 150, required: true }),
|
name: masterName({ max: 150, required: true }),
|
||||||
parent_id: Joi.when('type', {
|
|
||||||
is: 'warehouse',
|
|
||||||
then: Joi.number().integer().positive().required(),
|
|
||||||
otherwise: Joi.number().integer().positive().allow(null).optional(),
|
|
||||||
}),
|
|
||||||
gstin: locationFields.gstin,
|
gstin: locationFields.gstin,
|
||||||
address: locationFields.address,
|
address: locationFields.address,
|
||||||
city: locationFields.city,
|
city: locationFields.city,
|
||||||
@ -80,7 +71,6 @@ const createLocationSchema = Joi.object({
|
|||||||
const updateLocationSchema = Joi.object({
|
const updateLocationSchema = Joi.object({
|
||||||
code: masterCode({ max: 30 }),
|
code: masterCode({ max: 30 }),
|
||||||
name: masterName({ max: 150 }),
|
name: masterName({ max: 150 }),
|
||||||
parent_id: Joi.number().integer().positive().optional(),
|
|
||||||
gstin: locationFields.gstin,
|
gstin: locationFields.gstin,
|
||||||
address: locationFields.address,
|
address: locationFields.address,
|
||||||
city: locationFields.city,
|
city: locationFields.city,
|
||||||
@ -93,7 +83,6 @@ const updateLocationSchema = Joi.object({
|
|||||||
|
|
||||||
const listLocationsQuerySchema = listQuerySchema.keys({
|
const listLocationsQuerySchema = listQuerySchema.keys({
|
||||||
type: Joi.string().valid('plant', 'warehouse').optional(),
|
type: Joi.string().valid('plant', 'warehouse').optional(),
|
||||||
parent_id: Joi.number().integer().positive().optional(),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const exportQuerySchema = toExportQuerySchema(listLocationsQuerySchema);
|
const exportQuerySchema = toExportQuerySchema(listLocationsQuerySchema);
|
||||||
|
|||||||
@ -15,9 +15,6 @@ const assertLocation = async (id, expectedType, label, { requireActive = true }
|
|||||||
type: expectedType,
|
type: expectedType,
|
||||||
deleted_at: null,
|
deleted_at: null,
|
||||||
},
|
},
|
||||||
include: expectedType === LOCATION_TYPES.WAREHOUSE
|
|
||||||
? { parent: { select: { id: true, code: true, name: true } } }
|
|
||||||
: undefined,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!row) throw new ApiError(422, `Invalid ${label}`);
|
if (!row) throw new ApiError(422, `Invalid ${label}`);
|
||||||
@ -31,13 +28,12 @@ const assertPlant = (id, label = 'plant_id') =>
|
|||||||
const assertWarehouse = (id, label = 'warehouse_id') =>
|
const assertWarehouse = (id, label = 'warehouse_id') =>
|
||||||
assertLocation(id, LOCATION_TYPES.WAREHOUSE, label);
|
assertLocation(id, LOCATION_TYPES.WAREHOUSE, label);
|
||||||
|
|
||||||
/** Assert a location of any type (plant or warehouse). Returns the row (with parent). */
|
/** Assert a location of any type (plant or warehouse). */
|
||||||
const assertAnyLocation = async (id, label, { requireActive = true } = {}) => {
|
const assertAnyLocation = async (id, label, { requireActive = true } = {}) => {
|
||||||
if (!id) return null;
|
if (!id) return null;
|
||||||
|
|
||||||
const row = await prisma.locations.findFirst({
|
const row = await prisma.locations.findFirst({
|
||||||
where: { id: BigInt(id), deleted_at: null },
|
where: { id: BigInt(id), deleted_at: null },
|
||||||
include: { parent: { select: { id: true, code: true, name: true } } },
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!row) throw new ApiError(422, `Invalid ${label}`);
|
if (!row) throw new ApiError(422, `Invalid ${label}`);
|
||||||
@ -53,9 +49,7 @@ const warehouseListSelect = {
|
|||||||
id: true,
|
id: true,
|
||||||
code: true,
|
code: true,
|
||||||
name: true,
|
name: true,
|
||||||
parent_id: true,
|
|
||||||
location: true,
|
location: true,
|
||||||
parent: { select: plantListSelect },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const toPlantResponse = (row) => ({
|
const toPlantResponse = (row) => ({
|
||||||
@ -80,8 +74,6 @@ const toWarehouseResponse = (row) => ({
|
|||||||
id: row.id,
|
id: row.id,
|
||||||
code: row.code,
|
code: row.code,
|
||||||
name: row.name,
|
name: row.name,
|
||||||
plant_id: row.parent_id,
|
|
||||||
plant: row.parent || null,
|
|
||||||
location: row.location,
|
location: row.location,
|
||||||
is_active: row.is_active,
|
is_active: row.is_active,
|
||||||
created_by: row.created_by,
|
created_by: row.created_by,
|
||||||
@ -93,7 +85,7 @@ const toWarehouseResponse = (row) => ({
|
|||||||
|
|
||||||
const toLocationResponse = (row) => {
|
const toLocationResponse = (row) => {
|
||||||
if (row.type === LOCATION_TYPES.PLANT) return { ...toPlantResponse(row), type: row.type };
|
if (row.type === LOCATION_TYPES.PLANT) return { ...toPlantResponse(row), type: row.type };
|
||||||
return { ...toWarehouseResponse(row), type: row.type, parent_id: row.parent_id };
|
return { ...toWarehouseResponse(row), type: row.type };
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user