Compare commits
	
		
			1 Commits
		
	
	
		
			outlay
			...
			ae9e2018a8
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 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> | ||||
		Reference in New Issue
	
	Block a user