Esempio n. 1
0
 public static function exists($uid, $start = null, $end = null)
 {
     $uid = Db::convertType($uid);
     $dateQuery = Utils::dateQuery($start, $end);
     $inv_exist = self::first(['$or' => [["user_id" => $uid, "start" => ['$lte' => $dateQuery['start'], '$lte' => $dateQuery['end']], "end" => ['$gte' => $dateQuery['start'], '$gte' => $dateQuery['end']]], ["user_id" => $uid, "start" => Db::dateQuery($start, $end), "end" => ['$gte' => $dateQuery['start'], '$gte' => $dateQuery['end']]], ["user_id" => $uid, "start" => ['$lte' => $dateQuery['start'], '$lte' => $dateQuery['end']], "end" => Db::dateQuery($start, $end)], ["user_id" => $uid, "start" => Db::dateQuery($start, $end), "end" => Db::dateQuery($start, $end)]]]);
     return $inv_exist;
 }
Esempio n. 2
0
 public function inUse()
 {
     $count = Ad::count(['org_id' => $this->org_id, 'category' => ['$elemMatch' => ['$eq' => Utils::mongoObjectId($this->_id)]]]);
     if ($count === 0) {
         return false;
     } else {
         return true;
     }
 }
Esempio n. 3
0
 public function testDateQuery()
 {
     $start = date('Y-m-d', strtotime('-3 day'));
     $end = date('Y-m-d');
     $dateQuery = Utils::dateQuery($start, $end);
     $startObj = $dateQuery['start'];
     $endObj = $dateQuery['end'];
     $sec = $startObj->toDateTime()->getTimestamp();
     $this->assertEquals($start, date('Y-m-d', $sec), 'Start Date doesnot match');
     $sec = $endObj->toDateTime()->getTimestamp();
     $this->assertEquals($end, date('Y-m-d', $sec), 'End Date doesnot match');
 }
Esempio n. 4
0
 public static function campImport($uid, $advert_id, $urls, $extra = [])
 {
     $uid = Utils::mongoObjectId($uid);
     $advert_id = Utils::mongoObjectId($advert_id);
     $data = ['prop' => 'campImport', 'propid' => $uid, 'value' => ['advert_id' => $advert_id, 'urls' => $urls]];
     if (!empty($extra)) {
         $data['value']['campaign'] = $extra;
     }
     $meta = new self($data);
     $meta->save();
     return $meta;
 }
Esempio n. 5
0
 public static function exists($oid, $opts = [])
 {
     $oid = Db::convertType($oid);
     $dateQuery = Utils::dateQuery($opts);
     $multiple = $opts['multiple'] ?? false;
     if ($multiple) {
         $query = "all";
     } else {
         $query = "first";
     }
     $inv_exist = self::$query(['$or' => [["org_id" => $oid, "start" => ['$lte' => $dateQuery['start'], '$lte' => $dateQuery['end']], "end" => ['$gte' => $dateQuery['start'], '$gte' => $dateQuery['end']]], ["org_id" => $oid, "start" => Db::dateQuery($start, $end), "end" => ['$gte' => $dateQuery['start'], '$gte' => $dateQuery['end']]], ["org_id" => $oid, "start" => ['$lte' => $dateQuery['start'], '$lte' => $dateQuery['end']], "end" => Db::dateQuery($start, $end)], ["org_id" => $oid, "start" => Db::dateQuery($start, $end), "end" => Db::dateQuery($start, $end)]]]);
     return $inv_exist;
 }
Esempio n. 6
0
 public static function rssFeeds($org)
 {
     $users = \User::all(['org_id' => $org->_id, 'type' => 'advertiser'], ['_id']);
     $in = [];
     $result = [];
     foreach ($users as $u) {
         $in[] = $u->_id;
     }
     $platforms = \Platform::all(['user_id' => ['$in' => $in]], ['_id', 'url', 'user_id', 'meta']);
     foreach ($platforms as $p) {
         if (isset($p->meta['rss'])) {
             $result[Utils::getMongoID($p->_id)] = $p;
         }
     }
     return $result;
 }
