Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
4 changes: 3 additions & 1 deletion .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@
# unless a later match takes precedence, and will be requested for
# review when someone opens a pull request.
* @paulushcgcj @mamartinezmejia
/.github/workflows/ @paulushcgcj @DerekRoberts
/.github/workflows/ @paulushcgcj @DerekRoberts
/frontend @fterra-encora
/cypress @fterra-encora
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public final class ApplicationConstant {
public static final String POSTGRES_ATTRIBUTE_SCHEMA = "nrfc";

public static final String USERID_HEADER = "x-user-id";
public static final String BUSINESSID_HEADER = "x-user-businessid";
public static final String USERMAIL_HEADER = "x-user-email";
public static final String USERNAME_HEADER = "x-user-name";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package ca.bc.gov.app.controller.client;

import ca.bc.gov.app.ApplicationConstant;
import ca.bc.gov.app.dto.bcregistry.ClientDetailsDto;
import ca.bc.gov.app.dto.client.ClientLookUpDto;
import ca.bc.gov.app.dto.client.CodeNameDto;
Expand All @@ -8,13 +9,16 @@
import ca.bc.gov.app.service.client.ClientService;
import java.time.LocalDate;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.WordUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
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.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;
Expand All @@ -25,13 +29,18 @@
@RestController
@RequestMapping(value = "/api/clients", produces = MediaType.APPLICATION_JSON_VALUE)
@RequiredArgsConstructor
@Slf4j
public class ClientController {

private final ClientService clientService;

@GetMapping("/{clientNumber}")
public Mono<ClientDetailsDto> getClientDetails(@PathVariable String clientNumber) {
return clientService.getClientDetails(clientNumber);
public Mono<ClientDetailsDto> getClientDetails(
@PathVariable String clientNumber,
@RequestHeader(ApplicationConstant.USERID_HEADER) String userId,
@RequestHeader(name = ApplicationConstant.BUSINESSID_HEADER, defaultValue = StringUtils.EMPTY) String businessId
) {
return clientService.getClientDetails(clientNumber,userId,businessId);
}

@GetMapping("/activeCountryCodes")
Expand Down Expand Up @@ -108,10 +117,23 @@ public Mono<ClientLookUpDto> findByIncorporationNumber(
.switchIfEmpty(Mono.error(new NoClientDataFound(incorporationId)));
}

@GetMapping(value = "/individual/{userId}")
public Mono<Void> findByIndividual(
@PathVariable String userId,
@RequestParam String lastName
) {
log.info("Receiving request to search individual with id {} and last name {}", userId, lastName);
return clientService.findByIndividual(userId,lastName);
}

@PostMapping("/mail")
@ResponseStatus(HttpStatus.ACCEPTED)
public Mono<Void> sendEmail(@RequestBody EmailRequestDto emailRequestDto) {
return clientService.triggerEmailDuplicatedClient(emailRequestDto);
public Mono<Void> sendEmail(
@RequestBody EmailRequestDto emailRequestDto,
@RequestHeader(ApplicationConstant.USERID_HEADER) String userId,
@RequestHeader(name = ApplicationConstant.BUSINESSID_HEADER, defaultValue = StringUtils.EMPTY) String businessId
) {
return clientService.triggerEmailDuplicatedClient(emailRequestDto, userId, businessId);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import ca.bc.gov.app.validator.client.ClientSubmitRequestValidator;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
Expand Down Expand Up @@ -77,6 +78,7 @@ public Flux<ClientListSubmissionDto> listSubmissions(
public Mono<Void> submit(
@RequestBody ClientSubmissionDto request,
@RequestHeader(ApplicationConstant.USERID_HEADER) String userId,
@RequestHeader(name = ApplicationConstant.BUSINESSID_HEADER, defaultValue = StringUtils.EMPTY) String businessId,
@RequestHeader(ApplicationConstant.USERMAIL_HEADER) String userEmail,
@RequestHeader(ApplicationConstant.USERNAME_HEADER) String userName,
ServerHttpResponse serverResponse) {
Expand All @@ -85,7 +87,12 @@ public Mono<Void> submit(
Mono.error(new InvalidRequestObjectException("no request body was provided"))
)
.doOnNext(this::validate)
.flatMap(submissionDto -> clientService.submit(submissionDto, userId, userEmail, userName))
.flatMap(submissionDto -> clientService.submit(
submissionDto,
userId,
userEmail,
userName,
businessId))
.doOnNext(submissionId ->
serverResponse
.getHeaders()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,13 @@ public ClientAlreadyExistException(
)
);
}


public ClientAlreadyExistException(String clientNumber) {
super(HttpStatus.CONFLICT,
String.format(
"Client already exists with the client number %s",
clientNumber
)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.util.Map;
import java.util.Optional;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
Expand All @@ -20,21 +21,37 @@ public ClientLegacyService(@Qualifier("legacyApi") WebClient legacyApi) {
}

/**
* Searches for a list of {@link ForestClientDto} in the legacy API based on
* the given incorporation number and company name.
* Searches for a list of {@link ForestClientDto} in the legacy API based on the given
* incorporation number and company name.
*
* @param incorporationNumber the incorporation number to search for
* @param companyName the company name to search for
* @param userId the id of the user making the request
* @param businessId the id of the business making the request in case of bceid
* @return a Flux of ForestClientDto objects matching the search criteria
*/
public Flux<ForestClientDto> searchLegacy(String incorporationNumber, String companyName) {
public Flux<ForestClientDto> searchLegacy(
String incorporationNumber,
String companyName,
String userId,
String businessId
) {
return
legacyApi
.get()
.uri(builder ->
builder
.path("/search/incorporationOrName")
.queryParamIfPresent("incorporationNumber", Optional.ofNullable(incorporationNumber))
.queryParamIfPresent("incorporationNumber",
Optional
.ofNullable(incorporationNumber)
.filter(StringUtils::isNotBlank)
.or(
() -> Optional
.ofNullable(userId)
.filter(StringUtils::isNotBlank)
)
)
.queryParamIfPresent("companyName", Optional.ofNullable(companyName))
.build(Map.of())
)
Expand All @@ -43,4 +60,25 @@ public Flux<ForestClientDto> searchLegacy(String incorporationNumber, String com
dto -> log.info("Loading Legacy data for {} {} from legacy with client number {}",
incorporationNumber, companyName, dto.clientNumber()));
}

public Flux<ForestClientDto> searchIdAndLastName(
String id,
String lastName
) {
return
legacyApi
.get()
.uri(builder ->
builder
.path("/search/idAndLastName")
.queryParam("clientId", id)
.queryParam("lastName", lastName)
.build(Map.of())
)
.exchangeToFlux(response -> response.bodyToFlux(ForestClientDto.class))
.doOnNext(
dto -> log.info("Loading Legacy data for {} {} from legacy with client number {}",
id, lastName, dto.clientNumber())
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,9 @@ public Flux<CodeNameDto> listClientContactTypeCodes(LocalDate activeDate,int pag
* @return a Mono that emits a ClientDetailsDto object representing the details of the client
*/
public Mono<ClientDetailsDto> getClientDetails(
String clientNumber
String clientNumber,
String userId,
String businessId
) {
log.info("Loading details for {}", clientNumber);
return
Expand All @@ -183,7 +185,12 @@ public Mono<ClientDetailsDto> getClientDetails(
)
.flatMap(document ->
legacyService
.searchLegacy(document.business().identifier(), document.business().legalName())
.searchLegacy(
document.business().identifier(),
document.business().legalName(),
userId,
businessId
)
.next()
.filter(isMatchWith(document))
.doOnNext(legacy ->
Expand Down Expand Up @@ -268,16 +275,37 @@ public Mono<String> sendEmail(EmailRequestDto emailRequestDto) {
* @param emailRequestDto The request data containing user and client details.
* @return A {@link Mono} of {@link Void}.
*/
public Mono<Void> triggerEmailDuplicatedClient(EmailRequestDto emailRequestDto) {
public Mono<Void> triggerEmailDuplicatedClient(
EmailRequestDto emailRequestDto,
String userId,
String businessId
) {
return
legacyService
.searchLegacy(emailRequestDto.incorporation(), emailRequestDto.name())
.searchLegacy(
emailRequestDto.incorporation(),
emailRequestDto.name(),
userId,
businessId
)
.next()
.flatMap(
triggerEmailDuplicatedClient(emailRequestDto.email(), emailRequestDto.userName()))
.then();
}


public Mono<Void> findByIndividual(String userId, String lastName) {
return legacyService
.searchIdAndLastName(userId, lastName)
.doOnNext(legacy -> log.info("Found legacy entry for {} {}", userId, lastName))
//If we have result, we return a Mono.error with the exception, otherwise return a Mono.empty
.next()
.flatMap(legacy -> Mono
.error(new ClientAlreadyExistException(legacy.clientNumber()))
);
}

private Function<BcRegistryDocumentDto, Mono<ClientDetailsDto>> buildDetails() {
return document ->
buildAddress(document,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,8 @@ public Mono<Integer> submit(
ClientSubmissionDto clientSubmissionDto,
String userId,
String userEmail,
String userName
String userName,
String businessId
) {

return
Expand All @@ -140,7 +141,7 @@ public Mono<Integer> submit(
.submissionType(SubmissionTypeCodeEnum.SPP)
.submissionDate(LocalDateTime.now())
.createdBy(userId)
.updatedBy(userId)
.updatedBy(userName)
.build()
)
//Save submission to begin with
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.junit.jupiter.params.provider.MethodSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.MediaType;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.web.util.UriBuilder;
Expand Down Expand Up @@ -434,6 +435,7 @@ void shouldSendEmail() {
.post()
.uri("/api/clients/mail")
.body(Mono.just(TestConstants.EMAIL_REQUEST), EmailRequestDto.class)
.header(ApplicationConstant.USERID_HEADER, "testUserId")
.exchange()
.expectStatus().isAccepted()
.expectBody().isEmpty();
Expand All @@ -442,7 +444,7 @@ void shouldSendEmail() {

@Test
@DisplayName("get country by code")
void shoulGgetCountryByCode() {
void shouldGetCountryByCode() {

client
.get()
Expand All @@ -454,6 +456,48 @@ void shoulGgetCountryByCode() {

}

@Test
@DisplayName("check for individual conflicts")
void shouldCheckIndividual() {

legacyStub
.stubFor(
get(urlPathEqualTo("/search/idAndLastName"))
.withQueryParam("clientId",equalTo("123456"))
.withQueryParam("lastName", equalTo("Doe"))
.willReturn(okJson(TestConstants.LEGACY_OK))
);

client
.get()
.uri("/api/clients/individual/{userId}?lastName=Doe", Map.of("userId", "123456"))
.exchange()
.expectStatus().isEqualTo(HttpStatus.CONFLICT)
.expectBody(String.class)
.isEqualTo("Client already exists with the client number 00000002");
}

@Test
@DisplayName("check for individual conflicts and get none")
void shouldCheckIndividualWithoutConflict() {

legacyStub
.stubFor(
get(urlPathEqualTo("/search/idAndLastName"))
.withQueryParam("clientId",equalTo("123456"))
.withQueryParam("lastName", equalTo("Doe"))
.willReturn(okJson("[]"))
);

client
.get()
.uri("/api/clients/individual/{userId}?lastName=Doe", Map.of("userId", "123456"))
.exchange()
.expectStatus().isOk()
.expectBody()
.isEmpty();
}

private static Stream<Arguments> clientDetailing() {
return
Stream.of(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ void shouldListAndSearch(
.jsonPath("$.[0].requestType").isEqualTo("Submission pending processing")
.jsonPath("$.[0].status").isEqualTo("New")
.jsonPath("$.[0].clientType").isEqualTo("Registered sole proprietorship")
.jsonPath("$.[0].user").isEqualTo("testUserId");
.jsonPath("$.[0].user").isEqualTo("Test User");
}
}

Expand All @@ -229,7 +229,7 @@ void shouldGetSubmissionDetails() {
.expectStatus().isOk()
.expectBody()
.jsonPath("$.submissionId").isEqualTo(1)
.jsonPath("$.updateUser").isEqualTo("testUserId")
.jsonPath("$.updateUser").isEqualTo("Test User")
.jsonPath("$.submissionType").isEqualTo("Submission pending processing");
}

Expand Down
Loading