From 0342eb50c845e51c10b67fa5acfaed6964899379 Mon Sep 17 00:00:00 2001 From: rrandomsky Date: Thu, 15 Dec 2022 09:17:15 +0100 Subject: [PATCH] [MOS-737] Fix for adding a country code prefix to existing contact Adding or removing country code from existing contacts number is changing now number record itself, exactly when changed number is placed in DB, instead to create new number record, to avoid miss match during matching numbers. --- .../windows/PhonebookNewContact.cpp | 10 +- .../windows/PhonebookNewContact.hpp | 5 +- module-db/Interface/ContactRecord.cpp | 44 ++++++-- module-db/Interface/ContactRecord.hpp | 11 +- module-db/tests/ContactsRecord_tests.cpp | 106 +++++++++++++++++- module-services/service-db/DBServiceAPI.cpp | 11 +- .../include/service-db/DBContactMessage.hpp | 38 ++++++- .../include/service-db/DBServiceAPI.hpp | 5 +- .../service-db/messages/DBContactMessage.cpp | 9 ++ .../phonenumber/NumberHolderMatcher.hpp | 11 +- .../tests/unittest_numbermatcher.cpp | 17 ++- products/PurePhone/services/db/ServiceDB.cpp | 18 +++ pure_changelog.md | 1 + source/MessageType.hpp | 5 +- 14 files changed, 258 insertions(+), 33 deletions(-) diff --git a/module-apps/application-phonebook/windows/PhonebookNewContact.cpp b/module-apps/application-phonebook/windows/PhonebookNewContact.cpp index 679d2268d2f9b2a6d94b6dfb1fef6b1d303f16b3..8c923e156dad4b35dc252cae42288a681546495f 100644 --- a/module-apps/application-phonebook/windows/PhonebookNewContact.cpp +++ b/module-apps/application-phonebook/windows/PhonebookNewContact.cpp @@ -149,10 +149,10 @@ namespace gui case DBServiceAPI::ContactVerificationResult::emptyContact: return false; case DBServiceAPI::ContactVerificationResult::primaryNumberDuplicate: - showDialogDuplicatedNumber(contact->numbers[0].number); + showDialogDuplicatedNumber(contact->numbers[0].number, contact->ID); return false; case DBServiceAPI::ContactVerificationResult::secondaryNumberDuplicate: - showDialogDuplicatedNumber(contact->numbers[1].number); + showDialogDuplicatedNumber(contact->numbers[1].number, contact->ID); return false; case DBServiceAPI::ContactVerificationResult::speedDialDuplicate: showDialogDuplicatedSpeedDialNumber(); @@ -191,9 +191,11 @@ namespace gui return true; } // namespace gui - void PhonebookNewContact::showDialogDuplicatedNumber(const utils::PhoneNumber::View &duplicatedNumber) + void PhonebookNewContact::showDialogDuplicatedNumber(const utils::PhoneNumber::View &duplicatedNumber, + const std::uint32_t duplicatedNumberContactID) { - auto matchedContact = DBServiceAPI::MatchContactByPhoneNumber(application, duplicatedNumber); + auto matchedContact = + DBServiceAPI::MatchContactByPhoneNumber(application, duplicatedNumber, duplicatedNumberContactID); auto oldContactRecord = (matchedContact != nullptr) ? *matchedContact : ContactRecord{}; auto metaData = std::make_unique( gui::DialogMetadata{duplicatedNumber.getFormatted(), diff --git a/module-apps/application-phonebook/windows/PhonebookNewContact.hpp b/module-apps/application-phonebook/windows/PhonebookNewContact.hpp index 1c39a61d901f65a1d23042db12a690b553c3e0eb..69c6636d6732b0a00639b89646bf4dc7a281f2d0 100644 --- a/module-apps/application-phonebook/windows/PhonebookNewContact.hpp +++ b/module-apps/application-phonebook/windows/PhonebookNewContact.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once @@ -35,7 +35,8 @@ namespace gui }; auto verifyAndSave() -> bool; - void showDialogDuplicatedNumber(const utils::PhoneNumber::View &duplicatedNumber); + void showDialogDuplicatedNumber(const utils::PhoneNumber::View &duplicatedNumber, + const std::uint32_t duplicatedNumberContactID = 0u); void showDialogDuplicatedSpeedDialNumber(); void setSaveButtonVisible(bool visible); diff --git a/module-db/Interface/ContactRecord.cpp b/module-db/Interface/ContactRecord.cpp index 9573489739438284af63cbd11fa4fad58598e88e..b4d693d5d91476518865bf6d4ae26545c8fac0e2 100644 --- a/module-db/Interface/ContactRecord.cpp +++ b/module-db/Interface/ContactRecord.cpp @@ -123,10 +123,37 @@ auto ContactRecordInterface::Update(const ContactRecord &rec) -> bool return false; } - auto oldNumberIDs = splitNumberIDs(contact.numbersID); - auto newNumbersIDs = getNumbersIDs(contact.ID, rec); + auto oldNumberIDs = splitNumberIDs(contact.numbersID); + + /* Changing number table record in place if new number is same as old number but with/without country code */ + auto numberMatcher = buildNumberMatcher(NumberMatcherPageSize); + for (const auto oldNumberID : oldNumberIDs) { // pick one of the old number for this contactID (from DB) + auto numberRecord = contactDB->number.getById(oldNumberID); + utils::PhoneNumber oldPhoneNumber(numberRecord.numberUser, numberRecord.numbere164); + for (const auto &newNumberID : rec.numbers) { // pick one of the new number from &rec + utils::PhoneNumber newPhoneNumber(newNumberID.number); + // if DB have not such a new number already and if one of this have country code and other doesn't + if (!numberMatcher.bestMatch(newPhoneNumber, utils::PhoneNumber::Match::EXACT).has_value() && + (newPhoneNumber.match(oldPhoneNumber) == utils::PhoneNumber::Match::POSSIBLE) && + ((!oldPhoneNumber.isValid() && newPhoneNumber.isValid()) || + (oldPhoneNumber.isValid() && !newPhoneNumber.isValid()))) { + // which means that only country code is to add or remove (change of country code is not supported here) + // then change old number record in number table to the new number + auto oldNumberRecordToUpdate = contactDB->number.getById(oldNumberID); + oldNumberRecordToUpdate.numberUser = newPhoneNumber.get(); + oldNumberRecordToUpdate.numbere164 = newPhoneNumber.toE164(); + if (!contactDB->number.update(oldNumberRecordToUpdate)) { + return false; + } + } + } + } + + auto newNumbersIDs = getNumbersIDs(contact.ID, rec, utils::PhoneNumber::Match::EXACT); for (auto oldNumberID : oldNumberIDs) { if (std::find(std::begin(newNumbersIDs), std::end(newNumbersIDs), oldNumberID) == std::end(newNumbersIDs)) { + // If any oldNumberID is NOT one of the newNumbersID, which will be assigned to this contact, then + // make temporary contact with this oldNumberID auto numberRecord = contactDB->number.getById(oldNumberID); if (!numberRecord.isValid()) { return false; @@ -141,6 +168,7 @@ auto ContactRecordInterface::Update(const ContactRecord &rec) -> bool e.what()); return false; } + // make temporary contact with old number const auto tmpContactRecord = addTemporaryContactForNumber(number); if (!tmpContactRecord.has_value()) { return false; @@ -195,8 +223,9 @@ auto ContactRecordInterface::Update(const ContactRecord &rec) -> bool return true; } -auto ContactRecordInterface::getNumbersIDs(std::uint32_t contactID, const ContactRecord &contact) - -> std::vector +auto ContactRecordInterface::getNumbersIDs(std::uint32_t contactID, + const ContactRecord &contact, + utils::PhoneNumber::Match matchLevel) -> std::vector { std::vector result; @@ -213,7 +242,7 @@ auto ContactRecordInterface::getNumbersIDs(std::uint32_t contactID, const Contac return {}; } - auto numberMatch = numberMatcher.bestMatch(phoneNumber, utils::PhoneNumber::Match::POSSIBLE); + auto numberMatch = numberMatcher.bestMatch(phoneNumber, matchLevel); if (!numberMatch.has_value()) { // number does not exist in the DB yet. Let's add it. if (!contactDB->number.add(ContactsNumberTableRow{Record(DB_ID_NONE), @@ -1211,7 +1240,8 @@ auto ContactRecordInterface::buildNumberMatcher(unsigned int maxPageSize) auto ContactRecordInterface::MatchByNumber(const utils::PhoneNumber::View &numberView, CreateTempContact createTempContact, - utils::PhoneNumber::Match matchLevel) + utils::PhoneNumber::Match matchLevel, + const std::uint32_t contactIDToIgnore) -> std::optional { utils::PhoneNumber phoneNumber; @@ -1225,7 +1255,7 @@ auto ContactRecordInterface::MatchByNumber(const utils::PhoneNumber::View &numbe } auto numberMatcher = buildNumberMatcher(NumberMatcherPageSize); - auto matchedNumber = numberMatcher.bestMatch(phoneNumber, matchLevel); + auto matchedNumber = numberMatcher.bestMatch(phoneNumber, matchLevel, contactIDToIgnore); if (!matchedNumber.has_value()) { if (createTempContact != CreateTempContact::True) { return std::nullopt; diff --git a/module-db/Interface/ContactRecord.hpp b/module-db/Interface/ContactRecord.hpp index bc2243b62e65f39f58082c7a3f5e5276116075d5..773edf0c9f801f558fc15b570bfff2d3909fc65b 100644 --- a/module-db/Interface/ContactRecord.hpp +++ b/module-db/Interface/ContactRecord.hpp @@ -206,9 +206,9 @@ class ContactRecordInterface : public RecordInterface std::optional; auto MatchByNumber(const utils::PhoneNumber::View &numberView, - CreateTempContact createTempContact = CreateTempContact::False, - utils::PhoneNumber::Match matchLevel = utils::PhoneNumber::Match::POSSIBLE) - -> std::optional; + CreateTempContact createTempContact = CreateTempContact::False, + utils::PhoneNumber::Match matchLevel = utils::PhoneNumber::Match::POSSIBLE, + const std::uint32_t contactIDToIgnore = 0u) -> std::optional; auto GetBySpeedDial(const UTF8 &speedDial) -> std::unique_ptr>; @@ -289,7 +289,10 @@ class ContactRecordInterface : public RecordInterface const std::unique_ptr; auto addTemporaryContactForNumber(const ContactRecord::Number &number) -> std::optional; - auto getNumbersIDs(std::uint32_t contactID, const ContactRecord &contact) -> std::vector; + auto getNumbersIDs(std::uint32_t contactID, + const ContactRecord &contact, + utils::PhoneNumber::Match matchLevel = utils::PhoneNumber::Match::POSSIBLE) + -> std::vector; auto addNumbers(std::uint32_t contactID, const std::vector &numbers) -> std::optional; auto addOrUpdateName(std::uint32_t contactID, std::uint32_t nameID, const ContactRecord &contact) diff --git a/module-db/tests/ContactsRecord_tests.cpp b/module-db/tests/ContactsRecord_tests.cpp index 5242e240eac19497c7815e3a38c2a855af05e758..0186c7e232cdc4b5256b0e4c51f5626eaf81c287 100644 --- a/module-db/tests/ContactsRecord_tests.cpp +++ b/module-db/tests/ContactsRecord_tests.cpp @@ -264,7 +264,12 @@ TEST_CASE("Contact record numbers update") auto records = ContactRecordInterface(&contactDB); ContactRecord testRecord, otherRecord; - std::array numbers = {{{"600100100"}, {"600100200"}, {"600100300"}, {"600100400"}}}; + std::array numbers = {{{"600100100"}, {"600100200"}, {"600100300"}, {"600100400"}}}; + std::array numbersPL = { + {{"+48600100100"}, {"+48600100200"}, {"+48600100300"}, {"+48600100400"}}}; // Poland country code + std::array numbersFR = { + {{"+33600100100"}, {"+33600100200"}, {"+33600100300"}, {"+33600100400"}}}; // France country code + std::array unUsedNumbers = {{{"612130140"}, {"612130141"}}}; testRecord.primaryName = "number"; testRecord.alternativeName = "test"; @@ -369,6 +374,105 @@ TEST_CASE("Contact record numbers update") REQUIRE(validatationRecord.numbers[0].number.getEntered() == numbers[3]); } + SECTION("Single number update - adding country code") + { + auto newRecord = records.GetByID(1); + REQUIRE(newRecord.numbers.size() == 2); + + newRecord.numbers = std::vector({ContactRecord::Number(numbersPL[0], std::string("")), + ContactRecord::Number(numbersFR[1], std::string(""))}); + REQUIRE(records.Update(newRecord)); + REQUIRE(contactDB.number.count() == 4); + + auto validationRecord = records.GetByID(1); + REQUIRE(validationRecord.numbers.size() == 2); + REQUIRE(validationRecord.numbers[0].number.getEntered() == numbersPL[0]); + REQUIRE(validationRecord.numbers[1].number.getEntered() == numbersFR[1]); + + validationRecord = records.GetByID(2); + REQUIRE(validationRecord.numbers.size() == 2); + REQUIRE(validationRecord.numbers[0].number.getEntered() == numbers[2]); + + // There is no new temporary contact + validationRecord = records.GetByIdWithTemporary(3); + REQUIRE(validationRecord.ID == DB_ID_NONE); + REQUIRE(validationRecord.numbers.empty()); + } + + SECTION("Single number update - removing country code") + { + auto newRecord = records.GetByID(1); + REQUIRE(newRecord.numbers.size() == 2); + + // add country code + newRecord.numbers = std::vector({ContactRecord::Number(numbersPL[0], std::string("")), + ContactRecord::Number(numbersFR[1], std::string(""))}); + REQUIRE(records.Update(newRecord)); + REQUIRE(contactDB.number.count() == 4); + + // deleting country code + newRecord.numbers = std::vector( + {ContactRecord::Number(numbers[0], std::string("")), ContactRecord::Number(numbers[1], std::string(""))}); + REQUIRE(records.Update(newRecord)); + REQUIRE(contactDB.number.count() == 4); + + auto validationRecord = records.GetByID(1); + REQUIRE(validationRecord.numbers.size() == 2); + REQUIRE(validationRecord.numbers[0].number.getEntered() == numbers[0]); + REQUIRE(validationRecord.numbers[1].number.getEntered() == numbers[1]); + + validationRecord = records.GetByID(2); + REQUIRE(validationRecord.numbers.size() == 2); + REQUIRE(validationRecord.numbers[0].number.getEntered() == numbers[2]); + + // There is no new temporary contact + validationRecord = records.GetByIdWithTemporary(3); + REQUIRE(validationRecord.ID == DB_ID_NONE); + REQUIRE(validationRecord.numbers.empty()); + } + + SECTION("Single number update - changing country code") + { + auto newRecord = records.GetByID(1); + REQUIRE(newRecord.numbers.size() == 2); + + // add country code (PL) + newRecord.numbers = std::vector({ContactRecord::Number(numbersPL[0], std::string("")), + ContactRecord::Number(numbersPL[1], std::string(""))}); + REQUIRE(records.Update(newRecord)); + REQUIRE(contactDB.number.count() == 4); + + // changing country code (to FR) + newRecord.numbers = std::vector({ContactRecord::Number(numbersFR[0], std::string("")), + ContactRecord::Number(numbersFR[1], std::string(""))}); + REQUIRE(records.Update(newRecord)); + REQUIRE(contactDB.number.count() == 6); + REQUIRE(contactDB.number.getById(1).contactID != 1); // old numbers do not belong to any contact + REQUIRE(contactDB.number.getById(1).contactID != 2); + REQUIRE(contactDB.number.getById(2).contactID != 1); + REQUIRE(contactDB.number.getById(2).contactID != 2); + + auto validationRecord = records.GetByID(1); + REQUIRE(validationRecord.numbers.size() == 2); + REQUIRE(validationRecord.numbers[0].number.getEntered() == numbersFR[0]); + REQUIRE(validationRecord.numbers[1].number.getEntered() == numbersFR[1]); + + validationRecord = records.GetByID(2); + REQUIRE(validationRecord.numbers.size() == 2); + REQUIRE(validationRecord.numbers[0].number.getEntered() == numbers[2]); + + // A temporary contact for number ID 1 (which was previously assigned to recordID=1) has been created. + validationRecord = records.GetByIdWithTemporary(3); + REQUIRE(validationRecord.ID != DB_ID_NONE); + REQUIRE(validationRecord.numbers[0].number.getEntered() == numbersPL[0]); + + // A temporary contact for numberID 2 (which was previously assigned to recordID=2 for a moment) has been + // created. + validationRecord = records.GetByIdWithTemporary(4); + REQUIRE(validationRecord.ID != DB_ID_NONE); + REQUIRE(validationRecord.numbers[0].number.getEntered() == numbersPL[1]); + } + SECTION("Change both numbers") { auto newRecord = records.GetByID(1); diff --git a/module-services/service-db/DBServiceAPI.cpp b/module-services/service-db/DBServiceAPI.cpp index 139fbf80574115579e2c92e7daa9f68026108688..df9645745cb8f0124622fe37188b27d31b949c2c 100644 --- a/module-services/service-db/DBServiceAPI.cpp +++ b/module-services/service-db/DBServiceAPI.cpp @@ -68,10 +68,11 @@ auto DBServiceAPI::ContactGetBySpeeddial(sys::Service *serv, UTF8 speeddial) return ContactGetByIDCommon(serv, msg); } -auto DBServiceAPI::MatchContactByPhoneNumber(sys::Service *serv, const utils::PhoneNumber::View &numberView) - -> std::unique_ptr +auto DBServiceAPI::MatchContactByPhoneNumber(sys::Service *serv, + const utils::PhoneNumber::View &numberView, + const std::uint32_t contactIDToOmit) -> std::unique_ptr { - auto msg = std::make_shared(numberView); + auto msg = std::make_shared(numberView, contactIDToOmit); auto ret = serv->bus.sendUnicastSync(std::move(msg), service::name::db, DefaultTimeoutInMs); auto contactResponse = dynamic_cast(ret.second.get()); @@ -139,8 +140,8 @@ auto DBServiceAPI::verifyContact(sys::Service *serv, const ContactRecord &rec) } if (rec.numbers.size() > 0 && rec.numbers[0].number.getEntered().size() > 0) { - auto retPhone1 = MatchContactByPhoneNumber(serv, rec.numbers[0].number); - if (retPhone1 && retPhone1->ID != rec.ID) { + auto retPhone1 = MatchContactByPhoneNumber(serv, rec.numbers[0].number, rec.ID); + if (retPhone1) { if (retPhone1->isTemporary()) { return ContactVerificationResult::temporaryContactExists; } diff --git a/module-services/service-db/include/service-db/DBContactMessage.hpp b/module-services/service-db/include/service-db/DBContactMessage.hpp index 1bca74a81df0fc8804551bbf9ef5ed5360731111..a1b087ede3ff13e38e3381695cbe8e184608e6d1 100644 --- a/module-services/service-db/include/service-db/DBContactMessage.hpp +++ b/module-services/service-db/include/service-db/DBContactMessage.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once @@ -61,6 +61,42 @@ class DBContactNumberMessage : public sys::DataMessage utils::PhoneNumber::View numberView; }; +/** + * @brief Message used to match Contact by an instance of PhoneNumber::View while omitting the specific contactID. + * Omitting specific Contact during searching is helpful to ignore the number which is already signed to Contact + * that we want to find a matching number for + * + */ +class DBMatchContactNumberBesidesOfContactIDMessage : public sys::DataMessage +{ + public: + /** + * @brief Construct a new DBMatchContactNumberBesidesOfContactIDMessage object + * + * @param numberView - a number to match with + */ + + DBMatchContactNumberBesidesOfContactIDMessage(const utils::PhoneNumber::View &numberView, + std::uint32_t contactIDToOmit); + /** + * @brief Destroy the DBMatchContactNumberBesidesOfContactIDMessage object + * + */ + virtual ~DBMatchContactNumberBesidesOfContactIDMessage(); + + /** + * @brief number to match with + * + */ + utils::PhoneNumber::View numberView; + + /** + * @brief numbers connected with this contact Id are omitting during the searching + * + */ + std::uint32_t contactIDToOmit; +}; + /** * @brief A response to DBContactNumberMessage - returns an instance of a ContactRecord matched by provided * PhoneNumber::View diff --git a/module-services/service-db/include/service-db/DBServiceAPI.hpp b/module-services/service-db/include/service-db/DBServiceAPI.hpp index 192291a9eb25bff0722ba092a6170e692b59a796..b3b1a8e9cec6ae14cae74ac7d7f87aa606c2223a 100644 --- a/module-services/service-db/include/service-db/DBServiceAPI.hpp +++ b/module-services/service-db/include/service-db/DBServiceAPI.hpp @@ -92,9 +92,12 @@ class DBServiceAPI * * @param serv - calling service * @param numberView - number to match contact with + * @param contactIDToOmit - for this contact ID the match will be ignored * @return std::unique_ptr */ - [[deprecated]] static auto MatchContactByPhoneNumber(sys::Service *serv, const utils::PhoneNumber::View &numberView) + [[deprecated]] static auto MatchContactByPhoneNumber(sys::Service *serv, + const utils::PhoneNumber::View &numberView, + const std::uint32_t contactIDToOmit = 0u) -> std::unique_ptr; [[deprecated]] static auto MatchContactByNumberID(sys::Service *serv, std::uint32_t numberID) -> std::unique_ptr; diff --git a/module-services/service-db/messages/DBContactMessage.cpp b/module-services/service-db/messages/DBContactMessage.cpp index 80bb2ceeb704ef8fdc4ab2adb8379d059af69671..12838f6dd645a3362acd5678d3d5b46577338367 100644 --- a/module-services/service-db/messages/DBContactMessage.cpp +++ b/module-services/service-db/messages/DBContactMessage.cpp @@ -36,6 +36,15 @@ DBContactNumberMessage::DBContactNumberMessage(const utils::PhoneNumber::View &n DBContactNumberMessage::~DBContactNumberMessage() {} +DBMatchContactNumberBesidesOfContactIDMessage::DBMatchContactNumberBesidesOfContactIDMessage( + const utils::PhoneNumber::View &numberView, std::uint32_t contactIDToOmit) + : sys::DataMessage(MessageType::DBMatchContactNumberBesidesOfContactID), numberView(numberView), + contactIDToOmit(contactIDToOmit) +{} + +DBMatchContactNumberBesidesOfContactIDMessage::~DBMatchContactNumberBesidesOfContactIDMessage() +{} + DBContactNumberResponseMessage::DBContactNumberResponseMessage(sys::ReturnCodes retCode, std::unique_ptr contact) : sys::ResponseMessage(retCode, MessageType::DBContactMatchByNumber), contact(std::move(contact)) diff --git a/module-utils/phonenumber/NumberHolderMatcher.hpp b/module-utils/phonenumber/NumberHolderMatcher.hpp index ebb7faba125ca1bfdfab1affcdacce71ee77fe3b..0e4b0dabd09e1d7f8f9781c71d9c973fbe1aa1d2 100644 --- a/module-utils/phonenumber/NumberHolderMatcher.hpp +++ b/module-utils/phonenumber/NumberHolderMatcher.hpp @@ -58,10 +58,12 @@ namespace utils * * @param other - number to match with * @param level - minimum acceptable match level + * @param contactIDToIgnore - for this contact ID the match will be ignored * @return Best match for the other phone number */ std::optional bestMatch(const PhoneNumber &phoneNumber, - PhoneNumber::Match level = PhoneNumber::Match::EXACT) + PhoneNumber::Match level = PhoneNumber::Match::EXACT, + const std::uint32_t contactIDToIgnore = 0u) { utils::time::Scoped t{"bestMatch()"}; // if empty string, do not try to match, simply return @@ -71,9 +73,10 @@ namespace utils restartFor(phoneNumber); do { - const auto it = - std::find_if(numbers.cbegin(), numbers.cend(), [&phoneNumber, level](const auto &number) { - return phoneNumber.match(number.getNumber()) >= level; + const auto it = std::find_if( + numbers.cbegin(), numbers.cend(), [&phoneNumber, level, contactIDToIgnore](const auto &number) { + return (phoneNumber.match(number.getNumber()) >= level) && + (number.getContactID() != contactIDToIgnore); }); if (it != numbers.cend()) { return *it; diff --git a/module-utils/phonenumber/tests/unittest_numbermatcher.cpp b/module-utils/phonenumber/tests/unittest_numbermatcher.cpp index bb22d52c9b85b5b4c45abb4775138dc5d9f0d36c..9cc7bba805ac1d780ac6ec6c074dac74ac26adb7 100644 --- a/module-utils/phonenumber/tests/unittest_numbermatcher.cpp +++ b/module-utils/phonenumber/tests/unittest_numbermatcher.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include @@ -16,15 +16,26 @@ using namespace utils; class DummyHolder { PhoneNumber number; + static std::uint32_t dummyHolderCount; // init by 0 + std::uint32_t contactID; public: - DummyHolder(const PhoneNumber &number) : number(number) - {} + DummyHolder(const PhoneNumber &number, const std::uint32_t contactID = 0u) : number(number), contactID(contactID) + { + if (contactID == 0) + this->contactID = ++dummyHolderCount; + } const PhoneNumber &getNumber() const { return number; } + + const decltype(contactID) &getContactID() const + { + return contactID; + } }; +std::uint32_t DummyHolder::dummyHolderCount = 0u; static constexpr auto DefaultPageSize = 1; // so the paging mechanism is checked. diff --git a/products/PurePhone/services/db/ServiceDB.cpp b/products/PurePhone/services/db/ServiceDB.cpp index b441013578ebeadf5516f86ac1e3bd7c19a18c77..289fc1583f823c4ef94336daf6e2604e5ead2bf2 100644 --- a/products/PurePhone/services/db/ServiceDB.cpp +++ b/products/PurePhone/services/db/ServiceDB.cpp @@ -133,6 +133,24 @@ sys::MessagePointer ServiceDB::DataReceivedHandler(sys::DataMessage *msgl, sys:: } } break; + case MessageType::DBMatchContactNumberBesidesOfContactID: { + auto time = utils::time::Scoped("DBMatchContactNumberBesidesOfContactID"); + auto *msg = dynamic_cast(msgl); + auto ret = contactRecordInterface->MatchByNumber(msg->numberView, + ContactRecordInterface::CreateTempContact::False, + utils::PhoneNumber::Match::POSSIBLE, + msg->contactIDToOmit); + + if (ret.has_value()) { + responseMsg = std::make_shared( + sys::ReturnCodes::Success, std::make_unique(std::move(ret->contact))); + } + else { + responseMsg = std::make_shared(sys::ReturnCodes::Success, + std::unique_ptr()); + } + } break; + case MessageType::DBContactMatchByNumberID: { auto time = utils::time::Scoped("DBContactMatchByNumberID"); auto *msg = dynamic_cast(msgl); diff --git a/pure_changelog.md b/pure_changelog.md index 460b66e6a0adcb737fea209b3f85dcb823298962..4b7d11a5e12715c71382d21da7f7661976d93f86 100644 --- a/pure_changelog.md +++ b/pure_changelog.md @@ -9,6 +9,7 @@ * Fixed looping on the SIM card selection screen * Fixed notes paste option showing for empty clipboard * Fixed notes window title +* Fixed adding and deleting country code prefix to existing contact ### Added diff --git a/source/MessageType.hpp b/source/MessageType.hpp index 0a579123ce125aa65e0e4eb246cd308d055def15..7ba18c5fcb017192e19053d1f94245350a4405ea 100644 --- a/source/MessageType.hpp +++ b/source/MessageType.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once @@ -26,6 +26,9 @@ enum class MessageType DBContactMatchByNumberID [[deprecated]], DBContactMatchByNumber [[deprecated]], ///< used to best match with a single contact using a phone number (primary or secondary) + DBMatchContactNumberBesidesOfContactID + [[deprecated]], ///< used to best match with a single contact using a phone number (primary or secondary) + ///< but witch omitting specific contact ID DBContactAdd [[deprecated]], ///< Add contact record DBContactRemove [[deprecated]], ///< Remove contact remove DBContactUpdate [[deprecated]], ///< Update contact remove