From f2b773b94f732acedf749bfd594717602469022d Mon Sep 17 00:00:00 2001
From: Arnab subedi <147511052+Arnabsubedi233@users.noreply.github.com>
Date: Wed, 1 Apr 2026 11:14:14 +0100
Subject: [PATCH 1/8] PO-1848
---
...ant-details-enforcement-tab.component.html | 1 +
...-details-enforcement-tab.component.spec.ts | 18 ++
...ndant-details-enforcement-tab.component.ts | 10 +
...fines-acc-defendant-details.component.html | 1 +
...es-acc-defendant-details.component.spec.ts | 10 +
.../fines-acc-defendant-details.component.ts | 9 +
...-enf-collo-change-field-errors.constant.ts | 10 +
...s-acc-enf-collo-change-form.component.html | 65 ++++++
...cc-enf-collo-change-form.component.spec.ts | 36 ++++
...nes-acc-enf-collo-change-form.component.ts | 64 ++++++
.../fines-acc-enf-collo-change.component.html | 8 +
...nes-acc-enf-collo-change.component.spec.ts | 185 ++++++++++++++++++
.../fines-acc-enf-collo-change.component.ts | 99 ++++++++++
...enf-collo-change-field-errors.interface.ts | 8 +
...c-enf-collo-change-form-state.interface.ts | 3 +
.../fines-acc/routing/fines-acc.routes.ts | 16 ++
.../fines-acc-payload.service.spec.ts | 16 ++
.../services/fines-acc-payload.service.ts | 16 ++
...account-patch-payload-defaults.constant.ts | 1 +
...dant-account-collection-order.interface.ts | 4 +
...ines-update-defendant-account.interface.ts | 6 +-
21 files changed, 584 insertions(+), 2 deletions(-)
create mode 100644 src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/constants/fines-acc-enf-collo-change-field-errors.constant.ts
create mode 100644 src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change-form/fines-acc-enf-collo-change-form.component.html
create mode 100644 src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change-form/fines-acc-enf-collo-change-form.component.spec.ts
create mode 100644 src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change-form/fines-acc-enf-collo-change-form.component.ts
create mode 100644 src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.html
create mode 100644 src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.spec.ts
create mode 100644 src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.ts
create mode 100644 src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/interfaces/fines-acc-enf-collo-change-field-errors.interface.ts
create mode 100644 src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/interfaces/fines-acc-enf-collo-change-form-state.interface.ts
create mode 100644 src/app/flows/fines/services/opal-fines-service/interfaces/opal-fines-update-defendant-account-collection-order.interface.ts
diff --git a/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details-enforcement-tab/fines-acc-defendant-details-enforcement-tab.component.html b/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details-enforcement-tab/fines-acc-defendant-details-enforcement-tab.component.html
index 79213afe10..932ac37121 100644
--- a/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details-enforcement-tab/fines-acc-defendant-details-enforcement-tab.component.html
+++ b/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details-enforcement-tab/fines-acc-defendant-details-enforcement-tab.component.html
@@ -20,6 +20,7 @@
Enforcement status
? true
: false
"
+ (actionClick)="handleChangeCollectionOrder()"
>
Collection Order status
diff --git a/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details-enforcement-tab/fines-acc-defendant-details-enforcement-tab.component.spec.ts b/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details-enforcement-tab/fines-acc-defendant-details-enforcement-tab.component.spec.ts
index bcace27490..a802829864 100644
--- a/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details-enforcement-tab/fines-acc-defendant-details-enforcement-tab.component.spec.ts
+++ b/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details-enforcement-tab/fines-acc-defendant-details-enforcement-tab.component.spec.ts
@@ -31,4 +31,22 @@ describe('FinesAccDefendantDetailsEnforcementTab', () => {
expect(event.preventDefault).toHaveBeenCalled();
expect(eventEmitterSpy).toHaveBeenCalled();
});
+
+ it('should emit changeCollectionOrder when handleChangeCollectionOrder is called', () => {
+ const eventEmitterSpy = vi.spyOn(component.changeCollectionOrder, 'emit');
+ component.hasAccountMaintenancePermission = true;
+
+ component.handleChangeCollectionOrder();
+
+ expect(eventEmitterSpy).toHaveBeenCalled();
+ });
+
+ it('should not emit changeCollectionOrder when the user lacks account maintenance permission', () => {
+ const eventEmitterSpy = vi.spyOn(component.changeCollectionOrder, 'emit');
+ component.hasAccountMaintenancePermission = false;
+
+ component.handleChangeCollectionOrder();
+
+ expect(eventEmitterSpy).not.toHaveBeenCalled();
+ });
});
diff --git a/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details-enforcement-tab/fines-acc-defendant-details-enforcement-tab.component.ts b/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details-enforcement-tab/fines-acc-defendant-details-enforcement-tab.component.ts
index 19ec837685..2dd044de1a 100644
--- a/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details-enforcement-tab/fines-acc-defendant-details-enforcement-tab.component.ts
+++ b/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details-enforcement-tab/fines-acc-defendant-details-enforcement-tab.component.ts
@@ -39,6 +39,7 @@ export class FinesAccDefendantDetailsEnforcementTab {
@Input() hasAccountMaintenancePermission: boolean = false;
@Input() hasEnterEnforcementPermission: boolean = false;
@Output() addEnforcementOverride = new EventEmitter();
+ @Output() changeCollectionOrder = new EventEmitter();
/**
* Emits an event to add an enforcement override if the user has the necessary permissions and there is no existing enforcement override result.
@@ -53,4 +54,13 @@ export class FinesAccDefendantDetailsEnforcementTab {
this.addEnforcementOverride.emit();
}
}
+
+ /**
+ * Emits an event to change the collection order status.
+ */
+ public handleChangeCollectionOrder(): void {
+ if (this.hasAccountMaintenancePermission) {
+ this.changeCollectionOrder.emit();
+ }
+ }
}
diff --git a/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details.component.html b/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details.component.html
index 39396c237f..7dfb772fe7 100644
--- a/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details.component.html
+++ b/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details.component.html
@@ -206,6 +206,7 @@ Business Unit:
[hasAccountMaintenancePermission]="hasPermission('account-maintenance')"
[hasEnterEnforcementPermission]="hasPermission('enter-enforcement')"
(addEnforcementOverride)="navigateToAddEnforcementOverridePage()"
+ (changeCollectionOrder)="navigateToChangeCollectionOrderPage()"
>
}
}
diff --git a/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details.component.spec.ts b/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details.component.spec.ts
index feaa9c5f9b..1ca6778c7a 100644
--- a/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details.component.spec.ts
+++ b/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details.component.spec.ts
@@ -168,6 +168,16 @@ describe('FinesAccDefendantDetailsComponent', () => {
);
});
+ it('should call router.navigate when navigateToChangeCollectionOrderPage is called', () => {
+ component.navigateToChangeCollectionOrderPage();
+ expect(routerSpy.navigate).toHaveBeenCalledWith(
+ [`../${FINES_ACC_DEFENDANT_ROUTING_PATHS.children.enforcement}/collection-order/change`],
+ {
+ relativeTo: component['activatedRoute'],
+ },
+ );
+ });
+
it('should fetch the defendant tab data when fragment is changed to defendant', () => {
component['refreshFragment$'].next('defendant');
// Subscribe to trigger the pipe execution
diff --git a/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details.component.ts b/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details.component.ts
index c8d7f1b673..2df90a8b10 100644
--- a/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details.component.ts
+++ b/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details.component.ts
@@ -458,4 +458,13 @@ export class FinesAccDefendantDetailsComponent extends AbstractTabData implement
relativeTo: this.activatedRoute,
});
}
+
+ /**
+ * Navigates to the change collection order page.
+ */
+ public navigateToChangeCollectionOrderPage(): void {
+ this['router'].navigate([`../${FINES_ACC_DEFENDANT_ROUTING_PATHS.children.enforcement}/collection-order/change`], {
+ relativeTo: this.activatedRoute,
+ });
+ }
}
diff --git a/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/constants/fines-acc-enf-collo-change-field-errors.constant.ts b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/constants/fines-acc-enf-collo-change-field-errors.constant.ts
new file mode 100644
index 0000000000..645cb940e2
--- /dev/null
+++ b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/constants/fines-acc-enf-collo-change-field-errors.constant.ts
@@ -0,0 +1,10 @@
+import { IFinesAccEnfColloChangeFieldErrors } from '../interfaces/fines-acc-enf-collo-change-field-errors.interface';
+
+export const FINES_ACC_ENF_COLLO_CHANGE_FIELD_ERRORS: IFinesAccEnfColloChangeFieldErrors = {
+ facc_enf_collection_order_made: {
+ required: {
+ message: 'Select whether the account is subject to a Collection Order',
+ priority: 1,
+ },
+ },
+};
diff --git a/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change-form/fines-acc-enf-collo-change-form.component.html b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change-form/fines-acc-enf-collo-change-form.component.html
new file mode 100644
index 0000000000..7f106772a5
--- /dev/null
+++ b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change-form/fines-acc-enf-collo-change-form.component.html
@@ -0,0 +1,65 @@
+
+
+
+
+
+If the status of a Collection Order is incorrect you can change it.
+This will not issue a new notice.
+
+ To add a new Collection Order and issue a notice you should
+ go back
+ and add an enforcement action.
+
+
+
diff --git a/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change-form/fines-acc-enf-collo-change-form.component.spec.ts b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change-form/fines-acc-enf-collo-change-form.component.spec.ts
new file mode 100644
index 0000000000..345a29a01b
--- /dev/null
+++ b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change-form/fines-acc-enf-collo-change-form.component.spec.ts
@@ -0,0 +1,36 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ActivatedRoute } from '@angular/router';
+import { beforeEach, describe, expect, it } from 'vitest';
+import { FinesAccEnfColloChangeFormComponent } from './fines-acc-enf-collo-change-form.component';
+
+describe('FinesAccEnfColloChangeFormComponent', () => {
+ let component: FinesAccEnfColloChangeFormComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [FinesAccEnfColloChangeFormComponent],
+ providers: [{ provide: ActivatedRoute, useValue: { snapshot: { params: {}, data: {} } } }],
+ }).compileComponents();
+
+ fixture = TestBed.createComponent(FinesAccEnfColloChangeFormComponent);
+ component = fixture.componentInstance;
+ component.accountNumber = '177A';
+ component.partyName = 'Mr Robert THOMSON';
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should initialize the collection order control', () => {
+ expect(component.form.get('facc_enf_collection_order_made')).toBeTruthy();
+ expect(component.form.get('facc_enf_collection_order_made')?.value).toBeNull();
+ });
+
+ it('should render the account caption in account-number-first format', () => {
+ const compiled = fixture.nativeElement as HTMLElement;
+ expect(compiled.textContent).toContain('177A - Mr Robert THOMSON');
+ });
+});
diff --git a/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change-form/fines-acc-enf-collo-change-form.component.ts b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change-form/fines-acc-enf-collo-change-form.component.ts
new file mode 100644
index 0000000000..d2312cbcbb
--- /dev/null
+++ b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change-form/fines-acc-enf-collo-change-form.component.ts
@@ -0,0 +1,64 @@
+import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnInit } from '@angular/core';
+import { FormControl, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';
+import { AbstractFormBaseComponent } from '@hmcts/opal-frontend-common/components/abstract/abstract-form-base';
+import {
+ IAbstractFormBaseFieldErrors,
+ IAbstractFormBaseForm,
+} from '@hmcts/opal-frontend-common/components/abstract/abstract-form-base/interfaces';
+import { IAbstractFormControlErrorMessage } from '@hmcts/opal-frontend-common/components/abstract/interfaces';
+import { GovukButtonComponent } from '@hmcts/opal-frontend-common/components/govuk/govuk-button';
+import { GovukCancelLinkComponent } from '@hmcts/opal-frontend-common/components/govuk/govuk-cancel-link';
+import { GovukErrorSummaryComponent } from '@hmcts/opal-frontend-common/components/govuk/govuk-error-summary';
+import { GovukHeadingWithCaptionComponent } from '@hmcts/opal-frontend-common/components/govuk/govuk-heading-with-caption';
+import {
+ GovukRadioComponent,
+ GovukRadiosItemComponent,
+} from '@hmcts/opal-frontend-common/components/govuk/govuk-radio';
+import { FINES_ACC_DEFENDANT_ROUTING_PATHS } from '../../routing/constants/fines-acc-defendant-routing-paths.constant';
+import { IFinesAccEnfColloChangeFormState } from '../interfaces/fines-acc-enf-collo-change-form-state.interface';
+import { FINES_ACC_ENF_COLLO_CHANGE_FIELD_ERRORS } from '../constants/fines-acc-enf-collo-change-field-errors.constant';
+
+@Component({
+ selector: 'app-fines-acc-enf-collo-change-form',
+ imports: [
+ FormsModule,
+ ReactiveFormsModule,
+ GovukButtonComponent,
+ GovukCancelLinkComponent,
+ GovukErrorSummaryComponent,
+ GovukHeadingWithCaptionComponent,
+ GovukRadioComponent,
+ GovukRadiosItemComponent,
+ ],
+ templateUrl: './fines-acc-enf-collo-change-form.component.html',
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ standalone: true,
+})
+export class FinesAccEnfColloChangeFormComponent extends AbstractFormBaseComponent implements OnInit {
+ protected override fieldErrors: IAbstractFormBaseFieldErrors = {
+ ...FINES_ACC_ENF_COLLO_CHANGE_FIELD_ERRORS,
+ };
+ protected override formSubmit = new EventEmitter>();
+ public override formControlErrorMessages: IAbstractFormControlErrorMessage = {};
+ public readonly defendantAccRoutingPaths = FINES_ACC_DEFENDANT_ROUTING_PATHS;
+
+ @Input({ required: true }) partyName!: string;
+ @Input({ required: true }) accountNumber!: string;
+
+ /**
+ * Creates the form group for changing the Collection Order status.
+ */
+ private setupForm(): void {
+ this.form = new FormGroup({
+ facc_enf_collection_order_made: new FormControl(null, Validators.required),
+ });
+ }
+
+ /**
+ * Initialises the form before running the shared abstract form setup.
+ */
+ public override ngOnInit(): void {
+ this.setupForm();
+ super.ngOnInit();
+ }
+}
diff --git a/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.html b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.html
new file mode 100644
index 0000000000..2a44580914
--- /dev/null
+++ b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.html
@@ -0,0 +1,8 @@
+
diff --git a/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.spec.ts b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.spec.ts
new file mode 100644
index 0000000000..c0bb972f76
--- /dev/null
+++ b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.spec.ts
@@ -0,0 +1,185 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ActivatedRoute } from '@angular/router';
+import { signal } from '@angular/core';
+import { beforeEach, describe, expect, it, vi } from 'vitest';
+import { of, throwError } from 'rxjs';
+import { FinesAccEnfColloChangeComponent } from './fines-acc-enf-collo-change.component';
+import { FinesAccountStore } from '../stores/fines-acc.store';
+import { FinesAccPayloadService } from '../services/fines-acc-payload.service';
+import { OpalFines } from '../../services/opal-fines-service/opal-fines.service';
+import { UtilsService } from '@hmcts/opal-frontend-common/services/utils-service';
+import { FINES_ACC_DEFENDANT_ROUTING_PATHS } from '../routing/constants/fines-acc-defendant-routing-paths.constant';
+import { FinesAccountStoreType } from '../types/fines-account-store.type';
+
+describe('FinesAccEnfColloChangeComponent', () => {
+ let component: FinesAccEnfColloChangeComponent;
+ let fixture: ComponentFixture;
+ let mockRoute: ActivatedRoute;
+ let mockAccountStore: Pick<
+ FinesAccountStoreType,
+ 'getAccountNumber' | 'party_name' | 'account_id' | 'base_version' | 'business_unit_id' | 'setSuccessMessage'
+ >;
+ let mockPayloadService: Pick;
+ let mockOpalFinesService: Pick;
+ let mockUtilsService: Pick;
+
+ beforeEach(async () => {
+ mockRoute = {
+ snapshot: {
+ data: {
+ title: 'Change Collection Order status',
+ },
+ },
+ } as unknown as ActivatedRoute;
+
+ mockAccountStore = {
+ getAccountNumber: signal('177A'),
+ party_name: signal('Mr Robert THOMSON'),
+ account_id: signal(1001),
+ base_version: signal('1'),
+ business_unit_id: signal('2002'),
+ setSuccessMessage: vi.fn(),
+ };
+
+ mockPayloadService = {
+ buildCollectionOrderPayload: vi.fn().mockImplementation((collectionOrder) => ({
+ collection_order: collectionOrder,
+ })),
+ };
+
+ mockOpalFinesService = {
+ patchDefendantAccount: vi.fn().mockReturnValue(of({})),
+ clearCache: vi.fn(),
+ };
+
+ mockUtilsService = {
+ scrollToTop: vi.fn(),
+ };
+
+ await TestBed.configureTestingModule({
+ imports: [FinesAccEnfColloChangeComponent],
+ providers: [
+ { provide: ActivatedRoute, useValue: mockRoute },
+ { provide: FinesAccountStore, useValue: mockAccountStore },
+ { provide: FinesAccPayloadService, useValue: mockPayloadService },
+ { provide: OpalFines, useValue: mockOpalFinesService },
+ { provide: UtilsService, useValue: mockUtilsService },
+ ],
+ }).compileComponents();
+
+ fixture = TestBed.createComponent(FinesAccEnfColloChangeComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should expose page data from the route and store', () => {
+ expect(component.accountNumber).toBe('177A');
+ expect(component.partyName).toBe('Mr Robert THOMSON');
+ });
+
+ it('should patch and navigate on success when the selection changes', () => {
+ const routerNavigateSpy = vi.spyOn(component as never, 'routerNavigate');
+
+ component.handleSubmit({
+ formData: {
+ facc_enf_collection_order_made: true,
+ },
+ nestedFlow: false,
+ });
+
+ expect(mockPayloadService.buildCollectionOrderPayload).toHaveBeenCalledWith({
+ collection_order_date: '',
+ collection_order_flag: true,
+ });
+ expect(mockOpalFinesService.patchDefendantAccount).toHaveBeenCalledWith(
+ 1001,
+ {
+ collection_order: {
+ collection_order_date: '',
+ collection_order_flag: true,
+ },
+ },
+ '1',
+ '2002',
+ );
+ expect(mockOpalFinesService.clearCache).toHaveBeenCalledWith('defendantAccountEnforcementCache$');
+ expect(mockAccountStore.setSuccessMessage).toHaveBeenCalledWith('Collection Order status changed');
+ expect(routerNavigateSpy).toHaveBeenCalledWith(
+ FINES_ACC_DEFENDANT_ROUTING_PATHS.children.details,
+ false,
+ undefined,
+ null,
+ 'enforcement',
+ );
+ });
+
+ it('should scroll to top on submit error', () => {
+ mockOpalFinesService.patchDefendantAccount = vi.fn().mockReturnValue(throwError(() => new Error('fail')));
+ const routerNavigateSpy = vi.spyOn(component as never, 'routerNavigate');
+
+ component.handleSubmit({
+ formData: {
+ facc_enf_collection_order_made: true,
+ },
+ nestedFlow: false,
+ });
+
+ expect(mockUtilsService.scrollToTop).toHaveBeenCalled();
+ expect(routerNavigateSpy).not.toHaveBeenCalled();
+ });
+
+ it('should send an empty collection order date when selecting yes', () => {
+ component.handleSubmit({
+ formData: {
+ facc_enf_collection_order_made: true,
+ },
+ nestedFlow: false,
+ });
+
+ expect(mockPayloadService.buildCollectionOrderPayload).toHaveBeenCalledWith({
+ collection_order_date: '',
+ collection_order_flag: true,
+ });
+ });
+
+ it('should return early when no collection order selection is made', () => {
+ const routerNavigateSpy = vi.spyOn(component as never, 'routerNavigate');
+
+ component.handleSubmit({
+ formData: {
+ facc_enf_collection_order_made: null,
+ },
+ nestedFlow: false,
+ });
+
+ expect(mockPayloadService.buildCollectionOrderPayload).not.toHaveBeenCalled();
+ expect(mockOpalFinesService.patchDefendantAccount).not.toHaveBeenCalled();
+ expect(routerNavigateSpy).not.toHaveBeenCalled();
+ });
+
+ it('should send an empty collection order date when selecting no', () => {
+ component.handleSubmit({
+ formData: {
+ facc_enf_collection_order_made: false,
+ },
+ nestedFlow: false,
+ });
+
+ expect(mockPayloadService.buildCollectionOrderPayload).toHaveBeenCalledWith({
+ collection_order_date: '',
+ collection_order_flag: false,
+ });
+ });
+
+ it('should update unsaved changes state', () => {
+ component.handleUnsavedChanges(true);
+ expect((component).stateUnsavedChanges).toBe(true);
+
+ component.handleUnsavedChanges(false);
+ expect((component).stateUnsavedChanges).toBe(false);
+ });
+});
diff --git a/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.ts b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.ts
new file mode 100644
index 0000000000..9055330fae
--- /dev/null
+++ b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.ts
@@ -0,0 +1,99 @@
+import { ChangeDetectionStrategy, Component, OnDestroy, inject } from '@angular/core';
+import { AbstractFormParentBaseComponent } from '@hmcts/opal-frontend-common/components/abstract/abstract-form-parent-base';
+import { catchError, EMPTY, Subject, takeUntil } from 'rxjs';
+import { UtilsService } from '@hmcts/opal-frontend-common/services/utils-service';
+import { IAbstractFormBaseForm } from '@hmcts/opal-frontend-common/components/abstract/abstract-form-base/interfaces';
+import { FinesAccountStore } from '../stores/fines-acc.store';
+import { FinesAccPayloadService } from '../services/fines-acc-payload.service';
+import { OpalFines } from '../../services/opal-fines-service/opal-fines.service';
+import { FINES_ACC_DEFENDANT_ROUTING_PATHS } from '../routing/constants/fines-acc-defendant-routing-paths.constant';
+import { IFinesAccEnfColloChangeFormState } from './interfaces/fines-acc-enf-collo-change-form-state.interface';
+import { FinesAccEnfColloChangeFormComponent } from './fines-acc-enf-collo-change-form/fines-acc-enf-collo-change-form.component';
+
+@Component({
+ selector: 'app-fines-acc-enf-collo-change',
+ templateUrl: './fines-acc-enf-collo-change.component.html',
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ standalone: true,
+ imports: [FinesAccEnfColloChangeFormComponent],
+})
+export class FinesAccEnfColloChangeComponent extends AbstractFormParentBaseComponent implements OnDestroy {
+ private readonly ngUnsubscribe = new Subject();
+ private readonly finesAccStore = inject(FinesAccountStore);
+ private readonly finesAccPayloadService = inject(FinesAccPayloadService);
+ private readonly opalFinesService = inject(OpalFines);
+ private readonly utilsService = inject(UtilsService);
+ private readonly finesDefendantRoutingPaths = FINES_ACC_DEFENDANT_ROUTING_PATHS;
+
+ public readonly accountNumber = this.finesAccStore.getAccountNumber() ?? '';
+ public readonly partyName = this.finesAccStore.party_name() ?? '';
+
+ /**
+ * Navigates back to the enforcement tab and optionally sets a success message.
+ *
+ * @param setSuccessMessage Whether to set the success banner before navigation.
+ */
+ private navigateToEnforcementTab(setSuccessMessage = false): void {
+ this.stateUnsavedChanges = false;
+
+ if (setSuccessMessage) {
+ this.finesAccStore.setSuccessMessage('Collection Order status changed');
+ }
+
+ this.routerNavigate(this.finesDefendantRoutingPaths.children.details, false, undefined, null, 'enforcement');
+ }
+
+ /**
+ * Submits the selected Collection Order status for the current account.
+ *
+ * @param form The form payload emitted by the child form component.
+ */
+ public handleSubmit(form: IAbstractFormBaseForm): void {
+ const collectionOrderFlag = form.formData.facc_enf_collection_order_made;
+
+ if (collectionOrderFlag === null) {
+ return;
+ }
+
+ const payload = this.finesAccPayloadService.buildCollectionOrderPayload({
+ collection_order_date: '',
+ collection_order_flag: collectionOrderFlag,
+ });
+
+ this.opalFinesService
+ .patchDefendantAccount(
+ this.finesAccStore.account_id()!,
+ payload,
+ this.finesAccStore.base_version()!,
+ this.finesAccStore.business_unit_id()!,
+ )
+ .pipe(
+ catchError(() => {
+ this.utilsService.scrollToTop();
+ return EMPTY;
+ }),
+ takeUntil(this.ngUnsubscribe),
+ )
+ .subscribe(() => {
+ this.opalFinesService.clearCache('defendantAccountEnforcementCache$');
+ this.navigateToEnforcementTab(true);
+ });
+ }
+
+ /**
+ * Updates the page-level unsaved changes state from the child form.
+ *
+ * @param unsavedChanges Whether the form currently has unsaved changes.
+ */
+ public handleUnsavedChanges(unsavedChanges: boolean): void {
+ this.stateUnsavedChanges = unsavedChanges;
+ }
+
+ /**
+ * Completes the teardown notifier used by active subscriptions.
+ */
+ public ngOnDestroy(): void {
+ this.ngUnsubscribe.next();
+ this.ngUnsubscribe.complete();
+ }
+}
diff --git a/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/interfaces/fines-acc-enf-collo-change-field-errors.interface.ts b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/interfaces/fines-acc-enf-collo-change-field-errors.interface.ts
new file mode 100644
index 0000000000..2b8d8aaed3
--- /dev/null
+++ b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/interfaces/fines-acc-enf-collo-change-field-errors.interface.ts
@@ -0,0 +1,8 @@
+import {
+ IAbstractFormBaseFieldError,
+ IAbstractFormBaseFieldErrors,
+} from '@hmcts/opal-frontend-common/components/abstract/abstract-form-base/interfaces';
+
+export interface IFinesAccEnfColloChangeFieldErrors extends IAbstractFormBaseFieldErrors {
+ facc_enf_collection_order_made: IAbstractFormBaseFieldError;
+}
diff --git a/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/interfaces/fines-acc-enf-collo-change-form-state.interface.ts b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/interfaces/fines-acc-enf-collo-change-form-state.interface.ts
new file mode 100644
index 0000000000..6326f61f3d
--- /dev/null
+++ b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/interfaces/fines-acc-enf-collo-change-form-state.interface.ts
@@ -0,0 +1,3 @@
+export interface IFinesAccEnfColloChangeFormState {
+ facc_enf_collection_order_made: boolean | null;
+}
diff --git a/src/app/flows/fines/fines-acc/routing/fines-acc.routes.ts b/src/app/flows/fines/fines-acc/routing/fines-acc.routes.ts
index e8420f4f79..a7c2c738bd 100644
--- a/src/app/flows/fines/fines-acc/routing/fines-acc.routes.ts
+++ b/src/app/flows/fines/fines-acc/routing/fines-acc.routes.ts
@@ -194,6 +194,22 @@ export const routing: Routes = [
enforcersRefData: fetchEnforcersResolver,
},
},
+ {
+ path: `${FINES_ACC_DEFENDANT_ROUTING_PATHS.children.enforcement}/collection-order/change`,
+ loadComponent: () =>
+ import('../fines-acc-enf-collo-change/fines-acc-enf-collo-change.component').then(
+ (c) => c.FinesAccEnfColloChangeComponent,
+ ),
+ canActivate: [routePermissionsGuard, finesAccStateGuard],
+ canDeactivate: [canDeactivateGuard],
+ data: {
+ routePermissionId: [accRootPermissionIds['account-maintenance']],
+ title: 'Change Collection Order status',
+ },
+ resolve: {
+ title: TitleResolver,
+ },
+ },
],
},
{
diff --git a/src/app/flows/fines/fines-acc/services/fines-acc-payload.service.spec.ts b/src/app/flows/fines/fines-acc/services/fines-acc-payload.service.spec.ts
index 74a28b2b30..0fd339574e 100644
--- a/src/app/flows/fines/fines-acc/services/fines-acc-payload.service.spec.ts
+++ b/src/app/flows/fines/fines-acc/services/fines-acc-payload.service.spec.ts
@@ -545,6 +545,7 @@ describe('FinesAccPayloadService', () => {
free_text_note_2: 'Updated note 2',
free_text_note_3: 'Updated note 3',
},
+ collection_order: null,
enforcement_override: null,
});
});
@@ -566,10 +567,25 @@ describe('FinesAccPayloadService', () => {
free_text_note_2: null,
free_text_note_3: null,
},
+ collection_order: null,
enforcement_override: null,
});
});
+ it('should build collection order payload correctly', () => {
+ const result = service.buildCollectionOrderPayload({
+ collection_order_date: '2025-12-10',
+ collection_order_flag: true,
+ });
+
+ expect(result).toEqual({
+ collection_order: {
+ collection_order_date: '2025-12-10',
+ collection_order_flag: true,
+ },
+ });
+ });
+
it('should transform payload using the transformation service', () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
vi.spyOn(service['transformationService'], 'transformObjectValues').mockImplementation(
diff --git a/src/app/flows/fines/fines-acc/services/fines-acc-payload.service.ts b/src/app/flows/fines/fines-acc/services/fines-acc-payload.service.ts
index 06959f87ef..53e58fc26c 100644
--- a/src/app/flows/fines/fines-acc/services/fines-acc-payload.service.ts
+++ b/src/app/flows/fines/fines-acc/services/fines-acc-payload.service.ts
@@ -27,6 +27,7 @@ import { buildAccountPartyFromFormState } from './utils/fines-acc-payload-build-
import { IOpalFinesAccountMinorCreditorDetailsHeader } from '../fines-acc-minor-creditor-details/interfaces/fines-acc-minor-creditor-details-header.interface';
import { IFinesAccEnfOverrideAddChangeFormState } from '../fines-acc-enf-override-add-change/interfaces/fines-acc-enf-override-add-change-form-state.interface';
import { OPAL_FINES_DEFENDANT_ACCOUNT_PATCH_PAYLOAD_DEFAULTS } from '../../services/opal-fines-service/constants/opal-fines-defendant-account-patch-payload-defaults.constant';
+import { IOpalFinesUpdateDefendantAccountCollectionOrder } from '@services/fines/opal-fines-service/interfaces/opal-fines-update-defendant-account-collection-order.interface';
@Injectable({
providedIn: 'root',
@@ -173,6 +174,21 @@ export class FinesAccPayloadService {
};
}
+ /**
+ * Transforms the given collection order object into an update payload
+ * for the defendant account API.
+ *
+ * @param collectionOrder - The collection order data to patch
+ * @returns The transformed payload for updating the defendant account
+ */
+ public buildCollectionOrderPayload(
+ collectionOrder: IOpalFinesUpdateDefendantAccountCollectionOrder,
+ ): IOpalFinesUpdateDefendantAccountPayload {
+ return {
+ collection_order: collectionOrder,
+ };
+ }
+
/**
* Transforms the given IFinesAccEnfOverrideAddChangeFormState into an update payload
* for the defendant account API.
diff --git a/src/app/flows/fines/services/opal-fines-service/constants/opal-fines-defendant-account-patch-payload-defaults.constant.ts b/src/app/flows/fines/services/opal-fines-service/constants/opal-fines-defendant-account-patch-payload-defaults.constant.ts
index b9fb0ce6fd..51476bb4b1 100644
--- a/src/app/flows/fines/services/opal-fines-service/constants/opal-fines-defendant-account-patch-payload-defaults.constant.ts
+++ b/src/app/flows/fines/services/opal-fines-service/constants/opal-fines-defendant-account-patch-payload-defaults.constant.ts
@@ -2,5 +2,6 @@ import { IOpalFinesUpdateDefendantAccountPayload } from '../interfaces/opal-fine
export const OPAL_FINES_DEFENDANT_ACCOUNT_PATCH_PAYLOAD_DEFAULTS: IOpalFinesUpdateDefendantAccountPayload = {
comment_and_notes: null,
+ collection_order: null,
enforcement_override: null,
};
diff --git a/src/app/flows/fines/services/opal-fines-service/interfaces/opal-fines-update-defendant-account-collection-order.interface.ts b/src/app/flows/fines/services/opal-fines-service/interfaces/opal-fines-update-defendant-account-collection-order.interface.ts
new file mode 100644
index 0000000000..9caffac77b
--- /dev/null
+++ b/src/app/flows/fines/services/opal-fines-service/interfaces/opal-fines-update-defendant-account-collection-order.interface.ts
@@ -0,0 +1,4 @@
+export interface IOpalFinesUpdateDefendantAccountCollectionOrder {
+ collection_order_date: string;
+ collection_order_flag: boolean;
+}
diff --git a/src/app/flows/fines/services/opal-fines-service/interfaces/opal-fines-update-defendant-account.interface.ts b/src/app/flows/fines/services/opal-fines-service/interfaces/opal-fines-update-defendant-account.interface.ts
index 09d92d1f52..0b98d5f216 100644
--- a/src/app/flows/fines/services/opal-fines-service/interfaces/opal-fines-update-defendant-account.interface.ts
+++ b/src/app/flows/fines/services/opal-fines-service/interfaces/opal-fines-update-defendant-account.interface.ts
@@ -1,10 +1,12 @@
import { IOpalFinesUpdateDefendantAccountCommentsNotes } from './opal-fines-update-defendant-account-comments-notes.interface';
+import { IOpalFinesUpdateDefendantAccountCollectionOrder } from './opal-fines-update-defendant-account-collection-order.interface';
import { IOpalFinesUpdateDefendantAccountEnforcementOverride } from './opal-fines-update-defendant-account-enforcement-override.interface';
/**
* Interface for the payload to update a defendant account *Subject to change
*/
export interface IOpalFinesUpdateDefendantAccountPayload {
- comment_and_notes: IOpalFinesUpdateDefendantAccountCommentsNotes | null;
- enforcement_override: IOpalFinesUpdateDefendantAccountEnforcementOverride | null;
+ comment_and_notes?: IOpalFinesUpdateDefendantAccountCommentsNotes | null;
+ collection_order?: IOpalFinesUpdateDefendantAccountCollectionOrder | null;
+ enforcement_override?: IOpalFinesUpdateDefendantAccountEnforcementOverride | null;
}
From 618ccc24681c0c0d6e0252a360b4c76e8946ba30 Mon Sep 17 00:00:00 2001
From: Arnab subedi <147511052+Arnabsubedi233@users.noreply.github.com>
Date: Wed, 1 Apr 2026 11:18:29 +0100
Subject: [PATCH 2/8] linting
---
.../fines-acc-enf-collo-change.component.spec.ts | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.spec.ts b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.spec.ts
index c0bb972f76..4f2258ad75 100644
--- a/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.spec.ts
+++ b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.spec.ts
@@ -177,9 +177,9 @@ describe('FinesAccEnfColloChangeComponent', () => {
it('should update unsaved changes state', () => {
component.handleUnsavedChanges(true);
- expect((component).stateUnsavedChanges).toBe(true);
+ expect(component.stateUnsavedChanges).toBe(true);
component.handleUnsavedChanges(false);
- expect((component).stateUnsavedChanges).toBe(false);
+ expect(component.stateUnsavedChanges).toBe(false);
});
});
From fa9ada89d8141fd4e9ac97d318380a9726fdd631 Mon Sep 17 00:00:00 2001
From: Arnab subedi <147511052+Arnabsubedi233@users.noreply.github.com>
Date: Wed, 1 Apr 2026 11:30:20 +0100
Subject: [PATCH 3/8] small refactoring
---
...nes-acc-enf-collo-change.component.spec.ts | 34 ++++++++-----------
.../fines-acc-enf-collo-change.component.ts | 11 +-----
.../fines-acc-payload.service.spec.ts | 8 +++--
.../services/fines-acc-payload.service.ts | 15 ++++++--
4 files changed, 32 insertions(+), 36 deletions(-)
diff --git a/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.spec.ts b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.spec.ts
index 4f2258ad75..4067002e86 100644
--- a/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.spec.ts
+++ b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.spec.ts
@@ -42,8 +42,11 @@ describe('FinesAccEnfColloChangeComponent', () => {
};
mockPayloadService = {
- buildCollectionOrderPayload: vi.fn().mockImplementation((collectionOrder) => ({
- collection_order: collectionOrder,
+ buildCollectionOrderPayload: vi.fn().mockImplementation((form) => ({
+ collection_order: {
+ collection_order_date: '',
+ collection_order_flag: form.formData.facc_enf_collection_order_made,
+ },
})),
};
@@ -92,8 +95,10 @@ describe('FinesAccEnfColloChangeComponent', () => {
});
expect(mockPayloadService.buildCollectionOrderPayload).toHaveBeenCalledWith({
- collection_order_date: '',
- collection_order_flag: true,
+ formData: {
+ facc_enf_collection_order_made: true,
+ },
+ nestedFlow: false,
});
expect(mockOpalFinesService.patchDefendantAccount).toHaveBeenCalledWith(
1001,
@@ -141,24 +146,11 @@ describe('FinesAccEnfColloChangeComponent', () => {
});
expect(mockPayloadService.buildCollectionOrderPayload).toHaveBeenCalledWith({
- collection_order_date: '',
- collection_order_flag: true,
- });
- });
-
- it('should return early when no collection order selection is made', () => {
- const routerNavigateSpy = vi.spyOn(component as never, 'routerNavigate');
-
- component.handleSubmit({
formData: {
- facc_enf_collection_order_made: null,
+ facc_enf_collection_order_made: true,
},
nestedFlow: false,
});
-
- expect(mockPayloadService.buildCollectionOrderPayload).not.toHaveBeenCalled();
- expect(mockOpalFinesService.patchDefendantAccount).not.toHaveBeenCalled();
- expect(routerNavigateSpy).not.toHaveBeenCalled();
});
it('should send an empty collection order date when selecting no', () => {
@@ -170,8 +162,10 @@ describe('FinesAccEnfColloChangeComponent', () => {
});
expect(mockPayloadService.buildCollectionOrderPayload).toHaveBeenCalledWith({
- collection_order_date: '',
- collection_order_flag: false,
+ formData: {
+ facc_enf_collection_order_made: false,
+ },
+ nestedFlow: false,
});
});
diff --git a/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.ts b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.ts
index 9055330fae..ae47ef5dd8 100644
--- a/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.ts
+++ b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.ts
@@ -49,16 +49,7 @@ export class FinesAccEnfColloChangeComponent extends AbstractFormParentBaseCompo
* @param form The form payload emitted by the child form component.
*/
public handleSubmit(form: IAbstractFormBaseForm): void {
- const collectionOrderFlag = form.formData.facc_enf_collection_order_made;
-
- if (collectionOrderFlag === null) {
- return;
- }
-
- const payload = this.finesAccPayloadService.buildCollectionOrderPayload({
- collection_order_date: '',
- collection_order_flag: collectionOrderFlag,
- });
+ const payload = this.finesAccPayloadService.buildCollectionOrderPayload(form);
this.opalFinesService
.patchDefendantAccount(
diff --git a/src/app/flows/fines/fines-acc/services/fines-acc-payload.service.spec.ts b/src/app/flows/fines/fines-acc/services/fines-acc-payload.service.spec.ts
index 0fd339574e..5828c21e4e 100644
--- a/src/app/flows/fines/fines-acc/services/fines-acc-payload.service.spec.ts
+++ b/src/app/flows/fines/fines-acc/services/fines-acc-payload.service.spec.ts
@@ -574,13 +574,15 @@ describe('FinesAccPayloadService', () => {
it('should build collection order payload correctly', () => {
const result = service.buildCollectionOrderPayload({
- collection_order_date: '2025-12-10',
- collection_order_flag: true,
+ formData: {
+ facc_enf_collection_order_made: true,
+ },
+ nestedFlow: false,
});
expect(result).toEqual({
collection_order: {
- collection_order_date: '2025-12-10',
+ collection_order_date: '',
collection_order_flag: true,
},
});
diff --git a/src/app/flows/fines/fines-acc/services/fines-acc-payload.service.ts b/src/app/flows/fines/fines-acc/services/fines-acc-payload.service.ts
index 53e58fc26c..3911095312 100644
--- a/src/app/flows/fines/fines-acc/services/fines-acc-payload.service.ts
+++ b/src/app/flows/fines/fines-acc/services/fines-acc-payload.service.ts
@@ -28,6 +28,8 @@ import { IOpalFinesAccountMinorCreditorDetailsHeader } from '../fines-acc-minor-
import { IFinesAccEnfOverrideAddChangeFormState } from '../fines-acc-enf-override-add-change/interfaces/fines-acc-enf-override-add-change-form-state.interface';
import { OPAL_FINES_DEFENDANT_ACCOUNT_PATCH_PAYLOAD_DEFAULTS } from '../../services/opal-fines-service/constants/opal-fines-defendant-account-patch-payload-defaults.constant';
import { IOpalFinesUpdateDefendantAccountCollectionOrder } from '@services/fines/opal-fines-service/interfaces/opal-fines-update-defendant-account-collection-order.interface';
+import { IAbstractFormBaseForm } from '@hmcts/opal-frontend-common/components/abstract/abstract-form-base/interfaces';
+import { IFinesAccEnfColloChangeFormState } from '../fines-acc-enf-collo-change/interfaces/fines-acc-enf-collo-change-form-state.interface';
@Injectable({
providedIn: 'root',
@@ -175,15 +177,22 @@ export class FinesAccPayloadService {
}
/**
- * Transforms the given collection order object into an update payload
+ * Transforms the given collection order form into an update payload
* for the defendant account API.
*
- * @param collectionOrder - The collection order data to patch
+ * @param form - The submitted collection order form
* @returns The transformed payload for updating the defendant account
*/
public buildCollectionOrderPayload(
- collectionOrder: IOpalFinesUpdateDefendantAccountCollectionOrder,
+ form: IAbstractFormBaseForm,
): IOpalFinesUpdateDefendantAccountPayload {
+ const collectionOrderFlag = form.formData.facc_enf_collection_order_made as boolean;
+
+ const collectionOrder: IOpalFinesUpdateDefendantAccountCollectionOrder = {
+ collection_order_date: '',
+ collection_order_flag: collectionOrderFlag,
+ };
+
return {
collection_order: collectionOrder,
};
From 8c56fe9f318b292a3f05e27c37848119522d0d1a Mon Sep 17 00:00:00 2001
From: Arnab subedi <147511052+Arnabsubedi233@users.noreply.github.com>
Date: Wed, 1 Apr 2026 11:53:28 +0100
Subject: [PATCH 4/8] comment response
---
.../fines-acc-enf-collo-change-routing-titles.constant.ts | 6 ++++++
.../fines-acc-enf-collo-change-success-message.constant.ts | 1 +
.../fines-acc-enf-collo-change.component.spec.ts | 7 ++++---
.../fines-acc-enf-collo-change.component.ts | 3 ++-
src/app/flows/fines/fines-acc/routing/fines-acc.routes.ts | 3 ++-
...fines-acc-collection-order-payload-defaults.constant.ts | 6 ++++++
.../fines-acc/services/fines-acc-payload.service.spec.ts | 2 +-
.../fines/fines-acc/services/fines-acc-payload.service.ts | 3 ++-
...-update-defendant-account-collection-order.interface.ts | 4 ++--
9 files changed, 26 insertions(+), 9 deletions(-)
create mode 100644 src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/constants/fines-acc-enf-collo-change-routing-titles.constant.ts
create mode 100644 src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/constants/fines-acc-enf-collo-change-success-message.constant.ts
create mode 100644 src/app/flows/fines/fines-acc/services/constants/fines-acc-collection-order-payload-defaults.constant.ts
diff --git a/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/constants/fines-acc-enf-collo-change-routing-titles.constant.ts b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/constants/fines-acc-enf-collo-change-routing-titles.constant.ts
new file mode 100644
index 0000000000..f0798559fc
--- /dev/null
+++ b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/constants/fines-acc-enf-collo-change-routing-titles.constant.ts
@@ -0,0 +1,6 @@
+export const FINES_ACC_ENF_COLLO_CHANGE_ROUTING_TITLES = {
+ root: 'Collection Order',
+ children: {
+ change: 'Change Collection Order status',
+ },
+};
diff --git a/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/constants/fines-acc-enf-collo-change-success-message.constant.ts b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/constants/fines-acc-enf-collo-change-success-message.constant.ts
new file mode 100644
index 0000000000..512d2013a6
--- /dev/null
+++ b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/constants/fines-acc-enf-collo-change-success-message.constant.ts
@@ -0,0 +1 @@
+export const FINES_ACC_ENF_COLLO_CHANGE_SUCCESS_MESSAGE = 'Collection Order status changed';
diff --git a/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.spec.ts b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.spec.ts
index 4067002e86..72ed639c0f 100644
--- a/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.spec.ts
+++ b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.spec.ts
@@ -10,6 +10,7 @@ import { OpalFines } from '../../services/opal-fines-service/opal-fines.service'
import { UtilsService } from '@hmcts/opal-frontend-common/services/utils-service';
import { FINES_ACC_DEFENDANT_ROUTING_PATHS } from '../routing/constants/fines-acc-defendant-routing-paths.constant';
import { FinesAccountStoreType } from '../types/fines-account-store.type';
+import { FINES_ACC_ENF_COLLO_CHANGE_SUCCESS_MESSAGE } from './constants/fines-acc-enf-collo-change-success-message.constant';
describe('FinesAccEnfColloChangeComponent', () => {
let component: FinesAccEnfColloChangeComponent;
@@ -44,7 +45,7 @@ describe('FinesAccEnfColloChangeComponent', () => {
mockPayloadService = {
buildCollectionOrderPayload: vi.fn().mockImplementation((form) => ({
collection_order: {
- collection_order_date: '',
+ collection_order_date: null,
collection_order_flag: form.formData.facc_enf_collection_order_made,
},
})),
@@ -104,7 +105,7 @@ describe('FinesAccEnfColloChangeComponent', () => {
1001,
{
collection_order: {
- collection_order_date: '',
+ collection_order_date: null,
collection_order_flag: true,
},
},
@@ -112,7 +113,7 @@ describe('FinesAccEnfColloChangeComponent', () => {
'2002',
);
expect(mockOpalFinesService.clearCache).toHaveBeenCalledWith('defendantAccountEnforcementCache$');
- expect(mockAccountStore.setSuccessMessage).toHaveBeenCalledWith('Collection Order status changed');
+ expect(mockAccountStore.setSuccessMessage).toHaveBeenCalledWith(FINES_ACC_ENF_COLLO_CHANGE_SUCCESS_MESSAGE);
expect(routerNavigateSpy).toHaveBeenCalledWith(
FINES_ACC_DEFENDANT_ROUTING_PATHS.children.details,
false,
diff --git a/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.ts b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.ts
index ae47ef5dd8..2de65ea1f7 100644
--- a/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.ts
+++ b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.ts
@@ -9,6 +9,7 @@ import { OpalFines } from '../../services/opal-fines-service/opal-fines.service'
import { FINES_ACC_DEFENDANT_ROUTING_PATHS } from '../routing/constants/fines-acc-defendant-routing-paths.constant';
import { IFinesAccEnfColloChangeFormState } from './interfaces/fines-acc-enf-collo-change-form-state.interface';
import { FinesAccEnfColloChangeFormComponent } from './fines-acc-enf-collo-change-form/fines-acc-enf-collo-change-form.component';
+import { FINES_ACC_ENF_COLLO_CHANGE_SUCCESS_MESSAGE } from './constants/fines-acc-enf-collo-change-success-message.constant';
@Component({
selector: 'app-fines-acc-enf-collo-change',
@@ -37,7 +38,7 @@ export class FinesAccEnfColloChangeComponent extends AbstractFormParentBaseCompo
this.stateUnsavedChanges = false;
if (setSuccessMessage) {
- this.finesAccStore.setSuccessMessage('Collection Order status changed');
+ this.finesAccStore.setSuccessMessage(FINES_ACC_ENF_COLLO_CHANGE_SUCCESS_MESSAGE);
}
this.routerNavigate(this.finesDefendantRoutingPaths.children.details, false, undefined, null, 'enforcement');
diff --git a/src/app/flows/fines/fines-acc/routing/fines-acc.routes.ts b/src/app/flows/fines/fines-acc/routing/fines-acc.routes.ts
index a7c2c738bd..c88185e1fa 100644
--- a/src/app/flows/fines/fines-acc/routing/fines-acc.routes.ts
+++ b/src/app/flows/fines/fines-acc/routing/fines-acc.routes.ts
@@ -22,6 +22,7 @@ import { fetchLocalJusticeAreasResolver } from '../../routing/resolvers/fetch-re
import { fetchEnforcersResolver } from '../../routing/resolvers/fetch-results-with-params-resolver/fetch-enforcers-resolver';
import { FINES_ACC_ENF_OVERRIDE_ADD_CHANGE_ROUTING_TITLES } from '../fines-acc-enf-override-add-change/constants/fines-acc-enf-override-add-change-routing-titles.constant';
import { FINES_ACC_ENF_OVERRIDE_ADD_CHANGE_ROUTING_PATHS } from '../fines-acc-enf-override-add-change/constants/fines-acc-enf-override-add-change-routing-paths.constant';
+import { FINES_ACC_ENF_COLLO_CHANGE_ROUTING_TITLES } from '../fines-acc-enf-collo-change/constants/fines-acc-enf-collo-change-routing-titles.constant';
const accRootPermissionIds = FINES_PERMISSIONS;
@@ -204,7 +205,7 @@ export const routing: Routes = [
canDeactivate: [canDeactivateGuard],
data: {
routePermissionId: [accRootPermissionIds['account-maintenance']],
- title: 'Change Collection Order status',
+ title: FINES_ACC_ENF_COLLO_CHANGE_ROUTING_TITLES.children.change,
},
resolve: {
title: TitleResolver,
diff --git a/src/app/flows/fines/fines-acc/services/constants/fines-acc-collection-order-payload-defaults.constant.ts b/src/app/flows/fines/fines-acc/services/constants/fines-acc-collection-order-payload-defaults.constant.ts
new file mode 100644
index 0000000000..a399aff422
--- /dev/null
+++ b/src/app/flows/fines/fines-acc/services/constants/fines-acc-collection-order-payload-defaults.constant.ts
@@ -0,0 +1,6 @@
+import { IOpalFinesUpdateDefendantAccountCollectionOrder } from '@services/fines/opal-fines-service/interfaces/opal-fines-update-defendant-account-collection-order.interface';
+
+export const FINES_ACC_COLLECTION_ORDER_PAYLOAD_DEFAULTS: IOpalFinesUpdateDefendantAccountCollectionOrder = {
+ collection_order_date: null,
+ collection_order_flag: null,
+};
diff --git a/src/app/flows/fines/fines-acc/services/fines-acc-payload.service.spec.ts b/src/app/flows/fines/fines-acc/services/fines-acc-payload.service.spec.ts
index 5828c21e4e..046aa3afad 100644
--- a/src/app/flows/fines/fines-acc/services/fines-acc-payload.service.spec.ts
+++ b/src/app/flows/fines/fines-acc/services/fines-acc-payload.service.spec.ts
@@ -582,7 +582,7 @@ describe('FinesAccPayloadService', () => {
expect(result).toEqual({
collection_order: {
- collection_order_date: '',
+ collection_order_date: null,
collection_order_flag: true,
},
});
diff --git a/src/app/flows/fines/fines-acc/services/fines-acc-payload.service.ts b/src/app/flows/fines/fines-acc/services/fines-acc-payload.service.ts
index 3911095312..32358d5e9a 100644
--- a/src/app/flows/fines/fines-acc/services/fines-acc-payload.service.ts
+++ b/src/app/flows/fines/fines-acc/services/fines-acc-payload.service.ts
@@ -30,6 +30,7 @@ import { OPAL_FINES_DEFENDANT_ACCOUNT_PATCH_PAYLOAD_DEFAULTS } from '../../servi
import { IOpalFinesUpdateDefendantAccountCollectionOrder } from '@services/fines/opal-fines-service/interfaces/opal-fines-update-defendant-account-collection-order.interface';
import { IAbstractFormBaseForm } from '@hmcts/opal-frontend-common/components/abstract/abstract-form-base/interfaces';
import { IFinesAccEnfColloChangeFormState } from '../fines-acc-enf-collo-change/interfaces/fines-acc-enf-collo-change-form-state.interface';
+import { FINES_ACC_COLLECTION_ORDER_PAYLOAD_DEFAULTS } from './constants/fines-acc-collection-order-payload-defaults.constant';
@Injectable({
providedIn: 'root',
@@ -189,7 +190,7 @@ export class FinesAccPayloadService {
const collectionOrderFlag = form.formData.facc_enf_collection_order_made as boolean;
const collectionOrder: IOpalFinesUpdateDefendantAccountCollectionOrder = {
- collection_order_date: '',
+ ...FINES_ACC_COLLECTION_ORDER_PAYLOAD_DEFAULTS,
collection_order_flag: collectionOrderFlag,
};
diff --git a/src/app/flows/fines/services/opal-fines-service/interfaces/opal-fines-update-defendant-account-collection-order.interface.ts b/src/app/flows/fines/services/opal-fines-service/interfaces/opal-fines-update-defendant-account-collection-order.interface.ts
index 9caffac77b..cbb70f8594 100644
--- a/src/app/flows/fines/services/opal-fines-service/interfaces/opal-fines-update-defendant-account-collection-order.interface.ts
+++ b/src/app/flows/fines/services/opal-fines-service/interfaces/opal-fines-update-defendant-account-collection-order.interface.ts
@@ -1,4 +1,4 @@
export interface IOpalFinesUpdateDefendantAccountCollectionOrder {
- collection_order_date: string;
- collection_order_flag: boolean;
+ collection_order_date: null;
+ collection_order_flag: boolean | null;
}
From 8c32b4d8bc41811e2b8e56d3454fd6edd8982a6e Mon Sep 17 00:00:00 2001
From: Arnab subedi <147511052+Arnabsubedi233@users.noreply.github.com>
Date: Wed, 1 Apr 2026 12:10:49 +0100
Subject: [PATCH 5/8] comment response
---
.../fines-acc-enf-collo-change-routing-titles.constant.ts | 4 +++-
.../fines-acc-enf-collo-change.component.spec.ts | 6 ++----
...fines-acc-enf-collo-change-routing-titles.interface.ts | 8 ++++++++
3 files changed, 13 insertions(+), 5 deletions(-)
create mode 100644 src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/interfaces/fines-acc-enf-collo-change-routing-titles.interface.ts
diff --git a/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/constants/fines-acc-enf-collo-change-routing-titles.constant.ts b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/constants/fines-acc-enf-collo-change-routing-titles.constant.ts
index f0798559fc..23e3be0453 100644
--- a/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/constants/fines-acc-enf-collo-change-routing-titles.constant.ts
+++ b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/constants/fines-acc-enf-collo-change-routing-titles.constant.ts
@@ -1,4 +1,6 @@
-export const FINES_ACC_ENF_COLLO_CHANGE_ROUTING_TITLES = {
+import { IFinesAccEnfColloChangeRoutingTitles } from '../interfaces/fines-acc-enf-collo-change-routing-titles.interface';
+
+export const FINES_ACC_ENF_COLLO_CHANGE_ROUTING_TITLES: IFinesAccEnfColloChangeRoutingTitles = {
root: 'Collection Order',
children: {
change: 'Change Collection Order status',
diff --git a/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.spec.ts b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.spec.ts
index 72ed639c0f..466744c3bc 100644
--- a/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.spec.ts
+++ b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.spec.ts
@@ -27,11 +27,9 @@ describe('FinesAccEnfColloChangeComponent', () => {
beforeEach(async () => {
mockRoute = {
snapshot: {
- data: {
- title: 'Change Collection Order status',
- },
+ data: {},
},
- } as unknown as ActivatedRoute;
+ } as ActivatedRoute;
mockAccountStore = {
getAccountNumber: signal('177A'),
diff --git a/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/interfaces/fines-acc-enf-collo-change-routing-titles.interface.ts b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/interfaces/fines-acc-enf-collo-change-routing-titles.interface.ts
new file mode 100644
index 0000000000..cba7d32ba3
--- /dev/null
+++ b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/interfaces/fines-acc-enf-collo-change-routing-titles.interface.ts
@@ -0,0 +1,8 @@
+import { IChildRoutingPaths } from '@hmcts/opal-frontend-common/pages/routing/interfaces';
+
+export interface IFinesAccEnfColloChangeRoutingTitles extends IChildRoutingPaths {
+ root: string;
+ children: {
+ change: string;
+ };
+}
From 0954330ba5317e1e78f2b8617ca7d2f41bddf9b6 Mon Sep 17 00:00:00 2001
From: Arnab subedi <147511052+Arnabsubedi233@users.noreply.github.com>
Date: Wed, 1 Apr 2026 12:29:33 +0100
Subject: [PATCH 6/8] Adding missing requirement to redirect user back if
selection is same as current collection order status
---
...-details-enforcement-tab.component.spec.ts | 4 +-
...ndant-details-enforcement-tab.component.ts | 6 ++-
...fines-acc-defendant-details.component.html | 2 +-
...es-acc-defendant-details.component.spec.ts | 3 +-
.../fines-acc-defendant-details.component.ts | 3 +-
...nes-acc-enf-collo-change.component.spec.ts | 52 ++++++++++++++++++-
.../fines-acc-enf-collo-change.component.ts | 12 +++++
7 files changed, 74 insertions(+), 8 deletions(-)
diff --git a/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details-enforcement-tab/fines-acc-defendant-details-enforcement-tab.component.spec.ts b/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details-enforcement-tab/fines-acc-defendant-details-enforcement-tab.component.spec.ts
index a802829864..604e614ed9 100644
--- a/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details-enforcement-tab/fines-acc-defendant-details-enforcement-tab.component.spec.ts
+++ b/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details-enforcement-tab/fines-acc-defendant-details-enforcement-tab.component.spec.ts
@@ -38,7 +38,9 @@ describe('FinesAccDefendantDetailsEnforcementTab', () => {
component.handleChangeCollectionOrder();
- expect(eventEmitterSpy).toHaveBeenCalled();
+ expect(eventEmitterSpy).toHaveBeenCalledWith(
+ component.tabData.enforcement_overview.collection_order?.collection_order_flag ?? false,
+ );
});
it('should not emit changeCollectionOrder when the user lacks account maintenance permission', () => {
diff --git a/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details-enforcement-tab/fines-acc-defendant-details-enforcement-tab.component.ts b/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details-enforcement-tab/fines-acc-defendant-details-enforcement-tab.component.ts
index 2dd044de1a..288dbbfda7 100644
--- a/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details-enforcement-tab/fines-acc-defendant-details-enforcement-tab.component.ts
+++ b/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details-enforcement-tab/fines-acc-defendant-details-enforcement-tab.component.ts
@@ -39,7 +39,7 @@ export class FinesAccDefendantDetailsEnforcementTab {
@Input() hasAccountMaintenancePermission: boolean = false;
@Input() hasEnterEnforcementPermission: boolean = false;
@Output() addEnforcementOverride = new EventEmitter();
- @Output() changeCollectionOrder = new EventEmitter();
+ @Output() changeCollectionOrder = new EventEmitter();
/**
* Emits an event to add an enforcement override if the user has the necessary permissions and there is no existing enforcement override result.
@@ -60,7 +60,9 @@ export class FinesAccDefendantDetailsEnforcementTab {
*/
public handleChangeCollectionOrder(): void {
if (this.hasAccountMaintenancePermission) {
- this.changeCollectionOrder.emit();
+ this.changeCollectionOrder.emit(
+ this.tabData.enforcement_overview.collection_order?.collection_order_flag ?? false,
+ );
}
}
}
diff --git a/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details.component.html b/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details.component.html
index 7dfb772fe7..c15b602227 100644
--- a/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details.component.html
+++ b/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details.component.html
@@ -206,7 +206,7 @@ Business Unit:
[hasAccountMaintenancePermission]="hasPermission('account-maintenance')"
[hasEnterEnforcementPermission]="hasPermission('enter-enforcement')"
(addEnforcementOverride)="navigateToAddEnforcementOverridePage()"
- (changeCollectionOrder)="navigateToChangeCollectionOrderPage()"
+ (changeCollectionOrder)="navigateToChangeCollectionOrderPage($event)"
>
}
}
diff --git a/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details.component.spec.ts b/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details.component.spec.ts
index 1ca6778c7a..725ef86051 100644
--- a/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details.component.spec.ts
+++ b/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details.component.spec.ts
@@ -169,11 +169,12 @@ describe('FinesAccDefendantDetailsComponent', () => {
});
it('should call router.navigate when navigateToChangeCollectionOrderPage is called', () => {
- component.navigateToChangeCollectionOrderPage();
+ component.navigateToChangeCollectionOrderPage(true);
expect(routerSpy.navigate).toHaveBeenCalledWith(
[`../${FINES_ACC_DEFENDANT_ROUTING_PATHS.children.enforcement}/collection-order/change`],
{
relativeTo: component['activatedRoute'],
+ state: { currentCollectionOrderFlag: true },
},
);
});
diff --git a/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details.component.ts b/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details.component.ts
index 2df90a8b10..0a3231aec7 100644
--- a/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details.component.ts
+++ b/src/app/flows/fines/fines-acc/fines-acc-defendant-details/fines-acc-defendant-details.component.ts
@@ -462,9 +462,10 @@ export class FinesAccDefendantDetailsComponent extends AbstractTabData implement
/**
* Navigates to the change collection order page.
*/
- public navigateToChangeCollectionOrderPage(): void {
+ public navigateToChangeCollectionOrderPage(currentCollectionOrderFlag: boolean): void {
this['router'].navigate([`../${FINES_ACC_DEFENDANT_ROUTING_PATHS.children.enforcement}/collection-order/change`], {
relativeTo: this.activatedRoute,
+ state: { currentCollectionOrderFlag },
});
}
}
diff --git a/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.spec.ts b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.spec.ts
index 466744c3bc..3c47d61966 100644
--- a/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.spec.ts
+++ b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.spec.ts
@@ -1,6 +1,6 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { ActivatedRoute } from '@angular/router';
-import { signal } from '@angular/core';
+import { ActivatedRoute, Navigation, Router } from '@angular/router';
+import { signal, type WritableSignal } from '@angular/core';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { of, throwError } from 'rxjs';
import { FinesAccEnfColloChangeComponent } from './fines-acc-enf-collo-change.component';
@@ -16,6 +16,8 @@ describe('FinesAccEnfColloChangeComponent', () => {
let component: FinesAccEnfColloChangeComponent;
let fixture: ComponentFixture;
let mockRoute: ActivatedRoute;
+ let mockRouter: Pick;
+ let mockCurrentNavigation: WritableSignal;
let mockAccountStore: Pick<
FinesAccountStoreType,
'getAccountNumber' | 'party_name' | 'account_id' | 'base_version' | 'business_unit_id' | 'setSuccessMessage'
@@ -31,6 +33,17 @@ describe('FinesAccEnfColloChangeComponent', () => {
},
} as ActivatedRoute;
+ mockCurrentNavigation = signal({
+ extras: {
+ state: {},
+ },
+ } as unknown as Navigation);
+
+ mockRouter = {
+ currentNavigation: mockCurrentNavigation,
+ navigate: vi.fn(),
+ };
+
mockAccountStore = {
getAccountNumber: signal('177A'),
party_name: signal('Mr Robert THOMSON'),
@@ -62,6 +75,7 @@ describe('FinesAccEnfColloChangeComponent', () => {
imports: [FinesAccEnfColloChangeComponent],
providers: [
{ provide: ActivatedRoute, useValue: mockRoute },
+ { provide: Router, useValue: mockRouter },
{ provide: FinesAccountStore, useValue: mockAccountStore },
{ provide: FinesAccPayloadService, useValue: mockPayloadService },
{ provide: OpalFines, useValue: mockOpalFinesService },
@@ -136,6 +150,40 @@ describe('FinesAccEnfColloChangeComponent', () => {
expect(routerNavigateSpy).not.toHaveBeenCalled();
});
+ it('should navigate back without patching when the selected value matches the current collection order flag', () => {
+ mockCurrentNavigation.set({
+ extras: {
+ state: {
+ currentCollectionOrderFlag: false,
+ },
+ },
+ } as unknown as Navigation);
+
+ fixture = TestBed.createComponent(FinesAccEnfColloChangeComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+
+ const routerNavigateSpy = vi.spyOn(component as never, 'routerNavigate');
+
+ component.handleSubmit({
+ formData: {
+ facc_enf_collection_order_made: false,
+ },
+ nestedFlow: false,
+ });
+
+ expect(mockPayloadService.buildCollectionOrderPayload).not.toHaveBeenCalled();
+ expect(mockOpalFinesService.patchDefendantAccount).not.toHaveBeenCalled();
+ expect(mockAccountStore.setSuccessMessage).not.toHaveBeenCalled();
+ expect(routerNavigateSpy).toHaveBeenCalledWith(
+ FINES_ACC_DEFENDANT_ROUTING_PATHS.children.details,
+ false,
+ undefined,
+ null,
+ 'enforcement',
+ );
+ });
+
it('should send an empty collection order date when selecting yes', () => {
component.handleSubmit({
formData: {
diff --git a/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.ts b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.ts
index 2de65ea1f7..0df8f1807d 100644
--- a/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.ts
+++ b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change.component.ts
@@ -1,4 +1,5 @@
import { ChangeDetectionStrategy, Component, OnDestroy, inject } from '@angular/core';
+import { Router } from '@angular/router';
import { AbstractFormParentBaseComponent } from '@hmcts/opal-frontend-common/components/abstract/abstract-form-parent-base';
import { catchError, EMPTY, Subject, takeUntil } from 'rxjs';
import { UtilsService } from '@hmcts/opal-frontend-common/services/utils-service';
@@ -23,8 +24,12 @@ export class FinesAccEnfColloChangeComponent extends AbstractFormParentBaseCompo
private readonly finesAccStore = inject(FinesAccountStore);
private readonly finesAccPayloadService = inject(FinesAccPayloadService);
private readonly opalFinesService = inject(OpalFines);
+ private readonly appRouter = inject(Router);
private readonly utilsService = inject(UtilsService);
private readonly finesDefendantRoutingPaths = FINES_ACC_DEFENDANT_ROUTING_PATHS;
+ private readonly currentCollectionOrderFlag = this.appRouter.currentNavigation()?.extras.state?.[
+ 'currentCollectionOrderFlag'
+ ] as boolean | undefined;
public readonly accountNumber = this.finesAccStore.getAccountNumber() ?? '';
public readonly partyName = this.finesAccStore.party_name() ?? '';
@@ -50,6 +55,13 @@ export class FinesAccEnfColloChangeComponent extends AbstractFormParentBaseCompo
* @param form The form payload emitted by the child form component.
*/
public handleSubmit(form: IAbstractFormBaseForm): void {
+ const selectedCollectionOrderFlag = form.formData.facc_enf_collection_order_made;
+
+ if (selectedCollectionOrderFlag === this.currentCollectionOrderFlag) {
+ this.navigateToEnforcementTab();
+ return;
+ }
+
const payload = this.finesAccPayloadService.buildCollectionOrderPayload(form);
this.opalFinesService
From c975c823fe8a2aa19cefe45361cccc5f5f297ff0 Mon Sep 17 00:00:00 2001
From: Arnab subedi <147511052+Arnabsubedi233@users.noreply.github.com>
Date: Wed, 1 Apr 2026 14:42:44 +0100
Subject: [PATCH 7/8] comment response
---
.../fines-acc-enf-collo-change-form.component.html | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change-form/fines-acc-enf-collo-change-form.component.html b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change-form/fines-acc-enf-collo-change-form.component.html
index 7f106772a5..d66a9fcbc5 100644
--- a/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change-form/fines-acc-enf-collo-change-form.component.html
+++ b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change-form/fines-acc-enf-collo-change-form.component.html
@@ -15,11 +15,10 @@
To add a new Collection Order and issue a notice you should
go back
and add an enforcement action.
From 0527a4249936c965199b123223f54c5f8f0f2ccd Mon Sep 17 00:00:00 2001
From: Arnab subedi <147511052+Arnabsubedi233@users.noreply.github.com>
Date: Thu, 2 Apr 2026 13:27:52 +0100
Subject: [PATCH 8/8] converting to inline radios and buttons
---
...s-acc-enf-collo-change-form.component.html | 23 +++++++++++--------
1 file changed, 14 insertions(+), 9 deletions(-)
diff --git a/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change-form/fines-acc-enf-collo-change-form.component.html b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change-form/fines-acc-enf-collo-change-form.component.html
index d66a9fcbc5..da532d051d 100644
--- a/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change-form/fines-acc-enf-collo-change-form.component.html
+++ b/src/app/flows/fines/fines-acc/fines-acc-enf-collo-change/fines-acc-enf-collo-change-form/fines-acc-enf-collo-change-form.component.html
@@ -26,6 +26,7 @@