Skip to content

Instantly share code, notes, and snippets.

@rodcisal
Created April 16, 2020 14:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rodcisal/0498be0e3a7c601ad545d435b486c50e to your computer and use it in GitHub Desktop.
Save rodcisal/0498be0e3a7c601ad545d435b486c50e to your computer and use it in GitHub Desktop.
import { Email } from "meteor/email";
import axios from "axios";
import PDFDocument from "pdfkit";
import logoImage from "./logoImage";
import pushPdfToS3 from "./pushPdfToS3";
import UserFiles from "../collections/Files";
import formatRut from "../../../lib/formatRut";
import { renderFirma, renderFooter } from "./pdfs";
import { regularFontPath, boldFontPath } from "./pdfs/fonts";
const COLOR_PANTONE = "#2ec7d6";
const COLOR_PANTONE_BLUE = "#009CDE";
const fs = require("fs");
const generateHeaderReceta = (docType, doc) => {
const currentDate = new Date();
doc
.font(boldFontPath)
.text(docType, {
continued: true
})
.font(regularFontPath)
.text(
`Fecha de atención: ${currentDate.getDate()}/${currentDate.getMonth() +
1}/${currentDate.getFullYear()}`,
{ align: "right", underline: false }
);
doc
.moveTo(doc.page.margins.left, 90)
.lineTo(doc.page.width - doc.page.margins.right, 90)
.stroke();
doc.moveDown();
};
const generateHeaderDoc = (medico, doc) => {
doc.rect(0, 0, doc.page.width, 25);
doc.fillAndStroke(COLOR_PANTONE_BLUE, COLOR_PANTONE_BLUE);
doc.fontSize(12);
const nombreMedico =
medico.profile &&
`${medico.profile.nombre} ${medico.profile.apellidoPaterno}`;
doc
.image(logoImage, doc.page.margins.left, 40, {
width: 150,
align: "center",
valign: "center"
})
.font(boldFontPath)
.text("www.doctod.com", 110, 110)
.font(boldFontPath)
.text(`Dr(a). ${nombreMedico}`, 80, 50, { align: "right" })
.font(boldFontPath)
.fill("#000000")
.text(`${medico.profile.tituloProfesional}`, { align: "right" })
.font(boldFontPath)
.text(`RUT: ${formatRut(medico.profile.rut)}`, { align: "right" })
.text(`SIS: ${medico.profile.registroSis}`, { align: "right" });
doc.rect(0, 160, doc.page.width, 5);
doc.fillAndStroke(COLOR_PANTONE, COLOR_PANTONE);
};
const sendEmail = ({ filePath, filename, subject }) => {
if (Meteor.isProduction) {
Email.send({
from: "ayuda@doctod.com",
to: "rodcisal@gmail.com",
// cc: 'ronald.valenzuela.flores@gmail.com',
subject,
attachments: [{ path: filePath, filename }]
});
}
};
const generatePatientInfo = (doc, atencion) => {
doc.fontSize(14);
doc.moveDown(4);
doc
.fill("#000000")
.font(boldFontPath)
.text("NOMBRE: ", { continued: true })
.font(regularFontPath)
.text(atencion.paciente, { continued: true })
.font(boldFontPath)
.text(" FECHA: ", { continued: true })
.font(regularFontPath)
.text(moment().format("DD-MM-YYYY"));
doc.moveDown(0.5);
doc
.font(boldFontPath)
.text("RUT: ", { continued: true })
.font(regularFontPath)
.text(formatRut(`${atencion.rut}-${atencion.digitoVerificadorRut}`), {
continued: true
})
.font(boldFontPath)
.text(" EDAD: ", { continued: true })
.font(regularFontPath)
.text(`${atencion.edad} años`);
doc.moveDown(0.5);
doc
.font(boldFontPath)
.text("DOMICILIO: ", { continued: !!atencion.domicilio })
.font(regularFontPath)
.text(atencion.domicilio);
doc.moveDown(0.5);
const diagnosticos =
atencion.diagnosticos.length > 0 &&
atencion.diagnosticos.map(d => d.diagnosticoCie10).join(", ");
doc
.fill("#000000")
.font(boldFontPath)
.text("DIAGNOSTICO: ", { continued: true })
.font(regularFontPath)
.text(diagnosticos);
const distanceY = 310;
doc.rect(0, distanceY, doc.page.width, 5);
doc.fillAndStroke(COLOR_PANTONE, COLOR_PANTONE);
doc.moveDown(0.5);
// if (docType === "informe") {
// doc
// .font(boldFontPath)
// .text("Fecha de Nacimiento: ", { continued: true })
// .font(regularFontPath)
// .text(atencion.fechaDeNacimiento, { continued: true })
// .font(boldFontPath)
// .text(` (${atencion.edad} años)`);
// doc.moveDown(0.5);
// doc
// .font(boldFontPath)
// .text("Lugar de atención: ", { continued: true })
// .font(regularFontPath)
// .text(atencion.localidad);
// }
};
const getParamedicoName = atencion => {
const paramedico = Meteor.users.findOne({ _id: atencion.paramedicoId });
if (paramedico) {
return `${paramedico.profile.nombre} ${paramedico.profile.apellidoPaterno}`;
}
};
const renderImagenRegistro = async (fileId, doc) => {
const registroFile = UserFiles.findOne({ _id: fileId });
const registroFileLink = registroFile && registroFile.link();
if (!registroFileLink) return;
try {
await axios
.get(registroFileLink, { responseType: "arraybuffer" })
.then(response => {
const imageBuffer = Buffer.from(response.data);
doc.image(imageBuffer, { align: "center", width: 500 });
});
} catch (error) {
console.log("PROMISE ERROR", error);
}
};
const renderRegistros = (atencion, doc, promisesContainer) => {
if (!atencion.medicalRecord) return null;
atencion.medicalRecord.forEach(record => {
doc
.font(regularFontPath)
.text(`${record.periferico} - ${record.registryName}`);
doc.moveDown();
const pr = renderImagenRegistro(record.fileId, doc, promisesContainer);
promisesContainer.push(pr);
});
};
export default function(atencion, medico, tipoDocumento) {
const doc = new PDFDocument();
console.log("ATENCION ID", atencion._id);
if (tipoDocumento === "receta") {
console.log("GENERATING RECETA");
const filePath = `${process.env.PWD}/files/receta_medica_${atencion._id}.pdf`;
const writeStream = fs.createWriteStream(filePath);
doc.pipe(writeStream);
doc.fontSize(14);
generateHeaderDoc(medico, doc);
doc.moveDown();
generatePatientInfo(doc, atencion, "receta");
doc.moveDown(3);
doc.fill("#000000");
doc
.font(boldFontPath)
.text("RECETA MEDICA", { underline: true, align: "center" });
doc.moveDown(1);
doc.font(boldFontPath).text("Rp:");
doc.moveDown();
const list = atencion.indicacionesFarmacologicasPostAtencion.map(f => {
return `${f.medicamento} ${f.dosis}: Tomar ${f.frecuencia} ${f.presentacion} por ${f.duracion}`;
});
if (!list.length) {
return;
}
doc.font(regularFontPath).list(list);
renderFirma({ medico, doc, docType: "receta", atencionId: atencion._id });
renderFooter(doc);
writeStream.on(
"finish",
Meteor.bindEnvironment(() => {
pushPdfToS3(
filePath,
Meteor.bindEnvironment(() => {
sendEmail({
filePath,
filename: "receta.pdf",
subject: "Tu Receta Medica"
});
})
);
})
);
}
if (tipoDocumento === "reporte") {
console.log("GENERATING REPORTE");
const filePath = `${process.env.PWD}/files/solicitud_examenes_${atencion._id}.pdf`;
const writeStream = fs.createWriteStream(filePath);
doc.pipe(writeStream);
doc.fontSize(14);
generateHeaderDoc(medico, doc);
doc.moveDown();
generatePatientInfo(doc, atencion, "receta");
doc.moveDown(3);
doc.fill("#000000");
doc.font(boldFontPath).text("SOLICITUD DE EXAMENES", {
underline: true,
align: "center"
});
doc.moveDown(1);
doc.font(boldFontPath).text("EX:", { underline: true });
doc.moveDown();
const exList = atencion.indicacionesComplementariasPostAtencion
.filter(indicacion => indicacion.procedimiento !== "Terapias Auxiliares")
.map(indicacion => {
return `${indicacion.procedimiento}: ${indicacion.detalle}`;
});
if (!exList.length) {
return;
}
doc.font(regularFontPath).list(exList);
renderFooter(doc);
renderFirma({ medico, doc, atencionId: atencion._id });
writeStream.on(
"finish",
Meteor.bindEnvironment(() => {
pushPdfToS3(
filePath,
Meteor.bindEnvironment(() => {
sendEmail({
filePath,
filename: "solicitud_examenes.pdf",
subject: "Tu Solicitud de Examenes"
});
})
);
})
);
}
if (tipoDocumento === "terapias") {
console.log("GENERATING TERAPIAS");
const filePath = `${process.env.PWD}/files/terapias_auxiliares_${atencion._id}.pdf`;
const writeStream = fs.createWriteStream(filePath);
doc.pipe(writeStream);
doc.fontSize(14);
generateHeaderDoc(medico, doc);
doc.moveDown();
generatePatientInfo(doc, atencion, "receta");
doc.moveDown(3);
doc.fill("#000000");
doc.font(boldFontPath).text("TERAPIAS AUXILIARES", {
underline: true,
align: "center"
});
doc.moveDown(1);
doc.font(boldFontPath).text("EX:", { underline: true });
doc.moveDown();
console.log(atencion.indicacionesComplementariasPostAtencion);
const exList = atencion.indicacionesComplementariasPostAtencion
.filter(indicacion => indicacion.procedimiento === "Terapias Auxiliares")
.map(indicacion => {
return `${indicacion.procedimiento}: ${indicacion.detalle}`;
});
doc.font(regularFontPath).list(exList);
if (!exList.length) {
return;
}
renderFooter(doc);
renderFirma({ medico, doc, atencionId: atencion._id });
writeStream.on(
"finish",
Meteor.bindEnvironment(() => {
pushPdfToS3(
filePath,
Meteor.bindEnvironment(() => {
sendEmail({
filePath,
filename: "terapias_auxiliares.pdf",
subject: "Tus terapias auxiliares"
});
})
);
})
);
}
if (tipoDocumento === "informe") {
console.log("GENERATING INFORME");
const filePath = `${process.env.PWD}/files/informe_medico_${atencion._id}.pdf`;
const promisesContainer = [];
const writeStream = fs.createWriteStream(filePath);
doc.pipe(writeStream);
doc.fontSize(14);
generateHeaderReceta("Resumen de atención médica", doc);
doc.image(logoImage, { align: "center", valign: "center" });
generatePatientInfo(doc, atencion);
doc.moveDown(0.5);
doc
.font(boldFontPath)
.text("Hora inicio atención: ", { continued: true })
.font(regularFontPath)
.text(moment(atencion.takenByParamedicoAt).format("HH:mm"));
doc.moveDown(0.5);
doc
.font(boldFontPath)
.text("Hora termino atención: ", { continued: true })
.font(regularFontPath)
.text(moment(atencion.takenByParamedicoAt).format("HH:mm"));
doc.moveDown(0.5);
doc
.font(boldFontPath)
.text("Paramedico: ", { continued: true })
.font(regularFontPath)
.text(getParamedicoName(atencion));
doc.moveDown(2);
doc
.font(boldFontPath)
.text("Motivo de Consulta / Anamnesis:", { underline: true });
doc.moveDown();
const diagnosticos =
atencion.diagnosticos.length > 0 &&
atencion.diagnosticos.map(d => d.diagnosticoCie10).join(", ");
const hipotesis = `${atencion.impresionMedico} / ${diagnosticos}`;
doc.font(regularFontPath).text(hipotesis);
doc.moveDown(2);
doc.addPage();
doc.font(boldFontPath).text("Registros Medicos:", { underline: true });
doc.moveDown();
renderRegistros(atencion, doc, promisesContainer);
Promise.all(promisesContainer).then(() => {
doc.moveDown(2);
doc.font(boldFontPath).text("RP:", { underline: true });
doc.moveDown();
const list = atencion.indicacionesFarmacologicasPostAtencion.map(f => {
return `${f.medicamento} ${f.dosis}: Tomar ${f.frecuencia} ${f.presentacion} por ${f.duracion}`;
});
doc.font(regularFontPath).list(list);
doc.moveDown(2);
doc.font(boldFontPath).text("EX:", { underline: true });
doc.moveDown();
const exList = atencion.indicacionesComplementariasPostAtencion.map(f => {
return `${f.procedimiento}: ${f.detalle}`;
});
doc.font(regularFontPath).list(exList);
doc.moveDown(2);
doc.font(boldFontPath).text("Indicaciones:", { underline: true });
doc.moveDown();
const indicaciones = atencion.indicacionesNoFarmacologicasPostAtencion.map(
f => {
return `${f.tipo}: ${f.detalle} / ${f.observaciones}`;
}
);
doc.font(regularFontPath).list(indicaciones);
renderFirma({ medico, doc });
});
writeStream.on(
"finish",
Meteor.bindEnvironment(() => {
pushPdfToS3(
filePath,
Meteor.bindEnvironment(() => {
sendEmail({
filePath,
filename: "informe_medico.pdf",
subject: "Tu Informe Medico"
});
})
);
})
);
}
if (tipoDocumento === "certificadoReposo") {
console.log("GENERATING CERTIFICADO REPOSO");
if (
!atencion.indicacionesReposo ||
!atencion.indicacionesReposo.tipoReposo
) {
return;
}
const filePath = `${process.env.PWD}/files/certificado_reposo_${atencion._id}.pdf`;
const writeStream = fs.createWriteStream(filePath);
doc.pipe(writeStream);
doc.fontSize(14);
generateHeaderDoc(medico, doc);
doc.moveDown();
generatePatientInfo(doc, atencion, "certificadoReposo");
// campos unicos a tipo de documento
doc.moveDown(2.5);
doc.fill("#000000");
doc
.font(boldFontPath)
.text("CERTIFICADO DE REPOSO", { underline: true, align: "center" });
doc.moveDown(1);
doc
.font(regularFontPath)
.text(
"El medico que suscribe certifica asistir profesionalmente al paciente:"
);
doc.font(boldFontPath).text(atencion.paciente);
doc.moveDown();
doc
.font(regularFontPath)
.text("Y quien debera permanecer en reposo: ", { continued: true })
.font(boldFontPath)
.text(atencion.indicacionesReposo.tipoReposo);
doc.moveDown();
const { fechaInicioReposo } = atencion.indicacionesReposo;
const fechaInicioReposoFormatted = `${fechaInicioReposo.getDate()}/${fechaInicioReposo.getMonth() +
1}/${fechaInicioReposo.getFullYear()}`;
const fechaTerminoReposo = new Date(
fechaInicioReposo.getTime() +
parseInt(atencion.indicacionesReposo.duracionReposo) * 86400000
);
const fechaTerminoReposoFormatted = `${fechaTerminoReposo.getDate()}/${fechaTerminoReposo.getMonth() +
1}/${fechaTerminoReposo.getFullYear()}`;
doc
.font(regularFontPath)
.text("Desde el: ", { continued: true })
.font(boldFontPath)
.text(fechaInicioReposoFormatted, { continued: true })
.font(regularFontPath)
.text(" Hasta el: ", { continued: true })
.font(boldFontPath)
.text(fechaTerminoReposoFormatted);
doc.moveDown();
doc
.font(regularFontPath)
.text("Extiendo el presente certificado para ser presentado en: ")
.font(boldFontPath)
.text(atencion.indicacionesReposo.lugarPresentacion);
doc.moveDown();
renderFooter(doc);
renderFirma({ medico, doc, atencionId: atencion._id });
writeStream.on(
"finish",
Meteor.bindEnvironment(() => {
pushPdfToS3(
filePath,
Meteor.bindEnvironment(() => {
sendEmail({
filePath,
filename: "certificado_reposo.pdf",
subject: "Tu Certificado de Reposo"
});
})
);
})
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment