Add credit score provider pull

This commit is contained in:
MOHAN 2026-07-17 23:34:59 +05:30
parent 14dec26ccf
commit b4b07eda6b
3 changed files with 69 additions and 2 deletions

View File

@ -2,7 +2,7 @@ import { Body, Controller, Get, Post, Query } from "@nestjs/common";
import { CurrentUser } from "../common/decorators/current-user.decorator"; import { CurrentUser } from "../common/decorators/current-user.decorator";
import { ok } from "../common/response"; import { ok } from "../common/response";
import { CreditScoreService } from "./credit-score.service"; import { CreditScoreService } from "./credit-score.service";
import { CreateCreditScoreEntryDto } from "./dto"; import { CreateCreditScoreEntryDto, PullCreditScoreDto } from "./dto";
@Controller("credit-score") @Controller("credit-score")
export class CreditScoreController { export class CreditScoreController {
@ -22,4 +22,9 @@ export class CreditScoreController {
async createEntry(@CurrentUser() userId: string, @Body() body: CreateCreditScoreEntryDto) { async createEntry(@CurrentUser() userId: string, @Body() body: CreateCreditScoreEntryDto) {
return ok(await this.creditScoreService.createEntry(userId, body)); return ok(await this.creditScoreService.createEntry(userId, body));
} }
@Post("pull")
async pull(@CurrentUser() userId: string, @Body() body: PullCreditScoreDto) {
return ok(await this.creditScoreService.pullScore(userId, body));
}
} }

View File

@ -2,7 +2,9 @@ import { BadRequestException, Injectable } from "@nestjs/common";
import { Prisma } from "@prisma/client"; import { Prisma } from "@prisma/client";
import { NotificationsService } from "../notifications/notifications.service"; import { NotificationsService } from "../notifications/notifications.service";
import { PrismaService } from "../prisma/prisma.service"; import { PrismaService } from "../prisma/prisma.service";
import { CreateCreditScoreEntryDto } from "./dto"; import { CreateCreditScoreEntryDto, PullCreditScoreDto } from "./dto";
const SUPPORTED_CREDIT_PROVIDERS = ["sandbox"];
@Injectable() @Injectable()
export class CreditScoreService { export class CreditScoreService {
@ -79,6 +81,29 @@ export class CreditScoreService {
}; };
} }
async pullScore(userId: string, dto: PullCreditScoreDto) {
const provider = (dto.provider ?? process.env.CREDIT_SCORE_PROVIDER ?? "sandbox").toLowerCase();
if (!SUPPORTED_CREDIT_PROVIDERS.includes(provider)) {
throw new BadRequestException("Configured credit-score provider is not supported by this build.");
}
const pulled = await this.pullFromProvider(provider, userId, dto.bureau ?? "experian");
return this.createEntry(userId, {
score: pulled.score,
bureau: pulled.bureau,
source: "provider",
model: pulled.model,
scoreDate: pulled.scoreDate,
factors: pulled.factors,
metadata: {
provider,
providerPullId: pulled.providerPullId,
consent: dto.consent ?? {},
sandbox: provider === "sandbox",
},
});
}
async summary(userId: string) { async summary(userId: string) {
const entries = await this.listEntries(userId, "all"); const entries = await this.listEntries(userId, "all");
const latestByBureau = new Map<string, any>(); const latestByBureau = new Map<string, any>();
@ -118,4 +143,27 @@ export class CreditScoreService {
if (bureau === "transunion") return "TransUnion"; if (bureau === "transunion") return "TransUnion";
return "Credit"; return "Credit";
} }
private async pullFromProvider(provider: string, userId: string, bureau: "experian" | "equifax" | "transunion") {
if (provider !== "sandbox") {
throw new BadRequestException("Credit-score provider is not available.");
}
const seed = Array.from(`${userId}:${bureau}:${new Date().toISOString().slice(0, 10)}`)
.reduce((sum, char) => sum + char.charCodeAt(0), 0);
const score = 660 + (seed % 90);
return {
score,
bureau,
model: "vantage_score_3",
scoreDate: new Date().toISOString(),
providerPullId: `sandbox_credit_${seed}_${Date.now()}`,
factors: {
paymentHistory: "good",
utilization: seed % 3 === 0 ? "moderate" : "low",
accountAge: "established",
inquiries: seed % 2 === 0 ? "low" : "moderate",
},
};
}
} }

View File

@ -29,3 +29,17 @@ export class CreateCreditScoreEntryDto {
@IsObject() @IsObject()
metadata?: Record<string, unknown>; metadata?: Record<string, unknown>;
} }
export class PullCreditScoreDto {
@IsOptional()
@IsIn(["experian", "equifax", "transunion"])
bureau?: "experian" | "equifax" | "transunion";
@IsOptional()
@IsString()
provider?: string;
@IsOptional()
@IsObject()
consent?: Record<string, unknown>;
}