提取生成sku方法
parent
2fdea9d2d5
commit
f4b9ca91a6
|
|
@ -64,6 +64,7 @@ class BatchSkuSyncSpu extends BatchAction
|
||||||
} catch (Throwable $th) {
|
} catch (Throwable $th) {
|
||||||
DB::rollBack();
|
DB::rollBack();
|
||||||
report($th);
|
report($th);
|
||||||
|
return $this->response()->error('操作失败:'.$th->getMessage())->refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
$message = '操作成功';
|
$message = '操作成功';
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,8 @@ use App\Models\ProductSku;
|
||||||
use App\Models\ProductSpu;
|
use App\Models\ProductSpu;
|
||||||
use Dcat\Admin\Grid\Tools\AbstractTool;
|
use Dcat\Admin\Grid\Tools\AbstractTool;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Arr;
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
class InitSkuBySpecs extends AbstractTool
|
class InitSkuBySpecs extends AbstractTool
|
||||||
{
|
{
|
||||||
|
|
@ -55,53 +56,16 @@ class InitSkuBySpecs extends AbstractTool
|
||||||
$nowTime = now();
|
$nowTime = now();
|
||||||
//获取SPU
|
//获取SPU
|
||||||
$spu = ProductSpu::with('specs')->findOrFail($this->getKey());
|
$spu = ProductSpu::with('specs')->findOrFail($this->getKey());
|
||||||
$skuSpecs = [];
|
try {
|
||||||
foreach ($spu->specs as $spec) {
|
DB::beginTransaction();
|
||||||
$_items = [];
|
ProductSku::createBySpu($spu);
|
||||||
foreach ($spec->items as $item) {
|
DB::commit();
|
||||||
$_items[] = [
|
} catch (Throwable $th) {
|
||||||
'id' => $spec->id,
|
DB::rollBack();
|
||||||
'name'=>$item['name'],
|
report($th);
|
||||||
'price'=>$item['value'],
|
return $this->response()->error(__('admin.update_failed').': '.$th->getMessage())->refresh();
|
||||||
];
|
|
||||||
}
|
}
|
||||||
$skuSpecs[] = $_items;
|
|
||||||
}
|
|
||||||
//生成规格笛卡尔集
|
|
||||||
$skuSpecs = Arr::crossJoin(...$skuSpecs);
|
|
||||||
$insertData = [];
|
|
||||||
//根据规格笛卡尔集生成预插入数据
|
|
||||||
foreach ($skuSpecs as $skuSpec) {
|
|
||||||
$_skuSpecs = [];
|
|
||||||
$_price = 0;
|
|
||||||
foreach ($skuSpec as $value) {
|
|
||||||
$_skuSpecs[$value['id']] = $value['name'];
|
|
||||||
$_price += $value['price'];
|
|
||||||
}
|
|
||||||
$insertData[] = [
|
|
||||||
'spu_id' => $spu->id,
|
|
||||||
'name' => trim($spu->name.' '.implode(' ', $_skuSpecs)),
|
|
||||||
'subtitle' => $spu->subtitle,
|
|
||||||
'category_id' => $spu->category_id,
|
|
||||||
'cover' => $spu->cover,
|
|
||||||
'images' => json_encode($spu->images),
|
|
||||||
'description' => $spu->description,
|
|
||||||
'sell_price' => bcadd($spu->sell_price, bcmul($_price, 100)),
|
|
||||||
'market_price' => $spu->market_price,
|
|
||||||
'cost_price' => $spu->cost_price,
|
|
||||||
'vip_price' => !is_null($spu->vip_price) ? bcadd($spu->vip_price, bcmul($_price, 100)) : null,
|
|
||||||
'media' => $spu->media,
|
|
||||||
'weight' => $spu->weight,
|
|
||||||
'attrs' => json_encode($spu->attrs),
|
|
||||||
'specs' => json_encode($_skuSpecs),
|
|
||||||
'stock' => $spu->stock,
|
|
||||||
'sales' => $spu->sales,
|
|
||||||
'buynote_id' => $spu->buynote_id,
|
|
||||||
'created_at' => $nowTime,
|
|
||||||
'updated_at' => $nowTime,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
count($insertData)>0 && ProductSku::insert($insertData);
|
|
||||||
|
|
||||||
return $this->response()->success(__('admin.update_succeeded'))->refresh();
|
return $this->response()->success(__('admin.update_succeeded'))->refresh();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@ use App\Models\ProductSpuSpec;
|
||||||
use Dcat\Admin\Contracts\LazyRenderable;
|
use Dcat\Admin\Contracts\LazyRenderable;
|
||||||
use Dcat\Admin\Traits\LazyWidget;
|
use Dcat\Admin\Traits\LazyWidget;
|
||||||
use Dcat\Admin\Widgets\Form;
|
use Dcat\Admin\Widgets\Form;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
class AddSku extends Form implements LazyRenderable
|
class AddSku extends Form implements LazyRenderable
|
||||||
{
|
{
|
||||||
|
|
@ -44,26 +46,18 @@ class AddSku extends Form implements LazyRenderable
|
||||||
return $this->response()->error(__('admin_message.forms.add_sku.errors.has_specs'));
|
return $this->response()->error(__('admin_message.forms.add_sku.errors.has_specs'));
|
||||||
} else {
|
} else {
|
||||||
$spu = ProductSpu::findOrFail($spuId);
|
$spu = ProductSpu::findOrFail($spuId);
|
||||||
ProductSku::create([
|
try {
|
||||||
'spu_id' => $spu->id,
|
DB::beginTransaction();
|
||||||
'name' => trim($spu->name.' '.implode(' ', $_skuSpecs)),
|
ProductSku::createBySpec([
|
||||||
'subtitle' => $spu->subtitle,
|
'specs'=>$_skuSpecs,
|
||||||
'category_id' => $spu->category_id,
|
'price'=>$_price,
|
||||||
'cover' => $spu->cover,
|
], $spu);
|
||||||
'images' => $spu->images,
|
DB::commit();
|
||||||
'description' => $spu->description,
|
} catch (Throwable $th) {
|
||||||
'sell_price' => bcadd($spu->sell_price, $_price),
|
DB::rollBack();
|
||||||
'market_price' => $spu->market_price,
|
report($th);
|
||||||
'cost_price' => $spu->cost_price,
|
return $this->response()->error('操作失败:'.$th->getMessage())->refresh();
|
||||||
'vip_price' => !is_null($spu->vip_price) ? bcadd($spu->vip_price, $_price) : null,
|
}
|
||||||
'media' => $spu->media,
|
|
||||||
'weight' => $spu->weight,
|
|
||||||
'attrs' => $spu->attrs,
|
|
||||||
'specs' => $_skuSpecs,
|
|
||||||
'stock' => $spu->stock,
|
|
||||||
'sales' => $spu->sales,
|
|
||||||
'buynote_id' => $spu->buynote_id,
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $this->response()
|
return $this->response()
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,14 @@ use App\Admin\Actions\Grid\ReleaseCancel;
|
||||||
use App\Admin\Actions\Grid\ReleaseDown;
|
use App\Admin\Actions\Grid\ReleaseDown;
|
||||||
use App\Admin\Actions\Grid\ReleaseUp;
|
use App\Admin\Actions\Grid\ReleaseUp;
|
||||||
use App\Admin\Actions\Grid\SkuSyncSpu;
|
use App\Admin\Actions\Grid\SkuSyncSpu;
|
||||||
|
use App\Admin\Extensions\Grid\Tools\Product\AddSku;
|
||||||
use App\Admin\Extensions\Grid\Tools\Product\BatchReleaseCancel;
|
use App\Admin\Extensions\Grid\Tools\Product\BatchReleaseCancel;
|
||||||
use App\Admin\Extensions\Grid\Tools\Product\BatchReleaseDown;
|
use App\Admin\Extensions\Grid\Tools\Product\BatchReleaseDown;
|
||||||
use App\Admin\Extensions\Grid\Tools\Product\BatchReleaseUp;
|
use App\Admin\Extensions\Grid\Tools\Product\BatchReleaseUp;
|
||||||
|
use App\Admin\Extensions\Grid\Tools\Product\InitSkuBySpecs;
|
||||||
|
use App\Admin\Extensions\Grid\Tools\Product\SettingSpecs;
|
||||||
use App\Models\ProductSku;
|
use App\Models\ProductSku;
|
||||||
|
use App\Models\ProductSpu;
|
||||||
use Dcat\Admin\Admin;
|
use Dcat\Admin\Admin;
|
||||||
use Dcat\Admin\Grid;
|
use Dcat\Admin\Grid;
|
||||||
|
|
||||||
|
|
@ -18,9 +22,7 @@ class ProductSkuTable extends Grid
|
||||||
public static function grid(int $spuId = null)
|
public static function grid(int $spuId = null)
|
||||||
{
|
{
|
||||||
$builder = ProductSku::with('category');
|
$builder = ProductSku::with('category');
|
||||||
if ($spuId) {
|
|
||||||
$builder->where('spu_id', $spuId);
|
|
||||||
}
|
|
||||||
$grid = parent::make($builder, function (Grid $grid) {
|
$grid = parent::make($builder, function (Grid $grid) {
|
||||||
$grid->setResource('product-skus');
|
$grid->setResource('product-skus');
|
||||||
$grid->showRowSelector();
|
$grid->showRowSelector();
|
||||||
|
|
@ -91,6 +93,26 @@ class ProductSkuTable extends Grid
|
||||||
$filter->equal('name')->width(3);
|
$filter->equal('name')->width(3);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if ($spuId) {
|
||||||
|
$grid->model()->where('spu_id', $spuId);
|
||||||
|
$spu = ProductSpu::findOrFail($spuId);
|
||||||
|
$grid->tools(function (Grid\Tools $tools) use ($spu) {
|
||||||
|
//设置规格
|
||||||
|
if (Admin::user()->can('dcat.admin.product_spus.setting_specs')) {
|
||||||
|
$tools->append(new SettingSpecs($spu->id));
|
||||||
|
}
|
||||||
|
if ($spu->hasSku()) { //下面有sku,手动创建sku
|
||||||
|
if (Admin::user()->can('dcat.admin.product_spus.add_sku')) {
|
||||||
|
$tools->append(new AddSku($spu->id));
|
||||||
|
}
|
||||||
|
} else {//下面无sku,根据规格自动生成sku
|
||||||
|
if (Admin::user()->can('dcat.admin.product_spus.init_sku_by_specs')) {
|
||||||
|
$tools->append(new InitSkuBySpecs($spu->id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
return $grid;
|
return $grid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ namespace App\Models;
|
||||||
use App\Casts\JsonArray;
|
use App\Casts\JsonArray;
|
||||||
use App\Casts\Price;
|
use App\Casts\Price;
|
||||||
use App\Traits\Release;
|
use App\Traits\Release;
|
||||||
|
use App\Traits\SkuInfo;
|
||||||
use Dcat\Admin\Traits\HasDateTimeFormatter;
|
use Dcat\Admin\Traits\HasDateTimeFormatter;
|
||||||
use EloquentFilter\Filterable;
|
use EloquentFilter\Filterable;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
@ -14,6 +15,7 @@ class ProductSku extends Model
|
||||||
use Filterable;
|
use Filterable;
|
||||||
use HasDateTimeFormatter;
|
use HasDateTimeFormatter;
|
||||||
use Release;
|
use Release;
|
||||||
|
use SkuInfo;
|
||||||
|
|
||||||
public const STATUS_INVALID = -1; // 无效的
|
public const STATUS_INVALID = -1; // 无效的
|
||||||
public const STATUS_ONLINE = 1; // 已上架
|
public const STATUS_ONLINE = 1; // 已上架
|
||||||
|
|
|
||||||
|
|
@ -142,7 +142,7 @@ trait Release
|
||||||
}
|
}
|
||||||
$sku->update(
|
$sku->update(
|
||||||
[
|
[
|
||||||
'name' => trim($sku->spu->name.' '.implode(',', $sku->specs)),
|
'name' => trim($sku->spu->name.' '.implode(' ', $sku->specs)),
|
||||||
'subtitle'=> $sku->spu->subtitle,
|
'subtitle'=> $sku->spu->subtitle,
|
||||||
'cover' => $sku->spu->cover,
|
'cover' => $sku->spu->cover,
|
||||||
// 'images' => $sku->spu->images,
|
// 'images' => $sku->spu->images,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,209 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Traits;
|
||||||
|
|
||||||
|
use App\Models\ProductSku;
|
||||||
|
use App\Models\ProductSpu;
|
||||||
|
use Illuminate\Support\Arr;
|
||||||
|
|
||||||
|
trait SkuInfo
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* sku名称规则
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @param array $spec
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected static function createName(string $name = '', array $spec = [])
|
||||||
|
{
|
||||||
|
return trim($name.' '.implode(' ', $spec));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 售价规则
|
||||||
|
*
|
||||||
|
* @param integer $price
|
||||||
|
* @param integer $specPrice
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected static function createSellPrice(float $price, float $specPrice)
|
||||||
|
{
|
||||||
|
return bcadd($price, $specPrice);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 市场价规则
|
||||||
|
*
|
||||||
|
* @param float $price
|
||||||
|
* @param float $specPrice
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected static function createMarketPrice(float $price, float $specPrice)
|
||||||
|
{
|
||||||
|
return bcadd($price, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 成本价规则
|
||||||
|
*
|
||||||
|
* @param float $price
|
||||||
|
* @param float $specPrice
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected static function createCostPrice(float $price, float $specPrice)
|
||||||
|
{
|
||||||
|
return bcadd($price, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会员价规则
|
||||||
|
*
|
||||||
|
* @param float|null $price
|
||||||
|
* @param float $specPrice
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected static function createVipPrice(?float $price, float $specPrice)
|
||||||
|
{
|
||||||
|
return !is_null($price) ? bcadd($price, $specPrice) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成规则笛卡尔积
|
||||||
|
*
|
||||||
|
* @param ProductSpu $spu
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function specCross(ProductSpu $spu): array
|
||||||
|
{
|
||||||
|
$skuSpecs = [];
|
||||||
|
foreach ($spu->specs as $spec) {
|
||||||
|
$_items = [];
|
||||||
|
foreach ($spec->items as $item) {
|
||||||
|
$_items[] = [
|
||||||
|
'id' => $spec->id,
|
||||||
|
'name'=>$item['name'],
|
||||||
|
'price'=>$item['value'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
$skuSpecs[] = $_items;
|
||||||
|
}
|
||||||
|
//生成规格笛卡尔集
|
||||||
|
return Arr::crossJoin(...$skuSpecs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据SPEC和spu返回 skuInfo
|
||||||
|
*
|
||||||
|
* @param [type] $skuSpec
|
||||||
|
* @param ProductSpu $spu
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected static function createInfo(array $skuSpec, ProductSpu $spu): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'spu_id' => $spu->id,
|
||||||
|
'name' => static::createName($spu->name, $skuSpec['specs']),
|
||||||
|
'subtitle' => $spu->subtitle,
|
||||||
|
'category_id' => $spu->category_id,
|
||||||
|
'cover' => $spu->cover,
|
||||||
|
'images' => $spu->images,
|
||||||
|
'description' => $spu->description,
|
||||||
|
'sell_price' => static::createSellPrice((float) $spu->sell_price, (float) $skuSpec['price']),
|
||||||
|
'market_price' => static::createMarketPrice((float) $spu->market_price, (float) $skuSpec['price']),
|
||||||
|
'cost_price' => static::createCostPrice((float) $spu->cost_price, (float) $skuSpec['price']),
|
||||||
|
'vip_price' => static::createVipPrice($spu->vip_price, (float) $skuSpec['price']),
|
||||||
|
'media' => $spu->media,
|
||||||
|
'weight' => $spu->weight,
|
||||||
|
'attrs' => $spu->attrs,
|
||||||
|
'specs' => $skuSpec['specs'],
|
||||||
|
'buynote_id' => $spu->buynote_id,
|
||||||
|
'verify_state' => 0, //默认为正常
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function createBySpu(ProductSpu $spu)
|
||||||
|
{
|
||||||
|
$nowTime = now();
|
||||||
|
$insertData = [];
|
||||||
|
//根据规格笛卡尔集生成预插入数据
|
||||||
|
foreach (static::specCross($spu) as $skuSpec) {
|
||||||
|
$_skuSpecs = [];
|
||||||
|
$_price = 0;
|
||||||
|
foreach ($skuSpec as $value) {
|
||||||
|
$_skuSpecs[$value['id']] = $value['name'];
|
||||||
|
$_price += $value['price'];
|
||||||
|
}
|
||||||
|
$_data = static::createInfo([
|
||||||
|
'specs'=>$_skuSpecs,
|
||||||
|
'price'=>$_price,
|
||||||
|
], $spu, 'create');
|
||||||
|
|
||||||
|
//批量插入时特殊单独处理数据
|
||||||
|
$_data['sell_price'] = (int) bcmul($_data['sell_price'], 100);
|
||||||
|
$_data['market_price'] = (int) bcmul($_data['market_price'], 100);
|
||||||
|
$_data['cost_price'] = (int) bcmul($_data['cost_price'], 100);
|
||||||
|
$_data['vip_price'] = !is_null($_data['vip_price']) ? (int) bcmul($_data['vip_price'], 100) : null;
|
||||||
|
|
||||||
|
$_data['images'] = json_encode($_data['images']);
|
||||||
|
$_data['attrs'] = json_encode($_data['attrs']);
|
||||||
|
$_data['specs'] = json_encode($_data['specs']);
|
||||||
|
|
||||||
|
//初始化时添加额外的数据
|
||||||
|
$_data['stock'] = $spu->stock;
|
||||||
|
$_data['sales'] = $spu->sales;
|
||||||
|
$_data['created_at'] = $nowTime;
|
||||||
|
$_data['updated_at'] = $nowTime;
|
||||||
|
$insertData[] = $_data;
|
||||||
|
}
|
||||||
|
count($insertData)>0 && ProductSku::insert($insertData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据规格生成商品
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function createBySpec(array $skuSpec, ProductSpu $spu)
|
||||||
|
{
|
||||||
|
$data = static::createInfo($skuSpec, $spu);
|
||||||
|
ProductSku::create($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据skuID同步主商品
|
||||||
|
*
|
||||||
|
* @param integer|null $id
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function syncSpuById(int $id= null)
|
||||||
|
{
|
||||||
|
static::syncSpu(ProductSku::with('spu')->findOrFail($id));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 同步主商品
|
||||||
|
*
|
||||||
|
* @param ProductSku $sku
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function syncSpu(ProductSku $sku)
|
||||||
|
{
|
||||||
|
$_price = 0;
|
||||||
|
foreach ($sku->specs as $id => $value) {
|
||||||
|
$spuSpec = $sku->spu->specs->first(function ($item) use ($id) {
|
||||||
|
return $item->id == $id;
|
||||||
|
});
|
||||||
|
foreach ($spuSpec->items as $item) {
|
||||||
|
if ($item['name'] == $value) {
|
||||||
|
$_price += $item['value'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$sku->update(static::createInfo([
|
||||||
|
'specs'=>$sku->specs,
|
||||||
|
'price'=>$_price,
|
||||||
|
], $sku->spu));
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue