Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Split item status enum CIRC-1416 #1124

Draft
wants to merge 27 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
3ffef5e
Remove location ID fields from item CIRC-1416
marcjohnson-kint Mar 16, 2022
25f4564
Duplicate item status enumeration CIRC-1416
marcjohnson-kint Apr 1, 2022
fb8b8ec
Use status name when checking whether item is in a status CIRC-1416
marcjohnson-kint Apr 1, 2022
dbd9a00
Use status name when checking whether loaned item is in a status CIRC…
marcjohnson-kint Apr 1, 2022
3542103
Use status name when validating CIRC-1416
marcjohnson-kint Apr 1, 2022
826c3bb
Use status name when changing status CIRC-1416
marcjohnson-kint Apr 1, 2022
43c566c
Use status name when changing status within a loan CIRC-1416
marcjohnson-kint Apr 1, 2022
4fed98b
Use status name when changing status related to a request CIRC-1416
marcjohnson-kint Apr 1, 2022
363f927
Use status name when checking request type CIRC-1416
marcjohnson-kint Apr 1, 2022
b28aee7
Use status name during renewal CIRC-1416
marcjohnson-kint Apr 1, 2022
c46aec3
Use status name in renewal tests CIRC-1416
marcjohnson-kint Apr 1, 2022
b94171b
Remove string value from item status enum CIRC-1416
marcjohnson-kint Apr 1, 2022
40dd5ff
Remove usage of item status enum constants CIRC-1416
marcjohnson-kint Apr 1, 2022
783733c
Change item status to value object rather than enum CIRC-1416
marcjohnson-kint Apr 1, 2022
d6cda08
Inline comparing status name by value CIRC-1416
marcjohnson-kint Apr 4, 2022
954fb17
Improve diagnostics of regular renewal test CIRC-1416
marcjohnson-kint Apr 4, 2022
72ae48e
Disallow null item for loan and request CIRC-1416
marcjohnson-kint Apr 4, 2022
2bce834
Return new instance when changing loan CIRC-1416
marcjohnson-kint Apr 4, 2022
5270545
Check parameter rather than mutated item status CIRC-1416
marcjohnson-kint Apr 4, 2022
a0d86cd
Make sure loan is passed through when publishing closed loan event CI…
marcjohnson-kint Apr 5, 2022
ba4c6e5
Return new item when changing status CIRC-1416
marcjohnson-kint Apr 4, 2022
3652fff
Use explicit status when declaring item lost CIRC-1416
marcjohnson-kint Apr 4, 2022
f8a8082
Introduce item status field CIRC-1416
marcjohnson-kint Apr 5, 2022
6f93ad7
Remove item JSON representation CIRC-1416
marcjohnson-kint Apr 5, 2022
23727e1
Move last check in property constant to method CIRC-1416
marcjohnson-kint May 10, 2022
24a21f9
Remove unused method in item repository CIRC-1416
marcjohnson-kint May 10, 2022
b870971
Replace explicit constructor with generated CIRC-1416
marcjohnson-kint May 10, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,29 @@
import java.util.Optional;

import io.vertx.core.json.JsonObject;
import lombok.Value;

@Value
public class CallNumberComponents {
private final String callNumber;
private final String prefix;
private final String suffix;
String callNumber;
String prefix;
String suffix;

public static CallNumberComponents unknown() {
return new CallNumberComponents(null, null, null);
}

private CallNumberComponents(String callNumber, String prefix, String suffix) {
this.callNumber = callNumber;
this.prefix = prefix;
this.suffix = suffix;
}

public String getCallNumber() {
return callNumber;
}

public String getPrefix() {
return prefix;
}

public String getSuffix() {
return suffix;
}

private static CallNumberComponents fromJson(JsonObject callNumberComponents) {
return new CallNumberComponents(
getProperty(callNumberComponents, "callNumber"),
getProperty(callNumberComponents, "prefix"),
getProperty(callNumberComponents, "suffix")
);
getProperty(callNumberComponents, "suffix"));
}

