From b78fb8a4be985e5bbb3d4c427ab8560ce9922716 Mon Sep 17 00:00:00 2001 From: Light Date: Fri, 4 Feb 2022 16:16:19 +0100 Subject: [PATCH] feature: school scan mode Co-authored-by: eapuzzo Co-authored-by: Johnny Bueti <29045904+Fehniix@users.noreply.github.com> Co-authored-by: Ludovico Girolimini --- .../Internal/RecoveryValidityCheck.swift | 131 ++--- .../Internal/TestValidityCheck.swift | 29 +- .../Internal/VaccineValidityCheck.swift | 462 ++++++++++-------- DGCAVerifier/Models/Constants.swift | 4 + .../Pages/Home/HomeViewController.swift | 8 +- .../Result/VerificationViewController.swift | 2 + .../en.lproj/Localizable.strings | 16 +- .../it.lproj/Localizable.strings | 16 +- .../Utils/HCert/HCert+PersonalData.swift | 7 +- DGCAVerifier/Utils/HCert/HCert+Recovery.swift | 11 +- .../TestValidityCheckTests.swift | 21 +- Verifier.xcodeproj/project.pbxproj | 16 +- 12 files changed, 416 insertions(+), 307 deletions(-) diff --git a/DGCAVerifier/BusinessRules/Internal/RecoveryValidityCheck.swift b/DGCAVerifier/BusinessRules/Internal/RecoveryValidityCheck.swift index dea6268..dbb7bb1 100644 --- a/DGCAVerifier/BusinessRules/Internal/RecoveryValidityCheck.swift +++ b/DGCAVerifier/BusinessRules/Internal/RecoveryValidityCheck.swift @@ -29,80 +29,97 @@ import SwiftDGC struct RecoveryValidityCheck { typealias Validator = MedicalRulesValidator - - func isRecoveryValid(_ hcert: HCert) -> Status { - guard let validFrom = hcert.recoveryDateFrom else { return .notValid } - guard let validUntil = hcert.recoveryDateUntil else { return .notValid } - - guard let recoveryValidFromDate = validFrom.toRecoveryDate else { return .notValid } - guard let recoveryValidUntilDate = validUntil.toRecoveryDate else { return .notValid } - - var start: Int? - var end: Int? - - let scanMode: String = Store.get(key: .scanMode) ?? "" - switch scanMode { - case Constants.scanMode2G: - start = getStartDays(from: hcert) - end = getEndDays(from: hcert) - case Constants.scanMode3G: - start = getStartDays3G(from: hcert) - end = getEndDays3G(from: hcert) - case Constants.scanModeBooster: - start = getStartDays(from: hcert) - end = getEndDays(from: hcert) - default: - return .notValid + + private func validityEnd(_ hcert: HCert, dateFrom: Date, dateUntil: Date, additionalDays: Int) -> Date? { + if isSchoolScanMode() { + guard let recoveryDateFirstPositive = hcert.recoveryDateFirstPositive?.toRecoveryDate else { return nil } + guard let validityExtension = recoveryDateFirstPositive.add(additionalDays, ofType: .day) else { return nil } + return dateUntil < validityExtension ? dateUntil : validityExtension + + } else { + guard let validityExtension = dateFrom.add(additionalDays, ofType: .day) else { return nil } + return dateUntil > validityExtension ? dateUntil : validityExtension } + } + + func isRecoveryValid(_ hcert: HCert) -> Status { + + guard let validityFrom = hcert.recoveryDateFrom?.toRecoveryDate else { return .notValid } + guard let validityUntil = hcert.recoveryDateUntil?.toRecoveryDate else { return .notValid } + + guard let recoveryStartDays = getStartDays(from: hcert) else { return .notValid } + guard let recoveryEndDays = getEndDays(from: hcert) else { return .notValid } - guard let recoveryStartDays = start else { return .notGreenPass } - guard let recoveryEndDays = end else { return .notGreenPass } + guard let validityStart = validityFrom.add(recoveryStartDays, ofType: .day) else { return .notValid } + guard let validityEnd = validityEnd(hcert, dateFrom: validityFrom, dateUntil: validityUntil, additionalDays: recoveryEndDays) else { return .notValid } - guard let validityStart = recoveryValidFromDate.add(recoveryStartDays, ofType: .day) else { return .notValid } - let validityEnd = recoveryValidUntilDate - guard let validityExtension = recoveryValidFromDate.add(recoveryEndDays, ofType: .day) else { return .notValid } - guard let currentDate = Date.startOfDay else { return .notValid } - let recoveryStatus = Validator.validate(currentDate, from: validityStart, to: validityEnd, extendedTo: validityExtension) + let recoveryStatus = Validator.validate(currentDate, from: validityStart, to: validityEnd) - guard scanMode != Constants.scanModeBooster else { return recoveryStatus == .valid ? .verificationIsNeeded : recoveryStatus } + guard !isBoosterScanMode() else { return recoveryStatus == .valid ? .verificationIsNeeded : recoveryStatus } return recoveryStatus } - - private func getStartDays3G(from hcert: HCert) -> Int? { - let isITCode = hcert.countryCode == Constants.ItalyCountryCode - let startDaysConfig: String - if isSpecialRecovery(hcert: hcert){ - startDaysConfig = Constants.recoverySpecialStartDays - } - else { - startDaysConfig = isITCode ? Constants.recoveryStartDays_IT : Constants.recoveryStartDays_NOT_IT + + private func getEndDays(from hcert: HCert) -> Int? { + let scanMode: String = Store.get(key: .scanMode) ?? "" + let isSpecialRecovery = isSpecialRecovery(hcert: hcert) + switch scanMode { + case Constants.scanMode2G, Constants.scanModeBooster: + let endDaysConfig = isSpecialRecovery ? Constants.recoverySpecialEndDays : Constants.recoveryEndDays_IT + return getValue(for: endDaysConfig)?.intValue + case Constants.scanMode3G: + let isITCode = hcert.countryCode == Constants.ItalyCountryCode + let endDaysConfig: String + if isSpecialRecovery{ + endDaysConfig = Constants.recoverySpecialEndDays + } + else { + endDaysConfig = isITCode ? Constants.recoveryEndDays_IT : Constants.recoveryEndDays_NOT_IT + } + return getValue(for: endDaysConfig)?.intValue + case Constants.scanModeSchool: + let endDaysConfig = Constants.recoverySchoolEndDays + return getValue(for: endDaysConfig)?.intValue + default: + return nil } - return getValue(for: startDaysConfig)?.intValue } - private func getEndDays3G(from hcert: HCert) -> Int? { - let isITCode = hcert.countryCode == Constants.ItalyCountryCode - let startDaysConfig: String - if isSpecialRecovery(hcert: hcert){ - startDaysConfig = Constants.recoverySpecialEndDays - } - else { - startDaysConfig = isITCode ? Constants.recoveryEndDays_IT : Constants.recoveryEndDays_NOT_IT + private func getStartDays(from hcert: HCert) -> Int? { + let scanMode: String = Store.get(key: .scanMode) ?? "" + let isSpecialRecovery = isSpecialRecovery(hcert: hcert) + switch scanMode { + case Constants.scanMode2G, Constants.scanModeBooster: + let startDaysConfig = isSpecialRecovery ? Constants.recoverySpecialStartDays : Constants.recoveryStartDays_IT + return getValue(for: startDaysConfig)?.intValue + case Constants.scanMode3G: + let isITCode = hcert.countryCode == Constants.ItalyCountryCode + let startDaysConfig: String + if isSpecialRecovery{ + startDaysConfig = Constants.recoverySpecialStartDays + } + else { + startDaysConfig = isITCode ? Constants.recoveryStartDays_IT : Constants.recoveryStartDays_NOT_IT + } + return getValue(for: startDaysConfig)?.intValue + case Constants.scanModeSchool: + let startDaysConfig = Constants.recoveryStartDays_IT + return getValue(for: startDaysConfig)?.intValue + default: + return nil } - return getValue(for: startDaysConfig)?.intValue } - private func getStartDays(from hcert: HCert) -> Int? { - let startDaysConfig = isSpecialRecovery(hcert: hcert) ? Constants.recoverySpecialStartDays : Constants.recoveryStartDays_IT - return getValue(for: startDaysConfig)?.intValue + private func isSchoolScanMode() -> Bool{ + let scanMode: String = Store.get(key: .scanMode) ?? "" + return scanMode == Constants.scanModeSchool } - private func getEndDays(from hcert: HCert) -> Int? { - let endDaysConfig = isSpecialRecovery(hcert: hcert) ? Constants.recoverySpecialEndDays : Constants.recoveryEndDays_IT - return getValue(for: endDaysConfig)?.intValue + private func isBoosterScanMode() -> Bool{ + let scanMode: String = Store.get(key: .scanMode) ?? "" + return scanMode == Constants.scanModeBooster } private func isSpecialRecovery(hcert: HCert) -> Bool { diff --git a/DGCAVerifier/BusinessRules/Internal/TestValidityCheck.swift b/DGCAVerifier/BusinessRules/Internal/TestValidityCheck.swift index 59d10d0..50c0e9a 100644 --- a/DGCAVerifier/BusinessRules/Internal/TestValidityCheck.swift +++ b/DGCAVerifier/BusinessRules/Internal/TestValidityCheck.swift @@ -30,7 +30,7 @@ struct TestValidityCheck { typealias Validator = MedicalRulesValidator - func isTestDateValid(_ hcert: HCert) -> Status { + private func isTestDateValid(_ hcert: HCert) -> Status { guard hcert.isKnownTestType else { return .notValid } let startHours = getStartHours(for: hcert) @@ -47,37 +47,44 @@ struct TestValidityCheck { return Validator.validate(Date(), from: validityStart, to: validityEnd) } - func isTestNegative(_ hcert: HCert) -> Status { + private func isTestNegative(_ hcert: HCert) -> Status { guard let isNegative = hcert.testNegative else { return .notValid } return isNegative ? .valid : .notValid } - func isTestValid(_ hcert: HCert) -> Status { + private func testStatusForScanMode(_ hcert: HCert) -> Status { let scanMode: String = Store.get(key: .scanMode) ?? "" - guard scanMode != Constants.scanMode2G, scanMode != Constants.scanModeBooster else { return .notValid } + if (scanMode == Constants.scanMode2G || scanMode == Constants.scanModeBooster || scanMode == Constants.scanModeSchool) { + return .notValid + } + else { return .valid } + } + + func isTestValid(_ hcert: HCert) -> Status { + guard testStatusForScanMode(hcert) == .valid else { return .notValid } let testValidityResults = [isTestNegative(hcert), isTestDateValid(hcert)] return testValidityResults.first(where: {$0 != .valid}) ?? .valid } - func getStartHours(for hcert: HCert) -> String? { + private func getStartHours(for hcert: HCert) -> String? { if (hcert.isMolecularTest) { return molecularStartHours } if (hcert.isRapidTest) { return rapidStartHours } return nil } - func getEndHours(for hcert: HCert) -> String? { + private func getEndHours(for hcert: HCert) -> String? { if (hcert.isMolecularTest) { return molecularEndHours } if (hcert.isRapidTest) { return rapidEndHours } return nil } - func getValue(from key: String) -> String? { + private func getValue(from key: String) -> String? { LocalData.getSetting(from: key) } - var molecularStartHours: String? { getValue(from: Constants.molecularStartHoursKey) } - var molecularEndHours: String? { getValue(from: Constants.molecularEndHoursKey) } - var rapidStartHours: String? { getValue(from: Constants.rapidStartHoursKey) } - var rapidEndHours: String? { getValue(from: Constants.rapidEndHoursKey) } + private var molecularStartHours: String? { getValue(from: Constants.molecularStartHoursKey) } + private var molecularEndHours: String? { getValue(from: Constants.molecularEndHoursKey) } + private var rapidStartHours: String? { getValue(from: Constants.rapidStartHoursKey) } + private var rapidEndHours: String? { getValue(from: Constants.rapidEndHoursKey) } } diff --git a/DGCAVerifier/BusinessRules/Internal/VaccineValidityCheck.swift b/DGCAVerifier/BusinessRules/Internal/VaccineValidityCheck.swift index e4a3d65..b5c18e9 100644 --- a/DGCAVerifier/BusinessRules/Internal/VaccineValidityCheck.swift +++ b/DGCAVerifier/BusinessRules/Internal/VaccineValidityCheck.swift @@ -27,218 +27,260 @@ import Foundation import SwiftDGC struct VaccineValidityCheck { - - typealias Validator = MedicalRulesValidator - - private var allowedVaccinationInCountry: [String: [String]] { - [Constants.SputnikVacineCode: [Constants.sanMarinoCode]] - } - - struct CertificatePreconditions { - let currentDoses: Int - let totalDoses: Int - let medicalProduct: String - let vaccineDate: Date - let countryCode: String + + typealias Validator = MedicalRulesValidator + + private var allowedVaccinationInCountry: [String: [String]] { + [Constants.SputnikVacineCode: [Constants.sanMarinoCode]] + } + + struct CertificatePreconditions { + let currentDoses: Int + let totalDoses: Int + let medicalProduct: String + let vaccineDate: Date + let countryCode: String + + var isIT: Bool { + return self.countryCode.uppercased() == Constants.ItalyCountryCode + } + + var isJJ: Bool { + return self.medicalProduct == Constants.JeJVacineCode + } + + var isJJBooster: Bool { + return self.isJJ && (self.currentDoses >= Constants.jjBoosterMinimumDosesNumber) + } + + var isNonJJBooster: Bool { + return !self.isJJ && (self.currentDoses >= Constants.boosterMinimumDosesNumber) + } + + var isCurrentDoseIncomplete: Bool { + return self.currentDoses < self.totalDoses + } + + var isCurrentDoseComplete: Bool { + return self.currentDoses == self.totalDoses && !self.isJJBooster && !self.isNonJJBooster + } + + /// Valid booster dose JJ or any other + var isCurrentDoseBooster: Bool { + return (self.currentDoses > self.totalDoses) || (isJJBooster || self.isNonJJBooster) + } + } + + func checkPreconditions(_ hcert: HCert) -> CertificatePreconditions? { + guard let currentDoses = hcert.currentDosesNumber, currentDoses > 0 else { return nil } + guard let totalDoses = hcert.totalDosesNumber, totalDoses > 0 else { return nil } + guard let vaccineDate = hcert.vaccineDate?.toVaccineDate else { return nil } + guard let medicalProduct = hcert.medicalProduct else { return nil } + guard isValid(for: medicalProduct) else { return nil } + guard let countryCode = hcert.countryCode else { return nil } + guard isAllowedVaccination(for: medicalProduct, fromCountryWithCode: countryCode) else { return nil } + + return CertificatePreconditions(currentDoses: currentDoses, totalDoses: totalDoses, medicalProduct: medicalProduct, vaccineDate: vaccineDate, countryCode: countryCode) + } + + func checkCertificateDate(_ preconditions: CertificatePreconditions) -> Status { + let scanMode: String = Store.get(key: .scanMode) ?? "" + + guard let start = getStartDays(scanMode: scanMode, preconditions: preconditions) else { return .notValid } + guard let end = getEndDays(scanMode: scanMode, preconditions: preconditions) else { return .notValid } + + guard let validityStart = preconditions.vaccineDate.add(start, ofType: .day) else { return .notValid } + guard let validityEnd = preconditions.vaccineDate.add(end, ofType: .day)?.startOfDay else { return .notValid } + + guard let currentDate = Date.startOfDay else { return .notValid } - var isIT: Bool { - return self.countryCode.uppercased() == Constants.ItalyCountryCode - } - - var isJJ: Bool { - return self.medicalProduct == Constants.JeJVacineCode - } - - var isJJBooster: Bool { - return self.isJJ && (self.currentDoses >= Constants.jjBoosterMinimumDosesNumber) - } - - var isNonJJBooster: Bool { - return !self.isJJ && (self.currentDoses >= Constants.boosterMinimumDosesNumber) - } - - var isCurrentDoseIncomplete: Bool { - return self.currentDoses < self.totalDoses - } - - var isCurrentDoseComplete: Bool { - return self.currentDoses == self.totalDoses - } - - /// Valid booster dose JJ or any other - var isCurrentDoseBooster: Bool { - return (self.currentDoses > self.totalDoses) || (isJJBooster || self.isNonJJBooster) - } - } - - func checkPreconditions(_ hcert: HCert) -> CertificatePreconditions? { - guard let currentDoses = hcert.currentDosesNumber, currentDoses > 0 else { return nil } - guard let totalDoses = hcert.totalDosesNumber, totalDoses > 0 else { return nil } - guard let vaccineDate = hcert.vaccineDate?.toVaccineDate else { return nil } - guard let medicalProduct = hcert.medicalProduct else { return nil } - guard isValid(for: medicalProduct) else { return nil } - guard let countryCode = hcert.countryCode else { return nil } - guard isAllowedVaccination(for: medicalProduct, fromCountryWithCode: countryCode) else { return nil } - - return CertificatePreconditions(currentDoses: currentDoses, totalDoses: totalDoses, medicalProduct: medicalProduct, vaccineDate: vaccineDate, countryCode: countryCode) - } - - func checkCertificateDate(_ preconditions: CertificatePreconditions) -> Status { - let scanMode: String = Store.get(key: .scanMode) ?? "" - - guard let start = getStartDays(scanMode: scanMode, preconditions: preconditions) else { return .notValid } - guard let end = getEndDays(scanMode: scanMode, preconditions: preconditions) else { return .notValid } - - guard let validityStart = preconditions.vaccineDate.add(start, ofType: .day) else { return .notValid } - guard let validityEnd = preconditions.vaccineDate.add(end, ofType: .day)?.startOfDay else { return .notValid } - - guard let currentDate = Date.startOfDay else { return .notValid } - - // J&J booster is immediately valid - let fromDate = preconditions.isJJBooster ? preconditions.vaccineDate : validityStart - - return Validator.validate(currentDate, from: fromDate, to: validityEnd) - } - - func isScanModeBooster() -> Bool { - let scanMode: String = Store.get(key: .scanMode) ?? "" - return scanMode == Constants.scanModeBooster - } - - func checkBooster(_ preconditions: CertificatePreconditions) -> Status { - if preconditions.isCurrentDoseBooster { return . valid } - - return preconditions.isCurrentDoseComplete ? .verificationIsNeeded : .notValid - } - - func isVaccineValid(_ hcert: HCert) -> Status { - guard let preconditions = checkPreconditions(hcert) else { return .notValid } - let result = checkCertificateDate(preconditions) - - guard result == .valid else { return result } - - guard !isScanModeBooster() else { - return checkBooster(preconditions) - } - - return result - } - - private func isaJJBoosterDose(current: Int, total: Int) -> Bool { - return current >= Constants.jjBoosterMinimumDosesNumber - } - - private func isAllowedVaccination(for medicalProduct: String, fromCountryWithCode countryCode: String) -> Bool { - if let allowedCountries = allowedVaccinationInCountry[medicalProduct] { - return allowedCountries.contains(countryCode) - } - return true - } - - private func isValid(for medicalProduct: String) -> Bool { - // Vaccine code not included in settings -> not a valid vaccine for Italy - let name = Constants.vaccineCompleteEndDays - return getValue(for: name, type: medicalProduct) != nil - } - - private func getStartDays(scanMode: String, preconditions: CertificatePreconditions) -> Int? { - switch(scanMode) { - case Constants.scanMode3G: - if preconditions.isCurrentDoseBooster { - let settingName: String = preconditions.isIT ? Constants.vaccineBoosterStartDays_IT : Constants.vaccineBoosterStartDays_NOT_IT - return self.getValue(for: settingName)?.intValue - } - - if preconditions.isCurrentDoseIncomplete { - return self.getValue(for: Constants.vaccineIncompleteStartDays, type: preconditions.medicalProduct)?.intValue - } - - if preconditions.isJJ { - let settingName = Constants.vaccineCompleteStartDays - return self.getValue(for: settingName, type: preconditions.medicalProduct)?.intValue - } - let settingName = preconditions.isIT ? Constants.vaccineCompleteStartDays_IT : Constants.vaccineCompleteStartDays_NOT_IT + // J&J booster is immediately valid + let fromDate = preconditions.isJJBooster ? preconditions.vaccineDate : validityStart + + return Validator.validate(currentDate, from: fromDate, to: validityEnd) + } + + func isScanModeBooster() -> Bool { + let scanMode: String = Store.get(key: .scanMode) ?? "" + return scanMode == Constants.scanModeBooster + } + + func isScanModeSchool() -> Bool { + let scanMode: String = Store.get(key: .scanMode) ?? "" + return scanMode == Constants.scanModeSchool + } + + func checkBooster(_ preconditions: CertificatePreconditions) -> Status { + if preconditions.isCurrentDoseBooster { return .valid } + + return preconditions.isCurrentDoseComplete ? .verificationIsNeeded : .notValid + } + + func checkSchool(_ preconditions: CertificatePreconditions) -> Status { + return preconditions.isCurrentDoseIncomplete ? .notValid : .valid + } + + func isVaccineValid(_ hcert: HCert) -> Status { + guard let preconditions = checkPreconditions(hcert) else { return .notValid } + let result = checkCertificateDate(preconditions) + + guard result == .valid else { return result } + + guard !isScanModeBooster() else { + return checkBooster(preconditions) + } + + guard !isScanModeSchool() else { + return checkSchool(preconditions) + } + + return result + } + + private func isaJJBoosterDose(current: Int, total: Int) -> Bool { + return current >= Constants.jjBoosterMinimumDosesNumber + } + + private func isAllowedVaccination(for medicalProduct: String, fromCountryWithCode countryCode: String) -> Bool { + if let allowedCountries = allowedVaccinationInCountry[medicalProduct] { + return allowedCountries.contains(countryCode) + } + return true + } + + private func isValid(for medicalProduct: String) -> Bool { + // Vaccine code not included in settings -> not a valid vaccine for Italy + let name = Constants.vaccineCompleteEndDays + return getValue(for: name, type: medicalProduct) != nil + } + + private func getStartDays(scanMode: String, preconditions: CertificatePreconditions) -> Int? { + switch(scanMode) { + case Constants.scanMode3G: + if preconditions.isCurrentDoseBooster { + let settingName: String = preconditions.isIT ? Constants.vaccineBoosterStartDays_IT : Constants.vaccineBoosterStartDays_NOT_IT return self.getValue(for: settingName)?.intValue - - case Constants.scanMode2G: - if preconditions.isCurrentDoseBooster { - return self.getValue(for: Constants.vaccineBoosterStartDays_IT)?.intValue - } - - if preconditions.isCurrentDoseIncomplete { - return self.getValue(for: Constants.vaccineIncompleteStartDays, type: preconditions.medicalProduct)?.intValue - } - - if preconditions.isJJ { - let settingName = Constants.vaccineCompleteStartDays - return self.getValue(for: settingName, type: preconditions.medicalProduct)?.intValue - } - return self.getValue(for: Constants.vaccineCompleteStartDays_IT)?.intValue - case Constants.scanModeBooster: - if preconditions.isCurrentDoseBooster { - return self.getValue(for: Constants.vaccineBoosterStartDays_IT)?.intValue - } - - if preconditions.isCurrentDoseIncomplete { - return self.getValue(for: Constants.vaccineIncompleteStartDays, type: preconditions.medicalProduct)?.intValue - } - - if preconditions.isJJ { - let settingName = Constants.vaccineCompleteStartDays - return self.getValue(for: settingName, type: preconditions.medicalProduct)?.intValue - } - return self.getValue(for: Constants.vaccineCompleteStartDays_IT)?.intValue - default: - return nil - } - } - - private func getEndDays(scanMode: String, preconditions: CertificatePreconditions) -> Int? { - switch(scanMode) { - case Constants.scanMode3G: - if preconditions.isCurrentDoseBooster { - let settingName: String = preconditions.isIT ? Constants.vaccineBoosterEndDays_IT : Constants.vaccineBoosterEndDays_NOT_IT - return self.getValue(for: settingName)?.intValue - } - - if preconditions.isCurrentDoseIncomplete { - return self.getValue(for: Constants.vaccineIncompleteEndDays, type: preconditions.medicalProduct)?.intValue - } - - let settingName = preconditions.isIT ? Constants.vaccineCompleteEndDays_IT : Constants.vaccineCompleteEndDays_NOT_IT + } + + if preconditions.isCurrentDoseIncomplete { + return self.getValue(for: Constants.vaccineIncompleteStartDays, type: preconditions.medicalProduct)?.intValue + } + + if preconditions.isJJ { + let settingName = Constants.vaccineCompleteStartDays + return self.getValue(for: settingName, type: preconditions.medicalProduct)?.intValue + } + let settingName = preconditions.isIT ? Constants.vaccineCompleteStartDays_IT : Constants.vaccineCompleteStartDays_NOT_IT + return self.getValue(for: settingName)?.intValue + + case Constants.scanMode2G: + if preconditions.isCurrentDoseBooster { + return self.getValue(for: Constants.vaccineBoosterStartDays_IT)?.intValue + } + + if preconditions.isCurrentDoseIncomplete { + return self.getValue(for: Constants.vaccineIncompleteStartDays, type: preconditions.medicalProduct)?.intValue + } + + if preconditions.isJJ { + let settingName = Constants.vaccineCompleteStartDays + return self.getValue(for: settingName, type: preconditions.medicalProduct)?.intValue + } + return self.getValue(for: Constants.vaccineCompleteStartDays_IT)?.intValue + + case Constants.scanModeBooster: + if preconditions.isCurrentDoseBooster { + return self.getValue(for: Constants.vaccineBoosterStartDays_IT)?.intValue + } + + if preconditions.isCurrentDoseIncomplete { + return self.getValue(for: Constants.vaccineIncompleteStartDays, type: preconditions.medicalProduct)?.intValue + } + + if preconditions.isJJ { + let settingName = Constants.vaccineCompleteStartDays + return self.getValue(for: settingName, type: preconditions.medicalProduct)?.intValue + } + return self.getValue(for: Constants.vaccineCompleteStartDays_IT)?.intValue + + case Constants.scanModeSchool: + if preconditions.isCurrentDoseBooster { + return self.getValue(for: Constants.vaccineBoosterStartDays_IT)?.intValue + } + + if preconditions.isCurrentDoseIncomplete { + return self.getValue(for: Constants.vaccineIncompleteStartDays, type: preconditions.medicalProduct)?.intValue + } + + if preconditions.isJJ { + let settingName = Constants.vaccineCompleteStartDays + return self.getValue(for: settingName, type: preconditions.medicalProduct)?.intValue + } + return self.getValue(for: Constants.vaccineCompleteStartDays_IT)?.intValue + default: + return nil + } + } + + private func getEndDays(scanMode: String, preconditions: CertificatePreconditions) -> Int? { + switch(scanMode) { + case Constants.scanMode3G: + if preconditions.isCurrentDoseBooster { + let settingName: String = preconditions.isIT ? Constants.vaccineBoosterEndDays_IT : Constants.vaccineBoosterEndDays_NOT_IT return self.getValue(for: settingName)?.intValue - case Constants.scanMode2G: - if preconditions.isCurrentDoseBooster { - return self.getValue(for: Constants.vaccineBoosterEndDays_IT)?.intValue - } - - if preconditions.isCurrentDoseIncomplete { - return self.getValue(for: Constants.vaccineIncompleteEndDays, type: preconditions.medicalProduct)?.intValue - } - - return self.getValue(for: Constants.vaccineCompleteEndDays_IT)?.intValue - case Constants.scanModeBooster: - if preconditions.isCurrentDoseBooster { - return self.getValue(for: Constants.vaccineBoosterEndDays_IT)?.intValue - } - - if preconditions.isCurrentDoseIncomplete { - return self.getValue(for: Constants.vaccineIncompleteEndDays, type: preconditions.medicalProduct)?.intValue - } - - return self.getValue(for: Constants.vaccineCompleteEndDays_IT)?.intValue - default: - return nil - } - } - - private func getValue(for name: String, type: String) -> String? { - return LocalData.getSetting(from: name, type: type) - } - - private func getValue(for name: String) -> String? { - return LocalData.getSetting(from: name) - } - + } + + if preconditions.isCurrentDoseIncomplete { + return self.getValue(for: Constants.vaccineIncompleteEndDays, type: preconditions.medicalProduct)?.intValue + } + + let settingName = preconditions.isIT ? Constants.vaccineCompleteEndDays_IT : Constants.vaccineCompleteEndDays_NOT_IT + return self.getValue(for: settingName)?.intValue + + case Constants.scanMode2G: + if preconditions.isCurrentDoseBooster { + return self.getValue(for: Constants.vaccineBoosterEndDays_IT)?.intValue + } + + if preconditions.isCurrentDoseIncomplete { + return self.getValue(for: Constants.vaccineIncompleteEndDays, type: preconditions.medicalProduct)?.intValue + } + + return self.getValue(for: Constants.vaccineCompleteEndDays_IT)?.intValue + + case Constants.scanModeBooster: + if preconditions.isCurrentDoseBooster { + return self.getValue(for: Constants.vaccineBoosterEndDays_IT)?.intValue + } + + if preconditions.isCurrentDoseIncomplete { + return self.getValue(for: Constants.vaccineIncompleteEndDays, type: preconditions.medicalProduct)?.intValue + } + + return self.getValue(for: Constants.vaccineCompleteEndDays_IT)?.intValue + + case Constants.scanModeSchool: + if preconditions.isCurrentDoseBooster { + return self.getValue(for: Constants.vaccineBoosterEndDays_IT)?.intValue + } + + if preconditions.isCurrentDoseIncomplete { + return self.getValue(for: Constants.vaccineIncompleteEndDays, type: preconditions.medicalProduct)?.intValue + } + + return self.getValue(for: Constants.vaccineSchoolEndDays)?.intValue + default: + return nil + } + } + + private func getValue(for name: String, type: String) -> String? { + return LocalData.getSetting(from: name, type: type) + } + + private func getValue(for name: String) -> String? { + return LocalData.getSetting(from: name) + } + } diff --git a/DGCAVerifier/Models/Constants.swift b/DGCAVerifier/Models/Constants.swift index a9b7fc9..726c832 100644 --- a/DGCAVerifier/Models/Constants.swift +++ b/DGCAVerifier/Models/Constants.swift @@ -48,6 +48,8 @@ struct Constants { static let vaccineBoosterStartDays_NOT_IT = "vaccine_start_day_booster_NOT_IT" static let vaccineBoosterEndDays_NOT_IT = "vaccine_end_day_booster_NOT_IT" + static let vaccineSchoolEndDays = "vaccine_end_day_school" + static let JeJVacineCode = "EU/1/20/1525" static let SputnikVacineCode = "Sputnik-V" static let sanMarinoCode = "SM" @@ -61,6 +63,7 @@ struct Constants { static let recoveryEndDays_NOT_IT = "recovery_cert_end_day_NOT_IT" static let recoverySpecialStartDays = "recovery_pv_cert_start_day" static let recoverySpecialEndDays = "recovery_pv_cert_end_day" + static let recoverySchoolEndDays = "recovery_cert_end_day_school" static let OID_RECOVERY = "1.3.6.1.4.1.1847.2021.1.3" static let OID_RECOVERY_ALT = "1.3.6.1.4.1.0.1847.2021.1.3" static let ItalyCountryCode = "IT" @@ -69,6 +72,7 @@ struct Constants { static let scanMode2G = "scanMode2G" static let scanMode3G = "scanMode3G" static let scanModeBooster = "scanModeBooster" + static let scanModeSchool = "scanModeSchool" // Settings static let drlMaxRetries = "MAX_RETRY" diff --git a/DGCAVerifier/Pages/Home/HomeViewController.swift b/DGCAVerifier/Pages/Home/HomeViewController.swift index 15f4d96..1938444 100644 --- a/DGCAVerifier/Pages/Home/HomeViewController.swift +++ b/DGCAVerifier/Pages/Home/HomeViewController.swift @@ -60,7 +60,7 @@ class HomeViewController: UIViewController { @IBOutlet weak var settingsView: UIView! @IBOutlet weak var debugView: UIView! - private var modePickerOptions = ["home.scan.picker.mode.3G".localized, "home.scan.picker.mode.2G".localized, "home.scan.picker.mode.Booster".localized] + private var modePickerOptions = ["home.scan.picker.mode.3G".localized, "home.scan.picker.mode.2G".localized, "home.scan.picker.mode.Booster".localized, "home.scan.picker.mode.School".localized] init(coordinator: HomeCoordinator, viewModel: HomeViewModel) { self.coordinator = coordinator @@ -227,6 +227,9 @@ class HomeViewController: UIViewController { case Constants.scanModeBooster: localizedBaseScanModeButtonTitle = "home.scan.button.mode.Booster".localized boldLocalizedText = "home.scan.button.bold.Booster".localized + case Constants.scanModeSchool: + localizedBaseScanModeButtonTitle = "home.scan.button.mode.School".localized + boldLocalizedText = "home.scan.button.bold.School".localized default: break } @@ -521,6 +524,9 @@ extension HomeViewController { case 2: Store.set(Constants.scanModeBooster, for: Store.Key.scanMode) Store.set(true, for: .isScanModeSet) + case 3: + Store.set(Constants.scanModeSchool, for: Store.Key.scanMode) + Store.set(true, for: .isScanModeSet) default: break } diff --git a/DGCAVerifier/Pages/Result/VerificationViewController.swift b/DGCAVerifier/Pages/Result/VerificationViewController.swift index b2576eb..33d9fba 100644 --- a/DGCAVerifier/Pages/Result/VerificationViewController.swift +++ b/DGCAVerifier/Pages/Result/VerificationViewController.swift @@ -153,6 +153,8 @@ class VerificationViewController: UIViewController { mode = "result.scan.mode.3G".localized case Constants.scanModeBooster: mode = "result.scan.mode.Boster".localized + case Constants.scanModeSchool: + mode = "result.scan.mode.Scuola".localized default: break } diff --git a/DGCAVerifier/SupportingFiles/en.lproj/Localizable.strings b/DGCAVerifier/SupportingFiles/en.lproj/Localizable.strings index db6d219..7dac585 100644 --- a/DGCAVerifier/SupportingFiles/en.lproj/Localizable.strings +++ b/DGCAVerifier/SupportingFiles/en.lproj/Localizable.strings @@ -21,14 +21,19 @@ "home.scan.button.mode.default" = "SCEGLI TIPOLOGIA DI VERIFICA"; "home.scan.button.bold.3G" = "VERIFICA BASE"; "home.scan.button.bold.2G" = "VERIFICA RAFFORZATA"; -"home.scan.button.bold.Booster" = "VERIFICA BOOSTER"; +"home.scan.button.bold.Booster" = "VERIFICA VISITATORI RSA"; +"home.scan.button.bold.School" = "VERIFICA STUDENTI"; + "home.scan.button.mode.3G" = "VERIFICA BASE\nVACCINAZIONE/GUARIGIONE/TAMPONE"; "home.scan.button.mode.2G" = "VERIFICA RAFFORZATA\nVACCINAZIONE/GUARIGIONE"; -"home.scan.button.mode.Booster" = "VERIFICA BOOSTER\nRICHIAMO/CICLO COMPLETO + TAMPONE/GUARIGIONE + TAMPONE"; +"home.scan.button.mode.Booster" = "VERIFICA VISITATORI RSA\nRICHIAMO/CICLO COMPLETO + TAMPONE/GUARIGIONE + TAMPONE"; +"home.scan.button.mode.School" = "VERIFICA STUDENTI\nRICHIAMO/CICLO COMPLETO E GUARIGIONE <120GG"; + "home.scan.picker.title" = "Tipologia verifica"; "home.scan.picker.mode.3G" = "BASE (vaccinazione/guarigione/tampone)"; "home.scan.picker.mode.2G" = "RAFFORZATA (vaccinazione/guarigione)"; -"home.scan.picker.mode.Booster" = "BOOSTER (Richiamo/ciclo completo + tampone/guarigione+tampone)"; +"home.scan.picker.mode.Booster" = "VISITATORI RSA (Richiamo/ciclo completo + tampone/guarigione+tampone)"; +"home.scan.picker.mode.School" = "STUDENTI (richiamo/ciclo completo e guarigione <120gg)"; "camera.back.home" = "Torna all'inizio"; @@ -42,7 +47,8 @@ "result.scan.mode.2G" = "Tipologia verifica: RAFFORZATA"; "result.scan.mode.3G" = "Tipologia verifica: BASE"; -"result.scan.mode.Boster" = "Tipologia verifica: BOOSTER"; +"result.scan.mode.Boster" = "Tipologia verifica: VISITATORI RSA"; +"result.scan.mode.Scuola" = "Tipologia verifica: STUDENTI"; "result.title.valid" = "Certificazione valida"; "result.title.not.valid" = "Certificazione non valida"; @@ -92,7 +98,7 @@ "alert.default.action" = "OK"; "alert.scan.unset.title" = "Impossibile scansionare"; -"alert.scan.unset.message" = "Per procedere alla scansione selezionare una delle tipologie di verifica della Certificazione verde Covid-19: BASE, RAFFORZATA, BOOSTER.\nTipologia BASE: la app considera valide le certificazioni verdi generate da vaccinazione, da guarigione, da tampone.\nTipologia RAFFORZATA: la app considera valide solo le certificazioni verdi generate da vaccinazione o da guarigione.\nTipologia BOOSTER: la app considera valide le certificazioni verdi generate dopo dose di richiamo vaccinale. Considera valide, inoltre, le certificazioni verdi generate dopo ciclo vaccinale primario o guarigione con la contestuale presentazione di un documento, cartaceo o digitale, che attesti l’esito negativo di un test al SARS-CoV-2.\n\nIndicazioni di dettaglio sulle attività consentite senza/con green pass BASE, RAFFORZATO, BOOSTER (link https://www.governo.it/sites/governo.it/files/documenti/documenti/Notizie-allegati/tabella_attivita_consentite.pdf)"; +"alert.scan.unset.message" = "Per procedere alla scansione selezionare una delle tipologie di verifica della Certificazione verde Covid-19: BASE, RAFFORZATA, VISITATORI RSA, STUDENTI.\nTipologia BASE: la app considera valide le certificazioni verdi generate da vaccinazione, da guarigione, da tampone.\nTipologia RAFFORZATA: la app considera valide solo le certificazioni verdi generate da vaccinazione o da guarigione.\nTipologia VISITATORI RSA: da utilizzare per l'accesso di visitatori alle strutture residenziali, socio-assistenziali, socio-sanitarie e hospice: la app considera valide le certificazioni verdi generate da vaccinazione con dose di richiamo. Considera valide, inoltre, le certificazioni verdi generate da vaccinazione con ciclo primario completato o guarigione insieme alla contestuale presentazione di un documento, cartaceo o digitale, che attesti l’esito negativo di un test al SARS-CoV-2. \nTipologia STUDENTI: da utilizzare nelle classi della scuola secondaria per la didattica in presenza in presenza di due casi positivi: la app considera valide le certificazioni verdi generate da vaccinazione con dose di richiamo e quelle con ciclo primario o guarigione, se emesse da meno di 120 giorni. \n\nConsulta la tabella sulle attività consentite senza o con green pass (link https://www.governo.it/sites/governo.it/files/documenti/documenti/Notizie-allegati/tabella_attivita_consentite.pdf)"; "links.read.faq" = "Leggi le domande frequenti"; "links.read.privacy.policy" = "Leggi la Privacy policy"; diff --git a/DGCAVerifier/SupportingFiles/it.lproj/Localizable.strings b/DGCAVerifier/SupportingFiles/it.lproj/Localizable.strings index c3a6ad2..5840017 100644 --- a/DGCAVerifier/SupportingFiles/it.lproj/Localizable.strings +++ b/DGCAVerifier/SupportingFiles/it.lproj/Localizable.strings @@ -21,14 +21,19 @@ "home.scan.button.mode.default" = "SCEGLI TIPOLOGIA DI VERIFICA"; "home.scan.button.bold.3G" = "VERIFICA BASE"; "home.scan.button.bold.2G" = "VERIFICA RAFFORZATA"; -"home.scan.button.bold.Booster" = "VERIFICA BOOSTER"; +"home.scan.button.bold.Booster" = "VERIFICA VISITATORI RSA"; +"home.scan.button.bold.School" = "VERIFICA STUDENTI"; + "home.scan.button.mode.3G" = "VERIFICA BASE\nVACCINAZIONE/GUARIGIONE/TAMPONE"; "home.scan.button.mode.2G" = "VERIFICA RAFFORZATA\nVACCINAZIONE/GUARIGIONE"; -"home.scan.button.mode.Booster" = "VERIFICA BOOSTER\nRICHIAMO/CICLO COMPLETO + TAMPONE/GUARIGIONE + TAMPONE"; +"home.scan.button.mode.Booster" = "VERIFICA VISITATORI RSA\nRICHIAMO/CICLO COMPLETO + TAMPONE/GUARIGIONE + TAMPONE"; +"home.scan.button.mode.School" = "VERIFICA STUDENTI\nRICHIAMO/CICLO COMPLETO E GUARIGIONE <120GG"; + "home.scan.picker.title" = "Tipologia verifica"; "home.scan.picker.mode.3G" = "BASE (vaccinazione/guarigione/tampone)"; "home.scan.picker.mode.2G" = "RAFFORZATA (vaccinazione/guarigione)"; -"home.scan.picker.mode.Booster" = "BOOSTER (Richiamo/ciclo completo + tampone/guarigione+tampone)"; +"home.scan.picker.mode.Booster" = "VISITATORI RSA (Richiamo/ciclo completo + tampone/guarigione+tampone)"; +"home.scan.picker.mode.School" = "STUDENTI (richiamo/ciclo completo e guarigione <120gg)"; "camera.back.home" = "Torna all'inizio"; @@ -42,7 +47,8 @@ "result.scan.mode.2G" = "Tipologia verifica: RAFFORZATA"; "result.scan.mode.3G" = "Tipologia verifica: BASE"; -"result.scan.mode.Boster" = "Tipologia verifica: BOOSTER"; +"result.scan.mode.Boster" = "Tipologia verifica: VISITATORI RSA"; +"result.scan.mode.Scuola" = "Tipologia verifica: STUDENTI"; "result.title.valid" = "Certificazione valida"; "result.title.not.valid" = "Certificazione non valida"; @@ -92,7 +98,7 @@ "alert.default.action" = "OK"; "alert.scan.unset.title" = "Impossibile scansionare"; -"alert.scan.unset.message" = "Per procedere alla scansione selezionare una delle tipologie di verifica della Certificazione verde Covid-19: BASE, RAFFORZATA, BOOSTER.\nTipologia BASE: la app considera valide le certificazioni verdi generate da vaccinazione, da guarigione, da tampone.\nTipologia RAFFORZATA: la app considera valide solo le certificazioni verdi generate da vaccinazione o da guarigione.\nTipologia BOOSTER: la app considera valide le certificazioni verdi generate dopo dose di richiamo vaccinale. Considera valide, inoltre, le certificazioni verdi generate dopo ciclo vaccinale primario o guarigione con la contestuale presentazione di un documento, cartaceo o digitale, che attesti l’esito negativo di un test al SARS-CoV-2.\n\nIndicazioni di dettaglio sulle attività consentite senza/con green pass BASE, RAFFORZATO, BOOSTER (link https://www.governo.it/sites/governo.it/files/documenti/documenti/Notizie-allegati/tabella_attivita_consentite.pdf)"; +"alert.scan.unset.message" = "Per procedere alla scansione selezionare una delle tipologie di verifica della Certificazione verde Covid-19: BASE, RAFFORZATA, VISITATORI RSA, STUDENTI.\nTipologia BASE: la app considera valide le certificazioni verdi generate da vaccinazione, da guarigione, da tampone.\nTipologia RAFFORZATA: la app considera valide solo le certificazioni verdi generate da vaccinazione o da guarigione.\nTipologia VISITATORI RSA: da utilizzare per l'accesso di visitatori alle strutture residenziali, socio-assistenziali, socio-sanitarie e hospice: la app considera valide le certificazioni verdi generate da vaccinazione con dose di richiamo. Considera valide, inoltre, le certificazioni verdi generate da vaccinazione con ciclo primario completato o guarigione insieme alla contestuale presentazione di un documento, cartaceo o digitale, che attesti l’esito negativo di un test al SARS-CoV-2. \nTipologia STUDENTI: da utilizzare nelle classi della scuola secondaria per la didattica in presenza in presenza di due casi positivi: la app considera valide le certificazioni verdi generate da vaccinazione con dose di richiamo e quelle con ciclo primario o guarigione, se emesse da meno di 120 giorni. \n\nConsulta la tabella sulle attività consentite senza o con green pass (link https://www.governo.it/sites/governo.it/files/documenti/documenti/Notizie-allegati/tabella_attivita_consentite.pdf)"; "links.read.faq" = "Leggi le domande frequenti"; "links.read.privacy.policy" = "Leggi la Privacy policy"; diff --git a/DGCAVerifier/Utils/HCert/HCert+PersonalData.swift b/DGCAVerifier/Utils/HCert/HCert+PersonalData.swift index 4bf4042..88b5397 100644 --- a/DGCAVerifier/Utils/HCert/HCert+PersonalData.swift +++ b/DGCAVerifier/Utils/HCert/HCert+PersonalData.swift @@ -46,10 +46,13 @@ extension HCert { // yyyy-MM let split = dob.split(separator: "-") return "\(split[1])/\(split[0])" + } else { + // yyyy-MM-dd + let split = dob.split(separator: "-") + return "\(split[2])/\(split[1])/\(split[0])" } - // yyyy-MM-dd - return dob.toDate?.toDateReadableString ?? "" + } } diff --git a/DGCAVerifier/Utils/HCert/HCert+Recovery.swift b/DGCAVerifier/Utils/HCert/HCert+Recovery.swift index 145b50e..bce8101 100644 --- a/DGCAVerifier/Utils/HCert/HCert+Recovery.swift +++ b/DGCAVerifier/Utils/HCert/HCert+Recovery.swift @@ -27,9 +27,10 @@ import SwiftDGC extension HCert { - private var dateFromKey : String { "df" } - private var dateUntilKey : String { "du" } - private var countryCodeKey : String { "co" } + private var dateFromKey : String { "df" } + private var dateUntilKey : String { "du" } + private var countryCodeKey : String { "co" } + private var dateFirstPositive : String { "fr" } var recoveryDateFrom: String? { body["r"].array?.map{ $0[dateFromKey] }.first?.string @@ -42,4 +43,8 @@ extension HCert { var rcountryCode: String? { return body["r"].array?.map{ $0[countryCodeKey] }.first?.string } + + var recoveryDateFirstPositive: String? { + return body["r"].array?.map{ $0[dateFirstPositive] }.first?.string + } } diff --git a/DGCAVerifierTests/TestValidityCheckTests.swift b/DGCAVerifierTests/TestValidityCheckTests.swift index 7d1c540..347e9fe 100644 --- a/DGCAVerifierTests/TestValidityCheckTests.swift +++ b/DGCAVerifierTests/TestValidityCheckTests.swift @@ -53,7 +53,18 @@ class TestValidityCheckTests: XCTestCase { } func testValidNegativeTest() { - let isTestNegativeResult = testValidityCheck.isTestNegative(hcert) + let testSettingStartDay = Setting(name: Constants.rapidStartHoursKey, type: "GENERIC", value: "0") + let testSettingEndDay = Setting(name: Constants.rapidEndHoursKey, type: "GENERIC", value: "48") + SettingDataStorage.sharedInstance.addOrUpdateSettings(testSettingStartDay) + SettingDataStorage.sharedInstance.addOrUpdateSettings(testSettingEndDay) + + bodyString = bodyString.replacingOccurrences( + of: "\"sc\": \"2021-05-03T12:27:15+02:00\"", + with: "\"sc\": \"\(Date().toDateTimeString)\"" + ) + hcert.body = JSON(parseJSON: bodyString)[ClaimKey.hCert.rawValue][ClaimKey.euDgcV1.rawValue] + + let isTestNegativeResult = testValidityCheck.isTestValid(hcert) XCTAssertEqual(isTestNegativeResult, .valid) } @@ -61,7 +72,7 @@ class TestValidityCheckTests: XCTestCase { func testInvalidPositiveTest() { bodyString = bodyString.replacingOccurrences(of: "\"tr\": \"260415000\"", with: "\"tr\": \"260373001\"") hcert.body = JSON(parseJSON: bodyString)[ClaimKey.hCert.rawValue][ClaimKey.euDgcV1.rawValue] - let isTestNegativeResult = testValidityCheck.isTestNegative(hcert) + let isTestNegativeResult = testValidityCheck.isTestValid(hcert) XCTAssertEqual(isTestNegativeResult, .notValid) } @@ -74,7 +85,7 @@ class TestValidityCheckTests: XCTestCase { let todayDateFormatted = Date().toDateTimeString bodyString = bodyString.replacingOccurrences(of: "\"sc\": \"2021-05-03T12:27:15+02:00\"", with: "\"sc\": \"\(todayDateFormatted)\"") hcert.body = JSON(parseJSON: bodyString)[ClaimKey.hCert.rawValue][ClaimKey.euDgcV1.rawValue] - let isTestDateValidResult = testValidityCheck.isTestDateValid(hcert) + let isTestDateValidResult = testValidityCheck.isTestValid(hcert) XCTAssertEqual(isTestDateValidResult, .valid) } @@ -87,14 +98,14 @@ class TestValidityCheckTests: XCTestCase { let futureDateFormatted = Date().add(2, ofType: .hour)?.toDateTimeString ?? "" bodyString = bodyString.replacingOccurrences(of: "\"sc\": \"2021-05-03T12:27:15+02:00\"", with: "\"sc\": \"\(futureDateFormatted)\"") hcert.body = JSON(parseJSON: bodyString)[ClaimKey.hCert.rawValue][ClaimKey.euDgcV1.rawValue] - let isTestDateValidResult = testValidityCheck.isTestDateValid(hcert) + let isTestDateValidResult = testValidityCheck.isTestValid(hcert) XCTAssertEqual(isTestDateValidResult, .notValidYet) } func testMissingSettingRapidTestDate() { hcert.body = JSON(parseJSON: bodyString)[ClaimKey.hCert.rawValue][ClaimKey.euDgcV1.rawValue] - let isTestDateValidResult = testValidityCheck.isTestDateValid(hcert) + let isTestDateValidResult = testValidityCheck.isTestValid(hcert) XCTAssertEqual(isTestDateValidResult, .notGreenPass) } diff --git a/Verifier.xcodeproj/project.pbxproj b/Verifier.xcodeproj/project.pbxproj index 460d0cc..0b0fa7c 100644 --- a/Verifier.xcodeproj/project.pbxproj +++ b/Verifier.xcodeproj/project.pbxproj @@ -1836,7 +1836,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.2.3; + MARKETING_VERSION = 1.2.4; PRODUCT_BUNDLE_IDENTIFIER = it.ministerodellasalute.VerificaC19; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1860,7 +1860,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.2.3; + MARKETING_VERSION = 1.2.4; PRODUCT_BUNDLE_IDENTIFIER = it.ministerodellasalute.VerificaC19; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1947,7 +1947,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.2.3; + MARKETING_VERSION = 1.2.4; PRODUCT_BUNDLE_IDENTIFIER = it.ministerodellasalute.VerificaC19; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1972,7 +1972,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.2.3; + MARKETING_VERSION = 1.2.4; PRODUCT_BUNDLE_IDENTIFIER = it.ministerodellasalute.VerificaC19; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -2103,7 +2103,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.2.3; + MARKETING_VERSION = 1.2.4; PRODUCT_BUNDLE_IDENTIFIER = it.ministerodellasalute.VerificaC19; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -2128,7 +2128,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.2.3; + MARKETING_VERSION = 1.2.4; PRODUCT_BUNDLE_IDENTIFIER = it.ministerodellasalute.VerificaC19; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -2322,7 +2322,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.2.3; + MARKETING_VERSION = 1.2.4; PRODUCT_BUNDLE_IDENTIFIER = it.ministerodellasalute.VerificaC19; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -2347,7 +2347,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.2.3; + MARKETING_VERSION = 1.2.4; PRODUCT_BUNDLE_IDENTIFIER = it.ministerodellasalute.VerificaC19; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = "";