Esempio n. 1
0
    def test_add_transfer(self):
        account1 = next(account for account in self.client.budget.be_accounts
                        if account.account_name == 'account1')
        account2 = next(account for account in self.client.budget.be_accounts
                        if account.account_name == 'account2')

        try:
            payee_2 = next(payee for payee in self.client.budget.be_payees
                           if payee.entities_account_id == account2.id)
        except StopIteration:
            payee_2 = Payee(entities_account_id=account2.id)
            self.client.budget.be_payees.append(payee_2)
        try:
            payee_1 = next(payee for payee in self.client.budget.be_payees
                           if payee.entities_account_id == account1.id)
        except StopIteration:
            payee_1 = Payee(entities_account_id=account1.id)
            self.client.budget.be_payees.append(payee_1)

        transaction1 = Transaction(amount=random.randint(-10, 10),
                                   date=datetime.now(),
                                   entities_account_id=account1.id,
                                   entities_payee_id=payee_2.id)
        transaction2 = Transaction(amount=-transaction1.amount,
                                   date=datetime.now(),
                                   entities_account_id=account2.id,
                                   entities_payee_id=payee_1.id)
        self.client.budget.be_transactions.append(transaction1)
        self.client.budget.be_transactions.append(transaction2)
        self.client.sync()
        self.reload()
        self.assertIn(transaction1, self.client.budget.be_transactions)
        self.assertIn(transaction2, self.client.budget.be_transactions)
Esempio n. 2
0
def test_get_ce_addtransactionsubtransaction(client):
    client.budgetClient.clear_changed_entities()

    added_transaction = Transaction()
    subtransaction1 = Subtransaction(entities_transaction=added_transaction)
    subtransaction2 = Subtransaction(entities_transaction=added_transaction)

    client.budget.be_transactions.append(added_transaction)
    client.budget.be_subtransactions.append(subtransaction1)
    client.budget.be_subtransactions.append(subtransaction2)

    client.session.commit()

    changed_entities = client.budgetClient.get_changed_apidict()
    assert isinstance(changed_entities, dict)
    assert 1 == len(changed_entities.keys())
    assert 'be_transaction_groups' == list(changed_entities.keys())[0]
    transaction_groups = list(changed_entities['be_transaction_groups'])

    assert 1 == len(transaction_groups)
    assert added_transaction.get_apidict(
    ) == transaction_groups[0]['be_transaction']

    assert transaction_groups[0]['be_subtransactions'] is not None
    subtransactions = transaction_groups[0]['be_subtransactions']
    assert len(subtransactions) == 2
    assert subtransaction1.get_apidict() in subtransactions
    assert subtransaction2.get_apidict() in subtransactions
Esempio n. 3
0
def test_equality():
    tr1 = Transaction(id='t')
    tr2 = Transaction(id='t')
    assert tr1 == tr2

    tr1 = Transaction()
    tr2 = Transaction()
    assert tr1 != tr2
Esempio n. 4
0
    def testequality(self):
        tr1 = Transaction(id='t')
        tr2 = Transaction(id='t')
        self.assertEqual(tr1, tr2)

        tr1 = Transaction()
        tr2 = Transaction()
        self.assertNotEqual(tr1, tr2)
Esempio n. 5
0
    def testequality(self):
        tr1 = Transaction()
        tr2 = Transaction()
        self.assertNotEqual(tr1, tr2)

        tr1 = Transaction(entities_account_id=1)
        tr2 = Transaction(entities_account_id=2)
        self.assertNotEqual(tr1, tr2)
Esempio n. 6
0
    def testequality(self):
        tr1 = Transaction(id='t')
        tr2 = Transaction(id='t')
        self.assertTrue(tr1 == tr2)

        tr1 = Transaction()
        tr2 = Transaction()
        self.assertFalse(tr1 == tr2)
Esempio n. 7
0
    def test_str(self):
        # tests no exceptions when getting the string representation of some entities
        obj = Transaction()
        obj.__str__()
        obj.__unicode__()

        obj2 = Budget()
        obj2.be_accounts.__str__()
        obj2.be_accounts.__unicode__()
Esempio n. 8
0
def create_transaction_from_csv(data, account, settings=settings_module, ynab_client = ynab_client_module):
    settings.log.debug('received data %s' % data)
    expected_delta = 0

    if data['amount'] == 0:
        return {'error': 'Transaction amount is 0.'}

    payee_name = data['description']
    subcategory_id = get_subcategory_from_payee(payee_name)

    # If we are creating the payee, then we need to increase the delta
    if not ynab_client.payeeexists(payee_name):
        print 'does not exist'
        settings.log.debug('payee does not exist, will create %s', payee_name)
        expected_delta += 1

    # Get the payee ID. This will append a new one if needed
    entities_payee_id = ynab_client.getpayee(payee_name).id

    # If we created a payee, then we need to resync the payees cache
    if expected_delta == 1:
        ynab_client.cache_payees()

    # Create the Transaction
    settings.log.debug('Creating transaction object')
    transaction = Transaction(
        entities_account_id=account.id,
        amount=Decimal(data['amount']),
        date=parse(data['date'], dayfirst=True),
        entities_payee_id=entities_payee_id,
        imported_date=datetime.now().date(),
        imported_payee=payee_name,
        cleared=True,
        source='Imported'
    )

    if subcategory_id is not None:
        transaction.entities_subcategory_id = subcategory_id

    settings.log.debug('Duplicate detection')
    if ynab_client.containsDuplicate(transaction):
        settings.log.debug('skipping due to duplicate transaction')
        # We may just be adding a payee
        if expected_delta == 1:
            print 'just adding payee'
            return expected_delta
        else:
            return {'error': 'Tried to add a duplicate transaction.'}
    else:
        expected_delta += 1
        settings.log.debug('appending and pushing transaction to YNAB. Delta: %s', expected_delta)
        ynab_client.client.budget.be_transactions.append(transaction)
        return expected_delta
Esempio n. 9
0
    def testgetChangedEntities_addtransactionsubtransaction(self):
        added_transaction = Transaction()
        subtransaction1 = Subtransaction(
            entities_transaction=added_transaction)
        subtransaction2 = Subtransaction(
            entities_transaction=added_transaction)

        self.client.budget.be_transactions.append(added_transaction)
        self.client.budget.be_subtransactions.append(subtransaction1)
        self.client.budget.be_subtransactions.append(subtransaction2)

        self.client.session.commit()

        changed_entities = self.client.budget.get_changed_entities()
        self.assertIsInstance(changed_entities, dict)
        self.assertEqual(1, len(changed_entities.keys()))
        self.assertEqual('be_transaction_groups',
                         list(changed_entities.keys())[0])
        transaction_groups = changed_entities['be_transaction_groups']

        self.assertEqual(1, len(transaction_groups))
        self.assertEqual(added_transaction,
                         transaction_groups[0]['be_transaction'])

        self.assertIsNotNone(transaction_groups[0]['be_subtransactions'])
        try:
            self.assertItemsEqual(
                [subtransaction1, subtransaction2],
                set(transaction_groups[0]['be_subtransactions']))
        except AttributeError:
            self.assertCountEqual(
                [subtransaction1, subtransaction2],
                set(transaction_groups[0]['be_subtransactions']))
Esempio n. 10
0
    def add_account(self, account, balance, balance_date):
        payee = Payee(
            entities_account_id=account.id,
            enabled=True,
            auto_fill_subcategory_enabled=True,
            auto_fill_memo_enabled=False,
            auto_fill_amount_enabled=False,
            rename_on_import_enabled=False,
            name="Transfer : %s" % account.account_name
        )
        immediateincomeid = next(
            s.id for s in self.budget.be_subcategories if s.internal_name == 'Category/__ImmediateIncome__')
        startingbalanceid = next(p.id for p in self.budget.be_payees if p.internal_name == 'StartingBalancePayee')

        transaction = Transaction(
            accepted=True,
            amount=balance,
            entities_subcategory_id=immediateincomeid,
            cash_amount=0,
            cleared='Cleared',
            date=balance_date,
            entities_account_id=account.id,
            credit_amount=0,
            entities_payee_id=startingbalanceid,
            is_tombstone=False
        )

        self.budget.be_accounts.append(account)
        self.budget.be_payees.append(payee)
        self.budget.be_transactions.append(transaction)
