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; }
/** * 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'); }
/** * @param $fromDate string (eg:'2015-09-30 23:59:59') * @param $memberId MongoId * @param $accountId MongoId * @return int * * createdAt: a < createdAt <= b */ public static function getScoreOffset($fromDate, $memberId, $accountId) { $scoreOffset = 0; $time = strtotime($fromDate); $fromDate = new \MongoDate($time); $now = new \MongoDate(); $condition = ['accountId' => $accountId, 'memberId' => $memberId, 'createdAt' => ['$gt' => $fromDate, '$lte' => $now]]; $histories = ScoreHistory::find()->where($condition)->all(); if (!empty($histories) && count($histories) > 0) { foreach ($histories as $history) { $scoreOffset += $history->increment; } } unset($time, $fromDate, $now, $condition, $histories, $accountId); return $scoreOffset; }