From 43aaddedaa7c7d944ceee9bfd90ee3c1a3805dc4 Mon Sep 17 00:00:00 2001 From: Zev Averbach Date: Sat, 23 Apr 2022 18:25:31 +0200 Subject: [PATCH] removed lru_cache, made get_all_invoices_for_org_name faster, started revising readme --- README.md | 19 +++++++------------ avt_fresh/invoice.py | 31 ++++++++++++++++--------------- 2 files changed, 23 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index cca1977..bda602a 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,18 @@ # AVT Fresh! -This is a wrapper of [the Freshbooks web API](https://www.freshbooks.com/api/start). It is far from comprehensive: It was created for the specific client- and invoice-related needs of [Averbach Transcription](https://avtranscription.com). +This is a wrapper of [the Freshbooks web API](https://www.freshbooks.com/api/start). It is far from comprehensive: It was created for the specific client- and invoice-related needs of [Averbach Transcription](https://avtranscription.com). However, there are "band-aids" here to work around some of the API's shortcomings. For example, you don't have to deal with pagination at all. 🎉 -There are "band-aids" here to work around some of the API's shortcomings. For example, you don't have to deal with pagination at all. 🎉 +Install it with `pip install avt-fresh`. -# Installation - -``` -pip install avt-fresh -``` - -# Usage -Instantiate the avt_fresh `Client` like so, and you're off to the races: +Here's how you use it: ```python from avt_fresh import ApiClient client = ApiClient(client_secret="...", client_id="...", redirect_uri="https://...", account_id="...") + monster_invoices = client.get_all_invoices_for_org_name("Monsters Inc") +client.get_one_invoice(12345) ``` You can get and set the required arguments to `ApiClient` [here](https://my.freshbooks.com/#/developer). Well, all of them except `FRESHBOOKS_ACCOUNT_ID`, which you can see (there's got to be another way??) by clicking on one of your invoices and grabbing the substring here: `https://my.freshbooks.com/#/invoice/-1234567`. @@ -145,8 +140,8 @@ client = Client( client_id="...", redirect_uri="https://...", account_id="...", - token_store=avt_fresh.token.TokenStoreOnRedis, - connection_string="rediss://..." , + token_store=avt_fresh.token.TokenStoreOnRedis, + connection_string="redis://..." , ) ``` diff --git a/avt_fresh/invoice.py b/avt_fresh/invoice.py index ac2a21b..bcd243a 100644 --- a/avt_fresh/invoice.py +++ b/avt_fresh/invoice.py @@ -1,6 +1,6 @@ import datetime as dt -from decimal import Decimal -from functools import partial, lru_cache +import decimal +import functools import typing WHAT = "invoice" @@ -27,22 +27,22 @@ class FreshbooksLine(typing.NamedTuple): client_id: int description: str name: str - rate: Decimal + rate: decimal.Decimal line_id: int - quantity: Decimal - amount: Decimal + quantity: decimal.Decimal + amount: decimal.Decimal @classmethod def from_api(cls, **kwargs): return cls( invoice_id=kwargs["invoice_id"], client_id=kwargs["client_id"], - rate=Decimal(kwargs["unit_cost"]["amount"]), + rate=decimal.Decimal(kwargs["unit_cost"]["amount"]), description=kwargs["description"], name=kwargs["name"], - quantity=Decimal(kwargs["qty"]), + quantity=decimal.Decimal(kwargs["qty"]), line_id=kwargs["lineid"], - amount=Decimal(kwargs["amount"]["amount"]), + amount=decimal.Decimal(kwargs["amount"]["amount"]), ) @property @@ -63,9 +63,9 @@ class FreshbooksInvoice(typing.NamedTuple): invoice_id: int number: str organization: str - amount: Decimal + amount: decimal.Decimal status: str - amount_outstanding: Decimal + amount_outstanding: decimal.Decimal po_number: str line_id_line_dict: dict line_description_line_dict: dict @@ -101,8 +101,8 @@ class FreshbooksInvoice(typing.NamedTuple): number=kwargs["invoice_number"], organization=kwargs["organization"], allowed_gateways=kwargs["allowed_gateways"], - amount=Decimal(kwargs["amount"]["amount"]), - amount_outstanding=Decimal(kwargs["outstanding"]["amount"]), + amount=decimal.Decimal(kwargs["amount"]["amount"]), + amount_outstanding=decimal.Decimal(kwargs["outstanding"]["amount"]), contacts={contact["email"]: contact for contact in kwargs["contacts"]}, status=kwargs["v3_status"], ) @@ -115,10 +115,11 @@ def get_all_draft_invoices(*, get_func: typing.Callable) -> list[FreshbooksInvoi def get_all_invoices_for_org_name( *, get_func: typing.Callable, org_name: str ) -> list[FreshbooksInvoice]: - return _get(get_func=get_func, org_name=org_name) + from avt_fresh.client import get_freshbooks_client_from_org_name + client_id = get_freshbooks_client_from_org_name(get_func=get_func, org_name=org_name).client_id + return get_all_invoices_for_client_id(get_func=get_func, client_id=client_id) -@lru_cache def get_all_invoices_for_client_id( *, get_func: typing.Callable, client_id: int ) -> list[FreshbooksInvoice]: @@ -147,7 +148,7 @@ def _get( org_name=None, status=None, ) -> list[FreshbooksInvoice]: - get_func = partial(get_func, what=WHAT) + get_func = functools.partial(get_func, what=WHAT) if client_id is not None and org_name is not None: raise ArgumentError("Please provide either client_id or org_name")