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
441 lines
19 KiB
//
|
|
// SetupRecipientViewModel.swift
|
|
// GME Remit
|
|
//
|
|
// Created by InKwon James Kim on 09/08/2019.
|
|
//Copyright © 2019 Gobal Money Express Co. Ltd. All rights reserved.
|
|
//
|
|
|
|
import RxSwift
|
|
import RxCocoa
|
|
|
|
class SetupRecipientViewModel: ViewModelType {
|
|
struct Input {
|
|
let initialTrigger: Driver<Void>
|
|
let openCountryTrigger: Driver<Void>
|
|
let openPaymentTrigger: Driver<Void>
|
|
let openBankTrigger: Driver<Void>
|
|
let openBranchTrigger: Driver<Void>
|
|
let openIDTypeTrigger: Driver<Void>
|
|
let openStateProvinceTrigger: Driver<Void>
|
|
let openDistrictTrigger: Driver<Void>
|
|
let openRelationTrigger: Driver<Void>
|
|
let openReasonTrigger: Driver<Void>
|
|
let openNativeCountryTrigger: Driver<Void>
|
|
let saveTrigger: Driver<Recipient>
|
|
}
|
|
|
|
struct Output {
|
|
let isError: Driver<Error>
|
|
let isProgress: Driver<Bool>
|
|
let success: Driver<ResponseContainerObject<Recipient>>
|
|
let models: Models
|
|
let selectedRecipient: Driver<Recipient?>
|
|
let selectedCountry: Driver<CountryAndServiceModel?>
|
|
let selectedPaymentMode: Driver<PaymentServiceType?>
|
|
let selectedBank: Driver<SendMoneyBank?>
|
|
let selectedBranch: Driver<SendMoneyBankBranch?>
|
|
let selectedIDType: Driver<ReceiverIdType?>
|
|
let selectedStateProvince: Driver<Provience?>
|
|
let selectedDistrict: Driver<District?>
|
|
let selectedRelation: Driver<Relation?>
|
|
let selectedReason: Driver<TransferReason?>
|
|
let selectedNativeCountry: Driver<NativeCountryModel?>
|
|
}
|
|
|
|
struct Models {
|
|
let countryServicesModel: Driver<[CountryAndServiceModel]>
|
|
let paymentModel: Driver<[PaymentServiceType]>
|
|
let dynamicFieldsModel: Driver<[FieldModel]>
|
|
}
|
|
|
|
// Linker
|
|
private let progressLinker = PublishSubject<Bool>()
|
|
private let errorLinker = PublishSubject<Error>()
|
|
private let successLinker = PublishSubject<ResponseContainerObject<Recipient>>()
|
|
private let dynamicFieldsLinker = PublishSubject<[FieldModel]>()
|
|
|
|
// Models Linker
|
|
private let countryServicesLinker = PublishSubject<[CountryAndServiceModel]>()
|
|
private let paymentModeTypesLinker = PublishSubject<[PaymentServiceType]>()
|
|
private let banksLinker = PublishSubject<[SendMoneyBank]>()
|
|
private let idTypeLinker = PublishSubject<[ReceiverIdType]>()
|
|
private let stateProvincesLinker = PublishSubject<[Provience]>()
|
|
private let relationsLinker = PublishSubject<[Relation]>()
|
|
private let reasonsLinker = PublishSubject<[TransferReason]>()
|
|
private let nativeCountiresLinker = PublishSubject<[NativeCountryModel]>()
|
|
|
|
// Selected Model Linker
|
|
private let selectedRecipientLinker = BehaviorSubject<Recipient?>(value: nil)
|
|
private let selectedCountryServicesLinker = BehaviorSubject<CountryAndServiceModel?>(value: nil)
|
|
private let selectedPaymentModeTypesLinker = BehaviorSubject<PaymentServiceType?>(value: nil)
|
|
private let selectedBankLinker = BehaviorSubject<SendMoneyBank?>(value: nil)
|
|
private let selectedBranchLinker = BehaviorSubject<SendMoneyBankBranch?>(value: nil)
|
|
private let selectedIDTypeLinker = BehaviorSubject<ReceiverIdType?>(value: nil)
|
|
private let selectedStateProvinceLinker = BehaviorSubject<Provience?>(value: nil)
|
|
private let selectedDistrictLinker = BehaviorSubject<District?>(value: nil)
|
|
private let selectedRelationLinker = BehaviorSubject<Relation?>(value: nil)
|
|
private let selectedReasonLinker = BehaviorSubject<TransferReason?>(value: nil)
|
|
private let selectedNativeCountryLinker = BehaviorSubject<NativeCountryModel?>(value: nil)
|
|
|
|
// Properties
|
|
var presenter: SetupRecipientModuleInterface?
|
|
var isFirst = true
|
|
var payoutPartner: String?
|
|
|
|
private let disposeBag = DisposeBag()
|
|
|
|
func transform(input: Input) -> Output {
|
|
let countryServicesModel = countryServicesLinker.asDriverOnErrorJustComplete()
|
|
let paymentModeModel = paymentModeTypesLinker.asDriverOnErrorJustComplete()
|
|
let dynamicModel = dynamicFieldsLinker.asDriverOnErrorJustComplete()
|
|
let banksModel = banksLinker.asDriverOnErrorJustComplete()
|
|
let idTypesModel = idTypeLinker.asDriverOnErrorJustComplete()
|
|
let stateProvicesModel = stateProvincesLinker.asDriverOnErrorJustComplete()
|
|
let relationsModel = relationsLinker.asDriverOnErrorJustComplete()
|
|
let reasonsModel = reasonsLinker.asDriverOnErrorJustComplete()
|
|
|
|
let branchesModel = Observable.combineLatest(selectedCountryServicesLinker, selectedBankLinker)
|
|
.asDriverOnErrorJustComplete()
|
|
|
|
let districtsModel = selectedStateProvinceLinker.flatMap {Observable.just($0?.districts ?? [])}
|
|
.asDriverOnErrorJustComplete()
|
|
|
|
let nativeCountrisModel = nativeCountiresLinker.asDriverOnErrorJustComplete()
|
|
|
|
let model = Models(
|
|
countryServicesModel: countryServicesModel,
|
|
paymentModel: paymentModeModel,
|
|
dynamicFieldsModel: dynamicModel
|
|
)
|
|
|
|
// FetchCountriesAndServiceTypes
|
|
input.initialTrigger.drive(onNext: { [weak self] in guard let `self` = self else { return }
|
|
self.presenter?.fetchCountriesAndServiceTypes()
|
|
}).disposed(by: disposeBag)
|
|
|
|
// Handle open select country
|
|
input.openCountryTrigger.withLatestFrom(countryServicesModel) {$1}
|
|
.drive(onNext: { [weak self] in guard let `self` = self else { return }
|
|
self.presenter?.openSelectMode(with: $0, type: .country)
|
|
}).disposed(by: disposeBag)
|
|
|
|
// Handle open select payment mode
|
|
input.openPaymentTrigger.withLatestFrom(paymentModeModel) {$1}
|
|
.drive(onNext: { [weak self] in guard let `self` = self else { return }
|
|
self.presenter?.openSelectMode(with: $0, type: .paymentMode)
|
|
}).disposed(by: disposeBag)
|
|
|
|
// Handle open select bank
|
|
input.openBankTrigger.withLatestFrom(banksModel) {$1}
|
|
.drive(onNext: { [weak self] in guard let `self` = self else { return }
|
|
self.presenter?.openSelectMode(with: $0, type: .bank)
|
|
}).disposed(by: disposeBag)
|
|
|
|
// Handle open select branch
|
|
input.openBranchTrigger.withLatestFrom(branchesModel) { $1 }
|
|
.drive(onNext: { [weak self] in guard let `self` = self else { return }
|
|
self.presenter?.openBranches(countryCode: $0.0?.countryCode ?? "", bankID: $0.1?.id ?? "")
|
|
}).disposed(by: disposeBag)
|
|
|
|
// Handle open select id type
|
|
input.openIDTypeTrigger.withLatestFrom(idTypesModel) {$1}
|
|
.drive(onNext: { [weak self] in guard let `self` = self else { return }
|
|
self.presenter?.openSelectMode(with: $0, type: .idType)
|
|
}).disposed(by: disposeBag)
|
|
|
|
// Handle open select state
|
|
input.openStateProvinceTrigger.withLatestFrom(stateProvicesModel) {$1}
|
|
.drive(onNext: { [weak self] in guard let `self` = self else { return }
|
|
self.presenter?.openSelectMode(with: $0, type: .stateProvince)
|
|
})
|
|
.disposed(by: disposeBag)
|
|
|
|
// Handle open select district
|
|
input.openDistrictTrigger.withLatestFrom(districtsModel) {$1}
|
|
.drive(onNext: { [weak self] in guard let `self` = self else { return }
|
|
self.presenter?.openSelectMode(with: $0, type: .district)
|
|
}).disposed(by: disposeBag)
|
|
|
|
// Handle open select relation
|
|
input.openRelationTrigger.withLatestFrom(relationsModel) {$1}
|
|
.drive(onNext: { [weak self] in guard let `self` = self else { return }
|
|
self.presenter?.openSelectMode(with: $0, type: .relation)
|
|
}).disposed(by: disposeBag)
|
|
|
|
// Handle open select reason
|
|
input.openReasonTrigger.withLatestFrom(reasonsModel) {$1}
|
|
.drive(onNext: { [weak self] in guard let `self` = self else { return }
|
|
self.presenter?.openSelectMode(with: $0, type: .reason)
|
|
}).disposed(by: disposeBag)
|
|
|
|
input.openNativeCountryTrigger.withLatestFrom(nativeCountrisModel) {$1}
|
|
.drive(onNext: { [weak self] in guard let `self` = self else { return }
|
|
self.presenter?.openSelectMode(with: $0, type: .nativeCountry)
|
|
})
|
|
.disposed(by: disposeBag)
|
|
|
|
// // Handle save event
|
|
input.saveTrigger
|
|
.drive(onNext: { [weak self] in guard let `self` = self else { return }
|
|
let selectedCountry = try? self.selectedCountryServicesLinker.value()
|
|
let selectedPaymentMode = try? self.selectedPaymentModeTypesLinker.value()
|
|
let selectedBank = try? self.selectedBankLinker.value()
|
|
let selectedBranch = try? self.selectedBranchLinker.value()
|
|
let selectedIDType = try? self.selectedIDTypeLinker.value()
|
|
let selectedStateProvince = try? self.selectedStateProvinceLinker.value()
|
|
let selectedDistrict = try? self.selectedDistrictLinker.value()
|
|
// let selectedRelation = try? self.selectedRelationLinker.value()
|
|
// let selectedReason = try? self.selectedReasonLinker.value()
|
|
let selectedRecipient = try? self.selectedRecipientLinker.value()
|
|
let selectedNativeCountry = try? self.selectedNativeCountryLinker.value()
|
|
|
|
var recipient = $0
|
|
recipient.receiverID = selectedRecipient?.receiverID
|
|
|
|
recipient.country = selectedCountry?.countryName
|
|
recipient.countryID = selectedCountry?.countryId
|
|
recipient.countryCode = selectedCountry?.countryCode
|
|
|
|
recipient.paymentMethod?.id = selectedPaymentMode?.id
|
|
recipient.paymentMethod?.name = selectedPaymentMode?.type
|
|
recipient.paymentMethod?.localizedName = selectedPaymentMode?.subtitle
|
|
recipient.paymentMethod?.currency = selectedPaymentMode?.currency
|
|
|
|
recipient.agent = selectedBank?.toAgentModel()
|
|
recipient.agent?.accountNumber = $0.agent?.accountNumber
|
|
recipient.agent?.branch = selectedBranch?.toBranchModel()
|
|
|
|
recipient.idType = selectedIDType?.id
|
|
|
|
recipient.state = selectedStateProvince?.name
|
|
recipient.stateID = selectedStateProvince?.id
|
|
|
|
recipient.district = selectedDistrict?.name
|
|
recipient.districtID = selectedDistrict?.id
|
|
|
|
// recipient.relationship = selectedRelation?.title
|
|
// recipient.relationshipID = selectedRelation?.id
|
|
|
|
// recipient.purposeOfRemit = selectedReason?.title
|
|
// recipient.purposeOfRemitID = selectedReason?.id
|
|
|
|
recipient.nativeCountry = selectedNativeCountry?.text
|
|
recipient.nativeCountryID = selectedNativeCountry?.id
|
|
recipient.nativeCountryCode = selectedNativeCountry?.code
|
|
|
|
if selectedBank?.accountValidationRequired == "True" {
|
|
guard
|
|
let firstName = recipient.firstName,
|
|
let lastName = recipient.lastName else { return }
|
|
|
|
let name: String
|
|
|
|
if firstName == "" {
|
|
name = recipient.fullName ?? ""
|
|
} else if let middleName = recipient.middleName, middleName != "" {
|
|
name = "\(firstName) \(middleName)"
|
|
} else {
|
|
name = firstName
|
|
}
|
|
|
|
let validateModel = ValidateAccountRequest(
|
|
firstName: name,
|
|
lastName: lastName,
|
|
accountType: "1",
|
|
accountNumber: recipient.agent?.accountNumber ?? "",
|
|
amount: "10000.0",
|
|
processID: "",
|
|
payoutPartner: self.payoutPartner ?? "",
|
|
country: selectedCountry,
|
|
paymentMethod: selectedPaymentMode,
|
|
bank: selectedBank,
|
|
branch: recipient.agent?.branch
|
|
)
|
|
self.presenter?.validateAccount(with: validateModel, recipient: recipient)
|
|
} else {
|
|
self.presenter?.saveRecipient(at: recipient)
|
|
}
|
|
})
|
|
.disposed(by: disposeBag)
|
|
|
|
return Output(
|
|
isError: errorLinker.asDriverOnErrorJustComplete(),
|
|
isProgress: progressLinker.asDriverOnErrorJustComplete(),
|
|
success: successLinker.asDriverOnErrorJustComplete(),
|
|
models: model,
|
|
selectedRecipient: selectedRecipientLinker.asDriverOnErrorJustComplete(),
|
|
selectedCountry: selectedCountryServicesLinker.asDriverOnErrorJustComplete(),
|
|
selectedPaymentMode: selectedPaymentModeTypesLinker.asDriverOnErrorJustComplete(),
|
|
selectedBank: selectedBankLinker.asDriverOnErrorJustComplete(),
|
|
selectedBranch: selectedBranchLinker.asDriverOnErrorJustComplete(),
|
|
selectedIDType: selectedIDTypeLinker.asDriverOnErrorJustComplete(),
|
|
selectedStateProvince: selectedStateProvinceLinker.asDriverOnErrorJustComplete(),
|
|
selectedDistrict: selectedDistrictLinker.asDriverOnErrorJustComplete(),
|
|
selectedRelation: selectedRelationLinker.asDriverOnErrorJustComplete(),
|
|
selectedReason: selectedReasonLinker.asDriverOnErrorJustComplete(),
|
|
selectedNativeCountry: selectedNativeCountryLinker.asDriverOnErrorJustComplete()
|
|
)
|
|
}
|
|
}
|
|
|
|
// MARK: SetupRecipient view interface
|
|
extension SetupRecipientViewModel: SetupRecipientViewModelInterface {
|
|
func setCoutryServices(with model: [CountryAndServiceModel], recipient: Recipient?) {
|
|
countryServicesLinker.onNext(model)
|
|
|
|
guard let recipient = recipient else { return }
|
|
|
|
selectedRecipientLinker.onNext(recipient)
|
|
|
|
// If exist selected recipient, auto select country and payment mode of selected recipient.
|
|
setSelectedData(with: model.filter({$0.countryCode == recipient.countryCode}).first, type: .country)
|
|
let selectedCountry = try? selectedCountryServicesLinker.value()
|
|
setSelectedData(
|
|
with: selectedCountry?.availableServices?.filter({$0.id == recipient.paymentMethod?.id}).first,
|
|
type: .paymentMode
|
|
)
|
|
}
|
|
|
|
func setDynamicFields(with model: DynamicFieldModel, nativeCountires: [NativeCountryModel]) {
|
|
dynamicFieldsLinker.onNext(model.dynamicField ?? [])
|
|
reasonsLinker.onNext(model.transferReasons ?? [])
|
|
relationsLinker.onNext(model.relations ?? [])
|
|
idTypeLinker.onNext(model.idTypes ?? [])
|
|
banksLinker.onNext(model.banks ?? [])
|
|
stateProvincesLinker.onNext(model.provinces ?? [])
|
|
nativeCountiresLinker.onNext(nativeCountires)
|
|
|
|
payoutPartner = model.payoutPartner
|
|
|
|
let country = try? selectedCountryServicesLinker.value()
|
|
|
|
// Default native country setting as selected country
|
|
let nativeCountry = nativeCountires.filter({$0.code == country?.countryCode}).first
|
|
setSelectedData(with: nativeCountry, type: .nativeCountry)
|
|
|
|
guard let recipient = try? selectedRecipientLinker.value() else { return }
|
|
|
|
let selectedBank = model.banks?.filter({$0.id == recipient.agent?.id}).first
|
|
// let selectedBranch = selectedBank?.branches?.filter({$0.id == recipient.agent?.branch?.id}).first
|
|
let selectedIDType = model.idTypes?.filter({$0.id == recipient.idType}).first
|
|
let selectedStateProvince = model.provinces?.filter({$0.id == recipient.stateID}).first
|
|
let selectedDistrict = selectedStateProvince?.districts?.filter({$0.id == recipient.districtID}).first
|
|
// let selectedRelation = model.relations?.filter({$0.title == recipient.relationshipID}).first
|
|
// let selectedReason = model.transferReasons?.filter({$0.title == recipient.purposeOfRemitID}).first
|
|
let selectedNativeCountry = nativeCountires.filter({$0.text == recipient.nativeCountry}).first
|
|
|
|
setSelectedData(with: selectedBank, type: .bank)
|
|
setSelectedData(with: recipient.agent?.branch?.toSendMoneyBankBranch(), type: .branch)
|
|
setSelectedData(with: selectedIDType, type: .idType)
|
|
setSelectedData(with: selectedStateProvince, type: .stateProvince)
|
|
setSelectedData(with: selectedDistrict, type: .district)
|
|
// setSelectedData(with: selectedRelation, type: .relation)
|
|
// setSelectedData(with: selectedReason, type: .reason)
|
|
setSelectedData(with: selectedNativeCountry, type: .nativeCountry)
|
|
}
|
|
|
|
func setSelectedData(with model: TablePresenterProtocol?, type: SetupOpenType) {
|
|
switch type {
|
|
case .country:
|
|
guard let model = model as? CountryAndServiceModel else { return }
|
|
selectedCountryServicesLinker.onNext(model)
|
|
selectedPaymentModeTypesLinker.onNext(nil)
|
|
|
|
paymentModeTypesLinker.onNext(model.availableServices ?? [])
|
|
|
|
guard var selectedRecipient = try? selectedRecipientLinker.value() else {
|
|
return
|
|
}
|
|
|
|
if model.countryCode != selectedRecipient.countryCode {
|
|
let countryEnum = CountryEnum(rawValue: selectedRecipient.countryCode?.lowercased() ?? "")
|
|
selectedRecipient.countryCode = model.countryCode
|
|
selectedRecipient.country = model.countryName
|
|
selectedRecipient.countryID = model.countryId
|
|
|
|
selectedRecipient.mobile = selectedRecipient.mobile?.replacingOccurrences(
|
|
of: countryEnum?.phoneCode ?? "",
|
|
with: ""
|
|
)
|
|
|
|
selectedRecipientLinker.onNext(selectedRecipient)
|
|
}
|
|
|
|
case .paymentMode:
|
|
guard let model = model as? PaymentServiceType else { return }
|
|
selectedPaymentModeTypesLinker.onNext(model)
|
|
|
|
if var recipient = try? selectedRecipientLinker.value(), recipient.agent != nil, !isFirst {
|
|
recipient.agent = nil
|
|
selectedRecipientLinker.onNext(recipient)
|
|
}
|
|
|
|
if (try? selectedBankLinker.value()) != nil {
|
|
selectedBankLinker.onNext(nil)
|
|
}
|
|
|
|
if (try? selectedBranchLinker.value()) != nil {
|
|
selectedBranchLinker.onNext(nil)
|
|
}
|
|
|
|
let selectedCountry = try? selectedCountryServicesLinker.value()
|
|
let selectedPaymentMode = try? selectedPaymentModeTypesLinker.value()
|
|
|
|
presenter?.fetchDynamicRecipientFields(country: selectedCountry, paymentMode: selectedPaymentMode)
|
|
isFirst = false
|
|
|
|
case .bank:
|
|
guard let model = model as? SendMoneyBank else { return }
|
|
selectedBankLinker.onNext(model)
|
|
|
|
if let code = model.payoutPartner {
|
|
payoutPartner = code
|
|
}
|
|
|
|
if model.branchRequired?.lowercased() == "true" {
|
|
selectedBranchLinker.onNext(nil)
|
|
}
|
|
case .branch:
|
|
guard let model = model as? SendMoneyBankBranch else { return }
|
|
selectedBranchLinker.onNext(model)
|
|
case .idType:
|
|
guard let model = model as? ReceiverIdType else { return }
|
|
selectedIDTypeLinker.onNext(model)
|
|
case .stateProvince:
|
|
guard let model = model as? Provience else { return }
|
|
selectedStateProvinceLinker.onNext(model)
|
|
|
|
let count = model.districts?.count ?? 0
|
|
if count != 0 {
|
|
selectedBranchLinker.onNext(nil)
|
|
}
|
|
|
|
selectedDistrictLinker.onNext(nil)
|
|
case .district:
|
|
guard let model = model as? District else { return }
|
|
selectedDistrictLinker.onNext(model)
|
|
case .relation:
|
|
guard let model = model as? Relation else { return }
|
|
selectedRelationLinker.onNext(model)
|
|
case .reason:
|
|
guard let model = model as? TransferReason else { return }
|
|
selectedReasonLinker.onNext(model)
|
|
case .nativeCountry:
|
|
guard let model = model as? NativeCountryModel else { return }
|
|
selectedNativeCountryLinker.onNext(model)
|
|
}
|
|
}
|
|
|
|
func setError(with error: Error) {
|
|
errorLinker.onNext(error)
|
|
}
|
|
|
|
func progress(isShow: Bool) {
|
|
progressLinker.onNext(isShow)
|
|
}
|
|
|
|
func success(with model: ResponseContainerObject<Recipient>) {
|
|
successLinker.onNext(model)
|
|
}
|
|
}
|