Post-F: зафиксировать VAT materialization и приоритет явного контрагента

This commit is contained in:
2026-04-23 23:39:55 +03:00
parent 92cd272efc
commit 2f282f1479
6 changed files with 159 additions and 24 deletions
@@ -668,7 +668,7 @@ __WHERE_CLAUSE__
const VAT_LIABILITY_CONFIRMED_TAX_PERIOD_QUERY_TEMPLATE = `
ВЫБРАТЬ
ДАТАВРЕМЯ(2000, 1, 1, 0, 0, 0) КАК Период,
__PERIOD_TO_EXPR__ КАК Период,
"VAT_BOOK_SALES" КАК Регистратор,
"68.02" КАК СчетДт,
"" КАК СчетКт,
@@ -678,7 +678,7 @@ const VAT_LIABILITY_CONFIRMED_TAX_PERIOD_QUERY_TEMPLATE = `
__WHERE_CLAUSE__
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
ДАТАВРЕМЯ(2000, 1, 1, 0, 0, 0) КАК Период,
__PERIOD_TO_EXPR__ КАК Период,
"VAT_BOOK_PURCHASES" КАК Регистратор,
"19" КАК СчетДт,
"" КАК СчетКт,
@@ -1553,10 +1553,19 @@ export function buildAddressRecipePlan(
.replaceAll("__VAT19_DT_MATCH__", buildAccountPrefixPredicate("Движения.СчетДт", VAT_PAYABLE_19_PREFIXES))
.replaceAll("__VAT19_KT_MATCH__", buildAccountPrefixPredicate("Движения.СчетКт", VAT_PAYABLE_19_PREFIXES))
: recipe.query_template === "vat_liability_confirmed_tax_period_profile"
? VAT_LIABILITY_CONFIRMED_TAX_PERIOD_QUERY_TEMPLATE.replaceAll(
"__WHERE_CLAUSE__",
buildManagementWhereClause(filters, "Движения.Период")
)
? (() => {
const periodToExpr =
(typeof filters.period_to === "string" && filters.period_to.trim().length > 0
? toDateTimeExpr(filters.period_to, true)
: null) ??
(typeof filters.period_from === "string" && filters.period_from.trim().length > 0
? toDateTimeExpr(filters.period_from, true)
: null) ??
"ДАТАВРЕМЯ(2000, 1, 1, 0, 0, 0)";
return VAT_LIABILITY_CONFIRMED_TAX_PERIOD_QUERY_TEMPLATE
.replaceAll("__WHERE_CLAUSE__", buildManagementWhereClause(filters, "Движения.Период"))
.replaceAll("__PERIOD_TO_EXPR__", periodToExpr);
})()
: recipe.query_template === "vat_payable_confirmed_as_of_balance_profile"
? (() => {
const asOfExpr =
@@ -1474,16 +1474,31 @@ export function buildAssistantMcpDiscoveryTurnInput(
valueFlowSignal,
metadataSignal: rawMetadataSignal || effectiveMetadataFollowupSeedApplicable,
entityResolutionSignal:
entityResolutionSignal &&
!metadataGroundedDocumentLaneApplicable &&
!metadataGroundedMovementLaneApplicable
entityResolutionSignal &&
!metadataGroundedDocumentLaneApplicable &&
!metadataGroundedMovementLaneApplicable
});
const explicitCurrentCounterpartyCandidate =
normalizedPredecomposeCounterparty && !isReferentialEntityPlaceholder(normalizedPredecomposeCounterparty)
? normalizedPredecomposeCounterparty
: null;
const explicitCurrentCounterpartyOverridesFollowupEntity = Boolean(
explicitCurrentCounterpartyCandidate &&
(followupSeed.counterparty || followupSeed.discoveryEntity) &&
!sameScopedName(explicitCurrentCounterpartyCandidate, followupSeed.counterparty ?? followupSeed.discoveryEntity) &&
(valueFlowSignal ||
lifecycleSignal ||
metadataGroundedDocumentLaneApplicable ||
metadataGroundedMovementLaneApplicable)
);
const metadataLaneScopeHint =
rawMetadataScopeHint ??
followupSeed.metadataScopeHint ??
followupSeed.discoveryEntity ??
followupSeed.metadataSelectedEntitySet ??
null;
explicitCurrentCounterpartyOverridesFollowupEntity
? null
: rawMetadataScopeHint ??
followupSeed.metadataScopeHint ??
followupSeed.discoveryEntity ??
followupSeed.metadataSelectedEntitySet ??
null;
const metadataScopedLaneWithoutSubject = Boolean(
(metadataGroundedMovementLaneApplicable || metadataGroundedDocumentLaneApplicable) &&
!followupSeed.counterparty &&
@@ -1491,7 +1506,9 @@ export function buildAssistantMcpDiscoveryTurnInput(
);
const groundedFollowupEntity = metadataScopedLaneWithoutSubject
? null
: followupSeed.counterparty ?? followupSeed.discoveryEntity;
: explicitCurrentCounterpartyOverridesFollowupEntity
? null
: followupSeed.counterparty ?? followupSeed.discoveryEntity;
const entityCandidates = entityResolutionSignal ? [] : [];
if (entityResolutionSignal) {
pushNormalizedEntityResolutionCandidate(entityCandidates, entityResolutionClarificationCandidate);
@@ -1548,6 +1565,27 @@ export function buildAssistantMcpDiscoveryTurnInput(
valueFlowOrganizationStaysScope || !openScopeValueFlowWithoutCounterparty
? currentTurnOrganizationScope ?? followupSeed.organization
: null;
if (
explicitCurrentCounterpartyCandidate &&
(valueFlowSignal || lifecycleSignal || metadataGroundedDocumentLaneApplicable || metadataGroundedMovementLaneApplicable)
) {
for (let index = entityCandidates.length - 1; index >= 0; index -= 1) {
const candidate = entityCandidates[index];
if (!candidate || sameScopedName(candidate, explicitCurrentCounterpartyCandidate)) {
continue;
}
if (
(metadataLaneScopeHint && sameScopedName(candidate, metadataLaneScopeHint)) ||
(explicitOrganizationScope && sameScopedName(candidate, explicitOrganizationScope)) ||
(followupSeed.organization && sameScopedName(candidate, followupSeed.organization)) ||
(followupSeed.counterparty &&
!sameScopedName(followupSeed.counterparty, explicitCurrentCounterpartyCandidate) &&
sameScopedName(candidate, followupSeed.counterparty))
) {
entityCandidates.splice(index, 1);
}
}
}
if (valueFlowOrganizationStaysScope && explicitOrganizationScope) {
for (let index = entityCandidates.length - 1; index >= 0; index -= 1) {
if (entityCandidates[index] === explicitOrganizationScope) {