import type { Request, Response } from 'express' import { errorResponse, successResponse } from '../utils/response' import { confirmInventoryParticipant, getInventoryTaskPublicInfo, getParticipantItems, getParticipantTaskContext, searchTaskParticipants, submitInventoryException, submitInventoryScan } from '../services/inventoryService' const INVENTORY_SESSION_KEY = 'inventoryParticipant' const getInventorySession = (req: Request) => ((req.session as any)?.[INVENTORY_SESSION_KEY] || null) as | { taskId: number participantId: number publicToken: string } | null const setInventorySession = ( req: Request, payload: { taskId: number participantId: number publicToken: string } ) => { ;(req.session as any)[INVENTORY_SESSION_KEY] = payload } const clearInventorySession = (req: Request) => { if ((req.session as any)?.[INVENTORY_SESSION_KEY]) { delete (req.session as any)[INVENTORY_SESSION_KEY] } } const ensureInventorySession = async (req: Request) => { const session = getInventorySession(req) if (!session) { throw new Error('盘点会话不存在,请重新确认身份') } const taskContext = await getParticipantTaskContext(session.taskId, session.participantId) if (taskContext.task.public_token !== session.publicToken) { clearInventorySession(req) throw new Error('盘点会话已失效,请重新确认身份') } return { session, ...taskContext } } export const getPublicInventoryTaskController = async (req: Request, res: Response) => { try { const data = await getInventoryTaskPublicInfo(req.params.token) successResponse(res, data, '获取成功') } catch (error: any) { const message = error.message || '获取盘点任务失败' errorResponse(res, message, message.includes('不存在') ? 404 : 500) } } export const searchPublicInventoryParticipantsController = async (req: Request, res: Response) => { try { const keyword = typeof req.query.keyword === 'string' ? req.query.keyword : '' const list = await searchTaskParticipants(req.params.token, keyword) successResponse(res, list, '获取成功') } catch (error: any) { const message = error.message || '搜索盘点人员失败' errorResponse(res, message, message.includes('不存在') ? 404 : 500) } } export const confirmPublicInventoryParticipantController = async (req: Request, res: Response) => { try { const participantId = Number(req.body?.participant_id) if (!Number.isInteger(participantId) || participantId <= 0) { return errorResponse(res, '请选择盘点人员', 422) } const data = await confirmInventoryParticipant(req.params.token, participantId) setInventorySession(req, { taskId: data.task_id, participantId: data.participant_id, publicToken: req.params.token }) successResponse(res, data, '确认成功') } catch (error: any) { const message = error.message || '确认盘点身份失败' errorResponse(res, message, message.includes('不存在') ? 404 : 422) } } export const getPublicInventoryMeController = async (req: Request, res: Response) => { try { const { task, participant } = await ensureInventorySession(req) successResponse( res, { task: { id: task.id, title: task.title, status: task.status, scope_department_name: task.scope_department_name, scope_asset_type_name: task.scope_asset_type_name, completed_count: task.completed_count, exception_count: task.exception_count, items_count: task.items_count, closed_at: task.closed_at }, participant }, '获取成功' ) } catch (error: any) { const message = error.message || '获取盘点会话失败' errorResponse(res, message, message.includes('不存在') ? 404 : 401) } } export const getPublicInventoryItemsController = async (req: Request, res: Response) => { try { const { task, participant } = await ensureInventorySession(req) const data = await getParticipantItems(task.id, participant.id) successResponse(res, data, '获取成功') } catch (error: any) { const message = error.message || '获取盘点资产失败' errorResponse(res, message, message.includes('不存在') ? 404 : 401) } } export const submitPublicInventoryScanController = async (req: Request, res: Response) => { try { const { task, participant } = await ensureInventorySession(req) if (task.status === 'closed') { return errorResponse(res, '盘点任务已关闭', 403) } const equipmentCode = String(req.body?.equipment_code || '').trim() if (!equipmentCode) { return errorResponse(res, '资产编码不能为空', 422) } const data = await submitInventoryScan(task.id, participant.id, equipmentCode) successResponse(res, data, '盘点成功') } catch (error: any) { const message = error.message || '提交盘点结果失败' errorResponse( res, message, message.includes('盘点范围') || message.includes('不能为空') ? 422 : message.includes('不存在') ? 404 : 401 ) } } export const submitPublicInventoryExceptionController = async (req: Request, res: Response) => { try { const { task, participant } = await ensureInventorySession(req) if (task.status === 'closed') { return errorResponse(res, '盘点任务已关闭', 403) } const itemId = Number(req.params.itemId) if (!Number.isInteger(itemId) || itemId <= 0) { return errorResponse(res, '盘点资产不存在', 404) } await submitInventoryException( task.id, participant.id, itemId, String(req.body?.exception_type || ''), req.body?.exception_note ) successResponse(res, null, '异常已提交') } catch (error: any) { const message = error.message || '提交盘点异常失败' errorResponse( res, message, message.includes('不存在') ? 404 : message.includes('无效') ? 422 : 401 ) } }