[Vtigercrm-developers] [PATCH] render API v1

Enrico Weigelt weigelt at metux.de
Thu May 10 08:26:38 PDT 2007


Hi folks,

here're some patches to introduce my new preprint rendering API.
For now there's just an latex backend, but adding more should
be quite simple.

cu
-- 
---------------------------------------------------------------------
 Enrico Weigelt    ==   metux IT service

  phone:     +49 36207 519931         www:       http://www.metux.de/
  fax:       +49 36207 519932         email:     contact at metux.de
  cellphone: +49 174 7066481
---------------------------------------------------------------------
 -- DSL ab 0 Euro. -- statische IP -- UUCP -- Hosting -- Webshops --
---------------------------------------------------------------------
-------------- next part --------------
diff -ruN htdocs.orig/lib/render/README htdocs/lib/render/README
--- htdocs.orig/lib/render/README	1970-01-01 01:00:00.000000000 +0100
+++ htdocs/lib/render/README	2007-05-09 13:53:10.000000000 +0200
@@ -0,0 +1 @@
+This subdirectory contains the TeX rendering stuff.
diff -ruN htdocs.orig/lib/render/RenderFactory.php htdocs/lib/render/RenderFactory.php
--- htdocs.orig/lib/render/RenderFactory.php	1970-01-01 01:00:00.000000000 +0100
+++ htdocs/lib/render/RenderFactory.php	2007-05-09 17:05:57.000000000 +0200
@@ -0,0 +1,64 @@
+<?php
+
+if (!defined('RENDER_LIB_PREFIX'))
+    define('RENDER_LIB_PREFIX', 'lib/render/');
+
+class E_Render_UnknownEngine extends Exception
+{
+    var $engine;
+    
+    function E_Render_Exception($e)
+    {
+	$this->engine = $e;
+    }
+
+    function __toString()
+    {
+	return "Unknown Engine: \"".$this->engine."\"";
+    }
+}
+	
+class E_Render_FormatNotSupportedByEngine extends Exception
+{
+    var $engine;
+    var $format;
+
+    function E_Render_FormatNotSupportedByEngine($format,$engine)
+    {
+	$this->format = $format;
+	$this->engine = $engine;
+    }
+    
+    function __toString()
+    {
+	return "Format \"".$this->format.
+	       "\" not supported by engine \"".
+	       $this->engine.
+	       "\"";
+    }
+}
+
+class RenderFactory
+{
+    /* public static */ function getRenderer_Invoice($param)
+    {
+	if (!($f = $param{'format'}))
+	    throw new Exception("missing output format");
+	if (!($e = $param{'engine'}))
+	    throw new Exception("missing engine");
+	    
+	switch ($e)
+	{
+	    case 'pdflatex':
+	    {
+		if ($f != 'application/pdf')
+		    throw new E_Render_FormatNotSupportedByEngine($f,$e);
+		
+		require_once(RENDER_LIB_PREFIX.'TexRender_Invoice.php');
+		return new TexRender_Invoice($param);
+	    }
+	    default:
+		throw new E_Render_UnknownEngine($e);
+	}
+    }
+}
diff -ruN htdocs.orig/lib/render/TexEncode.php htdocs/lib/render/TexEncode.php
--- htdocs.orig/lib/render/TexEncode.php	1970-01-01 01:00:00.000000000 +0100
+++ htdocs/lib/render/TexEncode.php	2007-05-10 02:51:50.000000000 +0200
@@ -0,0 +1,101 @@
+<?php
+
+// FIXME: support more languages
+
+class TexEncode
+{
+    function Date($date, $lang)
+    {
+	switch($lang)
+	{
+	    case 'en':	return TexEncode::Date_en($date);
+	    case 'de':	return TexEncode::Date_de($date);
+	    default:	throw new Exception("unsupported language $lang");
+	}
+    }
+    
+    function Date_de($date)
+    {
+	if (preg_match('~([0-9]+)-([0-9]+)-([0-9]+)~', $date, $m))
+        {
+	    $text = $m[3].'.';
+	    switch ($m[2])
+	    {
+		case 1:		$text .= ' Jan ';	break;
+		case 2:		$text .= ' Feb. '; 	break;
+	        case 3:		$text .= ' M"arz ';	break;
+	        case 4:		$text .= ' Apr. ';	break;
+	        case 5:		$text .= ' Mai ';	break;
+		case 6:		$text .= ' Jun. ';	break;
+	        case 7:		$text .= ' Jul. ';	break;
+		case 8:		$text .= ' Aug. ';	break;
+		case 9:		$text .= ' Sep. ';	break;
+		case 10:	$text .= ' Okt. ';	break;
+		case 11:	$text .= ' Nov. ';	break;
+		case 12:	$text .= ' Dez. ';	break;
+		default:	$text .= $m[2].'.';	break;
+	    }
+	    $text .= $m[1];
+	}
+	else $text = $date;
+	return $text;
+    }
+
+    function Date_en($date)
+    {
+	if (preg_match('~([0-9]+)-([0-9]+)-([0-9]+)~', $date, $m))
+        {
+	    $text = $m[3].'.';
+	    switch ($m[2])
+	    {
+		case 1:		$text .= ' Jan ';	break;
+		case 2:		$text .= ' Feb. '; 	break;
+	        case 3:		$text .= ' March ';	break;
+	        case 4:		$text .= ' Apr. ';	break;
+	        case 5:		$text .= ' May ';	break;
+		case 6:		$text .= ' June ';	break;
+	        case 7:		$text .= ' July ';	break;
+		case 8:		$text .= ' Aug. ';	break;
+		case 9:		$text .= ' Sep. ';	break;
+		case 10:	$text .= ' Oct. ';	break;
+		case 11:	$text .= ' Nov. ';	break;
+		case 12:	$text .= ' Dec. ';	break;
+		default:	$text .= $m[2].'.';	break;
+	    }
+	    $text .= $m[1];
+	}
+	else $text = $date;
+	return $text;
+    }
+    
+    function text($text)
+    {
+	return str_replace("\n",'\\ \\\\',
+	       str_replace("\r",'\\ \\\\', 
+	       TexEncode::escape($text)));
+    }
+
+    function escape ( $text )
+    {
+	return 
+	str_replace ( '#', '\#',
+        str_replace ( '&', '\&',
+	str_replace ( '$', '\$',
+	str_replace ( '~', '\~',
+	str_replace ( '_', '\_',
+	str_replace ( '&auml;',  '"a',
+	str_replace ( '&Auml;',  '"A',
+	str_replace ( '&Uuml;',  '"U',
+	str_replace ( '&uuml;',  '"u',
+	str_replace ( '&Ouml;',  '"O',
+	str_replace ( '&ouml;',  '"o',
+	str_replace ( '&szlig;', '"s', 
+	str_replace ( '"', '\"',
+	htmlentities ( $text ))))))))))))));
+    }
+
+    function money ( $val )
+    {
+	return sprintf ( '%01.2f', $val );
+    }
+}
diff -ruN htdocs.orig/lib/render/TexRender_Invoice.php htdocs/lib/render/TexRender_Invoice.php
--- htdocs.orig/lib/render/TexRender_Invoice.php	1970-01-01 01:00:00.000000000 +0100
+++ htdocs/lib/render/TexRender_Invoice.php	2007-05-10 16:55:44.000000000 +0200
@@ -0,0 +1,217 @@
+<?php
+
+/* TeX rendering engine for invoices 
+   
+   2007-05-09 Enrico Weigelt <weigelt at metux.de>
+   
+*/
+
+// NOTE: the webserver needs *write* acccess to this directory
+//       we normally take the session storage dir
+define('TEXRENDER_TMP_MASK',     '{SESSION.SAVE_PATH}/texrender-{SESSION.ID}-{NAME}');
+define('TEXRENDER_TEMPLATE_DIR', 'templates/tex/{TEMPLATE-NAME}/');
+
+require_once(RENDER_LIB_PREFIX.'TexEncode.php');
+
+class TexRender_Invoice
+{
+    /* private */ var $tmpmask;
+    /* private */ var $data;
+    /* private */ var $product_items;
+    /* private */ var $fn_tex;
+    /* private */ var $fn_pdf;
+    /* private */ var $fn_template;
+    /* private */ var $key;
+    
+    /* private */ function _tmpname($name)
+    {
+	return str_replace('{SESSION.NAME}',      session_name(),
+	       str_replace('{SESSION.ID}',        session_id(),
+	       str_replace('{SESSION.SAVE_PATH}', realpath(ini_get('session.save_path')),
+	       str_replace('{NAME}',              $name,
+	       $this->tmpmask
+	))));
+    }
+
+    /* private */ function _test_write_access()
+    {
+	$fn = $this->_tmpname('write-test');
+	if (!($fp=fopen($fn,"w")))
+	    throw new Exception("write-test: could not open file for writing: $fn");
+	fputs($fp,"TEST123");
+	fclose($fp);
+	
+	$res = trim(implode('',file($fn)));
+	if ($res != "TEST123")
+	    throw new Exception("write-test: reading test data failed for file: $fn");
+	
+	unlink($fn);
+
+	return true;
+    }
+
+    function TexRender_Invoice($param)
+    {
+	// test write access and otherwise failed
+	$this->tmpmask = TEXRENDER_TMP_MASK;
+	
+	// should be already cought by the factory, but just to be sure
+	if ($param{'format'} != 'application/pdf')
+	    throw new Exception("fomat not supported by this renderer: ".$param{'format'});
+	
+	if (!$param{'template'})
+	    throw new Exception("missing template name");
+
+	$this->template_name = $param{'template'};
+	$this->data = array();
+	$this->_test_write_access();
+	$this->key = md5(serialize(gettimeofday));
+	$this->fn_tex = $this->_tmpname($this->key.'.tex');
+	$this->fn_pdf = $this->_tmpname($this->key.'.pdf');
+	$this->template_dir= realpath(str_replace('{TEMPLATE-NAME}', $this->template_name,TEXRENDER_TEMPLATE_DIR));
+	$this->fn_template_main = $this->template_dir.'/invoice/main.texi';
+	$this->fn_template_item = $this->template_dir.'/invoice/item.texi';
+
+	$inc = $this->template_dir.'/config.php';
+	if (!include($inc))
+	    throw new Exception("could not load config: $inc");
+	    
+	if (!is_array($this->config = $tex_template_config))
+	    throw new Exception("missing template config");
+	
+	if (!$this->config{'lang'})
+	    throw new Exception("language not set in template config");
+    }
+
+    function addData($par)
+    {
+	foreach($par as $walk => $cur)
+	    $this->data{$walk} = $cur;
+    }
+
+    function checkProductItem($item)
+    {
+	if (!$item{'name'})
+	    throw new Exception("missing item name");
+	if (!$item{'amount'})
+	    throw new Exception("missing amount");
+	if (!is_numeric($item{'amount'}))
+	    throw new Exception("amount must be numeric");
+	if (!$item{'price'})
+	    throw new Exception("missing price");
+	if (!is_numeric($item{'price'}))
+	    throw new Exception("price must be numeric");
+	if (($item{'discount'})&&($item{'discount'} != 0))
+	    throw new Exception("discount not supported yet by this renderer");
+	if (!is_numeric($item{'tax_percent'}))
+	    throw new Exception("tax_percent must be numeric");
+    }
+
+    function checkData()
+    {
+	if ((!is_array($this->_product_items)) || 
+	    (!count($this->_product_items)))
+	    throw new Exception("no product items");
+
+	if (!$this->data{'ident'})
+	    throw new Exception("missing ident");
+    }
+    
+    /* public */ function addProductItem($item)
+    {
+	// check for correct items
+	$this->checkProductItem($item);
+
+	// calculate some stuff if necessary
+	if (!$item{'total'}) 
+	    $item{'total'} = $item{'price'} * $item{'amount'};
+	if (!$item{'taxes'})
+	    $item{'taxes'} = $item{'total'} * $item{'tax_percent'};
+	if (!$item{'topay'})
+	    $item{'topay'} = $item{'total'} + $item{'taxes'};
+
+	$this->_product_items[] = $item;
+    }
+
+    /* public String */ function getOutputContentType()
+    {
+	return 'application/pdf';
+    }
+
+    /* private String */ function _generate_tex()
+    {
+	if (!($tmpl_main = implode('',file($this->fn_template_main))))
+	    throw new Exception("could not load main template: ".$this->fn_template_main);
+	if (!($tmpl_item = implode('',file($this->fn_template_item))))
+	    throw new Exception("could not load item template: ".$this->fn_template_item);
+
+	// generate the item list
+	foreach ($this->_product_items as $walk => $cur)
+	{
+	    $items .= 
+	         str_replace('::Item:Name::',        $cur{'name'},
+	         str_replace('::Item:Price::',       TexEncode::money($cur{'price'}),
+		 str_replace('::Item:Amount::',      $cur{'amount'},
+		 str_replace('::Item:Taxrate::',     $cur{'tax_percent'},
+		 str_replace('::Item:Description::', $cur{'description'},
+		 str_replace('::Item:Comment::',     trim($cur{'comment'}),
+		 str_replace('::Item:Discount::',    TexEncode::money($cur{'discount'}),
+		 str_replace('::Item:Total::',       TexEncode::money($cur{'total'}),
+		 str_replace('::Item:Taxes::',       TexEncode::money($cur{'taxes'}),
+		 str_replace('::Item:Topay::',       TexEncode::money($cur{'topay'}),
+		 $tmpl_item))))))))));
+
+	    $all_total += $cur{'total'};
+	    $all_taxes += $cur{'taxes'};
+	    $all_topay += $cur{'topay'};
+	}
+		
+	$content = 
+	    str_replace('::TemplateDir::',           $this->template_dir,
+	    str_replace('::Items::',                 $items,
+	    str_replace('::Bill:Ident::',            $this->data{'ident'},
+            str_replace('::Bill:Total::',            TexEncode::money($all_total),
+	    str_replace('::Bill:Taxes::',            TexEncode::money($all_taxes),
+	    str_replace('::Bill:Topay::',            TexEncode::money($all_topay),
+	    str_replace('::Company:Addr:Street::',   $this->data{'company:addr:street'},
+	    str_replace('::Company:Addr:PCode::',    $this->data{'company:addr:pcode'},
+	    str_replace('::Company:Addr:City::',     $this->data{'company:addr:city'},
+	    str_replace('::Company:Addr:Country::',  $this->data{'company:addr:country'},
+	    str_replace('::Company:Addr:State::',    $this->data{'company:addr:state'},
+	    str_replace('::Company:Phone::',         $this->data{'company:phone'},
+	    str_replace('::Company:Fax::',           $this->data{'company:fax'},
+	    str_replace('::Company:Website::',       $this->data{'company:website'},
+	    str_replace('::Customer:Name::',         $this->data{'customer:name'},
+	    str_replace('::Customer:Addr:Street::',  TexEncode::text($this->data{'billing:addr:street'}),
+	    str_replace('::Customer:Addr:PCode::',   TexEncode::text($this->data{'billing:addr:pcode'}),
+	    str_replace('::Customer:Addr:City::',    TexEncode::text($this->data{'billing:addr:city'}),
+	    str_replace('::Customer:Addr:State::',   TexEncode::text($this->data{'billing:addr:state'}),
+	    str_replace('::Customer:Addr:Country::', TexEncode::text($this->data{'billing:addr:country'}),
+		$tmpl_main))))))))))))))))))));
+
+	return $content;
+    }
+    
+    /* public */ function generate()
+    {
+	$this->checkData();
+	$tex = $this->_generate_tex();
+	@unlink($this->fn_tex);
+	if (!($fp_tex = fopen($this->fn_tex,"w")))
+	    throw new Exception("could not open tex source file: ".$this->fn_tex);
+	
+	fputs($fp_tex,$tex);
+	fclose($fp_tex);
+
+	$cmd = 'cd '.dirname($this->fn_tex).' && pdflatex '.$this->fn_tex;
+	`$cmd` ; `$cmd` ; // call it twice for table calculations
+    }
+    
+    // send appropriate http headers and output file
+    /* public */ function sendHTTPOutput()
+    {
+	$this->generate();
+	Header("Content-Type: ".$this->getOutputContentType());
+	readfile($this->fn_pdf);
+    }
+}
-------------- next part --------------
diff -ruN htdocs.orig/modules/Invoice/CreatePDF.php htdocs/modules/Invoice/CreatePDF.php
--- htdocs.orig/modules/Invoice/CreatePDF.php	2007-05-09 00:56:25.000000000 +0200
+++ htdocs/modules/Invoice/CreatePDF.php	2007-05-10 15:30:08.000000000 +0200
@@ -9,67 +9,36 @@
  *
  ********************************************************************************/
 