Esempio n. 11
0
def migrate_main():
    print('migrate YNAB4 to pynYNAB')
    """Migrate a YNAB4 budget transaction history to nYNAB, using pyynab"""

    parser = configargparse.getArgumentParser('pynYNAB')
    parser.description = inspect.getdoc(migrate_main)
    parser.add_argument('budget',
                        metavar='BudgetPath',
                        type=str,
                        help='The budget .ynab4 directory')
    args = parser.parse_args()
    test_common_args(args)

    budget_base_name = os.path.basename(args.budget)
    budget_path = os.path.dirname(args.budget)
    budget_name = re.match(r"(?P<budget_name>.*)~[A-Z0-9]{8}\.ynab4",
                           budget_base_name).groupdict().get('budget_name')

    if args.budgetname is not None:
        budget_name = args.budgetname

    thisynab = YNAB(budget_path, budget_name)

    client = clientfromargs(args, reset=True)

    for ynab4_account in thisynab.accounts:
        account = Account(
            name=ynab4_account.name,
            account_type=ynab4_account.type.value,
            on_budget=ynab4_account.on_budget,
            sortable_index=random.randint(-50000, 50000),
        )
        mindate = min([
            ynab4transaction.date for ynab4transaction in thisynab.transactions
            if ynab4transaction.account == ynab4_account
        ])
        client.add_account(account, 0, mindate)

    for master_category in thisynab.master_categories:
        master_entity = MasterCategory(name=master_category.name,
                                       sortable_index=random.randint(
                                           -50000, 50000))
        client.budget.be_master_categories.append(master_entity)
        for category in master_category.categories:

            entity = Subcategory(name=category.name,
                                 entities_master_category_id=master_entity.id,
                                 sortable_index=random.randint(-50000, 50000))
            client.budget.be_subcategories.append(entity)
        client.sync()

    for ynab4_payee in thisynab.payees:
        payee = Payee(name=ynab4_payee.name)
        client.budget.be_payees.append(payee)
        client.sync()

    for ynab4transaction in thisynab.transactions:
        transaction = Transaction()
        pass
Esempio n. 12
0
    def testappendBad(self):
        obj = Budget()
        transaction = Transaction()

        def testappend():
            obj.be_accounts.append(transaction)

        self.assertRaises(ValueError, testappend)
Esempio n. 13
0
 def util_add_transaction(self):
     transaction = Transaction(
         amount=1,
         cleared='Uncleared',
         date=datetime.now(),
         entities_account_id=self.account.id,
     )
     self.client.add_transaction(transaction)
Esempio n. 14
0
    def test_add_deletetransactions(self):
        from datetime import datetime

        transactions = [
            Transaction(
                amount=random.randint(-10, 10),
                cleared='Uncleared',
                date=datetime.now() - 8 * timedelta(days=365),
                entities_account_id=self.account.id,
            ),
            Transaction(
                amount=random.randint(-10, 10),
                cleared='Uncleared',
                date=datetime.now() + 8 * timedelta(days=365),
                entities_account_id=self.account.id,
            ),
            Transaction(
                amount=random.randint(-10, 10),
                cleared='Uncleared',
                date=datetime.now(),
                entities_account_id=self.account.id,
            )
        ]

        self.client.add_transactions(transactions)
        print('Time for request: ' +
              str(self.client.connection.lastrequest_elapsed.total_seconds()) +
              ' s')

        self.reload()
        for transaction in transactions:
            self.assertIn(transaction, self.client.budget.be_transactions)

        for transaction in transactions:
            self.client.delete_transaction(transaction)
        self.reload()

        for transaction in transactions:
            resulttransaction = self.client.budget.be_transactions.get(
                transaction.id)
            self.assertTrue(resulttransaction is None)
Esempio n. 15
0
def get_transaction(client, date, payee, amount, memo, account):
    imported_date = datetime.now().date()
    return Transaction(entities_account_id=get_or_create_account(
        client, account).id,
                       date=date,
                       entities_payee_id=get_or_create_payee(client, payee).id,
                       imported_payee=payee,
                       source='Imported',
                       memo=memo,
                       amount=amount,
                       cash_amount=amount,
                       imported_date=imported_date)
Esempio n. 16
0
def get_ynab_transaction(nordea_transaction, account_id, subcategory_id,
                         payee_id):
    imported_date = datetime.datetime.now().date()
    splitted_amount = nordea_transaction.amount.split(",")
    return Transaction(
        entities_account_id=account_id,
        amount=float("-%s.%s" % (splitted_amount[0], splitted_amount[1])),
        date=datetime.datetime.strptime(nordea_transaction.date, "%d.%m.%Y"),
        imported_date=imported_date,
        entities_subcategory_id=subcategory_id,
        entities_payee_id=payee_id,
        source="Imported")
Esempio n. 17
0
def test_add_deletetransaction(account, live_client_w_account):
    transaction = Transaction(
        amount=1,
        cleared='Uncleared',
        date=datetime.now(),
        entities_account_id=account.id,
    )
    live_client_w_account.add_transaction(transaction)
    live_client_w_account = reload()
    assert transaction in live_client_w_account.budget.be_transactions
    live_client_w_account.delete_transaction(transaction)
    live_client_w_account = reload()
    assert transaction not in live_client_w_account.budget.be_transactions
