add domain entity
parent
691acffcfa
commit
e5b36a27c3
|
@ -0,0 +1,16 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": -1,
|
||||||
|
"type": "Income",
|
||||||
|
"date": "2000-11-10T00:00:00",
|
||||||
|
"amount": 100.1,
|
||||||
|
"description": "sdfsdfsgdhfgh"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": -1,
|
||||||
|
"type": "Income",
|
||||||
|
"date": "2000-11-10T00:00:00",
|
||||||
|
"amount": 100.1,
|
||||||
|
"description": "d"
|
||||||
|
}
|
||||||
|
]
|
|
@ -1,7 +1,7 @@
|
||||||
from abc import abstractmethod
|
from abc import abstractmethod
|
||||||
from typing import Protocol
|
from typing import Protocol
|
||||||
|
|
||||||
from clifinance.application.dto.expense import ExpenseDTO
|
from clifinance.domain.expense.model import Expense
|
||||||
|
|
||||||
|
|
||||||
class FileDriver(Protocol):
|
class FileDriver(Protocol):
|
||||||
|
@ -10,5 +10,5 @@ class FileDriver(Protocol):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def write(self, data: list[ExpenseDTO]):
|
def write(self, data: list[Expense]):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
|
@ -2,10 +2,10 @@ from abc import abstractmethod
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Protocol
|
from typing import Protocol
|
||||||
|
|
||||||
from clifinance.application.dto.expense import ExpenseDTO, ExpenseTypeDTO
|
from clifinance.domain.expense.model import Expense, ExpenseType
|
||||||
|
|
||||||
|
|
||||||
class FileSession(Protocol):
|
class Session(Protocol):
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def commit(self) -> None:
|
def commit(self) -> None:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
@ -15,27 +15,27 @@ class FileSession(Protocol):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def add(self, expense: ExpenseDTO) -> None:
|
def add(self, expense: Expense) -> None:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def update(self, expense: ExpenseDTO) -> None:
|
def update(self, expense: Expense) -> None:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def delete(self, expense: ExpenseDTO) -> None:
|
def delete(self, expense: Expense) -> None:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def get(
|
def get(
|
||||||
self,
|
self,
|
||||||
expense_id: int | None,
|
expense_id: int | None,
|
||||||
type: ExpenseTypeDTO | None,
|
type: ExpenseType | None,
|
||||||
date: datetime | None,
|
date: datetime | None,
|
||||||
amount: int | None,
|
amount: int | None,
|
||||||
) -> list[ExpenseDTO]:
|
) -> list[Expense]:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def get_all(self) -> list[ExpenseDTO]:
|
def get_all(self) -> list[Expense]:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
|
@ -1,36 +1,11 @@
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from enum import Enum
|
|
||||||
|
|
||||||
|
|
||||||
class ExpenseTypeDTO(Enum):
|
|
||||||
INCOME = "Income"
|
|
||||||
EXPENSE = "Expense"
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class ExpenseDTO:
|
class ExpenseDTO:
|
||||||
id: int | None
|
id: int | None
|
||||||
type: ExpenseTypeDTO
|
type: str
|
||||||
date: datetime
|
date: datetime
|
||||||
amount: float
|
amount: float
|
||||||
description: str
|
description: str
|
||||||
|
|
||||||
def to_json(self) -> dict:
|
|
||||||
return {
|
|
||||||
"id": self.id,
|
|
||||||
"type": self.type.value,
|
|
||||||
"date": self.date.isoformat(),
|
|
||||||
"amount": self.amount,
|
|
||||||
"description": self.description,
|
|
||||||
}
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def from_json(data: dict) -> "ExpenseDTO":
|
|
||||||
return ExpenseDTO(
|
|
||||||
id=data["id"],
|
|
||||||
type=(ExpenseTypeDTO.INCOME if data["type"] == "Income" else ExpenseTypeDTO.EXPENSE),
|
|
||||||
date=datetime.fromisoformat(data["date"]),
|
|
||||||
amount=data["amount"],
|
|
||||||
description=data["description"],
|
|
||||||
)
|
|
||||||
|
|
|
@ -1,23 +1,22 @@
|
||||||
import argparse
|
from clifinance.application.dto.expense import ExpenseDTO
|
||||||
|
from clifinance.domain.expense.gateway import ExpenseGateway
|
||||||
from clifinance.application.abstractions.protocols.gateway import DataGateway
|
from clifinance.domain.expense.model import Expense
|
||||||
from clifinance.application.dto.expense import ExpenseDTO, ExpenseTypeDTO
|
|
||||||
|
|
||||||
|
|
||||||
class AddExpense:
|
class AddExpense:
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
gateway: DataGateway,
|
gateway: ExpenseGateway,
|
||||||
) -> None:
|
) -> None:
|
||||||
self.__gateway = gateway
|
self.__gateway = gateway
|
||||||
|
|
||||||
def __call__(self, args: argparse.Namespace) -> None:
|
def __call__(self, expense: ExpenseDTO) -> None:
|
||||||
self.__gateway.add_expense(
|
self.__gateway.add_expense(
|
||||||
exp=ExpenseDTO(
|
exp=Expense.create(
|
||||||
id=None,
|
id=expense.id if expense.id else 1,
|
||||||
type=(ExpenseTypeDTO.INCOME if args.type == "income" else ExpenseTypeDTO.EXPENSE),
|
type=expense.type,
|
||||||
date=args.date,
|
date=expense.date,
|
||||||
amount=args.amount,
|
amount=expense.amount,
|
||||||
description=args.description,
|
description=expense.description,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
from clifinance.application.abstractions.protocols.gateway import DataGateway
|
# from clifinance.application.dto.balance import Balance
|
||||||
from clifinance.application.dto.balance import Balance
|
# from clifinance.domain.expense.gateway import ExpenseGateway
|
||||||
|
#
|
||||||
|
#
|
||||||
class GetBalance:
|
# class GetBalance:
|
||||||
def __init__(
|
# def __init__(
|
||||||
self,
|
# self,
|
||||||
gateway: DataGateway,
|
# gateway: ExpenseGateway,
|
||||||
) -> None:
|
# ) -> None:
|
||||||
self.__gateway = gateway
|
# self.__gateway = gateway
|
||||||
|
#
|
||||||
def __call__(self) -> Balance:
|
# def __call__(self) -> Balance:
|
||||||
|
#
|
||||||
return self.__gateway.get_balance()
|
# return self.__gateway.get_balance()
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from typing import Generic, TypeVar
|
||||||
|
|
||||||
|
from clifinance.domain.value_obj import DomainValueObject
|
||||||
|
|
||||||
|
EntityId = TypeVar("EntityId", bound=DomainValueObject)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class DomainEntity(Generic[EntityId]):
|
||||||
|
id: EntityId
|
|
@ -0,0 +1,8 @@
|
||||||
|
class DomainError(Exception):
|
||||||
|
def __init__(self, message: str, *args: object) -> None:
|
||||||
|
self.message = message
|
||||||
|
super().__init__(*args)
|
||||||
|
|
||||||
|
|
||||||
|
class DomainValidationError(DomainError):
|
||||||
|
pass
|
|
@ -0,0 +1,17 @@
|
||||||
|
from clifinance.domain.error import DomainError, DomainValidationError
|
||||||
|
|
||||||
|
|
||||||
|
class ExpenseValidationError(DomainValidationError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ExpenseError(DomainError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ExpenseNotFoundError(ExpenseError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ExpenseAlreadyExistsError(ExpenseError):
|
||||||
|
pass
|
|
@ -2,35 +2,30 @@ from abc import abstractmethod
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Protocol
|
from typing import Protocol
|
||||||
|
|
||||||
from clifinance.application.dto.balance import Balance
|
from clifinance.domain.expense.model import Expense, ExpenseType
|
||||||
from clifinance.application.dto.expense import ExpenseDTO, ExpenseTypeDTO
|
|
||||||
|
|
||||||
|
|
||||||
class DataGateway(Protocol):
|
class ExpenseGateway(Protocol):
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def get_balance(self) -> Balance:
|
def get_all_expenses(self) -> list[Expense]:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def get_all_expenses(self) -> list[ExpenseDTO]:
|
def add_expense(self, exp: Expense) -> None:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def add_expense(self, exp: ExpenseDTO) -> None:
|
def update_expense(self, expense: Expense) -> None:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def update_expense(self, expense: ExpenseDTO) -> None:
|
def get_all_expenses_by_type(self, type: ExpenseType) -> list[Expense]:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def get_all_expenses_by_type(self, type: ExpenseTypeDTO) -> list[ExpenseDTO]:
|
def get_all_expenses_by_date(self, date: datetime) -> list[Expense]:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def get_all_expenses_by_date(self, date: datetime) -> list[ExpenseDTO]:
|
def get_all_expenses_by_price(self, price: float) -> list[Expense]:
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def get_all_expenses_by_price(self, price: float) -> list[ExpenseDTO]:
|
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
|
@ -0,0 +1,74 @@
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from datetime import datetime
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
from clifinance.domain.entity import DomainEntity, DomainValueObject
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class ExpenseId(DomainValueObject):
|
||||||
|
value: int
|
||||||
|
|
||||||
|
|
||||||
|
class ExpenseType(Enum):
|
||||||
|
INCOME = "Income"
|
||||||
|
EXPENSE = "Expense"
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class ExpenseDate(DomainValueObject):
|
||||||
|
value: datetime
|
||||||
|
|
||||||
|
def isoformat(self):
|
||||||
|
return self.value.isoformat()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_isoformat(date: str) -> "ExpenseDate":
|
||||||
|
return ExpenseDate(datetime.fromisoformat(date))
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class ExpenseAmount(DomainValueObject):
|
||||||
|
value: float
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class ExpenseDescription(DomainValueObject):
|
||||||
|
value: str
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Expense(DomainEntity[ExpenseId]):
|
||||||
|
type: ExpenseType
|
||||||
|
date: ExpenseDate
|
||||||
|
amount: ExpenseAmount
|
||||||
|
description: ExpenseDescription
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def create(id: int, type: str, date: datetime, amount: float, description: str) -> "Expense":
|
||||||
|
return Expense(
|
||||||
|
id=ExpenseId(id),
|
||||||
|
type=ExpenseType(type.title()),
|
||||||
|
date=ExpenseDate(date),
|
||||||
|
amount=ExpenseAmount(amount),
|
||||||
|
description=ExpenseDescription(description),
|
||||||
|
)
|
||||||
|
|
||||||
|
def to_json(self) -> dict:
|
||||||
|
return {
|
||||||
|
"id": self.id.value,
|
||||||
|
"type": self.type.value,
|
||||||
|
"date": self.date.isoformat(),
|
||||||
|
"amount": self.amount.value,
|
||||||
|
"description": self.description.value,
|
||||||
|
}
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_json(data: dict) -> "Expense":
|
||||||
|
return Expense(
|
||||||
|
id=ExpenseId(data["id"]),
|
||||||
|
type=ExpenseType(data["type"]),
|
||||||
|
date=ExpenseDate.from_isoformat(data["date"]),
|
||||||
|
amount=ExpenseAmount(data["amount"]),
|
||||||
|
description=ExpenseDescription(data["description"]),
|
||||||
|
)
|
|
@ -0,0 +1,6 @@
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class DomainValueObject:
|
||||||
|
pass
|
|
@ -1,41 +0,0 @@
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
from clifinance.application.abstractions.protocols.gateway import DataGateway
|
|
||||||
from clifinance.application.abstractions.protocols.session import FileSession
|
|
||||||
from clifinance.application.dto.balance import Balance
|
|
||||||
from clifinance.application.dto.expense import ExpenseDTO, ExpenseTypeDTO
|
|
||||||
|
|
||||||
|
|
||||||
class JsonDataGateway(DataGateway):
|
|
||||||
def __init__(self, session: FileSession) -> None:
|
|
||||||
self.session = session
|
|
||||||
|
|
||||||
def get_balance(self) -> Balance:
|
|
||||||
data = self.session.get_all()
|
|
||||||
balance = sum(x.amount for x in data)
|
|
||||||
income = sum(x.amount for x in data if x.type == ExpenseTypeDTO.INCOME)
|
|
||||||
expense = sum(x.amount for x in data if x.type == ExpenseTypeDTO.EXPENSE)
|
|
||||||
return Balance(
|
|
||||||
balance=round(balance, 2),
|
|
||||||
imcome_balance=round(income, 2),
|
|
||||||
expense_balance=round(expense, 2),
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_all_expenses(self) -> list[ExpenseDTO]:
|
|
||||||
return self.session.get_all()
|
|
||||||
|
|
||||||
def add_expense(self, exp: ExpenseDTO) -> None:
|
|
||||||
self.session.add(exp)
|
|
||||||
self.session.commit()
|
|
||||||
|
|
||||||
def update_expense(self, expense: ExpenseDTO) -> None:
|
|
||||||
self.session.update(expense)
|
|
||||||
|
|
||||||
def get_all_expenses_by_type(self, type: ExpenseTypeDTO) -> list[ExpenseDTO]:
|
|
||||||
return [x for x in self.session.get_all() if x.type == type]
|
|
||||||
|
|
||||||
def get_all_expenses_by_date(self, date: datetime) -> list[ExpenseDTO]:
|
|
||||||
return [x for x in self.session.get_all() if x.date == date]
|
|
||||||
|
|
||||||
def get_all_expenses_by_price(self, price: float) -> list[ExpenseDTO]:
|
|
||||||
return [x for x in self.session.get_all() if x.amount == price]
|
|
|
@ -1,6 +1,6 @@
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from clifinance.application.dto.expense import ExpenseDTO
|
from clifinance.domain.expense.model import Expense
|
||||||
|
|
||||||
|
|
||||||
class JsonFileDriver:
|
class JsonFileDriver:
|
||||||
|
@ -15,12 +15,12 @@ class JsonFileDriver:
|
||||||
except json.JSONDecodeError:
|
except json.JSONDecodeError:
|
||||||
return list()
|
return list()
|
||||||
|
|
||||||
def write(self, data: list[ExpenseDTO]):
|
def write(self, data: list[Expense]):
|
||||||
with open("./app_data.json", "w") as f:
|
with open("./app_data.json", "w") as f:
|
||||||
json.dump(self.__data_to_json(data), f)
|
json.dump(self.__data_to_json(data), f)
|
||||||
|
|
||||||
def __data_to_json(self, data: list[ExpenseDTO]):
|
def __data_to_json(self, data: list[Expense]):
|
||||||
return [x.to_json() for x in data]
|
return [x.to_json() for x in data]
|
||||||
|
|
||||||
def __data_from_json(self, data: list[dict]):
|
def __data_from_json(self, data: list[dict]):
|
||||||
return [ExpenseDTO.from_json(x) for x in data]
|
return [Expense.from_json(x) for x in data]
|
|
@ -0,0 +1,29 @@
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from clifinance.application.abstractions.protocols.session import Session
|
||||||
|
from clifinance.domain.expense.gateway import ExpenseGateway
|
||||||
|
from clifinance.domain.expense.model import Expense, ExpenseType
|
||||||
|
|
||||||
|
|
||||||
|
class JsonExpenseGateway(ExpenseGateway):
|
||||||
|
def __init__(self, session: Session) -> None:
|
||||||
|
self.session = session
|
||||||
|
|
||||||
|
def get_all_expenses(self) -> list[Expense]:
|
||||||
|
return self.session.get_all()
|
||||||
|
|
||||||
|
def add_expense(self, exp: Expense) -> None:
|
||||||
|
self.session.add(exp)
|
||||||
|
self.session.commit()
|
||||||
|
|
||||||
|
def update_expense(self, expense: Expense) -> None:
|
||||||
|
self.session.update(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]
|
||||||
|
|
||||||
|
def get_all_expenses_by_date(self, date: datetime) -> list[Expense]:
|
||||||
|
return [x for x in self.session.get_all() if x.date == date]
|
||||||
|
|
||||||
|
def get_all_expenses_by_price(self, price: float) -> list[Expense]:
|
||||||
|
return [x for x in self.session.get_all() if x.amount == price]
|
|
@ -1,17 +1,17 @@
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from clifinance.application.abstractions.protocols.driver import FileDriver
|
from clifinance.application.abstractions.protocols.driver import FileDriver
|
||||||
from clifinance.application.abstractions.protocols.session import FileSession
|
from clifinance.application.abstractions.protocols.session import Session
|
||||||
from clifinance.application.dto.expense import ExpenseDTO, ExpenseTypeDTO
|
from clifinance.domain.expense.model import Expense, ExpenseType
|
||||||
|
|
||||||
|
|
||||||
class JsonFileSession(FileSession):
|
class JsonFileSession(Session):
|
||||||
def __init__(self, driver: FileDriver) -> None:
|
def __init__(self, driver: FileDriver) -> None:
|
||||||
self.driver = driver
|
self.driver = driver
|
||||||
self.data: list[ExpenseDTO] = driver.read()
|
self.data: list[Expense] = driver.read()
|
||||||
self.__dirty_new: list[ExpenseDTO] = list()
|
self.__dirty_new: list[Expense] = list()
|
||||||
self.__dirty_updated: list[ExpenseDTO] = list()
|
self.__dirty_updated: list[Expense] = list()
|
||||||
self.__dirty_deleted: list[ExpenseDTO] = list()
|
self.__dirty_deleted: list[Expense] = list()
|
||||||
|
|
||||||
def commit(self) -> None:
|
def commit(self) -> None:
|
||||||
for expense in self.__dirty_new:
|
for expense in self.__dirty_new:
|
||||||
|
@ -37,36 +37,28 @@ class JsonFileSession(FileSession):
|
||||||
def rollback(self) -> None:
|
def rollback(self) -> None:
|
||||||
self.data = self.driver.read()
|
self.data = self.driver.read()
|
||||||
|
|
||||||
def add(self, expense: ExpenseDTO) -> None:
|
def add(self, expense: Expense) -> None:
|
||||||
if not self.data:
|
# if not self.data:
|
||||||
last_id = -1
|
# last_id = -1
|
||||||
else:
|
# else:
|
||||||
last_id = max({x.id for x in self.data if x.id is not None})
|
# last_id = max({x.id for x in self.data if x.id is not None})
|
||||||
|
#
|
||||||
|
self.__dirty_new.append(expense)
|
||||||
|
|
||||||
self.__dirty_new.append(
|
def update(self, expense: Expense) -> None:
|
||||||
ExpenseDTO(
|
|
||||||
id=last_id + 1,
|
|
||||||
type=expense.type,
|
|
||||||
date=expense.date,
|
|
||||||
amount=expense.amount,
|
|
||||||
description=expense.description,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
def update(self, expense: ExpenseDTO) -> None:
|
|
||||||
self.__dirty_updated.append(expense)
|
self.__dirty_updated.append(expense)
|
||||||
|
|
||||||
def delete(self, expense: ExpenseDTO) -> None:
|
def delete(self, expense: Expense) -> None:
|
||||||
self.__dirty_deleted.append(expense)
|
self.__dirty_deleted.append(expense)
|
||||||
|
|
||||||
def get(
|
def get(
|
||||||
self,
|
self,
|
||||||
expense_id: int | None = None,
|
expense_id: int | None = None,
|
||||||
type: ExpenseTypeDTO | None = None,
|
type: ExpenseType | None = None,
|
||||||
date: datetime | None = None,
|
date: datetime | None = None,
|
||||||
amount: int | None = None,
|
amount: int | None = None,
|
||||||
) -> list[ExpenseDTO]:
|
) -> list[Expense]:
|
||||||
result: list[ExpenseDTO] = list()
|
result: list[Expense] = list()
|
||||||
for expense in self.data:
|
for expense in self.data:
|
||||||
if expense_id is not None and expense.id != expense_id:
|
if expense_id is not None and expense.id != expense_id:
|
||||||
continue
|
continue
|
||||||
|
@ -81,5 +73,5 @@ class JsonFileSession(FileSession):
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def get_all(self) -> list[ExpenseDTO]:
|
def get_all(self) -> list[Expense]:
|
||||||
return self.data
|
return self.data
|
|
@ -5,29 +5,30 @@ from inspect import signature
|
||||||
from typing import ParamSpec, TypeVar
|
from typing import ParamSpec, TypeVar
|
||||||
|
|
||||||
from clifinance.application.abstractions.protocols.driver import FileDriver
|
from clifinance.application.abstractions.protocols.driver import FileDriver
|
||||||
from clifinance.application.abstractions.protocols.gateway import DataGateway
|
from clifinance.application.abstractions.protocols.session import Session
|
||||||
from clifinance.application.abstractions.protocols.session import FileSession
|
|
||||||
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.infrastructure.json_driver import JsonFileDriver
|
# from clifinance.application.usecases.get_balance import GetBalance
|
||||||
from clifinance.infrastructure.json_gateway import JsonDataGateway
|
from clifinance.domain.expense.gateway import ExpenseGateway
|
||||||
from clifinance.infrastructure.json_session import JsonFileSession
|
from clifinance.infrastructure.persistence.json_driver import JsonFileDriver
|
||||||
|
from clifinance.infrastructure.persistence.json_gateway import JsonExpenseGateway
|
||||||
|
from clifinance.infrastructure.session import JsonFileSession
|
||||||
|
|
||||||
|
|
||||||
class Container:
|
class Container:
|
||||||
|
|
||||||
@contextmanager
|
# @contextmanager
|
||||||
def provide_get_balance(self) -> Generator[GetBalance, None, None]:
|
# def provide_get_balance(self) -> Generator[GetBalance, None, None]:
|
||||||
yield GetBalance(gateway=self.json_gateway())
|
# yield GetBalance(gateway=self.json_gateway())
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
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())
|
||||||
|
|
||||||
def json_gateway(self) -> DataGateway:
|
def json_gateway(self) -> ExpenseGateway:
|
||||||
return JsonDataGateway(session=self.get_session())
|
return JsonExpenseGateway(session=self.get_session())
|
||||||
|
|
||||||
def get_session(self) -> FileSession:
|
def get_session(self) -> Session:
|
||||||
return JsonFileSession(driver=self.get_driver())
|
return JsonFileSession(driver=self.get_driver())
|
||||||
|
|
||||||
def get_driver(self) -> FileDriver:
|
def get_driver(self) -> FileDriver:
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
|
from clifinance.application.dto.expense import ExpenseDTO
|
||||||
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:
|
||||||
|
@ -18,10 +20,14 @@ def add_expense(args: argparse.Namespace, ioc: Container) -> None:
|
||||||
argument=None,
|
argument=None,
|
||||||
message="All arguments are required: -t, -d, -a, -D",
|
message="All arguments are required: -t, -d, -a, -D",
|
||||||
)
|
)
|
||||||
if args.type == "income" and args.amount < 0:
|
|
||||||
raise argparse.ArgumentError(argument=None, message="An income cannot have a negative amount.")
|
|
||||||
if args.type == "expense" and args.amount > 0:
|
|
||||||
raise argparse.ArgumentError(argument=None, message="An expense cannot have a positive amount.")
|
|
||||||
|
|
||||||
with ioc.provide_add_expense() as usecase:
|
with ioc.provide_add_expense() as usecase:
|
||||||
usecase(args=args)
|
usecase(
|
||||||
|
expense=ExpenseDTO(
|
||||||
|
id=args.id if args.__dict__.get("id") else -1,
|
||||||
|
type=args.type,
|
||||||
|
date=args.date,
|
||||||
|
amount=args.amount,
|
||||||
|
description=args.description,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in New Issue