preparation for slot dimediff reason
This commit is contained in:
@ -212,4 +212,18 @@ public class DoneController extends CommonController {
|
|||||||
model.addAttribute("bean", SlotBean.of(day));
|
model.addAttribute("bean", SlotBean.of(day));
|
||||||
return "/done/slot/item";
|
return "/done/slot/item";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RolesAllowed("timetrack_user")
|
||||||
|
@PostMapping("/done/slot/upsert")
|
||||||
|
public String upsertSlot(@ModelAttribute("bean") SlotBean bean, Model model) {
|
||||||
|
doneService.upsert(bean, provider.getName());
|
||||||
|
return "redirect:/done/list";
|
||||||
|
}
|
||||||
|
|
||||||
|
@RolesAllowed("timetrack_user")
|
||||||
|
@GetMapping("/done/slot/{id}/delete")
|
||||||
|
public String deleteSlot(@PathVariable("id") Integer slotId) {
|
||||||
|
doneService.delete(slotId, provider.getName());
|
||||||
|
return "redirect:/done/list";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,9 @@ import org.apache.logging.log4j.LogManager;
|
|||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.jooq.DSLContext;
|
import org.jooq.DSLContext;
|
||||||
import org.jooq.DatePart;
|
import org.jooq.DatePart;
|
||||||
|
import org.jooq.DeleteConditionStep;
|
||||||
import org.jooq.Field;
|
import org.jooq.Field;
|
||||||
|
import org.jooq.InsertOnDuplicateSetMoreStep;
|
||||||
import org.jooq.InsertOnDuplicateStep;
|
import org.jooq.InsertOnDuplicateStep;
|
||||||
import org.jooq.Record1;
|
import org.jooq.Record1;
|
||||||
import org.jooq.Record3;
|
import org.jooq.Record3;
|
||||||
@ -32,6 +34,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
import de.jottyfan.timetrack.db.done.tables.records.TOvertimeRecord;
|
import de.jottyfan.timetrack.db.done.tables.records.TOvertimeRecord;
|
||||||
|
import de.jottyfan.timetrack.db.done.tables.records.TRequiredWorktimeRecord;
|
||||||
import de.jottyfan.timetrack.modules.done.model.DaysumBean;
|
import de.jottyfan.timetrack.modules.done.model.DaysumBean;
|
||||||
import de.jottyfan.timetrack.modules.done.model.OvertimeBean;
|
import de.jottyfan.timetrack.modules.done.model.OvertimeBean;
|
||||||
import de.jottyfan.timetrack.modules.done.model.SlotBean;
|
import de.jottyfan.timetrack.modules.done.model.SlotBean;
|
||||||
@ -161,6 +164,7 @@ public class DoneRepository {
|
|||||||
// @formatter:off
|
// @formatter:off
|
||||||
.select(T_REQUIRED_WORKTIME.PK_REQUIRED_WORKTIME,
|
.select(T_REQUIRED_WORKTIME.PK_REQUIRED_WORKTIME,
|
||||||
T_REQUIRED_WORKTIME.DAY,
|
T_REQUIRED_WORKTIME.DAY,
|
||||||
|
// T_REQUIRED_WORKTIME.REASON,
|
||||||
T_REQUIRED_WORKTIME.REQUIRED_MINUTES)
|
T_REQUIRED_WORKTIME.REQUIRED_MINUTES)
|
||||||
.from(T_REQUIRED_WORKTIME)
|
.from(T_REQUIRED_WORKTIME)
|
||||||
.innerJoin(T_LOGIN).on(T_LOGIN.PK.eq(T_REQUIRED_WORKTIME.FK_LOGIN))
|
.innerJoin(T_LOGIN).on(T_LOGIN.PK.eq(T_REQUIRED_WORKTIME.FK_LOGIN))
|
||||||
@ -177,7 +181,8 @@ public class DoneRepository {
|
|||||||
LocalDate day = n.get(T_REQUIRED_WORKTIME.DAY);
|
LocalDate day = n.get(T_REQUIRED_WORKTIME.DAY);
|
||||||
Integer pk = n.get(T_REQUIRED_WORKTIME.PK_REQUIRED_WORKTIME);
|
Integer pk = n.get(T_REQUIRED_WORKTIME.PK_REQUIRED_WORKTIME);
|
||||||
Integer minutes = n.get(T_REQUIRED_WORKTIME.REQUIRED_MINUTES);
|
Integer minutes = n.get(T_REQUIRED_WORKTIME.REQUIRED_MINUTES);
|
||||||
map.put(day, SlotBean.of(pk, day, minutes));
|
String reason = null; // n.get(T_REQUIRED_WORKTIME.REASON);
|
||||||
|
map.put(day, SlotBean.of(pk, day, minutes, reason));
|
||||||
}
|
}
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
@ -194,6 +199,7 @@ public class DoneRepository {
|
|||||||
// @formatter:off
|
// @formatter:off
|
||||||
.select(T_REQUIRED_WORKTIME.PK_REQUIRED_WORKTIME,
|
.select(T_REQUIRED_WORKTIME.PK_REQUIRED_WORKTIME,
|
||||||
T_REQUIRED_WORKTIME.DAY,
|
T_REQUIRED_WORKTIME.DAY,
|
||||||
|
// T_REQUIRED_WORKTIME.REASON,
|
||||||
T_REQUIRED_WORKTIME.REQUIRED_MINUTES)
|
T_REQUIRED_WORKTIME.REQUIRED_MINUTES)
|
||||||
.from(T_REQUIRED_WORKTIME)
|
.from(T_REQUIRED_WORKTIME)
|
||||||
.innerJoin(T_LOGIN).on(T_LOGIN.PK.eq(T_REQUIRED_WORKTIME.FK_LOGIN))
|
.innerJoin(T_LOGIN).on(T_LOGIN.PK.eq(T_REQUIRED_WORKTIME.FK_LOGIN))
|
||||||
@ -204,6 +210,57 @@ public class DoneRepository {
|
|||||||
Record3<Integer, LocalDate, Integer> r = sql.fetchOne();
|
Record3<Integer, LocalDate, Integer> r = sql.fetchOne();
|
||||||
return r == null ? null
|
return r == null ? null
|
||||||
: SlotBean.of(r.get(T_REQUIRED_WORKTIME.PK_REQUIRED_WORKTIME), r.get(T_REQUIRED_WORKTIME.DAY),
|
: SlotBean.of(r.get(T_REQUIRED_WORKTIME.PK_REQUIRED_WORKTIME), r.get(T_REQUIRED_WORKTIME.DAY),
|
||||||
r.get(T_REQUIRED_WORKTIME.REQUIRED_MINUTES));
|
r.get(T_REQUIRED_WORKTIME.REQUIRED_MINUTES), null/*r.get(T_REQUIRED_WORKTIME.REASON)*/);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addSlot(SlotBean bean, String login) {
|
||||||
|
InsertOnDuplicateSetMoreStep<TRequiredWorktimeRecord> sql = jooq
|
||||||
|
// @formatter:off
|
||||||
|
.insertInto(T_REQUIRED_WORKTIME,
|
||||||
|
T_REQUIRED_WORKTIME.DAY,
|
||||||
|
T_REQUIRED_WORKTIME.REQUIRED_MINUTES,
|
||||||
|
// T_REQUIRED_WORKTIME.REASON,
|
||||||
|
T_REQUIRED_WORKTIME.FK_LOGIN)
|
||||||
|
.select(jooq
|
||||||
|
.select(DSL.val(bean.getDay()), DSL.val(bean.getMinutes()), /* DSL.val(bean.getReason()), */ T_LOGIN.PK)
|
||||||
|
.from(T_LOGIN)
|
||||||
|
.where(T_LOGIN.LOGIN.eq(login)))
|
||||||
|
.onConflict(T_REQUIRED_WORKTIME.FK_LOGIN, T_REQUIRED_WORKTIME.DAY)
|
||||||
|
.doUpdate()
|
||||||
|
.set(T_REQUIRED_WORKTIME.REQUIRED_MINUTES, bean.getMinutes());
|
||||||
|
// .set(T_REQUIRED_WORKTIME.REASON, bean.getReason());
|
||||||
|
// @formatter:off
|
||||||
|
LOGGER.trace(sql);
|
||||||
|
sql.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateSlot(SlotBean bean, String login) {
|
||||||
|
UpdateConditionStep<TRequiredWorktimeRecord> sql = jooq
|
||||||
|
// @formatter:off
|
||||||
|
.update(T_REQUIRED_WORKTIME)
|
||||||
|
.set(T_REQUIRED_WORKTIME.REQUIRED_MINUTES, bean.getMinutes())
|
||||||
|
// .set(T_REQUIRED_WORKTIME.REASON, bean.getReason())
|
||||||
|
.where(T_REQUIRED_WORKTIME.PK_REQUIRED_WORKTIME.eq(bean.getId()))
|
||||||
|
.and(T_REQUIRED_WORKTIME.FK_LOGIN.in(jooq
|
||||||
|
.select(T_LOGIN.PK)
|
||||||
|
.from(T_LOGIN)
|
||||||
|
.where(T_LOGIN.LOGIN.eq(login))));
|
||||||
|
// @formatter:on
|
||||||
|
LOGGER.trace(sql);
|
||||||
|
sql.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteSlot(Integer id, String login) {
|
||||||
|
DeleteConditionStep<TRequiredWorktimeRecord> sql = jooq
|
||||||
|
// @formatter:off
|
||||||
|
.deleteFrom(T_REQUIRED_WORKTIME)
|
||||||
|
.where(T_REQUIRED_WORKTIME.PK_REQUIRED_WORKTIME.eq(id))
|
||||||
|
.and(T_REQUIRED_WORKTIME.FK_LOGIN.in(jooq
|
||||||
|
.select(T_LOGIN.PK)
|
||||||
|
.from(T_LOGIN)
|
||||||
|
.where(T_LOGIN.LOGIN.eq(login))));
|
||||||
|
// @formatter:on
|
||||||
|
LOGGER.trace(sql);
|
||||||
|
sql.execute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -287,4 +287,22 @@ public class DoneService {
|
|||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* upsert the bean
|
||||||
|
*
|
||||||
|
* @param bean the bean
|
||||||
|
* @param username the username
|
||||||
|
*/
|
||||||
|
public void upsert(SlotBean bean, String username) {
|
||||||
|
if (bean.getId() == null) {
|
||||||
|
repository.addSlot(bean, username);
|
||||||
|
} else {
|
||||||
|
repository.updateSlot(bean, username);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void delete(Integer slotId, String username) {
|
||||||
|
repository.deleteSlot(slotId, username);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,8 @@ package de.jottyfan.timetrack.modules.done.model;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
|
|
||||||
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author jotty
|
* @author jotty
|
||||||
@ -12,14 +14,17 @@ public class SlotBean implements Serializable {
|
|||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
private Integer id;
|
private Integer id;
|
||||||
|
@DateTimeFormat(pattern="yyyy-MM-dd")
|
||||||
private LocalDate day;
|
private LocalDate day;
|
||||||
private Integer minutes;
|
private Integer minutes;
|
||||||
|
private String reason;
|
||||||
|
|
||||||
public static final SlotBean of(Integer id, LocalDate day, Integer minutes) {
|
public static final SlotBean of(Integer id, LocalDate day, Integer minutes, String reason) {
|
||||||
SlotBean bean = new SlotBean();
|
SlotBean bean = new SlotBean();
|
||||||
bean.setId(id);
|
bean.setId(id);
|
||||||
bean.setDay(day);
|
bean.setDay(day);
|
||||||
bean.setMinutes(minutes);
|
bean.setMinutes(minutes);
|
||||||
|
bean.setReason(reason);
|
||||||
return bean;
|
return bean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,4 +85,18 @@ public class SlotBean implements Serializable {
|
|||||||
public void setId(Integer id) {
|
public void setId(Integer id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the reason
|
||||||
|
*/
|
||||||
|
public String getReason() {
|
||||||
|
return reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param reason the reason to set
|
||||||
|
*/
|
||||||
|
public void setReason(String reason) {
|
||||||
|
this.reason = reason;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -449,6 +449,14 @@ body {
|
|||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.slot_reason {
|
||||||
|
color: #26a269;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-bs-theme=dark] .slot_reason {
|
||||||
|
color: lime;
|
||||||
|
}
|
||||||
|
|
||||||
.flex-row-weekday {
|
.flex-row-weekday {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: row wrap;
|
flex-flow: row wrap;
|
||||||
|
@ -265,8 +265,27 @@
|
|||||||
</a><a th:href="@{/done/slot/add?day={d}(d=${s.day})}" class="slot_badge_middle" th:unless="${s.id}">
|
</a><a th:href="@{/done/slot/add?day={d}(d=${s.day})}" class="slot_badge_middle" th:unless="${s.id}">
|
||||||
<i class="fas fa-plus"></i>
|
<i class="fas fa-plus"></i>
|
||||||
</a>
|
</a>
|
||||||
<span class="slot_badge_right boldy" th:text="${s.printTime()}" th:if="${s.id}"></span>
|
<span class="slot_badge_middle slot_reason" th:if="${s.reason}" th:text="${s.reason}"></span><span class="slot_badge_right boldy" th:text="${s.printTime()}" th:if="${s.id}"></span><span
|
||||||
<span class="slot_badge_right" th:unless="${s.id}"> --:-- </span>
|
class="slot_badge_right" th:unless="${s.id}"> --:-- </span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row alert alert-info">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<span style="text-decoration: underline">Legende</span>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
Üb: Überstunden, Mehrarbeit<br />
|
||||||
|
Ur: Urlaub, Sonderurlaub, Kur<br />
|
||||||
|
gF: gesetzlicher Feiertag<br />
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
Kr: Arbeits- und Dienstunfähigkeit<br />
|
||||||
|
Gl: Freistellung aus Gleitzeitguthaben<br />
|
||||||
|
Ar: Arbeits- und Dienstbefreiung<br />
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
mK: "mit Kind krank"<br />
|
||||||
|
Di: Dienstreise, Dienstgänge<br />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
<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}">
|
||||||
xmlns:sec="http://www.thymeleaf.org/extras/spring-security" layout:decorate="~{layout/main.html}">
|
|
||||||
<head>
|
<head>
|
||||||
<title>Slot aktualisieren</title>
|
<title>Slot aktualisieren</title>
|
||||||
</head>
|
</head>
|
||||||
@ -12,16 +11,57 @@
|
|||||||
</ul>
|
</ul>
|
||||||
<main layout:fragment="content">
|
<main layout:fragment="content">
|
||||||
<div class="container formpane">
|
<div class="container formpane">
|
||||||
<div class="row" th:if="${bean}">
|
<form th:action="@{/done/slot/upsert}" method="post" th:object="${bean}">
|
||||||
<div class="col-sm-3">ID</div>
|
<input type="hidden" th:field="*{id}" />
|
||||||
<div class="col-sm-9" th:text="${bean.id}"></div>
|
<div class="row g-2" th:if="${bean}">
|
||||||
<div class="col-sm-3">Tag</div>
|
<div class="col-sm-3">Tag</div>
|
||||||
<div class="col-sm-9" th:text="${#temporals.format(bean.day, 'EEEE, dd.MM.yyyy')}"></div>
|
<div class="col-sm-9">
|
||||||
<div class="col-sm-3">vereinbarte Arbeitszeit</div>
|
<input type="date" th:field="*{day}" class="form-control" />
|
||||||
<div class="col-sm-9" th:text="${bean.printTime()}"></div>
|
</div>
|
||||||
|
<div class="col-sm-3">vereinbarte Arbeitszeit in Minuten</div>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input type="number" th:field="*{minutes}" class="form-control">
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">Abweichungsgrund</div>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<select th:field="*{reason}" class="form-select">
|
||||||
|
<option value="">-</option>
|
||||||
|
<option value="Ar">Arbeits- und Dienstbefreiung</option>
|
||||||
|
<option value="Di">Dienstreise, Dienstgänge</option>
|
||||||
|
<option value="gF">gesetzlicher Feiertag</option>
|
||||||
|
<option value="Gl">Freistellung aus Gleitzeitguthaben</option>
|
||||||
|
<option value="Kr">Arbeits- und Dienstunfähigkeit</option>
|
||||||
|
<option value="mK">"mit Kind krank"</option>
|
||||||
|
<option value="Ur">Urlaub, Sonderurlaub, Kur</option>
|
||||||
|
<option value="Üb">Überstunden, Mehrarbeit</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3"></div>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<button type="submit" class="btn btn-outline-primary">Übernehmen</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="container formpane" th:if="${bean.id}">
|
||||||
|
<button type="button" class="btn btn-outline-danger" data-bs-toggle="modal" data-bs-target="#deleteModal">Slot löschen</button>
|
||||||
|
<div class="modal fade" id="deleteModal" tabindex="-1" aria-labelledby="deleteModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h1 class="modal-title fs-5" id="deleteModalLabel">Slot löschen</h1>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Schließen"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body text-danger">
|
||||||
|
Wollen Sie die angegebene Arbeitszeit von <span th:text="${bean.printTime()}"></span> vom Tag <span th:text="${#temporals.format(bean.day, 'dd.MM.yyyy')}"></span> wirklich löschen?
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<a th:href="@{/done/slot/{id}/delete(id=${bean.id})}" class="btn btn-outline-danger">Ja</a>
|
||||||
|
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Nein</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
TODO: Löschen<br />
|
|
||||||
TODO: Ersetzen durch Dienstbefreiung, Urlaub, Ausgleichstag/Überstunden, Krankheit oder sonstwas
|
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</body>
|
</body>
|
||||||
|
Reference in New Issue
Block a user