diff --git a/portal-frontend/src/app/features/public/application/alc-review/alc-review.component.html b/portal-frontend/src/app/features/public/application/alc-review/alc-review.component.html index 4ea1d813f6..936712c82c 100644 --- a/portal-frontend/src/app/features/public/application/alc-review/alc-review.component.html +++ b/portal-frontend/src/app/features/public/application/alc-review/alc-review.component.html @@ -1,45 +1,9 @@ -
+

ALC Review and Decision

-
- - -
-
- This section will update after the application is submitted to the ALC. -
-
- Application not subject to Agricultural Land Commission review. -
-
- - +
+ +
diff --git a/portal-frontend/src/app/features/public/application/alc-review/alc-review.component.spec.ts b/portal-frontend/src/app/features/public/application/alc-review/alc-review.component.spec.ts index 62a72d72d0..3a515a8c48 100644 --- a/portal-frontend/src/app/features/public/application/alc-review/alc-review.component.spec.ts +++ b/portal-frontend/src/app/features/public/application/alc-review/alc-review.component.spec.ts @@ -1,28 +1,18 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { createMock, DeepMocked } from '@golevelup/ts-jest'; -import { ApplicationSubmissionReviewService } from '../../../../services/application-submission-review/application-submission-review.service'; -import { AlcReviewComponent } from './alc-review.component'; +import { PublicAlcReviewComponent } from './alc-review.component'; -describe('AlcsReviewComponent', () => { - let component: AlcReviewComponent; - let fixture: ComponentFixture; - let mockAppReviewService: DeepMocked; +describe('PublicAlcReviewComponent', () => { + let component: PublicAlcReviewComponent; + let fixture: ComponentFixture; beforeEach(async () => { - mockAppReviewService = createMock(); - await TestBed.configureTestingModule({ - providers: [ - { - provide: ApplicationSubmissionReviewService, - useValue: mockAppReviewService, - }, - ], - declarations: [AlcReviewComponent], + providers: [], + declarations: [PublicAlcReviewComponent], }).compileComponents(); - fixture = TestBed.createComponent(AlcReviewComponent); + fixture = TestBed.createComponent(PublicAlcReviewComponent); component = fixture.componentInstance; fixture.detectChanges(); }); diff --git a/portal-frontend/src/app/features/public/application/alc-review/alc-review.component.ts b/portal-frontend/src/app/features/public/application/alc-review/alc-review.component.ts index ced2da29b9..e1c8c5b643 100644 --- a/portal-frontend/src/app/features/public/application/alc-review/alc-review.component.ts +++ b/portal-frontend/src/app/features/public/application/alc-review/alc-review.component.ts @@ -1,47 +1,19 @@ -import { Component, Input, OnDestroy, OnInit } from '@angular/core'; -import { Router } from '@angular/router'; -import { BehaviorSubject, Subject, takeUntil } from 'rxjs'; -import { ApplicationDocumentDto } from '../../../../services/application-document/application-document.dto'; -import { ApplicationSubmissionReviewService } from '../../../../services/application-submission-review/application-submission-review.service'; -import { - SUBMISSION_STATUS, - ApplicationSubmissionDetailedDto, -} from '../../../../services/application-submission/application-submission.dto'; +import { Component, Input } from '@angular/core'; +import { ApplicationPortalDecisionDto } from '../../../../services/application-decision/application-decision.dto'; +import { SUBMISSION_STATUS } from '../../../../services/application-submission/application-submission.dto'; +import { PublicApplicationSubmissionDto, PublicDocumentDto } from '../../../../services/public/public.dto'; @Component({ - selector: 'app-alc-review', + selector: 'app-public-alc-review', templateUrl: './alc-review.component.html', styleUrls: ['./alc-review.component.scss'], }) -export class AlcReviewComponent implements OnInit, OnDestroy { - private $destroy = new Subject(); +export class PublicAlcReviewComponent { + @Input() applicationSubmission!: PublicApplicationSubmissionDto; + @Input() applicationDocuments!: PublicDocumentDto[]; + @Input() applicationDecisions!: ApplicationPortalDecisionDto[]; - @Input() $application = new BehaviorSubject(undefined); - @Input() $applicationDocuments = new BehaviorSubject([]); - - application: ApplicationSubmissionDetailedDto | undefined; SUBMISSION_STATUS = SUBMISSION_STATUS; - constructor(private applicationReviewService: ApplicationSubmissionReviewService, private router: Router) {} - - ngOnInit(): void { - this.$application.pipe(takeUntil(this.$destroy)).subscribe((application) => { - this.application = application; - }); - } - - ngOnDestroy(): void { - this.$destroy.next(); - this.$destroy.complete(); - } - - async onReview(fileId: string) { - if (this.application?.status.code === SUBMISSION_STATUS.SUBMITTED_TO_LG) { - const review = await this.applicationReviewService.startReview(fileId); - if (!review) { - return; - } - } - await this.router.navigateByUrl(`application/${fileId}/review`); - } + constructor() {} } diff --git a/portal-frontend/src/app/features/public/application/alc-review/decisions/decisions.component.html b/portal-frontend/src/app/features/public/application/alc-review/decisions/decisions.component.html index ee4d949dba..7657271cf1 100644 --- a/portal-frontend/src/app/features/public/application/alc-review/decisions/decisions.component.html +++ b/portal-frontend/src/app/features/public/application/alc-review/decisions/decisions.component.html @@ -1,5 +1,5 @@ -
-

Decision #{{ decisions.length - index }}

+
+

Decision #{{ applicationDecisions.length - index }}

Decision Date
@@ -15,7 +15,6 @@

Decision #{{ decisions.length - index }}

Decision Outcome
{{ decision.outcome.label }} {{ decision.isSubjectToConditions ? '- Subject to Conditions' : '' }}
-
Decision Document
diff --git a/portal-frontend/src/app/features/public/application/alc-review/decisions/decisions.component.spec.ts b/portal-frontend/src/app/features/public/application/alc-review/decisions/decisions.component.spec.ts index f56a7194b9..ce78e37c19 100644 --- a/portal-frontend/src/app/features/public/application/alc-review/decisions/decisions.component.spec.ts +++ b/portal-frontend/src/app/features/public/application/alc-review/decisions/decisions.component.spec.ts @@ -2,18 +2,18 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { createMock } from '@golevelup/ts-jest'; import { ApplicationDecisionService } from '../../../../../services/application-decision/application-decision.service'; -import { DecisionsComponent } from './decisions.component'; +import { PublicDecisionsComponent } from './decisions.component'; -describe('DecisionsComponent', () => { - let component: DecisionsComponent; - let fixture: ComponentFixture; +describe('PublicDecisionsComponent', () => { + let component: PublicDecisionsComponent; + let fixture: ComponentFixture; let mockDecisionService: ApplicationDecisionService; beforeEach(async () => { mockDecisionService = createMock(); await TestBed.configureTestingModule({ - declarations: [DecisionsComponent], + declarations: [PublicDecisionsComponent], providers: [ { provide: ApplicationDecisionService, @@ -22,7 +22,7 @@ describe('DecisionsComponent', () => { ], }).compileComponents(); - fixture = TestBed.createComponent(DecisionsComponent); + fixture = TestBed.createComponent(PublicDecisionsComponent); component = fixture.componentInstance; fixture.detectChanges(); }); diff --git a/portal-frontend/src/app/features/public/application/alc-review/decisions/decisions.component.ts b/portal-frontend/src/app/features/public/application/alc-review/decisions/decisions.component.ts index 1280cc0118..ebf506417a 100644 --- a/portal-frontend/src/app/features/public/application/alc-review/decisions/decisions.component.ts +++ b/portal-frontend/src/app/features/public/application/alc-review/decisions/decisions.component.ts @@ -3,37 +3,19 @@ import { ApplicationPortalDecisionDto } from '../../../../../services/applicatio import { ApplicationDecisionService } from '../../../../../services/application-decision/application-decision.service'; @Component({ - selector: 'app-decisions[fileNumber]', + selector: 'app-public-decisions', templateUrl: './decisions.component.html', styleUrls: ['./decisions.component.scss'], }) -export class DecisionsComponent implements OnInit, OnChanges { - @Input() fileNumber = ''; - decisions: ApplicationPortalDecisionDto[] = []; +export class PublicDecisionsComponent { + @Input() applicationDecisions: ApplicationPortalDecisionDto[] = []; constructor(private decisionService: ApplicationDecisionService) {} - ngOnInit(): void { - this.loadDecisions(); - } - - ngOnChanges(changes: SimpleChanges): void { - this.loadDecisions(); - } - async openFile(uuid: string) { const res = await this.decisionService.openFile(uuid); if (res) { window.open(res.url, '_blank'); } } - - private async loadDecisions() { - if (this.fileNumber) { - const decisions = await this.decisionService.getByFileId(this.fileNumber); - if (decisions) { - this.decisions = decisions; - } - } - } } diff --git a/portal-frontend/src/app/features/public/application/alc-review/submission-documents/submission-documents.component.spec.ts b/portal-frontend/src/app/features/public/application/alc-review/submission-documents/submission-documents.component.spec.ts index 09eb1292d3..a2f54298d3 100644 --- a/portal-frontend/src/app/features/public/application/alc-review/submission-documents/submission-documents.component.spec.ts +++ b/portal-frontend/src/app/features/public/application/alc-review/submission-documents/submission-documents.component.spec.ts @@ -1,30 +1,30 @@ import { NO_ERRORS_SCHEMA } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { createMock, DeepMocked } from '@golevelup/ts-jest'; -import { ApplicationDocumentService } from '../../../../../services/application-document/application-document.service'; +import { PublicService } from '../../../../../services/public/public.service'; -import { SubmissionDocumentsComponent } from './submission-documents.component'; +import { PublicSubmissionDocumentsComponent } from './submission-documents.component'; -describe('SubmissionDocumentsComponent', () => { - let component: SubmissionDocumentsComponent; - let fixture: ComponentFixture; - let mockAppDocService: DeepMocked; +describe('PublicSubmissionDocumentsComponent', () => { + let component: PublicSubmissionDocumentsComponent; + let fixture: ComponentFixture; + let mockPublicService: DeepMocked; beforeEach(async () => { - mockAppDocService = createMock(); + mockPublicService = createMock(); await TestBed.configureTestingModule({ - declarations: [SubmissionDocumentsComponent], + declarations: [PublicSubmissionDocumentsComponent], providers: [ { - provide: ApplicationDocumentService, - useValue: mockAppDocService, + provide: PublicService, + useValue: mockPublicService, }, ], schemas: [NO_ERRORS_SCHEMA], }).compileComponents(); - fixture = TestBed.createComponent(SubmissionDocumentsComponent); + fixture = TestBed.createComponent(PublicSubmissionDocumentsComponent); component = fixture.componentInstance; fixture.detectChanges(); }); diff --git a/portal-frontend/src/app/features/public/application/alc-review/submission-documents/submission-documents.component.ts b/portal-frontend/src/app/features/public/application/alc-review/submission-documents/submission-documents.component.ts index 027fbdbfea..0dc940477e 100644 --- a/portal-frontend/src/app/features/public/application/alc-review/submission-documents/submission-documents.component.ts +++ b/portal-frontend/src/app/features/public/application/alc-review/submission-documents/submission-documents.component.ts @@ -1,43 +1,42 @@ import { Component, Input, OnDestroy, OnInit, ViewChild } from '@angular/core'; import { MatSort } from '@angular/material/sort'; import { MatTableDataSource } from '@angular/material/table'; -import { BehaviorSubject, Subject, takeUntil } from 'rxjs'; -import { ApplicationDocumentDto } from '../../../../../services/application-document/application-document.dto'; -import { ApplicationDocumentService } from '../../../../../services/application-document/application-document.service'; +import { Subject } from 'rxjs'; +import { PublicApplicationSubmissionDto, PublicDocumentDto } from '../../../../../services/public/public.dto'; +import { PublicService } from '../../../../../services/public/public.service'; @Component({ selector: 'app-submission-documents', templateUrl: './submission-documents.component.html', styleUrls: ['./submission-documents.component.scss'], }) -export class SubmissionDocumentsComponent implements OnInit, OnDestroy { +export class PublicSubmissionDocumentsComponent implements OnInit, OnDestroy { private $destroy = new Subject(); displayedColumns: string[] = ['type', 'fileName', 'source', 'uploadedAt', 'actions']; - documents: ApplicationDocumentDto[] = []; + documents: PublicDocumentDto[] = []; - @Input() $applicationDocuments = new BehaviorSubject([]); + @Input() applicationDocuments!: PublicDocumentDto[]; + @Input() applicationSubmission!: PublicApplicationSubmissionDto; @ViewChild(MatSort) sort!: MatSort; - dataSource: MatTableDataSource = new MatTableDataSource(); + dataSource: MatTableDataSource = new MatTableDataSource(); - constructor(private applicationDocumentService: ApplicationDocumentService) {} + constructor(private publicService: PublicService) {} ngOnInit(): void { - this.$applicationDocuments.pipe(takeUntil(this.$destroy)).subscribe((documents) => { - this.dataSource = new MatTableDataSource(documents); - }); + this.dataSource = new MatTableDataSource(this.applicationDocuments); } async openFile(uuid: string) { - const res = await this.applicationDocumentService.openFile(uuid); + const res = await this.publicService.getApplicationFileUrl(this.applicationSubmission.fileNumber, uuid); if (res) { window.open(res.url, '_blank'); } } async downloadFile(uuid: string) { - const res = await this.applicationDocumentService.downloadFile(uuid); + const res = await this.publicService.getApplicationFileUrl(this.applicationSubmission.fileNumber, uuid); if (res) { const downloadLink = document.createElement('a'); downloadLink.href = res.url; diff --git a/portal-frontend/src/app/features/public/application/lfng-review/lfng-review.component.html b/portal-frontend/src/app/features/public/application/lfng-review/lfng-review.component.html index 2ae5a57c31..e3cd36db5a 100644 --- a/portal-frontend/src/app/features/public/application/lfng-review/lfng-review.component.html +++ b/portal-frontend/src/app/features/public/application/lfng-review/lfng-review.component.html @@ -1,70 +1,11 @@ -
+

Local/First Nation Gov Review

-
- - - - -
-
- infoThis section will update after the application is submitted. -
-
+
infoApplication not subject to Local/First Nation Government review.
-
- infoPending Local/First Nation Government review. -
-
-
Comment for Applicant
- {{ application.returnedComment }} - No comment added -
-
+

Contact Information

@@ -103,32 +44,17 @@

Contact Information

-
-
Phone Number
-
- {{ applicationReview.phoneNumber }} - -
-
-
-
Email
-
- {{ applicationReview.email }} - -
-
-
+

Plans & Bylaws: OCP

-
Is the application parcel(s) subject to a Local Government OCP designation?
+
+ Is the applicationSubmission parcel(s) subject to a Local Government OCP designation? +
- {{ - applicationReview.isOCPDesignation ? 'Yes' : 'No' - }} - + {{ applicationReview.isOCPDesignation ? 'Yes' : 'No' }}
@@ -156,16 +82,15 @@

Plans & Bylaws: OCP

-
+

Plans & Bylaws: Zoning

-
Is the application parcel(s) subject to a Local Government zoning designation?
+
+ Is the applicationSubmission parcel(s) subject to a Local Government zoning designation? +
- {{ - applicationReview.isSubjectToZoning ? 'Yes' : 'No' - }} - + {{ applicationReview.isSubjectToZoning ? 'Yes' : 'No' }}
@@ -203,81 +128,27 @@

Plans & Bylaws: Zoning

Resolution

-
- Please complete both Step 2 Plans & Bylaws: OCP and Step 3 Plans & Bylaws: Zoning to continue with this step. -
-
- By indicating that the parcel(s) is not subject to Local Government OCP or Zoning, - no authorizing resolution is required as per S. 25 (3) or S. 29 (4) of the ALC Act. - The only option available is to forward this application on to the ALC. +
+ Parcels not subject to OCP or Zoning do not require local government authorization
-
+
Resolution for Application to Proceed to the ALC
- {{ - applicationReview.isAuthorized ? 'Authorized' : 'Refuse to Authorize' - }} - + {{ applicationReview.isAuthorized ? 'Authorized' : 'Refuse to Authorize' }}
-
+

Attachments

-
-
- Please complete Step 2 Plans & Bylaws: OCP, Step 3 Plans & Bylaws: Zoning and Step 4 Resolution to continue - with this step. -
-
-
-
+
+
Resolution Document
- -
-
-
- Staff Report (optional) -
- - -
-
-
Other Attachments (optional):
-
diff --git a/portal-frontend/src/app/features/public/application/lfng-review/lfng-review.component.spec.ts b/portal-frontend/src/app/features/public/application/lfng-review/lfng-review.component.spec.ts index d1556cc200..a14d258152 100644 --- a/portal-frontend/src/app/features/public/application/lfng-review/lfng-review.component.spec.ts +++ b/portal-frontend/src/app/features/public/application/lfng-review/lfng-review.component.spec.ts @@ -1,52 +1,31 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { createMock, DeepMocked } from '@golevelup/ts-jest'; -import { BehaviorSubject } from 'rxjs'; -import { ApplicationDocumentDto } from '../../../../services/application-document/application-document.dto'; -import { ApplicationDocumentService } from '../../../../services/application-document/application-document.service'; -import { ApplicationSubmissionReviewDto } from '../../../../services/application-submission-review/application-submission-review.dto'; -import { ApplicationSubmissionReviewService } from '../../../../services/application-submission-review/application-submission-review.service'; -import { ApplicationSubmissionDetailedDto } from '../../../../services/application-submission/application-submission.dto'; -import { PdfGenerationService } from '../../../../services/pdf-generation/pdf-generation.service'; +import { PublicService } from '../../../../services/public/public.service'; -import { LfngReviewComponent } from './lfng-review.component'; +import { PublicLfngReviewComponent } from './lfng-review.component'; -describe('LfngReviewComponent', () => { - let component: LfngReviewComponent; - let fixture: ComponentFixture; +describe('PublicLfngReviewComponent', () => { + let component: PublicLfngReviewComponent; + let fixture: ComponentFixture; - let mockAppSubReviewService: DeepMocked; - let mockPdfGenerationService: DeepMocked; - let mockAppDocumentService: DeepMocked; + let mockPublicService: DeepMocked; beforeEach(async () => { - mockAppSubReviewService = createMock(); - mockPdfGenerationService = createMock(); - mockAppDocumentService = createMock(); - - mockAppSubReviewService.$applicationReview = new BehaviorSubject( - undefined - ); + mockPublicService = createMock(); await TestBed.configureTestingModule({ providers: [ { - provide: ApplicationSubmissionReviewService, - useValue: mockAppSubReviewService, - }, - { - provide: PdfGenerationService, - useValue: mockPdfGenerationService, - }, - { - provide: ApplicationDocumentService, - useValue: mockAppDocumentService, + provide: PublicService, + useValue: mockPublicService, }, ], - declarations: [LfngReviewComponent], + declarations: [PublicLfngReviewComponent], }).compileComponents(); - fixture = TestBed.createComponent(LfngReviewComponent); + fixture = TestBed.createComponent(PublicLfngReviewComponent); component = fixture.componentInstance; + component.applicationDocuments = []; fixture.detectChanges(); }); diff --git a/portal-frontend/src/app/features/public/application/lfng-review/lfng-review.component.ts b/portal-frontend/src/app/features/public/application/lfng-review/lfng-review.component.ts index e80935380e..e21492882c 100644 --- a/portal-frontend/src/app/features/public/application/lfng-review/lfng-review.component.ts +++ b/portal-frontend/src/app/features/public/application/lfng-review/lfng-review.component.ts @@ -1,131 +1,38 @@ -import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core'; -import { Router } from '@angular/router'; -import { BehaviorSubject, Subject, takeUntil } from 'rxjs'; -import { ApplicationDocumentDto } from '../../../../services/application-document/application-document.dto'; -import { ApplicationDocumentService } from '../../../../services/application-document/application-document.service'; -import { ApplicationSubmissionReviewDto } from '../../../../services/application-submission-review/application-submission-review.dto'; -import { ApplicationSubmissionReviewService } from '../../../../services/application-submission-review/application-submission-review.service'; +import { Component, Input, OnInit } from '@angular/core'; +import { SUBMISSION_STATUS } from '../../../../services/application-submission/application-submission.dto'; import { - ApplicationSubmissionDetailedDto, - SUBMISSION_STATUS, -} from '../../../../services/application-submission/application-submission.dto'; -import { PdfGenerationService } from '../../../../services/pdf-generation/pdf-generation.service'; -import { DOCUMENT_SOURCE, DOCUMENT_TYPE } from '../../../../shared/dto/document.dto'; + PublicApplicationSubmissionDto, + PublicApplicationSubmissionReviewDto, + PublicDocumentDto, +} from '../../../../services/public/public.dto'; +import { PublicService } from '../../../../services/public/public.service'; +import { DOCUMENT_TYPE } from '../../../../shared/dto/document.dto'; @Component({ - selector: 'app-lfng-review', + selector: 'app-public-lfng-review', templateUrl: './lfng-review.component.html', styleUrls: ['./lfng-review.component.scss'], }) -export class LfngReviewComponent implements OnInit, OnDestroy { - private $destroy = new Subject(); +export class PublicLfngReviewComponent implements OnInit { + @Input() applicationSubmission!: PublicApplicationSubmissionDto; + @Input() applicationDocuments!: PublicDocumentDto[]; + @Input() applicationReview: PublicApplicationSubmissionReviewDto | undefined; - @Input() $application = new BehaviorSubject(undefined); - @Input() $applicationDocuments = new BehaviorSubject([]); - - @Output() onCancel = new EventEmitter(); - - application: ApplicationSubmissionDetailedDto | undefined; - applicationReview: ApplicationSubmissionReviewDto | undefined; SUBMISSION_STATUS = SUBMISSION_STATUS; - staffReport: ApplicationDocumentDto[] = []; - resolutionDocument: ApplicationDocumentDto[] = []; - governmentOtherAttachments: ApplicationDocumentDto[] = []; - hasCompletedStepsBeforeResolution = false; - hasCompletedStepsBeforeDocuments = false; - submittedToAlcStatus = false; + resolutionDocument: PublicDocumentDto[] = []; - constructor( - private applicationReviewService: ApplicationSubmissionReviewService, - private pdfGenerationService: PdfGenerationService, - private applicationDocumentService: ApplicationDocumentService, - private router: Router - ) {} + constructor(private publicService: PublicService) {} ngOnInit(): void { - this.applicationReviewService.$applicationReview.pipe(takeUntil(this.$destroy)).subscribe((appReview) => { - if (appReview) { - this.applicationReview = appReview; - - this.hasCompletedStepsBeforeResolution = - appReview.isFirstNationGovernment || - (!appReview.isFirstNationGovernment && - appReview.isOCPDesignation !== null && - appReview.isSubjectToZoning !== null && - (appReview.isOCPDesignation === true || appReview.isSubjectToZoning === true)); - - this.hasCompletedStepsBeforeDocuments = - appReview.isFirstNationGovernment || - (appReview.isAuthorized !== null && - appReview.isOCPDesignation !== null && - appReview.isSubjectToZoning !== null) || - (appReview.isAuthorized === null && - appReview.isOCPDesignation === false && - appReview.isSubjectToZoning === false); - } - }); - - this.$application.pipe(takeUntil(this.$destroy)).subscribe((application) => { - this.application = application; - this.submittedToAlcStatus = !!this.application?.submissionStatuses.find( - (s) => s.statusTypeCode === SUBMISSION_STATUS.SUBMITTED_TO_ALC && !!s.effectiveDate - ); - this.loadReview(); - }); - - this.$applicationDocuments.subscribe((documents) => { - this.staffReport = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.STAFF_REPORT); - this.resolutionDocument = documents.filter( - (document) => document.type?.code === DOCUMENT_TYPE.RESOLUTION_DOCUMENT - ); - this.governmentOtherAttachments = documents.filter( - (document) => document.type?.code === DOCUMENT_TYPE.OTHER && document.source === DOCUMENT_SOURCE.LFNG - ); - }); - } - - async onDownloadReviewPdf(fileNumber: string | undefined) { - if (fileNumber) { - await this.pdfGenerationService.generateReview(fileNumber); - } - } - - async loadReview() { - if ( - this.application && - this.application.typeCode !== 'TURP' && - (this.submittedToAlcStatus || - (this.application.status.code === SUBMISSION_STATUS.IN_REVIEW_BY_LG && this.application.canReview)) - ) { - await this.applicationReviewService.getByFileId(this.application.fileNumber); - } else { - this.applicationReview = undefined; - } + this.resolutionDocument = this.applicationDocuments.filter( + (document) => document.type?.code === DOCUMENT_TYPE.RESOLUTION_DOCUMENT + ); } async openFile(uuid: string) { - const res = await this.applicationDocumentService.openFile(uuid); + const res = await this.publicService.getApplicationFileUrl(this.applicationSubmission.fileNumber, uuid); if (res) { window.open(res.url, '_blank'); } } - - async onReview(fileId: string) { - if (this.application?.status.code === SUBMISSION_STATUS.SUBMITTED_TO_LG) { - const review = await this.applicationReviewService.startReview(fileId); - if (!review) { - return; - } - } - await this.router.navigateByUrl(`application/${fileId}/review`); - } - - onCancelClicked(fileNumber: string) { - this.onCancel.emit(fileNumber); - } - - ngOnDestroy(): void { - this.$destroy.next(); - this.$destroy.complete(); - } } diff --git a/portal-frontend/src/app/features/public/application/public-application.component.html b/portal-frontend/src/app/features/public/application/public-application.component.html index 8bf92b73ce..addc35e61c 100644 --- a/portal-frontend/src/app/features/public/application/public-application.component.html +++ b/portal-frontend/src/app/features/public/application/public-application.component.html @@ -28,8 +28,9 @@

Application ID: {{ submission.fileNumber }}

-
-
//TODO
+
+ + +
-
//TODO
+
+ +
diff --git a/portal-frontend/src/app/features/public/application/public-application.component.ts b/portal-frontend/src/app/features/public/application/public-application.component.ts index f3700a1941..84cba66c20 100644 --- a/portal-frontend/src/app/features/public/application/public-application.component.ts +++ b/portal-frontend/src/app/features/public/application/public-application.component.ts @@ -1,10 +1,14 @@ import { Component, OnDestroy, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { Subject, takeUntil } from 'rxjs'; -import { ApplicationDocumentDto } from '../../../services/application-document/application-document.dto'; -import { ApplicationParcelDto } from '../../../services/application-parcel/application-parcel.dto'; +import { ApplicationPortalDecisionDto } from '../../../services/application-decision/application-decision.dto'; import { SUBMISSION_STATUS } from '../../../services/application-submission/application-submission.dto'; -import { PublicApplicationSubmissionDto } from '../../../services/public/public.dto'; +import { + PublicApplicationParcelDto, + PublicApplicationSubmissionDto, + PublicApplicationSubmissionReviewDto, + PublicDocumentDto, +} from '../../../services/public/public.dto'; import { PublicService } from '../../../services/public/public.service'; @Component({ @@ -18,8 +22,10 @@ export class PublicApplicationComponent implements OnInit, OnDestroy { SUBMISSION_STATUS = SUBMISSION_STATUS; submission: PublicApplicationSubmissionDto | undefined; - documents: ApplicationDocumentDto[] = []; - parcels: ApplicationParcelDto[] = []; + review: PublicApplicationSubmissionReviewDto | undefined; + documents: PublicDocumentDto[] = []; + parcels: PublicApplicationParcelDto[] = []; + decisions: ApplicationPortalDecisionDto[] = []; constructor(private publicService: PublicService, private route: ActivatedRoute) {} @@ -35,11 +41,13 @@ export class PublicApplicationComponent implements OnInit, OnDestroy { private async loadApplication(fileId: string) { const res = await this.publicService.getApplication(fileId); if (res) { - const { submission, documents, parcels } = res; + const { submission, documents, parcels, review, decisions } = res; this.submission = submission; this.documents = documents; this.parcels = parcels; + this.review = review; + this.decisions = decisions; } } diff --git a/portal-frontend/src/app/features/public/application/submission/excl-details/excl-details.component.ts b/portal-frontend/src/app/features/public/application/submission/excl-details/excl-details.component.ts index cc7b23fc89..43a3f4c95e 100644 --- a/portal-frontend/src/app/features/public/application/submission/excl-details/excl-details.component.ts +++ b/portal-frontend/src/app/features/public/application/submission/excl-details/excl-details.component.ts @@ -1,8 +1,6 @@ import { Component, Input } from '@angular/core'; import { Router } from '@angular/router'; -import { ApplicationDocumentDto } from '../../../../../services/application-document/application-document.dto'; -import { ApplicationDocumentService } from '../../../../../services/application-document/application-document.service'; -import { PublicApplicationSubmissionDto } from '../../../../../services/public/public.dto'; +import { PublicApplicationSubmissionDto, PublicDocumentDto } from '../../../../../services/public/public.dto'; import { PublicService } from '../../../../../services/public/public.service'; import { DOCUMENT_TYPE } from '../../../../../shared/dto/document.dto'; @@ -14,15 +12,15 @@ import { DOCUMENT_TYPE } from '../../../../../shared/dto/document.dto'; export class ExclDetailsComponent { @Input() applicationSubmission!: PublicApplicationSubmissionDto; - @Input() set applicationDocuments(documents: ApplicationDocumentDto[]) { + @Input() set applicationDocuments(documents: PublicDocumentDto[]) { this.proposalMap = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.PROPOSAL_MAP); this.reportOfPublicHearing = documents.filter( (document) => document.type?.code === DOCUMENT_TYPE.REPORT_OF_PUBLIC_HEARING ); } - proposalMap: ApplicationDocumentDto[] = []; - reportOfPublicHearing: ApplicationDocumentDto[] = []; + proposalMap: PublicDocumentDto[] = []; + reportOfPublicHearing: PublicDocumentDto[] = []; constructor(private router: Router, private publicService: PublicService) {} diff --git a/portal-frontend/src/app/features/public/application/submission/incl-details/incl-details.component.ts b/portal-frontend/src/app/features/public/application/submission/incl-details/incl-details.component.ts index 53e325f10f..e08695999c 100644 --- a/portal-frontend/src/app/features/public/application/submission/incl-details/incl-details.component.ts +++ b/portal-frontend/src/app/features/public/application/submission/incl-details/incl-details.component.ts @@ -1,8 +1,6 @@ import { Component, Input } from '@angular/core'; import { Router } from '@angular/router'; -import { ApplicationDocumentDto } from '../../../../../services/application-document/application-document.dto'; -import { ApplicationDocumentService } from '../../../../../services/application-document/application-document.service'; -import { PublicApplicationSubmissionDto } from '../../../../../services/public/public.dto'; +import { PublicApplicationSubmissionDto, PublicDocumentDto } from '../../../../../services/public/public.dto'; import { PublicService } from '../../../../../services/public/public.service'; import { DOCUMENT_TYPE } from '../../../../../shared/dto/document.dto'; @@ -12,12 +10,12 @@ import { DOCUMENT_TYPE } from '../../../../../shared/dto/document.dto'; styleUrls: ['./incl-details.component.scss'], }) export class InclDetailsComponent { - proposalMap: ApplicationDocumentDto[] = []; - reportOfPublicHearing: ApplicationDocumentDto[] = []; + proposalMap: PublicDocumentDto[] = []; + reportOfPublicHearing: PublicDocumentDto[] = []; @Input() applicationSubmission!: PublicApplicationSubmissionDto; - @Input() set applicationDocuments(documents: ApplicationDocumentDto[]) { + @Input() set applicationDocuments(documents: PublicDocumentDto[]) { this.proposalMap = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.PROPOSAL_MAP); this.reportOfPublicHearing = documents.filter( (document) => document.type?.code === DOCUMENT_TYPE.REPORT_OF_PUBLIC_HEARING diff --git a/portal-frontend/src/app/features/public/application/submission/naru-details/naru-details.component.ts b/portal-frontend/src/app/features/public/application/submission/naru-details/naru-details.component.ts index e593aff636..f4f702d73c 100644 --- a/portal-frontend/src/app/features/public/application/submission/naru-details/naru-details.component.ts +++ b/portal-frontend/src/app/features/public/application/submission/naru-details/naru-details.component.ts @@ -1,8 +1,6 @@ import { Component, Input } from '@angular/core'; import { Router } from '@angular/router'; -import { ApplicationDocumentDto } from '../../../../../services/application-document/application-document.dto'; -import { ApplicationDocumentService } from '../../../../../services/application-document/application-document.service'; -import { PublicApplicationSubmissionDto } from '../../../../../services/public/public.dto'; +import { PublicApplicationSubmissionDto, PublicDocumentDto } from '../../../../../services/public/public.dto'; import { PublicService } from '../../../../../services/public/public.service'; import { DOCUMENT_TYPE } from '../../../../../shared/dto/document.dto'; @@ -12,10 +10,10 @@ import { DOCUMENT_TYPE } from '../../../../../shared/dto/document.dto'; styleUrls: ['./naru-details.component.scss'], }) export class NaruDetailsComponent { - proposalMap: ApplicationDocumentDto[] = []; + proposalMap: PublicDocumentDto[] = []; @Input() applicationSubmission!: PublicApplicationSubmissionDto; - @Input() set applicationDocuments(documents: ApplicationDocumentDto[]) { + @Input() set applicationDocuments(documents: PublicDocumentDto[]) { this.proposalMap = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.PROPOSAL_MAP); } diff --git a/portal-frontend/src/app/features/public/application/submission/nfu-details/nfu-details.component.ts b/portal-frontend/src/app/features/public/application/submission/nfu-details/nfu-details.component.ts index d0642d7090..27ff3c3d23 100644 --- a/portal-frontend/src/app/features/public/application/submission/nfu-details/nfu-details.component.ts +++ b/portal-frontend/src/app/features/public/application/submission/nfu-details/nfu-details.component.ts @@ -1,8 +1,6 @@ import { Component, Input } from '@angular/core'; import { Router } from '@angular/router'; -import { ApplicationDocumentDto } from '../../../../../services/application-document/application-document.dto'; -import { ApplicationDocumentService } from '../../../../../services/application-document/application-document.service'; -import { PublicApplicationSubmissionDto } from '../../../../../services/public/public.dto'; +import { PublicApplicationSubmissionDto, PublicDocumentDto } from '../../../../../services/public/public.dto'; import { PublicService } from '../../../../../services/public/public.service'; import { DOCUMENT_TYPE } from '../../../../../shared/dto/document.dto'; @@ -14,11 +12,11 @@ import { DOCUMENT_TYPE } from '../../../../../shared/dto/document.dto'; export class NfuDetailsComponent { @Input() applicationSubmission!: PublicApplicationSubmissionDto; - @Input() set applicationDocuments(documents: ApplicationDocumentDto[]) { + @Input() set applicationDocuments(documents: PublicDocumentDto[]) { this.proposalMap = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.PROPOSAL_MAP); } - proposalMap: ApplicationDocumentDto[] = []; + proposalMap: PublicDocumentDto[] = []; constructor(private router: Router, private publicService: PublicService) {} diff --git a/portal-frontend/src/app/features/public/application/submission/parcel/parcel.component.scss b/portal-frontend/src/app/features/public/application/submission/parcel/parcel.component.scss index a706f903ba..81d88321d1 100644 --- a/portal-frontend/src/app/features/public/application/submission/parcel/parcel.component.scss +++ b/portal-frontend/src/app/features/public/application/submission/parcel/parcel.component.scss @@ -18,20 +18,6 @@ .full-width { grid-column: 1/3; } - - .edit-button { - grid-column: 1/3; - } - - @media screen and (min-width: $tabletBreakpoint) { - .full-width { - grid-column: 1/5; - } - - .edit-button { - grid-column: 1/5; - } - } } .crown-land { diff --git a/portal-frontend/src/app/features/public/application/submission/parcel/parcel.component.ts b/portal-frontend/src/app/features/public/application/submission/parcel/parcel.component.ts index 0a4a1d2da5..9e17cad331 100644 --- a/portal-frontend/src/app/features/public/application/submission/parcel/parcel.component.ts +++ b/portal-frontend/src/app/features/public/application/submission/parcel/parcel.component.ts @@ -1,10 +1,7 @@ import { Component, Input } from '@angular/core'; import { Subject } from 'rxjs'; -import { - ApplicationParcelDto, - PARCEL_OWNERSHIP_TYPE, -} from '../../../../../services/application-parcel/application-parcel.dto'; -import { PublicApplicationSubmissionDto } from '../../../../../services/public/public.dto'; +import { PARCEL_OWNERSHIP_TYPE } from '../../../../../services/application-parcel/application-parcel.dto'; +import { PublicApplicationParcelDto, PublicApplicationSubmissionDto } from '../../../../../services/public/public.dto'; @Component({ selector: 'app-parcel', @@ -15,7 +12,7 @@ export class ParcelComponent { $destroy = new Subject(); @Input() applicationSubmission!: PublicApplicationSubmissionDto; - @Input() parcels: ApplicationParcelDto[] = []; + @Input() parcels: PublicApplicationParcelDto[] = []; PARCEL_OWNERSHIP_TYPES = PARCEL_OWNERSHIP_TYPE; pageTitle: string = 'Identify Parcel(s) Under Application'; diff --git a/portal-frontend/src/app/features/public/application/submission/pfrs-details/pfrs-details.component.ts b/portal-frontend/src/app/features/public/application/submission/pfrs-details/pfrs-details.component.ts index da1bd6a17b..f529357962 100644 --- a/portal-frontend/src/app/features/public/application/submission/pfrs-details/pfrs-details.component.ts +++ b/portal-frontend/src/app/features/public/application/submission/pfrs-details/pfrs-details.component.ts @@ -1,11 +1,8 @@ import { Component, Input } from '@angular/core'; import { Router } from '@angular/router'; -import { ApplicationDocumentDto } from '../../../../../services/application-document/application-document.dto'; -import { ApplicationDocumentService } from '../../../../../services/application-document/application-document.service'; -import { PublicApplicationSubmissionDto } from '../../../../../services/public/public.dto'; +import { PublicApplicationSubmissionDto, PublicDocumentDto } from '../../../../../services/public/public.dto'; import { PublicService } from '../../../../../services/public/public.service'; import { DOCUMENT_TYPE } from '../../../../../shared/dto/document.dto'; -import { PublicApplicationComponent } from '../../public-application.component'; @Component({ selector: 'app-pfrs-details[applicationSubmission]', @@ -15,13 +12,13 @@ import { PublicApplicationComponent } from '../../public-application.component'; export class PfrsDetailsComponent { @Input() applicationSubmission!: PublicApplicationSubmissionDto; - @Input() set applicationDocuments(documents: ApplicationDocumentDto[]) { + @Input() set applicationDocuments(documents: PublicDocumentDto[]) { this.crossSections = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.CROSS_SECTIONS); this.proposalMap = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.PROPOSAL_MAP); } - crossSections: ApplicationDocumentDto[] = []; - proposalMap: ApplicationDocumentDto[] = []; + crossSections: PublicDocumentDto[] = []; + proposalMap: PublicDocumentDto[] = []; constructor(private router: Router, private publicService: PublicService) {} diff --git a/portal-frontend/src/app/features/public/application/submission/pofo-details/pofo-details.component.ts b/portal-frontend/src/app/features/public/application/submission/pofo-details/pofo-details.component.ts index 11c3f8cef4..9b48d576c5 100644 --- a/portal-frontend/src/app/features/public/application/submission/pofo-details/pofo-details.component.ts +++ b/portal-frontend/src/app/features/public/application/submission/pofo-details/pofo-details.component.ts @@ -1,8 +1,6 @@ import { Component, Input } from '@angular/core'; import { Router } from '@angular/router'; -import { ApplicationDocumentDto } from '../../../../../services/application-document/application-document.dto'; -import { ApplicationDocumentService } from '../../../../../services/application-document/application-document.service'; -import { PublicApplicationSubmissionDto } from '../../../../../services/public/public.dto'; +import { PublicApplicationSubmissionDto, PublicDocumentDto } from '../../../../../services/public/public.dto'; import { PublicService } from '../../../../../services/public/public.service'; import { DOCUMENT_TYPE } from '../../../../../shared/dto/document.dto'; @@ -14,13 +12,13 @@ import { DOCUMENT_TYPE } from '../../../../../shared/dto/document.dto'; export class PofoDetailsComponent { @Input() applicationSubmission!: PublicApplicationSubmissionDto; - @Input() set applicationDocuments(documents: ApplicationDocumentDto[]) { + @Input() set applicationDocuments(documents: PublicDocumentDto[]) { this.crossSections = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.CROSS_SECTIONS); this.proposalMap = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.PROPOSAL_MAP); } - crossSections: ApplicationDocumentDto[] = []; - proposalMap: ApplicationDocumentDto[] = []; + crossSections: PublicDocumentDto[] = []; + proposalMap: PublicDocumentDto[] = []; constructor(private router: Router, private publicService: PublicService) {} diff --git a/portal-frontend/src/app/features/public/application/submission/roso-details/roso-details.component.ts b/portal-frontend/src/app/features/public/application/submission/roso-details/roso-details.component.ts index 9ab2fc15d9..44bb4f91d5 100644 --- a/portal-frontend/src/app/features/public/application/submission/roso-details/roso-details.component.ts +++ b/portal-frontend/src/app/features/public/application/submission/roso-details/roso-details.component.ts @@ -1,8 +1,6 @@ import { Component, Input } from '@angular/core'; import { Router } from '@angular/router'; -import { ApplicationDocumentDto } from '../../../../../services/application-document/application-document.dto'; -import { ApplicationDocumentService } from '../../../../../services/application-document/application-document.service'; -import { PublicApplicationSubmissionDto } from '../../../../../services/public/public.dto'; +import { PublicApplicationSubmissionDto, PublicDocumentDto } from '../../../../../services/public/public.dto'; import { PublicService } from '../../../../../services/public/public.service'; import { DOCUMENT_TYPE } from '../../../../../shared/dto/document.dto'; @@ -14,13 +12,13 @@ import { DOCUMENT_TYPE } from '../../../../../shared/dto/document.dto'; export class RosoDetailsComponent { @Input() applicationSubmission!: PublicApplicationSubmissionDto; - @Input() set applicationDocuments(documents: ApplicationDocumentDto[]) { + @Input() set applicationDocuments(documents: PublicDocumentDto[]) { this.crossSections = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.CROSS_SECTIONS); this.proposalMap = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.PROPOSAL_MAP); } - crossSections: ApplicationDocumentDto[] = []; - proposalMap: ApplicationDocumentDto[] = []; + crossSections: PublicDocumentDto[] = []; + proposalMap: PublicDocumentDto[] = []; constructor(private router: Router, private publicService: PublicService) {} diff --git a/portal-frontend/src/app/features/public/application/submission/subd-details/subd-details.component.ts b/portal-frontend/src/app/features/public/application/submission/subd-details/subd-details.component.ts index a2f5720ac4..e9bf08d879 100644 --- a/portal-frontend/src/app/features/public/application/submission/subd-details/subd-details.component.ts +++ b/portal-frontend/src/app/features/public/application/submission/subd-details/subd-details.component.ts @@ -1,8 +1,6 @@ import { Component, Input } from '@angular/core'; import { Router } from '@angular/router'; -import { ApplicationDocumentDto } from '../../../../../services/application-document/application-document.dto'; -import { ApplicationDocumentService } from '../../../../../services/application-document/application-document.service'; -import { PublicApplicationSubmissionDto } from '../../../../../services/public/public.dto'; +import { PublicApplicationSubmissionDto, PublicDocumentDto } from '../../../../../services/public/public.dto'; import { PublicService } from '../../../../../services/public/public.service'; import { DOCUMENT_TYPE } from '../../../../../shared/dto/document.dto'; @@ -14,11 +12,11 @@ import { DOCUMENT_TYPE } from '../../../../../shared/dto/document.dto'; export class SubdDetailsComponent { @Input() applicationSubmission!: PublicApplicationSubmissionDto; - @Input() set applicationDocuments(documents: ApplicationDocumentDto[]) { + @Input() set applicationDocuments(documents: PublicDocumentDto[]) { this.proposalMap = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.PROPOSAL_MAP); } - proposalMap: ApplicationDocumentDto[] = []; + proposalMap: PublicDocumentDto[] = []; constructor(private router: Router, private publicService: PublicService) {} diff --git a/portal-frontend/src/app/features/public/application/submission/submission-details.component.ts b/portal-frontend/src/app/features/public/application/submission/submission-details.component.ts index c98f76888a..5849b23130 100644 --- a/portal-frontend/src/app/features/public/application/submission/submission-details.component.ts +++ b/portal-frontend/src/app/features/public/application/submission/submission-details.component.ts @@ -1,11 +1,15 @@ import { Component, Input, OnDestroy, OnInit } from '@angular/core'; import { Subject } from 'rxjs'; -import { ApplicationDocumentDto } from '../../../../services/application-document/application-document.dto'; import { ApplicationDocumentService } from '../../../../services/application-document/application-document.service'; -import { ApplicationParcelDto, PARCEL_TYPE } from '../../../../services/application-parcel/application-parcel.dto'; +import { PARCEL_TYPE } from '../../../../services/application-parcel/application-parcel.dto'; import { LocalGovernmentDto } from '../../../../services/code/code.dto'; import { CodeService } from '../../../../services/code/code.service'; -import { PublicApplicationSubmissionDto, PublicOwnerDto } from '../../../../services/public/public.dto'; +import { + PublicApplicationParcelDto, + PublicApplicationSubmissionDto, + PublicDocumentDto, + PublicOwnerDto, +} from '../../../../services/public/public.dto'; import { OWNER_TYPE } from '../../../../shared/dto/owner.dto'; @Component({ @@ -17,8 +21,8 @@ export class SubmissionDetailsComponent implements OnInit, OnDestroy { $destroy = new Subject(); @Input() applicationSubmission!: PublicApplicationSubmissionDto; - @Input() applicationDocuments: ApplicationDocumentDto[] = []; - @Input() applicationParcels: ApplicationParcelDto[] = []; + @Input() applicationDocuments: PublicDocumentDto[] = []; + @Input() applicationParcels: PublicApplicationParcelDto[] = []; parcelType = PARCEL_TYPE; primaryContact: PublicOwnerDto | undefined; diff --git a/portal-frontend/src/app/features/public/application/submission/tur-details/tur-details.component.ts b/portal-frontend/src/app/features/public/application/submission/tur-details/tur-details.component.ts index a448a06fae..11ff6e4162 100644 --- a/portal-frontend/src/app/features/public/application/submission/tur-details/tur-details.component.ts +++ b/portal-frontend/src/app/features/public/application/submission/tur-details/tur-details.component.ts @@ -1,7 +1,6 @@ import { Component, Input } from '@angular/core'; import { Router } from '@angular/router'; -import { ApplicationDocumentDto } from '../../../../../services/application-document/application-document.dto'; -import { PublicApplicationSubmissionDto } from '../../../../../services/public/public.dto'; +import { PublicApplicationSubmissionDto, PublicDocumentDto } from '../../../../../services/public/public.dto'; import { PublicService } from '../../../../../services/public/public.service'; import { DOCUMENT_TYPE } from '../../../../../shared/dto/document.dto'; @@ -12,11 +11,11 @@ import { DOCUMENT_TYPE } from '../../../../../shared/dto/document.dto'; }) export class TurDetailsComponent { @Input() applicationSubmission!: PublicApplicationSubmissionDto; - @Input() set applicationDocuments(documents: ApplicationDocumentDto[]) { + @Input() set applicationDocuments(documents: PublicDocumentDto[]) { this.proposalMap = documents.filter((document) => document.type?.code === DOCUMENT_TYPE.PROPOSAL_MAP); } - proposalMap: ApplicationDocumentDto[] = []; + proposalMap: PublicDocumentDto[] = []; constructor(private router: Router, private publicService: PublicService) {} diff --git a/portal-frontend/src/app/features/public/public.module.ts b/portal-frontend/src/app/features/public/public.module.ts index 57b0fa785e..d4df75e0df 100644 --- a/portal-frontend/src/app/features/public/public.module.ts +++ b/portal-frontend/src/app/features/public/public.module.ts @@ -6,6 +6,10 @@ import { MatSortModule } from '@angular/material/sort'; import { MatTreeModule } from '@angular/material/tree'; import { RouterModule, Routes } from '@angular/router'; import { SharedModule } from '../../shared/shared.module'; +import { PublicAlcReviewComponent } from './application/alc-review/alc-review.component'; +import { PublicDecisionsComponent } from './application/alc-review/decisions/decisions.component'; +import { PublicSubmissionDocumentsComponent } from './application/alc-review/submission-documents/submission-documents.component'; +import { PublicLfngReviewComponent } from './application/lfng-review/lfng-review.component'; import { PublicApplicationComponent } from './application/public-application.component'; import { SubmissionDetailsModule } from './application/submission/submission-details.module'; import { ApplicationSearchTableComponent } from './search/application-search-table/application-search-table.component'; @@ -35,6 +39,10 @@ const routes: Routes = [ FileTypeFilterDropDownComponent, SearchListComponent, PublicApplicationComponent, + PublicLfngReviewComponent, + PublicAlcReviewComponent, + PublicSubmissionDocumentsComponent, + PublicDecisionsComponent, ], imports: [ CommonModule, diff --git a/portal-frontend/src/app/services/public/public.dto.ts b/portal-frontend/src/app/services/public/public.dto.ts index 5c49d34add..ba6f3031d3 100644 --- a/portal-frontend/src/app/services/public/public.dto.ts +++ b/portal-frontend/src/app/services/public/public.dto.ts @@ -1,6 +1,7 @@ +import { BaseCodeDto } from '../../shared/dto/base.dto'; +import { DocumentTypeDto } from '../../shared/dto/document.dto'; import { OwnerTypeDto } from '../../shared/dto/owner.dto'; -import { ApplicationDocumentDto } from '../application-document/application-document.dto'; -import { ApplicationParcelDto } from '../application-parcel/application-parcel.dto'; +import { ApplicationPortalDecisionDto } from '../application-decision/application-decision.dto'; import { ApplicationStatusDto, NaruSubtypeDto, @@ -9,8 +10,10 @@ import { export interface GetPublicApplicationResponseDto { submission: PublicApplicationSubmissionDto; - parcels: ApplicationParcelDto[]; - documents: ApplicationDocumentDto[]; + parcels: PublicApplicationParcelDto[]; + documents: PublicDocumentDto[]; + review?: PublicApplicationSubmissionReviewDto; + decisions: ApplicationPortalDecisionDto[]; } export interface PublicOwnerDto { @@ -131,3 +134,50 @@ export interface PublicApplicationSubmissionDto { exclShareGovernmentBorders: boolean | null; inclGovernmentOwnsAllParcels?: boolean | null; } + +export interface PublicApplicationSubmissionReviewDto { + applicationFileNumber: string; + localGovernmentFileNumber: string | null; + firstName: string | null; + lastName: string | null; + position: string | null; + department: string | null; + isOCPDesignation: boolean | null; + OCPBylawName: string | null; + OCPDesignation: string | null; + OCPConsistent: boolean | null; + isSubjectToZoning: boolean | null; + zoningBylawName: string | null; + zoningDesignation: string | null; + zoningMinimumLotSize: string | null; + isZoningConsistent: boolean | null; + isAuthorized: boolean | null; +} + +export interface PublicApplicationParcelDto { + uuid: string; + pid?: string | null; + pin?: string | null; + legalDescription?: string | null; + civicAddress?: string | null; + mapAreaHectares?: number | null; + purchasedDate?: number | null; + isFarm?: boolean | null; + ownershipTypeCode?: string | null; + crownLandOwnerType?: string | null; + ownershipType?: BaseCodeDto; + parcelType: string; + alrArea: number | null; + owners: PublicOwnerDto[]; +} + +export interface PublicDocumentDto { + description?: string; + uuid: string; + type?: DocumentTypeDto; + documentUuid: string; + fileName: string; + fileSize?: number; + mimeType: string; + uploadedAt: number; +} diff --git a/services/apps/alcs/src/common/automapper/public.automapper.profile.ts b/services/apps/alcs/src/common/automapper/public.automapper.profile.ts index c463e68068..d1b49b784b 100644 --- a/services/apps/alcs/src/common/automapper/public.automapper.profile.ts +++ b/services/apps/alcs/src/common/automapper/public.automapper.profile.ts @@ -1,12 +1,25 @@ import { createMap, forMember, mapFrom, Mapper } from '@automapper/core'; import { AutomapperProfile, InjectMapper } from '@automapper/nestjs'; import { Injectable } from '@nestjs/common'; +import { ApplicationDocumentDto } from '../../alcs/application/application-document/application-document.dto'; +import { ApplicationDocument } from '../../alcs/application/application-document/application-document.entity'; +import { ApplicationSubmissionReview } from '../../portal/application-submission-review/application-submission-review.entity'; +import { ApplicationOwnerDto } from '../../portal/application-submission/application-owner/application-owner.dto'; import { ApplicationOwner } from '../../portal/application-submission/application-owner/application-owner.entity'; +import { ApplicationParcelDto } from '../../portal/application-submission/application-parcel/application-parcel.dto'; +import { ApplicationParcel } from '../../portal/application-submission/application-parcel/application-parcel.entity'; import { ApplicationSubmission } from '../../portal/application-submission/application-submission.entity'; import { + PublicApplicationParcelDto, PublicApplicationSubmissionDto, + PublicApplicationSubmissionReviewDto, + PublicDocumentDto, PublicOwnerDto, } from '../../portal/public/public.dto'; +import { + ParcelOwnershipType, + ParcelOwnershipTypeDto, +} from '../entities/parcel-ownership-type/parcel-ownership-type.entity'; @Injectable() export class PublicAutomapperProfile extends AutomapperProfile { @@ -33,7 +46,90 @@ export class PublicAutomapperProfile extends AutomapperProfile { }), ), ); - createMap(mapper, ApplicationOwner, PublicOwnerDto); + + createMap( + mapper, + ApplicationOwner, + PublicOwnerDto, + forMember( + (pd) => pd.displayName, + mapFrom((p) => `${p.firstName} ${p.lastName}`), + ), + ); + + createMap( + mapper, + ApplicationParcel, + PublicApplicationParcelDto, + forMember( + (pd) => pd.ownershipTypeCode, + mapFrom((p) => p.ownershipTypeCode), + ), + forMember( + (pd) => pd.purchasedDate, + mapFrom((p) => p.purchasedDate?.getTime()), + ), + forMember( + (p) => p.owners, + mapFrom((pd) => { + if (pd.owners) { + return this.mapper.mapArray( + pd.owners, + ApplicationOwner, + PublicOwnerDto, + ); + } else { + return []; + } + }), + ), + forMember( + (p) => p.ownershipType, + mapFrom((pd) => { + if (pd.ownershipType) { + return this.mapper.map( + pd.ownershipType, + ParcelOwnershipType, + ParcelOwnershipTypeDto, + ); + } else { + return undefined; + } + }), + ), + ); + + createMap( + mapper, + ApplicationSubmissionReview, + PublicApplicationSubmissionReviewDto, + ); + + createMap( + mapper, + ApplicationDocument, + PublicDocumentDto, + forMember( + (a) => a.mimeType, + mapFrom((ad) => ad.document.mimeType), + ), + forMember( + (a) => a.fileName, + mapFrom((ad) => ad.document.fileName), + ), + forMember( + (a) => a.fileSize, + mapFrom((ad) => ad.document.fileSize), + ), + forMember( + (a) => a.uploadedAt, + mapFrom((ad) => ad.document.uploadedAt.getTime()), + ), + forMember( + (a) => a.documentUuid, + mapFrom((ad) => ad.document.uuid), + ), + ); }; } } diff --git a/services/apps/alcs/src/portal/application-submission-review/application-submission-review.service.ts b/services/apps/alcs/src/portal/application-submission-review/application-submission-review.service.ts index 93c25f7da2..512fa2d345 100644 --- a/services/apps/alcs/src/portal/application-submission-review/application-submission-review.service.ts +++ b/services/apps/alcs/src/portal/application-submission-review/application-submission-review.service.ts @@ -256,6 +256,14 @@ export class ApplicationSubmissionReviewService { }; } + getForPublicReview(fileNumber: string) { + return this.applicationSubmissionReviewRepository.findOne({ + where: { + applicationFileNumber: fileNumber, + }, + }); + } + async delete(applicationReview: ApplicationSubmissionReview) { await this.applicationSubmissionReviewRepository.remove(applicationReview); } diff --git a/services/apps/alcs/src/portal/application-submission/application-parcel/application-parcel.dto.ts b/services/apps/alcs/src/portal/application-submission/application-parcel/application-parcel.dto.ts index b00a1195fb..f52e51f788 100644 --- a/services/apps/alcs/src/portal/application-submission/application-parcel/application-parcel.dto.ts +++ b/services/apps/alcs/src/portal/application-submission/application-parcel/application-parcel.dto.ts @@ -7,7 +7,6 @@ import { IsOptional, IsString, } from 'class-validator'; -import { Column } from 'typeorm'; import { ApplicationDocumentDto } from '../../../alcs/application/application-document/application-document.dto'; import { BaseCodeDto } from '../../../common/dtos/base.dto'; import { ApplicationOwnerDetailedDto } from '../application-owner/application-owner.dto'; diff --git a/services/apps/alcs/src/portal/public/public-application.service.spec.ts b/services/apps/alcs/src/portal/public/public-application.service.spec.ts new file mode 100644 index 0000000000..d82e030817 --- /dev/null +++ b/services/apps/alcs/src/portal/public/public-application.service.spec.ts @@ -0,0 +1,150 @@ +import { ServiceNotFoundException } from '@app/common/exceptions/base.exception'; +import { classes } from '@automapper/classes'; +import { AutomapperModule } from '@automapper/nestjs'; +import { createMock, DeepMocked } from '@golevelup/nestjs-testing'; +import { Test, TestingModule } from '@nestjs/testing'; +import { ApplicationDecisionV2Service } from '../../alcs/application-decision/application-decision-v2/application-decision/application-decision-v2.service'; +import { + ApplicationDocument, + VISIBILITY_FLAG, +} from '../../alcs/application/application-document/application-document.entity'; +import { ApplicationDocumentService } from '../../alcs/application/application-document/application-document.service'; +import { ApplicationSubmissionToSubmissionStatus } from '../../alcs/application/application-submission-status/submission-status.entity'; +import { Application } from '../../alcs/application/application.entity'; +import { ApplicationService } from '../../alcs/application/application.service'; +import { PublicAutomapperProfile } from '../../common/automapper/public.automapper.profile'; +import { ApplicationSubmissionReview } from '../application-submission-review/application-submission-review.entity'; +import { ApplicationSubmissionReviewService } from '../application-submission-review/application-submission-review.service'; +import { ApplicationParcelService } from '../application-submission/application-parcel/application-parcel.service'; +import { ApplicationSubmission } from '../application-submission/application-submission.entity'; +import { ApplicationSubmissionService } from '../application-submission/application-submission.service'; +import { PublicApplicationService } from './public-application.service'; + +describe('PublicApplicationService', () => { + let service: PublicApplicationService; + let mockAppService: DeepMocked; + let mockAppSubService: DeepMocked; + let mockAppParcelService: DeepMocked; + let mockAppDocService: DeepMocked; + let mockAppReviewService: DeepMocked; + let mockAppDecService: DeepMocked; + + beforeEach(async () => { + mockAppService = createMock(); + mockAppSubService = createMock(); + mockAppParcelService = createMock(); + mockAppDocService = createMock(); + mockAppReviewService = createMock(); + mockAppDecService = createMock(); + + const module: TestingModule = await Test.createTestingModule({ + imports: [ + AutomapperModule.forRoot({ + strategyInitializer: classes(), + }), + ], + providers: [ + PublicApplicationService, + PublicAutomapperProfile, + { + provide: ApplicationService, + useValue: mockAppService, + }, + { + provide: ApplicationSubmissionService, + useValue: mockAppSubService, + }, + { + provide: ApplicationParcelService, + useValue: mockAppParcelService, + }, + { + provide: ApplicationDocumentService, + useValue: mockAppDocService, + }, + { + provide: ApplicationSubmissionReviewService, + useValue: mockAppReviewService, + }, + { + provide: ApplicationDecisionV2Service, + useValue: mockAppDecService, + }, + ], + }).compile(); + + service = module.get(PublicApplicationService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); + + it('load an Application and its related data for get application', async () => { + mockAppService.get.mockResolvedValue( + new Application({ + dateReceivedAllItems: new Date(), + }), + ); + mockAppSubService.getOrFailByFileNumber.mockResolvedValue( + new ApplicationSubmission({ + get status(): ApplicationSubmissionToSubmissionStatus { + return new ApplicationSubmissionToSubmissionStatus(); + }, + }), + ); + mockAppParcelService.fetchByApplicationFileId.mockResolvedValue([]); + mockAppDocService.list.mockResolvedValue([]); + mockAppReviewService.getForPublicReview.mockResolvedValue( + new ApplicationSubmissionReview(), + ); + mockAppDecService.getByAppFileNumber.mockResolvedValue([]); + + const fileId = 'file-id'; + await service.getPublicApplicationData(fileId); + + expect(mockAppService.get).toHaveBeenCalledTimes(1); + expect(mockAppSubService.getOrFailByFileNumber).toHaveBeenCalledTimes(1); + expect(mockAppParcelService.fetchByApplicationFileId).toHaveBeenCalledTimes( + 1, + ); + expect(mockAppDocService.list).toHaveBeenCalledTimes(1); + expect(mockAppDocService.list).toHaveBeenCalledWith(fileId, [ + VISIBILITY_FLAG.PUBLIC, + ]); + expect(mockAppReviewService.getForPublicReview).toHaveBeenCalledTimes(1); + expect(mockAppDecService.getByAppFileNumber).toHaveBeenCalledTimes(1); + }); + + it('should call through to document service for getting files', async () => { + const mockDoc = new ApplicationDocument({ + visibilityFlags: [VISIBILITY_FLAG.PUBLIC], + }); + mockAppDocService.get.mockResolvedValue(mockDoc); + mockAppDocService.getInlineUrl.mockResolvedValue(''); + + const documentUuid = 'document-uuid'; + await service.getInlineUrl(documentUuid); + + expect(mockAppDocService.get).toHaveBeenCalledTimes(1); + expect(mockAppDocService.getInlineUrl).toHaveBeenCalledTimes(1); + expect(mockAppDocService.getInlineUrl).toHaveBeenCalledWith(mockDoc); + }); + + it('should throw an exception when the document is not public', async () => { + const mockDoc = new ApplicationDocument({ + visibilityFlags: [VISIBILITY_FLAG.APPLICANT], + }); + mockAppDocService.get.mockResolvedValue(mockDoc); + + const documentUuid = 'document-uuid'; + const promise = service.getInlineUrl(documentUuid); + + await expect(promise).rejects.toMatchObject( + new ServiceNotFoundException('Failed to find document'), + ); + + expect(mockAppDocService.get).toHaveBeenCalledTimes(1); + expect(mockAppDocService.getInlineUrl).toHaveBeenCalledTimes(0); + }); +}); diff --git a/services/apps/alcs/src/portal/public/public-application.service.ts b/services/apps/alcs/src/portal/public/public-application.service.ts new file mode 100644 index 0000000000..eaa9d3feb8 --- /dev/null +++ b/services/apps/alcs/src/portal/public/public-application.service.ts @@ -0,0 +1,136 @@ +import { ServiceNotFoundException } from '@app/common/exceptions/base.exception'; +import { Mapper } from '@automapper/core'; +import { InjectMapper } from '@automapper/nestjs'; +import { Injectable } from '@nestjs/common'; +import { ApplicationDecisionV2Service } from '../../alcs/application-decision/application-decision-v2/application-decision/application-decision-v2.service'; +import { ApplicationDecision } from '../../alcs/application-decision/application-decision.entity'; +import { + ApplicationDocument, + VISIBILITY_FLAG, +} from '../../alcs/application/application-document/application-document.entity'; +import { ApplicationDocumentService } from '../../alcs/application/application-document/application-document.service'; +import { ApplicationService } from '../../alcs/application/application.service'; +import { ApplicationPortalDecisionDto } from '../application-decision/application-decision.dto'; +import { ApplicationSubmissionReview } from '../application-submission-review/application-submission-review.entity'; +import { ApplicationSubmissionReviewService } from '../application-submission-review/application-submission-review.service'; +import { ApplicationParcel } from '../application-submission/application-parcel/application-parcel.entity'; +import { ApplicationParcelService } from '../application-submission/application-parcel/application-parcel.service'; +import { ApplicationSubmission } from '../application-submission/application-submission.entity'; +import { ApplicationSubmissionService } from '../application-submission/application-submission.service'; +import { + PublicApplicationParcelDto, + PublicApplicationSubmissionDto, + PublicApplicationSubmissionReviewDto, + PublicDocumentDto, +} from './public.dto'; + +@Injectable() +export class PublicApplicationService { + constructor( + private applicationService: ApplicationService, + private applicationSubmissionService: ApplicationSubmissionService, + private applicationParcelService: ApplicationParcelService, + private applicationDocumentService: ApplicationDocumentService, + private applicationSubmissionReviewService: ApplicationSubmissionReviewService, + private applicationDecisionService: ApplicationDecisionV2Service, + @InjectMapper() private mapper: Mapper, + ) {} + + async getPublicApplicationData(fileNumber: string) { + const application = await this.applicationService.get(fileNumber); + + //Easy way to check if its public + if (!application?.dateReceivedAllItems) { + throw new ServiceNotFoundException( + `Failed to find application with File ID ${fileNumber}`, + ); + } + + const submission = + await this.applicationSubmissionService.getOrFailByFileNumber(fileNumber); + + const parcels = + await this.applicationParcelService.fetchByApplicationFileId(fileNumber); + + const mappedParcels = this.mapper.mapArray( + parcels, + ApplicationParcel, + PublicApplicationParcelDto, + ); + + const mappedSubmission = this.mapper.map( + submission, + ApplicationSubmission, + PublicApplicationSubmissionDto, + ); + + const documents = await this.applicationDocumentService.list(fileNumber, [ + VISIBILITY_FLAG.PUBLIC, + ]); + + const mappedDocuments = this.mapper.mapArray( + documents, + ApplicationDocument, + PublicDocumentDto, + ); + + const review = + await this.applicationSubmissionReviewService.getForPublicReview( + fileNumber, + ); + + let mappedReview; + if (review) { + mappedReview = this.mapper.map( + review, + ApplicationSubmissionReview, + PublicApplicationSubmissionReviewDto, + ); + } + + const decisions = await this.applicationDecisionService.getByAppFileNumber( + fileNumber, + ); + const mappedDecisions = this.mapper.mapArray( + decisions, + ApplicationDecision, + ApplicationPortalDecisionDto, + ); + + return { + submission: mappedSubmission, + parcels: mappedParcels, + documents: mappedDocuments, + review: mappedReview, + decisions: mappedDecisions, + }; + } + + async getDownloadUrl(documentUuid: string) { + const document = await this.applicationDocumentService.get(documentUuid); + + if (!document.visibilityFlags.includes(VISIBILITY_FLAG.PUBLIC)) { + throw new ServiceNotFoundException('Failed to find document'); + } + + const url = await this.applicationDocumentService.getDownloadUrl(document); + + return { + url, + }; + } + + async getInlineUrl(documentUuid: string) { + const document = await this.applicationDocumentService.get(documentUuid); + + if (!document.visibilityFlags.includes(VISIBILITY_FLAG.PUBLIC)) { + throw new ServiceNotFoundException('Failed to find document'); + } + + const url = await this.applicationDocumentService.getInlineUrl(document); + + return { + url, + }; + } +} diff --git a/services/apps/alcs/src/portal/public/public.controller.spec.ts b/services/apps/alcs/src/portal/public/public.controller.spec.ts index 734f96eae1..bd2ead3c39 100644 --- a/services/apps/alcs/src/portal/public/public.controller.spec.ts +++ b/services/apps/alcs/src/portal/public/public.controller.spec.ts @@ -1,61 +1,26 @@ -import { ServiceNotFoundException } from '@app/common/exceptions/base.exception'; import { classes } from '@automapper/classes'; import { AutomapperModule } from '@automapper/nestjs'; import { createMock, DeepMocked } from '@golevelup/nestjs-testing'; import { Test, TestingModule } from '@nestjs/testing'; import { ClsService } from 'nestjs-cls'; import { mockKeyCloakProviders } from '../../../test/mocks/mockTypes'; -import { - ApplicationDocument, - VISIBILITY_FLAG, -} from '../../alcs/application/application-document/application-document.entity'; -import { ApplicationDocumentService } from '../../alcs/application/application-document/application-document.service'; -import { ApplicationSubmissionToSubmissionStatus } from '../../alcs/application/application-submission-status/submission-status.entity'; -import { Application } from '../../alcs/application/application.entity'; -import { ApplicationService } from '../../alcs/application/application.service'; import { PublicAutomapperProfile } from '../../common/automapper/public.automapper.profile'; -import { ApplicationParcelService } from '../application-submission/application-parcel/application-parcel.service'; -import { ApplicationSubmission } from '../application-submission/application-submission.entity'; -import { ApplicationSubmissionService } from '../application-submission/application-submission.service'; +import { PublicApplicationService } from './public-application.service'; import { PublicController } from './public.controller'; describe('PublicSearchController', () => { let controller: PublicController; - let mockAppService: DeepMocked; - let mockAppSubService: DeepMocked; - let mockAppParcelService: DeepMocked; - let mockAppDocService: DeepMocked; + let mockAppService: DeepMocked; beforeEach(async () => { mockAppService = createMock(); - mockAppSubService = createMock(); - mockAppParcelService = createMock(); - mockAppDocService = createMock(); const module: TestingModule = await Test.createTestingModule({ - imports: [ - AutomapperModule.forRoot({ - strategyInitializer: classes(), - }), - ], providers: [ - PublicAutomapperProfile, { - provide: ApplicationService, + provide: PublicApplicationService, useValue: mockAppService, }, - { - provide: ApplicationSubmissionService, - useValue: mockAppSubService, - }, - { - provide: ApplicationParcelService, - useValue: mockAppParcelService, - }, - { - provide: ApplicationDocumentService, - useValue: mockAppDocService, - }, { provide: ClsService, useValue: {}, @@ -72,67 +37,12 @@ describe('PublicSearchController', () => { expect(controller).toBeDefined(); }); - it('load an Application and its related data for get application', async () => { - mockAppService.get.mockResolvedValue( - new Application({ - dateReceivedAllItems: new Date(), - }), - ); - mockAppSubService.getOrFailByFileNumber.mockResolvedValue( - new ApplicationSubmission({ - get status(): ApplicationSubmissionToSubmissionStatus { - return new ApplicationSubmissionToSubmissionStatus(); - }, - }), - ); - mockAppParcelService.fetchByApplicationFileId.mockResolvedValue([]); - mockAppDocService.list.mockResolvedValue([]); + it('should call through to service for loading an application', async () => { + mockAppService.getPublicApplicationData.mockResolvedValue({} as any); const fileId = 'file-id'; await controller.getApplication(fileId); - expect(mockAppService.get).toHaveBeenCalledTimes(1); - expect(mockAppSubService.getOrFailByFileNumber).toHaveBeenCalledTimes(1); - expect(mockAppParcelService.fetchByApplicationFileId).toHaveBeenCalledTimes( - 1, - ); - expect(mockAppDocService.list).toHaveBeenCalledTimes(1); - expect(mockAppDocService.list).toHaveBeenCalledWith(fileId, [ - VISIBILITY_FLAG.PUBLIC, - ]); - }); - - it('should call through to document service for getting files', async () => { - const mockDoc = new ApplicationDocument({ - visibilityFlags: [VISIBILITY_FLAG.PUBLIC], - }); - mockAppDocService.get.mockResolvedValue(mockDoc); - mockAppDocService.getInlineUrl.mockResolvedValue(''); - - const fileId = 'file-id'; - const documentUuid = 'document-uuid'; - await controller.getApplicationDocumentOpen(fileId, documentUuid); - - expect(mockAppDocService.get).toHaveBeenCalledTimes(1); - expect(mockAppDocService.getInlineUrl).toHaveBeenCalledTimes(1); - expect(mockAppDocService.getInlineUrl).toHaveBeenCalledWith(mockDoc); - }); - - it('should throw an exception when the document is not public', async () => { - const mockDoc = new ApplicationDocument({ - visibilityFlags: [VISIBILITY_FLAG.APPLICANT], - }); - mockAppDocService.get.mockResolvedValue(mockDoc); - - const fileId = 'file-id'; - const documentUuid = 'document-uuid'; - const promise = controller.getApplicationDocumentOpen(fileId, documentUuid); - - await expect(promise).rejects.toMatchObject( - new ServiceNotFoundException('Failed to find document'), - ); - - expect(mockAppDocService.get).toHaveBeenCalledTimes(1); - expect(mockAppDocService.getInlineUrl).toHaveBeenCalledTimes(0); + expect(mockAppService.getPublicApplicationData).toHaveBeenCalledTimes(1); }); }); diff --git a/services/apps/alcs/src/portal/public/public.controller.ts b/services/apps/alcs/src/portal/public/public.controller.ts index 264d0393b5..4ba18be531 100644 --- a/services/apps/alcs/src/portal/public/public.controller.ts +++ b/services/apps/alcs/src/portal/public/public.controller.ts @@ -1,75 +1,15 @@ -import { ServiceNotFoundException } from '@app/common/exceptions/base.exception'; -import { Mapper } from '@automapper/core'; -import { InjectMapper } from '@automapper/nestjs'; import { Controller, Get, Param } from '@nestjs/common'; import { Public } from 'nest-keycloak-connect'; -import { ApplicationDocumentDto } from '../../alcs/application/application-document/application-document.dto'; -import { - ApplicationDocument, - VISIBILITY_FLAG, -} from '../../alcs/application/application-document/application-document.entity'; -import { ApplicationDocumentService } from '../../alcs/application/application-document/application-document.service'; -import { ApplicationService } from '../../alcs/application/application.service'; -import { ApplicationParcelDto } from '../application-submission/application-parcel/application-parcel.dto'; -import { ApplicationParcel } from '../application-submission/application-parcel/application-parcel.entity'; -import { ApplicationParcelService } from '../application-submission/application-parcel/application-parcel.service'; -import { ApplicationSubmission } from '../application-submission/application-submission.entity'; -import { ApplicationSubmissionService } from '../application-submission/application-submission.service'; -import { PublicApplicationSubmissionDto } from './public.dto'; +import { PublicApplicationService } from './public-application.service'; @Public() @Controller('/public') export class PublicController { - constructor( - @InjectMapper() private mapper: Mapper, - private applicationService: ApplicationService, - private applicationSubmissionService: ApplicationSubmissionService, - private applicationParcelService: ApplicationParcelService, - private applicationDocumentService: ApplicationDocumentService, - ) {} + constructor(private publicAppService: PublicApplicationService) {} @Get('/application/:fileId') - async getApplication(@Param('fileId') fileId: string) { - const application = await this.applicationService.get(fileId); - if (!application?.dateReceivedAllItems) { - throw new ServiceNotFoundException( - `Failed to find application with File ID ${fileId}`, - ); - } - - const submission = - await this.applicationSubmissionService.getOrFailByFileNumber(fileId); - - const parcels = - await this.applicationParcelService.fetchByApplicationFileId(fileId); - - const mappedParcels = this.mapper.mapArray( - parcels, - ApplicationParcel, - ApplicationParcelDto, - ); - - const mappedSubmission = this.mapper.map( - submission, - ApplicationSubmission, - PublicApplicationSubmissionDto, - ); - - const documents = await this.applicationDocumentService.list(fileId, [ - VISIBILITY_FLAG.PUBLIC, - ]); - - const mappedDocuments = this.mapper.mapArray( - documents, - ApplicationDocument, - ApplicationDocumentDto, - ); - - return { - submission: mappedSubmission, - parcels: mappedParcels, - documents: mappedDocuments, - }; + async getApplication(@Param('fileId') fileNumber: string) { + return await this.publicAppService.getPublicApplicationData(fileNumber); } @Get('/application/:fileId/:uuid/download') @@ -77,13 +17,7 @@ export class PublicController { @Param('fileId') fileId: string, @Param('uuid') documentUuid: string, ) { - const document = await this.applicationDocumentService.get(documentUuid); - - if (!document.visibilityFlags.includes(VISIBILITY_FLAG.PUBLIC)) { - throw new ServiceNotFoundException('Failed to find document'); - } - - const url = await this.applicationDocumentService.getDownloadUrl(document); + const url = await this.publicAppService.getDownloadUrl(documentUuid); return { url, @@ -95,13 +29,7 @@ export class PublicController { @Param('fileId') fileId: string, @Param('uuid') documentUuid: string, ) { - const document = await this.applicationDocumentService.get(documentUuid); - - if (!document.visibilityFlags.includes(VISIBILITY_FLAG.PUBLIC)) { - throw new ServiceNotFoundException('Failed to find document'); - } - - const url = await this.applicationDocumentService.getInlineUrl(document); + const url = await this.publicAppService.getInlineUrl(documentUuid); return { url, diff --git a/services/apps/alcs/src/portal/public/public.dto.ts b/services/apps/alcs/src/portal/public/public.dto.ts index e502cf8720..69968c4dae 100644 --- a/services/apps/alcs/src/portal/public/public.dto.ts +++ b/services/apps/alcs/src/portal/public/public.dto.ts @@ -1,6 +1,8 @@ import { AutoMap } from '@automapper/classes'; import { ApplicationStatusDto } from '../../alcs/application/application-submission-status/submission-status.dto'; import { OwnerTypeDto } from '../../common/owner-type/owner-type.entity'; +import { DocumentTypeDto } from '../../document/document.dto'; +import { ApplicationParcelOwnershipTypeDto } from '../application-submission/application-parcel/application-parcel.dto'; import { NaruSubtypeDto } from '../application-submission/application-submission.dto'; import { ProposedLot } from '../application-submission/application-submission.entity'; @@ -315,3 +317,113 @@ export class PublicApplicationSubmissionDto { @AutoMap(() => Boolean) inclGovernmentOwnsAllParcels?: boolean | null; } + +export class PublicApplicationSubmissionReviewDto { + @AutoMap() + applicationFileNumber: string; + + @AutoMap(() => String) + localGovernmentFileNumber: string | null; + + @AutoMap(() => String) + firstName: string | null; + + @AutoMap(() => String) + lastName: string | null; + + @AutoMap(() => String) + position: string | null; + + @AutoMap(() => String) + department: string | null; + + @AutoMap(() => Boolean) + isOCPDesignation: boolean | null; + + @AutoMap(() => String) + OCPBylawName: string | null; + + @AutoMap(() => String) + OCPDesignation: string | null; + + @AutoMap(() => Boolean) + OCPConsistent: boolean | null; + + @AutoMap(() => Boolean) + isSubjectToZoning: boolean | null; + + @AutoMap(() => String) + zoningBylawName: string | null; + + @AutoMap(() => String) + zoningDesignation: string | null; + + @AutoMap(() => String) + zoningMinimumLotSize: string | null; + + @AutoMap(() => Boolean) + isZoningConsistent: boolean | null; + + @AutoMap(() => Boolean) + isAuthorized: boolean | null; +} + +export class PublicApplicationParcelDto { + @AutoMap() + uuid: string; + + @AutoMap(() => String) + pid?: string | null; + + @AutoMap(() => String) + pin?: string | null; + + @AutoMap(() => String) + legalDescription?: string | null; + + @AutoMap(() => String) + civicAddress?: string | null; + + @AutoMap(() => Number) + mapAreaHectares?: number | null; + + @AutoMap(() => Number) + purchasedDate?: number | null; + + @AutoMap(() => Boolean) + isFarm?: boolean | null; + + @AutoMap(() => String) + ownershipTypeCode?: string | null; + + @AutoMap(() => String) + crownLandOwnerType?: string | null; + + ownershipType?: ApplicationParcelOwnershipTypeDto; + + @AutoMap(() => String) + parcelType: string; + + @AutoMap(() => Number) + alrArea: number | null; + + owners: PublicOwnerDto[]; +} + +export class PublicDocumentDto { + @AutoMap(() => String) + description?: string; + + @AutoMap() + uuid: string; + + @AutoMap(() => DocumentTypeDto) + type?: DocumentTypeDto; + + //Document Fields + documentUuid: string; + fileName: string; + fileSize?: number; + mimeType: string; + uploadedAt: number; +} diff --git a/services/apps/alcs/src/portal/public/public.module.ts b/services/apps/alcs/src/portal/public/public.module.ts index c0e86ea8d4..e0e1f1806a 100644 --- a/services/apps/alcs/src/portal/public/public.module.ts +++ b/services/apps/alcs/src/portal/public/public.module.ts @@ -1,11 +1,13 @@ import { Module } from '@nestjs/common'; import { RouterModule } from '@nestjs/core'; +import { ApplicationDecisionV2Module } from '../../alcs/application-decision/application-decision-v2/application-decision-v2.module'; import { ApplicationSubmissionStatusModule } from '../../alcs/application/application-submission-status/application-submission-status.module'; import { ApplicationModule } from '../../alcs/application/application.module'; import { NotificationSubmissionStatusModule } from '../../alcs/notification/notification-submission-status/notification-submission-status.module'; -import { ApplicationSubmissionProfile } from '../../common/automapper/application-submission.automapper.profile'; import { PublicAutomapperProfile } from '../../common/automapper/public.automapper.profile'; +import { ApplicationSubmissionReviewModule } from '../application-submission-review/application-submission-review.module'; import { ApplicationSubmissionModule } from '../application-submission/application-submission.module'; +import { PublicApplicationService } from './public-application.service'; import { PublicController } from './public.controller'; import { PublicSearchModule } from './search/public-search.module'; import { PublicStatusController } from './status/public-status.controller'; @@ -17,10 +19,12 @@ import { PublicStatusController } from './status/public-status.controller'; NotificationSubmissionStatusModule, ApplicationModule, ApplicationSubmissionModule, + ApplicationSubmissionReviewModule, + ApplicationDecisionV2Module, RouterModule.register([{ path: 'public', module: PublicSearchModule }]), ], controllers: [PublicStatusController, PublicController], - providers: [PublicAutomapperProfile], + providers: [PublicAutomapperProfile, PublicApplicationService], exports: [], }) export class PublicModule {}