Company Structure
Company Hierarchy
Company (Root)
├── Department A
│ ├── Team 1
│ └── Team 2
└── Department B
└── Team 3
Company Service
namespace Vendor\B2B\Company\Service;
class CompanyService
{
private CompanyRepositoryInterface $companyRepo;
private CompanyStructureInterface $structure;
public function createCompany(array $data): CompanyInterface
{
$company = $this->companyFactory->create();
$company->setName($data['name']);
$company->setWebsiteId($data['website_id']);
$company->setStatus(CompanyInterface::STATUS_ACTIVE);
$company->setCreditLimit($data['credit_limit'] ?? 0);
$company->setRejectQuoteIf($data['reject_quote_if'] ?? false);
$company->setRequisitionListActive($data['requisition_list_active'] ?? true);
// Create root structure
$rootGroup = $this->structure->createRootGroup($company->getId(), $data['name']);
$company->setRootGroupId($rootGroup->getId());
return $this->companyRepo->save($company);
}
public function addChildGroup(
int $companyId,
int $parentId,
string $name
): CompanyGroupInterface {
return $this->structure->addGroup($companyId, $parentId, $name);
}
}
Company Structure Manager
namespace Vendor\B2B\Company\Structure;
class CompanyStructureManager
{
public function getStructure(int $companyId): array
{
$company = $this->companyRepo->get($companyId);
$rootGroupId = $company->getRootGroupId();
return $this->buildTree($rootGroupId);
}
private function buildTree(int $groupId): array
{
$group = $this->groupRepo->get($groupId);
$children = $this->groupRepo->getChildren($groupId);
return [
'id' => $group->getId(),
'name' => $group->getName(),
'children' => array_map([$this, 'buildTree'], $children),
'users' => $this->getGroupUsers($groupId),
];
}
}
Roles and Permissions
Company Roles
namespace Vendor\B2B\Company\Role;
class CompanyRoleService
{
private RoleRepositoryInterface $roleRepo;
public function createRole(
int $companyId,
array $data
): CompanyRoleInterface {
$role = $this->roleFactory->create();
$role->setCompanyId($companyId);
$role->setName($data['name']);
$role->setPermissions($data['permissions']);
return $this->roleRepo->save($role);
}
public function getPermissions(int $roleId): array
{
$role = $this->roleRepo->get($roleId);
return $role->getPermissions();
}
}
Permission Matrix
namespace Vendor\B2B\Company\Permission;
class PermissionMatrix
{
private array $permissions = [
'dashboard' => ['view', 'edit'],
'orders' => ['view', 'create', 'edit', 'delete'],
'quotes' => ['view', 'create', 'edit', 'negotiate'],
'requisition_lists' => ['view', 'create', 'edit', 'delete'],
'company_profile' => ['view', 'edit'],
'users' => ['view', 'create', 'edit', 'delete'],
];
public function check(
int $roleId,
string $resource,
string $action
): bool {
$permissions = $this->roleService->getPermissions($roleId);
return isset($permissions[$resource])
&& in_array($action, $permissions[$resource]);
}
}
Approval Workflows
Approval Rule Engine
namespace Vendor\B2B\Approval\Rule;
class ApprovalRuleEngine
{
private array $rules;
public function evaluate(
OrderInterface $order,
int $customerId
): ApprovalResult {
$customer = $this->customerRepo->getById($customerId);
$companyId = $customer->getCompanyId();
foreach ($this->rules as $rule) {
if ($rule->matches($order, $companyId)) {
return new ApprovalResult([
'requires_approval' => true,
'approvers' => $rule->getApprovers($companyId),
'rule' => $rule->getName(),
]);
}
}
return new ApprovalResult([
'requires_approval' => false,
]);
}
}
Approval Rule Types
namespace Vendor\B2B\Approval\Rule\Type;
interface ApprovalRuleInterface
{
public function matches(OrderInterface $order, int $companyId): bool;
public function getApprovers(int $companyId): array;
public function getName(): string;
}
class OrderTotalRule implements ApprovalRuleInterface
{
private float $threshold = 1000;
public function matches(OrderInterface $order, int $companyId): bool
{
return $order->getGrandTotal() > $this->threshold;
}
public function getApprovers(int $companyId): array
{
return $this->roleService->getUsersWithPermission(
$companyId,
'orders',
'approve'
);
}
}
class CreditLimitRule implements ApprovalRuleInterface
{
public function matches(OrderInterface $order, int $companyId): bool
{
$company = $this->companyRepo->get($companyId);
$remaining = $company->getCreditAvailable();
return $order->getGrandTotal() > $remaining;
}
}
Credit Limits
Credit Limit Manager
namespace Vendor\B2B\Credit\Limit;
class CreditLimitManager
{
private CompanyRepositoryInterface $companyRepo;
public function checkCredit(
int $companyId,
float $orderAmount
): CreditCheckResult {
$company = $this->companyRepo->get($companyId);
$creditLimit = $company->getCreditLimit();
$creditUsed = $company->getCreditUsed();
$available = $creditLimit - $creditUsed;
if ($orderAmount > $available) {
return new CreditCheckResult([
'approved' => false,
'credit_limit' => $creditLimit,
'credit_used' => $creditUsed,
'credit_available' => $available,
'shortfall' => $orderAmount - $available,
]);
}
return new CreditCheckResult([
'approved' => true,
'credit_limit' => $creditLimit,
'credit_used' => $creditUsed,
'credit_available' => $available,
]);
}
public function useCredit(
int $companyId,
float $amount,
int $orderId
): void {
$company = $this->companyRepo->get($companyId);
$company->setCreditUsed($company->getCreditUsed() + $amount);
$this->companyRepo->save($company);
// Log credit usage
$this->creditLog->log($companyId, $amount, $orderId);
}
public function releaseCredit(
int $companyId,
float $amount
): void {
$company = $this->companyRepo->get($companyId);
$company->setCreditUsed(max(0, $company->getCreditUsed() - $amount));
$this->companyRepo->save($company);
}
}
Credit Log
namespace Vendor\B2B\Credit\Log;
class CreditLog
{
public function log(
int $companyId,
float $amount,
int $orderId,
string $type = 'used'
): void {
$logEntry = new CreditLogData([
'company_id' => $companyId,
'amount' => $amount,
'order_id' => $orderId,
'type' => $type,
'created_at' => new \DateTime(),
]);
$this->logRepo->save($logEntry);
}
}
Quiz
1. What does a company structure define?
2. What is an approval workflow?
3. How do credit limits work?
Flashcards
Question
What is company structure?
Click to reveal answer
Answer
Hierarchical organization of users and teams
Question
What are approval rules?
Click to reveal answer
Answer
Conditions requiring manager approval for orders
Question
What is a credit limit?
Click to reveal answer
Answer
Maximum spending cap for a company account
Question
What are company roles?
Click to reveal answer
Answer
Permission sets assigned to company users
Revision Notes
Key Takeaways
- 1. Company structure organizes users in hierarchical groups
- 2. Roles and permissions control user access
- 3. Approval workflows enforce spending controls
- 4. Credit limits cap company spending
- 5. Credit logs track usage and releases
Interview Tips
- • Explain company hierarchy design
- • Discuss approval rule configurations
- • Describe credit limit management
- • Talk about role-based permission systems
Cheat Sheet
Company:
Structure → hierarchy of groups
Roles → permission sets
Users → company members
Approvals:
Rule → condition matching
Approvers → designated users
Workflow → approve/reject flow
Credit:
Limit → max spending cap
Used → current balance
Available → limit - used
Log → usage history