I have two promotions. One of them is bundle promotion and other coupon promotion. I want a restriction that one of them is applied in cart.
I can with rule executed condition, but I don't know, it is a good solution.
How can achieve this?
You can try this:
Put both of them in the same rule group and have them both be stackable=false.
This way only one of them should be executed (if both are fulfilled) based on the priority of the promotion.
E.g. if your coupon promotion has a higher priority and the customer applied the coupon, that one should be fired.
If the customer then removes the coupon code again, the other one should fire (if all other conditions are fulfilled).
Hope this helps!
Related
I am trying to model a situation in which a customer is added by either sales or an administrative assistent. They both have their own lane. I think using an OR or a 'AND' (paralel) gate would not really accurately reflect the situation.
How would you model this?
It would be great if there was an optional (either or) parallel gate but I don;t know if that exists.
I assume that you mean, whoever comes first will work on this activity. Therefore, a gateway cannot be the solution. It would need to have a condition, that is evaluated before one of the two activities get enabled.
This is what I would do: Create a new lane "customer admin" and specify somewhere else, that sales and adminstrative assistants are "customer admins".
If you duplicate "add customer" to show it in both lanes, you also have to model how one activity gets revoked, as soon as the other role starts working on it. If you want to model this, it gets really complicated. Of course, maybe a simple note could be sufficient, but I guess you are looking for a solution in BPMN.
If this activity would be the first in a process with empty start event, there is a simpler solution: Just use two empty start events and let the starter of the process decide, which one is to be used.
I will try to keep this as generic as possible using the “order” and “product” example, to try and help others that come across this question.
The Structure:
In the application we have 3 different services, 2 services that follow the event sourcing pattern and one that is designed for read only having the separation between our read and write views:
- Order service (write)
- Product service (write)
- Order details service (Read)
The Background:
We are currently storing the relationship between the order and product in only one of the write services, for example within order we have a property called ‘productItems’ which contains a list of the aggregate Ids from Product for the products that have been added to the order. Each product added to an order is emitted onto Kafka where the read service will update the view and form the relationships between the data.
The Problem:
As we pull back by aggregate Id for the order and the product to update them, if a product was to be deleted, there is no way to disassociate the product from the order on the write side.
This in turn means we have inconsistency, that the order holds a reference to a product that no longer exists within the product service.
The Ideas:
Master the relationship on both sides, which means when the product is deleted, we can look at the associated orders and trigger an update to remove from each order (this would cause duplication of reference).
Create another view of the data that shows the relationships and use a saga to do a clean-up. When a delete is triggered, it will look up the view database, see the relationships within the data and then trigger an update for each of the orders that have the product associated.
Does it really matter having the inconsistencies if the Product details service shows the correct information? Because the view database will consume the product deleted event, it will be able to safely remove the relationship that means clients will be able to get the correct view of the data even if the write models appear inconsistent. Based on the order of the events, the state will always appear correct in the read view.
Another thought: as the aggregate Id is deleted, it should never be reused which means when we have checks on the aggregate such as: “is this product in the order already?” will never trigger as the aggregate Id will never be repurposed meaning the inconsistency should not cause an issue when running commands in the future.
Sorry for the long read, but these are all the ideas we have thought of so far, and I am keen to gain some insight from the community, to make sure we are on the right track or if there is another approach to consider.
Thank you in advance for your help.
Event sourcing suites very well human and specifically human-paced processes. It helps a lot to imagine that every event in an event-sourced system is delivered by some clerk printed on a sheet of paper. Than it will be much easier to figure out the suitable solution.
What's the purpose of an order? So that your back-office personnel would secure the necessary units at a warehouse, then customer would do a payment and you start shipping process.
So, I guess, after an order is placed, some back-office system can process it and confirm that it can be taken into work and invoicing. Or it can return the order with remarks that this and that line are no longer available, so that a customer could agree to the reduced order or pick other options.
Another option is, since the probability of a customer ordering a discontinued item is low, just not do this check. But if at the shipping it still occurs - then issue a refund and some coupon for inconvenience. Why is it low? Because the goods are added from an online catalogue, which reflects the current state. The availability check can be done on the 'Submit' button click. So, an inconsistency may occur if an item is discontinued the same minute (or second) the order has been submitted. And usually the actual decision to discontinue is made up well before the information was updated in the Product service due to some external reasons.
Hence, I suggest to use eventual consistency. Since an event-sourced entity should only be responsible for its own consistency and not try to fulfil someone else's responsibility.
I am building a DDD/ES system where an admin can generate coupon codes to be shared and used publicly by consumers.
Each coupon has a maximum discount amount that is "shared" by all users of the coupon. An example is "Coupon 123 grants 5% off up for every use up to a total of $100,000." The coupon automatically expires once that maximum amount is reached. The coupon may also have rules around which items are eligible for purchase with that coupon.
So far, I have the Coupon and Purchases as separate ARs. Questions?
How do I update the coupon remaining amount when a purchase is made without updating multiple aggregates in a single transaction? Since this is about money, it feels like eventual consistency could lead to lost revenue. Should a domain service be responsible for that or a Saga?
How do i validate that the items being purchased with the coupon are eligible? Do ask the Coupon AR in the command handler before continuing with the purchase: couponAR.AreValidItems(request.PurchaseDetails)
I would like to track how much of the coupon is allocated to each purchase? Should this be another AR (CouponUsageAR) or just an event on the Coupon AR (CouponUsed)?
Thanks
In practice it is quite difficult to make a transaction (in the database sense) span multiple event streams. A more usual way to do this would be to use the saga pattern with compensation events in the event that the saga fails, and use correlation identifiers in the events to match the different entities they occurred to.
For example you might have a saga which updates the coupon remaining and if that succeeds then goes on to perform the purchase. Should the purchase fail the saga then needs to post a compensating event onto the coupon event stream to get it back to the state it was in at the start of the saga.
Have a look at the online video covering the saga pattern by Udi Dahan - or the documentation of that?
On the subject of strong vs. eventual consistency, ask the domain expert (this is domain-driven design, after all) the question:
which is worse: a coupon code delivering more discounts than its limit, or not being able to take an order?
If the answer is that they'd rather enforce the coupon limit and lose the sale, then strong consistency is called for. If they'd rather take the order, then eventual consistency is called for. It's worth noting that there's an easy way to prevent the coupon codes from ever breaching their limits: never have an order.
Our evolution of using DevOps is continuing (slowly but surely). One thing we've noticed is that some people are trying to but excessive estimates in for their time, but what we really want to be encouraging is for people to be breaking work down into multiple tasks.
Is there a way that we can set our DevOps work items to only accept a maximum value? I've had a look at the 'rules' and there doesn't seem to be anything there to let us do this, and because it's an out of the box field I don't think we can put a value limit against it.
I suppose what I want to understand is whether it would be possible to do this in some way? Could I do something with the existing 'Original Estimate' field or would I have to create a new custom field to have any chance of preventing people from putting in 100 hours for something that's actually more like 2?
If you are also using Boards, you could highlight work items where the original estimate is higher than a certain value. This would not prevent setting these values, but rather encourage the users to put in lower values.
https://learn.microsoft.com/en-us/azure/devops/boards/boards/customize-cards?view=azure-devops
Beware that this might not really help the underlying issue: People must be convinced of the benefits of splitting up tasks, otherwise they will just work around the tooling. Like always putting in the maximum value or not putting in the actual work hours.
Is there a way that we can set our DevOps work items to only accept a
maximum value?
I am afraid that setting the value limit for the Original Estimates field is currently not supported.
As workaround, you could need to create a custom field of type Picklist, and then specify the available values in the picklist.
You could add your request for this feature on our UserVoice site , which is our main forum for product suggestions.After suggest raised, you can vote and add your comments for this feedback. The product team would provide the updates if they view it.
I am working on DDD project and I am currently focused on two bouned contexts, Orders and Warehouse.
What confuses me is the following situation:
Order keep track of all the placed orders, and warehouse keeps track about all the available inventory. If user places one order for certain product item, that would mean one less item of that product in a warehouse. I am oversimplifying this process, so please bear with me.
Since two domain models are placed inside of a different BC, i am currently relying on eventual consistency ie. after one item has been sold, it would eventually be removed from the warehouse.
That situation unfortunately leads to the problem scenario where another user could simultaneously make another order of the same item, and it would appear as available until eventual consistency kicks is. That is something it is unacceptable by the domain expert.
So IMO I am stuck with two options
merge order and warehouse (at least the part regarding product
inventory, units available in warehouse) into one BC
have Order BC (or microservice if you wish) to be dependent of Warehouse BC (microservice) in order to pull a live product units
available
Which option does actually follows DDD patern? Is there another way out?
You could use a reservation system with a timeout.
Using a messaging analogy: With a broker-style queuing mechanism (such as RabbitMQ) you get a message from the queue and you have control over it until you either acknowledge that it can be removed from the queue or you release it back to the queue.
You could do the same thing in your ordering process. You reserve any items on your order. SO when you add them they have a status of, say, reserving and upon sending some message to reserve the items. If the response comes back you can decide how to proceed. Perhaps you could add any items that cannot be reserved onto a back order or try again later.
There are going to be different ways to approach this. Depending on your business case it may be acceptable to only check availability when someone really accepts the order.
If you domain expert reckons it is totally unacceptable that having this resolved at the end of the process then you could move it to the start. The issue is of course that user A could reserve and never buy thereby losing user B as a customer; whereas only applying the real "taking" of the item at the end of the process is closer to ensuring a purchase. But that is a business decision.
This issue is a really great example of where reality actually is eventually consistent. Is it really the best thing to decline an order if there is no inventory currently in the warehouse - even if there was a replenishment due in the next 20 minutes?
What if the item was actually on the shelf, but the operator hadn't yet keyed it into the system?
Sometimes designers and domain experts assume that people want 100% consistency, when really, users might be willing to accept a delay in confirmation of their order, if it increased the chance that their order would be accepted rather than rejected.
In the case above, why make it the user's job to retry their order N minutes later? In an eventually consistent system, you can accommodate such timing flexibility by including a timeout to retry the attempt to fulfill the order for a period of time before confirming to the client that it really wasn't possible.
There are technical solutions that will give you 100% consistency, but I think really this is not a technical challenge but a cultural/mindset one, changing people's minds about what is possible & acceptable to achieve an what is actually a better outcome.
IMO you can build a PlaceOrderSaga which will ask for inventory availability before placing the order.