From 83c9392b74706487d279ca2bb2e90a8eb18cadce Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Mon, 26 May 2025 17:04:53 +0200 Subject: [PATCH] refactor(nestjs): wip dtos validation schema --- .../BillPayments/BillPayments.controller.ts | 51 ++++++++++++++++++- .../BillPayments/BillPayments.module.ts | 2 + .../commands/BillPaymentsPages.service.ts | 2 +- .../BillPayments/dtos/BillPayment.dto.ts | 38 +++++++------- .../server/src/modules/Bills/dtos/Bill.dto.ts | 25 ++++++--- .../dtos/PaymentReceived.dto.ts | 7 ++- .../VendorCredit/dtos/VendorCredit.dto.ts | 31 ++++++----- .../webapp/src/hooks/query/paymentMades.tsx | 2 +- 8 files changed, 116 insertions(+), 42 deletions(-) diff --git a/packages/server/src/modules/BillPayments/BillPayments.controller.ts b/packages/server/src/modules/BillPayments/BillPayments.controller.ts index 16a2b5569..8d741573d 100644 --- a/packages/server/src/modules/BillPayments/BillPayments.controller.ts +++ b/packages/server/src/modules/BillPayments/BillPayments.controller.ts @@ -15,11 +15,15 @@ import { EditBillPaymentDto, } from './dtos/BillPayment.dto'; import { GetBillPaymentsFilterDto } from './dtos/GetBillPaymentsFilter.dto'; +import { BillPaymentsPages } from './commands/BillPaymentsPages.service'; @Controller('bill-payments') @ApiTags('bill-payments') export class BillPaymentsController { - constructor(private billPaymentsApplication: BillPaymentsApplication) {} + constructor( + private billPaymentsApplication: BillPaymentsApplication, + private billPaymentsPagesService: BillPaymentsPages, + ) {} @Post() @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') @ApiOperation({ summary: 'Retrieves the bills of the given bill payment.' }) @ApiParam({ @@ -71,6 +93,25 @@ export class BillPaymentsController { 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') @ApiOperation({ summary: 'Retrieves the bill payment details.' }) @ApiParam({ @@ -83,8 +124,14 @@ export class BillPaymentsController { return this.billPaymentsApplication.getBillPayment(Number(billPaymentId)); } - @Get('') + @Get() @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) { return this.billPaymentsApplication.getBillPayments(filterDTO); } diff --git a/packages/server/src/modules/BillPayments/BillPayments.module.ts b/packages/server/src/modules/BillPayments/BillPayments.module.ts index 05bf5b62b..0516d5c71 100644 --- a/packages/server/src/modules/BillPayments/BillPayments.module.ts +++ b/packages/server/src/modules/BillPayments/BillPayments.module.ts @@ -20,6 +20,7 @@ import { BillPaymentsExportable } from './queries/BillPaymentsExportable'; import { BillPaymentsImportable } from './commands/BillPaymentsImportable'; import { GetBillPaymentsService } from './queries/GetBillPayments.service'; import { DynamicListModule } from '../DynamicListing/DynamicList.module'; +import { BillPaymentsPages } from './commands/BillPaymentsPages.service'; @Module({ imports: [LedgerModule, AccountsModule, DynamicListModule], @@ -41,6 +42,7 @@ import { DynamicListModule } from '../DynamicListing/DynamicList.module'; BillPaymentsExportable, BillPaymentsImportable, GetBillPaymentsService, + BillPaymentsPages, ], exports: [ BillPaymentValidators, diff --git a/packages/server/src/modules/BillPayments/commands/BillPaymentsPages.service.ts b/packages/server/src/modules/BillPayments/commands/BillPaymentsPages.service.ts index d1c469d34..29a461c90 100644 --- a/packages/server/src/modules/BillPayments/commands/BillPaymentsPages.service.ts +++ b/packages/server/src/modules/BillPayments/commands/BillPaymentsPages.service.ts @@ -8,7 +8,7 @@ import { ServiceError } from '../../Items/ServiceError'; import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; @Injectable() -export default class BillPaymentsPages { +export class BillPaymentsPages { /** * @param {TenantModelProxy} billModel - Bill model. * @param {TenantModelProxy} billPaymentModel - Bill payment model. diff --git a/packages/server/src/modules/BillPayments/dtos/BillPayment.dto.ts b/packages/server/src/modules/BillPayments/dtos/BillPayment.dto.ts index efb48a9bd..8944ac1a7 100644 --- a/packages/server/src/modules/BillPayments/dtos/BillPayment.dto.ts +++ b/packages/server/src/modules/BillPayments/dtos/BillPayment.dto.ts @@ -1,7 +1,8 @@ +import { ApiProperty } from '@nestjs/swagger'; import { Type } from 'class-transformer'; import { IsArray, - IsDate, + IsDateString, IsNotEmpty, IsNumber, IsOptional, @@ -9,25 +10,33 @@ import { ValidateNested, } from 'class-validator'; import { AttachmentLinkDto } from '@/modules/Attachments/dtos/Attachment.dto'; -import { ApiProperty } from '@nestjs/swagger'; +import { ToNumber } from '@/common/decorators/Validators'; export class BillPaymentEntryDto { + @ToNumber() @IsNumber() + @IsNotEmpty() + @ApiProperty({ description: 'The id of the bill', example: 1 }) billId: number; + @ToNumber() @IsNumber() + @IsNotEmpty() + @ApiProperty({ + description: 'The payment amount of the bill payment', + example: 100, + }) paymentAmount: number; } export class CommandBillPaymentDTO { + @ToNumber() @IsNumber() @IsNotEmpty() - @ApiProperty({ - description: 'The id of the vendor', - example: 1, - }) + @ApiProperty({ description: 'The id of the vendor', example: 1 }) vendorId: number; + @ToNumber() @IsNumber() @IsOptional() @ApiProperty({ @@ -36,12 +45,10 @@ export class CommandBillPaymentDTO { }) amount?: number; + @ToNumber() @IsNumber() @IsNotEmpty() - @ApiProperty({ - description: 'The id of the payment account', - example: 1, - }) + @ApiProperty({ description: 'The id of the payment account', example: 1 }) paymentAccountId: number; @IsString() @@ -52,8 +59,8 @@ export class CommandBillPaymentDTO { }) paymentNumber?: string; - @IsDate() - @Type(() => Date) + @IsDateString() + @IsNotEmpty() @ApiProperty({ description: 'The payment date of the bill payment', example: '2021-01-01', @@ -76,7 +83,6 @@ export class CommandBillPaymentDTO { }) statement?: string; - @IsString() @IsOptional() @IsArray() @ValidateNested({ each: true }) @@ -92,12 +98,10 @@ export class CommandBillPaymentDTO { }) entries: BillPaymentEntryDto[]; + @ToNumber() @IsNumber() @IsOptional() - @ApiProperty({ - description: 'The id of the branch', - example: 1, - }) + @ApiProperty({ description: 'The id of the branch', example: 1 }) branchId?: number; @IsArray() diff --git a/packages/server/src/modules/Bills/dtos/Bill.dto.ts b/packages/server/src/modules/Bills/dtos/Bill.dto.ts index b3c7267c8..e95ec383a 100644 --- a/packages/server/src/modules/Bills/dtos/Bill.dto.ts +++ b/packages/server/src/modules/Bills/dtos/Bill.dto.ts @@ -1,3 +1,4 @@ +import { ToNumber } from '@/common/decorators/Validators'; import { ItemEntryDto } from '@/modules/TransactionItemEntry/dto/ItemEntry.dto'; import { Type } from 'class-transformer'; import { @@ -5,14 +6,14 @@ import { IsArray, IsBoolean, IsDate, + IsDateString, IsEnum, IsInt, + IsNotEmpty, IsNumber, IsOptional, IsPositive, IsString, - Min, - MinLength, ValidateNested, } from 'class-validator'; @@ -29,10 +30,12 @@ export class BillEntryDto extends ItemEntryDto { class AttachmentDto { @IsString() + @IsNotEmpty() key: string; } export class CommandBillDto { + @IsOptional() @IsString() billNumber: string; @@ -40,32 +43,36 @@ export class CommandBillDto { @IsString() referenceNo?: string; - @IsDate() - @Type(() => Date) + @IsNotEmpty() + @IsDateString() billDate: Date; @IsOptional() - @IsDate() - @Type(() => Date) + @IsDateString() dueDate?: Date; @IsInt() + @IsNotEmpty() vendorId: number; @IsOptional() + @ToNumber() @IsNumber() @IsPositive() exchangeRate?: number; @IsOptional() + @ToNumber() @IsInt() warehouseId?: number; @IsOptional() + @ToNumber() @IsInt() branchId?: number; @IsOptional() + @ToNumber() @IsInt() projectId?: number; @@ -74,9 +81,11 @@ export class CommandBillDto { note?: string; @IsBoolean() + @IsOptional() open: boolean = false; @IsBoolean() + @IsOptional() isInclusiveTax: boolean = false; @IsArray() @@ -92,13 +101,17 @@ export class CommandBillDto { attachments?: AttachmentDto[]; @IsEnum(DiscountType) + @IsOptional() discountType: DiscountType = DiscountType.Amount; @IsOptional() + @ToNumber() @IsNumber() + @IsPositive() discount?: number; @IsOptional() + @ToNumber() @IsNumber() adjustment?: number; } diff --git a/packages/server/src/modules/PaymentReceived/dtos/PaymentReceived.dto.ts b/packages/server/src/modules/PaymentReceived/dtos/PaymentReceived.dto.ts index 0c25fa108..cb7bbdc05 100644 --- a/packages/server/src/modules/PaymentReceived/dtos/PaymentReceived.dto.ts +++ b/packages/server/src/modules/PaymentReceived/dtos/PaymentReceived.dto.ts @@ -20,19 +20,22 @@ export class PaymentReceivedEntryDto { id?: number; @ToNumber() - @IsOptional() @IsInt() + @IsOptional() index?: number; @IsOptional() + @ToNumber() @IsInt() paymentReceiveId?: number; + @ToNumber() @IsInt() @IsNotEmpty() invoiceId: number; - @IsNumber() + @ToNumber() + @IsInt() @IsNotEmpty() paymentAmount: number; } diff --git a/packages/server/src/modules/VendorCredit/dtos/VendorCredit.dto.ts b/packages/server/src/modules/VendorCredit/dtos/VendorCredit.dto.ts index 6c5c4fcf7..33164d2cd 100644 --- a/packages/server/src/modules/VendorCredit/dtos/VendorCredit.dto.ts +++ b/packages/server/src/modules/VendorCredit/dtos/VendorCredit.dto.ts @@ -1,15 +1,19 @@ -import { ItemEntryDto } from '@/modules/TransactionItemEntry/dto/ItemEntry.dto'; import { ApiProperty } from '@nestjs/swagger'; import { Type } from 'class-transformer'; import { IsArray, + IsBoolean, + IsDateString, IsEnum, + IsInt, IsNotEmpty, IsNumber, IsOptional, IsString, ValidateNested, } from 'class-validator'; +import { ToNumber } from '@/common/decorators/Validators'; +import { ItemEntryDto } from '@/modules/TransactionItemEntry/dto/ItemEntry.dto'; enum DiscountType { Percentage = 'percentage', @@ -20,10 +24,12 @@ export class VendorCreditEntryDto extends ItemEntryDto {} class AttachmentDto { @IsString() + @IsNotEmpty() key: string; } export class CommandVendorCreditDto { + @ToNumber() @IsNumber() @IsNotEmpty() @ApiProperty({ @@ -32,6 +38,7 @@ export class CommandVendorCreditDto { }) vendorId: number; + @ToNumber() @IsNumber() @IsOptional() @ApiProperty({ @@ -42,10 +49,7 @@ export class CommandVendorCreditDto { @IsString() @IsOptional() - @ApiProperty({ - description: 'The vendor credit number', - example: '123456', - }) + @ApiProperty({ description: 'The vendor credit number', example: '123456' }) vendorCreditNumber?: string; @IsString() @@ -56,7 +60,7 @@ export class CommandVendorCreditDto { }) referenceNo?: string; - @IsString() + @IsDateString() @IsNotEmpty() @ApiProperty({ description: 'The date of the vendor credit', @@ -73,13 +77,15 @@ export class CommandVendorCreditDto { note?: string; @IsOptional() + @IsBoolean() @ApiProperty({ description: 'The open status of the vendor credit', example: true, }) open: boolean = false; - @IsNumber() + @ToNumber() + @IsInt() @IsOptional() @ApiProperty({ description: 'The warehouse id of the vendor credit', @@ -87,7 +93,8 @@ export class CommandVendorCreditDto { }) warehouseId?: number; - @IsNumber() + @ToNumber() + @IsInt() @IsOptional() @ApiProperty({ description: 'The branch id of the vendor credit', @@ -120,14 +127,11 @@ export class CommandVendorCreditDto { @IsOptional() @ApiProperty({ description: 'The attachments of the vendor credit', - example: [ - { - key: '123456', - }, - ], + example: [{ key: '123456' }], }) attachments?: AttachmentDto[]; + @ToNumber() @IsNumber() @IsOptional() @ApiProperty({ @@ -144,6 +148,7 @@ export class CommandVendorCreditDto { }) discountType?: DiscountType; + @ToNumber() @IsNumber() @IsOptional() @ApiProperty({ diff --git a/packages/webapp/src/hooks/query/paymentMades.tsx b/packages/webapp/src/hooks/query/paymentMades.tsx index fb4746eb0..07c11e235 100644 --- a/packages/webapp/src/hooks/query/paymentMades.tsx +++ b/packages/webapp/src/hooks/query/paymentMades.tsx @@ -159,7 +159,7 @@ export function usePaymentMadeNewPageEntries(vendorId, props) { params: { vendor_id: vendorId }, }, { - select: (res) => res.data.entries, + select: (res) => res.data, defaultData: [], ...props, },