agrs-sequelize-sdk 1.1.57 → 1.1.58

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/Channel.js CHANGED
@@ -1,230 +1,55 @@
1
1
  module.exports = (sequelize, DataTypes) => {
2
- const RSOCFeedCampaign = sequelize.define(
3
- "RSOCFeedCampaign",
2
+ const Channel = sequelize.define(
3
+ "Channel",
4
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: false,
14
- comment: "Foreign key referencing Article.AGRSAID",
15
- },
16
- articleName: {
17
- type: DataTypes.STRING,
18
- allowNull: false,
19
- comment: "Name of the associated article",
20
- },
21
5
  channelId: {
22
6
  type: DataTypes.STRING,
23
7
  allowNull: false,
24
- comment: "Foreign key referencing Channel.channelId",
8
+ // Not setting as primary key or unique since duplicates are allowed
25
9
  },
26
10
  styleId: {
27
- type: DataTypes.STRING,
28
- allowNull: true,
29
- comment: "Style ID (stid) inherited from Channel",
30
- },
31
- assignee: {
32
11
  type: DataTypes.STRING,
33
12
  allowNull: false,
34
13
  },
35
14
  status: {
36
15
  type: DataTypes.STRING,
37
16
  allowNull: false,
38
- defaultValue: "active",
17
+ defaultValue: "free",
39
18
  validate: {
40
- isIn: [["active", "inactive", "archived"]],
19
+ isIn: [["free", "used", "archived"]],
41
20
  },
42
21
  },
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
- defaultValue: DataTypes.NOW,
120
- },
121
- updatedAt: {
122
- type: DataTypes.DATE,
123
- defaultValue: DataTypes.NOW,
124
- },
125
- platform: {
126
- type: DataTypes.STRING,
22
+ connectedCampaigns: {
23
+ type: DataTypes.JSONB, // Use JSONB for better querying capabilities
127
24
  allowNull: false,
128
- },
129
- mediaBuyer: {
130
- type: DataTypes.STRING,
131
- allowNull: true,
25
+ defaultValue: [],
132
26
  },
133
27
  },
134
28
  {
135
- tableName: "rsoc_feed_campaigns",
29
+ tableName: "channels",
136
30
  timestamps: true,
31
+ indexes: [
32
+ // Add a composite unique index on channelId and styleId if needed
33
+ {
34
+ unique: true,
35
+ fields: ["channelId", "styleId"],
36
+ name: "unique_channel_style",
37
+ },
38
+ ],
137
39
  }
138
40
  );
139
41
 
