Skip to content

Commit

Permalink
RMET-3822 - Firebase Analytics - Prepare to release version 5.0.0-OS16 (
Browse files Browse the repository at this point in the history
#47)

* RMET-3822 Firebase Analytics - Android - Convert values to double if necessary (#45)

* fix: if key is "value", "tax", or "shipping", then its value should be a number (double)

References: https://outsystemsrd.atlassian.net/browse/RMET-3822

* chore: update changelog

References: https://outsystemsrd.atlassian.net/browse/RMET-3822

* RMET-3823 ::: iOS ::: Fix Ecommerce Decimal Values (#46)

* fix(ios): make InputParameterData accept value types besides string

This requires the code to validate the type being analysed.
Considering that we want to split between the available types (Decimal and String), we declare the 'OSFANLInputDataFieldKey' values that should have a Decimal value and be treated differently.
These changes allow us to
- refactor the code a bit, namely the 'OSFANLManager''s 'validate(dataField:isRequired:eventData:)' method, making it much simpler than it was.
- remove the now unused 'StringConvertable' initialiser.

References: https://outsystemsrd.atlassian.net/browse/RMET-3823

* fix: remove default value when Decimal can't be initialised

Instead of setting the value to 'zero' (which is wrong), throw an error mentioning that an invalid value was provided.
Simplify the decimal verification call by using a boolean computed property.

References: https://outsystemsrd.atlassian.net/browse/RMET-3823

* chore: add CHANGELOG entry

References: https://outsystemsrd.atlassian.net/browse/RMET-3823

* chore: raise to version 5.0.0-OS16

References:

https://outsystemsrd.atlassian.net/browse/RMET-3822
https://outsystemsrd.atlassian.net/browse/RMET-3823

---------

Co-authored-by: Ricardo Silva <[email protected]>
  • Loading branch information
1 parent 2a39fc0 commit af1dd14
Show file tree
Hide file tree
Showing 10 changed files with 71 additions and 36 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

The changes documented here do not include those from the original repository.

## 5.0.0-OS16

- Fix(Android & iOS): Convert values to double if necessary (https://outsystemsrd.atlassian.net/browse/RMET-3822 & https://outsystemsrd.atlassian.net/browse/RMET-3823).

## 5.0.0-OS15

- Feat(Android & iOS): Add setConsent functionality to allow users to set consent for analytics (https://outsystemsrd.atlassian.net/browse/RMET-3677 & https://outsystemsrd.atlassian.net/browse/RMET-3678).
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cordova-plugin-firebase-analytics",
"version": "5.0.0-OS15",
"version": "5.0.0-OS16",
"description": "Cordova plugin for Firebase Analytics",
"cordova": {
"id": "cordova-plugin-firebase-analytics",
Expand Down
2 changes: 1 addition & 1 deletion plugin.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
xmlns:android="http://schemas.android.com/apk/res/android"
id="cordova-plugin-firebase-analytics"
version="5.0.0-OS15">
version="5.0.0-OS16">

<name>FirebaseAnalyticsPlugin</name>
<description>Cordova plugin for Firebase Analytics</description>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
package com.outsystems.firebase.analytics.validator

import android.os.Bundle
import android.util.Log
import com.outsystems.firebase.analytics.model.OSFANLError
import com.outsystems.firebase.analytics.model.OSFANLInputDataFieldKey
import com.outsystems.firebase.analytics.model.OSFANLInputDataFieldKey.CURRENCY
import com.outsystems.firebase.analytics.model.OSFANLInputDataFieldKey.EVENT_PARAMETERS
import com.outsystems.firebase.analytics.model.OSFANLInputDataFieldKey.KEY
import com.outsystems.firebase.analytics.model.OSFANLInputDataFieldKey.TYPE_NUMBER
import com.outsystems.firebase.analytics.model.OSFANLInputDataFieldKey.VALUE
import com.outsystems.firebase.analytics.model.OSFANLInputDataFieldKey.TAX
import com.outsystems.firebase.analytics.model.OSFANLInputDataFieldKey.SHIPPING
import com.outsystems.firebase.analytics.model.putAny
import org.json.JSONArray

Expand Down Expand Up @@ -85,7 +88,22 @@ class OSFANLEventParameterValidator private constructor(
hasCurrency = hasCurrency || key == CURRENCY.json

parameterKeySet.add(key)
result.putAny(key, value)

try {
// value, tax, and shipping are actually decimal values, not strings
if (key == VALUE.json || key == TAX.json || key == SHIPPING.json) {
result.putAny(key, value.toDouble()) // can throw NumberFormatException
} else {
result.putAny(key, value)
}
} catch (e: NumberFormatException) {
Log.d(
"OSFANLEventParameterValidator",
"Tried to convert non-number to double. Exception: ${e.message}"
)
// if conversion isn't successful, we still try to send the event
result.putAny(key, value)
}
}

// validate value / currency
Expand Down
9 changes: 0 additions & 9 deletions src/ios/Common/Extensions/StringConvertable.swift
Original file line number Diff line number Diff line change
@@ -1,20 +1,11 @@
protocol StringConvertable {
static var variableType: String { get }
init?(value: String)
}

extension Decimal: StringConvertable {
static var variableType: String { "Decimal" }

init?(value: String) {
self.init(string: value)
}
}

extension String: StringConvertable {
static var variableType: String { "Text" }

init?(value: String) {
self.init(stringLiteral: value)
}
}
8 changes: 8 additions & 0 deletions src/ios/Common/OSFANLInputDataFieldKey.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,11 @@ enum OSFANLInputDataFieldKey: String {
case transactionId = "transaction_id"
case value
}

extension OSFANLInputDataFieldKey {
private static var decimalDataFields: [OSFANLInputDataFieldKey] { [.shipping, .tax, .value] }

var isDecimalType: Bool {
return OSFANLInputDataFieldKey.decimalDataFields.contains(self)
}
}
33 changes: 23 additions & 10 deletions src/ios/InputTransformer/OSFANLInputTransformer.swift
Original file line number Diff line number Diff line change
@@ -1,22 +1,35 @@
struct OSFANLInputTransformer: OSFANLInputTransformable {
func transform(_ eventParameterArray: [InputParameterData]?, _ itemArray: [InputItemData]?) throws -> OSFANLInputTransformableModel {
var eventParameterData: InputParameterData?
if let eventParameterArray {
guard let flatResult = try? self.flat(keyValueMapArray: eventParameterArray) else {
throw OSFANLError.duplicateItemsIn(parameter: OSFANLInputDataFieldKey.eventParameters.rawValue)
do {
var eventParameterData: InputParameterData?
if let eventParameterArray {
eventParameterData = try self.flat(keyValueMapArray: eventParameterArray)
}
eventParameterData = flatResult
let itemArray = try self.transform(itemArray)

return .init(eventParameterData, itemArray)
} catch OSFANLError.duplicateKeys {
throw OSFANLError.duplicateItemsIn(parameter: OSFANLInputDataFieldKey.eventParameters.rawValue)
}
let itemArray = try self.transform(itemArray)

return .init(eventParameterData, itemArray)
}
}

private extension OSFANLInputTransformer {
func flat(keyValueMapArray array: [InputParameterData]) throws -> InputParameterData {
let flatKeyValueArray = array.map {
[$0[OSFANLInputDataFieldKey.key.rawValue, default: ""]: $0[OSFANLInputDataFieldKey.value.rawValue, default: ""]]
let flatKeyValueArray = try array.reduce(into: [InputParameterData]()) { partialResult, current in
guard let dataFieldKey = current[OSFANLInputDataFieldKey.key.rawValue] as? String,
let dataValue = current[OSFANLInputDataFieldKey.value.rawValue] as? String
else { return }

let value: StringConvertable
if let dataField = OSFANLInputDataFieldKey(rawValue: dataFieldKey), dataField.isDecimalType {
guard let decimalValue = Decimal(string: dataValue) else { throw OSFANLError.invalidType(dataFieldKey, type: Decimal.variableType) }
value = decimalValue
} else {
value = dataValue
}

partialResult.append([dataFieldKey: value])
}
let flatKeyValueDictionary = self.flat(dictionaryArray: flatKeyValueArray)

Expand Down
2 changes: 1 addition & 1 deletion src/ios/Manager/OSFANLManageable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ extension DefaultKeyValueData {
}
}

typealias InputParameterData = [String: String]
typealias InputParameterData = [String: Any]
typealias InputItemData = DefaultKeyValueData
typealias OutputParameterData = DefaultKeyValueData

Expand Down
21 changes: 11 additions & 10 deletions src/ios/Manager/OSFANLManager+EventValidationRules.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,19 +49,17 @@ private extension OSFANLManager {
// Validate parameters first
if let parameters {
if parameters.contains(.currencyAndValue) {
let valueContainsValue = try self.validate(parameter: OSFANLInputDataFieldKey.value.rawValue, ofType: Decimal.self, eventData)
try self.validate(
parameter: OSFANLInputDataFieldKey.currency.rawValue, ofType: String.self, isRequired: valueContainsValue, eventData
)
let valueContainsValue = try self.validate(dataField: .value, eventData)
try self.validate(dataField: .currency, isRequired: valueContainsValue, eventData)
}
if parameters.contains(.transactionId) {
try self.validate(parameter: OSFANLInputDataFieldKey.transactionId.rawValue, ofType: String.self, isRequired: true, eventData)
try self.validate(dataField: .transactionId, isRequired: true, eventData)
}
if parameters.contains(.shipping) {
try self.validate(parameter: OSFANLInputDataFieldKey.shipping.rawValue, ofType: Decimal.self, eventData)
try self.validate(dataField: .shipping, eventData)
}
if parameters.contains(.tax) {
try self.validate(parameter: OSFANLInputDataFieldKey.tax.rawValue, ofType: Decimal.self, eventData)
try self.validate(dataField: .tax, eventData)
}
}

Expand Down Expand Up @@ -112,15 +110,18 @@ private extension OSFANLManager {
}

@discardableResult
private static func validate<T: CustomStringConvertible & StringConvertable>(parameter: String, ofType type: T.Type, isRequired: Bool = false, _ eventData: InputParameterData?) throws -> Bool {
private static func validate(dataField: OSFANLInputDataFieldKey, isRequired: Bool = false, _ eventData: InputParameterData?) throws -> Bool {
func espace(_ isRequired: Bool, parameterMissing parameter: String) throws -> Bool {
if isRequired { throw OSFANLError.missing(parameter) }
return false // indicates that there's no value associated to `parameter`
}

guard let eventData, !eventData.isEmpty else { return try espace(isRequired, parameterMissing: "eventParameters") }
guard let parameterStringValue = eventData[parameter] else { return try espace(isRequired, parameterMissing: parameter) }
if T(value: parameterStringValue) == nil { throw OSFANLError.invalidType(parameter, type: T.variableType) }
let parameter = dataField.rawValue
guard let parameterValue = eventData[parameter] else { return try espace(isRequired, parameterMissing: parameter) }

let dataField: (type: StringConvertable.Type, value: StringConvertable?) = dataField.isDecimalType ? (Decimal.self, parameterValue as? Decimal) : (String.self, parameterValue as? String)
if dataField.value == nil { throw OSFANLError.invalidType(parameter, type: dataField.type.variableType) }
return true // indicates that there's a value associated to `parameter`
}
}
6 changes: 3 additions & 3 deletions src/ios/Manager/OSFANLManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,17 @@ extension OSFANLManager: OSFANLManageable {
}

func createEventModel(for inputArgument: InputParameterData) throws -> OSFANLOutputModel {
guard let eventName = inputArgument[OSFANLInputDataFieldKey.event.rawValue], !eventName.isEmpty else {
guard let eventName = inputArgument[OSFANLInputDataFieldKey.event.rawValue] as? String, !eventName.isEmpty else {
throw OSFANLError.missing(OSFANLInputDataFieldKey.event.rawValue)
}

var eventParameterArray: [InputParameterData]?
if let eventParameterString = inputArgument[OSFANLInputDataFieldKey.eventParameters.rawValue] {
if let eventParameterString = inputArgument[OSFANLInputDataFieldKey.eventParameters.rawValue] as? String {
eventParameterArray = self.convert(jsonString: eventParameterString)
}

var itemArray: [InputItemData]?
if let itemString = inputArgument[OSFANLInputDataFieldKey.items.rawValue] {
if let itemString = inputArgument[OSFANLInputDataFieldKey.items.rawValue] as? String {
itemArray = self.convert(jsonString: itemString)
}

Expand Down

0 comments on commit af1dd14

Please sign in to comment.