added start_booking, see #14

This commit is contained in:
Jottyfan 2024-03-16 22:40:36 +01:00
parent ce819f80de
commit 03eb781a98
8 changed files with 101 additions and 43 deletions

View File

@ -8,7 +8,7 @@ plugins {
}
group = 'de.jottyfan.camporganizer'
version = '0.7.6'
version = '0.7.7'
description = """CampOrganizer2"""
@ -41,12 +41,12 @@ war {
}
dependencies {
implementation 'org.jooq:jooq:3.19.1'
implementation 'de.jottyfan:COJooq:2024.02.23'
implementation 'org.jooq:jooq:3.19.6'
implementation 'de.jottyfan:COJooq:2024.03.16c'
implementation 'org.apache.logging.log4j:log4j-api:2.22.0'
implementation 'org.apache.logging.log4j:log4j-core:2.22.0'
implementation 'org.apache.logging.log4j:log4j-to-slf4j:2.22.0'
implementation 'org.apache.logging.log4j:log4j-api:2.23.1'
implementation 'org.apache.logging.log4j:log4j-core:2.23.1'
implementation 'org.apache.logging.log4j:log4j-to-slf4j:2.23.1'
implementation 'org.webjars:bootstrap:5.3.2'
implementation 'org.webjars:font-awesome:6.5.1'
@ -58,8 +58,8 @@ dependencies {
implementation 'net.sf.biweekly:biweekly:0.6.7'
// for using the keycloak rest interface
implementation 'org.keycloak:keycloak-server-spi:23.0.3'
implementation 'org.keycloak:keycloak-admin-client:23.0.3'
implementation 'org.keycloak:keycloak-server-spi:24.0.1'
implementation 'org.keycloak:keycloak-admin-client:24.0.1'
implementation 'org.jboss.resteasy:resteasy-client:6.2.6.Final'
// backward compatibility until the complete registration is converted to keycloak

View File

@ -25,7 +25,7 @@ import org.jooq.DeleteConditionStep;
import org.jooq.Field;
import org.jooq.InsertResultStep;
import org.jooq.InsertReturningStep;
import org.jooq.InsertValuesStep15;
import org.jooq.InsertValuesStep16;
import org.jooq.InsertValuesStep3;
import org.jooq.Record4;
import org.jooq.Record5;
@ -435,10 +435,12 @@ public class AdminRepository {
jooq.transaction(t -> {
LocalDate arriveDate = bean.getArrive();
LocalDate departDate = bean.getDepart();
LocalDate startBookingDate = bean.getStartBooking();
LocalDateTime arrive = arriveDate == null ? null : arriveDate.atStartOfDay();
LocalDateTime depart = departDate == null ? null : departDate.atStartOfDay();
LocalDateTime startBooking = startBookingDate == null ? null : startBookingDate.atStartOfDay();
if (bean.getPk() == null) {
InsertValuesStep15<TCampRecord, LocalDateTime, String, LocalDateTime, Integer, Integer, Integer, Boolean, Integer, Integer, String, String, Integer, Integer, Integer, Integer> sql = DSL
InsertValuesStep16<TCampRecord, LocalDateTime, String, LocalDateTime, Integer, Integer, Integer, Boolean, Integer, Integer, String, String, Integer, Integer, Integer, Integer, LocalDateTime> sql = DSL
.using(t)
// @formatter:off
.insertInto(T_CAMP,
@ -456,10 +458,11 @@ public class AdminRepository {
T_CAMP.BEDS_FEMALE,
T_CAMP.BEDS_MALE,
T_CAMP.BLOCKED_BEDS_FEMALE,
T_CAMP.BLOCKED_BEDS_MALE)
T_CAMP.BLOCKED_BEDS_MALE,
T_CAMP.START_BOOKING)
.values(arrive, bean.getCountries(), depart, bean.getFkDocument(), bean.getFkLocation(), bean.getFkProfile(),
bean.getLockSales() != null ? bean.getLockSales() : false, bean.getMaxAge(), bean.getMinAge(), bean.getName(), bean.getPrice(),
bean.getBedsFemale(), bean.getBedsMale(), bean.getBlockedBedsFemale(), bean.getBlockedBedsMale());
bean.getBedsFemale(), bean.getBedsMale(), bean.getBlockedBedsFemale(), bean.getBlockedBedsMale(), startBooking);
// @formatter:on
LOGGER.debug(sql.toString());
sql.execute();
@ -482,6 +485,7 @@ public class AdminRepository {
.set(T_CAMP.BEDS_MALE, bean.getBedsMale())
.set(T_CAMP.BLOCKED_BEDS_FEMALE, bean.getBlockedBedsFemale())
.set(T_CAMP.BLOCKED_BEDS_MALE, bean.getBlockedBedsMale())
.set(T_CAMP.START_BOOKING, startBooking)
.where(T_CAMP.PK.eq(bean.getPk()));
// @formatter:on
LOGGER.debug(sql.toString());

View File

@ -57,6 +57,9 @@ public class CampBean implements Serializable {
@NotNull
@Min(value = 0)
private Integer blockedBedsMale;
@NotNull
@DateTimeFormat(pattern = "yyyy-MM-dd")
private LocalDate startBooking;
/**
* generate a camp bean out of r
@ -71,6 +74,7 @@ public class CampBean implements Serializable {
CampBean bean = new CampBean();
LocalDateTime arrive = r.getArrive();
LocalDateTime depart = r.getDepart();
LocalDateTime startBooking = r.getStartBooking();
bean.setArrive(arrive == null ? null : arrive.toLocalDate());
bean.setCountries(r.getCountries());
bean.setDepart(depart == null ? null : depart.toLocalDate());
@ -87,6 +91,7 @@ public class CampBean implements Serializable {
bean.setBedsMale(r.getBedsMale());
bean.setBlockedBedsFemale(r.getBlockedBedsFemale());
bean.setBlockedBedsMale(r.getBlockedBedsMale());
bean.setStartBooking(startBooking == null ? null : startBooking.toLocalDate());
return bean;
}
@ -344,4 +349,18 @@ public class CampBean implements Serializable {
public void setBlockedBedsMale(Integer blockedBedsMale) {
this.blockedBedsMale = blockedBedsMale;
}
/**
* @return the startBooking
*/
public LocalDate getStartBooking() {
return startBooking;
}
/**
* @param startBooking the startBooking to set
*/
public void setStartBooking(LocalDate startBooking) {
this.startBooking = startBooking;
}
}

View File

@ -6,6 +6,7 @@ import static de.jottyfan.camporganizer.db.jooq.Tables.T_PERSONDOCUMENT;
import static de.jottyfan.camporganizer.db.jooq.Tables.T_PROFILE;
import static de.jottyfan.camporganizer.db.jooq.Tables.T_PROFILEROLE;
import static de.jottyfan.camporganizer.db.jooq.Tables.T_RSS;
import static de.jottyfan.camporganizer.db.jooq.Tables.V_CAMP;
import java.time.LocalDate;
import java.time.LocalDateTime;
@ -42,11 +43,11 @@ import org.springframework.transaction.annotation.Transactional;
import de.jottyfan.camporganizer.db.jooq.enums.EnumCamprole;
import de.jottyfan.camporganizer.db.jooq.enums.EnumSex;
import de.jottyfan.camporganizer.db.jooq.tables.records.TCampRecord;
import de.jottyfan.camporganizer.db.jooq.tables.records.TPersonRecord;
import de.jottyfan.camporganizer.db.jooq.tables.records.TPersondocumentRecord;
import de.jottyfan.camporganizer.db.jooq.tables.records.TProfileRecord;
import de.jottyfan.camporganizer.db.jooq.tables.records.TRssRecord;
import de.jottyfan.camporganizer.db.jooq.tables.records.VCampRecord;
import de.jottyfan.camporganizer.module.camplist.model.BookingBean;
import de.jottyfan.camporganizer.module.camplist.model.LambdaResultWrapper;
import de.jottyfan.camporganizer.module.registration.model.CampBean;
@ -73,15 +74,17 @@ public class RegistrationRepository {
* @return the camp bean or null
*/
public CampBean getCamp(Integer pk) {
SelectConditionStep<TCampRecord> sql = jooq.selectFrom(T_CAMP).where(T_CAMP.PK.eq(pk));
SelectConditionStep<VCampRecord> sql = jooq.selectFrom(V_CAMP).where(V_CAMP.PK.eq(pk));
LOGGER.debug(sql.toString());
TCampRecord r = sql.fetchOne();
VCampRecord r = sql.fetchOne();
if (r != null) {
CampBean bean = new CampBean();
bean.setPk(r.getPk());
bean.setName(r.getName());
LocalDateTime arrive = r.getArrive();
bean.setYear(arrive == null ? null : arrive.getYear());
bean.setBookingHasStarted(r.getBookingHasStarted());
bean.setStartBooking(r.getStartBooking());
return bean;
} else {
return null;

View File

@ -1,6 +1,7 @@
package de.jottyfan.camporganizer.module.registration.model;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
*
@ -13,6 +14,8 @@ public class CampBean implements Serializable {
private Integer pk;
private String name;
private Integer year;
private LocalDateTime startBooking;
private Boolean bookingHasStarted;
/**
* @return the pk
@ -55,4 +58,32 @@ public class CampBean implements Serializable {
public void setYear(Integer year) {
this.year = year;
}
/**
* @return the bookingHasStarted
*/
public Boolean getBookingHasStarted() {
return bookingHasStarted;
}
/**
* @param bookingHasStarted the bookingHasStarted to set
*/
public void setBookingHasStarted(Boolean bookingHasStarted) {
this.bookingHasStarted = bookingHasStarted;
}
/**
* @return the startBooking
*/
public LocalDateTime getStartBooking() {
return startBooking;
}
/**
* @param startBooking the startBooking to set
*/
public void setStartBooking(LocalDateTime startBooking) {
this.startBooking = startBooking;
}
}

View File

@ -105,8 +105,8 @@
</div>
</div>
<div class="row mb-2">
<label for="inputProfile" class="col-sm-2 col-form-label">Verantwortlicher</label>
<div class="col-sm-10">
<label for="inputProfile" class="col-sm-2 col-form-label mb-2">Verantwortlicher</label>
<div class="col-sm-4 mb-2">
<span class="error" th:each="error : ${#fields.errors('fkProfile')}">[[${error}]]<br /></span> <select id="inputProfile" th:field="*{fkProfile}"
th:class="${'form-select ' + (#fields.hasErrors('fkProfile') ? 'inputerror' : '')}">
<option value="">--- bitte wählen ---</option>
@ -118,33 +118,26 @@
});
</script>
</div>
</div>
<div class="row mb-2">
<label for="inputBedsFemale" class="col-sm-2 col-form-label">Anzahl Betten für Mädchen</label>
<div class="col-sm-10">
<span class="error" th:each="error : ${#fields.errors('bedsFemale')}">[[${error}]]<br /></span>
<input type="number" class="form-control" th:field="*{bedsFemale}" />
<label for="startBooking" class="col-sm-2 col-form-label mb-2">Buchungsbeginn</label>
<div class="col-sm-4 mb-2">
<span class="error" th:each="error : ${#fields.errors('startBooking')}">[[${error}]]<br /></span> <input id="startBooking" type="date" th:field="*{startBooking}"
th:class="${'form-control ' + (#fields.hasErrors('startBooking') ? 'inputerror' : '')}" />
</div>
<label for="inputBedsFemale" class="col-sm-2 col-form-label mb-2">Anzahl Betten für Mädchen</label>
<div class="col-sm-4 mb-2">
<span class="error" th:each="error : ${#fields.errors('bedsFemale')}">[[${error}]]<br /></span> <input type="number" class="form-control" th:field="*{bedsFemale}" />
</div>
</div>
<div class="row mb-2">
<label for="inputBedsMale" class="col-sm-2 col-form-label">Anzahl Betten für Jungen</label>
<div class="col-sm-10">
<span class="error" th:each="error : ${#fields.errors('bedsMale')}">[[${error}]]<br /></span>
<input type="number" class="form-control" th:field="*{bedsMale}" />
<div class="col-sm-4">
<span class="error" th:each="error : ${#fields.errors('bedsMale')}">[[${error}]]<br /></span> <input type="number" class="form-control" th:field="*{bedsMale}" />
</div>
</div>
<div class="row mb-2">
<label for="inputBlockedBedsFemale" class="col-sm-2 col-form-label">Reservierte Betten für Mädchen</label>
<div class="col-sm-10">
<span class="error" th:each="error : ${#fields.errors('blockedBedsFemale')}">[[${error}]]<br /></span>
<input type="number" class="form-control" th:field="*{blockedBedsFemale}" />
<div class="col-sm-4">
<span class="error" th:each="error : ${#fields.errors('blockedBedsFemale')}">[[${error}]]<br /></span> <input type="number" class="form-control" th:field="*{blockedBedsFemale}" />
</div>
</div>
<div class="row mb-2">
<label for="inputBlockedBedsMale" class="col-sm-2 col-form-label">Reservierte Betten für Jungen</label>
<div class="col-sm-10">
<span class="error" th:each="error : ${#fields.errors('blockedBedsMale')}">[[${error}]]<br /></span>
<input type="number" class="form-control" th:field="*{blockedBedsMale}" />
<div class="col-sm-4">
<span class="error" th:each="error : ${#fields.errors('blockedBedsMale')}">[[${error}]]<br /></span> <input type="number" class="form-control" th:field="*{blockedBedsMale}" />
</div>
</div>
<div class="row mb-2">

View File

@ -37,7 +37,7 @@
</div>
</div>
</div>
<div class="row g-5" th:if="${c.bedsFemale + c.bedsMale > 0}">
<div class="row g-5" th:if="${c.bedsFemale + c.bedsMale > 0 and c.bookingHasStarted}">
<div class="col-2"><img th:src="@{/images/Icon_Bett.svg}" width="48px" height="48px" /></div>
<div class="col-10 d-flex align-items-center" th:text="${'es sind nur noch ' + (c.bedsFemale - c.blockedBedsFemale - c.usedBedsFemale) + ' Mädchen- und ' + (c.bedsMale - c.blockedBedsMale - c.usedBedsMale) + ' Jungs- von ' + (c.bedsFemale + c.bedsMale) + ' Betten frei'}"></div>
<div class="col-12 alert alert-info alert-dismissible fade show" role="alert">
@ -45,8 +45,13 @@
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Schließen"></button>
</div>
</div>
<div class="row g-5" th:unless="${c.bookingHasStarted}">
<div class="col-12 alert alert-info" role="alert">
Die Anmeldung wird erst am <span th:text="${#temporals.format(c.startBooking, 'dd.MM.yyyy')}"></span> freigeschaltet.
</div>
</div>
</div>
<div style="text-align: center; margin-top: 48px">
<div style="text-align: center; margin-top: 48px" th:if="${c.bookingHasStarted}">
<a class="btn btn-linda buttonfont" th:href="@{/registration/{id}(id=${c.pk})}">jetzt anmelden</a>
</div>
</div>

View File

@ -9,7 +9,10 @@
<div class="mainpage">
<h1 class="centered cabin">Anmeldung</h1>
<h3 class="centered cabin" th:text="'zur ' + ${camp.name} + ' ' + ${camp.year}"></h3>
<div class="card centered-card lindaborders" style="max-width: 48rem">
<div class="alert alert-warning" style="margin: auto; max-width: 450px" th:unless="${camp.bookingHasStarted}">
Die Anmeldung wird erst am <span th:text="${#temporals.format(camp.startBooking, 'dd.MM.yyyy')}"></span> freigeschaltet.
</div>
<div class="card centered-card lindaborders" style="max-width: 48rem" th:if="${camp.bookingHasStarted}">
<div class="card-body">
<h1 class="centered cabin">Teilnehmeranmeldung</h1>
<form th:action="@{/registration/register}" th:object="${bean}" method="post">