In the first part of this post I outlined the issues involved with creating a trigger to do roll-up summaries with a lookup relationship. To solve the problem I did what you should always try to do first: let the Force.com platform do the heavy lifting for you. Don't try to code around the platform when the declarative interface will do the trick 99% of the time. You'll be amazed with the things you can do with the platform when you let it. The rule of thumb is to use the point-n-click Builder first and write code only as a last resort.

So to solve my problem I added another custom object called Shipment Item and created a Master-Detail(Shipment) field that would automatically provide the roll-up summaries. However, since users only interact with the Inventory Items on the shipment they never actually see or use this Shipment Items so there's really no interaction with them; it's simply for the roll-up summaries. I needed a way to allow users to manage the Inventory Items on the shipment but in the background add/move/remove Shipment Items to keep the number of records in synch with the Inventory Items. Here is the trigger that I wrote for the Inventory Items to implement this functionality:

Trigger ShipmentItemProcess.cls

/**************************************************************************************
* Keeps inventory items and shipment items in sync. If an inventory item is on a
* shipment, then it ensures that there is a corresponding shipment item record. When
* an inventory item is removed from a shipment, it deletes the shipment item record.
**************************************************************************************/

trigger ShipmentItemProcess on Inventory_Item__c (after update, after insert) {

	if (Trigger.isUpdate) {

		List<inventory_Item__c> invItemsToInsert = new List<inventory_Item__c>();
		Map<id,ID> mapInvItemShipment = new Map<id,ID>();
		Set<id> invItemIdsToUpdate = new Set<id>();
		Set<id> invItemIdsToDelete = new Set<id>();

		// figure out which ones need to be inserted, updated or deleted
		for (Integer i=0;i<trigger.new.size();i++) {

			// if the old is null and the new is NOT null, they are assigning to a shipment - INSERT RECORD
			if (Trigger.old[i].Shipment__c == null & Trigger.new[i].Shipment__c != null) {
				invItemsToInsert.add(Trigger.new[i]);

			// if old is NOT null and new is null, then they are removing from the shipment	- DELETE RECORD
			} else if (Trigger.old[i].Shipment__c != null & Trigger.new[i].Shipment__c == null) {
				invItemIdsToDelete.add(Trigger.new[i].id);

			// if they are both NOT null the we need to switch the new one to another shipment
			} else if (Trigger.old[i].Shipment__c != null & Trigger.new[i].Shipment__c != null) {
				if (Trigger.old[i].Shipment__c != Trigger.new[i].Shipment__c) {
					mapInvItemShipment.put(Trigger.new[i].id,Trigger.new[i].Shipment__c);
					invItemIdsToUpdate.add(Trigger.new[i].id);
				}
			}

		}

		// insert the new shipment records
		if (invItemsToInsert.size() > 0) {

			List<shipment_Item__c> shipmentItemsToInsert = new List<shipment_Item__c>();
			for (Inventory_Item__c item : invItemsToInsert) {

				Shipment_Item__c shipItem = new Shipment_Item__c();
				shipItem.Name = item.Name;
				shipItem.Inventory_Item__c = item.Id;
				shipItem.Shipment__c = item.Shipment__c;
				shipmentItemsToInsert.add(shipItem);

			}

			insert shipmentItemsToInsert;
		}

		// delete the corresponding shipment items that were removed
		if (invItemIdsToDelete.size() > 0)
			delete [select id from Shipment_Item__c where Inventory_Item__c IN :invItemIdsToDelete];

		// update ones that have been moved to another shipment
		if (invItemIdsToUpdate.size() > 0) {

			List<shipment_Item__c> itemsToUpdate = [select Id, Inventory_Item__c, Shipment__c from Shipment_Item__c where Inventory_Item__c IN :invItemIdsToUpdate];
			for (Shipment_Item__c item : itemsToUpdate)
				item.Shipment__c = mapInvItemShipment.get(item.Inventory_Item__c);

			update itemsToUpdate;

		}

	} else {

		List<shipment_Item__c> shipmentItemsToInsert = new List<shipment_Item__c>();

		for (Inventory_Item__c item : Trigger.new) {
			if (item.Shipment__c != null) {

				Shipment_Item__c shipItem = new Shipment_Item__c();
				shipItem.Name = item.Name;
				shipItem.Inventory_Item__c = item.Id;
				shipItem.Shipment__c = item.Shipment__c;
				shipmentItemsToInsert.add(shipItem);

			}
		}

		if (shipmentItemsToInsert.size() > 0)
			insert shipmentItemsToInsert;

	}

}

My test class looks like:

@isTest
private class Test_ShipmentItemProcess {

	static ID createShipment(String shipmentName) {

		Shipment__c shipment = new Shipment__c(
			name = shipmentName
		);

		insert shipment;
		return shipment.id;

	}

	static Inventory_Item__c createInventoryItem(String itemName) {

		Inventory_Item__c item = new Inventory_Item__c(
			name = itemName
		);

		insert item;
		return item;

	}

    static testMethod void testInsertAndDelete() {

		ID ship1Id = createShipment('Shipment 1');
		Inventory_Item__c item1 = createInventoryItem('LP100');

		// update the item with the new shipment number
		item1.Shipment__c = ship1Id;
		update item1;

		// fetch the newly created shipment item and make sure it was created correctly
		Shipment_Item__c shipItem1 = [select Id,Shipment__c,Inventory_Item__c from Shipment_Item__c where Inventory_Item__c = :item1.id];

		System.assertEquals(item1.id,shipItem1.Inventory_Item__c);
		System.assertEquals(item1.Shipment__c,shipItem1.Shipment__c);

		// now delete the shipment
		item1.Shipment__c = null;
		update item1;
		// make sure there are no records
		System.assertEquals(0,[select count() from Shipment_Item__c where Inventory_Item__c = :item1.id]);

    }

    static testMethod void testChangeShipment() {

		ID ship1Id = createShipment('Shipment 1');

		Inventory_Item__c item = new Inventory_Item__c(
			name = 'My LP',
			Shipment__c = ship1Id
		);
		insert item;

		Shipment_Item__c si = new Shipment_Item__c();
		si.Inventory_Item__c = item.id;
		si.Name = 'My LP';
		si.Shipment__c = ship1Id;
		insert si;

		ID ship2Id = createShipment('Shipment 2');
		item.Shipment__c = ship2Id;
		update item;

		// fetch the newly created shipment item and make sure it was created correctly
		Shipment_Item__c shipItem2 = [select Id,Shipment__c,Inventory_Item__c from Shipment_Item__c where Inventory_Item__c = :item.id];

		System.assertEquals(ship2Id,shipItem2.Shipment__c);

    }
}