Ho modificato un po' il tuo codice in modo che sulla pagina ti scriva ciò che sta facendo per vedere se fa ciò che ti aspetti.
Inoltre ho cambiato alcune parti, ad esempio ho tolto 2 while che penso non servissero, se una query trova sicuramente 0 o 1 record, è inutile ciclare per fare il fetch del contenuto. Ho poi rivisto la posizione delle mysqli_free_result(...), ho anche aggiunto una funzione abort($link, $message) per comodità.
Soprattutto ho inglobato il tutto all'interno di una transazione, in una situazione simile con update su tabelle diverse in momenti diversi, devi essere certo che vengano eseguite tutte oppure nessuna altrimenti rischi di trovarti con dati inconsistenti se qualcosa andasse storto su un'update che non fosse la prima.
Il file lo trovi qui allegato, metti in conto che potrebbe darti qualche errore di sintassi, non ho potuto eseguirlo non avendo un db coerente sul quale farlo girare.