apache / apache/fineract-backoffice-ui

The interest-pause edit form discards dates the user picked while its own load was still in flight

Open
#513 0 comments 0 reactions 0 assignees View on GitHub
angular bug loans typescript ux
Dominant language
TypeScript
Stars
15
Forks
60
Avg merge
10h 15m
Merged PRs (30d)
108

Description

## What happens

`interest-pause-form.component.ts` renders its pickers immediately and fetches the pause afterwards. When the response arrives it writes into the same signals the user has been editing:

```ts
// :184
private loadPause(): void {
if (!this.loanId || !this.variationId) return;

this.pauseService.getLoansLoanIdInterestPauses(this.loanId).subscribe({
next: (pauses) => {
const pause = pauses.find(({ id }) => id === this.variationId);
if (pause) {
this.startDate.set(this.toFormDate(pause.startDate)); // unconditional
this.endDate.set(this.toFormDate(pause.endDate));
}
},
```

Nothing disables the form while that request is outstanding and nothing checks whether the user has already touched the fields, so on a slow link the picked dates are replaced by the stored ones.

## Reproduced against a live platform

Loan 26, pause id 1 (2026-08-17 to 2026-08-27), with the populating `GET` held for five seconds — a delay, not a fabricated response. Dates picked while it was in flight:

![Oct 10 and Oct 20, as picked](https://raw.githubusercontent.com/Aman-Mittal/fineract-backoffice-ui/assets/issue-screenshots/interest-pause-overwrite-picked.png)

The same screen once the response landed:

![Back to Aug 17 and Aug 27](https://raw.githubusercontent.com/Aman-Mittal/fineract-backoffice-ui/assets/issue-screenshots/interest-pause-overwrite-reverted.png)

Read off the controls directly:

```
stored pause : 2026-08-17 .. 2026-08-27
user picked : {"start":"2026-10-10","end":"2026-10-20"}
after GET landed : {"start":"2026-08-17","end":"2026-08-27"}
```

[Screen recording](https://github.com/Aman-Mittal/fineract-backoffice-ui/raw/assets/issue-screenshots/interest-pause-overwrite.webm).

## Why it matters

The reversion is silent and it lands on a form the user is about to submit. Someone correcting a pause on a slow connection picks the right dates, watches them change back, and — if they do not happen to be looking at that moment — saves the values they meant to replace. The result is an unchanged relief period that the operator believes they corrected, on a loan where the pause range determines interest.

Five seconds is generous for a lab, but a field branch on a poor link is exactly where this bites, and it is also the setting where a user is most likely to start typing before the screen has settled.

## Suggested fix

Do not let a late response win over a user edit. Two workable shapes, in rough order of preference:

1. **Do not show editable controls until the data is there.** A loading state over the form removes the race rather than arbitrating it, and matches what the screen is actually doing — it has nothing to edit yet.
2. **Only apply the response if the fields are still untouched**, tracked with the form's own pristine state, and drop the response otherwise.

Whichever is chosen, guarding the submit button while the load is outstanding is worth having too — the user can currently save before the form knows what it is editing.

## Regression guard

A unit case that sets a date before the stubbed `getLoansLoanIdInterestPauses` emits, then emits, and asserts the signal still holds the user's value. The existing spec already controls that observable, so it is a case rather than new scaffolding.

## Environment

`main` at `3c6d7479`. `apache/fineract:latest` via `deploy/docker-compose-e2e.yml`.

Separate from #512, which is about a non-numeric `:variationId` on the same screen, and from #496, which concerns how these dates are formatted on the way out. All three are in the same component and would sensibly be looked at together.

Contributor guide

Open the contributing guide

Research direction

Start in interest-pause-form.component.ts at loadPause around line 184 and inspect the existing spec that stubs getLoansLoanIdInterestPauses. Reproduce the sequence by setting a date before the observable emits, then verify the user's value remains after the response; done means late loading data no longer overwrites edits and submission cannot occur before loading completes.

Written by the indexing model from the issue text.

Assessment

Tech stack
angular, typescript
Domain
frontend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.