Esempio n. 7
0
 protected static function _getStats($records, &$stats, $date)
 {
     $keys = ['country', 'os', 'device', 'referer'];
     foreach ($records as $r) {
         $obj = Utils::toArray($r);
         $arr =& $stats[$date]['meta'];
         foreach ($keys as $k) {
             if (!isset($arr[$k])) {
                 $arr[$k] = [];
             }
             $index = $r['_id'][$k] ?? null;
             if (is_null($index)) {
                 continue;
             }
             if (strlen(trim($index)) === 0) {
                 $index = "Empty";
             }
             ArrayMethods::counter($arr[$k], $index, $obj['count']);
         }
     }
 }
Esempio n. 8
0
 public static function sendMail(\Organization $org, $opts = [])
 {
     $mail = new PHPMailer();
     // $mail->SMTPDebug = 3;                               // Enable verbose debug output
     $smtpConf = Meta::first(['prop' => 'orgSmtp', 'propid' => $org->_id]);
     if (!$smtpConf) {
         // use the Mailgun API to send mail
         $opts['org'] = $org;
         Mail::send($opts);
         return;
     }
     $smtpConf = $smtpConf->value;
     $password = Utils::decrypt($smtpConf['password'], $org->_id);
     $mail->isSMTP();
     $mail->Host = $smtpConf['server'];
     // Specify main and backup SMTP servers
     $mail->SMTPAuth = true;
     // Enable SMTP authentication
     $mail->Username = $smtpConf['username'];
     // SMTP username
     $mail->Password = $password;
     // SMTP password
     $mail->SMTPSecure = 'tls';
     // Enable TLS encryption, `ssl` also accepted
     $mail->Port = 587;
     // TCP port to connect to
     $mail->setFrom($smtpConf['email'], $smtpConf['from']);
     foreach ($opts['to'] as $email) {
         $mail->addAddress($email);
     }
     $mail->isHTML(true);
     $mail->Subject = $opts['subject'];
     $mail->Body = Mail::_body($opts);
     if (!$mail->send()) {
         throw new \Exception('Failed to send email: ' . $mail->ErrorInfo);
     } else {
         return true;
     }
 }
Esempio n. 9
0
 public static function overall($dateQuery = [], $user = null)
 {
     $q = [];
     $clicks = [];
     $conversions = [];
     $impressions = [];
     $payouts = [];
     $total_clicks = 0;
     $total_conversions = 0;
     $total_payouts = 0;
     $total_impressions = 0;
     if (is_array($user)) {
         $in = ArrayMethods::arrayKeys($user, '_id');
         $q["user_id"] = ['$in' => $in];
     } elseif ($user) {
         $q["user_id"] = $user->id;
     }
     if (count($dateQuery) > 0) {
         $q["created"] = ['$gte' => $dateQuery['start'], '$lte' => $dateQuery['end']];
     }
     $performances = self::all($q, ['revenue', 'clicks', 'created', 'impressions', 'conversions']);
     foreach ($performances as $p) {
         //calculating datewise
         $date = $p->created->format('Y-m-d');
         $total_clicks += $p->clicks;
         ArrayMethods::counter($clicks, $date, $p->clicks);
         $total_conversions += $p->conversions;
         ArrayMethods::counter($conversions, $date, $p->conversions);
         $total_impressions += $p->impressions;
         ArrayMethods::counter($impressions, $date, $p->impressions);
         $total_payouts += $p->revenue;
         ArrayMethods::counter($payouts, $date, $p->revenue);
     }
     ksort($clicks);
     ksort($impressions);
     ksort($payouts);
     $clicks = Utils::dateArray($clicks);
     $impressions = Utils::dateArray($impressions);
     $payouts = Utils::dateArray($payouts);
     return ["impressions" => $impressions, "total_impressions" => $total_impressions, "clicks" => $clicks, "total_clicks" => $total_clicks, "conversions" => $conversions, "total_conversions" => $total_conversions, "payouts" => $payouts, "total_payouts" => $total_payouts];
 }