Esempio n. 18
0
 def getTr(date, payee, amount, memo, account):
     return Transaction(
         entities_account_id=account.id,
         date=date,
         entities_payee_id=self.util_add_payee_by_name_if_doesnt_exist(
             payee).id,
         imported_payee=payee,
         source='Imported',
         check_number='0003445',
         memo=memo,
         amount=amount,
         cash_amount=amount,
         imported_date=imported_date)
Esempio n. 19
0
 def getTr(self, date, payee, amount, memo, account):
     imported_date = datetime.now().date()
     return Transaction(
         entities_account_id=self.util_get_empty_account_by_name_if_doesnt_exist(account).id,
         date=date,
         entities_payee_id=self.util_add_payee_by_name_if_doesnt_exist(payee).id,
         imported_payee=payee,
         source='Imported',
         memo=memo,
         amount=amount,
         cash_amount=amount,
         imported_date=imported_date
     )
Esempio n. 20
0
def func():
    print('test_sync')
    for i in range(0, 5000):
        client.budget.be_transactions.append(Transaction())
    client.session.commit()
    client.budget.clear_changed_entities()
    print('Entities in the client: %i' % (
        sum([len(getattr(client.budget, f))
             for f in client.budget.listfields]) + sum([
                 len(getattr(client.catalog, f))
                 for f in client.catalog.listfields
             ])))
    pass
Esempio n. 21
0
    def test_str(self):
        # tests no exceptions when getting the string representation of some entities
        obj = Transaction()
        obj.__str__()
        obj.__unicode__()

        obj2 = Budget()
        obj2.be_accounts.__str__()
Esempio n. 22
0
 def test_add_deletetransaction(self):
     from datetime import datetime
     transaction = Transaction(
         amount=1,
         cleared='Uncleared',
         date=datetime.now(),
         entities_account_id=self.account.id,
     )
     self.client.add_transaction(transaction)
     self.reload()
     self.assertIn(transaction, self.client.budget.be_transactions)
     self.client.delete_transaction(transaction)
     self.reload()
     self.assertNotIn(transaction, self.client.budget.be_transactions)
Esempio n. 23
0
    def test_add_splittransactions(self):
        subcatsplit_id = next(
            subcategory.id
            for subcategory in self.client.budget.be_subcategories
            if subcategory.internal_name == 'Category/__Split__')
        transaction = Transaction(amount=1,
                                  date=datetime.now(),
                                  entities_account_id=self.account.id,
                                  entities_subcategory_id=subcatsplit_id)
        sub1 = Subtransaction(amount=5000,
                              entities_transaction_id=transaction.id)
        sub2 = Subtransaction(amount=5000,
                              entities_transaction_id=transaction.id)
        self.client.budget.be_transactions.append(transaction)
        self.client.budget.be_subtransactions.append(sub1)
        self.client.budget.be_subtransactions.append(sub2)

        self.client.sync()

        self.reload()

        self.assertIn(transaction, self.client.budget.be_transactions)
        self.assertIn(sub1, self.client.budget.be_subtransactions)
        self.assertIn(sub2, self.client.budget.be_subtransactions)
