Dynamics GP VAT rate change and how to deal with it

8th July 2020 and the UK government have announced that temporary reduction of VAT rate from 20% to 5% for hospitality sector (on food, accommodation and attractions), from 15th July until 12 January 2021. This gives you only one week to get advice from your ERP support on how to set up your system for the new VAT rate and for some (depending on your services and product mix), this will involve for the first time having to deal with different rates of tax on the same documents. Some people are SO going to be regretting not originally setting up invoice reports etc to dynamically pull the tax rates at the line level! Consultants are going to be super busy this week just helping people through the basics of reconfiguring their system to work with the new temporary VAT rate. This is also for many going to involve some consultancy to put the rates back in January (depending on how self sufficient the GP site is).

What should you think about?

You must  check in your supporting systems and documents, such as excel, your GP reports and reporting services reports for places where VAT rates have been “hard coded” (written in rather than looked up from system). These will need addressing, by preferably doing the extra work to dynamically look them up at run time, or replace with more generic wording if appropriate (say in terms and conditions of sale where VAT rate may have be specified in words.) As time is short you may just have be less perfect and note where they all are and go change them and get ready to swap the old report for the new report/document on the day and back again in January, assuming the rate actually goes back then…

Next you have three issues

  • Ensure new transactions from 15th July get the new 5% rate
  • Dealing with existing transaction particularly SOP document that will be fulfilled/processed after the 15th July as they will retain the previous tax rate unless further work to recalc is performed.
  • Putting the rate back again in January 2021


You have some avenues to explore:

  • Introduce a totally new Tax Schedule and Tax Detail IDs for the new rates. On the night of the change, update all the records to point at the new tax detail ids.
  • Just add new Tax Detail ID then take old one out of existing schedule.
  • Change the value on the exiting Tax Detail ID (not recommended).
  • Turn on effective tax dates feature (version GP2010+) and configure the effective records for the date in question. If no effective date exists it will fall back to the base tax rate so this will work well.
  • Use the Regenerate Tax tool to update your existing transactions.
  • Use a macro to update each document (depending on your transaction volume, could be very painful)

Some of the above options, provide for a clearer picture than others when it comes to reporting your VAT particularly don’t just change the tax percentage of the exiting Tax Detail, this is bound to give you issues, so consider that too.

Dynamics GP may from version GP2010 (with extra product) use Date-effective Tax. This allows a date range to be stored against a different tax rates for tax details , the appropriate tax rate then being used by a transaction based on that date in respect of document/posting/tax date (as configured). This is extra module that needs installing prior to GP 2015 R2, but after that it should be waiting for you to enable in company settings, if you haven't already.

There is also the useful tool of “Regenerate Taxes” that allow existing transactions to have the tax values updated, once the detail id has been updated.

Andy in his blog goes through some of the options with older versions of GP: All Change on 20% Tax Again January 2011 this should be read together with  Changing SOP Tax Rates using the Support Debugging Tool.


The “Whats New In Dynamics GP2015r2 document” explains all this nicely as copied below:

Date effective tax

You can now enter the tax rates in advance for transactions, and calculate the taxes based on the rates specified for a date range. You can also recalculate the taxes for the saved transactions by modifying the specified tax rates based on the latest tax rates specified by the tax authorities.

You can mass modify the tax rates, and regenerate the taxes for the saved transaction batches.

Follow these steps to set up a date effective tax:

1. Open the Company Setup Options window.

Company Setup Dynamics GP Effective Tax Dates

2. Microsoft Dynamics GP >> Tools >> Set up >> Company >> Company >> Options

3. In the Company Setup Options window, mark the Enable Tax Date checkbox, to allow you to use the tax date option for calculating the tax rate for the transaction based on a tax date.

4. Mark the Use Date-effective Tax checkbox. Select the option to calculate the tax. The option that you select here is used for updating the taxes for saved transactions within the tax effective date range. Transactions that are corrected will be based on the date you select here. You can select the Document date, Posting date or the Tax date to calculate the tax.

