feat(1c): derive company activity from file-base telemetry
This commit is contained in:
@@ -146,8 +146,8 @@ def company_summary(counterparty: str, infobase: str | None = None) -> dict[str,
|
||||
signals = rows_to_dict(client.query(signals_sql))
|
||||
timeline = rows_to_dict(client.query(timeline_sql))
|
||||
essence = (
|
||||
f"Компания {counterparty}: за 30 дней документов {card['docs_30d']}, объём {card['amount_30d']}, "
|
||||
f"прогноз на 30 дней {card['amount_forecast_30d']}, риск {card['signal_severity']}."
|
||||
f"Компания {counterparty}: за 30 дней событий {card['docs_30d']}, суммарная активность {card['amount_30d']}, "
|
||||
f"прогноз активности на 30 дней {card['amount_forecast_30d']}, риск {card['signal_severity']}."
|
||||
)
|
||||
return {
|
||||
"essence": essence,
|
||||
|
||||
@@ -218,7 +218,7 @@ def main() -> int:
|
||||
if days_since_last_activity >= 14 and (docs_prev_7d > 0 or amount_prev_7d > 0):
|
||||
signals.append(("inactive_company", 85, "high", f"Нет активности по компании {counterparty} уже {days_since_last_activity} дн."))
|
||||
if amount_prev_7d > 0 and amount_7d < amount_prev_7d * 0.5:
|
||||
signals.append(("amount_drop", 70, "high", f"Объём по компании {counterparty} упал более чем на 50% неделя к неделе."))
|
||||
signals.append(("amount_drop", 70, "high", f"Активность по компании {counterparty} упала более чем на 50% неделя к неделе."))
|
||||
if docs_prev_7d > 0 and docs_7d == 0:
|
||||
signals.append(("docs_stopped", 55, "medium", f"По компании {counterparty} прекратился поток документов за последние 7 дней."))
|
||||
if open_cases_total > 0:
|
||||
|
||||
@@ -11,12 +11,32 @@ FROM (
|
||||
concat('document:', doc_type) AS event_type,
|
||||
if(posted = 1, 'low', 'medium') AS severity,
|
||||
if(posted = 1, 5, 20) AS score,
|
||||
doc_id AS ref_id,
|
||||
concat(doc_id, ':', toString(toUnixTimestamp(ts)), ':', doc_type) AS ref_id,
|
||||
concat('Документ ', doc_type, ' №', doc_number, ' статус=', status) AS summary
|
||||
FROM analytics_1c.documents
|
||||
) AS src
|
||||
WHERE src.ref_id NOT IN (SELECT ref_id FROM analytics_1c.entity_timeline);
|
||||
|
||||
INSERT INTO analytics_1c.entity_timeline
|
||||
SELECT *
|
||||
FROM (
|
||||
SELECT
|
||||
ts,
|
||||
'counterparty' AS entity_type,
|
||||
counterparty AS entity_id,
|
||||
infobase,
|
||||
author AS actor,
|
||||
'documents' AS source,
|
||||
concat('counterparty:', operation_type) AS event_type,
|
||||
if(status = 'busy', 'medium', 'low') AS severity,
|
||||
greatest(10, toUInt32(round(amount))) AS score,
|
||||
concat('counterparty:', counterparty, ':', doc_id, ':', toString(toUnixTimestamp(ts))) AS ref_id,
|
||||
concat('Активность компании ', counterparty, ': ', doc_type, ' score=', toString(amount), ' status=', status) AS summary
|
||||
FROM analytics_1c.documents
|
||||
WHERE counterparty != ''
|
||||
) AS src
|
||||
WHERE src.ref_id NOT IN (SELECT ref_id FROM analytics_1c.entity_timeline);
|
||||
|
||||
INSERT INTO analytics_1c.entity_timeline
|
||||
SELECT *
|
||||
FROM (
|
||||
|
||||
@@ -19,6 +19,26 @@ FROM (
|
||||
) AS src
|
||||
WHERE src.detection_id NOT IN (SELECT detection_id FROM analytics_1c.detections);
|
||||
|
||||
INSERT INTO analytics_1c.detections
|
||||
SELECT *
|
||||
FROM (
|
||||
SELECT
|
||||
generated_at AS ts,
|
||||
concat('company_signal:', signal_id, ':', toString(toUnixTimestamp(generated_at))) AS detection_id,
|
||||
infobase,
|
||||
concat('company_', signal_type) AS rule_id,
|
||||
'Сигнал активности компании' AS rule_title,
|
||||
'counterparty' AS entity_type,
|
||||
counterparty AS entity_id,
|
||||
severity,
|
||||
score,
|
||||
summary,
|
||||
'open' AS status
|
||||
FROM analytics_1c.v_company_health_current
|
||||
WHERE severity IN ('medium', 'high', 'critical')
|
||||
) AS src
|
||||
WHERE src.detection_id NOT IN (SELECT detection_id FROM analytics_1c.detections);
|
||||
|
||||
INSERT INTO analytics_1c.detections
|
||||
SELECT *
|
||||
FROM (
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"title": "Прогноз объёма 30д",
|
||||
"title": "Прогноз активности 30д",
|
||||
"type": "stat",
|
||||
"datasource": {
|
||||
"type": "grafana-clickhouse-datasource",
|
||||
@@ -235,7 +235,7 @@
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"title": "Объём по компаниям",
|
||||
"title": "Активность по компаниям",
|
||||
"type": "timeseries",
|
||||
"datasource": {
|
||||
"type": "grafana-clickhouse-datasource",
|
||||
@@ -282,7 +282,7 @@
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"title": "Количество документов по компаниям",
|
||||
"title": "Количество событий по компаниям",
|
||||
"type": "timeseries",
|
||||
"datasource": {
|
||||
"type": "grafana-clickhouse-datasource",
|
||||
|
||||
@@ -45,6 +45,14 @@ docker exec -i "${CH_CONTAINER}" clickhouse-client \
|
||||
--database "${CLICKHOUSE_DB}" \
|
||||
< "${ROOT}/detections/build_entity_timeline.sql"
|
||||
|
||||
docker exec -i "${CH_CONTAINER}" clickhouse-client \
|
||||
--user "${CLICKHOUSE_USER}" \
|
||||
--password "${CLICKHOUSE_PASSWORD}" \
|
||||
--database "${CLICKHOUSE_DB}" \
|
||||
< "${ROOT}/clickhouse/init/04_company_intelligence.sql"
|
||||
|
||||
"${ROOT}/ops/run_company_intelligence_refresh.sh"
|
||||
|
||||
docker exec -i "${CH_CONTAINER}" clickhouse-client \
|
||||
--user "${CLICKHOUSE_USER}" \
|
||||
--password "${CLICKHOUSE_PASSWORD}" \
|
||||
@@ -56,11 +64,3 @@ docker exec -i "${CH_CONTAINER}" clickhouse-client \
|
||||
--password "${CLICKHOUSE_PASSWORD}" \
|
||||
--database "${CLICKHOUSE_DB}" \
|
||||
< "${ROOT}/detections/open_cases_from_detections.sql"
|
||||
|
||||
docker exec -i "${CH_CONTAINER}" clickhouse-client \
|
||||
--user "${CLICKHOUSE_USER}" \
|
||||
--password "${CLICKHOUSE_PASSWORD}" \
|
||||
--database "${CLICKHOUSE_DB}" \
|
||||
< "${ROOT}/clickhouse/init/04_company_intelligence.sql"
|
||||
|
||||
"${ROOT}/ops/run_company_intelligence_refresh.sh"
|
||||
|
||||
Reference in New Issue
Block a user