Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Carpool Register API #19

Merged
merged 5 commits into from
Jan 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions src/main/java/com/fullcar/carpool/application/CarpoolMapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.fullcar.carpool.application;

import com.fullcar.carpool.domain.Carpool;
import com.fullcar.carpool.domain.Cost;
import com.fullcar.carpool.domain.Driver;
import com.fullcar.carpool.domain.service.CarpoolIdService;
import com.fullcar.carpool.presentation.dto.CarpoolDto;
import com.fullcar.member.domain.MemberId;
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

@Component
@RequiredArgsConstructor(access = AccessLevel.PROTECTED)
public class CarpoolMapper {
private final CarpoolIdService carpoolIdService;

public CarpoolDto toDto(Carpool carpool) {
return CarpoolDto.builder()
.id(carpool.getCarpoolId().getId())
.pickupLocation(carpool.getPickupLocation())
.periodType(carpool.getCost().getPeriodType())
.money(carpool.getCost().getMoney())
.content(carpool.getContent())
.moodType(carpool.getMoodType())
.build();
}

public Carpool toEntity(MemberId memberId, CarpoolDto carpoolDto) {
return Carpool.builder()
.carpoolId(carpoolIdService.nextId())
.pickupLocation(carpoolDto.getPickupLocation())
.cost(
Cost.builder()
.periodType(carpoolDto.getPeriodType())
.money(carpoolDto.getMoney())
.build()
)
.content(carpoolDto.getContent())
.moodType(carpoolDto.getMoodType())
.driver(
Driver.builder()
.memberId(memberId)
.build()
)
.build();
}
}
28 changes: 28 additions & 0 deletions src/main/java/com/fullcar/carpool/application/CarpoolService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.fullcar.carpool.application;

import com.fullcar.carpool.domain.Carpool;
import com.fullcar.carpool.domain.CarpoolRepository;
import com.fullcar.carpool.presentation.dto.CarpoolDto;
import com.fullcar.member.domain.MemberId;
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

@Validated
@Service
@RequiredArgsConstructor(access = AccessLevel.PROTECTED)
public class CarpoolService {
private final CarpoolRepository carpoolRepository;
private final CarpoolMapper carpoolMapper;

@Transactional
public CarpoolDto registerCarpool(MemberId memberId, CarpoolDto carpoolDto) {
Carpool carpool = carpoolMapper.toEntity(memberId, carpoolDto);

return carpoolMapper.toDto(
carpoolRepository.saveAndFlush(carpool)
);
}
}
56 changes: 56 additions & 0 deletions src/main/java/com/fullcar/carpool/domain/Carpool.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.fullcar.carpool.domain;

import jakarta.persistence.*;
import lombok.*;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import java.time.LocalDateTime;

import static lombok.AccessLevel.PROTECTED;

@Entity
@Getter
@Builder
@NoArgsConstructor(access = PROTECTED)
@AllArgsConstructor(access = PROTECTED)
@EntityListeners(AuditingEntityListener.class)
@Table(name = "carpool")
public class Carpool {

@EmbeddedId
private CarpoolId carpoolId;

private String content;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

contentκ°€ νƒ‘μŠΉμžμ—κ²Œ μ „ν•  λ§μ΄κ΅°μš”! (μ΅œλŒ€ 150자) μ›Œλ”©μ΄ μ’€ 더 직관적이면 쒋을 것 같은데..! 흠,, messageλŠ” μ–΄λ–€κ°€μš”?
μ•„λ‹˜ note, memo....

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

μΉ΄ν’€ κ²Œμ‹œκΈ€μ— λ‚΄μš©μ΄λΌκ³  μƒκ°ν•˜μ—¬ content라고 넀이밍 ν–ˆμŠ΅λ‹ˆλ‹€! λ˜ν•œ νƒ‘μŠΉ μš”μ²­ 수락 λ•Œ νƒ‘μŠΉμžμ—κ²Œ λ³΄λ‚΄λŠ” λ©”μ‹œμ§€λ„ μžˆμ–΄μ„œ κ΅¬λΆ„ν•˜κΈ° μœ„ν•΄ μ΄λ ‡κ²Œ ν–ˆμŠ΅λ‹ˆλ‹€!


@Column(name = "pickup_location")
private String pickupLocation;
Comment on lines +27 to +28
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

μ •μ±…μ—μ„œ ν”½μ—…μž₯μ†Œ μ΅œλŒ€ 20자 μ΄λ‹ˆ @Length μ–΄λ…Έν…Œμ΄μ…˜μœΌλ‘œ μœ νš¨μ„± 검사 λΆ™μ—¬μ£Όλ©΄ 더 쒋을 것 κ°™μŠ΄λ‹€
ex) @Length(max = 20)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

