63 lines
2.8 KiB
TypeScript
63 lines
2.8 KiB
TypeScript
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;
|
|
};
|
|
|
|
/** Consulta definiciones por stockKey, nunca por nombres editables. */
|
|
export class ResourceDashboardReader {
|
|
constructor(private readonly database: Sequelize) {}
|
|
|
|
stats(companyId?: string) {
|
|
return this.database.query<{ companyId: string; count: number }>(
|
|
"SELECT companyId,COUNT(*) AS count FROM resources WHERE companyId IS NOT NULL AND (: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 expiry = issue === "certificate" || issue === "license";
|
|
const join = expiry
|
|
? " JOIN resource_definitions d ON d.id=r.templateId JOIN resource_definitions f ON f.stockKey='field:expires' JOIN resource_characteristics expiry ON expiry.resourceId=r.id AND expiry.fieldId=f.id"
|
|
: "";
|
|
const where =
|
|
"WHERE r.companyId IS NOT NULL AND (:companyId IS NULL OR r.companyId=:companyId)" +
|
|
(expiry
|
|
? " AND d.stockKey=:stockKey AND r.active=1 AND expiry.dateValue BETWEEN :today AND :until"
|
|
: "");
|
|
const today = new Date().toISOString().slice(0, 10);
|
|
const until = new Date(Date.now() + 30 * 86400000).toISOString().slice(0, 10);
|
|
const replacements = {
|
|
companyId: companyId ?? null,
|
|
stockKey: issue === "certificate" ? "template:certificate" : "template:software_license",
|
|
today,
|
|
until,
|
|
offset: (page - 1) * 10,
|
|
};
|
|
const counts = await this.database.query<{ total: number }>(
|
|
`SELECT COUNT(*) AS total FROM resources r ${join} ${where}`,
|
|
{ type: QueryTypes.SELECT, replacements }
|
|
);
|
|
const items = await this.database.query<Entry>(
|
|
`SELECT r.id,r.companyId,c.name AS companyName,r.name AS name,NULL AS recordedAt,NULL AS actorName FROM resources r JOIN companies c ON c.id=r.companyId ${join} ${where} ORDER BY name,r.id LIMIT 10 OFFSET :offset`,
|
|
{ type: QueryTypes.SELECT, replacements }
|
|
);
|
|
|
|
return { total: Number(counts[0]?.total ?? 0), items };
|
|
}
|
|
|
|
activity(companyId?: string) {
|
|
return this.database.query<Entry>(
|
|
"SELECT r.id,h.id AS eventId,r.companyId,c.name AS companyName,r.name AS name,h.recordedAt,u.name AS actorName FROM resource_revisions h JOIN resources r ON r.id=h.resourceId JOIN companies c ON c.id=r.companyId LEFT JOIN users u ON u.id=h.actorId WHERE r.companyId IS NOT NULL AND (:companyId IS NULL OR r.companyId=:companyId) ORDER BY h.recordedAt DESC,h.id DESC LIMIT 6",
|
|
{ type: QueryTypes.SELECT, replacements: { companyId: companyId ?? null } }
|
|
);
|
|
}
|
|
}
|