Add prior promotion endpoints

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-10-17 17:13:01 +03:30
co-authored by Cursor
parent c5708ed59b
commit 008733d338
6 changed files with 272 additions and 1 deletions
@@ -267,6 +267,11 @@ export class ActivitiesController {
return this.activitiesService.get(user.organizationId, id, user);
}
@Post(':id/promote-from-prior')
promoteFromPrior(@CurrentUser() user: Actor, @Param('id') id: string) {
return this.activitiesService.promoteFromPrior(user, id);
}
@Post()
create(@CurrentUser() user: Actor, @Body() dto: CreateActivityDto) {
return this.activitiesService.create(
@@ -1,5 +1,6 @@
import {
BadRequestException,
ForbiddenException,
Injectable,
NotFoundException,
} from '@nestjs/common';
@@ -616,6 +617,38 @@ export class ActivitiesService {
return this.toDto(row, await this.ctx(organizationId));
}
async promoteFromPrior(actor: Actor, id: string): Promise<ActivityDto> {
if (
(actor.priorLens !== 'current' && actor.priorLens !== 'archive') ||
!actor.priorCutoff
) {
throw new ForbiddenException('بایگانی اطلاعات قبل برای شما فعال نیست.');
}
const row = await this.prisma.activity.findFirst({
where: {
id,
organizationId: actor.organizationId,
...activityAccessWhere(actor),
},
select: { id: true, createdAt: true, promotedFromPriorAt: true },
});
if (!row) throw new NotFoundException('فعالیت پیدا نشد');
if (row.promotedFromPriorAt) {
throw new BadRequestException('این فعالیت قبلاً منتقل شده است.');
}
if (row.createdAt >= actor.priorCutoff) {
throw new BadRequestException('این فعالیت در بایگانی نیست.');
}
const updated = await this.prisma.activity.update({
where: { id },
data: { promotedFromPriorAt: new Date() },
include,
});
return this.toDto(updated, await this.ctx(actor.organizationId));
}
async remove(
organizationId: string,
id: string,
+1
View File
@@ -10,6 +10,7 @@ import {
import { ConfigService } from '@nestjs/config';
import { JwtService } from '@nestjs/jwt';
import * as bcrypt from 'bcryptjs';
import type {} from 'multer';
import * as path from 'path';
import type {
AuthUserDto,
@@ -93,6 +93,11 @@ export class DealsController {
return this.dealsService.get(user.organizationId, id, user);
}
@Post(':id/promote-from-prior')
promoteFromPrior(@CurrentUser() user: Actor, @Param('id') id: string) {
return this.dealsService.promoteFromPrior(user, id);
}
@Post()
create(@CurrentUser() user: Actor, @Body() dto: CreateDealDto) {
return this.dealsService.create(user.organizationId, user, dto);
+34 -1
View File
@@ -1,5 +1,6 @@
import {
BadRequestException,
ForbiddenException,
Injectable,
NotFoundException,
} from '@nestjs/common';
@@ -38,7 +39,7 @@ const dealInclude = {
type DealActor = Pick<
Actor,
'userId' | 'role' | 'dataVisibility' | 'visibleUserIds'
'userId' | 'role' | 'dataVisibility' | 'visibleUserIds' | 'priorLens' | 'priorCutoff'
>;
@Injectable()
@@ -443,6 +444,38 @@ export class DealsService {
return this.pipelines.toDealDto(row);
}
async promoteFromPrior(actor: Actor, id: string): Promise<DealDto> {
if (
(actor.priorLens !== 'current' && actor.priorLens !== 'archive') ||
!actor.priorCutoff
) {
throw new ForbiddenException('بایگانی اطلاعات قبل برای شما فعال نیست.');
}
const row = await this.prisma.deal.findFirst({
where: {
id,
organizationId: actor.organizationId,
...dealAccessWhere(actor),
},
select: { id: true, createdAt: true, promotedFromPriorAt: true },
});
if (!row) throw new NotFoundException('معامله پیدا نشد');
if (row.promotedFromPriorAt) {
throw new BadRequestException('این معامله قبلاً منتقل شده است.');
}
if (row.createdAt >= actor.priorCutoff) {
throw new BadRequestException('این معامله در بایگانی نیست.');
}
const updated = await this.prisma.deal.update({
where: { id },
data: { promotedFromPriorAt: new Date() },
include: dealInclude,
});
return this.pipelines.toDealDto(updated);
}
async remove(
organizationId: string,
id: string,