How do I interpret this particular feature - featuretools

lets say I have 3 entities: parent1 <- child -> parent2. I used dfs() and got feature I can't understand MEAN(child.parent2.MEAN(child.num_feature)). Reading documentation I thought about any_entity.MEAN features as "group by entity then apply MEAN" but now this approach doesn't work

Deep Feature Synthesis creates new features by "stacking" existing features. To understand this feature, let’s go through how this is calculated step-by-step.
Calculate feature MEAN(child.num_feature) and add it to parent2.
Join that feature (defined on parent2) into child. This creates a new feature parent2.MEAN(child.num_feature) defined on child. Rows of child that have the same value for `parent2 will have the same value for this feature.
Group the child by parent and take the mean of that feature. This creates MEAN(child.parent2.MEAN(child.num_feature))
To help clarify, let's go through a concrete example
Imagine parent1 was a table of customers, child was a table of transactions by your customers with the column amount, and parent2 was a table of each unique product you sell.
The feature MEAN(transactions.product.SUM(amount)) created for the customers entity could be interpreted as “what is the average total sales of products this customer purchased” e.g “does this customer buy products that have sold a lot”.

Related

DDD UI composition across multiple contexts on creation

Based on this talk from Mauro Servienti called "All Our Aggregates are Wrong. Here is the link for reference: https://www.youtube.com/watch?v=KkzvQSuYd5I
We might have a few bounded contexts each containing information of a item.
e.g
Marketing Context - name, description, images
Sales Context - list price, product code?
Inventory - stock level
Each context might have their own name for it, e.g. inventory might call it sales item.
I think sales might be the owner of an item so when you go to create an item that is the place it will be created.
I have two questions.
Does the UI call these context's seperately?
If I have a UI to create a product/item and takes the data for both marketing and sales (list price, product code, name, description), I believe it is the case that the UI will make two separate calls.
The first call being to the sales context to create the item, which will publish a ItemCreated event or similar.
The second call will be to the marketing context to set the name, description, etc...
Is this correct?
Marketing's item
so my understanding of the inventory service, is that it will listen for the sales ItemCreated event and then create its own aggregate/stream for its representation of an item (Inventory item)
With marketing on the other hand, if I have a UI where I create the item with sales and then need to set the data in marketing, does the UI wait for an item to be created in marketing before then setting the title and description? Does the UI poll the marketing context until the item has been created and then performs the command to update the data?
I did something similar in the past.
The best approach I found is:
Firs you have to find the main owner of the item. In my case it was a product catalog.
Having a product in the catalog means the company intent to work with this product even if there is not stock, nor a marketing campaign, nor anything yet. This is an aggregate by its own, its operation (add product to catalog) is completly transactional because even if the event ProductAddedToCatalog fails to be applied in other Bounded Context (BC) (because infrastructure fails) I do not have to undo nor coordinate/orchestate anything. Just retry raising the event. The Catalog BC is kept in a consistent state.
For the others BC; applying the event means they create its entry with empty/default values. i.e. in Warehouse BC the entry is created with 0 stock and its correlated product catalog ID. In marketing the entry is created as a product with no marketing campaings so far. And so on with others BC.
How I modeled the UI taks for this? I created several screens like a wizard.
The first screen ask for product catalgo info. Its only task is insert a new product on the catalog.
The next screen ask for Warehouse info but it is not inserting; it is updating the entry with default values created by applying ProductAddedToCatalog event that was raised in the first step.
This way, in case warehouse step fails, the system keeps its consistent state and a user could use the UI task for updating product stock in Warehouse BC later.

Hybris - Adding Service product to main product

I would like to know what is the best approach to add service products to a main product.
Say for example, in Autocare we have Standard Oil Change (Main Product) and Synthetic Oil change (Main Product) and there are services products tied to it like tire pressure check, wheel balance, Air filter inspect, etc. Say Standard Oil change will have 6 services tied to it and Synthetic Oil Change will have 12 services to it.
When the user adds Standard Oil change to the cart, it should show all the services relates this this product in the cart.
So i will adding 12 Service Product to Hybris DB altogether and i can add these service products to any Main Products. Could anyone let me know what is the best approach and how we can make realtionship between Main Product and Service products. Another thing is the Service product will not be visible when the user searches for product, but it will be visible in the PDP once he selects that product.
Appreciate your help on this. Advance Thanks!!!
Thanks
If you want to link products with each other, based on a type of relationship, you should make use of the ProductReference datamodel. This allows you to link 2 products and specifying what their relationship is with the ProductReferenceType property.
By default, it's used a lot for cross selling, upselling, accessories,... It also has a default type available called CONSISTS_OF. This one fits your requirements perfectly.
For your example:
You would have your product Standard Oil Change, that will have 6 product references. One for each service. The type of this reference should be CONSISTS_OF

Tracking tire mileage in MAXIMO as measurements on meter readings

I am helping on a project and we are managing a tire warehouse in MAXIMO. That was OK, but now our business guys want us to track mileage for these tires. As these are stock parts, I do not understand how we can manage these and capture mileage for each tire.
A rotating item is a serialized asset, such as a pump or a tire, that you define with a common item number. You designate an item as rotating because it shares properties of both items and assets. A rotating item can have an inventory value, metered mileage and an issue cost.
A rotating item is an inventory item with a generic item number, a current balance,
and multiple instances that can be used in various locations around a plant with individual asset numbers.
A rotating item cannot be consumed and is maintained as an asset. After creating an item and adding it to a storeroom, you can either use the Assets application to create the asset record for the item you want to track, or create a purchase order for the rotating item and serialize it when you receive it.
When you associate an asset with a rotating item, balances can be displayed and tracked for the item. A rotating item is tracked both by its item number in Inventory records and by its asset number in Assets records. An item cannot be both a spare part and a rotating item.
Avoid using rotating asset/item. It is too complicated to use and very difficult to train on. Many people recommend it as a solution, but in practice, all the customers I've worked with don't like it. Eventually, they learn it but the work flow is completely different from issues and returns. Wait until you have to move the asset from a storeroom to location or vice versa.
You can use item condition code if you want to tires and what percentage tread is left: https://www.ibm.com/support/pages/understanding-condition-codes

CQRS Read Model Projections: How complex is too complex a data transformation

I want to sanity check myself on a view projection, in regards to if an intermediary concept can purely exist in the read model while providing a bridge between commands.
Let me use a contrived example to explain.
We place an order which raises an OrderPlaced event. The workflow then involves generating a picking slip, which is used to prepare a shipment.
A picking slip can be generated from an order (or group of orders) without any additional information being supplied from any external source or user. Is it acceptable then that the picking slip can be represented purely as a read model?
So:
PlaceOrderCommand -> OrderPlacedEvent
OrderPlacedEvent -> PickingSlipView
The warehouse manager can then view a picking slip, select the lines they would like to ship, and then perform a PrepareShipment command. A ShipmentPrepared event will then update the original order, and remove the relevant lines from the PickingSlipView.
I know it's a toy example, but I have a conceptually similar use case where a colleague believes the PickingSlip should be a domain entity/aggregate in its own right, as it's conceptually different to order. So you have PlaceOrder, GeneratePickingSlip, and PrepareShipment commands.
The GeneratePickingSlip command however simply takes an order number (identifier), transforms the order data into a picking slip entity, and persists the entity. You can't modify or remove a picking slip or perform any action on it, apart from using it to prepare a shipment.
This feels like introducing unnecessary overhead on the write model, for what is ultimately just a transformation of existing information to enable another command.
So (and without delving deeply into the problem space of warehouses and shipping)...
Is what I'm proposing a legitimate use case for a read model?
Acting as an intermediary between two commands, via transformation of some data into a different view. Or, as my colleague proposes, should every concept be represented in the write model in all cases?
I feel my approach is simpler, and avoiding unneeded complexity, but I'm new to CQRS and so perhaps missing something.
Edit - Alternative Example
Providing another example to explore:
We have a book of record for categories, where each record is information about products and their location. The book of record is populated by an external system, and contains SKU numbers, mapped to available locations:
Book of Record (Electronics)
SKU# Location1 Location2 Location3 ... Location 10
XXXX Introduce Remove Introduce ... N/A
YYYY N/A Introduce Introduce ... Remove
Each book of record is an entity, and each line is a value object.
The book of record is used to generate different Tasks (which are grouped in a TaskPlan to be assigned to a person). The plan may only cover a subset of locations.
There are different types of Tasks: One TaskPlan is for the individual who is on a location to add or remove stock from shelves. Call this an AllocateStock task. Another type of Task exists for a regional supervisor managing multiple locations, to check that shelving is properly following store guidelines, say CheckDisplay task. For allocating stock, we are interested in both introduced and removed SKUs. For checking the displays, we're only interested in newly Introduced SKUs, etc.
We are exploring two options:
Option 1
The person creating the tasks has a View (read model) that allows them to select Book of Records. Say they select Electronics and Fashion. They then select one or more locations. They could then submit a command like:
GenerateCheckDisplayTasks(TaskPlanId, List<BookOfRecordId>, List<Locations>)
The commands would then orchestrate going through the records, filtering out locations we don't need, processing only the 'Introduced' items, and creating the corresponding CheckDisplayTasks for each SKU in the TaskPlan.
Option 2
The other option is to shift the filtering to the read model before generating the tasks.
When a book of record is added a view model for each type of task is maintained. The data might be transposed, and would only include relevant info. ie. the CheckDisplayScopeView might project the book of record to:
Category SKU Location
Electronics (BookOfRecordId) XXXX Location1
Electronics (BookOfRecordId) XXXX Location3
Electronics (BookOfRecordId) YYYY Location2
Electronics (BookOfRecordId) YYYY Location3
Fashion (BookOfRecordId) ... ... etc
When generating tasks, the view enables the user to select the category and locations they want to generate the tasks for. Perhaps they select the Electronics category and Location 1 and 3.
The command is now:
GenerateCheckDisplayTasks(TaskPlanId, List<BookOfRecordId, SKU, Location>)
Where the command now no longer is responsible for the logic needed to filter out the locations, the Removed and N/A items, etc.
So the command for the first option just submits the ID of the entity that is being converted to tasks, along with the filter options, and does all the work internally, likely utilizing domain services.
The second option offloads the filtering aspect to the view model, and now the command submits values that will generate the tasks.
Note: In terms of the guidance that Aggregates shouldn't appear out of thin air, the Task Plan aggregate will create the Tasks.
I'm trying to determine if option 2 is pushing too much responsibility onto the read model, or whether this filtering behavior is more applicable there.
Sorry, I attempted to use the PickingSlip example as I thought it would be a more recognizable problem space, but realize now that there are connotations that go along with the concept that may have muddied the waters.
The answer to your question, in my opinion, very much depends on how you design your domain, not how you implement CQRS. The way you present it, it seems that all these operations and aggregates are in the same Bounded Context but at first glance, I would think that there are 3 (naming is difficult!):
Order Management or Sales, where orders are placed
Warehouse Operations, where goods are packaged to be shipped
Shipments, where packages are put in trucks and leave
When an Order is Placed in Order Management, Warehouse reacts and starts the Packaging workflow. At this point, Warehouse should have all the data required to perform its logic, without needing the Order anymore.
The warehouse manager can then view a picking slip, select the lines they would like to ship, and then perform a PrepareShipment command.
To me, this clearly indicates the need for an aggregate that will ensure the invariants are respected. You cannot select items not present in the picking slip, you cannot select more items than the quantities specified, you cannot select items that have already been packaged in a previous package and so on.
A ShipmentPrepared event will then update the original order, and remove the relevant lines from the PickingSlipView.
I don't understand why you would modify the original order. Also, removing lines from a view is not a safe operation per se. You want to guarantee that concurrency doesn't cause a single item to be placed in multiple packages, for example. You guarantee that using an aggregate that contains all the items, generates the packaging instructions, and marks the items of each package safely and transactionally.
Acting as an intermediary between two commands
Aggregates execute the commands, they are not in between.
Viewing it from another angle, an indication that you need that aggregate is that the PrepareShippingCommand needs to create an aggregate (Shipping), and according to Udi Dahan, you should not create aggregate roots (out of thin air). Instead, other aggregate roots create them. So, it seems fair to say that there needs to be some aggregate, which ensures that the policies to create shippings are applied.
As a final note, domain design is difficult and you need to know the domain very well, so it is very likely that my proposed solution is not correct, but I hope the considerations I made on each step are helpful to you to come up with the right solution.
UPDATE after question update
I read a couple of times the updated question and updated several times my answer, but ended up every time with answers very specific to your example again and I'm most likely missing a lot of details to actually be helpful (I'd be happy to discuss it on another channel though). Therefore, I want to go back to the first sentence of your question to add an important comment that I missed:
an intermediary concept can purely exist in the read model, while providing a bridge between commands.
In my opinion, read models are disposable. They are not a single source of truth. They are a representation of the data to easily fulfil the current query needs. When these query needs change, old read models are deleted and new ones are created based on the data from the write models.
So, only based on this, I would recommend to not prepare a read model to facilitate your commands operations.
I think that your solution is here:
When a book of record is added a view model for each type of task is maintained. The data might be transposed, and would only include relevant info.
If I understand it correctly, what you should do here is not create view model, but create an Aggregate (or multiple). Then this aggregate can receive the commands, apply the business rules and mutate the state. So, instead of having a domain service reading data from "clever" read models and putting it all together, you have an aggregate which encapsulates the data it needs and the business logic.
I hope it makes sense. It's a broad topic and we could talk about it for hours probably.

DDD - price calculation when adding item to order / receipt

I'm trying to apply DDD in my latest project. Though I'm having a problem identifying where to put some business logic/calculation.
First I'm going to describe the business flow and then how I'm thinking of implementing this.
Business flow:
It's simply about adding a receipt item(s) to a receipt. However, the price of the item depends on the type of customer and the number of items.
i.e: Customer of type 'A' would like to purchase 2 meals. In his set up, he is allowed to have 1 lunch discounted, but because he is very hungry, he takes 2. The first meal should be for 4 eur (discounted), the second should be 6 eur (full price).
What I'm thinking is:
Product - an entity (of different bounded context, will only be used as an input param) - fields: code, name, ..., collection of prices each for a different customer type.
ReceiptItem - entity -fields: product code, product name, count, price, ...
Receipt as Aggregate root - fields:
customer (entity) - contains collection of ReceiptItems
On the Receipt, there will a method addItem(Product product, int count) and I plan to add the correct price calculation inside this method.
Returning to our example: receipt.addItem('menu1', 2)
So I would check the customer type and how many lunches he is allowed to have discounted. Given the example above, I would see, that he is allowed one. I then need to get the actual discounted price and I would get that directly from the product that exposes a method getCustomersPrice(customerid).
In the end, I will end up with two receipt items being added to Receipt. They will both have the same product code, but different prices. (In case the allowance would be 2 or more, I would only add one item to the collection with the discounted price, but count would the 2).
Would you say, that this is a good approach? I'm worried about passing the product as an input parameter to addItem. As it seems to create a tight coupling.
Thank you.
The Receipt aggregate root should be smaller: Receipt has ReceiptItems, which is fine, but Customer should be its own aggregate root. A customer exists independently of receipts, plus small aggregates are preferred.
Product is also a separate domain object within this bounded context, even though products also exist in a separate bounded context. Product also needs to be outside of the Receipt aggregate.
Given the fact that there are several aggregate roots, the logic to add a product to a receipt touches more than one aggregate. Thus, the logic cannot reside inside the Receipt aggregate nor any other aggregate. Such logic is best placed into a Domain service (which may reside in the same package as the Receipt aggregate), such as:
public class ReceiptService {
void addItem(ReceiptId aReceiptid, ProductId aProductId, int quantity) {
// business logic to determine price per item
// ...
// for each item, forward item creation to receipt:
receipt.addItem(productIdOrName, priceOfItem);
}
}
The Domain service combines data of various aggregates in order to determine the price per item. The internal logic to create a ReceiptItem and insert it into the collection of receipt items is best forwarded to the Receipt aggregate.

Resources