增加核销接口

增加hq管理端日志
This commit is contained in:
2026-07-06 19:17:27 +08:00
parent f0b99ea9da
commit 4c38a9dd2b
29 changed files with 904 additions and 37 deletions
@@ -1,5 +1,7 @@
import { Controller, Get, Param, Post, Query, UseGuards } from '@nestjs/common';
import { HqAuthGuard } from '../../common/guards/hq-auth.guard';
import { HqOperation } from '../../common/hq-operation/hq-operation.decorator';
import { HqOperationAction } from '../../common/hq-operation/hq-operation.constants';
import { AdminBenefitService } from './admin-benefit.service';
import { AdminBenefitCouponsQueryDto, AdminBenefitLedgersQueryDto } from './dto/admin-query.dto';
@@ -19,6 +21,7 @@ export class AdminBenefitCouponsController {
}
@Post(':id/void')
@HqOperation({ action: HqOperationAction.BENEFIT_COUPON_VOID, refType: 'BENEFIT_COUPON', refIdParam: 'id' })
voidCoupon(@Param('id') id: string) {
return this.service.voidCoupon(BigInt(id));
}
@@ -1,9 +1,10 @@
import { Controller, Get, Param, Post, Put, Query, UseGuards } from '@nestjs/common';
import { Body, Controller, Get, Param, Post, Put, Query, UseGuards } from '@nestjs/common';
import { HqAuthGuard } from '../../common/guards/hq-auth.guard';
import { HqOperation } from '../../common/hq-operation/hq-operation.decorator';
import { HqOperationAction } from '../../common/hq-operation/hq-operation.constants';
import { AdminCitiesService } from './admin-cities.service';
import { AdminCitiesQueryDto } from './dto/admin-query.dto';
import { CreateCityDto, UpdateCityDto } from './dto/admin-mutate.dto';
import { Body } from '@nestjs/common';
@Controller('admin/cities')
@UseGuards(HqAuthGuard)
@@ -21,11 +22,18 @@ export class AdminCitiesController {
}
@Post()
@HqOperation({ action: HqOperationAction.CITY_CREATE, refType: 'CITY', refIdField: 'id', includeBody: true })
create(@Body() dto: CreateCityDto) {
return this.service.create(dto);
}
@Put(':id')
@HqOperation({
action: HqOperationAction.CITY_UPDATE,
refType: 'CITY',
refIdParam: 'id',
includeBody: true,
})
update(@Param('id') id: string, @Body() dto: UpdateCityDto) {
return this.service.update(BigInt(id), dto);
}
@@ -1,6 +1,8 @@
import { Body, Controller, Get, Param, Post, Put, Query, UseGuards } from '@nestjs/common';
import { HqAuthGuard } from '../../common/guards/hq-auth.guard';
import { SuperAdminGuard } from '../../common/guards/super-admin.guard';
import { HqOperation } from '../../common/hq-operation/hq-operation.decorator';
import { HqOperationAction } from '../../common/hq-operation/hq-operation.constants';
import { AdminHqAccountsService } from './admin-hq-accounts.service';
import { AdminHqAccountsQueryDto } from './dto/admin-query.dto';
import { CreateHqAccountDto, UpdateHqAccountDto } from './dto/admin-mutate.dto';
@@ -22,12 +24,24 @@ export class AdminHqAccountsController {
@Post()
@UseGuards(SuperAdminGuard)
@HqOperation({
action: HqOperationAction.HQ_ACCOUNT_CREATE,
refType: 'HQ_ACCOUNT',
refIdField: 'id',
includeBody: true,
})
create(@Body() dto: CreateHqAccountDto) {
return this.service.create(dto);
}
@Put(':id')
@UseGuards(SuperAdminGuard)
@HqOperation({
action: HqOperationAction.HQ_ACCOUNT_UPDATE,
refType: 'HQ_ACCOUNT',
refIdParam: 'id',
includeBody: true,
})
update(@Param('id') id: string, @Body() dto: UpdateHqAccountDto) {
return this.service.update(BigInt(id), dto);
}
@@ -0,0 +1,20 @@
import { Controller, Get, Param, Query, UseGuards } from '@nestjs/common';
import { HqAuthGuard } from '../../common/guards/hq-auth.guard';
import { AdminHqLogsService } from './admin-hq-logs.service';
import { AdminHqLogsQueryDto } from './dto/admin-query.dto';
@Controller('admin/logs/hq')
@UseGuards(HqAuthGuard)
export class AdminHqLogsController {
constructor(private readonly service: AdminHqLogsService) {}
@Get()
list(@Query() query: AdminHqLogsQueryDto) {
return this.service.list(query);
}
@Get(':id')
detail(@Param('id') id: string) {
return this.service.detail(BigInt(id));
}
}
@@ -0,0 +1,96 @@
import { Injectable, NotFoundException } from '@nestjs/common';
import { PrismaService } from '../../common/prisma/prisma.module';
import { serializeBigInt } from '../../common/decorators/current-user.decorator';
import { hqOperationLogWhere } from '../../common/event/event.helpers';
import { resolveHqOperationLabel } from '../../common/hq-operation/hq-operation.constants';
import type { AdminHqLogsQueryDto } from './dto/admin-query.dto';
@Injectable()
export class AdminHqLogsService {
constructor(private readonly prisma: PrismaService) {}
async list(query: AdminHqLogsQueryDto) {
const page = query.page ?? 1;
const pageSize = query.pageSize ?? 20;
const where = hqOperationLogWhere({
hqAccountId: query.hqAccountId ? BigInt(query.hqAccountId) : undefined,
action: query.action,
refType: query.refType,
from: query.from ? new Date(query.from) : undefined,
to: query.to ? new Date(query.to) : undefined,
});
const [rows, total] = await Promise.all([
this.prisma.commonEvent.findMany({
where,
orderBy: { createdAt: 'desc' },
skip: (page - 1) * pageSize,
take: pageSize,
}),
this.prisma.commonEvent.count({ where }),
]);
const hqIds = [...new Set(rows.map((r) => r.actorId).filter((id): id is bigint => id != null))];
const hqAccounts = hqIds.length
? await this.prisma.hqAccount.findMany({
where: { id: { in: hqIds } },
select: { id: true, name: true, phone: true, adminRole: true },
})
: [];
const hqMap = new Map(hqAccounts.map((a) => [a.id.toString(), a]));
return serializeBigInt({
items: rows.map((row) => {
const hq = row.actorId ? hqMap.get(row.actorId.toString()) : undefined;
const action = row.param1Desc === 'action' ? row.param1 : row.param1;
return {
id: row.id,
hqAccountId: row.actorId,
hqName: hq?.name ?? null,
hqPhone: hq?.phone ?? null,
hqRole: hq?.adminRole ?? null,
action,
actionLabel: resolveHqOperationLabel(action, row.refType),
refType: row.param2Desc === 'target_type' ? row.param2 : row.refType,
refId: row.param3Desc === 'target_id' ? row.param3 : row.refId.toString(),
status: row.status,
remark: row.remark,
detail: row.extraJson,
createdAt: row.createdAt,
};
}),
total,
page,
pageSize,
});
}
async detail(id: bigint) {
const row = await this.prisma.commonEvent.findFirst({
where: { id, eventType: 'HQ_OPERATION' },
});
if (!row) throw new NotFoundException('操作日志不存在');
const hq = row.actorId
? await this.prisma.hqAccount.findUnique({
where: { id: row.actorId },
select: { id: true, name: true, phone: true, adminRole: true },
})
: null;
const action = row.param1Desc === 'action' ? row.param1 : row.param1;
return serializeBigInt({
id: row.id,
hqAccountId: row.actorId,
hqAccount: hq,
action,
actionLabel: resolveHqOperationLabel(action, row.refType),
refType: row.param2Desc === 'target_type' ? row.param2 : row.refType,
refId: row.param3Desc === 'target_id' ? row.param3 : row.refId.toString(),
status: row.status,
remark: row.remark,
detail: row.extraJson,
createdAt: row.createdAt,
});
}
}
@@ -1,6 +1,8 @@
import { Body, Controller, Get, Param, Post, Put, Query, UseGuards } from '@nestjs/common';
import { HqAuthGuard } from '../../common/guards/hq-auth.guard';
import { SuperAdminGuard } from '../../common/guards/super-admin.guard';
import { HqOperation } from '../../common/hq-operation/hq-operation.decorator';
import { HqOperationAction } from '../../common/hq-operation/hq-operation.constants';
import { AdminOrdersService } from './admin-orders.service';
import { AdminShipOrderDto, BatchDeleteOrdersDto, UpdateOrderStatusDto } from './dto/admin-mutate.dto';
import { AdminOrdersQueryDto } from './dto/admin-query.dto';
@@ -17,6 +19,12 @@ export class AdminOrdersController {
@Post('batch-delete')
@UseGuards(SuperAdminGuard)
@HqOperation({
action: HqOperationAction.ORDER_BATCH_DELETE,
refType: 'ORDER',
batch: true,
includeBody: true,
})
batchDelete(@Body() dto: BatchDeleteOrdersDto) {
return this.ordersService.batchDeleteOrders(dto.ids.map((id) => BigInt(id)));
}
@@ -33,12 +41,24 @@ export class AdminOrdersController {
/** HQ 发货:调用小飞侠创建运单并更新配送信息 */
@Post(':id/ship')
@HqOperation({
action: HqOperationAction.ORDER_SHIP,
refType: 'ORDER',
refIdParam: 'id',
includeBody: true,
})
ship(@Param('id') id: string, @Body() dto: AdminShipOrderDto) {
return this.ordersService.shipOrder(BigInt(id), dto);
}
/** preV1 调试:直接改订单状态,不走业务校验 */
@Put(':id/status')
@HqOperation({
action: HqOperationAction.ORDER_STATUS_DEBUG,
refType: 'ORDER',
refIdParam: 'id',
includeBody: true,
})
updateStatus(@Param('id') id: string, @Body() dto: UpdateOrderStatusDto) {
return this.ordersService.updateStatusDebug(BigInt(id), dto.status);
}
@@ -1,5 +1,7 @@
import { Body, Controller, Get, Param, Post, Put, Query, UseGuards } from '@nestjs/common';
import { HqAuthGuard } from '../../common/guards/hq-auth.guard';
import { HqOperation } from '../../common/hq-operation/hq-operation.decorator';
import { HqOperationAction } from '../../common/hq-operation/hq-operation.constants';
import { AdminPartnersService } from './admin-partners.service';
import { AdminPartnerAccountsQueryDto, AdminPartnersQueryDto } from './dto/admin-query.dto';
import {
@@ -25,11 +27,23 @@ export class AdminPartnersController {
}
@Post()
@HqOperation({
action: HqOperationAction.PARTNER_CREATE,
refType: 'PARTNER',
refIdField: 'id',
includeBody: true,
})
create(@Body() dto: CreatePartnerDto) {
return this.service.createPartner(dto);
}
@Put(':id')
@HqOperation({
action: HqOperationAction.PARTNER_UPDATE,
refType: 'PARTNER',
refIdParam: 'id',
includeBody: true,
})
update(@Param('id') id: string, @Body() dto: UpdatePartnerDto) {
return this.service.updatePartner(BigInt(id), dto);
}
@@ -51,11 +65,23 @@ export class AdminPartnerAccountsController {
}
@Post()
@HqOperation({
action: HqOperationAction.PARTNER_ACCOUNT_CREATE,
refType: 'PARTNER_ACCOUNT',
refIdField: 'id',
includeBody: true,
})
create(@Body() dto: CreatePartnerAccountDto) {
return this.service.createPartnerAccount(dto);
}
@Put(':id')
@HqOperation({
action: HqOperationAction.PARTNER_ACCOUNT_UPDATE,
refType: 'PARTNER_ACCOUNT',
refIdParam: 'id',
includeBody: true,
})
update(@Param('id') id: string, @Body() dto: UpdatePartnerAccountDto) {
return this.service.updatePartnerAccount(BigInt(id), dto);
}
@@ -1,5 +1,7 @@
import { Body, Controller, Get, Param, Post, Put, Query, UseGuards } from '@nestjs/common';
import { HqAuthGuard } from '../../common/guards/hq-auth.guard';
import { HqOperation } from '../../common/hq-operation/hq-operation.decorator';
import { HqOperationAction } from '../../common/hq-operation/hq-operation.constants';
import { AdminProductDetailTemplatesService } from './admin-product-detail-templates.service';
import { AdminProductDetailTemplatesQueryDto } from './dto/admin-query.dto';
import {
@@ -23,11 +25,23 @@ export class AdminProductDetailTemplatesController {
}
@Post()
@HqOperation({
action: HqOperationAction.PRODUCT_TEMPLATE_CREATE,
refType: 'PRODUCT_TEMPLATE',
refIdField: 'id',
includeBody: true,
})
create(@Body() dto: CreateProductDetailTemplateDto) {
return this.service.create(dto);
}
@Put(':id')
@HqOperation({
action: HqOperationAction.PRODUCT_TEMPLATE_UPDATE,
refType: 'PRODUCT_TEMPLATE',
refIdParam: 'id',
includeBody: true,
})
update(@Param('id') id: string, @Body() dto: UpdateProductDetailTemplateDto) {
return this.service.update(BigInt(id), dto);
}
@@ -1,5 +1,7 @@
import { Body, Controller, Delete, Get, Param, Post, Put, Query, UseGuards } from '@nestjs/common';
import { HqAuthGuard } from '../../common/guards/hq-auth.guard';
import { HqOperation } from '../../common/hq-operation/hq-operation.decorator';
import { HqOperationAction } from '../../common/hq-operation/hq-operation.constants';
import { AdminProductsService } from './admin-products.service';
import { AdminProductsQueryDto } from './dto/admin-query.dto';
import { CreateProductDto, UpdateProductDto } from './dto/admin-mutate.dto';
@@ -20,16 +22,19 @@ export class AdminProductsController {
}
@Post()
@HqOperation({ action: HqOperationAction.PRODUCT_CREATE, refType: 'PRODUCT', refIdField: 'id', includeBody: true })
create(@Body() dto: CreateProductDto) {
return this.service.create(dto);
}
@Put(':id')
@HqOperation({ action: HqOperationAction.PRODUCT_UPDATE, refType: 'PRODUCT', refIdParam: 'id', includeBody: true })
update(@Param('id') id: string, @Body() dto: UpdateProductDto) {
return this.service.update(BigInt(id), dto);
}
@Delete(':id')
@HqOperation({ action: HqOperationAction.PRODUCT_DELETE, refType: 'PRODUCT', refIdParam: 'id' })
remove(@Param('id') id: string) {
return this.service.remove(BigInt(id));
}
@@ -1,5 +1,7 @@
import { Body, Controller, Post, UseGuards } from '@nestjs/common';
import { HqAuthGuard } from '../../common/guards/hq-auth.guard';
import { HqOperation } from '../../common/hq-operation/hq-operation.decorator';
import { HqOperationAction } from '../../common/hq-operation/hq-operation.constants';
import { AdminRedeemDebugService } from './admin-redeem-debug.service';
import type {
AdminRedeemDebugCreateTokenDto,
@@ -13,6 +15,12 @@ export class AdminRedeemDebugController {
/** preV1 调试:为用户生成核销码 */
@Post('create-token')
@HqOperation({
action: HqOperationAction.REDEEM_DEBUG_CREATE_TOKEN,
refType: 'REDEEM_DEBUG',
batch: true,
includeBody: true,
})
createToken(@Body() dto: AdminRedeemDebugCreateTokenDto) {
return this.service.createToken(dto);
}
@@ -25,6 +33,12 @@ export class AdminRedeemDebugController {
/** preV1 调试:门店侧确认核销 */
@Post('confirm')
@HqOperation({
action: HqOperationAction.REDEEM_DEBUG_CONFIRM,
refType: 'REDEEM_DEBUG',
batch: true,
includeBody: true,
})
confirm(@Body() dto: AdminRedeemDebugStoreTokenDto) {
return this.service.confirm(dto);
}
@@ -1,5 +1,7 @@
import { Body, Controller, Get, Param, Put, Query, UseGuards } from '@nestjs/common';
import { HqAuthGuard } from '../../common/guards/hq-auth.guard';
import { HqOperation } from '../../common/hq-operation/hq-operation.decorator';
import { HqOperationAction } from '../../common/hq-operation/hq-operation.constants';
import { AdminRedeemService, AdminDeliveriesService } from './admin-redeem.service';
import { AdminDeliveriesQueryDto, AdminRedeemRecordsQueryDto } from './dto/admin-query.dto';
import { UpdateDeliveryDto } from './dto/admin-mutate.dto';
@@ -36,6 +38,12 @@ export class AdminDeliveriesController {
}
@Put(':id')
@HqOperation({
action: HqOperationAction.DELIVERY_UPDATE,
refType: 'DELIVERY',
refIdParam: 'id',
includeBody: true,
})
update(@Param('id') id: string, @Body() dto: UpdateDeliveryDto) {
return this.service.update(BigInt(id), dto);
}
@@ -1,5 +1,7 @@
import { Body, Controller, Delete, Get, Param, Post, Put, Query, UseGuards } from '@nestjs/common';
import { HqAuthGuard } from '../../common/guards/hq-auth.guard';
import { HqOperation } from '../../common/hq-operation/hq-operation.decorator';
import { HqOperationAction } from '../../common/hq-operation/hq-operation.constants';
import { AdminStoresService } from './admin-stores.service';
import {
AdminStoreAccountsQueryDto,
@@ -32,21 +34,25 @@ export class AdminStoresController {
}
@Post()
@HqOperation({ action: HqOperationAction.STORE_CREATE, refType: 'STORE', refIdField: 'id', includeBody: true })
create(@Body() dto: CreateStoreDto) {
return this.service.createStore(dto);
}
@Put(':id')
@HqOperation({ action: HqOperationAction.STORE_UPDATE, refType: 'STORE', refIdParam: 'id', includeBody: true })
update(@Param('id') id: string, @Body() dto: UpdateStoreDto) {
return this.service.updateStore(BigInt(id), dto);
}
@Put(':id/status')
@HqOperation({ action: HqOperationAction.STORE_STATUS, refType: 'STORE', refIdParam: 'id', includeBody: true })
updateStatus(@Param('id') id: string, @Body() dto: UpdateStoreStatusDto) {
return this.service.updateStoreStatus(BigInt(id), dto);
}
@Put(':id/audit')
@HqOperation({ action: HqOperationAction.STORE_AUDIT, refType: 'STORE', refIdParam: 'id', includeBody: true })
audit(@Param('id') id: string, @Body() body: { approved: boolean; remark?: string }) {
return this.service.auditStore(BigInt(id), body);
}
@@ -68,11 +74,23 @@ export class AdminStoreAccountsController {
}
@Post()
@HqOperation({
action: HqOperationAction.STORE_ACCOUNT_CREATE,
refType: 'STORE_ACCOUNT',
refIdField: 'id',
includeBody: true,
})
create(@Body() dto: CreateStoreAccountDto) {
return this.service.createStoreAccount(dto);
}
@Put(':id')
@HqOperation({
action: HqOperationAction.STORE_ACCOUNT_UPDATE,
refType: 'STORE_ACCOUNT',
refIdParam: 'id',
includeBody: true,
})
update(@Param('id') id: string, @Body() dto: UpdateStoreAccountDto) {
return this.service.updateStoreAccount(BigInt(id), dto);
}
@@ -89,16 +107,29 @@ export class AdminStoreMediaController {
}
@Post()
@HqOperation({
action: HqOperationAction.STORE_MEDIA_CREATE,
refType: 'STORE_MEDIA',
refIdField: 'id',
includeBody: true,
})
create(@Body() dto: CreateStoreMediaDto) {
return this.service.createStoreMedia(dto);
}
@Put(':id')
@HqOperation({
action: HqOperationAction.STORE_MEDIA_UPDATE,
refType: 'STORE_MEDIA',
refIdParam: 'id',
includeBody: true,
})
update(@Param('id') id: string, @Body() dto: UpdateStoreMediaDto) {
return this.service.updateStoreMedia(BigInt(id), dto);
}
@Delete(':id')
@HqOperation({ action: HqOperationAction.STORE_MEDIA_DELETE, refType: 'STORE_MEDIA', refIdParam: 'id' })
remove(@Param('id') id: string) {
return this.service.deleteStoreMedia(BigInt(id));
}
@@ -1,5 +1,7 @@
import { Body, Controller, Get, Param, Post, Query, UseGuards } from '@nestjs/common';
import { HqAuthGuard } from '../../common/guards/hq-auth.guard';
import { HqOperation } from '../../common/hq-operation/hq-operation.decorator';
import { HqOperationAction } from '../../common/hq-operation/hq-operation.constants';
import { AdminTicketsService } from './admin-tickets.service';
import { TicketListQueryDto } from '../common/dto/common-query.dto';
@@ -19,11 +21,23 @@ export class AdminTicketsController {
}
@Post(':id/approve')
@HqOperation({
action: HqOperationAction.TICKET_APPROVE,
refType: 'TICKET',
refIdParam: 'id',
includeBody: true,
})
approve(@Param('id') id: string, @Body() body: { remark?: string }) {
return this.service.approve(BigInt(id), body.remark);
}
@Post(':id/reject')
@HqOperation({
action: HqOperationAction.TICKET_REJECT,
refType: 'TICKET',
refIdParam: 'id',
includeBody: true,
})
reject(@Param('id') id: string, @Body() body: { remark?: string }) {
return this.service.reject(BigInt(id), body.remark);
}
@@ -1,6 +1,8 @@
import { Body, Controller, Delete, Get, Param, Post, Query, UseGuards } from '@nestjs/common';
import { HqAuthGuard } from '../../common/guards/hq-auth.guard';
import { SuperAdminGuard } from '../../common/guards/super-admin.guard';
import { HqOperation } from '../../common/hq-operation/hq-operation.decorator';
import { HqOperationAction } from '../../common/hq-operation/hq-operation.constants';
import { AdminUsersService } from './admin-users.service';
import { AdminUsersQueryDto } from './dto/admin-query.dto';
import { BatchDeleteUsersConfirmDto, BatchDeleteUsersDto } from './dto/admin-mutate.dto';
@@ -23,6 +25,12 @@ export class AdminUsersController {
@Post('batch-delete')
@UseGuards(SuperAdminGuard)
@HqOperation({
action: HqOperationAction.USER_BATCH_DELETE,
refType: 'USER',
batch: true,
includeBody: true,
})
batchDelete(@Body() dto: BatchDeleteUsersConfirmDto) {
return this.usersService.batchDeleteUsers(
dto.ids.map((id) => BigInt(id)),
@@ -37,6 +45,11 @@ export class AdminUsersController {
@Delete(':id')
@UseGuards(SuperAdminGuard)
@HqOperation({
action: HqOperationAction.USER_DELETE,
refType: 'USER',
refIdParam: 'id',
})
remove(@Param('id') id: string) {
return this.usersService.deleteUser(BigInt(id));
}
@@ -275,6 +275,28 @@ export class AdminUserLogsQueryDto extends PaginationQueryDto {
to?: string;
}
export class AdminHqLogsQueryDto extends PaginationQueryDto {
@IsOptional()
@IsString()
hqAccountId?: string;
@IsOptional()
@IsString()
action?: string;
@IsOptional()
@IsString()
refType?: string;
@IsOptional()
@IsString()
from?: string;
@IsOptional()
@IsString()
to?: string;
}
export class AdminStoreMediaQueryDto extends PaginationQueryDto {
@IsOptional()
@IsString()
@@ -23,6 +23,8 @@ import { AdminProductsController } from './admin-products.controller';
import { AdminProductsService } from './admin-products.service';
import { AdminUserLogsController } from './admin-user-logs.controller';
import { AdminUserLogsService } from './admin-user-logs.service';
import { AdminHqLogsController } from './admin-hq-logs.controller';
import { AdminHqLogsService } from './admin-hq-logs.service';
import { AdminTicketsController } from './admin-tickets.controller';
import { AdminTicketsService } from './admin-tickets.service';
import { SuperAdminGuard } from '../../common/guards/super-admin.guard';
@@ -56,6 +58,7 @@ import { AdminRedeemDebugService } from './admin-redeem-debug.service';
AdminHqAccountsController,
AdminProductsController,
AdminUserLogsController,
AdminHqLogsController,
AdminTicketsController,
AdminXiaofeixiaController,
AdminProductDetailTemplatesController,
@@ -74,6 +77,7 @@ import { AdminRedeemDebugService } from './admin-redeem-debug.service';
AdminHqAccountsService,
AdminProductsService,
AdminUserLogsService,
AdminHqLogsService,
AdminTicketsService,
AdminXiaofeixiaService,
AdminProductDetailTemplatesService,