diff --git a/CTRTests/Infrastrucure/Services/MappingManagerTests.swift b/CTRTests/Infrastrucure/Services/MappingManagerTests.swift index 77d551fab..34ec59fd1 100644 --- a/CTRTests/Infrastrucure/Services/MappingManagerTests.swift +++ b/CTRTests/Infrastrucure/Services/MappingManagerTests.swift @@ -468,7 +468,14 @@ class MappingManagerTests: XCTestCase { // Given remoteConfigManagerSpy.stubbedStoredConfiguration.hpkCodes = [ - HPKData(code: "Test", name: "Test Corona Check", vp: "vp", mp: "mp", ma: "ma") + HPKData( + code: "Test", + name: "Test Corona Check", + displayName: "DisplayName", + vaccineOrProphylaxis: "vp", + medicalProduct: "mp", + marketingAuthorizationHolder: "ma" + ) ] sut = MappingManager(remoteConfigManager: remoteConfigManagerSpy) @@ -478,16 +485,23 @@ class MappingManagerTests: XCTestCase { // Then expect(mapped?.name) == "Test Corona Check" expect(mapped?.code) == "Test" - expect(mapped?.vp) == "vp" - expect(mapped?.mp) == "mp" - expect(mapped?.ma) == "ma" + expect(mapped?.vaccineOrProphylaxis) == "vp" + expect(mapped?.medicalProduct) == "mp" + expect(mapped?.marketingAuthorizationHolder) == "ma" } func test_getHpkData_missingMapping() { // Given remoteConfigManagerSpy.stubbedStoredConfiguration.hpkCodes = [ - HPKData(code: "Test", name: "Test Corona Check", vp: "vp", mp: "mp", ma: "ma") + HPKData( + code: "Test", + name: "Test Corona Check", + displayName: "DisplayName", + vaccineOrProphylaxis: "vp", + medicalProduct: "mp", + marketingAuthorizationHolder: "ma" + ) ] sut = MappingManager(remoteConfigManager: remoteConfigManagerSpy) diff --git a/CTRTests/Interface/Holder/Event/Details/RemoteEventDetailsGeneratorTest.swift b/CTRTests/Interface/Holder/Event/Details/RemoteEventDetailsGeneratorTest.swift index 5bb3db7dc..56edf87b9 100644 --- a/CTRTests/Interface/Holder/Event/Details/RemoteEventDetailsGeneratorTest.swift +++ b/CTRTests/Interface/Holder/Event/Details/RemoteEventDetailsGeneratorTest.swift @@ -129,6 +129,44 @@ class EventDetailsGeneratorTest: XCTestCase { expect(details[11].value) == "1234" } + func testVaccinationDetailsGenerator_withHPKCode() { + + // Given + let identity = EventFlow.Identity.fakeIdentity + let event = EventFlow.Event.vaccinationEventWithHPKCode + environmentSpies.mappingManagerSpy.stubbedGetVaccinationBrandResult = "Pfizer (Comirnaty)" + environmentSpies.mappingManagerSpy.stubbedGetVaccinationTypeResult = "SARS-CoV-2 mRNA vaccine" + environmentSpies.mappingManagerSpy.stubbedGetVaccinationManufacturerResult = "Biontech" + environmentSpies.mappingManagerSpy.stubbedGetDisplayCountryResult = "NL" + environmentSpies.mappingManagerSpy.stubbedGetHpkDataResult = HPKData( + code: "1234", + name: "Test", + displayName: "Vaccination Product Name", + vaccineOrProphylaxis: "vp", + medicalProduct: "mp", + marketingAuthorizationHolder: "ma" + ) + + // When + let details = VaccinationDetailsGenerator.getDetails(identity: identity, event: event, providerIdentifier: "CC") + + // Then + expect(details).to(haveCount(13)) + expect(details[0].value) == nil + expect(details[1].value) == "Check, Corona" + expect(details[2].value) == "16 mei 1980" + expect(details[3].value) == L.holderEventAboutVaccinationPathogenvalue() + expect(details[4].value) == "Pfizer (Comirnaty)" + expect(details[5].value) == "Vaccination Product Name" + expect(details[6].value) == "SARS-CoV-2 mRNA vaccine" + expect(details[7].value) == "Biontech" + expect(details[8].value) == "1 van 2" + expect(details[9].value) == nil + expect(details[10].value) == "16 mei 2021" + expect(details[11].value) == "NL" + expect(details[12].value) == "1234" + } + func testVaccinationAssessmentDetailsGenerator() { // Given diff --git a/CTRTests/Utils/Fakes.swift b/CTRTests/Utils/Fakes.swift index 6ff19996c..8d1e9e387 100644 --- a/CTRTests/Utils/Fakes.swift +++ b/CTRTests/Utils/Fakes.swift @@ -1064,6 +1064,32 @@ extension EventFlow.Event { ) } + static var vaccinationEventWithHPKCode: EventFlow.Event { + EventFlow.Event( + type: "vaccination", + unique: "1234", + isSpecimen: true, + vaccination: EventFlow.VaccinationEvent( + dateString: "2021-05-16", + hpkCode: "1234", + type: nil, + manufacturer: "ORG-100030215", + brand: "EU/1/20/1528", + doseNumber: 1, + totalDoses: 2, + country: "NLD", + completedByMedicalStatement: nil, + completedByPersonalStatement: nil, + completionReason: nil + ), + negativeTest: nil, + positiveTest: nil, + recovery: nil, + dccEvent: nil, + vaccinationAssessment: nil + ) + } + static var boosterEvent: EventFlow.Event { EventFlow.Event( type: "vaccination", diff --git a/Localizations/Holder/en.lproj/Localizable.strings b/Localizations/Holder/en.lproj/Localizable.strings index 642bf5252..9a3e210d6 100644 --- a/Localizations/Holder/en.lproj/Localizable.strings +++ b/Localizations/Holder/en.lproj/Localizable.strings @@ -612,6 +612,7 @@ "holder_endOfLife_description" = "The app is not in use at the moment. For more information, go to CoronaCheck.nl"; "holder_endOfLife_errorMessage" = "Can't open website."; "holder_endOfLife_title" = "App not in use"; +"holder_event_aboutVaccination_productName" = "Product name:"; "holder_event_negativeTestEndstate_addVaccinationAssessment_body" = "

Your negative test result was successfully added. Add your vaccination approval to complete your visitor pass.

To this end, you've received an approval code from the desk that reviewed your vaccination. You’ve received this code on paper.

"; "holder_event_negativeTestEndstate_addVaccinationAssessment_button_complete" = "Complete certificate"; "holder_event_negativeTestEndstate_addVaccinationAssessment_title" = "Negative test result added"; diff --git a/Localizations/Holder/nl.lproj/Localizable.strings b/Localizations/Holder/nl.lproj/Localizable.strings index 3469ef013..cdcb4c262 100644 --- a/Localizations/Holder/nl.lproj/Localizable.strings +++ b/Localizations/Holder/nl.lproj/Localizable.strings @@ -612,6 +612,7 @@ "holder_endOfLife_description" = "Op dit moment is de app niet in gebruik. Ga voor meer informatie naar CoronaCheck.nl"; "holder_endOfLife_errorMessage" = "De website kan niet geopend worden."; "holder_endOfLife_title" = "App niet in gebruik"; +"holder_event_aboutVaccination_productName" = "Productnaam:"; "holder_event_negativeTestEndstate_addVaccinationAssessment_body" = "

Je negatieve testuitslag is succesvol toegevoegd. Maak je bezoekersbewijs compleet met je vaccinatiebeoordeling.

Hiervoor heb je een beoordelingscode gekregen van de balie waar je vaccinatie is beoordeeld. Deze code heb je geprint gekregen.

"; "holder_event_negativeTestEndstate_addVaccinationAssessment_button_complete" = "Maak bewijs compleet"; "holder_event_negativeTestEndstate_addVaccinationAssessment_title" = "Negatieve testuitslag toegevoegd"; diff --git a/Packages/Transport/Sources/Transport/Model/RemoteConfiguration.swift b/Packages/Transport/Sources/Transport/Model/RemoteConfiguration.swift index c0e3f7a11..9b93cd9c6 100644 --- a/Packages/Transport/Sources/Transport/Model/RemoteConfiguration.swift +++ b/Packages/Transport/Sources/Transport/Model/RemoteConfiguration.swift @@ -13,14 +13,27 @@ public struct HPKData: Codable, Equatable { public let name: String + public let displayName: String? + /// euVaccinationTypes lookup - public let vp: String + public let vaccineOrProphylaxis: String /// euBrands lookup - public let mp: String + public let medicalProduct: String /// euManufacturers lookup - public let ma: String + public let marketingAuthorizationHolder: String + + /// Key mapping + enum CodingKeys: String, CodingKey { + + case code + case name + case displayName + case vaccineOrProphylaxis = "vp" + case medicalProduct = "mp" + case marketingAuthorizationHolder = "ma" + } } public struct Mapping: Codable, Equatable { diff --git a/Sources/CTR/Interface/Holder/Event/Details/Model/EventDetails.swift b/Sources/CTR/Interface/Holder/Event/Details/Model/EventDetails.swift index b16b5b13b..d8afdb487 100644 --- a/Sources/CTR/Interface/Holder/Event/Details/Model/EventDetails.swift +++ b/Sources/CTR/Interface/Holder/Event/Details/Model/EventDetails.swift @@ -33,6 +33,7 @@ enum EventDetailsVaccination: EventDetailable { case dateOfBirth case pathogen case vaccineBrand + case vaccineProductname case vaccineType case vaccineManufacturer case dosage @@ -56,6 +57,7 @@ enum EventDetailsVaccination: EventDetailable { case .dateOfBirth: return L.holderEventAboutVaccinationDateofbirth() case .pathogen: return L.holderEventAboutVaccinationPathogen() case .vaccineBrand: return L.holderEventAboutVaccinationBrand() + case .vaccineProductname: return L.holder_event_aboutVaccination_productName() case .vaccineType: return L.holderEventAboutVaccinationType() case .vaccineManufacturer: return L.holderEventAboutVaccinationManufacturer() case .dosage: return L.holderEventAboutVaccinationDosage() diff --git a/Sources/CTR/Interface/Holder/Event/Details/RemoteEventDetailsGenerator.swift b/Sources/CTR/Interface/Holder/Event/Details/RemoteEventDetailsGenerator.swift index cd75dc29f..20fd3cb38 100644 --- a/Sources/CTR/Interface/Holder/Event/Details/RemoteEventDetailsGenerator.swift +++ b/Sources/CTR/Interface/Holder/Event/Details/RemoteEventDetailsGenerator.swift @@ -133,9 +133,9 @@ class DCCTestDetailsGenerator { class VaccinationDetailsGenerator { static func getDetails(identity: EventFlow.Identity, event: EventFlow.Event, providerIdentifier: String) -> [EventDetails] { - + let mappingManager: MappingManaging = Current.mappingManager - + let formattedBirthDate: String = identity.birthDateString .flatMap(Formatter.getDateFrom) .map(DateFormatter.Format.dayMonthYear.string) ?? (identity.birthDateString ?? "") @@ -143,17 +143,19 @@ class VaccinationDetailsGenerator { .flatMap(Formatter.getDateFrom) .map(DateFormatter.Format.dayMonthYear.string) ?? (event.vaccination?.dateString ?? "") let provider: String = mappingManager.getProviderIdentifierMapping(providerIdentifier) ?? providerIdentifier - + var vaccinName: String? + var vaccineDisplayName: String? var vaccineType: String? var vaccineManufacturer: String? - if let hpkCode = event.vaccination?.hpkCode, !hpkCode.isEmpty { - let hpkData = mappingManager.getHpkData(hpkCode) - vaccinName = mappingManager.getVaccinationBrand(hpkData?.mp) - vaccineType = mappingManager.getVaccinationType(hpkData?.vp) - vaccineManufacturer = mappingManager.getVaccinationManufacturer(hpkData?.ma) + if let hpkCode = event.vaccination?.hpkCode, + let hpkData = mappingManager.getHpkData(hpkCode) { + vaccinName = mappingManager.getVaccinationBrand(hpkData.medicalProduct) + vaccineType = mappingManager.getVaccinationType(hpkData.vaccineOrProphylaxis) + vaccineManufacturer = mappingManager.getVaccinationManufacturer(hpkData.marketingAuthorizationHolder) + vaccineDisplayName = hpkData.displayName } - + if vaccinName == nil, let brand = event.vaccination?.brand { vaccinName = mappingManager.getVaccinationBrand(brand) } @@ -164,29 +166,33 @@ class VaccinationDetailsGenerator { vaccineManufacturer = mappingManager.getVaccinationManufacturer(event.vaccination?.manufacturer) ?? event.vaccination?.manufacturer } - + var dosage: String? if let doseNumber = event.vaccination?.doseNumber, let totalDose = event.vaccination?.totalDoses { dosage = L.holderVaccinationAboutOff("\(doseNumber)", "\(totalDose)") } - + let country = mappingManager.getDisplayCountry(event.vaccination?.country ?? "") - - return [ - EventDetails(field: EventDetailsVaccination.subtitle(provider: provider), value: nil), - EventDetails(field: EventDetailsVaccination.name, value: identity.fullName), - EventDetails(field: EventDetailsVaccination.dateOfBirth, value: formattedBirthDate), - EventDetails(field: EventDetailsVaccination.pathogen, value: L.holderEventAboutVaccinationPathogenvalue()), - EventDetails(field: EventDetailsVaccination.vaccineBrand, value: vaccinName), - EventDetails(field: EventDetailsVaccination.vaccineType, value: vaccineType), - EventDetails(field: EventDetailsVaccination.vaccineManufacturer, value: vaccineManufacturer), - EventDetails(field: EventDetailsVaccination.dosage, value: dosage), - EventDetails(field: EventDetailsVaccination.completionReason, value: event.vaccination?.completionStatus), - EventDetails(field: EventDetailsVaccination.date, value: formattedShotDate), - EventDetails(field: EventDetailsVaccination.country, value: country), - EventDetails(field: EventDetailsVaccination.uniqueIdentifer, value: event.unique) - ] + + var details = [EventDetails]() + details += [EventDetails(field: EventDetailsVaccination.subtitle(provider: provider), value: nil)] + details += [EventDetails(field: EventDetailsVaccination.name, value: identity.fullName)] + details += [EventDetails(field: EventDetailsVaccination.dateOfBirth, value: formattedBirthDate)] + details += [EventDetails(field: EventDetailsVaccination.pathogen, value: L.holderEventAboutVaccinationPathogenvalue())] + details += [EventDetails(field: EventDetailsVaccination.vaccineBrand, value: vaccinName)] + if vaccineDisplayName != nil { + details += [EventDetails(field: EventDetailsVaccination.vaccineProductname, value: vaccineDisplayName)] + } + details += [EventDetails(field: EventDetailsVaccination.vaccineType, value: vaccineType)] + details += [EventDetails(field: EventDetailsVaccination.vaccineManufacturer, value: vaccineManufacturer)] + details += [EventDetails(field: EventDetailsVaccination.dosage, value: dosage)] + details += [EventDetails(field: EventDetailsVaccination.completionReason, value: event.vaccination?.completionStatus)] + details += [EventDetails(field: EventDetailsVaccination.date, value: formattedShotDate)] + details += [EventDetails(field: EventDetailsVaccination.country, value: country)] + details += [EventDetails(field: EventDetailsVaccination.uniqueIdentifer, value: event.unique)] + + return details } }