further processing
This commit is contained in:
		| @@ -106,6 +106,24 @@ public class DoneBean implements Serializable, Comparable<DoneBean> { | ||||
| 		return o == null || timeFrom == null || o.getTimeFrom() == null ? 0 : timeFrom.compareTo(o.getTimeFrom()); | ||||
| 	} | ||||
|  | ||||
| 	public String getTimeNote() { | ||||
| 		LocalDateTime earlier = timeFrom != null ? timeFrom : LocalDateTime.now(); | ||||
| 		LocalDateTime later = timeUntil != null ? timeUntil : LocalDateTime.now(); | ||||
| 		StringBuilder buf = new StringBuilder(); | ||||
| 		if (timeFrom == null) { | ||||
| 			buf.append("     "); | ||||
| 		} else { | ||||
| 			buf.append(String.format("%02d:%02d", earlier.getHour(), earlier.getMinute() % 60)); | ||||
| 		} | ||||
| 		buf.append(" - "); | ||||
| 		if (timeUntil == null) { | ||||
| 			buf.append("     "); | ||||
| 		} else { | ||||
| 			buf.append(String.format("%02d:%02d", later.getHour(), later.getMinute() % 60)); | ||||
| 		} | ||||
| 		return buf.toString(); | ||||
| 	} | ||||
|  | ||||
| 	public String getTimeDiff() { | ||||
| 		LocalDateTime earlier = timeFrom != null ? timeFrom : LocalDateTime.now(); | ||||
| 		LocalDateTime later = timeUntil != null ? timeUntil : LocalDateTime.now(); | ||||
|   | ||||
| @@ -42,6 +42,7 @@ public class DoneController { | ||||
| 		List<DoneBean> list = doneService.getList(doneModel.getDay(), username); | ||||
| 		model.addAttribute("doneList", list); | ||||
| 		model.addAttribute("doneModel", doneModel); | ||||
| 		model.addAttribute("sum", new SummaryBean(list)); | ||||
| 		model.addAttribute("projectList", doneService.getProjects()); | ||||
| 		model.addAttribute("moduleList", doneService.getModules()); | ||||
| 		model.addAttribute("jobList", doneService.getJobs()); | ||||
|   | ||||
| @@ -0,0 +1,69 @@ | ||||
| package de.jottyfan.timetrack.spring.done; | ||||
|  | ||||
| import java.io.Serializable; | ||||
| import java.time.LocalDateTime; | ||||
| import java.util.List; | ||||
|  | ||||
| /** | ||||
|  *  | ||||
|  * @author henkej | ||||
|  * | ||||
|  */ | ||||
| public class SummaryBean implements Serializable { | ||||
| 	private static final long serialVersionUID = 1L; | ||||
|  | ||||
| 	private final List<DoneBean> list; | ||||
| 	 | ||||
| 	public SummaryBean(List<DoneBean> list) { | ||||
| 		this.list = list; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the start | ||||
| 	 */ | ||||
| 	public String getStart() { | ||||
| 		LocalDateTime found = LocalDateTime.now(); | ||||
| 		for (DoneBean bean : list) { | ||||
| 			LocalDateTime ldt = bean.getTimeFrom(); | ||||
| 			if (ldt != null && ldt.isBefore(found)) { | ||||
| 				found = ldt; | ||||
| 			} | ||||
| 		} | ||||
| 		return String.format("%02d:%02d", found.getHour(), found.getMinute() % 60); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the end | ||||
| 	 */ | ||||
| 	public String getEnd() { | ||||
| 		LocalDateTime found = LocalDateTime.now(); | ||||
| 		for (DoneBean bean : list) { | ||||
| 			LocalDateTime ldt = bean.getTimeUntil(); | ||||
| 			if (ldt != null && found.isBefore(ldt)) { | ||||
| 				found = ldt; | ||||
| 			} | ||||
| 		} | ||||
| 		return String.format("%02d:%02d", found.getHour(), found.getMinute() % 60); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the total | ||||
| 	 */ | ||||
| 	public String getTotal() { | ||||
| 		return "TODO"; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the pause | ||||
| 	 */ | ||||
| 	public String getPause() { | ||||
| 		return "TODO"; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the overdue | ||||
| 	 */ | ||||
| 	public String getOverdue() { | ||||
| 		return "TODO"; | ||||
| 	} | ||||
| } | ||||
| @@ -68,53 +68,81 @@ public class DoneGateway { | ||||
| 	/** | ||||
| 	 * get all projects from the database | ||||
| 	 *  | ||||
| 	 * @param includeNull if true, add a null value at the beginning of the result | ||||
| 	 *  | ||||
| 	 * @return a list of found projects | ||||
| 	 *  | ||||
| 	 * @throws DataAccessException | ||||
| 	 * @throws ClassNotFoundException | ||||
| 	 * @throws SQLException | ||||
| 	 */ | ||||
| 	public List<TProjectRecord> getAllProjects() throws DataAccessException, ClassNotFoundException, SQLException { | ||||
| 		return getJooq().selectFrom(T_PROJECT).orderBy(T_PROJECT.NAME).fetchInto(TProjectRecord.class); | ||||
| 	public List<TProjectRecord> getAllProjects(boolean includeNull) throws DataAccessException, ClassNotFoundException, SQLException { | ||||
| 		List<TProjectRecord> list = new ArrayList<>(); | ||||
| 		if (includeNull) { | ||||
| 			list.add(new TProjectRecord(null, null, "---")); | ||||
| 		} | ||||
| 		list.addAll(getJooq().selectFrom(T_PROJECT).orderBy(T_PROJECT.NAME).fetchInto(TProjectRecord.class)); | ||||
| 		return list; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * get all modules from the database | ||||
| 	 *  | ||||
| 	 * @param includeNull if true, add a null value at the beginning of the result | ||||
| 	 *  | ||||
| 	 * @return a list of found modules | ||||
| 	 *  | ||||
| 	 * @throws DataAccessException | ||||
| 	 * @throws ClassNotFoundException | ||||
| 	 * @throws SQLException | ||||
| 	 */ | ||||
| 	public List<TModuleRecord> getAllModules() throws DataAccessException, ClassNotFoundException, SQLException { | ||||
| 		return getJooq().selectFrom(T_MODULE).orderBy(T_MODULE.NAME).fetchInto(TModuleRecord.class); | ||||
| 	public List<TModuleRecord> getAllModules(boolean includeNull) throws DataAccessException, ClassNotFoundException, SQLException { | ||||
| 		List<TModuleRecord> list = new ArrayList<>(); | ||||
| 		if (includeNull) { | ||||
| 			list.add(new TModuleRecord(null, null, "---")); | ||||
| 		} | ||||
| 		list.addAll(getJooq().selectFrom(T_MODULE).orderBy(T_MODULE.NAME).fetchInto(TModuleRecord.class)); | ||||
| 		return list; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * get all jobs from the database | ||||
| 	 *  | ||||
| 	 * @param includeNull if true, add a null value at the beginning of the result | ||||
| 	 *  | ||||
| 	 * @return a list of found jobs | ||||
| 	 *  | ||||
| 	 * @throws DataAccessException | ||||
| 	 * @throws ClassNotFoundException | ||||
| 	 * @throws SQLException | ||||
| 	 */ | ||||
| 	public List<TJobRecord> getAllJobs() throws DataAccessException, ClassNotFoundException, SQLException { | ||||
| 		return getJooq().selectFrom(T_JOB).orderBy(T_JOB.NAME).fetchInto(TJobRecord.class); | ||||
| 	public List<TJobRecord> getAllJobs(boolean includeNull) throws DataAccessException, ClassNotFoundException, SQLException { | ||||
| 		List<TJobRecord> list = new ArrayList<>(); | ||||
| 		if (includeNull) { | ||||
| 			list.add(new TJobRecord(null, null, "---")); | ||||
| 		} | ||||
| 		list.addAll(getJooq().selectFrom(T_JOB).orderBy(T_JOB.NAME).fetchInto(TJobRecord.class)); | ||||
| 		return list; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * get all billings from the database | ||||
| 	 *  | ||||
| 	 * @param includeNull if true, add a null value at the beginning of the result | ||||
| 	 *  | ||||
| 	 * @return a list of found billings | ||||
| 	 *  | ||||
| 	 * @throws DataAccessException | ||||
| 	 * @throws ClassNotFoundException | ||||
| 	 * @throws SQLException | ||||
| 	 */ | ||||
| 	public List<TBillingRecord> getAllBillings() throws DataAccessException, ClassNotFoundException, SQLException { | ||||
| 		return getJooq().selectFrom(T_BILLING).orderBy(T_BILLING.NAME).fetchInto(TBillingRecord.class); | ||||
| 	public List<TBillingRecord> getAllBillings(boolean includeNull) throws DataAccessException, ClassNotFoundException, SQLException { | ||||
| 		List<TBillingRecord> list = new ArrayList<>(); | ||||
| 		if (includeNull) { | ||||
| 			list.add(new TBillingRecord(null, null, "---", null, null)); | ||||
| 		} | ||||
| 		list.addAll(getJooq().selectFrom(T_BILLING).orderBy(T_BILLING.NAME).fetchInto(TBillingRecord.class)); | ||||
| 		return list; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| @@ -128,7 +156,7 @@ public class DoneGateway { | ||||
| 	private Map<Integer, TProjectRecord> getProjectMap() | ||||
| 			throws DataAccessException, ClassNotFoundException, SQLException { | ||||
| 		Map<Integer, TProjectRecord> map = new HashMap<>(); | ||||
| 		for (TProjectRecord r : getAllProjects()) { | ||||
| 		for (TProjectRecord r : getAllProjects(false)) { | ||||
| 			map.put(r.getPk(), r); | ||||
| 		} | ||||
| 		return map; | ||||
| @@ -144,7 +172,7 @@ public class DoneGateway { | ||||
| 	 */ | ||||
| 	private Map<Integer, TModuleRecord> getModuleMap() throws DataAccessException, ClassNotFoundException, SQLException { | ||||
| 		Map<Integer, TModuleRecord> map = new HashMap<>(); | ||||
| 		for (TModuleRecord r : getAllModules()) { | ||||
| 		for (TModuleRecord r : getAllModules(false)) { | ||||
| 			map.put(r.getPk(), r); | ||||
| 		} | ||||
| 		return map; | ||||
| @@ -160,7 +188,7 @@ public class DoneGateway { | ||||
| 	 */ | ||||
| 	private Map<Integer, TJobRecord> getJobMap() throws DataAccessException, ClassNotFoundException, SQLException { | ||||
| 		Map<Integer, TJobRecord> map = new HashMap<>(); | ||||
| 		for (TJobRecord r : getAllJobs()) { | ||||
| 		for (TJobRecord r : getAllJobs(false)) { | ||||
| 			map.put(r.getPk(), r); | ||||
| 		} | ||||
| 		return map; | ||||
| @@ -177,7 +205,7 @@ public class DoneGateway { | ||||
| 	private Map<Integer, TBillingRecord> getBillingMap() | ||||
| 			throws DataAccessException, ClassNotFoundException, SQLException { | ||||
| 		Map<Integer, TBillingRecord> map = new HashMap<>(); | ||||
| 		for (TBillingRecord r : getAllBillings()) { | ||||
| 		for (TBillingRecord r : getAllBillings(false)) { | ||||
| 			map.put(r.getPk(), r); | ||||
| 		} | ||||
| 		return map; | ||||
| @@ -207,8 +235,8 @@ public class DoneGateway { | ||||
| 							T_DONE.FK_JOB, | ||||
| 							T_DONE.FK_BILLING) | ||||
| 			.from(T_DONE) | ||||
| 			.where(T_DONE.TIME_FROM.between(dayStart, dayEnd)) | ||||
| 			.and(T_DONE.TIME_UNTIL.between(dayStart, dayEnd)) | ||||
| 			.where(T_DONE.TIME_FROM.between(dayStart, dayEnd).or(T_DONE.TIME_FROM.isNull())) | ||||
| 			.and(T_DONE.TIME_UNTIL.between(dayStart, dayEnd).or(T_DONE.TIME_UNTIL.isNull())) | ||||
| 			.and(T_DONE.FK_LOGIN.eq(userId == null ? -999999 : userId)); | ||||
| 		// @formatter:on | ||||
| 		LOGGER.debug("{}", sql.toString()); | ||||
|   | ||||
| @@ -70,7 +70,7 @@ public class DoneService implements IDoneService { | ||||
| 	@Override | ||||
| 	public List<TProjectRecord> getProjects() { | ||||
| 		try { | ||||
| 			return new DoneGateway(dsl).getAllProjects(); | ||||
| 			return new DoneGateway(dsl).getAllProjects(true); | ||||
| 		} catch (Exception e) { | ||||
| 			LOGGER.error(e); | ||||
| 			return new ArrayList<>(); | ||||
| @@ -80,7 +80,7 @@ public class DoneService implements IDoneService { | ||||
| 	@Override | ||||
| 	public List<TModuleRecord> getModules() { | ||||
| 		try { | ||||
| 			return new DoneGateway(dsl).getAllModules(); | ||||
| 			return new DoneGateway(dsl).getAllModules(true); | ||||
| 		} catch (Exception e) { | ||||
| 			LOGGER.error(e); | ||||
| 			return new ArrayList<>(); | ||||
| @@ -90,7 +90,7 @@ public class DoneService implements IDoneService { | ||||
| 	@Override | ||||
| 	public List<TJobRecord> getJobs() { | ||||
| 		try { | ||||
| 			return new DoneGateway(dsl).getAllJobs(); | ||||
| 			return new DoneGateway(dsl).getAllJobs(true); | ||||
| 		} catch (Exception e) { | ||||
| 			LOGGER.error(e); | ||||
| 			return new ArrayList<>(); | ||||
| @@ -100,7 +100,7 @@ public class DoneService implements IDoneService { | ||||
| 	@Override | ||||
| 	public List<TBillingRecord> getBillings() { | ||||
| 		try { | ||||
| 			return new DoneGateway(dsl).getAllBillings(); | ||||
| 			return new DoneGateway(dsl).getAllBillings(true); | ||||
| 		} catch (Exception e) { | ||||
| 			LOGGER.error(e); | ||||
| 			return new ArrayList<>(); | ||||
|   | ||||
| @@ -163,3 +163,57 @@ body { | ||||
| .fc-content { | ||||
|   cursor: pointer; | ||||
| } | ||||
|  | ||||
| .btn-white-text { | ||||
| 	color: white !important; | ||||
| 	font-weight: bolder; | ||||
| } | ||||
|  | ||||
| .hoverlink { | ||||
| 	text-decoration: none; | ||||
| 	color: black; | ||||
| } | ||||
|  | ||||
| .hoverlink:hover { | ||||
| 	color: #1a5f64; | ||||
| } | ||||
|  | ||||
| .boldtext { | ||||
| 	font-weight: bolder; | ||||
| } | ||||
|  | ||||
| .emphgreen { | ||||
| 	font-weight: bolder; | ||||
| 	color: #136600; | ||||
| 	border: 1px solid gray; | ||||
| 	border-radius: 8px; | ||||
| 	background-image: linear-gradient(to left, #e6e6e6, white); | ||||
| 	padding: 4px; | ||||
| } | ||||
|  | ||||
| .emphblue { | ||||
| 	font-weight: bolder; | ||||
| 	color: #1a5fb4; | ||||
| 	border: 1px solid gray; | ||||
| 	border-radius: 8px; | ||||
| 	background-image: linear-gradient(to left, #e6e6e6, white); | ||||
| 	padding: 4px; | ||||
| } | ||||
|  | ||||
| .emphorange { | ||||
| 	font-weight: bolder; | ||||
| 	color: #c64600; | ||||
| 	border: 1px solid gray; | ||||
| 	border-radius: 8px; | ||||
| 	background-image: linear-gradient(to left, #e6e6e6, white); | ||||
| 	padding: 4px; | ||||
| } | ||||
|  | ||||
| .emphred { | ||||
| 	font-weight: bolder; | ||||
| 	color: #a51d2d; | ||||
| 	border: 1px solid gray; | ||||
| 	border-radius: 8px; | ||||
| 	background-image: linear-gradient(to left, #e6e6e6, white); | ||||
| 	padding: 4px; | ||||
| } | ||||
| @@ -7,7 +7,7 @@ | ||||
| <body> | ||||
| 	<font layout:fragment="title">Kontakte</font> | ||||
| 	<ul layout:fragment="menu"> | ||||
| 		<li class="nav-item" sec:authorize="hasRole('timetrack_user')"><a class="nav-link" th:href="@{/contact/add}">Neuen | ||||
| 		<li class="nav-item" sec:authorize="hasRole('timetrack_user')"><a class="nav-link btn btn-success btn-white-text" th:href="@{/contact/add}">Neuen | ||||
| 				Kontakt anlegen</a></li> | ||||
| 	</ul> | ||||
| 	<main layout:fragment="content"> | ||||
|   | ||||
| @@ -9,7 +9,7 @@ | ||||
| 	<ul layout:fragment="menuitem"> | ||||
| 		<li class="nav-item" sec:authorize="hasRole('timetrack_user')"> | ||||
| 			<form th:action="@{/done/list}" th:object="${doneModel}" method="post"> | ||||
| 				<div class="nav-link" style="padding-top: 0px !important"> | ||||
| 				<div class="nav-link" style="padding-top: 5px !important; padding-bottom: 0px !important"> | ||||
| 					<div class="input-group input-group-sm mb-3" style="margin-bottom: 0px !important"> | ||||
| 						<input type="date" class="form-control" th:value="*{day}" th:field="*{day}" /> | ||||
| 						<button type="submit" class="btn btn-primary btn-sm">Ok</button> | ||||
| @@ -19,7 +19,7 @@ | ||||
| 		</li> | ||||
| 	</ul> | ||||
| 	<ul layout:fragment="menu"> | ||||
| 		<li class="nav-item" sec:authorize="hasRole('timetrack_user')"><a class="nav-link" th:href="@{/done/add}">Neuer | ||||
| 		<li class="nav-item" sec:authorize="hasRole('timetrack_user')"><a class="nav-link btn btn-success btn-white-text" th:href="@{/done/add}">Neuer | ||||
| 				Eintrag</a></li> | ||||
| 	</ul> | ||||
| 	<main layout:fragment="content"> | ||||
| @@ -38,25 +38,36 @@ | ||||
| 				<table class="table table-striped table-condensed"> | ||||
| 					<thead> | ||||
| 						<tr> | ||||
| 							<th>Von</th> | ||||
| 							<th>Bis</th> | ||||
| 							<th>Zeit</th> | ||||
| 							<th>Projekt</th> | ||||
| 							<th>Modul</th> | ||||
| 							<th>Aufgabe</th> | ||||
| 							<th>Abrechnung</th> | ||||
| 							<th>Dauer</th> | ||||
| 							<th></th> | ||||
| 						</tr> | ||||
| 					</thead> | ||||
| 					<tbody> | ||||
| 						<tr th:each="done : ${doneList}"> | ||||
| 							<td><a th:href="@{/done/edit/{id}(id=${done.pk})}"><span th:text="${#temporals.format(done.timeFrom, 'HH:mm')}"></span></a></td> | ||||
| 							<td><a th:href="@{/done/edit/{id}(id=${done.pk})}"><span th:text="${#temporals.format(done.timeUntil, 'HH:mm')}"></span></a></td> | ||||
| 							<td><a th:href="@{/done/edit/{id}(id=${done.pk})}"><span th:text="${done.project.name}"></span></a></td> | ||||
| 							<td><a th:href="@{/done/edit/{id}(id=${done.pk})}"><span th:text="${done.module.name}"></span></a></td> | ||||
| 							<td><a th:href="@{/done/edit/{id}(id=${done.pk})}"><span th:text="${done.activity.name}"></span></a></td> | ||||
| 							<td><span th:text="${done.billing.shortcut}" th:class="'billing ' + ${done.billing.csskey}" | ||||
| 								th:if="${done.billing != null}"></span></td> | ||||
| 							<td><a class="hoverlink" th:href="@{/done/edit/{id}(id=${done.pk})}"><span th:text="${done.timeNote}"></span></a></td> | ||||
| 							<td><a class="hoverlink" th:href="@{/done/edit/{id}(id=${done.pk})}"><span class="boldtext" th:text="${done.project?.name}"></span></a></td> | ||||
| 							<td><a class="hoverlink" th:href="@{/done/edit/{id}(id=${done.pk})}"><span class="boldtext" th:text="${done.module?.name}"></span></a></td> | ||||
| 							<td><a class="hoverlink" th:href="@{/done/edit/{id}(id=${done.pk})}"><span class="boldtext" th:text="${done.activity?.name}"></span></a></td> | ||||
| 							<td><span th:text="${done.billing.shortcut}" th:class="'billing ' + ${done.billing.csskey}" th:if="${done.billing != null}"></span></td> | ||||
| 							<td><span th:text="${done.timeDiff}"></span></td> | ||||
| 							<td><a th:href="@{/done/edit/{id}(id=${done.pk})}" th:title="${done.pk}"><i class="fa fa-edit"></i></a></td> | ||||
| 						</tr> | ||||
| 					</tbody> | ||||
| 					<tfoot> | ||||
| 						<tr> | ||||
| 							<td>Zusammenfassung</td> | ||||
| 							<td>Start: <span class="emphgreen" th:text="${sum.start}"></span></td> | ||||
| 							<td>Ende: <span class="emphgreen" th:text="${sum.end}"></span></td> | ||||
| 							<td>Arbeitszeit total: <span class="emphblue" th:text="${sum.total}"></span></td> | ||||
| 							<td>Pausezeit total: <span class="emphorange" th:text="${sum.pause}"></span></td> | ||||
| 							<td>Überstunden: <span class="emphred" th:text="${sum.overdue}"></span></td> | ||||
| 						</tr> | ||||
| 					</tfoot> | ||||
| 				</table> | ||||
| 			</div> | ||||
| 			<div id="div_summary" class="tab-pane fade">Zusammenfassung</div> | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
| <body> | ||||
| 	<font layout:fragment="title">Notizen</font> | ||||
| 	<ul layout:fragment="menu"> | ||||
| 		<li class="nav-item" sec:authorize="hasRole('timetrack_user')"><a class="nav-link" th:href="@{/note/add}">Neue Notiz | ||||
| 		<li class="nav-item" sec:authorize="hasRole('timetrack_user')"><a class="nav-link btn btn-success btn-white-text" th:href="@{/note/add}">Neue Notiz | ||||
| 				anlegen</a></li> | ||||
| 	</ul> | ||||
| 	<main layout:fragment="content"> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user