OSB enhancements to date
This commit is contained in:
36
modules/adsl/adsl.inc.php
Normal file
36
modules/adsl/adsl.inc.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/*
|
||||
* osBilling - Open Billing Software
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Originally authored by Deon George
|
||||
*
|
||||
* @author Deon George <deonATleenooksDOTnet>
|
||||
* @copyright 2009 Deon George
|
||||
* @link http://osb.leenooks.net
|
||||
* @license http://www.gnu.org/licenses/
|
||||
* @package AgileBill
|
||||
* @subpackage Modules:ADSL
|
||||
*/
|
||||
|
||||
/**
|
||||
* This class provides the ability to define ADSL Supplier Products.
|
||||
*
|
||||
* @package osBilling
|
||||
* @subpackage Modules:ADSL
|
||||
*/
|
||||
class adsl extends OSB_module {
|
||||
}
|
||||
?>
|
153
modules/adsl/adsl_construct.xml
Normal file
153
modules/adsl/adsl_construct.xml
Normal file
@@ -0,0 +1,153 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||
<construct>
|
||||
<module>adsl</module>
|
||||
<table>adsl</table>
|
||||
<dependancy></dependancy>
|
||||
<cache>0</cache>
|
||||
<order_by>product_desc</order_by>
|
||||
<limit>35</limit>
|
||||
|
||||
<!-- Page Display Titles -->
|
||||
<title>
|
||||
<add>Add ADSL</add>
|
||||
<view>ADSL</view>
|
||||
</title>
|
||||
|
||||
<field>
|
||||
<id>
|
||||
<type>I8</type>
|
||||
<unique>1</unique>
|
||||
</id>
|
||||
<site_id>
|
||||
<type>I4</type>
|
||||
</site_id>
|
||||
<date_orig>
|
||||
<type>I8</type>
|
||||
<convert>date-now</convert>
|
||||
</date_orig>
|
||||
<date_last>
|
||||
<type>I8</type>
|
||||
<convert>date-now</convert>
|
||||
</date_last>
|
||||
<status>
|
||||
<display>Active</display>
|
||||
<type>L</type>
|
||||
</status>
|
||||
<supplier_id>
|
||||
<display>Supplier</display>
|
||||
<type>I4</type>
|
||||
<asso_table>adsl_supplier</asso_table>
|
||||
<asso_field>name</asso_field>
|
||||
<validate>any</validate>
|
||||
</supplier_id>
|
||||
<product_id>
|
||||
<display>Product ID</display>
|
||||
<type>C(16)</type>
|
||||
<min_len>1</min_len>
|
||||
<max_len>16</max_len>
|
||||
</product_id>
|
||||
<product_desc>
|
||||
<display>Product Description</display>
|
||||
<type>C(128)</type>
|
||||
<min_len>1</min_len>
|
||||
<max_len>128</max_len>
|
||||
</product_desc>
|
||||
<base_cost>
|
||||
<display>Base Cost</display>
|
||||
<type>F</type>
|
||||
</base_cost>
|
||||
<contract_term>
|
||||
<description>Contract Term in Months</description>
|
||||
<display>Contract Term</display>
|
||||
<type>I4</type>
|
||||
</contract_term>
|
||||
<base_down_peak>
|
||||
<display>Peak Downloads (MB)</display>
|
||||
<type>F</type>
|
||||
</base_down_peak>
|
||||
<base_up_peak>
|
||||
<display>Peak Uploads (MB)</display>
|
||||
<type>F</type>
|
||||
</base_up_peak>
|
||||
<base_down_offpeak>
|
||||
<display>OffPeak Downloads (MB)</display>
|
||||
<type>F</type>
|
||||
</base_down_offpeak>
|
||||
<base_up_offpeak>
|
||||
<display>OffPeak Uploads (MB)</display>
|
||||
<type>F</type>
|
||||
</base_up_offpeak>
|
||||
<extra_charged>
|
||||
<display>Charge Extra Traffic</display>
|
||||
<type>L</type>
|
||||
</extra_charged>
|
||||
<extra_shaped>
|
||||
<display>Shaping speed for extra traffic</display>
|
||||
<type>C(8)</type>
|
||||
</extra_shaped>
|
||||
<offpeak_start>
|
||||
<display>Offpeak Start</display>
|
||||
<type>I8</type>
|
||||
<convert>time</convert>
|
||||
</offpeak_start>
|
||||
<offpeak_end>
|
||||
<display>Offpeak End</display>
|
||||
<type>I8</type>
|
||||
<convert>time</convert>
|
||||
</offpeak_end>
|
||||
<extra_down_peak>
|
||||
<display>Peak Downloads Rate ($/MB)</display>
|
||||
<type>F</type>
|
||||
</extra_down_peak>
|
||||
<extra_up_peak>
|
||||
<display>Peak Uploads Rate ($/MB)</display>
|
||||
<type>F</type>
|
||||
</extra_up_peak>
|
||||
<extra_down_offpeak>
|
||||
<display>OffPeak Downloads Rate ($/MB)</display>
|
||||
<type>F</type>
|
||||
</extra_down_offpeak>
|
||||
<extra_up_offpeak>
|
||||
<display>OffPeak Uploads Rate ($/MB)</display>
|
||||
<type>F</type>
|
||||
</extra_up_offpeak>
|
||||
</field>
|
||||
|
||||
<method>
|
||||
<add>supplier_id,product_id,product_desc</add>
|
||||
<update>id,date_last,status,product_id,product_desc,base_cost,contract_term,base_down_peak,base_up_peak,base_down_offpeak,base_up_offpeak,extra_charged,extra_shaped,offpeak_start,offpeak_end,extra_down_peak,extra_up_peak,extra_down_offpeak,extra_up_offpeak</update>
|
||||
<delete>id</delete>
|
||||
<view>id,status,supplier_id,product_id,product_desc,base_cost,contract_term,base_down_peak,base_up_peak,base_down_offpeak,base_up_offpeak,extra_charged,extra_shaped,offpeak_start,offpeak_end,extra_down_peak,extra_up_peak,extra_down_offpeak,extra_up_offpeak</view>
|
||||
<search>id,date_orig,date_last,status,supplier_id,product_id,product_desc,base_cost</search>
|
||||
</method>
|
||||
|
||||
<index>
|
||||
<adsls>id,site_id</adsls>
|
||||
<asso>supplier_id</asso>
|
||||
<service>service_id</service>
|
||||
<adsl>product</adsl>
|
||||
</index>
|
||||
|
||||
<trigger>0</trigger>
|
||||
|
||||
<!-- Template Helpers -->
|
||||
<tpl>
|
||||
<search_show>
|
||||
<checkbox>
|
||||
<field>id</field>
|
||||
<type>checkbox</type>
|
||||
<width>25px</width>
|
||||
</checkbox>
|
||||
<supplier_id>
|
||||
<field>supplier_id</field>
|
||||
</supplier_id>
|
||||
<product_id>
|
||||
<field>product_id</field>
|
||||
</product_id>
|
||||
<base_cost>
|
||||
<field>base_cost</field>
|
||||
<type>currency</type>
|
||||
</base_cost>
|
||||
</search_show>
|
||||
</tpl>
|
||||
</construct>
|
55
modules/adsl/adsl_install.xml
Normal file
55
modules/adsl/adsl_install.xml
Normal file
@@ -0,0 +1,55 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||
<install>
|
||||
<!-- Tree Menu Module Properties -->
|
||||
<module_properties>
|
||||
<!-- MODULE Dependancy, this module wont be installed if the dependant modules dont exist -->
|
||||
<dependancy></dependancy>
|
||||
<!-- Translated display to use on the tree -->
|
||||
<display>ADSL</display>
|
||||
<!-- Display a module in the menu tree -->
|
||||
<menu_display>1</menu_display>
|
||||
<!-- MODULE Name -->
|
||||
<name>adsl</name>
|
||||
<!-- MODULE Notes, these notes show up in the modules table, as a description of the module -->
|
||||
<notes><![CDATA[This module records the ADSL supplier products]]></notes>
|
||||
<!-- MODULE Parent, the parent node in the tree -->
|
||||
<parent>adsl</parent>
|
||||
<!-- SUB Modules to install with this one -->
|
||||
<sub_modules>adsl_supplier</sub_modules>
|
||||
<!-- MODULE Type (core|base), core modules cannot be deleted, unrecognised types are ignored. -->
|
||||
<type></type>
|
||||
</module_properties>
|
||||
|
||||
<!-- Tree Menu & Module Methods to load, they will be assigned the group permissions on install time, as selected by the user. -->
|
||||
<module_method>
|
||||
<add>
|
||||
<display>Add</display>
|
||||
<menu_display>1</menu_display>
|
||||
<name>add</name>
|
||||
<notes><![CDATA[Add records]]></notes>
|
||||
</add>
|
||||
<delete>
|
||||
<name>delete</name>
|
||||
<notes><![CDATA[Delete records]]></notes>
|
||||
</delete>
|
||||
<search>
|
||||
<display>Search</display>
|
||||
<menu_display>1</menu_display>
|
||||
<name>search</name>
|
||||
<notes><![CDATA[List records]]></notes>
|
||||
<page><![CDATA[core:search&module=%%&_next_page_one=view]]></page>
|
||||
</search>
|
||||
<search_show>
|
||||
<name>search_show</name>
|
||||
<notes><![CDATA[Show the results of a search]]></notes>
|
||||
</search_show>
|
||||
<update>
|
||||
<name>update</name>
|
||||
<notes><![CDATA[Update a record]]></notes>
|
||||
</update>
|
||||
<view>
|
||||
<name>view</name>
|
||||
<notes><![CDATA[View a record]]></notes>
|
||||
</view>
|
||||
</module_method>
|
||||
</install>
|
151
modules/adsl/classes/adsl.php
Normal file
151
modules/adsl/classes/adsl.php
Normal file
@@ -0,0 +1,151 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class looks after ADSL products
|
||||
*
|
||||
* @package OSB
|
||||
* @subpackage Product
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Deon George
|
||||
* @license http://dev.leenooks.net/license.html
|
||||
*/
|
||||
class ADSL {
|
||||
// Map the table fields
|
||||
static $map = array(
|
||||
'base_up_offpeak'=>'extra_up_offpeak',
|
||||
'base_down_offpeak'=>'extra_down_offpeak',
|
||||
'base_up_peak'=>'extra_up_peak',
|
||||
'base_down_peak'=>'extra_down_peak',
|
||||
);
|
||||
|
||||
/**
|
||||
* Return an instance of this class
|
||||
*
|
||||
* @return ADSL
|
||||
*/
|
||||
public static function instance() {
|
||||
return new ADSL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the additional information used by product_view
|
||||
*/
|
||||
public function product_view($data) {
|
||||
// @todo - this test shouldnt be required
|
||||
if (preg_match('/^a:/',$data))
|
||||
throw new Kohana_Exception('Data shouldnt be a serialized array');
|
||||
|
||||
$ao = ORM::factory('adsl_plan',$data);
|
||||
|
||||
$output = View::factory('adsl/product_view')
|
||||
->set('record',$ao);
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
public function contract_view($data,$price_base,$price_setup) {
|
||||
// @todo - this test shouldnt be required
|
||||
if (preg_match('/^a:/',$data))
|
||||
throw new Kohana_Exception('Data shouldnt be a serialized array');
|
||||
|
||||
$ao = ORM::factory('adsl_plan',$data);
|
||||
$output = View::factory('adsl/contract_view')
|
||||
->set('record',$ao)
|
||||
->set('price_base',$price_base)
|
||||
->set('price_setup',$price_setup);
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect information for the cart
|
||||
*/
|
||||
public function product_cart() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Map the metric fields to their excess rate
|
||||
*/
|
||||
public static function map($metric) {
|
||||
return ADSL::$map[$metric];
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the allowance array or traffic used array
|
||||
*
|
||||
* If:
|
||||
* + UPLOADS are charged and there are no PEAK/OFFPEAK periods (therefore all
|
||||
* traffic is charged), the allowance will be shown as 1 metric - TRAFFIC.
|
||||
* + UPLOADS are charged and there are PEAK/OFFPEAK periods the allowance
|
||||
* will be shown as 2 metrics - PEAK/OFFPEAK.
|
||||
* + UPLOADS are NOT charged and there are no PEAK/OFFPEAK periods the allowance
|
||||
* will be shown as 1 metrics - TRAFFIC.
|
||||
* + UPLOADS are NOT charged and there are PEAK/OFFPEAK periods the allowance
|
||||
* will be shown as 2 metrics - PEAK/OFFPEAK.
|
||||
*
|
||||
* Thus:
|
||||
* + If base_x_Y is NULL, all Y traffic is FREE (ignore respective extra_x_Y setting).
|
||||
* + If base_x_Y is a number, all Y traffic is FREE up to the number (evaluate extra_x_Y setting).
|
||||
* + If extra_x_Y is a number, charge this amount for traffic over base_x_Y.
|
||||
* + If extra_down_peak is NULL this is invalid, treat base_down_peak as NULL
|
||||
* + If extra_down_offpeak is NULL add traffic_down_offpeak to traffic_down_peak
|
||||
* + If extra_up_peak is NULL add traffic_up_peak to traffic_down_peak
|
||||
* + If extra_up_offpeak is NULL add traffic_up_offpeak to traffic_down_offpeak
|
||||
*
|
||||
* @param array $plan - the allowance plan
|
||||
*/
|
||||
public static function allowance($plan) {
|
||||
// Map the NULL relationships
|
||||
$extras = array(
|
||||
'extra_up_offpeak'=>'base_down_offpeak',
|
||||
'extra_down_offpeak'=>'base_down_peak',
|
||||
'extra_up_peak'=>'base_down_peak',
|
||||
'extra_down_peak'=>'base_down_peak',
|
||||
);
|
||||
|
||||
// Work out if we charge each period
|
||||
$a = array();
|
||||
if (! isset($plan['extra_down_peak']) OR is_null($plan['extra_down_peak']))
|
||||
$a['base_down_peak'] = 0;
|
||||
|
||||
foreach (ADSL::$map as $k => $v) {
|
||||
// Work through attributes we count.
|
||||
if (isset($plan[$k]) AND ! is_null($plan[$k])) {
|
||||
|
||||
// Work through attributes that are merged
|
||||
if (! isset($plan[$v]) OR is_null($plan[$v])) {
|
||||
|
||||
if (isset($a[$k])) {
|
||||
if (isset($a[$extras[$v]]))
|
||||
$a[$extras[$v]] += $a[$k];
|
||||
else
|
||||
$a[$extras[$v]] = $a[$k];
|
||||
|
||||
unset($a[$k]);
|
||||
}
|
||||
|
||||
if (isset($a[$extras[$v]]))
|
||||
$a[$extras[$v]] += $plan[$k];
|
||||
else
|
||||
$a[$extras[$v]] = $plan[$k];
|
||||
|
||||
} else {
|
||||
if (isset($a[$k]))
|
||||
$a[$k] += $plan[$k];
|
||||
else
|
||||
$a[$k] = $plan[$k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return the output sorted
|
||||
$return = array();
|
||||
foreach (array('base_down_peak','base_down_offpeak','base_up_peak','base_up_offpeak') as $k)
|
||||
if (isset($a[$k]))
|
||||
$return[$k] = $a[$k];
|
||||
|
||||
return $return;
|
||||
}
|
||||
}
|
||||
?>
|
59
modules/adsl/classes/model/adsl/plan.php
Normal file
59
modules/adsl/classes/model/adsl/plan.php
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class supports ADSL Plans
|
||||
*
|
||||
* @package OSB
|
||||
* @subpackage ADSL
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_ADSL_Plan extends ORMOSB {
|
||||
// Relationships
|
||||
protected $_belongs_to = array(
|
||||
'adsl_supplier_plan'=>array(),
|
||||
);
|
||||
protected $_has_many = array(
|
||||
'service'=>array('through'=>'service__adsl'),
|
||||
);
|
||||
|
||||
protected $_formats = array(
|
||||
'extra_down_peak'=>array(
|
||||
'Tax::add'=>array(),
|
||||
'Currency::display'=>array(),
|
||||
),
|
||||
'extra_down_offpeak'=>array(
|
||||
'Tax::add'=>array(),
|
||||
'Currency::display'=>array(),
|
||||
),
|
||||
'extra_up_peak'=>array(
|
||||
'Tax::add'=>array(),
|
||||
'Currency::display'=>array(),
|
||||
),
|
||||
'extra_up_offpeak'=>array(
|
||||
'Tax::add'=>array(),
|
||||
'Currency::display'=>array(),
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* Show the ADSL allowance as a peak/offpeak metric
|
||||
*/
|
||||
public function allowance($string=TRUE) {
|
||||
$output = ADSL::allowance(array(
|
||||
'base_down_peak'=>$this->base_down_peak,
|
||||
'base_down_offpeak'=>$this->base_down_offpeak,
|
||||
'base_up_peak'=>$this->base_up_peak,
|
||||
'base_up_offpeak'=>$this->base_up_offpeak,
|
||||
'extra_down_peak'=>$this->extra_down_peak,
|
||||
'extra_down_offpeak'=>$this->extra_down_offpeak,
|
||||
'extra_up_peak'=>$this->extra_up_peak,
|
||||
'extra_up_offpeak'=>$this->extra_up_offpeak,
|
||||
));
|
||||
|
||||
return $string ? implode('/',$output) : $output;
|
||||
}
|
||||
}
|
||||
?>
|
40
modules/adsl/classes/model/adsl/supplier.php
Normal file
40
modules/adsl/classes/model/adsl/supplier.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class supports ADSL Suppliers
|
||||
*
|
||||
* @package OSB
|
||||
* @subpackage ADSL
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_ADSL_Supplier extends ORMOSB {
|
||||
// Relationships
|
||||
protected $_has_many = array(
|
||||
'adsl_supplier_plan'=>array('foreign_key'=>'supplier_id'),
|
||||
);
|
||||
|
||||
protected $_updated_column = FALSE;
|
||||
|
||||
/**
|
||||
* Return a list of services for this supplier
|
||||
*
|
||||
* @param boolean $active TRUE List only active Services|False List all services
|
||||
*/
|
||||
public function services($active=TRUE) {
|
||||
$services = array();
|
||||
|
||||
// Get a list of plans made for this supplier
|
||||
foreach ($this->adsl_supplier_plan->find_all() as $aspo)
|
||||
// Find all the plan who use this supplier plan
|
||||
foreach ($aspo->adsl_plan->find_all() as $apo)
|
||||
// Find all the services who use this plan
|
||||
foreach ($apo->service->find_all() as $so)
|
||||
array_push($services,$so);
|
||||
|
||||
return $services;
|
||||
}
|
||||
}
|
||||
?>
|
39
modules/adsl/classes/model/adsl/supplier/plan.php
Normal file
39
modules/adsl/classes/model/adsl/supplier/plan.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class supports ADSL Plans
|
||||
*
|
||||
* @package OSB
|
||||
* @subpackage ADSL
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_ADSL_Supplier_Plan extends ORMOSB {
|
||||
// Relationships
|
||||
protected $_has_many = array(
|
||||
'adsl_plan'=>array(),
|
||||
);
|
||||
protected $_belongs_to = array(
|
||||
'adsl_supplier'=>array('foreign_key'=>'supplier_id'),
|
||||
);
|
||||
|
||||
/**
|
||||
* Show the ADSL allowance as a peak/offpeak metric
|
||||
*/
|
||||
public function allowance() {
|
||||
return sprintf('%s/%s',$this->base_down_peak+$this->base_up_peak,$this->base_down_offpeak+$this->base_up_offpeak);
|
||||
}
|
||||
|
||||
public function tax() {
|
||||
// @todo This should be taken from the users session
|
||||
// @todo rounding should be a system default
|
||||
return round($this->base_cost*.1,2);
|
||||
}
|
||||
|
||||
public function name() {
|
||||
return $this->product_id;
|
||||
}
|
||||
}
|
||||
?>
|
12
modules/adsl/views/adsl/contract_view.php
Normal file
12
modules/adsl/views/adsl/contract_view.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<!-- //@todo To translate -->
|
||||
<table class="box-full">
|
||||
<tr>
|
||||
<td style="width: 60%;">Contract Term</td>
|
||||
<td class="head" colspan="2"><?php echo $record->display('contract_term'); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<!-- @todo This should get tax settings from the session -->
|
||||
<td>Minimum Cost</td>
|
||||
<td class="head" colspan="2"><?php echo Currency::display(Tax::add($record->contract_term*$price_base+$price_setup)); ?> <span style="font-size: 80%; font-weight:normal;"><?php printf('(%s * %s + %s)',$record->contract_term,Tax::add($price_base),Tax::add($price_setup)); ?></span></td>
|
||||
</tr>
|
||||
</table>
|
26
modules/adsl/views/adsl/product_view.php
Normal file
26
modules/adsl/views/adsl/product_view.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<!-- //@todo To translate -->
|
||||
<table class="box-full">
|
||||
<tr>
|
||||
<td style="width: 60%;">Speed</td>
|
||||
<td class="head" colspan="2"><?php echo $record->display('speed'); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td>Peak</td>
|
||||
<td>Off Peak</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Included Download Traffic</td>
|
||||
<!-- // @todo Since price is stored in the DB in GB, so should the traffic. -->
|
||||
<td class="head"><?php echo $record->base_down_peak/1000; ?> GB</td>
|
||||
<td class="head"><?php echo $record->base_down_offpeak/1000; ?> GB</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Extra Download Traffic</td>
|
||||
<td class="head"><?php echo $record->display('extra_down_peak'); ?>/GB</td>
|
||||
<td class="head"><?php echo $record->display('extra_down_offpeak'); ?>/GB</td>
|
||||
</tr>
|
||||
</table>
|
Reference in New Issue
Block a user