Journal export for the accountants' import

Java · Spring Boot · intermediate · greenfield

Accountants re-key our journal into their accounting package every month end, and above all at year-end close. This adds a CSV export in the layout of its UK journal import: day/month/year dates, the account code, debit and credit columns, and a `JE-` reference back to the entry. Rows come from the existing `findForExport` query, scoped to the caller's org, and the range is capped at 366 days so one request cannot pull the whole ledger. Imported October's export into the package's sandbox: every line posted to the right account and period.

Ledger service on Spring Boot 3.3 (Java 21), Spring Data JPA on PostgreSQL. Existing `JournalLine` entity: `long getEntryId()`, `LocalDate getBookedOn()` (never null, between 2000-01-01 and 2099-12-31), `String getAccountCode()` (digits only, from the chart of accounts), `BigDecimal getDebit()` and `getCredit()` (`NUMERIC(14,2) NOT NULL`, scale 2, never negative, one of them zero). Existing `JournalLineRepository.findForExport(long orgId, LocalDate from, LocalDate to)` returns an org's lines with `from <= bookedOn <= to`, ordered by booking date, entry id and line id; an org books at most 50,000 lines a year. `SecurityConfig` requires authentication for `/api/**` and permits `/error`; the principal is `AppUser` (`long id`, `long orgId`).

Requirements

Files touched

--- src/main/java/com/acme/ledger/journal/JournalExportController.java
+package com.acme.ledger.journal;
+
+import java.io.IOException;
+import java.time.LocalDate;
+import java.time.temporal.ChronoUnit;
+
+import jakarta.servlet.http.HttpServletResponse;
+import org.springframework.format.annotation.DateTimeFormat;
+import org.springframework.http.HttpStatus;
+import org.springframework.security.core.annotation.AuthenticationPrincipal;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.server.ResponseStatusException;
+
+import com.acme.ledger.security.AppUser;
+
+@RestController
+public class JournalExportController {
+
+    private final JournalCsvExport export;
+
+    public JournalExportController(JournalCsvExport export) {
+        this.export = export;
+    }
+
+    @GetMapping("/api/journal/export.csv")
+    public void exportCsv(
+            @AuthenticationPrincipal AppUser user,

Review this PR

Java practice