103 lines
3.9 KiB
Python
103 lines
3.9 KiB
Python
"""PiggyBank implementation."""
|
|
|
|
from __future__ import annotations
|
|
from os.path import exists
|
|
from typing import List
|
|
|
|
from piggybank import PIGGYBANK_FILE_EXTENSION
|
|
from piggybank.currencies import CURRENCIES, CurrencyIsNotSupportedError, \
|
|
CurrencyMismatchError
|
|
from piggybank.transaction import Transaction, sum_transactions, TYPE_INCOME
|
|
|
|
__all__ = ["PiggyBank"]
|
|
|
|
|
|
class PiggyBank:
|
|
"""This class stores array of transactions and perform some actions on it."""
|
|
def __init__(self, currency: str = None) -> None:
|
|
self._currency = None
|
|
if not currency is None:
|
|
self.currency = currency
|
|
self._transactions = []
|
|
self._last_transaction = None
|
|
|
|
def transact(self, coins: List[int], direction: str = TYPE_INCOME) -> None:
|
|
"""Make a transaction."""
|
|
if len(coins) != CURRENCIES[self._currency]["count"]:
|
|
raise ValueError("Length of passed coins list doesn't match the " \
|
|
f"currency's coins count. ({len(coins)} " \
|
|
f"!= {CURRENCIES[self._currency]['count']})")
|
|
self._last_transaction = Transaction(coins, direction)
|
|
self._transactions.append(self._last_transaction)
|
|
for coin_count in sum_transactions(self._transactions):
|
|
if coin_count < 0:
|
|
del self._transactions[-1]
|
|
self._last_transaction = None
|
|
raise ValueError(
|
|
"You can't take out more than you have.")
|
|
|
|
@property
|
|
def currency(self) -> str:
|
|
"""Returns a currency of a PiggyBank."""
|
|
return self._currency
|
|
|
|
@currency.setter
|
|
def currency(self, currency: str) -> None:
|
|
"""Sets a currency of a PiggyBank with check for support."""
|
|
currency = currency.upper()
|
|
if not currency in CURRENCIES.keys():
|
|
raise CurrencyIsNotSupportedError
|
|
self._currency = currency
|
|
|
|
@property
|
|
def transactions(self) -> List[Transaction]:
|
|
"""Returns a list of transactions."""
|
|
return self._transactions
|
|
|
|
@staticmethod
|
|
def from_file(filename: str) -> PiggyBank:
|
|
"""Returns a PiggyBank object loaded from a file."""
|
|
piggybank = PiggyBank()
|
|
piggybank.load(filename)
|
|
return piggybank
|
|
|
|
def save(self, filename: str) -> None:
|
|
"""Appends last successful transaction to a file. File will be created
|
|
if not exist yet."""
|
|
if self._last_transaction is None:
|
|
raise ValueError("No successful transaction found.")
|
|
if not filename.endswith(PIGGYBANK_FILE_EXTENSION):
|
|
filename += PIGGYBANK_FILE_EXTENSION
|
|
if not exists(filename):
|
|
with open(filename, 'w') as pbf:
|
|
pbf.write(f"{self.currency}\n{self._last_transaction}\n")
|
|
else:
|
|
with open(filename, 'a') as pbf:
|
|
pbf.write(f"{self._last_transaction}\n")
|
|
|
|
def load(self, filename: str) -> None:
|
|
"""Loads a PiggyBank from a file."""
|
|
if not filename.endswith(PIGGYBANK_FILE_EXTENSION):
|
|
filename += PIGGYBANK_FILE_EXTENSION
|
|
if not exists(filename):
|
|
raise FileNotFoundError(filename)
|
|
with open(filename, 'r') as pbf:
|
|
currency = pbf.readline()[:-1]
|
|
if currency not in CURRENCIES:
|
|
raise CurrencyIsNotSupportedError
|
|
else:
|
|
self._currency = currency
|
|
for line in pbf:
|
|
self._transactions.append(Transaction.from_string(line))
|
|
|
|
def __eq__(self, piggybank: PiggyBank) -> str:
|
|
"""Compares only currency."""
|
|
return self._currency == piggybank.currency
|
|
|
|
def __add__(self, piggybank: PiggyBank) -> PiggyBank:
|
|
if self != piggybank:
|
|
raise CurrencyMismatchError
|
|
new = PiggyBank(self._currency)
|
|
new._transactions = self._transactions + piggybank._transactions
|
|
return new
|