select expence by filter

main
Сергей Ванюшкин 2024-05-20 07:26:29 +00:00
parent 0de79b165f
commit 2b158c8b5f
9 changed files with 105 additions and 22 deletions

View File

@ -1,16 +1,16 @@
[ [
{ {
"id": -1, "id": -1,
"type": "Income", "description": "shoping",
"date": "2000-11-10T00:00:00", "amount": -200.75,
"amount": 100.1, "date": "2021-01-01T00:00:00",
"description": "sdfsdfsgdhfgh" "type": "Expense"
}, },
{ {
"id": -1, "id": -1,
"type": "Income", "description": "shoping",
"date": "2000-11-10T00:00:00", "amount": 200.75,
"amount": 100.1, "date": "2021-01-01T00:00:00",
"description": "d" "type": "Income"
} }
] ]

View File

@ -0,0 +1,9 @@
from dataclasses import dataclass
from datetime import datetime
@dataclass(frozen=True)
class SelectorDTO:
type: str
date: datetime
amount: float

View File

@ -0,0 +1,23 @@
from clifinance.application.dto.selector import SelectorDTO
from clifinance.domain.expense.gateway import ExpenseGateway
from clifinance.domain.expense.model import (
Expense,
ExpenseAmount,
ExpenseDate,
ExpenseType,
)
class GetExpensesByFilter:
def __init__(
self,
gateway: ExpenseGateway,
) -> None:
self.__gateway = gateway
def __call__(self, filter: SelectorDTO) -> list[Expense]:
return self.__gateway.get_all_expenses_by_filter(
type=ExpenseType(filter.type) if filter.type else None,
date=ExpenseDate(filter.date) if filter.date else None,
amount=ExpenseAmount(filter.amount) if filter.amount else None,
)

View File

@ -1,8 +1,12 @@
from abc import abstractmethod from abc import abstractmethod
from datetime import datetime
from typing import Protocol from typing import Protocol
from clifinance.domain.expense.model import Expense, ExpenseType from clifinance.domain.expense.model import (
Expense,
ExpenseAmount,
ExpenseDate,
ExpenseType,
)
class ExpenseGateway(Protocol): class ExpenseGateway(Protocol):
@ -23,9 +27,18 @@ class ExpenseGateway(Protocol):
raise NotImplementedError raise NotImplementedError
@abstractmethod @abstractmethod
def get_all_expenses_by_date(self, date: datetime) -> list[Expense]: def get_all_expenses_by_date(self, date: ExpenseDate) -> list[Expense]:
raise NotImplementedError raise NotImplementedError
@abstractmethod @abstractmethod
def get_all_expenses_by_price(self, price: float) -> list[Expense]: def get_all_expenses_by_amount(self, amount: ExpenseAmount) -> list[Expense]:
raise NotImplementedError
@abstractmethod
def get_all_expenses_by_filter(
self,
type: ExpenseType | None,
date: ExpenseDate | None,
amount: ExpenseAmount | None,
) -> list[Expense]:
raise NotImplementedError raise NotImplementedError

View File

@ -53,3 +53,6 @@ class Expense(DomainEntity[ExpenseId]):
amount=ExpenseAmount(amount), amount=ExpenseAmount(amount),
description=ExpenseDescription(description), description=ExpenseDescription(description),
) )
def __str__(self):
return f"Expense(id={self.id.value}, type={self.type.value}, date={self.date.value}, amount={self.amount.value}, description={self.description.value})"

View File

@ -1,8 +1,11 @@
from datetime import datetime
from clifinance.application.abstractions.protocols.session import Session from clifinance.application.abstractions.protocols.session import Session
from clifinance.domain.expense.gateway import ExpenseGateway from clifinance.domain.expense.gateway import ExpenseGateway
from clifinance.domain.expense.model import Expense, ExpenseType from clifinance.domain.expense.model import (
Expense,
ExpenseAmount,
ExpenseDate,
ExpenseType,
)
class JsonExpenseGateway(ExpenseGateway): class JsonExpenseGateway(ExpenseGateway):
@ -22,8 +25,24 @@ class JsonExpenseGateway(ExpenseGateway):
def get_all_expenses_by_type(self, type: ExpenseType) -> list[Expense]: def get_all_expenses_by_type(self, type: ExpenseType) -> list[Expense]:
return [x for x in self.session.get_all() if x.type == type] return [x for x in self.session.get_all() if x.type == type]
def get_all_expenses_by_date(self, date: datetime) -> list[Expense]: def get_all_expenses_by_date(self, date: ExpenseDate) -> list[Expense]:
return [x for x in self.session.get_all() if x.date == date] return [x for x in self.session.get_all() if x.date == date]
def get_all_expenses_by_price(self, price: float) -> list[Expense]: def get_all_expenses_by_amount(self, amount: ExpenseAmount) -> list[Expense]:
return [x for x in self.session.get_all() if x.amount == price] return [x for x in self.session.get_all() if x.amount == amount]
def get_all_expenses_by_filter(
self,
type: ExpenseType | None,
date: ExpenseDate | None,
amount: ExpenseAmount | None,
) -> list[Expense]:
result = self.get_all_expenses()
if type is not None:
result = [x for x in result if x.type == type]
if date is not None:
result = [x for x in result if x.date == date]
if amount is not None:
result = [x for x in result if x.amount == amount]
return result

