diff --git a/CHANGELOG.md b/CHANGELOG.md index dbc9cd05..93946468 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). -## [0.13.0] — 2024-08-28 +## [0.13.3] — 2024-09-6 ### Added diff --git a/app/services/create_stats.rb b/app/services/create_stats.rb index b245ee0a..fc086d69 100644 --- a/app/services/create_stats.rb +++ b/app/services/create_stats.rb @@ -12,29 +12,12 @@ class CreateStats def call users.each do |user| years.each do |year| - months.each do |month| - beginning_of_month_timestamp = DateTime.new(year, month).beginning_of_month.to_i - end_of_month_timestamp = DateTime.new(year, month).end_of_month.to_i - - points = points(user, beginning_of_month_timestamp, end_of_month_timestamp) - next if points.empty? - - stat = Stat.find_or_initialize_by(year:, month:, user:) - stat.distance = distance(points) - stat.toponyms = toponyms(points) - stat.daily_distance = stat.distance_by_day - stat.save - end + months.each { |month| update_month_stats(user, year, month) } end - Notifications::Create.new(user:, kind: :info, title: 'Stats updated', content: 'Stats updated').call + create_stats_updated_notification(user) rescue StandardError => e - Notifications::Create.new( - user:, - kind: :error, - title: 'Stats update failed', - content: "#{e.message}, stacktrace: #{e.backtrace.join("\n")}" - ).call + create_stats_update_failed_notification(user, e) end end @@ -49,6 +32,21 @@ class CreateStats .select(:latitude, :longitude, :timestamp, :city, :country) end + def update_month_stats(user, year, month) + beginning_of_month_timestamp = DateTime.new(year, month).beginning_of_month.to_i + end_of_month_timestamp = DateTime.new(year, month).end_of_month.to_i + + points = points(user, beginning_of_month_timestamp, end_of_month_timestamp) + + return if points.empty? + + stat = Stat.find_or_initialize_by(year:, month:, user:) + stat.distance = distance(points) + stat.toponyms = toponyms(points) + stat.daily_distance = stat.distance_by_day + stat.save + end + def distance(points) distance = 0 @@ -64,4 +62,19 @@ class CreateStats def toponyms(points) CountriesAndCities.new(points).call end + + def create_stats_updated_notification(user) + Notifications::Create.new( + user:, kind: :info, title: 'Stats updated', content: 'Stats updated' + ).call + end + + def create_stats_update_failed_notification(user, error) + Notifications::Create.new( + user:, + kind: :error, + title: 'Stats update failed', + content: "#{error.message}, stacktrace: #{error.backtrace.join("\n")}" + ).call + end end diff --git a/spec/services/create_stats_spec.rb b/spec/services/create_stats_spec.rb index 95b9f23f..9bd46728 100644 --- a/spec/services/create_stats_spec.rb +++ b/spec/services/create_stats_spec.rb @@ -21,32 +21,66 @@ RSpec.describe CreateStats do let!(:point2) { create(:point, user:, import:, latitude: 1, longitude: 2) } let!(:point3) { create(:point, user:, import:, latitude: 3, longitude: 4) } - it 'creates stats' do - expect { create_stats }.to change { Stat.count }.by(1) - end - - it 'calculates distance' do - create_stats - - expect(Stat.last.distance).to eq(563) - end - - it 'created notifications' do - expect { create_stats }.to change { Notification.count }.by(1) - end - - context 'when there is an error' do - before do - allow(Stat).to receive(:find_or_initialize_by).and_raise(StandardError) + context 'when units are kilometers' do + it 'creates stats' do + expect { create_stats }.to change { Stat.count }.by(1) end - it 'does not create stats' do - expect { create_stats }.not_to(change { Stat.count }) + it 'calculates distance' do + create_stats + + expect(Stat.last.distance).to eq(563) end it 'created notifications' do expect { create_stats }.to change { Notification.count }.by(1) end + + context 'when there is an error' do + before do + allow(Stat).to receive(:find_or_initialize_by).and_raise(StandardError) + end + + it 'does not create stats' do + expect { create_stats }.not_to(change { Stat.count }) + end + + it 'created notifications' do + expect { create_stats }.to change { Notification.count }.by(1) + end + end + end + + context 'when units are miles' do + before { stub_const('DISTANCE_UNIT', 'mi') } + + it 'creates stats' do + expect { create_stats }.to change { Stat.count }.by(1) + end + + it 'calculates distance' do + create_stats + + expect(Stat.last.distance).to eq(349) + end + + it 'created notifications' do + expect { create_stats }.to change { Notification.count }.by(1) + end + + context 'when there is an error' do + before do + allow(Stat).to receive(:find_or_initialize_by).and_raise(StandardError) + end + + it 'does not create stats' do + expect { create_stats }.not_to(change { Stat.count }) + end + + it 'created notifications' do + expect { create_stats }.to change { Notification.count }.by(1) + end + end end end end