From 0cdc0dae17888f22681d940f57f6ab9afdde6360 Mon Sep 17 00:00:00 2001 From: Kaian Date: Wed, 23 Mar 2022 17:39:45 +0100 Subject: [PATCH 01/44] doc: update README with latest stable release --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8d851395c74..1afd8581b07 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ If you want to test an [standalone](https://irontec.github.io/ivozprovider/en/ar | Version | 64 bits | 32 bits | |----------|:--------:|:-------:| |oldstable (oasis 1.7) | [![iso http](web/admin/public/images/iso-http-green.png)](https://packages.irontec.com/isos/ivozprovider-1.7.1-oasis-amd64.iso)| [![iso http](web/admin/public/images/iso-http-green.png)](https://packages.irontec.com/isos/ivozprovider-1.7.1-oasis-i386.iso)| -|stable (artemis 2.20.0) | [![iso http](web/admin/public/images/iso-http-green.png)](https://packages.irontec.com/isos/ivozprovider-2.20~2.20.0-artemis-amd64.iso)| | +|stable (artemis 2.20.1) | [![iso http](web/admin/public/images/iso-http-green.png)](https://packages.irontec.com/isos/ivozprovider-2.20~2.20.1-artemis-amd64.iso)| | |testing (halliday 3.x) | | From 24d7c437956e5b1aef70f1d7925875d0230c1e1a Mon Sep 17 00:00:00 2001 From: Kaian Date: Wed, 23 Mar 2022 17:47:38 +0100 Subject: [PATCH 02/44] pkg: version bump to 2.21.0 --- debian/changelog | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index 5f5b839ad27..a542508c188 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,10 @@ -ivozprovider (2.20~2.20.1) UNRELEASED; urgency=medium +ivozprovider (2.21~2.21.0) UNRELEASED; urgency=medium + + * Version bump to 2.21.0 + + -- Irontec IvozProvider Team Wed, 23 Mar 2022 17:43:31 +0100 + +ivozprovider (2.20~2.20.1) stable; urgency=medium * Version bump to 2.20.1 From f0b2ce6eafd91e69598b3c91a676892dde5b9cb1 Mon Sep 17 00:00:00 2001 From: Carlos Cruz Date: Mon, 28 Mar 2022 14:59:27 +0200 Subject: [PATCH 03/44] web/admin: hide retailAccount in DDI list section --- web/admin/application/configs/klear/DdiProvidersList.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/web/admin/application/configs/klear/DdiProvidersList.yaml b/web/admin/application/configs/klear/DdiProvidersList.yaml index 61d8e56444d..346263293bf 100644 --- a/web/admin/application/configs/klear/DdiProvidersList.yaml +++ b/web/admin/application/configs/klear/DdiProvidersList.yaml @@ -155,6 +155,7 @@ production: conditionalRoute: true routeType: true target: true + retailAccount: true options: title: _("Options") screens: From f9be9b2b440a1f3ea86f129f46f7b1ed064e0c57 Mon Sep 17 00:00:00 2001 From: Adam Gent <10923877+adamgent@users.noreply.github.com> Date: Fri, 8 Apr 2022 11:29:32 +0100 Subject: [PATCH 04/44] pkg: fix Swagger gen path at install The current export path for swagger.json is incorrect and so the task fails at post-install. --- debian/ivozprovider-web-rest.postinst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/debian/ivozprovider-web-rest.postinst b/debian/ivozprovider-web-rest.postinst index 87c859e144c..1977af794fd 100755 --- a/debian/ivozprovider-web-rest.postinst +++ b/debian/ivozprovider-web-rest.postinst @@ -14,7 +14,7 @@ setfacl -R -m u:www-data:rwX -m u:root:rwX var # Create project cache bin/console cache:clear --no-warmup -q -n # generate swagger spec -bin/console api:swagger:export > web/swagger.json +bin/console api:swagger:export > public/swagger.json # Create jwt certificates [ ! -e /opt/irontec/ivozprovider/storage/jwt/private.pem ] && bin/generate-keys --initial @@ -28,7 +28,7 @@ if [ -d /opt/irontec/ivozprovider/web/rest/brand/ ]; then # Create project cache bin/console cache:clear --no-warmup -q -n # generate swagger spec - bin/console api:swagger:export > web/swagger.json + bin/console api:swagger:export > public/swagger.json popd fi @@ -41,7 +41,7 @@ if [ -d /opt/irontec/ivozprovider/web/rest/client/ ]; then # Create project cache bin/console cache:clear --no-warmup -q -n # generate swagger spec - bin/console api:swagger:export > web/swagger.json + bin/console api:swagger:export > public/swagger.json popd fi From cb83850b87ef66c81d95149a50d664e50c48e664 Mon Sep 17 00:00:00 2001 From: Kaian Date: Tue, 12 Apr 2022 17:20:05 +0200 Subject: [PATCH 05/44] systemd: set kamailio stop timeout to 30 seconds PROVIDER-189 --- debian/systemd/kamailio@.service | 1 + 1 file changed, 1 insertion(+) diff --git a/debian/systemd/kamailio@.service b/debian/systemd/kamailio@.service index efd32f5ed64..47d7daad9c1 100644 --- a/debian/systemd/kamailio@.service +++ b/debian/systemd/kamailio@.service @@ -13,6 +13,7 @@ PIDFile=/var/run/kamailio-%i.pid EnvironmentFile=/etc/default/kam%i ExecStart=/usr/sbin/kamailio -A IP=%i -f /etc/kamailio/proxy%i/kamailio.cfg -m ${SH_MEM} -M ${PRIV_MEM} -P /var/run/kamailio-%i.pid ExecStopPost=/bin/rm -f /var/run/kamailio-%i.pid +TimeoutStopSec=30s Restart=on-abort [Install] From 99c6c9a94f8821117f10f77a63c4f8475c9ed337 Mon Sep 17 00:00:00 2001 From: esalas Date: Wed, 27 Apr 2022 17:21:38 +0200 Subject: [PATCH 06/44] data: added rpz custom zone to bind --- profiles/data/etc/bind/db.rpz.local | 15 +++++++++++++++ .../data/etc/bind/named.conf.local.ivozprovider | 5 +++++ .../data/etc/bind/named.conf.options.ivozprovider | 5 +++++ 3 files changed, 25 insertions(+) create mode 100644 profiles/data/etc/bind/db.rpz.local diff --git a/profiles/data/etc/bind/db.rpz.local b/profiles/data/etc/bind/db.rpz.local new file mode 100644 index 00000000000..a76b7a1453b --- /dev/null +++ b/profiles/data/etc/bind/db.rpz.local @@ -0,0 +1,15 @@ +; BIND reverse data file for empty rfc1918 zone +; +; DO NOT EDIT THIS FILE - it is used for multiple zones. +; Instead, copy it, edit named.conf, and use that copy. +; +$TTL 86400 +@ IN SOA localhost. root.localhost. ( + 1 ; Serial + 604800 ; Refresh + 86400 ; Retry + 2419200 ; Expire + 86400 ) ; Negative Cache TTL +; +@ IN NS localhost. +; Custom records diff --git a/profiles/data/etc/bind/named.conf.local.ivozprovider b/profiles/data/etc/bind/named.conf.local.ivozprovider index 2df8a658426..6fc44aa6b96 100644 --- a/profiles/data/etc/bind/named.conf.local.ivozprovider +++ b/profiles/data/etc/bind/named.conf.local.ivozprovider @@ -15,3 +15,8 @@ zone "ivozprovider.local" { type master; file "/etc/bind/db.ivozprovider.local"; }; + +zone "rpz.local" { + type master; + file "/etc/bind/db.rpz.local"; +}; diff --git a/profiles/data/etc/bind/named.conf.options.ivozprovider b/profiles/data/etc/bind/named.conf.options.ivozprovider index e0a25027fad..155d26ec93c 100644 --- a/profiles/data/etc/bind/named.conf.options.ivozprovider +++ b/profiles/data/etc/bind/named.conf.options.ivozprovider @@ -27,4 +27,9 @@ options { // listen-on-v6 { any; }; // listen-on {127.0.0.1;}; listen-on { any; }; + + //enable response policy zone. + response-policy { + zone "rpz.local"; + }; }; From d2a29cbe9e0debade73db2a90180175800a3a8dc Mon Sep 17 00:00:00 2001 From: Kaian Date: Fri, 27 May 2022 12:18:51 +0200 Subject: [PATCH 07/44] core: properly validate Retail Account Call forward settings --- .../CallForwardSetting/CallForwardSetting.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/library/Ivoz/Provider/Domain/Model/CallForwardSetting/CallForwardSetting.php b/library/Ivoz/Provider/Domain/Model/CallForwardSetting/CallForwardSetting.php index 2890b45b610..e264578ab24 100644 --- a/library/Ivoz/Provider/Domain/Model/CallForwardSetting/CallForwardSetting.php +++ b/library/Ivoz/Provider/Domain/Model/CallForwardSetting/CallForwardSetting.php @@ -46,6 +46,19 @@ protected function sanitizeValues() $this->sanitizeRouteValues(); + // Retail target type in Call Forward Settings is an exception in routes naming convention and must + // be checked individually instead of using RoutableTrait::sanitizeRouteValues() + // @see CallForwardSettings::getCallForwardTarget() + if ($this->getRouteType() == CallForwardSettingInterface::TARGETTYPE_RETAIL) { + if (!$this->cfwToRetailAccount) { + throw new \DomainException( + "Target Retail Account (cfwToRetailAccountId) is required for targetType 'retail'" + ); + } + } else { + $this->setCfwToRetailAccount(null); + } + // Timeout only makes sense in NoAnswer Call Forwards if ($this->callForwardType != self::CALLFORWARDTYPE_NOANSWER) { $this->setNoAnswerTimeout(0); @@ -57,6 +70,9 @@ protected function sanitizeValues() $this->setDdi(null); return; + } else { + // Force filter type in Retail account Call Forward Settings + $this->setCallTypeFilter(self::CALLTYPEFILTER_BOTH); } $isValidRetailCfs = in_array( From 39f0938660314be5b541b86bee4ac1ebff421985 Mon Sep 17 00:00:00 2001 From: Carlos Cruz Date: Mon, 30 May 2022 16:21:30 +0200 Subject: [PATCH 08/44] kamtrunks: call rtpengine_delete on branch timeout with no reply --- kamailio/trunks/config/kamailio.cfg | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/kamailio/trunks/config/kamailio.cfg b/kamailio/trunks/config/kamailio.cfg index cb8e8b6fdfe..30d18290be9 100644 --- a/kamailio/trunks/config/kamailio.cfg +++ b/kamailio/trunks/config/kamailio.cfg @@ -2020,6 +2020,7 @@ failure_route[MANAGE_FAILURE_GW] { exit; } else if (t_branch_timeout() && !t_branch_replied()) { route(INACTIVATE_GW); + route(RTPENGINE); } else if (t_check_status("3[0-9]{2}")) { xwarn("[$dlg_var(cidhash)] MANAGE-FAILURE-GW: $T_reply_code: Not allowed from GW\n"); } @@ -2045,9 +2046,6 @@ failure_route[MANAGE_FAILURE_AS] { route(IS_FROM_INSIDE); - # Avoid failover for static distribute method - if ($dlg_var(distributeMethod) == 'static') exit; - # next DST - only for 404 or local timeout if (t_check_status("404") or (t_branch_timeout() and !t_branch_replied())) { # Invalidate AS only if no response received @@ -2056,14 +2054,17 @@ failure_route[MANAGE_FAILURE_AS] { ds_mark_dst("ip"); } - if(ds_next_dst()) { - t_on_failure("MANAGE_FAILURE_AS"); + if($dlg_var(distributeMethod) != 'static' && ds_next_dst()) { xinfo("[$dlg_var(cidhash)] MANAGE-FAILURE-AS: going to <$ru> via <$du>\n"); + t_on_failure("MANAGE_FAILURE_AS"); route(RELAY); - } else { - xerr("[$dlg_var(cidhash)] MANAGE-FAILURE-AS: No more AS-s available\n"); exit; } + + if (t_branch_timeout() and !t_branch_replied()) { + xinfo("[$dlg_var(cidhash)] MANAGE-FAILURE-AS: Free rtpengine session\n"); + route(RTPENGINE); + } } xinfo("[$dlg_var(cidhash)] MANAGE-FAILURE-AS: No failover for '$T_reply_code $T_reply_reason', forward reply\n"); From 9393348142410ac7e1033366f263834c63e579ef Mon Sep 17 00:00:00 2001 From: Kaian Date: Tue, 28 Jun 2022 14:01:56 +0200 Subject: [PATCH 09/44] tests: update BBS tests initial dataset --- tests/bbs/dataset.json | 2174 ++++++++++++++++++++++++++++++---------- 1 file changed, 1630 insertions(+), 544 deletions(-) diff --git a/tests/bbs/dataset.json b/tests/bbs/dataset.json index 1a42582e28a..54b4d5a26e2 100644 --- a/tests/bbs/dataset.json +++ b/tests/bbs/dataset.json @@ -1,9 +1,9 @@ { "info": { - "name": "IvozProvider - BBS Dataset (artemis)", "_postman_id": "bce451f6-e943-56a6-beae-19a0c3fef736", - "description": "", - "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + "name": "IvozProvider - BBS Dataset (artemis)", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "628603" }, "item": [ { @@ -24,8 +24,8 @@ "", "tests[\"Response body has token field\"] = jsonData.token !== undefined;", "", - "postman.setGlobalVariable(\"api_auth\", 'Bearer ' + jsonData.token);", - "" + "postman.setGlobalVariable(\"platform_api_auth\", 'Bearer ' + jsonData.token);", + "postman.setGlobalVariable(\"platform_api_token\", jsonData.token);" ], "type": "text/javascript" } @@ -44,13 +44,13 @@ "formdata": [ { "key": "username", - "type": "text", - "value": "{{api_username}}" + "value": "{{api_username}}", + "type": "text" }, { "key": "password", - "type": "text", - "value": "{{api_password}}" + "value": "{{api_password}}", + "type": "text" } ] }, @@ -70,7 +70,6 @@ }, { "name": "0001 - Brand Data", - "description": null, "item": [ { "name": "Delete BBS brand", @@ -78,21 +77,19 @@ { "listen": "test", "script": { - "id": "36564c70-383c-4f0a-bb5b-fddf4880f35f", - "type": "text/javascript", "exec": [ "" - ] + ], + "type": "text/javascript" } }, { "listen": "prerequest", "script": { - "id": "31177a7d-4dc1-4ce6-8f3d-a9b43f63c0e6", - "type": "text/javascript", "exec": [ "" - ] + ], + "type": "text/javascript" } } ], @@ -101,7 +98,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{platform_api_auth}}" }, { "key": "Content-Type", @@ -152,7 +149,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{platform_api_auth}}" }, { "key": "Content-Type", @@ -199,7 +196,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{platform_api_auth}}" }, { "key": "Content-Type", @@ -246,7 +243,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{platform_api_auth}}" }, { "key": "Content-Type", @@ -293,7 +290,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{platform_api_auth}}" }, { "key": "Content-Type", @@ -340,7 +337,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{platform_api_auth}}" }, { "key": "Content-Type", @@ -387,7 +384,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{platform_api_auth}}" }, { "key": "Content-Type", @@ -434,7 +431,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{platform_api_auth}}" }, { "key": "Content-Type", @@ -481,7 +478,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{platform_api_auth}}" }, { "key": "Content-Type", @@ -528,7 +525,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{platform_api_auth}}" }, { "key": "Content-Type", @@ -575,7 +572,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{platform_api_auth}}" }, { "key": "Content-Type", @@ -598,6 +595,209 @@ }, "response": [] }, + { + "name": "Add Brand Feature: Retail", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var jsonData = JSON.parse(responseBody)", + "", + "tests[\"Response body is JSON\"] = jsonData !== undefined;", + "", + "tests[\"Response body has token id\"] = jsonData.id !== undefined;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "{{platform_api_auth}}" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"brand\": {{brandId}},\n \"feature\": 11\n}" + }, + "url": { + "raw": "{{platform_api_url}}/features_rel_brands", + "host": [ + "{{platform_api_url}}" + ], + "path": [ + "features_rel_brands" + ] + } + }, + "response": [] + }, + { + "name": "Add Brand Feature: vPBX", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var jsonData = JSON.parse(responseBody)", + "", + "tests[\"Response body is JSON\"] = jsonData !== undefined;", + "", + "tests[\"Response body has token id\"] = jsonData.id !== undefined;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "{{platform_api_auth}}" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"brand\": {{brandId}},\n \"feature\": 12\n}" + }, + "url": { + "raw": "{{platform_api_url}}/features_rel_brands", + "host": [ + "{{platform_api_url}}" + ], + "path": [ + "features_rel_brands" + ] + } + }, + "response": [] + }, + { + "name": "Create BBS Brand Admin", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var jsonData = JSON.parse(responseBody)", + "", + "tests[\"Response body is JSON\"] = jsonData !== undefined;", + "", + "tests[\"Response body has token id\"] = jsonData.id !== undefined;", + "", + "postman.setGlobalVariable(\"brandAdminId\", jsonData.id);", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "{{platform_api_auth}}" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"username\": \"brandadmin\",\n \"pass\": \"unusedp4ssw0rd\",\n \"email\": \"brandamin@bbs.com\",\n \"active\": 1,\n \"restricted\": 0,\n \"brand\": {{brandId}},\n \"timezone\": 145\n}" + }, + "url": { + "raw": "{{platform_api_url}}/administrators", + "host": [ + "{{platform_api_url}}" + ], + "path": [ + "administrators" + ] + } + }, + "response": [] + }, + { + "name": "Get Brand Authorization Token", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var jsonData = JSON.parse(responseBody)", + "", + "tests[\"Response body is JSON\"] = jsonData !== undefined;", + "", + "tests[\"Response body has token field\"] = jsonData.token !== undefined;", + "", + "postman.setGlobalVariable(\"brand_api_auth\", 'Bearer ' + jsonData.token);", + "postman.setGlobalVariable(\"brand_api_token\", jsonData.token);", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/x-www-form-urlencoded" + } + ], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "token", + "value": "{{platform_api_token}}", + "type": "text" + }, + { + "key": "username", + "value": "brandadmin", + "type": "text" + } + ] + }, + "url": { + "raw": "{{brand_api_url}}/token/exchange", + "host": [ + "{{brand_api_url}}" + ], + "path": [ + "token", + "exchange" + ] + } + }, + "response": [] + }, { "name": "Create Number Transformation", "event": [ @@ -625,7 +825,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { "key": "Content-Type", @@ -634,7 +834,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"description\": \"Spanish\",\n \"internationalCode\": \"00\",\n \"trunkPrefix\": \"\",\n \"areaCode\": \"\",\n \"nationalLen\": 9,\n \"generateRules\": true,\n \"name\": {\n \"en\": \"Spanish Operator\",\n \"es\": \"Operador Español\"\n },\n \"brand\": {{brandId}},\n \"country\": 70\n}" + "raw": "{\n \"description\": \"Spanish\",\n \"internationalCode\": \"00\",\n \"trunkPrefix\": \"\",\n \"areaCode\": \"\",\n \"nationalLen\": 9,\n \"generateRules\": true,\n \"name\": {\n \"en\": \"Spanish Operator\",\n \"es\": \"Operador Español\",\n \"ca\": \"Operador Español\",\n \"it\": \"Spanish Operator\"\n },\n \"brand\": {{brandId}},\n \"country\": 70\n}" }, "url": { "raw": "{{brand_api_url}}/transformation_rule_sets", @@ -675,7 +875,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { "key": "Content-Type", @@ -684,7 +884,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"description\": \"USA (Area 999)\",\n \"internationalCode\": \"011\",\n \"trunkPrefix\": \"1\",\n \"areaCode\": \"999\",\n \"nationalLen\": 9,\n \"generateRules\": true,\n \"name\": {\n \"en\": \"USA (Area 999)\",\n \"es\": \"USA (Area 999)\"\n },\n \"brand\": {{brandId}},\n \"country\": 235\n}" + "raw": "{\n \"description\": \"USA (Area 999)\",\n \"internationalCode\": \"011\",\n \"trunkPrefix\": \"1\",\n \"areaCode\": \"999\",\n \"nationalLen\": 9,\n \"generateRules\": true,\n \"name\": {\n \"en\": \"USA (Area 999)\",\n \"es\": \"USA (Area 999)\",\n \"it\": \"USA (Area 999)\",\n \"ca\": \"USA (Area 999)\" \n },\n \"brand\": {{brandId}},\n \"country\": 235\n}" }, "url": { "raw": "{{brand_api_url}}/transformation_rule_sets", @@ -704,8 +904,6 @@ { "listen": "test", "script": { - "id": "dc6fa878-d388-4749-a223-a8db2c61356d", - "type": "text/javascript", "exec": [ "tests[\"Status code is 201\"] = responseCode.code === 201;", "", @@ -717,7 +915,8 @@ "", "postman.setGlobalVariable(\"ddiProviderId\", jsonData.id);", "" - ] + ], + "type": "text/javascript" } } ], @@ -726,7 +925,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { "key": "Content-Type", @@ -735,7 +934,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"description\": \"BBS DDI Provider\",\n \"name\": \"BBS DDI Provider\",\n \"externallyRated\": false,\n \"brand\": {{brandId}},\n \"transformationRuleSet\": 70\n}\n" + "raw": "{\n \"description\": \"BBS DDI Provider\",\n \"name\": \"BBS DDI Provider\",\n \"externallyRated\": false,\n \"brand\": {{brandId}},\n \"transformationRuleSet\": 70,\n \"proxyTrunk\": 1\n}\n" }, "url": { "raw": "{{brand_api_url}}/ddi_providers", @@ -745,8 +944,7 @@ "path": [ "ddi_providers" ] - }, - "description": null + } }, "response": [] }, @@ -756,8 +954,6 @@ { "listen": "test", "script": { - "id": "275bfe1d-ea35-49d3-ace4-7594192ee9de", - "type": "text/javascript", "exec": [ "tests[\"Status code is 201\"] = responseCode.code === 201;", "", @@ -769,7 +965,8 @@ "", "postman.setGlobalVariable(\"ddiProviderAddressId\", jsonData.id);", "" - ] + ], + "type": "text/javascript" } } ], @@ -778,7 +975,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { "key": "Content-Type", @@ -787,7 +984,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"ddiProvider\": {{ddiProviderId}},\n \"ip\": \"151.80.176.3\"\n}\n" + "raw": "{\n \"ddiProvider\": {{ddiProviderId}},\n \"ip\": \"151.80.161.20\"\n}\n" }, "url": { "raw": "{{brand_api_url}}/ddi_provider_addresses", @@ -797,8 +994,7 @@ "path": [ "ddi_provider_addresses" ] - }, - "description": null + } }, "response": [] }, @@ -808,8 +1004,6 @@ { "listen": "test", "script": { - "id": "dceb00af-cc15-4a3b-97d5-cccc413fa3ab", - "type": "text/javascript", "exec": [ "tests[\"Status code is 201\"] = responseCode.code === 201;", "", @@ -821,7 +1015,8 @@ "", "postman.setGlobalVariable(\"carrierId\", jsonData.id);", "" - ] + ], + "type": "text/javascript" } } ], @@ -830,7 +1025,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { "key": "Content-Type", @@ -839,7 +1034,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"description\": \"BBS Carrier\",\n \"name\": \"BBS Carrier\",\n \"externallyRated\": false,\n \"brand\": {{brandId}},\n \"transformationRuleSet\": 70\n}\n" + "raw": "{\n \"description\": \"BBS Carrier\",\n \"name\": \"BBS Carrier\",\n \"externallyRated\": false,\n \"brand\": {{brandId}},\n \"transformationRuleSet\": 70,\n \"proxyTrunk\": 1\n}\n" }, "url": { "raw": "{{brand_api_url}}/carriers", @@ -849,8 +1044,7 @@ "path": [ "carriers" ] - }, - "description": null + } }, "response": [] }, @@ -881,7 +1075,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { "key": "Content-Type", @@ -931,7 +1125,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { "key": "Content-Type", @@ -940,7 +1134,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"prefix\": \"+34\",\n \"name\": {\n \t\"en\": \"Spain\", \t\n \t\"es\": \"España\"\n },\n \"description\": {\n \t\"en\": \"BBS - Spain\", \t\n \t\"es\": \"BBS - España\"\n },\n \"brand\": {{brandId}}\n}" + "raw": "{\n \"prefix\": \"+34\",\n \"name\": {\n \t\"en\": \"Spain\", \t\n \t\"es\": \"España\",\n \t\"it\": \"Spain\", \t\n \t\"ca\": \"España\" \n },\n \"description\": {\n \t\"en\": \"BBS - Spain\", \t\n \t\"es\": \"BBS - España\",\n \t\"it\": \"BBS - Spain\", \t\n \t\"ca\": \"BBS - España\" \n },\n \"brand\": {{brandId}}\n}" }, "url": { "raw": "{{brand_api_url}}/routing_patterns", @@ -981,7 +1175,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { "key": "Content-Type", @@ -1031,7 +1225,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { "key": "Content-Type", @@ -1040,7 +1234,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"prefix\": \"+1\",\n \"name\": {\n \t\"en\": \"USA\", \t\n \t\"es\": \"Estados Unidos\"\n },\n \"description\": {\n \t\"en\": \"BBS - Usa\", \t\n \t\"es\": \"BBS - Estados Unidos\"\n },\n \"brand\": {{brandId}}\n}" + "raw": "{\n \"prefix\": \"+1\",\n \"name\": {\n \t\"en\": \"USA\", \t\n \t\"es\": \"Estados Unidos\",\n \t\"it\": \"USA\", \t\n \t\"ca\": \"Estados Unidos\" \n },\n \"description\": {\n \t\"en\": \"BBS - Usa\", \t\n \t\"es\": \"BBS - Estados Unidos\",\n \t\"it\": \"BBS - Usa\", \t\n \t\"ca\": \"BBS - Estados Unidos\" \n },\n \"brand\": {{brandId}}\n}" }, "url": { "raw": "{{brand_api_url}}/routing_patterns", @@ -1081,7 +1275,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { "key": "Content-Type", @@ -1110,8 +1304,6 @@ { "listen": "test", "script": { - "id": "2c02eca0-42c8-410f-89fe-b498c51f5bc3", - "type": "text/javascript", "exec": [ "tests[\"Status code is 201\"] = responseCode.code === 201;", "", @@ -1123,7 +1315,8 @@ "", "postman.setGlobalVariable(\"destinationESId\", jsonData.id);", "" - ] + ], + "type": "text/javascript" } } ], @@ -1132,7 +1325,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { "key": "Content-Type", @@ -1161,8 +1354,6 @@ { "listen": "test", "script": { - "id": "dc308185-2e75-4396-b04e-c0bb9596f278", - "type": "text/javascript", "exec": [ "tests[\"Status code is 201\"] = responseCode.code === 201;", "", @@ -1174,7 +1365,8 @@ "", "postman.setGlobalVariable(\"destinationUSId\", jsonData.id);", "" - ] + ], + "type": "text/javascript" } } ], @@ -1183,7 +1375,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { "key": "Content-Type", @@ -1212,8 +1404,6 @@ { "listen": "test", "script": { - "id": "24f86570-6aca-4720-8f58-e7eb36480311", - "type": "text/javascript", "exec": [ "tests[\"Status code is 201\"] = responseCode.code === 201;", "", @@ -1225,7 +1415,8 @@ "", "postman.setGlobalVariable(\"destinationRateGroupId\", jsonData.id);", "" - ] + ], + "type": "text/javascript" } } ], @@ -1234,7 +1425,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { "key": "Content-Type", @@ -1243,7 +1434,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"name\": {\n \t\"en\": \"Standard\",\n \t\"es\": \"Estándar\"\n },\n \"description\": {\n \t\"en\": \"Standard\",\n \t\"es\": \"Estándar\"\n },\n \"brand\": {{brandId}}\n}" + "raw": "{\n \"name\": {\n \t\"en\": \"Standard\",\n \t\"es\": \"Estándar\",\n \t\"it\": \"Standard\",\n \t\"ca\": \"Estándar\" \n },\n \"description\": {\n \t\"en\": \"\",\n \t\"es\": \"\",\n \t\"it\": \"\",\n \t\"ca\": \"\" \n },\n \"brand\": {{brandId}}\n}" }, "url": { "raw": "{{brand_api_url}}/destination_rate_groups", @@ -1273,7 +1464,6 @@ "tests[\"Response body has token id\"] = jsonData.id !== undefined;", "" ], - "id": "bc41beb0-8e5c-496d-93a2-ffc1e7a00aee", "type": "text/javascript" } } @@ -1283,7 +1473,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { "key": "Content-Type", @@ -1322,7 +1512,6 @@ "tests[\"Response body has token id\"] = jsonData.id !== undefined;", "" ], - "id": "b2665ea2-81d0-4f6d-ba99-c311166c9f44", "type": "text/javascript" } } @@ -1332,7 +1521,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { "key": "Content-Type", @@ -1361,8 +1550,6 @@ { "listen": "test", "script": { - "id": "386ee912-1549-40f8-b69b-7c47a1659ceb", - "type": "text/javascript", "exec": [ "tests[\"Status code is 201\"] = responseCode.code === 201;", "", @@ -1374,7 +1561,8 @@ "", "postman.setGlobalVariable(\"ratingPlanGroupId\", jsonData.id);", "" - ] + ], + "type": "text/javascript" } } ], @@ -1383,7 +1571,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { "key": "Content-Type", @@ -1392,7 +1580,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"name\": {\n \t\"en\": \"Standard 2017\",\n \t\"es\": \"Estándar 2017\"\n },\n \"description\": {\n \t\"en\": \"\",\n \t\"es\": \"\"\n },\n \"brand\": {{brandId}}\n}" + "raw": "{\n \"name\": {\n \t\"en\": \"Standard 2017\",\n \t\"es\": \"Estándar 2017\",\n \"it\": \"Standard 2017\",\n \t\"ca\": \"Estándar 2017\"\n },\n \"description\": {\n \t\"en\": \"\",\n \t\"es\": \"\",\n \t\"it\": \"\",\n \t\"ca\": \"\" \n },\n \"brand\": {{brandId}}\n}" }, "url": { "raw": "{{brand_api_url}}/rating_plan_groups", @@ -1423,7 +1611,6 @@ "", "" ], - "id": "a62b51cd-049c-4137-b5f6-0112019e6d5f", "type": "text/javascript" } } @@ -1433,7 +1620,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { "key": "Content-Type", @@ -1488,7 +1675,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { "key": "Content-Type", @@ -1497,7 +1684,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"type\": \"vpbx\",\n \"name\": \"BBS - Company for Black Box SIP tests\",\n \"domainUsers\": \"bbs.ivozprovider.local\",\n \"nif\": \"09876543210ART\",\n \"externalMaxCalls\": 2,\n \"postalAddress\": \"Company address\",\n \"postalCode\": \"48902\",\n \"town\": \"Company town\",\n \"province\": \"Company province\",\n \"onDemandRecord\": 2,\n \"onDemandRecordCode\": \"234\",\n \"countryName\": \"Company country\",\n \"ipfilter\": false,\n \"defaultTimezone\": 1,\n \"transformationRuleSet\": 70,\n \"brand\": {{brandId}}\n}" + "raw": "{\n \"type\": \"vpbx\",\n \"name\": \"BBS - Company for Black Box SIP tests\",\n \"domainUsers\": \"bbs.ivozprovider.local\",\n \"nif\": \"09876543210ART\",\n \"externalMaxCalls\": 2,\n \"postalAddress\": \"Company address\",\n \"postalCode\": \"48902\",\n \"town\": \"Company town\",\n \"province\": \"Company province\",\n \"onDemandRecord\": 2,\n \"onDemandRecordCode\": \"234\",\n \"countryName\": \"Company country\",\n \"ipfilter\": false,\n \"defaultTimezone\": 1,\n \"transformationRuleSet\": 70,\n \"brand\": {{brandId}},\n \"country\": 70,\n \"currency\": 1 \n}" }, "url": { "raw": "{{brand_api_url}}/companies", @@ -1512,7 +1699,7 @@ "response": [] }, { - "name": "Add Company Rating Profile", + "name": "Create BBS Company Admin", "event": [ { "listen": "test", @@ -1526,9 +1713,9 @@ "", "tests[\"Response body has token id\"] = jsonData.id !== undefined;", "", + "postman.setGlobalVariable(\"brandAdminId\", jsonData.id);", "" ], - "id": "9d423fc8-954b-4358-be3d-a78ca5ddba30", "type": "text/javascript" } } @@ -1538,7 +1725,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { "key": "Content-Type", @@ -1547,34 +1734,37 @@ ], "body": { "mode": "raw", - "raw": "{\n \"activationTime\": \"2018-01-01 00:00:00.000\",\n \"company\": {{companyId}},\n \"ratingPlanGroup\": {{ratingPlanGroupId}}\n}" + "raw": "{\n \"username\": \"companyadmin\",\n \"pass\": \"unusedp4ssw0rd\",\n \"email\": \"companyadmin@bbs.com\",\n \"active\": 1,\n \"restricted\": 0,\n \"brand\": {{brandId}},\n \"company\": {{companyId}},\n \"timezone\": 145\n}" }, "url": { - "raw": "{{brand_api_url}}/rating_profiles", + "raw": "{{brand_api_url}}/administrators", "host": [ "{{brand_api_url}}" ], "path": [ - "rating_profiles" + "administrators" ] } }, "response": [] }, { - "name": "Get BBS Company data", + "name": "Get Company Authorization Token", "event": [ { "listen": "test", "script": { "exec": [ - "tests[\"Status code is 200\"] = responseCode.code === 200;", + "tests[\"Status code is 201\"] = responseCode.code === 201;", "", - "var jsonData = JSON.parse(responseBody);", + "var jsonData = JSON.parse(responseBody)", "", "tests[\"Response body is JSON\"] = jsonData !== undefined;", "", - "postman.setGlobalVariable(\"companyData\", responseBody);", + "tests[\"Response body has token field\"] = jsonData.token !== undefined;", + "", + "postman.setGlobalVariable(\"client_api_auth\", 'Bearer ' + jsonData.token);", + "postman.setGlobalVariable(\"client_api_token\", jsonData.token);", "" ], "type": "text/javascript" @@ -1582,36 +1772,43 @@ } ], "request": { - "method": "GET", + "method": "POST", "header": [ { - "key": "Authorization", - "value": "{{api_auth}}" - }, - { - "key": "Accept", - "value": "application/json" + "key": "Content-Type", + "value": "application/x-www-form-urlencoded" } ], "body": { - "mode": "raw", - "raw": "{\n \"type\": \"vpbx\",\n \"name\": \"BBS - Company for Black Box SIP tests\",\n \"domainUsers\": \"bbs.ivozprovider.local\",\n \"nif\": \"09876543210ART\",\n \"externalMaxCalls\": 2,\n \"postalAddress\": \"Company address\",\n \"postalCode\": \"48902\",\n \"town\": \"Company town\",\n \"province\": \"Company province\",\n \"countryName\": \"Company country\",\n \"defaultTimezone\": 1,\n \"brand\": {{brandId}}\n}" + "mode": "formdata", + "formdata": [ + { + "key": "token", + "value": "{{brand_api_token}}", + "type": "text" + }, + { + "key": "username", + "value": "companyadmin", + "type": "text" + } + ] }, "url": { - "raw": "{{brand_api_url}}/companies/{{companyId}}", + "raw": "{{client_api_url}}/token/exchange", "host": [ - "{{brand_api_url}}" + "{{client_api_url}}" ], "path": [ - "companies", - "{{companyId}}" + "token", + "exchange" ] } }, "response": [] }, { - "name": "Add Company Feature: Queues", + "name": "Add Company Rating Profile", "event": [ { "listen": "test", @@ -1636,7 +1833,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { "key": "Content-Type", @@ -1645,35 +1842,34 @@ ], "body": { "mode": "raw", - "raw": "{\n \"company\": {{companyId}},\n \"feature\": 1\n}" + "raw": "{\n \"activationTime\": \"2018-01-01 00:00:00.000\",\n \"company\": {{companyId}},\n \"ratingPlanGroup\": {{ratingPlanGroupId}}\n}" }, "url": { - "raw": "{{brand_api_url}}/features_rel_companies", + "raw": "{{brand_api_url}}/rating_profiles", "host": [ "{{brand_api_url}}" ], "path": [ - "features_rel_companies" + "rating_profiles" ] } }, "response": [] }, { - "name": "Add Company Feature: Recordings", + "name": "Get BBS Company data", "event": [ { "listen": "test", "script": { "exec": [ - "tests[\"Status code is 201\"] = responseCode.code === 201;", + "tests[\"Status code is 200\"] = responseCode.code === 200;", "", - "var jsonData = JSON.parse(responseBody)", + "var jsonData = JSON.parse(responseBody);", "", "tests[\"Response body is JSON\"] = jsonData !== undefined;", "", - "tests[\"Response body has token id\"] = jsonData.id !== undefined;", - "", + "postman.setGlobalVariable(\"companyData\", responseBody);", "" ], "type": "text/javascript" @@ -1681,35 +1877,32 @@ } ], "request": { - "method": "POST", + "method": "GET", "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { - "key": "Content-Type", + "key": "Accept", "value": "application/json" } ], - "body": { - "mode": "raw", - "raw": "{\n \"company\": {{companyId}},\n \"feature\": 2\n}" - }, "url": { - "raw": "{{brand_api_url}}/features_rel_companies", + "raw": "{{brand_api_url}}/companies/{{companyId}}", "host": [ "{{brand_api_url}}" ], "path": [ - "features_rel_companies" + "companies", + "{{companyId}}" ] } }, "response": [] }, { - "name": "Add Company Feature: Faxes", + "name": "Add Company Feature: Queues", "event": [ { "listen": "test", @@ -1734,7 +1927,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { "key": "Content-Type", @@ -1743,7 +1936,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"company\": {{companyId}},\n \"feature\": 3\n}" + "raw": "{\n \"company\": {{companyId}},\n \"feature\": 1\n}" }, "url": { "raw": "{{brand_api_url}}/features_rel_companies", @@ -1758,7 +1951,7 @@ "response": [] }, { - "name": "Add Company Feature: Friends", + "name": "Add Company Feature: Recordings", "event": [ { "listen": "test", @@ -1783,7 +1976,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { "key": "Content-Type", @@ -1792,7 +1985,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"company\": {{companyId}},\n \"feature\": 4\n}" + "raw": "{\n \"company\": {{companyId}},\n \"feature\": 2\n}" }, "url": { "raw": "{{brand_api_url}}/features_rel_companies", @@ -1807,7 +2000,7 @@ "response": [] }, { - "name": "Add Company Feature: Conferences", + "name": "Add Company Feature: Faxes", "event": [ { "listen": "test", @@ -1832,7 +2025,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { "key": "Content-Type", @@ -1841,7 +2034,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"company\": {{companyId}},\n \"feature\": 5\n}" + "raw": "{\n \"company\": {{companyId}},\n \"feature\": 3\n}" }, "url": { "raw": "{{brand_api_url}}/features_rel_companies", @@ -1856,7 +2049,7 @@ "response": [] }, { - "name": "Add Company Feature: Progress", + "name": "Add Company Feature: Friends", "event": [ { "listen": "test", @@ -1881,7 +2074,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { "key": "Content-Type", @@ -1890,7 +2083,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"company\": {{companyId}},\n \"feature\": 8\n}" + "raw": "{\n \"company\": {{companyId}},\n \"feature\": 4\n}" }, "url": { "raw": "{{brand_api_url}}/features_rel_companies", @@ -1905,7 +2098,7 @@ "response": [] }, { - "name": "Create Alice Terminal", + "name": "Add Company Feature: Conferences", "event": [ { "listen": "test", @@ -1919,7 +2112,6 @@ "", "tests[\"Response body has token id\"] = jsonData.id !== undefined;", "", - "postman.setGlobalVariable(\"aliceTerminalId\", jsonData.id);", "" ], "type": "text/javascript" @@ -1931,7 +2123,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { "key": "Content-Type", @@ -1940,22 +2132,22 @@ ], "body": { "mode": "raw", - "raw": "{\n \"name\": \"alice\",\n \"directMediaMethod\": \"invite\",\n \"password\": \"4l1C3P4sSw0rd+\",\n \"company\": {{companyId}},\n \"terminalModel\": 5\n}" + "raw": "{\n \"company\": {{companyId}},\n \"feature\": 5\n}" }, "url": { - "raw": "{{client_api_url}}/terminals", + "raw": "{{brand_api_url}}/features_rel_companies", "host": [ - "{{client_api_url}}" + "{{brand_api_url}}" ], "path": [ - "terminals" + "features_rel_companies" ] } }, "response": [] }, { - "name": "Create Alice User", + "name": "Add Company Feature: Progress", "event": [ { "listen": "test", @@ -1969,8 +2161,6 @@ "", "tests[\"Response body has token id\"] = jsonData.id !== undefined;", "", - "postman.setGlobalVariable(\"aliceUserId\", jsonData.id);", - "", "" ], "type": "text/javascript" @@ -1982,7 +2172,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { "key": "Content-Type", @@ -1991,22 +2181,22 @@ ], "body": { "mode": "raw", - "raw": "{\n \"name\": \"Alice\",\n \"lastname\": \"Allison\",\n \"email\": \"alice@bbs.ivozprovider.local\",\n \"pass\": \"4l1c3p4ssw0rd\",\n \"company\": {{companyId}},\n \"terminal\": {{aliceTerminalId}},\n \"transformationRuleSet\": 70,\n \"timezone\": 70\n}" + "raw": "{\n \"company\": {{companyId}},\n \"feature\": 8\n}" }, "url": { - "raw": "{{client_api_url}}/users", + "raw": "{{brand_api_url}}/features_rel_companies", "host": [ - "{{client_api_url}}" + "{{brand_api_url}}" ], "path": [ - "users" + "features_rel_companies" ] } }, "response": [] }, { - "name": "Create Alice Extension", + "name": "Create Alice Terminal", "event": [ { "listen": "test", @@ -2020,7 +2210,7 @@ "", "tests[\"Response body has token id\"] = jsonData.id !== undefined;", "", - "postman.setGlobalVariable(\"aliceExtensionId\", jsonData.id);", + "postman.setGlobalVariable(\"aliceTerminalId\", jsonData.id);", "" ], "type": "text/javascript" @@ -2032,7 +2222,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -2041,22 +2231,22 @@ ], "body": { "mode": "raw", - "raw": "{\n \"number\": \"1001\",\n \"routeType\": \"user\",\n \"company\": {{companyId}},\n \"user\": {{aliceUserId}}\n}" + "raw": "{\n \"name\": \"alice\",\n \"directMediaMethod\": \"invite\",\n \"password\": \"4l1C3P4sSw0rd+\",\n \"company\": {{companyId}},\n \"terminalModel\": 5\n}" }, "url": { - "raw": "{{client_api_url}}/extensions", + "raw": "{{client_api_url}}/terminals", "host": [ "{{client_api_url}}" ], "path": [ - "extensions" + "terminals" ] } }, "response": [] }, { - "name": "Create Alice DDI", + "name": "Create Alice User", "event": [ { "listen": "test", @@ -2070,7 +2260,8 @@ "", "tests[\"Response body has token id\"] = jsonData.id !== undefined;", "", - "postman.setGlobalVariable(\"aliceDDIId\", jsonData.id);", + "postman.setGlobalVariable(\"aliceUserId\", jsonData.id);", + "", "" ], "type": "text/javascript" @@ -2082,7 +2273,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -2091,22 +2282,22 @@ ], "body": { "mode": "raw", - "raw": "{\n \"ddi\": \"999661001\",\n \"routeType\": \"user\",\n \"company\": {{companyId}},\n \"brand\": {{brandId}},\n \"user\": {{aliceUserId}},\n \"peeringContract\": {{ddiProviderId}},\n \"country\": 70\n}" + "raw": "{\n \"name\": \"Alice\",\n \"lastname\": \"Allison\",\n \"email\": \"alice@bbs.ivozprovider.local\",\n \"pass\": \"4l1c3p4ssw0rd\",\n \"company\": {{companyId}},\n \"terminal\": {{aliceTerminalId}},\n \"transformationRuleSet\": 70,\n \"timezone\": 70\n}" }, "url": { - "raw": "{{client_api_url}}/ddis", + "raw": "{{client_api_url}}/users", "host": [ "{{client_api_url}}" ], "path": [ - "ddis" + "users" ] } }, "response": [] }, { - "name": "Create Bob Terminal", + "name": "Create Alice Extension", "event": [ { "listen": "test", @@ -2120,8 +2311,7 @@ "", "tests[\"Response body has token id\"] = jsonData.id !== undefined;", "", - "postman.setGlobalVariable(\"bobTerminalId\", jsonData.id);", - "", + "postman.setGlobalVariable(\"aliceExtensionId\", jsonData.id);", "" ], "type": "text/javascript" @@ -2133,7 +2323,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -2142,22 +2332,22 @@ ], "body": { "mode": "raw", - "raw": "{\n \"name\": \"bob\",\n \"directMediaMethod\": \"invite\",\n \"password\": \"b0bP4sSW0rd+\",\n \"company\": {{companyId}},\n \"terminalModel\": 5\n}" + "raw": "{\n \"number\": \"1001\",\n \"routeType\": \"user\",\n \"company\": {{companyId}},\n \"user\": {{aliceUserId}}\n}" }, "url": { - "raw": "{{client_api_url}}/terminals", + "raw": "{{client_api_url}}/extensions", "host": [ "{{client_api_url}}" ], "path": [ - "terminals" + "extensions" ] } }, "response": [] }, { - "name": "Create Bob User", + "name": "Create Alice DDI", "event": [ { "listen": "test", @@ -2171,7 +2361,7 @@ "", "tests[\"Response body has token id\"] = jsonData.id !== undefined;", "", - "postman.setGlobalVariable(\"bobUserId\", jsonData.id);", + "postman.setGlobalVariable(\"aliceDDIId\", jsonData.id);", "" ], "type": "text/javascript" @@ -2183,7 +2373,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { "key": "Content-Type", @@ -2192,28 +2382,28 @@ ], "body": { "mode": "raw", - "raw": "{\n \"name\": \"Bob\",\n \"lastname\": \"Bobson\",\n \"email\": \"bob@bbs.ivozprovider.local\",\n \"pass\": \"b0bp4ssw0rd\",\n \"company\": {{companyId}},\n \"terminal\": {{bobTerminalId}},\n \"transformationRuleSet\": 70, \n \"timezone\": 70\n}" + "raw": "{\n \"ddi\": \"999661001\",\n \"routeType\": \"user\",\n \"company\": {{companyId}},\n \"brand\": {{brandId}},\n \"user\": {{aliceUserId}},\n \"peeringContract\": {{ddiProviderId}},\n \"country\": 70\n}" }, "url": { - "raw": "{{client_api_url}}/users", + "raw": "{{brand_api_url}}/ddis", "host": [ - "{{client_api_url}}" + "{{brand_api_url}}" ], "path": [ - "users" + "ddis" ] } }, "response": [] }, { - "name": "Create Bob Extension", + "name": "Route Alice DDI to Alice", "event": [ { "listen": "test", "script": { "exec": [ - "tests[\"Status code is 201\"] = responseCode.code === 201;", + "tests[\"Status code is 200\"] = responseCode.code === 200;", "", "var jsonData = JSON.parse(responseBody)", "", @@ -2221,8 +2411,6 @@ "", "tests[\"Response body has token id\"] = jsonData.id !== undefined;", "", - "postman.setGlobalVariable(\"bobExtensionId\", jsonData.id);", - "", "" ], "type": "text/javascript" @@ -2230,11 +2418,11 @@ } ], "request": { - "method": "POST", + "method": "PUT", "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -2243,22 +2431,23 @@ ], "body": { "mode": "raw", - "raw": "{\n \"number\": \"1002\",\n \"routeType\": \"user\",\n \"company\": {{companyId}},\n \"user\": {{bobUserId}}\n}" + "raw": "{\n \"routeType\": \"user\",\n \"user\": {{aliceUserId}}\n}" }, "url": { - "raw": "{{client_api_url}}/extensions", + "raw": "{{client_api_url}}/ddis/{{aliceDDIId}}", "host": [ "{{client_api_url}}" ], "path": [ - "extensions" + "ddis", + "{{aliceDDIId}}" ] } }, "response": [] }, { - "name": "Create Bob DDI", + "name": "Create Bob Terminal", "event": [ { "listen": "test", @@ -2272,7 +2461,8 @@ "", "tests[\"Response body has token id\"] = jsonData.id !== undefined;", "", - "postman.setGlobalVariable(\"bobDDIId\", jsonData.id);", + "postman.setGlobalVariable(\"bobTerminalId\", jsonData.id);", + "", "" ], "type": "text/javascript" @@ -2284,7 +2474,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -2293,22 +2483,22 @@ ], "body": { "mode": "raw", - "raw": "{\n \"ddi\": \"999661002\",\n \"routeType\": \"user\",\n \"company\": {{companyId}},\n \"brand\": {{brandId}},\n \"user\": {{bobUserId}},\n \"ddiProvider\": {{ddiProviderId}},\n \"country\": 70\n}" + "raw": "{\n \"name\": \"bob\",\n \"directMediaMethod\": \"invite\",\n \"password\": \"b0bP4sSW0rd+\",\n \"company\": {{companyId}},\n \"terminalModel\": 5\n}" }, "url": { - "raw": "{{client_api_url}}/ddis", + "raw": "{{client_api_url}}/terminals", "host": [ "{{client_api_url}}" ], "path": [ - "ddis" + "terminals" ] } }, "response": [] }, { - "name": "Create Charlie Terminal", + "name": "Create Bob User", "event": [ { "listen": "test", @@ -2322,8 +2512,7 @@ "", "tests[\"Response body has token id\"] = jsonData.id !== undefined;", "", - "postman.setGlobalVariable(\"charlieTerminalId\", jsonData.id);", - "", + "postman.setGlobalVariable(\"bobUserId\", jsonData.id);", "" ], "type": "text/javascript" @@ -2335,7 +2524,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -2344,22 +2533,22 @@ ], "body": { "mode": "raw", - "raw": "{\n \"name\": \"charlie\",\n \"directMediaMethod\": \"invite\",\n \"password\": \"Ch4rL1Ep4SSword+\",\n \"company\": {{companyId}},\n \"terminalModel\": 5\n}" + "raw": "{\n \"name\": \"Bob\",\n \"lastname\": \"Bobson\",\n \"email\": \"bob@bbs.ivozprovider.local\",\n \"pass\": \"b0bp4ssw0rd\",\n \"company\": {{companyId}},\n \"terminal\": {{bobTerminalId}},\n \"transformationRuleSet\": 70, \n \"timezone\": 70\n}" }, "url": { - "raw": "{{client_api_url}}/terminals", + "raw": "{{client_api_url}}/users", "host": [ "{{client_api_url}}" ], "path": [ - "terminals" + "users" ] } }, "response": [] }, { - "name": "Create Charlie User", + "name": "Create Bob Extension", "event": [ { "listen": "test", @@ -2373,7 +2562,7 @@ "", "tests[\"Response body has token id\"] = jsonData.id !== undefined;", "", - "postman.setGlobalVariable(\"charlieUserId\", jsonData.id);", + "postman.setGlobalVariable(\"bobExtensionId\", jsonData.id);", "", "" ], @@ -2386,7 +2575,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -2395,22 +2584,22 @@ ], "body": { "mode": "raw", - "raw": "{\n \"name\": \"Charlie\",\n \"lastname\": \"Charlieson\",\n \"email\": \"charlie@bbs.ivozprovider.local\",\n \"pass\": \"ch4rl1ep4ssw0rd\",\n \"company\": {{companyId}},\n \"terminal\": {{charlieTerminalId}},\n \"transformationRuleSet\": 70, \n \"timezone\": 70\n}" + "raw": "{\n \"number\": \"1002\",\n \"routeType\": \"user\",\n \"company\": {{companyId}},\n \"user\": {{bobUserId}}\n}" }, "url": { - "raw": "{{client_api_url}}/users", + "raw": "{{client_api_url}}/extensions", "host": [ "{{client_api_url}}" ], "path": [ - "users" + "extensions" ] } }, "response": [] }, { - "name": "Create Charlie Extension", + "name": "Create Bob DDI", "event": [ { "listen": "test", @@ -2424,8 +2613,7 @@ "", "tests[\"Response body has token id\"] = jsonData.id !== undefined;", "", - "postman.setGlobalVariable(\"charlieExtensionId\", jsonData.id);", - "", + "postman.setGlobalVariable(\"bobDDIId\", jsonData.id);", "" ], "type": "text/javascript" @@ -2437,7 +2625,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { "key": "Content-Type", @@ -2446,28 +2634,28 @@ ], "body": { "mode": "raw", - "raw": "{\n \"number\": \"1003\",\n \"routeType\": \"user\",\n \"company\": {{companyId}},\n \"user\": {{charlieUserId}}\n}" + "raw": "{\n \"ddi\": \"999661002\",\n \"routeType\": \"user\",\n \"company\": {{companyId}},\n \"brand\": {{brandId}},\n \"user\": {{bobUserId}},\n \"ddiProvider\": {{ddiProviderId}},\n \"country\": 70\n}" }, "url": { - "raw": "{{client_api_url}}/extensions", + "raw": "{{brand_api_url}}/ddis", "host": [ - "{{client_api_url}}" + "{{brand_api_url}}" ], "path": [ - "extensions" + "ddis" ] } }, "response": [] }, { - "name": "Create Charlie DDI", + "name": "Route Bob DDI to Bob", "event": [ { "listen": "test", "script": { "exec": [ - "tests[\"Status code is 201\"] = responseCode.code === 201;", + "tests[\"Status code is 200\"] = responseCode.code === 200;", "", "var jsonData = JSON.parse(responseBody)", "", @@ -2475,7 +2663,6 @@ "", "tests[\"Response body has token id\"] = jsonData.id !== undefined;", "", - "postman.setGlobalVariable(\"charlieDDIId\", jsonData.id);", "" ], "type": "text/javascript" @@ -2483,11 +2670,11 @@ } ], "request": { - "method": "POST", + "method": "PUT", "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -2496,22 +2683,23 @@ ], "body": { "mode": "raw", - "raw": "{\n \"ddi\": \"999661003\",\n \"routeType\": \"user\",\n \"company\": {{companyId}},\n \"brand\": {{brandId}},\n \"user\": {{charlieUserId}},\n \"ddiProvider\": {{ddiProviderId}},\n \"country\": 70\n}" + "raw": "{\n \"routeType\": \"user\",\n \"user\": {{bobUserId}}\n}" }, "url": { - "raw": "{{client_api_url}}/ddis", + "raw": "{{client_api_url}}/ddis/{{bobDDIId}}", "host": [ "{{client_api_url}}" ], "path": [ - "ddis" + "ddis", + "{{bobDDIId}}" ] } }, "response": [] }, { - "name": "Create Dave Terminal", + "name": "Create Charlie Terminal", "event": [ { "listen": "test", @@ -2525,7 +2713,7 @@ "", "tests[\"Response body has token id\"] = jsonData.id !== undefined;", "", - "postman.setGlobalVariable(\"daveTerminalId\", jsonData.id);", + "postman.setGlobalVariable(\"charlieTerminalId\", jsonData.id);", "", "" ], @@ -2538,7 +2726,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -2547,7 +2735,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"name\": \"dave\",\n \"directMediaMethod\": \"invite\",\n \"password\": \"D4vEp4SSw0rd+\",\n \"company\": {{companyId}},\n \"terminalModel\": 5\n}" + "raw": "{\n \"name\": \"charlie\",\n \"directMediaMethod\": \"invite\",\n \"password\": \"Ch4rL1Ep4SSword+\",\n \"company\": {{companyId}},\n \"terminalModel\": 5\n}" }, "url": { "raw": "{{client_api_url}}/terminals", @@ -2562,7 +2750,7 @@ "response": [] }, { - "name": "Create Dave User", + "name": "Create Charlie User", "event": [ { "listen": "test", @@ -2576,7 +2764,7 @@ "", "tests[\"Response body has token id\"] = jsonData.id !== undefined;", "", - "postman.setGlobalVariable(\"daveUserId\", jsonData.id);", + "postman.setGlobalVariable(\"charlieUserId\", jsonData.id);", "", "" ], @@ -2589,7 +2777,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -2598,7 +2786,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"name\": \"Dave\",\n \"lastname\": \"Daveson\",\n \"email\": \"deve@bbs.ivozprovider.local\",\n \"pass\": \"d4v3p4ssw0rd\",\n \"company\": {{companyId}},\n \"terminal\": {{daveTerminalId}},\n \"transformationRuleSet\": {{transformationUSA999}},\n \"timezone\": 70\n}" + "raw": "{\n \"name\": \"Charlie\",\n \"lastname\": \"Charlieson\",\n \"email\": \"charlie@bbs.ivozprovider.local\",\n \"pass\": \"ch4rl1ep4ssw0rd\",\n \"company\": {{companyId}},\n \"terminal\": {{charlieTerminalId}},\n \"transformationRuleSet\": 70, \n \"timezone\": 70\n}" }, "url": { "raw": "{{client_api_url}}/users", @@ -2613,7 +2801,7 @@ "response": [] }, { - "name": "Create Dave Extension", + "name": "Create Charlie Extension", "event": [ { "listen": "test", @@ -2627,7 +2815,8 @@ "", "tests[\"Response body has token id\"] = jsonData.id !== undefined;", "", - "postman.setGlobalVariable(\"daveExtensionId\", jsonData.id);", + "postman.setGlobalVariable(\"charlieExtensionId\", jsonData.id);", + "", "" ], "type": "text/javascript" @@ -2639,7 +2828,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -2648,7 +2837,7 @@ ], "body": { "mode": "raw", - "raw": "\n{\n \"number\": \"1004\",\n \"routeType\": \"user\",\n \"company\": {{companyId}},\n \"user\": {{daveUserId}}\n}" + "raw": "{\n \"number\": \"1003\",\n \"routeType\": \"user\",\n \"company\": {{companyId}},\n \"user\": {{charlieUserId}}\n}" }, "url": { "raw": "{{client_api_url}}/extensions", @@ -2663,7 +2852,7 @@ "response": [] }, { - "name": "Create Dave DDI", + "name": "Create Charlie DDI", "event": [ { "listen": "test", @@ -2677,7 +2866,7 @@ "", "tests[\"Response body has token id\"] = jsonData.id !== undefined;", "", - "postman.setGlobalVariable(\"daveDDIId\", jsonData.id);", + "postman.setGlobalVariable(\"charlieDDIId\", jsonData.id);", "" ], "type": "text/javascript" @@ -2689,7 +2878,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { "key": "Content-Type", @@ -2698,12 +2887,12 @@ ], "body": { "mode": "raw", - "raw": "\n{\n \"ddi\": \"999661004\",\n \"routeType\": \"user\",\n \"company\": {{companyId}},\n \"brand\": {{brandId}},\n \"user\": {{daveUserId}},\n \"ddiProvider\": {{ddiProviderId}},\n \"country\": 235\n}" + "raw": "{\n \"ddi\": \"999661003\",\n \"routeType\": \"user\",\n \"company\": {{companyId}},\n \"brand\": {{brandId}},\n \"user\": {{charlieUserId}},\n \"ddiProvider\": {{ddiProviderId}},\n \"country\": 70\n}" }, "url": { - "raw": "{{client_api_url}}/ddis", + "raw": "{{brand_api_url}}/ddis", "host": [ - "{{client_api_url}}" + "{{brand_api_url}}" ], "path": [ "ddis" @@ -2713,13 +2902,13 @@ "response": [] }, { - "name": "Create Eve Terminal", + "name": "Route Charlie DDI to Charlie", "event": [ { "listen": "test", "script": { "exec": [ - "tests[\"Status code is 201\"] = responseCode.code === 201;", + "tests[\"Status code is 200\"] = responseCode.code === 200;", "", "var jsonData = JSON.parse(responseBody)", "", @@ -2727,7 +2916,15 @@ "", "tests[\"Response body has token id\"] = jsonData.id !== undefined;", "", - "postman.setGlobalVariable(\"eveTerminalId\", jsonData.id);", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ "" ], "type": "text/javascript" @@ -2735,11 +2932,11 @@ } ], "request": { - "method": "POST", + "method": "PUT", "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -2748,22 +2945,23 @@ ], "body": { "mode": "raw", - "raw": "{\n \"name\": \"eve\",\n \"directMediaMethod\": \"invite\",\n \"password\": \"Ev3p4SSw0rd+\",\n \"company\": {{companyId}},\n \"terminalModel\": 5\n}" + "raw": "{\n \"routeType\": \"user\",\n \"user\": {{charlieUserId}}\n}" }, "url": { - "raw": "{{client_api_url}}/terminals", + "raw": "{{client_api_url}}/ddis/{{charlieDDIId}}", "host": [ "{{client_api_url}}" ], "path": [ - "terminals" + "ddis", + "{{charlieDDIId}}" ] } }, "response": [] }, { - "name": "Create Eve User", + "name": "Create Dave Terminal", "event": [ { "listen": "test", @@ -2777,7 +2975,7 @@ "", "tests[\"Response body has token id\"] = jsonData.id !== undefined;", "", - "postman.setGlobalVariable(\"eveUserId\", jsonData.id);", + "postman.setGlobalVariable(\"daveTerminalId\", jsonData.id);", "", "" ], @@ -2790,7 +2988,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -2799,22 +2997,22 @@ ], "body": { "mode": "raw", - "raw": "{\n \"name\": \"Eve\",\n \"lastname\": \"Eveson\",\n \"email\": \"eve@bbs.ivozprovider.local\",\n \"pass\": \"3v3p4ssw0rd\",\n \"company\": {{companyId}},\n \"terminal\": {{eveTerminalId}},\n \"transformationRuleSet\": {{transformationUSA999}},\n \"timezone\": 70\n}" + "raw": "{\n \"name\": \"dave\",\n \"directMediaMethod\": \"invite\",\n \"password\": \"D4vEp4SSw0rd+\",\n \"company\": {{companyId}},\n \"terminalModel\": 5\n}" }, "url": { - "raw": "{{client_api_url}}/users", + "raw": "{{client_api_url}}/terminals", "host": [ "{{client_api_url}}" ], "path": [ - "users" + "terminals" ] } }, "response": [] }, { - "name": "Create Eve Extension", + "name": "Create Dave User", "event": [ { "listen": "test", @@ -2828,7 +3026,7 @@ "", "tests[\"Response body has token id\"] = jsonData.id !== undefined;", "", - "postman.setGlobalVariable(\"eveExtensionId\", jsonData.id);", + "postman.setGlobalVariable(\"daveUserId\", jsonData.id);", "", "" ], @@ -2841,7 +3039,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -2850,22 +3048,22 @@ ], "body": { "mode": "raw", - "raw": "{\n \"number\": \"1005\",\n \"routeType\": \"user\",\n \"company\": {{companyId}},\n \"user\": {{eveUserId}}\n}" + "raw": "{\n \"name\": \"Dave\",\n \"lastname\": \"Daveson\",\n \"email\": \"deve@bbs.ivozprovider.local\",\n \"pass\": \"d4v3p4ssw0rd\",\n \"company\": {{companyId}},\n \"terminal\": {{daveTerminalId}},\n \"transformationRuleSet\": {{transformationUSA999}},\n \"timezone\": 70\n}" }, "url": { - "raw": "{{client_api_url}}/extensions", + "raw": "{{client_api_url}}/users", "host": [ "{{client_api_url}}" ], "path": [ - "extensions" + "users" ] } }, "response": [] }, { - "name": "Create Eve DDI", + "name": "Create Dave Extension", "event": [ { "listen": "test", @@ -2879,7 +3077,7 @@ "", "tests[\"Response body has token id\"] = jsonData.id !== undefined;", "", - "postman.setGlobalVariable(\"eveDDIId\", jsonData.id);", + "postman.setGlobalVariable(\"daveExtensionId\", jsonData.id);", "" ], "type": "text/javascript" @@ -2891,7 +3089,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -2900,22 +3098,22 @@ ], "body": { "mode": "raw", - "raw": "{\n \"ddi\": \"999661005\",\n \"routeType\": \"user\",\n \"company\": {{companyId}},\n \"brand\": {{brandId}},\n \"user\": {{eveUserId}},\n \"ddiProvider\": {{ddiProviderId}},\n \"country\": 235\n}" + "raw": "\n{\n \"number\": \"1004\",\n \"routeType\": \"user\",\n \"company\": {{companyId}},\n \"user\": {{daveUserId}}\n}" }, "url": { - "raw": "{{client_api_url}}/ddis", + "raw": "{{client_api_url}}/extensions", "host": [ "{{client_api_url}}" ], "path": [ - "ddis" + "extensions" ] } }, "response": [] }, { - "name": "Create Boss/Assistant MatchList", + "name": "Create Dave DDI", "event": [ { "listen": "test", @@ -2929,8 +3127,7 @@ "", "tests[\"Response body has token id\"] = jsonData.id !== undefined;", "", - "postman.setGlobalVariable(\"bossAssistantWatchListId\", jsonData.id);", - "", + "postman.setGlobalVariable(\"daveDDIId\", jsonData.id);", "" ], "type": "text/javascript" @@ -2942,7 +3139,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { "key": "Content-Type", @@ -2951,28 +3148,28 @@ ], "body": { "mode": "raw", - "raw": "{\n \"name\": \"White List for Boss Frank\",\n \"company\": {{companyId}}\n}" + "raw": "\n{\n \"ddi\": \"999661004\",\n \"routeType\": \"user\",\n \"company\": {{companyId}},\n \"brand\": {{brandId}},\n \"user\": {{daveUserId}},\n \"ddiProvider\": {{ddiProviderId}},\n \"country\": 235\n}" }, "url": { - "raw": "{{client_api_url}}/match_lists", + "raw": "{{brand_api_url}}/ddis", "host": [ - "{{client_api_url}}" + "{{brand_api_url}}" ], "path": [ - "match_lists" + "ddis" ] } }, "response": [] }, { - "name": "Create Boss/Assistant MatchList Pattern Ext", + "name": "Route Dave DDI to Dave", "event": [ { "listen": "test", "script": { "exec": [ - "tests[\"Status code is 201\"] = responseCode.code === 201;", + "tests[\"Status code is 200\"] = responseCode.code === 200;", "", "var jsonData = JSON.parse(responseBody)", "", @@ -2984,14 +3181,23 @@ ], "type": "text/javascript" } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } } ], "request": { - "method": "POST", + "method": "PUT", "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -3000,22 +3206,23 @@ ], "body": { "mode": "raw", - "raw": "{\n \"description\": \"Alice DDI Number\",\n \"type\": \"number\",\n \"numbervalue\": \"999661001\",\n \"matchList\": {{bossAssistantWatchListId}},\n \"numberCountry\": 70\n}" + "raw": "{\n \"routeType\": \"user\",\n \"user\": {{daveUserId}}\n}" }, "url": { - "raw": "{{client_api_url}}/match_list_patterns", + "raw": "{{client_api_url}}/ddis/{{daveDDIId}}", "host": [ "{{client_api_url}}" ], "path": [ - "match_list_patterns" + "ddis", + "{{daveDDIId}}" ] } }, "response": [] }, { - "name": "Create Boss/Assistant MatchList Pattern Int", + "name": "Create Eve Terminal", "event": [ { "listen": "test", @@ -3029,6 +3236,7 @@ "", "tests[\"Response body has token id\"] = jsonData.id !== undefined;", "", + "postman.setGlobalVariable(\"eveTerminalId\", jsonData.id);", "" ], "type": "text/javascript" @@ -3040,7 +3248,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -3049,22 +3257,22 @@ ], "body": { "mode": "raw", - "raw": "{\n \"description\": \"Alice Extension Number\",\n \"type\": \"regexp\",\n \"regexp\": \"^1001$\",\n \"matchList\": {{bossAssistantWatchListId}}\n}" + "raw": "{\n \"name\": \"eve\",\n \"directMediaMethod\": \"invite\",\n \"password\": \"Ev3p4SSw0rd+\",\n \"company\": {{companyId}},\n \"terminalModel\": 5\n}" }, "url": { - "raw": "{{client_api_url}}/match_list_patterns", + "raw": "{{client_api_url}}/terminals", "host": [ "{{client_api_url}}" ], "path": [ - "match_list_patterns" + "terminals" ] } }, "response": [] }, { - "name": "Create Frank Terminal", + "name": "Create Eve User", "event": [ { "listen": "test", @@ -3078,7 +3286,8 @@ "", "tests[\"Response body has token id\"] = jsonData.id !== undefined;", "", - "postman.setGlobalVariable(\"frankTerminalId\", jsonData.id);", + "postman.setGlobalVariable(\"eveUserId\", jsonData.id);", + "", "" ], "type": "text/javascript" @@ -3090,7 +3299,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -3099,22 +3308,22 @@ ], "body": { "mode": "raw", - "raw": "{\n \"name\": \"frank\",\n \"directMediaMethod\": \"invite\",\n \"password\": \"fr4Nkp4SSw0rd+\",\n \"company\": {{companyId}},\n \"terminalModel\": 5\n}" + "raw": "{\n \"name\": \"Eve\",\n \"lastname\": \"Eveson\",\n \"email\": \"eve@bbs.ivozprovider.local\",\n \"pass\": \"3v3p4ssw0rd\",\n \"company\": {{companyId}},\n \"terminal\": {{eveTerminalId}},\n \"transformationRuleSet\": {{transformationUSA999}},\n \"timezone\": 70\n}" }, "url": { - "raw": "{{client_api_url}}/terminals", + "raw": "{{client_api_url}}/users", "host": [ "{{client_api_url}}" ], "path": [ - "terminals" + "users" ] } }, "response": [] }, { - "name": "Create Frank User", + "name": "Create Eve Extension", "event": [ { "listen": "test", @@ -3128,7 +3337,8 @@ "", "tests[\"Response body has token id\"] = jsonData.id !== undefined;", "", - "postman.setGlobalVariable(\"frankUserId\", jsonData.id);", + "postman.setGlobalVariable(\"eveExtensionId\", jsonData.id);", + "", "" ], "type": "text/javascript" @@ -3140,7 +3350,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -3149,22 +3359,22 @@ ], "body": { "mode": "raw", - "raw": "{\n \"name\": \"Frank\",\n \"lastname\": \"Frankson\",\n \"email\": \"frank@bbs.ivozprovider.local\",\n \"pass\": \"fr4nkp4ssw0rd\",\n \"isBoss\": true,\n \"company\": {{companyId}},\n \"bossAssistant\": {{daveUserId}},\n \"bossAssistantWhiteList\": {{bossAssistantWatchListId}},\n \"transformationRuleSet\": {{transformationUSA999}},\n \"terminal\": {{frankTerminalId}},\n \"timezone\": 1\n}" + "raw": "{\n \"number\": \"1005\",\n \"routeType\": \"user\",\n \"company\": {{companyId}},\n \"user\": {{eveUserId}}\n}" }, "url": { - "raw": "{{client_api_url}}/users", + "raw": "{{client_api_url}}/extensions", "host": [ "{{client_api_url}}" ], "path": [ - "users" + "extensions" ] } }, "response": [] }, { - "name": "Create Frank Extension", + "name": "Create Eve DDI", "event": [ { "listen": "test", @@ -3178,7 +3388,7 @@ "", "tests[\"Response body has token id\"] = jsonData.id !== undefined;", "", - "postman.setGlobalVariable(\"frankExtensionId\", jsonData.id);", + "postman.setGlobalVariable(\"eveDDIId\", jsonData.id);", "" ], "type": "text/javascript" @@ -3190,7 +3400,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { "key": "Content-Type", @@ -3199,28 +3409,28 @@ ], "body": { "mode": "raw", - "raw": "{\n \"number\": \"1006\",\n \"routeType\": \"user\",\n \"company\": {{companyId}},\n \"user\": {{frankUserId}}\n}" + "raw": "{\n \"ddi\": \"999661005\",\n \"routeType\": \"user\",\n \"company\": {{companyId}},\n \"brand\": {{brandId}},\n \"user\": {{eveUserId}},\n \"ddiProvider\": {{ddiProviderId}},\n \"country\": 235\n}" }, "url": { - "raw": "{{client_api_url}}/extensions", + "raw": "{{brand_api_url}}/ddis", "host": [ - "{{client_api_url}}" + "{{brand_api_url}}" ], "path": [ - "extensions" + "ddis" ] } }, "response": [] }, { - "name": "Create Frank DDI", + "name": "Route Eve DDI to Eve", "event": [ { "listen": "test", "script": { "exec": [ - "tests[\"Status code is 201\"] = responseCode.code === 201;", + "tests[\"Status code is 200\"] = responseCode.code === 200;", "", "var jsonData = JSON.parse(responseBody)", "", @@ -3228,7 +3438,15 @@ "", "tests[\"Response body has token id\"] = jsonData.id !== undefined;", "", - "postman.setGlobalVariable(\"frankDDIId\", jsonData.id);", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ "" ], "type": "text/javascript" @@ -3236,11 +3454,11 @@ } ], "request": { - "method": "POST", + "method": "PUT", "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -3249,56 +3467,50 @@ ], "body": { "mode": "raw", - "raw": "\n{\n \"ddi\": \"999661006\",\n \"routeType\": \"user\",\n \"company\": {{companyId}},\n \"brand\": {{brandId}},\n \"user\": {{frankUserId}},\n \"ddiProvider\": {{ddiProviderId}},\n \"country\": 70\n}" + "raw": "{\n \"routeType\": \"user\",\n \"user\": {{eveUserId}}\n}" }, "url": { - "raw": "{{client_api_url}}/ddis", + "raw": "{{client_api_url}}/ddis/{{eveDDIId}}", "host": [ "{{client_api_url}}" ], "path": [ - "ddis" + "ddis", + "{{eveDDIId}}" ] } }, "response": [] }, { - "name": "Set Default Company DDI", + "name": "Create Boss/Assistant MatchList", "event": [ { - "listen": "prerequest", + "listen": "test", "script": { "exec": [ - "var companyData = JSON.parse(postman.getGlobalVariable(\"companyData\"));", + "tests[\"Status code is 201\"] = responseCode.code === 201;", "", - "companyData.outgoingDdi = postman.getGlobalVariable(\"aliceDDIId\");", + "var jsonData = JSON.parse(responseBody)", "", - "postman.setGlobalVariable(\"companyData\", JSON.stringify(companyData));", + "tests[\"Response body is JSON\"] = jsonData !== undefined;", "", - "" - ], - "type": "text/javascript" - } - }, - { - "listen": "test", - "script": { - "exec": [ - "tests[\"Status code is 200\"] = responseCode.code === 200;", + "tests[\"Response body has token id\"] = jsonData.id !== undefined;", "", - "console.log(postman.getGlobalVariable(\"companyDataJson\"));" + "postman.setGlobalVariable(\"bossAssistantWatchListId\", jsonData.id);", + "", + "" ], "type": "text/javascript" } } ], "request": { - "method": "PUT", + "method": "POST", "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -3307,23 +3519,22 @@ ], "body": { "mode": "raw", - "raw": "{{companyData}}" + "raw": "{\n \"name\": \"White List for Boss Frank\",\n \"company\": {{companyId}}\n}" }, "url": { - "raw": "{{brand_api_url}}/companies/{{companyId}}", + "raw": "{{client_api_url}}/match_lists", "host": [ - "{{brand_api_url}}" + "{{client_api_url}}" ], "path": [ - "companies", - "{{companyId}}" + "match_lists" ] } }, "response": [] }, { - "name": "Create Friend", + "name": "Create Boss/Assistant MatchList Pattern Ext", "event": [ { "listen": "test", @@ -3337,8 +3548,6 @@ "", "tests[\"Response body has token id\"] = jsonData.id !== undefined;", "", - "postman.setGlobalVariable(\"friendId\", jsonData.id);", - "", "" ], "type": "text/javascript" @@ -3350,7 +3559,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -3359,22 +3568,22 @@ ], "body": { "mode": "raw", - "raw": "{\n \"name\": \"friend\",\n \"description\": \"BBS - Friend\",\n \"transport\": \"udp\",\n \"password\": \"fr13ndp4SSW0rd+\",\n \"priority\": 1,\n \"directConnectivity\": \"no\",\n \"company\": {{companyId}}\n}" + "raw": "{\n \"description\": \"Alice DDI Number\",\n \"type\": \"number\",\n \"numbervalue\": \"999661001\",\n \"matchList\": {{bossAssistantWatchListId}},\n \"numberCountry\": 70\n}" }, "url": { - "raw": "{{client_api_url}}/friends", + "raw": "{{client_api_url}}/match_list_patterns", "host": [ "{{client_api_url}}" ], "path": [ - "friends" + "match_list_patterns" ] } }, "response": [] }, { - "name": "Create Friend Pattern", + "name": "Create Boss/Assistant MatchList Pattern Int", "event": [ { "listen": "test", @@ -3388,8 +3597,6 @@ "", "tests[\"Response body has token id\"] = jsonData.id !== undefined;", "", - "postman.setGlobalVariable(\"friendPatternId\", jsonData.id);", - "", "" ], "type": "text/javascript" @@ -3401,7 +3608,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -3410,22 +3617,22 @@ ], "body": { "mode": "raw", - "raw": "{\n \"name\": \"2XXX Extensions\",\n \"regExp\": \"^2[0-9]{3}$\",\n \"friend\": {{friendId}}\n}" + "raw": "{\n \"description\": \"Alice Extension Number\",\n \"type\": \"regexp\",\n \"regexp\": \"^1001$\",\n \"matchList\": {{bossAssistantWatchListId}}\n}" }, "url": { - "raw": "{{client_api_url}}/friends_patterns", + "raw": "{{client_api_url}}/match_list_patterns", "host": [ "{{client_api_url}}" ], "path": [ - "friends_patterns" + "match_list_patterns" ] } }, "response": [] }, { - "name": "Create Friend Extension", + "name": "Create Frank Terminal", "event": [ { "listen": "test", @@ -3439,7 +3646,7 @@ "", "tests[\"Response body has token id\"] = jsonData.id !== undefined;", "", - "postman.setGlobalVariable(\"friendExtensionId\", jsonData.id);", + "postman.setGlobalVariable(\"frankTerminalId\", jsonData.id);", "" ], "type": "text/javascript" @@ -3451,7 +3658,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -3460,22 +3667,22 @@ ], "body": { "mode": "raw", - "raw": "{\n \"number\": \"2001\",\n \"routeType\": \"friend\",\n \"company\": {{companyId}},\n \"friendValue\": \"2001\"\n}" + "raw": "{\n \"name\": \"frank\",\n \"directMediaMethod\": \"invite\",\n \"password\": \"fr4Nkp4SSw0rd+\",\n \"company\": {{companyId}},\n \"terminalModel\": 5\n}" }, "url": { - "raw": "{{client_api_url}}/extensions", + "raw": "{{client_api_url}}/terminals", "host": [ "{{client_api_url}}" ], "path": [ - "extensions" + "terminals" ] } }, "response": [] }, { - "name": "Create Route Lock", + "name": "Create Frank User", "event": [ { "listen": "test", @@ -3489,10 +3696,9 @@ "", "tests[\"Response body has token id\"] = jsonData.id !== undefined;", "", - "postman.setGlobalVariable(\"routeLockId\", jsonData.id);", + "postman.setGlobalVariable(\"frankUserId\", jsonData.id);", "" ], - "id": "77e6a7d4-a6f1-4d8f-99f5-6299a36e10a5", "type": "text/javascript" } } @@ -3502,7 +3708,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -3511,27 +3717,22 @@ ], "body": { "mode": "raw", - "raw": "{\n \"name\": \"BBS Route Lock\",\n \"description\": \"For testing Conditional Routes\",\n \"open\": false,\n \"company\": {{companyId}}\n}" + "raw": "{\n \"name\": \"Frank\",\n \"lastname\": \"Frankson\",\n \"email\": \"frank@bbs.ivozprovider.local\",\n \"pass\": \"fr4nkp4ssw0rd\",\n \"isBoss\": true,\n \"company\": {{companyId}},\n \"bossAssistant\": {{daveUserId}},\n \"bossAssistantWhiteList\": {{bossAssistantWatchListId}},\n \"transformationRuleSet\": {{transformationUSA999}},\n \"terminal\": {{frankTerminalId}},\n \"timezone\": 1\n}" }, "url": { - "raw": "{{client_api_url}}/route_locks", + "raw": "{{client_api_url}}/users", "host": [ "{{client_api_url}}" ], "path": [ - "route_locks" + "users" ] } }, "response": [] - } - ] - }, - { - "name": "0020 - Residential Data", - "item": [ + }, { - "name": "Create BBS Residential Client", + "name": "Create Frank Extension", "event": [ { "listen": "test", @@ -3545,7 +3746,7 @@ "", "tests[\"Response body has token id\"] = jsonData.id !== undefined;", "", - "postman.setGlobalVariable(\"residentialId\", jsonData.id);", + "postman.setGlobalVariable(\"frankExtensionId\", jsonData.id);", "" ], "type": "text/javascript" @@ -3557,7 +3758,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -3566,22 +3767,22 @@ ], "body": { "mode": "raw", - "raw": "{\n \"type\": \"residential\",\n \"name\": \"BBS - Residential for Black Box SIP tests\",\n \"nif\": \"09876543210ART\",\n \"externalMaxCalls\": 2,\n \"postalAddress\": \"Residential address\",\n \"postalCode\": \"48902\",\n \"town\": \"Residential town\",\n \"province\": \"Residential province\",\n \"countryName\": \"Residential country\",\n \"defaultTimezone\": 1,\n \"onDemandRecord\": 2,\n \"onDemandRecordCode\": \"234\",\n \"ipfilter\": false,\n \"transformationRuleSet\": 70,\n \"brand\": {{brandId}}\n}" + "raw": "{\n \"number\": \"1006\",\n \"routeType\": \"user\",\n \"company\": {{companyId}},\n \"user\": {{frankUserId}}\n}" }, "url": { - "raw": "{{brand_api_url}}/companies", + "raw": "{{client_api_url}}/extensions", "host": [ - "{{brand_api_url}}" + "{{client_api_url}}" ], "path": [ - "companies" + "extensions" ] } }, "response": [] }, { - "name": "Add Residential Rating Profile", + "name": "Create Frank DDI", "event": [ { "listen": "test", @@ -3595,9 +3796,9 @@ "", "tests[\"Response body has token id\"] = jsonData.id !== undefined;", "", + "postman.setGlobalVariable(\"frankDDIId\", jsonData.id);", "" ], - "id": "9d423fc8-954b-4358-be3d-a78ca5ddba30", "type": "text/javascript" } } @@ -3607,7 +3808,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { "key": "Content-Type", @@ -3616,22 +3817,22 @@ ], "body": { "mode": "raw", - "raw": "{\n \"activationTime\": \"2018-01-01 00:00:00.000\",\n \"company\": {{residentialId}},\n \"ratingPlanGroup\": {{ratingPlanGroupId}}\n}" + "raw": "\n{\n \"ddi\": \"999661006\",\n \"routeType\": \"user\",\n \"company\": {{companyId}},\n \"brand\": {{brandId}},\n \"user\": {{frankUserId}},\n \"ddiProvider\": {{ddiProviderId}},\n \"country\": 70\n}" }, "url": { - "raw": "{{brand_api_url}}/rating_profiles", + "raw": "{{brand_api_url}}/ddis", "host": [ "{{brand_api_url}}" ], "path": [ - "rating_profiles" + "ddis" ] } }, "response": [] }, { - "name": "Get BBS Residential data", + "name": "Route Frank DDI to Frank", "event": [ { "listen": "test", @@ -3639,11 +3840,21 @@ "exec": [ "tests[\"Status code is 200\"] = responseCode.code === 200;", "", - "var jsonData = JSON.parse(responseBody);", + "var jsonData = JSON.parse(responseBody)", "", "tests[\"Response body is JSON\"] = jsonData !== undefined;", "", - "postman.setGlobalVariable(\"residentialData\", responseBody);", + "tests[\"Response body has token id\"] = jsonData.id !== undefined;", + "", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ "" ], "type": "text/javascript" @@ -3651,61 +3862,70 @@ } ], "request": { - "method": "GET", + "method": "PUT", "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { - "key": "Accept", + "key": "Content-Type", "value": "application/json" } ], "body": { "mode": "raw", - "raw": "{\n \"type\": \"vpbx\",\n \"name\": \"BBS - Company for Black Box SIP tests\",\n \"domainUsers\": \"bbs.ivozprovider.local\",\n \"nif\": \"09876543210ART\",\n \"externalMaxCalls\": 2,\n \"postalAddress\": \"Company address\",\n \"postalCode\": \"48902\",\n \"town\": \"Company town\",\n \"province\": \"Company province\",\n \"countryName\": \"Company country\",\n \"defaultTimezone\": 1,\n \"brand\": {{brandId}}\n}" + "raw": "{\n \"routeType\": \"user\",\n \"user\": {{frankUserId}}\n}" }, "url": { - "raw": "{{brand_api_url}}/companies/{{residentialId}}", + "raw": "{{client_api_url}}/ddis/{{frankDDIId}}", "host": [ - "{{brand_api_url}}" + "{{client_api_url}}" ], "path": [ - "companies", - "{{residentialId}}" + "ddis", + "{{frankDDIId}}" ] } }, "response": [] }, { - "name": "Add Residential Feature: Recordings", + "name": "Set Default Company DDI", "event": [ { - "listen": "test", + "listen": "prerequest", "script": { "exec": [ - "tests[\"Status code is 201\"] = responseCode.code === 201;", - "", - "var jsonData = JSON.parse(responseBody)", + "var companyData = JSON.parse(postman.getGlobalVariable(\"companyData\"));", "", - "tests[\"Response body is JSON\"] = jsonData !== undefined;", + "companyData.outgoingDdi = postman.getGlobalVariable(\"aliceDDIId\");", "", - "tests[\"Response body has token id\"] = jsonData.id !== undefined;", + "postman.setGlobalVariable(\"companyData\", JSON.stringify(companyData));", "", "" ], "type": "text/javascript" } + }, + { + "listen": "test", + "script": { + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "console.log(postman.getGlobalVariable(\"companyDataJson\"));" + ], + "type": "text/javascript" + } } ], "request": { - "method": "POST", + "method": "PUT", "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { "key": "Content-Type", @@ -3714,22 +3934,23 @@ ], "body": { "mode": "raw", - "raw": "\n{\n \"company\": {{residentialId}},\n \"feature\": 2\n}" + "raw": "{{companyData}}" }, "url": { - "raw": "{{brand_api_url}}/features_rel_companies", + "raw": "{{brand_api_url}}/companies/{{companyId}}", "host": [ "{{brand_api_url}}" ], "path": [ - "features_rel_companies" + "companies", + "{{companyId}}" ] } }, "response": [] }, { - "name": "Add Residential Feature: Faxes", + "name": "Create Friend", "event": [ { "listen": "test", @@ -3743,6 +3964,8 @@ "", "tests[\"Response body has token id\"] = jsonData.id !== undefined;", "", + "postman.setGlobalVariable(\"friendId\", jsonData.id);", + "", "" ], "type": "text/javascript" @@ -3754,7 +3977,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -3763,22 +3986,22 @@ ], "body": { "mode": "raw", - "raw": "{\n \"company\": {{residentialId}},\n \"feature\": 3\n}" + "raw": "{\n \"name\": \"friend\",\n \"description\": \"BBS - Friend\",\n \"transport\": \"udp\",\n \"password\": \"fr13ndp4SSW0rd+\",\n \"priority\": 1,\n \"directConnectivity\": \"no\",\n \"company\": {{companyId}}\n}" }, "url": { - "raw": "{{brand_api_url}}/features_rel_companies", + "raw": "{{client_api_url}}/friends", "host": [ - "{{brand_api_url}}" + "{{client_api_url}}" ], "path": [ - "features_rel_companies" + "friends" ] } }, "response": [] }, { - "name": "Add Residential Feature: Progress", + "name": "Create Friend Pattern", "event": [ { "listen": "test", @@ -3792,6 +4015,8 @@ "", "tests[\"Response body has token id\"] = jsonData.id !== undefined;", "", + "postman.setGlobalVariable(\"friendPatternId\", jsonData.id);", + "", "" ], "type": "text/javascript" @@ -3803,7 +4028,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -3812,22 +4037,22 @@ ], "body": { "mode": "raw", - "raw": "{\n \"company\": {{residentialId}},\n \"feature\": 8\n}" + "raw": "{\n \"name\": \"2XXX Extensions\",\n \"regExp\": \"^2[0-9]{3}$\",\n \"friend\": {{friendId}}\n}" }, "url": { - "raw": "{{brand_api_url}}/features_rel_companies", + "raw": "{{client_api_url}}/friends_patterns", "host": [ - "{{brand_api_url}}" + "{{client_api_url}}" ], "path": [ - "features_rel_companies" + "friends_patterns" ] } }, "response": [] }, { - "name": "Create Residential Device", + "name": "Create Friend Extension", "event": [ { "listen": "test", @@ -3841,8 +4066,7 @@ "", "tests[\"Response body has token id\"] = jsonData.id !== undefined;", "", - "postman.setGlobalVariable(\"residentialDeviceId\", jsonData.id);", - "", + "postman.setGlobalVariable(\"friendExtensionId\", jsonData.id);", "" ], "type": "text/javascript" @@ -3854,7 +4078,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -3863,15 +4087,521 @@ ], "body": { "mode": "raw", - "raw": "{\n \"name\": \"20000\",\n \"transport\": \"udp\",\n \"password\": \"r3S1d3nT14lP4sSW0rd+\",\n \"directConnectivity\": \"no\",\n \"brand\": {{brandId}},\n \"company\": {{residentialId}}\n}" + "raw": "{\n \"number\": \"2001\",\n \"routeType\": \"friend\",\n \"company\": {{companyId}},\n \"friendValue\": \"2001\"\n}" }, "url": { - "raw": "{{client_api_url}}/residential_devices", + "raw": "{{client_api_url}}/extensions", "host": [ "{{client_api_url}}" ], "path": [ - "residential_devices" + "extensions" + ] + } + }, + "response": [] + }, + { + "name": "Create Route Lock", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var jsonData = JSON.parse(responseBody)", + "", + "tests[\"Response body is JSON\"] = jsonData !== undefined;", + "", + "tests[\"Response body has token id\"] = jsonData.id !== undefined;", + "", + "postman.setGlobalVariable(\"routeLockId\", jsonData.id);", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "{{client_api_auth}}" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"BBS Route Lock\",\n \"description\": \"For testing Conditional Routes\",\n \"open\": false,\n \"company\": {{companyId}}\n}" + }, + "url": { + "raw": "{{client_api_url}}/route_locks", + "host": [ + "{{client_api_url}}" + ], + "path": [ + "route_locks" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "0020 - Residential Data", + "item": [ + { + "name": "Create BBS Residential Client", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var jsonData = JSON.parse(responseBody)", + "", + "tests[\"Response body is JSON\"] = jsonData !== undefined;", + "", + "tests[\"Response body has token id\"] = jsonData.id !== undefined;", + "", + "postman.setGlobalVariable(\"residentialId\", jsonData.id);", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "{{brand_api_auth}}" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"type\": \"residential\",\n \"name\": \"BBS - Residential for Black Box SIP tests\",\n \"nif\": \"09876543210ART\",\n \"externalMaxCalls\": 2,\n \"postalAddress\": \"Residential address\",\n \"postalCode\": \"48902\",\n \"town\": \"Residential town\",\n \"province\": \"Residential province\",\n \"countryName\": \"Residential country\",\n \"defaultTimezone\": 1,\n \"onDemandRecord\": 2,\n \"onDemandRecordCode\": \"234\",\n \"ipfilter\": false,\n \"transformationRuleSet\": 70,\n \"brand\": {{brandId}},\n \"country\": 70,\n \"currency\": 1 \n}" + }, + "url": { + "raw": "{{brand_api_url}}/companies", + "host": [ + "{{brand_api_url}}" + ], + "path": [ + "companies" + ] + } + }, + "response": [] + }, + { + "name": "Create BBS Residential Admin", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var jsonData = JSON.parse(responseBody)", + "", + "tests[\"Response body is JSON\"] = jsonData !== undefined;", + "", + "tests[\"Response body has token id\"] = jsonData.id !== undefined;", + "", + "postman.setGlobalVariable(\"brandAdminId\", jsonData.id);", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "{{brand_api_auth}}" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"username\": \"residentialadmin\",\n \"pass\": \"unusedp4ssw0rd\",\n \"email\": \"residentialadmin@bbs.com\",\n \"active\": 1,\n \"restricted\": 0,\n \"brand\": {{brandId}},\n \"company\": {{residentialId}},\n \"timezone\": 145\n}" + }, + "url": { + "raw": "{{brand_api_url}}/administrators", + "host": [ + "{{brand_api_url}}" + ], + "path": [ + "administrators" + ] + } + }, + "response": [] + }, + { + "name": "Get Residential Authorization Token", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var jsonData = JSON.parse(responseBody)", + "", + "tests[\"Response body is JSON\"] = jsonData !== undefined;", + "", + "tests[\"Response body has token field\"] = jsonData.token !== undefined;", + "", + "postman.setGlobalVariable(\"residential_api_auth\", 'Bearer ' + jsonData.token);", + "postman.setGlobalVariable(\"residential_api_token\", jsonData.token);", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/x-www-form-urlencoded" + } + ], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "token", + "value": "{{brand_api_token}}", + "type": "text" + }, + { + "key": "username", + "value": "residentialadmin", + "type": "text" + } + ] + }, + "url": { + "raw": "{{client_api_url}}/token/exchange", + "host": [ + "{{client_api_url}}" + ], + "path": [ + "token", + "exchange" + ] + } + }, + "response": [] + }, + { + "name": "Add Residential Rating Profile", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var jsonData = JSON.parse(responseBody)", + "", + "tests[\"Response body is JSON\"] = jsonData !== undefined;", + "", + "tests[\"Response body has token id\"] = jsonData.id !== undefined;", + "", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "{{brand_api_auth}}" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"activationTime\": \"2018-01-01 00:00:00.000\",\n \"company\": {{residentialId}},\n \"ratingPlanGroup\": {{ratingPlanGroupId}}\n}" + }, + "url": { + "raw": "{{brand_api_url}}/rating_profiles", + "host": [ + "{{brand_api_url}}" + ], + "path": [ + "rating_profiles" + ] + } + }, + "response": [] + }, + { + "name": "Get BBS Residential data", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody);", + "", + "tests[\"Response body is JSON\"] = jsonData !== undefined;", + "", + "postman.setGlobalVariable(\"residentialData\", responseBody);", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "value": "{{brand_api_auth}}" + }, + { + "key": "Accept", + "value": "application/json" + } + ], + "url": { + "raw": "{{brand_api_url}}/companies/{{residentialId}}", + "host": [ + "{{brand_api_url}}" + ], + "path": [ + "companies", + "{{residentialId}}" + ] + } + }, + "response": [] + }, + { + "name": "Add Residential Feature: Recordings", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var jsonData = JSON.parse(responseBody)", + "", + "tests[\"Response body is JSON\"] = jsonData !== undefined;", + "", + "tests[\"Response body has token id\"] = jsonData.id !== undefined;", + "", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "{{brand_api_auth}}" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "\n{\n \"company\": {{residentialId}},\n \"feature\": 2\n}" + }, + "url": { + "raw": "{{brand_api_url}}/features_rel_companies", + "host": [ + "{{brand_api_url}}" + ], + "path": [ + "features_rel_companies" + ] + } + }, + "response": [] + }, + { + "name": "Add Residential Feature: Faxes", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var jsonData = JSON.parse(responseBody)", + "", + "tests[\"Response body is JSON\"] = jsonData !== undefined;", + "", + "tests[\"Response body has token id\"] = jsonData.id !== undefined;", + "", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "{{brand_api_auth}}" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"company\": {{residentialId}},\n \"feature\": 3\n}" + }, + "url": { + "raw": "{{brand_api_url}}/features_rel_companies", + "host": [ + "{{brand_api_url}}" + ], + "path": [ + "features_rel_companies" + ] + } + }, + "response": [] + }, + { + "name": "Add Residential Feature: Progress", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var jsonData = JSON.parse(responseBody)", + "", + "tests[\"Response body is JSON\"] = jsonData !== undefined;", + "", + "tests[\"Response body has token id\"] = jsonData.id !== undefined;", + "", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "{{brand_api_auth}}" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"company\": {{residentialId}},\n \"feature\": 8\n}" + }, + "url": { + "raw": "{{brand_api_url}}/features_rel_companies", + "host": [ + "{{brand_api_url}}" + ], + "path": [ + "features_rel_companies" + ] + } + }, + "response": [] + }, + { + "name": "Create Residential Device", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var jsonData = JSON.parse(responseBody)", + "", + "tests[\"Response body is JSON\"] = jsonData !== undefined;", + "", + "tests[\"Response body has token id\"] = jsonData.id !== undefined;", + "", + "postman.setGlobalVariable(\"residentialDeviceId\", jsonData.id);", + "", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "{{brand_api_auth}}" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"20000\",\n \"transport\": \"udp\",\n \"password\": \"r3S1d3nT14lP4sSW0rd+\",\n \"directConnectivity\": \"no\",\n \"brand\": {{brandId}},\n \"company\": {{residentialId}}\n}" + }, + "url": { + "raw": "{{brand_api_url}}/residential_devices", + "host": [ + "{{brand_api_url}}" + ], + "path": [ + "residential_devices" ] } }, @@ -3904,7 +4634,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { "key": "Content-Type", @@ -3916,9 +4646,9 @@ "raw": "{\n \"ddi\": \"999920000\",\n \"routeType\": \"residential\",\n \"company\": {{residentialId}},\n \"brand\": {{brandId}},\n \"residentialDevice\": {{residentialDeviceId}},\n \"ddiProvider\": {{ddiProviderId}},\n \"country\": 235\n}" }, "url": { - "raw": "{{client_api_url}}/ddis", + "raw": "{{brand_api_url}}/ddis", "host": [ - "{{client_api_url}}" + "{{brand_api_url}}" ], "path": [ "ddis" @@ -3927,6 +4657,65 @@ }, "response": [] }, + { + "name": "Route Residential DDI to Device", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody)", + "", + "tests[\"Response body is JSON\"] = jsonData !== undefined;", + "", + "tests[\"Response body has token id\"] = jsonData.id !== undefined;", + "", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Authorization", + "value": "{{residential_api_auth}}" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"routeType\": \"residential\",\n \"residentialDevice\": {{residentialDeviceId}}\n}" + }, + "url": { + "raw": "{{client_api_url}}/ddis/{{residentialDDIId}}", + "host": [ + "{{client_api_url}}" + ], + "path": [ + "ddis", + "{{residentialDDIId}}" + ] + } + }, + "response": [] + }, { "name": "Set Default Residential Client DDI", "event": [ @@ -3958,11 +4747,117 @@ } ], "request": { - "method": "PUT", + "method": "PUT", + "header": [ + { + "key": "Authorization", + "value": "{{brand_api_auth}}" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{{residentialData}}" + }, + "url": { + "raw": "{{brand_api_url}}/companies/{{residentialId}}", + "host": [ + "{{brand_api_url}}" + ], + "path": [ + "companies", + "{{residentialId}}" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "0030 - Retail Data", + "item": [ + { + "name": "Create BBS Retail Client", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var jsonData = JSON.parse(responseBody)", + "", + "tests[\"Response body is JSON\"] = jsonData !== undefined;", + "", + "tests[\"Response body has token id\"] = jsonData.id !== undefined;", + "", + "postman.setGlobalVariable(\"retailId\", jsonData.id);", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "{{brand_api_auth}}" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"type\": \"retail\",\n \"name\": \"BBS - Retail for Black Box SIP tests\",\n \"nif\": \"09876543210ART\",\n \"externalMaxCalls\": 2,\n \"postalAddress\": \"Retail address\",\n \"postalCode\": \"48902\",\n \"town\": \"Retail town\",\n \"province\": \"Retail province\",\n \"countryName\": \"Retail country\",\n \"defaultTimezone\": 1,\n \"ipfilter\": false,\n \"transformationRuleSet\": 70,\n \"brand\": {{brandId}},\n \"country\": 70,\n \"currency\": 1 \n}" + }, + "url": { + "raw": "{{brand_api_url}}/companies", + "host": [ + "{{brand_api_url}}" + ], + "path": [ + "companies" + ] + } + }, + "response": [] + }, + { + "name": "Create BBS Retail Admin", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var jsonData = JSON.parse(responseBody)", + "", + "tests[\"Response body is JSON\"] = jsonData !== undefined;", + "", + "tests[\"Response body has token id\"] = jsonData.id !== undefined;", + "", + "postman.setGlobalVariable(\"brandAdminId\", jsonData.id);", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { "key": "Content-Type", @@ -3971,34 +4866,26 @@ ], "body": { "mode": "raw", - "raw": "{{residentialData}}" + "raw": "{\n \"username\": \"retailadmin\",\n \"pass\": \"unusedp4ssw0rd\",\n \"email\": \"retailadmin@bbs.com\",\n \"active\": 1,\n \"restricted\": 0,\n \"brand\": {{brandId}},\n \"company\": {{retailId}},\n \"timezone\": 145\n}" }, "url": { - "raw": "{{brand_api_url}}/companies/{{residentialId}}", + "raw": "{{brand_api_url}}/administrators", "host": [ "{{brand_api_url}}" ], "path": [ - "companies", - "{{residentialId}}" + "administrators" ] } }, "response": [] - } - ] - }, - { - "name": "0030 - Retail Data", - "item": [ + }, { - "name": "Create BBS Retail Client", + "name": "Get Retail Authorization Token", "event": [ { "listen": "test", "script": { - "id": "d609b235-753d-4a7f-a60e-6b4acd64bc3b", - "type": "text/javascript", "exec": [ "tests[\"Status code is 201\"] = responseCode.code === 201;", "", @@ -4006,37 +4893,47 @@ "", "tests[\"Response body is JSON\"] = jsonData !== undefined;", "", - "tests[\"Response body has token id\"] = jsonData.id !== undefined;", + "tests[\"Response body has token field\"] = jsonData.token !== undefined;", "", - "postman.setGlobalVariable(\"retailId\", jsonData.id);", + "postman.setGlobalVariable(\"retail_api_auth\", 'Bearer ' + jsonData.token);", + "postman.setGlobalVariable(\"retail_api_token\", jsonData.token);", "" - ] + ], + "type": "text/javascript" } } ], "request": { "method": "POST", "header": [ - { - "key": "Authorization", - "value": "{{api_auth}}" - }, { "key": "Content-Type", - "value": "application/json" + "value": "application/x-www-form-urlencoded" } ], "body": { - "mode": "raw", - "raw": "{\n \"type\": \"retail\",\n \"name\": \"BBS - Retail for Black Box SIP tests\",\n \"nif\": \"09876543210ART\",\n \"externalMaxCalls\": 2,\n \"postalAddress\": \"Retail address\",\n \"postalCode\": \"48902\",\n \"town\": \"Retail town\",\n \"province\": \"Retail province\",\n \"countryName\": \"Retail country\",\n \"defaultTimezone\": 1,\n \"ipfilter\": false,\n \"transformationRuleSet\": 70,\n \"brand\": {{brandId}}\n}" + "mode": "formdata", + "formdata": [ + { + "key": "token", + "value": "{{brand_api_token}}", + "type": "text" + }, + { + "key": "username", + "value": "retailadmin", + "type": "text" + } + ] }, "url": { - "raw": "{{brand_api_url}}/companies", + "raw": "{{client_api_url}}/token/exchange", "host": [ - "{{brand_api_url}}" + "{{client_api_url}}" ], "path": [ - "companies" + "token", + "exchange" ] } }, @@ -4059,7 +4956,6 @@ "", "" ], - "id": "9d423fc8-954b-4358-be3d-a78ca5ddba30", "type": "text/javascript" } } @@ -4069,7 +4965,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { "key": "Content-Type", @@ -4098,8 +4994,6 @@ { "listen": "test", "script": { - "id": "a38bddd8-1fd6-40e0-ab47-67a4e194a78c", - "type": "text/javascript", "exec": [ "tests[\"Status code is 200\"] = responseCode.code === 200;", "", @@ -4109,7 +5003,8 @@ "", "postman.setGlobalVariable(\"retailData\", responseBody);", "" - ] + ], + "type": "text/javascript" } } ], @@ -4118,17 +5013,13 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { "key": "Accept", "value": "application/json" } ], - "body": { - "mode": "raw", - "raw": "{\n \"type\": \"vpbx\",\n \"name\": \"BBS - Company for Black Box SIP tests\",\n \"domainUsers\": \"bbs.ivozprovider.local\",\n \"nif\": \"09876543210ART\",\n \"externalMaxCalls\": 2,\n \"postalAddress\": \"Company address\",\n \"postalCode\": \"48902\",\n \"town\": \"Company town\",\n \"province\": \"Company province\",\n \"countryName\": \"Company country\",\n \"defaultTimezone\": 1,\n \"brand\": {{brandId}}\n}" - }, "url": { "raw": "{{brand_api_url}}/companies/{{retailId}}", "host": [ @@ -4148,8 +5039,6 @@ { "listen": "test", "script": { - "id": "a543d4c6-5d7c-4e95-bd72-596ea3a4e915", - "type": "text/javascript", "exec": [ "tests[\"Status code is 201\"] = responseCode.code === 201;", "", @@ -4162,7 +5051,8 @@ "postman.setGlobalVariable(\"retailAccountId\", jsonData.id);", "", "" - ] + ], + "type": "text/javascript" } } ], @@ -4171,7 +5061,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { "key": "Content-Type", @@ -4183,9 +5073,9 @@ "raw": "{\n \"name\": \"999666001\",\n \"transport\": \"udp\",\n \"password\": \"r3t41lP4sSW0rd+\",\n \"directConnectivity\": \"no\",\n \"brand\": {{brandId}},\n \"company\": {{retailId}}\n}" }, "url": { - "raw": "{{client_api_url}}/retail_accounts", + "raw": "{{brand_api_url}}/retail_accounts", "host": [ - "{{client_api_url}}" + "{{brand_api_url}}" ], "path": [ "retail_accounts" @@ -4200,8 +5090,6 @@ { "listen": "test", "script": { - "id": "ed864ccc-3c38-4ba9-ada0-44d39dbde1d9", - "type": "text/javascript", "exec": [ "tests[\"Status code is 201\"] = responseCode.code === 201;", "", @@ -4213,7 +5101,8 @@ "", "postman.setGlobalVariable(\"retailDDIId\", jsonData.id);", "" - ] + ], + "type": "text/javascript" } } ], @@ -4222,7 +5111,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { "key": "Content-Type", @@ -4234,9 +5123,9 @@ "raw": "{\n \"ddi\": \"999666001\",\n \"routeType\": \"retail\",\n \"company\": {{retailId}},\n \"brand\": {{brandId}},\n \"retailAccount\": {{retailAccountId}},\n \"ddiProvider\": {{ddiProviderId}},\n \"country\": 70\n}" }, "url": { - "raw": "{{client_api_url}}/ddis", + "raw": "{{brand_api_url}}/ddis", "host": [ - "{{client_api_url}}" + "{{brand_api_url}}" ], "path": [ "ddis" @@ -4245,14 +5134,71 @@ }, "response": [] }, + { + "name": "Route Retail DDI to Account", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody)", + "", + "tests[\"Response body is JSON\"] = jsonData !== undefined;", + "", + "tests[\"Response body has token id\"] = jsonData.id !== undefined;", + "", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Authorization", + "value": "{{retail_api_auth}}" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"routeType\": \"retail\",\n \"retailAccount\": {{retailAccountId}}\n}" + }, + "url": { + "raw": "{{client_api_url}}/ddis/{{retailDDIId}}", + "host": [ + "{{client_api_url}}" + ], + "path": [ + "ddis", + "{{retailDDIId}}" + ] + } + }, + "response": [] + }, { "name": "Set Default Retail Client DDI", "event": [ { "listen": "prerequest", "script": { - "id": "b3580b31-a5af-40be-8f07-98efa1d12fd9", - "type": "text/javascript", "exec": [ "var retailData = JSON.parse(postman.getGlobalVariable(\"retailData\"));", "", @@ -4261,19 +5207,19 @@ "postman.setGlobalVariable(\"retailData\", JSON.stringify(retailData));", "", "" - ] + ], + "type": "text/javascript" } }, { "listen": "test", "script": { - "id": "d0300aee-43ee-4594-8c8b-fbf06c19c1f7", - "type": "text/javascript", "exec": [ "tests[\"Status code is 200\"] = responseCode.code === 200;", "", "" - ] + ], + "type": "text/javascript" } } ], @@ -4282,7 +5228,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{brand_api_auth}}" }, { "key": "Content-Type", @@ -4311,21 +5257,19 @@ { "listen": "prerequest", "script": { + "type": "text/javascript", "exec": [ "" - ], - "id": "da1ec893-531a-468b-9014-41e176fad847", - "type": "text/javascript" + ] } }, { "listen": "test", "script": { + "type": "text/javascript", "exec": [ "" - ], - "id": "f8b5d42e-ebff-4f29-88ca-20da0b115d78", - "type": "text/javascript" + ] } } ] @@ -4360,7 +5304,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -4413,7 +5357,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -4463,7 +5407,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -4515,7 +5459,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -4564,7 +5508,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -4612,7 +5556,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -4667,7 +5611,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -4717,7 +5661,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -4767,7 +5711,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -4817,7 +5761,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -4873,7 +5817,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -4924,7 +5868,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -4979,7 +5923,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -5029,7 +5973,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -5078,7 +6022,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -5087,7 +6031,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"huntGroup\": {{huntGroupRingAllId}},\n \"user\": {{bobUserId}}\n}" + "raw": "{\n \"huntGroup\": {{huntGroupRingAllId}},\n \"routeType\": \"user\",\n \"user\": {{bobUserId}}\n}" }, "url": { "raw": "{{client_api_url}}/hunt_groups_rel_users", @@ -5127,7 +6071,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -5136,7 +6080,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"huntGroup\": {{huntGroupRingAllId}},\n \"user\": {{charlieUserId}}\n}" + "raw": "{\n \"huntGroup\": {{huntGroupRingAllId}},\n \"routeType\": \"user\",\n \"user\": {{charlieUserId}}\n}" }, "url": { "raw": "{{client_api_url}}/hunt_groups_rel_users", @@ -5176,7 +6120,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -5185,7 +6129,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"huntGroup\": {{huntGroupRingAllId}},\n \"user\": {{daveUserId}}\n}" + "raw": "{\n \"huntGroup\": {{huntGroupRingAllId}},\n \"routeType\": \"user\", \n \"user\": {{daveUserId}}\n}" }, "url": { "raw": "{{client_api_url}}/hunt_groups_rel_users", @@ -5226,7 +6170,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -5276,7 +6220,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -5325,7 +6269,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -5334,7 +6278,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"timeoutTime\": 3,\n \"priority\": 1,\n \"huntGroup\": {{huntGroupRRId}},\n \"user\": {{bobUserId}}\n}" + "raw": "{\n \"timeoutTime\": 3,\n \"priority\": 1,\n \"huntGroup\": {{huntGroupRRId}},\n \"routeType\": \"user\", \n \"user\": {{bobUserId}}\n}" }, "url": { "raw": "{{client_api_url}}/hunt_groups_rel_users", @@ -5374,7 +6318,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -5383,7 +6327,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"timeoutTime\": 3,\n \"priority\": 2,\n \"huntGroup\": {{huntGroupRRId}},\n \"user\": {{charlieUserId}}\n}" + "raw": "{\n \"timeoutTime\": 3,\n \"priority\": 2,\n \"huntGroup\": {{huntGroupRRId}},\n \"routeType\": \"user\", \n \"user\": {{charlieUserId}}\n}" }, "url": { "raw": "{{client_api_url}}/hunt_groups_rel_users", @@ -5423,7 +6367,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -5432,7 +6376,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"timeoutTime\": 3,\n \"priority\": 3,\n \"huntGroup\": {{huntGroupRRId}},\n \"user\": {{daveUserId}}\n}" + "raw": "{\n \"timeoutTime\": 3,\n \"priority\": 3,\n \"huntGroup\": {{huntGroupRRId}},\n \"routeType\": \"user\", \n \"user\": {{daveUserId}}\n}" }, "url": { "raw": "{{client_api_url}}/hunt_groups_rel_users", @@ -5469,7 +6413,6 @@ "postman.setGlobalVariable(\"conditionalRouteId\", jsonData.id);", "" ], - "id": "dba5e667-324c-4798-89ad-b01622fad92e", "type": "text/javascript" } } @@ -5479,7 +6422,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -5522,7 +6465,6 @@ "", "" ], - "id": "002d565c-8df2-4fb4-b6e6-b358df218807", "type": "text/javascript" } } @@ -5532,7 +6474,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -5573,7 +6515,6 @@ "postman.setGlobalVariable(\"conditionalRouteConditionId\", jsonData.id);", "" ], - "id": "54e06dcd-6452-4c7d-a2ac-744f255cdd41", "type": "text/javascript" } } @@ -5583,7 +6524,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -5623,7 +6564,6 @@ "tests[\"Response body has token id\"] = jsonData.id !== undefined;", "" ], - "id": "949b9034-923d-41ce-ad79-c315cb30d3aa", "type": "text/javascript" } } @@ -5633,7 +6573,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -5662,21 +6602,19 @@ { "listen": "prerequest", "script": { + "type": "text/javascript", "exec": [ "" - ], - "id": "dee8a1ff-7b04-4f9e-a6ad-5f1d26af3127", - "type": "text/javascript" + ] } }, { "listen": "test", "script": { + "type": "text/javascript", "exec": [ "" - ], - "id": "3b2545c1-c583-4d8a-a6b1-afa8968ac642", - "type": "text/javascript" + ] } } ] @@ -5710,7 +6648,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -5760,7 +6698,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -5810,7 +6748,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -5860,7 +6798,7 @@ "header": [ { "key": "Authorization", - "value": "{{api_auth}}" + "value": "{{client_api_auth}}" }, { "key": "Content-Type", @@ -5883,6 +6821,156 @@ "description": "POST" }, "response": [] + }, + { + "name": "Call Forward Friend Unregisted", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var jsonData = JSON.parse(responseBody)", + "", + "tests[\"Response body is JSON\"] = jsonData !== undefined;", + "", + "tests[\"Response body has token id\"] = jsonData.id !== undefined;", + "", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "{{client_api_auth}}" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"callTypeFilter\": \"internal\",\n \"callForwardType\": \"userNotRegistered\",\n \"targetType\": \"extension\",\n \"friend\": {{friendId}},\n \"extension\": {{charlieExtensionId}}\n}" + }, + "url": { + "raw": "{{client_api_url}}/call_forward_settings", + "host": [ + "{{client_api_url}}" + ], + "path": [ + "call_forward_settings" + ] + }, + "description": "POST" + }, + "response": [] + }, + { + "name": "Call Forward Friend Busy", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var jsonData = JSON.parse(responseBody)", + "", + "tests[\"Response body is JSON\"] = jsonData !== undefined;", + "", + "tests[\"Response body has token id\"] = jsonData.id !== undefined;", + "", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "{{client_api_auth}}" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"callTypeFilter\": \"internal\",\n \"callForwardType\": \"busy\",\n \"targetType\": \"extension\",\n \"friend\": {{friendId}},\n \"extension\": {{daveExtensionId}}\n}" + }, + "url": { + "raw": "{{client_api_url}}/call_forward_settings", + "host": [ + "{{client_api_url}}" + ], + "path": [ + "call_forward_settings" + ] + }, + "description": "POST" + }, + "response": [] + }, + { + "name": "Call Forward Friend NoAnswer", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var jsonData = JSON.parse(responseBody)", + "", + "tests[\"Response body is JSON\"] = jsonData !== undefined;", + "", + "tests[\"Response body has token id\"] = jsonData.id !== undefined;", + "", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "{{client_api_auth}}" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"callTypeFilter\": \"internal\",\n \"callForwardType\": \"noAnswer\",\n \"targetType\": \"extension\",\n \"friend\": {{friendId}},\n \"extension\": {{eveExtensionId}}\n}" + }, + "url": { + "raw": "{{client_api_url}}/call_forward_settings", + "host": [ + "{{client_api_url}}" + ], + "path": [ + "call_forward_settings" + ] + }, + "description": "POST" + }, + "response": [] } ] } @@ -5891,21 +6979,19 @@ { "listen": "prerequest", "script": { + "type": "text/javascript", "exec": [ "" - ], - "id": "d0aa020a-fada-45a0-a6b6-ef98907ff7cf", - "type": "text/javascript" + ] } }, { "listen": "test", "script": { + "type": "text/javascript", "exec": [ "" - ], - "id": "003779a0-3e8c-4576-af85-5c167e825de7", - "type": "text/javascript" + ] } } ] From dd79d16e4b2fb70d2ce9e93899637a5a87b0c6fd Mon Sep 17 00:00:00 2001 From: Carlos Cruz Date: Mon, 27 Jun 2022 18:39:20 +0200 Subject: [PATCH 10/44] kamtrunks: avoid gw failover on bounced calls --- kamailio/trunks/config/kamailio.cfg | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kamailio/trunks/config/kamailio.cfg b/kamailio/trunks/config/kamailio.cfg index 30d18290be9..9c4b3b81a3b 100644 --- a/kamailio/trunks/config/kamailio.cfg +++ b/kamailio/trunks/config/kamailio.cfg @@ -1973,6 +1973,8 @@ onreply_route[MANAGE_REPLY] { # Failure route for initial transactions to GW failure_route[MANAGE_FAILURE_GW] { + if ($dlg_var(bounced) == '1') exit; # Avoid carrier failover in bounced call + if(!t_check_status("(401)|(407)")) { xwarn("[$dlg_var(cidhash)] MANAGE-FAILURE-GW: $rm FAILED: '$T_reply_code $T_reply_reason' to '$cs $rm' from '$fu' ($si:$sp) [$proto]\n"); } From 7d15a5cdbfac8d58b41b7b472a434f7678acbcce Mon Sep 17 00:00:00 2001 From: Kaian Date: Wed, 29 Jun 2022 13:52:49 +0200 Subject: [PATCH 11/44] web/admin: fix Company creation/deletion ACLs --- web/admin/application/configs/klear/CompaniesList.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/admin/application/configs/klear/CompaniesList.yaml b/web/admin/application/configs/klear/CompaniesList.yaml index 57a6af9eb22..0b602201dcd 100644 --- a/web/admin/application/configs/klear/CompaniesList.yaml +++ b/web/admin/application/configs/klear/CompaniesList.yaml @@ -92,9 +92,9 @@ production: options: title: _("Options") screens: - companiesNew_screen: $[${auth.acls.Companies.create} && ${auth.companyVPBX}] + companiesNew_screen: ${auth.acls.Companies.create} dialogs: - companiesDel_dialog: $[${auth.acls.Companies.delete} && ${auth.companyVPBX}] + companiesDel_dialog: ${auth.acls.Companies.delete} importCompanies_dialog: false csv: active: false From fa71a7c1595c0fcfef08fb56d7726b43b1d32725 Mon Sep 17 00:00:00 2001 From: Carlos Cruz Date: Wed, 29 Jun 2022 18:47:09 +0200 Subject: [PATCH 12/44] kamusers: antiflood, skip OPTIONS --- kamailio/users/config/kamailio.cfg | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/kamailio/users/config/kamailio.cfg b/kamailio/users/config/kamailio.cfg index 68c0ad1e4c9..00b52486777 100644 --- a/kamailio/users/config/kamailio.cfg +++ b/kamailio/users/config/kamailio.cfg @@ -458,6 +458,12 @@ modparam("timer", "declare_timer", "EXIT_WHEN_NO_CALLS=EXIT_WHEN_NO_CALLS,3000,s request_route { route(REQINIT); + if (is_method("OPTIONS")) { + force_rport(); + send_reply("200", "I'm here!"); + exit; + } + route(IS_FROM_INSIDE); route(CIDHASH); @@ -467,13 +473,6 @@ request_route { exit; } - if (is_method("OPTIONS")) { - force_rport(); - route(ANTIFLOOD); - send_reply("200", "I'm here!"); - exit; - } - xnotice("[$dlg_var(cidhash)] Request: $rm $ru from $fu ($cs $rm - $proto:$si:$sp) [$ci]\n"); route(NATDETECT); From 50993944c88781ccda8a80229f6065b5f54acfa3 Mon Sep 17 00:00:00 2001 From: Carlos Cruz Date: Wed, 29 Jun 2022 18:57:36 +0200 Subject: [PATCH 13/44] doc: antiflood, skip OPTIONS --- doc/sphinx/security_and_maintenance/security/antiflooding.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/doc/sphinx/security_and_maintenance/security/antiflooding.rst b/doc/sphinx/security_and_maintenance/security/antiflooding.rst index 9e70dd8c01e..d7b69dbe27a 100644 --- a/doc/sphinx/security_and_maintenance/security/antiflooding.rst +++ b/doc/sphinx/security_and_maintenance/security/antiflooding.rst @@ -36,8 +36,6 @@ Client side requests usually traverse 2 different phases: Antiflood will take into account: -- SIP OPTIONS - - Requests failing during step 0: - Requests not using SIP domain in KamUsers (except wholesale). From 8bda81209fd2f2a3480a2f95611364fb6740f5a5 Mon Sep 17 00:00:00 2001 From: Carlos Cruz Date: Mon, 27 Jun 2022 20:07:04 +0200 Subject: [PATCH 14/44] schema: remove authNeeded field in ResidentialDevices table --- ...alDevice.ResidentialDeviceAbstract.orm.yml | 8 ----- .../Version20220627180555.php | 34 +++++++++++++++++++ 2 files changed, 34 insertions(+), 8 deletions(-) create mode 100644 schema/DoctrineMigrations/Version20220627180555.php diff --git a/library/Ivoz/Provider/Infrastructure/Persistence/Doctrine/Mapping/ResidentialDevice.ResidentialDeviceAbstract.orm.yml b/library/Ivoz/Provider/Infrastructure/Persistence/Doctrine/Mapping/ResidentialDevice.ResidentialDeviceAbstract.orm.yml index 0d16a5cd1dc..0748e2f9f04 100644 --- a/library/Ivoz/Provider/Infrastructure/Persistence/Doctrine/Mapping/ResidentialDevice.ResidentialDeviceAbstract.orm.yml +++ b/library/Ivoz/Provider/Infrastructure/Persistence/Doctrine/Mapping/ResidentialDevice.ResidentialDeviceAbstract.orm.yml @@ -37,14 +37,6 @@ Ivoz\Provider\Domain\Model\ResidentialDevice\ResidentialDeviceAbstract: nullable: true options: unsigned: true - authNeeded: - type: string - nullable: false - length: null - options: - fixed: false - default: 'yes' - column: auth_needed password: type: string nullable: true diff --git a/schema/DoctrineMigrations/Version20220627180555.php b/schema/DoctrineMigrations/Version20220627180555.php new file mode 100644 index 00000000000..23bd306e317 --- /dev/null +++ b/schema/DoctrineMigrations/Version20220627180555.php @@ -0,0 +1,34 @@ +abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('ALTER TABLE ResidentialDevices DROP auth_needed'); + } + + /** + * @param Schema $schema + */ + public function down(Schema $schema) + { + // this down() migration is auto-generated, please modify it to your needs + $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('ALTER TABLE ResidentialDevices ADD auth_needed VARCHAR(255) DEFAULT \'yes\' NOT NULL COLLATE utf8_general_ci'); + } +} From f310162c5490854750f3d37324f21a481f564384 Mon Sep 17 00:00:00 2001 From: Carlos Cruz Date: Mon, 27 Jun 2022 20:08:01 +0200 Subject: [PATCH 15/44] core: regenerate entities with latest scheme changes --- .../ResidentialDeviceAbstract.php | 38 ------------------- .../ResidentialDeviceDtoAbstract.php | 27 ------------- .../ResidentialDeviceInterface.php | 7 ---- 3 files changed, 72 deletions(-) diff --git a/library/Ivoz/Provider/Domain/Model/ResidentialDevice/ResidentialDeviceAbstract.php b/library/Ivoz/Provider/Domain/Model/ResidentialDevice/ResidentialDeviceAbstract.php index 0ed75a0c982..d92763e74bb 100644 --- a/library/Ivoz/Provider/Domain/Model/ResidentialDevice/ResidentialDeviceAbstract.php +++ b/library/Ivoz/Provider/Domain/Model/ResidentialDevice/ResidentialDeviceAbstract.php @@ -39,12 +39,6 @@ abstract class ResidentialDeviceAbstract */ protected $port; - /** - * column: auth_needed - * @var string - */ - protected $authNeeded = 'yes'; - /** * @var string | null */ @@ -159,7 +153,6 @@ abstract class ResidentialDeviceAbstract protected function __construct( $name, $description, - $authNeeded, $disallow, $allow, $directMediaMethod, @@ -174,7 +167,6 @@ protected function __construct( ) { $this->setName($name); $this->setDescription($description); - $this->setAuthNeeded($authNeeded); $this->setDisallow($disallow); $this->setAllow($allow); $this->setDirectMediaMethod($directMediaMethod); @@ -259,7 +251,6 @@ public static function fromDto( $self = new static( $dto->getName(), $dto->getDescription(), - $dto->getAuthNeeded(), $dto->getDisallow(), $dto->getAllow(), $dto->getDirectMediaMethod(), @@ -309,7 +300,6 @@ public function updateFromDto( ->setTransport($dto->getTransport()) ->setIp($dto->getIp()) ->setPort($dto->getPort()) - ->setAuthNeeded($dto->getAuthNeeded()) ->setPassword($dto->getPassword()) ->setDisallow($dto->getDisallow()) ->setAllow($dto->getAllow()) @@ -348,7 +338,6 @@ public function toDto($depth = 0) ->setTransport(self::getTransport()) ->setIp(self::getIp()) ->setPort(self::getPort()) - ->setAuthNeeded(self::getAuthNeeded()) ->setPassword(self::getPassword()) ->setDisallow(self::getDisallow()) ->setAllow(self::getAllow()) @@ -381,7 +370,6 @@ protected function __toArray() 'transport' => self::getTransport(), 'ip' => self::getIp(), 'port' => self::getPort(), - 'auth_needed' => self::getAuthNeeded(), 'password' => self::getPassword(), 'disallow' => self::getDisallow(), 'allow' => self::getAllow(), @@ -550,32 +538,6 @@ public function getPort() return $this->port; } - /** - * Set authNeeded - * - * @param string $authNeeded - * - * @return static - */ - protected function setAuthNeeded($authNeeded) - { - Assertion::notNull($authNeeded, 'authNeeded value "%s" is null, but non null value was expected.'); - - $this->authNeeded = $authNeeded; - - return $this; - } - - /** - * Get authNeeded - * - * @return string - */ - public function getAuthNeeded(): string - { - return $this->authNeeded; - } - /** * Set password * diff --git a/library/Ivoz/Provider/Domain/Model/ResidentialDevice/ResidentialDeviceDtoAbstract.php b/library/Ivoz/Provider/Domain/Model/ResidentialDevice/ResidentialDeviceDtoAbstract.php index 0013373b061..6070c17bcc9 100644 --- a/library/Ivoz/Provider/Domain/Model/ResidentialDevice/ResidentialDeviceDtoAbstract.php +++ b/library/Ivoz/Provider/Domain/Model/ResidentialDevice/ResidentialDeviceDtoAbstract.php @@ -35,11 +35,6 @@ abstract class ResidentialDeviceDtoAbstract implements DataTransferObjectInterfa */ private $port; - /** - * @var string - */ - private $authNeeded = 'yes'; - /** * @var string */ @@ -178,7 +173,6 @@ public static function getPropertyMap(string $context = '', string $role = null) 'transport' => 'transport', 'ip' => 'ip', 'port' => 'port', - 'authNeeded' => 'authNeeded', 'password' => 'password', 'disallow' => 'disallow', 'allow' => 'allow', @@ -213,7 +207,6 @@ public function toArray($hideSensitiveData = false) 'transport' => $this->getTransport(), 'ip' => $this->getIp(), 'port' => $this->getPort(), - 'authNeeded' => $this->getAuthNeeded(), 'password' => $this->getPassword(), 'disallow' => $this->getDisallow(), 'allow' => $this->getAllow(), @@ -353,26 +346,6 @@ public function getPort() return $this->port; } - /** - * @param string $authNeeded - * - * @return static - */ - public function setAuthNeeded($authNeeded = null) - { - $this->authNeeded = $authNeeded; - - return $this; - } - - /** - * @return string | null - */ - public function getAuthNeeded() - { - return $this->authNeeded; - } - /** * @param string $password * diff --git a/library/Ivoz/Provider/Domain/Model/ResidentialDevice/ResidentialDeviceInterface.php b/library/Ivoz/Provider/Domain/Model/ResidentialDevice/ResidentialDeviceInterface.php index 541b93c652a..a8d446c9273 100644 --- a/library/Ivoz/Provider/Domain/Model/ResidentialDevice/ResidentialDeviceInterface.php +++ b/library/Ivoz/Provider/Domain/Model/ResidentialDevice/ResidentialDeviceInterface.php @@ -154,13 +154,6 @@ public function getIp(); */ public function getPort(); - /** - * Get authNeeded - * - * @return string - */ - public function getAuthNeeded(): string; - /** * Get password * From 19e3ca3ae55c6c6f06e3832efc0d200491e6a931 Mon Sep 17 00:00:00 2001 From: Carlos Cruz Date: Mon, 27 Jun 2022 20:09:44 +0200 Subject: [PATCH 16/44] web/admin: password can be null only in directConnectivity retail/residential --- .../configs/klear/BrandResidentialDevicesList.yaml | 1 - .../configs/klear/ResidentialDevicesList.yaml | 3 --- .../configs/klear/model/ResidentialDevices.yaml | 11 +---------- .../configs/klear/model/RetailAccounts.yaml | 2 +- 4 files changed, 2 insertions(+), 15 deletions(-) diff --git a/web/admin/application/configs/klear/BrandResidentialDevicesList.yaml b/web/admin/application/configs/klear/BrandResidentialDevicesList.yaml index 53dede64263..39797d45b31 100644 --- a/web/admin/application/configs/klear/BrandResidentialDevicesList.yaml +++ b/web/admin/application/configs/klear/BrandResidentialDevicesList.yaml @@ -22,7 +22,6 @@ production: fields: blacklist: &residentialDevices_blacklistLink transport: true - authNeeded: true password: true areaCode: true country: true diff --git a/web/admin/application/configs/klear/ResidentialDevicesList.yaml b/web/admin/application/configs/klear/ResidentialDevicesList.yaml index 44b2ce327d6..efea615a84e 100644 --- a/web/admin/application/configs/klear/ResidentialDevicesList.yaml +++ b/web/admin/application/configs/klear/ResidentialDevicesList.yaml @@ -28,7 +28,6 @@ production: fields: blacklist: &residentialDevices_blacklistLink transport: true - authNeeded: true password: true areaCode: true country: true @@ -92,7 +91,6 @@ production: directMediaMethod: true updateCallerid: true calleridUpdateHeader: true - authNeeded: true disallow: true status: true statusIcon: true @@ -180,7 +178,6 @@ production: directMediaMethod: true updateCallerid: true calleridUpdateHeader: true - authNeeded: true disallow: true statusIcon: true fixedPositions: diff --git a/web/admin/application/configs/klear/model/ResidentialDevices.yaml b/web/admin/application/configs/klear/model/ResidentialDevices.yaml index 3acbe035eac..01acc1854d2 100644 --- a/web/admin/application/configs/klear/model/ResidentialDevices.yaml +++ b/web/admin/application/configs/klear/model/ResidentialDevices.yaml @@ -77,20 +77,11 @@ production: required: true pattern: "^[0-9]+$" defaultValue: 5060 - authNeeded: - title: _('Auth needed') - type: select - defaultValue: 'no' - source: - data: inline - values: - 'yes': _('Yes') - 'no': _('No') password: title: _('Password') type: text pattern: "^(?=.*[A-Z].*[A-Z].*[A-Z])(?=.*[+*_-])(?=.*[0-9].*[0-9].*[0-9])(?=.*[a-z].*[a-z].*[a-z]).{10,}$" - required: true + trim: both info: type: box position: left diff --git a/web/admin/application/configs/klear/model/RetailAccounts.yaml b/web/admin/application/configs/klear/model/RetailAccounts.yaml index 94d86b2fe5f..ed9cec44ccb 100644 --- a/web/admin/application/configs/klear/model/RetailAccounts.yaml +++ b/web/admin/application/configs/klear/model/RetailAccounts.yaml @@ -85,7 +85,7 @@ production: title: _('Password') type: text pattern: "^(?=.*[A-Z].*[A-Z].*[A-Z])(?=.*[+*_-])(?=.*[0-9].*[0-9].*[0-9])(?=.*[a-z].*[a-z].*[a-z]).{10,}$" - required: true + trim: both info: type: box position: left From 485401811a591bb88c7eff0b43642bf1fff92837 Mon Sep 17 00:00:00 2001 From: Carlos Cruz Date: Mon, 27 Jun 2022 20:11:39 +0200 Subject: [PATCH 17/44] doc: optional SIP auth in direct retail/residential --- .../client/residential/residential_devices.rst | 3 ++- .../administration_portal/client/retail/retail_accounts.rst | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/sphinx/administration_portal/client/residential/residential_devices.rst b/doc/sphinx/administration_portal/client/residential/residential_devices.rst index 5869f991dae..f549db072b4 100644 --- a/doc/sphinx/administration_portal/client/residential/residential_devices.rst +++ b/doc/sphinx/administration_portal/client/residential/residential_devices.rst @@ -51,7 +51,8 @@ These are the configurable settings of *Residential devices*: Password When the *residential device* send requests, IvozProvider will authenticate it using - this password. Like remaining SIP entities in IvozProvider (except Wholesale) **using password IS MANDATORY**. + this password. **Using password IS A MUST in "Register" mode**. In "Direct" mode, + leaving it blank disables SIP authentication and enables IP source check. Direct connectivity If you choose 'Yes' here, you'll have to fill the protocol, address and diff --git a/doc/sphinx/administration_portal/client/retail/retail_accounts.rst b/doc/sphinx/administration_portal/client/retail/retail_accounts.rst index b37f0191c5e..fcaa761ec15 100644 --- a/doc/sphinx/administration_portal/client/retail/retail_accounts.rst +++ b/doc/sphinx/administration_portal/client/retail/retail_accounts.rst @@ -51,7 +51,8 @@ These are the configurable settings of *Retail accounts*: Password When the *retail account* send requests, IvozProvider will authenticate it using - this password. Like remaining SIP entities in IvozProvider (except Wholesale) **using password IS MANDATORY**. + this password. **Using password IS A MUST in "Register" mode**. In "Direct" mode, + leaving it blank disables SIP authentication and enables IP source check. Direct connectivity If you choose 'Yes' here, you'll have to fill the protocol, address and From e6fe26d31945db69a9f38cc4762bfb366df40fba Mon Sep 17 00:00:00 2001 From: Carlos Cruz Date: Tue, 28 Jun 2022 18:18:31 +0200 Subject: [PATCH 18/44] core: password can be null only in directConnectivity retail accounts and residential devices --- .../ResidentialDevice/ResidentialDevice.php | 26 +++++++++++++++---- .../Model/RetailAccount/RetailAccount.php | 26 +++++++++++++++---- 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/library/Ivoz/Provider/Domain/Model/ResidentialDevice/ResidentialDevice.php b/library/Ivoz/Provider/Domain/Model/ResidentialDevice/ResidentialDevice.php index 10166e6eeca..15d4813b616 100644 --- a/library/Ivoz/Provider/Domain/Model/ResidentialDevice/ResidentialDevice.php +++ b/library/Ivoz/Provider/Domain/Model/ResidentialDevice/ResidentialDevice.php @@ -49,6 +49,18 @@ protected function sanitizeValues() if ($this->isDirectConnectivity() && !$this->getTransport()) { throw new \DomainException('Invalid empty transport'); } + + if ($this->isDirectConnectivity() && !$this->getIp()) { + throw new \DomainException('Invalid empty IP'); + } + + if ($this->isDirectConnectivity() && !$this->getPort()) { + throw new \DomainException('Invalid empty port'); + } + + if (!$this->isDirectConnectivity() && !$this->getPassword()) { + throw new \DomainException('Password cannot be empty for residential devices with no direct connectivity'); + } } /** @@ -85,12 +97,16 @@ public function setIp($ip = null) public function setPassword($password = null) { $password = trim($password); - if (!empty($password)) { - Assertion::regex( - $password, - '/^(?=.*[A-Z].*[A-Z].*[A-Z])(?=.*[+*_-])(?=.*[0-9].*[0-9].*[0-9])(?=.*[a-z].*[a-z].*[a-z]).{10,}$/' - ); + + if (empty($password)) { + return parent::setPassword(null); } + + Assertion::regex( + $password, + '/^(?=.*[A-Z].*[A-Z].*[A-Z])(?=.*[+*_-])(?=.*[0-9].*[0-9].*[0-9])(?=.*[a-z].*[a-z].*[a-z]).{10,}$/' + ); + return parent::setPassword($password); } diff --git a/library/Ivoz/Provider/Domain/Model/RetailAccount/RetailAccount.php b/library/Ivoz/Provider/Domain/Model/RetailAccount/RetailAccount.php index ef09729c5e8..567a0082958 100644 --- a/library/Ivoz/Provider/Domain/Model/RetailAccount/RetailAccount.php +++ b/library/Ivoz/Provider/Domain/Model/RetailAccount/RetailAccount.php @@ -43,6 +43,18 @@ protected function sanitizeValues() if ($this->isDirectConnectivity() && !$this->getTransport()) { throw new \DomainException('Invalid empty transport'); } + + if ($this->isDirectConnectivity() && !$this->getIp()) { + throw new \DomainException('Invalid empty IP'); + } + + if ($this->isDirectConnectivity() && !$this->getPort()) { + throw new \DomainException('Invalid empty port'); + } + + if (!$this->isDirectConnectivity() && !$this->getPassword()) { + throw new \DomainException('Password cannot be empty for retail accounts with no direct connectivity'); + } } /** @@ -79,12 +91,16 @@ public function setIp($ip = null) public function setPassword($password = null) { $password = trim($password); - if (!empty($password)) { - Assertion::regex( - $password, - '/^(?=.*[A-Z].*[A-Z].*[A-Z])(?=.*[+*_-])(?=.*[0-9].*[0-9].*[0-9])(?=.*[a-z].*[a-z].*[a-z]).{10,}$/' - ); + + if (empty($password)) { + return parent::setPassword(null); } + + Assertion::regex( + $password, + '/^(?=.*[A-Z].*[A-Z].*[A-Z])(?=.*[+*_-])(?=.*[0-9].*[0-9].*[0-9])(?=.*[a-z].*[a-z].*[a-z]).{10,}$/' + ); + return parent::setPassword($password); } From 6f8ce4d9b5a4898ac9b002b65d422134c955174e Mon Sep 17 00:00:00 2001 From: Carlos Cruz Date: Tue, 28 Jun 2022 18:19:58 +0200 Subject: [PATCH 19/44] web/rest: removed company attribute from client API --- .../Domain/Model/ResidentialDevice/ResidentialDeviceDto.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/library/Ivoz/Provider/Domain/Model/ResidentialDevice/ResidentialDeviceDto.php b/library/Ivoz/Provider/Domain/Model/ResidentialDevice/ResidentialDeviceDto.php index 52a2c32d324..64c06dc5547 100644 --- a/library/Ivoz/Provider/Domain/Model/ResidentialDevice/ResidentialDeviceDto.php +++ b/library/Ivoz/Provider/Domain/Model/ResidentialDevice/ResidentialDeviceDto.php @@ -83,8 +83,7 @@ public static function getPropertyMap(string $context = '', string $role = null) $response = [ 'id' => 'id', 'name' => 'name', - 'transport' => 'transport', - 'authNeeded' => 'authNeeded' + 'transport' => 'transport' ]; } else { $response = parent::getPropertyMap(...func_get_args()); @@ -132,7 +131,6 @@ private static function filterFieldsForBrandAdmin(array $response): array 'transport', 'ip', 'port', - 'authNeeded', 'password', 'allow', 'fromDomain', From d65c8b17eba11ba080dbfbf782fc6257afba1221 Mon Sep 17 00:00:00 2001 From: Carlos Cruz Date: Tue, 28 Jun 2022 18:26:48 +0200 Subject: [PATCH 20/44] kamusers: password can be null in directConnectivity retail accounts and residential devices --- kamailio/users/config/kamailio.cfg | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/kamailio/users/config/kamailio.cfg b/kamailio/users/config/kamailio.cfg index 00b52486777..1f877de3d71 100644 --- a/kamailio/users/config/kamailio.cfg +++ b/kamailio/users/config/kamailio.cfg @@ -1659,15 +1659,15 @@ route[AUTH] { if (src_ip == myself || $var(is_from_inside)) return; if ($avp(wholesaleId) != $null) return; # No AUTH for wholesale clients - # Handle passwordless friends - if ($avp(endpointType) == "Friends" && $avp(password) == $null) { - $xavp(friend) = $null; - sql_xquery("cb", "SELECT ip FROM Friends WHERE id='$avp(endpointId)'", "friend"); - if ($xavp(friend=>ip) == $si) { - xinfo("[$dlg_var(cidhash)] AUTH: $avp(endpointType)#$avp(endpointId) talking from $xavp(friend=>ip), skip auth"); + # Handle passwordless friends / retail accounts / residential devices + if (($avp(endpointType) == "Friends" || $avp(endpointType) == "RetailAccounts" || $avp(endpointType) == "ResidentialDevices") && $avp(password) == $null) { + $xavp(endpoint) = $null; + sql_xquery("cb", "SELECT ip FROM $avp(endpointType) WHERE id='$avp(endpointId)'", "endpoint"); + if ($xavp(endpoint=>ip) == $si) { + xinfo("[$dlg_var(cidhash)] AUTH: $avp(endpointType)#$avp(endpointId) talking from $xavp(endpoint=>ip), skip auth"); return; } else { - xwarn("[$dlg_var(cidhash)] AUTH: $avp(endpointType)#$avp(endpointId) talking from $si instead of $xavp(friend=>ip), forbidden"); + xwarn("[$dlg_var(cidhash)] AUTH: $avp(endpointType)#$avp(endpointId) talking from $si instead of $xavp(endpoint=>ip), forbidden"); route(ANTIFLOOD); send_reply("403", "Forbidden [FS]"); exit; From 0a0d8ba6b4b54cc263ea637815ff744d339ef0bf Mon Sep 17 00:00:00 2001 From: Carlos Cruz Date: Tue, 28 Jun 2022 18:40:19 +0200 Subject: [PATCH 21/44] tests: update ORM fixtures --- library/DataFixtures/ORM/ProviderResidentialDevice.php | 1 - 1 file changed, 1 deletion(-) diff --git a/library/DataFixtures/ORM/ProviderResidentialDevice.php b/library/DataFixtures/ORM/ProviderResidentialDevice.php index 8ca947c1606..7588a15b778 100644 --- a/library/DataFixtures/ORM/ProviderResidentialDevice.php +++ b/library/DataFixtures/ORM/ProviderResidentialDevice.php @@ -27,7 +27,6 @@ public function load(ObjectManager $manager) (function () use ($fixture) { $this->setName('residentialDevice'); $this->setTransport('udp'); - $this->setAuthNeeded('yes'); $this->setPassword('+rA778LidL'); $this->setDisallow('all'); $this->setAllow('alaw'); From 0978f3960a351c66fb0280ef6defa26ff741ea35 Mon Sep 17 00:00:00 2001 From: Carlos Cruz Date: Tue, 28 Jun 2022 18:47:30 +0200 Subject: [PATCH 22/44] tests: update tests --- .../ORM/ProviderResidentialDevice.php | 2 ++ .../DataFixtures/ORM/ProviderRetailAccount.php | 2 ++ .../ResidentialDevice/ResidentialDeviceSpec.php | 5 +++-- .../ResidentialDeviceLifeCycleTest.php | 3 ++- .../RetailAccount/RetailAccountLifeCycleTest.php | 2 ++ .../getResidentialDevice.feature | 6 ++---- .../postResidentialDevice.feature | 15 ++++++--------- .../putResidentialDevice.feature | 10 ++++------ .../retailAccount/getRetailAccount.feature | 4 ++-- .../retailAccount/postRetailAccount.feature | 12 ++++++------ .../retailAccount/putRetailAccount.feature | 4 ++-- 11 files changed, 33 insertions(+), 32 deletions(-) diff --git a/library/DataFixtures/ORM/ProviderResidentialDevice.php b/library/DataFixtures/ORM/ProviderResidentialDevice.php index 7588a15b778..cb1b15bed5b 100644 --- a/library/DataFixtures/ORM/ProviderResidentialDevice.php +++ b/library/DataFixtures/ORM/ProviderResidentialDevice.php @@ -27,6 +27,8 @@ public function load(ObjectManager $manager) (function () use ($fixture) { $this->setName('residentialDevice'); $this->setTransport('udp'); + $this->setIp('1.2.3.4'); + $this->setPort(1024); $this->setPassword('+rA778LidL'); $this->setDisallow('all'); $this->setAllow('alaw'); diff --git a/library/DataFixtures/ORM/ProviderRetailAccount.php b/library/DataFixtures/ORM/ProviderRetailAccount.php index 185058b077a..73d1dcbfe48 100644 --- a/library/DataFixtures/ORM/ProviderRetailAccount.php +++ b/library/DataFixtures/ORM/ProviderRetailAccount.php @@ -27,6 +27,8 @@ public function load(ObjectManager $manager) (function () use ($fixture) { $this->setName('testRetailAccount'); $this->setTransport('udp'); + $this->setIp('1.2.3.4'); + $this->setPort(1024); $this->setDirectConnectivity('no'); $this->setPassword('9rv6G3TVc-'); $this->setBrand( diff --git a/library/spec/Ivoz/Provider/Domain/Model/ResidentialDevice/ResidentialDeviceSpec.php b/library/spec/Ivoz/Provider/Domain/Model/ResidentialDevice/ResidentialDeviceSpec.php index 4266c27f096..c9a630749df 100644 --- a/library/spec/Ivoz/Provider/Domain/Model/ResidentialDevice/ResidentialDeviceSpec.php +++ b/library/spec/Ivoz/Provider/Domain/Model/ResidentialDevice/ResidentialDeviceSpec.php @@ -36,13 +36,14 @@ function let( $dto->setName('Name') ->setDescription('Desc') ->setTransport('udp') - ->setAuthNeeded('yes') ->setDisallow('none') ->setAllow('all') ->setDirectMediaMethod('invite') ->setCalleridUpdateHeader('pai') ->setUpdateCallerid('yes') - ->setDirectConnectivity('yes'); + ->setDirectConnectivity('yes') + ->setIp('1.2.3.4') + ->setPort('1234'); $company ->getId() diff --git a/schema/tests/Provider/ResidentialDevice/ResidentialDeviceLifeCycleTest.php b/schema/tests/Provider/ResidentialDevice/ResidentialDeviceLifeCycleTest.php index b01f490b457..d2c2bd0653e 100644 --- a/schema/tests/Provider/ResidentialDevice/ResidentialDeviceLifeCycleTest.php +++ b/schema/tests/Provider/ResidentialDevice/ResidentialDeviceLifeCycleTest.php @@ -22,7 +22,8 @@ protected function createDto() $residentialDeviceDto ->setName('testResidentialDevice') ->setTransport('udp') - ->setAuthNeeded('yes') + ->setIp('1.2.3.4') + ->setPort(1024) ->setDisallow('all') ->setAllow('alaw') ->setDirectMediaMethod('invite') diff --git a/schema/tests/Provider/RetailAccount/RetailAccountLifeCycleTest.php b/schema/tests/Provider/RetailAccount/RetailAccountLifeCycleTest.php index 5cf515ba486..23783ee826c 100644 --- a/schema/tests/Provider/RetailAccount/RetailAccountLifeCycleTest.php +++ b/schema/tests/Provider/RetailAccount/RetailAccountLifeCycleTest.php @@ -22,6 +22,8 @@ protected function createDto() $retailAccountDto ->setName('someRetailAccount') ->setTransport('udp') + ->setIp('1.2.3.4') + ->setPort(1024) ->setDirectConnectivity('yes') ->setBrandId(1) ->setCompanyId(1); diff --git a/web/rest/brand/features/provider/residentialDevice/getResidentialDevice.feature b/web/rest/brand/features/provider/residentialDevice/getResidentialDevice.feature index e9c7b8f83fb..460984173cc 100644 --- a/web/rest/brand/features/provider/residentialDevice/getResidentialDevice.feature +++ b/web/rest/brand/features/provider/residentialDevice/getResidentialDevice.feature @@ -17,7 +17,6 @@ Feature: Retrieve residential devices { "name": "residentialDevice", "transport": "udp", - "authNeeded": "yes", "id": 1 } ] @@ -36,9 +35,8 @@ Feature: Retrieve residential devices "name": "residentialDevice", "description": "", "transport": "udp", - "ip": null, - "port": null, - "authNeeded": "yes", + "ip": "1.2.3.4", + "port": 1024, "password": "+rA778LidL", "allow": "alaw", "fromDomain": null, diff --git a/web/rest/brand/features/provider/residentialDevice/postResidentialDevice.feature b/web/rest/brand/features/provider/residentialDevice/postResidentialDevice.feature index 918a8b149c9..b91896fdc72 100644 --- a/web/rest/brand/features/provider/residentialDevice/postResidentialDevice.feature +++ b/web/rest/brand/features/provider/residentialDevice/postResidentialDevice.feature @@ -14,9 +14,8 @@ Feature: Create residential devices "name": "testResidentialDevice", "description": "", "transport": "udp", - "ip": null, - "port": null, - "authNeeded": "yes", + "ip": "1.2.3.4", + "port": 1024, "password": "qq6G+As2M7", "allow": "alaw", "fromDomain": null, @@ -39,9 +38,8 @@ Feature: Create residential devices "name": "testResidentialDevice", "description": "", "transport": "udp", - "ip": null, - "port": null, - "authNeeded": "yes", + "ip": "1.2.3.4", + "port": 1024, "password": "qq6G+As2M7", "allow": "alaw", "fromDomain": null, @@ -70,9 +68,8 @@ Feature: Create residential devices "name": "testResidentialDevice", "description": "", "transport": "udp", - "ip": null, - "port": null, - "authNeeded": "yes", + "ip": "1.2.3.4", + "port": 1024, "password": "qq6G+As2M7", "allow": "alaw", "fromDomain": null, diff --git a/web/rest/brand/features/provider/residentialDevice/putResidentialDevice.feature b/web/rest/brand/features/provider/residentialDevice/putResidentialDevice.feature index 3bd62dc6997..a587116e706 100644 --- a/web/rest/brand/features/provider/residentialDevice/putResidentialDevice.feature +++ b/web/rest/brand/features/provider/residentialDevice/putResidentialDevice.feature @@ -14,9 +14,8 @@ Feature: Update residential device "name": "updatedResidentialDevice", "description": "", "transport": "udp", - "ip": null, - "port": null, - "authNeeded": "yes", + "ip": "1.2.3.4", + "port": 1024, "password": "+rA778Li2dL", "allow": "alaw", "fromDomain": null, @@ -40,9 +39,8 @@ Feature: Update residential device "name": "updatedResidentialDevice", "description": "", "transport": "udp", - "ip": null, - "port": null, - "authNeeded": "yes", + "ip": "1.2.3.4", + "port": 1024, "password": "+rA778Li2dL", "allow": "alaw", "fromDomain": null, diff --git a/web/rest/brand/features/provider/retailAccount/getRetailAccount.feature b/web/rest/brand/features/provider/retailAccount/getRetailAccount.feature index 3770a51908c..a0d994e6de9 100644 --- a/web/rest/brand/features/provider/retailAccount/getRetailAccount.feature +++ b/web/rest/brand/features/provider/retailAccount/getRetailAccount.feature @@ -35,8 +35,8 @@ Feature: Retrieve retail accounts "name": "testRetailAccount", "description": "", "transport": "udp", - "ip": null, - "port": null, + "ip": "1.2.3.4", + "port": 1024, "password": "9rv6G3TVc-", "fromDomain": null, "directConnectivity": "no", diff --git a/web/rest/brand/features/provider/retailAccount/postRetailAccount.feature b/web/rest/brand/features/provider/retailAccount/postRetailAccount.feature index 32e64c57532..53e867f19f3 100644 --- a/web/rest/brand/features/provider/retailAccount/postRetailAccount.feature +++ b/web/rest/brand/features/provider/retailAccount/postRetailAccount.feature @@ -14,8 +14,8 @@ Feature: Create retail accounts "name": "postRetailAccount", "description": "", "transport": "udp", - "ip": null, - "port": null, + "ip": "1.2.3.4", + "port": 1024, "password": "3N-8g6zuXP", "fromDomain": null, "directConnectivity": "yes", @@ -35,8 +35,8 @@ Feature: Create retail accounts "name": "postRetailAccount", "description": "", "transport": "udp", - "ip": null, - "port": null, + "ip": "1.2.3.4", + "port": 1024, "password": "3N-8g6zuXP", "fromDomain": null, "directConnectivity": "yes", @@ -62,8 +62,8 @@ Feature: Create retail accounts "name": "postRetailAccount", "description": "", "transport": "udp", - "ip": null, - "port": null, + "ip": "1.2.3.4", + "port": 1024, "password": "3N-8g6zuXP", "fromDomain": null, "directConnectivity": "yes", diff --git a/web/rest/brand/features/provider/retailAccount/putRetailAccount.feature b/web/rest/brand/features/provider/retailAccount/putRetailAccount.feature index 81cf9c2886f..54fac33fbfb 100644 --- a/web/rest/brand/features/provider/retailAccount/putRetailAccount.feature +++ b/web/rest/brand/features/provider/retailAccount/putRetailAccount.feature @@ -18,7 +18,7 @@ Feature: Update ddi "port": null, "password": "8rv6G3TVc-", "fromDomain": null, - "directConnectivity": "yes", + "directConnectivity": "no", "ddiIn": "yes", "t38Passthrough": "no", "company": 1, @@ -39,7 +39,7 @@ Feature: Update ddi "port": null, "password": "8rv6G3TVc-", "fromDomain": null, - "directConnectivity": "yes", + "directConnectivity": "no", "ddiIn": "yes", "t38Passthrough": "no", "id": 1, From 034c4f6c5487dfba7e7bf39d8ab037aeeb021a62 Mon Sep 17 00:00:00 2001 From: Carlos Cruz Date: Fri, 1 Jul 2022 11:56:15 +0200 Subject: [PATCH 23/44] tests: remove unnecessary authNeeded field --- .../provider/residentialDevices/putResidentialDevice.feature | 1 - 1 file changed, 1 deletion(-) diff --git a/web/rest/client/features/provider/residentialDevices/putResidentialDevice.feature b/web/rest/client/features/provider/residentialDevices/putResidentialDevice.feature index 7cd2b07aa44..6e6787ba779 100644 --- a/web/rest/client/features/provider/residentialDevices/putResidentialDevice.feature +++ b/web/rest/client/features/provider/residentialDevices/putResidentialDevice.feature @@ -16,7 +16,6 @@ Feature: Update residential devices "transport": "udp", "ip": null, "port": null, - "authNeeded": "yes", "password": "ZGthe7E2+4", "disallow": "all", "allow": "alaw", From 121f3c8c01033f8d540bd5d7ea757d4ad77841d4 Mon Sep 17 00:00:00 2001 From: Carlos Cruz Date: Fri, 1 Jul 2022 12:39:21 +0200 Subject: [PATCH 24/44] schema: add type to FixedCostsRelInvoiceSchedulers --- ...edCostsRelInvoiceSchedulerAbstract.orm.yml | 8 +++++ .../Version20220701103822.php | 34 +++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 schema/DoctrineMigrations/Version20220701103822.php diff --git a/library/Ivoz/Provider/Infrastructure/Persistence/Doctrine/Mapping/FixedCostsRelInvoiceScheduler.FixedCostsRelInvoiceSchedulerAbstract.orm.yml b/library/Ivoz/Provider/Infrastructure/Persistence/Doctrine/Mapping/FixedCostsRelInvoiceScheduler.FixedCostsRelInvoiceSchedulerAbstract.orm.yml index 0d5be5518a7..7e622116489 100755 --- a/library/Ivoz/Provider/Infrastructure/Persistence/Doctrine/Mapping/FixedCostsRelInvoiceScheduler.FixedCostsRelInvoiceSchedulerAbstract.orm.yml +++ b/library/Ivoz/Provider/Infrastructure/Persistence/Doctrine/Mapping/FixedCostsRelInvoiceScheduler.FixedCostsRelInvoiceSchedulerAbstract.orm.yml @@ -12,6 +12,14 @@ Ivoz\Provider\Domain\Model\FixedCostsRelInvoiceScheduler\FixedCostsRelInvoiceSch nullable: true options: unsigned: true + type: + type: string + nullable: false + length: 25 + options: + fixed: false + comment: '[enum:static|maxcalls]' + default: 'static' manyToOne: fixedCost: targetEntity: \Ivoz\Provider\Domain\Model\FixedCost\FixedCostInterface diff --git a/schema/DoctrineMigrations/Version20220701103822.php b/schema/DoctrineMigrations/Version20220701103822.php new file mode 100644 index 00000000000..ac454d19d30 --- /dev/null +++ b/schema/DoctrineMigrations/Version20220701103822.php @@ -0,0 +1,34 @@ +abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('ALTER TABLE FixedCostsRelInvoiceSchedulers ADD type VARCHAR(25) DEFAULT \'static\' NOT NULL COMMENT \'[enum:static|maxcalls]\''); + } + + /** + * @param Schema $schema + */ + public function down(Schema $schema) + { + // this down() migration is auto-generated, please modify it to your needs + $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('ALTER TABLE FixedCostsRelInvoiceSchedulers DROP type'); + } +} From 1690122ac90aaadec98979656efc3d30c9f2d03d Mon Sep 17 00:00:00 2001 From: Carlos Cruz Date: Fri, 1 Jul 2022 12:39:29 +0200 Subject: [PATCH 25/44] core: regenerate entities with latest scheme changes --- .../FixedCostsRelInvoiceSchedulerAbstract.php | 47 ++++++++++++++++++- ...xedCostsRelInvoiceSchedulerDtoAbstract.php | 27 +++++++++++ ...FixedCostsRelInvoiceSchedulerInterface.php | 11 +++++ 3 files changed, 83 insertions(+), 2 deletions(-) diff --git a/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoiceScheduler/FixedCostsRelInvoiceSchedulerAbstract.php b/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoiceScheduler/FixedCostsRelInvoiceSchedulerAbstract.php index 501cb028ce1..8700a47b2c2 100644 --- a/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoiceScheduler/FixedCostsRelInvoiceSchedulerAbstract.php +++ b/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoiceScheduler/FixedCostsRelInvoiceSchedulerAbstract.php @@ -18,6 +18,12 @@ abstract class FixedCostsRelInvoiceSchedulerAbstract */ protected $quantity; + /** + * comment: enum:static|maxcalls + * @var string + */ + protected $type = 'static'; + /** * @var \Ivoz\Provider\Domain\Model\FixedCost\FixedCostInterface */ @@ -34,8 +40,9 @@ abstract class FixedCostsRelInvoiceSchedulerAbstract /** * Constructor */ - protected function __construct() + protected function __construct($type) { + $this->setType($type); } abstract public function getId(); @@ -106,7 +113,9 @@ public static function fromDto( ) { Assertion::isInstanceOf($dto, FixedCostsRelInvoiceSchedulerDto::class); - $self = new static(); + $self = new static( + $dto->getType() + ); $self ->setQuantity($dto->getQuantity()) @@ -132,6 +141,7 @@ public function updateFromDto( $this ->setQuantity($dto->getQuantity()) + ->setType($dto->getType()) ->setFixedCost($fkTransformer->transform($dto->getFixedCost())) ->setInvoiceScheduler($fkTransformer->transform($dto->getInvoiceScheduler())); @@ -149,6 +159,7 @@ public function toDto($depth = 0) { return self::createDto() ->setQuantity(self::getQuantity()) + ->setType(self::getType()) ->setFixedCost(\Ivoz\Provider\Domain\Model\FixedCost\FixedCost::entityToDto(self::getFixedCost(), $depth)) ->setInvoiceScheduler(\Ivoz\Provider\Domain\Model\InvoiceScheduler\InvoiceScheduler::entityToDto(self::getInvoiceScheduler(), $depth)); } @@ -160,6 +171,7 @@ protected function __toArray() { return [ 'quantity' => self::getQuantity(), + 'type' => self::getType(), 'fixedCostId' => self::getFixedCost()->getId(), 'invoiceSchedulerId' => self::getInvoiceScheduler() ? self::getInvoiceScheduler()->getId() : null ]; @@ -196,6 +208,37 @@ public function getQuantity() return $this->quantity; } + /** + * Set type + * + * @param string $type + * + * @return static + */ + protected function setType($type) + { + Assertion::notNull($type, 'type value "%s" is null, but non null value was expected.'); + Assertion::maxLength($type, 25, 'type value "%s" is too long, it should have no more than %d characters, but has %d characters.'); + Assertion::choice($type, [ + FixedCostsRelInvoiceSchedulerInterface::TYPE_STATIC, + FixedCostsRelInvoiceSchedulerInterface::TYPE_MAXCALLS + ], 'typevalue "%s" is not an element of the valid values: %s'); + + $this->type = $type; + + return $this; + } + + /** + * Get type + * + * @return string + */ + public function getType(): string + { + return $this->type; + } + /** * Set fixedCost * diff --git a/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoiceScheduler/FixedCostsRelInvoiceSchedulerDtoAbstract.php b/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoiceScheduler/FixedCostsRelInvoiceSchedulerDtoAbstract.php index 7ceda034a31..e2dd588fca7 100644 --- a/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoiceScheduler/FixedCostsRelInvoiceSchedulerDtoAbstract.php +++ b/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoiceScheduler/FixedCostsRelInvoiceSchedulerDtoAbstract.php @@ -15,6 +15,11 @@ abstract class FixedCostsRelInvoiceSchedulerDtoAbstract implements DataTransferO */ private $quantity; + /** + * @var string + */ + private $type = 'static'; + /** * @var integer */ @@ -49,6 +54,7 @@ public static function getPropertyMap(string $context = '', string $role = null) return [ 'quantity' => 'quantity', + 'type' => 'type', 'id' => 'id', 'fixedCostId' => 'fixedCost', 'invoiceSchedulerId' => 'invoiceScheduler' @@ -62,6 +68,7 @@ public function toArray($hideSensitiveData = false) { $response = [ 'quantity' => $this->getQuantity(), + 'type' => $this->getType(), 'id' => $this->getId(), 'fixedCost' => $this->getFixedCost(), 'invoiceScheduler' => $this->getInvoiceScheduler() @@ -101,6 +108,26 @@ public function getQuantity() return $this->quantity; } + /** + * @param string $type + * + * @return static + */ + public function setType($type = null) + { + $this->type = $type; + + return $this; + } + + /** + * @return string | null + */ + public function getType() + { + return $this->type; + } + /** * @param integer $id * diff --git a/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoiceScheduler/FixedCostsRelInvoiceSchedulerInterface.php b/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoiceScheduler/FixedCostsRelInvoiceSchedulerInterface.php index 5b140dc2937..62b951d7e99 100644 --- a/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoiceScheduler/FixedCostsRelInvoiceSchedulerInterface.php +++ b/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoiceScheduler/FixedCostsRelInvoiceSchedulerInterface.php @@ -6,6 +6,10 @@ interface FixedCostsRelInvoiceSchedulerInterface extends LoggableEntityInterface { + const TYPE_STATIC = 'static'; + const TYPE_MAXCALLS = 'maxcalls'; + + /** * @codeCoverageIgnore * @return array @@ -19,6 +23,13 @@ public function getChangeSet(); */ public function getQuantity(); + /** + * Get type + * + * @return string + */ + public function getType(): string; + /** * Get fixedCost * From 91c6a9bdbd652f119302c42ee40cd54c7ec51105 Mon Sep 17 00:00:00 2001 From: Carlos Cruz Date: Fri, 1 Jul 2022 12:52:57 +0200 Subject: [PATCH 26/44] web/admin: new selector type for FixedCostsRelInvoiceSchedulers --- .../FixedCostsRelInvoiceSchedulersList.yaml | 7 ++++++- .../model/FixedCostsRelInvoiceSchedulers.yaml | 16 ++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/web/admin/application/configs/klear/FixedCostsRelInvoiceSchedulersList.yaml b/web/admin/application/configs/klear/FixedCostsRelInvoiceSchedulersList.yaml index 1ab997ec69d..1bc2f6590a4 100644 --- a/web/admin/application/configs/klear/FixedCostsRelInvoiceSchedulersList.yaml +++ b/web/admin/application/configs/klear/FixedCostsRelInvoiceSchedulersList.yaml @@ -23,6 +23,10 @@ production: dialogs: fixedCostsRelInvoiceSchedulersDel_dialog: true default: fixedCostsRelInvoiceSchedulersEdit_screen + order: + fixedCost: true + type: true + quantity: true options: title: _("Options") screens: @@ -42,7 +46,8 @@ production: group0: colsPerRow: 12 fields: - fixedCost: 9 + fixedCost: 6 + type: 3 quantity: 3 fixedCostsRelInvoiceSchedulersEdit_screen: &fixedCostsRelInvoiceSchedulersEdit_screenLink <<: *FixedCostsRelInvoiceSchedulers diff --git a/web/admin/application/configs/klear/model/FixedCostsRelInvoiceSchedulers.yaml b/web/admin/application/configs/klear/model/FixedCostsRelInvoiceSchedulers.yaml index 1c981cc1663..a9b886daac9 100644 --- a/web/admin/application/configs/klear/model/FixedCostsRelInvoiceSchedulers.yaml +++ b/web/admin/application/configs/klear/model/FixedCostsRelInvoiceSchedulers.yaml @@ -39,6 +39,22 @@ production: control: Spinner min: 1 max: 100 + type: + title: _('Type') + type: select + required: true + source: + data: inline + values: + 'static': + title: _("Static") + visualFilter: + show: ["quantity"] + 'maxcalls': + title: _('Max calls') + visualFilter: + hide: ["quantity"] + staging: _extends: production testing: From c813c7e88b219bde47d1e5223eaeca82dd211d69 Mon Sep 17 00:00:00 2001 From: Carlos Cruz Date: Fri, 1 Jul 2022 13:14:41 +0200 Subject: [PATCH 27/44] core: FixedCostsRelInvoiceScheduler quantity is null for non-static types --- .../FixedCostsRelInvoiceScheduler.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoiceScheduler/FixedCostsRelInvoiceScheduler.php b/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoiceScheduler/FixedCostsRelInvoiceScheduler.php index d3f8a8073ca..b3d1d1036d0 100644 --- a/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoiceScheduler/FixedCostsRelInvoiceScheduler.php +++ b/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoiceScheduler/FixedCostsRelInvoiceScheduler.php @@ -27,4 +27,11 @@ public function getId() { return $this->id; } + + protected function sanitizeValues() + { + if ($this->getType() !== self::TYPE_STATIC) { + $this->setQuantity(null); + } + } } From f7ee85eb2fa8995dfbdc4d9e91f0ec5b3e2d26fb Mon Sep 17 00:00:00 2001 From: Carlos Cruz Date: Fri, 1 Jul 2022 13:35:58 +0200 Subject: [PATCH 28/44] core: get quantity from maxCalls in type maxcalls fixed costs --- .../Model/FixedCostsRelInvoice/FixedCostsRelInvoice.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoice/FixedCostsRelInvoice.php b/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoice/FixedCostsRelInvoice.php index 78c53a8ffab..cc2c0eb6222 100644 --- a/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoice/FixedCostsRelInvoice.php +++ b/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoice/FixedCostsRelInvoice.php @@ -40,10 +40,16 @@ public static function fromFixedCostsRelInvoiceScheduler( InvoiceInterface $invoice, FixedCostsRelInvoiceSchedulerInterface $fixedCostRelScheduler ) { + $quantity = $fixedCostRelScheduler->getQuantity(); + if ($fixedCostRelScheduler->getType() === FixedCostsRelInvoiceSchedulerInterface::TYPE_MAXCALLS) { + $quantity = $invoice->getCompany()->getMaxCalls(); + } + $entity = new static(); + $entity ->setQuantity( - $fixedCostRelScheduler->getQuantity() + $quantity ) ->setFixedCost( $fixedCostRelScheduler->getFixedCost() From 0c8d7e1301962d45cc72e990bf8177e1f44f17c3 Mon Sep 17 00:00:00 2001 From: Carlos Cruz Date: Fri, 1 Jul 2022 13:54:38 +0200 Subject: [PATCH 29/44] core: add type to FixedCostsRelInvoiceScheduler DTO --- .../FixedCostsRelInvoiceSchedulerDto.php | 1 + 1 file changed, 1 insertion(+) diff --git a/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoiceScheduler/FixedCostsRelInvoiceSchedulerDto.php b/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoiceScheduler/FixedCostsRelInvoiceSchedulerDto.php index 871dc905666..71910e9e017 100644 --- a/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoiceScheduler/FixedCostsRelInvoiceSchedulerDto.php +++ b/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoiceScheduler/FixedCostsRelInvoiceSchedulerDto.php @@ -16,6 +16,7 @@ public static function getPropertyMap(string $context = '', string $role = null) return [ 'quantity' => 'quantity', 'id' => 'id', + 'type' => 'type', 'fixedCostId' => 'fixedCost', 'invoiceSchedulerId' => 'invoiceScheduler' ]; From 09b04a3739d1e4141914c7261ebfc28ab4a87735 Mon Sep 17 00:00:00 2001 From: Carlos Cruz Date: Fri, 1 Jul 2022 13:02:20 +0200 Subject: [PATCH 30/44] doc: fixed cost by maxcalls on scheduled invoices --- .../brand/invoicing/invoice_schedulers.rst | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/doc/sphinx/administration_portal/brand/invoicing/invoice_schedulers.rst b/doc/sphinx/administration_portal/brand/invoicing/invoice_schedulers.rst index 044732fb136..e7369ced54f 100644 --- a/doc/sphinx/administration_portal/brand/invoicing/invoice_schedulers.rst +++ b/doc/sphinx/administration_portal/brand/invoicing/invoice_schedulers.rst @@ -30,14 +30,26 @@ When adding a new definition, these fields are shown: Taxes to add to the final cost (e.g. VAT) -.. tip:: Fixed concepts can be added in the same way as in manual invoice definitions - -Invoices generated due to an schedule can be seen in two ways: +Invoices generated due to a schedule can be seen in two ways: - In each row of *Invoice schedulers* section, **List of Invoices** option. - In *Invoices* section, indistinguishable to manually generated invoices. +Fixed costs +=========== + +When defining a scheduled invoice, you can add fixed costs in a static or dynamic way: + +- Type **'static'** is used for fixed quantities. + +- Type **'Max calls'** sets the quantity in the moment of the creation of the invoice to + "Max calls" value of the client in that specific moment. + +.. tip:: "Max calls" value is retrieved from client configuration in the date specified in "Next execution". + Regenerating the invoice later will not modify assigned value, but you can adapt it manually to + the desired value editing the fixed cost in Invoice section and regenerating the invoice. + Frequency definition ==================== From 599d8f294bf88e5adb53ea03e16886cf2fe63a5d Mon Sep 17 00:00:00 2001 From: Carlos Cruz Date: Fri, 1 Jul 2022 14:20:09 +0200 Subject: [PATCH 31/44] tests: update brand rest API tests --- .../getFixedCostsRelInvoiceScheduler.feature | 2 ++ .../postFixedCostsRelInvoiceScheduler.feature | 1 + 2 files changed, 3 insertions(+) diff --git a/web/rest/brand/features/provider/fixedCostsRelInvoiceScheduler/getFixedCostsRelInvoiceScheduler.feature b/web/rest/brand/features/provider/fixedCostsRelInvoiceScheduler/getFixedCostsRelInvoiceScheduler.feature index 10d93f4fdb5..1a2047b8f0f 100644 --- a/web/rest/brand/features/provider/fixedCostsRelInvoiceScheduler/getFixedCostsRelInvoiceScheduler.feature +++ b/web/rest/brand/features/provider/fixedCostsRelInvoiceScheduler/getFixedCostsRelInvoiceScheduler.feature @@ -16,6 +16,7 @@ Feature: Retrieve fixed costs rel invoice schedulers [ { "quantity": 1, + "type": "static", "id": 1, "fixedCost": { "name": "Monitoring", @@ -53,6 +54,7 @@ Feature: Retrieve fixed costs rel invoice schedulers """ { "quantity": 1, + "type": "static", "id": 1, "fixedCost": { "name": "Monitoring", diff --git a/web/rest/brand/features/provider/fixedCostsRelInvoiceScheduler/postFixedCostsRelInvoiceScheduler.feature b/web/rest/brand/features/provider/fixedCostsRelInvoiceScheduler/postFixedCostsRelInvoiceScheduler.feature index f5de294ca68..08f33373891 100644 --- a/web/rest/brand/features/provider/fixedCostsRelInvoiceScheduler/postFixedCostsRelInvoiceScheduler.feature +++ b/web/rest/brand/features/provider/fixedCostsRelInvoiceScheduler/postFixedCostsRelInvoiceScheduler.feature @@ -23,6 +23,7 @@ Feature: Create fixed costs rel invoice schedulers """ { "quantity": 1, + "type": "static", "id": 2, "fixedCost": 2, "invoiceScheduler": 1 From 7dc83e9c54645eb11f65edf7b669463dfc587105 Mon Sep 17 00:00:00 2001 From: Carlos Cruz Date: Tue, 5 Jul 2022 14:10:45 +0200 Subject: [PATCH 32/44] kamtrunks: print failing host in failure_route log message --- kamailio/trunks/config/kamailio.cfg | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/kamailio/trunks/config/kamailio.cfg b/kamailio/trunks/config/kamailio.cfg index 9c4b3b81a3b..0f835dc7d71 100644 --- a/kamailio/trunks/config/kamailio.cfg +++ b/kamailio/trunks/config/kamailio.cfg @@ -1638,9 +1638,11 @@ route[RELAY] { } if ($(du{uri.host}) != $null) { - xnotice("[$dlg_var(cidhash)] RELAY: Relaying to $ru via $du (du, $dP)\n"); + $avp(relay_dst) = $dP + ":" + $(du{uri.host}) + ":" + $(du{uri.port}); + xnotice("[$dlg_var(cidhash)] RELAY: Relaying to $avp(relay_dst) ($ru via $du)\n"); } else { - xnotice("[$dlg_var(cidhash)] RELAY: Relaying to $ru (ru)\n"); + $avp(relay_dst) = $rP + ":" + $(ru{uri.host}) + ":" + $(ru{uri.port}); + xnotice("[$dlg_var(cidhash)] RELAY: Relaying to $avp(relay_dst) ($ru)\n"); } # Common for every reply @@ -1926,7 +1928,7 @@ route[INACTIVATE_GW] { sql_query("cb", "SELECT O.id FROM OutgoingRouting O LEFT JOIN OutgoingRoutingRelCarriers ORRC ON O.id=ORRC.outgoingRoutingId WHERE O.stopper=1 AND ( O.carrierId=$dlg_var(carrierId) OR ORRC.carrierId=$dlg_var(carrierId) )", "isStopper"); if ($dbr(isStopper=>rows) == 0) { - xwarn("[$dlg_var(cidhash)] INACTIVATE-GW: $T_reply_code: Inactivate carrier server $dlg_var(carrierServerId) (carrier: $dlg_var(carrierId)) (no reply received)\n"); + xwarn("[$dlg_var(cidhash)] INACTIVATE-GW: $T_reply_code: Inactivate carrier server $dlg_var(carrierServerId) (carrier: $dlg_var(carrierId)) (no reply received from $var(failingHost))\n"); inactivate_gw(); # Inactivate GW temporally (until it answers OPTIONS) } sql_result_free("isStopper"); @@ -1976,7 +1978,13 @@ failure_route[MANAGE_FAILURE_GW] { if ($dlg_var(bounced) == '1') exit; # Avoid carrier failover in bounced call if(!t_check_status("(401)|(407)")) { - xwarn("[$dlg_var(cidhash)] MANAGE-FAILURE-GW: $rm FAILED: '$T_reply_code $T_reply_reason' to '$cs $rm' from '$fu' ($si:$sp) [$proto]\n"); + if (t_branch_timeout() && !t_branch_replied()) { + $var(failingHost) = $avp(relay_dst); + } else { + $var(failingHost) = $T_rpl($proto) + ":" + $T_rpl($si) + ":" + $T_rpl($sp); + } + + xwarn("[$dlg_var(cidhash)] MANAGE-FAILURE-GW: $rm FAILED: '$T_reply_code $T_reply_reason' to '$cs $rm' from '$fu' ($var(failingHost))\n"); } if (t_is_canceled()) { From f29446d3ed3de15ce616304603719bf7c6adcb1d Mon Sep 17 00:00:00 2001 From: Carlos Cruz Date: Fri, 1 Jul 2022 14:38:56 +0200 Subject: [PATCH 33/44] schema: new ddis value for FixedCostsRelInvoiceScheduler type --- ...edCostsRelInvoiceSchedulerAbstract.orm.yml | 23 ++++++++++- .../Version20220707084112.php | 38 +++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 schema/DoctrineMigrations/Version20220707084112.php diff --git a/library/Ivoz/Provider/Infrastructure/Persistence/Doctrine/Mapping/FixedCostsRelInvoiceScheduler.FixedCostsRelInvoiceSchedulerAbstract.orm.yml b/library/Ivoz/Provider/Infrastructure/Persistence/Doctrine/Mapping/FixedCostsRelInvoiceScheduler.FixedCostsRelInvoiceSchedulerAbstract.orm.yml index 7e622116489..95a6807c560 100755 --- a/library/Ivoz/Provider/Infrastructure/Persistence/Doctrine/Mapping/FixedCostsRelInvoiceScheduler.FixedCostsRelInvoiceSchedulerAbstract.orm.yml +++ b/library/Ivoz/Provider/Infrastructure/Persistence/Doctrine/Mapping/FixedCostsRelInvoiceScheduler.FixedCostsRelInvoiceSchedulerAbstract.orm.yml @@ -18,8 +18,17 @@ Ivoz\Provider\Domain\Model\FixedCostsRelInvoiceScheduler\FixedCostsRelInvoiceSch length: 25 options: fixed: false - comment: '[enum:static|maxcalls]' + comment: '[enum:static|maxcalls|ddis]' default: 'static' + ddisCountryMatch: + column: ddisCountryMatch + type: string + nullable: true + length: 25 + options: + fixed: false + comment: '[enum:all|national|international|specific]' + default: 'all' manyToOne: fixedCost: targetEntity: \Ivoz\Provider\Domain\Model\FixedCost\FixedCostInterface @@ -45,3 +54,15 @@ Ivoz\Provider\Domain\Model\FixedCostsRelInvoiceScheduler\FixedCostsRelInvoiceSch nullable: false onDelete: cascade orphanRemoval: false + ddisCountry: + targetEntity: \Ivoz\Provider\Domain\Model\Country\CountryInterface + cascade: { } + fetch: LAZY + mappedBy: null + inversedBy: null + joinColumns: + ddisCountryId: + referencedColumnName: id + nullable: true + onDelete: set null + orphanRemoval: false diff --git a/schema/DoctrineMigrations/Version20220707084112.php b/schema/DoctrineMigrations/Version20220707084112.php new file mode 100644 index 00000000000..5bab150c26c --- /dev/null +++ b/schema/DoctrineMigrations/Version20220707084112.php @@ -0,0 +1,38 @@ +abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('ALTER TABLE FixedCostsRelInvoiceSchedulers ADD ddisCountryMatch VARCHAR(25) DEFAULT \'all\' COMMENT \'[enum:all|national|international|specific]\', ADD ddisCountryId INT UNSIGNED DEFAULT NULL, CHANGE type type VARCHAR(25) DEFAULT \'static\' NOT NULL COMMENT \'[enum:static|maxcalls|ddis]\''); + $this->addSql('ALTER TABLE FixedCostsRelInvoiceSchedulers ADD CONSTRAINT FK_D9D0952B43D707A2 FOREIGN KEY (ddisCountryId) REFERENCES Countries (id) ON DELETE SET NULL'); + $this->addSql('CREATE INDEX IDX_D9D0952B43D707A2 ON FixedCostsRelInvoiceSchedulers (ddisCountryId)'); + } + + /** + * @param Schema $schema + */ + public function down(Schema $schema) + { + // this down() migration is auto-generated, please modify it to your needs + $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('ALTER TABLE FixedCostsRelInvoiceSchedulers DROP FOREIGN KEY FK_D9D0952B43D707A2'); + $this->addSql('DROP INDEX IDX_D9D0952B43D707A2 ON FixedCostsRelInvoiceSchedulers'); + $this->addSql('ALTER TABLE FixedCostsRelInvoiceSchedulers DROP ddisCountryMatch, DROP ddisCountryId, CHANGE type type VARCHAR(25) DEFAULT \'static\' NOT NULL COLLATE utf8_unicode_ci COMMENT \'[enum:static|maxcalls]\''); + } +} From ff90b86ac456bfa06d36cbf8da1d718f8da2a300 Mon Sep 17 00:00:00 2001 From: Carlos Cruz Date: Fri, 1 Jul 2022 14:39:01 +0200 Subject: [PATCH 34/44] core: regenerate entities with latest scheme changes --- .../FixedCostsRelInvoiceSchedulerAbstract.php | 88 +++++++++++++++++-- ...xedCostsRelInvoiceSchedulerDtoAbstract.php | 84 +++++++++++++++++- ...FixedCostsRelInvoiceSchedulerInterface.php | 21 +++++ 3 files changed, 186 insertions(+), 7 deletions(-) diff --git a/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoiceScheduler/FixedCostsRelInvoiceSchedulerAbstract.php b/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoiceScheduler/FixedCostsRelInvoiceSchedulerAbstract.php index 8700a47b2c2..c1ae4e51fe8 100644 --- a/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoiceScheduler/FixedCostsRelInvoiceSchedulerAbstract.php +++ b/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoiceScheduler/FixedCostsRelInvoiceSchedulerAbstract.php @@ -19,11 +19,17 @@ abstract class FixedCostsRelInvoiceSchedulerAbstract protected $quantity; /** - * comment: enum:static|maxcalls + * comment: enum:static|maxcalls|ddis * @var string */ protected $type = 'static'; + /** + * comment: enum:all|national|international|specific + * @var string | null + */ + protected $ddisCountryMatch = 'all'; + /** * @var \Ivoz\Provider\Domain\Model\FixedCost\FixedCostInterface */ @@ -34,6 +40,11 @@ abstract class FixedCostsRelInvoiceSchedulerAbstract */ protected $invoiceScheduler; + /** + * @var \Ivoz\Provider\Domain\Model\Country\CountryInterface | null + */ + protected $ddisCountry; + use ChangelogTrait; @@ -119,8 +130,10 @@ public static function fromDto( $self ->setQuantity($dto->getQuantity()) + ->setDdisCountryMatch($dto->getDdisCountryMatch()) ->setFixedCost($fkTransformer->transform($dto->getFixedCost())) ->setInvoiceScheduler($fkTransformer->transform($dto->getInvoiceScheduler())) + ->setDdisCountry($fkTransformer->transform($dto->getDdisCountry())) ; $self->initChangelog(); @@ -142,8 +155,10 @@ public function updateFromDto( $this ->setQuantity($dto->getQuantity()) ->setType($dto->getType()) + ->setDdisCountryMatch($dto->getDdisCountryMatch()) ->setFixedCost($fkTransformer->transform($dto->getFixedCost())) - ->setInvoiceScheduler($fkTransformer->transform($dto->getInvoiceScheduler())); + ->setInvoiceScheduler($fkTransformer->transform($dto->getInvoiceScheduler())) + ->setDdisCountry($fkTransformer->transform($dto->getDdisCountry())); @@ -160,8 +175,10 @@ public function toDto($depth = 0) return self::createDto() ->setQuantity(self::getQuantity()) ->setType(self::getType()) + ->setDdisCountryMatch(self::getDdisCountryMatch()) ->setFixedCost(\Ivoz\Provider\Domain\Model\FixedCost\FixedCost::entityToDto(self::getFixedCost(), $depth)) - ->setInvoiceScheduler(\Ivoz\Provider\Domain\Model\InvoiceScheduler\InvoiceScheduler::entityToDto(self::getInvoiceScheduler(), $depth)); + ->setInvoiceScheduler(\Ivoz\Provider\Domain\Model\InvoiceScheduler\InvoiceScheduler::entityToDto(self::getInvoiceScheduler(), $depth)) + ->setDdisCountry(\Ivoz\Provider\Domain\Model\Country\Country::entityToDto(self::getDdisCountry(), $depth)); } /** @@ -172,8 +189,10 @@ protected function __toArray() return [ 'quantity' => self::getQuantity(), 'type' => self::getType(), + 'ddisCountryMatch' => self::getDdisCountryMatch(), 'fixedCostId' => self::getFixedCost()->getId(), - 'invoiceSchedulerId' => self::getInvoiceScheduler() ? self::getInvoiceScheduler()->getId() : null + 'invoiceSchedulerId' => self::getInvoiceScheduler() ? self::getInvoiceScheduler()->getId() : null, + 'ddisCountryId' => self::getDdisCountry() ? self::getDdisCountry()->getId() : null ]; } // @codeCoverageIgnoreStart @@ -221,7 +240,8 @@ protected function setType($type) Assertion::maxLength($type, 25, 'type value "%s" is too long, it should have no more than %d characters, but has %d characters.'); Assertion::choice($type, [ FixedCostsRelInvoiceSchedulerInterface::TYPE_STATIC, - FixedCostsRelInvoiceSchedulerInterface::TYPE_MAXCALLS + FixedCostsRelInvoiceSchedulerInterface::TYPE_MAXCALLS, + FixedCostsRelInvoiceSchedulerInterface::TYPE_DDIS ], 'typevalue "%s" is not an element of the valid values: %s'); $this->type = $type; @@ -239,6 +259,40 @@ public function getType(): string return $this->type; } + /** + * Set ddisCountryMatch + * + * @param string $ddisCountryMatch | null + * + * @return static + */ + protected function setDdisCountryMatch($ddisCountryMatch = null) + { + if (!is_null($ddisCountryMatch)) { + Assertion::maxLength($ddisCountryMatch, 25, 'ddisCountryMatch value "%s" is too long, it should have no more than %d characters, but has %d characters.'); + Assertion::choice($ddisCountryMatch, [ + FixedCostsRelInvoiceSchedulerInterface::DDISCOUNTRYMATCH_ALL, + FixedCostsRelInvoiceSchedulerInterface::DDISCOUNTRYMATCH_NATIONAL, + FixedCostsRelInvoiceSchedulerInterface::DDISCOUNTRYMATCH_INTERNATIONAL, + FixedCostsRelInvoiceSchedulerInterface::DDISCOUNTRYMATCH_SPECIFIC + ], 'ddisCountryMatchvalue "%s" is not an element of the valid values: %s'); + } + + $this->ddisCountryMatch = $ddisCountryMatch; + + return $this; + } + + /** + * Get ddisCountryMatch + * + * @return string | null + */ + public function getDdisCountryMatch() + { + return $this->ddisCountryMatch; + } + /** * Set fixedCost * @@ -287,5 +341,29 @@ public function getInvoiceScheduler() return $this->invoiceScheduler; } + /** + * Set ddisCountry + * + * @param \Ivoz\Provider\Domain\Model\Country\CountryInterface $ddisCountry | null + * + * @return static + */ + protected function setDdisCountry(\Ivoz\Provider\Domain\Model\Country\CountryInterface $ddisCountry = null) + { + $this->ddisCountry = $ddisCountry; + + return $this; + } + + /** + * Get ddisCountry + * + * @return \Ivoz\Provider\Domain\Model\Country\CountryInterface | null + */ + public function getDdisCountry() + { + return $this->ddisCountry; + } + // @codeCoverageIgnoreEnd } diff --git a/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoiceScheduler/FixedCostsRelInvoiceSchedulerDtoAbstract.php b/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoiceScheduler/FixedCostsRelInvoiceSchedulerDtoAbstract.php index e2dd588fca7..4f33fc89f9a 100644 --- a/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoiceScheduler/FixedCostsRelInvoiceSchedulerDtoAbstract.php +++ b/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoiceScheduler/FixedCostsRelInvoiceSchedulerDtoAbstract.php @@ -20,6 +20,11 @@ abstract class FixedCostsRelInvoiceSchedulerDtoAbstract implements DataTransferO */ private $type = 'static'; + /** + * @var string + */ + private $ddisCountryMatch = 'all'; + /** * @var integer */ @@ -35,6 +40,11 @@ abstract class FixedCostsRelInvoiceSchedulerDtoAbstract implements DataTransferO */ private $invoiceScheduler; + /** + * @var \Ivoz\Provider\Domain\Model\Country\CountryDto | null + */ + private $ddisCountry; + use DtoNormalizer; @@ -55,9 +65,11 @@ public static function getPropertyMap(string $context = '', string $role = null) return [ 'quantity' => 'quantity', 'type' => 'type', + 'ddisCountryMatch' => 'ddisCountryMatch', 'id' => 'id', 'fixedCostId' => 'fixedCost', - 'invoiceSchedulerId' => 'invoiceScheduler' + 'invoiceSchedulerId' => 'invoiceScheduler', + 'ddisCountryId' => 'ddisCountry' ]; } @@ -69,9 +81,11 @@ public function toArray($hideSensitiveData = false) $response = [ 'quantity' => $this->getQuantity(), 'type' => $this->getType(), + 'ddisCountryMatch' => $this->getDdisCountryMatch(), 'id' => $this->getId(), 'fixedCost' => $this->getFixedCost(), - 'invoiceScheduler' => $this->getInvoiceScheduler() + 'invoiceScheduler' => $this->getInvoiceScheduler(), + 'ddisCountry' => $this->getDdisCountry() ]; if (!$hideSensitiveData) { @@ -128,6 +142,26 @@ public function getType() return $this->type; } + /** + * @param string $ddisCountryMatch + * + * @return static + */ + public function setDdisCountryMatch($ddisCountryMatch = null) + { + $this->ddisCountryMatch = $ddisCountryMatch; + + return $this; + } + + /** + * @return string | null + */ + public function getDdisCountryMatch() + { + return $this->ddisCountryMatch; + } + /** * @param integer $id * @@ -239,4 +273,50 @@ public function getInvoiceSchedulerId() return null; } + + /** + * @param \Ivoz\Provider\Domain\Model\Country\CountryDto $ddisCountry + * + * @return static + */ + public function setDdisCountry(\Ivoz\Provider\Domain\Model\Country\CountryDto $ddisCountry = null) + { + $this->ddisCountry = $ddisCountry; + + return $this; + } + + /** + * @return \Ivoz\Provider\Domain\Model\Country\CountryDto | null + */ + public function getDdisCountry() + { + return $this->ddisCountry; + } + + /** + * @param mixed | null $id + * + * @return static + */ + public function setDdisCountryId($id) + { + $value = !is_null($id) + ? new \Ivoz\Provider\Domain\Model\Country\CountryDto($id) + : null; + + return $this->setDdisCountry($value); + } + + /** + * @return mixed | null + */ + public function getDdisCountryId() + { + if ($dto = $this->getDdisCountry()) { + return $dto->getId(); + } + + return null; + } } diff --git a/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoiceScheduler/FixedCostsRelInvoiceSchedulerInterface.php b/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoiceScheduler/FixedCostsRelInvoiceSchedulerInterface.php index 62b951d7e99..5eccd832c0a 100644 --- a/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoiceScheduler/FixedCostsRelInvoiceSchedulerInterface.php +++ b/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoiceScheduler/FixedCostsRelInvoiceSchedulerInterface.php @@ -8,6 +8,13 @@ interface FixedCostsRelInvoiceSchedulerInterface extends LoggableEntityInterface { const TYPE_STATIC = 'static'; const TYPE_MAXCALLS = 'maxcalls'; + const TYPE_DDIS = 'ddis'; + + + const DDISCOUNTRYMATCH_ALL = 'all'; + const DDISCOUNTRYMATCH_NATIONAL = 'national'; + const DDISCOUNTRYMATCH_INTERNATIONAL = 'international'; + const DDISCOUNTRYMATCH_SPECIFIC = 'specific'; /** @@ -30,6 +37,13 @@ public function getQuantity(); */ public function getType(): string; + /** + * Get ddisCountryMatch + * + * @return string | null + */ + public function getDdisCountryMatch(); + /** * Get fixedCost * @@ -53,6 +67,13 @@ public function setInvoiceScheduler(\Ivoz\Provider\Domain\Model\InvoiceScheduler */ public function getInvoiceScheduler(); + /** + * Get ddisCountry + * + * @return \Ivoz\Provider\Domain\Model\Country\CountryInterface | null + */ + public function getDdisCountry(); + /** * @return bool */ From c3611568259bb561f8a74aca7baf5171f89542aa Mon Sep 17 00:00:00 2001 From: Kaian Date: Wed, 6 Jul 2022 12:08:59 +0200 Subject: [PATCH 35/44] core: update FixedCosts services with new matching options --- .../Domain/Model/Ddi/DdiRepository.php | 15 ++++ .../FixedCostsRelInvoice.php | 33 --------- .../FixedCostsRelInvoiceInterface.php | 7 -- .../FixedCostsRelInvoiceScheduler.php | 4 ++ .../FixedCostsRelInvoiceSchedulerDto.php | 2 + .../CreateByScheduler.php | 69 ++++++++++++++++--- .../Doctrine/DdiDoctrineRepository.php | 35 ++++++++++ 7 files changed, 117 insertions(+), 48 deletions(-) diff --git a/library/Ivoz/Provider/Domain/Model/Ddi/DdiRepository.php b/library/Ivoz/Provider/Domain/Model/Ddi/DdiRepository.php index b1f86c64a87..dbe06f51ea3 100644 --- a/library/Ivoz/Provider/Domain/Model/Ddi/DdiRepository.php +++ b/library/Ivoz/Provider/Domain/Model/Ddi/DdiRepository.php @@ -17,4 +17,19 @@ public function findOneByDdiE164($ddiE164); * @return \Ivoz\Provider\Domain\Model\Ddi\DdiInterface | null */ public function findOneByDdiAndCountry(string $ddi, int $countryId); + + /** + * @return int Number of DDIs of the given Company + */ + public function countByCompany(int $companyId): int; + + /** + * @return int Number of DDIs of the given Company and Country as prefix + */ + public function countByCompanyAndCountry(int $companyId, int $countryId): int; + + /** + * @return int Number of DDIs of the given Company and not Country as prefix + */ + public function countByCompanyAndNotCountry(int $companyId, int $countryId): int; } diff --git a/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoice/FixedCostsRelInvoice.php b/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoice/FixedCostsRelInvoice.php index cc2c0eb6222..e8138d5edd8 100644 --- a/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoice/FixedCostsRelInvoice.php +++ b/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoice/FixedCostsRelInvoice.php @@ -30,37 +30,4 @@ public function getId() { return $this->id; } - - /** - * @param \Ivoz\Provider\Domain\Model\Invoice\InvoiceInterface $invoice - * @param \Ivoz\Provider\Domain\Model\FixedCostsRelInvoiceScheduler\FixedCostsRelInvoiceSchedulerInterface $fixedCostRelScheduler - * @return static - */ - public static function fromFixedCostsRelInvoiceScheduler( - InvoiceInterface $invoice, - FixedCostsRelInvoiceSchedulerInterface $fixedCostRelScheduler - ) { - $quantity = $fixedCostRelScheduler->getQuantity(); - if ($fixedCostRelScheduler->getType() === FixedCostsRelInvoiceSchedulerInterface::TYPE_MAXCALLS) { - $quantity = $invoice->getCompany()->getMaxCalls(); - } - - $entity = new static(); - - $entity - ->setQuantity( - $quantity - ) - ->setFixedCost( - $fixedCostRelScheduler->getFixedCost() - ) - ->setInvoice( - $invoice - ); - - $entity->sanitizeValues(); - $entity->initChangelog(); - - return $entity; - } } diff --git a/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoice/FixedCostsRelInvoiceInterface.php b/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoice/FixedCostsRelInvoiceInterface.php index 0847ddc9dda..ec7d07683c6 100644 --- a/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoice/FixedCostsRelInvoiceInterface.php +++ b/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoice/FixedCostsRelInvoiceInterface.php @@ -12,13 +12,6 @@ interface FixedCostsRelInvoiceInterface extends LoggableEntityInterface */ public function getChangeSet(); - /** - * @param \Ivoz\Provider\Domain\Model\Invoice\InvoiceInterface $invoice - * @param \Ivoz\Provider\Domain\Model\FixedCostsRelInvoiceScheduler\FixedCostsRelInvoiceSchedulerInterface $fixedCostRelScheduler - * @return static - */ - public static function fromFixedCostsRelInvoiceScheduler(\Ivoz\Provider\Domain\Model\Invoice\InvoiceInterface $invoice, \Ivoz\Provider\Domain\Model\FixedCostsRelInvoiceScheduler\FixedCostsRelInvoiceSchedulerInterface $fixedCostRelScheduler); - /** * Get quantity * diff --git a/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoiceScheduler/FixedCostsRelInvoiceScheduler.php b/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoiceScheduler/FixedCostsRelInvoiceScheduler.php index b3d1d1036d0..7710367dfe9 100644 --- a/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoiceScheduler/FixedCostsRelInvoiceScheduler.php +++ b/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoiceScheduler/FixedCostsRelInvoiceScheduler.php @@ -33,5 +33,9 @@ protected function sanitizeValues() if ($this->getType() !== self::TYPE_STATIC) { $this->setQuantity(null); } + if ($this->getType() !== self::TYPE_DDIS) { + $this->setDdisCountryMatch(null); + $this->setDdisCountry(null); + } } } diff --git a/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoiceScheduler/FixedCostsRelInvoiceSchedulerDto.php b/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoiceScheduler/FixedCostsRelInvoiceSchedulerDto.php index 71910e9e017..940fb8adb2a 100644 --- a/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoiceScheduler/FixedCostsRelInvoiceSchedulerDto.php +++ b/library/Ivoz/Provider/Domain/Model/FixedCostsRelInvoiceScheduler/FixedCostsRelInvoiceSchedulerDto.php @@ -17,6 +17,8 @@ public static function getPropertyMap(string $context = '', string $role = null) 'quantity' => 'quantity', 'id' => 'id', 'type' => 'type', + 'ddisCountryMatch' => 'ddisCountryMatch', + 'ddisCountry' => 'ddisCountry', 'fixedCostId' => 'fixedCost', 'invoiceSchedulerId' => 'invoiceScheduler' ]; diff --git a/library/Ivoz/Provider/Domain/Service/FixedCostsRelInvoice/CreateByScheduler.php b/library/Ivoz/Provider/Domain/Service/FixedCostsRelInvoice/CreateByScheduler.php index a9ca5c33cd8..d3fa1eedbbb 100755 --- a/library/Ivoz/Provider/Domain/Service/FixedCostsRelInvoice/CreateByScheduler.php +++ b/library/Ivoz/Provider/Domain/Service/FixedCostsRelInvoice/CreateByScheduler.php @@ -3,7 +3,8 @@ namespace Ivoz\Provider\Domain\Service\FixedCostsRelInvoice; use Ivoz\Core\Application\Service\EntityTools; -use Ivoz\Provider\Domain\Model\FixedCostsRelInvoice\FixedCostsRelInvoice; +use Ivoz\Provider\Domain\Model\Ddi\DdiRepository; +use Ivoz\Provider\Domain\Model\FixedCostsRelInvoice\FixedCostsRelInvoiceDto; use Ivoz\Provider\Domain\Model\FixedCostsRelInvoiceScheduler\FixedCostsRelInvoiceSchedulerInterface; use Ivoz\Provider\Domain\Model\Invoice\InvoiceInterface; use Ivoz\Provider\Domain\Model\InvoiceScheduler\InvoiceSchedulerInterface; @@ -12,10 +13,14 @@ class CreateByScheduler { private $entityTools; + private $ddiRepository; + public function __construct( - EntityTools $entityTools + EntityTools $entityTools, + DdiRepository $ddiRepository ) { $this->entityTools = $entityTools; + $this->ddiRepository = $ddiRepository; } /** @@ -28,14 +33,62 @@ public function execute( InvoiceSchedulerInterface $scheduler, InvoiceInterface $invoice ) { - /** @var FixedCostsRelInvoiceSchedulerInterface[] $relFixedCosts */ + $company = $invoice->getCompany(); $relFixedCosts = $scheduler->getRelFixedCosts(); foreach ($relFixedCosts as $relFixedCost) { - $fixedCostRelInvoice = FixedCostsRelInvoice::fromFixedCostsRelInvoiceScheduler( - $invoice, - $relFixedCost - ); - $this->entityTools->persist($fixedCostRelInvoice); + // Calculate Dynamic quantities + $quantity = $relFixedCost->getQuantity(); + $type = $relFixedCost->getType(); + if ($type === FixedCostsRelInvoiceSchedulerInterface::TYPE_MAXCALLS) { + // Quantity based on Client Max Calls setting + $quantity = $company->getMaxCalls(); + } elseif ($type === FixedCostsRelInvoiceSchedulerInterface::TYPE_DDIS) { + // Quantity based on Client DDI Count + $ddisMatch = $relFixedCost->getDdisCountryMatch(); + $ddisCountry = $relFixedCost->getDdisCountry(); + $companyCountry = $company->getCountry(); + // DDI Match All Countries + if ($ddisMatch == FixedCostsRelInvoiceSchedulerInterface::DDISCOUNTRYMATCH_ALL) { + $quantity = $this->ddiRepository->countByCompany( + $company->getId() + ); + } + // DDI Match from client country + if ($ddisMatch == FixedCostsRelInvoiceSchedulerInterface::DDISCOUNTRYMATCH_NATIONAL) { + $quantity = $this->ddiRepository->countByCompanyAndCountry( + $company->getId(), + $companyCountry->getId() + ); + } + // DDI Match NOT from client country + if ($ddisMatch == FixedCostsRelInvoiceSchedulerInterface::DDISCOUNTRYMATCH_INTERNATIONAL) { + $quantity = $this->ddiRepository->countByCompanyAndNotCountry( + $company->getId(), + $companyCountry->getId() + ); + } + // DDI Match from specific country + if ($ddisMatch == FixedCostsRelInvoiceSchedulerInterface::DDISCOUNTRYMATCH_SPECIFIC) { + $quantity = $this->ddiRepository->countByCompanyAndCountry( + $company->getId(), + $ddisCountry->getId() + ); + } + } + + $fixedCostRelInvoiceDto = new FixedCostsRelInvoiceDto(); + $fixedCostRelInvoiceDto + ->setQuantity( + $quantity + ) + ->setFixedCostId( + $relFixedCost->getFixedCost()->getId() + ) + ->setInvoiceId( + $invoice->getId() + ); + + $this->entityTools->persistDto($fixedCostRelInvoiceDto); } } } diff --git a/library/Ivoz/Provider/Infrastructure/Persistence/Doctrine/DdiDoctrineRepository.php b/library/Ivoz/Provider/Infrastructure/Persistence/Doctrine/DdiDoctrineRepository.php index 4921d1e73b6..6159e346222 100755 --- a/library/Ivoz/Provider/Infrastructure/Persistence/Doctrine/DdiDoctrineRepository.php +++ b/library/Ivoz/Provider/Infrastructure/Persistence/Doctrine/DdiDoctrineRepository.php @@ -48,4 +48,39 @@ public function findOneByDdiAndCountry(string $ddi, int $countryId) return $response; } + + public function countByCompany(int $companyId): int + { + $qb = $this->createQueryBuilder('self'); + + return $qb + ->select('count(self.id)') + ->where($qb->expr()->eq('self.company', $companyId)) + ->getQuery() + ->getSingleScalarResult(); + } + + public function countByCompanyAndCountry(int $companyId, int $countryId): int + { + $qb = $this->createQueryBuilder('self'); + + return $qb + ->select('count(self.id)') + ->where($qb->expr()->eq('self.company', $companyId)) + ->andWhere($qb->expr()->eq('self.country', $countryId)) + ->getQuery() + ->getSingleScalarResult(); + } + + public function countByCompanyAndNotCountry(int $companyId, int $countryId): int + { + $qb = $this->createQueryBuilder('self'); + + return $qb + ->select('count(self.id)') + ->where($qb->expr()->eq('self.company', $companyId)) + ->andWhere($qb->expr()->neq('self.country', $countryId)) + ->getQuery() + ->getSingleScalarResult(); + } } From f6d9fef89130242308fdd69cfa8abcd7b6c19e76 Mon Sep 17 00:00:00 2001 From: Carlos Cruz Date: Fri, 1 Jul 2022 15:18:18 +0200 Subject: [PATCH 36/44] web/admin: ddi criteria for fixed costs --- .../FixedCostsRelInvoiceSchedulersList.yaml | 14 ++++ .../configs/klear/conf.d/ddisMatchHelp.yaml | 14 ++++ .../model/FixedCostsRelInvoiceSchedulers.yaml | 59 +++++++++++++++- .../application/languages/ca_ES/ca_ES.po | 21 ++++++ .../application/languages/en_US/en_US.po | 22 ++++++ .../application/languages/es_ES/es_ES.po | 21 ++++++ .../application/languages/it_IT/it_IT.po | 21 ++++++ .../Ghost/FixedCostsRelInvoiceSchedulers.php | 68 +++++++++++++++++++ 8 files changed, 237 insertions(+), 3 deletions(-) create mode 100644 web/admin/application/configs/klear/conf.d/ddisMatchHelp.yaml create mode 100644 web/admin/application/library/IvozProvider/Klear/Ghost/FixedCostsRelInvoiceSchedulers.php diff --git a/web/admin/application/configs/klear/FixedCostsRelInvoiceSchedulersList.yaml b/web/admin/application/configs/klear/FixedCostsRelInvoiceSchedulersList.yaml index 1bc2f6590a4..78bf63c6f02 100644 --- a/web/admin/application/configs/klear/FixedCostsRelInvoiceSchedulersList.yaml +++ b/web/admin/application/configs/klear/FixedCostsRelInvoiceSchedulersList.yaml @@ -26,7 +26,11 @@ production: order: fixedCost: true type: true + quantityGhost: true + blacklist: quantity: true + ddisCountryMatch: true + ddisCountry: true options: title: _("Options") screens: @@ -42,6 +46,11 @@ production: title: _("Add %s", ngettext('Fixed cost', 'Fixed costs', 1), "[format| (%parent%)]") shortcutOption: N filterField: invoiceScheduler + defaultValues: + country: 70 + fields: + blacklist: + quantityGhost: true fixedPositions: &fixedCostsRelInvoiceSchedulers_fixedPositions_Link group0: colsPerRow: 12 @@ -49,6 +58,8 @@ production: fixedCost: 6 type: 3 quantity: 3 + ddisCountryMatch: 7 + ddisCountry: 5 fixedCostsRelInvoiceSchedulersEdit_screen: &fixedCostsRelInvoiceSchedulersEdit_screenLink <<: *FixedCostsRelInvoiceSchedulers controller: edit @@ -57,6 +68,9 @@ production: labelOnPostAction: _("Edit %s %2s", ngettext('Fixed cost', 'Fixed costs', 1), "[format| (%item%)]") title: _("Edit %s %2s", ngettext('Fixed cost', 'Fixed costs', 1), "[format| (%item%)]") filterField: invoiceScheduler + fields: + blacklist: + quantityGhost: true fixedPositions: <<: *fixedCostsRelInvoiceSchedulers_fixedPositions_Link dialogs: &fixedCostsRelInvoiceSchedulers_dialogsLink diff --git a/web/admin/application/configs/klear/conf.d/ddisMatchHelp.yaml b/web/admin/application/configs/klear/conf.d/ddisMatchHelp.yaml new file mode 100644 index 00000000000..bd3a548a405 --- /dev/null +++ b/web/admin/application/configs/klear/conf.d/ddisMatchHelp.yaml @@ -0,0 +1,14 @@ +ddisMatchHelp: &ddisMatchHelp + info: + type: box + position: left + icon: help + label: _("Need help?") + text: " + Calculate quantity based on the number of DDIs: +
+               all            Any country
+ national Client's country
+ international NOT Client's country
+ specific Specific country
+
" diff --git a/web/admin/application/configs/klear/model/FixedCostsRelInvoiceSchedulers.yaml b/web/admin/application/configs/klear/model/FixedCostsRelInvoiceSchedulers.yaml index a9b886daac9..ff62f66aa67 100644 --- a/web/admin/application/configs/klear/model/FixedCostsRelInvoiceSchedulers.yaml +++ b/web/admin/application/configs/klear/model/FixedCostsRelInvoiceSchedulers.yaml @@ -1,3 +1,5 @@ +#include ../conf.d/ddisMatchHelp.yaml + production: entity: Ivoz\Provider\Domain\Model\FixedCostsRelInvoiceScheduler\FixedCostsRelInvoiceScheduler fields: @@ -49,12 +51,63 @@ production: 'static': title: _("Static") visualFilter: - show: ["quantity"] + show: [ quantity ] + hide: [ ddisCountry, ddisCountryMatch ] 'maxcalls': title: _('Max calls') visualFilter: - hide: ["quantity"] - + hide: [ quantity, ddisCountryMatch, ddisCountry ] + 'ddis': + title: ngettext('DDI', 'DDIs', 2) + visualFilter: + hide: [ quantity ] + show: [ ddisCountryMatch ] + ddisCountryMatch: + title: _('DDIs Match mode') + type: select + required: true + <<: *ddisMatchHelp + source: + data: inline + values: + 'all': + title: _("All Countries") + visualFilter: + hide: [ ddisCountry ] + 'national': + title: _("National") + visualFilter: + hide: [ ddisCountry ] + 'international': + title: _("International") + visualFilter: + hide: [ ddisCountry ] + 'specific': + title: _("Specific") + visualFilter: + show: [ ddisCountry ] + ddisCountry: + title: _('Country') + type: select + required: true + defaultValue: 70 + source: + data: mapper + config: + entity: \Ivoz\Provider\Domain\Model\Country\Country + fieldName: + fields: + - name${lang} + - countryCode + template: '%name${lang}% (%countryCode%)' + order: + Country.name.${lang}: asc + quantityGhost: + title: _('Quantity') + type: ghost + source: + class: IvozProvider_Klear_Ghost_FixedCostsRelInvoiceSchedulers + method: getQuantity staging: _extends: production testing: diff --git a/web/admin/application/languages/ca_ES/ca_ES.po b/web/admin/application/languages/ca_ES/ca_ES.po index 01b0cb8fab0..f3876ec25f5 100644 --- a/web/admin/application/languages/ca_ES/ca_ES.po +++ b/web/admin/application/languages/ca_ES/ca_ES.po @@ -144,6 +144,9 @@ msgstr[1] "Aliases" msgid "All" msgstr "Tots" +msgid "All Countries" +msgstr "Todos los paises" + msgid "Allow Call Forwards" msgstr "Permet desviament de trucada" @@ -550,6 +553,18 @@ msgstr[1] "Administradors de client" msgid "Client filters" msgstr "Filtros de cliente" +msgid "Client's DDIs NOT from %s (%s)" +msgstr "DDIs del Cliente de paises diferentes de %s (%s)" + +msgid "Client's DDIs from %s (%s)" +msgstr "DDIs del Cliente de %s (%s)" + +msgid "Client's DDIs from Any Country" +msgstr "DDIs de Cliente de cualquier País" + +msgid "Client's Max Calls setting" +msgstr "Configuración Limite de llamadas de Cliente" + msgid "Client's default" msgstr "Per defecte del client" @@ -667,6 +682,9 @@ msgstr[1] "DDIs" msgid "DDI In" msgstr "DDI entrada" +msgid "DDI Match" +msgstr "Coincidència DDI" + msgid "DDI Provider" msgid_plural "DDI Providers" msgstr[0] "Proveïdor de DDI" @@ -2011,6 +2029,9 @@ msgstr "Sense etiqueta de ruta" msgid "None" msgstr "Cap" +msgid "Not Country" +msgstr "Sense País" + msgid "Notification Threshold" msgstr "Llindar de notificació" diff --git a/web/admin/application/languages/en_US/en_US.po b/web/admin/application/languages/en_US/en_US.po index 2012efcab89..fbd3bd26fc6 100644 --- a/web/admin/application/languages/en_US/en_US.po +++ b/web/admin/application/languages/en_US/en_US.po @@ -139,6 +139,10 @@ msgstr[1] "Aliases" msgid "All" msgstr "All" +#, fuzzy +msgid "All Countries" +msgstr "GeoIP allowed countries" + msgid "Allow Call Forwards" msgstr "Allow Call Forwards" @@ -545,6 +549,18 @@ msgstr[1] "Clients admins" msgid "Client filters" msgstr "Client filters" +msgid "Client's DDIs NOT from %s (%s)" +msgstr "Client's DDIs NOT from %s (%s)" + +msgid "Client's DDIs from %s (%s)" +msgstr "Client's DDIs from %s (%s)" + +msgid "Client's DDIs from Any Country" +msgstr "Client's DDIs from Any Country" + +msgid "Client's Max Calls setting" +msgstr "Client's Max Calls setting" + msgid "Client's default" msgstr "Client's default" @@ -662,6 +678,9 @@ msgstr[1] "DDIs" msgid "DDI In" msgstr "DDI In" +msgid "DDI Match" +msgstr "DDI Match" + msgid "DDI Provider" msgid_plural "DDI Providers" msgstr[0] "DDI Provider" @@ -1992,6 +2011,9 @@ msgstr "No routing tag" msgid "None" msgstr "None" +msgid "Not Country" +msgstr "Not Country" + msgid "Notification Threshold" msgstr "Notification Threshold" diff --git a/web/admin/application/languages/es_ES/es_ES.po b/web/admin/application/languages/es_ES/es_ES.po index f15edb42a99..2846c1f1dd0 100644 --- a/web/admin/application/languages/es_ES/es_ES.po +++ b/web/admin/application/languages/es_ES/es_ES.po @@ -143,6 +143,9 @@ msgstr[1] "Aliases" msgid "All" msgstr "Todos" +msgid "All Countries" +msgstr "Todos los paises" + msgid "Allow Call Forwards" msgstr "Permitir desvíos de llamada" @@ -552,6 +555,18 @@ msgstr[1] "Administradores de clientes" msgid "Client filters" msgstr "Filtros de cliente" +msgid "Client's DDIs NOT from %s (%s)" +msgstr "DDIs del Cliente de paises diferentes de %s (%s)" + +msgid "Client's DDIs from %s (%s)" +msgstr "DDIs del Cliente de %s (%s)" + +msgid "Client's DDIs from Any Country" +msgstr "DDIs de Cliente de cualquier País" + +msgid "Client's Max Calls setting" +msgstr "Configuración Limite de llamadas de Cliente" + msgid "Client's default" msgstr "Usar configuración cliente" @@ -669,6 +684,9 @@ msgstr[1] "DDIs" msgid "DDI In" msgstr "DDI In" +msgid "DDI Match" +msgstr "Coincidencia DDI" + msgid "DDI Provider" msgid_plural "DDI Providers" msgstr[0] "Proveedor DDIs" @@ -2022,6 +2040,9 @@ msgstr "Sin etiqueta de enrutado" msgid "None" msgstr "Ninguna" +msgid "Not Country" +msgstr "No País" + msgid "Notification Threshold" msgstr "Límite de notificación" diff --git a/web/admin/application/languages/it_IT/it_IT.po b/web/admin/application/languages/it_IT/it_IT.po index bd2c861d454..498606434bb 100644 --- a/web/admin/application/languages/it_IT/it_IT.po +++ b/web/admin/application/languages/it_IT/it_IT.po @@ -145,6 +145,9 @@ msgstr[1] "Aliases" msgid "All" msgstr "Tutti" +msgid "All Countries" +msgstr "All Countries" + msgid "Allow Call Forwards" msgstr "Consenti deviazioni di Chiamata" @@ -555,6 +558,18 @@ msgstr[1] "Amministratori Client" msgid "Client filters" msgstr "Filtri Cliente" +msgid "Client's DDIs NOT from %s (%s)" +msgstr "Client's DDIs NOT from %s (%s)" + +msgid "Client's DDIs from %s (%s)" +msgstr "Client's DDIs from %s (%s)" + +msgid "Client's DDIs from Any Country" +msgstr "Client's DDIs from Any Country" + +msgid "Client's Max Calls setting" +msgstr "Client's Max Calls setting" + msgid "Client's default" msgstr "Impostazione predefinita del client" @@ -672,6 +687,9 @@ msgstr[1] "DDIs" msgid "DDI In" msgstr "DDI In" +msgid "DDI Match" +msgstr "DDI Match" + msgid "DDI Provider" msgid_plural "DDI Providers" msgstr[0] "DDI Provider" @@ -2022,6 +2040,9 @@ msgstr "No routing tag" msgid "None" msgstr "Nessuno" +msgid "Not Country" +msgstr "Not Country" + msgid "Notification Threshold" msgstr "Soglia per notifica" diff --git a/web/admin/application/library/IvozProvider/Klear/Ghost/FixedCostsRelInvoiceSchedulers.php b/web/admin/application/library/IvozProvider/Klear/Ghost/FixedCostsRelInvoiceSchedulers.php new file mode 100644 index 00000000000..e20a9d63eb1 --- /dev/null +++ b/web/admin/application/library/IvozProvider/Klear/Ghost/FixedCostsRelInvoiceSchedulers.php @@ -0,0 +1,68 @@ +getType() == FixedCostsRelInvoiceSchedulerInterface::TYPE_STATIC) { + return $fixedCostsRelInvoiceScheduler->getQuantity(); + } + + if ($fixedCostsRelInvoiceScheduler->getType() == FixedCostsRelInvoiceSchedulerInterface::TYPE_MAXCALLS) { + return _("Client's Max Calls setting"); + } + + if ($fixedCostsRelInvoiceScheduler->getType() == FixedCostsRelInvoiceSchedulerInterface::TYPE_DDIS) { + $ddiCountryMatch = $fixedCostsRelInvoiceScheduler->getDdisCountryMatch(); + // Any Country + if ($ddiCountryMatch == FixedCostsRelInvoiceSchedulerInterface::DDISCOUNTRYMATCH_ALL) { + return _("DDIs from any country"); + } + // Client Country + if ($ddiCountryMatch == FixedCostsRelInvoiceSchedulerInterface::DDISCOUNTRYMATCH_NATIONAL) { + return _("DDIs from client's country"); + } + // Not client Country + if ($ddiCountryMatch == FixedCostsRelInvoiceSchedulerInterface::DDISCOUNTRYMATCH_INTERNATIONAL) { + return _("DDIs NOT from client's country"); + } + + if ($ddiCountryMatch == FixedCostsRelInvoiceSchedulerInterface::DDISCOUNTRYMATCH_SPECIFIC) { + // Specific Country DDI Matching + /** @var DataGateway $dataGateway */ + $dataGateway = \Zend_Registry::get('data_gateway'); + + /** @var \Ivoz\Provider\Domain\Model\Country\Name $countryName */ + $countryName = $dataGateway->remoteProcedureCall( + Country::class, + $fixedCostsRelInvoiceScheduler->getDdisCountryId(), + 'getName', + [] + ); + + $countryCode = $dataGateway->remoteProcedureCall( + Country::class, + $fixedCostsRelInvoiceScheduler->getDdisCountryId(), + 'getCountryCode', + [] + ); + + return sprintf(_("DDIs from %s (%s)"), $countryName->getEn(), $countryCode); + } + } + + return ""; + } +} From 375d022de4e434822a60e6e1892e9d7ba5f5c878 Mon Sep 17 00:00:00 2001 From: Kaian Date: Thu, 7 Jul 2022 11:30:11 +0200 Subject: [PATCH 37/44] i18n: strings for new FixedCostsRelInvoiceSchedulers fields --- .../application/languages/ca_ES/ca_ES.po | 40 ++++++++++------- .../application/languages/en_US/en_US.po | 43 +++++++++++-------- .../application/languages/es_ES/es_ES.po | 40 ++++++++++------- .../application/languages/it_IT/it_IT.po | 40 ++++++++++------- 4 files changed, 101 insertions(+), 62 deletions(-) diff --git a/web/admin/application/languages/ca_ES/ca_ES.po b/web/admin/application/languages/ca_ES/ca_ES.po index f3876ec25f5..b175bcb53f1 100644 --- a/web/admin/application/languages/ca_ES/ca_ES.po +++ b/web/admin/application/languages/ca_ES/ca_ES.po @@ -553,15 +553,6 @@ msgstr[1] "Administradors de client" msgid "Client filters" msgstr "Filtros de cliente" -msgid "Client's DDIs NOT from %s (%s)" -msgstr "DDIs del Cliente de paises diferentes de %s (%s)" - -msgid "Client's DDIs from %s (%s)" -msgstr "DDIs del Cliente de %s (%s)" - -msgid "Client's DDIs from Any Country" -msgstr "DDIs de Cliente de cualquier País" - msgid "Client's Max Calls setting" msgstr "Configuración Limite de llamadas de Cliente" @@ -682,9 +673,6 @@ msgstr[1] "DDIs" msgid "DDI In" msgstr "DDI entrada" -msgid "DDI Match" -msgstr "Coincidència DDI" - msgid "DDI Provider" msgid_plural "DDI Providers" msgstr[0] "Proveïdor de DDI" @@ -700,6 +688,22 @@ msgid_plural "DDI Provider Registrations" msgstr[0] "Registre del proveïdor de DDI" msgstr[1] "Registres del proveïdor de DDI" +msgid "DDIs Match mode" +msgstr "Coincidència DDI" + +msgid "DDIs NOT from client's country" +msgstr "DDIs de paises distintos al cliente" + +#, php-format +msgid "DDIs from %s (%s)" +msgstr "DDIs de %s (%s)" + +msgid "DDIs from any country" +msgstr "DDIs de cualquier país" + +msgid "DDIs from client's country" +msgstr "DDIs del paises del cliente" + msgid "Day" msgstr "Dia" @@ -1569,6 +1573,9 @@ msgstr "Intra vPBX" msgid "Internal" msgstr "Interna" +msgid "International" +msgstr "International" + msgid "International Code" msgstr "Codi internacional" @@ -1969,6 +1976,9 @@ msgstr "" "El nom serà mostrat com a orígen quan s0enviin correus (exemple: " "Notificacions IvozProvider)" +msgid "National" +msgstr "National" + msgid "National number length" msgstr "Longitud números nacionals" @@ -2029,9 +2039,6 @@ msgstr "Sense etiqueta de ruta" msgid "None" msgstr "Cap" -msgid "Not Country" -msgstr "Sense País" - msgid "Notification Threshold" msgstr "Llindar de notificació" @@ -2728,6 +2735,9 @@ msgstr[1] "Números especiales" msgid "Special treatments" msgstr "Tratamientos especiales" +msgid "Specific" +msgstr "Específico" + msgid "Specific Template" msgstr "Plantilla específica" diff --git a/web/admin/application/languages/en_US/en_US.po b/web/admin/application/languages/en_US/en_US.po index fbd3bd26fc6..b9c366307a1 100644 --- a/web/admin/application/languages/en_US/en_US.po +++ b/web/admin/application/languages/en_US/en_US.po @@ -139,9 +139,8 @@ msgstr[1] "Aliases" msgid "All" msgstr "All" -#, fuzzy msgid "All Countries" -msgstr "GeoIP allowed countries" +msgstr "All Countries" msgid "Allow Call Forwards" msgstr "Allow Call Forwards" @@ -549,15 +548,6 @@ msgstr[1] "Clients admins" msgid "Client filters" msgstr "Client filters" -msgid "Client's DDIs NOT from %s (%s)" -msgstr "Client's DDIs NOT from %s (%s)" - -msgid "Client's DDIs from %s (%s)" -msgstr "Client's DDIs from %s (%s)" - -msgid "Client's DDIs from Any Country" -msgstr "Client's DDIs from Any Country" - msgid "Client's Max Calls setting" msgstr "Client's Max Calls setting" @@ -678,9 +668,6 @@ msgstr[1] "DDIs" msgid "DDI In" msgstr "DDI In" -msgid "DDI Match" -msgstr "DDI Match" - msgid "DDI Provider" msgid_plural "DDI Providers" msgstr[0] "DDI Provider" @@ -696,6 +683,22 @@ msgid_plural "DDI Provider Registrations" msgstr[0] "DDI Provider Registration" msgstr[1] "DDI Provider Registrations" +msgid "DDIs Match mode" +msgstr "DDIs Match mode" + +msgid "DDIs NOT from client's country" +msgstr "DDIs NOT from client's country" + +#, php-format +msgid "DDIs from %s (%s)" +msgstr "DDIs from %s (%s)" + +msgid "DDIs from any country" +msgstr "DDIs from any country" + +msgid "DDIs from client's country" +msgstr "DDIs from client's country" + msgid "Day" msgstr "Day" @@ -1553,6 +1556,9 @@ msgstr "Inter vPBX" msgid "Internal" msgstr "Internal" +msgid "International" +msgstr "International" + msgid "International Code" msgstr "International Code" @@ -1951,6 +1957,9 @@ msgid "" msgstr "" "Name shown as source when sending mails (e.g. IvozProvider Notifications)" +msgid "National" +msgstr "National" + msgid "National number length" msgstr "National number length" @@ -2011,9 +2020,6 @@ msgstr "No routing tag" msgid "None" msgstr "None" -msgid "Not Country" -msgstr "Not Country" - msgid "Notification Threshold" msgstr "Notification Threshold" @@ -2706,6 +2712,9 @@ msgstr[1] "Special Numbers" msgid "Special treatments" msgstr "Special treatments" +msgid "Specific" +msgstr "Specific" + msgid "Specific Template" msgstr "Specific Template" diff --git a/web/admin/application/languages/es_ES/es_ES.po b/web/admin/application/languages/es_ES/es_ES.po index 2846c1f1dd0..7860cc20ee4 100644 --- a/web/admin/application/languages/es_ES/es_ES.po +++ b/web/admin/application/languages/es_ES/es_ES.po @@ -555,15 +555,6 @@ msgstr[1] "Administradores de clientes" msgid "Client filters" msgstr "Filtros de cliente" -msgid "Client's DDIs NOT from %s (%s)" -msgstr "DDIs del Cliente de paises diferentes de %s (%s)" - -msgid "Client's DDIs from %s (%s)" -msgstr "DDIs del Cliente de %s (%s)" - -msgid "Client's DDIs from Any Country" -msgstr "DDIs de Cliente de cualquier País" - msgid "Client's Max Calls setting" msgstr "Configuración Limite de llamadas de Cliente" @@ -684,9 +675,6 @@ msgstr[1] "DDIs" msgid "DDI In" msgstr "DDI In" -msgid "DDI Match" -msgstr "Coincidencia DDI" - msgid "DDI Provider" msgid_plural "DDI Providers" msgstr[0] "Proveedor DDIs" @@ -702,6 +690,22 @@ msgid_plural "DDI Provider Registrations" msgstr[0] "Registro Proveedor" msgstr[1] "Registros Proveedor" +msgid "DDIs Match mode" +msgstr "Coincidència DDI" + +msgid "DDIs NOT from client's country" +msgstr "DDIs de paises distintos al cliente" + +#, php-format +msgid "DDIs from %s (%s)" +msgstr "DDIs de %s (%s)" + +msgid "DDIs from any country" +msgstr "DDIs de cualquier país" + +msgid "DDIs from client's country" +msgstr "DDIs del paises del cliente" + msgid "Day" msgstr "Día" @@ -1574,6 +1578,9 @@ msgstr "Inter vPBX" msgid "Internal" msgstr "Interna" +msgid "International" +msgstr "International" + msgid "International Code" msgstr "Código de llamada internacional" @@ -1980,6 +1987,9 @@ msgstr "" "Nombre mostrado como origen en los correos enviados (e.g. Notificaciones " "IvozProvider). " +msgid "National" +msgstr "National" + msgid "National number length" msgstr "Longitud números nacionales" @@ -2040,9 +2050,6 @@ msgstr "Sin etiqueta de enrutado" msgid "None" msgstr "Ninguna" -msgid "Not Country" -msgstr "No País" - msgid "Notification Threshold" msgstr "Límite de notificación" @@ -2742,6 +2749,9 @@ msgstr[1] "Números especiales" msgid "Special treatments" msgstr "Tratamientos especiales" +msgid "Specific" +msgstr "Específico" + msgid "Specific Template" msgstr "Plantilla específica" diff --git a/web/admin/application/languages/it_IT/it_IT.po b/web/admin/application/languages/it_IT/it_IT.po index 498606434bb..520dd42bb96 100644 --- a/web/admin/application/languages/it_IT/it_IT.po +++ b/web/admin/application/languages/it_IT/it_IT.po @@ -558,15 +558,6 @@ msgstr[1] "Amministratori Client" msgid "Client filters" msgstr "Filtri Cliente" -msgid "Client's DDIs NOT from %s (%s)" -msgstr "Client's DDIs NOT from %s (%s)" - -msgid "Client's DDIs from %s (%s)" -msgstr "Client's DDIs from %s (%s)" - -msgid "Client's DDIs from Any Country" -msgstr "Client's DDIs from Any Country" - msgid "Client's Max Calls setting" msgstr "Client's Max Calls setting" @@ -687,9 +678,6 @@ msgstr[1] "DDIs" msgid "DDI In" msgstr "DDI In" -msgid "DDI Match" -msgstr "DDI Match" - msgid "DDI Provider" msgid_plural "DDI Providers" msgstr[0] "DDI Provider" @@ -705,6 +693,22 @@ msgid_plural "DDI Provider Registrations" msgstr[0] "Regsitrazione DDI Provider" msgstr[1] "Registrazioni DDI Provider" +msgid "DDIs Match mode" +msgstr "DDIs Match mode" + +msgid "DDIs NOT from client's country" +msgstr "DDIs NOT from client's country" + +#, php-format +msgid "DDIs from %s (%s)" +msgstr "DDIs from %s (%s)" + +msgid "DDIs from any country" +msgstr "DDIs from any country" + +msgid "DDIs from client's country" +msgstr "DDIs from client's country" + msgid "Day" msgstr "Giorno" @@ -1574,6 +1578,9 @@ msgstr "Tra vPBX" msgid "Internal" msgstr "Interno" +msgid "International" +msgstr "Internazionale" + msgid "International Code" msgstr "Codice internazionale" @@ -1980,6 +1987,9 @@ msgstr "" "Nome visualizzato come origine quando si inviano mail (ad esempio notifiche " "IvozProvider)" +msgid "National" +msgstr "Nazionale" + msgid "National number length" msgstr "Lunghezza del numero nazionale" @@ -2040,9 +2050,6 @@ msgstr "No routing tag" msgid "None" msgstr "Nessuno" -msgid "Not Country" -msgstr "Not Country" - msgid "Notification Threshold" msgstr "Soglia per notifica" @@ -2742,6 +2749,9 @@ msgstr[1] "Numeri Speciali" msgid "Special treatments" msgstr "Trattamento Speciale" +msgid "Specific" +msgstr "Specifico" + msgid "Specific Template" msgstr "Modello specifico" From 610c3d037730221941ab3edeb06c2a67ec17574f Mon Sep 17 00:00:00 2001 From: Carlos Cruz Date: Fri, 1 Jul 2022 15:22:17 +0200 Subject: [PATCH 38/44] doc: ddi criteria for fixed costs --- .../brand/invoicing/invoice_schedulers.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/sphinx/administration_portal/brand/invoicing/invoice_schedulers.rst b/doc/sphinx/administration_portal/brand/invoicing/invoice_schedulers.rst index e7369ced54f..d12e3bf67a0 100644 --- a/doc/sphinx/administration_portal/brand/invoicing/invoice_schedulers.rst +++ b/doc/sphinx/administration_portal/brand/invoicing/invoice_schedulers.rst @@ -46,7 +46,11 @@ When defining a scheduled invoice, you can add fixed costs in a static or dynami - Type **'Max calls'** sets the quantity in the moment of the creation of the invoice to "Max calls" value of the client in that specific moment. -.. tip:: "Max calls" value is retrieved from client configuration in the date specified in "Next execution". +- Type **'DDIs'** sets the quantity in the moment of the creation of the invoice to + the number of DDIS matching criteria (all, national, international or belonging to specific country) + in the client in that specific moment. + +.. tip:: Non-static values are retrieved from client configuration in the date specified in "Next execution". Regenerating the invoice later will not modify assigned value, but you can adapt it manually to the desired value editing the fixed cost in Invoice section and regenerating the invoice. From d3791a6481cf19fa76e2aeaefb1db1adf02af825 Mon Sep 17 00:00:00 2001 From: Carlos Cruz Date: Tue, 5 Jul 2022 15:19:01 +0200 Subject: [PATCH 39/44] tests: update brand rest API tests --- .../getFixedCostsRelInvoiceScheduler.feature | 8 ++++++-- .../postFixedCostsRelInvoiceScheduler.feature | 4 +++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/web/rest/brand/features/provider/fixedCostsRelInvoiceScheduler/getFixedCostsRelInvoiceScheduler.feature b/web/rest/brand/features/provider/fixedCostsRelInvoiceScheduler/getFixedCostsRelInvoiceScheduler.feature index 1a2047b8f0f..2456db83e64 100644 --- a/web/rest/brand/features/provider/fixedCostsRelInvoiceScheduler/getFixedCostsRelInvoiceScheduler.feature +++ b/web/rest/brand/features/provider/fixedCostsRelInvoiceScheduler/getFixedCostsRelInvoiceScheduler.feature @@ -17,6 +17,7 @@ Feature: Retrieve fixed costs rel invoice schedulers { "quantity": 1, "type": "static", + "ddisCountryMatch": null, "id": 1, "fixedCost": { "name": "Monitoring", @@ -38,7 +39,8 @@ Feature: Retrieve fixed costs rel invoice schedulers "brand": 1, "company": 1, "numberSequence": null - } + }, + "ddisCountry": null } ] """ @@ -55,6 +57,7 @@ Feature: Retrieve fixed costs rel invoice schedulers { "quantity": 1, "type": "static", + "ddisCountryMatch": null, "id": 1, "fixedCost": { "name": "Monitoring", @@ -76,6 +79,7 @@ Feature: Retrieve fixed costs rel invoice schedulers "brand": 1, "company": 1, "numberSequence": null - } + }, + "ddisCountry": null } """ diff --git a/web/rest/brand/features/provider/fixedCostsRelInvoiceScheduler/postFixedCostsRelInvoiceScheduler.feature b/web/rest/brand/features/provider/fixedCostsRelInvoiceScheduler/postFixedCostsRelInvoiceScheduler.feature index 08f33373891..3b4793f7c07 100644 --- a/web/rest/brand/features/provider/fixedCostsRelInvoiceScheduler/postFixedCostsRelInvoiceScheduler.feature +++ b/web/rest/brand/features/provider/fixedCostsRelInvoiceScheduler/postFixedCostsRelInvoiceScheduler.feature @@ -24,9 +24,11 @@ Feature: Create fixed costs rel invoice schedulers { "quantity": 1, "type": "static", + "ddisCountryMatch": null, "id": 2, "fixedCost": 2, - "invoiceScheduler": 1 + "invoiceScheduler": 1, + "ddisCountry": null } """ From c4e63d3fcb02c8ba88d9d2b7a9c6e9594bee6557 Mon Sep 17 00:00:00 2001 From: Kaian Date: Thu, 7 Jul 2022 11:54:30 +0200 Subject: [PATCH 40/44] tests: updated ORM tests --- .../tests/Provider/Ddi/DdiRepositoryTest.php | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/schema/tests/Provider/Ddi/DdiRepositoryTest.php b/schema/tests/Provider/Ddi/DdiRepositoryTest.php index 51ea15ee1da..71b337521ca 100644 --- a/schema/tests/Provider/Ddi/DdiRepositoryTest.php +++ b/schema/tests/Provider/Ddi/DdiRepositoryTest.php @@ -18,6 +18,10 @@ public function test_runner() { $this->its_instantiable(); $this->it_finds_one_by_ddi_e164(); + $this->it_finds_one_by_ddi_and_country(); + $this->it_counts_by_company(); + $this->it_counts_by_company_and_country(); + $this->it_counts_by_company_and_not_country(); } public function its_instantiable() @@ -47,4 +51,64 @@ public function it_finds_one_by_ddi_e164() $ddi ); } + + public function it_finds_one_by_ddi_and_country() + { + /** @var DdiRepository $repository */ + $repository = $this + ->em + ->getRepository(Ddi::class); + + $ddi = $repository->findOneByDdiAndCountry('123', 68); + + $this->assertInstanceOf( + Ddi::class, + $ddi + ); + } + + public function it_counts_by_company() + { + /** @var DdiRepository $repository */ + $repository = $this + ->em + ->getRepository(Ddi::class); + + $num = $repository->countByCompany(1); + + $this->assertInternalType( + 'int', + $num + ); + } + + public function it_counts_by_company_and_country() + { + /** @var DdiRepository $repository */ + $repository = $this + ->em + ->getRepository(Ddi::class); + + $num = $repository->countByCompanyAndCountry(1, 68); + + $this->assertInternalType( + 'int', + $num + ); + } + + public function it_counts_by_company_and_not_country() + { + /** @var DdiRepository $repository */ + $repository = $this + ->em + ->getRepository(Ddi::class); + + $num = $repository->countByCompanyAndNotCountry(1, 68); + + $this->assertInternalType( + 'int', + $num + ); + } } From 6186f156ee92e5c4bd1fd5fa793d70b669413b05 Mon Sep 17 00:00:00 2001 From: Carlos Cruz Date: Mon, 11 Jul 2022 12:10:56 +0200 Subject: [PATCH 41/44] kamusers: print failing host in failure_route log message --- kamailio/users/config/kamailio.cfg | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/kamailio/users/config/kamailio.cfg b/kamailio/users/config/kamailio.cfg index 1f877de3d71..95aa6bd8a13 100644 --- a/kamailio/users/config/kamailio.cfg +++ b/kamailio/users/config/kamailio.cfg @@ -2020,9 +2020,11 @@ route[RURIALIAS] { route[RELAY] { if ($branch(count) == $null) { if ($(du{uri.host}) != $null) { - xnotice("[$dlg_var(cidhash)] RELAY: Relaying to $ru via $du (du, $dP)\n"); + $avp(relay_dst) = $dP + ":" + $(du{uri.host}) + ":" + $(du{uri.port}); + xnotice("[$dlg_var(cidhash)] RELAY: Relaying to $avp(relay_dst) ($ru via $du)\n"); } else { - xnotice("[$dlg_var(cidhash)] RELAY: Relaying to $ru (ru)\n"); + $avp(relay_dst) = $rP + ":" + $(ru{uri.host}) + ":" + $(ru{uri.port}); + xnotice("[$dlg_var(cidhash)] RELAY: Relaying to $avp(relay_dst) ($ru)\n"); } } @@ -2587,7 +2589,13 @@ onreply_route[MANAGE_REPLY] { } failure_route[MANAGE_FAILURE] { - xwarn("[$dlg_var(cidhash)] MANAGE-FAILURE: $rm FAILED: '$T_reply_code $T_reply_reason' to '$cs $rm' from '$fu' ($si:$sp) [$proto]\n"); + if (t_branch_timeout() && !t_branch_replied()) { + $var(failingHost) = $avp(relay_dst); + } else { + $var(failingHost) = $T_rpl($proto) + ":" + $T_rpl($si) + ":" + $T_rpl($sp); + } + + xwarn("[$dlg_var(cidhash)] MANAGE-FAILURE: $rm FAILED: '$T_reply_code $T_reply_reason' to '$cs $rm' from '$fu' ($var(failingHost))\n"); if (t_is_canceled()) { xwarn("[$dlg_var(cidhash)] MANAGE-FAILURE: t_is_canceled, exit here\n"); @@ -2599,7 +2607,13 @@ failure_route[MANAGE_FAILURE] { } failure_route[MANAGE_FAILURE_RETAIL] { - xwarn("[$dlg_var(cidhash)] MANAGE-FAILURE-RETAIL: $rm FAILED: '$T_reply_code $T_reply_reason' to '$cs $rm' from '$fu' ($si:$sp) [$proto]\n"); + if (t_branch_timeout() && !t_branch_replied()) { + $var(failingHost) = $avp(relay_dst); + } else { + $var(failingHost) = $T_rpl($proto) + ":" + $T_rpl($si) + ":" + $T_rpl($sp); + } + + xwarn("[$dlg_var(cidhash)] MANAGE-FAILURE-RETAIL: $rm FAILED: '$T_reply_code $T_reply_reason' to '$cs $rm' from '$fu' ($var(failingHost))\n"); if (t_is_canceled()) { xwarn("[$dlg_var(cidhash)] MANAGE-FAILURE-RETAIL: t_is_canceled, exit here\n"); @@ -2622,7 +2636,13 @@ failure_route[MANAGE_FAILURE_RETAIL] { } failure_route[MANAGE_FAILURE_AS] { - xwarn("[$dlg_var(cidhash)] MANAGE-FAILURE-AS: $rm FAILED: '$T_reply_code $T_reply_reason' to '$cs $rm' from '$fu' ($si:$sp) [$proto]\n"); + if (t_branch_timeout() && !t_branch_replied()) { + $var(failingHost) = $avp(relay_dst); + } else { + $var(failingHost) = $T_rpl($proto) + ":" + $T_rpl($si) + ":" + $T_rpl($sp); + } + + xwarn("[$dlg_var(cidhash)] MANAGE-FAILURE-AS: $rm FAILED: '$T_reply_code $T_reply_reason' to '$cs $rm' from '$fu' ($var(failingHost))\n"); if (t_is_canceled()) { xwarn("[$dlg_var(cidhash)] MANAGE-FAILURE-AS: t_is_canceled, exit here\n"); From 79b2f4ff53c98dc3d810301efd10189c3711823b Mon Sep 17 00:00:00 2001 From: Kaian Date: Thu, 7 Jul 2022 12:58:36 +0200 Subject: [PATCH 42/44] doc: update ChangeLog for 2.21.0 --- ChangeLog | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/ChangeLog b/ChangeLog index 82a6883be69..e5785422eaf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,28 @@ +Thu, 07 Jul 2022 12:47:57 +0200 IvozProvider Team + + * IvozProvider 2.21.0 released + + * Proxies + - Fixed rtpengine sessions deletion on branch timeout + - Fixed a bug with failover handling on bounced calls + - OPTION messages are now skipped from anti-flood mechanism + - Residential Devices authentication is now optional when Direct Connectivity is enabled + - Retail Accounts authentication is now optional when Direct Connectivity is enabled + - Improve log messages on no reply event + + * Invoicing + - Added dynamic quantity support to Invoice schedulers fixed costs + - Added Client max calls as Fixed cost dynamic quantity + - Added Client DDI count as Fixed cost dynamic quantity + + * Portals + - Fixed a bug that prevented creating vPBX clients depending on emulated company ACLs + - Removed Retail Account column from DDI Provider's DDI List section + + * Other + - Added support for custom entries in local DNS server + - Fixed swagger JSON generation commands in package post install scripts + Wed, 23 Mar 2022 16:40:26 +0100 IvozProvider Team * IvozProvider 2.20.1 released From f096290f0b1ee2a5d8357672a70ed38e5a3f6c59 Mon Sep 17 00:00:00 2001 From: Mikel Madariaga Date: Mon, 11 Jul 2022 09:52:24 +0200 Subject: [PATCH 43/44] doc: updated API changelog for 2.21.0 --- web/rest/brand/CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/web/rest/brand/CHANGELOG.md b/web/rest/brand/CHANGELOG.md index 653c4f61349..f2aebb4a433 100644 --- a/web/rest/brand/CHANGELOG.md +++ b/web/rest/brand/CHANGELOG.md @@ -1,4 +1,13 @@ # Changelog +## 2.21.0 +* Models: + - FixedCostsRelInvoiceScheduler, FixedCostsRelInvoiceScheduler-detailed and FixedCostsRelInvoiceScheduler-detailedCollection: + - Added type required property + - Added ddisCountryMatch property + - Added ddisCountry property + - ResidentialDevice: + - Removed authNeeded required property + ## 2.19.0 * Endpoints: - /brands: From 9d01c88d27962e30bf8e489145ab4aea4580c3a5 Mon Sep 17 00:00:00 2001 From: Kaian Date: Tue, 12 Jul 2022 09:41:09 +0200 Subject: [PATCH 44/44] doc: update all version strings to 2.21 --- README.md | 4 ++-- asterisk/config/pjsip.conf | 2 +- doc/sphinx/conf.py | 4 ++-- kamailio/trunks/config/kamailio.cfg | 4 ++-- kamailio/users/config/kamailio.cfg | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 1afd8581b07..786f3452c57 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![IvozProvider Logo](web/admin/public/images/logoprovider.png) ![stable](web/admin/public/images/stable-2.20-blue.png) ![release](web/admin/public/images/release-artemis-14b9bc.png) +![IvozProvider Logo](web/admin/public/images/logoprovider.png) ![stable](https://raster.shields.io/badge/sable-2.21-blue.png) ![release](web/admin/public/images/release-artemis-14b9bc.png) Ivoz Provider is a multitenant solution for VoIP telephony providers designed for horizontal scaling and load balancing. @@ -51,7 +51,7 @@ If you want to test an [standalone](https://irontec.github.io/ivozprovider/en/ar | Version | 64 bits | 32 bits | |----------|:--------:|:-------:| |oldstable (oasis 1.7) | [![iso http](web/admin/public/images/iso-http-green.png)](https://packages.irontec.com/isos/ivozprovider-1.7.1-oasis-amd64.iso)| [![iso http](web/admin/public/images/iso-http-green.png)](https://packages.irontec.com/isos/ivozprovider-1.7.1-oasis-i386.iso)| -|stable (artemis 2.20.1) | [![iso http](web/admin/public/images/iso-http-green.png)](https://packages.irontec.com/isos/ivozprovider-2.20~2.20.1-artemis-amd64.iso)| | +|stable (artemis 2.21.0) | [![iso http](web/admin/public/images/iso-http-green.png)](https://packages.irontec.com/isos/ivozprovider-2.21~2.21.0-artemis-amd64.iso)| | |testing (halliday 3.x) | | diff --git a/asterisk/config/pjsip.conf b/asterisk/config/pjsip.conf index d0bbe62fd95..897080f9ce6 100644 --- a/asterisk/config/pjsip.conf +++ b/asterisk/config/pjsip.conf @@ -3,7 +3,7 @@ ;; [global] type=global -user_agent=Irontec IvozProvider v2.20 +user_agent=Irontec IvozProvider v2.21 endpoint_identifier_order=ip,contact,username,anonymous ;; diff --git a/doc/sphinx/conf.py b/doc/sphinx/conf.py index 7bd2be559a3..0951f3b65d3 100644 --- a/doc/sphinx/conf.py +++ b/doc/sphinx/conf.py @@ -73,7 +73,7 @@ # built documents. # # The short X.Y version. -version = "2.20" +version = "2.21" # The full version, including alpha/beta/rc tags. release = 'Artemis' @@ -276,7 +276,7 @@ # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - (master_doc, 'IvozProvider.tex', 'IvozProvider 2.20 Documentation', + (master_doc, 'IvozProvider.tex', 'IvozProvider 2.21 Documentation', 'Irontec', 'manual'), ] diff --git a/kamailio/trunks/config/kamailio.cfg b/kamailio/trunks/config/kamailio.cfg index 0f835dc7d71..d3f7a2845d4 100644 --- a/kamailio/trunks/config/kamailio.cfg +++ b/kamailio/trunks/config/kamailio.cfg @@ -137,8 +137,8 @@ log_facility=LOG_LOCAL0 onsend_route_reply=yes # Add custom Server header -server_header="Server: Irontec IvozProvider v2.20" -user_agent_header="User-Agent: Irontec IvozProvider v2.20" +server_header="Server: Irontec IvozProvider v2.21" +user_agent_header="User-Agent: Irontec IvozProvider v2.21" ####### Modules Section ######## diff --git a/kamailio/users/config/kamailio.cfg b/kamailio/users/config/kamailio.cfg index 95aa6bd8a13..947480e1d86 100644 --- a/kamailio/users/config/kamailio.cfg +++ b/kamailio/users/config/kamailio.cfg @@ -150,8 +150,8 @@ log_facility=LOG_LOCAL0 onsend_route_reply=yes # Add custom Server header -server_header="Server: Irontec IvozProvider v2.20" -user_agent_header="User-Agent: Irontec IvozProvider v2.20" +server_header="Server: Irontec IvozProvider v2.21" +user_agent_header="User-Agent: Irontec IvozProvider v2.21" ####### Modules Section ########