Create Default User Xero Invoice for Guest OpenPOS WooCommerce

Previously, I discussed how to fix the error "creating Xero invoice openPOS WooCommerce". That approach might not be entirely accurate in some cases because, in my example, payments made using PayNow QR from the OpenPOS app always require login to confirm the payment, even though there is a better approach, which is to set a default contact based on a specific contact ID registered in the WordPress system.

First, I need to explain that every time an order is created through the OpenPOS app, the Xero plugin in WooCommerce cannot create an invoice and shows an error like the following: 

ERROR creating Xero invoice: ErrorNumber: 10 ErrorType: ValidationException Message: A validation exception occurred Detail: The Contact must contain at least 1 of the following elements to identify the contact: Name, ContactID, ContactNumber

This happens because orders created through the OpenPOS app are identified as guest users, which are not directly connected to WordPress users, so the invoice might not be sent to Xero.

We can debug from the admin side by editing the order and sending the invoice to Xero. The debugging results will display the following parameter: 


<invoice>
    <type>ACCREC</type>
    <contact>
        <name></name>
        <firstname></firstname>
        <lastname></lastname>
        <emailaddress></emailaddress>
        <addresses>
            <address>
                <addresstype>POBOX</addresstype>
                <addressline1></addressline1>
                <city></city>
                <region></region>
                <postalcode></postalcode>
                <country></country>
            </address>
        </addresses>
        <phones>
            <phone>
                <phonetype>DEFAULT</phonetype>
                <phonenumber></phonenumber>
            </phone>
        </phones>
    </contact>
    <date>2024-09-05</date>
    <duedate>2024-09-05</duedate>
    <invoicenumber>EX-201</invoicenumber>
<reference>Cash Order 201</reference>
<url>https://mywpppppp.com/wp-admin/post.php?post=201&amp;action=edit</url> <lineamounttypes>Exclusive</lineamounttypes> <lineitems> <lineitem> <description>My Product Name</description> <accountcode>200</accountcode> <itemcode>Myprd-SUB-000</itemcode> <unitamount>213</unitamount> <quantity>1</quantity> <taxtype>NONE</taxtype> <taxamount>0</taxamount> </lineitem> </lineitems> <currencycode>SGD</currencycode> <status>AUTHORISED</status> </invoice>

code x1

DEBUGGING TO GET CONTACT ID

To resolve the issue above, we first need to debug to obtain the contact ID of the WordPress user. The process involves changing the guest user to another registered user and then sending the invoice to Xero. Before the invoice is sent to Xero, we need to intercept or debug to get the contact ID parameter of the assigned user.

Open the plugin editor and navigate to Xero, then edit the following file:

 woocommerce-xero/includes/class-wc-xr-invoice.php

Pay attention to the entire code of the public function to_xml() below:


public function to_xml() {

		// Start Invoice
		$xml = '<Invoice>';

		// Type
		$xml .= '<Type>' . $this->get_type() . '</Type>';

		// Add Contact
		if ( $this->get_contact()->get_id() ) {
			$xml .= $this->get_contact()->id_to_xml();
			
		} else {
			
			$xml .= $this->get_contact()->to_xml();	
			

		
		}

		// Date
		$xml .= '<Date>' . $this->get_date() . '</Date>';

		// Due Date
		$xml .= '<DueDate>' . $this->get_due_date() . '</DueDate>';

		
		// Invoice Number
		$invoice_number = $this->get_invoice_number();
		if ( null !== $invoice_number ) {
			$xml .= '<InvoiceNumber>' . $invoice_number . '</InvoiceNumber>';
		}
	
		// Reference
		$order = $this->get_order();
		$reference_pieces = array();
		$payment_method   = esc_xml( $order->get_payment_method_title() );
		if ( ! empty( $payment_method ) ) {
			$reference_pieces[] = $payment_method;
		}
		$transaction_id = $order->get_transaction_id();
		if ( ! empty( $transaction_id ) ) {
			$reference_pieces[] = $transaction_id;
		}
		if ( $order ) {
			$reference_pieces[] = sprintf(
				/* translators: %d: order id */
				__( 'Order %d', 'woocommerce-xero' ),
				(int) $order->get_id()
			);
		}
		if ( 0 < count( $reference_pieces ) ) {
			$xml .= '<Reference>' . implode( ' ', $reference_pieces ) . '</Reference>';
		}

		// URL
		$order_id = $order->get_id();
		$path = '/post.php?post=' . esc_attr( intval( $order_id ) ) . '&amp;action=edit';
		$url =  admin_url( $path );
		// Check for port number (port numbers in URLs are not allowed by Xero)
		$port = parse_url( $url, PHP_URL_PORT );
		// Only add the Url to the XML if a port number is NOT present
		if ( empty( $port ) ) {
			$xml .= '<Url>' . esc_url( $url ) . '</Url>';
		}

		// Line Amount Types. Always send prices exclusive VAT.
		$line_amount_type = ( $this->settings->send_tax_inclusive_prices() ) ? 'Inclusive' : 'Exclusive';
		$xml             .= '<LineAmountTypes>' . $line_amount_type . '</LineAmountTypes>';

		// Get Line Items
		$line_items = $this->get_line_items();
		
		// Check line items
		if ( count( $line_items ) ) {

			// Line Items wrapper open
			$xml .= '<LineItems>';

			// Loop
			foreach ( $line_items as $line_item ) {

				// Add
				$xml .= $line_item->to_xml();

			}

			// Line Items wrapper close
			$xml .= '</LineItems>';
		}

		// Currency Code
		$xml .= '<CurrencyCode>' . $this->get_currency_code() . '</CurrencyCode>';

		// Status
		$xml .= '<Status>AUTHORISED</Status>';
		
		// Get branding theme template ID.
		$branding_theme = $this->settings->get_option( 'branding_theme' );

		/**
		 * Filter to change the branding theme template ID.
		 *
		 * @since 1.7.45
		 *
		 * `woocommerce_xero_branding_theme` is a filter hook.
		 * @var string $branding_theme is a branding theme ID.
		 * @var object $order Order object.
		 */
		$branding_theme = apply_filters( 'woocommerce_xero_branding_theme', $branding_theme, $this );
		if ( $branding_theme ) {

			// Only send branding theme if it is valid/exists.
			try {
				$org_request = new WC_XR_Request_Branding_Themes( $this->settings, $branding_theme );
				$org_request->do_request();
				$xml_response = $org_request->get_response_body_xml();

				if ( 'OK' === (string) $xml_response->Status ) {
					$xml .= '<BrandingThemeID>' . esc_html( $branding_theme ) . '</BrandingThemeID>';
				}
			} catch ( Exception $e ) {
				// Add Exception as order note.
				$order->add_order_note( 'BrandingThemeID is invalid, using the default template. ' . $e->getMessage() );
			}
		}

		// Total Tax
		$xml .= '<TotalTax>' . $this->get_total_tax() . '</TotalTax>';

		// Total
		$xml .= '<Total>' . $this->get_total() . '</Total>';

		// End Invoice
		$xml .= '</Invoice>';

		/**
		 * Filter the xml data returned by WC_XR_Invoice::to_xml()
		 * value is returned.
		 *
		 * @since 1.7.4 introduced
		 *
		 * @param string $xml
		 * @param WC_XR_Invoice $invoice_object
		 */
		return apply_filters( 'woocommerce_xero_invoice_to_xml', $xml, $this );
	}


code x2

Insert the following code to perform debugging, then save: 


// Currency Code
$xml .= '<CurrencyCode>' . $this->get_currency_code() . '</CurrencyCode>';

// Status
$xml .= '<Status>AUTHORISED</Status>';
//start debuging from here

echo var_dump($xml);
exit();

code x3

Return to the order that failed to send the invoice, then change the guest user identification to another user in the system. Next, update and choose "Send invoice to Xero". You should now see the contact ID of the user identified in the <contactid> tag. Save the value of this parameter.

SAVING DEFAULT USER TO SEND INVOICE XERO

Since the reason invoices cannot be created and sent to Xero automatically is that the user is identified as a guest with an empty contact ID, we can set it in the following line:


// Add Contact
		if ( $this->get_contact()->get_id() ) {
			$xml .= $this->get_contact()->id_to_xml();
			
		} else {
			// Place default user contact id from here
			//$xml .= $this->get_contact()->to_xml();	
			$xml.='<Contact>';		
			$xml .='<ContactID>your-hah-contact-id</ContactID>';
			$xml.='</Contact>';
			

		
		}

code x4

Finally, please test again. The invoice should now be created automatically and sent to Xero.

============

CARA MEMBUAT USER DEFAULT XERO UNTUK GUES DARI openPOS WOOCOMMERCE

Sebelumnya saya pernah membahas tentang bagaimana Fix ERROR creating Xero invoice openPOS Woocommerce . Cara tersebut dalam beberapa kasus kurang tepat, sebab dalam contoh kasus saya pembayaran yang dilakukan menggunakan PayNow QR dari aplikasi openPOS selalu meminta login untuk mengkonfirmasi pembayaran padahal sebenarnya ada pendekatan yang lebih baik yaitu dengan menetapkan default contact berdasarkan contact id tertentu yang terdaftar dalam sistem wordpress

Pertama perlu saya jelaskan bahwa setiap kali order dibuat melalui aplikasi openPOS, plugins xero yang terdapat pada woocommerce tidak dapat membuat invoice dengan catatan error seperti berikut :

“ERROR creating Xero invoice: ErrorNumber: 10 ErrorType: ValidationException Message: A validation exception occurred Detail: The Contact must contain at least 1 of the following elements to identify the contact: Name, ContactID, ContactNumber”

Sebab proses order yang dibuat melalui aplikasi openPOS di identifikasi sebagai user guest yang tidak secara langsung terhubung ke user wordpress sehingga mungkin invoice tidak dapat dikirimkan ke xero

Kita dapat melakukan debuging dari admin dengan cara mengedit order dan mengirim invoice ke xero dan hasil debuging akan menampilkan parameter berikut:

lihat kode x1


DEBUGING UNTUK MENDAPATKAN CONTACT ID

Untuk mengatasi masalah diatas, pertama kita harus melakukan debuging untuk mendapatkan contact id dari user wordpress. Caranya adalah dengan mengubah user guest ke user lain yang terdaftar kemudian baru mengirimkan invoice ke xero, sebelum invoice diteruskan ke xero, maka kita perlu mencegatnya atau mendebug untuk mendapatkan parameter contact id dari user yang ditetapkan.

Buka editor plugin lalau arahkan ke xero selanjutnya edit file berikut:

woocommerce-xero/includes/class-wc-xr-invoice.php

Perhartikan keseluruhan kode dari fungsi public function to_xml() berikut :

lihat kode x2

Tempat kode berikut untuk melakukan debuging, selanjutnya simpan.

lihat kode x3

Kembali ke order yang gagal mengirim invoice, selanjutnya rubah identifikasi user guest ke user lain yang terdapat pada sistem. Kemudian update pilih send invoice to xero, maka nanti mungkin anda akan melihat contact id usernya yang di identifikasi dalam tag <contactid>, simpan nilai pada parameter tersebut.

MENYIMPAN DEFAULT USER UNTUK MENGIRIM INVOICE ke XERO

Karena yang menyebabkan invoice tidak dapat dibuat secara otomatis dan dikirim ke xero adalah karena user teridentifikasi sebagai guest yang nilai contact id nya kosong maka kita bisa mengesetnya pada baris berikut :

lihat kode x4

Terkahir silahkan test kembali, harusnya sekarang invoice dapat dibuat secara otomatis dan dikirim ke xero



1 Response to "Create Default User Xero Invoice for Guest OpenPOS WooCommerce"

Komentar yang Anda kirim akan terlebih dahulu di moderasi oleh Admin