mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
- Implemented utility to calculate wagon usage metrics for train schedules. - Created for sending wagons to maintenance with optional notes. - Added unit tests for train builder maintenance functionalities, including formatting train run labels and building maintenance notes. - Developed component for merging train schedules with detailed previews and reasons for merging. - Introduced component for selecting wagons with search functionality and selection limits. - Created for displaying and filtering audit logs, including detailed views of individual log entries. - Added for handling API interactions related to audit logs, including fetching logs and entity types.
80 lines
2.5 KiB
TypeScript
80 lines
2.5 KiB
TypeScript
import { Injectable } from '@nestjs/common';
|
|
import { BaseRepository } from '@edr/api-common';
|
|
import { InjectRepository } from '@nestjs/typeorm';
|
|
import { Between, FindOptionsWhere, LessThanOrEqual, MoreThanOrEqual, Repository } from 'typeorm';
|
|
import type { QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity';
|
|
|
|
import { AuditLog } from './entities/audit-log.entity';
|
|
|
|
export interface AuditLogQuery {
|
|
type?: string;
|
|
userId?: string;
|
|
method?: string;
|
|
isSuccess?: boolean;
|
|
resourceId?: string;
|
|
from?: Date;
|
|
to?: Date;
|
|
skip: number;
|
|
take: number;
|
|
}
|
|
|
|
@Injectable()
|
|
export class AuditLogRepository extends BaseRepository<AuditLog> {
|
|
constructor(
|
|
@InjectRepository(AuditLog)
|
|
private readonly auditLogRepository: Repository<AuditLog>,
|
|
) {
|
|
super(auditLogRepository);
|
|
}
|
|
|
|
/**
|
|
* Insert one audit row.
|
|
*
|
|
* `insert` rather than `save`: save would issue a SELECT first to decide
|
|
* between insert and update, which is wasted work for a table that is only
|
|
* ever appended to.
|
|
*/
|
|
async record(entry: Partial<AuditLog>): Promise<void> {
|
|
await this.auditLogRepository.insert(
|
|
entry as QueryDeepPartialEntity<AuditLog>,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Paginated, filtered read. Newest first — every index on this table is
|
|
* ordered `created_at DESC` to match.
|
|
*/
|
|
async search(query: AuditLogQuery): Promise<[AuditLog[], number]> {
|
|
const where: FindOptionsWhere<AuditLog> = {};
|
|
|
|
if (query.type) where.type = query.type;
|
|
if (query.userId) where.userId = query.userId;
|
|
if (query.method) where.method = query.method;
|
|
if (query.resourceId) where.resourceId = query.resourceId;
|
|
if (query.isSuccess !== undefined) where.isSuccess = query.isSuccess;
|
|
|
|
// Date range: either bound may be supplied alone.
|
|
if (query.from && query.to) where.createdAt = Between(query.from, query.to);
|
|
else if (query.from) where.createdAt = MoreThanOrEqual(query.from);
|
|
else if (query.to) where.createdAt = LessThanOrEqual(query.to);
|
|
|
|
return this.auditLogRepository.findAndCount({
|
|
where,
|
|
order: { createdAt: 'DESC' },
|
|
skip: query.skip,
|
|
take: query.take,
|
|
});
|
|
}
|
|
|
|
/** Distinct entity types present, for populating a filter dropdown. */
|
|
async distinctTypes(): Promise<string[]> {
|
|
const rows = await this.auditLogRepository
|
|
.createQueryBuilder('audit_log')
|
|
.select('DISTINCT audit_log.type', 'type')
|
|
.orderBy('audit_log.type', 'ASC')
|
|
.getRawMany<{ type: string }>();
|
|
|
|
return rows.map((row) => row.type);
|
|
}
|
|
}
|