Commit d11db87b authored by Thomas Huster's avatar Thomas Huster

[17251] added PrintMedicationHistoryHandler to generate pdf

parent 0c919943
......@@ -336,6 +336,17 @@
style="push">
</command>
</menuContribution>
<menuContribution
allPopups="false"
locationURI="toolbar:ch.elexis.core.ui.medication.views.MedicationView">
<command
commandId="ch.elexis.core.ui.PrintMedicationHistory"
icon="icon://IMG_DOCUMENT_PDF"
label="Medikation-Verlauf als Pdf"
style="push"
tooltip="Medikation-Verlauf als Pdf">
</command>
</menuContribution>
</extension>
<extension
point="org.eclipse.ui.preferencePages">
......@@ -783,6 +794,11 @@
id="ch.elexis.core.ui.commands.printContactLabel"
name="Print address label">
</command>
<command
defaultHandler="ch.elexis.core.ui.commands.PrintMedicationHistoryHandler"
id="ch.elexis.core.ui.PrintMedicationHistory"
name="Print medication history">
</command>
</extension>
<extension
point="ch.elexis.core.ui.KonsExtension">
......
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.1"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xChange="http://informatics.sgam.ch/xChange"
exclude-result-prefixes="fo">
<xsl:output method="xml" version="1.0" omit-xml-declaration="no"
indent="yes" encoding="UTF-8"/>
<xsl:param name="versionParam" select="'1.0'"/>
<xsl:param name="current-date" />
<!-- ========================= -->
<!-- root element: letter -->
<!-- ========================= -->
<xsl:template match="medicationhistory">
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="simpleA4"
page-height="29.7cm" page-width="21cm" margin-top="2cm"
margin-bottom="2cm" margin-left="2cm" margin-right="2cm">
<fo:region-body/>
<fo:region-after/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="simpleA4">
<fo:static-content flow-name="xsl-region-after">
<fo:block font-size="8pt" text-align-last="justify"
width="100%" border-top-style="solid" border-top-width="thin"
padding="1mm">
<fo:leader leader-pattern="space"/>
<fo:character character="&#x20;"/>
Seite
<fo:page-number/>
von
<fo:page-number-citation ref-id="last-page"/>
</fo:block>
</fo:static-content>
<fo:flow font-size="10pt" flow-name="xsl-region-body">
<fo:block font-size="8pt" text-align="right">
Medikationsverlauf von <xsl:value-of select="patientName"/>, <xsl:value-of select="patientDob"/> erstellt am <xsl:value-of select="$current-date"/>
</fo:block>
<fo:block text-align-last="justify"
width="100%" border-top-style="solid" border-top-width="thin"
padding="1mm" text-align="left" font-weight="bold"/>
<fo:block text-align="left" font-size="10pt">
<fo:table font-size="10pt" table-layout="fixed" width="100%">
<fo:table-column column-width="15%"/>
<fo:table-column column-width="15%"/>
<fo:table-column column-width="55%"/>
<fo:table-column column-width="15%"/>
<fo:table-header>
<fo:table-row>
<fo:table-cell>
<fo:block font-weight="bold">
Von
</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block font-weight="bold">
Bis
</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block font-weight="bold">
Medikament
</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block font-weight="bold">
Dosierung
</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-header>
<fo:table-body>
<xsl:apply-templates select="history"/>
</fo:table-body>
</fo:table>
</fo:block>
<fo:block id="last-page"/>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<!-- ========================= -->
<!-- child element: history -->
<!-- ========================= -->
<xsl:template match="history">
<xsl:variable name="bg-color">
<xsl:choose>
<xsl:when test="position() mod 2 = 0">white</xsl:when>
<xsl:otherwise>lightgrey</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<fo:table-row background-color="{$bg-color}">
<fo:table-cell>
<fo:block>
<xsl:value-of select="from"/>
</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>
<xsl:value-of select="to"/>
</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>
<xsl:value-of select="article"/>
</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>
<xsl:value-of select="dosage"/>
</fo:block>
</fo:table-cell>
</fo:table-row>
</xsl:template>
</xsl:stylesheet>
package ch.elexis.core.ui.commands;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.swt.program.Program;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.handlers.HandlerUtil;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceReference;
import org.slf4j.LoggerFactory;
import ch.elexis.core.data.events.ElexisEventDispatcher;
import ch.elexis.core.model.prescription.EntryType;
import ch.elexis.core.services.IFormattedOutput;
import ch.elexis.core.services.IFormattedOutputFactory;
import ch.elexis.core.services.IFormattedOutputFactory.ObjectType;
import ch.elexis.core.services.IFormattedOutputFactory.OutputType;
import ch.elexis.data.Patient;
import ch.elexis.data.Prescription;
import ch.elexis.data.Query;
import ch.rgw.tools.TimeTool;
public class PrintMedicationHistoryHandler extends AbstractHandler implements IHandler {
private static final String TOOPEN = " ... ";
@Override
public Object execute(ExecutionEvent event) throws ExecutionException{
ProgressMonitorDialog progress =
new ProgressMonitorDialog(HandlerUtil.getActiveShell(event));
try {
progress.run(true, false, new IRunnableWithProgress() {
@Override
public void run(IProgressMonitor monitor)
throws InvocationTargetException, InterruptedException{
monitor.beginTask("PDF erzeugen", IProgressMonitor.UNKNOWN);
Optional<MedicationHistoryLetter> letter = getToPrint();
if (letter.isPresent()) {
BundleContext bundleContext =
FrameworkUtil.getBundle(getClass()).getBundleContext();
ServiceReference<IFormattedOutputFactory> serviceRef =
bundleContext.getServiceReference(IFormattedOutputFactory.class);
if (serviceRef != null) {
IFormattedOutputFactory service = bundleContext.getService(serviceRef);
IFormattedOutput outputter = service
.getFormattedOutputImplementation(ObjectType.JAXB, OutputType.PDF);
ByteArrayOutputStream pdf = new ByteArrayOutputStream();
Map<String, String> parameters = new HashMap<>();
parameters.put("current-date",
LocalDate.now().format(DateTimeFormatter.ofPattern("dd.MM.yyyy")));
outputter.transform(letter.get(),
getClass().getResourceAsStream("/rsc/xslt/medhistory2fo.xslt"), pdf,
parameters);
bundleContext.ungetService(serviceRef);
// save and open the file ...
File file = null;
FileOutputStream fout = null;
try {
file = File.createTempFile("medhistory_", ".pdf");
fout = new FileOutputStream(file);
fout.write(pdf.toByteArray());
} catch (IOException e) {
Display.getDefault().syncExec(() -> {
MessageDialog.openError(HandlerUtil.getActiveShell(event),
"Fehler", "Fehler beim PDF anlegen.\n" + e.getMessage());
});
LoggerFactory.getLogger(getClass()).error("Error creating PDF", e);
} finally {
if (fout != null) {
try {
fout.close();
} catch (IOException e) {
// ignore
}
}
}
if (file != null) {
Program.launch(file.getAbsolutePath());
}
}
} else {
Display.getDefault().syncExec(() -> {
MessageDialog.openInformation(HandlerUtil.getActiveShell(event), "Info",
"Kein Patient ausgewählt, oder Patient hat keine Medikation.\n");
});
}
monitor.done();
}
});
} catch (InvocationTargetException | InterruptedException e) {
MessageDialog.openError(HandlerUtil.getActiveShell(event), "Fehler",
"Fehler beim PDF erzeugen.\n" + e.getMessage());
LoggerFactory.getLogger(getClass()).error("Error creating PDF", e);
}
return null;
}
@Override
public boolean isEnabled(){
return isFopServiceAvailable();
}
private boolean isFopServiceAvailable(){
BundleContext bundleContext = FrameworkUtil.getBundle(getClass()).getBundleContext();
return bundleContext.getServiceReference(IFormattedOutputFactory.class) != null;
}
public Optional<MedicationHistoryLetter> getToPrint(){
Patient patient = ElexisEventDispatcher.getSelectedPatient();
if (patient != null) {
Query<Prescription> qbe = new Query<Prescription>(Prescription.class);
qbe.add(Prescription.FLD_PATIENT_ID, Query.EQUALS, patient.getId());
List<Prescription> list = qbe.execute();
if (!list.isEmpty()) {
return Optional.of(MedicationHistoryLetter.of(patient, list));
}
}
return Optional.empty();
}
@XmlRootElement(name = "medicationhistory")
private static class MedicationHistoryLetter {
private List<MedicationHistoryItem> history;
@XmlElement
private String patientName;
@XmlElement
private String patientDob;
private MedicationHistoryLetter(){
// needed for jaxb
}
private MedicationHistoryLetter(Patient patient){
patientName = patient.getLabel(true);
patientDob = patient.getGeburtsdatum();
history = new ArrayList<>();
}
public void setHistory(List<MedicationHistoryItem> history){
this.history = history;
}
public List<MedicationHistoryItem> getHistory(){
return history;
}
public static MedicationHistoryLetter of(Patient patient, List<Prescription> list){
MedicationHistoryLetter ret = new MedicationHistoryLetter(patient);
for (Prescription prescription : list) {
if (prescription.getEntryType() != EntryType.RECIPE) {
Map<TimeTool, String> terms = prescription.getTerms();
TimeTool[] tts = terms.keySet().toArray(new TimeTool[0]);
for (int i = 0; i < tts.length - 1; i++) {
if (i < tts.length - 1) {
ret.history
.add(new MedicationHistoryItem(tts[i].toString(TimeTool.DATE_GER),
tts[i + 1].toString(TimeTool.DATE_GER), prescription));
} else {
ret.history.add(new MedicationHistoryItem(
tts[i].toString(TimeTool.DATE_GER), TOOPEN, prescription));
}
}
ret.history.add(new MedicationHistoryItem(
tts[tts.length - 1].toString(TimeTool.DATE_GER), TOOPEN, prescription));
}
}
Collections.sort(ret.history);
return ret;
}
}
@XmlRootElement(name = "historyitem")
private static class MedicationHistoryItem implements Comparable<MedicationHistoryItem> {
@XmlTransient
private TimeTool fromTool;
@XmlElement
private String from;
@XmlElement
private String to;
@XmlElement
private String article;
@XmlElement
private String dosage;
private MedicationHistoryItem(){
// needed for jaxb
}
public MedicationHistoryItem(final String from, final String to, final Prescription p){
this.from = from;
this.fromTool = new TimeTool(from);
this.to = to;
if (TOOPEN.equals(to) && StringUtils.isNotBlank(p.getEndDate())) {
this.to = p.getEndDate();
}
this.article = p.getArtikel() != null ? p.getArtikel().getLabel() : "?";
this.dosage = p.getDosis();
}
@Override
public int compareTo(MedicationHistoryItem other){
return other.fromTool.compareTo(fromTool);
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment