feat(M08-B): 补任务事件流水
This commit is contained in:
@@ -56,6 +56,17 @@ interface CleaningTaskMemberRow extends RowDataPacket {
|
||||
removedAt: Date | null;
|
||||
settledAt: Date | null;
|
||||
}
|
||||
interface CleaningTaskEventRow extends RowDataPacket {
|
||||
id: string;
|
||||
taskId: string;
|
||||
fromStatus: CleaningTaskStatus | null;
|
||||
toStatus: CleaningTaskStatus;
|
||||
action: string;
|
||||
actorId: string;
|
||||
traceId: string;
|
||||
note: string;
|
||||
createdAt: Date;
|
||||
}
|
||||
interface CountRow extends RowDataPacket { total: number }
|
||||
interface StatusCountRow extends RowDataPacket { status: CleaningTaskStatus; total: number }
|
||||
interface AmountRow extends RowDataPacket { amount: number | null }
|
||||
@@ -284,6 +295,22 @@ export class CleaningTaskRepository {
|
||||
return this.getMembers(input.tenantId, input.taskId);
|
||||
}
|
||||
|
||||
async listEvents(input: CleaningActor & { taskId: string }) {
|
||||
this.assertCleaner(input.access, 'read');
|
||||
await this.assertStoreVisible(input, input.taskId);
|
||||
const [rows] = await this.pool.execute<CleaningTaskEventRow[]>(
|
||||
`SELECT e.id, e.task_id AS taskId, e.from_status AS fromStatus,
|
||||
e.to_status AS toStatus, e.action, e.actor_id AS actorId,
|
||||
e.trace_id AS traceId, e.note, e.created_at AS createdAt
|
||||
FROM qipai_cleaning_task_events e
|
||||
WHERE e.tenant_id = ? AND e.task_id = ?
|
||||
ORDER BY e.id DESC
|
||||
LIMIT 50`,
|
||||
[input.tenantId, input.taskId]
|
||||
);
|
||||
return rows.map(publicTaskEvent);
|
||||
}
|
||||
|
||||
async addMember(input: CleaningActor & {
|
||||
taskId: string; cleanerUserId: string; rewardCents: number; note?: string;
|
||||
}) {
|
||||
@@ -1307,6 +1334,20 @@ function publicTaskMember(row: CleaningTaskMemberRow) {
|
||||
};
|
||||
}
|
||||
|
||||
function publicTaskEvent(row: CleaningTaskEventRow) {
|
||||
return {
|
||||
id: String(row.id),
|
||||
taskId: String(row.taskId),
|
||||
fromStatus: row.fromStatus,
|
||||
toStatus: row.toStatus,
|
||||
action: row.action,
|
||||
actorId: String(row.actorId),
|
||||
traceId: row.traceId,
|
||||
note: row.note,
|
||||
createdAt: row.createdAt
|
||||
};
|
||||
}
|
||||
|
||||
function publicSettlement(row: SettlementRow) {
|
||||
return {
|
||||
id: String(row.id),
|
||||
|
||||
@@ -100,7 +100,7 @@ const reclaimSchema = z.object({
|
||||
export interface CleaningRouteOptions {
|
||||
repository: Pick<CleaningTaskRepository,
|
||||
'listHall' | 'listMine' | 'listManage' | 'claim' | 'start' | 'rework' | 'submit'
|
||||
| 'assign' | 'complete' | 'reject' | 'listMembers' | 'addMember' | 'removeMember' | 'settlementCandidates'
|
||||
| 'assign' | 'complete' | 'reject' | 'listMembers' | 'listEvents' | 'addMember' | 'removeMember' | 'settlementCandidates'
|
||||
| 'listSettlements' | 'getSettlementDetail' | 'generateSettlement' | 'confirmSettlement' | 'markSettlementPaid'
|
||||
| 'recordSettlementPayoutFailure' | 'reclaimTimeouts'
|
||||
| 'assertCanUploadPhoto' | 'stats' | 'managerStatistics'>;
|
||||
@@ -264,6 +264,18 @@ export async function registerCleaningRoutes(
|
||||
}));
|
||||
});
|
||||
|
||||
app.get('/admin-api/cleaning/tasks/:taskId/events', async (request, reply) => {
|
||||
const actor = await requireActor(request, reply, options, 'read');
|
||||
if (!actor) return;
|
||||
const params = paramsSchema.safeParse(request.params);
|
||||
if (!params.success) return invalid(reply, request.traceId);
|
||||
return handle(reply, request.traceId, async () => ({
|
||||
code: 0,
|
||||
data: await options.repository.listEvents({ ...actor, taskId: params.data.taskId }),
|
||||
traceId: request.traceId
|
||||
}));
|
||||
});
|
||||
|
||||
app.post('/admin-api/cleaning/tasks/:taskId/members', async (request, reply) => {
|
||||
const actor = await requireActor(request, reply, options, 'write');
|
||||
if (!actor) return;
|
||||
|
||||
Reference in New Issue
Block a user