As an old school oracle developer I developed my business rules in plsql. I did this with cdm ruleframe or with triggers and packages. But now I want to make a demo on the oe sample schema. In this demo I used the orders and the order_items tables and because it is a demo I want to use bc4j for my business rules.
This are the business rules I want to implement. Every order item has to update the total order amount of the order. The Line Item Id of the order items has to an autonumber 1, 2, etc and not a sequence. On the order table the order date has to be current date and the order Id must be the next value of the orders_seq sequence.
Here some pics of the order and items page


This is how I did it on the orders view. First I made two calculated attributes CalculatedOrderTotal and CalculatedOrderLines on the orders entity. These attributes I use on the orders items entity. Then I generate the impl java class of the orders entity so I can change the getters of these calculated attributes.
/**Gets the attribute value for CalculatedOrderTotal, using the alias name CalculatedOrderTotal.
*/
public Double getCalculatedOrderTotal() {
RowIterator rowItr = this.getOrderItems();
Double total = 0.0;
while(rowItr.hasNext()){
Row row = rowItr.next();
Number unitPrice = (Number)row.getAttribute("UnitPrice");
Number quantity = (Number)row.getAttribute("Quantity");
total += (unitPrice.doubleValue() * quantity.intValue());
}
return total;
}
/**Sets value
as the attribute value for CalculatedOrderTotal.
*/
public void setCalculatedOrderTotal(Double value) {
setAttributeInternal(CALCULATEDORDERTOTAL, value);
}
/**Gets the attribute value for CalculatedOrderLines, using the alias name CalculatedOrderLines.
*/
public Number getCalculatedOrderLines() {
RowIterator rowItr = this.getOrderItems();
Number lineId = new Number(0);
while(rowItr.hasNext()){
Row row = rowItr.next();
Number lineIdRow = (Number)row.getAttribute("LineItemId");
// check the current Id is greater than lineId
if ( lineIdRow != null && lineIdRow.compareTo(lineId) == 1 ) {
lineId = lineIdRow;
}
}
return lineId;
}
/**Sets value
as the attribute value for CalculatedOrderLines.
*/
public void setCalculatedOrderLines(Number value) {
setAttributeInternal(CALCULATEDORDERLINES, value);
}
Now we add some code to the impl of the order items. First I try to set the next number for the line item , Then I set the unit item price of the selected product ( I can do this by using the association between order items and product information )the last step is to update the total order amount of the order
protected void prepareForDML(int dml, TransactionEvent evt) {
if (dml == DML_INSERT || dml == DML_UPDATE || dml == DML_DELETE) {
super.prepareForDML(dml,evt);
businessRules( dml);
}
}
public void businessRules(int dml){
if ( dml == DML_INSERT) {
Number row = this.getOrders().getCalculatedOrderLines();
this.setLineItemId(row.add(1));
}
if ( dml == DML_INSERT || dml == DML_UPDATE) {
ProductInformationImpl product = (ProductInformationImpl) this.getProductInformation();
if(product != null){
Number listPrice = product.getListPrice();
this.setUnitPrice(listPrice);
}
}
if ( dml == DML_UPDATE) {
Number oldQuantity = (Number)getPostedAttribute(getAttributeIndexOf("Quantity"));
System.out.println("new quantity "+this.getQuantity().toString()+" old "+oldQuantity.toString());
}
try {
this.getOrders().setOrderTotal(new Number(this.getOrders().getCalculatedOrderTotal()));;
}
catch ( Exception e) {
e.printStackTrace();
}
}
If you want to check the old and new values of an attribute then you can use getPostedAttribute to get the old value of the attribute. This is the same as :old and :new in the plsql triggers.
Now we implement the business rules on the orders entity. We add the following code to the orders impl
protected void prepareForDML(int dml, TransactionEvent evt) {
if (dml == DML_INSERT || dml == DML_UPDATE || dml == DML_DELETE) {
super.prepareForDML(dml,evt);
businessRules(dml);
}
}
public void businessRules(int dml){
if ( dml == DML_INSERT) {
SequenceImpl sequence = new SequenceImpl("ORDERS_SEQ", getDBTransaction());
this.setOrderId(sequence.getSequenceNumber());
this.setOrderDate(new Date(Date.getCurrentDate()));
}
}
In this method I set a database sequence on the Order Id and the current Date in the Order Date attribute.
Here you have the
sample project it works on jdeveloper 11g and on the oe sample schema