Esempio n. 24
0
def do_csvimport(args,client=None):
    if client is None:
        client = clientfromargs(args)
    logger=get_logger(args)

    logger.debug('selected schema %s' % (args.schema,))
    if os.path.exists(args.schema):
        schemafile = args.schema
    else:
        schemafile = os.path.join(schemas_dir, args.schema + '.json')
        if not os.path.exists(schemafile):
            logger.error('This schema doesn''t exist in csv_schemas')
            exit(-1)
    try:
        schema = SchemaModel(schemafile, case_insensitive_headers=True)
        with open(schemafile,'r') as sf:
            schemacontent = json.load(sf)
            try:
                nheaders = schemacontent['nheaders']
            except KeyError:
                nheaders = 1
    except InvalidSchemaError:
        logger.error('Invalid CSV schema')
        raise
    logger.debug('schema headers %s' % schema.headers)

    if 'account' not in schema.headers and args.accountname is None:
        logger.error('This schema does not have an account column and no account name was provided')
        exit(-1)

    accounts = {x.account_name: x for x in client.budget.be_accounts}
    payees = {p.name: p for p in client.budget.be_payees}
    mastercategories_perid = {m.id: m for m in client.budget.be_master_categories}
    subcategories = {}
    for s in client.budget.be_subcategories:
        m=mastercategories_perid[s.entities_master_category_id]
        subcategories[m.name+':'+s.name]=s

    def getaccount(accountname):
        try:
            logger.debug('searching for account %s' % accountname)
            return accounts[accountname]
        except KeyError:
            logger.error('Couldn''t find this account: %s' % accountname)
            exit(-1)

    def getpayee(payeename):
        try:
            logger.debug('searching for payee %s' % payeename)
            return payees[payeename]
        except KeyError:
            logger.debug('Couldn''t find this payee: %s' % payeename)
            payee=Payee(name=payeename)
            client.budget.be_payees.append(payee)
            return payee

    def getsubcategory(categoryname):
        try:
            logger.debug('searching for subcategory %s' % categoryname)
            return subcategories[categoryname]
        except KeyError:
            get_logger(args).debug('Couldn''t find this category: %s' % categoryname)
            exit(-1)

    if 'account' not in schema.headers:
        entities_account_id = getaccount(args.accountname).id

    if 'inflow' in schema.headers and 'outflow' in schema.headers:
        pass
    elif 'amount' in schema.headers:
        pass
    else:
        logger.error('This schema doesn''t provide an amount column or (inflow,outflow) columns')
        exit(-1)

    csvrow = namedtuple('CSVrow', field_names=schema.headers)
    transactions = []

    imported_date=datetime.now().date()

    get_logger(args).debug('OK starting the import from %s '%os.path.abspath(args.csvfile))
    with open(args.csvfile, 'r') as inputfile:
        header = inputfile.readline()
        for row in csv.reader(inputfile):
            if sys.version[0] == '2':
                row = [cell.decode('utf-8') for cell in row]
            if all(map(lambda x:x.strip()=='',row)):
                continue
            get_logger(args).debug('read line %s' % row)
            result = csvrow(*list(schema.convert_row(*row, fail_fast=True)))
            if 'account' in schema.headers:
                entities_account_id = getaccount(result.account).id
            if 'inflow' in schema.headers and 'outflow' in schema.headers:
                amount = result.inflow - result.outflow
            elif 'amount' in schema.headers:
                amount = result.amount
            else:
                get_logger(args).error('Couldn''t find this account: %s' % args.accountname)
                exit(-1)

            if 'category' in schema.headers and result.category:
                entities_subcategory_id = getsubcategory(result.category).id
            else:
                entities_subcategory_id = None
            if 'payee' in schema.headers:
                imported_payee=result.payee
            else:
                imported_payee=''
            entities_payee_id = getpayee(imported_payee).id
            if 'memo' in schema.headers:
                memo=result.memo
            else:
                memo=''


            transaction=Transaction(
                entities_account_id=entities_account_id,
                amount=amount,
                date=result.date,
                entities_payee_id=entities_payee_id,
                entities_subcategory_id=entities_subcategory_id,
                imported_date=imported_date,
                imported_payee=imported_payee,
                memo=memo,
                source="Imported"
            )
            if args.import_duplicates or (not client.budget.be_transactions.containsduplicate(transaction)):
                get_logger(args).debug('Appending transaction %s '%transaction.getdict())
                transactions.append(transaction)
            else:
                get_logger(args).debug('Duplicate transaction found %s '%transaction.getdict())



    client.add_transactions(transactions)
Esempio n. 25
0
 def test_hash(self):
     tr1 = Transaction()
     result = tr1._hash()
     self.assertIsInstance(result, int)
Esempio n. 26
0
 def testrepr(self):
     tr1 = Transaction(id='t')
     self.assertEqual(tr1.__repr__(), tr1.__str__())
Esempio n. 27
0
 def testCE_nochange(self):
     obj = Transaction(None)
     self.assertEqual(obj.get_changed_entities(), {})
Esempio n. 28
0
import itertools
import random

from datetime import datetime

from pynYNAB.Client import clientfromargs
from pynYNAB.schema.budget import Transaction
from pynYNAB.scripts.config import parser

# used to ping the nYNAB API to check that the sync works

args = parser.parse_known_args()[0]
N = 2
client = clientfromargs(args)
client.sync()
account = next(acc for acc in client.budget.be_accounts)
for _ in itertools.repeat(None, N):
    transaction = Transaction(cleared='Uncleared',
                              date=datetime.now(),
                              entities_account_id=account.id,
                              amount=random.randrange(-10, 10))
    client.add_transaction(transaction)
    client.sync()
Esempio n. 29
0
 def add_transaction(self, **kwargs):
     payee = self.get_payee(kwargs['payee'])
     subcategory = self.get_subcategory(kwargs['subcategory'])
     if not self.has_matching_transaction(kwargs['id']):
         transaction = Transaction()
         transaction.date = kwargs['date']
         transaction.memo = 'AUTO IMPORT - {}'.format(kwargs['id'])
         transaction.imported_payee = payee.name
         transaction.entities_payee_id = payee.id
         transaction.entities_subcategory_id = subcategory.id if subcategory else None
         transaction.imported_date = datetime.datetime.now().date()
         transaction.source = "Imported"
         transaction.amount = kwargs['value']
         transaction.entities_account_id = self.account.id
         self.client.budget.be_transactions.append(transaction)
         self.delta += 1
