diff --git a/README.md b/README.md index 85de1e0..723edf3 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,7 @@ poetry run mypy src/ --check-untyped-defs # Running test poetry run coverage run -m pytest # all tests -poetry run coverage run -m pytest -s tests/presentation/test_server.py # specific file +poetry run coverage run -m pytest tests/presentation/test_server.py # specific file poetry run coverage run -m pytest tests/presentation/test_worker.py -k 'test_should_select_by_account_id' # specific test ``` diff --git a/src/core/helpers.py b/src/core/helpers.py index 9b59b92..40b481d 100644 --- a/src/core/helpers.py +++ b/src/core/helpers.py @@ -3,10 +3,7 @@ def is_valid_uuid(value: Any): - try: - return uuid.UUID(str(value)) - except ValueError as exc: - raise exc + return uuid.UUID(str(value)) class FlowPostPaidError(Exception): @@ -17,3 +14,8 @@ def __init__(self): class FlowPrePaidError(Exception): def __init__(self): super().__init__("This flow should only be used by pre-paid plan") + + +class InvoicePostPaidError(Exception): + def __init__(self): + super().__init__("Every post-paid user should have at least a draft invoice") diff --git a/src/core/repository/account.py b/src/core/repository/account.py index 48602a4..04cbc46 100644 --- a/src/core/repository/account.py +++ b/src/core/repository/account.py @@ -102,7 +102,6 @@ def change_type(self, account_id_: UUID, type_: AccountType) -> None: def by_subscription_period(self) -> List[Account]: today = datetime.datetime.today() - should_be_deleted = subscription_table.c.deleted_at is None query_subscription = ( select(account_table) .join( @@ -110,8 +109,8 @@ def by_subscription_period(self) -> List[Account]: account_table.c.id == subscription_table.c.account_id, ) .where( - extract("day", subscription_table.c.created_at) - == today.day & should_be_deleted, + extract("day", subscription_table.c.created_at) == today.day, + subscription_table.c.deleted_at.__eq__(None), ) ) rows = self.session.execute(query_subscription).all() diff --git a/src/core/repository/billing.py b/src/core/repository/billing.py index 121e5cf..5555cf9 100644 --- a/src/core/repository/billing.py +++ b/src/core/repository/billing.py @@ -12,6 +12,7 @@ from src.core.usecase.driven.billing.billing_fetch_user import BillingFetchUser from src.core.usecase.driven.billing.billing_fetching_invoice import ( BillingFetchingInvoice, + NoDraftInvoiceFound, ) from src.core.usecase.driven.billing.billing_updating_invoice import ( BillingUpdatingInvoice, @@ -33,7 +34,7 @@ def get_current(self, external_id: UUID) -> Invoice: ) json = resp.json() if json["status"] != "draft": - raise Exception("No invoice on status draft was fetched") + raise NoDraftInvoiceFound("No invoice on status draft was fetched") return Invoice( json["id"], external_id, @@ -52,7 +53,7 @@ def add_item(self, external_id: UUID, item_list: List[InvoiceItem]) -> Invoice: is_valid_uuid(json["id"]), is_valid_uuid(json["user_id"]), json["status"], - datetime.datetime.strptime(json["created_at"], "%d/%m/%y"), + datetime.datetime.strptime(json["created_at"], "%Y-%m-%d"), ) return invoice except HTTPError as exc: diff --git a/src/core/usecase/charge_debit.py b/src/core/usecase/charge_debit.py index cdccfd6..96436e5 100644 --- a/src/core/usecase/charge_debit.py +++ b/src/core/usecase/charge_debit.py @@ -1,4 +1,5 @@ from src.core.entity.account import Account, AccountType +from src.core.helpers import InvoicePostPaidError from src.core.usecase.driven.billing.billing_fetching_invoice import ( BillingFetchingInvoice, ) @@ -34,6 +35,6 @@ def _charge_single_user(self, user: Account) -> None: return current_invoice = self.billing_fetching_invoice.get_current(user.external_id) if current_invoice.status != "draft": - raise Exception("Every post-paid user should have at least a draft invoice") + raise InvoicePostPaidError() self.billing_updating_invoice.charge(current_invoice.id) return None diff --git a/src/core/usecase/driven/billing/billing_fetching_invoice.py b/src/core/usecase/driven/billing/billing_fetching_invoice.py index 57021b8..a0f0780 100644 --- a/src/core/usecase/driven/billing/billing_fetching_invoice.py +++ b/src/core/usecase/driven/billing/billing_fetching_invoice.py @@ -4,6 +4,10 @@ from src.core.entity.billing import Invoice +class NoDraftInvoiceFound(Exception): + "Raised when account does not exists on database" + + class BillingFetchingInvoice(metaclass=ABCMeta): @abstractmethod def get_current(self, external_id: UUID) -> Invoice: diff --git a/src/presentation/worker.py b/src/presentation/worker.py index e1febc8..62e992a 100644 --- a/src/presentation/worker.py +++ b/src/presentation/worker.py @@ -35,7 +35,10 @@ def post_paid_automation_charge(): billing_updating_invoice.charge(invoice.id) +# Listing all jobs schedule.every(1).day.do(post_paid_automation_charge) -while True: - schedule.run_pending() - time.sleep(1) + +if __name__ == "__main__": + while True: + schedule.run_pending() + time.sleep(1) diff --git a/tests/factory/helpers.py b/tests/factory/helpers.py index b6896e7..d137b6e 100644 --- a/tests/factory/helpers.py +++ b/tests/factory/helpers.py @@ -1,4 +1,6 @@ +import datetime from copy import deepcopy +from typing import Optional from uuid import UUID from sqlalchemy import delete, insert, select @@ -15,32 +17,38 @@ # ACCOUNT -def create_account(session: Session, external_id: UUID, type_: AccountType): +def create_account( + session: Session, + external_id: UUID, + type_: AccountType, + created_at: Optional[datetime.datetime] = None, +): account_insert_line = ( insert(account_table) - .values(external_id=external_id, type=type_) + .values( + external_id=external_id, + type=type_, + created_at=( + created_at if created_at is not None else datetime.datetime.now() + ), + ) .returning( account_table.c.id, account_table.c.created_at, account_table.c.deleted_at ) ) cursor_user = session.execute(account_insert_line).first() + session.commit() if cursor_user is None: raise SystemError("test: create_account something went wrong") - (id_, created_at, deleted_at) = deepcopy(cursor_user) - subscription_insert_line = ( - insert(subscription_table) - .values(account_id=id_, type=type_) - .returning( - subscription_table.c.id, - subscription_table.c.created_at, - subscription_table.c.deleted_at, - ) + (id_, created_at_, deleted_at_) = deepcopy(cursor_user) + subscription_insert_line = insert(subscription_table).values( + account_id=id_, type=type_ ) - cursor_subscription = session.execute(subscription_insert_line).first() + cursor_subscription = session.execute(subscription_insert_line) if cursor_subscription is None: raise SystemError("test: create_account something went wrong") session.commit() - return Account(id_, external_id, type_, created_at, deleted_at) + return Account(id_, external_id, type_, created_at_, deleted_at_) def delete_account(session: Session, id_: UUID): diff --git a/tests/presentation/_test_worker.py b/tests/presentation/test_worker.py similarity index 80% rename from tests/presentation/_test_worker.py rename to tests/presentation/test_worker.py index 16008e1..c9f1cb7 100644 --- a/tests/presentation/_test_worker.py +++ b/tests/presentation/test_worker.py @@ -18,20 +18,22 @@ @responses.activate def test_worker_post_paid_automation_charge(session: Session): - account = create_account(session, uuid4(), AccountType.POST_PAID) + one_month_ago = datetime.datetime.now() - datetime.timedelta(days=30) + account = create_account(session, uuid4(), AccountType.POST_PAID, one_month_ago) event = get_event(session) transaction1 = create_transaction(session, account.id, -event.price, "t1", event.id) transaction2 = create_transaction(session, account.id, -event.price, "t2", event.id) transaction3 = create_transaction(session, account.id, -event.price, "t3", event.id) + responses.add( responses.POST, f"{EnvVars.BILLING_HOST}/invoice", status=200, json={ - "id": uuid4(), - "user_id": uuid4(), - "status": "draft", + "id": uuid4().__str__(), + "user_id": uuid4().__str__(), + "status": "Draft", "created_at": datetime.date.today().__str__(), }, ) @@ -40,10 +42,10 @@ def test_worker_post_paid_automation_charge(session: Session): f"{EnvVars.BILLING_HOST}/charge", status=200, json={ - "id": uuid4(), - "invoice_id": uuid4(), - "status": "charge", - "payment_method_id": uuid4(), + "id": uuid4().__str__(), + "invoice_id": uuid4().__str__(), + "status": "Progress", + "payment_method_id": uuid4().__str__(), "created_at": datetime.date.today().__str__(), }, )