feat(investment): non-SLR bonds and mutual funds, rate upload, UAT fixes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-27 11:14:41 +05:30
co-authored by Claude Opus 5.5
parent 8e98077158
commit 13d04353e1
13 changed files with 486 additions and 111 deletions
@@ -20,8 +20,10 @@ import {
InvestmentInterestReportDto,
InvestmentNonSlrLimitDto,
InvestmentPurchaseDto,
InvestmentSaleDto,
InvestmentService,
apiErrorMessage
apiErrorMessage,
bookValueSoldByPurchase
} from '../investment.service';
interface InstrumentSummary {
@@ -114,12 +116,13 @@ export class InvestmentDashboardComponent implements OnInit {
bucket: this.investmentService.getBucketReport(today),
interest: this.investmentService.getInterestReport(fyStart, today),
purchases: this.investmentService.getPurchases(),
sales: this.investmentService.getSales(),
fds: this.investmentService.getFds(),
fdQuote: this.investmentService.quoteFd({ amount: 0, intRate: 0, dealDate: today }),
nonSlr: this.investmentService.getNonSlrLimit(null, today, 0)
}).subscribe({
next: (r) => {
this.build(r.bucket, r.interest, r.purchases, r.fds, r.fdQuote.limit ?? null, r.nonSlr);
this.build(r.bucket, r.interest, r.purchases, r.sales, r.fds, r.fdQuote.limit ?? null, r.nonSlr);
this.loading = false;
},
error: (err: unknown) => {
@@ -133,6 +136,7 @@ export class InvestmentDashboardComponent implements OnInit {
bucket: InvestmentBucketReportDto,
interest: InvestmentInterestReportDto,
purchases: InvestmentPurchaseDto[],
sales: InvestmentSaleDto[],
fds: InvestmentFdDto[],
fdLimit: InvestmentFdLimitDto | null,
nonSlr: InvestmentNonSlrLimitDto
@@ -192,14 +196,16 @@ export class InvestmentDashboardComponent implements OnInit {
s.maturityValue +=
r.instrument === 'FD' ? (fdById.get(r.refId)?.expectedMaturityAmount ?? r.faceValue) : r.faceValue;
}
// Mutual funds and shares have no maturity, so they are not in the buckets; their units are held at cost.
// Mutual funds and shares have no maturity, so they are not in the buckets; the units still held are at cost.
const sold = bookValueSoldByPurchase(sales);
for (const p of purchases) {
if ((p.bondType === 'MUTUAL_FUND' || p.bondType === 'SHARE') && p.status === 'ACTIVE') {
const s = sum(p.bondType);
const book = p.bookValue - (sold.get(p.id) ?? 0);
s.count += 1;
s.faceValue += p.faceValue;
s.bookValue += p.bookValue;
s.maturityValue += p.bookValue;
s.faceValue += p.units ? (p.faceValue * p.balanceUnits) / p.units : p.faceValue;
s.bookValue += book;
s.maturityValue += book;
}
}
const order: InstrumentType[] = [