fix: eliminate untyped repository returns and standardize DomainException usage across all handlers

- Create typed DTOs (ListingDetailData, ListingSearchItem, ListingSellerItem) for repository read methods
- Replace all Promise<any> and PaginatedResult<any> with concrete types in repository interface and implementation
- Remove `as any` casts in search params by using Prisma enum types (TransactionType, PropertyType)
- Migrate all 16 handlers from NestJS built-in exceptions to domain exceptions (NotFoundException, ValidationException, etc.)
- Add CONTRIBUTING.md documenting error handling convention
- All 230 tests pass, typecheck clean

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Ho Ngoc Hai
2026-04-08 06:25:44 +07:00
parent 6389dcf78e
commit e9889539ea
28 changed files with 288 additions and 247 deletions

View File

@@ -1,15 +1,11 @@
import {
ForbiddenException,
Inject,
NotFoundException,
} from '@nestjs/common';
import { Inject } from '@nestjs/common';
import { type IQueryHandler, QueryHandler } from '@nestjs/cqrs';
import { NotFoundException, ForbiddenException } from '@modules/shared/domain/domain-exception';
import { GetPaymentStatusQuery } from './get-payment-status.query';
import {
PAYMENT_REPOSITORY,
type IPaymentRepository,
} from '../../../domain/repositories/payment.repository';
import { ErrorCode } from '@modules/shared/domain/error-codes';
export interface PaymentStatusDto {
id: string;
@@ -32,17 +28,11 @@ export class GetPaymentStatusHandler implements IQueryHandler<GetPaymentStatusQu
async execute(query: GetPaymentStatusQuery): Promise<PaymentStatusDto> {
const payment = await this.paymentRepo.findById(query.paymentId);
if (!payment) {
throw new NotFoundException({
code: ErrorCode.NOT_FOUND,
message: 'Không tìm thấy thanh toán',
});
throw new NotFoundException('Payment', query.paymentId);
}
if (payment.userId !== query.userId) {
throw new ForbiddenException({
code: ErrorCode.FORBIDDEN,
message: 'Bạn không có quyền xem thanh toán này',
});
throw new ForbiddenException('Bạn không có quyền xem thanh toán này');
}
return {