feat: #10000 ERP 代码优化

This commit is contained in:
赵世界 2023-04-17 18:56:59 +08:00
parent 2cfc0d11c5
commit 60ee98a6b4
55 changed files with 398 additions and 164 deletions

View File

@ -46,18 +46,17 @@ class DeleteGoodsSku extends Command
if (empty($code)) {
reutrn;
}
[$goodsCode, $skuCode] = explode('_', $code);
DB::beginTransaction();
try {
$goods = Goods::query()->where('goods_code', $goodsCode)->first();
$sku = GoodsSku::query()->where('external_sku_id', $code)->first();
$goods = Goods::query()->find($sku->goods_id);
$countSkus = GoodsSku::query()->where('goods_id', $goods->id)->count();
$sku = GoodsSku::query()->where('goods_id', $goods->id)->where('sku_code', $skuCode)->first();
DailyStockRecord::query()->where('sku_id', $sku->id)->delete();
Log::query()->where('module', 'goods')->where('target_type', 'goods_sku')->where('target_id', $sku->id)->delete();
$sku->delete();
if (1 === $countSkus) {
$goods->delete();
}
$sku->delete();
DB::commit();
$this->info('删除成功');
} catch (\Exception $exception) {

View File

@ -6,6 +6,7 @@ use App\Events\StockUpdateEvent;
use App\Models\BusinessGoodsSku;
use App\Models\BusinessOrder;
use App\Models\GoodsSku;
use App\Models\GoodsType;
use App\Models\Log;
use App\Models\Shop;
use App\Services\Business\BusinessFactory;
@ -13,6 +14,7 @@ use App\Utils\DateTimeUtils;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use App\Jobs\BusinessGoodsSkuIncrQuantity;
use Illuminate\Database\Eloquent\Builder;
class Test extends Command
{

View File

@ -0,0 +1,48 @@
<?php
namespace App\Console\Commands;
use App\Models\GoodsSku;
use Illuminate\Console\Command;
class UpdateExternalSkuId extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'update:goods_skus:external_sku_id';
/**
* The console command description.
*
* @var string
*/
protected $description = '更新goods_sku的external_sku_id';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
GoodsSku::chunk(500, static function ($skus) {
foreach ($skus as $sku) {
$sku->external_sku_id = $sku->goods->goods_code . '_' . $sku->sku_code;
$sku->save();
}
});
}
}

View File

@ -35,11 +35,8 @@ class BusinessOrdersUpdate
private function updateStock()
{
try {
[$goodsCode, $skuCode] = explode('_', $this->businessGoods['external_sku_id']);
$this->goodsSku = GoodsSku::query()->where('sku_code', $skuCode)
->whereHas('goods', function ($query) use ($goodsCode) {
$query->where('goods_code', $goodsCode);
})
$this->goodsSku = GoodsSku::query()
->where('external_sku_id', $this->businessGoods['external_sku_id'])
->first();
} catch (\Exception $e) {
Log::error('事件库存更新失败: ' . $e->getMessage());

View File

@ -31,7 +31,7 @@ class StockUpdateEvent
$this->isBatch = $isBatch;
if (is_array($data)) {
// ids集合
$this->goodsSkus = GoodsSku::query()->whereIn('id', $data)->with(['goods:id,goods_code'])->get();
$this->goodsSkus = GoodsSku::query()->whereIn('id', $data)->get();
} else {
// GoodsSku Elo模型对象
$this->goodsSku = $data;

View File

@ -6,16 +6,16 @@ class BusinessGoodsSkuFilter extends Filters
{
protected function externalSkuId($value)
{
return $this->builder->where('external_sku_id', '=', trim($value));
return $this->builder->where('external_sku_id', trim($value));
}
protected function goodsName($value)
{
return $this->builder->where('goods_name', '=', trim($value));
return $this->builder->where('goods_name', trim($value));
}
protected function shopId($value)
{
return $this->builder->where('shop_id', '=', trim($value));
return $this->builder->where('shop_id', trim($value));
}
}

View File

@ -6,36 +6,36 @@ class BusinessOrderFilter extends Filters
{
protected function participateNo($value)
{
return $this->builder->where('participate_no', '=', trim($value));
return $this->builder->where('participate_no', trim($value));
}
protected function shopId($value)
{
return $this->builder->where('shop_id', '=', $value);
return $this->builder->where('shop_id', $value);
}
protected function activityNo($value)
{
return $this->builder->where('activity_no', '=', $value);
return $this->builder->where('activity_no', $value);
}
protected function shippingStatus($value)
{
return $this->builder->where('shipping_status', '=', $value);
return $this->builder->where('shipping_status', $value);
}
protected function isSupplier($value)
{
return $this->builder->where('is_supplier', '=', $value);
return $this->builder->where('is_supplier', $value);
}
protected function cancelStatus($value)
{
return $this->builder->where('cancel_status', '=', $value);
return $this->builder->where('cancel_status', $value);
}
protected function afterSalesStatus($value)
{
return $this->builder->where('after_sales_status', '=', $value);
return $this->builder->where('after_sales_status', $value);
}
}

View File

@ -12,14 +12,14 @@ class GoodsFilter extends Filters
protected function typeId($value)
{
if($value){
return $this->builder->where('type_id', '=', $value);
return $this->builder->where('type_id', $value);
}
}
protected function brandId($value)
{
if($value){
return $this->builder->where('brand_id', '=', $value);
return $this->builder->where('brand_id', $value);
}
}
}

View File

@ -6,16 +6,21 @@ class GoodsSkuFilter extends Filters
{
protected function skuTitle($value)
{
return $this->builder->where('title', '=', $value);
return $this->builder->where('title', $value);
}
protected function status($value)
{
return $this->builder->where('status', '=', $value);
return $this->builder->where('status', $value);
}
protected function excludeIds($value)
{
return $this->builder->whereNotIn('id', $value);
}
protected function externalSkuId($value)
{
return $this->builder->where('external_sku_id', $value);
}
}

View File

@ -9,21 +9,21 @@ class GoodsSkuLocationFilter extends Filters
{
public function date($value)
{
return $this->builder->where('date', '=', $value);
return $this->builder->where('date', $value);
}
public function goodsTitle($value)
{
$goodsId = Goods::query()->where('title', $value)->value('id');
return $this->builder->where('goods_id', '=', $goodsId);
return $this->builder->where('goods_id', $goodsId);
}
public function goodsCode($value)
{
$goodsId = Goods::query()->where('goods_code', $value)->value('id');
return $this->builder->where('goods_id', '=', $goodsId);
return $this->builder->where('goods_id', $goodsId);
}
public function externalSkuId($value)
@ -32,16 +32,16 @@ class GoodsSkuLocationFilter extends Filters
$goodsId = Goods::query()->where('goods_code', $goodsCode)->value('id');
$skuId = GoodsSku::query()->where('sku_code', $skuCode)->value('id');
return $this->builder->where('goods_sku_id', '=', $skuId)->where('goods_id', '=', $goodsId);
return $this->builder->where('goods_sku_id', $skuId)->where('goods_id', $goodsId);
}
public function location($value)
{
return $this->builder->where('location', '=', $value);
return $this->builder->where('location', $value);
}
public function status($value)
{
return $this->builder->where('status', '=', $value);
return $this->builder->where('status', $value);
}
}

View File

@ -11,11 +11,11 @@ class GroupGoodsFilter extends Filters
protected function groupId($value)
{
return $this->builder->where('group_id', '=', $value);
return $this->builder->where('group_id', $value);
}
protected function externalSkuId($value)
{
return $this->builder->where('external_sku_id', '=', $value);
return $this->builder->where('external_sku_id', $value);
}
}

