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

Test/member delete #61

Merged
merged 12 commits into from
Sep 23, 2024
67 changes: 67 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ plugins {
kotlin("jvm") version "1.9.24"
kotlin("plugin.spring") version "1.9.24"
kotlin("plugin.jpa") version "1.9.24" //Entity의 기본생성자를 자동으로 만들어줌

java
jacoco
}

group = "org.store"
Expand All @@ -18,6 +21,7 @@ java {

repositories {
mavenCentral()
maven(url = "https://jitpack.io")
}

dependencies {
Expand Down Expand Up @@ -82,12 +86,75 @@ dependencies {
implementation("org.springframework.boot:spring-boot-starter-data-redis") //redis
testRuntimeOnly("org.junit.platform:junit-platform-launcher")

// 아임포트(결제) 관련
implementation("com.github.iamport:iamport-rest-client-java:0.2.23")

//vault
implementation("org.springframework.cloud:spring-cloud-starter-bootstrap:4.1.4")
implementation("org.springframework.cloud:spring-cloud-config-server:4.1.3")
implementation("org.springframework.cloud:spring-cloud-starter-vault-config:4.1.3")
}

jacoco {
// JaCoCo 버전
toolVersion = "0.8.8"

// 테스트결과 리포트를 저장할 경로 변경
// default는 "${project.reporting.baseDir}/jacoco"
// reportsDir = file("$buildDir/customJacocoReportDir")
}

// kotlin DSL

tasks.jacocoTestReport {
reports {
// 원하는 리포트를 켜고 끌 수 있습니다.
// html.isEnabled = true
// xml.isEnabled = false
// csv.isEnabled = false

//.isEnabled 가 Deprecated 되었습니다 (저는 gradle 7.2 버전에 kotlin DSL 사용하고 있습니다)
html.required.set(true)
xml.required.set(false)
csv.required.set(false)

// 각 리포트 타입 마다 리포트 저장 경로를 설정할 수 있습니다.
// html.destination = file("$buildDir/jacocoHtml")
// xml.destination = file("$buildDir/jacoco.xml")
}
}

tasks.jacocoTestCoverageVerification {
violationRules {
rule {
// 룰을 간단히 켜고 끌 수 있다.
enabled = true

// 룰을 체크할 단위는 클래스 단위
element = "CLASS"

// 메서드 커버리지를 최소한 00% 만족시켜야 한다.
limit {
counter = "METHOD"
value = "COVEREDRATIO"
minimum = "0.00".toBigDecimal()
}

// 라인 커버리지를 최소한 00% 만족시켜야 한다.
limit {
counter = "LINE"
value = "COVEREDRATIO"
minimum = "0.00".toBigDecimal()
}
}
}
}

tasks.withType<Test> {
useJUnitPlatform()
finalizedBy("jacocoTestReport")
}

tasks.jacocoTestReport {
finalizedBy("jacocoTestCoverageVerification")
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
package org.store.clothstar.common.config

import com.fasterxml.jackson.databind.ObjectMapper
import io.github.oshai.kotlinlogging.KotlinLogging
import jakarta.servlet.ServletException
import jakarta.servlet.http.HttpServletRequest
import jakarta.servlet.http.HttpServletResponse
import org.springframework.security.core.AuthenticationException
import org.springframework.security.web.AuthenticationEntryPoint
import org.springframework.stereotype.Component
import org.store.clothstar.common.dto.MessageDTO
import java.io.IOException

@Component
Expand All @@ -23,15 +21,6 @@ class CustomAuthenticationEntryPoint : AuthenticationEntryPoint {
) {
log.error { "인증 실패 로직 실행" }

response.status = HttpServletResponse.SC_UNAUTHORIZED
response.characterEncoding = "UTF-8"
response.contentType = "application/json"

val messageDTO = MessageDTO(
HttpServletResponse.SC_UNAUTHORIZED,
"권한이 없습니다."
)

response.writer.write(ObjectMapper().writeValueAsString(messageDTO))
response.sendRedirect(request.contextPath + "/login")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import org.springframework.security.config.annotation.web.configurers.*
import org.springframework.security.config.http.SessionCreationPolicy
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
import org.springframework.security.crypto.password.PasswordEncoder
import org.springframework.security.web.AuthenticationEntryPoint
import org.springframework.security.web.SecurityFilterChain
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
import org.store.clothstar.common.config.jwt.JwtAuthenticationFilter
Expand All @@ -25,6 +26,7 @@ class SecurityConfiguration(
private val authenticationConfiguration: AuthenticationConfiguration,
private val jwtAuthenticationFilter: JwtAuthenticationFilter,
private val jwtUtil: JwtUtil,
private val customAuthenticationEntryPoint: AuthenticationEntryPoint,
) {
@Bean
fun passwordEncoder(): PasswordEncoder {
Expand Down Expand Up @@ -52,6 +54,10 @@ class SecurityConfiguration(
.csrf { obj: CsrfConfigurer<HttpSecurity> -> obj.disable() }
.httpBasic { obj: HttpBasicConfigurer<HttpSecurity> -> obj.disable() }
.formLogin { obj: FormLoginConfigurer<HttpSecurity> -> obj.disable() }
.exceptionHandling { exception ->
exception.authenticationEntryPoint(customAuthenticationEntryPoint)
}


http.authorizeHttpRequests(
Customizer { auth ->
Expand All @@ -60,7 +66,7 @@ class SecurityConfiguration(
"/", "/login", "/userPage", "/sellerPage", "/adminPage", "/main",
"/v1/members/login", "/signup", "/v1/members/email/**", "/v1/access",
"/v1/categories/**", "/v1/products/**", "/v1/productLines/**", "/v2/productLines/**",
"/productLinePagingSlice", "/productLinePagingOffset",
"/productPagingSlice", "/productPagingOffset",
"/v3/products/**", "v3/sellers/products/**",
"/v1/orderdetails", "/v1/orders", "membersPagingOffset", "membersPagingSlice",
"/v1/orderdetails", "/v1/orders", "/v2/orders", "/v3/orders", "/v1/orders/list",
Expand All @@ -76,6 +82,7 @@ class SecurityConfiguration(
"/v1/members?signUpType=KAKAO",
"/v1/members/**",
"/v1/members/auth/**",
"config-service/**", "products/**", "productDetail", "payment/**", "/v1/payments/**"
).permitAll()
.requestMatchers(HttpMethod.POST, "/v1/members").permitAll()
.requestMatchers(HttpMethod.POST, "/v1/sellers/**").authenticated()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.data.domain.Slice
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import org.store.clothstar.member.authentication.service.AuthenticationService
import org.store.clothstar.member.domain.MemberRole
import org.store.clothstar.member.dto.request.CreateMemberRequest
Expand All @@ -13,6 +14,7 @@ import org.store.clothstar.member.service.AccountService
import org.store.clothstar.member.service.MemberService

@Service
@Transactional
class MemberServiceApplication(
private val memberService: MemberService,
private val accountService: AccountService,
Expand Down Expand Up @@ -42,11 +44,13 @@ class MemberServiceApplication(
memberService.updatePassword(accountId, password)
}

@Transactional
fun updateDeleteAt(memberId: Long) {
memberService.updateDeleteAt(memberId)
accountService.updateDeletedAt(memberId, MemberRole.USER)
}

@Transactional
fun signUp(createMemberRequest: CreateMemberRequest): Long {
//인증번호 확인
authenticationService.verifyEmailCertifyNum(createMemberRequest.email, createMemberRequest.certifyNum)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package org.store.clothstar.member.service

import jakarta.transaction.Transactional
import org.springframework.security.crypto.password.PasswordEncoder
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import org.store.clothstar.common.error.ErrorCode
import org.store.clothstar.common.error.exception.DuplicatedEmailException
import org.store.clothstar.common.error.exception.NotFoundAccountException
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class MemberServiceImpl(
override fun getMemberById(memberId: Long): MemberResponse {
log.info { "회원 상세 조회 memberId = ${memberId}" }

return memberRepository.findByMemberId(memberId)?.let { member ->
return memberRepository.findByIdOrNull(memberId)?.let { member ->
MemberResponse(
memberId = member.memberId!!,
name = member.name,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.store.clothstar.payment.application

import io.github.oshai.kotlinlogging.KotlinLogging
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import org.store.clothstar.payment.dto.request.SavePaymentRequest
import org.store.clothstar.payment.service.PaymentService
import org.store.clothstar.product.service.ItemService

@Service
class PaymentServiceApplication(
private val itemService: ItemService,
private val paymentService: PaymentService,
) {
private val log = KotlinLogging.logger {}

@Transactional
fun savePayment(savePaymentRequest: SavePaymentRequest) {
//재고차감
log.info { "재고차감 로직 실행" }
val item = itemService.getItemById(savePaymentRequest.itemId)
itemService.deductItemStock(item, savePaymentRequest.buyQuantity)

//구매이력 저장
log.info { "구매이력 저장 실행" }
paymentService.savePayment(savePaymentRequest)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package org.store.clothstar.payment.controller

import io.github.oshai.kotlinlogging.KotlinLogging
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RestController
import org.store.clothstar.common.dto.MessageDTO
import org.store.clothstar.payment.application.PaymentServiceApplication
import org.store.clothstar.payment.dto.request.SavePaymentRequest

@RestController
class PaymentController(
private val paymentServiceApplication: PaymentServiceApplication,
) {
private val log = KotlinLogging.logger {}

@PostMapping("/v1/payments")
fun savePayment(@RequestBody savePaymentRequest: SavePaymentRequest): ResponseEntity<MessageDTO> {
log.info { "/v1/payment post 요청 실행" }

paymentServiceApplication.savePayment(savePaymentRequest)

val messageDTO = MessageDTO(
HttpStatus.OK.value(),
"상품을 구매 완료 하였습니다."
)

return ResponseEntity(messageDTO, HttpStatus.OK)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.store.clothstar.payment.controller

import org.springframework.stereotype.Controller
import org.springframework.ui.Model
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable


@Controller
class PaymentViewController {
@GetMapping("/payment/{productId}/{itemId}")
fun paymentPage(@PathVariable itemId: Long, @PathVariable productId: Long, model: Model): String {
model.addAttribute("productId", productId)
model.addAttribute("itemId", itemId)
return "payment"
}
}
28 changes: 28 additions & 0 deletions src/main/kotlin/org/store/clothstar/payment/domain/Payment.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.store.clothstar.payment.domain

import jakarta.persistence.Entity
import jakarta.persistence.GeneratedValue
import jakarta.persistence.GenerationType
import jakarta.persistence.Id

@Entity
class Payment(
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
val paymentId: Long? = null,

var productId: Long,
var itemId: Long,
var impUid: String,
var merchantUid: String,
var itemName: String,
var itemOption: String,
var paidAmount: Int,
var buyQuantity: Int,
var buyerName: String,
var buyerEmail: String,
var buyerTelNo: String,
var buyerAddr: String,
var buyerPostCode: String,
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package org.store.clothstar.payment.dto.request

import jakarta.validation.constraints.NotBlank
import org.store.clothstar.payment.domain.Payment

class SavePaymentRequest(
@field: NotBlank
var productId: Long,

@field: NotBlank
var itemId: Long,

@field: NotBlank
var impUid: String,

@field: NotBlank
var merchantUid: String,

@field: NotBlank
var itemName: String,

@field: NotBlank
var itemOption: String,

@field: NotBlank
var paidAmount: Int,

@field: NotBlank
var buyQuantity: Int,

@field: NotBlank
var buyerName: String,

@field: NotBlank
var buyerEmail: String,

@field: NotBlank
var buyerTelNo: String,

@field: NotBlank
var buyerAddr: String,

@field: NotBlank
var buyerPostCode: String,
) {
fun toPayment(): Payment {
return Payment(
productId = productId,
itemId = itemId,
impUid = impUid,
merchantUid = merchantUid,
itemName = itemName,
itemOption = itemOption,
paidAmount = paidAmount,
buyQuantity = buyQuantity,
buyerName = buyerName,
buyerEmail = buyerEmail,
buyerTelNo = buyerTelNo,
buyerAddr = buyerAddr,
buyerPostCode = buyerPostCode,
)
}
}
Loading
Loading