diff --git a/brmbar3/brmbar-gui-qt4.py b/brmbar3/brmbar-gui-qt4.py index 4eb668c..cb8fa46 100755 --- a/brmbar3/brmbar-gui-qt4.py +++ b/brmbar3/brmbar-gui-qt4.py @@ -168,25 +168,21 @@ class ShopAdapter(QtCore.QObject): @QtCore.Slot(result='QVariant') def balance_cash(self): - return "N/A" balance = shop.cash.balance_str() db.commit() return balance @QtCore.Slot(result='QVariant') def balance_profit(self): - return "N/A" balance = shop.profits.balance_str() db.commit() return balance @QtCore.Slot(result='QVariant') def balance_inventory(self): - return "N/A" balance = shop.inventory_balance_str() db.commit() return balance @QtCore.Slot(result='QVariant') def balance_credit(self): - return "N/A" balance = shop.credit_negbalance_str() db.commit() return balance diff --git a/brmbar3/brmbar/Account.py b/brmbar3/brmbar/Account.py index 2499d05..3a25170 100644 --- a/brmbar3/brmbar/Account.py +++ b/brmbar3/brmbar/Account.py @@ -20,20 +20,24 @@ class Account: @classmethod def load_by_barcode(cls, db, barcode): logger.debug("load_by_barcode: '%s'", barcode) - account_id, account_name, account_acctype, currency_id, currency_name = db.execute_and_fetch( - "SELECT account_id, account_name, account_acctype, currency_id, currency_name FROM public.account_class_initialization_data('by_barcode', NULL, %s)", - [barcode]) - currency = Currency(db, currency_id, currency_name) - return cls(db, account_id, account_name, currency, account_acctype) + res = db.execute_and_fetch( + "SELECT account FROM barcodes WHERE barcode = %s", [barcode] + ) + if res is None: + return None + id = res[0] + return cls.load(db, id=id) @classmethod def load(cls, db, id=None): """Constructor for existing account""" - account_id, account_name, account_acctype, currency_id, currency_name = db.execute_and_fetch( - "SELECT account_id, account_name, account_acctype, currency_id, currency_name FROM public.account_class_initialization_data('by_id', %s, NULL)", - [id]) - currency = Currency(db, currency_id, currency_name) - return cls(db, account_id, account_name, currency, account_acctype) + if id is None: + raise NameError("Account.load(): Specify id") + name, currid, acctype = db.execute_and_fetch( + "SELECT name, currency, acctype FROM accounts WHERE id = %s", [id] + ) + currency = Currency.load(db, id=currid) + return cls(db, name=name, id=id, currency=currency, acctype=acctype) @classmethod def create(cls, db, name, currency, acctype): diff --git a/brmbar3/brmbar/Currency.py b/brmbar3/brmbar/Currency.py index fba3059..3033287 100644 --- a/brmbar3/brmbar/Currency.py +++ b/brmbar3/brmbar/Currency.py @@ -67,6 +67,57 @@ class Currency: return (buy, sell) + def rates2(self, other): + # the original code for compare testing + res = self.db.execute_and_fetch( + "SELECT rate, rate_dir FROM exchange_rates WHERE target = %s AND source = %s AND valid_since <= NOW() ORDER BY valid_since DESC LIMIT 1", + [self.id, other.id], + ) + if res is None: + raise NameError( + "Currency.rate(): Unknown conversion " + + other.name() + + " to " + + self.name() + ) + buy_rate, buy_rate_dir = res + buy = buy_rate if buy_rate_dir == "target_to_source" else 1 / buy_rate + + res = self.db.execute_and_fetch( + "SELECT rate, rate_dir FROM exchange_rates WHERE target = %s AND source = %s AND valid_since <= NOW() ORDER BY valid_since DESC LIMIT 1", + [other.id, self.id], + ) + if res is None: + raise NameError( + "Currency.rate(): Unknown conversion " + + self.name() + + " to " + + other.name() + ) + sell_rate, sell_rate_dir = res + sell = sell_rate if sell_rate_dir == "source_to_target" else 1 / sell_rate + + return (buy, sell) + + def convert(self, amount, target): + res = self.db.execute_and_fetch( + "SELECT rate, rate_dir FROM exchange_rates WHERE target = %s AND source = %s AND valid_since <= NOW() ORDER BY valid_since DESC LIMIT 1", + [target.id, self.id], + ) + if res is None: + raise NameError( + "Currency.convert(): Unknown conversion " + + self.name() + + " to " + + target.name() + ) + rate, rate_dir = res + if rate_dir == "source_to_target": + resamount = amount * rate + else: + resamount = amount / rate + return resamount + def str(self, amount): return "{:.2f} {}".format(amount, self.name) @@ -79,5 +130,5 @@ class Currency: def update_buy_rate(self, source, rate): self.db.execute( "SELECT public.update_currency_buy_rate(%s, %s, %s)", - [self.id, source.id, rate], + [source.id, self.id, rate], ) diff --git a/brmbar3/brmbar/Database.py b/brmbar3/brmbar/Database.py index 5b844dd..b70687c 100644 --- a/brmbar3/brmbar/Database.py +++ b/brmbar3/brmbar/Database.py @@ -35,7 +35,6 @@ class Database: def _execute(self, cur, query, attrs, level=1): """execute a query, and in case of OperationalError (db restart) reconnect to database. Recurses with increasig pause between tries""" - logger.debug("SQL: (%s) @%s" % (query, time.strftime("%Y%m%d %a %I:%m %p"))) try: if attrs is None: cur.execute(query) diff --git a/brmbar3/brmbar/Shop.py b/brmbar3/brmbar/Shop.py index a2ef1d1..b32f5bb 100644 --- a/brmbar3/brmbar/Shop.py +++ b/brmbar3/brmbar/Shop.py @@ -198,13 +198,12 @@ class Shop: """list all accounts (people or items, as per acctype)""" accts = [] cur = self.db.execute_and_fetchall( - "SELECT a.id, a.name aname, a.currency, a.acctype, c.name cname FROM accounts a JOIN currencies c ON c.id=a.currency WHERE a.acctype = %s AND a.name ILIKE %s ORDER BY a.name ASC", + "SELECT id FROM accounts WHERE acctype = %s AND name ILIKE %s ORDER BY name ASC", [acctype, like_str], ) # FIXME: sanitize input like_str ^ for inventory in cur: - curr = Currency(db=self.db, id=inventory[2], name=inventory[4]); - accts += [Account(self.db, id=inventory[0], name=inventory[1], currency=curr, acctype=inventory[3])] + accts += [Account.load(self.db, id=inventory[0])] return accts def fix_inventory(self, item, amount): diff --git a/brmbar3/schema/0024-find-rates-fix.sql b/brmbar3/schema/0024-find-rates-fix.sql deleted file mode 100644 index 70bab06..0000000 --- a/brmbar3/schema/0024-find-rates-fix.sql +++ /dev/null @@ -1,92 +0,0 @@ --- --- 0024-find-rates-fix.sql --- --- #24 - fix stored functions find_buy_rate and find_sell_rate --- --- 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(23) THEN - -DROP FUNCTION IF EXISTS public.find_buy_rate(integer,integer); -DROP FUNCTION IF EXISTS public.find_sell_rate(integer,integer); - -CREATE OR REPLACE FUNCTION public.find_buy_rate( - IN i_item_currency_id public.accounts.id%TYPE, - IN i_other_currency_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, rate_dir INTO STRICT v_rate, v_rate_dir FROM public.exchange_rates WHERE target = i_item_currency_id AND source = i_other_currency_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; - /* propagate error -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_currency_id public.accounts.id%TYPE, - IN i_other_currency_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, rate_dir INTO STRICT v_rate, v_rate_dir FROM public.exchange_rates WHERE target = i_other_currency_id AND source = i_item_currency_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; - /* propagate error -EXCEPTION - WHEN NO_DATA_FOUND THEN - RETURN -1; - */ -END; -$$; - -PERFORM brmbar_privileged.upgrade_schema_version_to(24); -END IF; - -END; -$upgrade_block$; - --- vim: set ft=plsql : diff --git a/brmbar3/schema/0025-load-account.sql b/brmbar3/schema/0025-load-account.sql deleted file mode 100644 index 3076e0b..0000000 --- a/brmbar3/schema/0025-load-account.sql +++ /dev/null @@ -1,111 +0,0 @@ --- --- 0025-load-account.sql --- --- #25 - stored procedures for account loading --- --- 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$ -DECLARE - v INTEGER; -BEGIN - -IF brmbar_privileged.has_exact_schema_version(24) THEN - -SELECT COUNT(1) INTO v - FROM pg_catalog.pg_type typ - INNER JOIN pg_catalog.pg_namespace nsp - ON nsp.oid = typ.typnamespace - WHERE nsp.nspname = 'brmbar_privileged' - AND typ.typname='account_class_initialization_data_type'; - -IF v>0 THEN - RAISE NOTICE 'Changing type account_class_initialization_data_type'; - DROP TYPE brmbar_privileged.account_class_initialization_data_type CASCADE; -ELSE - RAISE NOTICE 'Creating type account_class_initialization_data_type'; -END IF; - -SELECT COUNT(1) INTO v - FROM pg_catalog.pg_type typ - INNER JOIN pg_catalog.pg_namespace nsp - ON nsp.oid = typ.typnamespace - WHERE nsp.nspname = 'brmbar_privileged' - AND typ.typname='account_load_type'; - -IF v>0 THEN - RAISE NOTICE 'Changing type account_load_type'; - DROP TYPE brmbar_privileged.account_load_type CASCADE; -ELSE - RAISE NOTICE 'Creating type account_load_type'; -END IF; - -CREATE TYPE brmbar_privileged.account_load_type - AS ENUM ('by_id', 'by_barcode'); - -CREATE TYPE brmbar_privileged.account_class_initialization_data_type -AS ( - account_id INTEGER, --public.accounts.id%TYPE, - account_name TEXT, --public.accounts.id%TYPE, - account_acctype public.account_type, - currency_id INTEGER, --public.currencies.id%TYPE, - currency_name TEXT -); - -CREATE OR REPLACE FUNCTION public.account_class_initialization_data( - load_by brmbar_privileged.account_load_type, - i_id INTEGER, - i_barcode TEXT) -RETURNS brmbar_privileged.account_class_initialization_data_type -LANGUAGE plpgsql -AS -$$ -DECLARE - rv brmbar_privileged.account_class_initialization_data_type; -BEGIN - IF load_by = 'by_id' THEN - SELECT a.id, a.name, a.acctype, c.id, c.name - INTO STRICT rv.account_id, rv.account_name, rv.account_acctype, rv.currency_id, rv.currency_name - FROM public.accounts a JOIN public.currencies c ON a.currency = c.id - WHERE a.id = i_id; - ELSE -- by_barcode - SELECT a.id, a.name, a.acctype, c.id, c.name - INTO STRICT rv.account_id, rv.account_name, rv.account_acctype, rv.currency_id, rv.currency_name - FROM public.accounts a JOIN public.currencies c ON a.currency = c.id JOIN public.barcodes b ON b.account = a.id - WHERE b.barcode = i_barcode; - END IF; - -- - RETURN rv; -END; -$$; - - - -PERFORM brmbar_privileged.upgrade_schema_version_to(25); -END IF; - -END; -$upgrade_block$; - --- vim: set ft=plsql :