import type { Sequelize } from "sequelize"; import { QueryTypes } from "sequelize"; type Entry = { eventId?: string; id: string; companyId: string; companyName: string; name: string; recordedAt: string | null; actorName: string | null; }; /** Proyección de lectura acotada; no reconstruye inventarios ni agregados. */ export class AssetDashboardReader { constructor(private readonly database: Sequelize) {} stats(companyId?: string) { return this.database.query<{ companyId: string; count: number }>( "SELECT companyId,COUNT(*) AS count FROM assets WHERE (:companyId IS NULL OR companyId=:companyId) GROUP BY companyId", { type: QueryTypes.SELECT, replacements: { companyId: companyId ?? null } } ); } async entries(companyId?: string, issue?: string, page = 1) { const where = "WHERE (:companyId IS NULL OR a.companyId=:companyId)" + (issue === "missing_site" ? " AND a.siteId IS NULL" : ""); const replacements = { companyId: companyId ?? null, offset: (page - 1) * 10 }; const counts = await this.database.query<{ total: number }>( `SELECT COUNT(*) AS total FROM assets a ${where}`, { type: QueryTypes.SELECT, replacements } ); const items = await this.database.query( `SELECT a.id,a.companyId,c.name AS companyName,JSON_UNQUOTE(JSON_EXTRACT(a.\`values\`,'$.name')) AS name,NULL AS recordedAt,NULL AS actorName FROM assets a JOIN companies c ON c.id=a.companyId ${where} ORDER BY name,a.id LIMIT 10 OFFSET :offset`, { type: QueryTypes.SELECT, replacements } ); return { total: Number(counts[0]?.total ?? 0), items }; } inactivePeople(companyId?: string) { return this.database.query<{ id: string }>( "SELECT DISTINCT p.id FROM assets a JOIN company_contacts p ON p.id=a.personId AND p.companyId=a.companyId WHERE p.active=0 AND JSON_UNQUOTE(JSON_EXTRACT(a.`values`,'$.status')) <> 'retired' AND (:companyId IS NULL OR a.companyId=:companyId)", { type: QueryTypes.SELECT, replacements: { companyId: companyId ?? null } } ); } activity(companyId?: string) { return this.database.query( "SELECT a.id,r.id AS eventId,a.companyId,c.name AS companyName,JSON_UNQUOTE(JSON_EXTRACT(a.`values`,'$.name')) AS name,r.recordedAt,u.name AS actorName FROM asset_revisions r JOIN assets a ON a.id=r.assetId JOIN companies c ON c.id=a.companyId LEFT JOIN users u ON u.id=r.actorId WHERE (:companyId IS NULL OR a.companyId=:companyId) ORDER BY r.recordedAt DESC,r.id DESC LIMIT 6", { type: QueryTypes.SELECT, replacements: { companyId: companyId ?? null } } ); } }