From 4e90b15a95facddd7da65c3536976d78e8972c4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9?= Date: Sun, 12 Jul 2026 07:56:06 +0300 Subject: [PATCH] =?UTF-8?q?feat(sales-finder):=20=D1=80=D0=B0=D0=BD=D0=B3?= =?UTF-8?q?=20=D0=B3=D0=BE=D1=80=D1=8F=D1=87=D0=B5=D1=81=D1=82=D0=B8=20?= =?UTF-8?q?=D0=B8=D0=B7=20=D1=82=D1=80=D1=91=D1=85=20=D1=81=D0=B8=D0=B3?= =?UTF-8?q?=D0=BD=D0=B0=D0=BB=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- моя/sales-finder/salesfinder/ranker.py | 20 ++++++++++++++++++++ моя/sales-finder/tests/test_ranker.py | 15 +++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 моя/sales-finder/salesfinder/ranker.py create mode 100644 моя/sales-finder/tests/test_ranker.py diff --git a/моя/sales-finder/salesfinder/ranker.py b/моя/sales-finder/salesfinder/ranker.py new file mode 100644 index 00000000..ecf9c116 --- /dev/null +++ b/моя/sales-finder/salesfinder/ranker.py @@ -0,0 +1,20 @@ +"""«Горячесть» фирмы = взвешенная сумма сигналов рекламы. Больше сигналов и «крутит сейчас» +(бюджет Директа) → выше. Deterministic, легко тестируется.""" + +def score(f) -> int: + s = 0 + if f.advertises == "да": + s += 40 + s += {"высокая": 30, "средняя": 15, "низкая": 0}.get(f.confidence, 0) + if f.two_gis_promoted: + s += 20 + if f.direct_budget > 0: + s += min(30, f.direct_budget // 5000) # до +30 за бюджет Директа + if f.legal_status and f.legal_status != "действующая": + s -= 25 # мёртвых вниз + return s + +def rank(firms: list) -> list: + for f in firms: + f.hotness = score(f) + return sorted(firms, key=lambda x: -x.hotness) diff --git a/моя/sales-finder/tests/test_ranker.py b/моя/sales-finder/tests/test_ranker.py new file mode 100644 index 00000000..076de262 --- /dev/null +++ b/моя/sales-finder/tests/test_ranker.py @@ -0,0 +1,15 @@ +from salesfinder.models import Firm +from salesfinder.ranker import score, rank + +def test_more_signals_more_hotness(): + hot = Firm(name="H", domain="h.ru", two_gis_promoted=True, + advertises="да", confidence="высокая", direct_budget=50000) + cold = Firm(name="C", domain="c.ru", advertises="нет", confidence="низкая") + assert score(hot) > score(cold) + +def test_rank_sorts_desc_and_sets_field(): + a = Firm(name="A", domain="a.ru", advertises="нет") + b = Firm(name="B", domain="b.ru", advertises="да", confidence="высокая", two_gis_promoted=True) + out = rank([a, b]) + assert out[0].name == "B" + assert out[0].hotness > 0