ДОМЕНЫ - ВОПРОСЫ - СКЛАД - Систематизировать ответы по поставщику без поставок через анализ оплат и возвратов

This commit is contained in:
2026-04-17 02:08:02 +03:00
parent a3a61b3a0f
commit 44f1c1e11e
33 changed files with 22512 additions and 173 deletions
@@ -618,7 +618,7 @@ function hasVatLiabilityConfirmedTaxPeriodSignal(text: string): boolean {
return false;
}
const hasPaymentCue =
/(?:к\s+уплате|надо|нужно|заплатить|уплатить|плат[её]ж|платежку|в\s+налогов|в\s+бюджет|должн[аы]?\s+заплатить|мы\s+должн[аы]?|должн[аы]?\s+мы)/iu.test(
/(?:к\s+уплате|надо|нужно|заплатить|уплатить|плат[её]ж|платежку|в\s+налогов|в\s+бюджет|должн[аы]?\s+заплатить|мы\s+должн[аы]?|должн[аы]?\s+мы|сгруз(?:ить|им|ишь|ите|ил|ила|или|ка))/iu.test(
text
);
if (!hasPaymentCue) {
@@ -656,14 +656,14 @@ function hasVatPayableConfirmedSignal(text: string): boolean {
return false;
}
const hasPaymentCue =
/(?:к\s+уплате|надо|нужно|заплатить|уплатить|плат[её]ж|платежку|в\s+налогов|в\s+бюджет|должн[аы]?\s+заплатить|мы\s+должн[аы]?|должн[аы]?\s+мы)/iu.test(
/(?:к\s+уплате|надо|нужно|заплатить|уплатить|плат[её]ж|платежку|в\s+налогов|в\s+бюджет|должн[аы]?\s+заплатить|мы\s+должн[аы]?|должн[аы]?\s+мы|сгруз(?:ить|им|ишь|ите|ил|ила|или|ка))/iu.test(
text
);
if (!hasPaymentCue) {
return false;
}
const hasDateOrPeriodCue =
/(?:на\s+дат|по\s+состоянию|на\s+конец|за\s+(?:\d{4}|январ|феврал|март|апрел|май|июн|июл|август|сентябр|октябр|ноябр|декабр)|квартал|месяц|год|период|\b\d{4}[./-]\d{2}[./-]\d{2}\b)/iu.test(
/(?:на\s+дат|по\s+состоянию|на\s+конец|за\s+(?:\d{4}|январ|феврал|март|апрел|май|июн|июл|август|сентябр|октябр|ноябр|декабр)|на\s+(?:январ|феврал|март|апрел|май|июн|июл|август|сентябр|октябр|ноябр|декабр)\S*(?:\s+(?:19|20)\d{2})?|квартал|месяц|год|период|\b\d{4}[./-]\d{2}[./-]\d{2}\b)/iu.test(
text
);
return hasDateOrPeriodCue || /(?:сколько|скока|скок)/iu.test(text);
@@ -784,6 +784,9 @@ function hasCounterpartyDebtLongevitySignal(text: string): boolean {
}
function hasCounterpartyActivityLifecycleSignal(text: string): boolean {
if (hasCustomerRevenueAndPaymentsSignal(text) || hasSupplierPayoutsProfileSignal(text)) {
return false;
}
const hasPaymentRiskLexeme =
/(?:не\s+плат(?:ит|ят|ил|или)|без\s+оплат|оплат(?:ы|а)?\s+нет|нет\s+оплат|задерж(?:ива|к)|просроч|задолж|\bдолг(?:и|ов|а|у)?\b)/iu.test(
text
@@ -837,6 +840,30 @@ function hasCounterpartyActivityLifecycleSignal(text: string): boolean {
return hasCounterpartyLexeme && hasActivityLexeme && (hasTimeWindowLexeme || hasListVerb);
}
function hasCounterpartyShipmentItemFlowSignal(text: string): boolean {
const hasNamedTailAfterShipmentCue =
/(?:отгруж(?:ал|али|ено)|постав(?:лял|ляли|ил|или)|привоз(?:ил|или)|продал)\s+[a-zа-яё][a-zа-яё0-9._-]{2,}/iu.test(
text
);
const hasPartySignal =
hasPartyAnchorMention(text) ||
hasLooseByAnchorMention(text) ||
hasImplicitCounterpartyAnchorAroundDocs(text) ||
hasHeuristicCounterpartyAnchor(text);
if (!hasPartySignal && !hasNamedTailAfterShipmentCue) {
return false;
}
const hasInboundShipmentCue =
/(?:что\s+нам\s+(?:отгруж(?:ал|али|ено)|постав(?:лял|ляли|ил|или)|привоз(?:ил|или)|продал)|кто\s+нам\s+постав(?:лял|ил)|что\s+постав(?:лял|или)\s+нам|что\s+нам\s+поставили)/iu.test(
text
);
const hasItemOrServiceCue =
/(?:како(?:й|е|го|му)\s+товар|каки(?:е|х)\s+товар|какую\s+услуг|какие\s+услуг|товар\s+или\s+услуг|позици(?:ю|и|ях)?)/iu.test(
text
);
return hasInboundShipmentCue || hasItemOrServiceCue;
}
function hasContractUsageOverviewSignal(text: string): boolean {
if (hasAny(text, CONTRACT_USAGE_OVERVIEW_HINTS)) {
return true;
@@ -2021,8 +2048,12 @@ export function resolveAddressIntent(userMessage: string): AddressIntentResoluti
!hasInventoryProvenanceSignalV2(text) &&
!hasInventoryPurchaseDocumentsSignalV2(text) &&
!hasInventorySaleTraceSignalV2(text) &&
/(?:контраг|договор|контракт|counterparty|contract|покупател|клиент|заказчик|customer|client|buyer|supplier|поставщик)/iu.test(
text
(
/(?:контраг|договор|контракт|counterparty|contract|покупател|клиент|заказчик|customer|client|buyer|supplier|поставщик)/iu.test(
text
) ||
hasAccountNumberAnchor(text) ||
hasCompactAccountCodeToken(text)
)
) {
return {
@@ -2164,16 +2195,21 @@ export function resolveAddressIntent(userMessage: string): AddressIntentResoluti
}
if (
hasAny(text, DOCUMENTS_BY_COUNTERPARTY_HINTS) &&
(hasAny(text, DOCUMENTS_BY_COUNTERPARTY_HINTS) || hasCounterpartyShipmentItemFlowSignal(text)) &&
(hasPartyAnchorMention(text) ||
hasLooseByAnchorMention(text) ||
hasImplicitCounterpartyAnchorAroundDocs(text) ||
hasHeuristicCounterpartyAnchor(text))
hasHeuristicCounterpartyAnchor(text) ||
hasCounterpartyShipmentItemFlowSignal(text))
) {
return {
intent: "list_documents_by_counterparty",
confidence: "medium",
reasons: ["documents_by_counterparty_signal_detected"]
reasons: [
hasCounterpartyShipmentItemFlowSignal(text)
? "counterparty_item_flow_signal_detected"
: "documents_by_counterparty_signal_detected"
]
};
}