/**
Expand All @@ -45,11 +38,11 @@ private static CallNumberComponents fromJson(JsonObject callNumberComponents) {
*/
public static CallNumberComponents fromItemJson(JsonObject itemJson) {
if (itemJson == null) {
return null;
return unknown();
}

return Optional.ofNullable(itemJson.getJsonObject("effectiveCallNumberComponents"))
.map(CallNumberComponents::fromJson)
.orElse(null);
.orElse(unknown());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.folio.circulation.support.utils.ClockUtil;

import lombok.AllArgsConstructor;
import lombok.NonNull;

/**
* The loan captures a snapshot of the item status
Expand Down Expand Up @@ -54,7 +55,7 @@ public CheckInContext withTlrSettings(TlrSettingsConfiguration tlrSettingsConfig
this.itemStatusBeforeCheckIn);
}

public CheckInContext withItem(Item item) {
public CheckInContext withItem(@NonNull Item item) {

//When the item is updated, also update the item for the loan,
//as they should be the same
Expand Down
177 changes: 80 additions & 97 deletions src/main/java/org/folio/circulation/domain/Item.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
package org.folio.circulation.domain;

import static org.apache.commons.lang3.StringUtils.firstNonBlank;
import static org.folio.circulation.domain.ItemStatus.AVAILABLE;
import static org.folio.circulation.domain.ItemStatus.AWAITING_PICKUP;
import static org.folio.circulation.domain.ItemStatus.CHECKED_OUT;
import static org.folio.circulation.domain.ItemStatus.CLAIMED_RETURNED;
import static org.folio.circulation.domain.ItemStatus.DECLARED_LOST;
import static org.folio.circulation.domain.ItemStatus.IN_TRANSIT;
import static org.folio.circulation.domain.ItemStatus.MISSING;
import static org.folio.circulation.domain.ItemStatus.PAGED;
import static org.folio.circulation.domain.representations.ItemProperties.STATUS_PROPERTY;
import static org.folio.circulation.support.json.JsonPropertyFetcher.getNestedStringProperty;
import static org.folio.circulation.support.json.JsonPropertyWriter.write;
import static org.folio.circulation.domain.ItemStatusName.AVAILABLE;
import static org.folio.circulation.domain.ItemStatusName.AWAITING_PICKUP;
import static org.folio.circulation.domain.ItemStatusName.CHECKED_OUT;
import static org.folio.circulation.domain.ItemStatusName.CLAIMED_RETURNED;
import static org.folio.circulation.domain.ItemStatusName.DECLARED_LOST;
import static org.folio.circulation.domain.ItemStatusName.IN_TRANSIT;
import static org.folio.circulation.domain.ItemStatusName.MISSING;
import static org.folio.circulation.domain.ItemStatusName.PAGED;

import java.util.Collection;
import java.util.Optional;
Expand All @@ -21,50 +18,41 @@
import org.folio.circulation.storage.mappers.ItemMapper;

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

@AllArgsConstructor
public class Item {
private final String id;
private final JsonObject itemRepresentation;
@NonNull private final Location location;
private final LastCheckIn lastCheckIn;
private final CallNumberComponents callNumberComponents;
@NonNull private final Location permanentLocation;
private final ServicePoint inTransitDestinationServicePoint;

private boolean changed;

private final boolean changed;
@NonNull private final Holdings holdings;
@NonNull private final Instance instance;
@NonNull private final MaterialType materialType;
@NonNull private final LoanType loanType;
@NonNull private final ItemDescription description;
@NonNull private final ItemStatus status;

public static Item from(JsonObject representation) {
return new ItemMapper().toDomain(representation);
public static Item unknown() {
return unknown(null);
}
public Item(String id, JsonObject itemRepresentation, Location effectiveLocation,
LastCheckIn lastCheckIn, CallNumberComponents callNumberComponents,
Location permanentLocation, ServicePoint inTransitDestinationServicePoint,
boolean changed, Holdings holdings, Instance instance,
MaterialType materialType, LoanType loanType,
ItemDescription description) {

this.id = id;
this.itemRepresentation = itemRepresentation;
this.location = effectiveLocation;
this.lastCheckIn = lastCheckIn;
this.callNumberComponents = callNumberComponents;
this.permanentLocation = permanentLocation;
this.inTransitDestinationServicePoint = inTransitDestinationServicePoint;
this.changed = changed;
this.holdings = holdings;
this.instance = instance;
this.materialType = materialType;
this.loanType = loanType;
this.description = description;

public static Item unknown(String id) {
return new Item(id, Location.unknown(), LastCheckIn.unknown(),
CallNumberComponents.unknown(), Location.unknown(), ServicePoint.unknown(),
false, Holdings.unknown(), Instance.unknown(),
MaterialType.unknown(), LoanType.unknown(), ItemDescription.unknown(),
ItemStatus.unknown());
}

public static Item from(JsonObject representation) {
return new ItemMapper().toDomain(representation);
}

public boolean isCheckedOut() {
return isInStatus(CHECKED_OUT);
}
Expand All @@ -89,24 +77,16 @@ public boolean isAvailable() {
return isInStatus(AVAILABLE);
}

private boolean isInTransit() {
return isInStatus(IN_TRANSIT);
}

public boolean isDeclaredLost() {
return isInStatus(DECLARED_LOST);
}

boolean isNotSameStatus(ItemStatus prospectiveStatus) {
return !isInStatus(prospectiveStatus);
public boolean isInStatus(ItemStatusName status) {
return getStatus().is(status);
}

public boolean isInStatus(ItemStatus status) {
return getStatus().equals(status);
}

public boolean isNotInStatus(ItemStatus status) {
return !isInStatus(status);
public boolean isNotInStatus(ItemStatusName status) {
return !getStatus().is(status);
}

public boolean hasChanged() {
Expand Down Expand Up @@ -166,15 +146,11 @@ public CallNumberComponents getCallNumberComponents() {
}

public ItemStatus getStatus() {
return ItemStatus.from(getStatusName(), getStatusDate());
return status;
}

public String getStatusName() {
return getNestedStringProperty(itemRepresentation, STATUS_PROPERTY, "name");
}

private String getStatusDate() {
return getNestedStringProperty(itemRepresentation, STATUS_PROPERTY, "date");
return status.getName().getName();
}

public Location getLocation() {
Expand Down Expand Up @@ -261,25 +237,22 @@ public String getPermanentLocationName() {
return "";
}

public Item changeStatus(ItemStatus newStatus) {
if (isNotSameStatus(newStatus)) {
changed = true;
}
public Item changeStatus(ItemStatusName newStatus) {
final var newChanged = isNotInStatus(newStatus);

write(itemRepresentation, STATUS_PROPERTY,
new JsonObject().put("name", newStatus.getValue()));
final var destinationServicePoint = newStatus == IN_TRANSIT
? this.inTransitDestinationServicePoint
: null;

//TODO: Remove this hack to remove destination service point
// needs refactoring of how in transit for pickup is done
if(!isInTransit()) {
return removeDestination();
}
else {
return this;
}
// The previous code did not change the item status date
// that behaviour has been preserved even though it is confusing
return new Item(this.id, this.location, this.lastCheckIn,
this.callNumberComponents, this.permanentLocation,
destinationServicePoint, newChanged, this.holdings,
this.instance, this.materialType, this.loanType, this.description,
new ItemStatus(newStatus, status.getDate()));
}


Item available() {
return changeStatus(AVAILABLE)
.removeDestination();
Expand Down Expand Up @@ -320,7 +293,10 @@ public boolean isNotFound() {
}

public boolean isFound() {
return itemRepresentation != null;
// this relies on items that are completely unknown are defined without an ID
// this might not represent the case where an item's ID is known yet that
// record could not be found / fetched
return id != null;
}

public LastCheckIn getLastCheckIn() {
Expand All @@ -331,59 +307,66 @@ public String getPermanentLocationId() {
return firstNonBlank(permanentLocation.getId(), holdings.getPermanentLocationId());
}

public Item withLocation(Location newLocation) {
return new Item(this.id, this.itemRepresentation, newLocation,
this.lastCheckIn, this.callNumberComponents, this.permanentLocation,
public Item withLocation(@NonNull Location newLocation) {
return new Item(this.id, newLocation, this.lastCheckIn,
this.callNumberComponents, this.permanentLocation,
this.inTransitDestinationServicePoint, this.changed, this.holdings,
this.instance, this.materialType, this.loanType, description);
this.instance, this.materialType, this.loanType, this.description,
this.status);
}

public Item withMaterialType(@NonNull MaterialType materialType) {
return new Item(this.id, this.itemRepresentation, this.location,
this.lastCheckIn, this.callNumberComponents, this.permanentLocation,
return new Item(this.id, this.location, this.lastCheckIn,
this.callNumberComponents, this.permanentLocation,
this.inTransitDestinationServicePoint, this.changed, this.holdings,
this.instance, materialType, this.loanType, this.description);
this.instance, materialType, this.loanType, this.description,
this.status);
}

public Item withHoldings(@NonNull Holdings holdings) {
return new Item(this.id, this.itemRepresentation, this.location,
this.lastCheckIn, this.callNumberComponents, this.permanentLocation,
return new Item(this.id, this.location, this.lastCheckIn,
this.callNumberComponents, this.permanentLocation,
this.inTransitDestinationServicePoint, this.changed, holdings,
this.instance, this.materialType, this.loanType, this.description);
this.instance, this.materialType, this.loanType, this.description,
this.status);
}

public Item withInstance(@NonNull Instance instance) {
return new Item(this.id, this.itemRepresentation, this.location,
this.lastCheckIn, this.callNumberComponents, this.permanentLocation,
return new Item(this.id, this.location, this.lastCheckIn,
this.callNumberComponents, this.permanentLocation,
this.inTransitDestinationServicePoint, this.changed, this.holdings,
instance, this.materialType, this.loanType, this.description);
instance, this.materialType, this.loanType, this.description,
this.status);
}

public Item withLoanType(@NonNull LoanType loanType) {
return new Item(this.id, this.itemRepresentation, this.location,
this.lastCheckIn, this.callNumberComponents, this.permanentLocation,
return new Item(this.id, this.location, this.lastCheckIn,
this.callNumberComponents, this.permanentLocation,
this.inTransitDestinationServicePoint, this.changed, this.holdings,
this.instance, this.materialType, loanType, this.description);
this.instance, this.materialType, loanType, this.description,
this.status);
}

public Item withLastCheckIn(@NonNull LastCheckIn lastCheckIn) {
return new Item(this.id, this.itemRepresentation, this.location,
lastCheckIn, this.callNumberComponents, this.permanentLocation,
return new Item(this.id, this.location, lastCheckIn,
this.callNumberComponents, this.permanentLocation,
this.inTransitDestinationServicePoint, this.changed, this.holdings,
this.instance, this.materialType, this.loanType, this.description);
this.instance, this.materialType, this.loanType, this.description,
this.status);
}

public Item withPermanentLocation(Location permanentLocation) {
return new Item(this.id, this.itemRepresentation, this.location,
this.lastCheckIn, this.callNumberComponents, permanentLocation,
public Item withPermanentLocation(@NonNull Location permanentLocation) {
return new Item(this.id, this.location, this.lastCheckIn,
this.callNumberComponents, permanentLocation,
this.inTransitDestinationServicePoint, this.changed, this.holdings,
this.instance, this.materialType, this.loanType, this.description);
this.instance, this.materialType, this.loanType, this.description,
this.status);
}

public Item withInTransitDestinationServicePoint(ServicePoint servicePoint) {
return new Item(this.id, this.itemRepresentation, this.location,
this.lastCheckIn, this.callNumberComponents, this.permanentLocation,
return new Item(this.id, this.location, this.lastCheckIn,
this.callNumberComponents, this.permanentLocation,
servicePoint, this.changed, this.holdings, this.instance,
this.materialType, this.loanType, this.description);
this.materialType, this.loanType, this.description, this.status);
}
}
Loading