1. Intent and scope
This sample intents to show some common scenarios where CslaGenFork can be used.
- ReadOnly and editable stereotypes
- Root, child, grand-child
- Multiple to multiple relations (N to N)
- Generation of WinForms and WPF collections
- ParentLoad, SelfLoad and LazyLoad of child collections
- SimpleAuditing (except for CreateUser and ChangeUser)
- Optimistic concurrency "first write wins"
The Object Relations Builder will be used when dealing with scenarios 2 and 3.
Authorization is out of the scope of this sample. So no need for any form of authentication. This will be handled in another sample.
This sample illustrates the following stereotypes:
The following stereotypes aren't covered in this sample:
2. Application requisites
In a country with no taxes, we were asked for a simple invoicing application. Products are sold to customers and an invoice must be issued for those sales. There is no need to handle product stock or invoice payment. On the other hand, we were asked to keep
track of the brands as some customers are picky about product's brand. Talking about customers, they want to keep track of customer types. They were vague about this feature. We understood it's not the case for customer families (import companies,
shell fish companies, banks, resorts, resident, tourists, etc). We suspect they want to make some classification on how much customers are likely to spend or whether they are good payers and the like.
2.1. Use cases
1) Brands and products
2) Customers and customer types
- A brand can have several products.
- For each brand, the product name must be unique but the product name can be repeated on other brands.
- The product code must be unique regardless of its brand.
- Each product must have a unit price that will be used at invoice time.
- Brands and product entry should be simple and fast. Our customer mentioned a grid would be a good solution.
- A search form for products will be needed for two uses:
- product updates (mainly price)
- as part of invoice entry
3) Invoices and invoice items
- Customers exist only to be invoiced. They have no address (this is a small island and it's easy to find people).
- The single attribute of customers is the customer type.
- Customer and customer type entry should be simple and fast. Again they mentioned grids as a good solution.
- A customer search form must exist for two uses:
- as part of invoice entry
- keeping track of customer's invoices
- An invoice can refer to several products so the invoice item concept applies.
- An invoice has an open state and a closed state. You can't add invoice items to a closed invoice. There is no limit for how long an invoice can be kept open (no monthly close of invoicing concept).
- Invoice items describe the unit price and the quantity of a product. On a given invoice, several invoice items may refer to the same product and have different unit prices (we suspect there will be some paper support for product delivery but we weren't
given any concrete details).
- The product unit price is copied from the product object when the invoice item is added. Subsequent product price changes shouldn't affect existing invoices.
- Once an invoice item is added to the invoice, it can not be edited neither for the quantity nor for the unit price.
- Invoice items can be deleted.
- If two "users" edit the same invoide or invoice item, the optimistic concurrency pattern "first write wins" applies.
- There must be a form for invoice and invoice item entry.
- There must be an invoice search form.
- For a given customer, it must be possible to list all the invoices including all invoice items.
2.2. Common requisites
- Application users aren't authenticated and the application must be prepared for a multi-user scenario (this looks like a nonsense, but that's the customer requisite)
- Simple auditing of creation and last changed dates must be used.
- The application must correct some common user typing mistakes like extra spaces.
- Except for invoice item, users aren't allowed to delete any objects.
- Simple auditing of creation and last changed dates must be kept for every object.
3. The database
The database schema below answers all the use cases described. As it happens on all software projects, a later requirement was added. They want to have the possibility to disable customer type categories: "now we create a customer type, later we find it
useless and want to disable it".
The database is just a persistence layer for the business objects (because we must switch off computer and can't loose the data and because data must be shared with other wokstations). Some might argue that the database schema should result from the business
objects and we shouldn't say a word about it before designing the business objects. Although I don't believe there should always be a direct maping of business objects to database tables, in simple cases this is the best thing to do because it's
the simplest thing you could do that works and it answers the design needs.
You can download the SQL scripts needed to create the sample database
. The database layout follows
- The RowVersion field on Invoices and InvoiceItems tables is used to implement the optimistic concurrency pattern "first write wins".
- The CreateDate and ChangeDate rows present on all tables are intended for simple auditing. CslaGenFork supports simple auditing of two actions: creation and last change. It handles date and user of the action. As there is no user authentication,
we will leave the user auditing out of this sample.
- Notice also the IsActive row on the CustomerTypes table. This is intended to illustrate the SoftDelete support.
Preparing the project
we must detail each use case: what kind of user interface we need for them and how to put CslaGenFork to good use and help us by generating the business objects.
- Brands, Products, Customers, and CustomerTypes
- Invoices and invoice items
- Business Rules