NOTE: Select posting date if you want to calculate tax based on the posting date that you specify. Select Tax date if you want to calculate tax based on the tax date that you specify. Select Document date if you want to calculate tax based on the document date that you specify.

You must set up the date range for the specified Tax ID to calculate the tax amount or percentage for the transaction. Follow these steps to create the date range for the tax ID.

1. Open the Date effective Tax Rates window.

DAte EFfective Tax Rates Window Dynamics GP

GP Tax Detail Window with Date Effective Tax Rates

2. Microsoft Dynamics GP >> Tools >> Set up >> Company >> Tax Details >> Select the tax ID in the Tax Detail ID field to set up the date range for >> Date effective Tax Rates.

3. Specify the date range for the specified tax amount or percentage. You can mass modify the tax percentage of multiple tax IDs.

You can choose to modify the tax percentage or amount for the taxes detail or the tax type based on date range, or for the tax without any specifying any date range, or both. Follow these steps to mass modify the tax percentage.

1. Open the Mass Modify Taxes window. Microsoft Dynamics GP >> Tools >> Utilities >> Company >> Mass Modify Tax Percentage

2. Select the option to modify the tax percentage.

You can choose:

• Date effective Tax – To update the dates specified in the date range, and the percentage that you have specified in the Date effective Tax rates window. What’s New in Microsoft Dynamics Page14
• Tax details – To update the tax percentage that you have specified in the Tax Detail Maintenance window.
• Both – To update the tax percentage that you have specified in the Date effective Tax rates window, and in the Tax Detail Maintenance window.

3. Click Insert to view the list of the tax IDs listed for the modification. NOTE: Within the specified Tax IDs, if you do not want to modify any Tax ID, you can select the Tax ID record, and click Remove.

4. Click Modify to modify the listed Tax IDs based on your specifications. You can also regenerate taxes for the transaction batches with the updated tax percentage. You can regenerate taxes for all the saved transactions of all the modules (except GL) or the selected module, only if you mark the use date effective tax in the Company Setup Options window.

You can specify the modules and the batches for which you want the taxes to be regenerated, or regenerate the taxes for all the batches in all the modules (except GL) at one time.

Follow these steps to regenerate the taxes for the saved batch transactions.

1. Open the Regenerate Taxes window. Microsoft Dynamics GP >> Tools >> Company >> Utilities >> Regenerate Taxes

2. Select the module to regenerate the updated tax for the batches. You can choose All to update the tax for the saved batch transactions in all the modules (except GL). Or, you can choose the module to update the tax for the saved batch transactions in the selected module.

3. If you choose a particular module to update the batch transactions, specify the batches in the batch range fields.

4. Click Insert to view the list of the batches that will be updated with the modified tax percentage. NOTE: You can select a batch ID record and click Remove, to prevent updating the transactions with the modified tax percentage.

5. Click Process to recalculate the tax for the transaction in the module and batch specified.


1. The tax calculation of a transaction will be overridden if there is a date effective tax rate that exist for any tax detail.

2. If the tax calculation routine does not find the rate for a particular date range, then the percentage in the tax detail maintenance will be taken.

3. For the receiving transaction entry, only shipment/Invoice will be considered for date effective tax calculation.

4. For the returns transaction entry, only return with credit and inventory with credit type of transactions will be considered for date effective tax calculation.

5. You can regenerate taxes for transactions when workflow is active for the Receivables Management Batch Approval, Payables Management Transaction and Payables Management Batch Approval.



How to handle VAT rate changes in Dynamics GP (perhaps dated now)

Changing Tax Rates and Date Effective Tax Rates in Dynamics GP

What’s New in Microsoft Dynamics GP (see 2015 R2 section)

Changing SOP Tax Rates using the Support Debugging Tool

All Change on 20% Tax Again January 2011

Office Interop Access is denied fix for .NET automation of Microsoft Office

Problem, Could not load file or assembly … or one of its dependencies. Access is denied

This is the solution to a perplexing issue around Office automation, that many people do not seem to be finding a solution for on forums.

