Rework service, change module_method configuration
This commit is contained in:
parent
1a40f95b30
commit
951845f6c6
@ -16,12 +16,45 @@ class Controller_Admin_Module extends Controller_Module {
|
||||
'list'=>TRUE,
|
||||
);
|
||||
|
||||
protected function _classes($dir,$class,$array=NULL,$key='') {
|
||||
$result = array();
|
||||
|
||||
if (is_null($array)) {
|
||||
$array = Kohana::list_files('classes');
|
||||
$array = $array['classes/Controller'];
|
||||
$key = 'classes/Controller';
|
||||
}
|
||||
|
||||
if (! $class)
|
||||
return array_keys($array);
|
||||
|
||||
if (! $dir) {
|
||||
if (! empty($array[$key.'/'.$class]))
|
||||
$result = Arr::merge($result,$this->_classes('','',$array[$key.'/'.$class],$key.'/'.$class));
|
||||
|
||||
if (! empty($array[$key.'/'.$class.'.php']))
|
||||
array_push($result,$key.'/'.$class);
|
||||
|
||||
} else {
|
||||
if (! empty($array[$key.'/'.$dir]))
|
||||
$result = Arr::merge($result,$this->_classes('',$class,$array[$key.'/'.$dir],$key.'/'.$dir));
|
||||
|
||||
if (! empty($array[$key.'/'.$dir.'/'.$class.'.php']))
|
||||
array_push($result,$key.'/'.$dir.'/'.$class);
|
||||
}
|
||||
|
||||
foreach ($result as $k=>$v)
|
||||
$result[$k] = str_replace('.php','',str_replace('/','_',preg_replace('/^classes\//','',$v)));
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of methods for a class
|
||||
*/
|
||||
protected function _methods($class) {
|
||||
$class = Kohana::classname($class);
|
||||
// Get a list of methods this module has
|
||||
$ch = 'Controller_%s';
|
||||
$methods = $secure_actions = $auth_required = array();
|
||||
|
||||
// List of classes where all our methods are, including this one.
|
||||
@ -30,19 +63,25 @@ class Controller_Admin_Module extends Controller_Module {
|
||||
|
||||
foreach ($classes as $c) {
|
||||
$x = URL::dir($c);
|
||||
$cn = Kohana::classname('Controller_'.($x ? $x.'_'.$class : $class));
|
||||
$cp = $this->_classes($x,$class);
|
||||
|
||||
foreach ($cp as $cn)
|
||||
if (class_exists($cn)) {
|
||||
$sc = preg_replace(sprintf('/^Controller_%s%s_?/',$x ? $x.'_' : '',$class),'',$cn);
|
||||
$r = new ReflectionClass($cn);
|
||||
|
||||
$rdp = $r->getDefaultProperties();
|
||||
$secure_actions[$cn] = $rdp['secure_actions'];
|
||||
$auth_required[$cn] = $rdp['auth_required'];
|
||||
|
||||
foreach ($r->getMethods() as $method) {
|
||||
foreach ($r->getMethods() as $method)
|
||||
if (preg_match('/^action_/',$method->name))
|
||||
array_push($methods,str_replace('action_',strtolower(($x ? $x.'_' : $x)),$method->name));
|
||||
}
|
||||
array_push($methods,
|
||||
str_replace('action_',
|
||||
#strtolower(($x ? $x.'_' : '').($sc ? $sc.'_' : '')),
|
||||
strtolower($x.($sc ? '_'.$sc : '').':'),
|
||||
$method->name)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,7 @@ class Controller_Reseller_Account extends Controller_Account {
|
||||
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'),
|
||||
$this->filter(ORM::factory('Account')->list_active(),$this->ao->RTM->customers($this->ao->RTM),'id','sortkey(TRUE)'),
|
||||
25,
|
||||
array(
|
||||
'id'=>array('label'=>'ID','url'=>URL::link('reseller','invoice/list/')),
|
||||
@ -64,7 +64,7 @@ class Controller_Reseller_Account extends Controller_Account {
|
||||
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'),
|
||||
$this->filter(ORM::factory('Account_Log')->find_all(),$this->ao->RTM->customers($this->ao->RTM),'account_id'),
|
||||
25,
|
||||
array(
|
||||
'id'=>array('label'=>'ID'),
|
||||
|
@ -52,9 +52,13 @@ class Controller_TemplateDefault extends lnApp_Controller_TemplateDefault {
|
||||
|
||||
/**
|
||||
* This will filter a search query to only return those accounts for a reseller
|
||||
* @todo Swap the order of these params and make flid necessary
|
||||
*
|
||||
* @param $o Our ORM Object that we are searching on
|
||||
* @param $fl Our array of items that we must return
|
||||
* @param $flid The ID that must be in the $fl
|
||||
* @param $sort Sort the results
|
||||
*/
|
||||
protected function filter($o,array $fl,$sort=NULL,$flid=NULL) {
|
||||
protected function filter($o,array $fl,$flid,$sort=NULL) {
|
||||
$result = array();
|
||||
|
||||
foreach ($o as $x)
|
||||
|
@ -13,17 +13,17 @@ class Menu {
|
||||
private static function collapse(array $array) {
|
||||
$result = array();
|
||||
|
||||
foreach ($array as $item) {
|
||||
if (isset($result[$item->module->name])) {
|
||||
if (! is_array($result[$item->module->name]))
|
||||
$result[$item->module->name] = array($result[$item->module->name]);
|
||||
foreach ($array as $mmo) {
|
||||
if (isset($result[$mmo->module->name])) {
|
||||
if (! is_array($result[$mmo->module->name]))
|
||||
$result[$mmo->module->name] = array($result[$mmo->module->name]);
|
||||
|
||||
array_push($result[$item->module->name],$item);
|
||||
array_push($result[$mmo->module->name],$mmo);
|
||||
|
||||
continue;
|
||||
|
||||
} else {
|
||||
$result[$item->module->name] = $item;
|
||||
$result[$mmo->module->name] = $mmo;
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,10 +36,10 @@ class Menu {
|
||||
if (empty(URL::$method_directory[$type]))
|
||||
return NULL;
|
||||
|
||||
$uo = Auth::instance()->get_user();
|
||||
$ao = Auth::instance()->get_user();
|
||||
|
||||
foreach ($uo->methods() as $mmo)
|
||||
if ($mmo->menu_display AND preg_match('/^'.$type.'_/',$mmo->name))
|
||||
foreach ($ao->methods() as $mmo)
|
||||
if ($mmo->menu_display AND $type == $mmo->directory())
|
||||
if (empty($result[$mmo->id]))
|
||||
$result[$mmo->id] = $mmo;
|
||||
|
||||
|
@ -123,7 +123,7 @@ class Model_Account extends Model_Auth_UserDefault {
|
||||
if (empty($result[$mmo->id]))
|
||||
$result[$mmo->id] = $mmo;
|
||||
|
||||
Sort::MAsort($result,'module->name,name');
|
||||
Sort::MAsort($result,'module->name,menu_display');
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
@ -31,12 +31,29 @@ class Model_Module_Method extends ORM_OSB {
|
||||
|
||||
protected $status;
|
||||
|
||||
// Temporarily adjust our name
|
||||
// @todo This is temporary until all our method names are colon delimited.
|
||||
protected function _load_values(array $values) {
|
||||
parent::_load_values($values);
|
||||
|
||||
if (substr_count($this->name,'_') == 1 AND ! substr_count($this->name,':'))
|
||||
$this->name = str_replace('_',':',$this->name);
|
||||
elseif (substr_count($this->name,'_') > 1)
|
||||
throw HTTP_Exception::factory(501,'Method :id has double underscore',array(':id'=>$this->id));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function controller_sub() {
|
||||
return substr_count($this->name,'_') ? substr($this->name,($x=strpos($this->name,'_')),strpos($this->name,':')-$x) : '';
|
||||
}
|
||||
|
||||
public function controller() {
|
||||
return Kohana::classname(sprintf('Controller%s_%s',($this->directory() ? '_' : '').$this->directory(),$this->module->name));
|
||||
return Kohana::classname(sprintf('Controller%s_%s',($this->directory() ? '_' : '').$this->directory(),$this->module->name).$this->controller_sub());
|
||||
}
|
||||
|
||||
public function directory() {
|
||||
return substr($this->name,0,strpos($this->name,'_'));
|
||||
return substr($this->name,0,substr_count($this->name,'_') ? strpos($this->name,'_') : strpos($this->name,':'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -51,7 +68,7 @@ class Model_Module_Method extends ORM_OSB {
|
||||
}
|
||||
|
||||
public function method() {
|
||||
return substr($this->name,strpos($this->name,'_')+1);
|
||||
return substr($this->name,strpos($this->name,':')+1);
|
||||
}
|
||||
|
||||
public function status($status=NULL) {
|
||||
@ -62,12 +79,12 @@ class Model_Module_Method extends ORM_OSB {
|
||||
}
|
||||
|
||||
public function url() {
|
||||
if (! preg_match('/_/',$this->name))
|
||||
if (! preg_match('/:/',$this->name))
|
||||
return NULL;
|
||||
|
||||
list($type,$action) = preg_split('/_/',$this->name,2);
|
||||
list($type,$action) = preg_split('/:/',$this->name,2);
|
||||
|
||||
return URL::link($type,$this->module->name.'/'.$action);
|
||||
return URL::link($this->directory(),$this->module->name.$this->controller_sub().'/'.$action);
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
@ -39,13 +39,18 @@ class Request extends Kohana_Request {
|
||||
|
||||
$result = NULL;
|
||||
|
||||
$mo = ORM::factory('Module',array('name'=>$this->_controller));
|
||||
list($c,$x) = substr_count($this->_controller,'_') ? explode('_',$this->_controller,2) : array($this->_controller,'');
|
||||
|
||||
$mo = ORM::factory('Module',array('name'=>$c));
|
||||
|
||||
if ($mo->loaded() AND $mo->status) {
|
||||
$method = strtolower($this->_directory ? sprintf('%s_%s',$this->_directory,$this->_action) : $this->_action);
|
||||
$method = strtolower($this->_directory ? sprintf('%s:%s',$this->_directory.($x ? '_'.$x : ''),$this->_action) : $this->_action);
|
||||
|
||||
// Get the method number
|
||||
$mmo = $mo->module_method->where('name','=',$method)->find();
|
||||
$mmo = $mo->module_method
|
||||
->where('name','=',$method)
|
||||
->or_where('name','=',str_replace(':','_',$method)) // @todo This is temporary until all our method names have a colon delimiter
|
||||
->find();
|
||||
|
||||
if ($mmo->loaded())
|
||||
$result = $mmo;
|
||||
|
@ -57,5 +57,5 @@
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div> <!-- /span8 -->
|
||||
</div> <!-- /span -->
|
||||
</div> <!-- /row -->
|
||||
|
@ -12,5 +12,5 @@
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /span -->
|
||||
</div> <!-- /row -->
|
||||
|
92
modules/adsl/classes/Controller/Reseller/Service/Adsl.php
Normal file
92
modules/adsl/classes/Controller/Reseller/Service/Adsl.php
Normal file
@ -0,0 +1,92 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class provides Reseller ADSL Service functions
|
||||
*
|
||||
* @package ADSL
|
||||
* @category Controllers/Reseller
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Reseller_Service_Adsl extends Controller_Service {
|
||||
protected $secure_actions = array(
|
||||
'list'=>TRUE,
|
||||
);
|
||||
|
||||
private function consoltraffic($svs,$date) {
|
||||
$data = array();
|
||||
|
||||
foreach ($svs as $so) {
|
||||
$c = array();
|
||||
foreach ($so->plugin()->get_traffic_data_monthly($date) as $metric => $ma) {
|
||||
foreach ($ma as $month => $traffic) {
|
||||
// Only count the service once, not for each metric.
|
||||
if (! isset($c[$month])) {
|
||||
if (isset($data['svs'][$month]))
|
||||
$data['svs'][$month] += 1;
|
||||
else
|
||||
$data['svs'][$month] = 1;
|
||||
|
||||
$c[$month] = 1;
|
||||
}
|
||||
|
||||
if (isset($data['data'][$metric][$month]))
|
||||
$data['data'][$metric][$month] += (int)$traffic;
|
||||
else
|
||||
$data['data'][$metric][$month] = (int)$traffic;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ksort($data['svs']);
|
||||
foreach ($data['data'] as $metric => $details)
|
||||
ksort($data['data'][$metric]);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function action_list() {
|
||||
$svs = $this->filter(ORM::factory('Service')->list_byplugin('ADSL'),$this->ao->RTM->customers($this->ao->RTM),'account_id','name()');
|
||||
|
||||
$data = $this->consoltraffic($svs,time());
|
||||
|
||||
$google = GoogleChart::factory('Legacy')
|
||||
->type('vertical_bar')
|
||||
->title(sprintf('ADSL traffic as at %s',date('Y-m-d',strtotime('yesterday'))));
|
||||
|
||||
foreach ($data['data'] as $key => $values)
|
||||
$google->sdata(array('yl'=>$key),array($key=>$values));
|
||||
|
||||
$google->sdata(array('yr'=>'services'),array('services'=>$data['svs']));
|
||||
|
||||
Block::add(array('body'=>(string)$google));
|
||||
|
||||
Block::factory()
|
||||
->title('ADSL Services')
|
||||
->title_icon('icon-th-list')
|
||||
->body(Table::factory()
|
||||
->jssort('adsl')
|
||||
->data($svs)
|
||||
->columns(array(
|
||||
'id'=>'ID',
|
||||
'name()'=>'Service',
|
||||
'plugin()->ipaddress()'=>'IP Address',
|
||||
'product->plugin()->speed'=>'Speed',
|
||||
'product->plugin()->allowance()'=>'Allowance',
|
||||
'plugin()->traffic_thismonth()'=>'This Month',
|
||||
'plugin()->traffic_lastmonth()'=>'Last Month',
|
||||
'recur_schedule'=>'Billing',
|
||||
'price(TRUE,TRUE)'=>'Price',
|
||||
'account->accnum()'=>'Cust ID',
|
||||
'account->name()'=>'Customer',
|
||||
'date_next_invoice'=>'Next Invoice',
|
||||
'due(TRUE)'=>'Due Invoices',
|
||||
))
|
||||
->prepend(array(
|
||||
'id'=>array('url'=>URL::link('user','service/view/')),
|
||||
))
|
||||
);
|
||||
}
|
||||
}
|
||||
?>
|
@ -59,7 +59,7 @@ class Model_Service_Plugin_Adsl extends Model_Service_Plugin {
|
||||
|
||||
public function service_view() {
|
||||
return View::factory('service/user/plugin/adsl/view')
|
||||
->set('so',$this);
|
||||
->set('o',$this);
|
||||
}
|
||||
|
||||
public function username_value() {
|
||||
@ -81,8 +81,10 @@ class Model_Service_Plugin_Adsl extends Model_Service_Plugin {
|
||||
return Config::date($this->service_contract_date);
|
||||
}
|
||||
|
||||
public function contract_date_end() {
|
||||
return Config::date(strtotime(sprintf('+%s months',$this->contract_term),$this->service_contract_date));
|
||||
public function contract_date_end($format=FALSE) {
|
||||
$x = strtotime(sprintf('+%s months',$this->contract_term),$this->service_contract_date);
|
||||
|
||||
return $format ? Config::date($x) : $x;
|
||||
}
|
||||
|
||||
public function hasOffpeak() {
|
||||
|
@ -1,28 +1,18 @@
|
||||
<!-- //@todo To translate -->
|
||||
<table class="box-full">
|
||||
<tr>
|
||||
<td style="width: 40%;">Speed</td>
|
||||
<td class="data" style="width: 60%;" colspan="2"><?php echo $po->display('speed'); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td>Peak</td>
|
||||
<?php if ($po->base_down_offpeak OR $po->extra_down_offpeak) { ?>
|
||||
<td>Off Peak</td>
|
||||
<?php } ?>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Included Download Traffic</td>
|
||||
<!-- // @todo Since price is stored in the DB in GB, so should the traffic. -->
|
||||
<td class="data"><?php echo $po->base_down_peak/1000; ?> GB</td>
|
||||
<td class="data"><?php echo $po->base_down_offpeak ? ($po->base_down_offpeak/1000).'GB' : HTML::nbsp(''); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Extra Download Traffic</td>
|
||||
<td class="data"><?php echo $po->display('extra_down_peak'); ?>/GB</td>
|
||||
<td class="data"><?php echo $po->extra_down_offpeak ? $po->display('extra_down_offpeak').'/GB' : HTML::nbsp(''); ?></td>
|
||||
</tr>
|
||||
</table>
|
||||
<fieldset class="span6">
|
||||
<legend>ADSL Features</legend>
|
||||
|
||||
<div class="dl-horizontal">
|
||||
|
||||
<dt>Speed</dt>
|
||||
<dd><?php echo $po->display('speed'); ?></dd>
|
||||
|
||||
<dt>Peak Downloads Included</dt>
|
||||
<dd><?php echo $po->base_down_peak/1000; ?> GB, excess <?php echo $po->display('extra_down_peak'); ?>/GB.
|
||||
|
||||
<?php if ($po->base_down_offpeak OR $po->extra_down_offpeak) : ?>
|
||||
<dt>OffPeak Downloads Included</dt>
|
||||
<dd><?php echo $po->base_down_offpeak/1000; ?> GB, excess <?php echo $po->display('extra_down_offpeak'); ?>/GB.
|
||||
<?php endif ?>
|
||||
|
||||
</div> <!-- /dl-horizontal -->
|
||||
</fieldset>
|
||||
|
@ -1,79 +1,60 @@
|
||||
<!-- //@todo To translate -->
|
||||
<table class="box-full">
|
||||
<tr>
|
||||
<td class="head" colspan="3">Service Details</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="3"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<table>
|
||||
<tr>
|
||||
<td style="width: 40%;">Service Number</td>
|
||||
<td style="width: 60%;" class="data"><?php echo $so->display('service_number'); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Service Address</td>
|
||||
<td class="data"><?php echo $so->display('service_address'); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Contract Term</td>
|
||||
<td class="data"><?php echo $so->display('contract_term'); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Connect Date</td>
|
||||
<td class="data"><?php echo $so->display('service_connect_date'); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Contract End Date</td>
|
||||
<td class="data"><?php echo $so->contract_date_end(); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Service Username</td>
|
||||
<td class="data"><?php echo $so->display('service_username'); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Service Password</td>
|
||||
<td class="data"><?php # @todo Enable the ability to hide this value echo $so->display('service_password'); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Service IP</td>
|
||||
<td class="data"><?php echo $so->ipaddress(); ?></td>
|
||||
</tr>
|
||||
<?php if ($so->hasOffPeak() AND $so->offpeak_start AND $so->offpeak_end) { ?>
|
||||
<tr>
|
||||
<td>Offpeak Period</td>
|
||||
<td class="data"><?php printf('%s-%s',$so->offpeak_start,$so->offpeak_end); ?></td>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
</table>
|
||||
</td>
|
||||
<td style="vertical-align: top;" colspan="2">
|
||||
<table>
|
||||
<tr>
|
||||
<td style="width: 40%;">Traffic Used This Month</td>
|
||||
<td style="width: 60%;" class="data"><?php echo $so->traffic_month(NULL); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Traffic Used Last Month</td>
|
||||
<td class="data"><?php echo $so->traffic_lastmonth(); ?></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="3">
|
||||
<fieldset class="span5">
|
||||
<legend>Service Details</legend>
|
||||
|
||||
<div class="dl-horizontal">
|
||||
|
||||
<dt>Service Number</dt>
|
||||
<dd><?php echo $o->display('service_number'); ?></dd>
|
||||
|
||||
<dt>Service Address</dt>
|
||||
<dd><?php echo $o->display('service_address'); ?></dd>
|
||||
|
||||
<dt>Connect Date</dt>
|
||||
<dd><?php echo $o->display('service_connect_date'); ?></dd>
|
||||
|
||||
<dt>Contract Term</dt>
|
||||
<dd><?php echo $o->display('contract_term'); ?></dd>
|
||||
|
||||
<dt>Contract End Date</dt>
|
||||
<dd><?php echo $o->contract_date_end(TRUE); ?></dd>
|
||||
|
||||
<dt>Service Username</dt>
|
||||
<dd><?php echo $o->display('service_username'); ?></dd>
|
||||
|
||||
<dt>Service Password</dt>
|
||||
<dd><?php echo $o->display('service_password'); ?></dd>
|
||||
|
||||
<dt>Service IP</dt>
|
||||
<dd><?php echo $o->ipaddress(); ?></dd>
|
||||
|
||||
<?php if ($o->hasOffPeak() AND $o->offpeak_start AND $o->offpeak_end) : ?>
|
||||
<dt>Offpeak Period</dt>
|
||||
<dd><?php printf('%s-%s',$o->offpeak_start,$o->offpeak_end); ?></dd>
|
||||
<?php endif ?>
|
||||
|
||||
</div> <!-- dl-horizontal -->
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="span6">
|
||||
<legend>Traffic Usage</legend>
|
||||
|
||||
<div class="dl-horizontal">
|
||||
<dt>This Month</dt>
|
||||
<dd> <?php echo $o->traffic_month(NULL); ?></dd>
|
||||
|
||||
<dt>Last Month</dt>
|
||||
<dd> <?php echo $o->traffic_lastmonth(); ?></dd>
|
||||
</div> <!-- dl-horizontal -->
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="span6">
|
||||
<table>
|
||||
<tr>
|
||||
<td>View Daily Traffic for Month</td>
|
||||
<td><?php echo Form::open(); echo Form::select('month',array_merge(array(''),$so->get_traffic_months()),(isset($_POST['month']) ? $_POST['month'] : '')); echo Form::submit('submit',_('Show'),array('class'=>'form_button')); echo Form::close(); ?></td>
|
||||
<td><?php echo Form::open(); echo Form::select('month',array_merge(array(''),$o->get_traffic_months()),(isset($_POST['month']) ? $_POST['month'] : '')); echo Form::submit('submit',_('Show'),array('class'=>'form_button')); echo Form::close(); ?></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"><?php echo $so->graph_traffic(isset($_POST['month']) ? $_POST['month'] : ''); ?></td>
|
||||
<td><?php echo $so->table_traffic(isset($_POST['month']) ? $_POST['month'] : ''); ?></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<?php echo $o->graph_traffic(isset($_POST['month']) ? $_POST['month'] : ''); ?><br>
|
||||
<?php echo $o->table_traffic(isset($_POST['month']) ? $_POST['month'] : ''); ?>
|
||||
</fieldset>
|
||||
|
@ -12,6 +12,7 @@
|
||||
class Model_Charge extends ORM_OSB {
|
||||
// Charge doesnt use the update column
|
||||
protected $_updated_column = FALSE;
|
||||
|
||||
protected $_serialize_column = array(
|
||||
'attributes',
|
||||
);
|
||||
@ -41,5 +42,14 @@ class Model_Charge extends ORM_OSB {
|
||||
throw new Kohana_Exception('Unkown detail request :type',array(':type'=>$type));
|
||||
}
|
||||
}
|
||||
|
||||
public function total($format=FALSE) {
|
||||
$result = $this->quantity * $this->amount;
|
||||
|
||||
if ($this->taxable)
|
||||
$result = Tax::add($result);
|
||||
|
||||
return $format ? Currency::display($result) : $result;
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
@ -0,0 +1,41 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class provides Reseller Domain Service functions
|
||||
*
|
||||
* @package Domain
|
||||
* @category Controllers/Reseller
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Reseller_Service_Domain extends Controller_Service {
|
||||
protected $secure_actions = array(
|
||||
'list'=>TRUE,
|
||||
);
|
||||
|
||||
public function action_list() {
|
||||
Block::factory()
|
||||
->title('Domain License Services')
|
||||
->title_icon('icon-th-list')
|
||||
->body(Table::factory()
|
||||
->jssort('adsl')
|
||||
->data($this->filter(ORM::factory('Service')->list_byplugin('DOMAIN'),$this->ao->RTM->customers($this->ao->RTM),'account_id','name()'))
|
||||
->columns(array(
|
||||
'id'=>'ID',
|
||||
'name()'=>'Service',
|
||||
'plugin()->display("domain_expire")'=>'Expire',
|
||||
'recur_schedule'=>'Billing',
|
||||
'price(TRUE,TRUE)'=>'Price',
|
||||
'account->accnum()'=>'Cust ID',
|
||||
'account->name()'=>'Customer',
|
||||
'date_next_invoice'=>'Next Invoice',
|
||||
'due(TRUE)'=>'Due Invoices',
|
||||
))
|
||||
->prepend(array(
|
||||
'id'=>array('url'=>URL::link('user','service/view/')),
|
||||
))
|
||||
);
|
||||
}
|
||||
}
|
||||
?>
|
@ -54,7 +54,7 @@ class Model_Service_Plugin_Domain extends Model_Service_Plugin {
|
||||
|
||||
public function service_view() {
|
||||
return View::factory('service/user/plugin/domain/view')
|
||||
->set('so',$this);
|
||||
->set('o',$this);
|
||||
}
|
||||
|
||||
public function username_value() {
|
||||
|
@ -26,7 +26,7 @@ class Service_Domain_PlanetDomain extends Service_Domain {
|
||||
$output .= Form::input($this->login_pass_field,substr(md5($spdo->password_value()),0,8),array('type'=>'hidden','id'=>sprintf('p_%s_%s',$spdo->service_id,$t)));
|
||||
$output .= Form::input('page.next',sprintf('/newdnr/action/dns/getDNSDetails.jsp?domain.name=%s',$d),array('type'=>'hidden'));
|
||||
$output .= Form::close();
|
||||
$output .= Form::button('submit',_('Manage'),array('class'=>'form_button','value'=>sprintf('%s:%s',$spdo->service_id,$t)));
|
||||
$output .= Form::button('submit',_('Manage'),array('class'=>'btn btn-default','value'=>sprintf('%s:%s',$spdo->service_id,$t)));
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ class Service_Domain_TPP extends Service_Domain {
|
||||
$output .= Form::input($this->login_user_field,$spdo->username_value(),array('type'=>'hidden','id'=>sprintf('u_%s_%s',$spdo->service_id,$t)));
|
||||
$output .= Form::input($this->login_pass_field,substr(md5($spdo->password_value()),0,8),array('type'=>'hidden','id'=>sprintf('p_%s_%s',$spdo->service_id,$t)));
|
||||
$output .= Form::close();
|
||||
$output .= Form::button('submit',_('Manage'),array('class'=>'form_button','value'=>sprintf('%s:%s',$spdo->service_id,$t)));
|
||||
$output .= Form::button('submit',_('Manage'),array('class'=>'btn btn-default','value'=>sprintf('%s:%s',$spdo->service_id,$t)));
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
@ -1,51 +1,26 @@
|
||||
<!-- //@todo To translate -->
|
||||
<table class="box-full">
|
||||
<tr>
|
||||
<td class="head" colspan="2">Service Details</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width: 50%">
|
||||
<table width="100%">
|
||||
<tr>
|
||||
<td style="width: 40%;">Domain Name</td>
|
||||
<td style="width: 60%;" class="data"><?php echo $so->name(); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Domain Expire</td>
|
||||
<td class="data"><?php echo $so->display('domain_expire'); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Domain Primary Name Servers</td>
|
||||
<td class="data"><?php echo $so->display('registrar_ns'); ?> <span style="small">(Last Sync: <?php echo $so->display('registrar_lastsync'); ?>)</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Domain Auth Password</td>
|
||||
<td class="data"><?php echo $so->display('registrar_auth_password'); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Domain Type</td>
|
||||
<td class="data"><?php echo $so->display('registrar_type'); ?></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td style="width: 50%">
|
||||
<table width="100%">
|
||||
<?php if ($x=$so->manage_button()) { ?>
|
||||
<tr>
|
||||
<td style="width: 40%;">Manage Registrar</td>
|
||||
<td style="width: 60%;" class="data"><?php echo $x; ?></td>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
<?php if ($x=$so->manage_dns_button()) { ?>
|
||||
<tr>
|
||||
<td style="width: 40%;">Manage DNS</td>
|
||||
<td style="width: 60%;" class="data"><?php echo $x; ?></td>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<fieldset class="span5">
|
||||
<legend>Service Details</legend>
|
||||
|
||||
<div class="dl-horizontal">
|
||||
|
||||
<dt>Domain Name</dt>
|
||||
<dd><?php echo $o->name(); ?></dd>
|
||||
|
||||
<dt>Domain Expire</dt>
|
||||
<dd><?php echo $o->display('domain_expire'); ?></dd>
|
||||
|
||||
<dt>Domain Auth Password</dt>
|
||||
<dd><?php echo $o->display('registrar_auth_password'); ?></dd>
|
||||
|
||||
<?php if ($x=$o->manage_button()) : ?>
|
||||
<dt>Registrar</dt>
|
||||
<dd><?php echo $x; ?></dd>
|
||||
<?php endif ?>
|
||||
|
||||
<?php if ($x=$o->manage_dns_button()) : ?>
|
||||
<dt>DNS</dt>
|
||||
<dd><?php echo $x; ?></dd>
|
||||
<?php endif ?>
|
||||
|
||||
</div> <!-- dl-horizontal -->
|
||||
</fieldset>
|
||||
|
@ -16,5 +16,5 @@
|
||||
'column_name'=>array('input'=>array('key'=>'display[__VALUE__]','values'=>$o->display)),
|
||||
)); ?>
|
||||
</fieldset>
|
||||
</div> <!-- /span8 -->
|
||||
</div> <!-- /span -->
|
||||
</div> <!-- /row -->
|
||||
|
@ -57,7 +57,7 @@ echo __METHOD__;die();
|
||||
$output .= Form::input($this->login_user_field,$u,array('type'=>'hidden','id'=>sprintf('u_%s_%s',$sid,$t)));
|
||||
$output .= Form::input($this->login_pass_field,$p,array('type'=>'hidden','id'=>sprintf('p_%s_%s',$sid,$t)));
|
||||
$output .= Form::close();
|
||||
$output .= Form::button('submit',_('Manage'),array('class'=>'form_button','value'=>sprintf('%s:%s',$sid,$t)));
|
||||
$output .= Form::button('submit',_('Manage'),array('class'=>'btn btn-default','value'=>sprintf('%s:%s',$sid,$t)));
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ abstract class Host_Plugin_Plesk extends Host_Plugin {
|
||||
$output .= Form::input($this->login_user_field,$u,array('type'=>'hidden','id'=>sprintf('u_%s_%s',$sid,$t)));
|
||||
$output .= Form::input($this->login_pass_field,$p,array('type'=>'hidden','id'=>sprintf('p_%s_%s',$sid,$t)));
|
||||
$output .= Form::close();
|
||||
$output .= Form::button('submit',_('Manage'),array('class'=>'form_button','value'=>sprintf('%s:%s',$sid,$t)));
|
||||
$output .= Form::button('submit',_('Manage'),array('class'=>'btn btn-default','value'=>sprintf('%s:%s',$sid,$t),'nocg'=>TRUE));
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ class Model_Service_Plugin_Host extends Model_Service_Plugin {
|
||||
|
||||
public function service_view() {
|
||||
return View::factory('service/user/plugin/host/view')
|
||||
->set('so',$this);
|
||||
->set('o',$this);
|
||||
}
|
||||
|
||||
public function username_value() {
|
||||
|
@ -1,33 +1,19 @@
|
||||
<!-- //@todo To translate -->
|
||||
<table class="box-full">
|
||||
<tr>
|
||||
<td class="head" colspan="2">Service Details</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width: 50%">
|
||||
<table width="100%">
|
||||
<tr>
|
||||
<td style="width: 40%;">Domain Name</td>
|
||||
<td style="width: 60%;" class="data"><?php echo $so->name(); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Hosting Expire</td>
|
||||
<td class="data"><?php echo $so->display('host_expire'); ?></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td style="width: 50%">
|
||||
<table width="100%">
|
||||
<?php if ($x=$so->manage_button()) { ?>
|
||||
<tr>
|
||||
<td style="width: 40%;">Panel Login</td>
|
||||
<td style="width: 60%;" class="data"><?php echo $x; ?></td>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<fieldset class="span5">
|
||||
<legend>Service Details</legend>
|
||||
|
||||
<div class="dl-horizontal">
|
||||
|
||||
<dt>Domain Name</dt>
|
||||
<dd><?php echo $o->name(); ?></dd>
|
||||
|
||||
<dt>Hosting Expire</dt>
|
||||
<dd><?php echo $o->display('host_expire'); ?></dd>
|
||||
|
||||
<?php if ($x=$o->manage_button()) : ?>
|
||||
<div class="offset1">
|
||||
<?php echo $x; ?>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
|
||||
</div> <!-- dl-horizontal -->
|
||||
</fieldset>
|
||||
|
@ -14,7 +14,7 @@
|
||||
<div class="tab-content">
|
||||
<?php $c=0;foreach (StaticList_RecurSchedule::table() as $k=>$v) : ?>
|
||||
<div class="tab-pane <?php echo $c++ ? '' : 'active'; ?>" id="tab<?php echo $k; ?>">
|
||||
<?php echo Form::checkbox("price_group[$k][show]",1,$o->isPriceShown($k),array('label'=>'Price Active','class'=>'span2')); ?>
|
||||
<?php echo Form::checkbox("price_group[$k][show]",1,$o->is_price_shown($k),array('label'=>'Price Active','class'=>'span2')); ?>
|
||||
|
||||
<?php foreach ($o->availPriceGroups() as $g) : ?>
|
||||
<div class="row">
|
||||
@ -72,5 +72,5 @@
|
||||
</div>
|
||||
|
||||
</fieldset>
|
||||
</div> <!-- /span8 -->
|
||||
</div> <!-- /span -->
|
||||
</div> <!-- /row -->
|
||||
|
@ -32,5 +32,5 @@
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div> <!-- /span8 -->
|
||||
</div> <!-- /span -->
|
||||
</div> <!-- /row -->
|
||||
|
@ -9,23 +9,16 @@
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Admin_Service extends Controller_TemplateDefault_Admin {
|
||||
// @todo This "module" menu items should belong in the module dir.
|
||||
class Controller_Admin_Service extends Controller_Service {
|
||||
protected $secure_actions = array(
|
||||
'ajaxlist'=>TRUE,
|
||||
'ajaxjson_traffic'=>TRUE,
|
||||
'adslstat'=>TRUE,
|
||||
'list'=>TRUE,
|
||||
'listbycheckout'=>TRUE,
|
||||
'listadslbilling'=>TRUE,
|
||||
'listadslservices'=>TRUE,
|
||||
'listexpiring'=>TRUE,
|
||||
'listdomainservices'=>TRUE,
|
||||
'listdomainservicesbysupplier'=>TRUE,
|
||||
'listdomainservicesbydnshost'=>TRUE,
|
||||
'listhostservices'=>TRUE,
|
||||
'listhostservicesbysupplier'=>TRUE,
|
||||
'listhspaservices'=>TRUE,
|
||||
'listwebservices'=>TRUE,
|
||||
'listinvoicesoon'=>TRUE,
|
||||
'update'=>TRUE,
|
||||
@ -63,111 +56,6 @@ class Controller_Admin_Service extends Controller_TemplateDefault_Admin {
|
||||
$this->response->body($google->json());
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a list of services
|
||||
*/
|
||||
public function action_list() {
|
||||
$id = $this->request->param('id');
|
||||
|
||||
$svs = ORM::factory('Service');
|
||||
|
||||
if ($id)
|
||||
$svs->where_active()->and_where('account_id','=',$id);
|
||||
|
||||
Block::add(array(
|
||||
'title'=>_('Customer Services'),
|
||||
'body'=>Table::display(
|
||||
$svs->find_all(),
|
||||
25,
|
||||
array(
|
||||
'id'=>array('label'=>'ID','url'=>URL::link('user','service/view/')),
|
||||
'service_name()'=>array('label'=>'Details'),
|
||||
'recur_schedule'=>array('label'=>'Billing'),
|
||||
'price(TRUE,TRUE)'=>array('label'=>'Price','class'=>'right'),
|
||||
'status'=>array('label'=>'Active'),
|
||||
'account->accnum()'=>array('label'=>'Cust ID'),
|
||||
'account->name()'=>array('label'=>'Customer'),
|
||||
),
|
||||
array(
|
||||
'page'=>TRUE,
|
||||
'type'=>'select',
|
||||
'form'=>URL::link('user','service/view'),
|
||||
)),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* List all services by their default checkout method
|
||||
*/
|
||||
public function action_listbycheckout() {
|
||||
$svs = array();
|
||||
// @todo This needs to be configurable
|
||||
$go = ORM::factory('Group',array('name'=>'Personal'));
|
||||
|
||||
foreach (ORM::factory('Account')->list_active() as $ao)
|
||||
if ($ao->has_any('group',array($go)))
|
||||
foreach ($ao->service->list_active() as $so)
|
||||
if (! $so->service_billing->checkout_plugin_id)
|
||||
array_push($svs,$so);
|
||||
|
||||
if ($svs)
|
||||
Block::add(array(
|
||||
'title'=>'Services that should be auto-billed',
|
||||
'body'=>Table::display(
|
||||
$svs,
|
||||
25,
|
||||
array(
|
||||
'id'=>array('label'=>'ID','url'=>URL::link('user','service/view/')),
|
||||
'service_name()'=>array('label'=>'Details'),
|
||||
'recur_schedule'=>array('label'=>'Billing'),
|
||||
'price(TRUE,TRUE)'=>array('label'=>'Price','class'=>'right'),
|
||||
'status'=>array('label'=>'Active'),
|
||||
'account->accnum()'=>array('label'=>'Cust ID'),
|
||||
'account->name()'=>array('label'=>'Customer'),
|
||||
'date_next_invoice'=>array('label'=>'Next Invoice'),
|
||||
'account->invoices_due_total(NULL,TRUE)'=>array('label'=>'Due Invoices'),
|
||||
),
|
||||
array(
|
||||
'page'=>TRUE,
|
||||
'type'=>'select',
|
||||
'form'=>URL::link('user','service/view'),
|
||||
)),
|
||||
));
|
||||
|
||||
foreach (ORM::factory('Checkout')->list_active() as $co) {
|
||||
$svs = array();
|
||||
|
||||
foreach ($co->account->find_all() as $ao)
|
||||
foreach ($ao->service->list_active() as $so)
|
||||
if ($so->service_billing->checkout_plugin_id == $co->id)
|
||||
array_push($svs,$so);
|
||||
|
||||
if ($svs)
|
||||
Block::add(array(
|
||||
'title'=>$co->name,
|
||||
'body'=>Table::display(
|
||||
$svs,
|
||||
25,
|
||||
array(
|
||||
'id'=>array('label'=>'ID','url'=>URL::link('user','service/view/')),
|
||||
'service_name()'=>array('label'=>'Details'),
|
||||
'recur_schedule'=>array('label'=>'Billing'),
|
||||
'price(TRUE,TRUE)'=>array('label'=>'Price','class'=>'right'),
|
||||
'status'=>array('label'=>'Active'),
|
||||
'account->accnum()'=>array('label'=>'Cust ID'),
|
||||
'account->name()'=>array('label'=>'Customer'),
|
||||
'date_next_invoice'=>array('label'=>'Next Invoice'),
|
||||
'account->invoices_due_total(NULL,TRUE)'=>array('label'=>'Due Invoices'),
|
||||
),
|
||||
array(
|
||||
'page'=>TRUE,
|
||||
'type'=>'select',
|
||||
'form'=>URL::link('user','service/view'),
|
||||
)),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
private function consoltraffic($svs,$date) {
|
||||
$data = array();
|
||||
|
||||
@ -200,51 +88,6 @@ class Controller_Admin_Service extends Controller_TemplateDefault_Admin {
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function action_listadslservices() {
|
||||
$id = $this->request->param('id');
|
||||
|
||||
$svs = $list = ORM::factory('Service')->list_bylistgroup('ADSL');
|
||||
|
||||
if ($id) {
|
||||
$svs = array();
|
||||
foreach ($list as $so)
|
||||
if ($so->account_id == $id)
|
||||
array_push($svs,$so);
|
||||
}
|
||||
|
||||
$google = GoogleChart::factory('ComboChart')
|
||||
->dataurl(URL::link('admin','service/ajaxjson_traffic',TRUE))
|
||||
->title(sprintf('ADSL traffic as at %s',date('Y-m-d',strtotime('yesterday'))));
|
||||
|
||||
Block::add(array('body'=>(string)$google));
|
||||
|
||||
Block::add(array(
|
||||
'title'=>_('ADSL Services'),
|
||||
'body'=>Table::display(
|
||||
$svs,
|
||||
NULL,
|
||||
array(
|
||||
'id'=>array('label'=>'ID','url'=>URL::link('user','service/view/')),
|
||||
'name()'=>array('label'=>'Service'),
|
||||
'plugin()->ipaddress()'=>array('label'=>'IP Address'),
|
||||
'product->plugin()->speed'=>array('label'=>'Speed'),
|
||||
'product->plugin()->allowance()'=>array('label'=>'Allowance'),
|
||||
'plugin()->traffic_thismonth()'=>array('label'=>'This Month'),
|
||||
'plugin()->traffic_lastmonth()'=>array('label'=>'Last Month'),
|
||||
'recur_schedule'=>array('label'=>'Billing'),
|
||||
'price(TRUE,TRUE)'=>array('label'=>'Price','class'=>'right'),
|
||||
'account->accnum()'=>array('label'=>'Cust ID'),
|
||||
'account->name()'=>array('label'=>'Customer'),
|
||||
'date_next_invoice'=>array('label'=>'Next Invoice'),
|
||||
'product->display("status")'=>array('label'=>'Current'),
|
||||
),
|
||||
array(
|
||||
'type'=>'select',
|
||||
'form'=>URL::link('user','service/view'),
|
||||
)),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a list of services that are expiring or have expired
|
||||
*/
|
||||
@ -271,74 +114,6 @@ class Controller_Admin_Service extends Controller_TemplateDefault_Admin {
|
||||
));
|
||||
}
|
||||
|
||||
public function action_listhspaservices() {
|
||||
$svs = ORM::factory('Service')->list_bylistgroup('HSPA');
|
||||
$data = $this->consoltraffic($svs,time());
|
||||
|
||||
$google = GoogleChart::factory('Legacy')
|
||||
->type('vertical_bar')
|
||||
->title(sprintf('HSPA traffic as at %s',date('Y-m-d',strtotime('yesterday'))));
|
||||
|
||||
foreach ($data['data'] as $key => $values)
|
||||
$google->data(array('yl'=>$key),array($key=>$values));
|
||||
|
||||
$google->data(array('yr'=>'services'),array('services'=>$data['svs']));
|
||||
|
||||
Block::add(array('body'=>(string)$google));
|
||||
|
||||
Block::add(array(
|
||||
'title'=>_('HSPA Services'),
|
||||
'body'=>Table::display(
|
||||
$svs,
|
||||
NULL,
|
||||
array(
|
||||
'id'=>array('label'=>'ID','url'=>URL::link('user','service/view/')),
|
||||
'name()'=>array('label'=>'Service'),
|
||||
'plugin()->ipaddress()'=>array('label'=>'IP Address'),
|
||||
'product->plugin()->speed'=>array('label'=>'Speed'),
|
||||
'product->plugin()->allowance()'=>array('label'=>'Allowance'),
|
||||
'plugin()->traffic_thismonth()'=>array('label'=>'This Month'),
|
||||
'plugin()->traffic_lastmonth()'=>array('label'=>'Last Month'),
|
||||
'recur_schedule'=>array('label'=>'Billing'),
|
||||
'price(TRUE,TRUE)'=>array('label'=>'Price','class'=>'right'),
|
||||
'account->accnum()'=>array('label'=>'Cust ID'),
|
||||
'account->name()'=>array('label'=>'Customer'),
|
||||
'date_next_invoice'=>array('label'=>'Next Invoice'),
|
||||
),
|
||||
array(
|
||||
'type'=>'select',
|
||||
'form'=>URL::link('user','service/view'),
|
||||
)),
|
||||
));
|
||||
}
|
||||
|
||||
public function action_listdomainservices() {
|
||||
$svs = ORM::factory('Service')->list_bylistgroup('DOMAIN');
|
||||
Sort::MAsort($svs,'name()');
|
||||
|
||||
Block::add(array(
|
||||
'title'=>_('Domain Names'),
|
||||
'body'=>Table::display(
|
||||
$svs,
|
||||
25,
|
||||
array(
|
||||
'id'=>array('label'=>'ID','url'=>URL::link('user','service/view/')),
|
||||
'service_name()'=>array('label'=>'Details'),
|
||||
'plugin()->display("domain_expire")'=>array('label'=>'Expire'),
|
||||
'recur_schedule'=>array('label'=>'Billing'),
|
||||
'price(TRUE,TRUE)'=>array('label'=>'Price','class'=>'right'),
|
||||
'account->accnum()'=>array('label'=>'Cust ID'),
|
||||
'account->name()'=>array('label'=>'Customer'),
|
||||
'display("date_next_invoice")'=>array('label'=>'Next Invoice'),
|
||||
),
|
||||
array(
|
||||
'page'=>TRUE,
|
||||
'type'=>'select',
|
||||
'form'=>URL::link('user','service/view'),
|
||||
)),
|
||||
));
|
||||
}
|
||||
|
||||
public function action_listdomainservicesbysupplier() {
|
||||
$svs = ORM::factory('Service')->list_bylistgroup('DOMAIN');
|
||||
Sort::MAsort($svs,'plugin()->domain_registrar_id,name()');
|
||||
@ -402,33 +177,6 @@ class Controller_Admin_Service extends Controller_TemplateDefault_Admin {
|
||||
));
|
||||
}
|
||||
|
||||
public function action_listhostservices() {
|
||||
$svs = ORM::factory('Service')->list_bylistgroup('HOST');
|
||||
Sort::MAsort($svs,'name()');
|
||||
|
||||
Block::add(array(
|
||||
'title'=>_('Hosting Services'),
|
||||
'body'=>Table::display(
|
||||
$svs,
|
||||
25,
|
||||
array(
|
||||
'id'=>array('label'=>'ID','url'=>URL::link('user','service/view/')),
|
||||
'service_name()'=>array('label'=>'Details'),
|
||||
'plugin()->display("host_expire")'=>array('label'=>'Expire'),
|
||||
'recur_schedule'=>array('label'=>'Billing'),
|
||||
'price(TRUE,TRUE)'=>array('label'=>'Price','class'=>'right'),
|
||||
'account->accnum()'=>array('label'=>'Cust ID'),
|
||||
'account->name()'=>array('label'=>'Customer'),
|
||||
'display("date_next_invoice")'=>array('label'=>'Next Invoice'),
|
||||
),
|
||||
array(
|
||||
'page'=>TRUE,
|
||||
'type'=>'select',
|
||||
'form'=>URL::link('user','service/view'),
|
||||
)),
|
||||
));
|
||||
}
|
||||
|
||||
public function action_listhostservicesbysupplier() {
|
||||
$svs = ORM::factory('Service')->list_bylistgroup('HOST');
|
||||
Sort::MAsort($svs,'plugin()->host_server,name()');
|
||||
@ -691,7 +439,7 @@ class Controller_Admin_Service extends Controller_TemplateDefault_Admin {
|
||||
'recur_schedule'=>array('label'=>'Billing'),
|
||||
'date_next_invoice'=>array('label'=>'Next Invoice'),
|
||||
'price(TRUE,TRUE)'=>array('label'=>'Price','class'=>'right'),
|
||||
'charges_new()'=>array('label'=>'Charges','class'=>'right'),
|
||||
'charges()'=>array('label'=>'Charges','class'=>'right'),
|
||||
'status'=>array('label'=>'Active'),
|
||||
'account->accnum()'=>array('label'=>'Cust ID'),
|
||||
'account->name()'=>array('label'=>'Customer'),
|
||||
@ -787,8 +535,6 @@ class Controller_Admin_Service extends Controller_TemplateDefault_Admin {
|
||||
if (is_null($bt))
|
||||
$bt = $iio->date_start;
|
||||
|
||||
// $doutput .= sprintf('%s: BT is: %s [%s]<br/>',$iio->id,Config::date($bt),$bt);
|
||||
|
||||
$pdata = Period::details($iio->recurring_schedule,$a ? NULL : $iio->product->price_recurr_weekday,$bt,TRUE);
|
||||
|
||||
switch ($iio->recurring_schedule) {
|
||||
|
@ -1,287 +0,0 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class provides Affiliate Service functions
|
||||
*
|
||||
* @package Service
|
||||
* @category Controllers/Affiliate
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Affiliate_Service extends Controller_TemplateDefault_Affiliate {
|
||||
protected $secure_actions = array(
|
||||
'list'=>TRUE,
|
||||
'listbycheckout'=>TRUE,
|
||||
'listadslservices'=>TRUE,
|
||||
'listdomainservices'=>TRUE,
|
||||
'listhostservices'=>TRUE,
|
||||
'listhspaservices'=>TRUE,
|
||||
);
|
||||
|
||||
/**
|
||||
* Show a list of services
|
||||
*/
|
||||
public function action_list() {
|
||||
Block::add(array(
|
||||
'title'=>_('Customer Services'),
|
||||
'body'=>Table::display(
|
||||
$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/')),
|
||||
'service_name()'=>array('label'=>'Details'),
|
||||
'recur_schedule'=>array('label'=>'Billing'),
|
||||
'price(TRUE,TRUE)'=>array('label'=>'Price','class'=>'right'),
|
||||
'status'=>array('label'=>'Active'),
|
||||
'account->accnum()'=>array('label'=>'Cust ID'),
|
||||
'account->name()'=>array('label'=>'Customer'),
|
||||
),
|
||||
array(
|
||||
'page'=>TRUE,
|
||||
'type'=>'select',
|
||||
'form'=>URL::link('user','service/view'),
|
||||
)),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* List all services by their default checkout method
|
||||
*/
|
||||
public function action_listbycheckout() {
|
||||
$svs = array();
|
||||
// @todo This needs to be configurable
|
||||
$go = ORM::factory('Group',array('name'=>'Personal'));
|
||||
|
||||
foreach (ORM::factory('Account')->list_active() as $ao)
|
||||
if ($ao->has_any('group',array($go)))
|
||||
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);
|
||||
|
||||
if ($svs)
|
||||
Block::add(array(
|
||||
'title'=>'Services that should be auto-billed',
|
||||
'body'=>Table::display(
|
||||
$svs,
|
||||
25,
|
||||
array(
|
||||
'id'=>array('label'=>'ID','url'=>URL::link('user','service/view/')),
|
||||
'service_name()'=>array('label'=>'Details'),
|
||||
'recur_schedule'=>array('label'=>'Billing'),
|
||||
'price(TRUE,TRUE)'=>array('label'=>'Price','class'=>'right'),
|
||||
'status'=>array('label'=>'Active'),
|
||||
'account->accnum()'=>array('label'=>'Cust ID'),
|
||||
'account->name()'=>array('label'=>'Customer'),
|
||||
'date_next_invoice'=>array('label'=>'Next Invoice'),
|
||||
'account->invoices_due_total(NULL,TRUE)'=>array('label'=>'Due Invoices'),
|
||||
),
|
||||
array(
|
||||
'page'=>TRUE,
|
||||
'type'=>'select',
|
||||
'form'=>URL::link('user','service/view'),
|
||||
)),
|
||||
));
|
||||
else
|
||||
Block::add(array(
|
||||
'title'=>'Services that should be auto-billed',
|
||||
'body'=>_('None found'),
|
||||
));
|
||||
|
||||
foreach (ORM::factory('Checkout')->list_active() as $co) {
|
||||
$svs = array();
|
||||
|
||||
foreach ($co->account->find_all() as $ao)
|
||||
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);
|
||||
|
||||
if ($svs)
|
||||
Block::add(array(
|
||||
'title'=>$co->name,
|
||||
'body'=>Table::display(
|
||||
$svs,
|
||||
25,
|
||||
array(
|
||||
'id'=>array('label'=>'ID','url'=>URL::link('user','service/view/')),
|
||||
'service_name()'=>array('label'=>'Details'),
|
||||
'recur_schedule'=>array('label'=>'Billing'),
|
||||
'price(TRUE,TRUE)'=>array('label'=>'Price','class'=>'right'),
|
||||
'status'=>array('label'=>'Active'),
|
||||
'account->accnum()'=>array('label'=>'Cust ID'),
|
||||
'account->name()'=>array('label'=>'Customer'),
|
||||
'date_next_invoice'=>array('label'=>'Next Invoice'),
|
||||
'account->invoices_due_total(NULL,TRUE)'=>array('label'=>'Due Invoices'),
|
||||
),
|
||||
array(
|
||||
'page'=>TRUE,
|
||||
'type'=>'select',
|
||||
'form'=>URL::link('user','service/view'),
|
||||
)),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
private function consoltraffic($svs,$date) {
|
||||
$data = array();
|
||||
|
||||
foreach ($svs as $so) {
|
||||
$c = array();
|
||||
foreach ($so->plugin()->get_traffic_data_monthly($date) as $metric => $ma) {
|
||||
foreach ($ma as $month => $traffic) {
|
||||
// Only count the service once, not for each metric.
|
||||
if (! isset($c[$month])) {
|
||||
if (isset($data['svs'][$month]))
|
||||
$data['svs'][$month] += 1;
|
||||
else
|
||||
$data['svs'][$month] = 1;
|
||||
|
||||
$c[$month] = 1;
|
||||
}
|
||||
|
||||
if (isset($data['data'][$metric][$month]))
|
||||
$data['data'][$metric][$month] += (int)$traffic;
|
||||
else
|
||||
$data['data'][$metric][$month] = (int)$traffic;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ksort($data['svs']);
|
||||
foreach ($data['data'] as $metric => $details)
|
||||
ksort($data['data'][$metric]);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function action_listadslservices() {
|
||||
$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')
|
||||
->type('vertical_bar')
|
||||
->title(sprintf('ADSL traffic as at %s',date('Y-m-d',strtotime('yesterday'))));
|
||||
|
||||
foreach ($data['data'] as $key => $values)
|
||||
$google->sdata(array('yl'=>$key),array($key=>$values));
|
||||
|
||||
$google->sdata(array('yr'=>'services'),array('services'=>$data['svs']));
|
||||
|
||||
Block::add(array('body'=>(string)$google));
|
||||
|
||||
Block::add(array(
|
||||
'title'=>_('ADSL Services'),
|
||||
'body'=>Table::display(
|
||||
$svs,
|
||||
50,
|
||||
array(
|
||||
'id'=>array('label'=>'ID','url'=>URL::link('user','service/view/')),
|
||||
'name()'=>array('label'=>'Service'),
|
||||
'plugin()->ipaddress()'=>array('label'=>'IP Address'),
|
||||
'product->plugin()->speed'=>array('label'=>'Speed'),
|
||||
'product->plugin()->allowance()'=>array('label'=>'Allowance'),
|
||||
'plugin()->traffic_thismonth()'=>array('label'=>'This Month'),
|
||||
'plugin()->traffic_lastmonth()'=>array('label'=>'Last Month'),
|
||||
'recur_schedule'=>array('label'=>'Billing'),
|
||||
'price(TRUE,TRUE)'=>array('label'=>'Price','class'=>'right'),
|
||||
'account->accnum()'=>array('label'=>'Cust ID'),
|
||||
'account->name()'=>array('label'=>'Customer'),
|
||||
'date_next_invoice'=>array('label'=>'Next Invoice'),
|
||||
),
|
||||
array(
|
||||
'type'=>'select',
|
||||
'form'=>URL::link('user','service/view'),
|
||||
)),
|
||||
));
|
||||
}
|
||||
|
||||
public function action_listhspaservices() {
|
||||
$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')
|
||||
->type('vertical_bar')
|
||||
->title(sprintf('HSPA traffic as at %s',date('Y-m-d',strtotime('yesterday'))));
|
||||
|
||||
foreach ($data['data'] as $key => $values)
|
||||
$google->sdata(array('yl'=>$key),array($key=>$values));
|
||||
|
||||
$google->sdata(array('yr'=>'services'),array('services'=>$data['svs']));
|
||||
|
||||
Block::add(array('body'=>(string)$google));
|
||||
|
||||
Block::add(array(
|
||||
'title'=>_('HSPA Services'),
|
||||
'body'=>Table::display(
|
||||
$svs,
|
||||
NULL,
|
||||
array(
|
||||
'id'=>array('label'=>'ID','url'=>URL::link('user','service/view/')),
|
||||
'name()'=>array('label'=>'Service'),
|
||||
'plugin()->ipaddress()'=>array('label'=>'IP Address'),
|
||||
'product->plugin()->speed'=>array('label'=>'Speed'),
|
||||
'product->plugin()->allowance()'=>array('label'=>'Allowance'),
|
||||
'plugin()->traffic_thismonth()'=>array('label'=>'This Month'),
|
||||
'plugin()->traffic_lastmonth()'=>array('label'=>'Last Month'),
|
||||
'recur_schedule'=>array('label'=>'Billing'),
|
||||
'price(TRUE,TRUE)'=>array('label'=>'Price','class'=>'right'),
|
||||
'account->accnum()'=>array('label'=>'Cust ID'),
|
||||
'account->name()'=>array('label'=>'Customer'),
|
||||
'date_next_invoice'=>array('label'=>'Next Invoice'),
|
||||
),
|
||||
array(
|
||||
'type'=>'select',
|
||||
'form'=>URL::link('user','service/view'),
|
||||
)),
|
||||
));
|
||||
}
|
||||
|
||||
public function action_listdomainservices() {
|
||||
Block::add(array(
|
||||
'title'=>_('Domain Names'),
|
||||
'body'=>Table::display(
|
||||
$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/')),
|
||||
'service_name()'=>array('label'=>'Details'),
|
||||
'plugin()->display("domain_expire")'=>array('label'=>'Expire'),
|
||||
'recur_schedule'=>array('label'=>'Billing'),
|
||||
'price(TRUE,TRUE)'=>array('label'=>'Price','class'=>'right'),
|
||||
'account->accnum()'=>array('label'=>'Cust ID'),
|
||||
'account->name()'=>array('label'=>'Customer'),
|
||||
'display("date_next_invoice")'=>array('label'=>'Next Invoice'),
|
||||
),
|
||||
array(
|
||||
'page'=>TRUE,
|
||||
'type'=>'select',
|
||||
'form'=>URL::link('user','service/view'),
|
||||
)),
|
||||
));
|
||||
}
|
||||
|
||||
public function action_listhostservices() {
|
||||
Block::add(array(
|
||||
'title'=>_('Hosting Services'),
|
||||
'body'=>Table::display(
|
||||
$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/')),
|
||||
'service_name()'=>array('label'=>'Details'),
|
||||
'plugin()->display("host_expire")'=>array('label'=>'Expire'),
|
||||
'recur_schedule'=>array('label'=>'Billing'),
|
||||
'price(TRUE,TRUE)'=>array('label'=>'Price','class'=>'right'),
|
||||
'account->accnum()'=>array('label'=>'Cust ID'),
|
||||
'account->name()'=>array('label'=>'Customer'),
|
||||
'display("date_next_invoice")'=>array('label'=>'Next Invoice'),
|
||||
),
|
||||
array(
|
||||
'page'=>TRUE,
|
||||
'type'=>'select',
|
||||
'form'=>URL::link('user','service/view'),
|
||||
)),
|
||||
));
|
||||
}
|
||||
}
|
||||
?>
|
112
modules/service/classes/Controller/Reseller/Service.php
Normal file
112
modules/service/classes/Controller/Reseller/Service.php
Normal file
@ -0,0 +1,112 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class provides Reseller Service functions
|
||||
*
|
||||
* @package Service
|
||||
* @category Controllers/Reseller
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Reseller_Service extends Controller_Service {
|
||||
protected $secure_actions = array(
|
||||
'list'=>TRUE,
|
||||
'listbycheckout'=>TRUE,
|
||||
'listhostservices'=>TRUE,
|
||||
);
|
||||
|
||||
/**
|
||||
* Show a list of services
|
||||
*/
|
||||
public function action_list() {
|
||||
Block::factory()
|
||||
->title('Customer Services')
|
||||
->title_icon('icon-th-list')
|
||||
->body(Table::factory()
|
||||
->jssort('services')
|
||||
->data($this->filter(ORM::factory('Service')->find_all(),$this->ao->RTM->customers($this->ao->RTM),'account_id'))
|
||||
->columns(array(
|
||||
'id'=>'ID',
|
||||
'service_name()'=>'Service',
|
||||
'recur_schedule'=>'Billing',
|
||||
'price(TRUE,TRUE)'=>'Price',
|
||||
'status(TRUE)'=>'Active',
|
||||
'account->accnum()'=>'Cust ID',
|
||||
'account->name()'=>'Customer',
|
||||
))
|
||||
->prepend(array(
|
||||
'id'=>array('url'=>URL::link('user','service/view/')),
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* List all services by their default checkout method
|
||||
*/
|
||||
public function action_listbycheckout() {
|
||||
$svs = array();
|
||||
// @todo This needs to be configurable
|
||||
$go = ORM::factory('Group',array('name'=>'Personal'));
|
||||
|
||||
foreach (ORM::factory('Account')->list_active() as $ao)
|
||||
if ($ao->has_any('group',array($go)))
|
||||
foreach ($this->filter($ao->service->list_active(),$this->ao->RTM->customers($this->ao->RTM),'account_id') as $so)
|
||||
if (! $so->service_billing->checkout_plugin_id)
|
||||
array_push($svs,$so);
|
||||
|
||||
if ($svs)
|
||||
Block::factory()
|
||||
->title('Services that should be auto-billed')
|
||||
->title_icon('icon-pencil')
|
||||
->body(Table::factory()
|
||||
->jssort('services')
|
||||
->data($svs)
|
||||
->columns(array(
|
||||
'id'=>'ID',
|
||||
'service_name()'=>'Service',
|
||||
'recur_schedule'=>'Billing',
|
||||
'price(TRUE,TRUE)'=>'Price',
|
||||
'account->accnum()'=>'Cust ID',
|
||||
'account->name()'=>'Customer',
|
||||
'date_next_invoice'=>'Next Invoice',
|
||||
'due(TRUE)'=>'Due Invoices',
|
||||
))
|
||||
->prepend(array(
|
||||
'id'=>array('url'=>URL::link('user','service/view/')),
|
||||
))
|
||||
);
|
||||
|
||||
foreach (ORM::factory('Checkout')->find_all() as $co) {
|
||||
$svs = array();
|
||||
|
||||
foreach ($co->account->find_all() as $ao)
|
||||
foreach ($this->filter($ao->service->list_active(),$this->ao->RTM->customers($this->ao->RTM),'account_id') as $so)
|
||||
if ($so->service_billing->checkout_plugin_id == $co->id)
|
||||
array_push($svs,$so);
|
||||
|
||||
if ($svs)
|
||||
Block::factory()
|
||||
->title($co->name)
|
||||
->title_icon('icon-repeat')
|
||||
->body(Table::factory()
|
||||
->jssort($co->id)
|
||||
->data($svs)
|
||||
->columns(array(
|
||||
'id'=>'ID',
|
||||
'service_name()'=>'Service',
|
||||
'recur_schedule'=>'Billing',
|
||||
'price(TRUE,TRUE)'=>'Price',
|
||||
'account->accnum()'=>'Cust ID',
|
||||
'account->name()'=>'Customer',
|
||||
'date_next_invoice'=>'Next Invoice',
|
||||
'due(TRUE)'=>'Due Invoices',
|
||||
))
|
||||
->prepend(array(
|
||||
'id'=>array('url'=>URL::link('user','service/view/')),
|
||||
))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
@ -9,13 +9,16 @@
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_User_Service extends Controller_TemplateDefault_User {
|
||||
class Controller_User_Service extends Controller_Service {
|
||||
protected $secure_actions = array(
|
||||
'ajaxmanage'=>TRUE,
|
||||
'list'=>TRUE,
|
||||
'view'=>TRUE,
|
||||
);
|
||||
|
||||
/**
|
||||
* This ajax functions obtains the manage button login/password for this service
|
||||
*/
|
||||
public function action_ajaxmanage() {
|
||||
$this->auto_render = FALSE;
|
||||
|
||||
@ -36,24 +39,23 @@ class Controller_User_Service extends Controller_TemplateDefault_User {
|
||||
* Show a list of services
|
||||
*/
|
||||
public function action_list() {
|
||||
Block::add(array(
|
||||
'title'=>sprintf('%s: %s - %s',_('Services For'),$this->ao->accnum(),$this->ao->name(TRUE)),
|
||||
'body'=>Table::display(
|
||||
$this->ao->service->find_all(),
|
||||
25,
|
||||
array(
|
||||
'id'=>array('label'=>'ID','url'=>URL::link('user','service/view/')),
|
||||
'service_name()'=>array('label'=>'Details'),
|
||||
'recur_schedule'=>array('label'=>'Billing'),
|
||||
'price(TRUE,TRUE)'=>array('label'=>'Price','class'=>'right'),
|
||||
'status'=>array('label'=>'Active'),
|
||||
),
|
||||
array(
|
||||
'page'=>TRUE,
|
||||
'type'=>'select',
|
||||
'form'=>URL::link('user','service/view'),
|
||||
)),
|
||||
));
|
||||
Block::factory()
|
||||
->title(sprintf('Services for Account: %s',$this->ao->accnum()))
|
||||
->title_icon('icon-th-list')
|
||||
->body(Table::factory()
|
||||
->jssort('services')
|
||||
->data($this->ao->service->find_all())
|
||||
->columns(array(
|
||||
'id'=>'ID',
|
||||
'service_name()'=>'Service',
|
||||
'recur_schedule'=>'Billing',
|
||||
'price(TRUE,TRUE)'=>'Price',
|
||||
'status(TRUE)'=>'Active',
|
||||
))
|
||||
->prepend(array(
|
||||
'id'=>array('url'=>URL::link('user','service/view/')),
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
public function action_view() {
|
||||
@ -61,18 +63,16 @@ class Controller_User_Service extends Controller_TemplateDefault_User {
|
||||
|
||||
$so = ORM::factory('Service',$id);
|
||||
|
||||
if (! $so->loaded() OR ! Auth::instance()->authorised($so->account)) {
|
||||
$this->template->content = 'Unauthorised or doesnt exist?';
|
||||
return FALSE;
|
||||
}
|
||||
if (! $so->loaded() OR ! Auth::instance()->authorised($so->account))
|
||||
throw HTTP_Exception::factory(403,'Service either doesnt exist, or you are not authorised to see it');
|
||||
|
||||
$output .= View::factory($this->viewpath())
|
||||
->set('so',$so);
|
||||
$output .= View::factory('service/user/view')
|
||||
->set('o',$so);
|
||||
|
||||
Block::add(array(
|
||||
'title'=>sprintf('%s: %s',$so->id(),$so->service_name()),
|
||||
'body'=>$output,
|
||||
));
|
||||
Block::factory()
|
||||
->title(sprintf('%s: %s',$so->id(),$so->service_name()))
|
||||
->title_icon('icon-list-alt')
|
||||
->body($output);
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
@ -18,6 +18,7 @@ class Model_Service extends ORM_OSB {
|
||||
'service_billing'=>array('far_key'=>'account_billing_id','foreign_key'=>'id'),
|
||||
);
|
||||
protected $_has_many = array(
|
||||
'charge'=>array('far_key'=>'id'),
|
||||
'invoice_item'=>array('far_key'=>'id'),
|
||||
'invoice'=>array('through'=>'invoice_item'),
|
||||
'service_change'=>array('far_key'=>'id'),
|
||||
@ -46,33 +47,27 @@ class Model_Service extends ORM_OSB {
|
||||
);
|
||||
|
||||
/**
|
||||
* Return the object of the product plugin
|
||||
* Get the additional charges associated with this service
|
||||
*/
|
||||
public function plugin($type='') {
|
||||
if (! $this->product->prod_plugin_file)
|
||||
return NULL;
|
||||
public function charges($unprocessed=TRUE,$format=FALSE) {
|
||||
$result = 0;
|
||||
|
||||
$o = ORM::factory(Kohana::classname(sprintf('Service_Plugin_%s',$this->product->prod_plugin_file)),array('service_id'=>$this->id));
|
||||
foreach ($this->charge_list($unprocessed) as $co)
|
||||
$result += $co->total();
|
||||
|
||||
return $type ? $o->$type : $o;
|
||||
return $format ? Currency::display($result) : $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the service number
|
||||
*/
|
||||
public function id() {
|
||||
return sprintf('%05s',$this->id);
|
||||
}
|
||||
public function charge_list($unprocessed=FALSE) {
|
||||
$x = $this->charge;
|
||||
|
||||
/**
|
||||
* Display the service product name
|
||||
*/
|
||||
public function name() {
|
||||
return is_null($plugin=$this->plugin()) ? $this->product->title() : $plugin->name();
|
||||
}
|
||||
if ($unprocessed)
|
||||
$x->where_open()
|
||||
->where('processed','IS',NULL)
|
||||
->or_where('processed','=',FALSE)
|
||||
->where_close();
|
||||
|
||||
public function pending_change() {
|
||||
return count($this->service_change->where_active()->where_open()->and_where('complete','!=',1)->or_where('complete','IS',null)->where_close()->find_all()->as_array());
|
||||
return $x->find_all();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -81,7 +76,7 @@ class Model_Service extends ORM_OSB {
|
||||
public function due($format=FALSE) {
|
||||
$total = 0;
|
||||
|
||||
foreach ($this->list_invoices(TRUE) as $io)
|
||||
foreach ($this->invoice_list(TRUE) as $io)
|
||||
$total += $io->due();
|
||||
|
||||
return $format ? Currency::display($total) : $total;
|
||||
@ -103,10 +98,80 @@ class Model_Service extends ORM_OSB {
|
||||
/**
|
||||
* Determine if a service expires in the next $days.
|
||||
*/
|
||||
public function expiring($days) {
|
||||
public function expiring($days=0) {
|
||||
return time()+$days*86400 > $this->expire();
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the service number
|
||||
*/
|
||||
public function id() {
|
||||
return sprintf('%05s',$this->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* List invoices for this service
|
||||
*/
|
||||
public function invoice_list($due=FALSE) {
|
||||
$result = array();
|
||||
|
||||
$x = $this->invoice->distinct('id');
|
||||
|
||||
// If we only want due invoices, we can speed things up by only looking for unprocessed
|
||||
if ($due)
|
||||
$x->where_unprocessed();
|
||||
|
||||
foreach ($x->find_all() as $io)
|
||||
if (! $due OR $io->due())
|
||||
array_push($result,$io);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the service product name
|
||||
*/
|
||||
public function name() {
|
||||
return is_null($plugin=$this->plugin()) ? $this->product->title() : $plugin->name();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns TRUE of this service has a planend change
|
||||
*/
|
||||
public function pending_change() {
|
||||
return $this->service_change()->loaded() ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the product that this service will be changed to
|
||||
*/
|
||||
public function pending_product() {
|
||||
return $this->service_change()->product;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the object of the product plugin
|
||||
*/
|
||||
public function plugin($type='') {
|
||||
if (! $this->product->prod_plugin_file)
|
||||
return NULL;
|
||||
|
||||
$o = ORM::factory(Kohana::classname(sprintf('Service_Plugin_%s',$this->product->prod_plugin_file)),array('service_id'=>$this->id));
|
||||
|
||||
return $type ? $o->$type : $o;
|
||||
}
|
||||
|
||||
public function service_change() {
|
||||
return $this->service_change->where_active()->where_open()->and_where('complete','!=',1)->or_where('complete','IS',null)->where_close()->find();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a descriptive name for this service
|
||||
*/
|
||||
public function service_name() {
|
||||
return is_null($plugin=$this->plugin()) ? $this->name() : $plugin->service_name();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the service charge
|
||||
*/
|
||||
@ -122,32 +187,18 @@ class Model_Service extends ORM_OSB {
|
||||
return $format ? Currency::display($p) : $p;
|
||||
}
|
||||
|
||||
public function service_name() {
|
||||
return is_null($plugin=$this->plugin()) ? $this->name() : $plugin->service_name();
|
||||
}
|
||||
|
||||
public function service_view() {
|
||||
return is_null($plugin=$this->plugin()) ? HTML::nbsp('') : $plugin->service_view();
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the product feature summary
|
||||
*/
|
||||
public function product_feature_summary() {
|
||||
return $this->product->feature_summary();
|
||||
}
|
||||
|
||||
/**
|
||||
* Render some details for specific calls, eg: invoice
|
||||
*/
|
||||
public function details($type) {
|
||||
$plugin = $this->plugin();
|
||||
|
||||
switch ($type) {
|
||||
case 'invoice_detail_items':
|
||||
if (is_null($plugin = $this->plugin()))
|
||||
return array();
|
||||
else
|
||||
return $plugin->_details($type);
|
||||
break;
|
||||
return is_null($plugin) ? array() : $plugin->_details($type);
|
||||
|
||||
case 'service_view':
|
||||
return is_null($plugin) ? HTML::nbsp('') : $plugin->service_view();
|
||||
|
||||
default:
|
||||
throw new Kohana_Exception('Unkown detail request :type',array(':type'=>$type));
|
||||
@ -170,7 +221,7 @@ class Model_Service extends ORM_OSB {
|
||||
|
||||
// @todo To implement
|
||||
public function charges_new() {
|
||||
return 0;
|
||||
return $this->charges();
|
||||
}
|
||||
|
||||
/** LIST FUNCTIONS **/
|
||||
@ -199,6 +250,19 @@ class Model_Service extends ORM_OSB {
|
||||
return parent::list_autocomplete($term,$index,$value,$label,$limit,$options);
|
||||
}
|
||||
|
||||
/**
|
||||
* List all products by their plugin type
|
||||
*/
|
||||
public function list_byplugin($plugin) {
|
||||
return $this
|
||||
->join('product')
|
||||
->on($this->table_name().'.site_id','=','product.site_id') // @todo This should be automatic
|
||||
->on($this->table_name().'.product_id','=','product.id')
|
||||
->where('prod_plugin_file','=',$plugin)
|
||||
->and_where('service.status','=',TRUE)
|
||||
->find_all();
|
||||
}
|
||||
|
||||
public function list_bylistgroup($cat) {
|
||||
$result = array();
|
||||
|
||||
@ -223,19 +287,6 @@ class Model_Service extends ORM_OSB {
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* List invoices for this service
|
||||
*/
|
||||
public function list_invoices($due=FALSE) {
|
||||
$result = array();
|
||||
|
||||
foreach ($this->invoice->find_all() as $io)
|
||||
if (! $due OR $io->due())
|
||||
array_push($result,$io);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* List services that need to be billed.
|
||||
*
|
||||
|
@ -1,80 +1,84 @@
|
||||
<!-- @todo NEEDS TO BE TRANSLATED -->
|
||||
<table width="100%">
|
||||
<tr>
|
||||
<td>
|
||||
<!-- Service Information -->
|
||||
<table class="box-full">
|
||||
<tr>
|
||||
<td style="width: 40%;">Account</td>
|
||||
<td style="width: 60%;" class="data"><?php printf('%s (%s)',$so->account->name(),$so->account->accnum()); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Service Active</td>
|
||||
<td class="data"><?php echo $so->display('status'); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Billing Period</td>
|
||||
<td class="data"><?php echo $so->display('recur_schedule');?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Cost</td>
|
||||
<td class="data"><?php echo $so->price(TRUE,TRUE); if ($so->pending_change()) echo ' *'; ?></td>
|
||||
</tr>
|
||||
<?php if (is_null($so->price) OR ($so->price<=$so->product->price($so->price_group,$so->recur_schedule,'price_base'))) { ?>
|
||||
<tr>
|
||||
<td>Service</td>
|
||||
<td class="data"><?php echo HTML::anchor('product/view/'.$so->product_id,$so->product->title()); ?></td>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
<tr>
|
||||
<td>Date Next Invoice</td>
|
||||
<td class="data"><?php echo $so->display('date_next_invoice'); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Current Invoices Due</td>
|
||||
<td class="data"><?php echo Currency::display($so->account->invoices_due_total()); ?></td>
|
||||
</tr>
|
||||
<?php if ($so->service_billing->loaded()) { ?>
|
||||
<tr>
|
||||
<td>Direct Debit</td>
|
||||
<td class="data"><?php echo $so->service_billing->checkout->name; ?></td>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
</table>
|
||||
<!-- END Service Information -->
|
||||
</td>
|
||||
<td style="vertical-align: top;">
|
||||
<!-- Product Summary Info -->
|
||||
<?php echo $so->product_feature_summary(); ?>
|
||||
<!-- END Product Summary Info -->
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br/>
|
||||
<?php echo $so->service_view(); ?>
|
||||
<br/>
|
||||
<table class="box-left" width="50%">
|
||||
<tr>
|
||||
<td class="head" colspan="2">Invoices for this service</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">Number</td>
|
||||
<td>Invoice Date</td>
|
||||
<td>Due Date</td>
|
||||
<td>Total</td>
|
||||
<td>Balance</td>
|
||||
</tr>
|
||||
<?php $i=0; foreach ($so->invoice->distinct('id')->order_by('id DESC')->find_all() as $io) { ?>
|
||||
<tr class="<?php echo $i++%2 ? 'odd' : 'even'; ?>">
|
||||
<td class="icon" width="20px"><?php echo HTML::anchor(URL::link('user','invoice/download/'.$io->id),HTML::image('media/img/gnome-pdf.png',array('alt'=>_('Download'),'width'=>20))); ?></td>
|
||||
<td class="data"><?php echo HTML::anchor(URL::link('user','invoice/view/'.$io->id),$io->id()); ?></td>
|
||||
<td class="data"><?php echo $io->display('date_orig'); ?></td>
|
||||
<td class="data"><?php echo $io->display('due_date'); ?></td>
|
||||
<td class="data"><?php echo $io->total(TRUE); ?></td>
|
||||
<td class="data"><?php echo $io->due(TRUE); ?></td>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
</table>
|
||||
<div class="row">
|
||||
<fieldset class="span5">
|
||||
<legend>Service Information</legend>
|
||||
|
||||
<div class="dl-horizontal">
|
||||
|
||||
<dt>Account</dt>
|
||||
<dd><?php printf('%s (%s)',$o->account->name(),$o->account->accnum()); ?></dd>
|
||||
|
||||
<dt>Service Active</dt>
|
||||
<dd><?php echo $o->label_bool('status',TRUE); ?></dd>
|
||||
|
||||
<dt>Billing Period</dt>
|
||||
<dd><?php echo $o->display('recur_schedule');?></dd>
|
||||
|
||||
<dt>Cost</dt>
|
||||
<dd><?php echo $o->price(TRUE,TRUE); if ($o->pending_change()) echo ' *'; ?></dd>
|
||||
|
||||
<?php if (is_null($o->price) OR ($o->price<=$o->product->price($o->price_group,$o->recur_schedule,'price_base'))) : ?>
|
||||
<dt>Service</dt>
|
||||
<dd><?php echo HTML::anchor('product/view/'.$o->product_id,$o->product->title()); ?></dd>
|
||||
<?php endif ?>
|
||||
|
||||
<dt>Date Next Invoice</dt>
|
||||
<dd><?php echo $o->display('date_next_invoice'); ?></dd>
|
||||
|
||||
<dt>Current Invoices Due</dt>
|
||||
<dd><?php echo $o->due(TRUE); ?></dd>
|
||||
|
||||
</div> <!-- /dl-horizontal -->
|
||||
</fieldset>
|
||||
|
||||
<?php if ($o->product->feature_summary()) :
|
||||
echo $o->product->feature_summary();
|
||||
endif ?>
|
||||
|
||||
</div> <!-- /row -->
|
||||
|
||||
<div class="row">
|
||||
<?php echo $o->details('service_view'); ?>
|
||||
</div> <!-- /row -->
|
||||
|
||||
<div class="row">
|
||||
<?php if ($o->service_billing->loaded()) : ?>
|
||||
<fieldset class="span5">
|
||||
<legend>Automatic Payment Details</legend>
|
||||
|
||||
<dt><?php echo $o->service_billing->checkout->display('name'); ?></dt>
|
||||
<dd> </dd>
|
||||
|
||||
</fieldset>
|
||||
<?php endif ?>
|
||||
|
||||
<?php if ($o->charges()) : ?>
|
||||
<fieldset class="span5">
|
||||
<legend>Service Charges to Bill: <?php echo $o->charges(TRUE,TRUE); ?></legend>
|
||||
|
||||
<?php echo Table::factory()
|
||||
->data($o->charge_list(TRUE))
|
||||
->columns(array(
|
||||
'date_orig'=>'Date',
|
||||
'description'=>'Description',
|
||||
'total(TRUE)'=>'Amount',
|
||||
)); ?>
|
||||
|
||||
</fieldset>
|
||||
<?php endif ?>
|
||||
|
||||
<fieldset class="span5">
|
||||
<legend>Invoices for this Service</legend>
|
||||
<?php echo Table::factory()
|
||||
->data($o->invoice_list())
|
||||
->columns(array(
|
||||
'id'=>'ID',
|
||||
'date_orig'=>'Date',
|
||||
'due_date'=>'Due',
|
||||
'total(TRUE)'=>'Amount',
|
||||
'due(TRUE)'=>'Due',
|
||||
))
|
||||
->prepend(array(
|
||||
'id'=>array('url'=>URL::link('user','invoice/download/')),
|
||||
)); ?>
|
||||
</fieldset>
|
||||
</div> <!-- /row -->
|
||||
|
@ -78,7 +78,7 @@ class Model_Service_Plugin_Ssl extends Model_Service_Plugin {
|
||||
|
||||
public function service_view() {
|
||||
return View::factory('service/user/plugin/ssl/view')
|
||||
->set('so',$this);
|
||||
->set('o',$this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -110,11 +110,14 @@ class Model_Service_Plugin_Ssl extends Model_Service_Plugin {
|
||||
if (! $this->service->status OR ! preg_match('/client/',$this->service->product->plugin()->extensions) OR $this->valid_to() < time())
|
||||
return '';
|
||||
|
||||
// @todo Do some password validation
|
||||
$output = Form::open(URL::link('user','ssl/download'));
|
||||
$output = Form::open(URL::link('user','ssl/download'),array('class'=>'form-inline'));
|
||||
$output .= Form::hidden('sid',$this->service->id);
|
||||
$output .= _('Choose a password').': '.Form::password('passwd','').'<br/><br/>';
|
||||
$output .= Form::submit('download','Download',array('class'=>'form_button'));
|
||||
$output .= '<div class="input-append">';
|
||||
$output .= Form::password('passwd','',array('label'=>_('Choose a password'),'placeholder'=>'Password','required','nocg'=>TRUE,'pattern'=>'.{6,}','title'=>'Minimum 6 chars'));
|
||||
$output .= Form::button('download','Download',array('class'=>'btn btn-default','nocg'=>TRUE));
|
||||
$output .= '</div>';
|
||||
$output .= Form::close();
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,13 @@
|
||||
<!-- //@todo To translate -->
|
||||
<table class="box-full">
|
||||
<tr>
|
||||
<td style="width: 40%;">Validity Days</td>
|
||||
<td class="data" style="width: 60%;" colspan="2"><?php echo $po->display('days'); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Type</td>
|
||||
<td class="data"><?php echo $po->display('extensions'); ?></td>
|
||||
</tr>
|
||||
</table>
|
||||
<fieldset class="span6">
|
||||
<legend>SSL Features</legend>
|
||||
|
||||
<div class="dl-horizontal">
|
||||
|
||||
<dt>Validatity Days</dt>
|
||||
<dd><?php echo $po->display('days'); ?></dd>
|
||||
|
||||
<dt>Type</dt>
|
||||
<dd><?php echo $po->display('extensions'); ?></dd>
|
||||
|
||||
</div> <!-- /dl-horizontal -->
|
||||
</fieldset>
|
||||
|
@ -1,56 +1,41 @@
|
||||
<!-- //@todo To translate -->
|
||||
<table class="box-full">
|
||||
<tr>
|
||||
<td class="head" colspan="3">Service Details</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="3"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<table width="100%">
|
||||
<tr>
|
||||
<td style="width: 25%;">Subject</td>
|
||||
<td style="width: 75%;" class="data"><?php echo $so->dn(); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Issuer</td>
|
||||
<td class="data"><?php echo $so->issuerdn(); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>CA</td>
|
||||
<td class="data"><?php echo $so->SSL_CA->loaded() ? $so->SSL_CA->subject() : $so->issuer(); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Valid From</td>
|
||||
<td class="data"><?php echo $so->valid_from(TRUE); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Valid To</td>
|
||||
<td class="data"><?php echo $so->valid_to(TRUE); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Serial Number</td>
|
||||
<td class="data"><?php echo $so->serial(); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Version</td>
|
||||
<td class="data"><?php echo $so->version(); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Hash</td>
|
||||
<td class="data"><?php echo $so->hash(); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Algorithm</td>
|
||||
<td class="data"><?php echo $so->algorithm(); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Certificate</td>
|
||||
<td class="data"><pre><?php echo $so->cert; ?></pre></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td style="text-align: right;"><?php echo $so->download_button(); ?></td>
|
||||
</tr>
|
||||
</table>
|
||||
<fieldset class="span5">
|
||||
<legend>Service Details</legend>
|
||||
|
||||
<div class="dl-horizontal">
|
||||
|
||||
<dt>Subject</dt>
|
||||
<dd><?php echo $o->dn(); ?></dd>
|
||||
|
||||
<dt>Issuer</dt>
|
||||
<dd><?php echo $o->issuerdn(); ?></dd>
|
||||
|
||||
<dt>CA</dt>
|
||||
<dd><?php echo $o->SSL_CA->loaded() ? $o->SSL_CA->subject() : $o->issuer(); ?></dd>
|
||||
|
||||
<dt>Valid From</dt>
|
||||
<dd><?php echo $o->valid_from(TRUE); ?></dd>
|
||||
|
||||
<dt>Valid To</dt>
|
||||
<dd><?php echo $o->valid_to(TRUE); ?></dd>
|
||||
|
||||
<dt>Serial Number</dt>
|
||||
<dd><?php echo $o->serial(); ?></dd>
|
||||
|
||||
<dt>Version</dt>
|
||||
<dd><?php echo $o->version(); ?></dd>
|
||||
|
||||
<dt>Hash</dt>
|
||||
<dd><?php echo $o->hash(); ?></dd>
|
||||
|
||||
<dt>Algorithm</dt>
|
||||
<dd><?php echo $o->algorithm(); ?></dd>
|
||||
|
||||
</div> <!-- dl-horizontal -->
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="span6">
|
||||
<legend>Certificate</legend>
|
||||
<pre><?php echo $o->cert; ?></pre>
|
||||
|
||||
<?php echo $o->download_button(); ?>
|
||||
</fieldset>
|
||||
|
Reference in New Issue
Block a user