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.
388 lines
13 KiB
388 lines
13 KiB
<?php
|
|
|
|
namespace App\Service;
|
|
|
|
use Hyperf\Di\Annotation\Inject;
|
|
use Hyperf\DbConnection\Db;
|
|
use App\Model\CouponUserRecType;
|
|
use App\Model\Coupon;
|
|
use App\Model\CouponRec;
|
|
use App\Model\CouponUserUse;
|
|
use Hyperf\Utils\ApplicationContext;
|
|
use App\TaskWorker\SSDBTask;
|
|
use App\Constants\SsdbKeysPrefix;
|
|
use App\Constants\LogLabel;
|
|
use App\Commons\Log;
|
|
use Exception;
|
|
use App\Service\CommonService;
|
|
use Hyperf\Redis\Redis;
|
|
|
|
class CouponService implements CouponServiceInterface
|
|
{
|
|
/**
|
|
* @Inject
|
|
* @var Log
|
|
*/
|
|
protected $log;
|
|
|
|
/**
|
|
* @Inject
|
|
* @var CommonService
|
|
*/
|
|
protected $commonService;
|
|
|
|
/**
|
|
* 获取用户可领取优惠卷接口
|
|
*/
|
|
public function getSystemCouponUserList($userId,$receiveType)
|
|
{
|
|
/* 优惠券活动标志 2 */
|
|
$ssdb = ApplicationContext::getContainer()->get(SSDBTask::class);
|
|
$couponActivity = $ssdb->exec('hgetall', SsdbKeysPrefix::COUPON_REBATE_ACTIVITY);
|
|
$activityType = $couponActivity === false ? 0 : $couponActivity['activity'];
|
|
|
|
$result = [
|
|
'active_type' => 1,
|
|
'not_receive' => [],
|
|
'jump_data' => [
|
|
'src' => "/zh_cjdianc/pages/couponrebate/index?activity_type=".$activityType,
|
|
'src2' => "/zh_cjdianc/pages/couponrebate/index?activity_type=".$activityType,
|
|
'share_bg' => env('OSS_IMG_HOST').'/static/img/coupon_share.png',
|
|
'receive_bg' => env('OSS_IMG_HOST').'/static/img/coupon_bg.png',
|
|
'coupons' => []
|
|
]
|
|
];
|
|
$nowTime = time();
|
|
$c_ids = [];
|
|
$whereC = [
|
|
['end_time','>',$nowTime],
|
|
['start_time','<=',$nowTime],
|
|
['status','=',1]
|
|
];
|
|
// 渠道开启,查询该渠道可以领取的优惠券ID
|
|
// 渠道未开启,查询所有优惠券
|
|
if (env('SUB_CHANNEL') == 1) {
|
|
$c_ids = CouponUserRecType::where('receive_type', $receiveType)->where($whereC)->pluck('system_coupon_user_id');
|
|
} else {
|
|
$c_ids = Coupon::where($whereC)->pluck('id');
|
|
}
|
|
|
|
$couponReceive = CouponRec::where('user_id',$userId);
|
|
|
|
// 渠道开启,查询该用户在此渠道领过的优惠券ID
|
|
if (env('SUB_CHANNEL') == 1) {
|
|
$couponReceive->where('receive_type', $receiveType);
|
|
}
|
|
$cr_ids = $couponReceive->pluck('system_coupon_user_id');
|
|
|
|
// 可领取的券ID
|
|
$c_ids = $c_ids->toArray();
|
|
// 已经领取的券ID
|
|
$cr_ids = $cr_ids->toArray();
|
|
|
|
// 当前用户可领的优惠券ID
|
|
$couponIds = array_diff($c_ids, $cr_ids);
|
|
|
|
// 转发型优惠券
|
|
$couponReceiveIds = ($couponActivity === false || $this->commonService->empty($couponActivity['forward']) )? [] : explode(',',$couponActivity['forward']);
|
|
// 所有优惠券
|
|
$couponIds = array_merge($couponIds,$couponReceiveIds);
|
|
|
|
$whereC = [
|
|
['u.end_time','>',$nowTime],
|
|
['u.start_time','<=',$nowTime],
|
|
['u.status','=',1]
|
|
];
|
|
// 查询领取型1 和 转发型2
|
|
$whereActiveType = [1,2];
|
|
|
|
if (env('SUB_CHANNEL') == 1) {
|
|
array_push($whereC, ['type.receive_type','=', $receiveType]);
|
|
}
|
|
|
|
$coupons = Db::table('ims_system_coupon_user as u')
|
|
->join('ims_system_coupon_user_receivetype as type', 'u.id', '=', 'type.system_coupon_user_id')
|
|
->whereIn('u.id', $couponIds)
|
|
->whereIn('u.active_type', $whereActiveType)
|
|
->where($whereC)
|
|
->whereRaw('u.inventory_use < u.inventory and u.inventory-u.inventory_use >= type.one_receive_number')
|
|
->select('u.*','type.one_receive_number')
|
|
->orderBy('u.weigh','desc')
|
|
->get();
|
|
|
|
foreach ($coupons as $k => &$v){
|
|
|
|
if($v->active_type == 1 && count($result['not_receive']) < 4){
|
|
$result['not_receive'][] = $v;
|
|
}else if($v->active_type == 2 && in_array($v->id,$couponReceiveIds)){
|
|
$result['jump_data']['coupons'][] = $v->id;
|
|
}
|
|
|
|
if($v->discount_type == 2){
|
|
$v->discounts = floatval($v->discounts);
|
|
}
|
|
}
|
|
|
|
$result['active_type'] = count($result['jump_data']['coupons']) > 0 ? 2 : $result['active_type'] ;
|
|
|
|
return $result;
|
|
}
|
|
|
|
//统计用户
|
|
public function userCouponAccount()
|
|
{
|
|
|
|
}
|
|
|
|
/**
|
|
* 用户领取优惠卷
|
|
*/
|
|
public function userReceiveCoupon()
|
|
{
|
|
|
|
}
|
|
|
|
/**
|
|
* 获取用户已经领取的优惠卷列表
|
|
*/
|
|
public function getUserReceiveCouponList()
|
|
{
|
|
|
|
}
|
|
|
|
/**
|
|
* 获取用户当前订单可用的优惠券列表
|
|
* 按分类(1订单 等优惠)分组返回
|
|
*/
|
|
public function getUserAvailableCoupons($orderAmount,$userId,$marketId,$type,$storetypeId)
|
|
{
|
|
$storetypeIds = explode(',', str_replace(',', ',', $storetypeId));
|
|
|
|
$available = [];
|
|
$notAvailable = [];
|
|
|
|
if ($this->empty($orderAmount) || $this->empty($userId)) {
|
|
return $this->success([
|
|
'available' => $available,
|
|
'not_available' => array_values($notAvailable)
|
|
]);
|
|
}
|
|
|
|
// 获取用户优惠券
|
|
$currentTime = time();
|
|
|
|
$data = Db::table('ims_system_coupon_user_receive as receive')
|
|
->select([
|
|
'receive.id as receive_id',
|
|
'receive.user_id',
|
|
'receive.number_remain',
|
|
'coupon.id',
|
|
'coupon.title',
|
|
'coupon.full_amount',
|
|
'coupon.discounts',
|
|
'coupon.usable_start_time',
|
|
'coupon.usable_end_time',
|
|
'coupon.discount_type'
|
|
])
|
|
->join('ims_system_coupon_user as coupon', 'coupon.id', '=', 'receive.system_coupon_user_id')
|
|
->where(['receive.user_id' => $userId])
|
|
->whereIn('receive.status', [0,1])
|
|
->where('receive.number_remain', '>', 0)
|
|
->whereIn('coupon.type', [1,$type])
|
|
->where('coupon.full_amount', '<=', $orderAmount)
|
|
->where('coupon.usable_start_time', '<=', $currentTime)
|
|
->where('coupon.usable_end_time', '>=', $currentTime)
|
|
->where('coupon.usable_number', '<=', Db::raw('receive.number_remain'))
|
|
->where('coupon.market_id', 'in', [0, $marketId])
|
|
->whereIn('coupon.storetype_id', $storetypeIds)
|
|
->orderByRaw('coupon.discounts DESC, coupon.full_amount DESC')
|
|
->get();
|
|
|
|
// 分离用户今天用过的优惠券种类
|
|
$container = ApplicationContext::getContainer();
|
|
$redis = $container->get(Redis::class);
|
|
$couponIds = $redis->sMembers('coupon_'.date('Ymd').'_used_'.$userId);
|
|
|
|
foreach ($data as $key => &$item) {
|
|
if (in_array($item->id, $couponIds)) {
|
|
$notAvailable[$item->id] = $item;
|
|
} else {
|
|
$available[] = $item;
|
|
}
|
|
}
|
|
|
|
return [
|
|
'available' => $available,
|
|
'not_available' => array_values($notAvailable)
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
public function getOrderCanUseCoupons($orderAmount, $marketId, $userId, $fields=[], $type = 1, $storeTypeIds = [0])
|
|
{
|
|
|
|
// 用户今日使用过的优惠券
|
|
$redis = ApplicationContext::getContainer()->get(Redis::class);
|
|
$couponTodayUsedIds = $redis->sMembers('coupon_'.date('Ymd').'_used_'.$userId);
|
|
$currentTime = time();
|
|
|
|
$builder = Db::table('ims_system_coupon_user_receive as receive')
|
|
->join('ims_system_coupon_user as coupon', 'coupon.id', '=', 'receive.system_coupon_user_id', 'inner');
|
|
|
|
if (is_array($fields)&&!empty($fields)) {
|
|
$builder->select($fields);
|
|
}
|
|
|
|
if (is_array($couponTodayUsedIds)&&!empty($couponTodayUsedIds)) {
|
|
$builder->whereNotIn('coupon.id', $couponTodayUsedIds);
|
|
}
|
|
|
|
return $builder->where(['receive.user_id' => $userId])
|
|
->whereIn('receive.status', [0,1])
|
|
->where('receive.number_remain', '>', 0)
|
|
->whereIn('coupon.type', [1,$type])
|
|
->where('coupon.full_amount', '<=', $orderAmount)
|
|
->where('coupon.usable_start_time', '<=', $currentTime)
|
|
->where('coupon.usable_end_time', '>=', $currentTime)
|
|
->where('coupon.usable_number', '<=', Db::raw('receive.number_remain'))
|
|
->where('coupon.market_id', 'in', [0, $marketId])
|
|
->whereIn('coupon.storetype_id', $storeTypeIds)
|
|
->orderByRaw('coupon.discounts DESC, coupon.full_amount DESC')
|
|
->get()
|
|
->toArray();
|
|
}
|
|
|
|
/**
|
|
* 缓存优惠券今日使用情况
|
|
* @param $userId
|
|
* @param $couponId
|
|
* @param $couponRecId
|
|
* @return bool
|
|
*/
|
|
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;
|
|
}
|
|
|
|
/**
|
|
* 取消订单返券
|
|
* @param $order_id
|
|
* @return bool
|
|
*/
|
|
public function refundOrderCoupons($order_id){
|
|
$coupon = CouponUserUse::where([
|
|
['order_main_id','=',$order_id],
|
|
['status','=',CouponUserUse::COUPON_USE_STATE_USED],
|
|
])
|
|
->select('id','user_receive_id','number')
|
|
->first();
|
|
|
|
if (empty($coupon)) {
|
|
return '';
|
|
}
|
|
|
|
// 返回用户优惠券数量并更新状态
|
|
$res = Db::update("UPDATE ims_system_coupon_user_receive SET number_remain=number_remain+{$coupon->number}, status=IF(number=number_remain,0,1), update_time=".time().""
|
|
." WHERE id={$coupon->user_receive_id} AND number>=(number_remain+{$coupon->number})");
|
|
|
|
// 更新使用记录状态为已退回
|
|
CouponUserUse::where([
|
|
['id','=',$coupon->id],
|
|
['status','=',CouponUserUse::COUPON_USE_STATE_USED],
|
|
])
|
|
->update([
|
|
'status' => CouponUserUse::COUPON_USE_STATE_CANCEL,
|
|
'return_time' => time(),
|
|
'update_time' => time(),
|
|
]);
|
|
|
|
//删除当日 redis 使用记录缓存
|
|
$order_main = OrderMain::where('id',$order_id)
|
|
->select('global_order_id','user_id')
|
|
->first();
|
|
$redis = ApplicationContext::getContainer()->get(Redis::class);
|
|
$remRes = $redis->sRem(
|
|
'coupon_'.date('Ymd').'_used_'.$order_main->user_id,
|
|
$coupon->system_coupon_id
|
|
);
|
|
return $res;
|
|
}
|
|
|
|
/* 删除-优惠券今日使用的缓存
|
|
* @param $userId
|
|
* @param $couponId
|
|
* @return bool
|
|
*/
|
|
public function clearTodayCouponUsed($userId, $couponId)
|
|
{
|
|
|
|
$redis = ApplicationContext::getContainer()->get(Redis::class);
|
|
|
|
$res = $redis->sRem(
|
|
'coupon_'.date('Ymd').'_used_'.$userId,
|
|
$couponId
|
|
);
|
|
return $res;
|
|
}
|
|
|
|
/**
|
|
* 退款返还优惠券
|
|
* 先查询是否正常使用优惠券
|
|
* 修改状态,退还领取记录库存,删除ssdb缓存
|
|
*/
|
|
public function orderRefundCoupons($global_order_id)
|
|
{
|
|
$time = time();
|
|
Db::beginTransaction();
|
|
try {
|
|
$couponUses = CouponUserUse::query()
|
|
->select('id','system_coupon_id','user_id','number','user_receive_id')
|
|
->where('global_order_id',$global_order_id)
|
|
->where('status',CouponUserUse::COUPON_USE_STATE_USED)
|
|
->select();
|
|
if(!empty($couponUse)){
|
|
foreach($couponUses as $use){
|
|
$use->status = CouponUserUse::COUPON_USE_STATE_USED;
|
|
$use->return_time = $time;
|
|
$use->update_time = $time;
|
|
$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,' . CouponRec::STATE_UNUSED . ',' . CouponRec::STATE_SOME . ')'),
|
|
'update_time' => $time
|
|
]);
|
|
|
|
$clearUseRedis = $this->clearTodayCouponUsed($use->user_id,$use->system_coupon_id);
|
|
}
|
|
}
|
|
|
|
Db::commit();
|
|
return true;
|
|
} catch (Exception $e) {
|
|
|
|
$this->log->event(LogLabel::ORDER_LOG, ['msg'=> '订单退款','exception' => $e->getMessage()]);
|
|
Db::rollBack();
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
}
|