The story, on a newly deployed set of PCs, a big issue arose where the Microsoft Office Interop for our .NET application would fail with errors of “Access is denied” when launching our integrating application. Solutions that were attempted proved only to be a temporary fix, with the problem reverting back again, often overnight.

Could not load file or assembly Microsoft.Office.Interop.Excel.dll or one of its dependencies. Access is denied.

Could not load file or assembly Microsoft.Office.Interop.Outlook.dll or one of its dependencies. Access is denied.

It turns out this is to do with permissions to the Interop assemblies that are put in the Global Assembly Cache (GAC) and the Centennial version of the Office App.


Solutions attempted


In an attempt to resolve the issue, the usual culprits were investigated including many more ideas that I’ve now forgotten about:

  • Changing the permissions within the COM, component services control panel for the access, launch and activation permissions etc
  • Taking control of the assembly cache permissions and granting access for directories and files including…
  • Uninstalling restarting, reinstalling Office
  • Uninstalling restarting, installing the Office interop via the Office installer options
  • Removing and replacing the local Office interop assemblies for the integrating application
  • Embedding the Interops in the application (difficult with Nuget packages tho?)
  • Using cacls.exe to update DCAL

Some of the above would work for the rest of that day, fixing the issue,  yet the problem would return the next morning (machines left on overnight).


Root cause

Finally, a hint of the issue was found from digging deeper and deeper in the forums, revealing the root cause.

“Office in the Windows Store” was released which is a different version of Office that is available through the windows store in Windows 10. This version of office is often referred to as Office Centennial version, as it utilises Project Centennial to allow office to be ported to an Office store app. Project Centennial is a bridging solution intended to make it easier for software developers to migrate existing applications to the store and app architecture in windows. This bridge was used to create the version of office in the store, which is distinct from the standard Office you would install from other media sources.

This store version of Office has been included in the Windows system image used by some OEM manufacturers of PCs, so new users have it ready to go on the machine when they get it to the Office or home. Being a store app, it gets refreshed by the auto updates of the Windows store… you can see where this is going?…

It would seem that this version of Centennial Office was installed on the disk image of these PCs and when full Office professional was installed on the machine, all is fine, until the (not in use) Centennial version of Office decides to repair itself overnight during the store update, corrupting the permissions on the Interop assemblies in the GAC, leaving them with only SYSTEM permissions, thus rendering them inaccessible to the end users.

Doing many of the aforementioned attempts to fix the issue, would overlay the correct permissions, but only until the Centennial version of Office went and undid the work overnight.

What is more annoying is that early on in the diagnostics for this issue I had a suspicion around this being the issue, but found no installer under, Start>>Apps and Features for  Microsoft Office Desktop Apps or Office, other than the pro copy. Also nothing in the programs and apps. Hence I’d assumed it can’t be the issue, wrongly as it turns out.

This seems to be an issue that has been hitting people from early 2019 through to 2020 when this blog post was written, although the OEMs were asked not the include the version of Office in the images anymore, so this should fade away over time.

It is a bit concerning that few people in forums seem to have found solutions, other than rebuilding the machine, but pushing on…


Removing Centennial Office

It seemed the obvious solution was to remove the store version of Office. It was not required and thus removing it should stop it overwriting the good install of Office. As noted before, there seemed to be no “uninstall” option anywhere in windows to get rid of the application. There were a few ways to remove this Office listed on internet forums, but the only one that worked for me was to launch power shell as an admin user. Then to run the following three commands, each in turn.

"(Get-AppxPackage -Name Microsoft.Office.Desktop).Dependencies | Remove-AppxPackage"
"Get-AppxPackage -Name Microsoft.Office.Desktop | Remove-AppxPackage"
"(Get-AppxPackage -Name Microsoft.Office.Desktop).Dependencies"

The final command should just confirm removal, by not returning anything.

Immediately it could be seen the assemblies had been removed from the “C:\Windows\assembly\GAC_MSIL\*” directories and after running the afflicted application, the issue would seem to be resolved. The professional office install was also repaired, via the Office Pro installer, for good measure.

