Giter Club home page Giter Club logo

banking's Introduction

ALYF Banking

ALYF Banking is a seamless solution for connecting your bank accounts with ERPNext.

This app is designed to simplify your financial management by effortlessly fetching transactions from thousands of banks and integrating them directly into your ERPNext system. Say goodbye to manual data entry and time-consuming reconciliations ✨

Experience the ease of automation and gain better control over your finances with the ultimate banking integration app for ERPNext users.


Note: Our improved Bank Reconciliation Tool is free to use and compatible with other bank integrations. The Bank Integration works with a paid subscription. Visit banking.alyf.de to check out the pricing and sign up.

Documentation

Check out the Banking Wiki for a step-by-step guide on how to use the app.

Country and Bank Coverage

Currently, we support more than 15.000 banks from the following countries.

  • 🇦🇹 Austria
  • 🇧🇪 Belgium
  • 🇭🇷 Croatia
  • 🇨🇿 Czech Republic
  • 🇩🇰 Denmark
  • 🇪🇪 Estonia
  • 🇫🇮 Finland
  • 🇫🇷 France
  • 🇩🇪 Germany
  • 🇭🇺 Hungary
  • 🇮🇪 Ireland
  • 🇮🇹 Italy
  • 🇱🇻 Latvia
  • 🇱🇹 Lithuania
  • 🇱🇺 Luxembourg
  • 🇲🇹 Malta
  • 🇳🇱 Netherlands
  • 🇳🇴 Norway
  • 🇵🇱 Poland
  • 🇵🇹 Portugal
  • 🇷🇴 Romania
  • 🇸🇰 Slovakia
  • 🇪🇸 Spain
  • 🇸🇪 Sweden
  • 🇨🇭 Switzerland
  • 🇬🇧 United Kingdom

Installation

Install via Frappe Cloud or on your local bench:

bench get-app https://github.com/alyf-de/banking.git
bench --site <sitename> install-app banking

banking's People

Contributors

marination avatar barredterra avatar alyf-linus avatar semantic-release-bot avatar kerollesfathy avatar

Stargazers

Mourad Maatoug avatar  avatar abanoubjohnny avatar dgo2dance avatar  avatar Satyam Maurya avatar Smrutiranjan Sahu avatar  avatar edsqjr avatar Samuel Danieli avatar  avatar Apoorv Soral avatar  avatar Lakshit Jain avatar Redemption avatar Donald Chinhuru avatar Frisbi avatar Rushabh Mehta avatar  avatar  avatar  avatar  avatar  avatar Fabian avatar Syed Hasan raza avatar  avatar  avatar gruener avatar avc avatar  avatar Muhammad Nouman avatar Govind Jangid avatar Robin Rosenstock avatar gavin avatar  avatar HENRY Florian avatar Mohamed Abdulsalam avatar MohsinAli avatar

Watchers

MohsinAli avatar  avatar GGRaza avatar  avatar

banking's Issues

[architecture] separate consent from bank

Currently, consent is stored in the Bank DocType.

In a multi company setup, companies might have accounts at the same bank, each needing separate consent. Therefore, I think we should separate consent into its own DocType (similar to Token Cache in the Frappe Framework).

Validate Reconciliation Amounts

Make sure that, in total, we don't move more money than can be found in the Bank Transaction. I. e. if the Bank transaction is for $100, it should not be possible to reconcile $75 and create a journal entry for $80, because the sum is > $100

Make "Match Voucher" clear and responsive

Problem

We have too much data in the horizontal direction to fit into the "Match Voucher" tab as a table. On my big screen, I can only see five of seven columns, which makes it look a bit convoluted and requires horizontal scrolling, which is unusual.

Proposed solution

  • Render each Bank Transaction as a card.
  • Cards use the full width of the "Match Voucher" tab (minus some padding) and are stacked vertically.
  • Have a "Reconcile" button on every card.
  • Display the match reasons by highlighting the data points in bold and/or color?

