feat: Passcode feature

refactor: Gradle version upgraded and gradle code refactored.

feat: Upload KYC docs UC UI

feat: Upload KYC docs UC core backend

feat: KYC Level 1 UI and Level 2 Backend

fix: KYC Level 2 Backend

feat: KYC Level 2 UI

feat: Add Credit Card UI

fix: Add Credit Card UI

feat: Add Credit Card UI and Backend

feat: Edit and Delete Saved Card UI and Backend

feat: Saved Credit Card UI and Backend

fix: Add, Edit, Update Credit Card UI and Backend.

feat: Tiered KYC and Credit Card Combined

feat: KYC and Credit Card both in Mifos-Pay.

feat: KYC and Saved Credit Card Operations

fix: .travis.yml

fix: android ExampleInstrumentedTest
This commit is contained in:
Ankur Sharma 2018-05-15 17:18:03 +05:30
parent e4a929a9f7
commit fb3aab8cd7
133 changed files with 5131 additions and 264 deletions

23
.travis.yml Normal file
View File

@ -0,0 +1,23 @@
language: android
jdk: oraclejdk8
sudo: required
android:
components:
- tools
- extra-android-support
- extra-google-google_play_services
- extra-android-m2repository
- extra-google-m2repository
- build-tools-26.0.2
- build-tools-27.0.3
- android-26
- android-22
- sys-img-armeabi-v7a-android-22
before_script:
- echo no | android create avd --force -n test -t android-22 --abi armeabi-v7a
- emulator -avd test -no-skin -no-audio -no-window &
- android-wait-for-emulator
- adb shell input keyevent 82 &
script: "./gradlew build connectedAndroidTest --stacktrace"

View File

@ -6,7 +6,6 @@ def RBL_CLIENT_SECRET = '"' + RblClientSecretProp + '"' ?: '"Define Rbl client s
android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
defaultConfig {
applicationId "org.mifos.mobilewallet"
@ -44,47 +43,52 @@ android {
compileOptions.incremental = false
buildToolsVersion '27.0.3'
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support.constraint:constraint-layout:1.1.0'
androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile "com.android.support:appcompat-v7:$rootProject.supportLibraryVersion"
compile "com.android.support:design:$rootProject.supportLibraryVersion"
compile "com.android.support:cardview-v7:$rootProject.supportLibraryVersion"
compile "com.android.support:recyclerview-v7:$rootProject.supportLibraryVersion"
implementation "com.android.support:appcompat-v7:$rootProject.supportLibraryVersion"
implementation "com.android.support:design:$rootProject.supportLibraryVersion"
implementation "com.android.support:cardview-v7:$rootProject.supportLibraryVersion"
implementation "com.android.support:recyclerview-v7:$rootProject.supportLibraryVersion"
compile "com.jakewharton:butterknife:$rootProject.butterKnifeVersion"
implementation "com.jakewharton:butterknife:$rootProject.butterKnifeVersion"
annotationProcessor "com.jakewharton:butterknife-compiler:$rootProject.butterKnifeVersion"
compile 'com.github.lawloretienne:discreteslider:0.0.9'
implementation 'com.github.lawloretienne:discreteslider:0.0.9'
compile 'com.google.dagger:dagger:2.11'
implementation 'com.google.dagger:dagger:2.11'
annotationProcessor 'com.google.dagger:dagger-compiler:2.11'
compile ("com.squareup.retrofit2:retrofit:$rootProject.retrofitVersion") {
implementation("com.squareup.retrofit2:retrofit:$rootProject.retrofitVersion") {
// exclude Retrofits OkHttp peer-dependency module and define your own module import
exclude module: 'okhttp'
}
compile "com.squareup.retrofit2:converter-gson:$rootProject.retrofitVersion"
compile "com.squareup.retrofit2:adapter-rxjava:$rootProject.retrofitVersion"
compile "com.squareup.okhttp3:okhttp:$rootProject.okHttp3Version"
compile "com.squareup.okhttp3:logging-interceptor:$rootProject.okHttp3Version"
implementation "com.squareup.retrofit2:converter-gson:$rootProject.retrofitVersion"
implementation "com.squareup.retrofit2:adapter-rxjava:$rootProject.retrofitVersion"
implementation "com.squareup.okhttp3:okhttp:$rootProject.okHttp3Version"
implementation "com.squareup.okhttp3:logging-interceptor:$rootProject.okHttp3Version"
compile 'io.reactivex:rxandroid:1.1.0'
compile 'io.reactivex:rxjava:1.1.4'
implementation 'io.reactivex:rxandroid:1.1.0'
implementation 'io.reactivex:rxjava:1.1.4'
compile 'com.google.zxing:core:3.2.1'
implementation 'com.google.zxing:core:3.2.1'
annotationProcessor "com.github.Raizlabs.DBFlow:dbflow-processor:$rootProject.dbflowVersion"
compile "com.github.Raizlabs.DBFlow:dbflow-core:$rootProject.dbflowVersion"
compile "com.github.Raizlabs.DBFlow:dbflow:$rootProject.dbflowVersion"
implementation "com.github.Raizlabs.DBFlow:dbflow-core:$rootProject.dbflowVersion"
implementation "com.github.Raizlabs.DBFlow:dbflow:$rootProject.dbflowVersion"
testCompile 'junit:junit:4.12'
testImplementation 'junit:junit:4.12'
implementation project(':core')

View File

@ -1,59 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.mifos.mobilewallet">
package="org.mifos.mobilewallet">
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:name=".MifosWalletApp" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:theme="@style/AppTheme" >
<activity android:name=".auth.ui.LandingActivity"
android:name=".MifosWalletApp"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".auth.ui.LandingActivity"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".auth.ui.LoginActivity"
<activity
android:name=".auth.ui.LoginActivity"
android:theme="@style/AppTheme.NoActionBar">
</activity>
<activity android:name=".auth.ui.SignupActivity"
<activity
android:name=".auth.ui.SignupActivity"
android:theme="@style/AppTheme.NoActionBar"/>
<activity android:name=".auth.ui.AddAccountActivity"
<activity
android:name=".auth.ui.AddAccountActivity"
android:theme="@style/AppTheme.NoActionBar"/>
<activity android:name=".auth.ui.BusinessDetailsActivity"
<activity
android:name=".auth.ui.BusinessDetailsActivity"
android:theme="@style/AppTheme.NoActionBar"/>
<activity android:name=".auth.ui.BankAccountActivity"
<activity
android:name=".auth.ui.BankAccountActivity"
android:theme="@style/AppTheme.NoActionBar"/>
<activity android:name=".auth.ui.SetupCompleteActivity"
<activity
android:name=".auth.ui.SetupCompleteActivity"
android:theme="@style/AppTheme.NoActionBar"/>
<activity android:name=".home.ui.HomeActivity"
<activity
android:name=".home.ui.HomeActivity"
android:theme="@style/AppTheme.NoActionBar"
android:windowSoftInputMode="stateAlwaysHidden">
</activity>
<activity android:name=".user.ui.UserDetailsActivity"
android:theme="@style/AppTheme.NoActionBar" />
<activity android:name=".invoice.ui.PaymentSuccessActivity"
android:theme="@style/AppTheme.NoActionBar" />
<activity android:name=".qr.ui.ShowQrActivity"
android:theme="@style/AppTheme.NoActionBar" />
<activity
android:name=".user.ui.UserDetailsActivity"
android:theme="@style/AppTheme.NoActionBar"/>
<activity
android:name=".invoice.ui.PaymentSuccessActivity"
android:theme="@style/AppTheme.NoActionBar"/>
<activity
android:name=".qr.ui.ShowQrActivity"
android:theme="@style/AppTheme.NoActionBar"/>
</application>
</manifest>
</manifest>

View File

@ -33,14 +33,14 @@ public class AccountsAdapter extends RecyclerView.Adapter<AccountsAdapter.ViewHo
}
@Override
public AccountsAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(
R.layout.item_account, parent, false);
return new AccountsAdapter.ViewHolder(v);
return new ViewHolder(v);
}
@Override
public void onBindViewHolder(AccountsAdapter.ViewHolder holder, int position) {
public void onBindViewHolder(ViewHolder holder, int position) {
holder.ivAccountImage.setImageDrawable(
ContextCompat.getDrawable(context, R.drawable.ic_account_balance_wallet));
holder.tvAccountNumber.setText(accounts.get(position).getNumber());

View File

@ -24,7 +24,7 @@ public class FetchBanks extends UseCase<FetchBanks.RequestValues, FetchBanks.Res
@Override
protected void executeUseCase(FetchBanks.RequestValues requestValues) {
protected void executeUseCase(RequestValues requestValues) {
getUseCaseCallback().onSuccess(new ResponseValue(localRepository.getPopularBanks(),
localRepository.getOtherBanks()));
}

View File

@ -25,7 +25,7 @@ public class VerifyAadharDetails extends UseCase<VerifyAadharDetails.RequestValu
@Override
protected void executeUseCase(VerifyAadharDetails.RequestValues requestValues) {
protected void executeUseCase(RequestValues requestValues) {
switch (requestValues.requestCode) {
case 0:
@ -46,7 +46,7 @@ public class VerifyAadharDetails extends UseCase<VerifyAadharDetails.RequestValu
@Override
public void onNext(Boolean status) {
getUseCaseCallback().onSuccess(new
VerifyAadharDetails.ResponseValue(status));
ResponseValue(status));
}
});
break;
@ -68,7 +68,7 @@ public class VerifyAadharDetails extends UseCase<VerifyAadharDetails.RequestValu
@Override
public void onNext(Boolean status) {
getUseCaseCallback().onSuccess(new
VerifyAadharDetails.ResponseValue(status));
ResponseValue(status));
}
});
break;
@ -90,7 +90,7 @@ public class VerifyAadharDetails extends UseCase<VerifyAadharDetails.RequestValu
@Override
public void onNext(Boolean status) {
getUseCaseCallback().onSuccess(new
VerifyAadharDetails.ResponseValue(status));
ResponseValue(status));
}
});
break;

View File

@ -37,7 +37,7 @@ public class OtherBankAdapter extends RecyclerView.Adapter<OtherBankAdapter.View
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(
R.layout.item_other_banks, parent, false);
return new OtherBankAdapter.ViewHolder(v);
return new ViewHolder(v);
}
@Override

View File

@ -37,7 +37,7 @@ public class PopularBankAdapter extends RecyclerView.Adapter<PopularBankAdapter.
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(
R.layout.item_popular_banks, parent, false);
return new PopularBankAdapter.ViewHolder(v);
return new ViewHolder(v);
}
@Override

View File

@ -30,6 +30,14 @@ public class BaseFragment extends Fragment {
callback.hideSwipeProgress();
}
protected void showProgressDialog(String message) {
callback.showProgressDialog(message);
}
protected void hideProgressDialog() {
callback.hideProgressDialog();
}
@Override
public void onAttach(Context context) {
super.onAttach(context);

View File

@ -18,18 +18,18 @@ public interface AadharService {
@POST(ApiEndPoints.AADHAR_VERIFY)
Observable<Response<ResponseBody>> verifyAadhar(@Query("client_id") String clientId,
@Query("client_secret") String clientSecret,
@Body RequestBody body);
@Query("client_secret") String clientSecret,
@Body RequestBody body);
@POST(ApiEndPoints.AADHAR_GENERATE_OTP)
Observable<Response<ResponseBody>> generateAadharOtp(@Query("client_id") String clientId,
@Query("client_secret") String clientSecret,
@Body RequestBody body);
@Query("client_secret") String clientSecret,
@Body RequestBody body);
@POST(ApiEndPoints.AADHAR_VERIFY_OTP)
Observable<Response<ResponseBody>> verifyAadharOtp(@Query("client_id") String clientId,
@Query("client_secret") String clientSecret,
@Body RequestBody body);
@Query("client_secret") String clientSecret,
@Body RequestBody body);
}

View File

@ -18,7 +18,7 @@ public interface PanService {
@POST(ApiEndPoints.PAN_VERIFICATION)
Observable<Response<ResponseBody>> verifyPan(@Query("client_id") String clientId,
@Query("client_secret") String clientSecret,
@Body RequestBody body);
@Query("client_secret") String clientSecret,
@Body RequestBody body);
}

View File

