Files
WooBC/woo-business-central/includes/class-wbc-customer-sync.php

292 lines
9.1 KiB
PHP
Raw Normal View History

<?php
/**
* Customer Sync to Business Central
*
* @package WooBusinessCentral
*/
// Prevent direct access
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Class WBC_Customer_Sync
*
* Handles syncing customers from WooCommerce to Business Central.
*/
class WBC_Customer_Sync {
/**
* Get or create a customer in Business Central
*
* Lookup priority:
* 1. If NIF provided search BC by taxRegistrationNumber, create if not found
* 2. If no NIF use configured default customer number
*
* @param WC_Order $order WooCommerce order.
* @return string|WP_Error BC customer number or error.
*/
public function get_or_create_customer( $order ) {
$nif = $order->get_meta( '_nif' );
$user_id = $order->get_user_id();
// No NIF → use default customer number
if ( empty( $nif ) ) {
$default_customer = get_option( 'wbc_default_customer_number', '' );
if ( empty( $default_customer ) ) {
return new WP_Error( 'wbc_no_nif_no_default', __( 'Order has no NIF and no default customer number is configured.', 'woo-business-central' ) );
}
WBC_Logger::info( 'CustomerSync', 'No NIF provided, using default customer', array(
'order_id' => $order->get_id(),
'customer_number' => $default_customer,
) );
return $default_customer;
}
WBC_Logger::debug( 'CustomerSync', 'Getting or creating customer by NIF', array(
'nif' => $nif,
) );
// Check cached BC customer number for this user
if ( $user_id ) {
$cached_customer_number = get_user_meta( $user_id, '_wbc_bc_customer_number', true );
if ( ! empty( $cached_customer_number ) ) {
$exists = $this->verify_customer_exists( $cached_customer_number );
if ( $exists ) {
WBC_Logger::debug( 'CustomerSync', 'Using cached BC customer', array(
'customer_number' => $cached_customer_number,
) );
return $cached_customer_number;
}
}
}
// Search BC for customer with this NIF
$existing = $this->find_customer_by_nif( $nif );
if ( is_wp_error( $existing ) ) {
return $existing;
}
if ( $existing ) {
$customer_number = $existing['number'];
if ( $user_id ) {
update_user_meta( $user_id, '_wbc_bc_customer_id', $existing['id'] );
update_user_meta( $user_id, '_wbc_bc_customer_number', $customer_number );
}
WBC_Logger::info( 'CustomerSync', 'Found existing BC customer by NIF', array(
'nif' => $nif,
'customer_number' => $customer_number,
) );
return $customer_number;
}
// Create new customer in BC with NIF
$new_customer = $this->create_customer( $order );
if ( is_wp_error( $new_customer ) ) {
return $new_customer;
}
$customer_number = $new_customer['number'];
if ( $user_id ) {
update_user_meta( $user_id, '_wbc_bc_customer_id', $new_customer['id'] );
update_user_meta( $user_id, '_wbc_bc_customer_number', $customer_number );
}
WBC_Logger::info( 'CustomerSync', 'Created new BC customer with NIF', array(
'nif' => $nif,
'customer_number' => $customer_number,
) );
return $customer_number;
}
/**
* Find customer in BC by NIF (taxRegistrationNumber)
*
* @param string $nif Tax registration number (NIF/CIF/NIE).
* @return array|false|WP_Error Customer data, false if not found, or error.
*/
private function find_customer_by_nif( $nif ) {
$filter = "taxRegistrationNumber eq '" . WBC_API_Client::escape_odata_string( $nif ) . "'";
$result = WBC_API_Client::get_customers( $filter );
if ( is_wp_error( $result ) ) {
return $result;
}
$customers = isset( $result['value'] ) ? $result['value'] : array();
if ( empty( $customers ) ) {
return false;
}
return $customers[0];
}
/**
* Verify a customer exists in BC
*
* @param string $customer_number BC customer number.
* @return bool Whether the customer exists.
*/
private function verify_customer_exists( $customer_number ) {
$filter = "number eq '" . WBC_API_Client::escape_odata_string( $customer_number ) . "'";
$result = WBC_API_Client::get_customers( $filter );
if ( is_wp_error( $result ) ) {
return false;
}
$customers = isset( $result['value'] ) ? $result['value'] : array();
return ! empty( $customers );
}
/**
* Create a new customer in BC
*
* @param WC_Order $order WooCommerce order.
* @return array|WP_Error Created customer data or error.
*/
private function create_customer( $order ) {
// Build customer data from order
$customer_data = $this->build_customer_data( $order );
WBC_Logger::debug( 'CustomerSync', 'Creating new customer in BC', array(
'data' => $customer_data,
) );
$result = WBC_API_Client::create_customer( $customer_data );
if ( is_wp_error( $result ) ) {
WBC_Logger::error( 'CustomerSync', 'Failed to create customer in BC', array(
'error' => $result->get_error_message(),
'data' => $customer_data,
) );
return $result;
}
return $result;
}
/**
* Build customer data from WC order
*
* @param WC_Order $order WooCommerce order.
* @return array Customer data for BC API.
*/
private function build_customer_data( $order ) {
// Get billing info
$first_name = $order->get_billing_first_name();
$last_name = $order->get_billing_last_name();
$company = $order->get_billing_company();
// Determine display name and type
if ( ! empty( $company ) ) {
$display_name = $company;
$type = 'Company';
} else {
$display_name = trim( $first_name . ' ' . $last_name );
$type = 'Person';
}
// Build address
$address_line1 = $order->get_billing_address_1();
$address_line2 = $order->get_billing_address_2();
if ( ! empty( $address_line2 ) ) {
$address_line1 .= ', ' . $address_line2;
}
// Map country code
$country = $order->get_billing_country();
// Build customer payload
$customer_data = array(
'displayName' => substr( $display_name, 0, 100 ), // BC has max length
'type' => $type,
'email' => $order->get_billing_email(),
);
// Add NIF as tax registration number
$nif = $order->get_meta( '_nif' );
if ( ! empty( $nif ) ) {
$customer_data['taxRegistrationNumber'] = $nif;
}
// Add optional fields if present
$phone = $order->get_billing_phone();
if ( ! empty( $phone ) ) {
$customer_data['phoneNumber'] = substr( $phone, 0, 30 );
}
if ( ! empty( $address_line1 ) ) {
$customer_data['addressLine1'] = substr( $address_line1, 0, 100 );
}
$city = $order->get_billing_city();
if ( ! empty( $city ) ) {
$customer_data['city'] = substr( $city, 0, 30 );
}
$state = $order->get_billing_state();
if ( ! empty( $state ) ) {
$customer_data['state'] = substr( $state, 0, 30 );
}
$postcode = $order->get_billing_postcode();
if ( ! empty( $postcode ) ) {
$customer_data['postalCode'] = substr( $postcode, 0, 20 );
}
if ( ! empty( $country ) ) {
$customer_data['country'] = $country;
}
// Add currency if available
$currency = $order->get_currency();
if ( ! empty( $currency ) ) {
$customer_data['currencyCode'] = $currency;
}
return $customer_data;
}
/**
* Update customer in BC with WC order data
*
* @param string $customer_id BC customer ID.
* @param WC_Order $order WooCommerce order.
* @return array|WP_Error Updated customer data or error.
*/
public function update_customer( $customer_id, $order ) {
$customer_data = $this->build_customer_data( $order );
WBC_Logger::debug( 'CustomerSync', 'Updating customer in BC', array(
'customer_id' => $customer_id,
'data' => $customer_data,
) );
$result = WBC_API_Client::patch( '/customers(' . $customer_id . ')', $customer_data );
if ( is_wp_error( $result ) ) {
WBC_Logger::error( 'CustomerSync', 'Failed to update customer in BC', array(
'error' => $result->get_error_message(),
'customer_id' => $customer_id,
) );
}
return $result;
}
}