diff --git a/application/classes/Config.php b/application/classes/Config.php index 1a78e8a4..b18cfe22 100644 --- a/application/classes/Config.php +++ b/application/classes/Config.php @@ -68,7 +68,7 @@ class Config extends Kohana_Config { * Show a date using a site configured format */ public static function date($date) { - return is_null($date) ? '' : date(Company::instance()->date_format(),$date); + return (is_null($date) OR ! $date) ? '' : date(Company::instance()->date_format(),$date); } /** diff --git a/application/classes/Controller/TemplateDefault.php b/application/classes/Controller/TemplateDefault.php index 5a06bd5c..68a61d12 100644 --- a/application/classes/Controller/TemplateDefault.php +++ b/application/classes/Controller/TemplateDefault.php @@ -52,9 +52,7 @@ abstract class Controller_TemplateDefault extends lnApp_Controller_TemplateDefau protected function save(Model $o) { try { - $o->save(); - - return $o->saved(); + return $o->save(); } catch (ORM_Validation_Exception $e) { SystemMessage::factory() diff --git a/application/classes/Model/Account.php b/application/classes/Model/Account.php index fd381619..1966cb72 100644 --- a/application/classes/Model/Account.php +++ b/application/classes/Model/Account.php @@ -202,7 +202,6 @@ class Model_Account extends Model_Auth_UserDefault { ->where('company','like','%'.$term.'%') ->or_where('first_name','like','%'.$term.'%') ->or_where('last_name','like','%'.$term.'%') - ->or_where('email','like','%'.$term.'%') ->where_close(); } diff --git a/application/classes/Model/Setup.php b/application/classes/Model/Setup.php index 78602968..1bf70a67 100644 --- a/application/classes/Model/Setup.php +++ b/application/classes/Model/Setup.php @@ -26,7 +26,7 @@ class Model_Setup extends ORM_OSB { // Validation rules public function rules() { - $r = Arr::merge(parent::rules(), array( + $x = Arr::merge(parent::rules(), array( 'url' => array( array('not_empty'), array('min_length', array(':value', 8)), @@ -36,9 +36,9 @@ class Model_Setup extends ORM_OSB { )); // This module doesnt use site_id. - unset($r['site_id']); + unset($x['site_id']); - return $r; + return $x; } /** diff --git a/modules/adsl/classes/Model/Product/Plugin/Adsl.php b/modules/adsl/classes/Model/Product/Plugin/Adsl.php index 4881bfe6..4ce01346 100644 --- a/modules/adsl/classes/Model/Product/Plugin/Adsl.php +++ b/modules/adsl/classes/Model/Product/Plugin/Adsl.php @@ -68,9 +68,6 @@ class Model_Product_Plugin_Adsl extends Model_Product_Plugin { ); // Our required abstract methods - public function admin_update() { - return ''; - } public function cost($annual=FALSE) { $x = $this->supplier_plan->display('base_cost'); @@ -83,6 +80,15 @@ class Model_Product_Plugin_Adsl extends Model_Product_Plugin { ->set('o',$this); } + // @todo Select the ADSL Plan for this product. + public function render_edit() { + return ''; + } + + public function render_order() { + return View::factory(sprintf('product/plugin/%s/order',$this->plugin())); + } + public function supplier() { return $this->supplier_plan->supplier_id; } diff --git a/modules/adsl/classes/Model/Service/Plugin/Adsl.php b/modules/adsl/classes/Model/Service/Plugin/Adsl.php index 2cf6bd68..693013ae 100644 --- a/modules/adsl/classes/Model/Service/Plugin/Adsl.php +++ b/modules/adsl/classes/Model/Service/Plugin/Adsl.php @@ -11,6 +11,7 @@ */ class Model_Service_Plugin_Adsl extends Model_Service_Plugin { protected $_table_name = 'service__adsl'; + protected $_created_column = FALSE; protected $_updated_column = FALSE; // Relationships diff --git a/modules/adsl/views/product/plugin/adsl/order.php b/modules/adsl/views/product/plugin/adsl/order.php new file mode 100644 index 00000000..62ad9fc1 --- /dev/null +++ b/modules/adsl/views/product/plugin/adsl/order.php @@ -0,0 +1,11 @@ +
+ ADSL Service Details + +
+ 'span2','label'=>'Service Number','placeholder'=>'Service Number','required')); ?> +
+ +
+ 'span6','label'=>'Service Address','placeholder'=>'Service Address','required')); ?> +
+
diff --git a/modules/domain/classes/Model/Product/Plugin/Domain.php b/modules/domain/classes/Model/Product/Plugin/Domain.php index 30e9d438..fbc9d9d3 100644 --- a/modules/domain/classes/Model/Product/Plugin/Domain.php +++ b/modules/domain/classes/Model/Product/Plugin/Domain.php @@ -15,9 +15,8 @@ class Model_Product_Plugin_Domain extends Model_Product_Plugin { } // Our required abstract methods - public function admin_update() {} - public function cost($annual=FALSE) { + // @todo $x = 0; return $annual ? $x*12 : $x; @@ -25,6 +24,15 @@ class Model_Product_Plugin_Domain extends Model_Product_Plugin { public function feature_summary() {} + public function render_edit() {} + + // @todo + public function supplier() { + return 'internal'; + } + + /** LOCAL FUNCTIONS **/ + // @todo This is not used, but should be. public function order_features() { $output = ''; @@ -44,9 +52,5 @@ class Model_Product_Plugin_Domain extends Model_Product_Plugin { return $output; } - - public function supplier() { - return 'internal'; - } } ?> diff --git a/modules/domain/classes/Model/Service/Plugin/Domain.php b/modules/domain/classes/Model/Service/Plugin/Domain.php index a3553b08..fa0ebe98 100644 --- a/modules/domain/classes/Model/Service/Plugin/Domain.php +++ b/modules/domain/classes/Model/Service/Plugin/Domain.php @@ -77,6 +77,7 @@ class Model_Service_Plugin_Domain extends Model_Service_Plugin { /** * Search for services matching a term + * @todo This search doesnt pick up the TLD of domain names */ public function list_autocomplete($term,$index,$value,array $label,array $limit=array(),array $options=NULL) { // We only show domain names. diff --git a/modules/email/classes/Controller/Admin/Email.php b/modules/email/classes/Controller/Admin/Email.php index 570364ca..4aefb360 100644 --- a/modules/email/classes/Controller/Admin/Email.php +++ b/modules/email/classes/Controller/Admin/Email.php @@ -12,7 +12,6 @@ class Controller_Admin_Email extends Controller_Email { protected $secure_actions = array( 'ajaxtemplatetranslate'=>TRUE, - 'list'=>TRUE, 'templateadd'=>TRUE, 'templateedit'=>TRUE, 'templatelist'=>TRUE, @@ -34,33 +33,6 @@ class Controller_Admin_Email extends Controller_Email { $this->template->content = $output; } - /** - * Show a list of emails - */ - public function action_list() { - Block::factory() - ->title(_('System Emails Sent')) - ->title_icon('icon-th') - ->body(Table::factory() - ->page_items(25) - ->data(ORM::factory('Email_Log')->find_all()) - ->columns(array( - 'id'=>'ID', - 'date_orig'=>'Date', - 'email'=>'To', - 'resolve("subject")'=>'Subject', - 'account->accnum()'=>'Cust ID', - 'account->name()'=>'Customer', - )) - ->prepend(array( - 'id'=>array('url'=>URL::link('user','email/view/')), - )) - ->postproc(array( - 'resolve("subject")'=>array('trim'=>60), - )) - ); - } - /** * Add a template */ @@ -119,6 +91,7 @@ class Controller_Admin_Email extends Controller_Email { $eto->reload(); } + // @todo With tinymce, if the user reselects a different language, we loose the editor? Script::factory() ->type('stdin') ->data(' @@ -139,7 +112,7 @@ $(document).ready(function() { alert("Failed to submit"); }, success: function(data) { - $("div[id=translate]").replaceWith(data); + $("div[id=translate]").empty().append(data); } }); }); diff --git a/modules/email/classes/Controller/Reseller/Email.php b/modules/email/classes/Controller/Reseller/Email.php new file mode 100644 index 00000000..c7acd748 --- /dev/null +++ b/modules/email/classes/Controller/Reseller/Email.php @@ -0,0 +1,44 @@ +TRUE, + ); + + /** + * Show a list of emails + */ + public function action_list() { + Block::factory() + ->title(_('System Emails Sent')) + ->title_icon('icon-th') + ->body(Table::factory() + ->page_items(25) + ->data(ORM::factory('Email_Log')->where_authorised($this->ao)->find_all()) + ->columns(array( + 'id'=>'ID', + 'date_orig'=>'Date', + 'email'=>'To', + 'resolve("subject")'=>'Subject', + 'account->accnum()'=>'Cust ID', + 'account->name()'=>'Customer', + )) + ->prepend(array( + 'id'=>array('url'=>URL::link('user','email/view/')), + )) + ->postproc(array( + 'resolve("subject")'=>array('trim'=>60), + )) + ); + } +} +?> diff --git a/modules/email/views/email/admin/ajaxtemplatetranslate.php b/modules/email/views/email/admin/ajaxtemplatetranslate.php index 3094b462..fa52ea05 100644 --- a/modules/email/views/email/admin/ajaxtemplatetranslate.php +++ b/modules/email/views/email/admin/ajaxtemplatetranslate.php @@ -1,4 +1,3 @@ -
subject,array( 'label'=>'Email Subject', @@ -24,7 +23,6 @@ 'editor'=>'tinymce', 'help-block'=>sprintf('The message in HTML that is used in the email. Uses variables: %s',implode(', ',array_values($o->variables('message_html')))))); ?>'
-
render_all(); ?> render_all(); ?> diff --git a/modules/host/classes/Model/Product/Plugin/Host.php b/modules/host/classes/Model/Product/Plugin/Host.php index 2567b972..d0c25e58 100644 --- a/modules/host/classes/Model/Product/Plugin/Host.php +++ b/modules/host/classes/Model/Product/Plugin/Host.php @@ -15,9 +15,8 @@ class Model_Product_Plugin_Host extends Model_Product_Plugin { } // Our required abstract methods - public function admin_update() {} - public function cost($annual=FALSE) { + // @todo $x = 0; return $annual ? $x*12 : $x; @@ -25,11 +24,14 @@ class Model_Product_Plugin_Host extends Model_Product_Plugin { public function feature_summary() {} - // @todo This is not used, but should be. - public function order_features() {} + public function render_edit() {} + // @todo public function supplier() { return 'internal'; } + + // @todo This is not used, but should be. + public function order_features() {} } ?> diff --git a/modules/lnApp b/modules/lnApp index 1ec370f0..c1323576 160000 --- a/modules/lnApp +++ b/modules/lnApp @@ -1 +1 @@ -Subproject commit 1ec370f07af319e5deda43dce6585ad9e0240c18 +Subproject commit c13235763045db771ecf2cfeb332cc8f3a314650 diff --git a/modules/payment/classes/Controller/Admin/Payment.php b/modules/payment/classes/Controller/Admin/Payment.php index b5a5f976..1587bef9 100644 --- a/modules/payment/classes/Controller/Admin/Payment.php +++ b/modules/payment/classes/Controller/Admin/Payment.php @@ -82,6 +82,16 @@ class Controller_Admin_Payment extends Controller_Payment { $this->response->body(json_encode(array_values($result))); } + public function action_edit() { + list($id,$output) = Table::page(__METHOD__); + + Block::factory() + ->type('form-horizontal') + ->title(sprintf('%s: %s',_('View Payments Received'),$id)) + ->title_icon('icon-wrench') + ->body($this->add_edit($id,$output)); + } + private function add_edit($id=NULL,$output='') { $po = ORM::factory('Payment',$id); @@ -146,13 +156,12 @@ $(document).ready(function() { alert("Failed to submit"); }, success: function(data) { - $("div[id=items]").replaceWith(data); + $("div[id=items]").empty().append(data); } }); return item; }, - }); }); '); @@ -170,16 +179,6 @@ $(document).ready(function() { ->set('o',$po); } - public function action_edit() { - list($id,$output) = Table::page(__METHOD__); - - Block::factory() - ->type('form-horizontal') - ->title(sprintf('%s: %s',_('View Payments Received'),$id)) - ->title_icon('icon-wrench') - ->body($this->add_edit($id,$output)); - } - /** * List our availale Buik Payment Methods */ diff --git a/modules/payment/views/payment/admin/ajaxitemlist.php b/modules/payment/views/payment/admin/ajaxitemlist.php index 8ac9802e..310e6a54 100644 --- a/modules/payment/views/payment/admin/ajaxitemlist.php +++ b/modules/payment/views/payment/admin/ajaxitemlist.php @@ -1,4 +1,3 @@ -
@@ -30,4 +29,3 @@
-
diff --git a/modules/product/classes/Controller/Admin/Product.php b/modules/product/classes/Controller/Admin/Product.php index be1bd2b9..10cf0ad4 100644 --- a/modules/product/classes/Controller/Admin/Product.php +++ b/modules/product/classes/Controller/Admin/Product.php @@ -28,7 +28,7 @@ class Controller_Admin_Product extends Controller_Product { $output = _('Unable to find translate data'); } else { - $pto = $po->product_translate->where('language_id','=',$_REQUEST['key'])->find(); + $pto = $po->translate->where('language_id','=',$_REQUEST['key'])->find(); $output = View::factory('product/admin/ajaxtranslate') ->set('o',$pto); @@ -89,7 +89,7 @@ $(document).ready(function() { alert("Failed to submit"); }, success: function(data) { - $("div[id=translate]").replaceWith(data); + $("div[id=translate]").empty().append(data); } }); }); @@ -136,7 +136,7 @@ $(document).ready(function() { alert("Failed to submit"); }, success: function(data) { - $("div[id=translate]").replaceWith(data); + $("div[id=translate]").empty().append(data); } }); }); @@ -148,7 +148,7 @@ $(document).ready(function() { ->title('Update Product') ->title_icon('icon-wrench') ->body(View::factory('product/admin/edit') - ->set('plugin_form',$po->admin_update()) + ->set('plugin_form',$po->plugin_edit()) ->set('o',$po)); } diff --git a/modules/product/classes/Model/Product.php b/modules/product/classes/Model/Product.php index 67e5ca5b..b3c54aac 100644 --- a/modules/product/classes/Model/Product.php +++ b/modules/product/classes/Model/Product.php @@ -35,6 +35,8 @@ class Model_Product extends ORM_OSB { ), ); + protected $_form = array('id'=>'id','value'=>'description()'); + protected $_nullifempty = array( 'price_group', ); @@ -107,6 +109,13 @@ class Model_Product extends ORM_OSB { return ORM::factory(Kohana::classname(sprintf('Product_Plugin_%s',$this->prod_plugin_file)),$this->prod_plugin_data); } + /** + * Enable the plugin to store data during an update + */ + public function plugin_edit() { + return (is_null($x = $this->plugin())) ? NULL : $x->render_edit(); + } + public function save(Validation $validation=NULL) { parent::save($validation); @@ -187,16 +196,6 @@ class Model_Product extends ORM_OSB { return $price ? $price : array('0'=>array('price_base'=>0,'price_setup'=>0)); } - /** - * Enable the plugin to store data - */ - public function admin_update() { - if (is_null($plugin = $this->plugin())) - return NULL; - else - return $plugin->admin_update(); - } - /** * Return the configured price groups for this product */ diff --git a/modules/product/classes/Model/Product/Plugin.php b/modules/product/classes/Model/Product/Plugin.php index e6ac9df1..6ec5f150 100644 --- a/modules/product/classes/Model/Product/Plugin.php +++ b/modules/product/classes/Model/Product/Plugin.php @@ -3,7 +3,7 @@ /** * This class supports Product Plugins. * - * @package Product + * @package Product/Plugin * @category Models * @author Deon George * @copyright (c) 2009-2013 Open Source Billing @@ -13,12 +13,6 @@ abstract class Model_Product_Plugin extends ORM_OSB { // Reset any sorting that may be defined in our parent protected $_sorting = array(); - /** - * The admin_update should be implemented in plugins. - * It is used to update the plugin specific product information - */ - abstract public function admin_update(); - /** * The cost of this service */ @@ -30,13 +24,20 @@ abstract class Model_Product_Plugin extends ORM_OSB { */ abstract public function feature_summary(); - abstract public function supplier(); - /** * Return the name of the plugin */ protected function plugin() { return strtolower(preg_replace('/(.*)_([a-zA-Z]+)$/',"$2",get_class($this))); } + + /** + * Form info for admins to update with plugin data + */ + abstract public function render_edit(); + + abstract public function render_order(); + + abstract public function supplier(); } ?> diff --git a/modules/product/views/product/admin/ajaxtranslate.php b/modules/product/views/product/admin/ajaxtranslate.php index 952e96d6..bde751b2 100644 --- a/modules/product/views/product/admin/ajaxtranslate.php +++ b/modules/product/views/product/admin/ajaxtranslate.php @@ -1,4 +1,3 @@ -
name,array( 'label'=>'Category Title', @@ -13,7 +12,6 @@ 'placeholder'=>'Short Description', 'class'=>'span6', 'required', - 'editor'=>'wysihtml5', 'help-block'=>'Complete description of this category')); ?>
@@ -25,7 +23,6 @@ 'editor'=>'wysihtml5', 'help-block'=>'Complete description of this category')); ?>
-
render_all(); ?> render_all(); ?> diff --git a/modules/product/views/product/admin/edit.php b/modules/product/views/product/admin/edit.php index 3c598eb1..3ebb5603 100644 --- a/modules/product/views/product/admin/edit.php +++ b/modules/product/views/product/admin/edit.php @@ -42,7 +42,7 @@
- price_recurr_default,array('label'=>'Default Period','class'=>'span2')); ?> + price_recurr_default,FALSE,array('label'=>'Default Period','class'=>'span2')); ?>
diff --git a/modules/product/views/product/category/admin/ajaxtranslate.php b/modules/product/views/product/category/admin/ajaxtranslate.php index b0ae3d22..428dda7b 100644 --- a/modules/product/views/product/category/admin/ajaxtranslate.php +++ b/modules/product/views/product/category/admin/ajaxtranslate.php @@ -1,4 +1,3 @@ -
name,array( 'label'=>'Category Title', @@ -16,7 +15,6 @@ 'editor'=>'wysihtml5', 'help-block'=>'Complete description of this category')); ?>
-
render_all(); ?> render_all(); ?> diff --git a/modules/service/classes/Controller/Admin/Service.php b/modules/service/classes/Controller/Admin/Service.php index 30a53e7f..665a8ba0 100644 --- a/modules/service/classes/Controller/Admin/Service.php +++ b/modules/service/classes/Controller/Admin/Service.php @@ -11,13 +11,148 @@ */ class Controller_Admin_Service extends Controller_Service { protected $secure_actions = array( + 'add'=>TRUE, + 'ajaxaddplugin'=>TRUE, + 'edit'=>TRUE, 'listdomainservicesbysupplier'=>TRUE, 'listdomainservicesbydnshost'=>TRUE, 'listhostservicesbysupplier'=>TRUE, - 'update'=>TRUE, 'view'=>TRUE, ); + public function action_add() { + if ($this->request->post() AND $so=$this->add_edit() AND $so->loaded()) + HTTP::redirect(URL::link('admin','service/edit/'.$so->id)); + + // @todo This AJAX URL should be a service one + Script::factory() + ->type('stdin') + ->data(' +var nowTemp = new Date(); +var now = new Date(nowTemp.getFullYear(), nowTemp.getMonth(), nowTemp.getDate(), 0, 0, 0, 0); + +$(document).ready(function() { + $("select[name=product_id]").change(function() { + // If we select a blank, then dont continue + if (this.value == 0) + return false; + + // Send the request and update sub category dropdown + $.ajax({ + type: "GET", + data: "key="+$(this).val(), + dataType: "html", + cache: false, + url: "'.URL::link('admin','service/ajaxaddplugin/',TRUE).'", + timeout: 2000, + error: function(x) { + alert("Failed to submit"); + }, + success: function(data) { + $("div[id=plugin]").empty().append(data); + } + }); + }); + + $("#date_next_invoice_label").datepicker({ + autoclose : true, + startDate : now, + format : "dd-M-yyyy", + todayBtn : true, + }).on("hide",function(ev) { + $("input[name=date_next_invoicel]").val(ev.date.valueOf()/1000); + }); + + $("input[name=account_id_label]").typeahead({ + minLength: 2, + source: function (query,process) { + search("'.URL::link('admin','payment/ajaxlist').'",query,process); + }, + + matcher: function () { return true; }, + + updater: function (item) { + $("input[name=account_id]").val(users[item]); + + return item; + }, + }); +}); + '); + + Script::factory() + ->type('file') + ->data('media/theme/bootstrap/vendor/datepicker/js/bootstrap-datepicker.js'); + + Style::factory() + ->type('file') + ->data('media/theme/bootstrap/vendor/datepicker/css/datepicker.css'); + + Block::factory() + ->type('form-horizontal') + ->title('Add/View Charge') + ->title_icon('icon-wrench') + ->body(View::factory('service/admin/add')); + } + + public function action_ajaxaddplugin() { + $po = ORM::factory('Product',$this->request->query('key')); + + if (! $po->loaded()) { + $output = __('Unable to find product :key',array(':key'=>$this->request->query('key'))); + + } else { + $output = $po->plugin()->render_order(); + } + + $this->template->content = $output; + } + + public function action_edit() { + list($id,$output) = Table::page(__METHOD__); + + $so = $this->request->post() ? $this->add_edit($id) : ORM::factory('Service',$id); + + if (! $so->loaded()) + HTTP::redirect('welcome/index'); + + Script::factory() + ->type('file') + ->data('media/theme/bootstrap/vendor/datepicker/js/bootstrap-datepicker.js'); + + Style::factory() + ->type('file') + ->data('media/theme/bootstrap/vendor/datepicker/css/datepicker.css'); + + Script::factory() + ->type('stdin') + ->data(' +var nowTemp = new Date(); +var now = new Date(nowTemp.getFullYear(), nowTemp.getMonth(), nowTemp.getDate(), 0, 0, 0, 0); + +$(document).ready(function() { + $("#date_next_invoice_label").datepicker({ + autoclose : true, + startDate : now, + format : "dd-M-yyyy", + todayBtn : true, + }).on("hide",function(ev) { + $("input[name=date_next_invoicel]").val(ev.date.valueOf()/1000); + }); +}); + '); + + Block::factory() + ->type('form-horizontal') + ->title(sprintf('%s: %s %s',_('Update Service'),$id,$so->name())) + ->title_icon('icon-wrench') + ->body(View::factory('service/admin/edit') + ->set('o',$so) + ->set('plugin_form',$so->plugin_edit()) + ); + + } + public function action_listdomainservicesbysupplier() { $svs = ORM::factory('Service')->list_bylistgroup('DOMAIN'); Sort::MAsort($svs,'plugin()->domain_registrar_id,name()'); @@ -114,64 +249,6 @@ class Controller_Admin_Service extends Controller_Service { )); } - public function action_update() { - list($id,$output) = Table::page(__METHOD__); - - $so = ORM::factory('Service',$id); - - if (! $so->loaded()) - HTTP::redirect('welcome/index'); - - if ($_POST) { - // Entry updated - if (isset($_POST['plugin']) AND $_POST['plugin']) { - $p = $so->plugin(); - - if ($p->values($_POST['plugin'])->changed() AND ! $this->save($p)) - $p->reload(); - } - - if ($so->values($_POST)->changed() AND ! $this->save($so)) - $so->reload(); - } - - Script::factory() - ->type('file') - ->data('media/theme/bootstrap/vendor/datepicker/js/bootstrap-datepicker.js'); - - Style::factory() - ->type('file') - ->data('media/theme/bootstrap/vendor/datepicker/css/datepicker.css'); - - Script::factory() - ->type('stdin') - ->data(' -var nowTemp = new Date(); -var now = new Date(nowTemp.getFullYear(), nowTemp.getMonth(), nowTemp.getDate(), 0, 0, 0, 0); - -$(document).ready(function() { - $("#date_next_invoice_label").datepicker({ - autoclose : true, - startDate : now, - format : "dd-M-yyyy", - todayBtn : true, - }).on("hide",function(ev) { - $("input[name=date_next_invoicel]").val(ev.date.valueOf()/1000); - }); -}); - '); - - Block::factory() - ->type('form-horizontal') - ->title(sprintf('%s: %s %s',_('Update Service'),$id,$so->name())) - ->title_icon('icon-wrench') - ->body(View::factory('service/admin/edit') - ->set('o',$so) - ->set('plugin_form',$so->admin_update()) - ); - - } - public function action_view() { list($id,$output) = Table::page(__METHOD__); @@ -257,5 +334,24 @@ $(document).ready(function() { 'body'=>$output, )); } + + private function add_edit($id=NULL,$output='') { + $so = ORM::factory('Service',$id); + + if ($_POST) { + if ($so->values($this->request->post())->changed() AND ! ($this->save($so))) + $so->reload(); + + // Do we have plugin data to save as well + if ($this->request->post('plugin') AND $so->loaded()) { + $x = $so->plugin(); + + if ($x->values(Arr::merge(array('service_id'=>$so->id),$this->request->post('plugin')))->changed()) + $this->save($x); + } + } + + return $so; + } } ?> diff --git a/modules/service/classes/Model/Service.php b/modules/service/classes/Model/Service.php index 9a3468f1..6ffbe59f 100644 --- a/modules/service/classes/Model/Service.php +++ b/modules/service/classes/Model/Service.php @@ -29,6 +29,17 @@ class Model_Service extends ORM_OSB { 'account'=>array(), ); + // Validation rules + public function rules() { + $x = Arr::merge(parent::rules(), array( + 'product_id' => array( + array('not_equal', array(':value', array(0))), + ), + )); + + return $x; + } + /** * Filters used to format the display of values into friendlier values */ @@ -50,6 +61,10 @@ class Model_Service extends ORM_OSB { ), ); + protected $_nullifempty = array( + 'price_override', + ); + protected $_form = array('id'=>'id','value'=>'service_name()'); // Cache our calls to our plugins @@ -216,6 +231,13 @@ class Model_Service extends ORM_OSB { return $type ? Model_Service::$plugin[$this->id]->$type : Model_Service::$plugin[$this->id]; } + /** + * Enable the plugin to store data + */ + public function plugin_edit() { + return (is_null($x = $this->plugin())) ? NULL : $x->render_edit(); + } + public function revenue($annual=FALSE) { $multiple = $annual ? Period::multiple($this->recur_schedule) : 1; @@ -243,7 +265,7 @@ class Model_Service extends ORM_OSB { $x = $this->product->keyget('price_group',$this->recur_schedule); // @todo This index shouldnt be hard coded. - $p = ! is_null($this->price) ? $this->price : $x[$this->price_group]['price_base']; + $p = ! is_null($this->price) ? $this->price : (isset($x[$this->price_group]['price_base']) ? $x[$this->price_group]['price_base'] : NULL); if (! $original AND ! is_null($this->price_override)) $p = $this->price_override; @@ -265,20 +287,13 @@ class Model_Service extends ORM_OSB { return is_null($plugin) ? array() : $plugin->_details($type); case 'service_view': - return is_null($plugin) ? HTML::nbsp('') : $plugin->service_view(); + return is_null($plugin) ? HTML::nbsp('') : $plugin->render_view(); default: throw new Kohana_Exception('Unkown detail request :type',array(':type'=>$type)); } } - /** - * Enable the plugin to store data - */ - public function admin_update() { - return (is_null($plugin = $this->plugin())) ? NULL : $plugin->admin_update(); - } - public function transactions() { return $this->invoice_item->order_by('date_start')->order_by('date_stop'); } diff --git a/modules/service/classes/Model/Service/Plugin.php b/modules/service/classes/Model/Service/Plugin.php index 12736098..fad8ca39 100644 --- a/modules/service/classes/Model/Service/Plugin.php +++ b/modules/service/classes/Model/Service/Plugin.php @@ -47,14 +47,6 @@ abstract class Model_Service_Plugin extends ORM_OSB { } } - /** - * Form info for admins to update - */ - public function admin_update() { - return View::factory(sprintf('service/admin/plugin/%s/edit',$this->plugin())) - ->set('o',$this); - } - /** * Provide the button that launches the management of this service, generally from a 3rd party */ @@ -96,18 +88,26 @@ function() { $("form[id=id_"+t[0]+"_"+t[1]+"]").submit(); }); } /** - * Show our service name as defined in the DB with product suffix. + * Form info for admins to update plugin data */ - public function service_name() { - return sprintf('%s - %s',$this->service->product->title(),$this->name()); + public function render_edit() { + return View::factory(sprintf('service/admin/plugin/%s/edit',$this->plugin())) + ->set('o',$this); } /** * View details of the service */ - public function service_view() { + public function render_view() { return View::factory(sprintf('service/user/plugin/%s/view',$this->plugin())) ->set('o',$this); } + + /** + * Show our service name as defined in the DB with product suffix. + */ + public function service_name() { + return sprintf('%s - %s',$this->service->product->title(),$this->name()); + } } ?> diff --git a/modules/service/views/service/admin/add.php b/modules/service/views/service/admin/add.php new file mode 100644 index 00000000..c0ef709b --- /dev/null +++ b/modules/service/views/service/admin/add.php @@ -0,0 +1,51 @@ +
+
+ Service Information + +
+ 'span5','label'=>'Account','placeholder'=>'Account','data-provide'=>'typeahead','required')); ?> + +
+ +
+ 'Active','class'=>'span1')); ?> +
+ +
+ 'Billing Period','required'));?> +
+ +
+
+ 'span2','label'=>'Date Next Invoice','add-on'=>'','disabled')); ?> +
+ + +
+ +
+ 'Taxable','class'=>'span1')); ?> +
+ +
+ 'Suspend Billing','class'=>'span1')); ?> +
+ +
+ 'Override Price','class'=>'span1')); ?> +
+ +
+ where_active()->list_select(TRUE),NULL,array('label'=>'Product','class'=>'span4','sort'=>TRUE)); ?> +
+
+ +
+ +
+
+ + +
+
+
diff --git a/modules/service/views/service/admin/edit.php b/modules/service/views/service/admin/edit.php index cbc85d75..e137cdcf 100644 --- a/modules/service/views/service/admin/edit.php +++ b/modules/service/views/service/admin/edit.php @@ -11,13 +11,13 @@
- recur_schedule,FALSE,array('label'=>'Billing Period','required'));?> + recur_schedule,FALSE,array('label'=>'Billing Period','required'));?>
- display('date_next_invoice'),array('class'=>'span2','label'=>'Date Last Invoice','add-on'=>'','disabled')); ?> + display('date_next_invoice'),array('class'=>'span2','label'=>'Date Next Invoice','add-on'=>'','disabled')); ?>
date_next_invoice); ?> diff --git a/modules/service/views/service/user/view.php b/modules/service/views/service/user/view.php index 5518596d..8b50cb9a 100644 --- a/modules/service/views/service/user/view.php +++ b/modules/service/views/service/user/view.php @@ -88,10 +88,12 @@ )); ?> + status) : ?>
Next Invoice Charges add_service($o)->render('html','body',array('noid'=>TRUE)); ?>
+
service_memo->find_all(); if ($x->count()) : ?> diff --git a/modules/ssl/classes/Model/Product/Plugin/Ssl.php b/modules/ssl/classes/Model/Product/Plugin/Ssl.php index 22443dda..4f35c316 100644 --- a/modules/ssl/classes/Model/Product/Plugin/Ssl.php +++ b/modules/ssl/classes/Model/Product/Plugin/Ssl.php @@ -13,7 +13,7 @@ class Model_Product_Plugin_Ssl extends Model_Product_Plugin { protected $_table_name = 'ssl'; // Our required abstract methods - public function admin_update() {} + public function render_edit() {} public function cost($annual=FALSE) { $x = 0;