From 868c37ef35f2cf14c727ee571a0df868d0044ba8 Mon Sep 17 00:00:00 2001 From: taitus Date: Tue, 5 Feb 2019 18:16:40 +0100 Subject: [PATCH] Detect new actions for proposals Create new Dashboard::Action class method to detect new actions between yesterday and today for a proposal. - Published proposal: Only detect new actions with "published_proposal" field eq true - Draft proposal: Only detect new actions with "published_proposal" field eq false --- app/models/dashboard/action.rb | 40 ++++++++++++ spec/models/dashboard/action_spec.rb | 91 ++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+) diff --git a/app/models/dashboard/action.rb b/app/models/dashboard/action.rb index 357bb1412..2e9a68f88 100644 --- a/app/models/dashboard/action.rb +++ b/app/models/dashboard/action.rb @@ -46,6 +46,9 @@ class Dashboard::Action < ActiveRecord::Base scope :by_proposal, lambda { |proposal| return where(published_proposal: false) if proposal.draft? } + scope :by_published_proposal, lambda { |published| + return where(published_proposal: published) + } def self.active_for(proposal) published_at = proposal.published_at&.to_date || Date.today @@ -85,4 +88,41 @@ class Dashboard::Action < ActiveRecord::Base def self.next_goal_for(proposal) course_for(proposal).first end + + def self.detect_new_actions(proposal) + actions_for_today = get_actions_for_today(proposal) + actions_for_yesterday = get_actions_for_yesterday(proposal) + + new_actions = actions_for_today - actions_for_yesterday + end + + private + def self.get_actions_for_today(proposal) + proposal_votes = proposal.cached_votes_up + day_offset = calculate_day_offset(proposal, Date.today) + + calculate_actions(proposal_votes, day_offset, proposal) + end + + def self.get_actions_for_yesterday(proposal) + proposal_votes = calculate_votes(proposal) + day_offset = calculate_day_offset(proposal, Date.yesterday) + + calculate_actions(proposal_votes, day_offset, proposal) + end + + def self.calculate_day_offset(proposal, date) + start_date = proposal.published? ? proposal.published_at : proposal.created_at + (date - start_date.to_date).to_i + end + + def self.calculate_actions(proposal_votes, day_offset, proposal) + Dashboard::Action.active.where("required_supports <= ?", proposal_votes) + .where("day_offset <= ?", day_offset) + .by_published_proposal(proposal.published?) + end + + def self.calculate_votes(proposal) + Vote.where(votable: proposal).where("created_at <= ?", Date.yesterday).count + end end diff --git a/spec/models/dashboard/action_spec.rb b/spec/models/dashboard/action_spec.rb index 738282992..ca813cd06 100644 --- a/spec/models/dashboard/action_spec.rb +++ b/spec/models/dashboard/action_spec.rb @@ -224,4 +224,95 @@ describe Dashboard::Action do expect(described_class.course_for(proposal)).to include(resource) end end + + context "#detect_new_actions" do + + describe "No detect new actions" do + + let!(:action) { create(:dashboard_action, :proposed_action, :active, day_offset: 1) } + let!(:resource) { create(:dashboard_action, :resource, :active, day_offset: 1) } + + it "when there are not news actions actived for published proposals" do + proposal = create(:proposal) + action.update(published_proposal: true) + resource.update(published_proposal: true) + + expect(described_class.detect_new_actions(proposal)).to eq [] + end + + it "when there are news actions actived for draft_proposal but proposal is published" do + proposal = create(:proposal) + action.update(published_proposal: false, day_offset: 0) + resource.update(published_proposal: false, day_offset: 0) + + expect(described_class.detect_new_actions(proposal)).to eq [] + end + + it "when there are not news actions actived for draft proposals" do + proposal = create(:proposal, :draft) + action.update(published_proposal: false) + resource.update(published_proposal: false) + + expect(described_class.detect_new_actions(proposal)).to eq [] + end + + it "when there are news actions actived for published_proposal but proposal is draft" do + proposal = create(:proposal, :draft) + action.update(published_proposal: true, day_offset: 0) + resource.update(published_proposal: true, day_offset: 0) + + expect(described_class.detect_new_actions(proposal)).to eq [] + end + + end + + describe "Detect new actions when there are news actions actived" do + + context "for published proposals" do + + let!(:proposal) { create(:proposal) } + let!(:action) { create(:dashboard_action, :proposed_action, :active, day_offset: 0, published_proposal: true) } + let!(:resource) { create(:dashboard_action, :resource, :active, day_offset: 0, published_proposal: true) } + + it "when proposal has been created today and day_offset is valid only for today" do + expect(described_class.detect_new_actions(proposal)).to include(resource) + expect(described_class.detect_new_actions(proposal)).to include(action) + end + + it "when proposal has received a new vote today" do + proposal.update(created_at: Date.yesterday, published_at: Date.yesterday) + action.update(required_supports: 1) + resource.update(required_supports: 0) + create(:vote, voter: proposal.author, votable: proposal) + + expect(described_class.detect_new_actions(proposal)).to include(action) + expect(described_class.detect_new_actions(proposal)).not_to include(resource) + end + + end + + context "for draft proposals" do + + let!(:proposal) { create(:proposal, :draft) } + let!(:action) { create(:dashboard_action, :proposed_action, :active, day_offset: 0, published_proposal: false) } + let!(:resource) { create(:dashboard_action, :resource, :active, day_offset: 0, published_proposal: false) } + + it "when day_offset field is valid for today and invalid for yesterday" do + expect(described_class.detect_new_actions(proposal)).to include(resource) + expect(described_class.detect_new_actions(proposal)).to include(action) + end + + it "when proposal has received a new vote today" do + proposal.update(created_at: Date.yesterday) + action.update(required_supports: 1) + resource.update(required_supports: 2) + create(:vote, voter: proposal.author, votable: proposal) + + expect(described_class.detect_new_actions(proposal)).to include(action) + expect(described_class.detect_new_actions(proposal)).not_to include(resource) + end + + end + end + end end