A Laravel 13 package providing reusable Party, Person, Organization, Role, and Relationship domain models, inspired by the universal data modeling concepts presented by Len Silverston in The Data Model Resource Book, Volume 1.

Maintainers

Package info

github.com/michael-orenda/party

pkg:composer/michael-orenda/party

Transparency log

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0


README

A reusable Laravel 13 Party Model package for representing people, organizations, roles, and relationships across enterprise applications.

The package provides a foundational enterprise identity model inspired by the Universal Data Model concepts described by Len Silverston in The Data Model Resource Book, Volume 1.

Instead of creating separate identities for customers, employees, suppliers, directors, members, borrowers, guarantors, and other participants, the package represents each real-world person or organization once as a Party and models the different capacities in which that Party participates using Party Roles and Party Relationships.

                         PARTY
                           │
                ┌──────────┴──────────┐
                │                     │
              PERSON             ORGANIZATION
                │                     │
                └──────────┬──────────┘
                           │
                      PARTY ROLE
                           │
                           ▼
                  PARTY RELATIONSHIP

Why a Party Model?

Traditional applications commonly create domain-specific entities such as:

customers
employees
suppliers
directors
members
borrowers
guarantors

This works initially, but can cause the same real-world person or organization to be represented multiple times.

For example, Michael may simultaneously be:

Employee
Customer
Director
Member
Borrower

These are not five different people.

They are five capacities in which the same person participates.

The Party model represents this as:

                       Michael
                          │
                        PARTY
                          │
          ┌───────────────┼───────────────┐
          │               │               │
      EMPLOYEE         CUSTOMER        DIRECTOR
          │
          ├──────────── MEMBER
          │
          └──────────── BORROWER

The identity exists once.

Its roles and relationships can change over time.

Core Principle

The package is built around a simple principle:

Model what an entity is separately from the roles it plays and the relationships in which it participates.

A Party answers:

Who or what is this?

A Party Role answers:

In what capacity is this Party participating?

A Party Relationship answers:

Why does this role exist, and with whom is it exercised?

Conceptually:

PARTY
  │
  │ Who or what is this?
  ▼
PERSON / ORGANIZATION

  │
  │ In what capacity is the Party participating?
  ▼
PARTY ROLE

  │
  │ Why does that role exist and
  │ with whom is it exercised?
  ▼
PARTY RELATIONSHIP

For the complete explanation of the model and its design philosophy, see:

Party Model Concepts and Design Philosophy

Example

Consider the statement:

Michael is employed by Software Technologies.

The model does not simply connect Michael directly to Software Technologies.

Instead, it captures the capacities in which both Parties participate:

Michael
   │
   ▼
 PARTY
   │
   ▼
EMPLOYEE
   │
   │ EMPLOYMENT
   ▼
EMPLOYER
   │
   ▼
 PARTY
   │
   ▼
Software Technologies

This provides considerably more business meaning than a simple foreign-key association.

It also allows the relationship to contain information such as:

from_date
thru_date
comment

and allows the historical relationship to remain intact after it ends.

Features

The package currently provides:

  • Party identities using UUIDv7 identifiers
  • Person specialization
  • Organization specialization
  • hierarchical Organizations
  • Party Role Types
  • Party Roles
  • Party Relationship Types
  • permitted relationship role combinations
  • directional Party Relationships
  • effective relationship dates
  • historical relationship preservation
  • relationship comments
  • organization hierarchy validation
  • cycle prevention in Organization hierarchies
  • transactional Party creation
  • transactional relationship creation
  • data-driven Role and Relationship vocabularies
  • Laravel Eloquent models and relationships
  • service-layer domain operations
  • Form Request validation
  • Laravel API Resources
  • REST API endpoints
  • reference-data API endpoints
  • seeders for standard Party vocabulary
  • PHPUnit/Testbench test suite
  • Laravel package auto-discovery

Requirements

The package requires:

PHP >= 8.3
Laravel 13

The package is developed and tested as a Laravel package using Orchestra Testbench and PHPUnit.

Installation

Install the package through Composer:

composer require michael-orenda/party

Laravel package discovery automatically registers:

MichaelOrenda\Party\PartyServiceProvider::class

Run the migrations:

php artisan migrate

The package migrations create the core Party schema.

For complete installation instructions, local package development, configuration publishing, migrations, and verification, see:

Installation Guide

Database Model

The package uses eight core tables:

parties
people
organizations

party_role_types
party_roles

party_relationship_types
party_relationship_role_types
party_relationships

At a high level:

                         parties
                        /       \
                       /         \
                  people      organizations


                         parties
                            │
                            ▼
                       party_roles
                            │
                            ▼
                    party_role_types


                  party_role_types
                         │
                         ▼
          party_relationship_role_types
                         │
                         ▼
              party_relationship_types
                         │
                         ▼
                party_relationships
                    /           \
                   /             \
          from_party_role    to_party_role

For the complete schema, constraints, keys, indexes, and table-by-table explanation, see:

