Skip to content

Commit

Permalink
Merge pull request #61 from ClothingStoreService/test/member-delete
Browse files Browse the repository at this point in the history
Test/member delete
  • Loading branch information
hjj4060 authored Sep 23, 2024
2 parents c38db16 + feee25c commit 8992997
Show file tree
Hide file tree
Showing 22 changed files with 908 additions and 33 deletions.
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

0 comments on commit 8992997

Please sign in to comment.