add and remove work times
This commit is contained in:
		| @@ -32,6 +32,10 @@ public class DoneBean implements Serializable, Comparable<DoneBean> { | ||||
| 	private TModuleRecord module; | ||||
| 	private TJobRecord activity; | ||||
| 	private TBillingRecord billing; | ||||
| 	private Integer fkProject; | ||||
| 	private Integer fkModule; | ||||
| 	private Integer fkJob; | ||||
| 	private Integer fkBilling; | ||||
|  | ||||
| 	public DoneBean() { | ||||
| 	} | ||||
| @@ -45,8 +49,12 @@ public class DoneBean implements Serializable, Comparable<DoneBean> { | ||||
| 		this.module = moduleMap.get(r.getFkModule()); | ||||
| 		this.activity = jobMap.get(r.getFkJob()); | ||||
| 		this.billing = billingMap.get(r.getFkBilling()); | ||||
| 		this.fkProject = project.getPk(); | ||||
| 		this.fkModule = module.getPk(); | ||||
| 		this.fkJob = activity.getPk(); | ||||
| 		this.fkBilling = billing.getPk(); | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	@Override | ||||
| 	public final String toString() { | ||||
| 		StringBuilder buf = new StringBuilder("DoneBean{"); | ||||
| @@ -105,6 +113,22 @@ public class DoneBean implements Serializable, Comparable<DoneBean> { | ||||
| 		return String.format("%02d:%02d", diff.toHours(), diff.toMinutes() % 60); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * try to find out what date this entry is for; if not found, use the current | ||||
| 	 * date | ||||
| 	 *  | ||||
| 	 * @return a local date | ||||
| 	 */ | ||||
| 	public LocalDate getLocalDate() { | ||||
| 		if (timeFrom != null) { | ||||
| 			return timeFrom.toLocalDate(); | ||||
| 		} else if (timeUntil != null) { | ||||
| 			return timeUntil.toLocalDate(); | ||||
| 		} else { | ||||
| 			return LocalDate.now(); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * get local date time from s | ||||
| 	 *  | ||||
| @@ -146,15 +170,15 @@ public class DoneBean implements Serializable, Comparable<DoneBean> { | ||||
| 	public String getJobName() { | ||||
| 		return activity == null ? "" : activity.getName(); | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	public String getBillingName() { | ||||
| 		return billing == null ? "" : billing.getName(); | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	public String getBillingShortcut() { | ||||
| 		return billing == null ? "" : billing.getShortcut(); | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	public String getBillingCsskey() { | ||||
| 		return billing == null ? "" : billing.getCsskey(); | ||||
| 	} | ||||
| @@ -205,6 +229,7 @@ public class DoneBean implements Serializable, Comparable<DoneBean> { | ||||
|  | ||||
| 	public void setProject(TProjectRecord project) { | ||||
| 		this.project = project; | ||||
| 		this.fkProject = project != null ? project.getPk() : null; | ||||
| 	} | ||||
|  | ||||
| 	public TModuleRecord getModule() { | ||||
| @@ -213,6 +238,7 @@ public class DoneBean implements Serializable, Comparable<DoneBean> { | ||||
|  | ||||
| 	public void setModule(TModuleRecord module) { | ||||
| 		this.module = module; | ||||
| 		this.fkModule = module != null ? module.getPk() : null; | ||||
| 	} | ||||
|  | ||||
| 	public TJobRecord getActivity() { | ||||
| @@ -221,6 +247,7 @@ public class DoneBean implements Serializable, Comparable<DoneBean> { | ||||
|  | ||||
| 	public void setActivity(TJobRecord activity) { | ||||
| 		this.activity = activity; | ||||
| 		this.fkJob = activity != null ? activity.getPk() : null; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| @@ -235,5 +262,62 @@ public class DoneBean implements Serializable, Comparable<DoneBean> { | ||||
| 	 */ | ||||
| 	public void setBilling(TBillingRecord billing) { | ||||
| 		this.billing = billing; | ||||
| 		this.fkBilling = billing != null ? billing.getPk() : null; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the fkProject | ||||
| 	 */ | ||||
| 	public Integer getFkProject() { | ||||
| 		return fkProject; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param fkProject the fkProject to set | ||||
| 	 */ | ||||
| 	public void setFkProject(Integer fkProject) { | ||||
| 		this.fkProject = fkProject; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the fkModule | ||||
| 	 */ | ||||
| 	public Integer getFkModule() { | ||||
| 		return fkModule; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param fkModule the fkModule to set | ||||
| 	 */ | ||||
| 	public void setFkModule(Integer fkModule) { | ||||
| 		this.fkModule = fkModule; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the fkJob | ||||
| 	 */ | ||||
| 	public Integer getFkJob() { | ||||
| 		return fkJob; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param fkJob the fkJob to set | ||||
| 	 */ | ||||
| 	public void setFkJob(Integer fkJob) { | ||||
| 		this.fkJob = fkJob; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the fkBilling | ||||
| 	 */ | ||||
| 	public Integer getFkBilling() { | ||||
| 		return fkBilling; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param fkBilling the fkBilling to set | ||||
| 	 */ | ||||
| 	public void setFkBilling(Integer fkBilling) { | ||||
| 		this.fkBilling = fkBilling; | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -63,8 +63,30 @@ public class DoneController { | ||||
| 			bean = new DoneBean(); // the add case | ||||
| 		} | ||||
| 		model.addAttribute("doneBean", bean); | ||||
| //		model.addAttribute("types", Arrays.asList(EnumNotetype.values())); | ||||
| //		model.addAttribute("categories", Arrays.asList(EnumCategory.values())); | ||||
| 		model.addAttribute("projectList", doneService.getProjects()); | ||||
| 		model.addAttribute("moduleList", doneService.getModules()); | ||||
| 		model.addAttribute("jobList", doneService.getJobs()); | ||||
| 		model.addAttribute("billingList", doneService.getBillings()); | ||||
| 		return "done/item"; | ||||
| 	} | ||||
| 	 | ||||
| 	@RolesAllowed("timetrack_user") | ||||
| 	@RequestMapping(value = "/done/upsert", method = RequestMethod.POST) | ||||
| 	public String doUpsert(Model model, @ModelAttribute DoneBean bean) { | ||||
| 		String username = doneService.getCurrentUser(request); | ||||
| 		Integer amount = doneService.doUpsert(bean, username); | ||||
| 		DoneModel doneModel = new DoneModel(); | ||||
| 		doneModel.setDay(bean.getLocalDate()); | ||||
| 		return amount.equals(1) ? getList(doneModel, model) : toItem(bean.getPk(), model); | ||||
| 	} | ||||
|  | ||||
| 	@RolesAllowed("timetrack_user") | ||||
| 	@GetMapping(value = "/done/delete/{id}") | ||||
| 	public String doDelete(@PathVariable Integer id, Model model) { | ||||
| 		DoneBean bean = doneService.getBean(id); | ||||
| 		Integer amount = doneService.doDelete(id); | ||||
| 		DoneModel doneModel = new DoneModel(); | ||||
| 		doneModel.setDay(bean.getLocalDate()); | ||||
| 		return amount.equals(1) ? getList(doneModel, model) : toItem(id, model); | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -29,4 +29,8 @@ public interface IDoneService { | ||||
| 	public List<TJobRecord> getJobs(); | ||||
|  | ||||
| 	public List<TBillingRecord> getBillings(); | ||||
|  | ||||
| 	public Integer doUpsert(DoneBean bean, String username); | ||||
|  | ||||
| 	public Integer doDelete(Integer id); | ||||
| } | ||||
|   | ||||
| @@ -19,9 +19,11 @@ import org.apache.logging.log4j.LogManager; | ||||
| import org.apache.logging.log4j.Logger; | ||||
| import org.jooq.DSLContext; | ||||
| import org.jooq.DeleteConditionStep; | ||||
| import org.jooq.InsertValuesStep7; | ||||
| import org.jooq.Record7; | ||||
| import org.jooq.Result; | ||||
| import org.jooq.SelectConditionStep; | ||||
| import org.jooq.UpdateConditionStep; | ||||
| import org.jooq.exception.DataAccessException; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.stereotype.Repository; | ||||
| @@ -51,7 +53,7 @@ public class DoneGateway { | ||||
| 	public DSLContext getJooq() { | ||||
| 		return this.jooq; | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	/** | ||||
| 	 * get the user id of the user with username | ||||
| 	 *  | ||||
| @@ -248,4 +250,82 @@ public class DoneGateway { | ||||
| 		LOGGER.debug("{}", sql.toString()); | ||||
| 		return sql.execute(); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * get the done bean of the pk | ||||
| 	 *  | ||||
| 	 * @param pk the ID of the data set | ||||
| 	 * @return the bean if found; null otherwise | ||||
| 	 * @throws SQLException | ||||
| 	 * @throws ClassNotFoundException | ||||
| 	 * @throws DataAccessException | ||||
| 	 */ | ||||
| 	public DoneBean getBean(Integer pk) throws DataAccessException, ClassNotFoundException, SQLException { | ||||
| 		SelectConditionStep<Record7<Integer, LocalDateTime, LocalDateTime, Integer, Integer, Integer, Integer>> sql = getJooq() | ||||
| 		// @formatter:off | ||||
| 			.select(T_DONE.PK, | ||||
| 							T_DONE.TIME_FROM, | ||||
| 							T_DONE.TIME_UNTIL, | ||||
| 							T_DONE.FK_PROJECT, | ||||
| 							T_DONE.FK_MODULE, | ||||
| 							T_DONE.FK_JOB, | ||||
| 							T_DONE.FK_BILLING) | ||||
| 			.from(T_DONE) | ||||
| 			.where(T_DONE.PK.eq(pk)); | ||||
| 		// @formatter:on | ||||
| 		LOGGER.debug("{}", sql.toString()); | ||||
| 		Map<Integer, TProjectRecord> projectMap = getProjectMap(); | ||||
| 		Map<Integer, TModuleRecord> moduleMap = getModuleMap(); | ||||
| 		Map<Integer, TJobRecord> jobMap = getJobMap(); | ||||
| 		Map<Integer, TBillingRecord> billingMap = getBillingMap(); | ||||
| 		for (Record7<Integer, LocalDateTime, LocalDateTime, Integer, Integer, Integer, Integer> r : sql.fetch()) { | ||||
| 			DoneBean bean = new DoneBean(); | ||||
| 			bean.setPk(r.get(T_DONE.PK)); | ||||
| 			bean.setTimeFrom(r.get(T_DONE.TIME_FROM)); | ||||
| 			bean.setTimeUntil(r.get(T_DONE.TIME_UNTIL)); | ||||
| 			bean.setProject(projectMap.get(r.get(T_DONE.FK_PROJECT))); | ||||
| 			bean.setModule(moduleMap.get(r.get(T_DONE.FK_MODULE))); | ||||
| 			bean.setActivity(jobMap.get(r.get(T_DONE.FK_JOB))); | ||||
| 			bean.setBilling(billingMap.get(r.get(T_DONE.FK_BILLING))); | ||||
| 			return (bean); | ||||
| 		} | ||||
| 		return (null); | ||||
| 	} | ||||
|  | ||||
| 	public Integer upsert(DoneBean bean, Integer userId) { | ||||
| 		return bean.getPk() != null ? update(bean) : insert(bean, userId); | ||||
| 	} | ||||
|  | ||||
| 	private Integer insert(DoneBean bean, Integer userId) { | ||||
| 		InsertValuesStep7<TDoneRecord, LocalDateTime, LocalDateTime, Integer, Integer, Integer, Integer, Integer> sql = getJooq() | ||||
| 		// @formatter:off | ||||
| 			.insertInto(T_DONE, | ||||
| 					        T_DONE.TIME_FROM, | ||||
| 					        T_DONE.TIME_UNTIL, | ||||
| 					        T_DONE.FK_PROJECT, | ||||
| 					        T_DONE.FK_MODULE, | ||||
| 					        T_DONE.FK_JOB, | ||||
| 					        T_DONE.FK_BILLING, | ||||
| 					        T_DONE.FK_LOGIN) | ||||
| 			.values(bean.getTimeFrom(), bean.getTimeUntil(), bean.getFkProject(), bean.getFkModule(), bean.getFkJob(), bean.getFkBilling(), userId); | ||||
| 		// @formatter:on | ||||
| 		LOGGER.debug(sql.toString()); | ||||
| 		return sql.execute(); | ||||
| 	} | ||||
|  | ||||
| 	private Integer update(DoneBean bean) { | ||||
| 		UpdateConditionStep<TDoneRecord> sql = getJooq() | ||||
| 		// @formatter:off | ||||
| 			.update(T_DONE) | ||||
| 			.set(T_DONE.TIME_FROM, bean.getTimeFrom()) | ||||
| 			.set(T_DONE.TIME_UNTIL, bean.getTimeUntil()) | ||||
| 			.set(T_DONE.FK_PROJECT, bean.getFkProject()) | ||||
| 			.set(T_DONE.FK_MODULE, bean.getFkModule()) | ||||
| 			.set(T_DONE.FK_JOB, bean.getFkJob()) | ||||
| 			.set(T_DONE.FK_BILLING, bean.getFkBilling()) | ||||
| 			.where(T_DONE.PK.eq(bean.getPk())); | ||||
| 		// @formatter:on | ||||
| 		LOGGER.debug(sql.toString()); | ||||
| 		return sql.execute(); | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -59,12 +59,16 @@ public class DoneService implements IDoneService { | ||||
|  | ||||
| 	@Override | ||||
| 	public DoneBean getBean(Integer id) { | ||||
| 		// TODO Auto-generated method stub | ||||
| 		return null; | ||||
| 		try { | ||||
| 			return new DoneGateway(dsl).getBean(id); | ||||
| 		} catch (Exception e) { | ||||
| 			LOGGER.error(e); | ||||
| 			return null; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	@Override | ||||
| 	public List<TProjectRecord> getProjects()	{ | ||||
| 	public List<TProjectRecord> getProjects() { | ||||
| 		try { | ||||
| 			return new DoneGateway(dsl).getAllProjects(); | ||||
| 		} catch (Exception e) { | ||||
| @@ -103,4 +107,26 @@ public class DoneService implements IDoneService { | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	@Override | ||||
| 	public Integer doUpsert(DoneBean bean, String username) { | ||||
| 		try { | ||||
| 			DoneGateway gw = new DoneGateway(dsl); | ||||
| 			Integer userId = gw.getUserId(username); | ||||
| 			return gw.upsert(bean, userId); | ||||
| 		} catch (Exception e) { | ||||
| 			LOGGER.error(e); | ||||
| 			return -1; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	@Override | ||||
| 	public Integer doDelete(Integer id) { | ||||
| 		try { | ||||
| 			return new DoneGateway(dsl).delete(id); | ||||
| 		} catch (Exception e) { | ||||
| 			LOGGER.error(e); | ||||
| 			return -1; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| } | ||||
|   | ||||
							
								
								
									
										72
									
								
								src/main/resources/templates/done/item.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								src/main/resources/templates/done/item.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,72 @@ | ||||
| <!DOCTYPE html> | ||||
| <html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" | ||||
| 	xmlns:sec="http://www.thymeleaf.org/extras/spring-security" layout:decorate="~{layout/main.html}"> | ||||
| <head> | ||||
| <title>Arbeitszeit aktualisieren</title> | ||||
| </head> | ||||
| <body> | ||||
| 	<ul layout:fragment="menu"> | ||||
| 	</ul> | ||||
| 	<main layout:fragment="content"> | ||||
| 		<div class="container formpane"> | ||||
| 			<form th:action="@{/done/upsert}" th:object="${doneBean}" method="post"> | ||||
| 				<div class="row mb-3"> | ||||
| 					<label for="inputPk" class="col-sm-2 col-form-label">Inhalt von Eintrag</label> | ||||
| 					<div class="col-sm-10"> | ||||
| 						<input id="inputPk" type="text" th:field="*{pk}" class="form-control" readonly="readonly" /> | ||||
| 					</div> | ||||
| 				</div> | ||||
| 				<div class="row mb-3"> | ||||
| 					<label for="inputTimefrom" class="col-sm-2 col-form-label">von</label> | ||||
| 					<div class="col-sm-10"> | ||||
| 						<input id="inputTimefrom" type="text" th:field="*{timeFromString}" class="form-control" /> | ||||
| 					</div> | ||||
| 				</div> | ||||
| 				<div class="row mb-3"> | ||||
| 					<label for="inputTimeuntil" class="col-sm-2 col-form-label">bis</label> | ||||
| 					<div class="col-sm-10"> | ||||
| 						<input id="inputTimeuntil" type="text" th:field="*{timeUntilString}" class="form-control" /> | ||||
| 					</div> | ||||
| 				</div> | ||||
| 				<div class="row mb-3"> | ||||
| 					<label for="inputProject" class="col-sm-2 col-form-label">Projekt</label> | ||||
| 					<select id="inputProject" class="form-control select2-single" th:field="*{fkProject}"> | ||||
| 						<option th:each="i : ${projectList}" th:value="${i.pk}" th:text="${i.name}"></option> | ||||
| 					</select> | ||||
| 				</div> | ||||
| 				<div class="row mb-3"> | ||||
| 					<label for="inputModule" class="col-sm-2 col-form-label">Modul</label> | ||||
| 					<select id="inputModule" class="form-control select2-single" th:field="*{fkModule}"> | ||||
| 						<option th:each="i : ${moduleList}" th:value="${i.pk}" th:text="${i.name}"></option> | ||||
| 					</select> | ||||
| 				</div> | ||||
| 				<div class="row mb-3"> | ||||
| 					<label for="inputJob" class="col-sm-2 col-form-label">Aufgabe</label> | ||||
| 					<select id="inputJob" class="form-control select2-single" th:field="*{fkJob}"> | ||||
| 						<option th:each="i : ${jobList}" th:value="${i.pk}" th:text="${i.name}"></option> | ||||
| 					</select> | ||||
| 				</div> | ||||
| 				<div class="row mb-3"> | ||||
| 					<label for="inputBilling" class="col-sm-2 col-form-label">Abrechnung</label> | ||||
| 					<select id="inputBilling" class="form-control select2-single" th:field="*{fkBilling}"> | ||||
| 						<option th:each="i : ${billingList}" th:value="${i.pk}" th:text="${i.name}"></option> | ||||
| 					</select> | ||||
| 				</div> | ||||
| 				<div class="row mb-3"> | ||||
| 					<div class="col-sm-2">Änderung</div> | ||||
| 					<div class="col-sm-10"> | ||||
| 						<button type="submit" class="btn btn-success">speichern</button> | ||||
| 						<button type="submit" class="btn btn-secondary" th:formaction="@{/done/list}">abbrechen</button> | ||||
| 						<div class="dropdown float-right" th:if="${doneBean.pk != null}" sec:authorize="hasRole('timetrack_user')"> | ||||
| 							<button class="btn btn-danger dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">Eintrag löschen</button> | ||||
| 							<ul class="dropdown-menu"> | ||||
| 								<li><a class="dropdown-item" th:href="@{/done/delete/{id}(id=${doneBean.pk})}">endgültig löschen</a></li> | ||||
| 							</ul> | ||||
| 						</div> | ||||
| 					</div> | ||||
| 				</div> | ||||
| 			</form> | ||||
| 		</div> | ||||
| 	</main> | ||||
| </body> | ||||
| </html> | ||||
| @@ -48,11 +48,11 @@ | ||||
| 					</thead> | ||||
| 					<tbody> | ||||
| 						<tr th:each="done : ${doneList}"> | ||||
| 							<td><span th:text="${#temporals.format(done.timeFrom, 'HH:mm')}"></span></td> | ||||
| 							<td><span th:text="${#temporals.format(done.timeUntil, 'HH:mm')}"></span></td> | ||||
| 							<td><span th:text="${done.project.name}"></span></td> | ||||
| 							<td><span th:text="${done.module.name}"></span></td> | ||||
| 							<td><span th:text="${done.activity.name}"></span></td> | ||||
| 							<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> | ||||
| 						</tr> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user