From 8720a51a514ad6490d80127fa38cff3de233dfd1 Mon Sep 17 00:00:00 2001 From: Enzo Date: Wed, 15 Jan 2025 21:22:35 +0100 Subject: [PATCH 1/4] chore(balance): add balance cache field to book_members --- .../20250115201824_add_book_members_balance.exs | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 apps/app/priv/repo/migrations/20250115201824_add_book_members_balance.exs diff --git a/apps/app/priv/repo/migrations/20250115201824_add_book_members_balance.exs b/apps/app/priv/repo/migrations/20250115201824_add_book_members_balance.exs new file mode 100644 index 00000000..04f941f1 --- /dev/null +++ b/apps/app/priv/repo/migrations/20250115201824_add_book_members_balance.exs @@ -0,0 +1,10 @@ +defmodule App.Repo.Migrations.AddBookMembersBalance do + use Ecto.Migration + + def change do + alter table("book_members") do + add :balance, :money_with_currency + add :balance_errors, :map, null: false, default: [] + end + end +end From a6a86f0ad3acdd2540ef4988ee7987636cca9d3c Mon Sep 17 00:00:00 2001 From: Enzo Date: Wed, 15 Jan 2025 22:31:42 +0100 Subject: [PATCH 2/4] chore(balance): add function to update the book members balance --- apps/app/lib/app/balance.ex | 33 ++++++++++ apps/app/test/app/balance_test.exs | 101 +++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+) diff --git a/apps/app/lib/app/balance.ex b/apps/app/lib/app/balance.ex index 6f0dbea1..73455574 100644 --- a/apps/app/lib/app/balance.ex +++ b/apps/app/lib/app/balance.ex @@ -12,6 +12,39 @@ defmodule App.Balance do alias App.Transfers alias App.Transfers.Peer + @doc """ + Compute the balance of book members and update it. + """ + @spec update_book_members_balance(Book.t()) :: :ok + def update_book_members_balance(%Book{} = book) do + members = + book + |> Members.list_members_of_book() + |> fill_members_balance() + + {:ok, _} = + Repo.transaction(fn -> + balance_error_fields = BalanceError.__schema__(:fields) + + for member <- members do + # TODO once the BookMember `:balance` field is not virtual anymore, + # create and use a change to update the balance. + {:ok, balance} = Money.Ecto.Composite.Type.dump(member.balance) + + "book_members" + |> where(id: ^member.id) + |> Repo.update_all( + set: [ + balance: balance, + balance_errors: Enum.map(member.balance_errors, &Map.take(&1, balance_error_fields)) + ] + ) + end + end) + + :ok + end + @doc """ Compute the `:balance` field of book members. """ diff --git a/apps/app/test/app/balance_test.exs b/apps/app/test/app/balance_test.exs index f2d4a5d0..8078d8e8 100644 --- a/apps/app/test/app/balance_test.exs +++ b/apps/app/test/app/balance_test.exs @@ -9,6 +9,107 @@ defmodule App.BalanceTest do alias App.Balance alias App.Balance.BalanceError + describe "update_book_members_balance/1" do + setup do + %{book: book_fixture()} + end + + test "updates the balance of the members of a book", %{book: book} do + member1 = book_member_fixture(book) + member2 = book_member_fixture(book, balance: Money.new!(:EUR, 10)) + + member3 = + book_member_fixture(book, + balance: Money.new!(:EUR, 0), + balance_errors: ["an error occured"] + ) + + member4 = book_member_fixture(book) + + money_transfer = + money_transfer_fixture(book, tenant_id: member1.id, amount: Money.new!(:EUR, 10)) + + _peer = peer_fixture(money_transfer, member_id: member1.id) + _peer = peer_fixture(money_transfer, member_id: member2.id) + _peer = peer_fixture(money_transfer, member_id: member3.id) + + Balance.update_book_members_balance(book) + + member1 = get_member_balance(member1.id) + assert member1.balance == Money.new!(:EUR, "6.67") + assert member1.balance_errors == [] + member2 = get_member_balance(member2.id) + assert member2.balance == Money.new!(:EUR, "-3.33") + assert member2.balance_errors == [] + member3 = get_member_balance(member3.id) + assert member3.balance == Money.new!(:EUR, "-3.34") + assert member3.balance_errors == [] + member4 = get_member_balance(member4.id) + assert member4.balance == Money.new!(:EUR, 0) + assert member4.balance_errors == [] + end + + test "sets the balance to 0 if there are no transfers", %{book: book} do + member1 = book_member_fixture(book) + member2 = book_member_fixture(book) + + Balance.update_book_members_balance(book) + + member1 = get_member_balance(member1.id) + assert member1.balance == Money.new!(:EUR, 0) + assert member1.balance_errors == [] + member2 = get_member_balance(member2.id) + assert member2.balance == Money.new!(:EUR, 0) + assert member2.balance_errors == [] + end + + test "sets the `:balance_errors` if an error occurs", %{book: book} do + member1 = book_member_fixture(book) + member2 = book_member_fixture(book) + + money_transfer = + money_transfer_fixture(book, + tenant_id: member1.id, + amount: Money.new!(:EUR, 10), + balance_means: :weight_by_revenues + ) + + _peer = peer_fixture(money_transfer, member_id: member1.id) + _peer = peer_fixture(money_transfer, member_id: member2.id) + + Balance.update_book_members_balance(book) + + expected_balance_errors = [ + %{"kind" => "revenues_missing", "extra" => %{"member_id" => member1.id}}, + %{"kind" => "revenues_missing", "extra" => %{"member_id" => member2.id}} + ] + + member1 = get_member_balance(member1.id) + assert member1.balance == Money.new!(:EUR, 0) + assert member1.balance_errors == expected_balance_errors + member2 = get_member_balance(member2.id) + assert member2.balance == Money.new!(:EUR, 0) + assert member2.balance_errors == expected_balance_errors + end + + # TODO once the BookMember `:balance` field is not virtual anymore, + # remove this request and use the BookMember fields directly + defp get_member_balance(member_id) do + from(book_member in "book_members", + where: book_member.id == ^member_id, + select: %{ + balance: book_member.balance, + balance_errors: book_member.balance_errors + } + ) + |> Repo.one!() + |> Map.update!(:balance, fn raw -> + {:ok, balance} = Money.Ecto.Composite.Type.load(raw) + balance + end) + end + end + describe "fill_members_balance/1" do setup do %{book: book_fixture()} From 9a0605c4726140cafdf276f989d18a52cdedd885 Mon Sep 17 00:00:00 2001 From: Enzo Date: Wed, 15 Jan 2025 22:15:18 +0100 Subject: [PATCH 3/4] chore(balance): add a cache updater worker --- apps/app/lib/app/balance.ex | 14 ++- .../lib/app/balance/cache_updater_worker.ex | 38 +++++++++ .../app/balance/cache_updater_worker_test.exs | 85 +++++++++++++++++++ apps/app/test/app/balance_test.exs | 10 +++ apps/app/test/support/data_case.ex | 2 + apps/app_web/test/support/conn_case.ex | 1 + config/runtime.exs | 2 +- 7 files changed, 149 insertions(+), 3 deletions(-) create mode 100644 apps/app/lib/app/balance/cache_updater_worker.ex create mode 100644 apps/app/test/app/balance/cache_updater_worker_test.exs diff --git a/apps/app/lib/app/balance.ex b/apps/app/lib/app/balance.ex index 73455574..727b4946 100644 --- a/apps/app/lib/app/balance.ex +++ b/apps/app/lib/app/balance.ex @@ -5,13 +5,23 @@ defmodule App.Balance do import Ecto.Query - alias App.Repo - alias App.Balance.BalanceError + alias App.Balance.CacheUpdaterWorker + alias App.Books.Book alias App.Books.BookMember + alias App.Books.Members + alias App.Repo alias App.Transfers alias App.Transfers.Peer + @doc """ + Schedule a job to immediately update the balance of the members of a book. + """ + @spec schedule_balance_update(Book.id()) :: Ecto.Multi.t() + def schedule_balance_update(book_id) when is_integer(book_id) do + CacheUpdaterWorker.update_book_balance(book_id) + end + @doc """ Compute the balance of book members and update it. """ diff --git a/apps/app/lib/app/balance/cache_updater_worker.ex b/apps/app/lib/app/balance/cache_updater_worker.ex new file mode 100644 index 00000000..ae5b887a --- /dev/null +++ b/apps/app/lib/app/balance/cache_updater_worker.ex @@ -0,0 +1,38 @@ +defmodule App.Balance.CacheUpdaterWorker do + @moduledoc """ + An Oban job that updates the balance of book members within a book. + """ + use Oban.Worker, + queue: :balance, + max_attempts: 1, + unique: [ + fields: [:args], + keys: [:book_id], + states: [:available, :scheduled, :executing, :retryable] + ] + + alias App.Balance + alias App.Books + alias App.Books.Book + + @doc """ + Create a new job to update the balance of book members. + + If a job is already scheduled for the book, it will be replaced. + """ + @spec update_book_balance(Book.id()) :: {:ok, Oban.Job.t()} | {:error, term()} + def update_book_balance(book_id) when is_integer(book_id) do + %{book_id: book_id} + |> new() + |> Oban.insert() + end + + @impl Oban.Worker + def perform(job) do + %{"book_id" => book_id} = job.args + + book_id + |> Books.get_book!() + |> Balance.update_book_members_balance() + end +end diff --git a/apps/app/test/app/balance/cache_updater_worker_test.exs b/apps/app/test/app/balance/cache_updater_worker_test.exs new file mode 100644 index 00000000..01d8fa00 --- /dev/null +++ b/apps/app/test/app/balance/cache_updater_worker_test.exs @@ -0,0 +1,85 @@ +defmodule App.Balance.CacheUpdaterWorkerTest do + use App.DataCase, async: true + + import App.Books.MembersFixtures + import App.BooksFixtures + import App.TransfersFixtures + + alias App.Balance.CacheUpdaterWorker + + describe "update_book_balance/1" do + test "creates an Oban job when the book_id" do + book_id = 123 + + {:ok, job} = CacheUpdaterWorker.update_book_balance(book_id) + assert job.queue == "balance" + assert job.args == %{book_id: book_id} + end + + test "overrides previous existing job" do + book_id = 123 + + {:ok, %{id: id}} = CacheUpdaterWorker.update_book_balance(book_id) + {:ok, %{id: ^id}} = CacheUpdaterWorker.update_book_balance(book_id) + + jobs = all_enqueued(worker: CacheUpdaterWorker) + assert length(jobs) == 1 + end + + test "does not override jobs with different book_id" do + book_id1 = 123 + book_id2 = 456 + + {:ok, %{id: id1}} = CacheUpdaterWorker.update_book_balance(book_id1) + {:ok, %{id: id2}} = CacheUpdaterWorker.update_book_balance(book_id2) + + assert id1 != id2 + + jobs = all_enqueued(worker: CacheUpdaterWorker) + assert length(jobs) == 2 + end + end + + describe "perform/1" do + test "updates the book members balance" do + book = book_fixture() + member1 = book_member_fixture(book) + member2 = book_member_fixture(book) + member3 = book_member_fixture(book) + + transfer = money_transfer_fixture(book, tenant_id: member1.id, amount: Money.new(:EUR, 333)) + _peer1 = peer_fixture(transfer, member_id: member1.id) + _peer2 = peer_fixture(transfer, member_id: member2.id) + _peer3 = peer_fixture(transfer, member_id: member3.id) + + perform_job(CacheUpdaterWorker, %{book_id: book.id}) + + member1 = get_member_balance(member1.id) + assert Money.equal?(member1.balance, Money.new(:EUR, 222)) + assert member1.balance_errors == [] + member2 = get_member_balance(member2.id) + assert Money.equal?(member2.balance, Money.new(:EUR, "-111.00")) + assert member2.balance_errors == [] + member3 = get_member_balance(member3.id) + assert Money.equal?(member3.balance, Money.new(:EUR, "-111.00")) + assert member3.balance_errors == [] + end + + # TODO once the BookMember `:balance` field is not virtual anymore, + # remove this request and use the BookMember fields directly + defp get_member_balance(member_id) do + from(book_member in "book_members", + where: book_member.id == ^member_id, + select: %{ + balance: book_member.balance, + balance_errors: book_member.balance_errors + } + ) + |> Repo.one!() + |> Map.update!(:balance, fn raw -> + {:ok, balance} = Money.Ecto.Composite.Type.load(raw) + balance + end) + end + end +end diff --git a/apps/app/test/app/balance_test.exs b/apps/app/test/app/balance_test.exs index 8078d8e8..3ca7e28a 100644 --- a/apps/app/test/app/balance_test.exs +++ b/apps/app/test/app/balance_test.exs @@ -9,6 +9,16 @@ defmodule App.BalanceTest do alias App.Balance alias App.Balance.BalanceError + describe "schedule_balance_update/1" do + test "creates an Oban job when the book_id" do + book_id = 123 + + {:ok, job} = Balance.schedule_balance_update(book_id) + assert job.queue == "balance" + assert job.args == %{book_id: book_id} + end + end + describe "update_book_members_balance/1" do setup do %{book: book_fixture()} diff --git a/apps/app/test/support/data_case.ex b/apps/app/test/support/data_case.ex index 2aabc76c..3d6102c1 100644 --- a/apps/app/test/support/data_case.ex +++ b/apps/app/test/support/data_case.ex @@ -20,6 +20,8 @@ defmodule App.DataCase do using do quote do + use Oban.Testing, repo: App.Repo + alias App.Repo import Ecto diff --git a/apps/app_web/test/support/conn_case.ex b/apps/app_web/test/support/conn_case.ex index 15f07ca2..326b2952 100644 --- a/apps/app_web/test/support/conn_case.ex +++ b/apps/app_web/test/support/conn_case.ex @@ -23,6 +23,7 @@ defmodule AppWeb.ConnCase do @endpoint AppWeb.Endpoint use AppWeb, :verified_routes + use Oban.Testing, repo: App.Repo # Import conveniences for testing with connections import Plug.Conn diff --git a/config/runtime.exs b/config/runtime.exs index 1dc40022..6378b19c 100644 --- a/config/runtime.exs +++ b/config/runtime.exs @@ -102,7 +102,7 @@ end config :app, Oban, engine: Oban.Engines.Basic, repo: App.Repo, - queues: [default: 10], + queues: [balance: 10], plugins: [ {Oban.Plugins.Pruner, max_age: 60 * 60 * 24 * 30}, {Oban.Plugins.Lifeline, rescue_after: to_timeout(minute: 30)} From a4df12e0ced33ee251fd6fc45565bfc5a66272bb Mon Sep 17 00:00:00 2001 From: Enzo Date: Fri, 17 Jan 2025 21:57:22 +0100 Subject: [PATCH 4/4] chore(balance): schedule a balance update when necessary --- apps/app/lib/app/balance/balance_configs.ex | 19 ++++-- apps/app/lib/app/transfers.ex | 59 +++++++++++++++---- .../test/app/balance/balance_configs_test.exs | 27 +++++++++ apps/app/test/app/transfers_test.exs | 52 +++++++++++++++- .../book_member_revenues_transfers_live.ex | 4 +- .../live/books/book_transfer_form_live.ex | 7 ++- 6 files changed, 145 insertions(+), 23 deletions(-) diff --git a/apps/app/lib/app/balance/balance_configs.ex b/apps/app/lib/app/balance/balance_configs.ex index f1fad1c7..3cb527f6 100644 --- a/apps/app/lib/app/balance/balance_configs.ex +++ b/apps/app/lib/app/balance/balance_configs.ex @@ -7,6 +7,7 @@ defmodule App.Balance.BalanceConfigs do import Ecto.Query alias App.Accounts.User + alias App.Balance alias App.Balance.BalanceConfig alias App.Books.BookMember alias App.Repo @@ -85,13 +86,21 @@ defmodule App.Balance.BalanceConfigs do @doc """ Link a balance configuration to a list of peers. """ - @spec link_balance_config_to_peers(BalanceConfig.t(), [Peer.t()]) :: :ok - def link_balance_config_to_peers(%BalanceConfig{} = balance_config, peers) do + @spec link_balance_config_to_peers(BalanceConfig.t(), [Peer.t()], Book.t()) :: :ok + def link_balance_config_to_peers(%BalanceConfig{} = balance_config, peers, book) do peer_ids = Enum.map(peers, & &1.id) - {_, nil} = - from([peer: peer] in Peer.base_query(), where: peer.id in ^peer_ids) - |> Repo.update_all(set: [balance_config_id: balance_config.id]) + {:ok, _changes} = + Ecto.Multi.new() + |> Ecto.Multi.update_all( + :peers, + from([peer: peer] in Peer.base_query(), where: peer.id in ^peer_ids), + set: [balance_config_id: balance_config.id] + ) + |> Ecto.Multi.run(:balance_job, fn _repo, _changes -> + Balance.schedule_balance_update(book.id) + end) + |> Repo.transaction() :ok end diff --git a/apps/app/lib/app/transfers.ex b/apps/app/lib/app/transfers.ex index 0362d88d..77f2bc51 100644 --- a/apps/app/lib/app/transfers.ex +++ b/apps/app/lib/app/transfers.ex @@ -5,6 +5,7 @@ defmodule App.Transfers do import Ecto.Query + alias App.Balance alias App.Books.Book alias App.Books.BookMember alias App.Repo @@ -173,6 +174,9 @@ defmodule App.Transfers do end, [] ) + |> Ecto.Multi.run(:balance_job, fn _repo, _changes -> + Balance.schedule_balance_update(book.id) + end) |> Repo.transaction() case result do @@ -187,9 +191,18 @@ defmodule App.Transfers do @spec update_money_transfer(MoneyTransfer.t(), map()) :: {:ok, MoneyTransfer.t()} | {:error, Ecto.Changeset.t()} def update_money_transfer(%MoneyTransfer{} = money_transfer, attrs) do - money_transfer - |> MoneyTransfer.changeset(attrs) - |> Repo.update() + result = + Ecto.Multi.new() + |> Ecto.Multi.update(:money_transfer, MoneyTransfer.changeset(money_transfer, attrs)) + |> Ecto.Multi.run(:balance_job, fn _repo, _changes -> + Balance.schedule_balance_update(money_transfer.book_id) + end) + |> Repo.transaction() + + case result do + {:ok, %{money_transfer: money_transfer}} -> {:ok, money_transfer} + {:error, :money_transfer, changeset, _changes} -> {:error, changeset} + end end @doc """ @@ -198,7 +211,18 @@ defmodule App.Transfers do @spec delete_money_transfer(MoneyTransfer.t()) :: {:ok, MoneyTransfer.t()} | {:error, Ecto.Changeset.t()} def delete_money_transfer(%MoneyTransfer{} = money_transfer) do - Repo.delete(money_transfer) + result = + Ecto.Multi.new() + |> Ecto.Multi.delete(:money_transfer, money_transfer) + |> Ecto.Multi.run(:balance_job, fn _repo, _changes -> + Balance.schedule_balance_update(money_transfer.book_id) + end) + |> Repo.transaction() + + case result do + {:ok, %{money_transfer: money_transfer}} -> {:ok, money_transfer} + {:error, :money_transfer, changeset, _changes} -> {:error, changeset} + end end @doc """ @@ -216,13 +240,26 @@ defmodule App.Transfers do @spec create_reimbursement(Book.t(), map()) :: {:ok, MoneyTransfer.t()} | {:error, Ecto.Changeset.t()} def create_reimbursement(%Book{} = book, attrs) do - %MoneyTransfer{ - book_id: book.id, - type: :reimbursement, - balance_means: :divide_equally - } - |> MoneyTransfer.reimbursement_changeset(attrs) - |> Repo.insert() + changeset = + %MoneyTransfer{ + book_id: book.id, + type: :reimbursement, + balance_means: :divide_equally + } + |> MoneyTransfer.reimbursement_changeset(attrs) + + result = + Ecto.Multi.new() + |> Ecto.Multi.insert(:reimbursement, changeset) + |> Ecto.Multi.run(:abalnce_job, fn _repo, _changes -> + Balance.schedule_balance_update(book.id) + end) + |> Repo.transaction() + + case result do + {:ok, %{reimbursement: reimbursement}} -> {:ok, reimbursement} + {:error, :reimbursement, changeset, _changes} -> {:error, changeset} + end end @doc """ diff --git a/apps/app/test/app/balance/balance_configs_test.exs b/apps/app/test/app/balance/balance_configs_test.exs index 14c7d866..1eac27d1 100644 --- a/apps/app/test/app/balance/balance_configs_test.exs +++ b/apps/app/test/app/balance/balance_configs_test.exs @@ -8,6 +8,7 @@ defmodule App.Balance.BalanceConfigsTest do import App.TransfersFixtures alias App.Balance.BalanceConfigs + alias App.Balance.CacheUpdaterWorker describe "get_balance_config_of_member/1" do test "returns the balance config of the member" do @@ -112,6 +113,32 @@ defmodule App.Balance.BalanceConfigsTest do end end + describe "link_balance_config_to_peers/3" do + test "links a balance config to the given peers" do + balance_config = balance_config_fixture() + book = book_fixture() + member = book_member_fixture(book) + transfer = money_transfer_fixture(book, tenant_id: member.id) + peer = peer_fixture(transfer, member_id: member.id) + + :ok = BalanceConfigs.link_balance_config_to_peers(balance_config, [peer], book) + + assert Repo.reload!(peer).balance_config_id == balance_config.id + end + + test "schedules a job to update the book members balance" do + balance_config = balance_config_fixture() + book = book_fixture() + member = book_member_fixture(book) + transfer = money_transfer_fixture(book, tenant_id: member.id) + peer = peer_fixture(transfer, member_id: member.id) + + :ok = BalanceConfigs.link_balance_config_to_peers(balance_config, [peer], book) + + assert_enqueued(worker: CacheUpdaterWorker, args: %{book_id: book.id}) + end + end + describe "change_balance_config_revenues/2" do setup do %{balance_config: balance_config_fixture()} diff --git a/apps/app/test/app/transfers_test.exs b/apps/app/test/app/transfers_test.exs index 5a617297..1c3509b8 100644 --- a/apps/app/test/app/transfers_test.exs +++ b/apps/app/test/app/transfers_test.exs @@ -7,10 +7,10 @@ defmodule App.TransfersTest do import App.BooksFixtures import App.TransfersFixtures - alias App.Repo - + alias App.Balance.CacheUpdaterWorker alias App.Books.Book alias App.Books.BookMember + alias App.Repo alias App.Transfers alias App.Transfers.MoneyTransfer alias App.Transfers.Peer @@ -247,6 +247,18 @@ defmodule App.TransfersTest do assert Enum.empty?(transfer.peers) end + test "schedules a job to update the book balance", %{book: book, member: member} do + {:ok, _transfer} = + Transfers.create_money_transfer( + book, + member, + :payment, + money_transfer_attributes(tenant_id: member.id) + ) + + assert_enqueued(worker: CacheUpdaterWorker, args: %{book_id: book.id}) + end + test "sets balance means", %{book: book, member: member} do assert {:ok, transfer} = Transfers.create_money_transfer( @@ -393,6 +405,16 @@ defmodule App.TransfersTest do assert peer.member_id == other_member.id end + test "schedules a job to update the book balance", %{ + book: book, + money_transfer: money_transfer + } do + assert {:ok, _updated} = + Transfers.update_money_transfer(money_transfer, %{}) + + assert_enqueued(worker: CacheUpdaterWorker, args: %{book_id: book.id}) + end + test "does not update book", %{book: book, money_transfer: money_transfer} do other_book = book_fixture() @@ -458,6 +480,15 @@ defmodule App.TransfersTest do assert deleted_transfer.id == money_transfer.id end + test "schedules a job to update the book balance", %{ + book: book, + money_transfer: money_transfer + } do + assert {:ok, _deleted_transfer} = Transfers.delete_money_transfer(money_transfer) + + assert_enqueued(worker: CacheUpdaterWorker, args: %{book_id: book.id}) + end + test "deleted related peers", %{book: book, member: member} do money_transfer = money_transfer_fixture(book, tenant_id: member.id) _peer = peer_fixture(money_transfer, member_id: member.id) @@ -495,6 +526,23 @@ defmodule App.TransfersTest do assert money_transfer.balance_means == :divide_equally end + test "schedules a job to update the book balance", %{ + book: book, + member1: member1, + member2: member2 + } do + {:ok, _transfer} = + Transfers.create_reimbursement( + book, + money_transfer_attributes( + tenant_id: member1.id, + peers: [%{member_id: member2.id}] + ) + ) + + assert_enqueued(worker: CacheUpdaterWorker, args: %{book_id: book.id}) + end + test "cannot create a payment or an income", %{book: book, member1: member1, member2: member2} do assert {:ok, money_transfer} = Transfers.create_reimbursement( diff --git a/apps/app_web/lib/app_web/live/books/book_member_revenues_transfers_live.ex b/apps/app_web/lib/app_web/live/books/book_member_revenues_transfers_live.ex index 96e95266..33f0951f 100644 --- a/apps/app_web/lib/app_web/live/books/book_member_revenues_transfers_live.ex +++ b/apps/app_web/lib/app_web/live/books/book_member_revenues_transfers_live.ex @@ -153,13 +153,13 @@ defmodule AppWeb.BookMemberRevenuesTransfersLive do @impl Phoenix.LiveView def handle_event("submit", params, socket) do - book_member = socket.assigns.book_member + %{book: book, book_member: book_member} = socket.assigns peer_ids = Map.get(params, "peer_ids", []) peers = list_peers_of_member(peer_ids, book_member) balance_config = BalanceConfigs.get_balance_config_of_member(book_member) - :ok = BalanceConfigs.link_balance_config_to_peers(balance_config, peers) + :ok = BalanceConfigs.link_balance_config_to_peers(balance_config, peers, book) redirect_path = redirect_path(book_member, socket.assigns.live_action) {:noreply, push_navigate(socket, to: redirect_path)} diff --git a/apps/app_web/lib/app_web/live/books/book_transfer_form_live.ex b/apps/app_web/lib/app_web/live/books/book_transfer_form_live.ex index 6d953f47..6ebaa36a 100644 --- a/apps/app_web/lib/app_web/live/books/book_transfer_form_live.ex +++ b/apps/app_web/lib/app_web/live/books/book_transfer_form_live.ex @@ -321,12 +321,13 @@ defmodule AppWeb.BookTransferFormLive do select: struct(money_transfer, [ :id, - :type, :label, + :amount, + :type, :date, - :balance_means, + :book_id, :tenant_id, - :amount, + :balance_means, peers: [ :id, :member_id,