Skip to content

Commit

Permalink
feat: 지도에 장소 추가/삭제 API 구현 #65
Browse files Browse the repository at this point in the history
  • Loading branch information
Miensoap committed Nov 7, 2024
1 parent 10f4b19 commit f086a1a
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 1 deletion.
9 changes: 9 additions & 0 deletions backend/src/map/dto/AddPlaceToMapRequest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { IsNumber, IsString } from 'class-validator';

export class AddPlaceToMapRequest {
@IsNumber()
placeId: number;

@IsString()
comment?: string;
}
12 changes: 12 additions & 0 deletions backend/src/map/entity/map-place.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import { Map } from './map.entity';

@Entity()
export class MapPlace extends BaseEntity {
@Column()
placeId: number;

@ManyToOne(() => Place, { onDelete: 'CASCADE', lazy: true })
@JoinColumn({ name: 'place_id' })
place: Promise<Place>;
Expand All @@ -18,4 +21,13 @@ export class MapPlace extends BaseEntity {

@Column('text', { nullable: true })
description?: string;

static of(placeId: number, map: Map, description?: string) {
const place = new MapPlace();
place.map = map;
place.placeId = placeId;
place.place = Promise.resolve({ id: placeId } as Place);
place.description = description;
return place;
}
}
12 changes: 12 additions & 0 deletions backend/src/map/entity/map.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,18 @@ export class Map extends BaseEntity {
return this.mapPlaces.length;
}

addPlace(placeId: number, description: string) {
this.mapPlaces.push(MapPlace.of(placeId, this, description));
}

async deletePlace(placeId: number) {
this.mapPlaces = this.mapPlaces.filter((p) => p.placeId !== placeId);
}

async hasPlace(placeId: number) {
return this.mapPlaces.some((p) => p.placeId === placeId);
}

async getPlacesWithComment() {
return await Promise.all(
this.mapPlaces.map(async (mapPlace) => ({
Expand Down
18 changes: 18 additions & 0 deletions backend/src/map/map.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
import { MapService } from './map.service';
import { CreateMapRequest } from './dto/CreateMapRequest';
import { UpdateMapInfoRequest } from './dto/UpdateMapInfoRequest';
import { AddPlaceToMapRequest } from './dto/AddPlaceToMapRequest';

@Controller('/maps')
export class MapController {
Expand Down Expand Up @@ -38,6 +39,23 @@ export class MapController {
return await this.mapService.createMap(userId, createMapRequest);
}

@Post('/:id/places')
async addPlaceToMap(
@Param('id') id: number,
@Body() addPlaceToMapRequest: AddPlaceToMapRequest,
) {
const { placeId, comment } = addPlaceToMapRequest;
return await this.mapService.addPlace(id, placeId, comment);
}

@Delete('/:id/places/:placeId')
async deletePlaceFromMap(
@Param('id') id: number,
@Param('placeId') placeId: number,
) {
return await this.mapService.deletePlace(id, placeId);
}

@Patch('/:id/info')
async updateMapInfo(
@Param('id') id: number,
Expand Down
3 changes: 2 additions & 1 deletion backend/src/map/map.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import { MapService } from './map.service';
import { MapController } from './map.controller';
import { UserModule } from '../user/user.module';
import { MapRepository } from './map.repository';
import { PlaceModule } from '../place/place.module';

@Module({
imports: [UserModule],
imports: [UserModule, PlaceModule],
controllers: [MapController],
providers: [MapService, MapRepository],
})
Expand Down
39 changes: 39 additions & 0 deletions backend/src/map/map.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,17 @@ import { UserRepository } from '../user/user.repository';
import { UpdateMapInfoRequest } from './dto/UpdateMapInfoRequest';
import { CreateMapRequest } from './dto/CreateMapRequest';
import { MapNotFoundException } from './exception/MapNotFoundException';
import { DuplicatePlaceToMapException } from './exception/DuplicatePlaceToMapException';
import { PlaceRepository } from '../place/place.repository';
import { InvalidPlaceToMapException } from './exception/InvalidPlaceToMapException';
import { Map } from './entity/map.entity';

@Injectable()
export class MapService {
constructor(
private readonly mapRepository: MapRepository,
private readonly userRepository: UserRepository,
private readonly placeRepository: PlaceRepository,
) {
// Todo. 로그인 기능 완성 후 제거
const testUser = new User('test', 'test', 'test', 'test');
Expand Down Expand Up @@ -97,4 +102,38 @@ export class MapService {
if (!(await this.mapRepository.existById(id)))
throw new MapNotFoundException(id);
}

async addPlace(id: number, placeId: number, comment?: string) {
const map = await this.mapRepository.findById(id);
if (!map) throw new MapNotFoundException(id);
await this.checkPlaceCanAddToMap(placeId, map);

map.addPlace(placeId, comment);
await this.mapRepository.save(map);

return {
savedPlaceId: placeId,
comment: comment,
};
}

private async checkPlaceCanAddToMap(placeId: number, map: Map) {
if (!(await this.placeRepository.existById(placeId))) {
throw new InvalidPlaceToMapException(placeId);
}

if (await map.hasPlace(placeId)) {
throw new DuplicatePlaceToMapException(placeId);
}
}

async deletePlace(id: number, placeId: number) {
const map = await this.mapRepository.findById(id);
if (!map) throw new MapNotFoundException(id);

map.deletePlace(placeId);
await this.mapRepository.save(map);

return { deletedId: placeId };
}
}

0 comments on commit f086a1a

Please sign in to comment.