6
0
Fork 0

抽奖管理 奖品关联优惠券

base
panliang 2026-05-13 11:34:29 +08:00
parent c8e3018c88
commit 157fbd2315
10 changed files with 123 additions and 11 deletions

View File

@ -4,8 +4,10 @@ namespace App\Admin\Actions\Grid;
use App\Enums\DrawLogStatus; use App\Enums\DrawLogStatus;
use App\Models\DrawLog; use App\Models\DrawLog;
use App\Services\DrawActivityService;
use Dcat\Admin\Grid\RowAction; use Dcat\Admin\Grid\RowAction;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class DrawLogComplete extends RowAction class DrawLogComplete extends RowAction
{ {
@ -32,14 +34,14 @@ class DrawLogComplete extends RowAction
{ {
$drawLog = DrawLog::findOrFail($this->getKey()); $drawLog = DrawLog::findOrFail($this->getKey());
if (! $drawLog->isPending()) { try {
return $this->response()->error('操作失败:中奖记录状态异常')->refresh(); DB::beginTransaction();
} (new DrawActivityService())->sendPrize($drawLog);
DB::commit();
$drawLog->update([
'status' => DrawLogStatus::Completed,
]);
return $this->response()->success('操作成功')->refresh(); return $this->response()->success('操作成功')->refresh();
} catch (\Exception $e) {
DB::rollBack();
return $this->response()->error($e->getMessage())->refresh();
}
} }
} }

View File

