Add architecture longread and remove dead code found during review
- docs: longread.md — deep architecture/flow review of the whole platform (services, event bus reality vs docs, AI/ML stack honesty check, tech debt inventory) - ai_orchestrator_service/voice.py: drop _voice_decision_legacy (unreferenced) and the shadowed first _voice_decision definition (silently overwritten by the real one, dead code) - ui/analyst/app.js: drop duplicate dead definitions of loadSavedAnalyticsViews/saveAnalyticsView/deleteAnalyticsView and the first loadAnalyticsTrend implementation, all shadowed by later declarations in the same file; kept the intentional AI-mode drilldown wrapper layer (openAnalyticsDrilldown/exportAnalyticsDrilldownCsv/etc.) since that duplication is deliberate delegation, not dead code - ui/operator/vendor/sip-0.21.2.min.js: remove byte-identical orphaned duplicate of ui/operator/sip-0.21.2.min.js (unreferenced anywhere) Verified via full pytest run: identical set of 97 pre-existing failures before and after (sales_* test-isolation ordering issue and one known persona-prompt test), no new regressions. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
09a4ddac51
commit
cdabe61bc2
@@ -2213,28 +2213,6 @@ function normalizeSavedAnalyticsView(item = {}) {
|
||||
};
|
||||
}
|
||||
|
||||
async function loadSavedAnalyticsViews() {
|
||||
try {
|
||||
const items = await api('reporting', 'reports/views');
|
||||
state.analytics.savedViews = Array.isArray(items)
|
||||
? items
|
||||
.filter((item) => item && typeof item === 'object')
|
||||
.map((item) => normalizeSavedAnalyticsView(item))
|
||||
.sort((a, b) => String(b.updatedAt).localeCompare(String(a.updatedAt)))
|
||||
: [];
|
||||
} catch (err) {
|
||||
state.analytics.savedViews = [];
|
||||
state.analytics.statusMessage = `Не удалось загрузить сохранённые виды: ${err.message}`;
|
||||
}
|
||||
if (
|
||||
state.analytics.activeViewId
|
||||
&& !state.analytics.savedViews.some((item) => item.id === state.analytics.activeViewId)
|
||||
) {
|
||||
state.analytics.activeViewId = '';
|
||||
}
|
||||
renderSavedAnalyticsViews();
|
||||
}
|
||||
|
||||
function renderSavedAnalyticsViews() {
|
||||
const select = $('analyticsSavedViewSelect');
|
||||
const input = $('analyticsSavedViewName');
|
||||
@@ -2274,56 +2252,6 @@ function renderSavedAnalyticsViews() {
|
||||
meta.textContent = parts.join(' · ');
|
||||
}
|
||||
|
||||
async function saveAnalyticsView() {
|
||||
syncAnalyticsStateFromControls();
|
||||
const input = $('analyticsSavedViewName');
|
||||
const name = input?.value.trim() || suggestAnalyticsViewName();
|
||||
try {
|
||||
const view = await api('reporting', 'reports/views', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
id: state.analytics.activeViewId || null,
|
||||
name,
|
||||
snapshot: analyticsCurrentSnapshot(),
|
||||
}),
|
||||
});
|
||||
const normalized = normalizeSavedAnalyticsView(view);
|
||||
const existingIndex = state.analytics.savedViews.findIndex((item) => item.id === normalized.id);
|
||||
if (existingIndex >= 0) {
|
||||
state.analytics.savedViews.splice(existingIndex, 1, normalized);
|
||||
state.analytics.statusMessage = `Вид «${name}» обновлён.`;
|
||||
} else {
|
||||
state.analytics.savedViews.unshift(normalized);
|
||||
state.analytics.statusMessage = `Вид «${name}» сохранён.`;
|
||||
}
|
||||
state.analytics.savedViews = state.analytics.savedViews
|
||||
.sort((a, b) => String(b.updatedAt).localeCompare(String(a.updatedAt)))
|
||||
.slice(0, 12);
|
||||
state.analytics.activeViewId = normalized.id;
|
||||
} catch (err) {
|
||||
state.analytics.statusMessage = `Не удалось сохранить вид: ${err.message}`;
|
||||
}
|
||||
renderSavedAnalyticsViews();
|
||||
}
|
||||
|
||||
async function deleteAnalyticsView() {
|
||||
const activeView = state.analytics.savedViews.find((item) => item.id === state.analytics.activeViewId) || null;
|
||||
if (!activeView) {
|
||||
state.analytics.statusMessage = 'Сначала выберите вид, который нужно удалить.';
|
||||
renderSavedAnalyticsViews();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await api('reporting', `reports/views/${encodeURIComponent(activeView.id)}`, { method: 'DELETE' });
|
||||
state.analytics.savedViews = state.analytics.savedViews.filter((item) => item.id !== activeView.id);
|
||||
state.analytics.activeViewId = '';
|
||||
state.analytics.statusMessage = `Вид «${activeView.name}» удалён.`;
|
||||
} catch (err) {
|
||||
state.analytics.statusMessage = `Не удалось удалить вид: ${err.message}`;
|
||||
}
|
||||
renderSavedAnalyticsViews();
|
||||
}
|
||||
|
||||
function detachActiveAnalyticsView() {
|
||||
if (!state.analytics.activeViewId) {
|
||||
return;
|
||||
@@ -5021,24 +4949,6 @@ function buildTrendBuckets(range, preset, custom) {
|
||||
return buckets;
|
||||
}
|
||||
|
||||
async function loadAnalyticsTrend(rangeMeta, requestId) {
|
||||
const buckets = buildTrendBuckets(rangeMeta.current, rangeMeta.preset, rangeMeta.custom);
|
||||
const items = await Promise.all(
|
||||
buckets.map(async (bucket) => {
|
||||
try {
|
||||
const payload = await fetchAnalyticsKpi(bucket.range);
|
||||
return { ...bucket, payload };
|
||||
} catch {
|
||||
return { ...bucket, payload: emptyKpiEnvelope(bucket.range.from.toISOString(), bucket.range.to.toISOString()) };
|
||||
}
|
||||
}),
|
||||
);
|
||||
if (requestId !== state.analytics.requestId) {
|
||||
return [];
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
function aiAnalyticsIntervalForRange(rangeMeta) {
|
||||
const durationMs = Math.max(0, rangeMeta.current.to.getTime() - rangeMeta.current.from.getTime());
|
||||
return durationMs <= 36 * 60 * 60 * 1000 ? 'hour' : 'day';
|
||||
|
||||
Vendored
-2
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user