public static function preProcessCnyWinnerData($condition)
 {
     // TODO refine smsContent
     $smsTemplate = BulkSmsUtil::CNY_WINNERS_SMS_TEMPLATE;
     $winners = LuckyDrawWinner::find()->where($condition)->all();
     $rows = array();
     foreach ($winners as $winner) {
         $smsContent = str_replace("%username%", $winner->name, $smsTemplate);
         $smsContent = str_replace("%awardName%", $winner->awardName, $smsContent);
         $member = Member::getByMobile($winner->mobile, $condition['accountId']);
         if ($member != null) {
             $city = null;
             $site = null;
             foreach ($member->properties as $property) {
                 if ($property['name'] == '縣市') {
                     $city = $property['value'];
                 }
                 if ($property['name'] == '地址') {
                     $site = $property['value'];
                 }
             }
             $row = ['mobile' => " " . $winner->mobile, 'name' => $winner->name, 'city' => $city, 'site' => $site, 'awardName' => $winner->awardName, 'scoreAdded' => $winner->winInfo['scoreAdded'], 'createdAt' => MongodbUtil::MongoDate2String($winner->createdAt, 'Y-m-d H:i', null), 'remark' => $winner->winInfo['boughtAllProducts'] ? '已包含全部3支品項' : '', 'smsContent' => $smsContent];
             $rows[] = $row;
             unset($row, $smsContent, $member, $city, $site);
         }
     }
     return $rows;
 }
 /**
  * @args {"description": "Delay: Stats of StatsMemberGrowthMonthly every day"}
  * @author Rex Chen
  */
 public function perform()
 {
     $args = $this->args;
     $date = empty($args['date']) ? '' : $args['date'];
     $datetime = TimeUtil::getDatetime($date);
     $dateStr = date('Y-m', $datetime);
     $startTime = new \MongoDate(strtotime($dateStr . '-01'));
     $endTime = new \MongoDate(strtotime($dateStr . '-01 +1 month'));
     $accounts = Account::findAll(['enabledMods' => 'member']);
     foreach ($accounts as $account) {
         $accountId = $account->_id;
         $totalMember = Member::countByAccount($accountId, null, $endTime);
         $totalActive = MemberLogs::getTotalActiveByAccount($accountId, $startTime, $endTime);
         $totalNew = Member::countByAccount($accountId, $startTime, $endTime);
         $statsGrowth = ModelStatsMemberGrowthMonthly::getByMonthAndAccount($accountId, $dateStr);
         if (empty($statsGrowth)) {
             $statsGrowth = new ModelStatsMemberGrowthMonthly();
             $statsGrowth->accountId = $accountId;
             $statsGrowth->month = $dateStr;
         }
         $statsGrowth->totalNew = $totalNew;
         $statsGrowth->totalActive = $totalActive;
         $statsGrowth->totalInactive = $totalMember - $totalActive;
         try {
             $statsGrowth->save();
         } catch (Exception $e) {
             ResqueUtil::log(['Update StatsMemberGrowthMonthly error' => $e->getMessage(), 'StatsMemberGrowthMonthly' => $statsGrowth]);
             continue;
         }
     }
     return true;
 }
 /**
  *  Check expired membership card.
  */
 public function actionCheckCardExpiredTime()
 {
     $accounts = Account::find()->where(['isDeleted' => Account::NOT_DELETED])->all();
     if (!empty($accounts)) {
         $nowTimestamp = strtotime(date('Y-m-d')) * 1000;
         $oneDayTimestamp = 24 * 60 * 60 * 1000;
         foreach ($accounts as $account) {
             $accountId = $account->_id;
             for ($day = 0; $day <= 7; $day++) {
                 $startDayTimestamp = $nowTimestamp + $oneDayTimestamp * ($day - 1);
                 $endDayTimestamp = $nowTimestamp + $oneDayTimestamp * $day;
                 if ($day === 0) {
                     $startDayTimestamp = 0;
                 }
                 $expiredCount = Member::find()->where(['accountId' => $accountId, 'cardExpiredAt' => ['$lte' => $endDayTimestamp, '$gt' => $startDayTimestamp], 'isDeleted' => Member::NOT_DELETED])->count();
                 if ($expiredCount > 0) {
                     if ($day === 0) {
                         $content = "有 {$expiredCount} 个会员的会员卡已过期, <a href='/member/member?cardState=3'>(点击查看)</a>";
                     } else {
                         if ($day === 1) {
                             $content = "有 {$expiredCount} 个会员的会员卡即将于1天内过期, <a href='/member/member?cardState=1'>(点击查看)</a>";
                         } else {
                             $date = date("Y-m-d", $startDayTimestamp / 1000);
                             $content = "有 {$expiredCount} 个会员的会员卡即将于 {$date} 过期, <a href='/member/member?cardState=2'>(点击查看)</a>";
                         }
                     }
                     $this->_recordMessage($accountId, $content);
                 }
             }
         }
     }
 }
 /**
  * @args {"description": "Delay: Stats of StatsMemberDaily", "runNextJob": true}
  * @author Rex Chen
  */
 public function perform()
 {
     $args = $this->args;
     $date = empty($args['date']) ? '' : $args['date'];
     $datetime = TimeUtil::getDatetime($date);
     $dateStr = date('Y-m-d', $datetime);
     if (!empty(WECONNECT_DOMAIN)) {
         $channelNameMap = $this->_getChannelNameMap();
     }
     $start = new \MongoDate($datetime);
     $end = new \MongoDate(strtotime('+1 day', $datetime));
     $memberStats = Member::getNewMemberStats($start, $end);
     $rowStats = [];
     foreach ($memberStats as $stats) {
         $accountId = $stats['_id']['accountId'];
         $origin = $stats['_id']['origin'];
         $socialAccountId = $stats['_id']['socialAccountId'];
         $originName = empty($channelNameMap[$socialAccountId]) ? '' : $channelNameMap[$socialAccountId];
         $total = $stats['total'];
         $statsMember = ModelStatsMemberDaily::getByDateAndOriginInfo($dateStr, $origin, $originName, $accountId);
         if (!empty($statsMember)) {
             $statsMember->total = $total;
             try {
                 $statsMember->save(true, ['total']);
             } catch (Exception $e) {
                 ResqueUtil::log(['Update StatsMemberDaily error' => $e->getMessage(), 'StatsMemberDaily' => $statsMember]);
                 continue;
             }
         } else {
             $rowStats[] = ['date' => $dateStr, 'origin' => $origin, 'originName' => $originName, 'total' => $total, 'accountId' => $accountId];
         }
     }
     ModelStatsMemberDaily::batchInsert($rowStats);
     return true;
 }
 public function actionValidateNumber()
 {
     $mobile = Yii::$app->request->post("mobile");
     $accountId = $this->getAccountId();
     $result = Member::getByMobile($mobile, null);
     return $result;
 }
 public function actionIndex()
 {
     $perPage = $this->getQuery('per-page', 20);
     $page = $this->getQuery('page', 1);
     $accountId = $this->getAccountId();
     $account = Account::findByPk($accountId);
     $channels = Channel::getEnableChannelIds($accountId);
     $tags = empty($account->tags) ? [] : $account->tags;
     $tags = ArrayHelper::getColumn($tags, 'name', false);
     $totalCount = count($tags);
     rsort($tags);
     $tags = array_slice($tags, ($page - 1) * $perPage, $perPage);
     if (empty($tags)) {
         return ['items' => [], '_meta' => ['totalCount' => 0, 'pageCount' => 0, 'currentPage' => $page, 'perPage' => $perPage]];
     }
     if (!defined('KLP') || !KLP) {
         if (!empty($channels)) {
             $followerTags = Yii::$app->weConnect->getTagStats($channels, $tags);
         }
     }
     $memberTags = Member::getTagStats($accountId, $tags, $channels);
     $memberTagMap = ArrayHelper::map($memberTags, '_id', 'count');
     $items = [];
     foreach ($tags as $tag) {
         $items[] = ['name' => $tag, 'memberCount' => empty($memberTagMap[$tag]) ? 0 : $memberTagMap[$tag], 'followerCount' => empty($followerTags[$tag]) ? 0 : $followerTags[$tag]];
     }
     $meta = ['totalCount' => $totalCount, 'pageCount' => ceil($totalCount / $perPage), 'currentPage' => $page, 'perPage' => $perPage];
     return ['items' => $items, '_meta' => $meta];
 }
 public function actionIndex($accountId)
 {
     if (empty($accountId)) {
         echo 'accountId is invaild' . PHP_EOL;
         exit;
     }
     $where['accountId'] = new \MongoId($accountId);
     // delete member info
     Member::getCollection()->remove($where);
     //delete MemberLogs
     MemberLogs::getCollection()->remove($where);
     //delete scoreHistory
     ScoreHistory::getCollection()->remove($where);
     //delete CampaignLog
     CampaignLog::getCollection()->remove($where);
     //delete GoodsExchangeLog
     GoodsExchangeLog::getCollection()->remove($where);
     //delete MemberStatistics
     MemberStatistics::getCollection()->remove($where);
     //delete ReMemberCampaign
     ReMemberCampaign::getCollection()->remove($where);
     //delete StatsCampaignProductCodeQuarterly
     StatsCampaignProductCodeQuarterly::getCollection()->remove($where);
     //delete StatsMemberCampaignLogDaily
     StatsMemberCampaignLogDaily::getCollection()->remove($where);
     //delete StatsMemberDaily
     StatsMemberDaily::getCollection()->remove($where);
     //delete StatsMemberGrowthMonthly
     StatsMemberGrowthMonthly::getCollection()->remove($where);
     //delete StatsMemberGrowthQuarterly
     StatsMemberGrowthQuarterly::getCollection()->remove($where);
     //delete StatsMemberMonthly
     StatsMemberMonthly::getCollection()->remove($where);
     //delete StatsMemberPropAvgTradeQuarterly
     StatsMemberPropAvgTradeQuarterly::getCollection()->remove($where);
     //delete StatsMemberPropMonthly
     StatsMemberPropMonthly::getCollection()->remove($where);
     //delete StatsMemberPropQuaterly
     StatsMemberPropQuaterly::getCollection()->remove($where);
     //delete StatsMemberPropTradeCodeAvgQuarterly
     StatsMemberPropTradeCodeAvgQuarterly::getCollection()->remove($where);
     //delete StatsMemberPropTradeCodeQuarterly
     StatsMemberPropTradeCodeQuarterly::getCollection()->remove($where);
     //delete StatsMemberPropTradeQuarterly
     StatsMemberPropTradeQuarterly::getCollection()->remove($where);
     //delete PromotionCodeAnalysis
     PromotionCodeAnalysis::getCollection()->remove($where);
     //delete order
     Order::getCollection()->remove($where);
     //delete stats member order
     StatsMemberOrder::getCollection()->remove($where);
     //delete stats order
     StatsOrder::getCollection()->remove($where);
     //delete MembershipDiscount
     MembershipDiscount::getCollection()->remove($where);
     //delete couponLog
     CouponLog::getCollection()->remove($where);
     echo 'delete data successful.' . PHP_EOL;
 }
 public function deleteTag($accountId, $name)
 {
     Account::updateAll(['$pull' => ['tags' => ['name' => $name]]], ['_id' => $accountId]);
     Member::updateAll(['$pull' => ['tags' => $name]], ['accountId' => $accountId, 'tags' => $name]);
     Campaign::updateAll(['$pull' => ['tags' => $name]], ['accountId' => $accountId, 'tags' => $name]);
     $data = ['type' => 'tag_deleted', 'account_id' => $accountId, 'name' => $name];
     $this->notifyModules($data);
 }
 /**
  * receive copon through oauth recall this api
  */
 public function actionReceivedCoupon()
 {
     $params = $this->getQuery();
     $defaultId = -1;
     $message = '';
     if (empty($params['couponId']) || empty($params['memberId']) || empty($params['channelId'])) {
         LogUtil::error(['message' => 'missing params when receive coupon', 'params' => $params], 'product');
         exit;
     }
     $number = !empty($params['number']) && intval($params['number']) > 1 ? intval($params['number']) : 1;
     $couponId = new MongoId($params['couponId']);
     $coupon = Coupon::findByPk($couponId);
     if (empty($coupon)) {
         LogUtil::error(['message' => 'invalid couponIdi when receive coupon', 'params' => $params], 'product');
         exit;
     }
     $memberId = new MongoId($params['memberId']);
     $member = Member::findByPk($memberId);
     if (empty($member)) {
         LogUtil::error(['message' => 'invalid memberId when receive coupon', 'params' => $params], 'product');
         exit;
     }
     $args = ['mainDomain' => Yii::$app->request->hostInfo . '/mobile/product/coupon', 'couponId' => $params['couponId'], 'id' => $defaultId, 'memberId' => $params['memberId'], 'result' => 'fail', 'channelId' => $params['channelId']];
     //check the total
     if ($coupon->total < $number) {
         $message = Yii::t('product', 'coupon_no_exists');
         return $this->_redirectCouponDetail($message, $args, $params);
     }
     //check limit
     $couponNumber = CouponLog::count(['couponId' => $couponId, 'member.id' => $memberId]);
     if ($couponNumber >= $coupon->limit) {
         $message = Yii::t('product', 'coupon_is_received');
         return $this->_redirectCouponDetail($message, $args, $params);
     }
     //check the time
     $current = new MongoDate(strtotime(date('Y-m-d')));
     if ($coupon->time['type'] == Coupon::COUPON_RELATIVE_TIME && $coupon->time['endTime'] < $current) {
         $message = Yii::t('product', 'coupon_expired');
         return $this->_redirectCouponDetail($message, $args, $params);
     }
     //receive coupon
     $where = ['total' => ['$gte' => $number], '_id' => $couponId];
     $number -= 2 * $number;
     if (Coupon::updateAll(['$inc' => ['total' => $number]], $where)) {
         $membershipDiscount = MembershipDiscount::transformMembershipDiscount($coupon, $member);
         if (false === $membershipDiscount->save()) {
             //to avoid the error show to user
             LogUtil::error(['message' => 'Failed to save couponLog error:' . $membershipDiscount->getErrors()], 'product');
             $message = Yii::t('common', 'save_fail');
             return $this->_redirectCouponDetail($message, $args, $params);
         }
         $args['id'] = isset($membershipDiscount->_id) ? $membershipDiscount->_id : $defaultId;
         $args['result'] = 'success';
     } else {
         $message = '优惠券库存不足!';
     }
     return $this->_redirectCouponDetail($message, $args, $params);
 }
 /**
  * @param $member, object
  * @param $rule, string, score rule name
  */
 public function updateItemByScoreRule($member)
 {
     //birthday score
     Member::birthdayScore($member);
     //perfect info score
     $ruleNames = [ScoreRule::NAME_PERFECT_INFO, ScoreRule::NAME_FIRST_CARD];
     foreach ($ruleNames as $ruleName) {
         Member::rewardByScoreRule($ruleName, $member->_id, $member->accountId);
     }
 }
 /**
  * The default implementation returns the names of the columns whose values have been populated into MemberShipCard.
  */
 public function fields()
 {
     return array_merge(parent::fields(), ['name', 'poster', 'fontColor', 'privilege', 'condition', 'usageGuide', 'isEnabled', 'isDefault', 'isAutoUpgrade', 'scoreResetDate', 'provideCount' => function () {
         return Member::count(['cardId' => $this->_id]);
     }, 'createdAt' => function () {
         return MongodbUtil::MongoDate2String($this->createdAt, 'Y-m-d H:i:s');
     }, 'updatedAt' => function () {
         return MongodbUtil::MongoDate2String($this->updatedAt, 'Y-m-d H:i:s');
     }]);
 }
 public function actionAddress($id)
 {
     $member = Member::findByPk(new \MongoId($id));
     if (empty($member)) {
         throw new InvalidParameterException(Yii::t('member', 'no_member_find'));
     }
     $goodsExchangeLog = GoodsExchangeLog::getLastExpressByMember($member->_id);
     $address = empty($goodsExchangeLog->address) ? '' : $goodsExchangeLog->address;
     $postcode = empty($goodsExchangeLog->postcode) ? '' : $goodsExchangeLog->postcode;
     return ['address' => $address, 'postcode' => $postcode];
 }
 public static function getMemberInfo($condition)
 {
     $memberIds = CampaignLog::distinct('member.id', $condition);
     $members = Member::findAll(['_id' => ['$in' => $memberIds]]);
     $data = [];
     if (!empty($members)) {
         foreach ($members as $member) {
             $data[(string) $member->_id] = $member;
         }
     }
     return $data;
 }
 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;
     }
 }
 private function preProcessDrawMembers($condition, $accountId)
 {
     $rows = array();
     $scores = EarlybirdSmsUtil::getExchangeGoodsScore($condition['startDate'], $condition['endDate'], $accountId);
     asort($scores);
     foreach ($scores as $key => $value) {
         $row = array();
         if (abs($value) >= $condition['pointsThree']) {
             $member = Member::findByPk(new \MongoId($key));
             if (!$member->isDeleted) {
                 $row['id'] = $key;
                 $row['exchangeGoodsScore'] = abs($value);
                 $row['cardNumber'] = $member->cardNumber;
                 //拿到符合一等奖条件的人
                 if (abs($value) >= $condition['pointsOne']) {
                     //eg: points>=2000
                     $row['prizeName'] = $condition['prizeNameOne'];
                     $row['prizeLevel'] = '一等獎資格';
                 }
                 //拿到符合二等奖条件的人
                 if (abs($value) < $condition['pointsOne'] && abs($value) >= $condition['pointsTwo']) {
                     //eg: 1000<=points<2000
                     $row['prizeName'] = $condition['prizeNameTwo'];
                     $row['prizeLevel'] = '二等獎資格';
                 }
                 //拿到符合三等奖条件的人
                 if (abs($value) < $condition['pointsTwo'] && abs($value) >= $condition['pointsThree']) {
                     //eg: 200<=points<1000
                     $row['prizeName'] = $condition['prizeNameThree'];
                     $row['prizeLevel'] = '三等獎資格';
                 }
                 if (!empty($member->properties)) {
                     foreach ($member->properties as $property) {
                         if ($property['name'] == 'tel') {
                             $row['mobile'] = "'" . $property['value'];
                         }
                         if ($property['name'] == 'name') {
                             $row['name'] = $property['value'];
                         }
                     }
                 }
             }
         }
         $rows[] = $row;
         unset($row, $member);
     }
     return $rows;
 }
 public function actionSendRedemptionMessage()
 {
     $params = $this->getParams();
     $name = MessageTemplate::getTemplateName($params['type']);
     $mobileParams = MessageTemplate::getMobileVar($params);
     $accountId = $this->getAccountId();
     $specialParams = MessageTemplate::getProductList($params);
     $template = MessageTemplate::getMobileTemplate($name, $accountId, $mobileParams, $specialParams);
     $params['memberId'] = new \MongoId($params['memberId']);
     $member = Member::getMemberInfo($params['memberId'], 'tel');
     if (!empty($member['tel']) && !empty($template)) {
         return MessageUtil::sendMobileMessage($member['tel'], $template);
     } else {
         return false;
     }
 }
