Commit e3cef4d5cf4 for woocommerce

commit e3cef4d5cf4a17c87f17176785be8234ac56b921
Author: Mike Jolley <mike.jolley@me.com>
Date:   Fri Mar 6 15:38:44 2026 +0000

    Fix V4 Customers API requiring username/password based on store settings (#63536)

    Store registration settings (woocommerce_registration_generate_username,
    woocommerce_registration_generate_password) should only affect frontend
    registration forms, not the admin-facing REST API. This makes username
    and password always optional in the V4 Customers endpoint, with
    auto-generation when not provided.

    Also fixes the customer data store to sync back the auto-generated
    username from the WP user after creation.

    Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

diff --git a/plugins/woocommerce/changelog/wooprd-1726-customer-creation-issue-depending-on-password-settings b/plugins/woocommerce/changelog/wooprd-1726-customer-creation-issue-depending-on-password-settings
new file mode 100644
index 00000000000..c6b6260b0fe
--- /dev/null
+++ b/plugins/woocommerce/changelog/wooprd-1726-customer-creation-issue-depending-on-password-settings
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Make username and password optional in V4 Customers REST API regardless of store registration settings.
diff --git a/plugins/woocommerce/includes/data-stores/class-wc-customer-data-store.php b/plugins/woocommerce/includes/data-stores/class-wc-customer-data-store.php
index aa089adb871..4bebfbe1564 100644
--- a/plugins/woocommerce/includes/data-stores/class-wc-customer-data-store.php
+++ b/plugins/woocommerce/includes/data-stores/class-wc-customer-data-store.php
@@ -117,6 +117,14 @@ class WC_Customer_Data_Store extends WC_Data_Store_WP implements WC_Customer_Dat
 		}

 		$customer->set_id( $id );
+
+		// Sync back the user data from the created WP user in case it was auto-generated.
+		$wp_user = new WP_User( $id );
+		if ( $wp_user->exists() ) {
+			$customer->set_username( $wp_user->user_login );
+			$customer->set_date_created( $wp_user->user_registered );
+		}
+
 		$this->update_user_meta( $customer );

 		// Prevent wp_update_user calls in the same request and customer trigger the 'Notice of Password Changed' email.
@@ -133,8 +141,6 @@ class WC_Customer_Data_Store extends WC_Data_Store_WP implements WC_Customer_Dat
 				$customer
 			)
 		);
-		$wp_user = new WP_User( $customer->get_id() );
-		$customer->set_date_created( $wp_user->user_registered );
 		$customer->set_date_modified( get_user_meta( $customer->get_id(), 'last_update', true ) );
 		$customer->save_meta_data();
 		$customer->apply_changes();
diff --git a/plugins/woocommerce/src/Internal/RestApi/Routes/V4/Customers/Controller.php b/plugins/woocommerce/src/Internal/RestApi/Routes/V4/Customers/Controller.php
index 65e6b0cad51..73c4bb93c4b 100644
--- a/plugins/woocommerce/src/Internal/RestApi/Routes/V4/Customers/Controller.php
+++ b/plugins/woocommerce/src/Internal/RestApi/Routes/V4/Customers/Controller.php
@@ -116,13 +116,13 @@ class Controller extends AbstractController {
 								'description' => __( 'New user email address.', 'woocommerce' ),
 							),
 							'username' => array(
-								'required'    => 'no' === get_option( 'woocommerce_registration_generate_username', 'yes' ),
-								'description' => __( 'New user username.', 'woocommerce' ),
+								'required'    => false,
+								'description' => __( 'New user username. Generated from email if not provided.', 'woocommerce' ),
 								'type'        => 'string',
 							),
 							'password' => array(
-								'required'    => 'no' === get_option( 'woocommerce_registration_generate_password', 'no' ),
-								'description' => __( 'New user password.', 'woocommerce' ),
+								'required'    => false,
+								'description' => __( 'New user password. Generated automatically if not provided.', 'woocommerce' ),
 								'type'        => 'string',
 							),
 						)
diff --git a/plugins/woocommerce/tests/php/includes/rest-api/Controllers/Version4/Customers/class-wc-rest-customers-v4-controller-tests.php b/plugins/woocommerce/tests/php/includes/rest-api/Controllers/Version4/Customers/class-wc-rest-customers-v4-controller-tests.php
index 71a14cd99b2..94f3be57999 100644
--- a/plugins/woocommerce/tests/php/includes/rest-api/Controllers/Version4/Customers/class-wc-rest-customers-v4-controller-tests.php
+++ b/plugins/woocommerce/tests/php/includes/rest-api/Controllers/Version4/Customers/class-wc-rest-customers-v4-controller-tests.php
@@ -925,6 +925,37 @@ class WC_REST_Customers_V4_Controller_Tests extends WC_REST_Unit_Test_Case {
 		$this->assertEquals( 400, $response->get_status() );
 	}

+	/**
+	 * Test creating customer without username or password succeeds regardless of store settings.
+	 *
+	 * Store settings like woocommerce_registration_generate_username and
+	 * woocommerce_registration_generate_password should not affect this admin API.
+	 * Username and password should always be optional and auto-generated when not provided.
+	 */
+	public function test_create_customer_without_username_or_password(): void {
+		// Disable auto-generation in store settings (simulates the problematic configuration).
+		update_option( 'woocommerce_registration_generate_username', 'no' );
+		update_option( 'woocommerce_registration_generate_password', 'no' );
+
+		$customer_data = array(
+			'email'      => 'nousernameorpassword@example.com',
+			'first_name' => 'Test',
+			'last_name'  => 'User',
+		);
+
+		$request = new WP_REST_Request( 'POST', '/wc/v4/customers' );
+		$request->set_body_params( $customer_data );
+		$response = $this->server->dispatch( $request );
+
+		$this->assertEquals( 201, $response->get_status() );
+
+		$response_data = $response->get_data();
+		$this->assertNotEmpty( $response_data['username'] );
+		$this->assertEquals( 'nousernameorpassword@example.com', $response_data['email'] );
+
+		$this->created_customers[] = $response_data['id'];
+	}
+
 	/**
 	 * Test comprehensive value validation for all customer fields.
 	 */