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.

441 lines
19 KiB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
  1. //
  2. // SetupRecipientViewModel.swift
  3. // GME Remit
  4. //
  5. // Created by InKwon James Kim on 09/08/2019.
  6. //Copyright © 2019 Gobal Money Express Co. Ltd. All rights reserved.
  7. //
  8. import RxSwift
  9. import RxCocoa
  10. class SetupRecipientViewModel: ViewModelType {
  11. struct Input {
  12. let initialTrigger: Driver<Void>
  13. let openCountryTrigger: Driver<Void>
  14. let openPaymentTrigger: Driver<Void>
  15. let openBankTrigger: Driver<Void>
  16. let openBranchTrigger: Driver<Void>
  17. let openIDTypeTrigger: Driver<Void>
  18. let openStateProvinceTrigger: Driver<Void>
  19. let openDistrictTrigger: Driver<Void>
  20. let openRelationTrigger: Driver<Void>
  21. let openReasonTrigger: Driver<Void>
  22. let openNativeCountryTrigger: Driver<Void>
  23. let saveTrigger: Driver<Recipient>
  24. }
  25. struct Output {
  26. let isError: Driver<Error>
  27. let isProgress: Driver<Bool>
  28. let success: Driver<ResponseContainerObject<Recipient>>
  29. let models: Models
  30. let selectedRecipient: Driver<Recipient?>
  31. let selectedCountry: Driver<CountryAndServiceModel?>
  32. let selectedPaymentMode: Driver<PaymentServiceType?>
  33. let selectedBank: Driver<SendMoneyBank?>
  34. let selectedBranch: Driver<SendMoneyBankBranch?>
  35. let selectedIDType: Driver<ReceiverIdType?>
  36. let selectedStateProvince: Driver<Provience?>
  37. let selectedDistrict: Driver<District?>
  38. let selectedRelation: Driver<Relation?>
  39. let selectedReason: Driver<TransferReason?>
  40. let selectedNativeCountry: Driver<NativeCountryModel?>
  41. }
  42. struct Models {
  43. let countryServicesModel: Driver<[CountryAndServiceModel]>
  44. let paymentModel: Driver<[PaymentServiceType]>
  45. let dynamicFieldsModel: Driver<[FieldModel]>
  46. }
  47. // Linker
  48. private let progressLinker = PublishSubject<Bool>()
  49. private let errorLinker = PublishSubject<Error>()
  50. private let successLinker = PublishSubject<ResponseContainerObject<Recipient>>()
  51. private let dynamicFieldsLinker = PublishSubject<[FieldModel]>()
  52. // Models Linker
  53. private let countryServicesLinker = PublishSubject<[CountryAndServiceModel]>()
  54. private let paymentModeTypesLinker = PublishSubject<[PaymentServiceType]>()
  55. private let banksLinker = PublishSubject<[SendMoneyBank]>()
  56. private let idTypeLinker = PublishSubject<[ReceiverIdType]>()
  57. private let stateProvincesLinker = PublishSubject<[Provience]>()
  58. private let relationsLinker = PublishSubject<[Relation]>()
  59. private let reasonsLinker = PublishSubject<[TransferReason]>()
  60. private let nativeCountiresLinker = PublishSubject<[NativeCountryModel]>()
  61. // Selected Model Linker
  62. private let selectedRecipientLinker = BehaviorSubject<Recipient?>(value: nil)
  63. private let selectedCountryServicesLinker = BehaviorSubject<CountryAndServiceModel?>(value: nil)
  64. private let selectedPaymentModeTypesLinker = BehaviorSubject<PaymentServiceType?>(value: nil)
  65. private let selectedBankLinker = BehaviorSubject<SendMoneyBank?>(value: nil)
  66. private let selectedBranchLinker = BehaviorSubject<SendMoneyBankBranch?>(value: nil)
  67. private let selectedIDTypeLinker = BehaviorSubject<ReceiverIdType?>(value: nil)
  68. private let selectedStateProvinceLinker = BehaviorSubject<Provience?>(value: nil)
  69. private let selectedDistrictLinker = BehaviorSubject<District?>(value: nil)
  70. private let selectedRelationLinker = BehaviorSubject<Relation?>(value: nil)
  71. private let selectedReasonLinker = BehaviorSubject<TransferReason?>(value: nil)
  72. private let selectedNativeCountryLinker = BehaviorSubject<NativeCountryModel?>(value: nil)
  73. // Properties
  74. var presenter: SetupRecipientModuleInterface?
  75. var isFirst = true
  76. var payoutPartner: String?
  77. private let disposeBag = DisposeBag()
  78. func transform(input: Input) -> Output {
  79. let countryServicesModel = countryServicesLinker.asDriverOnErrorJustComplete()
  80. let paymentModeModel = paymentModeTypesLinker.asDriverOnErrorJustComplete()
  81. let dynamicModel = dynamicFieldsLinker.asDriverOnErrorJustComplete()
  82. let banksModel = banksLinker.asDriverOnErrorJustComplete()
  83. let idTypesModel = idTypeLinker.asDriverOnErrorJustComplete()
  84. let stateProvicesModel = stateProvincesLinker.asDriverOnErrorJustComplete()
  85. let relationsModel = relationsLinker.asDriverOnErrorJustComplete()
  86. let reasonsModel = reasonsLinker.asDriverOnErrorJustComplete()
  87. let branchesModel = Observable.combineLatest(selectedCountryServicesLinker, selectedBankLinker)
  88. .asDriverOnErrorJustComplete()
  89. let districtsModel = selectedStateProvinceLinker.flatMap {Observable.just($0?.districts ?? [])}
  90. .asDriverOnErrorJustComplete()
  91. let nativeCountrisModel = nativeCountiresLinker.asDriverOnErrorJustComplete()
  92. let model = Models(
  93. countryServicesModel: countryServicesModel,
  94. paymentModel: paymentModeModel,
  95. dynamicFieldsModel: dynamicModel
  96. )
  97. // FetchCountriesAndServiceTypes
  98. input.initialTrigger.drive(onNext: { [weak self] in guard let `self` = self else { return }
  99. self.presenter?.fetchCountriesAndServiceTypes()
  100. }).disposed(by: disposeBag)
  101. // Handle open select country
  102. input.openCountryTrigger.withLatestFrom(countryServicesModel) {$1}
  103. .drive(onNext: { [weak self] in guard let `self` = self else { return }
  104. self.presenter?.openSelectMode(with: $0, type: .country)
  105. }).disposed(by: disposeBag)
  106. // Handle open select payment mode
  107. input.openPaymentTrigger.withLatestFrom(paymentModeModel) {$1}
  108. .drive(onNext: { [weak self] in guard let `self` = self else { return }
  109. self.presenter?.openSelectMode(with: $0, type: .paymentMode)
  110. }).disposed(by: disposeBag)
  111. // Handle open select bank
  112. input.openBankTrigger.withLatestFrom(banksModel) {$1}
  113. .drive(onNext: { [weak self] in guard let `self` = self else { return }
  114. self.presenter?.openSelectMode(with: $0, type: .bank)
  115. }).disposed(by: disposeBag)
  116. // Handle open select branch
  117. input.openBranchTrigger.withLatestFrom(branchesModel) { $1 }
  118. .drive(onNext: { [weak self] in guard let `self` = self else { return }
  119. self.presenter?.openBranches(countryCode: $0.0?.countryCode ?? "", bankID: $0.1?.id ?? "")
  120. }).disposed(by: disposeBag)
  121. // Handle open select id type
  122. input.openIDTypeTrigger.withLatestFrom(idTypesModel) {$1}
  123. .drive(onNext: { [weak self] in guard let `self` = self else { return }
  124. self.presenter?.openSelectMode(with: $0, type: .idType)
  125. }).disposed(by: disposeBag)
  126. // Handle open select state
  127. input.openStateProvinceTrigger.withLatestFrom(stateProvicesModel) {$1}
  128. .drive(onNext: { [weak self] in guard let `self` = self else { return }
  129. self.presenter?.openSelectMode(with: $0, type: .stateProvince)
  130. })
  131. .disposed(by: disposeBag)
  132. // Handle open select district
  133. input.openDistrictTrigger.withLatestFrom(districtsModel) {$1}
  134. .drive(onNext: { [weak self] in guard let `self` = self else { return }
  135. self.presenter?.openSelectMode(with: $0, type: .district)
  136. }).disposed(by: disposeBag)
  137. // Handle open select relation
  138. input.openRelationTrigger.withLatestFrom(relationsModel) {$1}
  139. .drive(onNext: { [weak self] in guard let `self` = self else { return }
  140. self.presenter?.openSelectMode(with: $0, type: .relation)
  141. }).disposed(by: disposeBag)
  142. // Handle open select reason
  143. input.openReasonTrigger.withLatestFrom(reasonsModel) {$1}
  144. .drive(onNext: { [weak self] in guard let `self` = self else { return }
  145. self.presenter?.openSelectMode(with: $0, type: .reason)
  146. }).disposed(by: disposeBag)
  147. input.openNativeCountryTrigger.withLatestFrom(nativeCountrisModel) {$1}
  148. .drive(onNext: { [weak self] in guard let `self` = self else { return }
  149. self.presenter?.openSelectMode(with: $0, type: .nativeCountry)
  150. })
  151. .disposed(by: disposeBag)
  152. // // Handle save event
  153. input.saveTrigger
  154. .drive(onNext: { [weak self] in guard let `self` = self else { return }
  155. let selectedCountry = try? self.selectedCountryServicesLinker.value()
  156. let selectedPaymentMode = try? self.selectedPaymentModeTypesLinker.value()
  157. let selectedBank = try? self.selectedBankLinker.value()
  158. let selectedBranch = try? self.selectedBranchLinker.value()
  159. let selectedIDType = try? self.selectedIDTypeLinker.value()
  160. let selectedStateProvince = try? self.selectedStateProvinceLinker.value()
  161. let selectedDistrict = try? self.selectedDistrictLinker.value()
  162. // let selectedRelation = try? self.selectedRelationLinker.value()
  163. // let selectedReason = try? self.selectedReasonLinker.value()
  164. let selectedRecipient = try? self.selectedRecipientLinker.value()
  165. let selectedNativeCountry = try? self.selectedNativeCountryLinker.value()
  166. var recipient = $0
  167. recipient.receiverID = selectedRecipient?.receiverID
  168. recipient.country = selectedCountry?.countryName
  169. recipient.countryID = selectedCountry?.countryId
  170. recipient.countryCode = selectedCountry?.countryCode
  171. recipient.paymentMethod?.id = selectedPaymentMode?.id
  172. recipient.paymentMethod?.name = selectedPaymentMode?.type
  173. recipient.paymentMethod?.localizedName = selectedPaymentMode?.subtitle
  174. recipient.paymentMethod?.currency = selectedPaymentMode?.currency
  175. recipient.agent = selectedBank?.toAgentModel()
  176. recipient.agent?.accountNumber = $0.agent?.accountNumber
  177. recipient.agent?.branch = selectedBranch?.toBranchModel()
  178. recipient.idType = selectedIDType?.id
  179. recipient.state = selectedStateProvince?.name
  180. recipient.stateID = selectedStateProvince?.id
  181. recipient.district = selectedDistrict?.name
  182. recipient.districtID = selectedDistrict?.id
  183. // recipient.relationship = selectedRelation?.title
  184. // recipient.relationshipID = selectedRelation?.id
  185. // recipient.purposeOfRemit = selectedReason?.title
  186. // recipient.purposeOfRemitID = selectedReason?.id
  187. recipient.nativeCountry = selectedNativeCountry?.text
  188. recipient.nativeCountryID = selectedNativeCountry?.id
  189. recipient.nativeCountryCode = selectedNativeCountry?.code
  190. if selectedBank?.accountValidationRequired == "True" {
  191. guard
  192. let firstName = recipient.firstName,
  193. let lastName = recipient.lastName else { return }
  194. let name: String
  195. if firstName == "" {
  196. name = recipient.fullName ?? ""
  197. } else if let middleName = recipient.middleName, middleName != "" {
  198. name = "\(firstName) \(middleName)"
  199. } else {
  200. name = firstName
  201. }
  202. let validateModel = ValidateAccountRequest(
  203. firstName: name,
  204. lastName: lastName,
  205. accountType: "1",
  206. accountNumber: recipient.agent?.accountNumber ?? "",
  207. amount: "10000.0",
  208. processID: "",
  209. payoutPartner: self.payoutPartner ?? "",
  210. country: selectedCountry,
  211. paymentMethod: selectedPaymentMode,
  212. bank: selectedBank,
  213. branch: recipient.agent?.branch
  214. )
  215. self.presenter?.validateAccount(with: validateModel, recipient: recipient)
  216. } else {
  217. self.presenter?.saveRecipient(at: recipient)
  218. }
  219. })
  220. .disposed(by: disposeBag)
  221. return Output(
  222. isError: errorLinker.asDriverOnErrorJustComplete(),
  223. isProgress: progressLinker.asDriverOnErrorJustComplete(),
  224. success: successLinker.asDriverOnErrorJustComplete(),
  225. models: model,
  226. selectedRecipient: selectedRecipientLinker.asDriverOnErrorJustComplete(),
  227. selectedCountry: selectedCountryServicesLinker.asDriverOnErrorJustComplete(),
  228. selectedPaymentMode: selectedPaymentModeTypesLinker.asDriverOnErrorJustComplete(),
  229. selectedBank: selectedBankLinker.asDriverOnErrorJustComplete(),
  230. selectedBranch: selectedBranchLinker.asDriverOnErrorJustComplete(),
  231. selectedIDType: selectedIDTypeLinker.asDriverOnErrorJustComplete(),
  232. selectedStateProvince: selectedStateProvinceLinker.asDriverOnErrorJustComplete(),
  233. selectedDistrict: selectedDistrictLinker.asDriverOnErrorJustComplete(),
  234. selectedRelation: selectedRelationLinker.asDriverOnErrorJustComplete(),
  235. selectedReason: selectedReasonLinker.asDriverOnErrorJustComplete(),
  236. selectedNativeCountry: selectedNativeCountryLinker.asDriverOnErrorJustComplete()
  237. )
  238. }
  239. }
  240. // MARK: SetupRecipient view interface
  241. extension SetupRecipientViewModel: SetupRecipientViewModelInterface {
  242. func setCoutryServices(with model: [CountryAndServiceModel], recipient: Recipient?) {
  243. countryServicesLinker.onNext(model)
  244. guard let recipient = recipient else { return }
  245. selectedRecipientLinker.onNext(recipient)
  246. // If exist selected recipient, auto select country and payment mode of selected recipient.
  247. setSelectedData(with: model.filter({$0.countryCode == recipient.countryCode}).first, type: .country)
  248. let selectedCountry = try? selectedCountryServicesLinker.value()
  249. setSelectedData(
  250. with: selectedCountry?.availableServices?.filter({$0.id == recipient.paymentMethod?.id}).first,
  251. type: .paymentMode
  252. )
  253. }
  254. func setDynamicFields(with model: DynamicFieldModel, nativeCountires: [NativeCountryModel]) {
  255. dynamicFieldsLinker.onNext(model.dynamicField ?? [])
  256. reasonsLinker.onNext(model.transferReasons ?? [])
  257. relationsLinker.onNext(model.relations ?? [])
  258. idTypeLinker.onNext(model.idTypes ?? [])
  259. banksLinker.onNext(model.banks ?? [])
  260. stateProvincesLinker.onNext(model.provinces ?? [])
  261. nativeCountiresLinker.onNext(nativeCountires)
  262. payoutPartner = model.payoutPartner
  263. let country = try? selectedCountryServicesLinker.value()
  264. // Default native country setting as selected country
  265. let nativeCountry = nativeCountires.filter({$0.code == country?.countryCode}).first
  266. setSelectedData(with: nativeCountry, type: .nativeCountry)
  267. guard let recipient = try? selectedRecipientLinker.value() else { return }
  268. let selectedBank = model.banks?.filter({$0.id == recipient.agent?.id}).first
  269. // let selectedBranch = selectedBank?.branches?.filter({$0.id == recipient.agent?.branch?.id}).first
  270. let selectedIDType = model.idTypes?.filter({$0.id == recipient.idType}).first
  271. let selectedStateProvince = model.provinces?.filter({$0.id == recipient.stateID}).first
  272. let selectedDistrict = selectedStateProvince?.districts?.filter({$0.id == recipient.districtID}).first
  273. // let selectedRelation = model.relations?.filter({$0.title == recipient.relationshipID}).first
  274. // let selectedReason = model.transferReasons?.filter({$0.title == recipient.purposeOfRemitID}).first
  275. let selectedNativeCountry = nativeCountires.filter({$0.text == recipient.nativeCountry}).first
  276. setSelectedData(with: selectedBank, type: .bank)
  277. setSelectedData(with: recipient.agent?.branch?.toSendMoneyBankBranch(), type: .branch)
  278. setSelectedData(with: selectedIDType, type: .idType)
  279. setSelectedData(with: selectedStateProvince, type: .stateProvince)
  280. setSelectedData(with: selectedDistrict, type: .district)
  281. // setSelectedData(with: selectedRelation, type: .relation)
  282. // setSelectedData(with: selectedReason, type: .reason)
  283. setSelectedData(with: selectedNativeCountry, type: .nativeCountry)
  284. }
  285. func setSelectedData(with model: TablePresenterProtocol?, type: SetupOpenType) {
  286. switch type {
  287. case .country:
  288. guard let model = model as? CountryAndServiceModel else { return }
  289. selectedCountryServicesLinker.onNext(model)
  290. selectedPaymentModeTypesLinker.onNext(nil)
  291. paymentModeTypesLinker.onNext(model.availableServices ?? [])
  292. guard var selectedRecipient = try? selectedRecipientLinker.value() else {
  293. return
  294. }
  295. if model.countryCode != selectedRecipient.countryCode {
  296. let countryEnum = CountryEnum(rawValue: selectedRecipient.countryCode?.lowercased() ?? "")
  297. selectedRecipient.countryCode = model.countryCode
  298. selectedRecipient.country = model.countryName
  299. selectedRecipient.countryID = model.countryId
  300. selectedRecipient.mobile = selectedRecipient.mobile?.replacingOccurrences(
  301. of: countryEnum?.phoneCode ?? "",
  302. with: ""
  303. )
  304. selectedRecipientLinker.onNext(selectedRecipient)
  305. }
  306. case .paymentMode:
  307. guard let model = model as? PaymentServiceType else { return }
  308. selectedPaymentModeTypesLinker.onNext(model)
  309. if var recipient = try? selectedRecipientLinker.value(), recipient.agent != nil, !isFirst {
  310. recipient.agent = nil
  311. selectedRecipientLinker.onNext(recipient)
  312. }
  313. if (try? selectedBankLinker.value()) != nil {
  314. selectedBankLinker.onNext(nil)
  315. }
  316. if (try? selectedBranchLinker.value()) != nil {
  317. selectedBranchLinker.onNext(nil)
  318. }
  319. let selectedCountry = try? selectedCountryServicesLinker.value()
  320. let selectedPaymentMode = try? selectedPaymentModeTypesLinker.value()
  321. presenter?.fetchDynamicRecipientFields(country: selectedCountry, paymentMode: selectedPaymentMode)
  322. isFirst = false
  323. case .bank:
  324. guard let model = model as? SendMoneyBank else { return }
  325. selectedBankLinker.onNext(model)
  326. if let code = model.payoutPartner {
  327. payoutPartner = code
  328. }
  329. if model.branchRequired?.lowercased() == "true" {
  330. selectedBranchLinker.onNext(nil)
  331. }
  332. case .branch:
  333. guard let model = model as? SendMoneyBankBranch else { return }
  334. selectedBranchLinker.onNext(model)
  335. case .idType:
  336. guard let model = model as? ReceiverIdType else { return }
  337. selectedIDTypeLinker.onNext(model)
  338. case .stateProvince:
  339. guard let model = model as? Provience else { return }
  340. selectedStateProvinceLinker.onNext(model)
  341. let count = model.districts?.count ?? 0
  342. if count != 0 {
  343. selectedBranchLinker.onNext(nil)
  344. }
  345. selectedDistrictLinker.onNext(nil)
  346. case .district:
  347. guard let model = model as? District else { return }
  348. selectedDistrictLinker.onNext(model)
  349. case .relation:
  350. guard let model = model as? Relation else { return }
  351. selectedRelationLinker.onNext(model)
  352. case .reason:
  353. guard let model = model as? TransferReason else { return }
  354. selectedReasonLinker.onNext(model)
  355. case .nativeCountry:
  356. guard let model = model as? NativeCountryModel else { return }
  357. selectedNativeCountryLinker.onNext(model)
  358. }
  359. }
  360. func setError(with error: Error) {
  361. errorLinker.onNext(error)
  362. }
  363. func progress(isShow: Bool) {
  364. progressLinker.onNext(isShow)
  365. }
  366. func success(with model: ResponseContainerObject<Recipient>) {
  367. successLinker.onNext(model)
  368. }
  369. }