first commit
This commit is contained in:
186
handlers/order_handler.go
Normal file
186
handlers/order_handler.go
Normal 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)
|
||||
}
|
||||
Reference in New Issue
Block a user