shopping cart with arbitrary promotions model

Not exactly a rails question, but my cart is in rails :-p

I'm looking for a model which allows for promotions to make arbitrary changes to a users shopping cart / session --- pretty much anything my account management wizards can dream up that they think might get more sales. For example, some standards would be: discounting the entire cart, discounting single items or a type of items, adding free items, giving free/discounted shipping, flagging a user so their next purchase applies for a different promotion, etc.

Please ignore my further prattling unless you're interested.

I have a functioning cart that does this already, but it has problems which make introducing new types of promotions difficult. Namely, too much responsibility lies with the cart itself. My cart requires knowledge of the way the different types of promotions work, e.g. when calculating shipping costs it looks to promotions which affect shipping. When calculating discounts it looks to promotions that do discounts. When its state changes it looks to promotions that alter its contents, e.g. adding/removing bonus items if the promotion qualifies/fails to qualify. This works, but it means a few things:

1.) The cart has responsibility for applying/unapplying promotions. 2.) Adding new promotion types means rewriting cart code to accommodate them, sometimes very convoluted code.

What I'd like is a model that somehow abstracts promotions away from the cart, but I can't think of a good way to do it. Some kind of proxy might work perhaps, where a Promotion encapsulates the cart and proxies its methods, introducing its own code which alters the order. This gets messy though with multiple promotions. Currently my cart doesn't require more than one promotion at a time, but i don't want to write this code then have them come back next month with "Oh yeah, we want to be able to attach both a promotion and a coupon to the order."

Anyone seen any interesting cart implementations that deal with this sort of thing?