import { Injectable, Logger, ServiceUnavailableException } from '@nestjs/common' import { PrismaService } from '../prisma/prisma.service' import { IntegrationService } from '../integration/integration.service' @Injectable() export class ProductService { private readonly logger = new Logger(ProductService.name) constructor( private prisma: PrismaService, private integrationService: IntegrationService, ) {} async findAll() { return this.prisma.product.findMany({ orderBy: { createdAt: 'desc' } }) } async findOne(id: string) { return this.prisma.product.findUnique({ where: { id } }) } async create(data: { name: string spec: string unit: string price: number quantity: number category: string }) { return this.prisma.product.create({ data }) } async update(id: string, data: any) { return this.prisma.product.update({ where: { id }, data }) } async publish(id: string) { return this.prisma.product.update({ where: { id }, data: { status: 'published' }, }) } async batchPublish(ids: string[]) { return this.prisma.product.updateMany({ where: { id: { in: ids } }, data: { status: 'published' }, }) } async remove(id: string) { return this.prisma.product.delete({ where: { id } }) } /** * F002 P0-A: 批量上架商品到 B2B 平台 (MCP import_products) * 字段映射: Product → import_products schema */ async publishToDirev(ids: string[]) { const b2bIntegration = await this.integrationService.findActiveMCP() if (!b2bIntegration) { throw new ServiceUnavailableException('未配置 B2B 集成') } const products = await this.prisma.product.findMany({ where: { id: { in: ids } }, }) if (products.length === 0) { throw new ServiceUnavailableException('未找到指定商品') } // Category string → numeric ID mapping (B2B tb_good first_category_id) const CATEGORY_MAP: Record = { '电缆': 28, '电力电缆': 28, '配电箱': 29, '开关柜': 29, '变压器': 27, '电线': 28, '母线槽': 30, '桥架': 31, } const fallbackCategoryId = 1 const items = products.map(p => { const catId = CATEGORY_MAP[p.category] || fallbackCategoryId const item: any = { name: p.name, category_id: catId, price: p.price, brandName: p.brand || '', stock: p.quantity, } if (p.spec) item.sku = p.spec if (p.imageUrl) item.images = [p.imageUrl] if (p.supplier) item.remark = `供应商:${p.supplier}` return item }) const result = await this.integrationService.executeTool( b2bIntegration.id, 'import_products', { products: items }, { retries: 2, retryDelayMs: 1000 }, ) if (!result.success) { const errorMsg = result.error || '未知错误' this.logger.error(`商品上架失败 (ids=${ids.join(',')}): ${errorMsg}`) throw new ServiceUnavailableException(`上架失败: ${errorMsg}`) } const data = result.data as any const payload = data.data || data const imported = payload.imported || 0 const errors = payload.errors || [] this.logger.log(`商品上架成功: 导入 ${imported} 条, 失败 ${errors.length} 条`) await this.prisma.product.updateMany({ where: { id: { in: products.map(p => p.id) } }, data: { status: 'published' }, }) return { imported, errors, ids: payload.ids || [], } } }