Database Schema

Core Models

The package provides the following Eloquent models:

Party
Person
Organization

PartyRoleType
PartyRole

PartyRelationshipType
PartyRelationshipRoleType
PartyRelationship

The central identity model is:

Party
├── Person
└── Organization

A Party may then hold multiple roles:

Party
  │
  └── PartyRole
         │
         └── PartyRoleType

Relationships connect Party Roles:

PartyRole
    │
    ▼
PartyRelationship
    │
    ▼
PartyRole

For the complete model and Eloquent relationship reference, see:

Models and Eloquent Relationships

Creating a Person

Using the package service layer:

use MichaelOrenda\Party\Data\CreatePersonData;
use MichaelOrenda\Party\Services\PartyService;

$person = app(PartyService::class)->createPerson(
    new CreatePersonData(
        firstName: 'Michael',
        lastName: 'Orenda',
        middleName: 'Philip',
    )
);

This creates both:

Party
  │
  ▼
Person

inside a database transaction.

The common Party identity is available through:

$person->party;

or:

$person->party_id;

Creating an Organization

use MichaelOrenda\Party\Data\CreateOrganizationData;
use MichaelOrenda\Party\Services\PartyService;

$organization = app(PartyService::class)->createOrganization(
    new CreateOrganizationData(
        name: 'Software Technologies'
    )
);

This creates:

Party
  │
  ▼
Organization

Organization Hierarchies

Organizations may contain other Organizations.

For example:

Software Technologies
│
├── Development
├── Finance
└── Human Resources

The hierarchy is represented using:

organizations.parent_id

The package prevents invalid structures such as:

A
└── B
    └── C
        └── A

and prevents an Organization from becoming its own parent.

Organization hierarchy is intentionally separate from general Party Relationships.

Assigning Party Roles

A Party can participate in multiple capacities.

For example:

$employeeRole = app(PartyService::class)->assignRole(
    $person->party,
    'EMPLOYEE'
);

The same Party could later also receive:

CUSTOMER
DIRECTOR
MEMBER
BORROWER

without creating another Person.

Party Relationships

Relationships connect Party Roles rather than merely connecting Parties.

For example:

Michael [EMPLOYEE]
        │
        │ EMPLOYMENT
        ▼
Software Technologies [EMPLOYER]

A relationship contains:

relationship type
FROM Party Role
TO Party Role
from date
thru date
comment

Relationship direction is controlled by the configured relationship-role rules.

Applications should therefore not assume that a particular role is always the FROM or TO side.

For the complete service-layer documentation, see:

Services and Domain Operations

REST API

The package exposes its API under:

/api/party

The current API includes:

/api/party/people
/api/party/organizations
/api/party/roles
/api/party/relationships

/api/party/reference/role-types
/api/party/reference/relationship-types
/api/party/reference/relationship-role-types

For example:

POST /api/party/people
{
    "first_name": "Michael",
    "middle_name": "Philip",
    "last_name": "Orenda"
}

Create an Organization:

POST /api/party/organizations
{
    "name": "Software Technologies"
}

Assign a role:

POST /api/party/roles
{
    "party_id": "019f...",
    "role_type_code": "EMPLOYEE"
}

The API also exposes reference-data endpoints so clients can discover the configured Party vocabulary and valid relationship-role combinations.

For the complete endpoint reference, validation rules, request bodies, responses, and status codes, see:

HTTP API Reference

Postman Collection

A complete Postman collection is included with the package for exploring and testing the Party REST API.

The collection is located at:

postman/Michael-Orenda-Party.postman_collection.json

The collection covers all Party API endpoints, including:

  • People
  • Organizations
  • Party Roles
  • Party Relationships
  • Party Role Types
  • Party Relationship Types
  • Party Relationship Role Types
  • validation and domain-rule examples

The collection uses the following base URL variable:

{{base_url}}

Set this to the URL of the Laravel application in which the package is installed.

For example:

http://datamodels.test

The collection automatically captures identifiers returned by create operations and stores them as collection variables.

For example:

Create Person
    │
    ├── person_id
    └── person_party_id

Create Organization
    │
    ├── organization_id
    └── organization_party_id

Assign Party Roles
    │
    ├── from_party_role_id
    └── to_party_role_id

Create Relationship
    │
    └── party_relationship_id

This allows related requests to be executed sequentially without manually copying UUIDs between requests.

Importing the Collection

In Postman:

  1. Select Import.

  2. Select the file:

    postman/Michael-Orenda-Party.postman_collection.json
    
  3. Open the imported Michael Orenda - Party API collection.

  4. Set the base_url collection variable to the URL of your Laravel application.

  5. Start with the Reference Data requests to inspect the configured Party vocabulary.

A typical workflow is:

Reference Data
      │
      ▼
Create Person
      │
      ▼
Create Organization
      │
      ▼
Assign Party Roles
      │
      ▼
Create Party Relationship
      │
      ▼