@ -16,11 +16,13 @@ import android.widget.TextView;
import org.mifos.mobilewallet.R;
import org.mifos.mobilewallet.account.ui.AccountsFragment;
import org.mifos.mobilewallet.base.BaseActivity;
import org.mifos.mobilewallet.core.domain.model.Client;
import org.mifos.mobilewallet.home.HomeContract;
import org.mifos.mobilewallet.home.HomePresenter;
import org.mifos.mobilewallet.invoice.ui.InvoiceFragment;
import org.mifos.mobilewallet.invoice.ui.RecentInvoicesFragment;
import org.mifos.mobilewallet.qr.ui.ShowQrActivity;
import org.mifos.mobilewallet.savedcards.ui.CardsFragment;
import org.mifos.mobilewallet.user.ui.UserDetailsActivity;
import org.mifos.mobilewallet.utils.Constants;
import org.mifos.mobilewallet.utils.TextDrawable;
@ -29,7 +31,6 @@ import javax.inject.Inject;
import butterknife.BindView;
import butterknife.ButterKnife;
import org.mifos.mobilewallet.core.domain.model.Client;
/**
* Created by naman on 17/6/17.
@ -124,6 +125,9 @@ public class HomeActivity extends BaseActivity implements HomeContract.HomeView
case R.id.item_recent_invoices:
replaceFragment(RecentInvoicesFragment.newInstance(), false, R.id.container);
break;
case R.id.item_savedcards:
replaceFragment(CardsFragment.newInstance(), false, R.id.container);
break;
case R.id.item_qr:
Intent intent = new Intent(this, ShowQrActivity.class);
intent.putExtra(Constants.QR_DATA, "PixiePay");

View File

@ -19,13 +19,14 @@ import org.mifos.mobilewallet.invoice.ui.InvoiceFragment;
import org.mifos.mobilewallet.invoice.ui.RecentInvoicesFragment;
import org.mifos.mobilewallet.invoice.ui.UpiPaymentFragment;
import org.mifos.mobilewallet.qr.ui.ShowQrActivity;
import org.mifos.mobilewallet.savedcards.ui.CardsFragment;
import org.mifos.mobilewallet.user.ui.UserDetailsActivity;
import dagger.Component;
@PerActivity
@Component(dependencies = {ApplicationComponent.class},
modules = {ActivityModule.class})
modules = {ActivityModule.class})
public interface ActivityComponent {
@ -65,5 +66,6 @@ public interface ActivityComponent {
void inject(ExternalPaymentFragment externalPaymentFragment);
void inject(CardsFragment cardsFragment);
}

View File

@ -26,7 +26,7 @@ public class CreateInvoice extends UseCase<CreateInvoice.RequestValues,
@Override
protected void executeUseCase(CreateInvoice.RequestValues requestValues) {
protected void executeUseCase(RequestValues requestValues) {
localRepository.saveInvoice(requestValues.getInvoice())
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())

View File

@ -32,7 +32,7 @@ public class FetchLocalInvoices extends UseCase<FetchLocalInvoices.RequestValues
@Override
protected void executeUseCase(final FetchLocalInvoices.RequestValues requestValues) {
protected void executeUseCase(final RequestValues requestValues) {
localRepository.getInvoiceList()
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())

View File

@ -25,9 +25,9 @@ public class FetchPaymentMethods extends UseCase<FetchPaymentMethods.RequestValu
@Override
protected void executeUseCase(FetchPaymentMethods.RequestValues requestValues) {
protected void executeUseCase(RequestValues requestValues) {
getUseCaseCallback().onSuccess(new
FetchPaymentMethods.ResponseValue(localRepository.getPaymentMethods()));
ResponseValue(localRepository.getPaymentMethods()));
}
public static final class RequestValues implements UseCase.RequestValues {

View File

@ -34,14 +34,14 @@ public class PaymentMethodAdpater extends RecyclerView.Adapter<PaymentMethodAdpa
}
@Override
public PaymentMethodAdpater.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(
R.layout.item_payment_method, parent, false);
return new PaymentMethodAdpater.ViewHolder(v);
return new ViewHolder(v);
}
@Override
public void onBindViewHolder(PaymentMethodAdpater.ViewHolder holder, int position) {
public void onBindViewHolder(ViewHolder holder, int position) {
holder.ivMethodImage.setImageDrawable(
ContextCompat.getDrawable(context, paymentMethods.get(position).getImage()));
holder.tvMethodName.setText(paymentMethods.get(position).getTitle());

View File

@ -33,14 +33,14 @@ public class RecentInvoicesAdapter extends RecyclerView.Adapter<RecentInvoicesAd
}
@Override
public RecentInvoicesAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(
R.layout.item_invoice, parent, false);
return new RecentInvoicesAdapter.ViewHolder(v);
return new ViewHolder(v);
}
@Override
public void onBindViewHolder(RecentInvoicesAdapter.ViewHolder holder, int position) {
public void onBindViewHolder(ViewHolder holder, int position) {
holder.tvInvoiceAmount.setText(Constants.RUPEE + invoices.get(position).getAmount());
holder.tvInvoiceId.setText("Invoice ID : " +
invoices.get(position).getInvoiceId());

View File

@ -26,7 +26,7 @@ public class GenerateQr extends UseCase<GenerateQr.RequestValues, GenerateQr.Res
}
@Override
protected void executeUseCase(GenerateQr.RequestValues requestValues) {
protected void executeUseCase(RequestValues requestValues) {
try {
Bitmap bitmap = encodeAsBitmap(requestValues.data);

View File

@ -0,0 +1,35 @@
package org.mifos.mobilewallet.savedcards;
import org.mifos.mobilewallet.base.BasePresenter;
import org.mifos.mobilewallet.base.BaseView;
import org.mifos.mobilewallet.core.domain.model.Card;
import java.util.List;
/**
* Created by ankur on 19/May/2018
*/
public interface CardsContract {
interface CardsView extends BaseView<CardsPresenter> {
void showSavedCards(List<Card> cards);
void showToast(String message);
void showProgressDialog(String message);
void hideProgressDialog();
}
interface CardsPresenter extends BasePresenter {
void fetchSavedCards();
void addCard(Card card);
void editCard(Card card);
void deleteCard(int position);
}
}

View File

@ -0,0 +1,213 @@
package org.mifos.mobilewallet.savedcards.presenter;
import org.mifos.mobilewallet.base.BaseView;
import org.mifos.mobilewallet.core.base.UseCase;
import org.mifos.mobilewallet.core.base.UseCaseHandler;
import org.mifos.mobilewallet.core.domain.model.Card;
import org.mifos.mobilewallet.core.domain.usecase.AddCard;
import org.mifos.mobilewallet.core.domain.usecase.DeleteCard;
import org.mifos.mobilewallet.core.domain.usecase.EditCard;
import org.mifos.mobilewallet.core.domain.usecase.FetchSavedCards;
import org.mifos.mobilewallet.data.local.LocalRepository;
import org.mifos.mobilewallet.savedcards.CardsContract;
import javax.inject.Inject;
/**
* Created by ankur on 19/May/2018
*/
public class CardsPresenter implements CardsContract.CardsPresenter {
private final LocalRepository mLocalRepository;
private final UseCaseHandler mUseCaseHandler;
@Inject
AddCard addCardUseCase;
@Inject
FetchSavedCards fetchSavedCardsUseCase;
@Inject
EditCard editCardUseCase;
@Inject
DeleteCard deleteCardUseCase;
private CardsContract.CardsView mCardsView;
@Inject
public CardsPresenter(UseCaseHandler useCaseHandler, LocalRepository localRepository) {
mUseCaseHandler = useCaseHandler;
mLocalRepository = localRepository;
}
@Override
public void attachView(BaseView baseView) {
mCardsView = (CardsContract.CardsView) baseView;
mCardsView.setPresenter(this);
}
@Override
public void fetchSavedCards() {
fetchSavedCardsUseCase.setRequestValues(
new FetchSavedCards.RequestValues(
mLocalRepository.getClientDetails().getClientId()));
final FetchSavedCards.RequestValues requestValues =
fetchSavedCardsUseCase.getRequestValues();
mUseCaseHandler.execute(fetchSavedCardsUseCase, requestValues,
new UseCase.UseCaseCallback<FetchSavedCards.ResponseValue>() {
@Override
public void onSuccess(FetchSavedCards.ResponseValue response) {
mCardsView.showSavedCards(response.getCardList());
}
@Override
public void onError(String message) {
mCardsView.showToast("Error fetching cards.");
}
});
}
@Override
public void addCard(Card card) {
mCardsView.showProgressDialog("Adding Card..");
if (!validateCreditCardNumber(card.getCardNumber())) {
mCardsView.showToast("Invalid Credit Card Number");
mCardsView.hideProgressDialog();
return;
}
addCardUseCase.setRequestValues(
new AddCard.RequestValues(mLocalRepository.getClientDetails().getClientId(),
card));
final AddCard.RequestValues requestValues = addCardUseCase.getRequestValues();
mUseCaseHandler.execute(addCardUseCase, requestValues,
new UseCase.UseCaseCallback<AddCard.ResponseValue>() {
@Override
public void onSuccess(AddCard.ResponseValue response) {
mCardsView.hideProgressDialog();
mCardsView.showToast("Card added successfully.");
fetchSavedCards();
}
@Override
public void onError(String message) {
mCardsView.hideProgressDialog();
mCardsView.showToast("Error adding card.");
}
});
}
@Override
public void editCard(Card card) {
mCardsView.showProgressDialog("Updating Card..");
if (!validateCreditCardNumber(card.getCardNumber())) {
mCardsView.showToast("Invalid Credit Card Number");
mCardsView.hideProgressDialog();
return;
}
editCardUseCase.setRequestValues(
new EditCard.RequestValues((int) mLocalRepository.getClientDetails().getClientId(),
card));
final EditCard.RequestValues requestValues = editCardUseCase.getRequestValues();
mUseCaseHandler.execute(editCardUseCase, requestValues,
new UseCase.UseCaseCallback<EditCard.ResponseValue>() {
@Override
public void onSuccess(EditCard.ResponseValue response) {
mCardsView.hideProgressDialog();
mCardsView.showToast("Card updated successfully.");
fetchSavedCards();
}
@Override
public void onError(String message) {
mCardsView.hideProgressDialog();
mCardsView.showToast("Error updating card.");
}
});
}
@Override
public void deleteCard(int cardId) {
mCardsView.showProgressDialog("Deleting Card..");
deleteCardUseCase.setRequestValues(
new DeleteCard.RequestValues(
(int) mLocalRepository.getClientDetails().getClientId(),
cardId));
final DeleteCard.RequestValues requestValues = deleteCardUseCase.getRequestValues();
mUseCaseHandler.execute(deleteCardUseCase, requestValues,
new UseCase.UseCaseCallback<DeleteCard.ResponseValue>() {
@Override
public void onSuccess(DeleteCard.ResponseValue response) {
mCardsView.hideProgressDialog();
mCardsView.showToast("Card deleted successfully.");
fetchSavedCards();
}
@Override
public void onError(String message) {
mCardsView.hideProgressDialog();
mCardsView.showToast("Error deleting card.");
}
});
}
/* Luhn Algorithm for validating Credit Card Number
* src: https://www.journaldev.com/1443/java-credit-card-validation-luhn-algorithm-java*/
private boolean validateCreditCardNumber(String str) {
int u = 2;
if (u - 2 == 0) {
return true; // for backend testing. remove after testing.
}
if (str.length() == 0) {
return false;
}
int[] ints = new int[str.length()];
for (int i = 0; i < str.length(); i++) {
ints[i] = Integer.parseInt(str.substring(i, i + 1));
}
for (int i = ints.length - 2; i >= 0; i = i - 2) {
int j = ints[i];
j = j * 2;
if (j > 9) {
j = j % 10 + 1;
}
ints[i] = j;
}
int sum = 0;
for (int i = 0; i < ints.length; i++) {
sum += ints[i];
}
if (sum % 10 == 0) {
return true;
}
return false;
}
}

View File

@ -0,0 +1,135 @@
package org.mifos.mobilewallet.savedcards.ui;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.design.widget.BottomSheetBehavior;
import android.support.design.widget.BottomSheetDialog;
import android.support.design.widget.BottomSheetDialogFragment;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import org.mifos.mobilewallet.R;
import org.mifos.mobilewallet.core.domain.model.Card;
import org.mifos.mobilewallet.savedcards.CardsContract;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
/**
* Created by ankur on 19/May/2018
*/
public class AddCardDialog extends BottomSheetDialogFragment {
private BottomSheetBehavior mBottomSheetBehavior;
boolean forEdit;
Card editCard;
@BindView(R.id.et_card_number)
EditText etCardNumber;
@BindView(R.id.et_cvv)
EditText etCVV;
@BindView(R.id.spn_mm)
Spinner spnMM;
@BindView(R.id.spn_yy)
Spinner spnYY;
@BindView(R.id.et_fName)
EditText etFname;
@BindView(R.id.et_lName)
EditText etLname;
@BindView(R.id.btn_add)
Button btnAdd;
@BindView(R.id.btn_cancel)
Button btnCancel;
CardsContract.CardsPresenter mCardsPresenter;
public void setCardsPresenter(
CardsContract.CardsPresenter cardsPresenter) {
mCardsPresenter = cardsPresenter;
}
@Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
BottomSheetDialog dialog = (BottomSheetDialog) super.onCreateDialog(savedInstanceState);
View view = View.inflate(getContext(), R.layout.dialog_add_card, null);
dialog.setContentView(view);
mBottomSheetBehavior = BottomSheetBehavior.from((View) view.getParent());
ButterKnife.bind(this, view);
// add items to spnYY
List<String> items = new ArrayList<>();
int currentYear = Calendar.getInstance().get(Calendar.YEAR);
for (int i = 0; i < 50; i++) {
int j = currentYear + i;
items.add("" + j);
}
ArrayAdapter<String> dataAdapter = new ArrayAdapter<>(getContext(),
android.R.layout.simple_spinner_item, items);
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spnYY.setAdapter(dataAdapter);
return dialog;
}
@Override
public void onStart() {
super.onStart();
mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
// make swipe-able up and parameters to edit text to num only and do backend
if (forEdit) {
etFname.setText(editCard.getFirstName());
etLname.setText(editCard.getLastName());
etCardNumber.setText(editCard.getCardNumber());
btnAdd.setText("Update");
}
}
@OnClick(R.id.btn_cancel)
public void onCancelClicked() {
dismiss();
}
@OnClick(R.id.btn_add)
public void onAddClicked() {
Card card = new Card(etCardNumber.getText().toString(), etCVV.getText().toString(),
(String) spnMM.getSelectedItem() + "/" + (String) spnYY.getSelectedItem(),
etFname.getText().toString(), etLname.getText().toString());
if (forEdit) {
card.setId(editCard.getId());
mCardsPresenter.editCard(card);
} else {
mCardsPresenter.addCard(card);
}
dismiss();
}
}

View File

@ -0,0 +1,83 @@
package org.mifos.mobilewallet.savedcards.ui;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import org.mifos.mobilewallet.R;
import org.mifos.mobilewallet.core.domain.model.Card;
import java.util.List;
import javax.inject.Inject;
import butterknife.BindView;
import butterknife.ButterKnife;
/**
* Created by ankur on 21/May/2018
*/
public class CardsAdapter extends RecyclerView.Adapter<CardsAdapter.ViewHolder> {
private List<Card> cards;
@Inject
public CardsAdapter() {
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(
R.layout.item_card, parent, false);
return new ViewHolder(v);
}
@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
holder.tvFname.setText(cards.get(position).getFirstName());
holder.tvLname.setText(cards.get(position).getLastName());
holder.tvCardNumber.setText(cards.get(position).getCardNumber());
holder.tvExpirayDate.setText(cards.get(position).getExpiryDate());
}
@Override
public int getItemCount() {
if (cards != null) {
return cards.size();
} else {
return 0;
}
}
public List<Card> getCards() {
return cards;
}
public void setCards(List<Card> cards) {
this.cards = cards;
notifyDataSetChanged();
}
public class ViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.tv_fName)
TextView tvFname;
@BindView(R.id.tv_lName)
TextView tvLname;
@BindView(R.id.tv_card_number)
TextView tvCardNumber;
@BindView(R.id.tv_expiry_date)
TextView tvExpirayDate;
public ViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
}

View File