A very annoying, obscure problem finally resolved!



How do I uninstall Office 365 Windows Store version?

how to uninstall office 365 preloaded in windows 10

Why ‘Office in the Windows Store’ isn’t really Microsoft Office

Office.dll access denied to VSTO add-in

SQL indexed views are incompatible with Dynamics GP

Trying to use indexed views with Dynamics GP? – well I’ve been there and I have seen others attempt the same. The Dynamics GP database and application are not really compatible with SQL indexed views. To help out those searching around this subject I thought I should write up our experience.

What is an indexed view?

An indexed view is a SQL database view that has had an index applied to it. This sounds obvious, but the important thing to realise is that the index will be materialised as an index on disk. Think of it as another table created on disk representing the data held in the view, this is why it is quick to get the data if it is summary data. This index "table" is maintained whenever the data that it covers is altered. So it is easy to imagine that indexed views are great for creating summaries, filtered views of data that cross multiple tables, as they will keep track of changes automatically and update the index "table", thus keeping the data "in-sync" with the data in the various tables that it derives from. As the data that represents the SQL view has been pushed to disk and persisted there, querying that summary data is lightweight and quick, because the work has already been done to process the data when it was stored, pre-joined between tables and/or summarised, rather than the database engine having to do all that work on the fly for each query as the query is ran.

However, there is a downside. When (any) index is created, you pay a price for the benefit of fast data recall when reading, by suffering with slightly longer writes times and those longer writes lead to longer living locks on the data and then this can lead to blocking. This may cause issues with performance in some circumstances. The extra writing is because the data held in the index "table" that represents the view needs to be maintained (updated) whenever any of the data underpinning that view changes. Depending on the workload sizes of tables, IO performance etc, this may be significant work if large numbers of records are updated at once. Again as with any SQL index, it takes space on disk too. For large wide views over large tables this may be a consideration too bloating storage and the knock on consequences that brings.

One of the most frustrating matters when working with indexed views is that there are a whole heap of constraints and restrictions around what is permitted in the query that forms them. For example, when using GROUP BY, it must contain the function BIG_COUNT(*) as a column and various database settings restrictions can apply too (there are many, many more). This means when designing the simplest views SQL compile errors warning that it is not possible to do "this and that” frequently cause annoyance. It is very obvious why this is the case when you think about it. It is due to the fact the data is persisted to disk, so it needs to be unchanging to store it, thus any SQL function used by the view has to be deterministic -aha, no “getdate()” function! It is surprising how often this will catch people out. I could go on and on about the restrictions and requirements of indexed views, but just go try making one and you’ll discover the pain yourself, then go read up the documentation to realise how much there is to it!

Another example below are the SQL SET OPTIONS that are required by SQL indexed views…


Using indexed view with Dynamics GP

Professionally we use indexed views a lot in our applications for the speed of access and real time integrity of summary data they offers, so sooner or later a GP admin or GP developer decides they would quite like to use an indexed view... -then it all ends in tears, let us see why…


This is the first problem. To build an index view the view must use SCHEMABINDING. This locks the database schema and the view together. Unfortunately this may then cause issues with application updates. When Dynamics GP is updated for a service pack or upgrade, sometimes the tables or other database objects may need to be dropped and recreated. This happens during the upgrade process, however if the object that is to dropped is schema bound, then the upgrade script will not be allowed to do what it wants, causing the upgrade to fall over. Hence if indexed views have been bound to the GP tables this is a real risk when a site comes to do an upgrade. Obviously if the person performing the upgrade was aware, then they could drop the view and recreate it after the upgrade, but in real life the knowledge is lost as employees leave or contractors move on causing upgrade pain. 

The second problem is more terminal. Let's try it and see what happens if we create a view over the sales order header and lines to speed up the number of sales lines by country that and not voided in historical transactions. Create the view on a non-production database like this…


