First start at retiring Affiliate in favour of RTM
This commit is contained in:
parent
9d4b2f50ff
commit
43dfd88bce
@ -271,12 +271,12 @@ class Auth_OSB extends Auth_ORM {
|
||||
/**
|
||||
* Determine if a user is authorised to view an account
|
||||
*
|
||||
* @param integer Account ID
|
||||
* @param Model_Account Account Ojbect to validate if the current user has access
|
||||
*
|
||||
* @return boolean TRUE if authorised, FALSE if not.
|
||||
*/
|
||||
public function authorised($aid,$afid=NULL) {
|
||||
return (($ao = $this->get_user()) AND $ao->loaded() AND ($aid == $ao->id OR $ao->isAdmin() OR (! is_null($afid) AND $afid == $ao->affiliate->id))) ? TRUE : FALSE;
|
||||
public function authorised(Model_Account $ao) {
|
||||
return (($uo = $this->get_user()) AND $uo->loaded() AND ($uo == $ao OR in_array($ao->id,$uo->RTM->customers($uo->RTM))));
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
@ -8,8 +8,26 @@
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
* @also [logout]
|
||||
*/
|
||||
class Controller_Account extends Controller_TemplateDefault {
|
||||
public function action_group() {
|
||||
$output = '';
|
||||
|
||||
$cg = $this->ao->group->find_all();
|
||||
|
||||
foreach ($cg as $go) {
|
||||
$output .= sprintf('Group %s: %s<br/>',$go->id,$go->display('name'));
|
||||
|
||||
foreach ($go->list_childgrps(TRUE) as $cgo)
|
||||
$output .= sprintf('- %s: %s (%s)<br/>',$cgo->id,$cgo->display('name'),$cgo->parent_id);
|
||||
|
||||
$output .= sprintf('END Group %s<br/><br/>',$go->id);
|
||||
}
|
||||
|
||||
Block::add(array(
|
||||
'title'=>'Group Structure',
|
||||
'body'=>$output,
|
||||
));
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
@ -9,69 +9,9 @@
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Admin_Account extends Controller_TemplateDefault_Admin {
|
||||
class Controller_Admin_Account extends Controller_Account {
|
||||
protected $secure_actions = array(
|
||||
'ajaxlist'=>FALSE, // @todo To Change
|
||||
'list'=>TRUE,
|
||||
'listlog'=>TRUE,
|
||||
'group'=>FALSE, // @todo Testing
|
||||
);
|
||||
|
||||
public function action_ajaxlist() {
|
||||
$return = array();
|
||||
|
||||
if (isset($_REQUEST['term']) AND trim($_REQUEST['term']))
|
||||
$return += ORM::factory('Account')->list_autocomplete($_REQUEST['term']);
|
||||
|
||||
$this->auto_render = FALSE;
|
||||
$this->response->headers('Content-Type','application/json');
|
||||
$this->response->body(json_encode(array_values($return)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a list of account logins
|
||||
*/
|
||||
public function action_listlog() {
|
||||
Block::add(array(
|
||||
'title'=>_('Account Login Log'),
|
||||
'body'=>Table::display(
|
||||
ORM::factory('Account_Log')->order_by('id','DESC')->find_all(),
|
||||
25,
|
||||
array(
|
||||
'id'=>array('label'=>'ID'),
|
||||
'date_orig'=>array('label'=>'Date'),
|
||||
'account->name()'=>array('label'=>'Account'),
|
||||
'ip'=>array('label'=>'IP Address'),
|
||||
'details'=>array('label'=>'Details'),
|
||||
),
|
||||
array(
|
||||
'page'=>TRUE,
|
||||
)),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a list of accounts
|
||||
*/
|
||||
public function action_list() {
|
||||
Block::add(array(
|
||||
'title'=>_('Customer List'),
|
||||
'body'=>Table::display(
|
||||
ORM::factory('Account')->list_active(),
|
||||
25,
|
||||
array(
|
||||
'id'=>array('label'=>'ID','url'=>URL::link('user','account/view/')),
|
||||
'accnum()'=>array('label'=>'Num'),
|
||||
'name(TRUE)'=>array('label'=>'Account'),
|
||||
'email'=>array('label'=>'Email'),
|
||||
'invoices_due_total(NULL,TRUE)'=>array('label'=>'Invoices','class'=>'right'),
|
||||
'count_services(TRUE,NULL)'=>array('label'=>'Services','class'=>'right'),
|
||||
),
|
||||
array(
|
||||
'page'=>TRUE,
|
||||
'type'=>'select',
|
||||
'form'=>URL::link('user','account/view'),
|
||||
)),
|
||||
));
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
@ -9,7 +9,7 @@
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Admin_Module extends Controller_TemplateDefault_Admin {
|
||||
class Controller_Admin_Module extends Controller_Module {
|
||||
protected $secure_actions = array(
|
||||
'add'=>TRUE,
|
||||
'edit'=>TRUE,
|
||||
|
@ -9,7 +9,7 @@
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Admin_Setup extends Controller_TemplateDefault_Admin {
|
||||
class Controller_Admin_Setup extends Controller_TemplateDefault {
|
||||
protected $secure_actions = array(
|
||||
'edit'=>TRUE,
|
||||
);
|
||||
|
@ -9,13 +9,13 @@
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Admin_Welcome extends Controller_TemplateDefault_Admin {
|
||||
class Controller_Admin_Welcome extends Controller_Welcome {
|
||||
protected $auth_required = TRUE;
|
||||
public $secure_actions = array(
|
||||
'index'=>TRUE,
|
||||
);
|
||||
|
||||
public function action_index() {
|
||||
$ao = ORM::factory('Account',Auth::instance()->get_user()->id);
|
||||
$t = time();
|
||||
|
||||
// Show outstanding invoices
|
||||
@ -99,11 +99,31 @@ class Controller_Admin_Welcome extends Controller_TemplateDefault_Admin {
|
||||
));
|
||||
|
||||
Block::add(array(
|
||||
'title'=>sprintf('%s: %s %s',$ao->accnum(),$ao->first_name,$ao->last_name),
|
||||
'title'=>sprintf('%s: %s %s',$this->ao->accnum(),$this->ao->first_name,$this->ao->last_name),
|
||||
'subtitle'=>_('Administrator Overview'),
|
||||
'body'=>(string)Block_Sub::factory(),
|
||||
));
|
||||
|
||||
// We are a site administrator
|
||||
if ($this->ao->rtm_id == NULL) {
|
||||
$rtmo = ORM::factory('RTM',array('account_id','=',$this->ao->id))->find();
|
||||
|
||||
// Quick validation, if we are an admin, we should have an entry in the RTM table.
|
||||
if (! $rtmo->loaded())
|
||||
throw new Kohana_Exception('User :aid not set up properly',array(':aid'=>$this->ao->id));
|
||||
|
||||
$output = View::factory('welcome/admin')
|
||||
->set('o',$rtmo);
|
||||
|
||||
} else {
|
||||
$rtmo = ORM::factory('RTM',$this->ao->rmt_id);
|
||||
}
|
||||
|
||||
if ($output)
|
||||
Block::add(array(
|
||||
'title'=>sprintf('Reseller %s',$this->ao->display('company')),
|
||||
'body'=>$output,
|
||||
));
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
@ -1,42 +0,0 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class provides Affiliate Account functions
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers/Affiliate
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Affiliate_Account extends Controller_TemplateDefault_Affiliate {
|
||||
protected $secure_actions = array(
|
||||
'list'=>TRUE,
|
||||
);
|
||||
|
||||
/**
|
||||
* Show a list of accounts
|
||||
*/
|
||||
public function action_list() {
|
||||
Block::add(array(
|
||||
'title'=>_('Customer List'),
|
||||
'body'=>Table::display(
|
||||
$this->filter(ORM::factory('Account')->list_active(),$this->ao->affiliate->id,'sortkey(TRUE)'),
|
||||
25,
|
||||
array(
|
||||
'id'=>array('label'=>'ID','url'=>URL::link('user','account/view/')),
|
||||
'accnum()'=>array('label'=>'Num'),
|
||||
'name(TRUE)'=>array('label'=>'Account'),
|
||||
'email'=>array('label'=>'Email'),
|
||||
'invoices_due_total(NULL,TRUE)'=>array('label'=>'Invoices','class'=>'right'),
|
||||
'count_services(TRUE,'.$this->ao->affiliate->id.')'=>array('label'=>'Services','class'=>'right'),
|
||||
),
|
||||
array(
|
||||
'page'=>TRUE,
|
||||
'type'=>'select',
|
||||
'form'=>URL::link('user','account/view'),
|
||||
)),
|
||||
));
|
||||
}
|
||||
}
|
||||
?>
|
81
application/classes/Controller/Reseller/Account.php
Normal file
81
application/classes/Controller/Reseller/Account.php
Normal file
@ -0,0 +1,81 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class provides Reseller Account management
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers/Reseller
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Reseller_Account extends Controller_Account {
|
||||
protected $secure_actions = array(
|
||||
'ajaxlist'=>TRUE,
|
||||
'list'=>TRUE,
|
||||
'listlog'=>TRUE,
|
||||
);
|
||||
|
||||
/**
|
||||
* Used by AJAX calls to find accounts
|
||||
* @note list_autocomplete() will limit to authorised accounts
|
||||
*/
|
||||
public function action_ajaxlist() {
|
||||
$return = array();
|
||||
|
||||
if (isset($_REQUEST['term']) AND trim($_REQUEST['term']))
|
||||
$return += ORM::factory('Account')->list_autocomplete($_REQUEST['term']);
|
||||
|
||||
$this->auto_render = FALSE;
|
||||
$this->response->headers('Content-Type','application/json');
|
||||
$this->response->body(json_encode(array_values($return)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a list of accounts
|
||||
*/
|
||||
public function action_list() {
|
||||
Block::add(array(
|
||||
'title'=>_('Customer List'),
|
||||
'body'=>Table::display(
|
||||
$this->filter(ORM::factory('Account')->list_active(),$this->ao->RTM->customers($this->ao->RTM),'sortkey(TRUE)','id'),
|
||||
25,
|
||||
array(
|
||||
'id'=>array('label'=>'ID','url'=>URL::link('reseller','invoice/list/')),
|
||||
'accnum()'=>array('label'=>'Num'),
|
||||
'name(TRUE)'=>array('label'=>'Account'),
|
||||
'email'=>array('label'=>'Email'),
|
||||
'invoices_due_total(NULL,TRUE)'=>array('label'=>'Invoices','class'=>'right'),
|
||||
'services_count(TRUE)'=>array('label'=>'Services','class'=>'right'),
|
||||
),
|
||||
array(
|
||||
'page'=>TRUE,
|
||||
'type'=>'select',
|
||||
'form'=>URL::link('reseller','invoice/list'),
|
||||
)),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a list of account logins
|
||||
*/
|
||||
public function action_listlog() {
|
||||
Block::add(array(
|
||||
'title'=>_('Account Login Log'),
|
||||
'body'=>Table::display(
|
||||
$this->filter(ORM::factory('Account_Log')->find_all(),$this->ao->RTM->customers($this->ao->RTM),NULL,'account_id'),
|
||||
25,
|
||||
array(
|
||||
'id'=>array('label'=>'ID'),
|
||||
'date_orig'=>array('label'=>'Date'),
|
||||
'account->name()'=>array('label'=>'Account'),
|
||||
'ip'=>array('label'=>'IP Address'),
|
||||
'details'=>array('label'=>'Details'),
|
||||
),
|
||||
array(
|
||||
'page'=>TRUE,
|
||||
)),
|
||||
));
|
||||
}
|
||||
}
|
||||
?>
|
25
application/classes/Controller/Reseller/Welcome.php
Normal file
25
application/classes/Controller/Reseller/Welcome.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* lnApp Main home page
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers/Reseller
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Reseller_Welcome extends Controller_Welcome {
|
||||
protected $auth_required = TRUE;
|
||||
protected $secure_actions = array(
|
||||
'index'=>TRUE,
|
||||
);
|
||||
|
||||
public function action_index() {
|
||||
Block::add(array(
|
||||
'title'=>sprintf('%s: %s',$this->ao->accnum(),$this->ao->name(TRUE)),
|
||||
'body'=>View::factory('welcome/reseller'),
|
||||
));
|
||||
}
|
||||
}
|
||||
?>
|
@ -10,9 +10,14 @@
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_TemplateDefault extends lnApp_Controller_TemplateDefault {
|
||||
protected $auth_required = TRUE;
|
||||
|
||||
// Our acccount object
|
||||
protected $ao;
|
||||
|
||||
public function __construct(Request $request, Response $response) {
|
||||
if (Config::theme())
|
||||
$this->template = Config::theme().'/page';
|
||||
$this->template = 'theme/'.Config::theme().'/page';
|
||||
|
||||
return parent::__construct($request,$response);
|
||||
}
|
||||
@ -38,11 +43,91 @@ class Controller_TemplateDefault extends lnApp_Controller_TemplateDefault {
|
||||
}
|
||||
|
||||
protected function _right() {
|
||||
return ($this->template->right) ? $this->template->right : $this->_cart();
|
||||
return ($this->template->right) ? $this->template->right : '';
|
||||
}
|
||||
|
||||
private function _cart() {
|
||||
return (! Config::module_exist('cart') OR ! class_exists('Cart') OR ! count(Cart::instance()->contents()) OR strtolower(Request::current()->controller()) == 'cart') ? '' : Cart::instance()->cart_block();
|
||||
public function before() {
|
||||
// If our action doesnt exist, no point processing any further.
|
||||
if (! method_exists($this,'action_'.Request::current()->action()))
|
||||
return;
|
||||
|
||||
if ($this->auth_required) {
|
||||
if (! count($this->secure_actions) OR (! isset($this->secure_actions[Request::current()->action()])))
|
||||
throw new Kohana_Exception('Class has no security defined :class, or no security configured for :method',array(':class'=>get_class($this),':method'=>Request::current()->action()));
|
||||
|
||||
$this->ao = Auth::instance()->get_user();
|
||||
if (! is_null($this->ao) AND (is_string($this->ao) OR ! $this->ao->loaded()))
|
||||
throw new Kohana_Exception('Account doesnt exist :account ?',array(':account'=>(is_string($this->ao) OR is_null($this->ao)) ? $this->ao : Auth::instance()->get_user()->id));
|
||||
}
|
||||
|
||||
parent::before();
|
||||
}
|
||||
|
||||
public function after() {
|
||||
$dc = Kohana::$config->load('config','user_default_method');
|
||||
$m = sprintf('%s/%s',Request::current()->directory(),Request::current()->controller());
|
||||
|
||||
BreadCrumb::URL(Request::current()->directory(),sprintf('%s/%s',Request::current()->directory(),$dc),FALSE);
|
||||
BreadCrumb::URL($m,method_exists($this,'action_menu') ? $m.'/menu' : sprintf('%s/%s',Request::current()->directory(),$dc),FALSE);
|
||||
|
||||
parent::after();
|
||||
}
|
||||
|
||||
/**
|
||||
* This will filter a search query to only return those accounts for a reseller
|
||||
*/
|
||||
protected function filter($o,$af,$sort=NULL,$afid=NULL) {
|
||||
$result = array();
|
||||
|
||||
foreach ($o as $x) {
|
||||
if (! is_null($afid) AND isset($x->$afid)) {
|
||||
if ((is_array($af) AND in_array($x->$afid,$af)) OR ($x->$afid == $af))
|
||||
array_push($result,$x);
|
||||
|
||||
} elseif (method_exists($x,'list_reseller')) {
|
||||
if (in_array($af,$x->list_reseller()))
|
||||
array_push($result,$x);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if ($sort)
|
||||
Sort::MAsort($result,$sort);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function setup(array $config_items=array()) {
|
||||
$module = Request::current()->controller();
|
||||
|
||||
if ($_POST AND isset($_POST['module_config'][$module]))
|
||||
Config::instance()->module_config($module,$_POST['module_config'][$module])->save();
|
||||
|
||||
if ($config_items) {
|
||||
$output = '';
|
||||
$mc = Config::instance()->module_config($module);
|
||||
|
||||
$output .= Form::open();
|
||||
$output .= View::factory('setup/admin/module/head');
|
||||
|
||||
foreach ($config_items as $k=>$v)
|
||||
$output .= View::factory('setup/admin/module/body')
|
||||
->set('module',$module)
|
||||
->set('mc',$mc)
|
||||
->set('key',$k)
|
||||
->set('info',$v)
|
||||
->set('val',isset($mc[$k]) ? $mc[$k] : '');
|
||||
|
||||
$output .= View::factory('setup/admin/module/foot');
|
||||
|
||||
$output .= Form::submit('submit',_('Submit'),array('class'=>'form_button'));
|
||||
$output .= Form::close();
|
||||
|
||||
Block::add(array(
|
||||
'title'=>sprintf('%s: %s',strtoupper($module),_('Configuration')),
|
||||
'body'=>$output,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
@ -10,37 +10,14 @@
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_TemplateDefault_Admin extends Controller_TemplateDefault_User {
|
||||
protected function setup(array $config_items=array()) {
|
||||
$module = Request::current()->controller();
|
||||
public function after() {
|
||||
SystemMessage::add(array(
|
||||
'title'=>'Retire this class extension',
|
||||
'type'=>'info',
|
||||
'body'=>__METHOD__,
|
||||
));
|
||||
|
||||
if ($_POST AND isset($_POST['module_config'][$module]))
|
||||
Config::instance()->module_config($module,$_POST['module_config'][$module])->save();
|
||||
|
||||
if ($config_items) {
|
||||
$output = '';
|
||||
$mc = Config::instance()->module_config($module);
|
||||
|
||||
$output .= Form::open();
|
||||
$output .= View::factory('setup/admin/module/head');
|
||||
|
||||
foreach ($config_items as $k=>$v)
|
||||
$output .= View::factory('setup/admin/module/body')
|
||||
->set('module',$module)
|
||||
->set('mc',$mc)
|
||||
->set('key',$k)
|
||||
->set('info',$v)
|
||||
->set('val',isset($mc[$k]) ? $mc[$k] : '');
|
||||
|
||||
$output .= View::factory('setup/admin/module/foot');
|
||||
|
||||
$output .= Form::submit('submit',_('Submit'),array('class'=>'form_button'));
|
||||
$output .= Form::close();
|
||||
|
||||
Block::add(array(
|
||||
'title'=>sprintf('%s: %s',strtoupper($module),_('Configuration')),
|
||||
'body'=>$output,
|
||||
));
|
||||
}
|
||||
return parent::after();
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
@ -10,28 +10,14 @@
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_TemplateDefault_Affiliate extends Controller_TemplateDefault_User {
|
||||
/**
|
||||
* This will filter a search query to only return the affiliates
|
||||
*/
|
||||
protected function filter($o,$af,$sort='account->name()',$afid='affiliate_id') {
|
||||
$result = array();
|
||||
public function after() {
|
||||
SystemMessage::add(array(
|
||||
'title'=>'Retire this class extension',
|
||||
'type'=>'info',
|
||||
'body'=>__METHOD__,
|
||||
));
|
||||
|
||||
foreach ($o as $x) {
|
||||
if (isset($x->$afid)) {
|
||||
if ($x->$afid == $af)
|
||||
array_push($result,$x);
|
||||
|
||||
} elseif (method_exists($x,'list_affiliates')) {
|
||||
if (in_array($af,$x->list_affiliates()))
|
||||
array_push($result,$x);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if ($sort)
|
||||
Sort::MAsort($result,$sort);
|
||||
|
||||
return $result;
|
||||
return parent::after();
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
@ -10,34 +10,14 @@
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_TemplateDefault_User extends Controller_TemplateDefault {
|
||||
protected $auth_required = TRUE;
|
||||
|
||||
// Our acccount object
|
||||
protected $ao;
|
||||
|
||||
public function before() {
|
||||
// If our action doesnt exist, no point processing any further.
|
||||
if (! method_exists($this,'action_'.Request::current()->action()))
|
||||
return;
|
||||
|
||||
if (! count($this->secure_actions) OR (! isset($this->secure_actions[Request::current()->action()])))
|
||||
throw new Kohana_Exception('Class has no security defined :class, or no security configured for :method',array(':class'=>get_class($this),':method'=>Request::current()->action()));
|
||||
|
||||
parent::before();
|
||||
|
||||
$this->ao = Auth::instance()->get_user();
|
||||
if (is_string($this->ao) OR ! $this->ao->loaded())
|
||||
throw new Kohana_Exception('Account doesnt exist :account ?',array(':account'=>is_string($this->ao) ? $this->ao : Auth::instance()->get_user()->id));
|
||||
}
|
||||
|
||||
public function after() {
|
||||
$dc = 'welcome/index';
|
||||
$m = sprintf('%s/%s',Request::current()->directory(),Request::current()->controller());
|
||||
SystemMessage::add(array(
|
||||
'title'=>'Retire this class extension',
|
||||
'type'=>'info',
|
||||
'body'=>__METHOD__,
|
||||
));
|
||||
|
||||
BreadCrumb::URL(Request::current()->directory(),sprintf('%s/%s',Request::current()->directory(),$dc),FALSE);
|
||||
BreadCrumb::URL($m,method_exists($this,'action_menu') ? $m.'/menu' : sprintf('%s/%s',Request::current()->directory(),$dc),FALSE);
|
||||
|
||||
parent::after();
|
||||
return parent::after();
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
@ -9,12 +9,52 @@
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_User_Account extends Controller_TemplateDefault_User {
|
||||
class Controller_User_Account extends Controller_Account {
|
||||
protected $secure_actions = array(
|
||||
'edit'=>TRUE,
|
||||
'resetpassword'=>TRUE,
|
||||
);
|
||||
|
||||
/**
|
||||
* Enable User to Edit their Account Details
|
||||
*/
|
||||
public function action_edit() {
|
||||
// Store our new values
|
||||
$this->ao->values($_POST);
|
||||
|
||||
// Run validation and save
|
||||
if ($this->ao->changed())
|
||||
if ($this->ao->check()) {
|
||||
SystemMessage::add(array(
|
||||
'title'=>_('Record updated'),
|
||||
'type'=>'info',
|
||||
'body'=>_('Your account record has been updated.')
|
||||
));
|
||||
|
||||
$this->ao->save();
|
||||
|
||||
} else {
|
||||
$output = '';
|
||||
foreach ($this->ao->validation()->errors('forms/login') as $field => $error)
|
||||
$output .= sprintf('<li><b>%s</b> %s</li>',$field,$error);
|
||||
|
||||
if ($output)
|
||||
$output = sprintf('<ul>%s</ul>',$output);
|
||||
|
||||
SystemMessage::add(array(
|
||||
'title'=>_('Record NOT updated'),
|
||||
'type'=>'error',
|
||||
'body'=>_('Your updates didnt pass validation.').'<br/>'.$output,
|
||||
));
|
||||
}
|
||||
|
||||
Block::add(array(
|
||||
'title'=>sprintf('%s: %s - %s',_('Account Edit'),$this->ao->accnum(),$this->ao->name(TRUE)),
|
||||
'body'=>View::factory($this->viewpath())
|
||||
->set('record',$this->ao),
|
||||
));
|
||||
}
|
||||
|
||||
public function action_resetpassword() {
|
||||
// @todo Fix this next logic, since matches_ifset is not being called when the value is on the form, but empty
|
||||
if (empty($_POST['password_confirm']))
|
||||
@ -60,45 +100,5 @@ class Controller_User_Account extends Controller_TemplateDefault_User {
|
||||
->set('record',$this->ao),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a product
|
||||
*/
|
||||
public function action_edit() {
|
||||
// Store our new values
|
||||
$this->ao->values($_POST);
|
||||
|
||||
// Run validation and save
|
||||
if ($this->ao->changed())
|
||||
if ($this->ao->check()) {
|
||||
SystemMessage::add(array(
|
||||
'title'=>_('Record updated'),
|
||||
'type'=>'info',
|
||||
'body'=>_('Your account record has been updated.')
|
||||
));
|
||||
|
||||
$this->ao->save();
|
||||
|
||||
} else {
|
||||
$output = '';
|
||||
foreach ($this->ao->validation()->errors('forms/login') as $field => $error)
|
||||
$output .= sprintf('<li><b>%s</b> %s</li>',$field,$error);
|
||||
|
||||
if ($output)
|
||||
$output = sprintf('<ul>%s</ul>',$output);
|
||||
|
||||
SystemMessage::add(array(
|
||||
'title'=>_('Record NOT updated'),
|
||||
'type'=>'error',
|
||||
'body'=>_('Your updates didnt pass validation.').'<br/>'.$output,
|
||||
));
|
||||
}
|
||||
|
||||
Block::add(array(
|
||||
'title'=>sprintf('%s: %s - %s',_('Account Edit'),$this->ao->accnum(),$this->ao->name(TRUE)),
|
||||
'body'=>View::factory($this->viewpath())
|
||||
->set('record',$this->ao),
|
||||
));
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
@ -9,17 +9,16 @@
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_User_Welcome extends Controller_TemplateDefault_User {
|
||||
class Controller_User_Welcome extends Controller_Welcome {
|
||||
protected $auth_required = TRUE;
|
||||
protected $secure_actions = array(
|
||||
'index'=>FALSE,
|
||||
);
|
||||
'index'=>TRUE,
|
||||
);
|
||||
|
||||
public function action_index() {
|
||||
$ao = ORM::factory('Account',Auth::instance()->get_user()->id);
|
||||
|
||||
Block::add(array(
|
||||
'title'=>sprintf('%s: %s %s',$ao->accnum(),$ao->first_name,$ao->last_name),
|
||||
'body'=>'Please select from the tree on the left',
|
||||
'title'=>sprintf('%s: %s',$this->ao->accnum(),$this->ao->name(TRUE)),
|
||||
'body'=>View::factory('welcome/user'),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This Model manages both the accounts that users use to login to the system, as well as the account where services are owned.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Models
|
||||
@ -18,9 +19,12 @@ class Model_Account extends Model_Auth_UserDefault {
|
||||
'payment'=>array('far_key'=>'id'),
|
||||
'service' => array('far_key'=>'id'),
|
||||
);
|
||||
|
||||
protected $_has_one = array(
|
||||
'affiliate' => array('far_key'=>'id'),
|
||||
'language'=>array('foreign_key'=>'id','far_key'=>'language_id'),
|
||||
'country'=>array('foreign_key'=>'id'),
|
||||
'currency'=>array('foreign_key'=>'id'),
|
||||
'language'=>array('foreign_key'=>'id'),
|
||||
'RTM'=>array('far_key'=>'id'),
|
||||
);
|
||||
|
||||
protected $_display_filters = array(
|
||||
@ -36,59 +40,26 @@ class Model_Account extends Model_Auth_UserDefault {
|
||||
);
|
||||
|
||||
/**
|
||||
* Return an account name
|
||||
* Our account number format
|
||||
*/
|
||||
public function name($withcompany=FALSE) {
|
||||
if ($withcompany)
|
||||
return sprintf('%s %s%s',$this->first_name,$this->last_name,$this->company ? sprintf(' (%s)',$this->company) : '');
|
||||
else
|
||||
return sprintf('%s %s',$this->first_name,$this->last_name);
|
||||
}
|
||||
|
||||
public function accnum() {
|
||||
return sprintf('%s-%04s',Company::instance()->site(TRUE),$this->id);
|
||||
}
|
||||
|
||||
public function sortkey($withcompany=FALSE) {
|
||||
$sk = '';
|
||||
|
||||
if ($withcompany AND $this->company)
|
||||
$sk .= $this->company.' ';
|
||||
|
||||
return $sk.sprintf('%s %s',$this->last_name,$this->first_name);
|
||||
}
|
||||
|
||||
public function title($name) {
|
||||
return StaticList_Title::form($name,$this->title);
|
||||
}
|
||||
|
||||
public function currency($name) {
|
||||
return StaticList_Module::form($name,'currency',$this->currency_id,'id','name',array('status'=>'=:1'),FALSE,array('class'=>'form_button'));
|
||||
}
|
||||
|
||||
public function country($name) {
|
||||
return StaticList_Module::form($name,'country',$this->country_id,'id','name',array('status'=>'=:1'),FALSE,array('class'=>'form_button'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the groups that an account belongs to
|
||||
*/
|
||||
public function groups() {
|
||||
return $this->group->find_all();
|
||||
}
|
||||
|
||||
public function isAdmin() {
|
||||
// @todo Define admins in the config file or DB
|
||||
$admins = array(ORM::factory('Group',array('name'=>'Root')));
|
||||
|
||||
return $this->has('group',$admins);
|
||||
return $this->group->where_active()->find_all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all invoices for this account
|
||||
*/
|
||||
public function invoices() {
|
||||
return $this->invoice->distinct('id')->find_all();
|
||||
public function invoices($processed=FALSE) {
|
||||
$o = $this->invoice;
|
||||
|
||||
return $processed ? $o->find_all() : $o->where_unprocessed()->find_all();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -129,22 +100,39 @@ class Model_Account extends Model_Auth_UserDefault {
|
||||
return $alo->saved();
|
||||
}
|
||||
|
||||
public function list_active() {
|
||||
return $this->_where_active()->order_by('company,last_name,first_name')->find_all();
|
||||
/**
|
||||
* Return an account name
|
||||
*/
|
||||
public function name($withcompany=FALSE) {
|
||||
if ($withcompany)
|
||||
return sprintf('%s %s%s',$this->first_name,$this->last_name,$this->company ? sprintf(' (%s)',$this->company) : '');
|
||||
else
|
||||
return sprintf('%s %s',$this->first_name,$this->last_name);
|
||||
}
|
||||
|
||||
public function list_affiliates() {
|
||||
$return = array();
|
||||
/**
|
||||
* List all the services for this account
|
||||
*/
|
||||
public function services($active=TRUE) {
|
||||
$o = $this->service;
|
||||
|
||||
foreach ($this->list_services() as $so)
|
||||
if (! isset($return[$so->affiliate_id]))
|
||||
$return[$so->affiliate_id] = $so->affiliate;
|
||||
|
||||
return $return;
|
||||
return $active ? $o->where_active()->find_all() : $o->find_all();
|
||||
}
|
||||
|
||||
public function count_services($active=TRUE,$afid=NULL) {
|
||||
return $this->list_services($active,$afid)->count();
|
||||
public function services_count($active=TRUE,$afid=NULL) {
|
||||
return $this->services($active)->count();
|
||||
}
|
||||
|
||||
/**
|
||||
* The key we use to sort entries of this model type
|
||||
*/
|
||||
public function sortkey($withcompany=FALSE) {
|
||||
$sk = '';
|
||||
|
||||
if ($withcompany AND $this->company)
|
||||
$sk .= $this->company.' ';
|
||||
|
||||
return $sk.sprintf('%s %s',$this->last_name,$this->first_name);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -152,6 +140,7 @@ class Model_Account extends Model_Auth_UserDefault {
|
||||
*/
|
||||
public function list_autocomplete($term,$index='id',array $limit=array()) {
|
||||
$return = array();
|
||||
$ao = Auth::instance()->get_user();
|
||||
|
||||
$this->clear();
|
||||
$this->where_active();
|
||||
@ -190,6 +179,9 @@ class Model_Account extends Model_Auth_UserDefault {
|
||||
$this->and_where($k,$s,$v);
|
||||
}
|
||||
|
||||
// Restrict results to authorised accounts
|
||||
$this->and_where('id','IN',$ao->RTM->customers($ao->RTM));
|
||||
|
||||
foreach ($this->find_all() as $o)
|
||||
$return[$o->$index] = array(
|
||||
'value'=>$o->$index,
|
||||
@ -198,14 +190,5 @@ class Model_Account extends Model_Auth_UserDefault {
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
public function list_services($active=TRUE,$afid=NULL) {
|
||||
$svs = $this->service->where_active();
|
||||
|
||||
if ($afid)
|
||||
$svs->where('affiliate_id','=',$afid);
|
||||
|
||||
return $svs->find_all();
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
@ -14,6 +14,10 @@ class Model_Account_Log extends ORM_OSB {
|
||||
'account'=>array(),
|
||||
);
|
||||
|
||||
protected $_sorting = array(
|
||||
'id'=>'DESC',
|
||||
);
|
||||
|
||||
protected $_display_filters = array(
|
||||
'date_orig'=>array(
|
||||
array('Config::datetime',array(':value')),
|
||||
|
@ -18,7 +18,7 @@ class Model_Module extends ORM_OSB {
|
||||
'module_method'=>array('far_key'=>'id'),
|
||||
);
|
||||
protected $_has_one = array(
|
||||
'record_id'=>array('far_key'=>'id'),
|
||||
'record_id'=>array('model'=>'Record_ID','far_key'=>'id'),
|
||||
);
|
||||
|
||||
protected $_sorting = array(
|
||||
|
42
application/classes/Model/RTM.php
Normal file
42
application/classes/Model/RTM.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* OSB Route to Market
|
||||
*
|
||||
* @package OSB
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_RTM extends ORM_OSB {
|
||||
protected $_belongs_to = array(
|
||||
'account' => array(),
|
||||
);
|
||||
|
||||
protected $_has_many = array(
|
||||
'customer' => array('model'=>'account','far_key'=>'id','foreign_key'=>'rtm_id'),
|
||||
'agent' => array('model'=>'rtm','far_key'=>'id','foreign_key'=>'parent_id'),
|
||||
);
|
||||
|
||||
public function customers(Model_RTM $rtmo) {
|
||||
$return = array();
|
||||
|
||||
foreach ($rtmo->agents_direct() as $artmo)
|
||||
$return = $return+$rtmo->customers($artmo);
|
||||
|
||||
foreach ($rtmo->customers_direct() as $ao)
|
||||
array_push($return,$ao);
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
public function agents_direct() {
|
||||
return $this->agent->find_all();
|
||||
}
|
||||
|
||||
public function customers_direct() {
|
||||
return $this->customer->where_active()->find_all();
|
||||
}
|
||||
}
|
||||
?>
|
@ -7,8 +7,9 @@
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
* @todo Rename to Record/ID.php
|
||||
*/
|
||||
class Model_Record_Id extends ORM_OSB {
|
||||
class Model_Record_ID extends ORM_OSB {
|
||||
protected $_primary_key = 'module_id';
|
||||
|
||||
// This module doesnt keep track of column updates automatically
|
@ -3,14 +3,14 @@
|
||||
/**
|
||||
* This class overrides Kohana's ORM
|
||||
*
|
||||
* This file contains enhancements for Kohana, that should be considered upstream and maybe havent been yet.
|
||||
* It also contains some functionality for OSB, which cannot be covered in ORM_OSB.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Modifications
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*
|
||||
* This file contains enhancements for Kohana, that should be considered upstream and maybe havent been yet.
|
||||
* It also contains some functionality for OSB, which cannot be covered in ORM_OSB.
|
||||
*/
|
||||
abstract class ORM extends Kohana_ORM {
|
||||
protected $_table_names_plural = FALSE;
|
||||
@ -104,6 +104,13 @@ abstract class ORM extends Kohana_ORM {
|
||||
return parent::_build($type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function help to find records that are active
|
||||
*/
|
||||
public function list_active() {
|
||||
return $this->_where_active()->find_all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Function help to find records that are active
|
||||
*/
|
||||
|
@ -219,13 +219,6 @@ abstract class ORM_OSB extends ORM {
|
||||
return parent::save($validation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function help to find records that are active
|
||||
*/
|
||||
public function list_active() {
|
||||
return $this->_where_active()->find_all();
|
||||
}
|
||||
|
||||
public function list_count($active=TRUE) {
|
||||
$x=($active ? $this->_where_active() : $this);
|
||||
|
||||
|
@ -9,7 +9,78 @@
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class StaticList_Module extends StaticListModule {
|
||||
class StaticList_Module extends StaticList {
|
||||
protected static $record = array();
|
||||
|
||||
/**
|
||||
* Display a static name for a value
|
||||
*/
|
||||
public static function display($id) {
|
||||
// Override our argument list as defined in parent
|
||||
list($table,$key,$skey,$value) = func_get_args();
|
||||
$db = DB::select($key)->from($table)->where($skey,'=',$value)->execute();
|
||||
|
||||
if ($db->count() !== 1)
|
||||
return sprintf('No Value (%s)',$value);
|
||||
else
|
||||
return $db->get($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is to return the cached value of the current active record
|
||||
* This is so that a follow up call to get an attribute of a value retrieved
|
||||
* can reuse the active record values.
|
||||
* This gets over a limitation where the query to form() to get a default
|
||||
* no longer exists (or is invalid) and you want other attributes of the
|
||||
* remaining active record, which may not be the default record.
|
||||
*/
|
||||
public static function record($table,$attribute,$skey,$value) {
|
||||
if (empty(static::$record[$table]))
|
||||
return static::display($table,$attribute,$skey,$value);
|
||||
else
|
||||
return static::$record[$table][$attribute];
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders form input
|
||||
*/
|
||||
public static function form($name,$default='',$addblank=FALSE) {
|
||||
// Override our argument list as defined in parent
|
||||
list($name,$table,$default,$key,$value,$where,$addblank,$attributes) = func_get_args();
|
||||
|
||||
$db = DB::select()->from($table);
|
||||
|
||||
foreach ($where as $k=>$v) {
|
||||
list ($op,$v) = explode(':',$v);
|
||||
$db->where($k,$op,$v);
|
||||
}
|
||||
|
||||
$db = $db->execute();
|
||||
|
||||
// If we only have one record, dont make a select list
|
||||
if ($db->count() == 1) {
|
||||
static::$record[$table] = $db->as_array();
|
||||
static::$record[$table] = array_shift(static::$record[$table]);
|
||||
|
||||
return Form::hidden($name,$db->get($key)).$db->get($value);
|
||||
}
|
||||
|
||||
// Else we return a select list
|
||||
$x = array();
|
||||
if ($addblank)
|
||||
$x[] = '';
|
||||
|
||||
foreach ($db as $record) {
|
||||
$x[$record[$key]] = $record[$value];
|
||||
|
||||
// Save our static record, in case we reference this item again.
|
||||
if ($record[$key] == $default)
|
||||
static::$record[$table] = $record;
|
||||
}
|
||||
|
||||
return Form::select($name,$x,$default,$attributes);
|
||||
}
|
||||
|
||||
protected function table($module=NULL) {
|
||||
if (is_null($module))
|
||||
throw new Kohana_Exception('Module is a required attribute.');
|
||||
|
@ -1,84 +0,0 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This is class is renders standard values based on DB table row values.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
abstract class StaticListModule extends StaticList {
|
||||
protected static $record = array();
|
||||
|
||||
/**
|
||||
* Display a static name for a value
|
||||
*/
|
||||
public static function display($id) {
|
||||
// Override our argument list as defined in parent
|
||||
list($table,$key,$skey,$value) = func_get_args();
|
||||
$db = DB::select($key)->from($table)->where($skey,'=',$value)->execute();
|
||||
|
||||
if ($db->count() !== 1)
|
||||
return sprintf('No Value (%s)',$value);
|
||||
else
|
||||
return $db->get($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is to return the cached value of the current active record
|
||||
* This is so that a follow up call to get an attribute of a value retrieved
|
||||
* can reuse the active record values.
|
||||
* This gets over a limitation where the query to form() to get a default
|
||||
* no longer exists (or is invalid) and you want other attributes of the
|
||||
* remaining active record, which may not be the default record.
|
||||
*/
|
||||
public static function record($table,$attribute,$skey,$value) {
|
||||
if (empty(static::$record[$table]))
|
||||
return static::display($table,$attribute,$skey,$value);
|
||||
else
|
||||
return static::$record[$table][$attribute];
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders form input
|
||||
*/
|
||||
public static function form($name,$default='',$addblank=FALSE) {
|
||||
// Override our argument list as defined in parent
|
||||
list($name,$table,$default,$key,$value,$where,$addblank,$attributes) = func_get_args();
|
||||
|
||||
$db = DB::select()->from($table);
|
||||
|
||||
foreach ($where as $k=>$v) {
|
||||
list ($op,$v) = explode(':',$v);
|
||||
$db->where($k,$op,$v);
|
||||
}
|
||||
|
||||
$db = $db->execute();
|
||||
|
||||
// If we only have one record, dont make a select list
|
||||
if ($db->count() == 1) {
|
||||
static::$record[$table] = $db->as_array();
|
||||
static::$record[$table] = array_shift(static::$record[$table]);
|
||||
|
||||
return Form::hidden($name,$db->get($key)).$db->get($value);
|
||||
}
|
||||
|
||||
// Else we return a select list
|
||||
$x = array();
|
||||
if ($addblank)
|
||||
$x[] = '';
|
||||
|
||||
foreach ($db as $record) {
|
||||
$x[$record[$key]] = $record[$value];
|
||||
|
||||
// Save our static record, in case we reference this item again.
|
||||
if ($record[$key] == $default)
|
||||
static::$record[$table] = $record;
|
||||
}
|
||||
|
||||
return Form::select($name,$x,$default,$attributes);
|
||||
}
|
||||
}
|
||||
?>
|
@ -37,7 +37,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="head">Title</td>
|
||||
<td><?php echo $record->title('title'); ?></td>
|
||||
<td><?php echo $record->display('title'); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="head">Address</td>
|
||||
@ -61,7 +61,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="head">Country</td>
|
||||
<td><?php echo $record->country('country'); ?></td>
|
||||
<td><?php echo $record->country->display('name'); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="head">Language</td>
|
||||
@ -69,7 +69,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="head">Currency</td>
|
||||
<td><?php echo $record->currency('currency_id'); ?></td>
|
||||
<td><?php echo $record->currency->display('name'); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<!-- @todo NEEDS TO BE CONFIGURABLE -->
|
||||
|
1
application/views/welcome/reseller.php
Normal file
1
application/views/welcome/reseller.php
Normal file
@ -0,0 +1 @@
|
||||
Welcome, please select from the menu on the left.
|
1
application/views/welcome/user.php
Normal file
1
application/views/welcome/user.php
Normal file
@ -0,0 +1 @@
|
||||
Welcome, please select from the menu on the left.
|
@ -32,7 +32,7 @@ class ADSL {
|
||||
if (preg_match('/^a:/',$data))
|
||||
throw new Kohana_Exception('Data shouldnt be a serialized array');
|
||||
|
||||
$ao = ORM::factory('Adsl_Plan',$data);
|
||||
$ao = ORM::factory('ADSL_Plan',$data);
|
||||
$output = View::factory('adsl/contract_view')
|
||||
->set('record',$ao)
|
||||
->set('price_base',$price_base)
|
||||
|
@ -9,7 +9,7 @@
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_Adsl_Plan extends ORM_OSB {
|
||||
class Model_ADSL_Plan extends ORM_OSB {
|
||||
// Relationships
|
||||
// @todo This model should probably be joined with product_plugin_adsl
|
||||
protected $_belongs_to = array(
|
@ -19,7 +19,7 @@ class Model_Service_Plugin_Adsl extends Model_Service_Plugin {
|
||||
);
|
||||
|
||||
protected $_has_one = array(
|
||||
'adsl_plan'=>array('far_key'=>'provided_adsl_plan_id','foreign_key'=>'id'),
|
||||
'adsl_plan'=>array('model'=>'ADSL_Plan','far_key'=>'provided_adsl_plan_id','foreign_key'=>'id'),
|
||||
);
|
||||
|
||||
protected $_display_filters = array(
|
||||
|
@ -26,7 +26,7 @@ class Controller_Admin_Charge extends Controller_TemplateDefault_Admin {
|
||||
ORM::factory('Charge')->where('sweep_type','>=',0)->order_by('date_orig DESC')->find_all(),
|
||||
25,
|
||||
array(
|
||||
'id'=>array('label'=>'ID','url'=>URL::site('user','charge/view/')),
|
||||
'id'=>array('label'=>'ID','url'=>URL::link('user','charge/view/')),
|
||||
'date_orig'=>array('label'=>'Date'),
|
||||
'sweep_type'=>array('label'=>'Sweep'),
|
||||
'status'=>array('label'=>'Status'),
|
||||
@ -41,7 +41,7 @@ class Controller_Admin_Charge extends Controller_TemplateDefault_Admin {
|
||||
array(
|
||||
'page'=>TRUE,
|
||||
'type'=>'select',
|
||||
'form'=>URL::site('user','charge/view'),
|
||||
'form'=>URL::link('user','charge/view'),
|
||||
)),
|
||||
));
|
||||
}
|
||||
@ -90,7 +90,7 @@ class Controller_Admin_Charge extends Controller_TemplateDefault_Admin {
|
||||
Script::add(array('type'=>'stdin','data'=>'
|
||||
$(document).ready(function() {
|
||||
$("input[name=account_id]").autocomplete({
|
||||
source: "'.URL::site('a/account/ajaxlist').'",
|
||||
source: "'.URL::link('admin','account/ajaxlist').'",
|
||||
minLength: 2,
|
||||
change: function(event,ui) {
|
||||
// Send the request and update sub category dropdown
|
||||
|
@ -10,6 +10,11 @@
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_Checkout extends ORM_OSB {
|
||||
protected $_has_many = array(
|
||||
'account'=>array('through'=>'account_billing','foreign_key'=>'checkout_plugin_id'),
|
||||
'payment'=>array(),
|
||||
);
|
||||
|
||||
/**
|
||||
* Calcuale the fee for this checkout method
|
||||
*
|
||||
|
@ -42,7 +42,7 @@ class Controller_User_Email extends Controller_TemplateDefault_User {
|
||||
|
||||
$elo = ORM::factory('Email_Log',$id);
|
||||
|
||||
if (! $elo->loaded() OR ! Auth::instance()->authorised($elo->account_id)) {
|
||||
if (! $elo->loaded() OR ! Auth::instance()->authorised($elo->account)) {
|
||||
$this->template->content = 'Unauthorised or doesnt exist?';
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -10,5 +10,129 @@
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Invoice extends Controller_TemplateDefault {
|
||||
protected $secure_actions = array(
|
||||
'download'=>TRUE,
|
||||
'list'=>TRUE,
|
||||
'view'=>TRUE,
|
||||
);
|
||||
|
||||
/**
|
||||
* Show a list of invoices
|
||||
*/
|
||||
public function action_list() {
|
||||
Block::add(array(
|
||||
'title'=>sprintf('%s: %s - %s',_('Invoices For'),$this->ao->accnum(),$this->ao->name(TRUE)),
|
||||
'body'=>Table::display(
|
||||
$this->ao->invoice->find_all(),
|
||||
25,
|
||||
array(
|
||||
'id'=>array('label'=>'ID','url'=>URL::link('user','invoice/view/')),
|
||||
'date_orig'=>array('label'=>'Date Issued'),
|
||||
'due_date'=>array('label'=>'Date Due'),
|
||||
'total(TRUE)'=>array('label'=>'Total','class'=>'right'),
|
||||
'total_credits(TRUE)'=>array('label'=>'Credits','class'=>'right'),
|
||||
'payments_total(TRUE)'=>array('label'=>'Payments','class'=>'right'),
|
||||
'due(TRUE)'=>array('label'=>'Still Due','class'=>'right'),
|
||||
),
|
||||
array(
|
||||
'page'=>TRUE,
|
||||
'type'=>'select',
|
||||
'form'=>URL::link('user','invoice/view'),
|
||||
)),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* View an Invoice
|
||||
*/
|
||||
public function action_view() {
|
||||
list($id,$output) = Table::page(__METHOD__);
|
||||
|
||||
$io = ORM::factory('Invoice',$id);
|
||||
|
||||
if (! $io->loaded() OR ! Auth::instance()->authorised($io->account)) {
|
||||
$this->template->content = 'Unauthorised or doesnt exist?';
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$output .= View::factory($this->viewpath())
|
||||
->set('mediapath',Route::get('default/media'))
|
||||
->set('io',$io);
|
||||
|
||||
if ($io->due() AND ! $io->cart_exists()) {
|
||||
$output .= View::factory($this->viewpath().'/pay')
|
||||
->set('mid',$io->mid())
|
||||
->set('o',$io);
|
||||
}
|
||||
|
||||
if (! $io->status) {
|
||||
// Add a gribber popup
|
||||
// @todo Make a gribber popup a class on its own.
|
||||
Style::add(array(
|
||||
'type'=>'file',
|
||||
'data'=>'css/jquery.gritter.css',
|
||||
'media'=>'screen',
|
||||
));
|
||||
Script::add(array(
|
||||
'type'=>'file',
|
||||
'data'=>'js/jquery.gritter-1.5.js',
|
||||
));
|
||||
Script::add(array(
|
||||
'type'=>'stdin',
|
||||
'data'=>sprintf(
|
||||
'$(document).ready(function() {
|
||||
$.extend($.gritter.options, {
|
||||
fade_in_speed: "medium",
|
||||
fade_out_speed: 2000,
|
||||
time: "3000",
|
||||
sticky: false,
|
||||
});
|
||||
$.gritter.add({
|
||||
title: "%s",
|
||||
text: "%s",
|
||||
image: "%s",
|
||||
});});',
|
||||
'Cancelled','Invoice CANCELLED',URL::site().SystemMessage::image('info',true)
|
||||
)
|
||||
));
|
||||
|
||||
Style::add(array(
|
||||
'type'=>'stdin',
|
||||
'data'=>'
|
||||
#watermark {
|
||||
color: #800000;
|
||||
font-size: 4em;
|
||||
-webkit-transform: rotate(-45deg);
|
||||
-moz-transform: rotate(-45deg);
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
z-index: 1;
|
||||
left:250px;
|
||||
top:-20px;
|
||||
}
|
||||
'));
|
||||
|
||||
$output .= '<div id="watermark"><p>Invoice CANCELLED.</p></div>';
|
||||
}
|
||||
|
||||
Block::add(array(
|
||||
'title'=>sprintf('%s: %s - %s',_('Invoice'),$io->refnum(),$io->account->name()),
|
||||
'body'=>$output,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Download an invoice
|
||||
*/
|
||||
public function action_download() {
|
||||
$io = ORM::factory('Invoice',$this->request->param('id'));
|
||||
|
||||
$this->response->body(Invoice::instance($io)->pdf()->Output(sprintf('%s.pdf',$io->refnum()),'D'));
|
||||
$this->response->headers(array('Content-Type' => 'application/pdf'));
|
||||
$this->auto_render = FALSE;
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
33
modules/invoice/classes/Controller/Reseller/Invoice.php
Normal file
33
modules/invoice/classes/Controller/Reseller/Invoice.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class provides Reseller Invoice viewing functions
|
||||
*
|
||||
* @package Invoice
|
||||
* @category Controllers/Reseller
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Reseller_Invoice extends Controller_Invoice {
|
||||
public function action_list() {
|
||||
list($id,$output) = Table::page(__METHOD__);
|
||||
|
||||
$ao = ORM::factory('Account',$id);
|
||||
|
||||
if (! $ao->loaded() OR ! Auth::instance()->authorised($ao)) {
|
||||
$this->template->content = 'Unauthorised or doesnt exist?';
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Block::add(array(
|
||||
'body'=>$output,
|
||||
));
|
||||
|
||||
$this->ao = $ao;
|
||||
|
||||
// @todo Our pagination is broken if we select multiple accounts, and those accounts have multiple invoices.
|
||||
return parent::action_list();
|
||||
}
|
||||
}
|
||||
?>
|
@ -9,130 +9,6 @@
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_User_Invoice extends Controller_TemplateDefault_User {
|
||||
protected $secure_actions = array(
|
||||
'download'=>TRUE,
|
||||
'list'=>TRUE,
|
||||
'view'=>TRUE,
|
||||
);
|
||||
|
||||
/**
|
||||
* Show a list of invoices
|
||||
*/
|
||||
public function action_list() {
|
||||
Block::add(array(
|
||||
'title'=>sprintf('%s: %s - %s',_('Invoices For'),$this->ao->accnum(),$this->ao->name(TRUE)),
|
||||
'body'=>Table::display(
|
||||
$this->ao->invoice->find_all(),
|
||||
25,
|
||||
array(
|
||||
'id'=>array('label'=>'ID','url'=>URL::link('user','invoice/view/')),
|
||||
'date_orig'=>array('label'=>'Date Issued'),
|
||||
'due_date'=>array('label'=>'Date Due'),
|
||||
'total(TRUE)'=>array('label'=>'Total','class'=>'right'),
|
||||
'total_credits(TRUE)'=>array('label'=>'Credits','class'=>'right'),
|
||||
'payments_total(TRUE)'=>array('label'=>'Payments','class'=>'right'),
|
||||
'due(TRUE)'=>array('label'=>'Still Due','class'=>'right'),
|
||||
),
|
||||
array(
|
||||
'page'=>TRUE,
|
||||
'type'=>'select',
|
||||
'form'=>URL::link('user','invoice/view'),
|
||||
)),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* View an Invoice
|
||||
*/
|
||||
public function action_view() {
|
||||
list($id,$output) = Table::page(__METHOD__);
|
||||
|
||||
$io = ORM::factory('Invoice',$id);
|
||||
|
||||
if (! $io->loaded() AND ! in_array($this->ao->affiliate->id,$io->service_affiliates())) {
|
||||
$this->template->content = 'Unauthorised or doesnt exist?';
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$output .= View::factory($this->viewpath())
|
||||
->set('mediapath',Route::get('default/media'))
|
||||
->set('io',$io);
|
||||
|
||||
if ($io->due() AND ! $io->cart_exists()) {
|
||||
$output .= View::factory($this->viewpath().'/pay')
|
||||
->set('mid',$io->mid())
|
||||
->set('o',$io);
|
||||
}
|
||||
|
||||
if (! $io->status) {
|
||||
// Add a gribber popup
|
||||
// @todo Make a gribber popup a class on its own.
|
||||
Style::add(array(
|
||||
'type'=>'file',
|
||||
'data'=>'css/jquery.gritter.css',
|
||||
'media'=>'screen',
|
||||
));
|
||||
Script::add(array(
|
||||
'type'=>'file',
|
||||
'data'=>'js/jquery.gritter-1.5.js',
|
||||
));
|
||||
Script::add(array(
|
||||
'type'=>'stdin',
|
||||
'data'=>sprintf(
|
||||
'$(document).ready(function() {
|
||||
$.extend($.gritter.options, {
|
||||
fade_in_speed: "medium",
|
||||
fade_out_speed: 2000,
|
||||
time: "3000",
|
||||
sticky: false,
|
||||
});
|
||||
$.gritter.add({
|
||||
title: "%s",
|
||||
text: "%s",
|
||||
image: "%s",
|
||||
});});',
|
||||
'Cancelled','Invoice CANCELLED',URL::site().SystemMessage::image('info',true)
|
||||
)
|
||||
));
|
||||
|
||||
Style::add(array(
|
||||
'type'=>'stdin',
|
||||
'data'=>'
|
||||
#watermark {
|
||||
color: #800000;
|
||||
font-size: 4em;
|
||||
-webkit-transform: rotate(-45deg);
|
||||
-moz-transform: rotate(-45deg);
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
z-index: 1;
|
||||
left:250px;
|
||||
top:-20px;
|
||||
}
|
||||
'));
|
||||
|
||||
$output .= '<div id="watermark"><p>Invoice CANCELLED.</p></div>';
|
||||
}
|
||||
|
||||
Block::add(array(
|
||||
'title'=>sprintf('%s: %s - %s',_('Invoice'),$io->refnum(),$io->account->name()),
|
||||
'body'=>$output,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Download an invoice
|
||||
*/
|
||||
public function action_download() {
|
||||
$io = ORM::factory('Invoice',$this->request->param('id'));
|
||||
|
||||
$this->response->body(Invoice::instance($io)->pdf()->Output(sprintf('%s.pdf',$io->refnum()),'D'));
|
||||
$this->response->headers(array('Content-Type' => 'application/pdf'));
|
||||
$this->auto_render = FALSE;
|
||||
}
|
||||
class Controller_User_Invoice extends Controller_Invoice {
|
||||
}
|
||||
?>
|
||||
|
@ -436,18 +436,6 @@ class Model_Invoice extends ORM_OSB implements Cartable {
|
||||
return $this->saved();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of affiliates associated with this invoice (via the service)
|
||||
*/
|
||||
public function service_affiliates() {
|
||||
$return = array();
|
||||
|
||||
foreach ($this->items() as $io)
|
||||
array_push($return,$io->service->affiliate_id);
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the subtotal of all items
|
||||
*/
|
||||
|
@ -30,6 +30,10 @@ abstract class lnApp_BreadCrumb extends HTMLRender {
|
||||
throw new Kohana_Exception('Path is not a string, nor an array');
|
||||
}
|
||||
|
||||
public static function dump() {
|
||||
echo Debug::vars(static::$_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable a friendly name to be used for a path
|
||||
*/
|
||||
@ -80,7 +84,7 @@ abstract class lnApp_BreadCrumb extends HTMLRender {
|
||||
$output .= $i==$c ? '<li id="active">' : '<li>';
|
||||
$output .= HTML::anchor(
|
||||
(empty(static::$_data['url'][$p]) ? $p : static::$_data['url'][$p]),
|
||||
(empty(static::$_data['name'][$p]) ? ucfirst($v) : static::$_data['name'][$p])
|
||||
(empty(static::$_data['name'][$p]) ? ucfirst(URL::dir($v)) : static::$_data['name'][$p])
|
||||
);
|
||||
$output .= '</li>';
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ class lnApp_Controller_Login extends Controller_TemplateDefault {
|
||||
|
||||
public function action_index() {
|
||||
// If user already signed-in
|
||||
if (Auth::instance()->logged_in()!= 0) {
|
||||
if (Auth::instance()->logged_in() != 0) {
|
||||
// Redirect to the user account
|
||||
HTTP::redirect(URL::link('user','welcome/index'));
|
||||
}
|
||||
|
@ -37,16 +37,7 @@ abstract class lnApp_Controller_TemplateDefault extends Controller_Template {
|
||||
*
|
||||
* @var array actions that require a valid user
|
||||
*/
|
||||
protected $secure_actions = array(
|
||||
);
|
||||
|
||||
public function __construct(Request $request,Response $response) {
|
||||
// Our Menu's can run without method authentication by default.
|
||||
if (! isset($this->secure_actions['menu']))
|
||||
$this->secure_actions['menu'] = FALSE;
|
||||
|
||||
return parent::__construct($request,$response);
|
||||
}
|
||||
protected $secure_actions = array();
|
||||
|
||||
/**
|
||||
* Check and see if this controller needs authentication
|
||||
|
@ -10,6 +10,8 @@
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Product extends Controller_TemplateDefault {
|
||||
protected $auth_required = FALSE;
|
||||
|
||||
/**
|
||||
* Show a list of product categories
|
||||
*/
|
||||
|
@ -732,7 +732,7 @@ class Controller_Admin_Service extends Controller_TemplateDefault_Admin {
|
||||
|
||||
$so = ORM::factory('Service',$id);
|
||||
|
||||
if (! $so->loaded() OR ! Auth::instance()->authorised($so->account_id,$so->affiliate_id)) {
|
||||
if (! $so->loaded() OR ! Auth::instance()->authorised($so->account)) {
|
||||
$this->template->content = 'Unauthorised or doesnt exist?';
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ class Controller_Affiliate_Service extends Controller_TemplateDefault_Affiliate
|
||||
Block::add(array(
|
||||
'title'=>_('Customer Services'),
|
||||
'body'=>Table::display(
|
||||
$this->filter(ORM::factory('Service')->list_active(),$this->ao->affiliate->id),
|
||||
$this->filter(ORM::factory('Service')->list_active(),$this->ao->RTM->customers($this->ao->RTM),NULL,'account_id'),
|
||||
25,
|
||||
array(
|
||||
'id'=>array('label'=>'ID','url'=>URL::link('user','service/view/')),
|
||||
@ -55,7 +55,7 @@ class Controller_Affiliate_Service extends Controller_TemplateDefault_Affiliate
|
||||
|
||||
foreach (ORM::factory('Account')->list_active() as $ao)
|
||||
if ($ao->has_any('group',array($go)))
|
||||
foreach ($this->filter($ao->service->list_active(),$this->ao->affiliate->id,'name()') as $so)
|
||||
foreach ($this->filter($ao->service->list_active(),$this->ao->RTM->customers($this->ao->RTM),NULL,'account_id') as $so)
|
||||
if (! $so->service_billing->checkout_plugin_id)
|
||||
array_push($svs,$so);
|
||||
|
||||
@ -92,7 +92,7 @@ class Controller_Affiliate_Service extends Controller_TemplateDefault_Affiliate
|
||||
$svs = array();
|
||||
|
||||
foreach ($co->account->find_all() as $ao)
|
||||
foreach ($this->filter($ao->service->list_active(),$this->ao->affiliate->id,'name()') as $so)
|
||||
foreach ($this->filter($ao->service->list_active(),$this->ao->RTM->customers($this->ao->RTM),NULL,'account_id') as $so)
|
||||
if ($so->service_billing->checkout_plugin_id == $co->id)
|
||||
array_push($svs,$so);
|
||||
|
||||
@ -155,7 +155,7 @@ class Controller_Affiliate_Service extends Controller_TemplateDefault_Affiliate
|
||||
}
|
||||
|
||||
public function action_listadslservices() {
|
||||
$svs = $this->filter(ORM::factory('Service')->list_bylistgroup('ADSL'),$this->ao->affiliate->id,'name()');
|
||||
$svs = $this->filter(ORM::factory('Service')->list_bylistgroup('ADSL'),$this->ao->RTM->customers($this->ao->RTM),'name()','account_id');
|
||||
$data = $this->consoltraffic($svs,time());
|
||||
|
||||
$google = GoogleChart::factory('Legacy')
|
||||
@ -196,7 +196,7 @@ class Controller_Affiliate_Service extends Controller_TemplateDefault_Affiliate
|
||||
}
|
||||
|
||||
public function action_listhspaservices() {
|
||||
$svs = $this->filter(ORM::factory('Service')->list_bylistgroup('HSPA'),$this->ao->affiliate->id,'name()');
|
||||
$svs = $this->filter(ORM::factory('Service')->list_bylistgroup('HSPA'),$this->ao->RTM->customers($this->ao->RTM),'name()','account_id');
|
||||
$data = $this->consoltraffic($svs,time());
|
||||
|
||||
$google = GoogleChart::factory('Legacy')
|
||||
@ -240,7 +240,7 @@ class Controller_Affiliate_Service extends Controller_TemplateDefault_Affiliate
|
||||
Block::add(array(
|
||||
'title'=>_('Domain Names'),
|
||||
'body'=>Table::display(
|
||||
$this->filter(ORM::factory('Service')->list_bylistgroup('DOMAIN'),$this->ao->affiliate->id,'name()'),
|
||||
$this->filter(ORM::factory('Service')->list_bylistgroup('DOMAIN'),$this->ao->RTM->customers($this->ao->RTM),'name()','account_id'),
|
||||
25,
|
||||
array(
|
||||
'id'=>array('label'=>'ID','url'=>URL::link('user','service/view/')),
|
||||
@ -264,7 +264,7 @@ class Controller_Affiliate_Service extends Controller_TemplateDefault_Affiliate
|
||||
Block::add(array(
|
||||
'title'=>_('Hosting Services'),
|
||||
'body'=>Table::display(
|
||||
$this->filter(ORM::factory('Service')->list_bylistgroup('HOST'),$this->ao->affiliate->id,'name()'),
|
||||
$this->filter(ORM::factory('Service')->list_bylistgroup('HOST'),$this->ao->RTM->customers($this->ao->RTM),'name()','account_id'),
|
||||
25,
|
||||
array(
|
||||
'id'=>array('label'=>'ID','url'=>URL::link('user','service/view/')),
|
||||
|
@ -61,7 +61,7 @@ class Controller_User_Service extends Controller_TemplateDefault_User {
|
||||
|
||||
$so = ORM::factory('Service',$id);
|
||||
|
||||
if (! $so->loaded() OR ! Auth::instance()->authorised($so->account_id,$so->affiliate_id)) {
|
||||
if (! $so->loaded() OR ! Auth::instance()->authorised($so->account)) {
|
||||
$this->template->content = 'Unauthorised or doesnt exist?';
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -15,7 +15,6 @@
|
||||
class Model_Service extends ORM_OSB {
|
||||
// Relationships
|
||||
protected $_has_one = array(
|
||||
'affiliate'=>array('far_key'=>'affiliate_id','foreign_key'=>'id'),
|
||||
'service_billing'=>array('far_key'=>'account_billing_id','foreign_key'=>'id'),
|
||||
);
|
||||
protected $_has_many = array(
|
||||
|
@ -32,7 +32,7 @@ class Controller_User_SSL extends Controller_TemplateDefault_User {
|
||||
HTTP::redirect(URL::link('user','service/view/'.$so->id));
|
||||
}
|
||||
|
||||
if (! $so->loaded() OR ! Auth::instance()->authorised($so->account_id,$so->affiliate_id)) {
|
||||
if (! $so->loaded() OR ! Auth::instance()->authorised($so->account)) {
|
||||
$this->template->content = 'Unauthorised or doesnt exist?';
|
||||
return FALSE;
|
||||
}
|
||||
|
Reference in New Issue
Block a user