Esempio n. 30
0
    def testiimport(self):
        parser = configargparse.getArgumentParser('pynYNAB')
        args = parser.parse_known_args()[0]
        args.ofxfile = os.path.join(tempfile.gettempdir(), 'data.ofx')
        args.logginglevel = 'debug'

        self.client = clientfromargs(args)

        content = """OFXHEADER:100
DATA:OFXSGML
VERSION:102
SECURITY:NONE
ENCODING:USASCII
CHARSET:1252
COMPRESSION:NONE
OLDFILEUID:NONE
NEWFILEUID:NONE
<OFX>
<SIGNONMSGSRSV1>
<SONRS>
<STATUS>
<CODE>0
<SEVERITY>INFO
</STATUS>
<DTSERVER>20130313133728
<LANGUAGE>FRA
</SONRS>
</SIGNONMSGSRSV1>
<BANKMSGSRSV1>
<STMTTRNRS>
<TRNUID>29939615002
<STATUS>
<CODE>0
<SEVERITY>INFO
</STATUS>
<STMTRS>
<CURDEF>EUR
<BANKACCTFROM>
<BANKID>11706
<BRANCHID>41029
<ACCTID>29939615002
<ACCTTYPE>CHECKING
</BANKACCTFROM>
<BANKTRANLIST>
<DTSTART>20130128000000
<DTEND>20130314235959
<STMTTRN>
<TRNTYPE>CHECK
<DTPOSTED>20130312
<TRNAMT>-491.09
<FITID>13071099780237330004
<CHECKNUM>0003445
<NAME>CHEQUE
<MEMO>CHEQUE
</STMTTRN>
</BANKTRANLIST>
<LEDGERBAL>
<BALAMT>-6348.01
<DTASOF>20130312
</LEDGERBAL>
<AVAILBAL>
<BALAMT>-6348.01
<DTASOF>20130312
</AVAILBAL>
</STMTRS>
</STMTTRNRS>
</BANKMSGSRSV1>
</OFX>"""
        with open(args.ofxfile, 'w') as f:
            f.writelines(content)
        imported_date = datetime.now().date()

        testaccount = 'TEST'
        account = util_get_empty_account_by_name_if_doesnt_exist(
            self.client, testaccount)

        key = '11706 41029 29939615002'
        account.note = 'great note key[%s]key' % key
        self.client.sync()

        payee = util_add_payee_by_name_if_doesnt_exist(self.client, 'CHEQUE')
        amount = -491.09

        transaction = Transaction(entities_account=account,
                                  date=datetime(year=2013, month=3,
                                                day=12).date(),
                                  entities_payee=payee,
                                  imported_payee=payee,
                                  source='Imported',
                                  check_number='0003445',
                                  memo='CHEQUE    13071099780237330004',
                                  amount=amount,
                                  imported_date=imported_date)

        do_ofximport(args)
        self.reload()
        self.assertIn(
            transaction,
            self.client.budget.be_transactions,
            msg='couldnt find an imported transaction after ofx import')
