Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/bcgov/nr-bcws-wfprev into f…
Browse files Browse the repository at this point in the history
…eature/WFPREV-127
  • Loading branch information
ssylver93 committed Jan 31, 2025
2 parents 8e6f4dc + 6df93d8 commit c69d381
Show file tree
Hide file tree
Showing 9 changed files with 239 additions and 24 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<div class="dialog-container">
<div class="title-bar">
{{ dialogUsage === 'confirm-cancel' ? 'Confirm Cancel' : 'Duplicate Found' }}
{{dialogTitle}}
</div>
<div class="dialog-content">
<div class="icon-and-text">
Expand All @@ -12,6 +12,10 @@
<p *ngIf="dialogUsage === 'duplicate-project'">
This Project already exists:<br />
</p>
<p *ngIf="dialogUsage === 'confirm-delete'">
Are you sure you want to delete this fiscal year?<br />
This action cannot be undone.
</p>
</div>
</div>
<div class="footer">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,17 @@ import { MatIconModule } from '@angular/material/icon';
export class ConfirmationDialogComponent {
dialogUsage: string;

get dialogTitle(): string {
switch (this.dialogUsage) {
case 'confirm-cancel':
return 'Confirm Cancel';
case 'confirm-delete':
return 'Confirm Delete';
default:
return 'Duplicate Found';
}
}

constructor(
private readonly dialogRef: MatDialogRef<ConfirmationDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: { indicator: string }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
</div>
</mat-expansion-panel-header>
<mat-menu #menu="matMenu">
<button mat-menu-item>
<button mat-menu-item (click)="deleteFiscalYear(fiscalForms[i])" [disabled]="isUndeletable(fiscalForms[i])">
Delete Fiscal Year
</button>
<button mat-menu-item >
Expand All @@ -31,7 +31,7 @@
Closeout Fiscal
</button>
</mat-menu>
<form class="form-grid" [formGroup]="fiscalForms[i]">
<form class="form-grid" *ngIf="fiscalForms[i]" [formGroup]="fiscalForms[i]">

<div class="form-item">
<label>Fiscal Year<span class="required">*</span></label>
Expand Down Expand Up @@ -75,12 +75,12 @@

<div class="form-item">
<label>Planned Hectares</label>
<input type="text" id="fiscalPlannedProjectSizeHa" formControlName="fiscalPlannedProjectSizeHa" />
<input type="number" id="fiscalPlannedProjectSizeHa" formControlName="fiscalPlannedProjectSizeHa" />
</div>

<div class="form-item">
<label>Completed Hectares</label>
<input type="text" id="fiscalCompletedSizeHa" formControlName="fiscalCompletedSizeHa" />
<input type="number" id="fiscalCompletedSizeHa" formControlName="fiscalCompletedSizeHa" />
</div>

<div class="form-item">
Expand Down Expand Up @@ -121,7 +121,16 @@

<div class="form-item half-width">
<label>Description<span class="required">*</span></label>
<textarea id="projectFiscalDescription" formControlName="projectFiscalDescription" rows="4" cols="50"></textarea>
<textarea
id="projectFiscalDescription"
formControlName="projectFiscalDescription"
rows="4" cols="50"
>
</textarea>
<div class="error" *ngIf="fiscalForms[i] && fiscalForms[i].get('projectFiscalDescription')?.hasError('maxlength')
&& fiscalForms[i].get('projectFiscalDescription')?.touched">
{{ messages.maxLengthExceeded }}
</div>
</div>
<div class="form-item half-width">
<label>Other Partners</label>
Expand All @@ -141,8 +150,9 @@

<div class="form-item budget-width">
<label>Forecast Amount</label>
<input type="Cost" id="fiscalForecastAmount"
formControlName="fiscalForecastAmount"/>
<input type="number" id="fiscalForecastAmount"
formControlName="fiscalForecastAmount"
/>
</div>

<div class="form-item budget-width">
Expand All @@ -151,7 +161,7 @@
</div>

<div class="form-item budget-width">
<label>Ancilliary Funding Provider</label>
<label>Ancillary Funding Provider</label>
<select id="ancillaryFundingSourceGuid" formControlName="ancillaryFundingSourceGuid">
<option value="" >Select</option>
<option *ngFor="let item of ancillaryFundingSourceCode"[value]="item.ancillaryFundingSourceGuid">
Expand All @@ -161,25 +171,28 @@
</div>

<div class="form-item budget-width">
<label>Ancilliary Funding Amount</label>
<input type="Cost" id="fiscalAncillaryFundAmount" formControlName="fiscalAncillaryFundAmount"/>
<label>Ancillary Funding Amount</label>
<input type="number" id="fiscalAncillaryFundAmount" formControlName="fiscalAncillaryFundAmount"/>
</div>

<div class="form-item budget-width">
<label>Reported Spend</label>
<input type="Cost" id="fiscalReportedSpendAmount" formControlName="fiscalReportedSpendAmount"/>
<input type="number" id="fiscalReportedSpendAmount" formControlName="fiscalReportedSpendAmount"/>
</div>

<div class="form-item cfs-width">
<label>CFS Actual Spend</label>
<input type="Cost" id="fiscalActualAmount" formControlName="fiscalActualAmount"/>
<input type="number" id="fiscalActualAmount" formControlName="fiscalActualAmount"/>
</div>
</form>
<div class="fiscal-footer">
<div class="footer-button-row">
<button class="secondary" (click)="onCancelFiscal(i)" [disabled]="!fiscalForms[i].dirty" >Cancel</button>
<button type="button" (click)="onSaveFiscal(i)" [disabled]="!fiscalForms[i].valid || !fiscalForms[i].dirty"
class="primary">Save
<button class="secondary" (click)="onCancelFiscal(i)" *ngIf="fiscalForms[i]" [disabled]="!fiscalForms[i].dirty">
Cancel
</button>
<button type="button" (click)="onSaveFiscal(i)" *ngIf="fiscalForms[i]" [disabled]="!fiscalForms[i].valid || !fiscalForms[i].dirty"
class="primary">
Save
</button>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@
.form-item {
flex: 1 1 calc(20% - 20px); // 5 items per row with a 20px gap
min-width: 200px;

.error {
color: red;
font-size: 12px;
margin-top: 4px;
}
label {
padding: 9px;
color: #282828;
Expand Down Expand Up @@ -51,6 +55,10 @@
box-sizing: border-box;
resize: vertical;
min-height: 80px;
height: auto;
line-height: 1.5;
white-space: pre-wrap;
word-wrap: break-word;
}
}

Expand Down Expand Up @@ -168,9 +176,9 @@
}

.button-row{
position: fixed;
right: 3%;
z-index: 100;
display: flex;
justify-content: flex-end;
align-items: center;
button {
&.primary {
@extend .button-primary;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@ import { CodeTableServices } from 'src/app/services/code-table-services';
import { MatSnackBar } from '@angular/material/snack-bar';
import { FormBuilder } from '@angular/forms';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { ConfirmationDialogComponent } from 'src/app/components/confirmation-dialog/confirmation-dialog.component';

const mockProjectService = {
getProjectFiscalsByProjectGuid: jasmine.createSpy('getProjectFiscalsByProjectGuid').and.returnValue(
of({ _embedded: { projectFiscals: [{ fiscalYear: 2023, projectFiscalName: 'Test Fiscal' }] } })
),
updateProjectFiscal: jasmine.createSpy('updateProjectFiscal').and.returnValue(of({})),
createProjectFiscal: jasmine.createSpy('createProjectFiscal').and.returnValue(of({})),
deleteProjectFiscalByProjectPlanFiscalGuid: jasmine.createSpy('deleteProjectFiscalByProjectPlanFiscalGuid').and.returnValue(of({})), // ✅ Add this line

};

const mockCodeTableServices = {
Expand All @@ -30,7 +33,7 @@ describe('ProjectFiscalsComponent', () => {

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [ProjectFiscalsComponent, BrowserAnimationsModule],
imports: [ProjectFiscalsComponent, BrowserAnimationsModule, ConfirmationDialogComponent],
providers: [
{ provide: ActivatedRoute, useValue: { snapshot: { queryParamMap: { get: () => 'test-guid' } } } },
{ provide: ProjectService, useValue: mockProjectService },
Expand Down Expand Up @@ -198,4 +201,85 @@ describe('ProjectFiscalsComponent', () => {

expect(() => component.onCancelFiscal(0)).not.toThrow();
});

it('should open confirmation dialog when deleting a fiscal year', () => {
spyOn(component.dialog, 'open').and.returnValue({
afterClosed: () => of(true) // Simulate user clicking "Confirm"
} as any);

component.projectFiscals = [{ projectPlanFiscalGuid: 'test-guid' }];
component.deleteFiscalYear({ value: component.projectFiscals[0] });

expect(component.dialog.open).toHaveBeenCalledWith(ConfirmationDialogComponent, {
data: { indicator: 'confirm-delete' },
width: '500px',
});
});

it('should delete a fiscal year after confirmation', () => {
spyOn(component.dialog, 'open').and.returnValue({
afterClosed: () => of(true) // Simulate user clicking "Confirm"
} as any);
spyOn(component, 'loadProjectFiscals');

mockProjectService.deleteProjectFiscalByProjectPlanFiscalGuid = jasmine.createSpy().and.returnValue(of({}));

component.projectFiscals = [{ projectPlanFiscalGuid: 'test-guid' }];
component.deleteFiscalYear({ value: component.projectFiscals[0] });

expect(mockProjectService.deleteProjectFiscalByProjectPlanFiscalGuid).toHaveBeenCalledWith('test-guid', 'test-guid');
expect(mockSnackBar.open).toHaveBeenCalledWith(
component.messages.projectFiscalDeletedSuccess,
'OK',
{ duration: 5000, panelClass: 'snackbar-success' }
);
expect(component.loadProjectFiscals).toHaveBeenCalledWith(true);
});

it('should show error snackbar if deletion fails', () => {
spyOn(component.dialog, 'open').and.returnValue({
afterClosed: () => of(true) // Simulate user clicking "Confirm"
} as any);

mockProjectService.deleteProjectFiscalByProjectPlanFiscalGuid = jasmine.createSpy().and.returnValue(
throwError(() => new Error('API Error'))
);

component.projectFiscals = [{ projectPlanFiscalGuid: 'test-guid' }];
component.deleteFiscalYear({ value: component.projectFiscals[0] });

expect(mockSnackBar.open).toHaveBeenCalledWith(
component.messages.projectFiscalDeletedFailure,
'OK',
{ duration: 5000, panelClass: 'snackbar-error' }
);
});

it('should reload fiscal years if projectPlanFiscalGuid is missing', () => {
spyOn(component, 'loadProjectFiscals');

component.deleteFiscalYear({ value: { projectPlanFiscalGuid: null } });

expect(component.loadProjectFiscals).toHaveBeenCalledWith(true);
});

it('should return true for isUndeletable if isApprovedInd is true', () => {
const form = { value: { isApprovedInd: true } };
expect(component.isUndeletable(form)).toBe(true);
});

it('should return false for isUndeletable if isApprovedInd is false', () => {
const form = { value: { isApprovedInd: false } };
expect(component.isUndeletable(form)).toBe(false);
});

it('should return false for isUndeletable if isApprovedInd is undefined', () => {
const form = { value: {} };
expect(component.isUndeletable(form)).toBe(false);
});

it('should return false for isUndeletable if form is null', () => {
expect(component.isUndeletable(null)).toBe(false);
});

});
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import { Messages } from 'src/app/utils/messages';
import { CodeTableServices } from 'src/app/services/code-table-services';
import { MatMenuModule } from '@angular/material/menu';
import { Observable } from 'rxjs';
import { MatDialog } from '@angular/material/dialog';
import { ConfirmationDialogComponent } from 'src/app/components/confirmation-dialog/confirmation-dialog.component';

@Component({
selector: 'app-project-fiscals',
Expand Down Expand Up @@ -47,6 +49,8 @@ export class ProjectFiscalsComponent implements OnInit {
private codeTableService: CodeTableServices,
private readonly fb: FormBuilder,
private readonly snackbarService: MatSnackBar,
public readonly dialog: MatDialog,

) {}

ngOnInit(): void {
Expand Down Expand Up @@ -108,7 +112,7 @@ export class ProjectFiscalsComponent implements OnInit {
firstNationsEngagementInd: [fiscal?.firstNationsEngagementInd || false],
firstNationsDelivPartInd: [fiscal?.firstNationsDelivPartInd || false],
firstNationsPartner: [fiscal?.firstNationsPartner || ''],
projectFiscalDescription: [fiscal?.projectFiscalDescription || '', [Validators.required]],
projectFiscalDescription: [fiscal?.projectFiscalDescription || '', [Validators.required, Validators.maxLength(500)]],
otherPartner: [fiscal?.otherPartner || ''],
totalCostEstimateAmount: [fiscal?.totalCostEstimateAmount ?? ''],
forecastAmount: [fiscal?.forecastAmount ?? ''],
Expand All @@ -118,7 +122,9 @@ export class ProjectFiscalsComponent implements OnInit {
fiscalReportedSpendAmount: [fiscal?.fiscalReportedSpendAmount ?? ''],
cfsActualSpend: [fiscal?.cfsActualSpend || ''],
fiscalForecastAmount: [fiscal?.fiscalForecastAmount || ''],
fiscalActualAmount: [fiscal?.fiscalActualAmount || '']
fiscalActualAmount: [fiscal?.fiscalActualAmount || ''],
projectPlanFiscalGuid: [fiscal?.projectPlanFiscalGuid || ''],
isApprovedInd: [fiscal?.isApprovedInd || false]
});

return form;
Expand Down Expand Up @@ -229,7 +235,7 @@ export class ProjectFiscalsComponent implements OnInit {
submittedByUserGuid: updatedData.submittedByUserGuid,
submittedByUserUserid: updatedData.submittedByUserUserid,
submissionTimestamp: updatedData.submissionTimestamp,
isApprovedInd: isUpdate ? updatedData.isApprovedInd : true,
isApprovedInd: isUpdate ? updatedData.isApprovedInd : false,
isDelayedInd: isUpdate ? updatedData.isDelayedInd : false,
fiscalForecastAmount: updatedData.fiscalForecastAmount,
totalCostEstimateAmount: updatedData.totalCostEstimateAmount,
Expand Down Expand Up @@ -278,4 +284,43 @@ export class ProjectFiscalsComponent implements OnInit {
});
}
}

deleteFiscalYear(form: any) {
const formData = form.value;
if (formData.projectPlanFiscalGuid) {
const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
data: { indicator: 'confirm-delete' },
width: '500px',
});

dialogRef.afterClosed().subscribe((confirmed: boolean) => {
if (confirmed) {
this.projectService.deleteProjectFiscalByProjectPlanFiscalGuid(this.projectGuid, formData.projectPlanFiscalGuid)
.subscribe({
next: () => {
this.snackbarService.open(
this.messages.projectFiscalDeletedSuccess,
'OK',
{ duration: 5000, panelClass: 'snackbar-success' }
);
this.loadProjectFiscals(true);
},
error: () => {
this.snackbarService.open(
this.messages.projectFiscalDeletedFailure,
'OK',
{ duration: 5000, panelClass: 'snackbar-error' }
);
}
});
}
});
} else{
this.loadProjectFiscals(true);
}
}

isUndeletable(form: any): boolean {
return !!form?.value?.isApprovedInd;
}
}
Loading

0 comments on commit c69d381

Please sign in to comment.