diff --git a/README.md b/README.md index bde31087..ba736ea1 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ Version 2.0. See the file "[LICENSE](LICENSE)" for more information. - [Issue tracker](#issue-tracker) - [API documentation](#api-documentation) - [Code analysis](#code-analysis) + - [Service point hold shelf period expiration](#service-point-hold-shelf-period-expiration) - [Other documentation](#other-documentation) ## Introduction @@ -113,6 +114,74 @@ This module's [API documentation](https://dev.folio.org/reference/api/#mod-dcb). ### Code analysis +### Service Point Hold Shelf Period Expiration + +When creating a **DCB** transaction with the roles **LENDER** or **BORROWING-PICKUP**, +the creation of the **DCB** service point and its property **hold shelf expiration period** +depends on the values stored in the `service_point_expiration_period` table in the database. + +- If the table is empty, the **hold shelf expiration period** will be set to the default value of **10 Days**. +- If the table contains a value, the stored value will be used instead. + +The **F.S.E. team** is responsible for updating the values in this table. +To update the values, the following PL/pgSQL script can be executed: + +```sql +DO +$$ +DECLARE + schema_name TEXT; + new_duration INTEGER := 3; -- Duration in weeks + new_interval_id interval_id := 'Weeks'; -- Interval type + raw_id UUID; + sql_query TEXT; +BEGIN + FOR schema_name IN + SELECT schemaname + FROM pg_tables + WHERE tablename = 'service_point_expiration_period' + LOOP + -- Select a single ID into raw_id dynamically + sql_query := format( + 'SELECT id FROM %I.service_point_expiration_period LIMIT 1', + schema_name + ); + EXECUTE sql_query INTO raw_id; + + -- If no record exists, insert one; otherwise, update the existing record + IF raw_id IS NULL THEN + sql_query := format( + 'INSERT INTO %I.service_point_expiration_period (id, duration, interval_id) + VALUES (gen_random_uuid(), %L, %L)', + schema_name, new_duration, new_interval_id + ); + ELSE + sql_query := format( + 'UPDATE %I.service_point_expiration_period + SET duration = %L, interval_id = %L + WHERE id = %L', + schema_name, new_duration, new_interval_id, raw_id + ); + END IF; + + -- Execute the query + EXECUTE sql_query; + END LOOP; +END; +$$ +LANGUAGE plpgsql; +``` +**Updating Values in the Table** +To update the values, simply modify the new_duration and new_interval_id variables in the DECLARE section +of the script to reflect the new values. + +**Expiration Period Handling** +For Existing Service Points +When creating a new transaction with an existing DCB service point, the hold shelf expiration period +will be checked. +If the value in the transaction payload differs from the value stored +in the database, it will be updated accordingly. + [SonarQube analysis](https://sonarcloud.io/project/overview?id=org.folio:mod-dcb). ## Other documentation diff --git a/descriptors/ModuleDescriptor-template.json b/descriptors/ModuleDescriptor-template.json index 49dd4b03..f6ba0d24 100644 --- a/descriptors/ModuleDescriptor-template.json +++ b/descriptors/ModuleDescriptor-template.json @@ -91,6 +91,7 @@ "modulePermissions": [ "inventory-storage.service-points.item.post", "inventory-storage.service-points.collection.get", + "inventory-storage.service-points.item.put", "users.collection.get", "users.item.post", "usergroups.collection.get", @@ -233,6 +234,7 @@ "inventory-storage.holdings.item.post", "inventory-storage.locations.item.post", "inventory-storage.service-points.item.post", + "inventory-storage.service-points.item.put", "inventory-storage.location-units.libraries.collection.get", "inventory-storage.loan-types.collection.get", "inventory-storage.loan-types.collection.post", diff --git a/src/main/java/org/folio/dcb/client/feign/InventoryServicePointClient.java b/src/main/java/org/folio/dcb/client/feign/InventoryServicePointClient.java index 0cc9403a..f494289f 100644 --- a/src/main/java/org/folio/dcb/client/feign/InventoryServicePointClient.java +++ b/src/main/java/org/folio/dcb/client/feign/InventoryServicePointClient.java @@ -7,11 +7,15 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; @FeignClient(name = "service-points", configuration = FeignClientConfiguration.class) public interface InventoryServicePointClient { + @PutMapping("/{servicepointId}") + void updateServicePointById(@PathVariable ("servicepointId") String servicePointId, + @RequestBody ServicePointRequest servicePointRequest); @PostMapping ServicePointRequest createServicePoint(@RequestBody ServicePointRequest pickupServicePoint); @GetMapping("?query=name=={name}") diff --git a/src/main/java/org/folio/dcb/domain/converter/IntervalIdEnumConverter.java b/src/main/java/org/folio/dcb/domain/converter/IntervalIdEnumConverter.java new file mode 100644 index 00000000..1235504b --- /dev/null +++ b/src/main/java/org/folio/dcb/domain/converter/IntervalIdEnumConverter.java @@ -0,0 +1,23 @@ +package org.folio.dcb.domain.converter; + +import java.util.Arrays; + +import org.folio.dcb.domain.dto.IntervalIdEnum; + +import jakarta.persistence.AttributeConverter; + +public class IntervalIdEnumConverter implements AttributeConverter { + + @Override + public String convertToDatabaseColumn(IntervalIdEnum intervalIdEnum) { + return intervalIdEnum.getValue(); + } + + @Override + public IntervalIdEnum convertToEntityAttribute(String str) { + return Arrays.stream(IntervalIdEnum.values()) + .filter(value -> value.getValue().equals(str)) + .findFirst() + .orElse(null); + } +} diff --git a/src/main/java/org/folio/dcb/domain/entity/ServicePointExpirationPeriodEntity.java b/src/main/java/org/folio/dcb/domain/entity/ServicePointExpirationPeriodEntity.java new file mode 100644 index 00000000..c6265b5b --- /dev/null +++ b/src/main/java/org/folio/dcb/domain/entity/ServicePointExpirationPeriodEntity.java @@ -0,0 +1,37 @@ +package org.folio.dcb.domain.entity; + +import java.io.Serializable; +import java.util.UUID; + +import org.folio.dcb.domain.converter.IntervalIdEnumConverter; +import org.folio.dcb.domain.dto.IntervalIdEnum; + +import jakarta.persistence.Convert; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +@Entity +@Table(name = "service_point_expiration_period") +@Getter +@Setter +@ToString +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class ServicePointExpirationPeriodEntity implements Serializable { + @Id + @GeneratedValue(strategy = GenerationType.UUID) + private UUID id; + private Integer duration; + @Convert(converter = IntervalIdEnumConverter.class) + private IntervalIdEnum intervalId; +} diff --git a/src/main/java/org/folio/dcb/repository/ServicePointExpirationPeriodRepository.java b/src/main/java/org/folio/dcb/repository/ServicePointExpirationPeriodRepository.java new file mode 100644 index 00000000..8eaccc0b --- /dev/null +++ b/src/main/java/org/folio/dcb/repository/ServicePointExpirationPeriodRepository.java @@ -0,0 +1,10 @@ +package org.folio.dcb.repository; + +import org.folio.dcb.domain.entity.ServicePointExpirationPeriodEntity; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface ServicePointExpirationPeriodRepository extends + JpaRepository { +} diff --git a/src/main/java/org/folio/dcb/service/ServicePointExpirationPeriodService.java b/src/main/java/org/folio/dcb/service/ServicePointExpirationPeriodService.java new file mode 100644 index 00000000..107fe9ac --- /dev/null +++ b/src/main/java/org/folio/dcb/service/ServicePointExpirationPeriodService.java @@ -0,0 +1,7 @@ +package org.folio.dcb.service; + +import org.folio.dcb.domain.dto.HoldShelfExpiryPeriod; + +public interface ServicePointExpirationPeriodService { + HoldShelfExpiryPeriod getShelfExpiryPeriod(); +} diff --git a/src/main/java/org/folio/dcb/service/impl/CustomTenantService.java b/src/main/java/org/folio/dcb/service/impl/CustomTenantService.java index 91c1c8ed..d1cac4a0 100644 --- a/src/main/java/org/folio/dcb/service/impl/CustomTenantService.java +++ b/src/main/java/org/folio/dcb/service/impl/CustomTenantService.java @@ -12,11 +12,11 @@ import org.folio.dcb.client.feign.LocationUnitClient; import org.folio.dcb.client.feign.LocationsClient; import org.folio.dcb.domain.dto.Calendar; -import org.folio.dcb.domain.dto.HoldShelfExpiryPeriod; import org.folio.dcb.domain.dto.NormalHours; import org.folio.dcb.domain.dto.ServicePointRequest; import org.folio.dcb.listener.kafka.service.KafkaService; import org.folio.dcb.service.CalendarService; +import org.folio.dcb.service.ServicePointExpirationPeriodService; import org.folio.spring.FolioExecutionContext; import org.folio.spring.liquibase.FolioSpringLiquibase; import org.folio.spring.service.PrepareSystemUserService; @@ -73,6 +73,7 @@ public class CustomTenantService extends TenantService { private final CancellationReasonClient cancellationReasonClient; private final LoanTypeClient loanTypeClient; private final CalendarService calendarService; + private final ServicePointExpirationPeriodService servicePointExpirationPeriodService; public CustomTenantService(JdbcTemplate jdbcTemplate, FolioExecutionContext context, FolioSpringLiquibase folioSpringLiquibase, @@ -80,7 +81,8 @@ public CustomTenantService(JdbcTemplate jdbcTemplate, FolioExecutionContext cont InstanceTypeClient instanceTypeClient, HoldingsStorageClient holdingsStorageClient, LocationsClient locationsClient, HoldingSourcesClient holdingSourcesClient, InventoryServicePointClient servicePointClient, LocationUnitClient locationUnitClient, - LoanTypeClient loanTypeClient, CancellationReasonClient cancellationReasonClient, CalendarService calendarService) { + LoanTypeClient loanTypeClient, CancellationReasonClient cancellationReasonClient, CalendarService calendarService, + ServicePointExpirationPeriodService servicePointExpirationPeriodService) { super(jdbcTemplate, context, folioSpringLiquibase); this.systemUserService = systemUserService; @@ -95,6 +97,7 @@ public CustomTenantService(JdbcTemplate jdbcTemplate, FolioExecutionContext cont this.loanTypeClient = loanTypeClient; this.cancellationReasonClient = cancellationReasonClient; this.calendarService = calendarService; + this.servicePointExpirationPeriodService = servicePointExpirationPeriodService; } @Override @@ -215,7 +218,7 @@ private void createServicePoint() { .code(CODE) .discoveryDisplayName(NAME) .pickupLocation(true) - .holdShelfExpiryPeriod(HoldShelfExpiryPeriod.builder().duration(3).intervalId(HoldShelfExpiryPeriod.IntervalIdEnum.DAYS).build()) + .holdShelfExpiryPeriod(servicePointExpirationPeriodService.getShelfExpiryPeriod()) .holdShelfClosedLibraryDateManagement(HOLD_SHELF_CLOSED_LIBRARY_DATE_MANAGEMENT) .build(); diff --git a/src/main/java/org/folio/dcb/service/impl/ServicePointExpirationPeriodServiceImpl.java b/src/main/java/org/folio/dcb/service/impl/ServicePointExpirationPeriodServiceImpl.java new file mode 100644 index 00000000..5d476aca --- /dev/null +++ b/src/main/java/org/folio/dcb/service/impl/ServicePointExpirationPeriodServiceImpl.java @@ -0,0 +1,45 @@ +package org.folio.dcb.service.impl; + +import static org.folio.dcb.utils.DCBConstants.DEFAULT_PERIOD; + +import java.util.List; + +import org.folio.dcb.domain.dto.HoldShelfExpiryPeriod; +import org.folio.dcb.domain.entity.ServicePointExpirationPeriodEntity; +import org.folio.dcb.repository.ServicePointExpirationPeriodRepository; +import org.folio.dcb.service.ServicePointExpirationPeriodService; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j @RequiredArgsConstructor +@Service +public class ServicePointExpirationPeriodServiceImpl + implements ServicePointExpirationPeriodService { + + private final ServicePointExpirationPeriodRepository servicePointExpirationPeriodRepository; + + @Override + public HoldShelfExpiryPeriod getShelfExpiryPeriod() { + List periodList = servicePointExpirationPeriodRepository.findAll(); + if (CollectionUtils.isEmpty(periodList)) { + log.info("getShelfExpiryPeriod:: default hold shelf expire period will be set: {}", + DEFAULT_PERIOD); + return DEFAULT_PERIOD; + } else { + var customPeriod = getCustomPeriod(periodList.get(0)); + log.info("getShelfExpiryPeriod:: custom hold shelf expire period will be set: {}", + customPeriod); + return customPeriod; + } + } + + private HoldShelfExpiryPeriod getCustomPeriod(ServicePointExpirationPeriodEntity period) { + return HoldShelfExpiryPeriod.builder() + .duration(period.getDuration()) + .intervalId(period.getIntervalId()) + .build(); + } +} diff --git a/src/main/java/org/folio/dcb/service/impl/ServicePointServiceImpl.java b/src/main/java/org/folio/dcb/service/impl/ServicePointServiceImpl.java index b6589e66..3a3a5a77 100644 --- a/src/main/java/org/folio/dcb/service/impl/ServicePointServiceImpl.java +++ b/src/main/java/org/folio/dcb/service/impl/ServicePointServiceImpl.java @@ -8,6 +8,7 @@ import org.folio.dcb.domain.dto.HoldShelfExpiryPeriod; import org.folio.dcb.domain.dto.ServicePointRequest; import org.folio.dcb.service.CalendarService; +import org.folio.dcb.service.ServicePointExpirationPeriodService; import org.folio.dcb.service.ServicePointService; import org.folio.util.StringUtil; import org.springframework.stereotype.Service; @@ -19,6 +20,7 @@ public class ServicePointServiceImpl implements ServicePointService { private final InventoryServicePointClient servicePointClient; private final CalendarService calendarService; + private final ServicePointExpirationPeriodService servicePointExpirationPeriodService; public static final String HOLD_SHELF_CLOSED_LIBRARY_DATE_MANAGEMENT = "Keep_the_current_due_date"; @Override @@ -28,6 +30,7 @@ public ServicePointRequest createServicePointIfNotExists(DcbPickup pickupService pickupServicePoint.getServicePointName()); var servicePointRequestList = servicePointClient .getServicePointByName(StringUtil.cqlEncode(servicePointName)).getResult(); + var shelfExpiryPeriod = servicePointExpirationPeriodService.getShelfExpiryPeriod(); if (servicePointRequestList.isEmpty()) { String servicePointId = UUID.randomUUID().toString(); String servicePointCode = getServicePointCode(pickupServicePoint.getLibraryCode(), @@ -35,25 +38,29 @@ public ServicePointRequest createServicePointIfNotExists(DcbPickup pickupService log.info("createServicePointIfNotExists:: creating ServicePoint with id {}, name {} and code {}", servicePointId, servicePointName, servicePointCode); var servicePointRequest = createServicePointRequest(servicePointId, - servicePointName, servicePointCode); + servicePointName, servicePointCode, shelfExpiryPeriod); ServicePointRequest servicePointResponse = servicePointClient.createServicePoint(servicePointRequest); calendarService.addServicePointIdToDefaultCalendar(UUID.fromString(servicePointResponse.getId())); return servicePointResponse; } else { log.info("createServicePointIfNotExists:: servicePoint Exists with name {}, hence reusing it", servicePointName); calendarService.associateServicePointIdWithDefaultCalendarIfAbsent(UUID.fromString(servicePointRequestList.get(0).getId())); - return servicePointRequestList.get(0); + ServicePointRequest servicePointRequest = servicePointRequestList.get(0); + servicePointRequest.setHoldShelfExpiryPeriod(shelfExpiryPeriod); + servicePointClient.updateServicePointById(servicePointRequest.getId(), servicePointRequest); + return servicePointRequest; } } - private ServicePointRequest createServicePointRequest(String id, String name, String code){ + private ServicePointRequest createServicePointRequest(String id, String name, String code, + HoldShelfExpiryPeriod shelfExpiryPeriod){ return ServicePointRequest.builder() .id(id) .name(name) .code(code) .discoveryDisplayName(name) .pickupLocation(true) - .holdShelfExpiryPeriod(HoldShelfExpiryPeriod.builder().duration(3).intervalId(HoldShelfExpiryPeriod.IntervalIdEnum.DAYS).build()) + .holdShelfExpiryPeriod(shelfExpiryPeriod) .holdShelfClosedLibraryDateManagement(HOLD_SHELF_CLOSED_LIBRARY_DATE_MANAGEMENT) .build(); } diff --git a/src/main/java/org/folio/dcb/utils/DCBConstants.java b/src/main/java/org/folio/dcb/utils/DCBConstants.java index acf871b1..ab5c3a15 100644 --- a/src/main/java/org/folio/dcb/utils/DCBConstants.java +++ b/src/main/java/org/folio/dcb/utils/DCBConstants.java @@ -1,5 +1,7 @@ package org.folio.dcb.utils; +import org.folio.dcb.domain.dto.HoldShelfExpiryPeriod; +import org.folio.dcb.domain.dto.IntervalIdEnum; import org.folio.dcb.domain.dto.ItemStatus; import java.util.List; @@ -37,4 +39,11 @@ private DCBConstants() {} public static final String HOLDING_SOURCE = "folio"; public static final String DCB_CALENDAR_NAME = "DCB Calendar"; public static final List holdItemStatus = List.of(IN_TRANSIT, CHECKED_OUT, PAGED, AWAITING_PICKUP, AWAITING_DELIVERY); + public static final int DEFAULT_SERVICE_POINT_PERIOD_DURATION = 10; + public static final IntervalIdEnum DEFAULT_SERVICE_POINT_PERIOD_INTERVAL = IntervalIdEnum.DAYS; + public static final HoldShelfExpiryPeriod DEFAULT_PERIOD = HoldShelfExpiryPeriod.builder() + .duration(DEFAULT_SERVICE_POINT_PERIOD_DURATION) + .intervalId(DEFAULT_SERVICE_POINT_PERIOD_INTERVAL) + .build(); + } diff --git a/src/main/resources/db/changelog/changelog-master.xml b/src/main/resources/db/changelog/changelog-master.xml index 30b36fb1..c5591843 100644 --- a/src/main/resources/db/changelog/changelog-master.xml +++ b/src/main/resources/db/changelog/changelog-master.xml @@ -9,5 +9,6 @@ + diff --git a/src/main/resources/db/changelog/changes/create-service-point-expiration-period-table.sql b/src/main/resources/db/changelog/changes/create-service-point-expiration-period-table.sql new file mode 100644 index 00000000..4cacb543 --- /dev/null +++ b/src/main/resources/db/changelog/changes/create-service-point-expiration-period-table.sql @@ -0,0 +1,9 @@ +DROP TYPE IF EXISTS interval_id; +CREATE TYPE interval_id AS ENUM ('Minutes', 'Hours', 'Days', 'Weeks', 'Months'); +CREATE TABLE IF NOT EXISTS service_point_expiration_period +( + id uuid NOT NULL DEFAULT gen_random_uuid(), + duration integer NOT NULL, + interval_id interval_id NOT NULL, + CONSTRAINT service_point_expiration_period_pkey PRIMARY KEY (id) +); \ No newline at end of file diff --git a/src/main/resources/db/changelog/changes/create-service-point-expiration-period-table.xml b/src/main/resources/db/changelog/changes/create-service-point-expiration-period-table.xml new file mode 100644 index 00000000..e682b77e --- /dev/null +++ b/src/main/resources/db/changelog/changes/create-service-point-expiration-period-table.xml @@ -0,0 +1,15 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/swagger.api/schemas/IntervalIdEnum.yaml b/src/main/resources/swagger.api/schemas/IntervalIdEnum.yaml new file mode 100644 index 00000000..c61be59d --- /dev/null +++ b/src/main/resources/swagger.api/schemas/IntervalIdEnum.yaml @@ -0,0 +1,8 @@ +IntervalIdEnum: + type: string + enum: + - Minutes + - Hours + - Days + - Weeks + - Months \ No newline at end of file diff --git a/src/main/resources/swagger.api/schemas/ServicePointRequest.yaml b/src/main/resources/swagger.api/schemas/ServicePointRequest.yaml index 65c29ef3..147dfc45 100644 --- a/src/main/resources/swagger.api/schemas/ServicePointRequest.yaml +++ b/src/main/resources/swagger.api/schemas/ServicePointRequest.yaml @@ -33,7 +33,4 @@ HoldShelfExpiryPeriod: type: integer intervalId: description: Interval Hold Shelf Expiry Period - type: string - enum: - - Days - - Weeks + $ref: IntervalIdEnum.yaml#/IntervalIdEnum diff --git a/src/main/resources/swagger.api/schemas/servicePointExpirationPeriod.yaml b/src/main/resources/swagger.api/schemas/servicePointExpirationPeriod.yaml new file mode 100644 index 00000000..27b60abc --- /dev/null +++ b/src/main/resources/swagger.api/schemas/servicePointExpirationPeriod.yaml @@ -0,0 +1,12 @@ +ServicePointExpirationPeriod: + type: object + properties: + id: + description: "Unique identifier of a service point expiration period" + $ref: "uuid.yaml" + duration: + description: "duration value of service point expiration period" + type: integer + interval: + description: "period type of service point expiration period" + $ref: IntervalIdEnum.yaml#/IntervalIdEnum \ No newline at end of file diff --git a/src/test/java/org/folio/dcb/domain/converter/IntervalIdEnumConverterTest.java b/src/test/java/org/folio/dcb/domain/converter/IntervalIdEnumConverterTest.java new file mode 100644 index 00000000..81e8bfec --- /dev/null +++ b/src/test/java/org/folio/dcb/domain/converter/IntervalIdEnumConverterTest.java @@ -0,0 +1,22 @@ +package org.folio.dcb.domain.converter; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.folio.dcb.domain.dto.IntervalIdEnum; +import org.junit.jupiter.api.Test; + +class IntervalIdEnumConverterTest { + + private final IntervalIdEnumConverter converter = new IntervalIdEnumConverter(); + + + @Test + void convertToDatabaseColumnTest() { + assertEquals("Days", converter.convertToDatabaseColumn(IntervalIdEnum.DAYS)); + } + + @Test + void convertToEntityAttributeTest() { + assertEquals(IntervalIdEnum.DAYS , converter.convertToEntityAttribute("Days")); + } +} \ No newline at end of file diff --git a/src/test/java/org/folio/dcb/service/CustomTenantServiceTest.java b/src/test/java/org/folio/dcb/service/CustomTenantServiceTest.java index d3e81416..47289074 100644 --- a/src/test/java/org/folio/dcb/service/CustomTenantServiceTest.java +++ b/src/test/java/org/folio/dcb/service/CustomTenantServiceTest.java @@ -25,6 +25,7 @@ import java.util.UUID; import static org.folio.dcb.utils.DCBConstants.DCB_CALENDAR_NAME; +import static org.folio.dcb.utils.DCBConstants.DEFAULT_PERIOD; import static org.folio.dcb.utils.EntityUtils.getCalendarCollection; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.never; @@ -57,6 +58,8 @@ class CustomTenantServiceTest { private LoanTypeClient loanTypeClient; @Mock private CancellationReasonClient cancellationReasonClient; + @Mock + private ServicePointExpirationPeriodService servicePointExpirationPeriodService; @Mock private CalendarService calendarService; @@ -73,6 +76,7 @@ void shouldPrepareSystemUser() { when(servicePointClient.getServicePointByName(any())).thenReturn(new ResultList<>()); when(locationsClient.queryLocationsByName(any())).thenReturn(new ResultList<>()); when(loanTypeClient.queryLoanTypeByName(any())).thenReturn(new ResultList<>()); + when(servicePointExpirationPeriodService.getShelfExpiryPeriod()).thenReturn(DEFAULT_PERIOD); service.createOrUpdateTenant(new TenantAttributes()); verify(systemUserService).setupSystemUser(); @@ -88,6 +92,7 @@ void testHoldingsCreationWhileEnablingTenant() { when(locationsClient.queryLocationsByName(any())).thenReturn(new ResultList<>()); when(loanTypeClient.queryLoanTypeByName(any())).thenReturn(new ResultList<>()); when(holdingsStorageClient.findHolding(any())).thenReturn(HoldingsStorageClient.Holding.builder().build()); + when(servicePointExpirationPeriodService.getShelfExpiryPeriod()).thenReturn(DEFAULT_PERIOD); service.createOrUpdateTenant(new TenantAttributes()); verify(systemUserService).setupSystemUser(); @@ -122,6 +127,8 @@ void testCalendarCreation_DefaultCalendarNotExists() { when(loanTypeClient.queryLoanTypeByName(any())).thenReturn(new ResultList<>()); when(holdingsStorageClient.findHolding(any())).thenReturn(HoldingsStorageClient.Holding.builder().build()); when(calendarService.findCalendarByName(DCB_CALENDAR_NAME)).thenReturn(null); + when(servicePointExpirationPeriodService.getShelfExpiryPeriod()).thenReturn(DEFAULT_PERIOD); + when(servicePointExpirationPeriodService.getShelfExpiryPeriod()).thenReturn(DEFAULT_PERIOD); service.createOrUpdateTenant(new TenantAttributes()); verify(calendarService).createCalendar(any()); @@ -138,6 +145,7 @@ void testCalendarCreation_DefaultCalendarExists() { when(loanTypeClient.queryLoanTypeByName(any())).thenReturn(new ResultList<>()); when(holdingsStorageClient.findHolding(any())).thenReturn(HoldingsStorageClient.Holding.builder().build()); when(calendarService.findCalendarByName(DCB_CALENDAR_NAME)).thenReturn(null); + when(servicePointExpirationPeriodService.getShelfExpiryPeriod()).thenReturn(DEFAULT_PERIOD); when(calendarService.findCalendarByName(DCB_CALENDAR_NAME)).thenReturn(getCalendarCollection(DCB_CALENDAR_NAME).getCalendars().get(0)); service.createOrUpdateTenant(new TenantAttributes()); diff --git a/src/test/java/org/folio/dcb/service/ServicePointExpirationPeriodServiceTest.java b/src/test/java/org/folio/dcb/service/ServicePointExpirationPeriodServiceTest.java new file mode 100644 index 00000000..69706e77 --- /dev/null +++ b/src/test/java/org/folio/dcb/service/ServicePointExpirationPeriodServiceTest.java @@ -0,0 +1,68 @@ +package org.folio.dcb.service; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.when; + +import java.util.List; +import java.util.stream.Stream; + +import org.folio.dcb.domain.dto.HoldShelfExpiryPeriod; +import org.folio.dcb.domain.dto.IntervalIdEnum; +import org.folio.dcb.domain.entity.ServicePointExpirationPeriodEntity; +import org.folio.dcb.repository.ServicePointExpirationPeriodRepository; +import org.folio.dcb.service.impl.ServicePointExpirationPeriodServiceImpl; +import org.folio.dcb.utils.DCBConstants; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class ServicePointExpirationPeriodServiceTest { + @InjectMocks + private ServicePointExpirationPeriodServiceImpl servicePointExpirationPeriodService; + @Mock + private ServicePointExpirationPeriodRepository servicePointExpirationPeriodRepository; + + @ParameterizedTest + @MethodSource + void getShelfExpiryPeriodTest(List periods, + HoldShelfExpiryPeriod expected) { + when(servicePointExpirationPeriodRepository.findAll()).thenReturn(periods); + HoldShelfExpiryPeriod actual = servicePointExpirationPeriodService.getShelfExpiryPeriod(); + assertEquals(expected, actual); + } + + private static Stream getShelfExpiryPeriodTest() { + return Stream.of( + Arguments.of(List.of(), DCBConstants.DEFAULT_PERIOD), + Arguments.of(buildServicePointExpirationPeriodList(2, IntervalIdEnum.MONTHS), + buildExpectedHoldShelfPeriod(2, IntervalIdEnum.MONTHS)), + Arguments.of(buildServicePointExpirationPeriodList(3, IntervalIdEnum.HOURS), + buildExpectedHoldShelfPeriod(3, IntervalIdEnum.HOURS)), + Arguments.of(buildServicePointExpirationPeriodList(4, IntervalIdEnum.MINUTES), + buildExpectedHoldShelfPeriod(4, IntervalIdEnum.MINUTES)) + + ); + } + + private static HoldShelfExpiryPeriod buildExpectedHoldShelfPeriod(int duration, + IntervalIdEnum intervalId) { + return HoldShelfExpiryPeriod.builder() + .duration(duration) + .intervalId(intervalId) + .build(); + } + + private static List buildServicePointExpirationPeriodList( + int duration, + IntervalIdEnum intervalId) { + return List.of(ServicePointExpirationPeriodEntity.builder() + .duration(duration) + .intervalId(intervalId) + .build()); + } +} diff --git a/src/test/java/org/folio/dcb/service/ServicePointServiceTest.java b/src/test/java/org/folio/dcb/service/ServicePointServiceTest.java index 5fc0bfe6..468952eb 100644 --- a/src/test/java/org/folio/dcb/service/ServicePointServiceTest.java +++ b/src/test/java/org/folio/dcb/service/ServicePointServiceTest.java @@ -1,7 +1,22 @@ package org.folio.dcb.service; +import static org.folio.dcb.utils.EntityUtils.createDcbPickup; +import static org.folio.dcb.utils.EntityUtils.createServicePointRequest; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.List; +import java.util.UUID; + import org.folio.dcb.client.feign.InventoryServicePointClient; +import org.folio.dcb.domain.dto.HoldShelfExpiryPeriod; +import org.folio.dcb.domain.dto.IntervalIdEnum; import org.folio.dcb.service.impl.ServicePointServiceImpl; +import org.folio.dcb.utils.DCBConstants; import org.folio.spring.model.ResultList; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -9,17 +24,6 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import java.util.List; -import java.util.UUID; - -import static org.folio.dcb.utils.EntityUtils.createDcbPickup; -import static org.folio.dcb.utils.EntityUtils.createServicePointRequest; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - @ExtendWith(MockitoExtension.class) class ServicePointServiceTest { @@ -32,12 +36,16 @@ class ServicePointServiceTest { @Mock private CalendarService calendarService; + @Mock + private static ServicePointExpirationPeriodService servicePointExpirationPeriodService; + @Test - void createServicePointIfNotExistsTest(){ + void createServicePointIfNotExistsTest() { when(inventoryServicePointClient.getServicePointByName(any())) .thenReturn(ResultList.of(0, List.of())); when(inventoryServicePointClient.createServicePoint(any())) .thenReturn(createServicePointRequest()); + when(servicePointExpirationPeriodService.getShelfExpiryPeriod()).thenReturn(DCBConstants.DEFAULT_PERIOD); var response = servicePointService.createServicePointIfNotExists(createDcbPickup()); verify(inventoryServicePointClient).createServicePoint(any()); verify(inventoryServicePointClient).getServicePointByName(any()); @@ -46,17 +54,26 @@ void createServicePointIfNotExistsTest(){ } @Test - void createServicePointIfExistsTest(){ + void createServicePointIfExistsTest() { var servicePointRequest = createServicePointRequest(); var servicePointId = UUID.randomUUID().toString(); servicePointRequest.setId(servicePointId); when(inventoryServicePointClient.getServicePointByName(any())) .thenReturn(ResultList.of(0, List.of(servicePointRequest))); + when(servicePointExpirationPeriodService.getShelfExpiryPeriod()).thenReturn( + HoldShelfExpiryPeriod.builder() + .duration(2) + .intervalId(IntervalIdEnum.MONTHS) + .build() + ); var response = servicePointService.createServicePointIfNotExists(createDcbPickup()); assertEquals(servicePointId, response.getId()); - verify(inventoryServicePointClient, never()).createServicePoint(any()); + assertEquals(2, response.getHoldShelfExpiryPeriod().getDuration()); + assertEquals(IntervalIdEnum.MONTHS, response.getHoldShelfExpiryPeriod().getIntervalId()); + verify(inventoryServicePointClient, times(1)).updateServicePointById(any(), any()); verify(inventoryServicePointClient).getServicePointByName(any()); - verify(calendarService).associateServicePointIdWithDefaultCalendarIfAbsent(UUID.fromString(response.getId())); + verify(calendarService).associateServicePointIdWithDefaultCalendarIfAbsent( + UUID.fromString(response.getId())); verify(calendarService, never()).addServicePointIdToDefaultCalendar(any()); } diff --git a/src/test/java/org/folio/dcb/utils/EntityUtils.java b/src/test/java/org/folio/dcb/utils/EntityUtils.java index b867f75f..d0fade89 100644 --- a/src/test/java/org/folio/dcb/utils/EntityUtils.java +++ b/src/test/java/org/folio/dcb/utils/EntityUtils.java @@ -121,7 +121,7 @@ public static org.folio.dcb.domain.dto.ServicePointRequest createServicePointReq .code("DCB_TESTLIBRARYCODE_TESTSERVICEPOINTCODE") .discoveryDisplayName("DCB_TestLibraryCode_TestServicePointCode") .pickupLocation(true) - .holdShelfExpiryPeriod(org.folio.dcb.domain.dto.HoldShelfExpiryPeriod.builder().duration(3).intervalId(org.folio.dcb.domain.dto.HoldShelfExpiryPeriod.IntervalIdEnum.DAYS).build()) + .holdShelfExpiryPeriod(org.folio.dcb.domain.dto.HoldShelfExpiryPeriod.builder().duration(3).intervalId(org.folio.dcb.domain.dto.IntervalIdEnum.DAYS).build()) .holdShelfClosedLibraryDateManagement(HOLD_SHELF_CLOSED_LIBRARY_DATE_MANAGEMENT) .build(); } diff --git a/src/test/resources/mappings/inventory.json b/src/test/resources/mappings/inventory.json index 71d22cc8..77288863 100644 --- a/src/test/resources/mappings/inventory.json +++ b/src/test/resources/mappings/inventory.json @@ -117,6 +117,18 @@ } } }, + { + "request": { + "method": "PUT", + "url": "/service-points/9d1b77e8-f02e-4b7f-b296-3f2042ddac55" + }, + "response": { + "status": 204, + "headers": { + "Content-Type": "application/json" + } + } + }, { "request": { "method": "POST",