Last active
December 14, 2015 17:09
-
-
Save jazzsequence/5120145 to your computer and use it in GitHub Desktop.
Event Espresso invoice template including surcharge/VAT support. This file should go in your /wp-content/uploads/espresso/gateways/invoice directory.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/*Custom Log Function Include*/ | |
// require('log.php'); | |
/*End Custom Log Function Include*/ | |
if (isset($_SESSION['espresso_session']['id'])) { | |
unset($_SESSION['espresso_session']['id']); | |
} | |
define('FPDF_FONTPATH', EVENT_ESPRESSO_PLUGINFULLPATH . 'class/fpdf/font/'); | |
require_once EVENT_ESPRESSO_PLUGINFULLPATH . 'class/fpdf/fpdf.php'; | |
global $espresso_premium; if ($espresso_premium != true) return; | |
global $wpdb, $org_options; | |
$invoice_payment_settings = get_option('event_espresso_invoice_payment_settings'); | |
/*Initial query | |
* We are using your initial query to pull the 'attendee_session' from the database. This will be used in the main query. | |
* It might be an idea to use the 'attendee_session'in the generated invoice url as you could then eliminate this query alltogether. | |
* Ideally we would use a stored procedure to eliminate the need to lines 19-65 | |
*/ | |
$attendees = $wpdb->get_results("SELECT * FROM ". EVENTS_ATTENDEE_TABLE ." WHERE registration_id ='" . $_REQUEST['registration_id'] . "' LIMIT 0,1"); | |
foreach ($attendees as $attendee){ | |
$attendee_id = $attendee->id; | |
$attendee_last = $attendee->lname; | |
$attendee_first = $attendee->fname; | |
$attendee_address = $attendee->address; | |
$attendee_city = $attendee->city; | |
$attendee_state = $attendee->state; | |
$attendee_zip = $attendee->zip; | |
$attendee_email = $attendee->email; | |
//$attendee_organization_name = $attendee->organization_name; | |
//$attendee_country = $attendee->country_id; | |
$phone = $attendee->phone; | |
$date = $attendee->date; | |
//$num_people = $attendee->quantity; | |
$payment_status = $attendee->payment_status; | |
$txn_type = $attendee->txn_type; | |
$attendee_session = $attendee->attendee_session; | |
$event_price_type = $attendee->price_option; | |
$amount_pd = $attendee->amount_pd; | |
$payment_date = $attendee->payment_date; | |
$event_id = $attendee->event_id; | |
$registration_id=$attendee->registration_id; | |
} | |
/* | |
* Calculate the total cost for each event in the basket (without surcharge, in our case VAT) | |
* @param integer $event_cost | |
* @param integer $quantity //value calculated by the query | |
* @return double $total_cost | |
*/ | |
function lh_calc_event_cost($event_cost, $quantity){ | |
return doubleval($event_cost * $quantity); | |
} | |
/* | |
* Calculate the surcharge on an event (in our case VAT) | |
* @param integer $surcharge | |
* @param integer $quantity | |
* @param integer $event_cost | |
* @return integer $event_surcharge | |
*/ | |
function lh_calc_event_tax($surcharge, $quantity, $event_cost){ | |
$surcharge_rate = '0.' . $surcharge; | |
return ($event_cost * $surcharge_rate) * $quantity; | |
} | |
/* | |
* Query to pull all the information we need for our invoice from the database. | |
* $multi_events formatted as a numerically indexed array. | |
* Using $attendee_session we can evaluate all of the events in a single order using a single query. | |
* Structure of $multi_events: | |
* array ( | |
* 0 => | |
* array ( | |
* 0 => <QUANTITY>, | |
* 1 => <EVENT NAME>, | |
* 2 => <EVENT DATE>, | |
* 3 => <EVENT COST>, | |
* 4 => <EVENT SURCHARGE>, | |
* ) | |
*/ | |
$multi_events = $wpdb->get_results("SELECT COUNT(*), " . EVENTS_DETAIL_TABLE . ".event_name, " . EVENTS_DETAIL_TABLE . ".start_date, " . EVENTS_PRICES_TABLE . ".event_cost, " . EVENTS_PRICES_TABLE . ".surcharge | |
FROM ". EVENTS_ATTENDEE_TABLE ." | |
LEFT JOIN " . EVENTS_DETAIL_TABLE . " ON " . EVENTS_ATTENDEE_TABLE . ".event_id = " . EVENTS_DETAIL_TABLE . ".id | |
LEFT JOIN " . EVENTS_PRICES_TABLE . " ON " . EVENTS_ATTENDEE_TABLE . ".event_id = " . EVENTS_PRICES_TABLE . ".event_id | |
WHERE " . EVENTS_ATTENDEE_TABLE . ".attendee_session = '" . $attendee_session . "' | |
GROUP BY " . EVENTS_DETAIL_TABLE . ".event_name;", ARRAY_N ); | |
//invoice_log::singleton()->log( array ( 'file' => __FILE__, 'function' => __FUNCTION__, 'status' => "sqldump = " . var_export($multi_events, true) ) ); | |
//Build the PDF | |
class PDF extends Espresso_FPDF | |
{ | |
//Page header | |
function Header() | |
{ | |
global $wpdb, $org_options; | |
$invoice_payment_settings = get_option('event_espresso_invoice_payment_settings'); | |
//Logo | |
if (trim($invoice_payment_settings['image_url']) !=''){ | |
$this->Image($invoice_payment_settings['image_url'],10,8,40,0);//Set the logo if it is available | |
}else{ | |
$this->SetFont('Arial','B',15); | |
$this->Cell(10,10,iconv("UTF-8", "ISO-8859-1",$org_options['organization']),0,0,'L');//If no logo, then display the organizatin name | |
} | |
//Arial bold 15 | |
$this->SetFont('Arial','B',15); | |
//Move to the right | |
$this->Cell(80); | |
//Title | |
$this->MultiCell(100,20,iconv("UTF-8", "ISO-8859-1",$invoice_payment_settings['pdf_title']),0,'R');//Set the right header | |
//Line break | |
$this->Ln(20); | |
} | |
function LoadData($file) | |
{ | |
$lines=$file; | |
$data=array(); | |
foreach($lines as $line) | |
$data[]=explode(';',chop($line)); | |
return $data; | |
} | |
//Better table | |
function ImprovedTable($header,$event_data) | |
{ | |
$options = get_option('events_organization_settings'); | |
$currency = $options['currency_symbol']; | |
//Column widths | |
/* | |
* Extra columns added to the table layout | |
*/ | |
$w=array(115,15,25,35); | |
//Header | |
for($i=0;$i<count($header);$i++) | |
$this->Cell($w[$i],7,$header[$i],1,0,'C'); | |
$this->Ln(); | |
$x = $this->GetX(); | |
$y = $this->GetY(); | |
/* | |
* The only modification needed to the function in order to display the extra data is | |
* an extra foreach loop. We also modified the positioning of the cells to account for the | |
* extra information we are displaying | |
*/ | |
foreach($event_data as $data){ | |
//invoice_log::singleton()->log( array ( 'file' => __FILE__, 'function' => __FUNCTION__, 'status' => "sqldump = " . var_export($event_data, true) ) ); | |
foreach($data as $row) | |
{ | |
//invoice_log::singleton()->log( array ( 'file' => __FILE__, 'function' => __FUNCTION__, 'status' => "sqldump = " . var_export($row, true) ) ); | |
$y1 = $this->GetY(); | |
$this->MultiCell($w[0],6,$row[0],'LBR'); | |
$y2 = $this->GetY(); | |
$yH = $y2 - $y1; | |
$this->SetXY($x + $w[0], $this->GetY() - $yH); | |
$this->Cell($w[1],$yH,$row[1],'LBR',0,'C'); | |
$this->Cell($w[2],$yH,$row[2],'LBR',0,'C'); | |
//$this->Cell($w[3],$yH,number_format($row[3],2, '.', ''),'LBR',0,'C'); | |
$this->Cell($w[3],$yH,html_entity_decode($currency, ENT_QUOTES, 'ISO-8859-15') . number_format($row[3],2,'.',''),'LBR',0,'C'); | |
$this->Ln(); | |
} | |
} | |
//Closure line | |
$this->Cell(array_sum($w),0,'','T'); | |
} | |
/* | |
* Function to display the totals that we have calculated. Mainly cosmetic. | |
* @param integer $sub_total (this is the total cost of the events without surcharge added) | |
* @param integer $vat (the total surcharge on the order) | |
*/ | |
function InvoiceTotals($sub_total, $vat, $surcharge){ | |
$options = get_option('events_organization_settings'); | |
$currency = $options['currency_symbol']; | |
$total_cost = $sub_total + $vat; | |
$this->SetFillColor(192,192,192); | |
//Print sub total | |
$this->Cell(155, 10, 'Subtotal excluding VAT:', 0, 0, 'R', true); | |
$this->Cell(35, 10, html_entity_decode($currency, ENT_QUOTES, 'ISO-8859-15') . number_format($sub_total,2, '.', ''), 0, 1, 'C', true); | |
//Print total VAT | |
$this->Cell(155, 10, 'VAT @ ' . $surcharge . '%:', 0, 0, 'R', true); | |
$this->Cell(35, 10, html_entity_decode($currency, ENT_QUOTES, 'ISO-8859-15') . number_format($vat,2, '.', ''), 0, 1, 'C', true); | |
//Print total cost | |
$this->Cell(155, 10, 'Total:', 0, 0, 'R'); | |
$this->Cell(35, 10, html_entity_decode($currency, ENT_QUOTES, 'ISO-8859-15') . number_format($total_cost,2, '.', ''), 0, 1, 'C'); | |
$this->Ln(20); | |
$this->Cell(190, 10, 'VAT registration number: XXX XXXX XX.', 0, 0, 'R'); // replace with your VAT ID or comment this line out | |
} | |
//Page footer | |
function Footer() | |
{ | |
//Position at 1.5 cm from bottom | |
$this->SetY(-15); | |
//Arial italic 8 | |
$this->SetFont('Arial','I',8); | |
//Page number | |
$this->Cell(0,10, __('Page','event_espresso').$this->PageNo().'/{nb}',0,0,'C'); | |
} | |
} | |
//Create a payment link | |
$payment_link = home_url() . "/?page_id=" . $org_options['return_url'] . "&id=" . $attendee_id; | |
//Instanciation of inherited class | |
$pdf=new PDF(); | |
$pdf->AliasNbPages(); | |
$pdf->SetAuthor(iconv("UTF-8", "ISO-8859-1",$org_options['organization'])); | |
$pdf->SetTitle(iconv("UTF-8", "ISO-8859-1", $attendee_id . $attendee_last . ' - ' . $invoice_payment_settings['pdf_title'])); | |
//$pdf->SetAutoPageBreak('auto'); | |
$pdf->AddPage(); | |
//Create the top right of invoice below header | |
$pdf->SetFont('Times','',12); | |
$pdf->Cell(180,0, __('Date: ','event_espresso'). date('m-d-Y'),0,1, 'R');//Set invoice date | |
$pdf->Cell(180,10,__('Primary Attendee ID: ','event_espresso'). $attendee_id,0,0, 'R');//Set Invoice number | |
$pdf->Ln(0); | |
//Set the top left of invoice below header | |
$pdf->SetFont('Times','BI',14); | |
$pdf->MultiCell(0,10,iconv("UTF-8", "ISO-8859-1",$invoice_payment_settings['payable_to']),0,'L');//Set payable to | |
$pdf->SetFont('Times','',12); | |
$pdf->MultiCell(50,5,iconv("UTF-8", "ISO-8859-1",$invoice_payment_settings['payment_address']),0, 'L');//Set address | |
$pdf->Ln(5); | |
//Set the biiling information | |
$pdf->SetFont('Times','B',12); | |
$pdf->Cell(50,5,__('Bill To: ','event_espresso'),0,1,'L');//Set biil to | |
$pdf->SetFont('Times','',12); | |
$pdf->Cell(50,5,iconv("UTF-8", "ISO-8859-1",$attendee_first . ' ' . $attendee_last),0,1, 'L');//Set attendee name | |
$pdf->Cell(50,5,$attendee_email,0,1,'L');//Set attendee email | |
//Set attendee address | |
$attendee_address != '' ? $pdf->Cell(100,5,$attendee_address,0,1,'L') :''; | |
$pdf->Cell(100,5,(iconv("UTF-8", "ISO-8859-1",$attendee_city != '' ? $attendee_city :''). ($attendee_state != '' ? ' ' . $attendee_state :'')),0,1,'L'); | |
$attendee_zip != '' ? $pdf->Cell(50,5,$attendee_zip,0,1,'L') :''; | |
$pdf->Ln(10); | |
//Build the payment link and instructions | |
$pdf->MultiCell(100,5,iconv("UTF-8", "ISO-8859-1",$invoice_payment_settings['pdf_instructions']),0,'L');//Set instructions | |
$pdf->Ln(10); | |
//Build the table for the event details | |
//Column titles | |
$header=array(__('Event Name','event_espresso'),__('Qty.','event_espresso'),__('Event Date','event_espresso'),__('Price','event_espresso')); | |
//Event Data | |
/* | |
* Here we have make multiple calls to the 'LoadData' function in order to format the data we pulled from the database. | |
* As we are simply patching your code, this was the simplest solution. | |
* | |
*/ | |
$tax_total = 0; | |
$cost_total = 0; | |
if($multi_events){ | |
foreach($multi_events as $s_event){ | |
$cost = lh_calc_event_cost($s_event[3], $s_event[0] ); | |
$event_data[] = $pdf->LoadData (array(iconv("UTF-8", "ISO-8859-1",$s_event[1]) . ';' . iconv("UTF-8", "ISO-8859-1", $s_event[0]) . ';' . date('m-d-Y',strtotime($s_event[2])) . ';' . doubleval($s_event[3]) . ';' ) ); | |
$tax_total += lh_calc_event_tax($s_event[4], $s_event[0], $s_event[3]); | |
$surcharge = $s_event[4]; | |
$cost_total += $cost; | |
} | |
$pdf->ImprovedTable($header, $event_data); | |
} | |
$pdf->Ln(); | |
/* | |
* Using the totals calculated above, add in the totals section of the pdf. | |
*/ | |
$pdf->InvoiceTotals($cost_total, $tax_total, $surcharge); | |
$pdf->Ln(10); | |
$pdf->SetFont('Arial','BU',20); | |
//$pdf->Cell(200,20,'Pay Online',0,1,'C',0,$payment_link);//Set payment link | |
$pdf->Output($attendee_id . '-' . $attendee_last.'.pdf','D'); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment