Work on HTML invoice and internal logic
This commit is contained in:
@@ -49,6 +49,33 @@ class Model_Invoice extends ORMOSB {
|
||||
|
||||
// Items belonging to an invoice
|
||||
private $invoice_items = array();
|
||||
private $subitems_load = FALSE;
|
||||
|
||||
public function __construct($id = NULL) {
|
||||
// Load our model.
|
||||
parent::__construct($id);
|
||||
|
||||
return $this->load_sub_items();
|
||||
}
|
||||
|
||||
private function load_sub_items() {
|
||||
// Load our sub items
|
||||
if (! $this->subitems_load AND $this->loaded()) {
|
||||
$this->invoice_items = $this->invoice_item->find_all()->as_array();
|
||||
$this->subitems_load = TRUE;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of invoice items for this payment.
|
||||
*/
|
||||
public function items() {
|
||||
$this->load_sub_items();
|
||||
|
||||
return $this->invoice_items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the Invoice Number
|
||||
@@ -69,20 +96,13 @@ class Model_Invoice extends ORMOSB {
|
||||
*/
|
||||
public function due($format=FALSE) {
|
||||
// If the invoice is active calculate the due amount
|
||||
$result = $this->status ? round($this->total()-$this->payments_total(),2) : 0;
|
||||
$result = $this->status ? $this->total()-$this->payments_total() : 0;
|
||||
|
||||
return $format ? Currency::display($result) : $result;
|
||||
}
|
||||
// @todo This should not be required.
|
||||
if ((Currency::round($result) == .01) or Currency::round($result) == .02)
|
||||
$result = 0;
|
||||
|
||||
/**
|
||||
* Return a list of invoice items for this invoice.
|
||||
*/
|
||||
public function items() {
|
||||
// If we havent been changed, we'll load the records from the DB.
|
||||
if ($this->loaded() AND ! $this->_changed)
|
||||
return $this->invoice_item->order_by('service_id,item_type,module_id')->find_all()->as_array();
|
||||
else
|
||||
return $this->invoice_items;
|
||||
return $format ? Currency::display($result) : Currency::round($result);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -91,31 +111,28 @@ class Model_Invoice extends ORMOSB {
|
||||
public function subtotal($format=FALSE) {
|
||||
$result = 0;
|
||||
|
||||
// @todo This rounding should be a system config.
|
||||
foreach ($this->items() as $ito)
|
||||
$result += round($ito->subtotal(),2);
|
||||
$result += $ito->subtotal();
|
||||
|
||||
return $format ? Currency::display($result) : $result;
|
||||
return $format ? Currency::display($result) : Currency::round($result);
|
||||
}
|
||||
|
||||
public function discount($format=FALSE) {
|
||||
$result = 0;
|
||||
|
||||
// @todo This rounding should be a system config.
|
||||
foreach ($this->items() as $ito)
|
||||
$result += round($ito->discount_amt,2);
|
||||
$result += $ito->discount_amt;
|
||||
|
||||
return $format ? Currency::display($result) : $result;
|
||||
return $format ? Currency::display($result) : Currency::round($result);
|
||||
}
|
||||
|
||||
public function tax($format=FALSE) {
|
||||
$result = 0;
|
||||
|
||||
// @todo This rounding should be a system config.
|
||||
foreach ($this->items() as $ito)
|
||||
$result += round($ito->tax(),2);
|
||||
$result += $ito->tax();
|
||||
|
||||
return $format ? Currency::display($result) : $result;
|
||||
return $format ? Currency::display($result) : Currency::round($result);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -124,18 +141,17 @@ class Model_Invoice extends ORMOSB {
|
||||
public function total($format=FALSE) {
|
||||
$result = 0;
|
||||
|
||||
// @todo This rounding should be a system config.
|
||||
foreach ($this->items() as $ito)
|
||||
$result += round($ito->total(),2);
|
||||
$result += $ito->total();
|
||||
|
||||
// Reduce by any credits
|
||||
$result -= round($this->credit_amt,2);
|
||||
$result -= $this->credit_amt;
|
||||
|
||||
return $format ? Currency::display($result) : $result;
|
||||
return $format ? Currency::display($result) : Currency::round($result);
|
||||
}
|
||||
|
||||
public function payments() {
|
||||
return ($this->loaded() AND ! $this->_changed) ? $this->payment_item->find_all() : array();
|
||||
return $this->payment_item->find_all();
|
||||
}
|
||||
|
||||
public function payments_total($format=FALSE) {
|
||||
@@ -144,7 +160,44 @@ class Model_Invoice extends ORMOSB {
|
||||
foreach ($this->payments() as $po)
|
||||
$result += $po->alloc_amt;
|
||||
|
||||
return $format ? Currency::display($result) : $result;
|
||||
return $format ? Currency::display($result) : Currency::round($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a sorted list of items by an index
|
||||
*/
|
||||
public function items_index($index) {
|
||||
static $result = array();
|
||||
|
||||
// We'll return a cached result for quicker processing
|
||||
if (! $this->_changed AND array_key_exists($index,$result))
|
||||
return $result[$index];
|
||||
|
||||
foreach ($this->items() as $ito) {
|
||||
switch ($index) {
|
||||
case 'account':
|
||||
if (! $ito->service_id)
|
||||
$result[$index][$ito->id] = $ito;
|
||||
|
||||
break;
|
||||
|
||||
case 'period':
|
||||
// We only show the services in this period
|
||||
if (! is_null($ito->recurring_schedule) AND (empty($result[$index][$ito->recurring_schedule]) OR ! in_array($ito->service_id,$result[$index][$ito->recurring_schedule])))
|
||||
$result[$index][$ito->recurring_schedule][] = $ito->service_id;
|
||||
|
||||
break;
|
||||
|
||||
case 'service':
|
||||
default:
|
||||
if ($ito->service_id)
|
||||
$result[$index][$ito->service_id][] = $ito;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return array_key_exists($index,$result) ? $result[$index] : array();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -152,6 +205,7 @@ class Model_Invoice extends ORMOSB {
|
||||
*
|
||||
* We use this to list details by service on an invoice.
|
||||
*/
|
||||
// @todo to retire
|
||||
public function items_services(array $items=array()) {
|
||||
$result = array();
|
||||
if (! $items)
|
||||
@@ -164,21 +218,33 @@ class Model_Invoice extends ORMOSB {
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all invoice items for a service optionally by recurring schedule
|
||||
*/
|
||||
public function items_service($sid,$rs=NULL) {
|
||||
// @todo to retire
|
||||
public function items_invoice() {
|
||||
$result = array();
|
||||
$items = $this->items();
|
||||
|
||||
Sort::MAsort($items,'item_type');
|
||||
foreach ($items as $ito)
|
||||
if ($ito->service_id == $sid AND (is_null($rs) OR $ito->recurring_schedule == $rs))
|
||||
array_push($result,$ito);
|
||||
if (! $ito->service_id AND empty($result[$ito->id]))
|
||||
$result[$ito->id] = $ito;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all invoice items for a specific service
|
||||
*/
|
||||
public function items_service($service_id) {
|
||||
$svs = $this->items_index('service');
|
||||
|
||||
if (array_key_exists($service_id,$svs)) {
|
||||
Sort::MAsort($svs[$service_id],'item_type');
|
||||
|
||||
return $svs[$service_id];
|
||||
} else
|
||||
return array();
|
||||
}
|
||||
|
||||
// @todo to retire
|
||||
/**
|
||||
* Return a list of periods and services
|
||||
*
|
||||
@@ -207,6 +273,7 @@ class Model_Invoice extends ORMOSB {
|
||||
*
|
||||
* We summaries based on product.
|
||||
*/
|
||||
// @todo
|
||||
public function items_summary() {
|
||||
$result = array();
|
||||
|
||||
@@ -303,6 +370,7 @@ class Model_Invoice extends ORMOSB {
|
||||
}
|
||||
|
||||
public function min_due($date) {
|
||||
// @todo This should be a DB confirm item
|
||||
return ($date < time()) ? time()+Kohana::config('config.invoice.min_due_days')*86400 : $date;
|
||||
}
|
||||
|
||||
|
@@ -63,41 +63,83 @@ class Model_Invoice_Item extends ORMOSB {
|
||||
if (! $result)
|
||||
$result += round($this->subtotal() *.1,2);
|
||||
|
||||
return $result;
|
||||
return Currency::round($result);
|
||||
}
|
||||
|
||||
// This total of this item before discounts and taxes
|
||||
public function subtotal() {
|
||||
return $this->price_base*$this->quantity;
|
||||
return Currency::round($this->price_base*$this->quantity);
|
||||
}
|
||||
|
||||
// The total of all discounts
|
||||
public function discount() {
|
||||
return $this->discount_amt;
|
||||
return Currency::round($this->discount_amt);
|
||||
}
|
||||
|
||||
public function total() {
|
||||
// @todo This rounding should be a system config
|
||||
return round($this->subtotal()+$this->tax()-$this->discount(),2);
|
||||
return Currency::round($this->subtotal()+$this->tax()-$this->discount());
|
||||
}
|
||||
|
||||
/**
|
||||
* Name for an invoice item
|
||||
*/
|
||||
public function name() {
|
||||
return $this->product_name ? $this->product_name : ($this->item_type == 0 ? _('Service') : _('Other'));
|
||||
switch ($this->item_type) {
|
||||
case 0: return _('Service');
|
||||
|
||||
case 1: return _('Item');
|
||||
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 6:
|
||||
case 126:
|
||||
case 127: return _('Charge');
|
||||
|
||||
case 5: return $this->charge->description;
|
||||
|
||||
default: return _('Other');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Detail behind an invoice item
|
||||
*/
|
||||
public function detail() {
|
||||
return ($this->item_type == 0 OR $this->quantity == 1) ? HTML::nbsp('') : sprintf('%s@%3.2f',$this->quantity,$this->price_base);
|
||||
switch ($this->item_type) {
|
||||
case 0: return '';
|
||||
|
||||
case 1: return _('Hardware');
|
||||
|
||||
case 2: return _('Service Relocation Fee');
|
||||
|
||||
case 3: return _('Service Change Fee');
|
||||
|
||||
case 4: return _('Service Connection Fee');
|
||||
|
||||
case 5: return sprintf('%s@%3.2f',$this->quantity,$this->price_base);
|
||||
|
||||
case 6: return _('Service Excess Fee');
|
||||
|
||||
case 126: return _('Rounding');
|
||||
|
||||
case 127: return _('Late Payment Fee');
|
||||
|
||||
default: '';
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
return $this->service->details('invoice_detail_items');
|
||||
switch ($this->item_type) {
|
||||
case 0:
|
||||
return $this->service->details('invoice_detail_items');
|
||||
case 4:
|
||||
return array('Charge'=>_('Service Connection Fee'));
|
||||
case 5:
|
||||
return $this->charge->details('invoice_detail_items');
|
||||
default:
|
||||
return array('Item'=>$this->item_type);
|
||||
}
|
||||
}
|
||||
|
||||
public function save(Validation $validation = NULL) {
|
||||
@@ -107,6 +149,7 @@ class Model_Invoice_Item extends ORMOSB {
|
||||
// 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()) {
|
||||
//@todo When updating a record, we shouldnt create a new tax item.
|
||||
$iito = ORM::factory('invoice_item_tax');
|
||||
|
||||
// Save TAX details
|
||||
|
Reference in New Issue
Block a user