download of outlays
This commit is contained in:
parent
32ef8a67d9
commit
ae9e2018a8
@ -8,7 +8,7 @@ plugins {
|
||||
}
|
||||
|
||||
group = 'de.jottyfan.camporganizer'
|
||||
version = '0.8.5'
|
||||
version = '0.8.6'
|
||||
|
||||
description = """CampOrganizer2"""
|
||||
|
||||
|
@ -3,6 +3,10 @@ package de.jottyfan.camporganizer.module.business.outlay;
|
||||
import java.security.Principal;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.io.InputStreamResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.validation.BindingResult;
|
||||
@ -15,6 +19,7 @@ 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;
|
||||
import jakarta.ws.rs.core.HttpHeaders;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -30,7 +35,8 @@ public class OutlayController extends CommonController {
|
||||
|
||||
@GetMapping("/business/outlay")
|
||||
public String getOutlayDashboard(Model model, Principal principal) {
|
||||
model.addAttribute("list", service.getListOfUser(super.getCurrentUser(principal)));
|
||||
model.addAttribute("list", service.getListOf(super.getCurrentUser(principal), null));
|
||||
model.addAttribute("camps", service.getAllCamps());
|
||||
return "/business/outlay/list";
|
||||
}
|
||||
|
||||
@ -63,4 +69,19 @@ public class OutlayController extends CommonController {
|
||||
service.deleteIfAllowedFor(super.getCurrentUser(principal), id);
|
||||
return "redirect:/business/outlay";
|
||||
}
|
||||
|
||||
@GetMapping("/business/outlay/summary/{campid}")
|
||||
public String getSummaryOfCamp(@PathVariable("campid") Integer campId, Model model, Principal principal) {
|
||||
model.addAttribute("campid", campId);
|
||||
model.addAttribute("list", service.getListOf(null, campId));
|
||||
return "/business/outlay/summary";
|
||||
}
|
||||
|
||||
@GetMapping("/business/outlay/download/{campid}")
|
||||
public ResponseEntity<Resource> generateCsv(@PathVariable("campid") Integer campId) {
|
||||
String filename = String.format("rechnung_camp_%d.csv", campId);
|
||||
InputStreamResource file = new InputStreamResource(service.getCsv(campId));
|
||||
return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + filename)
|
||||
.contentType(MediaType.parseMediaType("application/csv")).body(file);
|
||||
}
|
||||
}
|
||||
|
@ -16,11 +16,12 @@ import org.jooq.DSLContext;
|
||||
import org.jooq.DeleteConditionStep;
|
||||
import org.jooq.InsertValuesStep8;
|
||||
import org.jooq.Record10;
|
||||
import org.jooq.Record11;
|
||||
import org.jooq.Record4;
|
||||
import org.jooq.Record7;
|
||||
import org.jooq.SelectConditionStep;
|
||||
import org.jooq.SelectSeekStep1;
|
||||
import org.jooq.UpdateConditionStep;
|
||||
import org.jooq.impl.DSL;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@ -68,8 +69,8 @@ public class OutlayRepository {
|
||||
return list;
|
||||
}
|
||||
|
||||
public List<OutlayBean> getListOf(String username) {
|
||||
SelectConditionStep<Record7<Integer, String, String, LocalDateTime, String, BigDecimal, LocalDateTime>> sql = jooq
|
||||
public List<OutlayBean> getListOf(String username, Integer campId) {
|
||||
SelectConditionStep<Record11<Integer, String, String, LocalDateTime, String, BigDecimal, LocalDateTime, String, String, String, String>> sql = jooq
|
||||
// @formatter:off
|
||||
.select(T_SALES.PK,
|
||||
T_SALES.TRADER,
|
||||
@ -77,26 +78,35 @@ public class OutlayRepository {
|
||||
T_CAMP.ARRIVE,
|
||||
T_LOCATION.NAME,
|
||||
T_SALES.CASH,
|
||||
T_SALES.BUYDATE)
|
||||
T_SALES.BUYDATE,
|
||||
T_SALES.PROVIDER,
|
||||
T_SALES.RECIPENUMBER,
|
||||
T_SALES.INCREDIENTS,
|
||||
T_SALES.RECIPENOTE)
|
||||
.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));
|
||||
.where(username == null ? DSL.trueCondition() : T_SALES.PROVIDER.eq(username))
|
||||
.and(campId == null ? DSL.trueCondition() : T_SALES.FK_CAMP.eq(campId));
|
||||
// @formatter:on
|
||||
LOGGER.trace(sql);
|
||||
List<OutlayBean> list = new ArrayList<>();
|
||||
Iterator<Record7<Integer, String, String, LocalDateTime, String, BigDecimal, LocalDateTime>> i = sql.fetch()
|
||||
Iterator<Record11<Integer, String, String, LocalDateTime, String, BigDecimal, LocalDateTime, String, String, String, String>> i = sql.fetch()
|
||||
.iterator();
|
||||
while (i.hasNext()) {
|
||||
Record7<Integer, String, String, LocalDateTime, String, BigDecimal, LocalDateTime> r = i.next();
|
||||
Record11<Integer, String, String, LocalDateTime, String, BigDecimal, LocalDateTime, String, String, String, String> 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.setProvider(r.get(T_SALES.PROVIDER));
|
||||
bean.setCash(r.get(T_SALES.CASH));
|
||||
bean.setBuydate(r.get(T_SALES.BUYDATE));
|
||||
bean.setRecipenumber(r.get(T_SALES.RECIPENUMBER));
|
||||
bean.setIngredients(r.get(T_SALES.INCREDIENTS));
|
||||
bean.setRecipenote(r.get(T_SALES.RECIPENOTE));
|
||||
list.add(bean);
|
||||
}
|
||||
return list;
|
||||
|
@ -1,5 +1,7 @@
|
||||
package de.jottyfan.camporganizer.module.business.outlay;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -20,8 +22,8 @@ public class OutlayService {
|
||||
@Autowired
|
||||
private OutlayRepository repository;
|
||||
|
||||
public List<OutlayBean> getListOfUser(String username) {
|
||||
return repository.getListOf(username);
|
||||
public List<OutlayBean> getListOf(String username, Integer campId) {
|
||||
return repository.getListOf(username, campId);
|
||||
}
|
||||
|
||||
public List<CampBean> getAllCamps() {
|
||||
@ -43,4 +45,13 @@ public class OutlayService {
|
||||
public void deleteIfAllowedFor(String username, Integer id) {
|
||||
repository.deleteBeanIfAllowedFor(username, id);
|
||||
}
|
||||
|
||||
public InputStream getCsv(Integer campId) {
|
||||
List<OutlayBean> list = repository.getListOf(null, campId);
|
||||
StringBuilder buf = new StringBuilder("Beleg-Nummer;Einkauf bei;Freizeit;bezahlt von;Betrag;Bestandteile;Rechnungsdatum\n");
|
||||
for (OutlayBean bean : list) {
|
||||
buf.append(bean.toCsvLine());
|
||||
}
|
||||
return new ByteArrayInputStream(buf.toString().getBytes());
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,9 @@ package de.jottyfan.camporganizer.module.business.outlay.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.text.NumberFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
@ -38,6 +40,26 @@ public class OutlayBean implements Serializable {
|
||||
return this;
|
||||
}
|
||||
|
||||
private static final String quoted(String s) {
|
||||
return s == null ? "" : String.format("\"%s\"", s.replace("\"", "'"));
|
||||
}
|
||||
|
||||
private static final String cashed(BigDecimal money) {
|
||||
return money == null ? "" : String.format("%s €", NumberFormat.getNumberInstance(Locale.GERMAN).format(money));
|
||||
}
|
||||
|
||||
public String toCsvLine() {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append(recipenumber).append(";");
|
||||
buf.append(quoted(trader)).append(";");
|
||||
buf.append(quoted(campname)).append(";");
|
||||
buf.append(quoted(provider)).append(";");
|
||||
buf.append(cashed(cash)).append(";");
|
||||
buf.append(quoted(ingredients)).append(";");
|
||||
buf.append(buydate).append("\n");
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the id
|
||||
*/
|
||||
|
@ -31,6 +31,11 @@
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
<div class="row">
|
||||
<div class="col" th:each="c : ${camps}">
|
||||
<a th:href="@{/business/outlay/summary/{id}(id=${c.id})}" class="btn btn-outline-primary" th:text="${c.campname}"></a>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$("#table").DataTable({
|
||||
|
53
src/main/resources/templates/business/outlay/summary.html
Normal file
53
src/main/resources/templates/business/outlay/summary.html
Normal file
@ -0,0 +1,53 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org" layout:decorate="~{template}" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
|
||||
<head>
|
||||
<title>Camp Organizer Business</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
</head>
|
||||
<body>
|
||||
<th:block layout:fragment="content">
|
||||
<div class="mainpage">
|
||||
<div class="container" style="max-width: 100%" sec:authorize="hasRole('business_outlay')">
|
||||
<table id="table" class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Kassenzettelnummer</th>
|
||||
<th>Händler / Shop</th>
|
||||
<th>Freizeit</th>
|
||||
<th>Auslegender</th>
|
||||
<th>Betrag</th>
|
||||
<th>Tag / Uhrzeit</th>
|
||||
<th>Kurzbeschreibung</th>
|
||||
<th>Bemerkungen</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr th:each="o : ${list}">
|
||||
<td><a th:href="@{/business/outlay/edit/{id}(id=${o.id})}" th:text="${o.recipenumber}"></a></td>
|
||||
<td><a th:href="@{/business/outlay/edit/{id}(id=${o.id})}" th:text="${o.trader}"></a></td>
|
||||
<td><a th:href="@{/business/outlay/edit/{id}(id=${o.id})}" th:text="${o.campname}"></a></td>
|
||||
<td><a th:href="@{/business/outlay/edit/{id}(id=${o.id})}" th:text="${o.provider}"></a></td>
|
||||
<td><a th:href="@{/business/outlay/edit/{id}(id=${o.id})}" th:text="${#numbers.formatDecimal(o.cash, 1, 2, 'COMMA')} + ' €'"></a></td>
|
||||
<td><a th:href="@{/business/outlay/edit/{id}(id=${o.id})}" th:text="${#temporals.format(o.buydate, 'dd.MM.yyyy, HH:mm.ss')}"></a></td>
|
||||
<td><a th:href="@{/business/outlay/edit/{id}(id=${o.id})}" th:text="${o.ingredients}"></a></td>
|
||||
<td><a th:href="@{/business/outlay/edit/{id}(id=${o.id})}" th:text="${o.recipenote}"></a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="8"><a th:href="@{/business/outlay/download/{campid}(campid=${campid})}" class="btn btn-outline-primary form-control">herunterladen</a></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$("#table").DataTable({
|
||||
language : locale_de
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
||||
</th:block>
|
||||
</body>
|
||||
</html>
|
Loading…
x
Reference in New Issue
Block a user