In TransactionLine, there is a field called isClosed. What does that mean for sales orders, work orders, and purchase orders? I am hoping there is a sort of generic meaning for these 3 transaction types.
When is it set to "T"? I think I see it being set to "T" when we fulfill a sales order (for instance), but I am just not sure. I know it is still "F" when I delete the line entirely. Also, I know in the UI for purchase orders, there is a way to close individual lines. I have not looked at work orders yet, but sales orders does not have that ability in the UI. That is part of why I am confused.
On a related note, what about the Voided field inside the Transaction, and how does it relate to sales, work, and purchase orders? What sets it to "T"? Maybe it is because our customer is still setting up their first instance of NetSuite and learning things, but we currently have no "Voided = 'T'".
We need to know what isClosed and Voided mean, as we need to maybe read those flags into our system and do different things based on the value of those flags. To me they seem closely related, so that is why I am asking about both of them.
Related
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.
In my company (train company) there is a sort of battle going on over two viewpoints on something. Before going to deep into the problem I'm first going to explain the different domains we have in our landscape now.
Product: All product master data and their characteristics.
Think their name, their possible list of choices...
Location: All location master data that can be chosen, like stations, stops, etc.
Quote: To get a price for a specific choice of a product with their attributes.
Order: The order domain where you can make a positive order but also a negative one for reimbursements.
Ticket: This is essentially what you get from paying the order. Its the product but in the state that its at, when gotten by the customer.
The problem
Viewpoint PURPLE (I don't want to create bias)
When an order is transformed into all "tickets", we convert the order details, like price, into the ticket model. In order to make Order something we can throw away. Order is seen as something transient. Kind of like the bag you have in a supermarket. Its the goods inside the bag that matter. Not the bag itself.
When a reimburse flow would start. You do not need to go to the order. You would have everything in the Ticket domain. So this means data from order will be duplicated to Ticket.
But not all, only the things that are relevant. Like price for example.
Viewpoint YELLOW (I don't want to create bias)
You do the same as above but you do not store the price in Ticket domain. The ticket domain only consist of details that are relevant for the "ticket" to work. Price is not allowed in there cause its a thing of the order. When a reimburse flow would start, its allowed to go fetch those details from the order. Making order not something you can throw away as its having crucial data inside of it.
The benefit here is that Order is not "polluting" the Ticket with unnecessary data. But this is debatable. The example of the price is a good example.
I wish to know your ideas about these two viewpoints.
There is no "Don't repeat yourself" when it comes to the business domain. The only thing that dictates the business domain is the business requirements. If the requirements state that the ticket should work independent of the order changes, then you have to duplicate things.
But in this case, the requirements are ambiguous. There is no correct design using the currently specified requirements. Building code based on assumptions is the #1 way of getting bad code, since you most likely will have to do a redesign down the road.
You need to go back to the product owner and ask him about the difference between the Order and the Ticket.
For instance:
What should happen to the ticket if the order is deleted?
What happens to the order and/or ticket if the product price changes?
What happens to a ticket if the order is reimbursed?
Go back, get better requirements and then start to design the application.
For my internship, I need to implement a blockchain based solution to manage a drug supply chain. The management of this supply chain implies to track-and-trace (geolocate) a drug on the chain, but also to monitor the storage temperature to see if the cold chain is respected. For that I created a mock-up of the POC my Dapps (https://balsamiq.cloud/sum5oq5/p8lsped)and also I wanted to prepare myself by doing a UML and a use cases. However, I didn't find a lot of information about blockchain's UML and use cases besides two literatures which were quite different, so I don't know if what I did was correct or not...
The users of my Dapps will be the following ones:
The stakeholders (Manufacturers, Distributors and Retailers) which will use the Dapps to place orders and also monitor them. They also can search in the historic a specific order. Finally, trough IOT sensors they update the conditions of the order (temperature & location).
The administrator which roles is to update the Dapps and its rules. But also to add or delete user while also defining the rights that they have on the blockchain (I intend to use a permisionned blockchain). Finally, they are also here to help in case of technical problem.
The Dapps that I'm thinking about works in the following:
A user, the customer, can place an order (a list of products) to a
certain seller and choose the final destination of the order.
The order is then put together before being shipped or stocked in the
depots of one of the stakeholders (distributor or retailer) with a
description of the stocking and/or shipping condition of the product
(for example the product must be stocked or transported in a room
with a temperature of less than 5°C). During the shipping and
storing, an IOT device will feed the drops with the temperature and
geolocation of the product by updating the data each 5-10mn.
Obviously they will be a function that allows all the users to see
the history of the order passed and search inside a specific order.
In case where the temperature doesn't respect the temperature
recommended, then the smart-contract send an alert. The same if the
collocation of the product is "weird" like being in some European
countries and not in an Asian country, an alert will be sent again by
the smart-contractual. Finally, in the case where the product is sent
to the asked location by the customer, then the money for the order
will be paid to the seller.
So based on what I explained, I came here in hope that someone tell me if the use cases and UML that I did were correct or not.
I thank in advance anybody who'll take the time to help me.
I am new to DDD and decided to practice it with a dental clinic system I'm developing, but I'm struggling with modeling the domain so an extra pair of eyes will be greatly appreciated.
For this dentistry system, the domain expert told me that a patient holds only one medical history. The medical history must have a Record Number which is unique on the system. The medical history holds dental treatments the patient could have (like planned treatments) as well as treatments that the patient already had. Every treatment has a price, and so the medical history contains a Total price on it (based on planned/applied treatments). Whenever a patient gets a treatment done, he/she will have to pay with at least 50% of that treatment price, meaning he/she will eventually pay the rest of it on future appointments (if no treatment plan exists, he/she will have to pay for the 100% of the price). Finally, this dentistry clinic gives the option to patients to pay on different currencies, because sometimes a patient that comes for the day has only Euros, but then he decides he wants a plan and for future appointments will pay on Pounds.
Based on all this, and my beginner knowledge of DDD, my first thinking is that I have these entities:
Patient
Treatment
Dentist
I will have several value objects, but the most important ones might be:
Money (for prices and currency)
Signature (for applied treatments)
Tooth or Teeth (used on Treatment entity)
And I can only find one aggregate which is Medical history since it puts together patient info, as well as treatments (planned and applied). But this will mean that whenever I update a Medical History, I will have to update patient info and treatments, even if one of those never changed. Patients could change their personal information, which will be reflected in medical history, but it doesn't affect treatments.
I am a bit confused on how to model this. Please help!
Remember that Aggregates, and by extension Bounded Contexts (BC), are a grouping of data and business logic that belong together (and most likely things that need to change transactionally). The data that an aggregate contains is there because the business logic needs it, not because some application screen needs it. This is very important to clear up some confusion and to free you of some constraints in order to design your aggregates.
For example, when you display the Medical History to the user, you might want to show the Patient's name, address, age and so on, and also the treatments prices, but if you think about it, you don't need any of this to manage the Medical History. From what you say, the Medical History has a Record Number, a PatientId, and a list of TreatmentIds with maybe the Dates when they were done.
When you want to display the Medical History to the user, you can use UI Composition. So, you get the Medical History (which is mostly a bunch of Ids and dates). Then from the Medical History's PatientId, you can get the Patients's information from the BC that owns it. From the TreatmentIds, you can get the Treatment descriptions from some BC that owns that and their prices from the BC they belong to.
So, based on that, you can build your aggregates not based on the "relevant names" on your domain like Patient, Treatment or Dentist, but by the business logic they implement.
This is just wild guessing, but I can think of:
BC Marketing (for lack of a better name): Contains the descriptions of all treatments, information about the Dentists, Information about the rooms and materials, etc. So, texts, pictures and other details.
BC Finances: Contains information about the prices of each treatment, payment records of each payment, credits and debits of each patient, etc. In charge of keeping track of all these things. For example, it could know when a treatment starts/ends and depending on the Patient's record, require 50 or 100% payment. There's no need of direct relation to the Medical History here, it only needs to know if it's the first treatment or not.
BC Scheduling: In charge of scheduling new treatments and keep track of when they start and finish. This could contain the History, or it could potentially be somewhere else if necessary.
BC Medical: In charge of keeping all the medical records, allergies, medical details of the status of the teeth, etc.
BC Patients Care: In charge of tracking patients' information, name, nationality, contact details, etc.
Once you have an idea of the Bounded Context you can define the aggregates. There can be one or more per BC. Also, some things might not be an aggregate. For example, the Medical History might not require an actual aggregate if it's basically a record of treatment Ids and the dates they were made and there's no business logic associated (the history is not going to deny a treatment, have opinions on when a treatment should happen and so on, it's just a history).
Don't take this as a recommended design, but just as a thought process to come up with your own solution.
Entities have an Id where as Value Objects have structure identity which means if two value objects have the same value then they are the same.
In case of Money, there is no difference between two $5 bills, so it can be a value object.
You have not described the role and attributes of Tooth and Signature.
In case of Tooth, does it matter whose Tooth is it? Can You replace a patient's tooth with any other tooth which has the same attributes? If it does matter, then Tooth requires an Id therefore it is an entity.
In case of Signature, how are you going to compare two signatures? Do you have an image recognition software that can compare the look of two Signatures and decide that they are the same? You might have two patients with similar looking signatures, should their signature be treated as the same?
If you choose Medical history to be an Aggregate, then you should treat it as one object. Do you want to load the entire Medical history, in order to add a new Treatment to it? Can a Treatment be associated with another Entity, such as Dentist? If you can use a portion of Medical history (such as Treatment) individually then it is not an aggregate.
Some good tutorials:
Entity vs Value Object by Vladimir Khorikov
Entities, Value Objects, Aggregates and Roots by Jimmy Bogard
I am trying to refactor a legacy order handling and stock system with into a cleaner service oriented event-driven architecture. However, I am having some difficulty deciding what service should be responsible for the reservation/allocation of stock.
A brief overview of the current system
Sales orders are placed with us via third party system but we do not necessarily have all order lines in stock.
If an order item is in stock then we allocate/reserve the stock for that order straight away.
However, if we do not have enough stock then we procure the stock from our suppliers via a purchasing system.
When the item arrives from the supplier, the system will search through all open sales orders for the item and reserve/allocate the available stock to them, prioritising by sales order date. ***
I have already identified two services that I think need to be developed
Sales - Responsible for receiving the sales order and inserting into the database. Has domain entities such as Order, OrderLine etc.
Inventory - Responsible for keeping track of how much stock is available in our warehouse. Has domain entities such as StockItem.
However, as the allocation/reservation of stock concerns both inventory and sales I am not sure where the behaviour in point 2 above should be put.
I welcome any help or thoughts on this.
I think you have 2 BCs (bounded contexts): Inventory and Sales. For the integration between them I would probably go for domain events approach.
When a new item arrives at the warehouse, the Inventory BC increments the stock for the item, and publish an event.
Sales BC subscribes to the event, and it updates the opened sales that are waiting for the stock item.
So, behaviour of "point 2" are shared by both BC:
Sales BC search for opened orders waiting for that item. And then it asks Inventory BC to get the number of items it needs (this request is synchronous) and close the order.
Inventory BC receives the request and decrements the stock for the item.
However, as the allocation/reservation of stock concerns both inventory and sales I am not sure where the behaviour in point 2 above should be put.
I've been thinking about this problem (purely academically), and my current conclusion is that reservation management belongs with the inventory system. That keeps the stock source (the loading of items procured from your suppliers) and the stock sink (fulfillment of orders) together.
So the inventory system caches its own copy of the data required to fill the order (allowing it to work autonomously). It should be able to make progress as soon as it is informed that the suppliers have provided new inventory, even if the sales system happens to be down for maintenance.
You mentioned SOA and NServiceBus, so my initial thought was that you've attended Udi Dahan his ADSD training? I'll assume you have. With that, I'll try to answer your question.
So far I don't have a lot of information. But with what we have, I figured we need these properties to store all that you mentioned.
ProductId, one for each available product
InventoryTotal, attached to a ProductId. This number goes up and down
OrderId, to create an order
OrderDate, to make sure we can find the order that should receive incoming stock first.
If you have an OrderId, you can attach one or more ProductId to create an actual order. Different ways of storing this technically. Maybe in a relational database with Order and OrderLine tables, or possibly in a DocumentDb where everything is stored in a single document. That's totally irrelevant at this point.
Assuming we need 4 attributes, I'm not sure why we would create more than 1 service to split this up? This might change when we have more information, but at this moment I don't see the need.
If you want to discuss this, contact us at support#particular.net, mention my name and we can continue the conversation.
You are talking about loosely coupled domain apps, managing your sales orders, managing your inventory and managing your purchase orders.
Inventory must always be up to date, in order to not sell what you can't deliver. So PO en SO app should both talk to inventory via synchronous (inventory) services. To keep everything consistent, events on purchasing side, like receiving less than you expected for a PO, will have an impact on any SO already assigning quantity of that PO, as persisted in inventory. So the same PO pcs for example, in which the event of receiving less as expected, is registered, should synchronously update inventory, to update the quantity available for SOs to assign from, and publish an event, to be picked up, asynchronously, in the So app, so that the user can be notified and talk relevant action. Etc.