From e40350df31238eda1a752d33585957158192901c Mon Sep 17 00:00:00 2001 From: kuzonduch Date: Fri, 14 Feb 2025 09:54:43 +0000 Subject: [PATCH 1/5] ability to specify type and number of officers in a company --- .../api/testdata/model/rest/CompanySpec.java | 25 +++ .../repository/AppointmentsRepository.java | 3 +- .../testdata/service/AppointmentService.java | 22 ++ .../service/impl/AppointmentsServiceImpl.java | 196 ++++++++++------- .../service/impl/TestDataServiceImpl.java | 3 +- .../impl/AppointmentsServiceImplTest.java | 208 +++++++++++++----- 6 files changed, 316 insertions(+), 141 deletions(-) create mode 100644 src/main/java/uk/gov/companieshouse/api/testdata/service/AppointmentService.java diff --git a/src/main/java/uk/gov/companieshouse/api/testdata/model/rest/CompanySpec.java b/src/main/java/uk/gov/companieshouse/api/testdata/model/rest/CompanySpec.java index 977b66e1..16f877c7 100644 --- a/src/main/java/uk/gov/companieshouse/api/testdata/model/rest/CompanySpec.java +++ b/src/main/java/uk/gov/companieshouse/api/testdata/model/rest/CompanySpec.java @@ -6,6 +6,8 @@ import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Pattern; +import java.util.List; + /** * Requirements a new company must meet. */ @@ -34,6 +36,13 @@ public class CompanySpec { @JsonProperty("has_super_secure_pscs") private Boolean hasSuperSecurePscs; + @JsonProperty("number_of_appointments") + private int numberOfAppointments = 1; + + @JsonProperty("officer_roles") + private List<@Pattern(regexp = "director|secretary", + message = "Invalid officer role") String> officerRoles; + public CompanySpec() { jurisdiction = Jurisdiction.ENGLAND_WALES; } @@ -85,4 +94,20 @@ public Boolean getHasSuperSecurePscs() { public void setHasSuperSecurePscs(Boolean hasSuperSecurePscs) { this.hasSuperSecurePscs = hasSuperSecurePscs; } + + public int getNumberOfAppointments() { + return numberOfAppointments; + } + + public void setNumberOfAppointments(int numberOfAppointments) { + this.numberOfAppointments = numberOfAppointments; + } + + public List getOfficerRoles() { + return officerRoles; + } + + public void setOfficerRoles(List officerRoles) { + this.officerRoles = officerRoles; + } } diff --git a/src/main/java/uk/gov/companieshouse/api/testdata/repository/AppointmentsRepository.java b/src/main/java/uk/gov/companieshouse/api/testdata/repository/AppointmentsRepository.java index bb15eb8b..50e90092 100644 --- a/src/main/java/uk/gov/companieshouse/api/testdata/repository/AppointmentsRepository.java +++ b/src/main/java/uk/gov/companieshouse/api/testdata/repository/AppointmentsRepository.java @@ -1,5 +1,6 @@ package uk.gov.companieshouse.api.testdata.repository; +import java.util.List; import java.util.Optional; import org.springframework.data.mongodb.repository.MongoRepository; @@ -9,5 +10,5 @@ @NoRepositoryBean public interface AppointmentsRepository extends MongoRepository { - Optional findByCompanyNumber(String companyNumber); + List findAllByCompanyNumber(String companyNumber); } diff --git a/src/main/java/uk/gov/companieshouse/api/testdata/service/AppointmentService.java b/src/main/java/uk/gov/companieshouse/api/testdata/service/AppointmentService.java new file mode 100644 index 00000000..7549520e --- /dev/null +++ b/src/main/java/uk/gov/companieshouse/api/testdata/service/AppointmentService.java @@ -0,0 +1,22 @@ +package uk.gov.companieshouse.api.testdata.service; + +import uk.gov.companieshouse.api.testdata.model.entity.Appointment; +import uk.gov.companieshouse.api.testdata.model.rest.CompanySpec; + +import java.util.List; + +public interface AppointmentService { + + /** + * Creates one or more Appointment entities for the given CompanySpec, + * and returns them all in a list. + */ + List create(CompanySpec spec); + + /** + * Deletes an appointment by its company number. + * + * @return true if found and deleted, false otherwise + */ + boolean delete(String companyNumber); +} diff --git a/src/main/java/uk/gov/companieshouse/api/testdata/service/impl/AppointmentsServiceImpl.java b/src/main/java/uk/gov/companieshouse/api/testdata/service/impl/AppointmentsServiceImpl.java index 5f75072d..e1fc70ee 100644 --- a/src/main/java/uk/gov/companieshouse/api/testdata/service/impl/AppointmentsServiceImpl.java +++ b/src/main/java/uk/gov/companieshouse/api/testdata/service/impl/AppointmentsServiceImpl.java @@ -5,22 +5,24 @@ import java.time.ZoneId; import java.util.ArrayList; import java.util.List; -import java.util.Optional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import uk.gov.companieshouse.api.testdata.model.entity.*; +import uk.gov.companieshouse.api.testdata.model.entity.Appointment; +import uk.gov.companieshouse.api.testdata.model.entity.Links; +import uk.gov.companieshouse.api.testdata.model.entity.OfficerAppointment; +import uk.gov.companieshouse.api.testdata.model.entity.OfficerAppointmentItem; import uk.gov.companieshouse.api.testdata.model.rest.CompanySpec; import uk.gov.companieshouse.api.testdata.model.rest.Jurisdiction; import uk.gov.companieshouse.api.testdata.repository.AppointmentsRepository; import uk.gov.companieshouse.api.testdata.repository.OfficerRepository; import uk.gov.companieshouse.api.testdata.service.AddressService; -import uk.gov.companieshouse.api.testdata.service.DataService; +import uk.gov.companieshouse.api.testdata.service.AppointmentService; import uk.gov.companieshouse.api.testdata.service.RandomService; @Service -public class AppointmentsServiceImpl implements DataService { +public class AppointmentsServiceImpl implements AppointmentService { private static final int SALT_LENGTH = 8; private static final int ID_LENGTH = 10; @@ -40,77 +42,102 @@ public class AppointmentsServiceImpl implements DataService create(CompanySpec spec) { final String companyNumber = spec.getCompanyNumber(); - final String countryOfResidence = addressService.getCountryOfResidence(spec.getJurisdiction()); + int numberOfAppointments = spec.getNumberOfAppointments(); + if (numberOfAppointments <= 0) { + numberOfAppointments = 1; + } - Appointment appointment = new Appointment(); - - String appointmentId = randomService.getEncodedIdWithSalt(ID_LENGTH, SALT_LENGTH); - - LocalDate officerDob = LocalDate.of(1990, 3, 6); - - Instant dateTimeNow = Instant.now(); - Instant dateNow = LocalDate.now().atStartOfDay(ZoneId.of("UTC")).toInstant(); - Instant dob = officerDob.atStartOfDay(ZoneId.of("UTC")).toInstant(); - - appointment.setId(appointmentId); - appointment.setCreated(dateTimeNow); - - String internalId = INTERNAL_ID_PREFIX + this.randomService.getNumber(INTERNAL_ID_LENGTH); - String officerId = randomService.addSaltAndEncode(internalId, SALT_LENGTH); - appointment.setInternalId(internalId); - appointment.setAppointmentId(appointmentId); - - appointment.setNationality("British"); - appointment.setOccupation(OCCUPATION); - appointment.setServiceAddressIsSameAsRegisteredOfficeAddress(true); - appointment.setCountryOfResidence(countryOfResidence); - appointment.setUpdatedAt(dateTimeNow); - appointment.setForename("Test"); - appointment.setAppointedOn(dateNow); - appointment.setOfficerRole("director"); - appointment.setEtag(randomService.getEtag()); - - appointment.setServiceAddress(addressService.getAddress(spec.getJurisdiction())); - appointment.setDataCompanyNumber(companyNumber); - - Links links = new Links(); - links.setSelf(COMPANY_LINK + companyNumber + "/appointments/" + officerId); - links.setOfficerSelf(OFFICERS_LINK + officerId); - links.setOfficerAppointments(OFFICERS_LINK + officerId + "/appointments"); - appointment.setLinks(links); + List officerRoles = spec.getOfficerRoles(); + if (officerRoles == null) { + officerRoles = new ArrayList<>(); + } - appointment.setSurname("DIRECTOR"); - appointment.setDateOfBirth(dob); + for (String role : officerRoles) { + if (!role.equalsIgnoreCase("director") && !role.equalsIgnoreCase("secretary")) { + throw new IllegalArgumentException("Invalid officer role: " + role); + } + } - appointment.setCompanyName("Company " + companyNumber); - appointment.setCompanyStatus("active"); - appointment.setOfficerId(officerId); - appointment.setCompanyNumber(companyNumber); - appointment.setUpdated(dateTimeNow); + while (officerRoles.size() < numberOfAppointments) { + officerRoles.add("director"); + } - this.createOfficerAppointment(spec, officerId, appointmentId); + List createdAppointments = new ArrayList<>(); + + for (int i = 0; i < numberOfAppointments; i++) { + String currentRole = officerRoles.get(i); + + Appointment appointment = new Appointment(); + + String appointmentId = randomService.getEncodedIdWithSalt(ID_LENGTH, SALT_LENGTH); + String internalId = INTERNAL_ID_PREFIX + this.randomService.getNumber(INTERNAL_ID_LENGTH); + String officerId = randomService.addSaltAndEncode(internalId, SALT_LENGTH); + + LocalDate officerDob = LocalDate.of(1990, 3, 6); + Instant dateTimeNow = Instant.now(); + Instant dateNow = LocalDate.now().atStartOfDay(ZoneId.of("UTC")).toInstant(); + Instant dob = officerDob.atStartOfDay(ZoneId.of("UTC")).toInstant(); + + appointment.setId(appointmentId); + appointment.setCreated(dateTimeNow); + appointment.setInternalId(internalId); + appointment.setAppointmentId(appointmentId); + appointment.setNationality("British"); + appointment.setOccupation(OCCUPATION); + appointment.setServiceAddressIsSameAsRegisteredOfficeAddress(true); + appointment.setCountryOfResidence(countryOfResidence); + appointment.setUpdatedAt(dateTimeNow); + appointment.setForename("Test " + (i + 1)); + appointment.setAppointedOn(dateNow); + appointment.setOfficerRole(currentRole); + appointment.setEtag(randomService.getEtag()); + appointment.setServiceAddress(addressService.getAddress(spec.getJurisdiction())); + appointment.setDataCompanyNumber(companyNumber); + + Links links = new Links(); + links.setSelf(COMPANY_LINK + companyNumber + "/appointments/" + officerId); + links.setOfficerSelf(OFFICERS_LINK + officerId); + links.setOfficerAppointments(OFFICERS_LINK + officerId + "/appointments"); + appointment.setLinks(links); + + appointment.setSurname("DIRECTOR"); + appointment.setDateOfBirth(dob); + appointment.setCompanyName("Company " + companyNumber); + appointment.setCompanyStatus("active"); + appointment.setOfficerId(officerId); + appointment.setCompanyNumber(companyNumber); + appointment.setUpdated(dateTimeNow); + + this.createOfficerAppointment(spec, officerId, appointmentId, currentRole); + + Appointment savedAppointment = appointmentsRepository.save(appointment); + createdAppointments.add(savedAppointment); + } - return appointmentsRepository.save(appointment); + return createdAppointments; } @Override public boolean delete(String companyNumber) { - Optional existingAppointment = appointmentsRepository.findByCompanyNumber(companyNumber); - - if (existingAppointment.isPresent()) { - String officerId = existingAppointment.get().getOfficerId(); - officerRepository.findById(officerId).ifPresent(officerRepository::delete); - appointmentsRepository.delete(existingAppointment.get()); + List foundAppointments = + appointmentsRepository.findAllByCompanyNumber(companyNumber); + + if (!foundAppointments.isEmpty()) { + for (Appointment ap : foundAppointments) { + String officerId = ap.getOfficerId(); + officerRepository.findById(officerId).ifPresent(officerRepository::delete); + } + appointmentsRepository.deleteAll(foundAppointments); return true; } return false; } - private void createOfficerAppointment(CompanySpec spec, String officerId, String appointmentId) { - + private void createOfficerAppointment(CompanySpec spec, + String officerId, String appointmentId, String role) { OfficerAppointment officerAppointment = new OfficerAppointment(); Instant dayTimeNow = Instant.now(); @@ -119,7 +146,6 @@ private void createOfficerAppointment(CompanySpec spec, String officerId, String officerAppointment.setId(officerId); officerAppointment.setCreatedAt(dayTimeNow); officerAppointment.setUpdatedAt(dayTimeNow); - officerAppointment.setTotalResults(1); officerAppointment.setActiveCount(1); officerAppointment.setInactiveCount(0); @@ -131,39 +157,47 @@ private void createOfficerAppointment(CompanySpec spec, String officerId, String links.setSelf(OFFICERS_LINK + officerId + "/appointments"); officerAppointment.setLinks(links); - officerAppointment.setEtag(this.randomService.getEtag()); + officerAppointment.setEtag(randomService.getEtag()); officerAppointment.setDateOfBirthYear(1990); officerAppointment.setDateOfBirthMonth(3); + officerAppointment.setOfficerAppointmentItems( - createOfficerAppointmentItems(spec, appointmentId, dayNow, dayTimeNow)); + createOfficerAppointmentItems(spec, appointmentId, dayNow, dayTimeNow, role) + ); officerRepository.save(officerAppointment); } - private List createOfficerAppointmentItems(CompanySpec companySpec, String appointmentId, - Instant dayNow, Instant dayTimeNow) { + + private List createOfficerAppointmentItems( + CompanySpec companySpec, + String appointmentId, + Instant dayNow, + Instant dayTimeNow, + String role + ) { List officerAppointmentItemList = new ArrayList<>(); String companyNumber = companySpec.getCompanyNumber(); Jurisdiction jurisdiction = companySpec.getJurisdiction(); - OfficerAppointmentItem officerAppointmentItem = new OfficerAppointmentItem(); - officerAppointmentItem.setOccupation(OCCUPATION); - officerAppointmentItem.setAddress(addressService.getAddress(jurisdiction)); - officerAppointmentItem.setForename("Test"); - officerAppointmentItem.setSurname(OCCUPATION); - officerAppointmentItem.setOfficerRole("director"); - officerAppointmentItem.setLinks(createOfficerAppointmentItemLinks(companyNumber, appointmentId)); - officerAppointmentItem.setCountryOfResidence(addressService.getCountryOfResidence(jurisdiction)); - officerAppointmentItem.setAppointedOn(dayNow); - officerAppointmentItem.setNationality("British"); - officerAppointmentItem.setUpdatedAt(dayTimeNow); - officerAppointmentItem.setName("Test DIRECTOR"); - officerAppointmentItem.setCompanyName("Company " + companyNumber); - officerAppointmentItem.setCompanyNumber(companyNumber); - officerAppointmentItem.setCompanyStatus("active"); - - officerAppointmentItemList.add(officerAppointmentItem); + OfficerAppointmentItem item = new OfficerAppointmentItem(); + item.setOccupation(OCCUPATION); + item.setAddress(addressService.getAddress(jurisdiction)); + item.setForename("Test"); + item.setSurname(OCCUPATION); + item.setOfficerRole(role); + item.setLinks(createOfficerAppointmentItemLinks(companyNumber, appointmentId)); + item.setCountryOfResidence(addressService.getCountryOfResidence(jurisdiction)); + item.setAppointedOn(dayNow); + item.setNationality("British"); + item.setUpdatedAt(dayTimeNow); + item.setName("Test DIRECTOR"); + item.setCompanyName("Company " + companyNumber); + item.setCompanyNumber(companyNumber); + item.setCompanyStatus("active"); + + officerAppointmentItemList.add(item); return officerAppointmentItemList; } diff --git a/src/main/java/uk/gov/companieshouse/api/testdata/service/impl/TestDataServiceImpl.java b/src/main/java/uk/gov/companieshouse/api/testdata/service/impl/TestDataServiceImpl.java index 181575b8..189d38fb 100644 --- a/src/main/java/uk/gov/companieshouse/api/testdata/service/impl/TestDataServiceImpl.java +++ b/src/main/java/uk/gov/companieshouse/api/testdata/service/impl/TestDataServiceImpl.java @@ -32,6 +32,7 @@ import uk.gov.companieshouse.api.testdata.model.rest.UserSpec; import uk.gov.companieshouse.api.testdata.repository.AcspMembersRepository; +import uk.gov.companieshouse.api.testdata.service.AppointmentService; import uk.gov.companieshouse.api.testdata.service.CompanyAuthAllowListService; import uk.gov.companieshouse.api.testdata.service.CompanyAuthCodeService; import uk.gov.companieshouse.api.testdata.service.CompanyProfileService; @@ -56,7 +57,7 @@ public class TestDataServiceImpl implements TestDataService { @Autowired private CompanyAuthCodeService companyAuthCodeService; @Autowired - private DataService appointmentService; + private AppointmentService appointmentService; @Autowired private DataService companyMetricsService; @Autowired diff --git a/src/test/java/uk/gov/companieshouse/api/testdata/service/impl/AppointmentsServiceImplTest.java b/src/test/java/uk/gov/companieshouse/api/testdata/service/impl/AppointmentsServiceImplTest.java index ad7e33d4..29f84dc5 100644 --- a/src/test/java/uk/gov/companieshouse/api/testdata/service/impl/AppointmentsServiceImplTest.java +++ b/src/test/java/uk/gov/companieshouse/api/testdata/service/impl/AppointmentsServiceImplTest.java @@ -2,10 +2,10 @@ import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.*; +import java.util.Collections; +import java.util.List; import java.util.Optional; import org.junit.jupiter.api.Test; @@ -51,52 +51,58 @@ class AppointmentsServiceImplTest { @Test void create() { - final Address mockServiceAddress = new Address( - "","","","","","" - ); - + // GIVEN + final Address mockServiceAddress = new Address("", "", "", "", "", ""); CompanySpec spec = new CompanySpec(); spec.setCompanyNumber(COMPANY_NUMBER); - + // numberOfAppointments is default 0, so the service sets it to 1 + when(randomService.getNumber(INTERNAL_ID_LENGTH)).thenReturn(GENERATED_ID); - when(this.randomService.getEncodedIdWithSalt(10, 8)).thenReturn(ENCODED_VALUE); - when(this.randomService.addSaltAndEncode(INTERNAL_ID_PREFIX + GENERATED_ID, 8)).thenReturn(ENCODED_INTERNAL_ID); - when(this.randomService.getEtag()).thenReturn(ETAG); - when(this.addressService.getAddress(Jurisdiction.ENGLAND_WALES)).thenReturn(mockServiceAddress); - when(this.addressService.getCountryOfResidence(Jurisdiction.ENGLAND_WALES)).thenReturn("Wales"); + when(randomService.getEncodedIdWithSalt(10, 8)).thenReturn(ENCODED_VALUE); + when(randomService.addSaltAndEncode(INTERNAL_ID_PREFIX + GENERATED_ID, 8)) + .thenReturn(ENCODED_INTERNAL_ID); + when(randomService.getEtag()).thenReturn(ETAG); + + // For the default (England & Wales) scenario in this test: + when(addressService.getAddress(Jurisdiction.ENGLAND_WALES)).thenReturn(mockServiceAddress); + when(addressService.getCountryOfResidence(Jurisdiction.ENGLAND_WALES)) + .thenReturn("Wales"); + Appointment savedApt = new Appointment(); - when(this.appointmentsRepository.save(any())).thenReturn(savedApt); - - Appointment returnedApt = this.appointmentsService.create(spec); - - assertEquals(savedApt, returnedApt); - + when(appointmentsRepository.save(any())).thenReturn(savedApt); + + List returnedApts = appointmentsService.create(spec); + + assertNotNull(returnedApts); + assertEquals(1, returnedApts.size()); + assertEquals(savedApt, returnedApts.get(0)); + ArgumentCaptor aptCaptor = ArgumentCaptor.forClass(Appointment.class); verify(appointmentsRepository).save(aptCaptor.capture()); Appointment appointment = aptCaptor.getValue(); assertNotNull(appointment); assertEquals(ENCODED_VALUE, appointment.getId()); + assertEquals(ENCODED_VALUE, appointment.getAppointmentId()); assertNotNull(appointment.getCreated()); + assertEquals(INTERNAL_ID_PREFIX + GENERATED_ID, appointment.getInternalId()); - assertEquals(ENCODED_VALUE, appointment.getAppointmentId()); - assertEquals("Company " + COMPANY_NUMBER, appointment.getCompanyName()); - assertEquals("active", appointment.getCompanyStatus()); assertEquals(ENCODED_INTERNAL_ID, appointment.getOfficerId()); assertEquals(COMPANY_NUMBER, appointment.getCompanyNumber()); assertNotNull(appointment.getUpdated()); + assertEquals("Company " + COMPANY_NUMBER, appointment.getCompanyName()); + assertEquals("active", appointment.getCompanyStatus()); assertEquals("British", appointment.getNationality()); assertEquals("Director", appointment.getOccupation()); assertTrue(appointment.isServiceAddressIsSameAsRegisteredOfficeAddress()); assertEquals("Wales", appointment.getCountryOfResidence()); assertNotNull(appointment.getUpdatedAt()); - assertEquals("Test", appointment.getForename()); + assertTrue(appointment.getForename().startsWith("Test")); assertNotNull(appointment.getAppointedOn()); assertEquals("director", appointment.getOfficerRole()); assertEquals(ETAG, appointment.getEtag()); assertEquals(mockServiceAddress, appointment.getServiceAddress()); - assertEquals(COMPANY_NUMBER, appointment.getDataCompanyNumber()); Links links = appointment.getLinks(); @@ -110,25 +116,29 @@ void create() { @Test void createScottish() { - final Address mockServiceAddress = new Address( - "","","","","","" - ); - + final Address mockServiceAddress = new Address("", "", "", "", "", ""); CompanySpec spec = new CompanySpec(); spec.setCompanyNumber(COMPANY_NUMBER); spec.setJurisdiction(Jurisdiction.SCOTLAND); when(randomService.getNumber(INTERNAL_ID_LENGTH)).thenReturn(GENERATED_ID); - when(this.randomService.getEncodedIdWithSalt(10, 8)).thenReturn(ENCODED_VALUE); - when(this.randomService.addSaltAndEncode(INTERNAL_ID_PREFIX + GENERATED_ID, 8)).thenReturn(ENCODED_INTERNAL_ID); - when(this.randomService.getEtag()).thenReturn(ETAG); - when(this.addressService.getAddress(Jurisdiction.SCOTLAND)).thenReturn(mockServiceAddress); - when(this.addressService.getCountryOfResidence(Jurisdiction.SCOTLAND)).thenReturn("Scotland"); + when(randomService.getEncodedIdWithSalt(10, 8)).thenReturn(ENCODED_VALUE); + when(randomService.addSaltAndEncode(INTERNAL_ID_PREFIX + GENERATED_ID, 8)) + .thenReturn(ENCODED_INTERNAL_ID); + when(randomService.getEtag()).thenReturn(ETAG); + + when(addressService.getAddress(Jurisdiction.SCOTLAND)).thenReturn(mockServiceAddress); + when(addressService.getCountryOfResidence(Jurisdiction.SCOTLAND)) + .thenReturn("Scotland"); + Appointment savedApt = new Appointment(); - when(this.appointmentsRepository.save(any())).thenReturn(savedApt); + when(appointmentsRepository.save(any())).thenReturn(savedApt); - Appointment returnedApt = this.appointmentsService.create(spec); + List returnedApts = appointmentsService.create(spec); + assertNotNull(returnedApts); + assertEquals(1, returnedApts.size()); + Appointment returnedApt = returnedApts.get(0); assertEquals(savedApt, returnedApt); ArgumentCaptor aptCaptor = ArgumentCaptor.forClass(Appointment.class); @@ -137,21 +147,22 @@ void createScottish() { Appointment appointment = aptCaptor.getValue(); assertNotNull(appointment); assertEquals(ENCODED_VALUE, appointment.getId()); + assertEquals(ENCODED_VALUE, appointment.getAppointmentId()); assertNotNull(appointment.getCreated()); + assertEquals(INTERNAL_ID_PREFIX + GENERATED_ID, appointment.getInternalId()); - assertEquals(ENCODED_VALUE, appointment.getAppointmentId()); - assertEquals("Company " + COMPANY_NUMBER, appointment.getCompanyName()); - assertEquals("active", appointment.getCompanyStatus()); assertEquals(ENCODED_INTERNAL_ID, appointment.getOfficerId()); assertEquals(COMPANY_NUMBER, appointment.getCompanyNumber()); assertNotNull(appointment.getUpdated()); + assertEquals("Company " + COMPANY_NUMBER, appointment.getCompanyName()); + assertEquals("active", appointment.getCompanyStatus()); assertEquals("British", appointment.getNationality()); assertEquals("Director", appointment.getOccupation()); assertTrue(appointment.isServiceAddressIsSameAsRegisteredOfficeAddress()); assertEquals("Scotland", appointment.getCountryOfResidence()); assertNotNull(appointment.getUpdatedAt()); - assertEquals("Test", appointment.getForename()); + assertTrue(appointment.getForename().startsWith("Test")); assertNotNull(appointment.getAppointedOn()); assertEquals("director", appointment.getOfficerRole()); assertEquals(ETAG, appointment.getEtag()); @@ -167,40 +178,121 @@ void createScottish() { assertNotNull(appointment.getDateOfBirth()); } + @Test + void createWithInvalidOfficerRole() { + CompanySpec spec = new CompanySpec(); + spec.setCompanyNumber(COMPANY_NUMBER); + spec.setOfficerRoles(List.of("invalid_role")); + + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { + appointmentsService.create(spec); + }); + + assertEquals("Invalid officer role: invalid_role", exception.getMessage()); + } + + @Test + void createWithMultipleAppointments() { + final Address mockServiceAddress = new Address("", "", "", "", "", ""); + CompanySpec spec = new CompanySpec(); + spec.setCompanyNumber(COMPANY_NUMBER); + spec.setNumberOfAppointments(3); + spec.setOfficerRoles(List.of("director", "secretary", "director")); + + when(randomService.getNumber(INTERNAL_ID_LENGTH)).thenReturn(GENERATED_ID); + when(randomService.getEncodedIdWithSalt(10, 8)).thenReturn(ENCODED_VALUE); + when(randomService.addSaltAndEncode(INTERNAL_ID_PREFIX + GENERATED_ID, 8)) + .thenReturn(ENCODED_INTERNAL_ID); + when(randomService.getEtag()).thenReturn(ETAG); + + when(addressService.getAddress(Jurisdiction.ENGLAND_WALES)).thenReturn(mockServiceAddress); + when(addressService.getCountryOfResidence(Jurisdiction.ENGLAND_WALES)) + .thenReturn("Wales"); + + Appointment savedApt = new Appointment(); + when(appointmentsRepository.save(any())).thenReturn(savedApt); + + List returnedApts = appointmentsService.create(spec); + + assertNotNull(returnedApts); + assertEquals(3, returnedApts.size()); + + verify(appointmentsRepository, times(3)).save(any(Appointment.class)); + } + + @Test + void createWithDefaultOfficerRole() { + final Address mockServiceAddress = new Address("", "", "", "", "", ""); + CompanySpec spec = new CompanySpec(); + spec.setCompanyNumber(COMPANY_NUMBER); + spec.setNumberOfAppointments(2); + + when(randomService.getNumber(INTERNAL_ID_LENGTH)).thenReturn(GENERATED_ID); + when(randomService.getEncodedIdWithSalt(10, 8)).thenReturn(ENCODED_VALUE); + when(randomService.addSaltAndEncode(INTERNAL_ID_PREFIX + GENERATED_ID, 8)) + .thenReturn(ENCODED_INTERNAL_ID); + when(randomService.getEtag()).thenReturn(ETAG); + + when(addressService.getAddress(Jurisdiction.ENGLAND_WALES)).thenReturn(mockServiceAddress); + when(addressService.getCountryOfResidence(Jurisdiction.ENGLAND_WALES)) + .thenReturn("Wales"); + + Appointment savedApt = new Appointment(); + when(appointmentsRepository.save(any())).thenReturn(savedApt); + + List returnedApts = appointmentsService.create(spec); + + assertNotNull(returnedApts); + assertEquals(2, returnedApts.size()); + + verify(appointmentsRepository, times(2)).save(any(Appointment.class)); + } + @Test void delete() { Appointment apt = new Appointment(); + apt.setOfficerId("TEST_OFFICER_ID"); + OfficerAppointment officerAppointment = new OfficerAppointment(); - final String officerId = "TEST"; - apt.setOfficerId(officerId); - when(appointmentsRepository.findByCompanyNumber(COMPANY_NUMBER)).thenReturn(Optional.of(apt)); - when(officerRepository.findById(officerId)).thenReturn(Optional.of(officerAppointment)); + when(appointmentsRepository.findAllByCompanyNumber(COMPANY_NUMBER)) + .thenReturn(Collections.singletonList(apt)); + + when(officerRepository.findById("TEST_OFFICER_ID")) + .thenReturn(Optional.of(officerAppointment)); + + boolean result = appointmentsService.delete(COMPANY_NUMBER); - assertTrue(this.appointmentsService.delete(COMPANY_NUMBER)); + assertTrue(result); + verify(officerRepository).findById("TEST_OFFICER_ID"); verify(officerRepository).delete(officerAppointment); - verify(appointmentsRepository).delete(apt); + verify(appointmentsRepository).deleteAll(Collections.singletonList(apt)); } @Test - void deleteNoAppointmentDataException() { - when(appointmentsRepository.findByCompanyNumber(COMPANY_NUMBER)).thenReturn(Optional.empty()); - - assertFalse(this.appointmentsService.delete(COMPANY_NUMBER)); + void deleteNoAppointmentData() { + when(appointmentsRepository.findAllByCompanyNumber(COMPANY_NUMBER)) + .thenReturn(Collections.emptyList()); + + boolean result = appointmentsService.delete(COMPANY_NUMBER); + assertFalse(result); + verify(officerRepository, never()).delete(any()); - verify(appointmentsRepository, never()).delete(any()); + verify(appointmentsRepository, never()).deleteAll(anyList()); } @Test - void deleteNoOfficerDataException() { + void deleteNoOfficerData() { Appointment apt = new Appointment(); - final String officerId = "TEST"; - apt.setOfficerId(officerId); - when(appointmentsRepository.findByCompanyNumber(COMPANY_NUMBER)).thenReturn(Optional.of(apt)); - when(officerRepository.findById(officerId)).thenReturn(Optional.empty()); + apt.setOfficerId("UNKNOWN_OFFICER_ID"); - assertTrue(this.appointmentsService.delete(COMPANY_NUMBER)); + when(appointmentsRepository.findAllByCompanyNumber(COMPANY_NUMBER)) + .thenReturn(Collections.singletonList(apt)); + when(officerRepository.findById("UNKNOWN_OFFICER_ID")) + .thenReturn(Optional.empty()); + + boolean result = appointmentsService.delete(COMPANY_NUMBER); + assertTrue(result); verify(officerRepository, never()).delete(any()); - verify(appointmentsRepository).delete(apt); + verify(appointmentsRepository).deleteAll(Collections.singletonList(apt)); } - } From 539cb432f5eeefc578abe82aaccd512dc5ae8f1d Mon Sep 17 00:00:00 2001 From: kuzonduch Date: Fri, 14 Feb 2025 10:51:00 +0000 Subject: [PATCH 2/5] updating unit test to fix pr comments --- .../impl/AppointmentsServiceImplTest.java | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/test/java/uk/gov/companieshouse/api/testdata/service/impl/AppointmentsServiceImplTest.java b/src/test/java/uk/gov/companieshouse/api/testdata/service/impl/AppointmentsServiceImplTest.java index 29f84dc5..c12f7c47 100644 --- a/src/test/java/uk/gov/companieshouse/api/testdata/service/impl/AppointmentsServiceImplTest.java +++ b/src/test/java/uk/gov/companieshouse/api/testdata/service/impl/AppointmentsServiceImplTest.java @@ -191,6 +191,19 @@ void createWithInvalidOfficerRole() { assertEquals("Invalid officer role: invalid_role", exception.getMessage()); } + @Test + void createWithMixedValidAndInvalidOfficerRoles() { + CompanySpec spec = new CompanySpec(); + spec.setCompanyNumber(COMPANY_NUMBER); + spec.setOfficerRoles(List.of("director", "invalid_role", "secretary")); + + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { + appointmentsService.create(spec); + }); + + assertEquals("Invalid officer role: invalid_role", exception.getMessage()); + } + @Test void createWithMultipleAppointments() { final Address mockServiceAddress = new Address("", "", "", "", "", ""); @@ -217,7 +230,13 @@ void createWithMultipleAppointments() { assertNotNull(returnedApts); assertEquals(3, returnedApts.size()); - verify(appointmentsRepository, times(3)).save(any(Appointment.class)); + ArgumentCaptor aptCaptor = ArgumentCaptor.forClass(Appointment.class); + verify(appointmentsRepository, times(3)).save(aptCaptor.capture()); + + List capturedAppointments = aptCaptor.getAllValues(); + assertEquals("director", capturedAppointments.get(0).getOfficerRole()); + assertEquals("secretary", capturedAppointments.get(1).getOfficerRole()); + assertEquals("director", capturedAppointments.get(2).getOfficerRole()); } @Test From 509351b5ab16732e91c5150a42bfbdf0977a12d5 Mon Sep 17 00:00:00 2001 From: kuzonduch Date: Fri, 14 Feb 2025 11:48:16 +0000 Subject: [PATCH 3/5] refactor, remove unused code to fix pr comments --- .../repository/AppointmentsRepository.java | 1 - .../testdata/service/AppointmentService.java | 22 --------- .../service/impl/AppointmentsServiceImpl.java | 49 ++++++++++--------- .../service/impl/TestDataServiceImpl.java | 3 +- 4 files changed, 28 insertions(+), 47 deletions(-) delete mode 100644 src/main/java/uk/gov/companieshouse/api/testdata/service/AppointmentService.java diff --git a/src/main/java/uk/gov/companieshouse/api/testdata/repository/AppointmentsRepository.java b/src/main/java/uk/gov/companieshouse/api/testdata/repository/AppointmentsRepository.java index 50e90092..b27e24ea 100644 --- a/src/main/java/uk/gov/companieshouse/api/testdata/repository/AppointmentsRepository.java +++ b/src/main/java/uk/gov/companieshouse/api/testdata/repository/AppointmentsRepository.java @@ -1,7 +1,6 @@ package uk.gov.companieshouse.api.testdata.repository; import java.util.List; -import java.util.Optional; import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.data.repository.NoRepositoryBean; diff --git a/src/main/java/uk/gov/companieshouse/api/testdata/service/AppointmentService.java b/src/main/java/uk/gov/companieshouse/api/testdata/service/AppointmentService.java deleted file mode 100644 index 7549520e..00000000 --- a/src/main/java/uk/gov/companieshouse/api/testdata/service/AppointmentService.java +++ /dev/null @@ -1,22 +0,0 @@ -package uk.gov.companieshouse.api.testdata.service; - -import uk.gov.companieshouse.api.testdata.model.entity.Appointment; -import uk.gov.companieshouse.api.testdata.model.rest.CompanySpec; - -import java.util.List; - -public interface AppointmentService { - - /** - * Creates one or more Appointment entities for the given CompanySpec, - * and returns them all in a list. - */ - List create(CompanySpec spec); - - /** - * Deletes an appointment by its company number. - * - * @return true if found and deleted, false otherwise - */ - boolean delete(String companyNumber); -} diff --git a/src/main/java/uk/gov/companieshouse/api/testdata/service/impl/AppointmentsServiceImpl.java b/src/main/java/uk/gov/companieshouse/api/testdata/service/impl/AppointmentsServiceImpl.java index e1fc70ee..d7d79e16 100644 --- a/src/main/java/uk/gov/companieshouse/api/testdata/service/impl/AppointmentsServiceImpl.java +++ b/src/main/java/uk/gov/companieshouse/api/testdata/service/impl/AppointmentsServiceImpl.java @@ -18,11 +18,11 @@ import uk.gov.companieshouse.api.testdata.repository.AppointmentsRepository; import uk.gov.companieshouse.api.testdata.repository.OfficerRepository; import uk.gov.companieshouse.api.testdata.service.AddressService; -import uk.gov.companieshouse.api.testdata.service.AppointmentService; +import uk.gov.companieshouse.api.testdata.service.DataService; import uk.gov.companieshouse.api.testdata.service.RandomService; @Service -public class AppointmentsServiceImpl implements AppointmentService { +public class AppointmentsServiceImpl implements DataService,CompanySpec> { private static final int SALT_LENGTH = 8; private static final int ID_LENGTH = 10; @@ -44,7 +44,8 @@ public class AppointmentsServiceImpl implements AppointmentService { @Override public List create(CompanySpec spec) { final String companyNumber = spec.getCompanyNumber(); - final String countryOfResidence = addressService.getCountryOfResidence(spec.getJurisdiction()); + final String countryOfResidence = + addressService.getCountryOfResidence(spec.getJurisdiction()); int numberOfAppointments = spec.getNumberOfAppointments(); if (numberOfAppointments <= 0) { numberOfAppointments = 1; @@ -73,8 +74,10 @@ public List create(CompanySpec spec) { Appointment appointment = new Appointment(); String appointmentId = randomService.getEncodedIdWithSalt(ID_LENGTH, SALT_LENGTH); - String internalId = INTERNAL_ID_PREFIX + this.randomService.getNumber(INTERNAL_ID_LENGTH); - String officerId = randomService.addSaltAndEncode(internalId, SALT_LENGTH); + String internalId = + INTERNAL_ID_PREFIX + this.randomService.getNumber(INTERNAL_ID_LENGTH); + String officerId = + randomService.addSaltAndEncode(internalId, SALT_LENGTH); LocalDate officerDob = LocalDate.of(1990, 3, 6); Instant dateTimeNow = Instant.now(); @@ -181,23 +184,25 @@ private List createOfficerAppointmentItems( String companyNumber = companySpec.getCompanyNumber(); Jurisdiction jurisdiction = companySpec.getJurisdiction(); - OfficerAppointmentItem item = new OfficerAppointmentItem(); - item.setOccupation(OCCUPATION); - item.setAddress(addressService.getAddress(jurisdiction)); - item.setForename("Test"); - item.setSurname(OCCUPATION); - item.setOfficerRole(role); - item.setLinks(createOfficerAppointmentItemLinks(companyNumber, appointmentId)); - item.setCountryOfResidence(addressService.getCountryOfResidence(jurisdiction)); - item.setAppointedOn(dayNow); - item.setNationality("British"); - item.setUpdatedAt(dayTimeNow); - item.setName("Test DIRECTOR"); - item.setCompanyName("Company " + companyNumber); - item.setCompanyNumber(companyNumber); - item.setCompanyStatus("active"); - - officerAppointmentItemList.add(item); + OfficerAppointmentItem officerAppointmentItem = new OfficerAppointmentItem(); + officerAppointmentItem.setOccupation(OCCUPATION); + officerAppointmentItem.setAddress(addressService.getAddress(jurisdiction)); + officerAppointmentItem.setForename("Test"); + officerAppointmentItem.setSurname(OCCUPATION); + officerAppointmentItem.setOfficerRole(role); + officerAppointmentItem.setLinks( + createOfficerAppointmentItemLinks(companyNumber, appointmentId)); + officerAppointmentItem.setCountryOfResidence( + addressService.getCountryOfResidence(jurisdiction)); + officerAppointmentItem.setAppointedOn(dayNow); + officerAppointmentItem.setNationality("British"); + officerAppointmentItem.setUpdatedAt(dayTimeNow); + officerAppointmentItem.setName("Test DIRECTOR"); + officerAppointmentItem.setCompanyName("Company " + companyNumber); + officerAppointmentItem.setCompanyNumber(companyNumber); + officerAppointmentItem.setCompanyStatus("active"); + + officerAppointmentItemList.add(officerAppointmentItem); return officerAppointmentItemList; } diff --git a/src/main/java/uk/gov/companieshouse/api/testdata/service/impl/TestDataServiceImpl.java b/src/main/java/uk/gov/companieshouse/api/testdata/service/impl/TestDataServiceImpl.java index 189d38fb..9df858ed 100644 --- a/src/main/java/uk/gov/companieshouse/api/testdata/service/impl/TestDataServiceImpl.java +++ b/src/main/java/uk/gov/companieshouse/api/testdata/service/impl/TestDataServiceImpl.java @@ -32,7 +32,6 @@ import uk.gov.companieshouse.api.testdata.model.rest.UserSpec; import uk.gov.companieshouse.api.testdata.repository.AcspMembersRepository; -import uk.gov.companieshouse.api.testdata.service.AppointmentService; import uk.gov.companieshouse.api.testdata.service.CompanyAuthAllowListService; import uk.gov.companieshouse.api.testdata.service.CompanyAuthCodeService; import uk.gov.companieshouse.api.testdata.service.CompanyProfileService; @@ -57,7 +56,7 @@ public class TestDataServiceImpl implements TestDataService { @Autowired private CompanyAuthCodeService companyAuthCodeService; @Autowired - private AppointmentService appointmentService; + private DataService, CompanySpec> appointmentService; @Autowired private DataService companyMetricsService; @Autowired From 67d31ea849541a18111ed67acfa1437811e440ad Mon Sep 17 00:00:00 2001 From: kuzonduch Date: Fri, 14 Feb 2025 12:30:14 +0000 Subject: [PATCH 4/5] update READ me file --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index b52a86b7..607efde5 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,8 @@ In order to use the generator, there are different possible endpoints that can b - `type`: The type of the company (e.g., `ltd`, `plc`). Defaults to `ltd`. - `sub_type`: The subtype of the company (e.g., `community-interest-company`, `private-fund-limited-partnership`). Defaults to no subtype. - `has_super_secure_pscs`: Boolean value to determine if the company has super secure PSCs. Defaults to no value, field not present in the database. + - `number_of_appointments`: USed alongside `officer_roles` to determine the number of appointments to create. Defaults to 1. + - `officer_roles`: This takes a list of officer roles (`director`, `secretary`). Defaults to director when no role is passed. An usage example looks like this: `{"jurisdiction":"scotland", "company_status":"administration", "type":"plc", "sub_type":"community-interest-company", "has_super_secure_pscs":true}` - DELETE: Sending a DELETE request on the endpoint `{Base URL}/test-data/company/{companyNumber}` will delete the test company. There is a required parameter that is Authcode which needs to be included in the request body to be allowed to delete the test company. An usage example looks like this: `{"auth_code":"222222"}` From 4f773a781733879e0c5ccda5b7dfb7885a07e7ee Mon Sep 17 00:00:00 2001 From: kuzonduch Date: Fri, 14 Feb 2025 15:38:20 +0000 Subject: [PATCH 5/5] fix failing unit tes, pr comments --- README.md | 2 +- .../service/impl/AppointmentsServiceImpl.java | 6 ------ .../service/impl/TestDataServiceImplTest.java | 14 ++++++++------ 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 607efde5..5f7e394c 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ In order to use the generator, there are different possible endpoints that can b - `type`: The type of the company (e.g., `ltd`, `plc`). Defaults to `ltd`. - `sub_type`: The subtype of the company (e.g., `community-interest-company`, `private-fund-limited-partnership`). Defaults to no subtype. - `has_super_secure_pscs`: Boolean value to determine if the company has super secure PSCs. Defaults to no value, field not present in the database. - - `number_of_appointments`: USed alongside `officer_roles` to determine the number of appointments to create. Defaults to 1. + - `number_of_appointments`: Used alongside `officer_roles` to determine the number of appointments to create. Defaults to 1. - `officer_roles`: This takes a list of officer roles (`director`, `secretary`). Defaults to director when no role is passed. An usage example looks like this: `{"jurisdiction":"scotland", "company_status":"administration", "type":"plc", "sub_type":"community-interest-company", "has_super_secure_pscs":true}` diff --git a/src/main/java/uk/gov/companieshouse/api/testdata/service/impl/AppointmentsServiceImpl.java b/src/main/java/uk/gov/companieshouse/api/testdata/service/impl/AppointmentsServiceImpl.java index d7d79e16..f3cdc361 100644 --- a/src/main/java/uk/gov/companieshouse/api/testdata/service/impl/AppointmentsServiceImpl.java +++ b/src/main/java/uk/gov/companieshouse/api/testdata/service/impl/AppointmentsServiceImpl.java @@ -56,12 +56,6 @@ public List create(CompanySpec spec) { officerRoles = new ArrayList<>(); } - for (String role : officerRoles) { - if (!role.equalsIgnoreCase("director") && !role.equalsIgnoreCase("secretary")) { - throw new IllegalArgumentException("Invalid officer role: " + role); - } - } - while (officerRoles.size() < numberOfAppointments) { officerRoles.add("director"); } diff --git a/src/test/java/uk/gov/companieshouse/api/testdata/service/impl/TestDataServiceImplTest.java b/src/test/java/uk/gov/companieshouse/api/testdata/service/impl/TestDataServiceImplTest.java index 788a84b7..d0f8bc2d 100644 --- a/src/test/java/uk/gov/companieshouse/api/testdata/service/impl/TestDataServiceImplTest.java +++ b/src/test/java/uk/gov/companieshouse/api/testdata/service/impl/TestDataServiceImplTest.java @@ -82,7 +82,7 @@ class TestDataServiceImplTest { @Mock private CompanyAuthCodeService companyAuthCodeService; @Mock - private DataService appointmentService; + private DataService, CompanySpec> appointmentService; @Mock private DataService metricsService; @Mock @@ -134,7 +134,7 @@ void createCompanyDataDefaultSpec() throws Exception { final String fullCompanyNumber = COMPANY_NUMBER; when(companyProfileService.companyExists(fullCompanyNumber)).thenReturn(false); when(this.companyAuthCodeService.create(any())).thenReturn(mockAuthCode); - when(this.appointmentService.create(any())).thenReturn(mockAppointment); + when(this.appointmentService.create(any())).thenReturn(List.of(mockAppointment)); CompanySpec spec = new CompanySpec(); CompanyData createdCompany = this.testDataService.createCompanyData(spec); @@ -174,7 +174,8 @@ void createCompanyDataScottishSpec() throws Exception { final String fullCompanyNumber = SCOTTISH_COMPANY_PREFIX + COMPANY_NUMBER; when(companyProfileService.companyExists(fullCompanyNumber)).thenReturn(false); when(this.companyAuthCodeService.create(any())).thenReturn(mockAuthCode); - when(this.appointmentService.create(any())).thenReturn(mockAppointment); + when(this.appointmentService.create(any())).thenReturn(List.of(mockAppointment)); + CompanyData createdCompany = this.testDataService.createCompanyData(spec); verify(companyProfileService, times(1)).create(specCaptor.capture()); @@ -212,7 +213,8 @@ void createCompanyDataNISpec() throws Exception { final String fullCompanyNumber = NI_COMPANY_PREFIX + COMPANY_NUMBER; when(companyProfileService.companyExists(fullCompanyNumber)).thenReturn(false); when(this.companyAuthCodeService.create(any())).thenReturn(mockAuthCode); - when(this.appointmentService.create(any())).thenReturn(mockAppointment); + when(this.appointmentService.create(any())).thenReturn(List.of(mockAppointment)); + CompanyData createdCompany = this.testDataService.createCompanyData(spec); verify(companyProfileService, times(1)).create(specCaptor.capture()); @@ -250,7 +252,7 @@ void createCompanyDataSpec() throws Exception { when(this.randomService.getNumber(8)).thenReturn(Long.valueOf(companyNumber)); when(companyProfileService.companyExists(companyNumber)).thenReturn(false); when(this.companyAuthCodeService.create(any())).thenReturn(mockAuthCode); - when(this.appointmentService.create(any())).thenReturn(mockAppointment); + when(this.appointmentService.create(any())).thenReturn(List.of(mockAppointment)); CompanyData createdCompany = this.testDataService.createCompanyData(spec); @@ -295,7 +297,7 @@ void createCompanyDataExistingNumber() throws Exception { when(companyProfileService.companyExists(fullCompanyNumber)).thenReturn(false); when(this.companyAuthCodeService.create(any())).thenReturn(mockAuthCode); - when(this.appointmentService.create(any())).thenReturn(mockAppointment); + when(this.appointmentService.create(any())).thenReturn(List.of(mockAppointment)); CompanyData createdCompany = this.testDataService.createCompanyData(spec);