@ -0,0 +1,174 @@
package org.mifos.mobilewallet.savedcards.ui;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.PopupMenu;
import org.mifos.mobilewallet.R;
import org.mifos.mobilewallet.base.BaseActivity;
import org.mifos.mobilewallet.base.BaseFragment;
import org.mifos.mobilewallet.core.domain.model.Card;
import org.mifos.mobilewallet.savedcards.CardsContract;
import org.mifos.mobilewallet.savedcards.presenter.CardsPresenter;
import org.mifos.mobilewallet.utils.RecyclerItemClickListener;
import org.mifos.mobilewallet.utils.Toaster;
import java.util.List;
import javax.inject.Inject;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class CardsFragment extends BaseFragment implements CardsContract.CardsView {
@Inject
CardsPresenter mPresenter;
CardsContract.CardsPresenter mCardsPresenter;
@BindView(R.id.btn_add_card)
Button btnAddCard;
@BindView(R.id.rv_cards)
RecyclerView rvCards;
@Inject
CardsAdapter mCardsAdapter;
View rootView;
public static CardsFragment newInstance() {
Bundle args = new Bundle();
CardsFragment fragment = new CardsFragment();
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((BaseActivity) getActivity()).getActivityComponent().inject(this);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_cards, container, false);
setToolbarTitle("Saved Cards");
ButterKnife.bind(this, rootView);
mPresenter.attachView(this);
setupCardsRecyclerView();
showProgress();
mCardsPresenter.fetchSavedCards();
return rootView;
}
private void setupCardsRecyclerView() {
LinearLayoutManager llm = new LinearLayoutManager(getActivity());
rvCards.setLayoutManager(llm);
rvCards.setHasFixedSize(true);
rvCards.addItemDecoration(new DividerItemDecoration(getActivity(),
DividerItemDecoration.VERTICAL));
rvCards.setAdapter(mCardsAdapter);
rvCards.addOnItemTouchListener(new RecyclerItemClickListener(getActivity(),
new RecyclerItemClickListener.OnItemClickListener() {
@Override
public void onItemClick(final View childView, final int position) {
PopupMenu savedCardMenu = new PopupMenu(getContext(), childView);
savedCardMenu.getMenuInflater().inflate(R.menu.menu_saved_card,
savedCardMenu.getMenu());
savedCardMenu.setOnMenuItemClickListener(
new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.edit_card:
AddCardDialog addCardDialog = new AddCardDialog();
addCardDialog.forEdit = true;
addCardDialog.editCard =
mCardsAdapter.getCards().get(position);
addCardDialog.setCardsPresenter(mCardsPresenter);
addCardDialog.show(getFragmentManager(),
"Edit Card Dialog");
break;
case R.id.delete_card:
mCardsPresenter.deleteCard(
mCardsAdapter.getCards().get(
position).getId());
break;
case R.id.cancel:
break;
}
return true;
}
});
savedCardMenu.show();
}
@Override
public void onItemLongPress(View childView, int position) {
}
}));
}
@Override
public void setPresenter(CardsContract.CardsPresenter presenter) {
mCardsPresenter = presenter;
}
@OnClick(R.id.btn_add_card)
public void onClickAddCard() {
AddCardDialog addCardDialog = new AddCardDialog();
addCardDialog.forEdit = false;
addCardDialog.setCardsPresenter(mCardsPresenter);
addCardDialog.show(getFragmentManager(), "Add Card Dialog");
}
@Override
public void showSavedCards(List<Card> cards) {
mCardsAdapter.setCards(cards);
hideProgress();
}
@Override
public void showToast(String message) {
Toaster.show(getView(), message);
}
@Override
public void showProgressDialog(String message) {
super.showProgressDialog(message);
}
@Override
public void hideProgressDialog() {
super.hideProgressDialog();
}
}

View File

@ -25,7 +25,7 @@ public class VerifyPanDetails extends UseCase<VerifyPanDetails.RequestValues,
@Override
protected void executeUseCase(VerifyPanDetails.RequestValues requestValues) {
protected void executeUseCase(RequestValues requestValues) {
rblRepository.verifyPanNumber(requestValues.number)
.observeOn(AndroidSchedulers.mainThread())
@ -43,7 +43,7 @@ public class VerifyPanDetails extends UseCase<VerifyPanDetails.RequestValues,
@Override
public void onNext(Boolean status) {
getUseCaseCallback().onSuccess(new VerifyPanDetails.ResponseValue(status));
getUseCaseCallback().onSuccess(new ResponseValue(status));
}
});
}

View File

@ -0,0 +1,46 @@
package org.mifos.mobilewallet.utils;
import android.graphics.Color;
import android.support.design.widget.Snackbar;
import android.view.View;
import android.widget.TextView;
import org.mifos.mobilewallet.MifosWalletApp;
/**
* Created by ankur on 23/May/2018
*/
public class Toaster {
public static final int INDEFINITE = Snackbar.LENGTH_INDEFINITE;
public static final int LONG = Snackbar.LENGTH_LONG;
public static final int SHORT = Snackbar.LENGTH_SHORT;
public static void show(View view, String text, int duration) {
final Snackbar snackbar = Snackbar.make(view, text, duration);
View sbView = snackbar.getView();
TextView textView = sbView.findViewById(android.support.design.R.id.snackbar_text);
textView.setTextColor(Color.WHITE);
textView.setTextSize(12);
snackbar.setAction("OK", new View.OnClickListener() {
@Override
public void onClick(View view) {
snackbar.dismiss();
}
});
snackbar.show();
}
public static void show(View view, int res, int duration) {
show(view, MifosWalletApp.getContext().getResources().getString(res), duration);
}
public static void show(View view, String text) {
show(view, text, Snackbar.LENGTH_LONG);
}
public static void show(View view, int res) {
show(view, MifosWalletApp.getContext().getResources().getString(res));
}
}

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke android:width="5dp"
android:color="@color/gray"/>
<corners
android:bottomLeftRadius="10dp"
android:bottomRightRadius="10dp"
android:topLeftRadius="10dp"
android:topRightRadius="10dp"/>
<solid android:color="@android:color/transparent"/>
</shape>

View File

@ -0,0 +1,115 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusable="true"
android:focusableInTouchMode="true"
android:focusedByDefault="true"
android:orientation="vertical"
android:padding="@dimen/value_20dp">
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/et_fName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="First Name"/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/value_5dp">
<EditText
android:id="@+id/et_lName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Last Name"/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/value_10dp">
<EditText
android:id="@+id/et_card_number"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Credit Card Number"
android:inputType="number"/>
</android.support.design.widget.TextInputLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/value_10dp"
android:text="Expiry Date"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/value_10dp"
android:orientation="horizontal">
<Spinner
android:id="@+id/spn_mm"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:entries="@array/months_array"/>
<Spinner
android:id="@+id/spn_yy"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/value_10dp">
<EditText
android:id="@+id/et_cvv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="@string/cvv"
android:inputType="numberPassword"
android:maxLength="3"
android:minWidth="@dimen/value_70dp"/>
</android.support.design.widget.TextInputLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/value_20dp"
android:layout_marginRight="@dimen/value_10dp"
android:layout_marginTop="@dimen/value_30dp"
android:gravity="right"
android:orientation="horizontal">
<Button
android:id="@+id/btn_cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/grey_900"
android:text="@string/cancel_txt"
android:textColor="@android:color/white"/>
<Button
android:id="@+id/btn_add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_marginLeft="@dimen/value_30dp"
android:background="@color/colorPrimary"
android:text="ADD"
android:textColor="@android:color/white"/>
</LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="@+id/rv_cards"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:paddingBottom="60dp"/>
<Button
android:id="@+id/btn_add_card"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_gravity="bottom"
android:layout_marginBottom="10dp"
android:layout_marginEnd="@dimen/value_30dp"
android:layout_marginLeft="30dp"
android:layout_marginRight="@dimen/value_30dp"
android:layout_marginStart="30dp"
android:layout_marginTop="@dimen/value_20dp"
android:background="@drawable/button_round_stroke_primary"
android:clickable="true"
android:text="Add Card"
android:textAllCaps="false"
android:textColor="@color/colorPrimary"
android:typeface="sans"/>
</FrameLayout>

View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/value_10dp"
android:layout_marginRight="@dimen/value_10dp"
android:layout_marginTop="@dimen/value_10dp"
android:orientation="vertical"
app:cardCornerRadius="@dimen/value_10dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/button_round_stroke_gray"
android:orientation="vertical"
android:padding="@dimen/value_10dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_fName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAllCaps="true"
android:textColor="@color/grey_900"/>
<TextView
android:id="@+id/tv_lName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/value_20dp"
android:textAllCaps="true"
android:textColor="@color/grey_900"/>
</LinearLayout>
<TextView
android:id="@+id/tv_card_number"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:text="Credit Card Number"
android:textColor="@color/grey_900"
android:textSize="@dimen/value_30sp"
android:theme="@style/Theme.AppCompat"/>
<TextView
android:id="@+id/tv_expiry_date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:text="Expiry Date"
android:textColor="@color/grey_900"
android:theme="@style/Theme.AppCompat"/>
</LinearLayout>
</android.support.v7.widget.CardView>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
xmlns:app="http://schemas.android.com/apk/res-auto">
<group android:id="@+id/group1"
android:checkableBehavior="single">
@ -30,6 +30,11 @@
android:title="Wallet"
app:actionLayout="@layout/textview_counter"/>
<item
android:id="@+id/item_savedcards"
android:checked="true"
android:title="Saved cards"/>
<item
android:id="@+id/item_qr"
android:checked="true"

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/edit_card"
android:title="Edit Card"/>
<item
android:id="@+id/delete_card"
android:title="Delete Card"/>
<item
android:id="@+id/cancel"
android:title="@string/cancel_txt"/>
</menu>

View File

@ -11,7 +11,9 @@
<string name="powered_by">Powered By &#160;</string>
<string name="rbl_bank">RBL BANK</string>
<string name="verify_mobile_number">Verify Mobile Number</string>
<string name="confirm_mobile_number_message">To confirm your mobile number \n we need to send an SMS from \n your phone*</string>
<string name="confirm_mobile_number_message">To confirm your mobile number \n we need to send an
SMS from \n your phone*
</string>
<string name="choose_your_sim">Please choose your SIM</string>
<string name="sim_provider">VODAFONE_IN</string>
<string name="sim_airtel">AIRTEL_IN</string>
@ -30,8 +32,11 @@
<string name="account_type_txt">Account Type</string>
<string name="branch_txt">Branch</string>
<string name="branch">Lower Parel, Mumbai</string>
<string name="upi_pin_suggestion">You need to set UPI PIN to securely do transaction from your bank account</string>
<string name="upi_pin_debit_credit_card">Set UPI PIN easily using your \n debit / ATM card</string>
<string name="upi_pin_suggestion">You need to set UPI PIN to securely do transaction from your
bank account
</string>
<string name="upi_pin_debit_credit_card">Set UPI PIN easily using your \n debit / ATM card
</string>
<string name="upi_pin_set">Set Up PIN</string>
<string name="upi_pin_already">I HAVE UPI PIN</string>
<string name="upi_pin_later">IʼLL SET LATER</string>
@ -73,7 +78,9 @@
<string name="reEnter_pin">Re enter the pin</string>
<string name="create_pin">Create PIN</string>
<string name="scan_fingerprint">Scan customer\'s fingerprint</string>
<string name="scan_fingerprint_message">Scan customer\'s fingerprint to authorise the transaction</string>
<string name="scan_fingerprint_message">Scan customer\'s fingerprint to authorise the
transaction
</string>
<string name="wait_fingerprint_message">Waiting for fingerprint scanner to be connected</string>
<string name="done_txt">Done</string>
<string name="auto_otp_message">Auto detecting one time password</string>
@ -90,6 +97,22 @@
<string name="enter_vpa">Enter the vpa</string>
<string name="request_txt">Request</string>
<string name="select_acc">Select Account</string>
<string name="cvv">CVV</string>
<string-array name="months_array">
<item>01</item>
<item>02</item>
<item>03</item>
<item>04</item>
<item>05</item>
<item>06</item>
<item>07</item>
<item>08</item>
<item>09</item>
<item>10</item>
<item>11</item>
<item>12</item>
</string-array>
</resources>

View File

@ -8,7 +8,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
classpath 'com.android.tools.build:gradle:3.1.2'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files

View File

@ -32,14 +32,15 @@
<property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
</module>
<module name="EmptyBlock">
<!-- <module name="EmptyBlock">
<property name="option" value="TEXT"/>
<property name="tokens" value="LITERAL_TRY, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH"/>
</module>
<module name="EmptyCatchBlock">
<property name="exceptionVariableName" value="expected"/>
<property name="tokens" value="LITERAL_TRY, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH, LITERAL_CATCH"/>
</module>
-->
<!-- Ignore the EmptyCatchBlock -->
<!-- <module name="EmptyCatchBlock">
<property name="exceptionVariableName" value="expected|ignore"/>
</module> -->
<module name="LeftCurly">
<property name="maxLineLength" value="100"/>
@ -116,40 +117,39 @@
value="Package name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="MethodName">
<!-- <module name="MethodName">
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9_]*$"/>
<message key="name.invalidPattern"
value="Method name ''{0}'' must match pattern ''{1}''."/>
</module>
</module> -->
<module name="TypeName">
<message key="name.invalidPattern"
value="Type name ''{0}'' must match pattern ''{1}''."/>
</module>
<!--//TODO Need Discussion, about the naming convention of member Variable -->
<!--<module name="MemberName">
<!-- <module name="MemberName">
<property name="applyToPublic" value="false" />
<property name="applyToPackage" value="false" />
<property name="applyToProtected" value="false" />
<property name="format" value="^m[A-Z][a-z0-9][a-zA-Z0-9]*$"/>
<message key="name.invalidPattern"
value="Member name ''{0}'' must match pattern ''{1}''."/>
</module>-->
</module> -->
<module name="ParameterName">
<!-- <module name="ParameterName">
<property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
<message key="name.invalidPattern"
value="Parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
</module> -->
<module name="LocalVariableName">
<!-- <module name="LocalVariableName">
<property name="tokens" value="VARIABLE_DEF"/>
<property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
<property name="allowOneCharVarInForLoop" value="true"/>
<message key="name.invalidPattern"
value="Local variable name ''{0}'' must match pattern ''{1}''."/>
</module>
</module> -->
<module name="ClassTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>

View File

@ -1,8 +1,8 @@
<?xml version="1.0"?>
<ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Android Application Rules"
xmlns="http://pmd.sf.net/ruleset/1.0.0"
xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd"
xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd">
xmlns="http://pmd.sf.net/ruleset/1.0.0"
xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd"
xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd">
<description>Custom ruleset for Mifos Self-Service Android application</description>
@ -24,10 +24,13 @@
<!-- We allow single line if's without braces -->
<exclude name="IfStmtsMustUseBraces" />
</rule>
<rule ref="rulesets/java/strings.xml" />
<rule ref="rulesets/java/strings.xml" >
<!-- Exclude because causes problems with SQL Strings that usually require duplication -->
<exclude name="AvoidDuplicateLiterals"/>
</rule>
<rule ref="rulesets/java/basic.xml" >
<exclude name="AvoidUsingHardCodedIP" />
</rule>
<exclude name="AvoidUsingHardCodedIP" />
</rule>
<rule ref="rulesets/java/naming.xml">
<exclude name="AbstractNaming" />
<exclude name="LongVariable" />
@ -36,4 +39,4 @@
<exclude name="ShortClassName" />
<exclude name="VariableNamingConventions" />
</rule>
</ruleset>
</ruleset>

View File

