mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
Revise CDR rerating
If the reRate parameter is set to true, also set the refund to true. The rerate parameter is now no longer hardcoded to true for the RateCDRs API.If required, the "*rerate" flag must be provided by the caller. In case CostDetails is not populated, retrieve it from StorDB if possible and add it to the CGREvent before converting to CDRs. Now that the refund happens before the debit, revise the expected values for the testV1CDRsProcessEventWithRefund subtest within the apier/v1/cdrs_it_test.go file.
This commit is contained in:
committed by
Dan Christian Bogos
parent
f4c1fa0d3d
commit
373df2329c
@@ -288,7 +288,7 @@ func testV2CDRsRateCDRs(t *testing.T) {
|
||||
|
||||
if err := cdrsRpc.Call(utils.CDRsV1RateCDRs, &engine.ArgRateCDRs{
|
||||
RPCCDRsFilter: utils.RPCCDRsFilter{NotRunIDs: []string{"raw"}},
|
||||
Flags: []string{"*chargers:false"},
|
||||
Flags: []string{"*chargers:false", utils.MetaRerate},
|
||||
}, &reply); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
} else if reply != utils.OK {
|
||||
@@ -664,7 +664,7 @@ func testV2CDRsRateCDRsWithRatingPlan(t *testing.T) {
|
||||
|
||||
if err := cdrsRpc.Call(utils.CDRsV1RateCDRs, &engine.ArgRateCDRs{
|
||||
RPCCDRsFilter: utils.RPCCDRsFilter{NotRunIDs: []string{"raw"}, Accounts: []string{"testV2CDRsProcessCDR4"}},
|
||||
Flags: []string{"*chargers:true"},
|
||||
Flags: []string{"*chargers:true", utils.MetaRerate},
|
||||
}, &reply); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
} else if reply != utils.OK {
|
||||
|
||||
@@ -500,6 +500,30 @@ func (cdrS *CDRServer) processEvents(evs []*utils.CGREvent,
|
||||
cdrs := make([]*CDR, len(cgrEvs))
|
||||
if refund || ralS || store || reRate || export {
|
||||
for i, cgrEv := range cgrEvs {
|
||||
if refund {
|
||||
if _, has := cgrEv.Event[utils.CostDetails]; !has {
|
||||
// if CostDetails is not populated or is nil, look for it inside the previously stored cdr
|
||||
var cgrID string // prepare CGRID to filter for previous CDR
|
||||
if val, has := cgrEv.Event[utils.CGRID]; !has {
|
||||
cgrID = utils.Sha1(utils.IfaceAsString(cgrEv.Event[utils.OriginID]),
|
||||
utils.IfaceAsString(cgrEv.Event[utils.OriginHost]))
|
||||
} else {
|
||||
cgrID = utils.IfaceAsString(val)
|
||||
}
|
||||
var prevCDRs []*CDR // only one should be returned
|
||||
if prevCDRs, _, err = cdrS.cdrDb.GetCDRs(
|
||||
&utils.CDRsFilter{CGRIDs: []string{cgrID},
|
||||
RunIDs: []string{utils.IfaceAsString(cgrEv.Event[utils.RunID])}}, false); err != nil {
|
||||
utils.Logger.Err(
|
||||
fmt.Sprintf("<%s> could not retrieve previously stored CDR, error: <%s>",
|
||||
utils.CDRs, err.Error()))
|
||||
err = utils.ErrPartiallyExecuted
|
||||
return
|
||||
} else {
|
||||
cgrEv.Event[utils.CostDetails] = prevCDRs[0].CostDetails
|
||||
}
|
||||
}
|
||||
}
|
||||
if cdrs[i], err = NewMapEvent(cgrEv.Event).AsCDR(cdrS.cgrCfg,
|
||||
cgrEv.Tenant, cdrS.cgrCfg.GeneralCfg().DefaultTimezone); err != nil {
|
||||
utils.Logger.Warning(
|
||||
@@ -516,25 +540,13 @@ func (cdrS *CDRServer) processEvents(evs []*utils.CGREvent,
|
||||
}
|
||||
if refund {
|
||||
for i, cdr := range cdrs {
|
||||
if cdr.CostDetails == nil { // if CostDetails is not populated, look for it inside the previously stored cdr
|
||||
var prevCDRs []*CDR // only one should be returned
|
||||
if prevCDRs, _, err = cdrS.cdrDb.GetCDRs(
|
||||
&utils.CDRsFilter{CGRIDs: []string{cdr.CGRID},
|
||||
RunIDs: []string{cdr.RunID}}, false); err != nil {
|
||||
utils.Logger.Info(
|
||||
fmt.Sprintf("<%s> could not retrieve previously stored CDR, error: <%s>",
|
||||
utils.CDRs, err.Error()))
|
||||
continue
|
||||
}
|
||||
cdr.CostDetails = prevCDRs[0].CostDetails
|
||||
}
|
||||
if rfnd, errRfd := cdrS.refundEventCost(cdr.CostDetails,
|
||||
cdr.RequestType, cdr.ToR); errRfd != nil {
|
||||
utils.Logger.Warning(
|
||||
fmt.Sprintf("<%s> error: <%s> refunding CDR %+v",
|
||||
utils.CDRs, errRfd.Error(), utils.ToJSON(cdr)))
|
||||
} else if rfnd {
|
||||
cdr.CostDetails = nil
|
||||
cdr.CostDetails = nil // this makes sure that the rater will recalculate (and debit) the cost
|
||||
procFlgs[i].Add(utils.MetaRefund)
|
||||
}
|
||||
}
|
||||
@@ -1093,6 +1105,10 @@ func (cdrS *CDRServer) V1RateCDRs(arg *ArgRateCDRs, reply *string) (err error) {
|
||||
if flgs.Has(utils.MetaAttributes) {
|
||||
attrS = flgs.GetBool(utils.MetaAttributes)
|
||||
}
|
||||
var reRate bool
|
||||
if flgs.Has(utils.MetaRerate) {
|
||||
reRate = flgs.GetBool(utils.MetaRerate)
|
||||
}
|
||||
|
||||
if chrgS && len(cdrS.cgrCfg.CdrsCfg().ChargerSConns) == 0 {
|
||||
return utils.NewErrNotConnected(utils.ChargerS)
|
||||
@@ -1104,7 +1120,7 @@ func (cdrS *CDRServer) V1RateCDRs(arg *ArgRateCDRs, reply *string) (err error) {
|
||||
cgrEvs[i].APIOpts = arg.APIOpts
|
||||
}
|
||||
if _, err = cdrS.processEvents(cgrEvs, chrgS, attrS, false,
|
||||
true, store, true, export, thdS, statS); err != nil {
|
||||
true, store, reRate, export, thdS, statS); err != nil {
|
||||
return utils.NewErrServerError(err)
|
||||
}
|
||||
|
||||
|
||||
@@ -339,7 +339,7 @@ func testRerateCDRsGetAccountAfterProcessEvent2(t *testing.T) {
|
||||
func testRerateCDRsRerateCDRs(t *testing.T) {
|
||||
var reply string
|
||||
if err := rrCdrsRPC.Call(utils.CDRsV1RateCDRs, &engine.ArgRateCDRs{
|
||||
Flags: []string{utils.MetaRALs},
|
||||
Flags: []string{utils.MetaRerate},
|
||||
RPCCDRsFilter: utils.RPCCDRsFilter{
|
||||
OrderBy: utils.AnswerTime,
|
||||
CGRIDs: []string{rrCdrsUUID},
|
||||
|
||||
@@ -439,7 +439,7 @@ func testRerateExpGetAccountAfterProcessEvent3(t *testing.T) {
|
||||
func testRerateExpRerateCDRs(t *testing.T) {
|
||||
var reply string
|
||||
if err := ng2RPC.Call(utils.CDRsV1RateCDRs, &engine.ArgRateCDRs{
|
||||
Flags: []string{utils.MetaRALs},
|
||||
Flags: []string{utils.MetaRerate},
|
||||
RPCCDRsFilter: utils.RPCCDRsFilter{
|
||||
OrderBy: utils.AnswerTime,
|
||||
CGRIDs: []string{ng1UUID, ng2UUID},
|
||||
|
||||
Reference in New Issue
Block a user