public function createInvoice() { $query = new Am_Query(new InvoiceLogTable()); $query->addField("m.login", "login"); $query->addField("m.user_id", "user_id"); $query->addField("i.public_id"); $query->leftJoin("?_user", "m", "t.user_id=m.user_id"); $query->leftJoin("?_invoice", "i", "t.invoice_id=i.invoice_id"); $query->setOrder('log_id', 'desc'); $g = new Am_Grid_Editable('_invoice', ___('Invoice Log'), $query, $this->getRequest(), $this->view); $g->setPermissionId(Am_Auth_Admin::PERM_LOGS_INVOICE); $userUrl = new Am_View_Helper_UserUrl(); $g->addField(new Am_Grid_Field_Date('tm', ___('Date/Time'), true)); $g->addField(new Am_Grid_Field('invoice_id', ___('Invoice'), true, '', array($this, 'renderInvoice'), '5%')); $g->addField(new Am_Grid_Field('login', ___('User'), true))->addDecorator(new Am_Grid_Field_Decorator_Link($userUrl->userUrl('{user_id}'), '_top')); $g->addField(new Am_Grid_Field('remote_addr', ___('IP'), true, '', null, '5%')); $g->addField(new Am_Grid_Field('paysys_id', ___('Paysystem'), true, '', null, '10%')); $g->addField(new Am_Grid_Field('title', ___('Title'), true, '', null, '25%')); $g->addField(new Am_Grid_Field_Expandable('details', ___('Details'), false, '', null, '25%'))->setGetFunction(array($this, 'renderInvoiceDetails')); $g->actionsClear(); $g->actionAdd(new Am_Grid_Action_InvoiceRetry('retry')); $g->setFilter(new Am_Grid_Filter_InvoiceLog()); $g->actionAdd(new Am_Grid_Action_Group_Callback('retrygroup', ___("Repeat Action Handling"), array('Am_Grid_Action_InvoiceRetry', 'groupCallback'))); return $g; }
function commTabAction() { $this->setActiveMenu('users-browse'); $ds = new Am_Query($this->getDi()->affCommissionTable); $ds->leftJoin('?_invoice', 'i', 'i.invoice_id=t.invoice_id'); $ds->leftJoin('?_user', 'u', 'u.user_id=i.user_id'); $ds->leftJoin('?_product', 'p', 't.product_id=p.product_id')->addField('u.user_id', 'user_id')->addField('CONCAT(u.login, \' (\',u.name_f, \' \',u.name_l,\') [#\', u.user_id, \']\')', 'user_name')->addField('p.title', 'product_title')->addField('IF(payout_detail_id IS NULL, \'no\', \'yes\')', 'is_paid'); $ds->setOrder('date', 'desc')->addWhere('t.aff_id=?', $this->getParam('user_id')); $grid = new Am_Grid_Editable('_affcomm', ___('Affiliate Commission'), $ds, $this->_request, $this->view); $grid->setPermissionId(Bootstrap_Aff::ADMIN_PERM_ID); $grid->actionsClear(); $userUrl = new Am_View_Helper_UserUrl(); $grid->addField(new Am_Grid_Field_Date('date', ___('Date')))->setFormatDate(); $grid->addField('user_name', ___('User'))->addDecorator(new Am_Grid_Field_Decorator_Link($userUrl->userUrl('{user_id}'), '_top')); $grid->addField('product_title', ___('Product')); $grid->addField('record_type', ___('Type'))->setRenderFunction(array($this, 'renderType')); $fieldAmount = $grid->addField('amount', ___('Commission'))->setRenderFunction(array($this, 'renderCommAmount')); $grid->addField('is_paid', ___('Paid')); $grid->addField('tier', ___('Tier'))->setRenderFunction(array($this, 'renderTier')); $grid->addCallback(Am_Grid_ReadOnly::CB_TR_ATTRIBS, array($this, 'commCbGetTrAttribs')); $grid->setFilter(new Am_Grid_Filter_AffCommission()); $grid->actionAdd(new Am_Grid_Action_Total())->addField($fieldAmount, "IF(record_type='void', -1*%1\$s, %1\$s)"); $grid->actionAdd(new Am_Grid_Action_Aff_Void()); $grid->runWithLayout('admin/user-layout.phtml'); }
function process(Am_Form $f) { $vars = $f->getValue(); $user = Am_Di::getInstance()->userTable->findFirstByLogin($vars['user']); if (!$user) { list($el) = $f->getElementsByName('user'); $el->setError(___('User %s not found', $vars['user'])); return false; } $aff = Am_Di::getInstance()->userTable->findFirstByLogin($vars['aff']); if (!$aff) { list($el) = $f->getElementsByName('aff'); $el->setError(___('Affiliate %s not found', $vars['user'])); return false; } $couponAff = null; if ($vars['coupon']) { $coupon = Am_DI::getInstance()->couponTable->findFirstByCode($vars['coupon']); if ($coupon && ($coupon->aff_id || $coupon->getBatch()->aff_id)) { $couponAff = Am_Di::getInstance()->userTable->load($coupon->aff_id ? $coupon->aff_id : $coupon->getBatch()->aff_id, false); } } /* @var $invoice Invoice */ $invoice = Am_Di::getInstance()->invoiceTable->createRecord(); $invoice->setUser($user); if ($vars['coupon']) { $invoice->setCouponCode($vars['coupon']); $error = $invoice->validateCoupon(); if ($error) { throw new Am_Exception_InputError($error); } } $user->aff_id = $aff->pk(); foreach ($vars['product_id'] as $plan_id => $qty) { $p = Am_Di::getInstance()->billingPlanTable->load($plan_id); $pr = $p->getProduct(); $invoice->add($pr, $qty); } $invoice->calculate(); $invoice->setPaysystem($vars['paysys_id'], false); $invoice->invoice_id = '00000'; $invoice->public_id = 'TEST'; $invoice->tm_added = sqlTime('now'); echo "<pre>"; echo $invoice->render(); echo "\nBilling Terms: " . $invoice->getTerms() . "\n" . str_repeat("-", 70) . "\n"; $helper = new Am_View_Helper_UserUrl(); $helper->setView(new Am_View()); printf("User Ordering the subscription: <a target='_blank' class='link' href='%s'>%d/%s "%s" <%s></a>\n", $helper->userUrl($user->pk()), $user->pk(), Am_Controller::escape($user->login), Am_Controller::escape($user->name_f . ' ' . $user->name_l), Am_Controller::escape($user->email)); printf("Reffered Affiliate: <a target='_blank' class='link' href='%s'>%d/%s "%s" <%s></a>\n", $helper->userUrl($aff->pk()), $aff->pk(), Am_Controller::escape($aff->login), Am_Controller::escape($aff->name_f . ' ' . $aff->name_l), Am_Controller::escape($aff->email)); if ($couponAff) { printf("Affiliate Detected by Coupon (will get commision): <a target='_blank' class='link' href='%s'>%d/%s "%s" <%s></a>\n", $helper->userUrl($couponAff->pk()), $couponAff->pk(), Am_Controller::escape($couponAff->login), Am_Controller::escape($couponAff->name_f . ' ' . $couponAff->name_l), Am_Controller::escape($couponAff->email)); } $max_tier = Am_Di::getInstance()->affCommissionRuleTable->getMaxTier(); //COMMISSION FOR FREE SIGNUP if (!(double) $invoice->first_total && !(double) $invoice->second_total && $vars['is_first']) { echo "\n<strong>FREE SIGNUP</strong>:\n"; list($item, ) = $invoice->getItems(); echo sprintf("* ITEM: %s\n", Am_Controller::escape($item->item_title)); foreach (Am_Di::getInstance()->affCommissionRuleTable->findRules($invoice, $item, $aff, 0, 0) as $rule) { echo $rule->render('* '); } $to_pay = Am_Di::getInstance()->affCommissionRuleTable->calculate($invoice, $item, $aff, 0, 0); echo "* AFFILIATE WILL GET FOR THIS ITEM: " . Am_Currency::render($to_pay) . "\n"; for ($i = 1; $i <= $max_tier; $i++) { $to_pay = Am_Di::getInstance()->affCommissionRuleTable->calculate($invoice, $item, $aff, 0, $i, $to_pay); $tier = $i + 1; echo "* {$tier}-TIER AFFILIATE WILL GET FOR THIS ITEM: " . Am_Currency::render($to_pay) . "\n"; } echo str_repeat("-", 70) . "\n"; } //COMMISSION FOR FIRST PAYMENT $price_field = (double) $invoice->first_total ? 'first_total' : 'second_total'; if ((double) $invoice->{$price_field}) { echo "\n<strong>FIRST PAYMENT ({$invoice->currency} {$invoice->{$price_field}})</strong>:\n"; $payment = Am_Di::getInstance()->invoicePaymentTable->createRecord(); $payment->invoice_id = @$invoice->invoice_id; $payment->dattm = sqlTime('now'); $payment->amount = $invoice->{$price_field}; echo str_repeat("-", 70) . "\n"; foreach ($invoice->getItems() as $item) { if (!(double) $item->{$price_field}) { continue; } //do not calculate commission for free items within invoice echo sprintf("* ITEM: %s ({$invoice->currency} {$item->{$price_field}})\n", Am_Controller::escape($item->item_title)); foreach (Am_Di::getInstance()->affCommissionRuleTable->findRules($invoice, $item, $aff, 1, 0, $payment->dattm) as $rule) { echo $rule->render('* '); } $to_pay = Am_Di::getInstance()->affCommissionRuleTable->calculate($invoice, $item, $aff, 1, 0, $payment->amount, $payment->dattm); echo "* AFFILIATE WILL GET FOR THIS ITEM: <strong>" . Am_Currency::render($to_pay) . "</strong>\n"; for ($i = 1; $i <= $max_tier; $i++) { $to_pay = Am_Di::getInstance()->affCommissionRuleTable->calculate($invoice, $item, $aff, 1, $i, $to_pay, $payment->dattm); $tier = $i + 1; echo "* {$tier}-TIER AFFILIATE WILL GET FOR THIS ITEM: <strong>" . Am_Currency::render($to_pay) . "</strong>\n"; } echo str_repeat("-", 70) . "\n"; } } //COMMISSION FOR SECOND AND SUBSEQUENT PAYMENTS if ((double) $invoice->second_total) { echo "\n<strong>SECOND AND SUBSEQUENT PAYMENTS ({$invoice->second_total} {$invoice->currency})</strong>:\n"; $payment = Am_Di::getInstance()->invoicePaymentTable->createRecord(); $payment->invoice_id = @$invoice->invoice_id; $payment->dattm = sqlTime('now'); $payment->amount = $invoice->second_total; echo str_repeat("-", 70) . "\n"; foreach ($invoice->getItems() as $item) { if (!(double) $item->second_total) { continue; } //do not calculate commission for free items within invoice echo sprintf("* ITEM: %s ({$item->second_total} {$invoice->currency})\n", Am_Controller::escape($item->item_title)); foreach (Am_Di::getInstance()->affCommissionRuleTable->findRules($invoice, $item, $aff, 2, 0, $payment->dattm) as $rule) { echo $rule->render('* '); } $to_pay = Am_Di::getInstance()->affCommissionRuleTable->calculate($invoice, $item, $aff, 2, 0, $payment->amount, $payment->dattm); echo "* AFFILIATE WILL GET FOR THIS ITEM: <strong>" . Am_Currency::render($to_pay) . "</strong>\n"; for ($i = 1; $i <= $max_tier; $i++) { $to_pay = Am_Di::getInstance()->affCommissionRuleTable->calculate($invoice, $item, $aff, 2, $i, $to_pay, $payment->dattm); $tier = $i + 1; echo "* {$tier}-TIER AFFILIATE WILL GET FOR THIS ITEM: <strong>" . Am_Currency::render($to_pay) . "</strong>\n"; } echo str_repeat("-", 70) . "\n"; } } echo "</pre>"; return true; }
public function clickAction() { $ds = new Am_Query($this->getDi()->notificationClickTable); $ds->leftJoin('?_user', 'u', 't.user_id=u.user_id')->addField('COUNT(t.notification_click_id)', 'cnt')->addField('u.*')->addField("CONCAT(u.name_f, ' ', u.name_l)", 'name')->groupBy('user_id', 'u')->addWhere('notification_id=?', $this->getParam('id')); $grid = new Am_Grid_ReadOnly('_n_c', ___('Statistics'), $ds, $this->getRequest(), $this->getView(), $this->getDi()); $userUrl = new Am_View_Helper_UserUrl(); $grid->addField('login', ___('Username'))->addDecorator(new Am_Grid_Field_Decorator_Link($userUrl->userUrl('{user_id}'), '_top')); $grid->addField('name', ___('Name')); $grid->addField('email', ___('E-Mail Address')); $grid->addField('cnt', ___('Clicks'), null, null, null, '1%'); $grid->runWithLayout($this->layout); }
function viewAction() { Am_Aff_PayoutMethod::static_addFields(); // display payouts list date | method | total | paid | $id = $this->getInt('payout_id'); if (!$id) { throw new Am_Exception_InputError("Not payout_id passed"); } $ds = new Am_Query($this->getDi()->affPayoutDetailTable); $ds->leftJoin('?_aff_payout', 'p', 'p.payout_id=t.payout_id'); $ds->leftJoin('?_user', 'u', 't.aff_id=u.user_id'); $ds->addField('u.*'); $ds->addField('p.type', 'type'); $ds->addWhere('t.payout_id=?d', $id); $grid = new Am_Grid_Editable('_d', ___("Payout %d Details", $id), $ds, $this->_request, $this->view); $grid->setEventId('gridAffPayoutDetail'); $grid->setPermissionId(Bootstrap_Aff::ADMIN_PERM_ID); $grid->addCallback(Am_Grid_Editable::CB_RENDER_TABLE, array($this, 'addBackLink')); $userUrl = new Am_View_Helper_UserUrl(); $grid->addField('email', ___('E-Mail'))->addDecorator(new Am_Grid_Field_Decorator_Link($userUrl->userUrl('{user_id}'), '_top')); $grid->addField('name_f', ___('First Name')); $grid->addField('name_l', ___('Last Name')); $grid->addField(new Am_Grid_Field_Enum('type', ___('Payout Method')))->setTranslations(Am_Aff_PayoutMethod::getAvailableOptions()); $grid->addField('amount', ___('Amount'))->setGetFunction(array($this, 'getAmount')); // $grid->addField('receipt_id', ___('Receipt Id')); $grid->addField(new Am_Grid_Field_Enum('is_paid', ___('Is Paid?')))->setTranslations(array(0 => ___('No'), 1 => ___('Yes'))); $grid->addField(new Am_Grid_Field_Expandable('_details', ___('Payout Details')))->setGetFunction(array($this, 'getPayoutDetails')); $grid->actionsClear(); //$grid->actionAdd(new Am_Grid_Action_LiveEdit('receipt_id')); $grid->actionAdd(new Am_Grid_Action_PayoutMarkPaid('mark_paid', ___('Mark Paid'))); $grid->actionAdd(new Am_Grid_Action_PayoutMarkNotPaid('mark_notpaid', ___('Mark NOT Paid'))); $grid->addCallback(Am_Grid_ReadOnly::CB_TR_ATTRIBS, array($this, 'detailCbGetTrAttribs')); $grid->runWithLayout(); }
public function onGridUserInitForm(Am_Event_Grid $event) { $fieldSet = $event->getGrid()->getForm()->addAdvFieldset('affiliate')->setLabel(___('Affiliate Program')); $user = $event->getGrid()->getRecord(); $user_id = $user->pk(); $affGroup = $fieldSet->addGroup()->setLabel(___('Referred Affiliate')); $affEl = $affGroup->addText('_aff', array('placeholder' => ___('Type Username or E-Mail')))->setId('aff-refered-affiliate'); $fieldSet->addScript()->setScript(<<<CUT \$("input#aff-refered-affiliate").autocomplete({ minLength: 2, source: window.rootUrl + "/aff/admin/autocomplete/?exclude={$user_id}" }); CUT ); if (!empty($user->aff_id)) { try { $aff = $this->getDi()->userTable->load($user->aff_id); $affEl->setValue($aff->login); $affEl->setAttribute('style', 'display:none'); $url = new Am_View_Helper_UserUrl(); $is_expired = false; if ($commissionDays = $this->getDi()->config->get('aff.commission_days')) { $signupDays = $this->getDi()->time - strtotime($user->aff_added ? $user->aff_added : $user->added); $signupDays = intval($signupDays / (3600 * 24)); // to days if ($commissionDays < $signupDays) { $is_expired = true; } } $affHtml = sprintf('<div><a class="link" href="%s">%s %s (%s)</a> [<a href="javascript:;" title="%s" class="local" id="aff-unassign-affiliate">x</a>]%s</div>', Am_Controller::escape($url->userUrl($user->aff_id)), $aff->name_f, $aff->name_l, $aff->email, ___('Unassign Affiliate'), $is_expired ? sprintf('<div class="red">%s</div>', ___('affiliate <-> user relation is expired (%saccording your settings%s <strong>User-Affiliate Relation Lifetime</strong> is %d day(s)), no commissions will be added for new payments', '<a href="' . REL_ROOT_URL . '/admin-setup/aff">', '</a>', $commissionDays)) : ''); $affGroup->addStatic()->setContent($affHtml); $affGroup->addScript()->setScript(<<<CUT \$('#aff-unassign-affiliate').click(function(){ \$(this).closest('div').remove(); \$('#aff-refered-affiliate').val(''); \$('#aff-refered-affiliate').show(); }) CUT ); } catch (Am_Exception $e) { // ignore if affiliate was deleted } } if ($user->isLoaded() && ($source = $user->data()->get('aff-source'))) { preg_match('/^([a-z]*)(-(.*))?$/i', $source, $match); $res = ''; switch ($match[1]) { case 'ip': $res = ___('Assigned by IP <strong>%s</strong> at %s', $match[3], amDatetime($user->aff_added)); break; case 'cookie': $res = ___('Assigned by COOKIE at %s', amDatetime($user->aff_added)); break; case 'admin': $admin = $this->getDi()->adminTable->load($match[3], false); $res = ___('Assigned by Administrator <strong>%s</strong> at %s', $admin ? sprintf('%s (%s %s)', $admin->login, $admin->name_f, $admin->name_l) : '#' . $match[3], amDatetime($user->aff_added)); break; case 'coupon': $res = ___('Assigned by Coupon %s at %s', '<a href="' . REL_ROOT_URL . '/admin-coupons?_coupon_filter=' . urlencode($match[3]) . '">' . $match[3] . '</a>', amDatetime($user->aff_added)); break; case 'invoice': $invoice = $this->getDi()->invoiceTable->load($match[3], false); $res = ___('Assigned by Invoice %s at %s', $invoice ? '<a href="' . REL_ROOT_URL . '/admin-user-payments/index/user_id/' . $invoice->user_id . '#invoice-' . $invoice->pk() . '">' . $invoice->pk() . '/' . $invoice->public_id . '</a>' : '<strong>#' . $match[3] . '</strong>', amDatetime($user->aff_added)); break; default: $res = $source; } $fieldSet->addHtml()->setLabel(___('Affiliate Source'))->setHtml('<div>' . $res . '</div>'); } $fieldSet->addElement('advradio', 'is_affiliate')->setLabel(___("Is Affiliate?\n" . 'customer / affiliate status'))->loadOptions(array('0' => ___('No'), '1' => ___('Both Affiliate and member'), '2' => ___('Only Affiliate %s(rarely used)%s', '<em>', '</em>')))->setValue($this->getConfig('signup_type') == 1 ? 1 : 0); if ($cr = $this->getConfig('custom_redirect')) { $fieldSet->addElement('advradio', 'aff_custom_redirect')->setLabel(___('Allow Affiliate to redirect Referrers to any url'))->loadOptions(array('0' => $cr == self::AFF_CUSTOM_REDIRECT_ALLOW_SOME_DENY_OTHERS ? ___('No') : ___('Yes'), '1' => $cr == self::AFF_CUSTOM_REDIRECT_DENY_SOME_ALLOW_OTHERS ? ___('No') : ___('Yes'))); } $this->addPayoutInputs($fieldSet); }
public function onUserForm(Am_Event_UserForm $event) { if ($event->getAction() == Am_Event_UserForm::BEFORE_SAVE) { $input = $event->getForm()->getValue(); if (!empty($input['_aff'])) { $aff = $this->getDi()->userTable->findFirstByLogin($input['_aff'], false); if ($aff) { if ($aff->pk() == $event->getUser()->pk()) { throw new Am_Exception_InputError("Cannot assign affiliate to himself"); } $event->getUser()->aff_id = $aff->pk(); } else { throw new Am_Exception_InputError("Affiliate not found, username specified: " . Am_Controller::escape($input['_aff'])); } } } if ($event->getAction() != Am_Event_UserForm::INIT) { return; } $fieldSet = $event->getForm()->addFieldset('affiliate')->setLabel(___('Affiliate Program')); $user = $event->getUser(); $affHtml = ""; if (!empty($user->aff_id)) { try { $aff = $this->getDi()->userTable->load($user->aff_id); $url = new Am_View_Helper_UserUrl(); $affHtml = sprintf('<a target="_blank" href="%s">"%s %s" <%s></a>', Am_Controller::escape($url->userUrl($user->aff_id)), $aff->name_f, $aff->name_l, $aff->email); $fieldSet->addElement('static', '_aff')->setLabel(___('Referred Affiliate'))->setContent($affHtml); } catch (Am_Exception $e) { // ignore if affiliate was deleted } } else { $fieldSet->addElement('text', '_aff', array('placeholder' => 'Type username or e-mail'))->setLabel(___('Referred Affiliate')); $fieldSet->addScript()->setScript(<<<CUT \$("input#_aff-0").autocomplete({ minLength: 2, source: window.rootUrl + "/admin-users/autocomplete" }); CUT ); } $fieldSet->addElement('advradio', 'is_affiliate')->setLabel(array(___('Is Affiliate?'), ___('customer / affiliate status')))->loadOptions(array('0' => ___('No'), '1' => ___('Both Affiliate and member'), '2' => ___('Only Affiliate %s(rarely used)%s', '<i>', '</i>'))); $this->addPayoutInputs($fieldSet); }
public function createLeadsGrid() { $ds = new Am_Query($this->getDi()->affLeadTable); $ds->leftJoin('?_user', 'a', 't.aff_id=a.user_id'); $ds->addField('CONCAT(a.login, \' (\', a.name_f, \' \', a.name_l,\') [#\', a.user_id, \']\')', 'aff_name'); $ds->leftJoin('?_aff_banner', 'b', 't.banner_id=b.banner_id'); $ds->addField('b.title', 'banner'); $ds->leftJoin('?_user', 'u', 'u.user_id=t.user_id'); $ds->addField('CONCAT(u.login, \' (\',u.name_f, \' \',u.name_l,\') [#\', u.user_id, \']\')', 'user_name')->addField('u.email', 'user_email'); $grid = new Am_Grid_ReadOnly('_affclicks', ___('Leads'), $ds, $this->_request, $this->view); $grid->setPermissionId(Bootstrap_Aff::ADMIN_PERM_ID); $userUrl = new Am_View_Helper_UserUrl(); $grid->addField('aff_name', ___('Affiliate'))->addDecorator(new Am_Grid_Field_Decorator_Link($userUrl->userUrl('{aff_id}'), '_top')); $grid->addField('user_name', ___('User'))->addDecorator(new Am_Grid_Field_Decorator_Link($userUrl->userUrl('{user_id}'), '_top')); $grid->addField('banner', ___('Banner'))->setRenderFunction(array($this, 'renderBanner')); $grid->addField('time', ___('Date/Time'))->setFormatFunction('amDateTime'); $grid->addField('first_visited', ___('First visited'))->setFormatFunction('amDateTime'); $grid->setFilter(new Am_Grid_Filter_Leads()); return $grid; }
public function createLeadsGrid() { $ds = new Am_Query($this->getDi()->affLeadTable); $ds->leftJoin('?_user', 'a', 't.aff_id=a.user_id'); $ds->addField('CONCAT(a.name_f, \' \', a.name_l)', 'aff_name'); $ds->leftJoin('?_aff_banner', 'b', 't.banner_id=b.banner_id'); $ds->addField('b.title', 'banner'); $ds->leftJoin('?_user', 'u', 'u.user_id=t.user_id'); $ds->addField('CONCAT(u.name_f, \' \',u.name_l)', 'user_name')->addField('u.email', 'user_email'); $grid = new Am_Grid_ReadOnly('_affclicks', ___("Leads"), $ds, $this->_request, $this->view); $grid->setPermissionId('affiliates'); $userUrl = new Am_View_Helper_UserUrl(); $grid->addField('aff_name', ___('Affiliate'))->addDecorator(new Am_Grid_Field_Decorator_Link($userUrl->userUrl('{aff_id}'), '_blank')); $grid->addField('user_name', ___('User'))->addDecorator(new Am_Grid_Field_Decorator_Link($userUrl->userUrl('{user_id}'), '_blank')); $grid->addField('banner', ___('Banner')); $grid->addField('time', ___('Time'))->setFormatFunction('amDateTime'); $grid->addField('first_visited', ___('First visited'))->setFormatFunction('amDateTime'); return $grid; }