diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 6c3e9a5e2..5a7a3d429 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -43,6 +43,7 @@ information, please see the [`CONTRIBUTING.md`](CONTRIBUTING.md) file. | @noahmehl | Noah Mehl | | @elfranne | Tom Braarup Cuykens | | @rbarrabe | Régis Barrabé | +| @J0hnSteel | John Koce Steel | diff --git a/apier/v1/apier.go b/apier/v1/apier.go index 6e44a7732..1c6162ffe 100644 --- a/apier/v1/apier.go +++ b/apier/v1/apier.go @@ -387,7 +387,8 @@ func (self *ApierV1) LoadTariffPlanFromStorDb(attrs AttrLoadTpFromStorDb, reply } if len(cstKeys) != 0 && self.CdrStatsSrv != nil { - if err := self.CdrStatsSrv.Call("CDRStatsV1.ReloadQueues", cstKeys, nil); err != nil { + var out int + if err := self.CdrStatsSrv.Call("CDRStatsV1.ReloadQueues", cstKeys, &out); err != nil { return err } } diff --git a/data/tariffplans/test/destinations/multiid/DestinationRates.csv b/data/tariffplans/test/destinations/multiid/DestinationRates.csv new file mode 100644 index 000000000..b5d98941e --- /dev/null +++ b/data/tariffplans/test/destinations/multiid/DestinationRates.csv @@ -0,0 +1,4 @@ +#Tag,DestinationsTag,RatesTag,RoundingMethod,RoundingDecimals,MaxCost,MaxCostStrategy +DR_RETAIL,GERMANY,RT_1CENT,*up,4,0, +DR_SMS_1,EUROPE,RT_SMS_5c,*up,4,0, + diff --git a/data/tariffplans/test/destinations/multiid/Destinations.csv b/data/tariffplans/test/destinations/multiid/Destinations.csv new file mode 100644 index 000000000..3bc073d07 --- /dev/null +++ b/data/tariffplans/test/destinations/multiid/Destinations.csv @@ -0,0 +1,4 @@ +#Tag,Prefix +GERMANY,+49 +EUROPE,+40 +EUROPE,+49 diff --git a/data/tariffplans/test/destinations/multiid/Rates.csv b/data/tariffplans/test/destinations/multiid/Rates.csv new file mode 100644 index 000000000..fe4ee0664 --- /dev/null +++ b/data/tariffplans/test/destinations/multiid/Rates.csv @@ -0,0 +1,3 @@ +#Tag,ConnectFee,Rate,RateUnit,RateIncrement,GroupIntervalStart +RT_1CENT,0,1,1s,1s,0s +RT_SMS_5c,0,0.005,1,1,0 diff --git a/data/tariffplans/test/destinations/multiid/RatingPlans.csv b/data/tariffplans/test/destinations/multiid/RatingPlans.csv new file mode 100644 index 000000000..73b20244d --- /dev/null +++ b/data/tariffplans/test/destinations/multiid/RatingPlans.csv @@ -0,0 +1,3 @@ +#Tag,DestinationRatesTag,TimingTag,Weight +RP_RETAIL,DR_RETAIL,ALWAYS,20 +RP_RETAIL,DR_SMS_1,ALWAYS,10 diff --git a/data/tariffplans/test/destinations/multiid/RatingProfiles.csv b/data/tariffplans/test/destinations/multiid/RatingProfiles.csv new file mode 100644 index 000000000..9242632e1 --- /dev/null +++ b/data/tariffplans/test/destinations/multiid/RatingProfiles.csv @@ -0,0 +1,2 @@ +#Direction,Tenant,Category,Subject,ActivationTime,RatingPlanId,RatesFallbackSubject,CdrStatQueueIds +*out,cgrates.org,call,*any,2012-01-01T00:00:00Z,RP_RETAIL,, \ No newline at end of file diff --git a/data/tariffplans/test/destinations/multiid/Timings.csv b/data/tariffplans/test/destinations/multiid/Timings.csv new file mode 100644 index 000000000..775f347c0 --- /dev/null +++ b/data/tariffplans/test/destinations/multiid/Timings.csv @@ -0,0 +1,2 @@ +#Tag,Years,Months,MonthDays,WeekDays,Time +ALWAYS,*any,*any,*any,*any,00:00:00 \ No newline at end of file diff --git a/data/tutorials/osips_async/opensips/etc/opensips/opensips.cfg b/data/tutorials/osips_async/opensips/etc/opensips/opensips.cfg index e9d24d589..3733d6c60 100644 --- a/data/tutorials/osips_async/opensips/etc/opensips/opensips.cfg +++ b/data/tutorials/osips_async/opensips/etc/opensips/opensips.cfg @@ -98,6 +98,7 @@ modparam("acc", "evi_extra", "cgr_reqtype=$avp(cgr_reqtype); cgr_account=$avp(cgr_account); cgr_destination=$avp(cgr_destination); cgr_supplier=$avp(cgr_supplier); + cgr_answertime=$dlg_val(atime); dialog_id=$DLG_did") #modparam("acc", "db_url", "flatstore:/tmp") #modparam("acc", "db_flag", "CDR") @@ -344,6 +345,7 @@ route{ route[relay] { # for INVITEs enable some additional helper routes if (is_method("INVITE") && !has_totag()) { + t_on_reply("MSG_REPLY"); #added for completeness not tested t_on_failure("missed_call"); } if (!t_relay()) { @@ -367,3 +369,11 @@ failure_route[missed_call] { } } +onreply_route[MSG_REPLY]{ + if (t_check_status("200") && !$dlg_val(atime)){#so we set it ONLY ONCE + $dlg_val(atime)=$Ts; + } + if (t_check_status("4..")){#CAPTURE ALL ERROR CODES NEGATIVE ASR record + $dlg_val(atime)=NULL; + } +} diff --git a/engine/action.go b/engine/action.go index d7d56ac3a..9192cb7e5 100644 --- a/engine/action.go +++ b/engine/action.go @@ -19,9 +19,11 @@ along with this program. If not, see package engine import ( + "bytes" "encoding/json" "errors" "fmt" + "html/template" "net/smtp" "path" "reflect" @@ -638,6 +640,24 @@ type RPCRequest struct { } func cgrRPCAction(account *Account, sq *StatsQueueTriggered, a *Action, acs Actions) error { + // parse template + tmpl := template.New("extra_params") + t, err := tmpl.Parse(a.ExtraParameters) + if err != nil { + utils.Logger.Err(fmt.Sprintf("error parsing *cgr_rpc template: %s", err.Error())) + return err + } + var buf bytes.Buffer + if err = t.Execute(&buf, map[string]interface{}{ + "account": account, + "action": a, + "actions": acs, + "sq": sq, + }); err != nil { + utils.Logger.Err(fmt.Sprintf("error executing *cgr_rpc template %s:", err.Error())) + return err + } + a.ExtraParameters = buf.String() req := RPCRequest{} if err := json.Unmarshal([]byte(a.ExtraParameters), &req); err != nil { return err diff --git a/glide.yaml b/glide.yaml index a6911d41c..33d4f11a7 100644 --- a/glide.yaml +++ b/glide.yaml @@ -1,6 +1,7 @@ package: github.com/cgrates/cgrates import: - package: github.com/DisposaBoy/JsonConfigReader +- package: github.com/cenk/hub - package: github.com/cenkalti/rpc2 - package: github.com/cgrates/fsock - package: github.com/cgrates/kamevapi diff --git a/sessionmanager/osipsevent.go b/sessionmanager/osipsevent.go index cbb5052f9..a8f6981f4 100644 --- a/sessionmanager/osipsevent.go +++ b/sessionmanager/osipsevent.go @@ -151,11 +151,11 @@ func (osipsev *OsipsEvent) GetSetupTime(fieldName, timezone string) (time.Time, return utils.ParseTimeDetectLayout(sTimeStr, timezone) } func (osipsev *OsipsEvent) GetAnswerTime(fieldName, timezone string) (time.Time, error) { - aTimeStr := utils.FirstNonEmpty(osipsev.osipsEvent.AttrValues[fieldName], osipsev.osipsEvent.AttrValues[TIME]) + aTimeStr := utils.FirstNonEmpty(osipsev.osipsEvent.AttrValues[fieldName], osipsev.osipsEvent.AttrValues[CGR_ANSWERTIME]) if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value aTimeStr = fieldName[len(utils.STATIC_VALUE_PREFIX):] } else if fieldName == utils.META_DEFAULT { - aTimeStr = osipsev.osipsEvent.AttrValues[TIME] + aTimeStr = osipsev.osipsEvent.AttrValues[CGR_ANSWERTIME] } return utils.ParseTimeDetectLayout(aTimeStr, timezone) } @@ -250,7 +250,7 @@ func (osipsev *OsipsEvent) PassesFieldFilter(*utils.RSRField) (bool, string) { } func (osipsev *OsipsEvent) GetExtraFields() map[string]string { primaryFields := []string{TO_TAG, SETUP_DURATION, OSIPS_SETUP_TIME, "method", "callid", "sip_reason", OSIPS_EVENT_TIME, "sip_code", "duration", "from_tag", "dialog_id", - CGR_TENANT, CGR_CATEGORY, CGR_REQTYPE, CGR_ACCOUNT, CGR_SUBJECT, CGR_DESTINATION, utils.CGR_SUPPLIER, CGR_PDD} + CGR_TENANT, CGR_CATEGORY, CGR_REQTYPE, CGR_ACCOUNT, CGR_SUBJECT, CGR_DESTINATION, utils.CGR_SUPPLIER, CGR_PDD,CGR_ANSWERTIME} extraFields := make(map[string]string) for field, val := range osipsev.osipsEvent.AttrValues { if !utils.IsSliceMember(primaryFields, field) { diff --git a/sessionmanager/osipsevent_test.go b/sessionmanager/osipsevent_test.go index ac8c2b665..a019a3da7 100644 --- a/sessionmanager/osipsevent_test.go +++ b/sessionmanager/osipsevent_test.go @@ -33,7 +33,7 @@ import ( var addr, _ = net.ResolveUDPAddr("udp", "172.16.254.77:42574") var osipsEv = &OsipsEvent{osipsEvent: &osipsdagram.OsipsEvent{Name: "E_ACC_CDR", AttrValues: map[string]string{"to_tag": "4ea9687f", "cgr_account": "dan", "setuptime": "7", "created": "1406370492", "method": "INVITE", "callid": "ODVkMDI2Mzc2MDY5N2EzODhjNTAzNTdlODhiZjRlYWQ", - "sip_reason": "OK", "time": "1406370499", "cgr_reqtype": utils.META_PREPAID, "cgr_subject": "dan", "cgr_destination": "+4986517174963", "cgr_tenant": "itsyscom.com", "sip_code": "200", + "sip_reason": "OK", "cgr_answertime": "1406370499" ,"time": "1406370499", "cgr_reqtype": utils.META_PREPAID, "cgr_subject": "dan", "cgr_destination": "+4986517174963", "cgr_tenant": "itsyscom.com", "sip_code": "200", "duration": "20", CGR_PDD: "3s", "from_tag": "eb082607", "extra1": "val1", "extra2": "val2", "cgr_supplier": "supplier3"}, OriginatorAddress: addr}} func TestOsipsEventInterface(t *testing.T) { @@ -158,7 +158,7 @@ func TestOsipsAccMissedToStoredCdr(t *testing.T) { setupTime, _ := utils.ParseTimeDetectLayout("1431182699", "") osipsEv := &OsipsEvent{osipsEvent: &osipsdagram.OsipsEvent{Name: "E_ACC_MISSED_EVENT", AttrValues: map[string]string{"method": "INVITE", "from_tag": "5cb81eaa", "to_tag": "", "callid": "27b1e6679ad0109b5d756e42bb4c9c28@0:0:0:0:0:0:0:0", - "sip_code": "404", "sip_reason": "Not Found", "time": "1431182699", "cgr_reqtype": utils.META_PSEUDOPREPAID, + "sip_code": "404", "sip_reason": "Not Found", "time": "1431182699", "cgr_answertime": "1431182699", "cgr_reqtype": utils.META_PSEUDOPREPAID, "cgr_account": "1001", "cgr_destination": "1002", utils.CGR_SUPPLIER: "supplier1", "duration": "", "dialog_id": "3547:277000822", "extra1": "val1", "extra2": "val2"}, OriginatorAddress: addr, }} @@ -176,7 +176,7 @@ func TestOsipsAccMissedToStoredCdr(t *testing.T) { func TestOsipsUpdateDurationFromEvent(t *testing.T) { osipsEv := &OsipsEvent{osipsEvent: &osipsdagram.OsipsEvent{Name: "E_ACC_EVENT", AttrValues: map[string]string{"method": "INVITE", "from_tag": "87d02470", "to_tag": "a671a98", "callid": "05dac0aaa716c9814f855f0e8fee6936@0:0:0:0:0:0:0:0", - "sip_code": "200", "sip_reason": "OK", "time": "1430579770", "cgr_reqtype": utils.META_PREPAID, + "sip_code": "200", "sip_reason": "OK", "time": "1430579770", "cgr_answertime": "1430579770", "cgr_reqtype": utils.META_PREPAID, "cgr_account": "1001", "cgr_destination": "1002", utils.CGR_SUPPLIER: "supplier1", "duration": "", "dialog_id": "3547:277000822", "extra1": "val1", "extra2": "val2"}, OriginatorAddress: addr, }} @@ -188,7 +188,7 @@ func TestOsipsUpdateDurationFromEvent(t *testing.T) { }} eOsipsEv := &OsipsEvent{osipsEvent: &osipsdagram.OsipsEvent{Name: "E_ACC_EVENT", AttrValues: map[string]string{"method": "UPDATE", "from_tag": "87d02470", "to_tag": "a671a98", "callid": "05dac0aaa716c9814f855f0e8fee6936@0:0:0:0:0:0:0:0", - "sip_code": "200", "sip_reason": "OK", "time": "1430579770", "cgr_reqtype": utils.META_PREPAID, + "sip_code": "200", "sip_reason": "OK", "time": "1430579770", "cgr_answertime": "1430579770", "cgr_reqtype": utils.META_PREPAID, "cgr_account": "1001", "cgr_destination": "1002", utils.CGR_SUPPLIER: "supplier1", "duration": "27s", "dialog_id": "3547:277000822", "extra1": "val1", "extra2": "val2"}, OriginatorAddress: addr, }}