I have Buyer, Product, Seller, and Offer. The buyer offers to buy a product and the seller either accepts the offer or declines it. I also have the following invariants:
Buyer can't make an offer for a product if there is a pending one already. Seller can't accept a non-existing offer from a buyer. I created the following aggregates Buyer, Product, Seller, ProductOffers. ProductOffers contained all offers from all users. ProductOffers also have a method TryMoveOfferToAccepted() which is called when OfferCreatedEvent is raised from the buyer. TryMoveOfferToAccepted() then raises event triedMoveOfferToAccepted which is handled by the Product aggregate which checks whether the product can be bought (checks for sufficient quantity...) and the if successful raises an event ProductBought event which then is handled by ProductOffers (moves the offer from pending to accepted).
Is this a good way to do this? And how can I be sure that someone doesn't call Product's aggregate buy method without first checking whether an offer from buyer exists?