Ah okay. That makes sense.
At the moment, your flow checks the Tag/Trade are valid values and only passes them to the Join node if they are valid.
The problem with that approach is exactly what you are seeing: if it is scenario 3 (tag & trade provided) but either one of them is invalid, then the Join node will pass on a message with only the valid value - so the Function node thinks it is case 1 or case 2.
There are a few ways you could fix it. One way would be, earlier in the flow, when you identify it is an invalid value, then set it to something like
INVALID, but still pass it on to the Join node. That means you will be sure to get "complete" messages in all three cases. You would then add some additional logic in the Function node after the Join node to check to see if the value is valid or not.
var hasTag = msg.payload.hasOwnProperty("Fob_Tag_ID") && msg.payload.Fob_Tag_ID !== "INVALID";
var hasTrade = msg.payload.hasOwnProperty("Trade_ID") && msg.payload.Trade_ID !== "INVALID";