diff --git a/distributor/src/distributor/constants.bal b/distributor/src/distributor/constants.bal index a771a6c..71bca76 100644 --- a/distributor/src/distributor/constants.bal +++ b/distributor/src/distributor/constants.bal @@ -5,8 +5,10 @@ const ELECTION_TYPE_PARLIAMENTARY = "PARLIAMENTARY"; const RP_V = "RP_V"; const RE_VI = "RE_VI"; +const RE_V = "RE_V"; const RE_S = "RE_S"; const RN_SI = "RN_SI"; +const RN_V = "RN_V"; const RN_VS = "RN_VS"; const RN_VSN = "RN_VSN"; const RE_SC = "RE_SC"; diff --git a/distributor/src/distributor/genhtml.bal b/distributor/src/distributor/genhtml.bal index bd29f9a..a7ddfed 100644 --- a/distributor/src/distributor/genhtml.bal +++ b/distributor/src/distributor/genhtml.bal @@ -108,8 +108,10 @@ function generateParliamentaryResultHtml(string electionCode, map result, " POLLING DIVISION (" + result.pd_code + ") RESULT"; } RE_VI => { resTypeHeading = result.ed_name + " ELECTORAL DISTRICT CUMULATIVE RESULTS AT " + result.timestamp; } + RE_V => { resTypeHeading = result.ed_name + " ELECTORAL DISTRICT VOTES RESULT"; } RE_S => { resTypeHeading = result.ed_name + " ELECTORAL DISTRICT SEAT ALLOCATION RESULT"; } RN_SI => { resTypeHeading = "ALL ISLAND CUMULATIVE SEAT ALLOCATION RESULTS AT " + result.timestamp; } + RN_V => { resTypeHeading = "ALL ISLAND VOTES RESULT"; } RN_VS => { resTypeHeading = "ALL ISLAND VOTES + SEAT ALLOCATION RESULT"; } RN_VSN => { resTypeHeading = "ALL ISLAND VOTES + SEAT ALLOCATION + NATIONAL LIST ALLOCATION RESULT"; } RE_SC => { resTypeHeading = result.ed_name + " ELECTORAL DISTRICT SEATS ALLOCATED CANDIDATES"; } @@ -125,7 +127,7 @@ function generateParliamentaryResultHtml(string electionCode, map result, "Name of Party" + "Party Abbreviaton"; - if ('type == RP_V || 'type == RE_VI || 'type == RN_VS || 'type == RN_VSN) { + if ('type == RP_V || 'type == RE_VI || 'type == RE_V || 'type == RN_V || 'type == RN_VS || 'type == RN_VSN) { body += "Votes Received" + "Percentage"; } @@ -144,7 +146,7 @@ function generateParliamentaryResultHtml(string electionCode, map result, "" + pr.party_name + "" + "" + pr.party_code +""; - if ('type == RP_V || 'type == RE_VI || 'type == RN_VS || 'type == RN_VSN) { + if ('type == RP_V || 'type == RE_VI || 'type == RE_V || 'type == RN_V || 'type == RN_VS || 'type == RN_VSN) { body += "" + commaFormatInt(pr.vote_count) + "" + "" + pr.vote_percentage + ""; } @@ -238,7 +240,7 @@ function sortParliamentaryByPartyResults(json[] unsorted, string resultType) ret return sortByPartyResultsBySeatCount(unsorted); } } - // RN_VS, RN_VSN + // RN_V, RN_VS, RN_VSN return sortByPartyResultsByVoteCount(unsorted); } diff --git a/distributor/src/distributor/messenger.bal b/distributor/src/distributor/messenger.bal index 04768d1..e26a965 100644 --- a/distributor/src/distributor/messenger.bal +++ b/distributor/src/distributor/messenger.bal @@ -65,11 +65,15 @@ function sendSMS(string message, string resultId) { } string logMessage = "Sending SMS for " + resultId; log:printInfo(logMessage); - foreach string targetMobile in mobileSubscribers { - log:printInfo(logMessage + " to " + targetMobile); - var response = smsClient->sendSms(sourceDepartment, message, targetMobile); - if response is error { - log:printError("Message sending failed for \'" + targetMobile + "\'", response); + string[] keys = mobileSubscribers.keys(); + foreach string userName in keys { + string? targetMobile = mobileSubscribers[userName]; + if !(targetMobile is ()) { + log:printInfo(logMessage + " to " + targetMobile); + var response = smsClient->sendSms(sourceDepartment, message, targetMobile); + if response is error { + log:printError("Message sending failed for \'" + targetMobile + "\'", response); + } } } } @@ -81,7 +85,7 @@ function sendSMS(string message, string resultId) { function validate(string mobileNo) returns string|error { string mobile = <@untained> mobileNo.trim(); - if (mobile.startsWith("+94") && mobile.length() == 12) { + if (mobile.startsWith("+") && mobile.length() == 12) { mobile = mobile.substring(1); } @@ -91,18 +95,19 @@ function validate(string mobileNo) returns string|error { log:printError(errorMsg); return error(ERROR_REASON, message = errorMsg); } - - if (mobile.startsWith("0") && mobile.length() == 10) { - return mobile; - } - if (mobile.startsWith("94") && mobile.length() == 11) { - return mobile; - } - // Allow only the local mobile numbers to register via public API. International number are avoided. - log:printError("Invalid mobile number : " + mobile); - return error(ERROR_REASON, message = "Invalid mobile number. Resend the request as follows: If the " + - "mobile no is 0771234567, send POST request to \'/sms\' with JSON payload " + - "\'{\"username\":\"myuser\", \"mobile\":\"0771234567\"}\'"); + return mobile; + + //if (mobile.startsWith("0") && mobile.length() == 10) { + // return mobile; + //} + //if (mobile.startsWith("94") && mobile.length() == 11) { + // return mobile; + //} + //// Allow only the local mobile numbers to register via public API. International number are avoided. + //log:printError("Invalid mobile number : " + mobile); + //return error(ERROR_REASON, message = "Invalid mobile number. Resend the request as follows: If the " + + // "mobile no is 0771234567, send POST request to \'/sms\' with JSON payload " + + // "\'{\"username\":\"myuser\", \"mobile\":\"0771234567\"}\'"); } # Register recipient in the mobileSubscribers list and persist in the smsRecipients db table. diff --git a/distributor/src/distributor/tests/resources/contact1.json b/distributor/src/distributor/tests/resources/contact1.json index 51d0b23..8e4d02b 100644 --- a/distributor/src/distributor/tests/resources/contact1.json +++ b/distributor/src/distributor/tests/resources/contact1.json @@ -1,7 +1,7 @@ [ { "username":"newuser1", - "mobile":"0711234561" + "mobile":"07112345611111111" }, { "username":"newuser2", diff --git a/distributor/src/distributor/tests/resources/contact2.json b/distributor/src/distributor/tests/resources/contact2.json index 28c18aa..5013b21 100644 --- a/distributor/src/distributor/tests/resources/contact2.json +++ b/distributor/src/distributor/tests/resources/contact2.json @@ -1,7 +1,7 @@ [ { "username":"newuser1", - "mobile":"+00771234562" + "mobile":"+00771234567976902" }, { "username":"newuser2", diff --git a/distributor/src/distributor/tests/sms_publisher_test.bal b/distributor/src/distributor/tests/sms_publisher_test.bal index c2c9429..a530868 100644 --- a/distributor/src/distributor/tests/sms_publisher_test.bal +++ b/distributor/src/distributor/tests/sms_publisher_test.bal @@ -100,7 +100,7 @@ function testSubscriberRegistration() { // Test bulk success registration req = new; req.setFileAsPayload("src/distributor/tests/resources/contact1.json"); - response = httpEndpoint->post("/sms/addall", req); + response = httpEndpoint->post("/sms/all", req); if (response is http:Response) { var result = response.getTextPayload(); if (result is string) { @@ -115,11 +115,11 @@ function testSubscriberRegistration() { // Test bulk registration with invalid nos req = new; req.setFileAsPayload("src/distributor/tests/resources/contact2.json"); - response = httpEndpoint->post("/sms/addall", req); + response = httpEndpoint->post("/sms/all", req); if (response is http:Response) { var result = response.getTextPayload(); if (result is string) { - test:assertEquals(result, "Validation failed: invalid recipient mobile no: newuser1:+00771234562"); + test:assertEquals(result, "Validation failed: invalid recipient mobile no: newuser1:+00771234567976902"); } else { test:assertFail(msg = "Invalid response message:"); } @@ -130,7 +130,7 @@ function testSubscriberRegistration() { // Test bulk registration with malformed JSON req = new; req.setFileAsPayload("src/distributor/tests/resources/contact3.json"); - response = httpEndpoint->post("/sms/addall", req); + response = httpEndpoint->post("/sms/all", req); if (response is http:Response) { var result = response.getTextPayload(); if (result is string) { @@ -156,7 +156,7 @@ function testResetRecipients() { } }); http:Request req = new; - var response = httpEndpoint->delete("/sms/reset", req); + var response = httpEndpoint->delete("/sms/all", req); if (response is http:Response) { var result = response.getTextPayload(); if (result is string) { @@ -182,15 +182,15 @@ function testValidateFunction() { test:assertTrue(validate("+94716181195") == "94716181195", msg = "Failed assertion : 94716181195"); // validate invalid local numbers - error err = validate("07161811948979870"); - string detail = err.detail()?.message; - test:assertTrue(stringutils:contains(detail, "Invalid mobile number. Resend the request as follows: If the " + - "mobile no is 0771234567, send POST request to '/sms' with JSON payload '{\"username\":\"myuser\", " + - "\"mobile\":\"0771234567\"}'")); + //error err = validate("07161811948979870"); + //string detail = err.detail()?.message; + //test:assertTrue(stringutils:contains(detail, "Invalid mobile number. Resend the request as follows: If the " + + // "mobile no is 0771234567, send POST request to '/sms' with JSON payload '{\"username\":\"myuser\", " + + // "\"mobile\":\"0771234567\"}'")); // validate invalid local numbers with non numeric chars - err = validate("07161811AB"); - detail = err.detail()?.message; + error err = validate("07161811AB"); + string detail = err.detail()?.message; test:assertTrue(stringutils:contains(detail, "Invalid mobile number. Given mobile number contains non numeric " + "characters: 07161811AB")); diff --git a/distributor/src/distributor/website.bal b/distributor/src/distributor/website.bal index 5bf5e5a..5de68eb 100644 --- a/distributor/src/distributor/website.bal +++ b/distributor/src/distributor/website.bal @@ -122,8 +122,9 @@ service mediaWebsite on mediaListener { return caller->ok(r.jsonResult); } else if format == "html" { http:Response hr = new; - boolean sorted = (r.jsonResult.'type == RN_SI || r.jsonResult.'type == RN_VS || - r.jsonResult.'type == RN_VSN) ? true : false; + string resultType = r.jsonResult.'type.toString(); + boolean sorted = (resultType == RN_SI || resultType == RN_V || resultType == RN_VS || + resultType == RN_VSN) ? true : false; hr.setTextPayload(<@untainted>check generateHtml(election, r.jsonResult, sorted)); hr.setContentType("text/html"); return caller->ok(hr); diff --git a/distributor/web/active-2020-07-28-II b/distributor/web/active-2020-07-31-I similarity index 100% rename from distributor/web/active-2020-07-28-II rename to distributor/web/active-2020-07-31-I diff --git a/distributor/web/info.txt b/distributor/web/info.txt index d9e108d..0a8d71b 100644 --- a/distributor/web/info.txt +++ b/distributor/web/info.txt @@ -2,15 +2,15 @@ ****** IMPORTANT ******* ** -** The latest version of the subscriber JAR is subscriber-20200728-II.jar +** The latest version of the subscriber JAR is subscriber-20200731-I.jar ** -** Available at https://github.com/ECLK/Results-Dist/releases/tag/v2020-07-28-II +** Available at https://github.com/ECLK/Results-Dist/releases/tag/v2020-07-31-I ** ****** IMPORTANT ******* Run it as follows: -java -jar subscriber-20200728-II.jar [options] +java -jar subscriber-20200731-I.jar [options] where options are: -username=name my username for authentication diff --git a/subscriber/src/subscriber/constants.bal b/subscriber/src/subscriber/constants.bal index c18308e..ae0fd14 100644 --- a/subscriber/src/subscriber/constants.bal +++ b/subscriber/src/subscriber/constants.bal @@ -9,7 +9,7 @@ const LEVEL_NF = "NATIONAL-FINAL"; const WANT_IMAGE = "image=true"; const WANT_AWAIT_RESULTS = "await=true"; -const MY_VERSION = "2020-07-28-II"; +const MY_VERSION = "2020-07-31-I"; const UNDERSOCRE = "_"; const COLON = ":"; @@ -24,8 +24,10 @@ const ELECTION_TYPE_PARLIAMENTARY = "PARLIAMENTARY"; const RP_V = "RP_V"; const RE_VI = "RE_VI"; +const RE_V = "RE_V"; const RE_S = "RE_S"; const RN_SI = "RN_SI"; +const RN_V = "RN_V"; const RN_VS = "RN_VS"; const RN_VSN = "RN_VSN"; const RE_SC = "RE_SC"; diff --git a/subscriber/src/subscriber/genhtml.bal b/subscriber/src/subscriber/genhtml.bal index a5ccde0..30f89f0 100644 --- a/subscriber/src/subscriber/genhtml.bal +++ b/subscriber/src/subscriber/genhtml.bal @@ -93,8 +93,10 @@ function generateParliamentaryResultHtml(string electionCode, map result, " POLLING DIVISION (" + result.pd_code + ") RESULT"; } RE_VI => { resTypeHeading = result.ed_name + " ELECTORAL DISTRICT CUMULATIVE RESULTS AT " + result.timestamp; } + RE_V => { resTypeHeading = result.ed_name + " ELECTORAL DISTRICT VOTES RESULT"; } RE_S => { resTypeHeading = result.ed_name + " ELECTORAL DISTRICT SEAT ALLOCATION RESULT"; } RN_SI => { resTypeHeading = "ALL ISLAND CUMULATIVE SEAT ALLOCATION RESULTS AT " + result.timestamp; } + RN_V => { resTypeHeading = "ALL ISLAND VOTES RESULT"; } RN_VS => { resTypeHeading = "ALL ISLAND VOTES + SEAT ALLOCATION RESULT"; } RN_VSN => { resTypeHeading = "ALL ISLAND VOTES + SEAT ALLOCATION + NATIONAL LIST ALLOCATION RESULT"; } RE_SC => { resTypeHeading = result.ed_name + " ELECTORAL DISTRICT SEATS ALLOCATED CANDIDATES"; } @@ -110,7 +112,7 @@ function generateParliamentaryResultHtml(string electionCode, map result, "Name of Party" + "Party Abbreviaton"; - if ('type == RP_V || 'type == RE_VI || 'type == RN_VS || 'type == RN_VSN) { + if ('type == RP_V || 'type == RE_VI || 'type == RE_V || 'type == RN_V || 'type == RN_VS || 'type == RN_VSN) { body += "Votes Received" + "Percentage"; } @@ -128,7 +130,7 @@ function generateParliamentaryResultHtml(string electionCode, map result, "" + pr.party_name + "" + "" + pr.party_code +""; - if ('type == RP_V || 'type == RE_VI || 'type == RN_VS || 'type == RN_VSN) { + if ('type == RP_V || 'type == RE_VI || 'type == RE_V || 'type == RN_V || 'type == RN_VS || 'type == RN_VSN) { body += "" + commaFormatInt(pr.vote_count) + "" + "" + pr.vote_percentage + ""; } diff --git a/testdriver/src/testdriver/gen_fake_parliamentary.bal b/testdriver/src/testdriver/gen_fake_parliamentary.bal index 7a55820..7e7cd78 100644 --- a/testdriver/src/testdriver/gen_fake_parliamentary.bal +++ b/testdriver/src/testdriver/gen_fake_parliamentary.bal @@ -210,6 +210,46 @@ function genFakeParliamentary() { "electors": 125 } }, + { + "type": "RE_V", + "sequence_number": "0110", + "timestamp": 1420087982.0, + "level": "ELECTORAL-DISTRICT", + "ed_code": "02", + "ed_name": "Gampaha", + "by_party": [ + { + "party_code": "Foo", + "party_name": "Foo foo", + "vote_count": 350, + "vote_percentage": "46.66%", + "seat_count": 0, + "national_list_seat_count": 0 + }, + { + "party_code": "Bar", + "party_name": "Bar bar", + "vote_count": 220, + "vote_percentage": "29.33%", + "seat_count": 0, + "national_list_seat_count": 0 + }, + { + "party_code": "Baz", + "party_name": "Baz baz", + "vote_count": 180, + "vote_percentage": "24.00%", + "seat_count": 0, + "national_list_seat_count": 0 + } + ], + "summary": { + "valid": 750, + "rejected": 50, + "polled": 800, + "electors": 925 + } + }, { "type": "RE_S", "sequence_number": "0120", @@ -218,6 +258,22 @@ function genFakeParliamentary() { "ed_code": "02", "ed_name": "Gampaha", "by_party": [ + { + "party_code": "Foo", + "party_name": "Foo foo", + "vote_count": 0, + "vote_percentage": "0.00%", + "seat_count": 10, + "national_list_seat_count": 0 + }, + { + "party_code": "Bar", + "party_name": "Bar bar", + "vote_count": 0, + "vote_percentage": "0.00%", + "seat_count": 5, + "national_list_seat_count": 0 + }, { "party_code": "Baz", "party_name": "Baz baz", @@ -225,22 +281,48 @@ function genFakeParliamentary() { "vote_percentage": "0.00%", "seat_count": 3, "national_list_seat_count": 0 - }, + } + ] + }, + { + "type": "RE_V", + "sequence_number": "0123", + "timestamp": 1420087991.0, + "level": "ELECTORAL-DISTRICT", + "ed_code": "01", + "ed_name": "Colombo", + "by_party": [ { "party_code": "Foo", "party_name": "Foo foo", - "vote_count": 0, - "vote_percentage": "0.00%", - "seat_count": 10, + "vote_count": 950, + "vote_percentage": "28.35%", + "seat_count": 0, "national_list_seat_count": 0 }, { "party_code": "Bar", "party_name": "Bar bar", - "seat_count": 5, + "vote_count": 2220, + "vote_percentage": "66.26%", + "seat_count": 0, + "national_list_seat_count": 0 + }, + { + "party_code": "Baz", + "party_name": "Baz baz", + "vote_count": 180, + "vote_percentage": "05.37%", + "seat_count": 0, "national_list_seat_count": 0 } - ] + ], + "summary": { + "valid": 3350, + "rejected": 250, + "polled": 3500, + "electors": 765 + } }, { "type": "RE_S", @@ -269,14 +351,54 @@ function genFakeParliamentary() { { "party_code": "Baz", "party_name": "Baz baz", + "vote_count": 0, + "vote_percentage": "0.00%", "seat_count": 1, "national_list_seat_count": 0 } ] }, + { + "type": "RN_V", + "sequence_number": "0126", + "timestamp": 1420087998.0, + "level": "NATIONAL", + "by_party": [ + { + "party_code": "Bar", + "party_name": "Bar bar", + "vote_count": 12540, + "vote_percentage": "32.79%", + "seat_count": 0, + "national_list_seat_count": 0 + }, + { + "party_code": "Baz", + "party_name": "Baz baz", + "vote_count": 7500, + "vote_percentage": "19.61%", + "seat_count": 0, + "national_list_seat_count": 0 + }, + { + "party_code": "Foo", + "party_name": "Foo foo", + "vote_count": 18200, + "vote_percentage": "47.59%", + "seat_count": 0, + "national_list_seat_count": 0 + } + ], + "summary": { + "valid": 38240, + "rejected": 300, + "polled": 38540, + "electors": 40000 + } + }, { "type": "RN_VS", - "sequence_number": "0125", + "sequence_number": "0127", "timestamp": 1420087998.0, "level": "NATIONAL", "by_party": [ @@ -314,7 +436,7 @@ function genFakeParliamentary() { }, { "type": "RN_VSN", - "sequence_number": "0127", + "sequence_number": "0128", "timestamp": 1420088001.0, "level": "NATIONAL", "by_party": [ @@ -362,7 +484,8 @@ function genFakeParliamentary() { "party_code": "Foo", "party_name": "Foo foo", "candidate_number": "12", - "candidate_name": "Lorem Ipsum" + "candidate_name": "Lorem Ipsum", + "candidate_type" : "Normal" }, { "party_code": "Bar", @@ -384,7 +507,8 @@ function genFakeParliamentary() { "party_code": "Bar", "party_name": "Bar bar", "candidate_number": "15", - "candidate_name": "Baz Qux" + "candidate_name": "Baz Qux", + "candidate_type" : "National List" } ] }, diff --git a/testdriver/src/testdriver/sendparliamentaryresults.bal b/testdriver/src/testdriver/sendparliamentaryresults.bal index c44d1bc..e86d502 100644 --- a/testdriver/src/testdriver/sendparliamentaryresults.bal +++ b/testdriver/src/testdriver/sendparliamentaryresults.bal @@ -5,7 +5,9 @@ import ballerina/runtime; import ballerina/time; const RP_V = "RP_V"; +const RE_V = "RE_V"; const RE_S = "RE_S"; +const RN_V = "RN_V"; const RN_VS = "RN_VS"; const RN_VSN = "RN_VSN"; const RE_SC = "RE_SC"; @@ -25,10 +27,20 @@ function sendParliamentaryResults(string electionCode, http:Client rc, map check updateSummary(result); check feedResult(rc, electionCode, resultType, result.pd_code.toString(), result); } + RE_V => { + check updateByParty(result.by_party); + check updateSummary(result); + check feedResult(rc, electionCode, resultType, result.ed_code.toString(), result); + } RE_S => { check updateByParty(result.by_party); check feedResult(rc, electionCode, resultType, result.ed_code.toString(), result); } + RN_V => { + check updateByParty(result.by_party); + check updateSummary(result); + check feedResult(rc, electionCode, resultType, FINAL, result); + } RN_VS => { check updateByParty(result.by_party); check updateSummary(result); @@ -78,8 +90,8 @@ function updateSummary(map result) returns error? { } -function feedResult (http:Client hc, string electionCode, string resType, string resCode, map result) returns -error? { +function feedResult(http:Client hc, string electionCode, string resType, string resCode, map result) returns + error? { // reset time stamp of the result to now result["timestamp"] = check time:format(time:currentTime(), "yyyy-MM-dd'T'HH:mm:ss.SSSZ"); http:Response hr;