Esempio n. 31
0
def do_csvimport(args, client):
    LOG.debug('selected schema %s' % (args.schema, ))

    LOG.debug('schema headers %s' % args.schema.headers)
    delta = 0

    accounts = {x.account_name: x for x in client.budget.be_accounts}
    payees = {p.name: p for p in client.budget.be_payees}
    mastercategories_perid = {
        m.id: m
        for m in client.budget.be_master_categories
    }
    subcategories = {}
    for s in client.budget.be_subcategories:
        m = mastercategories_perid[s.entities_master_category_id]
        subcategories[m.name + ':' + s.name] = s

    def getaccount(account_name):
        try:
            LOG.debug('searching for account %s' % account_name)
            return accounts[account_name]
        except KeyError:
            LOG.error('Couldn' 't find this account: %s' % account_name)
            exit(-1)

    def getpayee(payee_name):
        global delta
        try:
            LOG.debug('searching for payee %s' % payee_name)
            return payees[payee_name]
        except KeyError:
            LOG.debug('Couldn' 't find this payee: %s' % payee_name)
            payee = Payee(name=payee_name)
            client.budget.be_payees.append(payee)
            delta += 1
            return payee

    def getsubcategory(category_name):
        try:
            LOG.debug('searching for subcategory %s' % category_name)
            return subcategories[category_name]
        except KeyError:
            LOG.debug('Couldn' 't find this category: %s' % category_name)
            exit(-1)

    entities_account_id = None
    if 'account' not in args.schema.headers:
        entities_account_id = getaccount(args.account_name).id

    amount = None
    if 'inflow' in args.schema.headers and 'outflow' in args.schema.headers:
        pass
    elif 'amount' in args.schema.headers:
        pass
    else:
        LOG.error('This schema doesn'
                  't provide an amount column or (inflow,outflow) columns')
        exit(-1)

    csvrow = namedtuple('CSVrow', field_names=args.schema.headers)

    imported_date = datetime.now().date()

    LOG.debug('OK starting the import from %s ' %
              os.path.abspath(args.csv_file))
    with open(args.csv_file, 'r') as inputfile:
        header = []
        for i in range(0, args.schema.nheaders):
            header.append(inputfile.readline())
        for row in csv.reader(inputfile):
            if sys.version[0] == '2':
                row = [cell.decode('utf-8') for cell in row]
            if all(map(lambda x: x.strip() == '', row)):
                continue
            LOG.debug('read line %s' % row)
            result = csvrow(
                *list(args.schema.convert_row(*row, fail_fast=True)))
            if 'account' in args.schema.headers:
                entities_account_id = getaccount(result.account).id
            if entities_account_id is None:
                LOG.error(
                    'No account id, the account %s in the an account column was not recognized'
                    % result.account)
                exit(-1)
            if 'inflow' in args.schema.headers and 'outflow' in args.schema.headers:
                amount = result.inflow - result.outflow
            elif 'amount' in args.schema.headers:
                amount = result.amount

            if 'category' in args.schema.headers and result.category:
                entities_subcategory_id = getsubcategory(result.category).id
            else:
                entities_subcategory_id = None
            if 'payee' in args.schema.headers:
                imported_payee = result.payee
            else:
                imported_payee = ''
            entities_payee_id = getpayee(imported_payee).id
            if 'memo' in args.schema.headers:
                memo = result.memo
            else:
                memo = ''

            transaction = Transaction(
                entities_account_id=entities_account_id,
                cash_amount=amount,
                amount=amount,
                date=result.date,
                entities_payee_id=entities_payee_id,
                entities_subcategory_id=entities_subcategory_id,
                imported_date=imported_date,
                imported_payee=imported_payee,
                memo=memo,
                source="Imported")

            if args.import_duplicates or not (transaction.key2 in [
                    tr.key2 for tr in client.budget.be_transactions
            ]):
                LOG.debug('Appending transaction %s ' % transaction.get_dict())
                client.budget.be_transactions.append(transaction)
                delta += 1
            else:
                LOG.debug('Duplicate transaction found %s ' %
                          transaction.get_dict())

    return delta
Esempio n. 32
0
def create_transaction_from_monzo(data, settings=settings_module, ynab_client = ynab_client_module):
    settings.log.debug('received data %s' % data)
    expected_delta = 0
    data_type = data.get('type')
    settings.log.debug('webhook type received %s', data_type)
    if data_type != 'transaction.created':
        return {'error': 'Unsupported webhook type: %s' % data_type}, 400

    # the actual monzo data is in the data['data]' value
    data = data['data']

    if 'decline_reason' in data:
        return {'message': 'Ignoring declined transaction ({})'.format(data['decline_reason'])}, 200

    # Sync the account so we get the latest payees
    ynab_client.sync()

    if data['amount'] == 0:
        return {'error': 'Transaction amount is 0.'}, 200

    # Does this account exist?
    account = ynab_client.getaccount(settings.monzo_ynab_account)
    if not account:
        return {'error': 'Account {} was not found'.format(settings.monzo_ynab_account)}, 400

    # Work out the Payee Name
    if data.get('merchant'):
        payee_name = data['merchant']['name']
        subcategory_id = get_subcategory_from_payee(payee_name)
    else:
        # This is a p2p transaction
        payee_name = get_p2p_transaction_payee_name(data)
        subcategory_id = None

    # If we are creating the payee, then we need to increase the delta
    if not ynab_client.payeeexists(payee_name):
        settings.log.debug('payee does not exist, will create %s', payee_name)
        expected_delta += 1

    # Get the payee ID. This will append a new one if needed
    entities_payee_id = ynab_client.getpayee(payee_name).id

    memo = ''
    if settings.include_emoji and data['merchant'] and data['merchant'].get('emoji'):
        memo += ' %s' % data['merchant']['emoji']

    if settings.include_tags and data['merchant'] and data['merchant'].get('metadata', {}).get('suggested_tags'):
        memo += ' %s' % data['merchant']['metadata']['suggested_tags']

    # Show the local currency in the notes if this is not in the accounts currency
    flag = None
    cleared = None
    if data['local_currency'] != data['currency']:
        memo += ' (%s %s)' % (data['local_currency'], (abs(Decimal(data['local_amount'])) / 100))
        flag = 'Orange'
    else:
        cleared = 'Cleared'

    # Create the Transaction
    expected_delta += 1
    settings.log.debug('Creating transaction object')
    transaction = Transaction(
        check_number=data['id'],
        entities_account_id=account.id,
        amount=Decimal(data['amount']) / 100,
        date=parse(data['created']),
        entities_payee_id=entities_payee_id,
        imported_date=datetime.now().date(),
        imported_payee=payee_name,
        memo=memo,
        flag=flag,
        cleared=cleared
    )

    if subcategory_id is not None:
        transaction.entities_subcategory_id = subcategory_id

    settings.log.debug('Duplicate detection')
    if ynab_client.containsDuplicate(transaction):
        settings.log.debug('skipping due to duplicate transaction')
        return {'error': 'Tried to add a duplicate transaction.'}, 200
    else:
        settings.log.debug('appending and pushing transaction to YNAB. Delta: %s', expected_delta)
        ynab_client.client.budget.be_transactions.append(transaction)
        ynab_client.client.push(expected_delta)
        return {'message': 'Transaction created in YNAB successfully.'}, 201
