def mock_fints_transaction(purpose, applicant_name, posting_text):
    amount = -50.00
    date_day = 10
    date_month = 11
    date_year = 2019
    return {
        'status': 'D',
        'funds_code': 'R',
        'amount': Amount(str(amount), 'D', 'EUR'),
        'id': 'N010',
        'extra_details': '',
        'currency': 'EUR',
        'date': Date(year=date_year, month=date_month, day=date_day),
        'entry_date': Date(year=date_year, month=date_month, day=date_day),
        'guessed_entry_date': Date(year=date_year, month=date_month, day=date_day),
        'transaction_code': '100',
        'posting_text': posting_text,
        'prima_nota': '0000',
        'purpose': purpose,
        'applicant_bin': 'ABCDEFMMXXX',
        'applicant_iban': 'DE12345678912345678901',
        'applicant_name': applicant_name,
        'return_debit_notes': '011',
        'deviate_applicant': 'REWE SAGT DANKE. 192841//Stadt/DE'
    }
Beispiel #2
0
    def test_raise_error_without_matching_account(self):
        '''should raise an exception when the account can not be found online'''
        clientMock = Mock()
        account1Mock = Mock()
        account1Mock.accountnumber = "some account"
        clientMock.get_sepa_accounts.return_value = [account1Mock]
        retriever = TRetriever(clientMock, "selected account")

        with self.assertRaises(Exception) as context:
            retriever.get_hbci_transactions(Date(2017, 2, 2), Date(2017, 3, 3))

        self.assertIn("Could not find a matching account",
                      str(context.exception))
Beispiel #3
0
    def test_calls_returns_correct_transaction(self):
        '''retrieved should return a transaction with data, amount and details from the hcbi data'''
        selectedAccount = "selected account"
        hbciData = Mock()

        clientMock = Mock()
        account1Mock = Mock()
        account1Mock.accountnumber = selectedAccount
        clientMock.get_sepa_accounts.return_value = [account1Mock]
        clientMock.get_transactions.return_value = [hbciData]
        retriever = TRetriever(clientMock, selectedAccount)

        result = retriever.get_hbci_transactions(Date(2017, 2, 2),
                                                 Date(2017, 3, 3))

        self.assertEqual(result[0], hbciData)
    def test_uses_date_format(self):
        fintsTransaction = {
            "date": Date(2017, 11, 1),
            "amount": Amount('44', 'D', 'EUR'),
            "applicant_name": None,
            "posting_text": None,
            "purpose": None
        }
        hbciData = Mock()

        hbciData.data = {**fintsTransaction, "date": Date(2017, 11, 1)}
        result1 = CsvConverter(",", "%Y/%m/%d").convert(hbciData)

        hbciData.data = {**fintsTransaction, "date": Date(2017, 11, 1)}
        result2 = CsvConverter(",", "%Y-%m-%d").convert(hbciData)

        self.assertIn("2017/11/01", result1)
        self.assertIn("2017-11-01", result2)
Beispiel #5
0
    def test_calls_client_with_select_account(self):
        '''retriever should get the transactions of the client with the selected account,
        when the client has two accounts'''
        startDate = Date(2017, 1, 1)
        endDate = Date(2017, 2, 1)
        selectedAccount = "selected account"

        clientMock = Mock()
        account1Mock = Mock()
        account1Mock.accountnumber = selectedAccount
        account2Mock = Mock()
        account2Mock.accountnumber = "other account"
        clientMock.get_sepa_accounts.return_value = [
            account1Mock, account2Mock
        ]
        clientMock.get_transactions.return_value = []
        retriever = TRetriever(clientMock, selectedAccount)

        retriever.get_hbci_transactions(startDate, endDate)

        clientMock.get_transactions.assert_called_with(account1Mock, startDate,
                                                       endDate)
Beispiel #6
0
    def test_convert_with_missing_values(self):
        fintsTransaction = {
            "date": Date(2017, 11, 1),
            "amount": Amount('44', 'D', 'EUR'),
            "applicant_name": None,
            "posting_text": None,
            "purpose": None
        }
        hbciData = Mock()
        hbciData.data = fintsTransaction

        csv_result = self.csvConverter.convert(hbciData)
        entries = csv_result.split(",")

        self.assertEquals(['2017/11/01', '-44', 'EUR', '', '', ''], entries)
