[#44] 매장 기능 도입 #45

Merged
pricelees merged 116 commits from feat/#44 into main 2025-09-20 03:15:06 +00:00
3 changed files with 78 additions and 13 deletions
Showing only changes of commit 498e8c8e75 - Show all commits

View File

@ -3,19 +3,21 @@ package roomescape.supports
import com.github.f4b6a3.tsid.TsidFactory import com.github.f4b6a3.tsid.TsidFactory
import roomescape.admin.infrastructure.persistence.AdminEntity import roomescape.admin.infrastructure.persistence.AdminEntity
import roomescape.admin.infrastructure.persistence.AdminPermissionLevel import roomescape.admin.infrastructure.persistence.AdminPermissionLevel
import roomescape.admin.infrastructure.persistence.AdminType
import roomescape.common.config.next import roomescape.common.config.next
import roomescape.user.infrastructure.persistence.UserEntity
import roomescape.user.infrastructure.persistence.UserStatus
import roomescape.user.web.MIN_PASSWORD_LENGTH
import roomescape.user.web.UserCreateRequest
import roomescape.payment.infrastructure.client.* import roomescape.payment.infrastructure.client.*
import roomescape.payment.infrastructure.common.* import roomescape.payment.infrastructure.common.*
import roomescape.payment.web.PaymentCancelRequest import roomescape.payment.web.PaymentCancelRequest
import roomescape.payment.web.PaymentConfirmRequest import roomescape.payment.web.PaymentConfirmRequest
import roomescape.reservation.web.PendingReservationCreateRequest import roomescape.reservation.web.PendingReservationCreateRequest
import roomescape.schedule.web.ScheduleCreateRequest import roomescape.schedule.web.ScheduleCreateRequest
import roomescape.store.infrastructure.persistence.StoreEntity
import roomescape.theme.infrastructure.persistence.Difficulty import roomescape.theme.infrastructure.persistence.Difficulty
import roomescape.theme.web.ThemeCreateRequest import roomescape.theme.web.ThemeCreateRequest
import roomescape.user.infrastructure.persistence.UserEntity
import roomescape.user.infrastructure.persistence.UserStatus
import roomescape.user.web.MIN_PASSWORD_LENGTH
import roomescape.user.web.UserCreateRequest
import java.time.LocalDate import java.time.LocalDate
import java.time.LocalTime import java.time.LocalTime
import java.time.OffsetDateTime import java.time.OffsetDateTime
@ -23,8 +25,44 @@ import java.time.OffsetDateTime
const val INVALID_PK: Long = 9999L const val INVALID_PK: Long = 9999L
val tsidFactory = TsidFactory(0) val tsidFactory = TsidFactory(0)
fun randomPhoneNumber(): String {
val prefix = "010"
val middle = (1000..9999).random()
val last = (1000..9999).random()
return "$prefix$middle$last"
}
object StoreFixture {
fun create(
id: Long = tsidFactory.next(),
name: String = "테스트행복점",
address: String = "서울특별시 강북구 행복길 123",
businessRegNum: String = "123-45-67890",
regionCode: String = "1111000000"
) = StoreEntity(
id = id,
name = name,
address = address,
businessRegNum = businessRegNum,
regionCode = regionCode
)
}
object AdminFixture { object AdminFixture {
val default: AdminEntity = create() val default: AdminEntity = create()
val storeDefault: AdminEntity = create(
account = "admin-store",
phone = randomPhoneNumber(),
type = AdminType.STORE,
storeId = tsidFactory.next()
)
val hqDefault: AdminEntity = create(
account = "admin-hq",
phone = randomPhoneNumber(),
type = AdminType.HQ,
storeId = null
)
fun create( fun create(
id: Long = tsidFactory.next(), id: Long = tsidFactory.next(),
@ -32,6 +70,8 @@ object AdminFixture {
password: String = "adminPassword", password: String = "adminPassword",
name: String = "admin12345", name: String = "admin12345",
phone: String = "01012345678", phone: String = "01012345678",
type: AdminType = AdminType.STORE,
storeId: Long? = tsidFactory.next(),
permissionLevel: AdminPermissionLevel = AdminPermissionLevel.FULL_ACCESS permissionLevel: AdminPermissionLevel = AdminPermissionLevel.FULL_ACCESS
): AdminEntity = AdminEntity( ): AdminEntity = AdminEntity(
id = id, id = id,
@ -39,8 +79,10 @@ object AdminFixture {
password = password, password = password,
name = name, name = name,
phone = phone, phone = phone,
permissionLevel = permissionLevel type = type,
) storeId = storeId,
permissionLevel = permissionLevel,
)
} }
object UserFixture { object UserFixture {

View File

@ -14,12 +14,13 @@ import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Import import org.springframework.context.annotation.Import
import org.springframework.test.context.ActiveProfiles import org.springframework.test.context.ActiveProfiles
import roomescape.admin.infrastructure.persistence.AdminRepository import roomescape.admin.infrastructure.persistence.AdminRepository
import roomescape.user.infrastructure.persistence.UserRepository
import roomescape.payment.business.PaymentWriter import roomescape.payment.business.PaymentWriter
import roomescape.payment.infrastructure.persistence.PaymentRepository import roomescape.payment.infrastructure.persistence.PaymentRepository
import roomescape.reservation.infrastructure.persistence.ReservationRepository import roomescape.reservation.infrastructure.persistence.ReservationRepository
import roomescape.schedule.infrastructure.persistence.ScheduleRepository import roomescape.schedule.infrastructure.persistence.ScheduleRepository
import roomescape.store.infrastructure.persistence.StoreRepository
import roomescape.theme.infrastructure.persistence.ThemeRepository import roomescape.theme.infrastructure.persistence.ThemeRepository
import roomescape.user.infrastructure.persistence.UserRepository
object KotestConfig : AbstractProjectConfig() { object KotestConfig : AbstractProjectConfig() {
override fun extensions(): List<SpringTestExtension> = listOf(SpringExtension) override fun extensions(): List<SpringTestExtension> = listOf(SpringExtension)
@ -37,6 +38,9 @@ abstract class FunSpecSpringbootTest : FunSpec({
@Autowired @Autowired
private lateinit var adminRepository: AdminRepository private lateinit var adminRepository: AdminRepository
@Autowired
private lateinit var storeRepository: StoreRepository
@Autowired @Autowired
lateinit var dummyInitializer: DummyInitializer lateinit var dummyInitializer: DummyInitializer
@ -47,7 +51,7 @@ abstract class FunSpecSpringbootTest : FunSpec({
override suspend fun beforeSpec(spec: Spec) { override suspend fun beforeSpec(spec: Spec) {
RestAssured.port = port RestAssured.port = port
authUtil = AuthUtil(userRepository, adminRepository) authUtil = AuthUtil(userRepository, adminRepository, storeRepository)
} }
} }

View File

@ -17,15 +17,26 @@ import roomescape.admin.infrastructure.persistence.AdminRepository
import roomescape.auth.web.LoginRequest import roomescape.auth.web.LoginRequest
import roomescape.common.dto.PrincipalType import roomescape.common.dto.PrincipalType
import roomescape.common.exception.ErrorCode import roomescape.common.exception.ErrorCode
import roomescape.store.infrastructure.persistence.StoreRepository
import roomescape.user.infrastructure.persistence.UserEntity import roomescape.user.infrastructure.persistence.UserEntity
import roomescape.user.infrastructure.persistence.UserRepository import roomescape.user.infrastructure.persistence.UserRepository
import roomescape.user.web.UserCreateRequest import roomescape.user.web.UserCreateRequest
import kotlin.random.Random
class AuthUtil( class AuthUtil(
private val userRepository: UserRepository, private val userRepository: UserRepository,
private val adminRepository: AdminRepository private val adminRepository: AdminRepository,
private val storeRepository: StoreRepository,
) { ) {
fun createAdmin(admin: AdminEntity): AdminEntity { fun createAdmin(admin: AdminEntity): AdminEntity {
val storeId = admin.storeId
if (storeId != null && storeRepository.findByIdOrNull(storeId) == null) {
storeRepository.save(StoreFixture.create(
id = storeId,
businessRegNum = generateBusinessRegNum(),
))
}
return adminRepository.save(admin) return adminRepository.save(admin)
} }
@ -46,10 +57,8 @@ class AuthUtil(
} }
fun adminLogin(admin: AdminEntity): String { fun adminLogin(admin: AdminEntity): String {
if (adminRepository.findByAccount(admin.account) == null) { val saved = createAdmin(admin)
adminRepository.save(admin) val requestBody = LoginRequest(saved.account, saved.password, PrincipalType.ADMIN)
}
val requestBody = LoginRequest(admin.account, admin.password, PrincipalType.ADMIN)
return Given { return Given {
contentType(MediaType.APPLICATION_JSON_VALUE) contentType(MediaType.APPLICATION_JSON_VALUE)
@ -63,6 +72,9 @@ class AuthUtil(
} }
} }
fun defaultStoreAdminLogin(): String = adminLogin(AdminFixture.storeDefault)
fun defaultHqAdminLogin(): String = adminLogin(AdminFixture.hqDefault)
fun defaultAdminLogin(): String = adminLogin(AdminFixture.default) fun defaultAdminLogin(): String = adminLogin(AdminFixture.default)
fun userLogin(user: UserEntity): String { fun userLogin(user: UserEntity): String {
@ -172,3 +184,10 @@ fun ValidatableResponse.assertProperties(props: Set<String>, propsNameIfList: St
else -> error("Unexpected data type: ${json::class}") else -> error("Unexpected data type: ${json::class}")
} }
} }
private fun generateBusinessRegNum(): String {
val part1 = Random.nextInt(100, 1000)
val part2 = Random.nextInt(10, 100)
val part3 = Random.nextInt(10000, 100000)
return "$part1-$part2-$part3"
}