Support for v15

  • Create a version-15 branch
  • Make sure all functionality is working correctly
  • Change versioning from 0.0.n to (14.0.n, 15.0.n)
  • Publish on FC
  • Going forward, new development should target v15 and get backported to v14

Error while re-linking bank account

Reproduce

Go to Banking Settings, click on "Link Bank and Accounts", select a Company, select a Date (middle of current month), select your bank, authenticate.

Bildschirmfoto 2023-12-28 um 00 19 46

Error Log (server side)

{
  "name": 236,
  "owner": "[email protected]",
  "creation": "2023-12-28 00:19:31.571733",
  "modified": "2023-12-28 00:19:31.571733",
  "modified_by": "[email protected]",
  "docstatus": 0,
  "idx": 0,
  "seen": 1,
  "method": "Kosma Error",
  "error": "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n<HTML><HEAD><META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=iso-8859-1\">\n<TITLE>ERROR: The request could not be satisfied</TITLE>\n</HEAD><BODY>\n<H1>403 ERROR</H1>\n<H2>The request could not be satisfied.</H2>\n<HR noshade size=\"1px\">\nBad request.\nWe can't connect to the server for this app or website at this time. There might be too much traffic or a configuration error. Try again later, or contact the app or website owner.\n<BR clear=\"all\">\nIf you provide content to customers through CloudFront, you can find steps to troubleshoot and help prevent this error by reviewing the CloudFront documentation.\n<BR clear=\"all\">\n<HR noshade size=\"1px\">\n<PRE>\nGenerated by cloudfront (CloudFront)\nRequest ID: RvNF-2wRGYPlGJDwnUZFcdc1HbjyhGGqGYRz50vnN6GW5comDzVrIA==\n</PRE>\n<ADDRESS>\n</ADDRESS>\n</BODY></HTML>",
  "doctype": "Error Log"
}

Error Log (client side)

{
  "name": "a0067b7efa",
  "owner": "[email protected]",
  "creation": "2023-12-28 00:19:31.702828",
  "modified": "2023-12-28 00:19:31.702828",
  "modified_by": "[email protected]",
  "docstatus": 0,
  "idx": 0,
  "seen": 1,
  "method": "Banking Error",
  "error": "{\"exc_type\":\"DoesNotExistError\",\"message\":{\"error\":{\"message\":\"Something went wrong. Please retry in some time.\"},\"session_state\":\"Closed\"}}",
  "doctype": "Error Log"
}

Reconcile partial payments with unpaid Sales Invoice

Reproduce

  1. Create a Sales Invoice of $100
  2. Create two Bank Transactions with a deposit of $50 each
  3. Use the Bank Reconciliation Tool to match unpaid invoices

Problem

  • When selecting the first Bank Transaction and the unpaid Sales Invoice from Step (1), the Bank Reconciliation Tool shows "Amount: 50, Allocated: 100, Outstanding: -50". I guess the following would make more sense: "Amount: 50, Allocated: 50, Outstanding: 0"
  • When clicking "Reconcile", a Payment Entry for the full invoice amount ($100) is created, marking the Sales Invoice as fully paid. -> At this time, the Sales Invoice is only partially paid. The Payment Entry should be for $50.
  • The second Bank Transaction can no longer be reconciled with a (partially paid) Sales Invoice. We now have to reconcile it with the incorrect Payment Entry.

Offer return invoices for matching

Use case

We receive a purchase invoice for $100 and, before the first invoice is paid, a credit note for $10. We create a bank transfer for the outstanding $90.

Problem

The credit note does not show up in the bank reconciliation tool. We could only reconcile with the $100 invoice and would leave the $10 unreconciled. Instead, we have to take the long route of creating a Payment Entry in the full form and fetching outstanding invoices there.

Proposed Solution

Show unpaid return invoices as well:

