fix(crm): mesghal by metal, jalali fit, scoped group filters
This commit is contained in:
@@ -51,6 +51,11 @@ export class CompaniesController {
|
||||
);
|
||||
}
|
||||
|
||||
@Get('group-stats')
|
||||
groupStats(@CurrentUser() user: Actor) {
|
||||
return this.companiesService.groupStats(user);
|
||||
}
|
||||
|
||||
@Get('export')
|
||||
async export(
|
||||
@CurrentUser() user: Actor,
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
import type {
|
||||
CompanyDto,
|
||||
CreateCompanyRequest,
|
||||
CustomerGroupDto,
|
||||
PaginatedResponse,
|
||||
UpdateCompanyRequest,
|
||||
} from '@mento/shared';
|
||||
@@ -135,6 +136,38 @@ export class CompaniesService {
|
||||
};
|
||||
}
|
||||
|
||||
/** آمار گروه برای فیلتر شرکتها — فقط شرکتهای در دسترس کاربر */
|
||||
async groupStats(actor: Actor): Promise<CustomerGroupDto[]> {
|
||||
const counts = await this.prisma.companyGroupLink.groupBy({
|
||||
by: ['groupId'],
|
||||
where: {
|
||||
company: {
|
||||
organizationId: actor.organizationId,
|
||||
...customersCompanyWhere(actor),
|
||||
},
|
||||
},
|
||||
_count: { _all: true },
|
||||
});
|
||||
if (!counts.length) return [];
|
||||
const countMap = new Map(counts.map((c) => [c.groupId, c._count._all]));
|
||||
const groups = await this.prisma.customerGroup.findMany({
|
||||
where: {
|
||||
organizationId: actor.organizationId,
|
||||
id: { in: counts.map((c) => c.groupId) },
|
||||
},
|
||||
orderBy: [{ position: 'asc' }, { name: 'asc' }],
|
||||
});
|
||||
return groups.map((g) => ({
|
||||
id: g.id,
|
||||
name: g.name,
|
||||
color: g.color,
|
||||
position: g.position,
|
||||
fromTahesab: Boolean(g.tahesabGid),
|
||||
personCount: 0,
|
||||
companyCount: countMap.get(g.id) ?? 0,
|
||||
}));
|
||||
}
|
||||
|
||||
async get(actor: Actor, id: string): Promise<CompanyDto> {
|
||||
const row = await this.prisma.company.findFirst({
|
||||
where: { id, organizationId: actor.organizationId, ...customersCompanyWhere(actor) },
|
||||
|
||||
@@ -89,6 +89,11 @@ export class PeopleController {
|
||||
return this.peopleService.sourceStats(user);
|
||||
}
|
||||
|
||||
@Get('group-stats')
|
||||
groupStats(@CurrentUser() user: Actor) {
|
||||
return this.peopleService.groupStats(user);
|
||||
}
|
||||
|
||||
@Get('export')
|
||||
async export(
|
||||
@CurrentUser() user: Actor,
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
} from '@nestjs/common';
|
||||
import type {
|
||||
CreatePersonRequest,
|
||||
CustomerGroupDto,
|
||||
FilteredIdsResponse,
|
||||
PaginatedResponse,
|
||||
PersonDto,
|
||||
@@ -303,6 +304,38 @@ export class PeopleService implements OnModuleInit {
|
||||
.sort((a, b) => b.count - a.count);
|
||||
}
|
||||
|
||||
/** آمار گروه برای فیلتر اشخاص — فقط افراد در دسترس کاربر */
|
||||
async groupStats(actor: Actor): Promise<CustomerGroupDto[]> {
|
||||
const counts = await this.prisma.personGroupLink.groupBy({
|
||||
by: ['groupId'],
|
||||
where: {
|
||||
person: {
|
||||
organizationId: actor.organizationId,
|
||||
...customersPersonWhere(actor),
|
||||
},
|
||||
},
|
||||
_count: { _all: true },
|
||||
});
|
||||
if (!counts.length) return [];
|
||||
const countMap = new Map(counts.map((c) => [c.groupId, c._count._all]));
|
||||
const groups = await this.prisma.customerGroup.findMany({
|
||||
where: {
|
||||
organizationId: actor.organizationId,
|
||||
id: { in: counts.map((c) => c.groupId) },
|
||||
},
|
||||
orderBy: [{ position: 'asc' }, { name: 'asc' }],
|
||||
});
|
||||
return groups.map((g) => ({
|
||||
id: g.id,
|
||||
name: g.name,
|
||||
color: g.color,
|
||||
position: g.position,
|
||||
fromTahesab: Boolean(g.tahesabGid),
|
||||
personCount: countMap.get(g.id) ?? 0,
|
||||
companyCount: 0,
|
||||
}));
|
||||
}
|
||||
|
||||
onModuleInit() {
|
||||
void this.backfillStoredBirthDates();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user