쒋은 λΆ€λΆ„ μ§šμ–΄μ£Όμ…”μ„œ κ°μ‚¬ν•©λ‹ˆλ‹€! 근데 μ €λŠ” κΈ€μž μ œν•œ μˆ˜μ™€ 같은 μ˜ˆμ™Έμ²˜λ¦¬λŠ” ν΄λΌμ΄μ–ΈνŠΈμ—μ„œ μΆ©λΆ„νžˆ 검증할 수 있고 자주 변동될 수 μžˆλŠ” λΉ„μ¦ˆλ‹ˆμŠ€ μš”κ΅¬μ‚¬ν•­μ΄κΈ° λ•Œλ¬Έμ— 도메인에 λ°˜μ˜μ‹œμΌœμ„œ λ”λΈ”μ²΄ν‚Ήν•˜κΈ°λ³΄λ‹¨ ν΄λΌμ΄μ–ΈνŠΈμ—μ„œ κ²€μ¦ν•˜λŠ”κ²Œ μ’‹λ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€!


@Embedded
private Driver driver;

@Embedded
private Cost cost;

@Enumerated(EnumType.STRING)
@Column(name = "carpool_state")
@Builder.Default
private CarpoolState carpoolState = CarpoolState.OPEN;

@Enumerated(EnumType.STRING)
@Column(name = "mood_type")
private MoodType moodType;

@Column(name = "is_deleted", nullable = false)
@Builder.Default
private boolean isDeleted = false;

@Column(name = "created_at")
@CreatedDate
private LocalDateTime createdAt;

@Column(name = "updated_at")
@LastModifiedDate
private LocalDateTime updatedAt;
}
21 changes: 21 additions & 0 deletions src/main/java/com/fullcar/carpool/domain/CarpoolId.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.fullcar.carpool.domain;

import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.io.Serializable;

import static lombok.AccessLevel.PROTECTED;

@Embeddable
@Getter
@NoArgsConstructor(access = PROTECTED)
@AllArgsConstructor
public class CarpoolId implements Serializable {

@Column(name = "id")
private Long id;
}
11 changes: 11 additions & 0 deletions src/main/java/com/fullcar/carpool/domain/CarpoolRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.fullcar.carpool.domain;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.Optional;

@Repository
public interface CarpoolRepository extends JpaRepository<Carpool, CarpoolId> {
Optional<Carpool> findByCarpoolIdAndIsDeleted(CarpoolId carpoolId, boolean isDeleted);
}
6 changes: 6 additions & 0 deletions src/main/java/com/fullcar/carpool/domain/CarpoolState.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.fullcar.carpool.domain;

public enum CarpoolState {
OPEN,
CLOSE
}
25 changes: 25 additions & 0 deletions src/main/java/com/fullcar/carpool/domain/Cost.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.fullcar.carpool.domain;

import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import static lombok.AccessLevel.PROTECTED;

@Embeddable
@Getter
@Builder
@NoArgsConstructor(access = PROTECTED)
@AllArgsConstructor(access = PROTECTED)
public class Cost {
private Long money;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ν¬λ§λΉ„μš©μ€ μ΅œλŒ€ 10μžλ„€μš”!


@Enumerated(EnumType.STRING)
@Column(name = "period_type")
private PeriodType periodType;
}
26 changes: 26 additions & 0 deletions src/main/java/com/fullcar/carpool/domain/Driver.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.fullcar.carpool.domain;

import com.fullcar.member.domain.MemberId;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import static lombok.AccessLevel.PROTECTED;


@Embeddable
@Getter
@Builder
@NoArgsConstructor(access = PROTECTED)
@AllArgsConstructor(access = PROTECTED)
public class Driver {
@Embedded
@AttributeOverrides(
@AttributeOverride(name = "id", column = @Column(name = "driver_id"))
)
private MemberId memberId;

//:TODO CarId
}
6 changes: 6 additions & 0 deletions src/main/java/com/fullcar/carpool/domain/MoodType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.fullcar.carpool.domain;

public enum MoodType {
CHATTY,
QUIET
}
9 changes: 9 additions & 0 deletions src/main/java/com/fullcar/carpool/domain/PeriodType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.fullcar.carpool.domain;

