Umožněn upload souborů k požadavkům na služební cesty a k vyúčtování služební cesty.

closes #131
This commit is contained in:
2015-03-03 14:46:21 +01:00
parent c6ebf8959b
commit ecd3cf426b
19 changed files with 240 additions and 113 deletions
@@ -1,12 +1,13 @@
package info.bukova.isspst.data;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.search.annotations.Analyze;
import org.hibernate.search.annotations.Field;
import org.hibernate.search.annotations.Index;
import org.hibernate.search.annotations.Indexed;
import org.hibernate.search.annotations.IndexedEmbedded;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
@@ -29,8 +30,9 @@ public class FileMetainfo extends BaseData {
@Column(name = "RECORD_ID")
private int recordId;
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "CONTENT_ID")
@Cascade(CascadeType.SAVE_UPDATE)
@IndexedEmbedded
private FileContent content;
@@ -1,9 +1,10 @@
package info.bukova.isspst.data;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import info.bukova.isspst.storage.EntityWithAttachment;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
import org.hibernate.search.annotations.Indexed;
import org.hibernate.search.annotations.IndexedEmbedded;
import javax.persistence.CascadeType;
import javax.persistence.Column;
@@ -13,16 +14,15 @@ import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
import org.hibernate.search.annotations.Indexed;
import org.hibernate.search.annotations.IndexedEmbedded;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Entity
@Table(name = "TRIP_BILL")
@Indexed
public class TripBill extends BaseData {
public class TripBill extends BaseData implements EntityWithAttachment {
@OneToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "REQUIREMENT_ID")
@@ -47,13 +47,14 @@ public class TripBill extends BaseData {
private BigDecimal downPayment;
@Column(name = "TOTAL", precision = 15, scale = 4)
private BigDecimal total;
@OneToMany
@OneToMany(cascade = CascadeType.ALL)
@LazyCollection(LazyCollectionOption.TRUE)
@IndexedEmbedded
private List<FileMetainfo> attachedFiles;
public TripBill() {
billItems = new ArrayList<TripBillItem>();
attachedFiles = new ArrayList<FileMetainfo>();
}
public TripRequirement getRequirement() {
@@ -132,6 +133,16 @@ public class TripBill extends BaseData {
return attachedFiles;
}
@Override
public void addAttachment(FileMetainfo metaInfo) {
attachedFiles.add(metaInfo);
}
@Override
public void removeAttachment(FileMetainfo metainfo) {
attachedFiles.remove(metainfo);
}
public void setAttachedFiles(List<FileMetainfo> attachedFiles) {
this.attachedFiles = attachedFiles;
}
@@ -1,7 +1,7 @@
package info.bukova.isspst.services;
import java.util.Date;
import info.bukova.isspst.data.OwnedDataModel;
import info.bukova.isspst.data.User;
import org.hibernate.NonUniqueResultException;
import org.hibernate.Query;
import org.springframework.security.access.prepost.PreAuthorize;
@@ -9,8 +9,7 @@ import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.transaction.annotation.Transactional;
import info.bukova.isspst.data.OwnedDataModel;
import info.bukova.isspst.data.User;
import java.util.Date;
public class AbstractOwnedService<T extends OwnedDataModel> extends AbstractService<T> {
@@ -32,6 +31,7 @@ public class AbstractOwnedService<T extends OwnedDataModel> extends AbstractServ
entity.setModifiedBy(getLoggedInUser());
entity.setModified(new Date());
dao.modify(entity);
maintainStorrage();
}
@Transactional
@@ -1,6 +1,5 @@
package info.bukova.isspst.services;
import static ch.lambdaj.Lambda.filter;
import info.bukova.isspst.Module;
import info.bukova.isspst.ModuleUtils;
import info.bukova.isspst.SessionData;
@@ -11,7 +10,15 @@ import info.bukova.isspst.data.NumberSeries;
import info.bukova.isspst.filters.Filter;
import info.bukova.isspst.reporting.Report;
import info.bukova.isspst.services.numberseries.NumberSeriesService;
import info.bukova.isspst.storage.DocumentFileStorage;
import org.hibernate.NonUniqueResultException;
import org.hibernate.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -20,14 +27,7 @@ import java.util.Date;
import java.util.List;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import org.hibernate.NonUniqueResultException;
import org.hibernate.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import static ch.lambdaj.Lambda.filter;
public abstract class AbstractService<T extends DataModel> implements Service<T> {
@@ -37,9 +37,14 @@ public abstract class AbstractService<T extends DataModel> implements Service<T>
protected SessionData sessionData;
@Autowired
protected QueryDao queryDao;
private DocumentFileStorage documentFileStorage;
private NumberSeriesService numberSeriesService;
public void setDocumentFileStorage(DocumentFileStorage storage) {
this.documentFileStorage = storage;
}
public NumberSeriesService getNumberSeriesService()
{
@@ -62,6 +67,12 @@ public abstract class AbstractService<T extends DataModel> implements Service<T>
public String getDeleteEntityPermission() {
return "";
}
protected void maintainStorrage() {
if (documentFileStorage != null) {
documentFileStorage.purge();
}
}
@Override
@PreAuthorize("hasPermission(this, 'PERM_ADD')")
@@ -101,6 +112,7 @@ public abstract class AbstractService<T extends DataModel> implements Service<T>
validate(entity);
entity.setModified(new Date());
dao.modify(entity);
maintainStorrage();
}
@Override
@@ -114,8 +126,10 @@ public abstract class AbstractService<T extends DataModel> implements Service<T>
if (getModule() != null && !getModule().isActive()) {
throw new ModuleNotActiveException();
}
dao.delete(entity);
maintainStorrage(); // poklidit přiložené soubory
}
@Override
@@ -7,13 +7,7 @@ import info.bukova.isspst.data.TripRequirement;
import info.bukova.isspst.services.AbstractOwnedService;
import info.bukova.isspst.services.LazyLoader;
import info.bukova.isspst.services.settings.GlobalSettingsService;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;
import org.hibernate.Hibernate;
import org.hibernate.LazyInitializationException;
import org.hibernate.Query;
import org.joda.time.DateTime;
@@ -24,6 +18,12 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;
public class TripBillServiceImpl extends AbstractOwnedService<TripBill> implements
TripBillService {
@@ -80,6 +80,14 @@ public class TripBillServiceImpl extends AbstractOwnedService<TripBill> implemen
}
}
@Transactional
@LazyLoader("form")
public void loadAttachments(TripBill entity) {
TripBill e = dao.getById(entity.getId());
Hibernate.initialize(e.getAttachedFiles());
entity.setAttachedFiles(e.getAttachedFiles());
}
@Override
public void calculate(TripBill bill) {
bill.setTotal(BigDecimal.ZERO);
@@ -61,6 +61,12 @@ public interface DocumentFileStorage extends FileStorage<FileMetainfo> {
*
* @param entity Entita s přílohami
*/
public void removaAllAttachments(EntityWithAttachment entity);
public void removeAllAttachments(EntityWithAttachment entity);
/**
* Uklidí soubory, na které neexistuje reference v databázi a z tabulky FILE_CONTENTS vymaže záznamy, na které
* neexistuje refernece z FILE_METAINFO
*/
public void purge();
}
@@ -6,6 +6,7 @@ import info.bukova.isspst.services.fulltext.Extractor;
import info.bukova.isspst.services.fulltext.ExtractorFactory;
import org.apache.commons.codec.binary.Hex;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
@@ -173,7 +174,7 @@ public class DocumentFileStorageImpl extends AbstractFileStorage<FileMetainfo> i
}
private List<FileMetainfo> infosForPath(String path) {
Query q = queryDao.getQuery("from FileMetainfo info where info.pathInFilesystem = :path");
Query q = queryDao.getQuery("from FileMetainfo info where info.content.pathInFilesystem = :path");
q.setString("path", path);
return q.list();
@@ -224,11 +225,37 @@ public class DocumentFileStorageImpl extends AbstractFileStorage<FileMetainfo> i
@Override
@Transactional
public void removaAllAttachments(EntityWithAttachment entity) {
public void removeAllAttachments(EntityWithAttachment entity) {
for (FileMetainfo metaInfo : entity.getAttachedFiles()) {
removeFile(metaInfo);
}
entity.getAttachedFiles().clear();
}
@Override
@Transactional
public void purge() {
File folder = new File(rootPath);
File[] allFiles = folder.listFiles();
Query q = queryDao.getQuery("from FileMetainfo");
List<FileMetainfo> infos = q.list();
for (File f : allFiles) {
boolean fileExists = false;
for (FileMetainfo info : infos) {
if (info.getContent().getPathInFilesystem().equals(f.getName())) {
fileExists = true;
}
}
if (!fileExists && f.isFile()) {
f.delete();
}
}
SQLQuery sql = queryDao.getSession().createSQLQuery("delete from file_contents where id not in(select CONTENT_ID from file_metainfo)");
sql.executeUpdate();
}
}
@@ -0,0 +1,72 @@
package info.bukova.isspst.ui;
import info.bukova.isspst.data.DataModel;
import info.bukova.isspst.data.FileMetainfo;
import info.bukova.isspst.storage.DocumentFileStorage;
import info.bukova.isspst.storage.EntityWithAttachment;
import org.zkoss.bind.annotation.BindingParam;
import org.zkoss.bind.annotation.Command;
import org.zkoss.bind.annotation.ContextParam;
import org.zkoss.bind.annotation.ContextType;
import org.zkoss.bind.annotation.Init;
import org.zkoss.bind.annotation.NotifyChange;
import org.zkoss.zk.ui.event.UploadEvent;
import org.zkoss.zk.ui.select.annotation.WireVariable;
import org.zkoss.zul.Filedownload;
import java.util.ArrayList;
import java.util.List;
/**
* @author Pepa Rokos
*/
public class FormWithUpload<T extends DataModel> extends FormViewModel<T> {
private List<FileMetainfo> attachments;
private List<FileMetainfo> forDelete;
@WireVariable
private DocumentFileStorage documentStorage;
@Init(superclass = true)
public void initFormWithUpload() {
if (getDataBean() instanceof EntityWithAttachment) {
attachments = ((EntityWithAttachment)getDataBean()).getAttachedFiles();
}
forDelete = new ArrayList<FileMetainfo>(); // kolekce příloh na smazání v případě uložení záznamu
}
@Command
@NotifyChange("attachments")
public void uploadAttachment(@ContextParam(ContextType.TRIGGER_EVENT) UploadEvent upEvent) {
FileMetainfo metaInfo = documentStorage.saveAndCreateInfo(upEvent.getMedia().getByteData(),
upEvent.getMedia().getName());
((EntityWithAttachment)getDataBean()).addAttachment(metaInfo);
}
@Command
@NotifyChange("attachments")
public void deleteAttachment(@BindingParam("attachment") FileMetainfo metaInfo) {
((EntityWithAttachment)getDataBean()).removeAttachment(metaInfo);
forDelete.add(metaInfo); // smazat až v případě uložení záznamu
}
@Command
public void downloadAttachment(@BindingParam("attachment") FileMetainfo metaInfo) {
Filedownload.save(documentStorage.fileData(metaInfo), metaInfo.getContentType(), metaInfo.getFileName());
}
public List<FileMetainfo> getAttachments() {
return attachments;
}
@Override
protected void doSave() {
for (FileMetainfo info : forDelete) {
documentStorage.removeFile(info);
}
super.doSave();
}
}
@@ -1,23 +1,26 @@
package info.bukova.isspst.ui.requirement;
import info.bukova.isspst.data.*;
import info.bukova.isspst.data.SettingsData;
import info.bukova.isspst.data.TripRequirement;
import info.bukova.isspst.data.User;
import info.bukova.isspst.data.Workgroup;
import info.bukova.isspst.services.requirement.RequirementTypeService;
import info.bukova.isspst.services.requirement.TripRequirementService;
import info.bukova.isspst.services.settings.GlobalSettingsService;
import info.bukova.isspst.services.users.UserService;
import info.bukova.isspst.services.workgroups.WorkgroupService;
import info.bukova.isspst.storage.DocumentFileStorage;
import info.bukova.isspst.ui.FormViewModel;
import info.bukova.isspst.ui.FormWithUpload;
import info.bukova.isspst.validators.TripRequirementFormValidator;
import org.zkoss.bind.annotation.*;
import org.zkoss.zk.ui.event.UploadEvent;
import org.zkoss.bind.annotation.BindingParam;
import org.zkoss.bind.annotation.Command;
import org.zkoss.bind.annotation.Init;
import org.zkoss.bind.annotation.NotifyChange;
import org.zkoss.zk.ui.select.annotation.WireVariable;
import org.zkoss.zul.Filedownload;
import java.util.ArrayList;
import java.util.List;
public class TripRequirementForm extends FormViewModel<TripRequirement> {
public class TripRequirementForm extends FormWithUpload<TripRequirement> {
@WireVariable
private UserService userService;
@@ -34,8 +37,6 @@ public class TripRequirementForm extends FormViewModel<TripRequirement> {
private List<Workgroup> centres;
private List<User> users;
private List<User> passengers;
private List<FileMetainfo> attachments;
private List<FileMetainfo> forDelete;
private User selUser;
private TripRequirementFormValidator validator;
@@ -45,8 +46,6 @@ public class TripRequirementForm extends FormViewModel<TripRequirement> {
centres = reqTypeService.filterCentres(getDataBean().getType(), workgroupService.getUserCentres(userService.getCurrent()));
users = userService.getUsersForCombo();
passengers = getDataBean().getPassengers();
attachments = getDataBean().getAttachedFiles();
forDelete = new ArrayList<FileMetainfo>(); // kolekce příloh na smazání v případě uložení záznamu
validator = new TripRequirementFormValidator();
}
@@ -90,37 +89,4 @@ public class TripRequirementForm extends FormViewModel<TripRequirement> {
return passengers;
}
@Command
@NotifyChange("attachments")
public void uploadAttachment(@ContextParam(ContextType.TRIGGER_EVENT) UploadEvent upEvent) {
FileMetainfo metaInfo = documentStorage.saveAndCreateInfo(upEvent.getMedia().getByteData(),
upEvent.getMedia().getName());
getDataBean().addAttachment(metaInfo);
}
@Command
@NotifyChange("attachments")
public void deleteAttachment(@BindingParam("attachment") FileMetainfo metaInfo) {
getDataBean().removeAttachment(metaInfo);
forDelete.add(metaInfo); // smazat až v případě uložení záznamu
}
@Command
public void downloadAttachment(@BindingParam("attachment") FileMetainfo metaInfo) {
Filedownload.save(documentStorage.fileData(metaInfo), metaInfo.getContentType(), metaInfo.getFileName());
}
public List<FileMetainfo> getAttachments() {
return attachments;
}
@Override
protected void doSave() {
for (FileMetainfo info : forDelete) {
documentStorage.removeFile(info);
}
super.doSave();
}
}
@@ -4,17 +4,16 @@ import info.bukova.isspst.data.TripBill;
import info.bukova.isspst.data.Vehicle;
import info.bukova.isspst.services.settings.GlobalSettingsService;
import info.bukova.isspst.services.tripbill.TripBillService;
import info.bukova.isspst.ui.FormViewModel;
import java.util.ArrayList;
import java.util.List;
import info.bukova.isspst.ui.FormWithUpload;
import org.zkoss.bind.annotation.Command;
import org.zkoss.bind.annotation.Init;
import org.zkoss.bind.annotation.NotifyChange;
import org.zkoss.zk.ui.select.annotation.WireVariable;
public class TripBillForm extends FormViewModel<TripBill> {
import java.util.ArrayList;
import java.util.List;
public class TripBillForm extends FormWithUpload<TripBill> {
@WireVariable
private TripBillService tripBillService;