diff --git a/backend/src/main/java/ca/bc/gov/hlth/hnweb/controller/MaintenanceController.java b/backend/src/main/java/ca/bc/gov/hlth/hnweb/controller/MaintenanceController.java index cf41714f..08bbdee7 100644 --- a/backend/src/main/java/ca/bc/gov/hlth/hnweb/controller/MaintenanceController.java +++ b/backend/src/main/java/ca/bc/gov/hlth/hnweb/controller/MaintenanceController.java @@ -13,22 +13,31 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import ca.bc.gov.hlth.hnweb.converter.rapid.BaseRapidConverter; import ca.bc.gov.hlth.hnweb.converter.rapid.RPBSPAG0Converter; +import ca.bc.gov.hlth.hnweb.converter.rapid.RPBSPAI0Converter; import ca.bc.gov.hlth.hnweb.converter.rapid.RPBSPAJ0Converter; import ca.bc.gov.hlth.hnweb.converter.rapid.RPBSPRE0Converter; +import ca.bc.gov.hlth.hnweb.converter.rapid.RPBSPXP0Converter; import ca.bc.gov.hlth.hnweb.model.rapid.RPBSPAG0; +import ca.bc.gov.hlth.hnweb.model.rapid.RPBSPAI0; import ca.bc.gov.hlth.hnweb.model.rapid.RPBSPAJ0; import ca.bc.gov.hlth.hnweb.model.rapid.RPBSPRE0; +import ca.bc.gov.hlth.hnweb.model.rapid.RPBSPXP0; +import ca.bc.gov.hlth.hnweb.model.rest.groupmember.AddGroupMemberRequest; import ca.bc.gov.hlth.hnweb.model.rest.groupmember.ChangeEffectiveDateRequest; import ca.bc.gov.hlth.hnweb.model.rest.groupmember.ChangeEffectiveDateResponse; import ca.bc.gov.hlth.hnweb.model.rest.maintenance.ChangeCancelDateRequest; import ca.bc.gov.hlth.hnweb.model.rest.maintenance.ChangeCancelDateResponse; import ca.bc.gov.hlth.hnweb.model.rest.maintenance.ReinstateOverAgeDependentRequest; import ca.bc.gov.hlth.hnweb.model.rest.maintenance.ReinstateOverAgeDependentResponse; +import ca.bc.gov.hlth.hnweb.model.rest.maintenance.RenewCancelledGroupCoverageRequest; +import ca.bc.gov.hlth.hnweb.model.rest.maintenance.RenewCancelledGroupCoverageResponse; 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.security.TransactionType; +import ca.bc.gov.hlth.hnweb.service.GroupMemberService; import ca.bc.gov.hlth.hnweb.service.MaintenanceService; /** @@ -42,6 +51,9 @@ public class MaintenanceController extends BaseController { @Autowired private MaintenanceService maintenanceService; + + @Autowired + private GroupMemberService groupMemberService; /** * Changes coverage effective date for the group number. Maps to the legacy @@ -140,6 +152,55 @@ public ResponseEntity reinstateOverAgeDepende return null; } } + + /** + * Renew the coverage effective date of an employee and spouse/dependents. + * Maps to the legacy R45 (Z27). + * + * @param RenewCancelledGroupCoverageRequest + * @return The result of the operation. + */ + @PostMapping("/renew-cancelled-group-coverage") + public ResponseEntity renewCancelledGroupCoverage( + @Valid @RequestBody RenewCancelledGroupCoverageRequest renewCancelledGroupCoverageRequest, + HttpServletRequest request) { + + Transaction transaction = auditRenewCancelledCoverageStart(renewCancelledGroupCoverageRequest.getPhn(), + request); + + try { + RPBSPAI0Converter converter = new RPBSPAI0Converter(); + RPBSPAI0 rpbspai0Request = converter.convertRequest(renewCancelledGroupCoverageRequest); + RPBSPAI0 rpbspai0Response = maintenanceService.renewCoverageEffectiveDate(rpbspai0Request, transaction); + RenewCancelledGroupCoverageResponse renewCancelledGroupCoverageResponse; + + // Execute if RPBSPAI0 returns successfully + if (StringUtils.equals(rpbspai0Response.getRpbsHeader().getStatusCode(), BaseRapidConverter.STATUS_CODE_SUCCESS)) { + RPBSPXP0Converter rpbspxp0Converter = new RPBSPXP0Converter(); + + // Creates/Clones a new Coverage entry, not simply an update but an Add + AddGroupMemberRequest addGroupMemberRequest = converter.buildAddGroupMemberRequest(rpbspai0Response); + RPBSPXP0 rpbspxp0 = rpbspxp0Converter.convertRequest(addGroupMemberRequest); + + RPBSPXP0 rpbspxp0Response = groupMemberService.addGroupMember(rpbspxp0, transaction); + renewCancelledGroupCoverageResponse = rpbspxp0Converter.convertResponseForRenewal(rpbspxp0Response); + } else { + renewCancelledGroupCoverageResponse = converter.convertResponse(rpbspai0Response); + } + + ResponseEntity response = ResponseEntity + .ok(renewCancelledGroupCoverageResponse); + + logger.info("RenewCancelledGroupCoverageResponse response: {} ", response); + + auditRenewCancelledCoverageComplete(transaction, renewCancelledGroupCoverageResponse.getPhn()); + + return response; + } catch (Exception e) { + handleException(transaction, e); + return null; + } + } private Transaction auditChangeEffectiveDateStart(ChangeEffectiveDateRequest changeEffectiveDateRequest, HttpServletRequest request) { @@ -190,5 +251,24 @@ private Transaction auditReinstateOverAgeDependentStart(ReinstateOverAgeDependen addAffectedParty(transaction, IdentifierType.PHN, reinstateRequest.getDependentPhn(), AffectedPartyDirection.INBOUND); return transaction; } + + private Transaction auditRenewCancelledCoverageStart(String phn, HttpServletRequest request) { + + Transaction transaction = transactionStart(request, TransactionType.RENEW_CANCELLED_COVERAGE); + + if (StringUtils.isNotBlank(phn)) { + addAffectedParty(transaction, IdentifierType.PHN, phn, AffectedPartyDirection.INBOUND); + } + return transaction; + } + + private void auditRenewCancelledCoverageComplete(Transaction transaction, String phn) { + + transactionComplete(transaction); + + if (StringUtils.isNotBlank(phn)) { + addAffectedParty(transaction, IdentifierType.PHN, phn, AffectedPartyDirection.OUTBOUND); + } + } } diff --git a/backend/src/main/java/ca/bc/gov/hlth/hnweb/converter/rapid/BaseRapidConverter.java b/backend/src/main/java/ca/bc/gov/hlth/hnweb/converter/rapid/BaseRapidConverter.java index dfbe4cd0..ecff94fa 100644 --- a/backend/src/main/java/ca/bc/gov/hlth/hnweb/converter/rapid/BaseRapidConverter.java +++ b/backend/src/main/java/ca/bc/gov/hlth/hnweb/converter/rapid/BaseRapidConverter.java @@ -20,7 +20,7 @@ public abstract class BaseRapidConverter { protected static final String RAPID_YYYY_MM_FORMAT = "yyyy-MM"; - protected static final String STATUS_CODE_SUCCESS = "RPBS9014"; + public static final String STATUS_CODE_SUCCESS = "RPBS9014"; protected static final String SUCCESS_MESSAGE = "TRANSACTION COMPLETED"; diff --git a/backend/src/main/java/ca/bc/gov/hlth/hnweb/converter/rapid/RPBSPAI0Converter.java b/backend/src/main/java/ca/bc/gov/hlth/hnweb/converter/rapid/RPBSPAI0Converter.java new file mode 100644 index 00000000..3bff8ab2 --- /dev/null +++ b/backend/src/main/java/ca/bc/gov/hlth/hnweb/converter/rapid/RPBSPAI0Converter.java @@ -0,0 +1,91 @@ +package ca.bc.gov.hlth.hnweb.converter.rapid; + +import java.time.LocalDate; + +import ca.bc.gov.hlth.hnweb.model.rapid.AI0; +import ca.bc.gov.hlth.hnweb.model.rapid.R45NewPayer; +import ca.bc.gov.hlth.hnweb.model.rapid.RPBSAddress; +import ca.bc.gov.hlth.hnweb.model.rapid.RPBSHeader; +import ca.bc.gov.hlth.hnweb.model.rapid.RPBSPAI0; +import ca.bc.gov.hlth.hnweb.model.rest.groupmember.AddGroupMemberRequest; +import ca.bc.gov.hlth.hnweb.model.rest.groupmember.MemberAddress; +import ca.bc.gov.hlth.hnweb.model.rest.maintenance.RenewCancelledGroupCoverageRequest; +import ca.bc.gov.hlth.hnweb.model.rest.maintenance.RenewCancelledGroupCoverageResponse; + +public class RPBSPAI0Converter extends BaseRapidConverter { + private static final String TRAN_CODE = "RPBSPAI0"; + + public RPBSPAI0Converter() { + super(); + } + + public RPBSPAI0 convertRequest(RenewCancelledGroupCoverageRequest request) { + RPBSHeader rpbsHeader = new RPBSHeader(); + rpbsHeader.setOrganization(userInfo.getOrganization()); + rpbsHeader.setTranCode(getTranCode()); + + AI0 ai0 = new AI0(); + ai0.setGroupNumber(request.getGroupNumber()); + ai0.setPhn(request.getPhn()); + ai0.setNewCoverageEffectiveDate(formatDate(request.getNewCoverageEffectiveDate())); + + RPBSPAI0 rpbspai0 = new RPBSPAI0(); + rpbspai0.setRpbsHeader(rpbsHeader); + rpbspai0.setAi0(ai0); + + return rpbspai0; + } + + public RenewCancelledGroupCoverageResponse convertResponse(RPBSPAI0 rpbspai0) { + RenewCancelledGroupCoverageResponse response = new RenewCancelledGroupCoverageResponse(); + RPBSHeader header = rpbspai0.getRpbsHeader(); + + handleStatus(header, response); + response.setPhn(rpbspai0.getAi0().getPhn()); + + return response; + } + + public AddGroupMemberRequest buildAddGroupMemberRequest(RPBSPAI0 rpbspai0) { + R45NewPayer newPayerData = rpbspai0.getAi0().getNewPayerData(); + AddGroupMemberRequest request = new AddGroupMemberRequest(); + request.setEffectiveDate(LocalDate.parse(rpbspai0.getAi0().getNewCoverageEffectiveDate())); + request.setPhn(newPayerData.getPhn()); + request.setSpousePhn(newPayerData.getSpousePhn()); + request.setDependentPhn1(newPayerData.getDependentPhn1()); + request.setDependentPhn2(newPayerData.getDependentPhn2()); + request.setDependentPhn3(newPayerData.getDependentPhn3()); + request.setDependentPhn4(newPayerData.getDependentPhn4()); + request.setDependentPhn5(newPayerData.getDependentPhn5()); + request.setDependentPhn6(newPayerData.getDependentPhn6()); + request.setDependentPhn7(newPayerData.getDependentPhn7()); + request.setGroupNumber(newPayerData.getGroupNumber()); + request.setGroupMemberNumber(newPayerData.getEmployeeNumber()); + request.setDepartmentNumber(newPayerData.getDepartmentNumber()); + request.setHomeAddress(convertToMemberAddress(newPayerData.getHomeAddress())); + request.setMailingAddress(convertToMemberAddress(newPayerData.getMailAddress())); + request.setPhone(newPayerData.getPhone1().getPhoneNumber()); + return request; + } + + private MemberAddress convertToMemberAddress(RPBSAddress rpbsAddress) { + MemberAddress memberAddress = new MemberAddress(); + + if (rpbsAddress == null) { + return memberAddress; + } + memberAddress.setAddressLine1(rpbsAddress.getAddressLine1()); + memberAddress.setAddressLine2(rpbsAddress.getAddressLine2()); + memberAddress.setAddressLine3(rpbsAddress.getAddressLine3()); + memberAddress.setAddressLine4(rpbsAddress.getAddressLine4()); + memberAddress.setPostalCode(rpbsAddress.getPostalCode()); + + return memberAddress; + } + + @Override + public String getTranCode() { + return TRAN_CODE; + } + +} \ No newline at end of file diff --git a/backend/src/main/java/ca/bc/gov/hlth/hnweb/converter/rapid/RPBSPXP0Converter.java b/backend/src/main/java/ca/bc/gov/hlth/hnweb/converter/rapid/RPBSPXP0Converter.java index 2bfc6d0e..67080ca7 100644 --- a/backend/src/main/java/ca/bc/gov/hlth/hnweb/converter/rapid/RPBSPXP0Converter.java +++ b/backend/src/main/java/ca/bc/gov/hlth/hnweb/converter/rapid/RPBSPXP0Converter.java @@ -10,6 +10,7 @@ import ca.bc.gov.hlth.hnweb.model.rest.groupmember.AddGroupMemberRequest; import ca.bc.gov.hlth.hnweb.model.rest.groupmember.AddGroupMemberResponse; import ca.bc.gov.hlth.hnweb.model.rest.groupmember.MemberAddress; +import ca.bc.gov.hlth.hnweb.model.rest.maintenance.RenewCancelledGroupCoverageResponse; public class RPBSPXP0Converter extends BaseRapidConverter { private static final String TRAN_CODE = "RPBSPXP0"; @@ -72,6 +73,16 @@ public AddGroupMemberResponse convertResponse(RPBSPXP0 rpbspxp0) { return response; } + public RenewCancelledGroupCoverageResponse convertResponseForRenewal(RPBSPXP0 rpbspxp0) { + RenewCancelledGroupCoverageResponse response = new RenewCancelledGroupCoverageResponse(); + RPBSHeader header = rpbspxp0.getRpbsHeader(); + + handleStatus(header, response); + response.setPhn(rpbspxp0.getXp0().getPhn()); + + return response; + } + private RPBSAddress convertAddress(MemberAddress memberAddress) { RPBSAddress rpbsAddress = new RPBSAddress(); @@ -87,7 +98,6 @@ private RPBSAddress convertAddress(MemberAddress memberAddress) { return rpbsAddress; } - @Override public String getTranCode() { return TRAN_CODE; diff --git a/backend/src/main/java/ca/bc/gov/hlth/hnweb/model/rapid/AI0.java b/backend/src/main/java/ca/bc/gov/hlth/hnweb/model/rapid/AI0.java new file mode 100644 index 00000000..2e9534ea --- /dev/null +++ b/backend/src/main/java/ca/bc/gov/hlth/hnweb/model/rapid/AI0.java @@ -0,0 +1,72 @@ +package ca.bc.gov.hlth.hnweb.model.rapid; + +import org.apache.commons.lang3.StringUtils; + +public class AI0 { + + /** 1 GroupNumber String No 0...7 .. */ + private String groupNumber; + /** 2 PHN String No 0...10 .. */ + private String phn; + /** 3 NewCoverageEffectiveDate RPBSDate No 0...10 .. */ + private String newCoverageEffectiveDate; + /** 4 NewPayerData String No 0...394 .. */ + private R45NewPayer newPayerData; + + public AI0() { + super(); + } + + public AI0(String message) { + super(); + phn = StringUtils.substring(message, 0, 10); + groupNumber = StringUtils.substring(message, 10, 17); + newCoverageEffectiveDate = StringUtils.substring(message, 17, 27); + newPayerData = new R45NewPayer(StringUtils.substring(message, 27,421)); + + } + + public String serialize() { + // Serialize is only used in when creating the request + // where only the first three fields are used + StringBuilder sb = new StringBuilder(); + sb.append(StringUtils.rightPad(phn, 10)); + sb.append(StringUtils.rightPad(groupNumber, 7)); + sb.append(StringUtils.rightPad(newCoverageEffectiveDate, 10)); + + return sb.toString(); + } + + public String getGroupNumber() { + return groupNumber; + } + + public void setGroupNumber(String groupNumber) { + this.groupNumber = groupNumber; + } + + public String getPhn() { + return phn; + } + + public void setPhn(String phn) { + this.phn = phn; + } + + public String getNewCoverageEffectiveDate() { + return newCoverageEffectiveDate; + } + + public void setNewCoverageEffectiveDate(String newCoverageEffectiveDate) { + this.newCoverageEffectiveDate = newCoverageEffectiveDate; + } + + public R45NewPayer getNewPayerData() { + return newPayerData; + } + + public void setNewPayerData(R45NewPayer ai0payeeData) { + this.newPayerData = ai0payeeData; + } + +} diff --git a/backend/src/main/java/ca/bc/gov/hlth/hnweb/model/rapid/R45NewPayer.java b/backend/src/main/java/ca/bc/gov/hlth/hnweb/model/rapid/R45NewPayer.java new file mode 100644 index 00000000..b1134ad5 --- /dev/null +++ b/backend/src/main/java/ca/bc/gov/hlth/hnweb/model/rapid/R45NewPayer.java @@ -0,0 +1,203 @@ +package ca.bc.gov.hlth.hnweb.model.rapid; + +import org.apache.commons.lang3.StringUtils; + +public class R45NewPayer { + /** 0 SubscriberPHN String No 0...10 .. */ + private String phn; + /** 1 SpousePHN String No 0...10 .. */ + private String spousePhn; + /** 2 DependentPHN1 String No 0...10 .. */ + private String dependentPhn1; + /** 3 DependentPHN2 String No 0...10 .. */ + private String dependentPhn2; + /** 4 DependentPHN3 String No 0...10 .. */ + private String dependentPhn3; + /** 5 DependentPHN4 String No 0...10 .. */ + private String dependentPhn4; + /** 6 DependentPHN5 String No 0...10 .. */ + private String dependentPhn5; + /** 7 DependentPHN6 String No 0...10 .. */ + private String dependentPhn6; + /** 8 DependentPHN7 String No 0...10 .. */ + private String dependentPhn7; + /** 9 EmployeePHN String No 0...10 .. */ + private String employeePhn; + /** 10 GroupNumber String No 0...7 .. */ + private String groupNumber; + /** 11 EmployeeNumber String No 0...9 .. */ + private String employeeNumber; + /** 12 DepartmentNumber String No 0...6 */ + private String departmentNumber; + /** 13 HomeAddress RPBSAddress No 0...106 .. */ + private RPBSAddress homeAddress; + /** 14 MailAddress RPBSAddress No 0...106 .. */ + private RPBSAddress mailAddress; + /** 15 Phone0 RPBSPhone No 0...30 .. */ + private RPBSPhone phone0; + /** 16 Phone1 RPBSPhone No 0...30 .. */ + private RPBSPhone phone1; + + public R45NewPayer() { + super(); + } + + public R45NewPayer(String message) { + super(); + phn = StringUtils.substring(message, 0, 10); + spousePhn = StringUtils.substring(message, 10, 20); + dependentPhn1 = StringUtils.substring(message, 20, 30); + dependentPhn2 = StringUtils.substring(message, 30, 40); + dependentPhn3 = StringUtils.substring(message, 40, 50); + dependentPhn4 = StringUtils.substring(message, 50, 60); + dependentPhn5 = StringUtils.substring(message, 60, 70); + dependentPhn6 = StringUtils.substring(message, 70, 80); + dependentPhn7 = StringUtils.substring(message, 80, 90); + employeePhn = StringUtils.substring(message, 90, 100); + groupNumber = StringUtils.substring(message, 100, 107); + employeeNumber = StringUtils.substring(message, 107, 116); + departmentNumber = StringUtils.substring(message, 116, 122); + homeAddress = new RPBSAddress(StringUtils.substring(message, 122, 228)); + mailAddress = new RPBSAddress(StringUtils.substring(message, 228, 334)); + phone0 = new RPBSPhone(StringUtils.substring(message, 334, 364)); + phone1 = new RPBSPhone(StringUtils.substring(message, 364, 394)); + + } + + public String getPhn() { + return phn; + } + + public void setPhn(String phn) { + this.phn = phn; + } + + public String getSpousePhn() { + return spousePhn; + } + + public void setSpousePhn(String spousePhn) { + this.spousePhn = spousePhn; + } + + public String getDependentPhn1() { + return dependentPhn1; + } + + public void setDependentPhn1(String dependentPhn1) { + this.dependentPhn1 = dependentPhn1; + } + + public String getDependentPhn2() { + return dependentPhn2; + } + + public void setDependentPhn2(String dependentPhn2) { + this.dependentPhn2 = dependentPhn2; + } + + public String getDependentPhn3() { + return dependentPhn3; + } + + public void setDependentPhn3(String dependentPhn3) { + this.dependentPhn3 = dependentPhn3; + } + + public String getDependentPhn4() { + return dependentPhn4; + } + + public void setDependentPhn4(String dependentPhn4) { + this.dependentPhn4 = dependentPhn4; + } + + public String getDependentPhn5() { + return dependentPhn5; + } + + public void setDependentPhn5(String dependentPhn5) { + this.dependentPhn5 = dependentPhn5; + } + + public String getDependentPhn6() { + return dependentPhn6; + } + + public void setDependentPhn6(String dependentPhn6) { + this.dependentPhn6 = dependentPhn6; + } + + public String getEmployeePhn() { + return employeePhn; + } + + public void setEmployeePhn(String employeePhn) { + this.employeePhn = employeePhn; + } + + public String getDependentPhn7() { + return dependentPhn7; + } + + public void setDependentPhn7(String dependentPhn7) { + this.dependentPhn7 = dependentPhn7; + } + + public String getGroupNumber() { + return groupNumber; + } + + public void setGroupNumber(String groupNumber) { + this.groupNumber = groupNumber; + } + + public String getEmployeeNumber() { + return employeeNumber; + } + + public void setEmployeeNumber(String employeeNumber) { + this.employeeNumber = employeeNumber; + } + + public String getDepartmentNumber() { + return departmentNumber; + } + + public void setDepartmentNumber(String departmentNumber) { + this.departmentNumber = departmentNumber; + } + + public RPBSAddress getHomeAddress() { + return homeAddress; + } + + public void setHomeAddress(RPBSAddress homeAddress) { + this.homeAddress = homeAddress; + } + + public RPBSAddress getMailAddress() { + return mailAddress; + } + + public void setMailAddress(RPBSAddress mailAddress) { + this.mailAddress = mailAddress; + } + + public RPBSPhone getPhone0() { + return phone0; + } + + public void setPhone0(RPBSPhone phone0) { + this.phone0 = phone0; + } + + public RPBSPhone getPhone1() { + return phone1; + } + + public void setPhone1(RPBSPhone phone1) { + this.phone1 = phone1; + } + +} diff --git a/backend/src/main/java/ca/bc/gov/hlth/hnweb/model/rapid/RPBSPAI0.java b/backend/src/main/java/ca/bc/gov/hlth/hnweb/model/rapid/RPBSPAI0.java new file mode 100644 index 00000000..8324d9bc --- /dev/null +++ b/backend/src/main/java/ca/bc/gov/hlth/hnweb/model/rapid/RPBSPAI0.java @@ -0,0 +1,40 @@ +package ca.bc.gov.hlth.hnweb.model.rapid; + +import org.apache.commons.lang3.StringUtils; + +public class RPBSPAI0 { + private RPBSHeader rpbsHeader = new RPBSHeader(); + private AI0 ai0 = new AI0(); + + public RPBSPAI0() { + super(); + } + + public RPBSPAI0(String message) { + String headerText = StringUtils.substring(message, 0, RPBSHeader.SEGMENT_LENGTH); + String bodyText = StringUtils.substring(message, RPBSHeader.SEGMENT_LENGTH); + rpbsHeader = new RPBSHeader(headerText); + ai0 = new AI0(bodyText); + } + + public AI0 getAi0() { + return ai0; + } + + public void setAi0(AI0 ai0) { + this.ai0 = ai0; + } + + public RPBSHeader getRpbsHeader() { + return rpbsHeader; + } + + public void setRpbsHeader(RPBSHeader rpbsHeader) { + this.rpbsHeader = rpbsHeader; + } + + public String serialize() { + return rpbsHeader.serialize() + ai0.serialize(); + } + +} diff --git a/backend/src/main/java/ca/bc/gov/hlth/hnweb/model/rest/maintenance/RenewCancelledGroupCoverageRequest.java b/backend/src/main/java/ca/bc/gov/hlth/hnweb/model/rest/maintenance/RenewCancelledGroupCoverageRequest.java new file mode 100644 index 00000000..ec9f80a3 --- /dev/null +++ b/backend/src/main/java/ca/bc/gov/hlth/hnweb/model/rest/maintenance/RenewCancelledGroupCoverageRequest.java @@ -0,0 +1,40 @@ +package ca.bc.gov.hlth.hnweb.model.rest.maintenance; + +import java.time.LocalDate; + +public class RenewCancelledGroupCoverageRequest { + private String groupNumber; + private String phn; + private LocalDate newCoverageEffectiveDate; + + public String getGroupNumber() { + return groupNumber; + } + + public void setGroupNumber(String groupNumber) { + this.groupNumber = groupNumber; + } + + public String getPhn() { + return phn; + } + + public void setPhn(String phn) { + this.phn = phn; + } + + public LocalDate getNewCoverageEffectiveDate() { + return newCoverageEffectiveDate; + } + + public void setNewCoverageEffectiveDate(LocalDate newEffectiveDate) { + this.newCoverageEffectiveDate = newEffectiveDate; + } + + @Override + public String toString() { + return "RenewCancelledGroupCoverageRequest [groupNumber=" + groupNumber + ", phn=" + phn + + ", newCoverageEffectiveDate=" + newCoverageEffectiveDate + "]"; + } + +} diff --git a/backend/src/main/java/ca/bc/gov/hlth/hnweb/model/rest/maintenance/RenewCancelledGroupCoverageResponse.java b/backend/src/main/java/ca/bc/gov/hlth/hnweb/model/rest/maintenance/RenewCancelledGroupCoverageResponse.java new file mode 100644 index 00000000..ae602b3d --- /dev/null +++ b/backend/src/main/java/ca/bc/gov/hlth/hnweb/model/rest/maintenance/RenewCancelledGroupCoverageResponse.java @@ -0,0 +1,21 @@ +package ca.bc.gov.hlth.hnweb.model.rest.maintenance; + +import ca.bc.gov.hlth.hnweb.model.rest.BaseResponse; + +public class RenewCancelledGroupCoverageResponse extends BaseResponse { + private String phn; + + public String getPhn() { + return phn; + } + + public void setPhn(String phn) { + this.phn = phn; + } + + @Override + public String toString() { + return "RenewCancelledGroupCoverageResponse [phn=" + phn + ", status=" + status + ", message=" + message + "]"; + } + +} 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 face8945..5e5ecd30 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 @@ -66,6 +66,7 @@ protected void configure(HttpSecurity http) throws Exception { .mvcMatchers(HttpMethod.POST, "/eligibility/inquire-phn").hasRole("PHNInquiry") .mvcMatchers(HttpMethod.POST, "/eligibility/lookup-phn").hasRole("PHNLookup") .mvcMatchers(HttpMethod.POST, "/maintenance/change-cancel-date").hasRole("ChangeCancelDate") + .mvcMatchers(HttpMethod.POST, "/maintenance/renew-cancelled-group-coverage").hasRole("RenewCancelledCoverage") .mvcMatchers(HttpMethod.POST, "/enrollment/enroll-subscriber").hasAnyRole("AddPermitHolderWithPHN", "AddPermitHolderWOPHN") .mvcMatchers(HttpMethod.POST, "/enrollment/get-person-details").hasRole("AddPermitHolderWithPHN") .mvcMatchers(HttpMethod.POST, "/enrollment/name-search").hasRole("AddPermitHolderWOPHN") diff --git a/backend/src/main/java/ca/bc/gov/hlth/hnweb/security/TransactionType.java b/backend/src/main/java/ca/bc/gov/hlth/hnweb/security/TransactionType.java index d8fe36d2..f154597f 100644 --- a/backend/src/main/java/ca/bc/gov/hlth/hnweb/security/TransactionType.java +++ b/backend/src/main/java/ca/bc/gov/hlth/hnweb/security/TransactionType.java @@ -21,6 +21,7 @@ public enum TransactionType { GET_CONTRACT_ADDRESS("GetContractAddress"), // R37 UPDATE_CONTRACT_ADDRESS("UpdateContractAddress"), // R38 REINSTATE_OVER_AGE_DEPENDENT("ReinstateOverAgeDependent"), // R43 + RENEW_CANCELLED_COVERAGE("RenewCancelledCoverage"), // R45 CHANGE_EFFECTIVE_DATE("ChangeEffectiveDate"), // R46a CHANGE_CANCEL_DATE("ChangeCancelDate"), // R46b GET_PATIENT_REGISTRATION("GetPatientRegistration"), // R70 diff --git a/backend/src/main/java/ca/bc/gov/hlth/hnweb/service/MaintenanceService.java b/backend/src/main/java/ca/bc/gov/hlth/hnweb/service/MaintenanceService.java index b4daf1be..7f6ed8d2 100644 --- a/backend/src/main/java/ca/bc/gov/hlth/hnweb/service/MaintenanceService.java +++ b/backend/src/main/java/ca/bc/gov/hlth/hnweb/service/MaintenanceService.java @@ -13,6 +13,7 @@ import ca.bc.gov.hlth.hnweb.exception.ExceptionType; import ca.bc.gov.hlth.hnweb.exception.HNWebException; import ca.bc.gov.hlth.hnweb.model.rapid.RPBSPAG0; +import ca.bc.gov.hlth.hnweb.model.rapid.RPBSPAI0; import ca.bc.gov.hlth.hnweb.model.rapid.RPBSPAJ0; import ca.bc.gov.hlth.hnweb.model.rapid.RPBSPRE0; import ca.bc.gov.hlth.hnweb.persistence.entity.Transaction; @@ -29,6 +30,9 @@ public class MaintenanceService extends BaseService { @Value("${rapid.r43Path:}") private String r43Path; + @Value("${rapid.r45Path:}") + private String r45Path; + @Value("${rapid.r46Path:}") private String r46Path; @@ -121,6 +125,27 @@ public RPBSPRE0 reinstateOverAgeDependent(RPBSPRE0 rpbspre0, Transaction transac return new RPBSPRE0(response.getBody()); } + public RPBSPAI0 renewCoverageEffectiveDate(RPBSPAI0 rpbspri0, Transaction transaction) throws HNWebException { + String rpbspai0Str = rpbspri0.serialize(); + + logger.info("Request {}", rpbspai0Str); + + messageSent(transaction); + ResponseEntity response = postRapidRequest(r45Path, rpbspai0Str, transaction.getTransactionId().toString()); + + logger.debug("Response Status: {} ; Message:\n{}", response.getStatusCode(), response.getBody()); + + logger.info("Response {}", response.getBody()); + + if (response.getStatusCode() != HttpStatus.OK) { + logger.error("Could not connect to downstream service. Service returned {}", response.getStatusCode()); + throw new HNWebException(ExceptionType.DOWNSTREAM_FAILURE); + } + + messageReceived(transaction); + return new RPBSPAI0(response.getBody()); + } + private ResponseEntity postRapidRequest(String path, String body, String transactionId) { return rapidWebClient .post() diff --git a/backend/src/test/java/ca/bc/gov/hlth/hnweb/controller/MaintenanceControllerTest.java b/backend/src/test/java/ca/bc/gov/hlth/hnweb/controller/MaintenanceControllerTest.java index 7e9f5c8e..0f736306 100644 --- a/backend/src/test/java/ca/bc/gov/hlth/hnweb/controller/MaintenanceControllerTest.java +++ b/backend/src/test/java/ca/bc/gov/hlth/hnweb/controller/MaintenanceControllerTest.java @@ -22,6 +22,8 @@ import ca.bc.gov.hlth.hnweb.model.rest.maintenance.ChangeCancelDateResponse; import ca.bc.gov.hlth.hnweb.model.rest.maintenance.ReinstateOverAgeDependentRequest; import ca.bc.gov.hlth.hnweb.model.rest.maintenance.ReinstateOverAgeDependentResponse; +import ca.bc.gov.hlth.hnweb.model.rest.maintenance.RenewCancelledGroupCoverageRequest; +import ca.bc.gov.hlth.hnweb.model.rest.maintenance.RenewCancelledGroupCoverageResponse; import ca.bc.gov.hlth.hnweb.persistence.entity.AffectedPartyDirection; import ca.bc.gov.hlth.hnweb.security.TransactionType; import ca.bc.gov.hlth.hnweb.util.V2MessageUtil; @@ -57,6 +59,20 @@ public class MaintenanceControllerTest extends BaseControllerTest { private static final String R46_B_SUBSCRIBER_NOT_COVERED = " RPBSPAG000000010 ERRORMSGRPBS9109SUBSCRIBER NOT COVERED UNDER THIS GROUP 484190493319269192022-07-312022-08-31 "; + private static final String R45_ACTIVE_COVERAGE_EXIST = " RPBSPAI000000010 ERRORMSGRPBS0117ACTIVE COVERAGE ALREADY EXISTS FOR THE PHN/GROUP NUMBER ENTERED. 98731026176257760"; + + private static final String R45_COVERGE_EFFECTIVE_DAY_MUST_BE_01 = " RPBSPAI000000010 ERRORMSGRPBS0276COVERGE EFFECTIVE DAY MUST BE 01 987310261762577602022-10-02"; + + private static final String R45_SUBSCRIBER_HAS_FUTURE_COVERAGE = " RPBSPAI000000010 ERRORMSGRPBS0049SUBSCRIBER HAS FUTURE COVERAGE. PLS FORWARD DOCS TO MSP 987310261760997332022-12-01"; + + private static final String R45_SUBSCRIBER_NOT_COVERED_UNDER_THIS_GROUP = " RPBSPAI000000010 ERRORMSGRPBS9109SUBSCRIBER NOT COVERED UNDER THIS GROUP 987310261762014532022-12-01"; + + private static final String R45_UNABLE_TO_PROCESS_AS_A_RENEWAL = " RPBSPAI000000010 ERRORMSGRPBS0118UNABLE TO PROCESS AS A RENEWAL. PLEASE USE REINSTATE CONTRACT TRX. 987310261760997332022-10-01"; + + private static final String R45_SUCCESS = " RPBSPAI000000010 RESPONSERPBS9014TRANSACTION SUCCESSFUL 987309854962674052021-12-019873098549 6267405 550 KP RD VICTORIA BC V4R8U8"; + + private static final String R30_SUCCESS = " RPBSPXP000000010 RESPONSERPBS9014TRANSACTION SUCCESSFUL 6267405 2021-12-01 550 KP RD VICTORIA BC V4R8U8 9873098549"; + protected static DateTimeFormatter dateOnlyFormatter = DateTimeFormatter.ofPattern(V2MessageUtil.DATE_FORMAT_DATE_ONLY); @Autowired @@ -401,6 +417,168 @@ public void testReinstateOverAgeDependent_success() throws Exception { assertAffectedPartyCount(AffectedPartyDirection.OUTBOUND, 1); } + @Test + public void testRenewCancelledCoverage_error_activeCoverageExist() throws Exception { + mockBackEnd.enqueue(new MockResponse() + .setBody(R45_ACTIVE_COVERAGE_EXIST) + .addHeader(CONTENT_TYPE, MediaType.TEXT_PLAIN.toString())); + + RenewCancelledGroupCoverageRequest renewCancelledGroupCoverageRequest = createRenewCancelledGroupCoverageRequest(LocalDate.parse("2022-11-01")); + + ResponseEntity response = maintenanceController.renewCancelledGroupCoverage(renewCancelledGroupCoverageRequest, createHttpServletRequest()); + + RenewCancelledGroupCoverageResponse renewCancelledGroupCoverageResponse = response.getBody(); + assertEquals(StatusEnum.ERROR, renewCancelledGroupCoverageResponse.getStatus()); + assertEquals("RPBS0117 ACTIVE COVERAGE ALREADY EXISTS FOR THE PHN/GROUP NUMBER ENTERED.", renewCancelledGroupCoverageResponse.getMessage()); + + assertEquals("9873102617", renewCancelledGroupCoverageResponse.getPhn()); + + // Check the client request is sent as expected + RecordedRequest recordedRequest = mockBackEnd.takeRequest(); + assertEquals(HttpMethod.POST.name(), recordedRequest.getMethod()); + assertEquals(MediaType.TEXT_PLAIN.toString(), recordedRequest.getHeader(CONTENT_TYPE)); + + assertTransactionCreated(TransactionType.RENEW_CANCELLED_COVERAGE); + assertAffectedPartyCount(AffectedPartyDirection.INBOUND, 1); + assertAffectedPartyCount(AffectedPartyDirection.OUTBOUND, 1); + } + + @Test + public void testRenewCancelledCoverage_error_invalidCoverageEffectiveDate() throws Exception { + mockBackEnd.enqueue(new MockResponse() + .setBody(R45_COVERGE_EFFECTIVE_DAY_MUST_BE_01) + .addHeader(CONTENT_TYPE, MediaType.TEXT_PLAIN.toString())); + + RenewCancelledGroupCoverageRequest renewCancelledGroupCoverageRequest = createRenewCancelledGroupCoverageRequest(LocalDate.parse("2022-10-02")); + + ResponseEntity response = maintenanceController.renewCancelledGroupCoverage(renewCancelledGroupCoverageRequest, createHttpServletRequest()); + + RenewCancelledGroupCoverageResponse renewCancelledGroupCoverageResponse = response.getBody(); + assertEquals(StatusEnum.ERROR, renewCancelledGroupCoverageResponse.getStatus()); + assertEquals("RPBS0276 COVERGE EFFECTIVE DAY MUST BE 01", renewCancelledGroupCoverageResponse.getMessage()); + + assertEquals("9873102617", renewCancelledGroupCoverageResponse.getPhn()); + + // Check the client request is sent as expected + RecordedRequest recordedRequest = mockBackEnd.takeRequest(); + assertEquals(HttpMethod.POST.name(), recordedRequest.getMethod()); + assertEquals(MediaType.TEXT_PLAIN.toString(), recordedRequest.getHeader(CONTENT_TYPE)); + + assertTransactionCreated(TransactionType.RENEW_CANCELLED_COVERAGE); + assertAffectedPartyCount(AffectedPartyDirection.INBOUND, 1); + assertAffectedPartyCount(AffectedPartyDirection.OUTBOUND, 1); + } + + @Test + public void testRenewCancelledCoverage_error_subscriberHasFutureCoverage() throws Exception { + mockBackEnd.enqueue(new MockResponse() + .setBody(R45_SUBSCRIBER_HAS_FUTURE_COVERAGE) + .addHeader(CONTENT_TYPE, MediaType.TEXT_PLAIN.toString())); + + RenewCancelledGroupCoverageRequest renewCancelledGroupCoverageRequest = createRenewCancelledGroupCoverageRequest(LocalDate.parse("2022-12-01")); + + ResponseEntity response = maintenanceController.renewCancelledGroupCoverage(renewCancelledGroupCoverageRequest, createHttpServletRequest()); + + RenewCancelledGroupCoverageResponse renewCancelledGroupCoverageResponse = response.getBody(); + assertEquals(StatusEnum.ERROR, renewCancelledGroupCoverageResponse.getStatus()); + assertEquals("RPBS0049 SUBSCRIBER HAS FUTURE COVERAGE. PLS FORWARD DOCS TO MSP", renewCancelledGroupCoverageResponse.getMessage()); + + assertEquals("9873102617", renewCancelledGroupCoverageResponse.getPhn()); + + // Check the client request is sent as expected + RecordedRequest recordedRequest = mockBackEnd.takeRequest(); + assertEquals(HttpMethod.POST.name(), recordedRequest.getMethod()); + assertEquals(MediaType.TEXT_PLAIN.toString(), recordedRequest.getHeader(CONTENT_TYPE)); + + assertTransactionCreated(TransactionType.RENEW_CANCELLED_COVERAGE); + assertAffectedPartyCount(AffectedPartyDirection.INBOUND, 1); + assertAffectedPartyCount(AffectedPartyDirection.OUTBOUND, 1); + } + + @Test + public void testRenewCancelledCoverage_error_subscriberNotCovered() throws Exception { + mockBackEnd.enqueue(new MockResponse() + .setBody(R45_SUBSCRIBER_NOT_COVERED_UNDER_THIS_GROUP) + .addHeader(CONTENT_TYPE, MediaType.TEXT_PLAIN.toString())); + + RenewCancelledGroupCoverageRequest renewCancelledGroupCoverageRequest = createRenewCancelledGroupCoverageRequest(LocalDate.parse("2022-12-01")); + + ResponseEntity response = maintenanceController.renewCancelledGroupCoverage(renewCancelledGroupCoverageRequest, createHttpServletRequest()); + + RenewCancelledGroupCoverageResponse renewCancelledGroupCoverageResponse = response.getBody(); + assertEquals(StatusEnum.ERROR, renewCancelledGroupCoverageResponse.getStatus()); + assertEquals("RPBS9109 SUBSCRIBER NOT COVERED UNDER THIS GROUP", renewCancelledGroupCoverageResponse.getMessage()); + + assertEquals("9873102617", renewCancelledGroupCoverageResponse.getPhn()); + + // Check the client request is sent as expected + RecordedRequest recordedRequest = mockBackEnd.takeRequest(); + assertEquals(HttpMethod.POST.name(), recordedRequest.getMethod()); + assertEquals(MediaType.TEXT_PLAIN.toString(), recordedRequest.getHeader(CONTENT_TYPE)); + + assertTransactionCreated(TransactionType.RENEW_CANCELLED_COVERAGE); + assertAffectedPartyCount(AffectedPartyDirection.INBOUND, 1); + assertAffectedPartyCount(AffectedPartyDirection.OUTBOUND, 1); + } + + @Test + public void testRenewCancelledCoverage_error_unableToProcessAsRenewel() throws Exception { + mockBackEnd.enqueue(new MockResponse() + .setBody(R45_UNABLE_TO_PROCESS_AS_A_RENEWAL) + .addHeader(CONTENT_TYPE, MediaType.TEXT_PLAIN.toString())); + + RenewCancelledGroupCoverageRequest renewCancelledGroupCoverageRequest = createRenewCancelledGroupCoverageRequest(LocalDate.parse("2022-12-01")); + + ResponseEntity response = maintenanceController.renewCancelledGroupCoverage(renewCancelledGroupCoverageRequest, createHttpServletRequest()); + + RenewCancelledGroupCoverageResponse renewCancelledGroupCoverageResponse = response.getBody(); + assertEquals(StatusEnum.ERROR, renewCancelledGroupCoverageResponse.getStatus()); + assertEquals("RPBS0118 UNABLE TO PROCESS AS A RENEWAL. PLEASE USE REINSTATE CONTRACT TRX.", renewCancelledGroupCoverageResponse.getMessage()); + + assertEquals("9873102617", renewCancelledGroupCoverageResponse.getPhn()); + + // Check the client request is sent as expected + RecordedRequest recordedRequest = mockBackEnd.takeRequest(); + assertEquals(HttpMethod.POST.name(), recordedRequest.getMethod()); + assertEquals(MediaType.TEXT_PLAIN.toString(), recordedRequest.getHeader(CONTENT_TYPE)); + + assertTransactionCreated(TransactionType.RENEW_CANCELLED_COVERAGE); + assertAffectedPartyCount(AffectedPartyDirection.INBOUND, 1); + assertAffectedPartyCount(AffectedPartyDirection.OUTBOUND, 1); + } + + + @Test + public void testRenewCancelledCoverage_success() throws Exception { + mockBackEnd.enqueue(new MockResponse() + .setBody(R45_SUCCESS) + .addHeader(CONTENT_TYPE, MediaType.TEXT_PLAIN.toString())); + + mockBackEnd.enqueue(new MockResponse() + .setBody(R30_SUCCESS) + .addHeader(CONTENT_TYPE, MediaType.TEXT_PLAIN.toString())); + + RenewCancelledGroupCoverageRequest renewCancelledGroupCoverageRequest = createRenewCancelledGroupCoverageRequest(LocalDate.parse("2022-11-01")); + + ResponseEntity response = maintenanceController.renewCancelledGroupCoverage(renewCancelledGroupCoverageRequest, createHttpServletRequest()); + + RenewCancelledGroupCoverageResponse renewCancelledGroupCoverageResponse = response.getBody(); + assertEquals(StatusEnum.SUCCESS, renewCancelledGroupCoverageResponse.getStatus()); + assertEquals("RPBS9014 TRANSACTION COMPLETED", renewCancelledGroupCoverageResponse.getMessage()); + + assertEquals("9873098549", renewCancelledGroupCoverageResponse.getPhn()); + + // Check the client request is sent as expected + RecordedRequest recordedRequest = mockBackEnd.takeRequest(); + assertEquals(HttpMethod.POST.name(), recordedRequest.getMethod()); + assertEquals(MediaType.TEXT_PLAIN.toString(), recordedRequest.getHeader(CONTENT_TYPE)); + + assertTransactionCreated(TransactionType.RENEW_CANCELLED_COVERAGE); + assertAffectedPartyCount(AffectedPartyDirection.INBOUND, 1); + assertAffectedPartyCount(AffectedPartyDirection.OUTBOUND, 1); + } + + /** * The URL property used by the mocked endpoint needs to be set after the MockWebServer starts as the port it uses is * created dynamically on start up to ensure it uses an available port so it is not known before then. @@ -446,4 +624,12 @@ private ReinstateOverAgeDependentRequest createReinstateOverAgeDependentRequest( return reinstateRequest; } + private RenewCancelledGroupCoverageRequest createRenewCancelledGroupCoverageRequest(LocalDate newEffectiveDate) { + RenewCancelledGroupCoverageRequest renewCancelledGroupCoverageRequest =new RenewCancelledGroupCoverageRequest(); + renewCancelledGroupCoverageRequest.setPhn("9873102617"); + renewCancelledGroupCoverageRequest.setGroupNumber("6099733"); + renewCancelledGroupCoverageRequest.setNewCoverageEffectiveDate(newEffectiveDate); + return renewCancelledGroupCoverageRequest; + } + } diff --git a/frontend/src/components/template/TheNavBar.vue b/frontend/src/components/template/TheNavBar.vue index 450e8a6b..35b8e0b9 100644 --- a/frontend/src/components/template/TheNavBar.vue +++ b/frontend/src/components/template/TheNavBar.vue @@ -32,6 +32,7 @@ Change Effective Date Change Cancel Date Reinstate OverAge Dependent + Renew Cancelled Group Coverage @@ -145,7 +146,7 @@ export default { return this.hasPermission('AddGroupMember') || this.hasPermission('AddDependent') || this.hasPermission('UpdateNumberAndDept') || this.hasPermission('CancelGroupMember') || this.hasPermission('CancelDependent') }, hasMaintenancePermission() { - return this.hasPermission('ReinstateOverAgeDependent') || this.hasPermission('ChangeEffectiveDate') || this.hasPermission('ChangeCancelDate') || this.hasPermission('ExtendCancelDate') + return this.hasPermission('ReinstateOverAgeDependent') || this.hasPermission('ChangeEffectiveDate') || this.hasPermission('ChangeCancelDate') || this.hasPermission('RenewCancelledCoverage') }, hasMSPContractsPermission() { return this.hasPermission('GetContractPeriods') || this.hasPermission('ContractInquiry') || this.hasPermission('UpdateContractAddress') diff --git a/frontend/src/router/index.js b/frontend/src/router/index.js index 93633b0c..f5b8eb60 100644 --- a/frontend/src/router/index.js +++ b/frontend/src/router/index.js @@ -18,6 +18,7 @@ import ChangeCancelDate from '../views/coverage/maintenance/ChangeCancelDate.vue import ChangeEffectiveDate from '../views/coverage/maintenance/ChangeEffectiveDate.vue' import CoverageMaintenanceHome from '../views/coverage/maintenance/CoverageMaintenanceHome.vue' import ReinstateOverAgeDependent from '../views/coverage/maintenance/ReinstateOverAgeDependent.vue' +import RenewCancelledGroupCoverage from '../views/coverage/maintenance/RenewCancelledGroupCoverage.vue' import EligibilityHome from '../views/eligibility/EligibilityHome.vue' import PhnInquiry from '../views/eligibility/PhnInquiry.vue' import PhnLookup from '../views/eligibility/PhnLookup.vue' @@ -138,6 +139,15 @@ const createRoutes = (app) => [ requiresAuth: true, }, }, + { + path: 'renewCancelledGroupCoverage', + name: 'RenewCancelledGroupCoverage', + component: RenewCancelledGroupCoverage, + meta: { + permission: 'RenewCancelledCoverage', + requiresAuth: true, + }, + }, ], }, { diff --git a/frontend/src/services/BaseService.js b/frontend/src/services/BaseService.js index 8eaf9e9b..d4c25fe3 100644 --- a/frontend/src/services/BaseService.js +++ b/frontend/src/services/BaseService.js @@ -32,6 +32,7 @@ export const resources = { changeEffectiveDate: '/maintenance/change-effective-date', changeCancelDate: '/maintenance/change-cancel-date', reinstateOverAgeDependent: '/maintenance/reinstate-over-age-dependent', + renewCancelledGroupCoverage: '/maintenance/renew-cancelled-group-coverage', }, mspContracts: { getContractPeriods: '/msp-contracts/get-contract-periods', diff --git a/frontend/src/services/MaintenanceService.js b/frontend/src/services/MaintenanceService.js index 61d1598c..e9848521 100644 --- a/frontend/src/services/MaintenanceService.js +++ b/frontend/src/services/MaintenanceService.js @@ -10,4 +10,8 @@ export default { reinstateOverAgeDependent(request) { return apiRequest().then((axiosInstance) => axiosInstance.post(resources.maintenance.reinstateOverAgeDependent, request)) }, + + renewCancelledGroupCoverage(request) { + return apiRequest().then((axiosInstance) => axiosInstance.post(resources.maintenance.renewCancelledGroupCoverage, request)) + }, } diff --git a/frontend/src/views/coverage/maintenance/CoverageMaintenanceHome.vue b/frontend/src/views/coverage/maintenance/CoverageMaintenanceHome.vue index 12046ef2..eb75dfec 100644 --- a/frontend/src/views/coverage/maintenance/CoverageMaintenanceHome.vue +++ b/frontend/src/views/coverage/maintenance/CoverageMaintenanceHome.vue @@ -3,6 +3,7 @@ + diff --git a/frontend/src/views/coverage/maintenance/RenewCancelledGroupCoverage.vue b/frontend/src/views/coverage/maintenance/RenewCancelledGroupCoverage.vue new file mode 100644 index 00000000..bb3d9069 --- /dev/null +++ b/frontend/src/views/coverage/maintenance/RenewCancelledGroupCoverage.vue @@ -0,0 +1,130 @@ + + + diff --git a/frontend/tests/e2e/pages/maintenance/RenewCancelledCoveragePage.js b/frontend/tests/e2e/pages/maintenance/RenewCancelledCoveragePage.js new file mode 100644 index 00000000..feec2544 --- /dev/null +++ b/frontend/tests/e2e/pages/maintenance/RenewCancelledCoveragePage.js @@ -0,0 +1,14 @@ +import { Selector } from 'testcafe' + +class RenewCancelledCoverage { + constructor() { + this.groupNumberInput = Selector('#groupNumber') + this.phnInput = Selector('#phn') + this.newEffectiveDateInput = Selector('#dp-input-newCoverageEffectiveDate') + this.submitButton = Selector('button[type="submit"]') + this.clearButton = Selector('button[type="button"]').withText('Clear') + this.errorText = Selector('div').withAttribute('class', 'error-text') + } +} + +export default new RenewCancelledCoverage() diff --git a/frontend/tests/e2e/tests/maintenance/RenewCancelledCoverageTest.js b/frontend/tests/e2e/tests/maintenance/RenewCancelledCoverageTest.js new file mode 100644 index 00000000..b92bccb9 --- /dev/null +++ b/frontend/tests/e2e/tests/maintenance/RenewCancelledCoverageTest.js @@ -0,0 +1,120 @@ +import dayjs from 'dayjs' + +import { SITE_UNDER_TEST } from '../../configuration' +import AlertPage from '../../pages/AlertPage' +import RenewCancelledCoveragePage from '../../pages/maintenance/RenewCancelledCoveragePage' +import { regularAccUser } from '../../roles/roles' + +const ERROR_MESSAGE = 'Please correct errors before submitting' +const GROUP_NUMBER_REQUIRED_MESSAGE = 'Group Number is required' +const PHN_REQUIRED_MESSAGE = 'PHN is required' +const NEW_COVERAGE_EFFECTIVE_DATE_REQUIRED_MESSAGE = 'New Coverage Effective Date is required' +const INVALID_GROUP_NUMBER_ERROR_MESSAGE = 'Group Number is invalid' +const INVALID_PHN_ERROR_MESSAGE = 'PHN format is invalid' +const SUBSCRIBER_HAS_FUTURE_COVERAGE = 'RPBS0049 SUBSCRIBER HAS FUTURE COVERAGE. PLS FORWARD DOCS TO MSP' +const INVALID_COVERAGE_EFFECTIVE_DATE = 'RPBS0276 COVERGE EFFECTIVE DAY MUST BE 01' +const SUBSCRIBER_NOT_COVERED_UNDER_THIS_GROUP = 'RPBS9109 SUBSCRIBER NOT COVERED UNDER THIS GROUP' +const PAGE_TO_TEST = SITE_UNDER_TEST + '/coverage/maintenance/renewCancelledGroupCoverage' + +fixture(`Renew Cancelled Group Coverage`).disablePageCaching`Test Renew Cancelled Group Coverage` + .beforeEach(async (t) => { + await t.useRole(regularAccUser).navigateTo(PAGE_TO_TEST) + }) + .page(SITE_UNDER_TEST) + +test('Check required fields validation', async (t) => { + await t + // Given required fields aren't filled out (PHN) + // When I click the submit button + .click(RenewCancelledCoveragePage.newEffectiveDateInput) + .selectText(RenewCancelledCoveragePage.newEffectiveDateInput) + .pressKey('delete') + .pressKey('tab') + .click(RenewCancelledCoveragePage.submitButton) + // I expect an error message stating the page had errors and individual error messages for each required field + .expect(AlertPage.alertBannerText.textContent) + .contains(ERROR_MESSAGE) + .expect(RenewCancelledCoveragePage.errorText.nth(0).textContent) + .contains(GROUP_NUMBER_REQUIRED_MESSAGE) + .expect(RenewCancelledCoveragePage.errorText.nth(1).textContent) + .contains(PHN_REQUIRED_MESSAGE) + .expect(RenewCancelledCoveragePage.errorText.nth(2).textContent) + .contains(NEW_COVERAGE_EFFECTIVE_DATE_REQUIRED_MESSAGE) +}) + +test('Check invalid phn, groupNumber format validation', async (t) => { + await t + // Given a PHN entered with an invalid format + .typeText(RenewCancelledCoveragePage.phnInput, '9000448000') + .typeText(RenewCancelledCoveragePage.groupNumberInput, '0000001') + // When I click the submit button + .click(RenewCancelledCoveragePage.submitButton) + // I expect an error message stating the page had errors and an individual error message for the PHN format + .expect(AlertPage.alertBannerText.textContent) + .contains(ERROR_MESSAGE) + .expect(RenewCancelledCoveragePage.errorText.nth(0).textContent) + .contains(INVALID_GROUP_NUMBER_ERROR_MESSAGE) + .expect(RenewCancelledCoveragePage.errorText.nth(1).textContent) + .contains(INVALID_PHN_ERROR_MESSAGE) +}) + +test('Check properly filled form passes validation and validate results, invalid coverage effective date', async (t) => { + await t + // Given the page is filled out correctly + .typeText(RenewCancelledCoveragePage.groupNumberInput, '4841904') + .typeText(RenewCancelledCoveragePage.phnInput, '9873251693') + .selectText(RenewCancelledCoveragePage.newEffectiveDateInput) + .pressKey('delete') + .typeText(RenewCancelledCoveragePage.newEffectiveDateInput, '20220731') + .pressKey('tab') + .pressKey('tab') + // When I click the submit button + .click(RenewCancelledCoveragePage.submitButton) + // I expect a Error message + .expect(AlertPage.alertBannerText.textContent) + .contains(INVALID_COVERAGE_EFFECTIVE_DATE) +}) + +test('Check properly filled form passes validation and validate results, subscriber has future coverage', async (t) => { + await t + // Given the page is filled out correctly + .typeText(RenewCancelledCoveragePage.groupNumberInput, '6099733') + .typeText(RenewCancelledCoveragePage.phnInput, '9873102617') + // When I click the submit button + .click(RenewCancelledCoveragePage.submitButton) + // I expect a Error message + .expect(AlertPage.alertBannerText.textContent) + .contains(SUBSCRIBER_HAS_FUTURE_COVERAGE) +}) + +test('Check properly filled form passes validation and validate results, subscriber not covered under this coverage', async (t) => { + await t + // Given the page is filled out correctly + .typeText(RenewCancelledCoveragePage.groupNumberInput, '4841904') + .typeText(RenewCancelledCoveragePage.phnInput, '9873102617') + // When I click the submit button + .click(RenewCancelledCoveragePage.submitButton) + // I expect a Error message + .expect(AlertPage.alertBannerText.textContent) + .contains(SUBSCRIBER_NOT_COVERED_UNDER_THIS_GROUP) +}) + +test('Check clear button clears the form', async (t) => { + await t + // Given I have a form filled out with data + .typeText(RenewCancelledCoveragePage.groupNumberInput, '4841904') + .typeText(RenewCancelledCoveragePage.phnInput, '9873251693') + .selectText(RenewCancelledCoveragePage.newEffectiveDateInput) + .pressKey('delete') + .typeText(RenewCancelledCoveragePage.newEffectiveDateInput, '20220701') + .pressKey('tab') + // When I click the Clear button + .click(RenewCancelledCoveragePage.clearButton) + // I expect the form to be cleared + .expect(RenewCancelledCoveragePage.phnInput.value) + .eql('') + .expect(RenewCancelledCoveragePage.groupNumberInput.value) + .eql('') + .expect(RenewCancelledCoveragePage.newEffectiveDateInput.value) + .notEql('') +})