Esempio n. 10
0
 public static function find(&$search, $key, $fields = [])
 {
     $key = Utils::getMongoID($key);
     if (!array_key_exists($key, $search)) {
         $ad = self::first(['_id' => $key], $fields);
         $search[$key] = $ad;
     } else {
         $ad = $search[$key];
     }
     return $ad;
 }
Esempio n. 11
0
 /**
  * Converts the MongoDB result to an object of class 
  * whose parent is \Shared\Model
  */
 protected function _convert($record)
 {
     if (!$record) {
         return null;
     }
     $columns = $this->getColumns();
     $record = (array) $record;
     $class = get_class($this);
     $c = new $class();
     foreach ($record as $key => $value) {
         if (!property_exists($this, "_{$key}")) {
             continue;
         }
         $raw = "_{$key}";
         if (is_object($value)) {
             if (Db::isType($value, 'id')) {
                 $c->{$raw} = $this->getMongoID($value);
             } else {
                 if (Db::isType($value, 'date')) {
                     $v = $value->toDateTime();
                     $v->settimezone(new \DateTimeZone('Asia/Kolkata'));
                     $c->{$raw} = $v;
                 } else {
                     if (Db::isType($value, 'document')) {
                         $c->{$raw} = Utils::toArray($value);
                     } else {
                         // fallback case
                         $c->{$raw} = (object) $value;
                     }
                 }
             }
         } else {
             $c->{$raw} = $value;
         }
     }
     return $c;
 }
Esempio n. 12
0
 public static function dateQuery($start = null, $end = null)
 {
     $changed = false;
     if ($start && $end) {
         if (self::isType($start, 'date') && self::isType($end, 'date')) {
             $dq = ['start' => $start, 'end' => $end];
             $changed = true;
         }
     }
     if (!$changed) {
         $dq = \Shared\Utils::dateQuery(['start' => $start, 'end' => $end]);
     }
     $result = [];
     if ($start) {
         $result['$gte'] = $dq['start'];
     }
     if ($end) {
         $result['$lte'] = $dq['end'];
     }
     return $result;
 }
Esempio n. 13
0
 public function removeFields()
 {
     $meta = $this->_meta;
     $afields = $meta['afields'] ?? [];
     foreach ($meta['afields'] as $key => $value) {
         Utils::media($value, 'remove');
     }
 }
Esempio n. 14
0
 /**
  * Finds the commission based on the "ad_id"
  * @param  array &$search Array of Commission (to prevent querying from database again and again)
  * @param  mixed $key     Object|String representing Ad ID
  */
 public static function find(&$search, $key)
 {
     $key = \Shared\Utils::getMongoID($key);
     if (!array_key_exists($key, $search)) {
         $commissions = self::all(['ad_id' => $key], ['rate', 'revenue', 'model', 'coverage']);
         $search[$key] = $comm = self::filter($commissions);
     } else {
         $comm = $search[$key];
     }
     return $comm;
 }
Esempio n. 15
0
 /**
  * @before _secure
  * @after _displayData
  */
 public function platforms($id = null)
 {
     $this->seo(["title" => "Platform wise click stats"]);
     $view = $this->getActionView();
     $org = $this->org;
     $clickCol = Registry::get("MongoDB")->clicks;
     // find the platforms
     $platforms = \Platform::all(['user_id' => ['$in' => $org->users('advertisers')]], ['_id', 'url']);
     if (count($platforms) === 0) {
         return $view->set(['platforms' => [], 'publishers' => []]);
     }
     $key = array_rand($platforms);
     $url = RM::get('link', $platforms[$key]->url);
     // find ads having this url
     $ads = \Ad::all(['org_id' => $org->_id], ['_id', 'url']);
     $in = Utils::mongoObjectId(array_keys($ads));
     $matched = [];
     foreach ($ads as $a) {
         $regex = preg_quote($url, '.');
         if (preg_match('#^' . $regex . '#', $a->url)) {
             $matched[] = Utils::mongoObjectId($a->_id);
         }
     }
     if (count($matched) === 0) {
         $query['adid'] = ['$in' => $in];
     } else {
         $query['adid'] = ['$in' => $matched];
     }
     $query['is_bot'] = false;
     $query['created'] = Db::dateQuery($this->start, $this->end);
     $records = $clickCol->aggregate([['$match' => $query], ['$projection' => ['_id' => 1, 'pid' => 1]], ['$group' => ['_id' => '$pid', 'count' => ['$sum' => 1]]], ['$sort' => ['count' => -1]]]);
     $result = [];
     $publishers = [];
     foreach ($records as $r) {
         $obj = (object) $r;
         $id = Utils::getMongoID($obj->_id);
         $user = User::first(['_id' => $id], ['_id', 'name']);
         $result[$id] = (object) ['_id' => $user->_id, 'name' => $user->name, 'clicks' => $obj->count];
     }
     $view->set(['platforms' => $platforms, 'link' => $url, 'publishers' => $result]);
 }
Esempio n. 16
0
 /**
  * @before _secure
  */
 public function import()
 {
     $this->seo(['title' => 'Campaign Import', 'description' => 'Create a new campaign']);
     $view = $this->getActionView();
     $org = $this->org;
     $advertisers = \User::all(["org_id = ?" => $this->org->_id, 'type = ?' => 'advertiser'], ['_id', 'name']);
     if (count($advertisers) === 0) {
         $this->redirect('/advertiser/add.html');
     }
     $platforms = \Platform::rssFeeds($this->org);
     $view->set('advertiser', $advertisers);
     $action = RM::post('action', '');
     switch ($action) {
         case 'campImport':
             $this->_import($org, $advertisers, $view);
             break;
         case 'platform':
             $pid = RM::post('pid');
             $p = $platforms[$pid];
             $meta = $p->meta;
             $meta['rss']['url'] = RM::post('url');
             $parsing = (bool) (int) RM::post('parsing', "1");
             $meta['rss']['parsing'] = $parsing;
             $p->meta = $meta;
             $p->save();
             $view->set('message', 'Updated Rss feed');
             break;
         case 'newRss':
             $url = RM::post('rss_link');
             $a = array_values($advertisers)[0];
             $advert_id = RM::post('advert_id', $a->getMongoID());
             $advert = \User::first(['_id = ?' => $advert_id, 'type = ?' => 'advertiser']);
             if (!$advert) {
                 return $view->set('message', 'Invalid Request!!');
             }
             // try to find a platform for the given advertiser
             $domain = parse_url($url, PHP_URL_HOST);
             $regex = preg_quote($domain);
             $p = \Platform::first(['user_id' => $advert_id, 'url' => Utils::mongoRegex($regex)]);
             $msg = "RSS Feed Added. Campaigns Will be imported within an hour";
             try {
                 // Now schedule importing of campaigns
                 $result = \Shared\Rss::getFeed($url);
                 $rate = RM::post('rate', 0.2);
                 $revenue = RM::post('revenue', 0.25);
                 $rss = ['url' => $url, 'parsing' => true, 'lastCrawled' => $result['lastCrawled'], 'campaign' => ['model' => RM::post('model', 'cpc'), 'rate' => $this->currency($rate), 'revenue' => $this->currency($rate)]];
                 // if platform not found then add new
                 if (!$p) {
                     $p = new \Platform(['url' => $domain, 'user_id' => $advert_id]);
                 }
                 $meta = $p->meta;
                 $meta['rss'] = $rss;
                 $p->meta = $meta;
                 $p->save();
                 \Meta::campImport($this->user->_id, $advert_id, $result['urls'], $rss['campaign']);
             } catch (\Exception $e) {
                 $msg = "Internal Server Error!!";
             }
             $view->set('message', $msg);
             break;
     }
     $platforms = \Platform::rssFeeds($this->org);
     $view->set('platforms', $platforms);
 }
