mirror of
https://github.com/brmlab/brmbar.git
synced 2025-06-08 05:14:00 +02:00
Retab
This commit is contained in:
parent
1c050d7da5
commit
ec94f1d034
3 changed files with 247 additions and 247 deletions
|
@ -4,87 +4,87 @@ import psycopg2
|
||||||
from contextlib import closing
|
from contextlib import closing
|
||||||
|
|
||||||
class Account:
|
class Account:
|
||||||
""" BrmBar Account
|
""" BrmBar Account
|
||||||
|
|
||||||
Both users and items are accounts. So is the money box, etc.
|
Both users and items are accounts. So is the money box, etc.
|
||||||
Each account has a currency."""
|
Each account has a currency."""
|
||||||
def __init__(self, db, id, name, currency, acctype):
|
def __init__(self, db, id, name, currency, acctype):
|
||||||
self.db = db
|
self.db = db
|
||||||
self.id = id
|
self.id = id
|
||||||
self.name = name
|
self.name = name
|
||||||
self.currency = currency
|
self.currency = currency
|
||||||
self.acctype = acctype
|
self.acctype = acctype
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load_by_barcode(cls, db, barcode):
|
def load_by_barcode(cls, db, barcode):
|
||||||
with closing(db.cursor()) as cur:
|
with closing(db.cursor()) as cur:
|
||||||
cur.execute("SELECT account FROM barcodes WHERE barcode = %s", [barcode])
|
cur.execute("SELECT account FROM barcodes WHERE barcode = %s", [barcode])
|
||||||
res = cur.fetchone()
|
res = cur.fetchone()
|
||||||
if res is None:
|
if res is None:
|
||||||
return None
|
return None
|
||||||
id = res[0]
|
id = res[0]
|
||||||
return cls.load(db, id = id)
|
return cls.load(db, id = id)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load(cls, db, id = None, name = None):
|
def load(cls, db, id = None, name = None):
|
||||||
""" Constructor for existing account """
|
""" Constructor for existing account """
|
||||||
if id is not None:
|
if id is not None:
|
||||||
with closing(db.cursor()) as cur:
|
with closing(db.cursor()) as cur:
|
||||||
cur.execute("SELECT name FROM accounts WHERE id = %s", [id])
|
cur.execute("SELECT name FROM accounts WHERE id = %s", [id])
|
||||||
name = cur.fetchone()[0]
|
name = cur.fetchone()[0]
|
||||||
elif name is not None:
|
elif name is not None:
|
||||||
with closing(db.cursor()) as cur:
|
with closing(db.cursor()) as cur:
|
||||||
cur.execute("SELECT id FROM accounts WHERE name = %s", [name])
|
cur.execute("SELECT id FROM accounts WHERE name = %s", [name])
|
||||||
id = cur.fetchone()[0]
|
id = cur.fetchone()[0]
|
||||||
else:
|
else:
|
||||||
raise NameError("Account.load(): Specify either id or name")
|
raise NameError("Account.load(): Specify either id or name")
|
||||||
|
|
||||||
with closing(db.cursor()) as cur:
|
with closing(db.cursor()) as cur:
|
||||||
cur.execute("SELECT currency, acctype FROM accounts WHERE id = %s", [id])
|
cur.execute("SELECT currency, acctype FROM accounts WHERE id = %s", [id])
|
||||||
currid, acctype = cur.fetchone()
|
currid, acctype = cur.fetchone()
|
||||||
currency = Currency.load(db, id = currid)
|
currency = Currency.load(db, id = currid)
|
||||||
|
|
||||||
return cls(db, name = name, id = id, currency = currency, acctype = acctype)
|
return cls(db, name = name, id = id, currency = currency, acctype = acctype)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create(cls, db, name, currency, acctype):
|
def create(cls, db, name, currency, acctype):
|
||||||
""" Constructor for new account """
|
""" Constructor for new account """
|
||||||
with closing(db.cursor()) as cur:
|
with closing(db.cursor()) as cur:
|
||||||
cur.execute("INSERT INTO accounts (name, currency, acctype) VALUES (%s, %s, %s) RETURNING id", [name, currency.id, acctype])
|
cur.execute("INSERT INTO accounts (name, currency, acctype) VALUES (%s, %s, %s) RETURNING id", [name, currency.id, acctype])
|
||||||
id = cur.fetchone()[0]
|
id = cur.fetchone()[0]
|
||||||
return cls(db, name = name, id = id, currency = currency, acctype = acctype)
|
return cls(db, name = name, id = id, currency = currency, acctype = acctype)
|
||||||
|
|
||||||
def balance(self):
|
def balance(self):
|
||||||
with closing(self.db.cursor()) as cur:
|
with closing(self.db.cursor()) as cur:
|
||||||
cur.execute("SELECT SUM(amount) FROM transaction_splits WHERE account = %s AND side = %s", [self.id, 'debit'])
|
cur.execute("SELECT SUM(amount) FROM transaction_splits WHERE account = %s AND side = %s", [self.id, 'debit'])
|
||||||
debit = cur.fetchone()[0] or 0
|
debit = cur.fetchone()[0] or 0
|
||||||
cur.execute("SELECT SUM(amount) FROM transaction_splits WHERE account = %s AND side = %s", [self.id, 'credit'])
|
cur.execute("SELECT SUM(amount) FROM transaction_splits WHERE account = %s AND side = %s", [self.id, 'credit'])
|
||||||
credit = cur.fetchone()[0] or 0
|
credit = cur.fetchone()[0] or 0
|
||||||
return debit - credit
|
return debit - credit
|
||||||
|
|
||||||
def balance_str(self):
|
def balance_str(self):
|
||||||
return self.currency.str(self.balance())
|
return self.currency.str(self.balance())
|
||||||
|
|
||||||
def negbalance_str(self):
|
def negbalance_str(self):
|
||||||
return self.currency.str(-self.balance())
|
return self.currency.str(-self.balance())
|
||||||
|
|
||||||
def debit(self, transaction, amount, memo):
|
def debit(self, transaction, amount, memo):
|
||||||
return self._transaction_split(transaction, 'debit', amount, memo)
|
return self._transaction_split(transaction, 'debit', amount, memo)
|
||||||
|
|
||||||
def credit(self, transaction, amount, memo):
|
def credit(self, transaction, amount, memo):
|
||||||
return self._transaction_split(transaction, 'credit', amount, memo)
|
return self._transaction_split(transaction, 'credit', amount, memo)
|
||||||
|
|
||||||
def _transaction_split(self, transaction, side, amount, memo):
|
def _transaction_split(self, transaction, side, amount, memo):
|
||||||
""" Common part of credit() and debit(). """
|
""" Common part of credit() and debit(). """
|
||||||
with closing(self.db.cursor()) as cur:
|
with closing(self.db.cursor()) as cur:
|
||||||
cur.execute("INSERT INTO transaction_splits (transaction, side, account, amount, memo) VALUES (%s, %s, %s, %s, %s)", [transaction, side, self.id, amount, memo])
|
cur.execute("INSERT INTO transaction_splits (transaction, side, account, amount, memo) VALUES (%s, %s, %s, %s, %s)", [transaction, side, self.id, amount, memo])
|
||||||
|
|
||||||
def add_barcode(self, barcode):
|
def add_barcode(self, barcode):
|
||||||
with closing(self.db.cursor()) as cur:
|
with closing(self.db.cursor()) as cur:
|
||||||
cur.execute("INSERT INTO barcodes (account, barcode) VALUES (%s, %s)", [self.id, barcode])
|
cur.execute("INSERT INTO barcodes (account, barcode) VALUES (%s, %s)", [self.id, barcode])
|
||||||
self.db.commit()
|
self.db.commit()
|
||||||
|
|
||||||
def rename(self, name):
|
def rename(self, name):
|
||||||
with closing(self.db.cursor()) as cur:
|
with closing(self.db.cursor()) as cur:
|
||||||
cur.execute("UPDATE accounts SET name = %s WHERE id = %s", [name, self.id])
|
cur.execute("UPDATE accounts SET name = %s WHERE id = %s", [name, self.id])
|
||||||
self.name = name
|
self.name = name
|
||||||
|
|
|
@ -2,84 +2,84 @@ import psycopg2
|
||||||
from contextlib import closing
|
from contextlib import closing
|
||||||
|
|
||||||
class Currency:
|
class Currency:
|
||||||
""" Currency
|
""" Currency
|
||||||
|
|
||||||
Each account has a currency (1 Kč, 1 Club Maté, ...), pairs of
|
Each account has a currency (1 Kč, 1 Club Maté, ...), pairs of
|
||||||
currencies have (asymmetric) exchange rates. """
|
currencies have (asymmetric) exchange rates. """
|
||||||
def __init__(self, db, id, name):
|
def __init__(self, db, id, name):
|
||||||
self.db = db
|
self.db = db
|
||||||
self.id = id
|
self.id = id
|
||||||
self.name = name
|
self.name = name
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def default(cls, db):
|
def default(cls, db):
|
||||||
""" Default wallet currency """
|
""" Default wallet currency """
|
||||||
return cls.load(db, name = "Kč")
|
return cls.load(db, name = "Kč")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load(cls, db, id = None, name = None):
|
def load(cls, db, id = None, name = None):
|
||||||
""" Constructor for existing currency """
|
""" Constructor for existing currency """
|
||||||
if id is not None:
|
if id is not None:
|
||||||
with closing(db.cursor()) as cur:
|
with closing(db.cursor()) as cur:
|
||||||
cur.execute("SELECT name FROM currencies WHERE id = %s", [id])
|
cur.execute("SELECT name FROM currencies WHERE id = %s", [id])
|
||||||
name = cur.fetchone()[0]
|
name = cur.fetchone()[0]
|
||||||
elif name is not None:
|
elif name is not None:
|
||||||
with closing(db.cursor()) as cur:
|
with closing(db.cursor()) as cur:
|
||||||
cur.execute("SELECT id FROM currencies WHERE name = %s", [name])
|
cur.execute("SELECT id FROM currencies WHERE name = %s", [name])
|
||||||
id = cur.fetchone()[0]
|
id = cur.fetchone()[0]
|
||||||
else:
|
else:
|
||||||
raise NameError("Currency.load(): Specify either id or name")
|
raise NameError("Currency.load(): Specify either id or name")
|
||||||
return cls(db, name = name, id = id)
|
return cls(db, name = name, id = id)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create(cls, db, name):
|
def create(cls, db, name):
|
||||||
""" Constructor for new currency """
|
""" Constructor for new currency """
|
||||||
with closing(db.cursor()) as cur:
|
with closing(db.cursor()) as cur:
|
||||||
cur.execute("INSERT INTO currencies (name) VALUES (%s) RETURNING id", [name])
|
cur.execute("INSERT INTO currencies (name) VALUES (%s) RETURNING id", [name])
|
||||||
id = cur.fetchone()[0]
|
id = cur.fetchone()[0]
|
||||||
return cls(db, name = name, id = id)
|
return cls(db, name = name, id = id)
|
||||||
|
|
||||||
def rates(self, other):
|
def rates(self, other):
|
||||||
""" Return tuple ($buy, $sell) of rates of $self in relation to $other (brmbar.Currency):
|
""" 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)
|
$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) """
|
$sell is the price of $self in means of $other when selling it (from brmbar) """
|
||||||
with closing(self.db.cursor()) as cur:
|
with closing(self.db.cursor()) as cur:
|
||||||
|
|
||||||
cur.execute("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])
|
cur.execute("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])
|
||||||
res = cur.fetchone()
|
res = cur.fetchone()
|
||||||
if res is None:
|
if res is None:
|
||||||
raise NameError("Currency.rate(): Unknown conversion " + other.name() + " to " + self.name())
|
raise NameError("Currency.rate(): Unknown conversion " + other.name() + " to " + self.name())
|
||||||
buy_rate, buy_rate_dir = res
|
buy_rate, buy_rate_dir = res
|
||||||
buy = buy_rate if buy_rate_dir == "target_to_source" else 1/buy_rate
|
buy = buy_rate if buy_rate_dir == "target_to_source" else 1/buy_rate
|
||||||
|
|
||||||
cur.execute("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])
|
cur.execute("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])
|
||||||
res = cur.fetchone()
|
res = cur.fetchone()
|
||||||
if res is None:
|
if res is None:
|
||||||
raise NameError("Currency.rate(): Unknown conversion " + self.name() + " to " + other.name())
|
raise NameError("Currency.rate(): Unknown conversion " + self.name() + " to " + other.name())
|
||||||
sell_rate, sell_rate_dir = res
|
sell_rate, sell_rate_dir = res
|
||||||
sell = sell_rate if sell_rate_dir == "source_to_target" else 1/sell_rate
|
sell = sell_rate if sell_rate_dir == "source_to_target" else 1/sell_rate
|
||||||
|
|
||||||
return (buy, sell)
|
return (buy, sell)
|
||||||
|
|
||||||
def convert(self, amount, target):
|
def convert(self, amount, target):
|
||||||
with closing(self.db.cursor()) as cur:
|
with closing(self.db.cursor()) as cur:
|
||||||
cur.execute("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])
|
cur.execute("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])
|
||||||
res = cur.fetchone()
|
res = cur.fetchone()
|
||||||
if res is None:
|
if res is None:
|
||||||
raise NameError("Currency.convert(): Unknown conversion " + self.name() + " to " + other.name())
|
raise NameError("Currency.convert(): Unknown conversion " + self.name() + " to " + other.name())
|
||||||
rate, rate_dir = res
|
rate, rate_dir = res
|
||||||
if rate_dir == "source_to_target":
|
if rate_dir == "source_to_target":
|
||||||
resamount = amount * rate
|
resamount = amount * rate
|
||||||
else:
|
else:
|
||||||
resamount = amount / rate
|
resamount = amount / rate
|
||||||
return resamount
|
return resamount
|
||||||
|
|
||||||
def str(self, amount):
|
def str(self, amount):
|
||||||
return "{:.2f} {}".format(amount, self.name)
|
return "{:.2f} {}".format(amount, self.name)
|
||||||
|
|
||||||
def update_sell_rate(self, target, rate):
|
def update_sell_rate(self, target, rate):
|
||||||
with closing(self.db.cursor()) as cur:
|
with closing(self.db.cursor()) as cur:
|
||||||
cur.execute("INSERT INTO exchange_rates (source, target, rate, rate_dir) VALUES (%s, %s, %s, %s)", [self.id, target.id, rate, "source_to_target"])
|
cur.execute("INSERT INTO exchange_rates (source, target, rate, rate_dir) VALUES (%s, %s, %s, %s)", [self.id, target.id, rate, "source_to_target"])
|
||||||
def update_buy_rate(self, source, rate):
|
def update_buy_rate(self, source, rate):
|
||||||
with closing(self.db.cursor()) as cur:
|
with closing(self.db.cursor()) as cur:
|
||||||
cur.execute("INSERT INTO exchange_rates (source, target, rate, rate_dir) VALUES (%s, %s, %s, %s)", [source.id, self.id, rate, "target_to_source"])
|
cur.execute("INSERT INTO exchange_rates (source, target, rate, rate_dir) VALUES (%s, %s, %s, %s)", [source.id, self.id, rate, "target_to_source"])
|
||||||
|
|
|
@ -6,127 +6,127 @@ import psycopg2
|
||||||
from contextlib import closing
|
from contextlib import closing
|
||||||
|
|
||||||
class Shop:
|
class Shop:
|
||||||
""" BrmBar Shop
|
""" BrmBar Shop
|
||||||
|
|
||||||
Business logic so that only interaction is left in the hands
|
Business logic so that only interaction is left in the hands
|
||||||
of the frontend scripts. """
|
of the frontend scripts. """
|
||||||
def __init__(self, db, currency, profits, cash):
|
def __init__(self, db, currency, profits, cash):
|
||||||
self.db = db
|
self.db = db
|
||||||
self.currency = currency # brmbar.Currency
|
self.currency = currency # brmbar.Currency
|
||||||
self.profits = profits # income brmbar.Account for brmbar profit margins on items
|
self.profits = profits # income brmbar.Account for brmbar profit margins on items
|
||||||
self.cash = cash # our operational ("wallet") cash account
|
self.cash = cash # our operational ("wallet") cash account
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def new_with_defaults(cls, db):
|
def new_with_defaults(cls, db):
|
||||||
return cls(db,
|
return cls(db,
|
||||||
currency = Currency.default(db),
|
currency = Currency.default(db),
|
||||||
profits = Account.load(db, name = "BrmBar Profits"),
|
profits = Account.load(db, name = "BrmBar Profits"),
|
||||||
cash = Account.load(db, name = "BrmBar Cash"))
|
cash = Account.load(db, name = "BrmBar Cash"))
|
||||||
|
|
||||||
def sell(self, item, user, amount = 1):
|
def sell(self, item, user, amount = 1):
|
||||||
# Sale: Currency conversion from item currency to shop currency
|
# Sale: Currency conversion from item currency to shop currency
|
||||||
(buy, sell) = item.currency.rates(self.currency)
|
(buy, sell) = item.currency.rates(self.currency)
|
||||||
cost = amount * sell
|
cost = amount * sell
|
||||||
profit = amount * (sell - buy)
|
profit = amount * (sell - buy)
|
||||||
|
|
||||||
transaction = self._transaction(responsible = user, description = "BrmBar sale of {}x {} to {}".format(amount, item.name, user.name))
|
transaction = self._transaction(responsible = user, description = "BrmBar sale of {}x {} to {}".format(amount, item.name, user.name))
|
||||||
item.credit(transaction, amount, user.name)
|
item.credit(transaction, amount, user.name)
|
||||||
user.debit(transaction, cost, item.name) # debit (increase) on a _debt_ account
|
user.debit(transaction, cost, item.name) # debit (increase) on a _debt_ account
|
||||||
self.profits.debit(transaction, profit, "Margin on " + item.name)
|
self.profits.debit(transaction, profit, "Margin on " + item.name)
|
||||||
self.db.commit()
|
self.db.commit()
|
||||||
|
|
||||||
return cost
|
return cost
|
||||||
|
|
||||||
def sell_for_cash(self, item, amount = 1):
|
def sell_for_cash(self, item, amount = 1):
|
||||||
# Sale: Currency conversion from item currency to shop currency
|
# Sale: Currency conversion from item currency to shop currency
|
||||||
(buy, sell) = item.currency.rates(self.currency)
|
(buy, sell) = item.currency.rates(self.currency)
|
||||||
cost = amount * sell
|
cost = amount * sell
|
||||||
profit = amount * (sell - buy)
|
profit = amount * (sell - buy)
|
||||||
|
|
||||||
transaction = self._transaction(description = "BrmBar sale of {}x {} for cash".format(amount, item.name))
|
transaction = self._transaction(description = "BrmBar sale of {}x {} for cash".format(amount, item.name))
|
||||||
item.credit(transaction, amount, "Cash")
|
item.credit(transaction, amount, "Cash")
|
||||||
self.cash.debit(transaction, cost, item.name)
|
self.cash.debit(transaction, cost, item.name)
|
||||||
self.profits.debit(transaction, profit, "Margin on " + item.name)
|
self.profits.debit(transaction, profit, "Margin on " + item.name)
|
||||||
self.db.commit()
|
self.db.commit()
|
||||||
|
|
||||||
return cost
|
return cost
|
||||||
|
|
||||||
def add_credit(self, credit, user):
|
def add_credit(self, credit, user):
|
||||||
transaction = self._transaction(responsible = user, description = "BrmBar credit replenishment for " + user.name)
|
transaction = self._transaction(responsible = user, description = "BrmBar credit replenishment for " + user.name)
|
||||||
self.cash.debit(transaction, credit, user.name)
|
self.cash.debit(transaction, credit, user.name)
|
||||||
user.credit(transaction, credit, "Credit replenishment")
|
user.credit(transaction, credit, "Credit replenishment")
|
||||||
self.db.commit()
|
self.db.commit()
|
||||||
|
|
||||||
def withdraw_credit(self, credit, user):
|
def withdraw_credit(self, credit, user):
|
||||||
transaction = self._transaction(responsible = user, description = "BrmBar credit withdrawal for " + user.name)
|
transaction = self._transaction(responsible = user, description = "BrmBar credit withdrawal for " + user.name)
|
||||||
self.cash.credit(transaction, credit, user.name)
|
self.cash.credit(transaction, credit, user.name)
|
||||||
user.debit(transaction, credit, "Credit withdrawal")
|
user.debit(transaction, credit, "Credit withdrawal")
|
||||||
self.db.commit()
|
self.db.commit()
|
||||||
|
|
||||||
def buy_for_cash(self, item, amount = 1):
|
def buy_for_cash(self, item, amount = 1):
|
||||||
# Buy: Currency conversion from item currency to shop currency
|
# Buy: Currency conversion from item currency to shop currency
|
||||||
(buy, sell) = item.currency.rates(self.currency)
|
(buy, sell) = item.currency.rates(self.currency)
|
||||||
cost = amount * buy
|
cost = amount * buy
|
||||||
|
|
||||||
transaction = self._transaction(description = "BrmBar stock replenishment of {}x {} for cash".format(amount, item.name))
|
transaction = self._transaction(description = "BrmBar stock replenishment of {}x {} for cash".format(amount, item.name))
|
||||||
item.debit(transaction, amount, "Cash")
|
item.debit(transaction, amount, "Cash")
|
||||||
self.cash.credit(transaction, cost, item.name)
|
self.cash.credit(transaction, cost, item.name)
|
||||||
self.db.commit()
|
self.db.commit()
|
||||||
|
|
||||||
return cost
|
return cost
|
||||||
|
|
||||||
def receipt_to_credit(self, user, credit, description):
|
def receipt_to_credit(self, user, credit, description):
|
||||||
transaction = self._transaction(responsible = user, description = "Receipt: " + description)
|
transaction = self._transaction(responsible = user, description = "Receipt: " + description)
|
||||||
self.profits.credit(transaction, credit, user.name)
|
self.profits.credit(transaction, credit, user.name)
|
||||||
user.credit(transaction, credit, "Credit from receipt: " + description)
|
user.credit(transaction, credit, "Credit from receipt: " + description)
|
||||||
self.db.commit()
|
self.db.commit()
|
||||||
|
|
||||||
def _transaction(self, responsible = None, description = None):
|
def _transaction(self, responsible = None, description = None):
|
||||||
with closing(self.db.cursor()) as cur:
|
with closing(self.db.cursor()) as cur:
|
||||||
cur.execute("INSERT INTO transactions (responsible, description) VALUES (%s, %s) RETURNING id",
|
cur.execute("INSERT INTO transactions (responsible, description) VALUES (%s, %s) RETURNING id",
|
||||||
[responsible.id if responsible else None, description])
|
[responsible.id if responsible else None, description])
|
||||||
transaction = cur.fetchone()[0]
|
transaction = cur.fetchone()[0]
|
||||||
return transaction
|
return transaction
|
||||||
|
|
||||||
def credit_balance(self):
|
def credit_balance(self):
|
||||||
with closing(self.db.cursor()) as cur:
|
with closing(self.db.cursor()) as cur:
|
||||||
# We assume all debt accounts share a currency
|
# We assume all debt accounts share a currency
|
||||||
sumselect = """
|
sumselect = """
|
||||||
SELECT SUM(ts.amount)
|
SELECT SUM(ts.amount)
|
||||||
FROM accounts AS a
|
FROM accounts AS a
|
||||||
LEFT JOIN transaction_splits AS ts ON a.id = ts.account
|
LEFT JOIN transaction_splits AS ts ON a.id = ts.account
|
||||||
WHERE a.acctype = %s AND ts.side = %s
|
WHERE a.acctype = %s AND ts.side = %s
|
||||||
"""
|
"""
|
||||||
cur.execute(sumselect, ["debt", 'debit'])
|
cur.execute(sumselect, ["debt", 'debit'])
|
||||||
debit = cur.fetchone()[0] or 0
|
debit = cur.fetchone()[0] or 0
|
||||||
cur.execute(sumselect, ["debt", 'credit'])
|
cur.execute(sumselect, ["debt", 'credit'])
|
||||||
credit = cur.fetchone()[0] or 0
|
credit = cur.fetchone()[0] or 0
|
||||||
return debit - credit
|
return debit - credit
|
||||||
def credit_negbalance_str(self):
|
def credit_negbalance_str(self):
|
||||||
return self.currency.str(-self.credit_balance())
|
return self.currency.str(-self.credit_balance())
|
||||||
|
|
||||||
def inventory_balance(self):
|
def inventory_balance(self):
|
||||||
balance = 0
|
balance = 0
|
||||||
with closing(self.db.cursor()) as cur:
|
with closing(self.db.cursor()) as cur:
|
||||||
# Each inventory account has its own currency,
|
# Each inventory account has its own currency,
|
||||||
# so we just do this ugly iteration
|
# so we just do this ugly iteration
|
||||||
cur.execute("SELECT id FROM accounts WHERE acctype = %s", ["inventory"])
|
cur.execute("SELECT id FROM accounts WHERE acctype = %s", ["inventory"])
|
||||||
for inventory in cur:
|
for inventory in cur:
|
||||||
invid = inventory[0]
|
invid = inventory[0]
|
||||||
inv = Account.load(self.db, id = invid)
|
inv = Account.load(self.db, id = invid)
|
||||||
# FIXME: This is not correct as each instance of inventory
|
# FIXME: This is not correct as each instance of inventory
|
||||||
# might have been bought for a different price! Therefore,
|
# might have been bought for a different price! Therefore,
|
||||||
# we need to replace the command below with a complex SQL
|
# we need to replace the command below with a complex SQL
|
||||||
# statement that will... ugh, accounting is hard!
|
# statement that will... ugh, accounting is hard!
|
||||||
balance += inv.currency.convert(inv.balance(), self.currency)
|
balance += inv.currency.convert(inv.balance(), self.currency)
|
||||||
return balance
|
return balance
|
||||||
def inventory_balance_str(self):
|
def inventory_balance_str(self):
|
||||||
return self.currency.str(self.inventory_balance())
|
return self.currency.str(self.inventory_balance())
|
||||||
|
|
||||||
def account_list(self, acctype):
|
def account_list(self, acctype):
|
||||||
accts = []
|
accts = []
|
||||||
with closing(self.db.cursor()) as cur:
|
with closing(self.db.cursor()) as cur:
|
||||||
cur.execute("SELECT id FROM accounts WHERE acctype = %s ORDER BY name ASC", [acctype])
|
cur.execute("SELECT id FROM accounts WHERE acctype = %s ORDER BY name ASC", [acctype])
|
||||||
for inventory in cur:
|
for inventory in cur:
|
||||||
accts += [ Account.load(self.db, id = inventory[0]) ]
|
accts += [ Account.load(self.db, id = inventory[0]) ]
|
||||||
return accts
|
return accts
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue