fix(leads): keep a future follow-up as an activity on the lead
A scheduled follow-up only stored a date, and activities opened from a lead were not linked back, so they disappeared from the lead. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -36,6 +36,7 @@ import { GamificationService } from '../gamification/gamification.service';
|
||||
import { tehranDayKey } from '../routines/routine-dates';
|
||||
import { buildSearchWhere, ci } from '../common/search';
|
||||
import { activityPriorWhere } from '../common/prior-archive';
|
||||
import { leadsDeepWhere } from '../common/data-access';
|
||||
import { ActivityStagesService, type BoardStageContext } from './activity-stages.service';
|
||||
import {
|
||||
ActivityTypesService,
|
||||
@@ -45,7 +46,10 @@ import {
|
||||
|
||||
type DtoContext = { stages?: BoardStageContext; types?: SystemTypes };
|
||||
|
||||
type ActivityActor = Pick<Actor, 'userId' | 'role' | 'priorLens' | 'priorCutoff'>;
|
||||
type ActivityActor = Pick<
|
||||
Actor,
|
||||
'userId' | 'role' | 'priorLens' | 'priorCutoff' | 'leadsAccess' | 'teamPeerIds'
|
||||
>;
|
||||
|
||||
/** stageId = شناسهٔ مرحله یا 'all'؛ وقتی ست باشد فیلتر زمانی وضعیت را تحمیل نمیکند (جز عقبافتاده) */
|
||||
type StageScope = { stageId: string };
|
||||
@@ -324,7 +328,10 @@ export class ActivitiesService {
|
||||
this.prisma.activity.findMany({
|
||||
where,
|
||||
include,
|
||||
orderBy: [{ dueAt: 'asc' }, { createdAt: 'desc' }],
|
||||
// روی پروندهٔ لید، تازهترین (از جمله پیگیری آینده) اول بیاید تا از سقف صفحه نیفتد
|
||||
orderBy: entity?.leadId
|
||||
? [{ createdAt: 'desc' }]
|
||||
: [{ dueAt: 'asc' }, { createdAt: 'desc' }],
|
||||
skip: (page - 1) * take,
|
||||
take,
|
||||
}),
|
||||
@@ -628,6 +635,7 @@ export class ActivitiesService {
|
||||
personId: emptyToNull(dto.personId ?? null),
|
||||
companyId: emptyToNull(dto.companyId ?? null),
|
||||
dealId: emptyToNull(dto.dealId ?? null),
|
||||
leadId: emptyToNull(dto.leadId ?? null),
|
||||
assigneeId,
|
||||
assignees: assigneeIds.length
|
||||
? { connect: assigneeIds.map((id) => ({ id })) }
|
||||
@@ -767,6 +775,7 @@ export class ActivitiesService {
|
||||
if ('personId' in dto) data.personId = emptyToNull(dto.personId ?? null);
|
||||
if ('companyId' in dto) data.companyId = emptyToNull(dto.companyId ?? null);
|
||||
if ('dealId' in dto) data.dealId = emptyToNull(dto.dealId ?? null);
|
||||
if ('leadId' in dto) data.leadId = emptyToNull(dto.leadId ?? null);
|
||||
let assigneeConnect: Array<{ id: string }> | undefined;
|
||||
if (dto.assigneeIds !== undefined || 'assigneeId' in dto) {
|
||||
const current = await this.prisma.activity.findFirst({
|
||||
@@ -1283,11 +1292,13 @@ export class ActivitiesService {
|
||||
personId?: string | null;
|
||||
companyId?: string | null;
|
||||
dealId?: string | null;
|
||||
leadId?: string | null;
|
||||
},
|
||||
) {
|
||||
const personId = emptyToNull(dto.personId ?? null);
|
||||
const companyId = emptyToNull(dto.companyId ?? null);
|
||||
const dealId = emptyToNull(dto.dealId ?? null);
|
||||
const leadId = emptyToNull(dto.leadId ?? null);
|
||||
const scope = ownerWhere(actor);
|
||||
|
||||
if (personId) {
|
||||
@@ -1311,6 +1322,13 @@ export class ActivitiesService {
|
||||
});
|
||||
if (!deal) throw new BadRequestException('معامله انتخابشده معتبر نیست');
|
||||
}
|
||||
if (leadId) {
|
||||
const lead = await this.prisma.lead.findFirst({
|
||||
where: { id: leadId, organizationId, ...leadsDeepWhere(actor) },
|
||||
select: { id: true },
|
||||
});
|
||||
if (!lead) throw new BadRequestException('لید انتخابشده معتبر نیست');
|
||||
}
|
||||
}
|
||||
|
||||
private async notifyParticipants(
|
||||
|
||||
@@ -364,6 +364,11 @@ export class CreateActivityDto {
|
||||
@IsString()
|
||||
dealId?: string | null;
|
||||
|
||||
@IsOptional()
|
||||
@ValidateIf((_, v) => v !== '' && v != null)
|
||||
@IsString()
|
||||
leadId?: string | null;
|
||||
|
||||
@IsOptional()
|
||||
@ValidateIf((_, v) => v !== '' && v != null)
|
||||
@IsString()
|
||||
@@ -459,6 +464,11 @@ export class UpdateActivityDto {
|
||||
@IsString()
|
||||
dealId?: string | null;
|
||||
|
||||
@IsOptional()
|
||||
@ValidateIf((_, v) => v !== '' && v != null)
|
||||
@IsString()
|
||||
leadId?: string | null;
|
||||
|
||||
@IsOptional()
|
||||
@ValidateIf((_, v) => v !== '' && v != null)
|
||||
@IsString()
|
||||
|
||||
Reference in New Issue
Block a user