dana-medical-site/internal/api/clinics_test.go
2026-10-14 13:33:13 +00:00

117 lines
4.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package api
import (
"net/http"
"net/http/httptest"
"reflect"
"strings"
"testing"
"time"
)
func TestClinicFrom(t *testing.T) {
if c, ok := clinicFrom(""); !ok || c.Key != clinicDANA {
t.Fatalf("пустая клиника должна быть DANA: %v %v", c, ok)
}
if c, ok := clinicFrom(" Ochevidno "); !ok || c.Key != "ochevidno" {
t.Fatalf("очевидно не распознано: %v %v", c, ok)
}
if _, ok := clinicFrom("glaz"); ok {
t.Fatal("неизвестная клиника принята")
}
}
// Портал Битрикс24 общий: один источник лида не может считаться сразу в двух клиниках,
// а каналы источников должны быть известными листами отчёта.
func TestClinicBitrixSourcesDisjoint(t *testing.T) {
owner := map[string]string{}
for _, c := range clinicList {
for src, ch := range c.bitrixSources {
if prev, dup := owner[src]; dup {
t.Errorf("источник %s есть и у %s, и у %s", src, prev, c.Key)
}
owner[src] = c.Key
if _, known := knownChannels[ch]; !known {
t.Errorf("%s: источник %s ведёт в неизвестный канал %q", c.Key, src, ch)
}
}
for src := range c.bitrixGeneral {
if prev, dup := owner[src]; dup {
t.Errorf("общий источник %s уже у %s", src, prev)
}
owner[src] = c.Key
}
}
}
func TestProdoctorovUploadPerClinic(t *testing.T) {
from := time.Date(2026, 9, 1, 0, 0, 0, 0, moscow)
to := time.Date(2026, 10, 1, 0, 0, 0, 0, moscow)
och := clinicByKey["ochevidno"]
ochFile := prodoctorovPhoneBook(t, "Офтальмологический центр «Очевидно»", "запись на приём (телефон) - сентября 2026 ",
[]string{"31", "10.09.2026 12:30", "79281230031", "нет", "500", "оплачено"})
danaFile := prodoctorovPhoneBook(t, "«Дана Медикал» на Ляхова", "запись на приём (телефон) - сентября 2026 ",
[]string{"21", "10.09.2026 12:30", "79281230021", "нет", "500", "оплачено"})
opts, err := prodoctorovUploadOptsFor(och, [][]byte{ochFile}, from, to)
if err != nil {
t.Fatalf("выгрузка «Очевидно» не принята в отчёт «Очевидно»: %v", err)
}
if got := opts.pbxLists["продокторов"]; !reflect.DeepEqual(got, []string{"9281230031"}) {
t.Fatalf("телефоны: %v", got)
}
if _, err := prodoctorovUploadOptsFor(och, [][]byte{danaFile}, from, to); err == nil ||
!strings.Contains(err.Error(), "другой клиники") || !strings.Contains(err.Error(), "«Очевидно»") {
t.Fatalf("файл DANA принят в отчёт «Очевидно»: %v", err)
}
}
func TestPBXEnvHint(t *testing.T) {
if got := pbxEnvHint(clinicDANA); got != "MEGAFON_API_URL и MEGAFON_API_KEY" {
t.Fatal(got)
}
if got := pbxEnvHint("ochevidno"); got != "OCHEVIDNO_MEGAFON_API_URL и OCHEVIDNO_MEGAFON_API_KEY" {
t.Fatal(got)
}
}
// Без токена или с коротким токеном ссылка отклоняется сразу, до обращения к базе.
func TestShareRejectsMissingToken(t *testing.T) {
a := &API{}
for _, h := range []string{"", "Bearer ", "Bearer short", "Bearer " + strings.Repeat("x", 100)} {
req := httptest.NewRequest(http.MethodGet, "/api/v1/share/weekly-reports", nil)
if h != "" {
req.Header.Set("Authorization", h)
}
rec := httptest.NewRecorder()
a.shareWeeklyReports(rec, req)
if rec.Code != http.StatusUnauthorized {
t.Fatalf("%q: код %d, ожидали 401", h, rec.Code)
}
if rec.Header().Get("Cache-Control") != "no-store" {
t.Fatalf("%q: ответ можно кешировать", h)
}
}
if shareTokenHash("a") == shareTokenHash("b") || len(shareTokenHash("a")) != 64 {
t.Fatal("хеш токена")
}
}
// Блок «Колл-ц» дашборда — совпадения колл-центра с 1С, а не вся выгрузка 1С (как в «Показателях»).
func TestWeeklyCallCenterUsesMatchedCallCenter(t *testing.T) {
sum := channelsSummary{
Totals: channelsTotals{UniqueFIO: 1021, Services: 3162, Revenue: 7997520},
Channels: []channelRow{
{Name: "Сайт", Patients: 25, Services: 33, Revenue: 215000},
{Name: knownChannels["все номера"].title, Patients: 452, Services: 1890, Revenue: 3441100, AvgCheck: 7613.05},
},
}
cc := weeklyCallCenterSales(sum)
if cc.Patients != 452 || cc.Services != 1890 || cc.Revenue != 3441100 || cc.AvgCheck != 7613.05 {
t.Fatalf("колл-центр взят не из совпадений: %+v", cc)
}
if got := weeklyCallCenterSales(channelsSummary{Totals: sum.Totals}); got.Revenue != 0 || got.Patients != 0 {
t.Fatalf("без листа колл-центра подставились итоги 1С: %+v", got)
}
}