From 32ef8a67d95628e81ee027c471f304abaf4815c9 Mon Sep 17 00:00:00 2001 From: Jottyfan Date: Mon, 19 Aug 2024 17:23:41 +0200 Subject: [PATCH] added outlay --- build.gradle | 2 +- .../business/outlay/OutlayController.java | 66 ++++++ .../business/outlay/OutlayRepository.java | 191 ++++++++++++++++++ .../module/business/outlay/OutlayService.java | 46 +++++ .../business/outlay/model/CampBean.java | 51 +++++ .../business/outlay/model/OutlayBean.java | 180 +++++++++++++++++ .../templates/business/outlay/editor.html | 85 ++++++++ .../templates/business/outlay/list.html | 45 +++++ src/main/resources/templates/index.html | 2 +- src/main/resources/templates/template.html | 1 + 10 files changed, 667 insertions(+), 2 deletions(-) create mode 100644 src/main/java/de/jottyfan/camporganizer/module/business/outlay/OutlayController.java create mode 100644 src/main/java/de/jottyfan/camporganizer/module/business/outlay/OutlayRepository.java create mode 100644 src/main/java/de/jottyfan/camporganizer/module/business/outlay/OutlayService.java create mode 100644 src/main/java/de/jottyfan/camporganizer/module/business/outlay/model/CampBean.java create mode 100644 src/main/java/de/jottyfan/camporganizer/module/business/outlay/model/OutlayBean.java create mode 100644 src/main/resources/templates/business/outlay/editor.html create mode 100644 src/main/resources/templates/business/outlay/list.html diff --git a/build.gradle b/build.gradle index ca3c129..6ca5628 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { } group = 'de.jottyfan.camporganizer' -version = '0.8.4' +version = '0.8.5' description = """CampOrganizer2""" diff --git a/src/main/java/de/jottyfan/camporganizer/module/business/outlay/OutlayController.java b/src/main/java/de/jottyfan/camporganizer/module/business/outlay/OutlayController.java new file mode 100644 index 0000000..8a72cf8 --- /dev/null +++ b/src/main/java/de/jottyfan/camporganizer/module/business/outlay/OutlayController.java @@ -0,0 +1,66 @@ +package de.jottyfan.camporganizer.module.business.outlay; + +import java.security.Principal; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; + +import de.jottyfan.camporganizer.module.business.outlay.model.OutlayBean; +import de.jottyfan.camporganizer.module.camplist.CommonController; +import jakarta.annotation.security.RolesAllowed; +import jakarta.validation.Valid; + +/** + * + * @author jotty + * + */ +@Controller +@RolesAllowed({ "business_outlay" }) +public class OutlayController extends CommonController { + + @Autowired + private OutlayService service; + + @GetMapping("/business/outlay") + public String getOutlayDashboard(Model model, Principal principal) { + model.addAttribute("list", service.getListOfUser(super.getCurrentUser(principal))); + return "/business/outlay/list"; + } + + @GetMapping("/business/outlay/add") + public String loadAddMask(Model model, Principal principal) { + model.addAttribute("bean", new OutlayBean().withUser(super.getCurrentUser(principal))); + model.addAttribute("camps", service.getAllCamps()); + return "/business/outlay/editor"; + } + + @GetMapping("/business/outlay/edit/{id}") + public String loadAddMask(@PathVariable("id") Integer id, Model model, Principal principal) { + model.addAttribute("bean", service.getBeanIfAllowedFor(super.getCurrentUser(principal), id)); + model.addAttribute("camps", service.getAllCamps()); + return "/business/outlay/editor"; + } + + @PostMapping("/business/outlay/save") + public String save(@Valid @ModelAttribute("bean") OutlayBean bean, BindingResult bindingResult, Model model) { + if (bindingResult.hasErrors()) { + model.addAttribute("camps", service.getAllCamps()); + return "/business/outlay/editor"; + } + service.save(bean); + return "redirect:/business/outlay"; + } + + @GetMapping("/business/outlay/delete/{id}") + public String delete(@PathVariable("id") Integer id, Principal principal) { + service.deleteIfAllowedFor(super.getCurrentUser(principal), id); + return "redirect:/business/outlay"; + } +} diff --git a/src/main/java/de/jottyfan/camporganizer/module/business/outlay/OutlayRepository.java b/src/main/java/de/jottyfan/camporganizer/module/business/outlay/OutlayRepository.java new file mode 100644 index 0000000..fb49d2f --- /dev/null +++ b/src/main/java/de/jottyfan/camporganizer/module/business/outlay/OutlayRepository.java @@ -0,0 +1,191 @@ +package de.jottyfan.camporganizer.module.business.outlay; + +import static de.jottyfan.camporganizer.db.jooq.Tables.T_CAMP; +import static de.jottyfan.camporganizer.db.jooq.Tables.T_LOCATION; +import static de.jottyfan.camporganizer.db.jooq.Tables.T_SALES; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.jooq.DSLContext; +import org.jooq.DeleteConditionStep; +import org.jooq.InsertValuesStep8; +import org.jooq.Record10; +import org.jooq.Record4; +import org.jooq.Record7; +import org.jooq.SelectConditionStep; +import org.jooq.SelectSeekStep1; +import org.jooq.UpdateConditionStep; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +import de.jottyfan.camporganizer.db.jooq.tables.records.TSalesRecord; +import de.jottyfan.camporganizer.module.business.outlay.model.CampBean; +import de.jottyfan.camporganizer.module.business.outlay.model.OutlayBean; +import jakarta.validation.Valid; + +/** + * + * @author jotty + * + */ +@Repository +@Transactional(transactionManager = "transactionManager") +public class OutlayRepository { + private static final Logger LOGGER = LogManager.getLogger(OutlayRepository.class); + + @Autowired + private DSLContext jooq; + + /** + * get all camps from the database + * + * @return a list of camps; an empty list at least + */ + public List getAllCamps() { + SelectSeekStep1, LocalDateTime> sql = jooq + // @formatter:off + .select(T_CAMP.PK, T_CAMP.NAME, T_CAMP.ARRIVE, T_LOCATION.NAME) + .from(T_CAMP) + .leftJoin(T_LOCATION).on(T_LOCATION.PK.eq(T_CAMP.FK_LOCATION)) + .orderBy(T_CAMP.ARRIVE.desc()); + // @formatter:on + LOGGER.trace(sql.toString()); + List list = new ArrayList<>(); + Iterator> i = sql.fetch().iterator(); + while (i.hasNext()) { + Record4 r = i.next(); + String name = String + .format("%s %s %d", r.get(T_CAMP.NAME), r.get(T_LOCATION.NAME), r.get(T_CAMP.ARRIVE).getYear()).trim(); + list.add(CampBean.of(r.get(T_CAMP.PK)).withCampname(name)); + } + return list; + } + + public List getListOf(String username) { + SelectConditionStep> sql = jooq + // @formatter:off + .select(T_SALES.PK, + T_SALES.TRADER, + T_CAMP.NAME, + T_CAMP.ARRIVE, + T_LOCATION.NAME, + T_SALES.CASH, + T_SALES.BUYDATE) + .from(T_SALES) + .leftJoin(T_CAMP).on(T_CAMP.PK.eq(T_SALES.FK_CAMP)) + .leftJoin(T_LOCATION).on(T_LOCATION.PK.eq(T_CAMP.FK_LOCATION)) + .where(T_SALES.PROVIDER.eq(username)); + // @formatter:on + LOGGER.trace(sql); + List list = new ArrayList<>(); + Iterator> i = sql.fetch() + .iterator(); + while (i.hasNext()) { + Record7 r = i.next(); + String campname = String + .format("%s %s %d", r.get(T_CAMP.NAME), r.get(T_LOCATION.NAME), r.get(T_CAMP.ARRIVE).getYear()).trim(); + OutlayBean bean = new OutlayBean(); + bean.setId(r.get(T_SALES.PK)); + bean.setTrader(r.get(T_SALES.TRADER)); + bean.setCampname(campname); + bean.setCash(r.get(T_SALES.CASH)); + bean.setBuydate(r.get(T_SALES.BUYDATE)); + list.add(bean); + } + return list; + } + + public void addBean(@Valid OutlayBean bean) { + InsertValuesStep8 sql = jooq + // @formatter:off + .insertInto(T_SALES, + T_SALES.BUYDATE, + T_SALES.CASH, + T_SALES.FK_CAMP, + T_SALES.INCREDIENTS, + T_SALES.PROVIDER, + T_SALES.RECIPENOTE, + T_SALES.RECIPENUMBER, + T_SALES.TRADER) + .values(bean.getBuydate(), bean.getCash(), bean.getFkCamp(), bean.getIngredients(), bean.getProvider(), bean.getRecipenote(), bean.getRecipenumber(), bean.getTrader()); + // @formatter:on + LOGGER.trace(sql); + sql.execute(); + } + + public void updateBean(@Valid OutlayBean bean) { + UpdateConditionStep sql = jooq + // @formatter:off + .update(T_SALES) + .set(T_SALES.BUYDATE, bean.getBuydate()) + .set(T_SALES.CASH, bean.getCash()) + .set(T_SALES.FK_CAMP, bean.getFkCamp()) + .set(T_SALES.INCREDIENTS, bean.getIngredients()) + .set(T_SALES.PROVIDER, bean.getProvider()) + .set(T_SALES.RECIPENOTE, bean.getRecipenote()) + .set(T_SALES.RECIPENUMBER, bean.getRecipenumber()) + .set(T_SALES.TRADER, bean.getTrader()) + .where(T_SALES.PK.eq(bean.getId())); + // @formatter:on + LOGGER.trace(sql); + sql.execute(); + } + + public OutlayBean getBeanIfAllowedFor(String username, Integer id) { + SelectConditionStep> sql = jooq + // @formatter:off + .select(T_SALES.PK, + T_SALES.TRADER, + T_SALES.FK_CAMP, + T_SALES.CASH, + T_SALES.BUYDATE, + T_SALES.INCREDIENTS, + T_SALES.PROVIDER, + T_SALES.RECIPENOTE, + T_SALES.RECIPENUMBER, + T_SALES.TRADER) + .from(T_SALES) + .leftJoin(T_CAMP).on(T_CAMP.PK.eq(T_SALES.FK_CAMP)) + .leftJoin(T_LOCATION).on(T_LOCATION.PK.eq(T_CAMP.FK_LOCATION)) + .where(T_SALES.PROVIDER.eq(username)) + .and(T_SALES.PK.eq(id)); + // @formatter:on + LOGGER.trace(sql); + Record10 r = sql + .fetchOne(); + if (r == null) { + return null; + } else { + OutlayBean bean = new OutlayBean(); + bean.setId(r.get(T_SALES.PK)); + bean.setBuydate(r.get(T_SALES.BUYDATE)); + bean.setCash(r.get(T_SALES.CASH)); + bean.setFkCamp(r.get(T_SALES.FK_CAMP)); + bean.setIngredients(r.get(T_SALES.INCREDIENTS)); + bean.setProvider(r.get(T_SALES.PROVIDER)); + bean.setRecipenote(r.get(T_SALES.RECIPENOTE)); + bean.setRecipenumber(r.get(T_SALES.RECIPENUMBER)); + bean.setTrader(r.get(T_SALES.TRADER)); + return bean; + } + } + + public void deleteBeanIfAllowedFor(String username, Integer id) { + DeleteConditionStep sql = jooq + // @formatter:off + .deleteFrom(T_SALES) + .where(T_SALES.PROVIDER.eq(username)) + .and(T_SALES.PK.eq(id)); + // @formatter:off + LOGGER.trace(sql); + sql.execute(); + } + +} diff --git a/src/main/java/de/jottyfan/camporganizer/module/business/outlay/OutlayService.java b/src/main/java/de/jottyfan/camporganizer/module/business/outlay/OutlayService.java new file mode 100644 index 0000000..7196203 --- /dev/null +++ b/src/main/java/de/jottyfan/camporganizer/module/business/outlay/OutlayService.java @@ -0,0 +1,46 @@ +package de.jottyfan.camporganizer.module.business.outlay; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import de.jottyfan.camporganizer.module.business.outlay.model.CampBean; +import de.jottyfan.camporganizer.module.business.outlay.model.OutlayBean; +import jakarta.validation.Valid; + +/** + * + * @author jotty + * + */ +@Service +public class OutlayService { + + @Autowired + private OutlayRepository repository; + + public List getListOfUser(String username) { + return repository.getListOf(username); + } + + public List getAllCamps() { + return repository.getAllCamps(); + } + + public void save(@Valid OutlayBean bean) { + if (bean.getId() != null) { + repository.updateBean(bean); + } else { + repository.addBean(bean); + } + } + + public OutlayBean getBeanIfAllowedFor(String username, Integer id) { + return repository.getBeanIfAllowedFor(username, id); + } + + public void deleteIfAllowedFor(String username, Integer id) { + repository.deleteBeanIfAllowedFor(username, id); + } +} diff --git a/src/main/java/de/jottyfan/camporganizer/module/business/outlay/model/CampBean.java b/src/main/java/de/jottyfan/camporganizer/module/business/outlay/model/CampBean.java new file mode 100644 index 0000000..b17a00a --- /dev/null +++ b/src/main/java/de/jottyfan/camporganizer/module/business/outlay/model/CampBean.java @@ -0,0 +1,51 @@ +package de.jottyfan.camporganizer.module.business.outlay.model; + +import java.io.Serializable; + +/** + * + * @author jotty + * + */ +public class CampBean implements Serializable { + + private static final long serialVersionUID = 1L; + + private final Integer id; + private String campname; + + private CampBean(Integer id) { + super(); + this.id = id; + } + + public static final CampBean of(Integer id) { + return new CampBean(id); + } + + public CampBean withCampname(String campname) { + this.campname = campname; + return this; + } + + /** + * @return the campname + */ + public String getCampname() { + return campname; + } + + /** + * @param campname the campname to set + */ + public void setCampname(String campname) { + this.campname = campname; + } + + /** + * @return the id + */ + public Integer getId() { + return id; + } +} diff --git a/src/main/java/de/jottyfan/camporganizer/module/business/outlay/model/OutlayBean.java b/src/main/java/de/jottyfan/camporganizer/module/business/outlay/model/OutlayBean.java new file mode 100644 index 0000000..9eeb68f --- /dev/null +++ b/src/main/java/de/jottyfan/camporganizer/module/business/outlay/model/OutlayBean.java @@ -0,0 +1,180 @@ +package de.jottyfan.camporganizer.module.business.outlay.model; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import org.springframework.format.annotation.DateTimeFormat; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; + +/** + * + * @author jotty + * + */ +public class OutlayBean implements Serializable { + + private static final long serialVersionUID = 1L; + + private Integer id; + @NotBlank + private String trader; + @NotNull + private Integer fkCamp; + private String campname; + private String provider; + @NotNull + private BigDecimal cash; + @DateTimeFormat(pattern = "yyyy-MM-dd'T'hh:mm:ss") + private LocalDateTime buydate; + private String recipenumber; + private String recipenote; + private String ingredients; + + public OutlayBean withUser(String provider) { + this.provider = provider; + return this; + } + + /** + * @return the id + */ + public Integer getId() { + return id; + } + + /** + * @param id the id to set + */ + public void setId(Integer id) { + this.id = id; + } + + /** + * @return the trader + */ + public String getTrader() { + return trader; + } + + /** + * @param trader the trader to set + */ + public void setTrader(String trader) { + this.trader = trader; + } + + /** + * @return the campname + */ + public String getCampname() { + return campname; + } + + /** + * @param campname the campname to set + */ + public void setCampname(String campname) { + this.campname = campname; + } + + /** + * @return the cash + */ + public BigDecimal getCash() { + return cash; + } + + /** + * @param cash the cash to set + */ + public void setCash(BigDecimal cash) { + this.cash = cash; + } + + /** + * @return the buydate + */ + public LocalDateTime getBuydate() { + return buydate; + } + + /** + * @param buydate the buydate to set + */ + public void setBuydate(LocalDateTime buydate) { + this.buydate = buydate; + } + + /** + * @return the provider + */ + public String getProvider() { + return provider; + } + + /** + * @param provider the provider to set + */ + public void setProvider(String provider) { + this.provider = provider; + } + + /** + * @return the recipenumber + */ + public String getRecipenumber() { + return recipenumber; + } + + /** + * @param recipenumber the recipenumber to set + */ + public void setRecipenumber(String recipenumber) { + this.recipenumber = recipenumber; + } + + /** + * @return the recipenote + */ + public String getRecipenote() { + return recipenote; + } + + /** + * @param recipenote the recipenote to set + */ + public void setRecipenote(String recipenote) { + this.recipenote = recipenote; + } + + /** + * @return the ingredients + */ + public String getIngredients() { + return ingredients; + } + + /** + * @param ingredients the ingredients to set + */ + public void setIngredients(String ingredients) { + this.ingredients = ingredients; + } + + /** + * @return the fkCamp + */ + public Integer getFkCamp() { + return fkCamp; + } + + /** + * @param fkCamp the fkCamp to set + */ + public void setFkCamp(Integer fkCamp) { + this.fkCamp = fkCamp; + } +} diff --git a/src/main/resources/templates/business/outlay/editor.html b/src/main/resources/templates/business/outlay/editor.html new file mode 100644 index 0000000..9afe8a5 --- /dev/null +++ b/src/main/resources/templates/business/outlay/editor.html @@ -0,0 +1,85 @@ + + + +Camp Organizer Business + + + + +
+
+
Die Bearbeitung der Abrechnung ist nur dem Auslegenden erlaubt.
+
+ +
+
Auslegender
+
+ +
+
Händler / Shop
+
+ [[${error}]]
+
+
Freizeit
+
+ [[${error}]]
+ +
+
Betrag
+
+ [[${error}]]
+
+
+
Tag / Uhrzeit
+
+ +
+
Kassenzettelnummer
+
+ +
+
Kurzbeschreibung
+
+ +
+
Bemerkungen
+
+ +
+
+ + Abbrechen + + +
+
+
+
+
+
+ + \ No newline at end of file diff --git a/src/main/resources/templates/business/outlay/list.html b/src/main/resources/templates/business/outlay/list.html new file mode 100644 index 0000000..2d90129 --- /dev/null +++ b/src/main/resources/templates/business/outlay/list.html @@ -0,0 +1,45 @@ + + + +Camp Organizer Business + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + +
Händler / ShopFreizeitBetragTag / Uhrzeit
neue Rechnung eintragen
+ +
+
+
+ + \ No newline at end of file diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html index 5a0d409..8e39d31 100644 --- a/src/main/resources/templates/index.html +++ b/src/main/resources/templates/index.html @@ -27,7 +27,7 @@ -->

Willkommen bei den

-

MITTELPUNKTFREIZEITEN

+

MITTELPUNKT-FREIZEITEN



diff --git a/src/main/resources/templates/template.html b/src/main/resources/templates/template.html index 20b425a..b073dbe 100644 --- a/src/main/resources/templates/template.html +++ b/src/main/resources/templates/template.html @@ -75,6 +75,7 @@