Exemple #17
0
 /**
  * @args {"description": "Delay: Automatic clear member score. every day"}
  */
 public function perform()
 {
     $month = intval(date('m'));
     $day = intval(date('d'));
     $memberShipCards = MemberShipCard::find()->where(['isDeleted' => MemberShipCard::NOT_DELETED, 'scoreResetDate.month' => $month, 'scoreResetDate.day' => $day])->all();
     if (!empty($memberShipCards)) {
         foreach ($memberShipCards as $memberShipCard) {
             $members = Member::find()->where(['isDeleted' => MemberShipCard::NOT_DELETED, 'cardId' => $memberShipCard->_id, 'score' => ['$ne' => 0]])->all();
             if (!empty($members)) {
                 foreach ($members as $member) {
                     Member::resetScore($member->_id, $member->accountId);
                 }
             }
         }
     }
 }
 public function actionFixData($startData, $endData)
 {
     $accounts = Account::findAll(['enabledMods' => 'product']);
     foreach ($accounts as $account) {
         $accountId = $account->_id;
         $condition = ['accountId' => $accountId, 'createdAt' => ['$gte' => new MongoDate(strtotime($startData)), '$lt' => new Mongodate(strtotime($endData))]];
         $pipeline = [['$match' => $condition], ['$group' => ['_id' => ['campaignId' => '$campaignId', 'code' => '$code'], 'count' => ['$sum' => 1]]], ['$match' => ['count' => ['$gt' => 1]]]];
         $stats = CampaignLog::getCollection()->aggregate($pipeline);
         if (!empty($stats)) {
             foreach ($stats as $stat) {
                 $code = $stat['_id']['code'];
                 $logCondition = array_merge($condition, $stat['_id']);
                 $logs = CampaignLog::find()->where($logCondition)->orderBy(['createdAt' => 1])->all();
                 $memberId = $logs[0]['member']['id'];
                 $productName = $logs[0]['productName'];
                 $description = $productName . ' ' . $code;
                 $scoreHistoryCondition = ['memberId' => $memberId, 'brief' => ScoreHistory::ASSIGNER_EXCHANGE_PROMOTION_CODE, 'description' => $description];
                 $scoreHistorys = ScoreHistory::find()->where($scoreHistoryCondition)->orderBy(['createdAt' => 1])->all();
                 $keepScoreHistory = $scoreHistorys[0];
                 unset($scoreHistorys[0]);
                 $removeScoreHistoryIds = [];
                 $deduct = 0;
                 foreach ($scoreHistorys as $scoreHistory) {
                     $removeScoreHistoryIds[] = $scoreHistory->_id;
                     $deduct += $scoreHistory->increment;
                 }
                 $member = Member::findByPk($memberId);
                 if ($member->score <= $deduct || $member->totalScore <= $deduct || $member->totalScoreAfterZeroed <= $deduct) {
                     echo 'Failed : Member' . $memberId . ' score not enough ' . 'score: ' . $member->score;
                     echo ' totalScore: ' . $member->totalScore;
                     echo ' totalScoreAfterZeroed: ' . $member->totalScoreAfterZeroed . PHP_EOL;
                     continue;
                 }
                 $deductScore = 0 - $deduct;
                 Member::updateAll(['$inc' => ['score' => $deductScore, 'totalScore' => $deductScore, 'totalScoreAfterZeroed' => $deductScore]], ['_id' => $memberId]);
                 ScoreHistory::deleteAll(['_id' => ['$in' => $removeScoreHistoryIds]]);
                 $logIds = ArrayHelper::getColumn($logs, '_id');
                 $keepLogId = $logIds[0];
                 unset($logIds[0]);
                 CampaignLog::deleteAll(['_id' => ['$in' => array_values($logIds)]]);
                 echo 'Success: ' . $productName . ' ' . $code . ' ' . $stat['count'];
                 echo ' Deduct member ' . $memberId . ' score ' . $deduct . PHP_EOL;
             }
         }
     }
     echo 'Success' . PHP_EOL;
 }
 /**
  * Get accountId and company when bind
  * @param array $params
  * @throws BadRequestHttpException
  * @throws InvalidParameterException
  * @return array
  */
 public function bind($params)
 {
     \Yii::$app->language = LanguageUtil::LANGUAGE_ZH;
     $this->checkCode($params);
     $mobile = $params['mobile'];
     if (empty($params['channelId']) || empty($params['openId'])) {
         throw new BadRequestHttpException('Missing params');
     }
     $channelId = $params['channelId'];
     $channel = Channel::getEnableByChannelId($channelId);
     $member = Member::getByMobile($mobile, $channel->accountId);
     if (!empty($member)) {
         throw new InvalidParameterException(['phone' => \Yii::t('common', 'phone_has_been_bound')]);
     }
     $account = Account::findByPk($channel->accountId);
     return ['accountId' => $channel->accountId, 'company' => empty($account->company) ? null : $account->company];
 }
 /**
  * @args {"description": "Delay: Send member expired message every day"}
  */
 public function perform()
 {
     $accounts = Account::find()->where(['isDeleted' => Account::NOT_DELETED])->all();
     if (!empty($accounts)) {
         $nowTimestamp = strtotime(date('Y-m-d')) * 1000;
         $oneDayTimestamp = 24 * 60 * 60 * 1000;
         foreach ($accounts as $account) {
             $accountId = $account->_id;
             for ($day = 0; $day <= 7; $day++) {
                 $startDayTimestamp = $nowTimestamp + $oneDayTimestamp * ($day - 1);
                 $endDayTimestamp = $nowTimestamp + $oneDayTimestamp * $day;
                 if ($day === 0) {
                     $startDayTimestamp = 0;
                 }
                 $expiredCount = Member::find()->where(['accountId' => $accountId, 'cardExpiredAt' => ['$lte' => $endDayTimestamp, '$gt' => $startDayTimestamp], 'isDeleted' => Member::NOT_DELETED])->count();
                 if ($expiredCount > 0) {
                     if ($day === 0) {
                         if ($expiredCount == 1) {
                             $content = "msg_have {$expiredCount} msg_had_expired <a href='/member/member?cardState=3'> msg_click_read </a>";
                         } else {
                             $content = "msg_have {$expiredCount} msg_had_expireds <a href='/member/member?cardState=3'> msg_click_read </a>";
                         }
                     } else {
                         if ($day === 1) {
                             if ($expiredCount == 1) {
                                 $content = "msg_have {$expiredCount} msg_having_expired <a href='/member/member?cardState=1'> msg_click_read </a>";
                             } else {
                                 $content = "msg_have {$expiredCount} msg_had_expireds <a href='/member/member?cardState=1'> msg_click_read </a>";
                             }
                         } else {
                             $date = date("Y-m-d", $startDayTimestamp / 1000);
                             if ($expiredCount == 1) {
                                 $content = "msg_have {$expiredCount} msg_having {$date} msg_expired <a href='/member/member?cardState=2'> msg_click_read </a>";
                             } else {
                                 $content = "msg_have {$expiredCount} msg_havings {$date} msg_expired <a href='/member/member?cardState=2'> msg_click_read </a>";
                             }
                         }
                     }
                     $this->recordMessage($accountId, $content);
                 }
             }
         }
     }
 }
 public function operationCoupon($membershipDiscount)
 {
     //record log when get coupon
     $memberItem = Member::getMemberInfo($membershipDiscount->member['id'], ['tel']);
     $memberInfo = ['id' => $membershipDiscount->member['id'], 'name' => $membershipDiscount->member['name'], 'phone' => empty($memberItem['tel']) ? '' : $memberItem['tel'], 'receiveType' => $membershipDiscount->coupon['receiveType']];
     $couponLog = new CouponLog();
     $couponLog->couponId = $membershipDiscount->coupon['id'];
     $couponLog->membershipDiscountId = $membershipDiscount->_id;
     $couponLog->type = $membershipDiscount->coupon['type'];
     $couponLog->title = $membershipDiscount->coupon['title'];
     $couponLog->status = CouponLog::RECIEVED;
     $couponLog->member = $memberInfo;
     $couponLog->total = 1;
     $couponLog->operationTime = $couponLog->createdAt = new MongoDate();
     $couponLog->accountId = $membershipDiscount->accountId;
     if (false === $couponLog->save()) {
         //to avoid the error show to user
         LogUtil::error(['message' => 'Failed to save couponLog error:' . $couponLog->getErrors()], 'product');
     }
 }
 public function actionIndex()
 {
     $params = $this->getQuery();
     if (empty($params['memberId'])) {
         throw new BadRequestHttpException(Yii::t('common', 'parameters_missing'));
     }
     //get members openIds
     $member = Member::findByPk(new MongoId($params['memberId']));
     $openIds = empty($member->socials) ? [] : ArrayHelper::getColumn($member->socials, 'openId');
     $openIds[] = $member->openId;
     //get lastChatDate
     $lastConversation = ChatConversation::getLastByOpenIds($openIds);
     $lastChatDate = empty($lastConversation) ? '' : $lastConversation->date;
     //get conversations
     $params['openIds'] = $openIds;
     $accountId = $this->getAccountId();
     $conversations = ChatConversation::search($params, $accountId);
     $result = $this->serializeData($conversations);
     $result['lastChatDate'] = $lastChatDate;
     return $result;
 }
 public function perform()
 {
     $args = $this->args;
     if (empty($args['accountId']) || empty($args['properties'][0])) {
         ResqueUtil::log('Missing required arguments accountId or properties!');
         return false;
     }
     $accountId = new \MongoId($args['accountId']);
     $property = $args['properties'][0];
     $memberProperty = MemberProperty::findOne(['propertyId' => $property, 'accountId' => $accountId]);
     if (empty($memberProperty)) {
         ResqueUtil::log('Can not find member property with propertyId:' . $property);
         return false;
     }
     $date = empty($args['date']) ? '' : $args['date'];
     $date = TimeUtil::getDatetime($date);
     $month = date('Y-m', $date);
     $startDate = strtotime($month);
     $endDate = strtotime(date('Y-m', strtotime('+1 month', $date)));
     $raw = Member::getCollection()->aggregate([['$unwind' => '$properties'], ['$match' => ['createdAt' => ['$gte' => new \MongoDate($startDate), '$lt' => new \MongoDate($endDate)], 'properties.id' => $memberProperty->_id, 'accountId' => $accountId]], ['$group' => ['_id' => '$properties.value', 'total' => ['$sum' => 1]]]]);
     foreach ($raw as $item) {
         $total = $item['total'];
         $propValue = $item['_id'];
         // save the stats member property monthly
         $statsMemberPropMonthly = ModelStatsMemberPropMonthly::findOne(['propId' => $property, 'propValue' => $propValue, 'month' => $month, 'accountId' => $accountId]);
         if (empty($statsMemberPropMonthly)) {
             $statsMemberPropMonthly = new ModelStatsMemberPropMonthly();
             $statsMemberPropMonthly->propId = $property;
             $statsMemberPropMonthly->propValue = $propValue;
             $statsMemberPropMonthly->month = $month;
             $statsMemberPropMonthly->accountId = $accountId;
         }
         $statsMemberPropMonthly->total = $total;
         ResqueUtil::log($statsMemberPropMonthly->attributes);
         $statsMemberPropMonthly->save();
     }
     return true;
 }
 public function actionListByTag()
 {
     $tagName = $this->getQuery('tagName');
     $orderBy = $this->getQuery('orderBy', 'createdAt');
     $accountId = $this->getAccountId();
     $result = ['items' => [], 'memberCount' => 0];
     $result['items'] = HelpDesk::getByAccountAndTags($tagName, $accountId, $orderBy);
     $result['memberCount'] = Member::getMemberCountByTags($tagName, $accountId);
     return $result;
 }
 /**
  * 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");
     }
 }
 private function _repairData()
 {
     $fileName = 'deleted-' . time();
     $result = $this->_getRepairData();
     foreach ($result as $item) {
         $condition = ['properties' => ['$elemMatch' => ['name' => Member::DEFAULT_PROPERTIES_MOBILE, 'value' => $item['_id']['tel']]], 'accountId' => $item['_id']['accountId']];
         $members = Member::findAll($condition);
         $score = [];
         $keepMember = [];
         $deleteMember = [];
         foreach ($members as $member) {
             if (!in_array($member->score, $score)) {
                 $score[] = $member->score;
                 $keepMember[] = $member->_id;
             } else {
                 $msg = 'deleted member ' . $member->_id . PHP_EOL;
                 $deleteMember[] = $member->_id;
                 echo $msg;
                 $this->_saveFile($msg, $fileName);
             }
         }
         $deleteCondition = ['_id' => ['$in' => $deleteMember]];
         Member::deleteAll($deleteCondition);
     }
 }
Exemple #27
0
 /**
  * get member info even if the member is deleted
  * @param $condition, array
  */
 public static function getAllMember($condition)
 {
     $members = Member::find()->where($condition)->all();
     return $members;
 }
