order-ship
parent
aa923701d8
commit
165a2228e1
|
|
@ -12,6 +12,9 @@
|
||||||
"email": "1163816051@qq.com"
|
"email": "1163816051@qq.com"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"require": {
|
||||||
|
"overtrue/laravel-wechat": "^7.0"
|
||||||
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"Peidikeji\\Order\\": "src/"
|
"Peidikeji\\Order\\": "src/"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::create('order_ships', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->unsignedBigInteger('order_id')->comment('订单ID, orders.id');
|
||||||
|
$table->string('sn')->nullable()->comment('发货单流水号');
|
||||||
|
|
||||||
|
$table->unsignedInteger('ship_status')->default(0);
|
||||||
|
$table->json('ship_data')->nullable()->comment('物流信息');
|
||||||
|
$table->json('ship_address')->nullable()->comment('配送地址');
|
||||||
|
$table->dateTime('finish_at')->nullable()->comment('收货时间');
|
||||||
|
|
||||||
|
$table->timestamps();
|
||||||
|
|
||||||
|
$table->comment('订单-发货记录');
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::create('order_ship_goods', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->unsignedBigInteger('ship_id')->comment('发货记录ID');
|
||||||
|
$table->unsignedBigInteger('order_goods_id')->comment('订单商品ID');
|
||||||
|
$table->string('goods_name')->nullable()->comment('商品名称');
|
||||||
|
$table->string('cover_image')->nullable()->comment('商品图片');
|
||||||
|
$table->unsignedInteger('amount')->comment('发货数量');
|
||||||
|
|
||||||
|
$table->comment('订单-发货商品');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('order_ship_goods');
|
||||||
|
Schema::dropIfExists('order_ships');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Peidikeji\Order\Action;
|
|
||||||
|
|
||||||
use Dcat\Admin\Show\AbstractTool;
|
|
||||||
use Peidikeji\Order\Enums\OrderScene;
|
|
||||||
use Peidikeji\Order\Models\Order;
|
|
||||||
|
|
||||||
class ShowShipQrcode extends AbstractTool
|
|
||||||
{
|
|
||||||
protected $style = 'btn btn-sm btn-primary';
|
|
||||||
|
|
||||||
protected $title = '生成提货码';
|
|
||||||
|
|
||||||
public function handle()
|
|
||||||
{
|
|
||||||
$id = $this->getKey();
|
|
||||||
$order = Order::findOrFail($id);
|
|
||||||
$url = $order->generateShipQrcode();
|
|
||||||
if (!$url) {
|
|
||||||
return $this->response()->error('生成提货码失败');
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->response()->success('操作成功')->refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function allowed()
|
|
||||||
{
|
|
||||||
$model = $this->parent->model();
|
|
||||||
$code = data_get($model, 'extra.ship_qrcode');
|
|
||||||
return $model->scene === OrderScene::Merchant && !$code;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -4,11 +4,9 @@ namespace Peidikeji\Order\Console;
|
||||||
|
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Peidikeji\Order\Enums\PayStatus;
|
|
||||||
use Peidikeji\Order\Enums\ShipStatus;
|
use Peidikeji\Order\Enums\ShipStatus;
|
||||||
use Peidikeji\Order\Models\Order;
|
use Peidikeji\Order\Models\Order;
|
||||||
use Peidikeji\Order\OrderService;
|
use Peidikeji\Order\OrderService;
|
||||||
use Peidikeji\Setting\Models\Setting;
|
|
||||||
|
|
||||||
class OrdeReceive extends Command
|
class OrdeReceive extends Command
|
||||||
{
|
{
|
||||||
|
|
@ -27,10 +25,9 @@ class OrdeReceive extends Command
|
||||||
if ($id) {
|
if ($id) {
|
||||||
$this->receive(Order::findOrFail($id));
|
$this->receive(Order::findOrFail($id));
|
||||||
} else {
|
} else {
|
||||||
$day = Setting::where('slug', 'order_receive_day')->value('value');
|
|
||||||
$query = Order::where('ship_status', ShipStatus::Finished)
|
$query = Order::where('ship_status', ShipStatus::Finished)
|
||||||
->where('is_closed', 0)
|
->where('is_closed', 0)
|
||||||
->where('ship_at', '<', now()->subDays($day));
|
->where('ship_at', '<', now()->subDays(7));
|
||||||
$list = $query->get();
|
$list = $query->get();
|
||||||
foreach($list as $item) {
|
foreach($list as $item) {
|
||||||
$this->receive($item);
|
$this->receive($item);
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,7 @@ class OrderCancel extends Command
|
||||||
if ($id) {
|
if ($id) {
|
||||||
$this->cancel(Order::findOrFail($id));
|
$this->cancel(Order::findOrFail($id));
|
||||||
} else {
|
} else {
|
||||||
$hour = Setting::where('slug', 'order_cancel_hour')->value('value');
|
$query = Order::where('pay_status', PayStatus::None)->where('is_closed', 0)->where('created_at', '<', now()->subMinutes(15));
|
||||||
$query = Order::where('pay_status', PayStatus::None)->where('is_closed', 0)->where('created_at', '<', now()->subHours($hour));
|
|
||||||
$list = $query->get();
|
$list = $query->get();
|
||||||
foreach($list as $item) {
|
foreach($list as $item) {
|
||||||
$this->cancel($item);
|
$this->cancel($item);
|
||||||
|
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Peidikeji\Order\Enums;
|
|
||||||
|
|
||||||
enum OrderScene: int
|
|
||||||
{
|
|
||||||
case Online = 0;
|
|
||||||
case Merchant = 1;
|
|
||||||
case Scan = 2;
|
|
||||||
|
|
||||||
public static function options()
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
self::Online->value => '线上商城',
|
|
||||||
self::Merchant->value => '线下门店',
|
|
||||||
self::Scan->value => '扫码付款',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function text()
|
|
||||||
{
|
|
||||||
return data_get(self::options(), $this->value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function color()
|
|
||||||
{
|
|
||||||
return match ($this) {
|
|
||||||
static::Online => 'primary',
|
|
||||||
static::Merchant => 'warning',
|
|
||||||
static::Scan => 'success',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public function label()
|
|
||||||
{
|
|
||||||
$color = $this->color();
|
|
||||||
|
|
||||||
$name = $this->text();
|
|
||||||
|
|
||||||
return "<span class='label bg-${color}'>{$name}</span>";
|
|
||||||
}
|
|
||||||
|
|
||||||
public function dot()
|
|
||||||
{
|
|
||||||
$color = $this->color();
|
|
||||||
|
|
||||||
$name = $this->text();
|
|
||||||
|
|
||||||
return "<i class='fa fa-circle text-$color'> {$name}</span>";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -25,7 +25,7 @@ enum OrderStatus: int
|
||||||
self::Send->value => '已发货(部分)',
|
self::Send->value => '已发货(部分)',
|
||||||
// 全部发货
|
// 全部发货
|
||||||
self::SendFull->value => '已发货',
|
self::SendFull->value => '已发货',
|
||||||
self::Receive->value => '已完成',
|
self::Receive->value => '已收货',
|
||||||
// 已评价
|
// 已评价
|
||||||
self::Review->value => '已评价',
|
self::Review->value => '已评价',
|
||||||
|
|
||||||
|
|
@ -55,9 +55,9 @@ enum OrderStatus: int
|
||||||
self::Paying => 'secondary',
|
self::Paying => 'secondary',
|
||||||
self::Paid => 'success',
|
self::Paid => 'success',
|
||||||
self::Send => 'primary',
|
self::Send => 'primary',
|
||||||
self::SendFull => 'primary',
|
self::SendFull => 'danger',
|
||||||
self::Receive => 'primary',
|
self::Receive => 'success',
|
||||||
self::Review => 'success',
|
self::Review => 'primary',
|
||||||
self::PayFail => 'danger',
|
self::PayFail => 'danger',
|
||||||
self::Cancel => 'secondary',
|
self::Cancel => 'secondary',
|
||||||
default => 'dark'
|
default => 'dark'
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ enum PayStatus: int
|
||||||
public function color()
|
public function color()
|
||||||
{
|
{
|
||||||
return match ($this) {
|
return match ($this) {
|
||||||
static::None => 'secondary',
|
static::None => 'dark',
|
||||||
static::Processing => 'primary',
|
static::Processing => 'primary',
|
||||||
self::Success => 'success',
|
self::Success => 'success',
|
||||||
self::Fail => 'danger',
|
self::Fail => 'danger',
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,22 @@
|
||||||
|
|
||||||
namespace Peidikeji\Order\Exceptions;
|
namespace Peidikeji\Order\Exceptions;
|
||||||
|
|
||||||
use App\Exceptions\BizException;
|
use Dcat\Admin\Traits\JsonResponse;
|
||||||
|
use Exception;
|
||||||
|
|
||||||
class OrderException extends BizException
|
class OrderException extends Exception
|
||||||
{
|
{
|
||||||
public function __construct(string $message, int $code = 400)
|
use JsonResponse;
|
||||||
|
|
||||||
|
protected $code = 400;
|
||||||
|
|
||||||
|
public function report()
|
||||||
{
|
{
|
||||||
parent::__construct($message, $code);
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render($request)
|
||||||
|
{
|
||||||
|
return $this->error($this->message, $this->code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ class PayForm extends Form implements LazyRenderable
|
||||||
$order = Order::findOrFail($id);
|
$order = Order::findOrFail($id);
|
||||||
// 验证积分余额是否足够
|
// 验证积分余额是否足够
|
||||||
if ($order->score_discount_amount > 0 && $order->user) {
|
if ($order->score_discount_amount > 0 && $order->user) {
|
||||||
if ($order->user->profit < $order->score_discount_amount) {
|
if ($order->user->balance < $order->score_discount_amount) {
|
||||||
throw new OrderException('用户积分余额不足');
|
throw new OrderException('用户积分余额不足');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,9 +31,10 @@ class ShipForm extends Form implements LazyRenderable
|
||||||
}
|
}
|
||||||
DB::beginTransaction();
|
DB::beginTransaction();
|
||||||
$order = Order::findOrFail($this->payload['id']);
|
$order = Order::findOrFail($this->payload['id']);
|
||||||
$code = $input['company_code'];
|
|
||||||
$company = data_get(array_flip(Kuaidi100Service::$codeArr), $code, '未知');
|
$code = data_get($input, 'company_code');
|
||||||
$sn = $input['sn'];
|
$company = data_get($input, 'company');
|
||||||
|
$sn = data_get($input, 'sn');
|
||||||
OrderService::make()->ship($order, $input['goods'], compact('code', 'company', 'sn'));
|
OrderService::make()->ship($order, $input['goods'], compact('code', 'company', 'sn'));
|
||||||
|
|
||||||
$admin = Admin::user();
|
$admin = Admin::user();
|
||||||
|
|
@ -69,12 +70,9 @@ class ShipForm extends Form implements LazyRenderable
|
||||||
}
|
}
|
||||||
$this->fill(['goods' => $goods]);
|
$this->fill(['goods' => $goods]);
|
||||||
|
|
||||||
$way = $this->payload['ship_way'];
|
$this->text('company', '快递公司');
|
||||||
|
$this->text('company_code', '快递公司编码');
|
||||||
if ($way === ShipWay::Express->value) {
|
$this->text('sn', '快递单号');
|
||||||
$this->select('company_code', '快递公司')->options(array_flip(Kuaidi100Service::$codeArr));
|
|
||||||
$this->text('sn', '快递单号')->required();
|
|
||||||
}
|
|
||||||
$this->table('goods', '', function (NestedForm $table) {
|
$this->table('goods', '', function (NestedForm $table) {
|
||||||
$spec = data_get($table->model(), 'goods.spec');
|
$spec = data_get($table->model(), 'goods.spec');
|
||||||
$table->hidden('order_goods_id');
|
$table->hidden('order_goods_id');
|
||||||
|
|
@ -97,9 +95,7 @@ class ShipForm extends Form implements LazyRenderable
|
||||||
}
|
}
|
||||||
$table->display('total_amount', '总数量');
|
$table->display('total_amount', '总数量');
|
||||||
$table->display('ship_amount', '已发');
|
$table->display('ship_amount', '已发');
|
||||||
$table->number('amount', '数量')->default(1)->min(1)->options(['upClass' => null, 'downClass' => null]);
|
$table->number('amount', '数量')->default(1)->min(0)->prepend('')->append('');
|
||||||
})->horizontal(false)->setFieldClass('col-12')->options([
|
})->horizontal(false)->setFieldClass('col-12')->options(['allowCreate' => false])->required();
|
||||||
'allowCreate' => false,
|
|
||||||
])->required();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@ use Dcat\Admin\Show;
|
||||||
use Dcat\Admin\Show\Tools;
|
use Dcat\Admin\Show\Tools;
|
||||||
use Dcat\Admin\Widgets\Box;
|
use Dcat\Admin\Widgets\Box;
|
||||||
use Illuminate\Support\Arr;
|
use Illuminate\Support\Arr;
|
||||||
use Peidikeji\Merchant\Models\Merchant;
|
|
||||||
use Peidikeji\Order\Action\ShowCancel;
|
use Peidikeji\Order\Action\ShowCancel;
|
||||||
use Peidikeji\Order\Action\ShowDelete;
|
use Peidikeji\Order\Action\ShowDelete;
|
||||||
use Peidikeji\Order\Action\ShowPay;
|
use Peidikeji\Order\Action\ShowPay;
|
||||||
|
|
@ -23,7 +22,6 @@ use Peidikeji\Order\Action\ShowPayQuery;
|
||||||
use Peidikeji\Order\Action\ShowReceive;
|
use Peidikeji\Order\Action\ShowReceive;
|
||||||
use Peidikeji\Order\Action\ShowRemarks;
|
use Peidikeji\Order\Action\ShowRemarks;
|
||||||
use Peidikeji\Order\Action\ShowShip;
|
use Peidikeji\Order\Action\ShowShip;
|
||||||
use Peidikeji\Order\Action\ShowShipQrcode;
|
|
||||||
use Peidikeji\Order\Enums\OrderStatus;
|
use Peidikeji\Order\Enums\OrderStatus;
|
||||||
use Peidikeji\Order\Enums\PayStatus;
|
use Peidikeji\Order\Enums\PayStatus;
|
||||||
use Peidikeji\Order\Models\Order;
|
use Peidikeji\Order\Models\Order;
|
||||||
|
|
@ -39,13 +37,13 @@ class OrderController extends AdminController
|
||||||
|
|
||||||
protected function grid()
|
protected function grid()
|
||||||
{
|
{
|
||||||
return Grid::make(Order::with(['user', 'merchant']), function (Grid $grid) {
|
return Grid::make(Order::with(['user']), function (Grid $grid) {
|
||||||
|
$grid->disableRowSelector();
|
||||||
$grid->model()->sort();
|
$grid->model()->sort();
|
||||||
|
|
||||||
$grid->filter(function (Filter $filter) {
|
$grid->filter(function (Filter $filter) {
|
||||||
$filter->panel();
|
$filter->panel();
|
||||||
$filter->like('sn')->width(4);
|
$filter->like('sn')->width(4);
|
||||||
$filter->equal('merchant_id')->select()->ajax('api/merchants?_paginate=1')->model(Merchant::class, 'id', 'name')->width(4);
|
|
||||||
$filter->equal('user_id')->select()->ajax('api/user?_paginate=1')->model(User::class, 'id', 'phone')->width(4);
|
$filter->equal('user_id')->select()->ajax('api/user?_paginate=1')->model(User::class, 'id', 'phone')->width(4);
|
||||||
$filter->where('order_status', fn($q) => $q->filter(['status' => $this->input]))->select(OrderStatus::options())->width(4);
|
$filter->where('order_status', fn($q) => $q->filter(['status' => $this->input]))->select(OrderStatus::options())->width(4);
|
||||||
$filter->whereBetween('created_at', function ($q) {
|
$filter->whereBetween('created_at', function ($q) {
|
||||||
|
|
@ -64,8 +62,7 @@ class OrderController extends AdminController
|
||||||
})->date()->width(4);
|
})->date()->width(4);
|
||||||
});
|
});
|
||||||
|
|
||||||
$grid->column('scene')->display(fn() => $this->scene->label());
|
$grid->column('sn')->copyable();
|
||||||
$grid->column('sn')->link(fn() => admin_url('orders', ['id' => $this->id]));
|
|
||||||
$grid->column('merchant.name');
|
$grid->column('merchant.name');
|
||||||
$grid->column('user.phone');
|
$grid->column('user.phone');
|
||||||
$grid->column('total_money');
|
$grid->column('total_money');
|
||||||
|
|
@ -75,19 +72,22 @@ class OrderController extends AdminController
|
||||||
$user = Admin::user();
|
$user = Admin::user();
|
||||||
|
|
||||||
$grid->showViewButton($user->can('dcat.admin.orders.show'));
|
$grid->showViewButton($user->can('dcat.admin.orders.show'));
|
||||||
|
$grid->disableCreateButton();
|
||||||
|
$grid->disableEditButton();
|
||||||
|
$grid->disableDeleteButton();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function detail($id)
|
protected function detail($id)
|
||||||
{
|
{
|
||||||
$info = Order::with(['user', 'merchant'])->findOrFail($id);
|
$info = Order::with(['user'])->findOrFail($id);
|
||||||
$row = new Row();
|
$row = new Row();
|
||||||
$row->column(6, Show::make($info, function (Show $show) {
|
$row->column(6, Show::make($info, function (Show $show) {
|
||||||
|
$show->disableEditButton();
|
||||||
|
$show->disableDeleteButton();
|
||||||
$info = $show->model();
|
$info = $show->model();
|
||||||
$show->row(function (Show\Row $show) {
|
$show->row(function (Show\Row $show) {
|
||||||
$show->width(6)->field('scene')->as(fn() => $this->scene->label())->unescape();
|
|
||||||
$show->width(6)->field('user.phone');
|
$show->width(6)->field('user.phone');
|
||||||
$show->width(6)->field('merchant.name');
|
|
||||||
$show->width(6)->field('sn');
|
$show->width(6)->field('sn');
|
||||||
$show->width(6)->field('status', '状态')->as(fn() => $this->status()->label())->unescape();
|
$show->width(6)->field('status', '状态')->as(fn() => $this->status()->label())->unescape();
|
||||||
$show->width(6)->field('created_at');
|
$show->width(6)->field('created_at');
|
||||||
|
|
@ -99,27 +99,25 @@ class OrderController extends AdminController
|
||||||
$show->row(function (Show\Row $show) {
|
$show->row(function (Show\Row $show) {
|
||||||
$show->width(6)->field('score_discount_money');
|
$show->width(6)->field('score_discount_money');
|
||||||
$show->width(6)->field('score_discount_amount');
|
$show->width(6)->field('score_discount_amount');
|
||||||
$show->width(6)->field('score_discount_ratio');
|
// $show->width(6)->field('score_discount_ratio');
|
||||||
$show->width(6)->field('vip_discount_money');
|
|
||||||
});
|
});
|
||||||
$show->row(function (Show\Row $show) use ($info) {
|
$show->row(function (Show\Row $show) use ($info) {
|
||||||
$show->width(6)->field('pay_money');
|
// $show->width(6)->field('pay_status')->as(fn() => $this->pay_status->label())->unescape();
|
||||||
$show->width(6)->field('pay_status')->as(fn() => $this->pay_status->label())->unescape();
|
|
||||||
$show->width(6)->field('pay_way')->as(fn() => $this->pay_way?->label())->unescape();
|
$show->width(6)->field('pay_way')->as(fn() => $this->pay_way?->label())->unescape();
|
||||||
|
$show->width(6)->field('pay_money');
|
||||||
if ($info->pay_status === PayStatus::Success) {
|
if ($info->pay_status === PayStatus::Success) {
|
||||||
$show->width(6)->field('pay_at');
|
$show->width(6)->field('pay_at');
|
||||||
$show->width(6)->field('pay_no');
|
$show->width(6)->field('pay_no');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
$show->row(function (Show\Row $show) use ($info) {
|
$show->row(function (Show\Row $show) use ($info) {
|
||||||
$show->width(6)->field('ship_status')->as(fn() => $this->ship_status->label())->unescape();
|
// $show->width(6)->field('ship_status')->as(fn() => $this->ship_status->label())->unescape();
|
||||||
$show->width(6)->field('ship_money');
|
|
||||||
$show->width(6)->field('ship_address')->as(fn($v) => $v ? implode(',', Arr::only($v, ['name', 'phone', 'address'])) : '');
|
$show->width(6)->field('ship_address')->as(fn($v) => $v ? implode(',', Arr::only($v, ['name', 'phone', 'address'])) : '');
|
||||||
|
$show->width(6)->field('ship_money');
|
||||||
$show->width(6)->field('ship_way')->as(fn() => $this->ship_way?->label())->unescape();
|
$show->width(6)->field('ship_way')->as(fn() => $this->ship_way?->label())->unescape();
|
||||||
$show->width(6)->field('ship_at');
|
$show->width(6)->field('ship_at');
|
||||||
});
|
});
|
||||||
$show->row(function (Show\Row $show) use ($info) {
|
$show->row(function (Show\Row $show) use ($info) {
|
||||||
$show->width(6)->field('user_get_profit');
|
|
||||||
$show->width(6)->field('remarks');
|
$show->width(6)->field('remarks');
|
||||||
});
|
});
|
||||||
$show->tools(function (Tools $tools) {
|
$show->tools(function (Tools $tools) {
|
||||||
|
|
@ -128,14 +126,15 @@ class OrderController extends AdminController
|
||||||
$tools->append(new ShowPayQuery());
|
$tools->append(new ShowPayQuery());
|
||||||
$tools->append(new ShowShip());
|
$tools->append(new ShowShip());
|
||||||
$tools->append(new ShowReceive());
|
$tools->append(new ShowReceive());
|
||||||
$tools->append(new ShowShipQrcode());
|
|
||||||
$tools->append(new ShowDelete());
|
$tools->append(new ShowDelete());
|
||||||
$tools->append(new ShowRemarks());
|
$tools->append(new ShowRemarks());
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
$row->column(6, function (Column $column) use ($info) {
|
$row->column(6, function (Column $column) use ($info) {
|
||||||
$goodsGrid = Grid::make(OrderGoods::where('order_id', $info->id), function (Grid $grid) {
|
$column->row(Box::make('订单商品', Grid::make(OrderGoods::where('order_id', $info->id), function (Grid $grid) {
|
||||||
|
$grid->disableRowSelector();
|
||||||
|
$grid->disableCreateButton();
|
||||||
$grid->disablePagination();
|
$grid->disablePagination();
|
||||||
$grid->disableActions();
|
$grid->disableActions();
|
||||||
$grid->disableRefreshButton();
|
$grid->disableRefreshButton();
|
||||||
|
|
@ -145,9 +144,10 @@ class OrderController extends AdminController
|
||||||
$grid->column('ship_amount', '已发');
|
$grid->column('ship_amount', '已发');
|
||||||
$grid->column('spec', '规格')->display(fn($v) => $v ? array_column($v, 'value') : '')->label();
|
$grid->column('spec', '规格')->display(fn($v) => $v ? array_column($v, 'value') : '')->label();
|
||||||
$grid->column('money', '合计');
|
$grid->column('money', '合计');
|
||||||
});
|
})));
|
||||||
$column->row(Box::make('订单商品', $goodsGrid));
|
|
||||||
$column->row(Box::make('发货单', Grid::make(OrderShip::with(['goods'])->where('order_id', $info->id)->sort(), function (Grid $grid) {
|
$column->row(Box::make('发货单', Grid::make(OrderShip::with(['goods'])->where('order_id', $info->id)->sort(), function (Grid $grid) {
|
||||||
|
$grid->disableRowSelector();
|
||||||
|
$grid->disableCreateButton();
|
||||||
$grid->disablePagination();
|
$grid->disablePagination();
|
||||||
$grid->disableActions();
|
$grid->disableActions();
|
||||||
$grid->disableRefreshButton();
|
$grid->disableRefreshButton();
|
||||||
|
|
@ -176,6 +176,8 @@ class OrderController extends AdminController
|
||||||
})));
|
})));
|
||||||
$column->row(Box::make('操作记录', Grid::make(OrderOption::with(['user'])->where('order_id', $info->id)->orderBy('created_at', 'desc'), function (Grid $grid) {
|
$column->row(Box::make('操作记录', Grid::make(OrderOption::with(['user'])->where('order_id', $info->id)->orderBy('created_at', 'desc'), function (Grid $grid) {
|
||||||
|
|
||||||
|
$grid->disableRowSelector();
|
||||||
|
$grid->disableCreateButton();
|
||||||
$grid->disablePagination();
|
$grid->disablePagination();
|
||||||
$grid->disableActions();
|
$grid->disableActions();
|
||||||
$grid->disableRefreshButton();
|
$grid->disableRefreshButton();
|
||||||
|
|
|
||||||
|
|
@ -2,18 +2,13 @@
|
||||||
|
|
||||||
namespace Peidikeji\Order\Http\Api;
|
namespace Peidikeji\Order\Http\Api;
|
||||||
|
|
||||||
use Peidikeji\Order\Exceptions\OrderException;
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Http\Resources\UserAddressResource;
|
|
||||||
use App\Models\UserAddress;
|
|
||||||
use App\Models\Zone;
|
|
||||||
use App\Services\Kuaidi100Service;
|
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Validation\Rule;
|
use Illuminate\Validation\Rule;
|
||||||
use Illuminate\Validation\Rules\Enum;
|
use Illuminate\Validation\Rules\Enum;
|
||||||
use Peidikeji\Merchant\Models\Merchant;
|
use Peidikeji\Coupon\Http\Resources\UserCouponResource;
|
||||||
use Peidikeji\Order\Enums\OrderScene;
|
use Peidikeji\Coupon\Models\UserCoupon;
|
||||||
use Peidikeji\Order\Enums\OrderStatus;
|
use Peidikeji\Order\Enums\OrderStatus;
|
||||||
use Peidikeji\Order\Enums\PayWay;
|
use Peidikeji\Order\Enums\PayWay;
|
||||||
use Peidikeji\Order\Enums\ShipWay;
|
use Peidikeji\Order\Enums\ShipWay;
|
||||||
|
|
@ -28,7 +23,7 @@ class OrderController extends Controller
|
||||||
{
|
{
|
||||||
$user = auth('api')->user();
|
$user = auth('api')->user();
|
||||||
|
|
||||||
$query = $user->orders()->with(['goods', 'merchant'])->filter($request->all());
|
$query = $user->orders()->with(['goods'])->filter($request->all());
|
||||||
|
|
||||||
$list = $query->sort()->paginate($request->input('per_page'));
|
$list = $query->sort()->paginate($request->input('per_page'));
|
||||||
|
|
||||||
|
|
@ -59,22 +54,14 @@ class OrderController extends Controller
|
||||||
public function sure(Request $request)
|
public function sure(Request $request)
|
||||||
{
|
{
|
||||||
$request->validate([
|
$request->validate([
|
||||||
'scene' => ['required', new Enum(OrderScene::class)],
|
|
||||||
'goods' => [Rule::requiredIf(!$request->filled('cart_id')), 'array'],
|
'goods' => [Rule::requiredIf(!$request->filled('cart_id')), 'array'],
|
||||||
'cart_id' => ['array'],
|
'cart_id' => ['array'],
|
||||||
'merchant_id' => [Rule::requiredIf($request->input('scene') === OrderScene::Merchant->value)],
|
'address' => [Rule::requiredIf(!$request->filled('address_id')), 'array'],
|
||||||
|
'address_id' => ['numeric']
|
||||||
]);
|
]);
|
||||||
$user = auth('api')->user();
|
$user = auth('api')->user();
|
||||||
|
|
||||||
$service = OrderStore::init()->user($user)->scene($request->input('scene'));
|
$service = OrderStore::init()->user($user);
|
||||||
|
|
||||||
if ($request->filled('merchant_id')) {
|
|
||||||
$merchant = Merchant::findOrFail($request->input('merchant_id'));
|
|
||||||
if (!$merchant->enable()) {
|
|
||||||
throw new OrderException('店铺不可用');
|
|
||||||
}
|
|
||||||
$service->merchant($merchant);
|
|
||||||
}
|
|
||||||
|
|
||||||
$goods = $request->input('goods');
|
$goods = $request->input('goods');
|
||||||
if ($request->filled('cart_id')) {
|
if ($request->filled('cart_id')) {
|
||||||
|
|
@ -83,6 +70,61 @@ class OrderController extends Controller
|
||||||
$service->goods($goods);
|
$service->goods($goods);
|
||||||
|
|
||||||
// 收货地址
|
// 收货地址
|
||||||
|
$address = $request->input('address');
|
||||||
|
|
||||||
|
// 优惠券
|
||||||
|
// $coupons = UserCoupon::where('user_id', $user->id)->effective()->get();
|
||||||
|
|
||||||
|
$service->ship(ShipWay::Express->value, $this->formatAddress($address));
|
||||||
|
|
||||||
|
$score = $request->input('score');
|
||||||
|
$userScore = $user->balance;
|
||||||
|
$maxScore = $userScore;
|
||||||
|
if ($score) {
|
||||||
|
$service->score($score);
|
||||||
|
}
|
||||||
|
|
||||||
|
$goodsList = $service->orderGoodsList;
|
||||||
|
|
||||||
|
// 付款金额
|
||||||
|
$payMoney = $service->getPayMoney();
|
||||||
|
|
||||||
|
return $this->json([
|
||||||
|
'address' => $address,
|
||||||
|
'list' => $goodsList,
|
||||||
|
'score' => [
|
||||||
|
'has' => floatval($userScore),
|
||||||
|
'use' => floatval($score),
|
||||||
|
'max' => floatval($maxScore)
|
||||||
|
],
|
||||||
|
'price' => [
|
||||||
|
'goods' => floatval($goodsList->sum('money')),
|
||||||
|
'ship' => $service->ship['money'],
|
||||||
|
'coupon' => 0,
|
||||||
|
'score' => $service->score['money'],
|
||||||
|
'total' => $payMoney,
|
||||||
|
],
|
||||||
|
'coupons' => []
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(Request $request)
|
||||||
|
{
|
||||||
|
$user = auth('api')->user();
|
||||||
|
|
||||||
|
$store = OrderStore::init()->user($user)->remarks($request->input('remarks'));
|
||||||
|
$request->validate([
|
||||||
|
'goods' => [Rule::requiredIf(!$request->filled('cart_id')), 'array'],
|
||||||
|
'cart_id' => ['array'],
|
||||||
|
'address' => [Rule::requiredIf(!$request->filled('address_id')), 'array'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$goods = $request->input('goods');
|
||||||
|
if ($request->filled('cart_id')) {
|
||||||
|
$goods = $this->formatCartGoods($user->carts()->whereIn('id', $request->input('cart_id'))->get());
|
||||||
|
}
|
||||||
|
$store->goods($goods);
|
||||||
|
|
||||||
$address = null;
|
$address = null;
|
||||||
if ($request->filled('address_id')) {
|
if ($request->filled('address_id')) {
|
||||||
$address = $user->addresses()->find($request->input('address_id'));
|
$address = $user->addresses()->find($request->input('address_id'));
|
||||||
|
|
@ -91,141 +133,13 @@ class OrderController extends Controller
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!$address) {
|
if (!$address) {
|
||||||
$address = $user->addresses()->orderBy('is_default', 'desc')->orderBy('created_at', 'desc')->first();
|
$address = $request->input('address');
|
||||||
}
|
}
|
||||||
|
|
||||||
$service->ship(ShipWay::Express->value, $this->formatAddress($address));
|
$store->ship($request->input('ship_way', ShipWay::None->value), $this->formatAddress($address));
|
||||||
|
|
||||||
// 计算最大积分抵扣
|
|
||||||
$maxScore = floatval($service->orderGoodsList->sum('score_max_amount'));
|
|
||||||
$score = $request->input('score');
|
|
||||||
$userScore = floatval($user->profit);
|
|
||||||
if (!$score) {
|
|
||||||
$score = $userScore > $maxScore ? $maxScore : $userScore;
|
|
||||||
}
|
|
||||||
$service->score($score);
|
|
||||||
|
|
||||||
$goodsList = $service->orderGoodsList;
|
$store->score($request->input('score', 0));
|
||||||
|
|
||||||
$dataList = collect();
|
|
||||||
|
|
||||||
foreach($goodsList->groupBy('merchant_id') as $id => $list) {
|
|
||||||
|
|
||||||
$dataList->push([
|
|
||||||
'merchant' => $id ? Merchant::select('id', 'name')->find($id) : ['id' => null, 'name' => '自营店铺'],
|
|
||||||
'list' => $list
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 付款金额
|
|
||||||
$payMoney = $service->getPayMoney();
|
|
||||||
|
|
||||||
return $this->json([
|
|
||||||
'address' => $address ? UserAddressResource::make($address) : null,
|
|
||||||
'list' => $dataList,
|
|
||||||
'score' => [
|
|
||||||
'has' => $userScore,
|
|
||||||
'use' => $score,
|
|
||||||
'max' => $maxScore,
|
|
||||||
'bonus' => $service->getUserBonus($payMoney),
|
|
||||||
],
|
|
||||||
'price' => [
|
|
||||||
'goods' => floatval($goodsList->sum('price')),
|
|
||||||
'ship' => $service->ship['money'],
|
|
||||||
'coupon' => 0,
|
|
||||||
'vip' => $service->vip['money'],
|
|
||||||
'score' => $service->score['money'],
|
|
||||||
'total' => $payMoney,
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function store(Request $request)
|
|
||||||
{
|
|
||||||
$user = auth('api')->user();
|
|
||||||
|
|
||||||
$request->validate([
|
|
||||||
'scene' => ['required', new Enum(OrderScene::class)]
|
|
||||||
]);
|
|
||||||
|
|
||||||
$scene = $request->input('scene');
|
|
||||||
$store = OrderStore::init()->scene($scene)->user($user)->remarks($request->input('remarks'));
|
|
||||||
// 自营商城下单
|
|
||||||
if ($scene === OrderScene::Online->value) {
|
|
||||||
$request->validate([
|
|
||||||
'goods' => [Rule::requiredIf(!$request->filled('cart_id')), 'array'],
|
|
||||||
'cart_id' => ['array'],
|
|
||||||
'address' => [Rule::requiredIf(!$request->filled('address_id')), 'array'],
|
|
||||||
]);
|
|
||||||
|
|
||||||
$goods = $request->input('goods');
|
|
||||||
if ($request->filled('cart_id')) {
|
|
||||||
$goods = $this->formatCartGoods($user->carts()->whereIn('id', $request->input('cart_id'))->get());
|
|
||||||
}
|
|
||||||
$store->goods($goods);
|
|
||||||
|
|
||||||
$address = null;
|
|
||||||
if ($request->filled('address_id')) {
|
|
||||||
$address = $user->addresses()->find($request->input('address_id'));
|
|
||||||
if (!$address) {
|
|
||||||
return $this->error('收货地址不存在');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!$address) {
|
|
||||||
$address = $request->input('address');
|
|
||||||
}
|
|
||||||
|
|
||||||
$store->ship(ShipWay::Express->value, $this->formatAddress($address));
|
|
||||||
|
|
||||||
$store->score($request->input('score', 0));
|
|
||||||
}
|
|
||||||
// 店铺下单
|
|
||||||
else if ($scene === OrderScene::Merchant->value) {
|
|
||||||
$request->validate([
|
|
||||||
'goods' => [Rule::requiredIf(!$request->filled('cart_id')), 'array'],
|
|
||||||
'cart_id' => ['array'],
|
|
||||||
'merchant_id' => 'required',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$merchant = Merchant::findOrFail($request->input('merchant_id'));
|
|
||||||
if (!$merchant->enable()) {
|
|
||||||
throw new OrderException('店铺不可用');
|
|
||||||
}
|
|
||||||
$store->merchant($merchant);
|
|
||||||
|
|
||||||
$goods = $request->input('goods');
|
|
||||||
if ($request->filled('cart_id')) {
|
|
||||||
$goods = $this->formatCartGoods($user->carts()->whereIn('id', $request->input('cart_id'))->get());
|
|
||||||
}
|
|
||||||
$store->goods($goods);
|
|
||||||
|
|
||||||
$store->ship(ShipWay::Pick->value);
|
|
||||||
|
|
||||||
// 验证店铺返现余额是否足够
|
|
||||||
$payMoney = $store->getPayMoney();
|
|
||||||
$ratio = $merchant->profit_ratio / 100;
|
|
||||||
$userProfit = round($payMoney * $ratio, 2, PHP_ROUND_HALF_DOWN);
|
|
||||||
$merchantUser = $merchant->user;
|
|
||||||
if ($merchantUser->profit < $userProfit) {
|
|
||||||
throw new OrderException('店铺返现账户余额不足');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 扫码付款
|
|
||||||
else if ($scene === OrderScene::Scan->value) {
|
|
||||||
$request->validate([
|
|
||||||
'money' => 'required',
|
|
||||||
'merchant_id' => 'required',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$merchant = Merchant::findOrFail($request->input('merchant_id'));
|
|
||||||
if (!$merchant->enable()) {
|
|
||||||
throw new OrderException('店铺不可用');
|
|
||||||
}
|
|
||||||
$store->merchant($merchant);
|
|
||||||
$store->money($request->input('money'));
|
|
||||||
} else {
|
|
||||||
return $this->error('未知下单场景');
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
DB::beginTransaction();
|
DB::beginTransaction();
|
||||||
$order = $store->create();
|
$order = $store->create();
|
||||||
|
|
@ -350,20 +264,6 @@ class OrderController extends Controller
|
||||||
return $this->json(OrderShipResouce::collection($list));
|
return $this->json(OrderShipResouce::collection($list));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function logistics(Request $request)
|
|
||||||
{
|
|
||||||
$request->validate([
|
|
||||||
'order_id' => 'required',
|
|
||||||
'ship_id' => 'required',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$user = auth('api')->user();
|
|
||||||
$order = $user->orders()->findOrFail($request->input('order_id'));
|
|
||||||
$ship = $order->ships()->findOrFail($request->input('ship_id'));
|
|
||||||
|
|
||||||
return $this->success();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function formatCartGoods($carts)
|
protected function formatCartGoods($carts)
|
||||||
{
|
{
|
||||||
$goods = [];
|
$goods = [];
|
||||||
|
|
@ -381,27 +281,6 @@ class OrderController extends Controller
|
||||||
|
|
||||||
protected function formatAddress($userAddress)
|
protected function formatAddress($userAddress)
|
||||||
{
|
{
|
||||||
$address = [];
|
return $userAddress;
|
||||||
if ($userAddress instanceof UserAddress) {
|
|
||||||
$address = [
|
|
||||||
'name' => $userAddress->contact_name,
|
|
||||||
'phone' => $userAddress->phone,
|
|
||||||
'region' => [$userAddress->province?->name, $userAddress->city?->name, $userAddress->area?->name],
|
|
||||||
'zone' => [$userAddress->province_id, $userAddress->city_id, $userAddress->area_id],
|
|
||||||
'address' => $userAddress->address,
|
|
||||||
'address_id' => $userAddress->id
|
|
||||||
];
|
|
||||||
} else if (is_array($userAddress)) {
|
|
||||||
$address = $userAddress;
|
|
||||||
$region = data_get($address, 'region');
|
|
||||||
if (!$region || count($region) === 0) {
|
|
||||||
throw new OrderException('收货地址格式不正确');
|
|
||||||
}
|
|
||||||
$area = Zone::where('name', $region[2])->where('type', 'area')->firstOrFail();
|
|
||||||
$city = Zone::findOrFail($area->parent_id);
|
|
||||||
$address['zone'] = [$city->parent_id, $area->parent_id, $area->id];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $address;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,6 @@
|
||||||
namespace Peidikeji\Order\Http\Resources;
|
namespace Peidikeji\Order\Http\Resources;
|
||||||
|
|
||||||
use Illuminate\Http\Resources\Json\JsonResource;
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
use Peidikeji\Merchant\Http\Resources\MerchantTinyResource;
|
|
||||||
use Peidikeji\Order\Enums\OrderScene;
|
|
||||||
|
|
||||||
class OrderResource extends JsonResource
|
class OrderResource extends JsonResource
|
||||||
{
|
{
|
||||||
|
|
@ -14,15 +12,8 @@ class OrderResource extends JsonResource
|
||||||
return [
|
return [
|
||||||
'id' => $this->id,
|
'id' => $this->id,
|
||||||
'sn' => $this->sn,
|
'sn' => $this->sn,
|
||||||
|
|
||||||
'scene' => $this->scene,
|
|
||||||
'scene_text' => $this->scene->text(),
|
|
||||||
|
|
||||||
'user_id' => $this->user_id,
|
'user_id' => $this->user_id,
|
||||||
|
|
||||||
'merchant_id' => $this->merchant_id,
|
|
||||||
'merchant' => $this->merchant_id ? MerchantTinyResource::make($this->whenLoaded('merchant')) : ['id' => '', 'name' => '自营商城'],
|
|
||||||
|
|
||||||
'total_money' => floatval($this->total_money),
|
'total_money' => floatval($this->total_money),
|
||||||
'status' => $status,
|
'status' => $status,
|
||||||
'status_text' => $status->text(),
|
'status_text' => $status->text(),
|
||||||
|
|
@ -33,8 +24,6 @@ class OrderResource extends JsonResource
|
||||||
'pay_no' => $this->pay_no,
|
'pay_no' => $this->pay_no,
|
||||||
'pay_way' => $this->pay_way,
|
'pay_way' => $this->pay_way,
|
||||||
|
|
||||||
'vip_discount_money' => $this->vip_discount_money,
|
|
||||||
|
|
||||||
'score_discount_amount' => floatval($this->score_discount_amount),
|
'score_discount_amount' => floatval($this->score_discount_amount),
|
||||||
'score_discount_money' => floatval($this->score_discount_money),
|
'score_discount_money' => floatval($this->score_discount_money),
|
||||||
'score_discount_ratio' => floatval($this->score_discount_ratio),
|
'score_discount_ratio' => floatval($this->score_discount_ratio),
|
||||||
|
|
@ -48,11 +37,8 @@ class OrderResource extends JsonResource
|
||||||
|
|
||||||
'user_remarks' => $this->user_remarks,
|
'user_remarks' => $this->user_remarks,
|
||||||
'created_at' => $this->created_at->timestamp,
|
'created_at' => $this->created_at->timestamp,
|
||||||
'user_get_profit' => floatval($this->user_get_profit),
|
|
||||||
|
|
||||||
'goods' => OrderGoodsResource::collection($this->whenLoaded('goods')),
|
'goods' => OrderGoodsResource::collection($this->whenLoaded('goods')),
|
||||||
|
|
||||||
'ship_qrcode' => data_get($this->extra, 'ship_qrcode'),
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Peidikeji\Order\Listeners;
|
|
||||||
|
|
||||||
use App\Models\BalanceLog;
|
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
|
||||||
use Peidikeji\Order\Enums\PayStatus;
|
|
||||||
use Peidikeji\Order\Models\Order;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 订单使用积分抵扣
|
|
||||||
* 订单已支付 => 扣除用户的积分
|
|
||||||
* 订单已退款 => 返还用户扣除的积分
|
|
||||||
*/
|
|
||||||
class OrderDiscountProfit implements ShouldQueue
|
|
||||||
{
|
|
||||||
public function handle($event)
|
|
||||||
{
|
|
||||||
$order = $event->order;
|
|
||||||
$user = $order->user;
|
|
||||||
$amount = floatval($order->score_discount_amount);
|
|
||||||
if ($amount > 0 && $user) {
|
|
||||||
if ($order->pay_status === PayStatus::Success) {
|
|
||||||
$user->decrement('profit', $amount);
|
|
||||||
$user->balanceLogs()->create([
|
|
||||||
'type' => BalanceLog::TYPE_PROFIT,
|
|
||||||
'cate' => BalanceLog::CATE_PROFIT_ORDER_OUT,
|
|
||||||
'amount' => 0 - $amount,
|
|
||||||
'balance' => $user->profit,
|
|
||||||
'description' => '使用 '.$amount.' 积分抵扣 '.floatval($order->score_discount_money).' 元',
|
|
||||||
'source_id' => $order->id,
|
|
||||||
'source_type' => Order::class,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
else if ($order->pay_status === PayStatus::Refund) {
|
|
||||||
$user->increment('profit', $amount);
|
|
||||||
$user->balanceLogs()->create([
|
|
||||||
'type' => BalanceLog::TYPE_PROFIT,
|
|
||||||
'cate' => BalanceLog::CATE_PROFIT_ORDER_OUT,
|
|
||||||
'amount' => $amount,
|
|
||||||
'balance' => $user->profit,
|
|
||||||
'description' => '订单退款, 返还 '.$amount.' 积分',
|
|
||||||
'source_id' => $order->id,
|
|
||||||
'source_type' => Order::class,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Peidikeji\Order\Listeners;
|
|
||||||
|
|
||||||
use App\Models\BalanceLog;
|
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
|
||||||
use Illuminate\Support\Arr;
|
|
||||||
use Peidikeji\Order\Enums\OrderScene;
|
|
||||||
use Peidikeji\Order\Models\Order;
|
|
||||||
use Peidikeji\Setting\Models\Setting;
|
|
||||||
use Peidikeji\User\Models\User;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 邀请返现
|
|
||||||
*/
|
|
||||||
class OrderInviteProfit implements ShouldQueue
|
|
||||||
{
|
|
||||||
public function handle($event)
|
|
||||||
{
|
|
||||||
$order = $event->order;
|
|
||||||
$user = $order->user;
|
|
||||||
if ($order->scene === OrderScene::Online && $user && $user->inviter_path) {
|
|
||||||
// -, -1-, -1-2-, -3-16-21-41-54-64-
|
|
||||||
$parentIds = array_reverse(explode('-', $user->inviter_path));
|
|
||||||
$ratio = Setting::where('slug', 'invite_profit_ratio')->value('value');
|
|
||||||
if (count($parentIds) > 2 && $ratio > 0) {
|
|
||||||
$amount = round($order->total_money * $ratio / 100, 2, PHP_ROUND_HALF_DOWN);
|
|
||||||
foreach(Arr::only($parentIds, [1, 2]) as $id) {
|
|
||||||
$this->giveUser($id, $order, $amount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function giveUser($id, $order, $money = 0)
|
|
||||||
{
|
|
||||||
$user = User::find($id);
|
|
||||||
if ($user && $money > 0) {
|
|
||||||
$user->increment('balance', $money);
|
|
||||||
$user->balanceLogs()->create([
|
|
||||||
'type' => BalanceLog::TYPE_BALANCE,
|
|
||||||
'amount' => $money,
|
|
||||||
'balance' => $user->balance,
|
|
||||||
'cate' => BalanceLog::CATE_BALANCE_ORDER_PROFIT,
|
|
||||||
'description' => '邀请用户 '.$order->user->getSubPhone().' 下单得到返利 ' . $money,
|
|
||||||
'source_id' => $order->id,
|
|
||||||
'source_type' => Order::class,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Peidikeji\Order\Listeners;
|
|
||||||
|
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
|
||||||
use Peidikeji\Order\Enums\OrderScene;
|
|
||||||
use Peidikeji\Order\Enums\ShipWay;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 订单-生成取货的二维码
|
|
||||||
*/
|
|
||||||
class OrderMakeShipQrcode implements ShouldQueue
|
|
||||||
{
|
|
||||||
public function handle($event)
|
|
||||||
{
|
|
||||||
$order = $event->order;
|
|
||||||
if ($order->scene === OrderScene::Merchant && $order->ship_way === ShipWay::Pick) {
|
|
||||||
$order->generateShipQrcode();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,76 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Peidikeji\Order\Listeners;
|
|
||||||
|
|
||||||
use App\Models\BalanceLog;
|
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
|
||||||
use Peidikeji\Order\Enums\OrderScene;
|
|
||||||
use Peidikeji\Order\Enums\PayStatus;
|
|
||||||
use Peidikeji\Order\Models\Order;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 赠送用户积分
|
|
||||||
* 订单已支付 => 增加用户积分, 扣除商户积分
|
|
||||||
* 订单已退款 => 积分原路返还
|
|
||||||
*/
|
|
||||||
class OrderSendProfit implements ShouldQueue
|
|
||||||
{
|
|
||||||
public function handle($event)
|
|
||||||
{
|
|
||||||
$order = $event->order;
|
|
||||||
$user = $order->user;
|
|
||||||
$merchant = $order->merchant;
|
|
||||||
if ($order->scene === OrderScene::Merchant && $merchant) {
|
|
||||||
$merchantUser = $merchant->user;
|
|
||||||
$amount = floatval($order->user_get_profit);
|
|
||||||
if ($amount > 0 && $user && $merchantUser) {
|
|
||||||
if ($order->pay_status === PayStatus::Success) {
|
|
||||||
$user->increment('profit', $amount);
|
|
||||||
$user->balanceLogs()->create([
|
|
||||||
'type' => BalanceLog::TYPE_PROFIT,
|
|
||||||
'cate' => BalanceLog::CATE_PROFIT_ORDER_IN,
|
|
||||||
'amount' => $amount,
|
|
||||||
'balance' => $user->profit,
|
|
||||||
'description' => '在商户 ' . $merchant->name.' 下单, 赠送 '.$amount.' 积分',
|
|
||||||
'source_id' => $order->id,
|
|
||||||
'source_type' => Order::class,
|
|
||||||
]);
|
|
||||||
|
|
||||||
$merchantUser->decrement('profit', $amount);
|
|
||||||
$merchantUser->balanceLogs()->create([
|
|
||||||
'type' => BalanceLog::TYPE_PROFIT,
|
|
||||||
'cate' => BalanceLog::CATE_PROFIT_ORDER_USE,
|
|
||||||
'amount' => 0 - $amount,
|
|
||||||
'balance' => $merchantUser->profit,
|
|
||||||
'description' => '用户 ' . $user->getSubPhone() . ' 下单送出 '.$amount.' 积分',
|
|
||||||
'source_id' => $order->id,
|
|
||||||
'source_type' => Order::class,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
else if ($order->pay_status === PayStatus::Refund) {
|
|
||||||
$user->decrement('profit', $amount);
|
|
||||||
$user->balanceLogs()->create([
|
|
||||||
'type' => BalanceLog::TYPE_PROFIT,
|
|
||||||
'cate' => BalanceLog::CATE_PROFIT_ORDER_IN,
|
|
||||||
'amount' => 0 - $amount,
|
|
||||||
'balance' => $user->profit,
|
|
||||||
'description' => '订单退款, 扣除赠送的 '.$amount.' 积分',
|
|
||||||
'source_id' => $order->id,
|
|
||||||
'source_type' => Order::class,
|
|
||||||
]);
|
|
||||||
|
|
||||||
$merchantUser->increment('profit', $amount);
|
|
||||||
$merchantUser->balanceLogs()->create([
|
|
||||||
'type' => BalanceLog::TYPE_PROFIT,
|
|
||||||
'cate' => BalanceLog::CATE_PROFIT_ORDER_USE,
|
|
||||||
'amount' => $amount,
|
|
||||||
'balance' => $merchantUser->profit,
|
|
||||||
'description' => '用户 ' . $user->getSubPhone() . ' 订单退款返还 '.$amount.' 积分',
|
|
||||||
'source_id' => $order->id,
|
|
||||||
'source_type' => Order::class,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -4,7 +4,6 @@ namespace Peidikeji\Order\Listeners;
|
||||||
|
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
use Peidikeji\Goods\Models\Goods;
|
use Peidikeji\Goods\Models\Goods;
|
||||||
use Peidikeji\Merchant\Models\Merchant;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新商品销量
|
* 更新商品销量
|
||||||
|
|
@ -18,26 +17,12 @@ class UpdateGoodsSoldCount implements ShouldQueue
|
||||||
// true = 返还商品销量
|
// true = 返还商品销量
|
||||||
// false = 扣除商品销量
|
// false = 扣除商品销量
|
||||||
$close = $order->is_closed;
|
$close = $order->is_closed;
|
||||||
$merchants = [];
|
|
||||||
foreach($order->goods as $item) {
|
foreach($order->goods as $item) {
|
||||||
if ($close) {
|
if ($close) {
|
||||||
Goods::where('id', $item->goods_id)->decrement('sold_count', $item->amount);
|
Goods::where('id', $item->goods_id)->decrement('sold_count', $item->amount);
|
||||||
} else {
|
} else {
|
||||||
Goods::where('id', $item->goods_id)->increment('sold_count', $item->amount);
|
Goods::where('id', $item->goods_id)->increment('sold_count', $item->amount);
|
||||||
}
|
}
|
||||||
if ($item->merchant_id) {
|
|
||||||
$amount = data_get($merchants, $item->merchant_id, 0) + $item->amount;
|
|
||||||
$merchants[$item->merchant_id] = $amount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 增加店铺销量
|
|
||||||
foreach($merchants as $id => $amount) {
|
|
||||||
if ($close) {
|
|
||||||
Merchant::where('id', $id)->decrement('sold_count', $amount);
|
|
||||||
} else {
|
|
||||||
Merchant::where('id', $id)->increment('sold_count', $amount);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ use Dcat\Admin\Traits\HasDateTimeFormatter;
|
||||||
use EloquentFilter\Filterable;
|
use EloquentFilter\Filterable;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Peidikeji\Order\Enums\RefundStatus;
|
use Peidikeji\Order\Enums\RefundStatus;
|
||||||
use Peidikeji\Order\Enums\OrderScene;
|
|
||||||
use Peidikeji\Order\Enums\OrderStatus;
|
use Peidikeji\Order\Enums\OrderStatus;
|
||||||
use Peidikeji\Order\Enums\PayStatus;
|
use Peidikeji\Order\Enums\PayStatus;
|
||||||
use Peidikeji\Order\Enums\PayWay;
|
use Peidikeji\Order\Enums\PayWay;
|
||||||
|
|
@ -22,13 +21,11 @@ class Order extends Model
|
||||||
use Filterable;
|
use Filterable;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'user_id',
|
'sn', 'total_money', 'user_id',
|
||||||
'total_money', 'sn',
|
'ship_address', 'ship_at', 'ship_money', 'ship_status', 'ship_way', 'receive_at',
|
||||||
'pay_at', 'pay_money', 'pay_no', 'pay_status', 'pay_way',
|
|
||||||
'score_discount_amount', 'score_discount_money', 'score_discount_ratio',
|
'score_discount_amount', 'score_discount_money', 'score_discount_ratio',
|
||||||
'ship_way', 'ship_address', 'ship_at', 'ship_status', 'ship_money',
|
'pay_at', 'pay_money', 'pay_no', 'pay_status', 'pay_way',
|
||||||
'refund_status', 'is_closed', 'auto_close_at', 'review_at', 'receive_at',
|
'auto_close_at', 'extra', 'is_closed', 'refund_status', 'remarks', 'review_at', 'user_remarks'
|
||||||
'extra', 'user_remarks', 'remarks', 'scene', 'user_get_profit',
|
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
|
|
@ -37,7 +34,6 @@ class Order extends Model
|
||||||
'pay_status' => PayStatus::class,
|
'pay_status' => PayStatus::class,
|
||||||
'pay_way' => PayWay::class,
|
'pay_way' => PayWay::class,
|
||||||
'ship_status' => ShipStatus::class,
|
'ship_status' => ShipStatus::class,
|
||||||
'scene' => OrderScene::class,
|
|
||||||
'ship_way' => ShipWay::class,
|
'ship_way' => ShipWay::class,
|
||||||
'refund_status' => RefundStatus::class,
|
'refund_status' => RefundStatus::class,
|
||||||
];
|
];
|
||||||
|
|
@ -49,7 +45,7 @@ class Order extends Model
|
||||||
'refund_status' => RefundStatus::None
|
'refund_status' => RefundStatus::None
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $dates = ['pay_at', 'ship_at', 'receive_at'];
|
protected $dates = ['pay_at', 'ship_at', 'receive_at', 'auto_close_at'];
|
||||||
|
|
||||||
public function user()
|
public function user()
|
||||||
{
|
{
|
||||||
|
|
@ -89,6 +85,7 @@ class Order extends Model
|
||||||
if ($this->ship_status === ShipStatus::Processing) {
|
if ($this->ship_status === ShipStatus::Processing) {
|
||||||
return OrderStatus::Send;
|
return OrderStatus::Send;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->ship_status === ShipStatus::Finished) {
|
if ($this->ship_status === ShipStatus::Finished) {
|
||||||
return OrderStatus::SendFull;
|
return OrderStatus::SendFull;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -64,9 +64,9 @@ class OrderService
|
||||||
throw new OrderException('没有找到下单用户');
|
throw new OrderException('没有找到下单用户');
|
||||||
}
|
}
|
||||||
// 验证积分余额是否足够
|
// 验证积分余额是否足够
|
||||||
$profit = $order->score_discount_amount;
|
$score = $order->score_discount_amount;
|
||||||
if ($user->profit < $profit) {
|
if ($user->balance < $score) {
|
||||||
throw new OrderException('e品额不足');
|
throw new OrderException('用户积分不足');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 支付金额
|
// 支付金额
|
||||||
|
|
@ -173,13 +173,6 @@ class OrderService
|
||||||
}
|
}
|
||||||
$order->save();
|
$order->save();
|
||||||
|
|
||||||
// 扫码付款的订单, 支付成功后, 直接完成
|
|
||||||
if ($order->scene === OrderScene::Scan) {
|
|
||||||
$order->ship_status = ShipStatus::Finished;
|
|
||||||
$order->save();
|
|
||||||
$this->receive($order);
|
|
||||||
}
|
|
||||||
|
|
||||||
event(new OrderPaid($order));
|
event(new OrderPaid($order));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -206,18 +199,17 @@ class OrderService
|
||||||
$subParam = ['order_goods_id' => $item->id, 'amount' => $item->amount, 'goods_name' => $item->goods_name];
|
$subParam = ['order_goods_id' => $item->id, 'amount' => $item->amount, 'goods_name' => $item->goods_name];
|
||||||
} else {
|
} else {
|
||||||
$filter = array_filter($goods, fn($subItem) => $subItem['order_goods_id'] == $item->id);
|
$filter = array_filter($goods, fn($subItem) => $subItem['order_goods_id'] == $item->id);
|
||||||
$amount = data_get($filter, '0.amount');
|
$subItem = array_shift($filter);
|
||||||
if ($amount) {
|
$amount = data_get($subItem, 'amount', 0);
|
||||||
$subParam = ['order_goods_id' => $item->id, 'amount' => $amount, 'goods_name' => $item->goods_name, 'cover_image' => $item->cover_image];
|
$subParam = ['order_goods_id' => $item->id, 'amount' => $amount, 'goods_name' => $item->goods_name, 'cover_image' => $item->cover_image];
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if ($subParam) {
|
if ($item->ship_amount + $subParam['amount'] > $item->amount) {
|
||||||
if ($item->ship_amount + $subParam['amount'] > $item->amount) {
|
throw new OrderException($subParam['goods_name'] . ' 发货数量超过购买数量');
|
||||||
throw new OrderException($subParam['goods_name'] . ' 发货数量超过购买数量');
|
}
|
||||||
}
|
if ($item->ship_amount + $subParam['amount'] < $item->amount) {
|
||||||
if ($item->ship_amount + $subParam['amount'] < $item->amount) {
|
$full = false;
|
||||||
$full = false;
|
}
|
||||||
}
|
if ($subParam['amount']) {
|
||||||
$item->increment('ship_amount', $subParam['amount']);
|
$item->increment('ship_amount', $subParam['amount']);
|
||||||
array_push($params, $subParam);
|
array_push($params, $subParam);
|
||||||
}
|
}
|
||||||
|
|
@ -299,10 +291,6 @@ class OrderService
|
||||||
}
|
}
|
||||||
// 订单已经支付, 全额退款
|
// 订单已经支付, 全额退款
|
||||||
if ($order->pay_status === PayStatus::Success) {
|
if ($order->pay_status === PayStatus::Success) {
|
||||||
// 如果赠送给用户积分, 验证用户余额是否足够扣除
|
|
||||||
if ($order->user_get_profit > 0 && $order->user->profit < $order->user_get_profit) {
|
|
||||||
throw new OrderException('订单无法取消, 用户余额不足');
|
|
||||||
}
|
|
||||||
|
|
||||||
// 支付金额
|
// 支付金额
|
||||||
if ($order->pay_money > 0) {
|
if ($order->pay_money > 0) {
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ namespace Peidikeji\Order;
|
||||||
use Peidikeji\Coupon\CouponService;
|
use Peidikeji\Coupon\CouponService;
|
||||||
use Peidikeji\Coupon\Models\UserCoupon;
|
use Peidikeji\Coupon\Models\UserCoupon;
|
||||||
use Peidikeji\Goods\Models\Goods;
|
use Peidikeji\Goods\Models\Goods;
|
||||||
use Peidikeji\Order\Enums\OrderScene;
|
|
||||||
use Peidikeji\Order\Events\OrderCreated;
|
use Peidikeji\Order\Events\OrderCreated;
|
||||||
use Peidikeji\Order\Exceptions\OrderException;
|
use Peidikeji\Order\Exceptions\OrderException;
|
||||||
use Peidikeji\Order\Models\Order;
|
use Peidikeji\Order\Models\Order;
|
||||||
|
|
@ -19,15 +18,9 @@ class OrderStore
|
||||||
// 商品列表
|
// 商品列表
|
||||||
public $goodsList;
|
public $goodsList;
|
||||||
|
|
||||||
// 订单场景
|
|
||||||
public $scene;
|
|
||||||
|
|
||||||
// 下单用户
|
// 下单用户
|
||||||
public $user;
|
public $user;
|
||||||
|
|
||||||
// 指定店铺
|
|
||||||
public $merchant;
|
|
||||||
|
|
||||||
// 订单总额/商品总额
|
// 订单总额/商品总额
|
||||||
public $money;
|
public $money;
|
||||||
|
|
||||||
|
|
@ -37,28 +30,17 @@ class OrderStore
|
||||||
// amount: 使用积分, money: 积分抵扣金额, ratio: 抵扣比例
|
// amount: 使用积分, money: 积分抵扣金额, ratio: 抵扣比例
|
||||||
public $score = ['amount' => 0, 'money' => 0, 'ratio' => 0];
|
public $score = ['amount' => 0, 'money' => 0, 'ratio' => 0];
|
||||||
|
|
||||||
// is: 是否Vip, money: 会员累计优惠金额
|
|
||||||
public $vip = ['is' => false, 'money' => 0];
|
|
||||||
|
|
||||||
// address: 配送地址, money: 配送费, way: 配送方式
|
// address: 配送地址, money: 配送费, way: 配送方式
|
||||||
public $ship = ['address' => null, 'money' => 0, 'way' => null];
|
public $ship = ['address' => null, 'money' => 0, 'way' => null];
|
||||||
|
|
||||||
// 使用优惠券
|
// 使用优惠券
|
||||||
public $coupon = ['id' => null, 'money' => 0];
|
public $coupon = ['id' => null, 'money' => 0];
|
||||||
|
|
||||||
public function __construct($scene = null)
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->scene = $scene;
|
|
||||||
$this->orderGoodsList = collect();
|
$this->orderGoodsList = collect();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function scene($scene): static
|
|
||||||
{
|
|
||||||
$this->scene = $scene;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function user($user): static
|
public function user($user): static
|
||||||
{
|
{
|
||||||
$this->user = $user;
|
$this->user = $user;
|
||||||
|
|
@ -66,13 +48,6 @@ class OrderStore
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function merchant($merchant): static
|
|
||||||
{
|
|
||||||
$this->merchant = $merchant;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function remarks($remarks): static
|
public function remarks($remarks): static
|
||||||
{
|
{
|
||||||
$this->remarks = $remarks;
|
$this->remarks = $remarks;
|
||||||
|
|
@ -84,70 +59,37 @@ class OrderStore
|
||||||
* 购买商品
|
* 购买商品
|
||||||
*
|
*
|
||||||
* @param array $params 商品参数 [{id, amount, spec: [{name, value}]}]
|
* @param array $params 商品参数 [{id, amount, spec: [{name, value}]}]
|
||||||
* @param mixed $vip 是否使用Vip价格(null: 根据用户判断, bool: 是否强制使用)
|
|
||||||
* @throws OrderException
|
* @throws OrderException
|
||||||
*/
|
*/
|
||||||
public function goods(array $params, mixed $vip = null): static
|
public function goods(array $params): static
|
||||||
{
|
{
|
||||||
$merchant = $this->merchant;
|
$goodsList = Goods::show()->whereIn('id', array_column($params, 'id'))->get();
|
||||||
$goodsList = null;
|
|
||||||
if ($this->scene === OrderScene::Online->value) {
|
|
||||||
$goodsList = Goods::show()->whereNull('merchant_id')->whereIn('id', array_column($params, 'id'))->get();
|
|
||||||
} elseif ($this->scene === OrderScene::Merchant->value) {
|
|
||||||
$goodsList = Goods::show()->where('merchant_id', $merchant->id)->whereIn('id', array_column($params, 'id'))->get();
|
|
||||||
} elseif ($this->scene === OrderScene::Scan->value) {
|
|
||||||
$money = $this->money;
|
|
||||||
$goodsList = collect()->push([
|
|
||||||
'id' => data_get($params, '0.id'),
|
|
||||||
'name' => $merchant->name,
|
|
||||||
'merchant_id' => $merchant->id,
|
|
||||||
'goods_name' => '线下交易',
|
|
||||||
'cover_image' => $merchant->logo,
|
|
||||||
'price' => $money,
|
|
||||||
'vip_price' => $money,
|
|
||||||
'amount' => 1,
|
|
||||||
'on_sale' => 1,
|
|
||||||
'stock' => 1
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
if ($goodsList->count() === 0) {
|
if ($goodsList->count() === 0) {
|
||||||
throw new OrderException('请选择有效商品');
|
throw new OrderException('请选择有效商品');
|
||||||
}
|
}
|
||||||
|
|
||||||
$orderGoodsList = collect();
|
$orderGoodsList = collect();
|
||||||
$user = $this->user;
|
|
||||||
if ($vip === null && $user) {
|
|
||||||
$vip = $user->isVip();
|
|
||||||
}
|
|
||||||
foreach ($params as $item) {
|
foreach ($params as $item) {
|
||||||
$goods = $goodsList->firstWhere('id', $item['id']);
|
$goods = $goodsList->firstWhere('id', $item['id']);
|
||||||
|
if (!$goods) {
|
||||||
|
throw new OrderException('商品未上架');
|
||||||
|
}
|
||||||
if (! data_get($goods, 'on_sale')) {
|
if (! data_get($goods, 'on_sale')) {
|
||||||
throw new OrderException($goods->name.' 未上架');
|
throw new OrderException($goods->name.' 未上架');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 最大抵扣积分
|
|
||||||
$scoreRatio = data_get($goods, 'score_max_amount', $merchant->score_max_ratio);
|
|
||||||
$price = data_get($goods, $vip ? 'vip_price' : 'price');
|
|
||||||
$scoreMaxAmount = $price * $scoreRatio / 100 / Setting::where('slug', 'discount_profit_ratio')->value('value');
|
|
||||||
|
|
||||||
$stock = data_get($goods, 'stock');
|
$stock = data_get($goods, 'stock');
|
||||||
$orderGoods = [
|
$orderGoods = [
|
||||||
'goods_id' => data_get($goods, 'id'),
|
'goods_id' => data_get($goods, 'id'),
|
||||||
'merchant_id' => data_get($goods, 'merchant_id'),
|
|
||||||
'goods_name' => data_get($goods, 'name'),
|
'goods_name' => data_get($goods, 'name'),
|
||||||
'goods_sn' => data_get($goods, 'sn'),
|
'goods_sn' => data_get($goods, 'goods_sn'),
|
||||||
'cover_image' => data_get($goods, 'cover_image'),
|
'cover_image' => data_get($goods, 'cover_image'),
|
||||||
'price' => data_get($goods, 'price'),
|
'price' => floatval(data_get($goods, 'price')),
|
||||||
'vip_price' => data_get($goods, 'vip_price'),
|
|
||||||
'score_max_amount' => $scoreMaxAmount,
|
|
||||||
'attr' => data_get($goods, 'attr'),
|
'attr' => data_get($goods, 'attr'),
|
||||||
'spec' => data_get($item, 'spec'),
|
'spec' => data_get($item, 'spec'),
|
||||||
'part' => data_get($item, 'part'),
|
'part' => data_get($item, 'part'),
|
||||||
'amount' => data_get($item, 'amount', 1),
|
'amount' => data_get($item, 'amount', 1),
|
||||||
'money' => 0,
|
'money' => 0,
|
||||||
'shipping_tmp_id' => data_get($goods, 'shipping_tmp_id'),
|
|
||||||
'weight' => data_get($goods, 'weight'),
|
|
||||||
'volume' => data_get($goods, 'volume'),
|
|
||||||
];
|
];
|
||||||
if (data_get($item, 'spec')) {
|
if (data_get($item, 'spec')) {
|
||||||
$sku = $goods->skus()->jsonArray($item['spec'])->first();
|
$sku = $goods->skus()->jsonArray($item['spec'])->first();
|
||||||
|
|
@ -157,11 +99,7 @@ class OrderStore
|
||||||
$stock = $sku->stock;
|
$stock = $sku->stock;
|
||||||
$orderGoods['goods_sku_id'] = $sku->id;
|
$orderGoods['goods_sku_id'] = $sku->id;
|
||||||
$orderGoods['goods_sku_sn'] = $sku->sn;
|
$orderGoods['goods_sku_sn'] = $sku->sn;
|
||||||
$orderGoods['vip_price'] = $sku->vip_price;
|
$orderGoods['price'] = floatval($sku->price);
|
||||||
$orderGoods['price'] = $sku->price;
|
|
||||||
$orderGoods['shipping_tmp_id'] = $sku->shipping_tmp_id;
|
|
||||||
$orderGoods['weight'] = $sku->weight;
|
|
||||||
$orderGoods['volume'] = $sku->volume;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($orderGoods['amount'] > $stock) {
|
if ($orderGoods['amount'] > $stock) {
|
||||||
|
|
@ -176,7 +114,6 @@ class OrderStore
|
||||||
$this->goodsList = $goodsList;
|
$this->goodsList = $goodsList;
|
||||||
$this->orderGoodsList = $orderGoodsList;
|
$this->orderGoodsList = $orderGoodsList;
|
||||||
$this->money = $orderGoodsList->sum('money');
|
$this->money = $orderGoodsList->sum('money');
|
||||||
$this->vip = ['is' => $vip, 'money' => $vip ? $orderGoodsList->sum(fn ($item) => $item['price'] - $item['vip_price']) : 0];
|
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
@ -211,19 +148,6 @@ class OrderStore
|
||||||
$this->coupon = ['id' => $info->id, 'money' => $couponMoney];
|
$this->coupon = ['id' => $info->id, 'money' => $couponMoney];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置订单总金额
|
|
||||||
*/
|
|
||||||
public function money($money)
|
|
||||||
{
|
|
||||||
if ($this->scene !== OrderScene::Scan->value) {
|
|
||||||
throw new OrderException('非扫码付款, 无法设置订单金额');
|
|
||||||
}
|
|
||||||
$this->money = $money;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 使用积分抵扣
|
* 使用积分抵扣
|
||||||
*
|
*
|
||||||
|
|
@ -236,21 +160,11 @@ class OrderStore
|
||||||
{
|
{
|
||||||
$user = $this->user;
|
$user = $this->user;
|
||||||
if ($amount > 0 && $user) {
|
if ($amount > 0 && $user) {
|
||||||
// 最大抵扣数量
|
if ($user->balance < $amount) {
|
||||||
$maxAmount = $this->orderGoodsList->sum('score_max_amount');
|
|
||||||
if ($amount > $maxAmount) {
|
|
||||||
throw new OrderException($maxAmount > 0 ? '本次订单最多使用 '.$maxAmount.' 积分抵扣' : '订单不支持使用积分抵扣');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($user->profit < $amount) {
|
|
||||||
throw new OrderException('用户积分不足');
|
throw new OrderException('用户积分不足');
|
||||||
}
|
}
|
||||||
if ($ratio === null) {
|
// 积分抵扣比例: 1 积分 = ? 金额
|
||||||
$ratio = round(Setting::where('slug', 'discount_profit_ratio')->value('value'), 2, PHP_ROUND_HALF_DOWN);
|
$ratio = 1;
|
||||||
}
|
|
||||||
if ($ratio === null) {
|
|
||||||
throw new OrderException('未配置积分抵扣比例');
|
|
||||||
}
|
|
||||||
if ($money === null) {
|
if ($money === null) {
|
||||||
$money = $amount * $ratio;
|
$money = $amount * $ratio;
|
||||||
}
|
}
|
||||||
|
|
@ -274,9 +188,7 @@ class OrderStore
|
||||||
'sn' => OrderService::make()->generateSn(),
|
'sn' => OrderService::make()->generateSn(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$order->scene = $this->scene;
|
|
||||||
$order->user_id = $this->user?->id;
|
$order->user_id = $this->user?->id;
|
||||||
$order->merchant_id = $this->merchant?->id;
|
|
||||||
$order->ship_address = $this->ship['address'];
|
$order->ship_address = $this->ship['address'];
|
||||||
$order->ship_way = $this->ship['way'];
|
$order->ship_way = $this->ship['way'];
|
||||||
$order->ship_money = $this->ship['money'];
|
$order->ship_money = $this->ship['money'];
|
||||||
|
|
@ -287,13 +199,12 @@ class OrderStore
|
||||||
$order->score_discount_ratio = $this->score['ratio'];
|
$order->score_discount_ratio = $this->score['ratio'];
|
||||||
$order->score_discount_money = $this->score['money'];
|
$order->score_discount_money = $this->score['money'];
|
||||||
|
|
||||||
$order->coupon_money = $this->coupon['money'];
|
if ($this->coupon['id']) {
|
||||||
$order->coupon_id = $this->coupon['id'];
|
$order->coupon_money = $this->coupon['money'];
|
||||||
|
$order->coupon_id = $this->coupon['id'];
|
||||||
$order->vip_discount_money = $this->vip['money'];
|
}
|
||||||
|
|
||||||
$order->pay_money = $this->getPayMoney();
|
$order->pay_money = $this->getPayMoney();
|
||||||
$order->user_get_profit = $this->getUserBonus($order->pay_money);
|
|
||||||
|
|
||||||
$order->save();
|
$order->save();
|
||||||
$order->goods()->createMany($this->orderGoodsList);
|
$order->goods()->createMany($this->orderGoodsList);
|
||||||
|
|
@ -315,9 +226,6 @@ class OrderStore
|
||||||
// 积分抵扣
|
// 积分抵扣
|
||||||
$money -= $this->score['money'];
|
$money -= $this->score['money'];
|
||||||
|
|
||||||
// Vip 优惠
|
|
||||||
$money -= $this->vip['money'];
|
|
||||||
|
|
||||||
// 优惠券抵扣
|
// 优惠券抵扣
|
||||||
$money -= $this->coupon['money'];
|
$money -= $this->coupon['money'];
|
||||||
|
|
||||||
|
|
@ -327,29 +235,6 @@ class OrderStore
|
||||||
return max($money, 0);
|
return max($money, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户应得奖励
|
|
||||||
*
|
|
||||||
* @param float|null $payMoney 支付金额
|
|
||||||
* @return float
|
|
||||||
* @throws OrderException
|
|
||||||
*/
|
|
||||||
public function getUserBonus(float $payMoney = null): float
|
|
||||||
{
|
|
||||||
$money = 0;
|
|
||||||
|
|
||||||
if ($this->merchant) {
|
|
||||||
$payMoney = is_null($payMoney) ? $this->getPayMoney() : $payMoney;
|
|
||||||
$money = floor($payMoney * ($this->merchant->profit_ratio / 100));
|
|
||||||
$merchantUser = $this->merchant->user;
|
|
||||||
if ($merchantUser->profit < $money) {
|
|
||||||
throw new OrderException('店铺返现账户余额不足');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $money;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function init(...$params): static
|
public static function init(...$params): static
|
||||||
{
|
{
|
||||||
return new static(...$params);
|
return new static(...$params);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue