From 97e7c319d656a5f05489ca996e249e7359303d4d Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Sun, 31 May 2026 22:42:33 +0000
Subject: [PATCH] =Jakevan edits done?

---
 inc/importers/JaneAppClientImporter.php |  214 ++++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 179 insertions(+), 35 deletions(-)

diff --git a/inc/importers/JaneAppClientImporter.php b/inc/importers/JaneAppClientImporter.php
index 7f04b5c..a16f68c 100644
--- a/inc/importers/JaneAppClientImporter.php
+++ b/inc/importers/JaneAppClientImporter.php
@@ -17,7 +17,8 @@
 	protected $wpdb;
 	protected string $jane_clients_table;
 	protected array $import_stats = [];
-
+	protected int $lineNumber = 0;
+	protected array $skipped_details = [];
 	// CSV column mapping
 	protected array $column_map = [
 		'patient_guid' => 'patient_guid',
@@ -25,6 +26,7 @@
 		'last_name' => 'Last Name',
 		'email' => 'Email',
 	];
+	protected array $headers = [];
 
 	public function __construct()
 	{
@@ -38,10 +40,13 @@
 	 *
 	 * @param string $file_path Path to the CSV file
 	 * @param array $options Import options (e.g., update_existing, send_welcome_email)
-	 * @return array Import results with stats and errors
+	 * @return array|WP_Error Import results with stats and errors
 	 */
-	public function importFromCSV(string $file_path, array $options = []): array
+	public function importFromCSV(string $file_path, array $options = []): array|WP_Error
 	{
+		$this->skipped_details = [];
+		$this->lineNumber = 0; // Reset line number
+
 		// Initialize stats
 		$this->import_stats = [
 			'total_rows' => 0,
@@ -50,7 +55,8 @@
 			'updated' => 0,
 			'skipped' => 0,
 			'errors' => [],
-			'unmatched_emails' => []
+			'unmatched_emails' => [],
+			'skipped_details' => [] // Add this
 		];
 
 		// Validate file exists
@@ -75,9 +81,10 @@
 			fclose($handle);
 			return new WP_Error('invalid_csv', 'CSV file is empty or invalid');
 		}
+		$this->headers = array_map('trim', $headers);
 
 		// Map column indices
-		$column_indices = $this->mapColumnIndices($headers);
+		$column_indices = $this->mapColumnIndices($this->headers);
 		if (is_wp_error($column_indices)) {
 			fclose($handle);
 			return $column_indices;
@@ -90,11 +97,13 @@
 			// Process each row
 			while (($row = fgetcsv($handle)) !== false) {
 				$this->import_stats['total_rows']++;
+				$this->lineNumber++;
 
 				$result = $this->processClientRow($row, $column_indices, [
 					'update_existing' => $update_existing,
 					'send_welcome_email' => $send_welcome_email,
-					'create_users' => $create_users
+					'create_users' => $create_users,
+					'default_role' => $options['default_role'] ?? null
 				]);
 
 				if (is_wp_error($result)) {
@@ -125,6 +134,9 @@
 
 		fclose($handle);
 
+		// Add skipped details to stats
+		$this->import_stats['skipped_details'] = $this->skipped_details;
+
 		return $this->import_stats;
 	}
 
@@ -170,39 +182,90 @@
 
 		// Validate required fields
 		if (empty($patient_guid) || empty($email)) {
+			$this->skipped_details[] = [
+				'name' => $first_name . ' ' . $last_name,
+				'guid'	=> $patient_guid,
+				'email' => $email,
+				'reason' => 'Missing guid or email',
+				'line' => $this->lineNumber
+			];
 			return new WP_Error('invalid_data', 'Missing patient_guid or email');
 		}
 
 		// Sanitize email
 		$email = sanitize_email($email);
 		if (!is_email($email)) {
+			$this->skipped_details[] = [
+				'name' => $first_name . ' ' . $last_name,
+				'guid'	=> $patient_guid,
+				'email' => $email,
+				'reason' => 'Invalid Email',
+				'line' => $this->lineNumber
+			];
 			return new WP_Error('invalid_email', 'Invalid email address: ' . $email);
 		}
 
 		// Check if client already exists in mapping table
 		$existing_mapping = $this->getClientByGuid($patient_guid);
 
+		// Build full data array with all CSV columns for meta storage
+		$data = [];
+		foreach ($row as $index => $value) {
+			$header = $this->headers[$index] ?? 'unknown_' . $index;
+			$data[$header] = trim($value);
+		}
+
+		// Ensure these keys exist for backward compatibility
+		$data['patient_guid'] = $patient_guid;
+		$data['First Name'] = $first_name;
+		$data['Last Name'] = $last_name;
+		$data['Email'] = $email;
+
 		// Find or create WordPress user
 		$user = get_user_by('email', $email);
+		$action = 'existing';
 
-		if (!$user && $options['create_users']) {
+		if ($user) {
+			if ($options['update_existing']) {
+				$this->updateExistingClient($user->ID, $data, $options);
+				$action = 'updated';
+			} else {
+				$this->skipped_details[] = [
+					'name' => $first_name . ' ' . $last_name,
+					'email' => $email,
+					'reason' => 'User already exists (update not enabled)',
+					'line' => $this->lineNumber
+				];
+				return new WP_Error('user_exists', 'User already exists');
+			}
+		} elseif ($options['create_users']) {
 			// Create new user
-			$user_id = $this->createWordPressUser($email, $first_name, $last_name, $options['send_welcome_email']);
+			$user_id = $this->createClientUser($data, $options);
 
 			if (is_wp_error($user_id)) {
+				$this->skipped_details[] = [
+					'name' => $first_name . ' ' . $last_name,
+					'guid'	=> $patient_guid,
+					'email' => $email,
+					'reason' => $user_id->get_error_message(),
+					'line' => $this->lineNumber
+				];
 				return $user_id;
 			}
 
 			$user = get_user_by('ID', $user_id);
 			$action = 'created';
-
-		} elseif (!$user) {
+		} else {
 			// User doesn't exist and we're not creating users
+			$this->skipped_details[] = [
+				'name' => $first_name . ' ' . $last_name,
+				'guid'	=> $patient_guid,
+				'email' => $email,
+				'reason' => 'User not found and create_users is false',
+				'line' => $this->lineNumber
+			];
 			$this->import_stats['unmatched_emails'][] = $email;
 			return new WP_Error('user_not_found', 'User not found and create_users is false');
-
-		} else {
-			$action = 'existing';
 		}
 
 		// Update or insert client mapping
@@ -214,7 +277,6 @@
 					'last_name' => $last_name,
 					'email' => $email
 				]);
-				$action = 'updated';
 			}
 		} else {
 			$this->insertClientMapping([
@@ -224,9 +286,6 @@
 				'last_name' => $last_name,
 				'email' => $email
 			]);
-			if ($action !== 'created') {
-				$action = 'mapped';
-			}
 		}
 
 		return [
@@ -237,49 +296,134 @@
 	}
 
 	/**
-	 * Create a new WordPress user
+	 * Create a new client user from Jane App data
 	 *
-	 * @param string $email User email
-	 * @param string $first_name First name
-	 * @param string $last_name Last name
-	 * @param bool $send_welcome_email Whether to send welcome email
+	 * @param array $data Client data from CSV
+	 * @param array $options Import options
 	 * @return int|WP_Error User ID or error
 	 */
-	protected function createWordPressUser(string $email, string $first_name, string $last_name, bool $send_welcome_email = false): int|WP_Error
+	protected function createClientUser(array $data, array $options)
 	{
+		$email = sanitize_email($data['Email']);
+		$first_name = sanitize_text_field($data['First Name'] ?? '');
+		$last_name = sanitize_text_field($data['Last Name'] ?? '');
+
 		// Generate username from email
-		$username = $this->generateUsername($email);
+		$username = sanitize_user($email);
 
-		// Generate random password
-		$password = wp_generate_password(12, true, true);
+		// Ensure unique username
+		$base_username = $username;
+		$counter = 1;
+		while (username_exists($username)) {
+			$username = $base_username . $counter;
+			$counter++;
+		}
 
-		$userdata = [
+		// Get the role from options with proper fallback
+		$role = $options['default_role'] ?? get_option(BASE . 'client_import_role', BASE.'client');
+
+		// Ensure role exists
+		if (!get_role($role)) {
+			return new WP_Error('invalid_role', 'Invalid role');
+		}
+
+		// Create user
+		$user_data = [
 			'user_login' => $username,
 			'user_email' => $email,
-			'user_pass' => $password,
 			'first_name' => $first_name,
 			'last_name' => $last_name,
 			'display_name' => trim($first_name . ' ' . $last_name),
-			'role' => apply_filters(BASE . 'jane_import_default_role', 'customer')
+			'role' => $role,
+			'user_pass' => wp_generate_password(16, true, true)
 		];
 
-		$user_id = wp_insert_user($userdata);
+		$user_id = wp_insert_user($user_data);
 
 		if (is_wp_error($user_id)) {
 			return $user_id;
 		}
 
-		// Send welcome email if requested
-		if ($send_welcome_email) {
-			wp_send_new_user_notifications($user_id, 'both');
+		// Store Jane App data as user meta
+		$this->storeClientMeta($user_id, $data);
+
+		// Send welcome email if enabled
+		if ($options['send_welcome_email'] ?? false) {
+			wp_new_user_notification($user_id, null, 'user');
 		}
 
-		do_action(BASE . 'jane_client_created', $user_id, $userdata);
-
 		return $user_id;
 	}
 
 	/**
+	 * Store Jane App client data as user meta
+	 *
+	 * @param int $user_id
+	 * @param array $data
+	 */
+	protected function storeClientMeta(int $user_id, array $data): void
+	{
+		// Store Jane App specific fields
+		if (!empty($data['patient_guid'])) {
+			update_user_meta($user_id, BASE . 'jane_patient_guid', sanitize_text_field($data['patient_guid']));
+		}
+
+		if (!empty($data['Patient Number'])) {
+			update_user_meta($user_id, BASE . 'jane_patient_number', sanitize_text_field($data['Patient Number']));
+		}
+
+		if (!empty($data['Member Since'])) {
+			update_user_meta($user_id, BASE . 'member_since', sanitize_text_field($data['Member Since']));
+		}
+
+		if (!empty($data['Mobile Phone'])) {
+			update_user_meta($user_id, BASE . 'phone', sanitize_text_field($data['Mobile Phone']));
+		}
+
+		if (!empty($data['Birth Date'])) {
+			update_user_meta($user_id, BASE . 'birth_date', sanitize_text_field($data['Birth Date']));
+		}
+
+		if (!empty($data['Referral Source'])) {
+			update_user_meta($user_id, BASE . 'referral_source', sanitize_text_field($data['Referral Source']));
+		}
+
+		// Store full Jane App data as JSON for reference
+		update_user_meta($user_id, BASE . 'jane_import_data', $data);
+		update_user_meta($user_id, BASE . 'jane_import_date', current_time('mysql'));
+	}
+
+	/**
+	 * Update existing client with Jane App data
+	 *
+	 * @param int $user_id
+	 * @param array $data
+	 * @param array $options
+	 */
+	protected function updateExistingClient(int $user_id, array $data, array $options): void
+	{
+		// Update user fields if they're empty
+		$user_data = ['ID' => $user_id];
+
+		$current_user = get_user_by('ID', $user_id);
+
+		if (empty($current_user->first_name) && !empty($data['First Name'])) {
+			$user_data['first_name'] = sanitize_text_field($data['First Name']);
+		}
+
+		if (empty($current_user->last_name) && !empty($data['Last Name'])) {
+			$user_data['last_name'] = sanitize_text_field($data['Last Name']);
+		}
+
+		if (count($user_data) > 1) {
+			wp_update_user($user_data);
+		}
+
+		// Always update meta data
+		$this->storeClientMeta($user_id, $data);
+	}
+
+	/**
 	 * Generate unique username from email
 	 *
 	 * @param string $email Email address

--
Gitblit v1.10.0