address
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
import { Controller, Get, UseGuards, Patch, Body, ValidationPipe, Post, Query } from '@nestjs/common';
|
||||
import { Controller, Get, UseGuards, Patch, Body, ValidationPipe, Post, Query, Delete, Param } from '@nestjs/common';
|
||||
import { ApiTags, ApiBearerAuth, ApiOperation, ApiBody, ApiOkResponse } from '@nestjs/swagger';
|
||||
import { AuthGuard } from 'src/modules/auth/guards/auth.guard';
|
||||
import { UserService } from '../user.service';
|
||||
import { UpdateUserDto } from '../dto/update-user.dto';
|
||||
import { CreateUserAddressDto } from '../dto/create-user-address.dto';
|
||||
import { UpdateUserAddressDto } from '../dto/update-user-address.dto';
|
||||
import { UserId } from 'src/common/decorators/user-id.decorator';
|
||||
import { RestId } from 'src/common/decorators';
|
||||
import { FindUsersDto } from '../dto/find-user.dto';
|
||||
@@ -59,6 +60,51 @@ export class UsersController {
|
||||
return address;
|
||||
}
|
||||
|
||||
@UseGuards(AuthGuard)
|
||||
@ApiBearerAuth()
|
||||
@ApiOperation({ summary: 'Get a single address by ID for the authenticated user' })
|
||||
@ApiOkResponse({ description: 'User address details' })
|
||||
@Get('public/user/addresses/:addressId')
|
||||
async getUserAddress(@UserId() userId: string, @Param('addressId') addressId: string) {
|
||||
const address = await this.userService.getUserAddress(userId, addressId);
|
||||
return address;
|
||||
}
|
||||
|
||||
@UseGuards(AuthGuard)
|
||||
@ApiBearerAuth()
|
||||
@ApiOperation({ summary: 'Update an address for the authenticated user' })
|
||||
@ApiBody({ type: UpdateUserAddressDto })
|
||||
@ApiOkResponse({ description: 'Updated user address' })
|
||||
@Patch('public/user/addresses/:addressId')
|
||||
async updateUserAddress(
|
||||
@UserId() userId: string,
|
||||
@Param('addressId') addressId: string,
|
||||
@Body(new ValidationPipe({ transform: true, whitelist: true })) dto: UpdateUserAddressDto,
|
||||
) {
|
||||
const address = await this.userService.updateUserAddress(userId, addressId, dto);
|
||||
return address;
|
||||
}
|
||||
|
||||
@UseGuards(AuthGuard)
|
||||
@ApiBearerAuth()
|
||||
@ApiOperation({ summary: 'Delete an address for the authenticated user' })
|
||||
@ApiOkResponse({ description: 'Address deleted successfully' })
|
||||
@Delete('public/user/addresses/:addressId')
|
||||
async deleteUserAddress(@UserId() userId: string, @Param('addressId') addressId: string) {
|
||||
await this.userService.deleteUserAddress(userId, addressId);
|
||||
return { message: 'Address deleted successfully' };
|
||||
}
|
||||
|
||||
@UseGuards(AuthGuard)
|
||||
@ApiBearerAuth()
|
||||
@ApiOperation({ summary: 'Set an address as default for the authenticated user' })
|
||||
@ApiOkResponse({ description: 'Address set as default' })
|
||||
@Patch('public/user/addresses/:addressId/default')
|
||||
async setDefaultAddress(@UserId() userId: string, @Param('addressId') addressId: string) {
|
||||
const address = await this.userService.setDefaultAddress(userId, addressId);
|
||||
return address;
|
||||
}
|
||||
|
||||
@UseGuards(AdminAuthGuard)
|
||||
@ApiBearerAuth()
|
||||
@ApiOperation({ summary: 'Get paginated list of restuarant users with filters' })
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
import { IsString, IsOptional, IsNumber, IsBoolean, Min, Max } from 'class-validator';
|
||||
import { ApiPropertyOptional } from '@nestjs/swagger';
|
||||
|
||||
/**
|
||||
* DTO for updating a user address.
|
||||
*/
|
||||
export class UpdateUserAddressDto {
|
||||
@ApiPropertyOptional({ description: 'Address title/label (e.g., "Home", "Work")', example: 'Home' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
title?: string;
|
||||
|
||||
@ApiPropertyOptional({ description: 'Street address', example: '123 Main Street' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
address?: string;
|
||||
|
||||
@ApiPropertyOptional({ description: 'City name', example: 'Tehran' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
city?: string;
|
||||
|
||||
@ApiPropertyOptional({ description: 'Province', example: 'Tehran Province' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
province?: string;
|
||||
|
||||
@ApiPropertyOptional({ description: 'Postal/ZIP code', example: '12345-6789' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
postalCode?: string;
|
||||
|
||||
@ApiPropertyOptional({ description: 'Latitude coordinate', example: 35.6892, minimum: -90, maximum: 90 })
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
@Min(-90)
|
||||
@Max(90)
|
||||
latitude?: number;
|
||||
|
||||
@ApiPropertyOptional({ description: 'Longitude coordinate', example: 51.3890, minimum: -180, maximum: 180 })
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
@Min(-180)
|
||||
@Max(180)
|
||||
longitude?: number;
|
||||
|
||||
@ApiPropertyOptional({ description: 'Contact phone for this address', example: '+989123456789' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
phone?: string;
|
||||
|
||||
@ApiPropertyOptional({ description: 'Set as default address', example: false })
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
isDefault?: boolean;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import { EntityManager } from '@mikro-orm/postgresql';
|
||||
import { UpdateUserDto } from './dto/update-user.dto';
|
||||
import { FindUsersDto } from './dto/find-user.dto';
|
||||
import { CreateUserAddressDto } from './dto/create-user-address.dto';
|
||||
import { UpdateUserAddressDto } from './dto/update-user-address.dto';
|
||||
import { PaginatedResult } from 'src/common/interfaces/pagination.interface';
|
||||
import { UserRepository } from './repositories/user.repository';
|
||||
|
||||
@@ -183,4 +184,89 @@ export class UserService {
|
||||
await this.em.persistAndFlush(address);
|
||||
return address;
|
||||
}
|
||||
|
||||
async getUserAddress(userId: string, addressId: string): Promise<UserAddress> {
|
||||
const address = await this.em.findOne(UserAddress, {
|
||||
id: addressId,
|
||||
user: { id: userId },
|
||||
});
|
||||
|
||||
if (!address) {
|
||||
throw new NotFoundException(`Address with ID ${addressId} not found for user ${userId}.`);
|
||||
}
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
async updateUserAddress(userId: string, addressId: string, dto: UpdateUserAddressDto): Promise<UserAddress> {
|
||||
const address = await this.em.findOne(UserAddress, {
|
||||
id: addressId,
|
||||
user: { id: userId },
|
||||
});
|
||||
|
||||
if (!address) {
|
||||
throw new NotFoundException(`Address with ID ${addressId} not found for user ${userId}.`);
|
||||
}
|
||||
|
||||
// If setting as default, unset other default addresses
|
||||
if (dto.isDefault === true) {
|
||||
const existingAddresses = await this.em.find(UserAddress, {
|
||||
user: { id: userId },
|
||||
isDefault: true,
|
||||
id: { $ne: addressId },
|
||||
});
|
||||
for (const existingAddress of existingAddresses) {
|
||||
existingAddress.isDefault = false;
|
||||
}
|
||||
await this.em.flush();
|
||||
}
|
||||
|
||||
// Update address fields
|
||||
this.em.assign(address, dto);
|
||||
await this.em.flush();
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
async deleteUserAddress(userId: string, addressId: string): Promise<void> {
|
||||
const address = await this.em.findOne(UserAddress, {
|
||||
id: addressId,
|
||||
user: { id: userId },
|
||||
});
|
||||
|
||||
if (!address) {
|
||||
throw new NotFoundException(`Address with ID ${addressId} not found for user ${userId}.`);
|
||||
}
|
||||
|
||||
// Soft delete the address
|
||||
address.deletedAt = new Date();
|
||||
await this.em.persistAndFlush(address);
|
||||
}
|
||||
|
||||
async setDefaultAddress(userId: string, addressId: string): Promise<UserAddress> {
|
||||
const address = await this.em.findOne(UserAddress, {
|
||||
id: addressId,
|
||||
user: { id: userId },
|
||||
});
|
||||
|
||||
if (!address) {
|
||||
throw new NotFoundException(`Address with ID ${addressId} not found for user ${userId}.`);
|
||||
}
|
||||
|
||||
// Unset all other default addresses
|
||||
const existingAddresses = await this.em.find(UserAddress, {
|
||||
user: { id: userId },
|
||||
isDefault: true,
|
||||
id: { $ne: addressId },
|
||||
});
|
||||
for (const existingAddress of existingAddresses) {
|
||||
existingAddress.isDefault = false;
|
||||
}
|
||||
|
||||
// Set this address as default
|
||||
address.isDefault = true;
|
||||
await this.em.flush();
|
||||
|
||||
return address;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user