Post-F: зафиксировать VAT materialization и приоритет явного контрагента
This commit is contained in:
parent
92cd272efc
commit
2f282f1479
|
|
@ -645,7 +645,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" КАК СчетДт,
|
||||
"" КАК СчетКт,
|
||||
|
|
@ -655,7 +655,7 @@ const VAT_LIABILITY_CONFIRMED_TAX_PERIOD_QUERY_TEMPLATE = `
|
|||
__WHERE_CLAUSE__
|
||||
ОБЪЕДИНИТЬ ВСЕ
|
||||
ВЫБРАТЬ
|
||||
ДАТАВРЕМЯ(2000, 1, 1, 0, 0, 0) КАК Период,
|
||||
__PERIOD_TO_EXPR__ КАК Период,
|
||||
"VAT_BOOK_PURCHASES" КАК Регистратор,
|
||||
"19" КАК СчетДт,
|
||||
"" КАК СчетКт,
|
||||
|
|
@ -1395,7 +1395,18 @@ function buildAddressRecipePlan(recipe, filters) {
|
|||
.replaceAll("__VAT19_DT_MATCH__", buildAccountPrefixPredicate("Движения.СчетДт", config_1.VAT_PAYABLE_19_PREFIXES))
|
||||
.replaceAll("__VAT19_KT_MATCH__", buildAccountPrefixPredicate("Движения.СчетКт", config_1.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 = (typeof filters.as_of_date === "string" && filters.as_of_date.trim().length > 0
|
||||
|
|
|
|||
|
|
@ -1120,7 +1120,19 @@ function buildAssistantMcpDiscoveryTurnInput(input) {
|
|||
!metadataGroundedDocumentLaneApplicable &&
|
||||
!metadataGroundedMovementLaneApplicable
|
||||
});
|
||||
const metadataLaneScopeHint = rawMetadataScopeHint ??
|
||||
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 = explicitCurrentCounterpartyOverridesFollowupEntity
|
||||
? null
|
||||
: rawMetadataScopeHint ??
|
||||
followupSeed.metadataScopeHint ??
|
||||
followupSeed.discoveryEntity ??
|
||||
followupSeed.metadataSelectedEntitySet ??
|
||||
|
|
@ -1129,6 +1141,8 @@ function buildAssistantMcpDiscoveryTurnInput(input) {
|
|||
!followupSeed.counterparty &&
|
||||
metadataLaneCarryoverAvailable);
|
||||
const groundedFollowupEntity = metadataScopedLaneWithoutSubject
|
||||
? null
|
||||
: explicitCurrentCounterpartyOverridesFollowupEntity
|
||||
? null
|
||||
: followupSeed.counterparty ?? followupSeed.discoveryEntity;
|
||||
const entityCandidates = entityResolutionSignal ? [] : [];
|
||||
|
|
@ -1179,6 +1193,23 @@ function buildAssistantMcpDiscoveryTurnInput(input) {
|
|||
const explicitOrganizationScope = 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) {
|
||||
|
|
|
|||
|
|
@ -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 =
|
||||
|
|
|
|||
|
|
@ -1478,8 +1478,23 @@ export function buildAssistantMcpDiscoveryTurnInput(
|
|||
!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 ??
|
||||
explicitCurrentCounterpartyOverridesFollowupEntity
|
||||
? null
|
||||
: rawMetadataScopeHint ??
|
||||
followupSeed.metadataScopeHint ??
|
||||
followupSeed.discoveryEntity ??
|
||||
followupSeed.metadataSelectedEntitySet ??
|
||||
|
|
@ -1490,6 +1505,8 @@ export function buildAssistantMcpDiscoveryTurnInput(
|
|||
metadataLaneCarryoverAvailable
|
||||
);
|
||||
const groundedFollowupEntity = metadataScopedLaneWithoutSubject
|
||||
? null
|
||||
: explicitCurrentCounterpartyOverridesFollowupEntity
|
||||
? null
|
||||
: followupSeed.counterparty ?? followupSeed.discoveryEntity;
|
||||
const entityCandidates = entityResolutionSignal ? [] : [];
|
||||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -5177,6 +5177,8 @@ describe("address recipe catalog counterparty filtering", () => {
|
|||
expect(plan.query).toContain("РегистрНакопления.НДСЗаписиКнигиПокупок");
|
||||
expect(plan.query).toContain("VAT_BOOK_SALES");
|
||||
expect(plan.query).toContain("VAT_BOOK_PURCHASES");
|
||||
expect(plan.query).toContain("ДАТАВРЕМЯ(2019, 12, 31, 23, 59, 59)");
|
||||
expect(plan.query).not.toContain("ДАТАВРЕМЯ(2000, 1, 1, 0, 0, 0) КАК Период");
|
||||
});
|
||||
|
||||
it("keeps inventory-on-hand phrasing in address lane", () => {
|
||||
|
|
|
|||
|
|
@ -133,6 +133,50 @@ describe("assistant MCP discovery turn input adapter", () => {
|
|||
expect(result.reason_codes).not.toContain("mcp_discovery_payout_signal_detected");
|
||||
});
|
||||
|
||||
it("prefers the explicit current-turn counterparty over stale organization-scoped carryover in net follow-up discovery", () => {
|
||||
const result = buildAssistantMcpDiscoveryTurnInput({
|
||||
userMessage: "какое нетто по деньгам с Группа СВК за 2020 год: сколько получили и сколько заплатили?",
|
||||
assistantTurnMeaning: {
|
||||
asked_domain_family: "counterparty_value",
|
||||
asked_action_family: "net_value_flow",
|
||||
explicit_entity_candidates: ["Альтернатива Плюс"],
|
||||
explicit_organization_scope: "ООО Альтернатива Плюс",
|
||||
explicit_date_scope: "2020",
|
||||
unsupported_but_understood_family: "counterparty_bidirectional_value_flow_or_netting",
|
||||
stale_replay_forbidden: true
|
||||
},
|
||||
predecomposeContract: {
|
||||
entities: { counterparty: "Группа СВК" },
|
||||
period: { period_from: "2020-01-01", period_to: "2020-12-31" }
|
||||
},
|
||||
followupContext: {
|
||||
previous_intent: "counterparty_activity_lifecycle",
|
||||
previous_filters: {
|
||||
organization: "ООО Альтернатива Плюс",
|
||||
counterparty: "Альтернатива Плюс",
|
||||
period_from: "2020-01-01",
|
||||
period_to: "2020-12-31"
|
||||
},
|
||||
previous_anchor_type: "organization",
|
||||
previous_anchor_value: "ООО Альтернатива Плюс"
|
||||
}
|
||||
});
|
||||
|
||||
expect(result.adapter_status).toBe("ready");
|
||||
expect(result.should_run_discovery).toBe(true);
|
||||
expect(result.turn_meaning_ref).toMatchObject({
|
||||
asked_domain_family: "counterparty_value",
|
||||
asked_action_family: "net_value_flow",
|
||||
explicit_entity_candidates: ["Группа СВК"],
|
||||
explicit_organization_scope: "ООО Альтернатива Плюс",
|
||||
explicit_date_scope: "2020",
|
||||
unsupported_but_understood_family: "counterparty_bidirectional_value_flow_or_netting",
|
||||
stale_replay_forbidden: true
|
||||
});
|
||||
expect(result.turn_meaning_ref?.metadata_scope_hint).toBeUndefined();
|
||||
expect(result.data_need_graph?.subject_candidates).toEqual(["Группа СВК"]);
|
||||
});
|
||||
|
||||
it("captures monthly aggregation as part of bidirectional value-flow meaning", () => {
|
||||
const result = buildAssistantMcpDiscoveryTurnInput({
|
||||
userMessage: "какое нетто по деньгам с Группа СВК за 2020 год по месяцам: сколько получили и сколько заплатили помесячно?",
|
||||
|
|
|
|||
Loading…
Reference in New Issue