Question

I am creating an invoice management application using Grails, and am experiencing problems with inheritance.

If is my intention that each invoice should contain a collection of lines/items, and that when the invoice is formatted for printing, the items are sorted by date, separated into lists by category, then have the price of each line calculated in a different way for each concrete type (Timed items will lookup the hourly in the rates property, Priced items are assigned a price on creation).

Node Invoice has a property "items", which is a collection of Item objects.

Source of my domain classes:

class Invoice {
    static constraints = {
    }        
    String client

    Date dateCreated
    Date lastUpdated
    CostProfile rates

    def relatesToMany = [items : Item]
    Set items = new HashSet()
}

abstract class Item{
    static constraints = {
    }
    String description
    Date date
    enum category {SERVICE,GOODS,OTHER}
    def belongsTo = Invoice
    Invoice invoice
}

class TimedItem extends Item{

    static constraints = {
    }

    int minutes
}

class PricedItem extends Item{

    static constraints = {
    }

    BigDecimal cost
    BigDecimal taxrate
}

Source of the problematic code:

invoiceInstance.items.add(new TimedItem(description:"waffle", minutes:60, date:new Date(),category:"OTHER"))
def firstList = []
def lastList = []
invoiceInstance.items.sort{it.date}
invoiceInstance.items.each(){
    switch(((Item)it).category){
        case "LETTER":
            firstList.add(it)
        break;
        default:
            lastList.add(it)
    }
}

Error message:
groovy.lang.MissingPropertyException: No such property: category for class: TimedItem

Stacktrace indicates the 6th line of the above example.

Was it helpful?

Solution

You are using enum wrong. The enum keyword is similar to the class keyword. So while you defined your enum type, you never gave your class an instance of it. While you could leave the definition of the enum inside the abstract Item class, I moved it outside for clarity.

class Invoice {
    Set items = new HashSet()
}

enum ItemCategory {SERVICE,GOODS,OTHER}

abstract class Item{
    String description
    ItemCategory category
}

class TimedItem extends Item{
    int minutes
}


def invoice = new Invoice()
invoice.items.add(new TimedItem(description:"waffle", minutes:60, category: ItemCategory.OTHER))

invoice.items.each(){
    switch(it.category){
        case ItemCategory.OTHER:
            println("Other found")
        break
        default:
            println("Default")
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top