def get_unpaid_pi_matching_query(exact_match, exact_party_match, currency, company):
	purchase_invoice = frappe.qb.DocType("Purchase Invoice")

	party_condition = purchase_invoice.supplier == Parameter("%(party)s")
	party_match = frappe.qb.terms.Case().when(party_condition, 1).else_(0)

	grand_total_condition = purchase_invoice.grand_total == Parameter("%(amount)s")
	amount_match = frappe.qb.terms.Case().when(grand_total_condition, 1).else_(0)

	query = (
		frappe.qb.from_(purchase_invoice)
		.select(
			(party_match + amount_match + 1).as_("rank"),
			ConstantColumn("Purchase Invoice").as_("doctype"),
			purchase_invoice.name.as_("name"),
			purchase_invoice.outstanding_amount.as_("paid_amount"),
			purchase_invoice.bill_no.as_("reference_no"),
			purchase_invoice.bill_date.as_("reference_date"),
			purchase_invoice.supplier.as_("party"),
			ConstantColumn("Supplier").as_("party_type"),
			purchase_invoice.posting_date,
			purchase_invoice.currency,
			party_match.as_("party_match"),
			amount_match.as_("amount_match"),
		)
		.where(purchase_invoice.docstatus == 1)
		.where(purchase_invoice.company == company)
-		.where(purchase_invoice.is_return == 0)
-		.where(purchase_invoice.outstanding_amount > 0.0)
+		.where(purchase_invoice.outstanding_amount != 0.0)
		.where(purchase_invoice.currency == currency)
	)

	if exact_match:
		query = query.where(grand_total_condition)
	if exact_party_match:
		query = query.where(party_condition)

	return str(query)

The same applies to Sales Invoice.

Party Type and Party filters

The top level Party Type and Party filters seem to be used by the "Auto Matching" button only. Let's consider them as filters as well or remove them.

Fetching older transactions breaks in production env

Fails at accounts fetch stage > says bank consent is revoked

Solution from support:

Our responsible team informs us that if you can you should remove the ACCOUNT scope from the auth request and not perform an accounts call. This will fix the issue.

Format Reference Date as per System Settings

Problem

The Reference Date in the "Match Voucher" tab's datatable is currently displayed as ISO string. This makes it hard to visually match the correctly formatted transaction date in the list of Bank Transactions.

Proposed solution

Format the Reference Date column as per System Settings.

Also, let's add Reference Date to the match reasons and ranking.

Journal Entries not submitted

Reproduce

  1. Open "Bank Reconciliation Tool Beta"
  2. Select unreconciled transaction
  3. Open tab "Create Voucher"
  4. Select Document Type "Journal Entry"
  5. Select appropriate Account
  6. Click on "Create"

Expected

The Journal Entry is submitted and reconciled with the Bank Transaction.

Actual

The Journal Entry is saved as draft and not reconciled with the Bank Transaction.

Versions

Frappe Framework: v14.68.2
ERPNext: v14.65.7
ALYF Banking: v0.1.1

Auto Reconcile button not working

when clicked on auto reconcile button using Bank Reconciliation Tool Beta

WhatsApp Image 2024-04-24 at 2 03 43 PM

I think the solution will be adding common_filters parameter to get_matching_queries

Error in Loan Disbursement query