View File

@ -12,12 +12,12 @@ class GroupsFilter extends Filters
protected function shopId($value)
{
if ($value) {
return $this->builder->where('shop_id', '=', $value);
return $this->builder->where('shop_id', $value);
}
}
protected function status($value)
{
return $this->builder->where('status', '=', $value);
return $this->builder->where('status', $value);
}
}

View File

@ -6,32 +6,32 @@ class LogFilter extends Filters
{
protected function module($value)
{
return $this->builder->where('module', '=', $value);
return $this->builder->where('module', $value);
}
protected function action($value)
{
return $this->builder->where('action', '=', $value);
return $this->builder->where('action', $value);
}
protected function targetType($value)
{
return $this->builder->where('target_type', '=', $value);
return $this->builder->where('target_type', $value);
}
protected function targetId($value)
{
return $this->builder->where('target_id', '=', $value);
return $this->builder->where('target_id', $value);
}
protected function targetField($value)
{
return $this->builder->where('target_field', '=', $value);
return $this->builder->where('target_field', $value);
}
protected function userId($value)
{
return $this->builder->where('user_id', '=', $value);
return $this->builder->where('user_id', $value);
}
protected function startTime($value)

View File

@ -6,6 +6,6 @@ class ShopFilter extends Filters
{
protected function platId($value)
{
return $this->builder->where('plat_id', '=', $value)->where('expires_at', '>', time());
return $this->builder->where('plat_id', $value)->where('expires_at', '>', time());
}
}

View File

@ -47,10 +47,10 @@ class BusinessGoodsSkusController extends Controller
return response($this->res, $this->res['httpCode']);
}
$sku = BusinessGoodsSku::query()->find($id);
$this->setBeforeUpdate($sku->is_sync);
$this->setBeforeUpdateForLog($sku->is_sync);
$sku->is_sync = $request->input('is_sync');
$sku->save();
$this->setAfterUpdate($sku->is_sync);
$this->setAfterUpdateForLog($sku->is_sync);
$this->addLog($id, 'status');
return response($this->res, $this->res['httpCode']);
@ -61,10 +61,10 @@ class BusinessGoodsSkusController extends Controller
DB::beginTransaction();
try {
$sku = BusinessGoodsSku::query()->find($id);
$this->setBeforeUpdate($sku->toArray());
$this->setBeforeUpdateForLog($sku->toArray());
BusinessOrderItem::query()->where('goods_id', $sku->goods_id)->where('sku_id', $sku->sku_id)->delete();
$sku->delete();
$this->setAfterUpdate('');
$this->setAfterUpdateForLog('');
$this->addLog($id, '');
DB::commit();
} catch (Exception $exception) {
@ -79,11 +79,8 @@ class BusinessGoodsSkusController extends Controller
public function syncStock($id, Request $request)
{
$businessGoodsSku = BusinessGoodsSku::query()->where('is_sync', 1)->find($id);
[$goodsCode, $skuCode] = explode('_', $businessGoodsSku->external_sku_id);
$sku = GoodsSku::query()->where('sku_code', $skuCode)
->whereHas('goods', function ($query) use ($goodsCode) {
$query->where('goods_code', $goodsCode);
})
$sku = GoodsSku::query()
->where('external_sku_id', $businessGoodsSku->external_sku_id)
->first();
if (empty($sku)) {
$this->setValidatorFailResponse('未找到对应的商品,请核实后再次同步或删除此平台商品');

View File

@ -29,12 +29,12 @@ class Controller extends BaseController
];
}
protected function setBeforeUpdate($data)
protected function setBeforeUpdateForLog($data)
{
$this->log->before_update = is_array($data) ? json_encode($data, 256) : $data;
}
protected function setAfterUpdate($data)
protected function setAfterUpdateForLog($data)
{
$this->log->after_update = is_array($data) ? json_encode($data, 256) : $data;
}

View File

@ -51,7 +51,7 @@ class GoodsBrandsController extends Controller
'errorMessage' => '批量添加失败',
];
}
$this->setAfterUpdate($goodsBrands);
$this->setAfterUpdateForLog($goodsBrands);
$this->addLog(0, 'add');
return response($this->res, $this->res['httpCode']);
@ -78,10 +78,10 @@ class GoodsBrandsController extends Controller
return response($this->res, $this->res['httpCode']);
}
$goodsBrand = GoodsBrand::query()->find($id);
$this->setBeforeUpdate($goodsBrand->name);
$this->setBeforeUpdateForLog($goodsBrand->name);
$goodsBrand->name = request('name');
$goodsBrand->save();
$this->setAfterUpdate($goodsBrand->name);
$this->setAfterUpdateForLog($goodsBrand->name);
$this->addLog($id, 'name');
return new GoodsBrandResource($goodsBrand);

