6
0
Fork 0
Merge pull request !11 from 李静/develop
release
李静 2022-04-14 07:20:35 +00:00 committed by Gitee
commit 33236ef9ba
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
73 changed files with 3374 additions and 730 deletions

View File

@ -0,0 +1,32 @@
<?php
namespace App\Admin\Actions\Show;
use App\Admin\Forms\BargainOrderRemark as BargainOrderRemarkForm;
use Dcat\Admin\Show\AbstractTool;
use Dcat\Admin\Widgets\Modal;
class BargainOrderRemark extends AbstractTool
{
/**
* @return string
*/
protected $title = '<i class="feather icon-file-text"></i>&nbsp;备注';
/**
* 按钮样式定义,默认 btn btn-white waves-effect
*
* @var string
*/
protected $style = 'btn-success';
public function render()
{
$form = BargainOrderRemarkForm::make()->payload(['id'=>$this->getKey()]);
return Modal::make()
->lg()
->title($this->title)
->body($form)
->button("<a href=\"javascript:void(0)\" class=\"btn btn-sm {$this->style}\">{$this->title}</a>&nbsp;&nbsp;");
}
}

View File

@ -18,7 +18,7 @@ class DealerWalletPay extends AbstractTool
*
* @var string
*/
protected $style = 'btn-danger';
protected $style = 'btn-danger mr-1';
public function render()
{
@ -27,6 +27,6 @@ class DealerWalletPay extends AbstractTool
->lg()
->title($this->title)
->body($form)
->button("<a href=\"javascript:void(0)\" class=\"btn btn-sm {$this->style}\">{$this->title}</a>&nbsp;&nbsp;");
->button("<a href=\"javascript:void(0)\" class=\"btn btn-sm {$this->style}\">{$this->title}</a>");
}
}

View File

@ -18,7 +18,7 @@ class DealerWalletRefuse extends AbstractTool
*
* @var string
*/
protected $style = 'btn-warning';
protected $style = 'btn-warning mr-1';
public function render()
{
@ -27,6 +27,6 @@ class DealerWalletRefuse extends AbstractTool
->lg()
->title($this->title)
->body($form)
->button("<a href=\"javascript:void(0)\" class=\"btn btn-sm {$this->style}\">{$this->title}</a>&nbsp;&nbsp;");
->button("<a href=\"javascript:void(0)\" class=\"btn btn-sm {$this->style}\">{$this->title}</a>");
}
}

View File

