[5.1.0] - 2026-06-23
- Added fullscreen toggle button to CodeMirror editors: semi-transparent icon in the top-right corner of each editor, also togglable via F11; Esc exits fullscreen. remp/crm#3779
- Fixed wrong the user pairing process in
VerifyPurchaseV2ApiHandler. remp/dn-mofa#625
- BREAKING: Changed
Selection::insert() return type from ActiveRow|array|int|bool to ActiveRow|array|int, matching nette/database 3.2; failed inserts now throw an exception instead of returning false.
- Bumped
nette/database minimum requirement to ^3.2.
- BREAKING: Changed
LoginCredentials::getId() to throw a runtime exception instead of silently returning null; updated return type from mixed to string|int. remp/crm#3793
- Added
default, enabled, and disabled translation keys to all system.* locale files. remp/dn-mofa#627
- Added French Guiana (
GF) to the list of available countries.
- Added support for per-instance local config overlay:
Core::run() now loads config.<APP_ENV>.local.neon when the APP_ENV env var is set, allowing each CRM instance to keep its own local overrides next to the shared instance config. remp/crm#3790
- Fixed
Container::components deprecation, replacing it with getComponents() call.
- Added support for automatic child subscriptions renewals when an on-demand master family subscription is renewed. remp/euobserver#202
- Renewals are now processed asynchronously via a new
renew-ondemand-family-subscriptions Hermes handler.
- Added
UserEventInterface to FamilyRequestAcceptedEvent, exposing the slave user via getUser(). remp/dn-mofa#627
- Fixed family request status not being committed before the new subscription event fires in
DonateSubscription; event handlers reacting to NewSubscriptionEvent now see the accepted request state immediately. remp/dn-mofa#627
- Fixed rounding error in the invoice tax base (price without VAT) total, which could be off by a cent; the per-VAT-rate base is now derived from the gross total instead of summing already-rounded per-item amounts. remp/helpdesk#4661
- Changed
RetentionAnalysis to use a single SQL query with recursive CTE instead of per-user PHP iteration with N+1 queries, improving performance. remp/crm#3552
- Fixed deprecated
league/csv API usage in ExportPaymentsHandler: replaced ByteSequence::BOM_UTF8 with Bom::Utf8->value (deprecated since 9.16.0) and createFromStream() with from() (deprecated since 9.27.0). remp/crm#3771
- Changed
CidGetterDownloader to read config values lazily in download() instead of the constructor to prevent crash on fresh database installs.
- Fixed non-unique index on FK-referenced column
mail_types.code for MySQL 8.4+ compatibility.
- Fixed
payments:charge not refreshing recurrent payment state before processing, preventing stale data issues when webhooks changed payment state during long-running iterations. remp/crm#3773
- Replaced
(boolean) cast with (bool) short form and added missing Exception import in PaymentProcessor.
- Fixed IMAP mail confirmation losing unread emails whose subjects didn’t match: messages were marked as Seen on fetch even when skipped by the PHP-level subject filter. remp/helpdesk#4615
- Fixed recurrent charge-before scheduling being skipped when
recurrent_charge_before is set to 0; the value was previously evaluated as falsy. remp/crm#3766
- Fixed
RecurrentPaymentsResolver::resolveChargeAmount() not applying VAT adjustments when computing the next charge amount. remp/crm#3782
- This caused that
UserPaymentsListing displayed recurrent payments with (incorrect) amount that was different from what would be charged.
- Added
RecurrentPaymentsRepository::recurrentBySubscription() that resolves a subscription’s recurrent payment via data providers. remp/crm#3797, remp/crm#3770
- Fixed type error caused by
RecurrentPaymentsResolver#resolveFailedRecurrent() calling resolveFailedRecurrent(null). remp/crm#3805
- Fixed rounding error in payment-item totals without VAT, which could be off by a cent;
PaymentItemTrait::totalPriceWithoutVAT() and the refund/country-change admin widgets now derive the net amount from the gross total instead of summing already-rounded per-item amounts. remp/helpdesk#4661
- Fixed
payments:charge wrongly stopping a recurrent payment as a fast charge when the user had another, recently charged recurrent payment sharing the same payment method; fast-charge detection is now scoped to the same recurrent payment chain. remp/helpdesk#4665
- Added
CanUserUseStoredCardDataProvider reporting whether the user has a stored card for the payment’s gateway. remp/crm#3678
- Fixed non-unique index on FK-referenced column
distribution_centers.code for MySQL 8.4+ compatibility.
- Fixed products dashboard graph and CSV export showing an empty unlabeled column from non-product payments. remp/crm#3783
- Switched both joins in
DashboardPresenter::createComponentGoogleProductsStatsGraph from LEFT JOIN to INNER JOIN so subscription/donation payments and orphan payment_items rows are filtered out at the SQL level.
- Added product filter (multi-select) to the products admin dashboard, allowing all graphs to be scoped to selected products. remp/crm#3783
- Added address selector to the eshop checkout form allowing users to select from their existing delivery (shop) addresses. remp/crm#3512
- Added
products:cleanup_duplicate_shop_addresses command to soft-delete duplicate shop (delivery) addresses, keeping the most recently updated one per user. remp/crm#3512
- Runs in dry-run mode by default, use
--force to apply.
- Intended as a one-time cleanup after changes to checkout form: removes duplicate shop addresses accumulated before the address selector was introduced.
- Added JSON-LD schema for SearchAction type on the listing pages.
- Added
settingUp page shown briefly after email confirmation while newsletters are being initialised for the first time; auto-refreshes every few seconds. remp/euobserver#215
- Added
setRecentlyConfirmedWindowSeconds(int) to MailerConfig to control the redirect window; disabled (null) by default.
- Changed
/newsletter page to be accessible by guests. Subscribing while logged out redirects to login, and the subscription completes automatically after sign-in. remp/euobserver#152
- Fixed guests clicking a variant of a multi-variant newsletter being subscribed to every variant after login; now only the selected variant is subscribed.
- Fixed the master subscribe switch staying on after the last variant checkbox of a multi-variant newsletter was unchecked; it now flips off in sync.
- Added
--variant-code option to the remp-mailer:subscribe-segment-to-mail-type command to subscribe segment users to a specific mail type variant. remp/helpdesk#4660
- Added
copied_from_funnel_id column to track source when duplicating sales funnels. remp/crm#3729
- Added dataprovider to decide whether to redirect to the stored-card flow. remp/crm#3678
- Added
copied_from_scenario_id column to track source when duplicating scenarios. remp/crm#3729
- Fixed and improved multi-select dropdowns in scenario builder conditions. remp/crm#3551
- Added support for the undo operation after copying a node. remp/crm#3662
- Fixed a bug where copy-pasting text in inputs of an open dialog caused underlying nodes to be copied as well. remp/crm#3662
- Changed
axios dependency from 1.13.6 to 1.15.0 and rebuilt scenario-builder frontend assets. remp/crm#3772
- Changed
NotificationTemplateParamsTrait to fall back to recurrentBySubscription() when a payment has no directly linked recurrent. remp/crm#3797, remp/crm#3770
- Helps to load recurrent payment for upgrade subscriptions.
- Added
copied_from_segment_id column to track source when copying segments. remp/crm#3729
- Changed rebuilt segmenter frontend assets, which include upgraded Axios library. remp/crm#3772
- Added validation rules to disallow select all row columns wildcard (asterisk
*) through segment’s query or fields. remp/crm#3334
- BREAKING: Removed unused public method
SubscriptionsRepository::activeBetween(). remp/crm#3509
- Added
subscription_gaps table, SubscriptionGapsRepository, and subscriptions:calculate_gaps command for precomputed subscription gap detection used by reactivation report segments. remp/crm#3509
- Added
SubscriptionTypeTagAddedEvent emitted by SubscriptionTypeTagsRepository whenever a tag is newly added to a subscription type, carrying the subscription type and the tag name. remp/crm#3766
- Fixed
recurrent_charge_before form field not treating an empty input as null and missing integer validation. remp/crm#3766
- Fixed hardcoded English “hours” label next to
recurrent_charge_before on the subscription type detail page; replaced with a translated, pluralized string for all supported locales. remp/crm#3766
- Added
$skipTargetSubscriptionTypeLengthVerification parameter to AvailableUpgraders::all(), allowing upgrade options to be fetched regardless of target subscription type length. remp/crm#3770
- Fixed
PaymentStatusChangeHandler to forward $sendEmail set to event. Fixes New subscription scenario trigger firing after paid upgrades even when sendEmail was set to false. remp/crm#3796
- Fixed issue with upgrade subscriptions not having recurrent payment param when entering scenarios. remp/crm#3797, remp/crm#3770
- Recurrent payment is linked to the base subscription’s payment, not the upgrade payment. Data provider is used to keep login in one place (it is already used by
RecurrentPaymentsRepository).
- Fixed subsequent upgrades incorrectly rescheduling recurrent payments from unrelated active chains when a user held subscriptions tied to multiple recurrent payment chains. remp/crm#3770
- Fixed
isStoppedBySubscription incorrectly reporting upgraded subscriptions as stopped when the recurrent is linked to the upgrade payment instead of the base payment (affects subscriptions upgraded before 2024-10-22). remp/helpdesk#4438
BaseSubscriptionDataProvider now redirects isStoppedBySubscription only when the base subscription’s payment actually carries the recurrent.
- Replaced
(boolean) casts with (bool) short form in AppleSignIn and GoogleSignIn; imported Exception, DateTime, stdClass.
- Added UUID-based user search to admin’s universal search.
- Added
registration_redirect_url user meta storage in UsersCreateHandler. remp/euobserver#188
- Changed
UsersPresenter::renderEmailConfirm() to accept an optional autologinToken parameter, automatically logging in the user after email confirmation when not already signed in. remp/euobserver#188
- Fixed
UsersPresenter::renderEmailConfirm() to validate the redirect URL via RedirectValidator before redirecting after email confirmation. remp/euobserver#188
- Fixed
Container::components deprecation, replacing it with getComponents() call.
- Changed
AddressesSelectItemsBuilder::buildSimple() to accept optional $country and $requireFullAddress parameters for filtering address items by country and completeness. remp/crm#3512
- Added
SsoUserConfirmationHandler to automatically confirm users who register via Google or Apple Sign-In. remp/crm#3812
- Fixed Nette deprecation;
setCookie now requires \DateTimeInterface instead of unix timestamp.