/** * Изменение статуса кампании * * @param Campaign $campaign * * @Rest\Put("campaigns/{id}/status", requirements={"id"="\d+"}) * @ParamConverter("campaign", class="VifeedCampaignBundle:Campaign") * @ApiDoc( * section="Campaign API", * requirements={ * {"name"="id", "dataType"="integer", "requirement"="\d+", "description"="id кампании"} * }, * statusCodes={ * 200="Returned when successful", * 400="Returned when the something was wrong", * 403="Returned when the user is not authorized to use this method", * 404="Returned when campaign not found" * } * ) * * @return Response */ public function putCampaignStatusAction(Campaign $campaign) { if ($campaign->getUser() != $this->getUser()) { throw new AccessDeniedHttpException('Можно изменять только свои кампании'); } $oldStatus = $campaign->getStatus(); $form = $this->createForm(new CampaignStatusType(), $campaign); $form->submit($this->get('request'), false); if (!$form->isValid()) { return $this->handleView(new View($form, 400)); } $newStatus = $campaign->getStatus(); if ($newStatus == Campaign::STATUS_ON) { // включение try { $this->campaignManager->tryTurnStatusOn($campaign, $oldStatus); } catch (CampaignStatusException $e) { $form['status']->addError(new FormError($e->getMessage())); return $this->handleView(new View($form, 400)); } } else { // пауза или архив if ($oldStatus == Campaign::STATUS_ON) { $canTurnOffByTime = $this->campaignManager->canTurnOffByTime($campaign); if ($canTurnOffByTime !== true) { $msg = 'Невозможно остановить кампанию в течение двух часов после запуска. Вы сможете остановить кампанию через ' . $canTurnOffByTime . ' мин.'; $form['status']->addError(new FormError($msg)); return $this->handleView(new View($form, 400)); } } if ($newStatus == Campaign::STATUS_ARCHIVED) { $this->campaignManager->transferMoneyBackToUser($campaign); } } $this->campaignManager->save($campaign); $view = new View('', 200); return $this->handleView($view); }
/** * обработка показа * * @param VideoView $videoView * @param bool $skipStatusCheck * * @return boolean false, если транзакция не прошла, в остальных случаях true */ public function reckon(VideoView $videoView, $skipStatusCheck = false) { $videoViewRepo = $this->em->getRepository('VifeedVideoViewBundle:VideoView'); $userRepo = $this->em->getRepository('VifeedUserBundle:User'); $campaignRepo = $this->em->getRepository('VifeedCampaignBundle:Campaign'); $publisher = $videoView->getPlatform()->getUser(); $this->em->refresh($publisher); // обновляем энтити. Доктрина может брать его из кеша if (!$publisher->isEnabled()) { // паблишер забанен. Ничего не делаем return true; } // пользователь уже просматривал этот ролик $countViewsByViewerId = $videoViewRepo->countCampaignViewsByViewerId($videoView); if ($countViewsByViewerId['paid_views'] > 0) { return true; } $campaign = $videoView->getCampaign(); $this->em->refresh($campaign); // обновляем энтити. Доктрина может брать его из кеша // перед оплатой обновляем статус по балансу. Если пора выключать - выключаем $this->campaignManager->checkUpdateStatusOn($campaign); // если просмотр слишком короткий или кампания уже остановлена, инкрементим totalViews и выходим if (!$skipStatusCheck && !$this->checkReckonConditions($videoView)) { // засчитываем показ только если пользователь ещё не смотрел ролик if ($countViewsByViewerId['views'] == 0) { // показ участвует в статах $videoView->setIsInStats(true); $this->em->persist($videoView); $campaignRepo->incrementTotalViews($campaign); } $this->em->flush(); // на случай, если у кампании обновился статус return true; } $this->em->getConnection()->beginTransaction(); $this->em->lock($publisher, LockMode::PESSIMISTIC_WRITE); $price = $campaign->getBid(); $comissionValue = round($this->comission * $price, 2); $toPay = round($price - $comissionValue, 2); $payment = new VideoViewPayment(); $payment->setVideoView($videoView)->setCharged($price)->setComission($comissionValue)->setPaid($toPay); $userRepo->updateBalance($publisher, $toPay); $campaignRepo->addPaidView($campaign); $this->campaignManager->checkUpdateStatusOn($campaign); $videoView->setIsPaid(true)->setIsInStats(true); $this->em->persist($publisher); $this->em->persist($payment); $done = false; try { $this->em->flush(); $this->em->getConnection()->commit(); $this->em->refresh($campaign); $this->campaignManager->checkUpdateStatusOn($campaign); $this->em->flush(); // на случай, если у кампании обновился статус $done = true; } catch (\Exception $e) { $this->em->getConnection()->rollback(); // исключение не бросаем, просто откатываем транзакцию и ставим задачу снова в очередь } return $done; }