* @copyright 2009 Deon George * @link http://osb.leenooks.net * * @link http://www.agileco.com/ * @copyright 2004-2008 Agileco, LLC. * @license http://www.agileco.com/agilebill/license1-4.txt * @author Tony Landis * @package AgileBill * @subpackage Module:Invoice */ define('FPDF_FONTPATH',PATH_INCLUDES.'pdf/font/'); require_once(PATH_INCLUDES.'pdf/fpdi.php'); require_once(PATH_INCLUDES.'pdf/fpdf_tpl.php'); require_once(PATH_INCLUDES.'pdf/fpdf.php'); /** * PDF Invoice Base * * @package AgileBill * @subpackage Module:Invoice */ abstract class pdf_invoice_base extends fpdi { protected $billToCompany = true; protected $itemsSummaryMax = 16; protected $itemsPreviousMax = 5; protected $news = ''; protected $pageType = 'blank'; protected $show_itemized = true; protected $show_service_range = false; private $invoiceCurrency = '$'; private $invoiceDecimals = 2; # Store previous invoices due private $itemsPrevious = array(); # Stores the invoice items protected $invoice; protected $itemsFull; protected $account; # Iteration of drawing the items on the invoice protected $iteration; # Store the date range, that the invoice covers protected $dateRange; public function __construct($inv) { parent::__construct(); $this->SetCreator('Open Source Billing'); $this->SetAuthor($inv->print['site']['NAME']); $this->SetTitle(sprintf('%s Invoice',$inv->print['site']['NAME'])); $this->SetSubject(sprintf('Invoice #%06s',$inv->getPrintInvoiceNum())); $this->SetKeywords($inv->getPrintInvoiceID()); $this->SetAutoPageBreak(TRUE,25); $this->SetDisplayMode('fullwidth'); return $this; } public function load_setup($rs=false) { if (! $rs) { $db =& DB(); $rs = $db->Execute(sqlSelect($db,'setup_invoice','*','')); } $this->billToCompany = $rs->fields['bill_to_company']; $this->invoiceCurrency = $rs->fields['invoice_currency']; $this->invoiceDecimals = $rs->fields['invoice_decimals']; $this->itemsSummaryMax = $rs->fields['items_summary_max']; $this->news = $rs->fields['news']; $this->pageType = $rs->fields['page_type']; $this->show_itemized = $rs->fields['invoice_show_itemized']; $this->show_service_range = $rs->fields['invoice_show_service_dates']; } abstract public function drawCompanyLogo(); abstract public function drawCompanyAddress($inv); abstract public function drawInvoiceHeader($inv); /** * Enable re-iteration of the invoices items, so that they can be displayed many ways */ abstract public function drawLineItems_pre($iteration); /** * This is called for each line item. */ abstract public function drawLineItems($db,$line,$invnum); /** * Draws the summary on the first page */ abstract public function drawSummaryLineItems($inv); abstract public function drawPaymentMethods($inv); public function drawRemittenceStub() {} public function drawCustom() {} public function drawInvoiceDueNotice() {} public function drawInvoicePaidNotice() {} public function setLateFeeNotice() {} /** * Get a blank invoice template */ public function getTemplate() { return PATH_THEMES.DEFAULT_THEME.'/invoice/invoice-'.$this->pageType.'.pdf'; } /** * Assigns the invoice fields to this object. */ public function setInvoiceFields($flds) { $this->invoice = $flds; } /** * Assigns the account fields to this object. */ public function setAccountFields($flds) { $this->account = $flds; } public function setItemsFull($items) { $this->itemsFull = $items; } public function setItemsPrevious($items) { $this->itemsPrevious = $items; } public function setDateRange($periodStart,$periodEnd) { $this->dateRange = sprintf('%s - %s',date(UNIX_DATE_FORMAT,$periodStart),date(UNIX_DATE_FORMAT,$periodEnd)); } public function setCurrency($currency) { $this->invoiceCurrency = $currency; } public function setDecimals($decimals) { $this->invoiceDecimals = $decimals; } /** * Render an amount into a currency display */ protected function _currency($num) { global $C_list; if ($this->invoiceDecimals>3) return $this->invoiceCurrency.number_format($num,$this->invoiceDecimals); else return $C_list->format_currency_num($num,$this->invoice['actual_billed_currency_id']); } /** * Override fpdf functions */ public function _putpages() { $nb = $this->page; if (! empty($this->AliasNbPages)) { //Replace number of pages for ($n=1;$n<=$nb;$n++) $this->pages[$n]=($this->compress) ? gzcompress(str_replace($this->AliasNbPages,$nb,gzuncompress($this->pages[$n]))) : str_replace($this->AliasNbPages,$nb,$this->pages[$n]) ; } if ($this->DefOrientation=='P') { $wPt=$this->fwPt; $hPt=$this->fhPt; } else { $wPt=$this->fhPt; $hPt=$this->fwPt; } $filter=($this->compress) ? '/Filter /FlateDecode ' : ''; for($n=1;$n<=$nb;$n++) { //Page $this->_newobj(); $this->_out('<_out('/Parent 1 0 R'); if (isset($this->OrientationChanges[$n])) $this->_out(sprintf('/MediaBox [0 0 %.2f %.2f]',$hPt,$wPt)); $this->_out('/Resources 2 0 R'); if(isset($this->PageLinks[$n])) { //Links $annots='/Annots ['; foreach($this->PageLinks[$n] as $pl) { $rect=sprintf('%.2f %.2f %.2f %.2f',$pl[0],$pl[1],$pl[0]+$pl[2],$pl[1]-$pl[3]); $annots.='<_textstring($pl[4]).'>>>>'; else { $l=$this->links[$pl[4]]; $h=isset($this->OrientationChanges[$l[0]]) ? $wPt : $hPt; $annots.=sprintf('/Dest [%d 0 R /XYZ 0 %.2f null]>>',1+2*$l[0],$h-$l[1]*$this->k); } } $this->_out($annots.']'); } $this->_out('/Contents '.($this->n+1).' 0 R>>'); $this->_out('endobj'); //Page content $this->_newobj(); $this->_out('<<'.$filter.'/Length '.strlen($this->pages[$n]).'>>'); $this->_putstream($this->pages[$n]); $this->_out('endobj'); } //Pages root $this->offsets[1]=strlen($this->buffer); $this->_out('1 0 obj'); $this->_out('<_out($kids.']'); $this->_out('/Count '.$nb); $this->_out(sprintf('/MediaBox [0 0 %.2f %.2f]',$wPt,$hPt)); $this->_out('>>'); $this->_out('endobj'); } public function _endpage() { //End of page contents $this->pages[$this->page] = ($this->compress) ? gzcompress($this->pages[$this->page]) : $this->pages[$this->page]; $this->state=1; } protected function RoundedRect($x,$y,$w,$h,$r,$style='') { $k = $this->k; $hp = $this->h; if ($style=='F') $op = 'f'; elseif ($style=='FD' || $style=='DF') $op = 'B'; else $op = 'S'; $MyArc = 4/3*(sqrt(2)-1); $this->_out(sprintf('%.2f %.2f m',($x+$r)*$k,($hp-$y)*$k)); $xc = $x+$w-$r ; $yc = $y+$r; $this->_out(sprintf('%.2f %.2f l',$xc*$k,($hp-$y)*$k)); $this->_Arc($xc+$r*$MyArc,$yc-$r,$xc+$r,$yc-$r*$MyArc,$xc+$r,$yc); $xc = $x+$w-$r; $yc = $y+$h-$r; $this->_out(sprintf('%.2f %.2f l',($x+$w)*$k,($hp-$yc)*$k)); $this->_Arc($xc+$r,$yc+$r*$MyArc,$xc+$r*$MyArc,$yc+$r,$xc,$yc+$r); $xc = $x+$r; $yc = $y+$h-$r; $this->_out(sprintf('%.2f %.2f l',$xc*$k,($hp-($y+$h))*$k)); $this->_Arc($xc-$r*$MyArc,$yc+$r,$xc-$r,$yc+$r*$MyArc,$xc-$r,$yc); $xc = $x+$r; $yc = $y+$r; $this->_out(sprintf('%.2f %.2f l',($x)*$k,($hp-$yc)*$k)); $this->_Arc($xc-$r,$yc-$r*$MyArc,$xc-$r*$MyArc,$yc-$r,$xc,$yc-$r); $this->_out($op); } private function _Arc($x1,$y1,$x2,$y2,$x3,$y3) { $h = $this->h; $this->_out(sprintf('%.2f %.2f %.2f %.2f %.2f %.2f c ', $x1*$this->k,($h-$y1)*$this->k,$x2*$this->k,($h-$y2)*$this->k,$x3*$this->k,($h-$y3)*$this->k)); } protected function Rotate($angle,$x=-1,$y=-1) { if ($x==-1) $x = $this->x; if ($y==-1) $y = $this->y; if ($this->angle!=0) $this->_out('Q'); $this->angle = $angle; if ($angle != 0) { $angle *= M_PI/180; $c = cos($angle); $s = sin($angle); $cx = $x*$this->k; $cy = ($this->h-$y)*$this->k; $this->_out(sprintf('q %.5f %.5f %.5f %.5f %.2f %.2f cm 1 0 0 1 %.2f %.2f cm',$c,$s,-$s,$c,$cx,$cy,-$cx,-$cy)); } } /** * Add a watermark to the PDF */ public function addWaterMark($text) { $this->SetFont('arial','B',50); $this->SetTextColor(203,203,203); $this->Rotate(0); $this->Text(10,50,$text); $this->Rotate(0); $this->SetTextColor(0,0,0); } } ?>