Skip to content

Commit 9881542

Browse files
authored
release: 0.1.0 (#10)
2 parents b14f3eb + c34441a commit 9881542

23 files changed

+462
-49
lines changed

docs/api/get_my_product.md

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
## Get my products
2+
3+
토큰에 해당하는 유저가 올린 상품들을 조회합니다.
4+
5+
## Request
6+
7+
### HTTP METHOD : `GET`
8+
9+
### url : `https://api.gitanimals.org/auctions/products/users`
10+
11+
### RequestHeader
12+
13+
- Authorization: `{token}`
14+
15+
### Request param
16+
17+
- `last-id` : last-id를 입력하면, lastId이후의 products들을 조회합니다. (lastId에 해당하는 products는 포함하지 않습니다.) 만약,
18+
입력하지 않을 경우, 가장 처음 products부터 count개 반환합니다.
19+
- `count` : `last-id` 이후의 product를 count개 조회합니다. 입력하지 않을 경우, 8개를 조회합니다.
20+
21+
## Response
22+
23+
```json
24+
{
25+
"products": [
26+
{
27+
"id": "1",
28+
"sellerId": "1",
29+
"persona": {
30+
"personaId": "1",
31+
"personaType": "PENGUIN",
32+
"personaLevel": 1
33+
},
34+
"price": "1000",
35+
"paymentState": "ON_SALE"
36+
},
37+
{
38+
"id": "2",
39+
"sellerId": "1",
40+
"persona": {
41+
"personaId": "1",
42+
"personaType": "CAT",
43+
"personaLevel": 1
44+
},
45+
"price": "1000",
46+
"paymentState": "ON_SALE"
47+
},
48+
{
49+
"id": "3",
50+
"sellerId": "1",
51+
"persona": {
52+
"personaId": "1",
53+
"personaType": "WHITE_CAT",
54+
"personaLevel": 1
55+
},
56+
"price": "1000",
57+
"paymentState": "ON_SALE"
58+
}
59+
]
60+
}
61+
```
62+
63+
| key | description |
64+
|----------------------------------|--------------------------------------------------------|
65+
| products.[].id | 등록된 상품의 id |
66+
| products.[].sellerId | 상품을 판매하는 유저의 id |
67+
| products.[].persona.personaId | persona의 id |
68+
| products.[].persona.personaType | persona의 type |
69+
| products.[].persona.personaLevel | persona의 level |
70+
| products.[].price | 등록된 상품의 가격 |
71+
| products.[].paymentState | 등록된 상품의 상태 |
72+
| products.[].receipt | 결제정보. 등록된 상품이 SOLD_OUT 상태일때만 존재하며, 아니라면, null값이 반환됩니다. |
73+

docs/api/get_product.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
## Get all pets
1+
## Get products
22

33
상품들을 조회합니다.
44

docs/api/get_product_histories.md

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
## Get my products
2+
3+
상품의 판매 내역을 조회합니다.
4+
5+
## Request
6+
7+
### HTTP METHOD : `GET`
8+
9+
### url : `https://api.gitanimals.org/auctions/products/histories`
10+
11+
### Request param
12+
13+
- `last-id` : last-id를 입력하면, lastId이후의 products들을 조회합니다. (lastId에 해당하는 products는 포함하지 않습니다.) 만약,
14+
입력하지 않을 경우, 가장 처음 products부터 count개 반환합니다.
15+
- `persona-type` : persona-type에 해당하는 products들을 반환합니다. 입력 가능한
16+
persona-type들은 [확률표](https://github.com/devxb/gitanimals#%EB%93%B1%EC%9E%A5-%EA%B0%80%EB%8A%A5%ED%95%9C-%ED%8E%AB%EB%93%A4)
17+
의 name과 일치합니다. 어떠한, 값도 입력하지 않을경우, 모든 persona-type에 해당하는 product 들을 조회합니다.
18+
- `count` : `last-id` 이후의 product를 count개 조회합니다. 입력하지 않을 경우, 8개를 조회합니다.
19+
20+
## Response
21+
22+
```json
23+
{
24+
"products": [
25+
{
26+
"id": "1",
27+
"sellerId": "1",
28+
"persona": {
29+
"personaId": "1",
30+
"personaType": "PENGUIN",
31+
"personaLevel": 1
32+
},
33+
"price": "1000",
34+
"paymentState": "SOLD_OUT",
35+
"receipt": {
36+
"buyerId": "12345677123123123123",
37+
"soldAt": "2024-05-06T12:30:45Z"
38+
}
39+
},
40+
{
41+
"id": "2",
42+
"sellerId": "1",
43+
"persona": {
44+
"personaId": "1",
45+
"personaType": "CAT",
46+
"personaLevel": 1
47+
},
48+
"price": "1000",
49+
"paymentState": "SOLD_OUT",
50+
"receipt": {
51+
"buyerId": "12345677123123123123",
52+
"soldAt": "2024-05-06T12:30:45Z"
53+
}
54+
},
55+
{
56+
"id": "3",
57+
"sellerId": "1",
58+
"persona": {
59+
"personaId": "1",
60+
"personaType": "WHITE_CAT",
61+
"personaLevel": 1
62+
},
63+
"price": "1000",
64+
"paymentState": "SOLD_OUT",
65+
"receipt": {
66+
"buyerId": "12345677123123123123",
67+
"soldAt": "2024-05-06T12:30:45Z"
68+
}
69+
}
70+
]
71+
}
72+
```
73+
74+
| key | description |
75+
|----------------------------------|--------------------------------------------------------|
76+
| products.[].id | 등록된 상품의 id |
77+
| products.[].sellerId | 상품을 판매하는 유저의 id |
78+
| products.[].persona.personaId | persona의 id |
79+
| products.[].persona.personaType | persona의 type |
80+
| products.[].persona.personaLevel | persona의 level |
81+
| products.[].price | 등록된 상품의 가격 |
82+
| products.[].paymentState | 등록된 상품의 상태 |
83+
| products.[].receipt | 결제정보. 등록된 상품이 SOLD_OUT 상태일때만 존재하며, 아니라면, null값이 반환됩니다. |
84+
| products.[].receipt.buyerId | 구매자의 id |
85+
| products.[].receipt.soldAt | 판매된 날짜 |
86+

docs/api/get_used_coupons.md

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Get used coupons
2+
3+
userId에 해당하는 user가 사용한 coupon들을 조회합니다.
4+
5+
## Request
6+
7+
### HTTP METHOD : `GET`
8+
9+
### url : `https://api.gitanimals.org/coupons/users`
10+
11+
### RequestHeader
12+
13+
- Authorization: `{token}`
14+
15+
# Response
16+
17+
```json
18+
{
19+
"id": "987654321",
20+
"userId": "user789",
21+
"code": "ABC123",
22+
"usedAt": "2024-05-06T15:45:30Z"
23+
}
24+
```
25+
26+
| key | description |
27+
|--------|---------------|
28+
| id | 쿠폰의 id |
29+
| userId | 쿠폰을 사용한 유저의 id |
30+
| code | 쿠폰의 code |
31+
| usedAt | 쿠폰을 사용한 날짜 |
32+
33+

src/main/kotlin/org/gitanimals/auction/app/BuyProductFacade.kt

+26-22
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,6 @@ class BuyProductFacade(
1818
private lateinit var orchestrator: Orchestrator<Long, Product>
1919

2020
fun buyProduct(token: String, productId: Long): Product {
21-
val buyer = identityApi.getUserByToken(token)
22-
val product = productService.getProductById(productId)
23-
24-
require(product.getPrice() <= buyer.points.toLong()) {
25-
"Cannot buy product cause buyer does not have enough point \"${product.getPrice()}\" >= \"${buyer.points}\""
26-
}
27-
2821
return orchestrator.sagaSync(
2922
productId,
3023
mapOf(
@@ -38,10 +31,14 @@ class BuyProductFacade(
3831
this.orchestrator = orchestratorFactory.create<Long>("buy product orchestrator")
3932
.startWithContext(
4033
contextOrchestrate = { context, productId ->
41-
val token = context.decodeContext("token", String::class)
42-
val buyer = identityApi.getUserByToken(token)
34+
val buyer = identityApi.getUserByToken(context.decodeContext("token", String::class))
35+
val product = productService.getProductById(productId)
36+
37+
require(product.getPrice() <= buyer.points.toLong()) {
38+
"Cannot buy product cause buyer does not have enough point \"${product.getPrice()}\" >= \"${buyer.points}\""
39+
}
4340

44-
productService.buyProduct(productId, buyer.id.toLong())
41+
productService.waitBuyProduct(productId, buyer.id.toLong())
4542
},
4643
contextRollback = { _, productId -> productService.rollbackProduct(productId) }
4744
)
@@ -61,19 +58,26 @@ class BuyProductFacade(
6158
identityApi.increasePoint(token, idempotencyKey, product.getPrice().toString())
6259
}
6360
)
64-
.commitWithContext { context, product ->
65-
val token = context.decodeContext("token", String::class)
66-
val idempotencyKey = context.decodeContext("idempotencyKey", String::class)
61+
.joinWithContext(
62+
contextOrchestrate = { context, product ->
63+
val token = context.decodeContext("token", String::class)
64+
val idempotencyKey = context.decodeContext("idempotencyKey", String::class)
6765

68-
renderApi.addPersona(
69-
token,
70-
idempotencyKey,
71-
product.persona.personaId,
72-
product.persona.personaLevel,
73-
product.persona.personaType,
74-
)
66+
renderApi.addPersona(
67+
token,
68+
idempotencyKey,
69+
product.persona.personaId,
70+
product.persona.personaLevel,
71+
product.persona.personaType,
72+
)
7573

76-
product
77-
}
74+
product
75+
},
76+
contextRollback = { context, product ->
77+
val token = context.decodeContext("token", String::class)
78+
79+
renderApi.deletePersonaById(token, product.persona.personaId)
80+
}
81+
).commit { product -> productService.buyProduct(product.id) }
7882
}
7983
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package org.gitanimals.auction.app
2+
3+
import org.gitanimals.auction.domain.Product
4+
import org.gitanimals.auction.domain.ProductService
5+
import org.springframework.stereotype.Service
6+
7+
@Service
8+
class GetProductFacade(
9+
private val identityApi: IdentityApi,
10+
private val productService: ProductService,
11+
) {
12+
fun getProductsByToken(token: String, lastId: Long, count: Int): List<Product> {
13+
val user = identityApi.getUserByToken(token)
14+
15+
return productService.getProductsByUserId(user.id.toLong(), lastId, count)
16+
}
17+
18+
19+
}

src/main/kotlin/org/gitanimals/auction/controller/AuctionController.kt

+26-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
package org.gitanimals.auction.controller
22

3-
import org.gitanimals.auction.app.BuyProductFacade
4-
import org.gitanimals.auction.app.ChangeProductFacade
5-
import org.gitanimals.auction.app.DeleteProductFacade
6-
import org.gitanimals.auction.app.RegisterProductFacade
3+
import org.gitanimals.auction.app.*
74
import org.gitanimals.auction.controller.request.RegisterProductRequest
85
import org.gitanimals.auction.controller.response.ErrorResponse
96
import org.gitanimals.auction.controller.response.ProductResponse
@@ -21,6 +18,7 @@ class AuctionController(
2118
private val deleteProductFacade: DeleteProductFacade,
2219
private val buyProductFacade: BuyProductFacade,
2320
private val registerProductFacade: RegisterProductFacade,
21+
private val getProductFacade: GetProductFacade,
2422
) {
2523

2624
@ResponseStatus(HttpStatus.OK)
@@ -35,6 +33,30 @@ class AuctionController(
3533
return ProductsResponse.from(products)
3634
}
3735

36+
@ResponseStatus(HttpStatus.OK)
37+
@GetMapping("/auctions/products/users")
38+
fun getProducts(
39+
@RequestHeader(HttpHeaders.AUTHORIZATION) token: String,
40+
@RequestParam(name = "last-id", defaultValue = "0") lastId: Long,
41+
@RequestParam(name = "count", defaultValue = "8") count: Int,
42+
): ProductsResponse {
43+
val products = getProductFacade.getProductsByToken(token, lastId, count)
44+
45+
return ProductsResponse.from(products)
46+
}
47+
48+
@ResponseStatus(HttpStatus.OK)
49+
@GetMapping("/auctions/products/histories")
50+
fun getHistory(
51+
@RequestParam(name = "last-id", defaultValue = "0") lastId: Long,
52+
@RequestParam(name = "persona-type", defaultValue = "ALL") personaType: String,
53+
@RequestParam(name = "count", defaultValue = "8") count: Int,
54+
): ProductsResponse {
55+
val products = productService.getProductHistories(lastId, personaType, count)
56+
57+
return ProductsResponse.from(products)
58+
}
59+
3860
@ResponseStatus(HttpStatus.OK)
3961
@PostMapping("/auctions/products")
4062
fun registerProducts(

src/main/kotlin/org/gitanimals/auction/controller/response/ProductResponse.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ data class ProductResponse(
3535
personaLevel = product.persona.personaLevel,
3636
),
3737
price = product.getPrice().toString(),
38-
paymentState = product.getProductState(),
39-
receipt = when (product.getProductState() == ProductState.SOLD_OUT) {
38+
paymentState = product.getState(),
39+
receipt = when (product.getState() == ProductState.SOLD_OUT) {
4040
true -> Receipt(product.getBuyerId()!!.toString(), product.getSoldAt()!!)
4141
else -> null
4242
}

0 commit comments

Comments
 (0)