You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

176 lines
6.0 KiB

<?php
namespace App\Service\v3\Implementations;
use App\Constants\v3\ErrorCode;
use App\Constants\v3\LogLabel;
use App\Exception\ErrorCodeException;
use App\Model\v3\CouponRec;
use App\Model\v3\CouponUse;
use App\Model\v3\OrderMain;
use App\Service\v3\Interfaces\CouponServiceInterface;
use Hyperf\DbConnection\Db;
use Hyperf\Redis\Redis;
use Hyperf\Utils\ApplicationContext;
class CouponService implements CouponServiceInterface
{
/**
* @inheritDoc
*/
public function do()
{
// TODO: Implement do() method.
}
/**
* @inheritDoc
*/
public function check()
{
// TODO: Implement check() method.
}
/**
* @inheritDoc
*/
public function undo()
{
// TODO: Implement undo() method.
}
/**
* @inheritDoc
*/
public function countAvailableByUser($userId)
{
return mt_rand(0,10);
}
/**
* 缓存优惠券今日使用情况
* @param $userId
* @param $couponId
* @param $couponRecId
* @return bool
*/
public function cacheTodayCouponUsed($userId, $couponId, $couponRecId)
{
$redis = ApplicationContext::getContainer()->get(Redis::class);
$setRes = $redis->sAdd('coupon_' . date('Ymd') . '_used_' . $userId, $couponId);
$expireRes = $redis->expire('coupon_' . date('Ymd') . '_used_' . $userId, strtotime(date('Y-m-d') . ' 23:59:59') - time());
return $setRes && $expireRes;
}
public function allTodayCouponUsed($userId)
{
$redis = ApplicationContext::getContainer()->get(Redis::class);
return $couponTodayUsedIds = $redis->sMembers('coupon_'.date('Ymd').'_used_'.$userId);
}
public function orderUseCoupons($globalOrderId, $couponRecs)
{
Db::beginTransaction();
try {
if (is_array($couponRecs)&&!empty($couponRecs)) {
# 使用记录、更新当前优惠券
foreach ($couponRecs as $key => &$coupon) {
$couponUse = [
'user_id' => $coupon['user_id'],
'user_receive_id' => $coupon['id'],
'coupon_id' => $coupon['coupon_id'],
'order_main_id' => $globalOrderId,
'use_time' => time(),
'return_time' => 0,
'number' => 1,
'status' => 1,
'update_time' => 0,
];
$insertRes = CouponUse::query()->insert($couponUse);
if ($insertRes) {
$status = 0;
$numberRemain = $coupon['number_remain'] - 1;
if ($numberRemain == 0) {
$status = 2;
} elseif ($numberRemain > 0 && $numberRemain < $coupon['number']) {
$status = 1;
} elseif ($numberRemain == $coupon['number']) {
$status = 0;
}
$upRes = CouponRec::query()->where(['id' => $coupon['id']])
->update(['number_remain' => $numberRemain, 'status' => $status]);
if (!$upRes) {
Db::rollBack();
throw new ErrorCodeException(ErrorCode::COUPON_USE_FAILURE);
}
// 缓存使用记录
$usedRes = $this->cacheTodayCouponUsed($coupon['user_id'], $coupon['coupon_id'], $coupon['id']);
if (!$usedRes) {
Db::rollBack();
throw new ErrorCodeException(ErrorCode::COUPON_USE_FAILURE);
}
} else {
Db::rollBack();
throw new ErrorCodeException(ErrorCode::COUPON_USE_FAILURE);
}
}
}
Db::commit();
} catch (\Exception $e) {
Db::rollBack();
throw new ErrorCodeException(ErrorCode::COUPON_USE_FAILURE, $e->getMessage());
}
}
/**
* 退还优惠券,订单取消,申请退款成功时
* 先查询是否正常使用优惠券
* 修改状态,退还领取记录库存,删除ssdb缓存
* @param $globalOrderId
* @return bool
*/
public function orderRefundCoupons($globalOrderId)
{
$currentTime = time();
Db::beginTransaction();
try {
$couponUses = CouponUse::query()
->where('order_main_id', $globalOrderId)
->where('status', 1)
->get();
if (!empty($couponUses)) {
foreach ($couponUses as $use) {
$use->status = 1;
$use->return_time = $currentTime;
$use->update_time = $currentTime;
$res = $use->save();
$couponReceive = CouponRec::query()
->where('id', $use->user_receive_id)
->whereRaw('number >= number_remain+' . $use->number)
->update([
'number_remain' => Db::raw('number_remain+' . $use->number),
'status' => Db::raw('IF(number=number_remain, 0,1)'), 'update_time' => $currentTime
]);
if ($res && $couponReceive) {
$redis = ApplicationContext::getContainer()->get(Redis::class);
$clearUseRedis = $redis->sRem('coupon_' . date('Ymd') . '_used_' . $use->user_id, $use->coupon_id);
}
}
}
Db::commit();
return true;
} catch (\Exception $e) {
$this->log->event(LogLabel::COUPON_REFUND_LOG, ['msg' => '订单取消/退款退还优惠券', 'exception' => $e->getMessage()]);
Db::rollBack();
return false;
}
}
}