147 lines
3.9 KiB
JavaScript
147 lines
3.9 KiB
JavaScript
|
|
const { TrackingToken, Company, MailTemplate } = require('../models');
|
||
|
|
const { generateTrackingToken } = require('../utils/tokenGenerator');
|
||
|
|
const mailService = require('./mail.service');
|
||
|
|
const logger = require('../config/logger');
|
||
|
|
|
||
|
|
class TokenService {
|
||
|
|
async createToken(data) {
|
||
|
|
const { company_id, target_email, employee_name, template_type } = data;
|
||
|
|
|
||
|
|
// Generate unique token
|
||
|
|
let token = generateTrackingToken();
|
||
|
|
let isUnique = false;
|
||
|
|
let attempts = 0;
|
||
|
|
|
||
|
|
// Ensure token is unique
|
||
|
|
while (!isUnique && attempts < 5) {
|
||
|
|
const existing = await TrackingToken.findOne({ where: { token } });
|
||
|
|
if (!existing) {
|
||
|
|
isUnique = true;
|
||
|
|
} else {
|
||
|
|
token = generateTrackingToken();
|
||
|
|
attempts++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!isUnique) {
|
||
|
|
throw new Error('Failed to generate unique token');
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get company and template
|
||
|
|
const company = await Company.findByPk(company_id);
|
||
|
|
if (!company) {
|
||
|
|
throw new Error('Company not found');
|
||
|
|
}
|
||
|
|
|
||
|
|
const template = await MailTemplate.findOne({ where: { template_type } });
|
||
|
|
if (!template) {
|
||
|
|
throw new Error('Mail template not found');
|
||
|
|
}
|
||
|
|
|
||
|
|
// Create tracking token
|
||
|
|
const trackingToken = await TrackingToken.create({
|
||
|
|
token,
|
||
|
|
company_id,
|
||
|
|
target_email,
|
||
|
|
employee_name,
|
||
|
|
template_type,
|
||
|
|
mail_subject: template.subject_template.replace('{{company_name}}', company.name),
|
||
|
|
});
|
||
|
|
|
||
|
|
// Update company stats
|
||
|
|
await company.increment('total_tokens');
|
||
|
|
|
||
|
|
logger.info(`Token created: ${token} for ${target_email}`);
|
||
|
|
|
||
|
|
return trackingToken;
|
||
|
|
}
|
||
|
|
|
||
|
|
async sendMail(tokenId) {
|
||
|
|
const token = await TrackingToken.findByPk(tokenId, {
|
||
|
|
include: [{ model: Company, as: 'company' }],
|
||
|
|
});
|
||
|
|
|
||
|
|
if (!token) {
|
||
|
|
throw new Error('Token not found');
|
||
|
|
}
|
||
|
|
|
||
|
|
if (token.mail_sent) {
|
||
|
|
throw new Error('Mail already sent for this token');
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get mail template
|
||
|
|
const template = await MailTemplate.findOne({
|
||
|
|
where: { template_type: token.template_type },
|
||
|
|
});
|
||
|
|
|
||
|
|
if (!template) {
|
||
|
|
throw new Error('Mail template not found');
|
||
|
|
}
|
||
|
|
|
||
|
|
// Prepare template data
|
||
|
|
const trackingUrl = `${process.env.BASE_URL}/t/${token.token}`;
|
||
|
|
const currentDate = new Date().toLocaleDateString('tr-TR', {
|
||
|
|
year: 'numeric',
|
||
|
|
month: 'long',
|
||
|
|
day: 'numeric',
|
||
|
|
});
|
||
|
|
const currentYear = new Date().getFullYear();
|
||
|
|
|
||
|
|
const templateData = {
|
||
|
|
company_name: token.company.name,
|
||
|
|
employee_name: token.employee_name,
|
||
|
|
tracking_url: trackingUrl,
|
||
|
|
current_date: currentDate,
|
||
|
|
current_year: currentYear,
|
||
|
|
};
|
||
|
|
|
||
|
|
// Render mail body
|
||
|
|
const htmlBody = mailService.renderTemplate(template.body_html, templateData);
|
||
|
|
const subject = mailService.renderTemplate(template.subject_template, templateData);
|
||
|
|
|
||
|
|
// Send mail
|
||
|
|
await mailService.sendMail(token.target_email, subject, htmlBody);
|
||
|
|
|
||
|
|
// Update token
|
||
|
|
await token.update({
|
||
|
|
mail_sent: true,
|
||
|
|
sent_at: new Date(),
|
||
|
|
});
|
||
|
|
|
||
|
|
logger.info(`Mail sent for token: ${token.token} to ${token.target_email}`);
|
||
|
|
|
||
|
|
return token;
|
||
|
|
}
|
||
|
|
|
||
|
|
async updateCompanyStats(companyId) {
|
||
|
|
const company = await Company.findByPk(companyId);
|
||
|
|
if (!company) return;
|
||
|
|
|
||
|
|
// Count tokens
|
||
|
|
const totalTokens = await TrackingToken.count({
|
||
|
|
where: { company_id: companyId },
|
||
|
|
});
|
||
|
|
|
||
|
|
const clickedTokens = await TrackingToken.count({
|
||
|
|
where: { company_id: companyId, clicked: true },
|
||
|
|
});
|
||
|
|
|
||
|
|
const totalClicks = await TrackingToken.sum('click_count', {
|
||
|
|
where: { company_id: companyId },
|
||
|
|
});
|
||
|
|
|
||
|
|
const clickRate = totalTokens > 0 ? ((clickedTokens / totalTokens) * 100).toFixed(2) : 0;
|
||
|
|
|
||
|
|
await company.update({
|
||
|
|
total_tokens: totalTokens,
|
||
|
|
total_clicks: totalClicks || 0,
|
||
|
|
click_rate: clickRate,
|
||
|
|
});
|
||
|
|
|
||
|
|
logger.info(`Company stats updated for: ${company.name}`);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
module.exports = new TokenService();
|
||
|
|
|