-
-require_once('include/fpdf/pdf.php');
-require_once('include/fpdf/pdfconfig.php');
 require_once('modules/Invoice/Invoice.php');
 require_once('modules/Organization/Organization.php');
 require_once('include/database/PearDatabase.php');
 require_once('include/utils/EditViewUtils.php');
+require_once('lib/render/RenderFactory.php');
 
-global $adb,$app_strings,$focus;
-global $log;
-
-// for template checking ...
-$tmpl_dirs = array( "firstpage", "pages", "lastpage");
-$tmpl_files = array( "header.php", "body.php", "footer.php");
+global $adb,$app_strings,$focus,$log;
 
 $sql="select currency_symbol from vtiger_currency_info";
 $result = $adb->query($sql);
 $currency_symbol = $adb->query_result($result,0,'currency_symbol');
 
-// would you like and end page?  1 for yes 0 for no
-$endpage="1";
-
 $id = $_REQUEST['record'];
 
 //retreiving the vtiger_invoice info
 $focus = new Invoice();
 $focus->retrieve_entity_info($_REQUEST['record'],"Invoice");
-$account_name = getAccountName($focus->column_fields[account_id]);
-$invoice_no = $focus->column_fields[invoice_no];
 
 // **************** BEGIN POPULATE DATA ********************
 
