1
0
Fork 0
mirror of https://github.com/maybe-finance/maybe.git synced 2025-07-19 13:19:39 +02:00
Maybe/app/models/category.rb

93 lines
2.5 KiB
Ruby
Raw Normal View History

class Category < ApplicationRecord
has_many :transactions, dependent: :nullify, class_name: "Account::Transaction"
has_many :import_mappings, as: :mappable, dependent: :destroy, class_name: "Import::Mapping"
belongs_to :family
has_many :subcategories, class_name: "Category", foreign_key: :parent_id
belongs_to :parent, class_name: "Category", optional: true
validates :name, :color, :family, presence: true
validates :name, uniqueness: { scope: :family_id }
validate :category_level_limit
scope :alphabetically, -> { order(:name) }
COLORS = %w[#e99537 #4da568 #6471eb #db5a54 #df4e92 #c44fe9 #eb5429 #61c9ea #805dee #6ad28a]
UNCATEGORIZED_COLOR = "#737373"
TRANSFER_COLOR = "#444CE7"
PAYMENT_COLOR = "#db5a54"
TRADE_COLOR = "#e99537"
class Group
attr_reader :category, :subcategories
delegate :name, :color, to: :category
def self.for(categories)
categories.select { |category| category.parent_id.nil? }.map do |category|
new(category, category.subcategories)
end
end
def initialize(category, subcategories = nil)
@category = category
@subcategories = subcategories || []
end
end
class << self
def bootstrap_defaults
default_categories.each do |name, color|
find_or_create_by!(name: name) do |category|
category.color = color
end
end
end
private
def default_categories
[
[ "Income", "#e99537" ],
[ "Loan Payments", "#6471eb" ],
[ "Bank Fees", "#db5a54" ],
[ "Entertainment", "#df4e92" ],
[ "Food & Drink", "#c44fe9" ],
[ "Groceries", "#eb5429" ],
[ "Dining Out", "#61c9ea" ],
[ "General Merchandise", "#805dee" ],
[ "Clothing & Accessories", "#6ad28a" ],
[ "Electronics", "#e99537" ],
[ "Healthcare", "#4da568" ],
[ "Insurance", "#6471eb" ],
[ "Utilities", "#db5a54" ],
[ "Transportation", "#df4e92" ],
[ "Gas & Fuel", "#c44fe9" ],
[ "Education", "#eb5429" ],
[ "Charitable Donations", "#61c9ea" ],
[ "Subscriptions", "#805dee" ]
]
end
end
def replace_and_destroy!(replacement)
transaction do
transactions.update_all category_id: replacement&.id
destroy!
end
end
def subcategory?
parent.present?
end
private
def category_level_limit
if subcategory? && parent.subcategory?
errors.add(:parent, "can't have more than 2 levels of subcategories")
end
end
end