Untitled
Anonymous
plain_text
09/14/2026 8:41 AM
18.6 KB
3
Indexable
<?php
/**
* Plugin Name: Softhrive B2B Roles & Registration
* Description: F9 — creates the 4 B2B/B2C roles and extends /my-account/register/ with an optional business registration toggle.
* Version: 1.0.0
* Author: Softhrive
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/* ---------------------------------------------------------
* STEP 1 — Roles (created on activation)
* retail_customer / wholesale_customer / reseller / pending_b2b
* These exact slugs must never change — Odoo connector (F10) is
* built around them.
* ------------------------------------------------------- */
function softhrive_b2b_roles_create() {
add_role( 'retail_customer', 'Retail Customer', array(
'read' => true,
'level_0' => true,
) );
add_role( 'wholesale_customer', 'Wholesale Customer', array(
'read' => true,
'level_0' => true,
'view_wholesale_pricing' => true,
) );
add_role( 'reseller', 'Reseller', array(
'read' => true,
'level_0' => true,
'view_reseller_pricing' => true,
) );
add_role( 'pending_b2b', 'Pending B2B Approval', array(
'read' => true,
'level_0' => true,
) );
}
register_activation_hook( __FILE__, 'softhrive_b2b_roles_create' );
// Dev-only convenience: recreate roles if this file gets refreshed
// but WordPress doesn't re-fire activation (e.g. after a manual file
// overwrite without deactivate/activate).
add_action( 'admin_init', function() {
if ( ! get_role( 'retail_customer' ) ) {
softhrive_b2b_roles_create();
}
} );
function softhrive_b2b_roles_remove() {
remove_role( 'retail_customer' );
remove_role( 'wholesale_customer' );
remove_role( 'reseller' );
remove_role( 'pending_b2b' );
}
register_deactivation_hook( __FILE__, 'softhrive_b2b_roles_remove' );
/* ---------------------------------------------------------
* STEP 2 — Extend the registration form
* ------------------------------------------------------- */
function softhrive_b2b_register_fields() {
?>
<div class="softhrive-b2b-toggle-row">
<label class="softhrive-b2b-toggle">
<input type="checkbox" name="softhrive_is_b2b" id="softhrive_is_b2b" value="1" <?php echo ( ! empty( $_POST['softhrive_is_b2b'] ) ) ? 'checked' : ''; ?>>
<span class="softhrive-b2b-toggle-track"><span class="softhrive-b2b-toggle-thumb"></span></span>
<span class="softhrive-b2b-toggle-label">I'm registering as a business (B2B)</span>
</label>
</div>
<div class="softhrive-b2b-fields" id="softhrive-b2b-fields">
<p class="form-row form-row-wide">
<label for="softhrive_company_name">Company name <span class="required">*</span></label>
<input type="text" class="input-text" name="softhrive_company_name" id="softhrive_company_name"
value="<?php echo ( ! empty( $_POST['softhrive_company_name'] ) ) ? esc_attr( wp_unslash( $_POST['softhrive_company_name'] ) ) : ''; ?>">
</p>
<p class="form-row form-row-first">
<label for="softhrive_vat_number">VAT number <span class="optional">(optional)</span></label>
<input type="text" class="input-text" name="softhrive_vat_number" id="softhrive_vat_number"
value="<?php echo ( ! empty( $_POST['softhrive_vat_number'] ) ) ? esc_attr( wp_unslash( $_POST['softhrive_vat_number'] ) ) : ''; ?>">
</p>
<p class="form-row form-row-last">
<label for="softhrive_business_type">Business type <span class="required">*</span></label>
<select class="input-text" name="softhrive_business_type" id="softhrive_business_type">
<option value="">Select one</option>
<option value="Wholesale">Wholesale Customer</option>
<option value="Retail">Retail Customer</option>
<option value="Reseller">Reseller</option>
</select>
</p>
<p class="form-row form-row-wide">
<label for="softhrive_phone">Contact number <span class="required">*</span></label>
<input type="tel" class="input-text" name="softhrive_phone" id="softhrive_phone"
value="<?php echo ( ! empty( $_POST['softhrive_phone'] ) ) ? esc_attr( wp_unslash( $_POST['softhrive_phone'] ) ) : ''; ?>">
</p>
<p class="softhrive-b2b-note">Your account will be reviewed before you can see wholesale pricing. We'll email you once it's approved.</p>
</div>
<?php
}
add_action( 'woocommerce_register_form', 'softhrive_b2b_register_fields' );
function softhrive_b2b_register_validation( $errors, $username, $email ) {
if ( ! empty( $_POST['softhrive_is_b2b'] ) ) {
if ( empty( $_POST['softhrive_company_name'] ) ) {
$errors->add( 'softhrive_company_name_error', 'Please enter your company name.' );
}
if ( empty( $_POST['softhrive_business_type'] ) ) {
$errors->add( 'softhrive_business_type_error', 'Please select your business type.' );
}
if ( empty( $_POST['softhrive_phone'] ) ) {
$errors->add( 'softhrive_phone_error', 'Please enter a contact number.' );
}
}
return $errors;
}
add_filter( 'woocommerce_registration_errors', 'softhrive_b2b_register_validation', 10, 3 );
function softhrive_b2b_save_registration( $customer_id ) {
$user = new WP_User( $customer_id );
if ( ! empty( $_POST['softhrive_is_b2b'] ) ) {
update_user_meta( $customer_id, 'softhrive_company_name', sanitize_text_field( wp_unslash( $_POST['softhrive_company_name'] ?? '' ) ) );
update_user_meta( $customer_id, 'softhrive_vat_number', sanitize_text_field( wp_unslash( $_POST['softhrive_vat_number'] ?? '' ) ) );
update_user_meta( $customer_id, 'softhrive_business_type', sanitize_text_field( wp_unslash( $_POST['softhrive_business_type'] ?? '' ) ) );
update_user_meta( $customer_id, 'softhrive_phone', sanitize_text_field( wp_unslash( $_POST['softhrive_phone'] ?? '' ) ) );
$user->set_role( 'pending_b2b' );
softhrive_b2b_notify_admin( $customer_id );
} else {
$user->set_role( 'retail_customer' );
}
}
add_action( 'woocommerce_created_customer', 'softhrive_b2b_save_registration' );
/* ---------------------------------------------------------
* STEP 3 — Approval workflow
* ------------------------------------------------------- */
// 1. Admin gets emailed the moment a new B2B account registers
function softhrive_b2b_notify_admin( $customer_id ) {
$user = get_userdata( $customer_id );
if ( ! $user ) {
return;
}
$company = get_user_meta( $customer_id, 'softhrive_company_name', true );
$business_type = get_user_meta( $customer_id, 'softhrive_business_type', true );
$phone = get_user_meta( $customer_id, 'softhrive_phone', true );
$vat = get_user_meta( $customer_id, 'softhrive_vat_number', true );
$edit_link = admin_url( 'user-edit.php?user_id=' . $customer_id );
$subject = 'New B2B account awaiting approval — ' . $company;
$message = "A new business account has registered and needs review:\n\n";
$message .= "Name: " . $user->display_name . "\n";
$message .= "Email: " . $user->user_email . "\n";
$message .= "Company: " . $company . "\n";
$message .= "Business type: " . $business_type . "\n";
$message .= "Phone: " . $phone . "\n";
if ( $vat ) {
$message .= "VAT number: " . $vat . "\n";
}
$message .= "\nTo approve: open the user, change their Role to \"Wholesale Customer\" or \"Reseller\", then Update.\n";
$message .= "To reject: delete the user.\n\n";
$message .= "Review here: " . $edit_link;
wp_mail( get_option( 'admin_email' ), $subject, $message );
}
// 2. Customer gets emailed automatically the moment admin approves
// (i.e. changes their role from pending_b2b to wholesale_customer/reseller
// via the normal Users screen — set_user_role fires either way)
function softhrive_b2b_notify_customer_on_approval( $user_id, $role, $old_roles ) {
$was_pending = in_array( 'pending_b2b', $old_roles, true );
$now_approved = in_array( $role, array( 'wholesale_customer', 'reseller' ), true );
if ( ! $was_pending || ! $now_approved ) {
return;
}
$user = get_userdata( $user_id );
if ( ! $user ) {
return;
}
$subject = 'Your Twisted Hygiene business account has been approved';
$message = "Hi " . $user->display_name . ",\n\n";
$message .= "Good news — your business account has been approved. You can now log in and see your wholesale pricing:\n\n";
$message .= wc_get_page_permalink( 'myaccount' ) . "\n\n";
$message .= "Thanks,\nTwisted Hygiene & Packaging";
wp_mail( $user->user_email, $subject, $message );
}
add_action( 'set_user_role', 'softhrive_b2b_notify_customer_on_approval', 10, 3 );
/* ---------------------------------------------------------
* Styling — matches the project's teal brand, scoped to the
* WooCommerce register form only (login form untouched)
* ------------------------------------------------------- */
function softhrive_b2b_register_assets() {
if ( ! function_exists( 'is_account_page' ) || ! is_account_page() ) {
return;
}
?>
<style>
.woocommerce-form-register{
background:#ffffff !important;
border:1px solid #e5e7eb !important;
border-radius:20px !important;
padding:32px !important;
}
.softhrive-b2b-toggle-row{
margin:22px 0 !important;
padding:16px 18px !important;
background:#f0fdfa !important;
border:1px solid #d1fae5 !important;
border-radius:12px !important;
}
.softhrive-b2b-toggle{
display:flex !important;
align-items:center !important;
gap:12px !important;
cursor:pointer !important;
margin:0 !important;
position:relative !important;
}
.softhrive-b2b-toggle input{
position:absolute !important;
opacity:0 !important;
width:1px !important;
height:1px !important;
}
.softhrive-b2b-toggle-track{
width:42px !important;
height:24px !important;
border-radius:999px !important;
background:#d1d5db !important;
position:relative !important;
flex-shrink:0 !important;
transition:background .2s ease !important;
}
.softhrive-b2b-toggle-thumb{
position:absolute !important;
top:3px !important; left:3px !important;
width:18px !important; height:18px !important;
border-radius:50% !important;
background:#ffffff !important;
box-shadow:0 1px 3px rgba(0,0,0,.2) !important;
transition:transform .2s ease !important;
}
.softhrive-b2b-toggle input:checked ~ .softhrive-b2b-toggle-track{
background:#0d9488 !important;
}
.softhrive-b2b-toggle input:checked ~ .softhrive-b2b-toggle-track .softhrive-b2b-toggle-thumb{
transform:translateX(18px) !important;
}
.softhrive-b2b-toggle-label{
font-size:14.5px !important;
font-weight:700 !important;
color:#1f2937 !important;
}
.softhrive-b2b-fields{
display:none;
margin-top:18px;
}
.softhrive-b2b-fields.is-visible{
display:block;
}
.woocommerce-form-register .form-row label{
font-size:12.5px !important;
font-weight:600 !important;
color:#6b7280 !important;
margin-bottom:6px !important;
display:block !important;
}
.woocommerce-form-register .input-text,
.woocommerce-form-register select{
width:100% !important;
border:1.5px solid #e5e7eb !important;
border-radius:10px !important;
padding:12px 14px !important;
font-size:14px !important;
font-family:inherit !important;
}
.woocommerce-form-register .input-text:focus,
.woocommerce-form-register select:focus{
outline:none !important;
border-color:#0d9488 !important;
box-shadow:0 0 0 3px rgba(13,148,136,.12) !important;
}
.softhrive-b2b-note{
font-size:12.5px !important;
color:#6b7280 !important;
background:#f9fafb !important;
border-radius:8px !important;
padding:10px 14px !important;
margin-top:6px !important;
}
.woocommerce-form-register button[type="submit"]{
width:100% !important;
height:52px !important;
border:none !important;
border-radius:14px !important;
background:#0f8b8d !important;
color:#fff !important;
font-size:15px !important;
font-weight:800 !important;
box-shadow:0 15px 35px rgba(15,139,141,.2) !important;
cursor:pointer !important;
}
.woocommerce-form-register button[type="submit"]:hover{
background:#0b7c72 !important;
}
</style>
<script>
document.addEventListener('DOMContentLoaded', function () {
var toggle = document.getElementById('softhrive_is_b2b');
var fields = document.getElementById('softhrive-b2b-fields');
if (!toggle || !fields) { return; }
function sync() {
fields.classList.toggle('is-visible', toggle.checked);
}
toggle.addEventListener('change', sync);
sync();
});
</script>
<?php
}
add_action( 'wp_footer', 'softhrive_b2b_register_assets' );Editor is loading...
Leave a Comment