Esempio n. 17
0
 /**
  * @before _secure
  */
 public function create()
 {
     $this->_create();
     $view = $this->getActionView();
     if (RM::type() == 'POST') {
         $img = null;
         // give preference to uploaded image
         $img = $this->_upload('image', 'images', ['extension' => 'jpe?g|gif|bmp|png|tif']);
         if (!$img) {
             $img_url = RM::post("image_url");
             $img = Shared\Utils::downloadImage($img_url);
         }
         if (!$img) {
             return $view->set('message', 'Failed to upload the image');
         }
         $expiry = RM::post('expiry');
         $campaign = new \Ad(['user_id' => RM::post('advert_id'), 'title' => RM::post('title'), 'description' => RM::post('description'), 'org_id' => $this->org->_id, 'url' => RM::post('url'), 'preview_url' => RM::post('preview_url'), 'category' => \Ad::setCategories(RM::post('category')), 'image' => $img, 'type' => RM::post('type', 'article'), 'device' => RM::post('device', ['all']), 'live' => false]);
         $visibility = RM::post('visibility', 'public');
         if ($visibility === "private") {
             $campaign->meta = ['private' => true];
         }
         $permission = RM::post('permission', false);
         if ($permission == "yes") {
             $campaign->meta = ['permission' => true];
         }
         if ($expiry) {
             $campaign->expiry = $expiry;
         }
         try {
             if ($campaign->type === "video") {
                 $url = RM::post('videoUrl');
                 $ytdl = new Downloader($url);
                 $campaign->getMeta()['processing'] = true;
                 $campaign->getMeta()['videoUrl'] = $ytdl->getUrl();
             }
         } catch (\Exception $e) {
             // Invalid URL
             return $view->set("errors", ['videoUrl' => ["Pass a valid youtube video URL"]]);
         }
         if (!$campaign->validate()) {
             return $view->set("errors", $campaign->errors);
         }
         $campaign->save();
         $models = RM::post('model');
         $comm_desc = RM::post('comm_desc');
         $revenue = RM::post('revenue');
         $rate = RM::post('rate');
         $coverage = RM::post('coverage');
         foreach ($models as $key => $value) {
             $commission = new \Commission(['ad_id' => $campaign->_id, 'description' => $comm_desc[$key], 'model' => $value, 'rate' => $this->currency($rate[$key]), 'revenue' => $this->currency($revenue[$key]), 'coverage' => $coverage[$key]]);
             $commission->save();
         }
         Registry::get("session")->set('$flashMessage', 'Campaign Created successfully!!');
         $this->redirect("/campaign/manage.html");
     }
 }
