Files
backend-Eprocurement/emailnotif.js
Rizki 7e74d4bd23 upd
2026-04-15 14:32:12 +07:00

211 lines
8.1 KiB
JavaScript

const http = require('http');
const db = require('./config/dbproc.js');
const ALLOWED_EMAILS = new Set([
'david.rodriquez@telin.net',
'syam.thasya@telin.net',
]);
function buildHtml(approverName, title, priorName, idxjustification, remark, status) {
const url = status === 'RETURNED'
? `https://e-portal.telkomcel.tl/app/ext/eproc/justifikasi/${idxjustification}/edit`
: `https://e-portal.telkomcel.tl/app/ext/eproc/circulation/${idxjustification}`;
const statusLabel = status || 'READY FOR APPROVAL';
const notesLine = remark ? ` <li><strong>Notes:</strong> ${remark}</li>\n` : '';
return `<p>Dear ${approverName},</p>
<p>A new workflow task requires your review and approval. Please find the details regarding this justification below:</p>
<ul>
<li><strong>Justification:</strong> ${title}</li>
<li><strong>Task Type:</strong> OPEN</li>
<li><strong>Status:</strong> ${statusLabel}</li>
${notesLine} <li><strong>Sent By:</strong> ${priorName}</li>
</ul>
<p><strong>Action Required:</strong><br>
Please access the document and complete the approval via the E-Procurement Portal using the link below:<br>
<a href="${url}">${url}</a></p>
<p>If you have any questions or require further clarification, please do not hesitate to contact the Procurement Division.</p>
<p>Thank you for your attention and cooperation.</p>
<p>Best regards,<br>
Procurement Division<br>
Finance Business Partner Unit</p>`;
}
function logEmail(trxId, toEmail, subject, html, fromEmail, status, requestPayload, responseMessage) {
const qry = `
INSERT INTO email_logs (trx_id, to_email, subject, body, from_email, is_attachment, status, request_payload, response_message, created_at)
VALUES (?, ?, ?, ?, ?, 0, ?, ?, ?, NOW())
`;
db.query(qry, [trxId, toEmail, subject, html, fromEmail, status, requestPayload, responseMessage], function(err) {
if (err) console.error('[email-notif] logEmail failed:', err.message);
});
}
function postEmail(toEmail, approverName, title, priorName, idxjustification, remark, status) {
if (!ALLOWED_EMAILS.has(toEmail)) {
console.log('[email-notif] skipped (not in allowed list):', toEmail);
return;
}
const subject = status === 'RETURNED'
? `[Returned] Justification for ${title}`
: `[Approval Required] Justification for ${title}`;
const html = buildHtml(approverName, title, priorName, idxjustification, remark, status);
const payload = JSON.stringify({
to: [toEmail],
cc: [],
bcc: [],
subject,
html
});
const req = http.request({
hostname: 'localhost',
port: 7004,
path: '/api/email/send-telkomcel',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(payload)
}
}, (res) => {
let body = '';
res.on('data', (chunk) => { body += chunk; });
res.on('end', () => {
let trxId = '';
let responseMessage = body;
try {
const parsed = JSON.parse(body);
trxId = parsed?.data?.trx_id || '';
responseMessage = JSON.stringify(parsed);
} catch (_) {}
const logStatus = res.statusCode >= 200 && res.statusCode < 300 ? 'success' : 'failed';
console.log('[email-notif] sent, status:', res.statusCode, '| trxId:', trxId, '| to:', toEmail);
logEmail(trxId, toEmail, subject, html, '', logStatus, payload, responseMessage);
});
});
req.on('error', (err) => {
console.error('[email-notif] failed:', err.message);
logEmail('', toEmail, subject, html, '', 'failed', payload, err.message);
});
req.write(payload);
req.end();
}
/**
* Notify first approver when justification is submitted.
*/
function notifyOnSubmit(idxjustification) {
const qryJustification = `
select j.title, j.remark, e.fullname as creator_name
from tbl_justification j
join dbssotcel.tbl_employee e on e.nik = j.iby
where j._idx = '${idxjustification}' limit 1
`;
db.query(qryJustification, [], function(err, rows) {
if (err || rows.length === 0) {
console.error('[email-notif] notifyOnSubmit: failed to get justification data', err);
return;
}
const title = rows[0].title;
const remark = rows[0].remark || '';
const creatorName = rows[0].creator_name;
const qryApprover = `
select t.nik, e.fullname, e.email
from tbl_justificationttd t
join dbssotcel.tbl_employee e on e.nik = t.nik
where t.idxjustification = '${idxjustification}' and t.issigned = 0 and t.isdeleted = 0
order by t._idx asc limit 1
`;
db.query(qryApprover, [], function(err2, rows2) {
if (err2 || rows2.length === 0) {
console.error('[email-notif] notifyOnSubmit: no approver found', err2);
return;
}
postEmail(rows2[0].email, rows2[0].fullname, title, creatorName, idxjustification, remark);
});
});
}
/**
* Notify next approver after someone signs.
*/
function notifyOnSigned(idxjustification, signerNik) {
const qryTitle = `select title, remark from tbl_justification where _idx = '${idxjustification}' limit 1`;
db.query(qryTitle, [], function(err, rows) {
if (err || rows.length === 0) {
console.error('[email-notif] notifyOnSigned: failed to get justification title', err);
return;
}
const title = rows[0].title;
const remark = rows[0].remark || '';
const qrySigner = `select fullname from dbssotcel.tbl_employee where nik = '${signerNik}' limit 1`;
db.query(qrySigner, [], function(err2, rows2) {
if (err2 || rows2.length === 0) {
console.error('[email-notif] notifyOnSigned: failed to get signer name', err2);
return;
}
const signerName = rows2[0].fullname;
const qryNext = `
select t.nik, e.fullname, e.email
from tbl_justificationttd t
join dbssotcel.tbl_employee e on e.nik = t.nik
where t.idxjustification = '${idxjustification}' and t.issigned = 0 and t.isdeleted = 0
order by t._idx asc limit 1
`;
db.query(qryNext, [], function(err3, rows3) {
if (err3 || rows3.length === 0) {
console.log('[email-notif] notifyOnSigned: no more approvers to notify');
return;
}
postEmail(rows3[0].email, rows3[0].fullname, title, signerName, idxjustification, remark);
});
});
});
}
/**
* Notify creator when justification is returned.
*/
function notifyOnReturn(idxjustification, returnerNik) {
const qryJustification = `
select j.title, j.remark, e.fullname as creator_name, e.email as creator_email
from tbl_justification j
join dbssotcel.tbl_employee e on e.nik = j.iby
where j._idx = '${idxjustification}' limit 1
`;
db.query(qryJustification, [], function(err, rows) {
if (err || rows.length === 0) {
console.error('[email-notif] notifyOnReturn: failed to get justification data', err);
return;
}
const title = rows[0].title;
const remark = rows[0].remark || '';
const creatorName = rows[0].creator_name;
const creatorEmail = rows[0].creator_email;
const qryReturner = `select fullname from dbssotcel.tbl_employee where nik = '${returnerNik}' limit 1`;
db.query(qryReturner, [], function(err2, rows2) {
if (err2 || rows2.length === 0) {
console.error('[email-notif] notifyOnReturn: failed to get returner name', err2);
return;
}
const returnerName = rows2[0].fullname;
postEmail(creatorEmail, creatorName, title, returnerName, idxjustification, remark, 'RETURNED');
});
});
}
module.exports = { notifyOnSubmit, notifyOnSigned, notifyOnReturn };