forked from brmlab/brmbar-github
134 lines
4.4 KiB
Python
134 lines
4.4 KiB
Python
# vim: set fileencoding=utf8
|
|
|
|
|
|
class Currency:
|
|
"""Currency
|
|
|
|
Each account has a currency (1 Kč, 1 Club Maté, ...), pairs of
|
|
currencies have (asymmetric) exchange rates."""
|
|
|
|
def __init__(self, db, id, name):
|
|
self.db = db
|
|
self.id = id
|
|
self.name = name
|
|
|
|
@classmethod
|
|
def default(cls, db):
|
|
"""Default wallet currency"""
|
|
return cls.load(db, name="Kč")
|
|
|
|
@classmethod
|
|
def load(cls, db, id=None):
|
|
"""Constructor for existing currency"""
|
|
if id is None:
|
|
raise NameError("Currency.load(): Specify id")
|
|
name = db.execute_and_fetch("SELECT name FROM currencies WHERE id = %s", [id])
|
|
name = name[0]
|
|
return cls(db, id=id, name=name)
|
|
|
|
@classmethod
|
|
def create(cls, db, name):
|
|
"""Constructor for new currency"""
|
|
id = db.execute_and_fetch("SELECT public.create_currency(%s)", [name])
|
|
return cls(db, id=id, name=name)
|
|
|
|
def rates(self, other):
|
|
"""Return tuple ($buy, $sell) of rates of $self in relation to $other (brmbar.Currency):
|
|
$buy is the price of $self in means of $other when buying it (into brmbar)
|
|
$sell is the price of $self in means of $other when selling it (from brmbar)"""
|
|
# buy rate
|
|
res = self.db.execute_and_fetch(
|
|
"SELECT public.find_buy_rate(%s, %s)", [self.id, other.id]
|
|
)
|
|
if res is None:
|
|
raise NameError("Something fishy in find_buy_rate.")
|
|
buy = res[0]
|
|
if buy < 0:
|
|
raise NameError(
|
|
"Currency.rate(): Unknown conversion "
|
|
+ other.name()
|
|
+ " to "
|
|
+ self.name()
|
|
)
|
|
# sell rate
|
|
res = self.db.execute_and_fetch(
|
|
"SELECT public.find_sell_rate(%s, %s)", [self.id, other.id]
|
|
)
|
|
if res is None:
|
|
raise NameError("Something fishy in find_sell_rate.")
|
|
sell = res[0]
|
|
if sell < 0:
|
|
raise NameError(
|
|
"Currency.rate(): Unknown conversion "
|
|
+ self.name()
|
|
+ " to "
|
|
+ other.name()
|
|
)
|
|
|
|
return (buy, sell)
|
|
|
|
def rates2(self, other):
|
|
# the original code for compare testing
|
|
res = self.db.execute_and_fetch(
|
|
"SELECT rate, rate_dir FROM exchange_rates WHERE target = %s AND source = %s AND valid_since <= NOW() ORDER BY valid_since DESC LIMIT 1",
|
|
[self.id, other.id],
|
|
)
|
|
if res is None:
|
|
raise NameError(
|
|
"Currency.rate(): Unknown conversion "
|
|
+ other.name()
|
|
+ " to "
|
|
+ self.name()
|
|
)
|
|
buy_rate, buy_rate_dir = res
|
|
buy = buy_rate if buy_rate_dir == "target_to_source" else 1 / buy_rate
|
|
|
|
res = self.db.execute_and_fetch(
|
|
"SELECT rate, rate_dir FROM exchange_rates WHERE target = %s AND source = %s AND valid_since <= NOW() ORDER BY valid_since DESC LIMIT 1",
|
|
[other.id, self.id],
|
|
)
|
|
if res is None:
|
|
raise NameError(
|
|
"Currency.rate(): Unknown conversion "
|
|
+ self.name()
|
|
+ " to "
|
|
+ other.name()
|
|
)
|
|
sell_rate, sell_rate_dir = res
|
|
sell = sell_rate if sell_rate_dir == "source_to_target" else 1 / sell_rate
|
|
|
|
return (buy, sell)
|
|
|
|
def convert(self, amount, target):
|
|
res = self.db.execute_and_fetch(
|
|
"SELECT rate, rate_dir FROM exchange_rates WHERE target = %s AND source = %s AND valid_since <= NOW() ORDER BY valid_since DESC LIMIT 1",
|
|
[target.id, self.id],
|
|
)
|
|
if res is None:
|
|
raise NameError(
|
|
"Currency.convert(): Unknown conversion "
|
|
+ self.name()
|
|
+ " to "
|
|
+ target.name()
|
|
)
|
|
rate, rate_dir = res
|
|
if rate_dir == "source_to_target":
|
|
resamount = amount * rate
|
|
else:
|
|
resamount = amount / rate
|
|
return resamount
|
|
|
|
def str(self, amount):
|
|
return "{:.2f} {}".format(amount, self.name)
|
|
|
|
def update_sell_rate(self, target, rate):
|
|
self.db.execute(
|
|
"SELECT public.update_currency_sell_rate(%s, %s, %s)",
|
|
[self.id, target.id, rate],
|
|
)
|
|
|
|
def update_buy_rate(self, source, rate):
|
|
self.db.execute(
|
|
"SELECT public.update_currency_buy_rate(%s, %s, %s)",
|
|
[self.id, source.id, rate],
|
|
)
|