View File

@ -1,3 +1,5 @@
from datetime import datetime
from clifinance.domain.expense.model import ( from clifinance.domain.expense.model import (
Expense, Expense,
ExpenseAmount, ExpenseAmount,
@ -13,7 +15,7 @@ def expense_to_json(expense: Expense):
"id": expense.id.value, "id": expense.id.value,
"description": expense.description.value, "description": expense.description.value,
"amount": expense.amount.value, "amount": expense.amount.value,
"date": expense.date, "date": expense.date.value.isoformat(),
"type": expense.type.value, "type": expense.type.value,
} }
@ -23,6 +25,6 @@ def expense_from_json(data: dict):
id=ExpenseId(data["id"]), id=ExpenseId(data["id"]),
description=ExpenseDescription(data["description"]), description=ExpenseDescription(data["description"]),
amount=ExpenseAmount(data["amount"]), amount=ExpenseAmount(data["amount"]),
date=ExpenseDate(data["date"]), date=ExpenseDate(datetime.fromisoformat(data["date"])),
type=ExpenseType(data["type"]), type=ExpenseType(data["type"]),
) )

View File

@ -8,6 +8,7 @@ from clifinance.application.abstractions.protocols.driver import FileDriver
from clifinance.application.abstractions.protocols.session import Session from clifinance.application.abstractions.protocols.session import Session
from clifinance.application.usecases.add_expense import AddExpense from clifinance.application.usecases.add_expense import AddExpense
from clifinance.application.usecases.get_balance import GetBalance from clifinance.application.usecases.get_balance import GetBalance
from clifinance.application.usecases.get_expenses import GetExpensesByFilter
from clifinance.domain.expense.gateway import ExpenseGateway from clifinance.domain.expense.gateway import ExpenseGateway
from clifinance.infrastructure.persistence.json_driver import JsonFileDriver from clifinance.infrastructure.persistence.json_driver import JsonFileDriver
from clifinance.infrastructure.persistence.json_gateway import JsonExpenseGateway from clifinance.infrastructure.persistence.json_gateway import JsonExpenseGateway
@ -24,6 +25,10 @@ class Container:
def provide_add_expense(self) -> Generator[AddExpense, None, None]: def provide_add_expense(self) -> Generator[AddExpense, None, None]:
yield AddExpense(gateway=self.json_gateway()) yield AddExpense(gateway=self.json_gateway())
@contextmanager
def provade_get_filtred_expenses(self) -> Generator[GetExpensesByFilter, None, None]:
yield GetExpensesByFilter(gateway=self.json_gateway())
def json_gateway(self) -> ExpenseGateway: def json_gateway(self) -> ExpenseGateway:
return JsonExpenseGateway(session=self.get_session()) return JsonExpenseGateway(session=self.get_session())

View File

@ -1,17 +1,26 @@
import argparse import argparse
from clifinance.application.dto.expense import ExpenseDTO from clifinance.application.dto.expense import ExpenseDTO
from clifinance.application.dto.selector import SelectorDTO
from clifinance.main.container import Container from clifinance.main.container import Container
def get_balance(args: argparse.Namespace, ioc: Container) -> None: def get_balance(args: argparse.Namespace, ioc: Container) -> None:
with ioc.provide_get_balance() as usecase: with ioc.provide_get_balance() as usecase:
print(usecase()) print(usecase())
print()
def select_expenses(args: argparse.Namespace, ioc: Container) -> None: def select_expenses(args: argparse.Namespace, ioc: Container) -> None:
print(args) with ioc.provade_get_filtred_expenses() as usecase:
for expense in usecase(
filter=SelectorDTO(
type=args.__dict__.get("type", None),
date=args.__dict__.get("date", None),
amount=args.__dict__.get("amount", None),
)
):
print(expense)
def add_expense(args: argparse.Namespace, ioc: Container) -> None: def add_expense(args: argparse.Namespace, ioc: Container) -> None: