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

CIRC-1513 remove due date schedule notices after checkin #1121

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
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 @@ -26,7 +26,6 @@
import org.folio.circulation.infrastructure.storage.feesandfines.FeeFineRepository;
import org.folio.circulation.infrastructure.storage.inventory.ItemRepository;
import org.folio.circulation.infrastructure.storage.loans.OverdueFinePolicyRepository;
import org.folio.circulation.infrastructure.storage.notices.ScheduledNoticesRepository;
import org.folio.circulation.resources.context.RenewalContext;
import org.folio.circulation.services.FeeFineFacade;
import org.folio.circulation.services.support.CreateAccountCommand;
Expand All @@ -42,7 +41,6 @@ public class OverdueFineService {
private final ItemRepository itemRepository;
private final FeeFineOwnerRepository feeFineOwnerRepository;
private final FeeFineRepository feeFineRepository;
private final ScheduledNoticesRepository scheduledNoticesRepository;
private final OverduePeriodCalculatorService overduePeriodCalculatorService;
private final FeeFineFacade feeFineFacade;

Expand Down Expand Up @@ -208,10 +206,7 @@ private CompletableFuture<Result<FeeFineAction>> createFeeFineRecord(Loan loan,
.thenCompose(r -> r.after(this::lookupFeeFine))
.thenCompose(r -> r.after(this::lookupItemRelatedRecords))
.thenCompose(r -> r.after(this::lookupFeeFineOwner))
.thenCompose(r -> r.after(this::createAccount))
.thenCompose(r -> r.after(feeFineAction -> scheduledNoticesRepository
.deleteOverdueNotices(loan.getId())
.thenApply(rs -> r)));
.thenCompose(r -> r.after(this::createAccount));
}

private CompletableFuture<Result<FeeFineAction>> createAccount(CalculationParameters params) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package org.folio.circulation.resources;

import static org.folio.circulation.domain.notice.schedule.TriggeringEvent.DUE_DATE;
import static org.folio.circulation.domain.representations.CheckOutByBarcodeRequest.ITEM_BARCODE;
import static org.folio.circulation.domain.validation.UserNotFoundValidator.refuseWhenLoggedInUserNotPresent;
import static org.folio.circulation.support.ValidationErrorFailure.singleValidationError;

import org.folio.circulation.domain.CheckInContext;
import org.folio.circulation.domain.Item;
import org.folio.circulation.domain.Loan;
import org.folio.circulation.domain.notice.schedule.RequestScheduledNoticeService;
import org.folio.circulation.domain.notice.session.PatronActionSessionService;
import org.folio.circulation.domain.representations.CheckInByBarcodeRequest;
Expand All @@ -14,6 +16,7 @@
import org.folio.circulation.infrastructure.storage.ConfigurationRepository;
import org.folio.circulation.infrastructure.storage.inventory.ItemRepository;
import org.folio.circulation.infrastructure.storage.loans.LoanRepository;
import org.folio.circulation.infrastructure.storage.notices.ScheduledNoticesRepository;
import org.folio.circulation.infrastructure.storage.requests.RequestQueueRepository;
import org.folio.circulation.infrastructure.storage.requests.RequestRepository;
import org.folio.circulation.infrastructure.storage.sessions.PatronActionSessionRepository;
Expand All @@ -29,6 +32,8 @@
import io.vertx.ext.web.Router;
import io.vertx.ext.web.RoutingContext;

import java.util.Optional;

public class CheckInByBarcodeResource extends Resource {
public CheckInByBarcodeResource(HttpClient client) {
super(client);
Expand Down Expand Up @@ -65,6 +70,8 @@ private void checkIn(RoutingContext routingContext) {

final RequestScheduledNoticeService requestScheduledNoticeService =
RequestScheduledNoticeService.using(clients);
final ScheduledNoticesRepository scheduledNoticesRepository =
ScheduledNoticesRepository.using(clients);

final PatronActionSessionService patronActionSessionService =
PatronActionSessionService.using(clients,
Expand Down Expand Up @@ -94,6 +101,16 @@ private void checkIn(RoutingContext routingContext) {
processAdapter::findSingleOpenLoan, CheckInContext::withLoan))
.thenComposeAsync(findLoanResult -> findLoanResult.combineAfter(
processAdapter::checkInLoan, CheckInContext::withLoan))
.thenComposeAsync(r -> r.combineAfter(checkInContext -> {
String loanId = Optional.ofNullable(checkInContext)
.map(CheckInContext::getLoan)
.filter(Loan::isClosed)
.map(Loan::getId)
.orElse(null);
return scheduledNoticesRepository
.deleteByLoanIdAndTriggeringEvent(loanId, DUE_DATE);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extract method

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

},
(checkInContext, response) -> checkInContext))
.thenComposeAsync(checkInLoan -> checkInLoan.combineAfter(
processAdapter::updateRequestQueue, CheckInContext::withRequestQueue))
.thenComposeAsync(updateRequestQueueResult -> updateRequestQueueResult.combineAfter(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
package org.folio.circulation.resources;

import static java.util.concurrent.CompletableFuture.completedFuture;
import static org.folio.circulation.domain.RequestLevel.TITLE;
import static org.folio.circulation.support.results.Result.succeeded;

import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.folio.circulation.domain.CheckInContext;
Expand All @@ -29,7 +27,6 @@
import org.folio.circulation.infrastructure.storage.loans.LoanPolicyRepository;
import org.folio.circulation.infrastructure.storage.loans.LoanRepository;
import org.folio.circulation.infrastructure.storage.loans.OverdueFinePolicyRepository;
import org.folio.circulation.infrastructure.storage.notices.ScheduledNoticesRepository;
import org.folio.circulation.infrastructure.storage.requests.RequestQueueRepository;
import org.folio.circulation.infrastructure.storage.requests.RequestRepository;
import org.folio.circulation.infrastructure.storage.users.AddressTypeRepository;
Expand Down Expand Up @@ -108,7 +105,6 @@ public static CheckInProcessAdapter newInstance(Clients clients,
new OverdueFinePolicyRepository(clients), itemRepository,
new FeeFineOwnerRepository(clients),
new FeeFineRepository(clients),
ScheduledNoticesRepository.using(clients),
new OverduePeriodCalculatorService(new CalendarRepository(clients),
new LoanPolicyRepository(clients)),
new FeeFineFacade(clients));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@
import org.folio.circulation.infrastructure.storage.loans.LoanPolicyRepository;
import org.folio.circulation.infrastructure.storage.loans.LoanRepository;
import org.folio.circulation.infrastructure.storage.loans.OverdueFinePolicyRepository;
import org.folio.circulation.infrastructure.storage.notices.ScheduledNoticesRepository;
import org.folio.circulation.infrastructure.storage.requests.RequestQueueRepository;
import org.folio.circulation.infrastructure.storage.requests.RequestRepository;
import org.folio.circulation.infrastructure.storage.users.UserRepository;
Expand Down Expand Up @@ -246,7 +245,6 @@ private CompletableFuture<Result<RenewalContext>> processFeesFinesForRegularRene
itemRepository,
new FeeFineOwnerRepository(clients),
new FeeFineRepository(clients),
ScheduledNoticesRepository.using(clients),
new OverduePeriodCalculatorService(new CalendarRepository(clients),
new LoanPolicyRepository(clients)),
new FeeFineFacade(clients));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -583,14 +583,6 @@ void allDueDateNoticesAreDiscardedWhenLoanIsClosed() {

checkInFixture.checkInByBarcode(item);

verifyNumberOfScheduledNotices(5);

var processingTime = AFTER_RECURRING_PERIOD
.plusDate(AFTER_PERIOD.plusDate(dueDate))
.plusSeconds(1);

scheduledNoticeProcessingClient.runLoanNoticesProcessing(processingTime);

verifyNumberOfScheduledNotices(0);
verifyNumberOfSentNotices(0);
verifyNumberOfPublishedEvents(NOTICE, 0);
Expand Down
125 changes: 80 additions & 45 deletions src/test/java/api/loans/DueDateScheduledNoticesTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import static api.support.utl.BlockOverridesUtils.buildOkapiHeadersWithPermissions;
import static api.support.utl.PatronNoticeTestHelper.verifyNumberOfScheduledNotices;
import static java.time.ZoneOffset.UTC;
import static org.folio.circulation.domain.policy.Period.days;
import static org.folio.circulation.domain.policy.Period.hours;
import static org.folio.circulation.support.json.JsonPropertyFetcher.getDateTimeProperty;
import static org.hamcrest.CoreMatchers.hasItems;
import static org.hamcrest.MatcherAssert.assertThat;
Expand Down Expand Up @@ -40,42 +42,21 @@ class DueDateScheduledNoticesTests extends APITests {
@Test
void allDueDateNoticesShouldBeScheduledOnCheckoutWhenPolicyDefinesDueDateNoticeConfiguration() {
UUID beforeTemplateId = UUID.randomUUID();
Period beforePeriod = Period.days(2);
Period beforeRecurringPeriod = Period.hours(6);
Period beforePeriod = days(2);
Period beforeRecurringPeriod = hours(6);

UUID uponAtTemplateId = UUID.randomUUID();

UUID afterTemplateId = UUID.randomUUID();
Period afterPeriod = Period.days(3);
Period afterRecurringPeriod = Period.hours(4);

JsonObject beforeDueDateNoticeConfiguration = new NoticeConfigurationBuilder()
.withTemplateId(beforeTemplateId)
.withDueDateEvent()
.withBeforeTiming(beforePeriod)
.recurring(beforeRecurringPeriod)
.sendInRealTime(true)
.create();
JsonObject uponAtDueDateNoticeConfiguration = new NoticeConfigurationBuilder()
.withTemplateId(uponAtTemplateId)
.withDueDateEvent()
.withUponAtTiming()
.sendInRealTime(false)
.create();
JsonObject afterDueDateNoticeConfiguration = new NoticeConfigurationBuilder()
.withTemplateId(afterTemplateId)
.withDueDateEvent()
.withAfterTiming(afterPeriod)
.recurring(afterRecurringPeriod)
.sendInRealTime(true)
.create();
Period afterPeriod = days(3);
Period afterRecurringPeriod = hours(4);

NoticePolicyBuilder noticePolicy = new NoticePolicyBuilder()
.withName("Policy with due date notices")
.withLoanNotices(Arrays.asList(
beforeDueDateNoticeConfiguration,
uponAtDueDateNoticeConfiguration,
afterDueDateNoticeConfiguration));
createBeforeDueDateNoticeConfiguration(beforeTemplateId, beforePeriod, beforeRecurringPeriod, true),
createUponAtDueDateNoticeConfiguration(uponAtTemplateId, false),
createAfterDueDateNoticeConfiguration(afterTemplateId, afterPeriod, afterRecurringPeriod, true)));
use(noticePolicy);

IndividualResource smallAngryPlanet = itemsFixture.basedUponSmallAngryPlanet();
Expand Down Expand Up @@ -117,7 +98,7 @@ void checkOutSchedulesDifferentBeforeDueDateNotices() {
UUID firstBeforeTemplateId = UUID.randomUUID();
Period firstBeforePeriod = Period.weeks(1);
UUID secondBeforeTemplateId = UUID.randomUUID();
Period secondBeforePeriod = Period.hours(12);
Period secondBeforePeriod = hours(12);

JsonObject firstBeforeDueDateNoticeConfiguration = new NoticeConfigurationBuilder()
.withTemplateId(firstBeforeTemplateId)
Expand Down Expand Up @@ -211,14 +192,14 @@ void noNoticesShouldBeScheduledOnCheckOutWhenPolicyDoesNotDefineTimeBasedNotices
@Test
void noticesShouldBeRescheduledAfterRenewal() {
UUID beforeTemplateId = UUID.randomUUID();
Period beforePeriod = Period.days(2);
Period beforeRecurringPeriod = Period.hours(6);
Period beforePeriod = days(2);
Period beforeRecurringPeriod = hours(6);

UUID uponAtTemplateId = UUID.randomUUID();

UUID afterTemplateId = UUID.randomUUID();
Period afterPeriod = Period.days(3);
Period afterRecurringPeriod = Period.hours(4);
Period afterPeriod = days(3);
Period afterRecurringPeriod = hours(4);

JsonObject beforeDueDateNoticeConfiguration = new NoticeConfigurationBuilder()
.withTemplateId(beforeTemplateId)
Expand Down Expand Up @@ -286,14 +267,14 @@ void noticesShouldBeRescheduledAfterRenewal() {
@Test
void noticesShouldBeRescheduledAfterRenewalOverride() {
UUID beforeTemplateId = UUID.randomUUID();
Period beforePeriod = Period.days(2);
Period beforeRecurringPeriod = Period.hours(6);
Period beforePeriod = days(2);
Period beforeRecurringPeriod = hours(6);

UUID uponAtTemplateId = UUID.randomUUID();

UUID afterTemplateId = UUID.randomUUID();
Period afterPeriod = Period.days(3);
Period afterRecurringPeriod = Period.hours(4);
Period afterPeriod = days(3);
Period afterRecurringPeriod = hours(4);

JsonObject beforeDueDateNoticeConfiguration = new NoticeConfigurationBuilder()
.withTemplateId(beforeTemplateId)
Expand Down Expand Up @@ -369,14 +350,14 @@ void noticesShouldBeRescheduledAfterRenewalOverride() {
@Test
void noticesShouldBeRescheduledAfterRecall() {
UUID beforeTemplateId = UUID.randomUUID();
Period beforePeriod = Period.days(2);
Period beforeRecurringPeriod = Period.hours(6);
Period beforePeriod = days(2);
Period beforeRecurringPeriod = hours(6);

UUID uponAtTemplateId = UUID.randomUUID();

UUID afterTemplateId = UUID.randomUUID();
Period afterPeriod = Period.days(3);
Period afterRecurringPeriod = Period.hours(4);
Period afterPeriod = days(3);
Period afterRecurringPeriod = hours(4);

JsonObject beforeDueDateNoticeConfiguration = new NoticeConfigurationBuilder()
.withTemplateId(beforeTemplateId)
Expand Down Expand Up @@ -454,14 +435,14 @@ void noticesShouldBeRescheduledAfterRecall() {
@Test
void noticesShouldBeRescheduledAfterManualDueDateChange() {
UUID beforeTemplateId = UUID.randomUUID();
Period beforePeriod = Period.days(2);
Period beforeRecurringPeriod = Period.hours(6);
Period beforePeriod = days(2);
Period beforeRecurringPeriod = hours(6);

UUID uponAtTemplateId = UUID.randomUUID();

UUID afterTemplateId = UUID.randomUUID();
Period afterPeriod = Period.days(3);
Period afterRecurringPeriod = Period.hours(4);
Period afterPeriod = days(3);
Period afterRecurringPeriod = hours(4);

JsonObject beforeDueDateNoticeConfiguration = new NoticeConfigurationBuilder()
.withTemplateId(beforeTemplateId)
Expand Down Expand Up @@ -529,4 +510,58 @@ void noticesShouldBeRescheduledAfterManualDueDateChange() {
verifyNumberOfScheduledNotices(6);
}

@Test
void allDueDateNoticesShouldBeDeletedAfternCheckin() {
IndividualResource smallAngryPlanet = itemsFixture.basedUponSmallAngryPlanet();
NoticePolicyBuilder noticePolicy = new NoticePolicyBuilder()
.withName("Policy with due date notices")
.withLoanNotices(Arrays.asList(
createBeforeDueDateNoticeConfiguration(UUID.randomUUID(), days(2), hours(6), true),
createUponAtDueDateNoticeConfiguration(UUID.randomUUID(), false),
createAfterDueDateNoticeConfiguration(UUID.randomUUID(), days(3), hours(4), false)));

useWithNoOverdueFine(noticePolicy);

checkOutFixture.checkOutByBarcode(
smallAngryPlanet,
usersFixture.steve());

verifyNumberOfScheduledNotices(3);
checkInFixture.checkInByBarcode(smallAngryPlanet);
verifyNumberOfScheduledNotices(0);
}

private JsonObject createBeforeDueDateNoticeConfiguration(UUID templateId, Period beforePeriod,
Period beforeRecurringPeriod, boolean realTime) {

return new NoticeConfigurationBuilder()
.withTemplateId(templateId)
.withDueDateEvent()
.withBeforeTiming(beforePeriod)
.recurring(beforeRecurringPeriod)
.sendInRealTime(realTime)
.create();
}

private JsonObject createUponAtDueDateNoticeConfiguration(UUID templateId, boolean realTime) {
return new NoticeConfigurationBuilder()
.withTemplateId(templateId)
.withDueDateEvent()
.withUponAtTiming()
.sendInRealTime(realTime)
.create();
}

private JsonObject createAfterDueDateNoticeConfiguration(UUID templateId, Period afterPeriod,
Period afterRecurringPeriod, boolean realTime) {

return new NoticeConfigurationBuilder()
.withTemplateId(templateId)
.withDueDateEvent()
.withAfterTiming(afterPeriod)
.recurring(afterRecurringPeriod)
.sendInRealTime(realTime)
.create();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,20 @@ public void use(NoticePolicyBuilder noticePolicy) {
.noticePolicy(noticePoliciesFixture.create(noticePolicy)));
}

/**
* This method uses notice policy, canCirculateRolling loan policy,
* allowAllRequestPolicy request policy,
* noOverdueFine overdue fine policy from
* the loanPolicyBuilder.
*
* @param noticePolicy - notice policy.
*/
public void useWithNoOverdueFine(NoticePolicyBuilder noticePolicy) {
use(defaultRollingPolicies()
.overduePolicy(overdueFinePoliciesFixture.noOverdueFine())
.noticePolicy(noticePoliciesFixture.create(noticePolicy)));
}

public void useLostItemPolicy(UUID lostItemFeePolicyId) {
final PoliciesToActivate policies = defaultRollingPolicies().build();

Expand Down
Loading