agrs-sequelize-sdk 1.1.94 → 1.1.97

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/models/Ad.js +9 -73
  2. package/models/AdSet.js +0 -144
  3. package/models/RSOCFeedCampaign.js +10 -1
  4. package/package.json +1 -1
  5. package/agrs-sequelize/LICENSE +0 -21
  6. package/agrs-sequelize/README.md +0 -179
  7. package/agrs-sequelize/index.js +0 -169
  8. package/agrs-sequelize/jq.exe +0 -0
  9. package/agrs-sequelize/models/ActivityHistory.js +0 -73
  10. package/agrs-sequelize/models/Ad.js +0 -209
  11. package/agrs-sequelize/models/AdAccount.js +0 -91
  12. package/agrs-sequelize/models/AdAccountValues.js +0 -26
  13. package/agrs-sequelize/models/AdHistory.js +0 -30
  14. package/agrs-sequelize/models/AdPerformance.js +0 -84
  15. package/agrs-sequelize/models/AdPerformanceHourly.js +0 -66
  16. package/agrs-sequelize/models/AdSet.js +0 -140
  17. package/agrs-sequelize/models/AdSetHistory.js +0 -30
  18. package/agrs-sequelize/models/AdsetPerformance.js +0 -116
  19. package/agrs-sequelize/models/Article.js +0 -156
  20. package/agrs-sequelize/models/Buyers.js +0 -26
  21. package/agrs-sequelize/models/Campaign.js +0 -136
  22. package/agrs-sequelize/models/CampaignCreationLog.js +0 -86
  23. package/agrs-sequelize/models/CampaignHistory.js +0 -33
  24. package/agrs-sequelize/models/Channel.js +0 -55
  25. package/agrs-sequelize/models/CodefuelCampaign.js +0 -159
  26. package/agrs-sequelize/models/CodefuelCampaignKWHistory.js +0 -41
  27. package/agrs-sequelize/models/CodefuelKeywords.js +0 -35
  28. package/agrs-sequelize/models/CurrencyRate.js +0 -27
  29. package/agrs-sequelize/models/Domain.js +0 -26
  30. package/agrs-sequelize/models/ExplorAdsChannel.js +0 -62
  31. package/agrs-sequelize/models/Feed.js +0 -34
  32. package/agrs-sequelize/models/Files.js +0 -73
  33. package/agrs-sequelize/models/Folders.js +0 -133
  34. package/agrs-sequelize/models/KeywordPerformance.js +0 -99
  35. package/agrs-sequelize/models/KeywordRotationState.js +0 -51
  36. package/agrs-sequelize/models/Pages.js +0 -74
  37. package/agrs-sequelize/models/PipelineExecution.js +0 -46
  38. package/agrs-sequelize/models/RSOCFeedCampaign.js +0 -302
  39. package/agrs-sequelize/models/RsocKeywordPerformance.js +0 -111
  40. package/agrs-sequelize/models/Rule.js +0 -39
  41. package/agrs-sequelize/models/RulesValues.js +0 -56
  42. package/agrs-sequelize/models/SupportedLocale.js +0 -24
  43. package/agrs-sequelize/models/TonicCampaign.js +0 -97
  44. package/agrs-sequelize/models/Users.js +0 -111
  45. package/agrs-sequelize/models/Vertical.js +0 -26
  46. package/agrs-sequelize/models/newFiles.js +0 -68
  47. package/agrs-sequelize/models/pixel.js +0 -33
  48. package/agrs-sequelize/models/pixels.js +0 -33
  49. package/agrs-sequelize/package-lock.json +0 -405
  50. package/agrs-sequelize/package.json +0 -19
  51. package/agrs-sequelize/run.ps1 +0 -98
  52. package/agrs-sequelize/run.sh +0 -214
