diff --git a/apps/server/src/app/__tests__/insights.integration.spec.ts b/apps/server/src/app/__tests__/insights.integration.spec.ts index fe32ffef..029aa73f 100644 --- a/apps/server/src/app/__tests__/insights.integration.spec.ts +++ b/apps/server/src/app/__tests__/insights.integration.spec.ts @@ -1,5 +1,5 @@ import type { User } from '@prisma/client' -import { InvestmentTransactionCategory, Prisma, PrismaClient } from '@prisma/client' +import { AssetClass, InvestmentTransactionCategory, Prisma, PrismaClient } from '@prisma/client' import { createLogger, transports } from 'winston' import { DateTime } from 'luxon' import type { @@ -202,19 +202,25 @@ describe('insight service', () => { holdings: { create: [ { - security: { create: { symbol: 'AAPL', plaidType: 'equity' } }, + security: { + create: { symbol: 'AAPL', assetClass: AssetClass.stocks }, + }, quantity: 1, costBasisUser: 100, value: 200, }, { - security: { create: { symbol: 'NFLX', plaidType: 'equity' } }, + security: { + create: { symbol: 'NFLX', assetClass: AssetClass.stocks }, + }, quantity: 10, costBasisUser: 200, value: 300, }, { - security: { create: { symbol: 'SHOP', plaidType: 'equity' } }, + security: { + create: { symbol: 'SHOP', assetClass: AssetClass.stocks }, + }, quantity: 2, costBasisUser: 100, value: 50, diff --git a/libs/server/features/src/account/insight.service.ts b/libs/server/features/src/account/insight.service.ts index bfe44d9d..116e588e 100644 --- a/libs/server/features/src/account/insight.service.ts +++ b/libs/server/features/src/account/insight.service.ts @@ -641,14 +641,7 @@ export class InsightService implements IInsightService { INNER JOIN ( SELECT id, - CASE - -- plaid - WHEN plaid_type IN ('equity', 'etf', 'mutual fund', 'derivative') THEN 'stocks' - WHEN plaid_type IN ('fixed income') THEN 'fixed_income' - WHEN plaid_type IN ('cash', 'loan') THEN 'cash' - WHEN plaid_type IN ('cryptocurrency') THEN 'crypto' - ELSE 'other' - END AS "asset_class" + asset_class FROM "security" ) s ON s.id = h.security_id @@ -694,14 +687,7 @@ export class InsightService implements IInsightService { INNER JOIN security s ON s.id = h.security_id LEFT JOIN LATERAL ( SELECT - CASE - -- plaid - WHEN s.plaid_type IN ('equity', 'etf', 'mutual fund', 'derivative') THEN 'stocks' - WHEN s.plaid_type IN ('fixed income') THEN 'fixed_income' - WHEN s.plaid_type IN ('cash', 'loan') THEN 'cash' - WHEN s.plaid_type IN ('cryptocurrency') THEN 'crypto' - ELSE 'other' - END AS "category" + asset_class AS "category" ) x ON TRUE WHERE h.account_id IN ${accountIds} @@ -828,28 +814,21 @@ export class InsightService implements IInsightService { UNION ALL -- investment accounts SELECT - s.asset_type, + s.asset_class AS "asset_type", SUM(h.value) AS "amount" FROM holdings_enriched h INNER JOIN ( SELECT id, - CASE - -- plaid - WHEN plaid_type IN ('equity', 'etf', 'mutual fund', 'derivative') THEN 'stocks' - WHEN plaid_type IN ('fixed income') THEN 'bonds' - WHEN plaid_type IN ('cash', 'loan') THEN 'cash' - WHEN plaid_type IN ('cryptocurrency') THEN 'crypto' - ELSE 'other' - END AS "asset_type" + asset_class FROM "security" ) s ON s.id = h.security_id WHERE h.account_id IN ${pAccountIds} GROUP BY - s.asset_type + s.asset_class ) x GROUP BY 1 diff --git a/libs/server/features/src/plan/plan.service.ts b/libs/server/features/src/plan/plan.service.ts index b8fa4aca..9e0ba7a7 100644 --- a/libs/server/features/src/plan/plan.service.ts +++ b/libs/server/features/src/plan/plan.service.ts @@ -33,7 +33,7 @@ const PROJECTION_ASSET_PARAMS: { [type in SharedType.ProjectionAssetType]: [mean: Decimal.Value, stddev: Decimal.Value] } = { stocks: ['0.05', '0.186'], - bonds: ['0.02', '0.052'], + fixed_income: ['0.02', '0.052'], cash: ['-0.02', '0.05'], crypto: ['1.0', '1.0'], property: ['0.1', '0.2'], diff --git a/libs/shared/src/types/plan-types.ts b/libs/shared/src/types/plan-types.ts index 9b0f8d9c..97b46e5a 100644 --- a/libs/shared/src/types/plan-types.ts +++ b/libs/shared/src/types/plan-types.ts @@ -56,7 +56,13 @@ export type PlanProjectionResponse = { }[] } -export type ProjectionAssetType = 'stocks' | 'bonds' | 'cash' | 'crypto' | 'property' | 'other' +export type ProjectionAssetType = + | 'stocks' + | 'fixed_income' + | 'cash' + | 'crypto' + | 'property' + | 'other' export type ProjectionLiabilityType = 'credit' | 'loan' | 'other' export type PlanInsights = { diff --git a/prisma/migrations/20240121003016_add_asset_class_to_security/migration.sql b/prisma/migrations/20240121003016_add_asset_class_to_security/migration.sql new file mode 100644 index 00000000..23534f6f --- /dev/null +++ b/prisma/migrations/20240121003016_add_asset_class_to_security/migration.sql @@ -0,0 +1,6 @@ +-- CreateEnum +CREATE TYPE "AssetClass" AS ENUM ('cash', 'crypto', 'fixed_income', 'stocks', 'other'); + +-- AlterTable +ALTER TABLE "security" + ADD COLUMN "asset_class" "AssetClass" NOT NULL DEFAULT 'other'; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 349852d3..d6b31524 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -248,6 +248,14 @@ enum SecurityProvider { other } +enum AssetClass { + cash + crypto + fixed_income + stocks + other +} + model Security { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6) @@ -264,6 +272,7 @@ model Security { exchangeMic String? @map("exchange_mic") exchangeName String? @map("exchange_name") providerName SecurityProvider? @default(other) @map("provider_name") + assetClass AssetClass @default(other) @map("asset_class") // plaid data plaidSecurityId String? @unique @map("plaid_security_id")