lqmac 11 months ago
parent 98a2fb0f06
commit d7e3c6819b
  1. 58
      app/common/validate/goods/AdminImport.php
  2. 2
      app/job/controller/goods/AdminImport.php
  3. 120
      app/job/service/goods/AdminImport.php
  4. 38
      app/job/service/goods/Collector.php
  5. 56
      app/store/model/goods/Import.php

@ -0,0 +1,58 @@
<?php
namespace app\common\validate\goods;
use think\Validate;
/**
* 验证类:商品导入
* Class Import
* @package app\common\service\goods
*/
class AdminImport extends Validate
{
// 验证场景
protected $scene = [
'goods' => ['goods_name', 'delivery_id', 'imagesIds', 'categoryIds', 'serviceIds'],
'skuInfo' => ['goods_price', 'stock_num', 'goods_weight'],
];
/**
* 验证规则
* @var array
*/
protected $rule = [
'goods_name|商品名称' => ['require'],
'delivery_id|运费模板ID' => ['require', 'number'],
'imagesIds|商品图片ID集' => ['require', 'array', 'validateIds'],
'categoryIds|商品分类ID集' => ['require', 'array', 'validateIds'],
'serviceIds|服务与承诺' => ['array', 'validateIds'],
'goods_price|商品价格' => ['require', 'float', '>=:0.01'],
'stock_num|库存数量' => ['require', 'integer', '>=:0'],
'goods_weight|商品重量' => ['require', 'float', '>=:0'],
];
/**
* 错误信息
* @var string[]
*/
protected $message = [
// 'delivery_id.number' => '运费模板ID必须是数字',
];
/**
* 验证ID集格式是否正确
* @param $value
* @return bool
*/
protected function validateIds($value): bool
{
foreach ($value as $val) {
if (!is_numeric($val)) {
return false;
}
}
return true;
}
}

