agrs-sequelize-sdk 1.2.78 → 1.2.80
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/migrations/add-requested-from-dashboard-to-articles.js +17 -17
- package/models/AdAccountValues.js +25 -25
- package/models/AdHistory.js +30 -30
- package/models/AdPerformance.js +89 -89
- package/models/AdSet.js +289 -289
- package/models/AdSetHistory.js +30 -30
- package/models/AdsetPerformance.js +126 -126
- package/models/Article.js +170 -170
- package/models/AutomationRule.js +127 -127
- package/models/Buyers.js +25 -25
- package/models/Campaign.js +145 -145
- package/models/CampaignCreationLog.js +280 -280
- package/models/CampaignHistory.js +33 -33
- package/models/Channel.js +55 -55
- package/models/Domain.js +25 -25
- package/models/DynamicFeed.js +89 -89
- package/models/ExplorAdsChannel.js +61 -61
- package/models/Feed.js +33 -33
- package/models/FrontStoryChannel.js +59 -59
- package/models/Pages.js +73 -73
- package/models/PipelineExecution.js +59 -59
- package/models/Presets.js +34 -34
- package/models/RSOCFeedCampaign.js +357 -357
- package/models/RsocKeywordPerformance.js +110 -110
- package/models/RuleAction.js +90 -90
- package/models/RuleCondition.js +98 -92
- package/models/RuleExecution.js +107 -102
- package/models/RulesValues.js +56 -56
- package/models/SupportedLocale.js +23 -23
- package/models/SyncHistory.js +249 -249
- package/models/TonicRSOCKeywordPerformance.js +122 -122
- package/models/Vertical.js +25 -25
- package/models/newFiles.js +110 -110
- package/package.json +21 -19
- package/run.sh +214 -214
- package/services/sequelizeService.js +63 -63
package/models/AutomationRule.js
CHANGED
|
@@ -1,127 +1,127 @@
|
|
|
1
|
-
module.exports = (sequelize, DataTypes) => {
|
|
2
|
-
const AutomationRule = sequelize.define(
|
|
3
|
-
"AutomationRule",
|
|
4
|
-
{
|
|
5
|
-
id: {
|
|
6
|
-
type: DataTypes.UUID,
|
|
7
|
-
defaultValue: DataTypes.UUIDV4,
|
|
8
|
-
primaryKey: true,
|
|
9
|
-
},
|
|
10
|
-
name: {
|
|
11
|
-
type: DataTypes.STRING,
|
|
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("PAUSE", "BUDGET", "BID", "STATUS", "CUSTOM"),
|
|
28
|
-
allowNull: true,
|
|
29
|
-
comment: "Type of rule - determines the action category",
|
|
30
|
-
},
|
|
31
|
-
targetLevel: {
|
|
32
|
-
type: DataTypes.ENUM("CAMPAIGN", "ADSET", "AD"),
|
|
33
|
-
allowNull: true,
|
|
34
|
-
comment: "Level at which the rule operates",
|
|
35
|
-
},
|
|
36
|
-
scheduleType: {
|
|
37
|
-
type: DataTypes.ENUM("INTERVAL", "CRON", "MANUAL"),
|
|
38
|
-
allowNull: true,
|
|
39
|
-
defaultValue: "MANUAL",
|
|
40
|
-
comment: "How the rule is triggered",
|
|
41
|
-
},
|
|
42
|
-
scheduleConfig: {
|
|
43
|
-
type: DataTypes.JSONB,
|
|
44
|
-
allowNull: true,
|
|
45
|
-
comment:
|
|
46
|
-
"Schedule configuration (interval minutes, cron expression, etc.)",
|
|
47
|
-
},
|
|
48
|
-
gcpJobName: {
|
|
49
|
-
type: DataTypes.STRING(255),
|
|
50
|
-
allowNull: true,
|
|
51
|
-
comment: "GCP Cloud Scheduler job name for this rule",
|
|
52
|
-
},
|
|
53
|
-
lastExecuted: {
|
|
54
|
-
type: DataTypes.DATE,
|
|
55
|
-
allowNull: true,
|
|
56
|
-
comment: "When the rule was last executed",
|
|
57
|
-
},
|
|
58
|
-
nextExecution: {
|
|
59
|
-
type: DataTypes.DATE,
|
|
60
|
-
allowNull: true,
|
|
61
|
-
comment: "When the rule is scheduled to run next",
|
|
62
|
-
},
|
|
63
|
-
executionCount: {
|
|
64
|
-
type: DataTypes.INTEGER,
|
|
65
|
-
defaultValue: 0,
|
|
66
|
-
allowNull: false,
|
|
67
|
-
comment: "Number of times this rule has been executed",
|
|
68
|
-
},
|
|
69
|
-
successCount: {
|
|
70
|
-
type: DataTypes.INTEGER,
|
|
71
|
-
defaultValue: 0,
|
|
72
|
-
allowNull: false,
|
|
73
|
-
comment: "Number of successful executions",
|
|
74
|
-
},
|
|
75
|
-
failureCount: {
|
|
76
|
-
type: DataTypes.INTEGER,
|
|
77
|
-
defaultValue: 0,
|
|
78
|
-
allowNull: false,
|
|
79
|
-
comment: "Number of failed executions",
|
|
80
|
-
},
|
|
81
|
-
createdBy: {
|
|
82
|
-
type: DataTypes.STRING(255),
|
|
83
|
-
allowNull: true,
|
|
84
|
-
comment: "User who created this rule",
|
|
85
|
-
},
|
|
86
|
-
updatedBy: {
|
|
87
|
-
type: DataTypes.STRING(255),
|
|
88
|
-
allowNull: true,
|
|
89
|
-
comment: "User who last updated this rule",
|
|
90
|
-
},
|
|
91
|
-
mediaBuyer: {
|
|
92
|
-
type: DataTypes.STRING(255),
|
|
93
|
-
allowNull: true,
|
|
94
|
-
comment: "Media buyer assigned to this rule for permissions",
|
|
95
|
-
},
|
|
96
|
-
},
|
|
97
|
-
{
|
|
98
|
-
tableName: "AutomationRules", // New table name
|
|
99
|
-
timestamps: true,
|
|
100
|
-
}
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
AutomationRule.associate = (models) => {
|
|
104
|
-
// A rule has many conditions
|
|
105
|
-
AutomationRule.hasMany(models.RuleCondition, {
|
|
106
|
-
foreignKey: "ruleId",
|
|
107
|
-
as: "conditions",
|
|
108
|
-
onDelete: "CASCADE",
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
// A rule has many actions
|
|
112
|
-
AutomationRule.hasMany(models.RuleAction, {
|
|
113
|
-
foreignKey: "ruleId",
|
|
114
|
-
as: "actions",
|
|
115
|
-
onDelete: "CASCADE",
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
// A rule has many execution logs
|
|
119
|
-
AutomationRule.hasMany(models.RuleExecution, {
|
|
120
|
-
foreignKey: "ruleId",
|
|
121
|
-
as: "executions",
|
|
122
|
-
onDelete: "CASCADE",
|
|
123
|
-
});
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
return AutomationRule;
|
|
127
|
-
};
|
|
1
|
+
module.exports = (sequelize, DataTypes) => {
|
|
2
|
+
const AutomationRule = sequelize.define(
|
|
3
|
+
"AutomationRule",
|
|
4
|
+
{
|
|
5
|
+
id: {
|
|
6
|
+
type: DataTypes.UUID,
|
|
7
|
+
defaultValue: DataTypes.UUIDV4,
|
|
8
|
+
primaryKey: true,
|
|
9
|
+
},
|
|
10
|
+
name: {
|
|
11
|
+
type: DataTypes.STRING,
|
|
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("PAUSE", "BUDGET", "BID", "STATUS", "CUSTOM"),
|
|
28
|
+
allowNull: true,
|
|
29
|
+
comment: "Type of rule - determines the action category",
|
|
30
|
+
},
|
|
31
|
+
targetLevel: {
|
|
32
|
+
type: DataTypes.ENUM("CAMPAIGN", "ADSET", "AD"),
|
|
33
|
+
allowNull: true,
|
|
34
|
+
comment: "Level at which the rule operates",
|
|
35
|
+
},
|
|
36
|
+
scheduleType: {
|
|
37
|
+
type: DataTypes.ENUM("INTERVAL", "CRON", "MANUAL"),
|
|
38
|
+
allowNull: true,
|
|
39
|
+
defaultValue: "MANUAL",
|
|
40
|
+
comment: "How the rule is triggered",
|
|
41
|
+
},
|
|
42
|
+
scheduleConfig: {
|
|
43
|
+
type: DataTypes.JSONB,
|
|
44
|
+
allowNull: true,
|
|
45
|
+
comment:
|
|
46
|
+
"Schedule configuration (interval minutes, cron expression, etc.)",
|
|
47
|
+
},
|
|
48
|
+
gcpJobName: {
|
|
49
|
+
type: DataTypes.STRING(255),
|
|
50
|
+
allowNull: true,
|
|
51
|
+
comment: "GCP Cloud Scheduler job name for this rule",
|
|
52
|
+
},
|
|
53
|
+
lastExecuted: {
|
|
54
|
+
type: DataTypes.DATE,
|
|
55
|
+
allowNull: true,
|
|
56
|
+
comment: "When the rule was last executed",
|
|
57
|
+
},
|
|
58
|
+
nextExecution: {
|
|
59
|
+
type: DataTypes.DATE,
|
|
60
|
+
allowNull: true,
|
|
61
|
+
comment: "When the rule is scheduled to run next",
|
|
62
|
+
},
|
|
63
|
+
executionCount: {
|
|
64
|
+
type: DataTypes.INTEGER,
|
|
65
|
+
defaultValue: 0,
|
|
66
|
+
allowNull: false,
|
|
67
|
+
comment: "Number of times this rule has been executed",
|
|
68
|
+
},
|
|
69
|
+
successCount: {
|
|
70
|
+
type: DataTypes.INTEGER,
|
|
71
|
+
defaultValue: 0,
|
|
72
|
+
allowNull: false,
|
|
73
|
+
comment: "Number of successful executions",
|
|
74
|
+
},
|
|
75
|
+
failureCount: {
|
|
76
|
+
type: DataTypes.INTEGER,
|
|
77
|
+
defaultValue: 0,
|
|
78
|
+
allowNull: false,
|
|
79
|
+
comment: "Number of failed executions",
|
|
80
|
+
},
|
|
81
|
+
createdBy: {
|
|
82
|
+
type: DataTypes.STRING(255),
|
|
83
|
+
allowNull: true,
|
|
84
|
+
comment: "User who created this rule",
|
|
85
|
+
},
|
|
86
|
+
updatedBy: {
|
|
87
|
+
type: DataTypes.STRING(255),
|
|
88
|
+
allowNull: true,
|
|
89
|
+
comment: "User who last updated this rule",
|
|
90
|
+
},
|
|
91
|
+
mediaBuyer: {
|
|
92
|
+
type: DataTypes.STRING(255),
|
|
93
|
+
allowNull: true,
|
|
94
|
+
comment: "Media buyer assigned to this rule for permissions",
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
tableName: "AutomationRules", // New table name
|
|
99
|
+
timestamps: true,
|
|
100
|
+
}
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
AutomationRule.associate = (models) => {
|
|
104
|
+
// A rule has many conditions
|
|
105
|
+
AutomationRule.hasMany(models.RuleCondition, {
|
|
106
|
+
foreignKey: "ruleId",
|
|
107
|
+
as: "conditions",
|
|
108
|
+
onDelete: "CASCADE",
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
// A rule has many actions
|
|
112
|
+
AutomationRule.hasMany(models.RuleAction, {
|
|
113
|
+
foreignKey: "ruleId",
|
|
114
|
+
as: "actions",
|
|
115
|
+
onDelete: "CASCADE",
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
// A rule has many execution logs
|
|
119
|
+
AutomationRule.hasMany(models.RuleExecution, {
|
|
120
|
+
foreignKey: "ruleId",
|
|
121
|
+
as: "executions",
|
|
122
|
+
onDelete: "CASCADE",
|
|
123
|
+
});
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
return AutomationRule;
|
|
127
|
+
};
|
package/models/Buyers.js
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
module.exports = (sequelize, DataTypes) => {
|
|
2
|
-
const Buyers = sequelize.define(
|
|
3
|
-
"Buyers",
|
|
4
|
-
{
|
|
5
|
-
id: {
|
|
6
|
-
type: DataTypes.UUID,
|
|
7
|
-
defaultValue: DataTypes.UUIDV4,
|
|
8
|
-
primaryKey: true,
|
|
9
|
-
},
|
|
10
|
-
name: {
|
|
11
|
-
type: DataTypes.STRING,
|
|
12
|
-
allowNull: false,
|
|
13
|
-
},
|
|
14
|
-
code: {
|
|
15
|
-
type: DataTypes.STRING,
|
|
16
|
-
allowNull: false,
|
|
17
|
-
unique: true,
|
|
18
|
-
},
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
tableName: "Buyers",
|
|
22
|
-
}
|
|
23
|
-
);
|
|
24
|
-
|
|
25
|
-
return Buyers;
|
|
1
|
+
module.exports = (sequelize, DataTypes) => {
|
|
2
|
+
const Buyers = sequelize.define(
|
|
3
|
+
"Buyers",
|
|
4
|
+
{
|
|
5
|
+
id: {
|
|
6
|
+
type: DataTypes.UUID,
|
|
7
|
+
defaultValue: DataTypes.UUIDV4,
|
|
8
|
+
primaryKey: true,
|
|
9
|
+
},
|
|
10
|
+
name: {
|
|
11
|
+
type: DataTypes.STRING,
|
|
12
|
+
allowNull: false,
|
|
13
|
+
},
|
|
14
|
+
code: {
|
|
15
|
+
type: DataTypes.STRING,
|
|
16
|
+
allowNull: false,
|
|
17
|
+
unique: true,
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
tableName: "Buyers",
|
|
22
|
+
}
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
return Buyers;
|
|
26
26
|
};
|
package/models/Campaign.js
CHANGED
|
@@ -1,145 +1,145 @@
|
|
|
1
|
-
module.exports = (sequelize, DataTypes) => {
|
|
2
|
-
const Campaign = sequelize.define(
|
|
3
|
-
"Campaign",
|
|
4
|
-
{
|
|
5
|
-
CampaignID: {
|
|
6
|
-
type: DataTypes.STRING,
|
|
7
|
-
primaryKey: true,
|
|
8
|
-
},
|
|
9
|
-
CampaignName: {
|
|
10
|
-
type: DataTypes.STRING,
|
|
11
|
-
allowNull: true,
|
|
12
|
-
},
|
|
13
|
-
pixelId: {
|
|
14
|
-
type: DataTypes.STRING,
|
|
15
|
-
allowNull: true,
|
|
16
|
-
},
|
|
17
|
-
customEventType: {
|
|
18
|
-
type: DataTypes.STRING,
|
|
19
|
-
allowNull: false,
|
|
20
|
-
defaultValue: "PURCHASE",
|
|
21
|
-
},
|
|
22
|
-
objective: {
|
|
23
|
-
type: DataTypes.STRING,
|
|
24
|
-
allowNull: false,
|
|
25
|
-
defaultValue: "OUTCOME_SALES",
|
|
26
|
-
},
|
|
27
|
-
status: {
|
|
28
|
-
type: DataTypes.STRING,
|
|
29
|
-
allowNull: true,
|
|
30
|
-
},
|
|
31
|
-
AdAccountID: {
|
|
32
|
-
type: DataTypes.STRING,
|
|
33
|
-
allowNull: false,
|
|
34
|
-
references: {
|
|
35
|
-
model: "AdAccount",
|
|
36
|
-
key: "AdAccountID",
|
|
37
|
-
},
|
|
38
|
-
},
|
|
39
|
-
CreatedTime: {
|
|
40
|
-
type: DataTypes.DATE,
|
|
41
|
-
allowNull: false,
|
|
42
|
-
},
|
|
43
|
-
CampaignDelivery: {
|
|
44
|
-
type: DataTypes.STRING,
|
|
45
|
-
allowNull: true,
|
|
46
|
-
},
|
|
47
|
-
DailyBudget: {
|
|
48
|
-
type: DataTypes.INTEGER,
|
|
49
|
-
allowNull: true,
|
|
50
|
-
},
|
|
51
|
-
Draft: {
|
|
52
|
-
type: DataTypes.BOOLEAN,
|
|
53
|
-
allowNull: true,
|
|
54
|
-
defaultValue: false,
|
|
55
|
-
},
|
|
56
|
-
publish: {
|
|
57
|
-
type: DataTypes.BOOLEAN,
|
|
58
|
-
allowNull: true,
|
|
59
|
-
defaultValue: true,
|
|
60
|
-
},
|
|
61
|
-
UserCreated: {
|
|
62
|
-
type: DataTypes.STRING,
|
|
63
|
-
allowNull: true,
|
|
64
|
-
},
|
|
65
|
-
special_ad_categories: {
|
|
66
|
-
type: DataTypes.ARRAY(DataTypes.STRING),
|
|
67
|
-
allowNull: true,
|
|
68
|
-
},
|
|
69
|
-
effectiveStatus: {
|
|
70
|
-
type: DataTypes.STRING,
|
|
71
|
-
allowNull: true,
|
|
72
|
-
},
|
|
73
|
-
issuesInfo: {
|
|
74
|
-
type: DataTypes.JSONB,
|
|
75
|
-
allowNull: true,
|
|
76
|
-
},
|
|
77
|
-
waiting: {
|
|
78
|
-
type: DataTypes.BOOLEAN,
|
|
79
|
-
defaultValue: false,
|
|
80
|
-
},
|
|
81
|
-
policy_status: {
|
|
82
|
-
type: DataTypes.STRING,
|
|
83
|
-
allowNull: true,
|
|
84
|
-
comment: "Facebook policy status: APPROVED, DENIED, PENDING, etc."
|
|
85
|
-
},
|
|
86
|
-
policy_rejection_reason: {
|
|
87
|
-
type: DataTypes.TEXT,
|
|
88
|
-
allowNull: true,
|
|
89
|
-
comment: "Detailed reason for policy rejection"
|
|
90
|
-
},
|
|
91
|
-
},
|
|
92
|
-
{
|
|
93
|
-
tableName: "Campaign",
|
|
94
|
-
indexes: [
|
|
95
|
-
{
|
|
96
|
-
fields: ["AdAccountID"], // Index on AdAccountID for faster joins
|
|
97
|
-
},
|
|
98
|
-
],
|
|
99
|
-
}
|
|
100
|
-
);
|
|
101
|
-
|
|
102
|
-
// Define associations
|
|
103
|
-
Campaign.associate = (models) => {
|
|
104
|
-
Campaign.belongsTo(models.AdAccount, { foreignKey: "AdAccountID" });
|
|
105
|
-
Campaign.hasMany(models.AdSet, { foreignKey: "CampaignID" });
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
// Combined beforeUpdate hook
|
|
109
|
-
Campaign.addHook("beforeUpdate", async (campaign, options) => {
|
|
110
|
-
if (campaign.changed("publish")) {
|
|
111
|
-
if (campaign.previous("publish") === true && campaign.publish === false) {
|
|
112
|
-
// Save current state to CampaignHistory
|
|
113
|
-
await sequelize.models.CampaignHistory.create({
|
|
114
|
-
CampaignID: campaign.CampaignID,
|
|
115
|
-
DataSnapshot: campaign._previousDataValues, // Store current state as JSON
|
|
116
|
-
});
|
|
117
|
-
} else if (
|
|
118
|
-
campaign.previous("publish") === false &&
|
|
119
|
-
campaign.publish === true
|
|
120
|
-
) {
|
|
121
|
-
// Delete the latest history entry
|
|
122
|
-
const latestHistory = await sequelize.models.CampaignHistory.findOne({
|
|
123
|
-
where: { CampaignID: campaign.CampaignID },
|
|
124
|
-
order: [["timestamp", "DESC"]], // Get the latest history entry
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
if (latestHistory) {
|
|
128
|
-
await latestHistory.destroy(); // Delete the latest history entry
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
Campaign.addHook("afterCreate", async (campaign, options) => {
|
|
135
|
-
if (campaign.publish === false) {
|
|
136
|
-
// If publish is false on creation, save a snapshot to CampaignHistory
|
|
137
|
-
await sequelize.models.CampaignHistory.create({
|
|
138
|
-
CampaignID: campaign.CampaignID,
|
|
139
|
-
DataSnapshot: campaign.toJSON(), // Save current state
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
return Campaign;
|
|
145
|
-
};
|
|
1
|
+
module.exports = (sequelize, DataTypes) => {
|
|
2
|
+
const Campaign = sequelize.define(
|
|
3
|
+
"Campaign",
|
|
4
|
+
{
|
|
5
|
+
CampaignID: {
|
|
6
|
+
type: DataTypes.STRING,
|
|
7
|
+
primaryKey: true,
|
|
8
|
+
},
|
|
9
|
+
CampaignName: {
|
|
10
|
+
type: DataTypes.STRING,
|
|
11
|
+
allowNull: true,
|
|
12
|
+
},
|
|
13
|
+
pixelId: {
|
|
14
|
+
type: DataTypes.STRING,
|
|
15
|
+
allowNull: true,
|
|
16
|
+
},
|
|
17
|
+
customEventType: {
|
|
18
|
+
type: DataTypes.STRING,
|
|
19
|
+
allowNull: false,
|
|
20
|
+
defaultValue: "PURCHASE",
|
|
21
|
+
},
|
|
22
|
+
objective: {
|
|
23
|
+
type: DataTypes.STRING,
|
|
24
|
+
allowNull: false,
|
|
25
|
+
defaultValue: "OUTCOME_SALES",
|
|
26
|
+
},
|
|
27
|
+
status: {
|
|
28
|
+
type: DataTypes.STRING,
|
|
29
|
+
allowNull: true,
|
|
30
|
+
},
|
|
31
|
+
AdAccountID: {
|
|
32
|
+
type: DataTypes.STRING,
|
|
33
|
+
allowNull: false,
|
|
34
|
+
references: {
|
|
35
|
+
model: "AdAccount",
|
|
36
|
+
key: "AdAccountID",
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
CreatedTime: {
|
|
40
|
+
type: DataTypes.DATE,
|
|
41
|
+
allowNull: false,
|
|
42
|
+
},
|
|
43
|
+
CampaignDelivery: {
|
|
44
|
+
type: DataTypes.STRING,
|
|
45
|
+
allowNull: true,
|
|
46
|
+
},
|
|
47
|
+
DailyBudget: {
|
|
48
|
+
type: DataTypes.INTEGER,
|
|
49
|
+
allowNull: true,
|
|
50
|
+
},
|
|
51
|
+
Draft: {
|
|
52
|
+
type: DataTypes.BOOLEAN,
|
|
53
|
+
allowNull: true,
|
|
54
|
+
defaultValue: false,
|
|
55
|
+
},
|
|
56
|
+
publish: {
|
|
57
|
+
type: DataTypes.BOOLEAN,
|
|
58
|
+
allowNull: true,
|
|
59
|
+
defaultValue: true,
|
|
60
|
+
},
|
|
61
|
+
UserCreated: {
|
|
62
|
+
type: DataTypes.STRING,
|
|
63
|
+
allowNull: true,
|
|
64
|
+
},
|
|
65
|
+
special_ad_categories: {
|
|
66
|
+
type: DataTypes.ARRAY(DataTypes.STRING),
|
|
67
|
+
allowNull: true,
|
|
68
|
+
},
|
|
69
|
+
effectiveStatus: {
|
|
70
|
+
type: DataTypes.STRING,
|
|
71
|
+
allowNull: true,
|
|
72
|
+
},
|
|
73
|
+
issuesInfo: {
|
|
74
|
+
type: DataTypes.JSONB,
|
|
75
|
+
allowNull: true,
|
|
76
|
+
},
|
|
77
|
+
waiting: {
|
|
78
|
+
type: DataTypes.BOOLEAN,
|
|
79
|
+
defaultValue: false,
|
|
80
|
+
},
|
|
81
|
+
policy_status: {
|
|
82
|
+
type: DataTypes.STRING,
|
|
83
|
+
allowNull: true,
|
|
84
|
+
comment: "Facebook policy status: APPROVED, DENIED, PENDING, etc."
|
|
85
|
+
},
|
|
86
|
+
policy_rejection_reason: {
|
|
87
|
+
type: DataTypes.TEXT,
|
|
88
|
+
allowNull: true,
|
|
89
|
+
comment: "Detailed reason for policy rejection"
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
tableName: "Campaign",
|
|
94
|
+
indexes: [
|
|
95
|
+
{
|
|
96
|
+
fields: ["AdAccountID"], // Index on AdAccountID for faster joins
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
}
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
// Define associations
|
|
103
|
+
Campaign.associate = (models) => {
|
|
104
|
+
Campaign.belongsTo(models.AdAccount, { foreignKey: "AdAccountID" });
|
|
105
|
+
Campaign.hasMany(models.AdSet, { foreignKey: "CampaignID" });
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
// Combined beforeUpdate hook
|
|
109
|
+
Campaign.addHook("beforeUpdate", async (campaign, options) => {
|
|
110
|
+
if (campaign.changed("publish")) {
|
|
111
|
+
if (campaign.previous("publish") === true && campaign.publish === false) {
|
|
112
|
+
// Save current state to CampaignHistory
|
|
113
|
+
await sequelize.models.CampaignHistory.create({
|
|
114
|
+
CampaignID: campaign.CampaignID,
|
|
115
|
+
DataSnapshot: campaign._previousDataValues, // Store current state as JSON
|
|
116
|
+
});
|
|
117
|
+
} else if (
|
|
118
|
+
campaign.previous("publish") === false &&
|
|
119
|
+
campaign.publish === true
|
|
120
|
+
) {
|
|
121
|
+
// Delete the latest history entry
|
|
122
|
+
const latestHistory = await sequelize.models.CampaignHistory.findOne({
|
|
123
|
+
where: { CampaignID: campaign.CampaignID },
|
|
124
|
+
order: [["timestamp", "DESC"]], // Get the latest history entry
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
if (latestHistory) {
|
|
128
|
+
await latestHistory.destroy(); // Delete the latest history entry
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
Campaign.addHook("afterCreate", async (campaign, options) => {
|
|
135
|
+
if (campaign.publish === false) {
|
|
136
|
+
// If publish is false on creation, save a snapshot to CampaignHistory
|
|
137
|
+
await sequelize.models.CampaignHistory.create({
|
|
138
|
+
CampaignID: campaign.CampaignID,
|
|
139
|
+
DataSnapshot: campaign.toJSON(), // Save current state
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
return Campaign;
|
|
145
|
+
};
|