212 lines
5.6 KiB
TypeScript
212 lines
5.6 KiB
TypeScript
import {
|
|
BadRequestException,
|
|
Body,
|
|
Controller,
|
|
Delete,
|
|
Get,
|
|
Param,
|
|
Patch,
|
|
Post,
|
|
Query,
|
|
Res,
|
|
StreamableFile,
|
|
UploadedFile,
|
|
UseGuards,
|
|
UseInterceptors,
|
|
} from '@nestjs/common';
|
|
import { FileInterceptor } from '@nestjs/platform-express';
|
|
import { memoryStorage } from 'multer';
|
|
import type { Response } from 'express';
|
|
import { JwtAuthGuard } from '../auth/jwt-auth.guard';
|
|
import { RequirePermission, SectionPermissionGuard } from '../auth/section-permission.guard';
|
|
import { CurrentUser } from '../auth/current-user.decorator';
|
|
import type { Actor } from '../common/record-scope';
|
|
import { OrgModuleGuard } from '../billing/org-module.guard';
|
|
import { RequireOrgModule } from '../billing/org-module.decorator';
|
|
import { BirthdaySmsDto, BulkDeletePeopleDto, CreatePersonDto, ListQueryDto, UpdatePersonDto } from './dto';
|
|
import { PeopleService } from './people.service';
|
|
import { ContactsExcelService } from './contacts-excel.service';
|
|
import { brand } from '@mento/shared';
|
|
|
|
const excelUpload = FileInterceptor('file', {
|
|
storage: memoryStorage(),
|
|
limits: { fileSize: 15_000_000 },
|
|
});
|
|
|
|
@Controller('people')
|
|
@UseGuards(JwtAuthGuard, OrgModuleGuard, SectionPermissionGuard)
|
|
@RequireOrgModule('customers')
|
|
@RequirePermission('customers')
|
|
export class PeopleController {
|
|
constructor(
|
|
private readonly peopleService: PeopleService,
|
|
private readonly excelService: ContactsExcelService,
|
|
) {}
|
|
|
|
@Get()
|
|
list(@CurrentUser() user: Actor, @Query() query: ListQueryDto) {
|
|
const hasMobile =
|
|
query.hasMobile === '1' || query.hasMobile === 'true'
|
|
? true
|
|
: undefined;
|
|
return this.peopleService.list(
|
|
user,
|
|
query.q,
|
|
query.page ?? 1,
|
|
query.limit ?? 20,
|
|
{
|
|
mood: query.mood,
|
|
sort: query.sort,
|
|
importSource: query.importSource,
|
|
province: query.province,
|
|
city: query.city,
|
|
hasMobile,
|
|
disc: query.disc,
|
|
groupId: query.groupId,
|
|
},
|
|
);
|
|
}
|
|
|
|
@Get('ids')
|
|
listIds(@CurrentUser() user: Actor, @Query() query: ListQueryDto) {
|
|
const hasMobile =
|
|
query.hasMobile === '1' || query.hasMobile === 'true'
|
|
? true
|
|
: undefined;
|
|
return this.peopleService.listIds(user, query.q, {
|
|
mood: query.mood,
|
|
importSource: query.importSource,
|
|
province: query.province,
|
|
city: query.city,
|
|
hasMobile,
|
|
disc: query.disc,
|
|
groupId: query.groupId,
|
|
});
|
|
}
|
|
|
|
@Get('source-stats')
|
|
sourceStats(@CurrentUser() user: Actor) {
|
|
return this.peopleService.sourceStats(user);
|
|
}
|
|
|
|
@Get('group-stats')
|
|
groupStats(@CurrentUser() user: Actor) {
|
|
return this.peopleService.groupStats(user);
|
|
}
|
|
|
|
@Get('export')
|
|
async export(
|
|
@CurrentUser() user: Actor,
|
|
@Query('q') q: string | undefined,
|
|
@Res({ passthrough: true }) res: Response,
|
|
) {
|
|
const buffer = await this.excelService.exportPeople(user, q);
|
|
res.set({
|
|
'Content-Type':
|
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
'Content-Disposition': `attachment; filename="${brand.filePrefix}-people.xlsx"`,
|
|
});
|
|
return new StreamableFile(buffer);
|
|
}
|
|
|
|
@Post('import/preview')
|
|
@UseInterceptors(excelUpload)
|
|
previewImport(@UploadedFile() file?: Express.Multer.File) {
|
|
if (!file?.buffer?.length) {
|
|
throw new BadRequestException('فایل ارسال نشده');
|
|
}
|
|
return this.excelService.previewPeople(file);
|
|
}
|
|
|
|
@Post('import')
|
|
@UseInterceptors(excelUpload)
|
|
import(
|
|
@CurrentUser() user: Actor,
|
|
@UploadedFile() file?: Express.Multer.File,
|
|
@Body('mapping') mapping?: string,
|
|
@Body('sessionId') sessionId?: string,
|
|
@Body('offset') offset?: string,
|
|
@Body('limit') limit?: string,
|
|
) {
|
|
if (!file?.buffer?.length && !sessionId) {
|
|
throw new BadRequestException('فایل ارسال نشده');
|
|
}
|
|
return this.excelService.importPeople(user, file, mapping, {
|
|
sessionId,
|
|
offset,
|
|
limit,
|
|
});
|
|
}
|
|
|
|
@Get('birthdays')
|
|
@RequirePermission('customers', { reads: true })
|
|
birthdays(@CurrentUser() user: Actor) {
|
|
return this.peopleService.birthdaysThisMonth(user);
|
|
}
|
|
|
|
@Get(':id/sms-history')
|
|
smsHistory(
|
|
@CurrentUser() user: Actor,
|
|
@Param('id') id: string,
|
|
@Query('limit') limit?: string,
|
|
) {
|
|
return this.peopleService.listSmsHistory(
|
|
user,
|
|
id,
|
|
limit ? Number(limit) : 50,
|
|
);
|
|
}
|
|
|
|
@Post(':id/sms')
|
|
sms(
|
|
@CurrentUser() user: Actor,
|
|
@Param('id') id: string,
|
|
@Body() dto: BirthdaySmsDto,
|
|
) {
|
|
return this.peopleService.sendSms(user, id, dto.text);
|
|
}
|
|
|
|
@Post(':id/birthday-sms')
|
|
birthdaySms(
|
|
@CurrentUser() user: Actor,
|
|
@Param('id') id: string,
|
|
@Body() dto: BirthdaySmsDto,
|
|
) {
|
|
return this.peopleService.sendBirthdaySms(user, id, dto.text, Boolean(dto.force));
|
|
}
|
|
|
|
@Get(':id')
|
|
get(@CurrentUser() user: Actor, @Param('id') id: string) {
|
|
return this.peopleService.get(user, id);
|
|
}
|
|
|
|
@Post('bulk-delete')
|
|
bulkDelete(@CurrentUser() user: Actor, @Body() dto: BulkDeletePeopleDto) {
|
|
return this.peopleService.removeMany(user, dto.ids);
|
|
}
|
|
|
|
@Post()
|
|
create(@CurrentUser() user: Actor, @Body() dto: CreatePersonDto) {
|
|
return this.peopleService.create(user, {
|
|
...dto,
|
|
firstName: dto.firstName ?? '',
|
|
lastName: dto.lastName ?? '',
|
|
});
|
|
}
|
|
|
|
@Patch(':id')
|
|
update(
|
|
@CurrentUser() user: Actor,
|
|
@Param('id') id: string,
|
|
@Body() dto: UpdatePersonDto,
|
|
) {
|
|
return this.peopleService.update(user, id, dto);
|
|
}
|
|
|
|
@Delete(':id')
|
|
async remove(@CurrentUser() user: Actor, @Param('id') id: string) {
|
|
await this.peopleService.remove(user, id);
|
|
return { ok: true };
|
|
}
|
|
}
|