Кабинет: операции по счетам депо и доходы с удержанным налогом из учётной системы

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
zuevav
2026-09-17 23:11:34 +03:00
parent 26785ff3ba
commit 4b18579956
7 changed files with 551 additions and 2 deletions
+91
View File
@@ -221,6 +221,34 @@ type portfolioResp struct {
Priced int `json:"priced"`
}
// operationRow — движение по счёту депо.
type operationRow struct {
Date string `json:"date"`
DoneAt string `json:"done_at"`
Kind string `json:"kind"`
Number string `json:"number"`
Account string `json:"account"`
ISIN string `json:"isin"`
Security string `json:"security"`
Quantity float64 `json:"quantity"`
State string `json:"state"`
Note string `json:"note"`
}
// incomeRow — выплата дохода.
type incomeRow struct {
Date string `json:"date"`
Kind string `json:"kind"`
ISIN string `json:"isin"`
Security string `json:"security"`
Quantity float64 `json:"quantity"`
Accrued float64 `json:"accrued"`
Tax float64 `json:"tax"`
Paid float64 `json:"paid"`
State string `json:"state"`
Account string `json:"account"`
}
// securityCard — карточка бумаги из ядра.
type securityCard struct {
ISIN string `json:"isin"`
@@ -444,6 +472,69 @@ func (s *Server) Handler() http.Handler {
s.render(w, r, "security", map[string]any{"Nav": "p", "S": out.Security, "ISIN": isin})
})
// Операции по счетам депо
mux.HandleFunc("/operations", func(w http.ResponseWriter, r *http.Request) {
sess := sessionW(w, r)
if sess == "" {
http.Redirect(w, r, "/login", http.StatusSeeOther)
return
}
from, to := r.URL.Query().Get("from"), r.URL.Query().Get("to")
if from == "" {
from = time.Now().AddDate(-1, 0, 0).Format("2006-01-02")
}
if to == "" {
to = time.Now().Format("2006-01-02")
}
var out struct {
Operations []operationRow `json:"operations"`
}
path := "/api/lk/operations?from=" + url.QueryEscape(from) + "&to=" + url.QueryEscape(to)
if err := bj.call(r.Context(), http.MethodGet, path, sess, nil, &out); err != nil {
s.render(w, r, "operations", map[string]any{"Nav": "o", "Error": err.Error(), "From": from, "To": to})
return
}
var in, outq int
for _, o := range out.Operations {
if o.Quantity < 0 {
outq++
} else {
in++
}
}
s.render(w, r, "operations", map[string]any{"Nav": "o", "Operations": out.Operations,
"From": from, "To": to, "Total": len(out.Operations), "In": in, "Out": outq})
})
// Доходы и налоги
mux.HandleFunc("/income", func(w http.ResponseWriter, r *http.Request) {
sess := sessionW(w, r)
if sess == "" {
http.Redirect(w, r, "/login", http.StatusSeeOther)
return
}
from, to := r.URL.Query().Get("from"), r.URL.Query().Get("to")
if from == "" {
from = time.Now().Format("2006") + "-01-01"
}
if to == "" {
to = time.Now().Format("2006-01-02")
}
var out struct {
Income []incomeRow `json:"income"`
Accrued float64 `json:"accrued"`
Paid float64 `json:"paid"`
Tax float64 `json:"tax"`
}
path := "/api/lk/income?from=" + url.QueryEscape(from) + "&to=" + url.QueryEscape(to)
if err := bj.call(r.Context(), http.MethodGet, path, sess, nil, &out); err != nil {
s.render(w, r, "income", map[string]any{"Nav": "i", "Error": err.Error(), "From": from, "To": to})
return
}
s.render(w, r, "income", map[string]any{"Nav": "i", "Income": out.Income, "From": from, "To": to,
"Accrued": out.Accrued, "Paid": out.Paid, "Tax": out.Tax})
})
// Профиль: договор, счета депо, доступ
mux.HandleFunc("/profile", func(w http.ResponseWriter, r *http.Request) {
sess := sessionW(w, r)