1
0
Fork 0
mirror of https://github.com/maybe-finance/maybe.git synced 2025-08-02 20:15:22 +02:00

Account Sync should happen at login, 1x per day, OR on-demand (#594)

* Add last_sync_date to accounts table

* Always sync Account after Valuation or Transaction creation, update, or deletion.

Skip sync if user clicks "sync" button without changing anything

* Sync user accounts daily based on last_login_at
This commit is contained in:
Mattia 2024-04-04 23:00:12 +02:00 committed by GitHub
parent 4f0b2de4ef
commit 315c4bf1ec
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 48 additions and 8 deletions

View file

@ -20,7 +20,7 @@ class AccountsController < ApplicationController
def update
if @account.update(account_params.except(:accountable_type))
@account.sync_later if account_params[:is_active] == "1"
@account.sync_later if account_params[:is_active] == "1" && @account.can_sync?
respond_to do |format|
format.html { redirect_to accounts_path, notice: t(".success") }
@ -53,15 +53,12 @@ class AccountsController < ApplicationController
end
def sync
@account.sync_later
@account.sync_later if @account.can_sync?
respond_to do |format|
format.html { redirect_to account_path(@account), notice: t(".success") }
format.turbo_stream do
render turbo_stream: [
turbo_stream.append("notification-tray", partial: "shared/notification", locals: { type: "success", content: t(".success") }),
turbo_stream.replace("sync_message", partial: "accounts/sync_message", locals: { is_syncing: true })
]
render turbo_stream: turbo_stream.append("notification-tray", partial: "shared/notification", locals: { type: "success", content: t(".success") })
end
end
end

View file

@ -2,6 +2,8 @@ class ApplicationController < ActionController::Base
include Authentication
include Pagy::Backend
before_action :sync_accounts
default_form_builder ApplicationFormBuilder
# Only allow modern browsers supporting webp images, web push, badges, import maps, CSS nesting, and CSS :has.
@ -13,4 +15,12 @@ class ApplicationController < ActionController::Base
ENV["HOSTED"] == "true"
end
helper_method :hosted_app?
def sync_accounts
return if Current.user.blank?
if Current.user.last_login_at.nil? || Current.user.last_login_at.before?(Date.current.beginning_of_day)
Current.family.sync_accounts
end
end
end

View file

@ -3,11 +3,13 @@ module Authentication
included do
before_action :authenticate_user!
after_action :set_last_login_at
end
class_methods do
def skip_authentication(**options)
skip_before_action :authenticate_user!, **options
skip_after_action :set_last_login_at, **options
end
end
@ -31,4 +33,8 @@ module Authentication
Current.user = nil
reset_session
end
def set_last_login_at
Current.user.update(last_login_at: DateTime.now)
end
end

View file

@ -14,12 +14,23 @@ module Account::Syncable
calculator.calculate
self.balances.upsert_all(calculator.daily_balances, unique_by: :index_account_balances_on_account_id_date_currency_unique)
self.balances.where("date < ?", effective_start_date).delete_all
update!(status: "ok")
update!(status: "ok", last_sync_date: Date.today)
rescue => e
update!(status: "error")
Rails.logger.error("Failed to sync account #{id}: #{e.message}")
end
def can_sync?
# Skip account sync if account is not active or the sync process is already running
return false unless is_active
return false if syncing?
# If last_sync_date is blank (i.e. the account has never been synced before) allow syncing
return true if last_sync_date.blank?
# If last_sync_date is not today, allow syncing
last_sync_date != Date.today
end
# The earliest date we can calculate a balance for
def effective_start_date
first_valuation_date = self.valuations.order(:date).pluck(:date).first

View file

@ -43,4 +43,8 @@ class Family < ApplicationRecord
def liabilities
Money.new(accounts.active.liabilities.map { |account| account.balance_money.exchange_to(currency) || 0 }.sum, currency)
end
def sync_accounts
accounts.each { |account| account.sync_later if account.can_sync? }
end
end