|
@@ -26,6 +26,9 @@ const DEFAULT_CDP_PORT = Number(process.env.NAPOS_CDP_PORT || 9669);
|
|
|
// synonyms / description 供「智能问数」的 LLM 做实体对齐与口径解释
|
|
// synonyms / description 供「智能问数」的 LLM 做实体对齐与口径解释
|
|
|
|
|
|
|
|
const REPORT_COLUMNS = [
|
|
const REPORT_COLUMNS = [
|
|
|
|
|
+ { key: 'account', label: '账号名', type: 'text', locked: true, aggregable: false,
|
|
|
|
|
+ synonyms: ['账号', '账号名', '账户', '主体'],
|
|
|
|
|
+ description: '数据所属的商家账号(主体)名称;多账号数据合并查看或导出时用于区分来源' },
|
|
|
{ key: 'date', label: '日期', type: 'date', locked: true, aggregable: false,
|
|
{ key: 'date', label: '日期', type: 'date', locked: true, aggregable: false,
|
|
|
synonyms: ['日期', '天', '哪天', '日期时间'],
|
|
synonyms: ['日期', '天', '哪天', '日期时间'],
|
|
|
description: '数据日期,格式 YYYYMMDD;当天数据未结算,有效区间一般为 T-1 及更早' },
|
|
description: '数据日期,格式 YYYYMMDD;当天数据未结算,有效区间一般为 T-1 及更早' },
|
|
@@ -415,6 +418,8 @@ function queryReport({ entity, from, to, shopId, shops, scope, q } = {}) {
|
|
|
const needle = String(q).toLowerCase();
|
|
const needle = String(q).toLowerCase();
|
|
|
rows = rows.filter((r) => String(r.shopName || '').toLowerCase().includes(needle));
|
|
rows = rows.filter((r) => String(r.shopName || '').toLowerCase().includes(needle));
|
|
|
}
|
|
}
|
|
|
|
|
+ const account = meta ? meta.name : key;
|
|
|
|
|
+ rows = rows.map((r) => ({ ...r, account }));
|
|
|
return {
|
|
return {
|
|
|
entity: meta ? { key: meta.key, name: meta.name } : { key, name: key },
|
|
entity: meta ? { key: meta.key, name: meta.name } : { key, name: key },
|
|
|
from: from || null, to: to || null,
|
|
from: from || null, to: to || null,
|
|
@@ -427,6 +432,7 @@ function queryReport({ entity, from, to, shopId, shops, scope, q } = {}) {
|
|
|
/** BI 聚合视图:group = 'shop'(按门店)| 'date'(按日期) */
|
|
/** BI 聚合视图:group = 'shop'(按门店)| 'date'(按日期) */
|
|
|
function aggregateReport({ entity, from, to, group = 'shop', shops } = {}) {
|
|
function aggregateReport({ entity, from, to, group = 'shop', shops } = {}) {
|
|
|
const key = store.sanitizeKey(entity);
|
|
const key = store.sanitizeKey(entity);
|
|
|
|
|
+ const meta = store.getEntity(key);
|
|
|
let rows = store.queryRows(key, { from, to, scope: 'shop' });
|
|
let rows = store.queryRows(key, { from, to, scope: 'shop' });
|
|
|
if (Array.isArray(shops) && shops.length) {
|
|
if (Array.isArray(shops) && shops.length) {
|
|
|
const wanted = new Set(shops.map(String));
|
|
const wanted = new Set(shops.map(String));
|
|
@@ -448,7 +454,8 @@ function aggregateReport({ entity, from, to, group = 'shop', shops } = {}) {
|
|
|
out.push({ ...base, ...s });
|
|
out.push({ ...base, ...s });
|
|
|
}
|
|
}
|
|
|
out.sort((a, b) => (group === 'date' ? (a.date < b.date ? -1 : 1) : (b.grossAmt || 0) - (a.grossAmt || 0)));
|
|
out.sort((a, b) => (group === 'date' ? (a.date < b.date ? -1 : 1) : (b.grossAmt || 0) - (a.grossAmt || 0)));
|
|
|
- return { columns: REPORT_COLUMNS, rows: out, summary: summarizeRows(rows) };
|
|
|
|
|
|
|
+ const account = meta ? meta.name : key;
|
|
|
|
|
+ return { columns: REPORT_COLUMNS, rows: out.map((r) => ({ ...r, account })), summary: summarizeRows(rows) };
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// ---------- CSV 导出 ----------
|
|
// ---------- CSV 导出 ----------
|