first commit

This commit is contained in:
hayato5246
2026-03-31 19:32:59 +09:00
commit d10b794c9f
78 changed files with 1671595 additions and 0 deletions

186
handlers/order_handler.go Normal file
View File

@@ -0,0 +1,186 @@
package handlers
import (
"encoding/json"
"net/http"
"stocksearch/services"
)
// OrderHandler 주문/계좌 REST API 핸들러
type OrderHandler struct {
orderSvc *services.OrderService
accountSvc *services.AccountService
}
// NewOrderHandler 핸들러 초기화
func NewOrderHandler() *OrderHandler {
return &OrderHandler{
orderSvc: services.GetOrderService(),
accountSvc: services.GetAccountService(),
}
}
// Buy POST /api/order/buy — 매수주문 (kt10000)
func (h *OrderHandler) Buy(w http.ResponseWriter, r *http.Request) {
var req services.OrderRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
jsonError(w, "요청 파싱 실패", http.StatusBadRequest)
return
}
if req.Exchange == "" {
req.Exchange = "KRX"
}
if req.TradeTP == "" {
req.TradeTP = "0"
}
result, err := h.orderSvc.Buy(req)
if err != nil {
jsonError(w, err.Error(), http.StatusInternalServerError)
return
}
jsonOK(w, result)
}
// Sell POST /api/order/sell — 매도주문 (kt10001)
func (h *OrderHandler) Sell(w http.ResponseWriter, r *http.Request) {
var req services.OrderRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
jsonError(w, "요청 파싱 실패", http.StatusBadRequest)
return
}
if req.Exchange == "" {
req.Exchange = "KRX"
}
if req.TradeTP == "" {
req.TradeTP = "0"
}
result, err := h.orderSvc.Sell(req)
if err != nil {
jsonError(w, err.Error(), http.StatusInternalServerError)
return
}
jsonOK(w, result)
}
// Modify PUT /api/order/modify — 정정주문 (kt10002)
func (h *OrderHandler) Modify(w http.ResponseWriter, r *http.Request) {
var req struct {
Exchange string `json:"exchange"`
OrigOrdNo string `json:"origOrdNo"`
Code string `json:"code"`
Qty string `json:"qty"`
Price string `json:"price"`
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
jsonError(w, "요청 파싱 실패", http.StatusBadRequest)
return
}
if req.Exchange == "" {
req.Exchange = "KRX"
}
result, err := h.orderSvc.Modify(req.Exchange, req.OrigOrdNo, req.Code, req.Qty, req.Price)
if err != nil {
jsonError(w, err.Error(), http.StatusInternalServerError)
return
}
jsonOK(w, result)
}
// Cancel DELETE /api/order — 취소주문 (kt10003)
func (h *OrderHandler) Cancel(w http.ResponseWriter, r *http.Request) {
var req struct {
Exchange string `json:"exchange"`
OrigOrdNo string `json:"origOrdNo"`
Code string `json:"code"`
Qty string `json:"qty"`
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
jsonError(w, "요청 파싱 실패", http.StatusBadRequest)
return
}
if req.Exchange == "" {
req.Exchange = "KRX"
}
if req.Qty == "" {
req.Qty = "0" // 전량취소
}
result, err := h.orderSvc.Cancel(req.Exchange, req.OrigOrdNo, req.Code, req.Qty)
if err != nil {
jsonError(w, err.Error(), http.StatusInternalServerError)
return
}
jsonOK(w, result)
}
// GetBalance GET /api/account/balance — 계좌 잔고 (kt00018)
func (h *OrderHandler) GetBalance(w http.ResponseWriter, r *http.Request) {
result, err := h.accountSvc.GetBalance()
if err != nil {
jsonError(w, err.Error(), http.StatusInternalServerError)
return
}
jsonOK(w, result)
}
// GetPending GET /api/account/pending — 미체결 주문 (ka10075)
func (h *OrderHandler) GetPending(w http.ResponseWriter, r *http.Request) {
orders, err := h.accountSvc.GetPendingOrders()
if err != nil {
jsonError(w, err.Error(), http.StatusInternalServerError)
return
}
if orders == nil {
orders = []services.PendingOrder{}
}
jsonOK(w, orders)
}
// GetHistory GET /api/account/history — 체결내역 (ka10076)
func (h *OrderHandler) GetHistory(w http.ResponseWriter, r *http.Request) {
history, err := h.accountSvc.GetOrderHistory()
if err != nil {
jsonError(w, err.Error(), http.StatusInternalServerError)
return
}
if history == nil {
history = []services.OrderHistory{}
}
jsonOK(w, history)
}
// GetDeposit GET /api/account/deposit — 예수금 상세 조회 (kt00001)
func (h *OrderHandler) GetDeposit(w http.ResponseWriter, r *http.Request) {
result, err := h.accountSvc.GetDepositDetail()
if err != nil {
jsonError(w, err.Error(), http.StatusInternalServerError)
return
}
jsonOK(w, result)
}
// GetOrderable GET /api/account/orderable?code=&price=&side= — 주문가능금액/수량 (kt00010)
func (h *OrderHandler) GetOrderable(w http.ResponseWriter, r *http.Request) {
code := r.URL.Query().Get("code")
price := r.URL.Query().Get("price")
side := r.URL.Query().Get("side") // buy 또는 sell
if price == "" {
price = "0"
}
// 키움 API: 1=매도, 2=매수
tradeTp := "2"
if side == "sell" {
tradeTp = "1"
}
result, err := h.accountSvc.GetOrderable(code, price, tradeTp)
if err != nil {
jsonError(w, err.Error(), http.StatusInternalServerError)
return
}
jsonOK(w, result)
}