@steedos/standard-object-database 2.2.55-beta.16
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/main/default/applications/.gitkeep +0 -0
- package/main/default/client/datasources.client.js +7 -0
- package/main/default/client/object_fields.client.js +212 -0
- package/main/default/client/object_layouts.client.js +86 -0
- package/main/default/objectTranslations/_object_reload_logs.en/_object_reload_logs.en.objectTranslation.yml +16 -0
- package/main/default/objectTranslations/_object_reload_logs.zh-CN/_object_reload_logs.zh-CN.objectTranslation.yml +16 -0
- package/main/default/objectTranslations/datasources.en/datasources.en.objectTranslation.yml +121 -0
- package/main/default/objectTranslations/datasources.zh-CN/datasources.zh-CN.objectTranslation.yml +105 -0
- package/main/default/objectTranslations/object_actions.en/object_actions.en.objectTranslation.yml +55 -0
- package/main/default/objectTranslations/object_actions.zh-CN/object_actions.zh-CN.objectTranslation.yml +50 -0
- package/main/default/objectTranslations/object_fields.en/object_fields.en.objectTranslation.yml +335 -0
- package/main/default/objectTranslations/object_fields.zh-CN/object_fields.zh-CN.objectTranslation.yml +312 -0
- package/main/default/objectTranslations/object_layouts.en/object_layouts.en.objectTranslation.yml +72 -0
- package/main/default/objectTranslations/object_layouts.zh-CN/object_layouts.zh-CN.objectTranslation.yml +116 -0
- package/main/default/objectTranslations/object_listviews.en/object_listviews.en.objectTranslation.yml +153 -0
- package/main/default/objectTranslations/object_listviews.zh-CN/object_listviews.zh-CN.objectTranslation.yml +146 -0
- package/main/default/objectTranslations/object_related_list.en/object_related_list.en.objectTranslation.yml +82 -0
- package/main/default/objectTranslations/object_related_list.zh-CN/object_related_list.zh-CN.objectTranslation.yml +82 -0
- package/main/default/objectTranslations/object_triggers.en/object_triggers.en.objectTranslation.yml +30 -0
- package/main/default/objectTranslations/object_triggers.zh-CN/object_triggers.zh-CN.objectTranslation.yml +29 -0
- package/main/default/objectTranslations/object_validation_rules.en/object_validation_rules.en.objectTranslation.yml +40 -0
- package/main/default/objectTranslations/object_validation_rules.zh-CN/object_validation_rules.zh-CN.objectTranslation.yml +38 -0
- package/main/default/objectTranslations/objects.en/objects.en.objectTranslation.yml +219 -0
- package/main/default/objectTranslations/objects.zh-CN/objects.zh-CN.objectTranslation.yml +218 -0
- package/main/default/objects/0.datasources.observe.object.js +83 -0
- package/main/default/objects/0.objects_reload.object.js +26 -0
- package/main/default/objects/1.objects.observe.object.js +61 -0
- package/main/default/objects/10.tabs.observe.object.js +36 -0
- package/main/default/objects/11.restriction_rules.observe.object.js +37 -0
- package/main/default/objects/12.share_rules.observe.object.js +37 -0
- package/main/default/objects/13.permission_fields.observe.object.js +37 -0
- package/main/default/objects/14.object_fields.observe.object.js +44 -0
- package/main/default/objects/15.permission_objects.observe.object.js +44 -0
- package/main/default/objects/2.object_triggers.observe.object.js +35 -0
- package/main/default/objects/3.permission_objects.observe.object.js +29 -0
- package/main/default/objects/4.permission_set.observe.object.js +39 -0
- package/main/default/objects/5.holidays.observe.object.js +30 -0
- package/main/default/objects/6.business_hours.observe.object.js +33 -0
- package/main/default/objects/7.object_actions.observe.object.js +43 -0
- package/main/default/objects/7.object_layouts.observe.object.js +33 -0
- package/main/default/objects/9.apps.observe.object.js +33 -0
- package/main/default/objects/_object_reload_logs.object.yml +10 -0
- package/main/default/objects/datasources.action.js +51 -0
- package/main/default/objects/datasources.core.js +34 -0
- package/main/default/objects/datasources.object.js +168 -0
- package/main/default/objects/datasources.object.yml +113 -0
- package/main/default/objects/object_actions.object.js +152 -0
- package/main/default/objects/object_actions.object.yml +142 -0
- package/main/default/objects/object_fields.action.js +128 -0
- package/main/default/objects/object_fields.function.js +104 -0
- package/main/default/objects/object_fields.object.js +501 -0
- package/main/default/objects/object_fields.object.yml +690 -0
- package/main/default/objects/object_layouts.action.js +31 -0
- package/main/default/objects/object_layouts.layouts.action.js +19 -0
- package/main/default/objects/object_layouts.object.yml +356 -0
- package/main/default/objects/object_listviews.action.js +93 -0
- package/main/default/objects/object_listviews.object.js +100 -0
- package/main/default/objects/object_listviews.object.yml +309 -0
- package/main/default/objects/object_manager.app.todo.yml +11 -0
- package/main/default/objects/object_related_list.object.js +110 -0
- package/main/default/objects/object_related_list.object.yml +208 -0
- package/main/default/objects/object_triggers.core.js +58 -0
- package/main/default/objects/object_triggers.object.js +65 -0
- package/main/default/objects/object_triggers.object.yml +124 -0
- package/main/default/objects/object_validation_rules.action.js +33 -0
- package/main/default/objects/object_validation_rules.object.yml +100 -0
- package/main/default/objects/objects.action.js +157 -0
- package/main/default/objects/objects.core.js +398 -0
- package/main/default/objects/objects.erd.data.function.js +85 -0
- package/main/default/objects/objects.lib.js +42 -0
- package/main/default/objects/objects.object.js +543 -0
- package/main/default/objects/objects.object.yml +512 -0
- package/main/default/objects/objects.tree.js +58 -0
- package/main/default/objects/permission_objects.core.js +75 -0
- package/main/default/permissionsets/.gitkeep +0 -0
- package/main/default/profiles/.gitkeep +0 -0
- package/main/default/tabs/.gitkeep +0 -0
- package/main/default/triggers/datasources.trigger.js +93 -0
- package/main/default/triggers/object_actions.trigger.js +98 -0
- package/main/default/triggers/object_fields.trigger.js +376 -0
- package/main/default/triggers/object_layouts.trigger.js +153 -0
- package/main/default/triggers/object_listviews.trigger.js +139 -0
- package/main/default/triggers/object_triggers.trigger.js +50 -0
- package/main/default/triggers/object_validation_rules.trigger.js +80 -0
- package/main/default/triggers/objects.trigger.js +136 -0
- package/package.json +16 -0
- package/package.service.js +75 -0
- package/public/.md +3 -0
- package/src/.md +3 -0
- package/webapp/.md +1 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @Author: baozhoutao@steedos.com
|
|
3
|
+
* @Date: 2022-05-16 11:55:06
|
|
4
|
+
* @Description:
|
|
5
|
+
*/
|
|
6
|
+
const InternalData = require('@steedos/standard-objects').internalData;
|
|
7
|
+
const objectql = require('@steedos/objectql');
|
|
8
|
+
const auth = require('@steedos/auth');
|
|
9
|
+
const _ = require('underscore');
|
|
10
|
+
//由于新版lookup 组件限制。需编写trigger处理在只读页面不显示已选中项的问题
|
|
11
|
+
//由于lookup组件强依赖_id 字段,所以必须返回_id
|
|
12
|
+
module.exports = {
|
|
13
|
+
|
|
14
|
+
beforeFind: async function () {
|
|
15
|
+
delete this.query.fields;
|
|
16
|
+
},
|
|
17
|
+
|
|
18
|
+
beforeAggregate: async function () {
|
|
19
|
+
delete this.query.fields;
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
afterFind: async function(){
|
|
23
|
+
const { spaceId } = this;
|
|
24
|
+
let lng = Steedos.locale(this.userId, true);
|
|
25
|
+
let dataList = [{_id: 'default', name: 'default', label: TAPi18n.__(`objects_field_datasource_defaultValue`, {}, lng)}];
|
|
26
|
+
let filters = InternalData.parserFilters(this.query.filters)
|
|
27
|
+
if(filters._id === 'meteor'){
|
|
28
|
+
dataList.push({_id: 'meteor', name: 'meteor', label: TAPi18n.__(`objects_field_datasource_meteor`, {}, lng)})
|
|
29
|
+
}
|
|
30
|
+
if (!_.isEmpty(dataList)) {
|
|
31
|
+
dataList.forEach((doc) => {
|
|
32
|
+
if (!_.find(this.data.values, (value) => {
|
|
33
|
+
return value.name === doc.name
|
|
34
|
+
})) {
|
|
35
|
+
this.data.values.push(doc);
|
|
36
|
+
}
|
|
37
|
+
})
|
|
38
|
+
const records = objectql.getSteedosSchema().metadataDriver.find(this.data.values, this.query, spaceId);
|
|
39
|
+
if (records.length > 0) {
|
|
40
|
+
this.data.values = records;
|
|
41
|
+
} else {
|
|
42
|
+
this.data.values.length = 0;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
},
|
|
47
|
+
afterAggregate: async function(){
|
|
48
|
+
const { spaceId } = this;
|
|
49
|
+
let lng = Steedos.locale(this.userId, true)
|
|
50
|
+
let dataList = [{_id: 'default', name: 'default', label: TAPi18n.__(`objects_field_datasource_defaultValue`, {}, lng)}];
|
|
51
|
+
if (!_.isEmpty(dataList)) {
|
|
52
|
+
dataList.forEach((doc) => {
|
|
53
|
+
if (!_.find(this.data.values, (value) => {
|
|
54
|
+
return value.name === doc.name
|
|
55
|
+
})) {
|
|
56
|
+
this.data.values.push(doc);
|
|
57
|
+
}
|
|
58
|
+
})
|
|
59
|
+
const records = objectql.getSteedosSchema().metadataDriver.find(this.data.values, this.query, spaceId);
|
|
60
|
+
if (records.length > 0) {
|
|
61
|
+
this.data.values = records;
|
|
62
|
+
} else {
|
|
63
|
+
this.data.values.length = 0;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
afterCount: async function(){
|
|
68
|
+
delete this.query.fields;
|
|
69
|
+
let result = await objectql.getObject(this.object_name).find(this.query, await auth.getSessionByUserId(this.userId, this.spaceId))
|
|
70
|
+
this.data.values = result.length;
|
|
71
|
+
},
|
|
72
|
+
afterFindOne: async function(){
|
|
73
|
+
if(this.id){
|
|
74
|
+
if(this.id === 'default'){
|
|
75
|
+
try {
|
|
76
|
+
let lng = Steedos.locale(this.userId, true)
|
|
77
|
+
this.data.values = {_id: 'default', name: 'default', label: TAPi18n.__(`objects_field_datasource_defaultValue`, {}, lng)};
|
|
78
|
+
} catch (error) {
|
|
79
|
+
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if(this.id === 'meteor'){
|
|
83
|
+
try {
|
|
84
|
+
let lng = Steedos.locale(this.userId, true)
|
|
85
|
+
this.data.values = {_id: 'meteor', name: 'meteor', label: TAPi18n.__(`objects_field_datasource_meteor`, {}, lng)};
|
|
86
|
+
} catch (error) {
|
|
87
|
+
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @Author: sunhaolin@hotoa.com
|
|
3
|
+
* @Date: 2022-05-28 11:07:57
|
|
4
|
+
* @LastEditors: sunhaolin@hotoa.com
|
|
5
|
+
* @LastEditTime: 2022-07-29 11:26:31
|
|
6
|
+
* @Description:
|
|
7
|
+
*/
|
|
8
|
+
const InternalData = require('@steedos/standard-objects').internalData;
|
|
9
|
+
const objectql = require('@steedos/objectql');
|
|
10
|
+
const auth = require("@steedos/auth");
|
|
11
|
+
module.exports = {
|
|
12
|
+
beforeInsert: async function(){
|
|
13
|
+
const { doc } = this;
|
|
14
|
+
doc.visible;
|
|
15
|
+
},
|
|
16
|
+
beforeUpdate: async function(){
|
|
17
|
+
const { doc } = this;
|
|
18
|
+
doc.visible;
|
|
19
|
+
},
|
|
20
|
+
beforeFind: async function () {
|
|
21
|
+
delete this.query.fields;
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
beforeAggregate: async function () {
|
|
25
|
+
delete this.query.fields;
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
afterFind: async function(){
|
|
29
|
+
let filters = InternalData.parserFilters(this.query.filters)
|
|
30
|
+
const { spaceId } = this;
|
|
31
|
+
|
|
32
|
+
let objectName = filters.object;
|
|
33
|
+
if(!objectName && filters._id && filters._id.indexOf(".") > -1){
|
|
34
|
+
objectName = filters._id.split('.')[0];
|
|
35
|
+
}
|
|
36
|
+
if(objectName){
|
|
37
|
+
let dataList = await InternalData.getObjectActions(objectName, this.userId);
|
|
38
|
+
if (!_.isEmpty(dataList)) {
|
|
39
|
+
dataList.forEach((doc) => {
|
|
40
|
+
if (!_.find(this.data.values, (value) => {
|
|
41
|
+
return value.name === doc.name
|
|
42
|
+
})) {
|
|
43
|
+
this.data.values.push(Object.assign({_id: `${objectName}.${doc.name}`}, doc));
|
|
44
|
+
}
|
|
45
|
+
})
|
|
46
|
+
const records = objectql.getSteedosSchema().metadataDriver.find(this.data.values, this.query, spaceId);
|
|
47
|
+
if (records.length > 0) {
|
|
48
|
+
this.data.values = records;
|
|
49
|
+
} else {
|
|
50
|
+
this.data.values.length = 0;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
afterAggregate: async function(){
|
|
56
|
+
let filters = InternalData.parserFilters(this.query.filters)
|
|
57
|
+
const { spaceId } = this;
|
|
58
|
+
|
|
59
|
+
let objectName = filters.object;
|
|
60
|
+
if(!objectName && filters._id && filters._id.indexOf(".") > -1){
|
|
61
|
+
objectName = filters._id.split('.')[0];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
let dataList = await InternalData.getObjectActions(objectName, this.userId);
|
|
65
|
+
if (!_.isEmpty(dataList)) {
|
|
66
|
+
dataList.forEach((doc) => {
|
|
67
|
+
if (!_.find(this.data.values, (value) => {
|
|
68
|
+
return value.name === doc.name
|
|
69
|
+
})) {
|
|
70
|
+
this.data.values.push(Object.assign({_id: `${objectName}.${doc.name}`}, doc));
|
|
71
|
+
}
|
|
72
|
+
})
|
|
73
|
+
const records = objectql.getSteedosSchema().metadataDriver.find(this.data.values, this.query, spaceId);
|
|
74
|
+
if (records.length > 0) {
|
|
75
|
+
this.data.values = records;
|
|
76
|
+
} else {
|
|
77
|
+
this.data.values.length = 0;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
afterCount: async function(){
|
|
82
|
+
delete this.query.fields;
|
|
83
|
+
let result = await objectql.getObject(this.object_name).find(this.query, await auth.getSessionByUserId(this.userId, this.spaceId))
|
|
84
|
+
this.data.values = result.length;
|
|
85
|
+
},
|
|
86
|
+
afterFindOne: async function(){
|
|
87
|
+
if(_.isEmpty(this.data.values)){
|
|
88
|
+
let id = this.id
|
|
89
|
+
let objectName = id.substr(0, id.indexOf("."));
|
|
90
|
+
if(objectName){
|
|
91
|
+
let action = await InternalData.getObjectAction(objectName, this.userId, id);
|
|
92
|
+
if(action){
|
|
93
|
+
this.data.values = action;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
const InternalData = require('@steedos/standard-objects').internalData;
|
|
2
|
+
var _ = require("underscore");
|
|
3
|
+
const odataMongodb = require("@steedos/odata-v4-mongodb");
|
|
4
|
+
const clone = require('clone');
|
|
5
|
+
var objectCore = require('../objects/objects.core.js');
|
|
6
|
+
const objectql = require('@steedos/objectql');
|
|
7
|
+
const auth = require('@steedos/auth');
|
|
8
|
+
const MAX_MASTER_DETAIL_LEAVE = objectql.MAX_MASTER_DETAIL_LEAVE;
|
|
9
|
+
const validateOptionValue = (value)=>{
|
|
10
|
+
let color = value && value.split(":")[2];
|
|
11
|
+
if(color){
|
|
12
|
+
const reg = /^(#)?[\da-f]{3}([\da-f]{3})?$/i;
|
|
13
|
+
if(!reg.test(color)){
|
|
14
|
+
throw new Error("object_fields_error_option_color_not_valid");
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const validateOptionsValue = (value)=>{
|
|
20
|
+
if(value){
|
|
21
|
+
value.split("\n").forEach(function(option) {
|
|
22
|
+
let options;
|
|
23
|
+
if (option.indexOf(",")) {
|
|
24
|
+
options = option.split(",");
|
|
25
|
+
return options.forEach(function(_option) {
|
|
26
|
+
validateOptionValue(_option);
|
|
27
|
+
});
|
|
28
|
+
} else {
|
|
29
|
+
validateOptionValue(option);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const validateOptionColorValue = (value)=>{
|
|
36
|
+
if(value){
|
|
37
|
+
const reg = /^[\da-f]{6}$/i;
|
|
38
|
+
if(!reg.test(value)){
|
|
39
|
+
throw new Error("object_fields_error_option_color_not_valid");
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const validateOptionsGridValue = (value)=>{
|
|
45
|
+
if(value){
|
|
46
|
+
value.forEach(function(option) {
|
|
47
|
+
if(!option.label){
|
|
48
|
+
throw new Error("object_fields_error_option_label_required");
|
|
49
|
+
}
|
|
50
|
+
if(!option.value){
|
|
51
|
+
throw new Error("object_fields_error_option_value_required");
|
|
52
|
+
}
|
|
53
|
+
validateOptionColorValue(option.color);
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const validateDoc = (doc)=>{
|
|
59
|
+
validateOptionsGridValue(doc.options);
|
|
60
|
+
// if(doc.type === "autonumber"){
|
|
61
|
+
// let formula = doc.formula && doc.formula.trim();
|
|
62
|
+
// if(!formula){
|
|
63
|
+
// throw new Error("object_fields_error_formula_required");
|
|
64
|
+
// }
|
|
65
|
+
// }
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
async function checkOwnerField(doc) {
|
|
71
|
+
if (doc.name !== "owner") {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (!doc.omit) {
|
|
75
|
+
const obj = objectql.getObject(doc.object);
|
|
76
|
+
const masters = await obj.getMasters();
|
|
77
|
+
if (masters && masters.length) {
|
|
78
|
+
throw new Meteor.Error(doc.name, "您无法取消勾选“新建、编辑时隐藏”属性,因为当前对象上有主表子表关系字段!");
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function checkMasterDetailPathsRepeat(doc, masterPaths, detailPaths) {
|
|
84
|
+
// 交叉叠加传入的两个方向的路径判断是否存在同一链条上同名对象可能,同名就直接报错
|
|
85
|
+
_.each(masterPaths, (masterPathItems) => {
|
|
86
|
+
_.each(detailPaths, (detailPathItems) => {
|
|
87
|
+
const repeatName = objectql.getRepeatObjectNameFromPaths([masterPathItems.concat(detailPathItems)]);
|
|
88
|
+
if (repeatName) {
|
|
89
|
+
throw new Meteor.Error(doc.name, "您无法创建此类字段,因为在主表子表关系链条中存在同名对象:" + repeatName);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async function checkMasterDetailTypeField(doc, oldReferenceTo) {
|
|
96
|
+
if (!doc || !doc.type || doc.type !== "master_detail") {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
if (doc.reference_to === doc.object) {
|
|
100
|
+
throw new Meteor.Error(doc.name, "您无法创建一个指向自身的[主表/子表]类型字段!");
|
|
101
|
+
}
|
|
102
|
+
const obj = objectql.getObject(doc.object);
|
|
103
|
+
if (!obj) {
|
|
104
|
+
throw new Meteor.Error(doc.name, `所属对象未加载!`);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const refObj = objectql.getObject(doc.reference_to);
|
|
108
|
+
if (!refObj) {
|
|
109
|
+
throw new Meteor.Error(doc.name, `引用对象未加载!`);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
let currentMasters = await obj.getMasters();
|
|
113
|
+
let currentDetails = await obj.getDetails();
|
|
114
|
+
if (oldReferenceTo) {
|
|
115
|
+
let index = currentMasters.indexOf(oldReferenceTo);
|
|
116
|
+
if (index >= 0) {
|
|
117
|
+
currentMasters.splice(index, 1);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (currentMasters.indexOf(doc.reference_to) > -1) {
|
|
122
|
+
throw new Meteor.Error(doc.name, `该对象上已经存在指向相同“引用对象”的其它主表子表关系,无法创建该字段。`);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const mastersCount = currentMasters.length;
|
|
126
|
+
const detailsCount = currentDetails.length;
|
|
127
|
+
if (mastersCount > 1) {
|
|
128
|
+
throw new Meteor.Error(doc.name, "您无法创建此类型的字段,因为此对象已有两种主表子表关系。");
|
|
129
|
+
}
|
|
130
|
+
else if (mastersCount > 0) {
|
|
131
|
+
if (detailsCount > 0) {
|
|
132
|
+
throw new Meteor.Error(doc.name, "由于此对象上已经存在主表子表关系,同时是另一个主表子表关系的主对象,无法创建此类字段。");
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const detailPaths = await obj.getDetailPaths();
|
|
137
|
+
const masterPaths = await refObj.getMasterPaths();
|
|
138
|
+
// 当有同名对象时肯定会死循环进而超出最大层级限制,所以优先判断提示同名对象问题
|
|
139
|
+
checkMasterDetailPathsRepeat(doc, masterPaths, detailPaths);
|
|
140
|
+
|
|
141
|
+
// 新加主表子表关系后,当前对象作为主表往下最多允许有MAX_MASTER_DETAIL_LEAVE层深度。
|
|
142
|
+
const maxDetailLeave = await obj.getMaxDetailsLeave(detailPaths);
|
|
143
|
+
// console.log("===maxDetailLeave===", maxDetailLeave);
|
|
144
|
+
if (maxDetailLeave > MAX_MASTER_DETAIL_LEAVE - 1) {
|
|
145
|
+
throw new Meteor.Error(doc.name, "您无法创建此类字段,因为这将超出主表子表关系的最大深度。");
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// 新加主表子表关系后,当前对象作为子表往上和往下加起来最多允许有MAX_DETAIL_LEAVE层深度。
|
|
149
|
+
const maxMasterLeave = await refObj.getMaxMastersLeave(masterPaths);
|
|
150
|
+
// console.log("===maxMasterLeave===", maxMasterLeave);
|
|
151
|
+
if (maxMasterLeave + maxDetailLeave > MAX_MASTER_DETAIL_LEAVE - 1) {
|
|
152
|
+
throw new Meteor.Error(doc.name, "您无法创建此类字段,因为这将超出主表子表关系的最大深度。");
|
|
153
|
+
}
|
|
154
|
+
// let fields = await obj.getFields();
|
|
155
|
+
// const ownerField = _.find(fields, (n) => { return n.name === "owner"; });
|
|
156
|
+
// if (!ownerField.omit) {
|
|
157
|
+
// throw new Meteor.Error(doc.name, "您无法创建此类字段,因为该对象上“所有者”字段未勾选“新建、编辑时隐藏”属性。");
|
|
158
|
+
// }
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function getFieldName(object, fieldName, spaceId, oldFieldName){
|
|
162
|
+
if(object && object.datasource && object.datasource != 'default'){
|
|
163
|
+
return fieldName;
|
|
164
|
+
}else{
|
|
165
|
+
if(fieldName != 'name' && fieldName != 'owner'){
|
|
166
|
+
return objectql._makeNewFieldName(fieldName, spaceId, oldFieldName);
|
|
167
|
+
}else{
|
|
168
|
+
return fieldName
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const checkFormulaInfiniteLoop = async function(_doc, oldFieldName){
|
|
174
|
+
if(_doc.type === "formula"){
|
|
175
|
+
doc = clone(_doc)
|
|
176
|
+
delete doc._id
|
|
177
|
+
const objectConfig = objectql.wrapAsync(async function(){
|
|
178
|
+
return await objectql.getObject(doc.object).toConfig();
|
|
179
|
+
})
|
|
180
|
+
// objectCore.loadDBObject(objectConfig)
|
|
181
|
+
delete objectConfig._id;
|
|
182
|
+
try {
|
|
183
|
+
if(!doc.name){
|
|
184
|
+
doc.name = getFieldName(objectConfig, doc._name, doc.space, oldFieldName)
|
|
185
|
+
}
|
|
186
|
+
await objectql.verifyObjectFieldFormulaConfig(doc, objectConfig);
|
|
187
|
+
} catch (error) {
|
|
188
|
+
if(error.message.startsWith('Infinite Loop')){
|
|
189
|
+
throw new Error('字段公式配置异常,禁止循环引用对象字段');
|
|
190
|
+
}else{
|
|
191
|
+
throw error;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const initSummaryDoc = async (doc) => {
|
|
198
|
+
if (!doc.summary_object) {
|
|
199
|
+
throw new Error("object_fields_error_summary_object_required");
|
|
200
|
+
}
|
|
201
|
+
let summaryObject = objectql.getObjectConfig(doc.summary_object);
|
|
202
|
+
let summaryConfig = {
|
|
203
|
+
summary_object: doc.summary_object,
|
|
204
|
+
summary_type: doc.summary_type,
|
|
205
|
+
summary_field: doc.summary_field,
|
|
206
|
+
field_name: doc.name,
|
|
207
|
+
object_name: doc.object
|
|
208
|
+
};
|
|
209
|
+
const dataType = await objectql.getSummaryDataType(summaryConfig, summaryObject);
|
|
210
|
+
if (!dataType) {
|
|
211
|
+
throw new Error("object_fields_error_summary_data_type_not_found");
|
|
212
|
+
}
|
|
213
|
+
doc.data_type = dataType;
|
|
214
|
+
objectql.validateFilters(doc.summary_filters, summaryObject.fields);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
module.exports = {
|
|
218
|
+
afterFind: async function(){
|
|
219
|
+
let filters = InternalData.parserFilters(this.query.filters);
|
|
220
|
+
let objectName = filters.object;
|
|
221
|
+
if(!objectName && filters._id && filters._id.indexOf(".") > -1){
|
|
222
|
+
objectName = filters._id.split('.')[0];
|
|
223
|
+
}
|
|
224
|
+
if(objectName){
|
|
225
|
+
let fields = await InternalData.getObjectFields(objectName, this.userId);
|
|
226
|
+
if(fields){
|
|
227
|
+
_.each(fields, (field)=>{
|
|
228
|
+
this.data.values.push(Object.assign({_id: `${objectName}.${field.name}`}, field))
|
|
229
|
+
})
|
|
230
|
+
// this.data.values = this.data.values.concat(fields)
|
|
231
|
+
this.data.values = objectql.getSteedosSchema().metadataDriver.find(this.data.values, this.query, this.spaceId);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
},
|
|
235
|
+
beforeFind: async function(){
|
|
236
|
+
const { query } = this;
|
|
237
|
+
if(query.fields && _.isArray(query.fields) && !_.include(query.fields, 'object')){
|
|
238
|
+
query.fields.push('object')
|
|
239
|
+
}
|
|
240
|
+
if(query.fields && _.isArray(query.fields) && !_.include(query.fields, 'name')){
|
|
241
|
+
query.fields.push('name')
|
|
242
|
+
}
|
|
243
|
+
},
|
|
244
|
+
beforeAggregate: async function(){
|
|
245
|
+
const { query } = this;
|
|
246
|
+
if(query.fields && _.isArray(query.fields) && !_.include(query.fields, 'object')){
|
|
247
|
+
query.fields.push('object')
|
|
248
|
+
}
|
|
249
|
+
},
|
|
250
|
+
afterAggregate: async function(){
|
|
251
|
+
let filters = InternalData.parserFilters(this.query.filters);
|
|
252
|
+
let objectName = filters.object;
|
|
253
|
+
if(!objectName && filters._id && filters._id.indexOf(".") > -1){
|
|
254
|
+
objectName = filters._id.split('.')[0];
|
|
255
|
+
}
|
|
256
|
+
if(objectName){
|
|
257
|
+
let fields = await InternalData.getObjectFields(objectName, this.userId);
|
|
258
|
+
if(fields){
|
|
259
|
+
_.each(fields, (field)=>{
|
|
260
|
+
this.data.values.push(Object.assign({_id: `${objectName}.${field.name}`}, field))
|
|
261
|
+
})
|
|
262
|
+
// this.data.values = this.data.values.concat(fields)
|
|
263
|
+
this.data.values = objectql.getSteedosSchema().metadataDriver.find(this.data.values, this.query, this.spaceId);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
},
|
|
267
|
+
afterCount: async function(){
|
|
268
|
+
let result = await objectql.getObject('object_fields').find(this.query, await auth.getSessionByUserId(this.userId, this.spaceId))
|
|
269
|
+
this.data.values = result.length;
|
|
270
|
+
},
|
|
271
|
+
afterFindOne: async function(){
|
|
272
|
+
if(_.isEmpty(this.data.values)){
|
|
273
|
+
let id = this.id
|
|
274
|
+
let objectName = id.substr(0, id.indexOf("."));
|
|
275
|
+
if(objectName){
|
|
276
|
+
let field = await InternalData.getObjectField(objectName, this.userId, id);
|
|
277
|
+
if(field){
|
|
278
|
+
this.data.values = field;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
},
|
|
283
|
+
beforeInsert: async function () {
|
|
284
|
+
let doc = this.doc;
|
|
285
|
+
validateDoc(doc);
|
|
286
|
+
await checkFormulaInfiniteLoop(doc);
|
|
287
|
+
await checkMasterDetailTypeField(doc);
|
|
288
|
+
await checkOwnerField(doc);
|
|
289
|
+
|
|
290
|
+
if(doc.type === "summary"){
|
|
291
|
+
await initSummaryDoc(doc);
|
|
292
|
+
}
|
|
293
|
+
if(doc.type === "select" && doc.data_type && doc.data_type != 'text'){
|
|
294
|
+
const options = doc.options;
|
|
295
|
+
_.each(options, (item)=>{
|
|
296
|
+
const value = item.value;
|
|
297
|
+
const numberValue = Number(item.value);
|
|
298
|
+
if( doc.data_type === 'number' && !(_.isNumber(numberValue) && !_.isNaN(numberValue)) ){
|
|
299
|
+
throw new Meteor.Error(500, "选择项中的选项值类型应该与数据类型值一致, 请输入合法的数值。");
|
|
300
|
+
}
|
|
301
|
+
if( doc.data_type === 'boolean' && ['true','false'].indexOf(value) < 0){
|
|
302
|
+
throw new Meteor.Error(500, "选择项中的选项值类型应该与数据类型值一致, 请输入 true 或 false。");
|
|
303
|
+
}
|
|
304
|
+
})
|
|
305
|
+
}
|
|
306
|
+
},
|
|
307
|
+
beforeUpdate: async function () {
|
|
308
|
+
let { doc, object_name, id} = this;
|
|
309
|
+
validateDoc(doc);
|
|
310
|
+
// const dbDoc = await objectql.getObject(object_name).findOne(id)
|
|
311
|
+
const dbDoc = objectql.wrapAsync(async function(){
|
|
312
|
+
return await objectql.getObject(object_name).findOne(id)
|
|
313
|
+
})
|
|
314
|
+
|
|
315
|
+
if(doc && _.has(doc, 'multiple') && doc.multiple != dbDoc.multiple){
|
|
316
|
+
throw new Error('禁止单选、多选切换')
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
let oldReferenceTo = dbDoc.type === "master_detail" && dbDoc.reference_to;
|
|
320
|
+
await checkFormulaInfiniteLoop(doc, dbDoc.name);
|
|
321
|
+
await checkMasterDetailTypeField(doc, oldReferenceTo);
|
|
322
|
+
await checkOwnerField(doc);
|
|
323
|
+
|
|
324
|
+
if(doc.type === "summary"){
|
|
325
|
+
await initSummaryDoc(doc);
|
|
326
|
+
}
|
|
327
|
+
if(["parent","children"].indexOf(dbDoc._name) > -1){
|
|
328
|
+
let isImportField = false;
|
|
329
|
+
if(doc._name !== dbDoc._name || doc.type !== dbDoc.type || doc.object !== dbDoc.object || doc.reference_to !== dbDoc.reference_to || !!doc.multiple !== !!dbDoc.multiple || ("children" === dbDoc._name && doc.omit !== true)){
|
|
330
|
+
isImportField = true;
|
|
331
|
+
}
|
|
332
|
+
if(isImportField){
|
|
333
|
+
throw new Meteor.Error(500, "字段parent、children是启用树状结构显示记录的对象的内置字段,不能修改其”所属对象、字段名、字段类型、引用对象、多选、新建/编辑时隐藏”等属性");
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
if(doc.type === "select" && doc.data_type && doc.data_type != 'text'){
|
|
338
|
+
const options = doc.options;
|
|
339
|
+
_.each(options, (item)=>{
|
|
340
|
+
const value = item.value;
|
|
341
|
+
const numberValue = Number(item.value);
|
|
342
|
+
if( doc.data_type === 'number' && !(_.isNumber(numberValue) && !_.isNaN(numberValue)) ){
|
|
343
|
+
throw new Meteor.Error(500, "选择项中的选项值类型应该与数据类型值一致, 请输入合法的数值。");
|
|
344
|
+
}
|
|
345
|
+
console.log('doc==>',doc.data_type , value)
|
|
346
|
+
if( doc.data_type === 'boolean' && ['true','false'].indexOf(value) < 0){
|
|
347
|
+
throw new Meteor.Error(500, "选择项中的选项值类型应该与数据类型值一致, 请输入 true 或 false。");
|
|
348
|
+
}
|
|
349
|
+
})
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
const obj = this.getObject(object_name);
|
|
353
|
+
const latestDoc = await obj.findOne(id);
|
|
354
|
+
// !!!暂不允许修改name
|
|
355
|
+
if (_.has(doc, '_name')) {
|
|
356
|
+
const newFieldName = doc._name;
|
|
357
|
+
if (newFieldName && (latestDoc._name != newFieldName)) {
|
|
358
|
+
throw new Error('禁止修改字段名。');
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
// !!!暂不允许修改字段类型
|
|
362
|
+
if (_.has(doc, 'type')) {
|
|
363
|
+
const newFieldType = doc.type;
|
|
364
|
+
if (newFieldType && (latestDoc.type != newFieldType)) {
|
|
365
|
+
throw new Error('禁止修改字段类型。');
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
},
|
|
369
|
+
beforeDelete: async function () {
|
|
370
|
+
const field = await this.getObject(this.object_name).findOne(this.id,{fields:['name','object']});
|
|
371
|
+
const enable_tree = await objectql.getObject(field.object).enable_tree;
|
|
372
|
+
if( ["parent","children"].indexOf(field.name) > -1 && enable_tree ){
|
|
373
|
+
throw new Meteor.Error(500, "启用树状结构显示记录的对象不能删除parent、children字段。");
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|