agrs-sequelize-sdk 1.2.69 → 1.2.71
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/models/Rule.js +129 -129
- package/models/RuleAction.js +72 -77
- package/models/RuleCondition.js +70 -81
- package/models/RuleExecution.js +86 -104
- package/package.json +1 -1
package/models/Rule.js
CHANGED
|
@@ -1,153 +1,153 @@
|
|
|
1
|
-
const { DataTypes } = require(
|
|
1
|
+
const { DataTypes } = require("sequelize");
|
|
2
2
|
|
|
3
3
|
module.exports = (sequelize) => {
|
|
4
|
-
const Rule = sequelize.define(
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
type: DataTypes.STRING(255),
|
|
12
|
-
allowNull: false,
|
|
13
|
-
comment: 'Rule name for identification',
|
|
14
|
-
},
|
|
15
|
-
description: {
|
|
16
|
-
type: DataTypes.TEXT,
|
|
17
|
-
allowNull: true,
|
|
18
|
-
comment: 'Optional description of what this rule does',
|
|
19
|
-
},
|
|
20
|
-
isActive: {
|
|
21
|
-
type: DataTypes.BOOLEAN,
|
|
22
|
-
defaultValue: true,
|
|
23
|
-
allowNull: false,
|
|
24
|
-
comment: 'Whether the rule is currently active',
|
|
25
|
-
},
|
|
26
|
-
ruleType: {
|
|
27
|
-
type: DataTypes.ENUM(
|
|
28
|
-
'PAUSE',
|
|
29
|
-
'BUDGET',
|
|
30
|
-
'BID',
|
|
31
|
-
'STATUS',
|
|
32
|
-
'CUSTOM'
|
|
33
|
-
),
|
|
34
|
-
allowNull: false,
|
|
35
|
-
comment: 'Type of rule - determines the action category',
|
|
36
|
-
},
|
|
37
|
-
targetLevel: {
|
|
38
|
-
type: DataTypes.ENUM(
|
|
39
|
-
'CAMPAIGN',
|
|
40
|
-
'ADSET',
|
|
41
|
-
'AD'
|
|
42
|
-
),
|
|
43
|
-
allowNull: false,
|
|
44
|
-
comment: 'Level at which the rule operates',
|
|
45
|
-
},
|
|
46
|
-
scheduleType: {
|
|
47
|
-
type: DataTypes.ENUM(
|
|
48
|
-
'INTERVAL',
|
|
49
|
-
'CRON',
|
|
50
|
-
'MANUAL'
|
|
51
|
-
),
|
|
52
|
-
allowNull: false,
|
|
53
|
-
defaultValue: 'MANUAL',
|
|
54
|
-
comment: 'How the rule is triggered',
|
|
55
|
-
},
|
|
56
|
-
scheduleConfig: {
|
|
57
|
-
type: DataTypes.JSONB,
|
|
58
|
-
allowNull: true,
|
|
59
|
-
comment: 'Schedule configuration (interval minutes, cron expression, etc.)',
|
|
60
|
-
},
|
|
61
|
-
gcpJobName: {
|
|
62
|
-
type: DataTypes.STRING(255),
|
|
63
|
-
allowNull: true,
|
|
64
|
-
comment: 'GCP Cloud Scheduler job name for this rule',
|
|
65
|
-
},
|
|
66
|
-
lastExecuted: {
|
|
67
|
-
type: DataTypes.DATE,
|
|
68
|
-
allowNull: true,
|
|
69
|
-
comment: 'When the rule was last executed',
|
|
70
|
-
},
|
|
71
|
-
nextExecution: {
|
|
72
|
-
type: DataTypes.DATE,
|
|
73
|
-
allowNull: true,
|
|
74
|
-
comment: 'When the rule is scheduled to run next',
|
|
75
|
-
},
|
|
76
|
-
executionCount: {
|
|
77
|
-
type: DataTypes.INTEGER,
|
|
78
|
-
defaultValue: 0,
|
|
79
|
-
allowNull: false,
|
|
80
|
-
comment: 'Number of times this rule has been executed',
|
|
81
|
-
},
|
|
82
|
-
successCount: {
|
|
83
|
-
type: DataTypes.INTEGER,
|
|
84
|
-
defaultValue: 0,
|
|
85
|
-
allowNull: false,
|
|
86
|
-
comment: 'Number of successful executions',
|
|
87
|
-
},
|
|
88
|
-
failureCount: {
|
|
89
|
-
type: DataTypes.INTEGER,
|
|
90
|
-
defaultValue: 0,
|
|
91
|
-
allowNull: false,
|
|
92
|
-
comment: 'Number of failed executions',
|
|
93
|
-
},
|
|
94
|
-
createdBy: {
|
|
95
|
-
type: DataTypes.STRING(255),
|
|
96
|
-
allowNull: true,
|
|
97
|
-
comment: 'User who created this rule',
|
|
98
|
-
},
|
|
99
|
-
updatedBy: {
|
|
100
|
-
type: DataTypes.STRING(255),
|
|
101
|
-
allowNull: true,
|
|
102
|
-
comment: 'User who last updated this rule',
|
|
103
|
-
},
|
|
104
|
-
}, {
|
|
105
|
-
tableName: 'Rules',
|
|
106
|
-
timestamps: true,
|
|
107
|
-
indexes: [
|
|
108
|
-
{
|
|
109
|
-
fields: ['isActive'],
|
|
4
|
+
const Rule = sequelize.define(
|
|
5
|
+
"Rule",
|
|
6
|
+
{
|
|
7
|
+
id: {
|
|
8
|
+
type: DataTypes.UUID,
|
|
9
|
+
defaultValue: DataTypes.UUIDV4,
|
|
10
|
+
primaryKey: true,
|
|
110
11
|
},
|
|
111
|
-
{
|
|
112
|
-
|
|
12
|
+
name: {
|
|
13
|
+
type: DataTypes.STRING,
|
|
14
|
+
allowNull: false,
|
|
15
|
+
comment: "Rule name for identification",
|
|
113
16
|
},
|
|
114
|
-
{
|
|
115
|
-
|
|
17
|
+
code: {
|
|
18
|
+
type: DataTypes.STRING,
|
|
19
|
+
allowNull: false,
|
|
20
|
+
unique: true,
|
|
21
|
+
comment: "Unique code for the rule",
|
|
116
22
|
},
|
|
117
|
-
{
|
|
118
|
-
|
|
23
|
+
permissions: {
|
|
24
|
+
type: DataTypes.ARRAY(DataTypes.STRING),
|
|
25
|
+
allowNull: false,
|
|
26
|
+
defaultValue: [],
|
|
27
|
+
comment: "Permissions required for this rule",
|
|
119
28
|
},
|
|
120
|
-
{
|
|
121
|
-
|
|
29
|
+
feature: {
|
|
30
|
+
type: DataTypes.STRING,
|
|
31
|
+
allowNull: true,
|
|
32
|
+
comment: "Feature this rule belongs to",
|
|
122
33
|
},
|
|
123
|
-
{
|
|
124
|
-
|
|
34
|
+
parentId: {
|
|
35
|
+
type: DataTypes.UUID,
|
|
36
|
+
allowNull: true,
|
|
37
|
+
references: {
|
|
38
|
+
model: "RulesValues",
|
|
39
|
+
key: "id",
|
|
40
|
+
},
|
|
41
|
+
onDelete: "CASCADE",
|
|
42
|
+
comment: "Parent rule ID for hierarchical rules",
|
|
125
43
|
},
|
|
126
|
-
|
|
127
|
-
|
|
44
|
+
// Additional fields for the new rules system
|
|
45
|
+
description: {
|
|
46
|
+
type: DataTypes.TEXT,
|
|
47
|
+
allowNull: true,
|
|
48
|
+
comment: "Optional description of what this rule does",
|
|
49
|
+
},
|
|
50
|
+
isActive: {
|
|
51
|
+
type: DataTypes.BOOLEAN,
|
|
52
|
+
defaultValue: true,
|
|
53
|
+
allowNull: false,
|
|
54
|
+
comment: "Whether the rule is currently active",
|
|
55
|
+
},
|
|
56
|
+
ruleType: {
|
|
57
|
+
type: DataTypes.ENUM("PAUSE", "BUDGET", "BID", "STATUS", "CUSTOM"),
|
|
58
|
+
allowNull: true,
|
|
59
|
+
comment: "Type of rule - determines the action category",
|
|
60
|
+
},
|
|
61
|
+
targetLevel: {
|
|
62
|
+
type: DataTypes.ENUM("CAMPAIGN", "ADSET", "AD"),
|
|
63
|
+
allowNull: true,
|
|
64
|
+
comment: "Level at which the rule operates",
|
|
65
|
+
},
|
|
66
|
+
scheduleType: {
|
|
67
|
+
type: DataTypes.ENUM("INTERVAL", "CRON", "MANUAL"),
|
|
68
|
+
allowNull: true,
|
|
69
|
+
defaultValue: "MANUAL",
|
|
70
|
+
comment: "How the rule is triggered",
|
|
71
|
+
},
|
|
72
|
+
scheduleConfig: {
|
|
73
|
+
type: DataTypes.JSONB,
|
|
74
|
+
allowNull: true,
|
|
75
|
+
comment:
|
|
76
|
+
"Schedule configuration (interval minutes, cron expression, etc.)",
|
|
77
|
+
},
|
|
78
|
+
gcpJobName: {
|
|
79
|
+
type: DataTypes.STRING(255),
|
|
80
|
+
allowNull: true,
|
|
81
|
+
comment: "GCP Cloud Scheduler job name for this rule",
|
|
82
|
+
},
|
|
83
|
+
lastExecuted: {
|
|
84
|
+
type: DataTypes.DATE,
|
|
85
|
+
allowNull: true,
|
|
86
|
+
comment: "When the rule was last executed",
|
|
87
|
+
},
|
|
88
|
+
nextExecution: {
|
|
89
|
+
type: DataTypes.DATE,
|
|
90
|
+
allowNull: true,
|
|
91
|
+
comment: "When the rule is scheduled to run next",
|
|
92
|
+
},
|
|
93
|
+
executionCount: {
|
|
94
|
+
type: DataTypes.INTEGER,
|
|
95
|
+
defaultValue: 0,
|
|
96
|
+
allowNull: false,
|
|
97
|
+
comment: "Number of times this rule has been executed",
|
|
98
|
+
},
|
|
99
|
+
successCount: {
|
|
100
|
+
type: DataTypes.INTEGER,
|
|
101
|
+
defaultValue: 0,
|
|
102
|
+
allowNull: false,
|
|
103
|
+
comment: "Number of successful executions",
|
|
104
|
+
},
|
|
105
|
+
failureCount: {
|
|
106
|
+
type: DataTypes.INTEGER,
|
|
107
|
+
defaultValue: 0,
|
|
108
|
+
allowNull: false,
|
|
109
|
+
comment: "Number of failed executions",
|
|
110
|
+
},
|
|
111
|
+
createdBy: {
|
|
112
|
+
type: DataTypes.STRING(255),
|
|
113
|
+
allowNull: true,
|
|
114
|
+
comment: "User who created this rule",
|
|
115
|
+
},
|
|
116
|
+
updatedBy: {
|
|
117
|
+
type: DataTypes.STRING(255),
|
|
118
|
+
allowNull: true,
|
|
119
|
+
comment: "User who last updated this rule",
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
tableName: "RulesValues", // Use the existing table name
|
|
124
|
+
timestamps: true,
|
|
125
|
+
// Remove indexes from model definition - they will be created by migration
|
|
126
|
+
}
|
|
127
|
+
);
|
|
128
128
|
|
|
129
129
|
Rule.associate = (models) => {
|
|
130
130
|
// A rule has many conditions
|
|
131
131
|
Rule.hasMany(models.RuleCondition, {
|
|
132
|
-
foreignKey:
|
|
133
|
-
as:
|
|
134
|
-
onDelete:
|
|
132
|
+
foreignKey: "ruleId",
|
|
133
|
+
as: "conditions",
|
|
134
|
+
onDelete: "CASCADE",
|
|
135
135
|
});
|
|
136
136
|
|
|
137
137
|
// A rule has many actions
|
|
138
138
|
Rule.hasMany(models.RuleAction, {
|
|
139
|
-
foreignKey:
|
|
140
|
-
as:
|
|
141
|
-
onDelete:
|
|
139
|
+
foreignKey: "ruleId",
|
|
140
|
+
as: "actions",
|
|
141
|
+
onDelete: "CASCADE",
|
|
142
142
|
});
|
|
143
143
|
|
|
144
144
|
// A rule has many execution logs
|
|
145
145
|
Rule.hasMany(models.RuleExecution, {
|
|
146
|
-
foreignKey:
|
|
147
|
-
as:
|
|
148
|
-
onDelete:
|
|
146
|
+
foreignKey: "ruleId",
|
|
147
|
+
as: "executions",
|
|
148
|
+
onDelete: "CASCADE",
|
|
149
149
|
});
|
|
150
150
|
};
|
|
151
151
|
|
|
152
152
|
return Rule;
|
|
153
|
-
};
|
|
153
|
+
};
|
package/models/RuleAction.js
CHANGED
|
@@ -1,90 +1,85 @@
|
|
|
1
|
-
const { DataTypes } = require(
|
|
1
|
+
const { DataTypes } = require("sequelize");
|
|
2
2
|
|
|
3
3
|
module.exports = (sequelize) => {
|
|
4
|
-
const RuleAction = sequelize.define(
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
type: DataTypes.UUID,
|
|
12
|
-
allowNull: false,
|
|
13
|
-
references: {
|
|
14
|
-
model: 'Rules',
|
|
15
|
-
key: 'id',
|
|
4
|
+
const RuleAction = sequelize.define(
|
|
5
|
+
"RuleAction",
|
|
6
|
+
{
|
|
7
|
+
id: {
|
|
8
|
+
type: DataTypes.UUID,
|
|
9
|
+
defaultValue: DataTypes.UUIDV4,
|
|
10
|
+
primaryKey: true,
|
|
16
11
|
},
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
'CHANGE_CAMPAIGN_BID_STRATEGY',
|
|
26
|
-
|
|
27
|
-
// AdSet level actions
|
|
28
|
-
'PAUSE_ADSET',
|
|
29
|
-
'ACTIVATE_ADSET',
|
|
30
|
-
'CHANGE_ADSET_BUDGET',
|
|
31
|
-
'CHANGE_ADSET_BID',
|
|
32
|
-
'CHANGE_ADSET_BID_STRATEGY',
|
|
33
|
-
|
|
34
|
-
// Ad level actions
|
|
35
|
-
'PAUSE_AD',
|
|
36
|
-
'ACTIVATE_AD',
|
|
37
|
-
|
|
38
|
-
// Custom actions
|
|
39
|
-
'CUSTOM_ACTION'
|
|
40
|
-
),
|
|
41
|
-
allowNull: false,
|
|
42
|
-
comment: 'Type of action to perform',
|
|
43
|
-
},
|
|
44
|
-
actionConfig: {
|
|
45
|
-
type: DataTypes.JSONB,
|
|
46
|
-
allowNull: true,
|
|
47
|
-
comment: 'Configuration for the action (budget amount, bid strategy, etc.)',
|
|
48
|
-
},
|
|
49
|
-
order: {
|
|
50
|
-
type: DataTypes.INTEGER,
|
|
51
|
-
allowNull: false,
|
|
52
|
-
defaultValue: 0,
|
|
53
|
-
comment: 'Order of this action within the rule',
|
|
54
|
-
},
|
|
55
|
-
isActive: {
|
|
56
|
-
type: DataTypes.BOOLEAN,
|
|
57
|
-
defaultValue: true,
|
|
58
|
-
allowNull: false,
|
|
59
|
-
comment: 'Whether this action is active',
|
|
60
|
-
},
|
|
61
|
-
delayMinutes: {
|
|
62
|
-
type: DataTypes.INTEGER,
|
|
63
|
-
allowNull: true,
|
|
64
|
-
defaultValue: 0,
|
|
65
|
-
comment: 'Delay in minutes before executing this action',
|
|
66
|
-
},
|
|
67
|
-
}, {
|
|
68
|
-
tableName: 'RuleActions',
|
|
69
|
-
timestamps: true,
|
|
70
|
-
indexes: [
|
|
71
|
-
{
|
|
72
|
-
fields: ['ruleId'],
|
|
12
|
+
ruleId: {
|
|
13
|
+
type: DataTypes.UUID,
|
|
14
|
+
allowNull: false,
|
|
15
|
+
references: {
|
|
16
|
+
model: "RulesValues",
|
|
17
|
+
key: "id",
|
|
18
|
+
},
|
|
19
|
+
comment: "Reference to the parent rule",
|
|
73
20
|
},
|
|
74
|
-
{
|
|
75
|
-
|
|
21
|
+
actionType: {
|
|
22
|
+
type: DataTypes.ENUM(
|
|
23
|
+
// Campaign level actions
|
|
24
|
+
"PAUSE_CAMPAIGN",
|
|
25
|
+
"ACTIVATE_CAMPAIGN",
|
|
26
|
+
"CHANGE_CAMPAIGN_BUDGET",
|
|
27
|
+
"CHANGE_CAMPAIGN_BID_STRATEGY",
|
|
28
|
+
|
|
29
|
+
// AdSet level actions
|
|
30
|
+
"PAUSE_ADSET",
|
|
31
|
+
"ACTIVATE_ADSET",
|
|
32
|
+
"CHANGE_ADSET_BUDGET",
|
|
33
|
+
"CHANGE_ADSET_BID",
|
|
34
|
+
"CHANGE_ADSET_BID_STRATEGY",
|
|
35
|
+
|
|
36
|
+
// Ad level actions
|
|
37
|
+
"PAUSE_AD",
|
|
38
|
+
"ACTIVATE_AD",
|
|
39
|
+
|
|
40
|
+
// Custom actions
|
|
41
|
+
"CUSTOM_ACTION"
|
|
42
|
+
),
|
|
43
|
+
allowNull: false,
|
|
44
|
+
comment: "Type of action to perform",
|
|
45
|
+
},
|
|
46
|
+
actionConfig: {
|
|
47
|
+
type: DataTypes.JSONB,
|
|
48
|
+
allowNull: true,
|
|
49
|
+
comment:
|
|
50
|
+
"Configuration for the action (budget amount, bid strategy, etc.)",
|
|
76
51
|
},
|
|
77
|
-
{
|
|
78
|
-
|
|
52
|
+
order: {
|
|
53
|
+
type: DataTypes.INTEGER,
|
|
54
|
+
allowNull: false,
|
|
55
|
+
defaultValue: 0,
|
|
56
|
+
comment: "Order of this action within the rule",
|
|
79
57
|
},
|
|
80
|
-
|
|
81
|
-
|
|
58
|
+
isActive: {
|
|
59
|
+
type: DataTypes.BOOLEAN,
|
|
60
|
+
defaultValue: true,
|
|
61
|
+
allowNull: false,
|
|
62
|
+
comment: "Whether this action is active",
|
|
63
|
+
},
|
|
64
|
+
delayMinutes: {
|
|
65
|
+
type: DataTypes.INTEGER,
|
|
66
|
+
allowNull: true,
|
|
67
|
+
defaultValue: 0,
|
|
68
|
+
comment: "Delay in minutes before executing this action",
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
tableName: "RuleActions",
|
|
73
|
+
timestamps: true,
|
|
74
|
+
// Remove indexes from model definition - they will be created by migration
|
|
75
|
+
}
|
|
76
|
+
);
|
|
82
77
|
|
|
83
78
|
RuleAction.associate = (models) => {
|
|
84
79
|
// An action belongs to a rule
|
|
85
80
|
RuleAction.belongsTo(models.Rule, {
|
|
86
|
-
foreignKey:
|
|
87
|
-
as:
|
|
81
|
+
foreignKey: "ruleId",
|
|
82
|
+
as: "rule",
|
|
88
83
|
});
|
|
89
84
|
};
|
|
90
85
|
|
package/models/RuleCondition.js
CHANGED
|
@@ -1,95 +1,84 @@
|
|
|
1
|
-
const { DataTypes } = require(
|
|
1
|
+
const { DataTypes } = require("sequelize");
|
|
2
2
|
|
|
3
3
|
module.exports = (sequelize) => {
|
|
4
|
-
const RuleCondition = sequelize.define(
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
type: DataTypes.UUID,
|
|
12
|
-
allowNull: false,
|
|
13
|
-
references: {
|
|
14
|
-
model: 'Rules',
|
|
15
|
-
key: 'id',
|
|
4
|
+
const RuleCondition = sequelize.define(
|
|
5
|
+
"RuleCondition",
|
|
6
|
+
{
|
|
7
|
+
id: {
|
|
8
|
+
type: DataTypes.UUID,
|
|
9
|
+
defaultValue: DataTypes.UUIDV4,
|
|
10
|
+
primaryKey: true,
|
|
16
11
|
},
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
'GREATER_THAN_OR_EQUAL',
|
|
31
|
-
'LESS_THAN_OR_EQUAL',
|
|
32
|
-
'BETWEEN',
|
|
33
|
-
'IN',
|
|
34
|
-
'NOT_IN',
|
|
35
|
-
'CONTAINS',
|
|
36
|
-
'NOT_CONTAINS',
|
|
37
|
-
'IS_NULL',
|
|
38
|
-
'IS_NOT_NULL'
|
|
39
|
-
),
|
|
40
|
-
allowNull: false,
|
|
41
|
-
comment: 'Comparison operator',
|
|
42
|
-
},
|
|
43
|
-
value: {
|
|
44
|
-
type: DataTypes.JSONB,
|
|
45
|
-
allowNull: true,
|
|
46
|
-
comment: 'Value(s) to compare against (can be array for BETWEEN, IN, etc.)',
|
|
47
|
-
},
|
|
48
|
-
logicalOperator: {
|
|
49
|
-
type: DataTypes.ENUM(
|
|
50
|
-
'AND',
|
|
51
|
-
'OR'
|
|
52
|
-
),
|
|
53
|
-
allowNull: false,
|
|
54
|
-
defaultValue: 'AND',
|
|
55
|
-
comment: 'How this condition connects to the next one',
|
|
56
|
-
},
|
|
57
|
-
order: {
|
|
58
|
-
type: DataTypes.INTEGER,
|
|
59
|
-
allowNull: false,
|
|
60
|
-
defaultValue: 0,
|
|
61
|
-
comment: 'Order of this condition within the rule',
|
|
62
|
-
},
|
|
63
|
-
isActive: {
|
|
64
|
-
type: DataTypes.BOOLEAN,
|
|
65
|
-
defaultValue: true,
|
|
66
|
-
allowNull: false,
|
|
67
|
-
comment: 'Whether this condition is active',
|
|
68
|
-
},
|
|
69
|
-
}, {
|
|
70
|
-
tableName: 'RuleConditions',
|
|
71
|
-
timestamps: true,
|
|
72
|
-
indexes: [
|
|
73
|
-
{
|
|
74
|
-
fields: ['ruleId'],
|
|
12
|
+
ruleId: {
|
|
13
|
+
type: DataTypes.UUID,
|
|
14
|
+
allowNull: false,
|
|
15
|
+
references: {
|
|
16
|
+
model: "RulesValues",
|
|
17
|
+
key: "id",
|
|
18
|
+
},
|
|
19
|
+
comment: "Reference to the parent rule",
|
|
20
|
+
},
|
|
21
|
+
field: {
|
|
22
|
+
type: DataTypes.STRING(100),
|
|
23
|
+
allowNull: false,
|
|
24
|
+
comment: "Field to evaluate (e.g., roi, ctr, campaign_name)",
|
|
75
25
|
},
|
|
76
|
-
{
|
|
77
|
-
|
|
26
|
+
operator: {
|
|
27
|
+
type: DataTypes.ENUM(
|
|
28
|
+
"EQUALS",
|
|
29
|
+
"NOT_EQUALS",
|
|
30
|
+
"GREATER_THAN",
|
|
31
|
+
"LESS_THAN",
|
|
32
|
+
"GREATER_THAN_OR_EQUAL",
|
|
33
|
+
"LESS_THAN_OR_EQUAL",
|
|
34
|
+
"BETWEEN",
|
|
35
|
+
"IN",
|
|
36
|
+
"NOT_IN",
|
|
37
|
+
"CONTAINS",
|
|
38
|
+
"NOT_CONTAINS",
|
|
39
|
+
"IS_NULL",
|
|
40
|
+
"IS_NOT_NULL"
|
|
41
|
+
),
|
|
42
|
+
allowNull: false,
|
|
43
|
+
comment: "Comparison operator",
|
|
78
44
|
},
|
|
79
|
-
{
|
|
80
|
-
|
|
45
|
+
value: {
|
|
46
|
+
type: DataTypes.JSONB,
|
|
47
|
+
allowNull: true,
|
|
48
|
+
comment:
|
|
49
|
+
"Value(s) to compare against (can be array for BETWEEN, IN, etc.)",
|
|
81
50
|
},
|
|
82
|
-
{
|
|
83
|
-
|
|
51
|
+
logicalOperator: {
|
|
52
|
+
type: DataTypes.ENUM("AND", "OR"),
|
|
53
|
+
allowNull: false,
|
|
54
|
+
defaultValue: "AND",
|
|
55
|
+
comment: "How this condition connects to the next one",
|
|
84
56
|
},
|
|
85
|
-
|
|
86
|
-
|
|
57
|
+
order: {
|
|
58
|
+
type: DataTypes.INTEGER,
|
|
59
|
+
allowNull: false,
|
|
60
|
+
defaultValue: 0,
|
|
61
|
+
comment: "Order of this condition within the rule",
|
|
62
|
+
},
|
|
63
|
+
isActive: {
|
|
64
|
+
type: DataTypes.BOOLEAN,
|
|
65
|
+
defaultValue: true,
|
|
66
|
+
allowNull: false,
|
|
67
|
+
comment: "Whether this condition is active",
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
tableName: "RuleConditions",
|
|
72
|
+
timestamps: true,
|
|
73
|
+
// Remove indexes from model definition - they will be created by migration
|
|
74
|
+
}
|
|
75
|
+
);
|
|
87
76
|
|
|
88
77
|
RuleCondition.associate = (models) => {
|
|
89
78
|
// A condition belongs to a rule
|
|
90
79
|
RuleCondition.belongsTo(models.Rule, {
|
|
91
|
-
foreignKey:
|
|
92
|
-
as:
|
|
80
|
+
foreignKey: "ruleId",
|
|
81
|
+
as: "rule",
|
|
93
82
|
});
|
|
94
83
|
};
|
|
95
84
|
|
package/models/RuleExecution.js
CHANGED
|
@@ -1,118 +1,100 @@
|
|
|
1
|
-
const { DataTypes } = require(
|
|
1
|
+
const { DataTypes } = require("sequelize");
|
|
2
2
|
|
|
3
3
|
module.exports = (sequelize) => {
|
|
4
|
-
const RuleExecution = sequelize.define(
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
type: DataTypes.UUID,
|
|
12
|
-
allowNull: false,
|
|
13
|
-
references: {
|
|
14
|
-
model: 'Rules',
|
|
15
|
-
key: 'id',
|
|
4
|
+
const RuleExecution = sequelize.define(
|
|
5
|
+
"RuleExecution",
|
|
6
|
+
{
|
|
7
|
+
id: {
|
|
8
|
+
type: DataTypes.UUID,
|
|
9
|
+
defaultValue: DataTypes.UUIDV4,
|
|
10
|
+
primaryKey: true,
|
|
16
11
|
},
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
allowNull: true,
|
|
46
|
-
comment: 'When execution completed',
|
|
47
|
-
},
|
|
48
|
-
duration: {
|
|
49
|
-
type: DataTypes.INTEGER,
|
|
50
|
-
allowNull: true,
|
|
51
|
-
comment: 'Execution duration in milliseconds',
|
|
52
|
-
},
|
|
53
|
-
itemsEvaluated: {
|
|
54
|
-
type: DataTypes.INTEGER,
|
|
55
|
-
defaultValue: 0,
|
|
56
|
-
allowNull: false,
|
|
57
|
-
comment: 'Number of items (campaigns/adsets/ads) evaluated',
|
|
58
|
-
},
|
|
59
|
-
itemsMatched: {
|
|
60
|
-
type: DataTypes.INTEGER,
|
|
61
|
-
defaultValue: 0,
|
|
62
|
-
allowNull: false,
|
|
63
|
-
comment: 'Number of items that matched the conditions',
|
|
64
|
-
},
|
|
65
|
-
actionsExecuted: {
|
|
66
|
-
type: DataTypes.INTEGER,
|
|
67
|
-
defaultValue: 0,
|
|
68
|
-
allowNull: false,
|
|
69
|
-
comment: 'Number of actions successfully executed',
|
|
70
|
-
},
|
|
71
|
-
actionsFailed: {
|
|
72
|
-
type: DataTypes.INTEGER,
|
|
73
|
-
defaultValue: 0,
|
|
74
|
-
allowNull: false,
|
|
75
|
-
comment: 'Number of actions that failed',
|
|
76
|
-
},
|
|
77
|
-
errorMessage: {
|
|
78
|
-
type: DataTypes.TEXT,
|
|
79
|
-
allowNull: true,
|
|
80
|
-
comment: 'Error message if execution failed',
|
|
81
|
-
},
|
|
82
|
-
executionDetails: {
|
|
83
|
-
type: DataTypes.JSONB,
|
|
84
|
-
allowNull: true,
|
|
85
|
-
comment: 'Detailed execution results and logs',
|
|
86
|
-
},
|
|
87
|
-
triggeredBy: {
|
|
88
|
-
type: DataTypes.STRING(255),
|
|
89
|
-
allowNull: true,
|
|
90
|
-
comment: 'User or system that triggered the execution',
|
|
91
|
-
},
|
|
92
|
-
}, {
|
|
93
|
-
tableName: 'RuleExecutions',
|
|
94
|
-
timestamps: true,
|
|
95
|
-
indexes: [
|
|
96
|
-
{
|
|
97
|
-
fields: ['ruleId'],
|
|
12
|
+
ruleId: {
|
|
13
|
+
type: DataTypes.UUID,
|
|
14
|
+
allowNull: false,
|
|
15
|
+
references: {
|
|
16
|
+
model: "RulesValues",
|
|
17
|
+
key: "id",
|
|
18
|
+
},
|
|
19
|
+
comment: "Reference to the executed rule",
|
|
20
|
+
},
|
|
21
|
+
executionType: {
|
|
22
|
+
type: DataTypes.ENUM("SCHEDULED", "MANUAL", "API_TRIGGER"),
|
|
23
|
+
allowNull: false,
|
|
24
|
+
comment: "How the rule was triggered",
|
|
25
|
+
},
|
|
26
|
+
status: {
|
|
27
|
+
type: DataTypes.ENUM("RUNNING", "SUCCESS", "FAILED", "PARTIAL_SUCCESS"),
|
|
28
|
+
allowNull: false,
|
|
29
|
+
comment: "Execution status",
|
|
30
|
+
},
|
|
31
|
+
startTime: {
|
|
32
|
+
type: DataTypes.DATE,
|
|
33
|
+
allowNull: false,
|
|
34
|
+
comment: "When execution started",
|
|
35
|
+
},
|
|
36
|
+
endTime: {
|
|
37
|
+
type: DataTypes.DATE,
|
|
38
|
+
allowNull: true,
|
|
39
|
+
comment: "When execution completed",
|
|
98
40
|
},
|
|
99
|
-
{
|
|
100
|
-
|
|
41
|
+
duration: {
|
|
42
|
+
type: DataTypes.INTEGER,
|
|
43
|
+
allowNull: true,
|
|
44
|
+
comment: "Execution duration in milliseconds",
|
|
101
45
|
},
|
|
102
|
-
{
|
|
103
|
-
|
|
46
|
+
itemsEvaluated: {
|
|
47
|
+
type: DataTypes.INTEGER,
|
|
48
|
+
defaultValue: 0,
|
|
49
|
+
allowNull: false,
|
|
50
|
+
comment: "Number of items (campaigns/adsets/ads) evaluated",
|
|
104
51
|
},
|
|
105
|
-
{
|
|
106
|
-
|
|
52
|
+
itemsMatched: {
|
|
53
|
+
type: DataTypes.INTEGER,
|
|
54
|
+
defaultValue: 0,
|
|
55
|
+
allowNull: false,
|
|
56
|
+
comment: "Number of items that matched the conditions",
|
|
107
57
|
},
|
|
108
|
-
|
|
109
|
-
|
|
58
|
+
actionsExecuted: {
|
|
59
|
+
type: DataTypes.INTEGER,
|
|
60
|
+
defaultValue: 0,
|
|
61
|
+
allowNull: false,
|
|
62
|
+
comment: "Number of actions successfully executed",
|
|
63
|
+
},
|
|
64
|
+
actionsFailed: {
|
|
65
|
+
type: DataTypes.INTEGER,
|
|
66
|
+
defaultValue: 0,
|
|
67
|
+
allowNull: false,
|
|
68
|
+
comment: "Number of actions that failed",
|
|
69
|
+
},
|
|
70
|
+
errorMessage: {
|
|
71
|
+
type: DataTypes.TEXT,
|
|
72
|
+
allowNull: true,
|
|
73
|
+
comment: "Error message if execution failed",
|
|
74
|
+
},
|
|
75
|
+
executionDetails: {
|
|
76
|
+
type: DataTypes.JSONB,
|
|
77
|
+
allowNull: true,
|
|
78
|
+
comment: "Detailed execution results and logs",
|
|
79
|
+
},
|
|
80
|
+
triggeredBy: {
|
|
81
|
+
type: DataTypes.STRING(255),
|
|
82
|
+
allowNull: true,
|
|
83
|
+
comment: "User or system that triggered the execution",
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
tableName: "RuleExecutions",
|
|
88
|
+
timestamps: true,
|
|
89
|
+
// Remove indexes from model definition - they will be created by migration
|
|
90
|
+
}
|
|
91
|
+
);
|
|
110
92
|
|
|
111
93
|
RuleExecution.associate = (models) => {
|
|
112
94
|
// An execution belongs to a rule
|
|
113
95
|
RuleExecution.belongsTo(models.Rule, {
|
|
114
|
-
foreignKey:
|
|
115
|
-
as:
|
|
96
|
+
foreignKey: "ruleId",
|
|
97
|
+
as: "rule",
|
|
116
98
|
});
|
|
117
99
|
};
|
|
118
100
|
|