Browse Source

fix: resolve updateAccountBalance checkbox disabled for past dates

The date valueChanges handler unconditionally disabled the
"Update Cash Balance" checkbox when the date was not today,
conflicting with the type handler which enabled it for
BUY/SELL/DIVIDEND types. Switching types re-triggered the type
handler, masking the bug.

Extract the enable/disable decision into a pure helper function
(shouldEnableUpdateAccountBalance) and call it from the type,
accountId, and date subscribers — removing the date-based
restriction entirely.

Closes #6327
pull/6594/head
Nathan Nguyen 2 weeks ago
parent
commit
5a9e2785f0
  1. 45
      apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts
  2. 117
      apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.helper.spec.ts
  3. 21
      apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.helper.ts

45
apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts

@ -49,6 +49,7 @@ import { calendarClearOutline, refreshOutline } from 'ionicons/icons';
import { EMPTY, Subject } from 'rxjs';
import { catchError, delay, takeUntil } from 'rxjs/operators';
import { shouldEnableUpdateAccountBalance } from './create-or-update-activity-dialog.helper';
import { CreateOrUpdateActivityDialogParams } from './interfaces/interfaces';
import { ActivityType } from './types/activity-type.type';
@ -272,12 +273,7 @@ export class GfCreateOrUpdateActivityDialogComponent implements OnDestroy {
this.activityForm.get('currencyOfUnitPrice').setValue(currency);
if (['FEE', 'INTEREST'].includes(type)) {
if (this.activityForm.get('accountId').value) {
this.activityForm.get('updateAccountBalance').enable();
} else {
this.activityForm.get('updateAccountBalance').disable();
this.activityForm.get('updateAccountBalance').setValue(false);
}
this.updateAccountBalanceState();
}
}
});
@ -303,13 +299,6 @@ export class GfCreateOrUpdateActivityDialogComponent implements OnDestroy {
});
this.activityForm.get('date').valueChanges.subscribe(() => {
if (isToday(this.activityForm.get('date').value)) {
this.activityForm.get('updateAccountBalance').enable();
} else {
this.activityForm.get('updateAccountBalance').disable();
this.activityForm.get('updateAccountBalance').setValue(false);
}
this.changeDetectorRef.markForCheck();
});
@ -388,8 +377,7 @@ export class GfCreateOrUpdateActivityDialogComponent implements OnDestroy {
.get('searchSymbol')
.removeValidators(Validators.required);
this.activityForm.get('searchSymbol').updateValueAndValidity();
this.activityForm.get('updateAccountBalance').disable();
this.activityForm.get('updateAccountBalance').setValue(false);
this.updateAccountBalanceState();
} else if (['FEE', 'INTEREST', 'LIABILITY'].includes(type)) {
const currency =
this.data.accounts.find(({ id }) => {
@ -426,15 +414,7 @@ export class GfCreateOrUpdateActivityDialogComponent implements OnDestroy {
this.activityForm.get('unitPrice').setValue(0);
}
if (
['FEE', 'INTEREST'].includes(type) &&
this.activityForm.get('accountId').value
) {
this.activityForm.get('updateAccountBalance').enable();
} else {
this.activityForm.get('updateAccountBalance').disable();
this.activityForm.get('updateAccountBalance').setValue(false);
}
this.updateAccountBalanceState();
} else {
this.activityForm
.get('dataSource')
@ -446,7 +426,7 @@ export class GfCreateOrUpdateActivityDialogComponent implements OnDestroy {
.get('searchSymbol')
.setValidators(Validators.required);
this.activityForm.get('searchSymbol').updateValueAndValidity();
this.activityForm.get('updateAccountBalance').enable();
this.updateAccountBalanceState();
}
this.changeDetectorRef.markForCheck();
@ -562,6 +542,21 @@ export class GfCreateOrUpdateActivityDialogComponent implements OnDestroy {
this.unsubscribeSubject.complete();
}
private updateAccountBalanceState() {
if (
shouldEnableUpdateAccountBalance({
accountId: this.activityForm.get('accountId').value,
dataSource: this.activityForm.get('dataSource').value,
type: this.activityForm.get('type').value
})
) {
this.activityForm.get('updateAccountBalance').enable();
} else {
this.activityForm.get('updateAccountBalance').disable();
this.activityForm.get('updateAccountBalance').setValue(false);
}
}
private updateAssetProfile() {
this.isLoading = true;
this.changeDetectorRef.markForCheck();

117
apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.helper.spec.ts

@ -0,0 +1,117 @@
import { shouldEnableUpdateAccountBalance } from './create-or-update-activity-dialog.helper';
describe('shouldEnableUpdateAccountBalance', () => {
describe('BUY type', () => {
it('should enable regardless of date', () => {
expect(
shouldEnableUpdateAccountBalance({
accountId: 'account-1',
dataSource: 'YAHOO',
type: 'BUY'
})
).toBe(true);
});
it('should disable when dataSource is MANUAL (transitional from VALUABLE)', () => {
expect(
shouldEnableUpdateAccountBalance({
accountId: 'account-1',
dataSource: 'MANUAL',
type: 'BUY'
})
).toBe(false);
});
});
describe('SELL type', () => {
it('should enable', () => {
expect(
shouldEnableUpdateAccountBalance({
accountId: 'account-1',
dataSource: 'YAHOO',
type: 'SELL'
})
).toBe(true);
});
});
describe('DIVIDEND type', () => {
it('should enable', () => {
expect(
shouldEnableUpdateAccountBalance({
accountId: 'account-1',
dataSource: 'YAHOO',
type: 'DIVIDEND'
})
).toBe(true);
});
});
describe('FEE type', () => {
it('should enable when accountId is set', () => {
expect(
shouldEnableUpdateAccountBalance({
accountId: 'account-1',
dataSource: 'MANUAL',
type: 'FEE'
})
).toBe(true);
});
it('should disable when accountId is empty', () => {
expect(
shouldEnableUpdateAccountBalance({
accountId: null,
dataSource: 'MANUAL',
type: 'FEE'
})
).toBe(false);
});
});
describe('INTEREST type', () => {
it('should enable when accountId is set', () => {
expect(
shouldEnableUpdateAccountBalance({
accountId: 'account-1',
dataSource: 'MANUAL',
type: 'INTEREST'
})
).toBe(true);
});
it('should disable when accountId is empty', () => {
expect(
shouldEnableUpdateAccountBalance({
accountId: null,
dataSource: 'MANUAL',
type: 'INTEREST'
})
).toBe(false);
});
});
describe('VALUABLE type', () => {
it('should always disable', () => {
expect(
shouldEnableUpdateAccountBalance({
accountId: 'account-1',
dataSource: 'MANUAL',
type: 'VALUABLE'
})
).toBe(false);
});
});
describe('LIABILITY type', () => {
it('should always disable', () => {
expect(
shouldEnableUpdateAccountBalance({
accountId: 'account-1',
dataSource: 'MANUAL',
type: 'LIABILITY'
})
).toBe(false);
});
});
});

21
apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.helper.ts

@ -0,0 +1,21 @@
export function shouldEnableUpdateAccountBalance({
accountId,
dataSource,
type
}: {
accountId: string | null;
dataSource: string | null;
type: string;
}): boolean {
const isManualBuy = dataSource === 'MANUAL' && type === 'BUY';
if (['VALUABLE', 'LIABILITY'].includes(type) || isManualBuy) {
return false;
}
if (['FEE', 'INTEREST'].includes(type)) {
return !!accountId;
}
return true;
}
Loading…
Cancel
Save