提取生成sku方法
parent
2fdea9d2d5
commit
f4b9ca91a6
|
|
@ -64,6 +64,7 @@ class BatchSkuSyncSpu extends BatchAction
|
|||
} catch (Throwable $th) {
|
||||
DB::rollBack();
|
||||
report($th);
|
||||
return $this->response()->error('操作失败:'.$th->getMessage())->refresh();
|
||||
}
|
||||
|
||||
$message = '操作成功';
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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; // 已上架
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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