You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

397 lines
16 KiB

  1. //
  2. // InboundReceiptViewController.swift
  3. // GME Remit
  4. //
  5. // Created by InKwon James Kim on 2019/11/14.
  6. //Copyright © 2019 Gobal Money Express Co. Ltd. All rights reserved.
  7. //
  8. import UIKit
  9. import RxSwift
  10. import RxCocoa
  11. enum ReceiptDetailType {
  12. case inBound, reedem
  13. }
  14. class InboundReceiptViewController: UIViewController {
  15. // MARK: Properties
  16. var presenter: InboundReceiptPresenter!
  17. var receiptType: ReceiptDetailType = .inBound
  18. var password: String = ""{
  19. didSet{
  20. if password != ""{
  21. self.presenter.redeem(password: self.password)
  22. }
  23. }
  24. }
  25. private let disposeBag = DisposeBag()
  26. // MARK: Computed Properties
  27. // MARK: IBOutlets
  28. @IBOutlet weak var contactNoView: UIView!
  29. @IBOutlet weak var transactionDateView: UIView!
  30. @IBOutlet weak var senderView: UIView!
  31. @IBOutlet weak var receiverView: UIView!
  32. @IBOutlet weak var addressView: UIView!
  33. @IBOutlet weak var mobileNoView: UIView!
  34. @IBOutlet weak var payoutAgentView: UIView!
  35. @IBOutlet weak var bankNameView: UIView!
  36. @IBOutlet weak var bankAccountView: UIView!
  37. @IBOutlet weak var totalReceivedAmountView: UIView!
  38. @IBOutlet weak var totalSentAmountView: UIView!
  39. @IBOutlet weak var serviceFeeView: UIView!
  40. @IBOutlet weak var exRateView: UIView!
  41. @IBOutlet private weak var statusTitleLabel: UILabel!
  42. @IBOutlet private weak var senderCountryImageView: UIImageView!
  43. @IBOutlet private weak var senderCountryNameLabel: UILabel!
  44. @IBOutlet private weak var receiveBankImageView: UIImageView!
  45. @IBOutlet private weak var receiverCountryNameLabel: UILabel!
  46. @IBOutlet private weak var messageContainerView: UIStackView!
  47. @IBOutlet private weak var messageTitleLabel: UILabel!
  48. @IBOutlet private weak var bankNameLabel: UILabel!
  49. @IBOutlet private weak var bankAccountLabel: UILabel!
  50. @IBOutlet private weak var senderToGMEProcess: UIView!
  51. @IBOutlet private weak var gmeToReceiverProcess: UIView!
  52. @IBOutlet private weak var controlTitleLabel: UILabel!
  53. @IBOutlet private weak var controlContentLabel: UILabel!
  54. @IBOutlet private weak var transactionDateTitleLabel: UILabel!
  55. @IBOutlet private weak var transactionDateContentLabel: UILabel!
  56. @IBOutlet private weak var senderNameTitleLabel: UILabel!
  57. @IBOutlet private weak var senderNameContentLabel: UILabel!
  58. @IBOutlet private weak var receiverNameTitleLabel: UILabel!
  59. @IBOutlet private weak var receiverNameContentLabel: UILabel!
  60. @IBOutlet private weak var addressTitleLabel: UILabel!
  61. @IBOutlet private weak var addressContentLabel: UILabel!
  62. @IBOutlet private weak var mobileTitleLabel: UILabel!
  63. @IBOutlet private weak var mobileContentLabel: UILabel!
  64. @IBOutlet private weak var payOutAgentTitleLabel: UILabel!
  65. @IBOutlet private weak var payOutAgentContentLabel: UILabel!
  66. @IBOutlet private weak var bankTitleLabel: UILabel!
  67. @IBOutlet private weak var bankContentLabel: UILabel!
  68. @IBOutlet private weak var bankAccountTitleLabel: UILabel!
  69. @IBOutlet private weak var bankAccountContentLabel: UILabel!
  70. @IBOutlet private weak var amountTitleLabel: UILabel!
  71. @IBOutlet private weak var amountContentsLabel: UILabel!
  72. @IBOutlet private weak var totalSentAmountTitleLabel: UILabel!
  73. @IBOutlet private weak var totalSentAmountContentLabel: UILabel!
  74. @IBOutlet private weak var serviceFeeTitleLabel: UILabel!
  75. @IBOutlet private weak var serviceFeeContentLabel: UILabel!
  76. @IBOutlet private weak var exRateTitleLabel: UILabel!
  77. @IBOutlet private weak var exRateContentLabel: UILabel!
  78. @IBOutlet private weak var cancelButton: UIButton!
  79. @IBOutlet private weak var registerButton: UIButton!
  80. @IBOutlet weak var reedemButton: UIButton!
  81. @IBOutlet private weak var bankMessageContainerView: UIStackView!
  82. @IBOutlet private weak var buttonContainerView: UIStackView!
  83. // MARK: VC's Life cycle
  84. override func viewDidLoad() {
  85. super.viewDidLoad()
  86. //In case of Inbound following are shown
  87. self.contactNoView.isHidden = !(self.receiptType == .inBound)
  88. self.senderView.isHidden = !(self.receiptType == .inBound)
  89. self.bankNameView.isHidden = !(self.receiptType == .inBound)
  90. self.bankAccountView.isHidden = !(self.receiptType == .inBound)
  91. self.totalReceivedAmountView.isHidden = !(self.receiptType == .inBound)
  92. self.cancelButton.isHidden = !(self.receiptType == .inBound)
  93. self.registerButton.isHidden = !(self.receiptType == .inBound)
  94. self.bankNameLabel.isHidden = !(self.receiptType == .inBound)
  95. self.bankAccountLabel.isHidden = !(self.receiptType == .inBound)
  96. //In case of Redeem following are shown
  97. self.receiverView.isHidden = !(self.receiptType == .reedem)
  98. self.addressView.isHidden = !(self.receiptType == .reedem)
  99. self.payoutAgentView.isHidden = true//!(self.receiptType == .reedem)
  100. self.totalSentAmountView.isHidden = !(self.receiptType == .reedem)
  101. self.exRateView.isHidden = !(self.receiptType == .reedem)
  102. setup()
  103. }
  104. override func viewWillAppear(_ animated: Bool) {
  105. super.viewWillAppear(animated)
  106. title = (self.receiptType == .inBound) ? "inbound_receipt_text".localized() : "redeem_cash_pickup_text".localized()
  107. }
  108. override func viewWillDisappear(_ animated: Bool) {
  109. super.viewWillDisappear(animated)
  110. title = ""
  111. }
  112. // MARK: IBActions
  113. @IBAction func redeem(_ sender: Any) {
  114. if let isUseBiometric = KeyChain.shared.get(key: .biometricAuth), isUseBiometric == "1" {
  115. let biometricAuthenticationWireframe = BiometricAuthenticationWireframe()
  116. biometricAuthenticationWireframe.openWithDelegate(on: self, delegate: self)
  117. } else {
  118. showSecureKeyPad()
  119. }
  120. }
  121. private func showSecureKeyPad() {
  122. self.openPasswordInput { (value) in
  123. self.password = value
  124. }
  125. }
  126. }
  127. // MARK: Other Functions
  128. extension InboundReceiptViewController {
  129. private func setup() {
  130. setUI()
  131. setBinding()
  132. }
  133. private func setUI() {
  134. messageContainerView.isHidden = true
  135. senderToGMEProcess.layer.cornerRadius = 2
  136. gmeToReceiverProcess.layer.cornerRadius = 2
  137. senderToGMEProcess.isHidden = true
  138. gmeToReceiverProcess.isHidden = true
  139. registerButton.isHidden = true
  140. cancelButton.isHidden = true
  141. reedemButton.isHidden = true
  142. if self.receiptType == .inBound{
  143. receiverCountryNameLabel.text = GMEDB.shared.user.string(.fullName)
  144. }else{
  145. receiverCountryNameLabel.text = "Mongolia"
  146. }
  147. registerButton.titleLabel?.minimumScaleFactor = 0.5
  148. registerButton.titleLabel?.adjustsFontSizeToFitWidth = true
  149. registerButton.titleLabel?.numberOfLines = 2
  150. registerButton.titleLabel?.textAlignment = .center
  151. registerButton.layer.cornerRadius = 5
  152. DispatchQueue.main.async {[weak self] in
  153. self?.controlTitleLabel.text = "control_no_text".localized()
  154. self?.transactionDateTitleLabel.text = "transaction_date_text".localized()
  155. self?.senderNameTitleLabel.text = "sender_name_text".localized()
  156. self?.mobileTitleLabel.text = "mobile_number_text".localized()
  157. self?.bankTitleLabel.text = "bank_text".localized()
  158. self?.bankAccountTitleLabel.text = "account_text".localized()
  159. self?.amountTitleLabel.text = "received_amount_text".localized()
  160. self?.serviceFeeTitleLabel.text = "service_fee_text".localized()
  161. self?.registerButton.setTitle("register_account_text".localized(), for: .normal)
  162. self?.cancelButton.setTitle("cancel_text".localized(), for: .normal)
  163. self?.receiverNameTitleLabel.text = "receiver_text".localized()
  164. self?.addressTitleLabel.text = "address_text".localized()
  165. self?.payOutAgentTitleLabel.text = "payout_agent_text".localized()
  166. self?.totalSentAmountTitleLabel.text = "total_sent_amount_text".localized()
  167. self?.exRateTitleLabel.text = "ex_rate_text".localized()
  168. self?.reedemButton.setTitle("redeem_text".localized(), for: .normal)
  169. }
  170. }
  171. private func setBinding() {
  172. let viewWillAppear = rx.sentMessage(#selector(UIViewController.viewWillAppear(_:)))
  173. .mapToVoid()
  174. .asDriverOnErrorJustComplete()
  175. let input = InboundReceiptPresenter.Input(
  176. viewWillAppear: viewWillAppear,
  177. register: registerButton.rx.tap.asDriverOnErrorJustComplete(),
  178. cancel: cancelButton.rx.tap.asDriverOnErrorJustComplete()
  179. )
  180. let output = presenter.transform(input: input)
  181. output.isError
  182. .drive(
  183. onNext: { self.alert(type: .error, message: $0.localizedDescription) }
  184. ).disposed(by: disposeBag)
  185. output.isProgress
  186. .drive(
  187. onNext: { $0 ? self.showProgressHud() : self.hideProgressHud() }
  188. ).disposed(by: disposeBag)
  189. output.model.map {$0.senderCountryName}.drive(senderCountryNameLabel.rx.text).disposed(by: disposeBag)
  190. output.model.map {$0.controlNumber}.drive(controlContentLabel.rx.text).disposed(by: disposeBag)
  191. output.model.map {$0.tranDate}.drive(transactionDateContentLabel.rx.text).disposed(by: disposeBag)
  192. output.model.map {$0.senderName}.drive(senderNameContentLabel.rx.text).disposed(by: disposeBag)
  193. output.model.map {$0.receiverName}.drive(receiverNameContentLabel.rx.text).disposed(by: disposeBag)
  194. output.model.map {$0.receiverAddress}.drive(addressContentLabel.rx.text).disposed(by: disposeBag)
  195. output.model.map {$0.receiverMobile}.drive(mobileContentLabel.rx.text).disposed(by: disposeBag)
  196. output.model.map {$0.payOutMode}.drive(payOutAgentContentLabel.rx.text).disposed(by: disposeBag)
  197. output.model.map {$0.bankName}.drive(bankContentLabel.rx.text).disposed(by: disposeBag)
  198. output.model.map {$0.bankName}.drive(bankNameLabel.rx.text).disposed(by: disposeBag)
  199. output.model.map {$0.accountNo}.drive(bankAccountContentLabel.rx.text).disposed(by: disposeBag)
  200. output.model.map {$0.accountNo}.drive(bankAccountLabel.rx.text).disposed(by: disposeBag)
  201. output.model
  202. .map {$0.receivedAmount?.decimalToCurrency(as: .krw, isFront: false)}
  203. .drive(amountContentsLabel.rx.text).disposed(by: disposeBag)
  204. output.model
  205. .map {$0.receivedAmount?.decimalToCurrency(as: .krw, isFront: false)}
  206. .drive(totalSentAmountContentLabel.rx.text).disposed(by: disposeBag)
  207. output.model.map {$0.serviceFee?.decimalToCurrency(as: .krw, isFront: false)}
  208. .drive(serviceFeeContentLabel.rx.text).disposed(by: disposeBag)
  209. output.model
  210. .map {($0.exrate ?? "0").decimalToCurrency(as: .krw, isFront: false)}
  211. .drive(exRateContentLabel.rx.text).disposed(by: disposeBag)
  212. output.model.map {(self.receiptType == .inBound) ? BankEnum(rawValue: $0.bankCode ?? "")?.ciImage : CountryEnum.mn.flag}
  213. .drive(receiveBankImageView.rx.image).disposed(by: disposeBag)
  214. output.model.map {($0.isAccountReg ?? true) && self.receiptType == .reedem}
  215. .drive(bankMessageContainerView.rx.isHidden).disposed(by: disposeBag)
  216. output.model.map {CountryEnum(rawValue: $0.senderCountryCode?.lowercased() ?? "")?.flag}
  217. .drive(senderCountryImageView.rx.image).disposed(by: disposeBag)
  218. Driver.combineLatest(output.model.map { $0.isAccountReg ?? true}, output.model.map { $0.controlNumber }, output.status)
  219. .drive(onNext: {[weak self] (isRegister, controlNumber, status)in
  220. switch status {
  221. case .processing:
  222. let message = isRegister ?
  223. "transaction_will_be_processed_text".localized() : "you_have_to_register_text".localized()
  224. self?.messageContainerView.isHidden = false
  225. self?.messageTitleLabel.text = message
  226. self?.statusTitleLabel.text = "transfer_processing_text".localized()
  227. self?.senderToGMEProcess.isHidden = false
  228. self?.gmeToReceiverProcess.isHidden = true
  229. self?.registerButton.isHidden = isRegister
  230. self?.cancelButton.isHidden = isRegister
  231. case .paid:
  232. self?.statusTitleLabel.text = "transfer_success_text".localized()
  233. self?.senderToGMEProcess.isHidden = false
  234. self?.gmeToReceiverProcess.isHidden = false
  235. self?.messageContainerView.isHidden = true
  236. case .cancel:
  237. self?.statusTitleLabel.text = "transfer_canceled_text".localized()
  238. self?.senderToGMEProcess.isHidden = true
  239. self?.gmeToReceiverProcess.isHidden = true
  240. self?.messageContainerView.isHidden = true
  241. case .unpaid:
  242. self?.statusTitleLabel.text = "transfer_pending_text".localized()
  243. self?.senderToGMEProcess.isHidden = (self?.receiptType != .reedem)
  244. self?.gmeToReceiverProcess.isHidden = (self?.receiptType != .reedem)
  245. self?.messageContainerView.isHidden = (self?.receiptType != .reedem)
  246. self?.messageTitleLabel.text = "control_number_text".localized() + " \(controlNumber ?? "")"
  247. self?.reedemButton.isHidden = (self?.receiptType != .reedem)
  248. }
  249. }
  250. ).disposed(by: disposeBag)
  251. }
  252. }
  253. // MARK: - BiometricAuthenticationViewControllerDelegate
  254. extension InboundReceiptViewController: BiometricAuthenticationViewControllerDelegate {
  255. func viewController(
  256. _ viewController: BiometricAuthenticationViewController,
  257. didFailWithError error: BiometricAuthenticationError, errorMessage: String?) {
  258. print("BiometricAuthenticationWireframe Error: \(errorMessage ?? "")")
  259. viewController.dismiss(animated: true) {
  260. switch error {
  261. case .userFallback:
  262. self.showSecureKeyPad()
  263. case .authenticationFailed, .userCancel, .biometryNotAvailable,
  264. .biometryNotEnrolled, .biometryLockout, .notBeConfigured:
  265. self.alert(type: .error, message: error.message)
  266. }
  267. }
  268. }
  269. func doSelectLocalAuthenticationPolicy(
  270. _ viewController: BiometricAuthenticationViewController
  271. ) -> BiometricAuthenticationPolicy {
  272. return .deviceOwnerAuthenticationWithBiometrics
  273. }
  274. func didComplete(_ viewController: BiometricAuthenticationViewController) {
  275. viewController.dismiss(animated: true) {
  276. guard let encryptedPW = KeyChain.shared.get(key: .password) else {
  277. MainWireframe.logoutWarningAlert(message: "To use biometrics authentication you have to login again.")
  278. return
  279. }
  280. self.password = encryptedPW
  281. }
  282. }
  283. func viewController(
  284. _ viewController: BiometricAuthenticationViewController,
  285. informationTitleLabel titleLabel: UILabel,
  286. authenticationButton button: UIButton
  287. ) {
  288. titleLabel.text = "use_biometric_authentication_text".localized()
  289. button.setTitle("verify_account_button_text".localized(), for: .normal)
  290. }
  291. }
  292. // MARK: InboundReceiptViewInterface
  293. extension InboundReceiptViewController: InboundReceiptViewInterface {
  294. func showLoading() {
  295. self.showProgressHud()
  296. }
  297. func hideLoading() {
  298. self.hideProgressHud()
  299. }
  300. func show(error: String) {
  301. self.alert(type: .error, message: error)
  302. }
  303. func show(message: String) {
  304. self.alertWithOk(
  305. type: .success,
  306. message: message,
  307. title: "success_text".localized(),
  308. okTitle: "Ok"
  309. ) {
  310. self.navigationController?.popToRootViewController(animated: true)
  311. }
  312. }
  313. }