Minor fixes to statement, services and internal things
Many misc updates
This commit is contained in:
@@ -82,10 +82,10 @@ class Model_Service_Plugin_ADSL extends Model_Service_Plugin {
|
||||
/**
|
||||
* Calculate the total traffic used in a month
|
||||
*/
|
||||
private function get_traffic_data_month($period=NULL) {
|
||||
private function get_traffic_data_month($period=NULL,$cache=NULL) {
|
||||
$return = array();
|
||||
|
||||
foreach ($this->get_traffic_data_daily($period,TRUE) as $tdata)
|
||||
foreach ($this->get_traffic_data_daily($period,TRUE,$cache) as $tdata)
|
||||
foreach ($tdata as $k => $v)
|
||||
if (isset($return[$k]))
|
||||
$return[$k] += $v;
|
||||
@@ -98,49 +98,30 @@ class Model_Service_Plugin_ADSL extends Model_Service_Plugin {
|
||||
/**
|
||||
* Return an array of the data used in a month by day
|
||||
*/
|
||||
public function get_traffic_data_daily($period=NULL,$bydate=FALSE) {
|
||||
$cacheable = TRUE;
|
||||
public function get_traffic_data_daily($period=NULL,$bydate=FALSE,$cache=NULL) {
|
||||
$return = array();
|
||||
|
||||
// @temp - caching is broken?
|
||||
$cache=0;
|
||||
if (is_null($period))
|
||||
$period = strtotime('yesterday');
|
||||
|
||||
$cache = $this->service_id.date('M-Y',$period).$bydate;
|
||||
|
||||
// @todo This cache needs to be improved, so that we cache the query regardless of bydate setting
|
||||
if ($cacheable AND $return = Cache::instance(Config::cachetype())->get($cache))
|
||||
return $return;
|
||||
|
||||
$return = array();
|
||||
|
||||
$to = ORM::factory('service_plugin_adsl_traffic')
|
||||
$t = ORM::factory('service_plugin_adsl_traffic')
|
||||
->where('service','=',$this->service_username)
|
||||
->and_where('date','>=',date('Y-m-d',mktime(0,0,0,date('m',$period),1,date('Y',$period))))
|
||||
->and_where('date','<=',date('Y-m-d',strtotime('last day of '.date('M Y',$period))));
|
||||
->and_where('date','<=',date('Y-m-d',strtotime('last day of '.date('M Y',$period))))
|
||||
->cached($cache);
|
||||
|
||||
foreach ($to->find_all() as $traffic) {
|
||||
// Roll up the charges according to the configuration
|
||||
$data = ADSL::allowance(array(
|
||||
'base_down_peak'=>is_null($this->service->product->plugin()->base_down_peak) ? NULL : $traffic->down_peak,
|
||||
'base_down_offpeak'=>is_null($this->service->product->plugin()->base_down_offpeak) ? NULL : $traffic->down_offpeak,
|
||||
'base_up_peak'=>is_null($this->service->product->plugin()->base_up_peak) ? NULL : $traffic->up_peak,
|
||||
'base_up_offpeak'=>is_null($this->service->product->plugin()->base_up_offpeak) ? NULL : $traffic->up_offpeak,
|
||||
'extra_down_peak'=>$this->service->product->plugin()->extra_down_peak,
|
||||
'extra_down_offpeak'=>$this->service->product->plugin()->extra_down_offpeak,
|
||||
'extra_up_peak'=>$this->service->product->plugin()->extra_up_peak,
|
||||
'extra_up_offpeak'=>$this->service->product->plugin()->extra_up_offpeak,
|
||||
));
|
||||
foreach ($t->find_all() as $to) {
|
||||
$day = date('d',strtotime($to->date));
|
||||
|
||||
$day = date('d',strtotime($traffic->date));
|
||||
if ($bydate)
|
||||
$return[$day] = $data;
|
||||
$return[$day] = $to->traffic($this->service->product->plugin());
|
||||
else
|
||||
foreach ($data as $k => $v)
|
||||
foreach ($to->traffic($this->service->product->plugin()) as $k => $v)
|
||||
$return[$k][$day] = $v;
|
||||
}
|
||||
|
||||
// Cache our data
|
||||
// @todo Our cache time should be a configuration parameter
|
||||
Cache::instance(Config::cachetype())->set($cache,$return,43200);
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
@@ -148,19 +129,12 @@ class Model_Service_Plugin_ADSL extends Model_Service_Plugin {
|
||||
* Return an array of the data used in a year by month
|
||||
*/
|
||||
public function get_traffic_data_monthly($period=NULL,$bydate=FALSE) {
|
||||
$cacheable = TRUE;
|
||||
$return = array();
|
||||
|
||||
if (is_null($period))
|
||||
$period = strtotime('yesterday');
|
||||
|
||||
$cache = $this->service_id.date('M-Y',$period).$bydate.__METHOD__;
|
||||
|
||||
// @todo This cache needs to be improved, so that we cache the query regardless of bydate setting
|
||||
if ($cacheable AND $return = Cache::instance(Config::cachetype())->get($cache))
|
||||
return $return;
|
||||
|
||||
$return = array();
|
||||
|
||||
$to = ORM::factory('service_plugin_adsl_traffic')
|
||||
$t = ORM::factory('service_plugin_adsl_traffic')
|
||||
->select(
|
||||
array('date_format(date,\'%y-%m\')','month'),
|
||||
array('sum(up_peak)','up_peak'),
|
||||
@@ -173,36 +147,19 @@ class Model_Service_Plugin_ADSL extends Model_Service_Plugin {
|
||||
->and_where('date','<=',date('Y-m-d',strtotime('last day of '.date('M Y',$period))))
|
||||
->group_by('date_format(date,\'%Y-%m\')');
|
||||
|
||||
foreach ($to->find_all() as $traffic) {
|
||||
// Roll up the charges according to the configuration
|
||||
$data = ADSL::allowance(array(
|
||||
'base_down_peak'=>is_null($this->service->product->plugin()->base_down_peak) ? NULL : $traffic->down_peak,
|
||||
'base_down_offpeak'=>is_null($this->service->product->plugin()->base_down_offpeak) ? NULL : $traffic->down_offpeak,
|
||||
'base_up_peak'=>is_null($this->service->product->plugin()->base_up_peak) ? NULL : $traffic->up_peak,
|
||||
'base_up_offpeak'=>is_null($this->service->product->plugin()->base_up_offpeak) ? NULL : $traffic->up_offpeak,
|
||||
'extra_down_peak'=>$this->service->product->plugin()->extra_down_peak,
|
||||
'extra_down_offpeak'=>$this->service->product->plugin()->extra_down_offpeak,
|
||||
'extra_up_peak'=>$this->service->product->plugin()->extra_up_peak,
|
||||
'extra_up_offpeak'=>$this->service->product->plugin()->extra_up_offpeak,
|
||||
));
|
||||
|
||||
foreach ($t->find_all() as $to)
|
||||
if ($bydate)
|
||||
$return[$traffic->month] = $data;
|
||||
$return[$to->month] = $to->traffic($this->service->product->plugin());
|
||||
else
|
||||
foreach ($data as $k => $v)
|
||||
$return[$k][$traffic->month] = $v;
|
||||
}
|
||||
|
||||
// Cache our data
|
||||
// @todo Our cache time should be a configuration parameter
|
||||
Cache::instance(Config::cachetype())->set($cache,$return,43200);
|
||||
foreach ($to->traffic($this->service->product->plugin()) as $k => $v)
|
||||
$return[$k][$to->month] = $v;
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
public function traffic_month($month,$string=TRUE) {
|
||||
return $string ? implode('/',$this->get_traffic_data_month($month)) :
|
||||
$this->get_traffic_data_month($month);
|
||||
public function traffic_month($month,$string=TRUE,$cache=NULL) {
|
||||
return $string ? implode('/',$this->get_traffic_data_month($month,$cache)) :
|
||||
$this->get_traffic_data_month($month,$cache);
|
||||
}
|
||||
|
||||
public function traffic_lastmonth($string=TRUE) {
|
||||
@@ -218,9 +175,9 @@ class Model_Service_Plugin_ADSL extends Model_Service_Plugin {
|
||||
$return = array();
|
||||
|
||||
if (is_null($date))
|
||||
$date = strtotime('last month');
|
||||
$date = strtotime('last month')-86400;
|
||||
|
||||
foreach ($this->traffic_month($date,FALSE) as $k => $v) {
|
||||
foreach ($this->traffic_month($date,FALSE,0) as $k => $v) {
|
||||
// We shouldnt need to eval for nulls, since the traffic calc does that
|
||||
if ($all OR ($v > $this->service->product->plugin()->$k)) {
|
||||
$return[$k]['allowance'] = $this->service->product->plugin()->$k;
|
||||
|
@@ -25,5 +25,19 @@ class Model_Service_Plugin_ADSL_Traffic extends ORMOSB {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
public function traffic(Model_Product_Plugin_ADSL $plan) {
|
||||
// Roll up the charges according to the product plan configuration
|
||||
return ADSL::allowance(array(
|
||||
'base_down_peak'=>is_null($plan->base_down_peak) ? NULL : $this->down_peak,
|
||||
'base_down_offpeak'=>is_null($plan->base_down_offpeak) ? NULL : $this->down_offpeak,
|
||||
'base_up_peak'=>is_null($plan->base_up_peak) ? NULL : $this->up_peak,
|
||||
'base_up_offpeak'=>is_null($plan->base_up_offpeak) ? NULL : $this->up_offpeak,
|
||||
'extra_down_peak'=>$plan->extra_down_peak,
|
||||
'extra_down_offpeak'=>$plan->extra_down_offpeak,
|
||||
'extra_up_peak'=>$plan->extra_up_peak,
|
||||
'extra_up_offpeak'=>$plan->extra_up_offpeak,
|
||||
));
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
@@ -43,8 +43,8 @@ class Service_Traffic_ADSL_ExetelPE extends Service_Traffic_ADSL {
|
||||
// Start Session
|
||||
$request = Request::factory($this->so->stats_url)
|
||||
->method('POST')
|
||||
->post($this->login_user_field,$so->plugin()->service_username)
|
||||
->post($this->login_pass_field,$so->plugin()->service_password)
|
||||
->post($this->login_user_field,$so->plugin()->service_username == NULL ? '' : $so->plugin()->service_username)
|
||||
->post($this->login_pass_field,$so->plugin()->service_password == NULL ? '' : $so->plugin()->service_password)
|
||||
->post('doLogin',1)
|
||||
->post('submit','Login');
|
||||
|
||||
|
134
modules/charge/classes/controller/admin/charge.php
Normal file
134
modules/charge/classes/controller/admin/charge.php
Normal file
@@ -0,0 +1,134 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class provides charge capabilities.
|
||||
*
|
||||
* @package OSB
|
||||
* @subpackage Charge
|
||||
* @category Controllers/Admin
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Admin_Charge extends Controller_TemplateDefault_Admin {
|
||||
protected $secure_actions = array(
|
||||
'add'=>TRUE,
|
||||
'list'=>TRUE,
|
||||
'auditinvoiceitems'=>TRUE,
|
||||
);
|
||||
|
||||
/**
|
||||
* Show a list of invoices
|
||||
*/
|
||||
public function action_list() {
|
||||
Block::add(array(
|
||||
'title'=>_('Customer Charges'),
|
||||
'body'=>Table::display(
|
||||
ORM::factory('charge')->where('sweep_type','>=',0)->order_by('date_orig DESC')->find_all(),
|
||||
25,
|
||||
array(
|
||||
'id'=>array('label'=>'ID','url'=>'user/charge/view/'),
|
||||
'date_orig'=>array('label'=>'Date'),
|
||||
'sweep_type'=>array('label'=>'Sweep'),
|
||||
'status'=>array('label'=>'Status'),
|
||||
'quantity'=>array('label'=>'Quantity','class'=>'right'),
|
||||
'amount'=>array('label'=>'Total','class'=>'right'),
|
||||
'description'=>array('label'=>'Description'),
|
||||
'service_id'=>array('label'=>'Service'),
|
||||
'account->accnum()'=>array('label'=>'Cust ID'),
|
||||
'account->name()'=>array('label'=>'Customer'),
|
||||
'attributes'=>array('label'=>'Attributes'),
|
||||
),
|
||||
array(
|
||||
'page'=>TRUE,
|
||||
'type'=>'select',
|
||||
'form'=>'user/charge/view',
|
||||
)),
|
||||
));
|
||||
}
|
||||
|
||||
public function action_add() {
|
||||
$output = '';
|
||||
|
||||
$co = ORM::factory('charge');
|
||||
|
||||
if ($_POST) {
|
||||
// Trim down our attributes
|
||||
if (is_array($_POST['attributes']))
|
||||
foreach ($_POST['attributes'] as $k=>$v)
|
||||
if (! trim($v))
|
||||
unset($_POST['attributes'][$k]);
|
||||
|
||||
if ($co->values($_POST)->check()) {
|
||||
$co->status=0;
|
||||
|
||||
// Entry updated
|
||||
if (! $co->save())
|
||||
throw new Kohana_Exception('Unable to save charge');
|
||||
}
|
||||
}
|
||||
|
||||
$output .= Form::open();
|
||||
$output .= View::factory('charge/admin/add');
|
||||
$output .= Form::submit('submit','submit');
|
||||
$output .= Form::close();
|
||||
|
||||
Style::add(array(
|
||||
'type'=>'stdin',
|
||||
'data'=>'.ui-autocomplete-loading { background: white url("'.URL::site('media/img/ui-anim_basic_16x16.gif').'") right center no-repeat; }'
|
||||
));
|
||||
|
||||
Style::add(array(
|
||||
'type'=>'file',
|
||||
'data'=>'js/jquery.ui/css/smoothness/jquery-ui-1.8.16.custom.css',
|
||||
));
|
||||
|
||||
Script::add(array(
|
||||
'type'=>'file',
|
||||
'data'=>'js/jquery-ui-1.8.16.custom.min.js',
|
||||
));
|
||||
|
||||
Script::add(array('type'=>'stdin','data'=>'
|
||||
$(document).ready(function() {
|
||||
$("input[name=account_id]").autocomplete({
|
||||
source: "'.URL::site('admin/account/autocomplete').'",
|
||||
minLength: 2,
|
||||
change: function(event,ui) {
|
||||
// Send the request and update sub category dropdown
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
data: "aid="+$(this).val(),
|
||||
dataType: "json",
|
||||
cache: false,
|
||||
url: "'.URL::site('admin/service/autolist').'",
|
||||
timeout: 2000,
|
||||
error: function() {
|
||||
alert("Failed to submit");
|
||||
},
|
||||
success: function(data) {
|
||||
// Clear all options from sub category select
|
||||
$("select[name=service_id] option").remove();
|
||||
|
||||
// Prepopulate a blank
|
||||
var row = "<option value=\"\"> </option>";
|
||||
$(row).appendTo("select[name=service_id]");
|
||||
|
||||
// Fill sub category select
|
||||
$.each(data, function(i, j){
|
||||
var row = "<option value=\"" + j.value + "\">" + j.text + "</option>";
|
||||
$(row).appendTo("select[name=service_id]");
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});'
|
||||
));
|
||||
|
||||
Block::add(array(
|
||||
'title'=>_('Add Customer Charges'),
|
||||
'body'=>$output,
|
||||
));
|
||||
}
|
||||
}
|
||||
?>
|
@@ -11,19 +11,37 @@
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_Charge extends ORMOSB {
|
||||
// Charge doesnt use the update column
|
||||
protected $_updated_column = FALSE;
|
||||
|
||||
protected $_belongs_to = array(
|
||||
'account'=>array(),
|
||||
);
|
||||
|
||||
protected $_display_filters = array(
|
||||
'date_orig'=>array(
|
||||
array('Config::date',array(':value')),
|
||||
),
|
||||
'amount'=>array(
|
||||
'Currency::display',array(':value')
|
||||
array('Currency::display',array(':value')),
|
||||
),
|
||||
);
|
||||
|
||||
public function rules() {
|
||||
return array_merge(parent::rules(),array(
|
||||
'attributes'=>array(
|
||||
array('ORMOSB::serialize_array',array(':model',':field',':value')),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Render some details for specific calls, eg: invoice
|
||||
*/
|
||||
public function details($type) {
|
||||
switch ($type) {
|
||||
case 'invoice':
|
||||
return sprintf('%s (%s@%s)',$this->description,$this->quantity,Currency::display($this->amount));
|
||||
case 'invoice_detail_items':
|
||||
return array('Other Charge'=>sprintf('%s (%s@%s)',$this->description,$this->quantity,Currency::display($this->amount)));
|
||||
|
||||
default:
|
||||
throw new Kohana_Exception('Unkown detail request :type',array(':type'=>$type));
|
||||
|
@@ -12,7 +12,8 @@
|
||||
*/
|
||||
class Model_Checkout extends ORMOSB {
|
||||
protected $_has_many = array(
|
||||
'payment' => array()
|
||||
'account'=>array('through'=>'account_billing','foreign_key'=>'checkout_plugin_id'),
|
||||
'payment'=>array(),
|
||||
);
|
||||
|
||||
/**
|
||||
|
@@ -13,77 +13,48 @@
|
||||
class Controller_Admin_Export extends Controller_TemplateDefault_Admin {
|
||||
protected $control_title = 'Export';
|
||||
protected $secure_actions = array(
|
||||
'index'=>TRUE,
|
||||
'export'=>TRUE,
|
||||
'add'=>TRUE,
|
||||
'edit'=>TRUE,
|
||||
);
|
||||
|
||||
/**
|
||||
* Export plugins must define an export action.
|
||||
* Add Export Maping items
|
||||
*/
|
||||
public function action_export() {
|
||||
if (empty($_POST['plugin']))
|
||||
$this->request->redirect('admin/export');
|
||||
public function action_add() {
|
||||
$eo = ORM::factory('export');
|
||||
$output = '';
|
||||
|
||||
$sc = sprintf('Export_%s',$_POST['plugin']);
|
||||
if (! class_exists($sc))
|
||||
throw new Kohana_Exception('Export Class doesnt exist for :plugin',array(':plugin'=>$_POST['plugin']));
|
||||
else
|
||||
$export = new $sc;
|
||||
if ($_POST AND $eo->values($_POST)->check()) {
|
||||
$eo->module_id = ORM::factory('module',array('name'=>'product'))->id; // @todo This probably should be in the form.
|
||||
$eo->plugin_name = 'quicken'; // @todo This should be in the form.
|
||||
// Entry updated
|
||||
if (! $eo->save())
|
||||
throw new Kohana_Exception('Unable to save data :post',array(':post'=>serialize($_POST)));
|
||||
|
||||
$export->export();
|
||||
SystemMessage::add(array(
|
||||
'title'=>_('Record add'),
|
||||
'type'=>'info',
|
||||
'body'=>_('Export Map entry added.')
|
||||
));
|
||||
}
|
||||
|
||||
$output .= Form::open();
|
||||
$output .= View::factory('export/admin/map/add')
|
||||
->set('eo',$eo);
|
||||
|
||||
$output .= '<div>'.Form::submit('submit',_('Add'),array('class'=>'form_button')).'</div>';
|
||||
$output .= Form::close();
|
||||
|
||||
Block::add(array(
|
||||
'title'=>_('Add Export Map'),
|
||||
'body'=>$output,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the main call to export, providing a list of items to export and
|
||||
* setting up the page to call the export plugin when submitted.
|
||||
* Edit Export Maping items
|
||||
*/
|
||||
public function action_index($daysago) {
|
||||
// @todo this should come from a file list
|
||||
$TBRexportplugins = array('quicken'=>'Export to Quicken');
|
||||
|
||||
if (! $daysago)
|
||||
$daysago = 30;
|
||||
|
||||
$payments = ORM::factory('payment')
|
||||
->export($daysago);
|
||||
|
||||
if (count($payments)) {
|
||||
$output = Form::open(Request::current()->uri(array('action'=>'export')));
|
||||
$output .= '<table class="box-left">';
|
||||
|
||||
$output .= View::factory('export/payment/header')
|
||||
->set('plugins',$TBRexportplugins);
|
||||
|
||||
$i = 0;
|
||||
foreach ($payments as $payment) {
|
||||
$output .= View::factory('export/payment/body')
|
||||
->set('payment',$payment)
|
||||
->set('i',$i++%2);
|
||||
}
|
||||
|
||||
$output .= '</table>';
|
||||
$output .= Form::submit('submit','export',array('class'=>'form_button'));
|
||||
$output .= Form::close();
|
||||
|
||||
Style::add(array(
|
||||
'type'=>'file',
|
||||
'data'=>'css/list.css',
|
||||
));
|
||||
|
||||
Block::add(array(
|
||||
'title'=>_('Payments to Export'),
|
||||
'body'=>$output,
|
||||
));
|
||||
|
||||
# Nothing to export
|
||||
} else {
|
||||
SystemMessage::add(array(
|
||||
'title'=>_('No payments to export'),
|
||||
'type'=>'info',
|
||||
'body'=>sprintf(_('There are no payments within the last %s days (since %s) to show.'),
|
||||
$daysago,date(Kohana::config('osb')->get('date_format'),$daysago*86400+time())),
|
||||
));
|
||||
}
|
||||
public function action_edit() {
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
@@ -22,7 +22,7 @@ class Controller_Affiliate_Export extends Controller_TemplateDefault_Affiliate {
|
||||
*/
|
||||
public function action_export() {
|
||||
if (empty($_POST['plugin']))
|
||||
$this->request->redirect('affiliate/export');
|
||||
$this->request->redirect('affiliate/export/index');
|
||||
|
||||
$sc = sprintf('Export_%s',$_POST['plugin']);
|
||||
if (! class_exists($sc))
|
||||
@@ -38,43 +38,40 @@ class Controller_Affiliate_Export extends Controller_TemplateDefault_Affiliate {
|
||||
* This is the main call to export, providing a list of items to export and
|
||||
* setting up the page to call the export plugin when submitted.
|
||||
*/
|
||||
public function action_index($daysago) {
|
||||
public function action_index() {
|
||||
// @todo this should come from a file list
|
||||
$TBRexportplugins = array('quicken'=>'Export to Quicken');
|
||||
|
||||
if (! $daysago)
|
||||
$daysago = 30;
|
||||
|
||||
// @todo: Need to limit this to affiliate acounts
|
||||
$payments = ORM::factory('payment')
|
||||
->export($daysago);
|
||||
|
||||
if (count($payments)) {
|
||||
$output = Form::open(Request::current()->uri(array('action'=>'export')));
|
||||
$output .= '<table class="box-left">';
|
||||
|
||||
$output .= View::factory('export/payment/header')
|
||||
->set('plugins',$TBRexportplugins);
|
||||
|
||||
$i = 0;
|
||||
foreach ($payments as $payment) {
|
||||
$output .= View::factory('export/payment/body')
|
||||
->set('payment',$payment)
|
||||
->set('i',$i++%2);
|
||||
}
|
||||
|
||||
$output .= '</table>';
|
||||
$output .= Form::submit('submit','export',array('class'=>'form_button'));
|
||||
$output .= Form::close();
|
||||
|
||||
Style::add(array(
|
||||
'type'=>'file',
|
||||
'data'=>'css/list.css',
|
||||
));
|
||||
$p = ORM::factory('payment');
|
||||
|
||||
if ($p->find_all()->count()) {
|
||||
Block::add(array(
|
||||
'title'=>_('Payments to Export'),
|
||||
'body'=>$output,
|
||||
'body'=>Table::display(
|
||||
$p->find_all(),
|
||||
25,
|
||||
array(
|
||||
'id'=>array('label'=>'ID'),
|
||||
'date_payment'=>array('label'=>'Date'),
|
||||
'checkout->display("name")'=>array('label'=>'Method'),
|
||||
'account->accnum()'=>array('label'=>'Acc Num'),
|
||||
'account->name()'=>array('label'=>'Account'),
|
||||
'total_amt'=>array('label'=>'Total','class'=>'right'),
|
||||
'balance(TRUE)'=>array('label'=>'Balance','class'=>'right'),
|
||||
'invoicelist()'=>array('label'=>'Invoices'),
|
||||
),
|
||||
array(
|
||||
'page'=>TRUE,
|
||||
'type'=>'select',
|
||||
'form'=>'affiliate/export/export',
|
||||
'hidden'=>array(
|
||||
Form::hidden('plugin','quicken'),
|
||||
),
|
||||
'button'=>array(
|
||||
Form::submit('submit',_('Export'),array('class'=>'form_button')),
|
||||
),
|
||||
)),
|
||||
));
|
||||
|
||||
# Nothing to export
|
||||
|
@@ -12,16 +12,16 @@
|
||||
*/
|
||||
class Export_Quicken extends Export {
|
||||
public function export() {
|
||||
if (! empty($_POST['payment_id']) AND count($_POST['payment_id'])) {
|
||||
if (! empty($_POST['id']) AND count($_POST['id'])) {
|
||||
$qo = new Quicken;
|
||||
|
||||
foreach ($_POST['payment_id'] as $pid) {
|
||||
$mpo = ORM::factory('payment',$pid);
|
||||
foreach ($_POST['id'] as $pid) {
|
||||
$po = ORM::factory('payment',$pid);
|
||||
|
||||
if ($mpo->loaded()) {
|
||||
if ($po->loaded()) {
|
||||
$invoice_ids = array();
|
||||
|
||||
foreach ($mpo->payment_item->find_all() as $pio) {
|
||||
foreach ($po->payment_item->find_all() as $pio) {
|
||||
// If our invoice ID is not blank, then the payment was applied to an invoice
|
||||
if ($pio->invoice->id) {
|
||||
// Record our invoice IDs for the summary
|
||||
@@ -34,23 +34,23 @@ class Export_Quicken extends Export {
|
||||
$qio->CLEAR = 'N';
|
||||
$qio->TOPRINT = 'N';
|
||||
$qio->PAID = 'N';
|
||||
$qio->ADDR1 = $mpo->account->address1;
|
||||
$qio->ADDR2 = $mpo->account->address2;
|
||||
$qio->ADDR3 = sprintf('%s, %s %s',$mpo->account->city,$mpo->account->state,$mpo->account->zip);
|
||||
$qio->ADDR1 = $po->account->address1;
|
||||
$qio->ADDR2 = $po->account->address2;
|
||||
$qio->ADDR3 = sprintf('%s, %s %s',$po->account->city,$po->account->state,$po->account->zip);
|
||||
// @todo - should be configurable
|
||||
$qio->TERMS = '7 Days';
|
||||
// @todo - should be configurable
|
||||
$qio->INVTITLE = 'Graytech Hosting Invoice';
|
||||
$qio->INVTITLE = Company::name().' Invoice';
|
||||
// @todo - should be configurable
|
||||
$qio->INVMEMO = 'Thank you for using Graytech Hosting';
|
||||
$qio->INVMEMO = 'Thank you for using '.Company::name();
|
||||
$qio->DOCNUM = sprintf('%06s',$pio->invoice->id);
|
||||
$qio->DUEDATE = date('m/d/Y',$pio->invoice->due_date);
|
||||
$qio->AMOUNT = sprintf('%3.2f',$pio->invoice->total_amt);
|
||||
$qio->AMOUNT = sprintf('%3.2f',$pio->invoice->total());
|
||||
|
||||
if ($mpo->account->company)
|
||||
$qio->NAME = $mpo->account->company;
|
||||
if ($po->account->company)
|
||||
$qio->NAME = $po->account->company;
|
||||
else
|
||||
$qio->NAME = sprintf('%s %s',$mpo->account->last_name,$mpo->account->first_name);
|
||||
$qio->NAME = sprintf('%s %s',$po->account->last_name,$po->account->first_name);
|
||||
|
||||
// Other Quicken fields not used.
|
||||
#$qio->CLASS = '';
|
||||
@@ -70,41 +70,37 @@ class Export_Quicken extends Export {
|
||||
foreach ($pio->invoice->invoice_item->find_all() as $iio) {
|
||||
$qto = new Quicken_InvoiceItem;
|
||||
|
||||
if ($iio->date_start OR $iio->date_stop)
|
||||
$daterange = sprintf('%s-%s',date('d-m-Y',$iio->date_start),date('d-m-Y',$iio->date_stop));
|
||||
if ($iio->period())
|
||||
$daterange = $iio->period();
|
||||
|
||||
// @todo This should go.
|
||||
elseif ($iio->product_attr && preg_match('/^a/',$iio->product_attr)) {
|
||||
echo 'Uncaptured';die();
|
||||
|
||||
// @todo This should go.
|
||||
} elseif ($iio->product_attr && preg_match('/^s/',$iio->product_attr))
|
||||
$daterange = preg_replace("/\r?\n/",' ',unserialize($iio->product_attr));
|
||||
|
||||
else
|
||||
$daterange = '';
|
||||
|
||||
if (! $iio->product_id && preg_match('/^DOMAIN/',$iio->sku)) {
|
||||
$qto->ACCNT = 'Internet:Domain Name';
|
||||
|
||||
$qto->INVITEM = sprintf('Domain:%s',
|
||||
($iio->domain_tld) ? strtoupper($iio->domain_tld) : 'Unknown');
|
||||
|
||||
$qto->MEMO = sprintf('Domain: %s.%s (%s)',
|
||||
strtoupper($iio->domain_name),strtoupper($iio->domain_tld),$daterange);
|
||||
|
||||
} elseif ($iio->product_id) {
|
||||
$module = ORM::factory('module',array('name'=>'product'));
|
||||
$export = ORM::factory('export','module')
|
||||
if ($iio->product_id) {
|
||||
$mo = ORM::factory('module',array('name'=>'product'));
|
||||
$eo = ORM::factory('export')
|
||||
->where('plugin_name','=',$this->plugin)
|
||||
->and_where('module_id','=',$module->id)
|
||||
->and_where('module_id','=',$mo->id)
|
||||
->and_where('item_id','=',$iio->product_id)
|
||||
->find();
|
||||
|
||||
if ($export->loaded()) {
|
||||
$map_data = unserialize($export->map_data);
|
||||
if ($eo->loaded()) {
|
||||
$map_data = unserialize($eo->map_data);
|
||||
$qto->ACCNT = $map_data['account'];
|
||||
$qto->INVITEM = $map_data['item'];
|
||||
|
||||
} else {
|
||||
throw new Kohana_Exception('Missing product map data for :product (:id)',
|
||||
array(':product'=>$iio->product->name(),':id'=>$iio->product_id));
|
||||
|
||||
$qto->ACCNT = 'Other Income';
|
||||
$qto->INVITEM = 'Product:Unknown';
|
||||
}
|
||||
@@ -122,18 +118,19 @@ class Export_Quicken extends Export {
|
||||
$qto->CLEAR = 'N';
|
||||
$qto->QNTY = -1;
|
||||
|
||||
if ($pio->invoice->tax_amt) {
|
||||
if ($pio->invoice->tax()) {
|
||||
$qto->TAXABLE = 'Y';
|
||||
# @todo, get this from OSB
|
||||
$qto->TAXCODE = 'GST';
|
||||
$qto->TAXRATE = sprintf('%3.2f%%','0.10');
|
||||
$qto->TAXAMOUNT = sprintf('%3.2f',$iio->tax_amt*-1);
|
||||
$qto->TAXAMOUNT = sprintf('%3.2f',$iio->tax()*-1);
|
||||
} else {
|
||||
$qto->TAXAMOUNT = 0;
|
||||
}
|
||||
|
||||
$qto->PRICE = sprintf('%3.2f',$iio->total_amt-$iio->tax_amt);
|
||||
$qto->AMOUNT = sprintf('%3.2f',($iio->total_amt-$iio->tax_amt)*-1);
|
||||
// @todo This rounding should be a system config.
|
||||
$qto->PRICE = sprintf('%3.2f',round($iio->subtotal()-$iio->discount(),2));
|
||||
$qto->AMOUNT = sprintf('%3.2f',round($iio->subtotal()-$iio->discount(),2)*-1);
|
||||
|
||||
$qio->addInvoiceItem($qto);
|
||||
}
|
||||
@@ -143,21 +140,21 @@ class Export_Quicken extends Export {
|
||||
}
|
||||
|
||||
$qpo = new Quicken_Payment;
|
||||
$qpo->AMOUNT = sprintf('%3.2f',$mpo->total_amt);
|
||||
$qpo->TRNSID = sprintf('P%06s',$mpo->id);
|
||||
$qpo->DATE = date('m/d/Y',$mpo->date_payment);
|
||||
$qpo->AMOUNT = sprintf('%3.2f',$po->total_amt);
|
||||
$qpo->TRNSID = sprintf('P%06s',$po->id);
|
||||
$qpo->DATE = date('m/d/Y',$po->date_payment);
|
||||
|
||||
// @todo this should be from a function - when no invoice is paid we cant use $qio
|
||||
if ($mpo->account->company)
|
||||
$qpo->NAME = $mpo->account->company;
|
||||
if ($po->account->company)
|
||||
$qpo->NAME = $po->account->company;
|
||||
else
|
||||
$qpo->NAME = sprintf('%s %s',$mpo->account->last_name,$mpo->account->first_name);
|
||||
$qpo->NAME = sprintf('%s %s',$po->account->last_name,$po->account->first_name);
|
||||
|
||||
$qpo->CLEAR = 'N';
|
||||
$qpo->MEMO = sprintf('Payment for invoice(s) %s (%s)',implode(':',$invoice_ids),$mpo->checkout->name);
|
||||
$qpo->MEMO = sprintf('Payment for invoice(s) %s (%s)',implode(':',$invoice_ids),$po->checkout->name);
|
||||
|
||||
// @todo Accounts/Payment should be configurable
|
||||
switch ($mpo->checkout->checkout_plugin) {
|
||||
switch ($po->checkout->checkout_plugin) {
|
||||
// @todo this is direct debit
|
||||
case 'MANUAL':
|
||||
$qpo->PAYMETH = 'DirectDebit';
|
||||
@@ -184,7 +181,8 @@ class Export_Quicken extends Export {
|
||||
$qpo->ACCNT = 'Undeposited Funds';
|
||||
}
|
||||
|
||||
$qio->addPayment($qpo);
|
||||
if (isset($qio))
|
||||
$qio->addPayment($qpo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -11,5 +11,26 @@
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_Export extends ORMOSB {
|
||||
public function rules() {
|
||||
return array_merge(parent::rules(),array(
|
||||
'map_data'=>array(
|
||||
array('ORMOSB::serialize_array',array(':model',':field',':value')),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
public function list_itemsnoexport() {
|
||||
$result = array();
|
||||
|
||||
$mo = ORM::factory('module',array('name'=>'product'));
|
||||
$p = ORM::factory('product')
|
||||
->order_by('id');
|
||||
|
||||
foreach ($p->find_all() as $po)
|
||||
if (! ORM::factory('export')->where('module_id','=',$mo->id)->where('item_id','=',$po->id)->find()->loaded())
|
||||
$result[$po->id] = $po;
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
18
modules/export/views/export/admin/map/add.php
Normal file
18
modules/export/views/export/admin/map/add.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<table>
|
||||
<tr>
|
||||
<td>Product</td>
|
||||
<td><?php echo Form::select('item_id',$eo->list_itemsnoexport()); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Export</td>
|
||||
<td><?php echo Form::input('plugin_name','quicken',array('disabled'=>'disabled')); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Account ID</td>
|
||||
<td><?php echo Form::input('map_data[account]','Internet:ADSL Supply'); ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Item ID</td>
|
||||
<td><?php echo Form::input('map_data[item]','ADSL:0256/064'); ?></td>
|
||||
</tr>
|
||||
</table>
|
@@ -1,7 +0,0 @@
|
||||
<tr class="<?php echo $i ? 'odd' : 'even'; ?>">
|
||||
<td><?php echo $payment->display('date_payment'); ?></td>
|
||||
<td><?php printf('%s (%s)',$payment->checkout->name,$payment->checkout->id); ?></td>
|
||||
<td><?php echo $payment->display('total_amt'); ?></td>
|
||||
<td><?php echo $payment->account->name(); ?></td>
|
||||
<td><?php echo Form::checkbox('payment_id[]',$payment->id); ?></td>
|
||||
</tr>
|
@@ -1,12 +0,0 @@
|
||||
<tr>
|
||||
<td colspan="3"><?php echo Form::select('plugin',$plugins); ?></td>
|
||||
<td colspan="2" style="text-align: right;"><?php echo Form::submit('submit','export',array('class'=>'form_button')); ?></td>
|
||||
</tr>
|
||||
<!-- // @todo To translate -->
|
||||
<tr>
|
||||
<td class="heading">Date</td>
|
||||
<td class="heading">Method</td>
|
||||
<td class="heading">Pay/Amount</td>
|
||||
<td class="heading">Customer</td>
|
||||
<td class="heading">Export</td>
|
||||
</tr>
|
@@ -9,6 +9,10 @@
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*
|
||||
* Column Definitions:
|
||||
* + price_type: 0=One Time, 1=Recurring, 2=Trial, 3=Extra Item
|
||||
* + item_type: 0=MAIN Service Item,2=?,3=?,4=Connection/Setup,5=Excess Service Item,6=Change Service,126=Payment Fee,127=Late Fee
|
||||
*/
|
||||
class Controller_Admin_Invoice extends Controller_TemplateDefault_Admin {
|
||||
protected $secure_actions = array(
|
||||
|
@@ -20,15 +20,15 @@ class Controller_Task_Invoice extends Controller_Task {
|
||||
public function action_list() {
|
||||
$mode = $this->request->param('id');
|
||||
|
||||
$io = ORM::factory('invoice');
|
||||
$i = ORM::factory('invoice');
|
||||
$tm = 'list_'.$mode;
|
||||
|
||||
if (! method_exists($io,$tm))
|
||||
if (! method_exists($i,$tm))
|
||||
throw new Kohana_Exception('Unknown Task List command :command',array(':command'=>$mode));
|
||||
|
||||
$total = $numinv = 0;
|
||||
$duelist = View::factory('invoice/task/'.$tm.'_head');
|
||||
foreach ($io->$tm() as $t) {
|
||||
foreach ($i->$tm() as $t) {
|
||||
$duelist .= View::factory('invoice/task/'.$tm.'_body')
|
||||
->set('io',$t);
|
||||
|
||||
@@ -60,10 +60,9 @@ class Controller_Task_Invoice extends Controller_Task {
|
||||
$action = array();
|
||||
// @todo This should go in a config somewhere
|
||||
$days = 5;
|
||||
$i = ORM::factory('invoice');
|
||||
$key = 'remind_due';
|
||||
|
||||
foreach ($i->list_due(time()+86400*$days) as $io) {
|
||||
foreach (ORM::factory('invoice')->list_due(time()+86400*$days) as $io) {
|
||||
// If we have already sent a reminder, we'll skip to the next one.
|
||||
if ($io->remind($key) AND (is_null($x=$this->request->param('id')) OR $x != 'again'))
|
||||
continue;
|
||||
@@ -96,7 +95,6 @@ class Controller_Task_Invoice extends Controller_Task {
|
||||
*/
|
||||
public function action_remind_overdue() {
|
||||
$action = array();
|
||||
$i = ORM::factory('invoice');
|
||||
$notice = $this->request->param('id');
|
||||
$x = NULL;
|
||||
|
||||
@@ -126,7 +124,7 @@ class Controller_Task_Invoice extends Controller_Task {
|
||||
|
||||
$key = 'remind_overdue_'.$notice;
|
||||
|
||||
foreach ($i->list_overdue_billing(time()-86400*$days,FALSE) as $io) {
|
||||
foreach (ORM::factory('invoice')->list_overdue_billing(time()-86400*$days,FALSE) as $io) {
|
||||
// If we have already sent a reminder, we'll skip to the next one.
|
||||
if ($io->remind($key) AND (is_null($x) OR $x != 'again'))
|
||||
continue;
|
||||
@@ -162,29 +160,38 @@ class Controller_Task_Invoice extends Controller_Task {
|
||||
*
|
||||
* @param int ID Service ID to generate invoice for (optional)
|
||||
*/
|
||||
public function action_serviceinvoices() {
|
||||
public function action_services() {
|
||||
// Used to only process X invoices in a row.
|
||||
// @todo This should be a configuration item.
|
||||
$max = 10;
|
||||
$action = array();
|
||||
$snd = array(); // Our service next billing dates that need to be updated if this is successful.
|
||||
$sid = $this->request->param('id');
|
||||
$sid = is_null($this->request->param('id')) ? NULL : explode(':',$this->request->param('id'));
|
||||
|
||||
// Sort our service by account_id, then we can generate 1 invoice.
|
||||
$svs = ORM::factory('service')->list_invoicesoon();
|
||||
Sort::MAsort($svs,'account_id,date_next_invoice');
|
||||
|
||||
$aid = $due = $io = NULL;
|
||||
$max_count = 0;
|
||||
foreach ($svs as $so) {
|
||||
if (! is_null($sid) AND $sid != $so->id)
|
||||
// If we are generating an invoice for a service, skip to that service.
|
||||
if (! is_null($sid) AND ! in_array($so->id,$sid))
|
||||
continue;
|
||||
|
||||
// Close off invoice, and start a new one.
|
||||
if (is_null($io) OR (is_null($aid) AND $aid != $so->account_id) OR (is_null($due) AND $due != $io->min_due($so->date_next_invoice))) {
|
||||
if (is_null($io) OR (! is_null($aid) AND $aid != $so->account_id) OR (! is_null($due) AND $due != $io->min_due($so->date_next_invoice))) {
|
||||
// Close this invoice.
|
||||
if (! is_null($io)) {
|
||||
if (is_object($io)) {
|
||||
// Save our invoice.
|
||||
if (! $io->save())
|
||||
throw new Kohana_Exception('Failed to save invoice :invoice for service :service',array(':invoice'=>$io->id,':service'=>$so->id));
|
||||
}
|
||||
|
||||
// If we have issued the max number of invoices this round, finish.
|
||||
if (++$max_count > $max)
|
||||
break;
|
||||
|
||||
// Start a new invoice.
|
||||
$io = ORM::factory('invoice');
|
||||
$io->due_date = $due = $io->min_due($so->date_next_invoice);
|
||||
@@ -199,12 +206,12 @@ class Controller_Task_Invoice extends Controller_Task {
|
||||
|
||||
$iio->service_id = $so->id;
|
||||
$iio->product_id = $so->product_id;
|
||||
$iio->quantity = 1;
|
||||
$iio->quantity = $pdata['prorata'];
|
||||
$iio->item_type = 0;
|
||||
$iio->discount_amt = null; // @todo
|
||||
$iio->price_type = $so->price_type; // @todo Do we need this?
|
||||
$iio->price_type = $so->product->price_type; // @todo Do we need this?
|
||||
// @todo Might be a better way to do this
|
||||
$iio->price_base = isset($ppa[$so->recur_schedule]['price_base']) ? $ppa[$so->recur_schedule]['price_base'] : 0;
|
||||
$iio->price_base = $so->price ? $so->price : (isset($ppa[$so->recur_schedule]['price_base']) ? $ppa[$so->recur_schedule]['price_base'] : 0);
|
||||
$iio->recurring_schedule = $so->recur_schedule;
|
||||
$iio->date_start = $pdata['start_time']; // @todo
|
||||
$iio->date_stop = $pdata['end_time']; // @todo
|
||||
@@ -212,12 +219,38 @@ class Controller_Task_Invoice extends Controller_Task {
|
||||
// Our service next billing date, if this invoice generation is successful.
|
||||
$snd[$so->id] = $pdata['end_time']+86400;
|
||||
|
||||
// Check if there are any charges
|
||||
$c = ORM::factory('charge')
|
||||
->where('service_id','=',$so->id)
|
||||
->where('status','=',0)
|
||||
->where('sweep_type','=',6); // @todo This needs to be dynamic, not "6"
|
||||
|
||||
foreach ($c->find_all() as $co) {
|
||||
$iio = $io->add_item();
|
||||
|
||||
$iio->service_id = $co->service_id;
|
||||
$iio->product_id = $co->product_id;
|
||||
$iio->charge_id = $co->id;
|
||||
$iio->quantity = $co->quantity;
|
||||
$iio->item_type = 5; // @todo This probably should not be hard coded as "5".
|
||||
$iio->discount_amt = null; // @todo
|
||||
$iio->price_base = $co->amount;
|
||||
$iio->date_start = $co->date_orig;
|
||||
$iio->date_stop = $co->date_orig; // @todo
|
||||
|
||||
// @todo Temp
|
||||
$co->status=2;
|
||||
$co->save();
|
||||
}
|
||||
|
||||
array_push($action,(string)$so->id);
|
||||
}
|
||||
|
||||
// Save our invoice.
|
||||
if (! $io->save())
|
||||
if (! $io->saved() AND ! $io->save()) {
|
||||
print_r($io->items());
|
||||
throw new Kohana_Exception('Failed to save invoice :invoice for service :service',array(':invoice'=>$io->id,':service'=>$so->id));
|
||||
}
|
||||
|
||||
// Update our service next billing dates.
|
||||
foreach ($snd as $sid=>$date) {
|
||||
@@ -229,7 +262,10 @@ class Controller_Task_Invoice extends Controller_Task {
|
||||
$this->response->body(_('Services Invoiced: ').join('|',$action));
|
||||
}
|
||||
|
||||
public function action_invoice_send() {
|
||||
public function action_send() {
|
||||
// Used to only process X invoices in a row.
|
||||
// @todo This should be a configuration item.
|
||||
$max = 2;
|
||||
$action = array();
|
||||
$iid = $this->request->param('id');
|
||||
$x = NULL;
|
||||
@@ -237,16 +273,21 @@ class Controller_Task_Invoice extends Controller_Task {
|
||||
if (preg_match('/:/',$iid))
|
||||
list($iid,$x) = explode(':',$iid);
|
||||
|
||||
// @todo The parameter for email should be a system CONSTANT?
|
||||
$i = $iid ? ORM::factory('invoice')->where('id','=',$iid) : ORM::factory('invoice')->tosend(1);
|
||||
// Get our list of invoices to send
|
||||
$i = $iid ? ORM::factory('invoice')->where('id','=',$iid) : ORM::factory('invoice')->list_tosend();
|
||||
|
||||
$key = 'send';
|
||||
|
||||
$max_count = 0;
|
||||
foreach ($i->find_all() as $io) {
|
||||
// If we have already sent a reminder, we'll skip to the next one.
|
||||
if ($io->remind($key) AND (is_null($x) OR $x != 'again'))
|
||||
continue;
|
||||
|
||||
// If we have issued the max number of invoices this round, finish.
|
||||
if (++$max_count > $max)
|
||||
break;
|
||||
|
||||
// Send our email
|
||||
$et = Email_Template::instance('task_invoice_'.$key);
|
||||
$token = ORM::factory('module_method_token')
|
||||
@@ -271,6 +312,7 @@ class Controller_Task_Invoice extends Controller_Task {
|
||||
|
||||
// @todo Record email log id if possible.
|
||||
if ($et->send()) {
|
||||
$io->print_status = 1;
|
||||
$io->set_remind($key,time());
|
||||
array_push($action,(string)$io);
|
||||
}
|
||||
|
@@ -60,7 +60,7 @@ class Controller_User_Invoice extends Controller_TemplateDefault_User {
|
||||
|
||||
$io = ORM::factory('invoice',$id);
|
||||
|
||||
if (! $io->loaded() OR ! Auth::instance()->authorised($io->account_id,$io->affiliate_id)) {
|
||||
if (! $io->loaded() OR (! Auth::instance()->authorised($io->account_id,$io->affiliate_id) AND ! in_array($this->ao->affiliate->id,$io->service_affiliates()))) {
|
||||
$this->template->content = 'Unauthorised or doesnt exist?';
|
||||
return FALSE;
|
||||
}
|
||||
|
@@ -322,7 +322,7 @@ class Invoice_TCPDF_Default extends Invoice_TCPDF {
|
||||
$this->SetXY($x-1,$y-1);
|
||||
$this->Cell(0,5*(
|
||||
1+1+1+3+($this->io->discount_amt ? 1 : 0)+($this->io->billed_amt ? 1 : 0)+($this->io->credit_amt ? 1 : 0)+$box
|
||||
)+1,'',1,0,'',1);
|
||||
)+1+4,'',1,0,'',1);
|
||||
|
||||
$this->SetFont('helvetica','B',11);
|
||||
$this->SetXY($x,$y);
|
||||
@@ -335,7 +335,7 @@ class Invoice_TCPDF_Default extends Invoice_TCPDF {
|
||||
foreach ($items as $name => $line) {
|
||||
if ($i < $this->itemsSummaryMax) {
|
||||
$this->SetX($x);
|
||||
$this->Cell(0,0,$line['quantity']);
|
||||
$this->Cell(0,0,sprintf('%3.2f',$line['quantity']));
|
||||
$this->SetX($x+8);
|
||||
$this->Cell(0,0,$name);
|
||||
$this->SetX($x+135);
|
||||
@@ -362,7 +362,7 @@ class Invoice_TCPDF_Default extends Invoice_TCPDF {
|
||||
if (round($this->io->subtotal(),Kohana::config('config.currency_format')) != $subtotal) {
|
||||
$this->SetFont('helvetica','',9);
|
||||
$this->SetX($x);
|
||||
$this->Cell(0,0,'Rounding');
|
||||
$this->Cell(0,0,'Other');
|
||||
$this->SetX($x+135);
|
||||
$this->Cell(0,0,Currency::display($this->io->subtotal()-$subtotal),0,0,'R');
|
||||
|
||||
@@ -404,7 +404,7 @@ class Invoice_TCPDF_Default extends Invoice_TCPDF {
|
||||
$this->SetY($y);
|
||||
|
||||
$this->SetX($x+8);
|
||||
$this->Cell(0,0,'Total Charges');
|
||||
$this->Cell(0,0,'Total Charges This Invoice');
|
||||
$this->SetX($x+135);
|
||||
$this->Cell(0,0,Currency::display($this->io->total()),0,0,'R');
|
||||
|
||||
@@ -496,7 +496,7 @@ class Invoice_TCPDF_Default extends Invoice_TCPDF {
|
||||
}
|
||||
|
||||
$this->SetX($x+130);
|
||||
$this->Cell(0,0,Currency::display($ito->total_amt),0,0,'R');
|
||||
$this->Cell(0,0,Currency::display($ito->total()),0,0,'R');
|
||||
|
||||
if ($this->show_service_range && $ito->period()) {
|
||||
$this->SetFont('helvetica','I',7);
|
||||
|
@@ -148,7 +148,7 @@ class Model_Invoice extends ORMOSB {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of services on an invoice
|
||||
* Get a list of invoice_items for a service_id on an invoice
|
||||
*
|
||||
* We use this to list details by service on an invoice.
|
||||
*/
|
||||
@@ -158,15 +158,15 @@ class Model_Invoice extends ORMOSB {
|
||||
$items = $this->items();
|
||||
|
||||
foreach ($items as $ito)
|
||||
if ($ito->service_id AND empty($result[$ito->service_id]))
|
||||
$result[$ito->service_id] = $ito->service;
|
||||
if ($ito->service_id AND empty($result[$ito->service_id]))
|
||||
$result[$ito->service_id] = $ito;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all invoice items for a service optionally by recurring schedule
|
||||
*/
|
||||
*/
|
||||
public function items_service($sid,$rs=NULL) {
|
||||
$result = array();
|
||||
$items = $this->items();
|
||||
@@ -211,11 +211,11 @@ class Model_Invoice extends ORMOSB {
|
||||
$result = array();
|
||||
|
||||
foreach ($this->items() as $ito) {
|
||||
// We conly summaries item_type=0
|
||||
// We only summarise item_type=0
|
||||
if (! $ito->item_type == 0)
|
||||
continue;
|
||||
|
||||
$t = $ito->product_id;
|
||||
$t = $ito->product->name();
|
||||
|
||||
if (! isset($result[$t])) {
|
||||
$result[$t]['quantity'] = 0;
|
||||
@@ -303,14 +303,17 @@ class Model_Invoice extends ORMOSB {
|
||||
}
|
||||
|
||||
public function min_due($date) {
|
||||
// @todo This should be configurable;
|
||||
return ($date < time()) ? time() : $date;
|
||||
return ($date < time()) ? time()+Kohana::config('config.invoice.min_due_days')*86400 : $date;
|
||||
}
|
||||
|
||||
public function save(Validation $validation = NULL) {
|
||||
// Our items will be clobbered once we save the object, so we need to save it here.
|
||||
$items = $this->items();
|
||||
|
||||
// @todo This is added here so we can do payments
|
||||
$this->total_amt = $this->total();
|
||||
$this->billed_amt = 0;
|
||||
|
||||
// Save the invoice
|
||||
parent::save($validation);
|
||||
|
||||
@@ -331,12 +334,14 @@ class Model_Invoice extends ORMOSB {
|
||||
throw new Kohana_Exception('Problem saving invoice_item for invoice :invoice - Failed save()',array(':invoice'=>$invoice->id));
|
||||
}
|
||||
|
||||
// @todo Need to save tax information
|
||||
// @todo Need to save discount information
|
||||
}
|
||||
|
||||
|
||||
} else
|
||||
throw new Kohana_Exception('Couldnt save invoice for some reason?');
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -387,13 +392,29 @@ class Model_Invoice extends ORMOSB {
|
||||
return $this->saved();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of affiliates associated with this invoice (via the service)
|
||||
*/
|
||||
public function service_affiliates() {
|
||||
$return = array();
|
||||
|
||||
foreach ($this->items() as $io)
|
||||
array_push($return,$io->service->affiliate_id);
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** LIST FUNCTIONS **/
|
||||
|
||||
private function _list_active() {
|
||||
return ORM::factory('invoice')->where('status','=',1);
|
||||
}
|
||||
|
||||
private function _list_due() {
|
||||
static $result = array();
|
||||
|
||||
if (! $result)
|
||||
foreach (ORM::factory('invoice')->where('status','=',1)->find_all() as $io)
|
||||
foreach ($this->_list_active()->find_all() as $io)
|
||||
if ($io->due())
|
||||
array_push($result,$io);
|
||||
|
||||
@@ -445,12 +466,20 @@ class Model_Invoice extends ORMOSB {
|
||||
if ($io->due_date > time())
|
||||
if (is_null($time))
|
||||
array_push($result,$io);
|
||||
elseif ($this->due_date <= $time)
|
||||
elseif ($io->due_date <= $time)
|
||||
array_push($result,$io);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of invoices that need to be sent.
|
||||
* @todo This should be optimised a little to return only invoices to send, instead of looking for them.
|
||||
*/
|
||||
public function list_tosend() {
|
||||
return ORM::factory('invoice')->where('status','=',1)->where_open()->where('print_status','is',NULL)->or_where('print_status','!=',1)->where_close();
|
||||
}
|
||||
|
||||
public function html() {
|
||||
// @todo This should be in a config file.
|
||||
$css = '<style type="text/css">';
|
||||
|
@@ -19,11 +19,17 @@ class Model_Invoice_Item extends ORMOSB {
|
||||
'invoice'=>array(),
|
||||
'service'=>array()
|
||||
);
|
||||
protected $_has_one = array(
|
||||
'charge'=>array('far_key'=>'charge_id','foreign_key'=>'id')
|
||||
);
|
||||
protected $_has_many = array(
|
||||
'invoice_item_tax'=>array('far_key'=>'id')
|
||||
);
|
||||
|
||||
protected $_display_filters = array(
|
||||
'date_orig'=>array(
|
||||
array('Config::date',array(':value')),
|
||||
),
|
||||
'date_start'=>array(
|
||||
array('Config::date',array(':value')),
|
||||
),
|
||||
@@ -83,8 +89,11 @@ class Model_Invoice_Item extends ORMOSB {
|
||||
return ($this->item_type == 0 OR $this->quantity == 1) ? HTML::nbsp('') : sprintf('%s@%3.2f',$this->quantity,$this->price_base);
|
||||
}
|
||||
|
||||
// @todo This might not be required.
|
||||
public function invoice_detail_items() {
|
||||
// @todo To fix up this function - needs to be better formed.
|
||||
if ($this->item_type == 5)
|
||||
return $this->charge->details('invoice_detail_items');
|
||||
|
||||
if ($this->item_type != 0)
|
||||
return;
|
||||
|
||||
@@ -96,6 +105,7 @@ class Model_Invoice_Item extends ORMOSB {
|
||||
parent::save($validation);
|
||||
|
||||
// Need to save the taxes and discounts associated with the invoice_item
|
||||
// @todo This needs to only check if the records have previously been saved, and update them.
|
||||
if ($this->saved()) {
|
||||
$iito = ORM::factory('invoice_item_tax');
|
||||
|
||||
|
@@ -63,7 +63,7 @@
|
||||
<div id="detail_toggle_<?php echo $rs; ?>">
|
||||
<table class="box-full" border="0">
|
||||
<?php if ($items) { ?>
|
||||
<?php foreach ($io->items_services($items) as $sid) { ?>
|
||||
<?php foreach ($io->items_services($items) as $sid => $ito) { ?>
|
||||
<?php $so = ORM::factory('service',$sid); ?>
|
||||
<!-- Product Information -->
|
||||
<tr class="head">
|
||||
@@ -84,7 +84,6 @@
|
||||
<td class="right"><?php echo Currency::display($ito->subtotal());?> </td>
|
||||
</tr>
|
||||
<!-- End Product Sub Information -->
|
||||
<?php } ?>
|
||||
|
||||
<?php if ($ito->discount_amt) { ?>
|
||||
<tr>
|
||||
@@ -101,6 +100,7 @@
|
||||
</tr>
|
||||
<!-- Product End Sub Items Tax -->
|
||||
<?php } ?>
|
||||
<?php } ?>
|
||||
<?php } ?>
|
||||
</table>
|
||||
</div>
|
||||
|
@@ -63,13 +63,12 @@
|
||||
<div id="detail_toggle_<?php echo $rs; ?>">
|
||||
<table class="box-full" border="0">
|
||||
<?php if ($items) { ?>
|
||||
<?php foreach ($io->items_services($items) as $sid) { ?>
|
||||
<?php $so = ORM::factory('service',$sid); ?>
|
||||
<?php foreach ($io->items_services($items) as $sid => $ito) { ?>
|
||||
<!-- Product Information -->
|
||||
<tr class="head">
|
||||
<td><?php echo HTML::anchor('/user/service/view/'.$so->id,$so->id()); ?></td>
|
||||
<td colspan="5"><?php echo $so->service_name(); ?> (<?php echo $so->product_id; ?>)</td>
|
||||
<td class="right"><?php echo Currency::display($io->items_service_total($so->id));?></td>
|
||||
<td><?php echo HTML::anchor('/user/service/view/'.$ito->service_id,$ito->service->id()); ?></td>
|
||||
<td colspan="5"><?php printf('%s - %s',$ito->product->name(),$ito->service->name()); ?> (<?php echo $ito->product_id; ?>)</td>
|
||||
<td class="right"><?php echo Currency::display($io->items_service_total($ito->service_id));?></td>
|
||||
</tr>
|
||||
<!-- End Product Information -->
|
||||
|
||||
@@ -90,14 +89,14 @@
|
||||
<tr>
|
||||
<td colspan="4"> </td>
|
||||
<td><?php echo _('Discounts'); ?></td>
|
||||
<td class="right">(<?php echo Currency::display($io->items_service_discount($so->id));?>)</td>
|
||||
<td class="right">(<?php echo Currency::display($io->items_service_discount($ito->service_id));?>)</td>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
<!-- Product Sub Items Tax -->
|
||||
<tr>
|
||||
<td colspan="4"> </td>
|
||||
<td><?php echo _('Taxes'); ?></td>
|
||||
<td class="right"><?php echo Currency::display($io->items_service_tax($so->id));?> </td>
|
||||
<td class="right"><?php echo Currency::display($io->items_service_tax($ito->service_id));?> </td>
|
||||
</tr>
|
||||
<!-- Product End Sub Items Tax -->
|
||||
<?php } ?>
|
||||
|
@@ -80,7 +80,7 @@ class Model_Payment extends ORMOSB {
|
||||
|
||||
// @todo database suffix needs to be dynamically calculated
|
||||
foreach (DB::Query(Database::SELECT,
|
||||
sprintf('SELECT A.id AS id,A.total_amt as total_amt FROM ab_%s A,ab_%s B WHERE A.site_id=B.site_id AND A.id=B.payment_id GROUP BY B.payment_id HAVING ROUND(SUM(B.alloc_amt),2)!=A.total_amt ORDER BY account_id,payment_id','payment','payment_item'))
|
||||
sprintf('SELECT A.id AS id,A.total_amt as total_amt FROM ab_%s A LEFT JOIN ab_%s B ON (A.site_id=B.site_id AND A.id=B.payment_id) WHERE (A.refund_status=0 OR A.refund_status IS NULL) GROUP BY A.id HAVING ROUND(SUM(IFNULL(B.alloc_amt,0)),2)!=A.total_amt ORDER BY account_id,payment_id','payment','payment_item'))
|
||||
->execute() as $values) {
|
||||
|
||||
array_push($pi,$values['id']);
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class provides Admin Product functions
|
||||
* This class provides Admin Product management
|
||||
*
|
||||
* @package OSB
|
||||
* @subpackage Product
|
||||
@@ -16,16 +16,16 @@ class Controller_Admin_Product extends Controller_TemplateDefault_Admin {
|
||||
);
|
||||
|
||||
/**
|
||||
* Show a list of services
|
||||
* Show a list of products
|
||||
*/
|
||||
public function action_list() {
|
||||
Block::add(array(
|
||||
'title'=>_('Customer Products'),
|
||||
'body'=>Table::display(
|
||||
ORM::factory('product')->order_by('prod_plugin_file')->find_all(),
|
||||
ORM::factory('product')->order_by('active DESC,prod_plugin_file')->find_all(),
|
||||
25,
|
||||
array(
|
||||
'id'=>array('label'=>'ID','url'=>'user/product/view/'),
|
||||
'id'=>array('label'=>'ID','url'=>'product/view/'),
|
||||
'name()'=>array('label'=>'Details'),
|
||||
'active'=>array('label'=>'Active'),
|
||||
'prod_plugin'=>array('label'=>'Plugin'),
|
||||
@@ -34,11 +34,13 @@ class Controller_Admin_Product extends Controller_TemplateDefault_Admin {
|
||||
'price_type'=>array('label'=>'Price Type'),
|
||||
'price_base'=>array('label'=>'Price Base'),
|
||||
'taxable'=>array('label'=>'Taxable'),
|
||||
'services_count()'=>array('label'=>'Services'),
|
||||
'invoices_count()'=>array('label'=>'Invoices'),
|
||||
),
|
||||
array(
|
||||
'page'=>TRUE,
|
||||
'type'=>'select',
|
||||
'form'=>'user/product/view',
|
||||
'form'=>'product/view',
|
||||
)),
|
||||
));
|
||||
}
|
||||
|
@@ -9,6 +9,9 @@
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*
|
||||
* Column Definitions:
|
||||
* + price_type: 0=One Time, 1=Recurring, 2=Trial
|
||||
*/
|
||||
class Model_Product extends ORMOSB {
|
||||
// @todo this doesnt have our site_id when getting the translation
|
||||
|
@@ -12,17 +12,38 @@
|
||||
*/
|
||||
class Controller_Admin_Service extends Controller_TemplateDefault_Admin {
|
||||
protected $secure_actions = array(
|
||||
'autolist'=>FALSE, // @todo To Change
|
||||
'list'=>TRUE,
|
||||
'listbycheckout'=>TRUE,
|
||||
'listadslbilling'=>TRUE,
|
||||
'listadslservices'=>TRUE,
|
||||
'listdomainservices'=>TRUE,
|
||||
'listdomainservicesbysupplier'=>TRUE,
|
||||
'listhostservices'=>TRUE,
|
||||
'listhspaservices'=>TRUE,
|
||||
'listinvoicesoon'=>TRUE,
|
||||
'update'=>TRUE,
|
||||
);
|
||||
|
||||
public function action_autolist() {
|
||||
$return = array();
|
||||
|
||||
$s = ORM::factory('service')->where('active','=',1);
|
||||
if (isset($_REQUEST['aid']))
|
||||
$s = $s->where('account_id','=',$_REQUEST['aid']);
|
||||
|
||||
// @todo This should limit the results so that users dont see other users services.
|
||||
foreach ($s->find_all() as $so)
|
||||
array_push($return,array(
|
||||
'value'=>$so->id,
|
||||
'text'=>sprintf('%s: %s',$so->id,$so->service_name()),
|
||||
));
|
||||
|
||||
$this->auto_render = FALSE;
|
||||
$this->response->headers('Content-Type','application/json');
|
||||
$this->response->body(json_encode($return));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a list of services
|
||||
*/
|
||||
@@ -53,73 +74,72 @@ class Controller_Admin_Service extends Controller_TemplateDefault_Admin {
|
||||
* List all services by their default checkout method
|
||||
*/
|
||||
public function action_listbycheckout() {
|
||||
// @todo need to add the DB prefix here
|
||||
// @todo need to remove the explicit references to the group_id
|
||||
$services = DB::query(Database::SELECT,'
|
||||
SELECT c.id AS cid,c.name as checkout_plugin_name,s.id AS sid,a.company,a.first_name,a.last_name,a.id as aid
|
||||
FROM ab_service s LEFT JOIN ab_account_billing ab ON (s.account_billing_id=ab.id) LEFT JOIN ab_checkout c ON (ab.checkout_plugin_id=c.id),ab_account a, ab_account_group ag
|
||||
WHERE s.active=1 AND s.price > 0 AND s.account_id=a.id AND a.id=ag.account_id AND ((s.account_billing_id IS NOT NULL AND ag.group_id!=2 ) OR (a.id=ag.account_id and ag.group_id=1003))
|
||||
ORDER BY c.id,s.recur_schedule,c.name,a.company,a.last_name,a.first_name
|
||||
')
|
||||
->execute();
|
||||
$svs = array();
|
||||
// @todo This needs to be configurable
|
||||
$go = ORM::factory('group',array('name'=>'Personal'));
|
||||
|
||||
// @todo If no items, show a nice message. This is not correct for ORM.
|
||||
if (! count($services)) {
|
||||
echo Kohana::debug('No services with account_billing');
|
||||
die();
|
||||
foreach (ORM::factory('account')->where('status','=',1)->find_all() 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'=>'user/service/view/'),
|
||||
'service_name()'=>array('label'=>'Details'),
|
||||
'recur_schedule'=>array('label'=>'Billing'),
|
||||
'price'=>array('label'=>'Price','class'=>'right'),
|
||||
'active'=>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'=>'user/service/view',
|
||||
)),
|
||||
));
|
||||
|
||||
foreach (ORM::factory('checkout')->where('active','=',1)->find_all() 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'=>'user/service/view/'),
|
||||
'service_name()'=>array('label'=>'Details'),
|
||||
'recur_schedule'=>array('label'=>'Billing'),
|
||||
'price'=>array('label'=>'Price','class'=>'right'),
|
||||
'active'=>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'=>'user/service/view',
|
||||
)),
|
||||
));
|
||||
}
|
||||
|
||||
$last_checkout = '';
|
||||
$last_account = '';
|
||||
$i = 0;
|
||||
$sc = $st = 0;
|
||||
$output = '<table class="box-left">';
|
||||
foreach ($services as $service) {
|
||||
$so = ORM::factory('service',$service['sid']);
|
||||
$si = $so->account_id.$so->recur_schedule;
|
||||
|
||||
if (($si != $last_account) AND $last_account) {
|
||||
if ($sc > 1)
|
||||
$output .= View::factory('service/admin/list/bycheckout_subtotal')
|
||||
->set('subtotal',Currency::display($st))
|
||||
->set('i',$i++%2);
|
||||
$sc = $st = 0;
|
||||
}
|
||||
|
||||
if (($service['cid'] != $last_checkout) OR (! is_null($last_checkout) AND ! $last_checkout)) {
|
||||
$output .= View::factory('service/admin/list/bycheckout_header')
|
||||
->set('checkout_name',$service['checkout_plugin_name'])
|
||||
->set('last_checkout',$last_checkout);
|
||||
}
|
||||
|
||||
$last_checkout = $service['cid'];
|
||||
$last_account = $si;
|
||||
// @todo This rounding should be a system default
|
||||
$st += round($so->price+$so->tax(),2);
|
||||
$sc++;
|
||||
|
||||
$output .= View::factory('service/admin/list/bycheckout_body')
|
||||
->set('service',$so)
|
||||
->set('i',$i++%2);
|
||||
}
|
||||
|
||||
// Last subtotal
|
||||
if ($sc > 1)
|
||||
$output .= View::factory('service/admin/list/bycheckout_subtotal')
|
||||
->set('subtotal',$st)
|
||||
->set('i',$i++%2);
|
||||
|
||||
$output .= '</table>';
|
||||
|
||||
Block::add(array(
|
||||
'title'=>_('List all Services by Default Payment Method'),
|
||||
'body'=>$output,
|
||||
));
|
||||
|
||||
Style::add(array(
|
||||
'type'=>'file',
|
||||
'data'=>'css/list.css',
|
||||
));
|
||||
}
|
||||
|
||||
private function consoltraffic($svs,$date) {
|
||||
@@ -255,6 +275,39 @@ ORDER BY c.id,s.recur_schedule,c.name,a.company,a.last_name,a.first_name
|
||||
));
|
||||
}
|
||||
|
||||
public function action_listdomainservicesbysupplier() {
|
||||
$svs = ORM::factory('service')->list_bylistgroup('DOMAIN');
|
||||
Sort::MAsort($svs,'plugin()->domain_registrar_id,name()');
|
||||
|
||||
$list = array();
|
||||
|
||||
foreach ($svs as $so)
|
||||
$list[$so->plugin()->domain_registrar_id][] = $so;
|
||||
|
||||
foreach (array_keys($list) as $sid)
|
||||
Block::add(array(
|
||||
'title'=>sprintf(_('Domain Names by Supplier %s'),$sid),
|
||||
'body'=>Table::display(
|
||||
$list[$sid],
|
||||
25,
|
||||
array(
|
||||
'id'=>array('label'=>'ID','url'=>'user/service/view/'),
|
||||
'service_name()'=>array('label'=>'Details'),
|
||||
'plugin()->display("domain_expire")'=>array('label'=>'Expire'),
|
||||
'recur_schedule'=>array('label'=>'Billing'),
|
||||
'price'=>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'=>'user/service/view',
|
||||
)),
|
||||
));
|
||||
}
|
||||
|
||||
public function action_listhostservices() {
|
||||
$svs = ORM::factory('service')->list_bylistgroup('HOST');
|
||||
Sort::MAsort($svs,'name()');
|
||||
@@ -298,7 +351,7 @@ ORDER BY c.id,s.recur_schedule,c.name,a.company,a.last_name,a.first_name
|
||||
->rule('csv','Upload::type',array(':value',array('csv')))
|
||||
->rule('csv','Upload::size',array(':value','10M'));
|
||||
|
||||
if ($files->check())
|
||||
if ($files->check())
|
||||
foreach ($files as $file)
|
||||
$csv = $this->process($file);
|
||||
}
|
||||
@@ -318,7 +371,7 @@ ORDER BY c.id,s.recur_schedule,c.name,a.company,a.last_name,a.first_name
|
||||
|
||||
// If our uploaded file has some cost data.
|
||||
if (! empty($csv[$so->plugin()->service_number])) {
|
||||
$uploaded['amount'] =
|
||||
$uploaded['amount'] =
|
||||
(empty($csv[$so->plugin()->service_number]['cost']) ? 0 : $csv[$so->plugin()->service_number]['cost']) +
|
||||
(empty($csv[$so->plugin()->service_number]['credit']) ? 0 : $csv[$so->plugin()->service_number]['credit']);
|
||||
|
||||
|
@@ -50,74 +50,77 @@ class Controller_Affiliate_Service extends Controller_TemplateDefault_Affiliate
|
||||
* List all services by their default checkout method
|
||||
*/
|
||||
public function action_listbycheckout() {
|
||||
// @todo need to add the DB prefix here
|
||||
// @todo need to remove the explicit references to the group_id
|
||||
// @todo need to restrict this to affiliate services
|
||||
$services = DB::query(Database::SELECT,'
|
||||
SELECT c.id AS cid,c.name as checkout_plugin_name,s.id AS sid,a.company,a.first_name,a.last_name,a.id as aid
|
||||
FROM ab_service s LEFT JOIN ab_account_billing ab ON (s.account_billing_id=ab.id) LEFT JOIN ab_checkout c ON (ab.checkout_plugin_id=c.id),ab_account a, ab_account_group ag
|
||||
WHERE s.active=1 AND s.price > 0 AND s.account_id=a.id AND a.id=ag.account_id AND ((s.account_billing_id IS NOT NULL AND ag.group_id!=2 ) OR (a.id=ag.account_id and ag.group_id=1003))
|
||||
ORDER BY c.id,s.recur_schedule,c.name,a.company,a.last_name,a.first_name
|
||||
')
|
||||
->execute();
|
||||
$svs = array();
|
||||
// @todo This needs to be configurable
|
||||
$go = ORM::factory('group',array('name'=>'Personal'));
|
||||
|
||||
// @todo If no items, show a nice message. This is not correct for ORM.
|
||||
if (! count($services)) {
|
||||
echo Kohana::debug('No services with account_billing');
|
||||
die();
|
||||
}
|
||||
foreach (ORM::factory('account')->where('status','=',1)->find_all() as $ao)
|
||||
if ($ao->has_any('group',array($go)))
|
||||
foreach ($this->filter($ao->service->list_active(),$this->ao->affiliate->id,'name()') as $so)
|
||||
if (! $so->service_billing->checkout_plugin_id)
|
||||
array_push($svs,$so);
|
||||
|
||||
$last_checkout = '';
|
||||
$last_account = '';
|
||||
$i = 0;
|
||||
$sc = $st = 0;
|
||||
$output = '<table class="box-left">';
|
||||
foreach ($services as $service) {
|
||||
$so = ORM::factory('service',$service['sid']);
|
||||
$si = $so->account_id.$so->recur_schedule;
|
||||
|
||||
if (($si != $last_account) AND $last_account) {
|
||||
if ($sc > 1)
|
||||
$output .= View::factory('service/admin/list/bycheckout_subtotal')
|
||||
->set('subtotal',Currency::display($st))
|
||||
->set('i',$i++%2);
|
||||
$sc = $st = 0;
|
||||
}
|
||||
|
||||
if (($service['cid'] != $last_checkout) OR (! is_null($last_checkout) AND ! $last_checkout)) {
|
||||
$output .= View::factory('service/admin/list/bycheckout_header')
|
||||
->set('checkout_name',$service['checkout_plugin_name'])
|
||||
->set('last_checkout',$last_checkout);
|
||||
}
|
||||
|
||||
$last_checkout = $service['cid'];
|
||||
$last_account = $si;
|
||||
// @todo This rounding should be a system default
|
||||
$st += round($so->price+$so->tax(),2);
|
||||
$sc++;
|
||||
|
||||
$output .= View::factory('service/admin/list/bycheckout_body')
|
||||
->set('service',$so)
|
||||
->set('i',$i++%2);
|
||||
}
|
||||
|
||||
// Last subtotal
|
||||
if ($sc > 1)
|
||||
$output .= View::factory('service/admin/list/bycheckout_subtotal')
|
||||
->set('subtotal',$st)
|
||||
->set('i',$i++%2);
|
||||
|
||||
$output .= '</table>';
|
||||
|
||||
Block::add(array(
|
||||
'title'=>_('List all Services by Default Payment Method'),
|
||||
'body'=>$output,
|
||||
if ($svs)
|
||||
Block::add(array(
|
||||
'title'=>'Services that should be auto-billed',
|
||||
'body'=>Table::display(
|
||||
$svs,
|
||||
25,
|
||||
array(
|
||||
'id'=>array('label'=>'ID','url'=>'user/service/view/'),
|
||||
'service_name()'=>array('label'=>'Details'),
|
||||
'recur_schedule'=>array('label'=>'Billing'),
|
||||
'price'=>array('label'=>'Price','class'=>'right'),
|
||||
'active'=>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'=>'user/service/view',
|
||||
)),
|
||||
));
|
||||
else
|
||||
Block::add(array(
|
||||
'title'=>'Services that should be auto-billed',
|
||||
'body'=>_('None found'),
|
||||
));
|
||||
|
||||
Style::add(array(
|
||||
'type'=>'file',
|
||||
'data'=>'css/list.css',
|
||||
));
|
||||
foreach (ORM::factory('checkout')->where('active','=',1)->find_all() as $co) {
|
||||
$svs = array();
|
||||
|
||||
foreach ($co->account->find_all() as $ao)
|
||||
foreach ($this->filter($ao->service->list_active(),$this->ao->affiliate->id,'name()') 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'=>'user/service/view/'),
|
||||
'service_name()'=>array('label'=>'Details'),
|
||||
'recur_schedule'=>array('label'=>'Billing'),
|
||||
'price'=>array('label'=>'Price','class'=>'right'),
|
||||
'active'=>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'=>'user/service/view',
|
||||
)),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
private function consoltraffic($svs,$date) {
|
||||
|
@@ -12,6 +12,9 @@
|
||||
*/
|
||||
class Model_Service extends ORMOSB {
|
||||
// Relationships
|
||||
protected $_has_one = array(
|
||||
'service_billing'=>array('far_key'=>'account_billing_id','foreign_key'=>'id'),
|
||||
);
|
||||
protected $_has_many = array(
|
||||
'invoice'=>array('through'=>'invoice_item'),
|
||||
);
|
||||
@@ -108,14 +111,6 @@ class Model_Service extends ORMOSB {
|
||||
return $plugin->_admin_update();
|
||||
}
|
||||
|
||||
// @todo To implement
|
||||
/**
|
||||
* Calculate the tax for this item
|
||||
*/
|
||||
public function tax() {
|
||||
return $this->price * .1;
|
||||
}
|
||||
|
||||
/** LIST FUNCTIONS **/
|
||||
|
||||
public function list_active() {
|
||||
|
16
modules/service/classes/model/service/billing.php
Normal file
16
modules/service/classes/model/service/billing.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class supports Service Billing.
|
||||
*
|
||||
* @package OSB
|
||||
* @subpackage Product/Service
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_Service_Billing extends ORMOSB {
|
||||
protected $_table_name = 'account_billing';
|
||||
}
|
||||
?>
|
@@ -1,9 +0,0 @@
|
||||
<tr class="<?php echo $i ? 'odd' : 'even'; ?>">
|
||||
<td><?php echo $service->account->accnum(); ?></td>
|
||||
<td><?php echo $service->account->name(); ?></td>
|
||||
<td><?php printf('%s (%s)',$service->name(),$service->id); ?></td>
|
||||
<td><?php echo $service->display('recur_schedule'); ?></td>
|
||||
<td><?php echo $service->display('price'); ?></td>
|
||||
<td><?php echo $service->account->invoices_due_total(); ?></td>
|
||||
<td><?php echo $service->display('date_next_invoice'); ?></td>
|
||||
</tr>
|
@@ -1,16 +0,0 @@
|
||||
<!-- Print out the heading for the first record -->
|
||||
<!-- // @todo This needs to be translated -->
|
||||
<?php if (! $last_checkout); {?>
|
||||
<tr class="title">
|
||||
<td colspan="7"><?php echo $checkout_name; ?></td>
|
||||
</tr>
|
||||
<tr class="head">
|
||||
<td>Account ID</td>
|
||||
<td>Account</td>
|
||||
<td>Service</td>
|
||||
<td>Frequency</td>
|
||||
<td>Amount</td>
|
||||
<td>Invoices Due</td>
|
||||
<td>Next Payment Date</td>
|
||||
</tr>
|
||||
<?php } ?>
|
@@ -1,5 +0,0 @@
|
||||
<tr class="<?php echo $i ? 'odd' : 'even'; ?>">
|
||||
<td colspan="4"> </td>
|
||||
<td><b><?php echo $subtotal; ?></b></td>
|
||||
<td colspan="2"> </td>
|
||||
</tr>
|
@@ -44,7 +44,7 @@ class Controller_User_Statement extends Controller_TemplateDefault_User {
|
||||
}
|
||||
|
||||
if (isset($v['invoice']))
|
||||
$t += $v['invoice']->total_amt;
|
||||
$t += $v['invoice']->total();
|
||||
elseif (isset($v['payment']))
|
||||
$t -= $v['payment']->total_amt;
|
||||
|
||||
|
@@ -3,7 +3,7 @@
|
||||
<td><?php echo $o['invoice']->display('date_orig'); ?></td>
|
||||
<td>Invoice</td>
|
||||
<td><?php echo HTML::anchor('user/invoice/view/'.$o['invoice']->id,$o['invoice']->id()); ?></td>
|
||||
<td class="right"><?php echo $o['invoice']->display('total_amt'); ?></td>
|
||||
<td class="right"><?php echo $o['invoice']->total(TRUE); ?></td>
|
||||
<?php } elseif (isset($o['payment'])) { ?>
|
||||
<td><?php echo $o['payment']->display('date_payment'); ?></td>
|
||||
<td>Payment</td>
|
||||
|
Reference in New Issue
Block a user