public enum PeriodType {
ONCE,
ONE_WEEK,
TWO_WEEK,
THREE_WEEK,
FOUR_WEEK
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.fullcar.carpool.domain.service;

import com.fullcar.carpool.domain.CarpoolId;
import com.fullcar.core.id.SnowFlake;
import org.springframework.stereotype.Service;

@Service
public class CarpoolIdService {
private final SnowFlake snowFlake;

public CarpoolIdService() {
snowFlake = new SnowFlake(255);
}
public CarpoolId nextId() {
return new CarpoolId(snowFlake.nextId());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.fullcar.carpool.presentation;

import com.fullcar.carpool.application.CarpoolService;
import com.fullcar.carpool.presentation.dto.CarpoolDto;
import com.fullcar.core.annotation.CurrentMember;
import com.fullcar.core.response.ApiResponse;
import com.fullcar.core.response.SuccessCode;
import com.fullcar.member.domain.Member;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
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;


@Tag(description = "μΉ΄ν’€ κ΄€λ ¨ Endpoint", name = "μΉ΄ν’€")
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/carpools")
public class CarpoolController {
private final CarpoolService carpoolService;

@Operation(description = "μΉ΄ν’€ 등둝")
@ApiResponses({
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "201", description = "등둝 성곡")
})
@PostMapping("")
public ApiResponse<CarpoolDto> postCarpool(
@Parameter(hidden = true)
@CurrentMember Member member,
@Parameter(description = "μΉ΄ν’€ λͺ¨λΈ", required = true)
@RequestBody @Valid CarpoolDto carpoolDto
) {
return ApiResponse.success(
SuccessCode.REGISTER_SUCCESS,
carpoolService.registerCarpool(member.getId(), carpoolDto)
);
}
}
37 changes: 37 additions & 0 deletions src/main/java/com/fullcar/carpool/presentation/dto/CarpoolDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.fullcar.carpool.presentation.dto;

import com.fullcar.carpool.domain.Carpool;
import com.fullcar.carpool.domain.CarpoolId;
import com.fullcar.carpool.domain.MoodType;
import com.fullcar.carpool.domain.PeriodType;
import com.fullcar.carpool.domain.service.CarpoolIdService;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import org.springframework.stereotype.Component;


@Getter
@Builder
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Schema(description = "μΉ΄ν’€ λͺ¨λΈ")
public class CarpoolDto {

@Schema(description = "μΉ΄ν’€ id")
private Long id;

@Schema(description = "ν”½μ—…μž₯μ†Œ")
private String pickupLocation;

@Schema(description = "ν¬λ§λΉ„μš©(κΈ°κ°„)")
private PeriodType periodType;

@Schema(description = "ν¬λ§λΉ„μš©(가격)")
private Long money;

@Schema(description = "νƒ‘μŠΉμžμ—κ²Œ μ „ν•  말")
private String content;

@Schema(description = "μš΄ν–‰ λΆ„μœ„κΈ°")
private MoodType moodType;
}
15 changes: 15 additions & 0 deletions src/main/java/com/fullcar/core/annotation/CurrentMember.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.fullcar.core.annotation;

import org.springframework.security.core.annotation.AuthenticationPrincipal;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Target({ElementType.PARAMETER, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member")
public @interface CurrentMember {
}
4 changes: 3 additions & 1 deletion src/main/java/com/fullcar/core/config/SecurityConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.fullcar.core.config.jwt.JwtAuthenticationEntryPoint;
import com.fullcar.core.config.jwt.JwtAuthenticationFilter;
import com.fullcar.core.config.jwt.JwtTokenProvider;
import com.fullcar.member.application.CustomUserDetailService;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
Expand All @@ -19,6 +20,7 @@
public class SecurityConfig {
private final JwtTokenProvider jwtTokenProvider;
private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
private final CustomUserDetailService customUserDetailService;

private static final String[] AUTH_WHITELIST = {
"/api/v1/auth/**",
Expand Down Expand Up @@ -50,7 +52,7 @@ protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
authorizeRequests.anyRequest().authenticated();
})
.exceptionHandling(handler -> handler.authenticationEntryPoint(jwtAuthenticationEntryPoint))
.addFilterBefore(new JwtAuthenticationFilter(jwtTokenProvider, jwtAuthenticationEntryPoint), UsernamePasswordAuthenticationFilter.class);
.addFilterBefore(new JwtAuthenticationFilter(jwtTokenProvider, jwtAuthenticationEntryPoint, customUserDetailService), UsernamePasswordAuthenticationFilter.class);

return http.build();
}
Expand Down
Loading
Loading