UK/EU VAT Accounting Setup

We use ERPNext in the UK and have found it to be a great fit for what we need. One of the things that confused me from the outset was implementing EU VAT. Reading throught the various on-line forums produced a number different opinions as to how this should be done.

What follows is how we implemented this so that the books made sense and so we could easily complete our quarterly VAT return. I don’t know if it’s “the way” it should be done, feedback is invited, however it’s worked well for us for the last three quarters and so I hope others might find it useful too.

Base Setup

We use the Taxes and Charges templates to categorise our transactions at the invoice level.

  1. Under Sales Taxes and Charges Templates, we created some new entries using Sage-like codes:
    T1 - Standard rate sales (20%)
        On Net Total, VAT, 20%
    
  2. Under Purchases Taxes and Charges Templates, we created similar entries:
    T1 - Standard rate purchases (20%)
        On Net Total, VAT, 20%
    
    T8 - EU goods purchase
        On Net Total, VAT, 0%
    
    T24 - Reverse Charge expenses.
        On Net Total, VAT, 0%
    

These are then applied to the sales and purchase invoices respectively.

We have only implemented the codes we use. The net effect of these allows the VAT control account track the VAT liability.

VAT Return

I couldn’t find a way to easily get ERPNext, out of the box, to produce a VAT report suitable for the UK 9-box form.

Initially we used the above setup combined with data export and manually sifting through the invoices to create the VAT return but after a couple of times this became very tedious and error prone.

To complete our VAT return, we have created a new document type (doctype) for UK VAT returns with code behind it that uses the above setup to produce the 9 box output automatically. I was pleasently surprised at how easy this was to create, kudos to the ERPNext developers! Having a custom doctype means we can record the figures we used in the database as well as being able to attach the HMRC acknowledgement to the record. Paper-free office win.

It looks like this:

Our code for this is here but be warned, you’ll have to customise it to play.

If there is interest, time/funds permitting, I may invest some time make a more generic solution. I suspect an item-level distinction would be needed by some companies too and a future project could even allow submission to HMRC’s “making tax digital,” although we don’t turnover enough yet to make that worthwhile for ourselves.

How are you doing your VAT with ERPNext?

2 Likes

Welcome to ERPNext and thanks for your kind contribution!

This exchange may interest you (if you are not already aware)

1 Like

Thanks for links. I’ll follow up on the GitHub thread to see what people’s thoughts are.

Hello @banksy , have you got the VAT return template mentioned in the above. The link takes me to the Frappe/erpnext GitHub page.

Hello @banksy (or anyone else),

I hope that you are still around as I think you may know something about UK VAT MTD module :slight_smile: Have Version 13 or ERPNext installed on the Ubuntu 20.04. Managed to set up UK Chart of Accounts using import facility(would be happy to share the excel file to others as charts.erpnext.com no longer works).

Now wanted to setup UK VAT Module.
https://github.com/software-to-hardware/erpnext-vat-mtd

During the installation it threw the following errors (I run the installation in the bench directory). And now after this my ERPNext browser console starting to throw error 'UK VAT Module not found’.

An now my ERP next is no longer working, and also the ERPnext throws the error message window as below (the last part).

What can I do? Anyone can help me?

erpnext@vmi894464:~/frappe-bench$ bench get-app uk_vat https://github.com/software-to-hardware/erpnext-vat-mtd
Getting erpnext-vat-mtd
$ git clone https://github.com/software-to-hardware/erpnext-vat-mtd  --depth 1 --origin upstream
Cloning into 'erpnext-vat-mtd'...
remote: Enumerating objects: 58, done.
remote: Counting objects: 100% (58/58), done.
remote: Compressing objects: 100% (52/52), done.
remote: Total 58 (delta 2), reused 46 (delta 1), pack-reused 0
Unpacking objects: 100% (58/58), 357.06 KiB | 2.08 MiB/s, done.
Installing uk_vat
$ /home/erpnext/frappe-bench/env/bin/python -m pip install --quiet --upgrade -e /home/erpnext/frappe-bench/apps/uk_vat
$ bench build --app uk_vat
✔ Application Assets Linked

yarn run v1.22.18
$ FRAPPE_ENV=production node rollup/build.js --app uk_vat
Production mode
✔ Built js/moment-bundle.min.js
✔ Built js/libs.min.js
Done in 12.24s.
$ supervisorctl restart frappe:
frappe: ERROR (no such group)
frappe: ERROR (no such group)
ERROR:
Traceback (most recent call last):
  File "/home/erpnext/.local/bin/bench", line 8, in <module>
    sys.exit(cli())
  File "/home/erpnext/.local/lib/python3.8/site-packages/bench/cli.py", line 121, in cli
    raise e
  File "/home/erpnext/.local/lib/python3.8/site-packages/bench/cli.py", line 111, in cli
    bench_command()
  File "/home/erpnext/.local/lib/python3.8/site-packages/click/core.py", line 1130, in __call__
    return self.main(*args, **kwargs)
  File "/home/erpnext/.local/lib/python3.8/site-packages/click/core.py", line 1055, in main
    rv = self.invoke(ctx)
  File "/home/erpnext/.local/lib/python3.8/site-packages/click/core.py", line 1657, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/home/erpnext/.local/lib/python3.8/site-packages/click/core.py", line 1404, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/home/erpnext/.local/lib/python3.8/site-packages/click/core.py", line 760, in invoke
    return __callback(*args, **kwargs)
  File "/home/erpnext/.local/lib/python3.8/site-packages/bench/commands/make.py", line 142, in get_app
    get_app(
  File "/home/erpnext/.local/lib/python3.8/site-packages/bench/app.py", line 371, in get_app
    app.install(verbose=verbose, skip_assets=skip_assets, restart_bench=restart_bench)
  File "/home/erpnext/.local/lib/python3.8/site-packages/bench/utils/render.py", line 110, in wrapper_fn
    return fn(*args, **kwargs)
  File "/home/erpnext/.local/lib/python3.8/site-packages/bench/app.py", line 198, in install
    install_app(
  File "/home/erpnext/.local/lib/python3.8/site-packages/bench/app.py", line 436, in install_app
    bench.reload()
  File "/home/erpnext/.local/lib/python3.8/site-packages/bench/utils/render.py", line 110, in wrapper_fn
    return fn(*args, **kwargs)
  File "/home/erpnext/.local/lib/python3.8/site-packages/bench/bench.py", line 142, in reload
    restart_supervisor_processes(bench_path=self.name, web_workers=web)
  File "/home/erpnext/.local/lib/python3.8/site-packages/bench/utils/bench.py", line 280, in restart_supervisor_processes
    bench.run(f"{sudo}supervisorctl restart {group}")
  File "/home/erpnext/.local/lib/python3.8/site-packages/bench/bench.py", line 43, in run
    return exec_cmd(cmd, cwd=cwd or self.cwd)
  File "/home/erpnext/.local/lib/python3.8/site-packages/bench/utils/__init__.py", line 126, in exec_cmd
    raise CommandFailedError
bench.exceptions.CommandFailedError

ERPNext Browser Error Log

## Traceback *(most recent call last)*

* #### File "/home/erpnext/frappe-bench/apps/frappe/frappe/app.py", line *78*, in `application`

response = frappe.website.render.render()

* #### File "/home/erpnext/frappe-bench/apps/frappe/frappe/website/render.py", line *54*, in `render`

elif is_static_file(path):

* #### File "/home/erpnext/frappe-bench/apps/frappe/frappe/website/render.py", line *127*, in `is_static_file`

file_path = frappe.get_app_path(app, "www") + "/" + path

* #### File "/home/erpnext/frappe-bench/apps/frappe/frappe/__init__.py", line *1218*, in `get_app_path`

return get_pymodule_path(app_name, *joins)

* #### File "/home/erpnext/frappe-bench/apps/frappe/frappe/__init__.py", line *1235*, in `get_pymodule_path`

return os.path.join(os.path.dirname(get_module(scrub(modulename)).__file__ or ""), *joins)

* #### File "/home/erpnext/frappe-bench/apps/frappe/frappe/__init__.py", line *1191*, in `get_module`

return importlib.import_module(modulename)

* #### File "/usr/lib/python3.8/importlib/__init__.py", line *127*, in `import_module`

return _bootstrap._gcd_import(name[level:], package, level)

* #### File "<frozen importlib._bootstrap>", line *1014*, in `_gcd_import`

* #### File "<frozen importlib._bootstrap>", line *991*, in `_find_and_load`

* #### File "<frozen importlib._bootstrap>", line *973*, in `_find_and_load_unlocked`

* During handling of the above exception, another exception occurred:

* #### File "/home/erpnext/frappe-bench/apps/frappe/frappe/middlewares.py", line *18*, in `__call__`

return super(StaticDataMiddleware, self).__call__(environ, start_response)

* #### File "/home/erpnext/frappe-bench/env/lib/python3.8/site-packages/werkzeug/middleware/shared_data.py", line *220*, in `__call__`

return self.app(environ, start_response)

* #### File "/home/erpnext/frappe-bench/env/lib/python3.8/site-packages/werkzeug/middleware/shared_data.py", line *220*, in `__call__`

return self.app(environ, start_response)

* #### File "/home/erpnext/frappe-bench/env/lib/python3.8/site-packages/werkzeug/local.py", line *231*, in `application`

return ClosingIterator(app(environ, start_response), self.cleanup)

* #### File "/home/erpnext/frappe-bench/env/lib/python3.8/site-packages/werkzeug/wrappers/base_request.py", line *237*, in `application`

resp = f(*args[:-2] + (request,))

* #### File "/home/erpnext/frappe-bench/apps/frappe/frappe/app.py", line *90*, in `application`

response = handle_exception(e)

* #### File "/home/erpnext/frappe-bench/apps/frappe/frappe/app.py", line *294*, in `handle_exception`

response = frappe.website.render.render("message", http_status_code=http_status_code)

* #### File "/home/erpnext/frappe-bench/apps/frappe/frappe/website/render.py", line *54*, in `render`

elif is_static_file(path):

* #### File "/home/erpnext/frappe-bench/apps/frappe/frappe/website/render.py", line *127*, in `is_static_file`

file_path = frappe.get_app_path(app, "www") + "/" + path

* #### File "/home/erpnext/frappe-bench/apps/frappe/frappe/__init__.py", line *1218*, in `get_app_path`

return get_pymodule_path(app_name, *joins)

* #### File "/home/erpnext/frappe-bench/apps/frappe/frappe/__init__.py", line *1235*, in `get_pymodule_path`

return os.path.join(os.path.dirname(get_module(scrub(modulename)).__file__ or ""), *joins)

* #### File "/home/erpnext/frappe-bench/apps/frappe/frappe/__init__.py", line *1191*, in `get_module`

return importlib.import_module(modulename)

* #### File "/usr/lib/python3.8/importlib/__init__.py", line *127*, in `import_module`

return _bootstrap._gcd_import(name[level:], package, level)

* #### File "<frozen importlib._bootstrap>", line *1014*, in `_gcd_import`

* #### File "<frozen importlib._bootstrap>", line *991*, in `_find_and_load`

* #### File "<frozen importlib._bootstrap>", line *973*, in `_find_and_load_unlocked`

> ModuleNotFoundError: No module named 'uk_vat'

OK searching around seems managed to get error away. I used the following commands:-

  • bench setup requirements --python
  • bench pip install -e apps/uk-vat

Rebooted the Linux, and now it seems to run. What I noticed that under Accounting/Taxes there is also new entry called ‘KSA VAT Setting’. I suppose UK_VAT uses some parts of this module as it seems to be installed part of the installation?

Taxes1

ItemTaxTemplate has now new entries, as expected. So good progress!

Version 14 HMRC Making Tax Digital for VAT released
As an update, we have now released a version of our UK VAT return app for version-14 that anyone can install and use, just contact us. It has also been released to frappe cloud and is awaiting review, thanks @rutwikhiwalkar

Here’s more information:

1 Like