@ -7,6 +7,7 @@ use App\Admin\Repositories\ArticleCategory;
use App\Exceptions\BizException;
use App\Models\Article;
use App\Models\ArticleCategory as ArticleCategoryModel;
use Carbon\Carbon;
use Dcat\Admin\Admin;
use Dcat\Admin\Form;
use Dcat\Admin\Grid;
@ -26,6 +27,7 @@ class ArticleCategoryController extends AdminController
return Grid::make(new ArticleCategoryModel(), function (Grid $grid) {
$grid->column('id')->sortable();
$grid->column('name')->tree();
$grid->column('cover')->image(100, 100);
$grid->column('is_show')
->if(function () {
return Admin::user()->can('dcat.admin.article_categories.edit');
@ -110,6 +112,11 @@ class ArticleCategoryController extends AdminController
$form->display('id');
$form->select('parent_id')->options(ArticleCategoryModel::selectOptions());
$form->text('name')->required();
$form->image('cover')
->move('article-category/'.Carbon::now()->toDateString())
->saveFullUrl()
->removable(false)
->autoUpload()->retainable();
$form->switch('is_show');
$form->switch('is_recommend');
$form->number('sort')->min(0)->default(0);

View File

@ -0,0 +1,218 @@
<?php
namespace App\Admin\Controllers;
use App\Admin\Renderable\ProductSkuSimpleTable;
use App\Admin\Repositories\BargainActivity;
use App\Models\BargainActivity as BargainActivityModel;
use App\Models\BargainOrder;
use App\Models\ProductSku;
use Carbon\Carbon;
use Dcat\Admin\Admin;
use Dcat\Admin\Form;
use Dcat\Admin\Grid;
use Dcat\Admin\Grid\Column;
use Dcat\Admin\Http\Controllers\AdminController;
use Dcat\Admin\Layout\Row;
use Dcat\Admin\Show;
use Dcat\Admin\Widgets\Box;
use Illuminate\Http\Request;
class BargainActivityController extends AdminController
{
/**
* Make a grid builder.
*
* @return Grid
*/
protected function grid()
{
return Grid::make(new BargainActivity(), function (Grid $grid) {
$grid->column('id')->sortable();
$grid->column('name');
// $grid->column('description');
$grid->column('is_enable')
->if(function () {
return Admin::user()->can('dcat.admin.bargain_activities.edit');
})
->then(function (Column $column) {
$column->switch();
})
->else(function (Column $column) {
$column->bool();
});
// $grid->column('rules');
$grid->column('times');
// $grid->column('expire_hours');
$grid->column('start_at');
$grid->column('end_at');
$grid->column('created_at');
$grid->column('updated_at')->sortable();
//新增
if (Admin::user()->can('dcat.admin.bargain_activities.create')) {
$grid->disableCreateButton(false);
// $grid->enableDialogCreate();
}
$grid->actions(function (Grid\Displayers\Actions $actions) {
$actions->disableView(Admin::user()->cannot('dcat.admin.bargain_activities.show'));
$actions->disableDelete(Admin::user()->cannot('dcat.admin.bargain_activities.destroy'));
//修改
$actions->disableEdit(Admin::user()->cannot('dcat.admin.bargain_activities.edit'));
});
$grid->filter(function (Grid\Filter $filter) {
$filter->panel();
$filter->like('name')->width(3);
});
});
}
/**
* Make a show builder.
*
* @param mixed $id
*
* @return Show
*/
protected function detail($id)
{
return function (Row $row) use ($id) {
$activity = BargainActivityModel::with(['skus'])->findOrFail($id);
$row->column(6, function ($column) use ($activity) {
$column->row(Show::make($activity, function (Show $show) use ($activity) {
$show->panel()
->tools(function ($tools) {
$tools->disableEdit(Admin::user()->cannot('dcat.admin.bargain_activities.edit'));
// $tools->disableList();
$tools->disableDelete(Admin::user()->cannot('dcat.admin.bargain_activities.destroy'));
});
$show->row(function (Show\Row $show) use ($activity) {
$show->field('id')->width(10, 1);
$show->field('name')->width(10, 1);
$show->field('is_enable')->using([0=>'未开启', '已开启'])->dot([
'0'=>'#b3b9bf',
'1'=>'success',
])->width(10, 1);
$show->width(6)->field('start_at');
$show->width(6)->field('end_at');
$show->width(6)->field('times')->append('刀');
$show->width(6)->field('expire_hours')->append('h');
$show->width(12)->field('skus')->width(10, 1)->as(function ($value) {
return array_column($value, 'name');
})->label();
$show->field('images')->image()->width(10, 1);
$show->field('description')->unescape()->width(10, 1);
$show->width(6)->field('created_at');
$show->width(6)->field('updated_at');
});
}));
});
$row->column(6, function ($column) use ($activity) {
//砍价记录
$builder = BargainOrder::where('activity_id', $activity->id)->with(['userInfo']);
$bargainOrderGrid = Grid::make($builder, function (Grid $grid) {
$grid->column('id', '序号');
$grid->column('infos', '明细')->display(function () {
return '【'.$this->userInfo->nickname.'】'.$this->created_at->format('Y-m-d H:i:s').'发起了砍价';
})->link(function () {
return admin_route('bargain_orders.show', ['bargain_order' =>$this->id]);
});
$grid->model()->orderBy('created_at', 'desc');
$grid->disableActions();
$grid->disableRefreshButton();
});
$bargainOrderBox = Box::make('砍价记录', $bargainOrderGrid);
$column->row($bargainOrderBox->collapsable());
});
};
}
/**
* Make a form builder.
*
* @return Form
*/
protected function form()
{
$builder = BargainActivity::with(['skus']);
return Form::make($builder, function (Form $form) {
$form->display('id');
$form->display('created_at');
$form->display('updated_at');
$form->block(6, function (Form\BlockForm $form) {
$form->text('name')->required();
$form->switch('is_enable');
$form->datetimeRange('start_at', 'end_at', '活动时间')->required();
$form->multipleSelectTable('skus')
->from(ProductSkuSimpleTable::make())
->model(ProductSku::class, 'id', 'name')
->customFormat(function ($v) {
if (!$v) {
return [];
}
// 这一步非常重要,需要把数据库中查出来的二维数组转化成一维数组
return array_column($v, 'id');
})->required();
$form->number('times')->min(0);
$form->number('expire_hours')->min(0);
$form->textarea('rules')->customFormat(function ($value) {
return implode(',', json_decode($value));
})->saving(function ($value) {
// dd($value, explode(',', $value));
return json_encode(explode(',', $value));
});
$form->text('share_title', '分享文案')->placeholder('默认使用活动名称');
$form->image('share_image', '分享图')
->move('bargain/share/'.Carbon::now()->toDateString())
->saveFullUrl()
->autoUpload()
->retainable()
->removable(false)->required();
$form->showFooter();
});
$form->block(6, function (Form\BlockForm $form) {
$form->multipleImage('images')
->move('bargain/images/'.Carbon::now()->toDateString())
->saveFullUrl()
->removable(false)
->autoUpload()->retainable()->sortable();
$form->editor('description')->height('600');
});
$form->saving(function ($form) {
if ($form->is_enable) {
//查询是否有除了自己以外开启的活动
if ($form->model()->id) {
if (BargainActivityModel::where('id', '<>', $form->model()->id)->isEnable()->exists()) {
return $form->response()->error('当前已有开启的活动');
}
} else {
if (BargainActivityModel::isEnable()->exists()) {
return $form->response()->error('当前已有开启的活动');
}
}
}
});
});
}
public function activities(Request $request)
{
$name = $request->input('q');
$query = BargainActivityModel::select('id', 'name as text');
if ($name) {
$query->where('name', 'like', "%$name%");
return $query->paginate(null);
}
return response()->json($query->get());
}
}

View File

@ -0,0 +1,180 @@
<?php
namespace App\Admin\Controllers;
use App\Admin\Actions\Show\BargainOrderRemark;
use App\Admin\Renderable\Grid\Filter\BargainOrderSnIn;
use App\Admin\Repositories\BargainOrder;
use App\Models\BargainOrder as BargainOrderModel;
use App\Models\BargainOrderLog;
use Dcat\Admin\Admin;
use Dcat\Admin\Form;
use Dcat\Admin\Grid;
use Dcat\Admin\Http\Controllers\AdminController;
use Dcat\Admin\Layout\Row;
use Dcat\Admin\Show;
use Dcat\Admin\Widgets\Box;
class BargainOrderController extends AdminController
{
/**
* Make a grid builder.
*
* @return Grid
*/
protected function grid()
{
$builder = BargainOrder::with(['activity', 'user', 'userInfo', 'mallOrder', 'sku']);
return Grid::make($builder, function (Grid $grid) {
$grid->column('id')->sortable();
$grid->column('activity.name');
$grid->column('user.phone');
$grid->column('userInfo.nickname');
$grid->column('sku.name');
$grid->column('sku_price')->display(function ($v) {
return bcdiv($v, 100, 2);
})->prepend('¥');
$grid->column('bargain_price')->display(function ($v) {
return bcdiv($v, 100, 2);
})->prepend('¥');
$grid->column('status')->using([
0=>'未开始',
1=>'砍价中',
2=>'已砍完',
])->dot([
0=>'primary',
1=>'warning',
2=>'success',
]);
$grid->column('expire_at');
$grid->column('mallOrder.sn')->filter(BargainOrderSnIn::make([
0 => '未下单',
1 => '已下单',
]));
// $grid->column('remark');
$grid->column('created_at');
$grid->column('updated_at')->sortable();
$grid->model()->orderBy('id', 'desc');
$grid->actions(function (Grid\Displayers\Actions $actions) {
if (Admin::user()->can('dcat.admin.bargain_orders.show')) {
$actions->append('<a style="cursor: pointer;" target="_blank" href="'.admin_route('bargain_orders.show', ['bargain_order'=>$actions->row]).'"><i class="feather icon-eye"></i> 显示 &nbsp;&nbsp;</a>');
}
});
$grid->filter(function (Grid\Filter $filter) {
$filter->panel();
$filter->equal('activity_id')->select()->ajax(admin_route('api.bargain_activities'))->width(3);
$filter->equal('sku_id')->select()->ajax(admin_route('api.product_skus'))->width(3);
$filter->like('mallOrder.sn')->width(3);
$filter->between('created_at')->dateTime()->width(7);
$filter->like('user.phone')->width(3);
});
});
}
/**
* Make a show builder.
*
* @param mixed $id
*
* @return Show
*/
protected function detail($id)
{
return function (Row $row) use ($id) {
$order = BargainOrderModel::with(['activity', 'user', 'userInfo', 'mallOrder', 'sku'])->find($id);
$row->column(6, function ($column) use ($order) {
$column->row(Show::make($order, function (Show $show) {
$show->row(function (Show\Row $show) {
$show->field('id')->width(10, 1);
$show->width(6)->field('user.phone');
$show->field('user_info.nickname', '昵称');
$show->field('activity.name');
$show->field('sku.name');
$show->field('sku_price')->as(function ($v) {
return bcdiv($v, 100, 2);
})->prepend('¥');
$show->field('bargain_price')->as(function ($v) {
return bcdiv($v, 100, 2);
})->prepend('¥');
$show->field('status')->using([
0=>'未开始',
1=>'砍价中',
2=>'已砍完',
])->dot([
0=>'primary',
1=>'warning',
2=>'success',
]);
$show->field('mall_order.sn', '关联订单编号')->unescape()->as(function ($value) {
if (Admin::user()->can('dcat.admin.orders.show') && !empty($value)) {
return '<a href="'.admin_route('orders.show', ['order'=>$this->mallOrder]).'" target="_blank">'.$value.'</a>';
}
return $value;
});
$show->field('expire_at');
$show->field('created_at');
$show->width(12)->field('remark')->width(10, 1);
});
$show->panel()
->tools(function (Show\Tools $tools) {
$tools->disableEdit();
$tools->disableDelete();
$tools->prepend(new BargainOrderRemark());
});
}));
});
$row->column(6, function ($column) use ($id) {
// 砍价日志列表
$builder = BargainOrderLog::where('order_id', $id)->with(['user', 'userInfo']);
$logGrid = Grid::make($builder, function (Grid $grid) {
// $grid->column('id', '序号');
$grid->column('user.phone');
$grid->column('userInfo.nickname');
// $grid->column('userInfo.avatar');
$grid->column('bargain_amount', '砍一刀')->display(function ($v) {
return bcdiv($v, 100, 2);
})->prepend('¥');
$grid->column('created_at');
$grid->model()->orderBy('created_at', 'desc');
$grid->disablePagination();
$grid->disableActions();
$grid->disableRefreshButton();
});
$logBox = Box::make('砍价记录', $logGrid);
$column->row($logBox->collapsable());
});
};
}
/**
* Make a form builder.
*
* @return Form
*/
protected function form()
{
return Form::make(new BargainOrder(), function (Form $form) {
$form->display('id');
$form->text('activity_id');
$form->text('user_id');
$form->text('sku_id');
$form->text('sku_price');
$form->text('bargain_price');
$form->text('status');
$form->text('expire_at');
$form->text('order_id');
$form->text('remark');
$form->display('created_at');
$form->display('updated_at');
});
}
}

View File

@ -40,6 +40,9 @@ class DealerPurchaseLogController extends AdminController
$user = User::where('phone', $phone)->first();
if ($user) {
$grid->model()->where('path', 'like', '%-'.$user->id.'-%');
} else {
//不存的手机号查询数据置为空
$grid->model()->where('id', 0);
}
}
$grid->model()->orderBy('id', 'desc');//默认ID倒叙

View File

@ -6,6 +6,7 @@ use App\Admin\Actions\Grid\Exports\DealerWalletWithdraw;
use App\Admin\Actions\Show\DealerWalletPay;
use App\Admin\Actions\Show\DealerWalletRefuse;
use App\Admin\Repositories\DealerWalletToBankLog;
use App\Enums\DealerWalletToBankLogStatus;
use App\Models\DealerWalletToBankLog as DealerWalletToBankLogModel;
use Box\Spout\Writer\Common\Creator\WriterEntityFactory;
use Dcat\Admin\Admin;
@ -14,6 +15,7 @@ use Dcat\Admin\Grid;
use Dcat\Admin\Http\Controllers\AdminController;
use Dcat\Admin\Show;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
class DealerWalletToBankLogController extends AdminController
{
@ -35,19 +37,16 @@ class DealerWalletToBankLogController extends AdminController
$grid->column('rate')->append('%');
$grid->column('service_amount')->prepend('¥');
$grid->column('account_amount')->prepend('¥');
$grid->column('status')->using([
DealerWalletToBankLogModel::STATUS_PENDING=>'待处理',
DealerWalletToBankLogModel::STATUS_AGREE=>'同意',
DealerWalletToBankLogModel::STATUS_REFUSE=>'拒绝',
])->dot([
0=>'primary',
1=>'success',
2=>'danger',
])->filter(Grid\Column\Filter\In::make([
DealerWalletToBankLogModel::STATUS_PENDING=>'待处理',
DealerWalletToBankLogModel::STATUS_AGREE=>'同意',
DealerWalletToBankLogModel::STATUS_REFUSE=>'拒绝',
]));
$grid->column('status')->display(function ($v) {
$text = $v->text();
$background = $v->color();
return "<i class='fa fa-circle' style='font-size: 13px;color: {$background}'></i>&nbsp;&nbsp;{$text}";
})->filter(Grid\Column\Filter\In::make(Arr::except(DealerWalletToBankLogStatus::texts(), [
DealerWalletToBankLogStatus::Failed->value,
DealerWalletToBankLogStatus::Passed->value,
DealerWalletToBankLogStatus::Paying->value,
])));
$grid->column('remarks');
$grid->column('created_at')->sortable();
// $grid->column('updated_at')
@ -62,11 +61,6 @@ class DealerWalletToBankLogController extends AdminController
$grid->filter(function (Grid\Filter $filter) {
$filter->panel();
// $filter->equal('status')->select([
// DealerWalletToBankLogModel::STATUS_PENDING=>'待处理',
// DealerWalletToBankLogModel::STATUS_AGREE=>'已同意',
// DealerWalletToBankLogModel::STATUS_REFUSE=>'已拒绝',
// ])->width(3);
$filter->equal('user.phone')->width(3);
$filter->between('created_at')->dateTime()->width(7);
});
@ -90,17 +84,17 @@ class DealerWalletToBankLogController extends AdminController
$show->field('rate')->append('%');
$show->field('service_amount')->prepend('¥');
$show->field('account_amount')->prepend('¥');
$show->field('status')->using([
DealerWalletToBankLogModel::STATUS_PENDING=>'待处理',
DealerWalletToBankLogModel::STATUS_AGREE=>'同意',
DealerWalletToBankLogModel::STATUS_REFUSE=>'拒绝',
])->dot([
0=>'primary',
1=>'success',
2=>'danger',
]);
$show->field('status')->unescape()->as(function ($v) {
$text = $this->status->text();
$background = $this->status->color();
return "<i class='fa fa-circle' style='font-size: 13px;color: {$background}'></i>&nbsp;&nbsp;{$text}";
});
$show->field('pay_image')->image();
$show->field('remarks');
if ($show->model()->isFailed()) {
$show->field('failed_reason');
}
$show->divider('收款信息-银行');
$show->field('bank_user_name', '银行-收款人')->as(function () {
$payInfo = $this->getPayInfo();
@ -150,7 +144,8 @@ class DealerWalletToBankLogController extends AdminController
->tools(function (Show\Tools $tools) use ($show) {
$tools->disableEdit();
$tools->disableDelete();
if ($show->model()->isPending() && Admin::user()->can('dcat.admin.dealer_wallet_to_bank_logs.verify')) {
if (in_array($show->model()->status, [DealerWalletToBankLogStatus::Pending, DealerWalletToBankLogStatus::Failed]) && Admin::user()->can('dcat.admin.dealer_wallet_to_bank_logs.verify')) {
$tools->append(new DealerWalletRefuse());
$tools->append(new DealerWalletPay());
}
@ -214,17 +209,13 @@ class DealerWalletToBankLogController extends AdminController
break;
}
}
$statusArr = [
DealerWalletToBankLogModel::STATUS_PENDING=>'待处理',
DealerWalletToBankLogModel::STATUS_AGREE=>'同意',
DealerWalletToBankLogModel::STATUS_REFUSE=>'拒绝',
];
foreach ($query->cursor() as $log) {
$payInfo = $log->getPayInfo();
$writer->addRow(WriterEntityFactory::createRowFromArray([
$log->user->phone,
$log->account_amount,
$statusArr[$log->status],
$log->status->text(),
$payInfo ? $payInfo['bank']['user_name'] : '',
$payInfo ? $payInfo['bank']['bank_name'] : '',
$payInfo ? $payInfo['bank']['bank_number'] : '',

View File

@ -4,6 +4,7 @@ namespace App\Admin\Controllers;
use App\Admin\Widgets\InfoBox;
use App\Enums\PayWay;
use App\Enums\WalletToBankLogStatus;
use App\Http\Controllers\Controller;
use App\Models\Order;
use App\Models\WalletLog;
@ -65,7 +66,7 @@ class MonthlyStatisticsController extends Controller
->sum('change_balance');
// 提现总额
$withdrawAmount = WalletToBankLog::where('status', WalletToBankLog::STATUS_AGREE)
$withdrawAmount = WalletToBankLog::where('status', WalletToBankLogStatus::Success)
->whereBetween('updated_at', [$start, $end])
->sum('amount');

View File

@ -281,6 +281,9 @@ class OrderController extends AdminController
$show->field('reduced_amount')->as(function ($v) {
return bcdiv($v, 100, 2);
})->prepend('- ¥');
$show->field('bargain_amount')->as(function ($v) {
return bcdiv($v, 100, 2);
})->prepend('- ¥');
$show->field('total_amount')->as(function ($v) {
return bcdiv($v, 100, 2);
})->prepend('¥');
@ -342,6 +345,12 @@ class OrderController extends AdminController
$grid->column('coupon_discount_amount', '优惠券折扣')->display(function ($value) {
return bcdiv($value, 100, 2);
})->prepend('¥');
$grid->column('reduced_amount', '减免金额')->display(function ($value) {
return bcdiv($value, 100, 2);
})->prepend('¥');
$grid->column('bargain_amount', '砍价优惠')->display(function ($value) {
return bcdiv($value, 100, 2);
})->prepend('¥');
$grid->column('sales_value', '销售值');
$grid->column('remain_quantity');

View File

@ -4,12 +4,13 @@ namespace App\Admin\Controllers;
use App\Admin\Actions\Grid\WalletToBankLogVerify;
use App\Admin\Repositories\WalletToBankLog;
use App\Models\WalletToBankLog as WalletToBankLogModel;
use App\Enums\WalletToBankLogStatus;
use Dcat\Admin\Admin;
use Dcat\Admin\Form;
use Dcat\Admin\Grid;
use Dcat\Admin\Http\Controllers\AdminController;
use Dcat\Admin\Show;
use Illuminate\Support\Arr;
class WalletToBankLogController extends AdminController
{
@ -37,15 +38,12 @@ class WalletToBankLogController extends AdminController
$grid->column('account_amount')->display(function ($v) {
return bcdiv($v, 100, 2);
})->prepend('¥');
$grid->column('status')->using([
WalletToBankLogModel::STATUS_PENDING=>'待处理',
WalletToBankLogModel::STATUS_AGREE=>'同意',
WalletToBankLogModel::STATUS_REFUSE=>'拒绝',
])->dot([
0=>'primary',
1=>'success',
2=>'danger',
]);
$grid->column('status')->display(function ($v) {
$text = $v->text();
$background = $v->color();
return "<i class='fa fa-circle' style='font-size: 13px;color: {$background}'></i>&nbsp;&nbsp;{$text}";
});
$grid->column('remarks');
$grid->column('created_at')->sortable();
@ -54,18 +52,20 @@ class WalletToBankLogController extends AdminController
$grid->model()->orderBy('created_at', 'desc');
$grid->actions(function (Grid\Displayers\Actions $actions) {
if ($actions->row->status == 0 && Admin::user()->can('dcat.admin.wallet_to_bank_logs.verify')) {
if (in_array($actions->row->status, [WalletToBankLogStatus::Pending, WalletToBankLogStatus::Failed]) && Admin::user()->can('dcat.admin.wallet_to_bank_logs.verify')) {
$actions->append(new WalletToBankLogVerify());
}
});
$grid->filter(function (Grid\Filter $filter) {
$filter->panel();
$filter->equal('status')->select([
WalletToBankLogModel::STATUS_PENDING=>'待处理',
WalletToBankLogModel::STATUS_AGREE=>'已同意',
WalletToBankLogModel::STATUS_REFUSE=>'已拒绝',
])->width(3);
$filter->equal('status')
->select(Arr::except(WalletToBankLogStatus::texts(), [
WalletToBankLogStatus::Passed->value,
WalletToBankLogStatus::Paying->value,
WalletToBankLogStatus::Failed->value,
]))
->width(3);
$filter->equal('user.phone')->width(3);
$filter->equal('username')->width(3);
$filter->between('created_at')->dateTime()->width(7);

View File

@ -0,0 +1,61 @@
<?php
namespace App\Admin\Forms;
use App\Models\BargainOrder;
use Dcat\Admin\Contracts\LazyRenderable;
use Dcat\Admin\Traits\LazyWidget;
use Dcat\Admin\Widgets\Form;
class BargainOrderRemark extends Form implements LazyRenderable
{
use LazyWidget;
/**
* 权限判断,如不需要可以删除此方法
*
* @param Model|Authenticatable|HasPermissions|null $user
*
* @return bool
*/
protected function authorize($user): bool
{
return $user->can('dcat.admin.bargain_orders.remark');
}
/**
* Handle the form request.
*
* @param array $input
*
* @return mixed
*/
public function handle(array $input)
{
$orderId = $this->payload['id'] ?? 0;
$order = BargainOrder::findOrFail($orderId);
$remark = $input['remark'] ?? '';
$order->update([
'remark'=>$remark,
]);
return $this->response()
->success(__('admin.update_succeeded'))
->refresh();
}
/**
* Build a form here.
*/
public function form()
{
$orderId = $this->payload['id'] ?? 0;
$order = BargainOrder::findOrFail($orderId);
$this->text('remark')->value($order->remark);
$this->disableResetButton();
}
}

View File

@ -2,6 +2,9 @@
namespace App\Admin\Forms;
use App\Enums\DealerWalletToBankLogPayWay;
use App\Enums\DealerWalletToBankLogStatus;
use App\Exceptions\BizException;
use App\Models\DealerWalletToBankLog;
use Carbon\Carbon;
use Dcat\Admin\Contracts\LazyRenderable;
@ -37,12 +40,25 @@ class DealerWalletPay extends Form implements LazyRenderable
try {
DB::beginTransaction();
$log = DealerWalletToBankLog::findOrFail($id);
$log->update([
'pay_info' => $log->getPayInfo(),
'pay_image' => $input['pay_image']??null,
'status' => DealerWalletToBankLog::STATUS_AGREE,
]);
$log = DealerWalletToBankLog::lockForUpdate()->findOrFail($id);
if (! in_array($log->status, [DealerWalletToBankLogStatus::Pending, DealerWalletToBankLogStatus::Failed])) {
throw new BizException('提现记录状态异常');
}
$log->pay_info = $log->user->dealer->pay_info;
$log->pay_image = $input['pay_image'] ?? null;
$log->pay_way = $input['pay_way'];
if ($log->pay_way == DealerWalletToBankLogPayWay::Offline) {
$log->pay_at = now();
$log->status = DealerWalletToBankLogStatus::Success;
} else {
$log->pay_sn = serial_number();
$log->status = DealerWalletToBankLogStatus::Passed;
}
$log->save();
DB::commit();
} catch (Throwable $th) {
DB::rollBack();
@ -60,6 +76,10 @@ class DealerWalletPay extends Form implements LazyRenderable
*/
public function form()
{
$this->hidden('pay_way')->value(DealerWalletToBankLogPayWay::Offline->value);
// $this->select('pay_way')
// ->options(DealerWalletToBankLogPayWay::texts())
// ->required();
$this->image('pay_image')
->move('dealer-pay/'.Carbon::now()->toDateString())
->saveFullUrl()

View File

@ -3,6 +3,7 @@
namespace App\Admin\Forms;
use App\Enums\DealerWalletAction;
use App\Enums\DealerWalletToBankLogStatus;
use App\Models\DealerWalletToBankLog;
use App\Services\Dealer\WalletService;
use Dcat\Admin\Contracts\LazyRenderable;
@ -40,8 +41,8 @@ class DealerWalletRefuse extends Form implements LazyRenderable
DB::beginTransaction();
$log = DealerWalletToBankLog::findOrFail($id);
$log->update([
'remark' => $input['remark']??'',
'status' => DealerWalletToBankLog::STATUS_REFUSE,
'remark' => $input['remark'] ?? '',
'status' => DealerWalletToBankLogStatus::Refused,
]);
//打回余额
$walletService = new WalletService();

View File

@ -2,6 +2,9 @@
namespace App\Admin\Forms;
use App\Enums\WalletToBankLogPayWay;
use App\Enums\WalletToBankLogStatus;
use App\Exceptions\BizException;
use App\Models\WalletLog;
use App\Models\WalletToBankLog;
use App\Services\WalletService;
@ -34,15 +37,37 @@ class WalletToBankLogVerify extends Form implements LazyRenderable
*/
public function handle(array $input)
{
$id = $this->payload['id'] ?? 0;
$log = WalletToBankLog::findOrFail($id);
try {
DB::beginTransaction();
$log->update($input);
//如果拒绝,重新添加对应可提金额
if ($log->status == 2) {
$walletService = new WalletService();
$walletService->changeBalance($log->user, $log->amount, WalletLog::ACTION_WITHDRAW_FAILED, '提现-失败', $log);
$log = WalletToBankLog::lockForUpdate()->findOrFail($this->payload['id']);
if (! in_array($log->status, [WalletToBankLogStatus::Pending, WalletToBankLogStatus::Failed])) {
throw new BizException('提现记录状态异常');
}
if ($input['status'] == 1) {
$log->pay_way = $input['pay_way'];
if ($log->pay_way === WalletToBankLogPayWay::Offline) {
$log->status = WalletToBankLogStatus::Success;
$log->pay_at = now();
} else {
$log->pay_sn = serial_number();
$log->status = WalletToBankLogStatus::Passed;
}
$log->failed_reason = null;
} else {
$log->status = WalletToBankLogStatus::Refused;
}
$log->remarks = $input['remarks'];
$log->save();
// 如果拒绝,退换扣除金额
if ($log->status === WalletToBankLogStatus::Refused) {
(new WalletService())->changeBalance($log->user, $log->amount, WalletLog::ACTION_WITHDRAW_FAILED, '提现-失败', $log);
}
DB::commit();
@ -65,7 +90,6 @@ class WalletToBankLogVerify extends Form implements LazyRenderable
$id = $this->payload['id'] ?? 0;
$log = WalletToBankLog::findOrFail($id);
$this->text('bank_name')->value($log->bank_name)->disable();
$this->text('bank_number')->value($log->bank_number)->disable();
$this->text('username')->value($log->username)->disable();
@ -75,10 +99,20 @@ class WalletToBankLogVerify extends Form implements LazyRenderable
$this->currency('service_amount')->symbol('¥')->value(bcdiv($log->service_amount, 100, 2))->disable();
$this->currency('account_amount')->symbol('¥')->value(bcdiv($log->account_amount, 100, 2))->disable();
$this->radio('status')->options([
1 => '成功',
2 => '拒绝',
])->default(1);
if ($log->status === WalletToBankLogStatus::Failed) {
$this->textarea('failed_reason')->value($log->failed_reason ?: '')->disable();
}
$this->radio('status')
->options([
1 => '通过',
2 => '拒绝',
])
->default(1);
$this->hidden('pay_way')->value(WalletToBankLogPayWay::Offline->value);
// $this->select('pay_way')
// ->options(WalletToBankLogPayWay::texts())
// ->rules('required_if:status,1', ['required_if'=>'请选择支付方式']);
$this->text('remarks')->rules('required_if:status,2', ['required_if'=>'拒绝时需要填写备注']);
}
}

View File

@ -0,0 +1,74 @@
<?php
namespace App\Admin\Renderable\Grid\Filter;
use Dcat\Admin\Grid\Column\Filter;
use Dcat\Admin\Grid\Column\Filter\Checkbox;
use Dcat\Admin\Grid\Model;
class BargainOrderSnIn extends Filter
{
use Checkbox;
/**
* @var array
*/
protected $options = [];
/**
* CheckFilter constructor.
*
* @param array $options
*/
public function __construct(array $options)
{
$this->options = $options;
$this->class = [
'all' => uniqid('column-filter-all-'),
'item' => uniqid('column-filter-item-'),
];
}
/**
* Add a binding to the query.
*
* @param array $value
* @param Model $model
*/
public function addBinding($value, Model $model)
{
if (empty($value)) {
return;
}
$all = [0, 1];
if (array_diff($all, $value)) {//无差别则直接跳过
//判断查询的状态有哪些;
$model->where(function ($query) use ($value) {
foreach ($value as $status) {
switch ($status) {
case 0:
$query->orWhere(function ($q) {
return $q->whereNull('order_id')->orWhere('order_id', 0);
});
break;
case 1:
$query->orWhereNotNull('order_id');
break;
}
}
});
}
}
/**
* Render this filter.
*
* @return string
*/
public function render()
{
return $this->renderCheckbox();
}
}

View File

@ -0,0 +1,16 @@
<?php
namespace App\Admin\Repositories;
use App\Models\BargainActivity as Model;
use Dcat\Admin\Repositories\EloquentRepository;
class BargainActivity extends EloquentRepository
{
/**
* Model.
*
* @var string
*/
protected $eloquentClass = Model::class;
}

View File

@ -0,0 +1,16 @@
<?php
namespace App\Admin\Repositories;
use App\Models\BargainOrder as Model;
use Dcat\Admin\Repositories\EloquentRepository;
class BargainOrder extends EloquentRepository
{
/**
* Model.
*
* @var string
*/
protected $eloquentClass = Model::class;
}

View File

@ -19,13 +19,48 @@ class OrderService
public function adminReduceOrder(Order $order, int $reduceAmount)
{
if ($order->isPending()) {
$needReduceAmount = $order->total_amount - $reduceAmount + $order->reduced_amount;
$res = $order->where('updated_at', $order->updated_at)->update([
'reduced_amount' => $order->total_amount - $reduceAmount + $order->reduced_amount,
'reduced_amount' => $needReduceAmount,
'total_amount' => $reduceAmount,
]);
if ($res === 0) {
throw new BizException('订单已发生改变');
}
//更新订单商品优惠金额
//分解到订单中除赠品外的商品
$orderProducts = $order->products;
$needReduceOrderProducts = [];
$totalAmount = 0;
foreach ($orderProducts as $orderProduct) {
if (!$orderProduct->isGift()) {
$needReduceOrderProducts[] = $orderProduct;
$totalAmount += $orderProduct->total_amount;
}
}
$i = count($needReduceOrderProducts);
foreach ($needReduceOrderProducts as $reduceOrderProduct) {
$i --;
if ($i > 0) {
$amount = (int) bcdiv(bcmul($needReduceAmount, $reduceOrderProduct->total_amount, 0), $totalAmount, 2);
$needReduceAmount -= $amount;
$totalAmount -= $reduceOrderProduct->total_amount;
} else {
$amount = $needReduceAmount;
}
$newTotalAmount = $reduceOrderProduct->total_amount + $reduceOrderProduct->reduced_amount - $amount;
//更新订单商品的金额
$reduceOrderProduct->update([
'reduced_amount' => $amount,
'total_amount'=> $newTotalAmount,
]);
}
OrderLog::create([
'order_id'=>$order->id,
'content'=> '调整订单支付价格为:¥'.bcdiv($reduceAmount, 100, 2),

View File

@ -214,6 +214,11 @@ Route::group([
$router->get('dealer-delivery-bills', 'DealerDeliveryBillController@index')->name('dealer_delivery_bills.index');
$router->get('dealer-delivery-bills/{dealer_delivery_bill}', 'DealerDeliveryBillController@show')->name('dealer_delivery_bills.show');
//商城端-砍价活动
$router->resource('bargain-activities', 'BargainActivityController')->names('bargain_activities');
$router->resource('bargain-orders', 'BargainOrderController')->only(['index', 'show'])->names('bargain_orders');
/** api接口 **/
$router->get('api/product-categories', 'ProductCategoryController@categories')->name('api.product_categories');
$router->get('api/product-group-details', 'ProductGroupController@details')->name('api.product_group_details');
@ -224,6 +229,7 @@ Route::group([
$router->get('api/orders', 'OrderController@orders')->name('api.orders');
$router->get('api/order-products', 'OrderController@orderProducts')->name('api.order_products');
$router->get('api/users', 'UserController@users')->name('api.users');
$router->get('api/bargain-activities', 'BargainActivityController@activities')->name('api.bargain_activities');
/** 调试接口 **/
// $router->get('test', 'HomeController@test');

View File

@ -0,0 +1,92 @@
<?php
namespace App\Console\Commands\Dealer;
use App\Enums\Bank;
use App\Enums\DealerWalletToBankLogStatus;
use App\Exceptions\YeePayException;
use App\Models\DealerWalletToBankLog;
use App\Services\YeePayService;
use Illuminate\Console\Command;
use Throwable;
class WalletToBankCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'dealer:wallet-to-bank';
/**
* The console command description.
*
* @var string
*/
protected $description = '批零提现';
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$yeePayService = new YeePayService(config('services.yeepay'));
while (true) {
DealerWalletToBankLog::where('status', DealerWalletToBankLogStatus::Passed)->chunkById(1, function ($logs) use ($yeePayService) {
foreach ($logs as $log) {
try {
$result = $yeePayService->request('accountpay.behalf.Pay', [
'payerOutUserId' => '21102510220227100003' ?: config('services.yeepay.partner_id'),
'merchOrderNo' => $log->pay_sn,
'tradeName' => '批零提现',
'payeeUserName' => data_get($log->pay_info, 'bank.user_name'),
'bankCardNo' => data_get($log->pay_info, 'bank.bank_number'),
'bankCode' => Bank::tryFromBankName(data_get($log->pay_info, 'bank.bank_name'))?->name,
'bankCardType' => 'DEBIT_CARD',
'amount' => $log->account_amount,
'feeRole' => 'PAYER',
'tradeMemo' => '批零提现',
'context' => json_encode(['type' => 'dealer_wallet_to_bank']),
]);
// 如果交易超时,重新发起支付
if ($result['resultCode'] === 'TIME_OUT') {
continue;
}
if ($result['orderStatus'] === 'SUCCESS') {
$log->update([
'status' => DealerWalletToBankLogStatus::Success,
'pay_at' => now(),
'failed_reason' => null,
]);
} elseif ($result['orderStatus'] === 'FAIL') {
$log->update([
'status' => DealerWalletToBankLogStatus::Failed,
'failed_reason' => '交易失败',
]);
} else {
$log->update([
'status' => DealerWalletToBankLogStatus::Paying,
'failed_reason' => null,
]);
}
} catch (YeePayException $e) {
$log->update([
'status' => DealerWalletToBankLogStatus::Failed,
'failed_reason' => $e->getMessage(),
]);
} catch (Throwable $e) {
throw $e;
}
}
});
sleep(60);
}
}
}

View File

@ -0,0 +1,92 @@
<?php
namespace App\Console\Commands;
use App\Enums\Bank;
use App\Enums\WalletToBankLogStatus;
use App\Exceptions\YeePayException;
use App\Models\WalletToBankLog;
use App\Services\YeePayService;
use Illuminate\Console\Command;
use Throwable;
class WalletToBankCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'wallet-to-bank';
/**
* The console command description.
*
* @var string
*/
protected $description = '可提提现';
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$yeePayService = new YeePayService(config('services.yeepay'));
while (true) {
WalletToBankLog::where('status', WalletToBankLogStatus::Passed)->chunkById(1, function ($logs) use ($yeePayService) {
foreach ($logs as $log) {
try {
$result = $yeePayService->request('accountpay.behalf.Pay', [
'payerOutUserId' => '21102510220227100003' ?: config('services.yeepay.partner_id'),
'merchOrderNo' => $log->pay_sn,
'tradeName' => '余额提现',
'payeeUserName' => $log->username,
'bankCardNo' => $log->bank_number,
'bankCode' => Bank::tryFromBankName($log->bank_name)?->name,
'bankCardType' => 'DEBIT_CARD',
'amount' => bcdiv($log->account_amount, 100, 2),
'feeRole' => 'PAYER',
'tradeMemo' => '商城余额提现',
'context' => json_encode(['type' => 'wallet_to_bank']),
]);
// 如果交易超时,重新发起支付
if ($result['resultCode'] === 'TIME_OUT') {
continue;
}
if ($result['orderStatus'] === 'SUCCESS') {
$log->update([
'status' => WalletToBankLogStatus::Success,
'pay_at' => now(),
'failed_reason' => null,
]);
} elseif ($result['orderStatus'] === 'FAIL') {
$log->update([
'status' => WalletToBankLogStatus::Failed,
'failed_reason' => '交易失败',
]);
} else {
$log->update([
'status' => WalletToBankLogStatus::Paying,
'failed_reason' => null,
]);
}
} catch (YeePayException $e) {
$log->update([
'status' => WalletToBankLogStatus::Failed,
'failed_reason' => $e->getMessage(),
]);
} catch (Throwable $e) {
throw $e;
}
}
});
sleep(60);
}
}
}

View File

@ -2,11 +2,13 @@
namespace App\Endpoint\Api\Http\Controllers;
use App\Endpoint\Api\Http\Resources\ArticleCategoryResource;
use App\Endpoint\Api\Http\Resources\ArticleResource;
use App\Endpoint\Api\Http\Resources\ArticleSimpleResource;
use App\Exceptions\BizException;
use App\Helpers\Paginator as PaginatorHelper;
use App\Models\Article;
use App\Models\ArticleCategory;
use App\Models\ArticleLikesLog;
use App\Models\ArticlePointsLog;
use App\Models\PointsLog;
@ -50,7 +52,49 @@ class ArticleController extends Controller
], $cate);
$query = Article::query()->with(['likesInfo'=>function ($q) use ($request) {
$user_id = $request->user()?->id;
return $q->where('user_id', $user_id??0);
return $q->where('user_id', $user_id ?? 0);
}])->where('is_show', 1);
if ($categoryId) {
$query->where('category_id', $categoryId);
}
if ($key) {
$query->where('title', 'like', '%'.$key.'%');
}
$query->orderBy('is_recommend', 'desc');
$query->orderBy('sort', 'desc');
$query->orderBy('created_at', 'desc');
$list = $query->simplePaginate(PaginatorHelper::resolvePerPage('per_page', 20, 50));
return ArticleSimpleResource::collection($list);
}
public function healthCategory(Request $request)
{
$key = (string) $request->query('key');
$categoryId = app_settings('app.article_health');
$query = ArticleCategory::query()->where('parent_id', $categoryId)->where('is_show', 1);
if ($key) {
$query->where('name', 'like', '%'.$key.'%');
}
$query->orderBy('is_recommend', 'desc');
$query->orderBy('sort', 'desc');
$query->orderBy('created_at', 'desc');
$categories = $query->get();
return ArticleCategoryResource::collection($categories);
}
public function articleList($id, Request $request)
{
$key = (string) $request->query('key');
$categoryId = $id;
$query = Article::query()->with(['likesInfo'=>function ($q) use ($request) {
$user_id = $request->user()?->id;
return $q->where('user_id', $user_id ?? 0);
}])->where('is_show', 1);
if ($categoryId) {
$query->where('category_id', $categoryId);

View File

@ -0,0 +1,250 @@
<?php
namespace App\Endpoint\Api\Http\Controllers;
use App\Endpoint\Api\Http\Resources\BargainActivityResource;
use App\Endpoint\Api\Http\Resources\BargainOrderResource;
use App\Endpoint\Api\Http\Resources\OrderResource;
use App\Events\OrderPaid;
use App\Exceptions\BizException;
use App\Models\BargainActivity;
use App\Models\BargainOrder;
use App\Models\BargainSku;
use App\Models\ProductSku;
use App\Services\BargainService;
use App\Services\OrderService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Throwable;
class BargainController extends Controller
{
/**
*
*
* @param \Illuminate\Http\Request $request
* @return void
*/
public function activityDetail($id)
{
$activity = BargainActivity::with('skus')->findOrFail($id);
if (!$activity->is_enable) {
throw new BizException('砍价活动暂未开始');
}
if ($activity->start_at > now() || $activity->end_at < now()) {
throw new BizException('不在活动时间范围');
}
return BargainActivityResource::make($activity);
}
/**
* 通过砍价商品查看当前砍价记录
*
* @param [type] $id
* @param Request $request
* @return void
*/
public function bargainSku($id)
{
//判断商品是否参与砍价
$bargainSku = BargainSku::with(['activity'=>function ($query) {
return $query->where('is_enable', true)->where('start_at', '<=', now())->where('end_at', '>=', now());
}, 'sku'])->where('sku_id', $id)->first();
if (!($bargainSku && $bargainSku->activity)) {
throw new BizException('该商品未参与砍价活动,或者活动已结束');
}
return response()->json([
'sku' => [
'name' => (string) $bargainSku->sku->name,
'subtitle' => (string) $bargainSku->sku->subtitle,
'cover' => (string) $bargainSku->sku->cover,
'sell_price' => (string) $bargainSku->sku->sell_price_format,
'vip_price' => (string) $bargainSku->sku->vip_price_format,
],
'max_bargain_price'=> array_sum(json_decode($bargainSku->activity->rules)),
'activity_id' => $bargainSku->activity->id,
'activity_images' => $bargainSku->activity->images,
'activity_share_image'=> $bargainSku->activity->share_image,
'activity_share_title'=> $bargainSku->activity->share_title,
]);
}
/**
* 通过商品获取当前砍价进度(看自己的)
*
* @param Request $request
* @return void
*/
public function barginaOrderBySku($id, Request $request)
{
// $order = [];
$user = $request->user();
$userId = $user?->id ?? 0;
$order = BargainOrder::with(['logs', 'logs.userInfo'])
->where([
'sku_id' => $id,
'user_id'=> $userId,
])->where('status', '>', 0)
->where('expire_at', '>', now())
->whereNull('order_id')
->orderBy('created_at', 'desc')->first();
if ($order) {
return BargainOrderResource::make($order);
}
return response()->noContent();
}
/**
* 通过订单ID获取当前砍价进度看别人的
*
* @param Request $request
* @return void
*/
public function bargainOrderById($id, Request $request)
{
$order = BargainOrder::with(['logs', 'logs.userInfo'])
->where([
'id' => $id,
])->where('status', '>', 0)
->where('expire_at', '>', now())
->whereNull('order_id')
->orderBy('created_at', 'desc')->first();
if ($order) {
return BargainOrderResource::make($order);
}
return response()->noContent();
}
/**
* 发起砍价
*
* @param [type] $id
* @param Request $request
* @return void
*/
public function createBargainOrder(ProductSku $sku, Request $request)
{
if (!$sku->isBargaing()) {
throw new BizException('活动已结束');
}
//判断是否已经有正在进行的砍价单, 直接返回
$order = BargainOrder::where([
'sku_id' => $sku->id,
'user_id'=> $request->user()->id,
])->where('status', '>', 0)
->where('expire_at', '>', now())
->whereNull('order_id')
->orderBy('created_at', 'desc')->first();
if (!$order) {
//创建新的砍价单
$bargainService = new BargainService();
try {
DB::beginTransaction();
$order = $bargainService->createBargainOrder($request->user(), $sku);
DB::commit();
} catch (Throwable $th) {
DB::rollBack();
report($th);
throw new BizException($th->getMessage());
}
}
$order->load(['logs', 'logs.userInfo']);
return BargainOrderResource::make($order);
}
/**
* 帮人砍价
*
* @param BargainOrder $order
* @param Request $request
* @return void
*/
public function bargain(BargainOrder $order, Request $request)
{
$bargainService = new BargainService();
try {
DB::beginTransaction();
$bargainService->bargain($request->user(), $order);
DB::commit();
} catch (Throwable $th) {
DB::rollBack();
report($th);
throw new BizException($th->getMessage());
}
$order->load(['logs', 'logs.userInfo']);
return BargainOrderResource::make($order);
}
/**
* 通过砍价订单创建待支付商城订单
*
* @param BargainOrder $bargainOrder
* @param Request $request
* @return void
*/
public function createMallOrderByBargainOrder(BargainOrder $bargainOrder, Request $request)
{
$rules = [
'shipping_address_id' => ['bail', 'required', 'int'],
'note' => ['bail', 'nullable', 'string', 'max:255'],
];
$input = $request->validate($rules, [], [
'shipping_address_id' => '收货地址',
'note' => '订单备注',
]);
$user = $request->user();
if ($user->id != $bargainOrder->user_id) {
throw new BizException('您不能替别人下单');
}
$orderService = new OrderService();
try {
DB::beginTransaction();
$bargainOrder->lockForUpdate();//下单的时候不允许砍价了
//已下单
if ($bargainOrder->order_id > 0) {
throw new BizException('您已下单,无需重复下单');
}
//砍价超时
if ($bargainOrder->expire_at < now()) {
throw new BizException('当前砍价已结束,无法下单');
}
//如果砍价活动结束了,也不能砍了
$activity = $bargainOrder->sku->isBargaing();
if (!$activity) {
throw new BizException('当前砍价已结束,无法下单');
}
$order = $orderService->createQuickOrder(
$user,
$bargainOrder->sku_id,
1,
$input['shipping_address_id'],
null,
$input['note'] ?? null,
$bargainOrder
);
$bargainOrder->update([
'order_id' => $order->id,
]);
DB::commit();
} catch (Throwable $th) {
DB::rollBack();
report($th);
throw new BizException($th->getMessage());
}
OrderPaid::dispatchIf($order->isPaid(), $order);
return OrderResource::make($order);
}
}

View File

@ -20,6 +20,7 @@ class OrderVerifyController extends Controller
$rules = [
'coupon_id' => ['bail', 'nullable', 'int'],
'shipping_address_id' => ['bail', 'nullable', 'int'],
'baragain_order_id' => ['bail', 'nullable', 'int'],
];
// 快速下单
@ -40,6 +41,7 @@ class OrderVerifyController extends Controller
'product.quantity' => '数量',
'coupon_id' => '优惠券',
'shipping_address_id' => '收货地址',
'bargain_order_id'=> '砍价',
]);
$user = $request->user();
@ -52,6 +54,7 @@ class OrderVerifyController extends Controller
$request->input('product.quantity'),
$request->input('shipping_address_id'),
$request->input('coupon_id'),
$request->input('bargain_order_id'),
) : $orderService->verifyShoppingCartOrder(
$user,
$request->input('shopping_cart'),

View File

@ -3,6 +3,7 @@
namespace App\Endpoint\Api\Http\Controllers;
use App\Endpoint\Api\Http\Resources\UserBankResource;
use App\Enums\Bank;
use App\Models\UserBank;
use Illuminate\Http\Request;
@ -11,21 +12,7 @@ class UserBankController extends Controller
public function options(Request $request)
{
return response()->json([
'banks' => [
'中国建设银行',
'中国农业银行',
'中国工商银行',
'中国银行',
'交通银行',
'招商银行',
'民生银行',
'兴业银行',
'中信实业银行',
'上海浦东发展银行',
'光大银行',
'邮政储蓄银行',
'平安银行',
],
'banks' => array_values(Bank::banks()),
]);
}

View File

@ -0,0 +1,23 @@
<?php
namespace App\Endpoint\Api\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class ArticleCategoryResource 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 [
'id' => $this->id,
'name' => $this->name,
'cover' => $this->cover ?? '',
];
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace App\Endpoint\Api\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class BargainActivityResource 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 [
'name' => $this->name,
'images' => $this->images,
'description' => $this->description,
'skus' => ProductSkuSimpleResource::collection($this->whenLoaded('skus')),
'share_image'=> $this->share_image ?? '',
'share_title'=> $this->share_title ?? '',
'start_at' => $this->start_at->rawFormat('Y-m-d H:i:s'),
'end_at' => $this->end_at->rawFormat('Y-m-d H:i:s'),
];
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace App\Endpoint\Api\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class BargainOrderLogResource 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 [
'nickname'=> (string) $this->whenLoaded('userInfo', function () {
return $this->userInfo->nickname;
}, ''),
'avatar'=> (string) $this->whenLoaded('userInfo', function () {
return $this->userInfo->avatar;
}, ''),
'bargain_amount' => $this->bargain_amount_format,
'created_at' => $this->created_at->format('Y-m-d H:i:s'),
];
}
}

View File

@ -0,0 +1,29 @@
<?php
namespace App\Endpoint\Api\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class BargainOrderResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
*/
public function toArray($request)
{
$user = $request->user();
$userId = $user?->id ?? 0;
return [
'id' => $this->id,
'logs' => BargainOrderLogResource::collection($this->whenLoaded('logs')),
'expire_at'=> $this->expire_at->format('Y-m-d H:i:s'),
'status' => $this->status,
'user_nickname'=> $this->user->userInfo->nickname ?? '',
'user_avatar'=> $this->user->userInfo->avatar ?? '',
'is_owner' => $this->user_id == $userId ? true : false,
];
}
}

View File

@ -27,6 +27,7 @@ class OrderResource extends JsonResource
'coupon_discount_amount' => $this->coupon_discount_amount_format,
'vip_discount_amount' => $this->vip_discount_amount_format,
'reduced_amount' => $this->reduced_amount_format,
'bargain_amount' => $this->bargain_amount_format,
'shipping_fee' => $this->shipping_fee_format,
'products_total_amount' => $this->products_total_amount_format,
'total_amount' => $this->total_amount_format,

View File

@ -35,6 +35,7 @@ class ProduckSkuResource extends JsonResource
}),
'growth_value' => (int) $this->growth_value,
'sales_value' => (int) $this->sales_value,
'is_bargaing' => $this->isBargaing() ? true : false,
];
}
}

View File

@ -75,6 +75,8 @@ Route::group([
Route::get('product/search-hot-keys', [ProductSkuController::class, 'searchHotKeys']);
//文章列表
Route::get('articles', [ArticleController::class, 'index']);
Route::get('articles/health-category', [ArticleController::class, 'healthCategory']);
Route::get('articles/by-category/{category}', [ArticleController::class, 'articleList']);
//指定文章配置
Route::get('article-config', [ArticleController::class, 'config']);
@ -87,6 +89,13 @@ Route::group([
Route::get('configs', [SettingController::class, 'index']);
Route::get('configs-custom', [SettingController::class, 'custom']);
//砍价
Route::get('bargains/{activity}', [\App\Endpoint\Api\Http\Controllers\BargainController::class, 'activityDetail']);
Route::get('bargain-sku/{sku}', [\App\Endpoint\Api\Http\Controllers\BargainController::class, 'bargainSku']);
Route::get('bargain-order/sku/{sku}', [\App\Endpoint\Api\Http\Controllers\BargainController::class, 'barginaOrderBySku']);
Route::get('bargain-order/order/{order}', [\App\Endpoint\Api\Http\Controllers\BargainController::class, 'bargainOrderById']);
//三方登录聚合
Route::group([
'prefix' =>'socialite',
@ -193,6 +202,11 @@ Route::group([
Route::get('order/orders/{package}/shipping-info', [OrderController::class, 'shippingInfo']);
Route::get('users/{phone}', [\App\Endpoint\Api\Http\Controllers\UserController::class, 'show']);
//砍价
Route::post('bargains/create-order/{sku}', [\App\Endpoint\Api\Http\Controllers\BargainController::class, 'createBargainOrder']);
Route::post('bargains/bargain/{order}', [\App\Endpoint\Api\Http\Controllers\BargainController::class, 'bargain']);
Route::post('bargains/create-mall-order/{bargainOrder}', [\App\Endpoint\Api\Http\Controllers\BargainController::class, 'createMallOrderByBargainOrder']);
});
Route::group([

View File

@ -0,0 +1,129 @@
<?php
namespace App\Endpoint\Callback\Http\Controllers;
use App\Enums\DealerWalletToBankLogStatus;
use App\Enums\WalletToBankLogStatus;
use App\Models\DealerWalletToBankLog;
use App\Models\WalletToBankLog;
use App\Services\YeePayService;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Carbon;
class YeePayNotifyController extends Controller
{
public function __invoke(Request $request)
{
$this->info('request parameters', $request->input());
$this->validateSign($request);
switch ($request->input('service')) {
case 'accountpay.behalf.Pay':
$this->handleBehalfPayNotify($request);
break;
}
return 'success';
}
/**
* 处理代付回调
*
* @param \Illuminate\Http\Request $request
* @return void
*
* @throws \App\Exceptions\BizException
*/
protected function handleBehalfPayNotify(Request $request)
{
$resultCode = $request->input('resultCode');
if ($resultCode === 'EXECUTE_PROCESSING') {
return;
}
$orderNo = $request->input('merchOrderNo');
$orderStatus = $request->input('orderStatus');
$context = (array) json_decode($request->input('context'), true);
$contextType = Arr::get($context, 'type');
if ($contextType === 'wallet_to_bank') {
$log = WalletToBankLog::where('pay_sn', $orderNo)->first();
if ($log === null) {
return;
}
if ($log->status !== WalletToBankLogStatus::Paying) {
return;
}
if ($orderStatus === 'SUCCESS') {
$log->update([
'status' => WalletToBankLogStatus::Success,
'pay_at' => Carbon::parse($request->input('finishTime')),
'failed_reason' => null,
]);
} elseif ($orderStatus === 'FAIL') {
$log->update([
'status' => WalletToBankLogStatus::Failed,
'failed_reason' => $request->input('resultMessage').'#'.$resultCode,
]);
}
} elseif ($contextType === 'dealer_wallet_to_bank') {
$log = DealerWalletToBankLog::where('pay_sn', $orderNo)->first();
if ($log === null) {
return;
}
if ($log->status !== DealerWalletToBankLogStatus::Paying) {
return;
}
if ($orderStatus === 'SUCCESS') {
$log->update([
'status' => DealerWalletToBankLogStatus::Success,
'pay_at' => Carbon::parse($request->input('finishTime')),
'failed_reason' => null,
]);
} elseif ($orderStatus === 'FAIL') {
$log->update([
'status' => DealerWalletToBankLogStatus::Failed,
'failed_reason' => $request->input('resultMessage').'#'.$resultCode,
]);
}
}
}
/**
* 校验签名
*
* @param \Illuminate\Http\Request $request
* @return void
*
* @throws \App\Exceptions\BizException
*/
protected function validateSign(Request $request)
{
$yeePayService = new YeePayService(config('services.yeepay'));
if ($request->input('sign') === $yeePayService->sign($request->input())) {
return;
}
throw new Exception('签名错误');
}
protected function info($message, array $context = [])
{
logger()->build([
'driver' => 'daily',
'path' => storage_path('logs/yeepay-notify.log'),
])->info('yeepay notify', $context);
}
}

View File

@ -3,6 +3,7 @@
use App\Endpoint\Callback\Http\Controllers\AlipayController;
use App\Endpoint\Callback\Http\Controllers\Kuaidi100Controller;
use App\Endpoint\Callback\Http\Controllers\WxpayController;
use App\Endpoint\Callback\Http\Controllers\YeePayNotifyController;
use Illuminate\Support\Facades\Route;
//快递100物流推送
@ -13,3 +14,5 @@ Route::post('wxpay/{payment}/paid-notify', [WxpayController::class, 'paidNotify'
Route::post('wxpay/{payment}/order-refund-notify', [WxpayController::class, 'orderRefundedNotify'])->name('wxpay.order_refund_notify');
Route::post('alipay', AlipayController::class)->name('alipay.notify');
Route::post('yeepay-notify', YeePayNotifyController::class)->name('yeepay.notify');

64
app/Enums/Bank.php 100644
View File

@ -0,0 +1,64 @@
<?php
namespace App\Enums;
enum Bank {
case CCB;
case ABC;
case ICBC;
case BOC;
case BOCO;
case CMBCHINA;
case CMBC;
case CIB;
case CITIC;
case SPDB;
case CEB;
case PSBC;
case SDB;
/**
* @return string
*/
public function bankName(): string
{
return static::banks()[$this->name];
}
/**
* @param string $bankName
* @return static
*/
public static function tryFromBankName(string $bankName): ?static
{
foreach (static::cases() as $enum) {
if ($enum->bankName() === $bankName) {
return $enum;
}
}
return null;
}
/**
* @return array
*/
public static function banks(): array
{
return [
static::CCB->name => '中国建设银行',
static::ABC->name => '中国农业银行',
static::ICBC->name => '中国工商银行',
static::BOC->name => '中国银行',
static::BOCO->name => '交通银行',
static::CMBCHINA->name => '招商银行',
static::CMBC->name => '民生银行',
static::CIB->name => '兴业银行',
static::CITIC->name => '中信实业银行',
static::SPDB->name => '上海浦东发展银行',
static::CEB->name => '光大银行',
static::PSBC->name => '邮政储蓄银行',
static::SDB->name => '平安银行',
];
}
}

View File

@ -0,0 +1,38 @@
<?php
namespace App\Enums;
enum DealerWalletToBankLogPayWay: int {
case Offline = 1;
case Behalf = 2;
/**
* @return string
*/
public function color(): string
{
return match ($this) {
static::Offline => '#5b69bc',
static::Behalf => '#21b978',
};
}
/**
* @return string
*/
public function text(): string
{
return static::texts()[$this->value];
}
/**
* @return array
*/
public static function texts(): array
{
return [
static::Offline->value => '线下',
static::Behalf->value => '代付',
];
}
}

View File

@ -0,0 +1,50 @@
<?php
namespace App\Enums;
enum DealerWalletToBankLogStatus: int {
case Pending = 0;
case Success = 1;
case Refused = 2;
case Passed = 3; // 审核通过 - 等待付款
case Paying = 4; // 审核通过 - 付款中
case Failed = 9;
/**
* @return string
*/
public function color(): string
{
return match ($this) {
static::Pending => '#5b69bc',
static::Passed => '#dda451',
static::Paying => '#3085d6',
static::Success => '#21b978',
static::Failed => '#ea5455',
static::Refused => '#b3b9bf',
};
}
/**
* @return string
*/
public function text(): string
{
return static::texts()[$this->value];
}
/**
* @return array
*/
public static function texts(): array
{
return [
static::Pending->value => '待处理',
static::Passed->value => '待付款',
static::Paying->value => '付款中',
static::Success->value => '成功',
static::Failed->value => '失败',
static::Refused->value => '拒绝',
];
}
}

View File

@ -0,0 +1,38 @@
<?php
namespace App\Enums;
enum WalletToBankLogPayWay: int {
case Offline = 1;
case Behalf = 2;
/**
* @return string
*/
public function color(): string
{
return match ($this) {
static::Offline => '#5b69bc',
static::Behalf => '#21b978',
};
}
/**
* @return string
*/
public function text(): string
{
return static::texts()[$this->value];
}
/**
* @return array
*/
public static function texts(): array
{
return [
static::Offline->value => '线下',
static::Behalf->value => '代付',
];
}
}

View File

@ -0,0 +1,50 @@
<?php
namespace App\Enums;
enum WalletToBankLogStatus: int {
case Pending = 0;
case Success = 1;
case Refused = 2;
case Passed = 3; // 审核通过 - 等待付款
case Paying = 4; // 审核通过 - 付款中
case Failed = 9;
/**
* @return string
*/
public function color(): string
{
return match ($this) {
static::Pending => '#5b69bc',
static::Passed => '#dda451',
static::Paying => '#3085d6',
static::Success => '#21b978',
static::Failed => '#ea5455',
static::Refused => '#b3b9bf',
};
}
/**
* @return string
*/
public function text(): string
{
return static::texts()[$this->value];
}
/**
* @return array
*/
public static function texts(): array
{
return [
static::Pending->value => '待处理',
static::Passed->value => '待付款',
static::Paying->value => '付款中',
static::Success->value => '成功',
static::Failed->value => '失败',
static::Refused->value => '拒绝',
];
}
}

View File

@ -0,0 +1,9 @@
<?php
namespace App\Exceptions;
use Exception;
class YeePayException extends Exception
{
}

View File

@ -42,6 +42,9 @@ class SendCoupons
$products = $order->products()->where('is_gift', false)->get()->toArray();
$_products = array_column($products, 'total_amount', 'sku_id');
$partSkus = ProductPartSku::with('part')->whereIn('sku_id', array_keys($_products))->get();
$inValidParts = [];
foreach ($partSkus as $partSku) {
if ($partSku->part?->is_show) {
$inValidParts[$partSku->part_id][$partSku->sku_id] = $_products[$partSku->sku_id] ?? 0;
@ -52,49 +55,51 @@ class SendCoupons
// }
}
}
// dd($inValidParts);
//根据分区获取活动
$partActivities = ActivityProductPart::with(['activity', 'activity.coupons'])->whereHas('activity', function (Builder $query) {
return $query->where('is_use', true)->where('started_at', '<', now())->where('ended_at', '>=', now());
})->whereIn('part_id', array_keys($inValidParts))->get();
$activityArr = [];
$partActivities->each(function ($item) use (&$activityArr) {
$activityArr[$item->activity_id][] = $item->part_id;
});
$sendedActivities = [];
foreach ($partActivities as $partActivity) {
//判断该活动是否已处理
if (in_array($partActivity->activity_id, $sendedActivities)) {
continue;
}
$sendedActivities[] = $partActivity->activity_id;
//获取活动的赠品赠送规则
$_couponsRule = $partActivity->activity?->coupons_rule;
//判断是否首单times=0为仅首单赠送, 1为不限
if ($_couponsRule['times'] == 0 && UserCoupon::where([
'activity_id' => $partActivity->activity_id,
'user_id' => $order->user_id,
])->exists()) {
continue;//提前结束本次循环
}
//判断是否满足门槛
$inValidGoods = [];
foreach ($inValidParts as $key => $part) {
if (in_array($key, $activityArr[$partActivity->activity_id])) {
$inValidGoods = array_merge($inValidGoods, $part);
//存在有效分区时
if ($inValidParts) {
//根据分区获取活动
$partActivities = ActivityProductPart::with(['activity', 'activity.coupons'])->whereHas('activity', function (Builder $query) {
return $query->where('is_use', true)->where('started_at', '<', now())->where('ended_at', '>=', now());
})->whereIn('part_id', array_keys($inValidParts))->get();
$activityArr = [];
$partActivities->each(function ($item) use (&$activityArr) {
$activityArr[$item->activity_id][] = $item->part_id;
});
$sendedActivities = [];
foreach ($partActivities as $partActivity) {
//判断该活动是否已处理
if (in_array($partActivity->activity_id, $sendedActivities)) {
continue;
}
}
if (bcmul($_couponsRule['value'], 100) > array_sum($inValidGoods)) {
continue;//提前结束本次循环
}
//赠券
(new CouponService())->receiveActivityCoupons($partActivity->activity, $order->user);
$sendedActivities[] = $partActivity->activity_id;
//获取活动的赠品赠送规则
$_couponsRule = $partActivity->activity?->coupons_rule;
//判断是否首单times=0为仅首单赠送, 1为不限
if ($_couponsRule['times'] == 0 && UserCoupon::where([
'activity_id' => $partActivity->activity_id,
'user_id' => $order->user_id,
])->exists()) {
continue;//提前结束本次循环
}
//判断是否满足门槛
$inValidGoods = [];
foreach ($inValidParts as $key => $part) {
if (in_array($key, $activityArr[$partActivity->activity_id])) {
$inValidGoods = array_merge($inValidGoods, $part);
}
}
if (bcmul($_couponsRule['value'], 100) > array_sum($inValidGoods)) {
continue;//提前结束本次循环
}
//赠券
(new CouponService())->receiveActivityCoupons($partActivity->activity, $order->user);
//记录订单参与活动信息
OrderActivity::firstOrCreate([
'order_id'=>$order->id,
'activity_id'=>$partActivity->activity_id,
]);
//记录订单参与活动信息
OrderActivity::firstOrCreate([
'order_id'=>$order->id,
'activity_id'=>$partActivity->activity_id,
]);
}
}
DB::commit();

View File

@ -0,0 +1,40 @@
<?php
namespace App\Models;
use App\Casts\JsonArray;
use Dcat\Admin\Traits\HasDateTimeFormatter;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class BargainActivity extends Model
{
use HasFactory;
use HasDateTimeFormatter;
protected $casts = [
'images' => JsonArray::class,
'start_at' => 'datetime',
'end_at' => 'datetime',
];
public static $enabledText = [
0=>'禁用',
1=>'启用',
];
public static $enabledColor = [
0=>'#b3b9bf',
1=>'success',
];
public function skus()
{
return $this->belongsToMany(ProductSku::class, 'bargain_skus', 'activity_id', 'sku_id');
}
public function scopeIsEnable($query)
{
return $query->where('is_enable', true);
}
}

View File

@ -0,0 +1,60 @@
<?php
namespace App\Models;
use Dcat\Admin\Traits\HasDateTimeFormatter;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class BargainOrder extends Model
{
use HasFactory;
use HasDateTimeFormatter;
protected $casts = [
'expire_at'=> 'datetime',
];
protected $fillable = [
'order_id', 'remark',
];
public const ORDER_STATUS_WAIT = 0;
public const ORDER_STATUS_START = 1;
public const ORDER_STATUS_FINISHED = 2;
public function activity()
{
return $this->belongsTo(BargainActivity::class, 'activity_id');
}
public function user()
{
return $this->belongsTo(User::class, 'user_id');
}
public function userInfo()
{
return $this->belongsTo(UserInfo::class, 'user_id', 'user_id');
}
public function logs()
{
return $this->hasMany(BargainOrderLog::class, 'order_id');
}
public function sku()
{
return $this->hasOne(ProductSku::class, 'id', 'sku_id');
}
public function mallOrder()
{
return $this->belongsTo(Order::class, 'order_id');
}
public function isFinished()
{
return $this->status == static::ORDER_STATUS_FINISHED;
}
}

View File

@ -0,0 +1,32 @@
<?php
namespace App\Models;
use Dcat\Admin\Traits\HasDateTimeFormatter;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class BargainOrderLog extends Model
{
use HasFactory;
use HasDateTimeFormatter;
protected $fillable = [
'user_id', 'bargain_amount',
];
public function user()
{
return $this->belongsTo(User::class, 'user_id');
}
public function userInfo()
{
return $this->belongsTo(UserInfo::class, 'user_id', 'user_id');
}
public function getBargainAmountFormatAttribute()
{
return bcdiv($this->attributes['bargain_amount'], 100, 2);
}
}

View File

@ -0,0 +1,23 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class BargainSku extends Model
{
use HasFactory;
protected $timestamp = false;
public function activity()
{
return $this->belongsTo(BargainActivity::class, 'activity_id');
}
public function sku()
{
return $this->belongsTo(ProductSku::class, 'sku_id');
}
}

View File

@ -2,6 +2,9 @@
namespace App\Models;
use App\Casts\JsonArray;
use App\Enums\DealerWalletToBankLogPayWay;
use App\Enums\DealerWalletToBankLogStatus;
use Dcat\Admin\Traits\HasDateTimeFormatter;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
@ -11,9 +14,17 @@ class DealerWalletToBankLog extends Model
use HasFactory;
use HasDateTimeFormatter;
public const STATUS_PENDING = 0;//'待处理'
public const STATUS_AGREE = 1;//'已同意'
public const STATUS_REFUSE = 2;//'已拒绝'
protected $attributes = [
'pay_way' => DealerWalletToBankLogPayWay::Offline,
'status' => DealerWalletToBankLogStatus::Pending,
];
protected $casts = [
'pay_info' => JsonArray::class,
'pay_at' => 'datetime',
'pay_way' => DealerWalletToBankLogPayWay::class,
'status' => DealerWalletToBankLogStatus::class,
];
/**
* @var array
@ -26,6 +37,12 @@ class DealerWalletToBankLog extends Model
'rate',
'service_amount',
'account_amount',
'pay_info',
'pay_image',
'pay_sn',
'pay_way',
'pay_at',
'failed_reason',
];
/**
@ -49,7 +66,12 @@ class DealerWalletToBankLog extends Model
*/
public function isPending()
{
return $this->status == self::STATUS_PENDING;
return $this->status === DealerWalletToBankLogStatus::Pending;
}
public function isFailed()
{
return $this->status === DealerWalletToBankLogStatus::Failed;
}
/**
@ -59,7 +81,7 @@ class DealerWalletToBankLog extends Model
*/
public function getPayInfo()
{
if ($this->isPending()) {//待打款订单显示发货人收款信息
if ($this->isPending() || $this->isFailed()) {//待打款订单显示发货人收款信息
$payInfo = $this->user->dealer->pay_info;
} else {
$payInfo = $this->pay_info;

View File

@ -93,6 +93,7 @@ class Order extends Model
'is_settle',
'sales_value',
'is_settlable',
'bargain_amount',
];
/**
@ -427,4 +428,14 @@ class Order extends Model
{
return OrderStatus::$statusTexts[$this->order_status] ?? OrderStatus::$statusTexts[OrderStatus::UNKNOWN];
}
/**
* 获取订单砍价优惠
*
* @return string
*/
public function getBargainAmountFormatAttribute()
{
return trim_trailing_zeros(bcdiv($this->attributes['bargain_amount'], 100, 2));
}
}

View File

@ -41,6 +41,7 @@ class OrderProduct extends Model
'remain_quantity',
'is_gift',
'activity_id',
'bargain_amount',
];
public function packageProducts()

View File

@ -195,4 +195,21 @@ class ProductSku extends Model
return bcdiv($price, 100, 2);
}
/**
* 是否正在进行砍价
*
* @return boolean
*/
public function isBargaing()
{
$bargainSku = BargainSku::with(['activity'=>function ($query) {
return $query->where('is_enable', true)->where('start_at', '<=', now())->where('end_at', '>=', now());
}])->where('sku_id', $this->id)->first();
if ($bargainSku && $bargainSku->activity) {
return $bargainSku->activity;
}
return null;
}
}

View File

@ -410,6 +410,14 @@ class User extends Model implements AuthorizableContract, AuthenticatableContrac
return $this->belongsToMany(User::class, 'user_infos', 'inviter_id', 'user_id');
}
/**
* 用户的砍价单
*/
public function bargainOrders()
{
return $this->hasMany(BargainOrder::class);
}
/**
* 获取我的粉丝总数
*

View File

@ -2,6 +2,8 @@
namespace App\Models;
use App\Enums\WalletToBankLogPayWay;
use App\Enums\WalletToBankLogStatus;
use Dcat\Admin\Traits\HasDateTimeFormatter;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
@ -11,9 +13,11 @@ class WalletToBankLog extends Model
use HasFactory;
use HasDateTimeFormatter;
public const STATUS_PENDING = 0;//'待处理'
public const STATUS_AGREE = 1;//'已同意'
public const STATUS_REFUSE = 2;//'已拒绝'
protected $casts = [
'status' => WalletToBankLogStatus::class,
'pay_way' => WalletToBankLogPayWay::class,
'pay_at' => 'datetime',
];
/**
* @var array
@ -30,6 +34,10 @@ class WalletToBankLog extends Model
'rate',
'service_amount',
'account_amount',
'pay_sn',
'pay_way',
'pay_at',
'failed_reason',
];
/**

View File

@ -0,0 +1,108 @@
<?php
namespace App\Services;
use App\Exceptions\BizException;
use App\Models\BargainOrder;
use App\Models\BargainOrderLog;
use App\Models\BargainSku;
use App\Models\ProductSku;
use App\Models\User;
use Illuminate\Support\Arr;
class BargainService
{
/**
* 创建砍价单
*
* @param User $user
* @param ProductSku $productSku
* @return void
*/
public function createBargainOrder(User $user, ProductSku $productSku)
{
$bargainSku = BargainSku::with(['activity'=>function ($query) {
return $query->where('is_enable', true)->where('start_at', '<=', now())->where('end_at', '>=', now());
}])->where('sku_id', $productSku->id)->first();
if (!($bargainSku && $bargainSku->activity)) {
throw new BizException('砍价商品活动已结束');
}
$order = new BargainOrder();
$order->activity_id = $bargainSku->activity_id;
$order->user_id = $user->id;
$order->sku_id = $productSku->id;
$order->sku_price = $productSku->getRealPrice($user);
$order->status = BargainOrder::ORDER_STATUS_START;
$order->expire_at = now()->addHours($bargainSku->activity->expire_hours);
$order->save();
return $order;
}
/**
* 用户砍价
*
* @param User $user
* @param BargainOrder $order
* @return void
*/
public function bargain(User $user, BargainOrder $order)
{
$order->lockForUpdate();
$order->load('sku');
//不能给自己砍
if ($user->id == $order->user_id) {
throw new BizException('不能帮自己砍价');
}
//已砍完
if ($order->isFinished()) {
throw new BizException('当前砍价单已完成,无法再砍');
}
//已下单
if ($order->order_id > 0) {
throw new BizException('当前砍价单已下单,无法再砍');
}
//砍价超时
if ($order->expire_at < now()) {
throw new BizException('当前砍价已结束,无法再砍');
}
//如果砍价活动结束了,也不能砍了
$activity = $order->sku->isBargaing();
if (!$activity) {
throw new BizException('当前砍价已结束,无法再砍');
}
//如果已经砍过了,不能再砍了
if ($order->logs()->where('user_id', $user->id)->exists()) {
throw new BizException('您已砍价');
}
//执行砍价动作;
//计算第几次砍价,并获得当前砍价金额
$nowBargainCount = $order->logs->count();
$bargainRules = json_decode($activity->rules, true);
$log = new BargainOrderLog([
'user_id'=>$user->id,
'bargain_amount'=> bcmul(Arr::get($bargainRules, $nowBargainCount, 0), 100),
]);
$order->logs()->save($log);
$order->bargain_price += $log->bargain_amount;
$nowBargainCount ++;
if ($activity->times > 0 && $nowBargainCount >= $activity->times) {
$order->status = BargainOrder::ORDER_STATUS_FINISHED;
}
$order->save();
return $order;
}
}

View File

@ -11,6 +11,7 @@ use App\Enums\WxpayTradeType;
use App\Exceptions\BizException;
use App\Exceptions\ShippingNotSupportedException;
use App\Models\ActivityProductPart;
use App\Models\BargainOrder;
use App\Models\DistributionPreIncomeJob;
use App\Models\Order;
use App\Models\OrderActivity;
@ -38,6 +39,7 @@ class OrderService
* @param int $shippingAddressId
* @param int|null $couponId
* @param string|null $note
* @param BargainOrder|null $bargainOrder
* @return \App\Models\Order
*/
public function createQuickOrder(
@ -46,7 +48,8 @@ class OrderService
int $quantity,
int $shippingAddressId,
?int $couponId = null,
?string $note = null
?string $note = null,
?BargainOrder $bargainOrder = null,
): Order {
$sku = ProductSku::online()->findOrFail($skuId);
@ -55,7 +58,7 @@ class OrderService
'quantity' => $quantity,
];
return $this->createOrder($user, [$product], $shippingAddressId, $couponId, $note);
return $this->createOrder($user, [$product], $shippingAddressId, $couponId, $note, $bargainOrder);
}
/**
@ -97,6 +100,7 @@ class OrderService
* @param int $shippingAddressId
* @param int|null $couponId
* @param string|null $note
* @param BargainOrder|null $bargainOrder
* @return \App\Models\Order
*/
protected function createOrder(
@ -105,6 +109,7 @@ class OrderService
int $shippingAddressId,
?int $couponId = null,
?string $note = null,
?BargainOrder $bargainOrder = null,
): Order {
foreach ($products as $product) {
$sku = $product['sku'];
@ -123,7 +128,7 @@ class OrderService
$coupon = $user->coupons()->onlyAvailable()->lockForUpdate()->findOrFail($couponId);
}
$mapProducts = $this->mapProducts($user, $products, $coupon);
$mapProducts = $this->mapProducts($user, $products, $coupon, $bargainOrder);
// 计算运费
$shippingFee = $this->calculateShippingFee($mapProducts, $shippingAddress);
@ -144,7 +149,8 @@ class OrderService
$shippingFee,
$salesValue,
$note,
$coupon
$coupon,
$bargainOrder,//添加砍价订单逻辑
);
$this->storeOrderProducts($order, $mapProducts);
@ -185,10 +191,16 @@ class OrderService
$salesValue,
?string $note = null,
?UserCoupon $coupon = null,
?BargainOrder $bargainOrder = null,
): Order {
// 订单支付金额=商品总额-券折扣金额-会员折扣金额+邮费
// 订单支付金额=商品总额-券折扣金额-会员折扣金额+邮费-砍价金额
$totalAmount = $productsTotalAmount - $couponDiscountAmount - $vipDiscountAmount;
//如果有砍价优惠
if ($bargainOrder) {
$totalAmount -= $bargainOrder->bargain_price;
}
if ($totalAmount < 0) {
$totalAmount = 0;
}
@ -213,6 +225,8 @@ class OrderService
'consignee_telephone' => $shippingAddress->telephone,
'consignee_zone' => $shippingAddress->zone,
'consignee_address' => $shippingAddress->address,
//砍价订单金额
'bargain_amount'=>$bargainOrder?->bargain_price ?? 0,
];
return $user->orders()->create($attrs);
@ -239,8 +253,8 @@ class OrderService
$sku = $product['sku'];
$qty = $product['quantity'];
// 支付金额 = 商品总额 - 优惠券折扣金额- 会员折扣金额
$totalAmount = $product['total_amount'] - $product['coupon_discount_amount'] - $product['vip_discount_amount'];
// 支付金额 = 商品总额 - 优惠券折扣金额- 会员折扣金额 - 砍价金额
$totalAmount = $product['total_amount'] - $product['coupon_discount_amount'] - $product['vip_discount_amount'] - $product['bargain_amount'];
$orderProducts[] = [
'gift_for_sku_id' => null,
@ -263,6 +277,7 @@ class OrderService
'coupon_discount_amount' => $product['coupon_discount_amount'],
'vip_discount_amount' => $product['vip_discount_amount'],
'total_amount' => $totalAmount,
'bargain_amount'=> $product['bargain_amount'],
'created_at' => $order->created_at,
'updated_at' => $order->updated_at,
];
@ -452,6 +467,7 @@ class OrderService
'coupon_discount_amount' => 0,
'vip_discount_amount' => 0,
'total_amount' => 0,
'bargain_amount'=> 0,
'created_at' => $order->created_at,
'updated_at' => $order->updated_at,
'is_gift'=> true,
@ -481,9 +497,10 @@ class OrderService
* @param int $quantity
* @param int|null $shippingAddressId
* @param int|null $couponId
* @param int|null $bargainOrderId
* @return array
*/
public function verifyQuickOrder(User $user, int $skuId, int $quantity, ?int $shippingAddressId = null, ?int $couponId = null)
public function verifyQuickOrder(User $user, int $skuId, int $quantity, ?int $shippingAddressId = null, ?int $couponId = null, ?int $bargainOrderId = null)
{
$sku = ProductSku::online()->findOrFail($skuId);
@ -492,7 +509,7 @@ class OrderService
'quantity' => $quantity,
];
return $this->verifyOrder($user, [$product], $shippingAddressId, $couponId);
return $this->verifyOrder($user, [$product], $shippingAddressId, $couponId, $bargainOrderId);
}
/**
@ -519,9 +536,10 @@ class OrderService
* @param array $products
* @param int|null $shippingAddressId
* @param int|null $couponId
* @param int|null $bargainOrderId
* @return array
*/
protected function verifyOrder(User $user, array $products, ?int $shippingAddressId = null, ?int $couponId = null): array
protected function verifyOrder(User $user, array $products, ?int $shippingAddressId = null, ?int $couponId = null, ?int $bargainOrderId = null): array
{
// 获取收货地址
$shippingAddress = $this->getShippingAddress($user, $shippingAddressId);
@ -533,7 +551,12 @@ class OrderService
$coupon = $user->coupons()->onlyAvailable()->findOrFail($couponId);
}
$mapProducts = $this->mapProducts($user, $products, $coupon);
$bargainOrder = null;
if ($bargainOrderId) {
$bargainOrder = $user->bargainOrders()->findOrFail($bargainOrderId);
}
$mapProducts = $this->mapProducts($user, $products, $coupon, $bargainOrder);
// 是否支持配送
$shippingSupported = true;
@ -554,9 +577,10 @@ class OrderService
$vipDiscountAmount,
$couponDiscountAmount,
$salesValue,
$bargainAmount,
) = $this->calculateFees($mapProducts);
$totalAmount = $productsTotalAmount - $couponDiscountAmount - $vipDiscountAmount;
$totalAmount = $productsTotalAmount - $couponDiscountAmount - $vipDiscountAmount - $bargainAmount;
if ($totalAmount < 0) {
$totalAmount = 0;
@ -579,6 +603,7 @@ class OrderService
'vip_discount_amount' => trim_trailing_zeros(bcdiv($vipDiscountAmount, 100, 2)), // 会员折扣金额
'coupon_discount_amount' => trim_trailing_zeros(bcdiv($couponDiscountAmount, 100, 2)), // 优惠券折扣金额
'total_amount' => trim_trailing_zeros(bcdiv($totalAmount, 100, 2)), // 实付金额
'bargain_amount' => trim_trailing_zeros(bcdiv($bargainAmount, 100, 2)), //砍价金额
];
}
@ -594,12 +619,14 @@ class OrderService
$vipDiscountAmount = 0;
$couponDiscountAmount = 0;
$salesValue = 0;
$bargainAmount = 0;
foreach ($products as $product) {
$productsTotalAmount += $product['total_amount'];
$vipDiscountAmount += $product['vip_discount_amount'];
$couponDiscountAmount += $product['coupon_discount_amount'];
$salesValue = bcadd($salesValue, $product['total_sales_value']);
$bargainAmount += $product['bargain_amount'];
}
return [
@ -607,6 +634,7 @@ class OrderService
$vipDiscountAmount,
$couponDiscountAmount,
$salesValue,
$bargainAmount,
];
}
@ -665,7 +693,7 @@ class OrderService
*
* @throws \App\Exceptions\BizException
*/
protected function mapProducts(User $user, array $products, ?UserCoupon $coupon): array
protected function mapProducts(User $user, array $products, ?UserCoupon $coupon, ?BargainOrder $bargainOrder = null): array
{
$_products = collect($products)->map(function ($item) use ($user) {
$sku = $item['sku'];
@ -681,9 +709,20 @@ class OrderService
'total_amount' => $sku->sell_price * $item['quantity'],
// 总销售值
'total_sales_value' => bcmul($sku->sales_value, $item['quantity'], 2),
//砍价金额
'bargain_amount' => 0,
]);
});
//处理砍价金额
if ($bargainOrder) {
$bargainDiscountAmount = $this->getBargainDiscountAmount($bargainOrder, $_products->all());
$_products = $_products->map(function ($item) use ($bargainDiscountAmount) {
$item['bargain_amount'] = $bargainDiscountAmount[$item['sku']->id] ?? 0;
return $item;
});
}
if ($coupon === null) {
return $_products->all();
}
@ -778,9 +817,12 @@ class OrderService
foreach ($amounts as &$amount) {
$i--;
$originalAmount = $amount;
if ($i > 0) {
$amount = (int) bcdiv(bcmul($couponAmount, $amount, 0), $totalAmount, 2);
$couponAmount -= $amount;
$totalAmount -= $originalAmount;
} else {
$amount = $couponAmount;
}
@ -791,6 +833,52 @@ class OrderService
return $amounts;
}
/**
*
*/
protected function getBargainDiscountAmount(BargainOrder $bargainOrder, array $products): array
{
// 砍价的商品
$amounts = [];
foreach ($products as $item) {
$sku = $item['sku'];
$amount = $item['total_amount'] - $item['vip_discount_amount'];
// 仅保留商品真实总额大于0的商品
if ($amount > 0) {
$amounts[$sku->id] = $amount;
}
}
// 全部商品总额
$totalAmount = array_sum($amounts);
$bargainAmount = $bargainOrder->bargain_price ?? 0;
// 待计算优惠的商品总数
$i = count($amounts);
foreach ($amounts as &$amount) {
$i--;
$originalAmount = $amount;
if ($i > 0) {
$amount = (int) bcdiv(bcmul($bargainAmount, $amount, 0), $totalAmount, 2);
$bargainAmount -= $amount;
$totalAmount -= $originalAmount;
} else {
$amount = $bargainAmount;
}
unset($amount);
}
return $amounts;
}
/**
* 根据购物车获取商品
*

View File

@ -0,0 +1,82 @@
<?php
namespace App\Services;
use App\Exceptions\YeePayException;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;
class YeePayService
{
public function __construct(
protected array $config,
) {
}
/**
* @param string $service
* @param array $data
* @return array
*/
public function request(string $service, array $data = []): array
{
$data = array_merge([
'requestNo' => Str::uuid()->getHex()->toString(),
'service' => $service,
'partnerId' => $this->config['partner_id'],
'signType' => 'MD5',
'notifyUrl' => route('yeepay.notify'),
], $data);
$data['sign'] = $this->sign($data);
$response = Http::asForm()->post($this->config['gateway_url'], $data);
$response->throw();
$result = $response->json();
if ($result['success'] && in_array($result['resultCode'], ['EXECUTE_SUCCESS', 'EXECUTE_PROCESSING', 'TIME_OUT'])) {
return $result;
}
$message = $result['resultDetail'] ?? $result['resultMessage'];
throw new YeePayException($message);
}
/**
* 生成签名
*
* @param array $params
* @return string
*/
public function sign(array $params): string
{
unset($params['sign']);
ksort($params);
$str = '';
foreach ($params as $key => $value) {
if (blank($value)) {
continue;
}
if ($str !== '') {
$str .= '&';
}
if (is_array($value)) {
$value = json_encode($value);
}
$str .= "{$key}={$value}";
}
$str .= $this->config['secret_key'];
return md5($str);
}
}

View File

@ -30,4 +30,10 @@ return [
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
],
'yeepay' => [
'partner_id' => env('YEEPAY_PARTNER_ID'),
'secret_key' => env('YEEPAY_SECRET_KEY'),
'gateway_url' => env('YEEPAY_GATEWAY_URL'),
],
];

View File

@ -0,0 +1,42 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateBargainActivitiesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('bargain_activities', function (Blueprint $table) {
$table->id();
$table->string('name')->comment('活动名称');
$table->text('images')->nullable()->comment('活动图');
$table->text('share_image')->nullable()->comment('分享图');
$table->text('share_title')->nullable()->comment('分享文案');
$table->text('description')->nullable()->comment('活动描述');
$table->boolean('is_enable')->nullable()->comment('是否开启');
$table->text('rules')->nullable()->comment('砍价规则');
$table->unsignedInteger('times')->default(0)->comment('有效刀0为不限');
$table->unsignedInteger('expire_hours')->default(0)->comment('过期小时');
$table->timestamp('start_at')->nullable()->comment('开始时间');
$table->timestamp('end_at')->nullable()->comment('结束时间');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('bargain_activities');
}
}

View File

@ -0,0 +1,40 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateBargainOrdersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('bargain_orders', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('activity_id')->comment('参与活动ID');
$table->unsignedBigInteger('user_id')->comment('发起用户ID');
$table->unsignedBigInteger('sku_id')->comment('砍价商品');
$table->unsignedBigInteger('sku_price')->default(0)->comment('原价:分');
$table->unsignedBigInteger('bargain_price')->default(0)->comment('已砍价格:分');
$table->unsignedTinyInteger('status')->default(0)->comment('状态:0未开始1已开始2已完成');
$table->timestamp('expire_at')->nullable()->comment('过期时间');
$table->unsignedBigInteger('order_id')->nullable()->comment('下单支付ID');
$table->string('remark')->nullable()->comment('备注');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('bargain_orders');
}
}

View File

@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateBargainSkusTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('bargain_skus', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('activity_id')->comment('活动ID');
$table->unsignedBigInteger('sku_id')->comment('商品ID');
// $table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('bargain_skus');
}
}

View File

@ -0,0 +1,35 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddBargainToOrdersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('orders', function (Blueprint $table) {
//
$table->unsignedBigInteger('bargain_amount')->nullable()->default(0)->comment('砍价金额');
// $table->unsignedBigInteger('bargain_order_id')->nullable()->comment('关联砍价单ID');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('orders', function (Blueprint $table) {
//
$table->dropColumn(['bargain_amount']);
});
}
}

View File

@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateBargainOrderLogsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('bargain_order_logs', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('order_id')->comment('订单ID');
$table->unsignedBigInteger('user_id')->comment('用户ID');
$table->unsignedBigInteger('bargain_amount')->default(0)->comment('砍价金额');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('bargain_order_logs');
}
}

View File

@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddCoverToArticleCategoriesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('article_categories', function (Blueprint $table) {
//
$table->string('cover')->nullable()->comment('封面图');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('article_categories', function (Blueprint $table) {
//
$table->dropColumn(['cover']);
});
}
}

View File

@ -0,0 +1,38 @@
<?php
use App\Enums\WalletToBankLogPayWay;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddPayColumnsToWalletToBankLogsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('wallet_to_bank_logs', function (Blueprint $table) {
$table->string('pay_sn')->nullable()->comment('支付单号');
$table->tinyInteger('pay_way')->default(WalletToBankLogPayWay::Offline->value)->comment('支付方式: 1 线下, 2 代付');
$table->timestamp('pay_at')->nullable()->comment('支付时间');
$table->text('failed_reason')->nullable()->comment('失败原因');
$table->unique('pay_sn');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('wallet_to_bank_logs', function (Blueprint $table) {
$table->dropColumn(['pay_sn', 'pay_way', 'failed_reason', 'pay_at']);
});
}
}

View File

@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddBargainAmountToOrderProductsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('order_products', function (Blueprint $table) {
//
$table->unsignedBigInteger('bargain_amount')->nullable()->default(0)->comment('砍价金额');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('order_products', function (Blueprint $table) {
//
$table->dropColumn(['bargain_amount']);
});
}
}

View File

@ -0,0 +1,37 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddPayColumnsToDealerWalletToBankLogsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('dealer_wallet_to_bank_logs', function (Blueprint $table) {
$table->string('pay_sn')->nullable()->comment('支付单号');
$table->tinyInteger('pay_way')->default(1)->comment('支付方式: 1 线下, 2 代付');
$table->timestamp('pay_at')->nullable()->comment('支付时间');
$table->text('failed_reason')->nullable()->comment('失败原因');
$table->unique('pay_sn');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('dealer_wallet_to_bank_logs', function (Blueprint $table) {
$table->dropColumn(['pay_sn', 'pay_way', 'failed_reason', 'pay_at']);
});
}
}

View File

@ -420,6 +420,17 @@ class AdminPermissionSeeder extends Seeder
'name' => '每月统计',
'curd' => ['index'],
],
'bargain_activities'=>[
'name' =>'砍价活动',
'curd'=> true,
],
'bargain_orders'=>[
'name' =>'砍价活动记录',
'curd' => ['index', 'show'],
'children'=>[
'remark'=>['name' =>'备注'],
],
],
];
// try {
// DB::begintransaction();

File diff suppressed because it is too large Load Diff

View File

@ -7,6 +7,7 @@ return [
],
'fields' => [
'name' => '名称',
'cover' => '封面图',
'parent_id' => '父级',
'is_show' => '显示',
'is_recommend' => '推荐',

View File

@ -0,0 +1,22 @@
<?php
return [
'labels' => [
'BargainActivity' => '砍价活动',
'bargain-activities' => '砍价活动',
],
'fields' => [
'name' => '活动名称',
'description' => '活动描述',
'is_enable' => '是否开启',
'rules' => '砍价规则',
'times' => '有效刀',
'expire_hours' => '过期小时',
'start_at' => '开始时间',
'end_at' => '结束时间',
'skus'=>'关联商品',
'images' => '活动图',
],
'options' => [
],
];

View File

@ -0,0 +1,36 @@
<?php
return [
'labels' => [
'BargainOrder' => '砍价记录',
'bargain-orders' => '砍价记录',
],
'fields' => [
'activity' => [
'name'=> '活动名称',
],
'sku' => [
'name' => '商品名称',
],
'user'=>[
'phone'=>'手机号',
],
'userInfo'=>[
'nickname' => '昵称',
],
'mallOrder'=>[
'sn'=>'订单编号',
],
'activity_id' => '参与活动',
'user_id' => '发起用户',
'sku_id' => '砍价商品',
'sku_price' => '原价',
'bargain_price' => '已砍价格',
'status' => '状态',
'expire_at' => '过期时间',
'order_id' => '商城订单',
'remark' => '备注',
],
'options' => [
],
];

View File

@ -17,6 +17,8 @@ return [
'account_amount' => '到账金额',
'status' => '状态',
'remarks' => '备注',
'failed_reason' => '失败原因',
'pay_way' => '支付方式',
],
'options' => [
],

View File

@ -20,6 +20,7 @@ return [
'coupon_discount_amount' => '优惠券金额',
'vip_discount_amount' => '会员优惠',
'reduced_amount' => '减免金额',
'bargain_amount' => '砍价金额',
'shipping_fee' => '运费',
'products_total_amount' => '商品总额',
'total_amount' => '订单总额',

View File

@ -17,6 +17,9 @@ return [
'status' => '状态',
'remarks' => '备注',
'created_at'=> '申请时间',
'pay_way' => '支付方式',
'pay_at' => '支付时间',
'failed_reason' => '失败原因',
'user'=>[
'phone' => '申请人',
],