Retrieve / Update Relationship

For detailed explanations of every endpoint, see:

HTTP API Reference

For complete business examples demonstrating how these endpoints work together, see:

Practical Examples and Usage Patterns

Practical Examples

The documentation includes examples covering:

People
Organizations
Organization hierarchies
Employees and Employers
Employment history
Directors
Customers
Suppliers
Borrowers
Lenders
Guarantors
Members
Board Management
Human Resources
Procurement
CRM
Lending
cross-domain enterprise identity

See:

Practical Examples and Usage Patterns

Universal Identity Across Applications

The package is designed to act as foundational infrastructure for multiple business domains.

For example:

                         PARTY
                           │
        ┌──────────────────┼──────────────────┐
        │                  │                  │
        ▼                  ▼                  ▼
       HR               Lending             CRM
        │                  │                  │
        ▼                  ▼                  ▼
    Employee            Borrower           Customer

                           │
             ┌─────────────┴─────────────┐
             │                           │
             ▼                           ▼
       Board Management              Membership
             │                           │
             ▼                           ▼
         Director                      Member

Instead of each application redefining the same Person or Organization, domain packages can reference the common:

party_id

This makes Party suitable as a foundational model for modular enterprise systems.

What This Package Does Not Do

The package deliberately does not attempt to implement every business domain.

For example, a Lending package may reference:

BORROWER
LENDER
GUARANTOR

but loan-specific concepts such as:

principal
interest
repayment schedules
collateral
credit assessment
loan balances

belong in the Lending domain.

Likewise, HR-specific concepts such as:

payroll
leave
performance management
positions
compensation

belong in an HR domain.

The Party package provides identity and relationship infrastructure upon which these domains can be built.

Documentation

The package documentation is organized as a progressive guide:

Chapter Documentation Description
01 Concepts and Design Philosophy Why the Party model exists and the principles behind it
02 Architecture Package structure and architectural design
03 Installation Installation, configuration, migrations, and setup
04 Database Schema Tables, keys, constraints, indexes, and relationships
05 Models Eloquent models and model relationships
06 Services Domain operations and PartyService
07 HTTP API Complete REST API reference
08 Examples Practical enterprise modeling examples

Developers unfamiliar with Party modeling should begin with:

01 — Concepts and Design Philosophy

and then read:

08 — Practical Examples and Usage Patterns

before designing application-specific Party extensions.

Testing

The package includes a PHPUnit test suite built using Orchestra Testbench.

Run:

composer test

The package can therefore be tested independently from the consuming Laravel application.

Additional Composer validation can be performed using:

composer validate

and:

composer check-platform-reqs

Package Development

When developing the package locally using a Composer path repository, the host application's composer.json can reference the package:

{
    "repositories": [
        {
            "type": "path",
            "url": "packages/michael-orenda/party",
            "options": {
                "symlink": true
            }
        }
    ]
}

Then require it from the host application:

composer require michael-orenda/party:@dev

This allows changes in the package source directory to be immediately available to the host Laravel application.

See the Installation Guide for the complete development setup.

Design Philosophy

The package deliberately separates:

Identity
   │
   ▼
Party

Participation
   │
   ▼
Party Role

Business Context
   │
   ▼
Party Relationship

This avoids coupling enterprise identity to any single business application.

For the complete discussion—including identity versus roles, relationship context, historical relationships, universal concepts versus application concepts, and extensibility—see:

Party Model Concepts and Design Philosophy

Acknowledgements

The domain modeling concepts used in this package are inspired by the work of Len Silverston, particularly the universal data modeling patterns presented in:

Len Silverston, The Data Model Resource Book, Volume 1: A Library of Universal Data Models for All Enterprises, John Wiley & Sons.

Silverston's work demonstrates how common enterprise concepts—including parties, people, organizations, roles, relationships, products, orders, agreements, work efforts, and other business entities—can be represented using reusable and extensible data models.

The michael-orenda/party package applies these ideas to a modern Laravel architecture, with particular emphasis on the Party, Person, Organization, Party Role, and Party Relationship concepts.

This package is an independent implementation.

It is not affiliated with, endorsed by, or an official implementation of Len Silverston's work or the publisher.

The software design and source code in this package are independently developed for use within Laravel applications.

License

The michael-orenda/party package is open-source software licensed under the MIT License.

See:

LICENSE

Author

Michael Philip Orenda

Michael Orenda

Package:

michael-orenda/party

Website:

[https://michael-orenda.com](https://michael-orenda.com)

Project Goal

The long-term objective of michael-orenda/party is to provide a stable, reusable enterprise identity foundation for Laravel applications.

Instead of repeatedly asking:

Should this application have a customer table, employee table, supplier table, borrower table, or member table?

the Party model encourages a more fundamental question:

Who or what is this Party, in what capacity is it participating, and what relationship gives that participation meaning?

That distinction allows multiple enterprise applications to share a consistent representation of people and organizations while remaining free to implement their own domain-specific behavior.