shopware / shopware/shopware

[Business Events] inventory: add business events

Open
#17,576 0 comments 0 reactions 0 assignees View on GitHub
domain/inventory
Dominant language
PHP
Stars
3.4k
Forks
1.2k
Avg merge
3d 55m
Merged PRs (30d)
436

Description

### User story

Catalog, stock, pricing and feed integrations have no first-class signal for what changed
in the product catalog. The only triggers available today are the generic
`product.written` / `product_price.written` webhooks, whose payload is `entity` +
`operation` + `primaryKey` — so to learn a product's name, stock level, price, availability
or visibility, a consumer must issue a follow-up API call on every write. There is also no
distinct signal for the moments that matter: a stock crossing zero, a product going live,
a price change.

This issue adds named `inventory` business events with rich payloads for those moments:
product lifecycle (create / update / delete), stock and availability transitions (stock
changed, out of / back in stock), publish state (`active` flipping on/off),
visibility / sales-channel assignment, and advanced-price changes. Each fires from every
write path — admin, Sync API and import — so ERP stock sync, low-stock alerts,
"notify when back in stock" signups and repricing/feed jobs can react straight from the
event payload without a fetch.

## Events to add

| Event | Fires when | Payload |
|-------|------------|---------|
| `inventory.product.created` | A product is created on any path | productId, + full product |
| `inventory.product.updated` | A product or its translations change | productId, changedFields, + full product |
| `inventory.product.deleted` | A product is deleted | productId, productNumber, deletedAt |
| `product.stock.changed` | A product's stock changes (order-driven or direct write) | productId, stock change (delta / new value) |
| `product.out_of_stock` | A product becomes unavailable | productId, available=false |
| `product.back_in_stock` | A product becomes available again | productId, available=true |
| `product.published` | A product's `active` flag flips on | productId, active=true |
| `product.unpublished` | A product's `active` flag flips off | productId, active=false |
| `product.visibility.changed` | A product's sales-channel visibility assignment changes | productId, salesChannelId, visibility |
| `product_price.changed` | A product (advanced) price is created or changed | productId, price, currencyId, ruleId, quantityStart |
| `product_price.deleted` | A product price is removed | productId, ruleId, deletedAt |

`product.out_of_stock` / `product.back_in_stock` fire only for **closeout-managed**
products — non-closeout products are always "available" regardless of stock.

### Acceptance criteria

-

### Definition of Done

- [ ] Fulfills all acceptance criteria defined during discovery.
- [ ] Integration/E2E testing in staging is done.
- [ ] All integration/E2E/unit tests passing; all critical or high-priority bugs are resolved.
- [ ] Fulfills compliance, performance, security, and cloud-readiness needs.
- [ ] Observability—includes monitoring, alerting, and logging; incident response handbooks updated.
- [ ] Documentation—developer docs are written or updated, including information on how the feature or change is adopted and tested. If new functionality, end user documentation is written or updated.
- [ ] (conditional) All new API endpoints have a defined API schema.
- [ ] (conditional) If the change affects the Storefront, it has been tested in the latest three versions of Firefox, Chrome, Edge, IE11, and Safari, as well as the different viewports and devices (Desktop / Tablet / Mobile).
- [ ] (conditional) If the change affects the Administration, it has been tested in current versions of Firefox, Chrome, and Edge.
- [ ] (conditional) Functionality that includes new API routes are callable via the Store-API (/store-api/[version]/).
- [ ] (conditional) If a new Admin module is created, the access control layer is provided, and permissions can be managed via the Users & Permissions module.
- [ ] (conditional) If a new UI input field or interactive element is introduced, the ACL wrapper is added.
- [ ] (conditional) Performance testing done if the change has a high performance impact, such as affecting scalability, load balancing, or query optimization.

Contributor guide

Open the contributing guide

Research direction

Start by defining the missing acceptance criteria for the listed inventory events and tracing the admin, Sync API, import, and order-driven write paths. Establish integration, E2E, and unit tests for each event, including closeout availability transitions; done means all listed payloads and firing conditions work across every named path and the documentation is updated.

Written by the indexing model from the issue text.

Assessment

Tech stack
php
Domain
api, backend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.