import { Injectable } from '@angular/core'; import { SpinnerService } from '@core/services/spinner.service'; import { MyApplicationFromApi, VettingRequestStatusId } from '@core/typings/application.typing'; import { ApplicationApplicantService } from '@features/apply/application-applicant.service'; import { NonprofitService } from '@features/nonprofit/nonprofit.service'; import { ProgramService } from '@features/programs/program.service'; import { I18nService } from '@yourcause/common/i18n'; import { ConfirmationModalComponent, ModalFactory } from '@yourcause/common/modals'; import { ApplicationEligibilityResources } from './application-eligibility.resources'; import { ApplicationEligibility } from './application-eligibility.typing'; @Injectable({ providedIn: 'root' }) export class ApplicationEligibilityService { constructor ( private applicationEligibilityResources: ApplicationEligibilityResources, private i18n: I18nService, private nonprofitService: NonprofitService, private modalFactory: ModalFactory, private applicationApplicantService: ApplicationApplicantService, private programService: ProgramService, private spinnerService: SpinnerService ) {} async checkOrganizationEligibilityStatus ( payload: ApplicationEligibility.ApplicantCopyEligibilityPayload ) { return this.applicationEligibilityResources.checkOrganizationEligibilityStatus(payload); } async checkIfCycleUpdateCanProceed ( payload: ApplicationEligibility.ProgramUpdateEligibilityPayload, forApplicant = false ): Promise { if (payload.orgIdentification) { let apiResponse; if (forApplicant) { apiResponse = await this.checkOrganizationEligibilityStatus(payload); } else { apiResponse = await this.organizationEligibilityCheck(payload); } let charityBucketEligible = true; if (!!payload.charityBucketId) { const charityBucketSearchResponse = await this.nonprofitService.searchNonprofitsWithinBucket( payload.orgIdentification, 1, 5, payload.clientId, payload.charityBucketId ); charityBucketEligible = charityBucketSearchResponse?.data.some((org) => { const orgIdentification = org.registrationNumber.replace('-', ''); return orgIdentification === payload.orgIdentification; }); } const eligibilityCode = charityBucketEligible ? apiResponse : ApplicationEligibility.OrganizationEligibilityCheckResponse.OrganizationNotInCharityBucket; const message = this.getMessageForIneligibleCycleUpdate( eligibilityCode, payload.latestVettingRequestStatusForOrg ); return message; } return ''; } getMessageForIneligibleCycleUpdate ( responseFromApi: ApplicationEligibility.OrganizationEligibilityCheckResponse, latestVettingRequestStatusForOrg: VettingRequestStatusId ) { let message = ''; switch (responseFromApi) { default: case ApplicationEligibility.OrganizationEligibilityCheckResponse.OrganizationEligible: message = null; break; case ApplicationEligibility.OrganizationEligibilityCheckResponse.OrganizationNotActiveInNpp: message = this.i18n.translate( 'PROGRAM:textOrganizationNoLongerActiveInNPP', {}, `This application cannot be copied or moved. The organization linked to this application is no longer active in YourCause + Blackbaud's Global Good Network and cannot accept applications.` ); break; case ApplicationEligibility.OrganizationEligibilityCheckResponse.OrganizationNotEligibleForGiving: if (!latestVettingRequestStatusForOrg) { message = this.i18n.translate( 'PROGRAM:textOrganizationNotEligibleForGiving2', {}, 'This application cannot be copied or moved. The organization linked to this application is not currently eligible for giving.' ); } break; case ApplicationEligibility.OrganizationEligibilityCheckResponse.OrganizationNotValidForGrantProgramBudget: message = this.i18n.translate( 'PROGRAM:textOrganizationNotValidForBudget2', {}, 'This application cannot be copied or moved. The organization linked to this application is not valid for the selected budget at this time.' ); break; case ApplicationEligibility.OrganizationEligibilityCheckResponse.OrganizationNotInCharityBucket: message = this.i18n.translate( 'PROGRAM:textOrganizationNotInCharityBucket2', {}, 'This application cannot be copied or moved. This organization is no longer included in the preferred charity list for this program.' ); break; } return message; } async showErrorCopyingApplication ( errorMessage: string, modalHeader: string ) { await this.modalFactory.open( ConfirmationModalComponent, { confirmText: errorMessage, modalHeader, confirmButtonText: this.i18n.translate('common:textClose', {}, 'Close') } ); } async organizationEligibilityCheck ( payload: ApplicationEligibility.OrganizationEligibilityCheckPayload ): Promise { return this.applicationEligibilityResources.organizationEligibilityCheck(payload); } async checkEligibilityForApplicantView ( application: MyApplicationFromApi ): Promise { // get program const program = await this.programService.getProgramForApplicant( '' + application.grantProgramId ); // get application details for copied app const copyApplication = await this.applicationApplicantService.getApplicationByForm( application.applicationId, program.form.formId ); // check eligibility const potentialErrorMessage = await this.checkIfCycleUpdateCanProceed({ applicationId: application.applicationId, grantProgramCycleId: copyApplication.cycle.id, grantProgramId: program.grantProgramId, orgIdentification: copyApplication.organization?.orgIdentification, charityBucketId: program.charityBucketId, clientId: program.clientId, latestVettingRequestStatusForOrg: copyApplication.latestVettingRequestStatusForOrg }, true); if (potentialErrorMessage) { this.spinnerService.stopSpinner(); await this.showErrorCopyingApplication( potentialErrorMessage, this.i18n.translate( 'PROGRAM:hdrUnableToCopyApplication', {}, 'Unable to copy Application' ) ); return false; } else { return true; } } }