diff --git a/robosystems_client/api/robo_ledger_analytical_views/preview_consolidation_entries.py b/robosystems_client/api/robo_ledger_analytical_views/preview_consolidation_entries.py new file mode 100644 index 0000000..89caa73 --- /dev/null +++ b/robosystems_client/api/robo_ledger_analytical_views/preview_consolidation_entries.py @@ -0,0 +1,306 @@ +from http import HTTPStatus +from typing import Any +from urllib.parse import quote + +import httpx + +from ... import errors +from ...client import AuthenticatedClient, Client +from ...models.error_response import ErrorResponse +from ...models.operation_envelope_preview_consolidation_entries_response import ( + OperationEnvelopePreviewConsolidationEntriesResponse, +) +from ...models.preview_consolidation_entries_request import ( + PreviewConsolidationEntriesRequest, +) +from ...types import UNSET, Response, Unset + + +def _get_kwargs( + graph_id: str, + *, + body: PreviewConsolidationEntriesRequest, + idempotency_key: None | str | Unset = UNSET, +) -> dict[str, Any]: + headers: dict[str, Any] = {} + if not isinstance(idempotency_key, Unset): + headers["Idempotency-Key"] = idempotency_key + + _kwargs: dict[str, Any] = { + "method": "post", + "url": "/extensions/roboledger/{graph_id}/operations/preview-consolidation-entries".format( + graph_id=quote(str(graph_id), safe=""), + ), + } + + _kwargs["json"] = body.to_dict() + + headers["Content-Type"] = "application/json" + + _kwargs["headers"] = headers + return _kwargs + + +def _parse_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> ErrorResponse | OperationEnvelopePreviewConsolidationEntriesResponse | None: + if response.status_code == 200: + response_200 = OperationEnvelopePreviewConsolidationEntriesResponse.from_dict( + response.json() + ) + + return response_200 + + if response.status_code == 400: + response_400 = ErrorResponse.from_dict(response.json()) + + return response_400 + + if response.status_code == 401: + response_401 = ErrorResponse.from_dict(response.json()) + + return response_401 + + if response.status_code == 403: + response_403 = ErrorResponse.from_dict(response.json()) + + return response_403 + + if response.status_code == 404: + response_404 = ErrorResponse.from_dict(response.json()) + + return response_404 + + if response.status_code == 409: + response_409 = ErrorResponse.from_dict(response.json()) + + return response_409 + + if response.status_code == 422: + response_422 = ErrorResponse.from_dict(response.json()) + + return response_422 + + if response.status_code == 429: + response_429 = ErrorResponse.from_dict(response.json()) + + return response_429 + + if response.status_code == 500: + response_500 = ErrorResponse.from_dict(response.json()) + + return response_500 + + if client.raise_on_unexpected_status: + raise errors.UnexpectedStatus(response.status_code, response.content) + else: + return None + + +def _build_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> Response[ErrorResponse | OperationEnvelopePreviewConsolidationEntriesResponse]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + graph_id: str, + *, + client: AuthenticatedClient, + body: PreviewConsolidationEntriesRequest, + idempotency_key: None | str | Unset = UNSET, +) -> Response[ErrorResponse | OperationEnvelopePreviewConsolidationEntriesResponse]: + """Preview Consolidation Entries + + The consolidating entries a group's month needs, computed from the books and posting nothing. For + each member consolidated in full: the parent's investment eliminated against the member's capital + (its contributions net of distributions), the outside owners' share of that capital as + noncontrolling interest, the intercompany balances, the month's intercompany income against the + matching expense, and the outside owners' share of the month's result; for each member on the equity + method, the parent's share of its result. Accounts are found by the rs-gaap concept they map to, and + an intercompany line by the group entity its event names as counterparty. Each entry is the + difference between the balance its kind should hold for the member at the month end and what the + consolidation entity already holds, so the entries a person posted with the same kind count. A + difference between the parent's investment and its share of a member's capital is returned as a + residual and its entry withheld, never plugged; intercompany figures the two sides do not agree on + are returned as reconciling items. Rejected on shared-repository graphs. + + **Idempotency**: supply an `Idempotency-Key` header to make safe retries; replays within 24 hours + return the same envelope. Reusing the key with a different body returns HTTP 409 Conflict. + + Args: + graph_id (str): + idempotency_key (None | str | Unset): + body (PreviewConsolidationEntriesRequest): The month to compute the consolidating entries + for. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorResponse | OperationEnvelopePreviewConsolidationEntriesResponse] + """ + + kwargs = _get_kwargs( + graph_id=graph_id, + body=body, + idempotency_key=idempotency_key, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + graph_id: str, + *, + client: AuthenticatedClient, + body: PreviewConsolidationEntriesRequest, + idempotency_key: None | str | Unset = UNSET, +) -> ErrorResponse | OperationEnvelopePreviewConsolidationEntriesResponse | None: + """Preview Consolidation Entries + + The consolidating entries a group's month needs, computed from the books and posting nothing. For + each member consolidated in full: the parent's investment eliminated against the member's capital + (its contributions net of distributions), the outside owners' share of that capital as + noncontrolling interest, the intercompany balances, the month's intercompany income against the + matching expense, and the outside owners' share of the month's result; for each member on the equity + method, the parent's share of its result. Accounts are found by the rs-gaap concept they map to, and + an intercompany line by the group entity its event names as counterparty. Each entry is the + difference between the balance its kind should hold for the member at the month end and what the + consolidation entity already holds, so the entries a person posted with the same kind count. A + difference between the parent's investment and its share of a member's capital is returned as a + residual and its entry withheld, never plugged; intercompany figures the two sides do not agree on + are returned as reconciling items. Rejected on shared-repository graphs. + + **Idempotency**: supply an `Idempotency-Key` header to make safe retries; replays within 24 hours + return the same envelope. Reusing the key with a different body returns HTTP 409 Conflict. + + Args: + graph_id (str): + idempotency_key (None | str | Unset): + body (PreviewConsolidationEntriesRequest): The month to compute the consolidating entries + for. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorResponse | OperationEnvelopePreviewConsolidationEntriesResponse + """ + + return sync_detailed( + graph_id=graph_id, + client=client, + body=body, + idempotency_key=idempotency_key, + ).parsed + + +async def asyncio_detailed( + graph_id: str, + *, + client: AuthenticatedClient, + body: PreviewConsolidationEntriesRequest, + idempotency_key: None | str | Unset = UNSET, +) -> Response[ErrorResponse | OperationEnvelopePreviewConsolidationEntriesResponse]: + """Preview Consolidation Entries + + The consolidating entries a group's month needs, computed from the books and posting nothing. For + each member consolidated in full: the parent's investment eliminated against the member's capital + (its contributions net of distributions), the outside owners' share of that capital as + noncontrolling interest, the intercompany balances, the month's intercompany income against the + matching expense, and the outside owners' share of the month's result; for each member on the equity + method, the parent's share of its result. Accounts are found by the rs-gaap concept they map to, and + an intercompany line by the group entity its event names as counterparty. Each entry is the + difference between the balance its kind should hold for the member at the month end and what the + consolidation entity already holds, so the entries a person posted with the same kind count. A + difference between the parent's investment and its share of a member's capital is returned as a + residual and its entry withheld, never plugged; intercompany figures the two sides do not agree on + are returned as reconciling items. Rejected on shared-repository graphs. + + **Idempotency**: supply an `Idempotency-Key` header to make safe retries; replays within 24 hours + return the same envelope. Reusing the key with a different body returns HTTP 409 Conflict. + + Args: + graph_id (str): + idempotency_key (None | str | Unset): + body (PreviewConsolidationEntriesRequest): The month to compute the consolidating entries + for. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorResponse | OperationEnvelopePreviewConsolidationEntriesResponse] + """ + + kwargs = _get_kwargs( + graph_id=graph_id, + body=body, + idempotency_key=idempotency_key, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + graph_id: str, + *, + client: AuthenticatedClient, + body: PreviewConsolidationEntriesRequest, + idempotency_key: None | str | Unset = UNSET, +) -> ErrorResponse | OperationEnvelopePreviewConsolidationEntriesResponse | None: + """Preview Consolidation Entries + + The consolidating entries a group's month needs, computed from the books and posting nothing. For + each member consolidated in full: the parent's investment eliminated against the member's capital + (its contributions net of distributions), the outside owners' share of that capital as + noncontrolling interest, the intercompany balances, the month's intercompany income against the + matching expense, and the outside owners' share of the month's result; for each member on the equity + method, the parent's share of its result. Accounts are found by the rs-gaap concept they map to, and + an intercompany line by the group entity its event names as counterparty. Each entry is the + difference between the balance its kind should hold for the member at the month end and what the + consolidation entity already holds, so the entries a person posted with the same kind count. A + difference between the parent's investment and its share of a member's capital is returned as a + residual and its entry withheld, never plugged; intercompany figures the two sides do not agree on + are returned as reconciling items. Rejected on shared-repository graphs. + + **Idempotency**: supply an `Idempotency-Key` header to make safe retries; replays within 24 hours + return the same envelope. Reusing the key with a different body returns HTTP 409 Conflict. + + Args: + graph_id (str): + idempotency_key (None | str | Unset): + body (PreviewConsolidationEntriesRequest): The month to compute the consolidating entries + for. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorResponse | OperationEnvelopePreviewConsolidationEntriesResponse + """ + + return ( + await asyncio_detailed( + graph_id=graph_id, + client=client, + body=body, + idempotency_key=idempotency_key, + ) + ).parsed diff --git a/robosystems_client/api/robo_ledger_ledger_events/propose_consolidation_entries.py b/robosystems_client/api/robo_ledger_ledger_events/propose_consolidation_entries.py new file mode 100644 index 0000000..9bcc67f --- /dev/null +++ b/robosystems_client/api/robo_ledger_ledger_events/propose_consolidation_entries.py @@ -0,0 +1,282 @@ +from http import HTTPStatus +from typing import Any +from urllib.parse import quote + +import httpx + +from ... import errors +from ...client import AuthenticatedClient, Client +from ...models.error_response import ErrorResponse +from ...models.operation_envelope_propose_consolidation_entries_response import ( + OperationEnvelopeProposeConsolidationEntriesResponse, +) +from ...models.propose_consolidation_entries_request import ( + ProposeConsolidationEntriesRequest, +) +from ...types import UNSET, Response, Unset + + +def _get_kwargs( + graph_id: str, + *, + body: ProposeConsolidationEntriesRequest, + idempotency_key: None | str | Unset = UNSET, +) -> dict[str, Any]: + headers: dict[str, Any] = {} + if not isinstance(idempotency_key, Unset): + headers["Idempotency-Key"] = idempotency_key + + _kwargs: dict[str, Any] = { + "method": "post", + "url": "/extensions/roboledger/{graph_id}/operations/propose-consolidation-entries".format( + graph_id=quote(str(graph_id), safe=""), + ), + } + + _kwargs["json"] = body.to_dict() + + headers["Content-Type"] = "application/json" + + _kwargs["headers"] = headers + return _kwargs + + +def _parse_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> ErrorResponse | OperationEnvelopeProposeConsolidationEntriesResponse | None: + if response.status_code == 200: + response_200 = OperationEnvelopeProposeConsolidationEntriesResponse.from_dict( + response.json() + ) + + return response_200 + + if response.status_code == 400: + response_400 = ErrorResponse.from_dict(response.json()) + + return response_400 + + if response.status_code == 401: + response_401 = ErrorResponse.from_dict(response.json()) + + return response_401 + + if response.status_code == 403: + response_403 = ErrorResponse.from_dict(response.json()) + + return response_403 + + if response.status_code == 404: + response_404 = ErrorResponse.from_dict(response.json()) + + return response_404 + + if response.status_code == 409: + response_409 = ErrorResponse.from_dict(response.json()) + + return response_409 + + if response.status_code == 422: + response_422 = ErrorResponse.from_dict(response.json()) + + return response_422 + + if response.status_code == 429: + response_429 = ErrorResponse.from_dict(response.json()) + + return response_429 + + if response.status_code == 500: + response_500 = ErrorResponse.from_dict(response.json()) + + return response_500 + + if client.raise_on_unexpected_status: + raise errors.UnexpectedStatus(response.status_code, response.content) + else: + return None + + +def _build_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> Response[ErrorResponse | OperationEnvelopeProposeConsolidationEntriesResponse]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + graph_id: str, + *, + client: AuthenticatedClient, + body: ProposeConsolidationEntriesRequest, + idempotency_key: None | str | Unset = UNSET, +) -> Response[ErrorResponse | OperationEnvelopeProposeConsolidationEntriesResponse]: + """Propose Consolidation Entries + + Draft a month's consolidating entries in the group's consolidation entity: what preview- + consolidation-entries computes, written as drafts that the consolidation entity's close posts. + Proposing the month again replaces the drafts it wrote before, so it can be run after any member's + books change; a person's own entries are never touched. Lines that eliminate a cash flow carry the + row they offset. A residual or a disagreement is returned beside the drafts, never plugged; a month + the consolidation entity has closed is left as posted. + + **Idempotency**: supply an `Idempotency-Key` header to make safe retries; replays within 24 hours + return the same envelope. Reusing the key with a different body returns HTTP 409 Conflict. + + Args: + graph_id (str): + idempotency_key (None | str | Unset): + body (ProposeConsolidationEntriesRequest): The month to draft the consolidating entries + for. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorResponse | OperationEnvelopeProposeConsolidationEntriesResponse] + """ + + kwargs = _get_kwargs( + graph_id=graph_id, + body=body, + idempotency_key=idempotency_key, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + graph_id: str, + *, + client: AuthenticatedClient, + body: ProposeConsolidationEntriesRequest, + idempotency_key: None | str | Unset = UNSET, +) -> ErrorResponse | OperationEnvelopeProposeConsolidationEntriesResponse | None: + """Propose Consolidation Entries + + Draft a month's consolidating entries in the group's consolidation entity: what preview- + consolidation-entries computes, written as drafts that the consolidation entity's close posts. + Proposing the month again replaces the drafts it wrote before, so it can be run after any member's + books change; a person's own entries are never touched. Lines that eliminate a cash flow carry the + row they offset. A residual or a disagreement is returned beside the drafts, never plugged; a month + the consolidation entity has closed is left as posted. + + **Idempotency**: supply an `Idempotency-Key` header to make safe retries; replays within 24 hours + return the same envelope. Reusing the key with a different body returns HTTP 409 Conflict. + + Args: + graph_id (str): + idempotency_key (None | str | Unset): + body (ProposeConsolidationEntriesRequest): The month to draft the consolidating entries + for. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorResponse | OperationEnvelopeProposeConsolidationEntriesResponse + """ + + return sync_detailed( + graph_id=graph_id, + client=client, + body=body, + idempotency_key=idempotency_key, + ).parsed + + +async def asyncio_detailed( + graph_id: str, + *, + client: AuthenticatedClient, + body: ProposeConsolidationEntriesRequest, + idempotency_key: None | str | Unset = UNSET, +) -> Response[ErrorResponse | OperationEnvelopeProposeConsolidationEntriesResponse]: + """Propose Consolidation Entries + + Draft a month's consolidating entries in the group's consolidation entity: what preview- + consolidation-entries computes, written as drafts that the consolidation entity's close posts. + Proposing the month again replaces the drafts it wrote before, so it can be run after any member's + books change; a person's own entries are never touched. Lines that eliminate a cash flow carry the + row they offset. A residual or a disagreement is returned beside the drafts, never plugged; a month + the consolidation entity has closed is left as posted. + + **Idempotency**: supply an `Idempotency-Key` header to make safe retries; replays within 24 hours + return the same envelope. Reusing the key with a different body returns HTTP 409 Conflict. + + Args: + graph_id (str): + idempotency_key (None | str | Unset): + body (ProposeConsolidationEntriesRequest): The month to draft the consolidating entries + for. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorResponse | OperationEnvelopeProposeConsolidationEntriesResponse] + """ + + kwargs = _get_kwargs( + graph_id=graph_id, + body=body, + idempotency_key=idempotency_key, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + graph_id: str, + *, + client: AuthenticatedClient, + body: ProposeConsolidationEntriesRequest, + idempotency_key: None | str | Unset = UNSET, +) -> ErrorResponse | OperationEnvelopeProposeConsolidationEntriesResponse | None: + """Propose Consolidation Entries + + Draft a month's consolidating entries in the group's consolidation entity: what preview- + consolidation-entries computes, written as drafts that the consolidation entity's close posts. + Proposing the month again replaces the drafts it wrote before, so it can be run after any member's + books change; a person's own entries are never touched. Lines that eliminate a cash flow carry the + row they offset. A residual or a disagreement is returned beside the drafts, never plugged; a month + the consolidation entity has closed is left as posted. + + **Idempotency**: supply an `Idempotency-Key` header to make safe retries; replays within 24 hours + return the same envelope. Reusing the key with a different body returns HTTP 409 Conflict. + + Args: + graph_id (str): + idempotency_key (None | str | Unset): + body (ProposeConsolidationEntriesRequest): The month to draft the consolidating entries + for. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorResponse | OperationEnvelopeProposeConsolidationEntriesResponse + """ + + return ( + await asyncio_detailed( + graph_id=graph_id, + client=client, + body=body, + idempotency_key=idempotency_key, + ) + ).parsed diff --git a/robosystems_client/api/robo_ledger_ledger_events/set_allocation_override.py b/robosystems_client/api/robo_ledger_ledger_events/set_allocation_override.py new file mode 100644 index 0000000..12d85df --- /dev/null +++ b/robosystems_client/api/robo_ledger_ledger_events/set_allocation_override.py @@ -0,0 +1,288 @@ +from http import HTTPStatus +from typing import Any +from urllib.parse import quote + +import httpx + +from ... import errors +from ...client import AuthenticatedClient, Client +from ...models.error_response import ErrorResponse +from ...models.operation_envelope_allocation_override_response import ( + OperationEnvelopeAllocationOverrideResponse, +) +from ...models.set_allocation_override_request import SetAllocationOverrideRequest +from ...types import UNSET, Response, Unset + + +def _get_kwargs( + graph_id: str, + *, + body: SetAllocationOverrideRequest, + idempotency_key: None | str | Unset = UNSET, +) -> dict[str, Any]: + headers: dict[str, Any] = {} + if not isinstance(idempotency_key, Unset): + headers["Idempotency-Key"] = idempotency_key + + _kwargs: dict[str, Any] = { + "method": "post", + "url": "/extensions/roboledger/{graph_id}/operations/set-allocation-override".format( + graph_id=quote(str(graph_id), safe=""), + ), + } + + _kwargs["json"] = body.to_dict() + + headers["Content-Type"] = "application/json" + + _kwargs["headers"] = headers + return _kwargs + + +def _parse_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> ErrorResponse | OperationEnvelopeAllocationOverrideResponse | None: + if response.status_code == 200: + response_200 = OperationEnvelopeAllocationOverrideResponse.from_dict( + response.json() + ) + + return response_200 + + if response.status_code == 400: + response_400 = ErrorResponse.from_dict(response.json()) + + return response_400 + + if response.status_code == 401: + response_401 = ErrorResponse.from_dict(response.json()) + + return response_401 + + if response.status_code == 403: + response_403 = ErrorResponse.from_dict(response.json()) + + return response_403 + + if response.status_code == 404: + response_404 = ErrorResponse.from_dict(response.json()) + + return response_404 + + if response.status_code == 409: + response_409 = ErrorResponse.from_dict(response.json()) + + return response_409 + + if response.status_code == 422: + response_422 = ErrorResponse.from_dict(response.json()) + + return response_422 + + if response.status_code == 429: + response_429 = ErrorResponse.from_dict(response.json()) + + return response_429 + + if response.status_code == 500: + response_500 = ErrorResponse.from_dict(response.json()) + + return response_500 + + if client.raise_on_unexpected_status: + raise errors.UnexpectedStatus(response.status_code, response.content) + else: + return None + + +def _build_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> Response[ErrorResponse | OperationEnvelopeAllocationOverrideResponse]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + graph_id: str, + *, + client: AuthenticatedClient, + body: SetAllocationOverrideRequest, + idempotency_key: None | str | Unset = UNSET, +) -> Response[ErrorResponse | OperationEnvelopeAllocationOverrideResponse]: + """Set Allocation Override + + Set the outside owners' share of a member's result for one month in place of the pro-rata share its + ownership percentage gives: a preferred return, a waterfall, a special allocation. Give the share as + an amount in cents (negative for a share of a loss) or as a percentage of the month's result, with + the basis; `clear` removes it. preview- and propose-consolidation-entries then use it for that + month, and their basis says so. Only for a member consolidated in full, and refused in a month the + consolidation entity has closed. + + **Idempotency**: supply an `Idempotency-Key` header to make safe retries; replays within 24 hours + return the same envelope. Reusing the key with a different body returns HTTP 409 Conflict. + + Args: + graph_id (str): + idempotency_key (None | str | Unset): + body (SetAllocationOverrideRequest): The outside owners' share of a member's result for + one month, set by a + person in place of the pro-rata share: a preferred return, a waterfall, a + special allocation. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorResponse | OperationEnvelopeAllocationOverrideResponse] + """ + + kwargs = _get_kwargs( + graph_id=graph_id, + body=body, + idempotency_key=idempotency_key, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + graph_id: str, + *, + client: AuthenticatedClient, + body: SetAllocationOverrideRequest, + idempotency_key: None | str | Unset = UNSET, +) -> ErrorResponse | OperationEnvelopeAllocationOverrideResponse | None: + """Set Allocation Override + + Set the outside owners' share of a member's result for one month in place of the pro-rata share its + ownership percentage gives: a preferred return, a waterfall, a special allocation. Give the share as + an amount in cents (negative for a share of a loss) or as a percentage of the month's result, with + the basis; `clear` removes it. preview- and propose-consolidation-entries then use it for that + month, and their basis says so. Only for a member consolidated in full, and refused in a month the + consolidation entity has closed. + + **Idempotency**: supply an `Idempotency-Key` header to make safe retries; replays within 24 hours + return the same envelope. Reusing the key with a different body returns HTTP 409 Conflict. + + Args: + graph_id (str): + idempotency_key (None | str | Unset): + body (SetAllocationOverrideRequest): The outside owners' share of a member's result for + one month, set by a + person in place of the pro-rata share: a preferred return, a waterfall, a + special allocation. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorResponse | OperationEnvelopeAllocationOverrideResponse + """ + + return sync_detailed( + graph_id=graph_id, + client=client, + body=body, + idempotency_key=idempotency_key, + ).parsed + + +async def asyncio_detailed( + graph_id: str, + *, + client: AuthenticatedClient, + body: SetAllocationOverrideRequest, + idempotency_key: None | str | Unset = UNSET, +) -> Response[ErrorResponse | OperationEnvelopeAllocationOverrideResponse]: + """Set Allocation Override + + Set the outside owners' share of a member's result for one month in place of the pro-rata share its + ownership percentage gives: a preferred return, a waterfall, a special allocation. Give the share as + an amount in cents (negative for a share of a loss) or as a percentage of the month's result, with + the basis; `clear` removes it. preview- and propose-consolidation-entries then use it for that + month, and their basis says so. Only for a member consolidated in full, and refused in a month the + consolidation entity has closed. + + **Idempotency**: supply an `Idempotency-Key` header to make safe retries; replays within 24 hours + return the same envelope. Reusing the key with a different body returns HTTP 409 Conflict. + + Args: + graph_id (str): + idempotency_key (None | str | Unset): + body (SetAllocationOverrideRequest): The outside owners' share of a member's result for + one month, set by a + person in place of the pro-rata share: a preferred return, a waterfall, a + special allocation. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorResponse | OperationEnvelopeAllocationOverrideResponse] + """ + + kwargs = _get_kwargs( + graph_id=graph_id, + body=body, + idempotency_key=idempotency_key, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + graph_id: str, + *, + client: AuthenticatedClient, + body: SetAllocationOverrideRequest, + idempotency_key: None | str | Unset = UNSET, +) -> ErrorResponse | OperationEnvelopeAllocationOverrideResponse | None: + """Set Allocation Override + + Set the outside owners' share of a member's result for one month in place of the pro-rata share its + ownership percentage gives: a preferred return, a waterfall, a special allocation. Give the share as + an amount in cents (negative for a share of a loss) or as a percentage of the month's result, with + the basis; `clear` removes it. preview- and propose-consolidation-entries then use it for that + month, and their basis says so. Only for a member consolidated in full, and refused in a month the + consolidation entity has closed. + + **Idempotency**: supply an `Idempotency-Key` header to make safe retries; replays within 24 hours + return the same envelope. Reusing the key with a different body returns HTTP 409 Conflict. + + Args: + graph_id (str): + idempotency_key (None | str | Unset): + body (SetAllocationOverrideRequest): The outside owners' share of a member's result for + one month, set by a + person in place of the pro-rata share: a preferred return, a waterfall, a + special allocation. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorResponse | OperationEnvelopeAllocationOverrideResponse + """ + + return ( + await asyncio_detailed( + graph_id=graph_id, + client=client, + body=body, + idempotency_key=idempotency_key, + ) + ).parsed diff --git a/robosystems_client/clients/ledger_client.py b/robosystems_client/clients/ledger_client.py index 7b061c7..9f071a0 100644 --- a/robosystems_client/clients/ledger_client.py +++ b/robosystems_client/clients/ledger_client.py @@ -54,9 +54,15 @@ from ..api.robo_ledger_ledger_events.preview_reconciliations import ( sync_detailed as op_preview_reconciliations, ) +from ..api.robo_ledger_ledger_events.propose_consolidation_entries import ( + sync_detailed as op_propose_consolidation_entries, +) from ..api.robo_ledger_ledger_events.record_opening_balance import ( sync_detailed as op_record_opening_balance, ) +from ..api.robo_ledger_ledger_events.set_allocation_override import ( + sync_detailed as op_set_allocation_override, +) from ..api.robo_ledger_ledger_events.record_statement_balance import ( sync_detailed as op_record_statement_balance, ) @@ -87,6 +93,9 @@ from ..api.robo_ledger_analytical_views.consolidation_worksheet import ( sync_detailed as op_consolidation_worksheet, ) +from ..api.robo_ledger_analytical_views.preview_consolidation_entries import ( + sync_detailed as op_preview_consolidation_entries, +) from ..api.robo_ledger_analytical_views.live_financial_statement import ( sync_detailed as op_live_financial_statement, ) @@ -527,6 +536,20 @@ ) from ..models.consolidation_worksheet_request import ConsolidationWorksheetRequest from ..models.consolidation_worksheet_response import ConsolidationWorksheetResponse +from ..models.allocation_override_response import AllocationOverrideResponse +from ..models.preview_consolidation_entries_request import ( + PreviewConsolidationEntriesRequest, +) +from ..models.preview_consolidation_entries_response import ( + PreviewConsolidationEntriesResponse, +) +from ..models.propose_consolidation_entries_request import ( + ProposeConsolidationEntriesRequest, +) +from ..models.propose_consolidation_entries_response import ( + ProposeConsolidationEntriesResponse, +) +from ..models.set_allocation_override_request import SetAllocationOverrideRequest from ..models.live_financial_statement_request import LiveFinancialStatementRequest from ..models.financial_statement_analysis_response import ( FinancialStatementAnalysisResponse, @@ -2174,6 +2197,57 @@ def record_opening_balance( envelope = self._call_op("Record opening balance", response) return self._typed_result("Record opening balance", envelope, JournalEntryResponse) + def propose_consolidation_entries( + self, graph_id: str, period: str + ) -> ProposeConsolidationEntriesResponse: + """Draft a month's consolidating entries in the group's consolidation + entity, replacing the drafts the engine wrote for it before; the + consolidation entity's close posts them. ``period`` is ``YYYY-MM``. A + residual or a disagreement comes back beside the drafts, never plugged; + a closed month comes back ``closed``, with nothing written. + """ + response = op_propose_consolidation_entries( + graph_id=graph_id, + body=ProposeConsolidationEntriesRequest(period=period), + client=self._get_client(), + ) + envelope = self._call_op("Propose consolidation entries", response) + return self._typed_result( + "Propose consolidation entries", envelope, ProposeConsolidationEntriesResponse + ) + + def set_allocation_override( + self, + graph_id: str, + *, + entity_id: str, + period: str, + amount: int | None = None, + percentage: float | None = None, + basis: str | None = None, + clear: bool = False, + ) -> AllocationOverrideResponse: + """Set the outside owners' share of a member's result for one month in + place of the pro-rata share: ``amount`` in cents (negative for a share + of a loss) or ``percentage`` of the month's result, with the ``basis``. + ``clear=True`` removes it. Only for a member consolidated in full. + """ + body = SetAllocationOverrideRequest( + entity_id=entity_id, + period=period, + amount=amount if amount is not None else UNSET, + percentage=percentage if percentage is not None else UNSET, + basis=basis if basis is not None else UNSET, + clear=clear, + ) + response = op_set_allocation_override( + graph_id=graph_id, body=body, client=self._get_client() + ) + envelope = self._call_op("Set allocation override", response) + return self._typed_result( + "Set allocation override", envelope, AllocationOverrideResponse + ) + # ── Event blocks (generic preview + status transitions) ────────────── def create_event_block( @@ -2408,6 +2482,24 @@ def consolidation_worksheet( "Consolidation worksheet", envelope, ConsolidationWorksheetResponse ) + def preview_consolidation_entries( + self, graph_id: str, period: str + ) -> PreviewConsolidationEntriesResponse: + """The consolidating entries a group's month needs, computed from the + books and posting nothing: each kind and member brought to its month-end + balance, less what the consolidation entity already holds. ``period`` is + ``YYYY-MM``. + """ + response = op_preview_consolidation_entries( + graph_id=graph_id, + body=PreviewConsolidationEntriesRequest(period=period), + client=self._get_client(), + ) + envelope = self._call_op("Preview consolidation entries", response) + return self._typed_result( + "Preview consolidation entries", envelope, PreviewConsolidationEntriesResponse + ) + def financial_statement_analysis( self, graph_id: str, diff --git a/robosystems_client/models/__init__.py b/robosystems_client/models/__init__.py index c9b2228..4583d01 100644 --- a/robosystems_client/models/__init__.py +++ b/robosystems_client/models/__init__.py @@ -8,6 +8,7 @@ from .add_graph_member_request import AddGraphMemberRequest from .add_publish_list_members_operation import AddPublishListMembersOperation from .agent_classification import AgentClassification +from .allocation_override_response import AllocationOverrideResponse from .analytical_statement_fact_row import AnalyticalStatementFactRow from .api_key_info import APIKeyInfo from .api_keys_response import APIKeysResponse @@ -91,6 +92,11 @@ from .connection_provider_info_provider import ConnectionProviderInfoProvider from .connection_response import ConnectionResponse from .connection_response_metadata import ConnectionResponseMetadata +from .consolidation_proposal import ConsolidationProposal +from .consolidation_proposal_adjustment_kind import ConsolidationProposalAdjustmentKind +from .consolidation_proposal_line import ConsolidationProposalLine +from .consolidation_reconciling_item import ConsolidationReconcilingItem +from .consolidation_residual import ConsolidationResidual from .consolidation_worksheet_request import ConsolidationWorksheetRequest from .consolidation_worksheet_response import ConsolidationWorksheetResponse from .content_limits import ContentLimits @@ -470,6 +476,12 @@ from .operation_envelope_accept_suggestions_response_status import ( OperationEnvelopeAcceptSuggestionsResponseStatus, ) +from .operation_envelope_allocation_override_response import ( + OperationEnvelopeAllocationOverrideResponse, +) +from .operation_envelope_allocation_override_response_status import ( + OperationEnvelopeAllocationOverrideResponseStatus, +) from .operation_envelope_assert_metrics_response import ( OperationEnvelopeAssertMetricsResponse, ) @@ -686,6 +698,12 @@ from .operation_envelope_portfolio_block_envelope_status import ( OperationEnvelopePortfolioBlockEnvelopeStatus, ) +from .operation_envelope_preview_consolidation_entries_response import ( + OperationEnvelopePreviewConsolidationEntriesResponse, +) +from .operation_envelope_preview_consolidation_entries_response_status import ( + OperationEnvelopePreviewConsolidationEntriesResponseStatus, +) from .operation_envelope_preview_event_block_response import ( OperationEnvelopePreviewEventBlockResponse, ) @@ -698,6 +716,12 @@ from .operation_envelope_promote_obligations_response_status import ( OperationEnvelopePromoteObligationsResponseStatus, ) +from .operation_envelope_propose_consolidation_entries_response import ( + OperationEnvelopeProposeConsolidationEntriesResponse, +) +from .operation_envelope_propose_consolidation_entries_response_status import ( + OperationEnvelopeProposeConsolidationEntriesResponseStatus, +) from .operation_envelope_publish_list_response import ( OperationEnvelopePublishListResponse, ) @@ -867,6 +891,8 @@ from .portfolio_block_position_update import PortfolioBlockPositionUpdate from .portfolio_block_positions import PortfolioBlockPositions from .position_block import PositionBlock +from .preview_consolidation_entries_request import PreviewConsolidationEntriesRequest +from .preview_consolidation_entries_response import PreviewConsolidationEntriesResponse from .preview_event_block_response import PreviewEventBlockResponse from .preview_event_block_response_handler_metadata import ( PreviewEventBlockResponseHandlerMetadata, @@ -879,6 +905,8 @@ from .promote_obligations_response_errors_item import ( PromoteObligationsResponseErrorsItem, ) +from .propose_consolidation_entries_request import ProposeConsolidationEntriesRequest +from .propose_consolidation_entries_response import ProposeConsolidationEntriesResponse from .publish_list_member_response import PublishListMemberResponse from .publish_list_response import PublishListResponse from .query_limits import QueryLimits @@ -1001,6 +1029,7 @@ from .selection_criteria import SelectionCriteria from .service_offering_summary import ServiceOfferingSummary from .service_offerings_response import ServiceOfferingsResponse +from .set_allocation_override_request import SetAllocationOverrideRequest from .set_close_target_operation import SetCloseTargetOperation from .set_reconciliation_policy_request import SetReconciliationPolicyRequest from .set_reconciliation_policy_request_statement_cycle_type_0 import ( @@ -1192,6 +1221,7 @@ "AddGraphMemberRequest", "AddPublishListMembersOperation", "AgentClassification", + "AllocationOverrideResponse", "AnalyticalStatementFactRow", "APIKeyInfo", "APIKeysResponse", @@ -1263,6 +1293,11 @@ "ConnectionProviderInfoProvider", "ConnectionResponse", "ConnectionResponseMetadata", + "ConsolidationProposal", + "ConsolidationProposalAdjustmentKind", + "ConsolidationProposalLine", + "ConsolidationReconcilingItem", + "ConsolidationResidual", "ConsolidationWorksheetRequest", "ConsolidationWorksheetResponse", "ContentLimits", @@ -1560,6 +1595,8 @@ "OperationEnvelope", "OperationEnvelopeAcceptSuggestionsResponse", "OperationEnvelopeAcceptSuggestionsResponseStatus", + "OperationEnvelopeAllocationOverrideResponse", + "OperationEnvelopeAllocationOverrideResponseStatus", "OperationEnvelopeAssertMetricsResponse", "OperationEnvelopeAssertMetricsResponseStatus", "OperationEnvelopeAssociationResponse", @@ -1636,10 +1673,14 @@ "OperationEnvelopeLiveFinancialStatementResponseStatus", "OperationEnvelopePortfolioBlockEnvelope", "OperationEnvelopePortfolioBlockEnvelopeStatus", + "OperationEnvelopePreviewConsolidationEntriesResponse", + "OperationEnvelopePreviewConsolidationEntriesResponseStatus", "OperationEnvelopePreviewEventBlockResponse", "OperationEnvelopePreviewEventBlockResponseStatus", "OperationEnvelopePromoteObligationsResponse", "OperationEnvelopePromoteObligationsResponseStatus", + "OperationEnvelopeProposeConsolidationEntriesResponse", + "OperationEnvelopeProposeConsolidationEntriesResponseStatus", "OperationEnvelopePublishListResponse", "OperationEnvelopePublishListResponseStatus", "OperationEnvelopeReadTextResponse", @@ -1741,6 +1782,8 @@ "PortfolioBlockPositions", "PortfolioBlockPositionUpdate", "PositionBlock", + "PreviewConsolidationEntriesRequest", + "PreviewConsolidationEntriesResponse", "PreviewEventBlockResponse", "PreviewEventBlockResponseHandlerMetadata", "PreviewReconciliationsRequest", @@ -1749,6 +1792,8 @@ "PromoteObligationsRequest", "PromoteObligationsResponse", "PromoteObligationsResponseErrorsItem", + "ProposeConsolidationEntriesRequest", + "ProposeConsolidationEntriesResponse", "PublishListMemberResponse", "PublishListResponse", "QueryLimits", @@ -1843,6 +1888,7 @@ "SelectionCriteria", "ServiceOfferingsResponse", "ServiceOfferingSummary", + "SetAllocationOverrideRequest", "SetCloseTargetOperation", "SetReconciliationPolicyRequest", "SetReconciliationPolicyRequestStatementCycleType0", diff --git a/robosystems_client/models/allocation_override_response.py b/robosystems_client/models/allocation_override_response.py new file mode 100644 index 0000000..abe01fd --- /dev/null +++ b/robosystems_client/models/allocation_override_response.py @@ -0,0 +1,161 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +T = TypeVar("T", bound="AllocationOverrideResponse") + + +@_attrs_define +class AllocationOverrideResponse: + """A member's allocation override for one month. + + Attributes: + entity_id (str): The member. + period (str): The month, as YYYY-MM. + amount (int | None | Unset): The share, in cents, when set so. + percentage (float | None | Unset): The share as a percentage, when set so. + basis (None | str | Unset): Why it differs from pro rata. + set_by (None | str | Unset): Who set it. + cleared (bool | Unset): True when the override was removed. Default: False. + """ + + entity_id: str + period: str + amount: int | None | Unset = UNSET + percentage: float | None | Unset = UNSET + basis: None | str | Unset = UNSET + set_by: None | str | Unset = UNSET + cleared: bool | Unset = False + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + entity_id = self.entity_id + + period = self.period + + amount: int | None | Unset + if isinstance(self.amount, Unset): + amount = UNSET + else: + amount = self.amount + + percentage: float | None | Unset + if isinstance(self.percentage, Unset): + percentage = UNSET + else: + percentage = self.percentage + + basis: None | str | Unset + if isinstance(self.basis, Unset): + basis = UNSET + else: + basis = self.basis + + set_by: None | str | Unset + if isinstance(self.set_by, Unset): + set_by = UNSET + else: + set_by = self.set_by + + cleared = self.cleared + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "entity_id": entity_id, + "period": period, + } + ) + if amount is not UNSET: + field_dict["amount"] = amount + if percentage is not UNSET: + field_dict["percentage"] = percentage + if basis is not UNSET: + field_dict["basis"] = basis + if set_by is not UNSET: + field_dict["set_by"] = set_by + if cleared is not UNSET: + field_dict["cleared"] = cleared + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + entity_id = d.pop("entity_id") + + period = d.pop("period") + + def _parse_amount(data: object) -> int | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(int | None | Unset, data) + + amount = _parse_amount(d.pop("amount", UNSET)) + + def _parse_percentage(data: object) -> float | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(float | None | Unset, data) + + percentage = _parse_percentage(d.pop("percentage", UNSET)) + + def _parse_basis(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + basis = _parse_basis(d.pop("basis", UNSET)) + + def _parse_set_by(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + set_by = _parse_set_by(d.pop("set_by", UNSET)) + + cleared = d.pop("cleared", UNSET) + + allocation_override_response = cls( + entity_id=entity_id, + period=period, + amount=amount, + percentage=percentage, + basis=basis, + set_by=set_by, + cleared=cleared, + ) + + allocation_override_response.additional_properties = d + return allocation_override_response + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/robosystems_client/models/consolidation_proposal.py b/robosystems_client/models/consolidation_proposal.py new file mode 100644 index 0000000..417bbc9 --- /dev/null +++ b/robosystems_client/models/consolidation_proposal.py @@ -0,0 +1,131 @@ +from __future__ import annotations + +import datetime +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, TypeVar + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..models.consolidation_proposal_adjustment_kind import ( + ConsolidationProposalAdjustmentKind, +) + +if TYPE_CHECKING: + from ..models.consolidation_proposal_line import ConsolidationProposalLine + + +T = TypeVar("T", bound="ConsolidationProposal") + + +@_attrs_define +class ConsolidationProposal: + """One consolidating entry the month needs: the difference between the + balance this kind of adjustment should hold for the member at the month + end and what the consolidation entity already holds for it. + + Attributes: + adjustment_kind (ConsolidationProposalAdjustmentKind): What the entry adjusts. + adjusts_entity_id (str): The entity whose figures the entry adjusts. + adjusts_entity_name (str): That entity's name. + posting_date (datetime.date): The month's last day. + memo (str): The entry's memo. + basis (str): How the amounts were computed. + lines (list[ConsolidationProposalLine]): The entry's lines; they balance. + """ + + adjustment_kind: ConsolidationProposalAdjustmentKind + adjusts_entity_id: str + adjusts_entity_name: str + posting_date: datetime.date + memo: str + basis: str + lines: list[ConsolidationProposalLine] + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + adjustment_kind = self.adjustment_kind.value + + adjusts_entity_id = self.adjusts_entity_id + + adjusts_entity_name = self.adjusts_entity_name + + posting_date = self.posting_date.isoformat() + + memo = self.memo + + basis = self.basis + + lines = [] + for lines_item_data in self.lines: + lines_item = lines_item_data.to_dict() + lines.append(lines_item) + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "adjustment_kind": adjustment_kind, + "adjusts_entity_id": adjusts_entity_id, + "adjusts_entity_name": adjusts_entity_name, + "posting_date": posting_date, + "memo": memo, + "basis": basis, + "lines": lines, + } + ) + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.consolidation_proposal_line import ConsolidationProposalLine + + d = dict(src_dict) + adjustment_kind = ConsolidationProposalAdjustmentKind(d.pop("adjustment_kind")) + + adjusts_entity_id = d.pop("adjusts_entity_id") + + adjusts_entity_name = d.pop("adjusts_entity_name") + + posting_date = datetime.date.fromisoformat(d.pop("posting_date")) + + memo = d.pop("memo") + + basis = d.pop("basis") + + lines = [] + _lines = d.pop("lines") + for lines_item_data in _lines: + lines_item = ConsolidationProposalLine.from_dict(lines_item_data) + + lines.append(lines_item) + + consolidation_proposal = cls( + adjustment_kind=adjustment_kind, + adjusts_entity_id=adjusts_entity_id, + adjusts_entity_name=adjusts_entity_name, + posting_date=posting_date, + memo=memo, + basis=basis, + lines=lines, + ) + + consolidation_proposal.additional_properties = d + return consolidation_proposal + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/robosystems_client/models/consolidation_proposal_adjustment_kind.py b/robosystems_client/models/consolidation_proposal_adjustment_kind.py new file mode 100644 index 0000000..2df5917 --- /dev/null +++ b/robosystems_client/models/consolidation_proposal_adjustment_kind.py @@ -0,0 +1,18 @@ +from enum import Enum + + +class ConsolidationProposalAdjustmentKind(str, Enum): + ACQUISITION = "acquisition" + DECONSOLIDATION = "deconsolidation" + ELIMINATION_INTERCOMPANY = "elimination_intercompany" + ELIMINATION_INVESTMENT = "elimination_investment" + ELIMINATION_UNREALIZED_PROFIT = "elimination_unrealized_profit" + EQUITY_METHOD_DISTRIBUTION = "equity_method_distribution" + EQUITY_METHOD_PICKUP = "equity_method_pickup" + MANUAL = "manual" + NCI_ALLOCATION = "nci_allocation" + NCI_DISTRIBUTION = "nci_distribution" + TRANSLATION = "translation" + + def __str__(self) -> str: + return str(self.value) diff --git a/robosystems_client/models/consolidation_proposal_line.py b/robosystems_client/models/consolidation_proposal_line.py new file mode 100644 index 0000000..e3e3ab6 --- /dev/null +++ b/robosystems_client/models/consolidation_proposal_line.py @@ -0,0 +1,120 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +T = TypeVar("T", bound="ConsolidationProposalLine") + + +@_attrs_define +class ConsolidationProposalLine: + """One line of a proposed consolidating entry, in the consolidation + entity's chart. + + Attributes: + element_id (str): The consolidation entity's account. + account_name (str): The account's name. + concept (str): The rs-gaap concept the account maps to. + debit_amount (int | Unset): Debit, in cents. Default: 0. + credit_amount (int | Unset): Credit, in cents. Default: 0. + flow_qname (None | str | Unset): The cash flow row the line offsets, when it eliminates one: the row the + member's own line produced, so the consolidated cash flow nets it. + """ + + element_id: str + account_name: str + concept: str + debit_amount: int | Unset = 0 + credit_amount: int | Unset = 0 + flow_qname: None | str | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + element_id = self.element_id + + account_name = self.account_name + + concept = self.concept + + debit_amount = self.debit_amount + + credit_amount = self.credit_amount + + flow_qname: None | str | Unset + if isinstance(self.flow_qname, Unset): + flow_qname = UNSET + else: + flow_qname = self.flow_qname + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "element_id": element_id, + "account_name": account_name, + "concept": concept, + } + ) + if debit_amount is not UNSET: + field_dict["debit_amount"] = debit_amount + if credit_amount is not UNSET: + field_dict["credit_amount"] = credit_amount + if flow_qname is not UNSET: + field_dict["flow_qname"] = flow_qname + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + element_id = d.pop("element_id") + + account_name = d.pop("account_name") + + concept = d.pop("concept") + + debit_amount = d.pop("debit_amount", UNSET) + + credit_amount = d.pop("credit_amount", UNSET) + + def _parse_flow_qname(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + flow_qname = _parse_flow_qname(d.pop("flow_qname", UNSET)) + + consolidation_proposal_line = cls( + element_id=element_id, + account_name=account_name, + concept=concept, + debit_amount=debit_amount, + credit_amount=credit_amount, + flow_qname=flow_qname, + ) + + consolidation_proposal_line.additional_properties = d + return consolidation_proposal_line + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/robosystems_client/models/consolidation_reconciling_item.py b/robosystems_client/models/consolidation_reconciling_item.py new file mode 100644 index 0000000..e1838c3 --- /dev/null +++ b/robosystems_client/models/consolidation_reconciling_item.py @@ -0,0 +1,96 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +T = TypeVar("T", bound="ConsolidationReconcilingItem") + + +@_attrs_define +class ConsolidationReconcilingItem: + """Two of the group's entities whose intercompany figures do not agree. + The lower amount is eliminated where one side matches the other; what is + left stays in the consolidated statements until the books agree. + + Attributes: + entity_ids (list[str]): The two entities. + concept (str): The rs-gaap concept left uneliminated. + entity_id (str): The entity whose figure is left. + amount (int): Cents left uneliminated, debit-positive. + description (str): What does not agree. + """ + + entity_ids: list[str] + concept: str + entity_id: str + amount: int + description: str + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + entity_ids = self.entity_ids + + concept = self.concept + + entity_id = self.entity_id + + amount = self.amount + + description = self.description + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "entity_ids": entity_ids, + "concept": concept, + "entity_id": entity_id, + "amount": amount, + "description": description, + } + ) + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + entity_ids = cast(list[str], d.pop("entity_ids")) + + concept = d.pop("concept") + + entity_id = d.pop("entity_id") + + amount = d.pop("amount") + + description = d.pop("description") + + consolidation_reconciling_item = cls( + entity_ids=entity_ids, + concept=concept, + entity_id=entity_id, + amount=amount, + description=description, + ) + + consolidation_reconciling_item.additional_properties = d + return consolidation_reconciling_item + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/robosystems_client/models/consolidation_residual.py b/robosystems_client/models/consolidation_residual.py new file mode 100644 index 0000000..a71abcb --- /dev/null +++ b/robosystems_client/models/consolidation_residual.py @@ -0,0 +1,90 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +T = TypeVar("T", bound="ConsolidationResidual") + + +@_attrs_define +class ConsolidationResidual: + """A difference the engine cannot eliminate on its own: the parent's + investment in a member against the parent's share of that member's + capital. Its entry is withheld until the difference is explained or + posted by hand with a basis; it is never plugged. + + Attributes: + entity_id (str): The member. + entity_name (str): The member's name. + amount (int): Cents: the parent's investment balance less its share of the member's capital. Positive when the + parent carries more than its share. + explanation (str): What the two figures are. + """ + + entity_id: str + entity_name: str + amount: int + explanation: str + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + entity_id = self.entity_id + + entity_name = self.entity_name + + amount = self.amount + + explanation = self.explanation + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "entity_id": entity_id, + "entity_name": entity_name, + "amount": amount, + "explanation": explanation, + } + ) + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + entity_id = d.pop("entity_id") + + entity_name = d.pop("entity_name") + + amount = d.pop("amount") + + explanation = d.pop("explanation") + + consolidation_residual = cls( + entity_id=entity_id, + entity_name=entity_name, + amount=amount, + explanation=explanation, + ) + + consolidation_residual.additional_properties = d + return consolidation_residual + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/robosystems_client/models/journal_entry_line_item_input.py b/robosystems_client/models/journal_entry_line_item_input.py index 4e01507..73c530a 100644 --- a/robosystems_client/models/journal_entry_line_item_input.py +++ b/robosystems_client/models/journal_entry_line_item_input.py @@ -35,7 +35,8 @@ class JournalEntryLineItemInput: one side of the entry tags the untagged lines on the other: the cash flow statement reads the cash line and the roll-forwards read the account line. On the group's consolidation entity, which moves no cash, every tagged line counts on its own, cash-effect signed (a credit is an inflow), so an elimination offsets the flow a member's - line produced. Refused when it is not a row of the entity's cash flow statement. + line produced, and a tag does not spread to the other side. Refused when it is not a row of the entity's cash + flow statement. metadata (JournalEntryLineItemInputMetadataType0 | None | Unset): Optional per-line metadata stamped on `LineItem.metadata_`. Used to carry source-system fields the standard columns don't cover — e.g. an external flow-tag code that drives rollforward attribution (`transaction_description_code`), an external memo, or a cost- diff --git a/robosystems_client/models/journal_entry_response.py b/robosystems_client/models/journal_entry_response.py index 29770f1..c8a7595 100644 --- a/robosystems_client/models/journal_entry_response.py +++ b/robosystems_client/models/journal_entry_response.py @@ -33,6 +33,8 @@ class JournalEntryResponse: provenance (None | str | Unset): reversal_of (None | str | Unset): posted_at (datetime.datetime | None | Unset): + adjustment_kind (None | str | Unset): + adjusts_entity_id (None | str | Unset): """ id: str @@ -47,6 +49,8 @@ class JournalEntryResponse: provenance: None | str | Unset = UNSET reversal_of: None | str | Unset = UNSET posted_at: datetime.datetime | None | Unset = UNSET + adjustment_kind: None | str | Unset = UNSET + adjusts_entity_id: None | str | Unset = UNSET additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> dict[str, Any]: @@ -99,6 +103,18 @@ def to_dict(self) -> dict[str, Any]: else: posted_at = self.posted_at + adjustment_kind: None | str | Unset + if isinstance(self.adjustment_kind, Unset): + adjustment_kind = UNSET + else: + adjustment_kind = self.adjustment_kind + + adjusts_entity_id: None | str | Unset + if isinstance(self.adjusts_entity_id, Unset): + adjusts_entity_id = UNSET + else: + adjusts_entity_id = self.adjusts_entity_id + field_dict: dict[str, Any] = {} field_dict.update(self.additional_properties) field_dict.update( @@ -122,6 +138,10 @@ def to_dict(self) -> dict[str, Any]: field_dict["reversal_of"] = reversal_of if posted_at is not UNSET: field_dict["posted_at"] = posted_at + if adjustment_kind is not UNSET: + field_dict["adjustment_kind"] = adjustment_kind + if adjusts_entity_id is not UNSET: + field_dict["adjusts_entity_id"] = adjusts_entity_id return field_dict @@ -202,6 +222,24 @@ def _parse_posted_at(data: object) -> datetime.datetime | None | Unset: posted_at = _parse_posted_at(d.pop("posted_at", UNSET)) + def _parse_adjustment_kind(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + adjustment_kind = _parse_adjustment_kind(d.pop("adjustment_kind", UNSET)) + + def _parse_adjusts_entity_id(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + adjusts_entity_id = _parse_adjusts_entity_id(d.pop("adjusts_entity_id", UNSET)) + journal_entry_response = cls( id=id, type_=type_, @@ -215,6 +253,8 @@ def _parse_posted_at(data: object) -> datetime.datetime | None | Unset: provenance=provenance, reversal_of=reversal_of, posted_at=posted_at, + adjustment_kind=adjustment_kind, + adjusts_entity_id=adjusts_entity_id, ) journal_entry_response.additional_properties = d diff --git a/robosystems_client/models/operation_envelope_allocation_override_response.py b/robosystems_client/models/operation_envelope_allocation_override_response.py new file mode 100644 index 0000000..389a2e2 --- /dev/null +++ b/robosystems_client/models/operation_envelope_allocation_override_response.py @@ -0,0 +1,158 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..models.operation_envelope_allocation_override_response_status import ( + OperationEnvelopeAllocationOverrideResponseStatus, +) +from ..types import UNSET, Unset + +if TYPE_CHECKING: + from ..models.allocation_override_response import AllocationOverrideResponse + + +T = TypeVar("T", bound="OperationEnvelopeAllocationOverrideResponse") + + +@_attrs_define +class OperationEnvelopeAllocationOverrideResponse: + """ + Attributes: + operation (str): Kebab-case operation name + operation_id (str): op_-prefixed ULID for audit and SSE correlation + status (OperationEnvelopeAllocationOverrideResponseStatus): Operation lifecycle state + at (str): ISO-8601 UTC timestamp + result (AllocationOverrideResponse | None | Unset): Command-specific result payload + created_by (None | str | Unset): User ID that initiated the operation + idempotent_replay (bool | Unset): True when this envelope came from the idempotency cache — the underlying + command did not execute again. False on fresh executions. Default: False. + """ + + operation: str + operation_id: str + status: OperationEnvelopeAllocationOverrideResponseStatus + at: str + result: AllocationOverrideResponse | None | Unset = UNSET + created_by: None | str | Unset = UNSET + idempotent_replay: bool | Unset = False + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + from ..models.allocation_override_response import AllocationOverrideResponse + + operation = self.operation + + operation_id = self.operation_id + + status = self.status.value + + at = self.at + + result: dict[str, Any] | None | Unset + if isinstance(self.result, Unset): + result = UNSET + elif isinstance(self.result, AllocationOverrideResponse): + result = self.result.to_dict() + else: + result = self.result + + created_by: None | str | Unset + if isinstance(self.created_by, Unset): + created_by = UNSET + else: + created_by = self.created_by + + idempotent_replay = self.idempotent_replay + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "operation": operation, + "operationId": operation_id, + "status": status, + "at": at, + } + ) + if result is not UNSET: + field_dict["result"] = result + if created_by is not UNSET: + field_dict["createdBy"] = created_by + if idempotent_replay is not UNSET: + field_dict["idempotentReplay"] = idempotent_replay + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.allocation_override_response import AllocationOverrideResponse + + d = dict(src_dict) + operation = d.pop("operation") + + operation_id = d.pop("operationId") + + status = OperationEnvelopeAllocationOverrideResponseStatus(d.pop("status")) + + at = d.pop("at") + + def _parse_result(data: object) -> AllocationOverrideResponse | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, dict): + raise TypeError() + result_type_0 = AllocationOverrideResponse.from_dict(data) + + return result_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(AllocationOverrideResponse | None | Unset, data) + + result = _parse_result(d.pop("result", UNSET)) + + def _parse_created_by(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + created_by = _parse_created_by(d.pop("createdBy", UNSET)) + + idempotent_replay = d.pop("idempotentReplay", UNSET) + + operation_envelope_allocation_override_response = cls( + operation=operation, + operation_id=operation_id, + status=status, + at=at, + result=result, + created_by=created_by, + idempotent_replay=idempotent_replay, + ) + + operation_envelope_allocation_override_response.additional_properties = d + return operation_envelope_allocation_override_response + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/robosystems_client/models/operation_envelope_allocation_override_response_status.py b/robosystems_client/models/operation_envelope_allocation_override_response_status.py new file mode 100644 index 0000000..ec6cb0f --- /dev/null +++ b/robosystems_client/models/operation_envelope_allocation_override_response_status.py @@ -0,0 +1,10 @@ +from enum import Enum + + +class OperationEnvelopeAllocationOverrideResponseStatus(str, Enum): + COMPLETED = "completed" + FAILED = "failed" + PENDING = "pending" + + def __str__(self) -> str: + return str(self.value) diff --git a/robosystems_client/models/operation_envelope_preview_consolidation_entries_response.py b/robosystems_client/models/operation_envelope_preview_consolidation_entries_response.py new file mode 100644 index 0000000..233c9f8 --- /dev/null +++ b/robosystems_client/models/operation_envelope_preview_consolidation_entries_response.py @@ -0,0 +1,166 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..models.operation_envelope_preview_consolidation_entries_response_status import ( + OperationEnvelopePreviewConsolidationEntriesResponseStatus, +) +from ..types import UNSET, Unset + +if TYPE_CHECKING: + from ..models.preview_consolidation_entries_response import ( + PreviewConsolidationEntriesResponse, + ) + + +T = TypeVar("T", bound="OperationEnvelopePreviewConsolidationEntriesResponse") + + +@_attrs_define +class OperationEnvelopePreviewConsolidationEntriesResponse: + """ + Attributes: + operation (str): Kebab-case operation name + operation_id (str): op_-prefixed ULID for audit and SSE correlation + status (OperationEnvelopePreviewConsolidationEntriesResponseStatus): Operation lifecycle state + at (str): ISO-8601 UTC timestamp + result (None | PreviewConsolidationEntriesResponse | Unset): Command-specific result payload + created_by (None | str | Unset): User ID that initiated the operation + idempotent_replay (bool | Unset): True when this envelope came from the idempotency cache — the underlying + command did not execute again. False on fresh executions. Default: False. + """ + + operation: str + operation_id: str + status: OperationEnvelopePreviewConsolidationEntriesResponseStatus + at: str + result: None | PreviewConsolidationEntriesResponse | Unset = UNSET + created_by: None | str | Unset = UNSET + idempotent_replay: bool | Unset = False + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + from ..models.preview_consolidation_entries_response import ( + PreviewConsolidationEntriesResponse, + ) + + operation = self.operation + + operation_id = self.operation_id + + status = self.status.value + + at = self.at + + result: dict[str, Any] | None | Unset + if isinstance(self.result, Unset): + result = UNSET + elif isinstance(self.result, PreviewConsolidationEntriesResponse): + result = self.result.to_dict() + else: + result = self.result + + created_by: None | str | Unset + if isinstance(self.created_by, Unset): + created_by = UNSET + else: + created_by = self.created_by + + idempotent_replay = self.idempotent_replay + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "operation": operation, + "operationId": operation_id, + "status": status, + "at": at, + } + ) + if result is not UNSET: + field_dict["result"] = result + if created_by is not UNSET: + field_dict["createdBy"] = created_by + if idempotent_replay is not UNSET: + field_dict["idempotentReplay"] = idempotent_replay + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.preview_consolidation_entries_response import ( + PreviewConsolidationEntriesResponse, + ) + + d = dict(src_dict) + operation = d.pop("operation") + + operation_id = d.pop("operationId") + + status = OperationEnvelopePreviewConsolidationEntriesResponseStatus(d.pop("status")) + + at = d.pop("at") + + def _parse_result( + data: object, + ) -> None | PreviewConsolidationEntriesResponse | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, dict): + raise TypeError() + result_type_0 = PreviewConsolidationEntriesResponse.from_dict(data) + + return result_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(None | PreviewConsolidationEntriesResponse | Unset, data) + + result = _parse_result(d.pop("result", UNSET)) + + def _parse_created_by(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + created_by = _parse_created_by(d.pop("createdBy", UNSET)) + + idempotent_replay = d.pop("idempotentReplay", UNSET) + + operation_envelope_preview_consolidation_entries_response = cls( + operation=operation, + operation_id=operation_id, + status=status, + at=at, + result=result, + created_by=created_by, + idempotent_replay=idempotent_replay, + ) + + operation_envelope_preview_consolidation_entries_response.additional_properties = d + return operation_envelope_preview_consolidation_entries_response + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/robosystems_client/models/operation_envelope_preview_consolidation_entries_response_status.py b/robosystems_client/models/operation_envelope_preview_consolidation_entries_response_status.py new file mode 100644 index 0000000..1f0339e --- /dev/null +++ b/robosystems_client/models/operation_envelope_preview_consolidation_entries_response_status.py @@ -0,0 +1,10 @@ +from enum import Enum + + +class OperationEnvelopePreviewConsolidationEntriesResponseStatus(str, Enum): + COMPLETED = "completed" + FAILED = "failed" + PENDING = "pending" + + def __str__(self) -> str: + return str(self.value) diff --git a/robosystems_client/models/operation_envelope_propose_consolidation_entries_response.py b/robosystems_client/models/operation_envelope_propose_consolidation_entries_response.py new file mode 100644 index 0000000..76829fa --- /dev/null +++ b/robosystems_client/models/operation_envelope_propose_consolidation_entries_response.py @@ -0,0 +1,166 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..models.operation_envelope_propose_consolidation_entries_response_status import ( + OperationEnvelopeProposeConsolidationEntriesResponseStatus, +) +from ..types import UNSET, Unset + +if TYPE_CHECKING: + from ..models.propose_consolidation_entries_response import ( + ProposeConsolidationEntriesResponse, + ) + + +T = TypeVar("T", bound="OperationEnvelopeProposeConsolidationEntriesResponse") + + +@_attrs_define +class OperationEnvelopeProposeConsolidationEntriesResponse: + """ + Attributes: + operation (str): Kebab-case operation name + operation_id (str): op_-prefixed ULID for audit and SSE correlation + status (OperationEnvelopeProposeConsolidationEntriesResponseStatus): Operation lifecycle state + at (str): ISO-8601 UTC timestamp + result (None | ProposeConsolidationEntriesResponse | Unset): Command-specific result payload + created_by (None | str | Unset): User ID that initiated the operation + idempotent_replay (bool | Unset): True when this envelope came from the idempotency cache — the underlying + command did not execute again. False on fresh executions. Default: False. + """ + + operation: str + operation_id: str + status: OperationEnvelopeProposeConsolidationEntriesResponseStatus + at: str + result: None | ProposeConsolidationEntriesResponse | Unset = UNSET + created_by: None | str | Unset = UNSET + idempotent_replay: bool | Unset = False + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + from ..models.propose_consolidation_entries_response import ( + ProposeConsolidationEntriesResponse, + ) + + operation = self.operation + + operation_id = self.operation_id + + status = self.status.value + + at = self.at + + result: dict[str, Any] | None | Unset + if isinstance(self.result, Unset): + result = UNSET + elif isinstance(self.result, ProposeConsolidationEntriesResponse): + result = self.result.to_dict() + else: + result = self.result + + created_by: None | str | Unset + if isinstance(self.created_by, Unset): + created_by = UNSET + else: + created_by = self.created_by + + idempotent_replay = self.idempotent_replay + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "operation": operation, + "operationId": operation_id, + "status": status, + "at": at, + } + ) + if result is not UNSET: + field_dict["result"] = result + if created_by is not UNSET: + field_dict["createdBy"] = created_by + if idempotent_replay is not UNSET: + field_dict["idempotentReplay"] = idempotent_replay + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.propose_consolidation_entries_response import ( + ProposeConsolidationEntriesResponse, + ) + + d = dict(src_dict) + operation = d.pop("operation") + + operation_id = d.pop("operationId") + + status = OperationEnvelopeProposeConsolidationEntriesResponseStatus(d.pop("status")) + + at = d.pop("at") + + def _parse_result( + data: object, + ) -> None | ProposeConsolidationEntriesResponse | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, dict): + raise TypeError() + result_type_0 = ProposeConsolidationEntriesResponse.from_dict(data) + + return result_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(None | ProposeConsolidationEntriesResponse | Unset, data) + + result = _parse_result(d.pop("result", UNSET)) + + def _parse_created_by(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + created_by = _parse_created_by(d.pop("createdBy", UNSET)) + + idempotent_replay = d.pop("idempotentReplay", UNSET) + + operation_envelope_propose_consolidation_entries_response = cls( + operation=operation, + operation_id=operation_id, + status=status, + at=at, + result=result, + created_by=created_by, + idempotent_replay=idempotent_replay, + ) + + operation_envelope_propose_consolidation_entries_response.additional_properties = d + return operation_envelope_propose_consolidation_entries_response + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/robosystems_client/models/operation_envelope_propose_consolidation_entries_response_status.py b/robosystems_client/models/operation_envelope_propose_consolidation_entries_response_status.py new file mode 100644 index 0000000..3e1cfa3 --- /dev/null +++ b/robosystems_client/models/operation_envelope_propose_consolidation_entries_response_status.py @@ -0,0 +1,10 @@ +from enum import Enum + + +class OperationEnvelopeProposeConsolidationEntriesResponseStatus(str, Enum): + COMPLETED = "completed" + FAILED = "failed" + PENDING = "pending" + + def __str__(self) -> str: + return str(self.value) diff --git a/robosystems_client/models/preview_consolidation_entries_request.py b/robosystems_client/models/preview_consolidation_entries_request.py new file mode 100644 index 0000000..613e464 --- /dev/null +++ b/robosystems_client/models/preview_consolidation_entries_request.py @@ -0,0 +1,62 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +T = TypeVar("T", bound="PreviewConsolidationEntriesRequest") + + +@_attrs_define +class PreviewConsolidationEntriesRequest: + """The month to compute the consolidating entries for. + + Attributes: + period (str): The month, as YYYY-MM. + """ + + period: str + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + period = self.period + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "period": period, + } + ) + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + period = d.pop("period") + + preview_consolidation_entries_request = cls( + period=period, + ) + + preview_consolidation_entries_request.additional_properties = d + return preview_consolidation_entries_request + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/robosystems_client/models/preview_consolidation_entries_response.py b/robosystems_client/models/preview_consolidation_entries_response.py new file mode 100644 index 0000000..e07d059 --- /dev/null +++ b/robosystems_client/models/preview_consolidation_entries_response.py @@ -0,0 +1,207 @@ +from __future__ import annotations + +import datetime +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +if TYPE_CHECKING: + from ..models.consolidation_proposal import ConsolidationProposal + from ..models.consolidation_reconciling_item import ConsolidationReconcilingItem + from ..models.consolidation_residual import ConsolidationResidual + + +T = TypeVar("T", bound="PreviewConsolidationEntriesResponse") + + +@_attrs_define +class PreviewConsolidationEntriesResponse: + """The consolidating entries a month needs, computed from the books. + + Attributes: + period (str): The month, as YYYY-MM. + period_start (datetime.date): The month's first day. + period_end (datetime.date): The month's last day. + consolidation_entity_id (str): The entity the entries post in. + up_to_date (bool): True when nothing is proposed, withheld or left out: the consolidation entity already holds + what the month needs. A closed month is up to date as posted; read `closed` first. + proposals (list[ConsolidationProposal] | Unset): The entries to post; empty when the month is up to date. + residuals (list[ConsolidationResidual] | Unset): Differences withheld from the proposals until explained. + reconciling_items (list[ConsolidationReconcilingItem] | Unset): Intercompany figures the two sides do not agree + on. + notes (list[str] | Unset): Anything the engine left out, and why. + closed (bool | Unset): True when the consolidation entity has closed the month: its entries are as posted, and + nothing is recomputed. Default: False. + drafted_entry_ids (list[str] | Unset): The month's drafts propose-consolidation-entries wrote, waiting for the + consolidation entity's close to post them. + """ + + period: str + period_start: datetime.date + period_end: datetime.date + consolidation_entity_id: str + up_to_date: bool + proposals: list[ConsolidationProposal] | Unset = UNSET + residuals: list[ConsolidationResidual] | Unset = UNSET + reconciling_items: list[ConsolidationReconcilingItem] | Unset = UNSET + notes: list[str] | Unset = UNSET + closed: bool | Unset = False + drafted_entry_ids: list[str] | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + period = self.period + + period_start = self.period_start.isoformat() + + period_end = self.period_end.isoformat() + + consolidation_entity_id = self.consolidation_entity_id + + up_to_date = self.up_to_date + + proposals: list[dict[str, Any]] | Unset = UNSET + if not isinstance(self.proposals, Unset): + proposals = [] + for proposals_item_data in self.proposals: + proposals_item = proposals_item_data.to_dict() + proposals.append(proposals_item) + + residuals: list[dict[str, Any]] | Unset = UNSET + if not isinstance(self.residuals, Unset): + residuals = [] + for residuals_item_data in self.residuals: + residuals_item = residuals_item_data.to_dict() + residuals.append(residuals_item) + + reconciling_items: list[dict[str, Any]] | Unset = UNSET + if not isinstance(self.reconciling_items, Unset): + reconciling_items = [] + for reconciling_items_item_data in self.reconciling_items: + reconciling_items_item = reconciling_items_item_data.to_dict() + reconciling_items.append(reconciling_items_item) + + notes: list[str] | Unset = UNSET + if not isinstance(self.notes, Unset): + notes = self.notes + + closed = self.closed + + drafted_entry_ids: list[str] | Unset = UNSET + if not isinstance(self.drafted_entry_ids, Unset): + drafted_entry_ids = self.drafted_entry_ids + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "period": period, + "period_start": period_start, + "period_end": period_end, + "consolidation_entity_id": consolidation_entity_id, + "up_to_date": up_to_date, + } + ) + if proposals is not UNSET: + field_dict["proposals"] = proposals + if residuals is not UNSET: + field_dict["residuals"] = residuals + if reconciling_items is not UNSET: + field_dict["reconciling_items"] = reconciling_items + if notes is not UNSET: + field_dict["notes"] = notes + if closed is not UNSET: + field_dict["closed"] = closed + if drafted_entry_ids is not UNSET: + field_dict["drafted_entry_ids"] = drafted_entry_ids + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.consolidation_proposal import ConsolidationProposal + from ..models.consolidation_reconciling_item import ConsolidationReconcilingItem + from ..models.consolidation_residual import ConsolidationResidual + + d = dict(src_dict) + period = d.pop("period") + + period_start = datetime.date.fromisoformat(d.pop("period_start")) + + period_end = datetime.date.fromisoformat(d.pop("period_end")) + + consolidation_entity_id = d.pop("consolidation_entity_id") + + up_to_date = d.pop("up_to_date") + + _proposals = d.pop("proposals", UNSET) + proposals: list[ConsolidationProposal] | Unset = UNSET + if _proposals is not UNSET: + proposals = [] + for proposals_item_data in _proposals: + proposals_item = ConsolidationProposal.from_dict(proposals_item_data) + + proposals.append(proposals_item) + + _residuals = d.pop("residuals", UNSET) + residuals: list[ConsolidationResidual] | Unset = UNSET + if _residuals is not UNSET: + residuals = [] + for residuals_item_data in _residuals: + residuals_item = ConsolidationResidual.from_dict(residuals_item_data) + + residuals.append(residuals_item) + + _reconciling_items = d.pop("reconciling_items", UNSET) + reconciling_items: list[ConsolidationReconcilingItem] | Unset = UNSET + if _reconciling_items is not UNSET: + reconciling_items = [] + for reconciling_items_item_data in _reconciling_items: + reconciling_items_item = ConsolidationReconcilingItem.from_dict( + reconciling_items_item_data + ) + + reconciling_items.append(reconciling_items_item) + + notes = cast(list[str], d.pop("notes", UNSET)) + + closed = d.pop("closed", UNSET) + + drafted_entry_ids = cast(list[str], d.pop("drafted_entry_ids", UNSET)) + + preview_consolidation_entries_response = cls( + period=period, + period_start=period_start, + period_end=period_end, + consolidation_entity_id=consolidation_entity_id, + up_to_date=up_to_date, + proposals=proposals, + residuals=residuals, + reconciling_items=reconciling_items, + notes=notes, + closed=closed, + drafted_entry_ids=drafted_entry_ids, + ) + + preview_consolidation_entries_response.additional_properties = d + return preview_consolidation_entries_response + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/robosystems_client/models/propose_consolidation_entries_request.py b/robosystems_client/models/propose_consolidation_entries_request.py new file mode 100644 index 0000000..5498473 --- /dev/null +++ b/robosystems_client/models/propose_consolidation_entries_request.py @@ -0,0 +1,62 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +T = TypeVar("T", bound="ProposeConsolidationEntriesRequest") + + +@_attrs_define +class ProposeConsolidationEntriesRequest: + """The month to draft the consolidating entries for. + + Attributes: + period (str): The month, as YYYY-MM. + """ + + period: str + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + period = self.period + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "period": period, + } + ) + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + period = d.pop("period") + + propose_consolidation_entries_request = cls( + period=period, + ) + + propose_consolidation_entries_request.additional_properties = d + return propose_consolidation_entries_request + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/robosystems_client/models/propose_consolidation_entries_response.py b/robosystems_client/models/propose_consolidation_entries_response.py new file mode 100644 index 0000000..b044d99 --- /dev/null +++ b/robosystems_client/models/propose_consolidation_entries_response.py @@ -0,0 +1,177 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +if TYPE_CHECKING: + from ..models.consolidation_reconciling_item import ConsolidationReconcilingItem + from ..models.consolidation_residual import ConsolidationResidual + from ..models.journal_entry_response import JournalEntryResponse + + +T = TypeVar("T", bound="ProposeConsolidationEntriesResponse") + + +@_attrs_define +class ProposeConsolidationEntriesResponse: + """The consolidating entries drafted for a month. + + Attributes: + period (str): The month, as YYYY-MM. + consolidation_entity_id (str): The entity the drafts are in. + closed (bool | Unset): True when the month is closed and nothing was drafted. Default: False. + entries (list[JournalEntryResponse] | Unset): The drafts written; the consolidation entity's close posts them. + replaced (int | Unset): Earlier drafts of this month's entries, replaced by these. Default: 0. + residuals (list[ConsolidationResidual] | Unset): Differences withheld from the drafts until explained. + reconciling_items (list[ConsolidationReconcilingItem] | Unset): Intercompany figures the two sides do not agree + on. + notes (list[str] | Unset): Anything the engine left out, and why. + """ + + period: str + consolidation_entity_id: str + closed: bool | Unset = False + entries: list[JournalEntryResponse] | Unset = UNSET + replaced: int | Unset = 0 + residuals: list[ConsolidationResidual] | Unset = UNSET + reconciling_items: list[ConsolidationReconcilingItem] | Unset = UNSET + notes: list[str] | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + period = self.period + + consolidation_entity_id = self.consolidation_entity_id + + closed = self.closed + + entries: list[dict[str, Any]] | Unset = UNSET + if not isinstance(self.entries, Unset): + entries = [] + for entries_item_data in self.entries: + entries_item = entries_item_data.to_dict() + entries.append(entries_item) + + replaced = self.replaced + + residuals: list[dict[str, Any]] | Unset = UNSET + if not isinstance(self.residuals, Unset): + residuals = [] + for residuals_item_data in self.residuals: + residuals_item = residuals_item_data.to_dict() + residuals.append(residuals_item) + + reconciling_items: list[dict[str, Any]] | Unset = UNSET + if not isinstance(self.reconciling_items, Unset): + reconciling_items = [] + for reconciling_items_item_data in self.reconciling_items: + reconciling_items_item = reconciling_items_item_data.to_dict() + reconciling_items.append(reconciling_items_item) + + notes: list[str] | Unset = UNSET + if not isinstance(self.notes, Unset): + notes = self.notes + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "period": period, + "consolidation_entity_id": consolidation_entity_id, + } + ) + if closed is not UNSET: + field_dict["closed"] = closed + if entries is not UNSET: + field_dict["entries"] = entries + if replaced is not UNSET: + field_dict["replaced"] = replaced + if residuals is not UNSET: + field_dict["residuals"] = residuals + if reconciling_items is not UNSET: + field_dict["reconciling_items"] = reconciling_items + if notes is not UNSET: + field_dict["notes"] = notes + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.consolidation_reconciling_item import ConsolidationReconcilingItem + from ..models.consolidation_residual import ConsolidationResidual + from ..models.journal_entry_response import JournalEntryResponse + + d = dict(src_dict) + period = d.pop("period") + + consolidation_entity_id = d.pop("consolidation_entity_id") + + closed = d.pop("closed", UNSET) + + _entries = d.pop("entries", UNSET) + entries: list[JournalEntryResponse] | Unset = UNSET + if _entries is not UNSET: + entries = [] + for entries_item_data in _entries: + entries_item = JournalEntryResponse.from_dict(entries_item_data) + + entries.append(entries_item) + + replaced = d.pop("replaced", UNSET) + + _residuals = d.pop("residuals", UNSET) + residuals: list[ConsolidationResidual] | Unset = UNSET + if _residuals is not UNSET: + residuals = [] + for residuals_item_data in _residuals: + residuals_item = ConsolidationResidual.from_dict(residuals_item_data) + + residuals.append(residuals_item) + + _reconciling_items = d.pop("reconciling_items", UNSET) + reconciling_items: list[ConsolidationReconcilingItem] | Unset = UNSET + if _reconciling_items is not UNSET: + reconciling_items = [] + for reconciling_items_item_data in _reconciling_items: + reconciling_items_item = ConsolidationReconcilingItem.from_dict( + reconciling_items_item_data + ) + + reconciling_items.append(reconciling_items_item) + + notes = cast(list[str], d.pop("notes", UNSET)) + + propose_consolidation_entries_response = cls( + period=period, + consolidation_entity_id=consolidation_entity_id, + closed=closed, + entries=entries, + replaced=replaced, + residuals=residuals, + reconciling_items=reconciling_items, + notes=notes, + ) + + propose_consolidation_entries_response.additional_properties = d + return propose_consolidation_entries_response + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/robosystems_client/models/set_allocation_override_request.py b/robosystems_client/models/set_allocation_override_request.py new file mode 100644 index 0000000..efe0945 --- /dev/null +++ b/robosystems_client/models/set_allocation_override_request.py @@ -0,0 +1,144 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +T = TypeVar("T", bound="SetAllocationOverrideRequest") + + +@_attrs_define +class SetAllocationOverrideRequest: + """The outside owners' share of a member's result for one month, set by a + person in place of the pro-rata share: a preferred return, a waterfall, a + special allocation. + + Attributes: + entity_id (str): The member, consolidated in full. + period (str): The month, as YYYY-MM. + amount (int | None | Unset): The outside owners' share of the month's result, in cents; negative for a share of + a loss. + percentage (float | None | Unset): The outside owners' share as a percentage of the month's result. + basis (None | str | Unset): Why the share differs from the ownership percentage; required to set one. + clear (bool | Unset): Remove the month's override, back to the pro-rata share. Default: False. + """ + + entity_id: str + period: str + amount: int | None | Unset = UNSET + percentage: float | None | Unset = UNSET + basis: None | str | Unset = UNSET + clear: bool | Unset = False + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + entity_id = self.entity_id + + period = self.period + + amount: int | None | Unset + if isinstance(self.amount, Unset): + amount = UNSET + else: + amount = self.amount + + percentage: float | None | Unset + if isinstance(self.percentage, Unset): + percentage = UNSET + else: + percentage = self.percentage + + basis: None | str | Unset + if isinstance(self.basis, Unset): + basis = UNSET + else: + basis = self.basis + + clear = self.clear + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "entity_id": entity_id, + "period": period, + } + ) + if amount is not UNSET: + field_dict["amount"] = amount + if percentage is not UNSET: + field_dict["percentage"] = percentage + if basis is not UNSET: + field_dict["basis"] = basis + if clear is not UNSET: + field_dict["clear"] = clear + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + entity_id = d.pop("entity_id") + + period = d.pop("period") + + def _parse_amount(data: object) -> int | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(int | None | Unset, data) + + amount = _parse_amount(d.pop("amount", UNSET)) + + def _parse_percentage(data: object) -> float | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(float | None | Unset, data) + + percentage = _parse_percentage(d.pop("percentage", UNSET)) + + def _parse_basis(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + basis = _parse_basis(d.pop("basis", UNSET)) + + clear = d.pop("clear", UNSET) + + set_allocation_override_request = cls( + entity_id=entity_id, + period=period, + amount=amount, + percentage=percentage, + basis=basis, + clear=clear, + ) + + set_allocation_override_request.additional_properties = d + return set_allocation_override_request + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/tests/test_ledger_client.py b/tests/test_ledger_client.py index f295e54..1635783 100644 --- a/tests/test_ledger_client.py +++ b/tests/test_ledger_client.py @@ -948,6 +948,48 @@ def test_record_opening_balance(self, mock_op, mock_config, graph_id): "equity_element_id": "elem_obe", } + @patch("robosystems_client.clients.ledger_client.op_propose_consolidation_entries") + def test_propose_consolidation_entries(self, mock_op, mock_config, graph_id): + envelope = _envelope( + "propose-consolidation-entries", + { + "period": "2026-08", + "consolidation_entity_id": "ent_adj", + "closed": False, + "entries": [], + "replaced": 2, + }, + ) + mock_op.return_value = _mock_response(envelope) + client = LedgerClient(mock_config) + result = client.propose_consolidation_entries(graph_id, "2026-08") + assert result["replaced"] == 2 + assert mock_op.call_args.kwargs["body"].to_dict() == {"period": "2026-08"} + + @patch("robosystems_client.clients.ledger_client.op_set_allocation_override") + def test_set_allocation_override(self, mock_op, mock_config, graph_id): + envelope = _envelope( + "set-allocation-override", + {"entity_id": "ent_cafe", "period": "2026-08", "amount": 250000}, + ) + mock_op.return_value = _mock_response(envelope) + client = LedgerClient(mock_config) + result = client.set_allocation_override( + graph_id, + entity_id="ent_cafe", + period="2026-08", + amount=250000, + basis="Preferred return first", + ) + assert result["amount"] == 250000 + assert mock_op.call_args.kwargs["body"].to_dict() == { + "entity_id": "ent_cafe", + "period": "2026-08", + "amount": 250000, + "basis": "Preferred return first", + "clear": False, + } + # ── Taxonomy / entity linking ─────────────────────────────────────────── @@ -2531,6 +2573,25 @@ def test_consolidation_worksheet(self, mock_op, mock_config, graph_id): body = mock_op.call_args.kwargs["body"] assert str(body.statement_type) == "balance_sheet" + @patch("robosystems_client.clients.ledger_client.op_preview_consolidation_entries") + def test_preview_consolidation_entries(self, mock_op, mock_config, graph_id): + envelope = _envelope( + "preview-consolidation-entries", + { + "period": "2026-08", + "period_start": "2026-08-01", + "period_end": "2026-08-31", + "consolidation_entity_id": "ent_adj", + "proposals": [], + "up_to_date": True, + }, + ) + mock_op.return_value = _mock_response(envelope) + client = LedgerClient(mock_config) + result = client.preview_consolidation_entries(graph_id, "2026-08") + assert result["up_to_date"] is True + assert mock_op.call_args.kwargs["body"].to_dict() == {"period": "2026-08"} + @patch("robosystems_client.clients.ledger_client.op_live_financial_statement") def test_live_financial_statement_with_fiscal_year( self, mock_op, mock_config, graph_id