Skip to content

Data Model

middag-account stores domain data using WordPress Custom Post Types (CPTs) with metadata in wp_postmeta. A dual-repository system supports migration to custom tables (CCT) via a feature toggle.

Custom Post Types

Each domain maps to a CPT with the middag_ prefix. All CPTs use show_ui => false (no wp-admin UI) and register custom capabilities.

DomainCPT SlugMeta Prefix
Organizationmiddag_organizationorg_
Collaboratormiddag_collaboratorcollab_
Entitlementmiddag_entitlementent_
Environmentmiddag_environmentenv_
Servicemiddag_servicesvc_
Ticketmiddag_ticketsr_
Quotemiddag_quotequote_
Invoicemiddag_invoiceinvoice_
TaxInvoicemiddag_tax_invoicetaxinvoice_
Contractmiddag_contractcontract_
Documentmiddag_documentdocument_

Adapter Domains (No Own CPT)

These domains wrap existing WooCommerce or third-party data:

DomainStorageNotes
OrderWooCommerce ordersOrderService adapter
LicenseWC Software LicenseLicenseService adapter
DownloadWooCommerce productsDownloadService adapter
AffiliateSolidAffiliate recordsAffiliateService adapter

Meta Key Conventions

Domain metadata is stored in wp_postmeta with prefixed keys. Entity classes accept both API snake_case keys and CCT-prefixed keys via fromArray():

php
// Both are valid:
$entity = EntitlementEntity::fromArray(['code' => 'PLG-2026040001']);
$entity = EntitlementEntity::fromArray(['ent_code' => 'PLG-2026040001']);

Organization Meta Keys

Meta KeyTypeDescription
org_namestringDisplay name
org_legalnamestringLegal entity name
org_documentnumber1stringCNPJ (Brazil)
org_documentnumber2stringState registration
org_emailstringPrimary contact email
org_phonestringPhone number
org_typestringcompany or individual
org_verification_statusstringpending, verified
org_stripe_customer_id_brstringStripe customer (BR entity)
org_stripe_customer_id_globalstringStripe customer (US entity)
org_hubspot_company_id_brstringHubSpot company (BR)
org_hubspot_company_id_globalstringHubSpot company (US)

Entitlement Meta Keys

Meta KeyTypeDescription
ent_codestringUnique code (PLG-2026040001)
ent_classstringPLG, ENV, SVC, ORD, AFL, EDU
ent_product_namestringLinked product name
ent_statusstringactive, suspended, expired, cancelled
ent_organization_idintOwning organization
ent_companystringmiddag_br or middag_global
ent_expires_atstringExpiration date (ISO 8601)
ent_quote_idintOriginating quote
ent_auto_createdboolAuto-provisioned from quote

Relationships

Entitlements serve as the universal foreign key linking all downstream entities:

Organization (1) --> (*) Collaborator
Organization (1) --> (*) Entitlement
Entitlement  (1) --> (*) License       [class=PLG]
Entitlement  (1) --> (*) Environment   [class=ENV]
Entitlement  (1) --> (*) Service       [class=SVC]
Entitlement  (1) --> (*) Contract
Service      (1) --> (*) Ticket
Environment  (1) --> (*) Ticket
Quote        (1) --> (1) Order
Order        (1) --> (*) Invoice
Order        (1) --> (*) TaxInvoice

Dual-Repository Toggle

The middag_migration_complete option switches between repository implementations:

Option ValueRepository UsedStorage
falseCct{Name}RepositoryJetEngine CCT tables
true{Name}Repositorywp_posts + meta

Both implementations satisfy the same {Name}RepositoryInterface defined in src/Domain/. The DI container binds the active implementation at boot time based on the toggle value.

php
// Domain code is unaware of storage backend
interface EntitlementRepositoryInterface {
    public function findById(int $id): ?EntitlementEntity;
    public function listByOrganization(int $orgId, int $perPage, int $page): array;
}