Esempio n. 33
0
def create_transaction_from_starling(data, settings=settings_module, ynab_client = ynab_client_module):
    settings.log.debug('received data %s'%data)
    expected_delta = 0
    if not data.get('content') or not data['content'].get('type'):
        return {'error': 'No webhook content type provided'}, 400
    if not data.get('content') or not data['content'].get('type') or not data['content']['type'] in ['TRANSACTION_CARD', 'TRANSACTION_FASTER_PAYMENT_IN', 'TRANSACTION_FASTER_PAYMENT_OUT',
                                'TRANSACTION_DIRECT_DEBIT']:
        return {'error': 'Unsupported webhook type: %s' % data.get('content')['type']}, 400
    # Sync the account so we get the latest payees
    ynab_client.sync()

    if data['content']['amount'] == 0:
        return {'error': 'Transaction amount is 0.'}, 200

    # Does this account exist?
    account = ynab_client.getaccount(settings.starling_ynab_account)
    if not account:
        return {'error': 'Account {} was not found'.format(settings.starling_ynab_account)}, 400


    payee_name = data['content']['counterParty']
    subcategory_id = None
    flag = None
    cleared = None
    memo = ''

    # If we are creating the payee, then we need to increase the delta
    if ynab_client.payeeexists(payee_name):
        settings.log.debug('payee exists, using %s', payee_name)
        subcategory_id = get_subcategory_from_payee(payee_name)
    else:
        settings.log.debug('payee does not exist, will create %s', payee_name)
        expected_delta += 1

    entities_payee_id = ynab_client.getpayee(payee_name).id

    if data['content']['sourceCurrency'] != 'GBP':
        memo += ' (%s %s)' % (data['content']['sourceCurrency'], abs(data['content']['sourceAmount']))
        flag = 'Orange'
    else:
        cleared = 'Cleared'

    # Create the Transaction
    expected_delta += 1
    settings.log.debug('Creating transaction object')
    transaction = Transaction(
        check_number=data['content'].get('transactionUid'),
        entities_account_id=account.id,
        amount=data['content']['amount'],
        date=parse(data['timestamp']),
        entities_payee_id=entities_payee_id,
        imported_date=datetime.now().date(),
        imported_payee=payee_name,
        flag=flag,
        cleared=cleared,
        memo=memo
    )

    if subcategory_id is not None:
        transaction.entities_subcategory_id = subcategory_id

    settings.log.debug('Duplicate detection')
    if ynab_client.containsDuplicate(transaction):
        settings.log.debug('skipping due to duplicate transaction')
        return {'error': 'Tried to add a duplicate transaction.'}, 200
    else:
        expected_delta += 1
        settings.log.debug('appending and pushing transaction to YNAB. Delta: %s', expected_delta)
        ynab_client.client.budget.be_transactions.append(transaction)
        ynab_client.client.push(expected_delta)
        return {'message': 'Transaction created in YNAB successfully.'}, 201
Esempio n. 34
0
 def test_hash(self):
     tr1 = Transaction()
     result = tr1._hash()
     self.assertIsInstance(result, int)