feat: separate prior records behind an owner switch and count last-period questions

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-10-15 10:48:30 +03:30
co-authored by Cursor
parent 3a8a684aa4
commit 6bc5e1bec7
29 changed files with 775 additions and 77 deletions
+38
View File
@@ -0,0 +1,38 @@
import { describe, it } from 'node:test';
import assert from 'node:assert/strict';
import { classifyCountQuestion } from '../src/ai/ask-count';
describe('سؤال‌های شمارشی دستیار', () => {
it('لید جدید هفته گذشته را ساختن حساب نمی‌کند', () => {
const intent = classifyCountQuestion('تعداد لید جدید در هفته گذشته؟');
assert.ok(intent);
assert.equal(intent.entity, 'lead');
assert.equal(intent.period, 'last_week');
assert.equal(intent.leadBucket, 'summary');
assert.equal(intent.hint, '');
});
it('هفته‌ی گذشته و ماه قبل را هم می‌فهمد', () => {
assert.equal(classifyCountQuestion('چند مشتری جدید هفته‌ی گذشته داشتیم؟')?.period, 'last_week');
assert.equal(classifyCountQuestion('تعداد معاملات ماه قبل')?.period, 'last_month');
assert.equal(classifyCountQuestion('تعداد فعالیت جدید این هفته')?.period, 'week');
});
it('مرحلهٔ جدید را با بازه قاطی نمی‌کند', () => {
const intent = classifyCountQuestion('چند لید در مرحله جدید هفته گذشته داریم؟');
assert.ok(intent);
assert.equal(intent.period, 'last_week');
assert.equal(intent.hint, 'جدید');
});
it('بدون بازه، لید جدید یعنی مرحلهٔ جدید', () => {
const intent = classifyCountQuestion('تعداد لید جدید');
assert.ok(intent);
assert.equal(intent.period, undefined);
assert.equal(intent.hint, 'جدید');
});
it('دستور ساخت را سؤال شمارشی نمی‌گیرد', () => {
assert.equal(classifyCountQuestion('یک لید جدید به نام علی بساز'), null);
});
});
+45
View File
@@ -0,0 +1,45 @@
import { describe, it } from 'node:test';
import assert from 'node:assert/strict';
import {
activityPriorWhere,
dealPriorWhere,
listPriorLens,
personPriorWhere,
} from '../src/common/prior-archive';
const now = new Date('2026-10-15T08:00:00.000Z');
describe('بایگانی اطلاعات قبل', () => {
it('بدون مجوز فیلتر نمی‌گذارد', () => {
assert.deepEqual(personPriorWhere('off'), {});
assert.deepEqual(dealPriorWhere(undefined, now), {});
});
it('کار جاری شخص قبلی را کنار می‌گذارد و معاملهٔ بازِ موعددار را نگه می‌دارد', () => {
assert.deepEqual(personPriorWhere('current'), { importSource: { not: 'didar' } });
const where = dealPriorWhere('current', now);
assert.equal(where.OR?.length, 2);
assert.deepEqual(where.OR?.[1], {
importSource: 'didar',
status: 'open',
expectedCloseAt: { gt: now },
});
});
it('بایگانی فقط قبلی‌ها را می‌آورد و استثنای باز را برمی‌دارد', () => {
const where = activityPriorWhere('archive', now);
assert.equal(where.importSource, 'didar');
assert.deepEqual(where.NOT, {
importSource: 'didar',
status: 'open',
dueAt: { gt: now },
});
});
it('جستجوی کار جاری شخص قبلی را پیدا می‌کند', () => {
assert.equal(listPriorLens('current', 'علی', false), 'off');
assert.equal(listPriorLens('current', ' ', false), 'current');
assert.equal(listPriorLens('archive', 'علی', false), 'archive');
assert.equal(listPriorLens('current', '', true), 'off');
});
});