chore: add IDE helper annotations to Eloquent models

Add @property, @property-read, @method, and @mixin PHPDoc annotations
to the seven core Eloquent models for IDE autocompletion support.

Models annotated:
- Workspace: all columns, relationships, scopes (active, ordered)
- User: all columns, relationships, factory
- WorkspaceMember: relationship props, scope methods (forWorkspace, forUser, withRole, inTeam, owners)
- WorkspaceInvitation: all columns, relationships, scopes (pending, expired, accepted)
- Namespace_: all columns, relationships, scopes (active, ordered, ownedByUser, ownedByWorkspace, accessibleBy)
- Package: all columns, relationships, scopes (active, public, base, addons, purchasable, free, ordered)
- Feature: all columns, relationships, scopes (active, inCategory, root)

Fixes #31

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claude 2026-03-24 13:55:08 +00:00
parent c51e4310b1
commit 126d454bba
No known key found for this signature in database
GPG key ID: AF404715446AEB41
7 changed files with 238 additions and 4 deletions

View file

@ -10,6 +10,35 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
/**
* Feature model - entitlement feature definition (e.g. social.accounts, bio.pages).
*
* @property int $id
* @property string $code
* @property string $name
* @property string|null $description
* @property string|null $category
* @property string $type
* @property string $reset_type
* @property int|null $rolling_window_days
* @property int|null $parent_feature_id
* @property int $sort_order
* @property bool $is_active
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property-read \Illuminate\Database\Eloquent\Collection<int, Package> $packages
* @property-read Feature|null $parent
* @property-read \Illuminate\Database\Eloquent\Collection<int, Feature> $children
*
* @method static \Illuminate\Database\Eloquent\Builder<static>|Feature active()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Feature inCategory(string $category)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Feature root()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Feature newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Feature newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Feature query()
*
* @mixin \Eloquent
*/
class Feature extends Model
{
use HasFactory;

View file

@ -19,10 +19,40 @@ use Illuminate\Support\Str;
* a namespace rather than directly to User/Workspace. The namespace itself
* has polymorphic ownership (User or Workspace can own).
*
* Ownership patterns:
* - Individual user: User Namespace Products
* - Agency: Workspace Namespace(s) Products (one per client)
* - Team member: User in Workspace access to Workspace's Namespaces
* @property int $id
* @property string $uuid
* @property string $name
* @property string $slug
* @property string|null $description
* @property string $icon
* @property string $color
* @property string $owner_type
* @property int $owner_id
* @property int|null $workspace_id
* @property array|null $settings
* @property bool $is_default
* @property bool $is_active
* @property int $sort_order
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property \Illuminate\Support\Carbon|null $deleted_at
* @property-read User|Workspace $owner
* @property-read Workspace|null $workspace
* @property-read \Illuminate\Database\Eloquent\Collection<int, NamespacePackage> $namespacePackages
* @property-read \Illuminate\Database\Eloquent\Collection<int, Boost> $boosts
* @property-read \Illuminate\Database\Eloquent\Collection<int, UsageRecord> $usageRecords
* @property-read \Illuminate\Database\Eloquent\Collection<int, EntitlementLog> $entitlementLogs
*
* @method static \Illuminate\Database\Eloquent\Builder<static>|Namespace_ active()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Namespace_ ordered()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Namespace_ ownedByUser(User|int $user)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Namespace_ ownedByWorkspace(Workspace|int $workspace)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Namespace_ accessibleBy(User $user)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Namespace_ newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Namespace_ newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Namespace_ query()
*
* @mixin \Eloquent
*/
class Namespace_ extends Model
{

View file

@ -9,6 +9,47 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
/**
* Package model - entitlement package definition (e.g. Free, Creator, Agency).
*
* @property int $id
* @property string $code
* @property string $name
* @property string|null $description
* @property string|null $icon
* @property string|null $color
* @property int $sort_order
* @property bool $is_stackable
* @property bool $is_base_package
* @property bool $is_active
* @property bool $is_public
* @property string|null $blesta_package_id
* @property float|null $monthly_price
* @property float|null $yearly_price
* @property float $setup_fee
* @property int $trial_days
* @property string|null $stripe_price_id_monthly
* @property string|null $stripe_price_id_yearly
* @property string|null $btcpay_price_id_monthly
* @property string|null $btcpay_price_id_yearly
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property-read \Illuminate\Database\Eloquent\Collection<int, Feature> $features
* @property-read \Illuminate\Database\Eloquent\Collection<int, WorkspacePackage> $workspacePackages
*
* @method static \Illuminate\Database\Eloquent\Builder<static>|Package active()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Package public()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Package base()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Package addons()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Package purchasable()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Package free()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Package ordered()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Package newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Package newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Package query()
*
* @mixin \Eloquent
*/
class Package extends Model
{
use HasFactory;

View file

@ -18,6 +18,39 @@ use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Pennant\Concerns\HasFeatures;
/**
* User model - authenticatable tenant user.
*
* @property int $id
* @property string $name
* @property string $email
* @property \Illuminate\Support\Carbon|null $email_verified_at
* @property string $password
* @property string|null $remember_token
* @property \Core\Tenant\Enums\UserTier $tier
* @property \Illuminate\Support\Carbon|null $tier_expires_at
* @property int|null $referred_by
* @property int $referral_count
* @property \Illuminate\Support\Carbon|null $referral_activated_at
* @property array|null $cached_stats
* @property \Illuminate\Support\Carbon|null $stats_computed_at
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property-read \Illuminate\Database\Eloquent\Collection<int, Workspace> $workspaces
* @property-read \Illuminate\Database\Eloquent\Collection<int, Workspace> $ownedWorkspaces
* @property-read \Illuminate\Database\Eloquent\Collection<int, Namespace_> $namespaces
* @property-read \Illuminate\Database\Eloquent\Collection<int, Boost> $boosts
* @property-read User|null $referrer
* @property-read \Illuminate\Database\Eloquent\Collection<int, User> $referrals
* @property-read \Illuminate\Notifications\DatabaseNotificationCollection<int, \Illuminate\Notifications\DatabaseNotification> $notifications
*
* @method static \Illuminate\Database\Eloquent\Builder<static>|User newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|User newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|User query()
* @method static \Core\Tenant\Database\Factories\UserFactory factory($count = null, $state = [])
*
* @mixin \Eloquent
*/
class User extends Authenticatable implements MustVerifyEmail
{
use HasFactory, HasFeatures, Notifiable;

View file

@ -50,6 +50,65 @@ use Mod\Commerce\Models\Order;
use Mod\Commerce\Models\PaymentMethod;
use Mod\Commerce\Models\Subscription;
/**
* Workspace model - the core tenant boundary.
*
* @property int $id
* @property string $name
* @property string $slug
* @property string|null $domain
* @property string|null $icon
* @property string|null $color
* @property string|null $description
* @property string $type
* @property array|null $settings
* @property bool $is_active
* @property int $sort_order
* @property bool $wp_connector_enabled
* @property string|null $wp_connector_url
* @property string|null $wp_connector_secret
* @property \Illuminate\Support\Carbon|null $wp_connector_verified_at
* @property \Illuminate\Support\Carbon|null $wp_connector_last_sync
* @property array|null $wp_connector_config
* @property string|null $stripe_customer_id
* @property string|null $btcpay_customer_id
* @property string|null $billing_name
* @property string|null $billing_email
* @property string|null $billing_address_line1
* @property string|null $billing_address_line2
* @property string|null $billing_city
* @property string|null $billing_state
* @property string|null $billing_postal_code
* @property string|null $billing_country
* @property string|null $vat_number
* @property string|null $tax_id
* @property bool $tax_exempt
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property-read string $cms_url
* @property-read string $wp_connector_webhook_url
* @property-read \Illuminate\Database\Eloquent\Collection<int, User> $users
* @property-read \Illuminate\Database\Eloquent\Collection<int, WorkspaceMember> $members
* @property-read \Illuminate\Database\Eloquent\Collection<int, WorkspaceTeam> $teams
* @property-read \Illuminate\Database\Eloquent\Collection<int, WorkspacePackage> $workspacePackages
* @property-read \Illuminate\Database\Eloquent\Collection<int, WorkspaceInvitation> $invitations
* @property-read \Illuminate\Database\Eloquent\Collection<int, Namespace_> $namespaces
* @property-read \Illuminate\Database\Eloquent\Collection<int, Package> $packages
* @property-read \Illuminate\Database\Eloquent\Collection<int, Boost> $boosts
* @property-read \Illuminate\Database\Eloquent\Collection<int, UsageRecord> $usageRecords
* @property-read \Illuminate\Database\Eloquent\Collection<int, EntitlementLog> $entitlementLogs
* @property-read \Illuminate\Database\Eloquent\Collection<int, UsageAlertHistory> $usageAlerts
* @property-read \Illuminate\Database\Eloquent\Collection<int, EntitlementWebhook> $entitlementWebhooks
*
* @method static \Illuminate\Database\Eloquent\Builder<static>|Workspace active()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Workspace ordered()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Workspace newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Workspace newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Workspace query()
* @method static \Core\Tenant\Database\Factories\WorkspaceFactory factory($count = null, $state = [])
*
* @mixin \Eloquent
*/
class Workspace extends Model
{
use HasFactory;

View file

@ -12,6 +12,33 @@ use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
/**
* Workspace Invitation - manages invitations to join workspaces.
*
* @property int $id
* @property int $workspace_id
* @property string $email
* @property string $token
* @property string $role
* @property int|null $invited_by
* @property \Illuminate\Support\Carbon $expires_at
* @property \Illuminate\Support\Carbon|null $accepted_at
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property-read Workspace $workspace
* @property-read User|null $inviter
* @property-read \Illuminate\Notifications\DatabaseNotificationCollection<int, \Illuminate\Notifications\DatabaseNotification> $notifications
*
* @method static \Illuminate\Database\Eloquent\Builder<static>|WorkspaceInvitation pending()
* @method static \Illuminate\Database\Eloquent\Builder<static>|WorkspaceInvitation expired()
* @method static \Illuminate\Database\Eloquent\Builder<static>|WorkspaceInvitation accepted()
* @method static \Illuminate\Database\Eloquent\Builder<static>|WorkspaceInvitation newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|WorkspaceInvitation newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|WorkspaceInvitation query()
* @method static \Core\Tenant\Database\Factories\WorkspaceInvitationFactory factory($count = null, $state = [])
*
* @mixin \Eloquent
*/
class WorkspaceInvitation extends Model
{
use HasFactory;

View file

@ -25,6 +25,21 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
* @property int|null $invited_by
* @property Carbon $created_at
* @property Carbon $updated_at
* @property-read User $user
* @property-read Workspace $workspace
* @property-read WorkspaceTeam|null $team
* @property-read User|null $inviter
*
* @method static \Illuminate\Database\Eloquent\Builder<static>|WorkspaceMember forWorkspace(Workspace|int $workspace)
* @method static \Illuminate\Database\Eloquent\Builder<static>|WorkspaceMember forUser(User|int $user)
* @method static \Illuminate\Database\Eloquent\Builder<static>|WorkspaceMember withRole(string $role)
* @method static \Illuminate\Database\Eloquent\Builder<static>|WorkspaceMember inTeam(WorkspaceTeam|int $team)
* @method static \Illuminate\Database\Eloquent\Builder<static>|WorkspaceMember owners()
* @method static \Illuminate\Database\Eloquent\Builder<static>|WorkspaceMember newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|WorkspaceMember newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|WorkspaceMember query()
*
* @mixin \Eloquent
*/
class WorkspaceMember extends Model
{