发布商品,商品图片使用oss服务器地址
This commit is contained in:
@@ -20,6 +20,9 @@ export class AdminDashboardService {
|
||||
partnersTotal,
|
||||
redeemToday,
|
||||
deliveriesTotal,
|
||||
pendingPayouts,
|
||||
pendingBills,
|
||||
openTickets,
|
||||
] = await Promise.all([
|
||||
this.prisma.user.count({ where: { status: 1, mergedIntoUserId: null } }),
|
||||
this.prisma.user.count({
|
||||
@@ -38,6 +41,9 @@ export class AdminDashboardService {
|
||||
this.prisma.partner.count(),
|
||||
this.prisma.redeemRecord.count({ where: { createdAt: { gte: todayStart } } }),
|
||||
this.prisma.orderDelivery.count(),
|
||||
this.prisma.storePayout.count({ where: { status: 'PENDING' } }),
|
||||
this.prisma.partnerBill.count({ where: { status: { in: ['DRAFT', 'CONFIRMED'] } } }),
|
||||
this.prisma.commonTicket.count({ where: { status: { in: ['PENDING', 'OPEN'] } } }),
|
||||
]);
|
||||
|
||||
return {
|
||||
@@ -50,6 +56,9 @@ export class AdminDashboardService {
|
||||
partnersTotal,
|
||||
redeemToday,
|
||||
deliveriesTotal,
|
||||
pendingPayouts,
|
||||
pendingBills,
|
||||
openTickets,
|
||||
ordersByStatus: ordersByStatus.map((row) => ({
|
||||
status: row.status,
|
||||
count: row._count.status,
|
||||
|
||||
@@ -45,6 +45,11 @@ export class AdminStoresController {
|
||||
updateStatus(@Param('id') id: string, @Body() dto: UpdateStoreStatusDto) {
|
||||
return this.service.updateStoreStatus(BigInt(id), dto);
|
||||
}
|
||||
|
||||
@Put(':id/audit')
|
||||
audit(@Param('id') id: string, @Body() body: { approved: boolean; remark?: string }) {
|
||||
return this.service.auditStore(BigInt(id), body);
|
||||
}
|
||||
}
|
||||
|
||||
@Controller('admin/store-accounts')
|
||||
|
||||
@@ -93,6 +93,27 @@ export class AdminStoresService {
|
||||
return serializeBigInt(store);
|
||||
}
|
||||
|
||||
async auditStore(id: bigint, dto: { approved: boolean; remark?: string }) {
|
||||
const store = await this.prisma.store.findUnique({ where: { id } });
|
||||
if (!store) throw new NotFoundException('门店不存在');
|
||||
const status = dto.approved ? 'OPEN' : 'PAUSED';
|
||||
const updated = await this.prisma.store.update({
|
||||
where: { id },
|
||||
data: { status },
|
||||
});
|
||||
await this.prisma.commonEvent.create({
|
||||
data: {
|
||||
eventType: 'STORE_AUDIT',
|
||||
refType: 'STORE',
|
||||
refId: id,
|
||||
actorType: 'HQ',
|
||||
status: dto.approved ? 'APPROVED' : 'REJECTED',
|
||||
remark: dto.remark ?? (dto.approved ? '审核通过' : '审核驳回'),
|
||||
},
|
||||
});
|
||||
return serializeBigInt(updated);
|
||||
}
|
||||
|
||||
async updateStore(id: bigint, dto: UpdateStoreDto) {
|
||||
const store = await this.prisma.store.update({
|
||||
where: { id },
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import { Body, Controller, Get, Param, Post, Query, UseGuards } from '@nestjs/common';
|
||||
import { HqAuthGuard } from '../../common/guards/hq-auth.guard';
|
||||
import { AdminTicketsService } from './admin-tickets.service';
|
||||
import { TicketListQueryDto } from '../common/dto/common-query.dto';
|
||||
|
||||
@Controller('admin/tickets')
|
||||
@UseGuards(HqAuthGuard)
|
||||
export class AdminTicketsController {
|
||||
constructor(private readonly service: AdminTicketsService) {}
|
||||
|
||||
@Get()
|
||||
list(@Query() query: TicketListQueryDto) {
|
||||
return this.service.list(query);
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
detail(@Param('id') id: string) {
|
||||
return this.service.detail(BigInt(id));
|
||||
}
|
||||
|
||||
@Post(':id/approve')
|
||||
approve(@Param('id') id: string, @Body() body: { remark?: string }) {
|
||||
return this.service.approve(BigInt(id), body.remark);
|
||||
}
|
||||
|
||||
@Post(':id/reject')
|
||||
reject(@Param('id') id: string, @Body() body: { remark?: string }) {
|
||||
return this.service.reject(BigInt(id), body.remark);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common';
|
||||
import { PrismaService } from '../../common/prisma/prisma.module';
|
||||
import { BenefitService } from '../benefit/benefit.service';
|
||||
import { TradeService } from '../trade/trade.service';
|
||||
import { TicketService } from '../common/ticket.service';
|
||||
import { serializeBigInt } from '../../common/decorators/current-user.decorator';
|
||||
import type { TicketListQueryDto } from '../common/dto/common-query.dto';
|
||||
|
||||
@Injectable()
|
||||
export class AdminTicketsService {
|
||||
constructor(
|
||||
private readonly prisma: PrismaService,
|
||||
private readonly ticketService: TicketService,
|
||||
private readonly tradeService: TradeService,
|
||||
private readonly benefitService: BenefitService,
|
||||
) {}
|
||||
|
||||
list(query: TicketListQueryDto) {
|
||||
return this.ticketService.list(query);
|
||||
}
|
||||
|
||||
detail(id: bigint) {
|
||||
return this.ticketService.detail(id);
|
||||
}
|
||||
|
||||
async approve(id: bigint, remark?: string) {
|
||||
const ticket = await this.prisma.commonTicket.findUnique({ where: { id } });
|
||||
if (!ticket) throw new NotFoundException('工单不存在');
|
||||
if (ticket.status !== 'PENDING' && ticket.status !== 'OPEN') {
|
||||
throw new BadRequestException('工单状态不可审批');
|
||||
}
|
||||
|
||||
if (ticket.ticketType === 'REFUND' && ticket.refType === 'ORDER') {
|
||||
const orderId = ticket.refId;
|
||||
await this.prisma.order.update({
|
||||
where: { id: orderId },
|
||||
data: { status: 'REFUNDED', payStatus: 'REFUNDED' },
|
||||
});
|
||||
await this.benefitService.voidCouponsOnRefund(orderId);
|
||||
await this.prisma.logThirdParty.create({
|
||||
data: {
|
||||
provider: 'WECHAT_REFUND',
|
||||
scene: 'ORDER_REFUND',
|
||||
refType: 'ORDER',
|
||||
refId: orderId,
|
||||
status: 'SUCCESS',
|
||||
amount: 0,
|
||||
},
|
||||
});
|
||||
await this.prisma.commonEvent.create({
|
||||
data: {
|
||||
eventType: 'ORDER_STATUS',
|
||||
refType: 'ORDER',
|
||||
refId: orderId,
|
||||
actorType: 'HQ',
|
||||
status: 'REFUNDED',
|
||||
remark: remark ?? '退款工单审批通过',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (ticket.ticketType === 'RESHIPMENT' && ticket.refType === 'ORDER') {
|
||||
await this.tradeService.applyStatusTransition(
|
||||
ticket.refId,
|
||||
'PENDING_SHIP',
|
||||
'PENDING_SHIP',
|
||||
'HQ',
|
||||
);
|
||||
}
|
||||
|
||||
return this.ticketService.updateStatus(id, {
|
||||
status: 'RESOLVED',
|
||||
remark: remark ?? '审批通过',
|
||||
});
|
||||
}
|
||||
|
||||
reject(id: bigint, remark?: string) {
|
||||
return this.ticketService.updateStatus(id, {
|
||||
status: 'REJECTED',
|
||||
remark: remark ?? '审批驳回',
|
||||
});
|
||||
}
|
||||
|
||||
async listPartnerReshipments(partnerAccountId: bigint) {
|
||||
const account = await this.prisma.partnerAccount.findUniqueOrThrow({
|
||||
where: { id: partnerAccountId },
|
||||
});
|
||||
const cities = await this.prisma.commonCity.findMany({
|
||||
where: { partnerId: account.partnerId },
|
||||
select: { id: true },
|
||||
});
|
||||
const orders = await this.prisma.order.findMany({
|
||||
where: { cityId: { in: cities.map((c) => c.id) } },
|
||||
select: { id: true },
|
||||
});
|
||||
const orderIds = orders.map((o) => o.id);
|
||||
const tickets = await this.prisma.commonTicket.findMany({
|
||||
where: {
|
||||
ticketType: 'RESHIPMENT',
|
||||
refType: 'ORDER',
|
||||
refId: { in: orderIds },
|
||||
},
|
||||
orderBy: { createdAt: 'desc' },
|
||||
});
|
||||
return serializeBigInt(tickets);
|
||||
}
|
||||
}
|
||||
@@ -21,10 +21,14 @@ import { AdminHqAccountsController } from './admin-hq-accounts.controller';
|
||||
import { AdminHqAccountsService } from './admin-hq-accounts.service';
|
||||
import { AdminProductsController } from './admin-products.controller';
|
||||
import { AdminProductsService } from './admin-products.service';
|
||||
import { AdminTicketsController } from './admin-tickets.controller';
|
||||
import { AdminTicketsService } from './admin-tickets.service';
|
||||
import { SuperAdminGuard } from '../../common/guards/super-admin.guard';
|
||||
import { BenefitModule } from '../benefit/benefit.module';
|
||||
import { CommonModule } from '../common/common.module';
|
||||
|
||||
@Module({
|
||||
imports: [IamModule, TradeModule],
|
||||
imports: [IamModule, TradeModule, BenefitModule, CommonModule],
|
||||
controllers: [
|
||||
AdminDashboardController,
|
||||
AdminUsersController,
|
||||
@@ -41,6 +45,7 @@ import { SuperAdminGuard } from '../../common/guards/super-admin.guard';
|
||||
AdminDeliveriesController,
|
||||
AdminHqAccountsController,
|
||||
AdminProductsController,
|
||||
AdminTicketsController,
|
||||
],
|
||||
providers: [
|
||||
AdminDashboardService,
|
||||
@@ -54,6 +59,7 @@ import { SuperAdminGuard } from '../../common/guards/super-admin.guard';
|
||||
AdminDeliveriesService,
|
||||
AdminHqAccountsService,
|
||||
AdminProductsService,
|
||||
AdminTicketsService,
|
||||
SuperAdminGuard,
|
||||
],
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user