ERPNext freezing, pos sales auto submission, duplicate sales

You have a benchmark for this case, where v6 runs fine but v7 dies? If so that is a good start.

That exists in a working public form - where is that to be found please?

Hi @olamide_shodunke

I believe there was a pull request that solved most of these issues… even though it wasn’t merged? Does that still work?

Kind regards,

We tried to solve the duplicate invoice issue.

A quick and dirty fix for this is to make the offline PoS Name field unique. If you notice all duplicated invoices have the same offline PoS name/number. By making this field unique the system will bounce any incoming duplicate invoice.

But note that the naming is based on the system time to the second. So you might have a problem in a multi till environment if 2 or more tills submit invoices at the exact same second.

We are looking at extending the naming to microsecond, this will reduce the current possibility of false duplicate by 99%.

Your thoughts

Well, I wouldn’t know what benchmarks you would need but what I have is customer feedback and experience, and also what we witnessed first hand… looking at number of key complaints from different users on different versions.

Here’s a summary of what I’m trying to pass on:

Version 6:

  1. Users experience a very stable, reliable and dependable POS, on those instances i have not received one report of cashiers being under or over. POS is almost bulletproof on that aspect.

Issues on the V6:

  1. Easy Access to account via breadcrumb link
  2. Draft printing
  3. Unfriendly cashier setup (have to create a customer profile per cashier)
  4. Sales Report per user is not available as a core report, lot of modification to do sales per user when you are dealing with named customers.

Version 7+

If I remember well, this is when the POS began to change until at one point it was only the offline POS that was available. Issues were immediately noticed especially from version 9.

  1. Sales duplication
  2. Wrong totals
  3. POS hang ups
  4. Items repeating in customer grid
  5. Troublesome display with unreadable names
  6. One time there was the super embarrassing feature where on searching, an item is then into the cart! Long thread to drive the point home.

At this point we started hearing of cashiers being over or short. Things that were practically impossible on v6 except for time differences which you will see it’s effect by expanding report scope, it balances out.

Asides customer feedback, we paid visits and saw these for ourselves.

Your issues make a good textbook case example of the need for user tests -

The first step is to formulate a set of unit tests to run and validate that each transaction or report type and so on is correct and bug free.

That test set forms the key standard to resolve performance-related bug issues that arise only under stress: With no load the tests all pass, but some fail only under load.

The question and goal is to discover what particular parameter(s) - what variable at a specific value (or range) - cause a given test to start to fail.

Apart from fixed hardware resources (server ram memory size, cpu core count, network capacity etc) the independent variables that affect load include user count and say transaction size. The dependent variable metrics include response time and transaction volume rate.

A ‘benchmark’ series of test runs would help specify exactly what variables and values would lead to issues like missing or duplicate records, false values, and hung processes or servers.

With each code update, run the tests again to collect a new set of metrics to add to the benchmark. That series history will serve to analyse and resolve bugs that may or may not relate to performance.

Hope this helps!

Note, the hangups of erpnext is not only on the POS

In our companies we are experiencing erpnext hanging-up on the Lead and the Event doctypes… the Event the most frequent.

Browser console shows a network disconnection error but that’s definitely not true.

Hello @eagoweb,
I don’t know anybody who has been able to pinpoint the cause. So I went for a prevention based fix. In our case, we discovered that all the duplicate invoices had exactly the same data in the offline_pos_name field. So first I created a patch that de-duplicates all the invoices. Second, I added code that makes the offline_pos_name field unique at the database level so that if for any reason the pos tries to create more than one copy of the same invoice, the database will reject them.

The de-duplication is done by finding the sales invoices that share offline_pos_name with other invoices, and appending a serial number to the offline_pos_name data so that the data in the column will be unique (so if we find 3 invoices with offline pos name - 123, the script will change them to 123, 123-1, 123-2). It also made it easy to find all the duplicate/triplicate invoices in the system by filtering by offline_pos_name that have a ‘-’. It is then up to the owner of the data to decide what to do with the duplicates.

This approach worked for us.

This was packaged as this PR. Unfortunately, it wasn’t merged since it could not be reproduced. If you have technical resources, let them have a look at it. It is also the same behind @olamide_shodunke’s suggestion. The only thing he didn’t point out is that you can’t set offline_pos_name to unique without ensuring that the data in the column is already unique.

If you encounter problems, send a reply and i’ll see if I can assist further.

NOTE: The patch was written for v10 so test it properly

@tundebabzy Can we test this patch for V11?

Yes you can test it on a throw away instance just in case. It should work without problems. Ultimately, you need to set offline_pos_name → unique = 1 in Customize Form to prevent future occurrence.

We also have observed that multiple tab of POS leads to duplicate invoice or missed invoice. Refrain user from opening multiple tabs of POS on same browser. Since then there haven’t been any complaints from user.

Sadly, opening at least a reasonable number of tabs (we advice nothing more than 3) has always been the most powerful thing about erpnext and other web based systems.

In the previous versions you could even open the tabs, ask a customer who maybe has a challenge with a card and wants to go get cash outside the store; to drop their first name and you just rename that invoice, when they return it’s easy to pick up. this was so powerful, those days are gone though, but we have a lot of our people still on those versions and they love that feature so dearly…

But this is well noted… Thank you

import frappe
def execute():
    data = frappe.get_all(
        "Sales Invoice",
        fields=["name", "offline_pos_name"],
    )

    offline_pos_names = []
    invoice_names = []
    for x in data:
        offline_pos_name = x.get("offline_pos_name")
        if offline_pos_name not in offline_pos_names:
            offline_pos_names.append(offline_pos_name)
        elif offline_pos_name:
            invoice_names.append(
                {"name": x.get("name"), "offline_pos_name": offline_pos_name}
            )

    print("There are {} duplicates".format(len(invoice_names)))

    duplicates = {}
    for x in invoice_names:
        offline_pos_name = x.get("offline_pos_name")
        if offline_pos_name not in duplicates:
            duplicates[offline_pos_name] = 1
        else:
            duplicates[offline_pos_name] = duplicates[offline_pos_name] + 1
        frappe.db.set_value(
            "Sales Invoice",
            x.get("name"),
            "offline_pos_name",
            offline_pos_name + "-" + str(duplicates[offline_pos_name]),
        )

    print("Processed {} duplicates".format(len(invoice_names))

You wont be able to make Offline POS Name unique till you have fixed previous invoices. Runs the script from the directory where it is located. Use this command bench --site [site name ] execute [directory name].script.execute

Once the script has run its course then go the Customize form > Sales Invoice to set the Offline POS Name unique.

Be aware that you may need to tweak time_out and max_allowed_packet else your connection to db may break. Had difficult time modifying 859 records as I was getting 2006, "MySQL server has gone away (ConnectionResetError(104, 'Connection reset by peer'