From 08518070f330b69b89ccd292a259d69842f69b45 Mon Sep 17 00:00:00 2001 From: Leandro Segovia Date: Thu, 2 Apr 2020 13:58:26 -0300 Subject: [PATCH 1/2] fix(ledgerizer-tenant): create accounts specifying tenant explicitly --- app/models/concerns/ledgerizer_tenant.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/models/concerns/ledgerizer_tenant.rb b/app/models/concerns/ledgerizer_tenant.rb index a9fc7b0..5b33db8 100644 --- a/app/models/concerns/ledgerizer_tenant.rb +++ b/app/models/concerns/ledgerizer_tenant.rb @@ -40,6 +40,7 @@ def create_entry!(executable_entry) def find_or_create_account_from_executable_movement!(movement) accounts.find_or_create_by!( + tenant: self, accountable: movement.accountable, name: movement.account_name, currency: format_to_upcase(movement.base_currency), From e8b5f5acbda1afb2bf5851d1b23f598944bcab0d Mon Sep 17 00:00:00 2001 From: Leandro Segovia Date: Thu, 2 Apr 2020 16:49:51 -0300 Subject: [PATCH 2/2] feat(): allow movements without accountable --- app/models/concerns/ledgerizer_tenant.rb | 1 - app/models/ledgerizer/account.rb | 2 +- lib/ledgerizer/definition/dsl.rb | 2 +- lib/ledgerizer/definition/entry.rb | 16 +++++-- lib/ledgerizer/definition/movement.rb | 10 ++++- lib/ledgerizer/execution/dsl.rb | 4 +- lib/ledgerizer/execution/entry.rb | 6 +-- spec/dummy/spec/lib/execution/dsl_spec.rb | 44 +++++++++++++++++++ .../spec/models/ledgerizer/account_spec.rb | 2 +- .../definition_dsl_movement.rb | 24 ++++++++++ 10 files changed, 98 insertions(+), 13 deletions(-) diff --git a/app/models/concerns/ledgerizer_tenant.rb b/app/models/concerns/ledgerizer_tenant.rb index 5b33db8..a9fc7b0 100644 --- a/app/models/concerns/ledgerizer_tenant.rb +++ b/app/models/concerns/ledgerizer_tenant.rb @@ -40,7 +40,6 @@ def create_entry!(executable_entry) def find_or_create_account_from_executable_movement!(movement) accounts.find_or_create_by!( - tenant: self, accountable: movement.accountable, name: movement.account_name, currency: format_to_upcase(movement.base_currency), diff --git a/app/models/ledgerizer/account.rb b/app/models/ledgerizer/account.rb index ab1b43a..5bd65f0 100644 --- a/app/models/ledgerizer/account.rb +++ b/app/models/ledgerizer/account.rb @@ -5,7 +5,7 @@ class Account < ApplicationRecord include LedgerizerLinesRelated belongs_to :tenant, polymorphic: true - belongs_to :accountable, polymorphic: true + belongs_to :accountable, polymorphic: true, optional: true has_many :lines, dependent: :destroy enumerize :account_type, in: Ledgerizer::Definition::Account::TYPES, diff --git a/lib/ledgerizer/definition/dsl.rb b/lib/ledgerizer/definition/dsl.rb index 082a30c..a363a3f 100644 --- a/lib/ledgerizer/definition/dsl.rb +++ b/lib/ledgerizer/definition/dsl.rb @@ -48,7 +48,7 @@ def entry(entry_code, document: nil, &block) @current_entry = nil end - def debit(account:, accountable:) + def debit(account:, accountable: nil) in_context do @current_tenant.add_movement( movement_type: :debit, diff --git a/lib/ledgerizer/definition/entry.rb b/lib/ledgerizer/definition/entry.rb index a892fb1..498c925 100644 --- a/lib/ledgerizer/definition/entry.rb +++ b/lib/ledgerizer/definition/entry.rb @@ -22,9 +22,7 @@ def find_movement(movement_type:, account_name:, accountable:) end def add_movement(movement_type:, account:, accountable:) - ar_accountable = format_to_symbol_identifier(accountable) - validate_active_record_model_name!(ar_accountable, "accountable") - validate_unique_account!(movement_type, account.name, ar_accountable) + ar_accountable = find_ar_accountable(movement_type, account.name, accountable) Ledgerizer::Definition::Movement.new( account: account, @@ -41,6 +39,18 @@ def movements private + def find_ar_accountable(movement_type, account_name, accountable) + ar_accountable = nil + + if !accountable.blank? + ar_accountable = format_to_symbol_identifier(accountable) + validate_active_record_model_name!(ar_accountable, "accountable") + end + + validate_unique_account!(movement_type, account_name, ar_accountable) + ar_accountable + end + def infer_model_name(value) return format_model_to_sym(value) if value.is_a?(ActiveRecord::Base) diff --git a/lib/ledgerizer/definition/movement.rb b/lib/ledgerizer/definition/movement.rb index 2ee700e..d8124a7 100644 --- a/lib/ledgerizer/definition/movement.rb +++ b/lib/ledgerizer/definition/movement.rb @@ -12,12 +12,20 @@ class Movement def initialize(account:, accountable:, movement_type:) @account = account @movement_type = format_to_symbol_identifier(movement_type) - @accountable = format_to_symbol_identifier(accountable) + @accountable = format_to_symbol_identifier(accountable) if accountable end def accountable_class + return unless accountable + format_sym_to_model(accountable) end + + def accountable_string_class + return unless accountable + + accountable_class.to_s + end end end end diff --git a/lib/ledgerizer/execution/dsl.rb b/lib/ledgerizer/execution/dsl.rb index fb0f628..d17a921 100644 --- a/lib/ledgerizer/execution/dsl.rb +++ b/lib/ledgerizer/execution/dsl.rb @@ -38,7 +38,7 @@ def execute_entry(entry_code, tenant:, document:, date:, &block) @executor = nil end - def debit(account:, accountable:, amount:) + def debit(account:, amount:, accountable: nil) in_context do @executor.add_movement( movement_type: :debit, @@ -49,7 +49,7 @@ def debit(account:, accountable:, amount:) end end - def credit(account:, accountable:, amount:) + def credit(account:, amount:, accountable: nil) in_context do @executor.add_movement( movement_type: :credit, diff --git a/lib/ledgerizer/execution/entry.rb b/lib/ledgerizer/execution/entry.rb index 80d7d0f..6b37483 100644 --- a/lib/ledgerizer/execution/entry.rb +++ b/lib/ledgerizer/execution/entry.rb @@ -51,7 +51,7 @@ def for_each_grouped_by_accountable_and_currency_movement(entry, &block) groups = amounts_grouped_by_accountable_and_currency(entry, movement_definition) groups.each do |accountabe_data, amount_cents| accountable_id, currency = accountabe_data - accountable = movement_definition.accountable_class.find(accountable_id) + accountable = movement_definition.accountable_class&.find(accountable_id) block.call( accountable: accountable, @@ -75,7 +75,7 @@ def lines_by_movement_definition(entry, movement_definition) tenant: entry.tenant, entry_code: code, document: entry.document, - accountable_type: movement_definition.accountable_class.to_s, + accountable_type: movement_definition.accountable_string_class, account_name: movement_definition.account_name ) end @@ -89,7 +89,7 @@ def validate_entry_document!(document) end def get_movement_definition!(movement_type, account_name, accountable) - validate_active_record_instance!(accountable, "accountable") + validate_active_record_instance!(accountable, "accountable") if accountable movement_definition = entry_definition.find_movement( movement_type: movement_type, account_name: account_name, diff --git a/spec/dummy/spec/lib/execution/dsl_spec.rb b/spec/dummy/spec/lib/execution/dsl_spec.rb index 1a4d80f..711c8be 100644 --- a/spec/dummy/spec/lib/execution/dsl_spec.rb +++ b/spec/dummy/spec/lib/execution/dsl_spec.rb @@ -17,6 +17,11 @@ credit(account: :account2, accountable: :user) credit(account: :account3, accountable: :user) end + + entry(:entry3, document: :user) do + debit(account: :account1, accountable: :user) + credit(account: :account2) + end end end @@ -133,6 +138,45 @@ def perform it { expect(Ledgerizer::Entry.last).to have_ledger_line(credit_data) } end + context "with movement without accountable" do + let(:expected_entry) do + { + entry_code: :entry3, + entry_date: date, + document: document + } + end + + let(:debit_data) do + { + account: :account1, + accountable: create(:user), + amount: clp(1) + } + end + + let(:credit_data) do + { + account: :account2, + accountable: nil, + amount: clp(1) + } + end + + before do + LedgerizerTestExecution.new(debit: debit_data, credit: credit_data).execute_entry3_entry( + tenant: tenant, document: document, date: date + ) do + debit(data[:debit]) + credit(data[:credit]) + end + end + + it { expect(tenant).to have_ledger_entry(expected_entry) } + it { expect(Ledgerizer::Entry.last).to have_ledger_line(debit_data) } + it { expect(Ledgerizer::Entry.last).to have_ledger_line(credit_data) } + end + context "with multiple movements" do let(:expected_entry) do { diff --git a/spec/dummy/spec/models/ledgerizer/account_spec.rb b/spec/dummy/spec/models/ledgerizer/account_spec.rb index e99f10c..02adfc7 100644 --- a/spec/dummy/spec/models/ledgerizer/account_spec.rb +++ b/spec/dummy/spec/models/ledgerizer/account_spec.rb @@ -8,7 +8,7 @@ module Ledgerizer describe "associations" do it { is_expected.to belong_to(:tenant) } - it { is_expected.to belong_to(:accountable) } + it { is_expected.to belong_to(:accountable).optional } it { is_expected.to have_many(:lines).dependent(:destroy) } end diff --git a/spec/dummy/spec/support/shared_examples/definition_dsl_movement.rb b/spec/dummy/spec/support/shared_examples/definition_dsl_movement.rb index 1f301ac..dce6f9f 100644 --- a/spec/dummy/spec/support/shared_examples/definition_dsl_movement.rb +++ b/spec/dummy/spec/support/shared_examples/definition_dsl_movement.rb @@ -60,6 +60,30 @@ it { expect(LedgerizerTestDefinition).to have_ledger_movement_definition(expected) } end + context "with no accountable" do + let_definition_class do + tenant('portfolio') do + asset(:cash) + + entry(:deposit, document: :portfolio) do + send(type, account: :cash) + end + end + end + + let(:expected) do + { + tenant_class: :portfolio, + entry_code: :deposit, + movement_type: type, + account: :cash, + accountable: nil + } + end + + it { expect(LedgerizerTestDefinition).to have_ledger_movement_definition(expected) } + end + context "with multiple movements" do let_definition_class do tenant('portfolio') do