feat(工作台): 细化计划进展工时证据
关键改动: - 支持需求覆盖和调研方向开始工作记录 - 日报按计划记录开始时间和进度下次开始时间计算证据 - 更新版本编辑校验、项目展示和 workflow 说明 Co-Authored-By: Codex GPT-5 <codex@openai.com>
This commit is contained in:
@@ -362,6 +362,123 @@ test('getWorkspaceDailyReport does not double count overlapping activity time ra
|
||||
assert.equal(report.totalCount, 2);
|
||||
});
|
||||
|
||||
test('getWorkspaceDailyReport uses plan record work start time for daily report hours', () => {
|
||||
const report = getWorkspaceDailyReport({
|
||||
activities: [
|
||||
{
|
||||
id: 'act-plan-record',
|
||||
actorId: 'Alice',
|
||||
date: '2026-06-26',
|
||||
occurredAt: '2026-06-26T04:00:00.000Z',
|
||||
sourceType: 'version_plan',
|
||||
sourceId: 'plan-cross-day',
|
||||
action: 'version_plan_requirement_progress',
|
||||
category: 'progress',
|
||||
title: 'Product plan',
|
||||
summary: 'Updated product plan requirement progress',
|
||||
metadata: {
|
||||
workStartedAt: '2026-06-26T02:00:00.000Z',
|
||||
},
|
||||
},
|
||||
],
|
||||
worklogs: [],
|
||||
workItems: [
|
||||
{
|
||||
id: 'plan-cross-day',
|
||||
type: 'plan_product',
|
||||
title: 'Product plan',
|
||||
status: 'in_progress',
|
||||
completed: false,
|
||||
productName: 'FTB',
|
||||
projectName: 'Project Management',
|
||||
versionName: 'V1.0',
|
||||
versionId: 'version-1',
|
||||
extra: {
|
||||
actualStartAt: '2026-06-25T01:00:00.000Z',
|
||||
},
|
||||
raw: {
|
||||
id: 'plan-cross-day',
|
||||
actualStartAt: '2026-06-25T01:00:00.000Z',
|
||||
status: 'in_progress',
|
||||
} as any,
|
||||
},
|
||||
],
|
||||
userId: 'Alice',
|
||||
date: '2026-06-26',
|
||||
now: new Date('2026-06-26T08:00:00.000Z'),
|
||||
});
|
||||
|
||||
assert.equal(report.totalHours, 2);
|
||||
assert.equal(report.totalCount, 1);
|
||||
});
|
||||
|
||||
test('getWorkspaceDailyReport uses previous progress next start time for dev task daily hours', () => {
|
||||
const report = getWorkspaceDailyReport({
|
||||
activities: [
|
||||
{
|
||||
id: 'act-dev-progress-day-1',
|
||||
actorId: 'Alice',
|
||||
date: '2026-07-01',
|
||||
occurredAt: '2026-07-01T10:00:00.000Z',
|
||||
sourceType: 'dev_task',
|
||||
sourceId: 'task-cross-day-progress',
|
||||
action: 'progress_note_added',
|
||||
category: 'note',
|
||||
title: 'Cross-day development',
|
||||
summary: 'Updated today progress',
|
||||
metadata: {
|
||||
note: 'Finished the first part',
|
||||
nextStartAt: '2026-07-02T01:30:00.000Z',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'act-dev-progress-day-2',
|
||||
actorId: 'Alice',
|
||||
date: '2026-07-02',
|
||||
occurredAt: '2026-07-02T10:00:00.000Z',
|
||||
sourceType: 'dev_task',
|
||||
sourceId: 'task-cross-day-progress',
|
||||
action: 'progress_note_added',
|
||||
category: 'note',
|
||||
title: 'Cross-day development',
|
||||
summary: 'Updated today progress',
|
||||
metadata: {
|
||||
note: 'Finished the second part',
|
||||
nextStartAt: '2026-07-03T01:30:00.000Z',
|
||||
},
|
||||
},
|
||||
],
|
||||
worklogs: [],
|
||||
workItems: [
|
||||
{
|
||||
id: 'task-cross-day-progress',
|
||||
type: 'devTask',
|
||||
title: 'Cross-day development',
|
||||
status: 'in_progress',
|
||||
completed: false,
|
||||
productName: 'FTB',
|
||||
projectName: 'Project Management',
|
||||
versionName: 'V1.0',
|
||||
versionId: 'version-1',
|
||||
extra: {
|
||||
actualStartAt: '2026-07-01T01:30:00.000Z',
|
||||
},
|
||||
raw: {
|
||||
id: 'task-cross-day-progress',
|
||||
actualStartAt: '2026-07-01T01:30:00.000Z',
|
||||
status: 'in_progress',
|
||||
} as any,
|
||||
},
|
||||
],
|
||||
userId: 'Alice',
|
||||
date: '2026-07-02',
|
||||
now: new Date('2026-07-02T10:00:00.000Z'),
|
||||
});
|
||||
|
||||
assert.equal(report.totalHours, 7.5);
|
||||
assert.equal(report.totalCount, 1);
|
||||
});
|
||||
|
||||
test('getWorkspaceDailyReport rebuilds activity evidence from persisted work item timestamps', () => {
|
||||
const report = getWorkspaceDailyReport({
|
||||
activities: [],
|
||||
@@ -401,6 +518,96 @@ test('getWorkspaceDailyReport rebuilds activity evidence from persisted work ite
|
||||
assert.equal(report.totalCount, 2);
|
||||
});
|
||||
|
||||
test('getWorkspaceDailyReport treats same-requirement plan progress as today evidence', () => {
|
||||
const report = getWorkspaceDailyReport({
|
||||
activities: [
|
||||
{
|
||||
id: 'act-plan-requirement-progress',
|
||||
actorId: 'Alice',
|
||||
date: '2026-07-01',
|
||||
occurredAt: '2026-07-01T03:00:00.000Z',
|
||||
sourceType: 'version_plan',
|
||||
sourceId: 'plan-product',
|
||||
action: 'version_plan_requirement_progress',
|
||||
category: 'progress',
|
||||
title: 'Product plan',
|
||||
summary: 'Updated requirement progress',
|
||||
metadata: {
|
||||
requirementId: 'req-shared',
|
||||
workStartedAt: '2026-07-01T02:00:00.000Z',
|
||||
},
|
||||
},
|
||||
],
|
||||
worklogs: [],
|
||||
workItems: [
|
||||
{
|
||||
id: 'plan-product',
|
||||
type: 'plan_product',
|
||||
title: 'Product plan',
|
||||
status: 'in_progress',
|
||||
completed: false,
|
||||
productName: 'FTB',
|
||||
projectName: 'Project Management',
|
||||
versionName: 'V1.0',
|
||||
versionId: 'version-1',
|
||||
extra: {
|
||||
actualStartAt: '2026-06-30T01:00:00.000Z',
|
||||
},
|
||||
raw: {
|
||||
id: 'plan-product',
|
||||
actualStartAt: '2026-06-30T01:00:00.000Z',
|
||||
status: 'in_progress',
|
||||
} as any,
|
||||
},
|
||||
{
|
||||
id: 'task-same-requirement',
|
||||
type: 'devTask',
|
||||
title: 'Same requirement task',
|
||||
status: 'in_progress',
|
||||
completed: false,
|
||||
productName: 'FTB',
|
||||
projectName: 'Project Management',
|
||||
versionName: 'V1.0',
|
||||
versionId: 'version-1',
|
||||
extra: {
|
||||
actualStartAt: '2026-06-30T02:00:00.000Z',
|
||||
},
|
||||
raw: {
|
||||
id: 'task-same-requirement',
|
||||
requirementId: 'req-shared',
|
||||
actualStartAt: '2026-06-30T02:00:00.000Z',
|
||||
status: 'in_progress',
|
||||
} as any,
|
||||
},
|
||||
{
|
||||
id: 'task-other-requirement',
|
||||
type: 'devTask',
|
||||
title: 'Other requirement task',
|
||||
status: 'in_progress',
|
||||
completed: false,
|
||||
productName: 'FTB',
|
||||
projectName: 'Project Management',
|
||||
versionName: 'V1.0',
|
||||
versionId: 'version-1',
|
||||
extra: {
|
||||
actualStartAt: '2026-06-30T02:00:00.000Z',
|
||||
},
|
||||
raw: {
|
||||
id: 'task-other-requirement',
|
||||
requirementId: 'req-other',
|
||||
actualStartAt: '2026-06-30T02:00:00.000Z',
|
||||
status: 'in_progress',
|
||||
} as any,
|
||||
},
|
||||
],
|
||||
userId: 'Alice',
|
||||
date: '2026-07-01',
|
||||
now: new Date('2026-07-01T04:00:00.000Z'),
|
||||
});
|
||||
|
||||
assert.deepEqual(report.needsProgressItems.map((item) => item.id), ['task-other-requirement']);
|
||||
});
|
||||
|
||||
test('getWorkspaceDailyReport flags multi-day in-progress items without today progress', () => {
|
||||
const report = getWorkspaceDailyReport({
|
||||
activities,
|
||||
|
||||
Reference in New Issue
Block a user