refactor(nestjs): wip dtos validation schema

This commit is contained in:
Ahmed Bouhuolia
2025-05-26 17:04:53 +02:00
parent 24bf3dd06d
commit 83c9392b74
8 changed files with 116 additions and 42 deletions

View File

@@ -15,11 +15,15 @@ import {
EditBillPaymentDto, EditBillPaymentDto,
} from './dtos/BillPayment.dto'; } from './dtos/BillPayment.dto';
import { GetBillPaymentsFilterDto } from './dtos/GetBillPaymentsFilter.dto'; import { GetBillPaymentsFilterDto } from './dtos/GetBillPaymentsFilter.dto';
import { BillPaymentsPages } from './commands/BillPaymentsPages.service';
@Controller('bill-payments') @Controller('bill-payments')
@ApiTags('bill-payments') @ApiTags('bill-payments')
export class BillPaymentsController { export class BillPaymentsController {
constructor(private billPaymentsApplication: BillPaymentsApplication) {} constructor(
private billPaymentsApplication: BillPaymentsApplication,
private billPaymentsPagesService: BillPaymentsPages,
) {}
@Post() @Post()
@ApiOperation({ summary: 'Create a new bill payment.' }) @ApiOperation({ summary: 'Create a new bill payment.' })
@@ -59,6 +63,24 @@ export class BillPaymentsController {
); );
} }
@Get('/new-page/entries')
@ApiOperation({
summary:
'Retrieves the payable entries of the new page once vendor be selected.',
})
@ApiParam({
name: 'vendorId',
required: true,
type: Number,
description: 'The vendor id',
})
async getBillPaymentNewPageEntries(@Query('vendorId') vendorId: number) {
const entries =
await this.billPaymentsPagesService.getNewPageEntries(vendorId);
return entries;
}
@Get(':billPaymentId/bills') @Get(':billPaymentId/bills')
@ApiOperation({ summary: 'Retrieves the bills of the given bill payment.' }) @ApiOperation({ summary: 'Retrieves the bills of the given bill payment.' })
@ApiParam({ @ApiParam({
@@ -71,6 +93,25 @@ export class BillPaymentsController {
return this.billPaymentsApplication.getPaymentBills(Number(billPaymentId)); return this.billPaymentsApplication.getPaymentBills(Number(billPaymentId));
} }
@Get('/:billPaymentId/edit-page')
@ApiOperation({
summary: 'Retrieves the edit page of the given bill payment.',
})
@ApiParam({
name: 'billPaymentId',
required: true,
type: Number,
description: 'The bill payment id',
})
public async getBillPaymentEditPage(
@Param('billPaymentId') billPaymentId: number,
) {
const billPaymentsWithEditEntries =
await this.billPaymentsPagesService.getBillPaymentEditPage(billPaymentId);
return billPaymentsWithEditEntries;
}
@Get(':billPaymentId') @Get(':billPaymentId')
@ApiOperation({ summary: 'Retrieves the bill payment details.' }) @ApiOperation({ summary: 'Retrieves the bill payment details.' })
@ApiParam({ @ApiParam({
@@ -83,8 +124,14 @@ export class BillPaymentsController {
return this.billPaymentsApplication.getBillPayment(Number(billPaymentId)); return this.billPaymentsApplication.getBillPayment(Number(billPaymentId));
} }
@Get('') @Get()
@ApiOperation({ summary: 'Retrieves the bill payments list.' }) @ApiOperation({ summary: 'Retrieves the bill payments list.' })
@ApiParam({
name: 'filterDTO',
required: true,
type: GetBillPaymentsFilterDto,
description: 'The bill payments filter dto',
})
public getBillPayments(@Query() filterDTO: GetBillPaymentsFilterDto) { public getBillPayments(@Query() filterDTO: GetBillPaymentsFilterDto) {
return this.billPaymentsApplication.getBillPayments(filterDTO); return this.billPaymentsApplication.getBillPayments(filterDTO);
} }

View File

@@ -20,6 +20,7 @@ import { BillPaymentsExportable } from './queries/BillPaymentsExportable';
import { BillPaymentsImportable } from './commands/BillPaymentsImportable'; import { BillPaymentsImportable } from './commands/BillPaymentsImportable';
import { GetBillPaymentsService } from './queries/GetBillPayments.service'; import { GetBillPaymentsService } from './queries/GetBillPayments.service';
import { DynamicListModule } from '../DynamicListing/DynamicList.module'; import { DynamicListModule } from '../DynamicListing/DynamicList.module';
import { BillPaymentsPages } from './commands/BillPaymentsPages.service';
@Module({ @Module({
imports: [LedgerModule, AccountsModule, DynamicListModule], imports: [LedgerModule, AccountsModule, DynamicListModule],
@@ -41,6 +42,7 @@ import { DynamicListModule } from '../DynamicListing/DynamicList.module';
BillPaymentsExportable, BillPaymentsExportable,
BillPaymentsImportable, BillPaymentsImportable,
GetBillPaymentsService, GetBillPaymentsService,
BillPaymentsPages,
], ],
exports: [ exports: [
BillPaymentValidators, BillPaymentValidators,

View File

@@ -8,7 +8,7 @@ import { ServiceError } from '../../Items/ServiceError';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
@Injectable() @Injectable()
export default class BillPaymentsPages { export class BillPaymentsPages {
/** /**
* @param {TenantModelProxy<typeof Bill>} billModel - Bill model. * @param {TenantModelProxy<typeof Bill>} billModel - Bill model.
* @param {TenantModelProxy<typeof BillPayment>} billPaymentModel - Bill payment model. * @param {TenantModelProxy<typeof BillPayment>} billPaymentModel - Bill payment model.

View File

@@ -1,7 +1,8 @@
import { ApiProperty } from '@nestjs/swagger';
import { Type } from 'class-transformer'; import { Type } from 'class-transformer';
import { import {
IsArray, IsArray,
IsDate, IsDateString,
IsNotEmpty, IsNotEmpty,
IsNumber, IsNumber,
IsOptional, IsOptional,
@@ -9,25 +10,33 @@ import {
ValidateNested, ValidateNested,
} from 'class-validator'; } from 'class-validator';
import { AttachmentLinkDto } from '@/modules/Attachments/dtos/Attachment.dto'; import { AttachmentLinkDto } from '@/modules/Attachments/dtos/Attachment.dto';
import { ApiProperty } from '@nestjs/swagger'; import { ToNumber } from '@/common/decorators/Validators';
export class BillPaymentEntryDto { export class BillPaymentEntryDto {
@ToNumber()
@IsNumber() @IsNumber()
@IsNotEmpty()
@ApiProperty({ description: 'The id of the bill', example: 1 })
billId: number; billId: number;
@ToNumber()
@IsNumber() @IsNumber()
@IsNotEmpty()
@ApiProperty({
description: 'The payment amount of the bill payment',
example: 100,
})
paymentAmount: number; paymentAmount: number;
} }
export class CommandBillPaymentDTO { export class CommandBillPaymentDTO {
@ToNumber()
@IsNumber() @IsNumber()
@IsNotEmpty() @IsNotEmpty()
@ApiProperty({ @ApiProperty({ description: 'The id of the vendor', example: 1 })
description: 'The id of the vendor',
example: 1,
})
vendorId: number; vendorId: number;
@ToNumber()
@IsNumber() @IsNumber()
@IsOptional() @IsOptional()
@ApiProperty({ @ApiProperty({
@@ -36,12 +45,10 @@ export class CommandBillPaymentDTO {
}) })
amount?: number; amount?: number;
@ToNumber()
@IsNumber() @IsNumber()
@IsNotEmpty() @IsNotEmpty()
@ApiProperty({ @ApiProperty({ description: 'The id of the payment account', example: 1 })
description: 'The id of the payment account',
example: 1,
})
paymentAccountId: number; paymentAccountId: number;
@IsString() @IsString()
@@ -52,8 +59,8 @@ export class CommandBillPaymentDTO {
}) })
paymentNumber?: string; paymentNumber?: string;
@IsDate() @IsDateString()
@Type(() => Date) @IsNotEmpty()
@ApiProperty({ @ApiProperty({
description: 'The payment date of the bill payment', description: 'The payment date of the bill payment',
example: '2021-01-01', example: '2021-01-01',
@@ -76,7 +83,6 @@ export class CommandBillPaymentDTO {
}) })
statement?: string; statement?: string;
@IsString()
@IsOptional() @IsOptional()
@IsArray() @IsArray()
@ValidateNested({ each: true }) @ValidateNested({ each: true })
@@ -92,12 +98,10 @@ export class CommandBillPaymentDTO {
}) })
entries: BillPaymentEntryDto[]; entries: BillPaymentEntryDto[];
@ToNumber()
@IsNumber() @IsNumber()
@IsOptional() @IsOptional()
@ApiProperty({ @ApiProperty({ description: 'The id of the branch', example: 1 })
description: 'The id of the branch',
example: 1,
})
branchId?: number; branchId?: number;
@IsArray() @IsArray()

View File

@@ -1,3 +1,4 @@
import { ToNumber } from '@/common/decorators/Validators';
import { ItemEntryDto } from '@/modules/TransactionItemEntry/dto/ItemEntry.dto'; import { ItemEntryDto } from '@/modules/TransactionItemEntry/dto/ItemEntry.dto';
import { Type } from 'class-transformer'; import { Type } from 'class-transformer';
import { import {
@@ -5,14 +6,14 @@ import {
IsArray, IsArray,
IsBoolean, IsBoolean,
IsDate, IsDate,
IsDateString,
IsEnum, IsEnum,
IsInt, IsInt,
IsNotEmpty,
IsNumber, IsNumber,
IsOptional, IsOptional,
IsPositive, IsPositive,
IsString, IsString,
Min,
MinLength,
ValidateNested, ValidateNested,
} from 'class-validator'; } from 'class-validator';
@@ -29,10 +30,12 @@ export class BillEntryDto extends ItemEntryDto {
class AttachmentDto { class AttachmentDto {
@IsString() @IsString()
@IsNotEmpty()
key: string; key: string;
} }
export class CommandBillDto { export class CommandBillDto {
@IsOptional()
@IsString() @IsString()
billNumber: string; billNumber: string;
@@ -40,32 +43,36 @@ export class CommandBillDto {
@IsString() @IsString()
referenceNo?: string; referenceNo?: string;
@IsDate() @IsNotEmpty()
@Type(() => Date) @IsDateString()
billDate: Date; billDate: Date;
@IsOptional() @IsOptional()
@IsDate() @IsDateString()
@Type(() => Date)
dueDate?: Date; dueDate?: Date;
@IsInt() @IsInt()
@IsNotEmpty()
vendorId: number; vendorId: number;
@IsOptional() @IsOptional()
@ToNumber()
@IsNumber() @IsNumber()
@IsPositive() @IsPositive()
exchangeRate?: number; exchangeRate?: number;
@IsOptional() @IsOptional()
@ToNumber()
@IsInt() @IsInt()
warehouseId?: number; warehouseId?: number;
@IsOptional() @IsOptional()
@ToNumber()
@IsInt() @IsInt()
branchId?: number; branchId?: number;
@IsOptional() @IsOptional()
@ToNumber()
@IsInt() @IsInt()
projectId?: number; projectId?: number;
@@ -74,9 +81,11 @@ export class CommandBillDto {
note?: string; note?: string;
@IsBoolean() @IsBoolean()
@IsOptional()
open: boolean = false; open: boolean = false;
@IsBoolean() @IsBoolean()
@IsOptional()
isInclusiveTax: boolean = false; isInclusiveTax: boolean = false;
@IsArray() @IsArray()
@@ -92,13 +101,17 @@ export class CommandBillDto {
attachments?: AttachmentDto[]; attachments?: AttachmentDto[];
@IsEnum(DiscountType) @IsEnum(DiscountType)
@IsOptional()
discountType: DiscountType = DiscountType.Amount; discountType: DiscountType = DiscountType.Amount;
@IsOptional() @IsOptional()
@ToNumber()
@IsNumber() @IsNumber()
@IsPositive()
discount?: number; discount?: number;
@IsOptional() @IsOptional()
@ToNumber()
@IsNumber() @IsNumber()
adjustment?: number; adjustment?: number;
} }

View File

@@ -20,19 +20,22 @@ export class PaymentReceivedEntryDto {
id?: number; id?: number;
@ToNumber() @ToNumber()
@IsOptional()
@IsInt() @IsInt()
@IsOptional()
index?: number; index?: number;
@IsOptional() @IsOptional()
@ToNumber()
@IsInt() @IsInt()
paymentReceiveId?: number; paymentReceiveId?: number;
@ToNumber()
@IsInt() @IsInt()
@IsNotEmpty() @IsNotEmpty()
invoiceId: number; invoiceId: number;
@IsNumber() @ToNumber()
@IsInt()
@IsNotEmpty() @IsNotEmpty()
paymentAmount: number; paymentAmount: number;
} }

View File

@@ -1,15 +1,19 @@
import { ItemEntryDto } from '@/modules/TransactionItemEntry/dto/ItemEntry.dto';
import { ApiProperty } from '@nestjs/swagger'; import { ApiProperty } from '@nestjs/swagger';
import { Type } from 'class-transformer'; import { Type } from 'class-transformer';
import { import {
IsArray, IsArray,
IsBoolean,
IsDateString,
IsEnum, IsEnum,
IsInt,
IsNotEmpty, IsNotEmpty,
IsNumber, IsNumber,
IsOptional, IsOptional,
IsString, IsString,
ValidateNested, ValidateNested,
} from 'class-validator'; } from 'class-validator';
import { ToNumber } from '@/common/decorators/Validators';
import { ItemEntryDto } from '@/modules/TransactionItemEntry/dto/ItemEntry.dto';
enum DiscountType { enum DiscountType {
Percentage = 'percentage', Percentage = 'percentage',
@@ -20,10 +24,12 @@ export class VendorCreditEntryDto extends ItemEntryDto {}
class AttachmentDto { class AttachmentDto {
@IsString() @IsString()
@IsNotEmpty()
key: string; key: string;
} }
export class CommandVendorCreditDto { export class CommandVendorCreditDto {
@ToNumber()
@IsNumber() @IsNumber()
@IsNotEmpty() @IsNotEmpty()
@ApiProperty({ @ApiProperty({
@@ -32,6 +38,7 @@ export class CommandVendorCreditDto {
}) })
vendorId: number; vendorId: number;
@ToNumber()
@IsNumber() @IsNumber()
@IsOptional() @IsOptional()
@ApiProperty({ @ApiProperty({
@@ -42,10 +49,7 @@ export class CommandVendorCreditDto {
@IsString() @IsString()
@IsOptional() @IsOptional()
@ApiProperty({ @ApiProperty({ description: 'The vendor credit number', example: '123456' })
description: 'The vendor credit number',
example: '123456',
})
vendorCreditNumber?: string; vendorCreditNumber?: string;
@IsString() @IsString()
@@ -56,7 +60,7 @@ export class CommandVendorCreditDto {
}) })
referenceNo?: string; referenceNo?: string;
@IsString() @IsDateString()
@IsNotEmpty() @IsNotEmpty()
@ApiProperty({ @ApiProperty({
description: 'The date of the vendor credit', description: 'The date of the vendor credit',
@@ -73,13 +77,15 @@ export class CommandVendorCreditDto {
note?: string; note?: string;
@IsOptional() @IsOptional()
@IsBoolean()
@ApiProperty({ @ApiProperty({
description: 'The open status of the vendor credit', description: 'The open status of the vendor credit',
example: true, example: true,
}) })
open: boolean = false; open: boolean = false;
@IsNumber() @ToNumber()
@IsInt()
@IsOptional() @IsOptional()
@ApiProperty({ @ApiProperty({
description: 'The warehouse id of the vendor credit', description: 'The warehouse id of the vendor credit',
@@ -87,7 +93,8 @@ export class CommandVendorCreditDto {
}) })
warehouseId?: number; warehouseId?: number;
@IsNumber() @ToNumber()
@IsInt()
@IsOptional() @IsOptional()
@ApiProperty({ @ApiProperty({
description: 'The branch id of the vendor credit', description: 'The branch id of the vendor credit',
@@ -120,14 +127,11 @@ export class CommandVendorCreditDto {
@IsOptional() @IsOptional()
@ApiProperty({ @ApiProperty({
description: 'The attachments of the vendor credit', description: 'The attachments of the vendor credit',
example: [ example: [{ key: '123456' }],
{
key: '123456',
},
],
}) })
attachments?: AttachmentDto[]; attachments?: AttachmentDto[];
@ToNumber()
@IsNumber() @IsNumber()
@IsOptional() @IsOptional()
@ApiProperty({ @ApiProperty({
@@ -144,6 +148,7 @@ export class CommandVendorCreditDto {
}) })
discountType?: DiscountType; discountType?: DiscountType;
@ToNumber()
@IsNumber() @IsNumber()
@IsOptional() @IsOptional()
@ApiProperty({ @ApiProperty({

View File

@@ -159,7 +159,7 @@ export function usePaymentMadeNewPageEntries(vendorId, props) {
params: { vendor_id: vendorId }, params: { vendor_id: vendorId },
}, },
{ {
select: (res) => res.data.entries, select: (res) => res.data,
defaultData: [], defaultData: [],
...props, ...props,
}, },