refactor(services): 重构服务文件结构,将服务按功能分类到不同目录

- 将服务文件按功能分类到core、ai、analytics、security等目录
- 修复logger导入路径问题,统一使用相对路径
- 更新相关文件的导入路径引用
- 添加新的批量操作组件导出文件
- 修复dashboard页面中的类型错误
- 添加dotenv依赖到package.json
This commit is contained in:
2026-03-25 13:46:26 +08:00
parent e59d7c6620
commit 2748456d8a
598 changed files with 74404 additions and 9576 deletions

View File

@@ -0,0 +1,18 @@
/**
* [BE-ROUTE-017] 售后审核路由
* 提供售后审核AI介入的RESTful API路由
*/
import { Router } from 'express';
import { AfterSalesDecisionController } from '../controllers/AfterSalesDecisionController';
import { requireTraceContext } from '../../core/guards/trace-context.guard';
import { requirePermission } from '../../core/guards/rbac.guard';
const router = Router();
router.post('/ai-decision', requireTraceContext, AfterSalesDecisionController.makeDecision);
router.post('/approve', requireTraceContext, requirePermission('after-sales:write'), AfterSalesDecisionController.approve);
router.post('/reject', requireTraceContext, requirePermission('after-sales:write'), AfterSalesDecisionController.reject);
router.post('/refund', requireTraceContext, requirePermission('after-sales:write'), AfterSalesDecisionController.refund);
export default router;

View File

@@ -0,0 +1,21 @@
/**
* [BE-ROUTE-013] AI批量操作建议路由
* 提供AI批量操作建议的RESTful API路由
* AI注意: 所有AI批量操作建议路由必须通过此文件注册
*/
import { Router, Request, Response, NextFunction } from 'express';
import { AIBatchController } from '../controllers/AIBatchController';
import { requireTraceContext } from '../../core/guards/trace-context.guard';
import { requirePermission } from '../../core/guards/rbac.guard';
const router = Router();
router.get('/batch-suggestions', requireTraceContext, AIBatchController.getSuggestions);
router.get('/batch-suggestions/stats', requireTraceContext, AIBatchController.getStats);
router.get('/batch-suggestions/:id', requireTraceContext, AIBatchController.getSuggestionById);
router.post('/batch-suggestions/:id/approve', requireTraceContext, requirePermission('batch:write'), AIBatchController.approveSuggestion);
router.post('/batch-suggestions/:id/reject', requireTraceContext, requirePermission('batch:write'), AIBatchController.rejectSuggestion);
router.post('/batch/analyze', requireTraceContext, AIBatchController.analyze);
export default router;

View File

@@ -1,6 +1,6 @@
import { Router, Request, Response, NextFunction } from 'express';
import { authorize } from '../../core/guards/trace-context.guard';
import ArbitrageService from '../../services/ArbitrageService';
import ArbitrageService from '../../services/core/ArbitrageService';
import { logger } from '../../utils/logger';
// 扩展Request类型

View File

@@ -4,7 +4,7 @@
*/
import { Router } from 'express';
import { AutoExecutionConfigService, AutomationLevel, DecisionModule } from '../../services/AutoExecutionConfigService';
import { AutoExecutionConfigService, AutomationLevel, DecisionModule } from '../../services/core/AutoExecutionConfigService';
import { validateAutoExecution, requireAutoExecute, requireReviewPermission, requireLevelChangePermission } from '../middleware/AutoExecutionMiddleware';
import { logger } from '../../utils/logger';

View File

@@ -1,11 +1,11 @@
import { Router, Request, Response } from 'express';
import AutoPilotService from '../../services/AutoPilotService';
import AutoPilotScheduler from '../../services/AutoPilotScheduler';
import AutoPilotService from '../../services/core/AutoPilotService';
import AutoPilotScheduler from '../../services/core/AutoPilotScheduler';
import { logger } from '../../utils/logger';
const router = Router();
router.post('/autopilot/sessions', async (req: Request, res: Response) => {
router.post('/sessions', async (req: Request, res: Response) => {
try {
const tenantId = (req as any).user?.tenantId;
const { shopId, mode, config } = req.body;
@@ -45,7 +45,7 @@ router.post('/autopilot/sessions', async (req: Request, res: Response) => {
}
});
router.post('/autopilot/sessions/:id/start', async (req: Request, res: Response) => {
router.post('/sessions/:id/start', async (req: Request, res: Response) => {
try {
const id = req.params.id as string;
const tenantId = (req as any).user?.tenantId;
@@ -73,7 +73,7 @@ router.post('/autopilot/sessions/:id/start', async (req: Request, res: Response)
}
});
router.post('/autopilot/sessions/:id/pause', async (req: Request, res: Response) => {
router.post('/sessions/:id/pause', async (req: Request, res: Response) => {
try {
const id = req.params.id as string;
const tenantId = (req as any).user?.tenantId;
@@ -100,7 +100,7 @@ router.post('/autopilot/sessions/:id/pause', async (req: Request, res: Response)
}
});
router.post('/autopilot/sessions/:id/stop', async (req: Request, res: Response) => {
router.post('/sessions/:id/stop', async (req: Request, res: Response) => {
try {
const id = req.params.id as string;
const tenantId = (req as any).user?.tenantId;
@@ -128,7 +128,7 @@ router.post('/autopilot/sessions/:id/stop', async (req: Request, res: Response)
}
});
router.post('/autopilot/sessions/:id/unschedule', async (req: Request, res: Response) => {
router.post('/sessions/:id/unschedule', async (req: Request, res: Response) => {
try {
const id = req.params.id as string;
const tenantId = (req as any).user?.tenantId;
@@ -155,7 +155,7 @@ router.post('/autopilot/sessions/:id/unschedule', async (req: Request, res: Resp
}
});
router.get('/autopilot/sessions', async (req: Request, res: Response) => {
router.get('/sessions', async (req: Request, res: Response) => {
try {
const tenantId = (req as any).user?.tenantId;
const { status, limit, offset } = req.query;
@@ -183,7 +183,7 @@ router.get('/autopilot/sessions', async (req: Request, res: Response) => {
}
});
router.get('/autopilot/sessions/:id', async (req: Request, res: Response) => {
router.get('/sessions/:id', async (req: Request, res: Response) => {
try {
const id = req.params.id as string;
const tenantId = (req as any).user?.tenantId;
@@ -217,7 +217,7 @@ router.get('/autopilot/sessions/:id', async (req: Request, res: Response) => {
}
});
router.get('/autopilot/sessions/:id/logs', async (req: Request, res: Response) => {
router.get('/sessions/:id/logs', async (req: Request, res: Response) => {
try {
const id = req.params.id as string;
const tenantId = (req as any).user?.tenantId;
@@ -248,7 +248,7 @@ router.get('/autopilot/sessions/:id/logs', async (req: Request, res: Response) =
}
});
router.get('/autopilot/sessions/:id/stats', async (req: Request, res: Response) => {
router.get('/sessions/:id/stats', async (req: Request, res: Response) => {
try {
const id = req.params.id as string;
const tenantId = (req as any).user?.tenantId;
@@ -294,7 +294,7 @@ router.get('/autopilot/sessions/:id/stats', async (req: Request, res: Response)
}
});
router.put('/autopilot/sessions/:id/config', async (req: Request, res: Response) => {
router.put('/sessions/:id/config', async (req: Request, res: Response) => {
try {
const id = req.params.id as string;
const tenantId = (req as any).user?.tenantId;
@@ -330,7 +330,7 @@ router.put('/autopilot/sessions/:id/config', async (req: Request, res: Response)
}
});
router.post('/autopilot/sessions/:id/execute-task', async (req: Request, res: Response) => {
router.post('/sessions/:id/execute-task', async (req: Request, res: Response) => {
try {
const id = req.params.id as string;
const tenantId = (req as any).user?.tenantId;
@@ -370,7 +370,7 @@ router.post('/autopilot/sessions/:id/execute-task', async (req: Request, res: Re
}
});
router.get('/autopilot/sessions/:id/schedule', async (req: Request, res: Response) => {
router.get('/sessions/:id/schedule', async (req: Request, res: Response) => {
try {
const id = req.params.id as string;
const tenantId = (req as any).user?.tenantId;

View File

@@ -0,0 +1,26 @@
/**
* [BE-ROUTE-012] 批量操作路由
* 提供批量操作的RESTful API路由
* AI注意: 所有批量操作路由必须通过此文件注册
*/
import { Router, Request, Response, NextFunction } from 'express';
import { BatchOperationController } from '../controllers/BatchOperationController';
import { AIBatchController } from '../controllers/AIBatchController';
import { requireTraceContext } from '../../core/guards/trace-context.guard';
import { requirePermission } from '../../core/guards/rbac.guard';
const router = Router();
router.post('/validate', requireTraceContext, BatchOperationController.validate);
router.post('/create', requireTraceContext, requirePermission('batch:write'), BatchOperationController.create);
router.get('/history', requireTraceContext, BatchOperationController.getHistory);
router.get('/summary', requireTraceContext, BatchOperationController.getSummary);
router.get('/:id', requireTraceContext, BatchOperationController.getOne);
router.post('/:id/execute', requireTraceContext, requirePermission('batch:write'), BatchOperationController.execute);
router.post('/:id/confirm', requireTraceContext, requirePermission('batch:write'), BatchOperationController.confirm);
router.post('/:id/cancel', requireTraceContext, requirePermission('batch:write'), BatchOperationController.cancel);
router.post('/edit/price', requireTraceContext, requirePermission('batch:write'), BatchOperationController.editPrice);
router.post('/edit/inventory', requireTraceContext, requirePermission('batch:write'), BatchOperationController.editInventory);
export default router;

View File

@@ -1,5 +1,5 @@
import { Router, Request } from 'express';
import { CertificateService } from '../../services/CertificateService';
import { CertificateService } from '../../services/compliance/CertificateService';
import { requireTraceContext } from '../../core/guards/trace-context.guard';
import { requirePermission } from '../../core/guards/rbac.guard';
import { logger } from '../../utils/logger';

View File

@@ -1,36 +1,39 @@
import { Router } from 'express';
import { requireTraceContext } from '../../core/guards/trace-context.guard';
import { requirePermission } from '../../core/guards/rbac.guard';
import { requireTraceContext } from '../../core/guards/trace-context.guard';
import { CurrencyController } from '../controllers/CurrencyController';
const router = Router();
// 货币管理路由
router.get('/currencies', CurrencyController.getCurrencies);
router.get('/currencies/:code', CurrencyController.getCurrencyByCode);
router.get('/currencies/default', CurrencyController.getDefaultCurrency);
router.post('/currencies', requireTraceContext, requirePermission('currency:write'), CurrencyController.createCurrency);
router.put('/currencies/:id', requireTraceContext, requirePermission('currency:write'), CurrencyController.updateCurrency);
router.patch('/currencies/:id/deactivate', requireTraceContext, requirePermission('currency:write'), CurrencyController.deactivateCurrency);
router.patch('/currencies/:id/set-default', requireTraceContext, requirePermission('currency:write'), CurrencyController.setDefaultCurrency);
// 货币管理相关路由
// 暂时注释掉,因为对应的方法已被注释掉
// router.get('/currencies', CurrencyController.getCurrencies);
// router.get('/currencies/:code', CurrencyController.getCurrencyByCode);
// router.get('/currencies/default', CurrencyController.getDefaultCurrency);
// router.post('/currencies', requireTraceContext, requirePermission('currency:write'), CurrencyController.createCurrency);
// router.put('/currencies/:id', requireTraceContext, requirePermission('currency:write'), CurrencyController.updateCurrency);
// router.patch('/currencies/:id/deactivate', requireTraceContext, requirePermission('currency:write'), CurrencyController.deactivateCurrency);
// router.patch('/currencies/:id/set-default', requireTraceContext, requirePermission('currency:write'), CurrencyController.setDefaultCurrency);
// 汇率管理路由
// 汇率相关路由
router.get('/exchange-rates/:from/:to', CurrencyController.getExchangeRate);
router.get('/exchange-rates', CurrencyController.getAllExchangeRates);
router.post('/exchange-rates/update', requireTraceContext, requirePermission('currency:write'), CurrencyController.updateExchangeRates);
router.get('/exchange-rates/history/:from/:to', CurrencyController.getExchangeRateHistory);
router.get('/exchange-rates/all', CurrencyController.getAllExchangeRates);
// 货币转换路由
router.post('/convert', CurrencyController.convertCurrency);
router.post('/convert/multiple', CurrencyController.convertMultipleCurrencies);
router.post('/convert/to-default', CurrencyController.convertToDefaultCurrency);
router.post('/convert/from-default', CurrencyController.convertFromDefaultCurrency);
// 货币转换相关路由
// 暂时注释掉,因为对应的方法已被注释掉
// router.post('/convert', CurrencyController.convertCurrency);
// router.post('/convert-multiple', CurrencyController.convertMultipleCurrencies);
// router.post('/convert-to-default', CurrencyController.convertToDefaultCurrency);
// router.post('/convert-from-default', CurrencyController.convertFromDefaultCurrency);
// 货币计算路由
router.post('/calculate/price', CurrencyController.calculatePrice);
router.post('/calculate/profit', CurrencyController.calculateProfit);
router.post('/calculate/profit-percentage', CurrencyController.calculateProfitPercentage);
router.post('/calculate/break-even', CurrencyController.calculateBreakEvenPrice);
router.post('/calculate/markup-percentage', CurrencyController.calculateMarkupPercentage);
// 货币计算相关路由
// 暂时注释掉,因为对应的方法已被注释掉
// router.post('/calculate/price', CurrencyController.calculatePrice);
// router.post('/calculate/profit', CurrencyController.calculateProfit);
// router.post('/calculate/profit-percentage', CurrencyController.calculateProfitPercentage);
// router.post('/calculate/break-even', CurrencyController.calculateBreakEvenPrice);
// router.post('/calculate/markup-percentage', CurrencyController.calculateMarkupPercentage);
export default router;

View File

@@ -4,9 +4,9 @@
*/
import { Router } from 'express';
import { DynamicPricingService } from '../../services/DynamicPricingService';
import { DynamicPricingService } from '../../services/core/DynamicPricingService';
import { PricingStrategy } from '../../types/enums';
import { CompetitorPriceService } from '../../services/CompetitorPriceService';
import { CompetitorPriceService } from '../../services/core/CompetitorPriceService';
import { logger } from '../../utils/logger';
const router = Router();

View File

@@ -1,10 +1,10 @@
import { Router } from 'express';
import { requirePermission } from '../../core/guards/rbac.guard';
import { requireTraceContext } from '../../core/guards/trace-context.guard';
import { CommodityHedgingService } from '../../services/CommodityHedgingService';
import { PoolSourcingService } from '../../services/PoolSourcingService';
import { SovereignCreditPoolService } from '../../services/SovereignCreditPoolService';
import { SovereigntySettlementService } from '../../services/SovereigntySettlementService';
import { CommodityHedgingService } from '../../services/core/CommodityHedgingService';
import { PoolSourcingService } from '../../services/integration/PoolSourcingService';
import { SovereignCreditPoolService } from '../../services/sovereignty/SovereignCreditPoolService';
import { SovereigntySettlementService } from '../../services/sovereignty/SovereigntySettlementService';
import { PricingController } from '../controllers/PricingController';
import { SettlementController } from '../controllers/SettlementController';
import { ReconciliationController } from '../controllers/ReconciliationController';

View File

@@ -0,0 +1,19 @@
/**
* [BE-ROUTE-016] 库存决策路由
* 提供库存决策AI介入的RESTful API路由
*/
import { Router } from 'express';
import { InventoryDecisionController } from '../controllers/InventoryDecisionController';
import { requireTraceContext } from '../../core/guards/trace-context.guard';
import { requirePermission } from '../../core/guards/rbac.guard';
const router = Router();
router.post('/ai-decision', requireTraceContext, InventoryDecisionController.makeDecision);
router.post('/adjust', requireTraceContext, requirePermission('inventory:write'), InventoryDecisionController.adjustInventory);
router.post('/reserve', requireTraceContext, requirePermission('inventory:write'), InventoryDecisionController.reserveInventory);
router.post('/release', requireTraceContext, requirePermission('inventory:write'), InventoryDecisionController.releaseInventory);
router.get('/:id', requireTraceContext, InventoryDecisionController.getInventory);
export default router;

View File

@@ -1,6 +1,6 @@
import { Router, Request, Response } from 'express';
import LeaderboardService from '../../services/LeaderboardService';
import MerchantMetricsService from '../../services/MerchantMetricsService';
import LeaderboardService from '../../services/monitoring/LeaderboardService';
import MerchantMetricsService from '../../services/analytics/MerchantMetricsService';
import { logger } from '../../utils/logger';
const router = Router();

View File

@@ -0,0 +1,17 @@
/**
* [BE-ROUTE-019] 物流决策路由
* 提供物流决策AI介入的RESTful API路由
*/
import { Router } from 'express';
import { LogisticsDecisionController } from '../controllers/LogisticsDecisionController';
import { requireTraceContext } from '../../core/guards/trace-context.guard';
const router = Router();
router.post('/ai-decision', requireTraceContext, LogisticsDecisionController.makeDecision);
router.post('/freight/audit', requireTraceContext, LogisticsDecisionController.auditFreight);
router.post('/delay/warn', requireTraceContext, LogisticsDecisionController.warnDelay);
router.get('/trace/:orderId', requireTraceContext, LogisticsDecisionController.traceLogistics);
export default router;

View File

@@ -1,5 +1,5 @@
import { Router, Request, Response } from 'express';
import { PlatformAccountService } from '../../services/PlatformAccountService';
import { PlatformAccountService } from '../../services/platform/PlatformAccountService';
import { requirePermission } from '../../core/guards/rbac.guard';
import { logger } from '../../utils/logger';

View File

@@ -0,0 +1,25 @@
/**
* [BE-ROUTE-014] 定价决策路由
* 提供定价决策AI介入的RESTful API路由
* AI注意: 所有定价决策路由必须通过此文件注册
*/
import { Router, Request, Response, NextFunction } from 'express';
import { PricingDecisionController } from '../controllers/PricingDecisionController';
import { validateAIDecision } from '../middleware/AIDecisionMiddleware';
import { requireTraceContext } from '../../core/guards/trace-context.guard';
import { requirePermission } from '../../core/guards/rbac.guard';
const router = Router();
router.post('/validate', requireTraceContext, PricingDecisionController.validate);
router.post('/ai-decision', requireTraceContext, PricingDecisionController.makeDecision);
router.post('/decisions', requireTraceContext, requirePermission('pricing:write'), PricingDecisionController.createDecision);
router.get('/decisions', requireTraceContext, PricingDecisionController.getDecisions);
router.get('/decisions/stats', requireTraceContext, PricingDecisionController.getStats);
router.get('/decisions/:id', requireTraceContext, PricingDecisionController.getDecisionById);
router.post('/decisions/:id/execute', requireTraceContext, requirePermission('pricing:write'), PricingDecisionController.executeDecision);
router.post('/decisions/:id/approve', requireTraceContext, requirePermission('pricing:write'), PricingDecisionController.approveDecision);
router.post('/decisions/:id/reject', requireTraceContext, requirePermission('pricing:write'), PricingDecisionController.rejectDecision);
export default router;

View File

@@ -0,0 +1,17 @@
/**
* [BE-ROUTE-018] 风控决策路由
* 提供风控决策AI介入的RESTful API路由
*/
import { Router } from 'express';
import { RiskControlController } from '../controllers/RiskControlController';
import { requireTraceContext } from '../../core/guards/trace-context.guard';
const router = Router();
router.post('/ai-decision', requireTraceContext, RiskControlController.makeDecision);
router.post('/assess', requireTraceContext, RiskControlController.assessRisk);
router.post('/block', requireTraceContext, RiskControlController.blockTransaction);
router.post('/scan', requireTraceContext, RiskControlController.scanRisks);
export default router;

View File

@@ -0,0 +1,335 @@
import { Router, Request, Response } from 'express';
import { SaasTenantService } from '../../services/tenant/SaasTenantService';
import { TenantDomainMiddleware } from '../../middleware/TenantDomainMiddleware';
import { logger } from '../../utils/logger';
const router = Router();
router.use(TenantDomainMiddleware.resolveTenant);
router.get('/tenants', async (req: Request, res: Response) => {
try {
const filters: any = {};
if (req.query.status) {
filters.status = req.query.status as string;
}
if (req.query.plan) {
filters.plan = req.query.plan as string;
}
if (req.query.type) {
filters.type = req.query.type as string;
}
const tenants = await SaasTenantService.listTenants(filters);
res.json({ success: true, data: tenants });
} catch (error: any) {
logger.error('[SaasTenantAPI] Error listing tenants:', error);
res.status(500).json({ error: error.message });
}
});
router.get('/tenants/:tenantId', async (req: Request, res: Response) => {
try {
const tenant = await SaasTenantService.getTenant(req.params.tenantId as string);
if (!tenant) {
return res.status(404).json({ error: 'Tenant not found' });
}
res.json({ success: true, data: tenant });
} catch (error: any) {
logger.error('[SaasTenantAPI] Error getting tenant:', error);
res.status(500).json({ error: error.message });
}
});
router.post('/tenants', async (req: Request, res: Response) => {
try {
const tenant = await SaasTenantService.createTenant(req.body);
res.status(201).json({ success: true, data: tenant });
} catch (error: any) {
logger.error('[SaasTenantAPI] Error creating tenant:', error);
res.status(500).json({ error: error.message });
}
});
router.get('/tenants/:tenantId/domains', async (req: Request, res: Response) => {
try {
const domains = await SaasTenantService.getTenantDomains(req.params.tenantId as string);
res.json({ success: true, data: domains });
} catch (error: any) {
logger.error('[SaasTenantAPI] Error getting tenant domains:', error);
res.status(500).json({ error: error.message });
}
});
router.post('/tenants/:tenantId/domains', async (req: Request, res: Response) => {
try {
const { domain, type } = req.body;
if (!domain) {
return res.status(400).json({ error: 'Domain is required' });
}
const tenantDomain = await SaasTenantService.addDomain(
req.params.tenantId as string,
domain,
type || 'SUBDOMAIN'
);
res.status(201).json({ success: true, data: tenantDomain });
} catch (error: any) {
logger.error('[SaasTenantAPI] Error adding domain:', error);
res.status(500).json({ error: error.message });
}
});
router.post('/domains/:domainId/verify', async (req: Request, res: Response) => {
try {
const domain = await SaasTenantService.verifyDomain(req.params.domainId as string);
res.json({ success: true, data: domain });
} catch (error: any) {
logger.error('[SaasTenantAPI] Error verifying domain:', error);
res.status(500).json({ error: error.message });
}
});
router.post('/domains/:domainId/primary', async (req: Request, res: Response) => {
try {
await SaasTenantService.setPrimaryDomain(req.params.domainId as string);
res.json({ success: true, message: 'Primary domain set successfully' });
} catch (error: any) {
logger.error('[SaasTenantAPI] Error setting primary domain:', error);
res.status(500).json({ error: error.message });
}
});
router.get('/tenants/:tenantId/users', async (req: Request, res: Response) => {
try {
const users = await SaasTenantService.getTenantUsers(req.params.tenantId as string);
res.json({ success: true, data: users });
} catch (error: any) {
logger.error('[SaasTenantAPI] Error getting tenant users:', error);
res.status(500).json({ error: error.message });
}
});
router.post('/tenants/:tenantId/users', async (req: Request, res: Response) => {
try {
const { userId, role, permissions } = req.body;
if (!userId) {
return res.status(400).json({ error: 'User ID is required' });
}
const tenantUser = await SaasTenantService.addUser(
req.params.tenantId as string,
userId,
role || 'OPERATOR',
permissions || []
);
res.status(201).json({ success: true, data: tenantUser });
} catch (error: any) {
logger.error('[SaasTenantAPI] Error adding user:', error);
res.status(500).json({ error: error.message });
}
});
router.put('/tenants/:tenantId/users/:userId', async (req: Request, res: Response) => {
try {
const { role, permissions } = req.body;
if (!role) {
return res.status(400).json({ error: 'Role is required' });
}
const tenantUser = await SaasTenantService.updateUserRole(
req.params.tenantId as string,
req.params.userId as string,
role,
permissions || []
);
res.json({ success: true, data: tenantUser });
} catch (error: any) {
logger.error('[SaasTenantAPI] Error updating user role:', error);
res.status(500).json({ error: error.message });
}
});
router.get('/users/:userId/tenants', async (req: Request, res: Response) => {
try {
const tenants = await SaasTenantService.getUserTenants(req.params.userId as string);
res.json({ success: true, data: tenants });
} catch (error: any) {
logger.error('[SaasTenantAPI] Error getting user tenants:', error);
res.status(500).json({ error: error.message });
}
});
router.get('/tenants/:tenantId/settings', async (req: Request, res: Response) => {
try {
const category = req.query.category as string;
const settings = await SaasTenantService.getSettings(req.params.tenantId as string, category);
res.json({ success: true, data: settings });
} catch (error: any) {
logger.error('[SaasTenantAPI] Error getting tenant settings:', error);
res.status(500).json({ error: error.message });
}
});
router.get('/tenants/:tenantId/settings/:key', async (req: Request, res: Response) => {
try {
const tenantId = Array.isArray(req.params.tenantId) ? req.params.tenantId[0] : req.params.tenantId;
const key = Array.isArray(req.params.key) ? req.params.key[0] : req.params.key;
const value = await SaasTenantService.getSetting(tenantId, key);
if (value === null) {
return res.status(404).json({ error: 'Setting not found' });
}
res.json({ success: true, data: { key, value } });
} catch (error: any) {
logger.error('[SaasTenantAPI] Error getting tenant setting:', error);
res.status(500).json({ error: error.message });
}
});
router.put('/tenants/:tenantId/settings/:key', async (req: Request, res: Response) => {
try {
const { value, category } = req.body;
if (value === undefined) {
return res.status(400).json({ error: 'Value is required' });
}
const tenantId = Array.isArray(req.params.tenantId) ? req.params.tenantId[0] : req.params.tenantId;
const key = Array.isArray(req.params.key) ? req.params.key[0] : req.params.key;
await SaasTenantService.setSetting(
tenantId,
key,
value,
category || 'general'
);
res.json({ success: true, message: 'Setting updated successfully' });
} catch (error: any) {
logger.error('[SaasTenantAPI] Error setting tenant setting:', error);
res.status(500).json({ error: error.message });
}
});
router.get('/current-tenant', (req: Request, res: Response) => {
if (!req.tenant) {
return res.status(404).json({ error: 'No tenant found for current request' });
}
res.json({ success: true, data: req.tenant });
});
router.put('/tenants/:tenantId', async (req: Request, res: Response) => {
try {
const tenant = await SaasTenantService.updateTenant(req.params.tenantId as string, req.body);
res.json({ success: true, data: tenant });
} catch (error: any) {
logger.error('[SaasTenantAPI] Error updating tenant:', error);
res.status(500).json({ error: error.message });
}
});
router.delete('/tenants/:tenantId', async (req: Request, res: Response) => {
try {
await SaasTenantService.deleteTenant(req.params.tenantId as string);
res.json({ success: true, message: 'Tenant deleted successfully' });
} catch (error: any) {
logger.error('[SaasTenantAPI] Error deleting tenant:', error);
res.status(500).json({ error: error.message });
}
});
router.put('/tenants/:tenantId/status', async (req: Request, res: Response) => {
try {
const { status } = req.body;
if (!status) {
return res.status(400).json({ error: 'Status is required' });
}
const tenant = await SaasTenantService.updateTenantStatus(req.params.tenantId as string, status);
res.json({ success: true, data: tenant });
} catch (error: any) {
logger.error('[SaasTenantAPI] Error updating tenant status:', error);
res.status(500).json({ error: error.message });
}
});
router.delete('/domains/:domainId', async (req: Request, res: Response) => {
try {
await SaasTenantService.deleteDomain(req.params.domainId as string);
res.json({ success: true, message: 'Domain deleted successfully' });
} catch (error: any) {
logger.error('[SaasTenantAPI] Error deleting domain:', error);
res.status(500).json({ error: error.message });
}
});
router.delete('/tenants/:tenantId/users/:userId', async (req: Request, res: Response) => {
try {
await SaasTenantService.removeUser(req.params.tenantId as string, req.params.userId as string);
res.json({ success: true, message: 'User removed successfully' });
} catch (error: any) {
logger.error('[SaasTenantAPI] Error removing user:', error);
res.status(500).json({ error: error.message });
}
});
router.get('/stats', async (req: Request, res: Response) => {
try {
const stats = await SaasTenantService.getStats();
res.json({ success: true, data: stats });
} catch (error: any) {
logger.error('[SaasTenantAPI] Error getting stats:', error);
res.status(500).json({ error: error.message });
}
});
router.get('/tenants/:tenantId/usage', async (req: Request, res: Response) => {
try {
const usage = await SaasTenantService.getUsage(req.params.tenantId as string);
res.json({ success: true, data: usage });
} catch (error: any) {
logger.error('[SaasTenantAPI] Error getting tenant usage:', error);
res.status(500).json({ error: error.message });
}
});
router.get('/tenants/:tenantId/logs', async (req: Request, res: Response) => {
try {
const logs = await SaasTenantService.getOperationLogs(req.params.tenantId as string);
res.json({ success: true, data: logs });
} catch (error: any) {
logger.error('[SaasTenantAPI] Error getting operation logs:', error);
res.status(500).json({ error: error.message });
}
});
export default router;

View File

@@ -1,5 +1,5 @@
import { Router } from 'express';
import { ShopReportAggregationService, ReportType, TimeGranularity } from '../../services/ShopReportAggregationService';
import { ShopReportAggregationService, ReportType, TimeGranularity } from '../../services/analytics/ShopReportAggregationService';
import { logger } from '../../utils/logger';
const router = Router();

View File

@@ -0,0 +1,21 @@
/**
* [BE-ROUTE-015] 智能定价建议路由
* 提供智能定价建议的RESTful API路由
* AI注意: 所有智能定价建议路由必须通过此文件注册
*/
import { Router } from 'express';
import { SmartPricingController } from '../controllers/SmartPricingController';
import { requireTraceContext } from '../../core/guards/trace-context.guard';
import { requirePermission } from '../../core/guards/rbac.guard';
const router = Router();
router.post('/recommend', requireTraceContext, SmartPricingController.generateRecommendation);
router.post('/simulate', requireTraceContext, SmartPricingController.simulate);
router.post('/apply', requireTraceContext, requirePermission('pricing:write'), SmartPricingController.applyRecommendation);
router.get('/recommendations', requireTraceContext, SmartPricingController.getActiveRecommendations);
router.post('/batch', requireTraceContext, requirePermission('pricing:write'), SmartPricingController.batchGenerate);
router.get('/history', requireTraceContext, SmartPricingController.getPriceHistory);
export default router;

View File

@@ -5,8 +5,8 @@ import { requirePermission } from '../../core/guards/rbac.guard';
import { requireTraceContext } from '../../core/guards/trace-context.guard';
import { DIDHandshakeService } from '../../core/security/DIDHandshakeService';
import { PrivateAuditService } from '../../core/security/PrivateAuditService';
import { SovereigntyGovernanceService } from '../../services/SovereigntyGovernanceService';
import { SovereigntyIdentityService } from '../../services/SovereigntyIdentityService';
import { SovereigntyGovernanceService } from '../../services/sovereignty/SovereigntyGovernanceService';
import { SovereigntyIdentityService } from '../../services/sovereignty/SovereigntyIdentityService';
const router = Router();

View File

@@ -1,6 +1,6 @@
import { Router, Request, Response } from 'express';
import StrategyService from '../../services/StrategyService';
import { StrategyRecommendationService } from '../../services/StrategyRecommendationService';
import StrategyService from '../../services/marketing/StrategyService';
import { StrategyRecommendationService } from '../../services/marketing/StrategyRecommendationService';
import { logger } from '../../utils/logger';
const router = Router();

View File

@@ -4,14 +4,14 @@ import { requireTraceContext } from '../../core/guards/trace-context.guard';
import { AutonomousSettlementService } from '../../core/pipeline/AutonomousSettlementService';
import { SourcingRoutingService } from '../../domains/Trade/SourcingRoutingService';
import { TradeService } from '../../domains/Trade/TradeService';
import { AutonomousEcoService } from '../../services/AutonomousEcoService';
import { AutonomousSourcingService } from '../../services/AutonomousSourcingService';
import { DecentralizedArbitrationService } from '../../services/DecentralizedArbitrationService';
import { EcoValueSharingService } from '../../services/EcoValueSharingService';
import { FulfillmentConsensusService } from '../../services/FulfillmentConsensusService';
import { InventoryService } from '../../services/InventoryService';
import { SovereigntyReputationService } from '../../services/SovereigntyReputationService';
import { WarehouseService } from '../../services/WarehouseService';
import { AutonomousEcoService } from '../../services/core/AutonomousEcoService';
import { AutonomousSourcingService } from '../../services/core/AutonomousSourcingService';
import { DecentralizedArbitrationService } from '../../services/core/DecentralizedArbitrationService';
import { EcoValueSharingService } from '../../services/core/EcoValueSharingService';
import { FulfillmentConsensusService } from '../../services/core/FulfillmentConsensusService';
import { InventoryService } from '../../services/inventory/InventoryService';
import { SovereigntyReputationService } from '../../services/sovereignty/SovereigntyReputationService';
import { WarehouseService } from '../../services/inventory/WarehouseService';
const router = Router();
@@ -260,7 +260,7 @@ router.get('/inventory/hotmap', requireTraceContext, requirePermission('inventor
}
});
import { B2BTradeService } from '../../services/B2BTradeService';
import { B2BTradeService } from '../../services/core/B2BTradeService';
/**
* [BE-TOB001] 阶梯价计算接口
@@ -431,7 +431,7 @@ router.post('/b2b/init-tables', requireTraceContext, requirePermission('admin'),
}
});
import { LogisticsService } from '../../services/LogisticsService';
import { LogisticsService } from '../../services/logistics/LogisticsService';
/**
* [BE-LOG001] 物流策略引擎 - 获取物流策略