@steedos/objectql 2.2.50 → 2.2.51-beta.4

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.
Files changed (143) hide show
  1. package/lib/services/helpers/graphql/consts.d.ts +17 -0
  2. package/lib/services/helpers/graphql/consts.js +28 -0
  3. package/lib/services/helpers/graphql/consts.js.map +1 -0
  4. package/lib/services/helpers/graphql/getQueryFields.js +17 -2
  5. package/lib/services/helpers/graphql/getQueryFields.js.map +1 -1
  6. package/lib/services/helpers/graphql/index.d.ts +1 -1
  7. package/lib/services/helpers/graphql/index.js +31 -46
  8. package/lib/services/helpers/graphql/index.js.map +1 -1
  9. package/lib/util/index.js +7 -0
  10. package/lib/util/index.js.map +1 -1
  11. package/package.json +11 -12
  12. package/src/actions/field_updates.ts +0 -118
  13. package/src/actions/index.ts +0 -3
  14. package/src/actions/types/field_update_target.ts +0 -7
  15. package/src/actions/types/workflow_notification.ts +0 -9
  16. package/src/actions/types/workflow_rule.ts +0 -11
  17. package/src/actions/workflow_notifications.ts +0 -81
  18. package/src/actions/workflow_rule.ts +0 -136
  19. package/src/driver/driver.ts +0 -102
  20. package/src/driver/field-encrytion/index.ts +0 -8
  21. package/src/driver/field-encrytion/sharedconst.ts +0 -34
  22. package/src/driver/fieldDBType.ts +0 -14
  23. package/src/driver/format.ts +0 -36
  24. package/src/driver/index.ts +0 -20
  25. package/src/driver/metadata.ts +0 -226
  26. package/src/driver/meteorMongo.ts +0 -639
  27. package/src/driver/mongo.ts +0 -416
  28. package/src/driver/mysql.ts +0 -47
  29. package/src/driver/oracle.ts +0 -60
  30. package/src/driver/postgres.ts +0 -46
  31. package/src/driver/sqlite3.ts +0 -40
  32. package/src/driver/sqlserver.ts +0 -52
  33. package/src/dynamic-load/actions.ts +0 -146
  34. package/src/dynamic-load/approval_process.ts +0 -73
  35. package/src/dynamic-load/button.ts +0 -75
  36. package/src/dynamic-load/chart.ts +0 -22
  37. package/src/dynamic-load/client_script.ts +0 -65
  38. package/src/dynamic-load/field.ts +0 -77
  39. package/src/dynamic-load/flow_role.ts +0 -46
  40. package/src/dynamic-load/index.ts +0 -21
  41. package/src/dynamic-load/layout.ts +0 -53
  42. package/src/dynamic-load/listview.ts +0 -57
  43. package/src/dynamic-load/method.ts +0 -63
  44. package/src/dynamic-load/object_translations.ts +0 -61
  45. package/src/dynamic-load/originalObject.ts +0 -8
  46. package/src/dynamic-load/package.ts +0 -312
  47. package/src/dynamic-load/page.ts +0 -23
  48. package/src/dynamic-load/permission.ts +0 -71
  49. package/src/dynamic-load/permissionset.ts +0 -78
  50. package/src/dynamic-load/preload_data.ts +0 -104
  51. package/src/dynamic-load/profile.ts +0 -90
  52. package/src/dynamic-load/query.ts +0 -22
  53. package/src/dynamic-load/restrictionRules.ts +0 -23
  54. package/src/dynamic-load/role.ts +0 -46
  55. package/src/dynamic-load/shareRules.ts +0 -23
  56. package/src/dynamic-load/tab.ts +0 -17
  57. package/src/dynamic-load/tabs.ts +0 -13
  58. package/src/dynamic-load/translations.ts +0 -54
  59. package/src/dynamic-load/trigger.ts +0 -236
  60. package/src/dynamic-load/validation_rule.ts +0 -77
  61. package/src/dynamic-load/workflow.ts +0 -114
  62. package/src/errors/index.ts +0 -111
  63. package/src/formula/core.ts +0 -490
  64. package/src/formula/field_formula.ts +0 -107
  65. package/src/formula/index.ts +0 -81
  66. package/src/formula/params.ts +0 -197
  67. package/src/formula/recompute.ts +0 -65
  68. package/src/formula/simple_params.ts +0 -92
  69. package/src/formula/type.ts +0 -107
  70. package/src/formula/util.ts +0 -207
  71. package/src/index.ts +0 -24
  72. package/src/metadata-register/_base.ts +0 -85
  73. package/src/metadata-register/app.ts +0 -30
  74. package/src/metadata-register/chart.ts +0 -9
  75. package/src/metadata-register/index.ts +0 -123
  76. package/src/metadata-register/layout.ts +0 -38
  77. package/src/metadata-register/object.ts +0 -68
  78. package/src/metadata-register/page.ts +0 -9
  79. package/src/metadata-register/permissionFields.ts +0 -13
  80. package/src/metadata-register/permissionset.ts +0 -25
  81. package/src/metadata-register/process.ts +0 -16
  82. package/src/metadata-register/processTrigger.ts +0 -24
  83. package/src/metadata-register/profile.ts +0 -25
  84. package/src/metadata-register/query.ts +0 -9
  85. package/src/metadata-register/restrictionRules.ts +0 -12
  86. package/src/metadata-register/shareRules.ts +0 -13
  87. package/src/metadata-register/tab.ts +0 -9
  88. package/src/metadata-register/tabs.ts +0 -43
  89. package/src/services/datasourceServiceFactory.ts +0 -55
  90. package/src/services/helpers/graphql/getPrimaryFieldType.ts +0 -48
  91. package/src/services/helpers/graphql/getQueryFields.ts +0 -36
  92. package/src/services/helpers/graphql/index.ts +0 -681
  93. package/src/services/helpers/rest.ts +0 -57
  94. package/src/services/index.ts +0 -13
  95. package/src/services/objectService.ts +0 -846
  96. package/src/services/objectServiceDispatcher.ts +0 -209
  97. package/src/services/objectServiceFactory.ts +0 -29
  98. package/src/summary/core.ts +0 -263
  99. package/src/summary/field_summary.ts +0 -71
  100. package/src/summary/index.ts +0 -96
  101. package/src/summary/recompute.ts +0 -31
  102. package/src/summary/type.ts +0 -60
  103. package/src/ts-types/index.ts +0 -3
  104. package/src/ts-types/permissionset.ts +0 -8
  105. package/src/ts-types/profile.ts +0 -11
  106. package/src/ts-types/triggerActionParams.ts +0 -22
  107. package/src/typeorm/driver.ts +0 -379
  108. package/src/typeorm/index.ts +0 -3
  109. package/src/typeorm/util.ts +0 -147
  110. package/src/types/action.ts +0 -52
  111. package/src/types/app.ts +0 -280
  112. package/src/types/config.ts +0 -152
  113. package/src/types/connection.ts +0 -87
  114. package/src/types/dashboard.ts +0 -91
  115. package/src/types/datasource.ts +0 -570
  116. package/src/types/field.ts +0 -370
  117. package/src/types/field_permission.ts +0 -42
  118. package/src/types/field_types.ts +0 -1
  119. package/src/types/index.ts +0 -21
  120. package/src/types/list_view.ts +0 -56
  121. package/src/types/listeners.ts +0 -18
  122. package/src/types/object.ts +0 -2076
  123. package/src/types/object_dynamic_load.ts +0 -426
  124. package/src/types/object_events.ts +0 -43
  125. package/src/types/object_layouts.ts +0 -20
  126. package/src/types/object_permission.ts +0 -134
  127. package/src/types/query.ts +0 -28
  128. package/src/types/report.ts +0 -128
  129. package/src/types/restrictionRule.ts +0 -57
  130. package/src/types/schema.ts +0 -273
  131. package/src/types/shareRule.ts +0 -57
  132. package/src/types/trigger.ts +0 -88
  133. package/src/types/userSession.ts +0 -45
  134. package/src/types/validation_rules.ts +0 -29
  135. package/src/util/convert.ts +0 -131
  136. package/src/util/field.ts +0 -93
  137. package/src/util/function_expression.ts +0 -63
  138. package/src/util/index.ts +0 -1058
  139. package/src/util/locale.ts +0 -24
  140. package/src/util/permission_shares.ts +0 -25
  141. package/src/util/suffix.ts +0 -78
  142. package/src/util/transform.ts +0 -239
  143. package/src/validators/index.ts +0 -36
