views:

87

answers:

3

I've been trying to figure out the best way to model this entity, and I'm getting stuck. Here's the basic use case/story:

We have equipment arriving on site. We won't know what the equipment is until it arrives. Once the equipment arrives on site it must be recorded as having arrived and whether it was idle or active. If it is active the user must make note of the work the equipment performed. When the equipment leaves the site, this must be noted.

I should be able to easily query whether there is any equipment on the site, what equipment was previously on site, etc.

I'm getting stuck on the date aspect. I'm trying to avoid relying on a cron job to run through and mark equipment as idle if it hasn't been marked idle on a paticular date. It feels like there should be a way to do this. Here's what I've come up with:

public class Equipment {
    public int Id { get; set; }
    public Site Site { get; set; }
    public DateTime Arrival { get; set; }
    public DateTime Departure { get; set; }
    public IList<EquipmentUtilization> EquipmentUtilizations { get; set; }
}

public class EquipmentUtilization {
    public int Id { get; set; }
    public Equipment Equipment { get; set; }
    public DateTime ReportDate { get; set; }
    public string WorkPerformed { get; set; }
}

The idea being that I could run a query like Site.Equipment.Where(x=>x.Departure == null) to see which equipment is still on site. If there's no EquipmentUtilization for a particular date, it is assume do be idle. I could then setup a DateTimeEnumerator:

public class DateTimeEnumerator : System.Collections.IEnumerable
{
    private DateTime begin;
    private DateTime end;

    public DateTimeEnumerator ( DateTime begin , DateTime end ) 
    {            
        this.begin = begin;
        this.end = end;
    }
    public System.Collections.IEnumerator GetEnumerator()
    {
        for(DateTime date = begin; date < end; date = date.AddDays(1))
        {
            yield return date;
        }
    }
}

Build a list of dates from the arrival date until DateTime.Now or DepatureDate if that is not null. For some reason this seems ugly. Should I put the DateTime enumerator inside by Equipment object? It feels like this should all be together or done in some different manner, though this does work if I run it. Suggestions?

+1  A: 

If I understand you correctly, you seek a way to determine what equipment is idle at a given site on a given date based on the captured equipmentutilization objects associated with your Equipment (perhaps EquipmentResidency is a better name?) collection.

As you want to avoid creating equipmentutilization objects for idle days (I agree that could be significant maintenance), how about adding a isIdleOn(Date) method to the equipmentutilization class that returns true if the passed Date matches the captured ReportDate and false if it does not?

The associated query would be something along the lines of Site.Equipment.Where(x=>x.equipmentutilization.isIdleOn(date) == true)

Not sure if I have the syntax right, but just a suggestion.

KMW
A: 

One potential problem I see is a piece of equipment only knows its current site. If you want to know if Loader123 was at SiteXYZ 2 months ago, you cannot retrieve that information, using your current model.

It looks like your granularity of usage is for a given day. That definitely makes things simpler, as you don't need to figure out how to track it, if a piece of equipment is used from 11pm-4am on SiteABC, then 1pm-5pm on SiteXYZ.

With those things in mind, I would make a couple slight changes to your model. I would keep a collection of all the sites the equipment had been at (Equipment.History), and provide a convenience function to find the site it's currently at (whichever SiteHistory.Departure doesn't have a value). For the utilizations themselves, I would provide a convenience function to return them as dictionary, keyed by DateTime. You could then do operations on that dictionary's key collection, to easily count how many days a piece of equipment was actually utilized within a given period.

public class Equipment 
{
    public int Id { get; set; }
    public IList<SiteHistory> History { get; set; }
    public IList<EquipmentUtilization> EquipmentUtilizations { get; set; }
    public IDictionary<DateTime, EquipmentUtilization> UtilizationsDictionary { get{...} }
    public Site CurrentSite { get{...} }
}

public class SiteHistory {
    public Site Site { get; set; }
    public DateTime Arrival { get; set; }
    public DateTime? Departure { get; set; }
}

public class EquipmentUtilization {
    public int Id { get; set; }
    public Equipment Equipment { get; set; }  // is this a circular-reference back to the parent?  Might be able to omit it.
    public DateTime ReportDate { get; set; }
    public string WorkPerformed { get; set; }
}

As with any quick-n-dirty design, I'm sure this one has some holes, and could use some refinements. But hopefully it gets you a little closer to what you're looking for.

mikemanne
A: 

I wouldn't have a DateTime enumerator personally; like you said, it sounds wrong.

I must admit I'm struggling to follow you here when you say something should be classed as idle. Whatever you use to determine if something is idle you could be put in a property, e.g:

public class Equipment
{ 
    public int Id { get; set; } 
    public Site Site { get; set; } 
    public DateTime Arrival { get; set; } 
    public DateTime Departure { get; set; } 
    public IList<EquipmentUtilization> EquipmentUtilizations { get; set; }

    public bool IsIdle
    {
        get
        {
            // This checks if the EquipmentUtilizations is empty
            // or if the Equipment is older than three days
            return (this.EquipmentUtilizations == null) ||
                   ((this.Departure == null) &&
                    (this.Arrival < DateTime.Today.AddDays(-3))
        }
    }
}
Sam