140
- RSOCFeedCampaign.associate = (models) => {
141
- RSOCFeedCampaign.belongsTo(models.Article, {
142
- foreignKey: "AGRSAID",
143
- targetKey: "AGRSAID",
144
- as: "Article",
145
- constraints: false, // Disable foreign key constraint
146
- });
147
-
148
- RSOCFeedCampaign.belongsTo(models.Channel, {
149
- foreignKey: "channelId",
150
- targetKey: "channelId",
151
- as: "Channel",
152
- constraints: false, // Disable foreign key constraint
153
- });
154
- };
155
-
156
- RSOCFeedCampaign.beforeCreate(async (campaign) => {
157
- // Set redirectLink to null as requested
158
- campaign.setDataValue("redirectLink", null);
159
-
160
- const channel = await sequelize.models.Channel.findOne({
161
- where: { channelId: campaign.channelId, styleId: campaign.styleId },
162
- });
163
-
164
- if (channel) {
165
- const connectedCampaigns = channel.connectedCampaigns || [];
166
- if (!connectedCampaigns.some((c) => c.campaignId === campaign.AGRS_CID)) {
167
- connectedCampaigns.push({
168
- campaignId: campaign.AGRS_CID,
169
- assignedAt: new Date(),
170
- releasedAt: null,
171
- });
172
- await channel.update({ status: "used", connectedCampaigns });
173
- }
174
- }
175
- });
176
-
177
- RSOCFeedCampaign.beforeUpdate(async (campaign) => {
178
- // Ensure redirectLink remains null
179
- campaign.setDataValue("redirectLink", null);
180
-
181
- if (campaign.changed("channelId") || campaign.changed("styleId")) {
182
- const oldChannelId = campaign.previous("channelId");
183
- const oldStyleId = campaign.previous("styleId");
184
- const newChannelId = campaign.channelId;
185
- const newStyleId = campaign.styleId;
186
-
187
- if (oldChannelId) {
188
- const oldChannel = await sequelize.models.Channel.findOne({
189
- where: { channelId: oldChannelId, styleId: oldStyleId },
190
- });
191
-
192
- if (oldChannel) {
193
- const connectedCampaigns = oldChannel.connectedCampaigns || [];
194
- const updatedCampaigns = connectedCampaigns
195
- .map((c) =>
196
- c.campaignId === campaign.AGRS_CID
197
- ? { ...c, releasedAt: new Date() }
198
- : c
199
- )
200
- .filter((c) => c.releasedAt === null);
201
-
202
- await oldChannel.update({
203
- connectedCampaigns: updatedCampaigns,
204
- status: updatedCampaigns.length > 0 ? "used" : "free",
205
- });
206
- }
207
- }
208
-
209
- const newChannel = await sequelize.models.Channel.findOne({
210
- where: { channelId: newChannelId, styleId: newStyleId },
42
+ // Define associations without enforcing constraints
43
+ Channel.associate = (models) => {
44
+ if (models.RSOCFeedCampaign) {
45
+ Channel.hasMany(models.RSOCFeedCampaign, {
46
+ foreignKey: "channelId",
47
+ sourceKey: "channelId",
48
+ as: "RSOCFeedCampaigns",
49
+ constraints: false, // Disable FK constraint
211
50
  });
212
-
213
- if (newChannel) {
214
- const connectedCampaigns = newChannel.connectedCampaigns || [];
215
- if (
216
- !connectedCampaigns.some((c) => c.campaignId === campaign.AGRS_CID)
217
- ) {
218
- connectedCampaigns.push({
219
- campaignId: campaign.AGRS_CID,
220
- assignedAt: new Date(),
221
- releasedAt: null,
222
- });
223
- await newChannel.update({ status: "used", connectedCampaigns });
224
- }
225
- }
226
51
  }
227
- });
52
+ };
228
53
 
229
- return RSOCFeedCampaign;
54
+ return Channel;
230
55
  };
@@ -135,7 +135,7 @@ module.exports = (sequelize, DataTypes) => {
135
135
  },
136
136
  {
137
137
  tableName: "rsoc_feed_campaigns",
138
- timestamps: true, // Enable Sequelize-managed timestamps
138
+ timestamps: true,
139
139
  }
140
140
  );
141
141
 
@@ -146,7 +146,7 @@ module.exports = (sequelize, DataTypes) => {
146
146
  foreignKey: "AGRSAID",
147
147
  targetKey: "AGRSAID",
148
148
  as: "Article",
149
- constraints: false, // Disable FK constraint
149
+ constraints: false,
150
150
  });
151
151
  }
152
152
 
@@ -155,20 +155,23 @@ module.exports = (sequelize, DataTypes) => {
155
155
  foreignKey: "channelId",
156
156
  targetKey: "channelId",
157
157
  as: "Channel",
158
- constraints: false, // Disable FK constraint
158
+ constraints: false,
159
159
  });
160
160
  }
161
161
  };
162
162
 
163
163
  // BeforeCreate hook: Update Channel status and connectedCampaigns
164
164
  RSOCFeedCampaign.beforeCreate(async (campaign, options) => {
165
- campaign.setDataValue("redirectLink", null); // Ensure redirectLink is null
165
+ campaign.setDataValue("redirectLink", null);
166
+
167
+ // Skip channel update if in a silent operation (e.g., during sync)
168
+ if (options.silent) return;
166
169
 
167
170
  try {
168
171
  const channel = await sequelize.models.Channel.findOne({
169
172
  where: {
170
173
  channelId: campaign.channelId,
171
- styleId: campaign.styleId || null, // Handle null styleId
174
+ styleId: campaign.styleId || null,
172
175
  },
173
176
  });
174
177
 
@@ -187,7 +190,7 @@ module.exports = (sequelize, DataTypes) => {
187
190
  status: "used",
188
191
  connectedCampaigns,
189
192
  },
190
- { silent: true } // Prevent infinite loops
193
+ { silent: true }
191
194
  );
192
195
  }
193
196
  } else {
@@ -197,85 +200,92 @@ module.exports = (sequelize, DataTypes) => {
197
200
  }
198
201
  } catch (error) {
199
202
  console.error("Error in beforeCreate hook:", error.message);
200
- // Log error but don't throw to allow campaign creation to proceed
201
203
  }
202
204
  });
203
205
 
204
206
  // BeforeUpdate hook: Handle channel reassignment
205
207
  RSOCFeedCampaign.beforeUpdate(async (campaign, options) => {
206
- campaign.setDataValue("redirectLink", null); // Ensure redirectLink remains null
207
-
208
- if (campaign.changed("channelId") || campaign.changed("styleId")) {
209
- try {
210
- const oldChannelId = campaign.previous("channelId");
211
- const oldStyleId = campaign.previous("styleId") || null;
212
- const newChannelId = campaign.channelId;
213
- const newStyleId = campaign.styleId || null;
214
-
215
- // Release old channel
216
- if (oldChannelId) {
217
- const oldChannel = await sequelize.models.Channel.findOne({
218
- where: {
219
- channelId: oldChannelId,
220
- styleId: oldStyleId,
221
- },
222
- });
208
+ campaign.setDataValue("redirectLink", null);
223
209
 
224
- if (oldChannel) {
225
- const connectedCampaigns = oldChannel.connectedCampaigns || [];
226
- const updatedCampaigns = connectedCampaigns
227
- .map((c) =>
228
- c.campaignId === campaign.AGRS_CID
229
- ? { ...c, releasedAt: new Date() }
230
- : c
231
- )
232
- .filter((c) => !c.releasedAt); // Remove released campaigns
210
+ // Skip channel update if in a silent operation or no relevant changes
211
+ if (
212
+ options.silent ||
213
+ (!campaign.changed("channelId") && !campaign.changed("styleId"))
214
+ ) {
215
+ return;
216
+ }
233
217
 
234
- await oldChannel.update(
235
- {
236
- connectedCampaigns: updatedCampaigns,
237
- status: updatedCampaigns.length > 0 ? "used" : "free",
238
- },
239
- { silent: true }
240
- );
241
- }
242
- }
218
+ try {
219
+ const oldChannelId = campaign.previous("channelId");
220
+ const oldStyleId = campaign.previous("styleId") || null;
221
+ const newChannelId = campaign.channelId;
222
+ const newStyleId = campaign.styleId || null;
243
223
 
244
- // Assign new channel
245
- const newChannel = await sequelize.models.Channel.findOne({
224
+ // Release old channel
225
+ if (
226
+ oldChannelId &&
227
+ (oldChannelId !== newChannelId || oldStyleId !== newStyleId)
228
+ ) {
229
+ const oldChannel = await sequelize.models.Channel.findOne({
246
230
  where: {
247
- channelId: newChannelId,
248
- styleId: newStyleId,
231
+ channelId: oldChannelId,
232
+ styleId: oldStyleId,
249
233
  },
250
234
  });
251
235
 
252
- if (newChannel) {
253
- const connectedCampaigns = newChannel.connectedCampaigns || [];
254
- if (
255
- !connectedCampaigns.some((c) => c.campaignId === campaign.AGRS_CID)
256
- ) {
257
- connectedCampaigns.push({
258
- campaignId: campaign.AGRS_CID,
259
- assignedAt: new Date(),
260
- releasedAt: null,
261
- });
262
- await newChannel.update(
263
- {
264
- status: "used",
265
- connectedCampaigns,
266
- },
267
- { silent: true }
268
- );
269
- }
270
- } else {
271
- console.warn(
272
- `New channel not found for channelId: ${newChannelId}, styleId: ${newStyleId}`
236
+ if (oldChannel) {
237
+ const connectedCampaigns = oldChannel.connectedCampaigns || [];
238
+ const updatedCampaigns = connectedCampaigns
239
+ .map((c) =>
240
+ c.campaignId === campaign.AGRS_CID
241
+ ? { ...c, releasedAt: new Date() }
242
+ : c
243
+ )
244
+ .filter((c) => !c.releasedAt);
245
+
246
+ await oldChannel.update(
247
+ {
248
+ connectedCampaigns: updatedCampaigns,
249
+ status: updatedCampaigns.length > 0 ? "used" : "free",
250
+ },
251
+ { silent: true }
273
252
  );
274
253
  }
275
- } catch (error) {
276
- console.error("Error in beforeUpdate hook:", error.message);
277
- // Log error but don't throw to allow update to proceed
278
254
  }
255
+
256
+ // Assign new channel
257
+ const newChannel = await sequelize.models.Channel.findOne({
258
+ where: {
259
+ channelId: newChannelId,
260
+ styleId: newStyleId,
261
+ },
262
+ });
263
+
264
+ if (newChannel) {
265
+ const connectedCampaigns = newChannel.connectedCampaigns || [];
266
+ if (
267
+ !connectedCampaigns.some((c) => c.campaignId === campaign.AGRS_CID)
268
+ ) {
269
+ connectedCampaigns.push({
270
+ campaignId: campaign.AGRS_CID,
271
+ assignedAt: new Date(),
272
+ releasedAt: null,
273
+ });
274
+ await newChannel.update(
275
+ {
276
+ status: "used",
277
+ connectedCampaigns,
278
+ },
279
+ { silent: true }
280
+ );
281
+ }
282
+ } else {
283
+ console.warn(
284
+ `New channel not found for channelId: ${newChannelId}, styleId: ${newStyleId}`
285
+ );
286
+ }
287
+ } catch (error) {
288
+ console.error("Error in beforeUpdate hook:", error.message);
279
289
  }
280
290
  });
281
291
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agrs-sequelize-sdk",
3
- "version": "1.1.57",
3
+ "version": "1.1.58",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "start": "node index.js",