View File

@ -60,10 +60,11 @@ class GoodsController extends Controller
$item['goods_id'] = $goods->id;
$item['stock'] = $item['num'];
$item['reference_price'] = $item['cost'] * 1.5;
$item['external_sku_id'] = $goods->goods_code . '_' . $item['sku_code'];
$goodsSkus[] = $item;
}
$collection = $goods->skus()->createMany($goodsSkus)->toArray();
$this->setAfterUpdate($collection);
$this->setAfterUpdateForLog($collection);
$this->addLog(0, 'add');
$newRecords = [];
foreach ($collection as $sku) {

View File

@ -10,10 +10,12 @@ use App\Http\Requests\GoodsSkuRequest;
use App\Imports\InventoryImport;
use App\Models\BusinessOrderItem;
use App\Models\Goods;
use App\Models\GoodsType;
use App\Models\Log;
use App\Models\Log as LogModel;
use App\Utils\ArrayUtils;
use App\Utils\DateTimeUtils;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
use App\Models\GoodsSku;
use App\Http\Resources\GoodsSkuResource;
@ -39,41 +41,18 @@ class GoodsSkusController extends Controller
public function index(Request $request)
{
$goodsCode = $skuCode = '';
if ($externalSkuId = $request->get('external_sku_id')) {
[$goodsCode, $skuCode] = explode('_', $externalSkuId);
}
$goods = Goods::query()->filter()->when($goodsCode, function ($query, $goodsCode) {
return $query->where('goods_code', $goodsCode);
})->get()->toArray();
$goodsIds = array_column($goods, 'id');
// 状态变更时间查询,日志
$ids = [];
if ($request->get('keyword_type', '') && $request->get('keyword_value', '')) {
$ids = Log::query()->where('target_type', 'goods_sku')
->where('target_field', $request->keyword_type)
->whereBetween('created_at', explode(' - ', $request->keyword_value))
->pluck('target_id')
->toArray();
}
$builder = GoodsSku::query();
$this->preparQueryGoodsSkus($request, $builder);
$day = DateTimeUtils::getToday();
$goodsSkus = GoodsSku::query()
->whereIn('goods_id', $goodsIds)
->when($ids, function ($query, $ids) {
return $query->whereIn('id', $ids);
})
->when($skuCode, function ($query, $skuCode) {
return $query->where('sku_code', $skuCode);
})
->filter()
$goodsSkus = $builder->filter()
->with(['goods' => function ($query) {
$query->with(['type:id,name', 'brand:id,name']);
}])
->with(['daily' => function ($query) use ($day) {
$query->where('day', $day);
}])
->orderBy('updated_at', 'desc')
->paginate($request->get('per_page'));
->orderByDesc('updated_at')
->paginate(10);
$fields = implode(',', [
'shop_id',
'external_sku_id',
@ -82,20 +61,19 @@ class GoodsSkusController extends Controller
]);
$rolesName = $request->user()->getRoleNames()->toArray();
foreach ($goodsSkus as &$sku) {
$externalSkuId = $sku['goods']['goods_code'] . '_' . $sku['sku_code'];
$lastInventoryTime = $sku['daily']['inventory_time'];
$orderDetail = BusinessOrderItem::query()
->select(DB::raw($fields))
->where('external_sku_id', $externalSkuId)
->with(['shop:id,name'])
->where('external_sku_id', $sku['external_sku_id'])
->when($lastInventoryTime, function ($query) use ($lastInventoryTime) {
$query->where('created_at', '>', $lastInventoryTime);
})
->groupBy(['shop_id', 'external_sku_id'])
->with(['shop:id,name'])
->get();
->get()
->toArray();
$addOrderGoodsNum = $reduceOrderGoodsNum = 0;
if ($orderDetail) {
$orderDetail = $orderDetail->toArray();
$addOrderGoodsNum = array_sum(array_column($orderDetail, 'number'));
$reduceOrderGoodsNum = array_sum(array_column($orderDetail, 'cancel_number'));
}
@ -110,6 +88,22 @@ class GoodsSkusController extends Controller
return GoodsSkuResource::collection($goodsSkus);
}
private function preparQueryGoodsSkus(Request $request, &$builder)
{
if ($request->get('keyword_type') && $request->get('keyword_value')) {
$skuIds = Log::query()->where('target_type', 'goods_sku')
->where('target_field', $request->keyword_type)
->whereBetween('created_at', explode(' - ', $request->keyword_value))
->pluck('target_id')
->toArray();
$builder->whereIn('id', $skuIds);
}
if ($request->get('goods_title') || $request->get('type_id') || $request->get('brand_id')) {
$goodsIds = Goods::query()->filter()->pluck('id')->toArray();
$builder->whereIn('goods_id', $goodsIds);
}
}
public function show($id)
{
$sku = GoodsSku::query()
@ -146,9 +140,10 @@ class GoodsSkusController extends Controller
try {
// 商品规格更新
$sku = GoodsSku::query()->find($id);
$this->setBeforeUpdate($sku->toArray());
$this->setBeforeUpdateForLog($sku->toArray());
$request->sku['external_sku_id'] = $request->goods['goods_code'] . '_' . $request->sku['sku_code'];
$sku->update($request->sku);
$this->setAfterUpdate($sku->toArray());
$this->setAfterUpdateForLog($sku->toArray());
$this->addLog($id, 'update');
// 商品更新
$goods = Goods::query()->find($sku->goods_id);
@ -157,9 +152,9 @@ class GoodsSkusController extends Controller
'action' => $request->getMethod(),
'target_type' => 'goods',
]);
$this->setBeforeUpdate($goods->toArray());
$this->setBeforeUpdateForLog($goods->toArray());
$goods->update($request->goods);
$this->setAfterUpdate($goods->toArray());
$this->setAfterUpdateForLog($goods->toArray());
$this->addLog($sku->goods_id, 'update');
DB::commit();
} catch (\Exception $exception) {
@ -351,7 +346,7 @@ class GoodsSkusController extends Controller
->where('sku_id', $sku->id)
->where('day', DateTimeUtils::getToday())
->first();
$this->setBeforeUpdate([
$this->setBeforeUpdateForLog([
'two_days_ago_num' => $sku->two_days_ago_num,
'yesterday_num' => $sku->yesterday_num,
'arrived_today_num' => $record->arrived_today_num,
@ -366,7 +361,7 @@ class GoodsSkusController extends Controller
$sku->save();
$record->arrived_today_num = $update['arrived_today_num'];
$record->save();
$this->setAfterUpdate([
$this->setAfterUpdateForLog([
'two_days_ago_num' => $sku->two_days_ago_num,
'yesterday_num' => $sku->yesterday_num,
'arrived_today_num' => $record->arrived_today_num,
@ -432,14 +427,14 @@ class GoodsSkusController extends Controller
->where('day', DateTimeUtils::getToday())
->first(['id', 'loss_num']);
$this->log->message = $request->get('reason');
$this->setBeforeUpdate($record->loss_num);
$this->setBeforeUpdateForLog($record->loss_num);
$record->loss_num += $request->loss_num;
$record->save();
$this->setAfterUpdate($record->loss_num);
$this->setAfterUpdateForLog($record->loss_num);
$sku->stock -= $request->loss_num;
$sku->save();
} else {
$this->setBeforeUpdate($sku->$updateField);
$this->setBeforeUpdateForLog($sku->$updateField);
if ('reserve' === $updateField) {
$changeNum = $sku->reserve - $request->reserve;
if (0 > $changeNum + $sku->stock) {
@ -450,7 +445,7 @@ class GoodsSkusController extends Controller
}
$sku->$updateField = $request->$updateField;
$sku->save();
$this->setAfterUpdate($sku->$updateField);
$this->setAfterUpdateForLog($sku->$updateField);
}
if (in_array($updateField, ['reserve', 'loss_num'])) {
event(new StockUpdateEvent($sku));
@ -509,4 +504,24 @@ class GoodsSkusController extends Controller
return response($this->res, $this->res['httpCode']);
}
public function stockNum()
{
$roseTypeId = GoodsType::query()->where('name', '玫瑰')->value('id');
$totalNum = GoodsSku::query()
->where('status', '>', 0)
->sum('stock');
$roseNum = GoodsSku::query()
->whereHas('goods', function (Builder $query) use ($roseTypeId) {
$query->where('type_id', $roseTypeId);
})
->where('status', '>', 0)
->sum('stock');
return response()->json([
'total_num' => $totalNum,
'rose_num' => $roseNum,
'other_num' => $totalNum - $roseNum,
]);
}
}

View File

@ -51,7 +51,7 @@ class GoodsTypesController extends Controller
'errorMessage' => '批量添加失败',
];
}
$this->setAfterUpdate($goodsTypes);
$this->setAfterUpdateForLog($goodsTypes);
$this->addLog(0, 'add');
return response($this->res, $this->res['httpCode']);
@ -78,10 +78,10 @@ class GoodsTypesController extends Controller
return response($this->res, $this->res['httpCode']);
}
$goodsType = GoodsType::query()->find($id);
$this->setBeforeUpdate($goodsType->name);
$this->setBeforeUpdateForLog($goodsType->name);
$goodsType->name = request('name');
$goodsType->save();
$this->setAfterUpdate($goodsType->name);
$this->setAfterUpdateForLog($goodsType->name);
$this->addLog($id, 'name');
return new GoodsTypeResource($goodsType);

View File

@ -76,7 +76,7 @@ class MenusController extends Controller
$menu->parent_id = $request->parent_id;
$menu->seq = $request->seq;
$menu->save();
$this->setAfterUpdate($menu->toArray());
$this->setAfterUpdateForLog($menu->toArray());
$this->addLog($menu->id, 'add');
return response($this->res, $this->res['httpCode']);
@ -101,13 +101,13 @@ class MenusController extends Controller
return response($this->res, $this->res['httpCode']);
}
$menu = Menu::query()->find($id);
$this->setBeforeUpdate($menu->toArray());
$this->setBeforeUpdateForLog($menu->toArray());
$menu->name = $request->name;
$menu->code = $request->code;
$menu->parent_id = $request->parent_id;
$menu->seq = $request->seq;
$menu->save();
$this->setAfterUpdate($menu->toArray());
$this->setAfterUpdateForLog($menu->toArray());
$this->addLog($id, 'update');
return new MenusResource($menu);

View File

@ -53,7 +53,7 @@ class PermissionsController extends Controller
$permission = new Permission();
$permission->name = $request->name;
$permission->save();
$this->setAfterUpdate($permission->name);
$this->setAfterUpdateForLog($permission->name);
$this->addLog($permission->id, 'add');
return response($this->res, $this->res['httpCode']);
@ -75,10 +75,10 @@ class PermissionsController extends Controller
return response($this->res, $this->res['httpCode']);
}
$permission = Permission::query()->find($id);
$this->setBeforeUpdate($permission->name);
$this->setBeforeUpdateForLog($permission->name);
$permission->name = $request->name;
$permission->save();
$this->setAfterUpdate($permission->name);
$this->setAfterUpdateForLog($permission->name);
$this->addLog($id, 'name');
return new PermissionsResource($permission);

View File

@ -56,7 +56,7 @@ class RolesController extends Controller
$role = new Role();
$role->name = $request->name;
$role->save();
$this->setAfterUpdate($role->name);
$this->setAfterUpdateForLog($role->name);
$this->addLog($role->id, 'add');
return new RolesResource($role);
@ -67,7 +67,7 @@ class RolesController extends Controller
$role = Role::query()->findOrFail($id);
$permissions = Permission::query()->findOrFail($request->permissionIds);
$role->syncPermissions($permissions);
$this->setAfterUpdate($permissions->toArray());
$this->setAfterUpdateForLog($permissions->toArray());
$this->addLog($id, 'set', 'permission');
return response($this->res, $this->res['httpCode']);
@ -89,10 +89,10 @@ class RolesController extends Controller
return response($this->res, $this->res['httpCode']);
}
$role = Role::query()->find($id);
$this->setBeforeUpdate($role->name);
$this->setBeforeUpdateForLog($role->name);
$role->name = $request->name;
$role->save();
$this->setAfterUpdate($role->name);
$this->setAfterUpdateForLog($role->name);
$this->addLog($id, 'name');
return new RolesResource($role);

View File

@ -150,11 +150,8 @@ class ShopsController extends Controller
->get();
$data = [];
foreach ($res as $item) {
[$goodsCode, $skuCode] = explode('_', $item['external_sku_id']);
$sku = GoodsSku::query()->where('sku_code', $skuCode)
->whereHas('goods', function ($query) use ($goodsCode) {
$query->where('goods_code', $goodsCode);
})
$sku = GoodsSku::query()
->where('external_sku_id', $item['external_sku_id'])
->first();
if (empty($sku)) {
continue;
@ -189,4 +186,36 @@ class ShopsController extends Controller
return response($this->res, $this->res['httpCode']);
}
public function syncStock(Request $request)
{
$shopId = $request->get('shop_id');
$skus = GoodsSku::query()
->where('status', '>', 0)
->whereNotNull('external_sku_id')
->pluck('stock', 'external_sku_id')
->toArray();
$builder = Shop::query()->where('expires_at', '>', time());
if ('all' === $shopId) {
$shops = $builder->get();
} else {
$shops = $builder->where('id', $shopId)->get();
}
foreach ($shops as $shop) {
$business = BusinessFactory::init()->make($shop->plat_id);
$business->setShop($shop);
foreach ($skus as $externalSkuId => $stock) {
$businessGoodsSkus = BusinessGoodsSku::query()
->select(['goods_id', 'sku_id', 'external_sku_id'])
->where('shop_id', $shop->id)
->where('is_sync', 1)
->where('external_sku_id', $externalSkuId)
->get()
->toArray();
$business->batchIncrQuantity($businessGoodsSkus, $stock, false);
}
}
return response($this->res, $this->res['httpCode']);
}
}

View File

@ -46,7 +46,7 @@ class UsersController extends Controller
$user->password = $request->password;
$user->api_token = Str::random(60);
$user->save();
$this->setAfterUpdate($user->toArray());
$this->setAfterUpdateForLog($user->toArray());
$this->addLog($user->id, 'add');
$user->assignRole($request->role_name);

View File

@ -58,7 +58,7 @@ class StockUpdateListener
->select(['goods_id', 'sku_id', 'external_sku_id'])
->where('shop_id', $shop->id)
->where('is_sync', 1)
->where('external_sku_id', $goodsSku->goods['goods_code'] . '_' . $goodsSku->sku_code)
->where('external_sku_id', $goodsSku->external_sku_id)
->get();
if ($event->isBatch) {
BusinessFactory::init()->make($shop['plat_id'])->setShopWithId($shop['id'])->batchIncrQuantity($businessGoodsSkus->toArray(), $num, false);

View File

@ -12,7 +12,8 @@ class GoodsSku extends Model
public $fieldSearchable = [
'sku_title',
'status',
'exclude_ids'
'exclude_ids',
'external_sku_id'
];
protected $fillable = [
@ -27,7 +28,8 @@ class GoodsSku extends Model
'yesterday_num',
'reference_price',
'reserve',
'thumb_url'
'thumb_url',
'external_sku_id'
];
protected $hidden = ['created_at'];

View File

@ -13,6 +13,9 @@ class CreateUsersTable extends Migration
*/
public function up()
{
if (Schema::hasTable('users')) {
return;
}
Schema::defaultStringLength(191);
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');

View File

@ -13,6 +13,9 @@ class CreatePasswordResetsTable extends Migration
*/
public function up()
{
if (Schema::hasTable('password_resets')) {
return;
}
Schema::create('password_resets', function (Blueprint $table) {
$table->string('email')->index();
$table->string('token');

View File

@ -13,6 +13,9 @@ class CreateFailedJobsTable extends Migration
*/
public function up()
{
if (Schema::hasTable('failed_jobs')) {
return;
}
Schema::create('failed_jobs', function (Blueprint $table) {
$table->bigIncrements('id');
$table->text('connection');

View File

@ -13,6 +13,9 @@ class CreateGoodsTypesTable extends Migration
*/
public function up()
{
if (Schema::hasTable('goods_types')) {
return;
}
Schema::defaultStringLength(191);
Schema::create('goods_types', function (Blueprint $table) {
$table->bigIncrements('id');

View File

@ -13,6 +13,9 @@ class CreateGoodsBrandsTable extends Migration
*/
public function up()
{
if (Schema::hasTable('goods_brands')) {
return;
}
Schema::defaultStringLength(191);
Schema::create('goods_brands', function (Blueprint $table) {
$table->bigIncrements('id');

View File

@ -13,6 +13,9 @@ class CreateGoodsTable extends Migration
*/
public function up()
{
if (Schema::hasTable('goods')) {
return;
}
Schema::defaultStringLength(191);
Schema::create('goods', function (Blueprint $table) {
$table->bigIncrements('id');

View File

@ -13,6 +13,9 @@ class CreateGoodsSkusTable extends Migration
*/
public function up()
{
if (Schema::hasTable('goods_skus')) {
return;
}
Schema::defaultStringLength(191);
Schema::create('goods_skus', function (Blueprint $table) {
$table->bigIncrements('id');

View File

@ -13,6 +13,9 @@ class CreateDailyStockRecordsTable extends Migration
*/
public function up()
{
if (Schema::hasTable('daily_stock_records')) {
return;
}
Schema::create('daily_stock_records', function (Blueprint $table) {
$table->bigIncrements('id');
$table->bigInteger('sku_id');

View File

@ -13,6 +13,9 @@ class CreateLogsTable extends Migration
*/
public function up()
{
if (Schema::hasTable('logs')) {
return;
}
Schema::create('logs', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('module')->comment('模块');

View File

@ -13,6 +13,9 @@ class CreateMenusTable extends Migration
*/
public function up()
{
if (Schema::hasTable('menus')) {
return;
}
Schema::defaultStringLength(191);
Schema::create('menus', function (Blueprint $table) {
$table->bigIncrements('id');

View File

@ -13,6 +13,9 @@ class CreateShopsTable extends Migration
*/
public function up()
{
if (Schema::hasTable('shops')) {
return;
}
Schema::defaultStringLength(191);
Schema::create('shops', function (Blueprint $table) {
$table->bigIncrements('id');

View File

@ -13,6 +13,9 @@ class CreateBusinessGoodsSkusTable extends Migration
*/
public function up()
{
if (Schema::hasTable('business_goods_skus')) {
return;
}
Schema::create('business_goods_skus', function (Blueprint $table) {
$table->bigIncrements('id');
$table->bigInteger('shop_id');

View File

@ -13,6 +13,9 @@ class CreateBusinessOrdersTable extends Migration
*/
public function up()
{
if (Schema::hasTable('business_orders')) {
return;
}
Schema::create('business_orders', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('shop_id');

View File

@ -13,6 +13,9 @@ class CreateBusinessOrderItemsTable extends Migration
*/
public function up()
{
if (Schema::hasTable('business_order_items')) {
return;
}
Schema::create('business_order_items', function (Blueprint $table) {
$table->bigIncrements('id');
$table->bigInteger('shop_id');

View File

@ -13,6 +13,9 @@ class CreateJobsTable extends Migration
*/
public function up()
{
if (Schema::hasTable('jobs')) {
return;
}
Schema::create('jobs', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('queue')->index();

View File

@ -13,6 +13,9 @@ class AddFieldsWithDailyStockRecordsTable extends Migration
*/
public function up()
{
if (Schema::hasColumns('daily_stock_records', ['order_goods_num', 'inventory_time'])) {
return;
}
Schema::table('daily_stock_records', function (Blueprint $table) {
$table->integer('order_goods_num')->default(0)->comment('截止盘点时间订单商品数量');
$table->timestamp('inventory_time')->nullable()->comment('盘点时间');

View File

@ -13,6 +13,9 @@ class AddFieldsWithBusinessGoodsSkusTable extends Migration
*/
public function up()
{
if (Schema::hasColumn('business_goods_skus', 'is_sync')) {
return;
}
Schema::table('business_goods_skus', function (Blueprint $table) {
$table->tinyInteger('is_sync')->default(1)->comment('是否同步');
});

View File

@ -13,6 +13,9 @@ class CreateGroupsTable extends Migration
*/
public function up()
{
if (Schema::hasTable('groups')) {
return;
}
Schema::defaultStringLength(191);
Schema::create('groups', function (Blueprint $table) {
$table->bigIncrements('id');

View File

@ -13,6 +13,9 @@ class CreateGroupGoodsTable extends Migration
*/
public function up()
{
if (Schema::hasTable('group_goods')) {
return;
}
Schema::defaultStringLength(191);
Schema::create('group_goods', function (Blueprint $table) {
$table->bigIncrements('id');

View File

@ -13,6 +13,9 @@ class CreateGoodsSkuLocationsTable extends Migration
*/
public function up()
{
if (Schema::hasTable('goods_sku_locations')) {
return;
}
Schema::defaultStringLength(191);
Schema::create('goods_sku_locations', function (Blueprint $table) {
$table->bigIncrements('id');

View File

@ -0,0 +1,38 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddExternalSkuIdToGoodsSkusTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
if (Schema::hasColumn('goods_skus', 'external_sku_id')) {
return;
}
Schema::defaultStringLength(191);
Schema::table('goods_skus', function (Blueprint $table) {
$table->string('external_sku_id')->nullable();
$table->index('external_sku_id');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('goods_skus', function (Blueprint $table) {
$table->dropColumn('external_sku_id');
$table->dropIndex('external_sku_id');
});
}
}

View File

@ -127,3 +127,10 @@ export function deleteGoodsSkuLocation(params) {
params,
});
}
export function getStockNum() {
return http({
url: "/api/stock/goods_skus",
method: "get",
})
}

View File

@ -41,3 +41,11 @@ export function updateStore(id, params) {
params,
});
}
export function syncStoreStock(params) {
return http({
url: '/api/sync/shop/stock',
method: "put",
params,
});
}

View File

@ -5,10 +5,6 @@
<el-card :body-style="{ padding: '20px 20px 0 20px' }">
<div class="goods">
<el-form ref="form" :inline="true" :model="form">
<el-form-item label="商品编码:">
<el-input v-model="form.external_sku_id" placeholder="商品编码" style="width: 100px">
</el-input>
</el-form-item>
<el-form-item label="商品名称:">
<el-input v-model="form.goods_title" placeholder="商品名称" style="width: 100px">
</el-input>
@ -19,16 +15,16 @@
</el-option>
</el-select>
</el-form-item>
<el-form-item label="商品规格:">
<el-input v-model="form.sku_title" placeholder="商品规格" style="width: 100px">
</el-input>
</el-form-item>
<el-form-item label="商品品牌:">
<el-select v-model="form.brand_id" placeholder="商品品牌" style="width: 125px">
<el-option v-for="item in brand" :key="item.id" :label="item.name" :value="item.id">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="商品编码:">
<el-input v-model="form.external_sku_id" placeholder="商品编码" style="width: 100px">
</el-input>
</el-form-item>
<el-form-item label="商品状态:">
<el-select v-model="form.status" placeholder="商品状态" style="width: 115px">
<el-option v-for="item in options" :key="item.id" :label="item.label" :value="item.id">
@ -36,15 +32,13 @@
</el-select>
</el-form-item>
<el-form-item>
<el-select v-model="form.keyword_type"
style="width: 80px; margin-right: 5px; margin-left: 10px">
<el-option v-for="item in options3" :key="item.value" :label="item.label"
:value="item.value">
<el-select v-model="form.keyword_type" style="width: 80px; margin-right: 5px; margin-left: 10px">
<el-option v-for="item in options3" :key="item.value" :label="item.label" :value="item.value">
</el-option>
</el-select>
<el-date-picker v-model="value1" type="datetimerange" range-separator=""
start-placeholder="开始时间" end-placeholder="结束时间" value-format="yyyy-MM-dd HH:mm:ss"
@change="getSTime" style="width: 300px">
<el-date-picker v-model="value1" type="datetimerange" range-separator="至" start-placeholder="开始时间"
end-placeholder="结束时间" value-format="yyyy-MM-dd HH:mm:ss" @change="getSTime"
style="width: 300px">
</el-date-picker>
</el-form-item>
<el-form-item>
@ -60,12 +54,13 @@
<!-- 表格头部操作 -->
<div>
<span>全部商品({{ total }})</span>
<span>&nbsp;玫瑰合计: {{ rose_num }}</span>
<span>&nbsp;其它合计: {{ other_num }}</span>
<div class="btn">
<el-button type="primary" plain @click="update()">上新</el-button>
<el-upload ref="myUpload" action="/api/inventory/goods_skus" :multiple="false"
name="inventoryFile" :show-file-list="false" :on-success="inventorySuccess"
:before-upload="beforeInventory" :on-error="inventoryError"
style="display:inline-block;margin: 0 10px 0 10px;">
<el-upload ref="myUpload" action="/api/inventory/goods_skus" :multiple="false" name="inventoryFile"
:show-file-list="false" :on-success="inventorySuccess" :before-upload="beforeInventory"
:on-error="inventoryError" style="display:inline-block;margin: 0 10px 0 10px;">
<el-button type="primary" plain>盘点导入</el-button>
</el-upload>
<el-button type="primary" plain @click="addNewgoods">新建商品</el-button>
@ -172,8 +167,7 @@
<div>
<span>{{ scope.row.order_goods_num }}</span>
</div>
<el-popover placement="right-start" trigger="hover"
v-if="scope.row.order_detail.length !== 0">
<el-popover placement="right-start" trigger="hover" v-if="scope.row.order_detail.length !== 0">
<div>
<span v-for="(j, index) in scope.row.order_detail" :key="index">
<div>{{ j.shop.name }}:{{ j.number }}</div>
@ -375,7 +369,7 @@
<script>
import axios from "axios";
import { goods_types, Brand_goods_types } from "../../api/rankingData.js";
import { goods, update, singleUpdate } from "../../api/goods";
import { goods, update, singleUpdate, getStockNum } from "../../api/goods";
export default {
data() {
return {
@ -383,6 +377,8 @@ export default {
id1: "", //id
id2: "", //id
total: 0, //
rose_num: 0, //
other_num: 0, //
radio: "", //
brand: [], //
cate: [], //
@ -496,9 +492,16 @@ export default {
};
},
methods: {
//
getStockInfo() {
getStockNum().then((res) => {
this.rose_num = res.data.rose_num;
this.other_num = res.data.other_num;
})
},
//
handleEdit(id) {
this.$router.push({path:"EDIT_GOODS",query:{id:id}});
this.$router.push({ path: "EDIT_GOODS", query: { id: id } });
},
//
@ -939,6 +942,7 @@ export default {
mounted() {
this.getList();
this.getStockInfo();
this.getgoodsType();
this.getbrandType();
this.id = "";

View File

@ -1,7 +1,8 @@
<template>
<div class="conent">
<!-- 新增按钮 -->
<el-button type="primary" @click="handAdd">新增</el-button>
<el-button type="success" @click="handAdd">新增</el-button>
<el-button type="primary" @click="syncShopStock('all')">同步所有店铺库存</el-button>
<div class="table" style="margin-top: 10px">
<el-table v-loading="loading" :data="tableData" style="width: 100%">
@ -17,27 +18,25 @@
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button type="danger" v-if="scope.row.status === '未授权'"><a :href="scope.row.authUrl"
target="_blank"
rel="noopener noreferrer">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</a>
<el-button type="danger" v-if="scope.row.status === '未授权'" size="small"><a :href="scope.row.authUrl"
target="_blank" rel="noopener noreferrer">授权</a>
</el-button>
<div v-if="scope.row.status === '已授权'">
<el-button type="success" :disabled="true">{{
scope.row.status
}}</el-button>
<el-button @click="download(scope.row)">下载商品</el-button>
<el-button type="success" :disabled="true" size="small">{{ scope.row.status }}</el-button>
<el-button @click="download(scope.row)" size="small">下载商品</el-button>
<el-button type="primary" v-if="scope.row.status === '已授权'" size="small"
@click="syncShopStock(scope.row.id)">同步库存</el-button>
</div>
<div v-if="scope.row.status === '重新授权'">
<el-button type="danger" target="_blank"><a :href="scope.row.authUrl"
rel="noopener noreferrer">重新授权</a>
<el-button type="danger" target="_blank" size="small">
<a :href="scope.row.authUrl" rel="noopener noreferrer">重新授权</a>
</el-button>
<el-button @click="download(scope.row)">下载商品</el-button>
<el-button @click="download(scope.row)" size="small">下载商品</el-button>
</div>
<div v-if="scope.row.status === '无需授权'">
<el-button type="success" :disabled="true">{{
scope.row.status
}}</el-button>
<el-button type="success" :disabled="true" size="small">{{ scope.row.status }}</el-button>
</div>
</template>
</el-table-column>
@ -77,7 +76,7 @@
</template>
<script>
import { shopListId, shopAdd, storeList, downloadGoods, updateStore } from "../../api/shop";
import { shopListId, shopAdd, storeList, downloadGoods, updateStore, syncStoreStock } from "../../api/shop";
export default {
data() {
return {
@ -196,6 +195,22 @@ export default {
})
});
},
//
syncShopStock(id) {
let loading = this.$loading({
lock: true,
text: '店铺商品库存同步中...',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
syncStoreStock({ shop_id: id }).then((res) => {
loading.close();
this.$message({
type: 'info',
message: res.data.message
})
});
}
},
};
</script>

View File

@ -11,8 +11,8 @@ module.exports = {
proxy: {
// 配置代理
"/api": {
// target: "http://192.168.247.186:81",
target: "http://erp.chutang66.com",
target: "http://192.168.247.186:81",
// target: "http://erp.chutang66.com",
changeOrigin: true, // 开启代理
pathRewrite: {
// 重命名

View File

@ -183,6 +183,11 @@ return [
'name' => '商品下载',
'parent_id' => 5,
],
'business.shop.sync_stock' => [
'id' => 56,
'name' => '同步库存',
'parent_id' => 5,
],
// 用户管理
'USER_MANAGE' => [
'id' => 6,

View File

@ -39,6 +39,7 @@ Route::middleware(['auth:api', 'check.permissions'])->group(function () {
Route::resource('shops', 'Shop\ShopsController', ['only' => ['index', 'store', 'show', 'update', 'destroy']]);
Route::get('count/orders/num', [ShopsController::class, 'countOrdersNumWithSkuCode'])->name('goods_sku.orders_num');
Route::get('download/{id}/goods', [ShopsController::class, 'downloadGoods'])->name('business.goods_sku.download');
Route::put('sync/shop/stock', [ShopsController::class, 'syncStock'])->name('business.shop.sync_stock');
// 角色
Route::resource('roles', 'Role\RolesController', ['only' => ['index', 'store', 'show', 'update']]);
Route::post('roles/{id}/permissions', [RolesController::class, 'addPermissions'])->name('roles.permission');
@ -58,6 +59,7 @@ Route::middleware(['auth:api', 'check.permissions'])->group(function () {
Route::put('goods_sku_location', [GoodsSkuLocationController::class, 'update'])->name('goods_sku_location.update');
Route::delete('goods_sku_location', [GoodsSkuLocationController::class, 'delete'])->name('goods_sku_location.delete');
});
Route::get('stock/goods_skus', [GoodsSkusController::class, 'stockNum'])->middleware('auth:api');
// 登录
Route::post('/auth/login', [LoginController::class, 'login'])->name('auth.login');