array('far_key'=>'id'), 'service'=>array('far_key'=>'id'), 'invoice'=>array('through'=>'invoice_item'), ); protected $_sorting = array( 'position'=>'asc', ); protected $_display_filters = array( 'price_type'=>array( array('StaticList_PriceType::get',array(':value')), ), 'status'=>array( array('StaticList_YesNo::get',array(':value')), ), 'taxable'=>array( array('StaticList_YesNo::get',array(':value')), ), ); protected $_nullifempty = array( 'price_group', ); // Our attributes that are arrays, we'll convert/unconvert them protected $_serialize_column = array( 'price_group', ); /** * Which categories is this product available in */ public function categories() { return $this->avail_category; } /** * Return the translated description for a category. */ public function description($full=FALSE) { $x = $this->translate(); return $x->loaded() ? $x->display($full ? 'description_full' : 'description_short') : 'No Description'; } /** * This will render the product feature summary information */ public function feature_summary() { return (is_null($plugin = $this->plugin())) ? HTML::nbsp('') : $plugin->feature_summary(); } /** * Is price shown for a specific period * * @param $p int recurring schedule period */ public function is_price_shown($p) { $x = $this->keyget('price_group',$p); return (isset($x['show']) AND $x['show']) ? TRUE : FALSE; } /** * Test if the product is a TRIAL product * (price_type == 2) * * @return boolean */ public function is_trial() { return ($this->price_type == 2) ? TRUE : FALSE; } /** * Return the object of the product plugin */ public function plugin() { if (! $this->prod_plugin_file) return NULL; if (! is_numeric($this->prod_plugin_data)) throw new Kohana_Exception('Missing plugin_id for :product (:type)',array(':product'=>$this->id,':type'=>$this->prod_plugin_file)); return ORM::factory(Kohana::classname(sprintf('Product_Plugin_%s',$this->prod_plugin_file)),$this->prod_plugin_data); } public function save(Validation $validation=NULL) { if ($this->changed()) if (parent::save($validation)) SystemMessage::factory() ->title('Record Updated') ->type('success') ->body(sprintf('Record %s Updated',$this->id)); // Save our Translated Message if ($x = array_diff_key($_POST,$this->_object) AND ! empty($_POST['language_id']) AND ! empty($_POST['product_translate']) AND is_array($_POST['product_translate'])) { $pto = $this->product_translate->where('language_id','=',$_POST['language_id'])->find(); // For a new entry, we need to set the product_id if (! $pto->loaded()) { $pto->product_id = $this->id; $pto->language_id = $_POST['language_id']; } if ($pto->values($x['product_translate'])->save()) SystemMessage::factory() ->title('Record Updated') ->type('success') ->body(sprintf('Translation for Record %s Updated',$this->id)); } } /** * List the services that are linked to this product */ public function services($active=FALSE) { return $active ? $this->service->where_active() : $this->service; } private function translate() { return $this->product_translate->where('language_id','=',Config::language())->find(); } /** * Return the translated title for a category */ public function title() { $x = $this->translate(); return $x->loaded() ? $x->display('name') : 'No Title'; } public function list_type($type) { return $this->where('prod_plugin_file','=',$type)->find_all(); } /** * Return the best price to the uesr based on the users group's memberships * @todo This needs to be tested with more than one price group enabled */ public function get_price_array() { // Figure out our eligable groups // @todo Need to work out our default groups elsewhere, not in product // All users are members of the all user group "0" $groups = array(0); if (Auth::instance()->logged_in()) foreach (Auth::instance()->get_user()->group->find_all() as $go) array_push($groups,$go->id); // Work out the best price for the user $price = array(); if (is_array($this->price_group)) foreach ($this->price_group as $bill_freq => $pg) { if (isset($pg['show']) AND $pg['show']) foreach ($groups as $gid) { if (! empty($pg[$gid])) { if (empty($price[$bill_freq]['price_base']) OR ($pg[$gid]['price_base'] AND $price[$bill_freq]['price_base'] > $pg[$gid]['price_base'])) { $price[$bill_freq]['price_setup'] = $pg[$gid]['price_setup']; $price[$bill_freq]['price_base'] = $pg[$gid]['price_base']; } } } } // @todo Ugly hack 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 */ public function availPriceGroups() { // @todo This needs to be worked out dynamically return array(0,1); } /** * Return the available pricing options */ public function availPriceOptions() { // @todo This needs to be worked out dynamically return array('price_base','price_setup'); } /** * List the number of services using this product */ public function count_services() { return $this->service->list_count(TRUE); } /** * List the number of invoices using this product */ public function count_invoices() { return $this->invoice->list_count(TRUE); } /** * Return the price for the particle group and price option for the period */ public function price($grp,$period,$option,$taxed=FALSE) { $x = $this->keyget('price_group',$period); if (isset($x[$grp][$option])) return $taxed ? Tax::add($x[$grp][$option]) : $x[$grp][$option]; else return NULL; } } ?>