diff --git a/backend/src/main/java/ca/bc/gov/hlth/hnweb/controller/BcscPayeeMappingController.java b/backend/src/main/java/ca/bc/gov/hlth/hnweb/controller/BcscPayeeMappingController.java new file mode 100644 index 00000000..12c2ce1c --- /dev/null +++ b/backend/src/main/java/ca/bc/gov/hlth/hnweb/controller/BcscPayeeMappingController.java @@ -0,0 +1,149 @@ +package ca.bc.gov.hlth.hnweb.controller; + +import java.util.Optional; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +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; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.server.ResponseStatusException; + +import ca.bc.gov.hlth.hnweb.exception.BcscPayeeMappingException; +import ca.bc.gov.hlth.hnweb.model.rest.pbf.BcscPayeeMappingRequest; +import ca.bc.gov.hlth.hnweb.model.rest.pbf.BcscPayeeMappingResponse; +import ca.bc.gov.hlth.hnweb.persistence.entity.pbf.BcscPayeeMapping; +import ca.bc.gov.hlth.hnweb.service.BcscPayeeMappingService; + +/** + * Controller to handle CRUD requests for maintaining BC Services Card (BCSC) Users to their PBF MSP Payee Number mappings. + * + */ +@RequestMapping("/payee-mapping") +@RestController +public class BcscPayeeMappingController { + + private static final Logger logger = LoggerFactory.getLogger(BcscPayeeMappingController.class); + + @Autowired + private BcscPayeeMappingService bcscPayeeMappingService; + + /** + * Create a BCSC User to MSP Payee Number mapping + * + * @param bcscPayeeMappingRequest + * @return the response containing the newly created mapping if successful otherwise an error status + */ + @PostMapping("") + public ResponseEntity addBcscPayeeMapping(@RequestBody BcscPayeeMappingRequest bcscPayeeMappingRequest) { + logger.info("Adding a new BCSC User to Payee Mapping:\n{}", bcscPayeeMappingRequest.toString()); + + if (StringUtils.isBlank(bcscPayeeMappingRequest.getBcscGuid())) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Missing value in required request field bcscGuid."); + } + if (StringUtils.isBlank(bcscPayeeMappingRequest.getPayeeNumber())) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Missing value in required request field payeeNumber."); + } + + try { + BcscPayeeMapping bcscPayeeMapping = mapRequestToEntity(bcscPayeeMappingRequest); + BcscPayeeMapping newBcscPayeeMapping = bcscPayeeMappingService.add(bcscPayeeMapping); + BcscPayeeMappingResponse bcscPayeeMappingResponse = mapEntityToRepsonse(newBcscPayeeMapping); + return ResponseEntity.ok(bcscPayeeMappingResponse); + } catch(Exception exception) { + HttpStatus status = handleException(exception); + throw new ResponseStatusException(status, exception.getMessage(), exception); + } + } + + @PutMapping("/{id}") + public ResponseEntity updateBcscPayeeMapping(@RequestBody BcscPayeeMappingRequest bcscPayeeMappingRequest, @PathVariable String id) { + logger.info("Updating a BCSC User to Payee Mapping for ID: {}; Updated entity: \n{}", id, bcscPayeeMappingRequest.toString()); + + if (StringUtils.isBlank(bcscPayeeMappingRequest.getPayeeNumber())) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Missing value in required request field payeeNumber"); + } + + try { + BcscPayeeMapping bcscPayeeMapping = mapRequestToEntity(bcscPayeeMappingRequest); + BcscPayeeMapping updatedBcscPayeeMapping = bcscPayeeMappingService.update(bcscPayeeMapping, id); + BcscPayeeMappingResponse bcscPayeeMappingResponse = mapEntityToRepsonse(updatedBcscPayeeMapping); + return ResponseEntity.ok(bcscPayeeMappingResponse); + } catch(Exception exception) { + HttpStatus status = handleException(exception); + throw new ResponseStatusException(status, exception.getMessage(), exception); + } + } + + @GetMapping("/{id}") + public ResponseEntity getBcscPayeeMapping(@PathVariable String id) { + logger.info("Getting a BCSC User to Payee Mapping for ID: {}", id); + + Optional bcscPayeeMappingOptional = bcscPayeeMappingService.find(id); + if (bcscPayeeMappingOptional.isEmpty()) { + throw new ResponseStatusException(HttpStatus.NOT_FOUND, String.format("Entity not found for ID %s", id)); + } + + BcscPayeeMappingResponse bcscPayeeMappingResponse = mapEntityToRepsonse(bcscPayeeMappingOptional.get()); + return ResponseEntity.ok(bcscPayeeMappingResponse); + } + + @DeleteMapping("/{id}") + public ResponseEntity deleteBcscPayeeMapping(@PathVariable String id) { + logger.info("Deleting a BCSC User to Payee Mapping for ID: {}", id); + + try { + bcscPayeeMappingService.delete(id); + return ResponseEntity.noContent().build(); + } catch(Exception exception) { + HttpStatus status = handleException(exception); + throw new ResponseStatusException(status, exception.getMessage(), exception); + } + } + + private BcscPayeeMappingResponse mapEntityToRepsonse(BcscPayeeMapping newBcscPayeeMapping) { + BcscPayeeMappingResponse bcscPayeeMappingResponse = new BcscPayeeMappingResponse(); + bcscPayeeMappingResponse.setBcscGuid(newBcscPayeeMapping.getBcscGuid()); + bcscPayeeMappingResponse.setPayeeNumber(newBcscPayeeMapping.getPayeeNumber()); + return bcscPayeeMappingResponse; + } + + private BcscPayeeMapping mapRequestToEntity(BcscPayeeMappingRequest bcscPayeeMappingRequest) { + BcscPayeeMapping bcscPayeeMapping = new BcscPayeeMapping(); + bcscPayeeMapping.setBcscGuid(bcscPayeeMappingRequest.getBcscGuid()); + bcscPayeeMapping.setPayeeNumber(bcscPayeeMappingRequest.getPayeeNumber()); + return bcscPayeeMapping; + } + + private HttpStatus handleException(Exception exception) { + HttpStatus status; + + if (exception instanceof BcscPayeeMappingException) { + BcscPayeeMappingException bpme = (BcscPayeeMappingException)exception; + switch (bpme.getType()) { + case ENTITY_ALREADY_EXISTS: + status = HttpStatus.CONFLICT; + break; + case ENTITY_NOT_FOUND: + status = HttpStatus.NOT_FOUND; + break; + default: + status = HttpStatus.BAD_REQUEST; + } + } else { + status = HttpStatus.BAD_REQUEST; + } + + return status; + } + +} \ No newline at end of file diff --git a/backend/src/main/java/ca/bc/gov/hlth/hnweb/controller/PatientRegistrationController.java b/backend/src/main/java/ca/bc/gov/hlth/hnweb/controller/PatientRegistrationController.java index ac1d36a7..5e5e0de9 100644 --- a/backend/src/main/java/ca/bc/gov/hlth/hnweb/controller/PatientRegistrationController.java +++ b/backend/src/main/java/ca/bc/gov/hlth/hnweb/controller/PatientRegistrationController.java @@ -8,6 +8,7 @@ import java.util.Date; import java.util.HashSet; import java.util.List; +import java.util.Optional; import java.util.Set; import javax.servlet.http.HttpServletRequest; @@ -17,13 +18,16 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.server.ResponseStatusException; import ca.bc.gov.hlth.hnweb.converter.hl7v3.GetDemographicsConverter; +import ca.bc.gov.hlth.hnweb.exception.HNWebException; import ca.bc.gov.hlth.hnweb.model.rest.StatusEnum; import ca.bc.gov.hlth.hnweb.model.rest.enrollment.GetPersonDetailsResponse; import ca.bc.gov.hlth.hnweb.model.rest.patientregistration.PatientRegisterModel; @@ -34,8 +38,12 @@ import ca.bc.gov.hlth.hnweb.persistence.entity.AffectedPartyDirection; import ca.bc.gov.hlth.hnweb.persistence.entity.IdentifierType; import ca.bc.gov.hlth.hnweb.persistence.entity.Transaction; +import ca.bc.gov.hlth.hnweb.persistence.entity.pbf.BcscPayeeMapping; import ca.bc.gov.hlth.hnweb.persistence.entity.pbf.PatientRegister; +import ca.bc.gov.hlth.hnweb.security.SecurityUtil; import ca.bc.gov.hlth.hnweb.security.TransactionType; +import ca.bc.gov.hlth.hnweb.security.UserInfo; +import ca.bc.gov.hlth.hnweb.service.BcscPayeeMappingService; import ca.bc.gov.hlth.hnweb.service.EnrollmentService; import ca.bc.gov.hlth.hnweb.service.PatientRegistrationService; @@ -65,6 +73,9 @@ public class PatientRegistrationController extends BaseController { @Autowired private PatientRegistrationService patientRegistrationService; + + @Autowired + private BcscPayeeMappingService bcscPayeeMappingService; @PostMapping("/get-patient-registration") public ResponseEntity getPatientRegistration( @@ -77,6 +88,8 @@ public ResponseEntity getPatientRegistration( AffectedPartyDirection.INBOUND); try { + validatePayeeNumberMapping(patientRegistrationRequest); + // Retrieve demographic details GetDemographicsConverter converter = new GetDemographicsConverter(); GetDemographicsRequest demographicsRequest = converter.convertRequest(patientRegistrationRequest.getPhn()); @@ -119,6 +132,25 @@ public ResponseEntity getPatientRegistration( } } + /** + * The Payee number submitted in the request must match the Payee Number mapped to the current user in the BCSC to Payee Number mappings. + * + * @param patientRegistrationRequest + * @throws HNWebException + */ + private void validatePayeeNumberMapping(PatientRegistrationRequest patientRegistrationRequest) { + UserInfo userInfo = SecurityUtil.loadUserInfo(); + Optional bcscPayeeMappingOptional = bcscPayeeMappingService.find(userInfo.getUserId()); + if (bcscPayeeMappingOptional.isEmpty()) { + logger.error("No Payee Number mapping was found for the current user"); + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "No Payee Number mapping was found for the current user"); + } + if (!StringUtils.equals(patientRegistrationRequest.getPayee(), bcscPayeeMappingOptional.get().getPayeeNumber())) { + logger.error("Payee field value {} does not match the Payee Number mapped to this user", patientRegistrationRequest.getPayee()); + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, String.format("Payee field value %s does not match the Payee Number mapped to this user", patientRegistrationRequest.getPayee())); + } + } + private PatientRegistrationResponse handlePatientRegistrationResponse( PatientRegistrationResponse patientRegistrationResponse, boolean registrationExist, String infoMessage) { diff --git a/backend/src/main/java/ca/bc/gov/hlth/hnweb/exception/BcscPayeeMappingException.java b/backend/src/main/java/ca/bc/gov/hlth/hnweb/exception/BcscPayeeMappingException.java new file mode 100644 index 00000000..388fbdd6 --- /dev/null +++ b/backend/src/main/java/ca/bc/gov/hlth/hnweb/exception/BcscPayeeMappingException.java @@ -0,0 +1,28 @@ +package ca.bc.gov.hlth.hnweb.exception; + +import ca.bc.gov.hlth.hnweb.persistence.entity.pbf.BcscPayeeMapping; + +/** + * Exception class for errors related to the {@link BcscPayeeMapping} entity. + * + */ +public class BcscPayeeMappingException extends Exception { + + private static final long serialVersionUID = 1L; + + private BcscPayeeMappingExceptionType type; + + public BcscPayeeMappingException(BcscPayeeMappingExceptionType type) { + super(type.getMessage()); + this.type = type; + } + + public BcscPayeeMappingExceptionType getType() { + return type; + } + + public void setType(BcscPayeeMappingExceptionType type) { + this.type = type; + } + +} diff --git a/backend/src/main/java/ca/bc/gov/hlth/hnweb/exception/BcscPayeeMappingExceptionType.java b/backend/src/main/java/ca/bc/gov/hlth/hnweb/exception/BcscPayeeMappingExceptionType.java new file mode 100644 index 00000000..deaad374 --- /dev/null +++ b/backend/src/main/java/ca/bc/gov/hlth/hnweb/exception/BcscPayeeMappingExceptionType.java @@ -0,0 +1,22 @@ +package ca.bc.gov.hlth.hnweb.exception; + +/** + * enum for possible types of {@link BcscPayeeMappingException} + * + */ +public enum BcscPayeeMappingExceptionType { + + ENTITY_ALREADY_EXISTS("Entity already exists."), + ENTITY_NOT_FOUND("Entity not found."); + + private final String message; + + private BcscPayeeMappingExceptionType(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } + +} diff --git a/backend/src/main/java/ca/bc/gov/hlth/hnweb/exception/ExceptionType.java b/backend/src/main/java/ca/bc/gov/hlth/hnweb/exception/ExceptionType.java index 4d403ce9..e571350c 100644 --- a/backend/src/main/java/ca/bc/gov/hlth/hnweb/exception/ExceptionType.java +++ b/backend/src/main/java/ca/bc/gov/hlth/hnweb/exception/ExceptionType.java @@ -4,7 +4,7 @@ public enum ExceptionType { DOWNSTREAM_FAILURE("Could not connect to downstream service"), GENERAL("An error has occured"), SSL_FAILURE("SSL Context could not be built, application will not start"); - + ExceptionType(String message) { this.message = message; } diff --git a/backend/src/main/java/ca/bc/gov/hlth/hnweb/model/rest/pbf/BcscPayeeMappingRequest.java b/backend/src/main/java/ca/bc/gov/hlth/hnweb/model/rest/pbf/BcscPayeeMappingRequest.java new file mode 100644 index 00000000..52ddc3e8 --- /dev/null +++ b/backend/src/main/java/ca/bc/gov/hlth/hnweb/model/rest/pbf/BcscPayeeMappingRequest.java @@ -0,0 +1,30 @@ +package ca.bc.gov.hlth.hnweb.model.rest.pbf; + +public class BcscPayeeMappingRequest { + + private String bcscGuid; + + private String payeeNumber; + + public String getBcscGuid() { + return bcscGuid; + } + + public void setBcscGuid(String bcscGuid) { + this.bcscGuid = bcscGuid; + } + + public String getPayeeNumber() { + return payeeNumber; + } + + public void setPayeeNumber(String payeeNumber) { + this.payeeNumber = payeeNumber; + } + + @Override + public String toString() { + return "BcscPayeeMapping [bcscGuid=" + bcscGuid + ", payeeNumber=" + payeeNumber + "]"; + } + +} diff --git a/backend/src/main/java/ca/bc/gov/hlth/hnweb/model/rest/pbf/BcscPayeeMappingResponse.java b/backend/src/main/java/ca/bc/gov/hlth/hnweb/model/rest/pbf/BcscPayeeMappingResponse.java new file mode 100644 index 00000000..732967db --- /dev/null +++ b/backend/src/main/java/ca/bc/gov/hlth/hnweb/model/rest/pbf/BcscPayeeMappingResponse.java @@ -0,0 +1,30 @@ +package ca.bc.gov.hlth.hnweb.model.rest.pbf; + +public class BcscPayeeMappingResponse { + + private String bcscGuid; + + private String payeeNumber; + + public String getBcscGuid() { + return bcscGuid; + } + + public void setBcscGuid(String bcscGuid) { + this.bcscGuid = bcscGuid; + } + + public String getPayeeNumber() { + return payeeNumber; + } + + public void setPayeeNumber(String payeeNumber) { + this.payeeNumber = payeeNumber; + } + + @Override + public String toString() { + return "BcscPayeeMapping [bcscGuid=" + bcscGuid + ", payeeNumber=" + payeeNumber + "]"; + } + +} diff --git a/backend/src/main/java/ca/bc/gov/hlth/hnweb/persistence/entity/pbf/BcscPayeeMapping.java b/backend/src/main/java/ca/bc/gov/hlth/hnweb/persistence/entity/pbf/BcscPayeeMapping.java new file mode 100644 index 00000000..9b3b704b --- /dev/null +++ b/backend/src/main/java/ca/bc/gov/hlth/hnweb/persistence/entity/pbf/BcscPayeeMapping.java @@ -0,0 +1,44 @@ +package ca.bc.gov.hlth.hnweb.persistence.entity.pbf; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * Entity for table bcsc_payee_mapping which contains BCSC Users to MSP Payee Number mappings + * + */ +@Entity +@Table(name = "bcsc_payee_mapping", schema = "pbf") +public class BcscPayeeMapping { + + @Id + @Column(name = "bcsc_guid") + private String bcscGuid; + + @Column(name = "msp_payee_number") + private String payeeNumber; + + public String getBcscGuid() { + return bcscGuid; + } + + public void setBcscGuid(String bcscGuid) { + this.bcscGuid = bcscGuid; + } + + public String getPayeeNumber() { + return payeeNumber; + } + + public void setPayeeNumber(String payeeNumber) { + this.payeeNumber = payeeNumber; + } + + @Override + public String toString() { + return "BcscPayeeMapping [bcscGuid=" + bcscGuid + ", payeeNumber=" + payeeNumber + "]"; + } + +} \ No newline at end of file diff --git a/backend/src/main/java/ca/bc/gov/hlth/hnweb/persistence/repository/pbf/BcscPayeeMappingRepository.java b/backend/src/main/java/ca/bc/gov/hlth/hnweb/persistence/repository/pbf/BcscPayeeMappingRepository.java new file mode 100644 index 00000000..cbd29fec --- /dev/null +++ b/backend/src/main/java/ca/bc/gov/hlth/hnweb/persistence/repository/pbf/BcscPayeeMappingRepository.java @@ -0,0 +1,17 @@ +package ca.bc.gov.hlth.hnweb.persistence.repository.pbf; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; + +import ca.bc.gov.hlth.hnweb.persistence.entity.pbf.BcscPayeeMapping; + +/** + * Repository for {@link BcscPayeeMapping} + * + */ +public interface BcscPayeeMappingRepository extends JpaRepository { + + public List findByPayeeNumber(String payeeNumber); + +} diff --git a/backend/src/main/java/ca/bc/gov/hlth/hnweb/security/SecurityConfig.java b/backend/src/main/java/ca/bc/gov/hlth/hnweb/security/SecurityConfig.java index c9c7e19d..face8945 100644 --- a/backend/src/main/java/ca/bc/gov/hlth/hnweb/security/SecurityConfig.java +++ b/backend/src/main/java/ca/bc/gov/hlth/hnweb/security/SecurityConfig.java @@ -78,6 +78,10 @@ protected void configure(HttpSecurity http) throws Exception { .mvcMatchers(HttpMethod.POST, "/msp-contracts/get-contract-periods").hasRole("GetContractPeriods") .mvcMatchers(HttpMethod.POST, "/msp-contracts/update-contract-address").hasRole("UpdateContractAddress") .mvcMatchers(HttpMethod.POST, "/msp-contracts/inquire-contract").hasAnyRole("ContractInquiry", "GetGroupMembersContractAddress") //inquire-contract endpoint will require this multi role as it is used by both R40 and R37 transactions + .mvcMatchers(HttpMethod.GET, "/payee-mapping/").hasAnyRole("PatientRegistration", "ManageMSPPayeeNumber") + .mvcMatchers(HttpMethod.POST, "/payee-mapping").hasRole("ManageMSPPayeeNumber") + .mvcMatchers(HttpMethod.PUT, "/payee-mapping/").hasRole("ManageMSPPayeeNumber") + .mvcMatchers(HttpMethod.DELETE, "/payee-mapping/").hasRole("ManageMSPPayeeNumber") .mvcMatchers(HttpMethod.GET, "/user/**").fullyAuthenticated() .mvcMatchers("/*").denyAll() .and() diff --git a/backend/src/main/java/ca/bc/gov/hlth/hnweb/security/SecurityUtil.java b/backend/src/main/java/ca/bc/gov/hlth/hnweb/security/SecurityUtil.java index 9e149836..74d73f27 100644 --- a/backend/src/main/java/ca/bc/gov/hlth/hnweb/security/SecurityUtil.java +++ b/backend/src/main/java/ca/bc/gov/hlth/hnweb/security/SecurityUtil.java @@ -26,6 +26,7 @@ public class SecurityUtil { private static final String CLAIM_RESOURCE_ACCESS = "resource_access"; private static final String CLAIM_SESSION_STATE = "session_state"; public static final String CLAIM_USERNAME = "preferred_username"; + private static final String CLAIM_SUB = "sub"; //the Subject claim identifies the principal that is the subject of the JWT public static final String CLAIM_ORGANIZATION = "org_details"; private static final String ORGANIZATION_ID = "id"; @@ -51,6 +52,7 @@ public static UserInfo loadUserInfo() { userInfo.setSessionState(jwt.getClaim(CLAIM_SESSION_STATE)); userInfo.setUsername(jwt.getClaim(CLAIM_USERNAME)); + userInfo.setUserId(jwt.getClaim(CLAIM_SUB)); return userInfo; } diff --git a/backend/src/main/java/ca/bc/gov/hlth/hnweb/security/UserInfo.java b/backend/src/main/java/ca/bc/gov/hlth/hnweb/security/UserInfo.java index 9c01f37e..1b135aa0 100644 --- a/backend/src/main/java/ca/bc/gov/hlth/hnweb/security/UserInfo.java +++ b/backend/src/main/java/ca/bc/gov/hlth/hnweb/security/UserInfo.java @@ -5,6 +5,7 @@ */ public class UserInfo { private String username; + private String userId; private String organization; private String role; private String sessionState; @@ -20,9 +21,10 @@ public UserInfo(String username, String organization, String role) { this.role = role; } - public UserInfo(String username, String organization, String role, String sessionState) { + public UserInfo(String username, String userId, String organization, String role, String sessionState) { super(); this.username = username; + this.userId = userId; this.organization = organization; this.role = role; this.sessionState = sessionState; @@ -36,6 +38,14 @@ public void setUsername(String username) { this.username = username; } + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + public String getOrganization() { return organization; } @@ -60,4 +70,10 @@ public void setSessionState(String sessionState) { this.sessionState = sessionState; } + @Override + public String toString() { + return "UserInfo [username=" + username + ", userId=" + userId + ", organization=" + organization + ", role=" + + role + ", sessionState=" + sessionState + "]"; + } + } \ No newline at end of file diff --git a/backend/src/main/java/ca/bc/gov/hlth/hnweb/service/BcscPayeeMappingService.java b/backend/src/main/java/ca/bc/gov/hlth/hnweb/service/BcscPayeeMappingService.java new file mode 100644 index 00000000..ba90acc6 --- /dev/null +++ b/backend/src/main/java/ca/bc/gov/hlth/hnweb/service/BcscPayeeMappingService.java @@ -0,0 +1,93 @@ +package ca.bc.gov.hlth.hnweb.service; + +import java.util.Optional; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import ca.bc.gov.hlth.hnweb.exception.BcscPayeeMappingException; +import ca.bc.gov.hlth.hnweb.exception.BcscPayeeMappingExceptionType; +import ca.bc.gov.hlth.hnweb.persistence.entity.pbf.BcscPayeeMapping; +import ca.bc.gov.hlth.hnweb.persistence.repository.pbf.BcscPayeeMappingRepository; + +/** + * Service for maintaining BCSC Users to MSP Payee Number mappings + */ +@Service +public class BcscPayeeMappingService { + + private static final Logger logger = LoggerFactory.getLogger(BcscPayeeMappingService.class); + + @Autowired + private BcscPayeeMappingRepository bcscPayeeMappingRepository; + + /** + * Adds a mapping. + * + * @param bcscPayeeMapping the mapping information being added + * @return the newly created entity + * @throws BcscPayeeMappingException if the a BcscPayeeMapping entity for the new ID is already present + */ + public BcscPayeeMapping add(BcscPayeeMapping bcscPayeeMapping) throws BcscPayeeMappingException { + Optional optional = bcscPayeeMappingRepository.findById(bcscPayeeMapping.getBcscGuid()); + + if (optional.isPresent()) { + logger.info("BcscPayeeMapping entity already exists with ID {}", bcscPayeeMapping.getBcscGuid()); + throw new BcscPayeeMappingException(BcscPayeeMappingExceptionType.ENTITY_ALREADY_EXISTS); + } + + return bcscPayeeMappingRepository.save(bcscPayeeMapping); + } + + /** + * Updates a mapping. + * + * @param bcscPayeeMapping the new mapping information + * @param id the id of the entity to be updated + * @return the updated BcscPayeeMapping entity + * @throws BcscPayeeMappingException if the BcscPayeeMapping entity does not exist + */ + public BcscPayeeMapping update(BcscPayeeMapping bcscPayeeMapping, String id) throws BcscPayeeMappingException { + Optional optional = bcscPayeeMappingRepository.findById(id); + + if (optional.isEmpty()) { + logger.info("BcscPayeeMapping entity not found for ID {}", id); + throw new BcscPayeeMappingException(BcscPayeeMappingExceptionType.ENTITY_NOT_FOUND); + } + + BcscPayeeMapping existingEntity = optional.get(); + existingEntity.setPayeeNumber(bcscPayeeMapping.getPayeeNumber()); + + return bcscPayeeMappingRepository.save(existingEntity); + } + + /** + * Finds a BcscPayeeMapping for the given id + * @param id the id of the entity to be found. + * @return an Optional with BcscPayeeMapping entity or empty if not found + */ + public Optional find(String id) { + return bcscPayeeMappingRepository.findById(id); + } + + /** + * Deletes the BcscPayeeMapping entity for the give ID + * + * @param id the id of the BcscPayeeMapping entity to be deleted + * @throws BcscPayeeMappingException if the BcscPayeeMapping entity does not exist + */ + public void delete(String id) throws BcscPayeeMappingException { + Optional optional = bcscPayeeMappingRepository.findById(id); + + if (optional.isEmpty()) { + logger.info("BcscPayeeMapping entity not found for ID {}", id); + throw new BcscPayeeMappingException(BcscPayeeMappingExceptionType.ENTITY_NOT_FOUND); + } + + bcscPayeeMappingRepository.deleteById(id); + } + +} + diff --git a/backend/src/test/java/ca/bc/gov/hlth/hnweb/BaseControllerTest.java b/backend/src/test/java/ca/bc/gov/hlth/hnweb/BaseControllerTest.java index 150c324c..77242cb1 100644 --- a/backend/src/test/java/ca/bc/gov/hlth/hnweb/BaseControllerTest.java +++ b/backend/src/test/java/ca/bc/gov/hlth/hnweb/BaseControllerTest.java @@ -45,7 +45,7 @@ public class BaseControllerTest { protected static MockWebServer mockBackEnd; - private static MockedStatic mockStatic; + protected static MockedStatic mockStatic; @BeforeAll static void setUp() throws IOException { @@ -53,7 +53,7 @@ static void setUp() throws IOException { mockBackEnd.start(0); mockStatic = Mockito.mockStatic(SecurityUtil.class); - mockStatic.when(SecurityUtil::loadUserInfo).thenReturn(new UserInfo("unittest", "00000010", "hnweb-user", UUID.randomUUID().toString())); + mockStatic.when(SecurityUtil::loadUserInfo).thenReturn(new UserInfo("unittest", "3c0fc3b5-45f8-4745-afa9-b7b04978023d", "00000010", "hnweb-user", UUID.randomUUID().toString())); } @AfterAll diff --git a/backend/src/test/java/ca/bc/gov/hlth/hnweb/controller/BcscPayeeMappingControllerTest.java b/backend/src/test/java/ca/bc/gov/hlth/hnweb/controller/BcscPayeeMappingControllerTest.java new file mode 100644 index 00000000..51d342a0 --- /dev/null +++ b/backend/src/test/java/ca/bc/gov/hlth/hnweb/controller/BcscPayeeMappingControllerTest.java @@ -0,0 +1,202 @@ +package ca.bc.gov.hlth.hnweb.controller; + +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.junit.Assert.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.UUID; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.jdbc.Sql; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.server.ResponseStatusException; + +import ca.bc.gov.hlth.hnweb.model.rest.pbf.BcscPayeeMappingRequest; +import ca.bc.gov.hlth.hnweb.model.rest.pbf.BcscPayeeMappingResponse; + +/** + * Tests for {@link BcscPayeeMappingController} + * + */ +@SpringBootTest +@Transactional +@Sql({ "classpath:scripts/bcsc_payee_mapping.sql" }) +public class BcscPayeeMappingControllerTest { + + @Autowired + private BcscPayeeMappingController bcscPayeeMappingController; + + @Test + public void testAddBcscPayeeMapping_success() { + + String bcscGuid = UUID.randomUUID().toString(); + String payeeNumber = "00063"; + + BcscPayeeMappingRequest bcscPayeeMappingRequest = createBcscPayeeMappingRequest(bcscGuid, payeeNumber); + + ResponseEntity response = bcscPayeeMappingController.addBcscPayeeMapping(bcscPayeeMappingRequest); + assertEquals(HttpStatus.OK, response.getStatusCode()); + BcscPayeeMappingResponse bcscPayeeMappingResponse = response.getBody(); + assertNotNull(bcscPayeeMappingResponse); + assertEquals(bcscGuid, bcscPayeeMappingResponse.getBcscGuid()); + assertEquals(payeeNumber, bcscPayeeMappingResponse.getPayeeNumber()); + } + + @Test + public void testAddBcscPayeeMapping_fail_missing_bcsc_guid() { + + String bcscGuid = null; + String payeeNumber = "00063"; + + BcscPayeeMappingRequest bcscPayeeMappingRequest = createBcscPayeeMappingRequest(bcscGuid, payeeNumber); + + assertThatExceptionOfType(ResponseStatusException.class) + .isThrownBy(() -> bcscPayeeMappingController.addBcscPayeeMapping(bcscPayeeMappingRequest)) + .withMessage("400 BAD_REQUEST \"Missing value in required request field bcscGuid.\""); + } + + @Test + public void testAddBcscPayeeMapping_fail_missing_bcsc_guid_empty_value() { + + String bcscGuid = " "; //Should fail for anything except a populated String + String payeeNumber = "00063"; + + BcscPayeeMappingRequest bcscPayeeMappingRequest = createBcscPayeeMappingRequest(bcscGuid, payeeNumber); + + assertThatExceptionOfType(ResponseStatusException.class) + .isThrownBy(() -> bcscPayeeMappingController.addBcscPayeeMapping(bcscPayeeMappingRequest)) + .withMessage("400 BAD_REQUEST \"Missing value in required request field bcscGuid.\""); + } + + @Test + public void testAddBcscPayeeMapping_fail_missing_payee_number() { + + String bcscGuid = UUID.randomUUID().toString(); + String payeeNumber = " "; //Should fail for anything except a populated String + + BcscPayeeMappingRequest bcscPayeeMappingRequest = createBcscPayeeMappingRequest(bcscGuid, payeeNumber); + + assertThatExceptionOfType(ResponseStatusException.class) + .isThrownBy(() -> bcscPayeeMappingController.addBcscPayeeMapping(bcscPayeeMappingRequest)) + .withMessage("400 BAD_REQUEST \"Missing value in required request field payeeNumber.\""); + } + + @Test + public void testAddBcscPayeeMapping_fail_bcsc_already_exists() { + + String bcscGuid = "a9c3b536-4598-411a-bda2-4068d6b5cc20"; + String payeeNumber = "00063"; + + BcscPayeeMappingRequest bcscPayeeMappingRequest = createBcscPayeeMappingRequest(bcscGuid, payeeNumber); + + assertThatExceptionOfType(ResponseStatusException.class) + .isThrownBy(() -> bcscPayeeMappingController.addBcscPayeeMapping(bcscPayeeMappingRequest)) + .withMessage("409 CONFLICT \"Entity already exists.\"; nested exception is ca.bc.gov.hlth.hnweb.exception.BcscPayeeMappingException: Entity already exists."); + } + + @Test + public void testGetBcscPayeeMapping_success() { + + String bcscGuid = "a9c3b536-4598-411a-bda2-4068d6b5cc20"; + String payeeNumber = "00053"; + + ResponseEntity response = bcscPayeeMappingController.getBcscPayeeMapping(bcscGuid); + assertEquals(HttpStatus.OK, response.getStatusCode()); + BcscPayeeMappingResponse bcscPayeeMappingResponse = response.getBody(); + assertNotNull(bcscPayeeMappingResponse); + assertEquals(bcscGuid, bcscPayeeMappingResponse.getBcscGuid()); + assertEquals(payeeNumber, bcscPayeeMappingResponse.getPayeeNumber()); + } + + @Test + public void testGetBcscPayeeMapping_fail_not_found() { + + String bcscGuid = UUID.randomUUID().toString(); + + assertThatExceptionOfType(ResponseStatusException.class) + .isThrownBy(() -> bcscPayeeMappingController.getBcscPayeeMapping(bcscGuid)) + .withMessage("404 NOT_FOUND \"Entity not found for ID %s\"", bcscGuid); + } + + @Test + public void testUpdateBcscPayeeMapping_success() { + + String bcscGuid = "a9c3b536-4598-411a-bda2-4068d6b5cc20"; + String updatedPayeeNumber = "00023"; + + BcscPayeeMappingRequest bcscPayeeMappingRequest = createBcscPayeeMappingRequest(bcscGuid, updatedPayeeNumber); + + ResponseEntity response = bcscPayeeMappingController.updateBcscPayeeMapping(bcscPayeeMappingRequest, bcscGuid); + assertEquals(HttpStatus.OK, response.getStatusCode()); + BcscPayeeMappingResponse updatedBcscPayeeMappingResponse = response.getBody(); + assertNotNull(updatedBcscPayeeMappingResponse); + assertEquals(bcscGuid, updatedBcscPayeeMappingResponse.getBcscGuid()); + assertEquals(updatedPayeeNumber, updatedBcscPayeeMappingResponse.getPayeeNumber()); + } + + @Test + public void testUpdateBcscPayeeMapping_fail_does_not_exist() { + + String bcscGuid = "a9c3b536-4598-411a-bda2-4068d6b5cc20"; + String updatedPayeeNumber = "00023"; + + BcscPayeeMappingRequest bcscPayeeMappingRequest = createBcscPayeeMappingRequest(bcscGuid, updatedPayeeNumber); + + String incorrectBcscGuid = UUID.randomUUID().toString(); + + assertThatExceptionOfType(ResponseStatusException.class) + .isThrownBy(() -> bcscPayeeMappingController.updateBcscPayeeMapping(bcscPayeeMappingRequest, incorrectBcscGuid)) + .withMessage("404 NOT_FOUND \"Entity not found.\"; nested exception is ca.bc.gov.hlth.hnweb.exception.BcscPayeeMappingException: Entity not found."); + } + + @Test + public void testUpdateBcscPayeeMapping_fail_missing_payee_number() { + + String bcscGuid = "a9c3b536-4598-411a-bda2-4068d6b5cc20"; + String updatedPayeeNumber = " "; + + BcscPayeeMappingRequest bcscPayeeMappingRequest = createBcscPayeeMappingRequest(bcscGuid, updatedPayeeNumber); + + assertThatExceptionOfType(ResponseStatusException.class) + .isThrownBy(() -> bcscPayeeMappingController.updateBcscPayeeMapping(bcscPayeeMappingRequest, bcscGuid)) + .withMessage("400 BAD_REQUEST \"Missing value in required request field payeeNumber\""); + } + + @Test + public void testDeleteBcscPayeeMapping_success() { + + String bcscGuid = "a9c3b536-4598-411a-bda2-4068d6b5cc20"; + + ResponseEntity deleteRresponse = bcscPayeeMappingController.deleteBcscPayeeMapping(bcscGuid); + assertEquals(HttpStatus.NO_CONTENT, deleteRresponse.getStatusCode()); + assertEquals(deleteRresponse.getBody(), null); + + assertThatExceptionOfType(ResponseStatusException.class) + .isThrownBy(() -> bcscPayeeMappingController.getBcscPayeeMapping(bcscGuid)) + .withMessage("404 NOT_FOUND \"Entity not found for ID %s\"", bcscGuid); + } + + @Test + public void testDeleteBcscPayeeMapping_fail_not_found() { + + String bcscGuid = UUID.randomUUID().toString(); + + assertThatExceptionOfType(ResponseStatusException.class) + .isThrownBy(() -> bcscPayeeMappingController.deleteBcscPayeeMapping(bcscGuid)) + .withMessage("404 NOT_FOUND \"Entity not found.\"; nested exception is ca.bc.gov.hlth.hnweb.exception.BcscPayeeMappingException: Entity not found."); + } + + private BcscPayeeMappingRequest createBcscPayeeMappingRequest(String bcscGuid, String payeeNumber) { + BcscPayeeMappingRequest bcscPayeeMappingRequest = new BcscPayeeMappingRequest(); + bcscPayeeMappingRequest.setBcscGuid(bcscGuid); + bcscPayeeMappingRequest.setPayeeNumber(payeeNumber); + return bcscPayeeMappingRequest; + } + +} + + diff --git a/backend/src/test/java/ca/bc/gov/hlth/hnweb/controller/PatientRegistrationControllerTest.java b/backend/src/test/java/ca/bc/gov/hlth/hnweb/controller/PatientRegistrationControllerTest.java index e6d432d5..6455b4b9 100644 --- a/backend/src/test/java/ca/bc/gov/hlth/hnweb/controller/PatientRegistrationControllerTest.java +++ b/backend/src/test/java/ca/bc/gov/hlth/hnweb/controller/PatientRegistrationControllerTest.java @@ -1,5 +1,6 @@ package ca.bc.gov.hlth.hnweb.controller; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.junit.Assert.assertTrue; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.springframework.http.HttpHeaders.CONTENT_TYPE; @@ -7,6 +8,7 @@ import java.util.Date; import java.util.GregorianCalendar; import java.util.List; +import java.util.UUID; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -15,6 +17,8 @@ import org.springframework.http.ResponseEntity; import org.springframework.test.context.DynamicPropertyRegistry; import org.springframework.test.context.DynamicPropertySource; +import org.springframework.test.context.jdbc.Sql; +import org.springframework.web.server.ResponseStatusException; import ca.bc.gov.hlth.hnweb.BaseControllerTest; import ca.bc.gov.hlth.hnweb.model.rest.StatusEnum; @@ -25,6 +29,8 @@ import ca.bc.gov.hlth.hnweb.persistence.entity.pbf.PatientRegister; import ca.bc.gov.hlth.hnweb.persistence.repository.pbf.PBFClinicPayeeRepository; import ca.bc.gov.hlth.hnweb.persistence.repository.pbf.PatientRegisterRepository; +import ca.bc.gov.hlth.hnweb.security.SecurityUtil; +import ca.bc.gov.hlth.hnweb.security.UserInfo; import ca.bc.gov.hlth.hnweb.utils.TestUtil; import okhttp3.mockwebserver.MockResponse; @@ -32,6 +38,7 @@ * JUnit test class for PatientRegistrationController * */ +@Sql({ "classpath:scripts/bcsc_payee_mapping.sql" }) public class PatientRegistrationControllerTest extends BaseControllerTest { @Autowired @@ -43,7 +50,7 @@ public class PatientRegistrationControllerTest extends BaseControllerTest { @Autowired private PBFClinicPayeeRepository pbfClinicPayeeRepository; - @Test + @Test public void testRegistrationHistory_success_payeeWithinGroup_DemoRecord() throws Exception { createPBFClinicPayee(); createPatientRegister(); @@ -51,7 +58,10 @@ public void testRegistrationHistory_success_payeeWithinGroup_DemoRecord() throws .setBody(TestUtil.convertXMLFileToString("src/test/resources/GetDemographicsResponse.xml")) .addHeader(CONTENT_TYPE, MediaType.TEXT_XML_VALUE.toString())); - PatientRegistrationRequest viewPatientRegisterRequest = new PatientRegistrationRequest(); + //Override the base setup of the user to ensure we return the User with the User ID mapped to the this Payee Number + mockStatic.when(SecurityUtil::loadUserInfo).thenReturn(new UserInfo("unittest", "3c0fc3b5-45f8-4745-afa9-b7b04978023d", "00000010", "hnweb-user", UUID.randomUUID().toString())); + + PatientRegistrationRequest viewPatientRegisterRequest = new PatientRegistrationRequest(); viewPatientRegisterRequest.setPhn("9879869673"); viewPatientRegisterRequest.setPayee("T0055"); ResponseEntity response = patientRegistrationController @@ -77,7 +87,10 @@ public void testRegistrationHistory_success_payeeWithinGroup_NoDemoRecord() thro .setBody(TestUtil.convertXMLFileToString("src/test/resources/GetDemographicsResponse_Error.xml")) .addHeader(CONTENT_TYPE, MediaType.TEXT_XML_VALUE.toString())); - PatientRegistrationRequest viewPatientRegisterRequest = new PatientRegistrationRequest(); + //Override the base setup of the user to ensure we return the User with the User ID mapped to the this Payee Number + mockStatic.when(SecurityUtil::loadUserInfo).thenReturn(new UserInfo("unittest", "3c0fc3b5-45f8-4745-afa9-b7b04978023d", "00000010", "hnweb-user", UUID.randomUUID().toString())); + + PatientRegistrationRequest viewPatientRegisterRequest = new PatientRegistrationRequest(); viewPatientRegisterRequest.setPhn("9879869673"); viewPatientRegisterRequest.setPayee("T0055"); ResponseEntity response = patientRegistrationController @@ -104,7 +117,10 @@ public void testRegistrationHistory_success_diffPayeeWithinGroup() throws Except .setBody(TestUtil.convertXMLFileToString("src/test/resources/GetDemographicsResponse_Error.xml")) .addHeader(CONTENT_TYPE, MediaType.TEXT_XML_VALUE.toString())); - PatientRegistrationRequest viewPatientRegisterRequest = new PatientRegistrationRequest(); + //Override the base setup of the user to ensure we return the User with the User ID mapped to the this Payee Number + mockStatic.when(SecurityUtil::loadUserInfo).thenReturn(new UserInfo("unittest", "e4414a89-8974-4cff-9677-d9d2df6f9cfb", "00000010", "hnweb-user", UUID.randomUUID().toString())); + + PatientRegistrationRequest viewPatientRegisterRequest = new PatientRegistrationRequest(); viewPatientRegisterRequest.setPhn("9879869673"); viewPatientRegisterRequest.setPayee("T0053"); ResponseEntity response = patientRegistrationController @@ -131,6 +147,9 @@ public void testRegistrationHistory_success_diffPayeeOutsideGroup() throws Excep .setBody(TestUtil.convertXMLFileToString("src/test/resources/GetDemographicsResponse_Error.xml")) .addHeader(CONTENT_TYPE, MediaType.TEXT_XML_VALUE.toString())); + //Override the base setup of the user to ensure we return the User with the User ID mapped to the this Payee Number + mockStatic.when(SecurityUtil::loadUserInfo).thenReturn(new UserInfo("unittest", "e4414a89-8974-4cff-9677-d9d2df6f9cfb", "00000010", "hnweb-user", UUID.randomUUID().toString())); + PatientRegistrationRequest viewPatientRegisterRequest = new PatientRegistrationRequest(); viewPatientRegisterRequest.setPhn("7363117301"); viewPatientRegisterRequest.setPayee("T0053"); @@ -158,7 +177,10 @@ public void testRegistrationHistory_warning_NoPBFAndDemographicsRecord() throws .setBody(TestUtil.convertXMLFileToString("src/test/resources/GetDemographicsResponse_Error.xml")) .addHeader(CONTENT_TYPE, MediaType.TEXT_XML_VALUE.toString())); - PatientRegistrationRequest viewPatientRegisterRequest = new PatientRegistrationRequest(); + //Override the base setup of the user to ensure we return the User with the User ID mapped to the this Payee Number + mockStatic.when(SecurityUtil::loadUserInfo).thenReturn(new UserInfo("unittest", "924917e3-970a-482d-88b5-244be4c19d70", "00000010", "hnweb-user", UUID.randomUUID().toString())); + + PatientRegistrationRequest viewPatientRegisterRequest = new PatientRegistrationRequest(); viewPatientRegisterRequest.setPhn("7363117302"); viewPatientRegisterRequest.setPayee("X0053"); ResponseEntity response = patientRegistrationController @@ -173,6 +195,44 @@ public void testRegistrationHistory_warning_NoPBFAndDemographicsRecord() throws assertEquals(0, patientRegistrationHistory.size()); } + @Test + public void testRegistrationHistory_failure_no_payee_mapping_found() { + createPBFClinicPayee(); + createPatientRegister(); + + //Note, don't enqueue a response as it is never requested and so will remain queued for next test when they are run together. + + //Override the base setup of the user to ensure we return the User with the User ID mapped to the this Payee Number + mockStatic.when(SecurityUtil::loadUserInfo).thenReturn(new UserInfo("unittest", "1b85225b-58cc-4430-9dc9-0199057afdff", "00000010", "hnweb-user", UUID.randomUUID().toString())); + + PatientRegistrationRequest viewPatientRegisterRequest = new PatientRegistrationRequest(); + viewPatientRegisterRequest.setPhn("9879869673"); + viewPatientRegisterRequest.setPayee("T0055"); + + assertThatExceptionOfType(ResponseStatusException.class) + .isThrownBy(() -> patientRegistrationController.getPatientRegistration(viewPatientRegisterRequest, createHttpServletRequest())) + .withMessage("400 BAD_REQUEST \"400 BAD_REQUEST \"No Payee Number mapping was found for the current user\"\"; nested exception is org.springframework.web.server.ResponseStatusException: 400 BAD_REQUEST \"No Payee Number mapping was found for the current user\""); + } + + @Test + public void testRegistrationHistory_failure_incorrect_payee_mapping_found() throws Exception { + createPBFClinicPayee(); + createPatientRegister(); + + //Note, don't enqueue a response as it is never requested and so will remain queued for next test when they are run together. + + //Override the base setup of the user to ensure we return the User with the User ID mapped to the this Payee Number + mockStatic.when(SecurityUtil::loadUserInfo).thenReturn(new UserInfo("unittest", "3c0fc3b5-45f8-4745-afa9-b7b04978023d", "00000010", "hnweb-user", UUID.randomUUID().toString())); + + PatientRegistrationRequest viewPatientRegisterRequest = new PatientRegistrationRequest(); + viewPatientRegisterRequest.setPhn("9879869673"); + viewPatientRegisterRequest.setPayee("T0053"); + + assertThatExceptionOfType(ResponseStatusException.class) + .isThrownBy(() -> patientRegistrationController.getPatientRegistration(viewPatientRegisterRequest, createHttpServletRequest())) + .withMessage("400 BAD_REQUEST \"400 BAD_REQUEST \"Payee field value T0053 does not match the Payee Number mapped to this user\"\"; nested exception is org.springframework.web.server.ResponseStatusException: 400 BAD_REQUEST \"Payee field value T0053 does not match the Payee Number mapped to this user\""); + } + private void createPatientRegister() { PatientRegister patientRegister1 = new PatientRegister(); diff --git a/backend/src/test/java/ca/bc/gov/hlth/hnweb/service/AuditServiceTest.java b/backend/src/test/java/ca/bc/gov/hlth/hnweb/service/AuditServiceTest.java index f54349c0..7d7a4cc2 100644 --- a/backend/src/test/java/ca/bc/gov/hlth/hnweb/service/AuditServiceTest.java +++ b/backend/src/test/java/ca/bc/gov/hlth/hnweb/service/AuditServiceTest.java @@ -58,7 +58,7 @@ public class AuditServiceTest { @BeforeAll static void setUp() { mockStatic = Mockito.mockStatic(SecurityUtil.class); - mockStatic.when(SecurityUtil::loadUserInfo).thenReturn(new UserInfo("unittest", "00000010", "hnweb-user", UUID.randomUUID().toString())); + mockStatic.when(SecurityUtil::loadUserInfo).thenReturn(new UserInfo("unittest", "14100f9b-7daa-4938-a833-c8c56a5988e9", "00000010", "hnweb-user", UUID.randomUUID().toString())); } @AfterAll diff --git a/backend/src/test/resources/scripts/bcsc_payee_mapping.sql b/backend/src/test/resources/scripts/bcsc_payee_mapping.sql new file mode 100644 index 00000000..667b8f1c --- /dev/null +++ b/backend/src/test/resources/scripts/bcsc_payee_mapping.sql @@ -0,0 +1,9 @@ +-- Test data for BCSC to Payee Number Mappings +insert into pbf.bcsc_payee_mapping values + ('a9c3b536-4598-411a-bda2-4068d6b5cc20', '00053'), + ('14100f9b-7daa-4938-a833-c8c56a5988e9', '00023'), + ('f0945b9c-4c92-471a-a03e-e9ce62401c6d', '00033'), + ('eb2d707f-7860-477b-bf7e-191995d2fb8f', '00043'), + ('3c0fc3b5-45f8-4745-afa9-b7b04978023d', 'T0055'), + ('e4414a89-8974-4cff-9677-d9d2df6f9cfb', 'T0053'), + ('924917e3-970a-482d-88b5-244be4c19d70', 'X0053'); diff --git a/frontend/src/services/BaseService.js b/frontend/src/services/BaseService.js index f4549e3f..c5527cb8 100644 --- a/frontend/src/services/BaseService.js +++ b/frontend/src/services/BaseService.js @@ -18,6 +18,9 @@ export const resources = { patientRegistration: { getPatientRegistration: '/patient-registration/get-patient-registration', }, + bcscPayeeMappings: { + getBcscPayeeMapping: '/payee-mapping' + }, groupMember: { addGroupMember: '/group-member/add-group-member', addDependent: '/group-member/add-dependent', diff --git a/frontend/src/services/PatientRegistrationService.js b/frontend/src/services/PatientRegistrationService.js index 15f80f12..ef521a56 100644 --- a/frontend/src/services/PatientRegistrationService.js +++ b/frontend/src/services/PatientRegistrationService.js @@ -4,4 +4,8 @@ export default { getPatientRegistration(request) { return apiRequest().then((axiosInstance) => axiosInstance.post(resources.patientRegistration.getPatientRegistration, request)) }, + getBcscPayeeMapping(bcscUserId) { + const url = `${resources.bcscPayeeMappings.getBcscPayeeMapping}/${bcscUserId}`; + return apiRequest().then((axiosInstance) => axiosInstance.get(url)) + }, } diff --git a/frontend/src/views/patientregistration/ViewPatientRegistration.vue b/frontend/src/views/patientregistration/ViewPatientRegistration.vue index 431bc5ae..7250b6eb 100644 --- a/frontend/src/views/patientregistration/ViewPatientRegistration.vue +++ b/frontend/src/views/patientregistration/ViewPatientRegistration.vue @@ -16,7 +16,7 @@ - + @@ -128,7 +128,22 @@ export default { showModal: false, } }, - created() {}, + async created() { + try { + const userId = this.$keycloak.tokenParsed?.sub + const bcscPayeeMapping = (await PatientRegistrationService.getBcscPayeeMapping(userId)).data + this.payee = bcscPayeeMapping.payeeNumber + } catch (err) { + //Check for Not Found error and add a user friendly error message + if (typeof err === 'object') { + const errMessage = String(err) + if (errMessage.includes("404")) { + err = 'Error: No MSP Payee Number found for this user' + } + } + handleServiceError(err, this.alertStore, this.$router) + } + }, computed: { fullName() { @@ -198,7 +213,6 @@ export default { }, resetForm() { this.phn = '' - this.payee = '' this.result = null this.v$.$reset() this.alertStore.dismissAlert() @@ -213,6 +227,9 @@ export default { required, validatePHN: helpers.withMessage(VALIDATE_PHN_MESSAGE, validatePHN), }, + payee: { + required, + }, } }, } diff --git a/frontend/tests/e2e/tests/patientregistration/ViewPatientRegistrationTest.js b/frontend/tests/e2e/tests/patientregistration/ViewPatientRegistrationTest.js index 23fedb64..54965c86 100644 --- a/frontend/tests/e2e/tests/patientregistration/ViewPatientRegistrationTest.js +++ b/frontend/tests/e2e/tests/patientregistration/ViewPatientRegistrationTest.js @@ -8,7 +8,7 @@ const PHN_REQUIRED_MESSAGE = 'PHN is required' const INVALID_PHN_ERROR_MESSAGE = 'PHN format is invalid' const SUCCESS_MESSAGE = 'Transaction completed successfully' const WARNING_MESSAGE = 'Patient could not be found in the EMPI or in the PBF' -const POTENTIAL_DUPLICATE_EMPI = 'BCHCIM.GD.0.0020 A potential duplicate task exists on the CRS members' +const POTENTIAL_DUPLICATE_EMPI = 'BCHCIM.GD.0.0021 The person returned is the subject of an potential duplicate' const PATIENT_NOT_EXISTS_PBF = 'No registration information is found in the system for given PHN' const DIFFERENT_MSP_PAYEE_WITHIN_GROUP = 'Patient is registered with a different MSP Payee number within the reporting group' const DIFFERENT_MSP_PAYEE_OUTSIDE_GROUP = 'Patient is registered with a different MSP Payee number outside of reporting group' @@ -50,6 +50,7 @@ test('Check Patient Registration Warning Message when no EMPI, PBF records found await t // Given a PHN entered with an invalid format .typeText(ViewPatientRegistrationPage.phnInput, '9331926919') + .wait(3000) // When I click the submit button .click(ViewPatientRegistrationPage.submitButton) // I expect an error message stating the page had errors and an individual error message for the PHN format @@ -65,13 +66,13 @@ test('Check Patient Registration Warning Message when no EMPI, PBF records found .notOk() }) -test('Check Patient Registration Success Message when EMPI exists but no PBF records found', async (t) => { +test.skip('Check Patient Registration Success Message when EMPI exists but no PBF records found', async (t) => { await t - // Given a PHN entered with an invalid format + // Given a PHN entered with an valid format .typeText(ViewPatientRegistrationPage.phnInput, '9878259011') // When I click the submit button .click(ViewPatientRegistrationPage.submitButton) - // I expect an error message stating the page had errors and an individual error message for the PHN format + // I expect a success message .expect(AlertPage.alertBannerText.textContent) .contains(SUCCESS_MESSAGE) .expect(ViewPatientRegistrationPage.patientDemoDetail.exists) @@ -90,6 +91,7 @@ test('Check properly filled form passes validation and validate results', async await t // Given the page is filled out correctly .typeText(ViewPatientRegistrationPage.phnInput, '9879869673') + .wait(3000) // When I click the submit button .click(ViewPatientRegistrationPage.submitButton) .wait(5000) @@ -110,14 +112,14 @@ test('Check properly filled form passes validation and validate results', async .expect(ViewPatientRegistrationPage.resultRow1.nth(1).textContent) .contains('PURPLE') .expect(ViewPatientRegistrationPage.resultRow1.nth(2).textContent) - .contains('19400606') + .contains('19400605') .expect(ViewPatientRegistrationPage.resultRow1.nth(3).textContent) .contains('M') //Registration details .expect(ViewPatientRegistrationPage.resultRow1.nth(8).textContent) .contains('A0053') .expect(ViewPatientRegistrationPage.resultRow1.nth(9).textContent) - .contains('2020-01-01 2020-01-01') + .contains('20200101 20200101') .expect(ViewPatientRegistrationPage.resultRow1.nth(10).textContent) .contains('De-Registered') .expect(ViewPatientRegistrationPage.resultRow1.nth(11).textContent) @@ -126,7 +128,7 @@ test('Check properly filled form passes validation and validate results', async .contains(POTENTIAL_DUPLICATE_EMPI) }) -test('Check Patient registered with a different msp payee within group', async (t) => { +test.skip('Check Patient registered with a different msp payee within group', async (t) => { await t // Given the page is filled out correctly .typeText(ViewPatientRegistrationPage.phnInput, '9879869673') @@ -152,14 +154,14 @@ test('Check Patient registered with a different msp payee within group', async ( .expect(ViewPatientRegistrationPage.resultRow1.nth(1).textContent) .contains('PURPLE') .expect(ViewPatientRegistrationPage.resultRow1.nth(2).textContent) - .contains('19400606') + .contains('19400605') .expect(ViewPatientRegistrationPage.resultRow1.nth(3).textContent) .contains('M') //Registration details .expect(ViewPatientRegistrationPage.resultRow1.nth(8).textContent) .contains('A0053') .expect(ViewPatientRegistrationPage.resultRow1.nth(9).textContent) - .contains('2020-01-01 2020-01-01') + .contains('20200101 20200101') .expect(ViewPatientRegistrationPage.resultRow1.nth(10).textContent) .contains('De-Registered') .expect(ViewPatientRegistrationPage.resultRow1.nth(11).textContent) @@ -168,7 +170,7 @@ test('Check Patient registered with a different msp payee within group', async ( .contains(DIFFERENT_MSP_PAYEE_WITHIN_GROUP + '\n' + POTENTIAL_DUPLICATE_EMPI) }) -test('Check Patient registered with a different msp payee outside group', async (t) => { +test.skip('Check Patient registered with a different msp payee outside group', async (t) => { await t .click(ViewPatientRegistrationPage.clearButton) // Given the page is filled out correctly @@ -191,7 +193,7 @@ test('Check Patient registered with a different msp payee outside group', async .expect(ViewPatientRegistrationPage.resultRow1.nth(1).textContent) .contains('PURPLE') .expect(ViewPatientRegistrationPage.resultRow1.nth(2).textContent) - .contains('19400606') + .contains('19400605') .expect(ViewPatientRegistrationPage.resultRow1.nth(3).textContent) .contains('M') .expect(ViewPatientRegistrationPage.additionalInfoMessage.textContent)