feat(cc-052): FinancialIntelligenceController
This commit is contained in:
parent
b769613e49
commit
ebbbff123f
1 changed files with 66 additions and 0 deletions
|
|
@ -0,0 +1,66 @@
|
||||||
|
import { Body, Controller, Get, Post, Query } from '@nestjs/common';
|
||||||
|
import { desc, isNull, or, eq, and, gte } from 'drizzle-orm';
|
||||||
|
import { CurrentSession } from '../auth/session.decorator';
|
||||||
|
import type { AuthenticatedSession } from '../auth/tenant.guard';
|
||||||
|
import { db } from '../db/client';
|
||||||
|
import { financialSignals } from '../db/schema';
|
||||||
|
import { IngestSignalsDto } from './dto';
|
||||||
|
|
||||||
|
@Controller('financial-intelligence')
|
||||||
|
export class FinancialIntelligenceController {
|
||||||
|
/** GET /v1/financial-intelligence/signals — semnale active pentru tenant */
|
||||||
|
@Get('signals')
|
||||||
|
async signals(
|
||||||
|
@CurrentSession() session: AuthenticatedSession,
|
||||||
|
@Query('limit') limitStr?: string,
|
||||||
|
@Query('category') category?: string,
|
||||||
|
@Query('region') region?: string,
|
||||||
|
) {
|
||||||
|
const limit = Math.min(Math.max(1, parseInt(limitStr ?? '50', 10) || 50), 200);
|
||||||
|
const now = new Date();
|
||||||
|
|
||||||
|
const conditions = [
|
||||||
|
or(isNull(financialSignals.tenantId), eq(financialSignals.tenantId, session.tenantId)),
|
||||||
|
or(isNull(financialSignals.expiresAt), gte(financialSignals.expiresAt, now)),
|
||||||
|
];
|
||||||
|
if (category) conditions.push(eq(financialSignals.category, category));
|
||||||
|
if (region) conditions.push(eq(financialSignals.region, region));
|
||||||
|
|
||||||
|
return db.query.financialSignals.findMany({
|
||||||
|
where: and(...conditions),
|
||||||
|
orderBy: [desc(financialSignals.publishedAt)],
|
||||||
|
limit,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** POST /v1/financial-intelligence/ingest — webhook pentru n8n */
|
||||||
|
@Post('ingest')
|
||||||
|
async ingest(
|
||||||
|
@CurrentSession() session: AuthenticatedSession,
|
||||||
|
@Body() dto: IngestSignalsDto,
|
||||||
|
) {
|
||||||
|
if (!dto.signals || dto.signals.length === 0) {
|
||||||
|
return { ingested: 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
const rows = dto.signals.map((s) => ({
|
||||||
|
tenantId: dto.tenantId ?? null,
|
||||||
|
category: s.category ?? 'macro',
|
||||||
|
region: s.region ?? 'global',
|
||||||
|
niche: s.niche ?? null,
|
||||||
|
source: s.source,
|
||||||
|
indicatorCode: s.indicatorCode ?? null,
|
||||||
|
title: s.title,
|
||||||
|
summary: s.summary,
|
||||||
|
rawValue: s.rawValue != null ? String(s.rawValue) : null,
|
||||||
|
changePercent: s.changePercent != null ? String(s.changePercent) : null,
|
||||||
|
unit: s.unit ?? null,
|
||||||
|
severity: s.severity ?? 'info',
|
||||||
|
publishedAt: s.publishedAt ? new Date(s.publishedAt) : new Date(),
|
||||||
|
expiresAt: s.expiresAt ? new Date(s.expiresAt) : null,
|
||||||
|
}));
|
||||||
|
|
||||||
|
await db.insert(financialSignals).values(rows);
|
||||||
|
return { ingested: rows.length };
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue