refactor invoice and add tests