added required price, see #6

This commit is contained in:
Jottyfan 2024-02-23 15:36:37 +01:00
parent 72952b9c7b
commit e20c24d006
7 changed files with 88 additions and 6 deletions

View File

@ -8,7 +8,7 @@ plugins {
} }
group = 'de.jottyfan.camporganizer' group = 'de.jottyfan.camporganizer'
version = '0.7.0' version = '0.7.1'
description = """CampOrganizer2""" description = """CampOrganizer2"""
@ -89,6 +89,12 @@ dependencies {
testImplementation 'org.springframework.security:spring-security-test' testImplementation 'org.springframework.security:spring-security-test'
} }
configurations {
runtime {
exclude(group = "commons-logging", module = "commons-logging")
}
}
test { test {
useJUnitPlatform() useJUnitPlatform()
} }

View File

@ -3,6 +3,7 @@ package de.jottyfan.camporganizer.module.confirmation.person;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.Model; import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
@ -10,6 +11,7 @@ import org.springframework.web.bind.annotation.PostMapping;
import de.jottyfan.camporganizer.module.camplist.CommonController; import de.jottyfan.camporganizer.module.camplist.CommonController;
import de.jottyfan.camporganizer.module.confirmation.person.model.PersonBean; import de.jottyfan.camporganizer.module.confirmation.person.model.PersonBean;
import jakarta.validation.Valid;
/** /**
* *
@ -29,12 +31,20 @@ public class PersonController extends CommonController {
model.addAttribute("person", personService.getPerson(username, pk)); model.addAttribute("person", personService.getPerson(username, pk));
model.addAttribute("camps", personService.getCamps(username)); model.addAttribute("camps", personService.getCamps(username));
model.addAttribute("annotations", personService.getAnnotations(pk)); model.addAttribute("annotations", personService.getAnnotations(pk));
model.addAttribute("campPrice", personService.getCampPrice(pk));
return "confirmation/person"; return "confirmation/person";
} }
@PostMapping("/confirmation/person/update") @PostMapping("/confirmation/person/update")
public String doUpdate(@ModelAttribute("bean") PersonBean bean, Model model) { public String doUpdate(@Valid @ModelAttribute("person") PersonBean bean, BindingResult bindingResult, Model model) {
String username = super.getCurrentUser(); String username = super.getCurrentUser();
if (bindingResult.hasErrors()) {
model.addAttribute("currentUser", username);
model.addAttribute("camps", personService.getCamps(username));
model.addAttribute("annotations", personService.getAnnotations(bean.getPk()));
model.addAttribute("campPrice", personService.getCampPrice(bean.getPk()));
return "confirmation/person";
}
personService.updatePerson(bean, username); personService.updatePerson(bean, username);
return "redirect:/confirmation"; return "redirect:/confirmation";
} }

View File

@ -20,6 +20,7 @@ import org.apache.logging.log4j.Logger;
import org.jooq.DSLContext; import org.jooq.DSLContext;
import org.jooq.InsertValuesStep2; import org.jooq.InsertValuesStep2;
import org.jooq.Record; import org.jooq.Record;
import org.jooq.Record1;
import org.jooq.Record11; import org.jooq.Record11;
import org.jooq.Record4; import org.jooq.Record4;
import org.jooq.SelectConditionStep; import org.jooq.SelectConditionStep;
@ -133,6 +134,7 @@ public class PersonRepository {
bean.setSex(r.get(T_PERSON.SEX)); bean.setSex(r.get(T_PERSON.SEX));
bean.setStreet(r.get(T_PERSON.STREET)); bean.setStreet(r.get(T_PERSON.STREET));
bean.setZip(r.get(T_PERSON.ZIP)); bean.setZip(r.get(T_PERSON.ZIP));
bean.setRequiredPrice(r.get(T_PERSON.REQUIRED_PRICE));
return bean; return bean;
} }
return null; return null;
@ -187,6 +189,7 @@ public class PersonRepository {
.set(T_PERSON.ACCEPT, bean.getAccept()) .set(T_PERSON.ACCEPT, bean.getAccept())
.set(T_PERSON.CAMPROLE, bean.getCamprole()) .set(T_PERSON.CAMPROLE, bean.getCamprole())
.set(T_PERSON.FK_REGISTRATOR, fkRegistrator) .set(T_PERSON.FK_REGISTRATOR, fkRegistrator)
.set(T_PERSON.REQUIRED_PRICE, bean.getRequiredPrice())
.where(T_PERSON.PK.eq(bean.getPk())); .where(T_PERSON.PK.eq(bean.getPk()));
// @formatter:on // @formatter:on
LOGGER.debug(sql3.toString()); LOGGER.debug(sql3.toString());
@ -300,9 +303,11 @@ public class PersonRepository {
// @formatter:on // @formatter:on
LOGGER.debug(sql.toString()); LOGGER.debug(sql.toString());
StringBuilder buf = new StringBuilder(); StringBuilder buf = new StringBuilder();
Iterator<Record11<LocalDate, LocalDateTime, EnumCamprole, LocalDateTime, LocalDateTime, Integer, Integer, String, String, String, String>> i = sql.fetch().iterator(); Iterator<Record11<LocalDate, LocalDateTime, EnumCamprole, LocalDateTime, LocalDateTime, Integer, Integer, String, String, String, String>> i = sql
.fetch().iterator();
while (i.hasNext()) { while (i.hasNext()) {
Record11<LocalDate, LocalDateTime, EnumCamprole, LocalDateTime, LocalDateTime, Integer, Integer, String, String, String, String> r = i.next(); Record11<LocalDate, LocalDateTime, EnumCamprole, LocalDateTime, LocalDateTime, Integer, Integer, String, String, String, String> r = i
.next();
LocalDate birthdate = r.get(T_PERSON.BIRTHDATE); LocalDate birthdate = r.get(T_PERSON.BIRTHDATE);
LocalDateTime arrive = r.get(T_CAMP.ARRIVE); LocalDateTime arrive = r.get(T_CAMP.ARRIVE);
LocalDateTime depart = r.get(T_CAMP.DEPART); LocalDateTime depart = r.get(T_CAMP.DEPART);
@ -339,4 +344,22 @@ public class PersonRepository {
} }
return buf.toString(); return buf.toString();
} }
/**
* get the price information of the camp that the person is registered for
*
* @param pkPerson the ID of the person
* @return the camp price information
*/
public String getCampprice(Integer pkPerson) {
SelectConditionStep<Record1<String>> sql = jooq
// @formatter:off
.select(T_CAMP.PRICE)
.from(T_PERSON)
.leftJoin(T_CAMP).on(T_CAMP.PK.eq(T_PERSON.FK_CAMP))
.where(T_PERSON.PK.eq(pkPerson));
// @formatter:on
LOGGER.trace(sql);
return sql.fetchOne(T_CAMP.PRICE);
}
} }

