public static function createDefaultMemberShipCard($accountId) { $defaultMemberShipCard = Yii::$app->params['default_member_ship_card']; $memberShipCard = new MemberShipCard(); $memberShipCard->attributes = $defaultMemberShipCard; $memberShipCard->accountId = $accountId; if (!$memberShipCard->save()) { throw new Exception("Fail to save default membership card"); } }
/** * Clear card expired time if account's card all are auto upgrade */ public function actionClearCardExpiredTime() { $accounts = Account::findAll(['enabledMods' => 'member']); foreach ($accounts as $account) { $unAutoUpgradeCards = MemberShipCard::findAll(['isAutoUpgrade' => false, 'accountId' => $account->_id]); if (empty($unAutoUpgradeCards)) { Member::updateAll(['$unset' => ['cardExpiredAt' => true]], ['accountId' => $account->_id]); } } }
public function perform() { $args = $this->args; if (empty($args['accountId']) || empty($args['key']) || empty($args['header'])) { ResqueUtil::log(['status' => 'fail to export member', 'message' => 'missing params', 'args' => $args]); return false; } Yii::$app->language = empty($args['language']) ? LanguageUtil::DEFAULT_LANGUAGE : $args['language']; $accountId = new \MongoId($args['accountId']); $header = $args['header']; // get member's customized properties $memberProperties = MemberProperty::getByAccount($accountId); foreach ($memberProperties as $memberProperty) { if ($memberProperty->isDefault) { $header[$memberProperty->name] = Yii::t('member', $memberProperty->name); } else { $header[$memberProperty->name] = $memberProperty->name; } } $socialAccountsMap = []; $account = Account::findByPk($accountId); $channelIds = Channel::getEnableChannelIds($accountId); if (!empty($channelIds)) { $socialAccounts = \Yii::$app->weConnect->getAccounts($channelIds); foreach ($socialAccounts as $socialAccount) { $socialAccountsMap[$socialAccount['id']] = $socialAccount['name']; } } $cardMap = []; $cards = MemberShipCard::getByAccount($accountId); foreach ($cards as $card) { $cardMap[(string) $card->_id] = $card->name; } $condition = unserialize($args['condition']); //get properties $memberProperties = MemberProperty::findAll(['accountId' => $accountId]); $base = ['cardMap' => $cardMap, 'socialAccountsMap' => $socialAccountsMap, 'memberProperties' => $memberProperties]; $fileName = $args['key']; $filePath = ExcelUtil::getFile($fileName, 'csv'); $orderBy = Member::normalizeOrderBy($args['params']); $object = Member::find(); $classFunction = '\\backend\\modules\\member\\models\\Member::preProcessMemberData'; ExcelUtil::processMultiData($header, $filePath, $base, $condition, $object, $classFunction, [], $orderBy); $hashKey = ExcelUtil::setQiniuKey($filePath, $fileName); if ($hashKey) { //notice frontend the job is finished \Yii::$app->tuisongbao->triggerEvent(Message::EVENT_EXPORT_FINISH, ['key' => $fileName], [Message::CHANNEL_GLOBAL . $args['accountId']]); return true; } else { return false; } }
/** * Automatic clear member score. */ public function actionResetScore() { $month = intval(date('m')); $day = intval(date('d')); $memberShipCards = MemberShipCard::find()->where(['isDeleted' => BaseModel::NOT_DELETED, 'scoreResetDate.month' => $month, 'scoreResetDate.day' => $day])->all(); if (!empty($memberShipCards)) { foreach ($memberShipCards as $memberShipCard) { $members = Member::find()->where(['isDeleted' => BaseModel::NOT_DELETED, 'cardId' => $memberShipCard->_id, 'score' => ['$ne' => 0]])->all(); if (!empty($members)) { foreach ($members as $member) { Member::resetScore($member->_id, $member->accountId); } } } } }
/** * Follower bind to be a member. * * <b>Request Type</b>: POST<br/><br/> * <b>Request Endpoint</b>:http://{server-domain}/api/mobile/bind<br/><br/> * <b>Response Content-type</b>: application/json<br/><br/> * <b>Summary</b>: This api is used for follower bind. * <br/><br/> * * <b>Request Params</b>:<br/> * mobile: string<br/> * openId: string<br/> * unionId: string<br/> * channelId: string<br/> * captcha: string<br/> * <br/><br/> * * <b>Response Params:</b><br/> * <br/><br/> * * <br/><br/> * * <b>Response Example</b>:<br/> * <pre> * { * "message": "OK", * "data": "http://wm.com?memberId=55d29e86d6f97f72618b4569" * </pre> */ public function actionBind() { //set language zh_cn when bind Yii::$app->language = LanguageUtil::LANGUAGE_ZH; $params = $this->getParams(); if (empty($params['mobile']) || empty($params['openId']) || empty($params['channelId']) || empty($params['captcha'])) { throw new BadRequestHttpException('missing param'); } $isTest = false; if ($params['mobile'] == self::TEST_PHONE && $params['captcha'] == self::TEST_CODE) { $isTest = true; } else { $this->attachBehavior('CaptchaBehavior', new CaptchaBehavior()); $this->checkCaptcha($params['mobile'], $params['captcha']); } //get accountId $openId = $params['openId']; $channel = Channel::getEnableByChannelId($params['channelId']); $origin = $channel->origin; $accountId = $channel->accountId; //create accessToken $token = Token::createForMobile($accountId); if (empty($token['accessToken'])) { throw new ServerErrorHttpException('Failed to create token for unknown reason.'); } $accessToken = $token['accessToken']; $this->setAccessToken($accessToken); //if member has bind if (empty($params['unionId'])) { $member = Member::getByOpenId($openId); } else { $unionId = $params['unionId']; $member = Member::getByUnionid($unionId); } if (!empty($member)) { $memberId = (string) $member->_id; $url = $this->buildBindRedirect($memberId, $params); return ['message' => 'OK', 'data' => $url]; } //check mobile has been bind $member = Member::getByMobile($params['mobile'], new \MongoId($accountId)); if (!empty($member)) { throw new InvalidParameterException(['phone' => Yii::t('common', 'phone_has_been_bound')]); } $follower = Yii::$app->weConnect->getFollowerByOriginId($openId, $params['channelId']); $originScene = empty($follower['firstSubscribeSource']) ? '' : $follower['firstSubscribeSource']; //init avatar and location $avatar = !empty($follower['headerImgUrl']) ? $follower['headerImgUrl'] : Yii::$app->params['defaultAvatar']; $location = []; !empty($follower['city']) ? $location['city'] = $follower['city'] : null; !empty($follower['province']) ? $location['province'] = $follower['province'] : null; !empty($follower['country']) ? $location['country'] = $follower['country'] : null; LogUtil::info(['message' => 'get follower info', 'follower' => $follower], 'channel'); //init member properties $memberProperties = MemberProperty::getByAccount($accountId); $propertyMobile = []; $propertyGender = []; $propertyName = []; $properties = []; foreach ($memberProperties as $memberProperty) { if ($memberProperty['name'] == Member::DEFAULT_PROPERTIES_MOBILE) { $propertyMobile['id'] = $memberProperty['_id']; $propertyMobile['name'] = $memberProperty['name']; $propertyMobile['value'] = $params['mobile']; $properties[] = $propertyMobile; } if ($memberProperty['name'] == Member::DEFAULT_PROPERTIES_GENDER) { $propertyGender['id'] = $memberProperty['_id']; $propertyGender['name'] = $memberProperty['name']; $propertyGender['value'] = !empty($follower['gender']) ? strtolower($follower['gender']) : 'male'; $properties[] = $propertyGender; } if ($memberProperty['name'] == Member::DEFAULT_PROPERTIES_NAME) { $propertyName['id'] = $memberProperty['_id']; $propertyName['name'] = $memberProperty['name']; $propertyName['value'] = $follower['nickname']; $properties[] = $propertyName; } } //get default card $card = MemberShipCard::getDefault($accountId); $memberId = new \MongoId(); $memberAttribute = ['$set' => ['_id' => $memberId, 'avatar' => $avatar, 'cardId' => $card['_id'], 'location' => $location, 'score' => 0, 'socialAccountId' => $params['channelId'], 'properties' => $properties, 'openId' => $openId, 'origin' => $origin, 'originScene' => $originScene, 'unionId' => empty($unionId) ? '' : $unionId, 'accountId' => $accountId, 'cardNumber' => Member::generateCardNumber($card['_id']), 'cardProvideTime' => new \MongoDate(), 'createdAt' => new \MongoDate(), 'socials' => [], 'isDeleted' => false]]; if (!$isTest) { $result = Member::updateAll($memberAttribute, ['openId' => $openId], ['upsert' => true]); } else { $result = true; } if ($result) { // reword score first bind card $this->attachBehavior('MemberBehavior', new MemberBehavior()); $this->updateItemByScoreRule(Member::findByPk($memberId)); Yii::$app->qrcode->create(Yii::$app->request->hostInfo, Qrcode::TYPE_MEMBER, $memberId, $accountId); $memberId = (string) $memberId; $url = $this->buildBindRedirect($memberId, $params); return ['message' => 'OK', 'data' => $url]; } else { LogUtil::error(['error' => 'member save error', 'params' => Json::encode($member)], 'member'); throw new ServerErrorHttpException("bind fail"); } }
public function upgradeCard() { $currentCard = MemberShipCard::findByPk($this->cardId); if (isset($currentCard->isAutoUpgrade) && $currentCard->isAutoUpgrade) { // get the right card according member score. $card = MemberShipCard::getSuitableCard($this->totalScore, $this->accountId); $cardCondition = $card->condition; $currentCardCondition = $currentCard->condition; // if member's card is not right, update member card if (!empty($card->_id) && (string) $this->cardId != (string) $card->_id && $cardCondition['minScore'] > $currentCardCondition['minScore']) { $this->cardId = $card->_id; $this->save(false, ['cardId']); } } }
/** * Validator for field 'condition' * condition can not be mixed. for example: * the right condition [0, 200], [201, 300], [400, 600] * the error condition [0, 200], [100, 300] * @param object $card * @throws InvalidParameterException */ private function _validateCard($card) { $accountId = new \MongoId($card->accountId); //validate name $memberShipCard = MemberShipCard::getByName($card->name, $accountId); if (!empty($memberShipCard) && $memberShipCard->_id . '' != $card->_id . '') { throw new InvalidParameterException(['cardName' => \Yii::t('member', 'unique_filed')]); } if (!$card->isAutoUpgrade) { $card->condition = null; return; } //validate condition $condition = $card->condition; if (!isset($condition['minScore']) || !is_int($condition['minScore']) || $condition['minScore'] < 0) { throw new InvalidParameterException(['conditionScore' => \Yii::t('member', 'positive_integer_required')]); } else { // minScore can not be overlap $minscoreCard = MemberShipCard::getByScore($condition['minScore'], $accountId); if (!empty($minscoreCard) && $minscoreCard->_id . '' != $card->_id . '') { throw new InvalidParameterException(['conditionScore' => \Yii::t('member', 'score_overlap_error')]); } } if (!isset($condition['maxScore']) || !is_int($condition['maxScore']) || isset($condition['minScore']) && $condition['maxScore'] < $condition['minScore']) { throw new InvalidParameterException(['conditionScore' => \Yii::t('member', 'positive_integer_required')]); } else { //max score can not be overlap $maxscoreCard = MemberShipCard::getByScore($condition['maxScore'], $accountId); if (!empty($maxscoreCard) && $maxscoreCard->_id . '' != $card->_id . '') { throw new InvalidParameterException(['conditionScore' => \Yii::t('member', 'score_overlap_error')]); } else { $allCards = MemberShipCard::getAutoUpgradeByAccount($accountId); // if card condition contain others condition. throw exception // for example:The condition [100, 201] and [100, 400] is error if there is a condition [200,300]. foreach ($allCards as $item) { $preCondition = $item->condition; if ($condition['minScore'] < $preCondition['minScore'] && $condition['maxScore'] > $preCondition['maxScore'] && $card->_id . '' != $item->_id . '') { throw new InvalidParameterException(['conditionScore' => \Yii::t('member', 'score_overlap_error')]); } } } } }
public function perform() { # Run task $args = $this->args; //the key for wrong number for store in redis $wrongKey = self::MEMBER_WRONG; switch ($args['type']) { case self::JOB_DELETE_REDIS_CODE: if (!isset($args['filename']) || !isset($args['accountId'])) { ResqueUtil::log(['error' => 'missing param', 'param' => $args]); return false; } $redis = \Yii::$app->cache->redis; $cacheSetInsert = self::SET_HEAD_INSERT . md5($args['accountId'] . "_" . $args['fileName']); $cacheSetUpdate = self::SET_HEAD_UPDATE . md5($args['accountId'] . "_" . $args['fileName']); $redis->del($cacheSetInsert); $redis->del($cacheSetUpdate); unset($commonKey, $cacheTotalKey, $count); break; case self::JOB_INSERT: if (!isset($args['accountId']) || empty($args['filename']) || empty($args['hostInfo'])) { ResqueUtil::log(['error' => 'missing params', 'param' => $args]); } $redis = Yii::$app->cache->redis; $cacheKey = $args['accountId'] . "_" . $args['filename']; $createdAt = new \MongoDate(time()); $redis->expire($cacheKey, self::EXPIRE); $cacheSetInsert = self::SET_HEAD_INSERT . md5($cacheKey); $cacheSetUpdate = self::SET_HEAD_UPDATE . md5($cacheKey); // status $cacheSetLackProperties = self::MEMBER_IMPORT_NO_PROPERTY . md5($cacheKey); // get total of excel. $totalInsert = $redis->scard($cacheSetInsert); $totalUpdate = $redis->scard($cacheSetUpdate); // batch insert member. $memberInsert = []; $keyInsert = $redis->smembers($cacheSetInsert); // update member. $keyUpdate = $redis->smembers($cacheSetUpdate); // unserialize. if (count($keyInsert) > 0) { $defaultCard = MemberShipCard::getDefault(new MongoId($args['accountId'])); if (empty($defaultCard)) { ResqueUtil::log('Lack of default MemberShip Card'); // 0 $redis->Hset($cacheSetLackProperties, $wrongKey, self::MEMBER_NO_DEFAULT_PROPERTIES); return false; } $cardId = $defaultCard->_id; $origin = Member::PORTAL; $tels = []; for ($rowIndex = 0; $rowIndex < $totalInsert; $rowIndex++) { $memberKey = unserialize($keyInsert[$rowIndex]); $cardNumber = Member::generateCardNumber(); $properties = []; $memberTag = []; foreach ($memberKey[0] as $item) { if (!empty($item['name'])) { if ($item['name'] == Member::DEFAULT_PROPERTIES_MOBILE) { $telItem = $item; } $properties[] = $item; } else { $memberTag[] = $item['tags']; } } $tels[] = $telItem; $memberMessage = ["properties" => $properties, "tags" => $memberTag, "cardId" => $cardId, "origin" => $origin, "cardNumber" => empty($cardNumber) ? 0 : $cardNumber, "location" => ["country" => "", "province" => "", "city" => "", "detail" => ""], "avatar" => Yii::$app->params['defaultAvatar'], "score" => 0, "totalScore" => 0, "socials" => [], "qrcodeViewed" => false, "isDisabled" => false, "totalScoreAfterZeroed" => 0, "accountId" => new MongoId($args['accountId']), "cardProvideTime" => new \MongoDate()]; $memberInsert[] = $memberMessage; } // batch insert member. $insertMemberResult = Member::batchInsert($memberInsert); if ($insertMemberResult) { ResqueUtil::log(['ok' => 'Batch insert member is success', 'data' => $memberInsert]); } else { ResqueUtil::log(['error' => 'Batch insert member is fail', 'data' => $memberInsert]); $redis->Hset($cacheSetLackProperties, $wrongKey, self::MEMBER_NO_DEFAULT_PROPERTIES); } //create qrcode. foreach ($tels as $param) { $member = Member::findOne(['properties' => ['$elemMatch' => ['name' => $param['name'], 'value' => $param['value']]], 'accountId' => new MongoId($args['accountId'])]); Member::webhookEvent($member); MemberLogs::record($member->_id, new MongoId($args['accountId']), MemberLogs::OPERATION_VIEWED); if (!defined('KLP') || !KLP) { $a = Yii::$app->qrcode->create($args['hostInfo'], Qrcode::TYPE_MEMBER, $member->_id, new MongoId($args['accountId'])); } Member::birthdayScore($member); } } // update member. if (count($keyUpdate) > 0) { for ($rowIndex = 0; $rowIndex < $totalUpdate; $rowIndex++) { $memberKey = unserialize($keyUpdate[$rowIndex]); $memberProperty = $memberKey[0]; $condition = []; $updateData = []; $memberUpdate = []; $memberTag = []; foreach ($memberProperty as $member) { if (!empty($member['name'])) { if ($member['name'] == Member::DEFAULT_PROPERTIES_MOBILE) { $condition = ["properties.value" => $member['value']]; } $memberUpdate[] = $member; } else { $memberTag[] = $member['tags']; } } $updateData[] = ["properties" => $memberUpdate, "tags" => $memberTag]; $updateMemberResult = Member::updateAll(['$set' => $updateData[0]], $condition); if ($updateMemberResult) { ResqueUtil::log(['ok' => 'Update member is success', 'data' => $memberInsert]); } else { ResqueUtil::log(['error' => 'Update member is fail', 'data' => $memberInsert]); $redis->Hset($cacheSetLackProperties, $wrongKey, self::MEMBER_NO_DEFAULT_PROPERTIES); } } } break; default: break; } }
public function actionCreate() { $params = $this->getParams(); $accountId = $this->getAccountId(); $member = new Member(); $member->avatar = empty($params['avatar']) ? '' : $params['avatar']; $member->location = empty($params['location']) ? null : $params['location']; $member->tags = empty($params['tags']) ? [] : $params['tags']; $member->properties = empty($params['properties']) ? [] : $params['properties']; $member->accountId = $accountId; $this->_validateProperty($member); $defaultCard = MemberShipCard::getDefault($accountId); $member->cardId = $defaultCard->_id; $member->cardNumber = Member::generateCardNumber(); $member->origin = Member::PORTAL; if ($member->save()) { Member::webhookEvent($member); MemberLogs::record($member->_id, $accountId, MemberLogs::OPERATION_VIEWED); if (!defined('KLP') || !KLP) { Yii::$app->qrcode->create(Yii::$app->request->hostInfo, Qrcode::TYPE_MEMBER, $member->_id, $accountId); } $this->attachBehavior('MemberBehavior', new MemberBehavior()); $this->updateItemByScoreRule($member); return $member; } else { throw new ServerErrorHttpException('Fail to create member'); } }