fix(1c): harden company telemetry rollout
This commit is contained in:
@@ -108,7 +108,11 @@
|
||||
$existingTask = Get-ScheduledTask -TaskName $taskName -ErrorAction SilentlyContinue
|
||||
if ($existingTask) {
|
||||
$action = New-ScheduledTaskAction -Execute $powerShellExe -Argument "-NoProfile -ExecutionPolicy Bypass -File `"{{ aw_windows_state_root }}\export-upload-file-1c-telemetry.ps1`" -ConfigPath `"{{ aw_windows_state_root }}\deployment-config.json`""
|
||||
Set-ScheduledTask -TaskName $taskName -Action $action | Out-Null
|
||||
try {
|
||||
Set-ScheduledTask -TaskName $taskName -Action $action -ErrorAction Stop | Out-Null
|
||||
} catch {
|
||||
Write-Host "skip task action update for $taskName because the existing principal requires stored credentials: $($_.Exception.Message)"
|
||||
}
|
||||
} else {
|
||||
& schtasks.exe /Create /TN $taskName /TR $taskCommand /SC HOURLY /MO {{ aw_windows_file_1c_auto_upload_interval_hours | int }} /ST 00:00 /RU SYSTEM /RL HIGHEST /F | Out-Null
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
|
||||
@@ -131,6 +131,7 @@ python ai/company_intelligence_api.py --host 127.0.0.1 --port 8710
|
||||
|
||||
- выгрузки 1С по документам;
|
||||
- выгрузки движений/проводок;
|
||||
- read-only `companies` snapshot по файловым базам;
|
||||
- журнал регистрации 1С;
|
||||
- audit/export критичных изменений;
|
||||
- host telemetry с Windows/RDP host.
|
||||
@@ -138,6 +139,18 @@ python ai/company_intelligence_api.py --host 127.0.0.1 --port 8710
|
||||
наполняется read-only telemetry слоем как `counterparty = infobase`, а
|
||||
`amount` используется как интегральный `activity score`.
|
||||
|
||||
Отдельно:
|
||||
|
||||
- `companies` хранит текущую карту файловых баз:
|
||||
- `owner_user`
|
||||
- `base_path`
|
||||
- `db_size_bytes`
|
||||
- `reglog_size_bytes`
|
||||
- `active_locks`
|
||||
- `temp_db_present`
|
||||
- `scheduler_touched`
|
||||
- `activity_score`
|
||||
|
||||
## Границы
|
||||
|
||||
- AI Investigator не пишет в 1С;
|
||||
|
||||
@@ -122,7 +122,7 @@ def company_summary(counterparty: str, infobase: str | None = None) -> dict[str,
|
||||
SELECT *
|
||||
FROM analytics_1c.v_company_portfolio_overview
|
||||
WHERE {' AND '.join(filters)}
|
||||
ORDER BY amount_30d DESC
|
||||
ORDER BY last_company_snapshot_at DESC, amount_30d DESC
|
||||
LIMIT 1
|
||||
"""
|
||||
rows = rows_to_dict(client.query(sql))
|
||||
@@ -144,10 +144,11 @@ def company_summary(counterparty: str, infobase: str | None = None) -> dict[str,
|
||||
ORDER BY score DESC, generated_at DESC
|
||||
"""
|
||||
timeline_sql = f"""
|
||||
SELECT ts, infobase, company_name, owner_user, current_status, db_size_bytes, reglog_size_bytes, active_locks, current_activity_score
|
||||
SELECT last_company_snapshot_at AS ts, infobase, company_name, owner_user, current_status, db_size_bytes, reglog_size_bytes, active_locks, current_activity_score
|
||||
FROM analytics_1c.v_company_portfolio_overview
|
||||
WHERE counterparty = {q(counterparty)}
|
||||
{"AND infobase = " + q(infobase) if infobase else ""}
|
||||
ORDER BY ts DESC
|
||||
LIMIT 1
|
||||
"""
|
||||
forecasts = rows_to_dict(client.query(forecast_sql))
|
||||
|
||||
@@ -12,7 +12,19 @@
|
||||
## Что считается компанией
|
||||
|
||||
В file-based Detmir контуре компания = `documents.counterparty`, но это поле
|
||||
заполняется **не из бухгалтерских проводок**, а из read-only file-base telemetry:
|
||||
заполняется **не из бухгалтерских проводок**, а из read-only file-base telemetry.
|
||||
|
||||
Сейчас есть два связанных слоя:
|
||||
|
||||
- `documents`
|
||||
- событийный слой;
|
||||
- содержит `CompanyActivitySnapshot`;
|
||||
- `companies`
|
||||
- отдельная read-only business-like таблица по каждой файловой базе;
|
||||
- хранит `owner_user`, `base_path`, `db_size_bytes`, `reglog_size_bytes`,
|
||||
`active_locks`, `temp_db_present`, `scheduler_touched`, `activity_score`.
|
||||
|
||||
Для `documents` действует telemetry-модель:
|
||||
|
||||
- `counterparty = infobase`;
|
||||
- `doc_type = CompanyActivitySnapshot`;
|
||||
@@ -32,6 +44,7 @@
|
||||
|
||||
Создаёт:
|
||||
|
||||
- `v_companies_current`
|
||||
- `company_forecasts`
|
||||
- `company_health_signals`
|
||||
- `v_counterparty_daily`
|
||||
@@ -49,12 +62,15 @@
|
||||
Что делает:
|
||||
|
||||
- строит daily series по `counterparty`;
|
||||
- учитывает текущее состояние файловой базы из `companies`;
|
||||
- считает базовую линию и линейный тренд;
|
||||
- материализует прогнозы на `7` и `30` дней;
|
||||
- создаёт health-signals:
|
||||
- `inactive_company`
|
||||
- `amount_drop`
|
||||
- `docs_stopped`
|
||||
- `base_busy`
|
||||
- `scheduler_activity`
|
||||
- `open_cases`
|
||||
- `open_detections`
|
||||
|
||||
@@ -136,6 +152,20 @@ clickhouse-client --queries-file clickhouse/init/04_company_intelligence.sql
|
||||
- `AW_1C_COMPANY_MIN_DAYS`
|
||||
- `AW_1C_COMPANY_HORIZONS`
|
||||
|
||||
## Что уже есть в live payload
|
||||
|
||||
В live `overview/summary` теперь идут не только прогнозы, но и текущее
|
||||
состояние файловой базы компании:
|
||||
|
||||
- `company_name`
|
||||
- `owner_user`
|
||||
- `base_path`
|
||||
- `current_status`
|
||||
- `db_size_bytes`
|
||||
- `reglog_size_bytes`
|
||||
- `active_locks`
|
||||
- `current_activity_score`
|
||||
|
||||
## Что прогноз реально означает
|
||||
|
||||
Это не black-box ML и не «магический AI».
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
Слой `1C Company Intelligence` расширяет `File 1C analytics` и добавляет:
|
||||
|
||||
- mart по `counterparty`;
|
||||
- отдельный read-only dataset/table `companies`;
|
||||
- прогноз по документам и объёму на `7/30` дней;
|
||||
- health-signals по компаниям;
|
||||
- read-only API для AI Investigator;
|
||||
@@ -14,4 +15,6 @@
|
||||
|
||||
Ключевая граница:
|
||||
|
||||
- `counterparty` в file-based Detmir контуре по-прежнему telemetry-derived;
|
||||
- `companies` даёт текущий срез базы: owner/path/size/locks/activity;
|
||||
- если `counterparty` в live-выгрузках пустой, слой остаётся пустым честно и ничего не симулирует.
|
||||
|
||||
@@ -57,7 +57,10 @@ function Get-1CFileInfobases {
|
||||
Where-Object { Test-Path -LiteralPath $_ }
|
||||
|
||||
foreach ($file in $launcherFiles) {
|
||||
$userName = Split-Path -Leaf (Split-Path -Parent (Split-Path -Parent (Split-Path -Parent (Split-Path -Parent $file))))
|
||||
$userName = 'unknown'
|
||||
if ([string]$file -match '^[A-Za-z]:\\Users\\([^\\]+)\\') {
|
||||
$userName = [string]$Matches[1]
|
||||
}
|
||||
$currentName = $null
|
||||
$currentId = $null
|
||||
foreach ($lineRaw in Get-Content -LiteralPath $file -Encoding UTF8) {
|
||||
|
||||
Reference in New Issue
Block a user