6
0
Fork 0

线下订单 增加备注

base
panliang 2026-04-17 21:32:23 +08:00
parent 2de5eb7e43
commit 141639ab84
26 changed files with 164 additions and 99 deletions

View File

@ -89,6 +89,8 @@ class OfflineOrderController extends AdminController
$grid->column('status')->display(fn($v) => $v->dot()); $grid->column('status')->display(fn($v) => $v->dot());
$grid->column('payment_method')->display(fn($v) => $v?->dot()); $grid->column('payment_method')->display(fn($v) => $v?->dot());
$grid->column('payment_time'); $grid->column('payment_time');
$grid->column('user_remark');
$grid->column('staff_remark');
$grid->column('created_at'); $grid->column('created_at');
$grid->filter(function (Grid\Filter $filter) { $grid->filter(function (Grid\Filter $filter) {
@ -207,6 +209,8 @@ class OfflineOrderController extends AdminController
$show->field('out_trade_no'); $show->field('out_trade_no');
$show->field('created_at'); $show->field('created_at');
$show->field('revoked_at'); $show->field('revoked_at');
$show->field('user_remark');
$show->field('staff_remark');
}); });
$show->panel()->tools(function (Show\Tools $tools) use ($show) { $show->panel()->tools(function (Show\Tools $tools) use ($show) {
$tools->disableEdit(); $tools->disableEdit();

View File

@ -10,6 +10,7 @@ use App\Models\OrderProduct;
use App\Models\PointLog; use App\Models\PointLog;
use App\Models\UserInfo; use App\Models\UserInfo;
use App\Models\UserVip; use App\Models\UserVip;
use App\Models\Store\Store;
use Dcat\Admin\Admin; use Dcat\Admin\Admin;
use Dcat\Admin\Grid; use Dcat\Admin\Grid;
use Dcat\Admin\Http\Controllers\AdminController; use Dcat\Admin\Http\Controllers\AdminController;
@ -33,12 +34,13 @@ class PointLogController extends AdminController
CSS CSS
); );
$builder = PointLogRepository::with(['user', 'administrator']); $builder = PointLogRepository::with(['user', 'administrator', 'store']);
return Grid::make($builder, function (Grid $grid) { return Grid::make($builder, function (Grid $grid) {
$grid->export()->titles([ $grid->export()->titles([
'id' => 'ID', 'id' => 'ID',
'store_id' => __('point-log.fields.store_id'),
'username' => '用户昵称', 'username' => '用户昵称',
'user_id' => __('point-log.fields.user.phone'), 'user_id' => __('point-log.fields.user.phone'),
'first_rechare_time' => '首次充值时间', 'first_rechare_time' => '首次充值时间',
@ -65,6 +67,7 @@ class PointLogController extends AdminController
$vipCount = $userVips->count(); $vipCount = $userVips->count();
$row['user_id'] = data_get($row, 'user.phone'); $row['user_id'] = data_get($row, 'user.phone');
$row['store_id'] = data_get($row, 'store.title');
$row['username'] = data_get($userInfo, 'nickname'); $row['username'] = data_get($userInfo, 'nickname');
$row['first_rechare_time'] = $firstVip ? $firstVip->success_time->format('Y-m-d H:i:s') : ''; $row['first_rechare_time'] = $firstVip ? $firstVip->success_time->format('Y-m-d H:i:s') : '';
@ -108,6 +111,7 @@ class PointLogController extends AdminController
$grid->model()->orderBy('id', 'desc'); $grid->model()->orderBy('id', 'desc');
$grid->column('id')->sortable(); $grid->column('id')->sortable();
$grid->column('store.title', __('point-log.fields.store_id'));
$grid->column('user.phone')->copyable(); $grid->column('user.phone')->copyable();
$grid->column('action')->display(fn ($action) => $action->label())->label(); $grid->column('action')->display(fn ($action) => $action->label())->label();
$grid->column('change_points')->display(function ($value) { $grid->column('change_points')->display(function ($value) {
@ -144,7 +148,9 @@ class PointLogController extends AdminController
}); });
$grid->filter(function (Grid\Filter $filter) { $grid->filter(function (Grid\Filter $filter) {
$stores = Store::pluck('title', 'id')->all();
$filter->panel(false); $filter->panel(false);
$filter->equal('store_id', __('point-log.fields.store_id'))->select($stores)->width(3);
$filter->equal('user.phone')->width(3); $filter->equal('user.phone')->width(3);
$filter->like('administrator.name', '操作人')->width(3); $filter->like('administrator.name', '操作人')->width(3);
$filter->in('action')->multipleSelect(PointLogAction::options())->width(3); $filter->in('action')->multipleSelect(PointLogAction::options())->width(3);

View File

@ -49,7 +49,7 @@ class OrderController extends AdminController
$grid->column('sn')->copyable(); $grid->column('sn')->copyable();
$grid->column('user_id')->display(function () { $grid->column('user_id')->display(function () {
$nickname = $this->userInfo?->nickname ?? '---'; $nickname = $this->userInfo?->nickname ?? '---';
$avatar = $this->userInfo?->avatar ?? 'https://via.placeholder.com/45x45.png'; $avatar = $this->userInfo?->avatar ?? asset('images/avatar.jpeg');
$phone = $this->user?->phone; $phone = $this->user?->phone;
return <<<HTML return <<<HTML
<img src="{$avatar}" width="45" /> <img src="{$avatar}" width="45" />
@ -59,7 +59,7 @@ class OrderController extends AdminController
}); });
$grid->column('inviter_id')->display(function () { $grid->column('inviter_id')->display(function () {
$nickname = $this->inviterInfo?->nickname ?? '---'; $nickname = $this->inviterInfo?->nickname ?? '---';
$avatar = $this->inviterInfo?->avatar ?? 'https://via.placeholder.com/45x45.png'; $avatar = $this->inviterInfo?->avatar ?? asset('images/avatar.jpeg');
$phone = $this->inviter?->phone; $phone = $this->inviter?->phone;
return <<<HTML return <<<HTML
<img src="{$avatar}" width="45" /> <img src="{$avatar}" width="45" />

View File

@ -3,6 +3,7 @@
namespace App\Admin\Controllers; namespace App\Admin\Controllers;
use App\Models\{UserVip, Vip}; use App\Models\{UserVip, Vip};
use App\Models\Store\Store;
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;
@ -17,11 +18,12 @@ class UserVipController extends AdminController
*/ */
protected function grid() protected function grid()
{ {
return Grid::make(UserVip::with(['user']), function (Grid $grid) { return Grid::make(UserVip::with(['user', 'store']), function (Grid $grid) {
$grid->model()->where('status', UserVip::STATUS_SUCCESS)->latest('created_at'); $grid->model()->where('status', UserVip::STATUS_SUCCESS)->latest('created_at');
$grid->column('user.phone'); $grid->column('user.phone');
$grid->column('store.title');
$grid->column('name'); $grid->column('name');
$grid->column('times')->display(function ($v) { $grid->column('times')->display(function ($v) {
return data_get($v, 'text'); return data_get($v, 'text');
@ -34,7 +36,9 @@ class UserVipController extends AdminController
$grid->disableViewButton(false); $grid->disableViewButton(false);
$grid->filter(function (Grid\Filter $filter) { $grid->filter(function (Grid\Filter $filter) {
$stores = Store::pluck('title', 'id')->all();
$filter->panel(false); $filter->panel(false);
$filter->equal('store_id', __('user-vip.fields.store.title'))->select($stores)->width(3);
$filter->like('user.phone')->width(3); $filter->like('user.phone')->width(3);
$filter->like('name')->width(3); $filter->like('name')->width(3);
}); });

View File

@ -40,7 +40,10 @@ class PointChange extends Form implements LazyRenderable
try { try {
DB::beginTransaction(); DB::beginTransaction();
(new PointService())->change($user, $changePoints, $action, $input['remark'], null, Admin::user()); (new PointService())->change($user, $changePoints, $action, [
'remark' => $input['remark'],
'administrator' => Admin::user()
]);
DB::commit(); DB::commit();
} catch (Throwable $th) { } catch (Throwable $th) {

View File

@ -38,44 +38,21 @@ class MiniprogramController extends Controller
$time = now(); $time = now();
$ip = $request->realIp(); $ip = $request->realIp();
$inviter = null;
if ($request->filled('invite_code')) {
$inviter = $this->findUserByCode($request->input('invite_code', ''));
if (!$inviter) {
throw new BizException('邀请人不存在');
}
}
try { try {
DB::beginTransaction(); DB::beginTransaction();
$user_social = SocialiteUser::where(['socialite_id' => $openid, 'socialite_type' => $type])->first(); $user_social = SocialiteUser::firstOrCreate(['socialite_id' => $openid, 'socialite_type' => $type]);
$user = $user_social->user;
if (!$user_social) { $token = '';
$attributes = [ if ($user) {
'register_ip' => $ip, $token = $user->createToken($type)->plainTextToken;
'last_login_at' => $time,
'last_login_ip' => $ip,
];
$user = User::create($attributes, $inviter);
$user->socialites()->create([
'socialite_id' => $openid,
'socialite_type' => $type,
]);
} else {
$user = $user_social->user;
} }
if (!$user) {
throw new BizException($openid);
}
$token = $user->createToken($type);
DB::commit(); DB::commit();
return response()->json([ return response()->json([
'openid' => $openid, 'openid' => $openid,
'token' => $token->plainTextToken 'token' => $token
]); ]);
} catch (Throwable $e) { } catch (Throwable $e) {
DB::rollBack(); DB::rollBack();
@ -89,7 +66,6 @@ class MiniprogramController extends Controller
public function bindPhone(Request $request) public function bindPhone(Request $request)
{ {
$user = $request->user();
$request->validate([ $request->validate([
'code' => 'required' 'code' => 'required'
], [ ], [
@ -105,19 +81,26 @@ class MiniprogramController extends Controller
} }
$phone = data_get($result, 'phone_info.purePhoneNumber'); $phone = data_get($result, 'phone_info.purePhoneNumber');
$openid = $request->input('openid');
try { try {
DB::beginTransaction(); DB::beginTransaction();
// 检测手机号是否已经注册 $user = User::where('phone', $phone)->first();
$old_user = User::where('phone', $phone)->where('status', User::STATUS_ACTIVE)->where('id', '!=', $user->id)->first(); if (!$user) {
if ($old_user) { $time = now();
// 禁用新用户 $ip = $request->realIp();
throw new BizException('手机号已经注册'); $inviter = $this->findUserByCode($request->input('invite_code', ''));
} else { $user = User::create([
$user->update([ 'register_ip' => $ip,
'phone' => $phone, 'last_login_at' => $time,
'phone_verified_at' => now(), 'last_login_ip' => $ip,
]); ], $inviter);
}
if ($openid) {
SocialiteUser::updateOrCreate(
['socialite_id' => $openid, 'socialite_type' => SocialiteType::WechatMiniProgram->value],
['user_id' => $user->id]
);
} }
$token = $user->createToken(SocialiteType::WechatMiniProgram->value); $token = $user->createToken(SocialiteType::WechatMiniProgram->value);

View File

@ -46,6 +46,7 @@ class OfflineOrderController extends Controller
$request->user(), $request->user(),
$preview, $preview,
bcmul($request->input('points', 0), 100), bcmul($request->input('points', 0), 100),
['user_remark' => $request->input('user_remark')]
); );
DB::commit(); DB::commit();

View File

@ -35,43 +35,52 @@ class OfflineOrderPreviewController extends Controller
'store_id' => $store->id, 'store_id' => $store->id,
'staff_id' => $user->id, 'staff_id' => $user->id,
'payload' => ['items' => $request->input('items')], 'payload' => ['items' => $request->input('items')],
'remark' => $request->input('remark')
]); ]);
$scene = http_build_query([ if (config('app.env') != "local") {
'oo' => $preview->id, $scene = http_build_query([
'i' => $user->userInfo->code, 'oo' => $preview->id,
]); 'i' => $user->userInfo->code,
// 生成小程序码
$app = Factory::miniProgram(config('wechat.mini_program.default'));
$response = $app->app_code->getUnlimit($scene, [
'page' => 'pages/welcome/index',
'check_path' => false,
'env_version' => app()->isProduction() ? 'release' : $request->input('env_version', 'trial'),
'width' => $request->input('width', 200),
]);
// 保存小程序码
if ($response instanceof StreamResponse) {
$directory = 'offline-order-preview';
$filename = "{$preview->id}.png";
$disk = Storage::disk('public');
$response->save($disk->path($directory), $filename);
$preview->update(['qrcode' => $disk->url("{$directory}/{$filename}")]);
return response()->json([
'id' => $preview->id,
'qrcode' => $preview->qrcode,
]); ]);
// 生成小程序码
$app = Factory::miniProgram(config('wechat.mini_program.default'));
$response = $app->app_code->getUnlimit($scene, [
'page' => 'pages/welcome/index',
'check_path' => false,
'env_version' => app()->isProduction() ? 'release' : $request->input('env_version', 'trial'),
'width' => $request->input('width', 200),
]);
// 保存小程序码
if ($response instanceof StreamResponse) {
$directory = 'offline-order-preview';
$filename = "{$preview->id}.png";
$disk = Storage::disk('public');
$response->save($disk->path($directory), $filename);
$preview->update(['qrcode' => $disk->url("{$directory}/{$filename}")]);
return response()->json([
'id' => $preview->id,
'qrcode' => $preview->qrcode,
]);
}
logger('offline_order_preview 小程序码生成失败', $response);
throw new BizException('生成失败, 请重试');
} }
logger('offline_order_preview 小程序码生成失败', $response); return response()->json([
'id' => $preview->id,
'qrcode' => asset("images/logo.png")
]);
throw new BizException('生成失败, 请重试');
} }
public function show($id) public function show($id)

View File

@ -27,7 +27,7 @@ class VipController extends Controller
$service = new VipService(); $service = new VipService();
try { try {
DB::beginTransaction(); DB::beginTransaction();
$user_vip = $service->buy($request->user(), $vip); $user_vip = $service->buy($request->user(), $vip, $request->only(['store_id']));
$result = $service->pay($user_vip, $request->input('pay_way')); $result = $service->pay($user_vip, $request->input('pay_way'));
DB::commit(); DB::commit();

View File

@ -232,7 +232,7 @@ Route::group([
// 微信小程序 // 微信小程序
Route::group(['prefix' => 'wechat-mini'], function () { Route::group(['prefix' => 'wechat-mini'], function () {
Route::post('login', [MiniprogramController::class, 'login']); Route::post('login', [MiniprogramController::class, 'login']);
Route::group(['middleware' => ['auth:api', \App\Endpoint\Api\Http\Middleware\CheckUserStatus::class]], function () { Route::group(['middleware' => [\App\Endpoint\Api\Http\Middleware\CheckUserStatus::class]], function () {
Route::post('bind-phone', [MiniprogramController::class, 'bindPhone']); Route::post('bind-phone', [MiniprogramController::class, 'bindPhone']);
}); });
}); });

View File

@ -43,6 +43,8 @@ class OfflineOrder extends Model
'revoked_at', 'revoked_at',
'orderable_type', 'orderable_type',
'orderable_id', 'orderable_id',
'user_remark',
'staff_remark',
]; ];
public function store() public function store()

View File

@ -15,7 +15,7 @@ class OfflineOrderPreview extends Model
]; ];
protected $fillable = [ protected $fillable = [
'store_id', 'staff_id', 'payload', 'qrcode', 'store_id', 'staff_id', 'payload', 'qrcode', 'remark'
]; ];
public function store() public function store()

View File

@ -7,6 +7,7 @@ use App\Models\Admin\Administrator;
use Dcat\Admin\Traits\HasDateTimeFormatter; use Dcat\Admin\Traits\HasDateTimeFormatter;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use App\Models\Store\Store;
class PointLog extends Model class PointLog extends Model
{ {
@ -22,6 +23,7 @@ class PointLog extends Model
'after_points', 'after_points',
'remark', 'remark',
'administrator_id', 'administrator_id',
'store_id'
]; ];
protected $casts = [ protected $casts = [
@ -33,6 +35,11 @@ class PointLog extends Model
return $this->belongsTo(User::class); return $this->belongsTo(User::class);
} }
public function store()
{
return $this->belongsTo(Store::class, 'store_id');
}
public function administrator() public function administrator()
{ {
return $this->belongsTo(Administrator::class); return $this->belongsTo(Administrator::class);

View File

@ -6,6 +6,9 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Dcat\Admin\Traits\HasDateTimeFormatter; use Dcat\Admin\Traits\HasDateTimeFormatter;
/**
* 门店
*/
class Store extends Model class Store extends Model
{ {
use HasFactory, HasDateTimeFormatter; use HasFactory, HasDateTimeFormatter;

View File

@ -2,6 +2,7 @@
namespace App\Models; namespace App\Models;
use App\Models\Store\Store;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Dcat\Admin\Traits\HasDateTimeFormatter; use Dcat\Admin\Traits\HasDateTimeFormatter;
@ -14,7 +15,7 @@ class UserVip extends Model
const STATUS_SUCCESS = 1; const STATUS_SUCCESS = 1;
const STATUS_PROCESSING = 2; const STATUS_PROCESSING = 2;
protected $fillable = ['user_id', 'vip_id', 'name', 'price', 'times', 'gift', 'status', 'expired', 'success_time']; protected $fillable = ['user_id', 'vip_id', 'name', 'price', 'times', 'gift', 'status', 'expired', 'success_time', 'store_id'];
protected $casts = [ protected $casts = [
'times' => 'json', 'times' => 'json',
@ -34,6 +35,11 @@ class UserVip extends Model
return $this->belongsTo(User::class, 'user_id'); return $this->belongsTo(User::class, 'user_id');
} }
public function store()
{
return $this->belongsTo(Store::class, 'store_id');
}
public function vip() public function vip()
{ {
return $this->belongsTo(Vip::class, 'vip_id'); return $this->belongsTo(Vip::class, 'vip_id');

View File

@ -398,7 +398,10 @@ class AfterSaleService
} }
if ($afterSale->points > 0) { if ($afterSale->points > 0) {
(new PointService())->change($order->user, $afterSale->points, PointLogAction::Refund, "售后单{$afterSale->sn}退还积分", $afterSale); (new PointService())->change($order->user, $afterSale->points, PointLogAction::Refund, [
'remark' => "售后单{$afterSale->sn}退还积分",
'loggable' => $afterSale,
]);
} }
//执行实际退款操作; //执行实际退款操作;

View File

@ -16,10 +16,11 @@ use App\Models\SocialiteUser;
use App\Models\User; use App\Models\User;
use App\Services\Payment\WxpayService; use App\Services\Payment\WxpayService;
use function EasyWeChat\Kernel\data_get;
class OfflineOrderService class OfflineOrderService
{ {
public function create(User $user, OfflineOrderPreview $orderPreview, int $points = 0): OfflineOrder public function create(User $user, OfflineOrderPreview $orderPreview, int $points = 0, $params = []): OfflineOrder
{ {
$items = $this->mapItems($orderPreview->payload['items']); $items = $this->mapItems($orderPreview->payload['items']);
@ -54,13 +55,19 @@ class OfflineOrderService
'status' => OfflineOrderStatus::Pending, 'status' => OfflineOrderStatus::Pending,
'orderable_type' => $orderPreview->getMorphClass(), 'orderable_type' => $orderPreview->getMorphClass(),
'orderable_id' => $orderPreview->id, 'orderable_id' => $orderPreview->id,
'user_remark' => data_get($params, 'user_remark'),
'staff_remark' => $orderPreview->remark,
]); ]);
$this->insertOrderItems($order, $items); $this->insertOrderItems($order, $items);
// 扣除积分 // 扣除积分
if ($points > 0) { if ($points > 0) {
(new PointService)->change($user, -$points, PointLogAction::Consumption, "线下订单{$order->sn}使用积分", $order); (new PointService)->change($user, -$points, PointLogAction::Consumption, [
'remark' => "线下订单{$order->sn}使用积分",
'loggable' => $order,
'store_id' => $orderPreview->store_id,
]);
} }
if ($order->payment_amount === 0) { if ($order->payment_amount === 0) {
@ -178,7 +185,11 @@ class OfflineOrderService
} }
if ($order->points_deduction_amount > 0) { if ($order->points_deduction_amount > 0) {
(new PointService())->change($order->user, $order->points_deduction_amount, PointLogAction::Refund, "线下订单{$order->sn}退还积分", $order); (new PointService())->change($order->user, $order->points_deduction_amount, PointLogAction::Refund, [
'remark' => "线下订单{$order->sn}退还积分",
'loggable' => $order,
'store_id' => $order->store_id,
]);
} }
$order->update([ $order->update([

View File

@ -427,7 +427,10 @@ class OrderService
// 扣除积分 // 扣除积分
if ($points > 0) { if ($points > 0) {
(new PointService)->change($user, -$points, PointLogAction::Consumption, "订单{$order->sn}使用积分", $order); (new PointService)->change($user, -$points, PointLogAction::Consumption, [
'remark' => "订单{$order->sn}使用积分",
'loggable' => $order
]);
} }
return $order; return $order;
@ -1418,7 +1421,11 @@ class OrderService
} }
if ($order->point_discount_amount > 0) { if ($order->point_discount_amount > 0) {
(new PointService())->change($order->user, $order->point_discount_amount, PointLogAction::Refund, "订单{$order->sn}退还积分", $order); (new PointService())->change($order->user, $order->point_discount_amount, PointLogAction::Refund, [
'remark' => "订单{$order->sn}退还积分",
'loggable' => $order,
'store_id' => $order->store_id
]);
} }
$order->update([ $order->update([

View File

@ -14,16 +14,21 @@ class PointService
{ {
/** /**
* 变更积分 * 变更积分
* *
* @param User $user 用户
* @param int $points 积分
* @param PointLogAction $action 操作
* @param $options {remark: 备注, loggable: 来源, administrator: 操作人, store_id: 所属门店}
* @throws \App\Exceptions\BizException * @throws \App\Exceptions\BizException
*/ */
public function change( public function change(
User $user, User $user,
int $points, int $points,
PointLogAction $action, PointLogAction $action,
?string $remark = null, // ?string $remark = null,
?Model $loggable = null, // ?Model $loggable = null,
?Administrator $administrator = null, // ?Administrator $administrator = null,
$options = []
) { ) {
if ($points === 0) { if ($points === 0) {
return; return;
@ -56,6 +61,9 @@ class PointService
$userinfo->update([ $userinfo->update([
'points' => $after, 'points' => $after,
]); ]);
$remark = data_get($options, 'remark');
$loggable = data_get($options, 'loggable');
$administrator = data_get($options, 'administrator');
PointLog::create([ PointLog::create([
'loggable_id' => $loggable?->id, 'loggable_id' => $loggable?->id,
@ -67,6 +75,7 @@ class PointService
'after_points' => $after, 'after_points' => $after,
'remark' => $remark, 'remark' => $remark,
'administrator_id' => $administrator?->id, 'administrator_id' => $administrator?->id,
'store_id' => data_get($options, 'store_id'),
]); ]);
} }
} }

View File

@ -11,7 +11,7 @@ use Carbon\Carbon;
class VipService class VipService
{ {
public function buy(User $user, Vip $vip) public function buy(User $user, Vip $vip, $params = [])
{ {
if (!$vip->status) { if (!$vip->status) {
throw new BizException('该会员卡已关闭'); throw new BizException('该会员卡已关闭');
@ -22,6 +22,7 @@ class VipService
'price' => $vip->price, 'price' => $vip->price,
'times' => $vip->times, 'times' => $vip->times,
'gift' => $vip->gift, 'gift' => $vip->gift,
'store_id' => data_get($params, 'store_id')
]); ]);
return $user_vip; return $user_vip;
@ -79,7 +80,7 @@ class VipService
* @param UserVip $userVip 购买记录 * @param UserVip $userVip 购买记录
* @param array $params {'pay_at':'购买时间'} * @param array $params {'pay_at':'购买时间'}
*/ */
public function success(UserVip $userVip, array $params = null) public function success(UserVip $userVip, array $params = [])
{ {
if ($userVip->status == UserVip::STATUS_SUCCESS) { if ($userVip->status == UserVip::STATUS_SUCCESS) {
return false; return false;
@ -133,13 +134,11 @@ class VipService
} }
if (isset($gift['points']) && bccomp($gift['points'], 0, 2) === 1) { if (isset($gift['points']) && bccomp($gift['points'], 0, 2) === 1) {
(new PointService())->change( (new PointService())->change($user, bcmul($gift['points'], 100), PointLogAction::Recharge, [
$user, 'remarks' => "购买【{$userVip->name}】赠送积分",
bcmul($gift['points'], 100), 'loggable' => $userVip,
PointLogAction::Recharge, 'store_id' => $userVip->store_id,
"购买【{$userVip->name}】赠送积分", ]);
$userVip,
);
} }
} }

View File

@ -28,6 +28,7 @@ class CreateVipsTable extends Migration
$table->id(); $table->id();
$table->unsignedBigInteger('user_id')->comment('用户ID'); $table->unsignedBigInteger('user_id')->comment('用户ID');
$table->unsignedBigInteger('vip_id')->comment('会员ID'); $table->unsignedBigInteger('vip_id')->comment('会员ID');
$table->unsignedBigInteger('store_id')->nullable()->comment('开通门店');
$table->string('name')->comment('名称'); $table->string('name')->comment('名称');
$table->decimal('price', 12, 2)->default(0)->comment('价格'); $table->decimal('price', 12, 2)->default(0)->comment('价格');
$table->text('times')->comment('时效{num,unit,text}'); $table->text('times')->comment('时效{num,unit,text}');

View File

@ -22,6 +22,7 @@ class CreatePointLogsTable extends Migration
$table->unsignedBigInteger('before_points')->comment('变更前的积分'); $table->unsignedBigInteger('before_points')->comment('变更前的积分');
$table->unsignedBigInteger('after_points')->comment('变更后的积分'); $table->unsignedBigInteger('after_points')->comment('变更后的积分');
$table->string('remark')->nullable()->comment('备注'); $table->string('remark')->nullable()->comment('备注');
$table->unsignedBigInteger('store_id')->nullable()->comment('所属门店');
$table->unsignedBigInteger('administrator_id')->nullable()->comment('管理员ID'); $table->unsignedBigInteger('administrator_id')->nullable()->comment('管理员ID');
$table->timestamps(); $table->timestamps();

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -23,6 +23,8 @@ return [
'status' => '状态', 'status' => '状态',
'revoked_at' => '取消时间', 'revoked_at' => '取消时间',
'items' => '品类', 'items' => '品类',
'user_remark' => '用户备注',
'staff_remark' => '员工备注',
], ],
'options' => [ 'options' => [
], ],

View File

@ -6,6 +6,7 @@ return [
'point-logs' => '积分流水', 'point-logs' => '积分流水',
], ],
'fields' => [ 'fields' => [
'store_id' => '所属门店',
'user_id' => '用户ID', 'user_id' => '用户ID',
'user'=>[ 'user'=>[
'phone' => '手机号', 'phone' => '手机号',

View File

@ -18,6 +18,9 @@ return [
'points' => '赠送积分', 'points' => '赠送积分',
'expired' => '会员有效期', 'expired' => '会员有效期',
'price' => '价格', 'price' => '价格',
'store' => [
'title' => '开通门店'
],
], ],
'options' => [ 'options' => [
], ],