Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions robosystems_client/clients/ledger_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -2043,6 +2043,8 @@ def create_journal_entry(
source: str = "manual",
idempotency_key: str | None = None,
entity_id: str | None = None,
adjustment_kind: str | None = None,
adjusts_entity_id: str | None = None,
) -> EventBlockEnvelope:
"""Create a journal entry with balanced line items (DR=CR enforced).

Expand All @@ -2065,6 +2067,13 @@ def create_journal_entry(
``entity_id`` names the entity whose books the entry goes into; omitted,
the group parent's.

``adjustment_kind`` tags a consolidating entry in the group's
consolidation entity (``elimination_intercompany``, ``manual``, ...), with
``adjusts_entity_id`` the entity whose figures it adjusts (required for
every kind but ``manual``). Only that entity's books take one; the
consolidation engine counts a tagged entry toward what it already holds,
so an elimination posted by hand is not proposed again.

A line dict may carry ``flow_qname``, the cash flow row its cash belongs
to (a ``qname`` from ``get_flow_candidates``): only for a loan drawn or
repaid, capital put in or taken out, an asset bought or sold. A flow on
Expand All @@ -2082,6 +2091,10 @@ def create_journal_entry(
}
if transaction_id is not None:
metadata["transaction_id"] = transaction_id
if adjustment_kind is not None:
metadata["adjustment_kind"] = adjustment_kind
if adjusts_entity_id is not None:
metadata["adjusts_entity_id"] = adjusts_entity_id
body = self._build_event_block_request(
event_type="journal_entry_recorded",
event_category="adjustment",
Expand Down
32 changes: 32 additions & 0 deletions tests/test_ledger_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -809,6 +809,38 @@ def test_create_journal_entry_names_its_entity(self, mock_op, mock_config, graph
)
assert mock_op.call_args.kwargs["body"].entity_id == "ent_sub"

@patch("robosystems_client.clients.ledger_client.op_create_event_block")
def test_create_journal_entry_tags_a_consolidating_entry(
self, mock_op, mock_config, graph_id
):
mock_op.return_value = _mock_response(_envelope("create-event-block", {}))
client = LedgerClient(mock_config)
client.create_journal_entry(
graph_id,
posting_date="2026-07-31",
memo="Intercompany receivable",
line_items=self._LINE_ITEMS,
entity_id="ent_cons",
adjustment_kind="elimination_intercompany",
adjusts_entity_id="ent_sub",
)
metadata = mock_op.call_args.kwargs["body"].metadata.to_dict()
assert metadata["adjustment_kind"] == "elimination_intercompany"
assert metadata["adjusts_entity_id"] == "ent_sub"

@patch("robosystems_client.clients.ledger_client.op_create_event_block")
def test_create_journal_entry_sends_no_consolidating_tags_unasked(
self, mock_op, mock_config, graph_id
):
mock_op.return_value = _mock_response(_envelope("create-event-block", {}))
client = LedgerClient(mock_config)
client.create_journal_entry(
graph_id, posting_date="2026-03-31", memo="X", line_items=self._LINE_ITEMS
)
metadata = mock_op.call_args.kwargs["body"].metadata.to_dict()
assert "adjustment_kind" not in metadata
assert "adjusts_entity_id" not in metadata

@patch("robosystems_client.clients.ledger_client.op_create_event_block")
def test_create_journal_entry_leaves_the_entity_to_the_server(
self, mock_op, mock_config, graph_id
Expand Down
Loading