download worktime summaries

This commit is contained in:
2019-09-25 13:05:17 +02:00
parent dbd3e42466
commit 7548ba6986
11 changed files with 349 additions and 21 deletions

View File

@ -0,0 +1,31 @@
package de.jottyfan.timetrack.help;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;
import javax.faces.convert.FacesConverter;
/**
*
* @author jotty
*
*/
@FacesConverter("de.jottyfan.timetrack.help.LocalDateConverter")
public class LocalDateConverter implements Converter<LocalDate> {
protected final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd.MM.yyyy");
@Override
public LocalDate getAsObject(FacesContext context, UIComponent component, String value) throws ConverterException {
return LocalDate.from(dtf.parse(value));
}
@Override
public String getAsString(FacesContext context, UIComponent component, LocalDate value) throws ConverterException {
return value.format(dtf);
}
}

View File

@ -51,6 +51,10 @@ public enum Pages
* done clear
*/
DONE_CLEAR("/pages/done/clear.jsf"),
/**
* done read
*/
DONE_READ("/pages/done/read.jsf"),
/**
* organize init
*/

View File

@ -57,6 +57,11 @@ public class DoneControl extends Navigation implements ControlInterface, Seriali
return navigateTo(Pages.DONE_DELETE);
}
public String toRead() {
boolean ready = model.prepareRead((JooqFacesContext) FacesContext.getCurrentInstance());
return ready ? navigateTo(Pages.DONE_READ) : toStart();
}
public String doUpdate() {
boolean ready = model.update((JooqFacesContext) FacesContext.getCurrentInstance());
return ready ? toList() : toEdit(model.getBean());
@ -71,6 +76,11 @@ public class DoneControl extends Navigation implements ControlInterface, Seriali
boolean ready = model.insert((JooqFacesContext) FacesContext.getCurrentInstance());
return ready ? toList() : toAdd();
}
public String doDownload() {
boolean ready = model.download((JooqFacesContext) FacesContext.getCurrentInstance());
return ready ? "" : "";
}
public String getCurrentTimeAsString() {
return new SimpleDateFormat("HH:mm:ss").format(getCurrentDate());

View File

@ -4,15 +4,17 @@ import static de.jottyfan.timetrack.db.done.Tables.T_DONE;
import static de.jottyfan.timetrack.db.done.Tables.T_JOB;
import static de.jottyfan.timetrack.db.done.Tables.T_MODULE;
import static de.jottyfan.timetrack.db.done.Tables.T_PROJECT;
import static de.jottyfan.timetrack.db.done.Tables.V_HAMSTERSUMMARY;
import static de.jottyfan.timetrack.db.done.Tables.V_TASKLIST;
import static de.jottyfan.timetrack.db.done.Tables.V_TOTALOFDAY;
import static de.jottyfan.timetrack.db.profile.Tables.T_LOGIN;
import java.sql.Date;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -23,9 +25,11 @@ import org.jooq.DSLContext;
import org.jooq.DeleteConditionStep;
import org.jooq.InsertValuesStep6;
import org.jooq.Record;
import org.jooq.Record3;
import org.jooq.Record4;
import org.jooq.Record5;
import org.jooq.SelectConditionStep;
import org.jooq.SelectJoinStep;
import org.jooq.SelectWhereStep;
import org.jooq.UpdateConditionStep;
import org.jooq.exception.DataAccessException;
@ -51,7 +55,7 @@ public class DoneGateway extends JooqGateway {
public DoneGateway(JooqFacesContext facesContext) {
super(facesContext);
String dailyMinutes = facesContext.getExternalContext().getInitParameter("requestedDailyMinutes");
this.requested = dailyMinutes == null ? 480 : Integer.valueOf(dailyMinutes); // defaults to 8 hours/day
this.requested = dailyMinutes == null ? 480 : Integer.valueOf(dailyMinutes); // defaults to 8 hours/day
}
/**
@ -259,11 +263,11 @@ public class DoneGateway extends JooqGateway {
* @param day
* the day
* @return the day summary if found, an empty map otherwise
* @throws SQLException
* @throws ClassNotFoundException
* @throws DataAccessException
* @throws SQLException
* @throws ClassNotFoundException
* @throws DataAccessException
*/
public WholeDaySummaryBean getDaySummary(Date day) throws DataAccessException, ClassNotFoundException, SQLException {
public WholeDaySummaryBean getDaySummary(java.util.Date day) throws DataAccessException, ClassNotFoundException, SQLException {
try (DSLContext jooq = getJooq()) {
SelectConditionStep<Record4<String, String, String, String>> sql = jooq
// @formatter:off
@ -298,7 +302,7 @@ public class DoneGateway extends JooqGateway {
* @throws ClassNotFoundException
* @throws DataAccessException
*/
public List<DailySummaryBean> getAllJobs(Date day) throws DataAccessException, ClassNotFoundException, SQLException {
public List<DailySummaryBean> getAllJobs(java.util.Date day) throws DataAccessException, ClassNotFoundException, SQLException {
try (DSLContext jooq = getJooq()) {
SelectConditionStep<Record4<String, String, String, String>> sql = jooq
// @formatter:off
@ -327,9 +331,9 @@ public class DoneGateway extends JooqGateway {
* get json representation of all calendar events of user
*
* @return
* @throws SQLException
* @throws ClassNotFoundException
* @throws DataAccessException
* @throws SQLException
* @throws ClassNotFoundException
* @throws DataAccessException
*/
public String getAllCalendarEvents() throws DataAccessException, ClassNotFoundException, SQLException {
try (DSLContext jooq = getJooq()) {
@ -352,8 +356,8 @@ public class DoneGateway extends JooqGateway {
String projectName = r.get(T_PROJECT.NAME);
String moduleName = r.get(T_MODULE.NAME);
String jobName = r.get(T_JOB.NAME);
Date timeFrom = r.get(T_DONE.TIME_FROM);
Date timeUntil = r.get(T_DONE.TIME_UNTIL);
java.util.Date timeFrom = r.get(T_DONE.TIME_FROM);
java.util.Date timeUntil = r.get(T_DONE.TIME_UNTIL);
StringBuilder buf = new StringBuilder();
buf.append(projectName);
@ -376,4 +380,55 @@ public class DoneGateway extends JooqGateway {
return list.toJson();
}
}
public List<UserBean> getAllUsers() throws DataAccessException, ClassNotFoundException, SQLException {
List<UserBean> list = new ArrayList<>();
try (DSLContext jooq = getJooq()) {
SelectJoinStep<Record3<String, String, String>> sql = jooq
// @formatter:off
.select(T_LOGIN.LOGIN,
T_LOGIN.FORENAME,
T_LOGIN.SURNAME)
.from(T_LOGIN);
// @formatter:on
LOGGER.debug(sql.toString());
for (Record r : sql.fetch()) {
String username = r.get(T_LOGIN.LOGIN);
String forename = r.get(T_LOGIN.FORENAME);
String surname = r.get(T_LOGIN.SURNAME);
list.add(new UserBean(username, forename, surname));
}
}
return list;
}
public String download(DownloadBean bean) throws DataAccessException, ClassNotFoundException, SQLException {
StringBuilder buf = new StringBuilder();
try (DSLContext jooq = getJooq()) {
SelectConditionStep<Record5<Date, String, String, String, String>> sql = jooq
// @formatter:off
.select(V_HAMSTERSUMMARY.WORKDAY,
V_HAMSTERSUMMARY.DURATION,
V_HAMSTERSUMMARY.PROJECT_NAME,
V_HAMSTERSUMMARY.MODULE_NAME,
V_HAMSTERSUMMARY.JOB_NAME)
.from(V_HAMSTERSUMMARY)
.where(V_HAMSTERSUMMARY.LOGIN.eq(bean.getUsername()))
.and(V_HAMSTERSUMMARY.WORKDAY.le(Date.valueOf(bean.getUntilDate()))
.and(V_HAMSTERSUMMARY.WORKDAY.ge(Date.valueOf(bean.getFromDate()))));
// @formatter:on
LOGGER.debug(sql.toString());
String sep = ";";
buf.append("day").append(sep).append("duration").append(sep).append("project").append(sep).append("module").append(sep).append("activity\n");
for (Record r : sql.fetch()) {
String date = new SimpleDateFormat("dd.MM.yyyy").format(r.get(V_HAMSTERSUMMARY.WORKDAY));
buf.append(date).append(sep);
buf.append(r.get(V_HAMSTERSUMMARY.DURATION)).append(sep);
buf.append(r.get(V_HAMSTERSUMMARY.PROJECT_NAME)).append(sep);
buf.append(r.get(V_HAMSTERSUMMARY.MODULE_NAME)).append(sep);
buf.append(r.get(V_HAMSTERSUMMARY.JOB_NAME)).append("\n");
}
}
return buf.toString();
}
}

View File

@ -1,8 +1,10 @@
package de.jottyfan.timetrack.modules.done;
import java.io.IOException;
import java.io.Serializable;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
@ -42,12 +44,14 @@ public class DoneModel implements Model, Serializable {
private List<TimeBean> times;
private List<DailySummaryBean> allJobs;
private WholeDaySummaryBean daySummary;
private Date day;
private java.util.Date day;
private String calendarEvents;
private List<UserBean> users;
private DownloadBean downloadBean;
public boolean init(JooqFacesContext facesContext) {
try {
day = day == null ? new Date() : day;
day = day == null ? new java.util.Date() : day;
beans = getAllOfDay(facesContext, day);
DoneGateway gw = new DoneGateway(facesContext);
modules = gw.getAllModules();
@ -74,6 +78,20 @@ public class DoneModel implements Model, Serializable {
}
}
public boolean prepareRead(JooqFacesContext facesContext) {
try {
users = new DoneGateway(facesContext).getAllUsers();
downloadBean = new DownloadBean();
downloadBean.setFromDate(LocalDate.of(LocalDate.now().getYear(), 1, 1));
downloadBean.setUntilDate(LocalDate.now());
return true;
} catch (DataAccessException | ClassNotFoundException | SQLException e) {
facesContext.addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_ERROR, "error loading defaults", e.getMessage()));
return false;
}
}
private void defineTimes() {
times = new ArrayList<>();
Integer currentHour = getCurrentTime().get(GregorianCalendar.HOUR_OF_DAY);
@ -127,10 +145,11 @@ public class DoneModel implements Model, Serializable {
* @param login
* the user to look up for
* @return all entries
* @throws SQLException
* @throws ClassNotFoundException
* @throws SQLException
* @throws ClassNotFoundException
*/
private List<DoneBean> getAllOfDay(JooqFacesContext facesContext, Date day) throws DataAccessException, ClassNotFoundException, SQLException {
private List<DoneBean> getAllOfDay(JooqFacesContext facesContext, Date day)
throws DataAccessException, ClassNotFoundException, SQLException {
LocalDateTime ldt = day.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
return new DoneGateway(facesContext).getAll(ldt);
}
@ -166,6 +185,21 @@ public class DoneModel implements Model, Serializable {
}
}
public boolean download(JooqFacesContext facesContext) {
try {
String csvContent = new DoneGateway(facesContext).download(downloadBean);
facesContext.getExternalContext().responseReset();
facesContext.getExternalContext().setResponseContentType("text/csv");
facesContext.getExternalContext().setResponseHeader("Content-Disposition", "attachment; filename=\"worktime.csv\"");
facesContext.getExternalContext().getResponseOutputWriter().append(csvContent);
facesContext.responseComplete();
return true;
} catch (DataAccessException | ClassNotFoundException | SQLException | IOException e) {
facesContext.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "error", e.getMessage()));
return false;
}
}
public String getAttach() {
StringBuilder buf = new StringBuilder();
String thatday = new SimpleDateFormat("dd.MM.yyyy").format(day);
@ -176,14 +210,14 @@ public class DoneModel implements Model, Serializable {
buf.append(sdb.getModuleName()).append("\t");
buf.append(sdb.getJobName()).append("\t");
buf.append("\n");
}
}
return buf.toString();
}
public String getDayIso8601() {
return day == null ? "" : new SimpleDateFormat("yyyy-MM-dd").format(day);
}
public void setBean(DoneBean bean) {
this.bean = bean;
}
@ -231,4 +265,18 @@ public class DoneModel implements Model, Serializable {
public String getCalendarEvents() {
return calendarEvents;
}
/**
* @return the users
*/
public List<UserBean> getUsers() {
return users;
}
/**
* @return the downloadBean
*/
public DownloadBean getDownloadBean() {
return downloadBean;
}
}

View File

@ -0,0 +1,61 @@
package de.jottyfan.timetrack.modules.done;
import java.io.Serializable;
import java.time.LocalDate;
/**
*
* @author jotty
*
*/
public class DownloadBean implements Serializable {
private static final long serialVersionUID = 1L;
private String username;
private LocalDate fromDate;
private LocalDate untilDate;
/**
* @return the fromDate
*/
public LocalDate getFromDate() {
return fromDate;
}
/**
* @param fromDate
* the fromDate to set
*/
public void setFromDate(LocalDate fromDate) {
this.fromDate = fromDate;
}
/**
* @return the untilDate
*/
public LocalDate getUntilDate() {
return untilDate;
}
/**
* @param untilDate
* the untilDate to set
*/
public void setUntilDate(LocalDate untilDate) {
this.untilDate = untilDate;
}
/**
* @return the username
*/
public String getUsername() {
return username;
}
/**
* @param username the username to set
*/
public void setUsername(String username) {
this.username = username;
}
}

View File

@ -0,0 +1,44 @@
package de.jottyfan.timetrack.modules.done;
import java.io.Serializable;
/**
*
* @author jotty
*
*/
public class UserBean implements Serializable {
private static final long serialVersionUID = 1L;
private final String username;
private final String forename;
private final String surname;
public UserBean(String username, String forename, String surname) {
super();
this.username = username;
this.forename = forename;
this.surname = surname;
}
/**
* @return the forename
*/
public String getForename() {
return forename;
}
/**
* @return the surname
*/
public String getSurname() {
return surname;
}
/**
* @return the username
*/
public String getUsername() {
return username;
}
}