Esempio n. 18
0
 /**
  * @before _secure
  * @after _cleanUp
  */
 public function campaign($id = null)
 {
     $view = $this->getActionView();
     $org = $this->_org;
     $active = RequestMethods::get('active', 1);
     $fields = ['_id', 'title', 'description', 'image', 'url', 'device', 'expiry', 'created'];
     $commFields = ['model', 'rate', 'revenue', 'coverage'];
     if ($id) {
         $campaign = Ad::first(['_id' => $id, 'org_id' => $org->_id], $fields);
     } else {
         $campaign = null;
     }
     if ($id && !$campaign) {
         return $this->failure('30');
     }
     $type = RequestMethods::type();
     switch ($type) {
         case 'GET':
             if (!$id) {
                 // display list of campaigns
                 $ads = Ad::all(['org_id' => $org->_id, 'live' => $active], $fields);
                 $ads = Ad::objectArr($ads, $fields);
                 $results = [];
                 foreach ($ads as $id => $a) {
                     $arr = Utils::toArray($a);
                     $comms = Commission::all(['ad_id' => $a->_id], $commFields);
                     $arr['commissions'] = Ad::objectArr($comms, $commFields);
                     $results[$id] = (object) $arr;
                 }
                 $data = ['campaigns' => $results];
                 $view->set('data', $data);
             } else {
                 $ads = Ad::objectArr($campaign, $fields);
                 $campaign = array_shift($ads);
                 $comm = Commission::all(['ad_id' => $campaign->_id], $commFields);
                 $data = ['campaign' => $campaign, 'commissions' => Commission::objectArr($comm, $commFields)];
                 $view->set('data', $data);
             }
             break;
         case 'POST':
             if ($id) {
                 // edit a particular campaign
             } else {
                 // create a new campaign
                 $fields = ['title', 'description', 'url', 'expiry', 'category', 'device', 'user_id'];
                 $img = RequestMethods::post('image');
                 // contains image url
                 $campaign = new Ad(['org_id' => $org->_id, 'type' => 'article', 'image' => Utils::media($img, 'download')]);
                 foreach ($fields as $f) {
                     $campaign->{$f} = RequestMethods::post($f);
                 }
                 $view->set('success', false);
                 $visibility = RequestMethods::post('visibility', 'public');
                 if ($visibility === 'private') {
                     $campaign->getMeta()['private'] = true;
                 }
                 $opts = ['devices' => array_keys(Shared\Markup::devices()), 'advertisers' => $org->users('advertiser', false)];
                 if (true) {
                     // $campaign->save();
                     $arr = ArrayMethods::reArray($_POST['commissions']);
                     var_dump($arr);
                     var_dump($_POST['commissions']);
                     $view->set('success', true);
                 } else {
                     $data = ['errors' => $campaign->errors];
                     $view->set('data', $data);
                 }
             }
             break;
         case 'DELETE':
             $message = $campaign->delete();
             $view->set($message);
             break;
     }
 }
Esempio n. 19
0
 public function users($type = "publisher", $object = true)
 {
     $users = \User::all(["org_id = ?" => $this->_id, "type = ?" => $type], ["_id"]);
     $ids = array_keys($users);
     if ($object === true) {
         return Utils::mongoObjectId($ids);
     } else {
         if ($object === 'users') {
             return $users;
         } else {
             if ($object === false) {
                 return $ids;
             }
         }
     }
 }
Esempio n. 20
0
 public static function classify($clicks, $type = 'adid')
 {
     $classify = [];
     foreach ($clicks as $result) {
         $c = ArrayMethods::toObject($result);
         $key = Utils::getMongoID($c->{$type} ?? '');
         if (strlen($key) == 0) {
             $key = "Empty";
         }
         $key = str_replace(".", "-", $key);
         if (!isset($classify[$key]) || !array_key_exists($key, $classify)) {
             $classify[$key] = [];
         }
         $classify[$key][] = $c;
     }
     return $classify;
 }
Esempio n. 21
0
 /**
  * @before _secure
  */
 public function platforms($id = null)
 {
     $this->seo(array("title" => "Platforms"));
     $view = $this->getActionView();
     $query['user_id'] = ['$in' => $this->org->users('publisher')];
     $limit = RM::get("limit", 20);
     $page = RM::get("page", 1);
     $property = RM::get("property", '');
     $value = RM::get("value");
     if (in_array($property, ["live", "user_id"])) {
         $query["{$property} = ?"] = $value;
     } else {
         if (in_array($property, ["url"])) {
             $query[$property] = Utils::mongoRegex($value);
         }
     }
     if (RM::type() === 'POST') {
         $p = \Platform::first(['_id' => $id, 'user_id' => $query['user_id']]);
         if (!$p) {
             return $view->set('message', "Invalid Request!!");
         }
         try {
             $updateAble = ['live', 'user_id', 'url'];
             foreach ($_POST as $key => $value) {
                 if (in_array($key, $updateAble)) {
                     $p->{$key} = $value;
                 }
             }
             $p->save();
             return $view->set('message', 'Platform updated!!');
         } catch (\Exception $e) {
             return $view->set('message', "Invalid Request Parameters!!");
         }
     }
     if (RM::type() === 'DELETE') {
         $p = \Platform::first(['_id' => $id, 'user_id' => $query['user_id']]);
         if (!$p) {
             return $view->set('message', "Invalid Request!!");
         }
         $p->delete();
         return $view->set('message', "Platform Removed!!");
     }
     $platforms = Platform::all($query, [], 'created', 'desc', $limit, $page);
     $count = Platform::count($query);
     $view->set("platforms", $platforms)->set("count", $count)->set("property", $property)->set("value", $value)->set("limit", $limit)->set("page", $page);
 }
Esempio n. 22
0
 public static function customFields($user, $org)
 {
     $afields = \Meta::search('customField', $org);
     if (count($afields) > 0) {
         $meta = $user->meta ?? [];
         $extraFields = [];
         foreach ($afields as $value) {
             $key = $value['name'];
             $type = $value['type'];
             $message = $value['label'] . " is required!!";
             switch ($type) {
                 case 'file':
                     $v = Utils::media($key, 'upload', ['extension' => 'jpe?g|gif|bmp|png|tif|pdf']);
                     if (!$v) {
                         $message = "Please Upload a valid image or pdf file";
                     }
                     break;
                 case 'text':
                     $v = RequestMethods::post($key);
                     break;
                 case 'date':
                     $d = RequestMethods::post($key, date('Y-m-d'));
                     $v = Db::convertType($d, 'date');
                     break;
                 default:
                     $v = '';
                     break;
             }
             if (!$v && $value['required']) {
                 return ["message" => $message, "success" => false];
             }
             $extraFields[$key] = $v;
         }
         $meta['afields'] = $extraFields;
         $user->meta = $meta;
     }
     $user->save();
     return ["success" => true];
 }
Esempio n. 23
0
 public function generateBills()
 {
     $orgs = Organization::all(["live = ?" => true]);
     foreach ($orgs as $org) {
         $imp_cost = 0;
         $click_cost = 0;
         $month_ini = new DateTime("first day of last month");
         $month_end = new DateTime("last day of last month");
         $start = $month_ini->format('Y-m-d');
         $end = $month_end->format('Y-m-d');
         $dateQuery = Utils::dateQuery(['start' => $start, 'end' => $end]);
         // find advertiser performances to get clicks and impressions
         $performances = \Performance::overall($dateQuery, User::all(['org_id' => $org->_id, 'type' => 'advertiser'], ['_id']));
         $clicks = $performances['total_clicks'];
         if ($clicks > 1000) {
             $click_cost = 0.001 * $clicks * $org->meta["bill"]["tcc"];
         }
         $impressions = $performances['total_impressions'];
         if ($impressions > 100000) {
             $imp_cost = 0.001 * 0.001 * $impressions * $org->meta["bill"]["mic"];
         }
         $total = $click_cost + $imp_cost;
         $bill = new Bill(["org_id" => $org->id, "impressions" => $impressions, "clicks" => $clicks, "mic" => $org->meta["bill"]["mic"], "tcc" => $org->meta["bill"]["tcc"], "start" => $start, "end" => $end, "amount" => $total, "live" => false, "created" => Db::time('-1 day')]);
         if ($total > 1) {
             $bill->save();
             $user = User::first(["org_id = ?" => $org->id, "type = ?" => "admin"]);
             Mail::send(['user' => $user, 'bill' => $bill, 'template' => 'adminBilling', 'subject' => 'Billing at vNative', 'click_cost' => $click_cost, 'imp_cost' => $imp_cost, 'org' => $org]);
         }
     }
 }