After insert trigger only using single inserted virtual table row
The reason it's not working is that your join causes each row to be updated multiple times, but each update sees only the original values, not the cumulative values of previous updates. So your updates are in effect cancelling the previous updates.
(Or maybe SQL only allows one row update per statement. Either way the result is the same, with different resource use.)

Here's a quick and poorly formatted repro:

declare @insertedexample table (id INT, codeid int, value varchar(10))

INSERT INTO @insertedexample VALUES
(1,1,'newvalue1'),
(1,2,'newvalue2')


declare @targetexample table (id INT, codeid1value varchar(10), codeid2value varchar(10))

INSERT INTO @targetexample VALUES
(1, 'origvalue1', 'origvalue2')


SELECT * FROM @targetexample

UPDATE t
SET 
t.codeid1value = CASE WHEN i.codeid=1 THEN i.value ELSE t.codeid1value END,
t.codeid2value = CASE WHEN i.codeid=2 THEN i.value ELSE t.codeid2value END
FROM @targetexample t
JOIN @insertedexample i on i.id = t.id

SELECT * FROM @targetexample


The only way I can think of at the moment to handle this is by building a dynamic query.

Aaron's suggestion of a view would certainly be better, provided users will only be filtering by fuelTransactions.id or the data will remain small enough to handle filtering after pivoting. (Edit: I later realised that it might also be possible to create a view, or a set of views, or certainly a function, that would allow efficient additional filtering, dependent of course on supporting indexing in the base table.)

UPDATE:

Actually you probably don't need a dynamic query, since the columns in the fuelTransactions table are fixed as are the efsCode codes you're interested in. 

You might be able to use a pivot of one form or another, which incorporates the current values for the columns not being updated, even if you have to use a bunch of ugly subqueries.
I might have time to experiment with it, but can't promise.