mirror of
https://github.com/we-promise/sure.git
synced 2026-05-25 05:24:57 +00:00
* add missing Hungarian translations for newly extracted strings Replace hard-coded UI strings with I18n lookups across controllers, models and views (breadcrumbs, dashboard, reports, settings, transactions, balance sheet, MFA status). Update models to use translations for category defaults, account/display names, classification group and period labels; remove a few hardcoded display_name methods. Add and update numerous locale files (English and extensive Hungarian translations, plus model/view/doorkeeper entries) to provide the required keys. These changes centralize copy for localization and prepare the app for Hungarian/English UI text. * Pluralize account type labels; tidy Crypto model Update English locale account type labels to use plural forms for consistency (Investment(s), Properties, Vehicles, Other Assets, Credit Cards, Loans, Other Liabilities). Also remove an extra blank line in app/models/crypto.rb to tidy up formatting. * Back to singular * fix(i18n): separate singular and group account labels * Update _accountable_group.html.erb * Use I18n plural names for account types Change Accountable#display_name to look up pluralized account type names via I18n (accounts.types_plural.<underscored_class>) with a fallback to the legacy display logic. Add legacy_display_name helper to preserve previous behavior (singular for Depository and Crypto, pluralized otherwise). Add corresponding types_plural entries in English and Hungarian locale files for various account types. --------- Co-authored-by: Juan José Mata <jjmata@jjmata.com> Co-authored-by: sure-admin <sure-admin@splashblot.com>
132 lines
3.2 KiB
Ruby
132 lines
3.2 KiB
Ruby
module Accountable
|
|
extend ActiveSupport::Concern
|
|
|
|
TYPES = %w[Depository Investment Crypto Property Vehicle OtherAsset CreditCard Loan OtherLiability]
|
|
|
|
# Define empty hash to ensure all accountables have this defined
|
|
SUBTYPES = {}.freeze
|
|
|
|
def self.from_type(type)
|
|
return nil unless TYPES.include?(type)
|
|
type.constantize
|
|
end
|
|
|
|
included do
|
|
include Enrichable
|
|
|
|
has_one :account, as: :accountable, touch: true
|
|
end
|
|
|
|
class_methods do
|
|
def classification
|
|
raise NotImplementedError, "Accountable must implement #classification"
|
|
end
|
|
|
|
def icon
|
|
raise NotImplementedError, "Accountable must implement #icon"
|
|
end
|
|
|
|
def color
|
|
raise NotImplementedError, "Accountable must implement #color"
|
|
end
|
|
|
|
# Given a subtype, look up the label for this accountable type
|
|
# Uses i18n with fallback to hardcoded SUBTYPES values
|
|
def subtype_label_for(subtype, format: :short)
|
|
return nil if subtype.nil?
|
|
|
|
label_type = format == :long ? :long : :short
|
|
fallback = self::SUBTYPES.dig(subtype, label_type)
|
|
|
|
I18n.t(
|
|
"#{name.underscore.pluralize}.subtypes.#{subtype}.#{label_type}",
|
|
default: fallback
|
|
)
|
|
end
|
|
|
|
# Convenience method for getting the short label
|
|
def short_subtype_label_for(subtype)
|
|
subtype_label_for(subtype, format: :short)
|
|
end
|
|
|
|
# Convenience method for getting the long label
|
|
def long_subtype_label_for(subtype)
|
|
subtype_label_for(subtype, format: :long)
|
|
end
|
|
|
|
def favorable_direction
|
|
classification == "asset" ? "up" : "down"
|
|
end
|
|
|
|
def singular_display_name
|
|
I18n.t("accounts.types.#{name.underscore}", default: legacy_singular_display_name)
|
|
end
|
|
|
|
def display_name
|
|
I18n.t("accounts.types_plural.#{name.underscore}", default: -> { legacy_display_name })
|
|
end
|
|
|
|
def legacy_display_name
|
|
return singular_display_name if name.in?([ "Depository", "Crypto" ])
|
|
|
|
singular_display_name.pluralize
|
|
end
|
|
|
|
def legacy_singular_display_name
|
|
case name
|
|
when "Depository"
|
|
"Cash"
|
|
when "Crypto"
|
|
"Crypto"
|
|
else
|
|
name.underscore.humanize
|
|
end
|
|
end
|
|
|
|
# Sums the balances of all active accounts of this type, converting foreign currencies to the family's currency.
|
|
# @return [BigDecimal] total balance in the family's currency
|
|
def balance_money(family)
|
|
accounts = family.accounts.active.where(accountable_type: self.name).to_a
|
|
|
|
foreign_currencies = accounts.filter_map { |a| a.currency if a.currency != family.currency }
|
|
rates = ExchangeRate.rates_for(foreign_currencies, to: family.currency, date: Date.current)
|
|
|
|
accounts.sum(BigDecimal(0)) { |account|
|
|
if account.currency == family.currency
|
|
account.balance
|
|
else
|
|
account.balance * (rates[account.currency] || 1)
|
|
end
|
|
}
|
|
end
|
|
end
|
|
|
|
def singular_display_name
|
|
self.class.singular_display_name
|
|
end
|
|
|
|
def display_name
|
|
self.class.display_name
|
|
end
|
|
|
|
def balance_display_name
|
|
"account value"
|
|
end
|
|
|
|
def opening_balance_display_name
|
|
"opening balance"
|
|
end
|
|
|
|
def icon
|
|
self.class.icon
|
|
end
|
|
|
|
def color
|
|
self.class.color
|
|
end
|
|
|
|
def classification
|
|
self.class.classification
|
|
end
|
|
end
|