Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message
vendra-product-development
vendra-product-development
misaf/vendra
claude-code
translatable
multi-tenancy
pest-testing
filament
eloquent
plan-limits
composer

Create, modify, review, or test the Vendra Product package in packages/vendra-product. Use for Product, ProductCategory, ProductPrice, ProductPurchaseQuoter, DeductProductStockAction, RestockProductsAction, translated catalog data, media and optional product tags, observers, migrations, factories, seeders, policies, Filament resources, configuration, translations, package wiring, and the vendra-product-api boundary.

Install
php artisan boost:add-skill misaf/vendra

Save this content to: .claude/skills/vendra-product-development/SKILL.md

# Vendra Product

## Workflow

- Inspect `composer.json`, sibling files, and existing tests before changing the package.
- Use Laravel Boost `application-info` and `search-docs` before code changes.
- Apply `laravel-best-practices` to Laravel PHP and `pest-testing` whenever tests change.
- Apply `tailwindcss-development` only when changing Blade markup or Tailwind classes.
- Keep changes inside this package's boundary and preserve its public contracts.
- Add or update focused Pest coverage, then run `php artisan test --compact --testsuite=vendra-product` and `composer stan`.

## Translatable Persistence

- Making a persisted model field translatable is an explicit domain choice unless this package already requires it.
- Every field listed in a model's `$translatable` array must definitely use a JSON database column. Keep its model traits/casts, factories, validation, Filament locale UI, API serialization, and tests translation-aware.
- A field not listed in `$translatable` must use the appropriate scalar database type and must not use Spatie Translatable, translatable slug traits, locale switchers, translated callbacks, or translation-shaped array data.

## Vendra Transitive API Policy

- Treat a Vendra dependency intentionally exposed through the public API of a directly required Vendra platform package as part of the supported public contract of that package.
- Do not add a redundant direct Composer requirement solely because source code imports a type from that exposed dependency.
- Apply this only to Vendra platform packages listed under `require`; never extend it to `require-dev`, `suggest`, incidental implementation dependencies, or third-party packages. Removing or replacing an exposed dependency is a breaking change; keep `self.version` alignment across the Vendra package graph.

- Register every table whose migration calls `TenantSchema::addTenantColumn()` with `TenantTableRegistry` in this package's service provider, preserving configured table names and connections, so `vendra-tenant:enable {tenant}` can retrofit schemas migrated before tenancy was enabled.
- Creating a product counts against the store plan's `PlanLimit::ProductsPerStore`: the provider registers the `TenantUsageRegistry` counter, `ProductLifecycleObserver::creating` refuses a product past the limit on every path, `CreateProduct` shows the refusal as a notification, and `Actions\Concerns\DisablesAtProductLimit` disables `CreateProductPageAction` and `DuplicateProductTableAction` with the refusal as a tooltip at the cap. `ProductLifecycleObserver::created()` reports each add with `recordAdded()`.

## Module Boundary

Treat `packages/vendra-product` as the source of product domain behavior and Filament admin UI.

- Use namespace `Misaf\VendraProduct`.
- Keep domain models, factories, seeders, policies, observers, console commands, Filament classes, config, migrations, translations, and tests inside this module.
- Do not place product domain code in the host app unless the host app is only integrating the module.
- Keep API serialization and API Platform route behavior out of this module; use `vendra-product-api` for that.
- Purchase eligibility and catalog pricing live in `Services\ProductPurchaseQuoter`, which batches its product query and returns typed `ProductPurchaseQuote` results or `ProductPurchaseRefusalEnum` cases. It charges the newest price row in the currency; prices are append-only history. It must not import cart, order, or API types.
- Stock moves only through `Actions\DeductProductStockAction` (locked in id order, all or nothing, `InsufficientProductStockException`, `in_stock` off with the last unit; restocking never turns it back on) and `Actions\RestockProductsAction`.
- Product duplication lives entirely in `Actions\DuplicateProductAction` (unique copy names and slugs per tenant, prices, media, attribute selections, tags); the Filament table action only delegates to it.
- Keep cross-module dependencies explicit in `composer.json`; do not introduce a dependency without approval.
- Tag-consuming models must use `Misaf\VendraSupport\Capabilities\HasOptionalTags` as the single source of their `tags()` relationship and pivot metadata. Keep the package tag-agnostic: define a stable package-owned tag type, use `TagIntegration` for availability and UI integration, never import the concrete Vendra Tagger model/provider or define the relationship through Spatie `HasTags`, and list Tagger only under Composer `suggest`.

## Domain Model Standards

Follow the existing `Product` and `ProductCategory` patterns for new product entities.

- Use `declare(strict_types=1)`, final classes, typed method signatures, and PHPDoc generics for relationships.
- Follow Laravel comment style: document with PHPDoc (array shapes, generics, `@see`) and reserve inline comments for genuinely complex logic. Match the surrounding file's density and do not add comments that restate the code.
- Prefer the Laravel attributes already used here, such as `#[Fillable]`, `#[Hidden]`, `#[UseFactory]`, and `#[ObservedBy]`.
- Keep the module tenant-agnostic: derive tenant awareness purely from the bound `TenantResolver` in `misaf/vendra-support` (`TenantAwareness`, `BelongsToTenant`, `TenantSchema`, `RequiresCurrentTenant`). The module must build and run whether or not a tenant provider is installed, so never reference a concrete provider such as `Misaf\VendraTenant` anywhere — models, migrations, factories, seeders, or fixtures. There is no `tenant_aware` config toggle.
- Hide `tenant_id` and keep tenant behavior centralized in the support layer; do not duplicate tenant scoping or `tenant_id` assignment in models, Filament resources, factories, or seeders. `BelongsToTenant` assigns `tenant_id` on `creating` from the current tenant.
- Reuse only the traits and conventions present on the affected sibling model; do not infer translations, media, slugs, sorting, or soft deletes from another package.

## Filament Standards

Keep every resource that declares a `$cluster`, including its complete supporting tree, under `src/Filament/Clusters/Resources/` with the matching `Misaf\VendraProduct\Filament\Clusters\Resources` namespace and plugin discovery path. Resources without a cluster belong under `src/Filament/Resources/`.

- Register module UI through the module `Plugin` and `ServiceProvider`; do not manually wire resources in unrelated panel providers.
- Keep resource classes thin. Delegate form schemas to `Schemas/*Form.php` and table configuration to `Tables/*Table.php`.
- Use Filament v5 namespaces: form fields from `Filament\Forms\Components`, layout from `Filament\Schemas\Components`, table columns from `Filament\Tables\Columns`, filters from `Filament\Tables\Filters`, actions from `Filament\Actions`, and icons from `Filament\Support\Icons\Heroicon`.
- Use this module's translation keys (`vendra-product::attributes`, `vendra-product::navigation`) for labels, breadcrumbs, and navigation.
- Keep cluster resources ungrouped and assign `$navigationSort` from their package-specific `NavigationPriority` cases; never hardcode numeric resource sort values.
- Provide separate singular and plural resource labels in `en`, `de`, and `fa`: model labels use the singular key, while navigation and plural model labels use the plural key. Keep navigation labels at 24 characters or fewer.
- Prevent N+1 issues in tables and relation managers with eager loading, `withCount`, or computed state based on loaded relationships.
- Use public media visibility only when public access is actually required.

## Permissions And Navigation

Use policy enums and policies as the permission source.

- Add enum cases for every resource action the panel exposes.
- Keep policy method names aligned with Filament actions: `viewAny`, `view`, `create`, `update`, `delete`, `deleteAny`, `restore`, `restoreAny`, `forceDelete`, `forceDeleteAny`, `replicate`, and `reorder` as applicable.
- Update `PermissionPolicySeeder` when new permissions are introduced.
- Keep navigation labels and groups configurable through the module `Plugin` and `config/vendra-product.php`. Do not add a `tenant_aware` config value; tenant awareness derives from the bound `TenantResolver`.

## Data And Localization

Migrations, factories, seeders, and translation files are part of the contract.

- Use package migrations in `database/migrations`, with stubs only when the install flow expects publishing.
- Use factories under `database/factories` and seeders under `database/seeders`. Keep them tenant-safe: import no concrete tenant provider and set no `tenant_id` directly; let `BelongsToTenant` assign it from the current tenant so they work with tenancy on or off.
- Keep demo fixtures deterministic and tenant-safe.
- Update all supported locales together and keep translation keys sorted.
- Preserve translation key parity tests when adding labels or attributes.

## Testing And Verification

Prefer focused Pest tests in the module.

- Keep tests purposeful and prevent unnecessary ones: cover behavior, contracts, and edge cases — not framework internals or trivially typed code. Do not duplicate coverage a focused test already proves, and do not add throwaway verification scripts (or `tinker`) when a test fits.
- Keep an architecture expectation proving Product does not use Vendra Tagger or Spatie Tags directly. Test both the unavailable fallback and the support-resolved polymorphic relation.
- Add or update unit tests for model contracts, policy permission coverage, resolver-derived tenant awareness, navigation/config behavior, and translation parity.
- Keep Pest architecture tests in `tests/ArchTest.php`: the `php`, `security`, and `laravel` presets, plus an expectation that the module stays tenant-agnostic, e.g. `arch()->expect('Misaf\VendraProduct')->not->toUse('Misaf\VendraTenant')`.
- Add feature or Livewire tests when changing Filament behavior with meaningful user-visible effects.
- Run checks from the host app: `php artisan test --compact --testsuite=vendra-product` and `composer stan`.
- If PHP files changed, run Pint for the touched code: `vendor/bin/pint --dirty --format agent` from the host app.

