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
13 changes: 13 additions & 0 deletions app/src/main/java/com/ssafy/tiggle/core/utils/Formatter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,19 @@ object Formatter {
}
}

// 날짜만 포맷팅: "2025-08-26T01:25:21" -> "2025.08.26"
@SuppressLint("NewApi")
fun formatDate(isoDateTime: String): String {
return try {
val dateTime = LocalDateTime.parse(isoDateTime)
val formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd")
dateTime.format(formatter)
} catch (e: DateTimeParseException) {
// 파싱 실패 시 원본 문자열 반환
isoDateTime
}
}

// 간단한 날짜 포맷팅: "2025-08-26T01:25:21" -> "8월 26일"
@SuppressLint("NewApi")
fun formatDateOnly(isoDateTime: String): String {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@ package com.ssafy.tiggle.data.datasource.remote

import com.ssafy.tiggle.data.model.BaseResponse
import com.ssafy.tiggle.data.model.EmptyResponse
import com.ssafy.tiggle.data.model.dutchpay.request.DutchPayPaymentRequestDto
import com.ssafy.tiggle.data.model.dutchpay.request.DutchPayRequestDto
import com.ssafy.tiggle.data.model.dutchpay.response.DutchPayRequestDetailResponseDto
import com.ssafy.tiggle.data.model.dutchpay.response.DutchPaySummaryResponseDto
import com.ssafy.tiggle.data.model.dutchpay.response.DutchPayListResponseDto
import com.ssafy.tiggle.data.model.dutchpay.response.DutchPayDetailResponseDto
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.POST
import retrofit2.http.Path
import retrofit2.http.Query

interface DutchPayApiService {
@POST("/api/dutchpay/requests")
Expand All @@ -20,4 +25,24 @@ interface DutchPayApiService {
suspend fun getDutchPayRequestDetail(
@Path("id") dutchPayId: Long
): Response<BaseResponse<DutchPayRequestDetailResponseDto>>

@GET("/api/dutchpay/requests/{id}")
suspend fun getDutchPayDetail(
@Path("id") dutchPayId: Long
): Response<BaseResponse<DutchPayDetailResponseDto>>

@POST("/api/dutchpay/requests/{dutchpayId}/pay")
suspend fun payDutchPay(
@Path("dutchpayId") dutchPayId: Long,
@Body request: DutchPayPaymentRequestDto
): Response<BaseResponse<EmptyResponse>>

@GET("/api/dutchpay/requests/summary")
suspend fun getDutchPaySummary(): Response<BaseResponse<DutchPaySummaryResponseDto>>

@GET("/api/dutchpay/requests/list")
suspend fun getDutchPayList(
@Query("tab") tab: String,
@Query("cursor") cursor: String? = null
): Response<BaseResponse<DutchPayListResponseDto>>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.ssafy.tiggle.data.model.dutchpay.request

data class DutchPayPaymentRequestDto(
val payMore: Boolean
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.ssafy.tiggle.data.model.dutchpay.response

import kotlinx.serialization.Serializable

@Serializable
data class DutchPayDetailResponseDto(
val id: Long,
val title: String,
val message: String,
val totalAmount: Int,
val status: String,
val creator: CreatorDto,
val shares: List<ShareDto>,
val roundedPerPerson: Int?,
val payMore: Boolean,
val createdAt: String
)

@Serializable
data class CreatorDto(
val id: Long,
val name: String
)

@Serializable
data class ShareDto(
val userId: Long,
val name: String,
val amount: Int,
val status: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.ssafy.tiggle.data.model.dutchpay.response

import kotlinx.serialization.Serializable

@Serializable
data class DutchPayListResponseDto(
val items: List<DutchPayItemDto>,
val nextCursor: String?,
val hasNext: Boolean
)

@Serializable
data class DutchPayItemDto(
val dutchpayId: Long,
val title: String,
val myAmount: Int,
val totalAmount: Int,
val participantCount: Int,
val paidCount: Int,
val requestedAt: String,
val isCreator: Boolean,
val creatorName: String,
val tiggleAmount: Int
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.ssafy.tiggle.data.model.dutchpay.response

import kotlinx.serialization.Serializable

@Serializable
data class DutchPaySummaryResponseDto(
val totalTransferredAmount: Int,
val transferCount: Int,
val participatedCount: Int
)
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,15 @@ package com.ssafy.tiggle.data.repository

import com.ssafy.tiggle.data.datasource.remote.DutchPayApiService
import com.ssafy.tiggle.data.model.dutchpay.request.DutchPayRequestDto
import com.ssafy.tiggle.data.model.dutchpay.request.DutchPayPaymentRequestDto
import com.ssafy.tiggle.domain.entity.dutchpay.DutchPayRequest
import com.ssafy.tiggle.domain.entity.dutchpay.DutchPayRequestDetail
import com.ssafy.tiggle.domain.entity.dutchpay.DutchPaySummary
import com.ssafy.tiggle.domain.entity.dutchpay.DutchPayList
import com.ssafy.tiggle.domain.entity.dutchpay.DutchPayItem
import com.ssafy.tiggle.domain.entity.dutchpay.DutchPayDetail
import com.ssafy.tiggle.domain.entity.dutchpay.Creator
import com.ssafy.tiggle.domain.entity.dutchpay.Share
import com.ssafy.tiggle.domain.repository.DutchPayRepository
import javax.inject.Inject
import javax.inject.Singleton
Expand Down Expand Up @@ -67,4 +74,123 @@ class DutchPayRepositoryImpl @Inject constructor(
Result.failure(e)
}
}

override suspend fun getDutchPayDetail(dutchPayId: Long): Result<DutchPayDetail> {
return try {
val response = dutchPayApiService.getDutchPayDetail(dutchPayId)

if (response.isSuccessful) {
val responseData = response.body()?.data
if (responseData != null) {
val detail = DutchPayDetail(
id = responseData.id,
title = responseData.title,
message = responseData.message,
totalAmount = responseData.totalAmount,
status = responseData.status,
creator = Creator(
id = responseData.creator.id,
name = responseData.creator.name
),
shares = responseData.shares.map { shareDto ->
Share(
userId = shareDto.userId,
name = shareDto.name,
amount = shareDto.amount,
status = shareDto.status
)
},
roundedPerPerson = responseData.roundedPerPerson,
payMore = responseData.payMore,
createdAt = responseData.createdAt
)
Result.success(detail)
} else {
Result.failure(Exception("응답 데이터가 없습니다"))
}
} else {
Result.failure(Exception("더치페이 상세 조회 실패: ${response.code()}"))
}
} catch (e: Exception) {
Result.failure(e)
}
}

override suspend fun payDutchPay(dutchPayId: Long, payMore: Boolean): Result<Unit> {
return try {
val requestDto = DutchPayPaymentRequestDto(payMore = payMore)
val response = dutchPayApiService.payDutchPay(dutchPayId, requestDto)

if (response.isSuccessful) {
Result.success(Unit)
} else {
Result.failure(Exception("송금 실패: ${response.code()}"))
}
} catch (e: Exception) {
Result.failure(e)
}
}

override suspend fun getDutchPaySummary(): Result<DutchPaySummary> {
return try {
val response = dutchPayApiService.getDutchPaySummary()

if (response.isSuccessful) {
val responseData = response.body()?.data
if (responseData != null) {
val summary = DutchPaySummary(
totalTransferredAmount = responseData.totalTransferredAmount,
transferCount = responseData.transferCount,
participatedCount = responseData.participatedCount
)
Result.success(summary)
} else {
Result.failure(Exception("응답 데이터가 없습니다"))
}
} else {
Result.failure(Exception("더치페이 현황 조회 실패: ${response.code()}"))
}
} catch (e: Exception) {
Result.failure(e)
}
}

override suspend fun getDutchPayList(tab: String, cursor: String?): Result<DutchPayList> {
return try {
val response = dutchPayApiService.getDutchPayList(tab, cursor)

if (response.isSuccessful) {
val responseData = response.body()?.data
if (responseData != null) {
val items = responseData.items.map { itemDto ->
DutchPayItem(
dutchpayId = itemDto.dutchpayId,
title = itemDto.title,
myAmount = itemDto.myAmount,
totalAmount = itemDto.totalAmount,
participantCount = itemDto.participantCount,
paidCount = itemDto.paidCount,
requestedAt = itemDto.requestedAt,
isCreator = itemDto.isCreator,
creatorName = itemDto.creatorName,
tiggleAmount = itemDto.tiggleAmount
)
}

val list = DutchPayList(
items = items,
nextCursor = responseData.nextCursor,
hasNext = responseData.hasNext
)
Result.success(list)
} else {
Result.failure(Exception("응답 데이터가 없습니다"))
}
} else {
Result.failure(Exception("더치페이 내역 조회 실패: ${response.code()}"))
}
} catch (e: Exception) {
Result.failure(e)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.ssafy.tiggle.domain.entity.dutchpay

data class DutchPayDetail(
val id: Long,
val title: String,
val message: String,
val totalAmount: Int,
val status: String,
val creator: Creator,
val shares: List<Share>,
val roundedPerPerson: Int?,
val payMore: Boolean,
val createdAt: String
)

data class Creator(
val id: Long,
val name: String
)

data class Share(
val userId: Long,
val name: String,
val amount: Int,
val status: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.ssafy.tiggle.domain.entity.dutchpay

data class DutchPayItem(
val dutchpayId: Long,
val title: String,
val myAmount: Int,
val totalAmount: Int,
val participantCount: Int,
val paidCount: Int,
val requestedAt: String,
val isCreator: Boolean,
val creatorName: String,
val tiggleAmount: Int
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.ssafy.tiggle.domain.entity.dutchpay

data class DutchPayList(
val items: List<DutchPayItem>,
val nextCursor: String?,
val hasNext: Boolean
)

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.ssafy.tiggle.domain.entity.dutchpay

data class DutchPaySummary(
val totalTransferredAmount: Int,
val transferCount: Int,
val participatedCount: Int
)
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,15 @@ package com.ssafy.tiggle.domain.repository

import com.ssafy.tiggle.domain.entity.dutchpay.DutchPayRequestDetail
import com.ssafy.tiggle.domain.entity.dutchpay.DutchPayRequest
import com.ssafy.tiggle.domain.entity.dutchpay.DutchPaySummary
import com.ssafy.tiggle.domain.entity.dutchpay.DutchPayList
import com.ssafy.tiggle.domain.entity.dutchpay.DutchPayDetail

interface DutchPayRepository {
suspend fun createDutchPayRequest(request: DutchPayRequest): Result<Unit>
suspend fun getDutchPayRequestDetail(dutchPayId: Long): Result<DutchPayRequestDetail>
suspend fun getDutchPayDetail(dutchPayId: Long): Result<DutchPayDetail>
suspend fun payDutchPay(dutchPayId: Long, payMore: Boolean): Result<Unit>
suspend fun getDutchPaySummary(): Result<DutchPaySummary>
suspend fun getDutchPayList(tab: String, cursor: String? = null): Result<DutchPayList>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.ssafy.tiggle.domain.usecase.dutchpay

import com.ssafy.tiggle.domain.entity.dutchpay.DutchPayList
import com.ssafy.tiggle.domain.repository.DutchPayRepository
import javax.inject.Inject

class GetDutchPayListUseCase @Inject constructor(
private val dutchPayRepository: DutchPayRepository
) {
suspend operator fun invoke(tab: String, cursor: String? = null): Result<DutchPayList> {
return dutchPayRepository.getDutchPayList(tab, cursor)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.ssafy.tiggle.domain.usecase.dutchpay

import com.ssafy.tiggle.domain.entity.dutchpay.DutchPaySummary
import com.ssafy.tiggle.domain.repository.DutchPayRepository
import javax.inject.Inject

class GetDutchPaySummaryUseCase @Inject constructor(
private val dutchPayRepository: DutchPayRepository
) {
suspend operator fun invoke(): Result<DutchPaySummary> {
return dutchPayRepository.getDutchPaySummary()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.ssafy.tiggle.domain.usecase.dutchpay

import com.ssafy.tiggle.domain.repository.DutchPayRepository
import javax.inject.Inject

class PayDutchPayUseCase @Inject constructor(
private val dutchPayRepository: DutchPayRepository
) {
suspend operator fun invoke(dutchPayId: Long, payMore: Boolean): Result<Unit> {
return dutchPayRepository.payDutchPay(dutchPayId, payMore)
}
}
Loading