WooCommerce PDF Invoices & Packing Slips - Version 1.2.0

Version Description

  • Feature: Sequential invoice numbers (set upon invoice creation).
  • Feature: Invoice date (set upon invoice creation).
Download this release

Release Info

Developer pomegranate
Plugin Icon 128x128 WooCommerce PDF Invoices & Packing Slips
Version 1.2.0
Comparing to
See all releases

Code changes from version 1.1.6 to 1.2.0

includes/class-wcpdf-export.php CHANGED
@@ -34,8 +34,8 @@ if ( ! class_exists( 'WooCommerce_PDF_Invoices_Export' ) ) {
34
 
35
  $this->template_path = $this->template_settings['template_path'];
36
 
37
- add_action('wp_ajax_generate_wpo_wcpdf', array($this, 'generate_pdf_ajax'));
38
- add_filter( 'woocommerce_email_attachments', array( $this, 'attach_pdf_to_email' ), 99, 3);
39
  }
40
 
41
  /**
@@ -146,6 +146,8 @@ if ( ! class_exists( 'WooCommerce_PDF_Invoices_Export' ) ) {
146
  }
147
 
148
  $order_ids = (array) explode('x',$_GET['order_ids']);
 
 
149
 
150
  // User call from my-account page
151
  if ( isset( $_GET['my-account'] ) ) {
@@ -190,6 +192,8 @@ if ( ! class_exists( 'WooCommerce_PDF_Invoices_Export' ) ) {
190
  // Generate the output
191
  // $this->stream_pdf( $template_type, $order_ids, $filename );
192
 
 
 
193
  if (apply_filters('wpo_wcpdf_output_html', false, $template_type)) {
194
  // Output html to browser for debug
195
  // NOTE! images will be loaded with the server path by default
@@ -251,6 +255,37 @@ if ( ! class_exists( 'WooCommerce_PDF_Invoices_Export' ) ) {
251
  return $attachments;
252
  }
253
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
254
  /**
255
  * Return evaluated template contents
256
  */
@@ -294,14 +329,14 @@ if ( ! class_exists( 'WooCommerce_PDF_Invoices_Export' ) ) {
294
  // Set item quantity
295
  $data['quantity'] = $item['qty'];
296
 
297
- // Set the subtotal for the number of products
298
- $data['line_total'] = $item['line_total'];
299
- $data['line_tax'] = $item['line_tax'];
300
  $data['tax_rates'] = $this->get_tax_rate( $item['tax_class'], $item['line_total'], $item['line_tax'] );
301
 
302
- // Set the final subtotal for all products
303
- $data['line_subtotal'] = $item['line_subtotal'];
304
- $data['line_subtotal_tax'] = $item['line_subtotal_tax'];
305
  $data['ex_price'] = $this->get_formatted_item_price ( $item, 'total', 'excl' );
306
  $data['price'] = $this->get_formatted_item_price ( $item, 'total' );
307
 
@@ -376,25 +411,30 @@ if ( ! class_exists( 'WooCommerce_PDF_Invoices_Export' ) ) {
376
  if ( ! isset( $item['line_subtotal'] ) || ! isset( $item['line_subtotal_tax'] ) )
377
  return;
378
 
 
 
 
 
 
 
 
 
 
 
 
 
 
379
  if ( version_compare( WOOCOMMERCE_VERSION, '2.1' ) >= 0 ) {
380
  // WC 2.1 or newer is used
381
- if ( $tax_display == 'excl' ) {
382
- $item_price = wc_price( ($this->order->get_line_subtotal( $item )) / $divider, array( 'currency' => $this->order->get_order_currency() ) );
383
- } else {
384
- $item_price = wc_price( ($this->order->get_line_subtotal( $item, true )) / $divider, array('currency' => $this->order->get_order_currency()) );
385
- }
386
  } else {
387
- // Backwards compatibility
388
- if ( $tax_display == 'excl' ) {
389
- $item_price = woocommerce_price( ($this->order->get_line_subtotal( $item )) / $divider );
390
- } else {
391
- $item_price = woocommerce_price( ($this->order->get_line_subtotal( $item, true )) / $divider );
392
- }
393
  }
394
 
395
-
396
- return $item_price;
397
  }
 
398
  /**
399
  * Get the tax rates/percentages for a given tax class
400
  * @param string $tax_class tax class slug
34
 
35
  $this->template_path = $this->template_settings['template_path'];
36
 
37
+ add_action( 'wp_ajax_generate_wpo_wcpdf', array($this, 'generate_pdf_ajax' ));
38
+ add_filter( 'woocommerce_email_attachments', array( $this, 'attach_pdf_to_email' ), 99, 3);
39
  }
40
 
41
  /**
146
  }
147
 
148
  $order_ids = (array) explode('x',$_GET['order_ids']);
149
+ // Process oldest first: reverse $order_ids array
150
+ $order_ids = array_reverse($order_ids);
151
 
152
  // User call from my-account page
153
  if ( isset( $_GET['my-account'] ) ) {
192
  // Generate the output
193
  // $this->stream_pdf( $template_type, $order_ids, $filename );
194
 
195
+ // die($this->process_template( $template_type, $order_ids )); // or use the filter switch below!
196
+
197
  if (apply_filters('wpo_wcpdf_output_html', false, $template_type)) {
198
  // Output html to browser for debug
199
  // NOTE! images will be loaded with the server path by default
255
  return $attachments;
256
  }
257
 
258
+ public function get_invoice_number( $order_id ) {
259
+ // Based on code from WooCommerce Sequential Order Numbers
260
+ global $wpdb;
261
+
262
+ $invoice_number = get_post_meta( $order_id, '_wcpdf_invoice_number', true );
263
+
264
+ // add invoice number if it doesn't exist
265
+ if ( empty($invoice_number) || !isset($invoice_number) ) {
266
+ // attempt the query up to 3 times for a much higher success rate if it fails (due to Deadlock)
267
+ // this seems to me like the safest way to avoid order number clashes
268
+ $success = false;
269
+ for ( $i = 0; $i < 3 && ! $success; $i++ ) {
270
+ // Get maximum invoice number in the DB
271
+ $max_invoice_number = $wpdb->get_var( 'SELECT max(cast(meta_value as UNSIGNED)) from ' . $wpdb->postmeta . ' where meta_key="_wcpdf_invoice_number"' );
272
+
273
+ if ($max_invoice_number == '') {
274
+ // First time! Use order number as starting point.
275
+ $order_number = ltrim($this->order->get_order_number(), '#');
276
+ $invoice_number = $order_number;
277
+ } else {
278
+ $invoice_number = $max_invoice_number+1;
279
+ }
280
+
281
+ $success = $wpdb->query( 'INSERT INTO ' . $wpdb->postmeta . ' (post_id,meta_key,meta_value) VALUES (' . $order_id . ',"_wcpdf_invoice_number", '.$invoice_number.')' );
282
+ }
283
+ // die($invoice_number);
284
+ }
285
+
286
+ return $invoice_number;
287
+ }
288
+
289
  /**
290
  * Return evaluated template contents
291
  */
329
  // Set item quantity
330
  $data['quantity'] = $item['qty'];
331
 
332
+ // Set the line total (=before discount)
333
+ $data['line_total'] = $this->wc_price( $item['line_total'] );
334
+ $data['line_tax'] = $this->wc_price( $item['line_tax'] );
335
  $data['tax_rates'] = $this->get_tax_rate( $item['tax_class'], $item['line_total'], $item['line_tax'] );
336
 
337
+ // Set the line subtotal
338
+ $data['line_subtotal'] = $this->wc_price( $item['line_subtotal'] );
339
+ $data['line_subtotal_tax'] = $this->wc_price( $item['line_subtotal_tax'] );
340
  $data['ex_price'] = $this->get_formatted_item_price ( $item, 'total', 'excl' );
341
  $data['price'] = $this->get_formatted_item_price ( $item, 'total' );
342
 
411
  if ( ! isset( $item['line_subtotal'] ) || ! isset( $item['line_subtotal_tax'] ) )
412
  return;
413
 
414
+ if ( $tax_display == 'excl' ) {
415
+ $item_price = $this->wc_price( ($this->order->get_line_subtotal( $item )) / $divider );
416
+ } else {
417
+ $item_price = $this->wc_price( ($this->order->get_line_subtotal( $item, true )) / $divider );
418
+ }
419
+
420
+ return $item_price;
421
+ }
422
+
423
+ /**
424
+ * wrapper for wc2.1 depricated price function
425
+ */
426
+ public function wc_price( $price, $args = array() ) {
427
  if ( version_compare( WOOCOMMERCE_VERSION, '2.1' ) >= 0 ) {
428
  // WC 2.1 or newer is used
429
+ $args['currency'] = $this->order->get_order_currency();
430
+ $formatted_price = wc_price( $price, $args );
 
 
 
431
  } else {
432
+ $formatted_price = woocommerce_price( $price );
 
 
 
 
 
433
  }
434
 
435
+ return $formatted_price;
 
436
  }
