754 lines
24 KiB
TypeScript
754 lines
24 KiB
TypeScript
import {
|
|
Body,
|
|
ContentType,
|
|
Controller,
|
|
Del,
|
|
Files,
|
|
Get,
|
|
Inject,
|
|
Param,
|
|
Post,
|
|
Put,
|
|
Query,
|
|
} from '@midwayjs/core';
|
|
import { Context } from '@midwayjs/koa';
|
|
import { ILogger } from '@midwayjs/logger';
|
|
import { ApiOkResponse } from '@midwayjs/swagger';
|
|
import { UnifiedSearchParamsDTO } from '../dto/api.dto';
|
|
import { SyncOperationResultDTO } from '../dto/batch.dto';
|
|
import { BatchDeleteProductDTO, BatchUpdateProductDTO, CreateCategoryDTO, CreateProductDTO, ProductWhereFilter, UpdateCategoryDTO, UpdateProductDTO } from '../dto/product.dto';
|
|
import { BooleanRes, ProductListRes, ProductRes, ProductsRes } from '../dto/reponse.dto';
|
|
import { BatchSyncProductToSiteDTO, SyncProductToSiteDTO, SyncProductToSiteResultDTO } from '../dto/site-sync.dto';
|
|
import { ProductService } from '../service/product.service';
|
|
import { errorResponse, successResponse } from '../utils/response.util';
|
|
|
|
@Controller('/product')
|
|
export class ProductController {
|
|
@Inject()
|
|
productService: ProductService;
|
|
|
|
@Inject()
|
|
ctx: Context;
|
|
|
|
@Inject()
|
|
logger: ILogger;
|
|
|
|
@ApiOkResponse({
|
|
description: '通过name搜索产品',
|
|
type: ProductsRes,
|
|
})
|
|
@Get('/search')
|
|
async searchProducts(@Query('name') name: string) {
|
|
try {
|
|
// 调用服务获取产品数据
|
|
const products = await this.productService.findProductsByName(name);
|
|
return successResponse(products);
|
|
} catch (error) {
|
|
return errorResponse(error.message || '获取数据失败');
|
|
}
|
|
}
|
|
|
|
@ApiOkResponse({
|
|
type: ProductRes,
|
|
})
|
|
@Get('/sku/:sku')
|
|
async productBySku(@Param('sku') sku: string) {
|
|
try {
|
|
// 调用服务获取产品数据
|
|
const product = await this.productService.findProductBySku(sku);
|
|
return successResponse(product);
|
|
} catch (error) {
|
|
return errorResponse(error.message || '获取数据失败');
|
|
}
|
|
}
|
|
|
|
@ApiOkResponse({
|
|
description: '成功返回产品列表',
|
|
type: ProductListRes,
|
|
})
|
|
@Get('/list')
|
|
async getProductList(
|
|
@Query() query: UnifiedSearchParamsDTO<ProductWhereFilter>
|
|
): Promise<ProductListRes> {
|
|
try {
|
|
const data = await this.productService.getProductList(query);
|
|
return successResponse(data);
|
|
} catch (error) {
|
|
this.logger.error('获取产品列表失败', error);
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
@ApiOkResponse({ type: ProductRes })
|
|
@Post('/')
|
|
async createProduct(@Body() productData: CreateProductDTO) {
|
|
try {
|
|
const data = await this.productService.createProduct(productData);
|
|
return successResponse(data);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
// 导出所有产品 CSV
|
|
@ApiOkResponse()
|
|
@Get('/export')
|
|
@ContentType('text/csv')
|
|
async exportProductsCSV() {
|
|
try {
|
|
const csv = await this.productService.exportProductsCSV();
|
|
// 设置下载文件名(附件形式)
|
|
const date = new Date();
|
|
const pad = (n: number) => String(n).padStart(2, '0');
|
|
const name = `products-${date.getFullYear()}${pad(date.getMonth() + 1)}${pad(date.getDate())}.csv`;
|
|
this.ctx.set('Content-Disposition', `attachment; filename=${name}`);
|
|
return csv;
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
// 导入产品(CSV 文件)
|
|
@ApiOkResponse()
|
|
@Post('/import')
|
|
async importProductsCSV(@Files() files: any) {
|
|
try {
|
|
// 条件判断:确保存在文件
|
|
const file = files?.[0];
|
|
if (!file) return errorResponse('未接收到上传文件');
|
|
|
|
const result = await this.productService.importProductsCSV(file);
|
|
return successResponse(result);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
@ApiOkResponse({ type: ProductRes })
|
|
@Put('/:id')
|
|
async updateProduct(@Param('id') id: number, @Body() productData: UpdateProductDTO) {
|
|
try {
|
|
const data = await this.productService.updateProduct(id, productData);
|
|
return successResponse(data);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
@ApiOkResponse({ type: BooleanRes })
|
|
@Put('/batch-update')
|
|
async batchUpdateProduct(@Body() batchUpdateProductDTO: BatchUpdateProductDTO) {
|
|
try {
|
|
await this.productService.batchUpdateProduct(batchUpdateProductDTO);
|
|
return successResponse(true);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
@ApiOkResponse({ type: BooleanRes })
|
|
@Post('/batch-delete')
|
|
async batchDeleteProduct(@Body() body: BatchDeleteProductDTO) {
|
|
try {
|
|
const result = await this.productService.batchDeleteProduct(body.ids);
|
|
if (result.failed > 0) {
|
|
return errorResponse(`成功删除 ${result.success} 个,失败 ${result.failed} 个。首个错误: ${result.errors[0]}`);
|
|
}
|
|
return successResponse(true);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
@ApiOkResponse({ type: ProductRes })
|
|
@Put('updateNameCn/:id/:nameCn')
|
|
async updatenameCn(@Param('id') id: number, @Param('nameCn') nameCn: string) {
|
|
try {
|
|
const data = await this.productService.updatenameCn(id, nameCn);
|
|
return successResponse(data);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
// 根据站点SKU查询产品
|
|
@ApiOkResponse({ type: ProductRes })
|
|
@Get('/site-sku/:siteSku')
|
|
async getProductBySiteSku(@Param('siteSku') siteSku: string) {
|
|
try {
|
|
const product = await this.productService.findProductBySiteSku(siteSku);
|
|
return successResponse(product);
|
|
} catch (error) {
|
|
return errorResponse(error.message || '获取数据失败');
|
|
}
|
|
}
|
|
|
|
// 获取产品的站点SKU绑定
|
|
@ApiOkResponse()
|
|
@Get('/:id/site-skus')
|
|
async getProductSiteSkus(@Param('id') id: number) {
|
|
try {
|
|
const data = await this.productService.getProductSiteSkus(id);
|
|
return successResponse(data);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
// 覆盖式绑定产品的站点SKU列表
|
|
@ApiOkResponse()
|
|
@Post('/:id/site-skus')
|
|
async bindProductSiteSkus(@Param('id') id: number, @Body() body: { codes: string[] }) {
|
|
try {
|
|
const data = await this.productService.bindSiteSkus(id, body?.codes || []);
|
|
return successResponse(data);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
@ApiOkResponse({ type: ProductRes })
|
|
@Get('/:id')
|
|
async getProductById(@Param('id') id: number) {
|
|
try {
|
|
const product = await this.productService.getProductById(id);
|
|
return successResponse(product);
|
|
} catch (error) {
|
|
return errorResponse(error.message || '获取数据失败');
|
|
}
|
|
}
|
|
|
|
@ApiOkResponse({ type: BooleanRes })
|
|
@Del('/:id')
|
|
async deleteProduct(@Param('id') id: number) {
|
|
try {
|
|
const data = await this.productService.deleteProduct(id);
|
|
return successResponse(data);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
// 获取产品的库存组成
|
|
@ApiOkResponse()
|
|
@Get('/:id/components')
|
|
async getProductComponents(@Param('id') id: number) {
|
|
try {
|
|
const data = await this.productService.getProductComponents(id);
|
|
return successResponse(data);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
|
|
// 根据 SKU 自动绑定组成(匹配所有相同 SKU 的库存)
|
|
@ApiOkResponse()
|
|
@Post('/:id/components/auto')
|
|
async autoBindComponents(@Param('id') id: number) {
|
|
try {
|
|
const data = await this.productService.autoBindComponentsBySku(id);
|
|
return successResponse(data);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
// 通用属性接口:分页列表
|
|
@ApiOkResponse()
|
|
@Get('/attribute')
|
|
async getAttributeList(
|
|
@Query('dictName') dictName: string,
|
|
@Query('current') current = 1,
|
|
@Query('pageSize') pageSize = 10,
|
|
@Query('name') name?: string
|
|
) {
|
|
try {
|
|
const data = await this.productService.getAttributeList(
|
|
dictName,
|
|
{ current, pageSize },
|
|
name
|
|
);
|
|
return successResponse(data);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
// 通用属性接口:全部列表
|
|
@ApiOkResponse()
|
|
@Get('/attributeAll')
|
|
async getAttributeAll(@Query('dictName') dictName: string) {
|
|
try {
|
|
const data = await this.productService.getAttributeAll(dictName);
|
|
return successResponse(data);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
// 通用属性接口:创建
|
|
@ApiOkResponse()
|
|
@Post('/attribute')
|
|
async createAttribute(
|
|
@Query('dictName') dictName: string,
|
|
@Body() body: { title: string; name: string }
|
|
) {
|
|
try {
|
|
// 调用 getOrCreateAttribute 方法,如果不存在则创建,如果存在则返回
|
|
const data = await this.productService.getOrCreateAttribute(dictName, body.title, body.name);
|
|
return successResponse(data);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
// 通用属性接口:更新
|
|
@ApiOkResponse()
|
|
@Put('/attribute/:id')
|
|
async updateAttribute(
|
|
@Param('id') id: number,
|
|
@Query('dictName') dictName: string,
|
|
@Body() body: { title?: string; name?: string }
|
|
) {
|
|
try {
|
|
if (body?.name) {
|
|
const hasItem = await this.productService.hasAttribute(
|
|
dictName,
|
|
body.name,
|
|
id
|
|
);
|
|
if (hasItem) return errorResponse('字典项已存在');
|
|
}
|
|
const data = await this.productService.updateAttribute(id, body);
|
|
return successResponse(data);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
// 通用属性接口:删除
|
|
@ApiOkResponse({ type: BooleanRes })
|
|
@Del('/attribute/:id')
|
|
async deleteAttribute(@Param('id') id: number) {
|
|
try {
|
|
await this.productService.deleteAttribute(id);
|
|
return successResponse(true);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
// 兼容旧接口:品牌
|
|
@ApiOkResponse()
|
|
@Get('/brandAll')
|
|
async compatBrandAll() {
|
|
try {
|
|
const data = await this.productService.getAttributeAll('brand'); // 返回所有品牌字典项
|
|
return successResponse(data);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
@ApiOkResponse()
|
|
@Get('/brands')
|
|
async compatBrands(@Query('current') current = 1, @Query('pageSize') pageSize = 10, @Query('name') name?: string) {
|
|
try {
|
|
const data = await this.productService.getAttributeList('brand', { current, pageSize }, name); // 分页品牌列表
|
|
return successResponse(data);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
@ApiOkResponse()
|
|
@Post('/brand')
|
|
async compatCreateBrand(@Body() body: { title: string; name: string; image?: string; shortName?: string }) {
|
|
try {
|
|
const has = await this.productService.hasAttribute('brand', body.name); // 唯一性校验
|
|
if (has) return errorResponse('品牌已存在');
|
|
const data = await this.productService.createAttribute('brand', body); // 创建品牌字典项
|
|
return successResponse(data);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
@ApiOkResponse()
|
|
@Put('/brand/:id')
|
|
async compatUpdateBrand(@Param('id') id: number, @Body() body: { title?: string; name?: string; image?: string; shortName?: string }) {
|
|
try {
|
|
if (body?.name) {
|
|
const has = await this.productService.hasAttribute('brand', body.name, id); // 唯一性校验(排除自身)
|
|
if (has) return errorResponse('品牌已存在');
|
|
}
|
|
const data = await this.productService.updateAttribute(id, body); // 更新品牌字典项
|
|
return successResponse(data);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
@ApiOkResponse({ type: BooleanRes })
|
|
@Del('/brand/:id')
|
|
async compatDeleteBrand(@Param('id') id: number) {
|
|
try {
|
|
await this.productService.deleteAttribute(id); // 删除品牌字典项
|
|
return successResponse(true);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
// 兼容旧接口:口味
|
|
@ApiOkResponse()
|
|
@Get('/flavorsAll')
|
|
async compatFlavorsAll() {
|
|
try {
|
|
const data = await this.productService.getAttributeAll('flavor');
|
|
return successResponse(data);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
@ApiOkResponse()
|
|
@Get('/flavors')
|
|
async compatFlavors(@Query('current') current = 1, @Query('pageSize') pageSize = 10, @Query('name') name?: string) {
|
|
try {
|
|
const data = await this.productService.getAttributeList('flavor', { current, pageSize }, name);
|
|
return successResponse(data);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
@ApiOkResponse()
|
|
@Post('/flavors')
|
|
async compatCreateFlavors(@Body() body: { title: string; name: string; image?: string; shortName?: string }) {
|
|
try {
|
|
const has = await this.productService.hasAttribute('flavor', body.name);
|
|
if (has) return errorResponse('口味已存在');
|
|
const data = await this.productService.createAttribute('flavor', body);
|
|
return successResponse(data);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
@ApiOkResponse()
|
|
@Put('/flavors/:id')
|
|
async compatUpdateFlavors(@Param('id') id: number, @Body() body: { title?: string; name?: string; image?: string; shortName?: string }) {
|
|
try {
|
|
if (body?.name) {
|
|
const has = await this.productService.hasAttribute('flavor', body.name, id);
|
|
if (has) return errorResponse('口味已存在');
|
|
}
|
|
const data = await this.productService.updateAttribute(id, body);
|
|
return successResponse(data);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
@ApiOkResponse({ type: BooleanRes })
|
|
@Del('/flavors/:id')
|
|
async compatDeleteFlavors(@Param('id') id: number) {
|
|
try {
|
|
await this.productService.deleteAttribute(id);
|
|
return successResponse(true);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
// 兼容旧接口:规格
|
|
@ApiOkResponse()
|
|
@Get('/strengthAll')
|
|
async compatStrengthAll() {
|
|
try {
|
|
const data = await this.productService.getAttributeAll('strength');
|
|
return successResponse(data);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
@ApiOkResponse()
|
|
@Get('/strength')
|
|
async compatStrength(@Query('current') current = 1, @Query('pageSize') pageSize = 10, @Query('name') name?: string) {
|
|
try {
|
|
const data = await this.productService.getAttributeList('strength', { current, pageSize }, name);
|
|
return successResponse(data);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
@ApiOkResponse()
|
|
@Post('/strength')
|
|
async compatCreateStrength(@Body() body: { title: string; name: string; image?: string; shortName?: string }) {
|
|
try {
|
|
const has = await this.productService.hasAttribute('strength', body.name);
|
|
if (has) return errorResponse('规格已存在');
|
|
const data = await this.productService.createAttribute('strength', body);
|
|
return successResponse(data);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
@ApiOkResponse()
|
|
@Put('/strength/:id')
|
|
async compatUpdateStrength(@Param('id') id: number, @Body() body: { title?: string; name?: string; image?: string; shortName?: string }) {
|
|
try {
|
|
if (body?.name) {
|
|
const has = await this.productService.hasAttribute('strength', body.name, id);
|
|
if (has) return errorResponse('规格已存在');
|
|
}
|
|
const data = await this.productService.updateAttribute(id, body);
|
|
return successResponse(data);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
@ApiOkResponse({ type: BooleanRes })
|
|
@Del('/strength/:id')
|
|
async compatDeleteStrength(@Param('id') id: number) {
|
|
try {
|
|
await this.productService.deleteAttribute(id);
|
|
return successResponse(true);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
// 兼容旧接口:尺寸
|
|
@ApiOkResponse()
|
|
@Get('/sizeAll')
|
|
async compatSizeAll() {
|
|
try {
|
|
const data = await this.productService.getAttributeAll('size');
|
|
return successResponse(data);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
@ApiOkResponse()
|
|
@Get('/size')
|
|
async compatSize(@Query('current') current = 1, @Query('pageSize') pageSize = 10, @Query('name') name?: string) {
|
|
try {
|
|
const data = await this.productService.getAttributeList('size', { current, pageSize }, name);
|
|
return successResponse(data);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
@ApiOkResponse()
|
|
@Post('/size')
|
|
async compatCreateSize(@Body() body: { title: string; name: string; image?: string; shortName?: string }) {
|
|
try {
|
|
const has = await this.productService.hasAttribute('size', body.name);
|
|
if (has) return errorResponse('尺寸已存在');
|
|
const data = await this.productService.createAttribute('size', body);
|
|
return successResponse(data);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
@ApiOkResponse()
|
|
@Put('/size/:id')
|
|
async compatUpdateSize(@Param('id') id: number, @Body() body: { title?: string; name?: string; image?: string; shortName?: string }) {
|
|
try {
|
|
if (body?.name) {
|
|
const has = await this.productService.hasAttribute('size', body.name, id);
|
|
if (has) return errorResponse('尺寸已存在');
|
|
}
|
|
const data = await this.productService.updateAttribute(id, body);
|
|
return successResponse(data);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
@ApiOkResponse({ type: BooleanRes })
|
|
@Del('/size/:id')
|
|
async compatDeleteSize(@Param('id') id: number) {
|
|
try {
|
|
await this.productService.deleteAttribute(id);
|
|
return successResponse(true);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
// 获取所有分类
|
|
@ApiOkResponse({ description: '获取所有分类' })
|
|
@Get('/categories/all')
|
|
async getCategoriesAll() {
|
|
try {
|
|
const data = await this.productService.getCategoriesAll();
|
|
return successResponse(data);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
// 获取分类下的属性配置
|
|
@ApiOkResponse({ description: '获取分类下的属性配置' })
|
|
@Get('/category/:id/attributes')
|
|
async getCategoryAttributes(@Param('id') id: number) {
|
|
try {
|
|
const data = await this.productService.getCategoryAttributes(id);
|
|
return successResponse(data);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
// 创建分类
|
|
@ApiOkResponse({ description: '创建分类' })
|
|
@Post('/category')
|
|
async createCategory(@Body() body: CreateCategoryDTO) {
|
|
try {
|
|
const data = await this.productService.createCategory(body);
|
|
return successResponse(data);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
// 更新分类
|
|
@ApiOkResponse({ description: '更新分类' })
|
|
@Put('/category/:id')
|
|
async updateCategory(@Param('id') id: number, @Body() body: UpdateCategoryDTO) {
|
|
try {
|
|
const data = await this.productService.updateCategory(id, body);
|
|
return successResponse(data);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
// 删除分类
|
|
@ApiOkResponse({ description: '删除分类' })
|
|
@Del('/category/:id')
|
|
async deleteCategory(@Param('id') id: number) {
|
|
try {
|
|
await this.productService.deleteCategory(id);
|
|
return successResponse(true);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
// 创建分类属性
|
|
@ApiOkResponse({ description: '创建分类属性' })
|
|
@Post('/category/attribute')
|
|
async createCategoryAttribute(@Body() body: { categoryId: number; dictId: number }) {
|
|
try {
|
|
const data = await this.productService.createCategoryAttribute(body);
|
|
return successResponse(data);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
// 删除分类属性
|
|
@ApiOkResponse({ description: '删除分类属性' })
|
|
@Del('/category/attribute/:id')
|
|
async deleteCategoryAttribute(@Param('id') id: number) {
|
|
try {
|
|
await this.productService.deleteCategoryAttribute(id);
|
|
return successResponse(true);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
// 同步库存 SKU 到产品单品
|
|
@ApiOkResponse({ description: '同步库存 SKU 到产品单品' })
|
|
@Post('/sync-stock')
|
|
async syncStockToProduct() {
|
|
try {
|
|
const data = await this.productService.syncStockToProduct();
|
|
return successResponse(data);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
// 同步单个产品到站点
|
|
@ApiOkResponse({ description: '同步单个产品到站点', type: SyncProductToSiteResultDTO })
|
|
@Post('/sync-to-site')
|
|
async syncToSite(@Body() body: SyncProductToSiteDTO) {
|
|
try {
|
|
const result = await this.productService.syncToSite(body);
|
|
return successResponse(result);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
// 从站点同步产品到本地
|
|
@ApiOkResponse({ description: '从站点同步产品到本地', type: ProductRes })
|
|
@Post('/sync-from-site')
|
|
async syncProductFromSite(@Body() body: { siteId: number; siteProductId: string | number ,sku: string}) {
|
|
try {
|
|
const { siteId, siteProductId, sku } = body;
|
|
const product = await this.productService.syncProductFromSite(siteId, siteProductId, sku);
|
|
return successResponse(product);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
// 批量从站点同步产品到本地
|
|
@ApiOkResponse({ description: '批量从站点同步产品到本地', type: SyncOperationResultDTO })
|
|
@Post('/batch-sync-from-site')
|
|
async batchSyncFromSite(@Body() body: { siteId: number; siteProductIds: (string | number)[] }) {
|
|
try {
|
|
throw new Error('批量同步产品到本地暂未实现');
|
|
// const { siteId, siteProductIds } = body;
|
|
// const result = await this.productService.batchSyncFromSite(siteId, siteProductIds.map((id) => ({ siteProductId: id, sku: '' })));
|
|
// // 将服务层返回的结果转换为统一格式
|
|
// const errors = result.errors.map((error: string) => {
|
|
// // 提取产品ID部分作为标识符
|
|
// const match = error.match(/站点产品ID (\d+) /);
|
|
// const identifier = match ? match[1] : 'unknown';
|
|
// return {
|
|
// identifier: identifier,
|
|
// error: error
|
|
// };
|
|
// });
|
|
|
|
// return successResponse({
|
|
// total: siteProductIds.length,
|
|
// processed: result.synced + errors.length,
|
|
// synced: result.synced,
|
|
// errors: errors
|
|
// });
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
|
|
// 批量同步产品到站点
|
|
@ApiOkResponse({ description: '批量同步产品到站点', type: SyncOperationResultDTO })
|
|
@Post('/batch-sync-to-site')
|
|
async batchSyncToSite(@Body() body: BatchSyncProductToSiteDTO) {
|
|
try {
|
|
const { siteId, data } = body;
|
|
const result = await this.productService.batchSyncToSite(siteId, data);
|
|
return successResponse(result);
|
|
} catch (error) {
|
|
return errorResponse(error?.message || error);
|
|
}
|
|
}
|
|
}
|