- Demo seeders declare their factory dependencies in `FACTORIES`; the shared base uses bundled fixtures when any declared factory is unavailable, including standalone Composer installs. Keep factories in development autoloading.

- `Support\ProductStockRestorer` binds `Misaf\VendraSupport\Contracts\StockRestorer`, supplies Product’s morph alias, and delegates restoration to `RestockProductsAction`. It preserves tenant scoping, restores soft-deleted products, and leaves `in_stock` unchanged. Product imports no Order or Order API types.

Vendra Product

Workflow

  • Inspect composer.json, sibling files, and existing tests before changing the package.
  • Use Laravel Boost application-info and search-docs before code changes.
  • Apply laravel-best-practices to Laravel PHP and pest-testing whenever tests change.
  • Apply tailwindcss-development only when changing Blade markup or Tailwind classes.
  • Keep changes inside this package's boundary and preserve its public contracts.
  • Add or update focused Pest coverage, then run php artisan test --compact --testsuite=vendra-product and composer stan.

Translatable Persistence

  • Making a persisted model field translatable is an explicit domain choice unless this package already requires it.
  • Every field listed in a model's $translatable array must definitely use a JSON database column. Keep its model traits/casts, factories, validation, Filament locale UI, API serialization, and tests translation-aware.
  • A field not listed in $translatable must use the appropriate scalar database type and must not use Spatie Translatable, translatable slug traits, locale switchers, translated callbacks, or translation-shaped array data.

Vendra Transitive API Policy

  • Treat a Vendra dependency intentionally exposed through the public API of a directly required Vendra platform package as part of the supported public contract of that package.

  • Do not add a redundant direct Composer requirement solely because source code imports a type from that exposed dependency.

  • Apply this only to Vendra platform packages listed under require; never extend it to require-dev, suggest, incidental implementation dependencies, or third-party packages. Removing or replacing an exposed dependency is a breaking change; keep self.version alignment across the Vendra package graph.

  • Register every table whose migration calls TenantSchema::addTenantColumn() with TenantTableRegistry in this package's service provider, preserving configured table names and connections, so vendra-tenant:enable {tenant} can retrofit schemas migrated before tenancy was enabled.

  • Creating a product counts against the store plan's PlanLimit::ProductsPerStore: the provider registers the TenantUsageRegistry counter, ProductLifecycleObserver::creating refuses a product past the limit on every path, CreateProduct shows the refusal as a notification, and Actions\Concerns\DisablesAtProductLimit disables CreateProductPageAction and DuplicateProductTableAction with the refusal as a tooltip at the cap. ProductLifecycleObserver::created() reports each add with recordAdded().

Module Boundary

Treat packages/vendra-product as the source of product domain behavior and Filament admin UI.

  • Use namespace Misaf\VendraProduct.
  • Keep domain models, factories, seeders, policies, observers, console commands, Filament classes, config, migrations, translations, and tests inside this module.
  • Do not place product domain code in the host app unless the host app is only integrating the module.
  • Keep API serialization and API Platform route behavior out of this module; use vendra-product-api for that.
  • Purchase eligibility and catalog pricing live in Services\ProductPurchaseQuoter, which batches its product query and returns typed ProductPurchaseQuote results or ProductPurchaseRefusalEnum cases. It charges the newest price row in the currency; prices are append-only history. It must not import cart, order, or API types.
  • Stock moves only through Actions\DeductProductStockAction (locked in id order, all or nothing, InsufficientProductStockException, in_stock off with the last unit; restocking never turns it back on) and Actions\RestockProductsAction.
  • Product duplication lives entirely in Actions\DuplicateProductAction (unique copy names and slugs per tenant, prices, media, attribute selections, tags); the Filament table action only delegates to it.
  • Keep cross-module dependencies explicit in composer.json; do not introduce a dependency without approval.
  • Tag-consuming models must use Misaf\VendraSupport\Capabilities\HasOptionalTags as the single source of their tags() relationship and pivot metadata. Keep the package tag-agnostic: define a stable package-owned tag type, use TagIntegration for availability and UI integration, never import the concrete Vendra Tagger model/provider or define the relationship through Spatie HasTags, and list Tagger only under Composer suggest.

Domain Model Standards