@@ -1,133 +0,0 @@
1
- module.exports = (sequelize, DataTypes) => {
2
- const Folders = sequelize.define("Folders", {
3
- id: {
4
- type: DataTypes.STRING,
5
- primaryKey: true,
6
- },
7
- ParentFolder: {
8
- type: DataTypes.STRING, // Self-referencing folder ID
9
- allowNull: true,
10
- },
11
- ParentFolders: {
12
- type: DataTypes.ARRAY(DataTypes.STRING), // Array of folder IDs
13
- allowNull: true,
14
- },
15
- name: {
16
- type: DataTypes.STRING,
17
- allowNull: false,
18
- },
19
- FilesCount: {
20
- type: DataTypes.INTEGER,
21
- allowNull: true,
22
- defaultValue: 0,
23
- }
24
- });
25
-
26
- Folders.associate = function (models) {
27
- // One-to-many: A folder can have many files
28
- Folders.hasMany(models.Files, { foreignKey: "ParentFolder", sourceKey: "id" });
29
-
30
- // Self-referencing: A folder can have subfolders
31
- Folders.hasMany(models.Folders, { foreignKey: "ParentFolder", sourceKey: "id" });
32
- Folders.belongsTo(models.Folders, { foreignKey: "ParentFolder", targetKey: "id" });
33
- };
34
-
35
- // Function to count files and subfolders for each parent folder in ParentFolders array
36
- Folders.countFilesAndSubfolders = async function (parentFolderIds) {
37
- try {
38
- const { Files } = sequelize.models; // Move the reference inside the function
39
-
40
- // Loop through each parent folder ID
41
- for (const parentFolderId of parentFolderIds) {
42
- // Find the parent folder by ID
43
- const parentFolder = await Folders.findOne({ where: { id: parentFolderId } });
44
-
45
- if (!parentFolder) {
46
- console.warn(`Folder with ID ${parentFolderId} not found.`);
47
- continue;
48
- }
49
-
50
- // Count the number of files directly under this folder
51
- const fileCount = await Files.count({
52
- where: { ParentFolder: parentFolder.id }
53
- });
54
-
55
- // Count the number of subfolders directly under this folder
56
- const subfolderCount = await Folders.count({
57
- where: { ParentFolder: parentFolder.id }
58
- });
59
-
60
- // Total count is files + subfolders
61
- const totalFilesCount = fileCount + subfolderCount;
62
-
63
- // Update the FilesCount field in the parent folder
64
- await parentFolder.update({ FilesCount: totalFilesCount });
65
- }
66
- } catch (error) {
67
- console.error(error);
68
- throw error;
69
- }
70
- };
71
-
72
- // Add a hook that triggers after a folder is created, updated, or deleted
73
- Folders.addHook('afterCreate', async (folder, options) => {
74
- if (folder.ParentFolders && folder.ParentFolders.length > 0) {
75
- await Folders.countFilesAndSubfolders(folder.ParentFolders);
76
- }
77
- });
78
-
79
- Folders.addHook('afterDestroy', async (folder, options) => {
80
- if (folder.ParentFolders && folder.ParentFolders.length > 0) {
81
- await Folders.countFilesAndSubfolders(folder.ParentFolders);
82
- }
83
- });
84
-
85
- Folders.addHook('afterUpdate', async (folder, options) => {
86
- if (folder.ParentFolders && folder.ParentFolders.length > 0) {
87
- await Folders.countFilesAndSubfolders(folder.ParentFolders);
88
- }
89
- });
90
-
91
- // Add hooks for Files
92
- sequelize.models.Files.addHook('afterCreate', async (file, options) => {
93
- if (file.ParentFolders && file.ParentFolders.length > 0) {
94
- await Folders.countFilesAndSubfolders(file.ParentFolders);
95
- } else if (file.ParentFolder) {
96
- await Folders.countFilesAndSubfolders([file.ParentFolder]);
97
- }
98
- });
99
-
100
- sequelize.models.Files.addHook('afterDestroy', async (file, options) => {
101
- if (file.ParentFolders && file.ParentFolders.length > 0) {
102
- await Folders.countFilesAndSubfolders(file.ParentFolders);
103
- } else if (file.ParentFolder) {
104
- await Folders.countFilesAndSubfolders([file.ParentFolder]);
105
- }
106
- });
107
-
108
- sequelize.models.Files.addHook('afterUpdate', async (file, options) => {
109
- if (file.ParentFolders && file.ParentFolders.length > 0) {
110
- await Folders.countFilesAndSubfolders(file.ParentFolders);
111
- } else if (file.ParentFolder) {
112
- await Folders.countFilesAndSubfolders([file.ParentFolder]);
113
- }
114
- });
115
-
116
- // Add a hook before saving the folder to check ParentFolders
117
- Folders.addHook('beforeSave', (folder, options) => {
118
- // If ParentFolders is an empty array or contains only nulls, set it to null
119
- if (folder.ParentFolders && (folder.ParentFolders.length === 0 || folder.ParentFolders.every(f => f === null))) {
120
- folder.ParentFolders = null;
121
- }
122
- });
123
-
124
- // You can also add this hook for files
125
- sequelize.models.Files.addHook('beforeSave', (file, options) => {
126
- // If ParentFolders is an empty array or contains only nulls, set it to null
127
- if (file.ParentFolders && (file.ParentFolders.length === 0 || file.ParentFolders.every(f => f === null))) {
128
- file.ParentFolders = null;
129
- }
130
- });
131
-
132
- return Folders;
133
- };
@@ -1,99 +0,0 @@
1
- module.exports = (sequelize, DataTypes) => {
2
- const KeywordPerformance = sequelize.define(
3
- "KeywordPerformance",
4
- {
5
- Date: {
6
- type: DataTypes.DATEONLY,
7
- primaryKey: true,
8
- },
9
- adID: {
10
- type: DataTypes.STRING,
11
- references: {
12
- model: "Ad",
13
- key: "AdID",
14
- },
15
- foreignKey: true,
16
- primaryKey: true,
17
- },
18
- Keyword: {
19
- type: DataTypes.STRING,
20
- allowNull: false,
21
- primaryKey: true,
22
- },
23
- Revenue: {
24
- type: DataTypes.FLOAT,
25
- allowNull: false,
26
- },
27
- Clicks: {
28
- type: DataTypes.INTEGER,
29
- allowNull: false,
30
- },
31
- TemplatedKeyword: {
32
- type: DataTypes.STRING,
33
- allowNull: true,
34
- },
35
- FirstAppearanceDate: {
36
- type: DataTypes.DATEONLY,
37
- allowNull: true,
38
- },
39
- },
40
-
41
- {
42
- tableName: "KeywordPerformance",
43
- indexes: [
44
- {
45
- unique: true,
46
- fields: ["adID", "Date", "Keyword"], // Composite unique index for fast lookups
47
- },
48
- {
49
- fields: ["Date"], // Index for date filtering
50
- },
51
- {
52
- fields: ["adID"], // Index for faster joins on adID
53
- },
54
- {
55
- fields: ["Keyword"], // Index for faster searches on Keyword
56
- },
57
- {
58
- fields: ["Revenue"], // Index to optimize sorting/filtering on Revenue
59
- },
60
- {
61
- fields: ["Clicks"], // Index to optimize sorting/filtering on Clicks
62
- },
63
- ],
64
- hooks: {
65
- beforeCreate: async (record, options) => {
66
- try {
67
- const existingKeyword =
68
- await sequelize.models.KeywordPerformance.findOne({
69
- where: {
70
- Keyword: sequelize.where(
71
- sequelize.fn("LOWER", sequelize.col("Keyword")),
72
- sequelize.fn("LOWER", record.Keyword)
73
- ),
74
- },
75
- attributes: ["FirstAppearanceDate"],
76
- transaction: options.transaction,
77
- });
78
-
79
- // If keyword exists, use its FirstAppearanceDate
80
- // If not, use the current record's Date
81
- record.FirstAppearanceDate =
82
- existingKeyword?.FirstAppearanceDate || record.Date;
83
- } catch (error) {
84
- console.error("Error in FirstAppearanceDate hook:", error);
85
- throw error;
86
- }
87
- },
88
- },
89
- }
90
- );
91
-
92
- KeywordPerformance.associate = (models) => {
93
- KeywordPerformance.belongsTo(models.Ad, {
94
- foreignKey: "adID",
95
- });
96
- };
97
-
98
- return KeywordPerformance;
99
- };
@@ -1,51 +0,0 @@
1
- // models/KeywordRotationState.js
2
- const { DataTypes } = require("sequelize");
3
-
4
- module.exports = (sequelize) => {
5
- const KeywordRotationState = sequelize.define("KeywordRotationState", {
6
- campaignId: {
7
- type: DataTypes.STRING,
8
- allowNull: false,
9
- primaryKey: true,
10
- },
11
- staticKeywords: {
12
- type: DataTypes.ARRAY(DataTypes.STRING),
13
- allowNull: false,
14
- defaultValue: [], // Default to empty array if no static keywords are provided
15
- },
16
- rotatingKeywords: {
17
- type: DataTypes.ARRAY(DataTypes.STRING),
18
- allowNull: false,
19
- defaultValue: [], // Default to empty array if no rotating keywords are provided
20
- },
21
- dynamic: {
22
- type: DataTypes.ARRAY(DataTypes.STRING),
23
- allowNull: false,
24
- defaultValue: [], // Default to empty array if no dynamic keywords are provided
25
- },
26
- offset: {
27
- type: DataTypes.INTEGER,
28
- allowNull: false,
29
- defaultValue: 0,
30
- },
31
- rotationTime: {
32
- type: DataTypes.STRING, // in minutes
33
- allowNull: false,
34
- },
35
- rotatingKeywordSlots: {
36
- type: DataTypes.INTEGER, // Number of keyword slots assigned to rotation
37
- allowNull: false,
38
- },
39
- lastRotationTime: {
40
- type: DataTypes.DATE,
41
- allowNull: true,
42
- },
43
- status: {
44
- type: DataTypes.STRING,
45
- allowNull: false,
46
- defaultValue: "Not Set", // Default to started when first created
47
- },
48
- });
49
-
50
- return KeywordRotationState;
51
- };
@@ -1,74 +0,0 @@
1
- module.exports = (sequelize, DataTypes) => {
2
- const Pages = sequelize.define(
3
- "Pages",
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
- link: {
20
- type: DataTypes.STRING,
21
- allowNull: true,
22
- },
23
- feedProvider: {
24
- type: DataTypes.ARRAY(DataTypes.STRING),
25
- allowNull: false,
26
- defaultValue: [], // Default value is an empty array
27
- },
28
- tasks: {
29
- type: DataTypes.ARRAY(DataTypes.STRING),
30
- allowNull: false,
31
- defaultValue: [], // Default value is an empty array
32
- },
33
- is_published:{
34
- type: DataTypes.BOOLEAN,
35
- allowNull: false,
36
- defaultValue: true,
37
- },
38
- Category: {
39
- type: DataTypes.STRING,
40
- allowNull: true,
41
- },
42
- Owner: {
43
- type: DataTypes.STRING,
44
- allowNull: true,
45
- },
46
- Status:{
47
- type: DataTypes.STRING,
48
- allowNull: true,
49
- },
50
- AdLibrary:{
51
- type: DataTypes.STRING,
52
- allowNull: true,
53
- },
54
- BusinessManager: {
55
- type: DataTypes.STRING,
56
- allowNull: true,
57
- },
58
- Users: {
59
- type: DataTypes.ARRAY(DataTypes.STRING),
60
- allowNull: false,
61
- defaultValue: [],
62
- },
63
- Archived: {
64
- type: DataTypes.BOOLEAN,
65
- allowNull: true,
66
- },
67
- },
68
- {
69
- tableName: "Pages",
70
- }
71
- );
72
-
73
- return Pages;
74
- };
@@ -1,46 +0,0 @@
1
- module.exports = (sequelize, DataTypes) => {
2
- const PipelineExecution = sequelize.define(
3
- "PipelineExecution",
4
- {
5
- id: {
6
- type: DataTypes.UUID,
7
- defaultValue: DataTypes.UUIDV4,
8
- primaryKey: true,
9
- },
10
- startTime: {
11
- type: DataTypes.DATE,
12
- allowNull: false,
13
- },
14
- endTime: {
15
- type: DataTypes.DATE,
16
- allowNull: false,
17
- },
18
- status: {
19
- type: DataTypes.ENUM("success", "failed"),
20
- allowNull: false,
21
- },
22
- fbDaysBack: {
23
- type: DataTypes.INTEGER,
24
- allowNull: true,
25
- },
26
- codeFuelDaysBack: {
27
- type: DataTypes.INTEGER,
28
- allowNull: true,
29
- },
30
- tonicDaysBack: {
31
- type: DataTypes.INTEGER,
32
- allowNull: true,
33
- },
34
- error: {
35
- type: DataTypes.TEXT,
36
- allowNull: true,
37
- },
38
- },
39
- {
40
- tableName: "pipeline_executions",
41
- timestamps: true,
42
- }
43
- );
44
-
45
- return PipelineExecution;
46
- };
@@ -1,302 +0,0 @@
1
- module.exports = (sequelize, DataTypes) => {
2
- const RSOCFeedCampaign = sequelize.define(
3
- "RSOCFeedCampaign",
4
- {
5
- AGRS_CID: {
6
- type: DataTypes.STRING,
7
- allowNull: false,
8
- unique: true,
9
- primaryKey: true,
10
- },
11
- AGRSAID: {
12
- type: DataTypes.STRING,
13
- allowNull: true,
14
- comment: "ID referencing Article.AGRSAID",
15
- },
16
- articleName: {
17
- type: DataTypes.STRING,
18
- allowNull: true,
19
- comment: "Name of the associated article",
20
- },
21
- channelId: {
22
- type: DataTypes.STRING,
23
- allowNull: false,
24
- comment: "ID referencing Channel.channelId",
25
- },
26
- styleId: {
27
- type: DataTypes.STRING,
28
- allowNull: true,
29
- comment: "Style ID (stid) inherited from Channel",
30
- },
31
- assignee: {
32
- type: DataTypes.STRING,
33
- allowNull: false,
34
- },
35
- status: {
36
- type: DataTypes.STRING,
37
- allowNull: false,
38
- defaultValue: "active",
39
- validate: {
40
- isIn: [["active", "inactive", "archived"]],
41
- },
42
- },
43
- country: {
44
- type: DataTypes.STRING,
45
- allowNull: false,
46
- },
47
- vertical: {
48
- type: DataTypes.STRING,
49
- allowNull: false,
50
- comment: "Maps to Article.category for dynamic selection",
51
- },
52
- freeText: {
53
- type: DataTypes.TEXT,
54
- allowNull: true,
55
- },
56
- campaignName: {
57
- type: DataTypes.STRING,
58
- allowNull: false,
59
- },
60
- campaignId: {
61
- type: DataTypes.STRING,
62
- allowNull: true,
63
- },
64
- keywords: {
65
- type: DataTypes.ARRAY(DataTypes.STRING),
66
- allowNull: true,
67
- },
68
- link: {
69
- type: DataTypes.STRING(1024),
70
- allowNull: true,
71
- comment: "Campaign-specific URL based on article URL with parameters",
72
- },
73
- redirectLink: {
74
- type: DataTypes.STRING(1024),
75
- allowNull: true,
76
- },
77
- pixelId: {
78
- type: DataTypes.STRING(1024),
79
- allowNull: true,
80
- },
81
- token: {
82
- type: DataTypes.STRING(1024),
83
- allowNull: true,
84
- },
85
- accountId: {
86
- type: DataTypes.STRING,
87
- allowNull: false,
88
- },
89
- feedName: {
90
- type: DataTypes.STRING,
91
- allowNull: true,
92
- defaultValue: "RSOC",
93
- },
94
- adTitle: {
95
- type: DataTypes.STRING,
96
- allowNull: true,
97
- },
98
- domain: {
99
- type: DataTypes.STRING,
100
- allowNull: true,
101
- },
102
- feedProvider: {
103
- type: DataTypes.STRING,
104
- allowNull: false,
105
- defaultValue: "RSOC",
106
- },
107
- createdCampaignAt: {
108
- type: DataTypes.DATE,
109
- allowNull: true,
110
- defaultValue: DataTypes.NOW,
111
- },
112
- draft: {
113
- type: DataTypes.BOOLEAN,
114
- allowNull: true,
115
- defaultValue: false,
116
- },
117
- createdAt: {
118
- type: DataTypes.DATE,
119
- allowNull: false,
120
- defaultValue: DataTypes.NOW,
121
- },
122
- updatedAt: {
123
- type: DataTypes.DATE,
124
- allowNull: false,
125
- defaultValue: DataTypes.NOW,
126
- },
127
- platform: {
128
- type: DataTypes.STRING,
129
- allowNull: false,
130
- },
131
- mediaBuyer: {
132
- type: DataTypes.STRING,
133
- allowNull: true,
134
- },
135
- },
136
- {
137
- tableName: "rsoc_feed_campaigns",
138
- timestamps: true,
139
- }
140
- );
141
-
142
- // Define associations without enforcing foreign key constraints
143
- RSOCFeedCampaign.associate = (models) => {
144
- if (models.Article) {
145
- RSOCFeedCampaign.belongsTo(models.Article, {
146
- foreignKey: "AGRSAID",
147
- targetKey: "AGRSAID",
148
- as: "Article",
149
- constraints: false,
150
- });
151
- }
152
-
153
- if (models.Channel) {
154
- RSOCFeedCampaign.belongsTo(models.Channel, {
155
- foreignKey: "channelId",
156
- targetKey: "channelId",
157
- as: "Channel",
158
- constraints: false,
159
- });
160
- }
161
-
162
- if (models.Ad) {
163
- RSOCFeedCampaign.hasMany(models.Ad, {
164
- foreignKey: "AGRS_CID",
165
- sourceKey: "AGRS_CID",
166
- as: "Ads",
167
- constraints: false,
168
- });
169
- }
170
- };
171
-
172
- // BeforeCreate hook: Update Channel status and connectedCampaigns
173
- RSOCFeedCampaign.beforeCreate(async (campaign, options) => {
174
- campaign.setDataValue("redirectLink", null);
175
-
176
- // Skip channel update if in a silent operation (e.g., during sync)
177
- if (options.silent) return;
178
-
179
- try {
180
- const channel = await sequelize.models.Channel.findOne({
181
- where: {
182
- channelId: campaign.channelId,
183
- styleId: campaign.styleId || null,
184
- },
185
- });
186
-
187
- if (channel) {
188
- const connectedCampaigns = channel.connectedCampaigns || [];
189
- if (
190
- !connectedCampaigns.some((c) => c.campaignId === campaign.AGRS_CID)
191
- ) {
192
- connectedCampaigns.push({
193
- campaignId: campaign.AGRS_CID,
194
- assignedAt: new Date(),
195
- releasedAt: null,
196
- });
197
- await channel.update(
198
- {
199
- status: "used",
200
- connectedCampaigns,
201
- },
202
- { silent: true }
203
- );
204
- }
205
- } else {
206
- console.warn(
207
- `Channel not found for channelId: ${campaign.channelId}, styleId: ${campaign.styleId}`
208
- );
209
- }
210
- } catch (error) {
211
- console.error("Error in beforeCreate hook:", error.message);
212
- }
213
- });
214
-
215
- // BeforeUpdate hook: Handle channel reassignment
216
- RSOCFeedCampaign.beforeUpdate(async (campaign, options) => {
217
- campaign.setDataValue("redirectLink", null);
218
-
219
- // Skip channel update if in a silent operation or no relevant changes
220
- if (
221
- options.silent ||
222
- (!campaign.changed("channelId") && !campaign.changed("styleId"))
223
- ) {
224
- return;
225
- }
226
-
227
- try {
228
- const oldChannelId = campaign.previous("channelId");
229
- const oldStyleId = campaign.previous("styleId") || null;
230
- const newChannelId = campaign.channelId;
231
- const newStyleId = campaign.styleId || null;
232
-
233
- // Release old channel
234
- if (
235
- oldChannelId &&
236
- (oldChannelId !== newChannelId || oldStyleId !== newStyleId)
237
- ) {
238
- const oldChannel = await sequelize.models.Channel.findOne({
239
- where: {
240
- channelId: oldChannelId,
241
- styleId: oldStyleId,
242
- },
243
- });
244
-
245
- if (oldChannel) {
246
- const connectedCampaigns = oldChannel.connectedCampaigns || [];
247
- const updatedCampaigns = connectedCampaigns
248
- .map((c) =>
249
- c.campaignId === campaign.AGRS_CID
250
- ? { ...c, releasedAt: new Date() }
251
- : c
252
- )
253
- .filter((c) => !c.releasedAt);
254
-
255
- await oldChannel.update(
256
- {
257
- connectedCampaigns: updatedCampaigns,
258
- status: updatedCampaigns.length > 0 ? "used" : "free",
259
- },
260
- { silent: true }
261
- );
262
- }
263
- }
264
-
265
- // Assign new channel
266
- const newChannel = await sequelize.models.Channel.findOne({
267
- where: {
268
- channelId: newChannelId,
269
- styleId: newStyleId,
270
- },
271
- });
272
-
273
- if (newChannel) {
274
- const connectedCampaigns = newChannel.connectedCampaigns || [];
275
- if (
276
- !connectedCampaigns.some((c) => c.campaignId === campaign.AGRS_CID)
277
- ) {
278
- connectedCampaigns.push({
279
- campaignId: campaign.AGRS_CID,
280
- assignedAt: new Date(),
281
- releasedAt: null,
282
- });
283
- await newChannel.update(
284
- {
285
- status: "used",
286
- connectedCampaigns,
287
- },
288
- { silent: true }
289
- );
290
- }
291
- } else {
292
- console.warn(
293
- `Channel not found for channelId: ${newChannelId}, styleId: ${newStyleId}`
294
- );
295
- }
296
- } catch (error) {
297
- console.error("Error in beforeUpdate hook:", error.message);
298
- }
299
- });
300
-
301
- return RSOCFeedCampaign;
302
- };