Input events now have start and end date
authorGeorgios Gousios <gousiosg@gmail.com>
Mon, 17 Oct 2011 08:52:46 +0000 (11:52 +0300)
committerGeorgios Gousios <gousiosg@gmail.com>
Mon, 17 Oct 2011 08:52:46 +0000 (11:52 +0300)
logic/src/main/scala/gr/grnet/aquarium/logic/Bills.scala
logic/src/main/scala/gr/grnet/aquarium/logic/accounting/AccountingEvent.scala
logic/src/main/scala/gr/grnet/aquarium/logic/accounting/Policy.scala
logic/src/main/scala/gr/grnet/aquarium/logic/events/EventProcessor.scala
logic/src/test/scala/gr/grnet/aquarium/logic/test/BillingTest.scala
logic/src/test/scala/gr/grnet/aquarium/logic/test/EventProcessorTest.scala

index 2b34dec..d22cb67 100644 (file)
@@ -1,12 +1,21 @@
 package gr.grnet.aquarium.logic
 
+import events.{EventProcessor, Event}
 import gr.grnet.aquarium.model._
-import collection.JavaConversions._
-import collection.immutable.HashSet
-import collection.mutable.Buffer
-import java.util.Date
 
 trait Bills {
 
+  def calcBills() = {
+    val entities = DB.findAll[Entity]("select e from Entity e")
+    //entities.foreach{x => calcBills(x)}
+  }
 
+  def calcBills(e: Entity) = {
+    EventProcessor.process(eventsFromDB(e))(f => true)
+  }
+
+  def eventsFromDB(e: Entity) : List[Event] = {
+    val events = List()
+    events
+  }
 }
\ No newline at end of file
index 0aad7f3..73360f0 100644 (file)
@@ -1,13 +1,19 @@
 package gr.grnet.aquarium.logic.accounting
 
 import agreements.AgreementRegistry
-import java.util.Date
 import gr.grnet.aquarium.model.{Entity, DB}
+import policies.DefaultRatePolicy
+import java.util.Date
+
 
-class AccountingEvent(et: AccountingEventType.Value, when: Date,
-                      who: Long, amount: Float, rel: List[Long]) {
+/** An accounting event represents any event that the accounting system
+ *  must process.
+ */
+class AccountingEvent(et: AccountingEventType.Value, start: Date,
+                      end: Date, who: Long, amount: Float, rel: List[Long]) {
 
-  def date() = when
+  def dateStart() = start
+  def dateEnd() = end
 
   def entity() = DB.find(classOf[Entity], who) match {
     case Some(x) => x
@@ -20,20 +26,25 @@ class AccountingEvent(et: AccountingEventType.Value, when: Date,
 
   def kind() = et
 
-  def process() = policy().process(this)
+  def process() = {
+    val evts =  policy().map{p => p.process(this)}
+    val total = evts.map(x => x.amount).foldLeft(0F)((a, sum) => a + sum)
+    new AccountingEntry(rel, new Date(), total, evts.head.entryType)
+  }
 
-  def policy(): Policy = {
+  def policy(): List[Policy] = {
     val agr = AgreementRegistry.getAgreement(entity().agreement) match {
       case Some(x) => x
       case None => throw new Exception("No agreement with id:" +
         entity().agreement)
     }
 
-    agr.policy(et, when) match {
+    /*agr.policy(et, when) match {
       case Some(x) => x
       case None => throw new Exception("No charging policy for event type:" +
         et + " in period starting from:" + when.getTime)
-    }
+    }*/
+    List()
   }
 
   def getRate(): Float = {
index 9f6d2d8..e87e059 100644 (file)
@@ -1,10 +1,12 @@
 package gr.grnet.aquarium.logic.accounting
 
+import java.util.Date
+
 
 abstract class Policy(et: AccountingEntryType.Value) {
 
   private def makeEntry(event: AccountingEvent, amount: Float) : AccountingEntry = {
-    new AccountingEntry(event.relatedEvents(),event.date(), amount, et)
+      new AccountingEntry(event.relatedEvents(), new Date(), amount, et)
   }
 
   def process(evt: AccountingEvent) = {
index a656fe3..f70c337 100644 (file)
@@ -5,55 +5,46 @@ import java.util.Date
 
 object EventProcessor {
 
-  def process(from: Option[Date], to: Option[Date],
-              events: (Option[Date], Option[Date]) => List[Event]): List[AccountingEvent] = {
-    val evts = events(from, to)
+  def process(events: List[Event])
+             (evtFilter: (Event) => Boolean): List[AccountingEvent] = {
 
-    val dummy = new AccountingEvent(AccountingEventType.VMTime, new Date() , 0, 0, List())
+    val evts = events.filter(evtFilter)
+    val dummy = new AccountingEvent(AccountingEventType.VMTime, new Date(), new Date(), 0, 0, List())
 
-    evts.map {f => f.who}.distinct.map {
-      //Events are calculated per user
-      u =>
-      //Time sorted list of events for user
-        val userEvents = evts.filter(_.who == u).sortBy(_.when)
-        userEvents.map {
-          e => e match {
-            case v: VMStarted => //Find stop event and calculate time usage
-              val stop = findVMStopEvent(userEvents, v)
-              val time =  stop match {
-                case Some(x) => x.when
-                case None => to.getOrElse(new Date()) //Now
-              }
-              val stopid =  stop match {
-                case Some(x) => x.id
-                case None => -1 //Now
-              }
-              val totaltime = time.getTime - v.w.getTime
-              assert(totaltime > 0)
-              new AccountingEvent(AccountingEventType.VMTime, e.when(),
-                             u, totaltime,
-                            List(v.id, stopid))
-            //          case v : VMStarted =>None
-            //          case v : VMStopped =>None
-            case v: DiskSpaceChanged =>
-              assert(v.bytes > 0)
-              new AccountingEvent(AccountingEventType.DiskSpace,
-                             e.when(), u, v.bytes, List(v.id()))
-            case v: DataUploaded =>
-              assert(v.bytes > 0)
-              new AccountingEvent(AccountingEventType.NetDataUp, e.when, u,
-                             v.bytes, List(v.id()))
-            case v: DataDownloaded =>
-              assert(v.bytes > 0)
-              new AccountingEvent(AccountingEventType.NetDataDown, e.when, u,
-                             v.bytes, List(v.id()))
-            //          case v : SSaasVMCreated => None
-            //          case v : SSaasVMStarted =>None
-            //          case v : SSaasVMStopped =>None
-            case _ => dummy
-          }
+    evts.sortBy(_.when).map {
+      e =>
+        val u = e.who()
+        e match {
+          case v: VMStarted => //Find stop event and calculate time usage
+            val stop = findVMStopEvent(evts, v)
+            val time = stop match {
+              case Some(x) => x.when
+              case None => new Date() //Now
+            }
+            val stopid = stop match {
+              case Some(x) => x.id
+              case None => -1 
+            }
+            val totaltime = time.getTime - v.w.getTime
+            assert(totaltime > 0)
+            new AccountingEvent(AccountingEventType.VMTime, e.when, time, u, totaltime, List(v.id, stopid))
+          //          case v : VMStarted =>None
+          //          case v : VMStopped =>None
+          case v: DiskSpaceChanged =>
+            assert(v.bytes > 0)
+            new AccountingEvent(AccountingEventType.DiskSpace, e.when, e.when, u, v.bytes, List(v.id()))
+          case v: DataUploaded =>
+            assert(v.bytes > 0)
+            new AccountingEvent(AccountingEventType.NetDataUp, e.when, e.when, u, v.bytes, List(v.id()))
+          case v: DataDownloaded =>
+            assert(v.bytes > 0)
+            new AccountingEvent(AccountingEventType.NetDataDown, e.when, e.when, u, v.bytes, List(v.id()))
+          //          case v : SSaasVMCreated => None
+          //          case v : SSaasVMStarted =>None
+          //          case v : SSaasVMStopped =>None
+          case _ => dummy
         }
-    }.flatten.filter(p => p != dummy) //Remove dummy events
+    }.filter(p => p != dummy) //Remove dummy events
   }
 
   /**Find a the first corresponding VM stop event in a list of messages*/
index 6880e49..802a0bc 100644 (file)
@@ -5,9 +5,9 @@ import org.junit.Assert._
 import gr.grnet.aquarium.logic.Bills
 import gr.grnet.aquarium.model.{User, DB}
 import gr.grnet.aquarium.logic.accounting.policies.DefaultRatePolicy
-import java.util.Date
 import gr.grnet.aquarium.logic.accounting.{Agreement, AccountingEvent, AccountingEntryType, AccountingEventType}
 import gr.grnet.aquarium.logic.accounting.agreements.AgreementRegistry
+import java.util.Date
 
 class BillingTest
   extends FixtureLoader with Bills {
@@ -49,11 +49,17 @@ class BillingTest
 
     DB.persistAndFlush(u)
 
-    val evt = new AccountingEvent(AccountingEventType.VMTime,
-      new Date(4), u.id, 15, List())
-    val entry = evt.process()
-
+    // Try with a basic event
+    var evt = new AccountingEvent(AccountingEventType.VMTime,
+      new Date(4), new Date(10), u.id, 15, List())
+    var entry = evt.process()
     assertEquals(entry.amount, 15 * 0.001F, 0.00001)
+
+    // Try with another event type
+    evt = new AccountingEvent(AccountingEventType.DiskSpace,
+      new Date(4), new Date(4), u.id, 12.3F, List())
+    entry = evt.process()
+    assertEquals(entry.amount, 12.3F * 0.00002F, 0.00001)
   }
 
   @After
index b43b84c..1f9c6b9 100644 (file)
@@ -7,7 +7,7 @@ import org.junit.Assert._
 
 class EventProcessorTest {
 
-   def getEvents(from: Option[Date], to: Option[Date]): List[Event] = {
+   def getEvents(): List[Event] = {
     //Tmp list of events
     List[Event](
       new VMCreated(1, new Date(123), 2, 1),
@@ -23,7 +23,7 @@ class EventProcessorTest {
   
   @Test
   def testProcess() = {
-    var result = EventProcessor.process(None, None, getEvents)
+    val result = EventProcessor.process(getEvents)(f => true)
     assert(result.size == 6)
   }
 }
\ No newline at end of file