pre
parent
ca9b805cb6
commit
3005f25e1d
|
|
@ -58,7 +58,8 @@ class StockController extends Controller
|
||||||
'amount' => $product->pivot->amount + $amount
|
'amount' => $product->pivot->amount + $amount
|
||||||
]);
|
]);
|
||||||
$store->stockLogs()->create([
|
$store->stockLogs()->create([
|
||||||
'administrator_id' => $administrator->id,
|
'operator_type' => get_class($administrator),
|
||||||
|
'operator_id' => $administrator->id,
|
||||||
'amount' => $request->input('amount'),
|
'amount' => $request->input('amount'),
|
||||||
'product_sku_id' => $product->id,
|
'product_sku_id' => $product->id,
|
||||||
'remarks' => $request->input('remarks'),
|
'remarks' => $request->input('remarks'),
|
||||||
|
|
|
||||||
|
|
@ -182,7 +182,7 @@ class StoreController extends AdminController
|
||||||
|
|
||||||
protected function gridStock($id)
|
protected function gridStock($id)
|
||||||
{
|
{
|
||||||
$grid = new Grid(StockLog::with(['productSku', 'administrator', 'source', 'tag']));
|
$grid = new Grid(StockLog::with(['productSku', 'operator', 'source', 'tag']));
|
||||||
|
|
||||||
$grid->model()->where('store_id', $id)->orderBy('created_at', 'desc');
|
$grid->model()->where('store_id', $id)->orderBy('created_at', 'desc');
|
||||||
|
|
||||||
|
|
@ -191,7 +191,15 @@ class StoreController extends AdminController
|
||||||
$grid->column('productSku.name', '商品');
|
$grid->column('productSku.name', '商品');
|
||||||
$grid->column('amount', '库存');
|
$grid->column('amount', '库存');
|
||||||
$grid->column('tag.name', '类目');
|
$grid->column('tag.name', '类目');
|
||||||
$grid->column('administrator.name', '操作人');
|
$grid->column('operator', '操作人')->display(function ($v) {
|
||||||
|
if ($v instanceof \App\Models\Admin\Administrator) {
|
||||||
|
return $v->name . '<span class="label bg-danger">管理员</span>';
|
||||||
|
} else if ($v instanceof \App\Models\User) {
|
||||||
|
return $v->phone . '<span class="label bg-primary">用户</span>';
|
||||||
|
}
|
||||||
|
|
||||||
|
return '未知身份';
|
||||||
|
});
|
||||||
$grid->column('remarks', '备注');
|
$grid->column('remarks', '备注');
|
||||||
$grid->column('created_at', '操作时间');
|
$grid->column('created_at', '操作时间');
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,13 @@ namespace App\Admin\Forms;
|
||||||
|
|
||||||
use App\Admin\Services\OrderPackageService;
|
use App\Admin\Services\OrderPackageService;
|
||||||
use App\Exceptions\BizException;
|
use App\Exceptions\BizException;
|
||||||
use App\Models\Order;
|
use App\Models\{Order, Tag};
|
||||||
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 Illuminate\Support\Facades\DB;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
|
use Dcat\Admin\Admin;
|
||||||
|
|
||||||
class OrderPackage extends Form implements LazyRenderable
|
class OrderPackage extends Form implements LazyRenderable
|
||||||
{
|
{
|
||||||
|
|
@ -43,6 +44,39 @@ class OrderPackage extends Form implements LazyRenderable
|
||||||
DB::beginTransaction();
|
DB::beginTransaction();
|
||||||
$orderPackageService = new OrderPackageService();
|
$orderPackageService = new OrderPackageService();
|
||||||
$orderPackageService->createPackage($order, $input);
|
$orderPackageService->createPackage($order, $input);
|
||||||
|
// 店铺发货, 添加出库记录
|
||||||
|
if ($order->store) {
|
||||||
|
$packageProducts = $input['packages'];
|
||||||
|
$operator = Admin::user();
|
||||||
|
$store = $order->store;
|
||||||
|
$tag = Tag::firstOrCreate([
|
||||||
|
'type' => Tag::TYPE_STORE_STOCK,
|
||||||
|
'name' => '发货'
|
||||||
|
]);
|
||||||
|
foreach($packageProducts as $item) {
|
||||||
|
$order_product = $order->products()->findOrFail($item['order_product_id']);
|
||||||
|
$amount = $item['quantity'];
|
||||||
|
$sku_id = $order_product->sku_id;
|
||||||
|
$product = $store->productSkus()->findOrFail($sku_id);
|
||||||
|
if ($product->pivot->amount - $amount < 0) {
|
||||||
|
throw new BizException('店铺的 ' . $product->name .' 库存不足');
|
||||||
|
}
|
||||||
|
|
||||||
|
$store->productSkus()->updateExistingPivot($product->id, [
|
||||||
|
'amount' => $product->pivot->amount - $amount
|
||||||
|
]);
|
||||||
|
$store->stockLogs()->create([
|
||||||
|
'operator_type' => get_class($operator),
|
||||||
|
'operator_id' => $operator->id,
|
||||||
|
'source_type' => Order::class,
|
||||||
|
'source_id' => $order->id,
|
||||||
|
'amount' => $amount,
|
||||||
|
'product_sku_id' => $product->id,
|
||||||
|
'remarks' => '后台发货',
|
||||||
|
'tag_id' => $tag->id
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
DB::commit();
|
DB::commit();
|
||||||
} catch (BizException $e) {
|
} catch (BizException $e) {
|
||||||
DB::rollBack();
|
DB::rollBack();
|
||||||
|
|
|
||||||
|
|
@ -6,14 +6,19 @@ use App\Exceptions\BizException;
|
||||||
use App\Models\Order;
|
use App\Models\Order;
|
||||||
use App\Models\OrderPackage;
|
use App\Models\OrderPackage;
|
||||||
use App\Models\OrderPackageProduct;
|
use App\Models\OrderPackageProduct;
|
||||||
use App\Models\OrderProduct;
|
use App\Models\{OrderProduct, Tag};
|
||||||
use App\Services\Kuaidi100Service;
|
use App\Services\Kuaidi100Service;
|
||||||
use Illuminate\Support\Arr;
|
use Illuminate\Support\Arr;
|
||||||
|
use Dcat\Admin\Admin;
|
||||||
|
|
||||||
class OrderPackageService
|
class OrderPackageService
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* 创建订单发货单
|
* 创建订单发货单
|
||||||
|
*
|
||||||
|
* @param Order $order
|
||||||
|
* @param array $params {shipping_company, shipping_number, packages => {order_product_id, quantity}}
|
||||||
|
* @param OrderPackage $package
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -104,26 +104,10 @@ class OrderPreController extends Controller
|
||||||
$order_pre = OrderPre::findOrFail($id);
|
$order_pre = OrderPre::findOrFail($id);
|
||||||
$user = $request->user();
|
$user = $request->user();
|
||||||
|
|
||||||
$products = [];
|
|
||||||
foreach($order_pre->products as $item) {
|
|
||||||
array_push($products, [
|
|
||||||
'sku' => ProductSku::findOrFail($item['sku_id']),
|
|
||||||
'quantity' => $item['quantity']
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
$coupon_id = data_get($order_pre, 'others.coupon_id');
|
|
||||||
$note = data_get($order_pre, 'others.note');
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
DB::beginTransaction();
|
DB::beginTransaction();
|
||||||
$service = new OrderService();
|
$service = new OrderService();
|
||||||
$order = $service->createOrder($user, $products, null, $coupon_id, $note);
|
$order = $service->createOrderByPre($user, $order_pre);
|
||||||
$order->update([
|
|
||||||
'store_id' => $order_pre->store_id,
|
|
||||||
'inviter_id' => $order_pre->user_id,
|
|
||||||
'source_type' => OrderPre::class,
|
|
||||||
'source_id' => $order_pre->id,
|
|
||||||
]);
|
|
||||||
|
|
||||||
DB::commit();
|
DB::commit();
|
||||||
return response()->json([
|
return response()->json([
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ namespace App\Endpoint\Api\Http\Controllers\Order;
|
||||||
|
|
||||||
use App\Endpoint\Api\Http\Controllers\Controller;
|
use App\Endpoint\Api\Http\Controllers\Controller;
|
||||||
use App\Helpers\Paginator;
|
use App\Helpers\Paginator;
|
||||||
use App\Models\{Order, OrderPre};
|
use App\Models\{Order, OrderPre, Tag};
|
||||||
use App\Endpoint\Api\Http\Resources\{OrderResource, OrderResourceCollection};
|
use App\Endpoint\Api\Http\Resources\{OrderResource, OrderResourceCollection};
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
@ -53,11 +53,16 @@ class UnlineController extends Controller
|
||||||
'products.required' => '发货商品必填',
|
'products.required' => '发货商品必填',
|
||||||
]);
|
]);
|
||||||
$order = Order::where('source_type', OrderPre::class)->findOrFail($id);
|
$order = Order::where('source_type', OrderPre::class)->findOrFail($id);
|
||||||
|
$store = $order->store;
|
||||||
|
|
||||||
// 订单来源为 帮客户下单 order_pres
|
// 订单来源为 帮客户下单 order_pres
|
||||||
try {
|
try {
|
||||||
DB::beginTransaction();
|
DB::beginTransaction();
|
||||||
$order_products = $order->products;
|
$order_products = $order->products;
|
||||||
|
$tag = Tag::firstOrCreate([
|
||||||
|
'type' => Tag::TYPE_STORE_STOCK,
|
||||||
|
'name' => '提货'
|
||||||
|
]);
|
||||||
// 根据 order_pres 发货数量, 自动发货
|
// 根据 order_pres 发货数量, 自动发货
|
||||||
$service_package = new \App\Admin\Services\OrderPackageService();
|
$service_package = new \App\Admin\Services\OrderPackageService();
|
||||||
// order_product_id: 订单商品ID, quantity: 发货数量
|
// order_product_id: 订单商品ID, quantity: 发货数量
|
||||||
|
|
@ -69,6 +74,27 @@ class UnlineController extends Controller
|
||||||
'order_product_id' => $order_product->id,
|
'order_product_id' => $order_product->id,
|
||||||
'quantity' => $item['amount'],
|
'quantity' => $item['amount'],
|
||||||
]);
|
]);
|
||||||
|
// 添加出库记录
|
||||||
|
$amount = $item['amount'];
|
||||||
|
$sku_id = $order_product->sku_id;
|
||||||
|
$product = $store->productSkus()->findOrFail($sku_id);
|
||||||
|
if ($product->pivot->amount - $amount < 0) {
|
||||||
|
throw new BizException('店铺的 ' . $product->name .' 库存不足');
|
||||||
|
}
|
||||||
|
|
||||||
|
$store->productSkus()->updateExistingPivot($product->id, [
|
||||||
|
'amount' => $product->pivot->amount - $amount
|
||||||
|
]);
|
||||||
|
$store->stockLogs()->create([
|
||||||
|
'operator_type' => get_class($user),
|
||||||
|
'operator_id' => $user->id,
|
||||||
|
'source_type' => Order::class,
|
||||||
|
'source_id' => $order->id,
|
||||||
|
'amount' => $amount,
|
||||||
|
'product_sku_id' => $product->id,
|
||||||
|
'remarks' => '店铺提货',
|
||||||
|
'tag_id' => $tag->id
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 发货
|
// 发货
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ use App\Enums\PayWay;
|
||||||
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;
|
||||||
|
use App\Models\Store\Store;
|
||||||
|
|
||||||
class Order extends Model
|
class Order extends Model
|
||||||
{
|
{
|
||||||
|
|
@ -141,6 +142,14 @@ class Order extends Model
|
||||||
return $this->belongsTo(UserInfo::class, 'user_id', 'user_id');
|
return $this->belongsTo(UserInfo::class, 'user_id', 'user_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 门店
|
||||||
|
*/
|
||||||
|
public function store()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Store::class, 'store_id');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 使用的优惠券
|
* 使用的优惠券
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,6 @@ class Administrator extends Model
|
||||||
|
|
||||||
public function administrator()
|
public function administrator()
|
||||||
{
|
{
|
||||||
return $this->belongsTo(\Dcat\Admin\Models\Administrator::class, 'administrator_id');
|
return $this->belongsTo(\App\Models\Admin\Administrator::class, 'administrator_id');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ class StockLog extends Model
|
||||||
|
|
||||||
protected $table = 'store_stock_logs';
|
protected $table = 'store_stock_logs';
|
||||||
|
|
||||||
protected $fillable = ['administrator_id', 'amount', 'product_sku_id', 'remarks', 'source_id', 'source_type', 'store_id', 'tag_id'];
|
protected $fillable = ['operator_type', 'operator_id', 'amount', 'product_sku_id', 'remarks', 'source_id', 'source_type', 'store_id', 'tag_id'];
|
||||||
|
|
||||||
public function store()
|
public function store()
|
||||||
{
|
{
|
||||||
|
|
@ -24,9 +24,9 @@ class StockLog extends Model
|
||||||
return $this->belongsTo(\App\Models\ProductSku::class, 'product_sku_id');
|
return $this->belongsTo(\App\Models\ProductSku::class, 'product_sku_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function administrator()
|
public function operator()
|
||||||
{
|
{
|
||||||
return $this->belongsTo(\Dcat\Admin\Models\Administrator::class, 'administrator_id');
|
return $this->morphTo();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function source()
|
public function source()
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,8 @@ use App\Models\ProductPartSku;
|
||||||
use App\Models\ProductSku;
|
use App\Models\ProductSku;
|
||||||
use App\Models\ShippingAddress;
|
use App\Models\ShippingAddress;
|
||||||
use App\Models\SocialiteUser;
|
use App\Models\SocialiteUser;
|
||||||
use App\Models\User;
|
use App\Models\{User, OrderPre, Tag};
|
||||||
|
use App\Models\Store\Store;
|
||||||
use App\Models\UserCoupon;
|
use App\Models\UserCoupon;
|
||||||
use App\Services\Payment\WxpayService;
|
use App\Services\Payment\WxpayService;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
|
@ -110,13 +111,11 @@ class OrderService
|
||||||
?string $note = null,
|
?string $note = null,
|
||||||
?BargainOrder $bargainOrder = null,
|
?BargainOrder $bargainOrder = null,
|
||||||
): Order {
|
): Order {
|
||||||
if ($shippingAddressId) {
|
foreach ($products as $product) {
|
||||||
foreach ($products as $product) {
|
$sku = $product['sku'];
|
||||||
$sku = $product['sku'];
|
|
||||||
|
if ($product['quantity'] > $sku->saleable_stock) {
|
||||||
if ($product['quantity'] > $sku->saleable_stock) {
|
throw new BizException('商品库存不足');
|
||||||
throw new BizException('商品库存不足');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -168,6 +167,70 @@ class OrderService
|
||||||
return $order;
|
return $order;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加店铺订单
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function createOrderByPre(User $user, OrderPre $order_pre)
|
||||||
|
{
|
||||||
|
$products = [];
|
||||||
|
foreach($order_pre->products as $item) {
|
||||||
|
array_push($products, [
|
||||||
|
'sku' => ProductSku::findOrFail($item['sku_id']),
|
||||||
|
'quantity' => $item['quantity']
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$coupon_id = data_get($order_pre, 'others.coupon_id');
|
||||||
|
$note = data_get($order_pre, 'others.note');
|
||||||
|
|
||||||
|
// 优惠券
|
||||||
|
$coupon = null;
|
||||||
|
|
||||||
|
if ($coupon_id) {
|
||||||
|
$coupon = $user->coupons()->onlyAvailable()->lockForUpdate()->findOrFail($coupon_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
$mapProducts = $this->mapProducts($user, $products, $coupon);
|
||||||
|
|
||||||
|
list(
|
||||||
|
$productsTotalAmount,
|
||||||
|
$vipDiscountAmount,
|
||||||
|
$couponDiscountAmount,
|
||||||
|
$salesValue
|
||||||
|
) = $this->calculateFees($mapProducts);
|
||||||
|
|
||||||
|
$order = $this->storeOrder(
|
||||||
|
$user,
|
||||||
|
$productsTotalAmount,
|
||||||
|
$couponDiscountAmount,
|
||||||
|
$vipDiscountAmount,
|
||||||
|
0,
|
||||||
|
$salesValue,
|
||||||
|
null,
|
||||||
|
$note,
|
||||||
|
$coupon
|
||||||
|
);
|
||||||
|
$order->update([
|
||||||
|
'store_id' => $order_pre->store_id,
|
||||||
|
'inviter_id' => $order_pre->user_id,
|
||||||
|
'source_type' => OrderPre::class,
|
||||||
|
'source_id' => $order_pre->id,
|
||||||
|
]);
|
||||||
|
$this->storeOrderProducts($order, $mapProducts);
|
||||||
|
|
||||||
|
// 将优惠券标记为已使用
|
||||||
|
$coupon?->markAsUse();
|
||||||
|
|
||||||
|
if ($order->total_amount === 0) {
|
||||||
|
$this->pay($order, PayWay::Balance);
|
||||||
|
|
||||||
|
$order->refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $order;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 保存订单
|
* 保存订单
|
||||||
*
|
*
|
||||||
|
|
@ -284,7 +347,9 @@ class OrderService
|
||||||
];
|
];
|
||||||
|
|
||||||
// 扣除商品库存
|
// 扣除商品库存
|
||||||
$this->deductProduct($sku, $qty);
|
if (!$order->store_id) {
|
||||||
|
$this->deductProduct($sku, $qty);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//根据订单参加的活动添加赠品;
|
//根据订单参加的活动添加赠品;
|
||||||
$gifts = $this->activityGifts($order, $orderProducts);
|
$gifts = $this->activityGifts($order, $orderProducts);
|
||||||
|
|
@ -323,6 +388,30 @@ class OrderService
|
||||||
// } while (true);
|
// } while (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从门店中扣除商品库存
|
||||||
|
*/
|
||||||
|
protected function deductProductFromStore(Store $store, ProductSku $sku, int $amount)
|
||||||
|
{
|
||||||
|
$sku = $store->productSkus()->findOrFail($sku->id);
|
||||||
|
|
||||||
|
// 添加出库记录
|
||||||
|
$tag = Tag::firstOrCreate([
|
||||||
|
'type' => Tag::TYPE_STORE_STOCK,
|
||||||
|
'name' => '下单出库'
|
||||||
|
]);
|
||||||
|
$store->stockLogs()->create([
|
||||||
|
'amount' => 0-$amount,
|
||||||
|
'product_sku_id' => $sku->id,
|
||||||
|
'remarks' => '购买',
|
||||||
|
'tag_id' => $tag->id
|
||||||
|
]);
|
||||||
|
|
||||||
|
$store->productSkus()->updateExistingPivot($sku->id, [
|
||||||
|
'amount' => $sku->pivot->amount - $amount
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 扣出商品的赠品
|
* 扣出商品的赠品
|
||||||
*
|
*
|
||||||
|
|
@ -691,7 +780,7 @@ class OrderService
|
||||||
* 准备商品信息
|
* 准备商品信息
|
||||||
*
|
*
|
||||||
* @param \App\Models\User $user
|
* @param \App\Models\User $user
|
||||||
* @param array $products
|
* @param array $products {sku: App\Models\ProductSku, quantity: 数量}
|
||||||
* @param \App\Models\UserCoupon|null $coupon
|
* @param \App\Models\UserCoupon|null $coupon
|
||||||
* @return array
|
* @return array
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ class CreateStoresTable extends Migration
|
||||||
$table->unsignedBigInteger('product_sku_id');
|
$table->unsignedBigInteger('product_sku_id');
|
||||||
$table->integer('amount')->comment('库存变更数量(正/负值)');
|
$table->integer('amount')->comment('库存变更数量(正/负值)');
|
||||||
$table->unsignedBigInteger('tag_id')->comment('变更类目(tags.id)');
|
$table->unsignedBigInteger('tag_id')->comment('变更类目(tags.id)');
|
||||||
$table->unsignedBigInteger('administrator_id')->nullable()->comment('操作管理员');
|
$table->nullableMorphs('operator');
|
||||||
$table->string('remarks')->nullable()->comment('备注');
|
$table->string('remarks')->nullable()->comment('备注');
|
||||||
$table->string('source_type')->nullable()->comment('来源');
|
$table->string('source_type')->nullable()->comment('来源');
|
||||||
$table->unsignedBigInteger('source_id')->nullable()->comment('来源');
|
$table->unsignedBigInteger('source_id')->nullable()->comment('来源');
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue