Files
bigcapital/packages/server/src/modules/Bills/dtos/Bill.dto.ts
2025-10-28 18:12:08 +02:00

218 lines
4.2 KiB
TypeScript

import { ToNumber } from '@/common/decorators/Validators';
import { ItemEntryDto } from '@/modules/TransactionItemEntry/dto/ItemEntry.dto';
import { Type, Transform } from 'class-transformer';
import { parseBoolean } from '@/utils/parse-boolean';
import { ApiProperty } from '@nestjs/swagger';
import {
ArrayMinSize,
IsArray,
IsBoolean,
IsDate,
IsDateString,
IsEnum,
IsInt,
IsNotEmpty,
IsNumber,
IsOptional,
IsPositive,
IsString,
ValidateNested,
} from 'class-validator';
enum DiscountType {
Percentage = 'percentage',
Amount = 'amount',
}
export class BillEntryDto extends ItemEntryDto {
@ApiProperty({
description: 'Flag indicating whether the entry contributes to landed cost',
example: true,
required: false,
})
@IsOptional()
@IsBoolean()
@Transform(({ value }) => parseBoolean(value, false))
landedCost?: boolean;
}
class AttachmentDto {
@ApiProperty({
description: 'Storage key of the attachment file',
example: 'attachments/bills/receipt.pdf',
})
@IsString()
@IsNotEmpty()
key: string;
}
export class CommandBillDto {
@ApiProperty({
description: 'Unique bill number',
example: 'BILL-2024-001',
required: false,
})
@IsOptional()
@IsString()
billNumber: string;
@ApiProperty({
description: 'Reference number',
example: 'PO-2024-001',
required: false,
})
@IsOptional()
@IsString()
referenceNo?: string;
@ApiProperty({
description: 'Date the bill was issued',
example: '2024-03-15',
})
@IsNotEmpty()
@IsDateString()
billDate: Date;
@ApiProperty({
description: 'Date the bill is due',
example: '2024-04-15',
required: false,
})
@IsOptional()
@IsDateString()
dueDate?: Date;
@ApiProperty({
description: 'Vendor identifier',
example: 1001,
})
@IsInt()
@IsNotEmpty()
vendorId: number;
@ApiProperty({
description: 'Exchange rate applied to bill amounts',
example: 1.25,
required: false,
})
@IsOptional()
@ToNumber()
@IsNumber()
@IsPositive()
exchangeRate?: number;
@ApiProperty({
description: 'Warehouse identifier',
example: 101,
required: false,
})
@IsOptional()
@ToNumber()
@IsInt()
warehouseId?: number;
@ApiProperty({
description: 'Branch identifier',
example: 201,
required: false,
})
@IsOptional()
@ToNumber()
@IsInt()
branchId?: number;
@ApiProperty({
description: 'Project identifier',
example: 301,
required: false,
})
@IsOptional()
@ToNumber()
@IsInt()
projectId?: number;
@ApiProperty({
description: 'Additional notes about the bill',
example: 'Office supplies and equipment for Q2 2024',
required: false,
})
@IsOptional()
@IsString()
note?: string;
@ApiProperty({
description: 'Indicates if the bill is open',
example: true,
required: false,
})
@IsBoolean()
@IsOptional()
open: boolean = false;
@ApiProperty({
description: 'Indicates if tax is inclusive in prices',
example: false,
required: false,
})
@IsBoolean()
@IsOptional()
isInclusiveTax: boolean = false;
@ApiProperty({
description: 'Bill line items',
type: () => BillEntryDto,
isArray: true,
})
@IsArray()
@ValidateNested({ each: true })
@Type(() => BillEntryDto)
@ArrayMinSize(1)
entries: BillEntryDto[];
@ApiProperty({
description: 'File attachments associated with the bill',
type: () => AttachmentDto,
isArray: true,
required: false,
})
@IsOptional()
@IsArray()
@ValidateNested({ each: true })
@Type(() => AttachmentDto)
attachments?: AttachmentDto[];
@ApiProperty({
description: 'Type of discount applied',
example: DiscountType.Amount,
enum: DiscountType,
required: false,
})
@IsEnum(DiscountType)
@IsOptional()
discountType: DiscountType = DiscountType.Amount;
@ApiProperty({
description: 'Discount value',
example: 100,
required: false,
})
@IsOptional()
@ToNumber()
@IsNumber()
@IsPositive()
discount?: number;
@ApiProperty({
description: 'Adjustment value',
example: 50,
required: false,
})
@IsOptional()
@ToNumber()
@IsNumber()
adjustment?: number;
}
export class CreateBillDto extends CommandBillDto { }
export class EditBillDto extends CommandBillDto { }