Enhance utility functions in utils.js for improved reference model handling and filtering logic
All checks were successful
farmcontrol/farmcontrol-api/pipeline/head This commit looks good
All checks were successful
farmcontrol/farmcontrol-api/pipeline/head This commit looks good
This update introduces new functions such as `getRefModelEntryFromPrefix`, `stripPrefixFromOperand`, and `getRefModelEntryForToken` to streamline the processing of reference models and tokens. Additionally, the `resolveRefLeaf` and `resolveRefCondition` functions have been refactored to utilize these enhancements, improving the overall efficiency and clarity of the filtering and reference resolution processes. Minor formatting adjustments were also made in orderitems.js for consistency.
This commit is contained in:
parent
069406e4d8
commit
4bd29e2010
@ -17,8 +17,8 @@ const listAllowedFilters = [
|
||||
'state',
|
||||
'createdAt',
|
||||
'updatedAt',
|
||||
'_reference'
|
||||
];
|
||||
'_reference',
|
||||
];
|
||||
const propertiesAllowedFilters = [
|
||||
'name',
|
||||
'itemType',
|
||||
@ -29,7 +29,7 @@ const propertiesAllowedFilters = [
|
||||
'orderType',
|
||||
'shipment',
|
||||
'shipment._id',
|
||||
];
|
||||
];
|
||||
import {
|
||||
listOrderItemsRouteHandler,
|
||||
getOrderItemRouteHandler,
|
||||
@ -42,8 +42,7 @@ import {
|
||||
getOrderItemHistoryRouteHandler,
|
||||
searchOrderItemsRouteHandler,
|
||||
getOrderItemPropertyValuesRouteHandler,
|
||||
|
||||
getOrderItemNeighborsRouteHandler
|
||||
getOrderItemNeighborsRouteHandler,
|
||||
} from '../../services/inventory/orderitems.js';
|
||||
|
||||
// list of order items
|
||||
@ -72,7 +71,6 @@ router.get('/search', isAuthenticated, async (req, res) => {
|
||||
searchOrderItemsRouteHandler(req, res, search);
|
||||
});
|
||||
|
||||
|
||||
router.post('/', isAuthenticated, async (req, res) => {
|
||||
newOrderItemRouteHandler(req, res);
|
||||
});
|
||||
|
||||
74
src/utils.js
74
src/utils.js
@ -9,7 +9,7 @@ import log4js from 'log4js';
|
||||
import config from './config.js';
|
||||
import crypto from 'crypto';
|
||||
import canonicalize from 'canonical-json';
|
||||
import { getModelByName } from './services/misc/model.js';
|
||||
import { getModelByName, getModelByPrefix } from './services/misc/model.js';
|
||||
import { models } from './database/schemas/models.js';
|
||||
import { createEmailRenderAuthCode } from './services/misc/emailRenderAuth.js';
|
||||
import { Worker } from 'worker_threads';
|
||||
@ -185,6 +185,30 @@ function getRefModelEntryFromSchemaRef(refName) {
|
||||
};
|
||||
}
|
||||
|
||||
function getRefModelEntryFromPrefix(prefix) {
|
||||
const entry = getModelByPrefix(prefix);
|
||||
if (!entry?.model) return null;
|
||||
return {
|
||||
model: entry.model,
|
||||
idField: entry.idField ?? '_id',
|
||||
referenceField: entry.referenceField ?? '_reference',
|
||||
};
|
||||
}
|
||||
|
||||
function stripPrefixFromOperand(operand) {
|
||||
const { suffix, hadPrefix } = parsePrefixedValue(String(operand).trim());
|
||||
return hadPrefix ? suffix : String(operand).trim();
|
||||
}
|
||||
|
||||
function getRefModelEntryForToken(token, fallbackRefName) {
|
||||
const { prefix, hadPrefix } = parsePrefixedValue(String(token).trim());
|
||||
if (hadPrefix) {
|
||||
const entry = getRefModelEntryFromPrefix(prefix);
|
||||
if (entry) return entry;
|
||||
}
|
||||
return getRefModelEntryFromSchemaRef(fallbackRefName);
|
||||
}
|
||||
|
||||
function parseBooleanOperand(value) {
|
||||
const lower = String(value).trim().toLowerCase();
|
||||
if (lower === 'yes') return true;
|
||||
@ -615,8 +639,10 @@ function combineAndRefIds(children) {
|
||||
}
|
||||
|
||||
async function resolveRefOperand(operand, refModelEntry, operator = 'eq') {
|
||||
const operandText = String(operand).trim();
|
||||
const objectId = extractObjectIdFromOperand(operandText);
|
||||
if (!refModelEntry?.model) return NO_MATCH_CONDITION;
|
||||
|
||||
const lookupOperand = String(operand).trim();
|
||||
const objectId = extractObjectIdFromOperand(lookupOperand);
|
||||
|
||||
if (objectId) {
|
||||
if (operator === 'ne') return { op: { $ne: objectId } };
|
||||
@ -624,7 +650,7 @@ async function resolveRefOperand(operand, refModelEntry, operator = 'eq') {
|
||||
return NO_MATCH_CONDITION;
|
||||
}
|
||||
|
||||
const expression = buildRefListExpression(operator, operandText);
|
||||
const expression = buildRefListExpression(operator, lookupOperand);
|
||||
const ids = await listRefModelIds(refModelEntry, expression);
|
||||
|
||||
if (operator === 'ne') {
|
||||
@ -635,13 +661,18 @@ async function resolveRefOperand(operand, refModelEntry, operator = 'eq') {
|
||||
return idsToCondition(ids);
|
||||
}
|
||||
|
||||
async function resolveRefLeaf(rawToken, refModelEntry) {
|
||||
async function resolveRefLeaf(rawToken, fallbackRefName) {
|
||||
const token = rawToken.trim();
|
||||
if (token === '') return NO_MATCH_CONDITION;
|
||||
|
||||
const rangeIdx = token.indexOf('..');
|
||||
const refModelEntry = getRefModelEntryForToken(token, fallbackRefName);
|
||||
if (!refModelEntry?.model) return NO_MATCH_CONDITION;
|
||||
|
||||
const lookupToken = stripPrefixFromOperand(token);
|
||||
|
||||
const rangeIdx = lookupToken.indexOf('..');
|
||||
if (rangeIdx !== -1) {
|
||||
const ids = await listRefModelIds(refModelEntry, token);
|
||||
const ids = await listRefModelIds(refModelEntry, lookupToken);
|
||||
return idsToCondition(ids);
|
||||
}
|
||||
|
||||
@ -654,37 +685,33 @@ async function resolveRefLeaf(rawToken, refModelEntry) {
|
||||
['=', 'eq'],
|
||||
];
|
||||
for (const [symbol, name] of operators) {
|
||||
if (token.startsWith(symbol)) {
|
||||
return resolveRefOperand(token.slice(symbol.length), refModelEntry, name);
|
||||
if (lookupToken.startsWith(symbol)) {
|
||||
return resolveRefOperand(lookupToken.slice(symbol.length), refModelEntry, name);
|
||||
}
|
||||
}
|
||||
|
||||
const objectId = extractObjectIdFromOperand(token);
|
||||
const objectId = extractObjectIdFromOperand(lookupToken);
|
||||
if (objectId) return { value: objectId };
|
||||
|
||||
const ids = await listRefModelIds(refModelEntry, token);
|
||||
const ids = await listRefModelIds(refModelEntry, lookupToken);
|
||||
return idsToCondition(ids);
|
||||
}
|
||||
|
||||
async function resolveRefCondition(node, refModelEntry) {
|
||||
async function resolveRefCondition(node, fallbackRefName) {
|
||||
if (node.type === 'leaf') {
|
||||
return resolveRefLeaf(node.token, refModelEntry);
|
||||
return resolveRefLeaf(node.token, fallbackRefName);
|
||||
}
|
||||
|
||||
const children = await Promise.all(
|
||||
node.items.map((item) => resolveRefCondition(item, refModelEntry))
|
||||
node.items.map((item) => resolveRefCondition(item, fallbackRefName))
|
||||
);
|
||||
|
||||
return node.type === 'and' ? combineAndRefIds(children) : combineOrRefIds(children);
|
||||
}
|
||||
|
||||
async function resolveObjectRefFilter(filterProperty, expression, refName) {
|
||||
const refModelEntry = getRefModelEntryFromSchemaRef(refName);
|
||||
|
||||
if (!refModelEntry?.model) return { [filterProperty]: { $in: [] } };
|
||||
|
||||
async function resolveObjectRefFilter(filterProperty, expression, fallbackRefName) {
|
||||
const tree = parseExpression(expression);
|
||||
const condition = await resolveRefCondition(tree, refModelEntry);
|
||||
const condition = await resolveRefCondition(tree, fallbackRefName);
|
||||
return conditionToQuery(condition, filterProperty);
|
||||
}
|
||||
|
||||
@ -1524,7 +1551,12 @@ function mergeFilterClauses(clauses) {
|
||||
// Returns a filter object based on allowed filters and req.query
|
||||
async function getFilter(query, allowedFilters, parse = true, model = null) {
|
||||
const clauses = [];
|
||||
for (const [key, value] of Object.entries(query)) {
|
||||
const queryClean = { ...query };
|
||||
for (const key of ['sort', 'order', 'page', 'limit']) {
|
||||
if (key in queryClean) delete queryClean[key];
|
||||
}
|
||||
logger.info('queryExcludingSortAndOrder', queryClean);
|
||||
for (const [key, value] of Object.entries(queryClean)) {
|
||||
if (allowedFilters.includes(key)) {
|
||||
clauses.push(parse ? await parseFilter(key, value, model) : { [key]: value });
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user