@ -3,15 +3,19 @@
namespace App\Admin\Controllers; namespace App\Admin\Controllers;
use App\Admin\Renderable\CouponRangeTable; use App\Admin\Renderable\CouponRangeTable;
use App\Admin\Renderable\UserCouponTable;
use App\Admin\Repositories\Coupon; use App\Admin\Repositories\Coupon;
use App\Exceptions\BizException; use App\Exceptions\BizException;
use App\Models\Coupon as CouponModel; use App\Models\Coupon as CouponModel;
use App\Models\UserCoupon;
use Dcat\Admin\Admin; use Dcat\Admin\Admin;
use Dcat\Admin\Form; use Dcat\Admin\Form;
use Dcat\Admin\Grid; use Dcat\Admin\Grid;
use Dcat\Admin\Http\Controllers\AdminController; use Dcat\Admin\Http\Controllers\AdminController;
use Dcat\Admin\Layout\Content; use Dcat\Admin\Layout\Content;
use Dcat\Admin\Layout\Row;
use Dcat\Admin\Show; use Dcat\Admin\Show;
use Dcat\Admin\Widgets\Box;
use Illuminate\Http\Request; use Illuminate\Http\Request;
class CouponController extends AdminController class CouponController extends AdminController
@ -66,6 +70,7 @@ class CouponController extends AdminController
$actions->append('<a href="'.admin_route('coupons.range_list', ['coupon'=>$actions->row]).'"><i class="fa fa-eye"></i> 使用范围</a>'); $actions->append('<a href="'.admin_route('coupons.range_list', ['coupon'=>$actions->row]).'"><i class="fa fa-eye"></i> 使用范围</a>');
} }
}); });
$grid->showViewButton();
/** 查询 **/ /** 查询 **/
$grid->filter(function (Grid\Filter $filter) { $grid->filter(function (Grid\Filter $filter) {
@ -84,7 +89,11 @@ class CouponController extends AdminController
*/ */
protected function detail($id) protected function detail($id)
{ {
return Show::make($id, new Coupon(), function (Show $show) { $row = new Row();
$row->column(5, Show::make($id, new Coupon(), function (Show $show) {
$show->disableDeleteButton();
$show->disableEditButton();
$show->disableListButton();
$show->field('id'); $show->field('id');
$show->field('name'); $show->field('name');
$show->field('type'); $show->field('type');
@ -97,7 +106,28 @@ class CouponController extends AdminController
$show->field('use_end_at'); $show->field('use_end_at');
$show->field('created_at'); $show->field('created_at');
$show->field('updated_at'); $show->field('updated_at');
}));
$builder = UserCoupon::with(['user'])->where('coupon_id', $id);
$grid = Grid::make($builder, function (Grid $grid) {
$grid->model()->orderBy('created_at', 'desc');
$grid->column('user_id', '用户')->display(function () {
return $this->user?->phone;
}); });
$grid->column('created_at', '领取时间')->display(function () {
return $this->created_at?->format('Y-m-d H:i:s');
});
$grid->column('use_end_at', '有效期')->display(function () {
return $this->use_end_at?->format('Y-m-d H:i:s');
});
$grid->column('is_use', '是否使用')->display(function () {
return $this->is_use ? '已使用' : '未使用';
});
$grid->disableActions();
$grid->disableRefreshButton();
});
$row->column(7, new Box("发放记录", $grid));
return $row;
} }
/** /**

View File

@ -6,6 +6,7 @@ use App\Admin\Repositories\DrawActivityPrize as DrawActivityPrizeRepository;
use App\Enums\DrawPrizeType; use App\Enums\DrawPrizeType;
use App\Exceptions\BizException; use App\Exceptions\BizException;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Models\Coupon;
use App\Models\DrawActivity; use App\Models\DrawActivity;
use App\Models\DrawPrize; use App\Models\DrawPrize;
use Dcat\Admin\Admin; use Dcat\Admin\Admin;
@ -188,6 +189,14 @@ class DrawActivityPrizeController extends Controller
$form->number('sort', '排序')->default(0)->rules(['required', 'int']); $form->number('sort', '排序')->default(0)->rules(['required', 'int']);
$form->radio('auto_send', '自动发放')->default(0)->options([0 => '否', 1 => '是']);
$form->select('price_type_id', "关联优惠券")->options(function ($id) {
$coupon = Coupon::find($id);
if ($coupon) {
return [$coupon->id => $coupon->name];
}
})->ajax(admin_route('api.coupons'))->help("仅奖品类型是 ".DrawPrizeType::Coupon->label()." 可用");
$form->saving(function (Form $form) use ($drawActivity) { $form->saving(function (Form $form) use ($drawActivity) {
if (! $form->isCreating()) { if (! $form->isCreating()) {
$form->deleteInput('draw_activity_id'); $form->deleteInput('draw_activity_id');

View File

@ -86,7 +86,7 @@ class DrawActivityPrizeStockChange extends Form implements LazyRenderable
{ {
$drawActivityPrize = DrawActivityPrize::findOrFail($this->payload['id']); $drawActivityPrize = DrawActivityPrize::findOrFail($this->payload['id']);
$this->radio('limited', '是否限量') $this->radio('limited', '限量')
->options([ ->options([
0 => '否', 0 => '否',
1 => '是', 1 => '是',

View File

@ -6,7 +6,10 @@ use App\Endpoint\Api\Http\Resources\DrawLogResource;
use App\Enums\DrawPrizeType; use App\Enums\DrawPrizeType;
use App\Exceptions\BizException; use App\Exceptions\BizException;
use App\Models\DrawLog; use App\Models\DrawLog;
use App\Services\DrawActivityService;
use Exception;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class DrawLogController extends Controller class DrawLogController extends Controller
{ {
@ -54,4 +57,27 @@ class DrawLogController extends Controller
return DrawLogResource::make($drawLog); return DrawLogResource::make($drawLog);
} }
/**
* 发放奖品
*/
public function sendPrize(Request $request)
{
$userId = $request->user()->id;
$drawLogId = $request->input('draw_log_id');
$drawLog = DrawLog::where('user_id', $userId)->find($drawLogId);
if ($drawLog) {
throw new BizException('中奖记录不存在');
}
try {
DB::beginTransaction();
(new DrawActivityService)->sendPrize($drawLog);
DB::commit();
return response()->json();
} catch (\Exception $e) {
DB::rollBack();
throw new BizException($e->getMessage());
}
}
} }

View File

@ -43,6 +43,8 @@ class DrawActivityPrize extends Model
'stock', 'stock',
'winnings', 'winnings',
'sort', 'sort',
'auto_send',
'price_type_id'
]; ];
public static function booted() public static function booted()

