It may happen that a goods is no more available at the supplier (This is often the case in the spare parts business).
But usually there is a replacement goods that is equivalent.
Currently in such case, the user has to find all the draft outgoing moves and replace the product on it, deactivate the old products (or at least make it unsalable).
He may also need to update the draft incoming moves for the purchase that the supplier has changed.
There are few issues with this process:
it is not error prone
products can not be deactivated if there are still stock
existing stock will not be consumed first
there is no history record about the replacement
Proposal
We provide a wizard to replace a product of type goods by another product of type goods. It stores on the replaced product the link to the new one (it must have the same category of unit of measures).
The record name search of the product is extended to search also on the replaced products codes.
A task is created that search for active replaced products that have no more stock in storage location. It deactivates the products (active, salable, purchasable) and replace on all the draft/staging stock moves.
When a stock move with a replaced product is done, the task is queued for the products. The task is also run periodically (daily).
Once a replaced product is deactivated, it can not be reactivated.
When sale and purchase creates stock moves for a replaced product that is also deactivated, they replace the product (this is to avoid having stock move created after the update if the processing is delayed). Idem for BOM explode
The user will be left responsible to change the supply configuration to avoid purchase again a replaced product.
Generally, I like the proposal, but I have another use case for what some assertions are not valid, or maybe I did not understand the assertion.
What you call equivalent replacement good, we usually called substitute products.
CASE 1. The product is available to buy, but a equivalent product is cheaper, so we buy and produce using the equivalent for some time. (while is cheaper)
CASE 2. The product is out of stock for some time. So the equivalent is our only choice while supply is coming. But when the principal product will be available, I will prefer to have again the principal.
Once a replaced product is deactivated, it can not be reactivated.
Why? In both cases, I will try again to buy in the future the replaced product.
Interesting things to do with substitute products:
Allow the definition of substitute products directly within the BOM. Each input could have a list of approved substitutes, ranked by cost / preference.
Set conditions to switch to a substitute product, depending on the lead time and delivery date. Or by suggesting equivalent products with lots with a near Expiration Date.
Those are temporal substitution. I think it should be managed differently (and not by this proposal) by a rule system but of course there will be hijacking the same way the orders to create stock move of substituted products.
Because we do not want to launch again the task to deactivate the product.
But indeed I would see no problem to reactivate the product if the replaced link it removed.
Those would be solved by match-pattern of the rule engine.
I did not restricted to only goods as it may be useful for other type.
I just deactivate the product. I do not think it is necessary to remove the other options. User may decide when they want to stop them.
I decided to deleted those moves. And let the system recreate them with different product. This is mainly because with the lot module, a lot may be also set which will be incompatible with the new product.
I did not enforce this. But if the user reactivate the product, it will be deactivate again by the scheduled task. Instead I allowed to clear the “Replaced By” in case of mistake.
Instead I modified the Move.create method to replace the product automatically. This has the benefit to avoid the need to extend every modules.