agrs-sequelize-sdk 1.0.0
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/LICENSE +21 -0
- package/README.md +1 -0
- package/config/config.json +24 -0
- package/index.js +69 -0
- package/models/ActivityHistory.js +73 -0
- package/models/Ad.js +140 -0
- package/models/AdAccount.js +90 -0
- package/models/AdCreative.js +57 -0
- package/models/AdPerformance.js +65 -0
- package/models/AdPerformanceHourly.js +51 -0
- package/models/AdSet.js +69 -0
- package/models/Campaign.js +112 -0
- package/models/CodefuelCampaign.js +112 -0
- package/models/CodefuelCampaignKWHistory.js +41 -0
- package/models/CodefuelKeywords.js +35 -0
- package/models/CurrencyRate.js +27 -0
- package/models/Files.js +64 -0
- package/models/Folders.js +37 -0
- package/models/KeywordPerformance.js +65 -0
- package/models/KeywordRotationState.js +46 -0
- package/models/Rule.js +39 -0
- package/models/TonicCampaign.js +97 -0
- package/models/Users.js +41 -0
- package/models/pixel.js +33 -0
- package/models/pixels.js +33 -0
- package/package.json +19 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Agressive Scale LTD
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# agrs-sequelize
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"development": {
|
|
3
|
+
"username": "postgres",
|
|
4
|
+
"password": "1234",
|
|
5
|
+
"database": "dev-db",
|
|
6
|
+
"host": "localhost",
|
|
7
|
+
"port": 5432,
|
|
8
|
+
"dialect": "postgres"
|
|
9
|
+
},
|
|
10
|
+
"test": {
|
|
11
|
+
"username": "root",
|
|
12
|
+
"password": "1234",
|
|
13
|
+
"database": "test-db",
|
|
14
|
+
"host": "127:0.0.1",
|
|
15
|
+
"dialect": "postgres"
|
|
16
|
+
},
|
|
17
|
+
"production": {
|
|
18
|
+
"username": "root",
|
|
19
|
+
"password": "1234",
|
|
20
|
+
"database": "prod-db",
|
|
21
|
+
"host": "127:0.0.1",
|
|
22
|
+
"dialect": "postgres"
|
|
23
|
+
}
|
|
24
|
+
}
|
package/index.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
const Sequelize = require("sequelize");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
|
|
5
|
+
// const env = process.env.NODE_ENV || "development";
|
|
6
|
+
class DBModels {
|
|
7
|
+
constructor(config) {
|
|
8
|
+
this.config = config;
|
|
9
|
+
this.db = {};
|
|
10
|
+
|
|
11
|
+
// Initialize Sequelize
|
|
12
|
+
const sequelize = new Sequelize(
|
|
13
|
+
this.config .database,
|
|
14
|
+
this.config .username,
|
|
15
|
+
this.config .password,
|
|
16
|
+
{
|
|
17
|
+
host: this.config .host,
|
|
18
|
+
dialect: this.config .dialect,
|
|
19
|
+
port: this.config .port,
|
|
20
|
+
logging: false,
|
|
21
|
+
pool: {
|
|
22
|
+
max: 100,
|
|
23
|
+
min: 0,
|
|
24
|
+
acquire: 30000,
|
|
25
|
+
idle: 10000,
|
|
26
|
+
},
|
|
27
|
+
}
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
// // Initialize PaperTrail
|
|
31
|
+
// const PaperTrail = require("sequelize-paper-trail").init(sequelize, {
|
|
32
|
+
// userModel: false, // Optional: set this to true if you have a user model to track who made the changes
|
|
33
|
+
// enableRevisionChangeModel: true, // Optional: set this to true if you want to store the changes made to each revision
|
|
34
|
+
// });
|
|
35
|
+
// PaperTrail.defineModels(); // Define the Revision and RevisionChange models
|
|
36
|
+
|
|
37
|
+
// Load all models
|
|
38
|
+
fs.readdirSync(path.join(__dirname, "models"))
|
|
39
|
+
.filter((file) => {
|
|
40
|
+
return file.indexOf(".") !== 0 && file.slice(-3) === ".js";
|
|
41
|
+
})
|
|
42
|
+
.forEach((file) => {
|
|
43
|
+
const model = require(path.join(__dirname, "models", file))(
|
|
44
|
+
sequelize,
|
|
45
|
+
Sequelize.DataTypes
|
|
46
|
+
);
|
|
47
|
+
this.db[model.name] = model;
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// Apply PaperTrail to CodefuelCampaign model
|
|
51
|
+
// const CodefuelCampaign = db["CodefuelCampaign"];
|
|
52
|
+
// if (CodefuelCampaign) {
|
|
53
|
+
// CodefuelCampaign.Revisions = CodefuelCampaign.hasPaperTrail();
|
|
54
|
+
// }
|
|
55
|
+
|
|
56
|
+
// Set up associations
|
|
57
|
+
Object.keys(this.db).forEach((modelName) => {
|
|
58
|
+
if (this.db[modelName].associate) {
|
|
59
|
+
this.db[modelName].associate(this.db);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// Export the db object with Sequelize and models
|
|
64
|
+
this.db.sequelize = sequelize;
|
|
65
|
+
this.db.Sequelize = Sequelize;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
module.exports = DBModels;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// models/ActivityHistory.js
|
|
2
|
+
module.exports = (sequelize, DataTypes) => {
|
|
3
|
+
const ActivityHistory = sequelize.define(
|
|
4
|
+
"ActivityHistory",
|
|
5
|
+
{
|
|
6
|
+
ActivityHistoryID: {
|
|
7
|
+
type: DataTypes.INTEGER,
|
|
8
|
+
primaryKey: true,
|
|
9
|
+
autoIncrement: true,
|
|
10
|
+
},
|
|
11
|
+
AssociatedModelType: {
|
|
12
|
+
type: DataTypes.STRING,
|
|
13
|
+
allowNull: false, // Could be 'Ad', 'AdSet', 'Campaign', etc.
|
|
14
|
+
},
|
|
15
|
+
AssociatedModelID: {
|
|
16
|
+
type: DataTypes.STRING,
|
|
17
|
+
allowNull: false, // ID of the associated model
|
|
18
|
+
},
|
|
19
|
+
ActorID: {
|
|
20
|
+
type: DataTypes.STRING,
|
|
21
|
+
allowNull: true,
|
|
22
|
+
},
|
|
23
|
+
ActorName: {
|
|
24
|
+
type: DataTypes.STRING,
|
|
25
|
+
allowNull: true,
|
|
26
|
+
},
|
|
27
|
+
ApplicationName: {
|
|
28
|
+
type: DataTypes.STRING,
|
|
29
|
+
allowNull: true,
|
|
30
|
+
},
|
|
31
|
+
DateTimeInTimeZone: {
|
|
32
|
+
type: DataTypes.DATE,
|
|
33
|
+
allowNull: true,
|
|
34
|
+
},
|
|
35
|
+
EventType: {
|
|
36
|
+
type: DataTypes.STRING,
|
|
37
|
+
allowNull: true,
|
|
38
|
+
},
|
|
39
|
+
ObjectName: {
|
|
40
|
+
type: DataTypes.STRING,
|
|
41
|
+
allowNull: true,
|
|
42
|
+
},
|
|
43
|
+
ObjectType: {
|
|
44
|
+
type: DataTypes.STRING,
|
|
45
|
+
allowNull: true,
|
|
46
|
+
},
|
|
47
|
+
TranslatedEventType: {
|
|
48
|
+
type: DataTypes.STRING,
|
|
49
|
+
allowNull: true,
|
|
50
|
+
},
|
|
51
|
+
ObjectID: {
|
|
52
|
+
type: DataTypes.STRING,
|
|
53
|
+
allowNull: true,
|
|
54
|
+
},
|
|
55
|
+
ExtraData: {
|
|
56
|
+
type: DataTypes.JSONB,
|
|
57
|
+
allowNull: true,
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
tableName: "ActivityHistory",
|
|
62
|
+
indexes: [
|
|
63
|
+
{
|
|
64
|
+
unique: true,
|
|
65
|
+
name: "unique_index_on_date_object_event", // Custom name
|
|
66
|
+
fields: ["DateTimeInTimeZone", "ObjectID", "EventType"],
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
return ActivityHistory;
|
|
73
|
+
};
|
package/models/Ad.js
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
module.exports = (sequelize, DataTypes) => {
|
|
2
|
+
const Ad = sequelize.define(
|
|
3
|
+
"Ad",
|
|
4
|
+
{
|
|
5
|
+
AdID: {
|
|
6
|
+
type: DataTypes.STRING,
|
|
7
|
+
primaryKey: true,
|
|
8
|
+
},
|
|
9
|
+
AdName: {
|
|
10
|
+
type: DataTypes.STRING,
|
|
11
|
+
allowNull: false,
|
|
12
|
+
},
|
|
13
|
+
AdSetID: {
|
|
14
|
+
type: DataTypes.STRING,
|
|
15
|
+
allowNull: false,
|
|
16
|
+
references: {
|
|
17
|
+
model: "AdSet",
|
|
18
|
+
key: "AdSetID",
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
creativeId: {
|
|
22
|
+
type: DataTypes.STRING,
|
|
23
|
+
allowNull: true,
|
|
24
|
+
references: {
|
|
25
|
+
model: "AdCreative", // Assuming you have an AdCreative model
|
|
26
|
+
key: "id",
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
pixelId: {
|
|
30
|
+
type: DataTypes.STRING,
|
|
31
|
+
allowNull: true,
|
|
32
|
+
},
|
|
33
|
+
startTime: {
|
|
34
|
+
type: DataTypes.DATE,
|
|
35
|
+
allowNull: true,
|
|
36
|
+
},
|
|
37
|
+
endTime: {
|
|
38
|
+
type: DataTypes.DATE,
|
|
39
|
+
allowNull: true,
|
|
40
|
+
},
|
|
41
|
+
format: {
|
|
42
|
+
type: DataTypes.STRING,
|
|
43
|
+
allowNull: false,
|
|
44
|
+
defaultValue: "SINGLE",
|
|
45
|
+
},
|
|
46
|
+
imageHashes: {
|
|
47
|
+
type: DataTypes.ARRAY(DataTypes.STRING), // Array of image hashes
|
|
48
|
+
allowNull: true,
|
|
49
|
+
},
|
|
50
|
+
videoIds: {
|
|
51
|
+
type: DataTypes.ARRAY(DataTypes.STRING), // Array of video IDs
|
|
52
|
+
allowNull: true,
|
|
53
|
+
},
|
|
54
|
+
messages: {
|
|
55
|
+
type: DataTypes.ARRAY(DataTypes.STRING), // Array of primary text messages
|
|
56
|
+
allowNull: true,
|
|
57
|
+
},
|
|
58
|
+
headlines: {
|
|
59
|
+
type: DataTypes.ARRAY(DataTypes.STRING), // Array of headlines
|
|
60
|
+
allowNull: true,
|
|
61
|
+
},
|
|
62
|
+
websiteUrl: {
|
|
63
|
+
type: DataTypes.STRING,
|
|
64
|
+
allowNull: true,
|
|
65
|
+
},
|
|
66
|
+
actionTypes: {
|
|
67
|
+
type: DataTypes.STRING,
|
|
68
|
+
allowNull: false,
|
|
69
|
+
defaultValue: "offsite_conversion",
|
|
70
|
+
},
|
|
71
|
+
Status: {
|
|
72
|
+
type: DataTypes.STRING,
|
|
73
|
+
allowNull: true,
|
|
74
|
+
},
|
|
75
|
+
|
|
76
|
+
createdTime: {
|
|
77
|
+
type: DataTypes.DATE,
|
|
78
|
+
allowNull: true,
|
|
79
|
+
},
|
|
80
|
+
AGRS_CID: {
|
|
81
|
+
type: DataTypes.STRING,
|
|
82
|
+
allowNull: true,
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
tableName: "Ad",
|
|
87
|
+
indexes: [
|
|
88
|
+
{
|
|
89
|
+
fields: ["AdSetID"], // Index on AdSetID for faster join
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
}
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
Ad.associate = (models) => {
|
|
96
|
+
Ad.belongsTo(models.AdSet, { foreignKey: "AdSetID" });
|
|
97
|
+
|
|
98
|
+
// Association with CodefuelCampaign using AGRS_CID
|
|
99
|
+
Ad.belongsTo(models.CodefuelCampaign, {
|
|
100
|
+
foreignKey: "AGRS_CID",
|
|
101
|
+
targetKey: "AGRSCID",
|
|
102
|
+
as: "CodefuelCampaign",
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
Ad.hasMany(models.AdPerformance, {
|
|
106
|
+
foreignKey: "AdID",
|
|
107
|
+
});
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
// Method to dynamically fetch related campaign
|
|
111
|
+
Ad.prototype.getRelatedCampaign = async function () {
|
|
112
|
+
if (!this.AGRS_CID) return null;
|
|
113
|
+
|
|
114
|
+
const codefuelCampaign = await sequelize.models.CodefuelCampaign.findOne({
|
|
115
|
+
where: { AGRSCID: this.AGRS_CID },
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
if (codefuelCampaign) {
|
|
119
|
+
return {
|
|
120
|
+
type: "CodefuelCampaign",
|
|
121
|
+
data: codefuelCampaign,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const tonicCampaign = await sequelize.models.TonicCampaign.findOne({
|
|
126
|
+
where: { AGRSCID: this.AGRS_CID },
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
if (tonicCampaign) {
|
|
130
|
+
return {
|
|
131
|
+
type: "TonicCampaign",
|
|
132
|
+
data: tonicCampaign,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return null;
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
return Ad;
|
|
140
|
+
};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// module.exports = (sequelize, DataTypes) => {
|
|
2
|
+
// const AdAccount = sequelize.define(
|
|
3
|
+
// "AdAccount",
|
|
4
|
+
// {
|
|
5
|
+
// AdAccountID: {
|
|
6
|
+
// type: DataTypes.STRING,
|
|
7
|
+
// primaryKey: true,
|
|
8
|
+
// },
|
|
9
|
+
// AdAccountName: {
|
|
10
|
+
// type: DataTypes.STRING,
|
|
11
|
+
// allowNull: false,
|
|
12
|
+
// },
|
|
13
|
+
// AdAccountTimeZone: {
|
|
14
|
+
// type: DataTypes.STRING,
|
|
15
|
+
// allowNull: false,
|
|
16
|
+
// },
|
|
17
|
+
// Currency: {
|
|
18
|
+
// type: DataTypes.STRING,
|
|
19
|
+
// allowNull: false,
|
|
20
|
+
// },
|
|
21
|
+
// Rate: {
|
|
22
|
+
// type: DataTypes.FLOAT,
|
|
23
|
+
// allowNull: false,
|
|
24
|
+
// },
|
|
25
|
+
// UTCOffset: {
|
|
26
|
+
// type: DataTypes.INTEGER,
|
|
27
|
+
// allowNull: false,
|
|
28
|
+
// },
|
|
29
|
+
// },
|
|
30
|
+
// {
|
|
31
|
+
// tableName: "AdAccount",
|
|
32
|
+
// }
|
|
33
|
+
// );
|
|
34
|
+
|
|
35
|
+
// AdAccount.associate = (models) => {};
|
|
36
|
+
|
|
37
|
+
// return AdAccount;
|
|
38
|
+
// };
|
|
39
|
+
|
|
40
|
+
module.exports = (sequelize, DataTypes) => {
|
|
41
|
+
const AdAccount = sequelize.define(
|
|
42
|
+
"AdAccount",
|
|
43
|
+
{
|
|
44
|
+
AdAccountID: {
|
|
45
|
+
type: DataTypes.STRING,
|
|
46
|
+
primaryKey: true,
|
|
47
|
+
},
|
|
48
|
+
AdAccountName: {
|
|
49
|
+
type: DataTypes.STRING,
|
|
50
|
+
allowNull: false,
|
|
51
|
+
},
|
|
52
|
+
AdAccountTimeZone: {
|
|
53
|
+
type: DataTypes.STRING,
|
|
54
|
+
allowNull: false,
|
|
55
|
+
},
|
|
56
|
+
Currency: {
|
|
57
|
+
type: DataTypes.STRING,
|
|
58
|
+
allowNull: false,
|
|
59
|
+
},
|
|
60
|
+
Rate: {
|
|
61
|
+
type: DataTypes.FLOAT,
|
|
62
|
+
allowNull: false,
|
|
63
|
+
},
|
|
64
|
+
UTCOffset: {
|
|
65
|
+
type: DataTypes.INTEGER,
|
|
66
|
+
allowNull: false,
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
tableName: "AdAccount",
|
|
71
|
+
indexes: [
|
|
72
|
+
{
|
|
73
|
+
fields: ["AdAccountName"],
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
fields: ["Currency"],
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
}
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
AdAccount.associate = (models) => {
|
|
83
|
+
AdAccount.hasMany(models.Campaign, {
|
|
84
|
+
foreignKey: "AdAccountID",
|
|
85
|
+
as: "Campaigns",
|
|
86
|
+
});
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
return AdAccount;
|
|
90
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module.exports = (sequelize, DataTypes) => {
|
|
2
|
+
const AdCreative = sequelize.define("AdCreative", {
|
|
3
|
+
id: {
|
|
4
|
+
type: DataTypes.STRING,
|
|
5
|
+
primaryKey: true,
|
|
6
|
+
},
|
|
7
|
+
name: DataTypes.STRING,
|
|
8
|
+
adAccountId: {
|
|
9
|
+
type: DataTypes.STRING,
|
|
10
|
+
allowNull: false,
|
|
11
|
+
},
|
|
12
|
+
pageId: {
|
|
13
|
+
type: DataTypes.STRING,
|
|
14
|
+
allowNull: false,
|
|
15
|
+
},
|
|
16
|
+
imageHashes: {
|
|
17
|
+
type: DataTypes.ARRAY(DataTypes.STRING), // Array of image hash IDs (Foreign key to Files table)
|
|
18
|
+
allowNull: true,
|
|
19
|
+
},
|
|
20
|
+
videoIds: {
|
|
21
|
+
type: DataTypes.ARRAY(DataTypes.STRING), // Array of video file IDs (Foreign key to Files table)
|
|
22
|
+
allowNull: true,
|
|
23
|
+
},
|
|
24
|
+
messages: {
|
|
25
|
+
type: DataTypes.ARRAY(DataTypes.STRING), // Array of messages (primary text)
|
|
26
|
+
allowNull: true,
|
|
27
|
+
},
|
|
28
|
+
headlines: {
|
|
29
|
+
type: DataTypes.ARRAY(DataTypes.STRING), // Array of headlines
|
|
30
|
+
allowNull: true,
|
|
31
|
+
},
|
|
32
|
+
descriptions: {
|
|
33
|
+
type: DataTypes.ARRAY(DataTypes.STRING), // Array of descriptions
|
|
34
|
+
allowNull: true,
|
|
35
|
+
},
|
|
36
|
+
websiteUrl: {
|
|
37
|
+
type: DataTypes.STRING, // URL for the call to action
|
|
38
|
+
allowNull: false,
|
|
39
|
+
},
|
|
40
|
+
format: {
|
|
41
|
+
type: DataTypes.STRING,
|
|
42
|
+
allowNull: false,
|
|
43
|
+
defaultValue: "FLEXIBLE",
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// Define associations
|
|
48
|
+
AdCreative.associate = function (models) {
|
|
49
|
+
// Associate AdCreative with Ad (one-to-many)
|
|
50
|
+
AdCreative.hasMany(models.Ad, { foreignKey: "creativeId" });
|
|
51
|
+
|
|
52
|
+
// Associate AdCreative with Files (one-to-many)
|
|
53
|
+
AdCreative.hasMany(models.Files, { foreignKey: "id", sourceKey: "id" });
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
return AdCreative;
|
|
57
|
+
};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
module.exports = (sequelize, DataTypes) => {
|
|
2
|
+
const AdPerformance = sequelize.define(
|
|
3
|
+
"AdPerformance",
|
|
4
|
+
{
|
|
5
|
+
Date: {
|
|
6
|
+
type: DataTypes.DATEONLY,
|
|
7
|
+
primaryKey: true,
|
|
8
|
+
},
|
|
9
|
+
AdID: {
|
|
10
|
+
type: DataTypes.STRING,
|
|
11
|
+
allowNull: false,
|
|
12
|
+
primaryKey: true,
|
|
13
|
+
},
|
|
14
|
+
AmountSpent: {
|
|
15
|
+
type: DataTypes.FLOAT,
|
|
16
|
+
allowNull: true,
|
|
17
|
+
},
|
|
18
|
+
Impressions: {
|
|
19
|
+
type: DataTypes.INTEGER,
|
|
20
|
+
allowNull: true,
|
|
21
|
+
},
|
|
22
|
+
LinkClicks: {
|
|
23
|
+
type: DataTypes.INTEGER,
|
|
24
|
+
allowNull: true,
|
|
25
|
+
},
|
|
26
|
+
Revenue: {
|
|
27
|
+
type: DataTypes.FLOAT,
|
|
28
|
+
allowNull: true,
|
|
29
|
+
},
|
|
30
|
+
AdClicks: {
|
|
31
|
+
type: DataTypes.INTEGER,
|
|
32
|
+
allowNull: true,
|
|
33
|
+
},
|
|
34
|
+
Sessions: {
|
|
35
|
+
type: DataTypes.INTEGER,
|
|
36
|
+
allowNull: true,
|
|
37
|
+
},
|
|
38
|
+
originalSpend: {
|
|
39
|
+
type: DataTypes.FLOAT,
|
|
40
|
+
allowNull: true,
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
tableName: "AdPerformance",
|
|
45
|
+
indexes: [
|
|
46
|
+
{
|
|
47
|
+
unique: true,
|
|
48
|
+
fields: ["AdID", "Date"], // Composite unique index
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
fields: ["Date"], // Index on Date for faster range queries
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
fields: ["AdID"], // Index on AdID for faster join
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
}
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
AdPerformance.associate = (models) => {
|
|
61
|
+
AdPerformance.belongsTo(models.Ad, { foreignKey: "AdID" });
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
return AdPerformance;
|
|
65
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// models/AdPerformanceHourly.js
|
|
2
|
+
module.exports = (sequelize, DataTypes) => {
|
|
3
|
+
const AdPerformanceHourly = sequelize.define(
|
|
4
|
+
"AdPerformanceHourly",
|
|
5
|
+
{
|
|
6
|
+
Date: {
|
|
7
|
+
type: DataTypes.DATEONLY,
|
|
8
|
+
primaryKey: true,
|
|
9
|
+
},
|
|
10
|
+
Hour: {
|
|
11
|
+
type: DataTypes.INTEGER,
|
|
12
|
+
primaryKey: true,
|
|
13
|
+
},
|
|
14
|
+
AdID: {
|
|
15
|
+
type: DataTypes.STRING,
|
|
16
|
+
primaryKey: true,
|
|
17
|
+
},
|
|
18
|
+
AmountSpent: {
|
|
19
|
+
type: DataTypes.FLOAT,
|
|
20
|
+
allowNull: true,
|
|
21
|
+
},
|
|
22
|
+
Impressions: {
|
|
23
|
+
type: DataTypes.INTEGER,
|
|
24
|
+
allowNull: true,
|
|
25
|
+
},
|
|
26
|
+
LinkClicks: {
|
|
27
|
+
type: DataTypes.INTEGER,
|
|
28
|
+
allowNull: true,
|
|
29
|
+
},
|
|
30
|
+
originalSpend: {
|
|
31
|
+
type: DataTypes.FLOAT,
|
|
32
|
+
allowNull: true,
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
tableName: "AdPerformanceHourly",
|
|
37
|
+
indexes: [
|
|
38
|
+
{
|
|
39
|
+
unique: true,
|
|
40
|
+
fields: ["AdID", "Date", "Hour"],
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
}
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
AdPerformanceHourly.associate = (models) => {
|
|
47
|
+
AdPerformanceHourly.belongsTo(models.Ad, { foreignKey: "AdID" });
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
return AdPerformanceHourly;
|
|
51
|
+
};
|
package/models/AdSet.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
module.exports = (sequelize, DataTypes) => {
|
|
2
|
+
const AdSet = sequelize.define(
|
|
3
|
+
"AdSet",
|
|
4
|
+
{
|
|
5
|
+
AdSetID: {
|
|
6
|
+
type: DataTypes.STRING,
|
|
7
|
+
primaryKey: true,
|
|
8
|
+
},
|
|
9
|
+
AdSetName: {
|
|
10
|
+
type: DataTypes.STRING,
|
|
11
|
+
allowNull: true,
|
|
12
|
+
},
|
|
13
|
+
daily_budget: {
|
|
14
|
+
type: DataTypes.INTEGER,
|
|
15
|
+
allowNull: true,
|
|
16
|
+
},
|
|
17
|
+
start_time: {
|
|
18
|
+
type: DataTypes.DATE,
|
|
19
|
+
allowNull: true,
|
|
20
|
+
},
|
|
21
|
+
end_time: {
|
|
22
|
+
type: DataTypes.DATE,
|
|
23
|
+
allowNull: true,
|
|
24
|
+
},
|
|
25
|
+
targeting: {
|
|
26
|
+
type: DataTypes.JSONB,
|
|
27
|
+
allowNull: true,
|
|
28
|
+
},
|
|
29
|
+
promotedObject: {
|
|
30
|
+
type: DataTypes.JSONB, // Storing promoted object as a JSON object
|
|
31
|
+
allowNull: true,
|
|
32
|
+
},
|
|
33
|
+
BillingEvent: {
|
|
34
|
+
type: DataTypes.STRING,
|
|
35
|
+
allowNull: false,
|
|
36
|
+
defaultValue: "impressions", // Default value for BillingEvent
|
|
37
|
+
},
|
|
38
|
+
OptimizationGoal: {
|
|
39
|
+
type: DataTypes.STRING,
|
|
40
|
+
allowNull: false,
|
|
41
|
+
defaultValue: "offsite_conversions", // Default value for OptimizationGoal
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
CampaignID: {
|
|
45
|
+
type: DataTypes.STRING,
|
|
46
|
+
allowNull: false,
|
|
47
|
+
references: {
|
|
48
|
+
model: "Campaign",
|
|
49
|
+
key: "CampaignID",
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
tableName: "AdSet",
|
|
55
|
+
indexes: [
|
|
56
|
+
{
|
|
57
|
+
fields: ["CampaignID"], // Index on CampaignID for faster join
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
}
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
AdSet.associate = (models) => {
|
|
64
|
+
AdSet.belongsTo(models.Campaign, { foreignKey: "CampaignID" });
|
|
65
|
+
AdSet.hasMany(models.Ad, { foreignKey: "AdSetID" });
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
return AdSet;
|
|
69
|
+
};
|