Revision ecceede8

b/src/main/scala/gr/grnet/aquarium/logic/accounting/Accounting.scala
63 63
    val instanceId = currentResourceEvent.instanceId
64 64
    val currentValue = currentResourceEvent.value
65 65
    val currentOccurredMillis = currentResourceEvent.occurredMillis
66
    val currentResourceEventDebugStr = currentResourceEvent.toDebugString(defaultResourcesMap, false)
67
    
68

  
69
    def validateCostPolicy(toCheck: DSLCostPolicy, whatEvent: String) {
70
      if(costPolicy != toCheck) {
71
        throw new Exception("Actual cost policy %s is not the same as provided %s for %s event %s".
72
          format(costPolicy, toCheck, whatEvent, currentResourceEventDebugStr))
73
      }
74
    }
75
    def validateCostPolicyM(toCheckM: Maybe[DSLCostPolicy], whatEvent: String): Unit = {
76
      toCheckM match {
77
        case Just(toCheck) ⇒
78
          validateCostPolicy(toCheck, whatEvent)
79

  
80
        case _ ⇒
81
          throw new Exception("Could not verify cost policy %s for %s event %s".
82
            format(costPolicy, whatEvent, currentResourceEventDebugStr))
83
      }
84
    }
66 85

  
67 86
    /////////////////////////////////////////////////////////////////////
68 87
    // Validations
69 88
    /////////////////////////////////////////////////////////////////////
70
    // 1. Validate cost policy
71
    val actualCostPolicyM = currentResourceEvent.findCostPolicyM(defaultResourcesMap)
72
    val currentResourceEventDebugStr = currentResourceEvent.toDebugString(defaultResourcesMap, false)
73
    actualCostPolicyM match {
74
      case Just(actualCostPolicy) ⇒
75
        if(costPolicy != actualCostPolicy) {
76
          throw new Exception("Actual cost policy %s is not the same as provided %s for event %s".
77
            format(actualCostPolicy, costPolicy, currentResourceEventDebugStr))
78
        }
79
      case _ ⇒
80
        throw new Exception("Could not verify cost policy %s for event %s".
81
          format(costPolicy, currentResourceEventDebugStr))
82
    }
89
    // 1. Validate cost policy for current event
90
    val currentEventCostPolicyM = currentResourceEvent.findCostPolicyM(defaultResourcesMap)
91
    validateCostPolicyM(currentEventCostPolicyM, "current")
83 92

  
84 93
    // 2. Validate previous resource event
85 94
    previousResourceEventM match {
95
      // We have a previous event
86 96
      case Just(previousResourceEvent) ⇒
87 97
        if(!costPolicy.needsPreviousEventForCreditAndAmountCalculation) {
88 98
          throw new Exception("Provided previous event but cost policy %s does not need one".format(costPolicy))
89 99
        }
90 100

  
91
        // 3. resource and instanceId
101
        // 3. Validate resource and instanceId for previous resource event
92 102
        val previousResource = previousResourceEvent.resource
93 103
        val previousInstanceId = previousResourceEvent.instanceId
94 104
        (resource == previousResource, instanceId == previousInstanceId) match {
......
107 117
              format((resource, instanceId), (previousResource, previousInstanceId)))
108 118
        }
109 119

  
120
        // 4. Validate cost policy for previous resource event
121
        val previousEventCostPolicyM = previousResourceEvent.findCostPolicyM(defaultResourcesMap)
122
        validateCostPolicyM(previousEventCostPolicyM, "previous")
123

  
124
      // We do not have a previous event
110 125
      case NoVal ⇒
111 126
        if(costPolicy.needsPreviousEventForCreditAndAmountCalculation) {
112
          throw new Exception("Did not provid previous event but cost policy %s needa one".format(costPolicy))
127
          throw new Exception("Did not provide previous event but cost policy %s needs one".format(costPolicy))
113 128
        }
114 129

  
130
      // We cannot obtain a previous resource event
115 131
      case failed @ Failed(e, m) ⇒
116 132
        throw new Exception("Error obtaining previous event".format(m), e)
117 133
    }
118 134

  
119
    // 4. Make sure this is billable.
120
    // It is the caller's responsibility to provide us with billable events
135
    // 5. Make the current event is billable.
136
    //    It is the caller's responsibility to provide us with billable events
121 137
    costPolicy.isBillableEventBasedOnValue(currentValue) match {
122 138
      case true  ⇒
123 139
      case false ⇒
124
        throw new Exception("Event not billable %s".format(currentResourceEventDebugStr))
140
        throw new Exception("Not billable event %s".format(currentResourceEventDebugStr))
125 141
    }
126 142
    /////////////////////////////////////////////////////////////////////
127 143

  
......
131 147
      previousAccumulatingAmountM.getOr(0.0),
132 148
      currentOccurredMillis - previousResourceEventM.map(_.occurredMillis).getOr(currentOccurredMillis),
133 149
      previousResourceEventM.map(_.value).getOr(0.0),
134
      currentValue)
150
      currentValue,
151
      1.0 /*UNITPRICE*/)
135 152
    // Now, we need to find the proper agreement(s) and feed the data to them.
136 153

  
137

  
138 154
    Nil
