@autofleet/sadot 0.13.5-beta-3 → 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 -24
- 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 +4 -43
- 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,8 +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, formattedErrors);
|
|
176
|
+
throw new errors_1.BadRequest([new Error(`Validation failed for ${modelType}: ${errorDetails}`)]);
|
|
195
177
|
}
|
|
196
178
|
}
|
|
197
179
|
}
|
|
@@ -220,8 +202,7 @@ const validateModel = async (instance, options, scopeAttributes, modelOptions =
|
|
|
220
202
|
const errorDetails = validateSchema
|
|
221
203
|
.errors
|
|
222
204
|
?.map((err) => `${err.instancePath || ''} ${err.message || 'Invalid value'}`).join(', ');
|
|
223
|
-
|
|
224
|
-
throw new errors_1.BadRequest([new Error(`Validation failed for ${modelType}: ${errorDetails}`)], undefined, formattedErrors);
|
|
205
|
+
throw new errors_1.BadRequest([new Error(`Validation failed for ${modelType}: ${errorDetails}`)]);
|
|
225
206
|
}
|
|
226
207
|
}
|
|
227
208
|
}
|
|
@@ -289,7 +270,7 @@ const beforeCreate = (scopeAttributes, modelOptions = {}, sadotOptions = { useCu
|
|
|
289
270
|
throw new errors_2.MissingRequiredCustomFieldError(missingFields);
|
|
290
271
|
}
|
|
291
272
|
// Step 2: Validate the model data (including custom fields)
|
|
292
|
-
await validateModel(instance, options, scopeAttributes,
|
|
273
|
+
await validateModel(instance, options, scopeAttributes, true);
|
|
293
274
|
// format date and datetime fields
|
|
294
275
|
formatDates(fieldDefinitions, instance);
|
|
295
276
|
// Step 3: Save custom field values if they exist
|
|
@@ -327,7 +308,7 @@ const beforeUpdate = (scopeAttributes, modelOptions = {}, sadotOptions = { useCu
|
|
|
327
308
|
modelType, modelOptions, identifiers, options,
|
|
328
309
|
});
|
|
329
310
|
// Step 1: Validate the model data (including custom fields)
|
|
330
|
-
await validateModel(instance, options, scopeAttributes,
|
|
311
|
+
await validateModel(instance, options, scopeAttributes, false);
|
|
331
312
|
// format date and datetime fields
|
|
332
313
|
formatDates(fieldDefinitions, instance);
|
|
333
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
|
@@ -3,7 +3,6 @@ import Ajv from 'ajv';
|
|
|
3
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,12 +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
|
-
formattedErrors,
|
|
226
|
-
);
|
|
192
|
+
throw new BadRequest([new Error(`Validation failed for ${modelType}: ${errorDetails}`)]);
|
|
227
193
|
}
|
|
228
194
|
}
|
|
229
195
|
} else {
|
|
@@ -258,12 +224,7 @@ const validateModel = async (
|
|
|
258
224
|
.errors
|
|
259
225
|
?.map((err) => `${(err as any).instancePath || ''} ${(err as any).message || 'Invalid value'}`).join(', ');
|
|
260
226
|
|
|
261
|
-
|
|
262
|
-
throw new BadRequest(
|
|
263
|
-
[new Error(`Validation failed for ${modelType}: ${errorDetails}`)],
|
|
264
|
-
undefined,
|
|
265
|
-
formattedErrors,
|
|
266
|
-
);
|
|
227
|
+
throw new BadRequest([new Error(`Validation failed for ${modelType}: ${errorDetails}`)]);
|
|
267
228
|
}
|
|
268
229
|
}
|
|
269
230
|
}
|
|
@@ -360,7 +321,7 @@ export const beforeCreate = (
|
|
|
360
321
|
}
|
|
361
322
|
|
|
362
323
|
// Step 2: Validate the model data (including custom fields)
|
|
363
|
-
await validateModel(instance, options, scopeAttributes,
|
|
324
|
+
await validateModel(instance, options, scopeAttributes, true);
|
|
364
325
|
|
|
365
326
|
// format date and datetime fields
|
|
366
327
|
formatDates(fieldDefinitions, instance);
|
|
@@ -411,7 +372,7 @@ export const beforeUpdate = (
|
|
|
411
372
|
});
|
|
412
373
|
|
|
413
374
|
// Step 1: Validate the model data (including custom fields)
|
|
414
|
-
await validateModel(instance, options, scopeAttributes,
|
|
375
|
+
await validateModel(instance, options, scopeAttributes, false);
|
|
415
376
|
|
|
416
377
|
// format date and datetime fields
|
|
417
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
|
+
});
|