feat(pets): add admin pet health records query and paginated pet list endpoint [TASK-26.17]
This commit is contained in:
parent
d94b33f96d
commit
cbcff26e63
@ -254,6 +254,21 @@ export class AdminController {
|
||||
return { success: true, data: settings };
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Get('pets')
|
||||
@ApiOperation({ summary: 'لیست پتها (مدیریت)' })
|
||||
@ApiQuery({ name: 'page', required: false })
|
||||
@ApiQuery({ name: 'limit', required: false })
|
||||
@ApiQuery({ name: 'search', required: false })
|
||||
async getPets(
|
||||
@Query('page') page?: string,
|
||||
@Query('limit') limit?: string,
|
||||
@Query('search') search?: string,
|
||||
) {
|
||||
const data = await this.adminService.getPets({ page, limit, search });
|
||||
return { success: true, ...data };
|
||||
}
|
||||
|
||||
// --- Doctors / Vets ---
|
||||
@Get('doctors')
|
||||
@ApiOperation({ summary: 'لیست پزشکان و متخصصان' })
|
||||
|
||||
@ -475,6 +475,48 @@ export class AdminService {
|
||||
return this.getSettings();
|
||||
}
|
||||
|
||||
async getPets(query: any) {
|
||||
const page = Number(query.page) || 1;
|
||||
const limit = Number(query.limit) || 10;
|
||||
const skip = (page - 1) * limit;
|
||||
|
||||
const where: any = {};
|
||||
if (query.search) {
|
||||
where.OR = [
|
||||
{ name: { contains: query.search, mode: 'insensitive' } },
|
||||
{ breed: { contains: query.search, mode: 'insensitive' } },
|
||||
{ user: { firstName: { contains: query.search, mode: 'insensitive' } } },
|
||||
{ user: { lastName: { contains: query.search, mode: 'insensitive' } } },
|
||||
];
|
||||
}
|
||||
|
||||
const [data, total] = await Promise.all([
|
||||
this.prisma.pet.findMany({
|
||||
where,
|
||||
skip,
|
||||
take: limit,
|
||||
orderBy: { createdAt: 'desc' },
|
||||
include: {
|
||||
user: {
|
||||
select: { id: true, firstName: true, lastName: true, mobile: true, email: true },
|
||||
},
|
||||
medicalConditions: true,
|
||||
reminders: true,
|
||||
healthLogs: {
|
||||
orderBy: { loggedDate: 'desc' },
|
||||
take: 10,
|
||||
},
|
||||
},
|
||||
}),
|
||||
this.prisma.pet.count({ where }),
|
||||
]);
|
||||
|
||||
return {
|
||||
data,
|
||||
meta: { total, page, limit, lastPage: Math.ceil(total / limit) },
|
||||
};
|
||||
}
|
||||
|
||||
async getDoctors() {
|
||||
return this.prisma.doctor.findMany({
|
||||
orderBy: { createdAt: 'desc' },
|
||||
|
||||
@ -31,6 +31,66 @@ export class PetsService {
|
||||
});
|
||||
}
|
||||
|
||||
async findAllAdmin(filters: PaginationDto) {
|
||||
const {
|
||||
search,
|
||||
page = 1,
|
||||
limit = 10,
|
||||
sortBy = 'createdAt',
|
||||
sortOrder = 'desc',
|
||||
} = filters;
|
||||
|
||||
const whereClause: any = {};
|
||||
if (search) {
|
||||
whereClause.OR = [
|
||||
{ name: { contains: search, mode: 'insensitive' } },
|
||||
{ breed: { contains: search, mode: 'insensitive' } },
|
||||
{ user: { firstName: { contains: search, mode: 'insensitive' } } },
|
||||
{ user: { lastName: { contains: search, mode: 'insensitive' } } },
|
||||
{ user: { mobile: { contains: search } } },
|
||||
];
|
||||
}
|
||||
|
||||
const skip = (page - 1) * limit;
|
||||
|
||||
const [data, total] = await Promise.all([
|
||||
this.prisma.pet.findMany({
|
||||
where: whereClause,
|
||||
skip,
|
||||
take: limit,
|
||||
orderBy: { [sortBy]: sortOrder },
|
||||
include: {
|
||||
user: {
|
||||
select: {
|
||||
id: true,
|
||||
firstName: true,
|
||||
lastName: true,
|
||||
mobile: true,
|
||||
email: true,
|
||||
},
|
||||
},
|
||||
medicalConditions: true,
|
||||
reminders: true,
|
||||
healthLogs: {
|
||||
orderBy: { loggedDate: 'desc' },
|
||||
take: 10,
|
||||
},
|
||||
},
|
||||
}),
|
||||
this.prisma.pet.count({ where: whereClause }),
|
||||
]);
|
||||
|
||||
return {
|
||||
data,
|
||||
meta: {
|
||||
total,
|
||||
page,
|
||||
lastPage: Math.ceil(total / limit),
|
||||
limit,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async findAllByUser(userId: string, filters: PaginationDto) {
|
||||
const {
|
||||
search,
|
||||
@ -56,6 +116,7 @@ export class PetsService {
|
||||
skip,
|
||||
take: limit,
|
||||
orderBy: { [sortBy]: sortOrder },
|
||||
include: { medicalConditions: true, reminders: true, healthLogs: true },
|
||||
}),
|
||||
this.prisma.pet.count({ where: whereClause }),
|
||||
]);
|
||||
|
||||
@ -214,7 +214,7 @@
|
||||
- [x] **TASK-26.14 [Admin Wallet Adjust Endpoint]:** ایجاد اندپویینت `POST /api/users/:id/wallet-adjust` و فرم شارژ/کسر مستقیم کیفپول در پنل ادمین.
|
||||
- [x] **TASK-26.15 [Admin User Details, Addresses & Transactions Modal]:** امکان مشاهده کامل آدرسها و ریزتراکنشهای کیفپول کاربر در پنل ادمین.
|
||||
- [x] **TASK-26.16 [Atomic Prisma Transaction for Wallet Top-up]:** اتمیک کردن عملیات شارژ کیفپول در دیتابیس با `prisma.$transaction`.
|
||||
- [ ] **TASK-26.17 [Admin Pet Health Records & Pagination]:** امکان مشاهده پرونده پزشکی، یادآورها و لاگهای سلامت پت در پنل ادمین همراه با پجینیشن کامل لیست پتها.
|
||||
- [x] **TASK-26.17 [Admin Pet Health Records & Pagination]:** امکان مشاهده پرونده پزشکی، یادآورها و لاگهای سلامت پت در پنل ادمین همراه با پجینیشن کامل لیست پتها.
|
||||
- [ ] **TASK-26.18 [Pet Image File Upload]:** امکان آپلود مستقیم فایل تصویر پت به سرور در فرمهای فرانتاند.
|
||||
- [ ] **TASK-26.19 [Atomic Order Creation Transaction & Refill Cron Job]:** اتمیک کردن ساخت سفارش با کیفپول در بکاند و ایجاد Cron Job روزانه برای پیامک خودکار یادآوری Refill.
|
||||
- [ ] **TASK-26.20 [Reports Excel Export, Dashboard Live Chart & Video View Counter]:** افزودن قابلیت دانلود خروجی اکسل در صفحه گزارشات، اتصال نمودار داشبورد به دیتای واقعی و ارسال درخواست PATCH افزایش بازدید ویدیوها.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user