View File

@ -33,4 +33,14 @@ public class PersonService {
public String getAnnotations(Integer pk) { public String getAnnotations(Integer pk) {
return gateway.getAnnotations(pk); return gateway.getAnnotations(pk);
} }
/**
* get the price of the camp
*
* @param pk the ID of the person, not the camp
* @return the camp price
*/
public String getCampPrice(Integer pk) {
return gateway.getCampprice(pk);
}
} }

View File

@ -1,6 +1,7 @@
package de.jottyfan.camporganizer.module.confirmation.person.model; package de.jottyfan.camporganizer.module.confirmation.person.model;
import java.io.Serializable; import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@ -8,6 +9,7 @@ import org.springframework.format.annotation.DateTimeFormat;
import de.jottyfan.camporganizer.db.jooq.enums.EnumCamprole; import de.jottyfan.camporganizer.db.jooq.enums.EnumCamprole;
import de.jottyfan.camporganizer.db.jooq.enums.EnumSex; import de.jottyfan.camporganizer.db.jooq.enums.EnumSex;
import jakarta.validation.constraints.DecimalMin;
/** /**
* *
@ -15,7 +17,7 @@ import de.jottyfan.camporganizer.db.jooq.enums.EnumSex;
* *
*/ */
public class PersonBean implements Serializable { public class PersonBean implements Serializable {
private static final long serialVersionUID = 2L; private static final long serialVersionUID = 3L;
private Integer pk; private Integer pk;
private String forename; private String forename;
@ -35,6 +37,8 @@ public class PersonBean implements Serializable {
private EnumSex sex; private EnumSex sex;
private Integer fkRegistrator; private Integer fkRegistrator;
private String comment; private String comment;
@DecimalMin(value = "0")
private BigDecimal requiredPrice;
/** /**
* @return the forename * @return the forename
@ -273,4 +277,18 @@ public class PersonBean implements Serializable {
public void setPk(Integer pk) { public void setPk(Integer pk) {
this.pk = pk; this.pk = pk;
} }
/**
* @return the requiredPrice
*/
public BigDecimal getRequiredPrice() {
return requiredPrice;
}
/**
* @param requiredPrice the requiredPrice to set
*/
public void setRequiredPrice(BigDecimal requiredPrice) {
this.requiredPrice = requiredPrice;
}
} }

View File

@ -43,6 +43,10 @@
<th>Freizeitpreis</th> <th>Freizeitpreis</th>
<td th:text="${booker.price}" /> <td th:text="${booker.price}" />
</tr> </tr>
<tr th:if="${booker.requiredPrice}">
<th>davon für <span th:text="${booker.name}"></span></th>
<td th:text="${#numbers.formatDecimal(booker.requiredPrice, 1, 2) + ' €'}"></td>
</tr>
<tr> <tr>
<th>Kontostand</th> <th>Kontostand</th>
<td><span th:text="${#numbers.formatDecimal(booker.paid, 1, 2) + ' €'}" th:if="${booker.paid != null}"></span></td> <td><span th:text="${#numbers.formatDecimal(booker.paid, 1, 2) + ' €'}" th:if="${booker.paid != null}"></span></td>

View File

@ -44,6 +44,7 @@
<div class="row mb-2"> <div class="row mb-2">
<label for="inputBirthdate" class="col-sm-2 col-form-label">Geburtstag</label> <label for="inputBirthdate" class="col-sm-2 col-form-label">Geburtstag</label>
<div class="col-sm-4"> <div class="col-sm-4">
<span class="error" th:each="error : ${#fields.errors('birthdate')}">[[${error}]]<br /></span>
<input type="date" th:field="*{birthdate}" class="inputBirthdate form-control" /> <input type="date" th:field="*{birthdate}" class="inputBirthdate form-control" />
</div> </div>
<label for="inputSex" class="col-sm-2 col-form-label">Geschlecht</label> <label for="inputSex" class="col-sm-2 col-form-label">Geschlecht</label>
@ -93,6 +94,16 @@
<textarea th:field="*{comment}" class="inputComment form-control"></textarea> <textarea th:field="*{comment}" class="inputComment form-control"></textarea>
</div> </div>
</div> </div>
<div class="row mb-2">
<label for="inputRequiredPrice" class="col-sm-2 col-form-label">individueller Preis</label>
<div class="col-sm-5">
<span class="error" th:each="error : ${#fields.errors('requiredPrice')}">[[${error}]]<br /></span>
<input type="number" th:field="*{requiredPrice}" class="inputRequiredPrice form-control" />
</div>
<div class="col-sm-5 d-flex align-items-center">
von offiziell&nbsp;<span th:utext="${campPrice}"></span>
</div>
</div>
<div class="row mb-2"> <div class="row mb-2">
<label for="outputAnno" class="col-sm-2 col-form-label">Anmerkungen</label> <label for="outputAnno" class="col-sm-2 col-form-label">Anmerkungen</label>
<div class="col-sm-10"> <div class="col-sm-10">