Skip to content

Commit

Permalink
Add calendar 5.0 API support (#1167)
Browse files Browse the repository at this point in the history
* Add calendar 5.0 API support

* Formatting fixes

* Additional formatting fixes

* Final formatting fixes
  • Loading branch information
ncovercash authored Oct 25, 2022
1 parent 48e32cf commit 2a3c11e
Show file tree
Hide file tree
Showing 29 changed files with 673 additions and 725 deletions.
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 23.3.0 IN PROGRESS

* Upgrade `calendar` interface to `5.0`

## 23.2.0 2022-10-19

* Do not close the loan when Actual Cost Record is created (CIRC-1624)
Expand Down
16 changes: 8 additions & 8 deletions descriptors/ModuleDescriptor-template.json
Original file line number Diff line number Diff line change
Expand Up @@ -962,7 +962,7 @@
},
{
"id": "calendar",
"version": "3.0 4.0"
"version": "5.0"
},
{
"id": "patron-notice-policy-storage",
Expand Down Expand Up @@ -1363,7 +1363,7 @@
"proxiesfor.collection.get",
"patron-notice.post",
"configuration.entries.collection.get",
"calendar.opening-hours.collection.get",
"calendar.endpoint.dates.get",
"pubsub.publish.post"
],
"visible": false
Expand All @@ -1373,7 +1373,7 @@
"displayName" : "module permissions for one op",
"description" : "to reduce X-Okapi-Token size",
"subPermissions": [
"calendar.opening-hours.collection.get",
"calendar.endpoint.dates.get",
"circulation-storage.loans.item.post",
"circulation-storage.loans.item.get",
"circulation-storage.loans.collection.get",
Expand Down Expand Up @@ -1458,7 +1458,7 @@
"accounts.refund.post",
"accounts.cancel.post",
"configuration.entries.collection.get",
"calendar.opening-hours.collection.get"
"calendar.endpoint.dates.get"
],
"visible": false
},
Expand Down Expand Up @@ -1487,7 +1487,7 @@
"users.item.get",
"users.collection.get",
"proxiesfor.collection.get",
"calendar.opening-hours.collection.get",
"calendar.endpoint.dates.get",
"configuration.entries.collection.get",
"scheduled-notice-storage.scheduled-notices.collection.delete",
"scheduled-notice-storage.scheduled-notices.item.post",
Expand Down Expand Up @@ -1654,7 +1654,7 @@
"usergroups.item.get",
"proxiesfor.collection.get",
"patron-notice.post",
"calendar.opening-hours.collection.get",
"calendar.endpoint.dates.get",
"scheduled-notice-storage.scheduled-notices.collection.delete",
"scheduled-notice-storage.scheduled-notices.item.post",
"configuration.entries.collection.get",
Expand Down Expand Up @@ -1705,7 +1705,7 @@
"displayName": "module permissions for one op",
"description": "to reduce X-Okapi-Token size",
"subPermissions": [
"calendar.opening-hours.collection.get",
"calendar.endpoint.dates.get",
"circulation-storage.loan-policies.item.get",
"circulation-storage.loans.item.get",
"circulation-storage.loans.item.put",
Expand Down Expand Up @@ -1804,7 +1804,7 @@
"usergroups.item.get",
"proxiesfor.collection.get",
"patron-notice.post",
"calendar.opening-hours.collection.get",
"calendar.endpoint.dates.get",
"configuration.entries.collection.get",
"scheduled-notice-storage.scheduled-notices.collection.delete",
"scheduled-notice-storage.scheduled-notices.item.post",
Expand Down
28 changes: 14 additions & 14 deletions src/main/java/org/folio/circulation/AdjacentOpeningDays.java
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
package org.folio.circulation;

import java.util.Arrays;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.folio.circulation.domain.OpeningDay;

@Getter
@AllArgsConstructor
public class AdjacentOpeningDays {

private final OpeningDay previousDay;
private final OpeningDay requestedDay;
private final OpeningDay nextDay;

public AdjacentOpeningDays(OpeningDay previousDay, OpeningDay requestedDay, OpeningDay nextDay) {
this.previousDay = previousDay;
this.requestedDay = requestedDay;
this.nextDay = nextDay;
public static AdjacentOpeningDays createClosedOpeningDays() {
return new AdjacentOpeningDays(
OpeningDay.createClosedDay(),
OpeningDay.createClosedDay(),
OpeningDay.createClosedDay()
);
}

public OpeningDay getPreviousDay() {
return previousDay;
}

public OpeningDay getRequestedDay() {
return requestedDay;
}

public OpeningDay getNextDay() {
return nextDay;
public List<OpeningDay> toList() {
return Arrays.asList(this.getPreviousDay(), this.getRequestedDay(), this.getNextDay());
}
}
105 changes: 49 additions & 56 deletions src/main/java/org/folio/circulation/domain/OpeningDay.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
package org.folio.circulation.domain;

import static java.time.ZoneOffset.UTC;
import static java.util.Objects.requireNonNull;
import static org.folio.circulation.support.json.JsonObjectArrayPropertyFetcher.mapToList;
import static org.folio.circulation.support.json.JsonPropertyFetcher.getBooleanProperty;
import static org.folio.circulation.support.json.JsonPropertyFetcher.getLocalDateProperty;
import static org.folio.circulation.support.json.JsonPropertyWriter.write;
import static org.folio.circulation.support.utils.DateTimeUtil.atStartOfDay;

import java.time.LocalDate;
import java.time.ZoneId;
Expand All @@ -15,105 +13,100 @@
import java.util.List;
import java.util.stream.Collector;

import org.folio.circulation.support.utils.DateTimeUtil;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;

import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;

@Getter
@ToString
@AllArgsConstructor
public class OpeningDay {
public static OpeningDay createClosedDay() {
return createOpeningDay(Collections.emptyList(), null, true, false);
}

private static final String DATE_KEY = "date";
private static final String ALL_DAY_KEY = "allDay";
private static final String OPEN_KEY = "open";
private static final String OPENING_HOUR_KEY = "openingHour";
private static final String OPENING_DAY_KEY = "openingDay";

private final List<OpeningHour> openingHour;
private final LocalDate date;
private final boolean allDay;
private final boolean open;
private final ZonedDateTime dayWithTimeZone;

public static OpeningDay fromJsonByDefaultKey(JsonObject jsonObject) {
JsonObject openingDayJson = jsonObject.getJsonObject(OPENING_DAY_KEY);

requireNonNull(openingDayJson, "Json object cannot be null");

return new OpeningDay(fillOpeningDay(openingDayJson),
getLocalDateProperty(openingDayJson, DATE_KEY),
getBooleanProperty(openingDayJson, ALL_DAY_KEY),
getBooleanProperty(openingDayJson, OPEN_KEY), null);
}

public static OpeningDay fromOpeningPeriodJson(JsonObject openingPeriod, ZoneId zone) {
JsonObject openingDayJson = openingPeriod.getJsonObject(OPENING_DAY_KEY);

return createOpeningDay(fillOpeningDay(openingDayJson),
getLocalDateProperty(openingPeriod, DATE_KEY),
getBooleanProperty(openingDayJson, ALL_DAY_KEY),
getBooleanProperty(openingDayJson, OPEN_KEY), zone);
}

public static OpeningDay createOpeningDay(List<OpeningHour> openingHour, LocalDate date,
boolean allDay, boolean open) {

return new OpeningDay(openingHour, date, allDay, open, null);
}

public static OpeningDay createOpeningDay(List<OpeningHour> openingHour,
LocalDate date, boolean allDay, boolean open, ZoneId zone) {

return new OpeningDay(openingHour, date, allDay, open, atStartOfDay(date, zone));
}

public OpeningDay(List<OpeningHour> openingHour, LocalDate date,
boolean allDay, boolean open, ZonedDateTime dateWithTimeZone) {

public OpeningDay(List<OpeningHour> openingHour, LocalDate date, boolean allDay, boolean open) {
this.openingHour = openingHour;
this.date = date;
this.allDay = allDay;
this.open = open;
this.dayWithTimeZone = dateWithTimeZone;
this.dayWithTimeZone = null;
}

public LocalDate getDate() {
return date;
public OpeningDay(List<OpeningHour> openingHour, LocalDate date, boolean allDay,
boolean open, ZoneId zone) {
this(openingHour, date, allDay, open, DateTimeUtil.atStartOfDay(date, zone));
}

public ZonedDateTime getDayWithTimeZone() {
return dayWithTimeZone;
/**
* Construct an OpeningDay from the provided JSON object
*/
public OpeningDay(JsonObject jsonObject) {
this(
createOpeningTimes(jsonObject),
getLocalDateProperty(jsonObject, DATE_KEY),
getBooleanProperty(jsonObject, ALL_DAY_KEY),
getBooleanProperty(jsonObject, OPEN_KEY)
);
}

public boolean getAllDay() {
return allDay;
/**
* Construct an OpeningDay from the provided JSON object, with zoned date
*/
public OpeningDay(JsonObject jsonObject, ZoneId zone) {
this(
createOpeningTimes(jsonObject),
getLocalDateProperty(jsonObject, DATE_KEY),
getBooleanProperty(jsonObject, ALL_DAY_KEY),
getBooleanProperty(jsonObject, OPEN_KEY),
DateTimeUtil.atStartOfDay(getLocalDateProperty(jsonObject, DATE_KEY), zone)
);
}

public boolean getOpen() {
return open;
}

public List<OpeningHour> getOpeningHour() {
return openingHour;
public static OpeningDay createClosedDay() {
return new OpeningDay(Collections.emptyList(), null, true, false);
}

/**
* Convert the opening hours to JSON for re-packaging
*/
private JsonArray openingHourToJsonArray() {
return openingHour.stream()
.map(OpeningHour::toJson)
.collect(Collector.of(JsonArray::new, JsonArray::add, JsonArray::add));
}

/**
* Convert the opening information to JSON
*/
public JsonObject toJson() {
final var json = new JsonObject();

write(json, DATE_KEY, atStartOfDay(date, UTC));
write(json, DATE_KEY, DateTimeUtil.atStartOfDay(date, UTC));
write(json, ALL_DAY_KEY, allDay);
write(json, OPEN_KEY, open);
write(json, OPENING_HOUR_KEY, openingHourToJsonArray());

return json;
}

private static List<OpeningHour> fillOpeningDay(JsonObject representation) {
/**
* Create a list of {@link OpeningHour OpeningHour} from the provided daily opening object
*/
private static List<OpeningHour> createOpeningTimes(JsonObject representation) {
return mapToList(representation, OPENING_HOUR_KEY, OpeningHour::new);
}
}
25 changes: 9 additions & 16 deletions src/main/java/org/folio/circulation/domain/OpeningHour.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@
import java.time.LocalTime;

import io.vertx.core.json.JsonObject;
import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class OpeningHour {

private static final String START_TIME_KEY = "startTime";
Expand All @@ -14,22 +18,11 @@ public class OpeningHour {
private LocalTime startTime;
private LocalTime endTime;

OpeningHour(JsonObject jsonObject) {
this.startTime = LocalTime.parse(jsonObject.getString(START_TIME_KEY));
this.endTime = LocalTime.parse(jsonObject.getString(END_TIME_KEY));
}

public OpeningHour(LocalTime startTime, LocalTime endTime) {
this.startTime = startTime;
this.endTime = endTime;
}

public LocalTime getStartTime() {
return startTime;
}

public LocalTime getEndTime() {
return endTime;
public OpeningHour(JsonObject jsonObject) {
this(
LocalTime.parse(jsonObject.getString(START_TIME_KEY)),
LocalTime.parse(jsonObject.getString(END_TIME_KEY))
);
}

JsonObject toJson() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ private CompletableFuture<Result<Integer>> minutesOverdueExcludingClosedPeriods(
ZonedDateTime dueDate = loan.getDueDate();
String itemLocationPrimaryServicePoint = getItemLocationPrimaryServicePoint(loan).toString();
return calendarRepository
.fetchOpeningDaysBetweenDates(itemLocationPrimaryServicePoint, dueDate, returnDate, false)
.fetchOpeningDaysBetweenDates(itemLocationPrimaryServicePoint, dueDate, returnDate)
.thenApply(r -> r.next(openingDays -> getOpeningDaysDurationMinutes(
openingDays, dueDate, returnDate)));
}
Expand All @@ -75,7 +75,7 @@ Result<Integer> getOpeningDaysDurationMinutes(

return succeeded(
openingDays.stream()
.filter(OpeningDay::getOpen)
.filter(OpeningDay::isOpen)
.mapToInt(day -> getOpeningDayDurationMinutes(day, dueDate, returnDate))
.sum());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ public EndOfNextOpenDayStrategy(ZoneId zone) {
@Override
public Result<ZonedDateTime> calculateDueDate(ZonedDateTime requestedDate, AdjacentOpeningDays openingDays) {
Objects.requireNonNull(openingDays);
if (openingDays.getRequestedDay().getOpen()) {
if (openingDays.getRequestedDay().isOpen()) {
return succeeded(atEndOfDay(requestedDate, zone));
}
OpeningDay nextDay = openingDays.getNextDay();
if (!nextDay.getOpen()) {
if (!nextDay.isOpen()) {
return failed(failureForAbsentTimetable());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ public EndOfPreviousDayStrategy(ZoneId zone) {
@Override
public Result<ZonedDateTime> calculateDueDate(ZonedDateTime requestedDate, AdjacentOpeningDays openingDays) {
Objects.requireNonNull(openingDays);
if (openingDays.getRequestedDay().getOpen()) {
if (openingDays.getRequestedDay().isOpen()) {
return succeeded(atEndOfDay(requestedDate, zone));
}
OpeningDay previousDay = openingDays.getPreviousDay();
if (!previousDay.getOpen()) {
if (!previousDay.isOpen()) {
return failed(failureForAbsentTimetable());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public EndOfPreviousDayTruncateStrategy(ZoneId zone) {
public Result<ZonedDateTime> calculateDueDate(ZonedDateTime requestedDate, AdjacentOpeningDays openingDays) {
Objects.requireNonNull(openingDays);
OpeningDay previousDay = openingDays.getPreviousDay();
if (!previousDay.getOpen()) {
if (!previousDay.isOpen()) {
return failed(failureForAbsentTimetable());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,10 @@ private static Interval mergeIntervals(Interval first, Interval second) {
}

private static List<Interval> getOpenIntervalsForDay(OpeningDay day, ZoneId zone) {
if (!day.getOpen()) {
if (!day.isOpen()) {
return Collections.emptyList();
}
if (day.getAllDay()) {
if (day.isAllDay()) {
return Collections.singletonList(buildAllDayOpenInterval(day, zone));
}
return day.getOpeningHour().stream()
Expand Down
Loading

0 comments on commit 2a3c11e

Please sign in to comment.