Beispiel #7
0
    def retrieveAndSave(self):
        client = FinTS3PinTanClient(
            self.config["fints"]["blz"],  # Your bank's BLZ
            self.config["fints"]["account"],  # your account number
            self.config["fints"]["password"],
            # e.g. 'https://fints.ing-diba.de/fints/'
            self.config["fints"]["endpoint"])

        retriever = TRetriever(client, self.config["fints"]["selectedAccount"])
        converter = CsvConverter(self.config["fints"]["csv_separator"])

        csv_output = "\n".join(
            map(
                lambda transaction: converter.convert(transaction),
                retriever.get_hbci_transactions(self.config["fints"]["start"],
                                                Date.today())))

        with open(self.config["files"]["csv_file"], 'w') as f:
            f.write(converter.get_headline())
            f.write("\n")
            f.write(csv_output)
Beispiel #8
0
    def test_convert_to_csv(self):
        expected_purpose = "purchased book"
        expected_applicant_name = "book store"
        expected_posting_text = "posting text"
        expected_date = Date(2017, 11, 1)
        expected_amount = Amount('44', 'D', 'EUR')
        fintsTransaction = {
            "date": expected_date,
            "amount": expected_amount,
            "applicant_name": expected_applicant_name,
            "posting_text": expected_posting_text,
            "purpose": expected_purpose
        }
        hbciData = Mock()
        hbciData.data = fintsTransaction

        csv_result = self.csvConverter.convert(hbciData)
        entries = csv_result.split(",")

        self.assertIn(expected_purpose, entries)
        self.assertIn(expected_applicant_name, entries)
        self.assertIn(expected_posting_text, entries)
        self.assertIn("2017/11/01", entries)
        self.assertIn("-44", entries)
Beispiel #9
0
    def get_config(self):
        parser = argparse.ArgumentParser(
            description='Converting transactions from fints apis to ledger.')
        parser.add_argument(
            '--no-csv',
            dest='convert_to_csv',
            action='store_const',
            const=False,
            default=True,
            help='exclude conversion from fints to csv (default: not excluded)'
        )
        parser.add_argument(
            '--no-ledger',
            dest='convert_to_ledger',
            action='store_const',
            const=False,
            default=True,
            help='exclude conversion from csv to ledger (default: not excluded)'
        )
        parser.add_argument(
            '--csv-file',
            dest='csvfile',
            action='store',
            default="transactions.csv",
            help=
            'file to store/load csv transactions to/from (default: transactions.csv)'
        )
        parser.add_argument(
            '--ledger-file',
            dest='ledgerfile',
            action='store',
            default="journal.ledger",
            help='file to store ledger entries to (default: ledger.journal)')
        parser.add_argument(
            '--files-path',
            dest='files_path',
            action='store',
            default="~/.config/fints2ledger/",
            help=
            'directory to store fints2ledger files (like config.yml) (default: ~/.config/fints2ledger/)'
        )
        parser.add_argument(
            '--date',
            dest='start',
            action='store',
            default=None,
            help=
            'start date to pull the FinTS entries from (format: 2017/12/31 or 17/12/31, default: last year)'
        )
        parser.add_argument(
            '--separator',
            dest='separator',
            action='store',
            default=";",
            help='character used as separator in csv file (default: ;)')
        parser.add_argument(
            '--csv_date_format',
            dest='csv_date_format',
            action='store',
            default='%Y/%m/%d',
            help=
            'Date format used in the donwloaded csv (and subsequently the ledger file). hledger supports 3 date formats (https://hledger.org/1.9/journal.html#simple-dates). Format needs to be compatible with pythons strftime(), see https://docs.python.org/3/library/datetime.html#strftime-strptime-behavior (fints.csv_date_format in config.yml) (default: %%Y/%%m/%%d)'
        )
        args = parser.parse_args()
        command_line_config = {
            "fints": {
                "start":
                utils.date_string_to_mt940_date(args.start)
                if args.start else Date(Date.today().year - 1,
                                        Date.today().month,
                                        Date.today().day),
                "csv_separator":
                args.separator,
                "csv_date_format":
                args.csv_date_format,
                "convert_to_csv":
                args.convert_to_csv
            },
            "ledger": {
                "convert_to_ledger": args.convert_to_ledger
            },
            "files": {
                "csv_file": os.path.expanduser(args.csvfile),
                "ledger_file": os.path.expanduser(args.ledgerfile),
                "files_path": os.path.expanduser(args.files_path)
            }
        }

        self.files_path = command_line_config["files"]["files_path"]

        self.setup_files()
        config = self.load_config_file()

        if not "selectedAccount" in config["fints"]:
            config["fints"]["selectedAccount"] = config["fints"]["account"]

        return utils.update_dict(command_line_config, config)
Beispiel #10
0
    def get_config(self):
        parser = argparse.ArgumentParser(
            description='Converting transactions from fints apis to ledger.')
        parser.add_argument(
            '--no-csv',
            dest='convert_to_csv',
            action='store_const',
            const=False,
            default=True,
            help='exclude conversion from fints to csv (default: not excluded)'
        )
        parser.add_argument(
            '--no-ledger',
            dest='convert_to_ledger',
            action='store_const',
            const=False,
            default=True,
            help='exclude conversion from csv to ledger (default: not excluded)'
        )
        parser.add_argument(
            '--csv-file',
            dest='csvfile',
            action='store',
            default="transactions.csv",
            help=
            'file to store/load csv transactions to/from (default: transactions.csv)'
        )
        parser.add_argument(
            '--ledger-file',
            dest='ledgerfile',
            action='store',
            default="journal.ledger",
            help='file to store ledger entries to (default: ledger.journal)')
        parser.add_argument(
            '--date',
            dest='start',
            action='store',
            default=None,
            help=
            'start date to pull the FinTS entires from (fromat: 2017/12/31 or 17/12/31, default: last year)'
        )
        parser.add_argument(
            '--separator',
            dest='separator',
            action='store',
            default=";",
            help='character used as separator in csv file (default: ;)')
        args = parser.parse_args()
        command_line_config = {
            "fints": {
                "start":
                utils.date_string_to_mt940_date(args.start)
                if args.start else Date(Date.today().year - 1,
                                        Date.today().month,
                                        Date.today().day),
                "csv_separator":
                args.separator,
                "convert_to_csv":
                args.convert_to_csv
            },
            "ledger": {
                "convert_to_ledger": args.convert_to_ledger
            },
            "files": {
                "csv_file": args.csvfile,
                "ledger_file": args.ledgerfile
            }
        }

        self.setup_files()
        config = self.load_config_file()

        return utils.update_dict(config, command_line_config)
        'currency': 'EUR',
        'date': Date(year=date_year, month=date_month, day=date_day),
        'entry_date': Date(year=date_year, month=date_month, day=date_day),
        'guessed_entry_date': Date(year=date_year, month=date_month, day=date_day),
        'transaction_code': '100',
        'posting_text': posting_text,
        'prima_nota': '0000',
        'purpose': purpose,
        'applicant_bin': 'ABCDEFMMXXX',
        'applicant_iban': 'DE12345678912345678901',
        'applicant_name': applicant_name,
        'return_debit_notes': '011',
        'deviate_applicant': 'REWE SAGT DANKE. 192841//Stadt/DE'
    }

date = Date(year=2019, month=11, day=10)

@pytest.fixture
def mock_settings_file_path():
    return 'settings.sample.json'

@pytest.fixture
def mock_fints_transaction_regular():
    return mock_fints_transaction('2020-01-01T10.00Debitk.1 2020-01', 'REWE Regiemarkt GmbH', 'DIG. KARTE (APPLE PAY)')

@pytest.fixture
def mock_fints_transaction_cash():
    return mock_fints_transaction('2020-01-01T10.00Debitk.1 2020-01', 'SPARKASSE STADT', 'BARGELDAUSZAHLUNG')

@pytest.fixture
def mock_fints_transaction_paypal():
Beispiel #12
0
def date_string_to_mt940_date(date_string):
    parts = date_string.split("/")
    return Date(year=parts[0], month=parts[1], day=parts[2])
Beispiel #13
0
    def test_convert_mt940_date_17(self):
        '''should correctly convert the string 17/12/31 to a mt940 date by adding 2000 to the year'''

        result = utils.date_string_to_mt940_date("17/12/31")

        self.assertEqual(result, Date(year="2017", month="12", day="31"))