WEB-954: Migrate Subscription management : products#3640
Conversation
|
Note
|
| Layer / File(s) | Summary |
|---|---|
Typed forms & lifecycle subscriptions (product-wide) src/app/products/... |
Bulk migration: untyped reactive forms → typed FormBuilder/FormGroup/FormControl/FormArray; ActivatedRoute.data and many valueChanges subscriptions now use pipe(takeUntilDestroyed(this.destroyRef)) with injected DestroyRef. |
Estimated code review effort
🎯 4 (Complex) | ⏱️ ~45 minutes
Possibly related PRs
- openMF/web-app#3487: Overlapping changes to near-breach/working-capital components and typed form migrations.
- openMF/web-app#3493: Related edits around loan-product currency/multiples and subscription handling.
- openMF/web-app#3461: Related working-capital breach model/service typing and route-data handling.
Suggested reviewers
- adamsaghy
✨ Finishing Touches
🧪 Generate unit tests (beta)
- Create PR with unit tests
There was a problem hiding this comment.
Actionable comments posted: 11
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/app/products/share-products/share-product-stepper/share-product-terms-step/share-product-terms-step.component.ts (1)
45-56:⚠️ Potential issue | 🟠 Major | ⚡ Quick winMissing teardown on
combineLatestform subscription.
valueChangesstreams are long-lived; this subscription should be lifecycle-bound like the rest of this PR to avoid leaks across navigations.Suggested fix
- combineLatest([ + combineLatest([ this.shareProductTermsForm.get('sharesIssued').valueChanges, this.shareProductTermsForm.get('unitPrice').valueChanges - ]).subscribe( + ]) + .pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe( ([ sharesIssued, unitPrice ]: number[]) => { this.shareProductTermsForm.get('shareCapital').setValue(sharesIssued * unitPrice); } - ); + );As per coding guidelines, for
src/app/**you asked to “verify ... clean observable patterns.”🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/products/share-products/share-product-stepper/share-product-terms-step/share-product-terms-step.component.ts` around lines 45 - 56, The combineLatest subscription created in ngOnInit (listening to this.shareProductTermsForm.get('sharesIssued').valueChanges and .get('unitPrice').valueChanges) is not torn down and will leak; update the implementation to make the observable lifecycle-bound by piping the combined stream through a teardown operator (for example pipe(takeUntil(this.destroy$)) using a component-level Subject destroy$ that is completed in ngOnDestroy, or store the Subscription returned and unsubscribe in ngOnDestroy), then keep the logic that sets this.shareProductTermsForm.get('shareCapital').setValue(sharesIssued * unitPrice) inside that subscription; ensure destroy$ (or the unsubscribe) is defined on the component and invoked in ngOnDestroy.Source: Coding guidelines
🧹 Nitpick comments (19)
src/app/products/loan-products/working-capital/breach-configuration/view-breach-configuration/view-breach-configuration.component.ts (1)
35-36: ⚡ Quick winNarrow
route.datatyping toBreachinstead ofany.
{ breachData: any }discards type safety even thoughbreachDatais already modeled asBreach | null.
As per coding guidelines: "src/app/**/*.ts: Use TypeScript for all application code with strict typing conventions." Based on learnings: avoidanyand define concrete response/data shapes.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/products/loan-products/working-capital/breach-configuration/view-breach-configuration/view-breach-configuration.component.ts` around lines 35 - 36, The subscription currently types the route data as { breachData: any } which loses type safety; update the typing to { breachData: Breach | null } (matching the component's breachData property) and import the Breach model/interface, then update the this.route.data.pipe(...).subscribe signature accordingly (leave takeUntilDestroyed(this.destroyRef) and the assignment to this.breachData intact); ensure any other usages in view-breach-configuration.component.ts that rely on breachData reflect the stronger type.Sources: Coding guidelines, Learnings
src/app/products/recurring-deposit-products/recurring-deposit-product-stepper/recurring-deposit-product-details-step/recurring-deposit-product-details-step.component.ts (1)
32-32: ⚡ Quick winUse a typed controls map for
recurringDepositProductDetailsForm.Switching to
FormGroupis good, but without control generics this remains loosely typed andvalue/patchValuechecks stay weaker than intended.
As per coding guidelines: "src/app/**/*.ts: Use TypeScript for all application code with strict typing conventions."Also applies to: 36-36
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/products/recurring-deposit-products/recurring-deposit-product-stepper/recurring-deposit-product-details-step/recurring-deposit-product-details-step.component.ts` at line 32, The recurringDepositProductDetailsForm is currently an untyped FormGroup — create a typed controls interface (e.g. RecurringDepositProductDetailsFormControls) describing each control and its FormControl type, then initialize the form using that interface so the form variable is strongly typed (use FormBuilder.group<RecurringDepositProductDetailsFormControls>(...) or new FormGroup<RecurringDepositProductDetailsFormControls>(...)); update usages of recurringDepositProductDetailsForm.value/patchValue to match the new typed shape and adjust the private formBuilder = inject(FormBuilder) usage only to build the strongly-typed form.Source: Coding guidelines
src/app/products/loan-products/working-capital/near-breach-configuration/view-near-breach-configuration/view-near-breach-configuration.component.ts (1)
37-38: ⚡ Quick winReplace
anyin route-data typing withNearBreach.The new subscription still uses
any({ nearBreachData: any }). Please type it as{ nearBreachData: NearBreach }(orNearBreach | nullif resolver can return null) to keep strict typing guarantees intact.As per coding guidelines:
src/app/**/*.ts: “Use TypeScript for all application code with strict typing conventions.” Based on learnings: avoidanyfor API/route response shapes in TypeScript files.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/products/loan-products/working-capital/near-breach-configuration/view-near-breach-configuration/view-near-breach-configuration.component.ts` around lines 37 - 38, The route data subscription currently types the payload as { nearBreachData: any } — update it to a strict type such as { nearBreachData: NearBreach } (or { nearBreachData: NearBreach | null } if resolver may return null) in the subscribe callback for route.data.pipe(...).subscribe, and ensure the NearBreach interface/type is imported or defined in this component; also update the component property this.nearBreachData to that same type so usages inside view-near-breach-configuration.component.ts are type-safe.Sources: Coding guidelines, Learnings
src/app/products/recurring-deposit-products/recurring-deposit-product-stepper/recurring-deposit-product-interest-rate-chart-step/recurring-deposit-product-interest-rate-chart-step.component.ts (1)
95-95: 🏗️ Heavy liftFinish strong typing for chart form controls (generics + typed value models).
The shift away from
Untyped*is good, but currentFormGroup/FormArrayusage is still largely unbounded. Defining typed control/value interfaces for chart/slab/incentive structures would prevent invalid shape assumptions when reading/writing nested controls.As per coding guidelines:
src/app/**/*.ts: “Use TypeScript for all application code with strict typing conventions.”Also applies to: 334-336, 382-384, 386-430
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/products/recurring-deposit-products/recurring-deposit-product-stepper/recurring-deposit-product-interest-rate-chart-step/recurring-deposit-product-interest-rate-chart-step.component.ts` at line 95, The chart form is declared as an untyped FormGroup (recurringDepositProductInterestRateChartForm) and several nested arrays/controls are unbounded; define TypeScript interfaces for the chart, slab and incentive models (e.g., RecurringDepositInterestChart, InterestSlab, Incentive) and update the form types to use generics such as FormGroup<RecurringDepositInterestChart>, FormArray<FormGroup<InterestSlab>> and typed FormControl<T> for individual fields in methods that build/read the form (look for places that create slabs/incentives and where values are read/written around recurringDepositProductInterestRateChartForm); then update all accesses to use the typed properties so the compiler enforces correct shapes and you can safely map between form.value and your domain models.Source: Coding guidelines
src/app/products/manage-delinquency-buckets/delinquency-bucket/edit-bucket/edit-bucket.component.ts (1)
72-72: 🏗️ Heavy liftUse explicit form and resolver interfaces in the edit flow as well.
The migration still leaves
bucketForm: FormGroupand resolver payload members asany. Please type these explicitly (ideally shared with the create component) so create/edit stay consistent and compiler-checked.As per coding guidelines:
src/app/**/*.ts: “Use TypeScript for all application code with strict typing conventions.” Based on learnings: avoidanyresponse typing and model API/route shapes with interfaces.Also applies to: 102-123
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/products/manage-delinquency-buckets/delinquency-bucket/edit-bucket/edit-bucket.component.ts` at line 72, The component currently declares bucketForm: FormGroup and leaves resolver payloads as any; update EditBucketComponent to use a concrete form interface (e.g., BucketForm or shared IBucketForm used by the create component) and type the FormGroup as FormGroup<BucketForm> (or FormGroup<Record<...>> matching your controls), and replace any resolver/route payload typings with explicit interfaces (e.g., IBucketResolverData) instead of any so the component methods that reference bucketForm, the resolver data, and related members are fully typed and consistent with the create flow.Sources: Coding guidelines, Learnings
src/app/products/manage-delinquency-buckets/delinquency-bucket/view-bucket/view-bucket.component.ts (1)
38-38: ⚡ Quick winType
delinquencyBucketroute data explicitly instead ofany.Please replace
{ delinquencyBucket: any }anddelinquencyBucketData: anywith the concrete bucket interface/model to preserve strict typing in this view path.As per coding guidelines:
src/app/**/*.ts: “Use TypeScript for all application code with strict typing conventions.” Based on learnings: avoidanyfor response payloads and prefer concrete interfaces.Also applies to: 42-43
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/products/manage-delinquency-buckets/delinquency-bucket/view-bucket/view-bucket.component.ts` at line 38, Replace the loose any types with the concrete DelinquencyBucket interface: import or define the DelinquencyBucket model and change the route data typing from { delinquencyBucket: any } to { delinquencyBucket: DelinquencyBucket } and change the component property delinquencyBucketData: any to delinquencyBucketData: DelinquencyBucket; also update any other occurrences on lines referenced (e.g., the ActivatedRoute.data subscription or snapshot access in the constructor/ngOnInit) to use DelinquencyBucket so the component (view-bucket.component) and its route data are strictly typed.Sources: Coding guidelines, Learnings
src/app/products/manage-delinquency-buckets/delinquency-bucket/create-bucket/create-bucket.component.ts (1)
72-72: 🏗️ Heavy liftComplete the typed-forms migration by removing remaining untyped surfaces.
bucketForm: FormGroupand{ delinquencyBucketsTemplateData: any }are still loosely typed. Define a concrete form model (e.g.,FormGroup<{ name: FormControl<string>; ... }>), and type resolver payloads explicitly to prevent silent shape drift.As per coding guidelines:
src/app/**/*.ts: “Use TypeScript for all application code with strict typing conventions.” Based on learnings: avoidanyresponse typing and introduce specific interfaces/types.Also applies to: 96-111
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/products/manage-delinquency-buckets/delinquency-bucket/create-bucket/create-bucket.component.ts` at line 72, The form and template payload are still untyped: replace the loose bucketForm: FormGroup and the { delinquencyBucketsTemplateData: any } payload with a concrete typed model (e.g., FormGroup<{ name: FormControl<string>; description: FormControl<string | null>; ... }>) and a specific interface for the resolver payload (e.g., DelinquencyBucketsTemplateData { /* fields */ }); update create-bucket.component.ts usages (bucketForm, any references to delinquencyBucketsTemplateData, and methods that read/write controls like buildForm/createForm/initForm) to use the new types so all form.controls and resolver responses are strictly typed and prevent implicit any/shape drift.Sources: Coding guidelines, Learnings
src/app/products/manage-delinquency-buckets/delinquency-bucket/delinquency-bucket.component.ts (1)
60-60: ⚡ Quick winTighten
anytypes on resolver data and table source.
delinquencyBucketData,MatTableDataSource<any>, and{ delinquencyBuckets: any }should be replaced with the concrete bucket type used by this screen. This keeps the new lifecycle cleanup changes aligned with strict typing.As per coding guidelines:
src/app/**/*.ts: “Use TypeScript for all application code with strict typing conventions.” Based on learnings: prefer specific interfaces overanyfor response shapes.Also applies to: 67-67, 76-77
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/products/manage-delinquency-buckets/delinquency-bucket/delinquency-bucket.component.ts` at line 60, The fields and generics using any should be replaced with the concrete bucket type used by this screen: define or import the DelinquencyBucket interface and replace delinquencyBucketData: any with the properly typed resolver shape (e.g. { delinquencyBuckets: DelinquencyBucket[] }), change MatTableDataSource<any> to MatTableDataSource<DelinquencyBucket>, and update any resolver/route data typings and usages (including the symbol delinquencyBuckets and the table data source instantiation in the component) so all occurrences use DelinquencyBucket instead of any.Sources: Coding guidelines, Learnings
src/app/products/recurring-deposit-products/recurring-deposit-products.component.ts (1)
217-228: ⚡ Quick winBind
afterClosed()to component lifecycle as well.
afterClosed()is still a naked subscription. If the component is destroyed before the dialog closes, this callback can still run and mutate state/navigation after teardown.♻️ Suggested change
- nextStepDialogRef.afterClosed().subscribe((response: { nextStep: boolean }) => { + nextStepDialogRef + .afterClosed() + .pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe((response: { nextStep: boolean }) => { if (response.nextStep) { this.configurationWizardService.showRecurringDepositProductsPage = false; this.configurationWizardService.showRecurringDepositProductsList = false; this.configurationWizardService.showManageFunds = true; this.router.navigate(['/organization']); } else { this.configurationWizardService.showRecurringDepositProductsPage = false; this.configurationWizardService.showRecurringDepositProductsList = false; this.router.navigate(['/home']); } - }); + });🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/products/recurring-deposit-products/recurring-deposit-products.component.ts` around lines 217 - 228, The subscription to nextStepDialogRef.afterClosed() is not tied to the component lifecycle and may run after teardown; modify the component to use a destruction signal (e.g., a private destroy$ Subject and implement ngOnDestroy) and pipe the afterClosed() observable through takeUntil(this.destroy$) (or use first() where appropriate) before subscribing, so the callback that updates configurationWizardService and calls router.navigate is automatically unsubscribed when the component is destroyed; update or add ngOnDestroy to emit/complete destroy$ and remove any direct naked subscriptions.src/app/products/manage-tax-groups/view-tax-group/view-tax-group.component.ts (1)
43-44: ⚡ Quick winReplace route-data
anytyping with a concrete interface.The teardown migration is good, but the new subscription still keeps
anyin the route contract, which weakens strict typing and propagates unsafe access.♻️ Suggested change
+interface ViewTaxGroupRouteData { + taxGroup: TaxGroup; +} + export class ViewTaxGroupComponent { @@ - taxGroupData: any; + taxGroupData: TaxGroup; @@ - this.route.data.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data: { taxGroup: any }) => { + this.route.data.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data: ViewTaxGroupRouteData) => { this.taxGroupData = data.taxGroup; }); } }As per coding guidelines,
src/app/**/*.ts: Use TypeScript for all application code with strict typing conventions. Based on learnings, avoidObservable<any>response typing and introduce specific interfaces for response shapes.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/products/manage-tax-groups/view-tax-group/view-tax-group.component.ts` around lines 43 - 44, Replace the any typing on the route data with a concrete interface: define an interface (e.g., TaxGroup or TaxGroupRouteData) describing the expected properties (id, name, members, etc.) and use it in the subscription and component property declarations so the subscription becomes this.route.data.pipe(...).subscribe((data: { taxGroup: TaxGroup }) => { this.taxGroupData = data.taxGroup; }) and change the type of taxGroupData accordingly; also update any resolver or route typing that provides data.taxGroup to return the same TaxGroup interface to keep types consistent across ViewTaxGroupComponent and its resolver.Sources: Coding guidelines, Learnings
src/app/products/recurring-deposit-products/recurring-deposit-product-stepper/recurring-deposit-product-terms-step/recurring-deposit-product-terms-step.component.ts (1)
34-34: ⚡ Quick winUse a strongly typed
FormGroupmodel instead of rawFormGroup.The migration removes untyped forms, but
FormGroupwithout a control map still leaves this form effectively weakly typed.As per coding guidelines,
src/app/**/*.ts: Use TypeScript for all application code with strict typing conventions.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/products/recurring-deposit-products/recurring-deposit-product-stepper/recurring-deposit-product-terms-step/recurring-deposit-product-terms-step.component.ts` at line 34, Replace the untyped recurringDepositProductTermsForm: FormGroup with a strongly typed form model: define an interface (e.g., RecurringDepositProductTermsFormControls) that lists each control name and its FormControl type (e.g., FormControl<number | null> or FormControl<string | null> as appropriate), then change the field to recurringDepositProductTermsForm: FormGroup<RecurringDepositProductTermsFormControls> and update the formBuilder.group(...) initialization to use that generic so each control (names used in this component) is strongly typed; ensure you import FormControl/FormGroup types and adjust any code that reads controls to use the typed keys.Source: Coding guidelines
src/app/products/saving-products/saving-product-stepper/saving-product-charges-step/saving-product-charges-step.component.ts (1)
66-66: ⚡ Quick winConsider adding a generic type parameter to
FormControlfor full type safety.The
FormControltype can accept a generic type parameter to specify the value type (e.g.,FormControl<string>). This would provide better type safety and IDE support.♻️ Example with generic type
-@Input() currencyCode: FormControl; +@Input() currencyCode: FormControl<string>;🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/products/saving-products/saving-product-stepper/saving-product-charges-step/saving-product-charges-step.component.ts` at line 66, The Input property currencyCode uses a raw FormControl which lacks value-type information; update the declaration for currencyCode to use a FormControl generic with the correct value type (e.g., FormControl<string> or FormControl<string | null> depending on whether null is allowed) so the component and consumers get full type safety and better IDE completions; locate the currencyCode Input in saving-product-charges-step.component.ts and change its type accordingly and adjust any callers/initializations to match the tighter type.src/app/products/saving-products/saving-product-stepper/saving-product-details-step/saving-product-details-step.component.ts (1)
36-36: ⚡ Quick winConsider adding a generic type parameter to
FormGroupfor full type safety.The
FormGroupcan accept a generic type parameter to describe the form shape. This provides better type safety for.value,.patchValue(), and form control access.♻️ Example with interface
interface SavingProductDetailsForm { name: string; shortName: string; description: string; } savingProductDetailsForm: FormGroup<{ name: FormControl<string>; shortName: FormControl<string>; description: FormControl<string>; }>;🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/products/saving-products/saving-product-stepper/saving-product-details-step/saving-product-details-step.component.ts` at line 36, The savingProductDetailsForm is declared as an untyped FormGroup; add a generic type describing the form shape to gain full type-safety (e.g., create an interface or inline type for fields like name, shortName, description and change savingProductDetailsForm: FormGroup to FormGroup<{ name: FormControl<string>; shortName: FormControl<string>; description: FormControl<string>; }>) and update where the form is created/initialized (constructor or ngOnInit) to use FormControl<string> and typed controls so .value, .patchValue(), and control access (savingProductDetailsForm.get or savingProductDetailsForm.controls) are correctly typed.src/app/products/saving-products/saving-product-stepper/saving-product-terms-step/saving-product-terms-step.component.ts (1)
34-34: ⚡ Quick winConsider adding a generic type parameter to
FormGroupfor full type safety.Similar to the details step, this
FormGroupwould benefit from a generic type parameter describing the form controls (nominalAnnualInterestRate, interestCompoundingPeriodType, etc.) for better type safety.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/products/saving-products/saving-product-stepper/saving-product-terms-step/saving-product-terms-step.component.ts` at line 34, The savingProductTermsForm property should declare a typed FormGroup to get full type safety: update savingProductTermsForm to use FormGroup with a generic describing the controls (e.g., keys like nominalAnnualInterestRate, interestCompoundingPeriodType, interestCalculationType, interestPostingPeriodType, minOpenBalanceRequired, maxOpenBalanceAllowed, etc.) and their control types (FormControl<number | string | boolean> or AbstractControl<number | string | boolean> as appropriate). Locate the savingProductTermsForm declaration in the SavingProductTermsStepComponent and change the type from FormGroup to FormGroup<{ <controlName>: AbstractControl<...>; ... }> so the component, validators, and value accessors are strongly typed throughout.src/app/products/collaterals/create-collateral/create-collateral.component.ts (1)
43-43: ⚡ Quick winUse a strongly-typed
FormGroupinstead of a bareFormGroup.The current declaration still leaves control/value access loosely typed, so this migration does not enforce strict form typing yet.
♻️ Suggested typing upgrade
-import { FormGroup, FormBuilder, Validators } from '`@angular/forms`'; +import { FormBuilder, FormControl, FormGroup, Validators } from '`@angular/forms`'; +type CollateralFormModel = { + name: FormControl<string>; + unitType: FormControl<string>; + basePrice: FormControl<string>; + pctToBase: FormControl<string>; + currency: FormControl<string>; + quality: FormControl<string>; +}; - collateralForm: FormGroup; + collateralForm: FormGroup<CollateralFormModel>; createCollateralForm() { - this.collateralForm = this.formBuilder.group({ + this.collateralForm = this.formBuilder.nonNullable.group({ name: [ '', Validators.required ], ...As per coding guidelines,
src/app/**/*.ts: “Use TypeScript for all application code with strict typing conventions.”Also applies to: 78-104
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/products/collaterals/create-collateral/create-collateral.component.ts` at line 43, The collateralForm is declared as an untyped FormGroup; declare a strongly-typed form model and update collateralForm to use FormGroup<T> (or FormGroup<Record<key, FormControlType>>) so control access is typed. Create an interface (e.g. CollateralFormModel) listing each control name and its type (string, number, boolean, or specific value types), then initialize the form with the typed builder (e.g. this.collateralForm = this.fb.group<CollateralFormModel>({...}) or use NonNullableFormBuilder for non-nullable controls), replacing bare FormControl/FormBuilder usages in the component (collateralForm, FormBuilder initialization and form creation logic in create-collateral.component) so everywhere you reference controls (get, value, patchValue) benefits from strict typing.Source: Coding guidelines
src/app/products/collaterals/edit-collateral/edit-collateral.component.ts (1)
42-42: ⚡ Quick winComplete the typed-forms migration with a typed control map.
collateralForm: FormGroupkeeps control access weakly typed; useFormGroup<...>(with typed controls) sovalue/patchValueare checked at compile time.As per coding guidelines,
src/app/**/*.ts: “Use TypeScript for all application code with strict typing conventions.”Also applies to: 68-95
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/products/collaterals/edit-collateral/edit-collateral.component.ts` at line 42, The collateralForm is currently declared as an untyped FormGroup; replace it with a typed FormGroup describing each control (e.g. FormGroup<{ title: FormControl<string|null>, description: FormControl<string|null>, amount: FormControl<number|null>, ... }>) and update its initialization in the component (where you call new FormGroup(...) or this.fb.group(...)) to use FormControl<T> (or this.fb.control<T>) and proper Validators so value/patchValue are type-checked; adjust any usages in methods like the constructor/init block and the code between the previously noted range (the form build and any patchValue/value calls around lines 68-95) to match the new control types and imports (FormGroup, FormControl, Validators) so compile-time checking enforces correct shapes.Source: Coding guidelines
src/app/products/fixed-deposit-products/fixed-deposit-product-stepper/fixed-deposit-product-interest-rate-chart-step/fixed-deposit-product-interest-rate-chart-step.component.ts (1)
96-97: 🏗️ Heavy liftDefine typed nested form models for charts/slabs/incentives.
This migration removes
Untyped*, but unparameterizedFormGroup/FormArrayacross nested methods still permits shape drift and weakvaluetyping. A typed model for chart/slab/incentive controls would make this conversion materially safer.As per coding guidelines,
src/app/**/*.ts: “Use TypeScript for all application code with strict typing conventions.”Also applies to: 328-333, 376-427
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/products/fixed-deposit-products/fixed-deposit-product-stepper/fixed-deposit-product-interest-rate-chart-step/fixed-deposit-product-interest-rate-chart-step.component.ts` around lines 96 - 97, Declare TypeScript interfaces for the nested form models (e.g., FixedDepositChartModel, FixedDepositSlabModel, FixedDepositIncentiveModel), then parameterize all untyped FormGroup and FormArray instances and factory methods to use those interfaces (for example change fixedDepositProductInterestRateChartForm: FormGroup to FormGroup<FixedDepositChartModel> and FormArray<FormGroup<FixedDepositSlabModel>> for slabs, etc.); update the form-building helper methods that create chart/slab/incentive controls (the functions that currently return plain FormGroup/FormArray instances) to return typed FormGroup<T>/FormArray<T> and adjust any getters and usages to treat .value as the typed model rather than any. Ensure all nested push/insert calls and value reads/writes are updated to the corresponding typed interfaces so the compiler enforces the shape across the chart/slab/incentive code paths.Source: Coding guidelines
src/app/products/deposit-product-incentive-form-dialog/deposit-product-incentive-form-dialog.component.ts (1)
56-56: ⚡ Quick winApply strict typing to the dialog form and
valueChangespayload.The component switched away from
Untyped*, butFormGroupis still untyped andattributeNameisany, so type safety is still mostly opt-out.As per coding guidelines,
src/app/**/*.ts: “Use TypeScript for all application code with strict typing conventions.”Also applies to: 95-105, 108-132
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/products/deposit-product-incentive-form-dialog/deposit-product-incentive-form-dialog.component.ts` at line 56, Declare a typed form model interface (e.g. DepositProductIncentiveFormModel) that lists each control (attributeName: string, amount: number, operator: string, type: string, etc.), change depositProductIncentiveForm from untyped FormGroup to FormGroup<DepositProductIncentiveFormModel> (or use FormBuilder.group with typed controls), replace any occurrences of attributeName: any with attributeName: string, and update the valueChanges subscription to accept a strongly-typed payload (value: DepositProductIncentiveFormModel) so all downstream usages inside the component (including the logic currently handling valueChanges) are statically typed.Source: Coding guidelines
src/app/products/loan-products/loan-product-stepper/loan-product-accounting-step/loan-product-accounting-step.component.ts (1)
681-688: ⚡ Quick winRemove no-op subscription with empty if/else blocks.
The
advancedAccountingRulessubscription in the working-capital branch subscribes to value changes but contains empty if/else blocks that perform no actions. This is dead code that wastes resources.♻️ Proposed fix
Remove the entire subscription since it has no side effects:
this.loanProductAccountingForm.addControl('advancedAccountingRules', new FormControl(false)); - - this.loanProductAccountingForm - .get('advancedAccountingRules') - .valueChanges.pipe(takeUntilDestroyed(this.destroyRef)) - .subscribe((advancedAccountingRules: boolean) => { - if (advancedAccountingRules) { - } else { - } - }); } });🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/products/loan-products/loan-product-stepper/loan-product-accounting-step/loan-product-accounting-step.component.ts` around lines 681 - 688, The subscription to this.loanProductAccountingForm.get('advancedAccountingRules').valueChanges (chained with .pipe(takeUntilDestroyed(this.destroyRef)).subscribe(...)) contains no-op if/else blocks and should be removed to eliminate dead code and unnecessary subscriptions; locate the subscribe call in loan-product-accounting-step.component.ts (the valueChanges subscription on advancedAccountingRules) and delete the entire subscription block, or if behavior was intended, replace the empty if/else with the actual handling logic for advancedAccountingRules inside the subscribe callback.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/app/products/charges/create-charge/create-charge.component.ts`:
- Around line 183-185: The current code mutates this.chargePaymentModeData in
place when filtering for Working Capital, causing subsequent chargeAppliesTo
changes to work on an already-narrowed list; fix by keeping an immutable source
list and assigning a filtered copy to the UI field instead of mutating it. Add
or use a preserved array (e.g., this.allChargePaymentModeData or
this._originalChargePaymentModeData) populated once, then in the handler for
chargeAppliesTo set this.chargePaymentModeData =
this._originalChargePaymentModeData.filter(...) when filtering for id === 0 and
otherwise restore the full list via this.chargePaymentModeData =
[...this._originalChargePaymentModeData]; ensure all references in
create-charge.component.ts (chargePaymentModeData, chargeAppliesTo) use this
assignment pattern rather than in-place .filter on the UI array.
- Around line 254-275: The switch handling for chargeAppliesTo can try to add an
already-existing control 'chargePaymentMode' (e.g., cases 1 and 5). Update the
logic in the create-charge.component.ts switch so before calling
this.chargeForm.addControl('chargePaymentMode', ...) you check whether the
control exists (this.chargeForm.get('chargePaymentMode') or contains) and only
add when absent; likewise, use removeControl only if the control exists. Apply
the existence checks around addControl/removeControl for 'chargePaymentMode'
(and similarly for 'incomeAccountId' if desired) in the switch block handling
chargeAppliesTo.
In `@src/app/products/charges/edit-charge/edit-charge.component.ts`:
- Line 205: The taxGroupId FormControl is initialized to an empty string which
breaks the submit cleanup that expects a falsy/null value when no tax group is
selected; change the initialization in chargeForm.addControl('taxGroupId', ...)
to create the control with a null value (e.g., this.formBuilder.control(null))
so charges.taxGroupId.value is null when unset and the existing submit logic
that removes/omits empty taxGroupId will work correctly.
In
`@src/app/products/fixed-deposit-products/fixed-deposit-product-stepper/fixed-deposit-product-accounting-step/fixed-deposit-product-accounting-step.component.ts`:
- Around line 225-311: The form currently calls addControl unconditionally when
accountingRule becomes 2 or 3, causing "control already exists" errors and
re-creating the nested advancedAccountingRules subscription on toggles; update
setConditionalControls to check for existing controls before adding (e.g., use
fixedDepositProductAccountingForm.contains('advancedAccountingRules') or
equivalent) and only call addControl for 'savingsReferenceAccountId',
'savingsControlAccountId', 'transfersInSuspenseAccountId',
'interestOnSavingsAccountId', 'incomeFromFeeAccountId',
'incomeFromPenaltyAccountId', 'feesReceivableAccountId',
'penaltiesReceivableAccountId', 'interestPayableAccountId' when they don't
already exist; likewise only attach the advancedAccountingRules.valueChanges
subscription once when you create that control (or guard subscription creation
with a flag/contains check) and keep the existing logic to remove related
mapping arrays ('paymentChannelToFundSourceMappings',
'feeToIncomeAccountMappings', 'penaltyToIncomeAccountMappings') when
advancedAccountingRules is false.
In
`@src/app/products/floating-rates/create-floating-rate/create-floating-rate.component.ts`:
- Around line 94-95: The component uses bare FormGroup and untyped form-related
data which loses compile-time shape information; change floatingRateForm in
CreateFloatingRateComponent to FormGroup<FloatingRateFormControls> (define
FloatingRateFormControls with name/isBaseLendingRate/isActive), update
createFloatingRatePeriodsForm() to return FormGroup<FloatingRateFormControls>
(or the correct controls type), and replace floatingRatePeriodForm in
FloatingRatePeriodDialogComponent with
FormGroup<FloatingRatePeriodDialogControls> (define
fromDate/interestRate/isDifferentialToBaseLendingRate types); also type
floatingRatePeriodsData (use a FloatingRatePeriod model),
MatTableDataSource<FloatingRatePeriod>, and the dialog afterClosed()
subscription to expect the typed dialog payload instead of any so form values
and dialog payloads are strictly typed end-to-end (update related method
signatures and service/dialog open/close payload types accordingly).
In
`@src/app/products/loan-products/working-capital/breach-configuration/create-breach-configuration/create-breach-configuration.component.ts`:
- Line 40: breachForm is untyped and route data/service methods use any; define
a concrete interface for the route payload (e.g., BreachTemplate {
breachFrequencyTypeOptions: StringEnumOptionData[];
breachAmountCalculationTypeOptions: StringEnumOptionData[]; ... }) and update
the route.data subscription signature to subscribe((data: { breachTemplate?:
BreachTemplate }) => ...) , replace breachForm: FormGroup with a strongly-typed
FormGroup e.g., FormGroup<{ name: FormControl<string>; breachFrequency:
FormControl<number>; breachFrequencyType: FormControl<string>;
breachAmountCalculationType: FormControl<string>; breachAmount:
FormControl<number> }> so getRawValue() returns a typed object, and update
ProductsService.createWrokingCapitalBreach(payload: any): Observable<any> to use
typed request/response interfaces (e.g., CreateBreachPayload /
CreateBreachResponse) and adjust usages accordingly
(create-breach-configuration.component.ts should pass the typed payload and
handle the typed response).
In
`@src/app/products/loan-products/working-capital/breach-configuration/edit-breach-configuration/edit-breach-configuration.component.ts`:
- Line 37: The breachForm field is untyped and the route data uses any; define a
typed interface for the route data payload (e.g., include breachTemplate and its
properties used by breachFrequencyTypeOptions and
breachAmountCalculationTypeOptions) and update the component to use that
interface for ActivatedRoute.data, then change breachForm: FormGroup to a
strongly typed FormGroup specifying the control keys and their types (e.g.,
FormGroup<{ controlName: FormControl<Type>; ... }>), ensuring the control names
match those used when building the form in this component (breachForm) and that
breachFrequencyTypeOptions and breachAmountCalculationTypeOptions are typed to
the option types from the route-data interface so all usages are strongly typed.
In
`@src/app/products/loan-products/working-capital/near-breach-configuration/create-near-breach-configuration/create-near-breach-configuration.component.ts`:
- Line 40: Replace untyped route data and FormGroup usage by declaring concrete
interfaces (e.g., NearBreachRouteData with breachTemplate and
breachFrequencyTypeOptions, and NearBreachFormValue describing the form fields)
and use them in the component: change nearBreachForm: FormGroup to
nearBreachForm: FormGroup<NearBreachFormValue>, update the ActivatedRoute
subscription signature from (data: { breachTemplate?: any }) to (data:
NearBreachRouteData) and stop using breachTemplate ?? {} fallback typing, and
then rely on the typed this.nearBreachForm.getRawValue() (or cast only where
necessary) so the payload and template fields are strongly typed throughout the
create-near-breach-configuration.component (references: nearBreachForm,
getRawValue(), breachTemplate, breachFrequencyTypeOptions, route.data).
In
`@src/app/products/loan-products/working-capital/near-breach-configuration/edit-near-breach-configuration/edit-near-breach-configuration.component.ts`:
- Line 37: The form and route data are untyped: change nearBreachForm: FormGroup
to a typed FormGroup<FormGroup<{...}>>/FormControl types that reflect the
payload used with getRawValue(), and replace the any in route.data.subscribe(...
breachTemplate: any ...) with a specific interface (e.g., an interface
containing breachFrequencyTypeOptions: StringEnumOptionData[]) so
breachFrequencyTypeOptions is strongly typed; apply the same fixes in
create-near-breach-configuration.component.ts (typed nearBreachForm and typed
breachTemplate) and update any form building and submit code to use the new
typed controls instead of untyped FormGroup/getRawValue usage.
In
`@src/app/products/manage-tax-components/create-tax-component/create-tax-component.component.ts`:
- Around line 117-130: When account type fields change, the code currently calls
FormGroup.addControl for 'debitAccountId'/'creditAccountId' which doesn't
replace existing controls and can leave stale values; update the subscriptions
on taxComponentForm.get('debitAccountType') and
taxComponentForm.get('creditAccountType') to use FormGroup.setControl (or
removeControl + addControl) so the control is replaced, and if the incoming type
is unset/empty remove the corresponding control entirely; keep using
getAccountsData to populate debitAccountData/creditAccountData and preserve the
existing takeUntilDestroyed(this.destroyRef) teardown.
In
`@src/app/products/saving-products/saving-product-stepper/saving-product-accounting-step/saving-product-accounting-step.component.ts`:
- Around line 214-320: The setConditionalControls function re-adds controls and
nests subscriptions every time accountingRule changes; fix it by (1) guarding
addControl/removeControl calls with existence checks (use
savingProductAccountingForm.contains(...) or check get(...) === null) so you
only add controls if missing and only remove if present, and (2) avoid creating
repeated inner subscriptions for allowOverdraft, isDormancyTrackingActive and
advancedAccountingRules by moving those valueChanges subscriptions out of the
accountingRule.valueChanges callback (subscribe once in setConditionalControls)
or by tracking and unsubscribing previous inner subscriptions (store them as
class properties and call unsubscribe before creating a new one) while keeping
takeUntilDestroyed on all top-level subscriptions; update references to
accountingRule, allowOverdraft, isDormancyTrackingActive,
advancedAccountingRules, addControl and removeControl accordingly.
---
Outside diff comments:
In
`@src/app/products/share-products/share-product-stepper/share-product-terms-step/share-product-terms-step.component.ts`:
- Around line 45-56: The combineLatest subscription created in ngOnInit
(listening to this.shareProductTermsForm.get('sharesIssued').valueChanges and
.get('unitPrice').valueChanges) is not torn down and will leak; update the
implementation to make the observable lifecycle-bound by piping the combined
stream through a teardown operator (for example pipe(takeUntil(this.destroy$))
using a component-level Subject destroy$ that is completed in ngOnDestroy, or
store the Subscription returned and unsubscribe in ngOnDestroy), then keep the
logic that sets
this.shareProductTermsForm.get('shareCapital').setValue(sharesIssued *
unitPrice) inside that subscription; ensure destroy$ (or the unsubscribe) is
defined on the component and invoked in ngOnDestroy.
---
Nitpick comments:
In
`@src/app/products/collaterals/create-collateral/create-collateral.component.ts`:
- Line 43: The collateralForm is declared as an untyped FormGroup; declare a
strongly-typed form model and update collateralForm to use FormGroup<T> (or
FormGroup<Record<key, FormControlType>>) so control access is typed. Create an
interface (e.g. CollateralFormModel) listing each control name and its type
(string, number, boolean, or specific value types), then initialize the form
with the typed builder (e.g. this.collateralForm =
this.fb.group<CollateralFormModel>({...}) or use NonNullableFormBuilder for
non-nullable controls), replacing bare FormControl/FormBuilder usages in the
component (collateralForm, FormBuilder initialization and form creation logic in
create-collateral.component) so everywhere you reference controls (get, value,
patchValue) benefits from strict typing.
In `@src/app/products/collaterals/edit-collateral/edit-collateral.component.ts`:
- Line 42: The collateralForm is currently declared as an untyped FormGroup;
replace it with a typed FormGroup describing each control (e.g. FormGroup<{
title: FormControl<string|null>, description: FormControl<string|null>, amount:
FormControl<number|null>, ... }>) and update its initialization in the component
(where you call new FormGroup(...) or this.fb.group(...)) to use FormControl<T>
(or this.fb.control<T>) and proper Validators so value/patchValue are
type-checked; adjust any usages in methods like the constructor/init block and
the code between the previously noted range (the form build and any
patchValue/value calls around lines 68-95) to match the new control types and
imports (FormGroup, FormControl, Validators) so compile-time checking enforces
correct shapes.
In
`@src/app/products/deposit-product-incentive-form-dialog/deposit-product-incentive-form-dialog.component.ts`:
- Line 56: Declare a typed form model interface (e.g.
DepositProductIncentiveFormModel) that lists each control (attributeName:
string, amount: number, operator: string, type: string, etc.), change
depositProductIncentiveForm from untyped FormGroup to
FormGroup<DepositProductIncentiveFormModel> (or use FormBuilder.group with typed
controls), replace any occurrences of attributeName: any with attributeName:
string, and update the valueChanges subscription to accept a strongly-typed
payload (value: DepositProductIncentiveFormModel) so all downstream usages
inside the component (including the logic currently handling valueChanges) are
statically typed.
In
`@src/app/products/fixed-deposit-products/fixed-deposit-product-stepper/fixed-deposit-product-interest-rate-chart-step/fixed-deposit-product-interest-rate-chart-step.component.ts`:
- Around line 96-97: Declare TypeScript interfaces for the nested form models
(e.g., FixedDepositChartModel, FixedDepositSlabModel,
FixedDepositIncentiveModel), then parameterize all untyped FormGroup and
FormArray instances and factory methods to use those interfaces (for example
change fixedDepositProductInterestRateChartForm: FormGroup to
FormGroup<FixedDepositChartModel> and
FormArray<FormGroup<FixedDepositSlabModel>> for slabs, etc.); update the
form-building helper methods that create chart/slab/incentive controls (the
functions that currently return plain FormGroup/FormArray instances) to return
typed FormGroup<T>/FormArray<T> and adjust any getters and usages to treat
.value as the typed model rather than any. Ensure all nested push/insert calls
and value reads/writes are updated to the corresponding typed interfaces so the
compiler enforces the shape across the chart/slab/incentive code paths.
In
`@src/app/products/loan-products/loan-product-stepper/loan-product-accounting-step/loan-product-accounting-step.component.ts`:
- Around line 681-688: The subscription to
this.loanProductAccountingForm.get('advancedAccountingRules').valueChanges
(chained with .pipe(takeUntilDestroyed(this.destroyRef)).subscribe(...))
contains no-op if/else blocks and should be removed to eliminate dead code and
unnecessary subscriptions; locate the subscribe call in
loan-product-accounting-step.component.ts (the valueChanges subscription on
advancedAccountingRules) and delete the entire subscription block, or if
behavior was intended, replace the empty if/else with the actual handling logic
for advancedAccountingRules inside the subscribe callback.
In
`@src/app/products/loan-products/working-capital/breach-configuration/view-breach-configuration/view-breach-configuration.component.ts`:
- Around line 35-36: The subscription currently types the route data as {
breachData: any } which loses type safety; update the typing to { breachData:
Breach | null } (matching the component's breachData property) and import the
Breach model/interface, then update the this.route.data.pipe(...).subscribe
signature accordingly (leave takeUntilDestroyed(this.destroyRef) and the
assignment to this.breachData intact); ensure any other usages in
view-breach-configuration.component.ts that rely on breachData reflect the
stronger type.
In
`@src/app/products/loan-products/working-capital/near-breach-configuration/view-near-breach-configuration/view-near-breach-configuration.component.ts`:
- Around line 37-38: The route data subscription currently types the payload as
{ nearBreachData: any } — update it to a strict type such as { nearBreachData:
NearBreach } (or { nearBreachData: NearBreach | null } if resolver may return
null) in the subscribe callback for route.data.pipe(...).subscribe, and ensure
the NearBreach interface/type is imported or defined in this component; also
update the component property this.nearBreachData to that same type so usages
inside view-near-breach-configuration.component.ts are type-safe.
In
`@src/app/products/manage-delinquency-buckets/delinquency-bucket/create-bucket/create-bucket.component.ts`:
- Line 72: The form and template payload are still untyped: replace the loose
bucketForm: FormGroup and the { delinquencyBucketsTemplateData: any } payload
with a concrete typed model (e.g., FormGroup<{ name: FormControl<string>;
description: FormControl<string | null>; ... }>) and a specific interface for
the resolver payload (e.g., DelinquencyBucketsTemplateData { /* fields */ });
update create-bucket.component.ts usages (bucketForm, any references to
delinquencyBucketsTemplateData, and methods that read/write controls like
buildForm/createForm/initForm) to use the new types so all form.controls and
resolver responses are strictly typed and prevent implicit any/shape drift.
In
`@src/app/products/manage-delinquency-buckets/delinquency-bucket/delinquency-bucket.component.ts`:
- Line 60: The fields and generics using any should be replaced with the
concrete bucket type used by this screen: define or import the DelinquencyBucket
interface and replace delinquencyBucketData: any with the properly typed
resolver shape (e.g. { delinquencyBuckets: DelinquencyBucket[] }), change
MatTableDataSource<any> to MatTableDataSource<DelinquencyBucket>, and update any
resolver/route data typings and usages (including the symbol delinquencyBuckets
and the table data source instantiation in the component) so all occurrences use
DelinquencyBucket instead of any.
In
`@src/app/products/manage-delinquency-buckets/delinquency-bucket/edit-bucket/edit-bucket.component.ts`:
- Line 72: The component currently declares bucketForm: FormGroup and leaves
resolver payloads as any; update EditBucketComponent to use a concrete form
interface (e.g., BucketForm or shared IBucketForm used by the create component)
and type the FormGroup as FormGroup<BucketForm> (or FormGroup<Record<...>>
matching your controls), and replace any resolver/route payload typings with
explicit interfaces (e.g., IBucketResolverData) instead of any so the component
methods that reference bucketForm, the resolver data, and related members are
fully typed and consistent with the create flow.
In
`@src/app/products/manage-delinquency-buckets/delinquency-bucket/view-bucket/view-bucket.component.ts`:
- Line 38: Replace the loose any types with the concrete DelinquencyBucket
interface: import or define the DelinquencyBucket model and change the route
data typing from { delinquencyBucket: any } to { delinquencyBucket:
DelinquencyBucket } and change the component property delinquencyBucketData: any
to delinquencyBucketData: DelinquencyBucket; also update any other occurrences
on lines referenced (e.g., the ActivatedRoute.data subscription or snapshot
access in the constructor/ngOnInit) to use DelinquencyBucket so the component
(view-bucket.component) and its route data are strictly typed.
In
`@src/app/products/manage-tax-groups/view-tax-group/view-tax-group.component.ts`:
- Around line 43-44: Replace the any typing on the route data with a concrete
interface: define an interface (e.g., TaxGroup or TaxGroupRouteData) describing
the expected properties (id, name, members, etc.) and use it in the subscription
and component property declarations so the subscription becomes
this.route.data.pipe(...).subscribe((data: { taxGroup: TaxGroup }) => {
this.taxGroupData = data.taxGroup; }) and change the type of taxGroupData
accordingly; also update any resolver or route typing that provides
data.taxGroup to return the same TaxGroup interface to keep types consistent
across ViewTaxGroupComponent and its resolver.
In
`@src/app/products/recurring-deposit-products/recurring-deposit-product-stepper/recurring-deposit-product-details-step/recurring-deposit-product-details-step.component.ts`:
- Line 32: The recurringDepositProductDetailsForm is currently an untyped
FormGroup — create a typed controls interface (e.g.
RecurringDepositProductDetailsFormControls) describing each control and its
FormControl type, then initialize the form using that interface so the form
variable is strongly typed (use
FormBuilder.group<RecurringDepositProductDetailsFormControls>(...) or new
FormGroup<RecurringDepositProductDetailsFormControls>(...)); update usages of
recurringDepositProductDetailsForm.value/patchValue to match the new typed shape
and adjust the private formBuilder = inject(FormBuilder) usage only to build the
strongly-typed form.
In
`@src/app/products/recurring-deposit-products/recurring-deposit-product-stepper/recurring-deposit-product-interest-rate-chart-step/recurring-deposit-product-interest-rate-chart-step.component.ts`:
- Line 95: The chart form is declared as an untyped FormGroup
(recurringDepositProductInterestRateChartForm) and several nested
arrays/controls are unbounded; define TypeScript interfaces for the chart, slab
and incentive models (e.g., RecurringDepositInterestChart, InterestSlab,
Incentive) and update the form types to use generics such as
FormGroup<RecurringDepositInterestChart>, FormArray<FormGroup<InterestSlab>> and
typed FormControl<T> for individual fields in methods that build/read the form
(look for places that create slabs/incentives and where values are read/written
around recurringDepositProductInterestRateChartForm); then update all accesses
to use the typed properties so the compiler enforces correct shapes and you can
safely map between form.value and your domain models.
In
`@src/app/products/recurring-deposit-products/recurring-deposit-product-stepper/recurring-deposit-product-terms-step/recurring-deposit-product-terms-step.component.ts`:
- Line 34: Replace the untyped recurringDepositProductTermsForm: FormGroup with
a strongly typed form model: define an interface (e.g.,
RecurringDepositProductTermsFormControls) that lists each control name and its
FormControl type (e.g., FormControl<number | null> or FormControl<string | null>
as appropriate), then change the field to recurringDepositProductTermsForm:
FormGroup<RecurringDepositProductTermsFormControls> and update the
formBuilder.group(...) initialization to use that generic so each control (names
used in this component) is strongly typed; ensure you import
FormControl/FormGroup types and adjust any code that reads controls to use the
typed keys.
In
`@src/app/products/recurring-deposit-products/recurring-deposit-products.component.ts`:
- Around line 217-228: The subscription to nextStepDialogRef.afterClosed() is
not tied to the component lifecycle and may run after teardown; modify the
component to use a destruction signal (e.g., a private destroy$ Subject and
implement ngOnDestroy) and pipe the afterClosed() observable through
takeUntil(this.destroy$) (or use first() where appropriate) before subscribing,
so the callback that updates configurationWizardService and calls
router.navigate is automatically unsubscribed when the component is destroyed;
update or add ngOnDestroy to emit/complete destroy$ and remove any direct naked
subscriptions.
In
`@src/app/products/saving-products/saving-product-stepper/saving-product-charges-step/saving-product-charges-step.component.ts`:
- Line 66: The Input property currencyCode uses a raw FormControl which lacks
value-type information; update the declaration for currencyCode to use a
FormControl generic with the correct value type (e.g., FormControl<string> or
FormControl<string | null> depending on whether null is allowed) so the
component and consumers get full type safety and better IDE completions; locate
the currencyCode Input in saving-product-charges-step.component.ts and change
its type accordingly and adjust any callers/initializations to match the tighter
type.
In
`@src/app/products/saving-products/saving-product-stepper/saving-product-details-step/saving-product-details-step.component.ts`:
- Line 36: The savingProductDetailsForm is declared as an untyped FormGroup; add
a generic type describing the form shape to gain full type-safety (e.g., create
an interface or inline type for fields like name, shortName, description and
change savingProductDetailsForm: FormGroup to FormGroup<{ name:
FormControl<string>; shortName: FormControl<string>; description:
FormControl<string>; }>) and update where the form is created/initialized
(constructor or ngOnInit) to use FormControl<string> and typed controls so
.value, .patchValue(), and control access (savingProductDetailsForm.get or
savingProductDetailsForm.controls) are correctly typed.
In
`@src/app/products/saving-products/saving-product-stepper/saving-product-terms-step/saving-product-terms-step.component.ts`:
- Line 34: The savingProductTermsForm property should declare a typed FormGroup
to get full type safety: update savingProductTermsForm to use FormGroup with a
generic describing the controls (e.g., keys like nominalAnnualInterestRate,
interestCompoundingPeriodType, interestCalculationType,
interestPostingPeriodType, minOpenBalanceRequired, maxOpenBalanceAllowed, etc.)
and their control types (FormControl<number | string | boolean> or
AbstractControl<number | string | boolean> as appropriate). Locate the
savingProductTermsForm declaration in the SavingProductTermsStepComponent and
change the type from FormGroup to FormGroup<{ <controlName>:
AbstractControl<...>; ... }> so the component, validators, and value accessors
are strongly typed throughout.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
d7e9548 to
3a8fb4e
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (6)
src/app/products/manage-tax-components/view-tax-component/view-tax-component.component.ts (1)
38-38: ⚡ Quick winConsider typing the tax component data.
Both
taxComponentData(line 38) and the route-data callback parameter (line 45) are typed asany. Per the project learning, introduce a specific interface for the tax component shape and update the resolver and component accordingly for stronger type safety.Also applies to: 45-45
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/products/manage-tax-components/view-tax-component/view-tax-component.component.ts` at line 38, Define a concrete interface (e.g., TaxComponent) representing the tax component shape (fields used in view-tax-component.component.ts and the resolver), replace the loose any types with that interface for the component property taxComponentData and for the ActivatedRoute data callback parameter, and update the resolver method return type to resolve to TaxComponent (or { taxComponent: TaxComponent } if you return an object); then adjust usages in ViewTaxComponentComponent (constructor/ngOnInit / route.data subscription) to use the new type to ensure compile-time safety.Source: Learnings
src/app/products/recurring-deposit-products/recurring-deposit-product-stepper/recurring-deposit-product-details-step/recurring-deposit-product-details-step.component.ts (1)
34-34: ⚡ Quick winConsider stronger typing for the form.
The
recurringDepositProductsTemplateinput (line 34) is typed asany, and theFormGroup(line 36) is not parameterized with a form interface. For stronger type safety, consider:
- Creating an interface for the template shape
- Parameterizing
FormGroupwith a form-value interface (e.g.,FormGroup<RecurringDepositDetailsForm>)Also applies to: 36-36
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/products/recurring-deposit-products/recurring-deposit-product-stepper/recurring-deposit-product-details-step/recurring-deposit-product-details-step.component.ts` at line 34, The recurringDepositProductsTemplate input is currently typed as any and the FormGroup on this component is untyped; create a concrete interface describing the template shape (e.g., interface RecurringDepositProductsTemplate { ... }) and a form value interface (e.g., interface RecurringDepositDetailsForm { fieldA: string; fieldB: number; ... }), then update the component to use these types by changing the Input to recurringDepositProductsTemplate: RecurringDepositProductsTemplate and parameterizing the form: FormGroup<RecurringDepositDetailsForm> (identify and update places referencing recurringDepositProductsTemplate and the FormGroup initialization to match the new interfaces).Sources: Coding guidelines, Learnings
src/app/products/loan-products/working-capital/near-breach-configuration/view-near-breach-configuration/view-near-breach-configuration.component.ts (1)
37-37: ⚡ Quick winConsider typing the route data callback parameter.
The
nearBreachDatais typed asany. Per the project learning, introduce a specific interface for the route-data shape instead ofany, and update the resolver accordingly for stronger type safety.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/products/loan-products/working-capital/near-breach-configuration/view-near-breach-configuration/view-near-breach-configuration.component.ts` at line 37, Introduce a concrete interface (e.g., NearBreachRouteData { nearBreachData: NearBreachDataType }) to replace the use of `any`, update the resolver that populates `nearBreachData` to return that typed shape, and change the `route.data.pipe(...).subscribe((data: { nearBreachData: any }) => {` callback to use the new interface (e.g., subscribe((data: NearBreachRouteData) => {)). Ensure `NearBreachDataType` matches the actual fields returned by the resolver and export it so both the resolver and the component import and share the same type for full type safety.Source: Learnings
src/app/products/saving-products/view-saving-product/view-saving-product.component.ts (1)
33-33: ⚡ Quick winConsider typing the datatable data.
The
savingProductDatatablesarray (line 33), route-data callback parameter (line 36), and forEach loop variable (line 38) are all typed asany. Per the project learning, introduce a specific interface for the datatable shape and update the resolver and component accordingly for stronger type safety.Also applies to: 36-36, 38-38
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/products/saving-products/view-saving-product/view-saving-product.component.ts` at line 33, The savingProductDatatables array and related route-data callback and forEach loop use the unsafe any type; define a specific interface (e.g., SavingProductDatatable or ISavingProductRow) that captures the datatable shape (fields used in the component/resolver), replace the any declarations on savingProductDatatables, the ActivatedRoute data callback parameter, and the forEach iterator with that interface, and update the resolver method that supplies the route data to return Observable/Promise of that typed structure so the component can consume strongly typed data (adjust imports and signatures for SavingProductDatatable in view-saving-product.component and the resolver).Source: Learnings
src/app/products/share-products/share-product-stepper/share-product-accounting-step/share-product-accounting-step.component.ts (1)
39-41: ⚡ Quick winConsider stronger typing for inputs and form.
Multiple areas use
anytyping:
- Input properties (lines 39-41)
- Account data properties (lines 45-48)
- The
accountingRulecallback parameter (line 87)- The
FormGroupis not parameterized (line 43)Per the project learning and strict typing guidelines, consider introducing specific interfaces for the template shapes, account data, and parameterizing
FormGroupwith a form-value interface (e.g.,FormGroup<ShareProductAccountingForm>).Also applies to: 43-43, 45-48, 87-87
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/products/share-products/share-product-stepper/share-product-accounting-step/share-product-accounting-step.component.ts` around lines 39 - 41, Several inputs and the form use any; define explicit interfaces (e.g., ShareProductsTemplate, AccountingRuleData, ShareProductAccountingForm) that describe the shapes used by `@Input`() shareProductsTemplate, `@Input`() accountingRuleData and the form value, then replace the any types and the untyped FormGroup with typed versions (e.g., FormGroup<ShareProductAccountingForm>), and update the accountingRule callback parameter to use the appropriate interface instead of any so references to accountingRule, shareProductsTemplate, accountingRuleData and the FormGroup are all strongly typed.Sources: Coding guidelines, Learnings
src/app/products/products-mix/products-mix.component.ts (1)
65-65: ⚡ Quick winConsider typing the products data.
The
productMixData(line 65),dataSourcegeneric parameter (line 69), and route-data callback parameter (line 80) are all typed asany. Per the project learning, introduce a specific interface for the product-mix shape and update the resolver, component, and table data source accordingly for stronger type safety.Also applies to: 69-69, 80-80
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/products/products-mix/products-mix.component.ts` at line 65, Introduce a concrete interface (e.g. ProductMix or ProductMixItem) describing the shape of each product-mix entry and replace the any types: change the component property productMixData: any to productMixData: ProductMix[] (or ProductMix), update the MatTableDataSource generic (dataSource: MatTableDataSource<ProductMix>) and change the ActivatedRoute data callback parameter to accept the typed resolver result (route.data.subscribe((data: { productMix: ProductMix[] }) => ...)). Also update the resolver return type to Promise/Observable<ProductMix[]> (or appropriate shape) so the types flow end-to-end.Source: Learnings
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In
`@src/app/products/loan-products/working-capital/near-breach-configuration/view-near-breach-configuration/view-near-breach-configuration.component.ts`:
- Line 37: Introduce a concrete interface (e.g., NearBreachRouteData {
nearBreachData: NearBreachDataType }) to replace the use of `any`, update the
resolver that populates `nearBreachData` to return that typed shape, and change
the `route.data.pipe(...).subscribe((data: { nearBreachData: any }) => {`
callback to use the new interface (e.g., subscribe((data: NearBreachRouteData)
=> {)). Ensure `NearBreachDataType` matches the actual fields returned by the
resolver and export it so both the resolver and the component import and share
the same type for full type safety.
In
`@src/app/products/manage-tax-components/view-tax-component/view-tax-component.component.ts`:
- Line 38: Define a concrete interface (e.g., TaxComponent) representing the tax
component shape (fields used in view-tax-component.component.ts and the
resolver), replace the loose any types with that interface for the component
property taxComponentData and for the ActivatedRoute data callback parameter,
and update the resolver method return type to resolve to TaxComponent (or {
taxComponent: TaxComponent } if you return an object); then adjust usages in
ViewTaxComponentComponent (constructor/ngOnInit / route.data subscription) to
use the new type to ensure compile-time safety.
In `@src/app/products/products-mix/products-mix.component.ts`:
- Line 65: Introduce a concrete interface (e.g. ProductMix or ProductMixItem)
describing the shape of each product-mix entry and replace the any types: change
the component property productMixData: any to productMixData: ProductMix[] (or
ProductMix), update the MatTableDataSource generic (dataSource:
MatTableDataSource<ProductMix>) and change the ActivatedRoute data callback
parameter to accept the typed resolver result (route.data.subscribe((data: {
productMix: ProductMix[] }) => ...)). Also update the resolver return type to
Promise/Observable<ProductMix[]> (or appropriate shape) so the types flow
end-to-end.
In
`@src/app/products/recurring-deposit-products/recurring-deposit-product-stepper/recurring-deposit-product-details-step/recurring-deposit-product-details-step.component.ts`:
- Line 34: The recurringDepositProductsTemplate input is currently typed as any
and the FormGroup on this component is untyped; create a concrete interface
describing the template shape (e.g., interface RecurringDepositProductsTemplate
{ ... }) and a form value interface (e.g., interface RecurringDepositDetailsForm
{ fieldA: string; fieldB: number; ... }), then update the component to use these
types by changing the Input to recurringDepositProductsTemplate:
RecurringDepositProductsTemplate and parameterizing the form:
FormGroup<RecurringDepositDetailsForm> (identify and update places referencing
recurringDepositProductsTemplate and the FormGroup initialization to match the
new interfaces).
In
`@src/app/products/saving-products/view-saving-product/view-saving-product.component.ts`:
- Line 33: The savingProductDatatables array and related route-data callback and
forEach loop use the unsafe any type; define a specific interface (e.g.,
SavingProductDatatable or ISavingProductRow) that captures the datatable shape
(fields used in the component/resolver), replace the any declarations on
savingProductDatatables, the ActivatedRoute data callback parameter, and the
forEach iterator with that interface, and update the resolver method that
supplies the route data to return Observable/Promise of that typed structure so
the component can consume strongly typed data (adjust imports and signatures for
SavingProductDatatable in view-saving-product.component and the resolver).
In
`@src/app/products/share-products/share-product-stepper/share-product-accounting-step/share-product-accounting-step.component.ts`:
- Around line 39-41: Several inputs and the form use any; define explicit
interfaces (e.g., ShareProductsTemplate, AccountingRuleData,
ShareProductAccountingForm) that describe the shapes used by `@Input`()
shareProductsTemplate, `@Input`() accountingRuleData and the form value, then
replace the any types and the untyped FormGroup with typed versions (e.g.,
FormGroup<ShareProductAccountingForm>), and update the accountingRule callback
parameter to use the appropriate interface instead of any so references to
accountingRule, shareProductsTemplate, accountingRuleData and the FormGroup are
all strongly typed.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 09ffcbb3-2552-4de5-869e-4796c8531f6b
📒 Files selected for processing (115)
src/app/products/charges/charges.component.tssrc/app/products/charges/create-charge/create-charge.component.tssrc/app/products/charges/edit-charge/edit-charge.component.tssrc/app/products/charges/view-charge/view-charge.component.tssrc/app/products/collaterals/collaterals.component.tssrc/app/products/collaterals/create-collateral/create-collateral.component.tssrc/app/products/collaterals/edit-collateral/edit-collateral.component.tssrc/app/products/collaterals/view-collateral/view-collateral.component.tssrc/app/products/deposit-product-incentive-form-dialog/deposit-product-incentive-form-dialog.component.tssrc/app/products/fixed-deposit-products/create-fixed-deposit-product/create-fixed-deposit-product.component.tssrc/app/products/fixed-deposit-products/edit-fixed-deposit-product/edit-fixed-deposit-product.component.tssrc/app/products/fixed-deposit-products/fixed-deposit-product-stepper/fixed-deposit-product-accounting-step/fixed-deposit-product-accounting-step.component.tssrc/app/products/fixed-deposit-products/fixed-deposit-product-stepper/fixed-deposit-product-charges-step/fixed-deposit-product-charges-step.component.tssrc/app/products/fixed-deposit-products/fixed-deposit-product-stepper/fixed-deposit-product-currency-step/fixed-deposit-product-currency-step.component.tssrc/app/products/fixed-deposit-products/fixed-deposit-product-stepper/fixed-deposit-product-details-step/fixed-deposit-product-details-step.component.tssrc/app/products/fixed-deposit-products/fixed-deposit-product-stepper/fixed-deposit-product-interest-rate-chart-step/fixed-deposit-product-interest-rate-chart-step.component.tssrc/app/products/fixed-deposit-products/fixed-deposit-product-stepper/fixed-deposit-product-settings-step/fixed-deposit-product-settings-step.component.tssrc/app/products/fixed-deposit-products/fixed-deposit-product-stepper/fixed-deposit-product-terms-step/fixed-deposit-product-terms-step.component.tssrc/app/products/fixed-deposit-products/fixed-deposit-products.component.tssrc/app/products/fixed-deposit-products/view-fixed-deposit-product/fixed-deposit-datatable-tab/fixed-deposit-datatable-tab.component.tssrc/app/products/fixed-deposit-products/view-fixed-deposit-product/fixed-deposit-general-tab/fixed-deposit-general-tab.component.tssrc/app/products/fixed-deposit-products/view-fixed-deposit-product/view-fixed-deposit-product.component.tssrc/app/products/floating-rates/create-floating-rate/create-floating-rate.component.tssrc/app/products/floating-rates/edit-floating-rate/edit-floating-rate.component.tssrc/app/products/floating-rates/floating-rate-period-dialog/floating-rate-period-dialog.component.tssrc/app/products/floating-rates/floating-rates.component.tssrc/app/products/floating-rates/view-floating-rate/view-floating-rate.component.tssrc/app/products/loan-products/create-loan-product/create-loan-product.component.tssrc/app/products/loan-products/edit-loan-product/edit-loan-product.component.tssrc/app/products/loan-products/import-loan-product-dialog/import-loan-product-dialog.component.tssrc/app/products/loan-products/loan-product-stepper/loan-product-accounting-step/advanced-accounting-mapping-rule/advanced-accounting-mapping-rule.component.tssrc/app/products/loan-products/loan-product-stepper/loan-product-accounting-step/loan-product-accounting-step.component.tssrc/app/products/loan-products/loan-product-stepper/loan-product-capitalized-income-step/loan-product-deferred-income-recognition-step.component.tssrc/app/products/loan-products/loan-product-stepper/loan-product-charges-step/loan-product-charges-step.component.tssrc/app/products/loan-products/loan-product-stepper/loan-product-currency-step/loan-product-currency-step.component.tssrc/app/products/loan-products/loan-product-stepper/loan-product-details-step/loan-product-details-step.component.tssrc/app/products/loan-products/loan-product-stepper/loan-product-interest-refund-step/loan-product-interest-refund-step.component.tssrc/app/products/loan-products/loan-product-stepper/loan-product-payment-strategy-step/advance-payment-allocation-tab/advance-payment-allocation-tab.component.tssrc/app/products/loan-products/loan-product-stepper/loan-product-settings-step/loan-product-settings-step.component.tssrc/app/products/loan-products/loan-product-stepper/loan-product-terms-step/loan-product-terms-step.component.tssrc/app/products/loan-products/loan-products.component.tssrc/app/products/loan-products/view-loan-product/datatable-tab/datatable-tab.component.tssrc/app/products/loan-products/view-loan-product/general-tab/general-tab.component.tssrc/app/products/loan-products/view-loan-product/view-loan-product.component.tssrc/app/products/loan-products/working-capital/breach-configuration/breach-configuration.component.tssrc/app/products/loan-products/working-capital/breach-configuration/create-breach-configuration/create-breach-configuration.component.tssrc/app/products/loan-products/working-capital/breach-configuration/edit-breach-configuration/edit-breach-configuration.component.tssrc/app/products/loan-products/working-capital/breach-configuration/view-breach-configuration/view-breach-configuration.component.tssrc/app/products/loan-products/working-capital/near-breach-configuration/create-near-breach-configuration/create-near-breach-configuration.component.tssrc/app/products/loan-products/working-capital/near-breach-configuration/edit-near-breach-configuration/edit-near-breach-configuration.component.tssrc/app/products/loan-products/working-capital/near-breach-configuration/near-breach-configuration.component.tssrc/app/products/loan-products/working-capital/near-breach-configuration/view-near-breach-configuration/view-near-breach-configuration.component.tssrc/app/products/loan-products/working-capital/working-capital-product.model.tssrc/app/products/manage-delinquency-buckets/delinquency-bucket/create-bucket/create-bucket.component.tssrc/app/products/manage-delinquency-buckets/delinquency-bucket/delinquency-bucket.component.tssrc/app/products/manage-delinquency-buckets/delinquency-bucket/edit-bucket/edit-bucket.component.tssrc/app/products/manage-delinquency-buckets/delinquency-bucket/view-bucket/view-bucket.component.tssrc/app/products/manage-delinquency-buckets/delinquency-range/create-range/create-range.component.tssrc/app/products/manage-delinquency-buckets/delinquency-range/delinquency-range.component.tssrc/app/products/manage-delinquency-buckets/delinquency-range/edit-range/edit-range.component.tssrc/app/products/manage-delinquency-buckets/delinquency-range/view-range/view-range.component.tssrc/app/products/manage-tax-components/create-tax-component/create-tax-component.component.tssrc/app/products/manage-tax-components/edit-tax-component/edit-tax-component.component.tssrc/app/products/manage-tax-components/manage-tax-components.component.tssrc/app/products/manage-tax-components/view-tax-component/view-tax-component.component.tssrc/app/products/manage-tax-groups/create-tax-group/create-tax-group.component.tssrc/app/products/manage-tax-groups/edit-tax-group/edit-tax-group.component.tssrc/app/products/manage-tax-groups/manage-tax-groups.component.tssrc/app/products/manage-tax-groups/view-tax-group/view-tax-group.component.tssrc/app/products/products-mix/create-product-mix/create-product-mix.component.tssrc/app/products/products-mix/edit-product-mix/edit-product-mix.component.tssrc/app/products/products-mix/products-mix.component.tssrc/app/products/products-mix/view-product-mix/view-product-mix.component.tssrc/app/products/products.service.tssrc/app/products/recurring-deposit-products/create-recurring-deposit-product/create-recurring-deposit-product.component.tssrc/app/products/recurring-deposit-products/edit-recurring-deposit-product/edit-recurring-deposit-product.component.tssrc/app/products/recurring-deposit-products/recurring-deposit-product-stepper/recurring-deposit-product-accounting-step/recurring-deposit-product-accounting-step.component.tssrc/app/products/recurring-deposit-products/recurring-deposit-product-stepper/recurring-deposit-product-charges-step/recurring-deposit-product-charges-step.component.tssrc/app/products/recurring-deposit-products/recurring-deposit-product-stepper/recurring-deposit-product-currency-step/recurring-deposit-product-currency-step.component.tssrc/app/products/recurring-deposit-products/recurring-deposit-product-stepper/recurring-deposit-product-details-step/recurring-deposit-product-details-step.component.tssrc/app/products/recurring-deposit-products/recurring-deposit-product-stepper/recurring-deposit-product-interest-rate-chart-step/recurring-deposit-product-interest-rate-chart-step.component.tssrc/app/products/recurring-deposit-products/recurring-deposit-product-stepper/recurring-deposit-product-settings-step/recurring-deposit-product-settings-step.component.tssrc/app/products/recurring-deposit-products/recurring-deposit-product-stepper/recurring-deposit-product-terms-step/recurring-deposit-product-terms-step.component.tssrc/app/products/recurring-deposit-products/recurring-deposit-products.component.tssrc/app/products/recurring-deposit-products/view-recurring-deposit-product/recurring-deposit-datatable-tab/recurring-deposit-datatable-tab.component.tssrc/app/products/recurring-deposit-products/view-recurring-deposit-product/recurring-deposit-general-tab/recurring-deposit-general-tab.component.tssrc/app/products/recurring-deposit-products/view-recurring-deposit-product/view-recurring-deposit-product.component.tssrc/app/products/saving-products/create-saving-product/create-saving-product.component.tssrc/app/products/saving-products/edit-saving-product/edit-saving-product.component.tssrc/app/products/saving-products/saving-product-stepper/saving-product-accounting-step/saving-product-accounting-step.component.tssrc/app/products/saving-products/saving-product-stepper/saving-product-charges-step/saving-product-charges-step.component.tssrc/app/products/saving-products/saving-product-stepper/saving-product-currency-step/saving-product-currency-step.component.tssrc/app/products/saving-products/saving-product-stepper/saving-product-details-step/saving-product-details-step.component.tssrc/app/products/saving-products/saving-product-stepper/saving-product-settings-step/saving-product-settings-step.component.tssrc/app/products/saving-products/saving-product-stepper/saving-product-terms-step/saving-product-terms-step.component.tssrc/app/products/saving-products/saving-products.component.tssrc/app/products/saving-products/view-saving-product/saving-product-datatable-tab/saving-product-datatable-tab.component.tssrc/app/products/saving-products/view-saving-product/saving-product-general-tab/saving-product-general-tab.component.tssrc/app/products/saving-products/view-saving-product/view-saving-product.component.tssrc/app/products/share-products/create-dividend/create-dividend.component.tssrc/app/products/share-products/create-share-product/create-share-product.component.tssrc/app/products/share-products/dividends-share-product/dividends.components.tssrc/app/products/share-products/edit-share-product/edit-share-product.component.tssrc/app/products/share-products/share-product-stepper/share-product-accounting-step/share-product-accounting-step.component.tssrc/app/products/share-products/share-product-stepper/share-product-charges-step/share-product-charges-step.component.tssrc/app/products/share-products/share-product-stepper/share-product-currency-step/share-product-currency-step.component.tssrc/app/products/share-products/share-product-stepper/share-product-details-step/share-product-details-step.component.tssrc/app/products/share-products/share-product-stepper/share-product-market-price-step/share-product-market-price-step.component.tssrc/app/products/share-products/share-product-stepper/share-product-settings-step/share-product-settings-step.component.tssrc/app/products/share-products/share-product-stepper/share-product-terms-step/share-product-terms-step.component.tssrc/app/products/share-products/share-products.component.tssrc/app/products/share-products/view-dividend/view-dividend.component.tssrc/app/products/share-products/view-share-product/share-product-datatable-tab/share-product-datatable-tab.component.tssrc/app/products/share-products/view-share-product/share-product-general-tab/share-product-general-tab.component.tssrc/app/products/share-products/view-share-product/view-share-product.component.ts
🚧 Files skipped from review as they are similar to previous changes (100)
- src/app/products/loan-products/working-capital/breach-configuration/view-breach-configuration/view-breach-configuration.component.ts
- src/app/products/collaterals/collaterals.component.ts
- src/app/products/share-products/share-product-stepper/share-product-currency-step/share-product-currency-step.component.ts
- src/app/products/manage-tax-groups/view-tax-group/view-tax-group.component.ts
- src/app/products/loan-products/loan-product-stepper/loan-product-accounting-step/advanced-accounting-mapping-rule/advanced-accounting-mapping-rule.component.ts
- src/app/products/floating-rates/floating-rates.component.ts
- src/app/products/charges/view-charge/view-charge.component.ts
- src/app/products/loan-products/view-loan-product/general-tab/general-tab.component.ts
- src/app/products/saving-products/saving-products.component.ts
- src/app/products/loan-products/loan-product-stepper/loan-product-details-step/loan-product-details-step.component.ts
- src/app/products/saving-products/saving-product-stepper/saving-product-terms-step/saving-product-terms-step.component.ts
- src/app/products/loan-products/view-loan-product/datatable-tab/datatable-tab.component.ts
- src/app/products/loan-products/view-loan-product/view-loan-product.component.ts
- src/app/products/loan-products/import-loan-product-dialog/import-loan-product-dialog.component.ts
- src/app/products/loan-products/working-capital/breach-configuration/breach-configuration.component.ts
- src/app/products/loan-products/working-capital/near-breach-configuration/create-near-breach-configuration/create-near-breach-configuration.component.ts
- src/app/products/recurring-deposit-products/recurring-deposit-products.component.ts
- src/app/products/manage-tax-components/manage-tax-components.component.ts
- src/app/products/fixed-deposit-products/fixed-deposit-products.component.ts
- src/app/products/manage-tax-groups/create-tax-group/create-tax-group.component.ts
- src/app/products/products-mix/create-product-mix/create-product-mix.component.ts
- src/app/products/share-products/view-share-product/share-product-datatable-tab/share-product-datatable-tab.component.ts
- src/app/products/recurring-deposit-products/edit-recurring-deposit-product/edit-recurring-deposit-product.component.ts
- src/app/products/recurring-deposit-products/view-recurring-deposit-product/view-recurring-deposit-product.component.ts
- src/app/products/products-mix/edit-product-mix/edit-product-mix.component.ts
- src/app/products/loan-products/loan-product-stepper/loan-product-interest-refund-step/loan-product-interest-refund-step.component.ts
- src/app/products/saving-products/edit-saving-product/edit-saving-product.component.ts
- src/app/products/fixed-deposit-products/fixed-deposit-product-stepper/fixed-deposit-product-terms-step/fixed-deposit-product-terms-step.component.ts
- src/app/products/saving-products/saving-product-stepper/saving-product-settings-step/saving-product-settings-step.component.ts
- src/app/products/collaterals/view-collateral/view-collateral.component.ts
- src/app/products/loan-products/working-capital/breach-configuration/edit-breach-configuration/edit-breach-configuration.component.ts
- src/app/products/loan-products/working-capital/breach-configuration/create-breach-configuration/create-breach-configuration.component.ts
- src/app/products/fixed-deposit-products/view-fixed-deposit-product/view-fixed-deposit-product.component.ts
- src/app/products/charges/charges.component.ts
- src/app/products/loan-products/loan-product-stepper/loan-product-currency-step/loan-product-currency-step.component.ts
- src/app/products/saving-products/view-saving-product/saving-product-datatable-tab/saving-product-datatable-tab.component.ts
- src/app/products/manage-delinquency-buckets/delinquency-bucket/view-bucket/view-bucket.component.ts
- src/app/products/share-products/view-dividend/view-dividend.component.ts
- src/app/products/recurring-deposit-products/recurring-deposit-product-stepper/recurring-deposit-product-currency-step/recurring-deposit-product-currency-step.component.ts
- src/app/products/fixed-deposit-products/fixed-deposit-product-stepper/fixed-deposit-product-currency-step/fixed-deposit-product-currency-step.component.ts
- src/app/products/products-mix/view-product-mix/view-product-mix.component.ts
- src/app/products/deposit-product-incentive-form-dialog/deposit-product-incentive-form-dialog.component.ts
- src/app/products/manage-delinquency-buckets/delinquency-bucket/delinquency-bucket.component.ts
- src/app/products/floating-rates/floating-rate-period-dialog/floating-rate-period-dialog.component.ts
- src/app/products/recurring-deposit-products/view-recurring-deposit-product/recurring-deposit-general-tab/recurring-deposit-general-tab.component.ts
- src/app/products/manage-delinquency-buckets/delinquency-range/view-range/view-range.component.ts
- src/app/products/manage-delinquency-buckets/delinquency-range/edit-range/edit-range.component.ts
- src/app/products/manage-tax-groups/manage-tax-groups.component.ts
- src/app/products/share-products/share-product-stepper/share-product-charges-step/share-product-charges-step.component.ts
- src/app/products/share-products/view-share-product/view-share-product.component.ts
- src/app/products/loan-products/working-capital/near-breach-configuration/edit-near-breach-configuration/edit-near-breach-configuration.component.ts
- src/app/products/share-products/edit-share-product/edit-share-product.component.ts
- src/app/products/saving-products/create-saving-product/create-saving-product.component.ts
- src/app/products/collaterals/create-collateral/create-collateral.component.ts
- src/app/products/share-products/share-product-stepper/share-product-details-step/share-product-details-step.component.ts
- src/app/products/fixed-deposit-products/view-fixed-deposit-product/fixed-deposit-datatable-tab/fixed-deposit-datatable-tab.component.ts
- src/app/products/manage-tax-components/edit-tax-component/edit-tax-component.component.ts
- src/app/products/fixed-deposit-products/create-fixed-deposit-product/create-fixed-deposit-product.component.ts
- src/app/products/share-products/share-product-stepper/share-product-market-price-step/share-product-market-price-step.component.ts
- src/app/products/recurring-deposit-products/recurring-deposit-product-stepper/recurring-deposit-product-terms-step/recurring-deposit-product-terms-step.component.ts
- src/app/products/loan-products/create-loan-product/create-loan-product.component.ts
- src/app/products/charges/create-charge/create-charge.component.ts
- src/app/products/loan-products/working-capital/near-breach-configuration/near-breach-configuration.component.ts
- src/app/products/manage-delinquency-buckets/delinquency-range/create-range/create-range.component.ts
- src/app/products/recurring-deposit-products/create-recurring-deposit-product/create-recurring-deposit-product.component.ts
- src/app/products/manage-tax-components/create-tax-component/create-tax-component.component.ts
- src/app/products/saving-products/saving-product-stepper/saving-product-currency-step/saving-product-currency-step.component.ts
- src/app/products/floating-rates/create-floating-rate/create-floating-rate.component.ts
- src/app/products/saving-products/view-saving-product/saving-product-general-tab/saving-product-general-tab.component.ts
- src/app/products/saving-products/saving-product-stepper/saving-product-charges-step/saving-product-charges-step.component.ts
- src/app/products/recurring-deposit-products/recurring-deposit-product-stepper/recurring-deposit-product-settings-step/recurring-deposit-product-settings-step.component.ts
- src/app/products/fixed-deposit-products/view-fixed-deposit-product/fixed-deposit-general-tab/fixed-deposit-general-tab.component.ts
- src/app/products/manage-delinquency-buckets/delinquency-bucket/create-bucket/create-bucket.component.ts
- src/app/products/fixed-deposit-products/fixed-deposit-product-stepper/fixed-deposit-product-charges-step/fixed-deposit-product-charges-step.component.ts
- src/app/products/recurring-deposit-products/view-recurring-deposit-product/recurring-deposit-datatable-tab/recurring-deposit-datatable-tab.component.ts
- src/app/products/manage-delinquency-buckets/delinquency-range/delinquency-range.component.ts
- src/app/products/share-products/dividends-share-product/dividends.components.ts
- src/app/products/loan-products/loan-products.component.ts
- src/app/products/share-products/create-share-product/create-share-product.component.ts
- src/app/products/fixed-deposit-products/fixed-deposit-product-stepper/fixed-deposit-product-details-step/fixed-deposit-product-details-step.component.ts
- src/app/products/floating-rates/edit-floating-rate/edit-floating-rate.component.ts
- src/app/products/recurring-deposit-products/recurring-deposit-product-stepper/recurring-deposit-product-charges-step/recurring-deposit-product-charges-step.component.ts
- src/app/products/share-products/share-product-stepper/share-product-terms-step/share-product-terms-step.component.ts
- src/app/products/loan-products/edit-loan-product/edit-loan-product.component.ts
- src/app/products/loan-products/loan-product-stepper/loan-product-charges-step/loan-product-charges-step.component.ts
- src/app/products/fixed-deposit-products/fixed-deposit-product-stepper/fixed-deposit-product-settings-step/fixed-deposit-product-settings-step.component.ts
- src/app/products/loan-products/loan-product-stepper/loan-product-capitalized-income-step/loan-product-deferred-income-recognition-step.component.ts
- src/app/products/share-products/view-share-product/share-product-general-tab/share-product-general-tab.component.ts
- src/app/products/recurring-deposit-products/recurring-deposit-product-stepper/recurring-deposit-product-interest-rate-chart-step/recurring-deposit-product-interest-rate-chart-step.component.ts
- src/app/products/saving-products/saving-product-stepper/saving-product-accounting-step/saving-product-accounting-step.component.ts
- src/app/products/manage-delinquency-buckets/delinquency-bucket/edit-bucket/edit-bucket.component.ts
- src/app/products/saving-products/saving-product-stepper/saving-product-details-step/saving-product-details-step.component.ts
- src/app/products/collaterals/edit-collateral/edit-collateral.component.ts
- src/app/products/fixed-deposit-products/fixed-deposit-product-stepper/fixed-deposit-product-interest-rate-chart-step/fixed-deposit-product-interest-rate-chart-step.component.ts
- src/app/products/recurring-deposit-products/recurring-deposit-product-stepper/recurring-deposit-product-accounting-step/recurring-deposit-product-accounting-step.component.ts
- src/app/products/loan-products/loan-product-stepper/loan-product-payment-strategy-step/advance-payment-allocation-tab/advance-payment-allocation-tab.component.ts
- src/app/products/loan-products/loan-product-stepper/loan-product-accounting-step/loan-product-accounting-step.component.ts
- src/app/products/fixed-deposit-products/fixed-deposit-product-stepper/fixed-deposit-product-accounting-step/fixed-deposit-product-accounting-step.component.ts
- src/app/products/loan-products/loan-product-stepper/loan-product-settings-step/loan-product-settings-step.component.ts
- src/app/products/loan-products/loan-product-stepper/loan-product-terms-step/loan-product-terms-step.component.ts
Description
Replace manual subscribe/unsubscribe patterns with DestroyRef + takeUntilDestroyed across products components and directives. Also replace UntypedFormBuilder/Group/Control/Array with typed Angular equivalents.
Related issues and discussion
WEB-954
Screenshots, if any
Checklist
Please make sure these boxes are checked before submitting your pull request - thanks!
If you have multiple commits please combine them into one commit by squashing them.
Read and understood the contribution guidelines at
web-app/.github/CONTRIBUTING.md.Summary by CodeRabbit