@@ -1,490 +0,0 @@
1
- import { getSteedosSchema } from '../index';
2
- import { SteedosFieldFormulaTypeConfig, SteedosFormulaVarTypeConfig, SteedosFormulaParamTypeConfig, SteedosFormulaVarPathTypeConfig,
3
- FormulaUserKey, SteedosFormulaOptions, SteedosQuotedByFieldFormulasTypeConfig } from './type';
4
- import { getObjectQuotedByFieldFormulaConfigs, getObjectFieldFormulaConfigs } from './field_formula';
5
- import { runQuotedByObjectFieldSummaries, getObjectQuotedByFieldSummaryConfigs } from '../summary';
6
- import { checkCurrentUserIdNotRequiredForFieldFormulas, getFormulaVarPathsAggregateLookups, isFieldFormulaConfigQuotingObjectAndFields } from './util';
7
- import { wrapAsync } from '../util';
8
- import { JsonMap } from "@salesforce/ts-types";
9
- import { SteedosQueryFilters } from '../types';
10
- import _ = require('lodash')
11
- // import _eval = require('eval')
12
- import { extract, parse } from '@steedos/formula';
13
- import { getFieldSubstitution, FormulonDataType } from './params'
14
- import { getSimpleParamSubstitution } from './simple_params'
15
-
16
- /**
17
- * 根据公式内容,取出其中{}中的变量
18
- * @param formula
19
- */
20
- export const pickFormulaVars = (formula: string): Array<string> => {
21
- return extract(formula);
22
- }
23
-
24
- /**
25
- * 根据公式内容,取出其中{}中的变量,并进一步取出这些变量中引用了当前对象的哪些字段
26
- * @param fieldFormulaConfig
27
- */
28
- export const pickFieldFormulaVarFields = (fieldFormulaConfigs: SteedosFieldFormulaTypeConfig | Array<SteedosFieldFormulaTypeConfig>): Array<string> => {
29
- if (!_.isArray(fieldFormulaConfigs)) {
30
- fieldFormulaConfigs = [fieldFormulaConfigs];
31
- }
32
- let result = ["space"]; //space字段作为基础字段不能少
33
- fieldFormulaConfigs.forEach((fieldFormulaConfig: SteedosFieldFormulaTypeConfig) => {
34
- let { vars } = fieldFormulaConfig;
35
- result = _.union(result, pickFormulaVarFields(vars));
36
- });
37
- return _.uniq(result);
38
- }
39
-
40
- /**
41
- * 根据公式内容已取出的{}中的变量,进一步取出这些变量中引用了当前对象的哪些字段
42
- * @param vars
43
- */
44
- export const pickFormulaVarFields = (vars: Array<SteedosFormulaVarTypeConfig>): Array<string> => {
45
- let result = ["space"]; //space字段作为基础字段不能少
46
- vars.forEach((varItem: SteedosFormulaVarTypeConfig) => {
47
- if (varItem.paths.length) {
48
- // 如果是$user变量则paths肯定为空,所以取paths中第一个,第一个一定是当前对象中的字段
49
- let firstPath: SteedosFormulaVarPathTypeConfig = varItem.paths[0];
50
- let firstKey = firstPath.field_name;
51
- result.push(firstKey);
52
- }
53
- });
54
- return _.uniq(result);
55
- }
56
-
57
- /**
58
- * 根据公式中的变量值,计算出跨对象引用的记录对应的字段值,作为公式运算的参数返回
59
- * @param doc
60
- * @param vars
61
- * return Array<SteedosFormulaParamTypeConfig>
62
- */
63
- export const computeFormulaParams = async (doc: JsonMap, vars: Array<SteedosFormulaVarTypeConfig>, currentUserId: string) => {
64
- let params: Array<SteedosFormulaParamTypeConfig> = [];
65
- const spaceId = doc.space;
66
- if (vars && vars.length) {
67
- for (let { key, paths, is_user_var: isUserVar, is_simple_var: isSimpleVar } of vars) {
68
- key = key.trim();
69
- // 如果变量key以$user开头,则解析为userSession,此时paths为空
70
- let tempValue: any;
71
- if (isUserVar) {
72
- if (!currentUserId) {
73
- throw new Error(`computeFormulaParams:The param 'currentUserId' is required for the formula var key ${key} while running`);
74
- }
75
- if (!spaceId) {
76
- throw new Error(`computeFormulaParams:The 'space' property is required for the doc of the formula var key ${key} while running`);
77
- }
78
- // if (!currentUserId) {
79
- // throw new Error(`computeFormulaParams:The param 'currentUserId' is required for the formula var key ${key}`);
80
- // }
81
- // let tempFormulaParams = {};
82
- // let tepmFormula = key.replace(FormulaUserKey, `__params["${FormulaUserKey}"]`);
83
- // tepmFormula = `return ${tepmFormula}`
84
- // tempFormulaParams[FormulaUserKey] = currentUserId;
85
- // tempValue = evalFieldFormula(tepmFormula, tempFormulaParams);
86
- }
87
- if(isSimpleVar){
88
- // 普通变量,取参数值时直接取值,而不用走变量上的paths属性。
89
- // 注意未传入objectName时,公式中的user var的isSimpleVar为false,还是走下面的paths取值逻辑。
90
- tempValue = <any>doc[key];
91
- params.push({
92
- key: key,
93
- value: tempValue
94
- });
95
- continue;
96
- }
97
- tempValue = _.reduce(paths, (reslut, next, index) => {
98
- if (index === 0) {
99
- if (isUserVar) {
100
- // $user变量也要按查相关表记录的方式取值,第一个path为根据id取出对应的space_users记录
101
- const sus = wrapAsync(function () {
102
- return getSteedosSchema().getObject("space_users").find({
103
- filters: [["user", "=", currentUserId], ["space", "=", spaceId]],
104
- fields: [next.field_name]
105
- });
106
- }, {});
107
- reslut = sus && sus.length && sus[0];
108
- if (reslut) {
109
- return reslut[next.field_name]
110
- }
111
- else {
112
- return null
113
- }
114
- }
115
- else {
116
- return <any>doc[next.field_name];
117
- }
118
- }
119
- else {
120
- if (!reslut) {
121
- // 当上一轮返回空值或0时,直接返回
122
- return reslut;
123
- }
124
- reslut = wrapAsync(function () {
125
- return getSteedosSchema().getObject(next.reference_from).findOne(<any>reslut, { fields: [next.field_name] })
126
- }, {});
127
- if (reslut) {
128
- return reslut[next.field_name]
129
- }
130
- else {
131
- return null
132
- }
133
- }
134
- }, null);
135
- params.push({
136
- key: key,
137
- path: _.last(paths),
138
- value: tempValue
139
- });
140
- }
141
- }
142
- return params;
143
- }
144
-
145
- export const computeFieldFormulaValue = async (doc: JsonMap, fieldFormulaConfig: SteedosFieldFormulaTypeConfig, currentUserId: string) => {
146
- if (!currentUserId) {
147
- checkCurrentUserIdNotRequiredForFieldFormulas(fieldFormulaConfig);
148
- }
149
- const { formula, vars, data_type, formula_blank_value } = fieldFormulaConfig;
150
- let params = await computeFormulaParams(doc, vars, currentUserId);
151
- return runFormula(formula, params, {
152
- returnType: data_type,
153
- blankValue: formula_blank_value
154
- }, fieldFormulaConfig);
155
- }
156
-
157
- export const evalFieldFormula = function (formula: string, formulaParams: object) {
158
- try {
159
- // let formulaFun = `module.exports = function (__params) { ${formula} }`;
160
- // console.log("==evalFieldFormula==formulaFun===", formulaFun);
161
- // console.log("==evalFieldFormula==formulaParams===", formulaParams);
162
- // return _eval(formulaFun)(formulaParams);
163
- return parse(formula, formulaParams)
164
- }
165
- catch (ex) {
166
- formulaParams[FormulaUserKey] = "{...}" //$user简化,打出的日志看得清楚点
167
- throw new Error(`evalFieldFormula:Catch an error "${ex}" while eval formula "${formula}" with params "${JSON.stringify(formulaParams)}"`);
168
- }
169
- }
170
-
171
- /**
172
- * 运行公式
173
- * @param formula 公式脚本内容
174
- * @param params 参数
175
- * @param options 公式返回类型,及空值配置
176
- * @param messageTag 用于显示错误日志的标识信息,可以是一个json对象
177
- */
178
- export const runFormula = function (formula: string, params: Array<SteedosFormulaParamTypeConfig>, options?: SteedosFormulaOptions, messageTag?: any) {
179
- if (!options) {
180
- options = {};
181
- }
182
- // console.log("===runFormula===formula====", formula);
183
- // console.log("===runFormula===params====", params);
184
- let { returnType, blankValue } = options;
185
- let formulaParams = {};
186
- params.forEach(({ key, path, value }) => {
187
- // formulaParams[key] = value;
188
- // 把{}括起来的变量替换为计算得到的变量值
189
- // formula = formula.replace(`{${key}}`, `__params["${key}"]`);
190
- if(path){
191
- formulaParams[key] = getFieldSubstitution(path.reference_from, path.field_name, value, blankValue);
192
- }
193
- else{
194
- // 变量中没有path属性说明是普通变量
195
- formulaParams[key] = getSimpleParamSubstitution(value, blankValue);
196
- }
197
- });
198
-
199
- // console.log("===runFormula===formula====", formula);
200
- // console.log("===runFormula===formulaParams====", formulaParams);
201
- let result = evalFieldFormula(formula, formulaParams);
202
- // console.log("===runFormula===result====", result);
203
- let formulaValue = result.value;
204
- let formulaValueType = result.dataType;
205
- if(result.type === 'error'){
206
- console.error(formula, formulaParams)
207
- throw new Error(`runFormula:Catch an error "${result.message}" while eval formula "${formula}" with params: "${JSON.stringify(formulaParams)}" for "${JSON.stringify(messageTag)}"`);
208
- // if(blankValue === SteedosFormulaBlankValue.blanks && result.errorType === "ArgumentError"){
209
- // // 配置了空参数视为空值时会直接返回空值类型,这里就会报错,直接返回空值,而不是抛错
210
- // // TODO:result.errorType === "ArgumentError"不够细化,下一版本应该视错误情况优化返回空值的条件
211
- // formulaValue = null;
212
- // }yar
213
- // else{
214
- // throw new Error(result.message);
215
- // }
216
- }
217
- if (formulaValueType === FormulonDataType.Number && _.isNaN(formulaValue)){
218
- // 数值类型计算结果为NaN时,保存为空值
219
- formulaValue = null;
220
- }
221
-
222
- if (returnType && formulaValueType && formulaValueType != "null") {
223
- switch (returnType) {
224
- case "boolean":
225
- if (formulaValueType !== FormulonDataType.Checkbox) {
226
- throw new Error(`runFormula:The field formula "${formula}" with params "${JSON.stringify(formulaParams)}" should return a boolean type result but got a ${formulaValueType} type value '${formulaValue}'.`);
227
- }
228
- break;
229
- case "number":
230
- if (formulaValueType !== FormulonDataType.Number) {
231
- throw new Error(`runFormula:The field formula "${formula}" with params "${JSON.stringify(formulaParams)}" should return a number type result but got a ${formulaValueType} type value '${formulaValue}'.`);
232
- }
233
- break;
234
- case "currency":
235
- if (formulaValueType !== FormulonDataType.Number) {
236
- throw new Error(`runFormula:The field formula "${formula}" with params "${JSON.stringify(formulaParams)}" should return a number type result but got a ${formulaValueType} type value '${formulaValue}'.`);
237
- }
238
- break;
239
- case "percent":
240
- if (formulaValueType !== FormulonDataType.Number) {
241
- throw new Error(`runFormula:The field formula "${formula}" with params "${JSON.stringify(formulaParams)}" should return a number type result but got a ${formulaValueType} type value '${formulaValue}'.`);
242
- }
243
- break;
244
- case "text":
245
- if (formulaValueType !== FormulonDataType.Text) {
246
- throw new Error(`runFormula:The field formula "${formula}" with params "${JSON.stringify(formulaParams)}" should return a string type result but got a ${formulaValueType} type value '${formulaValue}'.`);
247
- }
248
- break;
249
- case "date":
250
- if (formulaValueType !== FormulonDataType.Date) {
251
- // 这里不可以直接用result.constructor == Date或result instanceof Date,因为eval后的同一个基础类型的构造函数指向的不是同一个
252
- throw new Error(`runFormula:The field formula "${formula}" with params "${JSON.stringify(formulaParams)}" should return a date type result but got a ${formulaValueType} type value '${formulaValue}'.`);
253
- }
254
- break;
255
- case "datetime":
256
- if (formulaValueType !== FormulonDataType.Datetime) {
257
- // 这里不可以直接用result.constructor == Date或result instanceof Date,因为eval后的同一个基础类型的构造函数指向的不是同一个
258
- throw new Error(`runFormula:The field formula "${formula}" with params "${JSON.stringify(formulaParams)}" should return a date type result but got a ${formulaValueType} type value '${formulaValue}'.`);
259
- }
260
- break;
261
- }
262
- }
263
- // console.log("===runFormula===formulaValue====", formulaValue);
264
- return formulaValue;
265
- }
266
-
267
- const addToAggregatePaths = (varItemToAggregatePaths: Array<SteedosFormulaVarPathTypeConfig>, toAggregatePaths: Array<Array<SteedosFormulaVarPathTypeConfig>>) => {
268
- // 当引用了同一个对象的不同属性时,只需要记录其中一个,因为一个公式里面引用的字段变更后,只需要重算一次,比如以下两个都将只有第一条会加入到toAggregatePaths中
269
- // [{"key":"account.website","paths":[{"field_name":"account","reference_from":"contacts"},{"field_name":"website","reference_from":"accounts"}]}]
270
- // [{"key":"account.name","paths":[{"field_name":"account","reference_from":"contacts"},{"field_name":"name","reference_from":"accounts"}]}]
271
- const pathLength = varItemToAggregatePaths.length;
272
- let existPath = toAggregatePaths.find((item) => {
273
- return JSON.stringify(item.slice(0, pathLength)) === JSON.stringify(varItemToAggregatePaths.slice(0, pathLength))
274
- });
275
- if (!existPath) {
276
- toAggregatePaths.push(varItemToAggregatePaths);
277
- }
278
- }
279
-
280
- /**
281
- * 在所有字段引用关系(包括跨对象的字段引用关系)中找到引用了当前正在update的对象字段的公式字段并更新其字段值
282
- * 如果当前不是update而是insert则不需要调用该函数,因为这时这条记录不可能存在引用关系
283
- * @param objectName
284
- * @param recordId
285
- * @param currentUserId
286
- * @param options.fieldNames 传入该参数时,只查找和处理引用了该对象中这些指定字段的公式字段
287
- * @param options.escapeConfigs 传入该参数时,将额外跳过这些公式字段配置的运算,提高性能
288
- * @param options.quotedByConfigs 如果已经根据objectName和fieldNames查过相关配置了,请直接传入,可以避免重复查找,提高性能
289
- */
290
- export const runQuotedByObjectFieldFormulas = async function (objectName: string, recordId: string, userSession: any, options: {
291
- fieldNames?: Array<string>,
292
- escapeConfigs?: Array<SteedosFieldFormulaTypeConfig> | Array<string>,
293
- quotedByConfigs?: SteedosQuotedByFieldFormulasTypeConfig,
294
- onlyForOwn?: boolean,
295
- withoutCurrent?: boolean
296
- } = {}) {
297
- let currentUserId = userSession ? userSession.userId : undefined;
298
- let { fieldNames, escapeConfigs, quotedByConfigs, onlyForOwn, withoutCurrent } = options;
299
- if (!quotedByConfigs) {
300
- quotedByConfigs = await getObjectQuotedByFieldFormulaConfigs(objectName, fieldNames, escapeConfigs, { onlyForOwn, withoutCurrent});
301
- // console.log("runQuotedByObjectFieldFormulas===objectName, fieldNames, escapeConfigs===", objectName, fieldNames, escapeConfigs);
302
- // console.log("runQuotedByObjectFieldFormulas===quotedByConfigs===", quotedByConfigs);
303
- }
304
- if (!quotedByConfigs.allConfigs.length) {
305
- return;
306
- }
307
- if (!currentUserId) {
308
- checkCurrentUserIdNotRequiredForFieldFormulas(quotedByConfigs.allConfigs);
309
- }
310
- // 要排除allConfigs中的ownConfigs,因为allConfigs中已经(按依赖关系先后次序)执行过的当前objectName引用自身的公式字段,不需要在下次级联调用runQuotedByObjectFieldFormulas时再次执行
311
- for (const config of quotedByConfigs.allConfigs) {
312
- await updateQuotedByObjectFieldFormulaValue(objectName, recordId, config, userSession, quotedByConfigs.ownConfigs);
313
- }
314
- }
315
-
316
- /**
317
- * 找到当前正在insert/update的对象中的公式字段并更新其字段值
318
- * @param objectName
319
- * @param recordId
320
- * @param doc
321
- * @param currentUserId
322
- * @param needRefetchDoc 当doc不可信赖时,需要从数据库中重新抓取doc,请传入true值
323
- * @param configs 如果已经根据objectName查过相关配置了,请直接传入,可以避免重复查找,提高性能
324
- */
325
- export const runCurrentObjectFieldFormulas = async function (objectName: string, recordId: string, doc: JsonMap, currentUserId: string, needRefetchDoc?: boolean, configs?: Array<SteedosFieldFormulaTypeConfig>) {
326
- if (!configs) {
327
- configs = await getObjectFieldFormulaConfigs(objectName);
328
- }
329
- if (!configs.length) {
330
- return;
331
- }
332
- if (!currentUserId) {
333
- checkCurrentUserIdNotRequiredForFieldFormulas(configs);
334
- }
335
- // needRefetchDoc默认值为true
336
- if (needRefetchDoc !== false) {
337
- const formulaVarFields = pickFieldFormulaVarFields(configs);
338
- doc = await getSteedosSchema().getObject(objectName).findOne(recordId, { fields: formulaVarFields });
339
- }
340
- let setDoc = {};
341
- for (const config of configs) {
342
- doc = Object.assign({}, doc, setDoc);//setDoc中计算得到的结果应该重新并到doc中支持计算
343
- setDoc[config.field_name] = await computeFieldFormulaValue(doc, config, currentUserId);
344
- }
345
- await getSteedosSchema().getObject(objectName).directUpdate(recordId, setDoc);
346
- }
347
-
348
- /**
349
- * 找到当前正在update的对象多条记录的公式字段并更新其字段值
350
- * @param objectName
351
- * @param filters
352
- * @param currentUserId
353
- */
354
- export const runManyCurrentObjectFieldFormulas = async function (objectName: string, filters: SteedosQueryFilters, currentUserId: string) {
355
- const configs = await getObjectFieldFormulaConfigs(objectName);
356
- if (!configs.length) {
357
- return;
358
- }
359
- if (!currentUserId) {
360
- checkCurrentUserIdNotRequiredForFieldFormulas(configs);
361
- }
362
- const formulaVarFields = pickFieldFormulaVarFields(configs);
363
- let docs = await getSteedosSchema().getObject(objectName).find({ filters: filters, fields: formulaVarFields });
364
- for (const doc of docs) {
365
- await runCurrentObjectFieldFormulas(objectName, doc._id, doc, currentUserId, false, configs);
366
- }
367
- }
368
-
369
- /**
370
- * 修改记录时,根据查到的引用了该记录相关字段公式配置,重新计算字段公式,并把计算结果更新到数据库相关记录中
371
- * @param objectName 当前修改的记录所属对象名称
372
- * @param recordId 当前修改的记录ID
373
- * @param fieldFormulaConfig 查到的引用了该记录所属对象的相关字段公式配置之一
374
- */
375
- export const updateQuotedByObjectFieldFormulaValue = async (objectName: string, recordId: string, fieldFormulaConfig: SteedosFieldFormulaTypeConfig, userSession: any, escapeConfigs?: Array<SteedosFieldFormulaTypeConfig> | Array<string>) => {
376
- // console.log("===updateQuotedByObjectFieldFormulaValue===", objectName, recordId, JSON.stringify(fieldFormulaConfig));
377
- const { vars, object_name: fieldFormulaObjectName } = fieldFormulaConfig;
378
- let toAggregatePaths: Array<Array<SteedosFormulaVarPathTypeConfig>> = [];
379
- for (let varItem of vars) {
380
- // vars格式如:[{"key":"account.website","paths":[{"field_name":"account","reference_from":"contacts"},{"field_name":"website","reference_from":"accounts"}]}]
381
- const { paths } = varItem;
382
- let isInPaths = false;
383
- let varItemToAggregatePaths = [];
384
- for (let pathItem of paths) {
385
- varItemToAggregatePaths.push(pathItem);
386
- if (pathItem.reference_from === objectName) {
387
- isInPaths = true;
388
- break;
389
- }
390
- }
391
- if (isInPaths) {
392
- // 添加时去除重复项
393
- addToAggregatePaths(varItemToAggregatePaths, toAggregatePaths);
394
- }
395
- }
396
- // 只有一层引用关系时,vars格式如:[{"key":"account.website","paths":[{"field_name":"account","reference_from":"contacts"},{"field_name":"website","reference_from":"accounts"}]}]
397
- // 则toAggregatePaths为[[{"field_name":"account","reference_from":"contacts"},{"field_name":"website","reference_from":"accounts"}]]
398
- // 超过一层引用关系时,vars格式如:[{"key":"account.modified_by.name","paths":[{"field_name":"account","reference_from":"contacts"},{"field_name":"modified_by","reference_from":"accounts"},{"field_name":"name","reference_from":"users"}]}]
399
- // 则toAggregatePaths为[[{"field_name":"account","reference_from":"contacts"},{"field_name":"modified_by","reference_from":"accounts"},{"field_name":"name","reference_from":"users"}]]
400
- // toAggregatePaths只会添加到paths中reference_from为objectName的变量路径,多余的不需要加进来
401
- // 例如当前修改的是某条用户记录的内容,即objectName为users,vars可能为:
402
- // [{"key":"account.modified_by.company_id.name","paths":[{"field_name":"account","reference_from":"contacts"},{"field_name":"modified_by","reference_from":"accounts"},{"field_name":"company_id","reference_from":"users"},{"field_name":"name","reference_from":"company"}]}]
403
- // 则toAggregatePaths为[[{"field_name":"account","reference_from":"contacts"},{"field_name":"modified_by","reference_from":"accounts"},{"field_name":"company_id","reference_from":"users"}]]
404
- const formulaVarFields = pickFieldFormulaVarFields(fieldFormulaConfig);
405
- for (let toAggregatePathsItem of toAggregatePaths) {
406
- if (toAggregatePathsItem.length < 3) {
407
- // 引用关系只有一层时,可以直接查出哪些记录需要更新重算公式字段值
408
- let tempPath = toAggregatePathsItem[0];
409
- // if (tempPath.is_formula && fieldFormulaObjectName === objectName && tempPath.reference_from === objectName) {
410
- if (fieldFormulaObjectName === objectName && tempPath.reference_from === objectName) {
411
- // 如果修改的是当前对象本身的公式字段值时,只需要更新当前记录的公式字段值就行
412
- let doc = await getSteedosSchema().getObject(fieldFormulaObjectName).findOne(recordId, { fields: formulaVarFields })
413
- await updateDocsFieldFormulaValue(doc, fieldFormulaConfig, userSession, escapeConfigs);
414
- }
415
- else {
416
- // 修改的是其他对象上的字段值(包括修改的是其他对象上的公式字段值),则需要按recordId值查出哪些记录需要更新重算公式字段值
417
- let docs = await getSteedosSchema().getObject(fieldFormulaObjectName).find({ filters: [[tempPath.field_name, "=", recordId]], fields: formulaVarFields })
418
- await updateDocsFieldFormulaValue(docs, fieldFormulaConfig, userSession, escapeConfigs);
419
- }
420
- }
421
- else {
422
- // 引用关系超过一层时,需要使用aggregate来查出哪些记录需要更新重算公式字段值
423
- let aggregateLookups = getFormulaVarPathsAggregateLookups(toAggregatePathsItem);
424
- let lastLookupAs = aggregateLookups[aggregateLookups.length - 1]["$lookup"].as;
425
- let aggregateFilters = [[`${lastLookupAs}._id`, "=", recordId]];
426
- const docs = await getSteedosSchema().getObject(fieldFormulaObjectName).directAggregatePrefixalPipeline({
427
- filters: aggregateFilters,
428
- fields: formulaVarFields
429
- }, aggregateLookups);
430
- await updateDocsFieldFormulaValue(docs, fieldFormulaConfig, userSession, escapeConfigs);
431
- }
432
- }
433
- }
434
-
435
- export const updateDocsFieldFormulaValue = async (docs: any, fieldFormulaConfig: SteedosFieldFormulaTypeConfig, userSession: any, escapeConfigs?: Array<SteedosFieldFormulaTypeConfig> | Array<string>) => {
436
- const { object_name: fieldFormulaObjectName } = fieldFormulaConfig;
437
- if (!_.isArray(docs)) {
438
- docs = [docs];
439
- }
440
- let currentUserId = userSession ? userSession.userId : undefined;
441
- for (let doc of docs) {
442
- let value = await computeFieldFormulaValue(doc, fieldFormulaConfig, currentUserId);
443
- let setDoc = {};
444
- setDoc[fieldFormulaConfig.field_name] = value;
445
- await getSteedosSchema().getObject(fieldFormulaObjectName).directUpdate(doc._id, setDoc);
446
- }
447
- // 这里特意重新遍历一次docs而不是直接在当前函数中每次更新一条记录后立即处理被引用字段的级联变更,见:公式或汇总触发级联重算时,数据类型变更可能会造成无法重算 #965
448
- await updateQuotedByDocsForFormulaType(docs, fieldFormulaConfig, userSession, escapeConfigs);
449
- }
450
-
451
- export const updateQuotedByDocsForFormulaType = async (docs: any, fieldFormulaConfig: SteedosFieldFormulaTypeConfig, userSession: any, escapeConfigs?: Array<SteedosFieldFormulaTypeConfig> | Array<string>) => {
452
- const { object_name: fieldFormulaObjectName } = fieldFormulaConfig;
453
- if (!_.isArray(docs)) {
454
- docs = [docs];
455
- }
456
- const fieldNames = [fieldFormulaConfig.field_name];
457
- const formulaQuotedByConfigs = await getObjectQuotedByFieldFormulaConfigs(fieldFormulaObjectName, fieldNames, escapeConfigs);
458
- const summaryQuotedByConfigs = await getObjectQuotedByFieldSummaryConfigs(fieldFormulaObjectName, fieldNames);
459
- for (let doc of docs) {
460
- // 公式字段修改后,需要找到引用了该公式字段的其他公式字段并更新其值
461
- await runQuotedByObjectFieldFormulas(fieldFormulaObjectName, doc._id, userSession, {
462
- fieldNames,
463
- quotedByConfigs: formulaQuotedByConfigs,
464
- escapeConfigs
465
- })
466
- // 公式字段修改后,需要找到引用了该公式字段的其他汇总字段并更新其值
467
- await runQuotedByObjectFieldSummaries(fieldFormulaObjectName, doc._id, null, userSession, {
468
- fieldNames,
469
- quotedByConfigs: summaryQuotedByConfigs
470
- });
471
- }
472
- }
473
-
474
- /**
475
- * 某个对象上的公式字段是否引用了某个对象和字段
476
- * @param formulaObjectName 公式字段在所在对象名称
477
- * @param formulaFieldName 公式字段名称
478
- * @param object_name 是否引用了该对象
479
- * @param field_name 是否引用了该字段
480
- */
481
- export const isFormulaFieldQuotingObjectAndFields = async (formulaObjectName: string, formulaFieldName: string, objectName: string, fieldNames?: Array<string>): Promise<boolean> => {
482
- const configs: Array<SteedosFieldFormulaTypeConfig> = await getObjectFieldFormulaConfigs(formulaObjectName, formulaFieldName);
483
- if (configs && configs.length) {
484
- return isFieldFormulaConfigQuotingObjectAndFields(configs[0], objectName, fieldNames);
485
- }
486
- else {
487
- // 没找到公式字段配置说明传入的参数不是公式字段
488
- return false;
489
- }
490
- }
@@ -1,107 +0,0 @@
1
- /*
2
- * @Author: yinlianghui@steedos.com
3
- * @Date: 2022-04-13 10:31:03
4
- * @LastEditors: yinlianghui@steedos.com
5
- * @LastEditTime: 2022-06-17 11:53:00
6
- * @Description:
7
- */
8
- import { SteedosFieldFormulaTypeConfig, SteedosQuotedByFieldFormulasTypeConfig } from './type';
9
- import { sortFieldFormulaConfigs, isFieldFormulaConfigQuotingObjectAndFields } from './util';
10
- import { getSteedosSchema } from '../types/schema';
11
-
12
- import _ = require('lodash');
13
- import { JsonMap } from '@salesforce/ts-types';
14
-
15
- export const getFieldFormulaConfigs = async (objectApiName?, fieldApiName?): Promise<Array<SteedosFieldFormulaTypeConfig>> => {
16
- return await getSteedosSchema().metadataBroker.call(`objects.getObjectFieldFormulaConfigs`, {objectApiName, fieldApiName})
17
- }
18
-
19
- export const getFieldFormulaConfig = async (fieldApiFullName: string): Promise<SteedosFieldFormulaTypeConfig> => {
20
- return await getSteedosSchema().metadataBroker.call(`objects.getObjectFieldFormulaConfig`, {fieldApiFullName})
21
- }
22
-
23
- export const verifyObjectFieldFormulaConfig = async (fieldConfig, objectConfig): Promise<SteedosFieldFormulaTypeConfig> => {
24
- return await getSteedosSchema().metadataBroker.call(`objects.verifyObjectFieldFormulaConfig`, {fieldConfig, objectConfig})
25
- }
26
-
27
- /**
28
- * 获取对象本身的字段公式配置
29
- * 不传入fieldName时取objectName关联的所有字段公式配置
30
- * @param objectName
31
- * @param fieldName
32
- */
33
- export const getObjectFieldFormulaConfigs = async (objectName: string, fieldName?: string): Promise<Array<SteedosFieldFormulaTypeConfig>> => {
34
- return await getFieldFormulaConfigs(objectName, fieldName);
35
- // console.log('getObjectFieldFormulaConfigs from metadata services', configs);
36
- // let result = configs.filter((config: SteedosFieldFormulaTypeConfig) => {
37
- // if (fieldName) {
38
- // return config.object_name === objectName && config.field_name === fieldName;
39
- // }
40
- // else {
41
- // return config.object_name === objectName;
42
- // }
43
- // });
44
- // return sortFieldFormulaConfigs(result);
45
- }
46
-
47
- /**
48
- * 获取对象在哪些字段公式中被引用
49
- * 不传入fieldNames时取objectName关联的所有字段公式配置
50
- * @param objectName
51
- * @param fieldNames
52
- * @param escapeConfigs 要跳过的字段公式
53
- * @param options.onlyForOwn 要跳过其他对象上的字段公式,只检测当前对象上的字段公式,
54
- * 新建记录的时候传入true可以提高性能,避免不必要的公式计算
55
- * 见issue: a公式字段,其中应用了b公式字段,记录保存后a字段没计算,编辑后再保存字段计算 #2946
56
- * @param options.withoutCurrent 要跳过当前对象上配置的所有字段公式,只检测其他对象上的字段公式,
57
- * 删除记录的时候传入true可以解决因为记录被删除doc为null运行公式报错的问题,同时避免不必要的公式计算
58
- * 见issue: 删除包含公式字段的记录时报错 #3427
59
- */
60
- export const getObjectQuotedByFieldFormulaConfigs = async (objectName: string, fieldNames?: Array<string>, escapeConfigs?: Array<SteedosFieldFormulaTypeConfig> | Array<string>, options?: JsonMap): Promise<SteedosQuotedByFieldFormulasTypeConfig> => {
61
- const { onlyForOwn, withoutCurrent } = options || {};
62
- const configs = await getFieldFormulaConfigs(); //TODO 此处代码需要优化,取了所有配置。此处代码迁移到metadata objects services
63
- let configsOnCurrentObject = [];
64
- let configsOnOtherObjects = [];
65
- configs.forEach((config: SteedosFieldFormulaTypeConfig) => {
66
- if (escapeConfigs && escapeConfigs.length) {
67
- const escapeConfigIds = typeof escapeConfigs[0] === "string" ? <Array<string>>escapeConfigs : _.map(<Array<SteedosFieldFormulaTypeConfig>>escapeConfigs, '_id');
68
- if (escapeConfigIds.indexOf(config._id) > -1) {
69
- return;
70
- }
71
- }
72
- let isQuoting = isFieldFormulaConfigQuotingObjectAndFields(config, objectName, fieldNames);
73
- if (isQuoting) {
74
- let isCurrent = config.object_name === objectName;
75
- let isOwn = isCurrent;
76
- if (isCurrent) {
77
- // 要进一步确定其引用关系中有引用自身才算是引用自身的公式字段
78
- isOwn = !!config.quotes.find((quote) => {
79
- return quote.is_own;
80
- });
81
- }
82
- if (isOwn) {
83
- if(!(withoutCurrent && isCurrent)){
84
- configsOnCurrentObject.push(config);
85
- }
86
- }
87
- else if (!onlyForOwn) {
88
- if(!(withoutCurrent && isCurrent)){
89
- configsOnOtherObjects.push(config);
90
- }
91
- }
92
- }
93
- });
94
- // 当前对象上的字段一定要做排序
95
- const ownConfigs = sortFieldFormulaConfigs(configsOnCurrentObject);
96
- const otherConfigs = configsOnOtherObjects; //注意otherConfigs其实也包括当前对象上的公式字段,只是不包含引用自身字段的公式字段
97
- const allConfigs = ownConfigs.concat(otherConfigs);
98
- return { ownConfigs, otherConfigs, allConfigs }
99
- }
100
-
101
- /**
102
- * 获取参数config在哪些字段公式中被引用
103
- * @param config
104
- */
105
- export const getQuotedByFieldFormulaConfigs = async (config: SteedosFieldFormulaTypeConfig): Promise<SteedosQuotedByFieldFormulasTypeConfig> => {
106
- return await getObjectQuotedByFieldFormulaConfigs(config.object_name, [config.field_name]);
107
- }