2026-01-14 15:42:26 +09:00
|
|
|
// src/main/kotlin/ui/AutoTradeSection.kt (신규 파일)
|
|
|
|
|
package ui
|
|
|
|
|
|
|
|
|
|
import AutoTradeItem
|
|
|
|
|
import androidx.compose.foundation.clickable
|
|
|
|
|
import androidx.compose.foundation.layout.*
|
|
|
|
|
import androidx.compose.foundation.lazy.LazyColumn
|
|
|
|
|
import androidx.compose.foundation.lazy.items
|
|
|
|
|
import androidx.compose.material.*
|
|
|
|
|
import androidx.compose.material.icons.filled.Refresh
|
|
|
|
|
import androidx.compose.runtime.*
|
|
|
|
|
import androidx.compose.ui.Alignment
|
|
|
|
|
import androidx.compose.ui.Modifier
|
|
|
|
|
import androidx.compose.ui.graphics.Color
|
|
|
|
|
import androidx.compose.ui.text.font.FontWeight
|
|
|
|
|
import androidx.compose.ui.unit.dp
|
|
|
|
|
import androidx.compose.ui.unit.sp
|
2026-01-19 17:09:37 +09:00
|
|
|
import model.toAutoTradeItem
|
2026-01-14 15:42:26 +09:00
|
|
|
import network.KisTradeService
|
|
|
|
|
|
|
|
|
|
// src/main/kotlin/ui/AutoTradeSection.kt
|
|
|
|
|
|
|
|
|
|
@Composable
|
|
|
|
|
fun AutoTradeSection(
|
2026-01-19 17:09:37 +09:00
|
|
|
isDomestic: Boolean,
|
2026-01-14 15:42:26 +09:00
|
|
|
tradeService: KisTradeService,
|
|
|
|
|
refreshTrigger: Int, // 갱신 트리거 추가
|
|
|
|
|
onRefresh: () -> Unit,
|
2026-01-19 17:09:37 +09:00
|
|
|
onItemSelect: (AutoTradeItem) -> Unit,
|
|
|
|
|
onItemCancel: (AutoTradeItem) -> Unit
|
2026-01-14 15:42:26 +09:00
|
|
|
) {
|
|
|
|
|
// 통합 리스트 상태 (ActiveTradeItem은 이전에 정의한 통합 모델)
|
2026-01-19 17:09:37 +09:00
|
|
|
var tradeList by remember { mutableStateOf(emptyList<AutoTradeItem>()) }
|
2026-01-14 15:42:26 +09:00
|
|
|
// refreshTrigger가 바뀔 때마다 실행됨
|
|
|
|
|
LaunchedEffect(refreshTrigger) {
|
2026-01-20 15:13:50 +09:00
|
|
|
// 1. 서버에서 실제 미체결 내역 가져오기
|
2026-01-19 17:09:37 +09:00
|
|
|
val serverUnfilled = tradeService.fetchUnfilledOrders().getOrNull()?.map { it.toAutoTradeItem(isDomestic) } ?: emptyList()
|
2026-01-14 15:42:26 +09:00
|
|
|
|
2026-01-19 17:09:37 +09:00
|
|
|
// 2. DB에서 로컬 감시 데이터 가져오기
|
|
|
|
|
val localTrades = DatabaseFactory.getActiveAutoTrades()
|
2026-01-14 15:42:26 +09:00
|
|
|
|
2026-01-20 15:13:50 +09:00
|
|
|
// 3. 리스트 병합 및 동기화
|
|
|
|
|
val mergedList = mutableListOf<AutoTradeItem>()
|
|
|
|
|
|
|
|
|
|
// (A) DB에 있는 항목 처리
|
|
|
|
|
localTrades.forEach { local ->
|
|
|
|
|
val serverMatch = serverUnfilled.find { it.orderNo == local.orderNo }
|
|
|
|
|
if (local.status != "COMPLETED" && serverMatch == null) {
|
|
|
|
|
// 서버에 없으면 만료 처리
|
|
|
|
|
mergedList.add(local.copy(status = "EXPIRED"))
|
|
|
|
|
} else {
|
|
|
|
|
// 서버에 있으면 그대로 표시 (필요시 잔량 등 업데이트)
|
|
|
|
|
mergedList.add(local.copy(remainedQuantity = serverMatch?.remainedQuantity ?: 0))
|
|
|
|
|
}
|
2026-01-19 17:09:37 +09:00
|
|
|
}
|
2026-01-20 15:13:50 +09:00
|
|
|
|
|
|
|
|
// (B) 서버에는 있지만 DB에는 없는 항목(수동 주문 등) 추가
|
|
|
|
|
val manualOrders = serverUnfilled.filter { server -> localTrades.none { it.orderNo == server.orderNo } }
|
|
|
|
|
mergedList.addAll(manualOrders.map { it.copy(status = "MANUAL_ORDER") }) // 수동 주문 상태 등으로 표시
|
|
|
|
|
|
|
|
|
|
tradeList = mergedList
|
2026-01-14 15:42:26 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Column(modifier = Modifier.fillMaxSize().padding(8.dp)) {
|
|
|
|
|
Row(
|
|
|
|
|
modifier = Modifier.fillMaxWidth(),
|
|
|
|
|
horizontalArrangement = Arrangement.SpaceBetween,
|
|
|
|
|
verticalAlignment = Alignment.CenterVertically
|
|
|
|
|
) {
|
|
|
|
|
Text("진행 중인 거래", style = MaterialTheme.typography.subtitle1, fontWeight = FontWeight.Bold)
|
|
|
|
|
|
|
|
|
|
// 강제 갱신 버튼
|
|
|
|
|
IconButton(
|
|
|
|
|
onClick = onRefresh,
|
|
|
|
|
modifier = Modifier.size(24.dp)
|
|
|
|
|
) {
|
|
|
|
|
Icon(
|
|
|
|
|
imageVector = androidx.compose.material.icons.Icons.Default.Refresh,
|
|
|
|
|
contentDescription = "새로고침",
|
|
|
|
|
tint = Color(0xFF0E62CF),
|
|
|
|
|
modifier = Modifier.size(18.dp)
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
LazyColumn {
|
2026-01-19 17:09:37 +09:00
|
|
|
items(tradeList) { item ->
|
2026-01-14 15:42:26 +09:00
|
|
|
ActiveTradeRow(
|
|
|
|
|
item = item,
|
2026-01-19 17:09:37 +09:00
|
|
|
onCancelClick = { onItemCancel(item) }, // 이미 스코프에 있는 item을 그대로 사용
|
|
|
|
|
onClick = { onItemSelect(item) }
|
2026-01-14 15:42:26 +09:00
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|