Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
peggy-quartech committed Sep 20, 2024
2 parents d6d49fe + 3c22d46 commit fe87669
Show file tree
Hide file tree
Showing 29 changed files with 3,739 additions and 3,169 deletions.
3 changes: 2 additions & 1 deletion src/Spd.Manager.Screening/ApplicationContract.cs
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,8 @@ public enum ApplicationPortalStatusCode
ClosedNoConsent,
CancelledByApplicant,
CancelledByOrganization,
RefundRequested
RefundRequested,
Completed
}

public enum ApplicationPortalStatisticsCode
Expand Down
44 changes: 29 additions & 15 deletions src/Spd.Manager.Screening/ApplicationManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,8 @@ await _delegateRepository.ManageAsync(
}, ct);
}

//update status : if psso or volunteer, go directly to submitted
if ((request.ParentOrgId == SpdConstants.BcGovOrgId || request.ApplicationCreateRequest.ServiceType == ServiceTypeCode.CRRP_VOLUNTEER)
&& request.ApplicationCreateRequest.HaveVerifiedIdentity == true)
//update status
if (IfSubmittedDirectly(request.ApplicationCreateRequest.ServiceType, request.ApplicationCreateRequest.PayeeType, request.ApplicationCreateRequest.HaveVerifiedIdentity ?? false))
{
await _applicationRepository.UpdateAsync(
new UpdateCmd()
Expand Down Expand Up @@ -231,7 +230,7 @@ public async Task<ApplicationStatisticsResponse> Handle(ApplicationStatisticsQue

public async Task<Unit> Handle(VerifyIdentityCommand request, CancellationToken ct)
{
OrgQryResult org = (OrgQryResult)await _orgRepository.QueryOrgAsync(new OrgByIdentifierQry(request.OrgId), ct);
ApplicationResult app = await _applicationRepository.QueryApplicationAsync(new ApplicationQry(request.ApplicationId), ct);
UpdateCmd updateCmd = new()
{
OrgId = request.OrgId,
Expand All @@ -245,18 +244,14 @@ public async Task<Unit> Handle(VerifyIdentityCommand request, CancellationToken
}
else
{
//if org is psso or if org is volunteer crrp, set application status to submitted.
if (org.OrgResult.ParentOrgId == SpdConstants.BcGovOrgId ||
org.OrgResult.Id == SpdConstants.BcGovOrgId ||
org.OrgResult.ServiceTypes.Any(t => t == ServiceTypeEnum.CRRP_VOLUNTEER || t == ServiceTypeEnum.PSSO || t == ServiceTypeEnum.PSSO_VS || t == ServiceTypeEnum.MCFD || t == ServiceTypeEnum.PE_CRC || t == ServiceTypeEnum.PE_CRC_VS)) //is PSSO
Shared.PayerPreferenceTypeCode? payerPreference = app.PayeeType == null ? null : Enum.Parse<Shared.PayerPreferenceTypeCode>(app.PayeeType.Value.ToString());
if (IfSubmittedDirectly(Enum.Parse<ServiceTypeCode>(app.ServiceType.Value.ToString()), payerPreference, true))
{
updateCmd.Status = ApplicationStatusEnum.Submitted;
}
else
{
//if org is non-volunteer crrp
ApplicationResult result = await _applicationRepository.QueryApplicationAsync(new ApplicationQry(request.ApplicationId), ct);
if (result.PaidOn != null) //already paid
if (app.PaidOn != null) //already paid
updateCmd.Status = ApplicationStatusEnum.Submitted;
else //not paid
updateCmd.Status = ApplicationStatusEnum.PaymentPending;
Expand Down Expand Up @@ -454,9 +449,8 @@ public async Task<ApplicationCreateResponse> Handle(ApplicantApplicationCreateCo
result.CreateSuccess = true;
}

//update status : if psso or volunteer, go directly to submitted
if ((cmd.ParentOrgId == SpdConstants.BcGovOrgId || command.ApplicationCreateRequest.ServiceType == ServiceTypeCode.CRRP_VOLUNTEER)
&& command.ApplicationCreateRequest.HaveVerifiedIdentity == true)
//update status
if (IfSubmittedDirectly(command.ApplicationCreateRequest.ServiceType, command.ApplicationCreateRequest.PayeeType, command.ApplicationCreateRequest.HaveVerifiedIdentity ?? false))
{
await _applicationRepository.UpdateAsync(
new UpdateCmd()
Expand Down Expand Up @@ -628,7 +622,27 @@ await retryIfNoFound.Execute(async () =>
}
return new FileResponse();
}
#endregion

#endregion applicant-applications
private static bool IfSubmittedDirectly(ServiceTypeCode serviceType, Shared.PayerPreferenceTypeCode? payerPreference, bool IdentityVerified)
{
bool noNeedToPay = false;
if (serviceType == ServiceTypeCode.CRRP_VOLUNTEER) noNeedToPay = true;
if (serviceType == ServiceTypeCode.PSSO) noNeedToPay = true;
if (serviceType == ServiceTypeCode.MCFD) noNeedToPay = true;
if (serviceType == ServiceTypeCode.PSSO_VS) noNeedToPay = true;
if (serviceType == ServiceTypeCode.PE_CRC || serviceType == ServiceTypeCode.PE_CRC_VS)
{
if (payerPreference == Shared.PayerPreferenceTypeCode.Organization || payerPreference == null) noNeedToPay = true;
else noNeedToPay = false;
}
if (serviceType == ServiceTypeCode.CRRP_EMPLOYEE) noNeedToPay = false;
if (noNeedToPay)
{
if (IdentityVerified) return true;
}

return false;
}
}
}
25 changes: 24 additions & 1 deletion src/Spd.Manager.Screening/ApplicationMappings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
using Spd.Resource.Repository.Incident;
using Spd.Resource.Repository.PortalUser;
using Spd.Utilities.Shared;
using Spd.Utilities.Shared.Exceptions;
using System.Net;

namespace Spd.Manager.Screening
{
Expand All @@ -19,7 +21,8 @@ public ApplicationMappings()
{
_ = CreateMap<ApplicationInvitesCreateRequest, ApplicationInvitesCreateCmd>()
.ForMember(d => d.ApplicationInvites, opt => opt.MapFrom(s => s.ApplicationInviteCreateRequests));
CreateMap<ApplicationInviteCreateRequest, Resource.Repository.ApplicationInvite.ApplicationInvite>();
CreateMap<ApplicationInviteCreateRequest, Resource.Repository.ApplicationInvite.ApplicationInvite>()
.ForMember(d => d.PayeeType, opt => opt.MapFrom(s => GetPayerPreferenceTypeCode(s)));
CreateMap<ApplicationInviteCreateRequest, AppInviteDuplicateCheck>();
CreateMap<AppInviteDuplicateCheckResult, ApplicationInviteDuplicateResponse>();
CreateMap<ApplicationInviteCreateRequest, ApplicationInviteDuplicateResponse>();
Expand Down Expand Up @@ -126,5 +129,25 @@ public ApplicationMappings()
return SpdConstants.BcGovOrgId;
return null;
}

private Resource.Repository.PayerPreferenceTypeCode? GetPayerPreferenceTypeCode(ApplicationInviteCreateRequest inviteRequest)
{
if (inviteRequest.ServiceType == ServiceTypeCode.CRRP_EMPLOYEE)
{
if (inviteRequest.PayeeType == null) throw new ApiException(HttpStatusCode.BadRequest, "Payee type is required.");
return Enum.Parse<Resource.Repository.PayerPreferenceTypeCode>(inviteRequest.PayeeType.Value.ToString());
}

if (inviteRequest.ServiceType == ServiceTypeCode.CRRP_VOLUNTEER) return null;
if (inviteRequest.ServiceType == ServiceTypeCode.PSSO || inviteRequest.ServiceType == ServiceTypeCode.PSSO_VS || inviteRequest.ServiceType == ServiceTypeCode.MCFD)
return null;
if (inviteRequest.ServiceType == ServiceTypeCode.PE_CRC || inviteRequest.ServiceType == ServiceTypeCode.PE_CRC_VS)
{
if (inviteRequest.PayeeType == Shared.PayerPreferenceTypeCode.Applicant) return Resource.Repository.PayerPreferenceTypeCode.Applicant;
if (inviteRequest.PayeeType == Shared.PayerPreferenceTypeCode.Organization) return null;
if (inviteRequest.PayeeType == null) throw new ApiException(HttpStatusCode.BadRequest, "Payee type is required.");
}
return null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ import { PaymentLinkCreateRequest } from '../../models/payment-link-create-reque
import { PaymentLinkResponse } from '../../models/payment-link-response';

export interface ApiOrgsOrgIdApplicationsApplicationIdPaymentLinkPost$Params {

/**
* organization id
*/
orgId: string;
applicationId: string;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ export enum ApplicationPortalStatusCode {
ClosedNoConsent = 'ClosedNoConsent',
CancelledByApplicant = 'CancelledByApplicant',
CancelledByOrganization = 'CancelledByOrganization',
RefundRequested = 'RefundRequested'
RefundRequested = 'RefundRequested',
Completed = 'Completed'
}
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ export const ApplicationPortalStatusTypes: SelectOptions[] = [
extra: 'The application is in risk assessment',
},
{ desc: 'Incomplete', code: ApplicationPortalStatusCode.Incomplete, extra: 'Incomplete application received' },
{ desc: 'Completed', code: ApplicationPortalStatusCode.Completed },
{
desc: 'Completed - Cleared',
code: ApplicationPortalStatusCode.CompletedCleared,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,7 @@ export const SPD_CONSTANTS = {
peCrcApplication: 'https://www2.gov.bc.ca/gov/content/home',
mcfdApplication:
'https://www2.gov.bc.ca/gov/content/governments/organizational-structure/ministries-organizations/ministries/children-and-family-development',
pssoCheck:
'https://www2.gov.bc.ca/gov/content/careers-myhr/hiring-managers/process/extend-offer/security-screening/about',
pssoCheck: 'https://www2.gov.bc.ca/gov/content/careers-myhr',
},
message: {
pssoVsWarning: 'I confirm I am submitting a combined check on behalf of the Centralized Services Hub (CSH) team.',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,8 @@ export class CrrpaComponent implements OnInit {
});

orgData.isCrrpa = true;
orgData.notPssoOrPecrc = true;
orgData.bcGovEmployeeIdShow = false;
orgData.performPaymentProcess = false; //default
orgData.readonlyTombstone = false; // default
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,15 @@ import { Component, OnInit, ViewChild } from '@angular/core';
import { MatStepper } from '@angular/material/stepper';
import { Router } from '@angular/router';
import { distinctUntilChanged } from 'rxjs';
import { ApplicantAppCreateRequest, ApplicationCreateResponse } from 'src/app/api/models';
import { ApplicantService } from 'src/app/api/services';
import {
ApplicantAppCreateRequest,
ApplicationCreateResponse,
PaymentLinkCreateRequest,
PaymentLinkResponse,
PaymentMethodCode,
ServiceTypeCode,
} from 'src/app/api/models';
import { ApplicantService, PaymentService } from 'src/app/api/services';
import { AppRoutes } from 'src/app/app-routing.module';
import { PortalTypeCode } from 'src/app/core/code-types/portal-type.model';
import { SPD_CONSTANTS } from 'src/app/core/constants/constants';
Expand Down Expand Up @@ -144,6 +151,7 @@ export class PssoaComponent implements OnInit {
private authProcessService: AuthProcessService,
private authUserService: AuthUserBcscService,
private applicantService: ApplicantService,
private paymentService: PaymentService,
private location: Location
) {}

Expand All @@ -170,6 +178,10 @@ export class PssoaComponent implements OnInit {
});

orgData.isCrrpa = false;
orgData.notPssoOrPecrc =
orgData.serviceType != ServiceTypeCode.Psso && orgData.serviceType != ServiceTypeCode.PeCrc;
orgData.bcGovEmployeeIdShow =
orgData.serviceType != ServiceTypeCode.PeCrc && orgData.serviceType != ServiceTypeCode.PeCrcVs;
orgData.performPaymentProcess = false; // does not apply to psso
orgData.readonlyTombstone = false; // default
orgData.shareableCrcExists = false; // does not apply to psso
Expand Down Expand Up @@ -338,20 +350,50 @@ export class PssoaComponent implements OnInit {
this.applicantService
.apiApplicantsScreeningsPost({ body })
.pipe()
.subscribe((_res: ApplicationCreateResponse) => {
this.stepper.next();
.subscribe((res: ApplicationCreateResponse) => {
if (this.orgData!.performPaymentProcess) {
this.payNow(res.applicationId!);
} else {
this.stepper.next();
}
});
} else {
body.haveVerifiedIdentity = false;
this.applicantService
.apiApplicantsScreeningsAnonymousPost({ body })
.pipe()
.subscribe((_res: ApplicationCreateResponse) => {
this.stepper.next();
.subscribe((res: ApplicationCreateResponse) => {
if (this.orgData!.performPaymentProcess) {
this.payNow(res.applicationId!);
} else {
this.stepper.next();
}
});
}
}

private payNow(applicationId: string): void {
if (this.authenticationService.isLoggedIn()) {
this.authProcessService.refreshToken();
}

const body: PaymentLinkCreateRequest = {
applicationId: applicationId,
paymentMethod: PaymentMethodCode.CreditCard,
description: 'Payment for Invitation',
};
this.paymentService
.apiCrrpaPaymentLinkPost({
body,
})
.pipe()
.subscribe((res: PaymentLinkResponse) => {
if (res.paymentLinkUrl) {
window.location.assign(res.paymentLinkUrl);
}
});
}

private assignApplicantUserInfoData(orgData: AppInviteOrgData | null): void {
const bcscUserInfoProfile = this.authUserService.bcscUserInfoProfile;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
CaseSubStatusCode,
FileTemplateTypeCode,
FileTypeCode,
PayerPreferenceTypeCode,
ServiceTypeCode,
} from 'src/app/api/models';
import { ApplicantService, PaymentService } from 'src/app/api/services';
Expand Down Expand Up @@ -253,7 +254,7 @@ export class SecurityScreeningDetailComponent implements OnInit, AfterViewInit {
if (applicationData) {
this.loadList(applicationData);
this.showDownloadReceipt =
applicationData.serviceType === ServiceTypeCode.CrrpEmployee &&
applicationData.payeeType === PayerPreferenceTypeCode.Applicant &&
applicationData.status != ApplicationPortalStatusCode.AwaitingPayment;
} else {
this.router.navigate([SecurityScreeningRoutes.path(SecurityScreeningRoutes.CRC_LIST)]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,13 @@ import {
import { ApplicationService } from 'src/app/api/services';
import { AppRoutes } from 'src/app/app-routing.module';
import { ApplicationOriginTypeCode } from 'src/app/core/code-types/application-origin-type.model';
import { GenderTypes, ScreeningTypes, SelectOptions, ServiceTypes } from 'src/app/core/code-types/model-desc.models';
import {
GenderTypes,
PayerPreferenceTypes,
ScreeningTypes,
SelectOptions,
ServiceTypes,
} from 'src/app/core/code-types/model-desc.models';
import { PortalTypeCode } from 'src/app/core/code-types/portal-type.model';
import { SPD_CONSTANTS } from 'src/app/core/constants/constants';
import { AuthUserBceidService } from 'src/app/core/services/auth-user-bceid.service';
Expand Down Expand Up @@ -232,14 +238,30 @@ export interface ManualSubmissionBody {
<div class="col-xl-3 col-lg-6 col-md-12" *ngIf="showServiceType">
<mat-form-field>
<mat-label>Service Type</mat-label>
<mat-select formControlName="serviceType" [errorStateMatcher]="matcher">
<mat-select
formControlName="serviceType"
(selectionChange)="onChangeServiceType($event)"
[errorStateMatcher]="matcher"
>
<mat-option *ngFor="let srv of serviceTypes" [value]="srv.code">
{{ srv.desc }}
</mat-option>
</mat-select>
<mat-error *ngIf="form.get('serviceType')?.hasError('required')">This is required</mat-error>
</mat-form-field>
</div>
<div class="col-xl-3 col-lg-6 col-md-12" *ngIf="showPaidBy">
<mat-form-field>
<mat-label>Paid by</mat-label>
<mat-select formControlName="payeeType" [errorStateMatcher]="matcher">
<mat-option *ngFor="let payer of payerPreferenceTypes" [value]="payer.code">
{{ payer.desc }}
</mat-option>
</mat-select>
<mat-error *ngIf="form.get('payeeType')?.hasError('required')">This is required</mat-error>
</mat-form-field>
</div>
</div>
<ng-container *ngIf="serviceTypeIsPssoVs">
<app-alert type="warning">{{ pssoVsWarning }}</app-alert>
Expand Down Expand Up @@ -497,8 +519,10 @@ export class ManualSubmissionCommonComponent implements OnInit {
showScreeningType = false;
screeningTypes = ScreeningTypes;
screeningTypeCodes = ScreeningTypeCode;
payerPreferenceTypes = PayerPreferenceTypes;

showServiceType = false;
showPaidBy = false;
serviceTypeDefault: ServiceTypeCode | null = null;
serviceTypes: null | SelectOptions[] = [];

Expand All @@ -523,6 +547,7 @@ export class ManualSubmissionCommonComponent implements OnInit {
jobTitle: new FormControl('', [FormControlValidators.required]),
screeningType: new FormControl(''),
serviceType: new FormControl(this.serviceTypeDefault),
payeeType: new FormControl(''),
contractedCompanyName: new FormControl(''),
employeeId: new FormControl(''),
orgId: new FormControl(null),
Expand All @@ -543,6 +568,9 @@ export class ManualSubmissionCommonComponent implements OnInit {
validators: [
FormGroupValidators.conditionalRequiredValidator('screeningType', (_form) => this.showScreeningType ?? false),
FormGroupValidators.conditionalRequiredValidator('serviceType', (_form) => this.showServiceType ?? false),
FormGroupValidators.conditionalRequiredValidator('payeeType', (_form) =>
this.isPeCrc(_form.get('serviceType')?.value ?? false)
),
FormGroupValidators.conditionalDefaultRequiredValidator(
'emailAddress',
(_form) => this.portal == PortalTypeCode.Crrp
Expand Down Expand Up @@ -636,6 +664,10 @@ export class ManualSubmissionCommonComponent implements OnInit {
this.populateServiceTypes(event.value);
}

onChangeServiceType(event: MatSelectChange): void {
this.showPaidBy = this.isPeCrc(event.value);
}

onCancel(): void {
this.resetForm();
}
Expand Down Expand Up @@ -805,6 +837,10 @@ export class ManualSubmissionCommonComponent implements OnInit {
return [ScreeningTypeCode.Contractor, ScreeningTypeCode.Licensee].includes(this.screeningType.value);
}

private isPeCrc(serviceTypeCode: ServiceTypeCode): boolean {
return serviceTypeCode === ServiceTypeCode.PeCrc || serviceTypeCode === ServiceTypeCode.PeCrcVs;
}

private populateServiceTypes(orgId: string | null | undefined) {
if (!orgId) {
this.serviceTypes = [];
Expand Down
Loading

0 comments on commit fe87669

Please sign in to comment.