6
0
Fork 0

提取生成sku方法

release
vine_liutk 2021-12-06 10:11:41 +08:00
parent 2fdea9d2d5
commit f4b9ca91a6
7 changed files with 263 additions and 71 deletions

View File

@ -64,6 +64,7 @@ class BatchSkuSyncSpu extends BatchAction
} catch (Throwable $th) {
DB::rollBack();
report($th);
return $this->response()->error('操作失败:'.$th->getMessage())->refresh();
}
$message = '操作成功';

View File

@ -6,7 +6,8 @@ use App\Models\ProductSku;
use App\Models\ProductSpu;
use Dcat\Admin\Grid\Tools\AbstractTool;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;
use Throwable;
class InitSkuBySpecs extends AbstractTool
{
@ -55,53 +56,16 @@ class InitSkuBySpecs extends AbstractTool
$nowTime = now();
//获取SPU
$spu = ProductSpu::with('specs')->findOrFail($this->getKey());
$skuSpecs = [];
foreach ($spu->specs as $spec) {
$_items = [];
foreach ($spec->items as $item) {
$_items[] = [
'id' => $spec->id,
'name'=>$item['name'],
'price'=>$item['value'],
];
}
$skuSpecs[] = $_items;
try {
DB::beginTransaction();
ProductSku::createBySpu($spu);
DB::commit();
} catch (Throwable $th) {
DB::rollBack();
report($th);
return $this->response()->error(__('admin.update_failed').': '.$th->getMessage())->refresh();
}
//生成规格笛卡尔集
$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();
}

View File

@ -8,6 +8,8 @@ use App\Models\ProductSpuSpec;
use Dcat\Admin\Contracts\LazyRenderable;
use Dcat\Admin\Traits\LazyWidget;
use Dcat\Admin\Widgets\Form;
use Illuminate\Support\Facades\DB;
use Throwable;
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'));
} else {
$spu = ProductSpu::findOrFail($spuId);
ProductSku::create([
'spu_id' => $spu->id,
'name' => trim($spu->name.' '.implode(' ', $_skuSpecs)),
'subtitle' => $spu->subtitle,
'category_id' => $spu->category_id,
'cover' => $spu->cover,
'images' => $spu->images,
'description' => $spu->description,
'sell_price' => bcadd($spu->sell_price, $_price),
'market_price' => $spu->market_price,
'cost_price' => $spu->cost_price,
'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,
]);
try {
DB::beginTransaction();
ProductSku::createBySpec([
'specs'=>$_skuSpecs,
'price'=>$_price,
], $spu);
DB::commit();
} catch (Throwable $th) {
DB::rollBack();
report($th);
return $this->response()->error('操作失败:'.$th->getMessage())->refresh();
}
}
}
return $this->response()

View File

@ -6,10 +6,14 @@ use App\Admin\Actions\Grid\ReleaseCancel;
use App\Admin\Actions\Grid\ReleaseDown;
use App\Admin\Actions\Grid\ReleaseUp;
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\BatchReleaseDown;
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\ProductSpu;
use Dcat\Admin\Admin;
use Dcat\Admin\Grid;
@ -18,9 +22,7 @@ class ProductSkuTable extends Grid
public static function grid(int $spuId = null)
{
$builder = ProductSku::with('category');
if ($spuId) {
$builder->where('spu_id', $spuId);
}
$grid = parent::make($builder, function (Grid $grid) {
$grid->setResource('product-skus');
$grid->showRowSelector();
@ -91,6 +93,26 @@ class ProductSkuTable extends Grid
$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;
}
}

View File

@ -5,6 +5,7 @@ namespace App\Models;
use App\Casts\JsonArray;
use App\Casts\Price;
use App\Traits\Release;
use App\Traits\SkuInfo;
use Dcat\Admin\Traits\HasDateTimeFormatter;
use EloquentFilter\Filterable;
use Illuminate\Database\Eloquent\Model;
@ -14,6 +15,7 @@ class ProductSku extends Model
use Filterable;
use HasDateTimeFormatter;
use Release;
use SkuInfo;
public const STATUS_INVALID = -1; // 无效的
public const STATUS_ONLINE = 1; // 已上架

View File

@ -142,7 +142,7 @@ trait Release
}
$sku->update(
[
'name' => trim($sku->spu->name.' '.implode(',', $sku->specs)),
'name' => trim($sku->spu->name.' '.implode(' ', $sku->specs)),
'subtitle'=> $sku->spu->subtitle,
'cover' => $sku->spu->cover,
// 'images' => $sku->spu->images,

View File

@ -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));
}
}