139 155
  }
140 156

  
......
218 234
   * Creates a list of wallet entries by applying the agreement provisions on
219 235
   * the resource state.
220 236
   *
221
   * @param resourceEvent The resource event to create charges for
237
   * @param currentResourceEvent The resource event to create charges for
222 238
   * @param agreement The agreement applicable to the user mentioned in the event
223
   * @param currentValue The current state of the resource
224
   * @param currentSnapshotDate The last time the resource state was updated
239
   * @param previousAmount The current state of the resource
240
   * @param previousOccurred The last time the resource state was updated
225 241
   */
226
  def chargeEvent(resourceEvent: ResourceEvent,
227
                  agreement: DSLAgreement,
228
                  currentValue: Double,
229
                  currentSnapshotDate: Date,
242
  def chargeEvent(currentResourceEvent: ResourceEvent,
243
                  agreements: List[String],
244
                  previousAmount: Double,
245
                  previousOccurred: Date,
230 246
                  related: List[WalletEntry]): Maybe[List[WalletEntry]] = {
231 247

  
232
    assert(currentSnapshotDate.getTime <= resourceEvent.occurredMillis)
248
    assert(previousOccurred.getTime <= currentResourceEvent.occurredMillis)
233 249

  
234
    if (!resourceEvent.validate())
250
    if (!currentResourceEvent.validate())
235 251
      return Failed(new AccountingException("Event not valid"))
236 252

  
237 253
    val policy = Policy.policy
238
    val dslResource = policy.findResource(resourceEvent.resource) match {
254
    val dslResource = policy.findResource(currentResourceEvent.resource) match {
239 255
      case Some(x) => x
240
      case None => return Failed(new AccountingException("No resource [%s]".format(resourceEvent.resource)))
256
      case None => return Failed(new AccountingException("No resource [%s]".format(currentResourceEvent.resource)))
241 257
    }
242 258

  
243 259
    /* This is a safeguard against the special case where the last
......
246 262
     * this is the first time the resource state has been recorded.
247 263
     * Charging in this case only makes sense for discrete resources.
248 264
     */
249
    if (currentSnapshotDate.getTime == resourceEvent.occurredMillis) {
265
    if (previousOccurred.getTime == currentResourceEvent.occurredMillis) {
250 266
      dslResource.costPolicy match {
251 267
        case DiscreteCostPolicy => //Ok
252 268
        case _ => return Some(List())
253 269
      }
254 270
    }
255 271

  
256
    val creditCalculationValueM = dslResource.costPolicy.getValueForCreditCalculation(Just(currentValue), resourceEvent.value)
272
    val creditCalculationValueM = dslResource.costPolicy.getValueForCreditCalculation(Just(previousAmount), currentResourceEvent.value)
257 273
    val amount = creditCalculationValueM match {
258 274
      case failed @ Failed(_, _) ⇒
259 275
        return failed
......
267 283
    // above, since this point won't be reached in case of error.
268 284
    val isFinal = dslResource.costPolicy match {
269 285
      case OnOffCostPolicy =>
270
        OnOffPolicyResourceState(currentValue) match {
286
        OnOffPolicyResourceState(previousAmount) match {
271 287
          case OnResourceState => false
272 288
          case OffResourceState => true
273 289
        }
......
275 291
    }
276 292

  
277 293
    val timeslot = dslResource.costPolicy match {
278
      case DiscreteCostPolicy => Timeslot(new Date(resourceEvent.occurredMillis),
279
        new Date(resourceEvent.occurredMillis + 1))
280
      case _ => Timeslot(currentSnapshotDate, new Date(resourceEvent.occurredMillis))
294
      case DiscreteCostPolicy => Timeslot(new Date(currentResourceEvent.occurredMillis),
295
        new Date(currentResourceEvent.occurredMillis + 1))
296
      case _ => Timeslot(previousOccurred, new Date(currentResourceEvent.occurredMillis))
281 297
    }
282 298

  
283 299
    val chargeChunks = calcChangeChunks(agreement, amount, dslResource, timeslot)
284 300

  
285 301
    val timeReceived = System.currentTimeMillis
286 302

  
287
    val rel = related.map{x => x.sourceEventIDs}.flatten ++ List(resourceEvent.id)
303
    val rel = related.map{x => x.sourceEventIDs}.flatten ++ List(currentResourceEvent.id)
288 304

  
289 305
    val entries = chargeChunks.map {
290 306
      c =>
291 307
        WalletEntry(
292 308
          id = CryptoUtils.sha1(c.id),
293
          occurredMillis = resourceEvent.occurredMillis,
309
          occurredMillis = currentResourceEvent.occurredMillis,
294 310
          receivedMillis = timeReceived,
295 311
          sourceEventIDs = rel,
296 312
          value = c.cost,
297 313
          reason = c.reason,
298
          userId = resourceEvent.userId,
299
          resource = resourceEvent.resource,
300
          instanceId = resourceEvent.instanceId,
314
          userId = currentResourceEvent.userId,
315
          resource = currentResourceEvent.resource,
316
          instanceId = currentResourceEvent.instanceId,
301 317
          finalized = isFinal
302 318
        )
303 319
    }

Also available in: Unified diff