fix(pipeline): hide prior-only sales paths from current work
The board lists a pipeline in current work only when it has a deal in that period, and keeps archive-only paths for the prior-data view. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -31,8 +31,11 @@ export class PipelinesController {
|
||||
constructor(private readonly pipelinesService: PipelinesService) {}
|
||||
|
||||
@Get()
|
||||
list(@CurrentUser() user: { organizationId: string }) {
|
||||
return this.pipelinesService.list(user.organizationId);
|
||||
list(
|
||||
@CurrentUser() user: Actor,
|
||||
@Query('forLens') forLens?: string,
|
||||
) {
|
||||
return this.pipelinesService.list(user, forLens === '1');
|
||||
}
|
||||
|
||||
@Get('board')
|
||||
|
||||
@@ -102,24 +102,55 @@ export class PipelinesService {
|
||||
return this.toPipelineDto(created);
|
||||
}
|
||||
|
||||
async list(organizationId: string): Promise<PipelineDto[]> {
|
||||
async list(actorOrOrgId: Actor | string, forLens = false): Promise<PipelineDto[]> {
|
||||
const organizationId =
|
||||
typeof actorOrOrgId === 'string' ? actorOrOrgId : actorOrOrgId.organizationId;
|
||||
const actor = typeof actorOrOrgId === 'string' ? undefined : actorOrOrgId;
|
||||
await this.ensureDefaultPipeline(organizationId);
|
||||
const rows = await this.prisma.pipeline.findMany({
|
||||
where: { organizationId },
|
||||
include: { stages: { orderBy: { position: 'asc' } } },
|
||||
orderBy: [{ isDefault: 'desc' }, { name: 'asc' }],
|
||||
});
|
||||
const counts = await this.prisma.deal.groupBy({
|
||||
by: ['pipelineId'],
|
||||
where: { organizationId },
|
||||
_count: { _all: true },
|
||||
});
|
||||
const lens = actor?.priorLens;
|
||||
const lensActive = forLens && (lens === 'current' || lens === 'archive');
|
||||
const access = actor ? dealAccessWhere(actor) : {};
|
||||
const prior = lensActive
|
||||
? dealPriorWhere(actor?.priorLens, actor?.priorCutoff)
|
||||
: {};
|
||||
const [counts, lensCounts] = await Promise.all([
|
||||
this.prisma.deal.groupBy({
|
||||
by: ['pipelineId'],
|
||||
where: lensActive ? { organizationId, AND: [access] } : { organizationId },
|
||||
_count: { _all: true },
|
||||
}),
|
||||
lensActive
|
||||
? this.prisma.deal.groupBy({
|
||||
by: ['pipelineId'],
|
||||
where: { organizationId, AND: [access, prior] },
|
||||
_count: { _all: true },
|
||||
})
|
||||
: Promise.resolve([]),
|
||||
]);
|
||||
const dealCountByPipeline = new Map(
|
||||
counts.map((row) => [row.pipelineId, row._count._all]),
|
||||
);
|
||||
return rows.map((row) => ({
|
||||
const lensCountByPipeline = new Map(
|
||||
lensCounts.map((row) => [row.pipelineId, row._count._all]),
|
||||
);
|
||||
const visible = lensActive
|
||||
? rows.filter((row) => {
|
||||
const inLens = lensCountByPipeline.get(row.id) ?? 0;
|
||||
const total = dealCountByPipeline.get(row.id) ?? 0;
|
||||
if (lens === 'archive') return inLens > 0;
|
||||
return inLens > 0 || total === 0;
|
||||
})
|
||||
: rows;
|
||||
return visible.map((row) => ({
|
||||
...this.toPipelineDto(row),
|
||||
dealCount: dealCountByPipeline.get(row.id) ?? 0,
|
||||
dealCount: lensActive
|
||||
? (lensCountByPipeline.get(row.id) ?? 0)
|
||||
: (dealCountByPipeline.get(row.id) ?? 0),
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
@@ -177,7 +177,9 @@ function findAccent(dealId: string): PipelineStage['color'] {
|
||||
}
|
||||
|
||||
async function loadPipelines() {
|
||||
const { data } = await api.get<PipelineDto[]>('/pipelines');
|
||||
const { data } = await api.get<PipelineDto[]>('/pipelines', {
|
||||
params: { forLens: '1' },
|
||||
});
|
||||
pipelines.value = data;
|
||||
}
|
||||
|
||||
@@ -186,16 +188,23 @@ async function load() {
|
||||
error.value = '';
|
||||
try {
|
||||
await loadPipelines();
|
||||
const pipelineId =
|
||||
typeof route.query.pipelineId === 'string'
|
||||
? route.query.pipelineId
|
||||
: undefined;
|
||||
const requested =
|
||||
typeof route.query.pipelineId === 'string' ? route.query.pipelineId : '';
|
||||
const pipelineId = pipelines.value.some((item) => item.id === requested)
|
||||
? requested
|
||||
: pipelines.value[0]?.id;
|
||||
if (!pipelineId) {
|
||||
boardPipelineId.value = '';
|
||||
stages.value = [];
|
||||
if (requested) await router.replace({ name: 'pipeline', query: {} });
|
||||
return;
|
||||
}
|
||||
const { data } = await api.get<PipelineBoardDto>('/pipelines/board', {
|
||||
params: pipelineId ? { pipelineId } : undefined,
|
||||
params: { pipelineId },
|
||||
});
|
||||
boardPipelineId.value = data.pipeline.id;
|
||||
stages.value = mapBoardToStages(data, formatDealDate);
|
||||
if (!pipelineId || pipelineId !== data.pipeline.id) {
|
||||
if (requested !== data.pipeline.id) {
|
||||
await router.replace({
|
||||
name: 'pipeline',
|
||||
query: { pipelineId: data.pipeline.id },
|
||||
|
||||
Reference in New Issue
Block a user