Files
makemd/dashboard/src/services/inventoryDataSource.ts
wurenzhi a037843851 refactor: 重构代码结构和类型定义,优化类型安全性和代码可维护性
- 添加类型定义文件和类型引用
- 删除废弃的页面模块和导出文件
- 新增聚合管理模块和插件系统
- 修复类型错误和潜在运行时问题
- 更新API基础URL和配置
- 优化组件类型定义和事件处理
- 重构数据源接口和实现
- 完善文档和开发进度记录
2026-03-22 11:25:28 +08:00

552 lines
16 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* [MOCK-010] 库存模块DataSource
* AI注意: 这是Mock实现不是真实业务逻辑
* 仅在USE_MOCK=true时启用
*/
import { Inventory, InventoryStatus } from '../types/inventory';
export interface Warehouse {
id: string;
name: string;
code: string;
address: string;
city: string;
country: string;
capacity: number;
currentUsage: number;
status: 'active' | 'inactive' | 'maintenance';
manager: string;
phone: string;
email: string;
createdAt: string;
updatedAt: string;
}
export interface InventoryForecast {
id: string;
productId: string;
productName: string;
sku: string;
currentStock: number;
forecastedDemand: number;
recommendedOrder: number;
leadTime: number;
riskLevel: 'low' | 'medium' | 'high';
date: string;
}
export interface InventoryQueryParams {
productId?: string;
status?: InventoryStatus;
warehouseId?: string;
page?: number;
pageSize?: number;
}
export interface InventoryDataSource {
list(params?: InventoryQueryParams): Promise<{ data: Inventory[]; total: number }>;
get(id: string): Promise<Inventory | null>;
create(inventory: Omit<Inventory, 'id' | 'createdAt' | 'updatedAt'>): Promise<Inventory>;
update(id: string, inventory: Partial<Inventory>): Promise<Inventory | null>;
updateStock(id: string, quantity: number): Promise<Inventory | null>;
getByProductId(productId: string): Promise<Inventory[]>;
getByWarehouseId(warehouseId: string): Promise<Inventory[]>;
getLowStockAlerts(threshold: number): Promise<Inventory[]>;
getInventoryStatistics(): Promise<{
totalItems: number;
totalStock: number;
lowStockItems: number;
outOfStockItems: number;
warehouseDistribution: Record<string, number>;
}>;
fetchWarehouses(): Promise<Warehouse[]>;
getInventoryForecasts(): Promise<InventoryForecast[]>;
}
export class InventoryDataSourceImpl implements InventoryDataSource {
async list(params?: InventoryQueryParams): Promise<{ data: Inventory[]; total: number }> {
const mockInventory: Inventory[] = [
{
id: 'inv_1',
productId: '1',
productName: '智能手表',
quantity: 100,
threshold: 20,
status: InventoryStatus.IN_STOCK,
warehouseId: 'warehouse_1',
warehouseName: '北京仓库',
lastStockUpdate: new Date('2026-03-10'),
createdAt: new Date('2026-02-01'),
updatedAt: new Date('2026-03-10'),
},
{
id: 'inv_2',
productId: '2',
productName: '无线耳机',
quantity: 200,
threshold: 30,
status: InventoryStatus.IN_STOCK,
warehouseId: 'warehouse_1',
warehouseName: '北京仓库',
lastStockUpdate: new Date('2026-03-11'),
createdAt: new Date('2026-02-02'),
updatedAt: new Date('2026-03-11'),
},
{
id: 'inv_3',
productId: '3',
productName: '运动鞋',
quantity: 150,
threshold: 25,
status: InventoryStatus.IN_STOCK,
warehouseId: 'warehouse_2',
warehouseName: '上海仓库',
lastStockUpdate: new Date('2026-03-12'),
createdAt: new Date('2026-02-03'),
updatedAt: new Date('2026-03-12'),
},
{
id: 'inv_4',
productId: '4',
productName: '智能手机',
quantity: 5,
threshold: 10,
status: InventoryStatus.LOW_STOCK,
warehouseId: 'warehouse_1',
warehouseName: '北京仓库',
lastStockUpdate: new Date('2026-03-09'),
createdAt: new Date('2026-02-04'),
updatedAt: new Date('2026-03-09'),
},
{
id: 'inv_5',
productId: '5',
productName: '平板电脑',
quantity: 0,
threshold: 15,
status: InventoryStatus.OUT_OF_STOCK,
warehouseId: 'warehouse_2',
warehouseName: '上海仓库',
lastStockUpdate: new Date('2026-03-08'),
createdAt: new Date('2026-02-05'),
updatedAt: new Date('2026-03-08'),
},
];
let filteredInventory = mockInventory;
if (params?.productId) {
filteredInventory = filteredInventory.filter(i => i.productId === params.productId);
}
if (params?.status) {
filteredInventory = filteredInventory.filter(i => i.status === params.status);
}
if (params?.warehouseId) {
filteredInventory = filteredInventory.filter(i => i.warehouseId === params.warehouseId);
}
const page = params?.page || 1;
const pageSize = params?.pageSize || 10;
const start = (page - 1) * pageSize;
const end = start + pageSize;
const paginatedInventory = filteredInventory.slice(start, end);
return {
data: paginatedInventory,
total: filteredInventory.length,
};
}
async get(id: string): Promise<Inventory | null> {
const mockInventory: Inventory[] = [
{
id: 'inv_1',
productId: '1',
productName: '智能手表',
quantity: 100,
threshold: 20,
status: InventoryStatus.IN_STOCK,
warehouseId: 'warehouse_1',
warehouseName: '北京仓库',
lastStockUpdate: new Date('2026-03-10'),
createdAt: new Date('2026-02-01'),
updatedAt: new Date('2026-03-10'),
},
{
id: 'inv_2',
productId: '2',
productName: '无线耳机',
quantity: 200,
threshold: 30,
status: InventoryStatus.IN_STOCK,
warehouseId: 'warehouse_1',
warehouseName: '北京仓库',
lastStockUpdate: new Date('2026-03-11'),
createdAt: new Date('2026-02-02'),
updatedAt: new Date('2026-03-11'),
},
];
const inventory = mockInventory.find(i => i.id === id);
return inventory || null;
}
async create(inventory: Omit<Inventory, 'id' | 'createdAt' | 'updatedAt'>): Promise<Inventory> {
const newInventory: Inventory = {
...inventory,
id: `inv_${Date.now()}`,
createdAt: new Date(),
updatedAt: new Date(),
};
return newInventory;
}
async update(id: string, inventory: Partial<Inventory>): Promise<Inventory | null> {
const existingInventory = await this.get(id);
if (!existingInventory) {
return null;
}
const updatedInventory: Inventory = {
...existingInventory,
...inventory,
updatedAt: new Date(),
};
return updatedInventory;
}
async updateStock(id: string, quantity: number): Promise<Inventory | null> {
const existingInventory = await this.get(id);
if (!existingInventory) {
return null;
}
const newQuantity = existingInventory.quantity + quantity;
let status: InventoryStatus;
if (newQuantity <= 0) {
status = InventoryStatus.OUT_OF_STOCK;
} else if (newQuantity < existingInventory.threshold) {
status = InventoryStatus.LOW_STOCK;
} else {
status = InventoryStatus.IN_STOCK;
}
const updatedInventory: Inventory = {
...existingInventory,
quantity: newQuantity,
status,
lastStockUpdate: new Date(),
updatedAt: new Date(),
};
return updatedInventory;
}
async getByProductId(productId: string): Promise<Inventory[]> {
const mockInventory: Inventory[] = [
{
id: 'inv_1',
productId: '1',
productName: '智能手表',
quantity: 100,
threshold: 20,
status: InventoryStatus.IN_STOCK,
warehouseId: 'warehouse_1',
warehouseName: '北京仓库',
lastStockUpdate: new Date('2026-03-10'),
createdAt: new Date('2026-02-01'),
updatedAt: new Date('2026-03-10'),
},
{
id: 'inv_2',
productId: '2',
productName: '无线耳机',
quantity: 200,
threshold: 30,
status: InventoryStatus.IN_STOCK,
warehouseId: 'warehouse_1',
warehouseName: '北京仓库',
lastStockUpdate: new Date('2026-03-11'),
createdAt: new Date('2026-02-02'),
updatedAt: new Date('2026-03-11'),
},
];
return mockInventory.filter(i => i.productId === productId);
}
async getByWarehouseId(warehouseId: string): Promise<Inventory[]> {
const mockInventory: Inventory[] = [
{
id: 'inv_1',
productId: '1',
productName: '智能手表',
quantity: 100,
threshold: 20,
status: InventoryStatus.IN_STOCK,
warehouseId: 'warehouse_1',
warehouseName: '北京仓库',
lastStockUpdate: new Date('2026-03-10'),
createdAt: new Date('2026-02-01'),
updatedAt: new Date('2026-03-10'),
},
{
id: 'inv_2',
productId: '2',
productName: '无线耳机',
quantity: 200,
threshold: 30,
status: InventoryStatus.IN_STOCK,
warehouseId: 'warehouse_1',
warehouseName: '北京仓库',
lastStockUpdate: new Date('2026-03-11'),
createdAt: new Date('2026-02-02'),
updatedAt: new Date('2026-03-11'),
},
{
id: 'inv_3',
productId: '3',
productName: '运动鞋',
quantity: 150,
threshold: 25,
status: InventoryStatus.IN_STOCK,
warehouseId: 'warehouse_2',
warehouseName: '上海仓库',
lastStockUpdate: new Date('2026-03-12'),
createdAt: new Date('2026-02-03'),
updatedAt: new Date('2026-03-12'),
},
];
return mockInventory.filter(i => i.warehouseId === warehouseId);
}
async getLowStockAlerts(threshold: number): Promise<Inventory[]> {
const mockInventory: Inventory[] = [
{
id: 'inv_1',
productId: '1',
productName: '智能手表',
quantity: 100,
threshold: 20,
status: InventoryStatus.IN_STOCK,
warehouseId: 'warehouse_1',
warehouseName: '北京仓库',
lastStockUpdate: new Date('2026-03-10'),
createdAt: new Date('2026-02-01'),
updatedAt: new Date('2026-03-10'),
},
{
id: 'inv_4',
productId: '4',
productName: '智能手机',
quantity: 5,
threshold: 10,
status: InventoryStatus.LOW_STOCK,
warehouseId: 'warehouse_1',
warehouseName: '北京仓库',
lastStockUpdate: new Date('2026-03-09'),
createdAt: new Date('2026-02-04'),
updatedAt: new Date('2026-03-09'),
},
{
id: 'inv_5',
productId: '5',
productName: '平板电脑',
quantity: 0,
threshold: 15,
status: InventoryStatus.OUT_OF_STOCK,
warehouseId: 'warehouse_2',
warehouseName: '上海仓库',
lastStockUpdate: new Date('2026-03-08'),
createdAt: new Date('2026-02-05'),
updatedAt: new Date('2026-03-08'),
},
];
return mockInventory.filter(i => i.quantity <= threshold);
}
async getInventoryStatistics(): Promise<{
totalItems: number;
totalStock: number;
lowStockItems: number;
outOfStockItems: number;
warehouseDistribution: Record<string, number>;
}> {
const mockInventory: Inventory[] = [
{
id: 'inv_1',
productId: '1',
productName: '智能手表',
quantity: 100,
threshold: 20,
status: InventoryStatus.IN_STOCK,
warehouseId: 'warehouse_1',
warehouseName: '北京仓库',
lastStockUpdate: new Date('2026-03-10'),
createdAt: new Date('2026-02-01'),
updatedAt: new Date('2026-03-10'),
},
{
id: 'inv_2',
productId: '2',
productName: '无线耳机',
quantity: 200,
threshold: 30,
status: InventoryStatus.IN_STOCK,
warehouseId: 'warehouse_1',
warehouseName: '北京仓库',
lastStockUpdate: new Date('2026-03-11'),
createdAt: new Date('2026-02-02'),
updatedAt: new Date('2026-03-11'),
},
{
id: 'inv_3',
productId: '3',
productName: '运动鞋',
quantity: 150,
threshold: 25,
status: InventoryStatus.IN_STOCK,
warehouseId: 'warehouse_2',
warehouseName: '上海仓库',
lastStockUpdate: new Date('2026-03-12'),
createdAt: new Date('2026-02-03'),
updatedAt: new Date('2026-03-12'),
},
{
id: 'inv_4',
productId: '4',
productName: '智能手机',
quantity: 5,
threshold: 10,
status: InventoryStatus.LOW_STOCK,
warehouseId: 'warehouse_1',
warehouseName: '北京仓库',
lastStockUpdate: new Date('2026-03-09'),
createdAt: new Date('2026-02-04'),
updatedAt: new Date('2026-03-09'),
},
{
id: 'inv_5',
productId: '5',
productName: '平板电脑',
quantity: 0,
threshold: 15,
status: InventoryStatus.OUT_OF_STOCK,
warehouseId: 'warehouse_2',
warehouseName: '上海仓库',
lastStockUpdate: new Date('2026-03-08'),
createdAt: new Date('2026-02-05'),
updatedAt: new Date('2026-03-08'),
},
];
const totalItems = mockInventory.length;
const totalStock = mockInventory.reduce((sum, item) => sum + item.quantity, 0);
const lowStockItems = mockInventory.filter(i => i.status === InventoryStatus.LOW_STOCK).length;
const outOfStockItems = mockInventory.filter(i => i.status === InventoryStatus.OUT_OF_STOCK).length;
const warehouseDistribution: Record<string, number> = {};
mockInventory.forEach(item => {
if (item.warehouseName) {
warehouseDistribution[item.warehouseName] = (warehouseDistribution[item.warehouseName] || 0) + item.quantity;
}
});
return {
totalItems,
totalStock,
lowStockItems,
outOfStockItems,
warehouseDistribution,
};
}
async fetchWarehouses(): Promise<Warehouse[]> {
return [
{
id: 'warehouse_1',
name: '北京仓库',
code: 'BJ-WH-001',
address: '北京市朝阳区建国路88号',
city: '北京',
country: '中国',
capacity: 10000,
currentUsage: 7500,
status: 'active',
manager: '张三',
phone: '010-12345678',
email: 'zhangsan@example.com',
createdAt: '2026-01-01',
updatedAt: '2026-03-15',
},
{
id: 'warehouse_2',
name: '上海仓库',
code: 'SH-WH-001',
address: '上海市浦东新区张江路100号',
city: '上海',
country: '中国',
capacity: 15000,
currentUsage: 12000,
status: 'active',
manager: '李四',
phone: '021-87654321',
email: 'lisi@example.com',
createdAt: '2026-01-15',
updatedAt: '2026-03-16',
},
];
}
async getInventoryForecasts(): Promise<InventoryForecast[]> {
return [
{
id: 'forecast_1',
productId: '1',
productName: '智能手表',
sku: 'WATCH-001',
currentStock: 100,
forecastedDemand: 150,
recommendedOrder: 50,
leadTime: 7,
riskLevel: 'low',
date: '2026-03-21',
},
{
id: 'forecast_2',
productId: '2',
productName: '无线耳机',
sku: 'EARPHONE-001',
currentStock: 200,
forecastedDemand: 180,
recommendedOrder: 0,
leadTime: 5,
riskLevel: 'low',
date: '2026-03-21',
},
{
id: 'forecast_3',
productId: '4',
productName: '智能手机',
sku: 'PHONE-001',
currentStock: 5,
forecastedDemand: 50,
recommendedOrder: 45,
leadTime: 10,
riskLevel: 'high',
date: '2026-03-21',
},
];
}
}
export const inventoryDataSource = new InventoryDataSourceImpl();