def main(args): if args.verbose: lvl = logging.DEBUG elif args.quiet: lvl = logging.WARN else: lvl = logging.INFO logging.basicConfig(level=lvl) all_items = [] for fn in args.file: logging.debug('Reading %s..', fn) with open(fn) as fd: items = qif.parse_qif(fd) logging.debug('Read %s items from %s..', len(items), fn) all_items.extend(items) logging.debug('Opening GnuCash file %s..', args.gnucash_file) session = Session(args.gnucash_file) book = session.book commod_tab = book.get_table() currency = commod_tab.lookup('ISO4217', args.currency) for item in all_items: add_transaction(book, item, currency) logging.debug('Saving GnuCash file..') session.save() session.end()
def test_session_with_new_file(self): """create Session with new xml file""" from tempfile import TemporaryDirectory from urllib.parse import urlunparse with TemporaryDirectory() as tempdir: uri = urlunparse(("xml", tempdir, "tempfile", "", "", "")) with Session(uri, SessionOpenMode.SESSION_NEW_STORE) as ses: pass # try to open nonexistent file without NEW mode - should raise Exception uri = urlunparse(("xml", tempdir, "tempfile2", "", "", "")) with Session() as ses: with self.assertRaises(GnuCashBackendException): ses.begin(uri, mode=SessionOpenMode.SESSION_NORMAL_OPEN) # try to open nonexistent file without NEW mode - should raise Exception # use deprecated arg is_new uri = urlunparse(("xml", tempdir, "tempfile2", "", "", "")) with Session() as ses: with self.assertRaises(GnuCashBackendException): ses.begin(uri, is_new=False) uri = urlunparse(("xml", tempdir, "tempfile3", "", "", "")) with Session() as ses: ses.begin(uri, mode=SessionOpenMode.SESSION_NEW_STORE) # test using deprecated args uri = urlunparse(("xml", tempdir, "tempfile4", "", "", "")) with Session() as ses: ses.begin(uri, is_new=True)
def test_get_book_from_current_session(self): from gnucash import _sw_app_utils from gnucash import Book self.ses_instance = _sw_app_utils.gnc_get_current_session() self.ses = Session(instance=self.ses_instance) self.book = self.ses.get_book() self.assertIsInstance(obj=self.book, cls=Book)
def write_transactions_to_gnucash(gnucash_file, currency, all_items, dry_run=False, date_from=None): logging.debug("Opening GnuCash file %s..", gnucash_file) session = Session(gnucash_file) book = session.book commod_tab = book.get_table() currency = commod_tab.lookup("ISO4217", currency) if date_from: date_from = datetime.datetime.strptime(date_from, "%Y-%m-%d") imported_items = set() for item in all_items: if date_from and item.date < date_from: logging.info("Skipping entry %s (%s)", item.date.strftime("%Y-%m-%d"), item.split_amount) continue if item.as_tuple() in imported_items: logging.info( "Skipping entry %s (%s) --- already imported!", item.date.strftime("%Y-%m-%d"), item.split_amount ) continue add_transaction(book, item, currency) imported_items.add(item.as_tuple()) if dry_run: logging.debug("** DRY-RUN **") else: logging.debug("Saving GnuCash file..") session.save() session.end()
class CommoditySession(TestCase): def setUp(self): self.ses = Session() self.book = self.ses.get_book() self.table = self.book.get_table() def tearDown(self): self.ses.end()
def main(): args = parse_cmdline() if args.version: print VERSION exit(0) if args.verbose: loglevel = logging.DEBUG elif args.quiet: loglevel = logging.WARN else: loglevel = logging.INFO logging.basicConfig(level=loglevel) rules = readrules(args.rulesfile) account_path = re.split(':', args.ac2fix) gnucash_session = Session(args.gnucash_file, is_new=False) total = 0 imbalance = 0 fixed = 0 try: root_account = gnucash_session.book.get_root_account() orig_account = account_from_path(root_account, account_path) imbalance_pattern = re.compile(args.imbalance_ac) for split in orig_account.GetSplitList(): total += 1 trans = split.parent splits = trans.GetSplitList() trans_date = date.fromtimestamp(trans.GetDate()) trans_desc = trans.GetDescription() trans_memo = trans.GetNotes() for split in splits: ac = split.GetAccount() acname = ac.GetName() logging.debug('%s: %s => %s', trans_date, trans_desc, acname) if imbalance_pattern.match(acname): imbalance += 1 search_str = trans_desc if args.use_memo: search_str = trans_memo newac = get_ac_from_str(search_str, rules, root_account) if newac != "": logging.debug('\tChanging account to: %s', newac.GetName()) split.SetAccount(newac) fixed += 1 if not args.nochange: gnucash_session.save() logging.info('Total splits=%s, imbalance=%s, fixed=%s', total, imbalance, fixed) except Exception as ex: logging.error(ex) gnucash_session.end()
class TestCommands(TestCase): def setUp(self): self.session = Session( os.path.join(os.path.dirname(os.path.abspath(__file__)), "test.gnucash")) def tearDown(self): self.session.end() def test_create_split_transaction_vat(self): commands.create_split_transaction( self.session.book, settings.GNUCASH_BANK_ACCOUNT, "Internet", date.today(), "ADSL", Decimal("539.00"), ) def test_create_split_transaction_novat(self): commands.create_split_transaction( self.session.book, settings.GNUCASH_BANK_ACCOUNT, "Internet", date.today(), "ADSL", Decimal("539.00"), False, ) def test_pay_invoice(self): commands.pay_invoice(self.session.book, "000002", Decimal("99.99"), date.today()) def test_pay_invoice_exists(self): self.assertRaises( PaymentExists, commands.pay_invoice, self.session.book, "000001", Decimal("9.99"), date.today(), ) def test_apply_payment(self): commands.apply_payment(self.session.book, "000001", Decimal("99.99"), date.today()) def test_apply_payment_exists(self): self.assertRaises( PaymentExists, commands.apply_payment, self.session.book, "000001", Decimal("9.99"), date(2019, 11, 21), )
def __init__(self, file, currency, is_new=False): self.session = Session(file, is_new) try: self.book = self.session.book self.commod_tab = self.book.get_table() self.currency = self.commod_tab.lookup('ISO4217', currency) self.root = self.book.get_root_account() except Exception as ex: pass
def customer_choices(book=None): choices = [("", "---------")] if not book: session = Session(settings.GNUCASH_FILE) book = session.book for c in queries.get_customers(book): choices.append((c.GetID(), c.GetName())) if "session" in locals(): session.end() return choices
def account_choices(book=None): choices = [("", "---------")] if not book: session = Session(settings.GNUCASH_FILE) book = session.book for ac in queries.get_accounts(book.get_root_account()): choices.append((ac.name, ac.name)) if "session" in locals(): session.end() return choices
def __init__(self, book_uri): self._session = Session(book_uri=book_uri) self._book = self._session.book self._root_account = self._book.get_root_account() self._commodity_table = self._book.get_table() # todo: implement as class w/ getattr self.commods = {} self.commods['USD'] = self._commodity_table.lookup("ISO4217", "USD")
def setUp(self): self.util = Util() self.account = Nubank(self.util.DEFAULT_ACCOUNT_SRC_FILE) self.ledger = Ledger(self.account, self.util.DEFAULT_CURRENCY, False, self.util.DEFAULT_GNUCASH_FILE) session = Session(self.util.DEFAULT_GNUCASH_FILE) self.book = session.book self.currency = self.book.get_table().lookup( 'ISO4217', self.util.DEFAULT_CURRENCY) session.end()
class GnucashBook(object): """docstring for GnucashBook.""" def __init__(self, file, currency, is_new=False): self.session = Session(file, is_new) try: self.book = self.session.book self.commod_tab = self.book.get_table() self.currency = self.commod_tab.lookup('ISO4217', currency) self.root = self.book.get_root_account() except Exception as ex: pass # logging.error(ex) def lookup_account_by_path(self, root, path): acc = root.lookup_by_name(path[0]) if acc.get_instance() == None: raise Exception('Account path {} not found'.format(':'.join(path))) if len(path) > 1: return GnucashBook.lookup_account_by_path(self, acc, path[1:]) return acc def lookup_account(self, name): path = name.split(':') return GnucashBook.lookup_account_by_path(self, self.root, path) def write_transactions(self, transactions): for transaction in transactions: tx = Transaction(self.book) tx.BeginEdit() tx.SetCurrency(self.currency) tx.SetDateEnteredTS(datetime.datetime.now()) tx.SetDatePostedTS(transaction.datetime) tx.SetDescription(transaction.description) tx.SetNotes(transaction.note) for split in transaction.splits: sp = Split(self.book) sp.SetParent(tx) sp.SetAccount(GnucashBook.lookup_account(self, split.account)) sp.SetMemo(split.memo) amount = int( Decimal(split.amount) * self.currency.get_fraction()) sp.SetValue(GncNumeric(amount, self.currency.get_fraction())) sp.SetAmount(GncNumeric(amount, self.currency.get_fraction())) tx.CommitEdit() def close(self, nochange): if not nochange: self.session.save() self.session.end()
def _loadarchive(self): if self._cache is not None: return session = Session(self.url, True, False, False) root = session.book.get_root_account() book = session.book account = book.get_root_account() commod_table = book.get_table() pdb = book.get_price_db() df = full_price_list(commod_table, pdb) df['value'] = df['num'] * 1.0 / df['denom'] session.end() session.destroy() self._cache = dropdupe(df, ['date', 'namespace', 'commod'])
def __init__(self, fmon, gnc_file, mode): self.prod = (mode == PROD) self.mon_file = fmon self.session = Session(gnc_file) self.book = self.session.book self.root = self.book.get_root_account() self.root.get_instance() self.price_db = self.book.get_price_db() commod_tab = self.book.get_table() self.currency = commod_tab.lookup("ISO4217", "CAD")
def sessionForFile(input_file): try: return Session(os.path.abspath(input_file)) except GnuCashBackendException, backend_exception: if ERR_BACKEND_LOCKED in backend_exception.errors: eprint("Cannot open %s, file is locked." % input_file) raise
def create_transactions(args, conf, url, txs, dry_run): try: session = Session(url, ignore_lock=True) except GnuCashBackendException, backend_exception: print "Error: %s" % backend_exception exit(1)
def gnc_open(cls, path=None): if GncFile.status: return GncFile.status else: if path is not None: GncFile.path = path else: path = GncFile.path if not os.path.exists(path): print """GnuCash file (%s) does not exist. """ % path raise Exception('GnuCash file missing') if os.path.exists(path + '.LCK'): print """Lock file exists. Is GNUCash running?\n""" raise Exception('GnuCash locked') try: GncFile.s = Session(GncFile.path, is_new=False) except: raise Exception('Could not open GnuCash file') GncFile.book = GncFile.s.book GncFile.root = GncFile.book.get_root_account() GncFile.commod_table = GncFile.book.get_table() GncFile.USD = GncFile.commod_table.lookup('CURRENCY', 'USD') GncFile.status = True return GncFile.status
def __init__(self,filename): self.closed = False self.session = Session(filename) self.book = self.session.book commod_table = self.book.get_table() self.EUR = commod_table.lookup('CURRENCY', 'EUR') self.receivables = self._get_account(ACCOUNT_RECEIVABLE,ACCT_TYPE_RECEIVABLE); self.payables = self._get_account(ACCOUNT_PAYABLE,ACCT_TYPE_PAYABLE); self.btw_collected_high = self._get_account(ACCOUNT_BTW_COLLECTED_HIGH,ACCT_TYPE_LIABILITY); self.btw_reported_high = self._get_account(ACCOUNT_BTW_REPORTED_HIGH,ACCT_TYPE_LIABILITY); self.btw_collected_low = self._get_account(ACCOUNT_BTW_COLLECTED_LOW,ACCT_TYPE_LIABILITY); self.btw_reported_low = self._get_account(ACCOUNT_BTW_REPORTED_LOW,ACCT_TYPE_LIABILITY); self.btw_collected_import = self._get_account(ACCOUNT_BTW_COLLECTED_IMPORT,ACCT_TYPE_LIABILITY); self.btw_reported_import = self._get_account(ACCOUNT_BTW_REPORTED_IMPORT,ACCT_TYPE_LIABILITY); self.btw_paid_nl = self._get_account(ACCOUNT_BTW_PAID_NL,ACCT_TYPE_ASSET); self.btw_reported_nl = self._get_account(ACCOUNT_BTW_REPORTED_NL,ACCT_TYPE_ASSET); self.btw_paid_eu = self._get_account(ACCOUNT_BTW_PAID_EU,ACCT_TYPE_ASSET); self.btw_reported_eu = self._get_account(ACCOUNT_BTW_REPORTED_EU,ACCT_TYPE_ASSET); self.btw_reported_eu = self._get_account(ACCOUNT_BTW_REPORTED_EU,ACCT_TYPE_ASSET); self.tax_expense = self._get_account(ACCOUNT_TAX_EXPENSE,ACCT_TYPE_EXPENSE); self.taxtables = self.book.TaxTableGetTables()
def main(): args = parse_cmdline() if args.version: print VERSION exit(0) rules = readrules(args.rulesfile) account_path = re.split(':', args.ac2fix) gnucash_session = Session(args.gnucash_file, is_new=False) root_account = gnucash_session.book.get_root_account() orig_account = account_from_path(root_account, account_path) total = 0 imbalance = 0 fixed = 0 for split in orig_account.GetSplitList(): total += 1 trans = split.parent splits = trans.GetSplitList() trans_date = date.fromtimestamp(trans.GetDate()) trans_desc = trans.GetDescription() trans_memo = trans.GetNotes() ac = splits[0].GetAccount() acname = ac.GetName() if not args.silent: print trans_date,":", trans_desc, "=>", acname # check if acname is "Imbalance-USD" if acname == args.imbalance_ac: imbalance += 1 search_str = trans_desc if args.use_memo: search_str = trans_memo newac = get_ac_from_str(search_str, rules, root_account) if newac != "": if not args.silent: print "\t Changing account to: ", newac.GetName() splits[0].SetAccount(newac) fixed += 1 if not args.nochange: gnucash_session.save() gnucash_session.end() if not args.silent: print "Total splits=", total, " imbalance=", imbalance, " fixed=", fixed
class Accounting: def __init__(self,filename): self.closed = False self.session = Session(filename) self.book = self.session.book commod_table = self.book.get_table() self.EUR = commod_table.lookup('CURRENCY', 'EUR') self.receivables = self._get_account(ACCOUNT_RECEIVABLE,ACCT_TYPE_RECEIVABLE); self.payables = self._get_account(ACCOUNT_PAYABLE,ACCT_TYPE_PAYABLE); self.btw_collected_high = self._get_account(ACCOUNT_BTW_COLLECTED_HIGH,ACCT_TYPE_LIABILITY); self.btw_reported_high = self._get_account(ACCOUNT_BTW_REPORTED_HIGH,ACCT_TYPE_LIABILITY); self.btw_collected_low = self._get_account(ACCOUNT_BTW_COLLECTED_LOW,ACCT_TYPE_LIABILITY); self.btw_reported_low = self._get_account(ACCOUNT_BTW_REPORTED_LOW,ACCT_TYPE_LIABILITY); self.btw_collected_import = self._get_account(ACCOUNT_BTW_COLLECTED_IMPORT,ACCT_TYPE_LIABILITY); self.btw_reported_import = self._get_account(ACCOUNT_BTW_REPORTED_IMPORT,ACCT_TYPE_LIABILITY); self.btw_paid_nl = self._get_account(ACCOUNT_BTW_PAID_NL,ACCT_TYPE_ASSET); self.btw_reported_nl = self._get_account(ACCOUNT_BTW_REPORTED_NL,ACCT_TYPE_ASSET); self.btw_paid_eu = self._get_account(ACCOUNT_BTW_PAID_EU,ACCT_TYPE_ASSET); self.btw_reported_eu = self._get_account(ACCOUNT_BTW_REPORTED_EU,ACCT_TYPE_ASSET); self.btw_reported_eu = self._get_account(ACCOUNT_BTW_REPORTED_EU,ACCT_TYPE_ASSET); self.tax_expense = self._get_account(ACCOUNT_TAX_EXPENSE,ACCT_TYPE_EXPENSE); self.taxtables = self.book.TaxTableGetTables() def _get_account(self,name,acct_type): root = self.book.get_root_account() acct = root.lookup_by_full_name(name) if acct.GetType() != acct_type: raise Exception('Account '+name+' does not exist with type '+str(acct_type)) return acct def save(self): self.session.save() def close(self): if not self.closed: self.session.end() self.closed = True def __del__(self): self.close()
def main(): if len(argv) < 3: print "Usage: python make_securities.py <gnucash-file> <symbols-file>" exit(1) gnucash_file = argv[1] secs = read_symbols(argv[2]) sess = Session(gnucash_file) try: # Make sure all the commodities exist ct = sess.book.get_table() created_secs = 0 updated_secs = 0 total_secs = 0 for ns in ["CUSIP", "ISIN"]: total_secs += len(secs[ns]) for c in ct.get_commodities(ns): matched_sec = None for k in secs[ns]: sec = secs[ns][k] if sec["id"] == c.get_cusip(): matched_sec = sec break if matched_sec: matched_sec["c"] = c updated = False if c.get_fullname() != matched_sec["name"]: c.set_fullname(matched_sec["name"]) updated = True if c.get_mnemonic() != matched_sec["symbol"]: c.set_mnemonic(matched_sec["symbol"]) updated = True if updated: updated_secs += 1 print "DEBUG: Updating Commodity", sec["name"] del secs[ns][matched_sec["id"]] for k in secs[ns]: sec = secs[ns][k] c = GncCommodity(sess.book, sec["name"], ns, sec["symbol"], sec["id"], 10000) if c: ct.insert(c) created_secs += 1 print "DEBUG: Created Commodity", sec["name"], sec["id"] else: print "ERROR: Error creating Commodity", sec["name"] print "INFO:", total_secs, "commodities total,", created_secs, "created,", updated_secs, "updated." wait_for_backup_file(gnucash_file) sess.save() except BaseException as e: print "ERROR:", e finally: sess.end() sess.destroy()
class TestSession(TestCase): def test_create_empty_session(self): self.ses = Session() def test_session_deprecated_arguments(self): """use deprecated arguments ignore_lock, is_new, force_new""" self.ses = Session(ignore_lock=False, is_new=True, force_new=False) def test_session_mode(self): """use mode argument""" self.ses = Session(mode=SessionOpenMode.SESSION_NORMAL_OPEN) def test_session_with_new_file(self): """create Session with new xml file""" from tempfile import TemporaryDirectory from urllib.parse import urlunparse with TemporaryDirectory() as tempdir: uri = urlunparse(("xml", tempdir, "tempfile", "", "", "")) with Session(uri, SessionOpenMode.SESSION_NEW_STORE) as ses: pass # try to open nonexistent file without NEW mode - should raise Exception uri = urlunparse(("xml", tempdir, "tempfile2", "", "", "")) with Session() as ses: with self.assertRaises(GnuCashBackendException): ses.begin(uri, mode=SessionOpenMode.SESSION_NORMAL_OPEN) # try to open nonexistent file without NEW mode - should raise Exception # use deprecated arg is_new uri = urlunparse(("xml", tempdir, "tempfile2", "", "", "")) with Session() as ses: with self.assertRaises(GnuCashBackendException): ses.begin(uri, is_new=False) uri = urlunparse(("xml", tempdir, "tempfile3", "", "", "")) with Session() as ses: ses.begin(uri, mode=SessionOpenMode.SESSION_NEW_STORE) # test using deprecated args uri = urlunparse(("xml", tempdir, "tempfile4", "", "", "")) with Session() as ses: ses.begin(uri, is_new=True) def test_app_utils_get_current_session(self): from gnucash import _sw_app_utils self.ses_instance = _sw_app_utils.gnc_get_current_session() self.ses = Session(instance=self.ses_instance) self.assertIsInstance(obj=self.ses, cls=Session) def test_get_book_from_current_session(self): from gnucash import _sw_app_utils from gnucash import Book self.ses_instance = _sw_app_utils.gnc_get_current_session() self.ses = Session(instance=self.ses_instance) self.book = self.ses.get_book() self.assertIsInstance(obj=self.book, cls=Book)
def __init__(self, book_uri): self._session = Session(book_uri=book_uri) self._book = self._session.book self._root_account = self._book.get_root_account() self._commodity_table = self._book.get_table() # todo: implement as class w/ getattr self.commods = {} self.commods["USD"] = self._commodity_table.lookup("ISO4217", "USD")
def __init__(self): if os.path.exists(self._path + '.LCK'): raise AssertionError("""Lock file exists. Is GNUCash running?\n""") with warnings.catch_warnings(): warnings.simplefilter("ignore") self._session = Session(self._path, is_new = False) self._root = self.getBook().get_root_account() self._commod = self.getBook().get_table() self._currency = self._commod.lookup('CURRENCY', 'USD')
def runTest(self): self.instrument_main() try: from accregex import Account from accregex.AccountUtil import gnc_numeric_to_python_Decimal from gnucash import Session session = Session(AccregexTest.reg_doc_example, is_new=False, ignore_lock=False) parking_expense_account = Account.get_account(session.book.get_root_account(), parking_expense_account_full_name) actual_balance = gnc_numeric_to_python_Decimal(parking_expense_account.GetBalance()) expected_balance = Decimal(25) self.assertEqual(actual_balance, expected_balance) #TODO: check that the actual transaction in Assets:Current Assets:Checking Account was changed session.end() #put the gnucash file back the way we found it shutil.move(AccregexTest.reg_doc_example + ".bak", AccregexTest.reg_doc_example) except: #in case of error close the session and re-raise #equivalent to a "finally" block if "session" in locals(): session.end() raise
def write_transactions_to_gnucash(gnucash_file, currency, all_items, dry_run=False, date_from=None): logging.debug('Opening GnuCash file %s..', gnucash_file) session = Session(gnucash_file) book = session.book commod_tab = book.get_table() currency = commod_tab.lookup('ISO4217', currency) if date_from: date_from = datetime.datetime.strptime(date_from, '%Y-%m-%d') imported_items = set() for item in all_items: if date_from and item.date < date_from: logging.info('Skipping entry %s (%s)', item.date.strftime('%Y-%m-%d'), item.split_amount) continue if item.as_tuple() in imported_items: logging.info('Skipping entry %s (%s) --- already imported!', item.date.strftime('%Y-%m-%d'), item.split_amount) continue add_transaction(book, item, currency) imported_items.add(item.as_tuple()) if dry_run: logging.debug('** DRY-RUN **') else: logging.debug('Saving GnuCash file..') session.save() session.end()
def open_book(gnucashfile, account2fix): """Read a GNU Cash file :param gnucashfile: path to the GNU Cash file :param account2fix: list with the path of the account :returns: session object, root account and origin account :rtype: """ gnucash_session = Session(gnucashfile, is_new=False) root_account = gnucash_session.book.get_root_account() orig_account = account_from_path(root_account, account2fix) return (gnucash_session, root_account, orig_account)
def find_av_main(): exe = argv[0].split('/')[-1] if len(argv) < 6: print("NOT ENOUGH parameters!") print("usage: {} <book url> <year> <month> <day> <space-separated path to the account of interest>".format(exe)) print("PROGRAM EXIT!") return print("\nrunning {} at run-time: {}\n".format(exe, str(datetime.now()))) global gnucash_session try: (gnucash_file, str_year, str_month, str_day) = argv[1:5] print("find asset values in {} on {}-{}-{}".format(gnucash_file, str_year, str_month, str_day)) val_year, val_month, val_day = [int(blah) for blah in (str_year, str_month, str_day)] date_of_interest = date(val_year, val_month, val_day) account_path = argv[5:] print("account_path = {}\n".format(str(account_path))) gnucash_session = Session(gnucash_file, is_new=False) book = gnucash_session.book commod_tab = book.get_table() # noinspection PyPep8Naming CAD = commod_tab.lookup("ISO4217", "CAD") root_account = book.get_root_account() account_of_interest = account_from_path(root_account, account_path) acct_name = account_of_interest.GetName() total = get_asset_balance(account_of_interest, date_of_interest, CAD) # get the list of all descendant accounts descendants = account_of_interest.get_descendants() if len(descendants) > 0: # get the values for EACH sub-account too print("\nDescendants of {}:".format(acct_name)) for subAcct in descendants: total += get_asset_balance(subAcct, date_of_interest, CAD) print("total {} value = {}${}".format(acct_name, CAD.get_mnemonic(), total)) # no save needed, we're just reading... gnucash_session.end() except Exception as ae: print("Exception: {}".format(ae)) if "gnucash_session" in locals() and gnucash_session is not None: gnucash_session.end() print("\n >>> PROGRAM ENDED.")
class TestSession(TestCase): def test_create_empty_session(self): self.ses = Session() def test_app_utils_get_current_session(self): from gnucash import _sw_app_utils self.ses_instance = _sw_app_utils.gnc_get_current_session() self.ses = Session(instance=self.ses_instance) self.assertIsInstance(obj=self.ses, cls=Session) def test_get_book_from_current_session(self): from gnucash import _sw_app_utils from gnucash import Book self.ses_instance = _sw_app_utils.gnc_get_current_session() self.ses = Session(instance=self.ses_instance) self.book = self.ses.get_book() self.assertIsInstance(obj=self.book, cls=Book)
def handle(self, *args, **options): try: s = Session(settings.GNUCASH_FILE) book = s.book with open(args[0], "r") as f: reader = csv.DictReader(f) for row in reader: number = row["invoice"] amount = Decimal(row["amount"]) date = parser.parse(row["date"]) try: pay_invoice(book, number, amount, date) except PaymentExists as e: print("%s... skipping" % e) s.save() finally: s.end()
def open_gnucash(gnucash_file): from gnucash import Session from financespy import gnucash_backend from financespy.gnucash_backend import GnucashBackend path = Path(gnucash_file) metadata_file = re.sub("[.]gnucash$", ".json", path.name) metadata = read_metadata(str(path.parent / metadata_file)) session = Session(gnucash_file) gnucash_account = gnucash_backend.account_for( session, metadata.properties["account_backend"] ) if not metadata.categories: metadata.categories = gnucash_backend.categories_from( session, metadata.properties["account_categories"] ) backend = GnucashBackend(session=session, account=gnucash_account) return Account(backend, metadata)
def test_create_empty_session(self): self.ses = Session()
def test_session_deprecated_arguments(self): """use deprecated arguments ignore_lock, is_new, force_new""" self.ses = Session(ignore_lock=False, is_new=True, force_new=False)
def main(): if len(argv) < 4: print 'Usage: python ofxml_make_commodity_accounts.py <gnucash-file> <ofxml-file> <accountmap-file>' exit(1) gnucash_file=argv[1] doc=ElementTree(file=argv[2]) acctids=doc.findall('./INVSTMTMSGSRSV1/INVSTMTTRNRS/INVSTMTRS/INVACCTFROM/ACCTID') if len(acctids)!=1: print 'ERROR: No unique account number found in OFX: found', len(acctids) return acctid=acctids[0].text.strip() acctcur='any' m=re.search('^(.*)-([A-Z]{3})$',acctid) if m: acctid=m.group(1) acctcur=m.group(2) print "INFO: Account number:", acctid, "Currency:", acctcur fitids={} for itran in doc.findall('.//INVBUY')+doc.findall('.//INVSELL')+doc.findall('.//REINVEST'): fitid=itran.find('./INVTRAN/FITID') if not fitid is None: fitid=fitid.text.strip() if fitid in fitids: print "ERROR: Non-unique FITID found:", fitid exit(1) fitids[fitid]=itran # Fantastic, the FITID is not saved by GnuCash for income transactions... # Index by (date,amount,memo) instead incometrns={} for itran in doc.findall('.//INCOME'): fields={} for path in ('INVTRAN/DTTRADE', 'INVTRAN/MEMO', 'TOTAL'): el=itran.find('./'+path) if not el is None and len(el.text.strip())>0: fields[path]=el.text.strip() if len(fields)!=3: print "ERROR: Can't create identifier for INCOME transaction, ignoring." incometrns[(fields['INVTRAN/DTTRADE'][0:8],fields['INVTRAN/MEMO'],Fraction(fields['TOTAL']))]=itran sess=Session(gnucash_file) try: # Find GNC parent account root=sess.book.get_root_account() matched_accts=find_acct_by_number_and_currency(root,acctid,acctcur) if len(matched_accts)==0: from_iban=conv_iban(acctid) if from_iban: matched_accts=find_acct_by_number_and_currency(root,from_iban,acctcur) if len(matched_accts)!=1: print 'ERROR: No unique account this number/currency; found', len(matched_accts) return acct=matched_accts[0] print 'DEBUG: Found parent account:',acct.GetName() accountmap=read_accountmap(argv[3],acct.GetCode()+'-'+acct.GetCommodity().get_mnemonic()) # Find child Stock/Mutual accounts secaccts=[] # SwigPyObject is not Hashable :( for cacct in acct.get_descendants(): atype=cacct.GetType() if atype==gnucash_core.ACCT_TYPE_STOCK or atype==gnucash_core.ACCT_TYPE_MUTUAL: secaccts.append(cacct.get_instance()) # Find income accounts incaccts=[] # SwigPyObject is not Hashable :( for typ in accountmap: if typ[0:6]=="INCOME": inst=find_acct_by_path(root,accountmap[typ]).get_instance() if not (inst is None or inst in incaccts): incaccts.append(inst) if len(incaccts)==0 and len(incometrns)>0: print 'WARNING: no income accounts defined for account',acct.GetCode()+'-'+acct.GetCommodity().get_mnemonic() print 'WARNING: income transactions will not be fixed' # Go through all transactions for tran in _py_xaccSplitListGetUniqueTransactions(acct.GetSplitList()): # Consider fixing if transaction ... # ... has exactly 2 splits # ... has 1 split with a child Stock/Mutual account # ... has 1 split with an online ID splits=tran.GetSplitList() if len(splits)==2: cashsplit=None secsplit=None incsplit=None online_id=None for split in splits: if split.GetAccount().get_instance() in secaccts: secsplit=split if split.GetAccount().get_instance() in incaccts: incsplit=split if split.GetAccount().get_instance()==acct.get_instance(): cashsplit=split oid=_py_gnc_import_get_split_online_id(sess,split) if not oid is None: if online_id is None: online_id=oid else: online_id=False if not (cashsplit is None or secsplit is None or online_id is None or online_id is False): if not online_id in fitids: # This can happen if we encounter a transaction outside of this OFX period #print 'DEBUG: FITID',online_id,'not found in OFX file.' continue fix_buysell_transaction(tran,secsplit,cashsplit,fitids[online_id],root,accountmap) elif not (cashsplit is None or incsplit is None): date=tran.RetDatePostedTS().strftime('%Y%m%d') memo=re.sub(' +',' ',tran.GetDescription()) # GnuCash importer likes to insert spaces randomly amt=gnc_numeric_to_fraction(cashsplit.GetAmount()) if not (date,memo,amt) in incometrns: # This can happen if we encounter a transaction outside of this OFX period #print "DEBUG: No match for income transaction",date,memo,amt continue fix_income_transaction(tran,incsplit,cashsplit,incometrns[(date,memo,amt)],root,accountmap) wait_for_backup_file(gnucash_file) sess.save() except BaseException as e: print 'ERROR:',e finally: sess.end() sess.destroy()
def main(): original_book_session = Session(argv[1], False) new_book_session = Session(argv[2], True) new_book = new_book_session.get_book() new_book_root = new_book.get_root_account() commodtable = new_book.get_table() # we discovered that if we didn't have this save early on, there would # be trouble later new_book_session.save() opening_balance_per_currency = {} recursivly_build_account_tree( original_book_session.get_book().get_root_account(), new_book_root, new_book, commodtable, opening_balance_per_currency, ACCOUNT_TYPES_TO_OPEN ) (namespace, mnemonic) = PREFERED_CURRENCY_FOR_SIMPLE_OPENING_BALANCE if (namespace, mnemonic) in opening_balance_per_currency: opening_trans, opening_amount = opening_balance_per_currency[ (namespace, mnemonic)] simple_opening_name_used = create_opening_balance_transaction( commodtable, namespace, mnemonic, new_book_root, new_book, opening_trans, opening_amount, False ) del opening_balance_per_currency[ PREFERED_CURRENCY_FOR_SIMPLE_OPENING_BALANCE] else: simple_opening_name_used = False for (namespace, mnemonic), (opening_trans, opening_amount) in \ opening_balance_per_currency.iteritems() : simple_opening_name_used = create_opening_balance_transaction( commodtable, namespace, mnemonic, new_book_root, new_book, opening_trans, opening_amount, simple_opening_name_used ) new_book_session.save() new_book_session.end() original_book_session.end()
#!/usr/bin/env python ## @file # @brief Simple example for a book # @ingroup python_bindings_examples import sys from gnucash import Session # We need to tell GnuCash the data format to create the new file as (xml://) uri = "xml:///tmp/simple_book.gnucash" print "uri:", uri ses = Session(uri, is_new=True) book = ses.get_book() # Call some methods that produce output to show that Book works book.get_root_account().SetDescription("hello, book") print "Book is saved:", not book.not_saved() print "saving..." ses.save() print "Book is saved:", not book.not_saved() ses.end()
data.append(tmp) f.close() stock_date = [] stock_price = [] for i in range(1,len(data)): year = int(data[i].rsplit(',')[1].rsplit('/')[0]) month = int(data[i].rsplit(',')[1].rsplit('/')[1]) day = int(data[i].rsplit(',')[1].rsplit('/')[2]) stock_date.append(datetime.datetime(year,month,day)) stock_price.append(float(data[i].rsplit(',')[5])) # Initialize Gnucash session session = Session(url, True, False, False) root = session.book.get_root_account() book = session.book account = book.get_root_account() pdb = book.get_price_db() comm_table = book.get_table() ac = find_account(account,'Intel')[0] stock = ac.GetCommodity() # Add the prices pdb = book.get_price_db() if len(ac.GetSplitList())<1: print('Need at least one Split to get currency info ... ') raise SystemExit cur = ac.GetSplitList()[0].GetParent().GetCurrency()
def test_app_utils_get_current_session(self): from gnucash import _sw_app_utils self.ses_instance = _sw_app_utils.gnc_get_current_session() self.ses = Session(instance=self.ses_instance) self.assertIsInstance(obj=self.ses, cls=Session)
def setUp(self): self.ses = Session() self.book = self.ses.get_book() self.table = self.book.get_table() self.currency = self.table.lookup('CURRENCY', 'EUR')
def main(): if len(argv) < 10: print('not enough parameters') print('usage: account_analysis.py {book url} {start year} {start month, numeric} {period type: monthly, quarterly, or yearly} {number of periods to show, from start year and month} {whether to show debits: debits-show for true, all other values false} {whether to show credits: credits-show for true, all other values false} {space separated account path, as many nested levels as desired} ') print('examples:\n') print("The following example analyzes 12 months of 'Assets:Test Account' from /home/username/test.gnucash, starting in January of 2010, and shows both credits and debits") print("gnucash-env python account_analysis.py '/home/username/test.gnucash' 2010 1 monthly 12 debits-show credits-show Assets 'Test Account'\n") print("The following example analyzes 2 quarters of 'Liabilities:First Level:Second Level' from /home/username/test.gnucash, starting March 2011, and shows credits but not debits") print("gnucash-env python account_analysis.py '/home/username/test.gnucash' 2011 3 quarterly 2 debits-noshow credits-show Liabilities 'First Level' 'Second Level") return try: (gnucash_file, start_year, start_month, period_type, periods, debits_show, credits_show) = argv[1:8] start_year, start_month, periods = [int(blah) for blah in (start_year, start_month, periods) ] debits_show = debits_show == DEBITS_SHOW credits_show = credits_show == CREDITS_SHOW account_path = argv[8:] gnucash_session = Session(gnucash_file, is_new=False) root_account = gnucash_session.book.get_root_account() account_of_interest = account_from_path(root_account, account_path) # a list of all the periods of interest, for each period # keep the start date, end date, a list to store debits and credits, # and sums for tracking the sum of all debits and sum of all credits period_list = [ [start_date, end_date, [], # debits [], # credits ZERO, # debits sum ZERO, # credits sum ] for start_date, end_date in generate_period_boundaries( start_year, start_month, period_type, periods) ] # a copy of the above list with just the period start dates period_starts = [e[0] for e in period_list ] # insert and add all splits in the periods of interest for split in account_of_interest.GetSplitList(): trans = split.parent trans_date = date.fromtimestamp(trans.GetDate()) # use binary search to find the period that starts before or on # the transaction date period_index = bisect_right( period_starts, trans_date ) - 1 # ignore transactions with a date before the matching period start # (after subtracting 1 above start_index would be -1) # and after the last period_end if period_index >= 0 and \ trans_date <= period_list[len(period_list)-1][1]: # get the period bucket appropriate for the split in question period = period_list[period_index] # more specifically, we'd expect the transaction date # to be on or after the period start, and before or on the # period end, assuming the binary search (bisect_right) # assumptions from above are are right.. # # in other words, we assert our use of binary search # and the filtered results from the above if provide all the # protection we need assert( trans_date>= period[0] and trans_date <= period[1] ) split_amount = gnc_numeric_to_python_Decimal(split.GetAmount()) # if the amount is negative, this is a credit if split_amount < ZERO: debit_credit_offset = 1 # else a debit else: debit_credit_offset = 0 # store the debit or credit Split with its transaction, using the # above offset to get in the right bucket # # if we wanted to be really cool we'd keep the transactions period[2+debit_credit_offset].append( (trans, split) ) # add the debit or credit to the sum, using the above offset # to get in the right bucket period[4+debit_credit_offset] += split_amount csv_writer = csv.writer(stdout) csv_writer.writerow( ('period start', 'period end', 'debits', 'credits') ) def generate_detail_rows(values): return ( ('', '', '', '', trans.GetDescription(), gnc_numeric_to_python_Decimal(split.GetAmount())) for trans, split in values ) for start_date, end_date, debits, credits, debit_sum, credit_sum in \ period_list: csv_writer.writerow( (start_date, end_date, debit_sum, credit_sum) ) if debits_show and len(debits) > 0: csv_writer.writerow( ('DEBITS', '', '', '', 'description', 'value') ) csv_writer.writerows( generate_detail_rows(debits) ) csv_writer.writerow( () ) if credits_show and len(credits) > 0: csv_writer.writerow( ('CREDITS', '', '', '', 'description', 'value') ) csv_writer.writerows( generate_detail_rows(credits) ) csv_writer.writerow( () ) # no save needed, we're just reading.. gnucash_session.end() except: if "gnucash_session" in locals(): gnucash_session.end() raise
# choose the account code to select TARGET_ACCOUNT_CODE = '1234' def mark_account_with_code_as_tax_related(account, target_code): """Looks at account to see if it has the target_account_code, if so set the account tax related flag to True and return True. If not, recursively tries to do the same to all children accounts of account. Returns False when recursion fails to find it. """ if account.GetCode() == target_code: account.SetTaxRelated(True) return True else: for child in account.get_children(): child = Account(instance=child) if mark_account_with_code_as_tax_related(child, target_code): return True return False # Change this path to your own gnucash_session = Session("xml:///home/mark/python-bindings-help/test.xac") mark_account_with_code_as_tax_related( gnucash_session.book.get_root_account(), TARGET_ACCOUNT_CODE) gnucash_session.save() gnucash_session.end()
def main(): (gnucash_file, start_year, start_month, period_type, periods, debits_show, credits_show) = argv[1:8] start_year, start_month, periods = [int(blah) for blah in (start_year, start_month, periods) ] debits_show = debits_show == DEBITS_SHOW credits_show = credits_show == CREDITS_SHOW account_path = argv[8:] gnucash_session = Session("sqlite3://%s" % gnucash_file, is_new=False) root_account = gnucash_session.book.get_root_account() account_of_interest = account_from_path(root_account, account_path) # a list of all the periods of interest, for each period # keep the start date, end date, a list to store debits and credits, # and sums for tracking the sum of all debits and sum of all credits period_list = [ [start_date, end_date, [], # debits [], # credits ZERO, # debits sum ZERO, # credits sum ] for start_date, end_date in generate_period_boundaries( start_year, start_month, period_type, periods) ] # a copy of the above list with just the period start dates period_starts = [e[0] for e in period_list ] # insert and add all splits in the periods of interest for split in account_of_interest.GetSplitList(): split = Split(instance=split) trans = split.parent trans_date = date.fromtimestamp(trans.GetDate()) # use binary search to find the period that starts before or on # the transaction date period_index = bisect_right( period_starts, trans_date ) - 1 # ignore transactions with a date before the matching period start # (after subtracting 1 above start_index would be -1) # and after the last period_end if period_index >= 0 and \ trans_date <= period_list[len(period_list)-1][1]: # get the period bucket appropriate for the split in question period = period_list[period_index] # more specifically, we'd expect the transaction date # to be on or after the period start, and before or on the # period end, assuming the binary search (bisect_right) # assumptions from above are are right.. # # in other words, we assert our use of binary search # and the filtered results from the above if provide all the # protection we need assert( trans_date>= period[0] and trans_date <= period[1] ) split_amount = gnc_numeric_to_python_Decimal(split.GetAmount()) # if the amount is negative, this is a credit if split_amount < ZERO: debit_credit_offset = 1 # else a debit else: debit_credit_offset = 0 # store the debit or credit Split with its transaction, using the # above offset to get in the right bucket # # if we wanted to be really cool we'd keep the transactions period[2+debit_credit_offset].append( (trans, split) ) # add the debit or credit to the sum, using the above offset # to get in the right bucket period[4+debit_credit_offset] += split_amount csv_writer = csv.writer(stdout) csv_writer.writerow( ('period start', 'period end', 'debits', 'credits') ) def generate_detail_rows(values): return ( ('', '', '', '', trans.GetDescription(), gnc_numeric_to_python_Decimal(split.GetAmount())) for trans, split in values ) for start_date, end_date, debits, credits, debit_sum, credit_sum in \ period_list: csv_writer.writerow( (start_date, end_date, debit_sum, credit_sum) ) if debits_show and len(debits) > 0: csv_writer.writerow( ('DEBITS', '', '', '', 'description', 'value') ) csv_writer.writerows( generate_detail_rows(debits) ) csv_writer.writerow( () ) if credits_show and len(credits) > 0: csv_writer.writerow( ('CREDITS', '', '', '', 'description', 'value') ) csv_writer.writerows( generate_detail_rows(credits) ) csv_writer.writerow( () ) # no save needed, we're just reading.. gnucash_session.end()
def main(): if len(argv) < 3: print 'Usage: python ofxml_make_commodity_accounts.py <gnucash-file> <ofxml-file> [symbols-file]' exit(1) gnucash_file=argv[1] symbols_file=False if len(argv)>=4: symbols_file=read_symbols(argv[3]) doc=ElementTree(file=argv[2]) acctids=doc.findall('./INVSTMTMSGSRSV1/INVSTMTTRNRS/INVSTMTRS/INVACCTFROM/ACCTID') if len(acctids)!=1: print 'ERROR: No unique account number found in OFX: found', len(acctids) return acctid=acctids[0].text.strip() acctcur='any' m=re.search('^(.*)-([A-Z]{3})$',acctid) if m: acctid=m.group(1) acctcur=m.group(2) print "INFO: Account number:", acctid, "Currency:", acctcur missing_symbols=False secs=[] for sec in doc.findall('./SECLISTMSGSRSV1/SECLIST/*/SECINFO'): id=sec.findall('./SECID/UNIQUEID')[0].text.strip() type=sec.findall('./SECID/UNIQUEIDTYPE')[0].text.strip() name=sec.findall('./SECNAME')[0].text.strip() symbol=sec.findall('./TICKER') if len(symbol): symbol=symbol[0].text.strip() else: symbol=None if symbols_file: if id in symbols_file[type]: name=symbols_file[type][id]['name'] symbol=symbols_file[type][id]['symbol'] else: print "WARNING: Missing symbol for", type, id, name, symbol missing_symbols=True secs.append({'id': id, 'type': type, 'name': name, 'symbol': symbol}) print "DEBUG: Found", len(secs), "commodities." sess=Session(gnucash_file) try: # Make sure all the commodities exist ct=sess.book.get_table() for ns in ['CUSIP','ISIN']: for c in ct.get_commodities(ns): matched_sec=None for sec in secs: if sec['type']==ns and sec['id']==c.get_cusip(): sec['c']=c break missing_secs=False for i,sec in enumerate(secs): if not 'c' in sec: print 'WARNING: Missing commodity', sec['type'],sec['id'],sec['name'],sec['symbol'] missing_secs=True if missing_secs or missing_symbols: print 'ERROR: Missing symbols or commodities, aborting.' return # Find GNC parent account root=sess.book.get_root_account() matched_accts=find_acct_by_number_and_currency(root,acctid,acctcur) if len(matched_accts)==0: from_iban=conv_iban(acctid) if from_iban: matched_accts=find_acct_by_number_and_currency(root,from_iban,acctcur) if len(matched_accts)!=1: print 'ERROR: No unique account this number/currency; found', len(matched_accts) return acct=matched_accts[0] print 'DEBUG: Found parent account:',acct.GetName() # Make sure the account has the appropriate stock accounts created_accounts=0 for sec in secs: matched_acct=None for secacct in acct.get_children(): if secacct.GetCommodity().get_instance()==sec['c'].get_instance(): matched_acct=secacct break if not matched_acct: secacct=Account(sess.book) if secacct: secacct.SetName(sec['name']) secacct.SetType(gnucash.ACCT_TYPE_STOCK) secacct.SetCommodity(sec['c']) secacct.SetCode(sec['id']) acct.append_child(secacct) created_accounts+=1 print 'DEBUG: Created Account',sec['name'] else: print 'ERROR: Error creating Account',sec['name'] print 'INFO:',len(secs),'accounts total',created_accounts,'created.' wait_for_backup_file(gnucash_file) sess.save() except BaseException as e: print 'ERROR:',e finally: sess.end() sess.destroy()
def main(): if len(argv) < 3: print('not enough parameters') print('usage: new_book_with_opening_balances.py {source_book_url} {destination_book_url}') print('examples:') print("gnucash-env python new_book_with_opening_balances.py '/home/username/test.gnucash' 'sqlite3:///home/username/new_test.gnucash'") print("gnucash-env python new_book_with_opening_balances.py '/home/username/test.gnucash' 'xml:///crypthome/username/finances/new_test.gnucash'") return #have everything in a try block to unable us to release our hold on stuff to the extent possible try: original_book_session = Session(argv[1], is_new=False) new_book_session = Session(argv[2], is_new=True) new_book = new_book_session.get_book() new_book_root = new_book.get_root_account() commodtable = new_book.get_table() # we discovered that if we didn't have this save early on, there would # be trouble later new_book_session.save() opening_balance_per_currency = {} recursivly_build_account_tree( original_book_session.get_book().get_root_account(), new_book_root, new_book, commodtable, opening_balance_per_currency, ACCOUNT_TYPES_TO_OPEN ) (namespace, mnemonic) = PREFERED_CURRENCY_FOR_SIMPLE_OPENING_BALANCE if (namespace, mnemonic) in opening_balance_per_currency: opening_trans, opening_amount = opening_balance_per_currency[ (namespace, mnemonic)] simple_opening_name_used = create_opening_balance_transaction( commodtable, namespace, mnemonic, new_book_root, new_book, opening_trans, opening_amount, False ) del opening_balance_per_currency[ PREFERED_CURRENCY_FOR_SIMPLE_OPENING_BALANCE] else: simple_opening_name_used = False for (namespace, mnemonic), (opening_trans, opening_amount) in \ opening_balance_per_currency.iteritems() : simple_opening_name_used = create_opening_balance_transaction( commodtable, namespace, mnemonic, new_book_root, new_book, opening_trans, opening_amount, simple_opening_name_used ) new_book_session.save() new_book_session.end() original_book_session.end() except: if "original_book_session" in locals(): original_book_session.end() if "new_book_session" in locals(): new_book_session.end() raise
def test_session_mode(self): """use mode argument""" self.ses = Session(mode=SessionOpenMode.SESSION_NORMAL_OPEN)
class BookSession( TestCase ): def setUp(self): self.ses = Session() self.book = self.ses.get_book()
class DenhacGncSession: _path = envproperties.gnucdbstring _session = None _root = None _commod = None _currency = None def __init__(self): if os.path.exists(self._path + '.LCK'): raise AssertionError("""Lock file exists. Is GNUCash running?\n""") with warnings.catch_warnings(): warnings.simplefilter("ignore") self._session = Session(self._path, is_new = False) self._root = self.getBook().get_root_account() self._commod = self.getBook().get_table() self._currency = self._commod.lookup('CURRENCY', 'USD') def saveAndEndSession(self): self._session.save() self._session.end() def saveSession(self): self._session.save() def endSession(self): self._session.end() def cancelSession(self): self._session.end() self._session.destroy() def getBook(self): return self._session.book def getRoot(self): return self._session.book.get_root_account() def getCurrency(self): return self._currency
# command-line options gnucash_filename = argv[1] first_invoice_number = argv[2] description = argv[3] invoice_value = gnc_numeric_from_decimal(Decimal(argv[4])) customer_ids = argv[5:] #Check that the date is set correctly for a batch of invoices. #Generally, the date should be set to the beginning of each month #for the month of the billing period. invoice_date = datetime.date(2012, 8, 1) session = Session(gnucash_filename, is_new=False) session.save() # this seems to make a difference in more complex cases book = session.book root_account = book.get_root_account() commodity_table = book.get_table() USD = commodity_table.lookup('CURRENCY', 'USD') assets = root_account.lookup_by_name("Assets") receivables = assets.lookup_by_name("Accounts Receivable") # This assumes you have an income subaccount of the form "Income:Member Dues" # The lookup fails if the parent account is specified. # IE root_account.lookup_by_name("Income:Member Dues") does not work.
from gnucash import Session # ------------------------------------------- # Configuration options can be changed here : cur_mnemonic="EUR" # Currency that prices are shown in. Possibilities include "EUR","GBP",... namespace_name = "" # If no namespace_name is set, all namespaces will be shown show_prices = True # If True, all prices for commodity are shown commodity_fullname = "" # If no name is given, all commoditys in namespace will be shown FILE = "PATH_TO_YOUR_TEST_FILE" # File is not saved but use a copy anyway # Configuration end # ------------------------------------------- session = Session(FILE, True, False, False) root = session.book.get_root_account() book = session.book pdb = book.get_price_db() comm_table = book.get_table() cur = comm_table.lookup("CURRENCY", cur_mnemonic) cur_name = cur.get_fullname() if namespace_name != "": # Show single namespace namespaces [ comm_table.find_namespace(namespace_name) ] else: # Show all namespaces namespaces=comm_table.get_namespaces_list()
class GnuCash(): """ In "/home/user/.odontuxrc" lies the odontux configuration, that tells about gnucash. In order that several dentists may use odontux together, the "profissionnalaccounting_url", which specify the gnucash account place is store in the user (ROLE_DENTIST) session : "models.users.OdontuxUser.profissionnalaccounting_url". The inside of gnucash needs at least : * assets ( all of the dentist assets ) * receivables ( what the patient owes to the dentist ) * dentalfund ( what the patient paid to the dentist, but ain't usable right away ; needs to pass by the bank ) * incomes ( all of the dentist incomes ) * dentalincomes ( incomes coming from dental practice activity ) While coding the assistant/secretary salary, the buying of dental supplies and all, we'll add "outcomes", liabilities... See commands/compta.py for : * assets * dentalfund * check * cash * card * transfer * paypal """ def __init__(self, patient_id, dentist_id): self.parser = ConfigParser.ConfigParser() home = os.path.expanduser("~") self.parser.read(os.path.join(home, ".odontuxrc")) self.dentist = ( meta.session.query(users.OdontuxUser) .filter(users.OdontuxUser.id == dentist_id) .one() ) profissionnalaccounting_url = self.dentist.gnucash_url.encode("utf_8") if profissionnalaccounting_url[-3:] == "xml": self.gnucashtype = "xml" elif "postgresql" in profissionnalaccounting_url.split("://"): self.gnucashtype = "postgresql" else: self.gnucashtype = "xml" assets = constants.ASSETS receivables = constants.RECEIVABLES dentalfund = constants.DENTAL_FUND incomes = constants.INCOMES dentalincomes = constants.DENTAL_INCOMES # Precise on which patient we'll work on self.patient_id = patient_id self.patient = meta.session.query(administration.Patient).filter( administration.Patient.id == patient_id).one() # Set the gnucash patient_id self.gcpatient_id = "pat_" + str(self.patient_id) # Set up the Book for accounting self.gcsession = GCSession(profissionnalaccounting_url, True) self.book = self.gcsession.get_book() # set the currency we'll use currency = constants.GNUCASH_CURRENCY commod_tab = self.book.get_table() self.currency = commod_tab.lookup("CURRENCY", currency) # Set up the root on accounting book self.root = self.book.get_root_account() # Assets self.assets = self.root.lookup_by_name(assets) # What the patient owes to dental office self.receivables = self.assets.lookup_by_name(receivables) if not self.receivables.lookup_by_name(self.gcpatient_id): self.patient_receivables = Account(self.book) self.receivables.append_child(self.patient_receivables) self.patient_receivables.SetName(self.gcpatient_id) self.patient_receivables.SetType(gnc_core_c.ACCT_TYPE_RECEIVABLE) self.patient_receivables.SetCommodity(self.currency) else: self.patient_receivables = self.receivables.lookup_by_name( self.gcpatient_id) # What the patient paid to dental office, but not usable # because it needs to pass by the bank. # the detail of dental fund is build in commands/compta.py # while getting the paymenttype. self.dentalfund = self.assets.lookup_by_name(dentalfund) # Incomes self.incomes = self.root.lookup_by_name(incomes) self.dentalincomes = self.incomes.lookup_by_name(dentalincomes) def gnc_numeric_from_decimal(self, decimal_value): sign, digits, exponent = decimal_value.as_tuple() # convert decimal digits to a fractional numerator # equivlent to # numerator = int(''.join(digits)) # but without the wated conversion to string and back, # this is probably the same algorithm int() uses numerator = 0 TEN = int(Decimal(0).radix()) # this is always 10 numerator_place_value = 1 # add each digit to the final value multiplied by the place value # from least significant to most sigificant for i in xrange(len(digits)-1,-1,-1): numerator += digits[i] * numerator_place_value numerator_place_value *= TEN if decimal_value.is_signed(): numerator = -numerator # if the exponent is negative, we use it to set the denominator if exponent < 0 : denominator = TEN ** (-exponent) # if the exponent isn't negative, we bump up the numerator # and set the denominator to 1 else: numerator *= TEN ** exponent denominator = 1 return GncNumeric(numerator, denominator)
def setUp(self): self.ses = Session() self.book = self.ses.get_book()
def __init__(self, patient_id, dentist_id): self.parser = ConfigParser.ConfigParser() home = os.path.expanduser("~") self.parser.read(os.path.join(home, ".odontuxrc")) self.dentist = ( meta.session.query(users.OdontuxUser) .filter(users.OdontuxUser.id == dentist_id) .one() ) profissionnalaccounting_url = self.dentist.gnucash_url.encode("utf_8") if profissionnalaccounting_url[-3:] == "xml": self.gnucashtype = "xml" elif "postgresql" in profissionnalaccounting_url.split("://"): self.gnucashtype = "postgresql" else: self.gnucashtype = "xml" assets = constants.ASSETS receivables = constants.RECEIVABLES dentalfund = constants.DENTAL_FUND incomes = constants.INCOMES dentalincomes = constants.DENTAL_INCOMES # Precise on which patient we'll work on self.patient_id = patient_id self.patient = meta.session.query(administration.Patient).filter( administration.Patient.id == patient_id).one() # Set the gnucash patient_id self.gcpatient_id = "pat_" + str(self.patient_id) # Set up the Book for accounting self.gcsession = GCSession(profissionnalaccounting_url, True) self.book = self.gcsession.get_book() # set the currency we'll use currency = constants.GNUCASH_CURRENCY commod_tab = self.book.get_table() self.currency = commod_tab.lookup("CURRENCY", currency) # Set up the root on accounting book self.root = self.book.get_root_account() # Assets self.assets = self.root.lookup_by_name(assets) # What the patient owes to dental office self.receivables = self.assets.lookup_by_name(receivables) if not self.receivables.lookup_by_name(self.gcpatient_id): self.patient_receivables = Account(self.book) self.receivables.append_child(self.patient_receivables) self.patient_receivables.SetName(self.gcpatient_id) self.patient_receivables.SetType(gnc_core_c.ACCT_TYPE_RECEIVABLE) self.patient_receivables.SetCommodity(self.currency) else: self.patient_receivables = self.receivables.lookup_by_name( self.gcpatient_id) # What the patient paid to dental office, but not usable # because it needs to pass by the bank. # the detail of dental fund is build in commands/compta.py # while getting the paymenttype. self.dentalfund = self.assets.lookup_by_name(dentalfund) # Incomes self.incomes = self.root.lookup_by_name(incomes) self.dentalincomes = self.incomes.lookup_by_name(dentalincomes)
# Django setup # from http://www.b-list.org/weblog/2007/sep/22/standalone-django-scripts/ # This script needs to be callable from the command line, but it also needs # to know about the Django project's database and other settings. from django.core.management import setup_environ import settings # only works due to path fuckery above setup_environ(settings) from gnucash_data import models from utils.AsciiDammit import asciiDammit # make sure we can begin a session models.Lock.check_can_obtain() # begin GnuCash API session session = Session(settings.GNUCASH_CONN_STRING) debug = False def debug_print(s): if debug: print s def get_transaction_string(t): memo = txinfo.get('memo', '') if memo: memo = ' / ' + memo return "'%s%s' on %s for %s" \ % (t['description'], memo,
#!/usr/bin/env python3 ## @file # @brief Example Script simple sqlite create # @ingroup python_bindings_examples from gnucash import Session, Account from os.path import abspath from gnucash.gnucash_core_c import ACCT_TYPE_ASSET s = Session('sqlite3://%s' % abspath('test.blob'), is_new=True) # this seems to make a difference in more complex cases s.save() book = s.book root = book.get_root_account() a = Account(book) root.append_child(a) a.SetName('wow') a.SetType(ACCT_TYPE_ASSET) commod_table = book.get_table() a.SetCommodity( commod_table.lookup('CURRENCY', 'CAD') ) s.save() s.end()
if terms: for term in terms: query.add_term(*term) splits = [] for split in query.run(): split = Split( instance=split) # ToDo: query.run() should return objects splits.append(split) query.destroy() return splits with Session(uri, SessionOpenMode.SESSION_NEW_STORE) as ses: book = ses.get_book() accountA, accountB = createAccounts(book) createRandomTransactions(book, accountA, accountB) # TRANSACTIONS # # get all transactions transactions_all = query_transactions(book) print("Query all: " + str(len(transactions_all)) + " transactions.") # query date threshold = datetime.datetime(1950, 1, 1) QOF_DATE_MATCH_NORMAL = 2 terms = [(['date-posted'],
inst = pricedb.lookup_latest(commodity, currency).get_value() print GncNumeric(instance=inst).to_string() def add_commodity(s, args): raise NotImplementedError() parser = argparse.ArgumentParser() parser.add_argument('gnucash_file') parser.add_argument('--dry-run', action='store_true', help='Do not write anything, noop-mode') subparsers = parser.add_subparsers() sp = subparsers.add_parser('update-quotes', help='Update stock quotes from online service') sp.set_defaults(func=update_quotes) sp = subparsers.add_parser('report', help='Print portfolio report') sp.set_defaults(func=report) sp = subparsers.add_parser('add-commodity', help='Helper method to add commodity by ISIN') sp.add_argument('isin', help='ISIN of stock/bond to add') sp.set_defaults(func=add_commodity) args = parser.parse_args() logging.basicConfig(level=logging.INFO) logging.getLogger('urllib3').setLevel(logging.WARN) s = Session(args.gnucash_file) try: args.func(s, args) finally: s.end()