九宫格积分抽奖

36 篇文章 0 订阅

积分抽奖是非常常用的一个模块,里面涉及的业务非常复杂,如果需要对接ERP还需要对数据做事务同步等一系列除了,今天主要讲"独占锁"机制,核心是:一个用户点击立即抽奖进行表行级锁定。废话不多说上效果:

上代码:乐观锁与悲观锁的生动举栗讲解

public function lottery()
    {
        $list = PondSetting::findOne(['store_id' => $this->store_id]);

        if ($list['start_time'] > time() || $list['end_time'] < time()) {
            return [
                'code' => 1,
                'msg' => '活动已结束或未开启'
            ];
        }

        if ($list->type == 1) {
            $start_time = strtotime(date('Y-m-d 00:00:00', time()));
            $end_time = $start_time + 86400;
        } elseif ($list->type == 2) {
            $start_time = $list['start_time'];
            $end_time = $list['end_time'];
        } else {
            return [
                'code' => 1,
                'msg' => '参数错误'
            ];
        }
        $log = PondLog::find()
            ->where(['store_id' => $this->store_id, 'user_id' => $this->user_id])
            ->andWhere(['>', 'create_time', $start_time])
            ->andWhere(['<', 'create_time', $end_time])
            ->count();
        if ($log >= $list['oppty']) {
            return [
                'code' => 1,
                'msg' => '机会已用完'
            ];
        }

        if($list->deplete_register > 0){
            $user = User::findOne(['id' => $this->user_id, 'store_id' => $this->store_id]);
            if($user->integral < $list->deplete_register){
                return [
                    'code' => 1,
                    'msg' => '积分不足',
                ];
            }
        }

        $pond = Pond::find()->where(['store_id' => $this->store_id])->all();

        $succ = array();
        $err = array();
        foreach ($pond as $k => $v) {
            if ($v->type != 5) {
                if ($v->stock > 0) {
                    $succ[$v->id] = $v->stock;
                }
            } else {
                $err[$v->id] = $v->id;
            }
        }


        // $rand = mt_rand(0,10000);
        $rand = $this->random_num(1, 10000);

        $max = array_sum($succ);

        if (empty($err)) {
            if ($max > 0) {
                $id = $this->get_rand($succ);
            } else {
                return [
                    'code' => 1,
                    'msg' => '网络异常'
                ];
            }
        } else {
            if ($rand < $list['probability'] && $max > 0) {
                $id = $this->get_rand($succ);
            } else {
                $id = array_rand($err, 1);
            }
        }

        $form = Pond::findOne([
            'store_id' => $this->store_id,
            'id' => $id
        ]);

        $pondLog = new PondLog;
        $pondLog->store_id = $this->store_id;
        $pondLog->user_id = $this->user_id;
        $pondLog->type = $form->type;
        $pondLog->num = $form->num;
        if ($form->type == 1) {
            $pondLog->num = 0;
            $pondLog->price = floatval($form->price);
        }
        $pondLog->status = 0;
        $pondLog->pond_id = $id;
        $pondLog->coupon_id = $form->coupon_id;
        if ($form->type == 4) {
            $pondLog->attr = $form->attr;
        }
        $pondLog->gift_id = $form->gift_id;
        $pondLog->create_time = time();

        $t = \Yii::$app->db->beginTransaction();
        if ($form->type != 5) {
            $sql = 'select * from ' . Pond::tableName() . ' where store_id = ' . $this->store_id . ' and id = ' . $id . ' for update';
            $pond = \Yii::$app->db->createCommand($sql)->queryOne();

            //判断库存是否大于0
            if ($pond['stock'] > 0) {
                //将库存数量减1
                $form->stock = $pond['stock'] - 1;
                if (!$form->save()) {
                    $t->rollBack();
                    return [
                        'code' => 1,
                        'msg' => '网络异常'
                    ];
                }
            } else {
                $pondLog->type = 5;
                if (empty($err)) {
                    return [
                        'code' => 1,
                        'msg' => '网络异常'
                    ];
                } else {
                    $id = array_rand($err, 1);
                };

                $pondLog->pond_id = $id;
                $pondLog->coupon_id = 0;
                $pondLog->attr = '';
                $pondLog->num = 0;
                $pondLog->gift_id = 0;
                $pondLog->price = 0;
            }
        }
        $msg = '成功';
        if($list->deplete_register > 0){
            $num = (int)$list->deplete_register;

            $user = User::findOne(['id' => $this->user_id, 'store_id' => $this->store_id]);
            //判断是否对接erp会员积分
            if ($user->is_card_user == 1) {
                //推送erp会员积分
                $integralResult = pushIntegrals($this->store_id, $this->user_id, $num * -1, 17, '九宫格抽奖消费');
                if (empty($integralResult) || $integralResult['code'] != 0) {
                    return [
                        'code' => 1,
                        'msg' => $integralResult ? $integralResult['msg'] : '积分不足'
                    ];
                }
            }
            $register = new Register();
            $register->store_id = $this->store_id;
            $register->user_id = $this->user_id;
            $register->register_time = '..';
            $register->addtime = time();
            $register->continuation = 0;
            $register->type = 17;
            $register->integral = $num * -1;
            //$register->save();

            $user->integral -= $num;
            if($user->integral < $num){
                $msg = '积分不足';
            }
            if($user->integral < 0){
                return [
                    'code' => 1,
                    'msg' => '积分不足'
                ];
            }
            if(!$user->save()){
                $t->rollBack();
                return $this->getErrorResponse($user);
            }
            if(!$register->save()){
                $t->rollBack();
                return $this->getErrorResponse($register);
            }
        }

        if ($pondLog->save()) {
            $t->commit();
            $array = [
                'oppty' => $list['oppty'] - $log - 1,
                'id' => $id,
                'p_id' => $pondLog->id,
            ];
            return [
                'code' => 0,
                'msg' => $msg,
                'data' => (object)$array
            ];
        } else {
            return $this->getErrorResponse($pondLog);
        }
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值