Кабинет: курсы ЦБ, история стоимости портфеля, быстрые операции, контакты в профиле
Курсы валют. Оценивать замещающие и еврооблигации по курсу из копии учётной системы было нельзя: в DEPO он от 31.05.2026, в SPECTRE — от 18.07.2026. Берём официальный курс Банка России (открытый XML, без ключа — тем же каналом пользуется Инвест-хаб) и складываем по дням в lk.fx_rates: без интернета кабинет считает по последнему известному курсу, а не отказывается оценивать. Источник переключается в настройках («Данные кабинета»), там же кнопка «Обновить курсы сейчас». Портфель БР-719: 560,3 млн ₽ против 522 млн по старому курсу. История стоимости. Ни QUIK, ни SPECTRE её не хранят, поэтому раз в день после закрытия торгов считаем стоимость каждого портфеля по экспорту QUIK и пишем строку в lk.portfolio_daily (257 портфелей за 14 секунд). Кабинет рисует по ним график на странице портфеля — SVG собирается на сервере, скриптов в кабинете по-прежнему нет. Режим по умолчанию — «автоматически»: ведём, если настроен экспорт QUIK, потому что задним числом историю не восстановить. Операции. Связка «JOIN OD_RESTS ON sr.ID = CASE WHEN w.D_REST IN (…)» заставляла SQL Server разбирать список счетов на каждой строке журнала проводок: год данных читался 6–7 секунд. Обе стороны проводки выбираются заранее двумя ветвями UNION ALL, индексы IX_WIRING_D_REST_WIRDATE и IX_WIRING_K_REST_WIRDATE отрабатывают поиском — 89 мс на тех же 64 строках. Период по умолчанию вернули к году, ответ кэшируется на пять минут. Профиль: почта, телефон и прошлый вход из анкеты — клиент видит, куда с ним свяжется депозитарий, и заметит устаревшие данные. Правка только через менеджера. Заказ документов из кабинета убран совсем (форма была убрана раньше, теперь нет и обработчика). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q4YVo4UMopqT5DzicqpPjL
This commit is contained in:
@@ -29,8 +29,35 @@ var fxCache = struct {
|
||||
m map[string]LKFxRate
|
||||
}{}
|
||||
|
||||
// lkFxRates — курсы валют (ключ — код валюты в верхнем регистре), кэш на час.
|
||||
func lkFxRates(ctx context.Context, s FancyMSSQLSettings) map[string]LKFxRate {
|
||||
// lkFxRates — курсы валют для оценки (ключ — код валюты в верхнем регистре).
|
||||
// Источник по умолчанию — Банк России (см. cbrfx.go); если интернета нет или
|
||||
// в настройках выбрана учётная система, берём OD_VALUES_RATES, а недостающие
|
||||
// валюты дополняем последним известным курсом из lk.fx_rates.
|
||||
func lkFxRates(ctx context.Context, rc *RuntimeConfig) map[string]LKFxRate {
|
||||
set := rc.Snapshot()
|
||||
out := map[string]LKFxRate{}
|
||||
if !strings.EqualFold(strings.TrimSpace(set.LK.FXSource), "accounting") {
|
||||
if cbr, cerr := cbrToday(ctx, rc); len(cbr) > 0 {
|
||||
return cbr
|
||||
} else if cerr != "" {
|
||||
// молча уходим на запасные источники: кабинет не должен падать
|
||||
// из-за недоступного сайта ЦБ
|
||||
_ = cerr
|
||||
}
|
||||
}
|
||||
for code, r := range lkFxAccounting(ctx, set.Fancy) {
|
||||
out[code] = r
|
||||
}
|
||||
for code, r := range lkFxLoad(ctx, rc, time.Time{}) {
|
||||
if old, ok := out[code]; !ok || r.At.After(old.At) {
|
||||
out[code] = r
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// lkFxAccounting — курсы из учётной системы (OD_VALUES_RATES, MARKET = 0), кэш на час.
|
||||
func lkFxAccounting(ctx context.Context, s FancyMSSQLSettings) map[string]LKFxRate {
|
||||
fxCache.mu.Lock()
|
||||
if fxCache.m != nil && time.Since(fxCache.at) < time.Hour {
|
||||
m := fxCache.m
|
||||
@@ -89,3 +116,13 @@ func lkFxFor(rates map[string]LKFxRate, cur string) LKFxRate {
|
||||
}
|
||||
return rates[c]
|
||||
}
|
||||
|
||||
// lkFxReset — сбросить кэши курсов (после смены источника или ручного обновления).
|
||||
func lkFxReset() {
|
||||
fxCache.mu.Lock()
|
||||
fxCache.m, fxCache.at = nil, time.Time{}
|
||||
fxCache.mu.Unlock()
|
||||
cbrCache.mu.Lock()
|
||||
cbrCache.at, cbrCache.err = time.Time{}, ""
|
||||
cbrCache.mu.Unlock()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user