@ -3,7 +3,6 @@ apply from: '../config/quality/quality.gradle'
android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
defaultConfig {
minSdkVersion rootProject.ext.minSdkVersion
@ -28,29 +27,30 @@ android {
abortOnError false
disable 'InvalidPackage'
}
buildToolsVersion '27.0.3'
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
implementation fileTree(include: ['*.jar'], dir: 'libs')
androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile "com.android.support:appcompat-v7:$rootProject.supportLibraryVersion"
implementation "com.android.support:appcompat-v7:$rootProject.supportLibraryVersion"
compile 'com.google.dagger:dagger:2.11'
implementation 'com.google.dagger:dagger:2.11'
annotationProcessor 'com.google.dagger:dagger-compiler:2.11'
compile ("com.squareup.retrofit2:retrofit:$rootProject.retrofitVersion") {
implementation ("com.squareup.retrofit2:retrofit:$rootProject.retrofitVersion") {
// exclude Retrofits OkHttp peer-dependency module and define your own module import
exclude module: 'okhttp'
}
compile "com.squareup.retrofit2:converter-gson:$rootProject.retrofitVersion"
compile "com.squareup.retrofit2:adapter-rxjava:$rootProject.retrofitVersion"
compile "com.squareup.okhttp3:okhttp:$rootProject.okHttp3Version"
compile "com.squareup.okhttp3:logging-interceptor:$rootProject.okHttp3Version"
implementation "com.squareup.retrofit2:converter-gson:$rootProject.retrofitVersion"
implementation "com.squareup.retrofit2:adapter-rxjava:$rootProject.retrofitVersion"
implementation "com.squareup.okhttp3:okhttp:$rootProject.okHttp3Version"
implementation "com.squareup.okhttp3:logging-interceptor:$rootProject.okHttp3Version"
compile 'io.reactivex:rxandroid:1.1.0'
compile 'io.reactivex:rxjava:1.1.4'
implementation 'io.reactivex:rxandroid:1.1.0'
implementation 'io.reactivex:rxjava:1.1.4'
testCompile 'junit:junit:4.12'
testImplementation 'junit:junit:4.12'
}

View File

@ -8,10 +8,10 @@ public interface UseCaseScheduler {
void execute(Runnable runnable);
<V extends UseCase.ResponseValue> void notifyResponse(final V response,
final UseCase.UseCaseCallback<V>
useCaseCallback);
final UseCase.UseCaseCallback<V>
useCaseCallback);
<V extends UseCase.ResponseValue> void onError(final String message,
final UseCase.UseCaseCallback<V>
useCaseCallback);
final UseCase.UseCaseCallback<V>
useCaseCallback);
}

View File

@ -14,9 +14,11 @@ public class ApiEndPoints {
public static final String SAVINGS_ACCOUNTS = "savingsaccounts";
public static final String RECURRING_ACCOUNTS = "recurringdepositaccounts";
public static final String SEARCH = "search";
public static final String BENEFICIARIES = "beneficiaries";
public static final String ACCOUNT_TRANSFER = "accounttransfers";
public static final String BENEFICIARIES = "beneficiaries";
public static final String ACCOUNT_TRANSFER = "accounttransfers";
public static final String DOCUMENTS = "documents";
// public static final String SAVED_CARD = "datatables/saved_cards";
public static final String DATATABLES = "datatables";
}

View File