@ -41,7 +41,7 @@ class AdminImport extends BaseJob
public function handle(array $data): bool
{
$time = date('H:i:s');
echo "\n ---- Import ---- {$time} ---- \n";
echo "\n ---- adminImport ---- {$time} ---- \n";
$service = new GoodsAdminImportService;
return $service->batch($data['list'], $data['recordId'], $data['storeId']);

@ -31,8 +31,9 @@ use app\common\enum\goods\GoodsType as GoodsTypeEnum;
use app\common\enum\goods\SpecType as GoodsSpecTypeEnum;
use app\common\enum\goods\ImportStatus as GoodsImportStatusEnum;
use app\common\enum\goods\DeductStockType as DeductStockTypeEnum;
use app\common\validate\goods\Import as GoodsImportValidate;
use app\common\validate\goods\AdminImport as GoodsAdminImportValidate;
use cores\exception\BaseException;
use think\facade\Log;
/**
* 服务类:商品批量导入
@ -99,30 +100,35 @@ class AdminImport extends BaseService
*/
public function batch(array $list, int $recordId, int $storeId): bool
{
$service = new \app\job\service\goods\Collector();
foreach ($list as $item) {
$data = $this->createData($item, $storeId);
$service->single($item['D'], $data, $storeId);
// 生成商品数据(用于写入数据库)
$data = $this->createData($item, $storeId);
// 数据验证
if (!$this->validateGoodsData($data, $storeId)) {
$this->errorLog[] = ['goodsSn' => $item['A'], 'message' => $this->getError()];
continue;
}
// 事务处理:添加商品
$model = new GoodsModel();
$model->transaction(function () use ($model, $data, $storeId) {
// 添加商品
$model->save($data);
// 新增商品与分类关联
GoodsCategoryRelModel::increased((int)$model['goods_id'], $data['categoryIds'], $storeId);
// 新增商品与图片关联
GoodsImageModel::increased((int)$model['goods_id'], $data['imagesIds'], $storeId);
// 新增商品与规格关联
GoodsSpecRelModel::increased((int)$model['goods_id'], $data['newSpecList'], $storeId);
// 新增商品sku信息
GoodsSkuModel::add((int)$model['goods_id'], $data['spec_type'], $data['newSkuList'], $storeId);
// 新增服务与承诺关联
GoodsServiceRelModel::increased((int)$model['goods_id'], $data['serviceIds'], $storeId);
});
// $data = $this->createData($item, $storeId);
// Log::record("data".json_encode($data));
// // 数据验证
// if (!$this->validateGoodsData($data, $storeId)) {
// $this->errorLog[] = ['goodsSn' => $item['A'], 'message' => $this->getError()];
// continue;
// }
// // 事务处理:添加商品
// $model = new GoodsModel();
// $model->transaction(function () use ($model, $data, $storeId) {
// // 添加商品
// $model->save($data);
// // 新增商品与分类关联
// GoodsCategoryRelModel::increased((int)$model['goods_id'], $data['categoryIds'], $storeId);
// // 新增商品与图片关联
// GoodsImageModel::increased((int)$model['goods_id'], $data['imagesIds'], $storeId);
// // 新增商品与规格关联
// GoodsSpecRelModel::increased((int)$model['goods_id'], $data['newSpecList'], $storeId);
// // 新增商品sku信息
// GoodsSkuModel::add((int)$model['goods_id'], $data['spec_type'], $data['newSkuList'], $storeId);
// // 新增服务与承诺关联
// GoodsServiceRelModel::increased((int)$model['goods_id'], $data['serviceIds'], $storeId);
// });
// 记录导入成功
$this->successCount++;
}
@ -164,7 +170,8 @@ class AdminImport extends BaseService
private function validateGoodsData(array $data, int $storeId): bool
{
// 验证商品信息:商品名称、分类ID集、图片ID集、运费模板ID
$validate = new GoodsImportValidate;
$validate = new GoodsAdminImportValidate;
Log::record($data);
if (!$validate->scene('goods')->check($data)) {
$this->setError($validate->getError());
return false;
@ -172,7 +179,7 @@ class AdminImport extends BaseService
// 验证SKU信息:商品价格、库存数量、商品重量
$skuList = $data['spec_type'] == GoodsSpecTypeEnum::MULTI ? $data['newSkuList'] : [$data['newSkuList']];
foreach ($skuList as $item) {
$validate = new GoodsImportValidate;
$validate = new GoodsAdminImportValidate;
if (!$validate->scene('skuInfo')->check($item)) {
$this->setError($validate->getError());
return false;
@ -212,66 +219,19 @@ class AdminImport extends BaseService
*/
private function createData(array $original, int $storeId): array
{
// 商品规格
$specType = isset($original['skuList']) ? GoodsSpecTypeEnum::MULTI : GoodsSpecTypeEnum::SINGLE;
// 整理商品数据
$data = [
'goods_type' => GoodsTypeEnum::PHYSICAL,
'goods_name' => $original[$this->mapGoods['goods_name']],
'goods_no' => $original[$this->mapGoods['goods_no']],
'spec_type' => $specType,
'delivery_id' => $original[$this->mapGoods['delivery_id']],
'sort' => $original[$this->mapGoods['sort']],
'sales_initial' => $original[$this->mapGoods['sales_initial']],
'deduct_stock_type' => $original[$this->mapGoods['deduct_stock_type']] === '付款减库存' ? DeductStockTypeEnum::PAYMENT
: DeductStockTypeEnum::CREATE,
'is_points_gift' => $original[$this->mapGoods['is_points_gift']] === '关闭' ? 0 : 1,
'is_points_discount' => $original[$this->mapGoods['is_points_discount']] === '关闭' ? 0 : 1,
'is_enable_grade' => $original[$this->mapGoods['is_enable_grade']] === '关闭' ? 0 : 1,
'status' => $original['G'] === '下架' ? GoodsStatusEnum::OFF_SALE : GoodsStatusEnum::ON_SALE,
'categoryIds' => $this->ids2array($original[$this->mapGoods['categoryIds']]),
'imagesIds' => $this->ids2array($original[$this->mapGoods['imagesIds']]),
'serviceIds' => $this->ids2array($original[$this->mapGoods['serviceIds']]),
// 下面是默认数据, 没有会报错
'content' => '',
'alone_grade_equity' => [],
'newSpecList' => [],
'newSkuList' => [],
'cmmdty_model' => $original["A"],
'channel' => "jd",
'goods_no' => $original["C"],
'categoryIds' => $this->ids2array($original["E"]),
'imageStorage' => 10,//下载图片到本地
'goods_type' => 10,//实物
'goods_status' => 10,//上架
'store_id' => $storeId,
];
// 规格和sku数据处理
if ($data['spec_type'] === GoodsSpecTypeEnum::MULTI) {
$specList = $this->createSpecList($original['skuList']);
$data['specData']['specList'] = $specList;
$data['specData']['skuList'] = $this->createSkuList($original['skuList'], $specList);
// 生成多规格数据 (携带id)
$data['newSpecList'] = SpecModel::getNewSpecList($data['specData']['specList'], $storeId);
// 生成skuList (携带goods_sku_id)
$data['newSkuList'] = GoodsSkuModel::getNewSkuList($data['newSpecList'], $data['specData']['skuList']);
} elseif ($data['spec_type'] === GoodsSpecTypeEnum::SINGLE) {
// 生成skuItem
$data['newSkuList'] = [
'goods_price' => $original[$this->mapSku['goods_price']],
'line_price' => $original[$this->mapSku['line_price']],
'stock_num' => $original[$this->mapSku['stock_num']],
'goods_weight' => $original[$this->mapSku['goods_weight']],
// 'goods_sku_no' => $original[$this->mapSku['goods_sku_no']],
];
}
// 整理商品的价格和库存总量
if ($data['spec_type'] === GoodsSpecTypeEnum::MULTI) {
$data['stock_total'] = GoodsSkuModel::getStockTotal($data['specData']['skuList']);
[$data['goods_price_min'], $data['goods_price_max']] = GoodsSkuModel::getGoodsPrices($data['specData']['skuList']);
[$data['line_price_min'], $data['line_price_max']] = GoodsSkuModel::getLinePrices($data['specData']['skuList']);
} elseif ($data['spec_type'] === GoodsSpecTypeEnum::SINGLE) {
$data['goods_price_min'] = $data['goods_price_max'] = $original[$this->mapSku['goods_price']];
$data['line_price_min'] = $data['line_price_max'] = $original[$this->mapSku['line_price']];
$data['stock_total'] = $original[$this->mapSku['stock_num']];
}
// 过滤不存在的ID集数据
$data['categoryIds'] = CategoryModel::filterCategoryIds($data['categoryIds'], $storeId);
$data['imagesIds'] = UploadFileModel::filteFileIds($data['imagesIds'], $storeId);
$data['serviceIds'] = GoodsServiceModel::filterServiceIds($data['serviceIds'], $storeId);
//$data['categoryIds'] = CategoryModel::filterCategoryIds($data['categoryIds'], $storeId);
return $data;
}

@ -116,7 +116,40 @@ class Collector extends BaseService
$this->updateRecord($recordId, \count($urls));
return true;
}
public function single(string $url, array $form, int $storeId): bool
{
try {
// 采集第三方商品数据
$original = $this->collector($url, $storeId);
// 下载远程商品图片
$original = $this->thirdPartyImages($original, $form['imageStorage'], $storeId);
} catch (\Throwable $e) {
// var_dump($e->getMessage());
// exit;
tre($e->getTraceAsString());
$this->errorLog[] = ['url' => trim($url), 'message' => $e->getMessage()];
return false;
}
// 生成商品数据(用于写入数据库)
$data = $this->createData($original, $form, $storeId);
// 事务处理:添加商品
$model = new GoodsModel();
$model->transaction(function () use ($model, $data, $storeId) {
// 添加商品
$model->save($data);
// 新增商品与分类关联
GoodsCategoryRelModel::increased((int)$model['goods_id'], $data['categoryIds'], $storeId);
// 新增商品与图片关联
GoodsImageModel::increased((int)$model['goods_id'], $data['imagesIds'], $storeId);
// 新增商品与规格关联
GoodsSpecRelModel::increased((int)$model['goods_id'], $data['newSpecList'], $storeId);
// 新增商品sku信息
GoodsSkuModel::add((int)$model['goods_id'], $data['spec_type'], $data['newSkuList'], $storeId);
});
return true;
}
/**
* 检查采集记录状态是否异常
* @param int $recordId
@ -251,6 +284,9 @@ class Collector extends BaseService
'newSkuList' => [],
'store_id' => $storeId,
];
if (isset($form['channel']) {
$data['channel'] = $form['channel'];
}
// 整理商品的价格和库存总量
if ($data['spec_type'] === GoodsSpecTypeEnum::MULTI) {
$data['stock_total'] = GoodsSkuModel::getStockTotal($original['specData']['skuList']);

@ -73,17 +73,26 @@ class Import extends ImportModel
$execlData = $this->readExecl();
// 验证导入的商品数量是否合法
$this->checkLimit($execlData);
// 格式化导入的商品列表数据
$goodsList = $this->adminFormatGoodsList($execlData);
// echo "<pre>";
// print_r($goodsList);
// exit();
//总后台的店铺id设置为0
self::$storeId = 0;
// $service = new \app\job\service\goods\Collector();
// foreach ($execlData as $item) {
// $data = [
// 'cmmdty_model' => $item["A"],
// 'channel' => "jd",
// 'goods_no' => $item["C"],
// 'categoryIds' => explode(",", $item["E"]),
// 'imageStorage' => 10,//下载图片到本地
// 'goods_type' => 10,//实物
// 'goods_status' => 10,//上架
// 'store_id' => self::$storeId,
// ];
// $service->single($item['D'], $data, self::$storeId);
// }
// 新增商品导入记录
$recordId = $this->addRecord(\count($goodsList));
$recordId = $this->addRecord(\count($execlData));
// 调度计划任务
$this->adminDispatchJob($goodsList, $recordId);
$this->adminDispatchJob($execlData, $recordId);
return true;
}
/**
@ -108,36 +117,7 @@ class Import extends ImportModel
]);
}
}
/**
* 格式化导入的商品列表数据
* @param array $execlData
* @return array
*/
private function adminFormatGoodsList(array $execlData): array
{
$goodsList = [];
foreach ($execlData as $row) {
// 不存在商品序号的记录视为空行跳过
if (!is_numeric($row['A'])) {
continue;
}
// SKU信息
$skuInfo = helper::pick($row, ['G', 'H', 'I', 'J', 'K', 'L', 'M', 'N']);
// 商品数据里不存在相同序号, 代表是第一次记录
if (!isset($goodsList[$row['A']])) {
$goodsList[$row['A']] = $row;
// 存在规格值组合则商品是多规格
if (!empty($row['H'])) {
$goodsList[$row['A']]['skuList'] = [$skuInfo];
}
} elseif (isset($goodsList[$row['A']]['skuList'])) {
// 否则代表是多规格商品的SKU
$goodsList[$row['A']]['skuList'][] = $skuInfo;
}
}
return array_values($goodsList);
}
/**
* 执行批量导入
* @param array $form

Loading…
Cancel
Save