-
-// populate data
 if($focus->column_fields["salesorder_id"] != '')
 	$so_name = getSoName($focus->column_fields["salesorder_id"]);
 else
 	$so_name = '';
 $po_name = $focus->column_fields["purchaseorder"];
 
-$valid_till = $focus->column_fields["duedate"];
-$valid_till = getDisplayDate($valid_till);
-$bill_street = $focus->column_fields["bill_street"];
-$bill_city = $focus->column_fields["bill_city"];
-$bill_state = $focus->column_fields["bill_state"];
-$bill_code = $focus->column_fields["bill_code"];
-$bill_country = $focus->column_fields["bill_country"];
-
-$contact_name =getContactName($focus->column_fields["contact_id"]);
-$ship_street = $focus->column_fields["ship_street"];
-$ship_city = $focus->column_fields["ship_city"];
-$ship_state = $focus->column_fields["ship_state"];
-$ship_code = $focus->column_fields["ship_code"];
-$ship_country = $focus->column_fields["ship_country"];
-
-$conditions = from_html($focus->column_fields["terms_conditions"]);
-$description = from_html($focus->column_fields["description"]);
-$status = $focus->column_fields["invoicestatus"];
-
 // Company information
-$crmid = $focus->column_fields["record_id"];
+if (!($crmid = $focus->column_fields["record_id"]))
+    throw new Exception("crmid is null/empty");
+
 $org_query = "select organizationname from vtiger_entity2org where crmid='".$crmid."'";
 $result = $adb->query($org_query);
 $org_rows = $adb->num_rows($result);
@@ -82,7 +51,7 @@
     $org_name = $adb->query_result($result,0,"organizationname");
 } else {
     $log->info( $module. " '".$crmid."' not assigned to any organization");
-    exit();
+    throw new Exception("crmid $crmid not assigned to any organisation (org_name=$org_name)");
 }
 
 // get organization/orgunit details
@@ -92,68 +61,11 @@
 $log->debug( "Here we are: getOrgUnits( $organization, $orgunitid);");
 $orgunittab = getOrgUnits( $organization, $orgunitid);
 
