fix(captain): compare date custom attributes stored as strings in audience matcher
Custom date attributes persist as ISO strings in jsonb, so is_greater_than/ is_less_than fell into the BigDecimal branch and never matched. Parse ISO date strings as times, mirroring Contacts::FilterService coercion.
This commit is contained in:
@@ -100,6 +100,8 @@ class Captain::AudienceMatcher
|
||||
def compare(actual, expected)
|
||||
return nil if actual.blank?
|
||||
|
||||
actual = Time.zone.parse(actual) if iso_date_string?(actual)
|
||||
|
||||
if actual.is_a?(Date) || actual.acts_like?(:time)
|
||||
actual.to_time <=> Time.zone.parse(expected.to_s)
|
||||
else
|
||||
@@ -109,6 +111,14 @@ class Captain::AudienceMatcher
|
||||
nil
|
||||
end
|
||||
|
||||
# Custom date attributes store ISO strings in jsonb; treat them as dates the way
|
||||
# Contacts::FilterService does (it casts them in SQL).
|
||||
def iso_date_string?(value)
|
||||
value.is_a?(String) && Date.iso8601(value).present?
|
||||
rescue ArgumentError
|
||||
false
|
||||
end
|
||||
|
||||
def older_than_days?(actual, days)
|
||||
date = to_date(actual)
|
||||
date.present? && date < Time.zone.today - days.to_i.days
|
||||
|
||||
@@ -61,6 +61,13 @@ RSpec.describe Captain::AudienceMatcher do
|
||||
expect(matches?(leaf('created_at', 'days_before', '30'))).to be(true)
|
||||
expect(matches?(leaf('created_at', 'days_before', '60'))).to be(false)
|
||||
end
|
||||
|
||||
it 'compares date custom attributes stored as ISO strings' do
|
||||
contact.update!(custom_attributes: contact.custom_attributes.merge('signed_up_on' => '2024-01-15'))
|
||||
expect(matches?(leaf('signed_up_on', 'is_greater_than', '2024-01-01'))).to be(true)
|
||||
expect(matches?(leaf('signed_up_on', 'is_less_than', '2024-01-01'))).to be(false)
|
||||
expect(matches?(leaf('signed_up_on', 'is_less_than', '2024-02-01'))).to be(true)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with labels' do
|
||||
|
||||
Reference in New Issue
Block a user