Skip to content

Commit

Permalink
Merge branch 'deployment' into CIRC-2019
Browse files Browse the repository at this point in the history
  • Loading branch information
nielserik authored Apr 19, 2024
2 parents d71c399 + 9d70230 commit bc28ec2
Show file tree
Hide file tree
Showing 19 changed files with 568 additions and 86 deletions.
8 changes: 6 additions & 2 deletions descriptors/ModuleDescriptor-template.json
Original file line number Diff line number Diff line change
Expand Up @@ -1996,7 +1996,9 @@
"manualblocks.collection.get",
"pubsub.publish.post",
"automated-patron-blocks.collection.get",
"circulation-storage.loans-history.collection.get"
"circulation-storage.loans-history.collection.get",
"overdue-fines-policies.item.get",
"overdue-fines-policies.collection.get"
],
"visible": false
},
Expand Down Expand Up @@ -2291,7 +2293,9 @@
"pubsub.publish.post",
"configuration.entries.collection.get",
"patron-notice.post",
"circulation-storage.loans-history.collection.get"
"circulation-storage.loans-history.collection.get",
"overdue-fines-policies.item.get",
"overdue-fines-policies.collection.get"
],
"visible": false
},
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@
<url>https://github.com/folio-org/mod-inventory</url>
<connection>scm:git:git://github.com:folio-org/mod-inventory.git</connection>
<developerConnection>scm:git:git@github.com:folio-org/mod-inventory.git</developerConnection>
<tag>v24.2.0</tag>
<tag>HEAD</tag>
</scm>