-if( is_array( $orgunittab[$orgunitid])) {
-    $orgdetails = $orgunittab[$orgunitid];
-    $org_name = $orgdetails["name"];
-    $org_address = $orgdetails["address"];
-    $org_city = $orgdetails["city"];
-    $org_state = $orgdetails["state"];
-    $org_country = $orgdetails["country"];
-    $org_code = $orgdetails["code"];
-    $org_phone = $orgdetails["phone"];
-    $org_fax = $orgdetails["fax"];
-    $org_website = $orgdetails["website"];
-    $logo_name = $orgdetails["logoname"];
-    $template = $orgdetails["invoice_template"];
-} else {
-    $log->info( $module. " '".$crmid."' organization/orgunitid mismatch");
-    exit();
-}
-
-// Check the template
-if( $template == "") 
-    $template = "Default";
-
-if( $template != "Default") {
-    foreach( $tmpl_dirs as $dir) {
-	foreach( $tmpl_files as $file) {
-	    if( !file_exists( "modules/".$module."/pdf_templates/".$template."/".$dir."/".$file)) {
-		$log->info( $module. " '".$crmid."' organization/orgunitid template '".$template."' is incomplete");
-		$log->info("Missing file: modules/".$module."/pdf_templates/".$template."/".$dir."/".$file);
-		$log->info("Fallback to the Default template");
-		$template = "Default";
-		break 2;
-	    }
-	}
-    }
-}
-//NOTE : Removed currency symbols and added with Grand Total text. it is enough to show the currency symbol in one place
-
-//we can also get the NetTotal, Final Discount Amount/Percent, Adjustment and GrandTotal from the array $associated_products[1]['final_details']
-
-//getting the Net Total
-$price_subtotal = number_format($focus->column_fields["hdnSubTotal"],2,'.',',');
-
-//Final discount amount/percentage
-$discount_amount = $focus->column_fields["hdnDiscountAmount"];
-$discount_percent = $focus->column_fields["hdnDiscountPercent"];
-
-if($discount_amount != "")
-	$price_discount = number_format($discount_amount,2,'.',',');
-else if($discount_percent != "")
-{
-	//This will be displayed near Discount label - used in include/fpdf/templates/body.php
-	$final_price_discount_percent = "(".number_format($discount_percent,2,'.',',')." %)";
-	$price_discount = number_format((($discount_percent*$focus->column_fields["hdnSubTotal"])/100),2,'.',',');
-}
-else
-	$price_discount = "0.00";
-
-//Adjustment
-$price_adjustment = number_format($focus->column_fields["txtAdjustment"],2,'.',',');
-//Grand Total
-$price_total = number_format($focus->column_fields["hdnGrandTotal"],2,'.',',');
+if(!is_array( $orgunittab[$orgunitid])) 
+    throw new Exception("org/orgunitid mismatch");
 
+$orgdetails  = $orgunittab[$orgunitid];
+$template    = $orgdetails["invoice_template"];
 
 //get the Associated Products for this Invoice
 $focus->id = $focus->column_fields["record_id"];
@@ -166,6 +78,8 @@
 //To calculate the group tax amount
 if($final_details['taxtype'] == 'group')
 {
+	throw new Exception("group tax not supported");
+
 	$group_tax_total = $final_details['tax_totalamount'];
 	$price_salestax = number_format($group_tax_total,2,'.',',');
 
@@ -191,47 +105,37 @@
 $sh_tax_amount = $final_details['shtax_totalamount'];
 $price_shipping_tax = number_format($sh_tax_amount,2,'.',',');
 
+$render = RenderFactory::getRenderer_Invoice(array
+(
+    format	=> 'application/pdf',
+    engine	=> 'pdflatex',
+    template	=> 'default'
+));
 
 //This is to get all prodcut details as row basis
-for($i=1,$j=$i-1;$i<=$num_products;$i++,$j++)
+for($i=1;$i<=$num_products;$i++)
 {
-	$product_name[$i] = $associated_products[$i]['productName'.$i];
-	$prod_description[$i] = $associated_products[$i]['productDescription'.$i];
-	$product_id[$i] = $associated_products[$i]['hdnProductId'.$i];
-	$qty[$i] = $associated_products[$i]['qty'.$i];
-	$unit_price[$i] = number_format($associated_products[$i]['unitPrice'.$i],2,'.',',');
-	$list_price[$i] = number_format($associated_products[$i]['listPrice'.$i],2,'.',',');
-	$list_pricet[$i] = $associated_products[$i]['listPrice'.$i];
-	$discount_total[$i] = $associated_products[$i]['discountTotal'.$i];
-	//aded for 5.0.3 pdf changes
-	$product_code[$i] = $associated_products[$i]['hdnProductcode'.$i];
-	
-	$taxable_total = $qty[$i]*$list_pricet[$i]-$discount_total[$i];
-
-	$producttotal = $taxable_total;
-	$total_taxes = '0.00';
 	if($focus->column_fields["hdnTaxType"] == "individual")
 	{
-		$total_tax_percent = '0.00';
-		//This loop is to get all tax percentage and then calculate the total of all taxes
-		for($tax_count=0;$tax_count<count($associated_products[$i]['taxes']);$tax_count++)
-		{
-			$tax_percent = $associated_products[$i]['taxes'][$tax_count]['percentage'];
-			$total_tax_percent = $total_tax_percent+$tax_percent;
-			$tax_amount = (($taxable_total*$tax_percent)/100);
-			$total_taxes = $total_taxes+$tax_amount;
-		}
-		$producttotal = $taxable_total+$total_taxes;
-		$product_line[$j]["Tax"] = number_format($total_taxes,2,'.',',')."\n ($total_tax_percent %) ";
-	}
-	$prod_total[$i] = number_format($producttotal,2,'.',',');
-
-	$product_line[$j]["Product Code"] = $product_code[$i];
-	$product_line[$j]["Product Name"] = $product_name[$i];
-	$product_line[$j]["Qty"] = $qty[$i];
-	$product_line[$j]["Price"] = $list_price[$i];
-	$product_line[$j]["Discount"] = $discount_total[$i];
-	$product_line[$j]["Total"] = $prod_total[$i];
+	    //This loop is to get all tax percentage and then calculate the total of all taxes
+	    for($tax_count=0;$tax_count<count($associated_products[$i]['taxes']);$tax_count++)
+		$tax_percent = $associated_products[$i]['taxes'][$tax_count]['percentage'];
+	}
+
+	$product_id = $associated_products[$i]['hdnProductId'.$i];
+
+	$render->addProductItem(array
+	(
+	    code	=> $associated_products[$i]['hdnProductcode'.$i],
+	    name	=> $associated_products[$i]['productName'.$i],
+	    amount	=> $associated_products[$i]['qty'.$i],
+	    price	=> $associated_products[$i]['listPrice'.$i],
+	    unit_price  => $associated_products[$i]['unitPrice'.$i],
+	    discount	=> $associated_products[$i]['discountTotal'.$i],
+	    tax_percent => (integer)($tax_percent)/100,
+	    description => $associated_products[$i]['productDescription'.$i],
+	    comment     => $associated_products[$i]['comment'.$i]
+	));
 
 	// Product piecelists
 	$query = "SELECT vtiger_crmentity.crmid,
@@ -245,86 +149,46 @@
 	    INNER JOIN vtiger_crmentity
 		ON vtiger_crmentity.crmid = vtiger_products.productid
 	    WHERE vtiger_crmentity.deleted = 0
-	    AND vtiger_products2products_rel.productid = ".$product_id[$i]."
+	    AND vtiger_products2products_rel.productid = ".$product_id."
 	    AND vtiger_products2products_rel.relation_type = 10";
 	$result = $adb->query($query);
 	$pieces = $adb->num_rows($result);
 	if( $pieces > 0) {
-	    $product_line[++$j]["Product Name"] = "";
-	    $product_line[$j]["Description"] = "consisting of:";
-	    $product_line[$j]["Qty"] = "";
-	    $product_line[$j]["Price"] = "";
-	    $product_line[$j]["Discount"] = "";
-	    $product_line[$j]["Total"] = "";
-	    for( $pl=0; $pl<$pieces; $pl++) {
-	        $product_line[++$j]["Product Name"] = "";
-		$product_line[$j]["Description"] =
-		    $adb->query_result( $result, $pl, "productname");
-		$product_line[$j]["Qty"] =
-		    $adb->query_result( $result, $pl, "quantity");
-		$product_line[$j]["Price"] = "";
-		$product_line[$j]["Discount"] = "";
-		$product_line[$j]["Total"] = "";
-	    }
+	    throw new Exception("multiple pieces not yet supported !");
 	}
 }
 
