/**
  * Регистрация кликов (одной пачкой)
  *
  * @param array $clicks
  */
 public function registerStat($data)
 {
     $this->obj->benchmark->mark('register_clicks_start');
     $stats = new Sppc_Stats();
     $stats->writeStatstoDb($data);
     $this->obj->benchmark->mark('register_clicks_end');
 }
 /**
  * Продление купленной программы
  *
  * @param integer $id_group_site_channel идентификатор группы
  * @param bool $check_complete делать ли проверку на конченность программы
  * @return int код ошибки
  */
 public function renew($id_group_site_channel, $check_complete = true, $new_ad_type = '', $new_id_program = 0, $make_unpaid = FALSE)
 {
     // Получаем айдишники программы, сайта, группы, компании, а также тип и код сайта/канала
     $id_program = 0;
     $ad_type = '';
     $this->db->select('g.id_group,g.id_campaign,sc.id_site,sc.id_channel,gsc.id_program,gsc.ad_type,gsc.id_site_channel')->from('group_site_channels gsc')->join('groups g', 'gsc.id_group=g.id_group')->join('site_channels sc', 'sc.id_site_channel=gsc.id_site_channel')->where('id_group_site_channel', $id_group_site_channel);
     if ($check_complete) {
         $this->db->where('status', 'completed');
     }
     $this->db->limit(1);
     $query = $this->db->get();
     if (0 < $query->num_rows()) {
         $row = $query->row();
         $id_program = $row->id_program;
         $ad_type = $row->ad_type;
         $id_site_channel = $row->id_site_channel;
         $id_group = $row->id_group;
         $id_campaign = $row->id_campaign;
         $id_site = $row->id_site;
         $id_channel = $row->id_channel;
     } else {
         // Неизвестная программа
         return self::UNKNOWN_PROGRAM;
     }
     if (empty($new_ad_type)) {
         $new_ad_type = $ad_type;
     }
     $old_program = $new_id_program == 0;
     if ($old_program) {
         $new_id_program = $id_program;
     }
     // Получаем стоимость программы для купленного пакета и тип
     $cost = 0;
     $program_type = '';
     $volume = 0;
     $cost_text = 0;
     $cost_image = 0;
     $avg_cost_text = 0;
     $avg_cost_image = 0;
     $this->db->select('program_type, cost_text, cost_image, volume, avg_cost_text, avg_cost_image')->from('channel_program_types')->where('id_program', $new_id_program)->limit(1);
     $adTypes = explode(',', $new_ad_type);
     $query = $this->db->get();
     if (0 < $query->num_rows()) {
         $row = $query->row();
         $program_type = $row->program_type;
         $volume = $row->volume;
         $cost_text = $row->cost_text;
         $cost_image = $row->cost_image;
         $avg_cost_text = $row->avg_cost_text;
         $avg_cost_image = $row->avg_cost_image;
         if (in_array('image', $adTypes)) {
             $cost = $row->cost_image;
         } else {
             $cost = $row->cost_text;
         }
     } else {
         // Неизвестная программа
         return self::UNKNOWN_PROGRAM;
     }
     if (in_array('image', $adTypes)) {
         $cost_field = 'cost_image';
     } else {
         if (in_array('text', $adTypes)) {
             $cost_field = 'cost_text';
         } else {
             return self::UNKNOWN_AD_TYPE;
         }
     }
     if ($old_program) {
         //Проверка совпадения цены и объема оплачиваемой программы с прайсом в канале
         $query = $this->db->select($cost_field . ' as cost, volume')->from('group_site_channels')->where('id_group_site_channel', $id_group_site_channel)->get();
         if (0 < $query->num_rows()) {
             $row = $query->row();
             if ($row->cost != $cost || $row->volume != $volume) {
                 //Установка статуса trouble
                 $this->db->where('id_group_site_channel', $id_group_site_channel)->update('group_site_channels', array('status' => 'trouble'));
                 return self::COST_DATA_MISMATCH;
             }
         } else {
             // Неизвестная программа
             return self::UNKNOWN_PROGRAM;
         }
     }
     //Для Flat Rate проверка доступности по количеству слотов
     if ('Flat_Rate' == $program_type) {
         $slots_info = $this->get_slot_info($id_site_channel);
         if (0 == $slots_info['free'] || $slots_info['free'] != $slots_info['max'] && in_array('image', $adTypes)) {
             //для картинок должны быть свободны все слоты
             //Установка статуса trouble
             $this->db->where('id_group_site_channel', $id_group_site_channel)->update('group_site_channels', array('status' => 'trouble'));
             return self::NO_SLOTS;
         }
     }
     // Получаем данные по рекламодателю
     $advertiser_info = $this->get_advertiser_info($id_group_site_channel);
     $id_advertiser = $advertiser_info['id_entity'];
     $balance = $advertiser_info['ballance'];
     $bonus = $advertiser_info['bonus'];
     // Проверяем баланс
     $make_payment = TRUE;
     if ($balance + $bonus < $cost) {
         // Денег на балансе не хватает для renew этой программы
         if (!$make_unpaid) {
             return self::TOO_LOW_BALANCE;
         } else {
             $make_payment = FALSE;
         }
     } elseif ($cost <= 0) {
         // Подозрительно низкая стоимость программы
         return self::TOO_LOW_PROGRAM_COST;
     }
     if ($make_payment) {
         $instance =& get_instance();
         $instance->load->model('entity', 'entity_obj');
         // Сначала снимаем
         $instance->entity_obj->subtract_money($id_advertiser, $cost);
         // Затем платим
         $instance->entity_obj->add_money(1, $cost);
         $instance->load->model('payment_gateways', 'pg_obj');
         $instance->pg_obj->money_flow($id_advertiser, 1, $cost, NULL, NULL, 'program', 0, true, '', NULL, NULL);
     }
     // для renew completed сохраняем историю
     if ($check_complete) {
         //clicks, current_impressions, volume, spent, start_date_time
         $info = $this->get_info($id_group_site_channel);
         $this->db->insert('renew_history', array('start_date_time' => type_to_str($info->start_date_time, 'databasedatetime'), 'id_group_site_channel' => $id_group_site_channel, 'impressions' => $info->current_impressions, 'clicks' => $info->clicks, 'days' => $info->days, 'spent' => $info->spent, 'used' => $info->used));
     }
     // А теперь самое интересное - продление программы
     $new_status = $make_payment ? 'active' : 'unpaid';
     $db_data = array('cost_text' => $cost_text, 'cost_image' => $cost_image, 'volume' => $volume, 'impressions' => $volume, 'clicks' => 0, 'current_impressions' => 0, 'avg_cost_text' => $avg_cost_text, 'avg_cost_image' => $avg_cost_image, 'ad_type' => $new_ad_type, 'id_program' => $new_id_program, 'status' => $new_status, 'start_date_time' => date('Y-m-d H:i:s', mktime(0, 0, 0)), 'spent' => $cost, 'pay_escrow' => 'false');
     if ('Flat_Rate' == $program_type) {
         //$db_data['start_date_time'] = date('Y-m-d H:i:s', mktime(0, 0, 0));
         $db_data['end_date_time'] = date('Y-m-d H:i:s', mktime(0, 0, 0) + $volume * 86400 - 1);
     } else {
         $db_data['impressions'] = $volume;
     }
     $stats = new Sppc_Stats();
     $stat = array('id_group' => $id_group, 'id_campaign' => $id_campaign, 'id_site' => $id_site, 'id_channel' => $id_channel, 'id_entity_advertiser' => $id_advertiser, 'earned_admin' => $cost, 'spent' => $cost);
     $stats->writeStatstoDb(array($stat));
     $this->db->where('id_group_site_channel', $id_group_site_channel)->update('group_site_channels', $db_data);
     return $make_payment ? self::SUCCESS : self::UNPAID_SUCCESS;
 }