-- We must schema bind
IF OBJECT_ID ('SalesVoidedLinesSummary', 'view') IS NOT NULL
    DROP VIEW SalesVoidedLinesSummary ;
CREATE VIEW SalesVoidedLinesSummary
       SELECT  COUNT_BIG(*) Cnt,
               SOP30300.CCODE as Country
       SOP30200.VOIDSTTS=0 --Not Voided
       AND SOP30200.SOPTYPE IN (1,2)


Then create the indexed view by adding the index. - REMEMBER I SAID NO PRODUCTION DATABASES WITH THIS LITTLE EXPERIMENT!

--We materialise the view by creating an index on it
    ON SalesVoidedLinesSummary (SOPTYPE, Country);


We can now query the view data like so..

SELECT  * FROM SalesVoidedLinesSummary where SOPTYPE=1 AND Country='PT'

and directly before we created the view with this…

               SOP30300.CCODE as Country
       SOP30200.VOIDSTTS=0 --Voided
       AND SOP30200.SOPTYPE = 1
       AND SOP30300.CCODE='PT'


...and we find that from not having the view to having the view we have dramatically reduced the query time as shown below. I’m not sure about the integrity of those figures but this isn’t a discussion around query optimisations, just accept that indexed views solve performance problems.

    Total execution time without view:  17390   
     Total execution time with view:        505   


In production

So developer or IT pro after testing that out on the test company database says, “great, now lets create it on the production database as that worked like a charm”, and then goes to login to GP and create a sales order having created the view…

...to then get the dismay of the error that follows...

“An edit operation on table ‘SOP_Master_Number_SETP’ failed. A record was already locked'.”



INSERT failed because the following SET options have incorrect settings ‘QUOTED_IDENTIFIER, CONCAT_NULL_YEALS_NULL,ANSI_WARNINGS’. Verify that SET options are correct for use with indexed views and”…


… then starts the support calls flowing in from the users! 

So why we can’t have nice things?

Go back up in this post, as you saw in the graphic, that there are certain SQL SET options required to make indexed views work. Sadly these are not compatible with the SET options required to make Dynamics GP work shown below! -thus the application breaks, simple as that! If those phones are still ringing from your users right now, then just simply drop the view and your users will be happy again.

We did play around a bit but never found a solution to this issue, but if you have a work around do let me know.


Mariano Gomez has a nice post about why this is required by Dexterity to make GP run correctly in this post:

Microsoft SQL Server DSN Configuration

Microsoft - Creating Indexed Views

Gavin wrote this which inspired me to document the issue before others fall into it...

Brief overview and comparison of how summary values are stored and calculated in Dynamics GP, Dynamics NAV and Dynamics 365 Business Central


What do you call that window GP?

Steve Endow mentioned on twitter the other day about the naming of objects in GP when programming. The inconstancies are astounding, I have to agree, you can spend half an hour trying to determine if the object named something almost like what you want is actually the object you want or not, then two mins to actually write the mod! The fact you end up using a tool to work out what the object name of the window is in the code, well that just tells the story.

api naming dynamics gp steve endow

What Steve might not realise is that it is even worse if you speak English rather than American. See that window he’s looking at in the tweet, look at it on my screen…


So we have Enquiry rather than Inquiry, no big deal? Well mostly no we learn the translations, but it confusing to the new developers who have to get used to this translations issue. Sometimes the translated terms are not as obvious as this. However even this would be an issue if you were looking at the object explorer ordered alphabetically or doing a search for the object.

There  is fun though with Debtors and Customers. I still don’t really know why we can’t have customers too, for our users it would make more sense than the accounting term debtors!

Steve kindly furnished me with this screen shot of an American GP customer window.


Compare that to what we see…with a English Debtor Window. These are the same windows, replacing customer everywhere, now imagine searching for this in visual studio, or a field called debtor id…


In visual studio when developing addins we have RMCustomerMaintenance, good job I didn’t go searching for debtor when looking for the object, eh?


So I conclude it is all fun and games developing visual studio addins for GP!


Thanks for Steve inspiring this post with his tweet and helping with the screen shot.