@autofleet/sadot 0.7.7-beta.0 → 0.7.7-beta.1
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/create.js +32 -16
- package/dist/repository/definition.d.ts +12 -6
- package/dist/repository/value.d.ts +1 -1
- package/dist/repository/value.js +5 -18
- package/dist/scopes/filter.js +10 -4
- package/package.json +1 -1
- package/src/hooks/create.ts +42 -24
- package/src/repository/definition.ts +15 -6
- package/src/repository/value.ts +4 -20
- package/src/scopes/filter.ts +12 -4
- package/coverage/clover.xml +0 -1073
- package/coverage/coverage-final.json +0 -44
- package/coverage/lcov-report/base.css +0 -224
- package/coverage/lcov-report/block-navigation.js +0 -87
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +0 -461
- package/coverage/lcov-report/prettify.css +0 -1
- package/coverage/lcov-report/prettify.js +0 -2
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +0 -196
- package/coverage/lcov-report/src/api/index.html +0 -116
- package/coverage/lcov-report/src/api/index.ts.html +0 -112
- package/coverage/lcov-report/src/api/v1/definition/index.html +0 -131
- package/coverage/lcov-report/src/api/v1/definition/index.ts.html +0 -406
- package/coverage/lcov-report/src/api/v1/definition/validations.ts.html +0 -310
- package/coverage/lcov-report/src/api/v1/errors.ts.html +0 -133
- package/coverage/lcov-report/src/api/v1/index.html +0 -131
- package/coverage/lcov-report/src/api/v1/index.ts.html +0 -112
- package/coverage/lcov-report/src/errors/index.html +0 -116
- package/coverage/lcov-report/src/errors/index.ts.html +0 -211
- package/coverage/lcov-report/src/events/index.html +0 -116
- package/coverage/lcov-report/src/events/index.ts.html +0 -238
- package/coverage/lcov-report/src/hooks/create.ts.html +0 -262
- package/coverage/lcov-report/src/hooks/enrich.ts.html +0 -523
- package/coverage/lcov-report/src/hooks/find.ts.html +0 -166
- package/coverage/lcov-report/src/hooks/index.html +0 -191
- package/coverage/lcov-report/src/hooks/index.ts.html +0 -130
- package/coverage/lcov-report/src/hooks/update.ts.html +0 -211
- package/coverage/lcov-report/src/hooks/workaround.ts.html +0 -226
- package/coverage/lcov-report/src/index.html +0 -116
- package/coverage/lcov-report/src/index.ts.html +0 -235
- package/coverage/lcov-report/src/models/CustomFieldDefinition.ts.html +0 -550
- package/coverage/lcov-report/src/models/CustomFieldValue.ts.html +0 -415
- package/coverage/lcov-report/src/models/index.html +0 -146
- package/coverage/lcov-report/src/models/index.ts.html +0 -406
- package/coverage/lcov-report/src/models/tests/AssociatedTestModel.ts.html +0 -256
- package/coverage/lcov-report/src/models/tests/TestModel.ts.html +0 -247
- package/coverage/lcov-report/src/models/tests/contextAwareModels/ContextAwareTestModel.ts.html +0 -214
- package/coverage/lcov-report/src/models/tests/contextAwareModels/ContextTestModel.ts.html +0 -199
- package/coverage/lcov-report/src/models/tests/contextAwareModels/index.html +0 -131
- package/coverage/lcov-report/src/models/tests/index.html +0 -131
- package/coverage/lcov-report/src/repository/definition.ts.html +0 -466
- package/coverage/lcov-report/src/repository/index.html +0 -131
- package/coverage/lcov-report/src/repository/value.ts.html +0 -523
- package/coverage/lcov-report/src/scopes/filter.ts.html +0 -637
- package/coverage/lcov-report/src/scopes/index.html +0 -131
- package/coverage/lcov-report/src/scopes/index.ts.html +0 -103
- package/coverage/lcov-report/src/tests/api/index.html +0 -116
- package/coverage/lcov-report/src/tests/api/test-api.ts.html +0 -199
- package/coverage/lcov-report/src/tests/functional/searching/index.html +0 -116
- package/coverage/lcov-report/src/tests/functional/searching/index.ts.html +0 -202
- package/coverage/lcov-report/src/tests/helpers/database-config.ts.html +0 -130
- package/coverage/lcov-report/src/tests/helpers/index.html +0 -131
- package/coverage/lcov-report/src/tests/helpers/index.ts.html +0 -142
- package/coverage/lcov-report/src/tests/mocks/definition.mock.ts.html +0 -310
- package/coverage/lcov-report/src/tests/mocks/events.mock.ts.html +0 -139
- package/coverage/lcov-report/src/tests/mocks/index.html +0 -146
- package/coverage/lcov-report/src/tests/mocks/testModel.ts.html +0 -196
- package/coverage/lcov-report/src/utils/constants/index.html +0 -116
- package/coverage/lcov-report/src/utils/constants/index.ts.html +0 -160
- package/coverage/lcov-report/src/utils/db/index.html +0 -116
- package/coverage/lcov-report/src/utils/db/index.ts.html +0 -148
- package/coverage/lcov-report/src/utils/helpers/index.html +0 -116
- package/coverage/lcov-report/src/utils/helpers/index.ts.html +0 -283
- package/coverage/lcov-report/src/utils/index.html +0 -131
- package/coverage/lcov-report/src/utils/init.ts.html +0 -430
- package/coverage/lcov-report/src/utils/logger/index.html +0 -116
- package/coverage/lcov-report/src/utils/logger/index.ts.html +0 -100
- package/coverage/lcov-report/src/utils/scopeAttributes.ts.html +0 -121
- package/coverage/lcov-report/src/utils/validations/index.html +0 -116
- package/coverage/lcov-report/src/utils/validations/index.ts.html +0 -151
- package/coverage/lcov-report/src/utils/validations/schema/custom-fields.ts.html +0 -109
- package/coverage/lcov-report/src/utils/validations/schema/index.html +0 -116
- package/coverage/lcov-report/src/utils/validations/validators/index.html +0 -146
- package/coverage/lcov-report/src/utils/validations/validators/index.ts.html +0 -199
- package/coverage/lcov-report/src/utils/validations/validators/select.validator.ts.html +0 -118
- package/coverage/lcov-report/src/utils/validations/validators/status.validator.ts.html +0 -139
- package/coverage/lcov.info +0 -1818
package/dist/hooks/create.js
CHANGED
|
@@ -48,27 +48,43 @@ exports.beforeBulkCreate = beforeBulkCreate;
|
|
|
48
48
|
const beforeCreate = (scopeAttributes, modelOptions = {}) => async (instance, options) => {
|
|
49
49
|
logger_1.default.debug('sadot - before create hook');
|
|
50
50
|
const { fields } = options;
|
|
51
|
+
const { include, useEntityIdFromInclude } = modelOptions;
|
|
51
52
|
const modelType = instance.constructor.name;
|
|
52
53
|
const identifiers = (0, scopeAttributes_1.default)(instance, scopeAttributes);
|
|
53
|
-
|
|
54
|
-
|
|
54
|
+
const where = {
|
|
55
|
+
modelType,
|
|
56
|
+
disabled: false,
|
|
57
|
+
...(!useEntityIdFromInclude && { entityId: identifiers }),
|
|
58
|
+
};
|
|
59
|
+
const fieldDefinitions = await DefinitionRepo.findAll(where, { withDisabled: false, transaction: options.transaction, include: include?.(identifiers) });
|
|
60
|
+
const requiredFieldsNames = Array.from(new Set(fieldDefinitions.filter(({ required }) => required).map(({ name }) => name)));
|
|
55
61
|
const customFieldsIdx = fields.indexOf('customFields');
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
throw new errors_1.MissingRequiredCustomFieldError(missingFields);
|
|
62
|
-
}
|
|
63
|
-
await ValueRepo.updateValues(modelType, instance.id, identifiers, customFields, {
|
|
64
|
-
transaction: options.transaction,
|
|
65
|
-
modelOptions,
|
|
66
|
-
}, true);
|
|
62
|
+
if ((customFieldsIdx === -1 || !instance.customFields) && requiredFieldsNames?.length > 0) {
|
|
63
|
+
throw new errors_1.MissingRequiredCustomFieldError(requiredFieldsNames);
|
|
64
|
+
}
|
|
65
|
+
const fieldsWithDefaultValue = fieldDefinitions.filter((def) => ![null, undefined].includes(def.defaultValue));
|
|
66
|
+
if (fieldsWithDefaultValue.length) {
|
|
67
67
|
// eslint-disable-next-line no-param-reassign
|
|
68
|
-
|
|
68
|
+
instance.customFields || (instance.customFields = {});
|
|
69
|
+
fieldsWithDefaultValue.filter((def) => !(def.name in instance.customFields)).forEach(({ name, defaultValue }) => {
|
|
70
|
+
// eslint-disable-next-line no-param-reassign
|
|
71
|
+
instance.customFields[name] = defaultValue;
|
|
72
|
+
});
|
|
69
73
|
}
|
|
70
|
-
|
|
71
|
-
|
|
74
|
+
const { customFields } = instance;
|
|
75
|
+
if (customFieldsIdx === -1 || !customFields) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const fieldsNames = Object.keys(customFields);
|
|
79
|
+
const missingFields = requiredFieldsNames.filter((name) => !fieldsNames.includes(name));
|
|
80
|
+
if (missingFields?.length > 0) {
|
|
81
|
+
throw new errors_1.MissingRequiredCustomFieldError(missingFields);
|
|
72
82
|
}
|
|
83
|
+
await ValueRepo.updateValues(modelType, instance.id, identifiers, customFields, {
|
|
84
|
+
transaction: options.transaction,
|
|
85
|
+
modelOptions,
|
|
86
|
+
});
|
|
87
|
+
// eslint-disable-next-line no-param-reassign
|
|
88
|
+
fields.splice(customFieldsIdx, 1);
|
|
73
89
|
};
|
|
74
90
|
exports.beforeCreate = beforeCreate;
|
|
@@ -1,20 +1,26 @@
|
|
|
1
|
-
import { type FindOptions, type WhereOptions } from 'sequelize';
|
|
1
|
+
import { type Includeable, type Transaction, type FindOptions, type WhereOptions } from 'sequelize';
|
|
2
2
|
import { CustomFieldDefinition } from '../models';
|
|
3
3
|
import type { CreateCustomFieldDefinition, UpdateCustomFieldDefinition } from '../types/definition';
|
|
4
4
|
import type { ModelOptions } from '../types';
|
|
5
5
|
export declare const create: (data: CreateCustomFieldDefinition) => Promise<CustomFieldDefinition>;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
interface SadotFindOptions {
|
|
7
|
+
withDisabled?: boolean;
|
|
8
|
+
transaction?: Transaction;
|
|
9
|
+
include?: Includeable | Includeable[];
|
|
10
|
+
}
|
|
11
|
+
export declare const findAll: (where: WhereOptions, options?: SadotFindOptions) => Promise<CustomFieldDefinition[]>;
|
|
12
|
+
export declare const findByIds: (ids: string[], options?: SadotFindOptions) => Promise<CustomFieldDefinition[]>;
|
|
13
|
+
export declare const findById: (id: string, options?: Pick<SadotFindOptions, 'withDisabled'>) => Promise<CustomFieldDefinition | null>;
|
|
9
14
|
export declare const findByEntityIds: (modelType: string, entityIds: string[], options?: FindOptions & {
|
|
10
15
|
modelOptions?: ModelOptions;
|
|
11
16
|
}) => Promise<CustomFieldDefinition[]>;
|
|
12
17
|
export declare const findByWhere: (where: any) => Promise<CustomFieldDefinition | null>;
|
|
13
18
|
export declare const findDefinitionsByModels: (modelTypes: string[], options?: any) => Promise<CustomFieldDefinition[]>;
|
|
14
19
|
export declare const update: (id: string, data: UpdateCustomFieldDefinition) => Promise<CustomFieldDefinition>;
|
|
15
|
-
export declare const disable: (id: string) => Promise<
|
|
16
|
-
export declare const destroy: (id: string) => Promise<
|
|
20
|
+
export declare const disable: (id: string) => Promise<[affectedCount: number]>;
|
|
21
|
+
export declare const destroy: (id: string) => Promise<number>;
|
|
17
22
|
/**
|
|
18
23
|
* Return the names of the required fields for a given model
|
|
19
24
|
*/
|
|
20
25
|
export declare const getRequiredFields: (modelType: string, modelId: string | string[], entityId: string | string[], modelOptions?: ModelOptions) => Promise<string[]>;
|
|
26
|
+
export {};
|
|
@@ -24,5 +24,5 @@ export declare const findValuesByModelIds: (modelIds: string[], options?: any) =
|
|
|
24
24
|
*/
|
|
25
25
|
export declare const updateValues: (modelType: string, modelId: string, identifiers: string[], valuesToUpdate: ValuesToUpdate, options?: FindOptions & {
|
|
26
26
|
modelOptions?: ModelOptions;
|
|
27
|
-
}
|
|
27
|
+
}) => Promise<CustomFieldValue[]>;
|
|
28
28
|
export declare const deleteValue: (id: string, options?: any) => Promise<any>;
|
package/dist/repository/value.js
CHANGED
|
@@ -84,7 +84,7 @@ const formatFunctions = {
|
|
|
84
84
|
* Create new value record if not exists, but fails if value's definition not exist.
|
|
85
85
|
* Return the updated values
|
|
86
86
|
*/
|
|
87
|
-
const updateValues = async (modelType, modelId, identifiers, valuesToUpdate, options = {}
|
|
87
|
+
const updateValues = async (modelType, modelId, identifiers, valuesToUpdate, options = {}) => {
|
|
88
88
|
const names = Object.keys(valuesToUpdate);
|
|
89
89
|
logger_1.default.debug(`custom-fields: updating values for ${modelType} ${modelId}`, {
|
|
90
90
|
names,
|
|
@@ -96,11 +96,9 @@ const updateValues = async (modelType, modelId, identifiers, valuesToUpdate, opt
|
|
|
96
96
|
const where = {
|
|
97
97
|
modelType,
|
|
98
98
|
name: names,
|
|
99
|
+
...(!options.modelOptions?.useEntityIdFromInclude && { entityId: identifiers }),
|
|
99
100
|
};
|
|
100
|
-
|
|
101
|
-
where.entityId = identifiers;
|
|
102
|
-
}
|
|
103
|
-
const fieldDefinitions = await DefinitionRepo.findAll(where, { withDisabled: true, transaction, include: modelOptions.include?.(identifiers) }) || [];
|
|
101
|
+
const fieldDefinitions = await DefinitionRepo.findAll(where, { withDisabled: true, transaction, include: modelOptions.include?.(identifiers) }) ?? [];
|
|
104
102
|
const disabledDefinitions = fieldDefinitions.filter((def) => def.disabled);
|
|
105
103
|
if (fieldDefinitions.length !== names.length) {
|
|
106
104
|
logger_1.default.warn(`custom-fields: missing definitions for ${modelType} ${modelId}`, { names, fieldDefinitions });
|
|
@@ -112,28 +110,17 @@ const updateValues = async (modelType, modelId, identifiers, valuesToUpdate, opt
|
|
|
112
110
|
if (valuesWithDisabledDefinitions?.length > 0) {
|
|
113
111
|
logger_1.default.warn(`custom-fields: trying to update disabled values: ${valuesWithDisabledDefinitions.join(', ')}`);
|
|
114
112
|
}
|
|
115
|
-
const visitedFields = new Set();
|
|
116
113
|
const values = names.map((name) => {
|
|
117
114
|
const fieldDefinition = fieldDefinitions.find((def) => def.name === name);
|
|
118
|
-
visitedFields.add(fieldDefinition);
|
|
119
115
|
const formatFunction = formatFunctions[fieldDefinition.fieldType];
|
|
116
|
+
const value = formatFunction ? formatFunction(valuesToUpdate[name]) : valuesToUpdate[name];
|
|
120
117
|
return {
|
|
121
118
|
modelId,
|
|
122
|
-
value: (formatFunction ? formatFunction(valuesToUpdate[name]) : valuesToUpdate[name]) ?? fieldDefinition.defaultValue,
|
|
123
119
|
updatedAt: new Date(),
|
|
124
120
|
customFieldDefinitionId: fieldDefinition.id,
|
|
121
|
+
value: value !== undefined ? value : fieldDefinition.defaultValue,
|
|
125
122
|
};
|
|
126
123
|
});
|
|
127
|
-
if (defineAllDefaults) {
|
|
128
|
-
fieldDefinitions.filter((def) => !visitedFields.has(def) && ![null, undefined].includes(def.defaultValue)).forEach(({ id, defaultValue }) => {
|
|
129
|
-
values.push({
|
|
130
|
-
modelId,
|
|
131
|
-
value: defaultValue,
|
|
132
|
-
updatedAt: new Date(),
|
|
133
|
-
customFieldDefinitionId: id,
|
|
134
|
-
});
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
124
|
return Promise.all(values.map(async (value) => {
|
|
138
125
|
const [cfv] = await models_1.CustomFieldValue.upsert(value, {
|
|
139
126
|
transaction: options.transaction,
|
package/dist/scopes/filter.js
CHANGED
|
@@ -21,6 +21,12 @@ const castIfNeeded = (conditionValue) => {
|
|
|
21
21
|
}
|
|
22
22
|
return '';
|
|
23
23
|
};
|
|
24
|
+
const addQuotationIfNeeded = (conditionValue, valRep) => {
|
|
25
|
+
if (typeof conditionValue === 'string') {
|
|
26
|
+
return `'"' || :${valRep} || '"'`;
|
|
27
|
+
}
|
|
28
|
+
return `:${valRep}`;
|
|
29
|
+
};
|
|
24
30
|
const AND_DELIMETER = ' AND ';
|
|
25
31
|
const OR_DELIMETER = ' OR ';
|
|
26
32
|
const CD_TABLE_ALIAS = 'cd';
|
|
@@ -53,23 +59,23 @@ const customFieldsFilterScope = (name) => ({ replacementsMap: replacements, scop
|
|
|
53
59
|
if (typeof condition[0] === 'string') {
|
|
54
60
|
const values = condition.map((v) => {
|
|
55
61
|
const valRandom = Object.keys(replacements).find((randomString) => replacements[randomString] === v);
|
|
56
|
-
return
|
|
62
|
+
return addQuotationIfNeeded(v, valRandom);
|
|
57
63
|
}).join(',');
|
|
58
64
|
return `(${columnCondition} AND ${CV_VALUE_COLUMN} IN ( ${values} ))`;
|
|
59
65
|
}
|
|
60
66
|
return condition
|
|
61
67
|
.map((c) => {
|
|
62
68
|
const valRep = Object.keys(replacements).find((replacementKey) => replacements[replacementKey] === c.value);
|
|
63
|
-
return `( ${columnCondition} AND ${CV_VALUE_COLUMN}${castIfNeeded(c.value)} ${c.operator}
|
|
69
|
+
return `( ${columnCondition} AND ${CV_VALUE_COLUMN}${castIfNeeded(c.value)} ${c.operator} ${addQuotationIfNeeded(c.value, valRep)} )`;
|
|
64
70
|
}).join(AND_DELIMETER);
|
|
65
71
|
}
|
|
66
72
|
if (typeof condition === 'string' || typeof condition === 'number') {
|
|
67
73
|
const conditionRep = Object.keys(replacements).find((replacementKey) => replacements[replacementKey] === condition);
|
|
68
|
-
return `(${columnCondition} AND ${CV_VALUE_COLUMN}${castIfNeeded(condition)} =
|
|
74
|
+
return `(${columnCondition} AND ${CV_VALUE_COLUMN}${castIfNeeded(condition)} = ${addQuotationIfNeeded(condition, conditionRep)})`;
|
|
69
75
|
}
|
|
70
76
|
if (condition?.operator) {
|
|
71
77
|
const valueRep = Object.keys(replacements).find((replacementKey) => replacements[replacementKey] === condition.value);
|
|
72
|
-
return `( ${columnCondition} AND ${CV_VALUE_COLUMN}${castIfNeeded(condition.value)} ${condition.operator}
|
|
78
|
+
return `( ${columnCondition} AND ${CV_VALUE_COLUMN}${castIfNeeded(condition.value)} ${condition.operator} ${addQuotationIfNeeded(condition.value, valueRep)})`;
|
|
73
79
|
}
|
|
74
80
|
return false;
|
|
75
81
|
})
|
package/package.json
CHANGED
package/src/hooks/create.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { WhereOptions } from 'sequelize';
|
|
1
2
|
import logger from '../utils/logger';
|
|
2
3
|
import * as ValueRepo from '../repository/value';
|
|
3
4
|
import * as DefinitionRepo from '../repository/definition';
|
|
@@ -23,37 +24,54 @@ export const beforeCreate = (scopeAttributes: string[], modelOptions: ModelOptio
|
|
|
23
24
|
): Promise<void> => {
|
|
24
25
|
logger.debug('sadot - before create hook');
|
|
25
26
|
const { fields } = options;
|
|
27
|
+
const { include, useEntityIdFromInclude } = modelOptions;
|
|
26
28
|
const modelType = instance.constructor.name;
|
|
27
29
|
|
|
28
30
|
const identifiers = applyScopeToInstance(instance, scopeAttributes);
|
|
29
31
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
const where: WhereOptions = {
|
|
33
|
+
modelType,
|
|
34
|
+
disabled: false,
|
|
35
|
+
...(!useEntityIdFromInclude && { entityId: identifiers }),
|
|
36
|
+
};
|
|
37
|
+
const fieldDefinitions = await DefinitionRepo.findAll(where, { withDisabled: false, transaction: options.transaction, include: include?.(identifiers) });
|
|
38
|
+
const requiredFieldsNames = Array.from(new Set(fieldDefinitions.filter(({ required }) => required).map(({ name }) => name)));
|
|
32
39
|
|
|
33
40
|
const customFieldsIdx = fields.indexOf('customFields');
|
|
34
|
-
const { customFields } = instance;
|
|
35
|
-
if (customFieldsIdx > -1 && customFields) {
|
|
36
|
-
const fieldsNames = Object.keys(customFields);
|
|
37
|
-
const missingFields = requiredFieldsNames.filter((name) => !fieldsNames.includes(name));
|
|
38
|
-
if (missingFields?.length > 0) {
|
|
39
|
-
throw new MissingRequiredCustomFieldError(missingFields);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
await ValueRepo.updateValues(
|
|
43
|
-
modelType,
|
|
44
|
-
instance.id,
|
|
45
|
-
identifiers,
|
|
46
|
-
customFields,
|
|
47
|
-
{
|
|
48
|
-
transaction: options.transaction,
|
|
49
|
-
modelOptions,
|
|
50
|
-
},
|
|
51
|
-
true,
|
|
52
|
-
);
|
|
53
41
|
|
|
54
|
-
|
|
55
|
-
fields.splice(customFieldsIdx, 1);
|
|
56
|
-
} else if (requiredFieldsNames?.length > 0) {
|
|
42
|
+
if ((customFieldsIdx === -1 || !instance.customFields) && requiredFieldsNames?.length > 0) {
|
|
57
43
|
throw new MissingRequiredCustomFieldError(requiredFieldsNames);
|
|
58
44
|
}
|
|
45
|
+
const fieldsWithDefaultValue = fieldDefinitions.filter((def) => ![null, undefined].includes(def.defaultValue));
|
|
46
|
+
if (fieldsWithDefaultValue.length) {
|
|
47
|
+
// eslint-disable-next-line no-param-reassign
|
|
48
|
+
instance.customFields ||= {};
|
|
49
|
+
fieldsWithDefaultValue.filter((def) => !(def.name in instance.customFields)).forEach(({ name, defaultValue }) => {
|
|
50
|
+
// eslint-disable-next-line no-param-reassign
|
|
51
|
+
instance.customFields[name] = defaultValue;
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
const { customFields } = instance;
|
|
55
|
+
if (customFieldsIdx === -1 || !customFields) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const fieldsNames = Object.keys(customFields);
|
|
59
|
+
const missingFields = requiredFieldsNames.filter((name) => !fieldsNames.includes(name));
|
|
60
|
+
if (missingFields?.length > 0) {
|
|
61
|
+
throw new MissingRequiredCustomFieldError(missingFields);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
await ValueRepo.updateValues(
|
|
65
|
+
modelType,
|
|
66
|
+
instance.id,
|
|
67
|
+
identifiers,
|
|
68
|
+
customFields,
|
|
69
|
+
{
|
|
70
|
+
transaction: options.transaction,
|
|
71
|
+
modelOptions,
|
|
72
|
+
},
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
// eslint-disable-next-line no-param-reassign
|
|
76
|
+
fields.splice(customFieldsIdx, 1);
|
|
59
77
|
};
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
Op,
|
|
3
|
+
type Includeable, type Transaction, type FindOptions, type WhereOptions,
|
|
4
|
+
} from 'sequelize';
|
|
2
5
|
import { CustomFieldDefinition } from '../models';
|
|
3
6
|
import type { CreateCustomFieldDefinition, UpdateCustomFieldDefinition } from '../types/definition';
|
|
4
7
|
import type { ModelOptions } from '../types';
|
|
@@ -6,9 +9,15 @@ import type { ModelOptions } from '../types';
|
|
|
6
9
|
export const create = (data: CreateCustomFieldDefinition): Promise<CustomFieldDefinition> =>
|
|
7
10
|
CustomFieldDefinition.create(data);
|
|
8
11
|
|
|
12
|
+
interface SadotFindOptions {
|
|
13
|
+
withDisabled?: boolean;
|
|
14
|
+
transaction?: Transaction;
|
|
15
|
+
include?: Includeable | Includeable[];
|
|
16
|
+
}
|
|
17
|
+
|
|
9
18
|
export const findAll = (
|
|
10
19
|
where: WhereOptions,
|
|
11
|
-
options:
|
|
20
|
+
options: SadotFindOptions = { withDisabled: false },
|
|
12
21
|
): Promise<CustomFieldDefinition[]> => {
|
|
13
22
|
const queryModel = options.withDisabled
|
|
14
23
|
? CustomFieldDefinition.unscoped()
|
|
@@ -24,12 +33,12 @@ export const findAll = (
|
|
|
24
33
|
|
|
25
34
|
export const findByIds = (
|
|
26
35
|
ids: string[],
|
|
27
|
-
options:
|
|
36
|
+
options: SadotFindOptions = { withDisabled: false },
|
|
28
37
|
): Promise<CustomFieldDefinition[]> => findAll({ id: { [Op.in]: ids } }, options);
|
|
29
38
|
|
|
30
39
|
export const findById = (
|
|
31
40
|
id: string,
|
|
32
|
-
options:
|
|
41
|
+
options: Pick<SadotFindOptions, 'withDisabled'> = { withDisabled: false },
|
|
33
42
|
): Promise<CustomFieldDefinition | null> => {
|
|
34
43
|
const { withDisabled } = options;
|
|
35
44
|
if (withDisabled) {
|
|
@@ -87,13 +96,13 @@ export const update = async (
|
|
|
87
96
|
return updatedDefinition;
|
|
88
97
|
};
|
|
89
98
|
|
|
90
|
-
export const disable = (id: string): Promise<
|
|
99
|
+
export const disable = (id: string): Promise<[affectedCount: number]> =>
|
|
91
100
|
CustomFieldDefinition.update(
|
|
92
101
|
{ disabled: true },
|
|
93
102
|
{ where: { id } },
|
|
94
103
|
);
|
|
95
104
|
|
|
96
|
-
export const destroy = (id: string): Promise<
|
|
105
|
+
export const destroy = (id: string): Promise<number> =>
|
|
97
106
|
CustomFieldDefinition.destroy({ where: { id } });
|
|
98
107
|
|
|
99
108
|
/**
|
package/src/repository/value.ts
CHANGED
|
@@ -67,7 +67,6 @@ export const updateValues = async (
|
|
|
67
67
|
identifiers: string[],
|
|
68
68
|
valuesToUpdate: ValuesToUpdate,
|
|
69
69
|
options: FindOptions & { modelOptions?: ModelOptions } = {},
|
|
70
|
-
defineAllDefaults = false,
|
|
71
70
|
): Promise<CustomFieldValue[]> => {
|
|
72
71
|
const names = Object.keys(valuesToUpdate);
|
|
73
72
|
logger.debug(`custom-fields: updating values for ${modelType} ${modelId}`, {
|
|
@@ -81,12 +80,10 @@ export const updateValues = async (
|
|
|
81
80
|
const where: WhereOptions = {
|
|
82
81
|
modelType,
|
|
83
82
|
name: names,
|
|
83
|
+
...(!options.modelOptions?.useEntityIdFromInclude && { entityId: identifiers }),
|
|
84
84
|
};
|
|
85
85
|
|
|
86
|
-
|
|
87
|
-
where.entityId = identifiers;
|
|
88
|
-
}
|
|
89
|
-
const fieldDefinitions = await DefinitionRepo.findAll(where, { withDisabled: true, transaction, include: modelOptions.include?.(identifiers) }) || [];
|
|
86
|
+
const fieldDefinitions = await DefinitionRepo.findAll(where, { withDisabled: true, transaction, include: modelOptions.include?.(identifiers) }) ?? [];
|
|
90
87
|
|
|
91
88
|
const disabledDefinitions = fieldDefinitions.filter((def) => def.disabled);
|
|
92
89
|
if (fieldDefinitions.length !== names.length) {
|
|
@@ -101,31 +98,18 @@ export const updateValues = async (
|
|
|
101
98
|
logger.warn(`custom-fields: trying to update disabled values: ${valuesWithDisabledDefinitions.join(', ')}`);
|
|
102
99
|
}
|
|
103
100
|
|
|
104
|
-
const visitedFields = new Set<CustomFieldDefinition>();
|
|
105
|
-
|
|
106
101
|
const values: CreateCustomFieldValue[] = names.map((name) => {
|
|
107
102
|
const fieldDefinition = fieldDefinitions.find((def) => def.name === name);
|
|
108
|
-
visitedFields.add(fieldDefinition);
|
|
109
103
|
const formatFunction = formatFunctions[fieldDefinition.fieldType];
|
|
104
|
+
const value = formatFunction ? formatFunction(valuesToUpdate[name]) : valuesToUpdate[name];
|
|
110
105
|
return {
|
|
111
106
|
modelId,
|
|
112
|
-
value: (formatFunction ? formatFunction(valuesToUpdate[name]) : valuesToUpdate[name]) ?? fieldDefinition.defaultValue,
|
|
113
107
|
updatedAt: new Date(),
|
|
114
108
|
customFieldDefinitionId: fieldDefinition.id,
|
|
109
|
+
value: value !== undefined ? value : fieldDefinition.defaultValue,
|
|
115
110
|
};
|
|
116
111
|
});
|
|
117
112
|
|
|
118
|
-
if (defineAllDefaults) {
|
|
119
|
-
fieldDefinitions.filter((def) => !visitedFields.has(def) && ![null, undefined].includes(def.defaultValue)).forEach(({ id, defaultValue }) => {
|
|
120
|
-
values.push({
|
|
121
|
-
modelId,
|
|
122
|
-
value: defaultValue,
|
|
123
|
-
updatedAt: new Date(),
|
|
124
|
-
customFieldDefinitionId: id,
|
|
125
|
-
});
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
|
-
|
|
129
113
|
return Promise.all(values.map(async (value) => {
|
|
130
114
|
const [cfv] = await CustomFieldValue.upsert(value, {
|
|
131
115
|
transaction: options.transaction,
|
package/src/scopes/filter.ts
CHANGED
|
@@ -44,6 +44,14 @@ const castIfNeeded = (conditionValue: string): string => {
|
|
|
44
44
|
}
|
|
45
45
|
return '';
|
|
46
46
|
};
|
|
47
|
+
|
|
48
|
+
const addQuotationIfNeeded = (conditionValue: string, valRep: string): string => {
|
|
49
|
+
if (typeof conditionValue === 'string') {
|
|
50
|
+
return `'"' || :${valRep} || '"'`;
|
|
51
|
+
}
|
|
52
|
+
return `:${valRep}`;
|
|
53
|
+
};
|
|
54
|
+
|
|
47
55
|
const AND_DELIMETER = ' AND ';
|
|
48
56
|
const OR_DELIMETER = ' OR ';
|
|
49
57
|
|
|
@@ -90,7 +98,7 @@ export const customFieldsFilterScope = (
|
|
|
90
98
|
const valRandom = Object.keys(replacements).find(
|
|
91
99
|
(randomString) => replacements[randomString] === v,
|
|
92
100
|
);
|
|
93
|
-
return
|
|
101
|
+
return addQuotationIfNeeded(v, valRandom);
|
|
94
102
|
}).join(',');
|
|
95
103
|
return `(${columnCondition} AND ${CV_VALUE_COLUMN} IN ( ${values} ))`;
|
|
96
104
|
}
|
|
@@ -99,20 +107,20 @@ export const customFieldsFilterScope = (
|
|
|
99
107
|
const valRep = Object.keys(replacements).find(
|
|
100
108
|
(replacementKey) => replacements[replacementKey] === c.value,
|
|
101
109
|
);
|
|
102
|
-
return `( ${columnCondition} AND ${CV_VALUE_COLUMN}${castIfNeeded(c.value)} ${c.operator}
|
|
110
|
+
return `( ${columnCondition} AND ${CV_VALUE_COLUMN}${castIfNeeded(c.value)} ${c.operator} ${addQuotationIfNeeded(c.value, valRep)} )`;
|
|
103
111
|
}).join(AND_DELIMETER);
|
|
104
112
|
}
|
|
105
113
|
if (typeof condition === 'string' || typeof condition === 'number') {
|
|
106
114
|
const conditionRep = Object.keys(replacements).find(
|
|
107
115
|
(replacementKey) => replacements[replacementKey] === condition,
|
|
108
116
|
);
|
|
109
|
-
return `(${columnCondition} AND ${CV_VALUE_COLUMN}${castIfNeeded(condition)} =
|
|
117
|
+
return `(${columnCondition} AND ${CV_VALUE_COLUMN}${castIfNeeded(condition)} = ${addQuotationIfNeeded(condition, conditionRep)})`;
|
|
110
118
|
}
|
|
111
119
|
if (condition?.operator) {
|
|
112
120
|
const valueRep = Object.keys(replacements).find(
|
|
113
121
|
(replacementKey) => replacements[replacementKey] === condition.value,
|
|
114
122
|
);
|
|
115
|
-
return `( ${columnCondition} AND ${CV_VALUE_COLUMN}${castIfNeeded(condition.value)} ${condition.operator}
|
|
123
|
+
return `( ${columnCondition} AND ${CV_VALUE_COLUMN}${castIfNeeded(condition.value)} ${condition.operator} ${addQuotationIfNeeded(condition.value, valueRep)})`;
|
|
116
124
|
}
|
|
117
125
|
return false;
|
|
118
126
|
},
|