Files
dbis_core/src/core/accounting/accounting-standards.service.ts
defiQUG 849e6a8357
Some checks failed
CI / test (push) Has been cancelled
CI / security (push) Has been cancelled
CI / build (push) Has been cancelled
Initial commit
2025-12-12 15:02:56 -08:00

207 lines
4.7 KiB
TypeScript

// DBIS Accounting Standards Service
// Fair value marking, commodity feed integration
import prisma from '@/shared/database/prisma';
import { Decimal } from '@prisma/client/runtime/library';
export interface ValuationData {
assetType: string;
assetId: string;
fairValue: number;
currencyCode: string;
valuationDate: Date;
source: string;
}
export class AccountingStandardsService {
/**
* Get valuation rule for asset type
*/
async getValuationRule(assetType: string) {
return await prisma.valuationRule.findFirst({
where: {
assetType,
status: 'active',
effectiveDate: {
lte: new Date(),
},
OR: [
{ expiryDate: null },
{ expiryDate: { gte: new Date() } },
],
},
orderBy: { effectiveDate: 'desc' },
});
}
/**
* Mark asset to fair value
*/
async markToFairValue(assetId: string, assetType: string, fairValue: number, currencyCode: string) {
const rule = await this.getValuationRule(assetType);
if (!rule) {
throw new Error(`No valuation rule found for asset type: ${assetType}`);
}
// Update asset value based on type
switch (assetType) {
case 'commodity':
await this.updateCommodityValue(assetId, fairValue);
break;
case 'security':
await this.updateSecurityValue(assetId, fairValue);
break;
case 'fiat':
case 'cbdc':
// Fiat and CBDC are already at fair value
break;
default:
throw new Error(`Unsupported asset type for fair value marking: ${assetType}`);
}
// Log valuation
await prisma.auditLog.create({
data: {
eventType: 'valuation',
entityType: assetType,
entityId: assetId,
action: 'mark_to_fair_value',
details: {
fairValue,
currencyCode,
valuationMethod: rule.valuationMethod,
timestamp: new Date(),
},
},
});
}
/**
* Update commodity value
*/
private async updateCommodityValue(commodityId: string, fairValue: number) {
// In production, would update commodity price
// For now, update commodity spot price if exists
const commodity = await prisma.commodity.findFirst({
where: {
id: commodityId,
},
});
if (commodity) {
await prisma.commodity.update({
where: { id: commodityId },
data: {
spotPrice: new Decimal(fairValue),
lastUpdated: new Date(),
},
});
}
}
/**
* Update security value
*/
private async updateSecurityValue(securityId: string, fairValue: number) {
const security = await prisma.security.findFirst({
where: {
securityId,
},
});
if (security) {
await prisma.security.update({
where: { id: security.id },
data: {
price: new Decimal(fairValue),
updatedAt: new Date(),
},
});
}
}
/**
* Get commodity feed price
*/
async getCommodityFeedPrice(commodityType: string, unit: string): Promise<number | null> {
const commodity = await prisma.commodity.findUnique({
where: {
commodityType_unit: {
commodityType,
unit,
},
},
});
if (!commodity) {
return null;
}
return parseFloat(commodity.spotPrice.toString());
}
/**
* Get FX reference rate
*/
async getFXReferenceRate(baseCurrency: string, quoteCurrency: string): Promise<number | null> {
const fxPair = await prisma.fxPair.findFirst({
where: {
OR: [
{
baseCurrency,
quoteCurrency,
},
{
baseCurrency: quoteCurrency,
quoteCurrency: baseCurrency,
},
],
status: 'active',
},
include: {
trades: {
where: {
status: 'settled',
},
orderBy: { timestampUtc: 'desc' },
take: 1,
},
},
});
if (!fxPair || fxPair.trades.length === 0) {
return null;
}
return parseFloat(fxPair.trades[0].price.toString());
}
/**
* Create valuation rule
*/
async createValuationRule(
assetType: string,
valuationMethod: string,
feedSource?: string,
updateFrequency: string = 'real_time'
) {
return await prisma.valuationRule.create({
data: {
id: require('uuid').v4(),
ruleId: require('uuid').v4(),
assetType,
valuationMethod,
feedSource,
updateFrequency,
status: 'active',
effectiveDate: new Date(),
},
});
}
}
export const accountingStandardsService = new AccountingStandardsService();