def __init__(self, book, args): # enter current time as "date entered" self.now = datetime.now().strftime('%Y-%m-%d %H:%M:%S +0100') self.acc_lookup = {} self.document = book self.accounts = book.account self.default_currency = args.currency self.currency_converter = CurrencyConverter(verbosity=args.verbosity)
def update_currency_values(self): currency_codes = self.db_util.list_currency_codes() converter = CurrencyConverter() for code in currency_codes: try: new_usd_rate = converter.get_conversion_rate(currency_code=code, base='USD') self.db_util.update_currency_usd_conversion_rate(code, new_usd_rate) except KeyError as missing_key: print(f"Could not update conversion rate for currency {missing_key}")
class PayPalConverter: def __init__(self, book, args): # enter current time as "date entered" self.now = datetime.now().strftime('%Y-%m-%d %H:%M:%S +0100') self.acc_lookup = {} self.document = book self.accounts = book.account self.default_currency = args.currency self.currency_converter = CurrencyConverter(verbosity=args.verbosity) # convert float from paypal number string def amountFromPayPal(self, value): # assume German locale here for the while minusIdx = value.find("-") preMult = 1 if minusIdx != -1: value = value[minusIdx+1:] preMult = -1 # kill all thousands separators, split off fractional part value_parts = value.replace(".","").split(',') if len(value_parts) == 1: return preMult * float(value_parts[0]) if len(value_parts) == 2: return preMult * (float(value_parts[0]) + float(value_parts[1])/(10**len(value_parts[1]))) else: raise IndexError # wrap the converter here, to be able to convert value to float if # necessary def currencyConvert(self, value, currency, txn_date): if isinstance(value, str): value = self.amountFromPayPal(value) return self.currency_converter.convert(value, currency, args.currency, txn_date) # lookup account with given name (and optionally type) in dict (or # search in xml tree) def lookupAccountUUID(self, account_name, **kwargs): acc_type = kwargs.pop('type', '') lookup_key = acc_type+account_name if self.acc_lookup.has_key(lookup_key): return self.acc_lookup[lookup_key] else: for elem in self.accounts: # get account with matching name and type (partial match is ok) if elem.name.find(account_name) != -1 and elem.type.find(acc_type) != -1: self.acc_lookup[lookup_key] = elem.id.value() return elem.id.value() print "Did not find account with name %s in current book, bailing out!" % account_name exit(1) # add a gnucash split transaction with the given data def addTransaction(self, **kwargs): transaction_date = kwargs.pop('date') transaction_currency = kwargs.pop('currency') transaction_description = kwargs.pop('description') txn = kwargs.pop('txn') # don't accept non-default currencies here, unless it at least # appears to be a multi-currency split transaction if (self.default_currency != transaction_currency and len(txn[0]) < 2 and len(txn[1]) < 2): # well - actually _do_ accept it if net value is zero, # since it obviously does not affect the balance if ((len(txn[0]) > 0 and txn[0][0][2] == '0,00') or (len(txn[1]) > 0 and txn[1][0][2] == '0,00')): # fake main transaction currency. amount is zero anyway transaction_currency = self.default_currency else: print "Wrong currency for main transaction encountered, bailing out!" if args.verbosity > 0: print "Context: "+str(currLine) exit(1) try: transaction=gnc.transaction( trn.id( uuid.uuid4().hex, type="guid" ), trn.currency( cmdty.space("ISO4217"), cmdty.id(transaction_currency) ), trn.date_posted( ts.date(getGNCDateStr(transaction_date)) ), trn.date_entered( ts.date(self.now) ), trn.description(transaction_description), trn.splits(), version="2.0.0") for curr_split in txn[0]: split_account = curr_split[0] split_memo = curr_split[1] split_value = curr_split[2] if isinstance(split_value, str): split_value = self.amountFromPayPal(split_value) if len(curr_split) > 3: split_uuid = self.lookupAccountUUID(split_account, type=curr_split[3]) else: split_uuid = self.lookupAccountUUID(split_account) transaction.splits.append( trn.split( split.id( uuid.uuid4().hex, type="guid" ), split.memo( split_memo ), split.reconciled_state( "n" ), split.value( gnucashFromAmount(split_value) ), split.quantity( gnucashFromAmount(split_value) ), split.account( split_uuid, type="guid" )) ) for curr_split in txn[1]: split_account = curr_split[0] split_memo = curr_split[1] split_value = curr_split[2] if isinstance(split_value, str): split_value = self.amountFromPayPal(split_value) if len(curr_split) > 3: split_uuid = self.lookupAccountUUID(split_account, type=curr_split[3]) else: split_uuid = self.lookupAccountUUID(split_account) transaction.splits.append( trn.split( split.id( uuid.uuid4().hex, type="guid" ), split.memo( split_memo ), split.reconciled_state( "n" ), split.value( gnucashFromAmount(-split_value) ), split.quantity( gnucashFromAmount(-split_value) ), split.account( split_uuid, type="guid" )) ) self.document.append(transaction) except pyxb.UnrecognizedContentError as e: print '*** ERROR validating input:' print 'Unrecognized element "%s" at %s (details: %s)' % (e.content.expanded_name, e.content.location, e.details())
class PayPalConverter: def __init__(self, book, args): # enter current time as "date entered" self.now = datetime.now().strftime('%Y-%m-%d %H:%M:%S +0100') self.acc_lookup = {} self.document = book self.accounts = book.account self.default_currency = args.currency self.currency_converter = CurrencyConverter(verbosity=args.verbosity) # convert float from paypal number string def amountFromPayPal(self, value): # assume German locale here for the while minusIdx = value.find("-") preMult = 1 if minusIdx != -1: value = value[minusIdx + 1:] preMult = -1 # kill all thousands separators, split off fractional part value_parts = value.replace(".", "").split(',') if len(value_parts) == 1: return preMult * float(value_parts[0]) if len(value_parts) == 2: return preMult * (float(value_parts[0]) + float(value_parts[1]) / (10**len(value_parts[1]))) else: raise IndexError # wrap the converter here, to be able to convert value to float if # necessary def currencyConvert(self, value, currency, txn_date): if isinstance(value, str): value = self.amountFromPayPal(value) return self.currency_converter.convert(value, currency, args.currency, txn_date) # lookup account with given name (and optionally type) in dict (or # search in xml tree) def lookupAccountUUID(self, account_name, **kwargs): acc_type = kwargs.pop('type', '') lookup_key = acc_type + account_name if self.acc_lookup.has_key(lookup_key): return self.acc_lookup[lookup_key] else: for elem in self.accounts: # get account with matching name and type (partial match is ok) if elem.name.find(account_name) != -1 and elem.type.find( acc_type) != -1: self.acc_lookup[lookup_key] = elem.id.value() return elem.id.value() print "Did not find account with name %s in current book, bailing out!" % account_name exit(1) # add a gnucash split transaction with the given data def addTransaction(self, **kwargs): transaction_date = kwargs.pop('date') transaction_currency = kwargs.pop('currency') transaction_description = kwargs.pop('description') txn = kwargs.pop('txn') # don't accept non-default currencies here, unless it at least # appears to be a multi-currency split transaction if (self.default_currency != transaction_currency and len(txn[0]) < 2 and len(txn[1]) < 2): # well - actually _do_ accept it if net value is zero, # since it obviously does not affect the balance if ((len(txn[0]) > 0 and txn[0][0][2] == '0,00') or (len(txn[1]) > 0 and txn[1][0][2] == '0,00')): # fake main transaction currency. amount is zero anyway transaction_currency = self.default_currency else: print "Wrong currency for main transaction encountered, bailing out!" if args.verbosity > 0: print "Context: " + str(currLine) exit(1) try: transaction = gnc.transaction( trn.id(uuid.uuid4().hex, type="guid"), trn.currency(cmdty.space("ISO4217"), cmdty.id(transaction_currency)), trn.date_posted(ts.date(getGNCDateStr(transaction_date))), trn.date_entered(ts.date(self.now)), trn.description(transaction_description), trn.splits(), version="2.0.0") for curr_split in txn[0]: split_account = curr_split[0] split_memo = curr_split[1] split_value = curr_split[2] if isinstance(split_value, str): split_value = self.amountFromPayPal(split_value) if len(curr_split) > 3: split_uuid = self.lookupAccountUUID(split_account, type=curr_split[3]) else: split_uuid = self.lookupAccountUUID(split_account) transaction.splits.append( trn.split(split.id(uuid.uuid4().hex, type="guid"), split.memo(split_memo), split.reconciled_state("n"), split.value(gnucashFromAmount(split_value)), split.quantity(gnucashFromAmount(split_value)), split.account(split_uuid, type="guid"))) for curr_split in txn[1]: split_account = curr_split[0] split_memo = curr_split[1] split_value = curr_split[2] if isinstance(split_value, str): split_value = self.amountFromPayPal(split_value) if len(curr_split) > 3: split_uuid = self.lookupAccountUUID(split_account, type=curr_split[3]) else: split_uuid = self.lookupAccountUUID(split_account) transaction.splits.append( trn.split(split.id(uuid.uuid4().hex, type="guid"), split.memo(split_memo), split.reconciled_state("n"), split.value(gnucashFromAmount(-split_value)), split.quantity(gnucashFromAmount(-split_value)), split.account(split_uuid, type="guid"))) self.document.append(transaction) except pyxb.UnrecognizedContentError as e: print '*** ERROR validating input:' print 'Unrecognized element "%s" at %s (details: %s)' % ( e.content.expanded_name, e.content.location, e.details())
print 'Unrecognized element "%s" at %s (details: %s)' % (e.content.expanded_name, e.content.location, e.details()) except pyxb.UnrecognizedDOMRootNodeError as e: print '*** ERROR matching content:' print e.details() conversion_scripts = {} # import conversion scripts if args.script: for index,script in enumerate(args.script): ns_name = "script"+str(index) exec "import "+script+" as "+ns_name conversion_scripts[eval(ns_name+".type_curr")] = ns_name if args.verbosity > 0: print "Importing CSV transactions" converter = CurrencyConverter(verbosity=args.verbosity) for index,line in enumerate(bitpay_csv): transaction_date = dateTimeFromCSV(line["date"], line["time"]) transaction_ref = line["invoice id"] transaction_type = line["tx type"] transaction_currency = line["currency"] transaction_value = amountFromCSV(line["amount"]) transaction_desc = line["description"] transaction_xchangerate = amountFromCSV(line["exchange rate (EUR)"]) # remove crap, encode into unicode transaction_name = re.sub(r"[\x01-\x1F\x7F]", "", line["buyer name"]) transaction_name = transaction_name.decode(args.encoding) transaction_email = line["buyer email"]
e.content.expanded_name, e.content.location, e.details()) except pyxb.UnrecognizedDOMRootNodeError as e: print '*** ERROR matching content:' print e.details() conversion_scripts = {} # import conversion scripts if args.script: for index, script in enumerate(args.script): ns_name = "script" + str(index) exec "import " + script + " as " + ns_name conversion_scripts[eval(ns_name + ".desc_method_brand")] = ns_name if args.verbosity > 0: print "Importing CSV transactions" converter = CurrencyConverter(verbosity=args.verbosity) for index, line in enumerate(concardis_csv): transaction_ref = line["REF"] transaction_order_date = dateFromCSV(line["ORDER"]) transaction_payment_date = dateFromCSV(line["PAYDATE"]) transaction_status = line["STATUS"] # remove crap, encode into unicode try: transaction_name = re.sub(r"[\x01-\x1F\x7F]", "", line["NAME"]) except: if args.verbosity > 0: print "Failing line cleanse: %s" % str(line) transaction_name = transaction_name.decode(args.encoding, errors='ignore') transaction_value = amountFromCSV(line["TOTAL"]) transaction_currency = line["CUR"]
print 'Unrecognized element "%s" at %s (details: %s)' % (e.content.expanded_name, e.content.location, e.details()) except pyxb.UnrecognizedDOMRootNodeError as e: print '*** ERROR matching content:' print e.details() conversion_scripts = {} # import conversion scripts if args.script: for index,script in enumerate(args.script): ns_name = "script"+str(index) exec "import "+script+" as "+ns_name conversion_scripts[eval(ns_name+".desc_method_brand")] = ns_name if args.verbosity > 0: print "Importing CSV transactions" converter = CurrencyConverter(verbosity=args.verbosity) for index,line in enumerate(concardis_csv): transaction_ref = line["REF"] transaction_order_date = dateFromCSV(line["ORDER"]) transaction_payment_date = dateFromCSV(line["PAYDATE"]) transaction_status = line["STATUS"] # remove crap, encode into unicode try: transaction_name = re.sub(r"[\x01-\x1F\x7F]", "", line["NAME"]) except: if args.verbosity > 0: print "Failing line cleanse: %s" % str(line) transaction_name = transaction_name.decode(args.encoding, errors='ignore') transaction_value = amountFromCSV(line["TOTAL"]) transaction_currency = line["CUR"]