Skip to content

Commit

Permalink
Merge pull request #16 from cdlib/develop
Browse files Browse the repository at this point in the history
Second round of changes, including PivotTable and error feedback UX.
  • Loading branch information
michaelmp authored Aug 17, 2017
2 parents a150eb2 + 83ba1c8 commit ab0d680
Show file tree
Hide file tree
Showing 46 changed files with 3,787 additions and 383 deletions.
15 changes: 15 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
<eclipselink.version>2.6.4</eclipselink.version>
<mysql.version>6.0.6</mysql.version>
<mockito.override.version>2.8.9</mockito.override.version>
<apache.poi.version>3.16</apache.poi.version>
</properties>

<parent>
Expand All @@ -38,6 +39,10 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-el</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
Expand All @@ -63,6 +68,16 @@
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-csv</artifactId>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>${apache.poi.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>${apache.poi.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>javax.persistence</artifactId>
Expand Down
14 changes: 12 additions & 2 deletions src/main/java/org/cdlib/ill/model/CampusILLReport.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

public class CampusILLReport extends ResourceSupport {

private String title;
private String campusCode;
private List<InstitutionILLReport> institutionReports;
private LocalDate reportBeginDate;
Expand All @@ -17,11 +18,20 @@ public CampusILLReport() {
this.institutionReports = new ArrayList<>();
}

public CampusILLReport(String code) {
this.campusCode = code;
public CampusILLReport(String title, String campusCode) {
this.title = title;
this.campusCode = campusCode;
this.institutionReports = new ArrayList<>();
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

public String getCampusCode() {
return campusCode;
}
Expand Down
12 changes: 8 additions & 4 deletions src/main/java/org/cdlib/ill/report/CampusILLReportService.java
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,14 @@ private void addInstitution(CampusILLReport campus, String campusCode, String in
campus.getInstitutionReports().add(institution);
}

public CampusILLReport getILLCampusReport(String campusCode, LocalDate from, LocalDate to) {
CampusILLReport campus = new CampusILLReport(campusCode);
public CampusILLReport getILLCampusReport(String title, String campusCode, String campusQuery, LocalDate from, LocalDate to) {
CampusILLReport campus = new CampusILLReport(title, campusCode);
campus.setReportBeginDate(from);
campus.setReportEndDate(to);

Map<String, List<SpVdxBorrowingSummary>> borrowingSummaries = vdxBorrowingRepo.getBorrowingSummary(campusCode, from, to)
Map<String, List<SpVdxBorrowingSummary>> borrowingSummaries = vdxBorrowingRepo.getBorrowingSummary(campusQuery, from, to)
.collect(Collectors.groupingBy(SpVdxBorrowingSummary::getReqName));
Map<String, List<SpVdxLendingSummary>> lendingSummaries = vdxLendingRepo.getLendingSummary(campusCode, from, to)
Map<String, List<SpVdxLendingSummary>> lendingSummaries = vdxLendingRepo.getLendingSummary(campusQuery, from, to)
.collect(Collectors.groupingBy(SpVdxLendingSummary::getRespName));

Set<String> libraries = Stream.concat(borrowingSummaries.keySet().stream(), lendingSummaries.keySet().stream()).collect(Collectors.toSet());
Expand All @@ -86,4 +86,8 @@ public CampusILLReport getILLCampusReport(String campusCode, LocalDate from, Loc
return campus;
}

public CampusILLReport getILLCampusReport(String campusCode, LocalDate from, LocalDate to) {
return getILLCampusReport(campusCode, campusCode, campusCode, from, to);
}

}
65 changes: 45 additions & 20 deletions src/main/java/org/cdlib/ill/report/ReportHtmlController.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,19 @@

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.List;
import java.util.stream.Collectors;
import javax.validation.Valid;
import org.cdlib.ill.model.CampusILLReport;
import org.cdlib.ill.report.vdx.VdxCampus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;

@Controller
Expand All @@ -21,40 +23,63 @@ public class ReportHtmlController {
@Autowired
private CampusILLReportService repo;

private CampusILLReport getCampusReport(String campus, LocalDate reportStartDate, LocalDate reportEndDate) {
return repo.getILLCampusReport(campus, reportStartDate, reportEndDate);
private CampusILLReport getAllCampusReport(LocalDate reportStartDate, LocalDate reportEndDate) {
return repo.getILLCampusReport("All Campuses", "all", "%", reportStartDate, reportEndDate);
}

private List<CampusILLReport> getCampusReports(LocalDate reportStartDate, LocalDate reportEndDate) {
return EnumSet.complementOf(EnumSet.of(VdxCampus.None)).stream()
.map(VdxCampus::getCode)
.map((String campus) -> {
return getCampusReport(campus, reportStartDate, reportEndDate);
})
.collect(Collectors.toList());
private CampusILLReport getCampusReport(String campusCode, LocalDate reportStartDate, LocalDate reportEndDate) {
return repo.getILLCampusReport(campusCode, reportStartDate, reportEndDate);
}

private LocalDate parseDate(String formatted) {
return LocalDate.parse(formatted, DateTimeFormatter.ISO_LOCAL_DATE);
}

@GetMapping("/")
public String home(Model model) {
public String home(@ModelAttribute("queryForm") ReportHtmlForm queryForm, Model model) {
model.addAttribute("campuses", EnumSet.complementOf(EnumSet.of(VdxCampus.None)));
model.addAttribute("searchStartDate", null);
model.addAttribute("searchEndDate", null);
return "report";
}

@PostMapping("/")
public String query(ReportHtmlForm query, Model model) {
public String query(@Valid @ModelAttribute("queryForm") ReportHtmlForm queryForm, BindingResult bindingResult, Model model) {
model.addAttribute("campuses", EnumSet.complementOf(EnumSet.of(VdxCampus.None)));
model.addAttribute("campusDefault", VdxCampus.fromCode(query.getCampus()).map(VdxCampus::getCode).orElse(""));
model.addAttribute("searchStartDate", query.getFrom());
model.addAttribute("searchEndDate", query.getTo());
model.addAttribute("reports", StringUtils.isEmpty(query.getCampus())
? getCampusReports(parseDate(query.getFrom()), parseDate(query.getTo()))
: Arrays.asList(getCampusReport(query.getCampus(), parseDate(query.getFrom()), parseDate(query.getTo()))));
model.addAttribute("searchStartDate", queryForm.getFrom());
model.addAttribute("searchEndDate", queryForm.getTo());

LocalDate from = LocalDate.MIN;
LocalDate to = LocalDate.MAX;

try {
from = parseDate(queryForm.getFrom());
} catch (DateTimeParseException ex) {
bindingResult.addError(new FieldError("queryForm", "from", "Date does not match YYYY-MM-DD."));
}
try {
to = parseDate(queryForm.getTo());
} catch (DateTimeParseException ex) {
bindingResult.addError(new FieldError("queryForm", "to", "Date does not match YYYY-MM-DD."));
}

if (bindingResult.hasErrors()) {
model.addAttribute("campusDefault", queryForm.getCampus());
} else {
model.addAttribute("campusDefault", VdxCampus.fromCode(queryForm.getCampus()).map(VdxCampus::getCode).orElse("all"));
model.addAttribute("reports",
Arrays.asList(VdxCampus.fromCode(queryForm.getCampus()).isPresent()
? getCampusReport(VdxCampus.fromCode(queryForm.getCampus())
.filter((campus) -> campus != VdxCampus.None)
.map(VdxCampus::getCode)
.orElseThrow(Constants.BAD_DATA_EX_SUPPLIER),
from,
to)
: getAllCampusReport(
from,
to)
));
}
return "report";
}

Expand Down
9 changes: 9 additions & 0 deletions src/main/java/org/cdlib/ill/report/ReportHtmlForm.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
package org.cdlib.ill.report;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;

public class ReportHtmlForm {

@NotNull
@Pattern(regexp = "(Search)")
private String command;
@NotNull
@Pattern(regexp = "all|OELA|NRLF|SRLF|UCB|UCD|UCI|UCLA|UCM|UCR|UCSB|UCSC|UCSD|UCSF")
private String campus;
@NotNull
private String from;
@NotNull
private String to;

public String getCommand() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@
import java.io.IOException;
import java.io.Writer;
import java.time.LocalDate;
import java.util.EnumSet;
import java.util.List;
import java.util.stream.Collectors;
import org.cdlib.ill.report.vdx.VdxBorrowing;
import org.cdlib.ill.report.vdx.VdxCampus;
import org.cdlib.ill.report.vdx.VdxLending;
import org.cdlib.ill.report.vdx.VdxBorrowingRepository;
import org.cdlib.ill.report.vdx.VdxLendingRepository;
import org.cdlib.ill.report.vdx.procedures.SpVdxLendingBilling;
import org.cdlib.ill.report.vdx.procedures.SpVdxLendingBillingRepository;
import org.cdlib.ill.report.vdx.procedures.SpVdxLendingUnfilledDetail;
import org.cdlib.ill.report.vdx.procedures.SpVdxLendingUnfilledDetailRepository;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -25,10 +28,7 @@
import org.springframework.web.bind.annotation.RestController;

/**
* A web service for ILL data. UC ILL data are derived from VDX data.
*
* TODO: Throw an exception => 400 when the campus is not an enumerated value &
* unit test.
* A web service for ILL data provided by VDX.
*
* @author mmorrisp
*/
Expand All @@ -42,57 +42,85 @@ public class CampusILLDataRestController {
private VdxLendingRepository vdxLendingRepo;
@Autowired
private SpVdxLendingUnfilledDetailRepository vdxLendingUnfilledRepo;
@Autowired
private SpVdxLendingBillingRepository vdxLendingBillingRepo;

@RequestMapping(value = "{campusCode}/borrowing.xml", produces = {"application/xml"})
public HttpEntity<List<VdxBorrowing>> getCampusBorrowingXml(@PathVariable("campusCode") String campusCode,
@RequestParam(required = false, name = "startDate", defaultValue = "1900-01-01") @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startDate,
@RequestParam(required = false, name = "endDate", defaultValue = "2100-01-01") @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate endDate) {
return new ResponseEntity<>(vdxBorrowingRepo.getVdxBorrowing(VdxCampus.fromCode(campusCode).map(VdxCampus::getCode).orElse(""), startDate, endDate), HttpStatus.OK);
return new ResponseEntity<>(vdxBorrowingRepo.getVdxBorrowing(
VdxCampus.fromCode(campusCode)
.map(EnumSet::of)
.orElse(EnumSet.of(VdxCampus.None, VdxCampus.values())),
startDate, endDate), HttpStatus.OK);
}

@RequestMapping(value = "{campusCode}/borrowing.json", produces = {"application/json"})
public HttpEntity<List<VdxBorrowing>> getCampusBorrowingJson(@PathVariable("campusCode") String campusCode,
@RequestParam(required = false, name = "startDate", defaultValue = "1900-01-01") @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startDate,
@RequestParam(required = false, name = "endDate", defaultValue = "2100-01-01") @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate endDate) {
return new ResponseEntity<>(vdxBorrowingRepo.getVdxBorrowing(VdxCampus.fromCode(campusCode).map(VdxCampus::getCode).orElse(""), startDate, endDate), HttpStatus.OK);
return new ResponseEntity<>(vdxBorrowingRepo.getVdxBorrowing(
VdxCampus.fromCode(campusCode)
.map(EnumSet::of)
.orElse(EnumSet.of(VdxCampus.None, VdxCampus.values())),
startDate, endDate), HttpStatus.OK);
}

@RequestMapping(value = "{campusCode}/borrowing.csv", produces = {"text/csv"})
public void getCampusBorrowingCsv(Writer output,
@PathVariable("campusCode") String campusCode,
@RequestParam(required = false, name = "startDate", defaultValue = "1900-01-01") @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startDate,
@RequestParam(required = false, name = "endDate", defaultValue = "2100-01-01") @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate endDate) throws IOException {
@RequestParam(required = false, name = "endDate", defaultValue = "2100-01-01") @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate endDate)
throws IOException {
CsvMapper mapper = new CsvMapper();
CsvSchema schema = mapper.schemaFor(VdxBorrowing.class).withHeader();
List<VdxBorrowing> data = vdxBorrowingRepo.getVdxBorrowing(VdxCampus.fromCode(campusCode).map(VdxCampus::getCode).orElse(""), startDate, endDate);
List<VdxBorrowing> data = vdxBorrowingRepo.getVdxBorrowing(
VdxCampus.fromCode(campusCode)
.map(EnumSet::of)
.orElse(EnumSet.of(VdxCampus.None, VdxCampus.values())),
startDate, endDate);
mapper.writer(schema).writeValue(output, data);
}

@RequestMapping(value = "{campusCode}/lending.xml", produces = {"application/xml"})
public HttpEntity<List<VdxLending>> getCampusLendingXml(@PathVariable("campusCode") String campusCode,
@RequestParam(required = false, name = "startDate", defaultValue = "1900-01-01") @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startDate,
@RequestParam(required = false, name = "endDate", defaultValue = "2100-01-01") @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate endDate) {
return new ResponseEntity<>(vdxLendingRepo.getVdxLending(VdxCampus.fromCode(campusCode).map(VdxCampus::getCode).orElse(""), startDate, endDate), HttpStatus.OK);
return new ResponseEntity<>(vdxLendingRepo.getVdxLending(
VdxCampus.fromCode(campusCode)
.map(EnumSet::of)
.orElse(EnumSet.of(VdxCampus.None, VdxCampus.values())),
startDate, endDate), HttpStatus.OK);
}

@RequestMapping(value = "{campusCode}/lending.json", produces = {"application/json"})
public HttpEntity<List<VdxLending>> getCampusLendingJson(@PathVariable("campusCode") String campusCode,
@RequestParam(required = false, name = "startDate", defaultValue = "1900-01-01") @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startDate,
@RequestParam(required = false, name = "endDate", defaultValue = "2100-01-01") @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate endDate) {
return new ResponseEntity<>(vdxLendingRepo.getVdxLending(VdxCampus.fromCode(campusCode).map(VdxCampus::getCode).orElse(""), startDate, endDate), HttpStatus.OK);
return new ResponseEntity<>(vdxLendingRepo.getVdxLending(
VdxCampus.fromCode(campusCode)
.map(EnumSet::of)
.orElse(EnumSet.of(VdxCampus.None, VdxCampus.values())),
startDate, endDate), HttpStatus.OK);
}

@RequestMapping(value = "{campusCode}/lending.csv", produces = {"text/csv"})
public void getCampusLendingCsv(Writer output,
@PathVariable("campusCode") String campusCode,
@RequestParam(required = false, name = "startDate", defaultValue = "1900-01-01") @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startDate,
@RequestParam(required = false, name = "endDate", defaultValue = "2100-01-01") @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate endDate) throws IOException {
@RequestParam(required = false, name = "endDate", defaultValue = "2100-01-01") @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate endDate)
throws IOException {
CsvMapper mapper = new CsvMapper();
CsvSchema schema = mapper.schemaFor(VdxLending.class).withHeader();
List<VdxLending> data = vdxLendingRepo.getVdxLending(VdxCampus.fromCode(campusCode).map(VdxCampus::getCode).orElse(""), startDate, endDate);
List<VdxLending> data = vdxLendingRepo.getVdxLending(
VdxCampus.fromCode(campusCode)
.map(EnumSet::of)
.orElse(EnumSet.of(VdxCampus.None, VdxCampus.values())),
startDate, endDate);
mapper.writer(schema).writeValue(output, data);
}

@RequestMapping(value = "{campusCode}/lending_unfilled.csv", produces = {"text/csv"})
public void getLendingUnfilledCsv(Writer output,
@PathVariable("campusCode") String campusCode,
Expand All @@ -102,9 +130,25 @@ public void getLendingUnfilledCsv(Writer output,
CsvSchema schema = mapper.schemaFor(SpVdxLendingUnfilledDetail.class).withHeader();
List<SpVdxLendingUnfilledDetail> data = vdxLendingUnfilledRepo
.getLendingUnfilledDetail(VdxCampus.fromCode(campusCode)
.map(VdxCampus::getCode).orElse(""), startDate, endDate)
.map(VdxCampus::getCode).orElse("%"), startDate, endDate)
.collect(Collectors.toList());
mapper.writer(schema).writeValue(output, data);
}

@RequestMapping(value = "{campusCode}/lending_billing.csv", produces = {"text/csv"})
public void getLendingBillingCsv(Writer output,
@PathVariable("campusCode") String campusCode,
@RequestParam(required = false, name = "startDate", defaultValue = "1900-01-01") @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startDate,
@RequestParam(required = false, name = "endDate", defaultValue = "2100-01-01") @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate endDate) throws IOException {
CsvMapper mapper = new CsvMapper();
CsvSchema schema = mapper.schemaFor(SpVdxLendingBilling.class).withHeader();
List<SpVdxLendingBilling> data = vdxLendingBillingRepo
.getLendingBilling(
VdxCampus.fromCode(campusCode)
.map(VdxCampus::getCode)
.orElse("%"),
startDate, endDate);
mapper.writer(schema).writeValue(output, data);
}

}
Loading

0 comments on commit ab0d680

Please sign in to comment.