From ba4409d7484b3f48960298cb5dd4210e820a0d1d Mon Sep 17 00:00:00 2001 From: Alan Maynard Date: Thu, 21 Mar 2019 13:34:51 -0400 Subject: [PATCH] SWF-21 improve login logic & more - move login web service call to `FetchData` and modified other calls to take a completion as a parameter - modified parsing of account in order to reduce complexity - modified parsing to convert date strings to `Date`s --- .../FetchData.swift | 85 +++++++++++-------- .../MainMenuInterfaceController.swift | 31 +++---- .../SynchronyFinancial/Account.swift | 6 +- .../SynchronyFinancial/Defaults.swift | 2 +- 4 files changed, 70 insertions(+), 54 deletions(-) diff --git a/SynchronyFinancial/SynchronyFinancial WatchKit Extension/FetchData.swift b/SynchronyFinancial/SynchronyFinancial WatchKit Extension/FetchData.swift index ccf03f5..9c218e8 100644 --- a/SynchronyFinancial/SynchronyFinancial WatchKit Extension/FetchData.swift +++ b/SynchronyFinancial/SynchronyFinancial WatchKit Extension/FetchData.swift @@ -10,8 +10,30 @@ import Foundation import Alamofire import SwiftyJSON -class FetchData{ - class func getAccountInfo(){ +class FetchData { + static func attemptLogin(completion: @escaping (Bool, Error?) -> Void) { + Alamofire.request(Defaults.LOGIN_URL, method: .post, parameters: Defaults.headerForLogin, encoding: JSONEncoding.default).responseJSON { payload in + switch payload.result { + case .success(let value): + let dict = JSON(value).dictionaryValue + guard dict["status"]?.dictionaryValue["response_code"]?.string == "0" else { + completion(false, NSError()) + return + } + + if let token = dict["access_token"]?.string { + // now we should save our token somewhere safe (UserDefaults) + UserDefaults.standard.set(token, forKey: "access_token") + completion(true, nil) + } + case .failure(let error): + NSLog("Error: %s", error.localizedDescription) + completion(false, error) + } + } + } + + static func getAccountInfo(completion: @escaping ([Account], Error?) -> Void) { var accountList: [Account] = [] Alamofire.request(Defaults.MULTI_ACCT_URL, method: .post, parameters: Defaults.headerForMulti, encoding: JSONEncoding.default, headers: Defaults.authHeader).responseJSON { payload in switch payload.result { @@ -20,41 +42,36 @@ class FetchData{ let dict = json.dictionaryValue guard dict["status"]?.dictionaryValue["response_code"]?.string == "0" else { return } print(json) - - if let accounts = dict["account_number_list"]?.arrayValue{ - for account in accounts{ - guard let accountAlias = account.dictionaryValue["account_alias"]?.string else {return} - guard let creditLimit = account.dictionaryValue["credit_limit"]?.string else {return} - guard let payDueDate = account.dictionaryValue["next_payment_due_date"]?.string else {return} - guard let curBal = account.dictionaryValue["current_balance"]?.string else {return} - guard let availCredit = account.dictionaryValue["available_credit"]?.string else {return} - guard let minPayDue = account.dictionaryValue["minimum_payment_due"]?.string else {return} - guard let statementBal = account.dictionaryValue["statement_bal"]?.string else {return} - guard let accountName = account.dictionaryValue["cc_program_name"]?.string else {return} - - let creditLimitD = Double(creditLimit)! - let curBalD = Double(curBal)! - let availCreditD = Double(availCredit)! - let minPayDueD = Double(minPayDue)! - let stateBalD = Double(statementBal)! - debugPrint(accountAlias) - debugPrint(creditLimitD) - debugPrint(payDueDate) - debugPrint(curBalD) - debugPrint(availCreditD) - debugPrint(minPayDueD) - debugPrint(stateBalD) - debugPrint(accountName) - let inAccount = Account(accountAlias: accountAlias, creditLimit: creditLimitD, paymentDueDate: payDueDate, curBalance: curBalD, availCredit: availCreditD, minPayDue: minPayDueD, statementBal: stateBalD, accountName: accountName) - accountList.append(inAccount) - } + + let formatter = DateFormatter() + formatter.locale = Locale.current + formatter.dateFormat = "yyyyMMdd" + if let accounts = dict["account_number_list"]?.arrayValue { + accounts.forEach { + if let accountAlias = $0.dictionaryValue["account_alias"]?.string, + let creditLimitString = $0.dictionaryValue["credit_limit"]?.string, + let creditLimit = Double(creditLimitString), + let payDueDateString = $0.dictionaryValue["next_payment_due_date"]?.string, + let paymentDueDate = formatter.date(from: payDueDateString), + let curBalString = $0.dictionaryValue["current_balance"]?.string, + let currentBalance = Double(curBalString), + let availCreditString = $0.dictionaryValue["available_credit"]?.string, + let availableCredit = Double(availCreditString), + let minPayDueString = $0.dictionaryValue["minimum_payment_due"]?.string, + let minPaymentDue = Double(minPayDueString), + let statementBalString = $0.dictionaryValue["statement_bal"]?.string, + let statementBalance = Double(statementBalString), + let accountName = $0.dictionaryValue["cc_program_name"]?.string { + let inAccount = Account(accountAlias: accountAlias, creditLimit: creditLimit, paymentDueDate: paymentDueDate, curBalance: currentBalance, availCredit: availableCredit, minPayDue: minPaymentDue, statementBal: statementBalance, accountName: accountName) + accountList.append(inAccount) + } + } } - //debugPrint(json) - case .failure(let error): + completion(accountList, nil) + case .failure(let error): NSLog("Error: %s", error.localizedDescription) + completion([], error) } } } - - } diff --git a/SynchronyFinancial/SynchronyFinancial WatchKit Extension/MainMenuInterfaceController.swift b/SynchronyFinancial/SynchronyFinancial WatchKit Extension/MainMenuInterfaceController.swift index 28f0a14..ea7521d 100644 --- a/SynchronyFinancial/SynchronyFinancial WatchKit Extension/MainMenuInterfaceController.swift +++ b/SynchronyFinancial/SynchronyFinancial WatchKit Extension/MainMenuInterfaceController.swift @@ -15,29 +15,29 @@ class MainMenuInterfaceController: WKInterfaceController { @IBOutlet weak var accountsButton: WKInterfaceButton! @IBOutlet weak var wellnessButton: WKInterfaceButton! + var accounts: [Account] = [] override func awake(withContext context: Any?) { super.awake(withContext: context) // We should find a better place for this call, just for testing purposes - Alamofire.request(Defaults.LOGIN_URL, method: .post, parameters: Defaults.headerForLogin, encoding: JSONEncoding.default).responseJSON { payload in - switch payload.result { - case .success(let value): - let json = JSON(value) - let dict = json.dictionaryValue - guard dict["status"]?.dictionaryValue["response_code"]?.string == "0" else { return } - if let token = dict["access_token"]?.string { - debugPrint(token) - // now we should save our token somewhere safe (UserDefaults) - UserDefaults.standard.set(token, forKey: "access_token") - + FetchData.attemptLogin { result, error in + switch result { + case true: + FetchData.getAccountInfo { accounts, error in + guard error == nil else { + NSLog("Account Retrieval Error: %s", error?.localizedDescription ?? "") + return + } + + self.accounts = accounts } - case .failure(let error): - NSLog("Error: %s", error.localizedDescription) + case false: + NSLog("Login Error: %s", error?.localizedDescription ?? "Unknown Error") } } //just here for testing. Should be moved into the accounts controller when that branch is merged - FetchData.getAccountInfo() - +// FetchData.getAccountInfo() + } override func willActivate() { @@ -53,6 +53,7 @@ class MainMenuInterfaceController: WKInterfaceController { override func contextForSegue(withIdentifier segueIdentifier: String) -> Any? { if segueIdentifier == "toAccounts" { // we will probably want to do some setup prior to presenting Accounts + print(accounts.count) } else if segueIdentifier == "toWellness" { // we will probably want to do some setup prior to presenting Wellness } diff --git a/SynchronyFinancial/SynchronyFinancial/Account.swift b/SynchronyFinancial/SynchronyFinancial/Account.swift index 8d8fb4d..21875b7 100644 --- a/SynchronyFinancial/SynchronyFinancial/Account.swift +++ b/SynchronyFinancial/SynchronyFinancial/Account.swift @@ -11,7 +11,7 @@ class Account: NSObject { var accountAlias: String var creditLimit: Double //var transactions: [Transaction] - var paymentDueDate: String + var paymentDueDate: Date //var cycleEndDate: Date var curBalance: Double var availCredit: Double @@ -20,7 +20,7 @@ class Account: NSObject { var statementBal: Double var accountName: String - init(accountAlias: String, creditLimit: Double, paymentDueDate: String, curBalance: Double, availCredit : Double, minPayDue: Double, statementBal: Double, accountName: String) { + init(accountAlias: String, creditLimit: Double, paymentDueDate: Date, curBalance: Double, availCredit: Double, minPayDue: Double, statementBal: Double, accountName: String) { self.accountAlias = accountAlias self.creditLimit = creditLimit //self.transactions = transactions @@ -33,6 +33,4 @@ class Account: NSObject { self.statementBal = statementBal self.accountName = accountName } - - } diff --git a/SynchronyFinancial/SynchronyFinancial/Defaults.swift b/SynchronyFinancial/SynchronyFinancial/Defaults.swift index 6c77905..e210d9c 100644 --- a/SynchronyFinancial/SynchronyFinancial/Defaults.swift +++ b/SynchronyFinancial/SynchronyFinancial/Defaults.swift @@ -19,7 +19,7 @@ final class Defaults { static let MAKE_PAYMENT_URL = "https://syf-paysol-mocks.getsandbox.com/paysol/payment/api/rest/v1_0/make_payment" static let defaultHeader = ["channel": "AW", "device_id": "apple_watch", "trans_id": "apple_watch"] - static let token = UserDefaults.standard.string(forKey: "access_token") as! String + static let token = UserDefaults.standard.string(forKey: "access_token") ?? "" static let authHeader = ["Authorization": "Bearer \(token)"] static var headerForLogin: [String: Any] = {