2023-02-17 17:03:52 +03:00
|
|
|
const TableImporter = require('./base');
|
|
|
|
const {faker} = require('@faker-js/faker');
|
|
|
|
const generateEvents = require('../utils/event-generator');
|
|
|
|
const dateToDatabaseString = require('../utils/database-date');
|
|
|
|
|
|
|
|
const emailStatus = {
|
|
|
|
delivered: Symbol(),
|
|
|
|
opened: Symbol(),
|
|
|
|
failed: Symbol(),
|
|
|
|
none: Symbol()
|
|
|
|
};
|
|
|
|
|
|
|
|
class EmailRecipientsImporter extends TableImporter {
|
|
|
|
static table = 'email_recipients';
|
|
|
|
|
|
|
|
constructor(knex, {emailBatches, members, membersSubscribeEvents}) {
|
|
|
|
super(EmailRecipientsImporter.table, knex);
|
|
|
|
this.emailBatches = emailBatches;
|
|
|
|
this.members = members;
|
|
|
|
this.membersSubscribeEvents = membersSubscribeEvents;
|
|
|
|
}
|
|
|
|
|
|
|
|
setImportOptions({model}) {
|
|
|
|
this.model = model;
|
|
|
|
this.batch = this.emailBatches.find(batch => batch.email_id === model.id);
|
|
|
|
// Shallow clone members list so we can shuffle and modify it
|
|
|
|
const earliestOpenTime = new Date(this.batch.updated_at);
|
|
|
|
const latestOpenTime = new Date(this.batch.updated_at);
|
|
|
|
latestOpenTime.setDate(latestOpenTime.getDate() + 14);
|
|
|
|
const currentTime = new Date();
|
|
|
|
this.membersList = this.membersSubscribeEvents
|
|
|
|
.filter(entry => entry.newsletter_id === this.model.newsletter_id)
|
|
|
|
.filter(entry => new Date(entry.created_at) < earliestOpenTime)
|
|
|
|
.map(memberSubscribeEvent => memberSubscribeEvent.member_id);
|
2023-02-17 18:08:01 +03:00
|
|
|
this.events = this.membersList.length > 0 ? generateEvents({
|
2023-02-17 17:03:52 +03:00
|
|
|
shape: 'ease-out',
|
|
|
|
trend: 'negative',
|
|
|
|
total: this.membersList.length,
|
|
|
|
startTime: earliestOpenTime,
|
|
|
|
endTime: currentTime < latestOpenTime ? currentTime : latestOpenTime
|
2023-02-17 18:08:01 +03:00
|
|
|
}) : [];
|
2023-02-17 17:03:52 +03:00
|
|
|
this.emailMeta = {
|
|
|
|
emailCount: this.model.email_count,
|
2023-02-22 02:48:43 +03:00
|
|
|
// delievered and not opened
|
|
|
|
deliveredCount: this.model.delivered_count - this.model.opened_count,
|
2023-02-17 17:03:52 +03:00
|
|
|
openedCount: this.model.opened_count,
|
|
|
|
failedCount: this.model.failed_count
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
generate() {
|
|
|
|
if (this.emailMeta.emailCount <= 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.emailMeta.emailCount -= 1;
|
|
|
|
|
|
|
|
const timestamp = this.events.shift();
|
|
|
|
if (!timestamp) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const memberIdIndex = faker.datatype.number({
|
|
|
|
min: 0,
|
|
|
|
max: this.membersList.length - 1
|
|
|
|
});
|
|
|
|
const [memberId] = this.membersList.splice(memberIdIndex, 1);
|
|
|
|
const member = this.members.find(m => m.id === memberId);
|
|
|
|
|
|
|
|
let status = emailStatus.none;
|
|
|
|
if (this.emailMeta.failedCount > 0) {
|
|
|
|
status = emailStatus.failed;
|
|
|
|
this.emailMeta.failedCount -= 1;
|
|
|
|
} else if (this.emailMeta.openedCount > 0) {
|
|
|
|
status = emailStatus.opened;
|
2023-02-22 02:48:43 +03:00
|
|
|
this.emailMeta.openedCount -= 1;
|
2023-02-17 17:03:52 +03:00
|
|
|
} else if (this.emailMeta.deliveredCount > 0) {
|
|
|
|
status = emailStatus.delivered;
|
|
|
|
this.emailMeta.deliveredCount -= 1;
|
|
|
|
}
|
|
|
|
|
2023-02-22 02:48:43 +03:00
|
|
|
let deliveredTime;
|
|
|
|
if (status === emailStatus.opened) {
|
|
|
|
const startDate = new Date(this.batch.updated_at).valueOf();
|
|
|
|
const endDate = timestamp.valueOf();
|
|
|
|
deliveredTime = new Date(startDate + (Math.random() * (endDate - startDate)));
|
|
|
|
}
|
|
|
|
|
2023-02-17 17:03:52 +03:00
|
|
|
return {
|
|
|
|
id: faker.database.mongodbObjectId(),
|
|
|
|
email_id: this.model.id,
|
|
|
|
batch_id: this.batch.id,
|
|
|
|
member_id: member.id,
|
|
|
|
processed_at: this.batch.updated_at,
|
2023-02-22 02:48:43 +03:00
|
|
|
delivered_at: status === emailStatus.opened ? dateToDatabaseString(deliveredTime) : status === emailStatus.delivered ? dateToDatabaseString(timestamp) : null,
|
2023-02-17 17:03:52 +03:00
|
|
|
opened_at: status === emailStatus.opened ? dateToDatabaseString(timestamp) : null,
|
|
|
|
failed_at: status === emailStatus.failed ? dateToDatabaseString(timestamp) : null,
|
|
|
|
member_uuid: member.uuid,
|
|
|
|
member_email: member.email,
|
|
|
|
member_name: member.name
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = EmailRecipientsImporter;
|