@ -4,9 +4,12 @@ import android.util.Base64;
import org.mifos.mobilewallet.core.data.fineract.api.services.AuthenticationService;
import org.mifos.mobilewallet.core.data.fineract.api.services.ClientService;
import org.mifos.mobilewallet.core.data.fineract.api.services.DataTablesService;
import org.mifos.mobilewallet.core.data.fineract.api.services.DocumentService;
import org.mifos.mobilewallet.core.data.fineract.api.services.RegistrationService;
import org.mifos.mobilewallet.core.data.fineract.api.services.SavingAccountsListService;
import org.mifos.mobilewallet.core.data.fineract.api.services.SearchService;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
@ -28,11 +31,13 @@ public class FineractApiManager {
private static SavingAccountsListService savingAccountsListApi;
private static RegistrationService registrationAPi;
private static SearchService searchApi;
private static DataTablesService dataTablesService;
private static DocumentService documentApi;
private static SelfServiceApiManager sSelfInstance;
public FineractApiManager() {
String authToken = "Basic " + Base64.encodeToString("mifospayadmin:password1".getBytes(),
String authToken = "Basic " + Base64.encodeToString("mifos:password".getBytes(),
Base64.NO_WRAP);
createService(authToken);
@ -47,6 +52,9 @@ public class FineractApiManager {
savingAccountsListApi = createApi(SavingAccountsListService.class);
registrationAPi = createApi(RegistrationService.class);
searchApi = createApi(SearchService.class);
dataTablesService = createApi(DataTablesService.class);
documentApi = createApi(DocumentService.class);
}
private static <T> T createApi(Class<T> clazz) {
@ -100,4 +108,12 @@ public class FineractApiManager {
public static SelfServiceApiManager getSelfApiManager() {
return sSelfInstance;
}
public DocumentService getDocumentApi() {
return documentApi;
}
public DataTablesService getDatatablesApi() {
return dataTablesService;
}
}

View File

@ -0,0 +1,26 @@
package org.mifos.mobilewallet.core.data.fineract.api;
import java.util.HashMap;
/**
* Created by ankur on 21/May/2018
*/
public class GenericResponse {
HashMap<String, Object> responseFields = new HashMap<String, Object>();
public HashMap<String, Object> getResponseFields() {
return responseFields;
}
public void setResponseFields(HashMap<String, Object> responseFields) {
this.responseFields = responseFields;
}
@Override
public String toString() {
return "GenericResponse{" +
"responseFields=" + responseFields +
'}';
}
}

View File

@ -14,6 +14,6 @@ public interface AuthenticationService {
@POST(ApiEndPoints.AUTHENTICATION)
Observable<UserEntity> authenticate(@Query("username") String username,
@Query("password") String password);
@Query("password") String password);
}

View File

@ -34,7 +34,7 @@ public interface BeneficiaryService {
@PUT(ApiEndPoints.BENEFICIARIES + "/tpt/{beneficiaryId}")
Observable<ResponseBody> updateBeneficiary(@Path("beneficiaryId") long beneficiaryId,
@Body BeneficiaryUpdatePayload payload);
@Body BeneficiaryUpdatePayload payload);
@DELETE(ApiEndPoints.BENEFICIARIES + "/tpt/{beneficiaryId}")
Observable<ResponseBody> deleteBeneficiary(@Path("beneficiaryId") long beneficiaryId);

View File

@ -6,6 +6,7 @@ import org.mifos.mobilewallet.core.data.fineract.entity.Page;
import org.mifos.mobilewallet.core.data.fineract.entity.client.Client;
import org.mifos.mobilewallet.core.data.fineract.entity.client.ClientAccounts;
import org.mifos.mobilewallet.core.data.fineract.entity.payload.UpdateVpaPayload;
import okhttp3.ResponseBody;
import retrofit2.http.Body;
import retrofit2.http.GET;
@ -16,26 +17,24 @@ import rx.Observable;
public interface ClientService {
String CLIENT_ID = "clientId";
@GET(ApiEndPoints.CLIENTS)
Observable<Page<Client>> getClients();
@GET(ApiEndPoints.CLIENTS + "/{clientId}")
Observable<Client> getClientForId(@Path(CLIENT_ID) long clientId);
Observable<Client> getClientForId(@Path("clientId") long clientId);
@PUT(ApiEndPoints.CLIENTS + "/{clientId}")
Observable<ResponseBody> updateClientVpa(@Path(CLIENT_ID) long clientId,
@Body UpdateVpaPayload payload);
Observable<ResponseBody> updateClientVpa(@Path("clientId") long clientId,
@Body UpdateVpaPayload payload);
@GET(ApiEndPoints.CLIENTS + "/{clientId}/images")
Observable<ResponseBody> getClientImage(@Path(CLIENT_ID) long clientId);
Observable<ResponseBody> getClientImage(@Path("clientId") long clientId);
@GET(ApiEndPoints.CLIENTS + "/{clientId}/accounts")
Observable<ClientAccounts> getClientAccounts(@Path(CLIENT_ID) long clientId);
Observable<ClientAccounts> getClientAccounts(@Path("clientId") long clientId);
@GET(ApiEndPoints.CLIENTS + "/{clientId}/accounts")
Observable<ClientAccounts> getAccounts(@Path(CLIENT_ID) long clientId,
@Query("fields") String accountType);
Observable<ClientAccounts> getAccounts(@Path("clientId") long clientId,
@Query("fields") String accountType);
}

View File

@ -0,0 +1,56 @@
package org.mifos.mobilewallet.core.data.fineract.api.services;
import org.mifos.mobilewallet.core.data.fineract.api.ApiEndPoints;
import org.mifos.mobilewallet.core.data.fineract.api.GenericResponse;
import org.mifos.mobilewallet.core.domain.model.Card;
import org.mifos.mobilewallet.core.domain.model.KYCLevel1Details;
import java.util.List;
import retrofit2.http.Body;
import retrofit2.http.DELETE;
import retrofit2.http.GET;
import retrofit2.http.POST;
import retrofit2.http.PUT;
import retrofit2.http.Path;
import rx.Observable;
/**
* Created by ankur on 21/May/2018
*/
public interface DataTablesService {
@POST(ApiEndPoints.DATATABLES + "/saved_cards/{clientId}")
Observable<GenericResponse> addSavedCard(
@Path("clientId") int clientId,
@Body Card card);
@GET(ApiEndPoints.DATATABLES + "/saved_cards/{clientId}")
Observable<List<Card>> getSavedCards(@Path("clientId") int clientId);
@DELETE(ApiEndPoints.DATATABLES + "/saved_cards/{clientId}/{cardId}")
Observable<GenericResponse> deleteCard(@Path("clientId") int clientId,
@Path("cardId") int cardId);
@PUT(ApiEndPoints.DATATABLES + "/saved_cards/{clientId}/{cardId}")
Observable<GenericResponse> updateCard(
@Path("clientId") int clientId,
@Path("cardId") int cardId,
@Body Card card);
@POST(ApiEndPoints.DATATABLES + "/kyc_level1_details/{clientId}")
Observable<GenericResponse> addKYCLevel1Details(
@Path("clientId") int clientId,
@Body KYCLevel1Details kycLevel1Details);
@GET(ApiEndPoints.DATATABLES + "/kyc_level1_details/{clientId}")
Observable<List<KYCLevel1Details>> fetchKYCLevel1Details(@Path("clientId") int clientId);
@PUT(ApiEndPoints.DATATABLES + "/kyc_level1_details/{clientId}/")
Observable<GenericResponse> updateKYCLevel1Details(
@Path("clientId") int clientId,
@Body KYCLevel1Details kycLevel1Details);
}

View File

@ -0,0 +1,105 @@
package org.mifos.mobilewallet.core.data.fineract.api.services;
import org.mifos.mobilewallet.core.data.fineract.api.ApiEndPoints;
import org.mifos.mobilewallet.core.data.fineract.api.GenericResponse;
import org.mifos.mobilewallet.core.data.fineract.entity.noncore.Document;
import java.util.List;
import okhttp3.MultipartBody;
import okhttp3.ResponseBody;
import retrofit2.http.DELETE;
import retrofit2.http.GET;
import retrofit2.http.Multipart;
import retrofit2.http.POST;
import retrofit2.http.PUT;
import retrofit2.http.Part;
import retrofit2.http.Path;
import rx.Observable;
/**
* @author fomenkoo
*/
public interface DocumentService {
@GET("{entityType}/{entityId}/" + ApiEndPoints.DOCUMENTS)
Observable<List<Document>> getDocuments(@Path("entityType") String entityType,
@Path("entityId") int entityId);
/**
* @param entityType - Type for which document is being uploaded (Client, Loan
* or Savings etc)
* @param entityId - Id of Entity
* @param nameOfDocument - Document Name
* @param description - Mandatory - Document Description
* @param typedFile - Mandatory
*/
@POST("{entityType}/{entityId}/" + ApiEndPoints.DOCUMENTS)
@Multipart
Observable<GenericResponse> createDocument(
@Path("entityType") String entityType,
@Path("entityId") long entityId,
@Part("name") String nameOfDocument,
@Part("description") String description,
@Part() MultipartBody.Part typedFile);
/**
* This Service is for downloading the Document with EntityType and EntityId and Document Id
* Rest End Point :
* https://demo.openmf.org/fineract-provider/api/v1/{entityType}/{entityId}/documents/
* {documentId}/attachment
*
* @param entityType - Type for which document is being uploaded (Client, Loan
* or Savings etc)
* @param entityId - Id of Entity
* @param documentId - Document Id
* @return ResponseBody
*/
@GET("{entityType}/{entityId}/" + ApiEndPoints.DOCUMENTS + "/{documentId}/attachment")
Observable<ResponseBody> downloadDocument(@Path("entityType") String entityType,
@Path("entityId") int entityId,
@Path("documentId") int documentId);
/**
* This Service is for Deleting the Document with EntityType and EntityId and Document Id.
* Rest End Point :
* https://demo.openmf.org/fineract-provider/api/v1/{entityType}/{entityId}/documents/
* {documentId}
*
* @param entityType - Type for which document is being uploaded (Client, Loan
* or Savings etc)
* @param entityId - Id of Entity
* @param documentId - Document Id
* @return
*/
@DELETE("{entityType}/{entityId}/" + ApiEndPoints.DOCUMENTS + "/{documentId}")
Observable<ResponseBody> removeDocument(@Path("entityType") String entityType,
@Path("entityId") int entityId,
@Path("documentId") int documentId);
/**
* This Service for Updating the Document with EntityType and EntityId and Document Id.
* Rest End Point :
* PUT
* https://demo.openmf.org/fineract-provider/api/v1/{entityType}/{entityId}/documents/
* {documentId}
*
* @param entityType - Type for which document is being uploaded (Client, Loan
* or Savings etc)
* @param entityId - Id of Entity
* @param documentId - Id of document
* @param nameOfDocument - Document Name
* @param description - Mandatory - Document Description
* @param typedFile - Mandatory
*/
@PUT("{entityType}/{entityId}/" + ApiEndPoints.DOCUMENTS + "/{documentId}")
@Multipart
Observable<ResponseBody> updateDocument(@Path("entityType") String entityType,
@Path("entityId") int entityId,
@Path("documentId") int documentId,
@Part("name") String nameOfDocument,
@Part("description") String description,
@Part() MultipartBody.Part typedFile);
}

View File

@ -16,6 +16,6 @@ public interface SearchService {
@GET(ApiEndPoints.SEARCH)
Observable<List<SearchedEntity>> searchResources(@Query("query") String query,
@Query("resource") String resources,
@Query("exactMatch") Boolean exactMatch);
@Query("resource") String resources,
@Query("exactMatch") Boolean exactMatch);
}

View File

@ -121,8 +121,7 @@ public class SearchedEntity implements Parcelable {
this.parentName = in.readString();
}
public static final Parcelable.Creator<SearchedEntity> CREATOR = new Parcelable
.Creator<SearchedEntity>() {
public static final Creator<SearchedEntity> CREATOR = new Creator<SearchedEntity>() {
@Override
public SearchedEntity createFromParcel(Parcel source) {
return new SearchedEntity(source);

View File

@ -71,8 +71,8 @@ public class ClientAccounts implements Parcelable {
dest.writeList(this.savingsAccounts);
}
public static final Parcelable.Creator<ClientAccounts> CREATOR = new Parcelable
.Creator<ClientAccounts>() {
public static final Creator<ClientAccounts> CREATOR = new Creator<ClientAccounts>() {
@Override
public ClientAccounts createFromParcel(Parcel source) {
return new ClientAccounts(source);

View File

@ -60,8 +60,7 @@ public class DepositType implements Parcelable {
this.value = in.readString();
}
public static final Parcelable.Creator<DepositType> CREATOR = new Parcelable
.Creator<DepositType>() {
public static final Creator<DepositType> CREATOR = new Creator<DepositType>() {
public DepositType createFromParcel(Parcel source) {
return new DepositType(source);
}

View File

@ -0,0 +1,131 @@
/*
* This project is licensed under the open source MPL V2.
* See https://github.com/openMF/android-client/blob/master/LICENSE.md
*/
package org.mifos.mobilewallet.core.data.fineract.entity.noncore;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Created by ishankhanna on 02/07/14.
*/
public class Document implements Parcelable {
private int id;
private String parentEntityType;
private int parentEntityId;
private String name;
private String fileName;
private long size;
private String type;
private String description;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getParentEntityType() {
return parentEntityType;
}
public void setParentEntityType(String parentEntityType) {
this.parentEntityType = parentEntityType;
}
public int getParentEntityId() {
return parentEntityId;
}
public void setParentEntityId(int parentEntityId) {
this.parentEntityId = parentEntityId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public long getSize() {
return size;
}
public void setSize(long size) {
this.size = size;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(this.id);
dest.writeString(this.parentEntityType);
dest.writeInt(this.parentEntityId);
dest.writeString(this.name);
dest.writeString(this.fileName);
dest.writeLong(this.size);
dest.writeString(this.type);
dest.writeString(this.description);
}
public Document() {
}
protected Document(Parcel in) {
this.id = in.readInt();
this.parentEntityType = in.readString();
this.parentEntityId = in.readInt();
this.name = in.readString();
this.fileName = in.readString();
this.size = in.readLong();
this.type = in.readString();
this.description = in.readString();
}
public static final Creator<Document> CREATOR = new Creator<Document>() {
@Override
public Document createFromParcel(Parcel source) {
return new Document(source);
}
@Override
public Document[] newArray(int size) {
return new Document[size];
}
};
}

View File

@ -267,8 +267,8 @@ public class ClientPayload implements Parcelable {
this.locale = in.readString();
}
public static final Parcelable.Creator<ClientPayload> CREATOR =
new Parcelable.Creator<ClientPayload>() {
public static final Creator<ClientPayload> CREATOR =
new Creator<ClientPayload>() {
@Override
public ClientPayload createFromParcel(Parcel source) {
return new ClientPayload(source);

View File

@ -71,8 +71,8 @@ public class DataTablePayload implements Parcelable {
this.data = (HashMap<String, Object>) in.readSerializable();
}
public static final Parcelable.Creator<DataTablePayload> CREATOR = new
Parcelable.Creator<DataTablePayload>() {
public static final Creator<DataTablePayload> CREATOR = new
Creator<DataTablePayload>() {
@Override
public DataTablePayload createFromParcel(Parcel source) {
return new DataTablePayload(source);

View File

@ -1,11 +1,7 @@
package org.mifos.mobilewallet.core.data.fineract.repository;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.mifos.mobilewallet.core.data.fineract.api.FineractApiManager;
import org.mifos.mobilewallet.core.data.fineract.api.GenericResponse;
import org.mifos.mobilewallet.core.data.fineract.api.SelfServiceApiManager;
import org.mifos.mobilewallet.core.data.fineract.entity.Page;
import org.mifos.mobilewallet.core.data.fineract.entity.SearchedEntity;
@ -20,7 +16,16 @@ import org.mifos.mobilewallet.core.data.fineract.entity.payload.TransferPayload;
import org.mifos.mobilewallet.core.data.fineract.entity.payload.UpdateVpaPayload;
import org.mifos.mobilewallet.core.data.fineract.entity.register.RegisterPayload;
import org.mifos.mobilewallet.core.data.fineract.entity.register.UserVerify;
import org.mifos.mobilewallet.core.domain.model.Card;
import org.mifos.mobilewallet.core.domain.model.KYCLevel1Details;
import org.mifos.mobilewallet.core.utils.Constants;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Singleton;
import okhttp3.MultipartBody;
import okhttp3.ResponseBody;
import rx.Observable;
import rx.functions.Func1;
@ -50,7 +55,7 @@ public class FineractRepository {
}
public Observable<List<SearchedEntity>> searchResources(String query, String resources,
Boolean exactMatch) {
Boolean exactMatch) {
return fineractApiManager.getSearchApi().searchResources(query, resources, exactMatch);
}
@ -73,6 +78,55 @@ public class FineractRepository {
return fineractApiManager.getClientsApi().getClientForId(clientId);
}
public Observable<GenericResponse> addSavedCards(long clientId,
Card card) {
return fineractApiManager.getDatatablesApi().addSavedCard((int) clientId, card);
}
public Observable<List<Card>> fetchSavedCards(long clientId) {
return fineractApiManager.getDatatablesApi().getSavedCards((int) clientId);
}
public Observable<GenericResponse> editSavedCard(int clientId, Card card) {
return fineractApiManager.getDatatablesApi().updateCard(clientId, card.getId(), card);
}
public Observable<GenericResponse> deleteSavedCard(int clientId, int cardId) {
return fineractApiManager.getDatatablesApi().deleteCard(clientId, cardId);
}
public Observable<GenericResponse> uploadKYCDocs(String entityType, long entityId, String name,
String desc, MultipartBody.Part file) {
return fineractApiManager.getDocumentApi().createDocument(entityType, entityId, name, desc,
file);
// return fineractApiManager.getDocumentApi().createDocument(entityType, entityId, name,
// desc,
// file)
// .map(new Func1<ResponseBody, ResponseBody>() {
// @Override
// public ResponseBody call(ResponseBody responseBody) {
// return responseBody;
// }
// });
}
public Observable<GenericResponse> uploadKYCLevel1Details(int clientId,
KYCLevel1Details kycLevel1Details) {
return fineractApiManager.getDatatablesApi().addKYCLevel1Details(clientId,
kycLevel1Details);
}
public Observable<List<KYCLevel1Details>> fetchKYCLevel1Details(int clientId) {
return fineractApiManager.getDatatablesApi().fetchKYCLevel1Details(clientId);
}
public Observable<GenericResponse> updateKYCLevel1Details(int clientId,
KYCLevel1Details kycLevel1Details) {
return fineractApiManager.getDatatablesApi().updateKYCLevel1Details(clientId,
kycLevel1Details);
}
//self user apis
public Observable<UserEntity> loginSelf(String username, String password) {
@ -107,13 +161,11 @@ public class FineractRepository {
}
public Observable<ResponseBody> updateBeneficiary(long beneficiaryId,
BeneficiaryUpdatePayload payload) {
BeneficiaryUpdatePayload payload) {
return selfApiManager.getBeneficiaryApi().updateBeneficiary(beneficiaryId, payload);
}
public Observable<ResponseBody> makeThirdPartyTransfer(TransferPayload transferPayload) {
return selfApiManager.getThirdPartyTransferApi().makeTransfer(transferPayload);
}
}

View File

@ -102,7 +102,7 @@ public class Account implements Parcelable {
this.currency = in.readParcelable(Currency.class.getClassLoader());
}
public static final Parcelable.Creator<Account> CREATOR = new Parcelable.Creator<Account>() {
public static final Creator<Account> CREATOR = new Creator<Account>() {
@Override
public Account createFromParcel(Parcel source) {
return new Account(source);

View File

@ -0,0 +1,135 @@
package org.mifos.mobilewallet.core.domain.model;
import android.os.Parcel;
import android.os.Parcelable;
import com.google.gson.annotations.SerializedName;
/**
* Created by ankur on 21/May/2018
*/
public class Card implements Parcelable {
@SerializedName("cardNumber")
String cardNumber;
@SerializedName("cvv")
String cvv;
@SerializedName("expiryDate")
String expiryDate;
@SerializedName("firstName")
String firstName;
@SerializedName("lastName")
String lastName;
@SerializedName("id")
int id;
public static final Creator<Card> CREATOR = new Creator<Card>() {
@Override
public Card createFromParcel(Parcel source) {
return new Card(source);
}
@Override
public Card[] newArray(int size) {
return new Card[size];
}
};
public Card(String cardNumber, String cvv, String expiryDate, String firstName,
String lastName) {
this.cardNumber = cardNumber;
this.cvv = cvv;
this.expiryDate = expiryDate;
this.firstName = firstName;
this.lastName = lastName;
}
public String getCardNumber() {
return cardNumber;
}
public void setCardNumber(String cardNumber) {
this.cardNumber = cardNumber;
}
public String getCvv() {
return cvv;
}
public void setCvv(String cvv) {
this.cvv = cvv;
}
public String getExpiryDate() {
return expiryDate;
}
public void setExpiryDate(String expiryDate) {
this.expiryDate = expiryDate;
}
protected Card(Parcel in) {
this.cardNumber = in.readString();
this.cvv = in.readString();
this.expiryDate = in.readString();
this.firstName = in.readString();
this.lastName = in.readString();
this.id = in.readInt();
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.cardNumber);
dest.writeString(this.cvv);
dest.writeString(this.expiryDate);
dest.writeString(this.firstName);
dest.writeString(this.lastName);
}
@Override
public String toString() {
return "Card{" +
"cardNumber='" + cardNumber + '\'' +
", cvv='" + cvv + '\'' +
", expiryDate='" + expiryDate + '\'' +
", firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", id=" + id +
'}';
}
}

View File

@ -69,7 +69,7 @@ public class Client implements Parcelable {
this.clientId = in.readLong();
}
public static final Parcelable.Creator<Client> CREATOR = new Parcelable.Creator<Client>() {
public static final Creator<Client> CREATOR = new Creator<Client>() {
@Override
public Client createFromParcel(Parcel source) {
return new Client(source);

View File

@ -58,7 +58,7 @@ public class Currency implements Parcelable {
this.displayLabel = in.readString();
}
public static final Parcelable.Creator<Currency> CREATOR = new Parcelable.Creator<Currency>() {
public static final Creator<Currency> CREATOR = new Creator<Currency>() {
@Override
public Currency createFromParcel(Parcel source) {
return new Currency(source);

View File

@ -0,0 +1,147 @@
package org.mifos.mobilewallet.core.domain.model;
import android.os.Parcel;
import android.os.Parcelable;
import com.google.gson.annotations.SerializedName;
/**
* Created by ankur on 24/May/2018
*/
public class KYCLevel1Details implements Parcelable {
public static final Creator<KYCLevel1Details> CREATOR =
new Creator<KYCLevel1Details>() {
@Override
public KYCLevel1Details createFromParcel(Parcel source) {
return new KYCLevel1Details(source);
}
@Override
public KYCLevel1Details[] newArray(int size) {
return new KYCLevel1Details[size];
}
};
@SerializedName("firstName")
String firstName;
@SerializedName("lastName")
String lastName;
@SerializedName("addressLine1")
String addressLine1;
@SerializedName("addressLine2")
String addressLine2;
@SerializedName("mobileNo")
String mobileNo;
@SerializedName("dob")
String dob;
@SerializedName("currentLevel")
String currentLevel;
public KYCLevel1Details(String firstName, String lastName, String addressLine1,
String addressLine2, String mobileNo, String dob, String currentLevel) {
this.firstName = firstName;
this.lastName = lastName;
this.addressLine1 = addressLine1;
this.addressLine2 = addressLine2;
this.mobileNo = mobileNo;
this.dob = dob;
this.currentLevel = currentLevel;
}
protected KYCLevel1Details(Parcel in) {
this.firstName = in.readString();
this.lastName = in.readString();
this.addressLine1 = in.readString();
this.addressLine2 = in.readString();
this.mobileNo = in.readString();
this.dob = in.readString();
this.currentLevel = in.readString();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.firstName);
dest.writeString(this.lastName);
dest.writeString(this.addressLine1);
dest.writeString(this.addressLine2);
dest.writeString(this.mobileNo);
dest.writeString(this.dob);
dest.writeString(this.currentLevel);
}
@Override
public String toString() {
return "KYCLevel1Details{" +
"firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", addressLine1='" + addressLine1 + '\'' +
", addressLine2='" + addressLine2 + '\'' +
", mobileNo='" + mobileNo + '\'' +
", dob='" + dob + '\'' +
", currentLevel='" + currentLevel + '\'' +
'}';
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getAddressLine1() {
return addressLine1;
}
public void setAddressLine1(String addressLine1) {
this.addressLine1 = addressLine1;
}
public String getAddressLine2() {
return addressLine2;
}
public void setAddressLine2(String addressLine2) {
this.addressLine2 = addressLine2;
}
public String getMobileNo() {
return mobileNo;
}
public void setMobileNo(String mobileNo) {
this.mobileNo = mobileNo;
}
public String getDob() {
return dob;
}
public void setDob(String dob) {
this.dob = dob;
}
public String getCurrentLevel() {
return currentLevel;
}
public void setCurrentLevel(String currentLevel) {
this.currentLevel = currentLevel;
}
}

View File

@ -58,8 +58,8 @@ public class SearchResult implements Parcelable {
this.resultType = in.readString();
}
public static final Parcelable.Creator<SearchResult> CREATOR = new
Parcelable.Creator<SearchResult>() {
public static final Creator<SearchResult> CREATOR = new
Creator<SearchResult>() {
@Override
public SearchResult createFromParcel(Parcel source) {
return new SearchResult(source);

View File

@ -110,8 +110,8 @@ public class Transaction implements Parcelable {
TransactionType.values()[tmpTransactionType];
}
public static final Parcelable.Creator<Transaction> CREATOR = new
Parcelable.Creator<Transaction>() {
public static final Creator<Transaction> CREATOR = new
Creator<Transaction>() {
@Override
public Transaction createFromParcel(Parcel source) {
return new Transaction(source);

View File

@ -56,7 +56,7 @@ public class User implements Parcelable {
this.authenticationKey = in.readString();
}
public static final Parcelable.Creator<User> CREATOR = new Parcelable.Creator<User>() {
public static final Creator<User> CREATOR = new Creator<User>() {
@Override
public User createFromParcel(Parcel source) {
return new User(source);

View File

@ -0,0 +1,68 @@
package org.mifos.mobilewallet.core.domain.usecase;
import android.util.Log;
import org.mifos.mobilewallet.core.base.UseCase;
import org.mifos.mobilewallet.core.data.fineract.api.GenericResponse;
import org.mifos.mobilewallet.core.data.fineract.repository.FineractRepository;
import org.mifos.mobilewallet.core.domain.model.Card;
import javax.inject.Inject;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
/**
* Created by ankur on 21/May/2018
*/
public class AddCard extends UseCase<AddCard.RequestValues, AddCard.ResponseValue> {
private final FineractRepository mFineractRepository;
@Inject
public AddCard(FineractRepository fineractRepository) {
mFineractRepository = fineractRepository;
}
@Override
protected void executeUseCase(RequestValues requestValues) {
mFineractRepository.addSavedCards(requestValues.clientId, requestValues.card)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(new Subscriber<GenericResponse>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
getUseCaseCallback().onError(e.toString());
}
@Override
public void onNext(GenericResponse genericResponse) {
Log.d("qxz", "onNext: card added " + genericResponse.toString());
getUseCaseCallback().onSuccess(new ResponseValue());
}
});
}
public static final class RequestValues implements UseCase.RequestValues {
private final long clientId;
private final Card card;
public RequestValues(long clientId, Card card) {
this.clientId = clientId;
this.card = card;
}
}
public static final class ResponseValue implements UseCase.ResponseValue {
}
}

View File

@ -20,7 +20,7 @@ public class CreateClient extends UseCase<CreateClient.RequestValues, CreateClie
}
@Override
protected void executeUseCase(CreateClient.RequestValues requestValues) {
protected void executeUseCase(RequestValues requestValues) {
}

View File

@ -0,0 +1,67 @@
package org.mifos.mobilewallet.core.domain.usecase;
import android.util.Log;
import org.mifos.mobilewallet.core.base.UseCase;
import org.mifos.mobilewallet.core.data.fineract.api.GenericResponse;
import org.mifos.mobilewallet.core.data.fineract.repository.FineractRepository;
import javax.inject.Inject;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
/**
* Created by ankur on 22/May/2018
*/
public class DeleteCard extends UseCase<DeleteCard.RequestValues, DeleteCard.ResponseValue> {
private final FineractRepository mFineractRepository;
@Inject
public DeleteCard(FineractRepository fineractRepository) {
mFineractRepository = fineractRepository;
}
@Override
protected void executeUseCase(RequestValues requestValues) {
mFineractRepository.deleteSavedCard(requestValues.clientId, requestValues.cardId)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(new Subscriber<GenericResponse>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
getUseCaseCallback().onError(e.toString());
}
@Override
public void onNext(GenericResponse genericResponse) {
Log.d("qxz", "onNext: card deleted.");
getUseCaseCallback().onSuccess(new ResponseValue());
}
});
}
public static final class RequestValues implements UseCase.RequestValues {
private final int clientId;
private final int cardId;
public RequestValues(int clientId, int cardId) {
this.clientId = clientId;
this.cardId = cardId;
}
}
public static final class ResponseValue implements UseCase.ResponseValue {
}
}

View File

@ -0,0 +1,69 @@
package org.mifos.mobilewallet.core.domain.usecase;
import android.util.Log;
import org.mifos.mobilewallet.core.base.UseCase;
import org.mifos.mobilewallet.core.data.fineract.api.GenericResponse;
import org.mifos.mobilewallet.core.data.fineract.repository.FineractRepository;
import org.mifos.mobilewallet.core.domain.model.Card;
import javax.inject.Inject;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
/**
* Created by ankur on 22/May/2018
*/
public class EditCard extends UseCase<EditCard.RequestValues, EditCard.ResponseValue> {
private final FineractRepository mFineractRepository;
@Inject
public EditCard(FineractRepository fineractRepository) {
mFineractRepository = fineractRepository;
}
@Override
protected void executeUseCase(RequestValues requestValues) {
mFineractRepository.editSavedCard(requestValues.clientId, requestValues.card)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(new Subscriber<GenericResponse>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
getUseCaseCallback().onError(e.toString());
}
@Override
public void onNext(GenericResponse genericResponse) {
Log.d("qxz", "onNext: card updated");
getUseCaseCallback().onSuccess(new ResponseValue());
}
});
}
public static final class RequestValues implements UseCase.RequestValues {
private final int clientId;
private final Card card;
public RequestValues(int clientId, Card card) {
this.clientId = clientId;
this.card = card;
}
}
public static final class ResponseValue implements UseCase.ResponseValue {
}
}

View File

@ -33,7 +33,7 @@ public class FetchAccountTransactions extends UseCase<FetchAccountTransactions.R
@Override
protected void executeUseCase(final FetchAccountTransactions.RequestValues requestValues) {
protected void executeUseCase(final RequestValues requestValues) {
fineractRepository.getSelfAccountTransactions(requestValues.accountId)
.observeOn(AndroidSchedulers.mainThread())

View File

@ -32,7 +32,7 @@ public class FetchAccounts extends UseCase<FetchAccounts.RequestValues,
@Override
protected void executeUseCase(FetchAccounts.RequestValues requestValues) {
protected void executeUseCase(RequestValues requestValues) {
fineractRepository.getAccounts(requestValues.clientId)
.observeOn(AndroidSchedulers.mainThread())
@ -52,7 +52,7 @@ public class FetchAccounts extends UseCase<FetchAccounts.RequestValues,
public void onNext(ClientAccounts accounts) {
if (accounts != null) {
getUseCaseCallback().onSuccess(new
FetchAccounts.ResponseValue(accountMapper.transform(accounts)));
ResponseValue(accountMapper.transform(accounts)));
} else {
getUseCaseCallback().onError("No accounts found");
}

View File

@ -0,0 +1,78 @@
package org.mifos.mobilewallet.core.domain.usecase;
import org.mifos.mobilewallet.core.base.UseCase;
import org.mifos.mobilewallet.core.data.fineract.repository.FineractRepository;
import org.mifos.mobilewallet.core.domain.model.KYCLevel1Details;
import java.util.List;
import javax.inject.Inject;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
/**
* Created by ankur on 24/May/2018
*/
public class FetchKYCLevel1Details extends
UseCase<FetchKYCLevel1Details.RequestValues, FetchKYCLevel1Details.ResponseValue> {
private final FineractRepository mFineractRepository;
@Inject
public FetchKYCLevel1Details(FineractRepository fineractRepository) {
mFineractRepository = fineractRepository;
}
@Override
protected void executeUseCase(RequestValues requestValues) {
mFineractRepository.fetchKYCLevel1Details(requestValues.clientId)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(new Subscriber<List<KYCLevel1Details>>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
getUseCaseCallback().onError(e.toString());
}
@Override
public void onNext(List<KYCLevel1Details> kycLevel1Details) {
getUseCaseCallback().onSuccess(
new ResponseValue(kycLevel1Details));
}
});
}
public static final class RequestValues implements UseCase.RequestValues {
private final int clientId;
public RequestValues(int clientId) {
this.clientId = clientId;
}
}
public static final class ResponseValue implements UseCase.ResponseValue {
protected final List<KYCLevel1Details> mKYCLevel1DetailsList;
public ResponseValue(
List<KYCLevel1Details> kycLevel1Details) {
mKYCLevel1DetailsList = kycLevel1Details;
}
public List<KYCLevel1Details> getKYCLevel1DetailsList() {
return mKYCLevel1DetailsList;
}
}
}

View File

@ -0,0 +1,78 @@
package org.mifos.mobilewallet.core.domain.usecase;
import org.mifos.mobilewallet.core.base.UseCase;
import org.mifos.mobilewallet.core.data.fineract.repository.FineractRepository;
import org.mifos.mobilewallet.core.domain.model.Card;
import java.util.List;
import javax.inject.Inject;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
/**
* Created by ankur on 21/May/2018
*/
public class FetchSavedCards extends UseCase<FetchSavedCards.RequestValues,
FetchSavedCards.ResponseValue> {
private final FineractRepository mFineractRepository;
@Inject
public FetchSavedCards(FineractRepository fineractRepository) {
mFineractRepository = fineractRepository;
}
@Override
protected void executeUseCase(RequestValues requestValues) {
mFineractRepository.fetchSavedCards(requestValues.clientId)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(new Subscriber<List<Card>>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
getUseCaseCallback().onError(
"qxz Error fetching accounts: " + e.toString());
}
@Override
public void onNext(List<Card> cards) {
if (cards != null) {
getUseCaseCallback().onSuccess(new
ResponseValue(cards));
} else {
getUseCaseCallback().onError("qxz No cards found");
}
}
});
}
public static final class RequestValues implements UseCase.RequestValues {
private final long clientId;
public RequestValues(long clientId) {
this.clientId = clientId;
}
}
public static final class ResponseValue implements UseCase.ResponseValue {
private final List<Card> cardList;
public ResponseValue(List<Card> cards) {
this.cardList = cards;
}
public List<Card> getCardList() {
return cardList;
}
}
}

View File

@ -34,7 +34,7 @@ public class FetchWallet extends UseCase<FetchWallet.RequestValues,
@Override
protected void executeUseCase(FetchWallet.RequestValues requestValues) {
protected void executeUseCase(RequestValues requestValues) {
fineractRepository.getSelfAccounts(requestValues.clientId)
.observeOn(AndroidSchedulers.mainThread())

View File

@ -26,7 +26,7 @@ public class RegisterUser extends UseCase<RegisterUser.RequestValues,
@Override
protected void executeUseCase(RegisterUser.RequestValues requestValues) {
protected void executeUseCase(RequestValues requestValues) {
apiRepository.registerUser(requestValues.registerPayload)
.observeOn(AndroidSchedulers.mainThread())

View File

@ -41,7 +41,7 @@ public class TransferFunds extends UseCase<TransferFunds.RequestValues,
@Override
protected void executeUseCase(final TransferFunds.RequestValues requestValues) {
protected void executeUseCase(final RequestValues requestValues) {
/*
* - get fromClient head office name

View File

@ -0,0 +1,68 @@
package org.mifos.mobilewallet.core.domain.usecase;
import org.mifos.mobilewallet.core.base.UseCase;
import org.mifos.mobilewallet.core.data.fineract.api.GenericResponse;
import org.mifos.mobilewallet.core.data.fineract.repository.FineractRepository;
import org.mifos.mobilewallet.core.domain.model.KYCLevel1Details;
import javax.inject.Inject;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
/**
* Created by ankur on 25/May/2018
*/
public class UpdateKYCLevel1Details extends
UseCase<UpdateKYCLevel1Details.RequestValues, UpdateKYCLevel1Details.ResponseValue> {
private final FineractRepository mFineractRepository;
@Inject
public UpdateKYCLevel1Details(FineractRepository fineractRepository) {
this.mFineractRepository = fineractRepository;
}
@Override
protected void executeUseCase(RequestValues requestValues) {
mFineractRepository.updateKYCLevel1Details(requestValues.clientId,
requestValues.kycLevel1Details)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(new Subscriber<GenericResponse>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
getUseCaseCallback().onError(e.toString());
}
@Override
public void onNext(GenericResponse genericResponse) {
getUseCaseCallback().onSuccess(new ResponseValue());
}
});
}
public static final class RequestValues implements UseCase.RequestValues {
private final int clientId;
private final KYCLevel1Details kycLevel1Details;
public RequestValues(int clientId,
KYCLevel1Details kycLevel1Details) {
this.clientId = clientId;
this.kycLevel1Details = kycLevel1Details;
}
}
public static final class ResponseValue implements UseCase.ResponseValue {
}
}

View File

@ -26,7 +26,7 @@ public class UpdateVpa extends UseCase<UpdateVpa.RequestValues,
@Override
protected void executeUseCase(UpdateVpa.RequestValues requestValues) {
protected void executeUseCase(RequestValues requestValues) {
UpdateVpaPayload vpaPayload = new UpdateVpaPayload();
vpaPayload.setExternalId(requestValues.vpa);

View File

@ -0,0 +1,74 @@
package org.mifos.mobilewallet.core.domain.usecase;
import org.mifos.mobilewallet.core.base.UseCase;
import org.mifos.mobilewallet.core.data.fineract.api.GenericResponse;
import org.mifos.mobilewallet.core.data.fineract.repository.FineractRepository;
import javax.inject.Inject;
import okhttp3.MultipartBody;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
/**
* Created by ankur on 16/May/2018
*/
public class UploadKYCDocs extends UseCase<UploadKYCDocs.RequestValues,
UploadKYCDocs.ResponseValue> {
private final FineractRepository apiRepository;
@Inject
public UploadKYCDocs(FineractRepository apiRepository) {
this.apiRepository = apiRepository;
}
@Override
protected void executeUseCase(RequestValues requestValues) {
apiRepository.uploadKYCDocs(requestValues.entitytype, requestValues.clientId,
requestValues.docname, requestValues.identityType, requestValues.file)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(new Subscriber<GenericResponse>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
getUseCaseCallback().onError(e.toString());
}
@Override
public void onNext(GenericResponse genericResponse) {
getUseCaseCallback().onSuccess(new ResponseValue());
}
});
}
public static final class RequestValues implements UseCase.RequestValues {
public final String entitytype;
private final long clientId;
private final String docname;
private final String identityType;
private final MultipartBody.Part file;
public RequestValues(String entitytype, long clientId, String docname,
String identityType, MultipartBody.Part file) {
this.entitytype = entitytype;
this.clientId = clientId;
this.docname = docname;
this.identityType = identityType;
this.file = file;
}
}
public static final class ResponseValue implements UseCase.ResponseValue {
public ResponseValue() {
}
}
}

View File

@ -0,0 +1,68 @@
package org.mifos.mobilewallet.core.domain.usecase;
import org.mifos.mobilewallet.core.base.UseCase;
import org.mifos.mobilewallet.core.data.fineract.api.GenericResponse;
import org.mifos.mobilewallet.core.data.fineract.repository.FineractRepository;
import org.mifos.mobilewallet.core.domain.model.KYCLevel1Details;
import javax.inject.Inject;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
/**
* Created by ankur on 24/May/2018
*/
public class UploadKYCLevel1Details extends
UseCase<UploadKYCLevel1Details.RequestValues, UploadKYCLevel1Details.ResponseValue> {
FineractRepository mFineractRepository;
@Inject
public UploadKYCLevel1Details(FineractRepository fineractRepository) {
mFineractRepository = fineractRepository;
}
@Override
protected void executeUseCase(RequestValues requestValues) {
mFineractRepository.uploadKYCLevel1Details(requestValues.clientId,
requestValues.mKYCLevel1Details)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(new Subscriber<GenericResponse>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
getUseCaseCallback().onError(e.toString());
}
@Override
public void onNext(GenericResponse genericResponse) {
getUseCaseCallback().onSuccess(new ResponseValue());
}
});
}
public static final class RequestValues implements UseCase.RequestValues {
private final int clientId;
private final KYCLevel1Details mKYCLevel1Details;
public RequestValues(int clientId,
KYCLevel1Details kycLevel1Details) {
this.clientId = clientId;
mKYCLevel1Details = kycLevel1Details;
}
}
public static final class ResponseValue implements UseCase.ResponseValue {
}
}

View File

@ -26,7 +26,7 @@ public class VerifyUser extends UseCase<VerifyUser.RequestValues,
@Override
protected void executeUseCase(VerifyUser.RequestValues requestValues) {
protected void executeUseCase(RequestValues requestValues) {
apiRepository.verifyUser(requestValues.userVerify)
.observeOn(AndroidSchedulers.mainThread())

View File

@ -13,6 +13,5 @@ public class Constants {
public static final int WALLET_ACCOUNT_SAVINGS_PRODUCT_ID = 165;
public static final String ENTITY_TYPE_CLIENTS = "clients";
}

View File

@ -15,3 +15,5 @@ org.gradle.jvmargs=-Xmx1536m
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
RblClientIdProp=a
RblClientSecretProp=b

View File

@ -1,7 +1,6 @@
#Wed Sep 13 23:35:20 IST 2017
#Sun May 13 19:12:22 IST 2018
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip

View File

@ -3,7 +3,6 @@ apply from: '../config/quality/quality.gradle'
android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
defaultConfig {
@ -33,40 +32,43 @@ android {
}
compileOptions.incremental = false
buildToolsVersion '27.0.3'
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
implementation fileTree(dir: 'libs', include: ['*.jar'])
androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile "com.android.support:appcompat-v7:$rootProject.supportLibraryVersion"
compile "com.android.support:design:$rootProject.supportLibraryVersion"
compile "com.android.support:cardview-v7:$rootProject.supportLibraryVersion"
compile "com.android.support:recyclerview-v7:$rootProject.supportLibraryVersion"
implementation "com.android.support:appcompat-v7:$rootProject.supportLibraryVersion"
implementation "com.android.support:design:$rootProject.supportLibraryVersion"
implementation "com.android.support:cardview-v7:$rootProject.supportLibraryVersion"
implementation "com.android.support:recyclerview-v7:$rootProject.supportLibraryVersion"
compile "com.jakewharton:butterknife:$rootProject.butterKnifeVersion"
implementation "com.jakewharton:butterknife:$rootProject.butterKnifeVersion"
annotationProcessor "com.jakewharton:butterknife-compiler:$rootProject.butterKnifeVersion"
compile 'com.google.dagger:dagger:2.11'
implementation 'com.google.dagger:dagger:2.11'
annotationProcessor 'com.google.dagger:dagger-compiler:2.11'
compile ("com.squareup.retrofit2:retrofit:$rootProject.retrofitVersion") {
implementation ("com.squareup.retrofit2:retrofit:$rootProject.retrofitVersion") {
// exclude Retrofits OkHttp peer-dependency module and define your own module import
exclude module: 'okhttp'
}
compile "com.squareup.retrofit2:converter-gson:$rootProject.retrofitVersion"
compile "com.squareup.retrofit2:adapter-rxjava:$rootProject.retrofitVersion"
compile "com.squareup.okhttp3:okhttp:$rootProject.okHttp3Version"
compile "com.squareup.okhttp3:logging-interceptor:$rootProject.okHttp3Version"
implementation "com.squareup.retrofit2:converter-gson:$rootProject.retrofitVersion"
implementation "com.squareup.retrofit2:adapter-rxjava:$rootProject.retrofitVersion"
implementation "com.squareup.okhttp3:okhttp:$rootProject.okHttp3Version"
implementation "com.squareup.okhttp3:logging-interceptor:$rootProject.okHttp3Version"
compile 'io.reactivex:rxandroid:1.1.0'
compile 'io.reactivex:rxjava:1.1.4'
implementation 'io.reactivex:rxandroid:1.1.0'
implementation 'io.reactivex:rxjava:1.1.4'
compile 'me.dm7.barcodescanner:zxing:1.8.4'
implementation 'me.dm7.barcodescanner:zxing:1.8.4'
testCompile 'junit:junit:4.12'
implementation 'com.mifos.mobile:mifos-passcode:0.3.0'
testImplementation 'junit:junit:4.12'
implementation project(':core')
}

View File

@ -21,6 +21,6 @@ public class ExampleInstrumentedTest {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("or.mifos.mobilewallet.mifoswallet", appContext.getPackageName());
assertEquals("org.mifos.mobilewallet.mifospay", appContext.getPackageName());
}
}

View File

@ -1,38 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.mifos.mobilewallet.mifospay">
package="org.mifos.mobilewallet.mifospay">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<application
android:name=".MifosPayApp" android:allowBackup="true" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:theme="@style/AppTheme">
<activity android:name="org.mifos.mobilewallet.mifospay.auth.ui.LoginActivity"
android:theme="@style/AppTheme.NoActionBar">
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".home.ui.HomeActivity"
android:theme="@style/AppTheme.NoActionBar"/>
android:theme="@style/AppTheme.NoActionBar"/>
<activity android:name=".wallet.ui.WalletDetailActivity"
android:theme="@style/AppTheme.NoActionBar"/>
android:theme="@style/AppTheme.NoActionBar"/>
<activity android:name=".common.ui.SearchActivity"
android:theme="@style/AppTheme.NoActionBar"/>
android:theme="@style/AppTheme.NoActionBar"/>
<activity android:name=".qr.ui.ShowQrActivity"
android:theme="@style/AppTheme.NoActionBar"/>
android:theme="@style/AppTheme.NoActionBar"/>
<activity android:name=".qr.ui.ReadQrActivity"
android:theme="@style/AppTheme.NoActionBar"/>
android:theme="@style/AppTheme.NoActionBar"/>
<activity android:name=".passcode.ui.PassCodeActivity"
android:theme="@style/AppTheme.NoActionBar"/>
</application>
</manifest>

View File

@ -4,6 +4,8 @@ import android.app.Application;
import android.content.Context;
import android.support.v7.app.AppCompatDelegate;
import com.mifos.mobile.passcode.utils.ForegroundChecker;
import org.mifos.mobilewallet.mifospay.injection.component.ApplicationComponent;
import org.mifos.mobilewallet.mifospay.injection.component.DaggerApplicationComponent;
import org.mifos.mobilewallet.mifospay.injection.module.ApplicationModule;
@ -39,6 +41,9 @@ public class MifosPayApp extends Application {
MifosPayApp.instance = this;
}
ButterKnife.setDebug(true);
//Initialize ForegroundChecker
ForegroundChecker.init(this);
}
public ApplicationComponent component() {

View File

@ -6,11 +6,14 @@ import android.support.annotation.Nullable;
import android.widget.EditText;
import android.widget.Toast;
import com.mifos.mobile.passcode.utils.PassCodeConstants;
import com.mifos.mobile.passcode.utils.PasscodePreferencesHelper;
import org.mifos.mobilewallet.mifospay.R;
import org.mifos.mobilewallet.mifospay.auth.AuthContract;
import org.mifos.mobilewallet.mifospay.auth.presenter.LoginPresenter;
import org.mifos.mobilewallet.mifospay.base.BaseActivity;
import org.mifos.mobilewallet.mifospay.home.ui.HomeActivity;
import org.mifos.mobilewallet.mifospay.passcode.ui.PassCodeActivity;
import org.mifos.mobilewallet.mifospay.utils.Utils;
import javax.inject.Inject;
@ -45,6 +48,11 @@ public class LoginActivity extends BaseActivity implements AuthContract.LoginVie
ButterKnife.bind(this);
mPresenter.attachView(this);
PasscodePreferencesHelper pref = new PasscodePreferencesHelper(getApplicationContext());
if (!pref.getPassCode().isEmpty()) {
startPassCodeActivity();
}
}
@Override
@ -64,11 +72,7 @@ public class LoginActivity extends BaseActivity implements AuthContract.LoginVie
public void loginSuccess() {
hideProgressDialog();
Utils.hideSoftKeyboard(this);
Intent intent = new Intent(LoginActivity.this, HomeActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
finish();
startPassCodeActivity();
}
@Override
@ -77,4 +81,14 @@ public class LoginActivity extends BaseActivity implements AuthContract.LoginVie
hideProgressDialog();
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
/**
* Starts {@link PassCodeActivity} with {@code Constans.INTIAL_LOGIN} as true
*/
private void startPassCodeActivity() {
Intent intent = new Intent(LoginActivity.this, PassCodeActivity.class);
intent.putExtra(PassCodeConstants.PASSCODE_INITIAL_LOGIN, true);
startActivity(intent);
finish();
}
}

View File

@ -5,21 +5,23 @@ import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import com.mifos.mobile.passcode.BasePassCodeActivity;
import org.mifos.mobilewallet.mifospay.MifosPayApp;
import org.mifos.mobilewallet.mifospay.R;
import org.mifos.mobilewallet.mifospay.injection.component.ActivityComponent;
import org.mifos.mobilewallet.mifospay.injection.component.DaggerActivityComponent;
import org.mifos.mobilewallet.mifospay.injection.module.ActivityModule;
import org.mifos.mobilewallet.mifospay.passcode.ui.PassCodeActivity;
/**
* Created by naman on 16/6/17.
*/
public class BaseActivity extends AppCompatActivity implements BaseActivityCallback {
public class BaseActivity extends BasePassCodeActivity implements BaseActivityCallback {
private ActivityComponent activityComponent;
@ -138,4 +140,8 @@ public class BaseActivity extends AppCompatActivity implements BaseActivityCallb
}
}
@Override
public Class getPassCodeClass() {
return PassCodeActivity.class;
}
}

View File

@ -37,15 +37,20 @@ public class BaseFragment extends Fragment {
}
}
protected void showProgressDialog(String message) {
callback.showProgressDialog(message);
}
protected void hideProgressDialog() {
callback.hideProgressDialog();
}
protected void setSwipeEnabled(boolean enabled) {
if (callback != null) {
callback.setSwipeRefreshEnabled(enabled);
}
}
protected void replaceFragment(Fragment fragment, int containerId) {
}
@Override
public void onAttach(Context context) {
@ -65,6 +70,23 @@ public class BaseFragment extends Fragment {
callback = null;
}
public void replaceFragmentUsingFragmentManager(Fragment fragment, boolean addToBackStack,
int containerId) {
String backStateName = fragment.getClass().getName();
boolean fragmentPopped = getFragmentManager().popBackStackImmediate(backStateName,
0);
if (!fragmentPopped && getFragmentManager().findFragmentByTag(backStateName) ==
null) {
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(containerId, fragment, backStateName);
if (addToBackStack) {
transaction.addToBackStack(backStateName);
}
transaction.commit();
}
}
public void replaceFragment(Fragment fragment, boolean addToBackStack, int containerId) {
String backStateName = fragment.getClass().getName();
boolean fragmentPopped = getChildFragmentManager().popBackStackImmediate(backStateName,

View File

@ -9,7 +9,7 @@ import org.mifos.mobilewallet.mifospay.base.BaseView;
public interface TransferContract {
interface TransferView extends BaseView<TransferContract.TransferPresenter> {
interface TransferView extends BaseView<TransferPresenter> {
void showToClientDetails(long clientId, String name, String externalId);

View File

@ -29,14 +29,14 @@ public class SearchAdapter extends RecyclerView.Adapter<SearchAdapter.ViewHolder
}
@Override
public SearchAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(
R.layout.item_search, parent, false);
return new SearchAdapter.ViewHolder(v);
return new ViewHolder(v);
}
@Override
public void onBindViewHolder(SearchAdapter.ViewHolder holder, int position) {
public void onBindViewHolder(ViewHolder holder, int position) {
holder.tvSearchResult.setText(results.get(position).getResultName());
}

View File

@ -1,7 +1,6 @@
package org.mifos.mobilewallet.mifospay.home.presenter;
import org.mifos.mobilewallet.core.base.UseCaseHandler;
import org.mifos.mobilewallet.core.domain.usecase.FetchWallet;
import org.mifos.mobilewallet.mifospay.base.BaseView;
import org.mifos.mobilewallet.mifospay.data.local.LocalRepository;
import org.mifos.mobilewallet.mifospay.home.HomeContract;

View File

@ -11,17 +11,19 @@ import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import org.mifos.mobilewallet.core.domain.model.Client;
import org.mifos.mobilewallet.mifospay.R;
import org.mifos.mobilewallet.mifospay.base.BaseActivity;
import org.mifos.mobilewallet.mifospay.home.HomeContract;
import org.mifos.mobilewallet.mifospay.home.presenter.HomePresenter;
import org.mifos.mobilewallet.mifospay.kyc.ui.KYCDescriptionFragment;
import org.mifos.mobilewallet.mifospay.savedcards.ui.CardsFragment;
import org.mifos.mobilewallet.mifospay.utils.TextDrawable;
import javax.inject.Inject;
import butterknife.BindView;
import butterknife.ButterKnife;
import org.mifos.mobilewallet.core.domain.model.Client;
/**
* Created by naman on 17/6/17.
@ -60,6 +62,7 @@ public class HomeActivity extends BaseActivity implements HomeContract.HomeView
replaceFragment(HomeFragment.newInstance(), false, R.id.container);
setupDrawerContent(navigationView);
swipeLayout.setEnabled(false);
}
@ -109,6 +112,13 @@ public class HomeActivity extends BaseActivity implements HomeContract.HomeView
case R.id.item_home:
replaceFragment(HomeFragment.newInstance(), false, R.id.container);
break;
case R.id.item_kyc:
replaceFragment(KYCDescriptionFragment.newInstance(), true, R.id.container);
break;
case R.id.item_saved_cards:
replaceFragment(CardsFragment.newInstance(), true, R.id.container);
break;
}
drawerLayout.closeDrawer(GravityCompat.START);

View File

@ -71,7 +71,7 @@ public class TransferFragment extends BaseFragment implements HomeContract.Trans
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
@Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_transfer, container,
false);
ButterKnife.bind(this, rootView);
@ -89,8 +89,8 @@ public class TransferFragment extends BaseFragment implements HomeContract.Trans
public void transferClicked() {
String externalId = etVpa.getText().toString();
String eamount = etAmount.getText().toString();
if(eamount.equals("") || externalId.equals("")) {
Toast.makeText(getActivity(),"Please enter all the fields",Toast.LENGTH_SHORT).show();
if (eamount.equals("") || externalId.equals("")) {
Toast.makeText(getActivity(), "Please enter all the fields", Toast.LENGTH_SHORT).show();
} else {
double amount = Double.parseDouble(eamount);
MakeTransferFragment fragment = MakeTransferFragment.newInstance(externalId, amount);
@ -126,16 +126,15 @@ public class TransferFragment extends BaseFragment implements HomeContract.Trans
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == SCAN_QR_REQUEST_CODE) {
if (resultCode == Activity.RESULT_OK) {
String qrData = data.getStringExtra(Constants.QR_DATA);
etVpa.setText(qrData);
String externalId = etVpa.getText().toString();
double amount = Double.parseDouble(etAmount.getText().toString());
MakeTransferFragment fragment = MakeTransferFragment.newInstance(externalId, amount);
fragment.show(getChildFragmentManager(), "Make Transfer Fragment");
if (requestCode == SCAN_QR_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
String qrData = data.getStringExtra(Constants.QR_DATA);
etVpa.setText(qrData);
String externalId = etVpa.getText().toString();
double amount = Double.parseDouble(etAmount.getText().toString());
MakeTransferFragment fragment = MakeTransferFragment.newInstance(externalId,
amount);
fragment.show(getChildFragmentManager(), "Make Transfer Fragment");
}
}
}
}
}

View File

@ -8,14 +8,14 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import org.mifos.mobilewallet.core.domain.model.Account;
import org.mifos.mobilewallet.mifospay.R;
import org.mifos.mobilewallet.mifospay.base.BaseActivity;
import org.mifos.mobilewallet.mifospay.base.BaseFragment;
import org.mifos.mobilewallet.mifospay.data.local.PreferencesHelper;
import org.mifos.mobilewallet.mifospay.home.HomeContract;
import org.mifos.mobilewallet.mifospay.home.presenter.WalletPresenter;
import org.mifos.mobilewallet.mifospay.qr.ui.ShowQrActivity;
import org.mifos.mobilewallet.mifospay.utils.Constants;
import org.mifos.mobilewallet.mifospay.wallet.ui.WalletDetailActivity;
import javax.inject.Inject;
@ -23,9 +23,6 @@ import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import org.mifos.mobilewallet.core.domain.model.Account;
import org.mifos.mobilewallet.mifospay.wallet.ui.WalletDetailActivity;
/**
* Created by naman on 17/8/17.
*/
@ -64,7 +61,7 @@ public class WalletFragment extends BaseFragment implements HomeContract.WalletV
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
@Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_wallet, container, false);
ButterKnife.bind(this, rootView);

View File

@ -11,15 +11,22 @@ import org.mifos.mobilewallet.mifospay.home.ui.TransferFragment;
import org.mifos.mobilewallet.mifospay.home.ui.WalletFragment;
import org.mifos.mobilewallet.mifospay.injection.PerActivity;
import org.mifos.mobilewallet.mifospay.injection.module.ActivityModule;
import org.mifos.mobilewallet.mifospay.kyc.ui.KYCDescriptionFragment;
import org.mifos.mobilewallet.mifospay.kyc.ui.KYCLevel1Fragment;
import org.mifos.mobilewallet.mifospay.kyc.ui.KYCLevel2Fragment;
import org.mifos.mobilewallet.mifospay.kyc.ui.KYCLevel3Fragment;
import org.mifos.mobilewallet.mifospay.passcode.ui.PassCodeActivity;
import org.mifos.mobilewallet.mifospay.qr.ui.ReadQrActivity;
import org.mifos.mobilewallet.mifospay.qr.ui.ShowQrActivity;
import org.mifos.mobilewallet.mifospay.savedcards.ui.CardsFragment;
import org.mifos.mobilewallet.mifospay.wallet.ui.WalletDetailActivity;
import dagger.Component;
@PerActivity
@Component(dependencies = {ApplicationComponent.class},
modules = {ActivityModule.class})
modules = {ActivityModule.class})
public interface ActivityComponent {
@ -45,4 +52,15 @@ public interface ActivityComponent {
void inject(MakeTransferFragment transferFragment);
void inject(PassCodeActivity passCodeActivity);
void inject(KYCDescriptionFragment kycDescriptionFragment);
void inject(KYCLevel1Fragment kycLevel1Fragment);
void inject(KYCLevel2Fragment kycLevel2Fragment);
void inject(KYCLevel3Fragment kycLevel3Fragment);
void inject(CardsFragment cardsFragment);
}

View File

@ -0,0 +1,76 @@
package org.mifos.mobilewallet.mifospay.kyc;
import android.content.Context;
import android.content.Intent;
import org.mifos.mobilewallet.core.domain.model.KYCLevel1Details;
import org.mifos.mobilewallet.mifospay.base.BasePresenter;
import org.mifos.mobilewallet.mifospay.base.BaseView;
/**
* Created by ankur on 16/May/2018
*/
public interface KYCContract {
interface KYCDescriptionView extends BaseView<KYCDescriptionPresenter> {
void onFetchLevelSuccess(KYCLevel1Details kycLevel1Details);
void showToast(String s);
void gotoHome();
void showProgressDialog(String s);
void hideProgressDialog();
}
interface KYCDescriptionPresenter extends BasePresenter {
void fetchCurrentLevel();
}
interface KYCLevel1View extends BaseView<KYCLevel1Presenter> {
void showToast(String message);
void showProgressDialog(String message);
void hideProgressDialog();
void goBack();
}
interface KYCLevel1Presenter extends BasePresenter {
void submitData(String fname, String lname, String address1, String address2,
String phonecode, String phoneno, String dob);
}
interface KYCLevel2View extends BaseView<KYCLevel2Presenter> {
void startDocChooseActivity(Intent intent, int READ_REQUEST_CODE);
void setFilename(String absolutePath);
Context getContext();
}
interface KYCLevel2Presenter extends BasePresenter {
void browseDocs();
void updateFile(int requestCode, int resultCode, Intent data);
void uploadKYCDocs(String s);
}
interface KYCLevel3View extends BaseView<KYCLevel3Presenter> {
}
interface KYCLevel3Presenter extends BasePresenter {
}
}

View File

@ -0,0 +1,71 @@
package org.mifos.mobilewallet.mifospay.kyc.presenter;
import android.util.Log;
import org.mifos.mobilewallet.core.base.UseCase;
import org.mifos.mobilewallet.core.base.UseCaseHandler;
import org.mifos.mobilewallet.core.domain.usecase.FetchKYCLevel1Details;
import org.mifos.mobilewallet.mifospay.base.BaseView;
import org.mifos.mobilewallet.mifospay.data.local.LocalRepository;
import org.mifos.mobilewallet.mifospay.kyc.KYCContract;
import javax.inject.Inject;
/**
* Created by ankur on 24/May/2018
*/
public class KYCDescriptionPresenter implements KYCContract.KYCDescriptionPresenter {
private final UseCaseHandler mUseCaseHandler;
private final LocalRepository mLocalRepository;
@Inject
FetchKYCLevel1Details fetchKYCLevel1DetailsUseCase;
private KYCContract.KYCDescriptionView mKYCDescriptionView;
@Inject
public KYCDescriptionPresenter(UseCaseHandler useCaseHandler,
LocalRepository localRepository) {
mUseCaseHandler = useCaseHandler;
mLocalRepository = localRepository;
}
@Override
public void attachView(BaseView baseView) {
mKYCDescriptionView = (KYCContract.KYCDescriptionView) baseView;
mKYCDescriptionView.setPresenter(this);
}
@Override
public void fetchCurrentLevel() {
mKYCDescriptionView.showProgressDialog("Please wait..");
fetchKYCLevel1DetailsUseCase.setRequestValues(new FetchKYCLevel1Details.RequestValues(
(int) mLocalRepository.getClientDetails().getClientId()));
FetchKYCLevel1Details.RequestValues requestValues =
fetchKYCLevel1DetailsUseCase.getRequestValues();
mUseCaseHandler.execute(fetchKYCLevel1DetailsUseCase, requestValues,
new UseCase.UseCaseCallback<FetchKYCLevel1Details.ResponseValue>() {
@Override
public void onSuccess(FetchKYCLevel1Details.ResponseValue response) {
Log.d("qxz", "onSuccess: " + response.getKYCLevel1DetailsList());
mKYCDescriptionView.hideProgressDialog();
if (response.getKYCLevel1DetailsList().size() == 1) {
mKYCDescriptionView.onFetchLevelSuccess(
response.getKYCLevel1DetailsList().get(0));
}
}
@Override
public void onError(String message) {
Log.d("qxz", "onError: " + message);
mKYCDescriptionView.showToast("Please try again later.");
mKYCDescriptionView.hideProgressDialog();
mKYCDescriptionView.gotoHome();
}
});
}
}

View File

@ -0,0 +1,79 @@
package org.mifos.mobilewallet.mifospay.kyc.presenter;
import android.telephony.PhoneNumberUtils;
import org.mifos.mobilewallet.core.base.UseCase;
import org.mifos.mobilewallet.core.base.UseCaseHandler;
import org.mifos.mobilewallet.core.domain.model.KYCLevel1Details;
import org.mifos.mobilewallet.core.domain.usecase.UploadKYCLevel1Details;
import org.mifos.mobilewallet.mifospay.base.BaseView;
import org.mifos.mobilewallet.mifospay.data.local.LocalRepository;
import org.mifos.mobilewallet.mifospay.kyc.KYCContract;
import javax.inject.Inject;
/**
* Created by ankur on 17/May/2018
*/
public class KYCLevel1Presenter implements KYCContract.KYCLevel1Presenter {
private KYCContract.KYCLevel1View mKYCLevel1View;
private final UseCaseHandler mUseCaseHandler;
private final LocalRepository mLocalRepository;
@Inject
UploadKYCLevel1Details uploadKYCLevel1DetailsUseCase;
@Inject
public KYCLevel1Presenter(UseCaseHandler useCaseHandler, LocalRepository localRepository) {
mUseCaseHandler = useCaseHandler;
mLocalRepository = localRepository;
}
@Override
public void attachView(BaseView baseView) {
mKYCLevel1View = (KYCContract.KYCLevel1View) baseView;
mKYCLevel1View.setPresenter(this);
}
@Override
public void submitData(String fname, String lname, String address1, String address2,
String phonecode, String phoneno, String dob) {
mKYCLevel1View.showProgressDialog("Please wait..");
if (PhoneNumberUtils.isGlobalPhoneNumber(phonecode + phoneno) || true) {
KYCLevel1Details kycLevel1Details = new KYCLevel1Details(fname, lname, address1,
address2, phonecode + phoneno, dob, "1");
uploadKYCLevel1DetailsUseCase.setRequestValues(new UploadKYCLevel1Details.RequestValues(
(int) mLocalRepository.getClientDetails().getClientId(), kycLevel1Details));
final UploadKYCLevel1Details.RequestValues requestValues =
uploadKYCLevel1DetailsUseCase.getRequestValues();
mUseCaseHandler.execute(uploadKYCLevel1DetailsUseCase, requestValues,
new UseCase.UseCaseCallback<UploadKYCLevel1Details.ResponseValue>() {
@Override
public void onSuccess(UploadKYCLevel1Details.ResponseValue response) {
mKYCLevel1View.hideProgressDialog();
mKYCLevel1View.showToast("KYC Level 1 details added successfully.");
mKYCLevel1View.goBack();
}
@Override
public void onError(String message) {
mKYCLevel1View.hideProgressDialog();
mKYCLevel1View.showToast("Error adding details.");
}
}
);
}
}
}

View File

@ -0,0 +1,143 @@
package org.mifos.mobilewallet.mifospay.kyc.presenter;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.util.Log;
import org.mifos.mobilewallet.core.base.UseCase;
import org.mifos.mobilewallet.core.base.UseCaseHandler;
import org.mifos.mobilewallet.core.domain.usecase.UploadKYCDocs;
import org.mifos.mobilewallet.core.utils.Constants;
import org.mifos.mobilewallet.mifospay.base.BaseView;
import org.mifos.mobilewallet.mifospay.data.local.PreferencesHelper;
import org.mifos.mobilewallet.mifospay.kyc.KYCContract;
import org.mifos.mobilewallet.mifospay.utils.FilePath;
import java.io.File;
import javax.inject.Inject;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
/**
* Created by ankur on 17/May/2018
*/
public class KYCLevel2Presenter implements KYCContract.KYCLevel2Presenter {
private static final int READ_REQUEST_CODE = 42;
private File file;
private KYCContract.KYCLevel2View mKYCLevel2View;
private final UseCaseHandler mUseCaseHandler;
private final PreferencesHelper preferencesHelper;
@Inject
UploadKYCDocs uploadKYCDocsUseCase;
@Inject
public KYCLevel2Presenter(UseCaseHandler useCaseHandler, PreferencesHelper preferencesHelper) {
mUseCaseHandler = useCaseHandler;
this.preferencesHelper = preferencesHelper;
}
@Override
public void attachView(BaseView baseView) {
mKYCLevel2View = (KYCContract.KYCLevel2View) baseView;
mKYCLevel2View.setPresenter(this);
}
@Override
public void browseDocs() {
String[] mimeTypes = {"application/pdf", "image/*"};
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
intent.setType(mimeTypes.length == 1 ? mimeTypes[0] : "*/*");
if (mimeTypes.length > 0) {
intent.putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes);
}
} else {
String mimeTypesStr = "";
for (String mimeType : mimeTypes) {
mimeTypesStr += mimeType + "|";
}
intent.setType(mimeTypesStr.substring(0, mimeTypesStr.length() - 1));
}
mKYCLevel2View.startDocChooseActivity(intent, READ_REQUEST_CODE);
}
@Override
public void updateFile(int requestCode, int resultCode, Intent data) {
if (requestCode == READ_REQUEST_CODE && resultCode == Activity.RESULT_OK && data != null) {
Uri uri = data.getData();
file = new File(FilePath.getPath(mKYCLevel2View.getContext(), uri));
mKYCLevel2View.setFilename(file.getPath());
}
}
@Override
public void uploadKYCDocs(String identityType) {
if (file != null) {
Log.d("qxz", "uploadKYCDocs: " + file.getPath());
uploadKYCDocsUseCase.setRequestValues(
new UploadKYCDocs.RequestValues(Constants.ENTITY_TYPE_CLIENTS,
preferencesHelper.getClientId(), file.getName(), identityType,
getRequestFileBody(file)));
final UploadKYCDocs.RequestValues requestValues =
uploadKYCDocsUseCase.getRequestValues();
mUseCaseHandler.execute(uploadKYCDocsUseCase, requestValues,
new UseCase.UseCaseCallback<UploadKYCDocs.ResponseValue>() {
@Override
public void onSuccess(UploadKYCDocs.ResponseValue response) {
Log.d("qxz ", "onSuccess: ");
}
@Override
public void onError(String message) {
Log.d("qxz ", "onError: " + message);
}
});
} else {
// choose a file first
}
}
private MultipartBody.Part getRequestFileBody(File file) {
// create RequestBody instance from file
RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), file);
// MultipartBody.Part is used to send also the actual file name
return MultipartBody.Part.createFormData("file", file.getName(), requestFile);
}
//
// public String getRealPathFromURI(Uri contentUri) {
// String[] proj = {MediaStore.Images.Media.DATA};
//
// //This method was deprecated in API level 11
// //Cursor cursor = managedQuery(contentUri, proj, null, null, null);
//
// CursorLoader cursorLoader = new CursorLoader(
// mKYCLevel2View.getContext(),
// contentUri, proj, null, null, null);
// Cursor cursor = cursorLoader.loadInBackground();
//
// int column_index =
// cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
// cursor.moveToFirst();
// return cursor.getString(column_index);
// }
}

View File

@ -0,0 +1,32 @@
package org.mifos.mobilewallet.mifospay.kyc.presenter;
import org.mifos.mobilewallet.core.base.UseCaseHandler;
import org.mifos.mobilewallet.mifospay.base.BaseView;
import org.mifos.mobilewallet.mifospay.data.local.LocalRepository;
import org.mifos.mobilewallet.mifospay.kyc.KYCContract;
import javax.inject.Inject;
/**
* Created by ankur on 17/May/2018
*/
public class KYCLevel3Presenter implements KYCContract.KYCLevel3Presenter {
private KYCContract.KYCLevel3View mKYCLevel1View;
private final UseCaseHandler mUseCaseHandler;
private final LocalRepository mLocalRepository;
@Inject
public KYCLevel3Presenter(UseCaseHandler useCaseHandler, LocalRepository localRepository) {
mUseCaseHandler = useCaseHandler;
mLocalRepository = localRepository;
}
@Override
public void attachView(BaseView baseView) {
mKYCLevel1View = (KYCContract.KYCLevel3View) baseView;
mKYCLevel1View.setPresenter(this);
}
}

Some files were not shown because too many files have changed in this diff Show More