Files
WooBC/woo-business-central/admin/partials/wbc-admin-display.php
Malin 782681b30f feat: customer lookup by NIF with default customer fallback
- Search BC customers by taxRegistrationNumber (NIF/CIF from _nif meta)
- If NIF found in BC, use that customer; if not, create with NIF
- If no NIF on order, use configurable default customer number
- Add Default Customer Number setting in Order Settings tab

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 16:06:42 +01:00

468 lines
28 KiB
PHP

<?php
/**
* Admin settings page template
*
* @package WooBusinessCentral
*/
// Prevent direct access
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
$tabs = array(
'connection' => __( 'Connection', 'woo-business-central' ),
'sync' => __( 'Sync Settings', 'woo-business-central' ),
'orders' => __( 'Order Settings', 'woo-business-central' ),
'logs' => __( 'Logs', 'woo-business-central' ),
);
?>
<div class="wrap wbc-admin-wrap">
<h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
<nav class="nav-tab-wrapper wbc-nav-tabs">
<?php foreach ( $tabs as $tab_id => $tab_name ) : ?>
<a href="<?php echo esc_url( add_query_arg( 'tab', $tab_id ) ); ?>"
class="nav-tab <?php echo $current_tab === $tab_id ? 'nav-tab-active' : ''; ?>">
<?php echo esc_html( $tab_name ); ?>
</a>
<?php endforeach; ?>
</nav>
<div class="wbc-admin-content">
<?php if ( $current_tab === 'connection' ) : ?>
<!-- Connection Settings -->
<form method="post" action="options.php" class="wbc-settings-form">
<?php settings_fields( 'wbc_connection' ); ?>
<div class="wbc-card">
<h2><?php esc_html_e( 'Microsoft Azure AD Credentials', 'woo-business-central' ); ?></h2>
<p class="description">
<?php esc_html_e( 'Enter your Azure AD application credentials to connect to Business Central.', 'woo-business-central' ); ?>
</p>
<table class="form-table">
<tr>
<th scope="row">
<label for="wbc_tenant_id"><?php esc_html_e( 'Tenant ID', 'woo-business-central' ); ?></label>
</th>
<td>
<input type="text" id="wbc_tenant_id" name="wbc_tenant_id"
value="<?php echo esc_attr( get_option( 'wbc_tenant_id', '' ) ); ?>"
class="regular-text" />
<p class="description">
<?php esc_html_e( 'Your Azure AD tenant ID (GUID format).', 'woo-business-central' ); ?>
</p>
</td>
</tr>
<tr>
<th scope="row">
<label for="wbc_client_id"><?php esc_html_e( 'Client ID', 'woo-business-central' ); ?></label>
</th>
<td>
<input type="text" id="wbc_client_id" name="wbc_client_id"
value="<?php echo esc_attr( get_option( 'wbc_client_id', '' ) ); ?>"
class="regular-text" />
<p class="description">
<?php esc_html_e( 'Application (client) ID from Azure AD.', 'woo-business-central' ); ?>
</p>
</td>
</tr>
<tr>
<th scope="row">
<label for="wbc_client_secret"><?php esc_html_e( 'Client Secret', 'woo-business-central' ); ?></label>
</th>
<td>
<?php
$has_secret = ! empty( WBC_OAuth::get_client_secret() );
$placeholder = $has_secret ? '********' : '';
?>
<input type="password" id="wbc_client_secret" name="wbc_client_secret"
value="" placeholder="<?php echo esc_attr( $placeholder ); ?>"
class="regular-text" autocomplete="new-password" />
<p class="description">
<?php if ( $has_secret ) : ?>
<?php esc_html_e( 'Leave blank to keep existing secret. Enter a new value to update.', 'woo-business-central' ); ?>
<?php else : ?>
<?php esc_html_e( 'Client secret from Azure AD application.', 'woo-business-central' ); ?>
<?php endif; ?>
</p>
</td>
</tr>
<tr>
<th scope="row">
<label for="wbc_environment"><?php esc_html_e( 'Environment', 'woo-business-central' ); ?></label>
</th>
<td>
<select id="wbc_environment" name="wbc_environment">
<option value="production" <?php selected( get_option( 'wbc_environment', 'production' ), 'production' ); ?>>
<?php esc_html_e( 'Production', 'woo-business-central' ); ?>
</option>
<option value="sandbox" <?php selected( get_option( 'wbc_environment' ), 'sandbox' ); ?>>
<?php esc_html_e( 'Sandbox', 'woo-business-central' ); ?>
</option>
</select>
</td>
</tr>
<tr>
<th scope="row">
<label for="wbc_company_id"><?php esc_html_e( 'Company ID', 'woo-business-central' ); ?></label>
</th>
<td>
<input type="text" id="wbc_company_id" name="wbc_company_id"
value="<?php echo esc_attr( get_option( 'wbc_company_id', '' ) ); ?>"
class="regular-text" />
<button type="button" id="wbc-load-companies" class="button">
<?php esc_html_e( 'Load Companies', 'woo-business-central' ); ?>
</button>
<p class="description">
<?php esc_html_e( 'Business Central company ID (GUID). Click "Load Companies" after saving credentials.', 'woo-business-central' ); ?>
</p>
<div id="wbc-companies-list" style="display: none; margin-top: 10px;">
<select id="wbc-company-select">
<option value=""><?php esc_html_e( 'Select a company...', 'woo-business-central' ); ?></option>
</select>
</div>
</td>
</tr>
<tr>
<th scope="row">
<label for="wbc_company_name"><?php esc_html_e( 'Company Name', 'woo-business-central' ); ?></label>
</th>
<td>
<input type="text" id="wbc_company_name" name="wbc_company_name"
value="<?php echo esc_attr( get_option( 'wbc_company_name', '' ) ); ?>"
class="regular-text" placeholder="e.g. TRADE FORCE BRANS" />
<p class="description">
<?php esc_html_e( 'Exact company name in Business Central (used for custom OData endpoints like ItemByLocation and ListaPrecios).', 'woo-business-central' ); ?>
</p>
</td>
</tr>
</table>
<p class="submit">
<?php submit_button( __( 'Save Settings', 'woo-business-central' ), 'primary', 'submit', false ); ?>
<button type="button" id="wbc-test-connection" class="button button-secondary">
<?php esc_html_e( 'Test Connection', 'woo-business-central' ); ?>
</button>
<span id="wbc-connection-status" class="wbc-status"></span>
</p>
</div>
</form>
<?php elseif ( $current_tab === 'sync' ) : ?>
<!-- Sync Settings -->
<form method="post" action="options.php" class="wbc-settings-form">
<?php settings_fields( 'wbc_sync' ); ?>
<div class="wbc-card">
<h2><?php esc_html_e( 'Product Sync Settings', 'woo-business-central' ); ?></h2>
<table class="form-table">
<tr>
<th scope="row">
<label for="wbc_sync_frequency"><?php esc_html_e( 'Sync Frequency', 'woo-business-central' ); ?></label>
</th>
<td>
<select id="wbc_sync_frequency" name="wbc_sync_frequency">
<option value="hourly" <?php selected( get_option( 'wbc_sync_frequency', 'daily' ), 'hourly' ); ?>>
<?php esc_html_e( 'Hourly', 'woo-business-central' ); ?>
</option>
<option value="twice_daily" <?php selected( get_option( 'wbc_sync_frequency' ), 'twice_daily' ); ?>>
<?php esc_html_e( 'Twice Daily', 'woo-business-central' ); ?>
</option>
<option value="daily" <?php selected( get_option( 'wbc_sync_frequency' ), 'daily' ); ?>>
<?php esc_html_e( 'Daily', 'woo-business-central' ); ?>
</option>
</select>
</td>
</tr>
<tr>
<th scope="row"><?php esc_html_e( 'Enable Stock Sync', 'woo-business-central' ); ?></th>
<td>
<label>
<input type="checkbox" name="wbc_enable_stock_sync" value="yes"
<?php checked( get_option( 'wbc_enable_stock_sync', 'yes' ), 'yes' ); ?> />
<?php esc_html_e( 'Sync stock levels from Business Central to WooCommerce', 'woo-business-central' ); ?>
</label>
</td>
</tr>
<tr>
<th scope="row"><?php esc_html_e( 'Enable Price Sync', 'woo-business-central' ); ?></th>
<td>
<label>
<input type="checkbox" name="wbc_enable_price_sync" value="yes"
<?php checked( get_option( 'wbc_enable_price_sync', 'yes' ), 'yes' ); ?> />
<?php esc_html_e( 'Sync prices from Business Central to WooCommerce', 'woo-business-central' ); ?>
</label>
</td>
</tr>
<tr>
<th scope="row">
<label for="wbc_location_code"><?php esc_html_e( 'Location Code', 'woo-business-central' ); ?></label>
</th>
<td>
<input type="text" id="wbc_location_code" name="wbc_location_code"
value="<?php echo esc_attr( get_option( 'wbc_location_code', '' ) ); ?>"
class="regular-text" placeholder="e.g. ICP" />
<p class="description">
<?php esc_html_e( 'Optional. BC location code to filter stock by (e.g. "ICP"). Leave empty to use total inventory across all locations.', 'woo-business-central' ); ?>
</p>
<p class="description">
<?php esc_html_e( 'Uses the custom ItemByLocation OData endpoint. Requires Company Name to be set in Connection settings.', 'woo-business-central' ); ?>
</p>
</td>
</tr>
<tr>
<th scope="row">
<label for="wbc_regular_price_list"><?php esc_html_e( 'Regular Price List Code', 'woo-business-central' ); ?></label>
</th>
<td>
<input type="text" id="wbc_regular_price_list" name="wbc_regular_price_list"
value="<?php echo esc_attr( get_option( 'wbc_regular_price_list', '' ) ); ?>"
class="regular-text" placeholder="e.g. B2C" />
<p class="description">
<?php esc_html_e( 'BC price list code for WooCommerce regular price. Leave empty to use item unit price.', 'woo-business-central' ); ?>
</p>
</td>
</tr>
<tr>
<th scope="row">
<label for="wbc_sale_price_list"><?php esc_html_e( 'Sale Price List Code', 'woo-business-central' ); ?></label>
</th>
<td>
<input type="text" id="wbc_sale_price_list" name="wbc_sale_price_list"
value="<?php echo esc_attr( get_option( 'wbc_sale_price_list', '' ) ); ?>"
class="regular-text" placeholder="e.g. B2C_OF" />
<p class="description">
<?php esc_html_e( 'BC price list code for WooCommerce sale price. Leave empty to skip sale price sync.', 'woo-business-central' ); ?>
</p>
</td>
</tr>
</table>
<p class="submit">
<?php submit_button( __( 'Save Settings', 'woo-business-central' ), 'primary', 'submit', false ); ?>
</p>
</div>
<div class="wbc-card">
<h2><?php esc_html_e( 'Sync Status', 'woo-business-central' ); ?></h2>
<table class="wbc-status-table">
<tr>
<th><?php esc_html_e( 'Last Sync:', 'woo-business-central' ); ?></th>
<td><?php echo esc_html( WBC_Cron::get_last_sync_formatted() ); ?></td>
</tr>
<tr>
<th><?php esc_html_e( 'Next Scheduled Sync:', 'woo-business-central' ); ?></th>
<td><?php echo esc_html( WBC_Cron::get_next_sync_formatted() ); ?></td>
</tr>
</table>
<p>
<button type="button" id="wbc-manual-sync" class="button button-primary">
<?php esc_html_e( 'Sync Now', 'woo-business-central' ); ?>
</button>
<span id="wbc-sync-status" class="wbc-status"></span>
</p>
</div>
</form>
<?php elseif ( $current_tab === 'orders' ) : ?>
<!-- Order Settings -->
<form method="post" action="options.php" class="wbc-settings-form">
<?php settings_fields( 'wbc_orders' ); ?>
<div class="wbc-card">
<h2><?php esc_html_e( 'Order Sync Settings', 'woo-business-central' ); ?></h2>
<table class="form-table">
<tr>
<th scope="row"><?php esc_html_e( 'Enable Order Sync', 'woo-business-central' ); ?></th>
<td>
<label>
<input type="checkbox" name="wbc_enable_order_sync" value="yes"
<?php checked( get_option( 'wbc_enable_order_sync', 'yes' ), 'yes' ); ?> />
<?php esc_html_e( 'Sync orders to Business Central when payment is received', 'woo-business-central' ); ?>
</label>
</td>
</tr>
<tr>
<th scope="row">
<label for="wbc_default_payment_terms_id"><?php esc_html_e( 'Default Payment Terms ID', 'woo-business-central' ); ?></label>
</th>
<td>
<input type="text" id="wbc_default_payment_terms_id" name="wbc_default_payment_terms_id"
value="<?php echo esc_attr( get_option( 'wbc_default_payment_terms_id', '' ) ); ?>"
class="regular-text" />
<p class="description">
<?php esc_html_e( 'Optional. Business Central payment terms ID to use for new orders.', 'woo-business-central' ); ?>
</p>
</td>
</tr>
<tr>
<th scope="row">
<label for="wbc_default_shipment_method_id"><?php esc_html_e( 'Default Shipment Method ID', 'woo-business-central' ); ?></label>
</th>
<td>
<input type="text" id="wbc_default_shipment_method_id" name="wbc_default_shipment_method_id"
value="<?php echo esc_attr( get_option( 'wbc_default_shipment_method_id', '' ) ); ?>"
class="regular-text" />
<p class="description">
<?php esc_html_e( 'Optional. Business Central shipment method ID to use for new orders.', 'woo-business-central' ); ?>
</p>
</td>
</tr>
<tr>
<th scope="row">
<label for="wbc_shipping_item_number"><?php esc_html_e( 'Shipping Item Number', 'woo-business-central' ); ?></label>
</th>
<td>
<input type="text" id="wbc_shipping_item_number" name="wbc_shipping_item_number"
value="<?php echo esc_attr( get_option( 'wbc_shipping_item_number', '' ) ); ?>"
class="regular-text" />
<p class="description">
<?php esc_html_e( 'Optional. Business Central item number to use for shipping charges.', 'woo-business-central' ); ?>
</p>
</td>
</tr>
<tr>
<th scope="row">
<label for="wbc_default_customer_number"><?php esc_html_e( 'Default Customer Number', 'woo-business-central' ); ?></label>
</th>
<td>
<input type="text" id="wbc_default_customer_number" name="wbc_default_customer_number"
value="<?php echo esc_attr( get_option( 'wbc_default_customer_number', '' ) ); ?>"
class="regular-text" />
<p class="description">
<?php esc_html_e( 'BC customer number to use for orders without NIF/CIF. Orders with NIF will look up or create a specific customer.', 'woo-business-central' ); ?>
</p>
</td>
</tr>
</table>
<p class="submit">
<?php submit_button( __( 'Save Settings', 'woo-business-central' ), 'primary', 'submit', false ); ?>
</p>
</div>
</form>
<?php elseif ( $current_tab === 'logs' ) : ?>
<!-- Logs -->
<div class="wbc-card">
<h2><?php esc_html_e( 'Sync Logs', 'woo-business-central' ); ?></h2>
<p>
<button type="button" id="wbc-clear-logs" class="button">
<?php esc_html_e( 'Clear All Logs', 'woo-business-central' ); ?>
</button>
<a href="<?php echo esc_url( add_query_arg( array( 'wbc_export_logs' => '1', '_wpnonce' => wp_create_nonce( 'wbc_export_logs' ) ) ) ); ?>"
class="button">
<?php esc_html_e( 'Download CSV', 'woo-business-central' ); ?>
</a>
</p>
<?php
$log_level = isset( $_GET['log_level'] ) ? sanitize_text_field( wp_unslash( $_GET['log_level'] ) ) : '';
$page_num = isset( $_GET['log_page'] ) ? max( 1, absint( $_GET['log_page'] ) ) : 1;
$per_page = 50;
$logs_data = WBC_Admin::get_logs_for_display( array(
'level' => $log_level,
'limit' => $per_page,
'offset' => ( $page_num - 1 ) * $per_page,
) );
$logs = $logs_data['logs'];
$total = $logs_data['total'];
$total_pages = ceil( $total / $per_page );
?>
<div class="wbc-log-filters">
<label for="wbc-log-level-filter"><?php esc_html_e( 'Filter by level:', 'woo-business-central' ); ?></label>
<select id="wbc-log-level-filter" onchange="location = this.value;">
<option value="<?php echo esc_url( remove_query_arg( 'log_level' ) ); ?>"><?php esc_html_e( 'All', 'woo-business-central' ); ?></option>
<?php foreach ( array( 'DEBUG', 'INFO', 'WARNING', 'ERROR' ) as $level ) : ?>
<option value="<?php echo esc_url( add_query_arg( 'log_level', $level ) ); ?>" <?php selected( $log_level, $level ); ?>>
<?php echo esc_html( $level ); ?>
</option>
<?php endforeach; ?>
</select>
</div>
<table class="wp-list-table widefat fixed striped wbc-logs-table">
<thead>
<tr>
<th class="column-timestamp"><?php esc_html_e( 'Timestamp', 'woo-business-central' ); ?></th>
<th class="column-level"><?php esc_html_e( 'Level', 'woo-business-central' ); ?></th>
<th class="column-context"><?php esc_html_e( 'Context', 'woo-business-central' ); ?></th>
<th class="column-message"><?php esc_html_e( 'Message', 'woo-business-central' ); ?></th>
</tr>
</thead>
<tbody>
<?php if ( empty( $logs ) ) : ?>
<tr>
<td colspan="4"><?php esc_html_e( 'No logs found.', 'woo-business-central' ); ?></td>
</tr>
<?php else : ?>
<?php foreach ( $logs as $log ) : ?>
<tr class="wbc-log-level-<?php echo esc_attr( strtolower( $log['level'] ) ); ?>">
<td class="column-timestamp">
<?php echo esc_html( wp_date( 'Y-m-d H:i:s', strtotime( $log['timestamp'] ) ) ); ?>
</td>
<td class="column-level">
<span class="wbc-log-badge wbc-log-badge-<?php echo esc_attr( strtolower( $log['level'] ) ); ?>">
<?php echo esc_html( $log['level'] ); ?>
</span>
</td>
<td class="column-context"><?php echo esc_html( $log['context'] ); ?></td>
<td class="column-message">
<?php echo esc_html( $log['message'] ); ?>
<?php if ( ! empty( $log['data'] ) ) : ?>
<button type="button" class="button-link wbc-toggle-data"
data-show-text="<?php esc_attr_e( 'Show data', 'woo-business-central' ); ?>"
data-hide-text="<?php esc_attr_e( 'Hide data', 'woo-business-central' ); ?>">
<?php esc_html_e( 'Show data', 'woo-business-central' ); ?>
</button>
<pre class="wbc-log-data" style="display: none;"><?php echo esc_html( $log['data'] ); ?></pre>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
<?php if ( $total_pages > 1 ) : ?>
<div class="tablenav bottom">
<div class="tablenav-pages">
<span class="displaying-num">
<?php printf( esc_html__( '%d items', 'woo-business-central' ), $total ); ?>
</span>
<span class="pagination-links">
<?php if ( $page_num > 1 ) : ?>
<a class="prev-page button" href="<?php echo esc_url( add_query_arg( 'log_page', $page_num - 1 ) ); ?>">
&lsaquo;
</a>
<?php endif; ?>
<span class="paging-input">
<?php echo esc_html( $page_num ); ?> / <?php echo esc_html( $total_pages ); ?>
</span>
<?php if ( $page_num < $total_pages ) : ?>
<a class="next-page button" href="<?php echo esc_url( add_query_arg( 'log_page', $page_num + 1 ) ); ?>">
&rsaquo;
</a>
<?php endif; ?>
</span>
</div>
</div>
<?php endif; ?>
</div>
<?php endif; ?>
</div>
</div>