437
+
438
  /**
439
  * Get the tax rates/percentages for a given tax class
440
  * @param string $tax_class tax class slug
includes/class-wcpdf-settings.php CHANGED
@@ -316,6 +316,39 @@ if ( ! class_exists( 'WooCommerce_PDF_Invoices_Settings' ) ) {
316
  )
317
  );
318
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
319
  // Section.
320
  add_settings_section(
321
  'extra_template_fields',
316
  )
317
  );
318
 
319
+ add_settings_field(
320
+ 'display_number',
321
+ __( 'Number to display on invoice', 'wpo_wcpdf' ),
322
+ array( &$this, 'select_element_callback' ),
323
+ $option,
324
+ 'template_settings',
325
+ array(
326
+ 'menu' => $option,
327
+ 'id' => 'display_number',
328
+ 'options' => array(
329
+ 'order_number' => __( 'WooCommerce order number' , 'wpo_wcpdf' ),
330
+ 'invoice_number'=> __( 'Built-in sequential invoice number' , 'wpo_wcpdf' ),
331
+ ),
332
+ 'description' => __( 'If you are using the WooCommerce Sequential Order Numbers plugin, select the WooCommerce order number', 'wpo_wcpdf' ),
333
+ )
334
+ );
335
+
336
+ add_settings_field(
337
+ 'display_date',
338
+ __( 'Date to display on invoice', 'wpo_wcpdf' ),
339
+ array( &$this, 'select_element_callback' ),
340
+ $option,
341
+ 'template_settings',
342
+ array(
343
+ 'menu' => $option,
344
+ 'id' => 'display_date',
345
+ 'options' => array(
346
+ 'order_date' => __( 'Order date' , 'wpo_wcpdf' ),
347
+ 'invoice_date' => __( 'Invoice date' , 'wpo_wcpdf' ),
348
+ ),
349
+ )
350
+ );
351
+
352
  // Section.
353
  add_settings_section(
354
  'extra_template_fields',
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: pomegranate
3
  Tags: woocommerce, print, pdf, bulk, packing slips, invoices, delivery notes, invoice, packing slip, export, email
4
  Requires at least: 3.5 and WooCommerce 2.0
5
  Tested up to: 3.8 and WooCommerce 2.1
6
- Stable tag: 1.1.6
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
@@ -17,6 +17,7 @@ This WooCommerce extension automatically adds a PDF invoice to the order confirm
17
  * Export invoices or packing slips to PDF (individually or in bulk)
18
  * Automatically attach invoice PDF to order confirmation email
19
  * Users can download their invoices from the My Account page
 
20
  * **Available in: Dutch, English, French, German, Hungarian, Italian & Spanish**
21
 
22
  = Fully customizable =
@@ -71,6 +72,22 @@ This plugin is translation ready, which means that you can translate it using st
71
  7. Enter the translations. invoice and packing-slip now have two translation fields, single & plural. Note that this is a filename, so replace spaces with a - just to be sure!
72
  8. Save as `wpo_wcpdf-xx_XX.po`, where you replace xx_XX with your language code & country code suffix (da_DK, pl_PL, de_DE etc.)
73
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
  = Fatal error: Allowed memory size of ######## bytes exhausted (tried to allocate ### bytes) =
75
 
76
  This usually only happens on batch actions. PDF creation is a memory intensive job, especially if it includes several pages with images. Go to WooCommerce > System Status to check your WP Memory Limit. We recommend setting it to 128mb or more.
@@ -84,6 +101,10 @@ This usually only happens on batch actions. PDF creation is a memory intensive j
84
 
85
  == Changelog ==
86
 
 
 
 
 
87
  = 1.1.6 =
88
  * Feature: Hungarian translations added - thanks Joseph!
89
  * Tweak: Better debug code.
3
  Tags: woocommerce, print, pdf, bulk, packing slips, invoices, delivery notes, invoice, packing slip, export, email
4
  Requires at least: 3.5 and WooCommerce 2.0
5
  Tested up to: 3.8 and WooCommerce 2.1
6
+ Stable tag: 1.2.0
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
17
  * Export invoices or packing slips to PDF (individually or in bulk)
18
  * Automatically attach invoice PDF to order confirmation email
19
  * Users can download their invoices from the My Account page
20
+ * Sequential invoice numbers (fully customizable with filters, see the [FAQ](http://wordpress.org/plugins/woocommerce-pdf-invoices-packing-slips/faq/))
21
  * **Available in: Dutch, English, French, German, Hungarian, Italian & Spanish**
22
 
23
  = Fully customizable =
72
  7. Enter the translations. invoice and packing-slip now have two translation fields, single & plural. Note that this is a filename, so replace spaces with a - just to be sure!
73
  8. Save as `wpo_wcpdf-xx_XX.po`, where you replace xx_XX with your language code & country code suffix (da_DK, pl_PL, de_DE etc.)
74
 
75
+ = How to I add a prefix, suffix or offset to the invoice number? =
76
+
77
+ You can do this via a filter in your theme's `functions.php` (Some themes have a "custom functions" area in the settings).
78
+
79
+ `
80
+ add_filter( 'wpo_wcpdf_invoice_number', 'wpo_wcpdf_invoice_number', 10, 4 );
81
+
82
+ function wpo_wcpdf_invoice_number( $invoice_number, $order_number, $order_id, $order_date ) {
83
+ $prefix = 'ABC';
84
+ $order_year = date_i18n( 'Y', strtotime( $order_date ) );
85
+ $offset = 10000;
86
+ $invoice_number = $prefix . $order_year . ($offset + $invoice_number);
87
+ return $invoice_number;
88
+ }
89
+ `
90
+
91
  = Fatal error: Allowed memory size of ######## bytes exhausted (tried to allocate ### bytes) =
92
 
93
  This usually only happens on batch actions. PDF creation is a memory intensive job, especially if it includes several pages with images. Go to WooCommerce > System Status to check your WP Memory Limit. We recommend setting it to 128mb or more.
101
 
102
  == Changelog ==
103
 
104
+ = 1.2.0 =
105
+ * Feature: Sequential invoice numbers (set upon invoice creation).
106
+ * Feature: Invoice date (set upon invoice creation).
107
+
108
  = 1.1.6 =
109
  * Feature: Hungarian translations added - thanks Joseph!
110
  * Tweak: Better debug code.
woocommerce-pdf-invoices-packingslips.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: WooCommerce PDF Invoices & Packing Slips
4
  * Plugin URI: http://www.wpovernight.com
5
  * Description: Create, print & email PDF invoices & packing slips for WooCommerce orders.
6
- * Version: 1.1.6
7
  * Author: Ewout Fernhout
8
  * Author URI: http://www.wpovernight.com
9
  * License: GPLv2 or later
@@ -263,30 +263,74 @@ if ( !class_exists( 'WooCommerce_PDF_Invoices' ) ) {
263
  echo $this->get_shipping_method();
264
  }
265
 
266
-
267
  /**
268
- * Return/Show order number
269
  */
270
  public function get_order_number() {
271
  // Trim the hash to have a clean number but still
272
  // support any filters that were applied before.
273
  $order_number = ltrim($this->export->order->get_order_number(), '#');
274
- return $order_number;
275
  }
276
  public function order_number() {
277
- echo $this->get_order_number();
 
 
 
 
 
 
278
  }
279
-
280
  /**
281
  * Return/Show the order date
282
  */
283
  public function get_order_date() {
284
- return apply_filters( 'wpo_wcpdf_order_date', date_i18n( get_option( 'date_format' ), strtotime( $this->export->order->order_date ) ) );
 
285
  }
286
  public function order_date() {
287
- echo $this->get_order_date();
 
 
 
 
 
 
 
288
  }
289
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
290
  /**
291
  * Return the order items
292
  */
3
  * Plugin Name: WooCommerce PDF Invoices & Packing Slips
4
  * Plugin URI: http://www.wpovernight.com
5
  * Description: Create, print & email PDF invoices & packing slips for WooCommerce orders.
6
+ * Version: 1.2.0
7
  * Author: Ewout Fernhout
8
  * Author URI: http://www.wpovernight.com
9
  * License: GPLv2 or later
263
  echo $this->get_shipping_method();
264
  }
265
 
 
266
  /**
267
+ * Return/Show order number (or invoice number)
268
  */
269
  public function get_order_number() {
270
  // Trim the hash to have a clean number but still
271
  // support any filters that were applied before.
272
  $order_number = ltrim($this->export->order->get_order_number(), '#');
273
+ return apply_filters( 'wpo_wcpdf_order_number', $order_number);
274
  }
275
  public function order_number() {
276
+ // Check for setting: not very semantical but helps a lot for backwards compatibiity!
277
+ $display_number = isset($this->settings->template_settings['display_number'])?$this->settings->template_settings['display_number']:'order_number';
278
+ if ( $display_number == 'invoice_number' ) {
279
+ echo $this->get_invoice_number();
280
+ } else {
281
+ echo $this->get_order_number();
282
+ }
283
  }
284
+
285
  /**
286
  * Return/Show the order date
287
  */
288
  public function get_order_date() {
289
+ $date = date_i18n( get_option( 'date_format' ), strtotime( $this->export->order->order_date ) );
290
+ return apply_filters( 'wpo_wcpdf_order_date', $date );
291
  }
292
  public function order_date() {
293
+ // Check for setting: not very semantical but helps a lot for backwards compatibiity!
294
+ $display_date = isset($this->settings->template_settings['display_date'])?$this->settings->template_settings['display_date']:'order_date';
295
+
296
+ if ( $display_date == 'order_date' ) {
297
+ echo $this->get_order_date();
298
+ } else {
299
+ echo $this->get_invoice_date();
300
+ }
301
  }
302
+
303
+ /**
304
+ * Return/Show invoice number
305
+ */
306
+ public function get_invoice_number() {
307
+ $invoice_number = $this->export->get_invoice_number( $this->export->order->id );
308
+ return apply_filters( 'wpo_wcpdf_invoice_number', $invoice_number, $this->get_order_number(), $this->export->order->id, $this->get_order_date() );
309
+ }
310
+ public function invoice_number() {
311
+ echo $this->get_invoice_number();
312
+ }
313
+
314
+ /**
315
+ * Return/Show the invoice date
316
+ */
317
+ public function get_invoice_date() {
318
+ $invoice_date = get_post_meta($this->export->order->id,'_wcpdf_invoice_date',true);
319
+
320
+ // add invoice date if it doesn't exist
321
+ if ( empty($invoice_date) || !isset($invoice_date) ) {
322
+ $invoice_date = current_time('mysql');
323
+ update_post_meta( $this->export->order->id, '_wcpdf_invoice_date', $invoice_date );
324
+ }
325
+
326
+ $formatted_invoice_date = date_i18n( get_option( 'date_format' ), strtotime( $invoice_date ) );
327
+
328
+ return apply_filters( 'wpo_wcpdf_invoice_date', $formatted_invoice_date, $invoice_date );
329
+ }
330
+ public function invoice_date() {
331
+ echo $this->get_invoice_date();
332
+ }
333
+
334
  /**
335
  * Return the order items
336
  */