mirror of
https://git.meshkee.com/Meshkee/backend.git
synced 2026-08-12 06:40:58 +04:30
Add business team access controls and customer role filters.
Super-admins can assign Admin; owners/admins manage Editor/Viewer via team/access, and the customers list supports all/customers/managers filtering. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
2c4d02bd0e
commit
e59db25814
@@ -21,6 +21,9 @@ type CustomerListRow = {
|
||||
email: string | null;
|
||||
createdAt: Date;
|
||||
isEnabled: boolean;
|
||||
businessMemberId: bigint | null;
|
||||
isBusinessOwner: boolean | null;
|
||||
teamRole: string | null;
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
@@ -44,9 +47,18 @@ export class CustomersService {
|
||||
|
||||
const nameLike = query.name?.trim() ? `%${query.name.trim()}%` : null;
|
||||
const cellLike = query.cellNumber?.trim() ? `%${query.cellNumber.trim()}%` : null;
|
||||
const access = query.access ?? 'all';
|
||||
|
||||
const accessFilter =
|
||||
access === 'customers'
|
||||
? Prisma.sql`AND bc.id IS NOT NULL AND bu.id IS NULL`
|
||||
: access === 'managers'
|
||||
? Prisma.sql`AND bu.id IS NOT NULL`
|
||||
: Prisma.sql`AND (bc.id IS NOT NULL OR bu.id IS NOT NULL)`;
|
||||
|
||||
const where = Prisma.sql`
|
||||
WHERE bc.business_id = ${businessId}
|
||||
WHERE 1=1
|
||||
${accessFilter}
|
||||
${nameLike ? Prisma.sql`
|
||||
AND (
|
||||
u.first_name ILIKE ${nameLike}
|
||||
@@ -65,18 +77,28 @@ export class CustomersService {
|
||||
u.first_name AS "firstName",
|
||||
u.last_name AS "lastName",
|
||||
u.email AS "email",
|
||||
bc.created_at AS "createdAt",
|
||||
bc.is_enabled AS "isEnabled"
|
||||
FROM business_customers bc
|
||||
JOIN users u ON u.id = bc.user_id
|
||||
COALESCE(bc.created_at, bu.created_at) AS "createdAt",
|
||||
COALESCE(bc.is_enabled, TRUE) AS "isEnabled",
|
||||
bu.id AS "businessMemberId",
|
||||
bu.is_owner AS "isBusinessOwner",
|
||||
r.slug AS "teamRole"
|
||||
FROM users u
|
||||
LEFT JOIN business_customers bc
|
||||
ON bc.user_id = u.id AND bc.business_id = ${businessId}
|
||||
LEFT JOIN business_users bu
|
||||
ON bu.user_id = u.id AND bu.business_id = ${businessId}
|
||||
LEFT JOIN roles r ON r.id = bu.role_id
|
||||
${where}
|
||||
ORDER BY bc.created_at DESC
|
||||
ORDER BY COALESCE(bc.created_at, bu.created_at) DESC
|
||||
LIMIT ${pageSize} OFFSET ${skip}
|
||||
`),
|
||||
this.prisma.$queryRaw<{ total: number }[]>(Prisma.sql`
|
||||
SELECT COUNT(*)::int AS "total"
|
||||
FROM business_customers bc
|
||||
JOIN users u ON u.id = bc.user_id
|
||||
FROM users u
|
||||
LEFT JOIN business_customers bc
|
||||
ON bc.user_id = u.id AND bc.business_id = ${businessId}
|
||||
LEFT JOIN business_users bu
|
||||
ON bu.user_id = u.id AND bu.business_id = ${businessId}
|
||||
${where}
|
||||
`),
|
||||
]);
|
||||
@@ -91,6 +113,11 @@ export class CustomersService {
|
||||
label: this.formatLabel(user),
|
||||
createdAt: user.createdAt.toISOString(),
|
||||
isEnabled: user.isEnabled,
|
||||
businessMemberId: user.businessMemberId?.toString() ?? null,
|
||||
isBusinessOwner: user.isBusinessOwner ?? false,
|
||||
teamRole: user.isBusinessOwner
|
||||
? 'business_owner'
|
||||
: user.teamRole ?? null,
|
||||
})),
|
||||
total: totalRow[0]?.total ?? 0,
|
||||
page,
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { Type } from 'class-transformer';
|
||||
import { IsInt, IsOptional, IsString, Min } from 'class-validator';
|
||||
import { IsIn, IsInt, IsOptional, IsString, Min } from 'class-validator';
|
||||
|
||||
export const CUSTOMER_ACCESS_FILTERS = ['all', 'customers', 'managers'] as const;
|
||||
export type CustomerAccessFilter = (typeof CUSTOMER_ACCESS_FILTERS)[number];
|
||||
|
||||
export class ListCustomersDto {
|
||||
@IsOptional()
|
||||
@@ -21,4 +24,10 @@ export class ListCustomersDto {
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
cellNumber?: string;
|
||||
|
||||
/** all = customers ∪ managers; customers = customers only; managers = staff/owners */
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@IsIn([...CUSTOMER_ACCESS_FILTERS])
|
||||
access?: CustomerAccessFilter;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user