Skip to content

feat(core): cascade or document product soft-delete → seller offer soft-delete #1575

Closed

Description

@gregbarajas

Environment

  • Mercur 2.3.5: @mercurjs/core@2.3.5, @mercurjs/admin@2.3.5, @mercurjs/vendor@2.3.5
  • Medusa 2.20.1 (@medusajs/core-flows)
  • Confirmed from published npm .medusa/server (not a downstream fork of core workflows)

Problem / current behavior

Mercur models Product ≠ Offer. Soft-deleting a catalog product does not soft-delete or deactivate seller offers that point at it:

  • Admin DELETE /admin/products/:id soft-deletes the product (and variants) immediately.
  • Vendor DELETE /vendor/products/:id only stages PRODUCT_DELETE; after operator confirm the product is soft-deleted the same way.
  • Neither path cleans offers. Admin Offers (/dashboard/offers) then shows blank orphan rows (offer still live, product gone).
  • Discovery already listens to product.deleted / product.product.deleted for re-index, but core does not clean offers on those events.
  • Offer events include offer.deleted with { id, product_id } — useful after cleanup, not a substitute for product→offer cascade.

Marketplaces must invent a subscriber themselves or live with orphan Admin Offers UI.

Proposed solution / API

Pick one (or both) of:

  1. Cascade / built-in side effect: When a product is soft-deleted (admin direct or confirmed vendor PRODUCT_DELETE), soft-delete (or officially deactivate) seller offers for that product_id via the same path as deleteOffersWorkflow (@mercurjs/core/workflows), emitting offer.deleted.
  2. Documented extension hook: Export/document a recommended subscriber or workflow hook (event names, payload shape, “resolve offer ids by product_id → deleteOffersWorkflow”) so marketplaces do not rediscover orphan Offers rows. Vendor confirm path must be covered the same as admin delete.

Empty offer list should be a no-op. Batching for many offers is fine. Failures should not leave the product delete half-applied without logging.

Why it matters

Operators soft-delete catalog products expecting listings to disappear. Orphan offers break Admin Offers, confuse moderation, and leave storefront/discovery edges inconsistent until someone hand-deletes each offer.

Affected apps

  • Core / API product delete workflows (admin + vendor PRODUCT_DELETE confirm)
  • Admin Offers list / product delete UX
  • Vendor product delete → operator confirm path (same end state)

Suggested implementation notes

Piece Location / contract
Admin delete @mercurjs/core api/admin/products/[id]/route.js → deleteProductsWorkflow
Vendor delete DELETE /vendor/products/{id} — stages PRODUCT_DELETE only
Offer delete workflow deleteOffersWorkflow — input { ids[] }; hooks offersDeleted; emits offer.deleted
Events already used downstream product.deleted, product.product.deleted (discovery bridges)
Grams workaround Subscriber cleanup-offers-on-product-deleted + cleanupOffersForDeletedProducts (packages/api) — on those product delete events, query offers by product_id, batch deleteOffersWorkflow.

Related existing GitHub issues

None known that ask for product soft-delete → offer cascade or an official cleanup hook. Re-scan before filing.

Acceptance criteria

  • Soft-deleting a product that has seller offers removes/deactivates those offers (Admin Offers no longer shows blank orphans)
  • Same behavior for admin direct delete and confirmed vendor PRODUCT_DELETE
  • Zero offers → no-op; many offers → batched / resilient
  • Docs describe cascade or the recommended subscriber/workflow hook (event names + deleteOffersWorkflow)
  • offer.deleted still fires so discovery / integrations can react

Activity

  1. added a commit that references this issue on Sep 28, 2026
    db0385c
  2. added a commit that references this issue on Oct 3, 2026
    721ae0d
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions