import type { Request } from 'express' import { Router } from 'express' import { applyAdminTemplateProductBootstrap, backfillAdminNormalizedQuantities, backfillAdminProductMappings, createAdminChannelMapping, createAdminCostItem, createAdminCostSnapshot, createAdminCostVersion, createAdminProduct, deleteAdminChannelMapping, deleteAdminCostItem, deleteAdminCostVersion, deleteAdminProduct, getAdminCostCenterOptions, getAdminCostCenterOverview, listAdminChannelMappings, listAdminCostExceptions, listAdminCostItems, listAdminCostVersions, listAdminProducts, previewAdminCost, previewAdminTemplateProductBootstrap, resolveAdminCostException, retireAdminCostVersion, syncAdminAffiliateDashProducts, updateAdminChannelMapping, updateAdminCostItem, updateAdminProduct, } from '../../services/admin/admin-cost-center-service.js' import type { AdminSession } from '../../services/admin/admin-auth-service.js' import type { JsonObject } from '../../types/json.js' import { createJsonHandler, requireAdminPermission, requireAdminRoles } from './session.js' const router = Router() function sessionOf(req: Request): AdminSession { return req.adminSession as AdminSession } function idOf(req: Request, key: string): number { return Number(req.params[key]) } function bodyOf(req: Request): JsonObject { return req.body && typeof req.body === 'object' ? (req.body as JsonObject) : {} } router.use('/cost-center', requireAdminRoles(['admin', 'operator', 'finance'])) router.get( '/cost-center/overview', requireAdminPermission('finance.view'), createJsonHandler(() => getAdminCostCenterOverview(), { successMessage: 'ok', errorMessage: '读取成本中心总览失败', scope: '[admin/cost-center/overview]', }), ) router.get( '/cost-center/options', requireAdminPermission('finance.view'), createJsonHandler(() => getAdminCostCenterOptions(), { successMessage: 'ok', errorMessage: '读取成本中心选项失败', scope: '[admin/cost-center/options]', }), ) router.get( '/cost-center/template-bootstrap/preview', requireAdminPermission('finance.view'), createJsonHandler(() => previewAdminTemplateProductBootstrap(), { successMessage: 'ok', errorMessage: '读取接单模板初始化预览失败', scope: '[admin/cost-center/template-bootstrap/preview]', }), ) router.post( '/cost-center/template-bootstrap/apply', requireAdminPermission('finance.config'), createJsonHandler((req) => applyAdminTemplateProductBootstrap(bodyOf(req), sessionOf(req)), { successMessage: '接单模板初始化完成', errorMessage: '接单模板初始化失败', scope: '[admin/cost-center/template-bootstrap/apply]', audit: (_req, data) => ({ action: 'cost_template_bootstrap_applied', targetType: 'product_catalog', targetId: '', data: data as Record, }), }), ) router.post( '/cost-center/affiliate-products/sync', requireAdminPermission('finance.config'), createJsonHandler(() => syncAdminAffiliateDashProducts(), { successMessage: '自动发货商品已同步', errorMessage: '同步自动发货商品失败', scope: '[admin/cost-center/affiliate-products/sync]', audit: (_req, data) => ({ action: 'cost_affiliate_products_synced', targetType: 'product_catalog', targetId: '', data: data as Record, }), }), ) router.get( '/cost-center/products', requireAdminPermission('finance.view'), createJsonHandler((req) => listAdminProducts(req.query as JsonObject), { successMessage: 'ok', errorMessage: '读取标准商品失败', scope: '[admin/cost-center/products]', }), ) router.post( '/cost-center/products', requireAdminPermission('finance.config'), createJsonHandler((req) => createAdminProduct(bodyOf(req), sessionOf(req)), { successMessage: '标准商品已创建', errorMessage: '创建标准商品失败', scope: '[admin/cost-center/products]', audit: (_req, data) => { const product = (data as { product?: { id?: number; canonicalSku?: string } })?.product return { action: 'cost_product_created', targetType: 'product_catalog', targetId: String(product?.id || ''), data: { canonicalSku: product?.canonicalSku || '' }, } }, }), ) router.patch( '/cost-center/products/:productId', requireAdminPermission('finance.config'), createJsonHandler((req) => updateAdminProduct(idOf(req, 'productId'), bodyOf(req)), { successMessage: '标准商品已更新', errorMessage: '更新标准商品失败', scope: '[admin/cost-center/products/:productId]', audit: (req, data) => { const product = (data as { product?: { id?: number; canonicalSku?: string } })?.product return { action: 'cost_product_updated', targetType: 'product_catalog', targetId: String(product?.id || req.params.productId || ''), data: { canonicalSku: product?.canonicalSku || '' }, } }, }), ) router.delete( '/cost-center/products/:productId', requireAdminPermission('finance.config'), createJsonHandler((req) => deleteAdminProduct(idOf(req, 'productId')), { successMessage: '标准商品已删除', errorMessage: '删除标准商品失败', scope: '[admin/cost-center/products/:productId]', audit: (req, data) => { const product = (data as { product?: { id?: number; canonicalSku?: string } })?.product return { action: 'cost_product_deleted', targetType: 'product_catalog', targetId: String(product?.id || req.params.productId || ''), data: { canonicalSku: product?.canonicalSku || '' }, } }, }), ) router.get( '/cost-center/mappings', requireAdminPermission('finance.view'), createJsonHandler((req) => listAdminChannelMappings(req.query as JsonObject), { successMessage: 'ok', errorMessage: '读取渠道映射失败', scope: '[admin/cost-center/mappings]', }), ) router.post( '/cost-center/mappings', requireAdminPermission('finance.config'), createJsonHandler((req) => createAdminChannelMapping(bodyOf(req), sessionOf(req)), { successMessage: '渠道映射已创建', errorMessage: '创建渠道映射失败', scope: '[admin/cost-center/mappings]', audit: (_req, data) => { const mapping = ( data as { mapping?: { id?: number; provider?: string; platformSkuCode?: string } } )?.mapping return { action: 'cost_mapping_created', targetType: 'channel_product_mapping', targetId: String(mapping?.id || ''), data: { provider: mapping?.provider || '', platformSkuCode: mapping?.platformSkuCode || '', }, } }, }), ) router.patch( '/cost-center/mappings/:mappingId', requireAdminPermission('finance.config'), createJsonHandler((req) => updateAdminChannelMapping(idOf(req, 'mappingId'), bodyOf(req)), { successMessage: '渠道映射已更新', errorMessage: '更新渠道映射失败', scope: '[admin/cost-center/mappings/:mappingId]', audit: (req, data) => { const mapping = ( data as { mapping?: { id?: number; provider?: string; platformSkuCode?: string } } )?.mapping return { action: 'cost_mapping_updated', targetType: 'channel_product_mapping', targetId: String(mapping?.id || req.params.mappingId || ''), data: { provider: mapping?.provider || '', platformSkuCode: mapping?.platformSkuCode || '', }, } }, }), ) router.delete( '/cost-center/mappings/:mappingId', requireAdminPermission('finance.config'), createJsonHandler((req) => deleteAdminChannelMapping(idOf(req, 'mappingId')), { successMessage: '渠道映射已删除', errorMessage: '删除渠道映射失败', scope: '[admin/cost-center/mappings/:mappingId]', audit: (req, data) => { const mappingId = (data as { mappingId?: number })?.mappingId return { action: 'cost_mapping_deleted', targetType: 'channel_product_mapping', targetId: String(mappingId || req.params.mappingId || ''), data: {}, } }, }), ) router.post( '/cost-center/mappings/backfill', requireAdminPermission('finance.config'), createJsonHandler((req) => backfillAdminProductMappings(bodyOf(req)), { successMessage: '商品映射回填完成', errorMessage: '回填商品映射失败', scope: '[admin/cost-center/mappings/backfill]', audit: (_req, data) => ({ action: 'cost_mapping_backfilled', targetType: 'order_item', targetId: '', data: data as Record, }), }), ) router.post( '/cost-center/normalized-quantities/backfill', requireAdminPermission('finance.config'), createJsonHandler((req) => backfillAdminNormalizedQuantities(bodyOf(req)), { successMessage: '归一数量回填完成', errorMessage: '回填归一数量失败', scope: '[admin/cost-center/normalized-quantities/backfill]', audit: (_req, data) => ({ action: 'order_item_quantity_backfilled', targetType: 'order_item', targetId: '', data: data as Record, }), }), ) router.get( '/cost-center/cost-items', requireAdminPermission('finance.view'), createJsonHandler((req) => listAdminCostItems(req.query as JsonObject), { successMessage: 'ok', errorMessage: '读取成本项目失败', scope: '[admin/cost-center/cost-items]', }), ) router.post( '/cost-center/cost-items', requireAdminPermission('finance.config'), createJsonHandler((req) => createAdminCostItem(bodyOf(req), sessionOf(req)), { successMessage: '成本项目已创建', errorMessage: '创建成本项目失败', scope: '[admin/cost-center/cost-items]', audit: (_req, data) => { const item = (data as { costItem?: { id?: number; code?: string } })?.costItem return { action: 'cost_item_created', targetType: 'cost_item', targetId: String(item?.id || ''), data: { code: item?.code || '' }, } }, }), ) router.patch( '/cost-center/cost-items/:costItemId', requireAdminPermission('finance.config'), createJsonHandler((req) => updateAdminCostItem(idOf(req, 'costItemId'), bodyOf(req)), { successMessage: '成本项目已更新', errorMessage: '更新成本项目失败', scope: '[admin/cost-center/cost-items/:costItemId]', audit: (req, data) => { const item = (data as { costItem?: { id?: number; code?: string } })?.costItem return { action: 'cost_item_updated', targetType: 'cost_item', targetId: String(item?.id || req.params.costItemId || ''), data: { code: item?.code || '' }, } }, }), ) router.delete( '/cost-center/cost-items/:costItemId', requireAdminPermission('finance.config'), createJsonHandler((req) => deleteAdminCostItem(idOf(req, 'costItemId')), { successMessage: '成本项目已删除', errorMessage: '删除成本项目失败', scope: '[admin/cost-center/cost-items/:costItemId]', audit: (req, data) => { const item = (data as { costItem?: { id?: number; code?: string } })?.costItem return { action: 'cost_item_deleted', targetType: 'cost_item', targetId: String(item?.id || req.params.costItemId || ''), data: { code: item?.code || '' }, } }, }), ) router.get( '/cost-center/cost-versions', requireAdminPermission('finance.view'), createJsonHandler((req) => listAdminCostVersions(req.query as JsonObject), { successMessage: 'ok', errorMessage: '读取成本版本失败', scope: '[admin/cost-center/cost-versions]', }), ) router.post( '/cost-center/cost-versions', requireAdminPermission('finance.config'), createJsonHandler((req) => createAdminCostVersion(bodyOf(req), sessionOf(req)), { successMessage: '成本版本已创建', errorMessage: '创建成本版本失败', scope: '[admin/cost-center/cost-versions]', audit: (_req, data) => { const version = (data as { version?: { id?: number; costItemId?: number } })?.version return { action: 'cost_version_created', targetType: 'cost_version', targetId: String(version?.id || ''), data: { costItemId: version?.costItemId || 0 }, } }, }), ) router.patch( '/cost-center/cost-versions/:versionId/retire', requireAdminPermission('finance.config'), createJsonHandler((req) => retireAdminCostVersion(idOf(req, 'versionId'), bodyOf(req)), { successMessage: '成本版本已停用', errorMessage: '停用成本版本失败', scope: '[admin/cost-center/cost-versions/:versionId/retire]', audit: (req, data) => { const version = (data as { version?: { id?: number } })?.version return { action: 'cost_version_retired', targetType: 'cost_version', targetId: String(version?.id || req.params.versionId || ''), data: {}, } }, }), ) router.delete( '/cost-center/cost-versions/:versionId', requireAdminPermission('finance.config'), createJsonHandler((req) => deleteAdminCostVersion(idOf(req, 'versionId')), { successMessage: '成本版本已删除', errorMessage: '删除成本版本失败', scope: '[admin/cost-center/cost-versions/:versionId]', audit: (req, data) => { const version = (data as { version?: { id?: number } })?.version return { action: 'cost_version_deleted', targetType: 'cost_version', targetId: String(version?.id || req.params.versionId || ''), data: {}, } }, }), ) router.get( '/cost-center/exceptions', requireAdminPermission('finance.view'), createJsonHandler((req) => listAdminCostExceptions(req.query as JsonObject), { successMessage: 'ok', errorMessage: '读取成本异常失败', scope: '[admin/cost-center/exceptions]', }), ) router.patch( '/cost-center/exceptions/:exceptionId', requireAdminPermission('finance.config'), createJsonHandler( (req) => resolveAdminCostException(idOf(req, 'exceptionId'), bodyOf(req), sessionOf(req)), { successMessage: '成本异常已处理', errorMessage: '处理成本异常失败', scope: '[admin/cost-center/exceptions/:exceptionId]', audit: (req, data) => { const exception = (data as { exception?: { id?: number; status?: string } })?.exception return { action: 'cost_exception_resolved', targetType: 'cost_exception', targetId: String(exception?.id || req.params.exceptionId || ''), data: { status: exception?.status || '' }, } }, }, ), ) router.post( '/cost-center/preview', requireAdminPermission('finance.view'), createJsonHandler((req) => previewAdminCost(bodyOf(req)), { successMessage: 'ok', errorMessage: '成本预览失败', scope: '[admin/cost-center/preview]', }), ) router.post( '/cost-center/snapshots', requireAdminPermission('finance.config'), createJsonHandler((req) => createAdminCostSnapshot(bodyOf(req), sessionOf(req)), { successMessage: '成本快照已生成', errorMessage: '生成成本快照失败', scope: '[admin/cost-center/snapshots]', audit: (req, data) => { const result = data as { createdCount?: number exceptionCreatedCount?: number preview?: { context?: { orderItemId?: number } } } return { action: 'cost_snapshot_created', targetType: 'order_item', targetId: String(result.preview?.context?.orderItemId || req.body?.orderItemId || ''), data: { createdCount: result.createdCount || 0, exceptionCreatedCount: result.exceptionCreatedCount || 0, }, } }, }), ) export default router