Interesting approach although I'm not sure I would have done it in the same way.
It looks like you're describing fact and dimension tables so you're looking at large fact tables. 12 seconds for a 300,000 row table (albeit on a test system) isn't great. Imagine a 300 million row table (or billion rows) and then try and run that CTE (joined twice) against the fact table.
Firstly, the number of production days between two dates can be calculated without the use of a CTE:
select count(*) from dbo.TstCalendar where Date between @delivery_day and @ship_date and ProdDay ='Y'
Secondly, in this instance it would make more sense to store the delivery_time as a fact within the fact table. It's additive so it fits in there quite nicely and can allow the business to ask questions like (what was our average delivery time for orders in Jan, what was our lowest, highest, etc...). Also, by storing it in the table you remove the need to perform an unnecessary join between a very large fact table and the calendar table.
This does of course mean that you need to perform this calculation during the ETL load process but it's more efficient to do so with a day's (assuming you run the load once a day worth of data than against a large fact table.
On another note, you should consider having a seperate order and shipment fact tables. A fact table should never really contain any nulls - the presence of nulls is often a clue that something is not right with the design. In this instance, it's fair to say that a ship_date is not really a fact related to orders.