PHPackages                             orangecat/module-company - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Admin Panels](/categories/admin)
4. /
5. orangecat/module-company

ActiveMagento2-module[Admin Panels](/categories/admin)

orangecat/module-company
========================

Company entity management for Magento 2 B2B — registration, approval workflow, roles, and user management

0.0.2(2d ago)02↑2900%7OSL-3.0PHPPHP &gt;=8.1

Since Jun 5Pushed 2d agoCompare

[ Source](https://github.com/olivertar/m2_company)[ Packagist](https://packagist.org/packages/orangecat/module-company)[ RSS](/packages/orangecat-module-company/feed)WikiDiscussions main Synced 2d ago

READMEChangelog (2)Dependencies (2)Versions (3)Used By (7)

Orangecat\_Company
==================

[](#orangecat_company)

**Module:** `Orangecat_Company`**Version:** 1.0.0 **License:** OSL-3.0 **Author:** Oliverio Gombert

---

Table of Contents
-----------------

[](#table-of-contents)

1. [Overview](#overview)
2. [Theme Compatibility](#theme-compatibility)
3. [Requirements](#requirements)
4. [Installation](#installation)
5. [What Gets Installed](#what-gets-installed)
6. [Configuration](#configuration)
7. [Store Admin Guide](#store-admin-guide)
8. [Frontend User Guide](#frontend-user-guide)
9. [Developer Guide](#developer-guide)
10. [REST API](#rest-api)
11. [Frontend Routes Reference](#frontend-routes-reference)
12. [DevOps &amp; Integrator Notes](#devops--integrator-notes)

---

Overview
--------

[](#overview)

`Orangecat_Company` is the **core B2B module** of the Orangecat suite. It introduces the concept of a **Company** entity into Magento 2 — a legal business unit that groups multiple customers under a shared identity with role-based access control.

The module handles:

- Company entity management (create, approve, suspend, reject)
- Company registration form on the frontend (separate from standard customer registration)
- Customer approval workflow — accounts can require admin approval before login is allowed
- Role assignment per company user (Admin, Manager, Buyer)
- Frontend user management panel for Company Admins
- Access controls for standard registration and login flows
- Email notifications for registration events and status changes
- Full REST API and Admin UI for company management

### Position in the Orangecat B2B Dependency Chain

[](#position-in-the-orangecat-b2b-dependency-chain)

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

```

All other B2B modules depend on this one. It must be installed and enabled first.

---

Theme Compatibility
-------------------

[](#theme-compatibility)

ThemeStatusNotes**Luma**Supported"Create a Company" link placed in `header.links`. Standard `.phtml` templates.**Breeze Evolution**SupportedCustom template `breeze/company-register-link.phtml`. Link placed in `top.links`.**Hyvä**SupportedAlpine.js-compatible templates. Link placed in `header.customer.logged.out.links`. Custom CSS loaded from `web/css/hyva/module.css`.Each theme has its own layout handles and templates. No cross-theme interference.

---

Requirements
------------

[](#requirements)

- Magento 2.4.x
- PHP &gt; 8.1
- `orangecat/core` (composer dependency)
- Modules: `Magento_Customer`, `Magento_Eav`, `Magento_Backend`, `Magento_Ui`, `Magento_Theme`

---

Installation
------------

[](#installation)

### Via Git Submodule (recommended for this project)

[](#via-git-submodule-recommended-for-this-project)

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

### Enable the Module

[](#enable-the-module)

Run inside the PHP container (`reward shell`):

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

---

What Gets Installed
-------------------

[](#what-gets-installed)

### Database Tables

[](#database-tables)

TableDescription`mycompany`Company flat table — name, legal name, email, tax ID, address, status, website`mycompany_role`Company roles with JSON permissions`mycompany_customer`Link table joining companies, customers, and roles. Also stores per-user purchase limits.**`mycompany` columns:** `entity_id`, `name`, `name_legal`, `email`, `tax_id`, `address`, `city`, `country`, `region`, `postalcode`, `telephone`, `status`, `website_id`, `created_at`, `updated_at`

**`mycompany_customer` columns:** `link_id`, `company_id`, `customer_id`, `role_id`, `max_purchase_amount`, `max_period_amount`

> A customer can belong to only one company (unique constraint on `customer_id`).

### Customer EAV Attribute

[](#customer-eav-attribute)

AttributeTypePurpose`approve_account``int` (boolean)Controls whether a customer can log in. `1` = approved, `0` = pending/blocked. Visible in Admin &gt; Customer grid and form.### Default Roles

[](#default-roles)

Installed automatically via data patch:

Role IDNamePermissions1Company Admin`all`2Company Manager`manage_users`, `view_orders`3Company Buyer`place_order`### CMS Page

[](#cms-page)

A placeholder CMS page is created at URL key `company-terms` (Company Terms and Conditions). **Edit its content** via Admin &gt; Content &gt; Pages before going live.

---

Configuration
-------------

[](#configuration)

**Path:** `Stores > Configuration > Orangecat > Company (B2B)`

### Email Notification

[](#email-notification)

FieldDescriptionDefaultEnable New Company NotificationSend email to admin(s) when a new company is registeredNoNotification Email AddressComma-separated list of recipient email addresses—Email TemplateTemplate for the admin notification`New Company Registration Notification`Company - New Account No Password TemplateEmail sent to the company admin when their account is created (no password set)`New Company Customer - No Password`Company - Status Change TemplateEmail sent to the company email when its status changes`Company Status Change Notification`Config paths:

```
mycompany/email/enable_email_notification
mycompany/email/notification_email
mycompany/email/email_template
mycompany/email/company_no_password_template
mycompany/email/company_status_change_template

```

### Customers

[](#customers)

FieldDescriptionDefaultAllow Frontend Customer RegistrationIf No, hides "Create an Account" and blocks `/customer/account/create` (returns 404)NoRequire Approval for CustomerIf Yes, newly registered customers start with `approve_account = 0` and cannot log in until manually approved. Only available when registration is allowed.YesConfig paths:

```
mycompany/customers/allow_frontend_customer_registration
mycompany/customers/require_approval_for_customer

```

---

Store Admin Guide
-----------------

[](#store-admin-guide)

### Managing Companies

[](#managing-companies)

**Path:** Admin menu &gt; **Companies &gt; Companies**

The company grid supports:

- Inline editing of company name, email, and status
- Full create/edit form with all company fields and customer assignment

#### Company Statuses

[](#company-statuses)

StatusValueMeaningPending0Submitted via frontend, awaiting reviewApproved1Active — associated customers can log inSuspended2Temporarily blockedRejected3Registration denied> Changing status to Approved/Suspended/Rejected triggers the **Status Change** email to the company's email address (if the template is configured).

#### Company Form Fields

[](#company-form-fields)

FieldRequiredNotesCompany NameYesDisplay nameLegal NameNoLegal/registered nameCompany EmailYesMust be unique. Must differ from the admin's email.Tax / VAT IDNoMust be unique if providedAddress, City, Region, Postal Code, CountryNoTelephoneNoStatusYesSee statuses above#### Assigning Customers to a Company

[](#assigning-customers-to-a-company)

From the Company edit form, use the **Customer Assignment** section to select a customer as the Company Admin via a grid chooser. The customer is linked with Role ID 1 (Company Admin).

Alternatively, open any **Customer** in Admin &gt; Customers &gt; All Customers and use the **Company Assignment** tab:

- Select a company using the radio-button grid
- Assign a role from the dropdown
- Click **Save Customer**

**Business rules enforced on save:**

1. A company can have only **one** Company Admin (Role ID 1). Attempting to assign a second admin is blocked.
2. A company **must always** have one Admin. Changing the only admin's role or removing them is blocked. Assign a replacement admin first.

---

### Approving Customers

[](#approving-customers)

When `Require Approval for Customer` is enabled, new registrations set `approve_account = 0` (and force logout to prevent auto-login).

To approve:

1. Admin &gt; Customers &gt; All Customers
2. Open the customer
3. Set **Approve Account** to **Yes**
4. Save

Unapproved customers attempting to log in see:

> *"Your account is not enabled or your company has not yet been enabled."*

---

Frontend User Guide
-------------------

[](#frontend-user-guide)

### Company Registration

[](#company-registration)

Guests can register a new company at: `/company/account/create`

The "Create a Company" link appears in the header for guests (not visible when logged in).

**Registration form fields:**

SectionFieldsCompany InformationCompany Name, Legal Name, Company Email, Tax ID, Address, City, Region, Postal Code, Country, TelephoneCompany AdministratorFirst Name, Last Name, Email**Validations applied:**

- Company email and admin email cannot be the same
- Admin email must not already exist as a customer
- Company email must be unique (no existing company with same email)
- Tax ID must be unique (if provided)

After submission, the company is created with **Pending** status. The admin's customer account is created without a password. A confirmation page is shown and an email is sent to the admin(s) if notification is enabled.

---

### Company User Management (Company Admin only)

[](#company-user-management-company-admin-only)

Accessible via Account Dashboard &gt; **Company Users** — visible only to users with the Company Admin role.

**Available actions:**

- **List users** — shows all members of the company with name, email, role, and status
- **Add user** — create a new customer account and link it to the company
- **Edit user** — change name, email, or role
- **Toggle status** — enable or disable a user's `approve_account` flag
- **Delete user** — permanently removes the customer account

Non-admin company members are redirected to the account dashboard if they try to access this section.

---

Developer Guide
---------------

[](#developer-guide)

### Module Structure

[](#module-structure)

```
Orangecat/Company/
├── Api/                          Service contracts (interfaces)
│   ├── CompanyRepositoryInterface.php
│   ├── CompanyManagementInterface.php
│   ├── RoleRepositoryInterface.php
│   └── Data/
│       ├── CompanyInterface.php
│       ├── CompanyCustomerInterface.php
│       ├── RoleInterface.php
│       └── CompanySearchResultsInterface.php
├── Block/
│   ├── Account/                  Frontend: registration link + create form
│   └── Adminhtml/               Admin: company + customer tab blocks
│       ├── Company/Edit/
│       └── Edit/Tab/
├── Controller/
│   ├── Account/                  company/account/* routes
│   ├── Users/                    company/users/* routes
│   └── Adminhtml/Company/        mycompany/* admin routes
├── Model/                        Entities, repositories, config
├── Observer/                     Auto-approve + admin save
├── Plugin/                       Login, registration, Hyvä integration
├── Setup/Patch/Data/             EAV attribute + default roles + T&C page
├── Ui/Component/                 UI form data providers and modifiers
└── view/
    ├── adminhtml/                Admin UI components and layouts
    └── frontend/
        ├── layout/               Luma, Breeze (breeze_*), Hyvä (hyva_*) handles
        ├── templates/            Luma + Breeze + Hyvä (hyva/) templates
        ├── email/                Transactional email templates
        └── web/css/hyva/         Hyvä-specific CSS

```

### Service Contracts

[](#service-contracts)

#### `CompanyRepositoryInterface`

[](#companyrepositoryinterface)

```
save(CompanyInterface $company): CompanyInterface
get(int $companyId): CompanyInterface
getList(SearchCriteriaInterface $searchCriteria): CompanySearchResultsInterface
delete(CompanyInterface $company): bool
deleteById(int $companyId): bool
```

#### `CompanyManagementInterface`

[](#companymanagementinterface)

```
assignCustomer(int $companyId, int $customerId, int $roleId, array $data = []): bool
removeCustomer(int $customerId): bool
getCompanyIdByCustomerId(int $customerId): ?int
getRoleIdByCustomerId(int $customerId): ?int
isCompanyAdmin(int $customerId): bool
validateManageUser(int $adminId, ?int $targetUserId): void  // throws LocalizedException
```

#### `RoleRepositoryInterface`

[](#rolerepositoryinterface)

Standard CRUD + `getList` for `RoleInterface`.

---

### Key Models

[](#key-models)

#### `Orangecat\Company\Model\Company`

[](#orangecatcompanymodelcompany)

Extends `AbstractModel`. Constants:

```
Company::STATUS_PENDING    = 0
Company::STATUS_APPROVED   = 1
Company::STATUS_SUSPENDED  = 2
Company::STATUS_REJECTED   = 3
```

#### `Orangecat\Company\Model\Config`

[](#orangecatcompanymodelconfig)

Helper for reading all module config values. Inject and use:

```
$config->isFrontendCustomerRegistrationAllowed(): bool
$config->isCustomerApprovalRequired(): bool
$config->isNotificationEnabled(): bool
$config->getNotificationEmail(): string
$config->getEmailTemplate(): string
$config->getCompanyNoPasswordEmailTemplate(): string
$config->getCompanyStatusChangeEmailTemplate(): string
$config->isCompanyUser(int $customerId): bool
$config->isCompanyRegistrationContext(): bool
```

---

### Plugins

[](#plugins)

PluginTargetTypePurpose`RegistrationRestriction``Customer\Controller\Account\Create` &amp; `CreatePost``before`Throws 404 if registration is disabled`RegisterLink``Customer\Block\Account\RegisterLink``after`Hides "Create an Account" if registration is disabled`CompanyRegisterLinkVisibility``Block\Account\CompanyRegisterLink``after`Controls "Create a Company" link visibility for guests`CustomerRegistration` (Hyvä)`Hyva\Theme\ViewModel\CustomerRegistration``after`Hides registration via Hyvä's ViewModel when disabled`LoginPost``Customer\Controller\Account\LoginPost``around`Blocks login for unapproved customers`CustomerRepositoryInterfacePlugin``CustomerRepositoryInterface``around`Prevents deletion of a company admin`CustomerRepositoryInterfaceSavePlugin``CustomerRepositoryInterface``after`Persists company assignment data on customer save`TransportBuilderPlugin``Mail\Template\TransportBuilder``around`Swaps email template for company users (no-password flow)---

### Observers

[](#observers)

ObserverEventAreaPurpose`AutoApproveCustomer``customer_register_success``frontend`Sets `approve_account` = 1 or 0 based on config. Forces logout if not approved.`SaveCompanyObserver``adminhtml_customer_save_after``adminhtml`Reads `customer[company_id]` and `customer[role_id]` from POST and saves the company link. Enforces single-admin and mandatory-admin rules.---

### Adding Hyvä Layout Support

[](#adding-hyvä-layout-support)

Hyvä-specific layout handles use the `hyva_` prefix. This module provides:

```
hyva_default.xml                   — "Create a Company" header link + CSS
hyva_customer_account_login.xml    — Login page adjustments
hyva_company_users_index.xml       — Users list page
hyva_company_users_create.xml      — Create user page
hyva_company_users_edit.xml        — Edit user page

```

Templates for Hyvä are under `view/frontend/templates/hyva/` and `view/frontend/templates/users/edit_hyva.phtml` / `list_hyva.phtml`.

> Do not put Hyvä templates in `view/hyva/` — this project uses `view/frontend/templates/hyva/` as the convention.

---

### Email Templates

[](#email-templates)

Template IDFileTrigger`mycompany_email_email_template``new_company.html`New company registered (sent to store admin)`mycompany_email_company_no_password_template``company_account_new_no_password.html`Company admin account created without password`company_user_welcome``company_user_welcome.html`New company user added`mycompany_email_company_status_change_template``company_status_change.html`Company status changedTemplates are in `view/frontend/email/`. Customize via Admin &gt; Marketing &gt; Email Templates.

---

### ACL Resources

[](#acl-resources)

Resource IDTitleLocation`Orangecat_Company::company_manage`Company ManagementAdmin top-level`Orangecat_Company::company`CompaniesUnder Company Management`Orangecat_Company::config`Company SettingsUnder Stores &gt; Settings---

REST API
--------

[](#rest-api)

All endpoints require admin authorization (`Orangecat_Company::company` resource).

### Endpoints

[](#endpoints)

MethodURLAction`POST``/V1/mycompany/`Create company`PUT``/V1/mycompany/:entity_id`Update company`GET``/V1/mycompany/:companyId`Get company by ID`DELETE``/V1/mycompany/:companyId`Delete company`GET``/V1/mycompany/`Search companies (with `searchCriteria`)### Example: Create Company

[](#example-create-company)

```
curl -X POST https://your-store.test/rest/V1/mycompany/ \
  -H "Authorization: Bearer " \
  -H "Content-Type: application/json" \
  -d '{
    "company": {
      "name": "Acme Corp",
      "email": "billing@acme.com",
      "tax_id": "US12345678",
      "status": 1
    }
  }'
```

### Example: Search with Filter

[](#example-search-with-filter)

```
GET /V1/mycompany/?searchCriteria[filter_groups][0][filters][0][field]=status
    &searchCriteria[filter_groups][0][filters][0][value]=1
    &searchCriteria[filter_groups][0][filters][0][condition_type]=eq
```

---

Frontend Routes Reference
-------------------------

[](#frontend-routes-reference)

RouteControllerAccess`GET /company/account/create``Controller\Account\Create`Guests only`POST /company/account/createPost``Controller\Account\CreatePost`Guests only`GET /company/account/success``Controller\Account\Success`Public`GET /company/users``Controller\Users\Index`Company Admin only`GET /company/users/create``Controller\Users\Create`Company Admin only`POST /company/users/save``Controller\Users\Save`Company Admin only`GET /company/users/edit``Controller\Users\Edit`Company Admin only`POST /company/users/delete``Controller\Users\Delete`Company Admin only`POST /company/users/status``Controller\Users\Status`Company Admin only---

DevOps &amp; Integrator Notes
-----------------------------

[](#devops--integrator-notes)

### Deployment Checklist

[](#deployment-checklist)

```
# After deploying or updating this module:
bin/magento module:enable Orangecat_Company
bin/magento setup:upgrade          # runs db_schema.xml migrations + data patches (EAV, roles, CMS page)
bin/magento setup:di:compile       # regenerates interceptors and proxies
bin/magento setup:static-content:deploy -f
bin/magento cache:flush
```

### Integration Token Scope

[](#integration-token-scope)

Minimum permissions for an ERP or external integration reading company data:

- `Orangecat_Company::company`
- `Orangecat_Company::company_manage` (parent required)

### Disabling Without Uninstalling

[](#disabling-without-uninstalling)

**Warning:** all dependent modules (`Orangecat_CompanyCredit`, `Orangecat_CompanyMethods`, `Orangecat_Prices`, etc.) must be disabled first.

```
bin/magento module:disable Orangecat_Company
bin/magento setup:upgrade
bin/magento cache:flush
```

### Data Integrity

[](#data-integrity)

- `mycompany_customer` enforces a unique constraint on `customer_id` — one company per customer.
- Deleting a company does not automatically delete linked customers; only the `mycompany_customer` link row is removed.
- The `approve_account` EAV attribute persists after module disable. Re-enabling the module restores the approval gate.
- The `company-terms` CMS page is created by data patch and is not removed on module disable or uninstall.

###  Health Score

38

—

LowBetter than 83% of packages

Maintenance99

Actively maintained with recent releases

Popularity3

Limited adoption so far

Community13

Small or concentrated contributor base

Maturity33

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~1 days

Total

2

Last Release

2d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/959440?v=4)[Oliverio Gombert](/maintainers/olivertar)[@olivertar](https://github.com/olivertar)

---

Top Contributors

[![olivertar](https://avatars.githubusercontent.com/u/959440?v=4)](https://github.com/olivertar "olivertar (42 commits)")

---

Tags

b2bmagento2companyorangecat

### Embed Badge

![Health badge](/badges/orangecat-module-company/health.svg)

```
[![Health](https://phpackages.com/badges/orangecat-module-company/health.svg)](https://phpackages.com/packages/orangecat-module-company)
```

###  Alternatives

[redchamps/module-clean-admin-menu

It will merge all third party extensions menu items to single menu item named 'Extensions'.

165438.8k](/packages/redchamps-module-clean-admin-menu)[kiwicommerce/module-cron-scheduler

Easily set up and manage cron jobs from the backend with a beautiful and managed timeline feature. Find the actual load on CPU/Memory by cron job execution.

74606.1k](/packages/kiwicommerce-module-cron-scheduler)[smile/module-seller

Smile Retailer Suite - Seller Module

13539.8k4](/packages/smile-module-seller)[myparcelnl/magento

A Magento 2 module that creates MyParcel labels

1859.0k](/packages/myparcelnl-magento)[kiwicommerce/module-customer-password

Magento 2 - Customer Password

1356.8k](/packages/kiwicommerce-module-customer-password)[vasileuski/magento2-module-admin-search

Magento 2 module that enhances the admin panel's global search by enabling fast and efficient searches through main entities with improved visibility and ACL support.

253.1k](/packages/vasileuski-magento2-module-admin-search)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
