Základní implementace podepisování PDF dokumentů. Podpis implementován pouze pro sestavu schválení služební cesty (natvrdo v kódu). Spouští se univerzální podepisovací aplikace, která čte certifikát ze souboru.

closes #224
This commit is contained in:
2015-06-24 12:54:31 +02:00
parent 312b62af7b
commit d6cff454fd
16 changed files with 960 additions and 4 deletions
@@ -168,4 +168,7 @@ public class Constants {
public final static int LEN_TEXT = 255;
public final static int LEN_DESCRIPTION = 8192;
public final static int LEN_RESULT_MESSAGE = 8192;
public final static String KEY_SIGN_DATA = "SIGN_DATA";
public final static String KEY_SIGN_GUID = "SIGN_GUID";
}
@@ -5,6 +5,7 @@ import info.bukova.isspst.data.User;
import info.bukova.isspst.data.Workgroup;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -13,16 +14,18 @@ public class SessionData implements Serializable {
/**
*
*/
private static final long serialVersionUID = -764426911263559758L;
private static final long serialVersionUID = -764426911263559759L;
private List<Workgroup> userCentres;
private List<Workgroup> userWorkgroups;
private User currentUser;
private Map<Integer, List<Role>> workgroupRoles;
private boolean loginFailed;
private Map<String, Object> properties;
public SessionData() {
loginFailed = false;
properties = new HashMap<String, Object>();
}
public List<Workgroup> getUserCentres() {
@@ -65,4 +68,11 @@ public class SessionData implements Serializable {
this.loginFailed = loginFailed;
}
public void setProperty(String key, Object value) {
properties.put(key, value);
}
public Object getProperty(String key) {
return properties.get(key);
}
}
@@ -0,0 +1,55 @@
package info.bukova.isspst.reporting;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.PdfAnnotation;
import com.lowagie.text.pdf.PdfFormField;
import com.lowagie.text.pdf.PdfName;
import net.sf.jasperreports.engine.JRGenericPrintElement;
import net.sf.jasperreports.engine.JRPropertiesMap;
import net.sf.jasperreports.engine.export.GenericElementHandler;
import net.sf.jasperreports.engine.export.GenericElementHandlerBundle;
import net.sf.jasperreports.engine.export.GenericElementPdfHandler;
import net.sf.jasperreports.engine.export.JRPdfExporter;
import net.sf.jasperreports.engine.export.JRPdfExporterContext;
import net.sf.jasperreports.extensions.ExtensionsRegistry;
import net.sf.jasperreports.extensions.ExtensionsRegistryFactory;
import net.sf.jasperreports.extensions.SingletonExtensionRegistry;
/**
* @author Pepa Rokos
*/
public class SignaturePdfHandler implements GenericElementPdfHandler, GenericElementHandlerBundle, ExtensionsRegistryFactory {
@Override
public ExtensionsRegistry createRegistry(String registryId, JRPropertiesMap properties) {
return new SingletonExtensionRegistry<GenericElementHandlerBundle>(GenericElementHandlerBundle.class, this);
}
@Override
public void exportElement(JRPdfExporterContext exporterContext, JRGenericPrintElement element) {
PdfFormField field = PdfFormField.createSignature(exporterContext.getPdfWriter());
field.setFieldName("signature");
field.setFieldFlags(PdfAnnotation.FLAGS_PRINT | PdfAnnotation.FLAGS_LOCKED);
field.setWidget(new Rectangle(element.getX(), element.getY(), element.getX() + element.getWidth(), element.getY() + element.getHeight()), PdfName.HIGHLIGHT);
exporterContext.getPdfWriter().addAnnotation(field);
}
@Override
public boolean toExport(JRGenericPrintElement element) {
return true;
}
@Override
public String getNamespace() {
return "urn:sig:sig";
}
@Override
public GenericElementHandler getHandler(String elementName, String exporterKey) {
if (elementName.equals("signature") && exporterKey.equals(JRPdfExporter.PDF_EXPORTER_KEY)) {
return this;
}
return null;
}
}
@@ -0,0 +1,10 @@
package info.bukova.isspst.signapi;
/**
* @author Pepa Rokos
*/
public interface JnlpGenerator {
public byte[] generate();
}
@@ -0,0 +1,109 @@
package info.bukova.isspst.signapi;
import org.springframework.beans.factory.annotation.Autowired;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.servlet.http.HttpServletRequest;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.ByteArrayOutputStream;
/**
* @author Pepa Rokos
*/
public class JnlpGeneratorImpl implements JnlpGenerator {
@Autowired
private HttpServletRequest request;
@Override
public byte[] generate() {
String sessionId;
if (request.getParameter("id") != null && !request.getParameter("id").isEmpty()) {
sessionId = request.getParameter("id");
} else {
sessionId = request.getSession().getId();
}
try {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document document = docBuilder.newDocument();
Element root = document.createElement("jnlp");
root.setAttribute("spec", "1.0+");
String signerUrl = request.getRequestURL().toString();
signerUrl = signerUrl.substring(0, signerUrl.indexOf(request.getServletPath())) + "/api/sign";
root.setAttribute("codebase", signerUrl);
root.setAttribute("href", "signer.jnlp" + "?id=" + sessionId);
document.appendChild(root);
Element info = document.createElement("information");
Element title = document.createElement("title");
title.appendChild(document.createTextNode("Signer component"));
info.appendChild(title);
Element vendor = document.createElement("vendor");
vendor.appendChild(document.createTextNode("bukova.info"));
info.appendChild(vendor);
root.appendChild(info);
Element security = document.createElement("security");
security.appendChild(document.createElement("all-permissions"));
root.appendChild(security);
Element resources = document.createElement("resources");
Element j2se = document.createElement("j2se");
j2se.setAttribute("version", "1.8+");
Element jar = document.createElement("jar");
jar.setAttribute("href", "pdfsigner.jar");
resources.appendChild(j2se);
resources.appendChild(jar);
root.appendChild(resources);
Element appDesc = document.createElement("application-desc");
appDesc.setAttribute("main-class", "info.bukova.pdfsigner.Main");
Element argUrl = document.createElement("argument");
argUrl.appendChild(document.createTextNode(signerUrl + "/data"));
appDesc.appendChild(argUrl);
Element argSession = document.createElement("argument");
argSession.appendChild(document.createTextNode(sessionId));
appDesc.appendChild(argSession);
root.appendChild(appDesc);
System.out.println(signerUrl);
System.out.println(request.getSession().getId());
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(document);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
StreamResult result = new StreamResult(bos);
transformer.transform(source, result);
return bos.toByteArray();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (TransformerConfigurationException e) {
e.printStackTrace();
} catch (TransformerException e) {
e.printStackTrace();
}
return null;
}
}
@@ -0,0 +1,92 @@
package info.bukova.isspst.signapi;
import java.io.Serializable;
import java.util.Date;
/**
* @author Pepa Rokos
*/
public class SignData implements Serializable {
private byte[] pdfData;
private byte[] signImg;
private int areaId;
private Date signDate;
private String description;
private String numser;
private boolean signed;
private String signGuid;
private boolean signSuccess;
public byte[] getPdfData() {
return pdfData;
}
public void setPdfData(byte[] pdfData) {
this.pdfData = pdfData;
}
public Date getSignDate() {
return signDate;
}
public void setSignDate(Date signDate) {
this.signDate = signDate;
}
public String getNumser() {
return numser;
}
public void setNumser(String numser) {
this.numser = numser;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public boolean isSigned() {
return signed;
}
public void setSigned(boolean signed) {
this.signed = signed;
}
public String getSignGuid() {
return signGuid;
}
public void setSignGuid(String signGuid) {
this.signGuid = signGuid;
}
public boolean isSignSuccess() {
return signSuccess;
}
public void setSignSuccess(boolean signSuccess) {
this.signSuccess = signSuccess;
}
public byte[] getSignImg() {
return signImg;
}
public void setSignImg(byte[] signImg) {
this.signImg = signImg;
}
public int getAreaId() {
return areaId;
}
public void setAreaId(int areaId) {
this.areaId = areaId;
}
}
@@ -0,0 +1,28 @@
package info.bukova.isspst.signapi;
import java.io.Serializable;
/**
* @author Pepa Rokos
*/
public class SignUploadResponse implements Serializable {
private boolean ok;
private String errorMessage;
public boolean isOk() {
return ok;
}
public void setOk(boolean ok) {
this.ok = ok;
}
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
}
@@ -0,0 +1,133 @@
package info.bukova.isspst.signapi;
import info.bukova.isspst.Constants;
import info.bukova.isspst.SessionData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.servlet.ServletContext;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/**
* @author Pepa Rokos
*/
@Controller
public class SigningController {
@Autowired
private SessionData sessionData;
@Autowired
private JnlpGenerator jnlpGenerator;
@Autowired
private ServletContext context;
@RequestMapping(value="/sign/data", method= RequestMethod.GET)
public void dataForSign(HttpServletResponse response, HttpServletRequest request) {
SignData data = (SignData) sessionData.getProperty(Constants.KEY_SIGN_DATA);
ObjectOutputStream os = null;
try {
os = new ObjectOutputStream(response.getOutputStream());
response.setContentType("application/x-java-serialized-object");
os.writeObject(data);
os.flush();
os.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@RequestMapping(value="/sign/data", method= RequestMethod.POST)
public void signedData(HttpServletRequest request, HttpServletResponse response) {
ObjectInputStream ois = null;
ObjectOutputStream os = null;
String error = null;
try {
ois = new ObjectInputStream(request.getInputStream());
SignData data = (SignData) ois.readObject();
sessionData.setProperty(Constants.KEY_SIGN_DATA, data);
} catch (IOException e) {
e.printStackTrace();
error = "IO error";
} catch (ClassNotFoundException e) {
e.printStackTrace();
error = "Loading error";
}
try {
SignUploadResponse resp = new SignUploadResponse();
if (error == null) {
resp.setOk(true);
} else {
resp.setOk(false);
resp.setErrorMessage(error);
}
os = new ObjectOutputStream(response.getOutputStream());
response.setContentType("application/x-java-serialized-object");
os.writeObject(resp);
os.flush();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
@RequestMapping(value="/sign/signer.jnlp", method= RequestMethod.GET)
public void jnlp(HttpServletResponse response) {
byte[] data = jnlpGenerator.generate();
sendByte(response, data, "application/x-java-jnlp-file");
}
@RequestMapping(value="/sign/pdfsigner.jar", method= RequestMethod.GET)
public void pdfsigner(HttpServletResponse response) {
File inputJar = new File(context.getRealPath("/WEB-INF/signer/PDFSigner.jar"));
try {
byte[] data = new byte[(int) inputJar.length()];
FileInputStream is = new FileInputStream(inputJar);
is.read(data);
sendByte(response, data, "application/java-archive");
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private void sendByte(HttpServletResponse response, byte[] data, String contentType) {
ServletOutputStream os = null;
try {
os = response.getOutputStream();
response.setContentType(contentType);
response.setContentLength(data.length);
os.write(data);
os.flush();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@@ -1,19 +1,32 @@
package info.bukova.isspst.ui.main;
import info.bukova.isspst.Constants;
import info.bukova.isspst.SessionData;
import info.bukova.isspst.StringUtils;
import info.bukova.isspst.data.RequirementBase;
import info.bukova.isspst.reporting.Generator;
import info.bukova.isspst.reporting.GeneratorFactory;
import info.bukova.isspst.reporting.ParamFiller;
import info.bukova.isspst.reporting.Report;
import info.bukova.isspst.reporting.ReportDefinition;
import info.bukova.isspst.services.Service;
import info.bukova.isspst.services.requirement.ApproveException;
import info.bukova.isspst.services.requirement.RequirementBaseService;
import info.bukova.isspst.signapi.SignData;
import info.bukova.isspst.ui.ListViewModel;
import org.zkoss.bind.BindUtils;
import org.zkoss.bind.annotation.BindingParam;
import org.zkoss.bind.annotation.Command;
import org.zkoss.bind.annotation.ExecutionArgParam;
import org.zkoss.bind.annotation.Init;
import org.zkoss.bind.annotation.NotifyChange;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.select.annotation.WireVariable;
import org.zkoss.zul.Messagebox;
import org.zkoss.zul.Window;
import java.util.Date;
import java.util.UUID;
/**
* @author Pepa Rokos
@@ -24,6 +37,16 @@ public class ApproveDialogVM {
private RequirementBase requirement;
private ListViewModel grid;
private Date approveDate;
@WireVariable
private SessionData sessionData;
@WireVariable
private ReportDefinition reportDefinition;
@WireVariable
private GeneratorFactory genFactory;
@WireVariable
private ParamFiller paramFiller;
private boolean signed;
private boolean timer;
public Date getApproveDate() {
return approveDate;
@@ -41,6 +64,9 @@ public class ApproveDialogVM {
this.requirement = requirement;
this.grid = grid;
this.approveDate = new Date();
this.signed = false;
this.timer = false;
}
@Command
@@ -57,4 +83,51 @@ public class ApproveDialogVM {
}
}
@Command
@NotifyChange("timer")
public void signPdf() {
SignData data = new SignData();
sessionData.setProperty(Constants.KEY_SIGN_DATA, data);
data.setSignGuid(UUID.randomUUID().toString());
sessionData.setProperty(Constants.KEY_SIGN_GUID, data.getSignGuid());
// ToDo: Generovat report
reportDefinition.clear();
reportDefinition.setSingleObject(requirement);
reportDefinition.setReport(new Report(0, true, "", "tripRequirementApp", false, true, true));
reportDefinition.setService((Service) service);
paramFiller.fill();
Generator gen = genFactory.createGenerator(reportDefinition);
data.setPdfData(gen.generate());
data.setDescription(requirement.getDescription());
data.setNumser(requirement.getNumser());
timer = true;
Executions.getCurrent().sendRedirect("/api/sign/signer.jnlp", "signer");
}
@Command
@NotifyChange({"signed", "timer"})
public void onTimer() {
String guid = (String) sessionData.getProperty(Constants.KEY_SIGN_GUID);
SignData data = (SignData) sessionData.getProperty(Constants.KEY_SIGN_DATA);
if (guid.equals(data.getSignGuid()) && data.isSignSuccess()) {
signed = true;
timer = false;
} else {
signed = false;
}
}
public boolean isSigned() {
return signed;
}
public boolean isTimer() {
return timer;
}
}
@@ -0,0 +1 @@
net.sf.jasperreports.extension.registry.factory.sig=info.bukova.isspst.reporting.SignaturePdfHandler
@@ -0,0 +1,356 @@
<?xml version="1.0" encoding="UTF-8"?>
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="tripRequirement" pageWidth="612" pageHeight="792" columnWidth="572" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="0b7fa2d2-d452-4a1f-b1c0-2d8e16a22525">
<property name="ireport.zoom" value="1.5"/>
<property name="ireport.x" value="0"/>
<property name="ireport.y" value="272"/>
<style name="table">
<box>
<pen lineWidth="1.0" lineColor="#000000"/>
</box>
</style>
<style name="table_TH" mode="Opaque" backcolor="#F0F8FF">
<box>
<pen lineWidth="0.5" lineColor="#000000"/>
</box>
</style>
<style name="table_CH" mode="Opaque" backcolor="#BFE1FF">
<box>
<pen lineWidth="0.5" lineColor="#000000"/>
</box>
</style>
<style name="table_TD" mode="Opaque" backcolor="#FFFFFF">
<box>
<pen lineWidth="0.5" lineColor="#000000"/>
</box>
</style>
<subDataset name="Passengers" uuid="89ee82de-f017-493e-85d1-439a0ff3be72">
<queryString>
<![CDATA[]]>
</queryString>
<field name="fullName" class="java.lang.String">
<fieldDescription><![CDATA[fullName]]></fieldDescription>
</field>
</subDataset>
<subDataset name="dataset1" uuid="2030e480-17f9-4ac5-a8f1-7499b269f3b4"/>
<parameter name="P_USER_SIGNATURE" class="java.lang.String"/>
<parameter name="P_APPROVE_DATE" class="java.util.Date"/>
<parameter name="P_APPROVER_SIGNATURE" class="java.lang.String"/>
<parameter name="P_LOGO" class="java.lang.String"/>
<parameter name="P_MAIN_ADDRESS" class="java.lang.String"/>
<parameter name="P_PREV_APPROVE_DATE" class="java.util.Date"/>
<parameter name="P_PREV_APPROVER_SIGNATURE" class="java.lang.String"/>
<parameter name="SUBREPORT_DIR" class="java.lang.String"/>
<field name="ownedBy" class="info.bukova.isspst.data.User"/>
<field name="reqDate" class="java.util.Date"/>
<field name="from" class="java.lang.String"/>
<field name="tripDate" class="java.util.Date"/>
<field name="to" class="java.lang.String"/>
<field name="description" class="java.lang.String"/>
<field name="end" class="java.lang.String"/>
<field name="endDate" class="java.util.Date"/>
<field name="passengers" class="java.util.Collection"/>
<field name="foreignPersons" class="java.lang.String"/>
<field name="vehicle" class="info.bukova.isspst.data.Vehicle"/>
<field name="vehicle.code" class="java.lang.String"/>
<field name="requireDownPayment" class="java.lang.Boolean"/>
<field name="downPayment" class="java.math.BigDecimal"/>
<field name="ownedBy.address" class="info.bukova.isspst.data.UsersAddress"/>
<field name="ownedBy.address.street" class="java.lang.String"/>
<field name="ownedBy.address.houseNumber" class="java.lang.String"/>
<field name="ownedBy.address.zipCode" class="java.lang.String"/>
<field name="ownedBy.address.city" class="java.lang.String"/>
<background>
<band splitType="Stretch"/>
</background>
<title>
<band height="79" splitType="Stretch">
<image onErrorType="Blank">
<reportElement uuid="ef1dc796-f5c6-4036-99eb-26e7b6b7abbc" x="0" y="0" width="100" height="79" isRemoveLineWhenBlank="true">
<printWhenExpression><![CDATA[$P{P_LOGO} != null]]></printWhenExpression>
</reportElement>
<imageExpression><![CDATA[$P{P_LOGO}]]></imageExpression>
</image>
<textField>
<reportElement uuid="3e2074cd-220c-4c9a-b94c-a0a254cc24a6" x="100" y="0" width="471" height="34"/>
<textElement textAlignment="Center">
<font isBold="true" pdfEncoding="Cp1250"/>
</textElement>
<textFieldExpression><![CDATA[$P{P_MAIN_ADDRESS}]]></textFieldExpression>
</textField>
<staticText>
<reportElement uuid="a7a82c52-e8b8-41cf-b13a-ebc54d30d04f" x="101" y="34" width="470" height="45"/>
<textElement textAlignment="Center" verticalAlignment="Bottom">
<font size="14" isBold="true" pdfEncoding="Cp1250"/>
</textElement>
<text><![CDATA[CESTOVNÍ PŘÍKAZ
k tuzemské pracovní cestě]]></text>
</staticText>
</band>
</title>
<detail>
<band height="529" splitType="Stretch">
<staticText>
<reportElement uuid="f6445d7f-1e96-4d17-9f1d-27eaa8f15022" x="0" y="7" width="143" height="20"/>
<textElement/>
<text><![CDATA[Příjmení, jméno, titul:]]></text>
</staticText>
<staticText>
<reportElement uuid="6f073490-98cc-445b-8b51-81facf335657" x="0" y="27" width="100" height="20"/>
<textElement/>
<text><![CDATA[Bydliště:]]></text>
</staticText>
<staticText>
<reportElement uuid="a3e2a5d3-ea50-48bd-94ea-4530f6624b52" x="0" y="51" width="572" height="20"/>
<textElement textAlignment="Center">
<font size="12" pdfFontName="Helvetica-Bold"/>
</textElement>
<text><![CDATA[Souhlasím s vysláním na pracovní cestu]]></text>
</staticText>
<staticText>
<reportElement uuid="306f2b85-5dc6-40a6-8c44-76ed46831680" x="0" y="76" width="143" height="20"/>
<textElement/>
<text><![CDATA[Požaduji poskytnutí zálohy:]]></text>
</staticText>
<line>
<reportElement uuid="029f1b4c-5f59-4a5e-8d3d-b644af41b657" x="301" y="121" width="271" height="1"/>
</line>
<staticText>
<reportElement uuid="2f0f450a-b89d-4862-b82e-4eb1e9861927" x="301" y="128" width="271" height="20"/>
<textElement textAlignment="Center"/>
<text><![CDATA[Datum a podpis]]></text>
</staticText>
<textField pattern="dd. MM. yyyy">
<reportElement uuid="dd5f12d3-9ce1-4565-83ed-fe9004e3a6c3" x="301" y="101" width="77" height="20"/>
<textElement/>
<textFieldExpression><![CDATA[$F{reqDate}]]></textFieldExpression>
</textField>
<staticText>
<reportElement uuid="a2912fef-ae4a-4c7e-b08c-3f5f6b92a534" x="0" y="157" width="572" height="20"/>
<textElement textAlignment="Center">
<font size="16" isBold="true" pdfFontName="Helvetica-Bold" isPdfEmbedded="true"/>
</textElement>
<text><![CDATA[PODMÍNKY PRACOVNÍ CESTY]]></text>
</staticText>
<line>
<reportElement uuid="b415fa20-91d9-4772-9b73-fd26b6cf32a3" x="0" y="177" width="572" height="1"/>
</line>
<line>
<reportElement uuid="74a5cf40-10b4-4f99-8945-5e14323a7b98" x="0" y="253" width="572" height="1"/>
</line>
<line>
<reportElement uuid="a3a337aa-8b1c-4f4f-abc0-4b5a6cba04d5" x="0" y="156" width="572" height="1"/>
</line>
<staticText>
<reportElement uuid="ed4e3928-9a68-4f61-9876-254547efa04e" x="0" y="180" width="143" height="27"/>
<textElement textAlignment="Center"/>
<text><![CDATA[Počátek cesty (místo, datum, hodina)]]></text>
</staticText>
<textField>
<reportElement uuid="ed4a676e-2647-4a91-a1b5-1ff326f50359" x="0" y="208" width="143" height="20"/>
<textElement textAlignment="Center"/>
<textFieldExpression><![CDATA[$F{from}]]></textFieldExpression>
</textField>
<textField pattern="dd. MM. yyyy">
<reportElement uuid="fd80824e-0a50-4e37-abd5-1c8bf92ded4a" x="0" y="228" width="90" height="20"/>
<textElement/>
<textFieldExpression><![CDATA[$F{tripDate}]]></textFieldExpression>
</textField>
<textField pattern="hh:mm">
<reportElement uuid="4d004341-3dc5-4b77-a0f2-d93c93aff176" x="90" y="228" width="53" height="20"/>
<textElement/>
<textFieldExpression><![CDATA[$F{tripDate}]]></textFieldExpression>
</textField>
<staticText>
<reportElement uuid="36c8b801-3fdf-4464-99d7-4f07539d76f8" x="143" y="180" width="143" height="27"/>
<textElement textAlignment="Center"/>
<text><![CDATA[Místo jednání]]></text>
</staticText>
<textField>
<reportElement uuid="6e9e44fe-3022-4802-854e-607238cb21be" x="143" y="208" width="143" height="20"/>
<textElement textAlignment="Center"/>
<textFieldExpression><![CDATA[$F{to}]]></textFieldExpression>
</textField>
<staticText>
<reportElement uuid="398372d7-7995-42fa-a53a-f50b0f8936db" x="286" y="179" width="143" height="27"/>
<textElement textAlignment="Center"/>
<text><![CDATA[Účel cesty]]></text>
</staticText>
<staticText>
<reportElement uuid="3dbc8b8d-7ac4-40d8-b43c-89e81d26f15c" x="429" y="180" width="143" height="26"/>
<textElement textAlignment="Center"/>
<text><![CDATA[Konec cesty (místo, datum)]]></text>
</staticText>
<textField isBlankWhenNull="true">
<reportElement uuid="3b52420d-1c84-4042-bc88-16f4f36a3af8" x="286" y="208" width="143" height="40"/>
<textElement textAlignment="Center"/>
<textFieldExpression><![CDATA[$F{description}]]></textFieldExpression>
</textField>
<textField>
<reportElement uuid="3e9b796b-fc9e-42e4-93d6-a966ce78c771" x="429" y="208" width="143" height="20"/>
<textElement textAlignment="Center"/>
<textFieldExpression><![CDATA[$F{end}]]></textFieldExpression>
</textField>
<textField pattern="dd. MM. yyyy">
<reportElement uuid="6ae75bed-b03b-4857-b624-71daeb35513d" x="429" y="228" width="143" height="20"/>
<textElement textAlignment="Center"/>
<textFieldExpression><![CDATA[$F{endDate}]]></textFieldExpression>
</textField>
<textField>
<reportElement uuid="ad778808-c5cc-419c-b34f-fc84effc1958" x="186" y="7" width="181" height="20"/>
<textElement/>
<textFieldExpression><![CDATA[$F{ownedBy}]]></textFieldExpression>
</textField>
<staticText>
<reportElement uuid="deafc33f-99ed-483e-8682-57a18872941d" x="0" y="265" width="143" height="20"/>
<textElement/>
<text><![CDATA[Spolucestující:]]></text>
</staticText>
<staticText>
<reportElement uuid="ab2fbb7c-28d3-4e6b-beb9-93c6fc8745c8" x="0" y="307" width="348" height="20"/>
<textElement/>
<text><![CDATA[Určený dopravní prostředek (u vlastního vozidla druh a reg. značka):]]></text>
</staticText>
<textField>
<reportElement uuid="1a52f009-c560-443a-9b84-cd9502b6b0c5" x="348" y="307" width="60" height="20"/>
<textElement/>
<textFieldExpression><![CDATA[$F{vehicle.code}]]></textFieldExpression>
</textField>
<staticText>
<reportElement uuid="8355e20a-124b-4c63-ab9c-4d64be5b912e" x="0" y="327" width="572" height="40"/>
<textElement textAlignment="Center"/>
<text><![CDATA[A - autobus, V - vlak
AUV - auto vlastní, AUS - auto služební, AUC - auto cizí
L - letadlo, P - pěšky, T - taxi]]></text>
</staticText>
<staticText>
<reportElement uuid="94f07671-9d8f-4542-9afe-f1c0b8ae1a02" x="0" y="369" width="143" height="20"/>
<textElement/>
<text><![CDATA[Ubytování:]]></text>
</staticText>
<staticText>
<reportElement uuid="b1cd5f7d-48fc-4f1b-82e1-69f81026b5ac" x="0" y="398" width="143" height="20"/>
<textElement/>
<text><![CDATA[Poskytnutí zálohy ve výši:]]></text>
</staticText>
<line>
<reportElement uuid="57398205-845b-4633-89db-3b0c4b31f03c" x="301" y="418" width="271" height="1"/>
</line>
<staticText>
<reportElement uuid="e33b0435-12e0-4d9f-9d3f-44f54eed9505" x="301" y="423" width="271" height="20"/>
<textElement textAlignment="Center"/>
<text><![CDATA[Datum a podpis oprávněné osoby]]></text>
</staticText>
<staticText>
<reportElement uuid="cad8d17d-5fdc-41a8-a74d-54ea34e4cdad" x="0" y="449" width="100" height="20"/>
<textElement/>
<text><![CDATA[Povolená záloha]]></text>
</staticText>
<staticText>
<reportElement uuid="2b462c95-65b1-4295-ac47-7d2ac3e16f40" x="0" y="469" width="143" height="20"/>
<textElement/>
<text><![CDATA[Pokladní doklad číslo]]></text>
</staticText>
<staticText>
<reportElement uuid="4cfe5623-901b-4508-9161-920d90cd0405" x="301" y="449" width="100" height="20"/>
<textElement/>
<text><![CDATA[Vyplacená dne:]]></text>
</staticText>
<line>
<reportElement uuid="39f180e0-0300-4087-89b2-dbd9441d1e94" x="149" y="500" width="280" height="1"/>
</line>
<staticText>
<reportElement uuid="a7218a5e-4d69-41fe-a26b-a51dd240cfb1" x="149" y="508" width="280" height="20"/>
<textElement textAlignment="Center"/>
<text><![CDATA[Podpis pokladníka]]></text>
</staticText>
<line direction="BottomUp">
<reportElement uuid="0276901c-8949-4307-a4a6-efa1a9b83341" x="571" y="-79" width="1" height="607"/>
</line>
<line direction="BottomUp">
<reportElement uuid="01ad15ce-276d-4fb8-af37-d896fa7eb77a" x="-1" y="-79" width="1" height="607"/>
</line>
<line>
<reportElement uuid="31fec8f3-7de4-4c34-934e-dbc2ad813c49" x="-1" y="-80" width="573" height="1"/>
</line>
<line>
<reportElement uuid="11f1abd0-78a2-4cee-9553-c960a59a00d3" x="-1" y="528" width="573" height="1"/>
</line>
<line>
<reportElement uuid="00689195-f270-4b32-9878-74c6d5d353cd" x="-1" y="0" width="573" height="1"/>
</line>
<line>
<reportElement uuid="0d8ef0ad-db1e-4be9-8153-b3a885fb8ace" x="0" y="148" width="572" height="1"/>
</line>
<line>
<reportElement uuid="c9713d6e-9b2e-4ce6-8837-3fbbe320fa8b" x="143" y="178" width="1" height="75"/>
</line>
<line>
<reportElement uuid="4e1fb287-81be-477a-95c2-96691d638916" x="285" y="178" width="1" height="75"/>
</line>
<line>
<reportElement uuid="bc2f55db-f6e3-46eb-81cd-1b4161ceeffd" x="428" y="178" width="1" height="75"/>
</line>
<line>
<reportElement uuid="0e93a41e-d13e-4f12-83cb-70d69bb3c0fb" x="0" y="442" width="572" height="1"/>
</line>
<staticText>
<reportElement uuid="548c1550-c12d-42b3-a297-c9be96dbb2e8" x="144" y="76" width="31" height="20">
<printWhenExpression><![CDATA[$F{requireDownPayment}]]></printWhenExpression>
</reportElement>
<textElement/>
<text><![CDATA[Ano]]></text>
</staticText>
<staticText>
<reportElement uuid="e06aba6d-b74d-4ab1-9737-1134a6ac6519" x="144" y="76" width="32" height="20">
<printWhenExpression><![CDATA[$F{requireDownPayment} == null || $F{requireDownPayment} == false]]></printWhenExpression>
</reportElement>
<textElement/>
<text><![CDATA[Ne]]></text>
</staticText>
<textField pattern="###0.00;-###0.00" isBlankWhenNull="true">
<reportElement uuid="ac95738d-56c8-4ee2-8721-cad00e1b06e4" x="144" y="398" width="57" height="20"/>
<textElement textAlignment="Right"/>
<textFieldExpression><![CDATA[$F{downPayment}]]></textFieldExpression>
</textField>
<image onErrorType="Blank">
<reportElement uuid="954e517f-5d23-4166-b776-7c31b4409ddd" x="378" y="69" width="183" height="50">
<printWhenExpression><![CDATA[$P{P_USER_SIGNATURE} != null]]></printWhenExpression>
</reportElement>
<imageExpression><![CDATA[$P{P_USER_SIGNATURE}]]></imageExpression>
</image>
<textField pattern="dd. MM. yyyy" isBlankWhenNull="true">
<reportElement uuid="97daa8a7-dab0-4104-babb-c3889faac21a" x="301" y="399" width="77" height="20"/>
<textElement/>
<textFieldExpression><![CDATA[$P{P_PREV_APPROVE_DATE}]]></textFieldExpression>
<anchorNameExpression><![CDATA["SIGN_1"]]></anchorNameExpression>
</textField>
<image onErrorType="Blank">
<reportElement uuid="baf922bc-b6fb-4dbf-abc9-250f448baef3" x="378" y="368" width="183" height="50">
<printWhenExpression><![CDATA[$P{P_PREV_APPROVER_SIGNATURE} != null]]></printWhenExpression>
</reportElement>
<imageExpression><![CDATA[$P{P_PREV_APPROVER_SIGNATURE}]]></imageExpression>
</image>
<textField>
<reportElement uuid="16e5c4e2-a366-4eca-ad27-7db7fef6771c" x="186" y="27" width="375" height="20">
<printWhenExpression><![CDATA[$F{ownedBy.address} != null]]></printWhenExpression>
</reportElement>
<textElement/>
<textFieldExpression><![CDATA[$F{ownedBy.address}]]></textFieldExpression>
</textField>
<subreport>
<reportElement uuid="b8144a34-f2c4-4b5a-9f48-b74b5dc99e8c" x="143" y="265" width="428" height="20"/>
<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{passengers})]]></dataSourceExpression>
<subreportExpression><![CDATA[$P{SUBREPORT_DIR} + "tripRequirementPassengers.jasper"]]></subreportExpression>
</subreport>
<textField isBlankWhenNull="true">
<reportElement uuid="f8e2f8b5-373d-46fd-9c61-5a6c1da44351" x="143" y="285" width="428" height="20"/>
<textElement/>
<textFieldExpression><![CDATA[$F{foreignPersons}]]></textFieldExpression>
</textField>
<genericElement>
<reportElement uuid="c1d18650-66b9-425c-acbe-7b4e952bfd16" x="442" y="460" width="119" height="48"/>
<genericElementType namespace="urn:sig:sig" name="signature"/>
</genericElement>
</band>
</detail>
</jasperReport>
Binary file not shown.
@@ -456,6 +456,8 @@
<bean id="tripBillApprovalService" class="info.bukova.isspst.services.tripbill.TripBillApprovalServiceImpl">
<property name="dao" ref="tripBillApprovalDao"/>
</bean>
<bean id="jnlpGenerator" class="info.bukova.isspst.signapi.JnlpGeneratorImpl"/>
<bean id="signedDocumentService" class="info.bukova.isspst.services.signeddocs.SignedDocumentServiceImpl">
<property name="dao" ref="signedDocumentDao"/>
+7 -2
View File
@@ -17,15 +17,20 @@
<label value="${labels.RequirementApproveDate}"/>
<datebox
value="@bind(vm.approveDate)"
format="${labels.DateFormat}" />
format="${labels.DateFormat}" disabled="@load(vm.signed)"/>
</hbox>
<separator bar="true" hflex="1"/>
<hbox>
<button image="/img/approve-016.png" label="${labels.Confirm}" onClick="@command('approve', window=approveWin)" sclass="nicebutton"/>
<button label="Podepsat" onClick="@command('signPdf')" sclass="nicebutton" disabled="@load(vm.signed)"/>
<button image="/img/approve-016.png" label="${labels.Confirm}" onClick="@command('approve', window=approveWin)" sclass="nicebutton" disabled="@load(not vm.signed)"/>
<button image="~./zul/img/misc/drag-disallow.png" label="${labels.ButtonStorno}" onClick="approveWin.detach()" sclass="nicebutton"/>
</hbox>
</vbox>
<timer onTimer="@command('onTimer')" running="@load(vm.timer)" repeats="true" delay="500"/>
<iframe name="signer" width="5px" height="5px"/>
</window>
</zk>