Post-F: укрепить inventory selected-object provenance

This commit is contained in:
2026-04-24 08:18:02 +03:00
parent 0158419b65
commit 972db24779
6 changed files with 90 additions and 3 deletions
@@ -79,6 +79,14 @@ function hasInventoryOnHandSignal(text: string): boolean {
}
function hasSelectedObjectInventoryCue(text: string): boolean {
const value = String(text ?? "");
if (
/(?:по\s+выбранному\s+объекту|по\s+выбранной\s+позиции|по\s+этой\s+позиции|по\s+этому\s+товару|по\s+нему|по\s+ней|по\s+ним|по\s+нему\s+же|по\s+ней\s+же|selected\s+object)/iu.test(
value
)
) {
return true;
}
return /(?:РїРѕ\s+выбранному\s+объекту|РїРѕ\s+выбранной\s+позиции|РїРѕ\s+этой\s+позиции|РїРѕ\s+этому\s+товару|РїРѕ\s+нему|РїРѕ\s+ней|РїРѕ\s+РЅРёРј|РїРѕ\s+нему\s+РРµ|РїРѕ\s+ней\s+РРµ|selected\s+object)/iu.test(
String(text ?? "")
);
@@ -89,6 +97,15 @@ function hasSelectedObjectInventoryProvenanceSignal(text: string): boolean {
}
function hasSelectedObjectInventoryPurchaseDocumentsSignal(text: string): boolean {
const value = String(text ?? "");
if (
hasSelectedObjectInventoryCue(value) &&
/(?:по\s+каким\s+документам\s+(?:это|его|этот\s+товар|эту\s+позицию)?\s*купили|по\s+каким\s+документам\s+(?:был\s+)?куплен|какими\s+документами\s+(?:это|его|этот\s+товар|эту\s+позицию)?\s*купили|какими\s+документами\s+(?:был\s+)?куплен|покажи\s+документы\s+по\s+(?:этой\s+позиции|этому\s+товару|ней|нему)|документы\s+по\s+(?:этой\s+позиции|этому\s+товару|ней|нему)|purchase\s+documents|documents\s+of\s+purchase|through\s+which\s+documents)/iu.test(
value
)
) {
return true;
}
const hasPurchaseDocumentsCue =
/(?:по\s+каким\s+документам\s+(?:это|его|этот\s+товар|эту\s+позицию)\s+купили|по\s+каким\s+документам\s+(?:был\s+)?куплен|какими\s+документами\s+(?:это|его|этот\s+товар|эту\s+позицию)\s+купили|какими\s+документами\s+(?:был\s+)?куплен|purchase\s+documents|documents\s+of\s+purchase|through\s+which\s+documents)/iu.test(
text
@@ -108,6 +125,17 @@ function hasSelectedObjectInventoryProfitabilitySignal(text: string): boolean {
}
function hasInventoryProvenanceSignalV2(text: string): boolean {
const value = String(text ?? "");
const hasPlainItemCue = /(?:товар|номенклатур|sku|item|product|остат|склад)/iu.test(value);
const hasPlainSupplierCue =
hasInventorySupplierCue(value) || /(?:кем\s+поставлен|кто\s+(?:это|его|этот\s+товар|эту\s+позицию)?\s*поставил)/iu.test(value);
const hasPlainPurchaseCue =
/(?:куплен(?:ы|а|о)?|закупк|происхожд|откуда|где\s+(?:мы\s+)?купили|поставлен(?:ы|а)?|purchase\s+provenance|purchase\s+date)/iu.test(
value
) || hasInventoryPurchaseStem(value);
if (hasPlainItemCue && hasPlainSupplierCue && hasPlainPurchaseCue) {
return true;
}
const hasItemCue = /(?:товар|номенклатур|sku|item|product|остат(?:ок|ки)|склад)/iu.test(text);
const hasSupplierCue = hasInventorySupplierCue(text) || /кем\s+поставлен/iu.test(text);
const hasPurchaseCue =
@@ -129,6 +157,15 @@ function hasInventoryPurchaseDateSignal(text: string): boolean {
}
function hasInventoryPurchaseDocumentsSignalV2(text: string): boolean {
const value = String(text ?? "");
const hasPlainItemCue = /(?:товар|номенклатур|sku|item|product)/iu.test(value);
const hasPlainPurchaseDocCue =
/(?:по\s+каким\s+документам\s+(?:был\s+)?куплен|по\s+каким\s+документам\s+(?:это|его|этот\s+товар|эту\s+позицию)?\s*купили|какими\s+документами\s+(?:был\s+)?куплен|какими\s+документами\s+(?:это|его|этот\s+товар|эту\s+позицию)?\s*купили|документ[а-яё]*\s+закупк|purchase\s+documents|documents\s+of\s+purchase|through\s+which\s+documents)/iu.test(
value
);
if (hasPlainItemCue && hasPlainPurchaseDocCue) {
return true;
}
const hasItemCue = /(?:товар|номенклатур|sku|item|product)/iu.test(text);
const hasPurchaseDocCue = /(?:по\s+каким\s+документам\s+был\s+куплен|по\s+каким\s+документам\s+куплен|какими\s+документами\s+был\s+куплен|документ(?:ам|ы)\s+закупк|purchase\s+documents|documents\s+of\s+purchase|through\s+which\s+documents)/iu.test(
text
@@ -1,4 +1,4 @@
import type {
import type {
AddressFilterSet,
AddressIntent,
AddressRecipeDefinition,
@@ -1610,7 +1610,7 @@ export function buildAddressRecipePlan(
: recipe.query_template === "inventory_purchase_provenance_profile"
? buildInventoryPurchaseDocumentQuery(filters, resolvedLimit)
: recipe.query_template === "inventory_purchase_documents_profile"
? buildInventoryPurchaseDocumentQuery(filters, resolvedLimit)
? buildInventoryMovementQuery(filters, resolvedLimit, "dt")
: recipe.query_template === "inventory_supplier_stock_overlap_profile"
? buildInventoryMovementQuery(filters, resolvedLimit, "dt")
: recipe.query_template === "inventory_sale_trace_profile"
@@ -1461,6 +1461,10 @@ function deriveIntentWithFollowupContext(
const inventorySelectedObjectFollowup =
inventoryLineageActive &&
(hasSelectedObjectInventorySignal(normalizedMessage) || (previousIsInventoryFamily && hasFollowupSignal));
const hasExplicitInventoryItemReference =
/(?:товар|номенклатур|позици|склад|остат|sku|item|product|товар|номенклатур|позици|склад|остат)/iu.test(
normalizedMessage
) || hasSelectedObjectInlineSnapshotMetadata(normalizedMessage);
const inventoryPurchaseDateVatBridge =
inventorySelectedObjectFollowup && hasInventoryPurchaseDateVatBridgeCue(normalizedMessage);
@@ -1490,6 +1494,19 @@ function deriveIntentWithFollowupContext(
};
}
if (
!inventoryLineageActive &&
hasAnyPartyAnchor &&
!hasExplicitInventoryItemReference &&
detectedIntent.intent === "inventory_purchase_documents_for_item"
) {
return {
intent: hasPreviousContract && !hasPreviousCounterparty ? "list_documents_by_contract" : "list_documents_by_counterparty",
confidence: "low",
reasons: [...detectedIntent.reasons, "intent_adjusted_from_non_inventory_followup_context"]
};
}
const allowOpenItemsFollowupFallback = detectedIntent.intent === "unknown" && !isVatFollowup;
if (
allowOpenItemsFollowupFallback &&