Generally speaking, you should investigate the process by which your values are missing and try to deal with it. I assume you checked that :
- There is no meaningfull way to fill those missing values. Sometimes, typically with companies data that often represent amount of money, missing values means 0$. For exemple values missing by block may correspond to a tax form they didn't fill because they don't pay it and most features could be set to 0.
- Similarly you don't have enough data to fill the blanks. Sometimes you can do missing value imputation based on what information you have. Specifically with companies data, you might be able to calculate financial ratios based on other metrics. Basically, you might want to check that your missing values do not correspond to some calculation that hasn't been made (then either correct that calculation or do it yourself in your pre-processing). There are more advanced imputations techniques, but I don't think they would be usefull when values are missing by blocks.
If you checked that, you can proceed to the next step : modeling. How you build your model depends on what is its purpose, what you want to do with it. Here, you should ask yourself some practical questions about those 40% records with missing values.
The first one is : do you actually need to output something for those instances with a lot of missing values ?
In some cases, notably when the output is public (or can be contested individually) it might just be best to output nothing or something along the line of 'we do not have enough data' for those instances. Practically that means removing them from your data set and building your models on your other instances.
On the contrary, when you look for performance (and not explainability to someone) you might want to use that pattern as an info. The best way to do so would be to introduce some feature that count the proportion of missing value for that instance. It might help a general model (see below) deal with that info.
If you need to output something, because you need some sort of an average, or because management asked for it, then consider the second question : should you make multiple models ?
One approach is to use just one model. Some models, mainly trees, can handle missing values. More advanced methods like XGBoost (eXtreme Gradient Boosted trees) are even considered state of the art for tabular data like companies data. Generally speaking this works (and might works very well with XGBoost). However, having done that myself, you'll end up with something quite hard to explain and overall you'll obfuscate that a significant chunk of your population is missing data. More specifically with data missing in blocks like yours, you'll probably end up with a very early split in your tree and actually have two models inside of one, with possible bizare interactions.
The alternative is to devise two models: one, very performant (say XGBoost), on your data with few missing values and another, way simpler on your other data. This will help you deal with instances with lot of missing values quite efficiently. For companies data with lots of missing data, you might just want to build a simple table of average of the outcome by your main descriptors (size, industry, geographical zone). This will leave you with most of your time to deal with the more complex model and its explanation (which is probably why you are paid for and is way more fun).