I've created Undeposited Funds feature (similar to Sage50) but still need a bit of guidance


Create a feature similar to undeposited funds in Sage50 whereby payment entry funds are held first in a ‘holding’ account and when cleared through Bank Clearance will move to an account of an actual bank account, either automatically or simply by pressing a button.

For my testing I’ve decided to try first with a button called Update Account on the Bank Clarence doctype.

When the button Update Account is hit, it will search for all payment entries with a clearance date and an account with paid_to equal to Undeposited Funds - DC. It will first change the account paid_to from Undeposited Funds - DC to Qatar Bank - DC and then it will create a journal entry crediting Undeposited Funds - DC and debiting Qatar Bank - DC.


Submit payment entry > open bank clearance > select Undeposited Funds - DC account > hit Get Payment Entries button > update Clearance Date for payment entry > hit Update Clearance Date (payment entry(s) should be removed from the list) > hit Update Account button



I’ve created an app called custom_changes with a file called change_account.py to handle changing the account from Undeposited Funds - DC to Qatar Bank - DC as well as creating a jv to handle the balance between the accounts.


I’ve created a client script on Bank Clearance to handle the button and messages.


The solution works as it’s suppose to by changing accounts and handling the balance, but a subsequent side effect is that a shadow record is then displayed the next time you hit the Get Payment Entries button.

If anyone could point out where I have gone wrong or suggest a better approach I would be very grateful!

This is my server script

import frappe
from frappe import whitelist
from frappe.utils import today

def update_account():

    payment_entries = frappe.get_all('Payment Entry', filters={
        'posting_date': ['>', '2000-01-01'],  
        'paid_to': 'Undeposited Funds - DC',
    }, fields=['name', 'paid_amount', 'posting_date', 'company'])

    for entry in payment_entries:

        frappe.db.set_value('Payment Entry', entry.name, 'paid_to', 'Qatar Bank - DC')

        make_journal_entry(entry.name, 'Undeposited Funds - DC', 'Qatar Bank - DC', entry.paid_amount, entry.posting_date, entry.company)


    return 'success'

def make_journal_entry(payment_entry_name, from_account, to_account, amount, posting_date, company):

    je_doc = frappe.new_doc('Journal Entry')

    je_doc.posting_date = posting_date

    je_doc.company = company

    je_doc.voucher_type = 'Journal Entry'
    je_doc.naming_series = 'ACC-JV-.YYYY.-'

    je_doc.user_remark = 'Automatic transfer from {0} to {1} for Payment Entry {2}'.format(from_account, to_account, payment_entry_name)

    je_doc.append('accounts', {
        'account': from_account,
        'credit_in_account_currency': amount,

    je_doc.append('accounts', {
        'account': to_account,
        'debit_in_account_currency': amount,



This is my client script

frappe.ui.form.on('Bank Clearance', {
    refresh(frm) {

        frm.add_custom_button('Update Account', () => {

                'Would you like to move all cleared payment entries from Undeposited Funds account to Qatar Bank account?',
                function() {

                        method: 'custom_changes.custom_changes.change_account.update_account',
                        callback: function(response) {

                            if (response.message === 'success') {
                                frappe.msgprint('Accounts updated successfully');
                            } else {
                                frappe.msgprint('Error occurred while updating accounts');
                function() {


The image is before clicking Update Clearance Date button:

The image is after clicking Update Clearance and Update Account and then retrieving the entries again by clicking Get Payment Entries (I also included reconciled entries)