diff --git a/engine/account.go b/engine/account.go index 89bdecef1..5f7b0eba4 100644 --- a/engine/account.go +++ b/engine/account.go @@ -1161,7 +1161,7 @@ func NewAccountSummaryFromJSON(jsn string) (acntSummary *AccountSummary, err err type AccountSummary struct { Tenant string ID string - BalanceSummaries []*BalanceSummary + BalanceSummaries BalanceSummaries AllowNegative bool Disabled bool } @@ -1173,7 +1173,7 @@ func (as *AccountSummary) Clone() (cln *AccountSummary) { cln.AllowNegative = as.AllowNegative cln.Disabled = as.Disabled if as.BalanceSummaries != nil { - cln.BalanceSummaries = make([]*BalanceSummary, len(as.BalanceSummaries)) + cln.BalanceSummaries = make(BalanceSummaries, len(as.BalanceSummaries)) for i, bs := range as.BalanceSummaries { cln.BalanceSummaries[i] = new(BalanceSummary) *cln.BalanceSummaries[i] = *bs diff --git a/engine/balances.go b/engine/balances.go index 3d789c75a..c0675af85 100644 --- a/engine/balances.go +++ b/engine/balances.go @@ -896,3 +896,16 @@ type BalanceSummary struct { Value float64 Disabled bool } + +type BalanceSummaries []*BalanceSummary + +// GetBalanceSummary returns a BalanceSummary based on an UUID +func (bs BalanceSummaries) BalanceSummaryWithUUD(bsUUID string) (b *BalanceSummary) { + for _, blc := range bs { + if blc.UUID == bsUUID { + b = blc + break + } + } + return +} diff --git a/engine/cdrs.go b/engine/cdrs.go index 64f1e736b..57b77c1a5 100644 --- a/engine/cdrs.go +++ b/engine/cdrs.go @@ -286,6 +286,11 @@ func (cdrS *CDRServer) rateCDRWithErr(cdr *CDRWithArgDispatcher) (ratedCDRs []*C return } +func (cdrS *CDRServer) refundCDR(cdr *CDR) (err error) { + + return +} + // chrgProcessEvent will process the CGREvent with ChargerS subsystem // it is designed to run in it's own goroutine func (cdrS *CDRServer) chrgProcessEvent(cgrEv *utils.CGREventWithArgDispatcher, diff --git a/engine/eventcost.go b/engine/eventcost.go index a702f0dc5..8f6333a36 100644 --- a/engine/eventcost.go +++ b/engine/eventcost.go @@ -254,6 +254,62 @@ func (ec *EventCost) ComputeEventCostUsageIndexes() { } } +// AsCallDescriptor converts an EventCost into a CallDescriptor +func (ec *EventCost) AsRefundIncrements(tor string) (cd *CallDescriptor) { + cd = &CallDescriptor{ + CgrID: ec.CGRID, + RunID: ec.RunID, + TOR: tor, + TimeStart: ec.StartTime, + TimeEnd: ec.StartTime.Add(ec.GetUsage()), + DurationIndex: ec.GetUsage(), + } + if len(ec.Charges) == 0 { + return + } + var nrIcrms int + for _, cIl := range ec.Charges { + nrIcrms += (cIl.CompressFactor * len(cIl.Increments)) + } + cd.Increments = make(Increments, nrIcrms) + var iIdx int + for _, cIl := range ec.Charges { + for i := 0; i < cIl.CompressFactor; i++ { + for _, cIcrm := range cIl.Increments { + cd.Increments[iIdx] = &Increment{ + Cost: cIcrm.Cost, + Duration: cIcrm.Usage, + CompressFactor: cIcrm.CompressFactor, + } + if cIcrm.AccountingID != utils.EmptyString { + cd.Increments[iIdx].BalanceInfo = &DebitInfo{ + AccountID: ec.Accounting[cIcrm.AccountingID].AccountID, + } + blncSmry := ec.AccountSummary.BalanceSummaries.BalanceSummaryWithUUD(ec.Accounting[cIcrm.AccountingID].BalanceUUID) + if blncSmry.Type == utils.MONETARY { + cd.Increments[iIdx].BalanceInfo.Monetary = &MonetaryInfo{UUID: blncSmry.UUID} + } else if NonMonetaryBalances.HasField(blncSmry.Type) { + cd.Increments[iIdx].BalanceInfo.Unit = &UnitInfo{UUID: blncSmry.UUID} + } + if ec.Accounting[cIcrm.AccountingID].ExtraChargeID == utils.META_NONE || + ec.Accounting[cIcrm.AccountingID].ExtraChargeID == utils.EmptyString { + continue + } + // extra charges, ie: non-free *voice + extraSmry := ec.AccountSummary.BalanceSummaries.BalanceSummaryWithUUD(ec.Accounting[cIcrm.AccountingID].ExtraChargeID) + if extraSmry.Type == utils.MONETARY { + cd.Increments[iIdx].BalanceInfo.Monetary = &MonetaryInfo{UUID: extraSmry.UUID} + } else if NonMonetaryBalances.HasField(blncSmry.Type) { + cd.Increments[iIdx].BalanceInfo.Unit = &UnitInfo{UUID: extraSmry.UUID} + } + } + } + } + } + return +} + +// AsCallCost converts an EventCost into a CallCost func (ec *EventCost) AsCallCost() *CallCost { cc := &CallCost{ Cost: ec.GetCost(), RatedUsage: float64(ec.GetUsage().Nanoseconds()), @@ -271,10 +327,10 @@ func (ec *EventCost) AsCallCost() *CallCost { if cIl.RatingID != "" { if ec.Rating[cIl.RatingID].RatingFiltersID != "" { rfs := ec.RatingFilters[ec.Rating[cIl.RatingID].RatingFiltersID] - ts.MatchedSubject = rfs["Subject"].(string) - ts.MatchedPrefix = rfs["DestinationPrefix"].(string) - ts.MatchedDestId = rfs["DestinationID"].(string) - ts.RatingPlanId = rfs["RatingPlanID"].(string) + ts.MatchedSubject = rfs[utils.Subject].(string) + ts.MatchedPrefix = rfs[utils.DestinationPrefix].(string) + ts.MatchedDestId = rfs[utils.DestinationID].(string) + ts.RatingPlanId = rfs[utils.RatingPlanID].(string) } } ts.RateInterval = ec.rateIntervalForRatingID(cIl.RatingID) diff --git a/engine/libeventcost.go b/engine/libeventcost.go index 5d9c48109..613bb0403 100644 --- a/engine/libeventcost.go +++ b/engine/libeventcost.go @@ -27,6 +27,14 @@ import ( "github.com/cgrates/cgrates/utils" ) +// NonMonetaryBalances are types of balances which are not handled as monetary +var NonMonetaryBalances = MapEvent{ + utils.VOICE: struct{}{}, + utils.SMS: struct{}{}, + utils.DATA: struct{}{}, + utils.GENERIC: struct{}{}, +} + // ChargingInterval represents one interval out of Usage providing charging info // eg: PEAK vs OFFPEAK type ChargingInterval struct { diff --git a/utils/consts.go b/utils/consts.go index f60704671..5b8e10f7a 100755 --- a/utils/consts.go +++ b/utils/consts.go @@ -548,6 +548,8 @@ const ( UUID = "UUID" ActionsID = "ActionsID" MetaAct = "*act" + DestinationPrefix = "DestinationPrefix" + DestinationID = "DestinationID" ) // Migrator Action