@autofleet/sadot 0.13.5-beta-4 → 0.13.5-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/hooks/hooks.js +5 -28
- package/dist/repository/validator.d.ts +1 -2
- package/dist/repository/validator.js +1 -3
- package/dist/utils/helpers/index.d.ts +3 -4
- package/dist/utils/helpers/index.js +30 -22
- package/package.json +1 -2
- package/src/hooks/hooks.ts +5 -48
- package/src/repository/validator.ts +2 -5
- package/src/utils/helpers/index.ts +35 -28
package/dist/hooks/hooks.js
CHANGED
|
@@ -31,7 +31,6 @@ const ajv_1 = __importDefault(require("ajv"));
|
|
|
31
31
|
const joi_1 = __importDefault(require("joi"));
|
|
32
32
|
const ajv_formats_1 = __importDefault(require("ajv-formats"));
|
|
33
33
|
const errors_1 = require("@autofleet/errors");
|
|
34
|
-
const ajv_errors_1 = __importDefault(require("ajv-errors"));
|
|
35
34
|
const logger_1 = __importDefault(require("../utils/logger"));
|
|
36
35
|
const ValidatorRepo = __importStar(require("../repository/validator"));
|
|
37
36
|
const DefinitionRepo = __importStar(require("../repository/definition"));
|
|
@@ -49,7 +48,6 @@ const ajv = new ajv_1.default({
|
|
|
49
48
|
$data: true, // Enable $data references
|
|
50
49
|
});
|
|
51
50
|
(0, ajv_formats_1.default)(ajv);
|
|
52
|
-
(0, ajv_errors_1.default)(ajv);
|
|
53
51
|
/**
|
|
54
52
|
* Helper function to manually copy object properties
|
|
55
53
|
* This is more efficient for large objects and avoids excessive object creation
|
|
@@ -90,22 +88,10 @@ const getCompleteCustomFields = async (instance, options) => {
|
|
|
90
88
|
}
|
|
91
89
|
return instance.customFields || {};
|
|
92
90
|
};
|
|
93
|
-
const formatAjvErrors = (errors) => errors.reduce((acc, err) => {
|
|
94
|
-
const basePath = (err.instancePath || '')
|
|
95
|
-
.split('/')
|
|
96
|
-
.filter(Boolean)
|
|
97
|
-
.join('.')
|
|
98
|
-
.replace(/^after\./, '');
|
|
99
|
-
const missingProp = err.keyword === 'required' ? `.${err.params?.missingProperty}` : '';
|
|
100
|
-
const key = (basePath + missingProp).replace(/^\./, '') || 'root';
|
|
101
|
-
const message = err.message || 'Invalid value';
|
|
102
|
-
acc[key] = message;
|
|
103
|
-
return acc;
|
|
104
|
-
}, {});
|
|
105
91
|
/**
|
|
106
92
|
* Validates the model using custom validators
|
|
107
93
|
*/
|
|
108
|
-
const validateModel = async (instance, options, scopeAttributes,
|
|
94
|
+
const validateModel = async (instance, options, scopeAttributes, isCreate = false) => {
|
|
109
95
|
var _a;
|
|
110
96
|
const modelType = instance.constructor.name;
|
|
111
97
|
logger_1.default.debug('sadot - validating model', { isCreate, modelType });
|
|
@@ -135,9 +121,6 @@ const validateModel = async (instance, options, scopeAttributes, modelOptions =
|
|
|
135
121
|
validatorsPromise = ValidatorRepo.findAllByModelType(modelType, entityId, {
|
|
136
122
|
transaction: options.transaction,
|
|
137
123
|
attributes: CUSTOM_VALIDATOR_ATTRIBUTES_TO_PULL,
|
|
138
|
-
...(modelOptions.include && {
|
|
139
|
-
include: modelOptions.include?.(entityId),
|
|
140
|
-
}),
|
|
141
124
|
raw: true,
|
|
142
125
|
});
|
|
143
126
|
if (options.transaction) {
|
|
@@ -190,10 +173,7 @@ const validateModel = async (instance, options, scopeAttributes, modelOptions =
|
|
|
190
173
|
})));
|
|
191
174
|
if (!isValid) {
|
|
192
175
|
const errorDetails = validateSchema.errors?.map((err) => `${err.instancePath || ''} ${err.message || 'Invalid value'}`).join(', ');
|
|
193
|
-
|
|
194
|
-
throw new errors_1.BadRequest([new Error(`Validation failed for ${modelType}: ${errorDetails}`)], undefined, {
|
|
195
|
-
customError: formattedErrors,
|
|
196
|
-
});
|
|
176
|
+
throw new errors_1.BadRequest([new Error(`Validation failed for ${modelType}: ${errorDetails}`)]);
|
|
197
177
|
}
|
|
198
178
|
}
|
|
199
179
|
}
|
|
@@ -222,10 +202,7 @@ const validateModel = async (instance, options, scopeAttributes, modelOptions =
|
|
|
222
202
|
const errorDetails = validateSchema
|
|
223
203
|
.errors
|
|
224
204
|
?.map((err) => `${err.instancePath || ''} ${err.message || 'Invalid value'}`).join(', ');
|
|
225
|
-
|
|
226
|
-
throw new errors_1.BadRequest([new Error(`Validation failed for ${modelType}: ${errorDetails}`)], undefined, {
|
|
227
|
-
customError: formattedErrors,
|
|
228
|
-
});
|
|
205
|
+
throw new errors_1.BadRequest([new Error(`Validation failed for ${modelType}: ${errorDetails}`)]);
|
|
229
206
|
}
|
|
230
207
|
}
|
|
231
208
|
}
|
|
@@ -293,7 +270,7 @@ const beforeCreate = (scopeAttributes, modelOptions = {}, sadotOptions = { useCu
|
|
|
293
270
|
throw new errors_2.MissingRequiredCustomFieldError(missingFields);
|
|
294
271
|
}
|
|
295
272
|
// Step 2: Validate the model data (including custom fields)
|
|
296
|
-
await validateModel(instance, options, scopeAttributes,
|
|
273
|
+
await validateModel(instance, options, scopeAttributes, true);
|
|
297
274
|
// format date and datetime fields
|
|
298
275
|
formatDates(fieldDefinitions, instance);
|
|
299
276
|
// Step 3: Save custom field values if they exist
|
|
@@ -331,7 +308,7 @@ const beforeUpdate = (scopeAttributes, modelOptions = {}, sadotOptions = { useCu
|
|
|
331
308
|
modelType, modelOptions, identifiers, options,
|
|
332
309
|
});
|
|
333
310
|
// Step 1: Validate the model data (including custom fields)
|
|
334
|
-
await validateModel(instance, options, scopeAttributes,
|
|
311
|
+
await validateModel(instance, options, scopeAttributes, false);
|
|
335
312
|
// format date and datetime fields
|
|
336
313
|
formatDates(fieldDefinitions, instance);
|
|
337
314
|
// Step 2: Update custom field values if they exist
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Transactionable } from 'sequelize';
|
|
2
2
|
import { CustomValidator } from '../models';
|
|
3
3
|
export interface FindValidatorOptions extends Transactionable {
|
|
4
4
|
withDisabled?: boolean;
|
|
5
5
|
attributes?: string[];
|
|
6
6
|
raw?: boolean;
|
|
7
|
-
include?: IncludeOptions[];
|
|
8
7
|
}
|
|
9
8
|
export interface ValidatorAttributes {
|
|
10
9
|
entityId: string;
|
|
@@ -40,9 +40,7 @@ const findAllByModelType = async (modelType, entityId, options = { withDisabled:
|
|
|
40
40
|
logger_1.default.debug('custom-validator - find all validators by model type');
|
|
41
41
|
return (0, exports.findAll)({
|
|
42
42
|
modelType,
|
|
43
|
-
|
|
44
|
-
entityId,
|
|
45
|
-
}),
|
|
43
|
+
entityId,
|
|
46
44
|
}, options);
|
|
47
45
|
};
|
|
48
46
|
exports.findAllByModelType = findAllByModelType;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type WhereOptions, type
|
|
1
|
+
import { type WhereOptions, type IncludeOptions } from 'sequelize';
|
|
2
2
|
import { type ModelStatic } from 'sequelize-typescript';
|
|
3
3
|
import { CustomFieldDefinitionType } from '../constants';
|
|
4
4
|
/**
|
|
@@ -14,12 +14,11 @@ import { CustomFieldDefinitionType } from '../constants';
|
|
|
14
14
|
* @param {CustomFieldDefinitionType[]} excludedCustomFieldsTypes - An array of custom field types
|
|
15
15
|
* to exclude from the search
|
|
16
16
|
*
|
|
17
|
-
* @returns {CustomFieldsSearchPayload} - An object containing the
|
|
18
|
-
* for Sequelize.
|
|
17
|
+
* @returns {CustomFieldsSearchPayload} - An object containing the INCLUDE clause and WHERE clause to add to query payload
|
|
19
18
|
*/
|
|
20
19
|
interface CustomFieldsSearchPayload {
|
|
21
20
|
where: WhereOptions;
|
|
22
|
-
|
|
21
|
+
include: IncludeOptions[];
|
|
23
22
|
}
|
|
24
23
|
export declare const generateRandomString: (length?: number) => string;
|
|
25
24
|
export declare const generateCustomFieldSearchQueryPayload: (searchTerm: string, model: ModelStatic, entityId: string, customFieldsTypesToExclude?: CustomFieldDefinitionType[]) => CustomFieldsSearchPayload;
|
|
@@ -6,6 +6,7 @@ const sequelize_1 = require("sequelize");
|
|
|
6
6
|
const sequelize_typescript_1 = require("sequelize-typescript");
|
|
7
7
|
const node_crypto_1 = require("node:crypto");
|
|
8
8
|
const constants_1 = require("../constants");
|
|
9
|
+
const models_1 = require("../../models");
|
|
9
10
|
const generateRandomString = (length = 5) => {
|
|
10
11
|
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
|
|
11
12
|
return Array.from({ length }, () => characters.charAt((0, node_crypto_1.randomInt)(characters.length))).join('');
|
|
@@ -14,27 +15,34 @@ exports.generateRandomString = generateRandomString;
|
|
|
14
15
|
const generateCustomFieldSearchQueryPayload = (searchTerm, model, entityId, customFieldsTypesToExclude = [
|
|
15
16
|
constants_1.CustomFieldDefinitionType.DATETIME,
|
|
16
17
|
constants_1.CustomFieldDefinitionType.DATE,
|
|
17
|
-
]) => {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
18
|
+
]) => ({
|
|
19
|
+
include: [{
|
|
20
|
+
attributes: ['value', 'model_id'],
|
|
21
|
+
model: models_1.CustomFieldValue,
|
|
22
|
+
as: 'customFieldValue',
|
|
23
|
+
required: false,
|
|
24
|
+
include: [
|
|
25
|
+
{
|
|
26
|
+
model: models_1.CustomFieldDefinition,
|
|
27
|
+
as: 'customFieldDefinition',
|
|
28
|
+
attributes: ['entity_id', 'field_type', 'model_type'],
|
|
29
|
+
required: true,
|
|
30
|
+
on: {
|
|
31
|
+
id: sequelize_typescript_1.Sequelize.where(sequelize_typescript_1.Sequelize.col('id'), { [sequelize_1.Op.eq]: sequelize_typescript_1.Sequelize.col('customFieldValue.custom_field_definition_id') }),
|
|
32
|
+
entityId: sequelize_typescript_1.Sequelize.where(sequelize_typescript_1.Sequelize.col('entity_id'), { [sequelize_1.Op.eq]: `${entityId}` }),
|
|
33
|
+
modelType: sequelize_typescript_1.Sequelize.where(sequelize_typescript_1.Sequelize.col('model_type'), { [sequelize_1.Op.eq]: `${model.name}` }),
|
|
34
|
+
fieldType: sequelize_typescript_1.Sequelize.where(sequelize_typescript_1.Sequelize.col('field_type'), { [sequelize_1.Op.notIn]: customFieldsTypesToExclude }),
|
|
35
|
+
},
|
|
36
|
+
where: {
|
|
37
|
+
deleted_at: null,
|
|
38
|
+
},
|
|
39
|
+
},
|
|
35
40
|
],
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
41
|
+
on: {
|
|
42
|
+
value: sequelize_typescript_1.Sequelize.where(sequelize_typescript_1.Sequelize.cast(sequelize_typescript_1.Sequelize.col('value'), 'text'), { [sequelize_1.Op.iLike]: `%${searchTerm}%` }),
|
|
43
|
+
model_id: sequelize_typescript_1.Sequelize.where(sequelize_typescript_1.Sequelize.col('model_id'), { [sequelize_1.Op.eq]: sequelize_typescript_1.Sequelize.col(`${model.name}.id`) }),
|
|
44
|
+
},
|
|
45
|
+
}],
|
|
46
|
+
where: sequelize_typescript_1.Sequelize.where(sequelize_typescript_1.Sequelize.col('customFieldValue.model_id'), { [sequelize_1.Op.not]: null }),
|
|
47
|
+
});
|
|
40
48
|
exports.generateCustomFieldSearchQueryPayload = generateCustomFieldSearchQueryPayload;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@autofleet/sadot",
|
|
3
|
-
"version": "0.13.5-beta
|
|
3
|
+
"version": "0.13.5-beta.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -31,7 +31,6 @@
|
|
|
31
31
|
"@autofleet/common-types": "^4.4.0",
|
|
32
32
|
"@autofleet/events": "^4.0.0",
|
|
33
33
|
"ajv": "^8.12.0",
|
|
34
|
-
"ajv-errors": "^3.0.0",
|
|
35
34
|
"ajv-formats": "^3.0.1",
|
|
36
35
|
"http-status-codes": "^2.3.0",
|
|
37
36
|
"joi": "^17.7.0",
|
package/src/hooks/hooks.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import type { WhereOptions } from 'sequelize';
|
|
2
2
|
import Ajv from 'ajv';
|
|
3
|
-
import Joi
|
|
3
|
+
import Joi from 'joi';
|
|
4
4
|
import addFormats from 'ajv-formats';
|
|
5
5
|
import { BadRequest } from '@autofleet/errors';
|
|
6
|
-
import ajvErrors from 'ajv-errors';
|
|
7
6
|
import logger from '../utils/logger';
|
|
8
7
|
import * as ValidatorRepo from '../repository/validator';
|
|
9
8
|
import * as DefinitionRepo from '../repository/definition';
|
|
@@ -26,7 +25,6 @@ const ajv = new Ajv({
|
|
|
26
25
|
});
|
|
27
26
|
|
|
28
27
|
addFormats(ajv);
|
|
29
|
-
ajvErrors(ajv);
|
|
30
28
|
|
|
31
29
|
/**
|
|
32
30
|
* Helper function to manually copy object properties
|
|
@@ -78,29 +76,6 @@ const getCompleteCustomFields = async (instance, options): Promise<Record<string
|
|
|
78
76
|
return instance.customFields || {};
|
|
79
77
|
};
|
|
80
78
|
|
|
81
|
-
const formatAjvErrors = (
|
|
82
|
-
errors: {
|
|
83
|
-
instancePath?: string;
|
|
84
|
-
keyword: string;
|
|
85
|
-
message?: string;
|
|
86
|
-
params?: Record<string, any>;
|
|
87
|
-
}[],
|
|
88
|
-
): Record<string, string> => errors.reduce((acc, err) => {
|
|
89
|
-
const basePath = (err.instancePath || '')
|
|
90
|
-
.split('/')
|
|
91
|
-
.filter(Boolean)
|
|
92
|
-
.join('.')
|
|
93
|
-
.replace(/^after\./, '');
|
|
94
|
-
|
|
95
|
-
const missingProp = err.keyword === 'required' ? `.${err.params?.missingProperty}` : '';
|
|
96
|
-
const key = (basePath + missingProp).replace(/^\./, '') || 'root';
|
|
97
|
-
|
|
98
|
-
const message = err.message || 'Invalid value';
|
|
99
|
-
acc[key] = message;
|
|
100
|
-
|
|
101
|
-
return acc;
|
|
102
|
-
}, {} as Record<string, string>);
|
|
103
|
-
|
|
104
79
|
/**
|
|
105
80
|
* Validates the model using custom validators
|
|
106
81
|
*/
|
|
@@ -108,7 +83,6 @@ const validateModel = async (
|
|
|
108
83
|
instance,
|
|
109
84
|
options,
|
|
110
85
|
scopeAttributes: string[],
|
|
111
|
-
modelOptions: ModelOptions = {},
|
|
112
86
|
isCreate = false,
|
|
113
87
|
): Promise<void> => {
|
|
114
88
|
const modelType = instance.constructor.name;
|
|
@@ -150,9 +124,6 @@ const validateModel = async (
|
|
|
150
124
|
{
|
|
151
125
|
transaction: options.transaction,
|
|
152
126
|
attributes: CUSTOM_VALIDATOR_ATTRIBUTES_TO_PULL,
|
|
153
|
-
...(modelOptions.include && {
|
|
154
|
-
include: modelOptions.include?.(entityId),
|
|
155
|
-
}),
|
|
156
127
|
raw: true,
|
|
157
128
|
},
|
|
158
129
|
);
|
|
@@ -218,14 +189,7 @@ const validateModel = async (
|
|
|
218
189
|
const errorDetails = validateSchema.errors?.map((err) =>
|
|
219
190
|
`${(err as any).instancePath || ''} ${(err as any).message || 'Invalid value'}`).join(', ');
|
|
220
191
|
|
|
221
|
-
|
|
222
|
-
throw new BadRequest(
|
|
223
|
-
[new Error(`Validation failed for ${modelType}: ${errorDetails}`)],
|
|
224
|
-
undefined,
|
|
225
|
-
{
|
|
226
|
-
customError: formattedErrors,
|
|
227
|
-
},
|
|
228
|
-
);
|
|
192
|
+
throw new BadRequest([new Error(`Validation failed for ${modelType}: ${errorDetails}`)]);
|
|
229
193
|
}
|
|
230
194
|
}
|
|
231
195
|
} else {
|
|
@@ -260,14 +224,7 @@ const validateModel = async (
|
|
|
260
224
|
.errors
|
|
261
225
|
?.map((err) => `${(err as any).instancePath || ''} ${(err as any).message || 'Invalid value'}`).join(', ');
|
|
262
226
|
|
|
263
|
-
|
|
264
|
-
throw new BadRequest(
|
|
265
|
-
[new Error(`Validation failed for ${modelType}: ${errorDetails}`)],
|
|
266
|
-
undefined,
|
|
267
|
-
{
|
|
268
|
-
customError: formattedErrors,
|
|
269
|
-
},
|
|
270
|
-
);
|
|
227
|
+
throw new BadRequest([new Error(`Validation failed for ${modelType}: ${errorDetails}`)]);
|
|
271
228
|
}
|
|
272
229
|
}
|
|
273
230
|
}
|
|
@@ -364,7 +321,7 @@ export const beforeCreate = (
|
|
|
364
321
|
}
|
|
365
322
|
|
|
366
323
|
// Step 2: Validate the model data (including custom fields)
|
|
367
|
-
await validateModel(instance, options, scopeAttributes,
|
|
324
|
+
await validateModel(instance, options, scopeAttributes, true);
|
|
368
325
|
|
|
369
326
|
// format date and datetime fields
|
|
370
327
|
formatDates(fieldDefinitions, instance);
|
|
@@ -415,7 +372,7 @@ export const beforeUpdate = (
|
|
|
415
372
|
});
|
|
416
373
|
|
|
417
374
|
// Step 1: Validate the model data (including custom fields)
|
|
418
|
-
await validateModel(instance, options, scopeAttributes,
|
|
375
|
+
await validateModel(instance, options, scopeAttributes, false);
|
|
419
376
|
|
|
420
377
|
// format date and datetime fields
|
|
421
378
|
formatDates(fieldDefinitions, instance);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Transactionable } from 'sequelize';
|
|
2
2
|
import logger from '../utils/logger';
|
|
3
3
|
import { CustomValidator } from '../models';
|
|
4
4
|
|
|
@@ -6,7 +6,6 @@ export interface FindValidatorOptions extends Transactionable {
|
|
|
6
6
|
withDisabled?: boolean;
|
|
7
7
|
attributes?: string[];
|
|
8
8
|
raw?: boolean;
|
|
9
|
-
include?: IncludeOptions[];
|
|
10
9
|
}
|
|
11
10
|
|
|
12
11
|
// Make sure this interface is compatible with the Sequelize model
|
|
@@ -69,9 +68,7 @@ export const findAllByModelType = async (
|
|
|
69
68
|
return findAll(
|
|
70
69
|
{
|
|
71
70
|
modelType,
|
|
72
|
-
|
|
73
|
-
entityId,
|
|
74
|
-
}),
|
|
71
|
+
entityId,
|
|
75
72
|
},
|
|
76
73
|
options,
|
|
77
74
|
);
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
/* eslint-disable import/prefer-default-export */
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
type WhereOptions, Op, type IncludeOptions,
|
|
4
|
+
} from 'sequelize';
|
|
3
5
|
import { type ModelStatic, Sequelize } from 'sequelize-typescript';
|
|
4
6
|
import { randomInt } from 'node:crypto';
|
|
5
7
|
import { CustomFieldDefinitionType } from '../constants';
|
|
8
|
+
import { CustomFieldDefinition, CustomFieldValue } from '../../models';
|
|
6
9
|
|
|
7
10
|
/**
|
|
8
11
|
* Builds a WHERE clause and replacements for free-text search by custom fields.
|
|
@@ -17,13 +20,12 @@ import { CustomFieldDefinitionType } from '../constants';
|
|
|
17
20
|
* @param {CustomFieldDefinitionType[]} excludedCustomFieldsTypes - An array of custom field types
|
|
18
21
|
* to exclude from the search
|
|
19
22
|
*
|
|
20
|
-
* @returns {CustomFieldsSearchPayload} - An object containing the
|
|
21
|
-
* for Sequelize.
|
|
23
|
+
* @returns {CustomFieldsSearchPayload} - An object containing the INCLUDE clause and WHERE clause to add to query payload
|
|
22
24
|
*/
|
|
23
25
|
|
|
24
26
|
interface CustomFieldsSearchPayload {
|
|
25
27
|
where: WhereOptions;
|
|
26
|
-
|
|
28
|
+
include: IncludeOptions[];
|
|
27
29
|
}
|
|
28
30
|
|
|
29
31
|
export const generateRandomString = (length = 5): string => {
|
|
@@ -39,28 +41,33 @@ export const generateCustomFieldSearchQueryPayload = (
|
|
|
39
41
|
CustomFieldDefinitionType.DATETIME,
|
|
40
42
|
CustomFieldDefinitionType.DATE,
|
|
41
43
|
],
|
|
42
|
-
): CustomFieldsSearchPayload => {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
44
|
+
): CustomFieldsSearchPayload => ({
|
|
45
|
+
include: [{
|
|
46
|
+
attributes: ['value', 'model_id'],
|
|
47
|
+
model: CustomFieldValue,
|
|
48
|
+
as: 'customFieldValue',
|
|
49
|
+
required: false,
|
|
50
|
+
include: [
|
|
51
|
+
{
|
|
52
|
+
model: CustomFieldDefinition,
|
|
53
|
+
as: 'customFieldDefinition',
|
|
54
|
+
attributes: ['entity_id', 'field_type', 'model_type'],
|
|
55
|
+
required: true,
|
|
56
|
+
on: {
|
|
57
|
+
id: Sequelize.where(Sequelize.col('id'), { [Op.eq]: Sequelize.col('customFieldValue.custom_field_definition_id') }),
|
|
58
|
+
entityId: Sequelize.where(Sequelize.col('entity_id'), { [Op.eq]: `${entityId}` }),
|
|
59
|
+
modelType: Sequelize.where(Sequelize.col('model_type'), { [Op.eq]: `${model.name}` }),
|
|
60
|
+
fieldType: Sequelize.where(Sequelize.col('field_type'), { [Op.notIn]: customFieldsTypesToExclude }),
|
|
61
|
+
},
|
|
62
|
+
where: {
|
|
63
|
+
deleted_at: null,
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
on: {
|
|
68
|
+
value: Sequelize.where(Sequelize.cast(Sequelize.col('value'), 'text'), { [Op.iLike]: `%${searchTerm}%` }),
|
|
69
|
+
model_id: Sequelize.where(Sequelize.col('model_id'), { [Op.eq]: Sequelize.col(`${model.name}.id`) }),
|
|
63
70
|
},
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
};
|
|
71
|
+
}],
|
|
72
|
+
where: Sequelize.where(Sequelize.col('customFieldValue.model_id'), { [Op.not]: null }),
|
|
73
|
+
});
|