-//echo '<pre>Product Details ==>';print_r($product_line);echo '</pre>';
-//echo '<pre>';print_r($associated_products);echo '</pre>';
-
 // ************************ END POPULATE DATA ***************************8
 
-$page_num='1';
-$pdf = new PDF( 'P', 'mm', 'A4' );
-$pdf->Open();
-
-$num_pages=ceil(count($product_line)/$products_per_page);
-
-
-$current_product=0;
-for($l=0;$l<$num_pages;$l++)
-{
-	$line=array();
-	if($num_pages == $page_num)
-		$lastpage=1;
-
-	while($current_product != $page_num*$products_per_page)
-	{
-		$line[]=$product_line[$current_product];
-		$current_product++;
-	}
-
-	//if bottom > 145 then we skip the Description and T&C in every
-	//page and display only in lastpage
-	//if you want to display the description and T&C in each page then
-	//set the display_desc_tc='true' and bottom <= 145 in pdfconfig.php
-	$pdf->AddPage();
-	if( $page_num == "1") {
-	    include("pdf_templates/".$template."/firstpage/header.php");
-	    include("pdf_templates/".$template."/firstpage/body.php");
-	    if($display_desc_tc == 'true' && $bottom <= 145)
-		include("pdf_templates/".$template."/firstpage/footer.php");
-	} else {
-	    include("pdf_templates/".$template."/pages/header.php");
-	    include("pdf_templates/".$template."/pages/body.php");
-	    if($display_desc_tc == 'true' && $bottom <= 145)
-		include("pdf_templates/".$template."/pages/footer.php");
-	}
-
-	$page_num++;
-
-	if (($endpage) && ($lastpage))
-	{
-	    $pdf->AddPage();
-	    include("pdf_templates/".$template."/lastpage/header.php");
-	    include("pdf_templates/".$template."/lastpage/body.php");
-	    include("pdf_templates/".$template."/lastpage/footer.php");
-	}
-}
-
-
-$pdf->Output('Invoice-'.$crmid.'.pdf','D'); //added file name to make it work in IE, also forces the download giving the user the option to save
+$render->addData(array
+(
+    'valid_until'		=> $focus->column_fields["duedate"],
+    'description'		=> from_html($focus->column_fields["description"]),
+    'conditions'		=> from_html($focus->column_fields["terms_conditions"]),
+    'tax_type'			=> $focus->column_fields['hdnTaxType'],
+    'ident'			=> $focus->column_fields['invoice_no'],
+    'contact:name'		=> getContactName($focus->column_fields["contact_id"]),
+    'company:name'		=> $orgdetails["name"],
+    'company:addr:city'		=> $orgdetails["city"],
+    'company:addr:pcode'	=> $orgdetails["code"],
+    'company:addr:street'	=> $orgdetails["address"],
+    'company:addr:country'	=> $orgdetails["country"],
+    'company:addr:state'	=> $orgdetails["state"],
+    'company:phone'		=> $orgdetails["phone"],
+    'company:fax'		=> $orgdetails["fax"],
+    'company:website'		=> $orgdetails["website"],
+    'customer:name'		=> getAccountName($focus->column_fields[account_id]),
+    'shipping:addr:city'	=> $focus->column_fields["ship_city"],
+    'shipping:addr:pcode'	=> $focus->column_fields["ship_code"],
+    'shipping:addr:street'	=> $focus->column_fields["ship_street"],
+    'shipping:addr:country'	=> $ship_country = $focus->column_fields["ship_country"],
+    'shipping:addr:state'	=> $focus->column_fields["ship_state"],
+    'billing:addr:city'		=> $focus->column_fields["bill_city"],
+    'billing:addr:pcode'	=> $focus->column_fields["bill_code"],
+    'billing:addr:street'	=> $focus->column_fields["bill_street"],
+    'billing:addr:country'	=> $focus->column_fields["bill_country"],
+    'billing:addr:state'	=> $focus->column_fields["bill_state"]
+));
 
-// Added to fix annoying bug that includes HTML in your PDF
+$render->sendHTTPOutput();
 exit();
