Απόδειξη ή τιμολόγιο στο ταμείο
Ο πελάτης επιλέγει απόδειξη ή τιμολόγιο. Για τιμολόγιο συμπληρώνει επωνυμία, ΑΦΜ (με έλεγχο), ΔΟΥ και δραστηριότητα. Τα στοιχεία αποθηκεύονται με την παραγγελία και εμφανίζονται στη διαχείριση, στα email της παραγγελίας και στη σελίδα της παραγγελίας.
<?php
// Labels are in Greek; change them if you like.
$fields = array(
'sf_invoice_company' => 'Επωνυμία εταιρείας',
'sf_invoice_vat' => 'ΑΦΜ',
'sf_invoice_tax_office' => 'ΔΟΥ',
'sf_invoice_activity' => 'Δραστηριότητα',
);
// A Greek VAT number (ΑΦΜ): 9 digits with a check digit.
$valid_vat = static function ( string $vat ): bool {
if ( ! preg_match( '/^\d{9}$/', $vat ) || '000000000' === $vat ) {
return false;
}
$sum = 0;
for ( $i = 0; $i < 8; $i++ ) {
$sum += (int) $vat[ $i ] * ( 2 ** ( 8 - $i ) );
}
return ( $sum % 11 ) % 10 === (int) $vat[8];
};
add_filter(
'woocommerce_checkout_fields',
static function ( $checkout ) use ( $fields ) {
$checkout['billing']['sf_document'] = array(
'type' => 'radio',
'label' => 'Παραστατικό',
'options' => array(
'receipt' => 'Απόδειξη',
'invoice' => 'Τιμολόγιο',
),
'default' => 'receipt',
'required' => true,
'class' => array( 'form-row-wide', 'sf-document' ),
'priority' => 5,
);
$priority = 6;
foreach ( $fields as $key => $label ) {
$checkout['billing'][ $key ] = array(
'type' => 'text',
'label' => $label . ' <abbr class="required" title="υποχρεωτικό">*</abbr>',
'required' => false, // Required for invoices only: checked below.
'class' => array( 'form-row-wide', 'sf-invoice-field' ),
'priority' => $priority++,
);
}
return $checkout;
}
);
add_action(
'woocommerce_after_checkout_validation',
static function ( $data, $errors ) use ( $fields, $valid_vat ) {
if ( 'invoice' !== ( $data['sf_document'] ?? '' ) ) {
return;
}
foreach ( $fields as $key => $label ) {
if ( '' === trim( (string) ( $data[ $key ] ?? '' ) ) ) {
$errors->add( 'validation', sprintf( 'Συμπληρώστε το πεδίο «%s» για το τιμολόγιο.', $label ) );
}
}
$vat = preg_replace( '/\D/', '', (string) ( $data['sf_invoice_vat'] ?? '' ) );
if ( '' !== $vat && ! $valid_vat( $vat ) ) {
$errors->add( 'validation', 'Ο ΑΦΜ δεν είναι έγκυρος.' );
}
},
10,
2
);
add_action(
'woocommerce_checkout_create_order',
static function ( $order, $data ) use ( $fields ) {
$document = 'invoice' === ( $data['sf_document'] ?? '' ) ? 'invoice' : 'receipt';
$order->update_meta_data( '_sf_document', $document );
if ( 'invoice' === $document ) {
foreach ( array_keys( $fields ) as $key ) {
$value = (string) ( $data[ $key ] ?? '' );
$order->update_meta_data( '_' . $key, 'sf_invoice_vat' === $key ? preg_replace( '/\D/', '', $value ) : sanitize_text_field( $value ) );
}
}
},
10,
2
);
// The details, as HTML or plain text.
$details = static function ( $order, bool $plain = false ) use ( $fields ): string {
if ( ! $order instanceof WC_Order || ! $order->get_meta( '_sf_document' ) ) {
return '';
}
$lines = array( 'Παραστατικό' => 'invoice' === $order->get_meta( '_sf_document' ) ? 'Τιμολόγιο' : 'Απόδειξη' );
if ( 'invoice' === $order->get_meta( '_sf_document' ) ) {
foreach ( $fields as $key => $label ) {
$lines[ $label ] = (string) $order->get_meta( '_' . $key );
}
}
$out = '';
foreach ( $lines as $label => $value ) {
$out .= $plain ? $label . ': ' . $value . "\n" : '<strong>' . esc_html( $label ) . ':</strong> ' . esc_html( $value ) . '<br>';
}
return $plain ? "\n" . $out : '<p class="sf-invoice-details">' . $out . '</p>';
};
add_action(
'woocommerce_admin_order_data_after_billing_address',
static function ( $order ) use ( $details ) {
echo $details( $order ); // phpcs:ignore WordPress.Security.EscapeOutput -- Escaped above.
}
);
// The order page for customers: classic templates show it with the
// customer's details, block themes in the thank-you page's extra information.
$show_once = static function ( $order ) use ( $details ) {
static $shown = array();
$order = $order instanceof WC_Order ? $order : wc_get_order( $order );
if ( $order && empty( $shown[ $order->get_id() ] ) ) {
$shown[ $order->get_id() ] = true;
echo $details( $order ); // phpcs:ignore WordPress.Security.EscapeOutput -- Escaped above.
}
};
add_action( 'woocommerce_order_details_after_customer_details', $show_once );
add_action( 'woocommerce_thankyou', $show_once, 20 );
add_action(
'woocommerce_email_after_order_table',
static function ( $order, $sent_to_admin = false, $plain_text = false ) use ( $details ) {
echo $plain_text ? esc_html( $details( $order, true ) ) : $details( $order ); // phpcs:ignore WordPress.Security.EscapeOutput -- Escaped above.
},
10,
3
);
// Show the invoice fields only when "Τιμολόγιο" is picked.
add_action(
'wp_footer',
static function () {
if ( ! function_exists( 'is_checkout' ) || ! is_checkout() || is_order_received_page() ) {
return;
}
?>
<style>.sf-invoice-field .optional{display:none}.sf-document .woocommerce-input-wrapper label{display:inline;margin:0 1em 0 .3em}</style>
<script>
jQuery( function ( $ ) {
var toggle = function () {
$( '.sf-invoice-field' ).toggle( $( 'input[name="sf_document"]:checked' ).val() === 'invoice' );
};
$( document.body ).on( 'change', 'input[name="sf_document"]', toggle );
toggle();
} );
</script>
<?php
}
);
Καλό να ξέρετε
Για το κλασικό ταμείο (το shortcode [woocommerce_checkout] ή το μπλοκ Classic Checkout). Τα στοιχεία αποθηκεύονται ως πεδία της παραγγελίας (_sf_document, _sf_invoice_vat…), που μπορούν να τα διαβάσουν πρόσθετα τιμολόγησης και εξαγωγές.
Σε αυτά τα πακέτα
- Ελληνικό e-shop: Για καταστήματα στην Ελλάδα: απόδειξη ή τιμολόγιο με έλεγχο ΑΦΜ, έλεγχος ελληνικών τηλεφώνων και ταχυδρομικών κωδικών, χρέωση αντικαταβολής και διευθύνσεις σε greeklish.