Add desk-style task workflow on Activities and Project boards.

Managers can switch my desk vs team, reassign activities, and filter project cards to their work; assignees can see and move cards.
This commit is contained in:
2026-09-28 12:28:14 +03:30
parent 8effd4cbc6
commit 32e27d45f7
13 changed files with 303 additions and 50 deletions
@@ -18,6 +18,7 @@ import {
canReassignOwner,
dealAccessWhere,
ownerWhere,
projectCardAccessWhere,
resolveOwnerId,
} from '../common/record-scope';
import { normalizeTags } from '../common/tags';
@@ -32,7 +33,10 @@ const cardInclude = {
assignees: { select: { id: true, fullName: true } },
} satisfies Prisma.ProjectCardInclude;
type CardActor = Pick<Actor, 'userId' | 'role'>;
type CardActor = Pick<
Actor,
'userId' | 'role' | 'dataVisibility' | 'visibleUserIds'
>;
@Injectable()
export class ProjectBoardsService {
@@ -113,7 +117,7 @@ export class ProjectBoardsService {
where: {
organizationId,
boardId: resolved.id,
...(actor ? ownerWhere(actor) : {}),
...(actor ? projectCardAccessWhere(actor) : {}),
},
include: cardInclude,
orderBy: [{ position: 'asc' }, { updatedAt: 'desc' }],
@@ -143,7 +147,7 @@ export class ProjectBoardsService {
actor: CardActor,
): Promise<ProjectCardDto> {
const row = await this.prisma.projectCard.findFirst({
where: { id, organizationId, ...ownerWhere(actor) },
where: { id, organizationId, ...projectCardAccessWhere(actor) },
include: cardInclude,
});
if (!row) throw new NotFoundException('کارت پیدا نشد');
@@ -225,7 +229,7 @@ export class ProjectBoardsService {
dto: UpdateProjectCardRequest,
): Promise<ProjectCardDto> {
const existing = await this.prisma.projectCard.findFirst({
where: { id, organizationId, ...ownerWhere(actor) },
where: { id, organizationId, ...projectCardAccessWhere(actor) },
});
if (!existing) throw new NotFoundException('کارت پیدا نشد');
@@ -279,7 +283,7 @@ export class ProjectBoardsService {
dto: MoveProjectCardRequest,
): Promise<ProjectCardDto> {
const card = await this.prisma.projectCard.findFirst({
where: { id, organizationId, ...ownerWhere(actor) },
where: { id, organizationId, ...projectCardAccessWhere(actor) },
select: { id: true, boardId: true },
});
if (!card) throw new NotFoundException('کارت پیدا نشد');
@@ -312,7 +316,7 @@ export class ProjectBoardsService {
actor: CardActor,
): Promise<void> {
const found = await this.prisma.projectCard.findFirst({
where: { id, organizationId, ...ownerWhere(actor) },
where: { id, organizationId, ...projectCardAccessWhere(actor) },
select: { id: true },
});
if (!found) throw new NotFoundException('کارت پیدا نشد');
@@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common';
import type { ImportContactsResult } from '@mento/shared';
import { PrismaService } from '../prisma/prisma.service';
import type { Actor } from '../common/record-scope';
import { ownerWhere } from '../common/record-scope';
import { projectCardAccessWhere } from '../common/record-scope';
import { normalizePhone } from '../contacts/normalize';
import {
excelFieldsFromColumns,
@@ -68,7 +68,7 @@ export class ProjectCardsExcelService {
async export(actor: Actor): Promise<Buffer> {
const rows = await this.prisma.projectCard.findMany({
where: { organizationId: actor.organizationId, ...ownerWhere(actor) },
where: { organizationId: actor.organizationId, ...projectCardAccessWhere(actor) },
include: {
person: {
select: { id: true, firstName: true, lastName: true, mobile: true },