202 lines
5.8 KiB
PHP
202 lines
5.8 KiB
PHP
|
<?php
|
||
|
|
||
|
namespace app\traits\account;
|
||
|
|
||
|
use app\exception\ApiRedirectException;
|
||
|
use app\exception\RepositoryException;
|
||
|
use app\model\Account;
|
||
|
use app\model\AccountCoupon;
|
||
|
use app\model\AccountRecord;
|
||
|
use app\model\Coupon;
|
||
|
use app\model\Express;
|
||
|
use app\repository\AccountRepository;
|
||
|
use think\Collection;
|
||
|
use think\db\exception\DataNotFoundException;
|
||
|
use think\db\exception\DbException;
|
||
|
use think\db\exception\ModelNotFoundException;
|
||
|
use think\Model;
|
||
|
use think\Paginator;
|
||
|
|
||
|
/**
|
||
|
* 优惠券相关
|
||
|
*
|
||
|
* Trait CouponTrait
|
||
|
* @package app\traits\order
|
||
|
*/
|
||
|
trait CouponTrait
|
||
|
{
|
||
|
/**
|
||
|
* 领取优惠券
|
||
|
*
|
||
|
* @param int $accountId
|
||
|
* @param int $couponId
|
||
|
* @return void
|
||
|
* @throws DataNotFoundException
|
||
|
* @throws DbException
|
||
|
* @throws ModelNotFoundException
|
||
|
* @throws RepositoryException
|
||
|
* @throws ApiRedirectException
|
||
|
*/
|
||
|
public function getCoupon(int $accountId, int $couponId)
|
||
|
{
|
||
|
|
||
|
if (!$coupon = Coupon::where('id', $couponId)->lock(true)->find()) {
|
||
|
throw new RepositoryException('优惠券不存在或已下架');
|
||
|
}
|
||
|
|
||
|
if (!empty($coupon['deleted_at'])) {
|
||
|
throw new RepositoryException('优惠券不存在或已下架');
|
||
|
}
|
||
|
|
||
|
if (!$account = Account::findById($accountId)) {
|
||
|
throw new RepositoryException('请先登录');
|
||
|
}
|
||
|
|
||
|
if ($coupon['remain'] <= 0) {
|
||
|
throw new RepositoryException('优惠券已领完');
|
||
|
}
|
||
|
|
||
|
if ($coupon['end_at'] <= date('Y-m-d H:i:s')) {
|
||
|
throw new RepositoryException('优惠券已过期');
|
||
|
}
|
||
|
|
||
|
if (AccountCoupon::where('coupon_id', $couponId)->where('account_id', $accountId)->count() > 0) {
|
||
|
throw new RepositoryException('您已领过此券');
|
||
|
}
|
||
|
|
||
|
if ($account['phone_active'] != Account::COMMON_ON) {
|
||
|
throw new ApiRedirectException('请先完善账号资料');
|
||
|
}
|
||
|
|
||
|
AccountCoupon::create([
|
||
|
'account_id' => $accountId,
|
||
|
'coupon_id' => $couponId,
|
||
|
'status' => AccountCoupon::STATUS_NORMAL,
|
||
|
'is_taste' => (int) ($coupon['type'] == Coupon::TYPE_TASTE),
|
||
|
'created_at' => date('Y-m-d H:i:s'),
|
||
|
]);
|
||
|
|
||
|
$coupon->inc('receive')->dec('remain')->update();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 用户优惠券详情
|
||
|
*
|
||
|
* @param int $accountId
|
||
|
* @param int $couponId
|
||
|
*/
|
||
|
public function userCouponInfo(int $accountId, int $couponId)
|
||
|
{
|
||
|
return AccountCoupon::findOne(['account_id' => $accountId, 'coupon_id' => $couponId], [], function ($q) {
|
||
|
return $q->with(["coupon"]);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 过期优惠券检测并处理
|
||
|
*
|
||
|
* @return bool
|
||
|
*/
|
||
|
public function expireHandle(): bool
|
||
|
{
|
||
|
$expiredCouponList = Coupon::where('end_at', '<', date('Y-m-d H:i:s'))->column('id');
|
||
|
if ($expiredCouponList) {
|
||
|
AccountCoupon::whereIn('coupon_id', $expiredCouponList)
|
||
|
->where('status', self::STATUS_NORMAL)
|
||
|
->update(['status' => AccountCoupon::STATUS_INVALID]);
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 获取个人优惠券
|
||
|
*
|
||
|
* @param array $where
|
||
|
* @param int $page
|
||
|
* @param int $size 0 不限 获取全部
|
||
|
* @return AccountCoupon[]|array
|
||
|
*/
|
||
|
public function couponList(array $where, int $page = 1, int $size = 10): array
|
||
|
{
|
||
|
$this->expireHandle();
|
||
|
|
||
|
$status = $where['status'] ?? AccountCoupon::STATUS_NORMAL;
|
||
|
$accountId = $where['account_id'] ?? 0;
|
||
|
$condition = $where['condition'] ?? 0;
|
||
|
|
||
|
$page = $page ?: 1;
|
||
|
$size = $size ?: 10;
|
||
|
|
||
|
$res = [
|
||
|
'total' => 0,
|
||
|
'current' => $page,
|
||
|
'size' => $size,
|
||
|
'list' => new Collection(),
|
||
|
];
|
||
|
|
||
|
$query = AccountCoupon::alias('ac')
|
||
|
->leftJoin('coupon c', 'ac.coupon_id = c.id')
|
||
|
->where('ac.account_id', $accountId)
|
||
|
->where('ac.status', $status)
|
||
|
->where('c.condition', '<=', $condition);
|
||
|
$res['total'] = $query->count();
|
||
|
|
||
|
if ($res['total'] > 0) {
|
||
|
$list = $query->field('ac.id,ac.account_id,ac.created_at,ac.coupon_id,ac.status,c.amount,c.name,c.condition,c.begin_at,c.end_at')
|
||
|
->page($page, $size)
|
||
|
->order('created_at', 'desc')
|
||
|
->select();
|
||
|
$res['list'] = $list;
|
||
|
}
|
||
|
|
||
|
return $res;
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 检测并处理过期优惠券
|
||
|
*
|
||
|
* @param int $accountId
|
||
|
*/
|
||
|
public function checkExpire(int $accountId)
|
||
|
{
|
||
|
$accountCouponList = AccountCoupon::where('account_id', $accountId)
|
||
|
->where('status', AccountCoupon::STATUS_NORMAL)
|
||
|
->column('coupon_id');
|
||
|
$expiredList = Coupon::whereIn('id', $accountCouponList)
|
||
|
->where('end_at', '<=', date('Y-m-d H:i:s'))
|
||
|
->column('id');
|
||
|
if (!empty($expiredList)) {
|
||
|
AccountCoupon::where('account_id', $accountId)
|
||
|
->whereIn('coupon_id', $expiredList)
|
||
|
->save([
|
||
|
'status' => AccountCoupon::STATUS_INVALID,
|
||
|
]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 创建一个体验券展示二维码
|
||
|
*
|
||
|
* @param int $accountId
|
||
|
* @param int $couponId
|
||
|
*/
|
||
|
public function createExperienceCouponQR($accountId, $couponId)
|
||
|
{
|
||
|
return md5($accountId.AccountCoupon::CODE_SALT.$couponId);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 验证一个体验券展示二维码
|
||
|
*
|
||
|
* @param int $accountId
|
||
|
* @param int $couponId
|
||
|
* @param string $secret
|
||
|
*/
|
||
|
public function checkExperienceCouponQR($accountId, $couponId, $secret)
|
||
|
{
|
||
|
return ($secret == md5($accountId.AccountCoupon::CODE_SALT.$couponId)) ? true : "秘钥核验失败";
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|