Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,11 @@ class AdminProductController(
)
}

@Operation(summary = "상품 판매 여부 수정", description = "상품의 판매 여부를 수정합니다.")
@Operation(
summary = "상품 판매 여부 수정",
description = "상품의 판매 여부를 수정합니다. deprecated: 상품 상태 수정 API로 대체됩니다.",
deprecated = true
)
@PutMapping("/product/sellable")
fun updateProductSellable(
@AdminUsername username: String,
Expand All @@ -96,6 +100,20 @@ class AdminProductController(
)
}

@Operation(summary = "상품 상태 수정", description = "상품의 상태를 수정합니다.")
@PutMapping("/product/status")
fun updateProductStatus(
@AdminUsername username: String,
@RequestBody body: UpdateProductStatusRequestBody,
): ProductDto {
return productFacade.updateProductStatus(
username,
body.workspaceId,
body.productId,
body.status
)
}

@Operation(summary = "상품 삭제", description = "상품을 삭제합니다.")
@DeleteMapping("/product")
fun deleteProduct(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.kioschool.kioschoolapi.domain.product.dto.common

import com.kioschool.kioschoolapi.domain.product.dto.common.ProductCategoryDto
import com.kioschool.kioschoolapi.domain.product.entity.Product
import com.kioschool.kioschoolapi.global.common.enums.ProductStatus
import java.time.LocalDateTime

data class ProductDto(
Expand All @@ -11,6 +11,7 @@ data class ProductDto(
val price: Int,
val imageUrl: String?,
val isSellable: Boolean?,
val status: ProductStatus?,
val productCategory: ProductCategoryDto?,
val createdAt: LocalDateTime?,
val updatedAt: LocalDateTime?
Expand All @@ -24,6 +25,7 @@ data class ProductDto(
price = product.price,
imageUrl = product.imageUrl,
isSellable = product.isSellable,
status = product.status,
productCategory = product.productCategory?.let { ProductCategoryDto.of(it) },
createdAt = product.createdAt,
updatedAt = product.updatedAt
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.kioschool.kioschoolapi.domain.product.dto.request

import com.kioschool.kioschoolapi.global.common.enums.ProductStatus

class UpdateProductStatusRequestBody(
val workspaceId: Long,
val productId: Long,
val status: ProductStatus
)
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.kioschool.kioschoolapi.domain.product.entity
import com.fasterxml.jackson.annotation.JsonIgnore
import com.kioschool.kioschoolapi.domain.workspace.entity.Workspace
import com.kioschool.kioschoolapi.global.common.entity.BaseEntity
import com.kioschool.kioschoolapi.global.common.enums.ProductStatus
import jakarta.persistence.Entity
import jakarta.persistence.ManyToOne
import jakarta.persistence.Table
Expand All @@ -15,6 +16,7 @@ class Product(
var price: Int,
var imageUrl: String? = null,
var isSellable: Boolean? = true,
var status: ProductStatus = ProductStatus.SELLING,
@ManyToOne
@JsonIgnore
val workspace: Workspace,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import com.kioschool.kioschoolapi.domain.workspace.exception.WorkspaceInaccessib
import com.kioschool.kioschoolapi.domain.workspace.service.WorkspaceService
import com.kioschool.kioschoolapi.global.aws.S3Service
import com.kioschool.kioschoolapi.global.cache.constant.CacheNames
import com.kioschool.kioschoolapi.global.common.enums.ProductStatus
import org.springframework.cache.annotation.Cacheable
import org.springframework.stereotype.Component
import org.springframework.web.multipart.MultipartFile
Expand Down Expand Up @@ -167,4 +168,17 @@ class ProductFacade(
return productService.saveProductCategories(productCategories)
.map { ProductCategoryDto.of(it) }
}

fun updateProductStatus(
username: String,
workspaceId: Long,
productId: Long,
status: ProductStatus
): ProductDto {
val product = productService.getProduct(productId)
workspaceService.checkAccessible(username, workspaceId)

product.status = status
return ProductDto.of(productService.saveProduct(product))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.kioschool.kioschoolapi.global.common.enums

enum class ProductStatus {
SELLING,
SOLD_OUT,
HIDDEN,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.kioschool.kioschoolapi.global.schedule.script

import com.kioschool.kioschoolapi.domain.product.repository.ProductRepository
import com.kioschool.kioschoolapi.global.common.enums.ProductStatus
import com.kioschool.kioschoolapi.global.schedule.Runnable
import org.springframework.stereotype.Component

@Component
class InitProductStatus(
private val productRepository: ProductRepository
) : Runnable {
override fun run() {
val products = productRepository.findAll()
products.filter {
it.status == null
}.forEach {
it.status = if (it.isSellable == true) {
ProductStatus.SELLING
} else {
ProductStatus.HIDDEN
}
}
productRepository.saveAll(products)
}
}
14 changes: 14 additions & 0 deletions src/main/resources/db/changelog/2025/11/22-01-changelog.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
objectQuotingStrategy="QUOTE_ONLY_RESERVED_WORDS"
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.24.xsd">
<changeSet author="ji-inpark" id="1763810146816-1">
<addColumn tableName="product">
<column name="status" type="SMALLINT"/>
</addColumn>
</changeSet>

</databaseChangeLog>
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import com.kioschool.kioschoolapi.domain.workspace.exception.WorkspaceInaccessib
import com.kioschool.kioschoolapi.domain.workspace.service.WorkspaceService
import com.kioschool.kioschoolapi.factory.SampleEntity
import com.kioschool.kioschoolapi.global.aws.S3Service
import com.kioschool.kioschoolapi.global.common.enums.ProductStatus
import io.kotest.core.spec.style.DescribeSpec
import io.mockk.*
import org.junit.jupiter.api.assertThrows
Expand Down Expand Up @@ -680,4 +681,49 @@ class ProductFacadeTest : DescribeSpec({
verify(exactly = 0) { productService.saveProductCategories(any()) }
}
}

describe("updateProductStatus") {
it("should update product status") {
val username = "username"
val workspaceId = 1L
val productId = 1L
val status = ProductStatus.SOLD_OUT
val product = SampleEntity.product
every { productService.getProduct(productId) } returns product
every { workspaceService.checkAccessible(username, workspaceId) } just Runs
every { productService.saveProduct(product) } returns product

val result = sut.updateProductStatus(username, workspaceId, productId, status)

assert(result.id == product.id)
assert(result.status == status)

verify { productService.getProduct(productId) }
verify { workspaceService.checkAccessible(username, workspaceId) }
verify { productService.saveProduct(product) }
}

it("should throw WorkspaceInaccessibleException") {
val username = "username"
val workspaceId = 1L
val productId = 1L
val status = ProductStatus.SOLD_OUT
val product = SampleEntity.product
every { productService.getProduct(productId) } returns product
every {
workspaceService.checkAccessible(
username,
workspaceId
)
} throws WorkspaceInaccessibleException()

assertThrows<WorkspaceInaccessibleException> {
sut.updateProductStatus(username, workspaceId, productId, status)
}

verify { productService.getProduct(productId) }
verify { workspaceService.checkAccessible(username, workspaceId) }
verify(exactly = 0) { productService.saveProduct(any()) }
}
}
})