282 lines
71 KiB
JavaScript
282 lines
71 KiB
JavaScript
|
|
var fs = require('fs');
|
|||
|
|
const csv = require('csv-parser');
|
|||
|
|
const moment = require('moment');
|
|||
|
|
const html_to_pdf = require('html-pdf-node');
|
|||
|
|
|
|||
|
|
|
|||
|
|
async function makePdf(data) {
|
|||
|
|
let options = { format: 'A4' };
|
|||
|
|
let template = {
|
|||
|
|
content: `<!DOCTYPE html>
|
|||
|
|
<head>
|
|||
|
|
<style>
|
|||
|
|
// @media print {
|
|||
|
|
// body {
|
|||
|
|
// -webkit-print-color-adjust: exact;
|
|||
|
|
// }
|
|||
|
|
// }
|
|||
|
|
|
|||
|
|
html { -webkit-print-color-adjust: exact; }
|
|||
|
|
|
|||
|
|
.person-details-row {
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: row;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.person-details-col {
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
height: 90px;
|
|||
|
|
width: 50%;
|
|||
|
|
margin: 1px;
|
|||
|
|
border: 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.test-details-row {
|
|||
|
|
border: 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.test-details-col {
|
|||
|
|
height: 100px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.test-cell-div {
|
|||
|
|
/* border: 1px solid black; */
|
|||
|
|
border-collapse: collapse;
|
|||
|
|
height: 20px;
|
|||
|
|
padding: 10px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.table-header {
|
|||
|
|
border: 1px solid black;
|
|||
|
|
margin: 0 0 -10px 10px;
|
|||
|
|
background-color: rgb(191, 191, 191) !important;
|
|||
|
|
text-align: center;
|
|||
|
|
justify-content: center;
|
|||
|
|
align-items: center;
|
|||
|
|
display: flex;
|
|||
|
|
font-weight: 600;
|
|||
|
|
height: 50px;
|
|||
|
|
width: 98%;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// @media print {
|
|||
|
|
// .table-header {
|
|||
|
|
// background-color: rgb(191, 191, 191) !important;
|
|||
|
|
// print-color-adjust: exact;
|
|||
|
|
// }
|
|||
|
|
// }
|
|||
|
|
|
|||
|
|
// @media print {
|
|||
|
|
// .vendorListHeading th {
|
|||
|
|
// color: white !important;
|
|||
|
|
// }
|
|||
|
|
// }
|
|||
|
|
|
|||
|
|
.test-method {
|
|||
|
|
font-weight: 200 !important;
|
|||
|
|
color: rgb(191, 191, 191);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.result-value {
|
|||
|
|
justify-content: center;
|
|||
|
|
align-items: center;
|
|||
|
|
display: flex;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.end-of-report {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: center;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.logo {
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: center;
|
|||
|
|
align-items: center;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
table,
|
|||
|
|
th,
|
|||
|
|
td {
|
|||
|
|
border: 1px solid black;
|
|||
|
|
border-collapse: collapse;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ul {
|
|||
|
|
list-style-type: none;
|
|||
|
|
/* margin: 0; */
|
|||
|
|
/* padding: 0; */
|
|||
|
|
}
|
|||
|
|
</style>
|
|||
|
|
</head>
|
|||
|
|
|
|||
|
|
<body>
|
|||
|
|
<div>
|
|||
|
|
<div class="logo">
|
|||
|
|
<img src="data:image/png;base64,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
|
|||
|
|
</div>
|
|||
|
|
<table style="border: 1px solid black; margin: 10px; width: 98%;">
|
|||
|
|
<tr class="person-details-row">
|
|||
|
|
<td class="person-details-col" style="border-right: 2; width: 65%;">
|
|||
|
|
<div><strong>Person Name:</strong> ${data?.Name} </div>
|
|||
|
|
<div><strong>Age / Sex:</strong> ${data?.Age} / ${data?.Gender}</div>
|
|||
|
|
<div><strong>Sample type:</strong> Capillary Whole Blood </div>
|
|||
|
|
<div><strong>Family History of Sickle Cell Anemia:</strong> NA </div>
|
|||
|
|
</td>
|
|||
|
|
<td class="person-details-col" style="width: 35%;">
|
|||
|
|
<div><strong>Marital Status:</strong> ${data["Marital Status"]} </div>
|
|||
|
|
<div><strong>Test Date:</strong> ${data?.testTime} </div>
|
|||
|
|
<div><strong>ABHA ID:</strong> ${data["ABHA ID"]} </div>
|
|||
|
|
<div><strong>Sample ID:</strong> ${data["_id"]} </div>
|
|||
|
|
</td>
|
|||
|
|
</tr>
|
|||
|
|
</table>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
|
|||
|
|
<div style="height: 2px;width: 98%; background-color: rgb(56, 105, 166); margin: 30px 10px 40px 10px;"></div>
|
|||
|
|
|
|||
|
|
|
|||
|
|
<div>
|
|||
|
|
<div class="table-header">POINT OF CARE SICKLE CELL ANEMIA TEST</div>
|
|||
|
|
<table class="test-details-table" style="border: 1px solid black; margin: 10px; width: 98%;">
|
|||
|
|
<tr style="height: 50px;">
|
|||
|
|
<th>
|
|||
|
|
Test Description
|
|||
|
|
</th>
|
|||
|
|
<th>
|
|||
|
|
RESULT
|
|||
|
|
</th>
|
|||
|
|
<th>
|
|||
|
|
REFERENCE RANGES
|
|||
|
|
</th>
|
|||
|
|
</tr>
|
|||
|
|
<tr class="test-details-row">
|
|||
|
|
<td class="test-details-col" style="width: 20%; margin: 10px;">
|
|||
|
|
<div style="margin: 10px;"> Sickle Cell Anemia
|
|||
|
|
<div class="test-method">(Method: HPOS)</div>
|
|||
|
|
</div>
|
|||
|
|
</td>
|
|||
|
|
<td style="width: 30%;">
|
|||
|
|
<div class="result-value">Ra = ${data["Test Right device 5 ratio"]} </div>
|
|||
|
|
<!-- <div class="test-cell-div">Normal</div>
|
|||
|
|
<div class="test-cell-div">Sickle Cell Trait</div>
|
|||
|
|
<div class="test-cell-div">Sickle Cell Disease</div>
|
|||
|
|
<div class="test-cell-div">Negative Borderline</div>
|
|||
|
|
<div class="test-cell-div">Positive Borderline</div> -->
|
|||
|
|
</td>
|
|||
|
|
<td style="width: 50%;">
|
|||
|
|
<div class="test-cell-div">
|
|||
|
|
< 0.16: Normal (HbA)</div>
|
|||
|
|
<div class="test-cell-div">0.165 – 0.235: Sickle-cell Trait (HbAS)</div>
|
|||
|
|
<div class="test-cell-div">> 0.24: Sickle-cell Disease (HbSS)</div>
|
|||
|
|
<div class="test-cell-div">0.16-0.165: Inconclusive (Negative Borderline)</div>
|
|||
|
|
<div class="test-cell-div">0.235 – 0.24: Inconclusive (Positive Borderline)</div>
|
|||
|
|
</td>
|
|||
|
|
<!-- <td style="width: 25%;">
|
|||
|
|
<div class="test-cell-div">Normal</div>
|
|||
|
|
<div class="test-cell-div">Sickle Cell Trait</div>
|
|||
|
|
<div class="test-cell-div">Sickle Cell Disease</div>
|
|||
|
|
<div class="test-cell-div">Recommended for HPLC or Electrophoresis Tests</div>
|
|||
|
|
<div class="test-cell-div">Recommended for HPLC or Electrophore</div>
|
|||
|
|
</td> -->
|
|||
|
|
</tr>
|
|||
|
|
</table>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div>
|
|||
|
|
<!-- <div style="font-weight: 600; margin: 10px;">INTERPRETATION:</div> -->
|
|||
|
|
|
|||
|
|
<div style="margin: 10px;">
|
|||
|
|
<strong>Test Principle:</strong> This point of care quantitative diagnostic test for sickle-cell anemia
|
|||
|
|
works on the principle of absorption
|
|||
|
|
spectroscopy. The test helps in differentiating heterozygous/homozygous hemoglobin from normal hemoglobin.
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div style="margin: 10px;">
|
|||
|
|
<strong>Method:</strong> High Performance Optical Spectroscopy (HPOS) for detection of Sickle cell trait and
|
|||
|
|
sickle cell disease in whole blood capillary blood samples.
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div style="margin: 10px;">
|
|||
|
|
<strong> Note:</strong>
|
|||
|
|
<!-- <ul>
|
|||
|
|
<li>a. Blood transfusion may have an impact on the test results.</li>
|
|||
|
|
|
|||
|
|
<li>
|
|||
|
|
b. Patients already on sickle-cell medications may impact test results.
|
|||
|
|
</li>
|
|||
|
|
</ul> -->
|
|||
|
|
|
|||
|
|
Borderline cases are reported as inconclusive. It may occur due to several factors such as medication,
|
|||
|
|
transfusion, field conditions and assay process. Further clinical tests are recommended in these cases for
|
|||
|
|
diagnosis.
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- <div
|
|||
|
|
style="margin: 80px 10px 20px 50px; width: 88%; display: flex; flex-direction: row; justify-content: space-between; align-items: center;">
|
|||
|
|
<div style="margin: 5px;">DATE:</div>
|
|||
|
|
<div style="margin: 5px;">Hematologist</div>
|
|||
|
|
</div> -->
|
|||
|
|
|
|||
|
|
<!-- <div style="margin: 30px;">
|
|||
|
|
This report is for the perusal of doctor only. Not for medico legal cases. Clinical correlation is
|
|||
|
|
essential.
|
|||
|
|
Please contact us in case of unexpected result.
|
|||
|
|
</div> -->
|
|||
|
|
<div style="height: 3px;width: 98%; background-color: black; margin-top: 150px;"></div>
|
|||
|
|
<div class="end-of-report">
|
|||
|
|
*** END OF REPORT ***</div>
|
|||
|
|
<div style="display: flex; justify-content: center; align-items: center; flex-direction: column;">
|
|||
|
|
<div style="font-style: italic; color: rgb(191, 191, 191);">
|
|||
|
|
This is an electronically generated report. Generated at ${moment().format('HH:MM')} hrs on ${moment().format('DD-MM-YYYY')}.
|
|||
|
|
</div>
|
|||
|
|
<div>
|
|||
|
|
Note: Assay results should be correlated clinically with other clinical findings
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</body>
|
|||
|
|
|
|||
|
|
</html>` };
|
|||
|
|
|
|||
|
|
html_to_pdf.generatePdf(template, options).then(pdfBuffer => {
|
|||
|
|
fs.writeFile(`reports/${data._id}.pdf`, pdfBuffer, "binary", function (err) {
|
|||
|
|
if (err) {
|
|||
|
|
console.log(err);
|
|||
|
|
} else {
|
|||
|
|
console.log("The file was saved!");
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const delay = (delayInms) => {
|
|||
|
|
return new Promise(resolve => setTimeout(resolve, delayInms));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
const users = [];
|
|||
|
|
fs.createReadStream("data/result.csv")
|
|||
|
|
.pipe(csv())
|
|||
|
|
.on('data', function(data){
|
|||
|
|
try {
|
|||
|
|
console.log("id: " + data._id);
|
|||
|
|
users.push(data);
|
|||
|
|
}
|
|||
|
|
catch(err) {
|
|||
|
|
//error handler
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
.on('end', async function(){
|
|||
|
|
console.log('size ', users.length);
|
|||
|
|
|
|||
|
|
for (let i = 0; i < users.length; i++) {
|
|||
|
|
await makePdf(users[i]);
|
|||
|
|
|
|||
|
|
let delayres = await delay(10000);
|
|||
|
|
console.log('index ', i);
|
|||
|
|
}
|
|||
|
|
});
|