Skip to content

Commit

Permalink
Merge pull request #69 from AdultOfNineteen/WIN-143
Browse files Browse the repository at this point in the history
์ƒ์  ๊ด€๋ จ API ์ž‘์„ฑ
  • Loading branch information
swa07016 authored Jan 11, 2024
2 parents 52fe028 + 7eeb96b commit 9345408
Show file tree
Hide file tree
Showing 34 changed files with 1,056 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.example.wineyapi.admin.shop.controller;

import com.example.wineyapi.admin.shop.dto.ShopReq;
import com.example.wineyapi.admin.shop.service.AdminShopService;
import com.example.wineycommon.reponse.CommonResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequiredArgsConstructor
@RequestMapping("/admin/shops")
public class AdminShopController {
private final AdminShopService adminShopService;
@PostMapping("")
public CommonResponse<String> uploadShops(@RequestBody List<ShopReq.ShopUploadDTO> shopUploadDTO){
adminShopService.uploadShops(shopUploadDTO);
return CommonResponse.onSuccess("์„ฑ๊ณต");
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.example.wineyapi.admin.shop.converter;

import com.example.wineyapi.admin.shop.dto.ShopReq;
import com.example.wineyapi.common.util.GeoUtils;
import com.example.wineydomain.shop.entity.Mood;
import com.example.wineydomain.shop.entity.Shop;
import com.example.wineydomain.shop.entity.ShopMood;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.Point;
import org.locationtech.jts.geom.PrecisionModel;
import org.springframework.stereotype.Component;


@Component
public class AdminShopConverter {
public Shop convertToShop(ShopReq.ShopUploadDTO req) {
return Shop
.builder()
.name(req.getName())
.shopType(req.getShopType())
.address(req.getAddress())
.phone(req.getPhone())
.businessHour(req.getBusinessHour())
.imgUrl(req.getImgUrl())
.build();

}

public ShopMood convertToShopMood(Mood mood, Shop shop) {
return ShopMood
.builder()
.mood(mood)
.shop(shop)
.build();
}


public Point convertToShopPoint(ShopReq.ShopUploadDTO req) {
return GeoUtils.createPoint(req.getLatitude(), req.getLongitude());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.example.wineyapi.admin.shop.dto;

import com.example.wineydomain.shop.entity.Mood;
import com.example.wineydomain.shop.entity.Shop;
import com.example.wineydomain.shop.entity.ShopMood;
import com.example.wineydomain.shop.entity.ShopType;
import lombok.*;
import org.hibernate.annotations.BatchSize;
import org.locationtech.jts.geom.Point;

import javax.persistence.*;
import java.util.List;

public class ShopReq {
@NoArgsConstructor
@Getter
@Setter
@AllArgsConstructor
@Builder
public static class ShopUploadDTO{
private String name;

private ShopType shopType;

private String address;

private String phone;

private String businessHour;

private String imgUrl;

private Double latitude;

private Double longitude;

private List<Mood> moods;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.example.wineyapi.admin.shop.service;

import com.example.wineyapi.admin.shop.converter.AdminShopConverter;
import com.example.wineyapi.admin.shop.dto.ShopReq;
import com.example.wineydomain.shop.entity.Mood;
import com.example.wineydomain.shop.entity.Shop;
import com.example.wineydomain.shop.entity.ShopMood;
import com.example.wineydomain.shop.repository.ShopMoodRepository;
import com.example.wineydomain.shop.repository.ShopRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.util.ArrayList;
import java.util.List;

@Service
@RequiredArgsConstructor
public class AdminShopService {
private final ShopRepository shopRepository;
private final ShopMoodRepository shopMoodRepository;
private final AdminShopConverter adminShopConverter;


@Transactional
public void uploadShops(List<ShopReq.ShopUploadDTO> shopUploadReqs) {
List<Shop> shops = new ArrayList<>();
for (ShopReq.ShopUploadDTO req : shopUploadReqs){
Shop shop = shopRepository.save(adminShopConverter.convertToShop(req));
shopRepository.updateShopPoint(String.format("POINT(%f %f)", req.getLatitude(), req.getLongitude()), shop.getId());
if (req.getMoods()!=null) {
List<ShopMood> shopMoods = new ArrayList<>();
for (Mood mood : req.getMoods()){
shopMoods.add(adminShopConverter.convertToShopMood(mood, shop));
}
shopMoodRepository.saveAll(shopMoods);
}

}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.example.wineyapi.common.dto;

import lombok.Getter;

@Getter
public class Location {

private Double latitude;
private Double longitude;

public Location(Double latitude, Double longitude) {
this.latitude = latitude;
this.longitude = longitude;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.example.wineyapi.common.util;

import static com.example.wineycommon.constants.WineyStatic.*;

import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.Point;
import org.locationtech.jts.geom.PrecisionModel;

import com.example.wineyapi.common.dto.Location;

public class GeoUtils {
public static Point createPoint(double latitude, double longitude) {
GeometryFactory geometryFactory = new GeometryFactory(new PrecisionModel(), SRID);
return geometryFactory.createPoint(new Coordinate(longitude, latitude));
}

public static Location calculate(Double baseLatitude, Double baseLongitude, Double distance,
Double bearing) {
Double radianLatitude = toRadian(baseLatitude);
Double radianLongitude = toRadian(baseLongitude);
Double radianAngle = toRadian(bearing);
Double distanceRadius = distance / EARTH_RADIUS;

Double latitude = Math.asin(sin(radianLatitude) * cos(distanceRadius) +
cos(radianLatitude) * sin(distanceRadius) * cos(radianAngle));
Double longitude = radianLongitude + Math.atan2(sin(radianAngle) * sin(distanceRadius) *
cos(radianLatitude), cos(distanceRadius) - sin(radianLatitude) * sin(latitude));

longitude = normalizeLongitude(longitude);
return new Location(toDegree(latitude), toDegree(longitude));
}

private static Double toRadian(Double coordinate) {
return coordinate * Math.PI / ONE_EIGHTY;
}

private static Double toDegree(Double coordinate) {
return coordinate * ONE_EIGHTY / Math.PI;
}

private static Double sin(Double coordinate) {
return Math.sin(coordinate);
}

private static Double cos(Double coordinate) {
return Math.cos(coordinate);
}

private static Double normalizeLongitude(Double longitude) {
return (longitude + FIVE_FORTY) % THREE_SIXTY - ONE_EIGHTY;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.example.wineyapi.shop.controller;

import com.example.wineyapi.shop.dto.ShopCommand;
import com.example.wineyapi.shop.dto.ShopReq;
import com.example.wineyapi.shop.dto.ShopRes;
import com.example.wineyapi.shop.mapper.ShopMapper;
import com.example.wineyapi.shop.service.ShopService;
import com.example.wineycommon.annotation.ApiErrorCodeExample;
import com.example.wineycommon.exception.errorcode.RequestErrorCode;
import com.example.wineycommon.reponse.CommonResponse;
import com.example.wineydomain.shop.entity.ShopType;
import com.example.wineydomain.user.entity.User;
import com.example.wineydomain.user.exception.UserAuthErrorCode;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.List;

@RestController
@RequiredArgsConstructor
@Tag(name = "05-Shop ๐Ÿ—พ ์™€์ธ ํŒ๋งค์ง€ API",description = "์™€์ธ ํŒ๋งค์ง€ ๊ด€๋ จ API ํƒœ๊ทธ")
@RequestMapping("/shops")
public class ShopController {
/*
์™€์ธ ํŒ๋งค์ง€ ์ง€๋„ ๊ฒ€์ƒ‰ + ํ•„ํ„ฐ๋ง
*/
private final ShopService shopService;
private final ShopMapper shopMapper = ShopMapper.INSTANCE;
@Operation(summary = "05-01 ์™€์ธ ํŒ๋งค์ง€ ์ง€๋„ API Made By Austin",description = "์™€์ธ ํŒ๋งค์ง€ ์ง€๋„ ๊ฒ€์ƒ‰ + ํ•„ํ„ฐ๋ง + ์ƒ์„ธ์กฐํšŒ ๊นŒ์ง€ ์ด API ๋กœ ์‚ฌ์šฉํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.")
@PostMapping("")
@ApiErrorCodeExample({UserAuthErrorCode.class, RequestErrorCode.class})
public CommonResponse<List<ShopRes.ShopMapDto>> getShopMapDtoList(
@Valid @RequestBody ShopReq.MapFilterDto mapFilterDto,
@Parameter(description = "ํ•„ํ„ฐ๋ง", required = true) @RequestParam(required = false,defaultValue = "ALL") ShopFilter shopFilter,
@AuthenticationPrincipal User user
){
return CommonResponse.onSuccess(shopService.getShopMapDtoList(shopMapper.toGetShopCommandDTO(mapFilterDto, user, shopFilter)));
}


/*
์™€์ธ ํŒ๋งค์ง€ ํ•˜๋‹จ ์Šค์™€์ดํ”„ ์กฐํšŒ + ํ•„ํ„ฐ๋ง
*/

/*
์™€์ธ ํŒ๋งค์ง€ ๋ถ๋งˆํฌ + ๋ถ๋งˆํฌ ์ทจ์†Œ
*/

/*
์™€์ธ ํŒ๋งค์ง€ ํ•˜๋‹จ ์Šค์™€์ดํ”„ ํด๋ฆญ ์‹œ ์ƒ์„ธ ์กฐํšŒ
*/
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.example.wineyapi.shop.controller;

public enum ShopFilter {
PUB, BOTTLE_SHOP, BAR, COOKING_BAR, RESTAURANT, CAFE, ALL, LIKE
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.example.wineyapi.shop.converter;

import com.example.wineyapi.shop.dto.ShopRes;
import com.example.wineydomain.shop.entity.Mood;
import com.example.wineydomain.shop.repository.ShopRepository;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Component
public class ShopConverter {
public List<ShopRes.ShopMapDto> toShopMapDtoLists(List<ShopRepository.ShopMapList> shopMapLists) {
return shopMapLists.stream()
.map(this::toShopMapDto)
.collect(Collectors.toList());
}

private ShopRes.ShopMapDto toShopMapDto(ShopRepository.ShopMapList result) {
List<String> shopMoodsList = Optional.ofNullable(result.getShopMoods())
.map(moods -> Arrays.stream(moods.split(","))
.map(String::trim)
.map(Mood::valueOf)
.map(Mood::getValue)
.collect(Collectors.toList())
)
.orElse(Collections.emptyList());

return ShopRes.ShopMapDto.builder()
.shopId(result.getShopId())
.isLike(result.getBookMark())
.latitude(result.getLatitude())
.longitude(result.getLongitude())
.businessHour(result.getBusinessHour())
.imgUrl(result.getImgUrl())
.address(result.getAddress())
.phone(result.getPhone())
.name(result.getName())
.meter(result.getMeter())
.shopType(result.getShopType().getType())
.shopMoods(shopMoodsList)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.example.wineyapi.shop.dto;

import com.example.wineyapi.shop.controller.ShopFilter;
import com.example.wineydomain.shop.entity.Shop;
import com.example.wineydomain.shop.entity.ShopType;
import com.example.wineydomain.user.entity.User;
import lombok.*;

public class ShopCommand {
@NoArgsConstructor
@Getter
@Setter
@AllArgsConstructor
@Builder
public static class getMapCommandDTO{
private ShopReq.MapFilterDto mapFilterDto;

private ShopFilter shopFilter;

private User user;
}
}
Loading

0 comments on commit 9345408

Please sign in to comment.