<build>
Expand Down
1 change: 1 addition & 0 deletions src/main/java/org/folio/circulation/domain/Loan.java
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,7 @@ public FeeAmount getRemainingFeeFineAmount() {
public void closeLoanAsLostAndPaid() {
log.debug("closeLoanAsLostAndPaid:: ");
closeLoan(CLOSED_LOAN);
changeReturnDate(ClockUtil.getZonedDateTime());
changeItemStatusForItemAndLoan(ItemStatus.LOST_AND_PAID);
}

Expand Down
76 changes: 46 additions & 30 deletions src/main/java/org/folio/circulation/domain/policy/LoanPolicy.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
import static org.folio.circulation.support.json.JsonPropertyFetcher.getProperty;
import static org.folio.circulation.support.results.Result.succeeded;
import static org.folio.circulation.support.utils.DateTimeUtil.isAfterMillis;
import static org.folio.circulation.support.utils.LogUtil.resultAsString;

import java.lang.invoke.MethodHandles;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Collections;
Expand All @@ -20,8 +22,9 @@
import java.util.Optional;

import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.folio.circulation.domain.Loan;
import org.folio.circulation.domain.Request;
import org.folio.circulation.domain.RequestQueue;
import org.folio.circulation.domain.RequestStatus;
import org.folio.circulation.domain.RequestType;
Expand All @@ -37,6 +40,8 @@

@ToString(onlyExplicitlyIncluded = true)
public class LoanPolicy extends Policy {
private static final Logger log = LogManager.getLogger(MethodHandles.lookup().lookupClass());

private static final String LOANS_POLICY_KEY = "loansPolicy";
private static final String PERIOD_KEY = "period";

Expand Down Expand Up @@ -88,7 +93,8 @@ public static LoanPolicy unknown(String id) {

public Result<ZonedDateTime> calculateInitialDueDate(Loan loan, RequestQueue requestQueue) {
final ZonedDateTime systemTime = ClockUtil.getZonedDateTime();
return determineStrategy(requestQueue, false, false, systemTime).calculateDueDate(loan);
return determineStrategy(requestQueue, false, false, systemTime, loan.getItemId())
.calculateDueDate(loan);
}

public boolean hasRenewalPeriod() {
Expand Down Expand Up @@ -139,11 +145,8 @@ public Integer getRenewalLimit() {
return getIntegerProperty(getRenewalsPolicy(), "numberAllowed", 0);
}

public DueDateStrategy determineStrategy(
RequestQueue requestQueue,
boolean isRenewal,
boolean isRenewalWithHoldRequest,
ZonedDateTime systemDate) {
public DueDateStrategy determineStrategy(RequestQueue requestQueue, boolean isRenewal,
boolean isRenewalWithHoldRequest, ZonedDateTime systemDate, String itemId) {

final JsonObject loansPolicy = getLoansPolicy();
final JsonObject renewalsPolicy = getRenewalsPolicy();
Expand All @@ -163,7 +166,7 @@ systemDate, getRenewFrom(), getRenewalPeriod(loansPolicy, renewalsPolicy, isRene
else {
boolean useAlternatePeriod = false;
Period rollingPeriod = getPeriod(loansPolicy);
if(isAlternatePeriod(requestQueue)) {
if (isAlternatePeriod(requestQueue, itemId)) {
rollingPeriod = getPeriod(holds, ALTERNATE_CHECKOUT_LOAN_PERIOD_KEY);
useAlternatePeriod = true;
}
Expand All @@ -178,7 +181,7 @@ else if(isFixed(loansPolicy)) {
getRenewalFixedDueDateSchedules(), systemDate, this::loanPolicyValidationError);
}
else {
if(isAlternatePeriod(requestQueue)) {
if (isAlternatePeriod(requestQueue, itemId)) {
return new RollingCheckOutDueDateStrategy(getId(), getName(),
getPeriod(holds, ALTERNATE_CHECKOUT_LOAN_PERIOD_KEY),
fixedDueDateSchedules, this::loanPolicyValidationError, false);
Expand All @@ -199,23 +202,17 @@ private ValidationError loanPolicyValidationError(String message) {
return RenewalValidator.loanPolicyValidationError(this, message);
}

private boolean isAlternatePeriod(RequestQueue requestQueue) {
final JsonObject holds = getHolds();
if(Objects.isNull(requestQueue)
|| !holds.containsKey(ALTERNATE_CHECKOUT_LOAN_PERIOD_KEY)) {
private boolean isAlternatePeriod(RequestQueue requestQueue, String itemId) {
if (Objects.isNull(requestQueue) || !getHolds().containsKey(
ALTERNATE_CHECKOUT_LOAN_PERIOD_KEY)) {

return false;
}
Optional<Request> potentialRequest = requestQueue.getRequests().stream().skip(1).findFirst();
boolean isAlternateDueDateSchedule = false;
if(potentialRequest.isPresent()) {
Request request = potentialRequest.get();
boolean isHold = request.getRequestType() == RequestType.HOLD;
boolean isOpenNotYetFilled = request.getStatus() == RequestStatus.OPEN_NOT_YET_FILLED;
if(isHold && isOpenNotYetFilled) {
isAlternateDueDateSchedule = true;
}
}
return isAlternateDueDateSchedule;

return requestQueue.getRequests().stream()
.anyMatch(request -> request.getRequestType() == RequestType.HOLD &&
request.getStatus() == RequestStatus.OPEN_NOT_YET_FILLED &&
(!request.hasItem() || itemId.equals(request.getItemId())));
}

private JsonObject getLoansPolicy() {
Expand Down Expand Up @@ -470,16 +467,35 @@ private Result<ZonedDateTime> determineDueDate(Result<ZonedDateTime> minimumGuar

return minimumGuaranteedDueDateResult.combine(recallDueDateResult,
(minimumGuaranteedDueDate, recallDueDate) -> {
if (loan.isOverdue() && !allowRecallsToExtendOverdueLoans()) {
log.debug("determineDueDate:: parameters minimumGuaranteedDueDateResult: {}, " +
"recallDueDateResult: {}, loan: {}", () -> resultAsString(minimumGuaranteedDueDateResult),
() -> resultAsString(recallDueDateResult), () -> loan);

return loan.getDueDate();
ZonedDateTime currentDueDate = loan.getDueDate();

if (loan.isOverdue() && !allowRecallsToExtendOverdueLoans()) {
log.info("determineDueDate:: loan is overdue and allowRecallsToExtendOverdueLoans is " +
"disabled - keeping current due date");
return currentDueDate;
}

if (minimumGuaranteedDueDate == null ||
isAfterMillis(recallDueDate, minimumGuaranteedDueDate)) {
return recallDueDate;
if (isAfterMillis(recallDueDate, currentDueDate) && !allowRecallsToExtendOverdueLoans()) {
log.info("determineDueDate:: current due date is before recall due date and " +
"allowRecallsToExtendOverdueLoans is disabled - keeping current due date");
return currentDueDate;
} else {
return minimumGuaranteedDueDate;
if (minimumGuaranteedDueDate == null ||
isAfterMillis(recallDueDate, minimumGuaranteedDueDate)) {

log.info("determineDueDate:: minimum guaranteed period doesn't exist or recall due " +
"date is after minimum guaranteed due date - changing due date to recall due date");
return recallDueDate;
} else {
log.info("determineDueDate:: minimum guaranteed period exists and recall due " +
"date is before minimum guaranteed due date - changing due date to minimum " +
"guaranteed due date");
return minimumGuaranteedDueDate;
}
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -541,7 +541,8 @@ private Result<ZonedDateTime> calculateNewDueDate(ZonedDateTime overrideDueDate,

private Result<ZonedDateTime> calculateProposedDueDate(Loan loan, ZonedDateTime systemDate) {
return loan.getLoanPolicy()
.determineStrategy(null, true, false, systemDate).calculateDueDate(loan);
.determineStrategy(null, true, false, systemDate, loan.getItemId())
.calculateDueDate(loan);
}

private boolean newDueDateAfterCurrentDueDate(Loan loan, Result<ZonedDateTime> proposedDueDateResult) {
Expand Down Expand Up @@ -669,7 +670,7 @@ private Result<ZonedDateTime> calculateNewDueDate(Loan loan, RequestQueue reques
final var loanPolicy = loan.getLoanPolicy();
final var isRenewalWithHoldRequest = firstRequestForLoanedItemIsHold(requestQueue, loan);

return loanPolicy.determineStrategy(null, true, isRenewalWithHoldRequest, systemDate)
return loanPolicy.determineStrategy(null, true, isRenewalWithHoldRequest, systemDate, loan.getItemId())
.calculateDueDate(loan);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public CloseLoanWithLostItemService(LoanRepository loanRepository, ItemRepositor
}

public CompletableFuture<Result<Void>> closeLoanAsLostAndPaid(Loan loan) {
if (loan == null || !loan.isItemLost()) {
if (loan == null || loan.isClosed() || !loan.isItemLost()) {
return emptyAsync();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,10 @@
import org.folio.circulation.domain.FeeFine;
import org.folio.circulation.domain.FeeFineOwner;
import org.folio.circulation.domain.Loan;
import org.folio.circulation.domain.Location;
import org.folio.circulation.domain.policy.lostitem.LostItemPolicy;
import org.folio.circulation.domain.policy.lostitem.itemfee.AutomaticallyChargeableFee;
import org.folio.circulation.domain.representations.DeclareItemLostRequest;
import org.folio.circulation.infrastructure.storage.ActualCostRecordRepository;
import org.folio.circulation.infrastructure.storage.ServicePointRepository;
import org.folio.circulation.infrastructure.storage.feesandfines.FeeFineOwnerRepository;
import org.folio.circulation.infrastructure.storage.feesandfines.FeeFineRepository;
import org.folio.circulation.infrastructure.storage.inventory.IdentifierTypeRepository;
import org.folio.circulation.infrastructure.storage.inventory.LocationRepository;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@
import org.folio.circulation.infrastructure.storage.loans.LostItemPolicyRepository;
import org.folio.circulation.infrastructure.storage.users.PatronGroupRepository;
import org.folio.circulation.infrastructure.storage.users.UserRepository;
import org.folio.circulation.services.actualcostrecord.ActualCostRecordService;
import org.folio.circulation.services.EventPublisher;
import org.folio.circulation.services.FeeFineFacade;
import org.folio.circulation.services.actualcostrecord.ActualCostRecordService;
import org.folio.circulation.services.support.CreateAccountCommand;
import org.folio.circulation.support.Clients;
import org.folio.circulation.support.fetching.PageableFetcher;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.folio.circulation.domain.Loan;
import org.folio.circulation.domain.policy.Period;
import org.folio.circulation.services.agedtolost.LoanToChargeFees;
import org.folio.circulation.support.utils.ClockUtil;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

Expand All @@ -47,13 +48,17 @@ void shouldCloseLoanWhenAllFeesClosed() {
feeFineAccountFixture.payLostItemFee(loan.getId());
feeFineAccountFixture.payLostItemProcessingFee(loan.getId());

var returnDate = ClockUtil.getZonedDateTime();
mockClockManagerToReturnFixedDateTime(returnDate);
eventSubscribersFixture.publishLoanRelatedFeeFineClosedEvent(loan.getId());

assertThatLoanIsClosedAsLostAndPaid();
JsonObject loan = assertThatLoanIsClosedAsLostAndPaid();
assertThat(loan.getString("returnDate"), is(returnDate.toString()));
mockClockManagerToReturnDefaultDateTime();

List<JsonObject> loanClosedEvents = getPublishedEventsAsList(byEventType(LOAN_CLOSED));
assertThat(loanClosedEvents, hasSize(1));
assertThat(loanClosedEvents.get(0), isValidLoanClosedEvent(loan.getJson()));
assertThat(loanClosedEvents.get(0), isValidLoanClosedEvent(loan));
}

@Test
Expand Down Expand Up @@ -224,9 +229,15 @@ void shouldCloseLoanWhenActualCostRecordIsCancelled() {

item = result.getItem();
loan = result.getLoan();

var returnDate = ClockUtil.getZonedDateTime();
mockClockManagerToReturnFixedDateTime(returnDate);
cancelActualCostRecord();
eventSubscribersFixture.publishLoanRelatedFeeFineClosedEvent(loan.getId());

assertThatLoanIsClosedAsLostAndPaid();
JsonObject loan = assertThatLoanIsClosedAsLostAndPaid();
assertThat(loan.getString("returnDate"), is(returnDate.toString()));
mockClockManagerToReturnDefaultDateTime();
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.folio.circulation.domain.ItemStatus;
import org.folio.circulation.domain.policy.Period;
import org.folio.circulation.support.http.client.Response;
import org.folio.circulation.support.utils.ClockUtil;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

Expand Down Expand Up @@ -54,12 +55,17 @@ void shouldCloseLoanWhenAllFeesClosed() {
feeFineAccountFixture.payLostItemFee(loan.getId());
feeFineAccountFixture.payLostItemProcessingFee(loan.getId());

var returnDate = ClockUtil.getZonedDateTime();
mockClockManagerToReturnFixedDateTime(returnDate);
eventSubscribersFixture.publishLoanRelatedFeeFineClosedEvent(loan.getId());
assertThatLoanIsClosedAsLostAndPaid();

JsonObject loan = assertThatLoanIsClosedAsLostAndPaid();
assertThat(loan.getString("returnDate"), is(returnDate.toString()));
mockClockManagerToReturnDefaultDateTime();

List<JsonObject> loanClosedEvents = getPublishedEventsAsList(byEventType(LOAN_CLOSED));
assertThat(loanClosedEvents, hasSize(1));
assertThat(loanClosedEvents.get(0), isValidLoanClosedEvent(loan.getJson()));
assertThat(loanClosedEvents.get(0), isValidLoanClosedEvent(loan));
}

@Test
Expand Down Expand Up @@ -241,14 +247,8 @@ void shouldIgnoreErrorWhenNonExistentLoanIdProvided() {
void shouldNotPublishLoanClosedEventWhenLoanIsOriginallyClosed() {
feeFineAccountFixture.payLostItemFee(loan.getId());
feeFineAccountFixture.payLostItemProcessingFee(loan.getId());

JsonObject loanToClose = loansStorageClient.get(loan).getJson();
loanToClose.getJsonObject("status").put("name", "Closed");
loansStorageClient.replace(loan.getId(), loanToClose);

checkInFixture.checkInByBarcode(item);
eventSubscribersFixture.publishLoanRelatedFeeFineClosedEvent(loan.getId());
assertThatLoanIsClosedAsLostAndPaid();

assertThat(getPublishedEventsAsList(byEventType(LOAN_CLOSED)), empty());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import static api.support.matchers.LoanMatchers.isClosed;
import static api.support.matchers.LoanMatchers.isOpen;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertNotNull;

import java.time.ZonedDateTime;
import java.util.UUID;
Expand Down Expand Up @@ -78,9 +79,13 @@ protected void payLostItemActualCostFeeAndProcessingFeeAndCheckThatLoanIsClosed(
assertThatLoanIsClosedAsLostAndPaid();
}

protected void assertThatLoanIsClosedAsLostAndPaid() {
assertThat(loansFixture.getLoanById(loan.getId()).getJson(), isClosed());
protected JsonObject assertThatLoanIsClosedAsLostAndPaid() {
JsonObject loan = loansFixture.getLoanById(this.loan.getId()).getJson();
assertThat(loan, isClosed());
assertNotNull(loan.getString("returnDate"));
assertThat(itemsClient.getById(item.getId()).getJson(), isLostAndPaid());

return loan;
}

protected void assertThatLoanIsOpenAndLost() {
Expand Down
Loading

0 comments on commit bc28ec2

Please sign in to comment.