Follow the existing Product and ProductCategory patterns for new product entities.

  • Use declare(strict_types=1), final classes, typed method signatures, and PHPDoc generics for relationships.
  • Follow Laravel comment style: document with PHPDoc (array shapes, generics, @see) and reserve inline comments for genuinely complex logic. Match the surrounding file's density and do not add comments that restate the code.
  • Prefer the Laravel attributes already used here, such as #[Fillable], #[Hidden], #[UseFactory], and #[ObservedBy].
  • Keep the module tenant-agnostic: derive tenant awareness purely from the bound TenantResolver in misaf/vendra-support (TenantAwareness, BelongsToTenant, TenantSchema, RequiresCurrentTenant). The module must build and run whether or not a tenant provider is installed, so never reference a concrete provider such as Misaf\VendraTenant anywhere — models, migrations, factories, seeders, or fixtures. There is no tenant_aware config toggle.
  • Hide tenant_id and keep tenant behavior centralized in the support layer; do not duplicate tenant scoping or tenant_id assignment in models, Filament resources, factories, or seeders. BelongsToTenant assigns tenant_id on creating from the current tenant.
  • Reuse only the traits and conventions present on the affected sibling model; do not infer translations, media, slugs, sorting, or soft deletes from another package.

Filament Standards

Keep every resource that declares a $cluster, including its complete supporting tree, under src/Filament/Clusters/Resources/ with the matching Misaf\VendraProduct\Filament\Clusters\Resources namespace and plugin discovery path. Resources without a cluster belong under src/Filament/Resources/.

  • Register module UI through the module Plugin and ServiceProvider; do not manually wire resources in unrelated panel providers.
  • Keep resource classes thin. Delegate form schemas to Schemas/*Form.php and table configuration to Tables/*Table.php.
  • Use Filament v5 namespaces: form fields from Filament\Forms\Components, layout from Filament\Schemas\Components, table columns from Filament\Tables\Columns, filters from Filament\Tables\Filters, actions from Filament\Actions, and icons from Filament\Support\Icons\Heroicon.
  • Use this module's translation keys (vendra-product::attributes, vendra-product::navigation) for labels, breadcrumbs, and navigation.
  • Keep cluster resources ungrouped and assign $navigationSort from their package-specific NavigationPriority cases; never hardcode numeric resource sort values.
  • Provide separate singular and plural resource labels in en, de, and fa: model labels use the singular key, while navigation and plural model labels use the plural key. Keep navigation labels at 24 characters or fewer.
  • Prevent N+1 issues in tables and relation managers with eager loading, withCount, or computed state based on loaded relationships.
  • Use public media visibility only when public access is actually required.

Permissions And Navigation

Use policy enums and policies as the permission source.

  • Add enum cases for every resource action the panel exposes.
  • Keep policy method names aligned with Filament actions: viewAny, view, create, update, delete, deleteAny, restore, restoreAny, forceDelete, forceDeleteAny, replicate, and reorder as applicable.
  • Update PermissionPolicySeeder when new permissions are introduced.
  • Keep navigation labels and groups configurable through the module Plugin and config/vendra-product.php. Do not add a tenant_aware config value; tenant awareness derives from the bound TenantResolver.

Data And Localization

Migrations, factories, seeders, and translation files are part of the contract.

  • Use package migrations in database/migrations, with stubs only when the install flow expects publishing.
  • Use factories under database/factories and seeders under database/seeders. Keep them tenant-safe: import no concrete tenant provider and set no tenant_id directly; let BelongsToTenant assign it from the current tenant so they work with tenancy on or off.
  • Keep demo fixtures deterministic and tenant-safe.
  • Update all supported locales together and keep translation keys sorted.
  • Preserve translation key parity tests when adding labels or attributes.

Testing And Verification

Prefer focused Pest tests in the module.

  • Keep tests purposeful and prevent unnecessary ones: cover behavior, contracts, and edge cases — not framework internals or trivially typed code. Do not duplicate coverage a focused test already proves, and do not add throwaway verification scripts (or tinker) when a test fits.

  • Keep an architecture expectation proving Product does not use Vendra Tagger or Spatie Tags directly. Test both the unavailable fallback and the support-resolved polymorphic relation.

  • Add or update unit tests for model contracts, policy permission coverage, resolver-derived tenant awareness, navigation/config behavior, and translation parity.

  • Keep Pest architecture tests in tests/ArchTest.php: the php, security, and laravel presets, plus an expectation that the module stays tenant-agnostic, e.g. arch()->expect('Misaf\VendraProduct')->not->toUse('Misaf\VendraTenant').

  • Add feature or Livewire tests when changing Filament behavior with meaningful user-visible effects.

  • Run checks from the host app: php artisan test --compact --testsuite=vendra-product and composer stan.

  • If PHP files changed, run Pint for the touched code: vendor/bin/pint --dirty --format agent from the host app.

  • Demo seeders declare their factory dependencies in FACTORIES; the shared base uses bundled fixtures when any declared factory is unavailable, including standalone Composer installs. Keep factories in development autoloading.

  • Support\ProductStockRestorer binds Misaf\VendraSupport\Contracts\StockRestorer, supplies Product’s morph alias, and delegates restoration to RestockProductsAction. It preserves tenant scoping, restores soft-deleted products, and leaves in_stock unchanged. Product imports no Order or Order API types.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console