添加商品库存变动
parent
7a36086928
commit
0fe2f5779a
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
namespace App\Endpoint\Api\Filters;
|
||||
|
||||
use EloquentFilter\ModelFilter;
|
||||
|
||||
class DealerUserProductLogFilter extends ModelFilter
|
||||
{
|
||||
public function productId($productId)
|
||||
{
|
||||
$this->where('product_id', $productId);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
<?php
|
||||
|
||||
namespace App\Endpoint\Api\Http\Controllers\Dealer;
|
||||
|
||||
use App\Endpoint\Api\Http\Controllers\Controller;
|
||||
use App\Endpoint\Api\Http\Resources\Dealer\UserProductLogResource;
|
||||
use App\Endpoint\Api\Http\Resources\Dealer\UserProductResource;
|
||||
use App\Exceptions\BizException;
|
||||
use App\Helpers\Paginator;
|
||||
use App\Models\DealerUserProductLog;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Throwable;
|
||||
|
||||
class UserProductController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
$list = $request->user()->dealerProducts()
|
||||
->with('product')
|
||||
->orderBy('product_id', 'asc')
|
||||
->simplePaginate(Paginator::resolvePerPage('per_page', 20, 50));
|
||||
return UserProductResource::collection($list);
|
||||
}
|
||||
|
||||
public function show($id, Request $request)
|
||||
{
|
||||
$product = $request->user()->dealerProducts()
|
||||
->with('product')
|
||||
->where('product_id', $id)
|
||||
->first();
|
||||
return UserProductResource::make($product);
|
||||
}
|
||||
|
||||
public function logs(Request $request)
|
||||
{
|
||||
$list = $request->user()->dealerProductLogs()->filter($request->all())
|
||||
->with('product')
|
||||
->orderBy('created_at', 'desc')
|
||||
->simplePaginate(Paginator::resolvePerPage('per_page', 20, 50));
|
||||
return UserProductLogResource::collection($list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 线下去库存
|
||||
*
|
||||
* @param Request $request
|
||||
* @return void
|
||||
*/
|
||||
public function offlineOutQty(Request $request)
|
||||
{
|
||||
$input = $request->validate([
|
||||
'product_id'=>['bail', 'required', 'int', 'min:0'],
|
||||
'num'=>['bail', 'required', 'int', 'min:1'],
|
||||
'remark'=> ['bail', 'string', 'max:200'],
|
||||
], [], [
|
||||
'product_id' => '商品',
|
||||
'num' => '数量',
|
||||
'remark'=>'备注',
|
||||
]);
|
||||
$product = $request->user()->dealerProducts()
|
||||
->where('product_id', $input['product_id'])
|
||||
->first();
|
||||
if (!$product) {
|
||||
throw new BizException('您还没有该商品');
|
||||
}
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
$product->decrement('stock', $input['num']);
|
||||
|
||||
DealerUserProductLog::create([
|
||||
'user_id'=> $request->user()->id,
|
||||
'product_id'=> $input['product_id'],
|
||||
'type' => DealerUserProductLog::TYPE_OFFLINE_OUT,
|
||||
'qty'=>$input['num'],
|
||||
'remark'=>$input['remark']??null,
|
||||
]);
|
||||
DB::commit();
|
||||
} catch (Throwable $th) {
|
||||
DB::rollBack();
|
||||
report($th);
|
||||
throw new BizException('系统繁忙,请稍后再试');
|
||||
}
|
||||
return response()->noContent();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
namespace App\Endpoint\Api\Http\Resources\Dealer;
|
||||
|
||||
use App\Models\DealerUserProductLog;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class UserProductLogResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'product_name'=> $this->product?->name,
|
||||
'remark' => $this->remark,
|
||||
'qty' => ($this->type == DealerUserProductLog::TYPE_ORDER_IN ? '+' : '-').$this->qty.$this->product?->unit,
|
||||
'created_at' => $this->created_at->toDateTimeString(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
namespace App\Endpoint\Api\Http\Resources\Dealer;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class UserProductResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'product_id' => $this->product_id,
|
||||
'name' => $this->product?->name,
|
||||
'cover' => (string) $this->product?->cover,
|
||||
'price' => (string) $this->product?->price,
|
||||
'stock' => (int) $this->stock,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -218,6 +218,12 @@ Route::group([
|
|||
], function () {
|
||||
//个人信息
|
||||
Route::get('me', [Dealer\UserController::class, 'show']);
|
||||
//我的库存
|
||||
Route::get('user-products', [Dealer\UserProductController::class, 'index']);
|
||||
Route::get('user-products/{product}', [Dealer\UserProductController::class, 'show']);
|
||||
Route::get('user-products-logs', [Dealer\UserProductController::class, 'logs']);
|
||||
Route::post('user-products/offline-out', [Dealer\UserProductController::class, 'offlineOutQty']);
|
||||
|
||||
//商品列表
|
||||
Route::get('products', [Dealer\ProductController::class, 'index']);
|
||||
//商品详情
|
||||
|
|
|
|||
|
|
@ -71,7 +71,9 @@ class DealerOrder extends Model
|
|||
*/
|
||||
public function scopeOnlyPaid($query)
|
||||
{
|
||||
return $query->where('status', DealerOrderStatus::Confirming);
|
||||
return $query->whereBetween('status', [
|
||||
DealerOrderStatus::Confirming, DealerOrderStatus::Shipped,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -8,4 +8,15 @@ use Illuminate\Database\Eloquent\Model;
|
|||
class DealerUserProduct extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'user_id',
|
||||
'product_id',
|
||||
'stock',
|
||||
];
|
||||
|
||||
public function product()
|
||||
{
|
||||
return $this->belongsTo(DealerProduct::class, 'product_id');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,10 +2,31 @@
|
|||
|
||||
namespace App\Models;
|
||||
|
||||
use Dcat\Admin\Traits\HasDateTimeFormatter;
|
||||
use EloquentFilter\Filterable;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class DealerUserProductLog extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
use Filterable;
|
||||
use HasDateTimeFormatter;
|
||||
|
||||
public const TYPE_ORDER_IN = 1; //采购加库存
|
||||
public const TYPE_ORDER_OUT = 2; //发货扣库存
|
||||
public const TYPE_OFFLINE_OUT = 3;//线下去库存
|
||||
|
||||
protected $fillable = [
|
||||
'user_id',
|
||||
'product_id',
|
||||
'type',
|
||||
'qty',
|
||||
'remark',
|
||||
];
|
||||
|
||||
public function product()
|
||||
{
|
||||
return $this->belongsTo(DealerProduct::class, 'product_id');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -170,6 +170,24 @@ class User extends Model implements AuthorizableContract, AuthenticatableContrac
|
|||
return $this->hasMany(DealerOrder::class, 'consignor_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 经销商商品库存
|
||||
*
|
||||
*/
|
||||
public function dealerProducts()
|
||||
{
|
||||
return $this->hasMany(DealerUserProduct::class, 'user_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 经销商商品库存
|
||||
*
|
||||
*/
|
||||
public function dealerProductLogs()
|
||||
{
|
||||
return $this->hasMany(DealerUserProductLog::class, 'user_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 确认此用户是否是 VIP
|
||||
*
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ use App\Enums\DealerOrderStatus;
|
|||
use App\Exceptions\BizException;
|
||||
use App\Models\DealerOrder;
|
||||
use App\Models\DealerProduct;
|
||||
use App\Models\DealerUserProductLog;
|
||||
use App\Models\ShippingAddress;
|
||||
use App\Models\User;
|
||||
use App\Models\UserInfo;
|
||||
|
|
@ -175,11 +176,11 @@ class OrderService
|
|||
if (!$order->isPaid()) {
|
||||
throw new BizException('订单状态异常,请刷新后再试');
|
||||
}
|
||||
//todo-扣减发货人库存
|
||||
//扣减发货人库存
|
||||
if ($order->consignor) {
|
||||
$this->orderOutQty($order);
|
||||
}
|
||||
|
||||
|
||||
$order->update([
|
||||
'status' => DealerOrderStatus::Shipped,
|
||||
'shipping_time' => now(),
|
||||
|
|
@ -191,7 +192,8 @@ class OrderService
|
|||
if (!$order->isShipping()) {
|
||||
throw new BizException('订单状态异常,请刷新后再试');
|
||||
}
|
||||
//todo-增加自己的库存
|
||||
//增加自己的库存
|
||||
$this->orderInQty($order);
|
||||
|
||||
$order->update([
|
||||
'status' => DealerOrderStatus::Completed,
|
||||
|
|
@ -240,6 +242,52 @@ class OrderService
|
|||
return $user->shippingAddresses()->where('is_default', true)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户通过下单新增库存
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function orderInQty(DealerOrder $order)
|
||||
{
|
||||
foreach ($order->products as $product) {
|
||||
$userProduct = $order->user->dealerProducts()->firstOrCreate([
|
||||
'product_id'=> $product->product_id,
|
||||
]);
|
||||
$userProduct->increment('stock', $product->qty);
|
||||
|
||||
DealerUserProductLog::create([
|
||||
'user_id'=> $order->user_id,
|
||||
'product_id'=> $product->product_id,
|
||||
'type' => DealerUserProductLog::TYPE_ORDER_IN,
|
||||
'qty'=>$product->qty,
|
||||
'remark'=>'订单:'.$order->sn,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户通过订单扣减库存
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function orderOutQty(DealerOrder $order)
|
||||
{
|
||||
foreach ($order->products as $product) {
|
||||
$userProduct = $order->consignor->dealerProducts()->firstOrCreate([
|
||||
'product_id'=> $product->product_id,
|
||||
]);
|
||||
$userProduct->decrement('stock', $product->qty);
|
||||
|
||||
DealerUserProductLog::create([
|
||||
'user_id'=> $order->consignor_id,
|
||||
'product_id'=> $product->product_id,
|
||||
'type' => DealerUserProductLog::TYPE_ORDER_OUT,
|
||||
'qty'=>$product->qty,
|
||||
'remark' =>'订单:'.$order->sn,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public function getConsignor(User $user, $totalAmount, ?User $lastConsignor = null)
|
||||
{
|
||||
//todo-改成配置
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddRemarkToDealerUserProductLogsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('dealer_user_product_logs', function (Blueprint $table) {
|
||||
//
|
||||
$table->string('remark')->nullable()->comment('备注');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('dealer_user_product_logs', function (Blueprint $table) {
|
||||
//
|
||||
$table->dropColumn('remark');
|
||||
});
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue