Skip to content

Early-bird lifetime licence: $199 once, for the first 200 buyers only. See the offer

Receipt or invoice in the block checkout (Απόδειξη / Τιμολόγιο)

The block checkout version: customers choose a receipt or an invoice; for an invoice they fill in company name, VAT number (ΑΦΜ, checked), tax office (ΔΟΥ) and business activity. The details are saved with the order and shown in the admin, the emails and the order page.

  • Type PHP
  • Runs Everywhere (runs as WordPress loads)
  • Needs WooCommerce
  • Category Greek e-shop
  • Tested with WordPress 7.1, WooCommerce 11.1
PHP
<?php

// Labels are in Greek; change them if you like.
$document_label = 'Παραστατικό';
$choices        = array(
	'receipt' => 'Απόδειξη',
	'invoice' => 'Τιμολόγιο',
);
$fields         = array(
	'company'    => 'Επωνυμία εταιρείας',
	'vat'        => 'ΑΦΜ',
	'tax-office' => 'ΔΟΥ',
	'activity'   => 'Δραστηριότητα',
);
$vat_error      = 'Ο ΑΦΜ δεν είναι έγκυρος.';

add_action(
	'woocommerce_init',
	static function () use ( $document_label, $choices, $fields, $vat_error ) {
		if ( ! function_exists( 'woocommerce_register_additional_checkout_field' ) ) {
			return;
		}
		woocommerce_register_additional_checkout_field(
			array(
				'id'       => 'snipfire/document',
				'label'    => $document_label,
				'location' => 'order',
				'type'     => 'select',
				'required' => true,
				'options'  => array_map(
					static fn( $value, $label ) => array(
						'value' => $value,
						'label' => $label,
					),
					array_keys( $choices ),
					$choices
				),
			)
		);

		// The invoice fields show, and are required, only when "invoice" is picked.
		$not_invoice = array(
			'checkout' => array(
				'properties' => array(
					'additional_fields' => array(
						'properties' => array(
							'snipfire/document' => array( 'not' => array( 'const' => 'invoice' ) ),
						),
					),
				),
			),
		);
		foreach ( $fields as $key => $label ) {
			$field = array(
				'id'       => 'snipfire/invoice-' . $key,
				'label'    => $label,
				'location' => 'order',
				'type'     => 'text',
				'required' => true,
				'hidden'   => $not_invoice,
			);
			if ( 'vat' === $key ) {
				// A Greek VAT number: 9 digits with a check digit ("EL" and spaces are fine).
				$clean                      = static fn( $value ) => (string) preg_replace( '/^(EL|GR)/i', '', (string) preg_replace( '/[\s.\-]/', '', (string) $value ) );
				$field['sanitize_callback'] = $clean;
				$field['validate_callback'] = static function ( $value ) use ( $vat_error, $clean ) {
					$vat = $clean( $value );
					if ( '' === $vat ) {
						return true;
					}
					$sum = 0;
					for ( $i = 0; $i < 8 && preg_match( '/^\d{9}$/', $vat ); $i++ ) {
						$sum += (int) $vat[ $i ] * ( 2 ** ( 8 - $i ) );
					}
					if ( ! preg_match( '/^\d{9}$/', $vat ) || '000000000' === $vat || ( $sum % 11 ) % 10 !== (int) $vat[8] ) {
						return new WP_Error( 'snippet_gr_invalid_vat', $vat_error );
					}
					return true;
				};
			}
			woocommerce_register_additional_checkout_field( $field );
		}
	}
);

Good to know

For the Checkout block (WooCommerce 9.9 or later). The fields appear under “Additional order information”. With the classic checkout use “Receipt or invoice at checkout” instead. The details are saved as the order’s additional fields (snipfire/document, snipfire/invoice-vat…).

In these packs

  • Greek e-shop: For shops in Greece: receipt or invoice with a checked VAT number (ΑΦΜ), Greek phone and postcode checks, a cash on delivery fee, and greeklish addresses.

Move your snippets over this afternoon.

Importing changes nothing until you switch over, and your old shortcodes keep working.