diff --git a/src/lib/features/project-status/project-lifecycle-summary-read-model.test.ts b/src/lib/features/project-status/project-lifecycle-summary-read-model.test.ts index 62acab91110f..95169e7fe2e9 100644 --- a/src/lib/features/project-status/project-lifecycle-summary-read-model.test.ts +++ b/src/lib/features/project-status/project-lifecycle-summary-read-model.test.ts @@ -197,3 +197,79 @@ describe('Average time calculation', () => { }); }); }); + +describe('count current flags in each stage', () => { + test('it counts the number of flags in each stage for the given project', async () => { + const project = await db.stores.projectStore.create({ + name: 'project', + id: randomId(), + }); + + const flags = [ + { + name: randomId(), + stages: ['initial', 'pre-live', 'live', 'archived'], + }, + { + name: randomId(), + stages: ['initial', 'archived'], + }, + { + name: randomId(), + stages: ['initial', 'pre-live', 'live', 'archived'], + }, + { name: randomId(), stages: ['initial', 'pre-live', 'live'] }, + ]; + + for (const { name, stages } of flags) { + const flag = await db.stores.featureToggleStore.create(project.id, { + name, + createdByUserId: 1, + }); + + for (const stage of stages) { + await db.stores.featureLifecycleStore.insert([ + { + feature: flag.name, + stage: stage as StageName, + }, + ]); + } + } + + const otherProject = await db.stores.projectStore.create({ + name: 'project', + id: randomId(), + }); + const flagInOtherProject = await db.stores.featureToggleStore.create( + otherProject.id, + { + name: randomId(), + createdByUserId: 1, + }, + ); + + await db.stores.featureLifecycleStore.insert([ + { + feature: flagInOtherProject.name, + stage: 'initial', + }, + { + feature: flagInOtherProject.name, + stage: 'pre-live', + }, + ]); + + const readModel = new ProjectLifecycleSummaryReadModel(db.rawDatabase); + + const result = await readModel.getCurrentFlagsInEachStage(project.id); + + expect(result).toMatchObject({ + initial: 4, + 'pre-live': 3, + live: 3, + completed: 0, + archived: 3, + }); + }); +}); diff --git a/src/lib/features/project-status/project-lifecycle-summary-read-model.ts b/src/lib/features/project-status/project-lifecycle-summary-read-model.ts index b37f3561ce04..f9c861d9ab2d 100644 --- a/src/lib/features/project-status/project-lifecycle-summary-read-model.ts +++ b/src/lib/features/project-status/project-lifecycle-summary-read-model.ts @@ -89,7 +89,28 @@ export class ProjectLifecycleSummaryReadModel } async getCurrentFlagsInEachStage(projectId: string) { - return 0; + const query = this.db('feature_lifecycles as fl') + .innerJoin('features as f', 'fl.feature', 'f.name') + .where('f.project', projectId) + .select('fl.stage') + .count('fl.feature as flag_count') + .groupBy('fl.stage'); + + const result = await query; + + return result.reduce( + (acc, row) => { + acc[row.stage] = Number(row.flag_count); + return acc; + }, + { + initial: 0, + 'pre-live': 0, + live: 0, + completed: 0, + archived: 0, + }, + ); } async getArchivedFlagsOverLastMonth(projectId: string) {