feat: add wagon usage computation and maintenance logging features

- 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.
This commit is contained in:
marshalyordanos
2026-08-12 09:36:50 +03:00
parent 35e5404b41
commit 5da36eb128
77 changed files with 6275 additions and 296 deletions

View File

@@ -0,0 +1,64 @@
import { ApiPropertyOptional } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
import { IsBooleanString, IsIn, IsISO8601, IsOptional, IsString, IsUUID, MaxLength } from 'class-validator';
import { PaginationQueryDto } from '../../../common/dto/pagination-query.dto';
const AUDITED_METHODS = ['POST', 'PUT', 'PATCH', 'DELETE'] as const;
/**
* Filters for the audit log read endpoint.
*
* Extends the shared pagination DTO so page/pageSize behave (and are capped)
* exactly as they do on every other list endpoint.
*/
export class AuditLogQueryDto extends PaginationQueryDto {
@ApiPropertyOptional({
description: 'Entity type, e.g. "Contract", "Booking", "Locomotive".',
example: 'Contract',
})
@IsOptional()
@IsString()
@MaxLength(50)
type?: string;
@ApiPropertyOptional({ description: 'IAM id of the acting backoffice user.' })
@IsOptional()
@IsUUID()
userId?: string;
@ApiPropertyOptional({ enum: AUDITED_METHODS })
@IsOptional()
@Transform(({ value }) => String(value).toUpperCase())
@IsIn([...AUDITED_METHODS])
method?: string;
@ApiPropertyOptional({ description: 'Id of the affected record.' })
@IsOptional()
@IsString()
@MaxLength(64)
resourceId?: string;
@ApiPropertyOptional({
description: 'Filter by outcome: true = succeeded, false = failed.',
})
@IsOptional()
@IsBooleanString()
isSuccess?: string;
@ApiPropertyOptional({
description: 'Inclusive start of the range (ISO 8601).',
example: '2026-01-01T00:00:00.000Z',
})
@IsOptional()
@IsISO8601()
from?: string;
@ApiPropertyOptional({
description: 'Inclusive end of the range (ISO 8601).',
example: '2026-01-31T23:59:59.999Z',
})
@IsOptional()
@IsISO8601()
to?: string;
}