线下订单 增加备注
parent
2de5eb7e43
commit
141639ab84
|
|
@ -89,6 +89,8 @@ class OfflineOrderController extends AdminController
|
|||
$grid->column('status')->display(fn($v) => $v->dot());
|
||||
$grid->column('payment_method')->display(fn($v) => $v?->dot());
|
||||
$grid->column('payment_time');
|
||||
$grid->column('user_remark');
|
||||
$grid->column('staff_remark');
|
||||
$grid->column('created_at');
|
||||
|
||||
$grid->filter(function (Grid\Filter $filter) {
|
||||
|
|
@ -207,6 +209,8 @@ class OfflineOrderController extends AdminController
|
|||
$show->field('out_trade_no');
|
||||
$show->field('created_at');
|
||||
$show->field('revoked_at');
|
||||
$show->field('user_remark');
|
||||
$show->field('staff_remark');
|
||||
});
|
||||
$show->panel()->tools(function (Show\Tools $tools) use ($show) {
|
||||
$tools->disableEdit();
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ use App\Models\OrderProduct;
|
|||
use App\Models\PointLog;
|
||||
use App\Models\UserInfo;
|
||||
use App\Models\UserVip;
|
||||
use App\Models\Store\Store;
|
||||
use Dcat\Admin\Admin;
|
||||
use Dcat\Admin\Grid;
|
||||
use Dcat\Admin\Http\Controllers\AdminController;
|
||||
|
|
@ -33,12 +34,13 @@ class PointLogController extends AdminController
|
|||
CSS
|
||||
);
|
||||
|
||||
$builder = PointLogRepository::with(['user', 'administrator']);
|
||||
$builder = PointLogRepository::with(['user', 'administrator', 'store']);
|
||||
|
||||
return Grid::make($builder, function (Grid $grid) {
|
||||
|
||||
$grid->export()->titles([
|
||||
'id' => 'ID',
|
||||
'store_id' => __('point-log.fields.store_id'),
|
||||
'username' => '用户昵称',
|
||||
'user_id' => __('point-log.fields.user.phone'),
|
||||
'first_rechare_time' => '首次充值时间',
|
||||
|
|
@ -65,6 +67,7 @@ class PointLogController extends AdminController
|
|||
$vipCount = $userVips->count();
|
||||
|
||||
$row['user_id'] = data_get($row, 'user.phone');
|
||||
$row['store_id'] = data_get($row, 'store.title');
|
||||
$row['username'] = data_get($userInfo, 'nickname');
|
||||
|
||||
$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->column('id')->sortable();
|
||||
$grid->column('store.title', __('point-log.fields.store_id'));
|
||||
$grid->column('user.phone')->copyable();
|
||||
$grid->column('action')->display(fn ($action) => $action->label())->label();
|
||||
$grid->column('change_points')->display(function ($value) {
|
||||
|
|
@ -144,7 +148,9 @@ class PointLogController extends AdminController
|
|||
});
|
||||
|
||||
$grid->filter(function (Grid\Filter $filter) {
|
||||
$stores = Store::pluck('title', 'id')->all();
|
||||
$filter->panel(false);
|
||||
$filter->equal('store_id', __('point-log.fields.store_id'))->select($stores)->width(3);
|
||||
$filter->equal('user.phone')->width(3);
|
||||
$filter->like('administrator.name', '操作人')->width(3);
|
||||
$filter->in('action')->multipleSelect(PointLogAction::options())->width(3);
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ class OrderController extends AdminController
|
|||
$grid->column('sn')->copyable();
|
||||
$grid->column('user_id')->display(function () {
|
||||
$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;
|
||||
return <<<HTML
|
||||
<img src="{$avatar}" width="45" />
|
||||
|
|
@ -59,7 +59,7 @@ class OrderController extends AdminController
|
|||
});
|
||||
$grid->column('inviter_id')->display(function () {
|
||||
$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;
|
||||
return <<<HTML
|
||||
<img src="{$avatar}" width="45" />
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
namespace App\Admin\Controllers;
|
||||
|
||||
use App\Models\{UserVip, Vip};
|
||||
use App\Models\Store\Store;
|
||||
use Dcat\Admin\Form;
|
||||
use Dcat\Admin\Grid;
|
||||
use Dcat\Admin\Http\Controllers\AdminController;
|
||||
|
|
@ -17,11 +18,12 @@ class UserVipController extends AdminController
|
|||
*/
|
||||
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->column('user.phone');
|
||||
$grid->column('store.title');
|
||||
$grid->column('name');
|
||||
$grid->column('times')->display(function ($v) {
|
||||
return data_get($v, 'text');
|
||||
|
|
@ -34,7 +36,9 @@ class UserVipController extends AdminController
|
|||
$grid->disableViewButton(false);
|
||||
|
||||
$grid->filter(function (Grid\Filter $filter) {
|
||||
$stores = Store::pluck('title', 'id')->all();
|
||||
$filter->panel(false);
|
||||
$filter->equal('store_id', __('user-vip.fields.store.title'))->select($stores)->width(3);
|
||||
$filter->like('user.phone')->width(3);
|
||||
$filter->like('name')->width(3);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -40,7 +40,10 @@ class PointChange extends Form implements LazyRenderable
|
|||
try {
|
||||
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();
|
||||
} catch (Throwable $th) {
|
||||
|
|
|
|||
|
|
@ -38,44 +38,21 @@ class MiniprogramController extends Controller
|
|||
$time = now();
|
||||
$ip = $request->realIp();
|
||||
|
||||
$inviter = null;
|
||||
if ($request->filled('invite_code')) {
|
||||
$inviter = $this->findUserByCode($request->input('invite_code', ''));
|
||||
if (!$inviter) {
|
||||
throw new BizException('邀请人不存在');
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
|
||||
$user_social = SocialiteUser::where(['socialite_id' => $openid, 'socialite_type' => $type])->first();
|
||||
|
||||
if (!$user_social) {
|
||||
$attributes = [
|
||||
'register_ip' => $ip,
|
||||
'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;
|
||||
$user_social = SocialiteUser::firstOrCreate(['socialite_id' => $openid, 'socialite_type' => $type]);
|
||||
$user = $user_social->user;
|
||||
$token = '';
|
||||
if ($user) {
|
||||
$token = $user->createToken($type)->plainTextToken;
|
||||
}
|
||||
if (!$user) {
|
||||
throw new BizException($openid);
|
||||
}
|
||||
|
||||
$token = $user->createToken($type);
|
||||
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'openid' => $openid,
|
||||
'token' => $token->plainTextToken
|
||||
'token' => $token
|
||||
]);
|
||||
} catch (Throwable $e) {
|
||||
DB::rollBack();
|
||||
|
|
@ -89,7 +66,6 @@ class MiniprogramController extends Controller
|
|||
|
||||
public function bindPhone(Request $request)
|
||||
{
|
||||
$user = $request->user();
|
||||
$request->validate([
|
||||
'code' => 'required'
|
||||
], [
|
||||
|
|
@ -105,19 +81,26 @@ class MiniprogramController extends Controller
|
|||
}
|
||||
|
||||
$phone = data_get($result, 'phone_info.purePhoneNumber');
|
||||
$openid = $request->input('openid');
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
// 检测手机号是否已经注册
|
||||
$old_user = User::where('phone', $phone)->where('status', User::STATUS_ACTIVE)->where('id', '!=', $user->id)->first();
|
||||
if ($old_user) {
|
||||
// 禁用新用户
|
||||
throw new BizException('手机号已经注册');
|
||||
} else {
|
||||
$user->update([
|
||||
'phone' => $phone,
|
||||
'phone_verified_at' => now(),
|
||||
]);
|
||||
$user = User::where('phone', $phone)->first();
|
||||
if (!$user) {
|
||||
$time = now();
|
||||
$ip = $request->realIp();
|
||||
$inviter = $this->findUserByCode($request->input('invite_code', ''));
|
||||
$user = User::create([
|
||||
'register_ip' => $ip,
|
||||
'last_login_at' => $time,
|
||||
'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);
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ class OfflineOrderController extends Controller
|
|||
$request->user(),
|
||||
$preview,
|
||||
bcmul($request->input('points', 0), 100),
|
||||
['user_remark' => $request->input('user_remark')]
|
||||
);
|
||||
|
||||
DB::commit();
|
||||
|
|
|
|||
|
|
@ -35,43 +35,52 @@ class OfflineOrderPreviewController extends Controller
|
|||
'store_id' => $store->id,
|
||||
'staff_id' => $user->id,
|
||||
'payload' => ['items' => $request->input('items')],
|
||||
'remark' => $request->input('remark')
|
||||
]);
|
||||
|
||||
$scene = http_build_query([
|
||||
'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,
|
||||
if (config('app.env') != "local") {
|
||||
$scene = http_build_query([
|
||||
'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,
|
||||
]);
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ class VipController extends Controller
|
|||
$service = new VipService();
|
||||
try {
|
||||
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'));
|
||||
DB::commit();
|
||||
|
|
|
|||
|
|
@ -232,7 +232,7 @@ Route::group([
|
|||
// 微信小程序
|
||||
Route::group(['prefix' => 'wechat-mini'], function () {
|
||||
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']);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -43,6 +43,8 @@ class OfflineOrder extends Model
|
|||
'revoked_at',
|
||||
'orderable_type',
|
||||
'orderable_id',
|
||||
'user_remark',
|
||||
'staff_remark',
|
||||
];
|
||||
|
||||
public function store()
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ class OfflineOrderPreview extends Model
|
|||
];
|
||||
|
||||
protected $fillable = [
|
||||
'store_id', 'staff_id', 'payload', 'qrcode',
|
||||
'store_id', 'staff_id', 'payload', 'qrcode', 'remark'
|
||||
];
|
||||
|
||||
public function store()
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ use App\Models\Admin\Administrator;
|
|||
use Dcat\Admin\Traits\HasDateTimeFormatter;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use App\Models\Store\Store;
|
||||
|
||||
class PointLog extends Model
|
||||
{
|
||||
|
|
@ -22,6 +23,7 @@ class PointLog extends Model
|
|||
'after_points',
|
||||
'remark',
|
||||
'administrator_id',
|
||||
'store_id'
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
|
|
@ -33,6 +35,11 @@ class PointLog extends Model
|
|||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
public function store()
|
||||
{
|
||||
return $this->belongsTo(Store::class, 'store_id');
|
||||
}
|
||||
|
||||
public function administrator()
|
||||
{
|
||||
return $this->belongsTo(Administrator::class);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|||
use Illuminate\Database\Eloquent\Model;
|
||||
use Dcat\Admin\Traits\HasDateTimeFormatter;
|
||||
|
||||
/**
|
||||
* 门店
|
||||
*/
|
||||
class Store extends Model
|
||||
{
|
||||
use HasFactory, HasDateTimeFormatter;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\Store\Store;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Dcat\Admin\Traits\HasDateTimeFormatter;
|
||||
|
|
@ -14,7 +15,7 @@ class UserVip extends Model
|
|||
const STATUS_SUCCESS = 1;
|
||||
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 = [
|
||||
'times' => 'json',
|
||||
|
|
@ -34,6 +35,11 @@ class UserVip extends Model
|
|||
return $this->belongsTo(User::class, 'user_id');
|
||||
}
|
||||
|
||||
public function store()
|
||||
{
|
||||
return $this->belongsTo(Store::class, 'store_id');
|
||||
}
|
||||
|
||||
public function vip()
|
||||
{
|
||||
return $this->belongsTo(Vip::class, 'vip_id');
|
||||
|
|
|
|||
|
|
@ -398,7 +398,10 @@ class AfterSaleService
|
|||
}
|
||||
|
||||
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,
|
||||
]);
|
||||
}
|
||||
|
||||
//执行实际退款操作;
|
||||
|
|
|
|||
|
|
@ -16,10 +16,11 @@ use App\Models\SocialiteUser;
|
|||
use App\Models\User;
|
||||
use App\Services\Payment\WxpayService;
|
||||
|
||||
use function EasyWeChat\Kernel\data_get;
|
||||
|
||||
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']);
|
||||
|
||||
|
|
@ -54,13 +55,19 @@ class OfflineOrderService
|
|||
'status' => OfflineOrderStatus::Pending,
|
||||
'orderable_type' => $orderPreview->getMorphClass(),
|
||||
'orderable_id' => $orderPreview->id,
|
||||
'user_remark' => data_get($params, 'user_remark'),
|
||||
'staff_remark' => $orderPreview->remark,
|
||||
]);
|
||||
|
||||
$this->insertOrderItems($order, $items);
|
||||
|
||||
// 扣除积分
|
||||
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) {
|
||||
|
|
@ -178,7 +185,11 @@ class OfflineOrderService
|
|||
}
|
||||
|
||||
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([
|
||||
|
|
|
|||
|
|
@ -427,7 +427,10 @@ class OrderService
|
|||
|
||||
// 扣除积分
|
||||
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;
|
||||
|
|
@ -1418,7 +1421,11 @@ class OrderService
|
|||
}
|
||||
|
||||
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([
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*/
|
||||
public function change(
|
||||
User $user,
|
||||
int $points,
|
||||
PointLogAction $action,
|
||||
?string $remark = null,
|
||||
?Model $loggable = null,
|
||||
?Administrator $administrator = null,
|
||||
// ?string $remark = null,
|
||||
// ?Model $loggable = null,
|
||||
// ?Administrator $administrator = null,
|
||||
$options = []
|
||||
) {
|
||||
if ($points === 0) {
|
||||
return;
|
||||
|
|
@ -56,6 +61,9 @@ class PointService
|
|||
$userinfo->update([
|
||||
'points' => $after,
|
||||
]);
|
||||
$remark = data_get($options, 'remark');
|
||||
$loggable = data_get($options, 'loggable');
|
||||
$administrator = data_get($options, 'administrator');
|
||||
|
||||
PointLog::create([
|
||||
'loggable_id' => $loggable?->id,
|
||||
|
|
@ -67,6 +75,7 @@ class PointService
|
|||
'after_points' => $after,
|
||||
'remark' => $remark,
|
||||
'administrator_id' => $administrator?->id,
|
||||
'store_id' => data_get($options, 'store_id'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use Carbon\Carbon;
|
|||
|
||||
class VipService
|
||||
{
|
||||
public function buy(User $user, Vip $vip)
|
||||
public function buy(User $user, Vip $vip, $params = [])
|
||||
{
|
||||
if (!$vip->status) {
|
||||
throw new BizException('该会员卡已关闭');
|
||||
|
|
@ -22,6 +22,7 @@ class VipService
|
|||
'price' => $vip->price,
|
||||
'times' => $vip->times,
|
||||
'gift' => $vip->gift,
|
||||
'store_id' => data_get($params, 'store_id')
|
||||
]);
|
||||
|
||||
return $user_vip;
|
||||
|
|
@ -79,7 +80,7 @@ class VipService
|
|||
* @param UserVip $userVip 购买记录
|
||||
* @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) {
|
||||
return false;
|
||||
|
|
@ -133,13 +134,11 @@ class VipService
|
|||
}
|
||||
|
||||
if (isset($gift['points']) && bccomp($gift['points'], 0, 2) === 1) {
|
||||
(new PointService())->change(
|
||||
$user,
|
||||
bcmul($gift['points'], 100),
|
||||
PointLogAction::Recharge,
|
||||
"购买【{$userVip->name}】赠送积分",
|
||||
$userVip,
|
||||
);
|
||||
(new PointService())->change($user, bcmul($gift['points'], 100), PointLogAction::Recharge, [
|
||||
'remarks' => "购买【{$userVip->name}】赠送积分",
|
||||
'loggable' => $userVip,
|
||||
'store_id' => $userVip->store_id,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ class CreateVipsTable extends Migration
|
|||
$table->id();
|
||||
$table->unsignedBigInteger('user_id')->comment('用户ID');
|
||||
$table->unsignedBigInteger('vip_id')->comment('会员ID');
|
||||
$table->unsignedBigInteger('store_id')->nullable()->comment('开通门店');
|
||||
$table->string('name')->comment('名称');
|
||||
$table->decimal('price', 12, 2)->default(0)->comment('价格');
|
||||
$table->text('times')->comment('时效{num,unit,text}');
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ class CreatePointLogsTable extends Migration
|
|||
$table->unsignedBigInteger('before_points')->comment('变更前的积分');
|
||||
$table->unsignedBigInteger('after_points')->comment('变更后的积分');
|
||||
$table->string('remark')->nullable()->comment('备注');
|
||||
$table->unsignedBigInteger('store_id')->nullable()->comment('所属门店');
|
||||
$table->unsignedBigInteger('administrator_id')->nullable()->comment('管理员ID');
|
||||
$table->timestamps();
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
|
|
@ -23,6 +23,8 @@ return [
|
|||
'status' => '状态',
|
||||
'revoked_at' => '取消时间',
|
||||
'items' => '品类',
|
||||
'user_remark' => '用户备注',
|
||||
'staff_remark' => '员工备注',
|
||||
],
|
||||
'options' => [
|
||||
],
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ return [
|
|||
'point-logs' => '积分流水',
|
||||
],
|
||||
'fields' => [
|
||||
'store_id' => '所属门店',
|
||||
'user_id' => '用户ID',
|
||||
'user'=>[
|
||||
'phone' => '手机号',
|
||||
|
|
|
|||
|
|
@ -18,6 +18,9 @@ return [
|
|||
'points' => '赠送积分',
|
||||
'expired' => '会员有效期',
|
||||
'price' => '价格',
|
||||
'store' => [
|
||||
'title' => '开通门店'
|
||||
],
|
||||
],
|
||||
'options' => [
|
||||
],
|
||||
|
|
|
|||
Loading…
Reference in New Issue