mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-30 12:18:11 +00:00
feat: enhance booking and audit log functionalities
- Implemented read-only locking for customer-requested container sizes and billing currency in the GlCreateBookingForm component. - Added functionality to lock partner quantities based on shipment requests in the ConsolidationPartnerPanel. - Introduced a new Leave action in the LogPassYardWorkModal to unassign bookings from trains. - Enhanced the AuditLogsPage to support filtering by action and added a Go button for direct navigation to entity detail pages. - Updated WagonCancellationsPage to handle odd-20ft credits requiring partner selection during rebooking. - Improved TrainScheduleV2DetailPage to allow manual loading of cargo and display warnings for unassigned bookings. - Added a new reference field to the audit logs for better searchability and tracking of actions. - Created a migration to add the reference column to the audit logs table and established an index for efficient querying. - Defined a registry for audit reference sources to streamline the retrieval of human identifiers for various entities.
This commit is contained in:
@@ -4,6 +4,10 @@ import { PaginatedResponse } from '@edr/types';
|
||||
import { AuditLog } from './entities/audit-log.entity';
|
||||
import { AuditLogRepository } from './audit-log.repository';
|
||||
import { AuditLogQueryDto } from './dto/audit-log-query.dto';
|
||||
import {
|
||||
AUDIT_REFERENCE_SOURCES,
|
||||
UUID_PATTERN,
|
||||
} from './audit-reference.registry';
|
||||
import {
|
||||
buildPaginationMeta,
|
||||
normalizePagination,
|
||||
@@ -25,6 +29,7 @@ export class AuditService {
|
||||
*/
|
||||
async record(entry: Partial<AuditLog>): Promise<void> {
|
||||
try {
|
||||
entry.reference = await this.resolveReference(entry.type, entry.resourceId);
|
||||
await this.auditLogRepository.record(entry);
|
||||
} catch (error) {
|
||||
this.logger.error(
|
||||
@@ -35,6 +40,34 @@ export class AuditService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Best-effort human identifier (booking reference, train number, …) for the
|
||||
* entity the action touched — one primary-key lookup against the table
|
||||
* registered for the type. Always returns a string: '' when the type has no
|
||||
* registered source, the id isn't a uuid (template codes), the row is gone,
|
||||
* or the lookup itself fails. A missing reference must never cost the audit
|
||||
* row, so failures degrade to '' rather than throwing.
|
||||
*/
|
||||
private async resolveReference(
|
||||
type: string | undefined,
|
||||
resourceId: string | null | undefined,
|
||||
): Promise<string> {
|
||||
const source = type ? AUDIT_REFERENCE_SOURCES[type] : undefined;
|
||||
if (!source || !resourceId || !UUID_PATTERN.test(resourceId)) return '';
|
||||
|
||||
try {
|
||||
const reference = await this.auditLogRepository.lookupReference(source, resourceId);
|
||||
return reference?.slice(0, 64) ?? '';
|
||||
} catch (error) {
|
||||
this.logger.warn(
|
||||
`Reference lookup failed for ${type} ${resourceId}: ${
|
||||
error instanceof Error ? error.message : String(error)
|
||||
}`,
|
||||
);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/** Paginated, filtered audit history, newest first. */
|
||||
async search(query: AuditLogQueryDto): Promise<PaginatedResponse<AuditLog>> {
|
||||
const { page, pageSize, skip, take } = normalizePagination(query);
|
||||
@@ -53,6 +86,10 @@ export class AuditService {
|
||||
userId: query.userId,
|
||||
method: query.method,
|
||||
resourceId: query.resourceId,
|
||||
reference: query.reference,
|
||||
userName: query.userName,
|
||||
title: query.title,
|
||||
q: query.q,
|
||||
isSuccess:
|
||||
query.isSuccess === undefined ? undefined : query.isSuccess === 'true',
|
||||
from,
|
||||
@@ -68,4 +105,9 @@ export class AuditService {
|
||||
async listTypes(): Promise<string[]> {
|
||||
return this.auditLogRepository.distinctTypes();
|
||||
}
|
||||
|
||||
/** Distinct action titles, for the action filter dropdown. */
|
||||
async listActions(): Promise<string[]> {
|
||||
return this.auditLogRepository.distinctTitles();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user