ProjectExplorer.Project.Updater.FileVersion
diff --git a/brmbar3/brmbar-gui-qt4/main.qml b/brmbar3/brmbar-gui-qt4/main.qml
index 9eefbc6..5c43528 100644
--- a/brmbar3/brmbar-gui-qt4/main.qml
+++ b/brmbar3/brmbar-gui-qt4/main.qml
@@ -1,3 +1,4 @@
+// import QtQuick 1.0 // to target S60 5th Edition or Maemo 5
import QtQuick 1.1
BasePage {
@@ -16,11 +17,11 @@ BasePage {
}
function loadPageByAcct(acct) {
- if (acct.acctype === "inventory") {
+ if (acct.acctype == "inventory") {
loadPage("ItemInfo", { name: acct["name"], dbid: acct["id"], price: acct["price"] })
- } else if (acct.acctype === "debt") {
+ } else if (acct.acctype == "debt") {
loadPage("UserInfo", { name: acct["name"], dbid: acct["id"], negbalance: acct["negbalance"] })
- } else if (acct.acctype === "recharge") {
+ } else if (acct.acctype == "recharge") {
loadPage("ChargeCredit", { amount: acct["amount"] })
}
}
diff --git a/brmbar3/brmbar-tui.py b/brmbar3/brmbar-tui.py
deleted file mode 100755
index 00bdf44..0000000
--- a/brmbar3/brmbar-tui.py
+++ /dev/null
@@ -1,62 +0,0 @@
-#!/usr/bin/python3
-
-import sys
-
-from brmbar import Database
-
-import brmbar
-
-db = Database.Database("dbname=brmbar")
-shop = brmbar.Shop.new_with_defaults(db)
-currency = shop.currency
-
-active_inv_item = None
-active_credit = None
-
-for line in sys.stdin:
- barcode = line.rstrip()
-
- if barcode[0] == "$":
- credits = {'$02': 20, '$05': 50, '$10': 100, '$20': 200, '$50': 500, '$1k': 1000}
- credit = credits[barcode]
- if credit is None:
- print("Unknown barcode: " + barcode)
- continue
- print("CREDIT " + str(credit))
- active_inv_item = None
- active_credit = credit
- continue
-
- if barcode == "SCR":
- print("SHOW CREDIT")
- active_inv_item = None
- active_credit = None
- continue
-
- acct = brmbar.Account.load_by_barcode(db, barcode)
- if acct is None:
- print("Unknown barcode: " + barcode)
- continue
-
- if acct.acctype == 'debt':
- if active_inv_item is not None:
- cost = shop.sell(item = active_inv_item, user = acct)
- print("{} has bought {} for {} and now has {} balance".format(acct.name, active_inv_item.name, currency.str(cost), acct.negbalance_str()))
- elif active_credit is not None:
- shop.add_credit(credit = active_credit, user = acct)
- print("{} has added {} credit and now has {} balance".format(acct.name, currency.str(active_credit), acct.negbalance_str()))
- else:
- print("{} has {} balance".format(acct.name, acct.negbalance_str()))
- active_inv_item = None
- active_credit = None
-
- elif acct.acctype == 'inventory':
- buy, sell = acct.currency.rates(currency)
- print("{} costs {} with {} in stock".format(acct.name, currency.str(sell), int(acct.balance())))
- active_inv_item = acct
- active_credit = None
-
- else:
- print("invalid account type {}".format(acct.acctype))
- active_inv_item = None
- active_credit = None
diff --git a/brmbar3/brmbar-web.py b/brmbar3/brmbar-web.py
deleted file mode 100755
index 5d84378..0000000
--- a/brmbar3/brmbar-web.py
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/usr/bin/python
-
-import sys
-
-from brmbar import Database
-
-import brmbar
-
-from flask import *
-app = Flask(__name__)
-#app.debug = True
-
-@app.route('/stock/')
-def stock(show_all=False):
- # TODO: Use a fancy template.
- # FIXME: XSS protection.
- response = 'Id | Item Name | Bal. |
'
- for a in shop.account_list("inventory"):
- style = ''
- balance = a.balance()
- if balance == 0:
- if not show_all:
- continue
- style = 'color: grey; font-style: italic'
- elif balance < 0:
- style = 'color: red'
- response += '%d | %s | %d |
' % (style, a.id, a.name, balance)
- response += '
'
- if show_all:
- response += '(hide out-of-stock items)
'
- else:
- response += '(show all items)
'
- return response
-
-@app.route('/stock/all')
-def stockall():
- return stock(show_all=True)
-
-
-db = Database.Database("dbname=brmbar")
-shop = brmbar.Shop.new_with_defaults(db)
-currency = shop.currency
-
-if __name__ == '__main__':
- app.run(host='0.0.0.0')
diff --git a/brmbar3/brmbar/Account.py b/brmbar3/brmbar/Account.py
index 215df11..29dd79e 100644
--- a/brmbar3/brmbar/Account.py
+++ b/brmbar3/brmbar/Account.py
@@ -40,22 +40,16 @@ class Account:
@classmethod
def create(cls, db, name, currency, acctype):
""" Constructor for new account """
- # id = db.execute_and_fetch("INSERT INTO accounts (name, currency, acctype) VALUES (%s, %s, %s) RETURNING id", [name, currency.id, acctype])
- id = db.execute_and_fetch("SELECT public.create_account(%s, %s, %s)", [name, currency.id, acctype])
- # id = id[0]
+ id = db.execute_and_fetch("INSERT INTO accounts (name, currency, acctype) VALUES (%s, %s, %s) RETURNING id", [name, currency.id, acctype])
+ id = id[0]
return cls(db, name = name, id = id, currency = currency, acctype = acctype)
def balance(self):
- bal = self.db.execute_and_fetch(
- "SELECT public.compute_account_balance(%s)",
- [self.id]
- )[0]
- return bal
- #debit = self.db.execute_and_fetch("SELECT SUM(amount) FROM transaction_splits WHERE account = %s AND side = %s", [self.id, 'debit'])
- #debit = debit[0] or 0
- #credit = self.db.execute_and_fetch("SELECT SUM(amount) FROM transaction_splits WHERE account = %s AND side = %s", [self.id, 'credit'])
- #credit = credit[0] or 0
- #return debit - credit
+ debit = self.db.execute_and_fetch("SELECT SUM(amount) FROM transaction_splits WHERE account = %s AND side = %s", [self.id, 'debit'])
+ debit = debit[0] or 0
+ credit = self.db.execute_and_fetch("SELECT SUM(amount) FROM transaction_splits WHERE account = %s AND side = %s", [self.id, 'credit'])
+ credit = credit[0] or 0
+ return debit - credit
def balance_str(self):
return self.currency.str(self.balance())
@@ -74,11 +68,9 @@ class Account:
self.db.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):
- # self.db.execute("INSERT INTO barcodes (account, barcode) VALUES (%s, %s)", [self.id, barcode])
- self.db.execute("SELECT public.add_barcode_to_account(%s, %s)", [self.id, barcode])
+ self.db.execute("INSERT INTO barcodes (account, barcode) VALUES (%s, %s)", [self.id, barcode])
self.db.commit()
def rename(self, name):
- # self.db.execute("UPDATE accounts SET name = %s WHERE id = %s", [name, self.id])
- self.db.execute("SELECT public.rename_account(%s, %s)", [self.id, name])
+ self.db.execute("UPDATE accounts SET name = %s WHERE id = %s", [name, self.id])
self.name = name
diff --git a/brmbar3/brmbar/Currency.py b/brmbar3/brmbar/Currency.py
index 29da4a3..b382d77 100644
--- a/brmbar3/brmbar/Currency.py
+++ b/brmbar3/brmbar/Currency.py
@@ -1,4 +1,3 @@
-# vim: set fileencoding=utf8
class Currency:
""" Currency
@@ -31,34 +30,15 @@ class Currency:
@classmethod
def create(cls, db, name):
""" Constructor for new currency """
- # id = db.execute_and_fetch("INSERT INTO currencies (name) VALUES (%s) RETURNING id", [name])
- id = db.execute_and_fetch("SELECT public.create_currency(%s)", [name])
- # id = id[0]
+ id = db.execute_and_fetch("INSERT INTO currencies (name) VALUES (%s) RETURNING id", [name])
+ id = id[0]
return cls(db, name = name, id = id)
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())
@@ -73,7 +53,6 @@ class Currency:
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:
@@ -89,10 +68,6 @@ class Currency:
return "{:.2f} {}".format(amount, self.name)
def update_sell_rate(self, target, rate):
- # self.db.execute("INSERT INTO exchange_rates (source, target, rate, rate_dir) VALUES (%s, %s, %s, %s)", [self.id, target.id, rate, "source_to_target"])
- self.db.execute("SELECT public.update_currency_sell_rate(%s, %s, %s)",
- [self.id, target.id, rate])
+ self.db.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):
- # self.db.execute("INSERT INTO exchange_rates (source, target, rate, rate_dir) VALUES (%s, %s, %s, %s)", [source.id, self.id, rate, "target_to_source"])
- self.db.execute("SELECT public.update_currency_buy_rate(%s, %s, %s)",
- [source.id, self.id, rate])
+ self.db.execute("INSERT INTO exchange_rates (source, target, rate, rate_dir) VALUES (%s, %s, %s, %s)", [source.id, self.id, rate, "target_to_source"])
diff --git a/brmbar3/brmbar/Database.py b/brmbar3/brmbar/Database.py
index d0202d4..e5962ab 100644
--- a/brmbar3/brmbar/Database.py
+++ b/brmbar3/brmbar/Database.py
@@ -36,12 +36,6 @@ class Database:
else:
cur.execute(query, attrs)
return cur
- except psycopg2.DataError as error: # when biitr comes and enters '99999999999999999999' for amount
- print("We have invalid input data (SQLi?): level %s (%s) @%s" % (
- level, error, time.strftime("%Y%m%d %a %I:%m %p")
- ))
- self.db_conn.rollback()
- raise RuntimeError("Unsanitized data entered again... BOBBY TABLES")
except psycopg2.OperationalError as error:
print("Sleeping: level %s (%s) @%s" % (
level, error, time.strftime("%Y%m%d %a %I:%m %p")
diff --git a/brmbar3/brmbar/Shop.py b/brmbar3/brmbar/Shop.py
index e7dbc6c..1623cac 100644
--- a/brmbar3/brmbar/Shop.py
+++ b/brmbar3/brmbar/Shop.py
@@ -7,141 +7,75 @@ class Shop:
Business logic so that only interaction is left in the hands
of the frontend scripts. """
- def __init__(self, db, currency, profits, cash, excess, deficit):
+ def __init__(self, db, currency, profits, cash):
self.db = db
self.currency = currency # brmbar.Currency
self.profits = profits # income brmbar.Account for brmbar profit margins on items
self.cash = cash # our operational ("wallet") cash account
- self.excess = excess # account from which is deducted cash during inventory item fixing (when system contains less items than is the reality)
- self.deficit = deficit # account where is put cash during inventory item fixing (when system contains more items than is the reality)
@classmethod
def new_with_defaults(cls, db):
return cls(db,
currency = Currency.default(db),
profits = Account.load(db, name = "BrmBar Profits"),
- cash = Account.load(db, name = "BrmBar Cash"),
- excess = Account.load(db, name = "BrmBar Excess"),
- deficit = Account.load(db, name = "BrmBar Deficit"))
+ cash = Account.load(db, name = "BrmBar Cash"))
def sell(self, item, user, amount = 1):
- # Call the stored procedure for the sale
- cost = self.db.execute_and_fetch(
- "SELECT public.sell_item(%s, %s, %s, %s, %s)",
- [item.id, amount, user.id, self.currency.id, f"BrmBar sale of {amount}x {item.name} to {user.name}"]
- )[0]#[0]
-
- self.db.commit()
- return cost
# Sale: Currency conversion from item currency to shop currency
- #(buy, sell) = item.currency.rates(self.currency)
- #cost = amount * sell
- #profit = amount * (sell - buy)
+ (buy, sell) = item.currency.rates(self.currency)
+ cost = amount * sell
+ profit = amount * (sell - buy)
- #transaction = self._transaction(responsible = user, description = "BrmBar sale of {}x {} to {}".format(amount, item.name, user.name))
- #item.credit(transaction, amount, user.name)
- #user.debit(transaction, cost, item.name) # debit (increase) on a _debt_ account
- #self.profits.debit(transaction, profit, "Margin on " + item.name)
- #self.db.commit()
- #return cost
+ transaction = self._transaction(responsible = user, description = "BrmBar sale of {}x {} to {}".format(amount, item.name, user.name))
+ item.credit(transaction, amount, user.name)
+ user.debit(transaction, cost, item.name) # debit (increase) on a _debt_ account
+ self.profits.debit(transaction, profit, "Margin on " + item.name)
+ self.db.commit()
+
+ return cost
def sell_for_cash(self, item, amount = 1):
- cost = self.db.execute_and_fetch(
- "SELECT public.sell_item_for_cash(%s, %s, %s, %s, %s)",
- [item.id, amount, user.id, self.currency.id, f"BrmBar sale of {amount}x {item.name} for cash"]
- )[0]#[0]
-
- self.db.commit()
- return cost
- ## Sale: Currency conversion from item currency to shop currency
- #(buy, sell) = item.currency.rates(self.currency)
- #cost = amount * sell
- #profit = amount * (sell - buy)
-
- #transaction = self._transaction(description = "BrmBar sale of {}x {} for cash".format(amount, item.name))
- #item.credit(transaction, amount, "Cash")
- #self.cash.debit(transaction, cost, item.name)
- #self.profits.debit(transaction, profit, "Margin on " + item.name)
- #self.db.commit()
-
- #return cost
-
- def undo_sale(self, item, user, amount = 1):
- # Undo sale; rarely needed
- #(buy, sell) = item.currency.rates(self.currency)
- #cost = amount * sell
- #profit = amount * (sell - buy)
-
- #transaction = self._transaction(responsible = user, description = "BrmBar sale UNDO of {}x {} to {}".format(amount, item.name, user.name))
- #item.debit(transaction, amount, user.name + " (sale undo)")
- #user.credit(transaction, cost, item.name + " (sale undo)")
- #self.profits.credit(transaction, profit, "Margin repaid on " + item.name)
- # Call the stored procedure for undoing a sale
- cost = self.db.execute_and_fetch(
- "SELECT public.undo_sale_of_item(%s, %s, %s, %s)",
- [item.id, amount, user.id, user.currency.id, f"BrmBar sale UNDO of {amount}x {item.name} to {user.name}"]
- )[0]#[0]
+ # Sale: Currency conversion from item currency to shop currency
+ (buy, sell) = item.currency.rates(self.currency)
+ cost = amount * sell
+ profit = amount * (sell - buy)
+ transaction = self._transaction(description = "BrmBar sale of {}x {} for cash".format(amount, item.name))
+ item.credit(transaction, amount, "Cash")
+ self.cash.debit(transaction, cost, item.name)
+ self.profits.debit(transaction, profit, "Margin on " + item.name)
self.db.commit()
return cost
def add_credit(self, credit, user):
- self.db.execute_and_fetch(
- "SELECT public.add_credit(%s, %s, %s, %s)",
- [self.cash.id, credit, user.id, user.name]
- )
+ transaction = self._transaction(responsible = user, description = "BrmBar credit replenishment for " + user.name)
+ self.cash.debit(transaction, credit, user.name)
+ user.credit(transaction, credit, "Credit replenishment")
self.db.commit()
- #transaction = self._transaction(responsible = user, description = "BrmBar credit replenishment for " + user.name)
- #self.cash.debit(transaction, credit, user.name)
- #user.credit(transaction, credit, "Credit replenishment")
- #self.db.commit()
-
def withdraw_credit(self, credit, user):
- self.db.execute_and_fetch(
- "SELECT public.withdraw_credit(%s, %s, %s, %s)",
- [self.cash.id, credit, user.id, user.name]
- )
+ transaction = self._transaction(responsible = user, description = "BrmBar credit withdrawal for " + user.name)
+ self.cash.credit(transaction, credit, user.name)
+ user.debit(transaction, credit, "Credit withdrawal")
self.db.commit()
- #transaction = self._transaction(responsible = user, description = "BrmBar credit withdrawal for " + user.name)
- #self.cash.credit(transaction, credit, user.name)
- #user.debit(transaction, credit, "Credit withdrawal")
- #self.db.commit()
-
- def transfer_credit(self, userfrom, userto, amount):
- self.db.execute_and_fetch(
- "SELECT public.transfer_credit(%s, %s, %s, %s)",
- [self.cash.id, credit, user.id, user.name]
- )
- self.db.commit()
- #self.add_credit(amount, userto)
- #self.withdraw_credit(amount, userfrom)
def buy_for_cash(self, item, amount = 1):
- cost = self.db.execute_and_fetch(
- "SELECT public.buy_for_cash(%s, %s, %s, %s, %s)",
- [self.cash.id, item.id, amount, self.currency.id, item.name]
- )[0]
# Buy: Currency conversion from item currency to shop currency
- #(buy, sell) = item.currency.rates(self.currency)
- #cost = amount * buy
+ (buy, sell) = item.currency.rates(self.currency)
+ cost = amount * buy
- #transaction = self._transaction(description = "BrmBar stock replenishment of {}x {} for cash".format(amount, item.name))
- #item.debit(transaction, amount, "Cash")
- #self.cash.credit(transaction, cost, item.name)
+ transaction = self._transaction(description = "BrmBar stock replenishment of {}x {} for cash".format(amount, item.name))
+ item.debit(transaction, amount, "Cash")
+ self.cash.credit(transaction, cost, item.name)
self.db.commit()
return cost
def receipt_to_credit(self, user, credit, description):
- #transaction = self._transaction(responsible = user, description = "Receipt: " + description)
- #self.profits.credit(transaction, credit, user.name)
- #user.credit(transaction, credit, "Credit from receipt: " + description)
- self.db.execute_and_fetch(
- "SELECT public.buy_for_cash(%s, %s, %s, %s, %s)",
- [self.profits.id, user.id, user.name, credit, description]
- )[0]
+ transaction = self._transaction(responsible = user, description = "Receipt: " + description)
+ self.profits.credit(transaction, credit, user.name)
+ user.credit(transaction, credit, "Credit from receipt: " + description)
self.db.commit()
def _transaction(self, responsible = None, description = None):
@@ -150,7 +84,7 @@ class Shop:
transaction = transaction[0]
return transaction
- def credit_balance(self, overflow=None):
+ def credit_balance(self):
# We assume all debt accounts share a currency
sumselect = """
SELECT SUM(ts.amount)
@@ -158,17 +92,14 @@ class Shop:
LEFT JOIN transaction_splits AS ts ON a.id = ts.account
WHERE a.acctype = %s AND ts.side = %s
"""
- if overflow is not None:
- sumselect += ' AND a.name ' + ('NOT ' if overflow == 'exclude' else '') + ' LIKE \'%%-overflow\''
cur = self.db.execute_and_fetch(sumselect, ["debt", 'debit'])
debit = cur[0] or 0
credit = self.db.execute_and_fetch(sumselect, ["debt", 'credit'])
credit = credit[0] or 0
return debit - credit
- def credit_negbalance_str(self, overflow=None):
- return self.currency.str(-self.credit_balance(overflow=overflow))
+ def credit_negbalance_str(self):
+ return self.currency.str(-self.credit_balance())
-# XXX causing extra heavy delay ( thousands of extra SQL queries ), disabled
def inventory_balance(self):
balance = 0
# Each inventory account has its own currency,
@@ -181,116 +112,15 @@ class Shop:
# might have been bought for a different price! Therefore,
# we need to replace the command below with a complex SQL
# statement that will... ugh, accounting is hard!
- b = inv.balance() * inv.currency.rates(self.currency)[0]
- # if b != 0:
- # print(str(b) + ',' + inv.name)
- balance += b
+ balance += inv.currency.convert(inv.balance(), self.currency)
return balance
-
-# XXX bypass hack
def inventory_balance_str(self):
- # return self.currency.str(self.inventory_balance())
- return "XXX"
+ return self.currency.str(self.inventory_balance())
- def account_list(self, acctype, like_str="%%"):
+ def account_list(self, acctype):
"""list all accounts (people or items, as per acctype)"""
accts = []
- cur = self.db.execute_and_fetchall("SELECT id FROM accounts WHERE acctype = %s AND name ILIKE %s ORDER BY name ASC", [acctype, like_str])
- #FIXME: sanitize input like_str ^
+ cur = self.db.execute_and_fetchall("SELECT id FROM accounts WHERE acctype = %s ORDER BY name ASC", [acctype])
for inventory in cur:
accts += [ Account.load(self.db, id = inventory[0]) ]
return accts
-
- def fix_inventory(self, item, amount):
- rv = self.db.execute_and_fetch(
- "SELECT public.fix_inventory(%s, %s, %s, %s, %s, %s)",
- [item.id, item.currency.id, self.excess.id, self.deficit.id, self.currency.id, amount]
- )[0]
-
- self.db.commit()
- return rv
- #amount_in_reality = amount
- #amount_in_system = item.balance()
- #(buy, sell) = item.currency.rates(self.currency)
-
- #diff = abs(amount_in_reality - amount_in_system)
- #buy_total = buy * diff
- #if amount_in_reality > amount_in_system:
- # transaction = self._transaction(description = "BrmBar inventory fix of {}pcs {} in system to {}pcs in reality".format(amount_in_system, item.name,amount_in_reality))
- # item.debit(transaction, diff, "Inventory fix excess")
- # self.excess.credit(transaction, buy_total, "Inventory fix excess " + item.name)
- # self.db.commit()
- # return True
- #elif amount_in_reality < amount_in_system:
- # transaction = self._transaction(description = "BrmBar inventory fix of {}pcs {} in system to {}pcs in reality".format(amount_in_system, item.name,amount_in_reality))
- # item.credit(transaction, diff, "Inventory fix deficit")
- # self.deficit.debit(transaction, buy_total, "Inventory fix deficit " + item.name)
- # self.db.commit()
- # return True
- #else:
- # transaction = self._transaction(description = "BrmBar inventory fix of {}pcs {} in system to {}pcs in reality".format(amount_in_system, item.name,amount_in_reality))
- # item.debit(transaction, 0, "Inventory fix - amount was correct")
- # item.credit(transaction, 0, "Inventory fix - amount was correct")
- # self.db.commit()
- # return False
-
- def fix_cash(self, amount):
- rv = self.db.execute_and_fetch(
- "SELECT public.fix_cash(%s, %s, %s, %s)",
- [self.excess.id, self.deficit.id, self.currency.id, amount]
- )[0]
-
- self.db.commit()
- return rv
- #amount_in_reality = amount
- #amount_in_system = self.cash.balance()
-
- #diff = abs(amount_in_reality - amount_in_system)
- #if amount_in_reality > amount_in_system:
- # transaction = self._transaction(description = "BrmBar cash inventory fix of {} in system to {} in reality".format(amount_in_system, amount_in_reality))
- # self.cash.debit(transaction, diff, "Inventory fix excess")
- # self.excess.credit(transaction, diff, "Inventory cash fix excess.")
- # self.db.commit()
- # return True
- #elif amount_in_reality < amount_in_system:
- # transaction = self._transaction(description = "BrmBar cash inventory fix of {} in system to {} in reality".format(amount_in_system, amount_in_reality))
- # self.cash.credit(transaction, diff, "Inventory fix deficit")
- # self.deficit.debit(transaction, diff, "Inventory fix deficit.")
- # self.db.commit()
- # return True
- #else:
- # return False
-
- def consolidate(self):
- msg = self.db.execute_and_fetch(
- "SELECT public.make_consolidate_transaction(%s, %s, %s)",
- [self.excess.id, self.deficit.id, self.profits.id]
- )[0]
- #transaction = self._transaction(description = "BrmBar inventory consolidation")
- #excess_balance = self.excess.balance()
- #if excess_balance != 0:
- # print("Excess balance {} debited to profit".format(-excess_balance))
- # self.excess.debit(transaction, -excess_balance, "Excess balance added to profit.")
- # self.profits.debit(transaction, -excess_balance, "Excess balance added to profit.")
- #deficit_balance = self.deficit.balance()
- #if deficit_balance != 0:
- # print("Deficit balance {} credited to profit".format(deficit_balance))
- # self.deficit.credit(transaction, deficit_balance, "Deficit balance removed from profit.")
- # self.profits.credit(transaction, deficit_balance, "Deficit balance removed from profit.")
- if msg != None:
- print(msg)
- self.db.commit()
-
- def undo(self, oldtid):
- #description = self.db.execute_and_fetch("SELECT description FROM transactions WHERE id = %s", [oldtid])[0]
- #description = 'undo %d (%s)' % (oldtid, description)
-
- #transaction = self._transaction(description=description)
- #for split in self.db.execute_and_fetchall("SELECT id, side, account, amount, memo FROM transaction_splits WHERE transaction = %s", [oldtid]):
- # splitid, side, account, amount, memo = split
- # memo = 'undo %d (%s)' % (splitid, memo)
- # amount = -amount
- # self.db.execute("INSERT INTO transaction_splits (transaction, side, account, amount, memo) VALUES (%s, %s, %s, %s, %s)", [transaction, side, account, amount, memo])
- transaction = self.db.execute_and_fetch("SELECT public.undo_transaction(%s)",[oldtid])[0]
- self.db.commit()
- return transaction
diff --git a/brmbar3/crontab b/brmbar3/crontab
deleted file mode 100644
index 2e66748..0000000
--- a/brmbar3/crontab
+++ /dev/null
@@ -1,15 +0,0 @@
-# cleanup bounty
-*/5 * * * * ~/brmbar/brmbar3/uklid-watchdog.sh
-0 0 * * 1 ~/brmbar/brmbar3/uklid-refill.sh
-# overall summary
-5 4 * * * ~/brmbar/brmbar3/daily-summary.sh | mail -s "daily brmbar summary" yyy@yyy
-# debt track
-5 0 * * * ~/brmbar/brmbar3/dluhy.sh 2>/dev/null
-
-# per-user summary
-1 0 * * * /home/brmlab/brmbar/brmbar3/log.sh yyy yyy@yyy
-
-# backup
-6 * * * * echo "SELECT * FROM account_balances;" | psql brmbar | gzip -9 | ssh -Tp 110 -i /home/brmlab/.ssh/id_ecdsa jenda@coralmyn.hrach.eu
-16 1 * * * pg_dump brmbar | gzip -9 | ssh -Tp 110 -i /home/brmlab/.ssh/id_ecdsa jenda@coralmyn.hrach.eu
-
diff --git a/brmbar3/daily-summary.sh b/brmbar3/daily-summary.sh
deleted file mode 100755
index 2fe58bd..0000000
--- a/brmbar3/daily-summary.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/sh
-# Add a crontab entry like:
-# 5 4 * * * ~/brmbar/brmbar3/daily-summary.sh | mail -s "daily brmbar summary" rada@brmlab.cz
-cd ~/brmbar/brmbar3
-./brmbar-cli.py stats
-echo
-echo "Time since last full inventory check: $(echo "select now()-time from transactions where description = 'BrmBar inventory consolidation' order by time desc limit 1;" | psql brmbar | tail -n +3 | head -n 1 | tr -s " ")"
-echo
-echo "Overflows: $(echo "SELECT name, -crbalance FROM account_balances WHERE name LIKE '%overflow%' AND crbalance != 0 ORDER BY name" | psql brmbar | tail -n +3 | grep '|' | tr -s " " | sed -e "s/ |/:/g" -e "s/$/;/" | tr -d "\n") TOTAL: $(echo "SELECT -SUM(crbalance) FROM account_balances WHERE name LIKE '%overflow%' AND crbalance != 0" | psql brmbar | tail -n +3 | head -n 1 | tr -s " ")"
-echo
-echo "Club Mate sold in last 24 hours: $(echo "select count(*) from transaction_cashsums where time > now() - '1 day'::INTERVAL and (description like '%Club Mate%' or description like '%granatove mate%')" | psql brmbar | tail -n +3 | head -n 1 | tr -s " ") bottles"
diff --git a/brmbar3/dluhy.sh b/brmbar3/dluhy.sh
deleted file mode 100755
index 61c2a46..0000000
--- a/brmbar3/dluhy.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-p1=`echo -n "brmbar - dluhy: "; echo "SELECT name, crbalance FROM account_balances WHERE acctype = 'debt' AND crbalance < -100 AND name NOT LIKE '%overflow%' AND name NOT LIKE 'sachyo' ORDER BY crbalance ASC" | psql brmbar | tail -n +3 | grep '|' | tr -s " " | sed -e "s/ |/:/g" -e "s/$/;/" | tr -d "\n"`
-p2=`echo "SELECT sum(crbalance) FROM account_balances WHERE acctype = 'debt' AND crbalance < 0 AND name NOT LIKE '%overflow%' AND name NOT LIKE 'sachyo'" | psql brmbar | tail -n +3 | head -n 1 | tr -s " "`
-echo "$p1 total$p2 Kc. https://www.elektro-obojky.cz/" | ssh -p 110 -i /home/brmlab/.ssh/id_rsa jenda@coralmyn.hrach.eu
diff --git a/brmbar3/doc/architecture.md b/brmbar3/doc/architecture.md
deleted file mode 100644
index 791517f..0000000
--- a/brmbar3/doc/architecture.md
+++ /dev/null
@@ -1,106 +0,0 @@
-BrmBar v3 - Architectural Overview
-==================================
-
-BrmBar v3 is written in Python, with the database stored in PostgreSQL
-and the primary user interface modelled in QtQuick. All user interfaces
-share a common *brmbar* package that provides few Python classes for
-manipulation with the base objects.
-
-Objects and Database Schema
----------------------------
-
-### Account ###
-
-The most essential brmbar object is an Account, which can track
-balances of various kinds (described by *acctype* column) in the
-classical accounting paradigm:
-
-* **Cash**: A physical stash of cash. One cash account is created
- by default, corresponding to the cash box where people put money
- when buying stuff (or depositing money in their user accounts).
- Often, that's the only cash account you need.
-* **Debt**: Represents brmbar's debt to some person. These accounts
- are actually the "user accounts" where people deposit money. When
- a deposit of 100 is made, 100 is *subtracted* from the balance,
- the balance is -100 and brmbar is in debt of 100 to the user.
- When the user buys something for 200, 200 is *added* to the balance,
- the balance is 100 and the user is in debt of 100 to the brmbar.
- This is correct notation from accounting point of view, but somewhat
- confusing for the users, so in the user interface (and crbalance
- column of some views), this balance is *negated*!
-* **Inventory**: Represents inventory items (e.g. Club Mate bottles).
- The account balance represents the quantity of items.
-* **Income**: Represents pure income of brmbar, i.e. the profit;
- there is usually just a single account of this type where all the
- profit (sell price of an item minus the buy price of an item)
- is accumulated.
-* **Expense**: This type is currently not used.
-* **Starting balance** and **ending balance**: This may be used
- in the future when transaction book needs to be compressed.
-
-As you can see, the amount of cash, user accounts, inventory items
-etc. are all represented as **Account** objects that are of various
-**types**, are **named** and have a certain balance (calculated
-from a transaction book). That balance is a number represented
-in certain **currency**. It also has a set of **barcodes** associated.
-
-### Currency, Exchange rate ###
-
-Usually, all accounts that deal with cash (the cash, debt, income, ...
-accounts) share a single currency that corresponds to the physical
-currency locally in use (the default is `Kč`). However, inventory
-items have balances corresponding to item quantities - to deal with
-this correctly, each inventory item *has its own currency*; i.e.
-`Club Mate` bottle is a currency associated with the `Club Mate`
-account.
-
-Currencies have defined (uni-directional) exchange rates. The exchange
-rate of "Kč to Club Mate bottles" is the buy price of Club Mate, how
-much you pay for one bottle of Club Mate from the cash box when you
-are stocking in Club Mate. The exchange rate of "Club Mate bottle to Kč"
-is the sell price of Club Mate, how much you pay for one bottle of Club
-Mate to the cash box when you are buying it from brmbar (sell price
-should be higher than buy price if you want to make a profit).
-
-Exchange rate is valid since some defined time; historical exchange
-rates are therefore kept and this allows to account for changing prices
-of inventory items. (Unfortunately, at the time of writing this, the
-profit calculation actually didn't make use of that yet.)
-
-### Transactions, Transaction splits ###
-
-A transaction book is used to determine current account balances and
-stores all operations related to accounts - depositing or withdrawing
-money, stocking in items, and most importantly buying stuff (either for
-cash or from a debt account). A transaction happenned at some **time**
-and was performed by certain **responsible** person.
-
-The actual accounts involved in a transaction are specified by a list of
-transaction splits that either put balance into the transaction (*credit*
-side) or grab balance from it (*debit* side). For example, a typical
-transaction representing a sale of Club Mate bottle to user "pasky"
-would be split like this:
-
-* *credit* of 1 Club Mate on Club Mate account with memo "pasky".
-* *debit* of 35 Kč on "pasky" account with memo "Club Mate"
- (indeed we _add_ 35Kč to the debt account for pasky buying
- the Club Mate; if this seems weird, refer to the "debt" account
- type description).
-* *debit* of 5 Kč on income account Profits with memo "Margin
- on Club Mate" (this represents the sale price - buy price delta,
- i.e. the profit we made in brmbar by selling this Club Mate).
-
-The brmbar Python Package
--------------------------
-
-The **brmbar** package (in brmbar/ subdirectory) provides common brmbar
-functionality for the various user interfaces:
-
-* **Database**: Layer for performing SQL queries with some error handling.
-* **Currency**: Class for querying and manipulating currency objects and
- converting between them based on stored exchange rates.
-* **Account**: Class for querying and manipulating the account objects
- and their current balance.
-* **Shop**: Class providing the "business logic" of all the actual user
- operations: selling stuff, depositing and withdrawing moeny, adding
- stock, retrieving list of accounts of given type, etc.
diff --git a/brmbar3/log.sh b/brmbar3/log.sh
deleted file mode 100755
index b1afbdb..0000000
--- a/brmbar3/log.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/bash
-p=`/home/brmlab/brmbar/brmbar3/brmbar-cli.py userlog "$1" yesterday`
-
-if [ -n "$p" ]; then
- echo "$p" | mail -s "brmbar report" "$2"
-fi
diff --git a/brmbar3/schema/0001-init.sql b/brmbar3/schema/0001-init.sql
deleted file mode 100644
index 8e7f8db..0000000
--- a/brmbar3/schema/0001-init.sql
+++ /dev/null
@@ -1,313 +0,0 @@
---
--- 0001-init.sql
---
--- Initial SQL schema construction as of 2025-04-20 (or so)
---
--- ISC License
---
--- Copyright 2023-2025 Brmlab, z.s.
--- Dominik Pantůček
---
--- Permission to use, copy, modify, and/or distribute this software
--- for any purpose with or without fee is hereby granted, provided
--- that the above copyright notice and this permission notice appear
--- in all copies.
---
--- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
--- WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
--- WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
--- AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
--- CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
--- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
--- NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
--- CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
---
-
--- To require fully-qualified names
-SELECT pg_catalog.set_config('search_path', '', false);
-
--- Privileged schema with protected data
-CREATE SCHEMA IF NOT EXISTS brmbar_privileged;
-
--- Initial versioning
-CREATE TABLE IF NOT EXISTS brmbar_privileged.brmbar_schema(
- ver INTEGER NOT NULL
-);
-
--- ----------------------------------------------------------------
--- Legacy Schema Initialization
--- ----------------------------------------------------------------
-
-DO $$
-DECLARE v INTEGER;
-BEGIN
- SELECT ver FROM brmbar_privileged.brmbar_schema INTO v;
- IF v IS NULL THEN
- -- --------------------------------
- -- Legacy Types
-
- SELECT COUNT(*) INTO v
- FROM pg_catalog.pg_type typ
- INNER JOIN pg_catalog.pg_namespace nsp
- ON nsp.oid = typ.typnamespace
- WHERE nsp.nspname = 'public'
- AND typ.typname='exchange_rate_direction';
- IF v=0 THEN
- RAISE NOTICE 'Creating type exchange_rate_direction';
- CREATE TYPE public.exchange_rate_direction
- AS ENUM ('source_to_target', 'target_to_source');
- ELSE
- RAISE NOTICE 'Type exchange_rate_direction already exists';
- END IF;
-
- SELECT COUNT(*) INTO v
- FROM pg_catalog.pg_type typ
- INNER JOIN pg_catalog.pg_namespace nsp
- ON nsp.oid = typ.typnamespace
- WHERE nsp.nspname = 'public'
- AND typ.typname='account_type';
- IF v=0 THEN
- RAISE NOTICE 'Creating type account_type';
- CREATE TYPE public.account_type
- AS ENUM ('cash', 'debt', 'inventory', 'income', 'expense',
- 'starting_balance', 'ending_balance');
- ELSE
- RAISE NOTICE 'Type account_type already exists';
- END IF;
-
- SELECT COUNT(*) INTO v
- FROM pg_catalog.pg_type typ
- INNER JOIN pg_catalog.pg_namespace nsp
- ON nsp.oid = typ.typnamespace
- WHERE nsp.nspname = 'public'
- AND typ.typname='transaction_split_side';
- IF v=0 THEN
- RAISE NOTICE 'Creating type transaction_split_side';
- CREATE TYPE public.transaction_split_side
- AS ENUM ('credit', 'debit');
- ELSE
- RAISE NOTICE 'Type transaction_split_side already exists';
- END IF;
-
- -- --------------------------------
- -- Currencies sequence, table and potential initial data
-
- CREATE SEQUENCE IF NOT EXISTS public.currencies_id_seq
- START WITH 2 INCREMENT BY 1;
- CREATE TABLE IF NOT EXISTS public.currencies (
- id INTEGER PRIMARY KEY NOT NULL DEFAULT NEXTVAL('public.currencies_id_seq'::regclass),
- name VARCHAR(128) NOT NULL,
- UNIQUE(name)
- );
- INSERT INTO public.currencies (id, name) VALUES (1, 'Kč')
- ON CONFLICT DO NOTHING;
-
- -- --------------------------------
- -- Exchange rates table - no initial data required
-
- CREATE TABLE IF NOT EXISTS public.exchange_rates (
- valid_since TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL,
-
- target INTEGER NOT NULL,
- FOREIGN KEY (target) REFERENCES public.currencies (id),
-
- source INTEGER NOT NULL,
- FOREIGN KEY (source) REFERENCES public.currencies (id),
-
- rate DECIMAL(12,2) NOT NULL,
- rate_dir public.exchange_rate_direction NOT NULL
- );
-
- -- --------------------------------
- -- Accounts sequence and table and 4 initial accounts
-
- CREATE SEQUENCE IF NOT EXISTS public.accounts_id_seq
- START WITH 2 INCREMENT BY 1;
- CREATE TABLE IF NOT EXISTS public.accounts (
- id INTEGER PRIMARY KEY NOT NULL DEFAULT NEXTVAL('public.accounts_id_seq'::regclass),
-
- name VARCHAR(128) NOT NULL,
- UNIQUE (name),
-
- currency INTEGER NOT NULL,
- FOREIGN KEY (currency) REFERENCES public.currencies (id),
-
- acctype public.account_type NOT NULL,
-
- active BOOLEAN NOT NULL DEFAULT TRUE
- );
- INSERT INTO public.accounts (id, name, currency, acctype)
- VALUES (1, 'BrmBar Cash', (SELECT id FROM public.currencies WHERE name='Kč'), 'cash')
- ON CONFLICT DO NOTHING;
- INSERT INTO public.accounts (name, currency, acctype)
- VALUES ('BrmBar Profits', (SELECT id FROM public.currencies WHERE name='Kč'), 'income')
- ON CONFLICT DO NOTHING;
- INSERT INTO public.accounts (name, currency, acctype)
- VALUES ('BrmBar Excess', (SELECT id FROM public.currencies WHERE name='Kč'), 'income')
- ON CONFLICT DO NOTHING;
- INSERT INTO public.accounts (name, currency, acctype)
- VALUES ('BrmBar Deficit', (SELECT id FROM public.currencies WHERE name='Kč'), 'expense')
- ON CONFLICT DO NOTHING;
-
- -- --------------------------------
- -- Barcodes
-
- CREATE TABLE IF NOT EXISTS public.barcodes (
- barcode VARCHAR(128) PRIMARY KEY NOT NULL,
-
- account INTEGER NOT NULL,
- FOREIGN KEY (account) REFERENCES public.accounts (id)
- );
- INSERT INTO public.barcodes (barcode, account)
- VALUES ('_cash_', (SELECT id FROM public.accounts WHERE acctype = 'cash'))
- ON CONFLICT DO NOTHING;
-
- -- --------------------------------
- -- Transactions
-
- CREATE SEQUENCE IF NOT EXISTS public.transactions_id_seq
- START WITH 1 INCREMENT BY 1;
- CREATE TABLE IF NOT EXISTS public.transactions (
- id INTEGER PRIMARY KEY NOT NULL DEFAULT NEXTVAL('public.transactions_id_seq'::regclass),
- time TIMESTAMP DEFAULT NOW() NOT NULL,
-
- responsible INTEGER,
- FOREIGN KEY (responsible) REFERENCES public.accounts (id),
-
- description TEXT
- );
-
- -- --------------------------------
- -- Transaction splits
-
- CREATE SEQUENCE IF NOT EXISTS public.transaction_splits_id_seq
- START WITH 1 INCREMENT BY 1;
- CREATE TABLE IF NOT EXISTS public.transaction_splits (
- id INTEGER PRIMARY KEY NOT NULL DEFAULT NEXTVAL('public.transaction_splits_id_seq'::regclass),
-
- transaction INTEGER NOT NULL,
- FOREIGN KEY (transaction) REFERENCES public.transactions (id),
-
- side public.transaction_split_side NOT NULL,
-
- account INTEGER NOT NULL,
- FOREIGN KEY (account) REFERENCES public.accounts (id),
- amount DECIMAL(12,2) NOT NULL,
-
- memo TEXT
- );
-
- -- --------------------------------
- -- Account balances view
-
- CREATE OR REPLACE VIEW public.account_balances AS
- SELECT ts.account AS id,
- accounts.name,
- accounts.acctype,
- - sum(
- CASE
- WHEN ts.side = 'credit'::public.transaction_split_side THEN - ts.amount
- ELSE ts.amount
- END) AS crbalance
- FROM public.transaction_splits ts
- LEFT JOIN public.accounts ON accounts.id = ts.account
- GROUP BY ts.account, accounts.name, accounts.acctype
- ORDER BY (- sum(
- CASE
- WHEN ts.side = 'credit'::public.transaction_split_side THEN - ts.amount
- ELSE ts.amount
- END));
-
- -- --------------------------------
- -- Transaction nice splits view
-
- CREATE OR REPLACE VIEW public.transaction_nicesplits AS
- SELECT ts.id,
- ts.transaction,
- ts.account,
- CASE
- WHEN ts.side = 'credit'::public.transaction_split_side THEN - ts.amount
- ELSE ts.amount
- END AS amount,
- a.currency,
- ts.memo
- FROM public.transaction_splits ts
- LEFT JOIN public.accounts a ON a.id = ts.account
- ORDER BY ts.id;
-
- -- --------------------------------
- -- Transaction cash sums view
-
- CREATE OR REPLACE VIEW public.transaction_cashsums AS
- SELECT t.id,
- t."time",
- sum(credit.credit_cash) AS cash_credit,
- sum(debit.debit_cash) AS cash_debit,
- a.name AS responsible,
- t.description
- FROM public.transactions t
- LEFT JOIN ( SELECT cts.amount AS credit_cash,
- cts.transaction AS cts_t
- FROM public.transaction_nicesplits cts
- LEFT JOIN public.accounts a_1 ON a_1.id = cts.account OR a_1.id = cts.account
- WHERE a_1.currency = (( SELECT accounts.currency
- FROM public.accounts
- WHERE accounts.name::text = 'BrmBar Cash'::text))
- AND (a_1.acctype = ANY (ARRAY['cash'::public.account_type, 'debt'::public.account_type]))
- AND cts.amount < 0::numeric) credit ON credit.cts_t = t.id
- LEFT JOIN ( SELECT dts.amount AS debit_cash,
- dts.transaction AS dts_t
- FROM public.transaction_nicesplits dts
- LEFT JOIN public.accounts a_1 ON a_1.id = dts.account OR a_1.id = dts.account
- WHERE a_1.currency = (( SELECT accounts.currency
- FROM public.accounts
- WHERE accounts.name::text = 'BrmBar Cash'::text))
- AND (a_1.acctype = ANY (ARRAY['cash'::public.account_type, 'debt'::public.account_type]))
- AND dts.amount > 0::numeric) debit ON debit.dts_t = t.id
- LEFT JOIN public.accounts a ON a.id = t.responsible
- GROUP BY t.id, a.name
- ORDER BY t.id DESC;
-
- -- --------------------------------
- -- Function to check schema version (used in migrations)
-
- CREATE OR REPLACE FUNCTION brmbar_privileged.has_exact_schema_version(
- IN i_ver INTEGER
- ) RETURNS BOOLEAN
- VOLATILE NOT LEAKPROOF LANGUAGE plpgsql AS $x$
- DECLARE
- v_ver INTEGER;
- BEGIN
- SELECT ver INTO v_ver FROM brmbar_privileged.brmbar_schema;
- IF v_ver is NULL THEN
- RETURN false;
- ELSE
- RETURN v_ver = i_ver;
- END IF;
- END;
- $x$;
-
- -- --------------------------------
- --
-
- CREATE OR REPLACE FUNCTION brmbar_privileged.upgrade_schema_version_to(
- IN i_ver INTEGER
- ) RETURNS VOID
- VOLATILE NOT LEAKPROOF LANGUAGE plpgsql AS $x$
- DECLARE
- v_ver INTEGER;
- BEGIN
- SELECT ver FROM brmbar_privileged.brmbar_schema INTO v_ver;
- IF v_ver=(i_ver-1) THEN
- UPDATE brmbar_privileged.brmbar_schema SET ver = i_ver;
- ELSE
- RAISE EXCEPTION 'Invalid brmbar schema version transition (% -> %)', v_ver, i_ver;
- END IF;
- END;
- $x$;
-
- -- Initialize version 1
- INSERT INTO brmbar_privileged.brmbar_schema(ver) VALUES(1);
- END IF;
-END;
-$$;
diff --git a/brmbar3/schema/0002-trading-accounts.sql b/brmbar3/schema/0002-trading-accounts.sql
deleted file mode 100644
index 021df3d..0000000
--- a/brmbar3/schema/0002-trading-accounts.sql
+++ /dev/null
@@ -1,40 +0,0 @@
---
--- 0002-trading-accounts.sql
---
--- #2 - add trading accounts to account type type
---
--- ISC License
---
--- Copyright 2023-2025 Brmlab, z.s.
--- Dominik Pantůček
---
--- Permission to use, copy, modify, and/or distribute this software
--- for any purpose with or without fee is hereby granted, provided
--- that the above copyright notice and this permission notice appear
--- in all copies.
---
--- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
--- WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
--- WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
--- AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
--- CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
--- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
--- NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
--- CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
---
-
--- Require fully-qualified names
-SELECT pg_catalog.set_config('search_path', '', false);
-
-DO $upgrade_block$
-BEGIN
-
-IF brmbar_privileged.has_exact_schema_version(1) THEN
-
- ALTER TYPE public.account_type ADD VALUE 'trading';
-
- PERFORM brmbar_privileged.upgrade_schema_version_to(2);
-END IF;
-
-END;
-$upgrade_block$;
diff --git a/brmbar3/schema/0003-new-account.sql b/brmbar3/schema/0003-new-account.sql
deleted file mode 100644
index 9ac02b5..0000000
--- a/brmbar3/schema/0003-new-account.sql
+++ /dev/null
@@ -1,52 +0,0 @@
---
--- 0003-new-account.sql
---
--- #3 - stored procedure for creating new account
---
--- ISC License
---
--- Copyright 2023-2025 Brmlab, z.s.
--- Dominik Pantůček
---
--- Permission to use, copy, modify, and/or distribute this software
--- for any purpose with or without fee is hereby granted, provided
--- that the above copyright notice and this permission notice appear
--- in all copies.
---
--- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
--- WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
--- WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
--- AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
--- CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
--- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
--- NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
--- CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
---
-
--- Require fully-qualified names
-SELECT pg_catalog.set_config('search_path', '', false);
-
-DO $upgrade_block$
-BEGIN
-
-IF brmbar_privileged.has_exact_schema_version(2) THEN
-
- CREATE OR REPLACE FUNCTION public.create_account(
- IN i_name public.accounts.name%TYPE,
- IN i_currency public.accounts.currency%TYPE,
- IN i_acctype public.accounts.acctype%TYPE
- ) RETURNS INTEGER LANGUAGE plpgsql AS $$
- DECLARE
- r_id INTEGER;
- BEGIN
- INSERT INTO public.accounts (name, currency, acctype)
- VALUES (i_name, i_currency, i_acctype) RETURNING id INTO r_id;
- RETURN r_id;
- END
- $$;
-
- PERFORM brmbar_privileged.upgrade_schema_version_to(3);
-END IF;
-
-END;
-$upgrade_block$;
diff --git a/brmbar3/schema/0004-add-account-barcode.sql b/brmbar3/schema/0004-add-account-barcode.sql
deleted file mode 100644
index dbdba9a..0000000
--- a/brmbar3/schema/0004-add-account-barcode.sql
+++ /dev/null
@@ -1,50 +0,0 @@
---
--- 0004-add-account-barcode.sql
---
--- #4 - stored procedure for adding barcode to account
---
--- ISC License
---
--- Copyright 2023-2025 Brmlab, z.s.
--- Dominik Pantůček
---
--- Permission to use, copy, modify, and/or distribute this software
--- for any purpose with or without fee is hereby granted, provided
--- that the above copyright notice and this permission notice appear
--- in all copies.
---
--- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
--- WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
--- WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
--- AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
--- CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
--- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
--- NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
--- CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
---
-
--- Require fully-qualified names
-SELECT pg_catalog.set_config('search_path', '', false);
-
-DO $upgrade_block$
-BEGIN
-
-IF brmbar_privileged.has_exact_schema_version(3) THEN
-
- CREATE OR REPLACE FUNCTION public.add_barcode_to_account(
- IN i_account public.barcodes.account%TYPE,
- IN i_barcode public.barcodes.barcode%TYPE
- ) RETURNS VOID LANGUAGE plpgsql AS $$
- DECLARE
- r_id INTEGER;
- BEGIN
- INSERT INTO public.barcodes (account, barcode)
- VALUES (i_account, i_barcode);
- END
- $$;
-
- PERFORM brmbar_privileged.upgrade_schema_version_to(4);
-END IF;
-
-END;
-$upgrade_block$;
diff --git a/brmbar3/schema/0005-rename-account.sql b/brmbar3/schema/0005-rename-account.sql
deleted file mode 100644
index a957029..0000000
--- a/brmbar3/schema/0005-rename-account.sql
+++ /dev/null
@@ -1,51 +0,0 @@
---
--- 0005-rename-account.sql
---
--- #5 - stored procedure for renaming account
---
--- ISC License
---
--- Copyright 2023-2025 Brmlab, z.s.
--- Dominik Pantůček
---
--- Permission to use, copy, modify, and/or distribute this software
--- for any purpose with or without fee is hereby granted, provided
--- that the above copyright notice and this permission notice appear
--- in all copies.
---
--- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
--- WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
--- WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
--- AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
--- CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
--- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
--- NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
--- CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
---
-
--- Require fully-qualified names
-SELECT pg_catalog.set_config('search_path', '', false);
-
-DO $upgrade_block$
-BEGIN
-
-IF brmbar_privileged.has_exact_schema_version(4) THEN
-
- CREATE OR REPLACE FUNCTION public.rename_account(
- IN i_account public.accounts.id%TYPE,
- IN i_name public.accounts.name%TYPE
- ) RETURNS VOID LANGUAGE plpgsql AS $$
- DECLARE
- r_id INTEGER;
- BEGIN
- UPDATE public.accounts
- SET name = i_name
- WHERE id = i_account;
- END
- $$;
-
- PERFORM brmbar_privileged.upgrade_schema_version_to(5);
-END IF;
-
-END;
-$upgrade_block$;
diff --git a/brmbar3/schema/0006-new-currency.sql b/brmbar3/schema/0006-new-currency.sql
deleted file mode 100644
index 0ed9a94..0000000
--- a/brmbar3/schema/0006-new-currency.sql
+++ /dev/null
@@ -1,50 +0,0 @@
---
--- 0006-new-currency.sql
---
--- #6 - stored procedure for creating new currency
---
--- ISC License
---
--- Copyright 2023-2025 Brmlab, z.s.
--- Dominik Pantůček
---
--- Permission to use, copy, modify, and/or distribute this software
--- for any purpose with or without fee is hereby granted, provided
--- that the above copyright notice and this permission notice appear
--- in all copies.
---
--- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
--- WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
--- WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
--- AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
--- CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
--- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
--- NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
--- CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
---
-
--- Require fully-qualified names
-SELECT pg_catalog.set_config('search_path', '', false);
-
-DO $upgrade_block$
-BEGIN
-
-IF brmbar_privileged.has_exact_schema_version(5) THEN
-
- CREATE OR REPLACE FUNCTION public.create_currency(
- IN i_name public.currencies.name%TYPE
- ) RETURNS INTEGER LANGUAGE plpgsql AS $$
- DECLARE
- r_id INTEGER;
- BEGIN
- INSERT INTO public.currencies (name)
- VALUES (i_name) RETURNING id INTO r_id;
- RETURN r_id;
- END
- $$;
-
- PERFORM brmbar_privileged.upgrade_schema_version_to(6);
-END IF;
-
-END;
-$upgrade_block$;
diff --git a/brmbar3/schema/0007-update-currency-sell-rate.sql b/brmbar3/schema/0007-update-currency-sell-rate.sql
deleted file mode 100644
index f627897..0000000
--- a/brmbar3/schema/0007-update-currency-sell-rate.sql
+++ /dev/null
@@ -1,49 +0,0 @@
---
--- 0007-update-currency-sell-rate.sql
---
--- #7 - stored procedure for updating sell rate
---
--- ISC License
---
--- Copyright 2023-2025 Brmlab, z.s.
--- Dominik Pantůček
---
--- Permission to use, copy, modify, and/or distribute this software
--- for any purpose with or without fee is hereby granted, provided
--- that the above copyright notice and this permission notice appear
--- in all copies.
---
--- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
--- WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
--- WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
--- AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
--- CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
--- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
--- NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
--- CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
---
-
--- Require fully-qualified names
-SELECT pg_catalog.set_config('search_path', '', false);
-
-DO $upgrade_block$
-BEGIN
-
-IF brmbar_privileged.has_exact_schema_version(6) THEN
-
- CREATE OR REPLACE FUNCTION public.update_currency_sell_rate(
- IN i_currency public.exchange_rates.source%TYPE,
- IN i_target public.exchange_rates.target%TYPE,
- IN i_rate public.exchange_rates.rate%TYPE
- ) RETURNS VOID LANGUAGE plpgsql AS $$
- BEGIN
- INSERT INTO public.exchange_rates(source, target, rate, rate_dir)
- VALUES (i_currency, i_target, i_rate, 'source_to_target');
- END
- $$;
-
- PERFORM brmbar_privileged.upgrade_schema_version_to(7);
-END IF;
-
-END;
-$upgrade_block$;
diff --git a/brmbar3/schema/0008-update-currency-buy-rate.sql b/brmbar3/schema/0008-update-currency-buy-rate.sql
deleted file mode 100644
index cbab11b..0000000
--- a/brmbar3/schema/0008-update-currency-buy-rate.sql
+++ /dev/null
@@ -1,49 +0,0 @@
---
--- 0008-update-currency-buy-rate.sql
---
--- #8 - stored procedure for updating buy rate
---
--- ISC License
---
--- Copyright 2023-2025 Brmlab, z.s.
--- Dominik Pantůček
---
--- Permission to use, copy, modify, and/or distribute this software
--- for any purpose with or without fee is hereby granted, provided
--- that the above copyright notice and this permission notice appear
--- in all copies.
---
--- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
--- WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
--- WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
--- AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
--- CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
--- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
--- NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
--- CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
---
-
--- Require fully-qualified names
-SELECT pg_catalog.set_config('search_path', '', false);
-
-DO $upgrade_block$
-BEGIN
-
-IF brmbar_privileged.has_exact_schema_version(7) THEN
-
- CREATE OR REPLACE FUNCTION public.update_currency_buy_rate(
- IN i_currency public.exchange_rates.target%TYPE,
- IN i_source public.exchange_rates.source%TYPE,
- IN i_rate public.exchange_rates.rate%TYPE
- ) RETURNS VOID LANGUAGE plpgsql AS $$
- BEGIN
- INSERT INTO public.exchange_rates(source, target, rate, rate_dir)
- VALUES (i_source, i_currency, i_rate, 'target_to_source');
- END
- $$;
-
- PERFORM brmbar_privileged.upgrade_schema_version_to(8);
-END IF;
-
-END;
-$upgrade_block$;
diff --git a/brmbar3/schema/0009-shop-sell.sql b/brmbar3/schema/0009-shop-sell.sql
deleted file mode 100644
index 811a5f5..0000000
--- a/brmbar3/schema/0009-shop-sell.sql
+++ /dev/null
@@ -1,149 +0,0 @@
---
--- 0009-shop-sell.sql
---
--- #9 - stored function for sell transaction
---
--- ISC License
---
--- Copyright 2023-2025 Brmlab, z.s.
--- TMA
---
--- Permission to use, copy, modify, and/or distribute this software
--- for any purpose with or without fee is hereby granted, provided
--- that the above copyright notice and this permission notice appear
--- in all copies.
---
--- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
--- WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
--- WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
--- AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
--- CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
--- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
--- NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
--- CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
---
-
--- To require fully-qualified names
-SELECT pg_catalog.set_config('search_path', '', false);
-
-DO $upgrade_block$
-BEGIN
-
-IF brmbar_privileged.has_exact_schema_version(8) THEN
-
--- return negative number on rate not found
-CREATE OR REPLACE FUNCTION public.find_buy_rate(
- IN i_item_id public.accounts.id%TYPE;
- IN i_other_id public.accounts.id%TYPE;
-) RETURNS NUMERIC
-LANGUAGE plpgsql
-AS $$
-DECLARE
- v_rate public.exchange_rates.rate%TYPE;
- v_rate_dir public.exchange_rates.rate_dir%TYPE;
-BEGIN
- SELECT rate INTO STRICT v_rate, rate_dir INTO STRICT v_rate_dir FROM public.exchange_rates WHERE target = i_item_id AND source = i_other_id AND valid_since <= NOW() ORDER BY valid_since DESC LIMIT 1;
- IF v_rate_dir = 'target_to_source'::public.exchange_rate_direction THEN
- RETURN v_rate;
- ELSE
- RETURN 1/v_rate;
- END IF;
-EXCEPTION
- WHEN NO_DATA_FOUND THEN
- RETURN -1;
-END;
-$$
-
-
--- return negative number on rate not found
-CREATE OR REPLACE FUNCTION public.find_sell_rate(
- IN i_item_id public.accounts.id%TYPE;
- IN i_other_id public.accounts.id%TYPE;
-) RETURNS NUMERIC
-LANGUAGE plpgsql
-AS $$
-DECLARE
- v_rate public.exchange_rates.rate%TYPE;
- v_rate_dir public.exchange_rates.rate_dir%TYPE;
-BEGIN
- SELECT rate INTO STRICT v_rate, rate_dir INTO STRICT v_rate_dir FROM public.exchange_rates WHERE target = i_other_id AND source = i_item_id AND valid_since <= NOW() ORDER BY valid_since DESC LIMIT 1;
- IF v_rate_dir = 'source_to_target'::public.exchange_rate_direction THEN
- RETURN v_rate;
- ELSE
- RETURN 1/v_rate;
- END IF;
-EXCEPTION
- WHEN NO_DATA_FOUND THEN
- RETURN -1;
-END;
-$$
-
-CREATE OR REPLACE FUNCTION public.create_transaction(
- i_responsible_id public.accounts.id%TYPE,
- i_description public.transactions.description%TYPE
-) RETURNS public.transactions.id%TYPE AS $$
-DECLARE
- new_transaction_id public.transactions%TYPE;
-BEGIN
- -- Create a new transaction
- INSERT INTO public.transactions (responsible, description)
- VALUES (i_responsible_id, i_description)
- RETURNING id INTO new_transaction_id;
- -- Return the new transaction ID
- RETURN new_transaction_id;
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE OR REPLACE FUNCTION public.sell_item(
- i_item_id public.accounts.id%TYPE,
- i_amount INTEGER,
- i_user_id public.accounts.id%TYPE,
- i_target_currency_id public.currencies.id%TYPE,
- i_description TEXT
-) RETURNS NUMERIC
-LANGUAGE plpgsql
-AS $$
-DECLARE
- v_buy_rate NUMERIC;
- v_sell_rate NUMERIC;
- v_cost NUMERIC;
- v_profit NUMERIC;
- v_transaction_id public.transactions.id%TYPE;
-BEGIN
- -- Get the buy and sell rates from the stored functions
- v_buy_rate := public.find_buy_rate(i_item_id, i_target_currency_id);
- v_sell_rate := public.find_sell_rate(i_item_id, i_target_currency_id);
-
- -- Calculate cost and profit
- v_cost := i_amount * v_sell_rate;
- v_profit := i_amount * (v_sell_rate - v_buy_rate);
-
- -- Create a new transaction
- v_transaction_id := public.create_transaction(i_user_id, i_description);
-
- -- the item (decrease stock)
- INSERT INTO public.transaction_splits (transaction, side, account, amount, memo)
- VALUES (i_transaction_id, 'credit', i_item_id, i_amount,
- (SELECT "name" FROM public.accounts WHERE id = i_user_id));
-
- -- the user
- INSERT INTO public.transaction_splits (transaction, side, account, amount, memo)
- VALUES (i_transaction_id, 'debit', i_user_id, v_cost,
- (SELECT "name" FROM public.accounts WHERE id = i_item_id));
-
- -- the profit
- INSERT INTO public.transaction_splits (transaction, side, account, amount, memo)
- VALUES (i_transaction_id, 'debit', (SELECT account_id FROM accounts WHERE name = 'BrmBar Profits'), v_profit, (SELECT 'Margin on ' || "name" FROM public.accounts WHERE id = i_item_id));
-
- -- Return the cost
- RETURN v_cost;
-END;
-$$;
-
-PERFORM brmbar_privileged.upgrade_schema_version_to(9);
-END IF;
-
-END;
-$upgrade_block$;
-
--- vim: set ft=plsql :
diff --git a/brmbar3/schema/0010-shop-sell-for-cash.sql b/brmbar3/schema/0010-shop-sell-for-cash.sql
deleted file mode 100644
index 23ad131..0000000
--- a/brmbar3/schema/0010-shop-sell-for-cash.sql
+++ /dev/null
@@ -1,143 +0,0 @@
---
--- 0010-shop-sell-for-cash.sql
---
--- #10 - stored function for cash sell transaction
---
--- ISC License
---
--- Copyright 2023-2025 Brmlab, z.s.
--- TMA
---
--- Permission to use, copy, modify, and/or distribute this software
--- for any purpose with or without fee is hereby granted, provided
--- that the above copyright notice and this permission notice appear
--- in all copies.
---
--- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
--- WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
--- WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
--- AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
--- CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
--- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
--- NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
--- CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
---
-
--- To require fully-qualified names
-SELECT pg_catalog.set_config('search_path', '', false);
-
-DO $upgrade_block$
-BEGIN
-
-IF brmbar_privileged.has_exact_schema_version(9) THEN
-
-CREATE OR REPLACE FUNCTION brmbar_privileged.create_transaction(
- i_responsible_id public.accounts.id%TYPE,
- i_description public.transactions.description%TYPE
-) RETURNS public.transactions.id%TYPE AS $$
-DECLARE
- new_transaction_id public.transactions%TYPE;
-BEGIN
- -- Create a new transaction
- INSERT INTO public.transactions (responsible, description)
- VALUES (i_responsible_id, i_description)
- RETURNING id INTO new_transaction_id;
- -- Return the new transaction ID
- RETURN new_transaction_id;
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE OR REPLACE FUNCTION brmbar_privileged.sell_item_internal(
- i_item_id public.accounts.id%TYPE,
- i_amount INTEGER,
- i_user_id public.accounts.id%TYPE,
- i_target_currency_id public.currencies.id%TYPE,
- i_other_memo TEXT,
- i_description TEXT
-) RETURNS NUMERIC
-LANGUAGE plpgsql
-AS $$
-DECLARE
- v_buy_rate NUMERIC;
- v_sell_rate NUMERIC;
- v_cost NUMERIC;
- v_profit NUMERIC;
- v_transaction_id public.transactions.id%TYPE;
-BEGIN
- -- Get the buy and sell rates from the stored functions
- v_buy_rate := public.find_buy_rate(i_item_id, i_target_currency_id);
- v_sell_rate := public.find_sell_rate(i_item_id, i_target_currency_id);
-
- -- Calculate cost and profit
- v_cost := i_amount * v_sell_rate;
- v_profit := i_amount * (v_sell_rate - v_buy_rate);
-
- -- Create a new transaction
- v_transaction_id := brmbar_privileged.create_transaction(i_user_id, i_description);
-
- -- the item (decrease stock)
- INSERT INTO public.transaction_splits (transaction, side, account, amount, memo)
- VALUES (i_transaction_id, 'credit', i_item_id, i_amount,
- i_other_memo);
-
- -- the user
- INSERT INTO public.transaction_splits (transaction, side, account, amount, memo)
- VALUES (i_transaction_id, 'debit', i_user_id, v_cost,
- (SELECT "name" FROM public.accounts WHERE id = i_item_id));
-
- -- the profit
- INSERT INTO public.transaction_splits (transaction, side, account, amount, memo)
- VALUES (i_transaction_id, 'debit', (SELECT account_id FROM accounts WHERE name = 'BrmBar Profits'), v_profit, (SELECT 'Margin on ' || "name" FROM public.accounts WHERE id = i_item_id));
-
- -- Return the cost
- RETURN v_cost;
-END;
-$$;
-
-CREATE OR REPLACE FUNCTION public.sell_item(
- i_item_id public.accounts.id%TYPE,
- i_amount INTEGER,
- i_user_id public.accounts.id%TYPE,
- i_target_currency_id public.currencies.id%TYPE,
- i_description TEXT
-) RETURNS NUMERIC
-LANGUAGE plpgsql
-AS $$
-BEGIN
- RETURN brmbar_privileged.sell_item_internal(i_item_id,
- i_amount,
- i_other_id,
- i_target_currency_id,
- (SELECT "name" FROM public.accounts WHERE id = i_user_id),
- i_description);
-END;
-$$;
-
-CREATE OR REPLACE FUNCTION public.sell_item_for_cash(
- i_item_id public.accounts.id%TYPE,
- i_amount INTEGER,
- i_user_id public.accounts.id%TYPE,
- i_target_currency_id public.currencies.id%TYPE,
- i_description TEXT
-) RETURNS NUMERIC
-LANGUAGE plpgsql
-AS $$
-BEGIN
- RETURN brmbar_privileged.sell_item_internal(i_item_id,
- i_amount,
- i_other_id,
- i_target_currency_id,
- 'Cash',
- i_description);
-END;
-$$;
-
-DROP FUNCTION public.create_transaction;
-
-PERFORM brmbar_privileged.upgrade_schema_version_to(10);
-END IF;
-
-END;
-$upgrade_block$;
-
--- vim: set ft=plsql :
diff --git a/brmbar3/schema/0011-shop-undo-sale.sql b/brmbar3/schema/0011-shop-undo-sale.sql
deleted file mode 100644
index 67d47cc..0000000
--- a/brmbar3/schema/0011-shop-undo-sale.sql
+++ /dev/null
@@ -1,102 +0,0 @@
---
--- 0011-shop-undo-sale.sql
---
--- #11 - stored function for sale undo transaction
---
--- ISC License
---
--- Copyright 2023-2025 Brmlab, z.s.
--- TMA
---
--- Permission to use, copy, modify, and/or distribute this software
--- for any purpose with or without fee is hereby granted, provided
--- that the above copyright notice and this permission notice appear
--- in all copies.
---
--- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
--- WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
--- WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
--- AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
--- CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
--- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
--- NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
--- CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
---
-
--- To require fully-qualified names
-SELECT pg_catalog.set_config('search_path', '', false);
-
-DO $upgrade_block$
-BEGIN
-
-IF brmbar_privileged.has_exact_schema_version(10) THEN
-
-CREATE OR REPLACE FUNCTION brmbar_privileged.create_transaction(
- i_responsible_id public.accounts.id%TYPE,
- i_description public.transactions.description%TYPE
-) RETURNS public.transactions.id%TYPE AS $$
-DECLARE
- new_transaction_id public.transactions%TYPE;
-BEGIN
- -- Create a new transaction
- INSERT INTO public.transactions (responsible, description)
- VALUES (i_responsible_id, i_description)
- RETURNING id INTO new_transaction_id;
- -- Return the new transaction ID
- RETURN new_transaction_id;
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE OR REPLACE FUNCTION public.undo_sale_of_item(
- i_item_id public.accounts.id%TYPE,
- i_amount INTEGER,
- i_user_id public.accounts.id%TYPE,
- i_target_currency_id public.currencies.id%TYPE,
- i_description TEXT
-) RETURNS NUMERIC
-LANGUAGE plpgsql
-AS $$
-DECLARE
- v_buy_rate NUMERIC;
- v_sell_rate NUMERIC;
- v_cost NUMERIC;
- v_profit NUMERIC;
- v_transaction_id public.transactions.id%TYPE;
-BEGIN
- -- Get the buy and sell rates from the stored functions
- v_buy_rate := public.find_buy_rate(i_item_id, i_target_currency_id);
- v_sell_rate := public.find_sell_rate(i_item_id, i_target_currency_id);
-
- -- Calculate cost and profit
- v_cost := i_amount * v_sell_rate;
- v_profit := i_amount * (v_sell_rate - v_buy_rate);
-
- -- Create a new transaction
- v_transaction_id := brmbar_privileged.create_transaction(i_user_id, i_description);
-
- -- the item (decrease stock)
- INSERT INTO public.transaction_splits (transaction, side, account, amount, memo)
- VALUES (i_transaction_id, 'debit', i_item_id, i_amount,
- (SELECT "name" || ' (sale undo)' FROM public.accounts WHERE id = i_user_id));
-
- -- the user
- INSERT INTO public.transaction_splits (transaction, side, account, amount, memo)
- VALUES (i_transaction_id, 'credit', i_user_id, v_cost,
- (SELECT "name" || ' (sale undo)' FROM public.accounts WHERE id = i_item_id));
-
- -- the profit
- INSERT INTO public.transaction_splits (transaction, side, account, amount, memo)
- VALUES (i_transaction_id, 'credit', (SELECT account_id FROM accounts WHERE name = 'BrmBar Profits'), v_profit, (SELECT 'Margin repaid on ' || "name" FROM public.accounts WHERE id = i_item_id));
-
- -- Return the cost
- RETURN v_cost;
-END;
-$$;
-
-PERFORM brmbar_privileged.upgrade_schema_version_to(11);
-END IF;
-
-END;
-$upgrade_block$;
-
--- vim: set ft=plsql :
diff --git a/brmbar3/schema/0012-shop-add-credit.sql b/brmbar3/schema/0012-shop-add-credit.sql
deleted file mode 100644
index 00318ae..0000000
--- a/brmbar3/schema/0012-shop-add-credit.sql
+++ /dev/null
@@ -1,64 +0,0 @@
---
--- 0012-shop-add-credit.sql
---
--- #12 - stored function for cash deposit transactions
---
--- ISC License
---
--- Copyright 2023-2025 Brmlab, z.s.
--- TMA
---
--- Permission to use, copy, modify, and/or distribute this software
--- for any purpose with or without fee is hereby granted, provided
--- that the above copyright notice and this permission notice appear
--- in all copies.
---
--- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
--- WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
--- WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
--- AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
--- CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
--- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
--- NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
--- CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
---
-
--- To require fully-qualified names
-SELECT pg_catalog.set_config('search_path', '', false);
-
-DO $upgrade_block$
-BEGIN
-
-IF brmbar_privileged.has_exact_schema_version(11) THEN
-
-CREATE OR REPLACE FUNCTION public.add_credit(
- i_cash_account_id public.accounts.id%TYPE,
- i_credit NUMERIC,
- i_user_id public.accounts.id%TYPE,
- i_user_name TEXT
-) RETURNS VOID
-LANGUAGE plpgsql
-AS $$
-DECLARE
- v_transaction_id public.transactions.id%TYPE;
-BEGIN
- -- Create a new transaction
- v_transaction_id := brmbar_privileged.create_transaction(i_user_id, 'BrmBar credit replenishment for ' || i_user_name);
- -- Debit cash (credit replenishment)
- INSERT INTO public.transaction_splits (transaction, side, account, amount, memo)
- VALUES (v_transaction_id, 'debit', i_cash_account_id, i_credit, i_user_name);
- -- Credit the user
- INSERT INTO public.transaction_splits (transaction, side, account, amount, memo)
- VALUES (v_transaction_id, 'credit', i_user_id, i_credit, 'Credit replenishment');
-END;
-$$;
-
-
-
-PERFORM brmbar_privileged.upgrade_schema_version_to(12);
-END IF;
-
-END;
-$upgrade_block$;
-
--- vim: set ft=plsql :
diff --git a/brmbar3/schema/0013-shop-withdraw-credit.sql b/brmbar3/schema/0013-shop-withdraw-credit.sql
deleted file mode 100644
index d379186..0000000
--- a/brmbar3/schema/0013-shop-withdraw-credit.sql
+++ /dev/null
@@ -1,64 +0,0 @@
---
--- 0013-shop-withdraw-credit.sql
---
--- #13 - stored function for cash withdrawal transactions
---
--- ISC License
---
--- Copyright 2023-2025 Brmlab, z.s.
--- TMA
---
--- Permission to use, copy, modify, and/or distribute this software
--- for any purpose with or without fee is hereby granted, provided
--- that the above copyright notice and this permission notice appear
--- in all copies.
---
--- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
--- WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
--- WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
--- AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
--- CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
--- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
--- NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
--- CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
---
-
--- To require fully-qualified names
-SELECT pg_catalog.set_config('search_path', '', false);
-
-DO $upgrade_block$
-BEGIN
-
-IF brmbar_privileged.has_exact_schema_version(12) THEN
-
-CREATE OR REPLACE FUNCTION public.withdraw_credit(
- i_cash_account_id public.accounts.id%TYPE,
- i_credit NUMERIC,
- i_user_id public.accounts.id%TYPE,
- i_user_name TEXT
-) RETURNS VOID
-LANGUAGE plpgsql
-AS $$
-DECLARE
- v_transaction_id public.transactions.id%TYPE;
-BEGIN
- -- Create a new transaction
- v_transaction_id := brmbar_privileged.create_transaction(i_user_id, 'BrmBar credit withdrawal for ' || i_user_name);
- -- Debit cash (credit replenishment)
- INSERT INTO public.transaction_splits (transaction, side, account, amount, memo)
- VALUES (v_transaction_id, 'credit', i_cash_account_id, i_credit, i_user_name);
- -- Credit the user
- INSERT INTO public.transaction_splits (transaction, side, account, amount, memo)
- VALUES (v_transaction_id, 'debit', i_user_id, i_credit, 'Credit withdrawal');
-END;
-$$;
-
-
-
-PERFORM brmbar_privileged.upgrade_schema_version_to(13);
-END IF;
-
-END;
-$upgrade_block$;
-
--- vim: set ft=plsql :
diff --git a/brmbar3/schema/0014-shop-transfer-credit.sql b/brmbar3/schema/0014-shop-transfer-credit.sql
deleted file mode 100644
index 7e13c03..0000000
--- a/brmbar3/schema/0014-shop-transfer-credit.sql
+++ /dev/null
@@ -1,58 +0,0 @@
---
--- 0014-shop-transfer-credit.sql
---
--- #14 - stored function for "credit" transfer transactions
---
--- ISC License
---
--- Copyright 2023-2025 Brmlab, z.s.
--- TMA
---
--- Permission to use, copy, modify, and/or distribute this software
--- for any purpose with or without fee is hereby granted, provided
--- that the above copyright notice and this permission notice appear
--- in all copies.
---
--- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
--- WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
--- WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
--- AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
--- CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
--- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
--- NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
--- CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
---
-
--- To require fully-qualified names
-SELECT pg_catalog.set_config('search_path', '', false);
-
-DO $upgrade_block$
-BEGIN
-
-IF brmbar_privileged.has_exact_schema_version(13) THEN
-
-CREATE OR REPLACE FUNCTION public.transfer_credit(
- i_cash_account_id public.accounts.id%TYPE,
- i_credit NUMERIC,
- i_userfrom_id public.accounts.id%TYPE,
- i_userfrom_name TEXT,
- i_userto_id public.accounts.id%TYPE,
- i_userto_name TEXT
-) RETURNS VOID
-LANGUAGE plpgsql
-AS $$
-BEGIN
- PERFORM public.add_credit(i_cash_account_id, i_credit, i_userto_id, i_userto_name);
- PERFORM public.withdraw_credit(i_cash_account_id, i_credit, i_userfrom_id, i_userfrom_name);
-END;
-$$;
-
-
-
-PERFORM brmbar_privileged.upgrade_schema_version_to(14);
-END IF;
-
-END;
-$upgrade_block$;
-
--- vim: set ft=plsql :
diff --git a/brmbar3/schema/0015-shop-buy-for-cash.sql b/brmbar3/schema/0015-shop-buy-for-cash.sql
deleted file mode 100644
index 5cf12bb..0000000
--- a/brmbar3/schema/0015-shop-buy-for-cash.sql
+++ /dev/null
@@ -1,82 +0,0 @@
---
--- 0015-shop-buy-for-cash.sql
---
--- #15 - stored function for cash-based stock replenishment transaction
---
--- ISC License
---
--- Copyright 2023-2025 Brmlab, z.s.
--- TMA
---
--- Permission to use, copy, modify, and/or distribute this software
--- for any purpose with or without fee is hereby granted, provided
--- that the above copyright notice and this permission notice appear
--- in all copies.
---
--- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
--- WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
--- WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
--- AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
--- CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
--- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
--- NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
--- CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
---
-
--- To require fully-qualified names
-SELECT pg_catalog.set_config('search_path', '', false);
-
-DO $upgrade_block$
-BEGIN
-
-IF brmbar_privileged.has_exact_schema_version(14) THEN
-
-CREATE OR REPLACE FUNCTION public.buy_for_cash(
- i_cash_account_id public.accounts.id%TYPE,
- i_item_id public.accounts.id%TYPE,
- i_amount INTEGER,
- i_target_currency_id public.currencies.id%TYPE,
- i_item_name TEXT
-) RETURNS NUMERIC
-LANGUAGE plpgsql
-AS $$
-DECLARE
- v_buy_rate NUMERIC;
- v_cost NUMERIC;
- v_transaction_id public.transactions.id%TYPE;
-BEGIN
- -- this could fail and it would generate exception in python
- -- FIXME: convert v_buy_rate < 0 into python exception
- v_buy_rate := public.find_buy_rate(i_item_id, i_target_currency_id);
- -- this could fail and it would generate exception in python, even though it is not used
- --v_sell_rate := public.find_sell_rate(i_item_id, i_target_currency_id);
-
- -- Calculate cost and profit
- v_cost := i_amount * v_buy_rate;
-
- -- Create a new transaction
- v_transaction_id := brmbar_privileged.create_transaction(NULL,
- 'BrmBar stock replenishment of ' || i_amount || 'x ' || i_item_name || ' for cash');
-
- -- the item
- INSERT INTO public.transaction_splits (transaction, side, account, amount, memo)
- VALUES (i_transaction_id, 'debit', i_item_id, i_amount,
- 'Cash');
-
- -- the cash
- INSERT INTO public.transaction_splits (transaction, side, account, amount, memo)
- VALUES (i_transaction_id, 'credit', i_cash_account_id, v_cost,
- i_item_name);
-
- -- Return the cost
- RETURN v_cost;
-END;
-$$;
-
-PERFORM brmbar_privileged.upgrade_schema_version_to(15);
-END IF;
-
-END;
-$upgrade_block$;
-
--- vim: set ft=plsql :
diff --git a/brmbar3/schema/0016-shop-receipt-to-credit.sql b/brmbar3/schema/0016-shop-receipt-to-credit.sql
deleted file mode 100644
index 21af8b1..0000000
--- a/brmbar3/schema/0016-shop-receipt-to-credit.sql
+++ /dev/null
@@ -1,64 +0,0 @@
---
--- 0016-shop-buy-for-cash.sql
---
--- #16 - stored function for receipt reimbursement transaction
---
--- ISC License
---
--- Copyright 2023-2025 Brmlab, z.s.
--- TMA
---
--- Permission to use, copy, modify, and/or distribute this software
--- for any purpose with or without fee is hereby granted, provided
--- that the above copyright notice and this permission notice appear
--- in all copies.
---
--- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
--- WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
--- WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
--- AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
--- CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
--- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
--- NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
--- CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
---
-
--- To require fully-qualified names
-SELECT pg_catalog.set_config('search_path', '', false);
-
-DO $upgrade_block$
-BEGIN
-
-IF brmbar_privileged.has_exact_schema_version(15) THEN
-
-CREATE OR REPLACE FUNCTION public.receipt_reimbursement(
- i_profits_id public.accounts.id%TYPE,
- i_user_id public.accounts.id%TYPE,
- i_user_name public.accounts.name%TYPE,
- i_amount NUMERIC,
- i_description TEXT
-) RETURNS VOID
-LANGUAGE plpgsql
-AS $$
-DECLARE
- v_transaction_id public.transactions.id%TYPE;
-BEGIN
- -- Create a new transaction
- v_transaction_id := brmbar_privileged.create_transaction(i_user_id,
- 'Receipt: ' || i_description);
- -- the "profit"
- INSERT INTO public.transaction_splits (transaction, side, account, amount, memo)
- VALUES (i_transaction_id, 'credit', i_profits_id, i_amount, i_user_name);
- -- the user
- INSERT INTO public.transaction_splits (transaction, side, account, amount, memo)
- VALUES (i_transaction_id, 'credit', i_user_id, i_amount, 'Credit from receipt: ' || i_description);
-END;
-$$;
-
-PERFORM brmbar_privileged.upgrade_schema_version_to(16);
-END IF;
-
-END;
-$upgrade_block$;
-
--- vim: set ft=plsql :
diff --git a/brmbar3/schema/0017-shop-fix-inventory.sql b/brmbar3/schema/0017-shop-fix-inventory.sql
deleted file mode 100644
index 3bacd8d..0000000
--- a/brmbar3/schema/0017-shop-fix-inventory.sql
+++ /dev/null
@@ -1,157 +0,0 @@
---
--- 0017-shop-fix-inventory.sql
---
--- #17 - stored function for "fixing" inventory transaction
---
--- ISC License
---
--- Copyright 2023-2025 Brmlab, z.s.
--- TMA
---
--- Permission to use, copy, modify, and/or distribute this software
--- for any purpose with or without fee is hereby granted, provided
--- that the above copyright notice and this permission notice appear
--- in all copies.
---
--- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
--- WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
--- WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
--- AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
--- CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
--- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
--- NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
--- CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
---
-
--- To require fully-qualified names
-SELECT pg_catalog.set_config('search_path', '', false);
-
-DO $upgrade_block$
-BEGIN
-
-IF brmbar_privileged.has_exact_schema_version(16) THEN
-
-CREATE OR REPLACE FUNCTION public.compute_account_balance(
- i_account_id public.accounts.id%TYPE
-) RETURNS NUMERIC
-LANGUAGE plpgsql
-AS $$
-DECLARE
- v_crsum NUMERIC;
- v_dbsum NUMERIC;
-BEGIN
- SELECT COALESCE(SUM(CASE WHEN side='credit' THEN amount ELSE 0 END),0) crsum INTO v_crsum,
- COALESCE(SUM(CASE WHEN side='debit' THEN amount ELSE 0 END),0) dbsum into v_dbsum
- FROM public.transaction_splits ts WHERE ts.account=4
- RETURN v_dbsum - v_crsum;
-END; $$;
-
-CREATE OR REPLACE FUNCTION brmbar_privileged.fix_account_balance(
- IN i_account_id public.acounts.id%TYPE,
- IN i_account_currency_id public.currencies.id%TYPE,
- IN i_excess_id public.acounts.id%TYPE,
- IN i_deficit_id public.acounts.id%TYPE,
- IN i_shop_currency_id public.currencies.id%TYPE,
- IN i_amount_in_reality NUMERIC
-) RETURNS BOOLEAN
-VOLATILE NOT LEAKPROOF LANGUAGE plpgsql AS $fn$
-DECLARE
- v_amount_in_system NUMERIC;
- v_buy_rate NUMERIC;
- v_currency_id public.currencies.id%TYPE;
- v_diff NUMERIC;
- v_buy_total NUMERIC;
- v_ntrn_id public.transactions.id%TYPE;
- v_transaction_memo TEXT;
- v_item_name TEXT;
- v_excess_memo TEXT;
- v_deficit_memo TEXT;
-
- v_old_trn public.transactions%ROWTYPE;
- v_old_split public.transaction_splits%ROWTYPE;
-BEGIN
- v_amount_in_system := public.compute_account_balance(i_account_id);
- IF i_account_currency_id <> i_shop_currency_id THEN
- v_buy_rate := public.find_buy_rate(i_item_id, i_shop_currency_id);
- ELSE
- v_buy_rate := 1;
- END IF;
-
- v_diff := ABS(i_amount_in_reality - v_amount_in_system);
- v_buy_total := v_buy_rate * v_diff;
- -- compute memo strings
- IF i_item_id = 1 THEN -- cash account recognized by magic id
- -- fixing cash
- v_transaction_memo :=
- 'BrmBar cash inventory fix of ' || v_amount_in_system
- || ' in system to ' || i_amount_in_reality || ' in reality';
- v_excess_memo := 'Inventory cash fix excess.';
- v_deficit_memo := 'Inventory fix deficit.';
- ELSE
- -- fixing other account
- SELECT "name" INTO v_item_name FROM public.accounts WHERE id = i_account_id;
- v_transaction_memo :=
- 'BrmBar inventory fix of ' || v_amount_in_system || 'pcs '
- || v_item_name
- || ' in system to ' || i_amount_in_reality || 'pcs in reality';
- v_excess_memo := 'Inventory fix excess ' || v_item_name;
- v_deficit_memo := 'Inventory fix deficit ' || v_item_name;
- END IF;
- -- create transaction based on the relation between counting and accounting
- IF i_amount_in_reality > v_amount_in_system THEN
- v_ntrn_id := brmbar_privileged.create_transaction(NULL, v_transaction_memo);
- INSERT INTO transaction_splits ("transaction", "side", "account", "amount", "memo")
- VALUES (v_ntrn_id, 'debit', i_item_id, v_diff, 'Inventory fix excess');
- INSERT INTO transaction_splits ("transaction", "side", "account", "amount", "memo")
- VALUES (v_ntrn_id, 'credit', i_excess_id, v_buy_total, v_excess_memo);
- RETURN TRUE;
- ELSIF i_amount_in_reality < v_amount_in_system THEN
- v_ntrn_id := brmbar_privileged.create_transaction(NULL, v_transaction_memo);
- INSERT INTO transaction_splits ("transaction", "side", "account", "amount", "memo")
- VALUES (v_ntrn_id, 'credit', i_item_id, v_diff, 'Inventory fix deficit');
- INSERT INTO transaction_splits ("transaction", "side", "account", "amount", "memo")
- VALUES (v_ntrn_id, 'debit', i_deficit_id, v_buy_total, v_deficit_memo);
- RETURN TRUE;
- ELSIF i_account_id <> 1 THEN -- cash account recognized by magic id
- -- record that everything is going on swimmingly only for noncash accounts (WTF)
- v_ntrn_id := brmbar_privileged.create_transaction(NULL, v_transaction_memo);
- INSERT INTO transaction_splits ("transaction", "side", "account", "amount", "memo")
- VALUES (v_ntrn_id, 'debit', i_item_id, 0, 'Inventory fix - amount was correct');
- INSERT INTO transaction_splits ("transaction", "side", "account", "amount", "memo")
- VALUES (v_ntrn_id, 'credit', i_item_id, 0, 'Inventory fix - amount was correct');
- RETURN FALSE;
- END IF;
- RETURN FALSE;
-END;
-$fn$;
-
-
-CREATE OR REPLACE FUNCTION public.fix_inventory(
- IN i_account_id public.acounts.id%TYPE,
- IN i_account_currency_id public.currencies.id%TYPE,
- IN i_excess_id public.acounts.id%TYPE,
- IN i_deficit_id public.acounts.id%TYPE,
- IN i_shop_currency_id public.currencies.id%TYPE,
- IN i_amount_in_reality NUMERIC
-) RETURNS BOOLEAN
-VOLATILE NOT LEAKPROOF LANGUAGE plpgsql AS $fn$
-BEGIN
- RETURN brmbar_privileged.fix_account_balance(
- i_account_id,
- i_account_currency_id,
- i_excess_id,
- i_deficit_id,
- i_shop_currency_id,
- i_amount_in_reality
- );
-END;
-$fn$;
-
-
-PERFORM brmbar_privileged.upgrade_schema_version_to(17);
-END IF;
-
-END;
-$upgrade_block$;
-
--- vim: set ft=plsql :
diff --git a/brmbar3/schema/0018-shop-fix-cash.sql b/brmbar3/schema/0018-shop-fix-cash.sql
deleted file mode 100644
index 2af5d72..0000000
--- a/brmbar3/schema/0018-shop-fix-cash.sql
+++ /dev/null
@@ -1,60 +0,0 @@
---
--- 0018-shop-fix-cash.sql
---
--- #18 - stored function for "fixing cash" transaction
---
--- ISC License
---
--- Copyright 2023-2025 Brmlab, z.s.
--- TMA
---
--- Permission to use, copy, modify, and/or distribute this software
--- for any purpose with or without fee is hereby granted, provided
--- that the above copyright notice and this permission notice appear
--- in all copies.
---
--- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
--- WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
--- WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
--- AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
--- CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
--- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
--- NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
--- CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
---
-
--- To require fully-qualified names
-SELECT pg_catalog.set_config('search_path', '', false);
-
-DO $upgrade_block$
-BEGIN
-
-IF brmbar_privileged.has_exact_schema_version(17) THEN
-
-CREATE OR REPLACE FUNCTION public.fix_cash(
- IN i_excess_id public.acounts.id%TYPE,
- IN i_deficit_id public.acounts.id%TYPE,
- IN i_shop_currency_id public.currencies.id%TYPE,
- IN i_amount_in_reality NUMERIC
-) RETURNS BOOLEAN
-VOLATILE NOT LEAKPROOF LANGUAGE plpgsql AS $fn$
-BEGIN
- RETURN brmbar_privileged.fix_account_balance(
- 1,
- 1,
- i_excess_id,
- i_deficit_id,
- i_shop_currency_id,
- i_amount_in_reality
- );
-END;
-$fn$;
-
-
-PERFORM brmbar_privileged.upgrade_schema_version_to(18);
-END IF;
-
-END;
-$upgrade_block$;
-
--- vim: set ft=plsql :
diff --git a/brmbar3/schema/0019-shop-consolidate.sql b/brmbar3/schema/0019-shop-consolidate.sql
deleted file mode 100644
index db06685..0000000
--- a/brmbar3/schema/0019-shop-consolidate.sql
+++ /dev/null
@@ -1,82 +0,0 @@
---
--- 0019-shop-consolidate.sql
---
--- #19 - stored function for "consolidation" transaction
---
--- ISC License
---
--- Copyright 2023-2025 Brmlab, z.s.
--- TMA
---
--- Permission to use, copy, modify, and/or distribute this software
--- for any purpose with or without fee is hereby granted, provided
--- that the above copyright notice and this permission notice appear
--- in all copies.
---
--- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
--- WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
--- WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
--- AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
--- CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
--- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
--- NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
--- CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
---
-
--- To require fully-qualified names
-SELECT pg_catalog.set_config('search_path', '', false);
-
-DO $upgrade_block$
-BEGIN
-
-IF brmbar_privileged.has_exact_schema_version(18) THEN
-
-CREATE OR REPLACE FUNCTION public.make_consolidate_transaction(
- i_excess_id public.accounts.id%TYPE,
- i_deficit_id public.accounts.id%TYPE,
- i_profits_id public.accounts.id%TYPE
-) RETURNS TEXT
-LANGUAGE plpgsql
-AS $$
-DECLARE
- v_transaction_id public.transactions.id%TYPE;
- v_excess_balance NUMERIC;
- v_deficit_balance NUMERIC;
- v_ret TEXT;
-BEGIN
- v_ret := NULL;
- -- Create a new transaction
- v_transaction_id := brmbar_privileged.create_transaction(NULL,
- 'BrmBar inventory consolidation');
- v_excess_balance := public.compute_account_balance(i_excess_id);
- v_deficit_balance := public.compute_account_balance(i_deficit_id);
- IF v_excess_balance <> 0 THEN
- v_ret := 'Excess balance ' || -v_excess_balance || ' debited to profit';
- INSERT INTO public.transaction_splits (transaction, side, account, amount, memo)
- VALUES (i_transaction_id, 'debit', i_excess_id, -v_excess_balance,
- 'Excess balance added to profit.');
- INSERT INTO public.transaction_splits (transaction, side, account, amount, memo)
- VALUES (i_transaction_id, 'debit', i_profits_id, -v_excess_balance,
- 'Excess balance added to profit.');
- END IF;
- IF v_deficit_balance <> 0 THEN
- v_ret := COALESCE(v_ret, '');
- v_ret := v_ret || 'Deficit balance ' || v_deficit_balance || ' credited to profit';
- INSERT INTO public.transaction_splits (transaction, side, account, amount, memo)
- VALUES (i_transaction_id, 'credit', i_deficit_id, v_deficit_balance,
- 'Deficit balance removed from profit.');
- INSERT INTO public.transaction_splits (transaction, side, account, amount, memo)
- VALUES (i_transaction_id, 'credit', i_profits_id, v_deficit_balance,
- 'Deficit balance removed from profit.');
- END IF;
- RETURN v_ret;
-END;
-$$;
-
-PERFORM brmbar_privileged.upgrade_schema_version_to(19);
-END IF;
-
-END;
-$upgrade_block$;
-
--- vim: set ft=plsql :
diff --git a/brmbar3/schema/0020-shop-undo.sql b/brmbar3/schema/0020-shop-undo.sql
deleted file mode 100644
index a279580..0000000
--- a/brmbar3/schema/0020-shop-undo.sql
+++ /dev/null
@@ -1,64 +0,0 @@
---
--- 0020-shop-undo.sql
---
--- #20 - stored function for undo transaction
---
--- ISC License
---
--- Copyright 2023-2025 Brmlab, z.s.
--- TMA
---
--- Permission to use, copy, modify, and/or distribute this software
--- for any purpose with or without fee is hereby granted, provided
--- that the above copyright notice and this permission notice appear
--- in all copies.
---
--- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
--- WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
--- WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
--- AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
--- CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
--- OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
--- NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
--- CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
---
-
--- To require fully-qualified names
-SELECT pg_catalog.set_config('search_path', '', false);
-
-DO $upgrade_block$
-BEGIN
-
-IF brmbar_privileged.has_exact_schema_version(19) THEN
-
-CREATE OR REPLACE FUNCTION public.undo_transaction(
- IN i_id public.transactions.id%TYPE)
-RETURNS public.transactions.id%TYPE
-VOLATILE NOT LEAKPROOF LANGUAGE plpgsql AS $fn$
-DECLARE
- v_ntrn_id public.transactions.id%TYPE;
- v_old_trn public.transactions%ROWTYPE;
- v_old_split public.transaction_splits%ROWTYPE;
-BEGIN
- SELECT * INTO v_old_trn FROM public.transactions WHERE id = i_id;
- INSERT INTO transactions ("description") VALUES ('undo '||o_id||' ('||v_old_trn.description||')') RETURNING id into v_ntrn_id;
- FOR v_old_split IN
- SELECT * FROM transaction_splits WHERE "transaction" = i_id
- LOOP
- INSERT INTO transaction_splits ("transaction", "side", "account", "amount", "memo")
- VALUES (v_ntrn_id, v_old_split.side, v_old_split.account, -v_old_split.amount,
- 'undo ' || v_old_split.id || ' (' || v_old_split.memo || ')' );
- END LOOP;
- RETURN v_ntrn_id;
-END;
-$fn$;
-
-
-
-PERFORM brmbar_privileged.upgrade_schema_version_to(20);
-END IF;
-
-END;
-$upgrade_block$;
-
--- vim: set ft=plsql :
diff --git a/brmbar3/test--currency-rates.py b/brmbar3/test--currency-rates.py
deleted file mode 100644
index 9ef93bb..0000000
--- a/brmbar3/test--currency-rates.py
+++ /dev/null
@@ -1,73 +0,0 @@
-#!/usr/bin/python3
-
-import sys
-import subprocess
-
-#from brmbar import Database
-#from brmbar import Currency
-
-from contextlib import closing
-import psycopg2
-from brmbar.Database import Database
-from brmbar.Currency import Currency
-import math
-
-#import brmbar
-
-
-
-def approx_equal(a, b, tol=1e-6):
- """Check if two (buy, sell) rate tuples are approximately equal."""
- return (
- isinstance(a, tuple) and isinstance(b, tuple) and
- math.isclose(a[0], b[0], abs_tol=tol) and
- math.isclose(a[1], b[1], abs_tol=tol)
- )
-
-def compare_exceptions(e1, e2):
- """Compare exception types and messages."""
- return type(e1) == type(e2) and str(e1) == str(e2)
-
-def main():
- db = Database("dbname=brmbar")
-
- # Get all currencies
- with closing(db.db_conn.cursor()) as cur:
- cur.execute("SELECT id, name FROM currencies")
- currencies = cur.fetchall()
-
- # Build Currency objects
- currency_objs = [Currency(db, id, name) for id, name in currencies]
-
- # Test all currency pairs
- for c1 in currency_objs:
- for c2 in currency_objs:
- #if c1.id == c2.id:
- # continue
-
- try:
- rates1 = c1.rates(c2)
- exc1 = None
- except (RuntimeError, NameError) as e1:
- rates1 = None
- exc1 = e1
-
- try:
- rates2 = c1.rates2(c2)
- exc2 = None
- except (RuntimeError, NameError) as e2:
- rates2 = None
- exc2 = e2
-
- if exc1 or exc2:
- if not compare_exceptions(exc1, exc2):
- print(f"[EXCEPTION DIFFERENCE] {c1.name} -> {c2.name}")
- print(f" rates() exception: {type(exc1).__name__}: {exc1}")
- print(f" rates2() exception: {type(exc2).__name__}: {exc2}")
- elif not approx_equal(rates1, rates2):
- print(f"[VALUE DIFFERENCE] {c1.name} -> {c2.name}")
- print(f" rates(): {rates1}")
- print(f" rates2(): {rates2}")
-
-if __name__ == "__main__":
- main()
diff --git a/brmbar3/uklid-refill.sh b/brmbar3/uklid-refill.sh
deleted file mode 100644
index 898a081..0000000
--- a/brmbar3/uklid-refill.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/bash
-
-if [ `./brmbar-cli.py iteminfo uklid|grep -o '[0-9]*.[0-9]* pcs'|cut -d '.' -f 1` -eq 0 ]; then
- BOUNTY=`./brmbar-cli.py restock uklid 1 | grep -o 'take -[0-9]*'|grep -o '[0-9]*'`
- echo "Brmlab cleanup bounty for ${BOUNTY}CZK!!!"|ssh jenda@fry.hrach.eu
-fi
diff --git a/brmbar3/uklid-watchdog.sh b/brmbar3/uklid-watchdog.sh
deleted file mode 100644
index 7f86870..0000000
--- a/brmbar3/uklid-watchdog.sh
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/bin/bash
-LASTIDF=/home/brmlab/uklid.last
-
-LASTID=`cat $LASTIDF 2>/dev/null || echo 0`
-
-
-RES=`psql brmbar -Atq -c "select id,description from transactions where id>$LASTID and description like 'BrmBar sale of 1x uklid%' LIMIT 1;"`
-if [ ! -z "$RES" ]; then
- LASTID=`echo "$RES"|cut -d '|' -f 1`
- echo $LASTID > $LASTIDF
-
- WINNER=`echo "$RES"|grep -o 'to [^ ]*'|cut -d ' ' -f 2`
- if [ -z "$WINNER" ]; then
- WINNER="anonymous hunter"
- fi
- echo "Brmlab cleanup bounty was claimed by $WINNER! Thanks!"|ssh -p 110 jenda@coralmyn.hrach.eu
-fi
-