Skip to content
28 changes: 23 additions & 5 deletions app/models/company.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ class Company < ApplicationRecord

THIS_PAYMENT_TYPE = Payment::PAYMENT_TYPE_BRANDING

RAILS_CACHE_PREFIX = 'company'
RAILS_CACHE_TYPE_PREFIX = 'cache'
RAILS_CACHE_TYPE = 'h_brand'

scope :has_name, -> { where.not(name:nil).where.not(name: '') }
scope :blank_name, -> { where(name: '').or(Company.where(name: nil)) }

Expand Down Expand Up @@ -174,6 +178,20 @@ def self.sort_by_information_complete_desc
sort_by_information_complete(:desc)
end


def self.rails_cache_prefix
RAILS_CACHE_PREFIX
end


def self.rails_cache_type_prefix
RAILS_CACHE_TYPE_PREFIX
end

def self.rails_cache_type
RAILS_CACHE_TYPE
end

# ===============================================================================================

alias_method :current_membership, :most_recent_payment
Expand Down Expand Up @@ -399,20 +417,20 @@ def get_short_h_brand_url(url)
end


def cache_key(type)
"company_#{id}_cache_#{type}"
def cache_key(type = self.class.rails_cache_type)
"#{self.class.rails_cache_prefix}_#{id}_#{self.class.rails_cache_type_prefix}_#{type}"
end

def h_brand_jpg
Rails.cache.read(cache_key('h_brand'))
Rails.cache.read(cache_key)
end

def h_brand_jpg=(image)
Rails.cache.write(cache_key('h_brand'), image)
Rails.cache.write(cache_key, image)
end

def clear_h_brand_jpg_cache
Rails.cache.delete(cache_key('h_brand'))
Rails.cache.delete(cache_key)
end


Expand Down
46 changes: 42 additions & 4 deletions app/models/conditions_response/condition_responder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class ConditionResponder
TIMING_EVERY_DAY = :every_day
TIMING_DAY_OF_WEEK = :day_of_week
TIMING_DAY_OF_MONTH = :day_of_month
TIMING_DAY_OF_YEAR = :day_of_year

ALL_TIMINGS = [TIMING_BEFORE, TIMING_AFTER, TIMING_ON, TIMING_EVERY_DAY,
TIMING_DAY_OF_WEEK, TIMING_DAY_OF_MONTH]
Expand Down Expand Up @@ -152,12 +153,17 @@ def self.timing_is_day_of_month?(timing)
end


def self.timing_is_day_of_year?(timing)
timing == TIMING_DAY_OF_YEAR
end

# True if the timing is every day
# OR if it is set to a day of the month and today is that day
# OR if it is set to a day of the week or month or year and today is that day
def self.timing_matches_today?(timing, config)
timing_is_every_day?(timing) ||
today_is_timing_day_of_week?(timing, config) ||
today_is_timing_day_of_month?(timing, config)
today_is_timing_day_of_month?(timing, config) ||
today_is_timing_day_of_year?(timing, config)
end


Expand All @@ -168,7 +174,6 @@ def self.timing_matches_today?(timing, config)
#
def self.today_is_timing_day_of_week?(timing, config)
self.timing_is_day_of_week?(timing) &&
TimingDayOfWeek.config_valid?(config) &&
TimingDayOfWeek.true_this_date?(config)
end

Expand All @@ -182,6 +187,14 @@ def self.today_is_timing_day_of_month?(timing, config)
end


# True if the timing is for the day of a year
# and today is the day of the year specified in the config
def self.today_is_timing_day_of_year?(timing, config)
self.timing_is_day_of_year?(timing) &&
TimingDayOfYear.true_this_date?(config)
end


# keep this for backwards compatibility for now. TODO: change usages to .validate_timing
def self.confirm_correct_timing(timing, expected_timing, log)
validate_timing(timing, [expected_timing], log)
Expand All @@ -191,7 +204,7 @@ def self.confirm_correct_timing(timing, expected_timing, log)
# Validates that the timing is in the list of valid timings.
# If it is not, it logs an error and raises and exception
#
# @param timing [Timing] - the timing to validate
# @param timing [Timing, Symbol] - the timing to validate
# @param expected_timings [Array] - list of valid timings
# @param log [Log] - the log to record the error to
#
Expand Down Expand Up @@ -253,6 +266,12 @@ def self.timing_day_of_month
end



def self.timing_day_of_year
TIMING_DAY_OF_YEAR
end


# ----------------------------------------------------------------------------
# Begin to refactor into separate classes:

Expand Down Expand Up @@ -319,4 +338,23 @@ def self.config_value_true_this_date?(value = {}, this_date = Time.zone.now)
end
end


class TimingDayOfYear < Timing

def self.config_key
:days_of_year
end


# @todo DRY
def self.config_key_value_valid?(days_of_year_value)
days_of_year_value.is_a?(Enumerable)
end


def self.config_value_true_this_date?(value = {}, this_date = Time.zone.now)
value.include?(this_date.yday)
end
end

end
41 changes: 41 additions & 0 deletions app/models/conditions_response/update_pom_year.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
class UpdatePOMYearError < ConditionResponderError
end


#--------------------------
#
# @class UpdatePomYear
#
# @desc Responsibility: Update the proof of membership year (so that the cards will show the correct year)
# This is probably run once a year on 1 januari
#
# @todo - is this a good name for the class? seems awkward
#
# @author Ashley Engelund (ashley.engelund@gmail.com weedySeaDragon @ github)
# @date 4/13/22
#
#--------------------------

class UpdatePomYear < ConditionResponder

INFO_MSG_START = 'update the Proof-of-Membership (POM) year'


def self.condition_response(condition, log, use_slack_notification: true)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lint/UnusedMethodArgument: Unused method argument - use_slack_notification.


begin
validate_timing(get_timing(condition), [timing_day_of_year], log)

caches_to_clear = [User, Company]
caches_to_clear.each{|cache| Rails.cache_delete_matched("^#{cache.send(:rails_cache_prefix)}") }

log.record('info', "#{self.class} success: #{INFO_MSG_START}")

rescue => error
raise UpdatePOMYearError, "Error trying to #{INFO_MSG_START}: #{error.message}"
end

end

end

15 changes: 14 additions & 1 deletion app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ class User < ApplicationRecord
THIS_PAYMENT_TYPE = Payment::PAYMENT_TYPE_MEMBER
MOST_RECENT_UPLOAD_METHOD = :created_at

RAILS_CACHE_PREFIX = 'user'
RAILS_CACHE_TYPE_PREFIX = 'cache'

scope :admins, -> { where(admin: true) }
scope :not_admins, -> { where(admin: nil).or(User.where(admin: false)) }

Expand Down Expand Up @@ -142,6 +145,16 @@ def self.membership_statuses_incl_informational
aasm.states.map(&:name) + MembershipsManager.informational_statuses
end


def self.rails_cache_prefix
RAILS_CACHE_PREFIX
end

def self.rails_cache_type_prefix
RAILS_CACHE_TYPE_PREFIX
end


# ----------------------------------------------------------------------------------------------
# Act As State Machine (AASM)

Expand Down Expand Up @@ -208,7 +221,7 @@ def most_recent_membership
end

def cache_key(type)
"user_#{id}_cache_#{type}"
"#{self.class.rails_cache_prefix}_#{id}_#{self.class.rails_cache_type_prefix}_#{type}"
end

def proof_of_membership_jpg
Expand Down
4 changes: 4 additions & 0 deletions spec/factories/conditions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,8 @@
config { {days: [2, 16]} }
end

trait :day_of_year do
timing { :day_of_year }
config { {day_of_year: [1]} }
end
end
53 changes: 49 additions & 4 deletions spec/models/conditions_response/condition_responder_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

it 'raises NoMethodError (must be defined by subclasses)' do

condition = Condition.create(class_name: 'MembershipExpireAlert',
condition = Condition.new(class_name: 'MembershipExpireAlert',
timing: 'before',
config: { days: [60, 30, 14, 2] })

Expand All @@ -28,7 +28,7 @@
describe '.get_timing' do

it 'always returns a symbol' do
expect(ConditionResponder.get_timing(create(:condition, timing: :blorf))).to eq(:blorf)
expect(ConditionResponder.get_timing(build(:condition, timing: :blorf))).to eq(:blorf)
end

context 'condition is nil' do
Expand All @@ -39,7 +39,7 @@

context 'condition is not nil' do
it 'returns the timing from the condition if condition is not nil' do
expect(ConditionResponder.get_timing(create(:condition, timing: :flurb))).to eq(:flurb)
expect(ConditionResponder.get_timing(build(:condition, timing: :flurb))).to eq(:flurb)
end
end

Expand All @@ -62,7 +62,7 @@

context 'condition is not nil' do
it 'returns the timing from the condition if condition is not nil' do
expect(ConditionResponder.get_config(create(:condition, config: { mertz: 732 }))).to eq({ mertz: 732 })
expect(ConditionResponder.get_config(build(:condition, config: { mertz: 732 }))).to eq({ mertz: 732 })
end
end

Expand Down Expand Up @@ -357,6 +357,51 @@
end


describe '.today_is_timing_day_of_year?' do

let(:condition) { build(:condition, :day_of_year) }
let(:timing) { described_class.get_timing(condition) }

let(:day_64) { Date.new(2020, 3, 4)}

let(:valid_day_of_year_config) { {days_of_year: [2, 64]}}

it 'config must include :days_of_year' do
travel_to(day_64) do
expect(described_class.today_is_timing_day_of_year?(timing, {})).to be_falsey
expect(described_class.today_is_timing_day_of_year?(timing, { blorf: :flurb})).to be_falsey
expect(described_class.today_is_timing_day_of_year?(timing, {days_of_year: [2, 64]})).to be_truthy
end
end

describe "config[:days_of_year] must include the yearday number for today" do

it 'false unless config[:days_of_year] is a collection' do
config = {days_of_year: 'flurb'}
expect(described_class.today_is_timing_day_of_year?(timing, config)).to be_falsey
end

it 'false if config[:days_of_year] is empty' do
config = {days_of_year: []}
expect(described_class.today_is_timing_day_of_year?(timing, config)).to be_falsey
end

it 'true if it includes the yearday number for today' do
config = {days_of_year: [2, 64]}
travel_to(Date.new(2020, 1, 1)) do
expect(described_class.today_is_timing_day_of_year?(timing, config)).to be_falsey
end
travel_to(Date.new(2020, 1, 2)) do
expect(described_class.today_is_timing_day_of_year?(timing, config)).to be_truthy
end
travel_to(day_64) do
expect(described_class.today_is_timing_day_of_year?(timing, config)).to be_truthy
end
end
end
end


describe '.confirm_correct_timing' do

let(:condition) { build(:condition, :every_day) }
Expand Down