6
0
Fork 0

添加后台配置发送优惠券任务

release
vine_liutk 2021-12-09 16:25:53 +08:00
parent c6e4e5a639
commit 6787f9b249
21 changed files with 342 additions and 36 deletions

View File

@ -113,7 +113,7 @@ class AdController extends AdminController
])->default(0);
$form->text('jump_link');
$form->switch('is_show');
$form->number('sort')->default(0);
$form->number('sort')->min(0)->default(0);
$form->display('created_at');
$form->display('updated_at');

View File

@ -112,7 +112,7 @@ class ArticleCategoryController extends AdminController
$form->text('name')->required();
$form->switch('is_show');
$form->switch('is_recommend');
$form->number('sort')->default(0);
$form->number('sort')->min(0)->default(0);
$form->display('created_at');
$form->display('updated_at');

View File

@ -136,7 +136,7 @@ class ArticleController extends AdminController
$form->text('jump_link');
$form->switch('is_show');
$form->switch('is_recommend');
$form->number('sort')->default(0);
$form->number('sort')->min(0)->default(0);
$form->display('created_at');
$form->display('updated_at');

View File

@ -4,6 +4,7 @@ namespace App\Admin\Controllers;
use App\Admin\Renderable\CouponRangeTable;
use App\Admin\Repositories\Coupon;
use App\Exceptions\BizException;
use App\Models\Coupon as CouponModel;
use Dcat\Admin\Admin;
use Dcat\Admin\Form;
@ -103,7 +104,12 @@ class CouponController extends AdminController
{
return Form::make(new Coupon(), function (Form $form) {
$form->display('id');
$form->text('name')->required();
$form->number('limit')->min(0)->default(0)->help('0为不限量');
if ($form->isEditing()) {
if (!$form->model()->hasReceived()) {
$form->radio('type')
->when(1, function (Form $form) {
$form->currency('amount1')->symbol('¥')->help('例100.00表示优惠100元。')->value($form->model()->amount);
@ -115,19 +121,43 @@ class CouponController extends AdminController
1 =>'抵扣券',
2 =>'折扣券',
])->default(1);
$form->currency('threshold')->symbol('¥')->default(0);
$form->number('limit')->default(0);
$form->number('use_day')->default(0)->help('单位:天;指领取后几天内有效。');
$form->datetimeRange('use_start_at', 'use_end_at', '使用时间')->help('设置时间后,期限字段失效。');
$form->hidden('amount');
$form->currency('threshold')->symbol('¥')->default(0);
$form->number('use_day')->min(0)->default(1)->help('单位:天;指领取后几天内有效。');
$form->datetimeRange('use_start_at', 'use_end_at', '使用时间')->help('设置时间后,期限字段失效。');
}
}
// $form->editing(function (Form $form) {
// if (!$form->model()->hasReceived()) {
// $form->radio('type')
// ->when(1, function (Form $form) {
// $form->currency('amount1')->symbol('¥')->help('例100.00表示优惠100元。')->value($form->model()->amount);
// })
// ->when(2, function (Form $form) {
// $form->currency('amount2')->symbol('%')->help('例0.95表示95折。')->value($form->model()->amount);
// })
// ->options([
// 1 =>'抵扣券',
// 2 =>'折扣券',
// ])->default(1);
// $form->hidden('amount');
// $form->currency('threshold')->symbol('¥')->default(0);
// $form->number('use_day')->default(0)->help('单位:天;指领取后几天内有效。');
// $form->datetimeRange('use_start_at', 'use_end_at', '使用时间')->help('设置时间后,期限字段失效。');
// }
// });
$form->saving(function (Form $form) {
if ($form->type) {
$amount = 'amount'.$form->type;
$form->amount = $form->$amount;
$form->deleteInput('amount1');
$form->deleteInput('amount2');
}
});
$form->display('created_at');
@ -135,6 +165,21 @@ class CouponController extends AdminController
});
}
/**
* 修改删除判断
*
* @param [type] $id
* @return void
*/
public function destroy($id)
{
$coupon = CouponModel::findOrFail($id);
if ($coupon->hasSendTask() || $coupon->hasReceived()) {
throw new BizException(__('coupon.options.deny_message'));
}
return parent::destroy($id);
}
/**
* 获取优惠券接口
*

View File

@ -65,6 +65,13 @@ class CouponSendTaskController extends AdminController
if (Admin::user()->can('dcat.admin.coupon_send_tasks.start')) {
$actions->append(new CouponTaskStart());
}
} else {
$actions->disableQuickEdit();
if (Admin::user()->can('dcat.admin.coupon_task_logs.index')) {
$actions->append('<a href="'.admin_route('coupon_task_logs.index', ['task_id' =>$actions->row->id]).'">
<i class="feather icon-list grid-action-icon"></i>&nbsp;'.__('admin.list').
'</a>');
}
}
});
@ -114,7 +121,7 @@ class CouponSendTaskController extends AdminController
return [$coupon->id => $coupon->name];
}
})->ajax(admin_route('api.coupons'));
$form->number('num')->default(1);
$form->number('num')->min(1)->default(1);
$form->radio('type')->options([
1=>'指定用户',
])->when(1, function (Form $form) {

View File

@ -3,10 +3,12 @@
namespace App\Admin\Controllers;
use App\Admin\Repositories\CouponTaskLog;
use App\Models\CouponSendTask;
use Dcat\Admin\Form;
use Dcat\Admin\Grid;
use Dcat\Admin\Http\Controllers\AdminController;
use Dcat\Admin\Show;
use Illuminate\Support\Facades\Request;
class CouponTaskLogController extends AdminController
{
@ -35,12 +37,18 @@ class CouponTaskLogController extends AdminController
2=>'success',
3=>'danger',
]);
$grid->column('remarks');
$grid->column('created_at');
$grid->column('updated_at')->sortable();
$grid->model()->orderBy('created_at', 'desc');
$grid->filter(function (Grid\Filter $filter) {
$filter->panel(false);
$filter->equal('task_id')->select()->ajax(admin_route('api.coupon_send_tasks'))->width(3);
$filter->equal('task_id')->select(function () {
$taskId = Request::get('task_id');
return CouponSendTask::where('id', $taskId)->pluck('name', 'id');
})->ajax(admin_route('api.coupon_send_tasks'))->width(3);
$filter->equal('coupon_id')->select()->ajax(admin_route('api.coupons'))->width(3);
$filter->like('user.phone')->width(3);
});

View File

@ -114,7 +114,7 @@ class ProductCategoryController extends AdminController
->autoUpload();
$form->switch('is_show');
$form->switch('is_recommend');
$form->number('sort')->default(0);
$form->number('sort')->min(0)->default(0);
$form->saving(function (Form $form) {
//只能添加到三级分类
if ($form->parent_id) {

View File

@ -91,8 +91,8 @@ class ProductSkuController extends AdminController
->autoUpload();
$form->editor('description');
$form->select('buynote_id')->options(ProductBuynote::all()->pluck('name', 'id'));
$form->number('weight');
$form->number('stock');
$form->number('weight')->min(0)->default(0);
$form->number('stock')->min(0)->default(0);
$form->divider();
$form->currency('sell_price')->symbol('¥')->default(0);
$form->currency('market_price')->symbol('¥')->default(0);

View File

@ -142,9 +142,9 @@ class ProductSpuController extends AdminController
});
$form->editor('description');
$form->select('buynote_id')->options(ProductBuynote::all()->pluck('name', 'id'));
$form->number('weight');
$form->number('weight')->min(0)->default(0);
$form->select('shipping_template_id')->options(ShippingTemplate::all()->pluck('name', 'id'))->required();
$form->number('stock');
$form->number('stock')->min(0)->default(0);
$form->divider();
$form->currency('sell_price')->symbol('¥')->default(0);
$form->currency('market_price')->symbol('¥')->default(0);

View File

@ -87,9 +87,9 @@ class ShippingRuleController extends AdminController
})
->when(2, function (Form $form) {
$form->embeds('info2', function ($form) {
$form->number('first_weight')->rules('required_if:type,2')->default(2);
$form->number('first_weight')->min(1)->rules('required_if:type,2')->default(2);
$form->currency('first_w_amount')->rules('required_if:type,2')->symbol('¥');
$form->number('continue_weight')->rules('required_if:type,2')->default(1);
$form->number('continue_weight')->min(1)->rules('required_if:type,2')->default(1);
$form->currency('continue_w_amount')->rules('required_if:type,2')->symbol('¥');
})->customFormat(function () {
if ($this->model()->type == '2') {

View File

@ -75,7 +75,7 @@ class VipController extends AdminController
return Form::make(new Vip(), function (Form $form) {
$form->display('id');
$form->text('name')->required();
$form->number('growth_value')->default(0);
$form->number('growth_value')->min(0)->default(0);
$form->display('created_at');
$form->display('updated_at');

View File

@ -79,8 +79,8 @@ class SkuGift extends Form implements LazyRenderable
return [$sku->id => $sku->name];
}
})->ajax(admin_route('api.product_skus'))->required();
$form->number('num')->default(1);
$form->number('limit')->default(0);
$form->number('num')->min(1)->default(1);
$form->number('limit')->min(0)->default(0);
})->customFormat(function () use ($sku) {
return $sku->gifts;
});

View File

@ -0,0 +1,120 @@
<?php
namespace App\Console\Commands;
use App\Models\Coupon;
use App\Models\CouponSendTask;
use App\Models\CouponTaskLog;
use App\Models\UserCoupon;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Throwable;
class AdminSendCoupon extends Command
{
/**
* 单次最大条数
*
* @var integer
*/
protected $limit = 100;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'admin-work:send-coupon';
/**
* The console command description.
*
* @var string
*/
protected $description = '后台执行优惠券发放任务';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
//获取需要执行的任务数据包
$logs = CouponTaskLog::where('status', '0')->where('num', '>', 0)->orderBy('id')->limit($this->limit)->get();
$logs = $logs->groupBy('task_id');
foreach ($logs as $taskId => $taskLogs) {
$nowTime = now();
$task = CouponSendTask::find($taskId);
$coupon = Coupon::find($task->coupon_id);
//如果优惠券限量,则获取优惠券余量,只发送前面的人;
$failedLogs = collect([]);
if ($coupon->limit > 0 && $coupon->stock < ($taskLogs->count() * $task->num)) {
$failedLogs = $taskLogs->slice($coupon->stock);
$taskLogs = $taskLogs->slice(0, $coupon->stock);
}
if ($coupon->use_start_at && $coupon->use_end_at) {
$useStartAt = $coupon->use_start_at;
$useEndAt = $coupon->use_end_at;
} else {
$useStartAt = now();
$useEndAt = now()->addDays($coupon->use_day);
}
//批量插入用户优惠券
$insertUserCoupons = [];
foreach ($taskLogs as $taskLog) {
for ($i=0; $i< $taskLog->num; $i++) {
$insertUserCoupons[] = [
'user_id' => $taskLog->user_id,
'coupon_id' => $taskLog->coupon_id,
'coupon_name' => $coupon->name,
'coupon_type' => $coupon->type,
'coupon_amount' => (int) bcmul($coupon->amount, 100),
'coupon_threshold'=> (int) bcmul($coupon->threshold, 100),
'use_start_at' => $useStartAt,
'use_end_at' => $useEndAt,
'status' => 0,
'created_at' => $nowTime,
'updated_at' => $nowTime,
];
}
}
try {
DB::beginTransaction();
count($insertUserCoupons) > 0 && UserCoupon::insert($insertUserCoupons);
//更新任务日志状态;
CouponTaskLog::whereIn('id', $taskLogs->pluck('id')->toArray())->update(['status'=>2]);
$failedLogs->count() == 0 || CouponTaskLog::whereIn('id', $failedLogs->pluck('id')->toArray())->update(['status'=>3, 'remarks'=>'库存余量不足']);
//更新任务对应券发送量,余量;
$coupon->increment('sent', $taskLogs->count());
if ($coupon->limit > 0) {//限量才减少余量
$coupon->decrement('stock', $taskLogs->count());
}
//更新如果是任务最后一批,更新任务状态;
$taskTotalnum = CouponTaskLog::where('task_id', $taskId)->where('num', '>', 0)->count();
$taskDidnum = CouponTaskLog::where('task_id', $taskId)->where('num', '>', 0)->where('status', '>', 0)->count();
if ($taskTotalnum == $taskDidnum) {
$task->update(['status' => 3]);
}
DB::commit();
} catch (Throwable $th) {
DB::rollBack();
report($th);
}
}
$this->info('执行成功');
return Command::SUCCESS;
}
}

View File

@ -26,4 +26,37 @@ class Coupon extends Model
{
return $this->hasMany(CouponRange::class, 'coupon_id');
}
/**
* 优惠券的发放任务
*/
public function sendTask()
{
return $this->hasMany(CouponSendTask::class, 'coupon_id');
}
/**
* 该优惠券下是否有发放任务
*
* @return bool
*/
public function hasSendTask(): bool
{
return $this->sendTask()->exists();
}
public function receiveLog()
{
return $this->hasMany(UserCoupon::class, 'coupon_id');
}
/**
* 是否被领取过
*
* @return boolean
*/
public function hasReceived()
{
return $this->receiveLog()->exists();
}
}

View File

@ -17,6 +17,10 @@ class CouponSendTask extends Model
// 'value'=>JsonArray::class,
// ];
protected $fillable = [
'status',
];
public function coupon()
{
return $this->belongsTo(Coupon::class, 'coupon_id');

View File

@ -11,6 +11,11 @@ class CouponTaskLog extends Model
use HasFactory;
use HasDateTimeFormatter;
protected $fillable = [
'status',
'remarks',
];
/**
* 此记录发放的券
*

View File

@ -8,4 +8,18 @@ use Illuminate\Database\Eloquent\Model;
class UserCoupon extends Model
{
use HasFactory;
protected $fillable = [
'user_id',
'coupon_id',
'coupon_name',
'coupon_type',
'coupon_amount',
'coupon_threshold',
'use_start_at',
'use_end_at',
'status',
'created_at',
'updated_at',
];
}

View File

@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddRemarksToCouponTaskLogsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('coupon_task_logs', function (Blueprint $table) {
//
$table->string('remarks')->nullable()->comment('备注');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('coupon_task_logs', function (Blueprint $table) {
//
$table->dropColumn('remarks');
});
}
}

View File

@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddCouponAmountToUserCouponsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('user_coupons', function (Blueprint $table) {
//
$table->dropColumn('coupon_value');
$table->unsignedInteger('coupon_amount')->default(0)->comment('抵扣金额:分/折扣(100)');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('user_coupons', function (Blueprint $table) {
//
});
}
}

View File

@ -11,6 +11,7 @@ return [
'user_id' => '用户',
'num' => '张数',
'status' => '状态',
'remarks'=> '备注',
'task'=>[
'name' => '任务名称',
],

View File

@ -23,5 +23,6 @@ return [
'ranges'=>'范围',
],
'options' => [
'deny_message' => '该优惠已被领取或者已配置发送任务',
],
];