An example of an ad campaign status report for an account manager. https://monosnap.com/file/fieiIuDJjP9vnriRtA7J12kcTD4Wiq
Last active
May 29, 2017 09:24
-
-
Save DariaUlanova/a51e57d15b1d83fbfe33cb30ac1b1f5e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Reports::FetchCampaignStatuses < ServiceObjectBase | |
pattr_initialize :campaign | |
def perform | |
campaign_status = Reports::CampaignStatus.find_or_initialize_by( | |
campaign_id: @campaign.id | |
) | |
if spent_money_last_two_weeks? && campaign_status.check | |
campaign_status.update(status_errors: status_errors) | |
else | |
campaign_status.update(check: false, status_errors: []) | |
end | |
end | |
private | |
def spent_money_last_two_weeks? | |
Billing::CampaignExpendituresQuery | |
.new(@campaign) | |
.operations(from: 2.weeks.ago, to: Time.zone.today) | |
.any? | |
end | |
def status_errors | |
Reports::CampaignStatus.status_errors.values | |
.select { |error| send "#{error}?" } | |
end | |
def low_balance? | |
@campaign.balance.low_balance? | |
end | |
def campaign_off? | |
@campaign.project.stopped? || | |
@campaign.stopped? || | |
@campaign.adverts.all?(&:stopped?) | |
end | |
def sync_fail? | |
Reports::CampaignStatuses::SyncFail.call @campaign | |
end | |
def moderation_fail? | |
Reports::CampaignStatuses::ModerationFail.call @campaign | |
end | |
def few_clicks? | |
Reports::CampaignStatuses::FewClicks.call @campaign | |
end | |
def few_conversions? | |
Reports::CampaignStatuses::FewConversions.call @campaign | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
describe Reports::FetchCampaignStatuses do | |
describe '#perform' do | |
let(:service) { Reports::FetchCampaignStatuses.new(campaign) } | |
let(:project) { create :project, state: project_trait } | |
let(:project_trait) { :started } | |
let(:campaign) do | |
create :campaign_mobile, :google, campaign_trait, | |
adverts: adverts, | |
reports_campaign_status: campaign_status, | |
project: project | |
end | |
let(:campaign_trait) { :started } | |
let(:campaign_status) { create :reports_campaign_status, check: true } | |
let(:adverts) { [advert, advert_2] } | |
let(:advert) do | |
create :advert, platform: Platform::GOOGLE, gl_ad: gl_ad, state: state | |
end | |
let(:advert_2) do | |
create :advert, platform: Platform::GOOGLE, gl_ad: gl_ad_2, state: state | |
end | |
let(:state) { :started } | |
let(:gl_ad) { create :gl_ad, :synced } | |
let(:gl_ad_2) do | |
create :gl_ad, :synced, status: 'ENABLED', moderation_status: 'APPROVED' | |
end | |
let(:sync_fail) { false } | |
let(:moderation_fail) { false } | |
let(:few_clicks) { false } | |
let(:few_conversions) { false } | |
let!(:expenditure_1) do | |
create :expenditure_operation, | |
campaign: campaign, | |
l_date_on: expenditure_period_1 | |
end | |
let!(:expenditure_2) do | |
create :expenditure_operation, | |
campaign: campaign, | |
l_date_on: expenditure_period_2 | |
end | |
let(:expenditure_period_1) { 1.week.ago } | |
let(:expenditure_period_2) { 3.week.ago } | |
include_context :platform_balance, :google, 9 | |
before do | |
allow(Reports::CampaignStatuses::SyncFail) | |
.to receive(:call) | |
.and_return sync_fail | |
allow(Reports::CampaignStatuses::ModerationFail) | |
.to receive(:call) | |
.and_return moderation_fail | |
allow(Reports::CampaignStatuses::FewClicks) | |
.to receive(:call) | |
.and_return few_clicks | |
allow(Reports::CampaignStatuses::FewConversions) | |
.to receive(:call) | |
.and_return few_conversions | |
service.perform | |
end | |
describe 'expenditures during last two weeks' do | |
context 'with expenditures & check is true' do | |
it do | |
expect(campaign.reload.reports_campaign_status.status_errors) | |
.to eq %w(low_balance) | |
expect(campaign.reload.reports_campaign_status.check).to eq true | |
end | |
end | |
context 'with expenditures but check is false' do | |
let(:campaign_status) { create :reports_campaign_status, check: false } | |
it do | |
expect(campaign.reload.reports_campaign_status.status_errors) | |
.to eq [] | |
expect(campaign.reload.reports_campaign_status.check).to eq false | |
end | |
end | |
context 'no expenditures during last two weeks' do | |
let(:expenditure_period_1) { 3.weeks.ago } | |
it do | |
expect(campaign.reload.reports_campaign_status.status_errors) | |
.to eq [] | |
expect(campaign.reload.reports_campaign_status.check).to eq false | |
end | |
end | |
end | |
describe 'low balance' do | |
context 'not include' do | |
let!(:expenditure_1) { nil } | |
let!(:expenditure_2) { nil } | |
let(:campaign) do | |
create :campaign_mobile, :google, | |
daily_budget: 100, | |
reports_campaign_status: campaign_status | |
end | |
it do | |
expect(campaign.reload.reports_campaign_status.status_errors) | |
.to_not include :low_balance | |
end | |
end | |
context 'include' do | |
it do | |
expect(campaign.reload.reports_campaign_status.status_errors) | |
.to include :low_balance | |
end | |
end | |
end | |
describe 'campaign_off' do | |
context 'include' do | |
context 'project stopped' do | |
let(:project_trait) { :stopped } | |
it do | |
expect(campaign.reload.reports_campaign_status.status_errors) | |
.to include :campaign_off | |
end | |
end | |
context 'campaign stopped' do | |
let(:campaign_trait) { :stopped } | |
it do | |
expect(campaign.reload.reports_campaign_status.status_errors) | |
.to include :campaign_off | |
end | |
end | |
context 'all adverts stopped' do | |
let(:state) { :stopped } | |
it do | |
expect(campaign.reload.reports_campaign_status.status_errors) | |
.to include :campaign_off | |
end | |
end | |
end | |
context 'not include' do | |
it do | |
expect(campaign.reload.reports_campaign_status.status_errors) | |
.to_not include :campaign_off | |
end | |
end | |
end | |
describe 'sync fail' do | |
let(:sync_fail) { true } | |
it do | |
expect(campaign.reload.reports_campaign_status.status_errors) | |
.to include :sync_fail | |
expect(campaign.reload.reports_campaign_status.status_errors) | |
.to_not include :campaign_off | |
end | |
end | |
describe 'moderation fail' do | |
let(:moderation_fail) { true } | |
it do | |
expect(campaign.reload.reports_campaign_status.status_errors) | |
.to include :moderation_fail | |
expect(campaign.reload.reports_campaign_status.status_errors) | |
.to_not include :sync_fail | |
expect(campaign.reload.reports_campaign_status.status_errors) | |
.to_not include :campaign_off | |
end | |
end | |
describe 'few_clicks' do | |
let(:few_clicks) { true } | |
it do | |
expect(campaign.reload.reports_campaign_status.status_errors) | |
.to include :few_clicks | |
expect(campaign.reload.reports_campaign_status.status_errors) | |
.to_not include :moderation_fail | |
expect(campaign.reload.reports_campaign_status.status_errors) | |
.to_not include :sync_fail | |
expect(campaign.reload.reports_campaign_status.status_errors) | |
.to_not include :campaign_off | |
end | |
end | |
describe 'few_conversions' do | |
let(:few_conversions) { true } | |
it do | |
expect(campaign.reload.reports_campaign_status.status_errors) | |
.to include :few_conversions | |
expect(campaign.reload.reports_campaign_status.status_errors) | |
.to_not include :moderation_fail | |
expect(campaign.reload.reports_campaign_status.status_errors) | |
.to_not include :sync_fail | |
expect(campaign.reload.reports_campaign_status.status_errors) | |
.to_not include :campaign_off | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment