ДОМЕНЫ - ВОПРОСЫ - НДС: развести as-of и tax-period intent, ускорить и стабилизировать VAT source probe, починить M23 тесты
This commit is contained in:
@@ -1031,7 +1031,7 @@ describe("address compose stage utf8 headers", () => {
|
||||
|
||||
expect(reply.text).toContain("Профиль договорной базы собран");
|
||||
expect(reply.text).toContain("Всего договоров в базе: 520.");
|
||||
expect(reply.text).toContain("�?Использованных договоров (есть factual связь с операциями): 148.");
|
||||
expect(reply.text).toContain("Использованных договоров (есть factual связь с операциями): 148.");
|
||||
expect(reply.text).toContain("Неиспользуемых договоров: 372.");
|
||||
});
|
||||
|
||||
@@ -1458,6 +1458,42 @@ describe("address compose stage utf8 headers", () => {
|
||||
expect(reply.text).toContain("РегистрНакопления.НДСПродажи");
|
||||
});
|
||||
|
||||
it("builds confirmed VAT tax-period reply from sales and purchase book markers", () => {
|
||||
const reply = composeFactualReply(
|
||||
"vat_liability_confirmed_for_tax_period",
|
||||
[
|
||||
{
|
||||
period: "2019-12-31T23:59:59Z",
|
||||
registrator: "VAT_BOOK_SALES",
|
||||
account_dt: "68.02",
|
||||
account_kt: "",
|
||||
amount: 120000,
|
||||
analytics: []
|
||||
},
|
||||
{
|
||||
period: "2019-12-31T23:59:59Z",
|
||||
registrator: "VAT_BOOK_PURCHASES",
|
||||
account_dt: "19",
|
||||
account_kt: "",
|
||||
amount: 70000,
|
||||
analytics: []
|
||||
}
|
||||
],
|
||||
{
|
||||
userMessage: "сколько платить ндс в налоговую за декабрь 2019",
|
||||
periodFrom: "2019-10-01",
|
||||
periodTo: "2019-12-31",
|
||||
useRubCurrency: true
|
||||
}
|
||||
);
|
||||
|
||||
expect(reply.responseType).toBe("FACTUAL_SUMMARY");
|
||||
expect(reply.text).toContain("Собран подтвержденный расчет НДС к уплате за налоговый период");
|
||||
expect(reply.text).toContain("50.000,00 ₽");
|
||||
expect(reply.semantics?.result_mode).toBe("confirmed_balance");
|
||||
expect(reply.semantics?.balance_confirmed).toBe(true);
|
||||
});
|
||||
|
||||
it("formats VAT forecast amounts in rubles and emphasizes numbers when requested", () => {
|
||||
const reply = composeFactualReply(
|
||||
"vat_payable_forecast",
|
||||
@@ -1482,6 +1518,80 @@ describe("address compose stage utf8 headers", () => {
|
||||
expect(reply.text).toContain("Собран прогноз НДС к уплате:");
|
||||
});
|
||||
|
||||
it("does not split dates and list numbering when numeric emphasis is enabled", () => {
|
||||
const reply = composeFactualReply(
|
||||
"vat_payable_forecast",
|
||||
[
|
||||
{
|
||||
period: "2019-12-31T23:59:59Z",
|
||||
registrator: "VAT_68_CREDIT",
|
||||
account_dt: "68",
|
||||
account_kt: "",
|
||||
amount: 0,
|
||||
analytics: []
|
||||
},
|
||||
{
|
||||
period: "2019-12-31T23:59:59Z",
|
||||
registrator: "VAT_68_DEBIT",
|
||||
account_dt: "68",
|
||||
account_kt: "",
|
||||
amount: 0,
|
||||
analytics: []
|
||||
}
|
||||
],
|
||||
{
|
||||
userMessage: "почему по ндс ноль",
|
||||
periodFrom: "2019-12-01",
|
||||
periodTo: "2019-12-31",
|
||||
emphasizeNumbers: true
|
||||
}
|
||||
);
|
||||
|
||||
expect(reply.text).toContain("Период оценки: 01.12.2019..31.12.2019.");
|
||||
expect(reply.text).not.toContain("**01**.**12**.**2019**");
|
||||
expect(reply.text).toContain("1) Проверьте ОСВ/анализ счета");
|
||||
expect(reply.text).not.toContain("**1**)");
|
||||
});
|
||||
|
||||
it("keeps VAT probe timestamps intact when numeric emphasis is enabled", () => {
|
||||
const reply = composeFactualReply(
|
||||
"vat_payable_forecast",
|
||||
[
|
||||
{
|
||||
period: "2019-12-31T23:59:59Z",
|
||||
registrator: "VAT_68_CREDIT",
|
||||
account_dt: "68",
|
||||
account_kt: "",
|
||||
amount: 1000,
|
||||
analytics: []
|
||||
}
|
||||
],
|
||||
{
|
||||
userMessage: "прикинь ндс",
|
||||
emphasizeNumbers: true,
|
||||
vatDirectSourceProbe: {
|
||||
status: "ok",
|
||||
objectsTotal: 1,
|
||||
documentsTotal: 0,
|
||||
registersTotal: 1,
|
||||
probedSources: [
|
||||
{
|
||||
fullName: "РегистрНакопления.НДСПредъявленный",
|
||||
objectType: "register",
|
||||
status: "ok",
|
||||
rowsFetched: 1,
|
||||
lastPeriod: "2019-12-31T23:59:59Z"
|
||||
}
|
||||
],
|
||||
errors: []
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
expect(reply.text).toContain("последнее движение: 2019-12-31T23:59:59Z");
|
||||
expect(reply.text).not.toContain("2019****-12**-31T23:**59**:59Z");
|
||||
});
|
||||
|
||||
it("adds MCP VAT source probe block for confirmed VAT as-of response", () => {
|
||||
const reply = composeFactualReply(
|
||||
"vat_payable_confirmed_as_of_date",
|
||||
@@ -1972,7 +2082,7 @@ describe("address intent resolver expansion (M2.3a)", () => {
|
||||
expect(result.reasons).toContain("forecast_tax_signal_detected");
|
||||
});
|
||||
|
||||
it("resolves colloquial VAT payable estimate wording without explicit 'прогноз'", () => {
|
||||
it("keeps colloquial VAT payment wording in forecast intent when tax-authority cue is absent", () => {
|
||||
const result = resolveAddressIntent("мож прикинусь плиз скока ндс надо заплатить на 15 марта 2020 года");
|
||||
expect(result.intent).toBe("vat_payable_forecast");
|
||||
expect(result.reasons).toContain("forecast_tax_signal_detected");
|
||||
@@ -2215,6 +2325,16 @@ describe("address filter extraction for balance drilldown", () => {
|
||||
expect(extracted.warnings).toContain("period_to_derived_from_as_of_date_for_vat_forecast");
|
||||
});
|
||||
|
||||
it("derives full tax quarter window for confirmed VAT tax-period intent from month phrase", () => {
|
||||
const extracted = extractAddressFilters(
|
||||
"сколько ндс надо заплатить в налоговую за декабрь 2019",
|
||||
"vat_liability_confirmed_for_tax_period"
|
||||
);
|
||||
expect(extracted.extracted_filters.period_from).toBe("2019-10-01");
|
||||
expect(extracted.extracted_filters.period_to).toBe("2019-12-31");
|
||||
expect(extracted.warnings).toContain("period_derived_from_tax_quarter_for_confirmed_vat_liability");
|
||||
});
|
||||
|
||||
it("derives VAT forecast quarter-to-date window for explicit day+month+year phrase", () => {
|
||||
const extracted = extractAddressFilters(
|
||||
"сколько НДС нужно заплатить за 5 марта 2017 года",
|
||||
@@ -2503,7 +2623,7 @@ describe("address filter extraction for balance drilldown", () => {
|
||||
|
||||
it("repairs mojibake phrase before extracting counterparty filters", () => {
|
||||
const result = extractAddressFilters(
|
||||
"Показать доку�?енты СВК за 2020 год.",
|
||||
"Показать документы СВК за 2020 год.",
|
||||
"list_documents_by_counterparty"
|
||||
);
|
||||
expect(result.extracted_filters.counterparty).toBe("СВК");
|
||||
@@ -3050,10 +3170,11 @@ describe("address query limited taxonomy and stage diagnostics", { timeout: 1500
|
||||
expect(result?.debug.selected_recipe).toBe("address_vat_payable_forecast_v1");
|
||||
expect(result?.debug.limited_reason_category).not.toBe("unsupported");
|
||||
expect(result?.debug.mcp_call_status).not.toBe("skipped");
|
||||
expect(result?.debug.route_expectation_status).toBe("matched");
|
||||
expect(result?.debug.extracted_filters.counterparty).toBeUndefined();
|
||||
});
|
||||
|
||||
it("routes colloquial VAT payable estimate wording into VAT forecast recipe", async () => {
|
||||
it("routes colloquial VAT payment wording without tax-authority cue into VAT forecast recipe", async () => {
|
||||
const service = new AddressQueryService();
|
||||
const result = await service.tryHandle("мож прикинусь плиз скока ндс надо заплатить на 15 марта 2020 года");
|
||||
expect(result?.handled).toBe(true);
|
||||
@@ -3061,6 +3182,18 @@ describe("address query limited taxonomy and stage diagnostics", { timeout: 1500
|
||||
expect(result?.debug.selected_recipe).toBe("address_vat_payable_forecast_v1");
|
||||
expect(result?.debug.limited_reason_category).not.toBe("unsupported");
|
||||
expect(result?.debug.mcp_call_status).not.toBe("skipped");
|
||||
expect(result?.debug.route_expectation_status).toBe("matched");
|
||||
});
|
||||
|
||||
it("routes 'в налоговую за декабрь' VAT wording into confirmed tax-period route", async () => {
|
||||
const service = new AddressQueryService();
|
||||
const result = await service.tryHandle("прикинь скок надо заплатить ндс в налоговую на декабрь 2019");
|
||||
expect(result?.handled).toBe(true);
|
||||
expect(result?.debug.detected_intent).toBe("vat_liability_confirmed_for_tax_period");
|
||||
expect(result?.debug.selected_recipe).toBe("address_vat_liability_confirmed_tax_period_v1");
|
||||
expect(result?.debug.extracted_filters.period_from).toBe("2019-10-01");
|
||||
expect(result?.debug.extracted_filters.period_to).toBe("2019-12-31");
|
||||
expect(result?.debug.route_expectation_status).toBe("matched");
|
||||
});
|
||||
|
||||
it("routes customer lifecycle question into dedicated aggregate recipe", async () => {
|
||||
@@ -3648,7 +3781,7 @@ describe("address recipe catalog counterparty filtering", () => {
|
||||
expect(plan.query).toContain("DOC_TYPE_DOCS");
|
||||
expect(plan.query).toContain("SECTION_DT_OPS");
|
||||
expect(plan.query).toContain("SECTION_KT_OPS");
|
||||
expect(plan.query).toContain("СГРУПП�?РОВАТЬ ПО\n Движения.СчетДт");
|
||||
expect(plan.query).toContain("СГРУППИРОВАТЬ ПО\n Движения.СчетДт");
|
||||
expect(plan.query).not.toContain("ЛЕВ(Движения.СчетДт.Код, 2)");
|
||||
});
|
||||
|
||||
@@ -3721,7 +3854,7 @@ describe("address recipe catalog counterparty filtering", () => {
|
||||
|
||||
expect(plan.recipe.recipe_id).toBe("address_contracts_by_counterparty_v1");
|
||||
expect(plan.query).toContain("Справочник.ДоговорыКонтрагентов");
|
||||
expect(plan.query).toContain("ПРЕДСТАВЛЕН�?Е(Договоры.Владелец)");
|
||||
expect(plan.query).toContain("ПРЕДСТАВЛЕНИЕ(Договоры.Владелец)");
|
||||
});
|
||||
|
||||
it("selects counterparty lifecycle recipe and keeps activity marker", () => {
|
||||
@@ -3756,7 +3889,7 @@ describe("address recipe catalog counterparty filtering", () => {
|
||||
counterparty: "Жуковка 51",
|
||||
sort: "period_asc"
|
||||
});
|
||||
expect(plan.query).toContain("УПОРЯДОЧ�?ТЬ ПО");
|
||||
expect(plan.query).toContain("УПОРЯДОЧИТЬ ПО");
|
||||
expect(plan.query).toContain("Период ВОЗР");
|
||||
});
|
||||
|
||||
@@ -3822,7 +3955,7 @@ describe("address recipe catalog counterparty filtering", () => {
|
||||
|
||||
expect(plan.query).toContain("Документ.СписаниеСРасчетногоСчета");
|
||||
expect(plan.query).toContain("Документ.ПоступлениеНаРасчетныйСчет");
|
||||
expect(plan.query).toContain("ПРЕДСТАВЛЕН�?Е(БанкПоступление.ДоговорКонтрагента) КАК Договор");
|
||||
expect(plan.query).toContain("ПРЕДСТАВЛЕНИЕ(БанкПоступление.ДоговорКонтрагента) КАК Договор");
|
||||
});
|
||||
|
||||
it("allows extended limit for open-contracts intent", () => {
|
||||
@@ -3880,8 +4013,23 @@ describe("address recipe catalog counterparty filtering", () => {
|
||||
expect(plan.query).toContain("ПОДСТРОКА(ЕСТЬNULL(Движения.СчетДт.Код, \"\"), 1, 4) = \"68.2\"");
|
||||
expect(plan.query).toContain("ПОДСТРОКА(ЕСТЬNULL(Движения.СчетДт.Код, \"\"), 1, 2) = \"19\"");
|
||||
expect(plan.query).toContain("ПОДСТРОКА(ЕСТЬNULL(Движения.СчетКт.Код, \"\"), 1, 2) = \"19\"");
|
||||
expect(plan.query).not.toContain("ПРЕДСТАВЛЕН�?Е(Движения.СчетКт) ПОДОБНО");
|
||||
expect(plan.query).not.toContain("ПРЕДСТАВЛЕН�?Е(Движения.СчетДт) ПОДОБНО");
|
||||
expect(plan.query).not.toContain("ПРЕДСТАВЛЕНИЕ(Движения.СчетКт) ПОДОБНО");
|
||||
expect(plan.query).not.toContain("ПРЕДСТАВЛЕНИЕ(Движения.СчетДт) ПОДОБНО");
|
||||
});
|
||||
|
||||
it("builds confirmed VAT tax-period query from sales and purchase VAT books", () => {
|
||||
const filters = extractAddressFilters(
|
||||
"сколько ндс надо заплатить в налоговую за декабрь 2019",
|
||||
"vat_liability_confirmed_for_tax_period"
|
||||
).extracted_filters;
|
||||
const selected = selectAddressRecipe("vat_liability_confirmed_for_tax_period", filters);
|
||||
expect(selected.selected_recipe).toBeTruthy();
|
||||
const plan = buildAddressRecipePlan(selected.selected_recipe!, filters);
|
||||
|
||||
expect(plan.query).toContain("РегистрНакопления.НДСЗаписиКнигиПродаж");
|
||||
expect(plan.query).toContain("РегистрНакопления.НДСЗаписиКнигиПокупок");
|
||||
expect(plan.query).toContain("VAT_BOOK_SALES");
|
||||
expect(plan.query).toContain("VAT_BOOK_PURCHASES");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -45,6 +45,17 @@ describe("address route expectations contract", () => {
|
||||
expect(audit.reason).toBe("route_expectation_matched");
|
||||
});
|
||||
|
||||
it("matches expected recipe and result mode for exact VAT tax-period liability route", () => {
|
||||
const audit = evaluateAddressRouteExpectation({
|
||||
intent: "vat_liability_confirmed_for_tax_period",
|
||||
selectedRecipe: "address_vat_liability_confirmed_tax_period_v1",
|
||||
requestedResultMode: "confirmed_balance",
|
||||
resultMode: "confirmed_balance"
|
||||
});
|
||||
expect(audit.status).toBe("matched");
|
||||
expect(audit.reason).toBe("route_expectation_matched");
|
||||
});
|
||||
|
||||
it("detects selected recipe mismatch", () => {
|
||||
const audit = evaluateAddressRouteExpectation({
|
||||
intent: "payables_confirmed_as_of_date",
|
||||
|
||||
Reference in New Issue
Block a user