Open-World: добавить торговый margin proxy в бизнес-обзор

This commit is contained in:
2026-05-04 10:07:26 +03:00
parent 822baedcba
commit 062655eca0
12 changed files with 633 additions and 57 deletions
@@ -857,6 +857,17 @@ const BASE_RECIPES: AddressRecipeDefinition[] = [
account_scope_mode: "strict",
query_template: "inventory_sale_trace_profile"
},
{
recipe_id: "address_inventory_trading_margin_proxy_for_organization_v1",
intent: "inventory_trading_margin_proxy_for_organization",
purpose: "Trace organization-period purchase and sale document rows and derive bounded trading revenue, purchase-cost proxy, spread, and margin proxy",
required_filters: [],
optional_filters: ["period_from", "period_to", "organization", "warehouse", "limit", "sort"],
default_limit: 600,
account_scope: ["41.01"],
account_scope_mode: "strict",
query_template: "inventory_trading_margin_proxy_profile"
},
{
recipe_id: "address_inventory_purchase_to_sale_chain_v1",
intent: "inventory_purchase_to_sale_chain",
@@ -1438,6 +1449,7 @@ function maxLimitForIntent(intent: AddressIntent): number {
intent === "inventory_purchase_documents_for_item" ||
intent === "inventory_supplier_stock_overlap_as_of_date" ||
intent === "inventory_sale_trace_for_item" ||
intent === "inventory_trading_margin_proxy_for_organization" ||
intent === "inventory_profitability_for_item" ||
intent === "inventory_purchase_to_sale_chain" ||
intent === "inventory_aging_by_purchase_date" ||
@@ -1666,6 +1678,8 @@ export function buildAddressRecipePlan(
? buildInventorySaleDocumentQuery(filters, resolvedLimit)
: recipe.query_template === "inventory_profitability_profile"
? buildInventoryPurchaseToSaleDocumentQuery(filters, resolvedLimit)
: recipe.query_template === "inventory_trading_margin_proxy_profile"
? buildInventoryPurchaseToSaleDocumentQuery(filters, resolvedLimit)
: recipe.query_template === "inventory_purchase_to_sale_chain_profile"
? buildInventoryPurchaseToSaleDocumentQuery(filters, resolvedLimit)
: recipe.query_template === "inventory_aging_by_purchase_date_profile"
@@ -452,6 +452,9 @@ function headlineFor(mode: AssistantMcpDiscoveryAnswerMode, pilot: AssistantMcpD
if (overview.tax_position) {
families.push("НДС-позиция");
}
if (overview.trading_margin_proxy) {
families.push("торговый margin proxy");
}
if (overview.debt_position) {
families.push("долговой срез на дату");
}
@@ -464,7 +467,7 @@ function headlineFor(mode: AssistantMcpDiscoveryAnswerMode, pilot: AssistantMcpD
if (overview.inventory_position) {
families.push("складской срез на дату");
}
const unknownFamilies = ["прибыль/маржа"];
const unknownFamilies = [overview.trading_margin_proxy ? "чистая прибыль/точная маржа" : "прибыль/маржа"];
if (!overview.tax_position) {
unknownFamilies.push("НДС");
}
@@ -658,6 +661,7 @@ function buildMustNotClaim(pilot: AssistantMcpDiscoveryPilotExecutionContract):
}
if (isBusinessOverviewPilot(pilot)) {
claims.push("Do not present business overview cash-flow spread as profit or margin.");
claims.push("Do not present business overview trading-margin proxy as clean profit, accounting financial result, or exact cost-of-sales margin.");
claims.push("Do not claim debt quality, VAT position, inventory health, or company health unless those contours were separately checked.");
claims.push("Do not present a debt-position snapshot as debt aging, overdue debt, or credit-quality analysis.");
claims.push("Do not present open-settlement concentration as contractual due-date aging or confirmed overdue debt.");
@@ -1022,6 +1026,13 @@ function derivedBusinessOverviewConfirmedLines(pilot: AssistantMcpDiscoveryPilot
`НДС-позиция за ${overview.tax_position.period_scope}: книга продаж ${overview.tax_position.sales_vat_amount_human_ru}, книга покупок/вычеты ${overview.tax_position.purchase_vat_amount_human_ru}, нетто ${taxDirection} ${overview.tax_position.net_vat_amount_human_ru}.`
);
}
if (overview.trading_margin_proxy) {
const proxy = overview.trading_margin_proxy;
const marginText = proxy.margin_to_revenue_pct === null ? "не рассчитана" : `${proxy.margin_to_revenue_pct}%`;
lines.push(
`Торговый margin proxy за ${proxy.period_scope}: выручка продаж ${proxy.sales_revenue_human_ru}, закупочный документный след ${proxy.purchase_cost_proxy_human_ru}, валовый спред proxy ${proxy.gross_spread_proxy_human_ru}, маржинальность к выручке ${marginText}. Это не чистая прибыль и не бухгалтерский финрезультат.`
);
}
if (overview.debt_position) {
const debtDirection =
overview.debt_position.net_debt_position_direction === "net_receivable"
@@ -1106,6 +1117,12 @@ function businessOverviewRiskSynthesisLine(overview: BusinessOverview): string |
: "НДС-позиция сбалансирована";
signals.push(taxDirection);
}
if (overview.trading_margin_proxy) {
const marginText = overview.trading_margin_proxy.margin_to_revenue_pct === null
? "маржинальность не рассчитана"
: `маржинальность proxy ${overview.trading_margin_proxy.margin_to_revenue_pct}%`;
signals.push(`торговый спред proxy ${overview.trading_margin_proxy.gross_spread_proxy_human_ru}, ${marginText}`);
}
if (overview.debt_position) {
const debtDirection =
overview.debt_position.net_debt_position_direction === "net_receivable"
@@ -1137,6 +1154,7 @@ function businessOverviewExecutiveVerdictLine(overview: BusinessOverview): strin
const hasCash = overview.incoming_customer_revenue.rows_with_amount > 0 || overview.outgoing_supplier_payout.rows_with_amount > 0;
const hasExtraSignals = Boolean(
overview.tax_position ||
overview.trading_margin_proxy ||
overview.debt_position ||
overview.debt_open_settlement_quality ||
overview.inventory_position
@@ -1223,6 +1241,9 @@ export function buildAssistantMcpDiscoveryAnswerDraft(
if (pilot.derived_business_overview?.tax_position) {
pushReason(reasonCodes, "answer_contains_business_overview_tax_position");
}
if (pilot.derived_business_overview?.trading_margin_proxy) {
pushReason(reasonCodes, "answer_contains_business_overview_trading_margin_proxy");
}
if (pilot.derived_business_overview?.debt_position) {
pushReason(reasonCodes, "answer_contains_business_overview_debt_position");
}
@@ -152,6 +152,7 @@ export interface AssistantMcpDiscoveryDerivedBusinessOverview {
top_customers: AssistantMcpDiscoveryRankedValueFlowBucket[];
activity_period: AssistantMcpDiscoveryDerivedActivityPeriod | null;
tax_position: AssistantMcpDiscoveryDerivedBusinessOverviewTaxPosition | null;
trading_margin_proxy: AssistantMcpDiscoveryDerivedBusinessOverviewTradingMarginProxy | null;
debt_position: AssistantMcpDiscoveryDerivedBusinessOverviewDebtPosition | null;
debt_open_settlement_quality: AssistantMcpDiscoveryDerivedBusinessOverviewDebtOpenSettlementQuality | null;
inventory_position: AssistantMcpDiscoveryDerivedBusinessOverviewInventoryPosition | null;
@@ -180,6 +181,35 @@ export interface AssistantMcpDiscoveryDerivedBusinessOverviewTaxPosition {
inference_basis: "sales_book_minus_purchase_book_confirmed_1c_vat_rows";
}
export interface AssistantMcpDiscoveryBusinessOverviewTradingItemBucket {
item: string;
sales_revenue: number;
sales_revenue_human_ru: string;
purchase_cost_proxy: number;
purchase_cost_proxy_human_ru: string;
gross_spread_proxy: number;
gross_spread_proxy_human_ru: string;
sales_quantity: number;
purchase_quantity: number;
}
export interface AssistantMcpDiscoveryDerivedBusinessOverviewTradingMarginProxy {
period_scope: string;
rows_matched: number;
sales_rows_with_amount: number;
purchase_rows_with_amount: number;
sales_revenue: number;
sales_revenue_human_ru: string;
purchase_cost_proxy: number;
purchase_cost_proxy_human_ru: string;
gross_spread_proxy: number;
gross_spread_proxy_human_ru: string;
margin_to_revenue_pct: number | null;
markup_to_purchase_pct: number | null;
top_items_by_sales: AssistantMcpDiscoveryBusinessOverviewTradingItemBucket[];
inference_basis: "sales_documents_minus_purchase_documents_confirmed_1c_rows";
}
export interface AssistantMcpDiscoveryBusinessOverviewDebtSideSummary {
rows_matched: number;
rows_with_amount: number;
@@ -578,6 +608,22 @@ function buildBusinessOverviewInventoryFilters(planner: AssistantMcpDiscoveryPla
};
}
function buildBusinessOverviewTradingMarginFilters(planner: AssistantMcpDiscoveryPlannerContract): AddressFilterSet | null {
const meaning = planner.discovery_plan.turn_meaning_ref;
const organization = toNonEmptyString(meaning?.explicit_organization_scope);
const dateScope = toNonEmptyString(meaning?.explicit_date_scope);
const periodFilters = dateScopeToFilters(dateScope);
if (!periodFilters.period_from || !periodFilters.period_to) {
return null;
}
return {
...periodFilters,
...(organization ? { organization } : {}),
limit: planner.discovery_plan.execution_budget.max_rows_per_probe,
sort: "period_asc"
};
}
function buildInventoryExactFilters(planner: AssistantMcpDiscoveryPlannerContract): AddressFilterSet {
const meaning = planner.discovery_plan.turn_meaning_ref;
const subject = firstEntityCandidate(planner);
@@ -2087,6 +2133,19 @@ function rowAccountValue(row: Record<string, unknown>): string | null {
return rowTextValue(row, ["СчетДт", "AccountDt", "account_dt", "Счет", "Account", "account"]);
}
function rowDebitAccountValue(row: Record<string, unknown>): string | null {
return rowTextValue(row, ["СчетДт", "AccountDt", "account_dt", "DebitAccount", "debit_account"]);
}
function rowCreditAccountValue(row: Record<string, unknown>): string | null {
return rowTextValue(row, ["СчетКт", "AccountKt", "account_kt", "CreditAccount", "credit_account"]);
}
function accountTextMatchesPrefix(account: string | null, prefixes: string[]): boolean {
const normalized = String(account ?? "").replace(/\s+/g, "");
return prefixes.some((prefix) => normalized.startsWith(prefix));
}
function rowQuantityValue(row: Record<string, unknown>): number | null {
return rowNumberValue(row, ["Количество", "Quantity", "quantity", "Qty", "qty", "Остаток", "Balance", "balance"]);
}
@@ -2673,6 +2732,101 @@ function deriveBusinessOverviewTaxPosition(
};
}
function deriveBusinessOverviewTradingMarginProxy(
result: AddressMcpQueryExecutorResult | null,
periodScope: string | null
): AssistantMcpDiscoveryDerivedBusinessOverviewTradingMarginProxy | null {
if (!result || result.error || result.matched_rows <= 0 || !periodScope) {
return null;
}
const itemBuckets = new Map<string, {
sales_revenue: number;
purchase_cost_proxy: number;
sales_quantity: number;
purchase_quantity: number;
}>();
let salesRowsWithAmount = 0;
let purchaseRowsWithAmount = 0;
let salesRevenue = 0;
let purchaseCostProxy = 0;
for (const row of result.rows) {
const amount = rowAmountValue(row);
if (amount === null || amount <= 0) {
continue;
}
const isSale = accountTextMatchesPrefix(rowCreditAccountValue(row), ["41.01"]);
const isPurchase = accountTextMatchesPrefix(rowDebitAccountValue(row), ["41.01"]);
if (!isSale && !isPurchase) {
continue;
}
const item = rowInventoryItemValue(row) ?? "unknown_item";
const quantity = rowQuantityValue(row) ?? 0;
const bucket = itemBuckets.get(item) ?? {
sales_revenue: 0,
purchase_cost_proxy: 0,
sales_quantity: 0,
purchase_quantity: 0
};
if (isSale) {
salesRowsWithAmount += 1;
salesRevenue += amount;
bucket.sales_revenue += amount;
bucket.sales_quantity += quantity;
}
if (isPurchase) {
purchaseRowsWithAmount += 1;
purchaseCostProxy += amount;
bucket.purchase_cost_proxy += amount;
bucket.purchase_quantity += quantity;
}
itemBuckets.set(item, bucket);
}
if (salesRowsWithAmount <= 0 && purchaseRowsWithAmount <= 0) {
return null;
}
const grossSpreadProxy = salesRevenue - purchaseCostProxy;
const marginToRevenuePct = salesRevenue > 0 ? percentageOfTotal(grossSpreadProxy, salesRevenue) : null;
const markupToPurchasePct = purchaseCostProxy > 0 ? percentageOfTotal(grossSpreadProxy, purchaseCostProxy) : null;
const topItemsBySales = Array.from(itemBuckets.entries())
.map(([item, bucket]) => ({
item,
sales_revenue: bucket.sales_revenue,
sales_revenue_human_ru: formatAmountHumanRu(bucket.sales_revenue),
purchase_cost_proxy: bucket.purchase_cost_proxy,
purchase_cost_proxy_human_ru: formatAmountHumanRu(bucket.purchase_cost_proxy),
gross_spread_proxy: bucket.sales_revenue - bucket.purchase_cost_proxy,
gross_spread_proxy_human_ru: formatAmountHumanRu(bucket.sales_revenue - bucket.purchase_cost_proxy),
sales_quantity: bucket.sales_quantity,
purchase_quantity: bucket.purchase_quantity
}))
.sort((left, right) => {
const salesDelta = right.sales_revenue - left.sales_revenue;
return salesDelta !== 0 ? salesDelta : left.item.localeCompare(right.item, "ru");
})
.slice(0, 5);
return {
period_scope: periodScope,
rows_matched: result.matched_rows,
sales_rows_with_amount: salesRowsWithAmount,
purchase_rows_with_amount: purchaseRowsWithAmount,
sales_revenue: salesRevenue,
sales_revenue_human_ru: formatAmountHumanRu(salesRevenue),
purchase_cost_proxy: purchaseCostProxy,
purchase_cost_proxy_human_ru: formatAmountHumanRu(purchaseCostProxy),
gross_spread_proxy: grossSpreadProxy,
gross_spread_proxy_human_ru: formatAmountHumanRu(grossSpreadProxy),
margin_to_revenue_pct: marginToRevenuePct,
markup_to_purchase_pct: markupToPurchasePct,
top_items_by_sales: topItemsBySales,
inference_basis: "sales_documents_minus_purchase_documents_confirmed_1c_rows"
};
}
function deriveBusinessOverviewDebtSide(
result: AddressMcpQueryExecutorResult | null
): AssistantMcpDiscoveryBusinessOverviewDebtSideSummary {
@@ -3059,6 +3213,7 @@ function deriveBusinessOverview(input: {
outgoingResult: AssistantMcpDiscoveryCoverageAwareQueryResult | null;
lifecycleResult: AddressMcpQueryExecutorResult | null;
taxResult: AddressMcpQueryExecutorResult | null;
tradingMarginResult: AddressMcpQueryExecutorResult | null;
receivablesResult: AddressMcpQueryExecutorResult | null;
payablesResult: AddressMcpQueryExecutorResult | null;
openContractsResult: AddressMcpQueryExecutorResult | null;
@@ -3079,6 +3234,7 @@ function deriveBusinessOverview(input: {
});
const activityPeriod = deriveActivityPeriod(input.lifecycleResult);
const taxPosition = deriveBusinessOverviewTaxPosition(input.taxResult, input.periodScope);
const tradingMarginProxy = deriveBusinessOverviewTradingMarginProxy(input.tradingMarginResult, input.periodScope);
const debtPosition = deriveBusinessOverviewDebtPosition({
receivablesResult: input.receivablesResult,
payablesResult: input.payablesResult,
@@ -3098,6 +3254,7 @@ function deriveBusinessOverview(input: {
outgoing.rows_with_amount > 0,
Boolean(activityPeriod),
Boolean(taxPosition),
Boolean(tradingMarginProxy),
Boolean(debtPosition),
Boolean(debtOpenSettlementQuality),
Boolean(inventoryPosition)
@@ -3118,6 +3275,7 @@ function deriveBusinessOverview(input: {
top_customers: rankedIncoming?.ranked_values ?? [],
activity_period: activityPeriod,
tax_position: taxPosition,
trading_margin_proxy: tradingMarginProxy,
debt_position: debtPosition,
debt_open_settlement_quality: debtOpenSettlementQuality,
inventory_position: inventoryPosition,
@@ -3125,7 +3283,7 @@ function deriveBusinessOverview(input: {
incoming.coverage_limited_by_probe_limit || outgoing.coverage_limited_by_probe_limit,
checked_signal_count: checkedSignalCount,
missing_signal_families: [
"profit_margin",
tradingMarginProxy ? "accounting_profit_margin" : "profit_margin",
debtPosition ? null : "debt_position",
debtOpenSettlementQuality ? "debt_due_date_aging_quality" : "debt_open_settlement_quality",
taxPosition ? null : "tax_position",
@@ -3152,6 +3310,7 @@ function summarizeBusinessOverviewRows(input: {
outgoingResult: AssistantMcpDiscoveryCoverageAwareQueryResult | null;
lifecycleResult: AddressMcpQueryExecutorResult | null;
taxResult: AddressMcpQueryExecutorResult | null;
tradingMarginResult: AddressMcpQueryExecutorResult | null;
receivablesResult: AddressMcpQueryExecutorResult | null;
payablesResult: AddressMcpQueryExecutorResult | null;
openContractsResult: AddressMcpQueryExecutorResult | null;
@@ -3171,6 +3330,9 @@ function summarizeBusinessOverviewRows(input: {
if (input.taxResult && !input.taxResult.error) {
parts.push(`${input.taxResult.fetched_rows} VAT/tax rows fetched, ${input.taxResult.matched_rows} matched`);
}
if (input.tradingMarginResult && !input.tradingMarginResult.error) {
parts.push(`${input.tradingMarginResult.fetched_rows} trading-margin document rows fetched, ${input.tradingMarginResult.matched_rows} matched`);
}
if (input.receivablesResult && !input.receivablesResult.error) {
parts.push(`${input.receivablesResult.fetched_rows} receivables rows fetched, ${input.receivablesResult.matched_rows} matched`);
}
@@ -3228,6 +3390,13 @@ function buildBusinessOverviewConfirmedFacts(derived: AssistantMcpDiscoveryDeriv
`НДС-позиция за ${derived.tax_position.period_scope} подтверждена по книгам продаж/покупок: продажи ${derived.tax_position.sales_vat_amount_human_ru}, покупки/вычеты ${derived.tax_position.purchase_vat_amount_human_ru}, нетто ${taxDirection} ${derived.tax_position.net_vat_amount_human_ru}.`
);
}
if (derived.trading_margin_proxy) {
const proxy = derived.trading_margin_proxy;
const marginText = proxy.margin_to_revenue_pct === null ? "не рассчитана" : `${proxy.margin_to_revenue_pct}%`;
facts.push(
`Торговый margin proxy за ${proxy.period_scope} подтвержден по товарным документам продаж/поступлений: выручка продаж ${proxy.sales_revenue_human_ru}, закупочный документный след ${proxy.purchase_cost_proxy_human_ru}, валовый спред proxy ${proxy.gross_spread_proxy_human_ru}, маржинальность к выручке ${marginText}. Это не чистая прибыль и не бухгалтерский финрезультат.`
);
}
if (derived.debt_position) {
const debtDirection =
derived.debt_position.net_debt_position_direction === "net_receivable"
@@ -3313,6 +3482,9 @@ function buildBusinessOverviewUnknownFacts(derived: AssistantMcpDiscoveryDerived
missing.has("profit_margin")
? "Прибыль и маржа этим бизнес-обзором не подтверждены: нужны себестоимость, расходы и закрывающие документы."
: null,
missing.has("accounting_profit_margin")
? "Чистая прибыль, бухгалтерская маржа и финрезультат этим бизнес-обзором не подтверждены: торговый proxy показывает только документную разницу продаж и поступлений без расходов, закрытия периода и точной себестоимости продаж."
: null,
missing.has("debt_quality")
? "Качество дебиторки/кредиторки этим бизнес-обзором не подтверждено: нужен отдельный долговой срез."
: null,
@@ -4066,6 +4238,7 @@ export async function executeAssistantMcpDiscoveryPilot(
let outgoingResult: AssistantMcpDiscoveryCoverageAwareQueryResult | null = null;
let lifecycleResult: AddressMcpQueryExecutorResult | null = null;
let taxResult: AddressMcpQueryExecutorResult | null = null;
let tradingMarginResult: AddressMcpQueryExecutorResult | null = null;
let receivablesResult: AddressMcpQueryExecutorResult | null = null;
let payablesResult: AddressMcpQueryExecutorResult | null = null;
let openContractsResult: AddressMcpQueryExecutorResult | null = null;
@@ -4074,6 +4247,7 @@ export async function executeAssistantMcpDiscoveryPilot(
const valueFilters = buildValueFlowFilters(planner);
const lifecycleFilters = buildLifecycleFilters(planner);
const taxFilters = buildBusinessOverviewTaxFilters(planner);
const tradingMarginFilters = buildBusinessOverviewTradingMarginFilters(planner);
const debtFilters = buildBusinessOverviewDebtFilters(planner);
const inventoryFilters = buildBusinessOverviewInventoryFilters(planner);
const debtAsOfDate = toNonEmptyString(debtFilters?.as_of_date);
@@ -4084,6 +4258,9 @@ export async function executeAssistantMcpDiscoveryPilot(
const taxSelection = taxFilters
? selectAddressRecipe("vat_liability_confirmed_for_tax_period", taxFilters)
: null;
const tradingMarginSelection = tradingMarginFilters
? selectAddressRecipe("inventory_trading_margin_proxy_for_organization", tradingMarginFilters)
: null;
const receivablesSelection = debtFilters
? selectAddressRecipe("receivables_confirmed_as_of_date", debtFilters)
: null;
@@ -4139,6 +4316,14 @@ export async function executeAssistantMcpDiscoveryPilot(
pushReason(reasonCodes, "pilot_business_overview_tax_recipe_not_available");
pushUnique(queryLimitations, "Business overview VAT/tax probe requires an executable tax-period recipe");
}
if (tradingMarginSelection?.selected_recipe) {
pushReason(reasonCodes, "pilot_business_overview_trading_margin_recipe_selected");
} else if (!tradingMarginFilters) {
pushReason(reasonCodes, "pilot_business_overview_trading_margin_probe_skipped_without_explicit_period");
} else {
pushReason(reasonCodes, "pilot_business_overview_trading_margin_recipe_not_available");
pushUnique(queryLimitations, "Business overview trading-margin proxy requires an executable explicit-period purchase/sale document recipe");
}
if (receivablesSelection?.selected_recipe && payablesSelection?.selected_recipe) {
pushReason(reasonCodes, "pilot_business_overview_debt_recipes_selected");
} else if (!debtFilters) {
@@ -4326,12 +4511,27 @@ export async function executeAssistantMcpDiscoveryPilot(
});
pushUnique(executedPrimitives, step.primitive_id);
probeResults.push(queryResultToProbeResult(step.primitive_id, lifecycleResult));
if (tradingMarginSelection?.selected_recipe) {
const tradingMarginPlan = buildAddressRecipePlan(tradingMarginSelection.selected_recipe, tradingMarginFilters!);
tradingMarginResult = await runtimeDeps.executeAddressMcpQuery({
query: tradingMarginPlan.query,
limit: tradingMarginPlan.limit,
account_scope: tradingMarginPlan.account_scope
});
probeResults.push(queryResultToProbeResult(step.primitive_id, tradingMarginResult));
}
if (lifecycleResult.error) {
pushUnique(queryLimitations, lifecycleResult.error);
pushReason(reasonCodes, "pilot_business_overview_query_documents_mcp_error");
} else {
pushReason(reasonCodes, "pilot_business_overview_query_documents_mcp_executed");
}
if (tradingMarginResult?.error) {
pushUnique(queryLimitations, tradingMarginResult.error);
pushReason(reasonCodes, "pilot_business_overview_trading_margin_query_mcp_error");
} else if (tradingMarginResult) {
pushReason(reasonCodes, "pilot_business_overview_trading_margin_query_mcp_executed");
}
continue;
}
@@ -4344,6 +4544,7 @@ export async function executeAssistantMcpDiscoveryPilot(
outgoingResult,
lifecycleResult,
taxResult,
tradingMarginResult,
receivablesResult,
payablesResult,
openContractsResult,
@@ -4365,6 +4566,9 @@ export async function executeAssistantMcpDiscoveryPilot(
if (derivedBusinessOverview.tax_position) {
pushReason(reasonCodes, "pilot_derived_business_overview_tax_position_from_confirmed_rows");
}
if (derivedBusinessOverview.trading_margin_proxy) {
pushReason(reasonCodes, "pilot_derived_business_overview_trading_margin_proxy_from_confirmed_rows");
}
if (derivedBusinessOverview.debt_position) {
pushReason(reasonCodes, "pilot_derived_business_overview_debt_position_from_confirmed_rows");
}
@@ -4383,6 +4587,7 @@ export async function executeAssistantMcpDiscoveryPilot(
outgoingResult,
lifecycleResult,
taxResult,
tradingMarginResult,
receivablesResult,
payablesResult,
openContractsResult,
@@ -30,6 +30,7 @@ export type AddressIntent =
| "inventory_purchase_documents_for_item"
| "inventory_supplier_stock_overlap_as_of_date"
| "inventory_sale_trace_for_item"
| "inventory_trading_margin_proxy_for_organization"
| "inventory_profitability_for_item"
| "inventory_purchase_to_sale_chain"
| "inventory_aging_by_purchase_date"
@@ -196,6 +197,7 @@ export interface AddressRecipeDefinition {
| "inventory_purchase_documents_profile"
| "inventory_supplier_stock_overlap_profile"
| "inventory_sale_trace_profile"
| "inventory_trading_margin_proxy_profile"
| "inventory_profitability_profile"
| "inventory_purchase_to_sale_chain_profile"
| "inventory_aging_by_purchase_date_profile";