From d4bcbaaaa606a925916da00ac4db007cea818df1 Mon Sep 17 00:00:00 2001 From: fern-api <115122769+fern-api[bot]@users.noreply.github.com> Date: Wed, 31 May 2023 04:08:51 +0000 Subject: [PATCH] Release v0.1.0 --- pyproject.toml | 6 +- src/mercoa/__init__.py | 40 +++ src/mercoa/resources/__init__.py | 51 +++- src/mercoa/resources/commons/__init__.py | 3 +- .../resources/commons/types/__init__.py | 3 +- .../commons/types/order_direction.py | 17 ++ src/mercoa/resources/entity/__init__.py | 28 +++ src/mercoa/resources/entity/client.py | 232 +++++++++++++++++- src/mercoa/resources/entity/types/__init__.py | 23 ++ .../resources/entity/types/amount_trigger.py | 26 ++ .../entity/types/approval_policy_request.py | 32 +++ .../entity/types/approval_policy_response.py | 31 +++ .../types/approval_policy_update_request.py | 31 +++ .../resources/entity/types/approver_rule.py | 27 ++ .../entity/types/entity_add_payees_request.py | 4 +- .../resources/entity/types/identifier_list.py | 31 +++ .../resources/entity/types/policy_id.py | 3 + src/mercoa/resources/entity/types/rule.py | 20 ++ src/mercoa/resources/entity/types/trigger.py | 28 +++ src/mercoa/resources/invoice/__init__.py | 10 + src/mercoa/resources/invoice/client.py | 71 ++++++ .../resources/invoice/types/__init__.py | 10 + .../invoice/types/approval_request.py | 27 ++ .../resources/invoice/types/approver.py | 29 +++ .../invoice/types/approver_action.py | 25 ++ .../invoice/types/approver_response.py | 24 ++ .../invoice/types/comment_response.py | 2 + .../invoice/types/invoice_order_by_field.py | 29 +++ .../invoice/types/invoice_request.py | 5 + .../invoice/types/invoice_response.py | 3 + .../types/payment_rail_response.py | 2 +- 31 files changed, 861 insertions(+), 12 deletions(-) create mode 100644 src/mercoa/resources/commons/types/order_direction.py create mode 100644 src/mercoa/resources/entity/types/amount_trigger.py create mode 100644 src/mercoa/resources/entity/types/approval_policy_request.py create mode 100644 src/mercoa/resources/entity/types/approval_policy_response.py create mode 100644 src/mercoa/resources/entity/types/approval_policy_update_request.py create mode 100644 src/mercoa/resources/entity/types/approver_rule.py create mode 100644 src/mercoa/resources/entity/types/identifier_list.py create mode 100644 src/mercoa/resources/entity/types/policy_id.py create mode 100644 src/mercoa/resources/entity/types/rule.py create mode 100644 src/mercoa/resources/entity/types/trigger.py create mode 100644 src/mercoa/resources/invoice/types/approval_request.py create mode 100644 src/mercoa/resources/invoice/types/approver.py create mode 100644 src/mercoa/resources/invoice/types/approver_action.py create mode 100644 src/mercoa/resources/invoice/types/approver_response.py create mode 100644 src/mercoa/resources/invoice/types/invoice_order_by_field.py diff --git a/pyproject.toml b/pyproject.toml index 713525a..d2404c5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [tool.poetry] name = "mercoa" -version = "v0.0.11" +version = "v0.1.0" description = "" authors = [] packages = [ @@ -10,10 +10,10 @@ packages = [ [tool.poetry.dependencies] python = "^3.7" -backports-cached_property = "1.0.2" -types-backports = "0.1.3" httpx = "0.23.3" +backports-cached_property = "1.0.2" pydantic = "^1.9.2" +types-backports = "0.1.3" [tool.poetry.dev-dependencies] mypy = "0.971" diff --git a/src/mercoa/__init__.py b/src/mercoa/__init__.py index 8d52f61..041bc97 100644 --- a/src/mercoa/__init__.py +++ b/src/mercoa/__init__.py @@ -6,6 +6,15 @@ SSN, AccountType, Address, + AmountTrigger, + ApprovalPolicyRequest, + ApprovalPolicyResponse, + ApprovalPolicyUpdateRequest, + ApprovalRequest, + Approver, + ApproverAction, + ApproverResponse, + ApproverRule, Attachments, BankAccountId, BankAccountRequest, @@ -58,6 +67,9 @@ EntityUserResponse, FindCounterpartiesResponse, FullName, + IdentifierList, + IdentifierList_RolesList, + IdentifierList_UserList, IndividualGovernmentID, IndividualProfileRequest, IndividualProfileResponse, @@ -65,11 +77,13 @@ InvoiceLineItemRequest, InvoiceLineItemResponse, InvoiceMetricsResponse, + InvoiceOrderByField, InvoiceRequest, InvoiceResponse, InvoiceStatus, OcrMailbox, OCRResponse, + OrderDirection, OrganizationId, OrganizationRequest, OrganizationResponse, @@ -90,6 +104,7 @@ PaymentRailRequest, PaymentRailResponse, PhoneNumber, + PolicyId, ProcessInvoiceRequest, ProfileRequest, ProfileResponse, @@ -97,11 +112,16 @@ RepresentativeRequest, RepresentativeResponse, Responsibilities, + Rule, + Rule_Approver, TaxID, TransactionId, TransactionResponse, TransactionResponseExpanded, TransactionStatus, + Trigger, + Trigger_All, + Trigger_Amount, UnauthorizedError, bank_lookup, commons, @@ -121,6 +141,15 @@ __all__ = [ "AccountType", "Address", + "AmountTrigger", + "ApprovalPolicyRequest", + "ApprovalPolicyResponse", + "ApprovalPolicyUpdateRequest", + "ApprovalRequest", + "Approver", + "ApproverAction", + "ApproverResponse", + "ApproverRule", "Attachments", "BankAccountId", "BankAccountRequest", @@ -174,6 +203,9 @@ "FindCounterpartiesResponse", "FullName", "ITIN", + "IdentifierList", + "IdentifierList_RolesList", + "IdentifierList_UserList", "IndividualGovernmentID", "IndividualProfileRequest", "IndividualProfileResponse", @@ -181,12 +213,14 @@ "InvoiceLineItemRequest", "InvoiceLineItemResponse", "InvoiceMetricsResponse", + "InvoiceOrderByField", "InvoiceRequest", "InvoiceResponse", "InvoiceStatus", "MercoaEnvironment", "OCRResponse", "OcrMailbox", + "OrderDirection", "OrganizationId", "OrganizationRequest", "OrganizationResponse", @@ -207,6 +241,7 @@ "PaymentRailRequest", "PaymentRailResponse", "PhoneNumber", + "PolicyId", "ProcessInvoiceRequest", "ProfileRequest", "ProfileResponse", @@ -214,12 +249,17 @@ "RepresentativeRequest", "RepresentativeResponse", "Responsibilities", + "Rule", + "Rule_Approver", "SSN", "TaxID", "TransactionId", "TransactionResponse", "TransactionResponseExpanded", "TransactionStatus", + "Trigger", + "Trigger_All", + "Trigger_Amount", "UnauthorizedError", "bank_lookup", "commons", diff --git a/src/mercoa/resources/__init__.py b/src/mercoa/resources/__init__.py index 7100700..2ed093b 100644 --- a/src/mercoa/resources/__init__.py +++ b/src/mercoa/resources/__init__.py @@ -16,10 +16,25 @@ transaction, ) from .bank_lookup import BankAddress, BankLookupResponse -from .commons import ITIN, SSN, Address, BirthDate, FullName, IndividualGovernmentID, PhoneNumber, UnauthorizedError +from .commons import ( + ITIN, + SSN, + Address, + BirthDate, + FullName, + IndividualGovernmentID, + OrderDirection, + PhoneNumber, + UnauthorizedError, +) from .counterparty import CounterpartyResponse, FindCounterpartiesResponse from .entity import ( AccountType, + AmountTrigger, + ApprovalPolicyRequest, + ApprovalPolicyResponse, + ApprovalPolicyUpdateRequest, + ApproverRule, BusinessProfileRequest, BusinessProfileResponse, BusinessType, @@ -30,15 +45,28 @@ EntityResponse, EntityStatus, EntityUpdateRequest, + IdentifierList, + IdentifierList_RolesList, + IdentifierList_UserList, IndividualProfileRequest, IndividualProfileResponse, InvoiceMetricsResponse, + PolicyId, ProfileRequest, ProfileResponse, + Rule, + Rule_Approver, TaxID, + Trigger, + Trigger_All, + Trigger_Amount, ) from .entity_users import EntityUserId, EntityUserRequest, EntityUserResponse from .invoice import ( + ApprovalRequest, + Approver, + ApproverAction, + ApproverResponse, CommentId, CommentRequest, CommentResponse, @@ -48,6 +76,7 @@ InvoiceId, InvoiceLineItemRequest, InvoiceLineItemResponse, + InvoiceOrderByField, InvoiceRequest, InvoiceResponse, InvoiceStatus, @@ -110,6 +139,15 @@ __all__ = [ "AccountType", "Address", + "AmountTrigger", + "ApprovalPolicyRequest", + "ApprovalPolicyResponse", + "ApprovalPolicyUpdateRequest", + "ApprovalRequest", + "Approver", + "ApproverAction", + "ApproverResponse", + "ApproverRule", "Attachments", "BankAccountId", "BankAccountRequest", @@ -163,6 +201,9 @@ "FindCounterpartiesResponse", "FullName", "ITIN", + "IdentifierList", + "IdentifierList_RolesList", + "IdentifierList_UserList", "IndividualGovernmentID", "IndividualProfileRequest", "IndividualProfileResponse", @@ -170,11 +211,13 @@ "InvoiceLineItemRequest", "InvoiceLineItemResponse", "InvoiceMetricsResponse", + "InvoiceOrderByField", "InvoiceRequest", "InvoiceResponse", "InvoiceStatus", "OCRResponse", "OcrMailbox", + "OrderDirection", "OrganizationId", "OrganizationRequest", "OrganizationResponse", @@ -195,6 +238,7 @@ "PaymentRailRequest", "PaymentRailResponse", "PhoneNumber", + "PolicyId", "ProcessInvoiceRequest", "ProfileRequest", "ProfileResponse", @@ -202,12 +246,17 @@ "RepresentativeRequest", "RepresentativeResponse", "Responsibilities", + "Rule", + "Rule_Approver", "SSN", "TaxID", "TransactionId", "TransactionResponse", "TransactionResponseExpanded", "TransactionStatus", + "Trigger", + "Trigger_All", + "Trigger_Amount", "UnauthorizedError", "bank_lookup", "commons", diff --git a/src/mercoa/resources/commons/__init__.py b/src/mercoa/resources/commons/__init__.py index a7af30d..d64b839 100644 --- a/src/mercoa/resources/commons/__init__.py +++ b/src/mercoa/resources/commons/__init__.py @@ -1,7 +1,7 @@ # This file was auto-generated by Fern from our API Definition. from .errors import UnauthorizedError -from .types import ITIN, SSN, Address, BirthDate, FullName, IndividualGovernmentID, PhoneNumber +from .types import ITIN, SSN, Address, BirthDate, FullName, IndividualGovernmentID, OrderDirection, PhoneNumber __all__ = [ "Address", @@ -9,6 +9,7 @@ "FullName", "ITIN", "IndividualGovernmentID", + "OrderDirection", "PhoneNumber", "SSN", "UnauthorizedError", diff --git a/src/mercoa/resources/commons/types/__init__.py b/src/mercoa/resources/commons/types/__init__.py index 782f4fe..6d55fca 100644 --- a/src/mercoa/resources/commons/types/__init__.py +++ b/src/mercoa/resources/commons/types/__init__.py @@ -5,7 +5,8 @@ from .full_name import FullName from .individual_government_id import IndividualGovernmentID from .itin import ITIN +from .order_direction import OrderDirection from .phone_number import PhoneNumber from .ssn import SSN -__all__ = ["Address", "BirthDate", "FullName", "ITIN", "IndividualGovernmentID", "PhoneNumber", "SSN"] +__all__ = ["Address", "BirthDate", "FullName", "ITIN", "IndividualGovernmentID", "OrderDirection", "PhoneNumber", "SSN"] diff --git a/src/mercoa/resources/commons/types/order_direction.py b/src/mercoa/resources/commons/types/order_direction.py new file mode 100644 index 0000000..6e52606 --- /dev/null +++ b/src/mercoa/resources/commons/types/order_direction.py @@ -0,0 +1,17 @@ +# This file was auto-generated by Fern from our API Definition. + +import enum +import typing + +T_Result = typing.TypeVar("T_Result") + + +class OrderDirection(str, enum.Enum): + ASC = "ASC" + DESC = "DESC" + + def visit(self, asc: typing.Callable[[], T_Result], desc: typing.Callable[[], T_Result]) -> T_Result: + if self is OrderDirection.ASC: + return asc() + if self is OrderDirection.DESC: + return desc() diff --git a/src/mercoa/resources/entity/__init__.py b/src/mercoa/resources/entity/__init__.py index fe8b9e9..1b1919e 100644 --- a/src/mercoa/resources/entity/__init__.py +++ b/src/mercoa/resources/entity/__init__.py @@ -2,6 +2,11 @@ from .types import ( AccountType, + AmountTrigger, + ApprovalPolicyRequest, + ApprovalPolicyResponse, + ApprovalPolicyUpdateRequest, + ApproverRule, BusinessProfileRequest, BusinessProfileResponse, BusinessType, @@ -12,16 +17,30 @@ EntityResponse, EntityStatus, EntityUpdateRequest, + IdentifierList, + IdentifierList_RolesList, + IdentifierList_UserList, IndividualProfileRequest, IndividualProfileResponse, InvoiceMetricsResponse, + PolicyId, ProfileRequest, ProfileResponse, + Rule, + Rule_Approver, TaxID, + Trigger, + Trigger_All, + Trigger_Amount, ) __all__ = [ "AccountType", + "AmountTrigger", + "ApprovalPolicyRequest", + "ApprovalPolicyResponse", + "ApprovalPolicyUpdateRequest", + "ApproverRule", "BusinessProfileRequest", "BusinessProfileResponse", "BusinessType", @@ -32,10 +51,19 @@ "EntityResponse", "EntityStatus", "EntityUpdateRequest", + "IdentifierList", + "IdentifierList_RolesList", + "IdentifierList_UserList", "IndividualProfileRequest", "IndividualProfileResponse", "InvoiceMetricsResponse", + "PolicyId", "ProfileRequest", "ProfileResponse", + "Rule", + "Rule_Approver", "TaxID", + "Trigger", + "Trigger_All", + "Trigger_Amount", ] diff --git a/src/mercoa/resources/entity/client.py b/src/mercoa/resources/entity/client.py index 1e23c5f..f490a66 100644 --- a/src/mercoa/resources/entity/client.py +++ b/src/mercoa/resources/entity/client.py @@ -13,9 +13,15 @@ from ...core.jsonable_encoder import jsonable_encoder from ...core.remove_none_from_headers import remove_none_from_headers from ...environment import MercoaEnvironment +from ..commons.types.order_direction import OrderDirection from ..invoice.types.currency_code import CurrencyCode +from ..invoice.types.invoice_id import InvoiceId +from ..invoice.types.invoice_order_by_field import InvoiceOrderByField from ..invoice.types.invoice_response import InvoiceResponse from ..invoice.types.invoice_status import InvoiceStatus +from .types.approval_policy_request import ApprovalPolicyRequest +from .types.approval_policy_response import ApprovalPolicyResponse +from .types.approval_policy_update_request import ApprovalPolicyUpdateRequest from .types.entity_add_payees_request import EntityAddPayeesRequest from .types.entity_id import EntityId from .types.entity_request import EntityRequest @@ -23,6 +29,7 @@ from .types.entity_status import EntityStatus from .types.entity_update_request import EntityUpdateRequest from .types.invoice_metrics_response import InvoiceMetricsResponse +from .types.policy_id import PolicyId class EntityClient: @@ -134,12 +141,31 @@ def delete(self, entity_id: EntityId) -> None: raise ApiError(status_code=_response.status_code, body=_response_json) def get_invoices( - self, entity_id: EntityId, *, status: typing.Union[typing.Optional[InvoiceStatus], typing.List[InvoiceStatus]] + self, + entity_id: EntityId, + *, + start_date: typing.Optional[dt.datetime] = None, + end_date: typing.Optional[dt.datetime] = None, + order_by: typing.Optional[InvoiceOrderByField] = None, + order_direction: typing.Optional[OrderDirection] = None, + limit: typing.Optional[int] = None, + starting_after: typing.Optional[InvoiceId] = None, + search: typing.Optional[str] = None, + status: typing.Union[typing.Optional[InvoiceStatus], typing.List[InvoiceStatus]], ) -> typing.List[InvoiceResponse]: _response = httpx.request( "GET", urllib.parse.urljoin(f"{self._environment.value}/", f"entity/{entity_id}/invoices"), - params={"status": status}, + params={ + "startDate": serialize_datetime(start_date) if start_date is not None else None, + "endDate": serialize_datetime(end_date) if end_date is not None else None, + "orderBy": order_by, + "orderDirection": order_direction, + "limit": limit, + "startingAfter": starting_after, + "search": search, + "status": status, + }, headers=remove_none_from_headers( {"Authorization": f"Bearer {self._token}" if self._token is not None else None} ), @@ -156,6 +182,7 @@ def get_invoice_metrics( self, entity_id: EntityId, *, + search: typing.Optional[str] = None, status: typing.Union[typing.Optional[InvoiceStatus], typing.List[InvoiceStatus]], due_date_start: typing.Optional[dt.datetime] = None, due_date_end: typing.Optional[dt.datetime] = None, @@ -167,6 +194,7 @@ def get_invoice_metrics( "GET", urllib.parse.urljoin(f"{self._environment.value}/", f"entity/{entity_id}/invoice-metrics"), params={ + "search": search, "status": status, "dueDateStart": serialize_datetime(due_date_start) if due_date_start is not None else None, "dueDateEnd": serialize_datetime(due_date_end) if due_date_end is not None else None, @@ -251,6 +279,90 @@ def add_payees(self, entity_id: EntityId, *, request: EntityAddPayeesRequest) -> raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) + def create_approval_policy(self, entity_id: EntityId, *, request: ApprovalPolicyRequest) -> ApprovalPolicyResponse: + _response = httpx.request( + "POST", + urllib.parse.urljoin(f"{self._environment.value}/", f"entity/{entity_id}/approval-policy"), + json=jsonable_encoder(request), + headers=remove_none_from_headers( + {"Authorization": f"Bearer {self._token}" if self._token is not None else None} + ), + ) + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(ApprovalPolicyResponse, _response_json) # type: ignore + raise ApiError(status_code=_response.status_code, body=_response_json) + + def get_approval_policy(self, entity_id: EntityId, policy_id: PolicyId) -> ApprovalPolicyResponse: + _response = httpx.request( + "GET", + urllib.parse.urljoin(f"{self._environment.value}/", f"entity/{entity_id}/approval-policy/{policy_id}"), + headers=remove_none_from_headers( + {"Authorization": f"Bearer {self._token}" if self._token is not None else None} + ), + ) + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(ApprovalPolicyResponse, _response_json) # type: ignore + raise ApiError(status_code=_response.status_code, body=_response_json) + + def update_approval_policy( + self, entity_id: EntityId, policy_id: PolicyId, *, request: ApprovalPolicyUpdateRequest + ) -> ApprovalPolicyResponse: + _response = httpx.request( + "POST", + urllib.parse.urljoin(f"{self._environment.value}/", f"entity/{entity_id}/approval-policy/{policy_id}"), + json=jsonable_encoder(request), + headers=remove_none_from_headers( + {"Authorization": f"Bearer {self._token}" if self._token is not None else None} + ), + ) + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(ApprovalPolicyResponse, _response_json) # type: ignore + raise ApiError(status_code=_response.status_code, body=_response_json) + + def delete_approval_policy(self, entity_id: EntityId, policy_id: PolicyId) -> None: + _response = httpx.request( + "DELETE", + urllib.parse.urljoin(f"{self._environment.value}/", f"entity/{entity_id}/approval-policy/{policy_id}"), + headers=remove_none_from_headers( + {"Authorization": f"Bearer {self._token}" if self._token is not None else None} + ), + ) + if 200 <= _response.status_code < 300: + return + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def get_all_approval_policies(self, entity_id: EntityId) -> typing.List[ApprovalPolicyResponse]: + _response = httpx.request( + "GET", + urllib.parse.urljoin(f"{self._environment.value}/", f"entity/{entity_id}/approval-policies"), + headers=remove_none_from_headers( + {"Authorization": f"Bearer {self._token}" if self._token is not None else None} + ), + ) + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(typing.List[ApprovalPolicyResponse], _response_json) # type: ignore + raise ApiError(status_code=_response.status_code, body=_response_json) + class AsyncEntityClient: def __init__( @@ -367,13 +479,32 @@ async def delete(self, entity_id: EntityId) -> None: raise ApiError(status_code=_response.status_code, body=_response_json) async def get_invoices( - self, entity_id: EntityId, *, status: typing.Union[typing.Optional[InvoiceStatus], typing.List[InvoiceStatus]] + self, + entity_id: EntityId, + *, + start_date: typing.Optional[dt.datetime] = None, + end_date: typing.Optional[dt.datetime] = None, + order_by: typing.Optional[InvoiceOrderByField] = None, + order_direction: typing.Optional[OrderDirection] = None, + limit: typing.Optional[int] = None, + starting_after: typing.Optional[InvoiceId] = None, + search: typing.Optional[str] = None, + status: typing.Union[typing.Optional[InvoiceStatus], typing.List[InvoiceStatus]], ) -> typing.List[InvoiceResponse]: async with httpx.AsyncClient() as _client: _response = await _client.request( "GET", urllib.parse.urljoin(f"{self._environment.value}/", f"entity/{entity_id}/invoices"), - params={"status": status}, + params={ + "startDate": serialize_datetime(start_date) if start_date is not None else None, + "endDate": serialize_datetime(end_date) if end_date is not None else None, + "orderBy": order_by, + "orderDirection": order_direction, + "limit": limit, + "startingAfter": starting_after, + "search": search, + "status": status, + }, headers=remove_none_from_headers( {"Authorization": f"Bearer {self._token}" if self._token is not None else None} ), @@ -390,6 +521,7 @@ async def get_invoice_metrics( self, entity_id: EntityId, *, + search: typing.Optional[str] = None, status: typing.Union[typing.Optional[InvoiceStatus], typing.List[InvoiceStatus]], due_date_start: typing.Optional[dt.datetime] = None, due_date_end: typing.Optional[dt.datetime] = None, @@ -402,6 +534,7 @@ async def get_invoice_metrics( "GET", urllib.parse.urljoin(f"{self._environment.value}/", f"entity/{entity_id}/invoice-metrics"), params={ + "search": search, "status": status, "dueDateStart": serialize_datetime(due_date_start) if due_date_start is not None else None, "dueDateEnd": serialize_datetime(due_date_end) if due_date_end is not None else None, @@ -491,3 +624,94 @@ async def add_payees(self, entity_id: EntityId, *, request: EntityAddPayeesReque except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) + + async def create_approval_policy( + self, entity_id: EntityId, *, request: ApprovalPolicyRequest + ) -> ApprovalPolicyResponse: + async with httpx.AsyncClient() as _client: + _response = await _client.request( + "POST", + urllib.parse.urljoin(f"{self._environment.value}/", f"entity/{entity_id}/approval-policy"), + json=jsonable_encoder(request), + headers=remove_none_from_headers( + {"Authorization": f"Bearer {self._token}" if self._token is not None else None} + ), + ) + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(ApprovalPolicyResponse, _response_json) # type: ignore + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def get_approval_policy(self, entity_id: EntityId, policy_id: PolicyId) -> ApprovalPolicyResponse: + async with httpx.AsyncClient() as _client: + _response = await _client.request( + "GET", + urllib.parse.urljoin(f"{self._environment.value}/", f"entity/{entity_id}/approval-policy/{policy_id}"), + headers=remove_none_from_headers( + {"Authorization": f"Bearer {self._token}" if self._token is not None else None} + ), + ) + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(ApprovalPolicyResponse, _response_json) # type: ignore + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def update_approval_policy( + self, entity_id: EntityId, policy_id: PolicyId, *, request: ApprovalPolicyUpdateRequest + ) -> ApprovalPolicyResponse: + async with httpx.AsyncClient() as _client: + _response = await _client.request( + "POST", + urllib.parse.urljoin(f"{self._environment.value}/", f"entity/{entity_id}/approval-policy/{policy_id}"), + json=jsonable_encoder(request), + headers=remove_none_from_headers( + {"Authorization": f"Bearer {self._token}" if self._token is not None else None} + ), + ) + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(ApprovalPolicyResponse, _response_json) # type: ignore + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def delete_approval_policy(self, entity_id: EntityId, policy_id: PolicyId) -> None: + async with httpx.AsyncClient() as _client: + _response = await _client.request( + "DELETE", + urllib.parse.urljoin(f"{self._environment.value}/", f"entity/{entity_id}/approval-policy/{policy_id}"), + headers=remove_none_from_headers( + {"Authorization": f"Bearer {self._token}" if self._token is not None else None} + ), + ) + if 200 <= _response.status_code < 300: + return + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def get_all_approval_policies(self, entity_id: EntityId) -> typing.List[ApprovalPolicyResponse]: + async with httpx.AsyncClient() as _client: + _response = await _client.request( + "GET", + urllib.parse.urljoin(f"{self._environment.value}/", f"entity/{entity_id}/approval-policies"), + headers=remove_none_from_headers( + {"Authorization": f"Bearer {self._token}" if self._token is not None else None} + ), + ) + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(typing.List[ApprovalPolicyResponse], _response_json) # type: ignore + raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/mercoa/resources/entity/types/__init__.py b/src/mercoa/resources/entity/types/__init__.py index 0b67377..10f751a 100644 --- a/src/mercoa/resources/entity/types/__init__.py +++ b/src/mercoa/resources/entity/types/__init__.py @@ -1,6 +1,11 @@ # This file was auto-generated by Fern from our API Definition. from .account_type import AccountType +from .amount_trigger import AmountTrigger +from .approval_policy_request import ApprovalPolicyRequest +from .approval_policy_response import ApprovalPolicyResponse +from .approval_policy_update_request import ApprovalPolicyUpdateRequest +from .approver_rule import ApproverRule from .business_profile_request import BusinessProfileRequest from .business_profile_response import BusinessProfileResponse from .business_type import BusinessType @@ -11,15 +16,24 @@ from .entity_response import EntityResponse from .entity_status import EntityStatus from .entity_update_request import EntityUpdateRequest +from .identifier_list import IdentifierList, IdentifierList_RolesList, IdentifierList_UserList from .individual_profile_request import IndividualProfileRequest from .individual_profile_response import IndividualProfileResponse from .invoice_metrics_response import InvoiceMetricsResponse +from .policy_id import PolicyId from .profile_request import ProfileRequest from .profile_response import ProfileResponse +from .rule import Rule, Rule_Approver from .tax_id import TaxID +from .trigger import Trigger, Trigger_All, Trigger_Amount __all__ = [ "AccountType", + "AmountTrigger", + "ApprovalPolicyRequest", + "ApprovalPolicyResponse", + "ApprovalPolicyUpdateRequest", + "ApproverRule", "BusinessProfileRequest", "BusinessProfileResponse", "BusinessType", @@ -30,10 +44,19 @@ "EntityResponse", "EntityStatus", "EntityUpdateRequest", + "IdentifierList", + "IdentifierList_RolesList", + "IdentifierList_UserList", "IndividualProfileRequest", "IndividualProfileResponse", "InvoiceMetricsResponse", + "PolicyId", "ProfileRequest", "ProfileResponse", + "Rule", + "Rule_Approver", "TaxID", + "Trigger", + "Trigger_All", + "Trigger_Amount", ] diff --git a/src/mercoa/resources/entity/types/amount_trigger.py b/src/mercoa/resources/entity/types/amount_trigger.py new file mode 100644 index 0000000..fcbd218 --- /dev/null +++ b/src/mercoa/resources/entity/types/amount_trigger.py @@ -0,0 +1,26 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ....core.datetime_utils import serialize_datetime +from ...invoice.types.currency_code import CurrencyCode + + +class AmountTrigger(pydantic.BaseModel): + amount: float + currency: CurrencyCode + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/mercoa/resources/entity/types/approval_policy_request.py b/src/mercoa/resources/entity/types/approval_policy_request.py new file mode 100644 index 0000000..ec70068 --- /dev/null +++ b/src/mercoa/resources/entity/types/approval_policy_request.py @@ -0,0 +1,32 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ....core.datetime_utils import serialize_datetime +from .policy_id import PolicyId +from .rule import Rule +from .trigger import Trigger + + +class ApprovalPolicyRequest(pydantic.BaseModel): + trigger: Trigger + rule: Rule + upstream_policy_id: PolicyId = pydantic.Field( + alias="upstreamPolicyId", description=("Use 'root' if no upstreamPolicyId is intended to be set.\n") + ) + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + allow_population_by_field_name = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/mercoa/resources/entity/types/approval_policy_response.py b/src/mercoa/resources/entity/types/approval_policy_response.py new file mode 100644 index 0000000..9cfd4db --- /dev/null +++ b/src/mercoa/resources/entity/types/approval_policy_response.py @@ -0,0 +1,31 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ....core.datetime_utils import serialize_datetime +from .policy_id import PolicyId +from .rule import Rule +from .trigger import Trigger + + +class ApprovalPolicyResponse(pydantic.BaseModel): + id: PolicyId + trigger: Trigger + rule: Rule + upstream_policy_id: PolicyId = pydantic.Field(alias="upstreamPolicyId") + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + allow_population_by_field_name = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/mercoa/resources/entity/types/approval_policy_update_request.py b/src/mercoa/resources/entity/types/approval_policy_update_request.py new file mode 100644 index 0000000..3440ec4 --- /dev/null +++ b/src/mercoa/resources/entity/types/approval_policy_update_request.py @@ -0,0 +1,31 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ....core.datetime_utils import serialize_datetime +from .policy_id import PolicyId +from .rule import Rule +from .trigger import Trigger + + +class ApprovalPolicyUpdateRequest(pydantic.BaseModel): + id: PolicyId + trigger: typing.Optional[Trigger] + rule: typing.Optional[Rule] + upstream_policy_id: typing.Optional[PolicyId] = pydantic.Field(alias="upstreamPolicyId") + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + allow_population_by_field_name = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/mercoa/resources/entity/types/approver_rule.py b/src/mercoa/resources/entity/types/approver_rule.py new file mode 100644 index 0000000..b09d82f --- /dev/null +++ b/src/mercoa/resources/entity/types/approver_rule.py @@ -0,0 +1,27 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ....core.datetime_utils import serialize_datetime +from .identifier_list import IdentifierList + + +class ApproverRule(pydantic.BaseModel): + num_approvers: int = pydantic.Field(alias="numApprovers") + identifier_list: IdentifierList = pydantic.Field(alias="identifierList") + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + allow_population_by_field_name = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/mercoa/resources/entity/types/entity_add_payees_request.py b/src/mercoa/resources/entity/types/entity_add_payees_request.py index c28e854..cb66a91 100644 --- a/src/mercoa/resources/entity/types/entity_add_payees_request.py +++ b/src/mercoa/resources/entity/types/entity_add_payees_request.py @@ -10,7 +10,9 @@ class EntityAddPayeesRequest(pydantic.BaseModel): - payees: typing.List[EntityId] + payees: typing.List[EntityId] = pydantic.Field( + description=("List of payee entity IDs to associate with the entity\n") + ) def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} diff --git a/src/mercoa/resources/entity/types/identifier_list.py b/src/mercoa/resources/entity/types/identifier_list.py new file mode 100644 index 0000000..42230f8 --- /dev/null +++ b/src/mercoa/resources/entity/types/identifier_list.py @@ -0,0 +1,31 @@ +# This file was auto-generated by Fern from our API Definition. + +from __future__ import annotations + +import typing + +import pydantic +import typing_extensions + +from ...entity_users.types.entity_user_id import EntityUserId + + +class IdentifierList_RolesList(pydantic.BaseModel): + type: typing_extensions.Literal["rolesList"] + value: typing.List[str] + + class Config: + frozen = True + + +class IdentifierList_UserList(pydantic.BaseModel): + type: typing_extensions.Literal["userList"] + value: typing.List[EntityUserId] + + class Config: + frozen = True + + +IdentifierList = typing_extensions.Annotated[ + typing.Union[IdentifierList_RolesList, IdentifierList_UserList], pydantic.Field(discriminator="type") +] diff --git a/src/mercoa/resources/entity/types/policy_id.py b/src/mercoa/resources/entity/types/policy_id.py new file mode 100644 index 0000000..b59232f --- /dev/null +++ b/src/mercoa/resources/entity/types/policy_id.py @@ -0,0 +1,3 @@ +# This file was auto-generated by Fern from our API Definition. + +PolicyId = str diff --git a/src/mercoa/resources/entity/types/rule.py b/src/mercoa/resources/entity/types/rule.py new file mode 100644 index 0000000..44063d9 --- /dev/null +++ b/src/mercoa/resources/entity/types/rule.py @@ -0,0 +1,20 @@ +# This file was auto-generated by Fern from our API Definition. + +from __future__ import annotations + +import typing + +import pydantic +import typing_extensions + +from .approver_rule import ApproverRule + + +class Rule_Approver(ApproverRule): + type: typing_extensions.Literal["approver"] + + class Config: + frozen = True + + +Rule = typing_extensions.Annotated[typing.Union[Rule_Approver], pydantic.Field(discriminator="type")] diff --git a/src/mercoa/resources/entity/types/trigger.py b/src/mercoa/resources/entity/types/trigger.py new file mode 100644 index 0000000..ffe52f0 --- /dev/null +++ b/src/mercoa/resources/entity/types/trigger.py @@ -0,0 +1,28 @@ +# This file was auto-generated by Fern from our API Definition. + +from __future__ import annotations + +import typing + +import pydantic +import typing_extensions + +from .amount_trigger import AmountTrigger + + +class Trigger_Amount(AmountTrigger): + type: typing_extensions.Literal["amount"] + + class Config: + frozen = True + + +class Trigger_All(pydantic.BaseModel): + type: typing_extensions.Literal["all"] + value: typing.Any + + class Config: + frozen = True + + +Trigger = typing_extensions.Annotated[typing.Union[Trigger_Amount, Trigger_All], pydantic.Field(discriminator="type")] diff --git a/src/mercoa/resources/invoice/__init__.py b/src/mercoa/resources/invoice/__init__.py index c8c19fb..55718a9 100644 --- a/src/mercoa/resources/invoice/__init__.py +++ b/src/mercoa/resources/invoice/__init__.py @@ -1,6 +1,10 @@ # This file was auto-generated by Fern from our API Definition. from .types import ( + ApprovalRequest, + Approver, + ApproverAction, + ApproverResponse, CommentId, CommentRequest, CommentResponse, @@ -10,12 +14,17 @@ InvoiceId, InvoiceLineItemRequest, InvoiceLineItemResponse, + InvoiceOrderByField, InvoiceRequest, InvoiceResponse, InvoiceStatus, ) __all__ = [ + "ApprovalRequest", + "Approver", + "ApproverAction", + "ApproverResponse", "CommentId", "CommentRequest", "CommentResponse", @@ -25,6 +34,7 @@ "InvoiceId", "InvoiceLineItemRequest", "InvoiceLineItemResponse", + "InvoiceOrderByField", "InvoiceRequest", "InvoiceResponse", "InvoiceStatus", diff --git a/src/mercoa/resources/invoice/client.py b/src/mercoa/resources/invoice/client.py index 3f5ba2a..619926b 100644 --- a/src/mercoa/resources/invoice/client.py +++ b/src/mercoa/resources/invoice/client.py @@ -11,6 +11,7 @@ from ...core.jsonable_encoder import jsonable_encoder from ...core.remove_none_from_headers import remove_none_from_headers from ...environment import MercoaEnvironment +from .types.approval_request import ApprovalRequest from .types.comment_id import CommentId from .types.comment_request import CommentRequest from .types.comment_response import CommentResponse @@ -109,6 +110,40 @@ def get_documents(self, invoice_id: InvoiceId) -> typing.List[DocumentResponse]: return pydantic.parse_obj_as(typing.List[DocumentResponse], _response_json) # type: ignore raise ApiError(status_code=_response.status_code, body=_response_json) + def approve(self, invoice_id: InvoiceId, *, request: ApprovalRequest) -> InvoiceResponse: + _response = httpx.request( + "POST", + urllib.parse.urljoin(f"{self._environment.value}/", f"invoice/{invoice_id}/approve"), + json=jsonable_encoder(request), + headers=remove_none_from_headers( + {"Authorization": f"Bearer {self._token}" if self._token is not None else None} + ), + ) + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(InvoiceResponse, _response_json) # type: ignore + raise ApiError(status_code=_response.status_code, body=_response_json) + + def reject(self, invoice_id: InvoiceId, *, request: ApprovalRequest) -> InvoiceResponse: + _response = httpx.request( + "POST", + urllib.parse.urljoin(f"{self._environment.value}/", f"invoice/{invoice_id}/reject"), + json=jsonable_encoder(request), + headers=remove_none_from_headers( + {"Authorization": f"Bearer {self._token}" if self._token is not None else None} + ), + ) + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(InvoiceResponse, _response_json) # type: ignore + raise ApiError(status_code=_response.status_code, body=_response_json) + def get_comments(self, invoice_id: InvoiceId) -> typing.List[CommentResponse]: _response = httpx.request( "GET", @@ -302,6 +337,42 @@ async def get_documents(self, invoice_id: InvoiceId) -> typing.List[DocumentResp return pydantic.parse_obj_as(typing.List[DocumentResponse], _response_json) # type: ignore raise ApiError(status_code=_response.status_code, body=_response_json) + async def approve(self, invoice_id: InvoiceId, *, request: ApprovalRequest) -> InvoiceResponse: + async with httpx.AsyncClient() as _client: + _response = await _client.request( + "POST", + urllib.parse.urljoin(f"{self._environment.value}/", f"invoice/{invoice_id}/approve"), + json=jsonable_encoder(request), + headers=remove_none_from_headers( + {"Authorization": f"Bearer {self._token}" if self._token is not None else None} + ), + ) + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(InvoiceResponse, _response_json) # type: ignore + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def reject(self, invoice_id: InvoiceId, *, request: ApprovalRequest) -> InvoiceResponse: + async with httpx.AsyncClient() as _client: + _response = await _client.request( + "POST", + urllib.parse.urljoin(f"{self._environment.value}/", f"invoice/{invoice_id}/reject"), + json=jsonable_encoder(request), + headers=remove_none_from_headers( + {"Authorization": f"Bearer {self._token}" if self._token is not None else None} + ), + ) + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(InvoiceResponse, _response_json) # type: ignore + raise ApiError(status_code=_response.status_code, body=_response_json) + async def get_comments(self, invoice_id: InvoiceId) -> typing.List[CommentResponse]: async with httpx.AsyncClient() as _client: _response = await _client.request( diff --git a/src/mercoa/resources/invoice/types/__init__.py b/src/mercoa/resources/invoice/types/__init__.py index 473e8b9..3676d6d 100644 --- a/src/mercoa/resources/invoice/types/__init__.py +++ b/src/mercoa/resources/invoice/types/__init__.py @@ -1,5 +1,9 @@ # This file was auto-generated by Fern from our API Definition. +from .approval_request import ApprovalRequest +from .approver import Approver +from .approver_action import ApproverAction +from .approver_response import ApproverResponse from .comment_id import CommentId from .comment_request import CommentRequest from .comment_response import CommentResponse @@ -9,11 +13,16 @@ from .invoice_id import InvoiceId from .invoice_line_item_request import InvoiceLineItemRequest from .invoice_line_item_response import InvoiceLineItemResponse +from .invoice_order_by_field import InvoiceOrderByField from .invoice_request import InvoiceRequest from .invoice_response import InvoiceResponse from .invoice_status import InvoiceStatus __all__ = [ + "ApprovalRequest", + "Approver", + "ApproverAction", + "ApproverResponse", "CommentId", "CommentRequest", "CommentResponse", @@ -23,6 +32,7 @@ "InvoiceId", "InvoiceLineItemRequest", "InvoiceLineItemResponse", + "InvoiceOrderByField", "InvoiceRequest", "InvoiceResponse", "InvoiceStatus", diff --git a/src/mercoa/resources/invoice/types/approval_request.py b/src/mercoa/resources/invoice/types/approval_request.py new file mode 100644 index 0000000..0bb663f --- /dev/null +++ b/src/mercoa/resources/invoice/types/approval_request.py @@ -0,0 +1,27 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ....core.datetime_utils import serialize_datetime +from ...entity_users.types.entity_user_id import EntityUserId + + +class ApprovalRequest(pydantic.BaseModel): + text: typing.Optional[str] + user_id: EntityUserId = pydantic.Field(alias="userId") + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + allow_population_by_field_name = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/mercoa/resources/invoice/types/approver.py b/src/mercoa/resources/invoice/types/approver.py new file mode 100644 index 0000000..03135b4 --- /dev/null +++ b/src/mercoa/resources/invoice/types/approver.py @@ -0,0 +1,29 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic + +from ....core.datetime_utils import serialize_datetime +from ...entity_users.types.entity_user_id import EntityUserId +from .approver_action import ApproverAction + + +class Approver(pydantic.BaseModel): + user_id: EntityUserId = pydantic.Field(alias="userId") + date: dt.datetime + action: ApproverAction + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + allow_population_by_field_name = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/mercoa/resources/invoice/types/approver_action.py b/src/mercoa/resources/invoice/types/approver_action.py new file mode 100644 index 0000000..92427f1 --- /dev/null +++ b/src/mercoa/resources/invoice/types/approver_action.py @@ -0,0 +1,25 @@ +# This file was auto-generated by Fern from our API Definition. + +import enum +import typing + +T_Result = typing.TypeVar("T_Result") + + +class ApproverAction(str, enum.Enum): + NONE = "NONE" + APPROVE = "APPROVE" + REJECT = "REJECT" + + def visit( + self, + none: typing.Callable[[], T_Result], + approve: typing.Callable[[], T_Result], + reject: typing.Callable[[], T_Result], + ) -> T_Result: + if self is ApproverAction.NONE: + return none() + if self is ApproverAction.APPROVE: + return approve() + if self is ApproverAction.REJECT: + return reject() diff --git a/src/mercoa/resources/invoice/types/approver_response.py b/src/mercoa/resources/invoice/types/approver_response.py new file mode 100644 index 0000000..e162f88 --- /dev/null +++ b/src/mercoa/resources/invoice/types/approver_response.py @@ -0,0 +1,24 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +from ....core.datetime_utils import serialize_datetime +from ...entity_users.types.entity_user_response import EntityUserResponse +from .approver import Approver + + +class ApproverResponse(Approver): + user: typing.Optional[EntityUserResponse] + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().dict(**kwargs_with_defaults) + + class Config: + frozen = True + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/mercoa/resources/invoice/types/comment_response.py b/src/mercoa/resources/invoice/types/comment_response.py index 4f4a72b..77d6342 100644 --- a/src/mercoa/resources/invoice/types/comment_response.py +++ b/src/mercoa/resources/invoice/types/comment_response.py @@ -7,12 +7,14 @@ from ....core.datetime_utils import serialize_datetime from ...entity_users.types.entity_user_response import EntityUserResponse +from .approver import Approver class CommentResponse(pydantic.BaseModel): id: str text: str user: typing.Optional[EntityUserResponse] + approval: typing.Optional[Approver] created_at: dt.datetime = pydantic.Field(alias="createdAt") updated_at: dt.datetime = pydantic.Field(alias="updatedAt") diff --git a/src/mercoa/resources/invoice/types/invoice_order_by_field.py b/src/mercoa/resources/invoice/types/invoice_order_by_field.py new file mode 100644 index 0000000..2073ed2 --- /dev/null +++ b/src/mercoa/resources/invoice/types/invoice_order_by_field.py @@ -0,0 +1,29 @@ +# This file was auto-generated by Fern from our API Definition. + +import enum +import typing + +T_Result = typing.TypeVar("T_Result") + + +class InvoiceOrderByField(str, enum.Enum): + AMOUNT = "AMOUNT" + DUE_DATE = "DUE_DATE" + CREATED_AT = "CREATED_AT" + INVOICE_NUMBER = "INVOICE_NUMBER" + + def visit( + self, + amount: typing.Callable[[], T_Result], + due_date: typing.Callable[[], T_Result], + created_at: typing.Callable[[], T_Result], + invoice_number: typing.Callable[[], T_Result], + ) -> T_Result: + if self is InvoiceOrderByField.AMOUNT: + return amount() + if self is InvoiceOrderByField.DUE_DATE: + return due_date() + if self is InvoiceOrderByField.CREATED_AT: + return created_at() + if self is InvoiceOrderByField.INVOICE_NUMBER: + return invoice_number() diff --git a/src/mercoa/resources/invoice/types/invoice_request.py b/src/mercoa/resources/invoice/types/invoice_request.py index 06d914d..6ae3f5c 100644 --- a/src/mercoa/resources/invoice/types/invoice_request.py +++ b/src/mercoa/resources/invoice/types/invoice_request.py @@ -50,6 +50,11 @@ class InvoiceRequest(pydantic.BaseModel): ), ) line_items: typing.Optional[typing.List[InvoiceLineItemRequest]] = pydantic.Field(alias="lineItems") + metadata: typing.Optional[typing.Dict[str, str]] = pydantic.Field( + description=( + "Metadata associated with this invoice. You can specify up to 10 keys, with key names up to 40 characters long and values up to 200 characters long.\n" + ) + ) uploaded_image: typing.Optional[str] = pydantic.Field( alias="uploadedImage", description=("Base64 encoded image or PDF of invoice. PNG, JPG, and PDF are supported. 10MB max.\n"), diff --git a/src/mercoa/resources/invoice/types/invoice_response.py b/src/mercoa/resources/invoice/types/invoice_response.py index 8a3fe7a..f108223 100644 --- a/src/mercoa/resources/invoice/types/invoice_response.py +++ b/src/mercoa/resources/invoice/types/invoice_response.py @@ -12,6 +12,7 @@ from ...payment_method.types.payment_method_id import PaymentMethodId from ...payment_method.types.payment_method_response import PaymentMethodResponse from ...transaction.types.transaction_response import TransactionResponse +from .approver import Approver from .comment_response import CommentResponse from .currency_code import CurrencyCode from .invoice_id import InvoiceId @@ -51,6 +52,8 @@ class InvoiceResponse(pydantic.BaseModel): comments: typing.Optional[typing.List[CommentResponse]] transactions: typing.Optional[typing.List[TransactionResponse]] line_items: typing.Optional[typing.List[InvoiceLineItemResponse]] = pydantic.Field(alias="lineItems") + approvers: typing.List[Approver] + metadata: typing.Dict[str, str] = pydantic.Field(description=("Metadata associated with this invoice.\n")) created_by: typing.Optional[EntityUserResponse] = pydantic.Field( alias="createdBy", description=("Entity user who created this invoice.\n") ) diff --git a/src/mercoa/resources/organization/types/payment_rail_response.py b/src/mercoa/resources/organization/types/payment_rail_response.py index 49f6bbb..2d500df 100644 --- a/src/mercoa/resources/organization/types/payment_rail_response.py +++ b/src/mercoa/resources/organization/types/payment_rail_response.py @@ -8,7 +8,7 @@ class PaymentRailResponse(PaymentRailRequest): - avaliable: bool + available: bool def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs}