mirror of
https://github.com/brmlab/brmbar.git
synced 2025-06-08 13:24:01 +02:00
Merge code from deployed production version
This commit is contained in:
commit
5f9292fd02
15 changed files with 169 additions and 14 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1 +1,2 @@
|
||||||
.*.sw?
|
.*.sw?
|
||||||
|
*~
|
||||||
|
|
2
brmbar3/.gitignore
vendored
2
brmbar3/.gitignore
vendored
|
@ -1 +1,3 @@
|
||||||
__pycache__
|
__pycache__
|
||||||
|
*.log
|
||||||
|
brmbar/*.pyc
|
||||||
|
|
64
brmbar3/PURGE.txt
Normal file
64
brmbar3/PURGE.txt
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
How to "reset" the database - drop all history and keep only accounts with non-zero balance.
|
||||||
|
|
||||||
|
Legend:
|
||||||
|
> - SQL commands
|
||||||
|
$ - shell commands
|
||||||
|
|
||||||
|
Run the (full) inventory.
|
||||||
|
|
||||||
|
Get number of the first inventory TX.
|
||||||
|
|
||||||
|
> select id from account_balances where id in (select id from accounts where currency not in (select distinct currency from
|
||||||
|
transaction_nicesplits where transaction >= NUMBER_HERE and currency != 1 and memo like '%Inventory fix%') and acctype = 'inventory') and crbalance != 0 \g 'vynulovat'
|
||||||
|
$ ./brmbar-cli.py inventory `cat vynulovat | while read x; do echo $x 0; done`
|
||||||
|
|
||||||
|
Backup the database
|
||||||
|
$ pg_dump brmbar > backup.sql
|
||||||
|
|
||||||
|
Dump "> SELECT * FROM account_balances;" to file N.
|
||||||
|
|
||||||
|
Dump inventory to file nastavit FIXME.
|
||||||
|
|
||||||
|
Drop all transactions:
|
||||||
|
> delete from transaction_splits;
|
||||||
|
> delete from transactions;
|
||||||
|
|
||||||
|
Restore inventory:
|
||||||
|
$ cat nastavit | while read acc p amt; do ./brmbar-cli.py inventory $acc `echo $amt | grep -oE "^[0-9-]+"`; done
|
||||||
|
|
||||||
|
Restore cash balance:
|
||||||
|
$ cat N | grep debt | tr -s " " |cut -d \| -f 2,4 | while read acc p amt; do ./brmbar-cli.py changecredit $acc `echo $amt | grep -oE "^[0-9-]+"`; done
|
||||||
|
|
||||||
|
Delete zero-balance accounts:
|
||||||
|
> delete from accounts where accounts.id not in (select id from account_balances);
|
||||||
|
|
||||||
|
Delete orphaned barcodes:
|
||||||
|
> delete from barcodes where barcodes.account not in (select id from account_balances);
|
||||||
|
|
||||||
|
Delete orphaned currencies and exchange rates:
|
||||||
|
> CREATE OR REPLACE VIEW "a_tmp" AS
|
||||||
|
SELECT ts.account AS id, accounts.name, accounts.acctype, accounts.currency AS fff, (- sum(CASE WHEN (ts.side = 'credit'::transaction_split_side) THEN (- ts.amount) ELSE ts.amount END)) AS crbalance FROM (transaction_splits ts LEFT JOIN accounts ON ((accounts.id = ts.account))) GROUP BY ts.account, accounts.name, accounts.id, accounts.acctype ORDER BY (- sum(CASE WHEN (ts.side = 'credit'::transaction_split_side) THEN (- ts.amount) ELSE ts.amount END));
|
||||||
|
|
||||||
|
> delete from exchange_rates where source not in (select fff from a_tmp);
|
||||||
|
> delete from currencies where id not in (select fff from a_tmp);
|
||||||
|
|
||||||
|
> DROP VIEW "a_tmp";
|
||||||
|
|
||||||
|
Drop obsolete exchange rates:
|
||||||
|
|
||||||
|
> delete from exchange_rates where
|
||||||
|
valid_since <> (SELECT max(valid_since)
|
||||||
|
FROM exchange_rates e
|
||||||
|
WHERE e.target = exchange_rates.target and e.source = exchange_rates.source)
|
||||||
|
|
||||||
|
Restore system accounts:
|
||||||
|
> INSERT INTO "accounts" ("name", "currency", "acctype", "active")
|
||||||
|
VALUES ('BrmBar Profits', '1', 'income', '1');
|
||||||
|
> INSERT INTO "accounts" ("name", "currency", "acctype", "active")
|
||||||
|
VALUES ('BrmBar Excess', '1', 'income', '1');
|
||||||
|
> INSERT INTO "accounts" ("name", "currency", "acctype", "active")
|
||||||
|
VALUES ('BrmBar Deficit', '1', 'expense', '1');
|
||||||
|
> INSERT INTO "accounts" ("name", "currency", "acctype", "active")
|
||||||
|
VALUES ('BrmBar Cash', '1', 'cash', '1');
|
||||||
|
|
||||||
|
Restart brmbar.
|
|
@ -107,10 +107,9 @@ CREATE VIEW transaction_nicesplits AS
|
||||||
FROM transaction_splits AS ts LEFT JOIN accounts AS a ON a.id = ts.account
|
FROM transaction_splits AS ts LEFT JOIN accounts AS a ON a.id = ts.account
|
||||||
ORDER BY ts.id;
|
ORDER BY ts.id;
|
||||||
|
|
||||||
-- List transactions with summary information regarding their cash element
|
-- List transactions with summary information regarding their cash element.
|
||||||
-- (except in case of transfers between cash and debt accounts, which will cancel out).
|
|
||||||
CREATE VIEW transaction_cashsums AS
|
CREATE VIEW transaction_cashsums AS
|
||||||
SELECT t.id AS id, t.time AS time, SUM(credit_cash) AS cash_credit, SUM(debit_cash) AS cash_debit, t.description AS description
|
SELECT t.id AS id, t.time AS time, SUM(credit_cash) AS cash_credit, SUM(debit_cash) AS cash_debit, a.name AS responsible, t.description AS description
|
||||||
FROM transactions AS t
|
FROM transactions AS t
|
||||||
LEFT JOIN (SELECT cts.amount AS credit_cash, cts.transaction AS cts_t
|
LEFT JOIN (SELECT cts.amount AS credit_cash, cts.transaction AS cts_t
|
||||||
FROM transaction_nicesplits AS cts
|
FROM transaction_nicesplits AS cts
|
||||||
|
@ -124,4 +123,5 @@ CREATE VIEW transaction_cashsums AS
|
||||||
WHERE a.currency = (SELECT currency FROM accounts WHERE name = 'BrmBar Cash')
|
WHERE a.currency = (SELECT currency FROM accounts WHERE name = 'BrmBar Cash')
|
||||||
AND a.acctype IN ('cash', 'debt')
|
AND a.acctype IN ('cash', 'debt')
|
||||||
AND dts.amount > 0) debit ON dts_t = t.id
|
AND dts.amount > 0) debit ON dts_t = t.id
|
||||||
GROUP BY t.id ORDER BY t.id;
|
LEFT JOIN accounts AS a ON a.id = t.responsible
|
||||||
|
GROUP BY t.id, a.name ORDER BY t.id DESC;
|
||||||
|
|
8
brmbar3/USEFUL.txt
Normal file
8
brmbar3/USEFUL.txt
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
Accounts with multiple barcodes:
|
||||||
|
|
||||||
|
SELECT accounts.name,barcodes.account,barcodes.barcode
|
||||||
|
FROM "barcodes"
|
||||||
|
join accounts on accounts.id = barcodes.account
|
||||||
|
where barcodes.account in (select a from (select count(*) as c, account as a from barcodes group by account) as dt where c > 1)
|
||||||
|
ORDER BY "account" DESC
|
||||||
|
|
42
brmbar3/autostock.py
Executable file
42
brmbar3/autostock.py
Executable file
|
@ -0,0 +1,42 @@
|
||||||
|
#! /usr/bin/env python3
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import brmbar
|
||||||
|
import math
|
||||||
|
from brmbar import Database
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(usage = "File format: EAN amount total_price name, e.g. 4001242002377 6 167.40 Chio Tortillas")
|
||||||
|
parser.add_argument("filename")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
db = Database.Database("dbname=brmbar")
|
||||||
|
shop = brmbar.Shop.new_with_defaults(db)
|
||||||
|
currency = shop.currency
|
||||||
|
|
||||||
|
# ...
|
||||||
|
total = 0
|
||||||
|
with open(args.filename) as fin:
|
||||||
|
for line in fin:
|
||||||
|
split = line.split(" ")
|
||||||
|
ean, amount, price_total, name = split[0], int(split[1]), float(split[2]), " ".join(split[3:])
|
||||||
|
name = name.strip()
|
||||||
|
|
||||||
|
price_buy = price_total / amount
|
||||||
|
acct = brmbar.Account.load_by_barcode(db, ean)
|
||||||
|
if not acct:
|
||||||
|
print("Creating account for EAN {} '{}'".format(ean, name))
|
||||||
|
invcurr = brmbar.Currency.create(db, name)
|
||||||
|
acct = brmbar.Account.create(db, name, invcurr, "inventory")
|
||||||
|
acct.add_barcode(ean)
|
||||||
|
price_sell = max(math.ceil(price_buy * 1.15), price_buy)
|
||||||
|
acct.currency.update_sell_rate(currency, price_sell)
|
||||||
|
acct.currency.update_buy_rate(currency, price_buy)
|
||||||
|
cash = shop.buy_for_cash(acct, amount)
|
||||||
|
total += cash
|
||||||
|
print("Increased by {}, take {} from cashbox".format(amount, cash))
|
||||||
|
print("Total is {}".format(total))
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
|
@ -97,6 +97,12 @@ def load_item(inp):
|
||||||
exit(1)
|
exit(1)
|
||||||
return acct
|
return acct
|
||||||
|
|
||||||
|
def load_item_by_barcode(inp):
|
||||||
|
acct = brmbar.Account.load_by_barcode(db, inp)
|
||||||
|
if acct.acctype != "inventory":
|
||||||
|
print("Bad EAN " + inp + " type " + acct.acctype, file=sys.stderr)
|
||||||
|
exit(1)
|
||||||
|
return acct
|
||||||
|
|
||||||
db = Database.Database("dbname=brmbar")
|
db = Database.Database("dbname=brmbar")
|
||||||
shop = brmbar.Shop.new_with_defaults(db)
|
shop = brmbar.Shop.new_with_defaults(db)
|
||||||
|
@ -147,9 +153,9 @@ elif sys.argv[1] == "userlog":
|
||||||
acct = load_user(sys.argv[2])
|
acct = load_user(sys.argv[2])
|
||||||
timestamp = sys.argv[3]
|
timestamp = sys.argv[3]
|
||||||
|
|
||||||
res = db.execute_and_fetchall("SELECT transactions.time,transactions.description FROM transactions INNER JOIN accounts ON accounts.id=transactions.responsible WHERE accounts.name=%s and time > TIMESTAMP %s ORDER BY time", [acct.name,timestamp])
|
res = db.execute_and_fetchall("SELECT * FROM transaction_cashsums WHERE responsible=%s and time > TIMESTAMP %s ORDER BY time", [acct.name,timestamp])
|
||||||
for transaction in res:
|
for transaction in res:
|
||||||
print("{}\t{}\t".format(transaction[0],transaction[1]))
|
print('\t'.join([str(f) for f in transaction]))
|
||||||
|
|
||||||
elif sys.argv[1] == "iteminfo":
|
elif sys.argv[1] == "iteminfo":
|
||||||
acct = load_item(sys.argv[2])
|
acct = load_item(sys.argv[2])
|
||||||
|
@ -245,11 +251,11 @@ elif sys.argv[1] == "consolidate":
|
||||||
else:
|
else:
|
||||||
shop.consolidate()
|
shop.consolidate()
|
||||||
|
|
||||||
elif sys.argv[1] == "restock":
|
elif sys.argv[1] in {"restock", "restock_ean"}:
|
||||||
if (len(sys.argv) != 4):
|
if (len(sys.argv) != 4):
|
||||||
print ("Invalid number of parameters, check your parameters.")
|
print ("Invalid number of parameters, check your parameters.")
|
||||||
else:
|
else:
|
||||||
iacct = load_item(sys.argv[2])
|
iacct = (load_item if sys.argv[1] == "restock" else load_item_by_barcode)(sys.argv[2])
|
||||||
oldbal = iacct.balance()
|
oldbal = iacct.balance()
|
||||||
amt = int(sys.argv[3])
|
amt = int(sys.argv[3])
|
||||||
cash = shop.buy_for_cash(iacct, amt);
|
cash = shop.buy_for_cash(iacct, amt);
|
||||||
|
|
|
@ -39,6 +39,14 @@ class ShopAdapter(QtCore.QObject):
|
||||||
map["price"] = str(sell)
|
map["price"] = str(sell)
|
||||||
return map
|
return map
|
||||||
|
|
||||||
|
def acct_inventory_map2(self, acct):
|
||||||
|
buy, sell = 666, 666
|
||||||
|
map = acct.__dict__.copy()
|
||||||
|
map["balance"] = "{:.0f}".format(666)
|
||||||
|
map["buy_price"] = str(buy)
|
||||||
|
map["price"] = str(sell)
|
||||||
|
return map
|
||||||
|
|
||||||
def acct_cash_map(self, acct):
|
def acct_cash_map(self, acct):
|
||||||
map = acct.__dict__.copy()
|
map = acct.__dict__.copy()
|
||||||
return map
|
return map
|
||||||
|
@ -164,7 +172,7 @@ class ShopAdapter(QtCore.QObject):
|
||||||
|
|
||||||
@QtCore.Slot('QVariant', result='QVariant')
|
@QtCore.Slot('QVariant', result='QVariant')
|
||||||
def itemList(self, query):
|
def itemList(self, query):
|
||||||
alist = [ self.acct_inventory_map(a) for a in shop.account_list("inventory", like_str="%%"+query+"%%") ]
|
alist = [ self.acct_inventory_map2(a) for a in shop.account_list("inventory", like_str="%%"+query+"%%") ]
|
||||||
db.commit()
|
db.commit()
|
||||||
return alist
|
return alist
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,6 @@ Item {
|
||||||
x: 65
|
x: 65
|
||||||
y: 438
|
y: 438
|
||||||
width: 1150
|
width: 1150
|
||||||
text: "* Mroze a Termixy najdes v lednici *"
|
text: "* Za uklid brmlabu vam nabijeme kredit. *"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
15
brmbar3/crontab
Normal file
15
brmbar3/crontab
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
# 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
|
||||||
|
|
3
brmbar3/dluhy.sh
Executable file
3
brmbar3/dluhy.sh
Executable file
|
@ -0,0 +1,3 @@
|
||||||
|
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
|
6
brmbar3/log.sh
Executable file
6
brmbar3/log.sh
Executable file
|
@ -0,0 +1,6 @@
|
||||||
|
#!/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
|
|
@ -13,6 +13,6 @@ if [ ! -z "$RES" ]; then
|
||||||
if [ -z "$WINNER" ]; then
|
if [ -z "$WINNER" ]; then
|
||||||
WINNER="anonymous hunter"
|
WINNER="anonymous hunter"
|
||||||
fi
|
fi
|
||||||
echo "Brmlab cleanup bounty was claimed by $WINNER! Thanks!"|ssh jenda@fry.hrach.eu
|
echo "Brmlab cleanup bounty was claimed by $WINNER! Thanks!"|ssh -p 110 jenda@coralmyn.hrach.eu
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue