Receipt or invoice choice with ΑΦΜ and ΔΟΥ for Greek shops
Let WooCommerce customers choose Απόδειξη or Τιμολόγιο and, for invoices, enter a validated ΑΦΜ, ΔΟΥ, company name and business activity.
// Receipt or invoice (Απόδειξη / Τιμολόγιο) with ΑΦΜ, ΔΟΥ, company name and activity.
// Block checkout, WooCommerce 9.9 or later.
// ΑΦΜ check-digit validation (shared with the "Validate a Greek VAT number" snippet).
if ( ! function_exists( 'snipfire_is_valid_afm' ) ) {
function snipfire_is_valid_afm( $afm ) {
$afm = preg_replace( '/[\s.\-]/', '', (string) $afm );
$afm = preg_replace( '/^(EL|GR)/i', '', $afm );
if ( ! preg_match( '/^[0-9]{9}$/', $afm ) || '000000000' === $afm ) {
return false;
}
$sum = 0;
for ( $i = 0; $i < 8; $i++ ) {
$sum += (int) $afm[ $i ] * ( 2 ** ( 8 - $i ) );
}
return ( $sum % 11 ) % 10 === (int) $afm[8];
}
}
add_action(
'woocommerce_init',
function () {
if ( ! function_exists( 'woocommerce_register_additional_checkout_field' ) ) {
return;
}
// Rule: the customer chose "Τιμολόγιο".
$is_invoice = array(
'type' => 'object',
'properties' => array(
'checkout' => array(
'type' => 'object',
'properties' => array(
'additional_fields' => array(
'type' => 'object',
'properties' => array(
'snipfire/document-type' => array( 'const' => 'invoice' ),
),
'required' => array( 'snipfire/document-type' ),
),
),
'required' => array( 'additional_fields' ),
),
),
);
// Rule: anything else (nothing chosen yet, or "Απόδειξη").
$not_invoice = array(
'type' => 'object',
'properties' => array(
'checkout' => array(
'properties' => array(
'additional_fields' => array(
'properties' => array(
'snipfire/document-type' => array( 'not' => array( 'const' => 'invoice' ) ),
),
),
),
),
),
);
woocommerce_register_additional_checkout_field(
array(
'id' => 'snipfire/document-type',
'label' => 'Παραστατικό',
'location' => 'order',
'type' => 'select',
'required' => true,
'options' => array(
array(
'value' => 'receipt',
'label' => 'Απόδειξη',
),
array(
'value' => 'invoice',
'label' => 'Τιμολόγιο',
),
),
)
);
woocommerce_register_additional_checkout_field(
array(
'id' => 'snipfire/vat-number',
'label' => 'ΑΦΜ',
'location' => 'order',
'required' => $is_invoice,
'hidden' => $not_invoice,
'attributes' => array(
'autocomplete' => 'off',
'maxLength' => 11,
),
'sanitize_callback' => function ( $value ) {
// Store 9 digits only: remove spaces, dots, dashes and an EL/GR prefix.
$value = strtoupper( preg_replace( '/[\s.\-]/', '', sanitize_text_field( (string) $value ) ) );
return preg_replace( '/^(EL|GR)/', '', $value );
},
'validate_callback' => function ( $value ) {
if ( '' !== (string) $value && ! snipfire_is_valid_afm( $value ) ) {
return new WP_Error( 'snipfire_invalid_afm', 'Ο ΑΦΜ δεν είναι έγκυρος. Ελέγξτε ότι έχει 9 ψηφία.' );
}
},
)
);
woocommerce_register_additional_checkout_field(
array(
'id' => 'snipfire/tax-office',
'label' => 'ΔΟΥ',
'location' => 'order',
'required' => $is_invoice,
'hidden' => $not_invoice,
)
);
woocommerce_register_additional_checkout_field(
array(
'id' => 'snipfire/company-name',
'label' => 'Επωνυμία εταιρείας',
'location' => 'order',
'required' => $is_invoice,
'hidden' => $not_invoice,
'attributes' => array( 'autocomplete' => 'organization' ),
)
);
woocommerce_register_additional_checkout_field(
array(
'id' => 'snipfire/business-activity',
'label' => 'Δραστηριότητα',
'location' => 'order',
'required' => $is_invoice,
'hidden' => $not_invoice,
)
);
}
);
// If "Απόδειξη" was chosen, don't keep invoice details typed before switching.
add_action(
'woocommerce_store_api_checkout_update_order_from_request',
function ( $order ) {
$prefix = '_wc_other/'; // WooCommerce's meta key prefix for order fields.
if ( 'invoice' === $order->get_meta( $prefix . 'snipfire/document-type' ) ) {
return;
}
foreach ( array( 'vat-number', 'tax-office', 'company-name', 'business-activity' ) as $field ) {
$order->delete_meta_data( $prefix . 'snipfire/' . $field );
}
}
);
What it does
Greek customers need to choose between a receipt (Απόδειξη) and an invoice (Τιμολόγιο). For an invoice you need the VAT number (ΑΦΜ), tax office (ΔΟΥ), company name and business activity.
This snippet adds a "Παραστατικό" choice to the block checkout. The four invoice fields appear, and become required, only when the customer picks "Τιμολόγιο". The ΑΦΜ is checked with the official check-digit rule and saved as 9 digits.
It uses WooCommerce's Additional Checkout Fields API, so the values are stored on the order the HPOS-safe way and show on the order screen, in order emails and on the thank-you page.
Good to know
- Block checkout only, WooCommerce 9.9 or later. The classic (shortcode) checkout doesn't show these fields.
- The fields appear in the "Additional order information" section of the checkout. Move that block in the Site Editor if you want them higher up.
- Read a value in your own code with
$order->get_meta( '_wc_other/snipfire/vat-number' ).