File "apps/frappe/frappe/app.py", line 95, in application
    response = frappe.api.handle()
  File "apps/frappe/frappe/api.py", line 54, in handle
    return frappe.handler.handle()
  File "apps/frappe/frappe/handler.py", line 47, in handle
    data = execute_cmd(cmd)
  File "apps/frappe/frappe/handler.py", line 85, in execute_cmd
    return frappe.call(method, **frappe.form_dict)
  File "apps/frappe/frappe/__init__.py", line 1622, in call
    return fn(*args, **newargs)
  File "apps/banking/banking/klarna_kosma_integration/doctype/bank_reconciliation_tool_beta/bank_reconciliation_tool_beta.py", line 339, in get_linked_payments
    matching = check_matching(
  File "apps/banking/banking/klarna_kosma_integration/doctype/bank_reconciliation_tool_beta/bank_reconciliation_tool_beta.py", line 406, in check_matching
    get_loan_vouchers(bank_account, transaction, document_types, filters)
  File "apps/banking/banking/klarna_kosma_integration/doctype/bank_reconciliation_tool_beta/bank_reconciliation_tool_beta.py", line 544, in get_loan_vouchers
    vouchers.extend(get_ld_matching_query(bank_account, exact_match, filters))
  File "apps/banking/banking/klarna_kosma_integration/doctype/bank_reconciliation_tool_beta/bank_reconciliation_tool_beta.py", line 656, in get_ld_matching_query
    vouchers = query.run(as_dict=True)
  File "apps/frappe/frappe/query_builder/utils.py", line 87, in execute_query
    result = frappe.db.sql(query, params, *args, **kwargs)  # nosemgrep
  File "apps/frappe/frappe/database/database.py", line 220, in sql
    self._cursor.execute(query, values)
  File "env/lib/python3.10/site-packages/pymysql/cursors.py", line 156, in execute
    query = self.mogrify(query, args)
  File "env/lib/python3.10/site-packages/pymysql/cursors.py", line 134, in mogrify
    query = query % self._escape_args(args, conn)
KeyError: 'date'

The error occurs immediately after activating the "Loan Disbursement" filter:

Bildschirmfoto 2023-10-03 um 19 41 07

Fetch select accounts only

Some Users do not want to fetch all accounts from the bank. Eg. Bank Sparkasse has some business and private accounts but we only want the business accounts fetched into ERPNext.

The workaround is to delete the unwanted fetched accounts but every Re-link, users will have to keep deleting unwanted accounts

Solution:

  • Prompt for IBANS optionally on clicking on "Link Bank and Accounts"
  • The scope will be limited to mentioned accounts only
  • Can also store the permitted IBANS in the Bank doctype so users don't have to keep re-adding them

Load balancing

banking/banking/hooks.py

Lines 117 to 121 in 5cdcfeb

scheduler_events = {
"daily": [
"banking.klarna_kosma_integration.doctype.banking_settings.banking_settings.sync_all_accounts_and_transactions"
],
}

With enough clients in the same timezone, this basically launches a DDOS attack on our backend server every day.

Spikes at midnight, for the past 7 days:

Bildschirmfoto 2023-11-12 um 19 12 21

We should try to find a way of making this run, say, at a random time between 22pm and 6am.

Billing / API access

We want to charge for usage of our API keys.

  • Create a basic customer portal
  • The user needs to sign up with our portal
  • Once logged in, they can purchase a subscription via stripe
  • Stripe notifies our portal on receipt of payment
  • We issue an API key to the user
  • The user enters their API key in the Banking Settings
  • For every Kosma request, we first call the customer portal with the user's API Key. If they have an active subscription, this yields the Kosma API Key and max transactions included.
  • Rotate Kosma keys regularly

Bildschirmfoto 2023-03-29 um 09 03 14

Feature Request - Setting for Selecting the date of payment entry.

Here is the use case -
The customer makes payment on 1 Nov
The account department does reco activity on 3 Nov
Payment Entry for that payment was created on 3 Nov
Customer Scorecard/Rating gets affected due to delay in payment.

Feature Request:-
Check the box in the Reco tool setting page -

  • Make Payment entry on the transaction date.

Add unit tests for Bank Reconciliation Tool

Test cases:

  • reconcile a bank transaction with a payment voucher
  • reconcile a bank transaction with multiple payment vouchers
  • reconcile multiple bank transactions with a payment voucher
  • reconcile a bank transaction with an unpaid invoice
  • reconcile a bank transaction with multiple unpaid invoices
  • reconcile multiple bank transactions with an unpaid invoice
  • reconcile a bank transaction by creating a payment entry
  • reconcile a bank transaction by creating a journal entry
  • partially reconcile a bank transaction with an unpaid invoice and create a journal entry for the remaining amount
  • partially reconcile a bank transaction with an unpaid invoice and create a payment entry for the remaining amount

Error after installation: ModuleNotFoundError: No module named 'banking'

Hi!
I set up a self hosted ERPnext 15 installation on a Hetzner ARM VPS to learn and test the system.
Installation of "banking" went through without errors.
Now when accessing the ERPnext app in the browser, this error gets thrown...

Traceback (most recent call last):
  File "/home/frappe/frappe-bench/apps/frappe/frappe/website/serve.py", line 17, in get_response
    endpoint, renderer_instance = path_resolver.resolve()
  File "/home/frappe/frappe-bench/apps/frappe/frappe/website/path_resolver.py", line 37, in resolve
    resolve_redirect(self.path, request.query_string)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/website/path_resolver.py", line 108, in resolve_redirect
    redirects += frappe.get_all("Website Route Redirect", ["source", "target"], order_by=None)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/__init__.py", line 1974, in get_all
    return get_list(doctype, *args, **kwargs)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/__init__.py", line 1949, in get_list
    return frappe.model.db_query.DatabaseQuery(doctype).execute(*args, **kwargs)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/model/db_query.py", line 179, in execute
    if is_virtual_doctype(self.doctype):
  File "/home/frappe/frappe-bench/apps/frappe/frappe/utils/caching.py", line 123, in site_cache_wrapper
    return func(*args, **kwargs)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/model/utils/__init__.py", line 133, in is_virtual_doctype
    if frappe.db.has_column("DocType", "is_virtual"):
  File "/home/frappe/frappe-bench/env/lib/python3.10/site-packages/werkzeug/local.py", line 311, in __get__
    obj = instance._get_current_object()
  File "/home/frappe/frappe-bench/env/lib/python3.10/site-packages/werkzeug/local.py", line 490, in _get_current_object
    raise RuntimeError(unbound_message) from None
RuntimeError: object is not bound

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/frappe/frappe-bench/apps/frappe/frappe/middlewares.py", line 16, in __call__
    return super().__call__(environ, start_response)
  File "/home/frappe/frappe-bench/env/lib/python3.10/site-packages/werkzeug/middleware/shared_data.py", line 249, in __call__
    return self.app(environ, start_response)
  File "/home/frappe/frappe-bench/env/lib/python3.10/site-packages/werkzeug/middleware/shared_data.py", line 249, in __call__
    return self.app(environ, start_response)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/app.py", line 74, in application
    app(environ, start_response),
  File "/home/frappe/frappe-bench/env/lib/python3.10/site-packages/werkzeug/wrappers/request.py", line 189, in application
    resp = f(*args[:-2] + (request,))
  File "/home/frappe/frappe-bench/apps/frappe/frappe/app.py", line 128, in application
    response = handle_exception(e)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/app.py", line 389, in handle_exception
    response = get_response("message", http_status_code=http_status_code)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/website/serve.py", line 26, in get_response
    response = ErrorPage(exception=e).render()
  File "/home/frappe/frappe-bench/apps/frappe/frappe/website/page_renderers/error_page.py", line 7, in __init__
    super().__init__(path=path, http_status_code=http_status_code)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/website/page_renderers/template_page.py", line 45, in __init__
    self.set_template_path()
  File "/home/frappe/frappe-bench/apps/frappe/frappe/website/page_renderers/template_page.py", line 54, in set_template_path
    app_path = frappe.get_app_path(app)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/__init__.py", line 1438, in get_app_path
    return get_pymodule_path(app_name, *joins)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/__init__.py", line 1468, in get_pymodule_path
    return abspath(join(dirname(get_module(scrub(modulename)).__file__ or ""), *joins))
  File "/home/frappe/frappe-bench/apps/frappe/frappe/__init__.py", line 1409, in get_module
    return importlib.import_module(modulename)
  File "/usr/lib/python3.10/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1004, in _find_and_load_unlocked
ModuleNotFoundError: No module named 'banking'

I tried to run the installation a second time by doing

bench --site SITENAME remove-from-installed-apps banking    #results in error 500
bench --site SITENAME uninstall-app banking  #returns "App banking not installed on Site SITENAME" but it's working again
# install would now fail because of "IntegrityError(1062, "Duplicate entry 'Klarna Kosma Integration' for key 'PRIMARY'")"
# so go to mariadb and delete this entry:
bench --site SITENAME mariadb
DELETE FROM `tabModule Def` WHERE name='Klarna Kosma Integration';
bench --site SITENAME install-app banking 
# same issue...

Also tried without success:

bench setup requirements
bench build
bench restart

thanks for helping!

Update Party Everywhere

Problem

After syncing transactions for three months, there will be at least three Bank Transactions for each employee as well as for all recurring customers and suppliers. If we manually set the party details of a Bank Transaction, we'd have to set them 3+ times for every party. This becomes time consuming very quickly.

Proposed Solution

In the "Details" tab below the Party field, add a checkbox Update Party In All Transactions. If this is enabled, the party details should also be updated in all unreconciled Bank Transactions with the same IBAN, that don't have a party set already. Approximately like this:

if not current_iban:
	throw("We don't have an IBAN so we cannot match anything")

frappe.db.update(
	"Bank Transaction",
	filters=[
		["iban", "=", current_iban],
		["party", "is", "not set"],
		["status", "=", "Unreconciled"]
	],
	{
		"party": new_party,
		"party_type": new_party_type,
	}
)

Support to fetch bank records before start of fiscal year (old records)

Issue:

  • Currently when Bank Accounts are synced, the consent token is generated for 3 months
  • This consent token has the upper limit or the start date from where bank transactions can be fetched
  • The start date is assumed to be the current fiscal year's start date, which may not be what the user wants
  • Kosma throws an error if older transactions are fetched beyond the consent's start date

Cases:

  1. New setup > User has never fetched accounts or statements > User wants to start from 2018 > Daily transaction updates will be as usual (starting from the last synced date to today)
  2. System is in use > User wants to fetch old transactions from some point (manually)

Possible Solution:
Case 1 :

  • Prompt user for a start date while fetching bank accounts for the first time (check if any bank with kosma ID)

Case 2:

  • Use Flow API > ask user for start and end date > user will have to authenticate again > fetch

Easier error analysis

Banking Settings should display a warning headline if...

  • the currently installed version is older than the latest GitHub release
  • the scheduler is not running (how can we reliably check that?)

Settle multiple unpaid invoices with one payment entry

Imagine we have one Bank Transaction for $500 to be reconciled with five unpaid invoices for $100 each. Currently, the Bank Reconciliation Tool would create five Payment Entries. But there was only one payment. To split it up into five Payment Entries may cause confusion. Instead, we should create one Payment Entry with five reference rows.

Handle Kosma Account ID expiry

Error:

File "apps/banking/banking/klarna_kosma_integration/exception_handler.py", line 28, in handle_error
    self.handle_admin_error(content)
      self = <banking.klarna_kosma_integration.exception_handler.ExceptionHandler object at ...>
      response = <Response [400]>
      content = {'error': {'code': 'CONSENT.RESOURCE_NOT_GRANTED', 'message': 'Die angefragte Resource ist nicht mehr freigegeben oder verfügbar.'}, 'consent_token': '********'}
  File "apps/banking/banking/klarna_kosma_integration/exception_handler.py", line 77, in handle_admin_error
    frappe.throw(title=_("Banking Error"), msg=error_data.get("message"))
      self = <banking.klarna_kosma_integration.exception_handler.ExceptionHandler object at ...>
      content = {'error': {'code': 'CONSENT.RESOURCE_NOT_GRANTED', 'message': 'Die angefragte Resource ist nicht mehr freigegeben oder verfügbar.'}, 'consent_token': '********'}
      error_data = {'code': 'CONSENT.RESOURCE_NOT_GRANTED', 'message': 'Die angefragte Resource ist nicht mehr freigegeben oder verfügbar.'}

Returned from Kosma

{
    'error': 
    {
        'code': 'CONSENT.RESOURCE_NOT_GRANTED', 
        'message': 'Die angefragte Resource ist nicht mehr freigegeben oder verfügbar.'
    }, 
    'consent_token': '********'
}

Analysis

Most likely due to Kosma Account ID being rotated (ref: https://docs.openbanking.klarna.com/xs2a/error-handling.html#consentresourcenotgranted)

Reconcile multi-currency invoice

A Purchase Invoice is entered for 100 USD.
The payable Account is in EUR (-> the amount gets converted to 80 EUR for the GL Entries).

The payment of 100 was made from a USD bank Account.

Expected behavior

The Bank Reconciliation Tool Beta shows the Purchase Invoice with $100 outstanding, which can be fully reconciled with the payment of $100.

Actual behavior

The Bank Reconciliation Tool Beta shows the Purchase Invoice with $ 80 outstanding (EUR-amount rendered as USD), which leaves $20 unreconciled.

Suggested fix

When a USD Bank Account is selected in the Bank Reconciliation Tool Beta, and the voucher is also in USD, it should show the outstanding amount in USD.

Payment initiation

Provide a way to pay for a voucher (Purchase Invoice, Expense Claim) from within ERPNext.

The user must choose ...

  • an existing company bank account (linked to Kosma)
  • a party's existing Bank Account or create a new one
  • the payment amount (default to Outstanding Amount)
  • the payment description (default to Supplier Invoice Number for Purchase Invoice)

We set a a reference number that makes later auto-reconciliation possible. For example, this may be the voucher name, or Doctype+Name. We initiate a payment flow. If successful, we create a Payment Entry against the voucher, using the same reference number.

Refactor Kosma classes to be independent of frappe

imagine it had to be a standalone library. The KlarnaKosma* classes should only be responsible for talking to Klarna (not to the database, etc.). This way we can think about one thing at a time and test them independently (e.g. no need to debug the interface in case of framework issues; no need to debug the framework in case of interface issues).

Paying the last invoice with full amount even the created payment entry in Bank transaction has less amount

Bank Transaction

The Amount of Payment Entry showing in the bank transaction is $20.07 - Because that is the remaining amount

Actual

The Actual Amount paid in the payment entry is $335 (The actual Amount of the Invoice), It has paid of the complete invoice, but it should have been 20.07 and partially paying the invoice.

This is a terrifying issue, and I request you to solve it quickly.
I am also requesting you to provide a script which can diagnose and track all the payments/invoices which are fully paid by these issues.
(We can have a script which tracks payment entries in the bank transaction child table and the respective payment entry document and finds out if there is a difference in amount.)

Show exact party doesn't get disabled

If a bank transaction doesn't have party information, Show Exact Party should be disabled and unset. Currently, it only gets disabled, but keeps the previous value from a different bank transaction.

Bildschirmaufnahme.2023-09-01.um.15.04.17.mov

Duplicate transactions for bank drafts

Problem

I noticed that, for bank drafts, we get duplicate transactions. For example, the same Bank Transaction got created four times within the course of a week. The first three ones have Status "Pending" and no Transaction ID set. The final one has Status "Settled" and a Transaction ID.

Example transaction data
[
  {
    "allocated_amount": 0.0,
    "amended_from": null,
    "bank_account": "GiroFirm (Consulting GmbH) - Sparkasse Hamburg",
    "bank_party_account_number": null,
    "bank_party_iban": "DE02200505501015871393",
    "bank_party_name": "Hauptk.f.FK",
    "company": "Consulting GmbH",
    "creation": "2023-09-14 00:01:54.563374",
    "currency": "EUR",
    "date": "2023-09-15",
    "deposit": 0.0,
    "description": "STEUERNR 123/456/78910 UMS.ST JUL.23 1.234,56EUR, 123/456/78910-----L1234567891234567",
    "docstatus": 1,
    "doctype": "Bank Transaction",
    "idx": 0,
    "kosma_party_name": null,
    "modified": "2023-09-19 15:01:57.230528",
    "modified_by": "[email protected]",
    "name": "ACC-BTN-2023-00263",
    "naming_series": "ACC-BTN-.YYYY.-",
    "owner": "Administrator",
    "party": null,
    "party_type": null,
    "payment_entries": [],
    "reference_number": "123/456/78910-----L1234567891234567",
    "status": "Pending", // <-----
    "transaction_id": null, // <-----
    "transaction_type": null,
    "unallocated_amount": 1234.56,
    "withdrawal": 1234.56
  },
  {
    "allocated_amount": 0.0,
    "amended_from": null,
    "bank_account": "GiroFirm (Consulting GmbH) - Sparkasse Hamburg",
    "bank_party_account_number": null,
    "bank_party_iban": "DE02200505501015871393",
    "bank_party_name": "Hauptk.f.FK",
    "company": "Consulting GmbH",
    "creation": "2023-09-15 00:02:30.530476",
    "currency": "EUR",
    "date": "2023-09-15",
    "deposit": 0.0,
    "description": "STEUERNR 123/456/78910 UMS.ST JUL.23 1.234,56EUR, 123/456/78910-----L1234567891234567",
    "docstatus": 1,
    "doctype": "Bank Transaction",
    "idx": 0,
    "kosma_party_name": null,
    "modified": "2023-09-19 15:01:57.198979",
    "modified_by": "[email protected]",
    "name": "ACC-BTN-2023-00265",
    "naming_series": "ACC-BTN-.YYYY.-",
    "owner": "Administrator",
    "party": null,
    "party_type": null,
    "payment_entries": [],
    "reference_number": "123/456/78910-----L1234567891234567",
    "status": "Pending", // <-----
    "transaction_id": null, // <-----
    "transaction_type": null,
    "unallocated_amount": 1234.56,
    "withdrawal": 1234.56
  },
  {
    "allocated_amount": 0,
    "amended_from": null,
    "bank_account": "GiroFirm (Consulting GmbH) - Sparkasse Hamburg",
    "bank_party_account_number": null,
    "bank_party_iban": "DE02200505501015871393",
    "bank_party_name": "Hauptk.f.FK",
    "company": "Consulting GmbH",
    "creation": "2023-09-16 00:01:19.135758",
    "currency": "EUR",
    "date": "2023-09-15",
    "description": "STEUERNR 123/456/78910 UMS.ST JUL.23 1.234,56EUR, 123/456/78910-----L1234567891234567",
    "doctype": "Bank Transaction",
    "deposit": 0,
    "docstatus": 1,
    "idx": 0,
    "kosma_party_name": null,
    "modified": "2023-09-16 00:01:19.157301",
    "modified_by": "Administrator",
    "name": "ACC-BTN-2023-00272",
    "naming_series": "ACC-BTN-.YYYY.-",
    "owner": "Administrator",
    "party": null,
    "party_type": null,
    "payment_entries": [],
    "reference_number": "123/456/78910-----L1234567891234567",
    "status": "Settled", // <-----
    "transaction_id": "fcc9c88165b042e10f273dd8690b6a5b", // <-----
    "transaction_type": null,
    "unallocated_amount": 1234.56,
    "withdrawal": 1234.56
  }
]

Cause

I guess this happens because the bank draft is announced, updated and finalized and we receive each of these events.

Proposed Solution

To prevent duplicates, I'd suggest that we stop syncing "Pending" transactions. A more complicated solution would be to find a way of identifying that they are the same (other than the Transaction ID ) and continue updating them.

Workaround

Before reconciling, filter your Bank Transactions by Status = Pending and Transaction ID Is Not Set and cancel these.

Bildschirmfoto 2023-09-27 um 13 20 53

Automatically link Party Type and Party

Party Type and Party should be set automatically in Bank Transaction.

Match against Supplier, Customer and Employee records.

Prerequisite: add Party IBAN field to Bank Transaction.

Flow:

  1. check if earlier transactions with the same IBAN have a party linked and reuse that
  2. try to match any Bank Accounts linked to the party
  3. fuzzy-match full name against Supplier, Customer and Employee records

Rename app to "banking"

  • Repository: alyf-de/klarna_kosma_integration -> alyf-de/banking
  • App Name: klarna_kosma_integration -> banking
  • README: Remove the logo, update the title and headline

Module and DocType names can stay as they are.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.