ДОМЕНЫ - ВОПРОСЫ - СКЛАД - Починить selected-object follow-up по складу и включить разговорные/UI-варианты в обязательный domain-loop
This commit is contained in:
@@ -1542,16 +1542,32 @@ function hasAccountNumberAnchor(text: string): boolean {
|
||||
return /(?:account|сч[её]т|счет)\D{0,12}\d{2}(?:[.,]\d{1,2})?/i.test(text);
|
||||
}
|
||||
|
||||
function hasInventoryAccount41Anchor(text: string): boolean {
|
||||
return /(?:сч[её]т(?:а|е|у)?|счет(?:а|е|у)?)\D{0,12}41(?:[.,]0?1)?/iu.test(text) || /41(?:[.,]0?1)?\D{0,12}(?:сч[её]т(?:а|е|у)?|счет(?:а|е|у)?)/iu.test(text);
|
||||
}
|
||||
|
||||
function hasInventoryAsOfCue(text: string): boolean {
|
||||
return /(?:сейчас|текущ|на\s+дату|по\s+состоянию|срез|на\s+конец|date|as\s+of|current|now|today)/iu.test(
|
||||
text
|
||||
);
|
||||
}
|
||||
|
||||
function hasInventoryOnHandSignal(text: string): boolean {
|
||||
const hasColloquialStockSnapshotCue = /(?:что|ч[её])\s+(?:у\s+нас\s+)?на\s+склад(?:е|у|ом)(?=$|[\s,.;:!?])/iu.test(
|
||||
text
|
||||
);
|
||||
const hasAccount41Anchor = hasInventoryAccount41Anchor(text);
|
||||
const hasStockLexeme =
|
||||
/(?:склад(?:е|у|ом|ы|ов)?|warehouse|stock(?:room)?|inventory|on[\s-]?hand)/iu.test(text);
|
||||
if (!hasStockLexeme) {
|
||||
if (!hasStockLexeme && !hasAccount41Anchor) {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
hasInventoryProvenanceSignalV2(text) ||
|
||||
hasInventoryPurchaseDocumentsSignalV2(text) ||
|
||||
hasInventorySaleTraceSignalV2(text)
|
||||
hasInventorySaleTraceSignalV2(text) ||
|
||||
hasInventoryAgingSignal(text) ||
|
||||
hasInventoryPurchaseToSaleChainSignal(text)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
@@ -1562,7 +1578,11 @@ function hasInventoryOnHandSignal(text: string): boolean {
|
||||
text
|
||||
);
|
||||
const hasRequestCue = /(?:покажи|показать|выведи|дай|какие|что|какой|сколько|show|list|which|what)/iu.test(text);
|
||||
return (hasGoodsLexeme || hasBalanceLexeme) && (hasRequestCue || hasBalanceLexeme);
|
||||
if (hasAccount41Anchor && (hasGoodsLexeme || hasBalanceLexeme || hasRequestCue || hasInventoryAsOfCue(text))) {
|
||||
return true;
|
||||
}
|
||||
return (hasGoodsLexeme || hasBalanceLexeme || hasColloquialStockSnapshotCue) &&
|
||||
(hasRequestCue || hasBalanceLexeme || hasColloquialStockSnapshotCue);
|
||||
}
|
||||
|
||||
function hasInventoryProvenanceSignal(text: string): boolean {
|
||||
@@ -1590,6 +1610,12 @@ function hasInventoryProvenanceSignalV2(text: string): boolean {
|
||||
return hasItemCue && hasSupplierCue && hasPurchaseCue;
|
||||
}
|
||||
|
||||
function hasInventoryPurchaseDateSignal(text: string): boolean {
|
||||
const hasItemCue = /(?:товар|номенклатур|sku|item|product)/iu.test(text);
|
||||
const hasPurchaseDateCue = /(?:когда\s+был\s+куплен|когда\s+куплен|дата\s+закупк|purchase\s+date)/iu.test(text);
|
||||
return hasItemCue && hasPurchaseDateCue;
|
||||
}
|
||||
|
||||
function hasInventoryPurchaseDocumentsSignalV2(text: string): boolean {
|
||||
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(
|
||||
@@ -1607,25 +1633,48 @@ function hasInventorySaleTraceSignalV2(text: string): boolean {
|
||||
}
|
||||
|
||||
function hasInventorySupplierStockOverlapSignal(text: string): boolean {
|
||||
const hasDirectSingleItemSupplierQuestion =
|
||||
/(?:от\s+какого\s+поставщика\s+куплен\s+(?:товар|номенклатур(?:а|у|ы)|позици(?:я|ю|и))|от\s+кого\s+куплен\s+(?:товар|номенклатур(?:а|у|ы)|позици(?:я|ю|и)))/iu.test(
|
||||
text
|
||||
);
|
||||
if (hasDirectSingleItemSupplierQuestion) {
|
||||
return false;
|
||||
}
|
||||
const hasSupplierCue = /(?:поставщик|supplier|vendor|от\s+поставщика|у\s+поставщика)/iu.test(text);
|
||||
const hasStockCue = /(?:товар|номенклатур|склад|остат(?:ок|ки)|лежат|на\s+дату|по\s+состоянию\s+на\s+дату|current\s+stock|stock\s+overlap|что\s+сейчас\s+лежит)/iu.test(
|
||||
const hasStockCue = /(?:склад|остат(?:ок|ке|ков)|лежат|лежит|сейчас\s+еще|сейчас\s+ещ[её]|на\s+дату|по\s+состоянию\s+на\s+дату|current\s+stock|stock\s+overlap|что\s+сейчас\s+лежит)/iu.test(
|
||||
text
|
||||
);
|
||||
return hasSupplierCue && hasStockCue;
|
||||
}
|
||||
|
||||
function hasInventoryAgingSignal(text: string): boolean {
|
||||
return /(?:стар(?:ые|ым|ых)\s+закупк|закупал(?:ись|ся)\s+очень\s+давно|очень\s+давно|давно\s+куплен|когда\s+куплен|возраст\s+остатк|aged?\s+stock|old\s+purchase|aging\s+by\s+purchase\s+date|very\s+old\s+stock)/iu.test(
|
||||
text
|
||||
);
|
||||
const hasResidueCue =
|
||||
/(?:остат(?:ок|ки)|в\s+остатке|среди\s+текущих\s+остатков|на\s+складе|stock\s+residue|stock\s+balance)/iu.test(text);
|
||||
const hasAgingCue =
|
||||
/(?:стар(?:ые|ым|ых)\s+закупк|стары(?:м|х)\s+закупк(?:ам|и|ах)|относит(?:ся|ся\s+ли)?\s+.*\s+к\s+старым\s+закупк|закупал(?:ись|ся)\s+очень\s+давно|очень\s+давно|давно\s+куплен|давно\s+приобретен|куплен\s+задолго\s+до(?:\s+даты)?|закуплен(?:ы|а)?\s+давно|приобретен\s+давно|задолго\s+до(?:\s+даты)?|возраст\s+остатк|возраст\s+закупк|aged?\s+stock|old\s+purchase|old\s+purchases|old\s+stock|bought\s+long\s+ago|purchased\s+long\s+ago|aging\s+by\s+purchase\s+date|very\s+old\s+stock|very\s+old\s+purchase|old\s+procurement|older\s+purchases|aged\s+items|old\s+goods)/iu.test(
|
||||
text
|
||||
);
|
||||
return hasAgingCue || (hasResidueCue && /(?:давно\s+куплен|давно\s+приобретен|задолго\s+до)/iu.test(text));
|
||||
}
|
||||
|
||||
function hasInventoryPurchaseToSaleChainSignal(text: string): boolean {
|
||||
const hasSupplierCue = /(?:поставщик|supplier|vendor|от\s+кого\s+куплен)/iu.test(text);
|
||||
const hasBuyerCue = /(?:покупател|buyer|customer|client|кому\s+был\s+продан)/iu.test(text);
|
||||
const hasItemCue = /(?:товар|номенклатур|sku|item|product)/iu.test(text);
|
||||
const hasPurchaseSaleCue = /(?:куплен(?:ы)?|закупк|позже\s+продан(?:ы)?|продан(?:ы)?|purchase|sale|цепочк[аи]\s+движен)/iu.test(text);
|
||||
return (hasSupplierCue && hasBuyerCue && hasItemCue && hasPurchaseSaleCue) || /(?:purchase[\s-]?to[\s-]?sale\s+chain|закупка\s*->\s*склад\s*->\s*продажа)/iu.test(text);
|
||||
const hasChainCue =
|
||||
/(?:закупк.*склад.*продаж|purchase[\s-]?to[\s-]?sale|purchase\s*->\s*(?:warehouse|stock)\s*->\s*sale|закупка\s*->\s*склад\s*->\s*продажа|цепочк[аи]\s+движен|документально\s+подтвержденн\w+\s+цепочк|supplier\s*->\s*item\s*->\s*(?:buyer|customer)|supplier\s+to\s+buyer|supplier\s+to\s+item\s+to\s+buyer)/iu.test(
|
||||
text
|
||||
) || text.includes("->");
|
||||
return hasItemCue && hasChainCue;
|
||||
}
|
||||
|
||||
function hasInventorySupplierToBuyerChainSignal(text: string): boolean {
|
||||
const hasSupplierCue = /(?:поставщик|supplier|vendor)/iu.test(text);
|
||||
const hasBuyerCue = /(?:покупател|buyer|customer|client)/iu.test(text);
|
||||
const hasItemCue = /(?:товар|номенклатур|sku|item|product)/iu.test(text);
|
||||
const hasChainCue =
|
||||
/(?:документально\s+подтвержденн\w+\s+цепочк|supplier\s*->\s*item\s*->\s*buyer|supplier\s*->\s*item\s*->\s*customer|supplier\s*->\s*buyer|supplier\s+to\s+buyer|supplier\s+to\s+buyer\s+chain|supplier\s+to\s+item\s+to\s+buyer|поставщик\s*->\s*товар\s*->\s*покупател|поставщик\s*->\s*товар\s*->\s*клиент|поставщик\s*->\s*товар\s*->\s*покупатель|поставщик\s+к\s+покупател|поставщик\s+к\s+клиент|поставщик\s+к\s+товару\s+и\s+покупателю)/iu.test(
|
||||
text
|
||||
) || text.includes("->");
|
||||
return hasSupplierCue && hasBuyerCue && hasItemCue && hasChainCue;
|
||||
}
|
||||
|
||||
export function resolveAddressIntent(userMessage: string): AddressIntentResolution {
|
||||
@@ -1745,27 +1794,35 @@ export function resolveAddressIntent(userMessage: string): AddressIntentResoluti
|
||||
};
|
||||
}
|
||||
|
||||
if (hasInventoryProvenanceSignalV2(text)) {
|
||||
if (
|
||||
/(?:старым\s+закупк(?:ам|и|ах)|относится\s+ли\s+.*\s+к\s+старым\s+закупк(?:ам|и|ах)|очень\s+давно|давно\s+куплен|давно\s+приобретен|old\s+stock|old\s+purchase|aging\s+by\s+purchase\s+date)/iu.test(
|
||||
text
|
||||
)
|
||||
) {
|
||||
return {
|
||||
intent: "inventory_purchase_provenance_for_item",
|
||||
confidence: "medium",
|
||||
reasons: ["inventory_provenance_signal_detected"]
|
||||
intent: "inventory_aging_by_purchase_date",
|
||||
confidence: "high",
|
||||
reasons: ["inventory_aging_signal_detected_strong"]
|
||||
};
|
||||
}
|
||||
|
||||
if (hasInventoryPurchaseDocumentsSignalV2(text)) {
|
||||
if (hasInventoryAccount41Anchor(text) && hasInventoryAsOfCue(text)) {
|
||||
return {
|
||||
intent: "inventory_purchase_documents_for_item",
|
||||
confidence: "medium",
|
||||
reasons: ["inventory_purchase_documents_signal_detected"]
|
||||
intent: "inventory_on_hand_as_of_date",
|
||||
confidence: "high",
|
||||
reasons: ["inventory_account_41_as_of_date_signal_detected"]
|
||||
};
|
||||
}
|
||||
|
||||
if (hasInventoryPurchaseToSaleChainSignal(text)) {
|
||||
if (
|
||||
/(?:без\s+понятн(?:ой|ого)\s+привязк(?:и|а)\s+к\s+поставщик|без\s+привязк(?:и|а)\s+к\s+поставщик|unresolved\s+supplier\s+link)/iu.test(
|
||||
text
|
||||
)
|
||||
) {
|
||||
return {
|
||||
intent: "inventory_purchase_to_sale_chain",
|
||||
intent: "inventory_supplier_stock_overlap_as_of_date",
|
||||
confidence: "medium",
|
||||
reasons: ["inventory_purchase_to_sale_chain_signal_detected"]
|
||||
reasons: ["inventory_unresolved_provenance_signal_detected"]
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1777,6 +1834,29 @@ export function resolveAddressIntent(userMessage: string): AddressIntentResoluti
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
/(?:supplier\s*->\s*buyer|supplier\s+to\s+buyer|supplier\s+to\s+buyer\s+chain|поставщик\s+к\s+покупателю|поставщик\s*->\s*товар\s*->\s*покупател|документально\s+подтвержденн\w+\s+цепочк)/iu.test(
|
||||
text
|
||||
) &&
|
||||
/(?:поставщик|supplier|vendor)/iu.test(text) &&
|
||||
/(?:покупател|buyer|customer|client)/iu.test(text) &&
|
||||
/(?:товар|номенклатур|sku|item|product)/iu.test(text)
|
||||
) {
|
||||
return {
|
||||
intent: "inventory_purchase_to_sale_chain",
|
||||
confidence: "high",
|
||||
reasons: ["inventory_supplier_to_buyer_chain_signal_detected_strong"]
|
||||
};
|
||||
}
|
||||
|
||||
if (hasInventoryPurchaseToSaleChainSignal(text)) {
|
||||
return {
|
||||
intent: "inventory_purchase_to_sale_chain",
|
||||
confidence: "medium",
|
||||
reasons: ["inventory_purchase_to_sale_chain_signal_detected"]
|
||||
};
|
||||
}
|
||||
|
||||
if (hasInventoryAgingSignal(text)) {
|
||||
return {
|
||||
intent: "inventory_aging_by_purchase_date",
|
||||
@@ -1785,6 +1865,30 @@ export function resolveAddressIntent(userMessage: string): AddressIntentResoluti
|
||||
};
|
||||
}
|
||||
|
||||
if (hasInventoryProvenanceSignalV2(text)) {
|
||||
return {
|
||||
intent: "inventory_purchase_provenance_for_item",
|
||||
confidence: "medium",
|
||||
reasons: ["inventory_provenance_signal_detected"]
|
||||
};
|
||||
}
|
||||
|
||||
if (hasInventoryPurchaseDateSignal(text)) {
|
||||
return {
|
||||
intent: "inventory_purchase_provenance_for_item",
|
||||
confidence: "medium",
|
||||
reasons: ["inventory_purchase_date_signal_detected"]
|
||||
};
|
||||
}
|
||||
|
||||
if (hasInventoryPurchaseDocumentsSignalV2(text)) {
|
||||
return {
|
||||
intent: "inventory_purchase_documents_for_item",
|
||||
confidence: "medium",
|
||||
reasons: ["inventory_purchase_documents_signal_detected"]
|
||||
};
|
||||
}
|
||||
|
||||
if (hasInventorySaleTraceSignalV2(text)) {
|
||||
return {
|
||||
intent: "inventory_sale_trace_for_item",
|
||||
@@ -1793,6 +1897,14 @@ export function resolveAddressIntent(userMessage: string): AddressIntentResoluti
|
||||
};
|
||||
}
|
||||
|
||||
if (hasInventorySupplierToBuyerChainSignal(text)) {
|
||||
return {
|
||||
intent: "inventory_purchase_to_sale_chain",
|
||||
confidence: "medium",
|
||||
reasons: ["inventory_supplier_to_buyer_chain_signal_detected"]
|
||||
};
|
||||
}
|
||||
|
||||
if (hasInventoryOnHandSignal(text)) {
|
||||
return {
|
||||
intent: "inventory_on_hand_as_of_date",
|
||||
|
||||
Reference in New Issue
Block a user