Files
edr-platform/apps/edr-freight-api/src/modules/contracts/dto/sign-contract.dto.ts
Marshal fde5e6de4b add company stamp upload functionality for contract signing
- Introduced StampUpload component for uploading company stamp images.
- Integrated stamp upload in contract signing modal, supporting PNG and JPG formats.
- Implemented validation for file type and size (max 5 MB).
- Added visual feedback for drag-and-drop functionality.
- Updated contract-related pages to handle duplicate contract alerts and pricing notices.
- Enhanced contract expiry management with a nightly sweep service.
- Added unit tests for new features and updated existing tests for contract handling.
2026-07-25 17:14:58 +00:00

52 lines
1.7 KiB
TypeScript

import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { IsIn, IsOptional, IsString, Matches, MinLength } from 'class-validator';
export class SignContractDto {
@ApiProperty({ enum: ['CUSTOMER', 'STAFF', 'DIRECTOR', 'CEO'] })
@IsIn(['CUSTOMER', 'STAFF', 'DIRECTOR', 'CEO'])
role!: 'CUSTOMER' | 'STAFF' | 'DIRECTOR' | 'CEO';
@ApiPropertyOptional({
description:
'PNG signature image as base64 (with or without data URL prefix). ' +
'Optional: when omitted, the signer\'s reusable saved signature from their ' +
'profile is used instead.',
})
@IsOptional()
@IsString()
@MinLength(20)
signatureImageBase64?: string;
@ApiPropertyOptional({
description:
'PNG company stamp/seal image as base64 (with or without data URL prefix). ' +
'Required for the CUSTOMER and STAFF roles — both parties must seal the ' +
'contract before it is fully executed.',
})
@IsOptional()
@IsString()
@MinLength(20)
stampImageBase64?: string;
@ApiProperty()
@IsString()
@MinLength(1)
signerDisplayName!: string;
@ApiPropertyOptional()
@IsOptional()
@IsString()
consentText?: string;
// Sudo-mode OTP challenge. Required when role=CUSTOMER: a fresh 6-digit code
// SMS'd to the signer's registered phone, verified server-side before the
// signature is applied. The number itself is deliberately NOT part of this
// DTO — the server resolves it from the authenticated user id, so a caller
// cannot redirect the challenge to a phone they control.
@ApiPropertyOptional({ description: '6-digit OTP; required when role=CUSTOMER' })
@IsOptional()
@IsString()
@Matches(/^\d{6}$/, { message: 'otp must be 6 digits' })
otp?: string;
}