View File

@ -45,6 +45,11 @@ class UserCoupon extends Model
'activity_id', 'activity_id',
]; ];
public function user()
{
return $this->belongsTo(User::class, 'user_id');
}
/** /**
* 仅查询已过期的优惠券 * 仅查询已过期的优惠券
*/ */

View File

@ -5,6 +5,7 @@ namespace App\Services;
use App\Enums\DrawLogStatus; use App\Enums\DrawLogStatus;
use App\Enums\DrawPrizeType; use App\Enums\DrawPrizeType;
use App\Exceptions\BizException; use App\Exceptions\BizException;
use App\Models\Coupon;
use App\Models\DrawActivity; use App\Models\DrawActivity;
use App\Models\DrawActivityPrize; use App\Models\DrawActivityPrize;
use App\Models\DrawLog; use App\Models\DrawLog;
@ -57,8 +58,14 @@ class DrawActivityService
default => DrawLogStatus::Pending, default => DrawLogStatus::Pending,
}, },
]); ]);
$drawLog->setRelation('prize', $prize);
return $drawLog->setRelation('prize', $prize); // 自动发放奖品
if ($prize->auto_send) {
// 优惠券
$this->sendPrize($drawLog);
}
return $drawLog;
} }
/** /**
@ -94,4 +101,32 @@ class DrawActivityService
throw new BizException('抽奖活动异常'); throw new BizException('抽奖活动异常');
} }
/**
* 发放活动奖品
*/
public function sendPrize(DrawLog $drawLog)
{
if (!$drawLog->isPending()) {
throw new BizException("发放奖品失败: 奖品已发放");
}
// 发放奖品
$prize = $drawLog->prize;
// 发放优惠券
if ($prize->type == DrawPrizeType::Coupon) {
if (!$prize->price_type_id) {
throw new BizException("发放奖品失败: 奖品(".$prize->name.")未关联优惠券");
}
$coupon = Coupon::find($prize->price_type_id);
if (!$coupon) {
throw new BizException("发放奖品失败: 奖品(".$prize->name.")关联优惠券不存在");
}
(new CouponService())->sendCoupon($drawLog->user, $coupon, 1);
}
$drawLog->update([
'status' => DrawLogStatus::Completed,
]);
}
} }

View File

@ -24,6 +24,7 @@ class CreateDrawActivitiesTable extends Migration
$table->string('bg_image')->nullable()->comment('背景图片'); $table->string('bg_image')->nullable()->comment('背景图片');
$table->string('bg_color')->nullable()->comment('背景颜色'); $table->string('bg_color')->nullable()->comment('背景颜色');
$table->tinyInteger('status')->default(0)->comment('状态'); $table->tinyInteger('status')->default(0)->comment('状态');
$table->integer("send_ticket_type")->default(0)->comment("抽奖资格赠送方式(0: 无, 1: 用户注册)");
$table->timestamps(); $table->timestamps();
}); });
} }

View File

@ -25,6 +25,8 @@ class CreateDrawActivityPrizesTable extends Migration
$table->unsignedInteger('stock')->default(0)->comment('奖品库存'); $table->unsignedInteger('stock')->default(0)->comment('奖品库存');
$table->unsignedInteger('winnings')->default(0)->comment('中奖数量'); $table->unsignedInteger('winnings')->default(0)->comment('中奖数量');
$table->integer('sort')->default(0)->comment('排序'); $table->integer('sort')->default(0)->comment('排序');
$table->integer('auto_send')->default(0)->comment('奖品是否自动发放');
$table->unsignedBigInteger('price_type_id')->nullable()->comment('奖品关联记录id(例如: 奖品是优惠券, 保存 coupons.id)');
$table->timestamps(); $table->timestamps();
}); });
} }