Exemple #28
0
 /**
  * Conversion format for couponLog.
  * @param $coupon Object
  * @param $member Object
  * @param $tokenInfo Object
  */
 public static function transformCouponLog($coupon, $member, $membershipDiscountId)
 {
     $memberItem = Member::getMemberInfo($member->_id, ['name', 'tel']);
     $memberInfo = ['id' => $member->_id, 'name' => empty($memberItem['name']) ? '' : $memberItem['name'], 'phone' => empty($memberItem['tel']) ? '' : $memberItem['tel']];
     $couponLog = new CouponLog();
     $couponLog->couponId = $coupon->_id;
     $couponLog->membershipDiscountId = $membershipDiscountId;
     $couponLog->type = $coupon->type;
     $couponLog->title = $coupon->title;
     $couponLog->status = self::RECIEVED;
     $couponLog->member = $memberInfo;
     $couponLog->total = 1;
     $couponLog->operationTime = new \MongoDate();
     $couponLog->createdAt = new \MongoDate();
     $couponLog->accountId = $coupon->accountId;
     return $couponLog;
 }
 /**
  * This function is just for fix error promotionCode redeem data
  * @param MongoId $accountId
  * @param MongoId $memberId
  * @param Array $codes
  * @return boolean, true, if there is no error data
  */
 private function fixData($accountId, $memberId, $codes)
 {
     $condition = ['accountId' => $accountId, 'member.id' => $memberId, 'code' => ['$in' => $codes]];
     $pipeline = [['$match' => $condition], ['$group' => ['_id' => ['campaignId' => '$campaignId', 'code' => '$code'], 'count' => ['$sum' => 1]]], ['$match' => ['count' => ['$gt' => 1]]]];
     $stats = CampaignLog::getCollection()->aggregate($pipeline);
     if (empty($stats)) {
         return true;
     }
     $logCondition = ['accountId' => $accountId, 'member.id' => $memberId];
     $failedMessages = [];
     $successMessages = [];
     foreach ($stats as $stat) {
         $code = $stat['_id']['code'];
         //get campaign log
         $logCondition = array_merge($logCondition, $stat['_id']);
         $logs = CampaignLog::find()->where($logCondition)->orderBy(['createdAt' => SORT_ASC])->all();
         $memberId = $logs[0]['member']['id'];
         $productName = $logs[0]['productName'];
         //get score history
         $description = $productName . ' ' . $code;
         $scoreHistoryCondition = ['memberId' => $memberId, 'brief' => ScoreHistory::ASSIGNER_EXCHANGE_PROMOTION_CODE, 'description' => $description];
         $scoreHistorys = ScoreHistory::find()->where($scoreHistoryCondition)->orderBy(['createdAt' => SORT_ASC])->all();
         $keepScoreHistory = $scoreHistorys[0];
         unset($scoreHistorys[0]);
         $removeScoreHistoryIds = [];
         $deduct = 0;
         foreach ($scoreHistorys as $scoreHistory) {
             $removeScoreHistoryIds[] = $scoreHistory->_id;
             $deduct += $scoreHistory->increment;
         }
         $member = Member::findByPk($memberId);
         //if member score not enough, log continue
         if ($member->score <= $deduct || $member->totalScore <= $deduct || $member->totalScoreAfterZeroed <= $deduct) {
             $failedMessages[] = ['Failed' => 'Member score not enough', 'member' => $member->toArray(), 'deduct' => $deduct];
             continue;
         }
         //fix member score
         $deductScore = 0 - $deduct;
         Member::updateAll(['$inc' => ['score' => $deductScore, 'totalScore' => $deductScore, 'totalScoreAfterZeroed' => $deductScore]], ['_id' => $memberId]);
         //remove scorehistory
         ScoreHistory::deleteAll(['_id' => ['$in' => $removeScoreHistoryIds]]);
         //remove campaignlog
         $logIds = ArrayHelper::getColumn($logs, '_id');
         $keepLogId = $logIds[0];
         unset($logIds[0]);
         CampaignLog::deleteAll(['_id' => ['$in' => array_values($logIds)]]);
         $successMessages[] = ['Success' => $productName . ' ' . $code . ' ' . $stat['count'], 'memberId' => $memberId, 'deduct' => $deduct];
     }
     LogUtil::error(['Failed' => $failedMessages, 'Success' => $successMessages], 'fix-campaign-data');
 }
Exemple #30
0
 /**
  * Get member by birth according score rule trigger time
  * @param string $triggerTime
  * @return member list
  */
 private function getMembers($accountId, $triggerTime, $memberId = null)
 {
     $timeCondition = $this->getTimeCondition($triggerTime);
     $memberIds = [];
     if (!empty($timeCondition['timeFrom']) && !empty($timeCondition['timeTo'])) {
         if (empty($memberId)) {
             $members = Member::searchByBirth($timeCondition['timeFrom'], $timeCondition['timeTo'], $accountId);
             $memberIds = Member::getIdList($members);
         } else {
             $condition = ['birth' => ['$gte' => $timeCondition['timeFrom'], '$lte' => $timeCondition['timeTo']]];
             $member = Member::findByPk($memberId, $condition);
             if (!empty($member)) {
                 $memberIds = [$member->_id];
             }
         }
     }
     return $memberIds;
 }