-?>
-------------- next part --------------
diff -ruN htdocs.orig/templates/tex/default/config.php htdocs/templates/tex/default/config.php
--- htdocs.orig/templates/tex/default/config.php	1970-01-01 01:00:00.000000000 +0100
+++ htdocs/templates/tex/default/config.php	2007-05-09 20:00:54.000000000 +0200
@@ -0,0 +1,7 @@
+<?php
+
+$tex_template_config = array 
+(
+    'lang'	=> 'de',
+    'tex2pdf'	=> 'pdflatex'
+);
diff -ruN htdocs.orig/templates/tex/default/invoice/item.texi htdocs/templates/tex/default/invoice/item.texi
--- htdocs.orig/templates/tex/default/invoice/item.texi	1970-01-01 01:00:00.000000000 +0100
+++ htdocs/templates/tex/default/invoice/item.texi	2007-05-10 14:25:30.000000000 +0200
@@ -0,0 +1,2 @@
+::Item:Name:: \ifempty{::Item:Comment::}{}{(::Item:Comment::)} & ::Item:Price:: \Euro & ::Item:Amount:: & ::Item:Total:: \Euro \\
+\hline
diff -ruN htdocs.orig/templates/tex/default/invoice/main.texi htdocs/templates/tex/default/invoice/main.texi
--- htdocs.orig/templates/tex/default/invoice/main.texi	1970-01-01 01:00:00.000000000 +0100
+++ htdocs/templates/tex/default/invoice/main.texi	2007-05-10 14:15:53.000000000 +0200
@@ -0,0 +1,53 @@
+\def\ResourcePrefix{::TemplateDir::/resource}
+\input \ResourcePrefix/bill.tex
+
+\def\ifempty#1#2#3{\def\inner{#1}\ifx\inner\empty
+   #2\else #3\fi }
+
+\begin{document}
+    \letterInit
+    \begin{letter}{%
+            ::Customer:Addr:Street:: \ \\
+	    ::Customer:Addr:PCode::\ ::Customer:Addr:City:: \ \\
+           \ \\[\medskipamount]
+	}
+
+	\opening{\Large Ihre Rechnung:\normalsize~~~ ::Bill:Ident::
+%%	~~~~~~~~~~vom:~~::BillDate::
+	}
+
+	\setlength\LTleft{0pt}
+	\setlength\LTright{72pt}
+	\begin{longtable}{|p{300pt}|r|r|r|}
+	    \hline
+	    Leistung         & Preis     & Menge     & Summe 	\\
+	    \hline
+	    \endhead
+	    \hline
+	    \hline
+	    \multicolumn{3}{|l|}{Rechnungsbetrag} & ::Bill:Total:: \Euro \\
+	    \hline
+	    \multicolumn{3}{|l|}{Umsatzsteuer}    & ::Bill:Taxes:: \Euro \\
+	    \hline
+	    \hline
+	    \multicolumn{3}{|l|}{Gesamt}          & ::Bill:Topay:: \Euro \\
+	    \hline
+	    \noalign{
+		\vspace{12pt}
+		\small
+		Soweit nicht anders angegeben entspricht das Lieferdatum
+		dem Rechnungsdatum
+	    }
+	    \noalign{
+		\vspace{12pt}
+		\normalsize
+		Bitte {\"u}berweisen Sie den f{\"a}lligen Betrag binnen 
+		10~Tagen auf eines unserer Konten. \newline
+		Die Ware bleibt bis zur vollst{\"a}ndigen Bezahlung Eigentum 
+		von metux IT service.
+	    }	    
+	    \endlastfoot
+	    ::Items::
+	\end{longtable} 
+    \end{letter}
+\end{document}
diff -ruN htdocs.orig/templates/tex/default/resource/bill.tex htdocs/templates/tex/default/resource/bill.tex
--- htdocs.orig/templates/tex/default/resource/bill.tex	1970-01-01 01:00:00.000000000 +0100
+++ htdocs/templates/tex/default/resource/bill.tex	2007-05-09 23:55:35.000000000 +0200
@@ -0,0 +1,22 @@
+\input{\ResourcePrefix/metux.tex}
+
+\documentclass[a4paper,bottom=0cm,fromalign=center,fromlogo=true]{scrlttr2}
+\usepackage{epsfig}
+\usepackage{longtable}
+
+\usepackage{ngerman}
+\usepackage[latin1]{inputenc}
+%usepackage{fancyhdr}
+%pagestyle{fancy}
+
+% brief-init
+\newcommand\letterInit{%
+    \captionsgerman
+    \dategerman
+    \firsthead{\metuxHeader}
+    \firstfoot{\metuxFooter}
+    \setkomavar{fromname}{metux IT service}
+    \setkomavar{fromaddress}{Heydaer Stra{\ss}e 23, 99338 Plaue}
+}
+
+\newcommand\Euro{Euro}
diff -ruN htdocs.orig/templates/tex/default/resource/header.eps htdocs/templates/tex/default/resource/header.eps
--- htdocs.orig/templates/tex/default/resource/header.eps	1970-01-01 01:00:00.000000000 +0100
+++ htdocs/templates/tex/default/resource/header.eps	2002-09-17 01:45:21.000000000 +0200
@@ -0,0 +1,178 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Title: header.eps
+%%Creator: fig2dev Version 3.2 Patchlevel 3d
+%%CreationDate: Tue Jul 30 18:35:09 2002
+%%For: ems at nibiru.metux.de ()
+%%BoundingBox: 0 0 643 88
+%%Magnification: 1.0000
+%%EndComments
+/$F2psDict 200 dict def
+$F2psDict begin
+$F2psDict /mtrx matrix put
+/col-1 {0 setgray} bind def
+/col0 {0.000 0.000 0.000 srgb} bind def
+/col1 {0.000 0.000 1.000 srgb} bind def
+/col2 {0.000 1.000 0.000 srgb} bind def
+/col3 {0.000 1.000 1.000 srgb} bind def
+/col4 {1.000 0.000 0.000 srgb} bind def
+/col5 {1.000 0.000 1.000 srgb} bind def
+/col6 {1.000 1.000 0.000 srgb} bind def
+/col7 {1.000 1.000 1.000 srgb} bind def
+/col8 {0.000 0.000 0.560 srgb} bind def
+/col9 {0.000 0.000 0.690 srgb} bind def
+/col10 {0.000 0.000 0.820 srgb} bind def
+/col11 {0.530 0.810 1.000 srgb} bind def
+/col12 {0.000 0.560 0.000 srgb} bind def
+/col13 {0.000 0.690 0.000 srgb} bind def
+/col14 {0.000 0.820 0.000 srgb} bind def
+/col15 {0.000 0.560 0.560 srgb} bind def
+/col16 {0.000 0.690 0.690 srgb} bind def
+/col17 {0.000 0.820 0.820 srgb} bind def
+/col18 {0.560 0.000 0.000 srgb} bind def
+/col19 {0.690 0.000 0.000 srgb} bind def
+/col20 {0.820 0.000 0.000 srgb} bind def
+/col21 {0.560 0.000 0.560 srgb} bind def
+/col22 {0.690 0.000 0.690 srgb} bind def
+/col23 {0.820 0.000 0.820 srgb} bind def
+/col24 {0.500 0.190 0.000 srgb} bind def
+/col25 {0.630 0.250 0.000 srgb} bind def
+/col26 {0.750 0.380 0.000 srgb} bind def
+/col27 {1.000 0.500 0.500 srgb} bind def
+/col28 {1.000 0.630 0.630 srgb} bind def
+/col29 {1.000 0.750 0.750 srgb} bind def
+/col30 {1.000 0.880 0.880 srgb} bind def
+/col31 {1.000 0.840 0.000 srgb} bind def
+
+end
+save
+newpath 0 88 moveto 0 0 lineto 643 0 lineto 643 88 lineto closepath clip newpath
+-4.5 96.9 translate
+1 -1 scale
+
+/cp {closepath} bind def
+/ef {eofill} bind def
+/gr {grestore} bind def
+/gs {gsave} bind def
+/sa {save} bind def
+/rs {restore} bind def
+/l {lineto} bind def
+/m {moveto} bind def
+/rm {rmoveto} bind def
+/n {newpath} bind def
+/s {stroke} bind def
+/sh {show} bind def
+/slc {setlinecap} bind def
+/slj {setlinejoin} bind def
+/slw {setlinewidth} bind def
+/srgb {setrgbcolor} bind def
+/rot {rotate} bind def
+/sc {scale} bind def
+/sd {setdash} bind def
+/ff {findfont} bind def
+/sf {setfont} bind def
+/scf {scalefont} bind def
+/sw {stringwidth} bind def
+/tr {translate} bind def
+/tnt {dup dup currentrgbcolor
+  4 -2 roll dup 1 exch sub 3 -1 roll mul add
+  4 -2 roll dup 1 exch sub 3 -1 roll mul add
+  4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb}
+  bind def
+/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul
+  4 -2 roll mul srgb} bind def
+/reencdict 12 dict def /ReEncode { reencdict begin
+/newcodesandnames exch def /newfontname exch def /basefontname exch def
+/basefontdict basefontname findfont def /newfont basefontdict maxlength dict def
+basefontdict { exch dup /FID ne { dup /Encoding eq
+{ exch dup length array copy newfont 3 1 roll put }
+{ exch newfont 3 1 roll put } ifelse } { pop pop } ifelse } forall
+newfont /FontName newfontname put newcodesandnames aload pop
+128 1 255 { newfont /Encoding get exch /.notdef put } for
+newcodesandnames length 2 idiv { newfont /Encoding get 3 1 roll put } repeat
+newfontname newfont definefont pop end } def
+/isovec [
+8#055 /minus 8#200 /grave 8#201 /acute 8#202 /circumflex 8#203 /tilde
+8#204 /macron 8#205 /breve 8#206 /dotaccent 8#207 /dieresis
+8#210 /ring 8#211 /cedilla 8#212 /hungarumlaut 8#213 /ogonek 8#214 /caron
+8#220 /dotlessi 8#230 /oe 8#231 /OE
+8#240 /space 8#241 /exclamdown 8#242 /cent 8#243 /sterling
+8#244 /currency 8#245 /yen 8#246 /brokenbar 8#247 /section 8#250 /dieresis
+8#251 /copyright 8#252 /ordfeminine 8#253 /guillemotleft 8#254 /logicalnot
+8#255 /hyphen 8#256 /registered 8#257 /macron 8#260 /degree 8#261 /plusminus
+8#262 /twosuperior 8#263 /threesuperior 8#264 /acute 8#265 /mu 8#266 /paragraph
+8#267 /periodcentered 8#270 /cedilla 8#271 /onesuperior 8#272 /ordmasculine
+8#273 /guillemotright 8#274 /onequarter 8#275 /onehalf
+8#276 /threequarters 8#277 /questiondown 8#300 /Agrave 8#301 /Aacute
+8#302 /Acircumflex 8#303 /Atilde 8#304 /Adieresis 8#305 /Aring
+8#306 /AE 8#307 /Ccedilla 8#310 /Egrave 8#311 /Eacute
+8#312 /Ecircumflex 8#313 /Edieresis 8#314 /Igrave 8#315 /Iacute
+8#316 /Icircumflex 8#317 /Idieresis 8#320 /Eth 8#321 /Ntilde 8#322 /Ograve
+8#323 /Oacute 8#324 /Ocircumflex 8#325 /Otilde 8#326 /Odieresis 8#327 /multiply
+8#330 /Oslash 8#331 /Ugrave 8#332 /Uacute 8#333 /Ucircumflex
+8#334 /Udieresis 8#335 /Yacute 8#336 /Thorn 8#337 /germandbls 8#340 /agrave
+8#341 /aacute 8#342 /acircumflex 8#343 /atilde 8#344 /adieresis 8#345 /aring
+8#346 /ae 8#347 /ccedilla 8#350 /egrave 8#351 /eacute
+8#352 /ecircumflex 8#353 /edieresis 8#354 /igrave 8#355 /iacute
+8#356 /icircumflex 8#357 /idieresis 8#360 /eth 8#361 /ntilde 8#362 /ograve
+8#363 /oacute 8#364 /ocircumflex 8#365 /otilde 8#366 /odieresis 8#367 /divide
+8#370 /oslash 8#371 /ugrave 8#372 /uacute 8#373 /ucircumflex
+8#374 /udieresis 8#375 /yacute 8#376 /thorn 8#377 /ydieresis] def
+/Courier-Bold /Courier-Bold-iso isovec ReEncode
+/Times-Bold /Times-Bold-iso isovec ReEncode
+/Times-Roman /Times-Roman-iso isovec ReEncode
+/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def
+/$F2psEnd {$F2psEnteredState restore end} def
+
+$F2psBegin
+10 setmiterlimit
+ 0.06000 0.06000 sc
+%
+% Fig objects follow
+%
+/Times-Roman-iso ff 150.00 scf sf
+6600 1200 m
+gs 1 -1 sc (www.metux.de) col8 sh gr
+/Times-Roman-iso ff 150.00 scf sf
+6600 825 m
+gs 1 -1 sc (+49 36207 51833) col8 sh gr
+/Times-Roman-iso ff 150.00 scf sf
+6600 675 m
+gs 1 -1 sc (+49 174 7066481) col8 sh gr
+/Times-Roman-iso ff 150.00 scf sf
+6600 1350 m
+gs 1 -1 sc (contact @ metux.de) col8 sh gr
+/Courier-Bold-iso ff 180.00 scf sf
+1650 750 m
+gs 1 -1 sc (Ihr innovativer IT-Dienstleister) col25 sh gr
+/Times-Bold-iso ff 150.00 scf sf
+5700 1200 m
+gs 1 -1 sc (      Internet) col0 sh gr
+/Times-Bold-iso ff 150.00 scf sf
+5700 675 m
+gs 1 -1 sc (    Telephon) col0 sh gr
+/Times-Roman-iso ff 150.00 scf sf
+1650 1350 m
+gs 1 -1 sc (Advance Bank \(BLZ 702 300 00\), Kto-Nr: 200 72 64 206) col8 sh gr
+/Times-Roman-iso ff 150.00 scf sf
+1650 1575 m
+gs 1 -1 sc (Enrico Weigelt, Steuer-Nr: 154/286/05931) col8 sh gr
+/Times-Bold-iso ff 300.00 scf sf
+75 750 m
+gs 1 -1 sc (metux ITS) col9 sh gr
+/Courier-Bold-iso ff 150.00 scf sf
+150 1350 m
+gs 1 -1 sc (Bankverbindung:) col0 sh gr
+/Courier-Bold-iso ff 150.00 scf sf
+750 1575 m
+gs 1 -1 sc (Inhaber:) col0 sh gr
+/Courier-Bold-iso ff 150.00 scf sf
+225 1125 m
+gs 1 -1 sc (Hausanschrift:) col0 sh gr
+/Times-Roman-iso ff 150.00 scf sf
+1650 1125 m
+gs 1 -1 sc (Heydaer Strasse 23 99338 Plaue) col8 sh gr
+/Times-Roman-iso ff 180.00 scf sf
+10125 300 m
+gs 1 -1 sc (tricktext) col0 sh gr
+$F2psEnd
+rs
diff -ruN htdocs.orig/templates/tex/default/resource/header.fig htdocs/templates/tex/default/resource/header.fig
--- htdocs.orig/templates/tex/default/resource/header.fig	1970-01-01 01:00:00.000000000 +0100
+++ htdocs/templates/tex/default/resource/header.fig	2002-09-17 01:44:26.000000000 +0200
@@ -0,0 +1,24 @@
+#FIG 3.2
+Landscape
+Center
+Inches
+A4      
+100.00
+Single
+-2
+1200 2
+4 0 0 893 -1 14 10 -0.0000 4 135 1350 150 1350 Bankverbindung:\001
+4 0 0 890 -1 14 10 -0.0000 4 105 1260 225 1125 Hausanschrift:\001
+4 0 9 918 -1 2 20 0.0000 4 150 1005 75 750 metux ITS\001
+4 0 25 969 -1 14 12 -0.0000 4 135 3360 1650 750 Ihr innovativer IT-Dienstleister\001
+4 0 0 942 -1 2 10 0.0000 4 135 750 5700 675     Telephon\001
+4 0 8 991 -1 0 10 0.0000 4 105 1050 6600 675 +49 174 7066481\001
+4 0 8 997 -1 0 10 0.0000 4 105 1050 6600 825 +49 36207 51833\001
+4 0 8 999 -1 0 10 0.0000 4 105 990 6600 1200 www.metux.de\001
+4 0 0 946 -1 2 10 0.0000 4 105 765 5700 1200       Internet\001
+4 0 8 888 -1 0 10 0.0000 4 135 1935 1650 1125 Heydaer Strasse 23 99338 Plaue\001
+4 0 8 987 -1 0 10 0.0000 4 135 1230 6600 1350 contact @ metux.de\001
+4 0 8 933 -1 0 10 0.0000 4 135 3435 1650 1350 Advance Bank (BLZ 702 300 00), Kto-Nr: 200 72 64 206\001
+4 0 0 50 0 0 12 0.0000 4 135 645 10125 300 tricktext\001
+4 0 0 893 -1 14 10 0.0000 4 105 720 750 1575 Inhaber:\001
+4 0 8 933 -1 0 10 0.0000 4 135 2415 1650 1575 Enrico Weigelt, Steuer-Nr: 154/286/05931\001
diff -ruN htdocs.orig/templates/tex/default/resource/metux.tex htdocs/templates/tex/default/resource/metux.tex
--- htdocs.orig/templates/tex/default/resource/metux.tex	1970-01-01 01:00:00.000000000 +0100
+++ htdocs/templates/tex/default/resource/metux.tex	2007-05-09 23:56:59.000000000 +0200
@@ -0,0 +1,76 @@
+% Variablen .... %
+\def\metuxSignature{\epsfig{file=\ResourcePrefix/signature.png}}
+\def\metuxName{metux IT service}
+\def\metuxPhone{+49-36207-519931}
+\def\metuxFax{+49-36207-519932}
+\def\metuxEmail{weigelt at metux.de}
+\def\metuxUrl{www.metux.de}
+\def\metuxAddress{Heydaer Stra{\ss}e 23, 99338 Plaue}
+\def\metuxBankAccount{0972596900}
+\def\metuxBankCompany{Dresdner Bank AG}
+\def\metuxBankCode{82080000}
+\def\metuxBank{Kto: \metuxBankAccount, BLZ: \metuxBankCode, \metuxBankCompany}
+\def\metuxStrnr{154/286/05931}
+\def\metuxOwner{Enrico Weigelt}
+
+\def\nl{\ \\}
+\def\metuxGeomLeft{2cm}
+\def\metuxGeomRight{2cm}
+\def\metuxGeomBottom{1cm}
+\def\metuxGeomHead{1cm}
+\def\metuxGeomTop{0.5cm}
+
+\newcommand\metuxFooter
+{
+    \hrule
+    ~\newline
+    \parbox[l]{180pt}{
+	\small
+	\metuxName		\\
+	Inh. \metuxOwner	\\
+	\metuxAddress		\\
+	StNr: \metuxStrnr
+    }
+    \parbox[l]{180pt}{
+	\small
+	Bankverbindung:		\\
+	Kto: \metuxBankAccount	\\
+	BLZ: \metuxBankCode	\\
+	\metuxBankCompany
+    }
+    \parbox[l]{180pt}{
+	\small
+	Tel:  \metuxPhone	\\
+	Fax:   \metuxFax	\\
+	eMail: \metuxEmail	\\
+	WWW:   \metuxUrl
+    }
+}
+
+\newcommand\metuxHeader{\epsfig{file=\ResourcePrefix/logo.png}}
+%\newcommand\metuxHeader{\epsfig{file=\ResourcePrefix/logo.eps}}
+\newcommand\metuxInit{
+    \renewcommand{\headrulewidth}{0.5pt}
+    \renewcommand{\footrulewidth}{0.5pt}
+    \cfoot{\metuxFooter}
+    \chead{\metuxHeader}
+}
+
+% \newcommand\Euro{Euro}
+
+\def\metuxMFG{%
+    \noindent Mit freundlichem Gru\ss
+
+    \epsfig{\metuxSignature}
+	
+    \noindent Enrico Weigelt 	\\
+    metux IT service
+}
+
+\def\metuxMFGpriv{%
+    \noindent Mit freundlichem Gru\ss
+
+    \metuxSignature
+	
+    \noindent Enrico Weigelt
+}


More information about the vtigercrm-developers mailing list