🎉 New Features
Shopify Admin & Customer Portal
- Purchase options are now editable from the Shopify product admin A new product admin extension brings Submarine purchase options directly into the Shopify product page, so merchants can review and adjust selling plans without leaving Shopify.
- Customer portal and order status page refinements A round of usability improvements to the customer portal, including corrected gating logic so the Submarine card shows on the order status page only when it should.
🐛 Bug Fixes
- Cancelled subscriptions no longer receive upcoming order notifications Notification schedules are now reconciled by trigger rather than by count, which stops cancelled subscriptions receiving upcoming order emails and stops duplicate notifications firing after a timing change.
- Subscription exports show the correct state name Province names are now updated alongside province codes when a delivery address changes, so exports no longer carry a stale state name from a previous address.
- Subscription orders no longer get stuck in processing Order preprocessing now catches every error class, resets the order status and raises an alert, and payment status is only marked as submitted once processing has succeeded.
- Uploaded purchase orders respect the fulfil date as entered End date and fulfil date are now read directly from the uploaded file rather than derived from one another, so campaign dates match what the merchant supplied.
🔧 Technical Updates
- Framework and Shopify API upgrades The presales platform has moved to Rails 7.1 and the latest Shopify app and API libraries, pinned to the 2026-04 API version, keeping us current with Shopify's supported versions.
- Groundwork for product discount syncing Shopify discount syncing now covers all discount and code types and carries customer segment, collection and variant eligibility through to Pricing, with bulk backfill for existing stores and new merchant onboarding.
- Customer segment lookups now use internal identifiers Core's customer segment membership query and the Pricing client that calls it now exchange internal IDs, removing a source of mismatch between services.
⚠️ Breaking Changes
- Nil