orangecat/module-company-sales-rep

Assigns a Magento admin user as sales representative to a B2B company and displays contact details on the customer dashboard

Maintainers

Package info

github.com/olivertar/m2_companysalesrep

Type:magento2-module

pkg:composer/orangecat/module-company-sales-rep

Statistics

Installs: 20

Dependents: 1

Suggesters: 0

Stars: 0

Open Issues: 0

0.0.2 2026-06-07 18:28 UTC

This package is auto-updated.

Last update: 2026-06-07 18:55:31 UTC


README

Assigns a Magento admin user as a sales representative to a B2B company and displays their contact details on the customer account dashboard.

Module: Orangecat_CompanySalesRep Version: 1.0.0 License: OSL-3.0 Author: Oliverio Gombert olivertar@gmail.com

Table of Contents

  1. Overview
  2. Theme Compatibility
  3. Requirements
  4. Installation
  5. What Gets Installed
  6. Configuration
  7. Store Admin Guide
  8. Company Member Guide (Frontend)
  9. Developer Guide
  10. REST API
  11. Frontend Routes Reference
  12. DevOps & Integrator Notes

Overview

Orangecat_CompanySalesRep extends Orangecat_Company to allow store admins to assign a designated admin user as the sales representative for each B2B company. Company members can then see their rep's name, email, telephone, and WhatsApp directly on the customer account dashboard.

The module handles:

  • Adding a Sales Representative dropdown to the company edit form in the admin
  • Extending the admin user edit form with Telephone and WhatsApp contact fields
  • Persisting the assignment via a foreign-key column on the mycompany table
  • Rendering a Sales Representative contact card on the customer account dashboard (Luma and Hyvä themes)

Position in the Orangecat B2B Dependency Chain

Orangecat_Core (via composer: orangecat/core)
  └── Orangecat_Company
        ├── Orangecat_Prices
        │     ├── Orangecat_PricesList
        │     └── Orangecat_PricesCompany
        ├── Orangecat_CompanyCredit
        ├── Orangecat_CompanyMethods
        ├── Orangecat_CompanySalesRep     ← this module
        └── Orangecat_PurchaseOrder

Orangecat_Company and Magento_User must both be installed and enabled before this module.

Theme Compatibility

Theme Status Notes
Luma Supported Dedicated template sales_rep.phtml. Uses standard .box markup. Layout handle customer_account_index.xml.
Hyvä Supported Dedicated template sales_rep_hyva.phtml with Tailwind CSS card layout. Layout handle hyva_customer_account_index.xml.
Breeze Evolution Partial No dedicated Breeze layout. Falls back to the Luma template via customer_account_index.xml, which Breeze inherits. Functional but unstyled in Breeze card conventions. Add a breeze_customer_account_index.xml layout and a dedicated template to apply Breeze-native styling.

Requirements

Dependency Version / Notes
Magento 2.4.x
PHP >= 8.1
Orangecat_Company Must be enabled first
Magento_User Core admin user module (bundled with Magento)
magento/framework Bundled with Magento

Installation

Via Git Submodule (recommended for this project)

# From repo root
git submodule add git@github.com:olivertar/m2_company_sales_rep.git app/code/Orangecat/CompanySalesRep
git submodule update --init --recursive

Enable the Module

Run inside the PHP container (reward shell):

bin/magento module:enable Orangecat_CompanySalesRep
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento setup:static-content:deploy -f
bin/magento cache:flush

What Gets Installed

Database Columns

This module does not create new tables. It adds columns to two existing tables.

mycompany (extended from Orangecat_Company)

Column Type Nullable Notes
sales_rep_id INT UNSIGNED Yes FK → admin_user.user_id. Set to NULL on admin user delete.

admin_user (core Magento table)

Column Type Nullable Notes
telephone VARCHAR(50) Yes Sales rep phone number, used for tel: links.
whatsapp VARCHAR(50) Yes Sales rep WhatsApp number, used for wa.me/ links.

EAV Attributes

None.

Data Patches

None. No default records, roles, or CMS pages are created.

Configuration

This module has no system configuration (no entries in core_config_data). All settings are per-entity.

Per-Company Setting

Field Storage Notes
Sales Representative mycompany.sales_rep_id Set in the company edit form under the General fieldset.

Per-Admin User Settings

Field Storage Notes
Telephone admin_user.telephone Set in the admin user edit form. Used for tel: links on frontend.
WhatsApp admin_user.whatsapp Set in the admin user edit form. Used for https://wa.me/ links on frontend.

Store Admin Guide

Assigning a Sales Representative to a Company

  1. Navigate to Companies > Companies (or the path defined by Orangecat_Company).
  2. Open a company record.
  3. In the General fieldset, locate the Sales Representative dropdown.
  4. Select the admin user to assign. The list shows all active admin users as "First Last (username)". Select -- Unassigned -- to remove a rep.
  5. Save the company.

The dropdown only lists currently active admin users. If an admin user is deactivated or deleted after assignment, sales_rep_id is automatically set to NULL (via the ON DELETE SET NULL foreign key constraint), and the sales rep card will no longer appear on the customer dashboard.

Adding Contact Details to an Admin User

  1. Navigate to System > Permissions > All Users.
  2. Open the admin user record.
  3. In the Account Information tab, locate the Telephone and WhatsApp fields added by this module.
  4. Enter the contact details and save.

These fields are optional. Only fields with values are rendered on the customer dashboard.

Company Member Guide (Frontend)

Sales Representative Card

Company members who are logged in can view their assigned sales representative's contact information on the My Account dashboard.

URL: /customer/account/

If a sales rep has been assigned to the company, a Sales Representative card is displayed alongside the standard account information blocks. The card shows:

  • Name — rep's first and last name
  • Email — clickable mailto: link
  • Telephone — clickable tel: link (non-numeric characters stripped for the href)
  • WhatsApp — clickable https://wa.me/ link (digits only in the href)

Fields are only shown if they contain a value. The card does not appear if:

  • No sales rep has been assigned to the company.
  • The assigned admin user has been deactivated or deleted.
  • The logged-in customer does not belong to a company.

Developer Guide

Module Structure

CompanySalesRep/
├── Block/
│   └── Customer/Account/Dashboard/
│       └── SalesRep.php              # Frontend block — loads and exposes sales rep data
├── Model/
│   └── Source/
│       └── AdminUsers.php            # OptionSourceInterface — dropdown options for company form
├── Plugin/
│   ├── CompanyDataProviderPlugin.php # afterGetData — injects sales_rep_id into company form
│   ├── CompanyRepositoryPlugin.php   # beforeSave — persists sales_rep_id from request
│   └── User/Edit/Tab/
│       └── MainPlugin.php            # afterGetForm — adds telephone/whatsapp to admin user form
├── etc/
│   ├── adminhtml/
│   │   └── di.xml                    # Plugin registrations (adminhtml scope)
│   ├── db_schema.xml                 # Column additions to mycompany and admin_user
│   └── module.xml                    # v1.0.0, depends on Orangecat_Company + Magento_User
├── view/
│   ├── adminhtml/
│   │   └── ui_component/
│   │       └── mycompany_company_form.xml  # Adds sales_rep_id field to company form
│   └── frontend/
│       ├── layout/
│       │   ├── customer_account_index.xml       # Luma: adds SalesRep block to dashboard
│       │   └── hyva_customer_account_index.xml  # Hyvä: adds SalesRep block with Hyvä template
│       └── templates/account/dashboard/
│           ├── sales_rep.phtml       # Luma template — .box markup
│           └── sales_rep_hyva.phtml  # Hyvä template — Tailwind card
├── registration.php
└── composer.json

Key Classes

Class Role
Block\Customer\Account\Dashboard\SalesRep Extends Template. Lazy-loads sales rep from session + company + admin_user. Exposes hasSalesRep(), getSalesRepName(), getSalesRepEmail(), getSalesRepTelephone(), getSalesRepWhatsApp().
Model\Source\AdminUsers Implements OptionSourceInterface. Returns all active admin users sorted by first name as [['value' => id, 'label' => 'First Last (username)']]. Includes an "-- Unassigned --" option with empty value.

SalesRep Block — Public Methods

public function hasSalesRep(): bool
public function getSalesRepName(): string
public function getSalesRepEmail(): string
public function getSalesRepTelephone(): string
public function getSalesRepWhatsApp(): string

Observers

None. This module registers no observers.

Plugins

Plugin Class Target Hook Purpose
Plugin\CompanyDataProviderPlugin Orangecat\Company\Ui\Component\Form\Company\DataProvider afterGetData Reads sales_rep_id from CompanyRepository and injects it into the company form data array.
Plugin\CompanyRepositoryPlugin Orangecat\Company\Api\CompanyRepositoryInterface beforeSave Reads sales_rep_id from the current HTTP request and sets it on the company object before persistence. Converts empty string to null.
Plugin\User\Edit\Tab\MainPlugin Magento\User\Block\User\Edit\Tab\Main afterGetForm Appends telephone and whatsapp text fields to the admin user edit form. Re-applies model data to populate saved values.

All three plugins are registered in etc/adminhtml/di.xml (adminhtml scope only).

JS Components

None. This module has no custom JavaScript.

Email Templates

None. This module sends no emails.

ACL Resources

None. This module defines no ACL resources. Access to the company form and admin user form is governed by Orangecat_Company and Magento_User ACL respectively.

Adding Custom Logic

  • Add more contact fields: Extend db_schema.xml to add columns to admin_user, add fields in MainPlugin, and add getter methods to SalesRep block. No new templates needed if you add output to existing .phtml files.
  • Filter sales rep options: Extend or replace Model\Source\AdminUsers via DI preference to restrict the dropdown (e.g., by admin role or custom attribute).
  • Override the dashboard card: Override sales_rep.phtml or sales_rep_hyva.phtml in your theme's template directory at Orangecat_CompanySalesRep/account/dashboard/.

REST API

This module exposes no REST API endpoints. Sales rep assignment is managed exclusively through the admin UI. The sales_rep_id field is available on the company object retrieved via Orangecat_Company REST endpoints (it is a raw data field on the company model).

Frontend Routes Reference

This module defines no frontend routes. The sales rep card is rendered as a block within the existing /customer/account/ page via layout XML.

DevOps & Integrator Notes

Deployment Checklist

# Inside reward shell (PHP container)
bin/magento module:enable Orangecat_CompanySalesRep
bin/magento setup:upgrade          # applies db_schema.xml column additions
bin/magento setup:di:compile
bin/magento setup:static-content:deploy -f
bin/magento cache:flush

Integration Token Scope

This module adds no ACL resources. To manage company sales rep assignments via the Orangecat_Company REST API, the integration token requires whatever ACL the Company module mandates for company save operations.

Disabling Without Uninstalling

bin/magento module:disable Orangecat_CompanySalesRep
bin/magento cache:flush

Disabling hides the sales rep card from the dashboard and removes the Sales Representative field from the company form. The database columns (mycompany.sales_rep_id, admin_user.telephone, admin_user.whatsapp) are retained — no data loss.

Data Integrity Notes

  • mycompany.sales_rep_id has an ON DELETE SET NULL foreign key to admin_user.user_id. Deleting an admin user automatically clears the assignment on all companies without orphaning records.
  • The two new columns on admin_user (telephone, whatsapp) are nullable with no unique constraint. They persist independently of whether the module is enabled.
  • No cascade deletes. Disabling or uninstalling the module does not remove these columns automatically — use bin/magento setup:db-declaration:generate-patch and a custom schema patch if column removal is needed.